diff --git a/CHANGELOG.md b/CHANGELOG.md index b6ccf54ef..1d1fe9392 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,18 @@ +### 3.1.48 +- Games added: + - Content Warning + - Plasma + - MS store support for Bomb Rush Cyberfunk +- Profile code exports now have a size restriction +- Fixes for Voices of the Void +- Other general fixes/improvements + +_Contributions:_ +- _anttimaki_ +- _cspotcode_ +- _Oksamies_ +- _ethangreen-dev_ + ### 3.1.47 - Significant performance improvements - Games added: diff --git a/package.json b/package.json index 272fc2540..0c47c831f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "r2modman", - "version": "3.1.47", + "version": "3.1.48", "description": "A simple and easy to use mod manager for several games using Thunderstore.", "productName": "r2modman", "author": "ebkr", diff --git a/src/App.vue b/src/App.vue index f266cc52f..c7eaccac0 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,25 +1,7 @@ @@ -64,23 +46,23 @@ import GenericProfileInstaller from './r2mm/installing/profile_installers/Generi import ConnectionProviderImpl from './r2mm/connection/ConnectionProviderImpl'; import ConnectionProvider from './providers/generic/connection/ConnectionProvider'; import UtilityMixin from './components/mixins/UtilityMixin.vue'; +import ErrorModal from './components/modals/ErrorModal.vue'; -@Component +@Component({ + components: { + ErrorModal, + } +}) export default class App extends mixins(UtilityMixin) { - private settings: ManagerSettings | null = null; private visible: boolean = false; async created() { - // Use as default game for settings load. - GameManager.activeGame = GameManager.unsetGame(); + // Load settings using the default game before the actual game is selected. + const settings: ManagerSettings = await this.$store.dispatch('setActiveGame', GameManager.defaultGame); this.hookThunderstoreModListRefresh(); - this.hookProfileModListRefresh(); await this.checkCdnConnection(); - const settings = await ManagerSettings.getSingleton(GameManager.activeGame); - this.settings = settings; - InstallationRuleApplicator.apply(); InstallationRules.validate(); diff --git a/src/_managerinf/ManagerInformation.ts b/src/_managerinf/ManagerInformation.ts index 51d95a700..5cbed4022 100644 --- a/src/_managerinf/ManagerInformation.ts +++ b/src/_managerinf/ManagerInformation.ts @@ -1,7 +1,7 @@ import VersionNumber from '../model/VersionNumber'; export default class ManagerInformation { - public static VERSION: VersionNumber = new VersionNumber('3.1.47'); + public static VERSION: VersionNumber = new VersionNumber('3.1.48'); public static IS_PORTABLE: boolean = false; public static APP_NAME: string = "r2modman"; } diff --git a/src/assets/images/game_selection/ContentWarning.png b/src/assets/images/game_selection/ContentWarning.png new file mode 100644 index 000000000..8ba40ba62 Binary files /dev/null and b/src/assets/images/game_selection/ContentWarning.png differ diff --git a/src/assets/images/game_selection/Plasma.jpg b/src/assets/images/game_selection/Plasma.jpg new file mode 100644 index 000000000..3da5b0b7b Binary files /dev/null and b/src/assets/images/game_selection/Plasma.jpg differ diff --git a/src/components/ExpandableCard.vue b/src/components/ExpandableCard.vue index 4792af1f6..0dff0b28f 100644 --- a/src/components/ExpandableCard.vue +++ b/src/components/ExpandableCard.vue @@ -7,7 +7,7 @@ @@ -56,13 +56,7 @@ id: string | undefined; @Prop({default: false}) - funkyMode: boolean | undefined; - - @Prop({default: false}) - expandedByDefault: boolean | undefined; - - @Prop({default: false}) - showSort: boolean | undefined; + allowSorting: boolean | undefined; @Prop({default: true}) enabled: boolean | undefined; @@ -70,7 +64,11 @@ // Keep track of visibility visible: boolean | undefined = false; - @Watch('expandedByDefault') + get showSort() { + return this.allowSorting && this.$store.getters["profile/canSortMods"]; + } + + @Watch('$store.state.profile.expandedByDefault') visibilityChanged(current: boolean) { this.visible = current; } @@ -80,7 +78,8 @@ } async created() { - this.visible = this.expandedByDefault; + await this.$store.dispatch('profile/loadModCardSettings'); + this.visible = this.$store.state.profile.expandedByDefault; } } diff --git a/src/components/SettingsLoader.vue b/src/components/SettingsLoader.vue index 85b6a4c1f..a0192eb0b 100644 --- a/src/components/SettingsLoader.vue +++ b/src/components/SettingsLoader.vue @@ -173,14 +173,12 @@ export default class SettingsLoader extends Vue { } const getDefaultGame = () => { - const defaultGame = GameManager.unsetGame(); - - // Don't trust the non-null asserted typing of .unsetGame(). - if (defaultGame === undefined) { - throw new Error("GameManager.unsetGame() returned undefined"); + // Don't trust the non-null asserted typing of GameManager.defaultGame. + if (GameManager.defaultGame === undefined) { + throw new Error("GameManager.defaultGame returned undefined"); } - return defaultGame; + return GameManager.defaultGame; }; diff --git a/src/components/config-components/ConfigSelectionLayout.vue b/src/components/config-components/ConfigSelectionLayout.vue index e319d2cec..e99564998 100644 --- a/src/components/config-components/ConfigSelectionLayout.vue +++ b/src/components/config-components/ConfigSelectionLayout.vue @@ -145,9 +145,9 @@ import ProfileModList from '../../r2mm/mods/ProfileModList'; this.configFiles = this.configFiles.filter(value => value.getName() !== file.getName()); this.textChanged(); } catch (e) { - this.$emit("error", new R2Error( + this.$store.commit("error/handleError", R2Error.fromThrownValue( + e, "Failed to delete config file", - (e as Error).message, `Try running ${ManagerInformation.APP_NAME} as an administrator.` )); } diff --git a/src/components/importing/LocalFileImportModal.vue b/src/components/importing/LocalFileImportModal.vue index 2973d9ef9..7e67ac4f3 100644 --- a/src/components/importing/LocalFileImportModal.vue +++ b/src/components/importing/LocalFileImportModal.vue @@ -289,15 +289,15 @@ export default class LocalFileImportModal extends Vue { const installCallback = (async (success: boolean, error: any | null) => { if (!success && error !== null) { - this.showError(error); + this.$store.commit("error/handleError", R2Error.fromThrownValue(error)); return; } const updatedModListResult = await ProfileModList.getModList(this.contextProfile!); if (updatedModListResult instanceof R2Error) { - this.showError(updatedModListResult); + this.$store.commit("error/handleError", updatedModListResult); return; } - await this.$store.dispatch("updateModList", updatedModListResult); + await this.$store.dispatch("profile/updateModList", updatedModListResult); this.emitClose(); }); @@ -308,10 +308,6 @@ export default class LocalFileImportModal extends Vue { } } - private showError(err: R2Error) { - this.$emit("error", err); - } - created() { this.contextProfile = Profile.getActiveProfile(); } diff --git a/src/components/mixins/UtilityMixin.vue b/src/components/mixins/UtilityMixin.vue index f40317c14..a8bb44787 100644 --- a/src/components/mixins/UtilityMixin.vue +++ b/src/components/mixins/UtilityMixin.vue @@ -3,58 +3,19 @@ import Vue from 'vue'; import Component from 'vue-class-component'; import R2Error from '../../model/errors/R2Error'; -import GameManager from '../../model/game/GameManager'; -import Profile from '../../model/Profile'; import CdnProvider from '../../providers/generic/connection/CdnProvider'; -import LoggerProvider, { LogSeverity } from '../../providers/ror2/logging/LoggerProvider'; import ThunderstorePackages from '../../r2mm/data/ThunderstorePackages'; -import ProfileModList from '../../r2mm/mods/ProfileModList'; import ApiCacheUtils from '../../utils/ApiCacheUtils'; @Component export default class UtilityMixin extends Vue { - private errorMessage: string = ''; - private errorStack: string = ''; - private errorSolution: string = ''; readonly REFRESH_INTERVAL = 5 * 60 * 1000; private tsRefreshFailed = false; - showError(error: R2Error) { - this.errorMessage = error.name; - this.errorStack = error.message; - this.errorSolution = error.solution; - LoggerProvider.instance.Log(LogSeverity.ERROR, `[${error.name}]: ${error.message}`); - } - - closeErrorModal() { - this.errorMessage = ''; - this.errorStack = ''; - this.errorSolution = ''; - } - - hookProfileModListRefresh() { - setInterval(this.refreshProfileModList, this.REFRESH_INTERVAL); - } - hookThunderstoreModListRefresh() { setInterval(this.tryRefreshThunderstoreModList, this.REFRESH_INTERVAL); } - async refreshProfileModList() { - const profile = Profile.getActiveProfile(); - - // If no profile is selected on game selection then getActiveProfile will return undefined. - if (profile === undefined) { - return; - } - - const modList = await ProfileModList.getModList(profile); - - if (!(modList instanceof R2Error)) { - this.$store.dispatch("updateModList", modList); - } - } - async refreshThunderstoreModList() { // Don't do background update on index route since the game // isn't really chosen yet, nor in the splash screen since it @@ -65,9 +26,10 @@ export default class UtilityMixin extends Vue { return; } - const response = await ThunderstorePackages.update(GameManager.activeGame); + const response = await ThunderstorePackages.update(this.$store.state.activeGame); await ApiCacheUtils.storeLastRequest(response.data); await this.$store.dispatch("updateThunderstoreModList", ThunderstorePackages.PACKAGES); + await this.$store.dispatch("profile/tryLoadModListFromDisk"); } /** @@ -101,7 +63,7 @@ export default class UtilityMixin extends Vue { await CdnProvider.checkCdnConnection(); } catch (error: unknown) { if (error instanceof R2Error) { - this.showError(error); + this.$store.commit('error/handleError', error); } else { console.error(error); } diff --git a/src/components/modals/ErrorModal.vue b/src/components/modals/ErrorModal.vue new file mode 100644 index 000000000..b8cd429be --- /dev/null +++ b/src/components/modals/ErrorModal.vue @@ -0,0 +1,51 @@ + + + + + diff --git a/src/components/navigation/NavigationLayout.vue b/src/components/navigation/NavigationLayout.vue index d7801328f..73d42c911 100644 --- a/src/components/navigation/NavigationLayout.vue +++ b/src/components/navigation/NavigationLayout.vue @@ -1,10 +1,10 @@