Skip to content

Commit

Permalink
feat: added start menu tiles updating system
Browse files Browse the repository at this point in the history
  • Loading branch information
Tormak9970 committed Feb 27, 2024
1 parent 90ce315 commit f8d80e5
Show file tree
Hide file tree
Showing 11 changed files with 176 additions and 70 deletions.
4 changes: 2 additions & 2 deletions src/components/Footer.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { open } from "@tauri-apps/api/shell";
import { AppController } from "../lib/controllers/AppController";
import { canSave, isOnline } from "../stores/AppState";
import { showManualGamesModal, showBatchApplyModal, showCleanGridsModal, showSettingsModal, showInfoModal, showTilesModal } from "../stores/Modals";
import { showManualGamesModal, showBatchApplyModal, showCleanGridsModal, showSettingsModal, showInfoModal, showUpdateTilesModal } from "../stores/Modals";
import Button from "./interactables/Button.svelte";
import IconButton from "./interactables/IconButton.svelte";
import { DialogController } from "../lib/controllers/DialogController";
Expand Down Expand Up @@ -62,7 +62,7 @@
</svg>
</IconButton>
<Spacer orientation="HORIZONTAL" />
<IconButton label="Edit Game Tiles" onClick={() => { $showTilesModal = true; }} width="auto" tooltipPosition="auto">
<IconButton label="Update Game Tiles" onClick={() => { $showUpdateTilesModal = true; }} width="auto" tooltipPosition="auto">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 12px; width: 12px;">
<!--!Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.-->
<path d="M288 448H64V224h64V160H64c-35.3 0-64 28.7-64 64V448c0 35.3 28.7 64 64 64H288c35.3 0 64-28.7 64-64V384H288v64zm-64-96H448c35.3 0 64-28.7 64-64V64c0-35.3-28.7-64-64-64H224c-35.3 0-64 28.7-64 64V288c0 35.3 28.7 64 64 64z"/>
Expand Down
2 changes: 1 addition & 1 deletion src/components/core/games/GameEntry.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import { renderGamesInList } from "../../../stores/AppState";
import ListEntry from "./list-view/ListEntry.svelte";
import GridEntry from "./grid-view/GridEntry.svelte";
import { currentGridsAppid, showCurrentGridsModal } from "../../../stores/Modals";
import { currentGridsAppid, showCurrentGridsModal } from "../../../stores/Modals";
export let game: GameStruct;
Expand Down
133 changes: 133 additions & 0 deletions src/components/modals/UpdateTilesModal.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
<script lang="ts">
import { showUpdateTilesModal } from "../../stores/Modals";
import { appLibraryCache, manualSteamGames, originalAppLibraryCache, steamGames } from "../../stores/AppState";
import { AppController } from "../../lib/controllers/AppController";
import { ToastController } from "../../lib/controllers/ToastController";
import { LogController } from "../../lib/controllers/LogController";
import { onMount } from "svelte";
import Button from "../interactables/Button.svelte";
import Spacer from "../layout/Spacer.svelte";
import ModalBody from "./modal-utils/ModalBody.svelte";
import GameFilter from "./modal-utils/game-filter/GameFilter.svelte";
let appsWithTilesIds: string[];
let appsWithTiles: Record<string, string>;
let filteredSteamGames: GameStruct[] = [];
let selectedGameIds: string[] = [];
/**
* The function to run when the modal closes.
*/
function onClose(): void {
$showUpdateTilesModal = false;
}
/**
* Updates the tile for the chosen games
*/
async function updateGameTiles(): Promise<void> {
const appIconEntries = selectedGameIds.map((appid) => [ appid, $appLibraryCache[appid].Icon ]);
const appIconsMap = Object.fromEntries(appIconEntries);
const appTilePathEntries = selectedGameIds.map((appid) => [ appid, appsWithTiles[appid] ]);
const appTilePathsMap = Object.fromEntries(appTilePathEntries);
const failedIds = await AppController.updateAppTiles(appIconsMap, appTilePathsMap);
if (failedIds.length > 0) {
LogController.error(`Failed to update ${failedIds.length} tiles. Ids that failed: ${JSON.stringify(failedIds)}.`);
ToastController.showWarningToast(`Failed to update ${failedIds.length} tiles!`)
} else {
LogController.log(`Updated ${selectedGameIds.length} tiles.`);
ToastController.showSuccessToast(`Updated ${selectedGameIds.length} tiles`);
onClose();
}
}
onMount(() => {
AppController.getAppTiles().then((appTiles) => {
appsWithTilesIds = Object.keys(appTiles);
appsWithTiles = appTiles;
const tilesFilter = (game: GameStruct) => {
return appsWithTilesIds.includes(game.appid.toString());
}
// TODO: potentially diff the images to determine if this has been applied before.
const gameIconChangedFilter = (game: GameStruct) => {
return $appLibraryCache[game.appid].Icon !== $originalAppLibraryCache[game.appid].Icon;
}
filteredSteamGames = [ ...$steamGames, ...$manualSteamGames ].filter(gameIconChangedFilter).filter(tilesFilter);
});
});
</script>

<ModalBody title={"Update Start Menu Tiles"} onClose={onClose}>
<div class="content">
<Spacer orientation="VERTICAL" />
<div class="description">
Here you can batch update the game icons shown in your Operating System's start menu to match your custom icons shown in steam.
<br/>
<br/>
Games that show up below are the result of the following filters:
<br/>
<ul>
<li>You already have a Start Menu shortcut for this game.</li>
<li>You have changed the icon for this game.</li>
</ul>
</div>
<Spacer orientation="VERTICAL" />
<Spacer orientation="VERTICAL" />
<div class="view">
<GameFilter steamGames={filteredSteamGames} bind:selectedGameIds={selectedGameIds} showPlatforms={false} showFilters={false} noGamesMessage={"No games with tiles/new icons were found."}/>
</div>
<div class="buttons">
<Button label="Update" onClick={updateGameTiles} width="47.5%" disabled={selectedGameIds.length === 0} />
<Button label="Cancel" onClick={onClose} width="47.5%" />
</div>
</div>
</ModalBody>

<style>
.content {
width: 600px;
height: calc(100% - 60px);
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
}
.description {
width: calc(100% - 14px);
font-size: 14px;
}
.description ul {
margin: 0px;
padding-left: 20px;
font-size: 13px;
}
.description li {
margin-top: 4px;
}
.view {
width: 100%;
}
.buttons {
margin-top: 14px;
margin-bottom: 7px;
width: 100%;
display: flex;
justify-content: space-around;
justify-self: flex-end;
}
</style>
10 changes: 6 additions & 4 deletions src/components/modals/batch-apply/BatchApplyModal.svelte
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
<script lang="ts">
import { GridTypes, gridType } from "../../../stores/AppState";
import { GridTypes, gridType, manualSteamGames, nonSteamGames, steamGames } from "../../../stores/AppState";
import Button from "../../interactables/Button.svelte";
import { AppController } from "../../../lib/controllers/AppController";
import { ToastController } from "../../../lib/controllers/ToastController";
import ModalBody from "../modal-utils/ModalBody.svelte";
import GameFilter from "../modal-utils/game-filter/GameFilter.svelte";
import { showBatchApplyModal, showBatchApplyProgress } from "../../../stores/Modals";
$: allSteamGames = [ ...$steamGames, ...$manualSteamGames ];
let selectedGameIds: string[] = [];
/**
* The function to run when the modal closes.
*/
function onClose(): void {
$showBatchApplyModal = false;
}
let selectedGameIds: string[] = [];
/**
* Batch applies grids to all games.
*/
Expand All @@ -39,7 +41,7 @@
<div class="info">
Choose the games you would like to batch apply grids to.
</div>
<GameFilter bind:selectedGameIds={selectedGameIds} />
<GameFilter steamGames={allSteamGames} nonSteamGames={$nonSteamGames} bind:selectedGameIds={selectedGameIds} />
<div class="buttons">
<Button label="Apply" onClick={batchApply} width="47.5%" />
<Button label="Cancel" onClick={cancel} width="47.5%" />
Expand Down
18 changes: 10 additions & 8 deletions src/components/modals/clean-grids/CleanGridsModal.svelte
Original file line number Diff line number Diff line change
@@ -1,19 +1,14 @@
<script lang="ts">
import { AppController } from "../../../lib/controllers/AppController";
import { showCleanGridsModal } from "../../../stores/Modals";
import { selectedCleanGridsPreset } from "../../../stores/AppState";
import { manualSteamGames, nonSteamGames, selectedCleanGridsPreset, steamGames } from "../../../stores/AppState";
import Button from "../../interactables/Button.svelte";
import DropDown from "../../interactables/DropDown.svelte";
import Spacer from "../../layout/Spacer.svelte";
import ModalBody from "../modal-utils/ModalBody.svelte";
import GameFilter from "../modal-utils/game-filter/GameFilter.svelte";
/**
* The function to run when the modal closes.
*/
function onClose(): void {
$showCleanGridsModal = false;
}
$: allSteamGames = [ ...$steamGames, ...$manualSteamGames ];
let presets = [
{ label: "Clean", data: "clean" },
Expand All @@ -22,6 +17,13 @@
let selectedGameIds: string[] = [];
/**
* The function to run when the modal closes.
*/
function onClose(): void {
$showCleanGridsModal = false;
}
/**
* Cleans out the undesired grids.
*/
Expand Down Expand Up @@ -57,7 +59,7 @@
<Spacer orientation="VERTICAL" />
<div class="view">
{#if $selectedCleanGridsPreset === "custom"}
<GameFilter bind:selectedGameIds={selectedGameIds} showFilters={false}/>
<GameFilter steamGames={allSteamGames} nonSteamGames={$nonSteamGames} bind:selectedGameIds={selectedGameIds} showFilters={false}/>
{/if}
</div>
<div class="buttons">
Expand Down
24 changes: 15 additions & 9 deletions src/components/modals/modal-utils/game-filter/GameFilter.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts">
import { Platforms, appLibraryCache, gridType, hiddenGameIds, manualSteamGames, nonSteamGames, steamGames } from "../../../../stores/AppState";
import { Platforms, appLibraryCache, gridType, hiddenGameIds } from "../../../../stores/AppState";
import { AppController } from "../../../../lib/controllers/AppController";
import DropDown from "../../../interactables/DropDown.svelte";
import SelectedGameEntry from "./SelectedGameEntry.svelte";
Expand All @@ -10,9 +10,14 @@
export let selectedGameIds: string[];
export let showFilters = true;
export let showPlatforms = true;
export let steamGames: GameStruct[];
export let nonSteamGames: GameStruct[] = [];
export let selectedPlatform = "All";
export let selectedGamesFilter = "All";
export let noGamesMessage = "No games matched the selected filters.";
$: allSteamGames = [ ...$steamGames, ...$manualSteamGames ];
$: allGames = [ ...allSteamGames, ...$nonSteamGames ];
$: allGames = [ ...steamGames, ...nonSteamGames ];
let platforms: { label: string, data: string}[] = Object.values(Platforms).map((platform) => {
return {
Expand All @@ -24,15 +29,12 @@
label: "All",
data: "All"
});
let selectedPlatform = "All";
let gameFilters = [
{ label: "All", data: "All" },
{ label: "Missing", data: "Missing" }
];
let selectedGamesFilter = "All";
// let gamesToFilter = (selectedPlatform === "All" ? allGames : (selectedPlatform === Platforms.STEAM ? allSteamGames : $nonSteamGames)).filter((game) => !includeHidden ? !$hiddenGameIds.includes(game.appid) : true);
let gamesToFilter = [];
let selectedGames = {};
let includeHidden = false;
Expand All @@ -44,7 +46,7 @@
* @param showHidden Whether to include hidden games or not.
*/
function onStateChange(platform: string, gameFilter: string, showHidden: boolean): void {
gamesToFilter = (platform === "All" ? allGames : (platform === Platforms.STEAM ? allSteamGames : $nonSteamGames)).filter((game) => !showHidden ? !$hiddenGameIds.includes(game.appid) : true);
gamesToFilter = (platform === "All" ? allGames : (platform === Platforms.STEAM ? steamGames : nonSteamGames)).filter((game) => !showHidden ? !$hiddenGameIds.includes(game.appid) : true);
const selectedGameEntries = gamesToFilter.map((game) => {
return [ game.appid, gameFilter === "All" ? true : (!$appLibraryCache[game.appid][$gridType]) ];
});
Expand Down Expand Up @@ -72,7 +74,9 @@
<div class="game-filter">
<div class="options">
<div class="dropdowns">
<DropDown label="Platforms" options={platforms} bind:value={selectedPlatform} width="100px" onChange={(platform) => { onStateChange(platform, selectedGamesFilter, includeHidden); }} showTooltip={false} />
{#if showPlatforms}
<DropDown label="Platforms" options={platforms} bind:value={selectedPlatform} width="100px" onChange={(platform) => { onStateChange(platform, selectedGamesFilter, includeHidden); }} showTooltip={false} />
{/if}
{#if showFilters}
<DropDown label="Filters" options={gameFilters} bind:value={selectedGamesFilter} width="100px" onChange={(gamesFilter) => { onStateChange(selectedPlatform, gamesFilter, includeHidden); }} showTooltip={false} />
{/if}
Expand All @@ -93,7 +97,9 @@
</span>
<span slot="data">
{#each gamesToFilter as game, i (`${game.appid}|${i}`)}
<SelectedGameEntry game={game} platform={selectedPlatform !== "All" ? selectedPlatform : (allSteamGames.some((steamGame) => steamGame.appid === game.appid) ? Platforms.STEAM : Platforms.NON_STEAM)} isChecked={!!selectedGames[game.appid]} onChange={onEntryChange} />
<SelectedGameEntry game={game} platform={selectedPlatform !== "All" ? selectedPlatform : (steamGames.some((steamGame) => steamGame.appid === game.appid) ? Platforms.STEAM : Platforms.NON_STEAM)} isChecked={!!selectedGames[game.appid]} onChange={onEntryChange} />
{:else}
<div>{noGamesMessage}</div>
{/each}
</span>
</Table>
Expand Down
16 changes: 0 additions & 16 deletions src/components/modals/tiles/TilesInfoModal.svelte

This file was deleted.

16 changes: 0 additions & 16 deletions src/components/modals/tiles/TilesModal.svelte

This file was deleted.

6 changes: 3 additions & 3 deletions src/lib/controllers/AppController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -556,12 +556,12 @@ export class AppController {
}

/**
* Sets the current app icons to their app tiles.
* Updates the current app tiles to their app icons.
* @param appIconsPaths The record of appid -> iconPath.
* @param appTilePaths The record of appid -> tilePath.
* @returns An array containing the ids of any tiles that failed to be updated
* @returns An array containing the ids of any tiles that failed to be updated.
*/
static async setAppTiles(appIconsPaths: Record<string, string>, appTilePaths: Record<string, string>): Promise<string[]> {
static async updateAppTiles(appIconsPaths: Record<string, string>, appTilePaths: Record<string, string>): Promise<string[]> {
return await RustInterop.writeAppTiles(appIconsPaths, appTilePaths);
}

Expand Down
3 changes: 1 addition & 2 deletions src/stores/Modals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,4 @@ export const showInfoModal = writable(false);
export const showCurrentGridsModal = writable(false);
export const currentGridsAppid = writable(null);

export const showTilesModal = writable(false);
export const showTilesInfoModal = writable(false);
export const showUpdateTilesModal = writable(false);
Loading

0 comments on commit f8d80e5

Please sign in to comment.