feat: cloud modal

This commit is contained in:
Zamitto 2024-12-22 17:38:55 -03:00
parent 041b7d520c
commit 313ebc6055
32 changed files with 304 additions and 88 deletions

View File

@ -309,7 +309,7 @@
"last_time_played": "لعبت آخر مرة {{period}}", "last_time_played": "لعبت آخر مرة {{period}}",
"activity": "النشاط الأخير", "activity": "النشاط الأخير",
"library": "مكتبة", "library": "مكتبة",
"total_play_time": "إجمالي وقت اللعب: {{amount}}", "total_play_time": "إجمالي وقت اللعب",
"no_recent_activity_title": "هممم... لا شيء هنا", "no_recent_activity_title": "هممم... لا شيء هنا",
"no_recent_activity_description": "لم تلعب أي مباراة مؤخرًا. ", "no_recent_activity_description": "لم تلعب أي مباراة مؤخرًا. ",
"display_name": "اسم العرض", "display_name": "اسم العرض",
@ -389,7 +389,7 @@
"achievement_progress": "{{unlockedCount}}/{{totalCount}} الإنجازات", "achievement_progress": "{{unlockedCount}}/{{totalCount}} الإنجازات",
"achievements_unlocked_for_game": "مفتوح {{achievementCount}} انجازات جديدة ل {{gameTitle}}" "achievements_unlocked_for_game": "مفتوح {{achievementCount}} انجازات جديدة ل {{gameTitle}}"
}, },
"tour": { "hydra_cloud": {
"subscription_tour_title": "اشتراك Hydra كلاود", "subscription_tour_title": "اشتراك Hydra كلاود",
"subscribe_now": "اشترك الآن", "subscribe_now": "اشترك الآن",
"cloud_saving": "الحفظ السحابي", "cloud_saving": "الحفظ السحابي",

View File

@ -293,7 +293,7 @@
"last_time_played": "Последно играно {{period}}", "last_time_played": "Последно играно {{period}}",
"activity": "Скорошна активност", "activity": "Скорошна активност",
"library": "Библиотека", "library": "Библиотека",
"total_play_time": "Общо време за игра: {{amount}}", "total_play_time": "Общо време за игра",
"no_recent_activity_title": "Хмм… няма нищо тук", "no_recent_activity_title": "Хмм… няма нищо тук",
"no_recent_activity_description": "Не сте играли игри напоследък. Време е да промените това.!", "no_recent_activity_description": "Не сте играли игри напоследък. Време е да промените това.!",
"display_name": "Показване на името", "display_name": "Показване на името",
@ -368,7 +368,7 @@
"achievement_progress": "{{unlockedCount}}/{{totalCount}} постижения", "achievement_progress": "{{unlockedCount}}/{{totalCount}} постижения",
"achievements_unlocked_for_game": "Отключени {{achievementCount}} нови постижения за {{gameTitle}}" "achievements_unlocked_for_game": "Отключени {{achievementCount}} нови постижения за {{gameTitle}}"
}, },
"tour": { "hydra_cloud": {
"subscription_tour_title": "Hydra Cloud Абонамент", "subscription_tour_title": "Hydra Cloud Абонамент",
"subscribe_now": "Абонирай се сега", "subscribe_now": "Абонирай се сега",
"cloud_saving": "Запазване в облака", "cloud_saving": "Запазване в облака",

View File

@ -224,7 +224,7 @@
"last_time_played": "Última partida {{period}}", "last_time_played": "Última partida {{period}}",
"activity": "Activitat recent", "activity": "Activitat recent",
"library": "Biblioteca", "library": "Biblioteca",
"total_play_time": "Temps total de joc:{{amount}}", "total_play_time": "Temps total de joc",
"no_recent_activity_title": "Hmmm… encara no res", "no_recent_activity_title": "Hmmm… encara no res",
"no_recent_activity_description": "No has jugat a cap joc recentment. És el moment de canviar-ho!", "no_recent_activity_description": "No has jugat a cap joc recentment. És el moment de canviar-ho!",
"display_name": "Nom de visualització", "display_name": "Nom de visualització",

View File

@ -293,7 +293,7 @@
"last_time_played": "Naposledy hráno {{period}}", "last_time_played": "Naposledy hráno {{period}}",
"activity": "Nedávná aktivita", "activity": "Nedávná aktivita",
"library": "Knihovna", "library": "Knihovna",
"total_play_time": "Celkový odehraný čas: {{amount}}", "total_play_time": "Celkový odehraný čas",
"no_recent_activity_title": "Hmmm… nic tu není", "no_recent_activity_title": "Hmmm… nic tu není",
"no_recent_activity_description": "V poslední době si nehrál žádnout hru, můžeš to ale napravit!", "no_recent_activity_description": "V poslední době si nehrál žádnout hru, můžeš to ale napravit!",
"display_name": "Zobrazované jméno", "display_name": "Zobrazované jméno",
@ -368,7 +368,7 @@
"achievement_progress": "{{unlockedCount}}/{{totalCount}} achievementů", "achievement_progress": "{{unlockedCount}}/{{totalCount}} achievementů",
"achievements_unlocked_for_game": "Odemčeno {{achievementCount}} nových achievementů pro {{gameTitle}}" "achievements_unlocked_for_game": "Odemčeno {{achievementCount}} nových achievementů pro {{gameTitle}}"
}, },
"tour": { "hydra_cloud": {
"subscription_tour_title": "Předplatné Hydra Cloud", "subscription_tour_title": "Předplatné Hydra Cloud",
"subscribe_now": "Připojit se", "subscribe_now": "Připojit se",
"cloud_saving": "Ukládání v cloudu", "cloud_saving": "Ukládání v cloudu",

View File

@ -251,7 +251,7 @@
"last_time_played": "Sidst spillet {{period}}", "last_time_played": "Sidst spillet {{period}}",
"activity": "Seneste aktivitet", "activity": "Seneste aktivitet",
"library": "Bibliotek", "library": "Bibliotek",
"total_play_time": "Samlet spiltid: {{amount}}", "total_play_time": "Samlet spiltid",
"no_recent_activity_title": "Hmmm… ikke noget her", "no_recent_activity_title": "Hmmm… ikke noget her",
"no_recent_activity_description": "Du har ikke spillet nogen spil for nyligt. Dét er det på tide at lave om på!", "no_recent_activity_description": "Du har ikke spillet nogen spil for nyligt. Dét er det på tide at lave om på!",
"display_name": "Brugernavn", "display_name": "Brugernavn",

View File

@ -224,7 +224,7 @@
"last_time_played": "Zuletzt gespielt {{period}}", "last_time_played": "Zuletzt gespielt {{period}}",
"activity": "Letzte Aktivität", "activity": "Letzte Aktivität",
"library": "Bibliothek", "library": "Bibliothek",
"total_play_time": "Gesamtspielzeit: {{amount}}", "total_play_time": "Gesamtspielzeit",
"no_recent_activity_title": "Hmmm… hier ist nichts", "no_recent_activity_title": "Hmmm… hier ist nichts",
"no_recent_activity_description": "Du hast in letzter Zeit keine Spiele gespielt. Es wird Zeit das zu ändern!", "no_recent_activity_description": "Du hast in letzter Zeit keine Spiele gespielt. Es wird Zeit das zu ändern!",
"display_name": "Anzeigename", "display_name": "Anzeigename",

View File

@ -163,7 +163,7 @@
"no_download_option_info": "No information available", "no_download_option_info": "No information available",
"backup_deletion_failed": "Failed to delete backup", "backup_deletion_failed": "Failed to delete backup",
"max_number_of_artifacts_reached": "Maximum number of backups reached for this game", "max_number_of_artifacts_reached": "Maximum number of backups reached for this game",
"achievements_not_sync": "Your achievements are not synchronized", "achievements_not_sync": "See how to synchronize your achievements",
"manage_files_description": "Manage which files will be backed up and restored", "manage_files_description": "Manage which files will be backed up and restored",
"select_folder": "Select folder", "select_folder": "Select folder",
"backup_from": "Backup from {{date}}", "backup_from": "Backup from {{date}}",
@ -302,7 +302,7 @@
"last_time_played": "Last played {{period}}", "last_time_played": "Last played {{period}}",
"activity": "Recent Activity", "activity": "Recent Activity",
"library": "Library", "library": "Library",
"total_play_time": "Total playtime: {{amount}}", "total_play_time": "Total playtime",
"no_recent_activity_title": "Hmmm… nothing here", "no_recent_activity_title": "Hmmm… nothing here",
"no_recent_activity_description": "You haven't played any games recently. It's time to change that!", "no_recent_activity_description": "You haven't played any games recently. It's time to change that!",
"display_name": "Display name", "display_name": "Display name",
@ -383,9 +383,9 @@
"achievement_progress": "{{unlockedCount}}/{{totalCount}} achievements", "achievement_progress": "{{unlockedCount}}/{{totalCount}} achievements",
"achievements_unlocked_for_game": "Unlocked {{achievementCount}} new achievements for {{gameTitle}}", "achievements_unlocked_for_game": "Unlocked {{achievementCount}} new achievements for {{gameTitle}}",
"hidden_achievement_tooltip": "This is a hidden achievement", "hidden_achievement_tooltip": "This is a hidden achievement",
"achievement_earn_points": "Earn {{points}} with this achievement" "achievement_earn_points": "Earn {{points}} points with this achievement"
}, },
"tour": { "hydra_cloud": {
"subscription_tour_title": "Hydra Cloud Subscription", "subscription_tour_title": "Hydra Cloud Subscription",
"subscribe_now": "Subscribe now", "subscribe_now": "Subscribe now",
"cloud_saving": "Cloud saving", "cloud_saving": "Cloud saving",

View File

@ -295,7 +295,7 @@
"last_time_played": "Última vez jugado: {{period}}", "last_time_played": "Última vez jugado: {{period}}",
"activity": "Actividad reciente", "activity": "Actividad reciente",
"library": "Biblioteca", "library": "Biblioteca",
"total_play_time": "Total de tiempo jugado: {{amount}}", "total_play_time": "Has jugado",
"no_recent_activity_title": "Que raro, no hay nada por acá...", "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!", "no_recent_activity_description": "No has jugado ningún juego recientemente, ¡vamos a cambiar eso ahora!",
"display_name": "Nombre en pantalla", "display_name": "Nombre en pantalla",
@ -358,7 +358,8 @@
"your_friend_code": "Tu código de amigo:", "your_friend_code": "Tu código de amigo:",
"upload_banner": "Subir un banner", "upload_banner": "Subir un banner",
"uploading_banner": "Subiendo banner…", "uploading_banner": "Subiendo banner…",
"background_image_updated": "Imagen de fondo actualizada" "background_image_updated": "Imagen de fondo actualizada",
"playing": "Jugando {{game}}"
}, },
"achievement": { "achievement": {
"achievement_unlocked": "Logro desbloqueado", "achievement_unlocked": "Logro desbloqueado",
@ -370,7 +371,7 @@
"achievement_progress": "{{unlockedCount}}/{{totalCount}} logros", "achievement_progress": "{{unlockedCount}}/{{totalCount}} logros",
"achievements_unlocked_for_game": "Se han desbloqueado {{achievementCount}} nuevos logros de {{gameTitle}}" "achievements_unlocked_for_game": "Se han desbloqueado {{achievementCount}} nuevos logros de {{gameTitle}}"
}, },
"tour": { "hydra_cloud": {
"subscription_tour_title": "Suscripción Hydra Cloud", "subscription_tour_title": "Suscripción Hydra Cloud",
"subscribe_now": "Suscribirse ahora", "subscribe_now": "Suscribirse ahora",
"cloud_saving": "Guardado en la nube", "cloud_saving": "Guardado en la nube",

View File

@ -290,7 +290,7 @@
"last_time_played": "Viimati mängitud {{period}}", "last_time_played": "Viimati mängitud {{period}}",
"activity": "Hiljutine aktiivsus", "activity": "Hiljutine aktiivsus",
"library": "Kogu", "library": "Kogu",
"total_play_time": "Kogu mängitud aeg: {{amount}}", "total_play_time": "Kogu mängitud aeg",
"no_recent_activity_title": "Hmmm… siin pole midagi", "no_recent_activity_title": "Hmmm… siin pole midagi",
"no_recent_activity_description": "Sa pole hiljuti ühtegi mängu mänginud. On aeg seda muuta!", "no_recent_activity_description": "Sa pole hiljuti ühtegi mängu mänginud. On aeg seda muuta!",
"display_name": "Kuvatav nimi", "display_name": "Kuvatav nimi",
@ -363,7 +363,7 @@
"subscription_needed": "Selle sisu nägemiseks on vaja Hydra Cloud tellimust", "subscription_needed": "Selle sisu nägemiseks on vaja Hydra Cloud tellimust",
"new_achievements_unlocked": "Avatud {{achievementCount}} uut saavutust {{gameCount}} mängust" "new_achievements_unlocked": "Avatud {{achievementCount}} uut saavutust {{gameCount}} mängust"
}, },
"tour": { "hydra_cloud": {
"subscription_tour_title": "Hydra Cloud Tellimus", "subscription_tour_title": "Hydra Cloud Tellimus",
"subscribe_now": "Telli kohe", "subscribe_now": "Telli kohe",
"cloud_saving": "Pilvesalvestus", "cloud_saving": "Pilvesalvestus",

View File

@ -224,7 +224,7 @@
"last_time_played": "Terakhir dimainkan {{period}}", "last_time_played": "Terakhir dimainkan {{period}}",
"activity": "Aktivitas terbaru", "activity": "Aktivitas terbaru",
"library": "Perpustakaan", "library": "Perpustakaan",
"total_play_time": "Total waktu bermain: {{amount}}", "total_play_time": "Total waktu bermain",
"no_recent_activity_title": "Hmm… kosong di sini", "no_recent_activity_title": "Hmm… kosong di sini",
"no_recent_activity_description": "Kamu belum main game baru-baru ini. Yuk, mulai main!", "no_recent_activity_description": "Kamu belum main game baru-baru ini. Yuk, mulai main!",
"display_name": "Nama tampilan", "display_name": "Nama tampilan",

View File

@ -220,7 +220,7 @@
"last_time_played": "Соңғы ойын {{period}}", "last_time_played": "Соңғы ойын {{period}}",
"activity": "Соңғы әрекет", "activity": "Соңғы әрекет",
"library": "Кітапхана", "library": "Кітапхана",
"total_play_time": "Барлығы ойнаған: {{amount}}", "total_play_time": "Барлығы ойнаған",
"no_recent_activity_title": "Хммм... Мұнда ештеңе жоқ", "no_recent_activity_title": "Хммм... Мұнда ештеңе жоқ",
"no_recent_activity_description": "Сіз ұзақ уақыт бойы ештеңе ойнаған жоқсыз. Мұны өзгерту керек!", "no_recent_activity_description": "Сіз ұзақ уақыт бойы ештеңе ойнаған жоқсыз. Мұны өзгерту керек!",
"display_name": "Көрсету аты", "display_name": "Көрсету аты",

View File

@ -251,7 +251,7 @@
"last_time_played": "Sist spilt {{period}}", "last_time_played": "Sist spilt {{period}}",
"activity": "Seneste aktivitet", "activity": "Seneste aktivitet",
"library": "Bibliotek", "library": "Bibliotek",
"total_play_time": "Samlet spilltid: {{amount}}", "total_play_time": "Samlet spilltid",
"no_recent_activity_title": "Hmmm… ikke noe her", "no_recent_activity_title": "Hmmm… ikke noe her",
"no_recent_activity_description": "Du har ikke spilt noen spill for på det seneste. Det er det på tide at endre på!", "no_recent_activity_description": "Du har ikke spilt noen spill for på det seneste. Det er det på tide at endre på!",
"display_name": "Brukernavn", "display_name": "Brukernavn",

View File

@ -158,7 +158,7 @@
"no_download_option_info": "Sem informações disponíveis", "no_download_option_info": "Sem informações disponíveis",
"backup_deletion_failed": "Falha ao apagar backup", "backup_deletion_failed": "Falha ao apagar backup",
"max_number_of_artifacts_reached": "Número máximo de backups atingido para este jogo", "max_number_of_artifacts_reached": "Número máximo de backups atingido para este jogo",
"achievements_not_sync": "Suas conquistas não estão sincronizadas", "achievements_not_sync": "Veja como exibir suas conquistas no perfil",
"backup_from": "Backup de {{date}}", "backup_from": "Backup de {{date}}",
"custom_backup_location_set": "Localização customizada selecionada", "custom_backup_location_set": "Localização customizada selecionada",
"select_folder": "Selecione a pasta", "select_folder": "Selecione a pasta",
@ -300,7 +300,7 @@
"last_time_played": "Última sessão {{period}}", "last_time_played": "Última sessão {{period}}",
"activity": "Atividades recentes", "activity": "Atividades recentes",
"library": "Biblioteca", "library": "Biblioteca",
"total_play_time": "Tempo de jogo: {{amount}}", "total_play_time": "Tempo total de jogo",
"no_recent_activity_title": "Hmmm… nada por aqui", "no_recent_activity_title": "Hmmm… nada por aqui",
"no_recent_activity_description": "Parece que você não jogou nada recentemente. Que tal começar agora?", "no_recent_activity_description": "Parece que você não jogou nada recentemente. Que tal começar agora?",
"display_name": "Nome de exibição", "display_name": "Nome de exibição",
@ -367,7 +367,8 @@
"stats": "Estatísticas", "stats": "Estatísticas",
"achievements": "Conquistas", "achievements": "Conquistas",
"games": "Jogos", "games": "Jogos",
"ranking_updated_weekly": "Ranking é atualizado semanalmente" "ranking_updated_weekly": "Ranking é atualizado semanalmente",
"playing": "Jogando {{game}}"
}, },
"achievement": { "achievement": {
"achievement_unlocked": "Conquista desbloqueada", "achievement_unlocked": "Conquista desbloqueada",
@ -379,9 +380,9 @@
"achievement_progress": "{{unlockedCount}}/{{totalCount}} conquistas", "achievement_progress": "{{unlockedCount}}/{{totalCount}} conquistas",
"achievements_unlocked_for_game": "Desbloqueadas {{achievementCount}} novas conquistas em {{gameTitle}}", "achievements_unlocked_for_game": "Desbloqueadas {{achievementCount}} novas conquistas em {{gameTitle}}",
"hidden_achievement_tooltip": "Está é uma conquista oculta", "hidden_achievement_tooltip": "Está é uma conquista oculta",
"achievement_earn_points": "Ganhe {{points}} com essa conquista" "achievement_earn_points": "Ganhe {{points}} pontos com essa conquista"
}, },
"tour": { "hydra_cloud": {
"subscription_tour_title": "Assinatura Hydra Cloud", "subscription_tour_title": "Assinatura Hydra Cloud",
"subscribe_now": "Inscreva-se agora", "subscribe_now": "Inscreva-se agora",
"cloud_achievements": "Salvamento de conquistas em nuvem", "cloud_achievements": "Salvamento de conquistas em nuvem",

View File

@ -287,7 +287,7 @@
"last_time_played": "Última sessão {{period}}", "last_time_played": "Última sessão {{period}}",
"activity": "Atividade recente", "activity": "Atividade recente",
"library": "Biblioteca", "library": "Biblioteca",
"total_play_time": "Tempo total de jogo: {{amount}}", "total_play_time": "Tempo total de jogo",
"no_recent_activity_title": "Hmmm… não há nada por aqui", "no_recent_activity_title": "Hmmm… não há nada por aqui",
"no_recent_activity_description": "Parece que não jogaste nada recentemente. Que tal começar agora?", "no_recent_activity_description": "Parece que não jogaste nada recentemente. Que tal começar agora?",
"display_name": "Nome de apresentação", "display_name": "Nome de apresentação",
@ -360,7 +360,7 @@
"subscription_needed": "Precisas de uma subscrição Hydra Cloud para visualizar este conteúdo", "subscription_needed": "Precisas de uma subscrição Hydra Cloud para visualizar este conteúdo",
"new_achievements_unlocked": "{{achievementCount}} novas conquistas de {{gameCount}} jogos" "new_achievements_unlocked": "{{achievementCount}} novas conquistas de {{gameCount}} jogos"
}, },
"tour": { "hydra_cloud": {
"subscription_tour_title": "Subscrição Hydra Cloud", "subscription_tour_title": "Subscrição Hydra Cloud",
"subscribe_now": "Subscreve agora", "subscribe_now": "Subscreve agora",
"cloud_achievements": "Gravação de conquistas na nuvem", "cloud_achievements": "Gravação de conquistas na nuvem",

View File

@ -294,7 +294,7 @@
"last_time_played": "Последняя игра {{period}}", "last_time_played": "Последняя игра {{period}}",
"activity": "Недавняя активность", "activity": "Недавняя активность",
"library": "Библиотека", "library": "Библиотека",
"total_play_time": "Всего сыграно: {{amount}}", "total_play_time": "Всего сыграно",
"no_recent_activity_title": "Хммм... Тут ничего нет", "no_recent_activity_title": "Хммм... Тут ничего нет",
"no_recent_activity_description": "Вы давно ни во что не играли. Пора это изменить!", "no_recent_activity_description": "Вы давно ни во что не играли. Пора это изменить!",
"display_name": "Отображаемое имя", "display_name": "Отображаемое имя",
@ -365,7 +365,7 @@
"achievement_progress": "{{unlockedCount}}/{{totalCount}} достижений", "achievement_progress": "{{unlockedCount}}/{{totalCount}} достижений",
"achievements_unlocked_for_game": "Разблокировано {{achievementCount}} новых достижений для {{gameTitle}}" "achievements_unlocked_for_game": "Разблокировано {{achievementCount}} новых достижений для {{gameTitle}}"
}, },
"tour": { "hydra_cloud": {
"subscription_tour_title": "Подписка Hydra Cloud", "subscription_tour_title": "Подписка Hydra Cloud",
"subscribe_now": "Подпишитесь прямо сейчас", "subscribe_now": "Подпишитесь прямо сейчас",
"cloud_saving": "Сохранение в облаке", "cloud_saving": "Сохранение в облаке",

View File

@ -231,7 +231,7 @@
"sign_out_modal_text": "Ваша бібліотека пов'язана з поточним обліковим записом. При виході з системи ваша бібліотека буде недоступною, і прогрес не буде збережено. Продовжити вихід?", "sign_out_modal_text": "Ваша бібліотека пов'язана з поточним обліковим записом. При виході з системи ваша бібліотека буде недоступною, і прогрес не буде збережено. Продовжити вихід?",
"sign_out_modal_title": "Ви впевнені?", "sign_out_modal_title": "Ви впевнені?",
"successfully_signed_out": "Успішний вихід з акаунту", "successfully_signed_out": "Успішний вихід з акаунту",
"total_play_time": "Всього зіграно: {{amount}}", "total_play_time": "Всього зіграно",
"try_again": "Будь ласка, попробуйте ще раз" "try_again": "Будь ласка, попробуйте ще раз"
} }
} }

