Merge branch 'main' into feat/remove-synchronize-typeorm

This commit is contained in:
Zamitto 2024-09-02 12:58:08 -03:00 committed by GitHub
commit 6b3d3c8f5b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 157 additions and 49 deletions

View File

@ -27,7 +27,7 @@ body:
label: Expected behavior label: Expected behavior
description: A clear and concise description of what you expected to happen. description: A clear and concise description of what you expected to happen.
validations: validations:
required: true required: false
- type: textarea - type: textarea
id: screenshots id: screenshots
attributes: attributes:
@ -56,3 +56,12 @@ body:
description: Please provide any additional information and context about your problem. description: Please provide any additional information and context about your problem.
validations: validations:
required: false required: false
- type: checkboxes
id: terms
attributes:
label: Before opening this Issue
options:
- label: I have searched the issues of this repository and believe that this is not a duplicate.
required: true
- label: I am aware that Hydra team does not offer any support or help regarding the downloaded games.
required: true

View File

@ -270,6 +270,7 @@
"pending": "Pending", "pending": "Pending",
"no_pending_invites": "You have no pending invites", "no_pending_invites": "You have no pending invites",
"no_blocked_users": "You have no blocked users", "no_blocked_users": "You have no blocked users",
"friend_code_copied": "Friend code copied" "friend_code_copied": "Friend code copied",
"undo_friendship_modal_text": "This will undo your friendship with {{displayName}}"
} }
} }

View File

@ -177,9 +177,6 @@
"download_count_zero": "No hay descargas en la lista", "download_count_zero": "No hay descargas en la lista",
"download_count_one": "{{countFormatted}} descarga en la lista", "download_count_one": "{{countFormatted}} descarga en la lista",
"download_count_other": "{{countFormatted}} descargas en la lista", "download_count_other": "{{countFormatted}} descargas en la lista",
"download_options_zero": "No hay descargas disponibles",
"download_options_one": "{{countFormatted}} descarga disponible",
"download_options_other": "{{countFormatted}} descargas disponibles",
"download_source_url": "Descargar URL de origen", "download_source_url": "Descargar URL de origen",
"add_download_source_description": "Introduce la URL con el archivo .json", "add_download_source_description": "Introduce la URL con el archivo .json",
"download_source_up_to_date": "Al día", "download_source_up_to_date": "Al día",
@ -261,6 +258,18 @@
"undo_friendship": "Eliminar amistad", "undo_friendship": "Eliminar amistad",
"request_accepted": "Solicitud aceptada", "request_accepted": "Solicitud aceptada",
"user_blocked_successfully": "Usuario bloqueado exitosamente", "user_blocked_successfully": "Usuario bloqueado exitosamente",
"user_block_modal_text": "Esto va a bloquear a {{displayName}}" "user_block_modal_text": "Esto va a bloquear a {{displayName}}",
"settings": "Ajustes",
"public": "Público",
"private": "Privado",
"friends_only": "Solo Amigos",
"privacy": "Privacidad",
"blocked_users": "Usuarios bloqueados",
"unblock": "Desbloquear",
"no_friends_added": "Todavía no tienes amigos añadidos",
"pending": "Pendiente",
"no_pending_invites": "No tienes invitaciones pendientes",
"no_blocked_users": "No has bloqueado a ningún usuario",
"friend_code_copied": "Código de amigo copiado"
} }
} }

View File

@ -273,6 +273,7 @@
"pending": "Pendentes", "pending": "Pendentes",
"no_pending_invites": "Você não possui convites de amizade pendentes", "no_pending_invites": "Você não possui convites de amizade pendentes",
"no_blocked_users": "Você não tem nenhum usuário bloqueado", "no_blocked_users": "Você não tem nenhum usuário bloqueado",
"friend_code_copied": "Código de amigo copiado" "friend_code_copied": "Código de amigo copiado",
"undo_friendship_modal_text": "Isso irá remover sua amizade com {{displayName}}"
} }
} }

View File

