mirror of
https://github.com/hydralauncher/hydra.git
synced 2025-02-03 00:33:49 +03:00
Merge branch 'feature/user-profile' of github.com:hydralauncher/hydra into feature/user-profile
This commit is contained in:
commit
93c6ef8510
@ -53,6 +53,7 @@
|
||||
"electron-log": "^5.1.4",
|
||||
"electron-updater": "^6.1.8",
|
||||
"fetch-cookie": "^3.0.1",
|
||||
"file-type": "^19.0.0",
|
||||
"flexsearch": "^0.7.43",
|
||||
"i18next": "^23.11.2",
|
||||
"i18next-browser-languagedetector": "^7.2.1",
|
||||
@ -61,7 +62,6 @@
|
||||
"jsdom": "^24.0.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"lottie-react": "^2.4.0",
|
||||
"mime": "^4.0.3",
|
||||
"parse-torrent": "^11.0.16",
|
||||
"piscina": "^4.5.1",
|
||||
"ps-list": "^8.1.1",
|
||||
|
@ -1,7 +1,6 @@
|
||||
{
|
||||
"home": {
|
||||
"featured": "مميّز",
|
||||
"recently_added": "مضاف مؤخراً",
|
||||
"trending": "شائع",
|
||||
"surprise_me": "فاجئني",
|
||||
"no_results": "لم يتم العثور على نتائج"
|
||||
@ -15,12 +14,7 @@
|
||||
"paused": "{{title}} (متوقف)",
|
||||
"downloading": "{{title}} ({{percentage}} - جارٍ التنزيل...)",
|
||||
"filter": "بحث في المكتبة",
|
||||
"follow_us": "تابعنا",
|
||||
"home": "الرئيسية",
|
||||
"discord": "انضم إلى الـDiscord الخاص بنا",
|
||||
"telegram": "انضم إلى قناة Telegram الخاصة بنا",
|
||||
"x": "تابعنا على X",
|
||||
"github": "ساهم في مشروعنا على GitHub"
|
||||
"home": "الرئيسية"
|
||||
},
|
||||
"header": {
|
||||
"search": "ابحث عن الألعاب",
|
||||
|
@ -1,7 +1,6 @@
|
||||
{
|
||||
"home": {
|
||||
"featured": "Рэкамэндаванае",
|
||||
"recently_added": "Нядаўна дададзенае",
|
||||
"trending": "Актуальнае",
|
||||
"surprise_me": "Здзіві мяне",
|
||||
"no_results": "Няма вынікаў"
|
||||
@ -15,12 +14,7 @@
|
||||
"paused": "{{title}} (Спынена)",
|
||||
"downloading": "{{title}} ({{percentage}} - Сцягванне…)",
|
||||
"filter": "Фільтар бібліятэкі",
|
||||
"follow_us": "Падпісвайцеся на нас",
|
||||
"home": "Галоўная",
|
||||
"discord": "Далучайцеся да Discord",
|
||||
"telegram": "Далучайцеся да Telegram",
|
||||
"x": "Падпісвайцеся на X",
|
||||
"github": "Зрабіць свой унёсак на GitHub"
|
||||
"home": "Галоўная"
|
||||
},
|
||||
"header": {
|
||||
"search": "Пошук",
|
||||
|
@ -1,7 +1,6 @@
|
||||
{
|
||||
"home": {
|
||||
"featured": "Anbefalet",
|
||||
"recently_added": "Nyligt tilføjet",
|
||||
"trending": "Trender",
|
||||
"surprise_me": "Overrask mig",
|
||||
"no_results": "Ingen resultater fundet"
|
||||
@ -15,12 +14,7 @@
|
||||
"paused": "{{title}} (Paused)",
|
||||
"downloading": "{{title}} ({{percentage}} - Downloading…)",
|
||||
"filter": "Filtrer bibliotek",
|
||||
"follow_us": "Følg os",
|
||||
"home": "Hjem",
|
||||
"discord": "Tilslut dig vores Discord",
|
||||
"telegram": "Tilslut dig vores Telegram",
|
||||
"x": "Følg på X",
|
||||
"github": "Bidrag på GitHub"
|
||||
"home": "Hjem"
|
||||
},
|
||||
"header": {
|
||||
"search": "Søg spil",
|
||||
|
@ -228,13 +228,21 @@
|
||||
"user_profile": {
|
||||
"amount_hours": "{{amount}} hours",
|
||||
"amount_minutes": "{{amount}} minutes",
|
||||
"play_time": "Played for {{amount}}",
|
||||
"last_time_played": "Last played {{period}}",
|
||||
"sign_out": "Sign out",
|
||||
"activity": "Recent activity",
|
||||
"library": "Library",
|
||||
"total_play_time": "Total playtime: {{amount}}",
|
||||
"no_recent_activity_title": "Hmmm… nothing here",
|
||||
"no_recent_activity_description": "You haven't played any games recently. It's time to change that!"
|
||||
"no_recent_activity_description": "You haven't played any games recently. It's time to change that!",
|
||||
"display_name": "Display name",
|
||||
"saving": "Saving",
|
||||
"save": "Save",
|
||||
"edit_profile": "Edit Profile",
|
||||
"saved_successfully": "Saved successfully",
|
||||
"try_again": "Please, try again",
|
||||
"signout_modal_title": "Are you sure?",
|
||||
"cancel": "Cancel",
|
||||
"signout": "Sign Out"
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
{
|
||||
"home": {
|
||||
"featured": "پیشنهادی",
|
||||
"recently_added": "تازه اضافه شده",
|
||||
"trending": "پرطرفدار",
|
||||
"surprise_me": "سوپرایزم کن",
|
||||
"no_results": "اتمامای پیدا نشد"
|
||||
@ -15,12 +14,7 @@
|
||||
"paused": "{{title}} (متوقف شده)",
|
||||
"downloading": "{{title}} ({{percentage}} - در حال دانلود…)",
|
||||
"filter": "فیلتر کردن کتابخانه",
|
||||
"follow_us": "دنبال کردن ما",
|
||||
"home": "خانه",
|
||||
"discord": "عضویت در دیسکورد ما",
|
||||
"telegram": "عضویت در تلگرام ما",
|
||||
"x": "دنبال کرد در ایکس",
|
||||
"github": "مشارکت در گیتهاب"
|
||||
"home": "خانه"
|
||||
},
|
||||
"header": {
|
||||
"search": "جستجوی بازیها",
|
||||
|
@ -1,7 +1,6 @@
|
||||
{
|
||||
"home": {
|
||||
"featured": "En vedette",
|
||||
"recently_added": "Récemment ajouté",
|
||||
"trending": "Tendance",
|
||||
"surprise_me": "Surprenez-moi",
|
||||
"no_results": "Aucun résultat trouvé"
|
||||
@ -15,8 +14,7 @@
|
||||
"paused": "{{title}} (En pause)",
|
||||
"downloading": "{{title}} ({{percentage}} - Téléchargement en cours…)",
|
||||
"filter": "Filtrer la bibliothèque",
|
||||
"home": "Page d’accueil",
|
||||
"follow_us": "Suivez-nous"
|
||||
"home": "Page d’accueil"
|
||||
},
|
||||
"header": {
|
||||
"search": "Recherche",
|
||||
|
@ -1,7 +1,6 @@
|
||||
{
|
||||
"home": {
|
||||
"featured": "Featured",
|
||||
"recently_added": "Nemrég hozzáadott",
|
||||
"trending": "Népszerű",
|
||||
"surprise_me": "Lepj meg",
|
||||
"no_results": "Nem található"
|
||||
@ -15,7 +14,6 @@
|
||||
"paused": "{{title}} (Szünet)",
|
||||
"downloading": "{{title}} ({{percentage}} - Letöltés…)",
|
||||
"filter": "Könyvtár szűrése",
|
||||
"follow_us": "Kövess minket",
|
||||
"home": "Főoldal"
|
||||
},
|
||||
"header": {
|
||||
|
@ -1,7 +1,6 @@
|
||||
{
|
||||
"home": {
|
||||
"featured": "Unggulan",
|
||||
"recently_added": "Terbaru",
|
||||
"trending": "Trending",
|
||||
"surprise_me": "Kejutkan Saya",
|
||||
"no_results": "Tidak ada hasil"
|
||||
@ -15,12 +14,7 @@
|
||||
"paused": "{{title}} (Terhenti)",
|
||||
"downloading": "{{title}} ({{percentage}} - Mengunduh…)",
|
||||
"filter": "Filter koleksi",
|
||||
"follow_us": "Ikuti kami",
|
||||
"home": "Beranda",
|
||||
"discord": "Gabung Discord kami",
|
||||
"telegram": "Gabung Telegram kami",
|
||||
"x": "Ikuti akun X kami",
|
||||
"github": "Kontribusi di GitHub"
|
||||
"home": "Beranda"
|
||||
},
|
||||
"header": {
|
||||
"search": "Pencarian",
|
||||
|
@ -1,7 +1,6 @@
|
||||
{
|
||||
"home": {
|
||||
"featured": "In primo piano",
|
||||
"recently_added": "Aggiunti di recente",
|
||||
"trending": "Di tendenza",
|
||||
"surprise_me": "Sorprendimi",
|
||||
"no_results": "Nessun risultato trovato"
|
||||
@ -15,12 +14,7 @@
|
||||
"paused": "{{title}} (In pausa)",
|
||||
"downloading": "{{title}} ({{percentage}} - Download…)",
|
||||
"filter": "Filtra libreria",
|
||||
"follow_us": "Seguici",
|
||||
"home": "Home",
|
||||
"discord": "Unisciti al nostro Discord",
|
||||
"telegram": "Unisciti al nostro Telegram",
|
||||
"x": "Segui su X",
|
||||
"github": "Contribuisci su GitHub"
|
||||
"home": "Home"
|
||||
},
|
||||
"header": {
|
||||
"search": "Cerca",
|
||||
|
@ -1,7 +1,6 @@
|
||||
{
|
||||
"home": {
|
||||
"featured": "추천",
|
||||
"recently_added": "최근 추가됨",
|
||||
"trending": "인기",
|
||||
"surprise_me": "무작위 추천",
|
||||
"no_results": "결과 없음"
|
||||
@ -15,12 +14,7 @@
|
||||
"paused": "{{title}} (일시 정지됨)",
|
||||
"downloading": "{{title}} ({{percentage}} - 다운로드 중…)",
|
||||
"filter": "라이브러리 정렬",
|
||||
"follow_us": "공식 SNS",
|
||||
"home": "홈",
|
||||
"discord": "공식 디스코드",
|
||||
"telegram": "공식 텔레그램",
|
||||
"x": "공식 X (구 트위터)",
|
||||
"github": "GitHub에서 기여하기"
|
||||
"home": "홈"
|
||||
},
|
||||
"header": {
|
||||
"search": "게임 검색하기",
|
||||
|
@ -1,7 +1,6 @@
|
||||
{
|
||||
"home": {
|
||||
"featured": "Uitgelicht",
|
||||
"recently_added": "Recent Toegevoegd",
|
||||
"trending": "Trending",
|
||||
"surprise_me": "Verrasing",
|
||||
"no_results": "Geen resultaten gevonden"
|
||||
@ -15,12 +14,7 @@
|
||||
"paused": "{{title}} (Gepauzeerd)",
|
||||
"downloading": "{{title}} ({{percentage}} - Downloading…)",
|
||||
"filter": "Filter Bibliotheek",
|
||||
"follow_us": "volg ons",
|
||||
"home": "Home",
|
||||
"discord": "Volg onze Discord",
|
||||
"telegram": "Volg onze Telegram",
|
||||
"x": "Volg ons op X",
|
||||
"github": "Contribute op GitHub"
|
||||
"home": "Home"
|
||||
},
|
||||
"header": {
|
||||
"search": "Zoek spellen",
|
||||
|
@ -1,7 +1,6 @@
|
||||
{
|
||||
"home": {
|
||||
"featured": "Wyróżnione",
|
||||
"recently_added": "Ostatnio dodane",
|
||||
"trending": "Trendujące",
|
||||
"surprise_me": "Zaskocz mnie",
|
||||
"no_results": "Nie znaleziono wyników"
|
||||
@ -15,12 +14,7 @@
|
||||
"paused": "{{title}} (Zatrzymano)",
|
||||
"downloading": "{{title}} ({{percentage}} - Pobieranie…)",
|
||||
"filter": "Filtruj biblioteke",
|
||||
"follow_us": "Śledź nas",
|
||||
"home": "Główna",
|
||||
"discord": "Dołącz nasz Discord",
|
||||
"telegram": "Dołącz nasz Telegram",
|
||||
"x": "Śledź na X",
|
||||
"github": "Przyczyń się na GitHub"
|
||||
"home": "Główna"
|
||||
},
|
||||
"header": {
|
||||
"search": "Szukaj",
|
||||
|
@ -15,7 +15,6 @@
|
||||
"downloading": "{{title}} ({{percentage}} - Baixando…)",
|
||||
"filter": "Filtrar biblioteca",
|
||||
"home": "Início",
|
||||
"follow_us": "Acompanhe-nos",
|
||||
"queued": "{{title}} (Na fila)",
|
||||
"game_has_no_executable": "Jogo não possui executável selecionado"
|
||||
},
|
||||
@ -229,13 +228,21 @@
|
||||
"user_profile": {
|
||||
"amount_hours": "{{amount}} horas",
|
||||
"amount_minutes": "{{amount}} minutos",
|
||||
"play_time": "Jogado por {{amount}}",
|
||||
"last_time_played": "Jogou {{period}}",
|
||||
"sign_out": "Sair da conta",
|
||||
"activity": "Atividade recente",
|
||||
"library": "Biblioteca",
|
||||
"total_play_time": "Tempo total de jogo: {{amount}}",
|
||||
"no_recent_activity_title": "Hmmm… nada por aqui",
|
||||
"no_recent_activity_description": "Parece que você não jogou nada recentemente. Que tal começar agora?"
|
||||
"no_recent_activity_description": "Parece que você não jogou nada recentemente. Que tal começar agora?",
|
||||
"display_name": "Nome de exibição",
|
||||
"saving": "Salvando…",
|
||||
"save": "Salvar",
|
||||
"edit_profile": "Editar Perfil",
|
||||
"saved_successfully": "Salvo com sucesso",
|
||||
"try_again": "Por favor, tente novamente",
|
||||
"cancel": "Cancelar",
|
||||
"signout": "Sair da conta",
|
||||
"signout_modal_title": "Tem certeza?"
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
{
|
||||
"home": {
|
||||
"featured": "Öne çıkan",
|
||||
"recently_added": "Son eklenen",
|
||||
"trending": "Popüler",
|
||||
"surprise_me": "Şaşırt beni",
|
||||
"no_results": "Sonuç bulunamadı"
|
||||
@ -15,12 +14,7 @@
|
||||
"paused": "{{title}} (Duraklatıldı)",
|
||||
"downloading": "{{title}} ({{percentage}} - İndiriliyor…)",
|
||||
"filter": "Kütüphaneyi filtrele",
|
||||
"follow_us": "Bizi takip et",
|
||||
"home": "Ana menü",
|
||||
"discord": "Discord'umuza katıl",
|
||||
"telegram": "Telegram'umuza katıl",
|
||||
"x": "X'te bizi takip et",
|
||||
"github": "GitHub'da bize katkı yap"
|
||||
"home": "Ana menü"
|
||||
},
|
||||
"header": {
|
||||
"search": "Ara",
|
||||
|
@ -1,7 +1,6 @@
|
||||
{
|
||||
"home": {
|
||||
"featured": "Рекомендоване",
|
||||
"recently_added": "Нове",
|
||||
"trending": "У тренді",
|
||||
"surprise_me": "Здивуй мене",
|
||||
"no_results": "Результатів не знайдено"
|
||||
@ -15,12 +14,7 @@
|
||||
"paused": "{{title}} (Призупинено)",
|
||||
"downloading": "{{title}} ({{percentage}} - Завантаження…)",
|
||||
"filter": "Фільтр бібліотеки",
|
||||
"follow_us": "Підписуйтесь на нас",
|
||||
"home": "Головна",
|
||||
"discord": "Приєднуйтесь до Discord",
|
||||
"telegram": "Приєднуйтесь до Telegram",
|
||||
"x": "Підписуйтесь на X",
|
||||
"github": "Зробіть свій внесок на GitHub"
|
||||
"home": "Головна"
|
||||
},
|
||||
"header": {
|
||||
"search": "Пошук",
|
||||
|
@ -1,7 +1,6 @@
|
||||
{
|
||||
"home": {
|
||||
"featured": "特色推荐",
|
||||
"recently_added": "最近添加",
|
||||
"trending": "最近热门",
|
||||
"surprise_me": "向我推荐",
|
||||
"no_results": "没有找到结果"
|
||||
@ -15,12 +14,7 @@
|
||||
"paused": "{{title}} (已暂停)",
|
||||
"downloading": "{{title}} ({{percentage}} - 正在下载…)",
|
||||
"filter": "筛选游戏库",
|
||||
"follow_us": "关注我们",
|
||||
"home": "主页",
|
||||
"discord": "加入我们的Discord",
|
||||
"telegram": "加入我们的Telegram",
|
||||
"x": "在X上关注我们",
|
||||
"github": "在GitHub上贡献"
|
||||
"home": "主页"
|
||||
},
|
||||
"header": {
|
||||
"search": "搜索",
|
||||
|
@ -22,6 +22,7 @@ import "./library/open-game-installer-path";
|
||||
import "./library/update-executable-path";
|
||||
import "./library/remove-game";
|
||||
import "./library/remove-game-from-library";
|
||||
import "./misc/is-user-logged-in";
|
||||
import "./misc/open-external";
|
||||
import "./misc/show-open-dialog";
|
||||
import "./torrenting/cancel-game-download";
|
||||
|
8
src/main/events/misc/is-user-logged-in.ts
Normal file
8
src/main/events/misc/is-user-logged-in.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { registerEvent } from "../register-event";
|
||||
import { HydraApi } from "@main/services/hydra-api";
|
||||
|
||||
const isUserLoggedIn = async (_event: Electron.IpcMainInvokeEvent) => {
|
||||
return HydraApi.isLoggedIn();
|
||||
};
|
||||
|
||||
registerEvent("isUserLoggedIn", isUserLoggedIn);
|
@ -3,7 +3,7 @@ import { HydraApi } from "@main/services/hydra-api";
|
||||
import axios from "axios";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import mime from "mime";
|
||||
import { fileTypeFromFile } from "file-type";
|
||||
import { UserProfile } from "@types";
|
||||
|
||||
const patchUserProfile = async (
|
||||
@ -44,11 +44,11 @@ const updateProfile = async (
|
||||
.then(async (preSignedResponse) => {
|
||||
const { presignedUrl, profileImageUrl } = preSignedResponse.data;
|
||||
|
||||
const mimeType = mime.getType(newProfileImagePath);
|
||||
const mimeType = await fileTypeFromFile(newProfileImagePath);
|
||||
|
||||
await axios.put(presignedUrl, fileBuffer, {
|
||||
headers: {
|
||||
"Content-Type": mimeType,
|
||||
"Content-Type": mimeType?.mime,
|
||||
},
|
||||
});
|
||||
return profileImageUrl;
|
||||
|
@ -14,6 +14,10 @@ export class HydraApi {
|
||||
expirationTimestamp: 0,
|
||||
};
|
||||
|
||||
static isLoggedIn() {
|
||||
return this.userAuth.authToken !== "";
|
||||
}
|
||||
|
||||
static async handleExternalAuth(auth: string) {
|
||||
const { payload } = url.parse(auth, true).query;
|
||||
|
||||
|
@ -106,6 +106,7 @@ contextBridge.exposeInMainWorld("electron", {
|
||||
getVersion: () => ipcRenderer.invoke("getVersion"),
|
||||
getDefaultDownloadsPath: () => ipcRenderer.invoke("getDefaultDownloadsPath"),
|
||||
openExternal: (src: string) => ipcRenderer.invoke("openExternal", src),
|
||||
isUserLoggedIn: () => ipcRenderer.invoke("isUserLoggedIn"),
|
||||
showOpenDialog: (options: Electron.OpenDialogOptions) =>
|
||||
ipcRenderer.invoke("showOpenDialog", options),
|
||||
platform: process.platform,
|
||||
|
@ -86,9 +86,12 @@ export function App() {
|
||||
dispatch(setProfileBackground(profileBackground));
|
||||
}
|
||||
|
||||
/* TODO: Check if user is logged in before calling this */
|
||||
fetchUserDetails().then((response) => {
|
||||
if (response) setUserDetails(response);
|
||||
window.electron.isUserLoggedIn().then((isLoggedIn) => {
|
||||
if (isLoggedIn) {
|
||||
fetchUserDetails().then((response) => {
|
||||
if (response) setUserDetails(response);
|
||||
});
|
||||
}
|
||||
});
|
||||
}, [dispatch, fetchUserDetails]);
|
||||
|
||||
|
1
src/renderer/src/declaration.d.ts
vendored
1
src/renderer/src/declaration.d.ts
vendored
@ -96,6 +96,7 @@ declare global {
|
||||
|
||||
/* Misc */
|
||||
openExternal: (src: string) => Promise<void>;
|
||||
isUserLoggedIn: () => Promise<boolean>;
|
||||
getVersion: () => Promise<string>;
|
||||
ping: () => string;
|
||||
getDefaultDownloadsPath: () => Promise<string>;
|
||||
|
@ -12,6 +12,7 @@ import { buildGameDetailsPath } from "@renderer/helpers";
|
||||
import { PersonIcon, TelescopeIcon } from "@primer/octicons-react";
|
||||
import { Button } from "@renderer/components";
|
||||
import { UserEditProfileModal } from "./user-edit-modal";
|
||||
import { UserSignOutModal } from "./user-signout-modal";
|
||||
|
||||
const MAX_MINUTES_TO_SHOW_IN_PLAYTIME = 120;
|
||||
|
||||
@ -29,6 +30,7 @@ export function UserContent({
|
||||
const { userDetails, profileBackground, signOut } = useUserDetails();
|
||||
|
||||
const [showEditProfileModal, setShowEditProfileModal] = useState(false);
|
||||
const [showSignOutModal, setShowSignOutModal] = useState(false);
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
@ -65,7 +67,7 @@ export function UserContent({
|
||||
setShowEditProfileModal(true);
|
||||
};
|
||||
|
||||
const handleSignout = async () => {
|
||||
const handleConfirmSignout = async () => {
|
||||
signOut();
|
||||
navigate("/");
|
||||
};
|
||||
@ -87,6 +89,12 @@ export function UserContent({
|
||||
userProfile={userProfile}
|
||||
/>
|
||||
|
||||
<UserSignOutModal
|
||||
visible={showSignOutModal}
|
||||
onClose={() => setShowSignOutModal(false)}
|
||||
onConfirm={handleConfirmSignout}
|
||||
/>
|
||||
|
||||
<section
|
||||
className={styles.profileContentBox}
|
||||
style={{
|
||||
@ -124,7 +132,10 @@ export function UserContent({
|
||||
Editar perfil
|
||||
</Button>
|
||||
|
||||
<Button theme="danger" onClick={handleSignout}>
|
||||
<Button
|
||||
theme="danger"
|
||||
onClick={() => setShowSignOutModal(true)}
|
||||
>
|
||||
{t("sign_out")}
|
||||
</Button>
|
||||
</>
|
||||
|
@ -5,6 +5,7 @@ import { DeviceCameraIcon, PersonIcon } from "@primer/octicons-react";
|
||||
import { SPACING_UNIT } from "@renderer/theme.css";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { useToast, useUserDetails } from "@renderer/hooks";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
export interface UserEditProfileModalProps {
|
||||
userProfile: UserProfile;
|
||||
@ -19,6 +20,8 @@ export const UserEditProfileModal = ({
|
||||
onClose,
|
||||
updateUserProfile,
|
||||
}: UserEditProfileModalProps) => {
|
||||
const { t } = useTranslation("user_profile");
|
||||
|
||||
const [displayName, setDisplayName] = useState("");
|
||||
const [newImagePath, setNewImagePath] = useState<string | null>(null);
|
||||
const [isSaving, setIsSaving] = useState(false);
|
||||
@ -36,8 +39,8 @@ export const UserEditProfileModal = ({
|
||||
properties: ["openFile"],
|
||||
filters: [
|
||||
{
|
||||
name: "Profile image",
|
||||
extensions: ["jpg", "png", "gif", "webp", "jpeg"],
|
||||
name: "Image",
|
||||
extensions: ["jpg", "jpeg", "png", "gif", "webp", "bmp"],
|
||||
},
|
||||
],
|
||||
});
|
||||
@ -58,11 +61,11 @@ export const UserEditProfileModal = ({
|
||||
patchUser(displayName, newImagePath)
|
||||
.then(async () => {
|
||||
await updateUserProfile();
|
||||
showSuccessToast("Salvo com sucesso");
|
||||
showSuccessToast(t("saved_successfully"));
|
||||
cleanFormAndClose();
|
||||
})
|
||||
.catch(() => {
|
||||
showErrorToast("Tente novamente");
|
||||
showErrorToast(t("try_again"));
|
||||
})
|
||||
.finally(() => {
|
||||
setIsSaving(false);
|
||||
@ -89,7 +92,7 @@ export const UserEditProfileModal = ({
|
||||
<>
|
||||
<Modal
|
||||
visible={visible}
|
||||
title="Editar Perfil"
|
||||
title={t("edit_profile")}
|
||||
onClose={cleanFormAndClose}
|
||||
>
|
||||
<form
|
||||
@ -123,8 +126,10 @@ export const UserEditProfileModal = ({
|
||||
</button>
|
||||
|
||||
<TextField
|
||||
label="Nome de exibição"
|
||||
label={t("display_name")}
|
||||
value={displayName}
|
||||
required
|
||||
minLength={3}
|
||||
containerProps={{ style: { width: "100%" } }}
|
||||
onChange={(e) => setDisplayName(e.target.value)}
|
||||
/>
|
||||
@ -133,7 +138,7 @@ export const UserEditProfileModal = ({
|
||||
style={{ alignSelf: "end" }}
|
||||
type="submit"
|
||||
>
|
||||
{isSaving ? "Salvando…" : "Salvar"}
|
||||
{isSaving ? t("saving") : t("save")}
|
||||
</Button>
|
||||
</form>
|
||||
</Modal>
|
||||
|
37
src/renderer/src/pages/user/user-signout-modal.tsx
Normal file
37
src/renderer/src/pages/user/user-signout-modal.tsx
Normal file
@ -0,0 +1,37 @@
|
||||
import { Button, Modal } from "@renderer/components";
|
||||
import * as styles from "./user.css";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
export interface UserEditProfileModalProps {
|
||||
visible: boolean;
|
||||
onConfirm: () => void;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
export const UserSignOutModal = ({
|
||||
visible,
|
||||
onConfirm,
|
||||
onClose,
|
||||
}: UserEditProfileModalProps) => {
|
||||
const { t } = useTranslation("user_profile");
|
||||
|
||||
return (
|
||||
<>
|
||||
<Modal
|
||||
visible={visible}
|
||||
title={t("signout_modal_title")}
|
||||
onClose={onClose}
|
||||
>
|
||||
<div className={styles.signOutModalButtonsContainer}>
|
||||
<Button onClick={onConfirm} theme="outline">
|
||||
{t("signout")}
|
||||
</Button>
|
||||
|
||||
<Button onClick={onClose} theme="primary">
|
||||
{t("cancel")}
|
||||
</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
};
|
@ -1,13 +1,40 @@
|
||||
import Skeleton from "react-loading-skeleton";
|
||||
import cn from "classnames";
|
||||
import * as styles from "./user.css";
|
||||
import { SPACING_UNIT } from "@renderer/theme.css";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
export const UserSkeleton = () => {
|
||||
const { t } = useTranslation("user_profile");
|
||||
return (
|
||||
<>
|
||||
<Skeleton className={styles.profileHeaderSkeleton} />
|
||||
<div className={styles.profileContent}>
|
||||
<Skeleton height={140} style={{ flex: 1 }} />
|
||||
<Skeleton width={300} className={styles.contentSidebar} />
|
||||
<div className={styles.profileGameSection}>
|
||||
<h2>{t("activity")}</h2>
|
||||
{Array.from({ length: 3 }).map((_, index) => (
|
||||
<Skeleton
|
||||
key={index}
|
||||
height={72}
|
||||
style={{ flex: "1", width: "100%" }}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className={cn(styles.contentSidebar, styles.profileGameSection)}>
|
||||
<h2>{t("library")}</h2>
|
||||
<div
|
||||
style={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: "repeat(4, 1fr)",
|
||||
gap: `${SPACING_UNIT}px`,
|
||||
}}
|
||||
>
|
||||
{Array.from({ length: 8 }).map((_, index) => (
|
||||
<Skeleton key={index} style={{ aspectRatio: "1" }} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
@ -132,9 +132,6 @@ export const feedItem = style({
|
||||
|
||||
export const gameListItem = style({
|
||||
color: vars.color.body,
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
gap: `${SPACING_UNIT}px`,
|
||||
transition: "all ease 0.2s",
|
||||
cursor: "pointer",
|
||||
zIndex: "1",
|
||||
@ -153,7 +150,7 @@ export const gameInformation = style({
|
||||
});
|
||||
|
||||
export const profileHeaderSkeleton = style({
|
||||
height: "200px",
|
||||
height: "144px",
|
||||
});
|
||||
|
||||
export const editProfileImageBadge = style({
|
||||
@ -191,3 +188,11 @@ export const noDownloads = style({
|
||||
flexDirection: "column",
|
||||
gap: `${SPACING_UNIT}px`,
|
||||
});
|
||||
|
||||
export const signOutModalButtonsContainer = style({
|
||||
display: "flex",
|
||||
width: "100%",
|
||||
justifyContent: "end",
|
||||
alignItems: "center",
|
||||
gap: `${SPACING_UNIT}px`,
|
||||
});
|
||||
|
14
yarn.lock
14
yarn.lock
@ -3305,6 +3305,15 @@ file-type@^18.7.0:
|
||||
strtok3 "^7.0.0"
|
||||
token-types "^5.0.1"
|
||||
|
||||
file-type@^19.0.0:
|
||||
version "19.0.0"
|
||||
resolved "https://registry.yarnpkg.com/file-type/-/file-type-19.0.0.tgz#62a6cadc43f73ba38c53e1a174943a75fdafafa9"
|
||||
integrity sha512-s7cxa7/leUWLiXO78DVVfBVse+milos9FitauDLG1pI7lNaJ2+5lzPnr2N24ym+84HVwJL6hVuGfgVE+ALvU8Q==
|
||||
dependencies:
|
||||
readable-web-to-node-stream "^3.0.2"
|
||||
strtok3 "^7.0.0"
|
||||
token-types "^5.0.1"
|
||||
|
||||
file-uri-to-path@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
|
||||
@ -4518,11 +4527,6 @@ mime@^2.5.2:
|
||||
resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367"
|
||||
integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==
|
||||
|
||||
mime@^4.0.3:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/mime/-/mime-4.0.3.tgz#cd4a1aa052fc980dfc34f111fe1be9e8b878c5d2"
|
||||
integrity sha512-KgUb15Oorc0NEKPbvfa0wRU+PItIEZmiv+pyAO2i0oTIVTJhlzMclU7w4RXWQrSOVH5ax/p/CkIO7KI4OyFJTQ==
|
||||
|
||||
mimic-fn@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc"
|
||||
|
Loading…
Reference in New Issue
Block a user