mirror of
https://github.com/dralkh/spaceforge.git
synced 2026-07-22 06:45:03 +00:00
refactor: improve settings tab and main functionality
This commit is contained in:
parent
4cbc58b5fa
commit
cb9a941597
2 changed files with 95 additions and 13 deletions
47
main.ts
47
main.ts
|
|
@ -40,6 +40,7 @@ export default class SpaceforgePlugin extends Plugin {
|
|||
pomodoroService: PomodoroService;
|
||||
calendarEventService: CalendarEventService;
|
||||
|
||||
|
||||
private readonly stylesheetPath: string = "styles.css";
|
||||
private readonly stylesheetId: string = "spaceforge-styles";
|
||||
private lastStylesModTime: number | null = null;
|
||||
|
|
@ -94,6 +95,8 @@ export default class SpaceforgePlugin extends Plugin {
|
|||
this.calendarEventService.initialize(eventsArray);
|
||||
|
||||
|
||||
|
||||
|
||||
this.registerView(
|
||||
'spaceforge-review-schedule',
|
||||
(leaf) => new ReviewSidebarView(leaf, this)
|
||||
|
|
@ -165,7 +168,7 @@ export default class SpaceforgePlugin extends Plugin {
|
|||
this.getSidebarView()?.refresh();
|
||||
}, 60 * 1000));
|
||||
|
||||
this.app.workspace.onLayoutReady(() => this.activateSidebarView());
|
||||
// this.app.workspace.onLayoutReady(() => this.activateSidebarView()); // Removed automatic activation
|
||||
this.addStylesheet();
|
||||
|
||||
if (this.app.vault.adapter.stat && typeof this.app.vault.adapter.stat === 'function') {
|
||||
|
|
@ -427,11 +430,31 @@ export default class SpaceforgePlugin extends Plugin {
|
|||
this.reviewScheduleService.lastLinkAnalysisTimestamp = typeof this.pluginState.lastLinkAnalysisTimestamp === 'number' ? this.pluginState.lastLinkAnalysisTimestamp : null;
|
||||
|
||||
} catch (error) {
|
||||
// Fallback to complete defaults if any error during loading sequence
|
||||
this.settings = { ...DEFAULT_SETTINGS };
|
||||
this.pluginState = { ...DEFAULT_PLUGIN_STATE_DATA };
|
||||
console.error("Spaceforge: Error loading data:", error);
|
||||
|
||||
// Repopulate services with these fresh defaults
|
||||
// SIMPLE RECOVERY: Try localStorage backup once, then use defaults
|
||||
try {
|
||||
const backupData = await this.app.loadLocalStorage('spaceforge-backup');
|
||||
if (backupData && typeof backupData === 'string') {
|
||||
const parsedBackup = JSON.parse(backupData);
|
||||
if (parsedBackup.reviewData) {
|
||||
this.settings = { ...DEFAULT_SETTINGS, ...parsedBackup.settings };
|
||||
this.pluginState = { ...DEFAULT_PLUGIN_STATE_DATA, ...parsedBackup.reviewData };
|
||||
new Notice("Spaceforge: Recovered data from backup.", 5000);
|
||||
} else {
|
||||
throw new Error("Invalid backup format");
|
||||
}
|
||||
} else {
|
||||
throw new Error("No backup found");
|
||||
}
|
||||
} catch (backupError) {
|
||||
console.warn("Spaceforge: Backup recovery failed, using defaults:", backupError);
|
||||
this.settings = { ...DEFAULT_SETTINGS };
|
||||
this.pluginState = { ...DEFAULT_PLUGIN_STATE_DATA };
|
||||
new Notice("Spaceforge: Error loading data. Using defaults to prevent crash.", 5000);
|
||||
}
|
||||
|
||||
// Repopulate services
|
||||
this.reviewScheduleService.schedules = this.pluginState.schedules || {};
|
||||
this.reviewHistoryService.history = this.pluginState.history || [];
|
||||
this.reviewSessionService.reviewSessions = this.pluginState.reviewSessions || { sessions: {}, activeSessionId: null };
|
||||
|
|
@ -440,11 +463,9 @@ export default class SpaceforgePlugin extends Plugin {
|
|||
this.reviewScheduleService.customNoteOrder = this.pluginState.customNoteOrder || [];
|
||||
this.reviewScheduleService.lastLinkAnalysisTimestamp = this.pluginState.lastLinkAnalysisTimestamp ?? null;
|
||||
|
||||
// Ensure FSRS service is also updated with these default settings
|
||||
if (this.reviewScheduleService) {
|
||||
this.reviewScheduleService.updateAlgorithmServicesForSettingsChange();
|
||||
}
|
||||
new Notice("Spaceforge: Error loading data, initialized with defaults.", 5000);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -504,6 +525,7 @@ export default class SpaceforgePlugin extends Plugin {
|
|||
new Notice(`Spaceforge: Created directory for custom data: ${dirPathOnly}`, 3000);
|
||||
}
|
||||
|
||||
// SIMPLE SAVE: Use Obsidian's standard file operations
|
||||
const file = this.app.vault.getAbstractFileByPath(effectiveSavePath);
|
||||
if (file instanceof TFile) {
|
||||
await this.app.vault.modify(file, JSON.stringify(dataToSave, null, 2));
|
||||
|
|
@ -513,14 +535,13 @@ export default class SpaceforgePlugin extends Plugin {
|
|||
// new Notice(`Spaceforge: Data saved to custom path: ${effectiveSavePath}`, 3000); // Removed notice
|
||||
|
||||
// Migration/Cleanup: If we just successfully saved to a custom path,
|
||||
// and the old default data.json exists, remove it.
|
||||
// and the old default data.json exists, KEEP IT as backup for safety.
|
||||
// CRITICAL FIX: Never automatically delete user data to prevent data loss during reloads
|
||||
const oldFile = this.app.vault.getAbstractFileByPath(defaultPluginDataPath);
|
||||
if (oldFile instanceof TFile) {
|
||||
// Check if this is a migration scenario (old data was loaded and new path was empty)
|
||||
// This check is a bit implicit. A more robust way would be a flag.
|
||||
// For now, if custom path is active and default exists, assume it's post-migration or user switched.
|
||||
await this.app.vault.delete(oldFile);
|
||||
new Notice(`Spaceforge: Removed old data file from default plugin folder as custom path is active.`, 5000);
|
||||
// Instead of deleting, we'll keep the old file as a backup
|
||||
// Users can manually clean it up later if needed
|
||||
new Notice(`Spaceforge: Successfully saved to custom path. Original data file kept as backup for safety.`, 5000);
|
||||
}
|
||||
} catch (writeError) {
|
||||
new Notice(`Error saving data to custom path ${effectiveSavePath}: ${writeError.message}. Falling back to default path for this save.`, 10000);
|
||||
|
|
|
|||
|
|
@ -1287,6 +1287,65 @@ export class SpaceforgeSettingTab extends PluginSettingTab {
|
|||
});
|
||||
}
|
||||
|
||||
// ========= DATA MANAGEMENT SECTION =========
|
||||
const dataSection = createCollapsible('Data Management', 'database', false);
|
||||
|
||||
const defaultPath = this.plugin.app.vault.configDir + `/plugins/${this.plugin.manifest.id}/data.json`;
|
||||
let locationDesc = `Default: ${defaultPath}`;
|
||||
if (this.plugin.settings.useCustomDataPath && this.plugin.settings.customDataPath) {
|
||||
const customPath = this.plugin.settings.customDataPath.endsWith('/data.json')
|
||||
? this.plugin.settings.customDataPath
|
||||
: `${this.plugin.settings.customDataPath}/data.json`;
|
||||
locationDesc = `Custom: ${customPath}`;
|
||||
}
|
||||
|
||||
new Setting(dataSection)
|
||||
.setName('Current data location')
|
||||
.setDesc(locationDesc)
|
||||
.addExtraButton(button => button
|
||||
.setIcon('info')
|
||||
.setTooltip('Current location of your Spaceforge data')
|
||||
.onClick(() => {
|
||||
const message = this.plugin.settings.useCustomDataPath && this.plugin.settings.customDataPath
|
||||
? `Your data is stored at: ${this.plugin.settings.customDataPath.endsWith('/data.json') ? this.plugin.settings.customDataPath : `${this.plugin.settings.customDataPath}/data.json`}`
|
||||
: `Your data is stored at: ${defaultPath}`;
|
||||
|
||||
new Notice(message, 8000);
|
||||
}));
|
||||
|
||||
// Check if old default data file exists when using custom path
|
||||
if (this.plugin.settings.useCustomDataPath) {
|
||||
const oldFile = this.plugin.app.vault.getAbstractFileByPath(defaultPath);
|
||||
|
||||
if (oldFile) {
|
||||
new Setting(dataSection)
|
||||
.setName('Legacy data file found')
|
||||
.setDesc(`A data file exists at the default location. You can safely delete it or keep it as a backup.`)
|
||||
.addButton(button => button
|
||||
.setButtonText('Keep as Backup')
|
||||
.setIcon('save')
|
||||
.onClick(() => {
|
||||
new Notice('Legacy data file kept as backup. You can delete it manually when ready.', 5000);
|
||||
}))
|
||||
.addButton(button => button
|
||||
.setButtonText('Delete Legacy File')
|
||||
.setIcon('trash')
|
||||
.setWarning()
|
||||
.onClick(async () => {
|
||||
const confirmed = confirm('Are you sure you want to delete the legacy data file? Make sure your custom data path is working correctly before proceeding.');
|
||||
if (confirmed) {
|
||||
try {
|
||||
await this.plugin.app.vault.delete(oldFile);
|
||||
new Notice('Legacy data file deleted successfully.', 3000);
|
||||
this.display(); // Refresh settings
|
||||
} catch (error) {
|
||||
new Notice('Failed to delete legacy file: ' + error.message, 5000);
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
// Add global action buttons at the bottom
|
||||
createActionButtons();
|
||||
}
|
||||
|
|
@ -1378,5 +1437,7 @@ export class SpaceforgeSettingTab extends PluginSettingTab {
|
|||
row4.createEl('td', { text: 'Recalled easily' });
|
||||
row4.createEl('td', { text: 'Largest increase in stability' });
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue