Skip to content

Commit 05451b9

Browse files
committed
Add DataFolderProvider
Create a new provider for handling changing the data folder. This shouldn't affect the functionality for r2mm, but allows tsmm to fix the feature on their end. As a bonus it moves the related logic from the bloated Manager component.
1 parent 447b733 commit 05451b9

File tree

4 files changed

+118
-35
lines changed

4 files changed

+118
-35
lines changed

src/App.vue

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ import LinkProvider from './providers/components/LinkProvider';
3030
import LinkImpl from './r2mm/component_override/LinkImpl';
3131
import FsProvider from './providers/generic/file/FsProvider';
3232
import NodeFs from './providers/generic/file/NodeFs';
33+
import { DataFolderProvider } from './providers/ror2/system/DataFolderProvider';
34+
import { DataFolderProviderImpl } from './r2mm/system/DataFolderProviderImpl';
3335
import InteractionProvider from './providers/ror2/system/InteractionProvider';
3436
import InteractionProviderImpl from './r2mm/system/InteractionProviderImpl';
3537
import ZipProvider from './providers/generic/zip/ZipProvider';
@@ -117,6 +119,7 @@ export default class App extends mixins(UtilityMixin) {
117119
LoggerProvider.provide(() => new Logger());
118120
LinkProvider.provide(() => new LinkImpl());
119121
InteractionProvider.provide(() => new InteractionProviderImpl());
122+
DataFolderProvider.provide(() => new DataFolderProviderImpl());
120123
121124
PlatformInterceptorProvider.provide(() => new PlatformInterceptorImpl());
122125

src/pages/Manager.vue

Lines changed: 17 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ import ManifestV2 from '../model/ManifestV2';
157157
import ManagerSettings from '../r2mm/manager/ManagerSettings';
158158
import ThemeManager from '../r2mm/manager/ThemeManager';
159159
import ManagerInformation from '../_managerinf/ManagerInformation';
160+
import { DataFolderProvider } from '../providers/ror2/system/DataFolderProvider';
160161
import InteractionProvider from '../providers/ror2/system/InteractionProvider';
161162
162163
import { homedir } from 'os';
@@ -504,41 +505,22 @@ import CategoryFilterModal from '../components/modals/CategoryFilterModal.vue';
504505
}
505506
}
506507
507-
changeDataFolder() {
508-
const fs = FsProvider.instance;
509-
const dir: string = PathResolver.ROOT;
510-
InteractionProvider.instance.selectFolder({
511-
title: `Select a new folder to store ${ManagerInformation.APP_NAME} data`,
512-
defaultPath: dir,
513-
buttonLabel: 'Select Data Folder'
514-
}).then(async files => {
515-
if (files.length === 1) {
516-
const dataDirectoryOverrideFile = ".ddir.mm";
517-
const filesInDirectory = await fs.readdir(files[0]);
518-
519-
const hasOverrideFile = filesInDirectory.find(value => value.toLowerCase() === dataDirectoryOverrideFile) != undefined;
520-
const directoryHasContents = filesInDirectory.length > 0;
521-
const isDefaultDataDirectory = files[0] === PathResolver.APPDATA_DIR;
522-
523-
if (hasOverrideFile || !directoryHasContents || isDefaultDataDirectory) {
524-
// Write dataDirectoryOverrideFile to allow re-selection of directory if changed at a later point.
525-
await fs.writeFile(path.join(files[0], dataDirectoryOverrideFile), "");
526-
await this.settings.setDataDirectory(files[0]);
527-
InteractionProvider.instance.restartApp();
528-
} else {
529-
this.$store.commit('error/handleError', new R2Error(
530-
"Selected directory is not empty",
531-
`Directory is not empty: ${files[0]}. Contains ${filesInDirectory.length} files.`,
532-
"Select an empty directory or create a new one."
533-
));
534-
}
508+
async changeDataFolder() {
509+
try {
510+
const folder = await DataFolderProvider.instance.showSelectionDialog();
511+
512+
if (folder === null) {
513+
return;
535514
}
536-
}).catch((err) => {
537-
this.$store.commit(
538-
"error/handleError",
539-
R2Error.fromThrownValue(err, "Failed to change Data Folder")
540-
);
541-
});
515+
516+
await DataFolderProvider.instance.throwForInvalidFolder(folder);
517+
await DataFolderProvider.instance.writeOverrideFile(folder);
518+
await this.settings.setDataDirectory(folder);
519+
InteractionProvider.instance.restartApp();
520+
} catch(err) {
521+
this.$store.commit("error/handleError", R2Error.fromThrownValue(err));
522+
return
523+
}
542524
}
543525
544526
async handleSettingsCallbacks(invokedSetting: any) {
@@ -613,7 +595,7 @@ import CategoryFilterModal from '../components/modals/CategoryFilterModal.vue';
613595
this.showDependencyStrings = true;
614596
break;
615597
case "ChangeDataFolder":
616-
this.changeDataFolder();
598+
await this.changeDataFolder();
617599
break;
618600
case "CleanCache":
619601
CacheUtil.clean();
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import ProviderUtils from '../../generic/ProviderUtils';
2+
3+
export abstract class DataFolderProvider {
4+
public abstract readonly overrideFile: string;
5+
6+
private static provider: () => DataFolderProvider;
7+
8+
static provide(provided: () => DataFolderProvider): void {
9+
this.provider = provided;
10+
}
11+
12+
public static get instance(): DataFolderProvider {
13+
if (DataFolderProvider.provider === undefined) {
14+
ProviderUtils.throwNotProvidedError('DataFolderProvider');
15+
}
16+
return DataFolderProvider.provider();
17+
}
18+
19+
public abstract showSelectionDialog(): Promise<string|null>;
20+
21+
public abstract throwForInvalidFolder(folderPath: string): Promise<void>;
22+
23+
public abstract writeOverrideFile(folderPath: string): Promise<void>;
24+
25+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import path from "path";
2+
3+
import ManagerInformation from "../../_managerinf/ManagerInformation";
4+
import R2Error from "../../model/errors/R2Error";
5+
import FsProvider from "../../providers/generic/file/FsProvider";
6+
import { DataFolderProvider } from "../../providers/ror2/system/DataFolderProvider";
7+
import InteractionProvider from "../../providers/ror2/system/InteractionProvider";
8+
import PathResolver from "../../r2mm/manager/PathResolver";
9+
10+
export class DataFolderProviderImpl extends DataFolderProvider {
11+
readonly overrideFile: string = ".ddir.mm"
12+
13+
/***
14+
* @returns folder path as string, null if user cancelled selection.
15+
*/
16+
async showSelectionDialog(): Promise<string|null> {
17+
const files = await InteractionProvider.instance.selectFolder({
18+
title: `Select a new folder to store ${ManagerInformation.APP_NAME} data`,
19+
defaultPath: PathResolver.ROOT,
20+
buttonLabel: "Select data folder"
21+
});
22+
23+
// User closed the dialog without selecting a folder.
24+
if (files.length === 0) {
25+
return null;
26+
}
27+
28+
if (files.length === 1) {
29+
return files[0];
30+
}
31+
32+
// Shouldn't be possible to select multiple folders but someone always finds a way.
33+
throw new R2Error("Select exactly one folder", `${files.length} items were selected.`);
34+
}
35+
36+
async throwForInvalidFolder(folderPath: string): Promise<void> {
37+
// Default DataFolder is always valid.
38+
if (folderPath === PathResolver.APPDATA_DIR) {
39+
return;
40+
}
41+
42+
const filesInFolder = await FsProvider.instance.readdir(folderPath);
43+
const hasOverrideFile = filesInFolder.some(
44+
file => file.toLowerCase() === this.overrideFile
45+
);
46+
47+
// Previously used DataFolders are valid.
48+
if (hasOverrideFile) {
49+
return;
50+
}
51+
52+
// Empty folders are valid.
53+
if (filesInFolder.length === 0) {
54+
return;
55+
}
56+
57+
throw new R2Error(
58+
"Selected folder is not empty",
59+
`${folderPath} contains ${filesInFolder.length} files.`,
60+
"Select an empty folder or create a new one."
61+
);
62+
}
63+
64+
async writeOverrideFile(folderPath: string): Promise<void> {
65+
const filePath = path.join(folderPath, this.overrideFile);
66+
67+
try {
68+
await FsProvider.instance.writeFile(filePath, "");
69+
} catch (err) {
70+
throw R2Error.fromThrownValue(err, "Failed to change data folder");
71+
}
72+
}
73+
}

0 commit comments

Comments
 (0)