refactor(workspace): clean up settings and improve module visibility

- Remove deprecated ExperimentalSettings duplicating fluent config
- Clean up unused FluentViewSettings fields (showFluentRibbon, showTopNavigation, etc.)
- Add workspace switch listener to refresh project list automatically
- Improve workspace manager with module visibility controls
- Add methods for managing hidden views, sidebar components, and features
- Auto-enable Fluent Layout when skipping onboarding
- Localize default workspace name with translations
- Remove deprecated Workspace types from fluent-types
This commit is contained in:
Quorafind 2025-10-17 00:31:02 +08:00
parent 0d3c6fa352
commit b475615592
9 changed files with 230 additions and 172 deletions

View file

@ -434,7 +434,6 @@ export interface BetaTestSettings {
export interface FluentViewSettings {
enableFluent: boolean;
showFluentRibbon: boolean;
workspaces?: Array<{
id: string;
name: string;
@ -445,33 +444,15 @@ export interface FluentViewSettings {
fluentConfig?: {
enableWorkspaces: boolean;
defaultWorkspace?: string;
showTopNavigation: boolean;
showNewSidebar: boolean;
allowViewSwitching: boolean;
persistViewMode: boolean;
maxOtherViewsBeforeOverflow?: number; // how many other views to show before overflow menu
};
}
export interface ExperimentalSettings {
enableFluent: boolean;
showFluentRibbon: boolean;
workspaces?: Array<{
id: string;
name: string;
color: string;
settings?: any;
}>;
useWorkspaceSideLeaves?: boolean;
fluentConfig?: {
enableWorkspaces: boolean;
defaultWorkspace?: string;
showTopNavigation: boolean;
showNewSidebar: boolean;
allowViewSwitching: boolean;
persistViewMode: boolean;
maxOtherViewsBeforeOverflow?: number; // how many other views to show before overflow menu
};
// Experimental feature 1
experimentalFeature1: boolean;
// Experimental feature 2
experimentalFeature2: boolean;
}
/** Project path mapping configuration */
@ -1670,10 +1651,6 @@ export const DEFAULT_SETTINGS: TaskProgressBarSettings = {
customDateFormats: [],
// Experimental Defaults
experimental: {
enableFluent: false,
showFluentRibbon: false,
},
// Onboarding Defaults
onboarding: {

View file

@ -1,8 +1,14 @@
import { Workspace, WorkspaceLeaf } from "obsidian";
import TaskProgressBarPlugin from "@/index";
import { FluentTaskView, FLUENT_TASK_VIEW } from "@/pages/FluentTaskView";
import { LeftSidebarView, TG_LEFT_SIDEBAR_VIEW_TYPE } from "@/pages/LeftSidebarView";
import { RightDetailView, TG_RIGHT_DETAIL_VIEW_TYPE } from "@/pages/RightDetailView";
import {
LeftSidebarView,
TG_LEFT_SIDEBAR_VIEW_TYPE,
} from "@/pages/LeftSidebarView";
import {
RightDetailView,
TG_RIGHT_DETAIL_VIEW_TYPE,
} from "@/pages/RightDetailView";
import { t } from "@/translations/helper";
import { TASK_VIEW_TYPE } from "@/pages/TaskView";
@ -26,25 +32,25 @@ export class FluentIntegration {
// Register the Fluent view
this.plugin.registerView(
FLUENT_TASK_VIEW,
(leaf: WorkspaceLeaf) => new FluentTaskView(leaf, this.plugin)
(leaf: WorkspaceLeaf) => new FluentTaskView(leaf, this.plugin),
);
// Register side leaf views for new architecture
this.plugin.registerView(
TG_LEFT_SIDEBAR_VIEW_TYPE,
(leaf: WorkspaceLeaf) => new LeftSidebarView(leaf, this.plugin)
(leaf: WorkspaceLeaf) => new LeftSidebarView(leaf, this.plugin),
);
this.plugin.registerView(
TG_RIGHT_DETAIL_VIEW_TYPE,
(leaf: WorkspaceLeaf) => new RightDetailView(leaf, this.plugin)
(leaf: WorkspaceLeaf) => new RightDetailView(leaf, this.plugin),
);
// When any of the V2 views becomes active, reveal the other side leaves without focusing them
this.plugin.registerEvent(
this.plugin.app.workspace.on("active-leaf-change", async (leaf) => {
if (this.revealingSideLeaves) return;
const useSideLeaves = !!(this.plugin.settings.fluentView)?.useWorkspaceSideLeaves;
const useSideLeaves =
!!this.plugin.settings.fluentView?.useWorkspaceSideLeaves;
if (!useSideLeaves || !leaf?.view?.getViewType) return;
const vt = leaf.view.getViewType();
const watched = new Set<string>([
@ -57,31 +63,47 @@ export class FluentIntegration {
this.revealingSideLeaves = true;
try {
// Ensure side leaves exist
const leftLeaf = await ws.ensureSideLeaf(TG_LEFT_SIDEBAR_VIEW_TYPE, "left", {active: false});
const rightLeaf = await ws.ensureSideLeaf(TG_RIGHT_DETAIL_VIEW_TYPE, "right", {active: false});
const leftLeaf = await ws.ensureSideLeaf(
TG_LEFT_SIDEBAR_VIEW_TYPE,
"left",
{ active: false },
);
const rightLeaf = await ws.ensureSideLeaf(
TG_RIGHT_DETAIL_VIEW_TYPE,
"right",
{ active: false },
);
// Bring them to front within their splits (without keeping focus)
if (leftLeaf) ws.revealLeaf(leftLeaf);
if (rightLeaf) ws.revealLeaf(rightLeaf);
// Expand sidebars if they are collapsed
if (ws.leftSplit?.collapsed && typeof ws.leftSplit.expand === "function") ws.leftSplit.expand();
if (ws.rightSplit?.collapsed && typeof ws.rightSplit.expand === "function") ws.rightSplit.expand();
if (
ws.leftSplit?.collapsed &&
typeof ws.leftSplit.expand === "function"
)
ws.leftSplit.expand();
if (
ws.rightSplit?.collapsed &&
typeof ws.rightSplit.expand === "function"
)
ws.rightSplit.expand();
// Restore focus to the currently active (incoming) leaf
if (ws.setActiveLeaf && leaf) ws.setActiveLeaf(leaf, {focus: true});
if (ws.setActiveLeaf && leaf)
ws.setActiveLeaf(leaf, { focus: true });
} catch (_) {
// noop
} finally {
this.revealingSideLeaves = false;
}
})
}),
);
}
/**
* Open the Fluent view
*/
private async openV2View() {
const {workspace} = this.plugin.app;
const { workspace } = this.plugin.app;
// Check if Fluent view is already open
const leaves = workspace.getLeavesOfType(FLUENT_TASK_VIEW);
@ -107,16 +129,20 @@ export class FluentIntegration {
}
private async ensureSideLeavesIfEnabled() {
const useSideLeaves = !!(this.plugin.settings.fluentView)?.useWorkspaceSideLeaves;
const useSideLeaves =
!!this.plugin.settings.fluentView?.useWorkspaceSideLeaves;
if (!useSideLeaves) return;
const ws = this.plugin.app.workspace as Workspace;
// Left sidebar
await ws.ensureSideLeaf(TG_LEFT_SIDEBAR_VIEW_TYPE, "left", {active: false});
await ws.ensureSideLeaf(TG_RIGHT_DETAIL_VIEW_TYPE, "right", {active: false});
await ws.ensureSideLeaf(TG_LEFT_SIDEBAR_VIEW_TYPE, "left", {
active: false,
});
await ws.ensureSideLeaf(TG_RIGHT_DETAIL_VIEW_TYPE, "right", {
active: false,
});
}
/**
* Check if Fluent features are enabled
*/
@ -131,14 +157,13 @@ export class FluentIntegration {
if (!this.plugin.settings.fluentView) {
this.plugin.settings.fluentView = {
enableFluent: false,
showFluentRibbon: false,
};
}
// Default workspace configuration
if (!this.plugin.settings.fluentView!.workspaces) {
this.plugin.settings.fluentView!.workspaces = [
{id: "default", name: "Default", color: "#3498db"},
{ id: "default", name: t("Default"), color: "#3498db" },
];
}
@ -147,17 +172,14 @@ export class FluentIntegration {
this.plugin.settings.fluentView!.fluentConfig = {
enableWorkspaces: true,
defaultWorkspace: "default",
showTopNavigation: true,
showNewSidebar: true,
allowViewSwitching: true,
persistViewMode: true,
maxOtherViewsBeforeOverflow: 5,
};
}
// Backfill extra experimental flag without touching types
const v2c = this.plugin.settings.fluentView;
if (v2c.useWorkspaceSideLeaves === undefined) v2c.useWorkspaceSideLeaves = true;
if (v2c.useWorkspaceSideLeaves === undefined)
v2c.useWorkspaceSideLeaves = true;
await this.plugin.saveSettings();
}
@ -166,7 +188,7 @@ export class FluentIntegration {
* Toggle between V1 and Fluent views
*/
public async toggleVersion() {
const {workspace} = this.plugin.app;
const { workspace } = this.plugin.app;
// Close all V1 views
const v1Leaves = workspace.getLeavesOfType(TASK_VIEW_TYPE);
@ -180,7 +202,6 @@ export class FluentIntegration {
if (!this.plugin.settings.fluentView) {
this.plugin.settings.fluentView = {
enableFluent: false,
showFluentRibbon: false,
};
}
this.plugin.settings.fluentView!.enableFluent =

View file

@ -289,7 +289,9 @@ export class FluentSidebar extends Component {
attr: { "aria-label": t("New Task") },
});
setIcon(addBtn, "plus");
this.registerDomEvent(addBtn, "click", () => this.onNavigate("new-task"));
this.registerDomEvent(addBtn, "click", () =>
this.onNavigate("new-task"),
);
}
private renderOtherViewsSection() {
@ -437,7 +439,7 @@ export class FluentSidebar extends Component {
menu.addItem((item) => {
const isDefault =
this.plugin.workspaceManager?.isDefaultWorkspace(w.id);
const title = isDefault ? `${w.name} 🔒` : w.name;
const title = isDefault ? `${w.name}` : w.name;
item.setTitle(title)
.setIcon("layers")

View file

@ -8,6 +8,7 @@ import {
} from "./ProjectPopover";
import type { CustomProject } from "@/common/setting-definition";
import { t } from "@/translations/helper";
import { onWorkspaceSwitched } from "@/components/features/fluent/events/ui-event";
interface Project {
id: string;
@ -78,9 +79,38 @@ export class ProjectList extends Component {
await this.loadExpandedNodes();
await this.loadProjects();
this.render();
// Listen for workspace switches to refresh the project list
this.registerEvent(
onWorkspaceSwitched(this.plugin.app, () => {
// Debounce the refresh to allow tasks to load in the new workspace
this.refreshWithDelay();
}),
);
}
private refreshTimeoutId: NodeJS.Timeout | null = null;
private refreshWithDelay() {
// Clear any pending refresh
if (this.refreshTimeoutId) {
clearTimeout(this.refreshTimeoutId);
}
// Schedule a refresh with a small delay to allow tasks to load
this.refreshTimeoutId = setTimeout(() => {
this.refresh();
this.refreshTimeoutId = null;
}, 100);
}
onunload() {
// Clean up any pending refresh timeout
if (this.refreshTimeoutId) {
clearTimeout(this.refreshTimeoutId);
this.refreshTimeoutId = null;
}
// Clean up any open popover
if (this.currentPopover) {
this.removeChild(this.currentPopover);

View file

@ -16,8 +16,8 @@ import {
emitWorkspaceSwitched,
} from "@/components/features/fluent/events/ui-event";
import { emit, Events } from "@/dataflow/events/Events";
import { t } from "@/translations/helper";
import type TaskProgressBarPlugin from "@/index";
import { TaskProgressBarSettings } from "@/common/setting-definition";
export class WorkspaceManager {
private app: App;
@ -48,7 +48,7 @@ export class WorkspaceManager {
byId: {
[defaultId]: {
id: defaultId,
name: "Default",
name: t("Default"),
updatedAt: Date.now(),
settings: {}, // Default workspace has no overrides
},
@ -70,7 +70,7 @@ export class WorkspaceManager {
config.defaultWorkspaceId = defaultId;
config.byId[defaultId] = {
id: defaultId,
name: "Default",
name: t("Default"),
updatedAt: Date.now(),
settings: {},
};
@ -101,7 +101,7 @@ export class WorkspaceManager {
for (const key of Object.keys(overrides)) {
if (WORKSPACE_SCOPED_KEYS.includes(key as any)) {
(this.plugin.settings as any)[key] = structuredClone(
overrides[key as keyof WorkspaceOverrides]
overrides[key as keyof WorkspaceOverrides],
);
}
}
@ -156,7 +156,7 @@ export class WorkspaceManager {
workspace.settings.fluentFilterState !== undefined
) {
effective.fluentFilterState = structuredClone(
workspace.settings.fluentFilterState
workspace.settings.fluentFilterState,
);
}
@ -256,7 +256,7 @@ export class WorkspaceManager {
if (config.activeWorkspaceId === workspaceId) {
console.log(
"[TG-WORKSPACE] setActiveWorkspace:noop (already active)",
{ id: workspaceId }
{ id: workspaceId },
);
return; // Already active
}
@ -277,7 +277,7 @@ export class WorkspaceManager {
public async createWorkspace(
name: string,
baseWorkspaceId?: string,
icon?: string
icon?: string,
): Promise<WorkspaceData> {
const config = this.getWorkspacesConfig();
const id = this.generateId();
@ -360,7 +360,7 @@ export class WorkspaceManager {
public async renameWorkspace(
workspaceId: string,
newName: string,
icon?: string
icon?: string,
): Promise<void> {
const config = this.getWorkspacesConfig();
const workspace = config.byId[workspaceId];
@ -382,7 +382,7 @@ export class WorkspaceManager {
// Save overrides for a workspace
public async saveOverrides(
workspaceId: string,
effective: EffectiveSettings
effective: EffectiveSettings,
): Promise<void> {
const config = this.getWorkspacesConfig();
@ -396,7 +396,7 @@ export class WorkspaceManager {
key !== "fluentFilterState"
) {
(this.plugin.settings as any)[key] = structuredClone(
effective[key]
effective[key],
);
changedKeys.push(key);
}
@ -406,7 +406,7 @@ export class WorkspaceManager {
const ws = config.byId[workspaceId];
ws.settings = (ws.settings || {}) as any;
(ws.settings as any).fluentFilterState = structuredClone(
effective.fluentFilterState
effective.fluentFilterState,
);
ws.updatedAt = Date.now();
changedKeys.push("fluentFilterState");
@ -421,7 +421,7 @@ export class WorkspaceManager {
emitWorkspaceOverridesSaved(
this.app,
workspaceId,
changedKeys.length ? changedKeys : undefined
changedKeys.length ? changedKeys : undefined,
);
emit(this.app, Events.SETTINGS_CHANGED);
return;
@ -453,7 +453,7 @@ export class WorkspaceManager {
// Save overrides quietly without triggering SETTINGS_CHANGED event
public async saveOverridesQuietly(
workspaceId: string,
effective: EffectiveSettings
effective: EffectiveSettings,
): Promise<void> {
const config = this.getWorkspacesConfig();
@ -466,7 +466,7 @@ export class WorkspaceManager {
key !== "fluentFilterState"
) {
(this.plugin.settings as any)[key] = structuredClone(
effective[key]
effective[key],
);
}
}
@ -475,14 +475,14 @@ export class WorkspaceManager {
const ws = config.byId[workspaceId];
ws.settings = (ws.settings || {}) as any;
(ws.settings as any).fluentFilterState = structuredClone(
effective.fluentFilterState
effective.fluentFilterState,
);
ws.updatedAt = Date.now();
}
console.log("[TG-WORKSPACE] saveOverridesQuietly(default)", {
workspaceId,
keys: WORKSPACE_SCOPED_KEYS.filter(
(k) => (effective as any)[k] !== undefined
(k) => (effective as any)[k] !== undefined,
),
});
this.clearCache();
@ -651,7 +651,7 @@ export class WorkspaceManager {
// Import workspace configuration
public async importWorkspace(
jsonData: string,
name?: string
name?: string,
): Promise<WorkspaceData | null> {
try {
const importData = JSON.parse(jsonData);
@ -698,8 +698,13 @@ export class WorkspaceManager {
* @returns true if the sidebar component is hidden
*/
public isSidebarComponentHidden(
componentId: 'projects-list' | 'tags-list' | 'view-switcher' | 'top-views' | 'bottom-views',
workspaceId?: string
componentId:
| "projects-list"
| "tags-list"
| "view-switcher"
| "top-views"
| "bottom-views",
workspaceId?: string,
): boolean {
const workspace = workspaceId
? this.getWorkspace(workspaceId)
@ -709,7 +714,9 @@ export class WorkspaceManager {
return false;
}
return workspace.settings.hiddenModules.sidebarComponents.includes(componentId);
return workspace.settings.hiddenModules.sidebarComponents.includes(
componentId,
);
}
/**
@ -719,8 +726,13 @@ export class WorkspaceManager {
* @returns true if the feature component is hidden
*/
public isFeatureHidden(
featureId: 'details-panel' | 'quick-capture' | 'filter' | 'progress-bar' | 'task-mark',
workspaceId?: string
featureId:
| "details-panel"
| "quick-capture"
| "filter"
| "progress-bar"
| "task-mark",
workspaceId?: string,
): boolean {
const workspace = workspaceId
? this.getWorkspace(workspaceId)
@ -744,9 +756,11 @@ export class WorkspaceManager {
: this.getActiveWorkspace();
const hiddenViews = workspace?.settings?.hiddenModules?.views || [];
const allViews = this.plugin.settings.viewConfiguration.map(v => v.id);
const allViews = this.plugin.settings.viewConfiguration.map(
(v) => v.id,
);
return allViews.filter(viewId => !hiddenViews.includes(viewId));
return allViews.filter((viewId) => !hiddenViews.includes(viewId));
}
/**
@ -754,7 +768,10 @@ export class WorkspaceManager {
* @param viewId - The view ID to toggle
* @param workspaceId - Optional workspace ID, defaults to active workspace
*/
public async toggleViewVisibility(viewId: string, workspaceId?: string): Promise<void> {
public async toggleViewVisibility(
viewId: string,
workspaceId?: string,
): Promise<void> {
const workspace = workspaceId
? this.getWorkspace(workspaceId)
: this.getActiveWorkspace();
@ -783,7 +800,7 @@ export class WorkspaceManager {
await this.plugin.saveSettings();
// Emit event to notify UI components
emitWorkspaceOverridesSaved(this.app, workspace.id, ['hiddenModules']);
emitWorkspaceOverridesSaved(this.app, workspace.id, ["hiddenModules"]);
}
/**
@ -791,7 +808,10 @@ export class WorkspaceManager {
* @param viewIds - Array of view IDs to hide
* @param workspaceId - Optional workspace ID, defaults to active workspace
*/
public async setHiddenViews(viewIds: string[], workspaceId?: string): Promise<void> {
public async setHiddenViews(
viewIds: string[],
workspaceId?: string,
): Promise<void> {
const workspace = workspaceId
? this.getWorkspace(workspaceId)
: this.getActiveWorkspace();
@ -807,7 +827,7 @@ export class WorkspaceManager {
this.clearCache();
await this.plugin.saveSettings();
emitWorkspaceOverridesSaved(this.app, workspace.id, ['hiddenModules']);
emitWorkspaceOverridesSaved(this.app, workspace.id, ["hiddenModules"]);
}
/**
@ -816,8 +836,14 @@ export class WorkspaceManager {
* @param workspaceId - Optional workspace ID, defaults to active workspace
*/
public async setHiddenSidebarComponents(
componentIds: Array<'projects-list' | 'tags-list' | 'view-switcher' | 'top-views' | 'bottom-views'>,
workspaceId?: string
componentIds: Array<
| "projects-list"
| "tags-list"
| "view-switcher"
| "top-views"
| "bottom-views"
>,
workspaceId?: string,
): Promise<void> {
const workspace = workspaceId
? this.getWorkspace(workspaceId)
@ -834,7 +860,7 @@ export class WorkspaceManager {
this.clearCache();
await this.plugin.saveSettings();
emitWorkspaceOverridesSaved(this.app, workspace.id, ['hiddenModules']);
emitWorkspaceOverridesSaved(this.app, workspace.id, ["hiddenModules"]);
}
/**
@ -843,8 +869,14 @@ export class WorkspaceManager {
* @param workspaceId - Optional workspace ID, defaults to active workspace
*/
public async setHiddenFeatures(
featureIds: Array<'details-panel' | 'quick-capture' | 'filter' | 'progress-bar' | 'task-mark'>,
workspaceId?: string
featureIds: Array<
| "details-panel"
| "quick-capture"
| "filter"
| "progress-bar"
| "task-mark"
>,
workspaceId?: string,
): Promise<void> {
const workspace = workspaceId
? this.getWorkspace(workspaceId)
@ -861,6 +893,6 @@ export class WorkspaceManager {
this.clearCache();
await this.plugin.saveSettings();
emitWorkspaceOverridesSaved(this.app, workspace.id, ['hiddenModules']);
emitWorkspaceOverridesSaved(this.app, workspace.id, ["hiddenModules"]);
}
}

View file

@ -346,8 +346,34 @@ export class OnboardingView extends ItemView {
* Handle skip button click
*/
private async handleSkip() {
// Auto-enable Fluent Layout for first-time users skipping onboarding
if (!this.plugin.settings.fluentView) {
this.plugin.settings.fluentView = {
enableFluent: true,
};
} else {
this.plugin.settings.fluentView.enableFluent = true;
}
// Ensure fluentConfig is initialized if needed
if (!this.plugin.settings.fluentView.fluentConfig) {
this.plugin.settings.fluentView.fluentConfig = {
enableWorkspaces: true,
defaultWorkspace: "default",
maxOtherViewsBeforeOverflow: 5,
};
}
await this.plugin.saveSettings();
// Mark onboarding as skipped
await this.configManager.skipOnboarding();
this.onComplete();
// Auto-open Task Genius View
await this.plugin.activateTaskView();
// Close onboarding view
this.leaf.detach();
}
@ -372,10 +398,6 @@ export class OnboardingView extends ItemView {
(this.plugin.settings.fluentView as any).fluentConfig = {
enableWorkspaces: true,
defaultWorkspace: "default",
showTopNavigation: true,
showNewSidebar: true,
allowViewSwitching: true,
persistViewMode: true,
maxOtherViewsBeforeOverflow: 5,
};
}

View file

@ -8,15 +8,15 @@ import {
export function renderInterfaceSettingsTab(
settingTab: TaskProgressBarSettingTab,
containerEl: HTMLElement
containerEl: HTMLElement,
) {
// Header
new Setting(containerEl)
.setName(t("User Interface"))
.setDesc(
t(
"Choose your preferred interface style and configure how Task Genius displays in your workspace."
)
"Choose your preferred interface style and configure how Task Genius displays in your workspace.",
),
)
.setHeading();
@ -25,8 +25,8 @@ export function renderInterfaceSettingsTab(
.setName(t("Interface Mode"))
.setDesc(
t(
"Select between the modern Fluent interface or the classic Legacy interface."
)
"Select between the modern Fluent interface or the classic Legacy interface.",
),
)
.setHeading();
@ -47,7 +47,7 @@ export function renderInterfaceSettingsTab(
title: t("Fluent"),
subtitle: t("Modern & Sleek"),
description: t(
"New visual design with elegant animations and modern interactions"
"New visual design with elegant animations and modern interactions",
),
preview: createFluentPreview(),
},
@ -56,7 +56,7 @@ export function renderInterfaceSettingsTab(
title: t("Legacy"),
subtitle: t("Classic & Familiar"),
description: t(
"Keep the familiar interface and interaction style you know"
"Keep the familiar interface and interaction style you know",
),
preview: createLegacyPreview(),
},
@ -76,15 +76,15 @@ export function renderInterfaceSettingsTab(
if (!settingTab.plugin.settings.fluentView) {
settingTab.plugin.settings.fluentView = {
enableFluent: false,
showFluentRibbon: false,
};
}
settingTab.plugin.settings.fluentView.enableFluent = mode === "fluent";
settingTab.plugin.settings.fluentView.enableFluent =
mode === "fluent";
await settingTab.plugin.saveSettings();
// Re-render the settings to show/hide Fluent-specific options
renderFluentSpecificSettings();
}
},
);
// Set initial selection
@ -116,35 +116,32 @@ export function renderInterfaceSettingsTab(
.setName(t("Use Workspace Side Leaves"))
.setDesc(
t(
"Use left/right workspace side leaves for Sidebar and Details. When enabled, the main V2 view won't render in-view sidebar or details."
)
"Use left/right workspace side leaves for Sidebar and Details. When enabled, the main V2 view won't render in-view sidebar or details.",
),
)
.addToggle((toggle) => {
const current = settingTab.plugin.settings.fluentView?.useWorkspaceSideLeaves ?? true;
toggle
.setValue(current)
.onChange(async (value) => {
if (!settingTab.plugin.settings.fluentView) {
settingTab.plugin.settings.fluentView = {
enableFluent: false,
showFluentRibbon: false,
};
}
if (!settingTab.plugin.settings.fluentView.fluentConfig) {
settingTab.plugin.settings.fluentView.fluentConfig = {
enableWorkspaces: true,
defaultWorkspace: "default",
showTopNavigation: true,
showNewSidebar: true,
allowViewSwitching: true,
persistViewMode: true,
};
}
// Store via 'any' to avoid typing constraints for experimental backfill
(settingTab.plugin.settings.fluentView as any).useWorkspaceSideLeaves = value;
await settingTab.plugin.saveSettings();
new Notice(t("Saved. Reopen the view to apply."));
});
const current =
settingTab.plugin.settings.fluentView
?.useWorkspaceSideLeaves ?? true;
toggle.setValue(current).onChange(async (value) => {
if (!settingTab.plugin.settings.fluentView) {
settingTab.plugin.settings.fluentView = {
enableFluent: false,
};
}
if (!settingTab.plugin.settings.fluentView.fluentConfig) {
settingTab.plugin.settings.fluentView.fluentConfig = {
enableWorkspaces: true,
defaultWorkspace: "default",
};
}
// Store via 'any' to avoid typing constraints for experimental backfill
(
settingTab.plugin.settings.fluentView as any
).useWorkspaceSideLeaves = value;
await settingTab.plugin.saveSettings();
new Notice(t("Saved. Reopen the view to apply."));
});
});
// Max Other Views before overflow threshold
@ -152,8 +149,8 @@ export function renderInterfaceSettingsTab(
.setName(t("Max Other Views before overflow"))
.setDesc(
t(
"Number of 'Other Views' to show before grouping the rest into an overflow menu (ellipsis)"
)
"Number of 'Other Views' to show before grouping the rest into an overflow menu (ellipsis)",
),
)
.addText((text) => {
const current =
@ -167,20 +164,20 @@ export function renderInterfaceSettingsTab(
if (!settingTab.plugin.settings.fluentView) {
settingTab.plugin.settings.fluentView = {
enableFluent: false,
showFluentRibbon: false,
};
}
if (!settingTab.plugin.settings.fluentView.fluentConfig) {
settingTab.plugin.settings.fluentView.fluentConfig = {
enableWorkspaces: true,
defaultWorkspace: "default",
showTopNavigation: true,
showNewSidebar: true,
allowViewSwitching: true,
persistViewMode: true,
};
if (
!settingTab.plugin.settings.fluentView
.fluentConfig
) {
settingTab.plugin.settings.fluentView.fluentConfig =
{
enableWorkspaces: true,
defaultWorkspace: "default",
};
}
settingTab.plugin.settings.fluentView.fluentConfig.maxOtherViewsBeforeOverflow = n;
settingTab.plugin.settings.fluentView.fluentConfig.maxOtherViewsBeforeOverflow =
n;
await settingTab.plugin.saveSettings();
}
});

View file

@ -1,22 +1,7 @@
// Deprecated - use WorkspaceData from types/workspace.ts instead
export interface Workspace {
id: string;
name: string;
color: string;
settings?: WorkspaceSettings;
isActive?: boolean;
}
export interface WorkspaceSettings {
projectIds?: string[];
filterConfigs?: Record<string, any>;
viewPreferences?: Record<string, any>;
}
export interface FluentTaskViewState {
currentWorkspace: string;
selectedProject?: string | null;
viewMode: 'list' | 'kanban' | 'tree' | 'calendar';
viewMode: "list" | "kanban" | "tree" | "calendar";
searchQuery?: string;
filterInputValue?: string;
filters?: any;
@ -26,16 +11,7 @@ export type FluentTaskNavigationItem = {
id: string;
label: string;
icon: string;
type: 'primary' | 'project' | 'other';
type: "primary" | "project" | "other";
action?: () => void;
badge?: number;
};
export interface V2ViewConfig {
enableWorkspaces: boolean;
defaultWorkspace?: string;
showTopNavigation: boolean;
showNewSidebar: boolean;
allowViewSwitching: boolean;
persistViewMode: boolean;
}

View file

@ -111,7 +111,8 @@ export const WORKSPACE_SCOPED_KEYS = [
'forecastOption',
'customProjectGroupsAndNames',
'tagCustomOrder',
'fluentFilterState'
'fluentFilterState',
'hiddenModules'
] as const;
export type WorkspaceScopedKey = typeof WORKSPACE_SCOPED_KEYS[number];