@ -177,9 +177,6 @@
"download_count_zero": "В списке нет загрузок", "download_count_zero": "В списке нет загрузок",
"download_count_one": "{{countFormatted}} загрузка в списке", "download_count_one": "{{countFormatted}} загрузка в списке",
"download_count_other": "{{countFormatted}} загрузок в списке", "download_count_other": "{{countFormatted}} загрузок в списке",
"download_options_zero": "Нет доступных загрузок",
"download_options_one": "{{countFormatted}} вариант загрузки доступен",
"download_options_other": "{{countFormatted}} вариантов загрузки доступно",
"download_source_url": "Ссылка на источник", "download_source_url": "Ссылка на источник",
"add_download_source_description": "Вставьте ссылку на .json-файл", "add_download_source_description": "Вставьте ссылку на .json-файл",
"download_source_up_to_date": "Обновлён", "download_source_up_to_date": "Обновлён",
@ -241,6 +238,38 @@
"successfully_signed_out": "Успешный выход из аккаунта", "successfully_signed_out": "Успешный выход из аккаунта",
"sign_out": "Выйти", "sign_out": "Выйти",
"playing_for": "Сыграно {{amount}}", "playing_for": "Сыграно {{amount}}",
"sign_out_modal_text": "Ваша библиотека связана с текущей учетной записью. При выходе из системы ваша библиотека станет недоступна, и прогресс не будет сохранен. Выйти?" "sign_out_modal_text": "Ваша библиотека связана с текущей учетной записью. При выходе из системы ваша библиотека станет недоступна, и прогресс не будет сохранен. Выйти?",
"add_friends": "Добавить друзей",
"add": "Добавить",
"friend_code": "Код друга",
"see_profile": "Просмотреть профиль",
"sending": "Отправка",
"friend_request_sent": "Запрос в друзья отправлен",
"friends": "Друзья",
"friends_list": "Список друзей",
"user_not_found": "Пользователь не найден",
"block_user": "Заблокировать пользователя",
"add_friend": "Добавить друга",
"request_sent": "Запрос отправлен",
"request_received": "Запрос получен",
"accept_request": "Принять запрос",
"ignore_request": "Игнорировать запрос",
"cancel_request": "Отменить запрос",
"undo_friendship": "Удалить друга",
"request_accepted": "Запрос принят",
"user_blocked_successfully": "Пользователь успешно заблокирован",
"user_block_modal_text": "{{displayName}} будет заблокирован",
"settings": "Настройки",
"public": "Публичный",
"private": "Приватный",
"friends_only": "Только друзья",
"privacy": "Приватность",
"blocked_users": "Заблокированные пользователи",
"unblock": "Разблокировать",
"no_friends_added": "Вы ещё не добавили ни одного друга",
"pending": "Ожидание",
"no_pending_invites": "У вас нет запросов ожидающих ответа",
"no_blocked_users": "Вы не заблокировали ни одного пользователя",
"friend_code_copied": "Код друга скопирован"
} }
} }

View File

