From 2ee3fdc22341adf480159922e4b97e1f5956af4c Mon Sep 17 00:00:00 2001 From: Lianela <140931995+Lianela@users.noreply.github.com> Date: Fri, 5 Jul 2024 12:40:16 -0600 Subject: [PATCH 01/35] updated es-translation.json added new string fixed one string --- src/locales/es/translation.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/locales/es/translation.json b/src/locales/es/translation.json index 77b43dd8..9724fb2b 100644 --- a/src/locales/es/translation.json +++ b/src/locales/es/translation.json @@ -69,7 +69,7 @@ "minutes": "minutos", "amount_hours": "{{amount}} horas", "amount_minutes": "{{amount}} minutos", - "accuracy": "{{accuracy}}% precisión", + "accuracy": "{{accuracy}}% completado", "add_to_library": "Agregar a la biblioteca", "remove_from_library": "Eliminar de la biblioteca", "no_downloads": "No hay descargas disponibles", @@ -200,7 +200,8 @@ "repack_list_updated": "Lista de repacks actualizadas", "repack_count_one": "{{count}} repack ha sido añadido", "repack_count_other": "{{count}} repacks añadidos", - "new_update_available": "Version {{version}} disponible" + "new_update_available": "Version {{version}} disponible", + "restart_to_install_update": "Reinicia Hydra para instalar la actualización" }, "system_tray": { "open": "Abrir Hydra", From 18488490c15080487285635233aebe02e9f4cd06 Mon Sep 17 00:00:00 2001 From: Lianela <140931995+Lianela@users.noreply.github.com> Date: Sat, 6 Jul 2024 16:44:36 -0600 Subject: [PATCH 02/35] fixed some strings changed some words and translations to a new one making some things easier to understand --- src/locales/es/translation.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/locales/es/translation.json b/src/locales/es/translation.json index 9724fb2b..84c86edd 100644 --- a/src/locales/es/translation.json +++ b/src/locales/es/translation.json @@ -48,7 +48,7 @@ "download_options_zero": "No hay opciones de descargas disponibles", "download_options_one": "{{count}} opción de descarga", "download_options_other": "{{count}} opciones de descargas", - "updated_at": "Actualizado el {{updated_at}}", + "updated_at": "Actualizado el: {{updated_at}}", "install": "Instalar", "resume": "Continuar", "pause": "Pausa", @@ -74,7 +74,7 @@ "remove_from_library": "Eliminar de la biblioteca", "no_downloads": "No hay descargas disponibles", "play_time": "Jugado por {{amount}}", - "last_time_played": "Jugado por última vez {{period}}", + "last_time_played": "Jugado por última vez: {{period}}", "not_played_yet": "Aún no has jugado a {{title}}", "next_suggestion": "Siguiente sugerencia", "play": "Jugar", @@ -107,8 +107,8 @@ "executable_section_description": "Ruta del archivo que se ejecutará cuando se presione \"Jugar\"", "downloads_secion_title": "Descargas", "downloads_section_description": "Buscar actualizaciones u otras versiones de este juego", - "danger_zone_section_title": "Zona de Peligro", - "danger_zone_section_description": "Eliminar este juego de tu librería o los archivos descargados por Hydra", + "danger_zone_section_title": "Opciones Avanzadas", + "danger_zone_section_description": "Eliminar este juego de tu librería o los archivos descargados por Hydra (Esto solo eliminará los archivos de instalación y no el juego instalado)", "download_in_progress": "Descarga en progreso", "download_paused": "Descarga pausada", "last_downloaded_option": "Última opción descargada", @@ -138,7 +138,7 @@ "deleting": "Eliminando instalador…", "delete": "Eliminar instalador", "delete_modal_title": "¿Estás seguro?", - "delete_modal_description": "Esto eliminará todos los archivos de instalación de tu computadora.", + "delete_modal_description": "Esto eliminará todos los archivos de la instalación del repack del juego de tu computadora. (Si ya instalaste el juego, puedes eliminar esto, no afectará al juego)", "install": "Instalar", "download_in_progress": "En progreso", "queued_downloads": "Descargas en cola", From 5683a0ba490b45bf434a82636acc0cc2f621f394 Mon Sep 17 00:00:00 2001 From: Lianela <140931995+Lianela@users.noreply.github.com> Date: Sat, 6 Jul 2024 16:53:02 -0600 Subject: [PATCH 03/35] variation of one line changed in a different variation a translation --- src/locales/es/translation.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/locales/es/translation.json b/src/locales/es/translation.json index 84c86edd..4d29b156 100644 --- a/src/locales/es/translation.json +++ b/src/locales/es/translation.json @@ -224,13 +224,13 @@ "user_profile": { "amount_hours": "{{amount}} horas", "amount_minutes": "{{amount}} minutos", - "last_time_played": "Última vez jugado {{period}}", + "last_time_played": "Última vez jugado: {{period}}", "activity": "Actividad reciente", "library": "Biblioteca", "total_play_time": "Total de tiempo jugado: {{amount}}", - "no_recent_activity_title": "Que raro, no hay nada por acá, ¿que tal si jugamos algo para empezar?", + "no_recent_activity_title": "Que raro, no hay nada por acá...", "no_recent_activity_description": "No has jugado ningún juego recientemente, ¡vamos a cambiar eso ahora!", - "display_name": "Nombre a mostrar", + "display_name": "Nombre en pantalla", "saving": "Guardando", "save": "Guardar", "edit_profile": "Editar perfil", From 6822ed8447107838ef981e415edc8f2bd1efb215 Mon Sep 17 00:00:00 2001 From: Ezequiel Neri Ferreira <106291086+Ezequiel9898@users.noreply.github.com> Date: Sun, 7 Jul 2024 23:42:12 -0300 Subject: [PATCH 04/35] Update translation.json --- src/locales/pt/translation.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/locales/pt/translation.json b/src/locales/pt/translation.json index f1a4e77e..02c0879f 100644 --- a/src/locales/pt/translation.json +++ b/src/locales/pt/translation.json @@ -45,7 +45,7 @@ "download_options_one": "{{count}} opção de download", "download_options_other": "{{count}} opções de download", "updated_at": "Atualizado {{updated_at}}", - "resume": "Resumir", + "resume": "Retomar", "pause": "Pausar", "cancel": "Cancelar", "remove": "Remover", From a9b92f3fc1b8d5ef0527c4678948a5c46b7569e9 Mon Sep 17 00:00:00 2001 From: Lianela <140931995+Lianela@users.noreply.github.com> Date: Tue, 9 Jul 2024 10:35:19 -0600 Subject: [PATCH 05/35] accuracy fixed --- src/locales/es/translation.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/locales/es/translation.json b/src/locales/es/translation.json index 4d29b156..ddcfdbca 100644 --- a/src/locales/es/translation.json +++ b/src/locales/es/translation.json @@ -69,7 +69,7 @@ "minutes": "minutos", "amount_hours": "{{amount}} horas", "amount_minutes": "{{amount}} minutos", - "accuracy": "{{accuracy}}% completado", + "accuracy": "Completar al {{accuracy}}%", "add_to_library": "Agregar a la biblioteca", "remove_from_library": "Eliminar de la biblioteca", "no_downloads": "No hay descargas disponibles", From e2b089e0f85abae85e8e09fb8c37a12c9acafda9 Mon Sep 17 00:00:00 2001 From: Antecess <59663394+xxDRV@users.noreply.github.com> Date: Mon, 15 Jul 2024 13:47:09 +0500 Subject: [PATCH 06/35] Updated RU to fit new features --- src/locales/ru/translation.json | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/locales/ru/translation.json b/src/locales/ru/translation.json index 69a9c33d..f6f18d11 100644 --- a/src/locales/ru/translation.json +++ b/src/locales/ru/translation.json @@ -36,7 +36,8 @@ "no_downloads_in_progress": "Нет активных загрузок", "downloading_metadata": "Загрузка метаданных {{title}}…", "downloading": "Загрузка {{title}}… ({{percentage}} завершено) - Окончание {{eta}} - {{speed}}", - "calculating_eta": "Загрузка {{title}}… ({{percentage}} завершено) - Подсчёт оставшегося времени…" + "calculating_eta": "Загрузка {{title}}… ({{percentage}} завершено) - Подсчёт оставшегося времени…", + "checking_files": "Проверка файлов {{title}}… ({{percentage}} завершено)" }, "catalogue": { "next_page": "Следующая страница", @@ -144,7 +145,8 @@ "downloads_completed": "Завершено", "queued": "В очереди", "no_downloads_title": "Здесь так пусто...", - "no_downloads_description": "Вы ещё ничего не скачали через Hydra, но никогда не поздно начать." + "no_downloads_description": "Вы ещё ничего не скачали через Hydra, но никогда не поздно начать.", + "checking_files": "Проверка файлов…" }, "settings": { "downloads_path": "Путь загрузок", @@ -198,7 +200,8 @@ "repack_list_updated": "Список репаков обновлен", "repack_count_one": "{{count}} репак добавлен", "repack_count_other": "{{count}} репаков добавлено", - "new_update_available": "Доступна версия {{version}}" + "new_update_available": "Доступна версия {{version}}", + "restart_to_install_update": "Перезапустите Hydra для установки обновления" }, "system_tray": { "open": "Открыть Hydra", From 8a01352eaba028b6abc474380ba0d061cde5a829 Mon Sep 17 00:00:00 2001 From: Lianela <140931995+Lianela@users.noreply.github.com> Date: Wed, 17 Jul 2024 12:56:24 -0600 Subject: [PATCH 07/35] updated es-translation.json Reverted changes on accuracy --- src/locales/es/translation.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/locales/es/translation.json b/src/locales/es/translation.json index ddcfdbca..5e016d34 100644 --- a/src/locales/es/translation.json +++ b/src/locales/es/translation.json @@ -69,7 +69,7 @@ "minutes": "minutos", "amount_hours": "{{amount}} horas", "amount_minutes": "{{amount}} minutos", - "accuracy": "Completar al {{accuracy}}%", + "accuracy": "{{accuracy}}% precisión", "add_to_library": "Agregar a la biblioteca", "remove_from_library": "Eliminar de la biblioteca", "no_downloads": "No hay descargas disponibles", From 6ccbff01602fc9fef768ebbb4156292ecdbc6566 Mon Sep 17 00:00:00 2001 From: Zamitto <167933696+zamitto@users.noreply.github.com> Date: Mon, 8 Jul 2024 22:07:14 -0300 Subject: [PATCH 08/35] feat: creating friends section --- src/locales/en/translation.json | 9 +- src/locales/pt/translation.json | 7 +- src/main/services/hydra-api.ts | 4 +- src/renderer/index.html | 2 +- src/renderer/src/hooks/use-user-details.ts | 5 + .../src/pages/user/user-add-friends-modal.tsx | 123 ++++++++++++++ src/renderer/src/pages/user/user-content.tsx | 160 +++++++++++++----- src/renderer/src/pages/user/user.css.ts | 32 +++- src/types/index.ts | 17 +- 9 files changed, 307 insertions(+), 52 deletions(-) create mode 100644 src/renderer/src/pages/user/user-add-friends-modal.tsx diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index e44dc7ea..2dadbcee 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -241,6 +241,13 @@ "successfully_signed_out": "Successfully signed out", "sign_out": "Sign out", "playing_for": "Playing for {{amount}}", - "sign_out_modal_text": "Your library is linked with your current account. When signing out, your library will not be visible anymore, and any progress will not be saved. Continue with sign out?" + "sign_out_modal_text": "Your library is linked with your current account. When signing out, your library will not be visible anymore, and any progress will not be saved. Continue with sign out?", + "add_friends": "Add Friends", + "friend_code": "Friend code", + "see_profile": "See profile", + "sending": "Sending", + "send": "Add friend", + "friend_request_sent": "Friend request sent", + "friends": "Friends" } } diff --git a/src/locales/pt/translation.json b/src/locales/pt/translation.json index 02c0879f..9ff165f9 100644 --- a/src/locales/pt/translation.json +++ b/src/locales/pt/translation.json @@ -241,6 +241,11 @@ "sign_out": "Sair da conta", "sign_out_modal_title": "Tem certeza?", "playing_for": "Jogando por {{amount}}", - "sign_out_modal_text": "Sua biblioteca de jogos está associada com a sua conta atual. Ao sair, sua biblioteca não aparecerá mais no Hydra e qualquer progresso não será salvo. Deseja continuar?" + "sign_out_modal_text": "Sua biblioteca de jogos está associada com a sua conta atual. Ao sair, sua biblioteca não aparecerá mais no Hydra e qualquer progresso não será salvo. Deseja continuar?", + "add_friends": "Adicionar Amigos", + "friend_code": "Código de amigo", + "see_profile": "Ver perfil", + "friend_request_sent": "Pedido de amizade enviado", + "friends": "Amigos" } } diff --git a/src/main/services/hydra-api.ts b/src/main/services/hydra-api.ts index 98b783f3..1abae98c 100644 --- a/src/main/services/hydra-api.ts +++ b/src/main/services/hydra-api.ts @@ -98,9 +98,9 @@ export class HydraApi { logger.error(config.method, config.baseURL, config.url, config.headers); if (error.response) { - logger.error(error.response.status, error.response.data); + logger.error("Response", error.response.status, error.response.data); } else if (error.request) { - logger.error(error.request); + logger.error("Request", error.request); } else { logger.error("Error", error.message); } diff --git a/src/renderer/index.html b/src/renderer/index.html index 543b85a9..52276268 100644 --- a/src/renderer/index.html +++ b/src/renderer/index.html @@ -6,7 +6,7 @@ Hydra diff --git a/src/renderer/src/hooks/use-user-details.ts b/src/renderer/src/hooks/use-user-details.ts index e87f8ff6..6495ba27 100644 --- a/src/renderer/src/hooks/use-user-details.ts +++ b/src/renderer/src/hooks/use-user-details.ts @@ -78,6 +78,10 @@ export function useUserDetails() { [updateUserDetails] ); + const sendFriendRequest = useCallback(async (userId: string) => { + console.log("sending friend request to", userId); + }, []); + return { userDetails, fetchUserDetails, @@ -85,6 +89,7 @@ export function useUserDetails() { clearUserDetails, updateUserDetails, patchUser, + sendFriendRequest, profileBackground, }; } diff --git a/src/renderer/src/pages/user/user-add-friends-modal.tsx b/src/renderer/src/pages/user/user-add-friends-modal.tsx new file mode 100644 index 00000000..a872abcf --- /dev/null +++ b/src/renderer/src/pages/user/user-add-friends-modal.tsx @@ -0,0 +1,123 @@ +import { Button, Modal, TextField } from "@renderer/components"; +import { PendingFriendRequest } from "@types"; +import * as styles from "./user.css"; +import { SPACING_UNIT } from "@renderer/theme.css"; +import { useEffect, useState } from "react"; +import { useToast, useUserDetails } from "@renderer/hooks"; +import { useTranslation } from "react-i18next"; +import { useNavigate } from "react-router-dom"; + +export interface UserAddFriendsModalProps { + visible: boolean; + onClose: () => void; +} + +export const UserAddFriendsModal = ({ + visible, + onClose, +}: UserAddFriendsModalProps) => { + const { t } = useTranslation("user_profile"); + + const [friendCode, setFriendCode] = useState(""); + const [isAddingFriend, setIsAddingFriend] = useState(false); + const [pendingRequests, setPendingRequests] = useState< + PendingFriendRequest[] + >([]); + + const navigate = useNavigate(); + + const { sendFriendRequest } = useUserDetails(); + + const { showSuccessToast, showErrorToast } = useToast(); + + const handleAddFriend: React.FormEventHandler = async ( + event + ) => { + event.preventDefault(); + setIsAddingFriend(true); + sendFriendRequest(friendCode) + .then(() => { + showSuccessToast(t("friend_request_sent")); + }) + .catch(() => { + showErrorToast("falhaaaa"); + }) + .finally(() => { + setIsAddingFriend(false); + }); + }; + + useEffect(() => { + setPendingRequests([]); + }); + + const handleSeeProfileClick = () => { + navigate(`profile/${friendCode}`); + }; + + const resetModal = () => { + setFriendCode(""); + }; + + const cleanFormAndClose = () => { + resetModal(); + onClose(); + }; + + return ( + <> + +
+ setFriendCode(e.target.value)} + /> + + + + +
+ {pendingRequests.map((request) => { + return ( +

+ {request.AId} - {request.BId} +

+ ); + })} +
+
+ + ); +}; diff --git a/src/renderer/src/pages/user/user-content.tsx b/src/renderer/src/pages/user/user-content.tsx index 6f897238..8e973e7f 100644 --- a/src/renderer/src/pages/user/user-content.tsx +++ b/src/renderer/src/pages/user/user-content.tsx @@ -14,10 +14,16 @@ import { } from "@renderer/hooks"; import { useNavigate } from "react-router-dom"; import { buildGameDetailsPath, steamUrlBuilder } from "@renderer/helpers"; -import { PersonIcon, TelescopeIcon } from "@primer/octicons-react"; +import { + PersonAddIcon, + PersonIcon, + PlusCircleIcon, + TelescopeIcon, +} from "@primer/octicons-react"; import { Button, Link } from "@renderer/components"; import { UserEditProfileModal } from "./user-edit-modal"; import { UserSignOutModal } from "./user-signout-modal"; +import { UserAddFriendsModal } from "./user-add-friends-modal"; const MAX_MINUTES_TO_SHOW_IN_PLAYTIME = 120; @@ -37,6 +43,7 @@ export function UserContent({ const [showEditProfileModal, setShowEditProfileModal] = useState(false); const [showSignOutModal, setShowSignOutModal] = useState(false); + const [showAddFriendsModal, setShowAddFriendsModal] = useState(false); const { gameRunning } = useAppSelector((state) => state.gameRunning); @@ -103,6 +110,11 @@ export function UserContent({ onConfirm={handleConfirmSignout} /> + setShowAddFriendsModal(false)} + /> +

{t("activity")}

- {!userProfile.recentGames.length ? ( + {!userProfile.recentGames?.length ? (
@@ -259,54 +271,116 @@ export function UserContent({ )}
-
-
-

{t("library")}

+
+
+
+

{t("library")}

+ +
+

+ {userProfile.libraryGames?.length} +

+
+ {t("total_play_time", { amount: formatPlayTime() })} +
+ {userProfile.libraryGames?.map((game) => ( + + ))} +
+
+ +
+
+

{t("friends")}

+ +
+ +
-

- {userProfile.libraryGames.length} -

-
- {t("total_play_time", { amount: formatPlayTime() })} -
- {userProfile.libraryGames.map((game) => ( + > - ))} + + +
diff --git a/src/renderer/src/pages/user/user.css.ts b/src/renderer/src/pages/user/user.css.ts index 299aa393..0128ec90 100644 --- a/src/renderer/src/pages/user/user.css.ts +++ b/src/renderer/src/pages/user/user.css.ts @@ -86,7 +86,13 @@ export const profileContent = style({ export const profileGameSection = style({ width: "100%", - height: "100%", + display: "flex", + flexDirection: "column", + gap: `${SPACING_UNIT * 2}px`, +}); + +export const friendsSection = style({ + width: "100%", display: "flex", flexDirection: "column", gap: `${SPACING_UNIT * 2}px`, @@ -94,6 +100,9 @@ export const profileGameSection = style({ export const contentSidebar = style({ width: "100%", + display: "flex", + flexDirection: "column", + gap: `${SPACING_UNIT * 3}px`, "@media": { "(min-width: 768px)": { width: "100%", @@ -116,12 +125,17 @@ export const libraryGameIcon = style({ borderRadius: "4px", }); +export const friendProfileIcon = style({ + height: "100%", +}); + export const feedItem = style({ color: vars.color.body, display: "flex", flexDirection: "row", gap: `${SPACING_UNIT * 2}px`, width: "100%", + overflow: "hidden", height: "72px", transition: "all ease 0.2s", cursor: "pointer", @@ -143,6 +157,22 @@ export const gameListItem = style({ }, }); +export const friendListItem = style({ + color: vars.color.body, + display: "flex", + flexDirection: "row", + gap: `${SPACING_UNIT}px`, + width: "100%", + height: "48px", + transition: "all ease 0.2s", + cursor: "pointer", + zIndex: "1", + overflow: "hidden", + ":hover": { + backgroundColor: "rgba(255, 255, 255, 0.15)", + }, +}); + export const gameInformation = style({ display: "flex", flexDirection: "column", diff --git a/src/types/index.ts b/src/types/index.ts index 71071620..17925ac0 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -269,14 +269,25 @@ export interface UserDetails { profileImageUrl: string | null; } +export interface UserFriend { + id: string; + displayName: string; + profileImageUrl: string | null; +} + +export interface PendingFriendRequest { + AId: string; + BId: string; +} + export interface UserProfile { id: string; displayName: string; - username: string; profileImageUrl: string | null; totalPlayTimeInSeconds: number; - libraryGames: UserGame[]; - recentGames: UserGame[]; + libraryGames: UserGame[] | null; + recentGames: UserGame[] | null; + friends: UserFriend[] | null; } export interface DownloadSource { From 6cc8e8f5fe2d32046c718ae6540a251d6210f3f4 Mon Sep 17 00:00:00 2001 From: Zamitto <167933696+zamitto@users.noreply.github.com> Date: Tue, 9 Jul 2024 16:14:47 -0300 Subject: [PATCH 09/35] feat: pending requests on modal --- .../src/pages/user/user-add-friends-modal.tsx | 167 +++++++++++++----- src/renderer/src/pages/user/user-content.tsx | 20 ++- .../user/user-friend-pending-request.tsx | 81 +++++++++ src/renderer/src/pages/user/user.css.ts | 27 +++ src/types/index.ts | 4 + 5 files changed, 244 insertions(+), 55 deletions(-) create mode 100644 src/renderer/src/pages/user/user-friend-pending-request.tsx diff --git a/src/renderer/src/pages/user/user-add-friends-modal.tsx b/src/renderer/src/pages/user/user-add-friends-modal.tsx index a872abcf..4306936d 100644 --- a/src/renderer/src/pages/user/user-add-friends-modal.tsx +++ b/src/renderer/src/pages/user/user-add-friends-modal.tsx @@ -1,11 +1,11 @@ import { Button, Modal, TextField } from "@renderer/components"; import { PendingFriendRequest } from "@types"; -import * as styles from "./user.css"; import { SPACING_UNIT } from "@renderer/theme.css"; import { useEffect, useState } from "react"; import { useToast, useUserDetails } from "@renderer/hooks"; import { useTranslation } from "react-i18next"; import { useNavigate } from "react-router-dom"; +import { UserFriendPendingRequest } from "./user-friend-pending-request"; export interface UserAddFriendsModalProps { visible: boolean; @@ -26,14 +26,11 @@ export const UserAddFriendsModal = ({ const navigate = useNavigate(); - const { sendFriendRequest } = useUserDetails(); + const { userDetails, sendFriendRequest } = useUserDetails(); const { showSuccessToast, showErrorToast } = useToast(); - const handleAddFriend: React.FormEventHandler = async ( - event - ) => { - event.preventDefault(); + const handleClickAddFriend = () => { setIsAddingFriend(true); sendFriendRequest(friendCode) .then(() => { @@ -47,12 +44,46 @@ export const UserAddFriendsModal = ({ }); }; - useEffect(() => { - setPendingRequests([]); - }); + const handleClickFriend = (userId: string) => { + navigate(userId); + }; - const handleSeeProfileClick = () => { - navigate(`profile/${friendCode}`); + useEffect(() => { + setPendingRequests([ + { + AId: "abcd1234", + ADisplayName: "Punheta Master 123", + AProfileImageUrl: + "https://cdn.discordapp.com/avatars/1239959140785455295/4aff4b901c7a9f5f814b4379b6cfd58a.webp", + BId: "BMmNRmP3", + BDisplayName: "Hydra", + BProfileImageUrl: null, + }, + { + AId: "BMmNRmP3", + ADisplayName: "Hydra", + AProfileImageUrl: null, + BId: "12345678", + BDisplayName: "Deyvis0n", + BProfileImageUrl: null, + }, + ]); + }, []); + + const handleClickSeeProfile = () => { + // navigate(`profile/${friendCode}`); + }; + + const handleClickCancelFriendRequest = (userId: string) => { + console.log(userId); + }; + + const handleClickAcceptFriendRequest = (userId: string) => { + console.log(userId); + }; + + const handleClickRefuseFriendRequest = (userId: string) => { + console.log(userId); }; const resetModal = () => { @@ -71,51 +102,89 @@ export const UserAddFriendsModal = ({ title={t("add_friends")} onClose={cleanFormAndClose} > -
- setFriendCode(e.target.value)} - /> - - - + setFriendCode(e.target.value)} + /> + + +
-
- {pendingRequests.map((request) => { - return ( -

- {request.AId} - {request.BId} -

- ); - })} +
+

Pendentes

+ {pendingRequests.map((request) => { + if (request.AId === userDetails?.id) { + return ( + + ); + } + + return ( + + ); + })} +
diff --git a/src/renderer/src/pages/user/user-content.tsx b/src/renderer/src/pages/user/user-content.tsx index 8e973e7f..9d9b9415 100644 --- a/src/renderer/src/pages/user/user-content.tsx +++ b/src/renderer/src/pages/user/user-content.tsx @@ -17,7 +17,6 @@ import { buildGameDetailsPath, steamUrlBuilder } from "@renderer/helpers"; import { PersonAddIcon, PersonIcon, - PlusCircleIcon, TelescopeIcon, } from "@primer/octicons-react"; import { Button, Link } from "@renderer/components"; @@ -79,6 +78,10 @@ export function UserContent({ setShowEditProfileModal(true); }; + const handleOnClickFriend = (userId: string) => { + console.log(userId); + }; + const handleConfirmSignout = async () => { await signOut(); @@ -359,6 +362,7 @@ export function UserContent({ >
diff --git a/src/renderer/src/pages/user/user-friend-pending-request.tsx b/src/renderer/src/pages/user/user-friend-pending-request.tsx new file mode 100644 index 00000000..40f4bf19 --- /dev/null +++ b/src/renderer/src/pages/user/user-friend-pending-request.tsx @@ -0,0 +1,81 @@ +import { CheckCircleIcon, XCircleIcon } from "@primer/octicons-react"; +import { SPACING_UNIT, vars } from "@renderer/theme.css"; +import * as styles from "./user.css"; +import cn from "classnames"; + +export interface UserFriendPendingRequestProps { + userId: string; + profileImageUrl: string | null; + displayName: string; + isRequestSent: boolean; + onClickCancelRequest: (userId: string) => void; + onClickAcceptRequest: (userId: string) => void; + onClickRefuseRequest: (userId: string) => void; + onClickRequest: (userId: string) => void; +} + +export const UserFriendPendingRequest = ({ + userId, + profileImageUrl, + displayName, + isRequestSent, + onClickCancelRequest, + onClickAcceptRequest, + onClickRefuseRequest, + onClickRequest, +}: UserFriendPendingRequestProps) => { + return ( + + ) : ( + <> + + + + )} + + ); +}; diff --git a/src/renderer/src/pages/user/user.css.ts b/src/renderer/src/pages/user/user.css.ts index 0128ec90..16a4d44f 100644 --- a/src/renderer/src/pages/user/user.css.ts +++ b/src/renderer/src/pages/user/user.css.ts @@ -245,3 +245,30 @@ export const profileBackground = style({ top: "0", borderRadius: "4px", }); + +export const friendRequestItem = style({ + color: vars.color.body, + ":hover": { + backgroundColor: "rgba(255, 255, 255, 0.15)", + }, +}); + +export const acceptRequestButton = style({ + cursor: "pointer", + color: vars.color.body, + width: "28px", + height: "28px", + ":hover": { + color: vars.color.success, + }, +}); + +export const cancelRequestButton = style({ + cursor: "pointer", + color: vars.color.body, + width: "28px", + height: "28px", + ":hover": { + color: vars.color.danger, + }, +}); diff --git a/src/types/index.ts b/src/types/index.ts index 17925ac0..396a3029 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -277,7 +277,11 @@ export interface UserFriend { export interface PendingFriendRequest { AId: string; + ADisplayName: string; + AProfileImageUrl: string | null; BId: string; + BDisplayName: string; + BProfileImageUrl: string | null; } export interface UserProfile { From 007da03837c52d25e77944084d558bd88ec083b1 Mon Sep 17 00:00:00 2001 From: Zamitto <167933696+zamitto@users.noreply.github.com> Date: Wed, 10 Jul 2024 14:29:04 -0300 Subject: [PATCH 10/35] feat: finish ui for modal showing pending requests --- .../src/pages/user/user-add-friends-modal.tsx | 48 ++++++------------- .../user/user-friend-pending-request.tsx | 32 ++++++++----- src/renderer/src/pages/user/user.css.ts | 16 ++++++- src/types/index.ts | 10 ++-- 4 files changed, 52 insertions(+), 54 deletions(-) diff --git a/src/renderer/src/pages/user/user-add-friends-modal.tsx b/src/renderer/src/pages/user/user-add-friends-modal.tsx index 4306936d..cb990e1c 100644 --- a/src/renderer/src/pages/user/user-add-friends-modal.tsx +++ b/src/renderer/src/pages/user/user-add-friends-modal.tsx @@ -26,7 +26,7 @@ export const UserAddFriendsModal = ({ const navigate = useNavigate(); - const { userDetails, sendFriendRequest } = useUserDetails(); + const { sendFriendRequest } = useUserDetails(); const { showSuccessToast, showErrorToast } = useToast(); @@ -51,21 +51,17 @@ export const UserAddFriendsModal = ({ useEffect(() => { setPendingRequests([ { - AId: "abcd1234", - ADisplayName: "Punheta Master 123", - AProfileImageUrl: + userId: "abcd1234", + displayName: "Punheta Master 123", + profileImageUrl: "https://cdn.discordapp.com/avatars/1239959140785455295/4aff4b901c7a9f5f814b4379b6cfd58a.webp", - BId: "BMmNRmP3", - BDisplayName: "Hydra", - BProfileImageUrl: null, + type: "RECEIVED", }, { - AId: "BMmNRmP3", - ADisplayName: "Hydra", - AProfileImageUrl: null, - BId: "12345678", - BDisplayName: "Deyvis0n", - BProfileImageUrl: null, + userId: "12345678", + displayName: "Deyvis0n", + profileImageUrl: null, + type: "SENT", }, ]); }, []); @@ -154,29 +150,13 @@ export const UserAddFriendsModal = ({ >

Pendentes

{pendingRequests.map((request) => { - if (request.AId === userDetails?.id) { - return ( - - ); - } - return ( onClickRequest(userId)} style={{ - display: "flex", - flexDirection: "row", - gap: `${SPACING_UNIT}px`, - alignItems: "center", + padding: "8px", }} > - +
+ {profileImageUrl ? ( + {displayName} + ) : ( + + )} +
{isRequestSent ? ( ) : ( <> diff --git a/src/renderer/src/pages/user/user.css.ts b/src/renderer/src/pages/user/user.css.ts index 16a4d44f..1582af29 100644 --- a/src/renderer/src/pages/user/user.css.ts +++ b/src/renderer/src/pages/user/user.css.ts @@ -35,6 +35,20 @@ export const profileAvatarContainer = style({ zIndex: 1, }); +export const pendingFriendRequestAvatarContainer = style({ + width: "32px", + height: "32px", + borderRadius: "50%", + display: "flex", + justifyContent: "center", + alignItems: "center", + backgroundColor: vars.color.background, + overflow: "hidden", + border: `solid 1px ${vars.color.border}`, + boxShadow: "0px 0px 5px 0px rgba(0, 0, 0, 0.7)", + zIndex: 1, +}); + export const profileAvatarEditContainer = style({ width: "128px", height: "128px", @@ -53,8 +67,6 @@ export const profileAvatarEditContainer = style({ export const profileAvatar = style({ height: "100%", width: "100%", - borderRadius: "50%", - overflow: "hidden", objectFit: "cover", }); diff --git a/src/types/index.ts b/src/types/index.ts index 396a3029..46a556b3 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -276,12 +276,10 @@ export interface UserFriend { } export interface PendingFriendRequest { - AId: string; - ADisplayName: string; - AProfileImageUrl: string | null; - BId: string; - BDisplayName: string; - BProfileImageUrl: string | null; + userId: string; + displayName: string; + profileImageUrl: string | null; + type: "SENT" | "RECEIVED"; } export interface UserProfile { From 0f0a1e98a36306d1307af0efd40c952cc16d5b37 Mon Sep 17 00:00:00 2001 From: Zamitto <167933696+zamitto@users.noreply.github.com> Date: Wed, 10 Jul 2024 17:32:32 -0300 Subject: [PATCH 11/35] feat: ui adjustments --- .../components/sidebar/sidebar-profile.tsx | 3 +- src/renderer/src/pages/user/user-content.tsx | 86 +++++++++++-------- .../user/user-friend-pending-request.tsx | 9 +- src/renderer/src/pages/user/user.css.ts | 24 ++++-- 4 files changed, 70 insertions(+), 52 deletions(-) diff --git a/src/renderer/src/components/sidebar/sidebar-profile.tsx b/src/renderer/src/components/sidebar/sidebar-profile.tsx index 914481b0..432ab9f0 100644 --- a/src/renderer/src/components/sidebar/sidebar-profile.tsx +++ b/src/renderer/src/components/sidebar/sidebar-profile.tsx @@ -40,12 +40,11 @@ export function SidebarProfile() {
{userDetails?.profileImageUrl ? ( {userDetails.displayName} ) : ( - + )}
diff --git a/src/renderer/src/pages/user/user-content.tsx b/src/renderer/src/pages/user/user-content.tsx index 9d9b9415..aca7cc60 100644 --- a/src/renderer/src/pages/user/user-content.tsx +++ b/src/renderer/src/pages/user/user-content.tsx @@ -1,4 +1,4 @@ -import { UserGame, UserProfile } from "@types"; +import { UserFriend, UserGame, UserProfile } from "@types"; import cn from "classnames"; import * as styles from "./user.css"; @@ -344,13 +344,15 @@ export function UserContent({ height: "1px", }} /> - + {isMe && ( + + )}
- + {( + [ + { + id: "", + displayName: "Punheta Master 123123123123123123", + profileImageUrl: + "https://cdn.discordapp.com/avatars/1239959140785455295/4aff4b901c7a9f5f814b4379b6cfd58a.webp", + }, + { + id: "", + displayName: "Hydra Launcher", + profileImageUrl: null, + }, + ] as UserFriend[] + ).map((friend) => { + return ( + +

+ {friend.displayName} +

+ + ); + })}
diff --git a/src/renderer/src/pages/user/user-friend-pending-request.tsx b/src/renderer/src/pages/user/user-friend-pending-request.tsx index c21f41aa..99fcb2f7 100644 --- a/src/renderer/src/pages/user/user-friend-pending-request.tsx +++ b/src/renderer/src/pages/user/user-friend-pending-request.tsx @@ -3,7 +3,6 @@ import { PersonIcon, XCircleIcon, } from "@primer/octicons-react"; -import { SPACING_UNIT } from "@renderer/theme.css"; import * as styles from "./user.css"; import cn from "classnames"; @@ -33,11 +32,8 @@ export const UserFriendPendingRequest = ({ type="button" className={cn(styles.friendListItem, styles.profileContentBox)} onClick={() => onClickRequest(userId)} - style={{ - padding: "8px", - }} > -
+
{profileImageUrl ? ( -

{displayName}

+

{displayName}

{isRequestSent ? "Pedido enviado" : "Pedido recebido"}
{isRequestSent ? ( diff --git a/src/renderer/src/pages/user/user.css.ts b/src/renderer/src/pages/user/user.css.ts index 1582af29..19da3caf 100644 --- a/src/renderer/src/pages/user/user.css.ts +++ b/src/renderer/src/pages/user/user.css.ts @@ -35,9 +35,10 @@ export const profileAvatarContainer = style({ zIndex: 1, }); -export const pendingFriendRequestAvatarContainer = style({ - width: "32px", - height: "32px", +export const friendAvatarContainer = style({ + width: "35px", + minWidth: "35px", + height: "35px", borderRadius: "50%", display: "flex", justifyContent: "center", @@ -46,7 +47,15 @@ export const pendingFriendRequestAvatarContainer = style({ overflow: "hidden", border: `solid 1px ${vars.color.border}`, boxShadow: "0px 0px 5px 0px rgba(0, 0, 0, 0.7)", - zIndex: 1, +}); + +export const friendListDisplayName = style({ + fontWeight: "bold", + fontSize: vars.size.body, + textAlign: "left", + overflow: "hidden", + textOverflow: "ellipsis", + whiteSpace: "nowrap", }); export const profileAvatarEditContainer = style({ @@ -173,13 +182,12 @@ export const friendListItem = style({ color: vars.color.body, display: "flex", flexDirection: "row", - gap: `${SPACING_UNIT}px`, + gap: `${SPACING_UNIT + SPACING_UNIT / 2}px`, width: "100%", - height: "48px", + height: "54px", + padding: "0 8px", transition: "all ease 0.2s", cursor: "pointer", - zIndex: "1", - overflow: "hidden", ":hover": { backgroundColor: "rgba(255, 255, 255, 0.15)", }, From 6ff48605da99f1539082b4b84c6e95725f8dfef2 Mon Sep 17 00:00:00 2001 From: Zamitto <167933696+zamitto@users.noreply.github.com> Date: Wed, 10 Jul 2024 17:51:53 -0300 Subject: [PATCH 12/35] feat: show friends from response --- src/renderer/src/pages/user/user-content.tsx | 139 +++++++++---------- 1 file changed, 64 insertions(+), 75 deletions(-) diff --git a/src/renderer/src/pages/user/user-content.tsx b/src/renderer/src/pages/user/user-content.tsx index aca7cc60..5d0de1c5 100644 --- a/src/renderer/src/pages/user/user-content.tsx +++ b/src/renderer/src/pages/user/user-content.tsx @@ -1,4 +1,4 @@ -import { UserFriend, UserGame, UserProfile } from "@types"; +import { UserGame, UserProfile } from "@types"; import cn from "classnames"; import * as styles from "./user.css"; @@ -79,7 +79,7 @@ export function UserContent({ }; const handleOnClickFriend = (userId: string) => { - console.log(userId); + navigate(`/user/${userId}`); }; const handleConfirmSignout = async () => { @@ -326,86 +326,75 @@ export function UserContent({
-
-
-

{t("friends")}

+ {(isMe || + (userProfile.friends && userProfile.friends.length > 0)) && ( +
+
+

{t("friends")}

+ +
+ {isMe && ( + + )} +
- {isMe && ( - - )} -
- -
- {( - [ - { - id: "", - displayName: "Punheta Master 123123123123123123", - profileImageUrl: - "https://cdn.discordapp.com/avatars/1239959140785455295/4aff4b901c7a9f5f814b4379b6cfd58a.webp", - }, - { - id: "", - displayName: "Hydra Launcher", - profileImageUrl: null, - }, - ] as UserFriend[] - ).map((friend) => { - return ( - - ); - })} +

+ {friend.displayName} +

+ + ); + })} +
-
+ )}
From b3f87d56629403904e1276d20bf994dc7cccf503 Mon Sep 17 00:00:00 2001 From: Zamitto <167933696+zamitto@users.noreply.github.com> Date: Wed, 10 Jul 2024 18:52:08 -0300 Subject: [PATCH 13/35] feat: get friends requests from api --- src/main/events/index.ts | 1 + .../events/profile/get-friend-requests.ts | 16 ++++++++++ src/preload/index.ts | 1 + src/renderer/src/declaration.d.ts | 2 ++ src/renderer/src/hooks/use-user-details.ts | 5 +++ .../src/pages/user/user-add-friends-modal.tsx | 32 ++++--------------- src/renderer/src/pages/user/user-content.tsx | 24 ++++++++++---- src/renderer/src/pages/user/user.tsx | 5 ++- 8 files changed, 54 insertions(+), 32 deletions(-) create mode 100644 src/main/events/profile/get-friend-requests.ts diff --git a/src/main/events/index.ts b/src/main/events/index.ts index 1b500be9..64f95108 100644 --- a/src/main/events/index.ts +++ b/src/main/events/index.ts @@ -43,6 +43,7 @@ import "./auth/sign-out"; import "./auth/open-auth-window"; import "./auth/get-session-hash"; import "./user/get-user"; +import "./profile/get-friend-requests"; import "./profile/get-me"; import "./profile/update-profile"; diff --git a/src/main/events/profile/get-friend-requests.ts b/src/main/events/profile/get-friend-requests.ts new file mode 100644 index 00000000..ba2cf1b5 --- /dev/null +++ b/src/main/events/profile/get-friend-requests.ts @@ -0,0 +1,16 @@ +import { registerEvent } from "../register-event"; +import { HydraApi } from "@main/services"; +import { PendingFriendRequest } from "@types"; + +const getFriendRequests = async ( + _event: Electron.IpcMainInvokeEvent +): Promise => { + try { + const response = await HydraApi.get(`/profile/friend-requests`); + return response.data; + } catch (err) { + return null; + } +}; + +registerEvent("getFriendRequests", getFriendRequests); diff --git a/src/preload/index.ts b/src/preload/index.ts index 0cadbc03..759b0224 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -136,6 +136,7 @@ contextBridge.exposeInMainWorld("electron", { getMe: () => ipcRenderer.invoke("getMe"), updateProfile: (displayName: string, newProfileImagePath: string | null) => ipcRenderer.invoke("updateProfile", displayName, newProfileImagePath), + getFriendRequests: () => ipcRenderer.invoke("getFriendRequests"), /* User */ getUser: (userId: string) => ipcRenderer.invoke("getUser", userId), diff --git a/src/renderer/src/declaration.d.ts b/src/renderer/src/declaration.d.ts index 48fa7aae..0ff9e876 100644 --- a/src/renderer/src/declaration.d.ts +++ b/src/renderer/src/declaration.d.ts @@ -14,6 +14,7 @@ import type { RealDebridUser, DownloadSource, UserProfile, + PendingFriendRequest, } from "@types"; import type { DiskSpace } from "check-disk-space"; @@ -132,6 +133,7 @@ declare global { displayName: string, newProfileImagePath: string | null ) => Promise; + getFriendRequests: () => Promise; } interface Window { diff --git a/src/renderer/src/hooks/use-user-details.ts b/src/renderer/src/hooks/use-user-details.ts index 6495ba27..d39c2578 100644 --- a/src/renderer/src/hooks/use-user-details.ts +++ b/src/renderer/src/hooks/use-user-details.ts @@ -82,6 +82,10 @@ export function useUserDetails() { console.log("sending friend request to", userId); }, []); + const fetchPendingRequests = useCallback(async () => { + return window.electron.getFriendRequests(); + }, []); + return { userDetails, fetchUserDetails, @@ -90,6 +94,7 @@ export function useUserDetails() { updateUserDetails, patchUser, sendFriendRequest, + fetchPendingRequests, profileBackground, }; } diff --git a/src/renderer/src/pages/user/user-add-friends-modal.tsx b/src/renderer/src/pages/user/user-add-friends-modal.tsx index cb990e1c..3037eadb 100644 --- a/src/renderer/src/pages/user/user-add-friends-modal.tsx +++ b/src/renderer/src/pages/user/user-add-friends-modal.tsx @@ -1,7 +1,7 @@ import { Button, Modal, TextField } from "@renderer/components"; import { PendingFriendRequest } from "@types"; import { SPACING_UNIT } from "@renderer/theme.css"; -import { useEffect, useState } from "react"; +import { useState } from "react"; import { useToast, useUserDetails } from "@renderer/hooks"; import { useTranslation } from "react-i18next"; import { useNavigate } from "react-router-dom"; @@ -10,19 +10,18 @@ import { UserFriendPendingRequest } from "./user-friend-pending-request"; export interface UserAddFriendsModalProps { visible: boolean; onClose: () => void; + pendingRequests: PendingFriendRequest[]; } export const UserAddFriendsModal = ({ visible, onClose, + pendingRequests, }: UserAddFriendsModalProps) => { const { t } = useTranslation("user_profile"); const [friendCode, setFriendCode] = useState(""); const [isAddingFriend, setIsAddingFriend] = useState(false); - const [pendingRequests, setPendingRequests] = useState< - PendingFriendRequest[] - >([]); const navigate = useNavigate(); @@ -37,7 +36,7 @@ export const UserAddFriendsModal = ({ showSuccessToast(t("friend_request_sent")); }) .catch(() => { - showErrorToast("falhaaaa"); + showErrorToast("Não foi possível enviar o pedido de amizade"); }) .finally(() => { setIsAddingFriend(false); @@ -45,29 +44,12 @@ export const UserAddFriendsModal = ({ }; const handleClickFriend = (userId: string) => { - navigate(userId); + navigate(`/user/${userId}`); }; - useEffect(() => { - setPendingRequests([ - { - userId: "abcd1234", - displayName: "Punheta Master 123", - profileImageUrl: - "https://cdn.discordapp.com/avatars/1239959140785455295/4aff4b901c7a9f5f814b4379b6cfd58a.webp", - type: "RECEIVED", - }, - { - userId: "12345678", - displayName: "Deyvis0n", - profileImageUrl: null, - type: "SENT", - }, - ]); - }, []); - const handleClickSeeProfile = () => { - // navigate(`profile/${friendCode}`); + onClose(); + navigate(`/user/${friendCode}`); }; const handleClickCancelFriendRequest = (userId: string) => { diff --git a/src/renderer/src/pages/user/user-content.tsx b/src/renderer/src/pages/user/user-content.tsx index 5d0de1c5..7944f0e5 100644 --- a/src/renderer/src/pages/user/user-content.tsx +++ b/src/renderer/src/pages/user/user-content.tsx @@ -1,9 +1,8 @@ -import { UserGame, UserProfile } from "@types"; +import { PendingFriendRequest, UserGame, UserProfile } from "@types"; import cn from "classnames"; - import * as styles from "./user.css"; import { SPACING_UNIT, vars } from "@renderer/theme.css"; -import { useMemo, useState } from "react"; +import { useEffect, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import SteamLogo from "@renderer/assets/steam-logo.svg?react"; import { @@ -90,8 +89,18 @@ export function UserContent({ navigate("/"); }; + const [pendingRequests, setPendingRequests] = useState< + PendingFriendRequest[] + >([]); + const isMe = userDetails?.id == userProfile.id; + useEffect(() => { + window.electron.getFriendRequests().then((friendsRequests) => { + setPendingRequests(friendsRequests ?? []); + }); + }, [isMe]); + const profileContentBoxBackground = useMemo(() => { if (profileBackground) return profileBackground; /* TODO: Render background colors for other users */ @@ -114,6 +123,7 @@ export function UserContent({ /> setShowAddFriendsModal(false)} /> @@ -231,9 +241,11 @@ export function UserContent({

{t("no_recent_activity_title")}

-

- {t("no_recent_activity_description")} -

+ {isMe && ( +

+ {t("no_recent_activity_description")} +

+ )} ) : (
{ const [userProfile, setUserProfile] = useState(); const navigate = useNavigate(); + const { showErrorToast } = useToast(); + const dispatch = useAppDispatch(); const getUserProfile = useCallback(() => { @@ -22,6 +24,7 @@ export const User = () => { dispatch(setHeaderTitle(userProfile.displayName)); setUserProfile(userProfile); } else { + showErrorToast("Usuário não encontrado"); navigate(-1); } }); From ef0699dbea91a7004c81a5eadfb834b224f9eb5d Mon Sep 17 00:00:00 2001 From: Zamitto <167933696+zamitto@users.noreply.github.com> Date: Wed, 10 Jul 2024 19:52:57 -0300 Subject: [PATCH 14/35] feat: refactor friends requests --- src/main/events/index.ts | 1 + .../events/profile/get-friend-requests.ts | 4 ++-- .../events/profile/update-friend-request.ts | 19 ++++++++++++++++++ src/preload/index.ts | 3 +++ src/renderer/src/declaration.d.ts | 9 +++++++-- .../src/features/user-details-slice.ts | 12 +++++++++-- src/renderer/src/hooks/use-user-details.ts | 20 ++++++++++++------- .../src/pages/user/user-add-friends-modal.tsx | 16 ++++++++------- src/renderer/src/pages/user/user-content.tsx | 14 ++++--------- ...ng-request.tsx => user-friend-request.tsx} | 6 +++--- src/types/index.ts | 4 +++- 11 files changed, 74 insertions(+), 34 deletions(-) create mode 100644 src/main/events/profile/update-friend-request.ts rename src/renderer/src/pages/user/{user-friend-pending-request.tsx => user-friend-request.tsx} (94%) diff --git a/src/main/events/index.ts b/src/main/events/index.ts index 64f95108..ab82eefd 100644 --- a/src/main/events/index.ts +++ b/src/main/events/index.ts @@ -45,6 +45,7 @@ import "./auth/get-session-hash"; import "./user/get-user"; import "./profile/get-friend-requests"; import "./profile/get-me"; +import "./profile/update-friend-request"; import "./profile/update-profile"; ipcMain.handle("ping", () => "pong"); diff --git a/src/main/events/profile/get-friend-requests.ts b/src/main/events/profile/get-friend-requests.ts index ba2cf1b5..0e75efba 100644 --- a/src/main/events/profile/get-friend-requests.ts +++ b/src/main/events/profile/get-friend-requests.ts @@ -1,10 +1,10 @@ import { registerEvent } from "../register-event"; import { HydraApi } from "@main/services"; -import { PendingFriendRequest } from "@types"; +import { FriendRequest } from "@types"; const getFriendRequests = async ( _event: Electron.IpcMainInvokeEvent -): Promise => { +): Promise => { try { const response = await HydraApi.get(`/profile/friend-requests`); return response.data; diff --git a/src/main/events/profile/update-friend-request.ts b/src/main/events/profile/update-friend-request.ts new file mode 100644 index 00000000..24929544 --- /dev/null +++ b/src/main/events/profile/update-friend-request.ts @@ -0,0 +1,19 @@ +import { registerEvent } from "../register-event"; +import { HydraApi } from "@main/services"; +import { FriendRequestAction } from "@types"; + +const updateFriendRequest = async ( + _event: Electron.IpcMainInvokeEvent, + userId: string, + action: FriendRequestAction +) => { + if (action == "CANCEL") { + return HydraApi.delete(`/profile/friend-requests/${userId}`); + } + + return HydraApi.patch(`/profile/friend-requests/${userId}`, { + requestState: action, + }); +}; + +registerEvent("updateFriendRequest", updateFriendRequest); diff --git a/src/preload/index.ts b/src/preload/index.ts index 759b0224..26601ebd 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -9,6 +9,7 @@ import type { AppUpdaterEvent, StartGameDownloadPayload, GameRunning, + FriendRequestAction, } from "@types"; contextBridge.exposeInMainWorld("electron", { @@ -137,6 +138,8 @@ contextBridge.exposeInMainWorld("electron", { updateProfile: (displayName: string, newProfileImagePath: string | null) => ipcRenderer.invoke("updateProfile", displayName, newProfileImagePath), getFriendRequests: () => ipcRenderer.invoke("getFriendRequests"), + updateFriendRequest: (userId: string, action: FriendRequestAction) => + ipcRenderer.invoke("updateFriendRequest", userId, action), /* User */ getUser: (userId: string) => ipcRenderer.invoke("getUser", userId), diff --git a/src/renderer/src/declaration.d.ts b/src/renderer/src/declaration.d.ts index 0ff9e876..747f8be4 100644 --- a/src/renderer/src/declaration.d.ts +++ b/src/renderer/src/declaration.d.ts @@ -14,7 +14,8 @@ import type { RealDebridUser, DownloadSource, UserProfile, - PendingFriendRequest, + FriendRequest, + FriendRequestAction, } from "@types"; import type { DiskSpace } from "check-disk-space"; @@ -133,7 +134,11 @@ declare global { displayName: string, newProfileImagePath: string | null ) => Promise; - getFriendRequests: () => Promise; + getFriendRequests: () => Promise; + updateFriendRequest: ( + userId: string, + action: FriendRequestAction + ) => Promise; } interface Window { diff --git a/src/renderer/src/features/user-details-slice.ts b/src/renderer/src/features/user-details-slice.ts index 0cc395b0..1912c810 100644 --- a/src/renderer/src/features/user-details-slice.ts +++ b/src/renderer/src/features/user-details-slice.ts @@ -1,14 +1,16 @@ import { PayloadAction, createSlice } from "@reduxjs/toolkit"; -import type { UserDetails } from "@types"; +import type { FriendRequest, UserDetails } from "@types"; export interface UserDetailsState { userDetails: UserDetails | null; profileBackground: null | string; + friendRequests: FriendRequest[] | null; } const initialState: UserDetailsState = { userDetails: null, profileBackground: null, + friendRequests: null, }; export const userDetailsSlice = createSlice({ @@ -21,8 +23,14 @@ export const userDetailsSlice = createSlice({ setProfileBackground: (state, action: PayloadAction) => { state.profileBackground = action.payload; }, + setFriendRequests: ( + state, + action: PayloadAction + ) => { + state.friendRequests = action.payload; + }, }, }); -export const { setUserDetails, setProfileBackground } = +export const { setUserDetails, setProfileBackground, setFriendRequests } = userDetailsSlice.actions; diff --git a/src/renderer/src/hooks/use-user-details.ts b/src/renderer/src/hooks/use-user-details.ts index d39c2578..bdbfcf2c 100644 --- a/src/renderer/src/hooks/use-user-details.ts +++ b/src/renderer/src/hooks/use-user-details.ts @@ -2,14 +2,18 @@ import { useCallback } from "react"; import { average } from "color.js"; import { useAppDispatch, useAppSelector } from "./redux"; -import { setProfileBackground, setUserDetails } from "@renderer/features"; +import { + setProfileBackground, + setUserDetails, + setFriendRequests, +} from "@renderer/features"; import { darkenColor } from "@renderer/helpers"; import { UserDetails } from "@types"; export function useUserDetails() { const dispatch = useAppDispatch(); - const { userDetails, profileBackground } = useAppSelector( + const { userDetails, profileBackground, friendRequests } = useAppSelector( (state) => state.userDetails ); @@ -82,19 +86,21 @@ export function useUserDetails() { console.log("sending friend request to", userId); }, []); - const fetchPendingRequests = useCallback(async () => { - return window.electron.getFriendRequests(); - }, []); + const updateFriendRequests = useCallback(async () => { + const friendRequests = await window.electron.getFriendRequests(); + dispatch(setFriendRequests(friendRequests)); + }, [dispatch]); return { userDetails, + profileBackground, + friendRequests, fetchUserDetails, signOut, clearUserDetails, updateUserDetails, patchUser, sendFriendRequest, - fetchPendingRequests, - profileBackground, + updateFriendRequests, }; } diff --git a/src/renderer/src/pages/user/user-add-friends-modal.tsx b/src/renderer/src/pages/user/user-add-friends-modal.tsx index 3037eadb..c5a2d9ec 100644 --- a/src/renderer/src/pages/user/user-add-friends-modal.tsx +++ b/src/renderer/src/pages/user/user-add-friends-modal.tsx @@ -1,22 +1,19 @@ import { Button, Modal, TextField } from "@renderer/components"; -import { PendingFriendRequest } from "@types"; import { SPACING_UNIT } from "@renderer/theme.css"; import { useState } from "react"; import { useToast, useUserDetails } from "@renderer/hooks"; import { useTranslation } from "react-i18next"; import { useNavigate } from "react-router-dom"; -import { UserFriendPendingRequest } from "./user-friend-pending-request"; +import { UserFriendRequest } from "./user-friend-request"; export interface UserAddFriendsModalProps { visible: boolean; onClose: () => void; - pendingRequests: PendingFriendRequest[]; } export const UserAddFriendsModal = ({ visible, onClose, - pendingRequests, }: UserAddFriendsModalProps) => { const { t } = useTranslation("user_profile"); @@ -25,7 +22,8 @@ export const UserAddFriendsModal = ({ const navigate = useNavigate(); - const { sendFriendRequest } = useUserDetails(); + const { sendFriendRequest, updateFriendRequests, friendRequests } = + useUserDetails(); const { showSuccessToast, showErrorToast } = useToast(); @@ -33,6 +31,7 @@ export const UserAddFriendsModal = ({ setIsAddingFriend(true); sendFriendRequest(friendCode) .then(() => { + updateFriendRequests(); showSuccessToast(t("friend_request_sent")); }) .catch(() => { @@ -54,14 +53,17 @@ export const UserAddFriendsModal = ({ const handleClickCancelFriendRequest = (userId: string) => { console.log(userId); + updateFriendRequests(); }; const handleClickAcceptFriendRequest = (userId: string) => { console.log(userId); + updateFriendRequests(); }; const handleClickRefuseFriendRequest = (userId: string) => { console.log(userId); + updateFriendRequests(); }; const resetModal = () => { @@ -131,9 +133,9 @@ export const UserAddFriendsModal = ({ }} >

Pendentes

- {pendingRequests.map((request) => { + {friendRequests?.map((request) => { return ( - ([]); - const isMe = userDetails?.id == userProfile.id; useEffect(() => { - window.electron.getFriendRequests().then((friendsRequests) => { - setPendingRequests(friendsRequests ?? []); - }); + if (isMe) updateFriendRequests(); }, [isMe]); const profileContentBoxBackground = useMemo(() => { @@ -123,7 +118,6 @@ export function UserContent({ /> setShowAddFriendsModal(false)} /> diff --git a/src/renderer/src/pages/user/user-friend-pending-request.tsx b/src/renderer/src/pages/user/user-friend-request.tsx similarity index 94% rename from src/renderer/src/pages/user/user-friend-pending-request.tsx rename to src/renderer/src/pages/user/user-friend-request.tsx index 99fcb2f7..1348cc2b 100644 --- a/src/renderer/src/pages/user/user-friend-pending-request.tsx +++ b/src/renderer/src/pages/user/user-friend-request.tsx @@ -6,7 +6,7 @@ import { import * as styles from "./user.css"; import cn from "classnames"; -export interface UserFriendPendingRequestProps { +export interface UserFriendRequestProps { userId: string; profileImageUrl: string | null; displayName: string; @@ -17,7 +17,7 @@ export interface UserFriendPendingRequestProps { onClickRequest: (userId: string) => void; } -export const UserFriendPendingRequest = ({ +export const UserFriendRequest = ({ userId, profileImageUrl, displayName, @@ -26,7 +26,7 @@ export const UserFriendPendingRequest = ({ onClickAcceptRequest, onClickRefuseRequest, onClickRequest, -}: UserFriendPendingRequestProps) => { +}: UserFriendRequestProps) => { return ( @@ -67,13 +67,13 @@ export const UserFriendRequest = ({ <> diff --git a/src/types/index.ts b/src/types/index.ts index 6768a840..3046a727 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -278,7 +278,7 @@ export interface UserFriend { } export interface FriendRequest { - userId: string; + id: string; displayName: string; profileImageUrl: string | null; type: "SENT" | "RECEIVED"; From 6f70b529a224510fab91064d029dd9b651ce1d30 Mon Sep 17 00:00:00 2001 From: Zamitto <167933696+zamitto@users.noreply.github.com> Date: Wed, 10 Jul 2024 21:35:39 -0300 Subject: [PATCH 16/35] feat: refactor hydra api --- .../events/profile/get-friend-requests.ts | 7 +------ src/main/events/profile/get-me.ts | 4 +--- src/main/events/profile/update-profile.ts | 6 +++--- src/main/events/user/get-user.ts | 3 +-- src/main/services/hydra-api.ts | 5 +++++ src/main/services/library-sync/create-game.ts | 6 +----- .../library-sync/merge-with-remote-games.ts | 2 +- src/renderer/src/hooks/use-user-details.ts | 18 ++++++++++-------- .../src/pages/user/user-add-friends-modal.tsx | 19 ++++--------------- 9 files changed, 27 insertions(+), 43 deletions(-) diff --git a/src/main/events/profile/get-friend-requests.ts b/src/main/events/profile/get-friend-requests.ts index 0e75efba..2c04b865 100644 --- a/src/main/events/profile/get-friend-requests.ts +++ b/src/main/events/profile/get-friend-requests.ts @@ -5,12 +5,7 @@ import { FriendRequest } from "@types"; const getFriendRequests = async ( _event: Electron.IpcMainInvokeEvent ): Promise => { - try { - const response = await HydraApi.get(`/profile/friend-requests`); - return response.data; - } catch (err) { - return null; - } + return HydraApi.get(`/profile/friend-requests`).catch(() => null); }; registerEvent("getFriendRequests", getFriendRequests); diff --git a/src/main/events/profile/get-me.ts b/src/main/events/profile/get-me.ts index 83463680..6e451134 100644 --- a/src/main/events/profile/get-me.ts +++ b/src/main/events/profile/get-me.ts @@ -9,9 +9,7 @@ const getMe = async ( _event: Electron.IpcMainInvokeEvent ): Promise => { return HydraApi.get(`/profile/me`) - .then((response) => { - const me = response.data; - + .then((me) => { userAuthRepository.upsert( { id: 1, diff --git a/src/main/events/profile/update-profile.ts b/src/main/events/profile/update-profile.ts index fe79d345..e6671992 100644 --- a/src/main/events/profile/update-profile.ts +++ b/src/main/events/profile/update-profile.ts @@ -29,7 +29,7 @@ const updateProfile = async ( ) => { if (!newProfileImagePath) { return patchUserProfile(displayName).then( - (response) => response.data as UserProfile + (response) => response as UserProfile ); } @@ -42,7 +42,7 @@ const updateProfile = async ( imageLength: fileSizeInBytes, }) .then(async (preSignedResponse) => { - const { presignedUrl, profileImageUrl } = preSignedResponse.data; + const { presignedUrl, profileImageUrl } = preSignedResponse; const mimeType = await fileTypeFromFile(newProfileImagePath); @@ -56,7 +56,7 @@ const updateProfile = async ( .catch(() => undefined); return patchUserProfile(displayName, profileImageUrl).then( - (response) => response.data as UserProfile + (response) => response as UserProfile ); }; diff --git a/src/main/events/user/get-user.ts b/src/main/events/user/get-user.ts index 596df084..7b4c0aa8 100644 --- a/src/main/events/user/get-user.ts +++ b/src/main/events/user/get-user.ts @@ -10,8 +10,7 @@ const getUser = async ( userId: string ): Promise => { try { - const response = await HydraApi.get(`/user/${userId}`); - const profile = response.data; + const profile = await HydraApi.get(`/user/${userId}`); const recentGames = await Promise.all( profile.recentGames.map(async (game) => { diff --git a/src/main/services/hydra-api.ts b/src/main/services/hydra-api.ts index 1abae98c..f74403ce 100644 --- a/src/main/services/hydra-api.ts +++ b/src/main/services/hydra-api.ts @@ -190,6 +190,7 @@ export class HydraApi { await this.revalidateAccessTokenIfExpired(); return this.instance .get(url, this.getAxiosConfig()) + .then((response) => response.data) .catch(this.handleUnauthorizedError); } @@ -199,6 +200,7 @@ export class HydraApi { await this.revalidateAccessTokenIfExpired(); return this.instance .post(url, data, this.getAxiosConfig()) + .then((response) => response.data) .catch(this.handleUnauthorizedError); } @@ -208,6 +210,7 @@ export class HydraApi { await this.revalidateAccessTokenIfExpired(); return this.instance .put(url, data, this.getAxiosConfig()) + .then((response) => response.data) .catch(this.handleUnauthorizedError); } @@ -217,6 +220,7 @@ export class HydraApi { await this.revalidateAccessTokenIfExpired(); return this.instance .patch(url, data, this.getAxiosConfig()) + .then((response) => response.data) .catch(this.handleUnauthorizedError); } @@ -226,6 +230,7 @@ export class HydraApi { await this.revalidateAccessTokenIfExpired(); return this.instance .delete(url, this.getAxiosConfig()) + .then((response) => response.data) .catch(this.handleUnauthorizedError); } } diff --git a/src/main/services/library-sync/create-game.ts b/src/main/services/library-sync/create-game.ts index c0e8b1f8..b66a1897 100644 --- a/src/main/services/library-sync/create-game.ts +++ b/src/main/services/library-sync/create-game.ts @@ -10,11 +10,7 @@ export const createGame = async (game: Game) => { lastTimePlayed: game.lastTimePlayed, }) .then((response) => { - const { - id: remoteId, - playTimeInMilliseconds, - lastTimePlayed, - } = response.data; + const { id: remoteId, playTimeInMilliseconds, lastTimePlayed } = response; gameRepository.update( { objectID: game.objectID }, diff --git a/src/main/services/library-sync/merge-with-remote-games.ts b/src/main/services/library-sync/merge-with-remote-games.ts index 2162ea58..2a6b5bb5 100644 --- a/src/main/services/library-sync/merge-with-remote-games.ts +++ b/src/main/services/library-sync/merge-with-remote-games.ts @@ -6,7 +6,7 @@ import { getSteamAppAsset } from "@main/helpers"; export const mergeWithRemoteGames = async () => { return HydraApi.get("/games") .then(async (response) => { - for (const game of response.data) { + for (const game of response) { const localGame = await gameRepository.findOne({ where: { objectID: game.objectId, diff --git a/src/renderer/src/hooks/use-user-details.ts b/src/renderer/src/hooks/use-user-details.ts index ecf66276..ceb2df3f 100644 --- a/src/renderer/src/hooks/use-user-details.ts +++ b/src/renderer/src/hooks/use-user-details.ts @@ -82,23 +82,25 @@ export function useUserDetails() { [updateUserDetails] ); - const sendFriendRequest = useCallback(async (userId: string) => { - return window.electron.sendFriendRequest(userId); - }, []); - const updateFriendRequests = useCallback(async () => { const friendRequests = await window.electron.getFriendRequests(); dispatch(setFriendRequests(friendRequests)); }, [dispatch]); + const sendFriendRequest = useCallback( + async (userId: string) => { + return window.electron + .sendFriendRequest(userId) + .then(() => updateFriendRequests()); + }, + [updateFriendRequests] + ); + const updateFriendRequestState = useCallback( async (userId: string, action: FriendRequestAction) => { return window.electron .updateFriendRequest(userId, action) - .then(() => {}) - .catch(() => { - console.log("falha no updateFriendsRequestState"); - }); + .then(() => updateFriendRequests()); }, [updateFriendRequests] ); diff --git a/src/renderer/src/pages/user/user-add-friends-modal.tsx b/src/renderer/src/pages/user/user-add-friends-modal.tsx index a5462c5b..b61f293c 100644 --- a/src/renderer/src/pages/user/user-add-friends-modal.tsx +++ b/src/renderer/src/pages/user/user-add-friends-modal.tsx @@ -22,12 +22,8 @@ export const UserAddFriendsModal = ({ const navigate = useNavigate(); - const { - sendFriendRequest, - updateFriendRequests, - updateFriendRequestState, - friendRequests, - } = useUserDetails(); + const { sendFriendRequest, updateFriendRequestState, friendRequests } = + useUserDetails(); const { showSuccessToast, showErrorToast } = useToast(); @@ -35,7 +31,6 @@ export const UserAddFriendsModal = ({ setIsAddingFriend(true); sendFriendRequest(friendCode) .then(() => { - updateFriendRequests(); showSuccessToast(t("friend_request_sent")); }) .catch(() => { @@ -47,13 +42,11 @@ export const UserAddFriendsModal = ({ }; const handleClickFriend = (userId: string) => { - console.log("click friend"); - onClose(); - navigate(`/user/${userId}`); + //onClose(); + //navigate(`/user/${userId}`); }; const handleClickSeeProfile = () => { - console.log("click see profile"); onClose(); navigate(`/user/${friendCode}`); }; @@ -62,8 +55,6 @@ export const UserAddFriendsModal = ({ event: React.MouseEvent, userId: string ) => { - console.log("cancel"); - event.preventDefault(); updateFriendRequestState(userId, "CANCEL") .then(() => { console.log("sucesso"); @@ -77,8 +68,6 @@ export const UserAddFriendsModal = ({ event: React.MouseEvent, userId: string ) => { - console.log("accept friend request"); - event.preventDefault(); updateFriendRequestState(userId, "ACCEPTED").catch(() => { showErrorToast("Falha ao aceitar convite"); }); From 22b66149b37632f819ea7f41ebc3c66ed779fec9 Mon Sep 17 00:00:00 2001 From: Zamitto <167933696+zamitto@users.noreply.github.com> Date: Wed, 10 Jul 2024 22:04:28 -0300 Subject: [PATCH 17/35] fix: buttons on friend request item --- .../src/pages/user/user-add-friends-modal.tsx | 172 ++++++++---------- src/renderer/src/pages/user/user-content.tsx | 2 +- .../src/pages/user/user-friend-request.tsx | 101 +++++----- src/renderer/src/pages/user/user.css.ts | 22 ++- 4 files changed, 143 insertions(+), 154 deletions(-) diff --git a/src/renderer/src/pages/user/user-add-friends-modal.tsx b/src/renderer/src/pages/user/user-add-friends-modal.tsx index b61f293c..d980df43 100644 --- a/src/renderer/src/pages/user/user-add-friends-modal.tsx +++ b/src/renderer/src/pages/user/user-add-friends-modal.tsx @@ -25,13 +25,13 @@ export const UserAddFriendsModal = ({ const { sendFriendRequest, updateFriendRequestState, friendRequests } = useUserDetails(); - const { showSuccessToast, showErrorToast } = useToast(); + const { showErrorToast } = useToast(); const handleClickAddFriend = () => { setIsAddingFriend(true); sendFriendRequest(friendCode) .then(() => { - showSuccessToast(t("friend_request_sent")); + setFriendCode(""); }) .catch(() => { showErrorToast("Não foi possível enviar o pedido de amizade"); @@ -41,133 +41,109 @@ export const UserAddFriendsModal = ({ }); }; - const handleClickFriend = (userId: string) => { - //onClose(); - //navigate(`/user/${userId}`); + const handleClickRequest = (userId: string) => { + resetAndClose(); + navigate(`/user/${userId}`); }; const handleClickSeeProfile = () => { - onClose(); + resetAndClose(); navigate(`/user/${friendCode}`); }; - const handleClickCancelFriendRequest = ( - event: React.MouseEvent, - userId: string - ) => { - updateFriendRequestState(userId, "CANCEL") - .then(() => { - console.log("sucesso"); - }) - .catch(() => { - showErrorToast("Falha ao cancelar convite"); - }); + const handleClickCancelFriendRequest = (userId: string) => { + updateFriendRequestState(userId, "CANCEL").catch(() => { + showErrorToast("Falha ao cancelar convite"); + }); }; - const handleClickAcceptFriendRequest = ( - event: React.MouseEvent, - userId: string - ) => { + const handleClickAcceptFriendRequest = (userId: string) => { updateFriendRequestState(userId, "ACCEPTED").catch(() => { showErrorToast("Falha ao aceitar convite"); }); }; - const handleClickRefuseFriendRequest = ( - event: React.MouseEvent, - userId: string - ) => { - event.preventDefault(); + const handleClickRefuseFriendRequest = (userId: string) => { updateFriendRequestState(userId, "REFUSED").catch(() => { showErrorToast("Falha ao recusar convite"); }); }; - const resetModal = () => { + const resetAndClose = () => { setFriendCode(""); - }; - - const cleanFormAndClose = () => { - resetModal(); onClose(); }; return ( - <> - +
+ setFriendCode(e.target.value)} + /> + + +
+ +
-
- setFriendCode(e.target.value)} - /> - - -
- -
-

Pendentes

- {friendRequests?.map((request) => { - return ( - - ); - })} -
+

Pendentes

+ {friendRequests?.map((request) => { + return ( + + ); + })}
- - +
+
); }; diff --git a/src/renderer/src/pages/user/user-content.tsx b/src/renderer/src/pages/user/user-content.tsx index 2915a82a..d8019159 100644 --- a/src/renderer/src/pages/user/user-content.tsx +++ b/src/renderer/src/pages/user/user-content.tsx @@ -375,7 +375,7 @@ export function UserContent({
- {isRequestSent ? ( - - ) : ( - <> - +

{displayName}

+ {isRequestSent ? "Pedido enviado" : "Pedido recebido"} + + + +
+ {isRequestSent ? ( - - )} - + ) : ( + <> + + + + )} +
+ ); }; diff --git a/src/renderer/src/pages/user/user.css.ts b/src/renderer/src/pages/user/user.css.ts index 19da3caf..8a56bd7d 100644 --- a/src/renderer/src/pages/user/user.css.ts +++ b/src/renderer/src/pages/user/user.css.ts @@ -178,21 +178,29 @@ export const gameListItem = style({ }, }); -export const friendListItem = style({ - color: vars.color.body, - display: "flex", - flexDirection: "row", - gap: `${SPACING_UNIT + SPACING_UNIT / 2}px`, +export const friendListContainer = style({ width: "100%", height: "54px", - padding: "0 8px", transition: "all ease 0.2s", - cursor: "pointer", + position: "relative", ":hover": { backgroundColor: "rgba(255, 255, 255, 0.15)", }, }); +export const friendListButton = style({ + display: "flex", + alignItems: "center", + position: "absolute", + cursor: "pointer", + height: "100%", + width: "100%", + flexDirection: "row", + color: vars.color.body, + gap: `${SPACING_UNIT + SPACING_UNIT / 2}px`, + padding: "0 8px", +}); + export const gameInformation = style({ display: "flex", flexDirection: "column", From cb93fbcb720db55d1daa23559ced76069d86bb8d Mon Sep 17 00:00:00 2001 From: Zamitto <167933696+zamitto@users.noreply.github.com> Date: Wed, 10 Jul 2024 22:13:42 -0300 Subject: [PATCH 18/35] feat: add buttons gap --- src/renderer/src/pages/user/user-friend-request.tsx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/renderer/src/pages/user/user-friend-request.tsx b/src/renderer/src/pages/user/user-friend-request.tsx index aebff56e..e37004fc 100644 --- a/src/renderer/src/pages/user/user-friend-request.tsx +++ b/src/renderer/src/pages/user/user-friend-request.tsx @@ -5,6 +5,7 @@ import { } from "@primer/octicons-react"; import * as styles from "./user.css"; import cn from "classnames"; +import { SPACING_UNIT } from "@renderer/theme.css"; export interface UserFriendRequestProps { userId: string; @@ -59,7 +60,14 @@ export const UserFriendRequest = ({ -
+
{isRequestSent ? ( + + {userDetails && !gameRunning && ( +
+ +
+ )} +
); } diff --git a/src/renderer/src/pages/user/user-content.tsx b/src/renderer/src/pages/user/user-content.tsx index d8019159..503561a9 100644 --- a/src/renderer/src/pages/user/user-content.tsx +++ b/src/renderer/src/pages/user/user-content.tsx @@ -355,10 +355,11 @@ export function UserContent({ {isMe && ( )}
diff --git a/yarn.lock b/yarn.lock index 00172038..e6b91b9e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2433,6 +2433,13 @@ modern-ahocorasick "^1.0.0" picocolors "^1.0.0" +"@vanilla-extract/dynamic@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@vanilla-extract/dynamic/-/dynamic-2.1.1.tgz#bc93a577b127a7dcb6f254973d13a863029a7faf" + integrity sha512-iqf736036ujEIKsIq28UsBEMaLC2vR2DhwKyrG3NDb/fRy9qL9FKl1TqTtBV4daU30Uh3saeik4vRzN8bzQMbw== + dependencies: + "@vanilla-extract/private" "^1.0.5" + "@vanilla-extract/integration@^7.1.3": version "7.1.4" resolved "https://registry.npmjs.org/@vanilla-extract/integration/-/integration-7.1.4.tgz" @@ -2456,6 +2463,11 @@ resolved "https://registry.npmjs.org/@vanilla-extract/private/-/private-1.0.4.tgz" integrity sha512-8FGD6AejeC/nXcblgNCM5rnZb9KXa4WNkR03HCWtdJBpANjTgjHEglNLFnhuvdQ78tC6afaxBPI+g7F2NX3tgg== +"@vanilla-extract/private@^1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@vanilla-extract/private/-/private-1.0.5.tgz#8c08ac4851f4cc89a3dcdb858d8938e69b1481c4" + integrity sha512-6YXeOEKYTA3UV+RC8DeAjFk+/okoNz/h88R+McnzA2zpaVqTR/Ep+vszkWYlGBcMNO7vEkqbq5nT/JMMvhi+tw== + "@vanilla-extract/recipes@^0.5.2": version "0.5.2" resolved "https://registry.npmjs.org/@vanilla-extract/recipes/-/recipes-0.5.2.tgz" From 5aec973882b9120e4daf9785a29dec02b0a21832 Mon Sep 17 00:00:00 2001 From: Zamitto <167933696+zamitto@users.noreply.github.com> Date: Tue, 16 Jul 2024 12:39:16 -0300 Subject: [PATCH 22/35] feat: show friend request modal when click on sidebar --- src/renderer/src/app.tsx | 19 +++++++- .../components/sidebar/sidebar-profile.css.ts | 2 +- .../components/sidebar/sidebar-profile.tsx | 15 +++--- .../src/features/user-details-slice.ts | 13 ++++- src/renderer/src/hooks/use-user-details.ts | 22 +++++++-- .../user-friend-request-modal.tsx} | 2 +- .../user-friend-request.tsx | 2 +- src/renderer/src/pages/user/user-content.tsx | 47 ++++++++----------- src/renderer/src/pages/user/user.css.ts | 11 +++++ 9 files changed, 91 insertions(+), 42 deletions(-) rename src/renderer/src/pages/{user/user-add-friends-modal.tsx => shared-modals/user-friend-request-modal.tsx} (99%) rename src/renderer/src/pages/{user => shared-modals}/user-friend-request.tsx (98%) diff --git a/src/renderer/src/app.tsx b/src/renderer/src/app.tsx index afce9622..a91e8881 100644 --- a/src/renderer/src/app.tsx +++ b/src/renderer/src/app.tsx @@ -25,6 +25,7 @@ import { setGameRunning, } from "@renderer/features"; import { useTranslation } from "react-i18next"; +import { UserFriendRequestModal } from "./pages/shared-modals/user-friend-request-modal"; export interface AppProps { children: React.ReactNode; @@ -38,6 +39,13 @@ export function App() { const { clearDownload, setLastPacket } = useDownload(); + const { + userDetails, + showFriendRequestsModal, + setShowFriendRequestModal, + updateFriendRequests, + } = useUserDetails(); + const { fetchUserDetails, updateUserDetails, clearUserDetails } = useUserDetails(); @@ -94,7 +102,10 @@ export function App() { } fetchUserDetails().then((response) => { - if (response) updateUserDetails(response); + if (response) { + updateUserDetails(response); + updateFriendRequests(); + } }); }, [fetchUserDetails, updateUserDetails, dispatch]); @@ -102,6 +113,7 @@ export function App() { fetchUserDetails().then((response) => { if (response) { updateUserDetails(response); + updateFriendRequests(); showSuccessToast(t("successfully_signed_in")); } }); @@ -206,6 +218,11 @@ export function App() { onClose={handleToastClose} /> + setShowFriendRequestModal(false)} + /> +
diff --git a/src/renderer/src/components/sidebar/sidebar-profile.css.ts b/src/renderer/src/components/sidebar/sidebar-profile.css.ts index 9fcc64c2..ba29c850 100644 --- a/src/renderer/src/components/sidebar/sidebar-profile.css.ts +++ b/src/renderer/src/components/sidebar/sidebar-profile.css.ts @@ -93,6 +93,6 @@ export const friendRequestButton = style({ width: "40px", height: "40px", ":hover": { - color: vars.color.body, + color: vars.color.muted, }, }); diff --git a/src/renderer/src/components/sidebar/sidebar-profile.tsx b/src/renderer/src/components/sidebar/sidebar-profile.tsx index d4414dec..33779c0f 100644 --- a/src/renderer/src/components/sidebar/sidebar-profile.tsx +++ b/src/renderer/src/components/sidebar/sidebar-profile.tsx @@ -12,7 +12,12 @@ export function SidebarProfile() { const { t } = useTranslation("sidebar"); - const { userDetails, profileBackground } = useUserDetails(); + const { + userDetails, + profileBackground, + friendRequests, + setShowFriendRequestModal, + } = useUserDetails(); const { gameRunning } = useAppSelector((state) => state.gameRunning); @@ -77,17 +82,15 @@ export function SidebarProfile() { )} - {userDetails && !gameRunning && ( + {userDetails && friendRequests?.length && !gameRunning && (
)} diff --git a/src/renderer/src/features/user-details-slice.ts b/src/renderer/src/features/user-details-slice.ts index 1912c810..04b716fd 100644 --- a/src/renderer/src/features/user-details-slice.ts +++ b/src/renderer/src/features/user-details-slice.ts @@ -5,12 +5,14 @@ export interface UserDetailsState { userDetails: UserDetails | null; profileBackground: null | string; friendRequests: FriendRequest[] | null; + showFriendRequestsModal: boolean; } const initialState: UserDetailsState = { userDetails: null, profileBackground: null, friendRequests: null, + showFriendRequestsModal: false, }; export const userDetailsSlice = createSlice({ @@ -29,8 +31,15 @@ export const userDetailsSlice = createSlice({ ) => { state.friendRequests = action.payload; }, + setShowFriendRequestsModal: (state, action: PayloadAction) => { + state.showFriendRequestsModal = action.payload; + }, }, }); -export const { setUserDetails, setProfileBackground, setFriendRequests } = - userDetailsSlice.actions; +export const { + setUserDetails, + setProfileBackground, + setFriendRequests, + setShowFriendRequestsModal, +} = userDetailsSlice.actions; diff --git a/src/renderer/src/hooks/use-user-details.ts b/src/renderer/src/hooks/use-user-details.ts index ceb2df3f..da4d51b5 100644 --- a/src/renderer/src/hooks/use-user-details.ts +++ b/src/renderer/src/hooks/use-user-details.ts @@ -6,6 +6,7 @@ import { setProfileBackground, setUserDetails, setFriendRequests, + setShowFriendRequestsModal, } from "@renderer/features"; import { darkenColor } from "@renderer/helpers"; import { FriendRequestAction, UserDetails } from "@types"; @@ -13,9 +14,12 @@ import { FriendRequestAction, UserDetails } from "@types"; export function useUserDetails() { const dispatch = useAppDispatch(); - const { userDetails, profileBackground, friendRequests } = useAppSelector( - (state) => state.userDetails - ); + const { + userDetails, + profileBackground, + friendRequests, + showFriendRequestsModal, + } = useAppSelector((state) => state.userDetails); const clearUserDetails = useCallback(async () => { dispatch(setUserDetails(null)); @@ -87,6 +91,16 @@ export function useUserDetails() { dispatch(setFriendRequests(friendRequests)); }, [dispatch]); + const setShowFriendRequestModal = useCallback( + (showModal: boolean) => { + dispatch(setShowFriendRequestsModal(showModal)); + if (showModal) { + updateFriendRequests(); + } + }, + [dispatch] + ); + const sendFriendRequest = useCallback( async (userId: string) => { return window.electron @@ -109,6 +123,7 @@ export function useUserDetails() { userDetails, profileBackground, friendRequests, + showFriendRequestsModal, fetchUserDetails, signOut, clearUserDetails, @@ -117,5 +132,6 @@ export function useUserDetails() { sendFriendRequest, updateFriendRequests, updateFriendRequestState, + setShowFriendRequestModal, }; } diff --git a/src/renderer/src/pages/user/user-add-friends-modal.tsx b/src/renderer/src/pages/shared-modals/user-friend-request-modal.tsx similarity index 99% rename from src/renderer/src/pages/user/user-add-friends-modal.tsx rename to src/renderer/src/pages/shared-modals/user-friend-request-modal.tsx index d980df43..9d8dbe6f 100644 --- a/src/renderer/src/pages/user/user-add-friends-modal.tsx +++ b/src/renderer/src/pages/shared-modals/user-friend-request-modal.tsx @@ -11,7 +11,7 @@ export interface UserAddFriendsModalProps { onClose: () => void; } -export const UserAddFriendsModal = ({ +export const UserFriendRequestModal = ({ visible, onClose, }: UserAddFriendsModalProps) => { diff --git a/src/renderer/src/pages/user/user-friend-request.tsx b/src/renderer/src/pages/shared-modals/user-friend-request.tsx similarity index 98% rename from src/renderer/src/pages/user/user-friend-request.tsx rename to src/renderer/src/pages/shared-modals/user-friend-request.tsx index e37004fc..e79a8369 100644 --- a/src/renderer/src/pages/user/user-friend-request.tsx +++ b/src/renderer/src/pages/shared-modals/user-friend-request.tsx @@ -3,7 +3,7 @@ import { PersonIcon, XCircleIcon, } from "@primer/octicons-react"; -import * as styles from "./user.css"; +import * as styles from "../user/user.css"; import cn from "classnames"; import { SPACING_UNIT } from "@renderer/theme.css"; diff --git a/src/renderer/src/pages/user/user-content.tsx b/src/renderer/src/pages/user/user-content.tsx index 503561a9..e1b0a8a2 100644 --- a/src/renderer/src/pages/user/user-content.tsx +++ b/src/renderer/src/pages/user/user-content.tsx @@ -16,12 +16,13 @@ import { buildGameDetailsPath, steamUrlBuilder } from "@renderer/helpers"; import { PersonAddIcon, PersonIcon, + PlusCircleIcon, + PlusIcon, TelescopeIcon, } from "@primer/octicons-react"; import { Button, Link } from "@renderer/components"; import { UserEditProfileModal } from "./user-edit-modal"; import { UserSignOutModal } from "./user-signout-modal"; -import { UserAddFriendsModal } from "./user-add-friends-modal"; const MAX_MINUTES_TO_SHOW_IN_PLAYTIME = 120; @@ -36,13 +37,17 @@ export function UserContent({ }: ProfileContentProps) { const { t, i18n } = useTranslation("user_profile"); - const { userDetails, profileBackground, signOut, updateFriendRequests } = - useUserDetails(); + const { + userDetails, + profileBackground, + signOut, + updateFriendRequests, + setShowFriendRequestModal, + } = useUserDetails(); const { showSuccessToast } = useToast(); const [showEditProfileModal, setShowEditProfileModal] = useState(false); const [showSignOutModal, setShowSignOutModal] = useState(false); - const [showAddFriendsModal, setShowAddFriendsModal] = useState(false); const { gameRunning } = useAppSelector((state) => state.gameRunning); @@ -117,11 +122,6 @@ export function UserContent({ onConfirm={handleConfirmSignout} /> - setShowAddFriendsModal(false)} - /> -
0)) && (
-
+

{t("friends")}

- {isMe && ( - - )} +

+ {userProfile.friends?.length || 0} +

); })} + +
)} diff --git a/src/renderer/src/pages/user/user.css.ts b/src/renderer/src/pages/user/user.css.ts index 8a56bd7d..629e8dc9 100644 --- a/src/renderer/src/pages/user/user.css.ts +++ b/src/renderer/src/pages/user/user.css.ts @@ -119,6 +119,17 @@ export const friendsSection = style({ gap: `${SPACING_UNIT * 2}px`, }); +export const friendsSectionHeader = style({ + cursor: "pointer", + display: "flex", + alignItems: "center", + justifyContent: "space-between", + gap: `${SPACING_UNIT * 2}px`, + ":hover": { + color: vars.color.muted, + }, +}); + export const contentSidebar = style({ width: "100%", display: "flex", From c6e99f8599ba18b5699a166d9cf0ecb28ea4c5d7 Mon Sep 17 00:00:00 2001 From: Zamitto <167933696+zamitto@users.noreply.github.com> Date: Tue, 16 Jul 2024 12:56:59 -0300 Subject: [PATCH 23/35] feat: update i18n and texts --- src/locales/en/translation.json | 2 +- src/locales/pt/translation.json | 4 +++- .../src/pages/shared-modals/user-friend-request-modal.tsx | 4 ++-- src/renderer/src/pages/user/user-content.tsx | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 2dadbcee..99839304 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -243,10 +243,10 @@ "playing_for": "Playing for {{amount}}", "sign_out_modal_text": "Your library is linked with your current account. When signing out, your library will not be visible anymore, and any progress will not be saved. Continue with sign out?", "add_friends": "Add Friends", + "add": "Add", "friend_code": "Friend code", "see_profile": "See profile", "sending": "Sending", - "send": "Add friend", "friend_request_sent": "Friend request sent", "friends": "Friends" } diff --git a/src/locales/pt/translation.json b/src/locales/pt/translation.json index 9ff165f9..19906e82 100644 --- a/src/locales/pt/translation.json +++ b/src/locales/pt/translation.json @@ -246,6 +246,8 @@ "friend_code": "Código de amigo", "see_profile": "Ver perfil", "friend_request_sent": "Pedido de amizade enviado", - "friends": "Amigos" + "friends": "Amigos", + "add": "Adicionar", + "sending": "Enviando" } } diff --git a/src/renderer/src/pages/shared-modals/user-friend-request-modal.tsx b/src/renderer/src/pages/shared-modals/user-friend-request-modal.tsx index 9d8dbe6f..6d72bba8 100644 --- a/src/renderer/src/pages/shared-modals/user-friend-request-modal.tsx +++ b/src/renderer/src/pages/shared-modals/user-friend-request-modal.tsx @@ -75,7 +75,7 @@ export const UserFriendRequestModal = ({ }; return ( - +
- {isAddingFriend ? t("sending") : t("send")} + {isAddingFriend ? t("sending") : t("add")}
From d0406282ceac1462337eb449d04ffe44a674350f Mon Sep 17 00:00:00 2001 From: Zamitto <167933696+zamitto@users.noreply.github.com> Date: Tue, 16 Jul 2024 13:44:52 -0300 Subject: [PATCH 24/35] feat: organize code --- src/renderer/src/app.tsx | 5 +- .../shared-modals/user-friend-modal.css.ts | 92 +++++++++++++++++++ ...equest-modal.tsx => user-friend-modal.tsx} | 2 +- .../shared-modals/user-friend-request.tsx | 2 +- src/renderer/src/pages/user/user-content.tsx | 22 ++--- src/renderer/src/pages/user/user.css.ts | 40 -------- 6 files changed, 105 insertions(+), 58 deletions(-) create mode 100644 src/renderer/src/pages/shared-modals/user-friend-modal.css.ts rename src/renderer/src/pages/shared-modals/{user-friend-request-modal.tsx => user-friend-modal.tsx} (99%) diff --git a/src/renderer/src/app.tsx b/src/renderer/src/app.tsx index a91e8881..09100d6b 100644 --- a/src/renderer/src/app.tsx +++ b/src/renderer/src/app.tsx @@ -25,7 +25,7 @@ import { setGameRunning, } from "@renderer/features"; import { useTranslation } from "react-i18next"; -import { UserFriendRequestModal } from "./pages/shared-modals/user-friend-request-modal"; +import { UserFriendModal } from "./pages/shared-modals/user-friend-modal"; export interface AppProps { children: React.ReactNode; @@ -40,7 +40,6 @@ export function App() { const { clearDownload, setLastPacket } = useDownload(); const { - userDetails, showFriendRequestsModal, setShowFriendRequestModal, updateFriendRequests, @@ -218,7 +217,7 @@ export function App() { onClose={handleToastClose} /> - setShowFriendRequestModal(false)} /> diff --git a/src/renderer/src/pages/shared-modals/user-friend-modal.css.ts b/src/renderer/src/pages/shared-modals/user-friend-modal.css.ts new file mode 100644 index 00000000..717bc95f --- /dev/null +++ b/src/renderer/src/pages/shared-modals/user-friend-modal.css.ts @@ -0,0 +1,92 @@ +import { SPACING_UNIT, vars } from "../../theme.css"; +import { style } from "@vanilla-extract/css"; + +export const profileContentBox = style({ + display: "flex", + gap: `${SPACING_UNIT * 3}px`, + alignItems: "center", + borderRadius: "4px", + border: `solid 1px ${vars.color.border}`, + width: "100%", + boxShadow: "0px 0px 15px 0px rgba(0, 0, 0, 0.7)", + transition: "all ease 0.3s", +}); + +export const friendAvatarContainer = style({ + width: "35px", + minWidth: "35px", + height: "35px", + borderRadius: "50%", + display: "flex", + justifyContent: "center", + alignItems: "center", + backgroundColor: vars.color.background, + overflow: "hidden", + border: `solid 1px ${vars.color.border}`, + boxShadow: "0px 0px 5px 0px rgba(0, 0, 0, 0.7)", +}); + +export const friendListDisplayName = style({ + fontWeight: "bold", + fontSize: vars.size.body, + textAlign: "left", + overflow: "hidden", + textOverflow: "ellipsis", + whiteSpace: "nowrap", +}); + +export const profileAvatar = style({ + height: "100%", + width: "100%", + objectFit: "cover", +}); + +export const friendListContainer = style({ + width: "100%", + height: "54px", + transition: "all ease 0.2s", + position: "relative", + ":hover": { + backgroundColor: "rgba(255, 255, 255, 0.15)", + }, +}); + +export const friendListButton = style({ + display: "flex", + alignItems: "center", + position: "absolute", + cursor: "pointer", + height: "100%", + width: "100%", + flexDirection: "row", + color: vars.color.body, + gap: `${SPACING_UNIT + SPACING_UNIT / 2}px`, + padding: "0 8px", +}); + +export const friendRequestItem = style({ + color: vars.color.body, + ":hover": { + backgroundColor: "rgba(255, 255, 255, 0.15)", + }, +}); + +export const acceptRequestButton = style({ + cursor: "pointer", + color: vars.color.body, + width: "28px", + height: "28px", + ":hover": { + color: vars.color.success, + }, +}); + +export const cancelRequestButton = style({ + cursor: "pointer", + color: vars.color.body, + width: "28px", + height: "28px", + ":hover": { + color: vars.color.danger, + }, +}); diff --git a/src/renderer/src/pages/shared-modals/user-friend-request-modal.tsx b/src/renderer/src/pages/shared-modals/user-friend-modal.tsx similarity index 99% rename from src/renderer/src/pages/shared-modals/user-friend-request-modal.tsx rename to src/renderer/src/pages/shared-modals/user-friend-modal.tsx index 6d72bba8..c8f870df 100644 --- a/src/renderer/src/pages/shared-modals/user-friend-request-modal.tsx +++ b/src/renderer/src/pages/shared-modals/user-friend-modal.tsx @@ -11,7 +11,7 @@ export interface UserAddFriendsModalProps { onClose: () => void; } -export const UserFriendRequestModal = ({ +export const UserFriendModal = ({ visible, onClose, }: UserAddFriendsModalProps) => { diff --git a/src/renderer/src/pages/shared-modals/user-friend-request.tsx b/src/renderer/src/pages/shared-modals/user-friend-request.tsx index e79a8369..022807d5 100644 --- a/src/renderer/src/pages/shared-modals/user-friend-request.tsx +++ b/src/renderer/src/pages/shared-modals/user-friend-request.tsx @@ -3,7 +3,7 @@ import { PersonIcon, XCircleIcon, } from "@primer/octicons-react"; -import * as styles from "../user/user.css"; +import * as styles from "./user-friend-modal.css"; import cn from "classnames"; import { SPACING_UNIT } from "@renderer/theme.css"; diff --git a/src/renderer/src/pages/user/user-content.tsx b/src/renderer/src/pages/user/user-content.tsx index de682922..8f1512e8 100644 --- a/src/renderer/src/pages/user/user-content.tsx +++ b/src/renderer/src/pages/user/user-content.tsx @@ -13,13 +13,7 @@ import { } from "@renderer/hooks"; import { useNavigate } from "react-router-dom"; import { buildGameDetailsPath, steamUrlBuilder } from "@renderer/helpers"; -import { - PersonAddIcon, - PersonIcon, - PlusCircleIcon, - PlusIcon, - TelescopeIcon, -} from "@primer/octicons-react"; +import { PersonIcon, PlusIcon, TelescopeIcon } from "@primer/octicons-react"; import { Button, Link } from "@renderer/components"; import { UserEditProfileModal } from "./user-edit-modal"; import { UserSignOutModal } from "./user-signout-modal"; @@ -386,12 +380,14 @@ export function UserContent({ ); })} - + {isMe && ( + + )}
)} diff --git a/src/renderer/src/pages/user/user.css.ts b/src/renderer/src/pages/user/user.css.ts index 629e8dc9..eceb06bc 100644 --- a/src/renderer/src/pages/user/user.css.ts +++ b/src/renderer/src/pages/user/user.css.ts @@ -199,19 +199,6 @@ export const friendListContainer = style({ }, }); -export const friendListButton = style({ - display: "flex", - alignItems: "center", - position: "absolute", - cursor: "pointer", - height: "100%", - width: "100%", - flexDirection: "row", - color: vars.color.body, - gap: `${SPACING_UNIT + SPACING_UNIT / 2}px`, - padding: "0 8px", -}); - export const gameInformation = style({ display: "flex", flexDirection: "column", @@ -284,30 +271,3 @@ export const profileBackground = style({ top: "0", borderRadius: "4px", }); - -export const friendRequestItem = style({ - color: vars.color.body, - ":hover": { - backgroundColor: "rgba(255, 255, 255, 0.15)", - }, -}); - -export const acceptRequestButton = style({ - cursor: "pointer", - color: vars.color.body, - width: "28px", - height: "28px", - ":hover": { - color: vars.color.success, - }, -}); - -export const cancelRequestButton = style({ - cursor: "pointer", - color: vars.color.body, - width: "28px", - height: "28px", - ":hover": { - color: vars.color.danger, - }, -}); From 7f3d7a56c31f2ff48f217ba7ca94ff1e130bf6ae Mon Sep 17 00:00:00 2001 From: Zamitto <167933696+zamitto@users.noreply.github.com> Date: Tue, 16 Jul 2024 14:52:39 -0300 Subject: [PATCH 25/35] feat: create tabs on user friend modal --- src/locales/en/translation.json | 3 +- src/locales/pt/translation.json | 3 +- .../pages/shared-modals/user-friend-modal.tsx | 149 ------------------ .../shared-modals/user-friend-modal/index.ts | 1 + .../user-friend-modal-add-friend.tsx | 138 ++++++++++++++++ .../user-friend-modal.css.ts | 2 +- .../user-friend-modal/user-friend-modal.tsx | 58 +++++++ .../user-friend-request.tsx | 0 8 files changed, 202 insertions(+), 152 deletions(-) delete mode 100644 src/renderer/src/pages/shared-modals/user-friend-modal.tsx create mode 100644 src/renderer/src/pages/shared-modals/user-friend-modal/index.ts create mode 100644 src/renderer/src/pages/shared-modals/user-friend-modal/user-friend-modal-add-friend.tsx rename src/renderer/src/pages/shared-modals/{ => user-friend-modal}/user-friend-modal.css.ts (97%) create mode 100644 src/renderer/src/pages/shared-modals/user-friend-modal/user-friend-modal.tsx rename src/renderer/src/pages/shared-modals/{ => user-friend-modal}/user-friend-request.tsx (100%) diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 99839304..917e5d75 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -248,6 +248,7 @@ "see_profile": "See profile", "sending": "Sending", "friend_request_sent": "Friend request sent", - "friends": "Friends" + "friends": "Friends", + "friends_list": "Friends list" } } diff --git a/src/locales/pt/translation.json b/src/locales/pt/translation.json index 19906e82..46fdf522 100644 --- a/src/locales/pt/translation.json +++ b/src/locales/pt/translation.json @@ -248,6 +248,7 @@ "friend_request_sent": "Pedido de amizade enviado", "friends": "Amigos", "add": "Adicionar", - "sending": "Enviando" + "sending": "Enviando", + "friends_list": "Lista de amigos" } } diff --git a/src/renderer/src/pages/shared-modals/user-friend-modal.tsx b/src/renderer/src/pages/shared-modals/user-friend-modal.tsx deleted file mode 100644 index c8f870df..00000000 --- a/src/renderer/src/pages/shared-modals/user-friend-modal.tsx +++ /dev/null @@ -1,149 +0,0 @@ -import { Button, Modal, TextField } from "@renderer/components"; -import { SPACING_UNIT } from "@renderer/theme.css"; -import { useState } from "react"; -import { useToast, useUserDetails } from "@renderer/hooks"; -import { useTranslation } from "react-i18next"; -import { useNavigate } from "react-router-dom"; -import { UserFriendRequest } from "./user-friend-request"; - -export interface UserAddFriendsModalProps { - visible: boolean; - onClose: () => void; -} - -export const UserFriendModal = ({ - visible, - onClose, -}: UserAddFriendsModalProps) => { - const { t } = useTranslation("user_profile"); - - const [friendCode, setFriendCode] = useState(""); - const [isAddingFriend, setIsAddingFriend] = useState(false); - - const navigate = useNavigate(); - - const { sendFriendRequest, updateFriendRequestState, friendRequests } = - useUserDetails(); - - const { showErrorToast } = useToast(); - - const handleClickAddFriend = () => { - setIsAddingFriend(true); - sendFriendRequest(friendCode) - .then(() => { - setFriendCode(""); - }) - .catch(() => { - showErrorToast("Não foi possível enviar o pedido de amizade"); - }) - .finally(() => { - setIsAddingFriend(false); - }); - }; - - const handleClickRequest = (userId: string) => { - resetAndClose(); - navigate(`/user/${userId}`); - }; - - const handleClickSeeProfile = () => { - resetAndClose(); - navigate(`/user/${friendCode}`); - }; - - const handleClickCancelFriendRequest = (userId: string) => { - updateFriendRequestState(userId, "CANCEL").catch(() => { - showErrorToast("Falha ao cancelar convite"); - }); - }; - - const handleClickAcceptFriendRequest = (userId: string) => { - updateFriendRequestState(userId, "ACCEPTED").catch(() => { - showErrorToast("Falha ao aceitar convite"); - }); - }; - - const handleClickRefuseFriendRequest = (userId: string) => { - updateFriendRequestState(userId, "REFUSED").catch(() => { - showErrorToast("Falha ao recusar convite"); - }); - }; - - const resetAndClose = () => { - setFriendCode(""); - onClose(); - }; - - return ( - -
-
- setFriendCode(e.target.value)} - /> - - -
- -
-

Pendentes

- {friendRequests?.map((request) => { - return ( - - ); - })} -
-
-
- ); -}; diff --git a/src/renderer/src/pages/shared-modals/user-friend-modal/index.ts b/src/renderer/src/pages/shared-modals/user-friend-modal/index.ts new file mode 100644 index 00000000..c7484512 --- /dev/null +++ b/src/renderer/src/pages/shared-modals/user-friend-modal/index.ts @@ -0,0 +1 @@ +export * from "./user-friend-modal"; diff --git a/src/renderer/src/pages/shared-modals/user-friend-modal/user-friend-modal-add-friend.tsx b/src/renderer/src/pages/shared-modals/user-friend-modal/user-friend-modal-add-friend.tsx new file mode 100644 index 00000000..45d3bc57 --- /dev/null +++ b/src/renderer/src/pages/shared-modals/user-friend-modal/user-friend-modal-add-friend.tsx @@ -0,0 +1,138 @@ +import { Button, TextField } from "@renderer/components"; +import { useToast, useUserDetails } from "@renderer/hooks"; +import { SPACING_UNIT } from "@renderer/theme.css"; +import { useState } from "react"; +import { useTranslation } from "react-i18next"; +import { useNavigate } from "react-router-dom"; +import { UserFriendRequest } from "./user-friend-request"; + +export interface UserFriendModalAddFriendProps { + closeModal: () => void; +} + +export const UserFriendModalAddFriend = ({ + closeModal, +}: UserFriendModalAddFriendProps) => { + const { t } = useTranslation("user_profile"); + + const [friendCode, setFriendCode] = useState(""); + const [isAddingFriend, setIsAddingFriend] = useState(false); + + const navigate = useNavigate(); + + const { sendFriendRequest, updateFriendRequestState, friendRequests } = + useUserDetails(); + + const { showErrorToast } = useToast(); + + const handleClickAddFriend = () => { + setIsAddingFriend(true); + sendFriendRequest(friendCode) + .then(() => { + setFriendCode(""); + }) + .catch(() => { + showErrorToast("Não foi possível enviar o pedido de amizade"); + }) + .finally(() => { + setIsAddingFriend(false); + }); + }; + + const resetAndClose = () => { + setFriendCode(""); + closeModal(); + }; + + const handleClickRequest = (userId: string) => { + resetAndClose(); + navigate(`/user/${userId}`); + }; + + const handleClickSeeProfile = () => { + resetAndClose(); + navigate(`/user/${friendCode}`); + }; + + const handleClickCancelFriendRequest = (userId: string) => { + updateFriendRequestState(userId, "CANCEL").catch(() => { + showErrorToast("Falha ao cancelar convite"); + }); + }; + + const handleClickAcceptFriendRequest = (userId: string) => { + updateFriendRequestState(userId, "ACCEPTED").catch(() => { + showErrorToast("Falha ao aceitar convite"); + }); + }; + + const handleClickRefuseFriendRequest = (userId: string) => { + updateFriendRequestState(userId, "REFUSED").catch(() => { + showErrorToast("Falha ao recusar convite"); + }); + }; + + return ( + <> +
+ setFriendCode(e.target.value)} + /> + + +
+ +
+

Pendentes

+ {friendRequests?.map((request) => { + return ( + + ); + })} +
+ + ); +}; diff --git a/src/renderer/src/pages/shared-modals/user-friend-modal.css.ts b/src/renderer/src/pages/shared-modals/user-friend-modal/user-friend-modal.css.ts similarity index 97% rename from src/renderer/src/pages/shared-modals/user-friend-modal.css.ts rename to src/renderer/src/pages/shared-modals/user-friend-modal/user-friend-modal.css.ts index 717bc95f..b5b29963 100644 --- a/src/renderer/src/pages/shared-modals/user-friend-modal.css.ts +++ b/src/renderer/src/pages/shared-modals/user-friend-modal/user-friend-modal.css.ts @@ -1,4 +1,4 @@ -import { SPACING_UNIT, vars } from "../../theme.css"; +import { SPACING_UNIT, vars } from "../../../theme.css"; import { style } from "@vanilla-extract/css"; export const profileContentBox = style({ diff --git a/src/renderer/src/pages/shared-modals/user-friend-modal/user-friend-modal.tsx b/src/renderer/src/pages/shared-modals/user-friend-modal/user-friend-modal.tsx new file mode 100644 index 00000000..0e66bc77 --- /dev/null +++ b/src/renderer/src/pages/shared-modals/user-friend-modal/user-friend-modal.tsx @@ -0,0 +1,58 @@ +import { Button, Modal } from "@renderer/components"; +import { SPACING_UNIT } from "@renderer/theme.css"; +import { useState } from "react"; +import { useTranslation } from "react-i18next"; +import { UserFriendModalAddFriend } from "./user-friend-modal-add-friend"; + +export interface UserAddFriendsModalProps { + visible: boolean; + onClose: () => void; +} + +export const UserFriendModal = ({ + visible, + onClose, +}: UserAddFriendsModalProps) => { + const { t } = useTranslation("user_profile"); + + const tabs = [t("add_friends"), t("friends_list")]; + + const [currentTabIndex, setCurrentTabIndex] = useState(0); + + const renderTab = () => { + if (currentTabIndex == 0) { + return ; + } + + return <>; + }; + + return ( + +
+
+ {tabs.map((tab, index) => { + return ( + + ); + })} +
+

{tabs[currentTabIndex]}

+ {renderTab()} +
+
+ ); +}; diff --git a/src/renderer/src/pages/shared-modals/user-friend-request.tsx b/src/renderer/src/pages/shared-modals/user-friend-modal/user-friend-request.tsx similarity index 100% rename from src/renderer/src/pages/shared-modals/user-friend-request.tsx rename to src/renderer/src/pages/shared-modals/user-friend-modal/user-friend-request.tsx From e55dc20c7db87bc1b1daf0018472ba75f45f420b Mon Sep 17 00:00:00 2001 From: Zamitto <167933696+zamitto@users.noreply.github.com> Date: Tue, 16 Jul 2024 21:45:04 -0300 Subject: [PATCH 26/35] feat: open modal in correct tab --- src/renderer/src/app.tsx | 10 +++--- .../components/sidebar/sidebar-profile.tsx | 7 ++-- .../src/features/user-details-slice.ts | 20 ++++++++--- src/renderer/src/hooks/use-user-details.ts | 20 +++++++---- .../user-friend-modal/user-friend-modal.tsx | 33 +++++++++++++++---- src/renderer/src/pages/user/user-content.tsx | 16 ++++++--- src/renderer/src/pages/user/user.css.ts | 2 ++ 7 files changed, 79 insertions(+), 29 deletions(-) diff --git a/src/renderer/src/app.tsx b/src/renderer/src/app.tsx index 09100d6b..ddad1c51 100644 --- a/src/renderer/src/app.tsx +++ b/src/renderer/src/app.tsx @@ -40,8 +40,9 @@ export function App() { const { clearDownload, setLastPacket } = useDownload(); const { - showFriendRequestsModal, - setShowFriendRequestModal, + showFriendsModal, + friendRequetsModalTab, + setShowFriendsModal, updateFriendRequests, } = useUserDetails(); @@ -218,8 +219,9 @@ export function App() { /> setShowFriendRequestModal(false)} + visible={showFriendsModal} + initialTab={friendRequetsModalTab} + onClose={() => setShowFriendsModal(false, null)} />
diff --git a/src/renderer/src/components/sidebar/sidebar-profile.tsx b/src/renderer/src/components/sidebar/sidebar-profile.tsx index 33779c0f..aef8de3d 100644 --- a/src/renderer/src/components/sidebar/sidebar-profile.tsx +++ b/src/renderer/src/components/sidebar/sidebar-profile.tsx @@ -6,6 +6,7 @@ import { useAppSelector, useUserDetails } from "@renderer/hooks"; import { useMemo } from "react"; import { useTranslation } from "react-i18next"; import { profileContainerBackground } from "./sidebar-profile.css"; +import { UserFriendModalTab } from "@renderer/pages/shared-modals/user-friend-modal"; export function SidebarProfile() { const navigate = useNavigate(); @@ -16,7 +17,7 @@ export function SidebarProfile() { userDetails, profileBackground, friendRequests, - setShowFriendRequestModal, + setShowFriendsModal, } = useUserDetails(); const { gameRunning } = useAppSelector((state) => state.gameRunning); @@ -87,7 +88,9 @@ export function SidebarProfile() { ); })}
-

{tabs[currentTabIndex]}

+

{tabs[currentTab]}

{renderTab()} diff --git a/src/renderer/src/pages/user/user-content.tsx b/src/renderer/src/pages/user/user-content.tsx index 8f1512e8..e560a50b 100644 --- a/src/renderer/src/pages/user/user-content.tsx +++ b/src/renderer/src/pages/user/user-content.tsx @@ -17,6 +17,7 @@ import { PersonIcon, PlusIcon, TelescopeIcon } from "@primer/octicons-react"; import { Button, Link } from "@renderer/components"; import { UserEditProfileModal } from "./user-edit-modal"; import { UserSignOutModal } from "./user-signout-modal"; +import { UserFriendModalTab } from "../shared-modals/user-friend-modal"; const MAX_MINUTES_TO_SHOW_IN_PLAYTIME = 120; @@ -36,7 +37,7 @@ export function UserContent({ profileBackground, signOut, updateFriendRequests, - setShowFriendRequestModal, + setShowFriendsModal, } = useUserDetails(); const { showSuccessToast } = useToast(); @@ -329,7 +330,12 @@ export function UserContent({ {(isMe || (userProfile.friends && userProfile.friends.length > 0)) && (
-
+
setShowFriendRequestModal(true)} + onClick={() => + setShowFriendsModal(true, UserFriendModalTab.AddFriend) + } > {t("add")} diff --git a/src/renderer/src/pages/user/user.css.ts b/src/renderer/src/pages/user/user.css.ts index eceb06bc..34e7b670 100644 --- a/src/renderer/src/pages/user/user.css.ts +++ b/src/renderer/src/pages/user/user.css.ts @@ -120,6 +120,8 @@ export const friendsSection = style({ }); export const friendsSectionHeader = style({ + fontSize: vars.size.body, + color: vars.color.body, cursor: "pointer", display: "flex", alignItems: "center", From 004ccd0db57304634791ecf0442d09146af45e4c Mon Sep 17 00:00:00 2001 From: Zamitto <167933696+zamitto@users.noreply.github.com> Date: Tue, 16 Jul 2024 21:51:42 -0300 Subject: [PATCH 27/35] feat: add comment --- .../user-friend-modal/user-friend-modal-add-friend.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/renderer/src/pages/shared-modals/user-friend-modal/user-friend-modal-add-friend.tsx b/src/renderer/src/pages/shared-modals/user-friend-modal/user-friend-modal-add-friend.tsx index 45d3bc57..f925ca65 100644 --- a/src/renderer/src/pages/shared-modals/user-friend-modal/user-friend-modal-add-friend.tsx +++ b/src/renderer/src/pages/shared-modals/user-friend-modal/user-friend-modal-add-friend.tsx @@ -29,6 +29,7 @@ export const UserFriendModalAddFriend = ({ setIsAddingFriend(true); sendFriendRequest(friendCode) .then(() => { + // TODO: add validation for this input? setFriendCode(""); }) .catch(() => { @@ -51,6 +52,7 @@ export const UserFriendModalAddFriend = ({ const handleClickSeeProfile = () => { resetAndClose(); + // TODO: add validation for this input? navigate(`/user/${friendCode}`); }; From d4902a5ab1cf2a81dd768019204a48344506b0e1 Mon Sep 17 00:00:00 2001 From: Zamitto <167933696+zamitto@users.noreply.github.com> Date: Tue, 16 Jul 2024 22:02:17 -0300 Subject: [PATCH 28/35] feat: use empty list --- src/renderer/src/components/sidebar/sidebar-profile.tsx | 2 +- src/renderer/src/features/user-details-slice.ts | 9 +++------ src/renderer/src/hooks/use-user-details.ts | 2 +- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/renderer/src/components/sidebar/sidebar-profile.tsx b/src/renderer/src/components/sidebar/sidebar-profile.tsx index aef8de3d..b5c2c539 100644 --- a/src/renderer/src/components/sidebar/sidebar-profile.tsx +++ b/src/renderer/src/components/sidebar/sidebar-profile.tsx @@ -83,7 +83,7 @@ export function SidebarProfile() { )}
- {userDetails && friendRequests?.length && !gameRunning && ( + {userDetails && friendRequests.length > 0 && !gameRunning && (
@@ -355,7 +355,7 @@ export function UserContent({ gap: `${SPACING_UNIT}px`, }} > - {userProfile.friends?.map((friend) => { + {userProfile.friends.map((friend) => { return (