Skip to content

Commit

Permalink
PoC of mod download/install through vuex store
Browse files Browse the repository at this point in the history
TODO: Installation is not yet done, but it should be pretty similar to download.
  • Loading branch information
VilppeRiskidev committed Nov 14, 2024
1 parent 5e73a77 commit bc696f8
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 43 deletions.
69 changes: 26 additions & 43 deletions src/components/views/DownloadModModal.vue
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
<template>
<div>
<div id='downloadProgressModal' :class="['modal', {'is-active':downloadingMod}]" v-if="downloadObject !== null">
<div id='downloadProgressModal' :class="['modal', {'is-active':downloadingMod}]" v-if="downloadingMod">
<div class="modal-background" @click="downloadingMod = false;"></div>
<div class='modal-content'>
<div class='notification is-info'>
<h3 class='title'>Downloading {{downloadObject.modName}}</h3>
<p>{{Math.floor(downloadObject.progress)}}% complete</p>
<h3 class='title'>Downloading {{activeDownloadModName}}</h3>
<p>{{Math.floor(downloadProgress)}}% complete</p>
<Progress
:max='100'
:value='downloadObject.progress'
:value='downloadProgress'
:className="['is-dark']"
/>
</div>
Expand Down Expand Up @@ -91,6 +91,7 @@
<script lang="ts">
import { Component, Vue, Watch } from 'vue-property-decorator';
import { mapGetters } from 'vuex';
import ThunderstoreMod from '../../model/ThunderstoreMod';
import ManifestV2 from '../../model/ManifestV2';
import ThunderstoreVersion from '../../model/ThunderstoreVersion';
Expand Down Expand Up @@ -123,6 +124,11 @@ let assignId = 0;
components: {
ModalCard,
Progress
},
computed: {
...mapGetters({
activeDownloadProgress: 'modDownload/activeDownloadProgress'
})
}
})
export default class DownloadModModal extends Vue {
Expand All @@ -133,6 +139,8 @@ let assignId = 0;
downloadingMod: boolean = false;
selectedVersion: string | null = null;
currentVersion: string | null = null;
downloadProgress: number | null = 0;
activeDownloadModName: string | null = null;
static allVersions: [number, DownloadProgress][] = [];
Expand Down Expand Up @@ -220,6 +228,11 @@ let assignId = 0;
return this.$store.state.modals.isDownloadModModalOpen;
}
@Watch('activeDownloadProgress')
async updateProgress() {
this.downloadProgress = this.$store.getters['modDownload/activeDownloadProgress'];
}
@Watch('$store.state.modals.downloadModModalMod')
async getModVersions() {
this.currentVersion = null;
Expand Down Expand Up @@ -326,47 +339,17 @@ let assignId = 0;
}, this.downloadCompletedCallback);
}
downloadHandler(tsMod: ThunderstoreMod, tsVersion: ThunderstoreVersion) {
async downloadHandler(tsMod: ThunderstoreMod, tsVersion: ThunderstoreVersion) {
this.closeModal();
const currentAssignId = assignId++;
const progressObject = {
progress: 0,
initialMods: [`${tsMod.getName()} (${tsVersion.getVersionNumber().toString()})`],
modName: '',
assignId: currentAssignId,
failed: false,
};
this.downloadObject = progressObject;
DownloadModModal.allVersions.push([currentAssignId, this.downloadObject]);
this.activeDownloadModName = tsMod.getName();
this.downloadingMod = true;
setTimeout(() => {
ThunderstoreDownloaderProvider.instance.download(this.profile.asImmutableProfile(), tsMod, tsVersion, this.ignoreCache, (progress: number, modName: string, status: number, err: R2Error | null) => {
const assignIndex = DownloadModModal.allVersions.findIndex(([number, val]) => number === currentAssignId);
if (status === StatusEnum.FAILURE) {
if (err !== null) {
this.downloadingMod = false;
const existing = DownloadModModal.allVersions[assignIndex]
existing[1].failed = true;
this.$set(DownloadModModal.allVersions, assignIndex, [currentAssignId, existing[1]]);
DownloadModModal.addSolutionsToError(err);
this.$store.commit('error/handleError', err);
return;
}
} else if (status === StatusEnum.PENDING) {
const obj = {
progress: progress,
initialMods: [`${tsMod.getName()} (${tsVersion.getVersionNumber().toString()})`],
modName: modName,
assignId: currentAssignId,
failed: false,
}
if (this.downloadObject!.assignId === currentAssignId) {
this.downloadObject = Object.assign({}, obj);
}
this.$set(DownloadModModal.allVersions, assignIndex, [currentAssignId, obj]);
}
}, this.downloadCompletedCallback);
}, 1);
await this.$store.dispatch(
'modDownload/downloadAndInstallMod',
{ profile: this.profile.asImmutableProfile(), mod: tsMod, version: tsVersion }
).catch((reason) => this.$store.commit('error/handleError', R2Error.fromThrownValue(reason)));
this.activeDownloadModName = null;
this.downloadingMod = false;
}
async downloadCompletedCallback(downloadedMods: ThunderstoreCombo[]) {
Expand Down
2 changes: 2 additions & 0 deletions src/store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import GameManager from '../model/game/GameManager';
import R2Error from '../model/errors/R2Error';
import { getModLoaderPackageNames } from '../r2mm/installing/profile_installers/ModLoaderVariantRecord';
import ManagerSettings from '../r2mm/manager/ManagerSettings';
import ModDownloadModule from "../store/modules/ModDownloadModule";

Vue.use(Vuex);

Expand Down Expand Up @@ -128,6 +129,7 @@ export const store = {
profile: ProfileModule,
profiles: ProfilesModule,
tsMods: TsModsModule,
modDownload: ModDownloadModule,
},

// enable strict mode (adds overhead!)
Expand Down
97 changes: 97 additions & 0 deletions src/store/modules/ModDownloadModule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { ActionTree, GetterTree } from 'vuex';

import StatusEnum from '../../model/enums/StatusEnum';
import { ImmutableProfile } from '../../model/Profile';
import ThunderstoreCombo from '../../model/ThunderstoreCombo';
import ThunderstoreMod from '../../model/ThunderstoreMod';
import ThunderstoreVersion from '../../model/ThunderstoreVersion';
import ThunderstoreDownloaderProvider from '../../providers/ror2/downloading/ThunderstoreDownloaderProvider';

import { State as RootState } from '../index';

interface Progress {
progress: number;
status: number; // StatusEnum
}

interface ModProgressItem {
mod: ThunderstoreMod;
version: ThunderstoreVersion;
installProgress: Progress;
downloadProgress: Progress;
}

interface State {
allDownloads: ModProgressItem[];
}

/**
* State for Mod Downloadning/Installation.
*/
export default {
namespaced: true,

state: (): State => ({
allDownloads: [],
}),

getters: <GetterTree<State, RootState>>{
allDownloads(state): ModProgressItem[] {
return state.allDownloads;
},
activeDownload(state): ModProgressItem {
return state.allDownloads.slice(-1)[0]; // Last element of the array
},
activeDownloadProgress(state): number | undefined {
if(state.allDownloads.length > 0) {
return state.allDownloads.slice(-1)[0].downloadProgress.progress; // Last element of the array
}
},
},
mutations: {},
actions: <ActionTree<State, RootState>>{

//TODO: Do the installation
async downloadAndInstallMod(
{dispatch, getters, state},
params: {
profile: ImmutableProfile,
mod: ThunderstoreMod,
version: ThunderstoreVersion,
}
): Promise<boolean> {
state.allDownloads.push({
mod: params.mod,
version: params.version,
installProgress: { progress: 0, status: StatusEnum.PENDING },
downloadProgress: { progress: 0, status: StatusEnum.PENDING }
});

return new Promise((resolve, reject) => {
ThunderstoreDownloaderProvider.instance.download(
params.profile,
params.mod,
params.version,
true,
(progress, modName, status, err) => {
const index = state.allDownloads.findIndex((modProgressItem) => modProgressItem.mod.getName() === modName);

if (status === StatusEnum.FAILURE) {
if(err) {
reject(err);
}
}
if (status === StatusEnum.PENDING) {
if (index !== -1) {
state.allDownloads[index].downloadProgress = { progress: progress, status: status };
}
}
},
() => {
resolve(true);
}
);
});
},
},
}

0 comments on commit bc696f8

Please sign in to comment.