@ -106,11 +106,16 @@ app.on("browser-window-created", (_, window) => {
const handleDeepLinkPath = (uri?: string) => { const handleDeepLinkPath = (uri?: string) => {
if (!uri) return; if (!uri) return;
try {
const url = new URL(uri); const url = new URL(uri);
if (url.host === "install-source") { if (url.host === "install-source") {
WindowManager.redirect(`settings${url.search}`); WindowManager.redirect(`settings${url.search}`);
} }
} catch (error) {
logger.error("Error handling deep link", uri, error);
}
}; };
app.on("second-instance", (_event, commandLine) => { app.on("second-instance", (_event, commandLine) => {

View File

@ -104,6 +104,7 @@ export const section = style({
alignItems: "center", alignItems: "center",
gap: `${SPACING_UNIT * 2}px`, gap: `${SPACING_UNIT * 2}px`,
height: "100%", height: "100%",
overflow: "hidden",
}); });
export const backButton = recipe({ export const backButton = recipe({
@ -136,11 +137,15 @@ export const backButton = recipe({
export const title = recipe({ export const title = recipe({
base: { base: {
transition: "all ease 0.2s", transition: "all ease 0.2s",
overflow: "hidden",
textOverflow: "ellipsis",
width: "100%",
}, },
variants: { variants: {
hasBackButton: { hasBackButton: {
true: { true: {
transform: "translateX(28px)", transform: "translateX(28px)",
width: "calc(100% - 28px)",
}, },
}, },
}, },

View File

@ -72,7 +72,7 @@ export function Header({ onSearch, onClear, search }: HeaderProps) {
isWindows: window.electron.platform === "win32", isWindows: window.electron.platform === "win32",
})} })}
> >
<section className={styles.section}> <section className={styles.section} style={{ flex: 1 }}>
<button <button
type="button" type="button"
className={styles.backButton({ className={styles.backButton({

View File

@ -7,22 +7,24 @@ export const profileContainerBackground = createVar();
export const profileContainer = style({ export const profileContainer = style({
background: profileContainerBackground, background: profileContainerBackground,
position: "relative", position: "relative",
display: "flex",
gap: `${SPACING_UNIT}px`,
cursor: "pointer", cursor: "pointer",
":hover": { ":hover": {
backgroundColor: "rgba(255, 255, 255, 0.15)", backgroundColor: "rgba(255, 255, 255, 0.15)",
}, },
borderBottom: `solid 1px ${vars.color.border}`,
boxShadow: "0px 0px 15px 0px rgb(0 0 0 / 70%)",
padding: `${SPACING_UNIT * 2}px ${SPACING_UNIT * 2}px`,
}); });
export const profileButton = style({ export const profileButton = style({
display: "flex", display: "flex",
cursor: "pointer", cursor: "pointer",
transition: "all ease 0.1s", transition: "all ease 0.1s",
padding: `${SPACING_UNIT * 2}px ${SPACING_UNIT * 2}px`,
color: vars.color.muted, color: vars.color.muted,
borderBottom: `solid 1px ${vars.color.border}`,
boxShadow: "0px 0px 15px 0px rgb(0 0 0 / 70%)",
width: "100%", width: "100%",
zIndex: "10", overflow: "hidden",
}); });
export const profileButtonContent = style({ export const profileButtonContent = style({
@ -75,16 +77,6 @@ export const profileButtonTitle = style({
whiteSpace: "nowrap", whiteSpace: "nowrap",
}); });
export const friendRequestContainer = style({
position: "absolute",
padding: "8px",
right: `${SPACING_UNIT}px`,
display: "flex",
top: 0,
bottom: 0,
alignItems: "center",
});
export const friendRequestButton = style({ export const friendRequestButton = style({
color: vars.color.success, color: vars.color.success,
cursor: "pointer", cursor: "pointer",

View File

@ -41,6 +41,9 @@ export function SidebarProfile() {
return undefined; return undefined;
}, [profileBackground]); }, [profileBackground]);
const showPendingRequests =
userDetails && receivedRequests.length > 0 && !gameRunning;
return ( return (
<div <div
className={styles.profileContainer} className={styles.profileContainer}
@ -88,8 +91,7 @@ export function SidebarProfile() {
)} )}
</div> </div>
</button> </button>
{userDetails && receivedRequests.length > 0 && !gameRunning && ( {showPendingRequests && (
<div className={styles.friendRequestContainer}>
<button <button
type="button" type="button"
className={styles.friendRequestButton} className={styles.friendRequestButton}
@ -100,7 +102,6 @@ export function SidebarProfile() {
<PersonAddIcon size={24} /> <PersonAddIcon size={24} />
{receivedRequests.length} {receivedRequests.length}
</button> </button>
</div>
)} )}
</div> </div>
); );

View File

@ -0,0 +1,40 @@
import { Button, Modal } from "@renderer/components";
import * as styles from "./user.css";
import { useTranslation } from "react-i18next";
export interface UserConfirmUndoFriendshipModalProps {
visible: boolean;
displayName: string;
onConfirm: () => void;
onClose: () => void;
}
export function UserConfirmUndoFriendshipModal({
visible,
displayName,
onConfirm,
onClose,
}: UserConfirmUndoFriendshipModalProps) {
const { t } = useTranslation("user_profile");
return (
<Modal
visible={visible}
title={t("sign_out_modal_title")}
onClose={onClose}
>
<div className={styles.signOutModalContent}>
<p>{t("undo_friendship_modal_text", { displayName })}</p>
<div className={styles.signOutModalButtonsContainer}>
<Button onClick={onConfirm} theme="danger">
{t("undo_friendship")}
</Button>
<Button onClick={onClose} theme="primary">
{t("cancel")}
</Button>
</div>
</div>
</Modal>
);
}

View File

@ -34,6 +34,7 @@ import { UserProfileSettingsModal } from "./user-profile-settings-modal";
import { UserSignOutModal } from "./user-sign-out-modal"; import { UserSignOutModal } from "./user-sign-out-modal";
import { UserFriendModalTab } from "../shared-modals/user-friend-modal"; import { UserFriendModalTab } from "../shared-modals/user-friend-modal";
import { UserBlockModal } from "./user-block-modal"; import { UserBlockModal } from "./user-block-modal";
import { UserConfirmUndoFriendshipModal } from "./user-confirm-undo-friendship-modal";
const MAX_MINUTES_TO_SHOW_IN_PLAYTIME = 120; const MAX_MINUTES_TO_SHOW_IN_PLAYTIME = 120;
@ -68,6 +69,7 @@ export function UserContent({
useState(false); useState(false);
const [showSignOutModal, setShowSignOutModal] = useState(false); const [showSignOutModal, setShowSignOutModal] = useState(false);
const [showUserBlockModal, setShowUserBlockModal] = useState(false); const [showUserBlockModal, setShowUserBlockModal] = useState(false);
const [showUndoFriendshipModal, setShowUndoFriendshipModal] = useState(false);
const [currentGame, setCurrentGame] = useState<GameRunning | null>(null); const [currentGame, setCurrentGame] = useState<GameRunning | null>(null);
const { gameRunning } = useAppSelector((state) => state.gameRunning); const { gameRunning } = useAppSelector((state) => state.gameRunning);
@ -213,17 +215,12 @@ export function UserContent({
} }
if (userProfile.relation.status === "ACCEPTED") { if (userProfile.relation.status === "ACCEPTED") {
const userId =
userProfile.relation.AId === userDetails?.id
? userProfile.relation.BId
: userProfile.relation.AId;
return ( return (
<> <>
<Button <Button
theme="outline" theme="outline"
className={styles.cancelRequestButton} className={styles.cancelRequestButton}
onClick={() => handleFriendAction(userId, "UNDO")} onClick={() => setShowUndoFriendshipModal(true)}
> >
<XCircleIcon size={28} /> {t("undo_friendship")} <XCircleIcon size={28} /> {t("undo_friendship")}
</Button> </Button>
@ -291,6 +288,13 @@ export function UserContent({
displayName={userProfile.displayName} displayName={userProfile.displayName}
/> />
<UserConfirmUndoFriendshipModal
visible={showUndoFriendshipModal}
onClose={() => setShowUndoFriendshipModal(false)}
onConfirm={() => handleFriendAction(userProfile.id, "UNDO")}
displayName={userProfile.displayName}
/>
<section <section
className={styles.profileContentBox} className={styles.profileContentBox}
style={{ style={{
@ -328,7 +332,9 @@ export function UserContent({
</div> </div>
<div className={styles.profileInformation}> <div className={styles.profileInformation}>
<h2 style={{ fontWeight: "bold" }}>{userProfile.displayName}</h2> <h2 className={styles.profileDisplayName}>
{userProfile.displayName}
</h2>
{currentGame && ( {currentGame && (
<div <div
style={{ style={{

View File

@ -126,6 +126,7 @@ export const UserEditProfile = ({
value={form.displayName} value={form.displayName}
required required
minLength={3} minLength={3}
maxLength={50}
containerProps={{ style: { width: "100%" } }} containerProps={{ style: { width: "100%" } }}
onChange={(e) => setForm({ ...form, displayName: e.target.value })} onChange={(e) => setForm({ ...form, displayName: e.target.value })}
/> />

View File

@ -23,6 +23,7 @@ export const profileContentBox = style({
export const profileAvatarContainer = style({ export const profileAvatarContainer = style({
width: "96px", width: "96px",
minWidth: "96px",
height: "96px", height: "96px",
borderRadius: "50%", borderRadius: "50%",
display: "flex", display: "flex",
@ -100,6 +101,14 @@ export const profileInformation = style({
alignItems: "flex-start", alignItems: "flex-start",
color: "#c0c1c7", color: "#c0c1c7",
zIndex: 1, zIndex: 1,
overflow: "hidden",
});
export const profileDisplayName = style({
fontWeight: "bold",
overflow: "hidden",
textOverflow: "ellipsis",
width: "100%",
}); });
export const profileContent = style({ export const profileContent = style({