mirror of
https://github.com/taskgenius/taskgenius-plugin.git
synced 2026-07-22 06:40:25 +00:00
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:
parent
0d3c6fa352
commit
b475615592
9 changed files with 230 additions and 172 deletions
|
|
@ -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: {
|
||||
|
|
|
|||
|
|
@ -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 =
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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"]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
Loading…
Reference in a new issue