View File

@ -290,7 +290,7 @@
"last_time_played": "上次游玩时间 {{period}}", "last_time_played": "上次游玩时间 {{period}}",
"activity": "近期活动", "activity": "近期活动",
"library": "库", "library": "库",
"total_play_time": "总游戏时长: {{amount}}", "total_play_time": "总游戏时长",
"no_recent_activity_title": "Emmm… 这里暂时啥都没有", "no_recent_activity_title": "Emmm… 这里暂时啥都没有",
"no_recent_activity_description": "你最近没玩过任何游戏。是时候做出改变了!", "no_recent_activity_description": "你最近没玩过任何游戏。是时候做出改变了!",
"display_name": "昵称", "display_name": "昵称",
@ -363,7 +363,7 @@
"subscription_needed": "需要订阅 Hydra Cloud 才能看到此内容", "subscription_needed": "需要订阅 Hydra Cloud 才能看到此内容",
"new_achievements_unlocked": "从 {{gameCount}} 游戏中解锁 {{achievementCount}} 新成就" "new_achievements_unlocked": "从 {{gameCount}} 游戏中解锁 {{achievementCount}} 新成就"
}, },
"tour": { "hydra_cloud": {
"subscription_tour_title": "Hydra 云订阅", "subscription_tour_title": "Hydra 云订阅",
"subscribe_now": "现在订购", "subscribe_now": "现在订购",
"cloud_saving": "云存档", "cloud_saving": "云存档",

View File

@ -29,6 +29,8 @@ import { UserFriendModal } from "./pages/shared-modals/user-friend-modal";
import { downloadSourcesWorker } from "./workers"; import { downloadSourcesWorker } from "./workers";
import { repacksContext } from "./context"; import { repacksContext } from "./context";
import { logger } from "./logger"; import { logger } from "./logger";
import { useSubscription } from "./hooks/use-subscription";
import { HydraCloudModal } from "./pages/shared-modals/hydra-cloud/hydra-cloud-modal";
export interface AppProps { export interface AppProps {
children: React.ReactNode; children: React.ReactNode;
@ -47,21 +49,21 @@ export function App() {
const { indexRepacks } = useContext(repacksContext); const { indexRepacks } = useContext(repacksContext);
const { const {
userDetails,
hasActiveSubscription,
isFriendsModalVisible, isFriendsModalVisible,
friendRequetsModalTab, friendRequetsModalTab,
friendModalUserId, friendModalUserId,
syncFriendRequests, syncFriendRequests,
hideFriendsModal, hideFriendsModal,
} = useUserDetails();
const {
userDetails,
hasActiveSubscription,
fetchUserDetails, fetchUserDetails,
updateUserDetails, updateUserDetails,
clearUserDetails, clearUserDetails,
} = useUserDetails(); } = useUserDetails();
const { hideHydraCloudModal, showHydraCloudModal, isHydraCloudModalVisible } =
useSubscription();
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const navigate = useNavigate(); const navigate = useNavigate();
@ -308,6 +310,11 @@ export function App() {
onClose={handleToastClose} onClose={handleToastClose}
/> />
<HydraCloudModal
visible={isHydraCloudModalVisible}
onClose={hideHydraCloudModal}
/>
{userDetails && ( {userDetails && (
<UserFriendModal <UserFriendModal
visible={isFriendsModalVisible} visible={isFriendsModalVisible}

View File

@ -53,7 +53,6 @@ export const gameDetailsContext = createContext<GameDetailsContext>({
setShowGameOptionsModal: () => {}, setShowGameOptionsModal: () => {},
setShowRepacksModal: () => {}, setShowRepacksModal: () => {},
setHasNSFWContentBlocked: () => {}, setHasNSFWContentBlocked: () => {},
handleClickOpenCheckout: () => {},
}); });
const { Provider } = gameDetailsContext; const { Provider } = gameDetailsContext;
@ -111,11 +110,6 @@ export function GameDetailsContextProvider({
(state) => state.userPreferences.value (state) => state.userPreferences.value
); );
const handleClickOpenCheckout = () => {
// TODO: show modal before redirecting to checkout page
window.electron.openCheckout();
};
const updateGame = useCallback(async () => { const updateGame = useCallback(async () => {
return window.electron return window.electron
.getGameByObjectId(objectId!) .getGameByObjectId(objectId!)
@ -290,7 +284,6 @@ export function GameDetailsContextProvider({
updateGame, updateGame,
setShowRepacksModal, setShowRepacksModal,
setShowGameOptionsModal, setShowGameOptionsModal,
handleClickOpenCheckout,
}} }}
> >
{children} {children}

View File

@ -29,5 +29,4 @@ export interface GameDetailsContext {
setShowRepacksModal: React.Dispatch<React.SetStateAction<boolean>>; setShowRepacksModal: React.Dispatch<React.SetStateAction<boolean>>;
setShowGameOptionsModal: React.Dispatch<React.SetStateAction<boolean>>; setShowGameOptionsModal: React.Dispatch<React.SetStateAction<boolean>>;
setHasNSFWContentBlocked: React.Dispatch<React.SetStateAction<boolean>>; setHasNSFWContentBlocked: React.Dispatch<React.SetStateAction<boolean>>;
handleClickOpenCheckout: () => void;
} }

View File

@ -6,3 +6,4 @@ export * from "./window-slice";
export * from "./toast-slice"; export * from "./toast-slice";
export * from "./user-details-slice"; export * from "./user-details-slice";
export * from "./running-game-slice"; export * from "./running-game-slice";
export * from "./subscription-slice";

View File

@ -0,0 +1,25 @@
import { createSlice } from "@reduxjs/toolkit";
export interface SubscriptionState {
isHydraCloudModalVisible: boolean;
}
const initialState: SubscriptionState = {
isHydraCloudModalVisible: false,
};
export const subscriptionSlice = createSlice({
name: "subscription",
initialState,
reducers: {
setHydraCloudModalVisible: (state) => {
state.isHydraCloudModalVisible = true;
},
setHydraCloudModalHidden: (state) => {
state.isHydraCloudModalVisible = false;
},
},
});
export const { setHydraCloudModalVisible, setHydraCloudModalHidden } =
subscriptionSlice.actions;

View File

@ -0,0 +1,28 @@
import { useCallback } from "react";
import { useAppDispatch, useAppSelector } from "./redux";
import {
setHydraCloudModalVisible,
setHydraCloudModalHidden,
} from "@renderer/features";
export function useSubscription() {
const dispatch = useAppDispatch();
const { isHydraCloudModalVisible } = useAppSelector(
(state) => state.subscription
);
const showHydraCloudModal = useCallback(() => {
dispatch(setHydraCloudModalVisible());
}, [dispatch]);
const hideHydraCloudModal = useCallback(() => {
dispatch(setHydraCloudModalHidden());
}, [dispatch]);
return {
isHydraCloudModalVisible,
showHydraCloudModal,
hideHydraCloudModal,
};
}

View File

@ -4,6 +4,8 @@ import { useTranslation } from "react-i18next";
import * as styles from "./achievements.css"; import * as styles from "./achievements.css";
import { EyeClosedIcon } from "@primer/octicons-react"; import { EyeClosedIcon } from "@primer/octicons-react";
import HydraIcon from "@renderer/assets/icons/hydra.svg?react"; import HydraIcon from "@renderer/assets/icons/hydra.svg?react";
import { useSubscription } from "@renderer/hooks/use-subscription";
import { vars } from "@renderer/theme.css";
interface AchievementListProps { interface AchievementListProps {
achievements: UserAchievement[]; achievements: UserAchievement[];
@ -11,6 +13,7 @@ interface AchievementListProps {
export function AchievementList({ achievements }: AchievementListProps) { export function AchievementList({ achievements }: AchievementListProps) {
const { t } = useTranslation("achievement"); const { t } = useTranslation("achievement");
const { showHydraCloudModal } = useSubscription();
const { formatDateTime } = useDate(); const { formatDateTime } = useDate();
return ( return (
@ -41,7 +44,7 @@ export function AchievementList({ achievements }: AchievementListProps) {
<p>{achievement.description}</p> <p>{achievement.description}</p>
</div> </div>
<div style={{ display: "flex", flexDirection: "column", gap: "8px" }}> <div style={{ display: "flex", flexDirection: "column", gap: "8px" }}>
{achievement.points && ( {achievement.points != undefined ? (
<div <div
style={{ display: "flex", alignItems: "center", gap: "4px" }} style={{ display: "flex", alignItems: "center", gap: "4px" }}
title={t("achievement_earn_points", { title={t("achievement_earn_points", {
@ -51,6 +54,23 @@ export function AchievementList({ achievements }: AchievementListProps) {
<HydraIcon width={20} height={20} /> <HydraIcon width={20} height={20} />
<p style={{ fontSize: "1.1em" }}>{achievement.points}</p> <p style={{ fontSize: "1.1em" }}>{achievement.points}</p>
</div> </div>
) : (
<button
onClick={showHydraCloudModal}
style={{
display: "flex",
alignItems: "center",
gap: "4px",
cursor: "pointer",
color: vars.color.warning,
}}
title={t("achievement_earn_points", {
points: "???",
})}
>
<HydraIcon width={20} height={20} />
<p style={{ fontSize: "1.1em" }}>???</p>
</button>
)} )}
{achievement.unlockTime && ( {achievement.unlockTime && (
<div <div

View File

@ -19,6 +19,7 @@ import * as styles from "./achievements.css";
import { AchievementList } from "./achievement-list"; import { AchievementList } from "./achievement-list";
import { AchievementPanel } from "./achievement-panel"; import { AchievementPanel } from "./achievement-panel";
import { ComparedAchievementPanel } from "./compared-achievement-panel"; import { ComparedAchievementPanel } from "./compared-achievement-panel";
import { useSubscription } from "@renderer/hooks/use-subscription";
interface UserInfo { interface UserInfo {
id: string; id: string;
@ -41,7 +42,7 @@ interface AchievementSummaryProps {
function AchievementSummary({ user, isComparison }: AchievementSummaryProps) { function AchievementSummary({ user, isComparison }: AchievementSummaryProps) {
const { t } = useTranslation("achievement"); const { t } = useTranslation("achievement");
const { userDetails, hasActiveSubscription } = useUserDetails(); const { userDetails, hasActiveSubscription } = useUserDetails();
const { handleClickOpenCheckout } = useContext(gameDetailsContext); const { showHydraCloudModal } = useSubscription();
const getProfileImage = ( const getProfileImage = (
user: Pick<UserInfo, "profileImageUrl" | "displayName"> user: Pick<UserInfo, "profileImageUrl" | "displayName">
@ -92,7 +93,7 @@ function AchievementSummary({ user, isComparison }: AchievementSummaryProps) {
<h3> <h3>
<button <button
className={styles.subscriptionRequiredButton} className={styles.subscriptionRequiredButton}
onClick={handleClickOpenCheckout} onClick={showHydraCloudModal}
> >
{t("subscription_needed")} {t("subscription_needed")}
</button> </button>

View File

@ -14,6 +14,7 @@ import { steamUrlBuilder } from "@shared";
import cloudIconAnimated from "@renderer/assets/icons/cloud-animated.gif"; import cloudIconAnimated from "@renderer/assets/icons/cloud-animated.gif";
import { useUserDetails } from "@renderer/hooks"; import { useUserDetails } from "@renderer/hooks";
import { useSubscription } from "@renderer/hooks/use-subscription";
const HERO_ANIMATION_THRESHOLD = 25; const HERO_ANIMATION_THRESHOLD = 25;
@ -31,9 +32,10 @@ export function GameDetailsContent() {
gameColor, gameColor,
setGameColor, setGameColor,
hasNSFWContentBlocked, hasNSFWContentBlocked,
handleClickOpenCheckout,
} = useContext(gameDetailsContext); } = useContext(gameDetailsContext);
const { showHydraCloudModal } = useSubscription();
const { userDetails, hasActiveSubscription } = useUserDetails(); const { userDetails, hasActiveSubscription } = useUserDetails();
const { setShowCloudSyncModal, getGameArtifacts } = const { setShowCloudSyncModal, getGameArtifacts } =
@ -104,7 +106,7 @@ export function GameDetailsContent() {
} }
if (!hasActiveSubscription) { if (!hasActiveSubscription) {
handleClickOpenCheckout(); showHydraCloudModal();
return; return;
} }

View File

@ -21,6 +21,8 @@ import { howLongToBeatEntriesTable } from "@renderer/dexie";
import { SidebarSection } from "../sidebar-section/sidebar-section"; import { SidebarSection } from "../sidebar-section/sidebar-section";
import { buildGameAchievementPath } from "@renderer/helpers"; import { buildGameAchievementPath } from "@renderer/helpers";
import { SPACING_UNIT } from "@renderer/theme.css"; import { SPACING_UNIT } from "@renderer/theme.css";
import { useSubmit } from "react-router-dom";
import { useSubscription } from "@renderer/hooks/use-subscription";
const fakeAchievements: UserAchievement[] = [ const fakeAchievements: UserAchievement[] = [
{ {
@ -67,15 +69,10 @@ export function Sidebar() {
const [activeRequirement, setActiveRequirement] = const [activeRequirement, setActiveRequirement] =
useState<keyof SteamAppDetails["pc_requirements"]>("minimum"); useState<keyof SteamAppDetails["pc_requirements"]>("minimum");
const { const { gameTitle, shopDetails, objectId, shop, stats, achievements } =
gameTitle, useContext(gameDetailsContext);
shopDetails,
objectId, const { showHydraCloudModal } = useSubscription();
shop,
stats,
achievements,
handleClickOpenCheckout,
} = useContext(gameDetailsContext);
const { t } = useTranslation("game_details"); const { t } = useTranslation("game_details");
const { formatDateTime } = useDate(); const { formatDateTime } = useDate();
@ -179,7 +176,7 @@ export function Sidebar() {
{!hasActiveSubscription && ( {!hasActiveSubscription && (
<button <button
className={styles.subscriptionRequiredButton} className={styles.subscriptionRequiredButton}
onClick={handleClickOpenCheckout} onClick={showHydraCloudModal}
> >
<CloudOfflineIcon size={16} /> <CloudOfflineIcon size={16} />
<span>{t("achievements_not_sync")}</span> <span>{t("achievements_not_sync")}</span>

View File

@ -203,3 +203,12 @@ export const achievementsProgressBar = style({
borderRadius: "4px", borderRadius: "4px",
}, },
}); });
export const link = style({
textAlign: "start",
color: vars.color.body,
":hover": {
textDecoration: "underline",
cursor: "pointer",
},
});

View File

@ -5,8 +5,11 @@ import { useTranslation } from "react-i18next";
import { useFormat } from "@renderer/hooks"; import { useFormat } from "@renderer/hooks";
import { MAX_MINUTES_TO_SHOW_IN_PLAYTIME } from "@renderer/constants"; import { MAX_MINUTES_TO_SHOW_IN_PLAYTIME } from "@renderer/constants";
import HydraIcon from "@renderer/assets/icons/hydra.svg?react"; import HydraIcon from "@renderer/assets/icons/hydra.svg?react";
import { useSubscription } from "@renderer/hooks/use-subscription";
export function UserStatsBox() { export function UserStatsBox() {
const { showHydraCloudModal } = useSubscription();
const { userStats } = useContext(userProfileContext); const { userStats } = useContext(userProfileContext);
const { t } = useTranslation("user_profile"); const { t } = useTranslation("user_profile");
@ -40,12 +43,19 @@ export function UserStatsBox() {
<div className={styles.box}> <div className={styles.box}>
<ul className={styles.list}> <ul className={styles.list}>
{userStats.achievementsPointsEarnedSum && (
<li> <li>
<h3 className={styles.listItemTitle}>{t("achievements")}</h3> <h3 className={styles.listItemTitle}>{t("achievements")}</h3>
<div style={{ display: "flex", justifyContent: "space-between" }}> {userStats.achievementsPointsEarnedSum !== undefined ? (
<>
<div
style={{ display: "flex", justifyContent: "space-between" }}
>
<p <p
style={{ display: "flex", alignItems: "center", gap: "4px" }} style={{
display: "flex",
alignItems: "center",
gap: "4px",
}}
> >
<HydraIcon width={20} height={20} /> <HydraIcon width={20} height={20} />
{userStats.achievementsPointsEarnedSum.value} {userStats.achievementsPointsEarnedSum.value}
@ -58,19 +68,24 @@ export function UserStatsBox() {
</p> </p>
</div> </div>
<p>Unlock count: {userStats.unlockedAchievementSum}</p> <p>Unlock count: {userStats.unlockedAchievementSum}</p>
</li> </>
) : (
<button
type="button"
onClick={showHydraCloudModal}
className={styles.link}
>
<small>
Saiba como exibir suas conquistas e pontos no perfil
</small>
</button>
)} )}
</li>
<li> <li>
<h3 className={styles.listItemTitle}>{t("games")}</h3> <h3 className={styles.listItemTitle}>{t("total_play_time")}</h3>
<div style={{ display: "flex", justifyContent: "space-between" }}> <div style={{ display: "flex", justifyContent: "space-between" }}>
<p> <p>{formatPlayTime(userStats.totalPlayTimeInSeconds.value)}</p>
{t("total_play_time", {
amount: formatPlayTime(
userStats.totalPlayTimeInSeconds.value
),
})}
</p>
<p title={t("ranking_updated_weekly")}> <p title={t("ranking_updated_weekly")}>
{t("top_percentile", { {t("top_percentile", {
percentile: userStats.totalPlayTimeInSeconds.topPercentile, percentile: userStats.totalPlayTimeInSeconds.topPercentile,

View File

@ -0,0 +1,79 @@
import { SPACING_UNIT, vars } from "../../../theme.css";
import { style } from "@vanilla-extract/css";
export const friendListDisplayName = style({
fontWeight: "bold",
fontSize: vars.size.body,
textAlign: "left",
overflow: "hidden",
textOverflow: "ellipsis",
whiteSpace: "nowrap",
});
export const friendListContainer = style({
display: "flex",
gap: `${SPACING_UNIT * 3}px`,
alignItems: "center",
borderRadius: "4px",
border: `solid 1px ${vars.color.border}`,
width: "100%",
height: "54px",
minHeight: "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 ${SPACING_UNIT}px`,
});
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,
},
});
export const friendCodeButton = style({
color: vars.color.body,
cursor: "pointer",
display: "flex",
gap: `${SPACING_UNIT / 2}px`,
alignItems: "center",
transition: "all ease 0.2s",
":hover": {
color: vars.color.muted,
},
});

View File

@ -0,0 +1,36 @@
import { Button, Modal } from "@renderer/components";
import { SPACING_UNIT } from "@renderer/theme.css";
import { useTranslation } from "react-i18next";
export interface HydraCloudModalProps {
visible: boolean;
onClose: () => void;
}
export const HydraCloudModal = ({ visible, onClose }: HydraCloudModalProps) => {
const { t } = useTranslation("hydra_cloud");
const handleClickOpenCheckout = () => {
window.electron.openCheckout();
};
return (
<Modal
visible={visible}
title={t("subscription_tour_title")}
onClose={onClose}
>
<div
style={{
display: "flex",
width: "500px",
flexDirection: "column",
gap: `${SPACING_UNIT * 2}px`,
}}
>
Você descobriu uma funcionalidade Hydra Cloud!
<Button onClick={handleClickOpenCheckout}>Saiba mais</Button>
</div>
</Modal>
);
};

View File

@ -8,6 +8,7 @@ import {
toastSlice, toastSlice,
userDetailsSlice, userDetailsSlice,
gameRunningSlice, gameRunningSlice,
subscriptionSlice,
} from "@renderer/features"; } from "@renderer/features";
export const store = configureStore({ export const store = configureStore({
@ -20,6 +21,7 @@ export const store = configureStore({
toast: toastSlice.reducer, toast: toastSlice.reducer,
userDetails: userDetailsSlice.reducer, userDetails: userDetailsSlice.reducer,
gameRunning: gameRunningSlice.reducer, gameRunning: gameRunningSlice.reducer,
subscription: subscriptionSlice.reducer,
}, },
}); });