From 741aeccd4c0fd44a0c2d0476530b3c3e6cd31a45 Mon Sep 17 00:00:00 2001 From: prostagma-fp Date: Sun, 19 May 2024 12:10:43 -0300 Subject: [PATCH] Tag filter icons Includes a field in the Tag Filter settings (Config tab) for the filename of an icon to be displayed at the Grid/List view for games with the related tags. The extreme icon takes preference over to be displayed. --- .gitignore | 2 +- lang/cs-CZ.json | 6 +++-- lang/de-DE.json | 6 +++-- lang/en.json | 6 +++-- lang/es-ES.json | 6 +++-- lang/et-EE.json | 6 +++-- lang/fi-FI.json | 6 +++-- lang/fr-FR.json | 6 +++-- lang/hu-HU.json | 6 +++-- lang/it-IT.json | 6 +++-- lang/ja-JP.json | 6 +++-- lang/mk-MK.json | 6 +++-- lang/pl-PL.json | 6 +++-- lang/pt-BR.json | 6 +++-- lang/ro-RO.json | 6 +++-- lang/ru-RU.json | 6 +++-- lang/tr-TR.json | 6 +++-- lang/vi-VN.json | 6 +++-- lang/zh-CN.json | 6 +++-- lang/zh-TW.json | 6 +++-- package-lock.json | 4 ++-- src/renderer/components/GameGrid.tsx | 6 +++++ src/renderer/components/GameGridItem.tsx | 12 ++++++++-- src/renderer/components/GameList.tsx | 6 +++++ src/renderer/components/GameListItem.tsx | 10 ++++++-- .../components/TagFilterGroupEditor.tsx | 8 +++++++ src/renderer/components/pages/BrowsePage.tsx | 3 +++ src/renderer/components/pages/ConfigPage.tsx | 24 +++++++++++++++---- src/shared/Util.ts | 3 ++- src/shared/lang.ts | 2 ++ src/shared/preferences/util.ts | 4 +++- tests/unit/back/configuration.test.ts | 5 ++-- typings/flashpoint-launcher.d.ts | 2 ++ 33 files changed, 152 insertions(+), 53 deletions(-) diff --git a/.gitignore b/.gitignore index ef6f2ff47..fd445f0f8 100644 --- a/.gitignore +++ b/.gitignore @@ -34,7 +34,7 @@ npm-debug.log.* /flashpoint.sqlite /extensions/test /src/shared/version.ts -Data/flashpoint.sqlite +Data # Jest related files /.coveralls.yml diff --git a/lang/cs-CZ.json b/lang/cs-CZ.json index 6e295ba52..b94de4097 100644 --- a/lang/cs-CZ.json +++ b/lang/cs-CZ.json @@ -380,7 +380,8 @@ "openGameDataBrowser": "Otevřít prohlížeč herních dat", "notArchived": "Nearchivováno", "archived": "Archivováno", - "playOnline": "Hrát online" + "playOnline": "Hrát online", + "tagFilterIcon": "" }, "tags": { "name": "Název", @@ -403,7 +404,8 @@ "makeAliasWhenMerged": "Udělat z tohoto alias Štítku?", "deleteTag": "Odstranit Štítek", "deleteTagCategory": "Odstranit Kategorii Štítků", - "locked": "Uzamčeno během zpracovávání..." + "locked": "Uzamčeno během zpracovávání...", + "filterIcon": "" }, "curate": { "noCurationSelected": "Není vybrána žádná kurace", diff --git a/lang/de-DE.json b/lang/de-DE.json index f23998f44..acbe0a329 100644 --- a/lang/de-DE.json +++ b/lang/de-DE.json @@ -380,7 +380,8 @@ "openGameDataBrowser": "Spieldaten-Browser öffnen", "notArchived": "Nicht archiviert", "archived": "Archiviert", - "playOnline": "Online spielen" + "playOnline": "Online spielen", + "tagFilterIcon": "" }, "tags": { "name": "Name", @@ -403,7 +404,8 @@ "makeAliasWhenMerged": "Dies zum Alias des Tags machen?", "deleteTag": "Tag löschen", "deleteTagCategory": "Tag-Kategorie löschen", - "locked": "Während der Verarbeitung gesperrt..." + "locked": "Während der Verarbeitung gesperrt...", + "filterIcon": "" }, "curate": { "noCurationSelected": "Keine Kuration ausgewählt", diff --git a/lang/en.json b/lang/en.json index f0b49b493..283ed4656 100644 --- a/lang/en.json +++ b/lang/en.json @@ -381,7 +381,8 @@ "openGameDataBrowser": "Open Game Data Browser", "notArchived": "Not Archived", "archived": "Archived", - "playOnline": "Play Online" + "playOnline": "Play Online", + "tagFilterIcon": "Tag Filter Icon" }, "tags": { "name": "Name", @@ -404,7 +405,8 @@ "makeAliasWhenMerged": "Make this an alias of the tag?", "deleteTag": "Delete Tag", "deleteTagCategory": "Delete Tag Category", - "locked": "Locked while processing..." + "locked": "Locked while processing...", + "filterIcon": "Icon filename" }, "curate": { "noCurationSelected": "No Curation Selected", diff --git a/lang/es-ES.json b/lang/es-ES.json index 89dcd83da..e83752a1e 100644 --- a/lang/es-ES.json +++ b/lang/es-ES.json @@ -380,7 +380,8 @@ "openGameDataBrowser": "Open Game Data Browser", "notArchived": "Not Archived", "archived": "Archived", - "playOnline": "Play Online" + "playOnline": "Play Online", + "tagFilterIcon": "" }, "tags": { "name": "Nombre", @@ -403,7 +404,8 @@ "makeAliasWhenMerged": "¿Hacer esto una alias de la etiqueta?", "deleteTag": "Eliminar etiqueta", "deleteTagCategory": "Eliminar categoría de etiqueta", - "locked": "Bloqueado mientras se procesa..." + "locked": "Bloqueado mientras se procesa...", + "filterIcon": "" }, "curate": { "noCurationSelected": "Ninguna curación seleccionada", diff --git a/lang/et-EE.json b/lang/et-EE.json index e3599df4e..072012ea3 100644 --- a/lang/et-EE.json +++ b/lang/et-EE.json @@ -380,7 +380,8 @@ "openGameDataBrowser": "Ava Mängu Andmete Brauser", "notArchived": "Pole Arhiveeritud", "archived": "Arhiveeritud", - "playOnline": "Mängi võrgus" + "playOnline": "Mängi võrgus", + "tagFilterIcon": "" }, "tags": { "name": "Nimi", @@ -403,7 +404,8 @@ "makeAliasWhenMerged": "Kas muuta see uueks märksõna alternatiiviks?", "deleteTag": "Kustuta Märksõna", "deleteTagCategory": "Kustuta Märksõna Kategooria", - "locked": "Lukus protsessi ajal..." + "locked": "Lukus protsessi ajal...", + "filterIcon": "" }, "curate": { "noCurationSelected": "Ühtegi Kureeringut Pole Valitud", diff --git a/lang/fi-FI.json b/lang/fi-FI.json index efe0a7af3..553cd2a2f 100644 --- a/lang/fi-FI.json +++ b/lang/fi-FI.json @@ -380,7 +380,8 @@ "openGameDataBrowser": "Avaa Pelitietojen Selain", "notArchived": "Ei Arkistoitu", "archived": "Arkistoitu", - "playOnline": "Pelaa verkossa" + "playOnline": "Pelaa verkossa", + "tagFilterIcon": "" }, "tags": { "name": "Nimi", @@ -403,7 +404,8 @@ "makeAliasWhenMerged": "Tee tästä tunnisteen alias?", "deleteTag": "Poista tunniste", "deleteTagCategory": "Poista tunnistekategoria", - "locked": "Lukittu käsittelyn aikana..." + "locked": "Lukittu käsittelyn aikana...", + "filterIcon": "" }, "curate": { "noCurationSelected": "Ei Kuraatiota Valittu", diff --git a/lang/fr-FR.json b/lang/fr-FR.json index a516428f0..8dc969380 100644 --- a/lang/fr-FR.json +++ b/lang/fr-FR.json @@ -380,7 +380,8 @@ "openGameDataBrowser": "Ouvrir le navigateur de données du jeu", "notArchived": "Not Archived", "archived": "Archived", - "playOnline": "Play Online" + "playOnline": "Play Online", + "tagFilterIcon": "" }, "tags": { "name": "Nom", @@ -403,7 +404,8 @@ "makeAliasWhenMerged": "Faire un alias de ce tag ?", "deleteTag": "Supprimer le tag", "deleteTagCategory": "Supprimer la catégorie tag", - "locked": "Protégé pendant le traitement..." + "locked": "Protégé pendant le traitement...", + "filterIcon": "" }, "curate": { "noCurationSelected": "Aucune conservation sélectionnée", diff --git a/lang/hu-HU.json b/lang/hu-HU.json index 5a9bb674a..4108e65dd 100644 --- a/lang/hu-HU.json +++ b/lang/hu-HU.json @@ -380,7 +380,8 @@ "openGameDataBrowser": "Játékadat Böngésző Megnyitása", "notArchived": "Not Archived", "archived": "Archived", - "playOnline": "Play Online" + "playOnline": "Play Online", + "tagFilterIcon": "" }, "tags": { "name": "Név", @@ -403,7 +404,8 @@ "makeAliasWhenMerged": "Kíván nevet készíteni a címkéből?", "deleteTag": "Címke törlése", "deleteTagCategory": "Címke kategória törlése", - "locked": "Zárolva a feldolgozás alatt.." + "locked": "Zárolva a feldolgozás alatt..", + "filterIcon": "" }, "curate": { "noCurationSelected": "Nincsen kiválasztott Kurátor", diff --git a/lang/it-IT.json b/lang/it-IT.json index cd5c0f63b..430bab4ca 100644 --- a/lang/it-IT.json +++ b/lang/it-IT.json @@ -380,7 +380,8 @@ "openGameDataBrowser": "Apri il browser dei dati di gioco", "notArchived": "Non Archiviato", "archived": "Archiviato", - "playOnline": "Gioca in Rete" + "playOnline": "Gioca in Rete", + "tagFilterIcon": "" }, "tags": { "name": "Nome", @@ -403,7 +404,8 @@ "makeAliasWhenMerged": "Imposta come alias dell'etichetta?", "deleteTag": "Elimina l'Etichetta", "deleteTagCategory": "Elimina la Categoria Etichette", - "locked": "Bloccato durante l'elaborazione..." + "locked": "Bloccato durante l'elaborazione...", + "filterIcon": "" }, "curate": { "noCurationSelected": "Nessun Contenuto Curato Selezionato", diff --git a/lang/ja-JP.json b/lang/ja-JP.json index 75a04b1e2..2f829e465 100644 --- a/lang/ja-JP.json +++ b/lang/ja-JP.json @@ -380,7 +380,8 @@ "openGameDataBrowser": "ゲームデータブラウザを開く", "notArchived": "アーカイブに保存していない", "archived": "アーカイブに保存している", - "playOnline": "オンラインでプレイ" + "playOnline": "オンラインでプレイ", + "tagFilterIcon": "" }, "tags": { "name": "名前", @@ -403,7 +404,8 @@ "makeAliasWhenMerged": "タグのエイリアスにしますか?", "deleteTag": "タグを削除", "deleteTagCategory": "タグカテゴリを削除", - "locked": "処理中にロックしています..." + "locked": "処理中にロックしています...", + "filterIcon": "" }, "curate": { "noCurationSelected": "キュレーションが選択されていません", diff --git a/lang/mk-MK.json b/lang/mk-MK.json index 7d838731a..979b691c7 100644 --- a/lang/mk-MK.json +++ b/lang/mk-MK.json @@ -380,7 +380,8 @@ "openGameDataBrowser": "Отворете го прелистувачот за податоци за игри", "notArchived": "Не е Архивирано", "archived": "Архивиран", - "playOnline": "Играј online" + "playOnline": "Играј online", + "tagFilterIcon": "" }, "tags": { "name": "Име", @@ -403,7 +404,8 @@ "makeAliasWhenMerged": "Направи алијас од ознаката?", "deleteTag": "Избриши ознака", "deleteTagCategory": "Избриши ја Категоријата на Ознаката", - "locked": "Заклучено додека се обработува..." + "locked": "Заклучено додека се обработува...", + "filterIcon": "" }, "curate": { "noCurationSelected": "Никаква Курација Селектирана", diff --git a/lang/pl-PL.json b/lang/pl-PL.json index 5a542a37b..ac23db373 100644 --- a/lang/pl-PL.json +++ b/lang/pl-PL.json @@ -380,7 +380,8 @@ "openGameDataBrowser": "Otwórz przeglądarkę danych gry", "notArchived": "Nie zarchiwizowano", "archived": "Zarchiwizowano", - "playOnline": "Zagraj online" + "playOnline": "Zagraj online", + "tagFilterIcon": "" }, "tags": { "name": "Nazwa", @@ -403,7 +404,8 @@ "makeAliasWhenMerged": "Ustawić to jako alias tagu?", "deleteTag": "Usuń tag", "deleteTagCategory": "Usuń kategorię tagu", - "locked": "Zablokowano podczas przetwarzania..." + "locked": "Zablokowano podczas przetwarzania...", + "filterIcon": "" }, "curate": { "noCurationSelected": "Nie wybrano kuracji", diff --git a/lang/pt-BR.json b/lang/pt-BR.json index 6462c41a0..1e0162024 100644 --- a/lang/pt-BR.json +++ b/lang/pt-BR.json @@ -380,7 +380,8 @@ "openGameDataBrowser": "Abrir Navegador de Dados de Jogo", "notArchived": "Não Arquivado", "archived": "Arquivado", - "playOnline": "Jogar Online" + "playOnline": "Jogar Online", + "tagFilterIcon": "" }, "tags": { "name": "Nome", @@ -403,7 +404,8 @@ "makeAliasWhenMerged": "Tornar isso um apelido da tag?", "deleteTag": "Deletar Tag", "deleteTagCategory": "Deletar Categoria de Tag", - "locked": "Bloqueado durante o processamento..." + "locked": "Bloqueado durante o processamento...", + "filterIcon": "" }, "curate": { "noCurationSelected": "Nenhuma Curação Selecionada", diff --git a/lang/ro-RO.json b/lang/ro-RO.json index 9d6911764..eab829ea2 100644 --- a/lang/ro-RO.json +++ b/lang/ro-RO.json @@ -380,7 +380,8 @@ "openGameDataBrowser": "Explorați datele jocului", "notArchived": "Not Archived", "archived": "Arhivat", - "playOnline": "Jucați online" + "playOnline": "Jucați online", + "tagFilterIcon": "" }, "tags": { "name": "Nume", @@ -403,7 +404,8 @@ "makeAliasWhenMerged": "Sigur doriți să stabiliți acest pseudonim ca numele etichetei?", "deleteTag": "Ştergeți eticheta", "deleteTagCategory": "Ștergeți categoria de etichete", - "locked": "Blocate în timpul procesării..." + "locked": "Blocate în timpul procesării...", + "filterIcon": "" }, "curate": { "noCurationSelected": "Nicio reparație selectată", diff --git a/lang/ru-RU.json b/lang/ru-RU.json index 425cd8be6..165afb127 100644 --- a/lang/ru-RU.json +++ b/lang/ru-RU.json @@ -380,7 +380,8 @@ "openGameDataBrowser": "Открыть браузер игровых данных", "notArchived": "Не в архиве", "archived": "В архиве", - "playOnline": "Играть в браузере" + "playOnline": "Играть в браузере", + "tagFilterIcon": "" }, "tags": { "name": "Наименование", @@ -403,7 +404,8 @@ "makeAliasWhenMerged": "Сделать это псевдонимомом тега?", "deleteTag": "Удалить тег", "deleteTagCategory": "Удалить категорию тега", - "locked": "Заблокировано во время обработки..." + "locked": "Заблокировано во время обработки...", + "filterIcon": "" }, "curate": { "noCurationSelected": "Кураций не выбрано", diff --git a/lang/tr-TR.json b/lang/tr-TR.json index 19a7bc3dd..5c2ec6a62 100644 --- a/lang/tr-TR.json +++ b/lang/tr-TR.json @@ -380,7 +380,8 @@ "openGameDataBrowser": "Oyun Verileri Tarayıcısını Aç", "notArchived": "Arşivlenmedi", "archived": "Arşivlendi", - "playOnline": "Çevrim içi Oyna" + "playOnline": "Çevrim içi Oyna", + "tagFilterIcon": "" }, "tags": { "name": "Adı", @@ -403,7 +404,8 @@ "makeAliasWhenMerged": "Bunu etiketin takma bir ismi yap?", "deleteTag": "Etiketi Sil", "deleteTagCategory": "Etiket Kategorisini Sil", - "locked": "İşlenirken kilitlendi..." + "locked": "İşlenirken kilitlendi...", + "filterIcon": "" }, "curate": { "noCurationSelected": "Küratör Seçilmedi", diff --git a/lang/vi-VN.json b/lang/vi-VN.json index d8ae693b2..1bb5e3048 100644 --- a/lang/vi-VN.json +++ b/lang/vi-VN.json @@ -380,7 +380,8 @@ "openGameDataBrowser": "Mở trình duyệt dữ liệu trò chơi", "notArchived": "Not Archived", "archived": "Archived", - "playOnline": "Chơi trực tuyến" + "playOnline": "Chơi trực tuyến", + "tagFilterIcon": "" }, "tags": { "name": "Tên", @@ -403,7 +404,8 @@ "makeAliasWhenMerged": "Đặt làm tên khác của nhãn?", "deleteTag": "Xoá nhãn", "deleteTagCategory": "Xoá danh mục nhãn", - "locked": "Bị khoá khi đang xử lí..." + "locked": "Bị khoá khi đang xử lí...", + "filterIcon": "" }, "curate": { "noCurationSelected": "Chưa có bản đóng góp nào", diff --git a/lang/zh-CN.json b/lang/zh-CN.json index 96eba3d19..b55a027a8 100644 --- a/lang/zh-CN.json +++ b/lang/zh-CN.json @@ -380,7 +380,8 @@ "openGameDataBrowser": "打开游戏数据浏览器", "notArchived": "未存档", "archived": "已存档", - "playOnline": "在线播放" + "playOnline": "在线播放", + "tagFilterIcon": "" }, "tags": { "name": "名称", @@ -403,7 +404,8 @@ "makeAliasWhenMerged": "设置为标签的别名吗?", "deleteTag": "删除标签", "deleteTagCategory": "删除标签类别", - "locked": "处理过程中暂时锁定..." + "locked": "处理过程中暂时锁定...", + "filterIcon": "" }, "curate": { "noCurationSelected": "未选择展品", diff --git a/lang/zh-TW.json b/lang/zh-TW.json index a30c9b640..9a0f3d974 100644 --- a/lang/zh-TW.json +++ b/lang/zh-TW.json @@ -380,7 +380,8 @@ "openGameDataBrowser": "Open Game Data Browser", "notArchived": "Not Archived", "archived": "Archived", - "playOnline": "Play Online" + "playOnline": "Play Online", + "tagFilterIcon": "" }, "tags": { "name": "名稱", @@ -403,7 +404,8 @@ "makeAliasWhenMerged": "將此標籤設為該標籤的別名嗎?", "deleteTag": "刪除標籤", "deleteTagCategory": "刪除標籤類別", - "locked": "系統處理時將鎖定操作..." + "locked": "系統處理時將鎖定操作...", + "filterIcon": "" }, "curate": { "noCurationSelected": "未選取任何典藏作品。", diff --git a/package-lock.json b/package-lock.json index 5d48e6ee6..44ba772c6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "flashpoint-launcher", - "version": "13.0.1", + "version": "13.0.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "flashpoint-launcher", - "version": "13.0.1", + "version": "13.0.2", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/src/renderer/components/GameGrid.tsx b/src/renderer/components/GameGrid.tsx index 50f088f02..a23c6bdb9 100644 --- a/src/renderer/components/GameGrid.tsx +++ b/src/renderer/components/GameGrid.tsx @@ -9,6 +9,8 @@ import { GameGridItem } from './GameGridItem'; import { GameItemContainer } from './GameItemContainer'; import { GameDragEventData } from './pages/BrowsePage'; import { ScreenshotPreviewMode } from '@shared/BrowsePageLayout'; +import { TagFilter } from 'flashpoint-launcher'; +import { getFileServerURL } from '@shared/Util'; const RENDERER_OVERSCAN = 5; @@ -36,6 +38,8 @@ export type GameGridProps = { cellHeight: number; /** List of Extreme tags */ extremeTags: string[]; + /** Tag Filter icons */ + tagGroupIcons: { tagFilter: TagFilter; iconPath: string; }[]; /** Function that renders the elements to show instead of the grid if there are no games (render prop). */ noRowsRenderer?: () => JSX.Element; /** Called when the user attempts to select a game. */ @@ -191,6 +195,7 @@ export class GameGrid extends React.Component { const index = props.rowIndex * this.columns + props.columnIndex; if (index < (gamesTotal || 0)) { const game = games[index]; + const tagGroupIcon = this.props.tagGroupIcons.find(tg => tg.tagFilter.find(t => game?.tags.includes(t)))?.iconPath; return ( { platforms={game ? [game.primaryPlatform] : []} extreme={game ? game.tags.findIndex(t => this.props.extremeTags.includes(t.trim())) !== -1 : false} extremeIconPath={extremeIconPath} + tagGroupIconPath={tagGroupIcon ? `${getFileServerURL()}/logos/${tagGroupIcon}?version=${this.props.logoVersion}` : '' } thumbnail={game ? getGameImageURL(LOGOS, game.id) : ''} screenshot={game ? getGameImageURL(SCREENSHOTS, game.id) : ''} screenshotPreviewMode={this.props.screenshotPreviewMode} diff --git a/src/renderer/components/GameGridItem.tsx b/src/renderer/components/GameGridItem.tsx index e0080ab3a..001373b48 100644 --- a/src/renderer/components/GameGridItem.tsx +++ b/src/renderer/components/GameGridItem.tsx @@ -24,6 +24,8 @@ export type GameGridItemProps = Partial & { isDragged: boolean; /** Path to the extreme icon */ extremeIconPath: string; + /** Icon for games in tag categories */ + tagGroupIconPath: string; /** On Drop event */ onDrop?: (event: React.DragEvent) => void; /** Screenshot Preview Mode */ @@ -55,7 +57,7 @@ export function GameGridItem(props: GameGridItemProps) { } }, [isHovered]); - const { rowIndex, id, title, platforms, thumbnail, screenshot, extreme, isDraggable, isSelected, isDragged, extremeIconPath, style, onDrop } = props; + const { rowIndex, id, title, platforms, thumbnail, screenshot, extreme, tagGroupIconPath, isDraggable, isSelected, isDragged, extremeIconPath, style, onDrop } = props; // Get the platform icon path const platformIcons = React.useMemo(() => platforms.slice(0, 5).map(p => getPlatformIconURL(p, props.logoVersion)) @@ -93,7 +95,13 @@ export function GameGridItem(props: GameGridItemProps) { className='game-grid-item__thumb__icons__icon' style={{ backgroundImage: `url('${extremeIconPath}')` }} /> - ) : undefined } + ) : (tagGroupIconPath ? ( +
+
+
+ ) : undefined )}
{platformIcons.map(p => (
= (instance: T | null) => void; @@ -32,6 +34,8 @@ export type OwnProps = { showExtremeIcon: boolean; /** Extreme Tag Filters */ extremeTags: string[]; + /** Tag Filter icons */ + tagGroupIconPath: { tagFilter: TagFilter; iconPath: string; }[]; /** Function that renders the elements to show instead of the grid if there are no games (render prop). */ noRowsRenderer?: () => JSX.Element; /** Called when the user attempts to select a game. */ @@ -193,6 +197,7 @@ class _GameList extends React.Component { if (!games) { throw new Error('Trying to render a row in game list, but no games are found?'); } const game = games[cellProps.index]; const platform = game?.primaryPlatform; + const tagGroupIcon = this.props.tagGroupIconPath.find(tg => tg.tagFilter.find(t => game?.tags.includes(t)))?.iconPath; return game ? ( { extreme={game.tags.findIndex(t => this.props.extremeTags.includes(t.trim())) !== -1} extremeIconPath={extremeIconPath} showExtremeIcon={showExtremeIcon} + tagGroupIconPath={tagGroupIcon ? `${getFileServerURL()}/logos/${tagGroupIcon}?version=${this.props.logoVersion}` : '' } logoVersion={this.props.logoVersion} isDraggable={true} isSelected={game.id === selectedGameId} diff --git a/src/renderer/components/GameListItem.tsx b/src/renderer/components/GameListItem.tsx index 2369a41af..9ed5afd72 100644 --- a/src/renderer/components/GameListItem.tsx +++ b/src/renderer/components/GameListItem.tsx @@ -24,13 +24,15 @@ export type GameListItemProps = ListRowProps & { isDragged: boolean; /** Path to the extreme icon */ extremeIconPath: string; + /** Icon for games in tag categories */ + tagGroupIconPath: string; /** Game drag event */ onDrop?: (event: React.DragEvent) => void; onDragOver?: (event: React.DragEvent) => void; }; export function GameListItem(props: GameListItemProps) { - const { id, title, platform, tags, developer, publisher, extreme, isDraggable, isSelected, isDragged, extremeIconPath, showExtremeIcon, index, style, onDrop, + const { id, title, platform, tags, developer, publisher, extreme, tagGroupIconPath, isDraggable, isSelected, isDragged, extremeIconPath, showExtremeIcon, index, style, onDrop, onDragOver } = props; // Get the platform icon path const platformIcon = React.useMemo(() => ( @@ -64,9 +66,13 @@ export function GameListItem(props: GameListItemProps) {
+ ) : (tagGroupIconPath ? ( +
) : (
- )) + ))) }
void; onChangeDescription: (description: string) => void; onToggleExtreme: (checked: boolean) => void; + onChangeIconPath: (iconPath: string) => void; closeEditor: () => void; showExtreme: boolean; tagCategories: TagCategory[]; @@ -138,6 +139,13 @@ export function TagFilterGroupEditor(props: TagFilterGroupEditorProps) { onTagSubmit={(tag) => onTagSubmit(tag)} />
+
+ {strings.tags.filterIcon} +
+ props.onChangeIconPath(event.target.value)} + text={props.tagFilterGroup.iconPath}/>
);}, [parsedTagsList, editTag, tagSuggestions, props.tagCategories, onAddTag, onRemoveTag, onTagSubmit, updateSuggestions]); } diff --git a/src/renderer/components/pages/BrowsePage.tsx b/src/renderer/components/pages/BrowsePage.tsx index b3e8fb4b9..529958b5f 100644 --- a/src/renderer/components/pages/BrowsePage.tsx +++ b/src/renderer/components/pages/BrowsePage.tsx @@ -184,6 +184,7 @@ export class BrowsePage extends React.Component !t.enabled && t.extreme).reduce((prev, cur) => prev.concat(cur.tags), []); + const tagGroupIcons = this.props.preferencesData.tagFilters.filter(t => !t.enabled && t.iconPath !== '').map(({tags, iconPath: tagGroupIcon}) => ({tagFilter:tags, iconPath:tagGroupIcon})); // Render return (
this.onRemoveTagEditorCategoryEvent(this.state.editingTagFilterGroupIdx || -1, category)} onChangeName={this.onChangeTagEditorNameEvent} onChangeDescription={this.onChangeTagEditorDescriptionEvent} + onChangeIconPath={this.onChangeTagEditorIconPathEvent} onToggleExtreme={this.onToggleExtremeTagEditorEvent} closeEditor={this.onCloseTagFilterGroupEditor} showExtreme={this.props.preferencesData.browsePageShowExtreme} @@ -602,11 +603,18 @@ export class ConfigPage extends React.Component - ) : ( + ) : (item.iconPath ? ( +
+ ) : + (
- )) + ))) }
{ + if (this.state.editingTagFilterGroup) { + const newTFG = {...this.state.editingTagFilterGroup, iconPath }; + this.setState({ editingTagFilterGroup: newTFG }); + } + }; + onDuplicateTagFilterGroup = (index: number): void => { const newTagFilters = [...this.props.preferencesData.tagFilters]; newTagFilters.push({...newTagFilters[index], name: `${newTagFilters[index].name} - Copy`}); diff --git a/src/shared/Util.ts b/src/shared/Util.ts index 56c0d5744..be6ac1ef9 100644 --- a/src/shared/Util.ts +++ b/src/shared/Util.ts @@ -460,7 +460,8 @@ export function generateTagFilterGroup(tags?: string[]): TagFilterGroup { extreme: false, tags: tags || [], categories: [], - childFilters: [] + childFilters: [], + iconPath: '' }; } diff --git a/src/shared/lang.ts b/src/shared/lang.ts index 134072804..6eef58222 100644 --- a/src/shared/lang.ts +++ b/src/shared/lang.ts @@ -394,6 +394,7 @@ const langTemplate = { 'showExtremeScreenshot', 'busy', 'openGameDataBrowser', + 'tagFilterIcon' ] as const, tags: [ 'name', @@ -417,6 +418,7 @@ const langTemplate = { 'deleteTag', 'deleteTagCategory', 'locked', + 'filterIcon', ] as const, curate: [ 'noCurationSelected', diff --git a/src/shared/preferences/util.ts b/src/shared/preferences/util.ts index 2589c50ea..7c7253718 100644 --- a/src/shared/preferences/util.ts +++ b/src/shared/preferences/util.ts @@ -372,7 +372,8 @@ function parseTagFilterGroup(parser: IObjectParserProp): TagFilt tags: [], categories: [], childFilters: [], - extreme: false + extreme: false, + iconPath: '' }; parser.prop('name', v => tfg.name = str(v)); parser.prop('description', v => tfg.description = str(v)); @@ -381,6 +382,7 @@ function parseTagFilterGroup(parser: IObjectParserProp): TagFilt parser.prop('categories').arrayRaw((item) => tfg.categories.push(str(item))); parser.prop('childFilters').arrayRaw((item) => tfg.childFilters.push(str(item))); parser.prop('extreme', v => tfg.extreme = !!v); + parser.prop('iconPath', v => tfg.iconPath = str(v)); return tfg; } diff --git a/tests/unit/back/configuration.test.ts b/tests/unit/back/configuration.test.ts index 114958015..afef25449 100644 --- a/tests/unit/back/configuration.test.ts +++ b/tests/unit/back/configuration.test.ts @@ -115,9 +115,10 @@ describe('Configuration Files', () => { 'tags': [ 'Action' ], - 'categories': [ 'test' ], + 'categories': ['test'], 'childFilters': [], - 'extreme': false + 'extreme': false, + iconPath: '' } ], 'tagFiltersInCurate': true, diff --git a/typings/flashpoint-launcher.d.ts b/typings/flashpoint-launcher.d.ts index a67705f7f..bdc05c2f6 100644 --- a/typings/flashpoint-launcher.d.ts +++ b/typings/flashpoint-launcher.d.ts @@ -918,6 +918,8 @@ declare module 'flashpoint-launcher' { childFilters: string[]; /** Are these tags considered Extreme? */ extreme: boolean; + /** Custon icon */ + iconPath: string; } export type TagFilter = string[];