mirror of
				https://github.com/hydralauncher/hydra.git
				synced 2025-03-09 15:40:26 +00:00 
			
		
		
		
	Merge pull request #1447 from leandroperin/feat-favorites
feat: favorites
This commit is contained in:
		
						commit
						110131f1d6
					
				
					 35 changed files with 251 additions and 60 deletions
				
			
		| 
						 | 
				
			
			@ -14,8 +14,10 @@
 | 
			
		|||
    "paused": "{{title}} (Спынена)",
 | 
			
		||||
    "downloading": "{{title}} ({{percentage}} - Сцягванне…)",
 | 
			
		||||
    "filter": "Фільтар бібліятэкі",
 | 
			
		||||
    "home": "Галоўная"
 | 
			
		||||
    "home": "Галоўная",
 | 
			
		||||
    "favorites": "Улюбленыя"
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  "header": {
 | 
			
		||||
    "search": "Пошук",
 | 
			
		||||
    "home": "Галоўная",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,7 +26,8 @@
 | 
			
		|||
    "game_has_no_executable": "Играта няма избран изпълним файл",
 | 
			
		||||
    "sign_in": "Вписване",
 | 
			
		||||
    "friends": "Приятели",
 | 
			
		||||
    "need_help": "Имате нужда от помощ??"
 | 
			
		||||
    "need_help": "Имате нужда от помощ??",
 | 
			
		||||
    "favorites": "Любими игри"
 | 
			
		||||
  },
 | 
			
		||||
  "header": {
 | 
			
		||||
    "search": "Търсене",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,10 +20,12 @@
 | 
			
		|||
    "home": "Inici",
 | 
			
		||||
    "queued": "{{title}} (En espera)",
 | 
			
		||||
    "game_has_no_executable": "El joc encara no té un executable seleccionat",
 | 
			
		||||
    "sign_in": "Entra"
 | 
			
		||||
    "sign_in": "Entra",
 | 
			
		||||
    "favorites": "Favorits"
 | 
			
		||||
  },
 | 
			
		||||
  "header": {
 | 
			
		||||
    "search": "Cerca jocs",
 | 
			
		||||
 | 
			
		||||
    "home": "Inici",
 | 
			
		||||
    "catalogue": "Catàleg",
 | 
			
		||||
    "downloads": "Baixades",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,7 +26,8 @@
 | 
			
		|||
    "game_has_no_executable": "Hra nemá zvolen žádný spustitelný soubor",
 | 
			
		||||
    "sign_in": "Přihlásit se",
 | 
			
		||||
    "friends": "Přátelé",
 | 
			
		||||
    "need_help": "Potřebujete pomoc?"
 | 
			
		||||
    "need_help": "Potřebujete pomoc?",
 | 
			
		||||
    "favorites": "Oblíbené"
 | 
			
		||||
  },
 | 
			
		||||
  "header": {
 | 
			
		||||
    "search": "Vyhledat hry",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,10 +24,12 @@
 | 
			
		|||
    "queued": "{{title}} (I køen)",
 | 
			
		||||
    "game_has_no_executable": "Spillet har ikke nogen eksekverbar fil valgt",
 | 
			
		||||
    "sign_in": "Log ind",
 | 
			
		||||
    "friends": "Venner"
 | 
			
		||||
    "friends": "Venner",
 | 
			
		||||
    "favorites": "Favoritter"
 | 
			
		||||
  },
 | 
			
		||||
  "header": {
 | 
			
		||||
    "search": "Søg efter spil",
 | 
			
		||||
 | 
			
		||||
    "home": "Hjem",
 | 
			
		||||
    "catalogue": "Katalog",
 | 
			
		||||
    "downloads": "Downloads",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,10 +20,12 @@
 | 
			
		|||
    "home": "Home",
 | 
			
		||||
    "queued": "{{title}} (In Warteschlange)",
 | 
			
		||||
    "game_has_no_executable": "Spiel hat keine ausführbare Datei gewählt",
 | 
			
		||||
    "sign_in": "Anmelden"
 | 
			
		||||
    "sign_in": "Anmelden",
 | 
			
		||||
    "favorites": "Favoriten"
 | 
			
		||||
  },
 | 
			
		||||
  "header": {
 | 
			
		||||
    "search": "Spiele suchen",
 | 
			
		||||
 | 
			
		||||
    "home": "Home",
 | 
			
		||||
    "catalogue": "Katalog",
 | 
			
		||||
    "downloads": "Downloads",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,7 +26,8 @@
 | 
			
		|||
    "game_has_no_executable": "Game has no executable selected",
 | 
			
		||||
    "sign_in": "Sign in",
 | 
			
		||||
    "friends": "Friends",
 | 
			
		||||
    "need_help": "Need help?"
 | 
			
		||||
    "need_help": "Need help?",
 | 
			
		||||
    "favorites": "Favorites"
 | 
			
		||||
  },
 | 
			
		||||
  "header": {
 | 
			
		||||
    "search": "Search games",
 | 
			
		||||
| 
						 | 
				
			
			@ -190,6 +191,7 @@
 | 
			
		|||
    "download_error_not_cached_in_real_debrid": "This download is not available on Real-Debrid and polling download status from Real-Debrid is not yet available.",
 | 
			
		||||
    "download_error_not_cached_in_torbox": "This download is not available on Torbox and polling download status from Torbox is not yet available."
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  "activation": {
 | 
			
		||||
    "title": "Activate Hydra",
 | 
			
		||||
    "installation_id": "Installation ID:",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,7 +26,8 @@
 | 
			
		|||
    "game_has_no_executable": "El juego no tiene un ejecutable seleccionado",
 | 
			
		||||
    "sign_in": "Iniciar sesión",
 | 
			
		||||
    "friends": "Amigos",
 | 
			
		||||
    "need_help": "¿Necesitas ayuda?"
 | 
			
		||||
    "need_help": "¿Necesitas ayuda?",
 | 
			
		||||
    "favorites": "Favoritos"
 | 
			
		||||
  },
 | 
			
		||||
  "header": {
 | 
			
		||||
    "search": "Buscar juegos",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,7 +25,8 @@
 | 
			
		|||
    "queued": "{{title}} (Järjekorras)",
 | 
			
		||||
    "game_has_no_executable": "Mängul pole käivitusfaili valitud",
 | 
			
		||||
    "sign_in": "Logi sisse",
 | 
			
		||||
    "friends": "Sõbrad"
 | 
			
		||||
    "friends": "Sõbrad",
 | 
			
		||||
    "favorites": "Lemmikud"
 | 
			
		||||
  },
 | 
			
		||||
  "header": {
 | 
			
		||||
    "search": "Otsi mänge",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,8 +14,10 @@
 | 
			
		|||
    "paused": "{{title}} (متوقف شده)",
 | 
			
		||||
    "downloading": "{{title}} ({{percentage}} - در حال دانلود…)",
 | 
			
		||||
    "filter": "فیلتر کردن کتابخانه",
 | 
			
		||||
    "home": "خانه"
 | 
			
		||||
    "home": "خانه",
 | 
			
		||||
    "favorites": "علاقهمندیها"
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  "header": {
 | 
			
		||||
    "search": "جستجوی  بازیها",
 | 
			
		||||
    "home": "خانه",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,10 +14,12 @@
 | 
			
		|||
    "paused": "{{title}} (En pause)",
 | 
			
		||||
    "downloading": "{{title}} ({{percentage}} - Téléchargement en cours…)",
 | 
			
		||||
    "filter": "Filtrer la bibliothèque",
 | 
			
		||||
    "home": "Page d’accueil"
 | 
			
		||||
    "home": "Page d’accueil",
 | 
			
		||||
    "favorites": "Favoris"
 | 
			
		||||
  },
 | 
			
		||||
  "header": {
 | 
			
		||||
    "search": "Recherche",
 | 
			
		||||
 | 
			
		||||
    "catalogue": "Catalogue",
 | 
			
		||||
    "downloads": "Téléchargements",
 | 
			
		||||
    "search_results": "Résultats de la recherche",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,10 +14,12 @@
 | 
			
		|||
    "paused": "{{title}} (Szünet)",
 | 
			
		||||
    "downloading": "{{title}} ({{percentage}} - Letöltés…)",
 | 
			
		||||
    "filter": "Könyvtár szűrése",
 | 
			
		||||
    "home": "Főoldal"
 | 
			
		||||
    "home": "Főoldal",
 | 
			
		||||
    "favorites": "Kedvenc játékok"
 | 
			
		||||
  },
 | 
			
		||||
  "header": {
 | 
			
		||||
    "search": "Keresés",
 | 
			
		||||
 | 
			
		||||
    "home": "Főoldal",
 | 
			
		||||
    "catalogue": "Katalógus",
 | 
			
		||||
    "downloads": "Letöltések",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,10 +20,12 @@
 | 
			
		|||
    "home": "Beranda",
 | 
			
		||||
    "queued": "{{title}} (Antrian)",
 | 
			
		||||
    "game_has_no_executable": "Game tidak punya file eksekusi yang dipilih",
 | 
			
		||||
    "sign_in": "Masuk"
 | 
			
		||||
    "sign_in": "Masuk",
 | 
			
		||||
    "favorites": "Favorit"
 | 
			
		||||
  },
 | 
			
		||||
  "header": {
 | 
			
		||||
    "search": "Cari game",
 | 
			
		||||
 | 
			
		||||
    "home": "Beranda",
 | 
			
		||||
    "catalogue": "Katalog",
 | 
			
		||||
    "downloads": "Unduhan",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,10 +14,12 @@
 | 
			
		|||
    "paused": "{{title}} (In pausa)",
 | 
			
		||||
    "downloading": "{{title}} ({{percentage}} - Download…)",
 | 
			
		||||
    "filter": "Filtra libreria",
 | 
			
		||||
    "home": "Home"
 | 
			
		||||
    "home": "Home",
 | 
			
		||||
    "favorites": "Preferiti"
 | 
			
		||||
  },
 | 
			
		||||
  "header": {
 | 
			
		||||
    "search": "Cerca",
 | 
			
		||||
 | 
			
		||||
    "home": "Home",
 | 
			
		||||
    "catalogue": "Catalogo",
 | 
			
		||||
    "downloads": "Download",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,8 +20,10 @@
 | 
			
		|||
    "home": "Басты бет",
 | 
			
		||||
    "queued": "{{title}} (Кезекте)",
 | 
			
		||||
    "game_has_no_executable": "Ойынды іске қосу файлы таңдалмаған",
 | 
			
		||||
    "sign_in": "Кіру"
 | 
			
		||||
    "sign_in": "Кіру",
 | 
			
		||||
    "favorites": "Таңдаулылар"
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  "header": {
 | 
			
		||||
    "search": "Іздеу",
 | 
			
		||||
    "home": "Басты бет",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,8 +14,10 @@
 | 
			
		|||
    "paused": "{{title}} (일시 정지됨)",
 | 
			
		||||
    "downloading": "{{title}} ({{percentage}} - 다운로드 중…)",
 | 
			
		||||
    "filter": "라이브러리 정렬",
 | 
			
		||||
    "home": "홈"
 | 
			
		||||
    "home": "홈",
 | 
			
		||||
    "favorites": "즐겨찾기"
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  "header": {
 | 
			
		||||
    "search": "게임 검색하기",
 | 
			
		||||
    "home": "홈",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,10 +24,12 @@
 | 
			
		|||
    "queued": "{{title}} (I køen)",
 | 
			
		||||
    "game_has_no_executable": "Spillet har ikke noen kjørbar fil valgt",
 | 
			
		||||
    "sign_in": "Logge inn",
 | 
			
		||||
    "friends": "Venner"
 | 
			
		||||
    "friends": "Venner",
 | 
			
		||||
    "favorites": "Favoritter"
 | 
			
		||||
  },
 | 
			
		||||
  "header": {
 | 
			
		||||
    "search": "Søk efter spill",
 | 
			
		||||
 | 
			
		||||
    "home": "Hjem",
 | 
			
		||||
    "catalogue": "Katalog",
 | 
			
		||||
    "downloads": "Nedlastinger",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,10 +14,12 @@
 | 
			
		|||
    "paused": "{{title}} (Gepauzeerd)",
 | 
			
		||||
    "downloading": "{{title}} ({{percentage}} - Downloading…)",
 | 
			
		||||
    "filter": "Filter Bibliotheek",
 | 
			
		||||
    "home": "Home"
 | 
			
		||||
    "home": "Home",
 | 
			
		||||
    "favorites": "Favorieten"
 | 
			
		||||
  },
 | 
			
		||||
  "header": {
 | 
			
		||||
    "search": "Zoek spellen",
 | 
			
		||||
 | 
			
		||||
    "home": "Home",
 | 
			
		||||
    "catalogue": "Bibliotheek",
 | 
			
		||||
    "downloads": "Downloads",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,10 +14,12 @@
 | 
			
		|||
    "paused": "{{title}} (Zatrzymano)",
 | 
			
		||||
    "downloading": "{{title}} ({{percentage}} - Pobieranie…)",
 | 
			
		||||
    "filter": "Filtruj biblioteke",
 | 
			
		||||
    "home": "Główna"
 | 
			
		||||
    "home": "Główna",
 | 
			
		||||
    "favorites": "Ulubione"
 | 
			
		||||
  },
 | 
			
		||||
  "header": {
 | 
			
		||||
    "search": "Szukaj",
 | 
			
		||||
 | 
			
		||||
    "home": "Główna",
 | 
			
		||||
    "catalogue": "Katalog",
 | 
			
		||||
    "downloads": "Pobrane",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,10 +26,12 @@
 | 
			
		|||
    "game_has_no_executable": "Jogo não possui executável selecionado",
 | 
			
		||||
    "sign_in": "Login",
 | 
			
		||||
    "friends": "Amigos",
 | 
			
		||||
    "need_help": "Precisa de ajuda?"
 | 
			
		||||
    "need_help": "Precisa de ajuda?",
 | 
			
		||||
    "favorites": "Favoritos"
 | 
			
		||||
  },
 | 
			
		||||
  "header": {
 | 
			
		||||
    "search": "Buscar jogos",
 | 
			
		||||
 | 
			
		||||
    "catalogue": "Catálogo",
 | 
			
		||||
    "downloads": "Downloads",
 | 
			
		||||
    "search_results": "Resultados da busca",
 | 
			
		||||
| 
						 | 
				
			
			@ -179,6 +181,7 @@
 | 
			
		|||
    "download_error_not_cached_in_real_debrid": "Este download não está disponível no Real-Debrid e a verificação do status do download não está disponível.",
 | 
			
		||||
    "download_error_not_cached_in_torbox": "Este download não está disponível no Torbox e a verificação do status do download não está disponível."
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  "activation": {
 | 
			
		||||
    "title": "Ativação",
 | 
			
		||||
    "installation_id": "ID da instalação:",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,10 +25,12 @@
 | 
			
		|||
    "queued": "{{title}} (Na fila)",
 | 
			
		||||
    "game_has_no_executable": "O jogo não tem um executável selecionado",
 | 
			
		||||
    "sign_in": "Iniciar sessão",
 | 
			
		||||
    "friends": "Amigos"
 | 
			
		||||
    "friends": "Amigos",
 | 
			
		||||
    "favorites": "Favoritos"
 | 
			
		||||
  },
 | 
			
		||||
  "header": {
 | 
			
		||||
    "search": "Procurar jogos",
 | 
			
		||||
 | 
			
		||||
    "catalogue": "Catálogo",
 | 
			
		||||
    "downloads": "Transferências",
 | 
			
		||||
    "search_results": "Resultados da pesquisa",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,10 +14,12 @@
 | 
			
		|||
    "paused": "{{title}} (Pauzat)",
 | 
			
		||||
    "downloading": "{{title}} ({{percentage}} - Se descarcă...)",
 | 
			
		||||
    "filter": "Filtrează biblioteca",
 | 
			
		||||
    "home": "Acasă"
 | 
			
		||||
    "home": "Acasă",
 | 
			
		||||
    "favorites": "Favorite"
 | 
			
		||||
  },
 | 
			
		||||
  "header": {
 | 
			
		||||
    "search": "Caută jocuri",
 | 
			
		||||
 | 
			
		||||
    "home": "Acasă",
 | 
			
		||||
    "catalogue": "Catalog",
 | 
			
		||||
    "downloads": "Descărcări",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,7 +26,8 @@
 | 
			
		|||
    "game_has_no_executable": "Файл запуска игры не выбран",
 | 
			
		||||
    "sign_in": "Войти",
 | 
			
		||||
    "friends": "Друзья",
 | 
			
		||||
    "need_help": "Нужна помощь?"
 | 
			
		||||
    "need_help": "Нужна помощь?",
 | 
			
		||||
    "favorites": "Избранное"
 | 
			
		||||
  },
 | 
			
		||||
  "header": {
 | 
			
		||||
    "search": "Поиск",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,7 +26,8 @@
 | 
			
		|||
    "game_has_no_executable": "Oyun için bir çalıştırılabilir dosya seçilmedi",
 | 
			
		||||
    "sign_in": "Giriş yap",
 | 
			
		||||
    "friends": "Arkadaşlar",
 | 
			
		||||
    "need_help": "Yardıma mı ihtiyacınız var?"
 | 
			
		||||
    "need_help": "Yardıma mı ihtiyacınız var?",
 | 
			
		||||
    "favorites": "Favoriler"
 | 
			
		||||
  },
 | 
			
		||||
  "header": {
 | 
			
		||||
    "search": "Oyunları ara",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,10 +20,12 @@
 | 
			
		|||
    "home": "Головна",
 | 
			
		||||
    "game_has_no_executable": "Не було вибрано файл для запуску гри",
 | 
			
		||||
    "queued": "{{title}} в черзі",
 | 
			
		||||
    "sign_in": "Увійти"
 | 
			
		||||
    "sign_in": "Увійти",
 | 
			
		||||
    "favorites": "Улюблені"
 | 
			
		||||
  },
 | 
			
		||||
  "header": {
 | 
			
		||||
    "search": "Пошук",
 | 
			
		||||
 | 
			
		||||
    "home": "Головна",
 | 
			
		||||
    "catalogue": "Каталог",
 | 
			
		||||
    "downloads": "Завантаження",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,7 +25,8 @@
 | 
			
		|||
    "queued": "{{title}} (已加入下载队列)",
 | 
			
		||||
    "game_has_no_executable": "未选择游戏的可执行文件",
 | 
			
		||||
    "sign_in": "登入",
 | 
			
		||||
    "friends": "好友"
 | 
			
		||||
    "friends": "好友",
 | 
			
		||||
    "favorites": "收藏"
 | 
			
		||||
  },
 | 
			
		||||
  "header": {
 | 
			
		||||
    "search": "搜索游戏",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,6 +13,8 @@ import "./catalogue/get-developers";
 | 
			
		|||
import "./hardware/get-disk-free-space";
 | 
			
		||||
import "./hardware/check-folder-write-permission";
 | 
			
		||||
import "./library/add-game-to-library";
 | 
			
		||||
import "./library/add-game-to-favorites";
 | 
			
		||||
import "./library/remove-game-from-favorites";
 | 
			
		||||
import "./library/create-game-shortcut";
 | 
			
		||||
import "./library/close-game";
 | 
			
		||||
import "./library/delete-game-folder";
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										25
									
								
								src/main/events/library/add-game-to-favorites.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/main/events/library/add-game-to-favorites.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,25 @@
 | 
			
		|||
import { registerEvent } from "../register-event";
 | 
			
		||||
import { gamesSublevel, levelKeys } from "@main/level";
 | 
			
		||||
import type { GameShop } from "@types";
 | 
			
		||||
 | 
			
		||||
const addGameToFavorites = async (
 | 
			
		||||
  _event: Electron.IpcMainInvokeEvent,
 | 
			
		||||
  shop: GameShop,
 | 
			
		||||
  objectId: string
 | 
			
		||||
) => {
 | 
			
		||||
  const gameKey = levelKeys.game(shop, objectId);
 | 
			
		||||
 | 
			
		||||
  const game = await gamesSublevel.get(gameKey);
 | 
			
		||||
  if (!game) return;
 | 
			
		||||
 | 
			
		||||
  try {
 | 
			
		||||
    await gamesSublevel.put(gameKey, {
 | 
			
		||||
      ...game,
 | 
			
		||||
      favorite: true,
 | 
			
		||||
    });
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
    throw new Error(`Failed to update game favorite status: ${error}`);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
registerEvent("addGameToFavorites", addGameToFavorites);
 | 
			
		||||
							
								
								
									
										25
									
								
								src/main/events/library/remove-game-from-favorites.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/main/events/library/remove-game-from-favorites.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,25 @@
 | 
			
		|||
import { registerEvent } from "../register-event";
 | 
			
		||||
import { gamesSublevel, levelKeys } from "@main/level";
 | 
			
		||||
import type { GameShop } from "@types";
 | 
			
		||||
 | 
			
		||||
const removeGameFromFavorites = async (
 | 
			
		||||
  _event: Electron.IpcMainInvokeEvent,
 | 
			
		||||
  shop: GameShop,
 | 
			
		||||
  objectId: string
 | 
			
		||||
) => {
 | 
			
		||||
  const gameKey = levelKeys.game(shop, objectId);
 | 
			
		||||
 | 
			
		||||
  const game = await gamesSublevel.get(gameKey);
 | 
			
		||||
  if (!game) return;
 | 
			
		||||
 | 
			
		||||
  try {
 | 
			
		||||
    await gamesSublevel.put(gameKey, {
 | 
			
		||||
      ...game,
 | 
			
		||||
      favorite: false,
 | 
			
		||||
    });
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
    throw new Error(`Failed to update game favorite status: ${error}`);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
registerEvent("removeGameFromFavorites", removeGameFromFavorites);
 | 
			
		||||
| 
						 | 
				
			
			@ -110,11 +110,16 @@ contextBridge.exposeInMainWorld("electron", {
 | 
			
		|||
    executablePath: string | null
 | 
			
		||||
  ) =>
 | 
			
		||||
    ipcRenderer.invoke("updateExecutablePath", shop, objectId, executablePath),
 | 
			
		||||
  addGameToFavorites: (shop: GameShop, objectId: string) =>
 | 
			
		||||
    ipcRenderer.invoke("addGameToFavorites", shop, objectId),
 | 
			
		||||
  removeGameFromFavorites: (shop: GameShop, objectId: string) =>
 | 
			
		||||
    ipcRenderer.invoke("removeGameFromFavorites", shop, objectId),
 | 
			
		||||
  updateLaunchOptions: (
 | 
			
		||||
    shop: GameShop,
 | 
			
		||||
    objectId: string,
 | 
			
		||||
    launchOptions: string | null
 | 
			
		||||
  ) => ipcRenderer.invoke("updateLaunchOptions", shop, objectId, launchOptions),
 | 
			
		||||
 | 
			
		||||
  selectGameWinePrefix: (
 | 
			
		||||
    shop: GameShop,
 | 
			
		||||
    objectId: string,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										50
									
								
								src/renderer/src/components/sidebar/sidebar-game-item.tsx
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								src/renderer/src/components/sidebar/sidebar-game-item.tsx
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,50 @@
 | 
			
		|||
import SteamLogo from "@renderer/assets/steam-logo.svg?react";
 | 
			
		||||
import { LibraryGame } from "@types";
 | 
			
		||||
import cn from "classnames";
 | 
			
		||||
import { useLocation } from "react-router-dom";
 | 
			
		||||
 | 
			
		||||
interface SidebarGameItemProps {
 | 
			
		||||
  game: LibraryGame;
 | 
			
		||||
  handleSidebarGameClick: (event: React.MouseEvent, game: LibraryGame) => void;
 | 
			
		||||
  getGameTitle: (game: LibraryGame) => string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function SidebarGameItem({
 | 
			
		||||
  game,
 | 
			
		||||
  handleSidebarGameClick,
 | 
			
		||||
  getGameTitle,
 | 
			
		||||
}: Readonly<SidebarGameItemProps>) {
 | 
			
		||||
  const location = useLocation();
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <li
 | 
			
		||||
      key={game.id}
 | 
			
		||||
      className={cn("sidebar__menu-item", {
 | 
			
		||||
        "sidebar__menu-item--active":
 | 
			
		||||
          location.pathname === `/game/${game.shop}/${game.objectId}`,
 | 
			
		||||
        "sidebar__menu-item--muted": game.download?.status === "removed",
 | 
			
		||||
      })}
 | 
			
		||||
    >
 | 
			
		||||
      <button
 | 
			
		||||
        type="button"
 | 
			
		||||
        className="sidebar__menu-item-button"
 | 
			
		||||
        onClick={(event) => handleSidebarGameClick(event, game)}
 | 
			
		||||
      >
 | 
			
		||||
        {game.iconUrl ? (
 | 
			
		||||
          <img
 | 
			
		||||
            className="sidebar__game-icon"
 | 
			
		||||
            src={game.iconUrl}
 | 
			
		||||
            alt={game.title}
 | 
			
		||||
            loading="lazy"
 | 
			
		||||
          />
 | 
			
		||||
        ) : (
 | 
			
		||||
          <SteamLogo className="sidebar__game-icon" />
 | 
			
		||||
        )}
 | 
			
		||||
 | 
			
		||||
        <span className="sidebar__menu-item-button-label">
 | 
			
		||||
          {getGameTitle(game)}
 | 
			
		||||
        </span>
 | 
			
		||||
      </button>
 | 
			
		||||
    </li>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -18,11 +18,11 @@ import "./sidebar.scss";
 | 
			
		|||
 | 
			
		||||
import { buildGameDetailsPath } from "@renderer/helpers";
 | 
			
		||||
 | 
			
		||||
import SteamLogo from "@renderer/assets/steam-logo.svg?react";
 | 
			
		||||
import { SidebarProfile } from "./sidebar-profile";
 | 
			
		||||
import { sortBy } from "lodash-es";
 | 
			
		||||
import cn from "classnames";
 | 
			
		||||
import { CommentDiscussionIcon } from "@primer/octicons-react";
 | 
			
		||||
import { SidebarGameItem } from "./sidebar-game-item";
 | 
			
		||||
 | 
			
		||||
const SIDEBAR_MIN_WIDTH = 200;
 | 
			
		||||
const SIDEBAR_INITIAL_WIDTH = 250;
 | 
			
		||||
| 
						 | 
				
			
			@ -206,6 +206,23 @@ export function Sidebar() {
 | 
			
		|||
            </ul>
 | 
			
		||||
          </section>
 | 
			
		||||
 | 
			
		||||
          <section className="sidebar__section">
 | 
			
		||||
            <small className="sidebar__section-title">{t("favorites")}</small>
 | 
			
		||||
 | 
			
		||||
            <ul className="sidebar__menu">
 | 
			
		||||
              {sortedLibrary
 | 
			
		||||
                .filter((game) => game.favorite)
 | 
			
		||||
                .map((game) => (
 | 
			
		||||
                  <SidebarGameItem
 | 
			
		||||
                    key={game.id}
 | 
			
		||||
                    game={game}
 | 
			
		||||
                    handleSidebarGameClick={handleSidebarGameClick}
 | 
			
		||||
                    getGameTitle={getGameTitle}
 | 
			
		||||
                  />
 | 
			
		||||
                ))}
 | 
			
		||||
            </ul>
 | 
			
		||||
          </section>
 | 
			
		||||
 | 
			
		||||
          <section className="sidebar__section">
 | 
			
		||||
            <small className="sidebar__section-title">{t("my_library")}</small>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -217,39 +234,16 @@ export function Sidebar() {
 | 
			
		|||
            />
 | 
			
		||||
 | 
			
		||||
            <ul className="sidebar__menu">
 | 
			
		||||
              {filteredLibrary.map((game) => (
 | 
			
		||||
                <li
 | 
			
		||||
                  key={game.id}
 | 
			
		||||
                  className={cn("sidebar__menu-item", {
 | 
			
		||||
                    "sidebar__menu-item--active":
 | 
			
		||||
                      location.pathname ===
 | 
			
		||||
                      `/game/${game.shop}/${game.objectId}`,
 | 
			
		||||
                    "sidebar__menu-item--muted":
 | 
			
		||||
                      game.download?.status === "removed",
 | 
			
		||||
                  })}
 | 
			
		||||
                >
 | 
			
		||||
                  <button
 | 
			
		||||
                    type="button"
 | 
			
		||||
                    className="sidebar__menu-item-button"
 | 
			
		||||
                    onClick={(event) => handleSidebarGameClick(event, game)}
 | 
			
		||||
                  >
 | 
			
		||||
                    {game.iconUrl ? (
 | 
			
		||||
                      <img
 | 
			
		||||
                        className="sidebar__game-icon"
 | 
			
		||||
                        src={game.iconUrl}
 | 
			
		||||
                        alt={game.title}
 | 
			
		||||
                        loading="lazy"
 | 
			
		||||
                      />
 | 
			
		||||
                    ) : (
 | 
			
		||||
                      <SteamLogo className="sidebar__game-icon" />
 | 
			
		||||
                    )}
 | 
			
		||||
 | 
			
		||||
                    <span className="sidebar__menu-item-button-label">
 | 
			
		||||
                      {getGameTitle(game)}
 | 
			
		||||
                    </span>
 | 
			
		||||
                  </button>
 | 
			
		||||
                </li>
 | 
			
		||||
              ))}
 | 
			
		||||
              {filteredLibrary
 | 
			
		||||
                .filter((game) => !game.favorite)
 | 
			
		||||
                .map((game) => (
 | 
			
		||||
                  <SidebarGameItem
 | 
			
		||||
                    key={game.id}
 | 
			
		||||
                    game={game}
 | 
			
		||||
                    handleSidebarGameClick={handleSidebarGameClick}
 | 
			
		||||
                    getGameTitle={getGameTitle}
 | 
			
		||||
                  />
 | 
			
		||||
                ))}
 | 
			
		||||
            </ul>
 | 
			
		||||
          </section>
 | 
			
		||||
        </div>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										5
									
								
								src/renderer/src/declaration.d.ts
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								src/renderer/src/declaration.d.ts
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -96,6 +96,11 @@ declare global {
 | 
			
		|||
      objectId: string,
 | 
			
		||||
      executablePath: string | null
 | 
			
		||||
    ) => Promise<void>;
 | 
			
		||||
    addGameToFavorites: (shop: GameShop, objectId: string) => Promise<void>;
 | 
			
		||||
    removeGameFromFavorites: (
 | 
			
		||||
      shop: GameShop,
 | 
			
		||||
      objectId: string
 | 
			
		||||
    ) => Promise<void>;
 | 
			
		||||
    updateLaunchOptions: (
 | 
			
		||||
      shop: GameShop,
 | 
			
		||||
      objectId: string,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,8 @@
 | 
			
		|||
import {
 | 
			
		||||
  DownloadIcon,
 | 
			
		||||
  GearIcon,
 | 
			
		||||
  HeartFillIcon,
 | 
			
		||||
  HeartIcon,
 | 
			
		||||
  PlayIcon,
 | 
			
		||||
  PlusCircleIcon,
 | 
			
		||||
} from "@primer/octicons-react";
 | 
			
		||||
| 
						 | 
				
			
			@ -52,6 +54,32 @@ export function HeroPanelActions() {
 | 
			
		|||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const addGameToFavorites = async () => {
 | 
			
		||||
    setToggleLibraryGameDisabled(true);
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      if (!objectId) throw new Error("objectId is required");
 | 
			
		||||
      await window.electron.addGameToFavorites(shop, objectId);
 | 
			
		||||
      updateLibrary();
 | 
			
		||||
      updateGame();
 | 
			
		||||
    } finally {
 | 
			
		||||
      setToggleLibraryGameDisabled(false);
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const removeGameFromFavorites = async () => {
 | 
			
		||||
    setToggleLibraryGameDisabled(true);
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      if (!objectId) throw new Error("objectId is required");
 | 
			
		||||
      await window.electron.removeGameFromFavorites(shop, objectId);
 | 
			
		||||
      updateLibrary();
 | 
			
		||||
      updateGame();
 | 
			
		||||
    } finally {
 | 
			
		||||
      setToggleLibraryGameDisabled(false);
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const openGame = async () => {
 | 
			
		||||
    if (game) {
 | 
			
		||||
      if (game.executablePath) {
 | 
			
		||||
| 
						 | 
				
			
			@ -159,6 +187,16 @@ export function HeroPanelActions() {
 | 
			
		|||
      <div className="hero-panel-actions__container">
 | 
			
		||||
        {gameActionButton()}
 | 
			
		||||
        <div className="hero-panel-actions__separator" />
 | 
			
		||||
        <Button
 | 
			
		||||
          onClick={game.favorite ? removeGameFromFavorites : addGameToFavorites}
 | 
			
		||||
          theme="outline"
 | 
			
		||||
          disabled={deleting}
 | 
			
		||||
          className="hero-panel-actions__action"
 | 
			
		||||
        >
 | 
			
		||||
          {game.favorite ? <HeartFillIcon /> : <HeartIcon />}
 | 
			
		||||
        </Button>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        <Button
 | 
			
		||||
          onClick={() => setShowGameOptionsModal(true)}
 | 
			
		||||
          theme="outline"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -42,6 +42,7 @@ export interface Game {
 | 
			
		|||
  winePrefixPath?: string | null;
 | 
			
		||||
  executablePath?: string | null;
 | 
			
		||||
  launchOptions?: string | null;
 | 
			
		||||
  favorite?: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface Download {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue