From 9ebe31d0d6623c9de74e294fa74c1a1400e43cdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antti=20M=C3=A4ki?= Date: Thu, 6 Oct 2022 12:33:27 +0300 Subject: [PATCH 1/2] Refactor FolderMigration Attempt to improve code quality, although most of the changes are subjective. Move the migration check into Vuex store so it doesn't get called multiple times now that the game selection screen can be accessed without restarting the app. The cache cleaning was removed, since it failed if the old directory structure was still used: it tried to read the profiles from a non- existing dir. Refs TS-1138 --- src/migrations/FolderMigration.ts | 34 ++++++++---- src/pages/GameSelectionScreen.vue | 92 +++++++++++++------------------ src/store/index.ts | 18 ++++++ 3 files changed, 78 insertions(+), 66 deletions(-) diff --git a/src/migrations/FolderMigration.ts b/src/migrations/FolderMigration.ts index ce9889b92..2fc65c563 100644 --- a/src/migrations/FolderMigration.ts +++ b/src/migrations/FolderMigration.ts @@ -1,25 +1,35 @@ -import PathResolver from '../r2mm/manager/PathResolver'; import * as path from 'path'; import FsProvider from '../providers/generic/file/FsProvider'; +import PathResolver from '../r2mm/manager/PathResolver'; import FileUtils from '../utils/FileUtils'; -import CacheUtil from '../r2mm/mods/CacheUtil'; -export default class FolderMigration { +/** + * Mod directory structure was changed when support for other games + * besides RoR2 was added. Update the dir structure if the old one is + * still in use. + */ +export class FolderMigration { - public static async needsMigration(): Promise { + public static async needsMigration() { const fs = FsProvider.instance; return await fs.exists(path.join(PathResolver.ROOT, "mods")); } - public static async runMigration(): Promise { - console.log("Started migration"); + public static async runMigration() { + if (!await this.needsMigration()) { + return; + } + + console.log("Started legacy directory migration"); const fs = FsProvider.instance; - await CacheUtil.clean(); - if ((await fs.exists(path.join(PathResolver.ROOT, "RiskOfRain2")))) { - await FileUtils.emptyDirectory(path.join(PathResolver.ROOT, "RiskOfRain2")); - await fs.rmdir(path.join(PathResolver.ROOT, "RiskOfRain2")); + const rorPath = path.join(PathResolver.ROOT, "RiskOfRain2"); + + if (await fs.exists(rorPath)) { + await FileUtils.emptyDirectory(rorPath); + await fs.rmdir(rorPath); } - await fs.rename(path.join(PathResolver.ROOT, "mods"), path.join(PathResolver.ROOT, "RiskOfRain2")); - } + await fs.rename(path.join(PathResolver.ROOT, "mods"), rorPath); + console.log("Directory migration done"); + } } diff --git a/src/pages/GameSelectionScreen.vue b/src/pages/GameSelectionScreen.vue index f77a94148..800fb01f7 100644 --- a/src/pages/GameSelectionScreen.vue +++ b/src/pages/GameSelectionScreen.vue @@ -27,7 +27,7 @@

An update to the manager has occurred and needs to do background work.

-

The option to select a game will appear once the work has completed.

+

The options to select a game are disabled until the work has completed.

@@ -180,7 +180,6 @@ import { Component, Vue } from 'vue-property-decorator'; import Game from '../model/game/Game'; import GameManager from '../model/game/GameManager'; import Hero from '../components/Hero.vue'; -import FolderMigration from '../migrations/FolderMigration'; import PathResolver from '../r2mm/manager/PathResolver'; import * as path from 'path'; import FileUtils from '../utils/FileUtils'; @@ -385,61 +384,46 @@ export default class GameSelectionScreen extends Vue { } } - created() { - const self = this; + async created() { this.runningMigration = true; - FolderMigration.needsMigration() - .then(isMigrationRequired => { - if (!isMigrationRequired) { - this.runningMigration = false; - } else { - return FolderMigration.runMigration(); - } - }) - .then(() => { - this.runningMigration = false; - }) - .catch((e) => { - console.log(e); - this.runningMigration = false; - }) - .finally(() => { - ManagerSettings.getSingleton(GameManager.unsetGame()).then(settings => { - const lastSelectedGame = settings.getContext().global.lastSelectedGame; - const savedViewMode = settings.getContext().global.gameSelectionViewMode; - switch (savedViewMode) { - case "List": this.viewMode = GameSelectionViewMode.LIST; break; - case "Card": - case undefined: - this.viewMode = GameSelectionViewMode.CARD; - break; - } - if (lastSelectedGame !== null) { - const game = GameManager.gameList.find(value => value.internalFolderName === lastSelectedGame); - if (game !== undefined) { - this.selectedGame = game; - } + await this.$store.dispatch('checkMigrations'); + this.runningMigration = false; + + ManagerSettings.getSingleton(GameManager.unsetGame()).then(settings => { + const lastSelectedGame = settings.getContext().global.lastSelectedGame; + const savedViewMode = settings.getContext().global.gameSelectionViewMode; + switch (savedViewMode) { + case "List": this.viewMode = GameSelectionViewMode.LIST; break; + case "Card": + case undefined: + this.viewMode = GameSelectionViewMode.CARD; + break; + } + if (lastSelectedGame !== null) { + const game = GameManager.gameList.find(value => value.internalFolderName === lastSelectedGame); + if (game !== undefined) { + this.selectedGame = game; } - }); - ManagerSettings.getSingleton(GameManager.unsetGame()).then(value => { - this.settings = value; - this.favourites = value.getContext().global.favouriteGames || []; - if (value.getContext().global.defaultGame !== undefined) { - if (value.getContext().global.defaultStore !== undefined) { - const game = GameManager.gameList - .find(value1 => value1.internalFolderName === value.getContext().global.defaultGame)!; - - const platform = game.storePlatformMetadata.find(value1 => value1.storePlatform === value.getContext().global.defaultStore)!; - - this.selectedGame = game; - this.selectedPlatform = platform.storePlatform; - - this.proceed(); - return; - } + } + }); + ManagerSettings.getSingleton(GameManager.unsetGame()).then(value => { + this.settings = value; + this.favourites = value.getContext().global.favouriteGames || []; + if (value.getContext().global.defaultGame !== undefined) { + if (value.getContext().global.defaultStore !== undefined) { + const game = GameManager.gameList + .find(value1 => value1.internalFolderName === value.getContext().global.defaultGame)!; + + const platform = game.storePlatformMetadata.find(value1 => value1.storePlatform === value.getContext().global.defaultStore)!; + + this.selectedGame = game; + this.selectedPlatform = platform.storePlatform; + + this.proceed(); + return; } - }); - }) + } + }); } toggleViewMode() { diff --git a/src/store/index.ts b/src/store/index.ts index 55dcb2481..2a48928e0 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -1,5 +1,6 @@ import Vue from 'vue'; import Vuex from 'vuex'; +import { FolderMigration } from '../migrations/FolderMigration'; // import example from './module-example' @@ -16,6 +17,7 @@ export default function(/* { ssrContext } */) { localModList: [], thunderstoreModList: [], dismissedUpdateAll: false, + isMigrationChecked: false, apiConnectionError: "" }, actions: { @@ -30,6 +32,19 @@ export default function(/* { ssrContext } */) { }, updateApiConnectionError({commit}, err) { commit('setApiConnectionError', err); + }, + async checkMigrations({commit, state}) { + if (state.isMigrationChecked) { + return; + } + + try { + await FolderMigration.runMigration(); + } catch (e) { + console.error(e); + } finally { + commit('setMigrationChecked'); + } } }, mutations: { @@ -42,6 +57,9 @@ export default function(/* { ssrContext } */) { dismissUpdateAll(state) { state.dismissedUpdateAll = true; }, + setMigrationChecked(state) { + state.isMigrationChecked = true; + }, setApiConnectionError(state, err) { state.apiConnectionError = err; } From afb39572667572716499c1c163ee1ae6c2d8026f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antti=20M=C3=A4ki?= Date: Fri, 7 Oct 2022 10:45:25 +0300 Subject: [PATCH 2/2] Refactor populating the attributes of GameSelectionScreen pre-mount Extract any logic out of the component, only setting the attributes by calling helper methods. Clean up unnecessary code and attempt to simplify the implementation. Refs TS-1138 --- src/model/game/GameManager.ts | 6 ++++ src/pages/GameSelectionScreen.vue | 46 ++++++++------------------ src/r2mm/manager/SettingsDexieStore.ts | 2 +- src/utils/ManagerUtils.ts | 18 ++++++++++ 4 files changed, 38 insertions(+), 34 deletions(-) create mode 100644 src/utils/ManagerUtils.ts diff --git a/src/model/game/GameManager.ts b/src/model/game/GameManager.ts index 07c3f8b37..6f5546722 100644 --- a/src/model/game/GameManager.ts +++ b/src/model/game/GameManager.ts @@ -319,4 +319,10 @@ export default class GameManager { public static unsetGame(): Game { return this._gameList.find(value => value.internalFolderName === "RiskOfRain2")!; } + + public static findByFolderName(name?: string|null) { + return name + ? this._gameList.find((game) => game.internalFolderName === name) + : undefined; + } } diff --git a/src/pages/GameSelectionScreen.vue b/src/pages/GameSelectionScreen.vue index 800fb01f7..906494a73 100644 --- a/src/pages/GameSelectionScreen.vue +++ b/src/pages/GameSelectionScreen.vue @@ -183,6 +183,7 @@ import Hero from '../components/Hero.vue'; import PathResolver from '../r2mm/manager/PathResolver'; import * as path from 'path'; import FileUtils from '../utils/FileUtils'; +import * as ManagerUtils from '../utils/ManagerUtils'; import ManagerSettings from '../r2mm/manager/ManagerSettings'; import { StorePlatform } from '../model/game/StorePlatform'; import { GameSelectionDisplayMode } from '../model/game/GameSelectionDisplayMode'; @@ -389,41 +390,20 @@ export default class GameSelectionScreen extends Vue { await this.$store.dispatch('checkMigrations'); this.runningMigration = false; - ManagerSettings.getSingleton(GameManager.unsetGame()).then(settings => { - const lastSelectedGame = settings.getContext().global.lastSelectedGame; - const savedViewMode = settings.getContext().global.gameSelectionViewMode; - switch (savedViewMode) { - case "List": this.viewMode = GameSelectionViewMode.LIST; break; - case "Card": - case undefined: - this.viewMode = GameSelectionViewMode.CARD; - break; - } - if (lastSelectedGame !== null) { - const game = GameManager.gameList.find(value => value.internalFolderName === lastSelectedGame); - if (game !== undefined) { - this.selectedGame = game; - } - } - }); - ManagerSettings.getSingleton(GameManager.unsetGame()).then(value => { - this.settings = value; - this.favourites = value.getContext().global.favouriteGames || []; - if (value.getContext().global.defaultGame !== undefined) { - if (value.getContext().global.defaultStore !== undefined) { - const game = GameManager.gameList - .find(value1 => value1.internalFolderName === value.getContext().global.defaultGame)!; - - const platform = game.storePlatformMetadata.find(value1 => value1.storePlatform === value.getContext().global.defaultStore)!; + this.settings = await ManagerSettings.getSingleton(GameManager.unsetGame()); + const globalSettings = this.settings.getContext().global; + this.viewMode = globalSettings.gameSelectionViewMode; + this.favourites = globalSettings.favouriteGames ?? []; + this.selectedGame = GameManager.findByFolderName(globalSettings.lastSelectedGame) ?? null; - this.selectedGame = game; - this.selectedPlatform = platform.storePlatform; + // Skip game selection view if valid default game & platform are set. + const {defaultGame, defaultPlatform} = ManagerUtils.getDefaults(this.settings); - this.proceed(); - return; - } - } - }); + if (defaultGame && defaultPlatform) { + this.selectedGame = defaultGame; + this.selectedPlatform = defaultPlatform; + this.proceed(); + } } toggleViewMode() { diff --git a/src/r2mm/manager/SettingsDexieStore.ts b/src/r2mm/manager/SettingsDexieStore.ts index 860574647..66bab4f2f 100644 --- a/src/r2mm/manager/SettingsDexieStore.ts +++ b/src/r2mm/manager/SettingsDexieStore.ts @@ -206,7 +206,7 @@ export interface ManagerSettingsInterfaceGlobal_V2 { favouriteGames: string[] | undefined; defaultGame: string | undefined; defaultStore: StorePlatform | undefined; - gameSelectionViewMode: string | undefined; + gameSelectionViewMode: GameSelectionViewMode; } /** diff --git a/src/utils/ManagerUtils.ts b/src/utils/ManagerUtils.ts new file mode 100644 index 000000000..cac909a4c --- /dev/null +++ b/src/utils/ManagerUtils.ts @@ -0,0 +1,18 @@ +import GameManager from "../model/game/GameManager"; +import ManagerSettings from "../r2mm/manager/ManagerSettings"; + + +/** + * Return default game selection needed to skip the game selection screen. + */ +export const getDefaults = (settings: ManagerSettings) => { + const globals = settings.getContext().global; + const defaultGame = GameManager.findByFolderName(globals.defaultGame); + const platforms = defaultGame ? defaultGame.storePlatformMetadata : []; + const defaultPlat = platforms.find(x => x.storePlatform === globals.defaultStore); + + return { + defaultGame, + defaultPlatform: defaultPlat ? defaultPlat.storePlatform : undefined + }; +}