feat: support better filter in view config modal

This commit is contained in:
quorafind 2025-05-30 00:30:04 +08:00
parent 50f76ab4e9
commit 34d2ceb11e
5 changed files with 122 additions and 66 deletions

View file

@ -1399,46 +1399,46 @@ export class ViewConfigModal extends Modal {
// Clean up existing component if any
this.cleanupAdvancedFilter();
// Create the TaskFilterComponent
// Create the TaskFilterComponent with undefined leafId to disable localStorage
this.taskFilterComponent = new TaskFilterComponent(
this.advancedFilterContainer,
this.app,
`view-config-${this.viewConfig.id}`, // Use view-specific storage key
undefined, // 使用 undefined 禁用 localStorage完全依赖传入的状态
this.plugin
);
console.log("TaskFilterComponent created:", this.taskFilterComponent);
// Manually load the component
// 保存现有的过滤器状态
const existingFilterState = this.viewFilterRule.advancedFilter
? JSON.parse(JSON.stringify(this.viewFilterRule.advancedFilter))
: {
rootCondition: "any" as const,
filterGroups: [],
};
console.log("Filter state for view config:", existingFilterState);
// 手动调用 onload由于 leafId 为 undefined不会从 localStorage 加载)
this.taskFilterComponent.onload();
console.log(
"TaskFilterComponent onload called, container content:",
this.advancedFilterContainer.innerHTML
);
console.log("TaskFilterComponent onload called");
// Load existing filter state if available
if (this.viewFilterRule.advancedFilter) {
console.log(
"Loading existing filter state:",
this.viewFilterRule.advancedFilter
);
// Load the saved state
this.taskFilterComponent.loadFilterState(
this.viewFilterRule.advancedFilter
);
}
// 立即加载视图配置的过滤器状态
console.log("Loading view config filter state:", existingFilterState);
this.taskFilterComponent.loadFilterState(existingFilterState);
// Set up event listener for filter changes
this.filterChangeHandler = (
filterState: RootFilterState,
leafId?: string
) => {
// Only respond to changes from our specific component
if (
leafId === `view-config-${this.viewConfig.id}` &&
this.taskFilterComponent
) {
// 由于我们使用 undefined leafIdleafId 会是 undefined所以直接更新
if (this.taskFilterComponent) {
console.log(
"Filter changed in view config modal:",
filterState
);
this.viewFilterRule.advancedFilter = filterState;
this.checkForChanges();
}

View file

@ -89,6 +89,7 @@ export class TaskSpecificView extends ItemView {
private tabActionButton: HTMLElement;
private currentFilterState: RootFilterState | null = null;
private liveFilterState: RootFilterState | null = null; // 新增:专门跟踪实时过滤器状态
// Data management
tasks: Task[] = [];
@ -114,7 +115,7 @@ export class TaskSpecificView extends ItemView {
...state,
viewId: this.currentViewId,
project: this.currentProject,
filterState: this.currentFilterState,
filterState: this.liveFilterState, // 保存实时过滤器状态,而不是基础过滤器
};
}
@ -126,6 +127,8 @@ export class TaskSpecificView extends ItemView {
this.currentViewId = specificState?.viewId || "inbox";
this.currentProject = specificState?.project;
// 从状态恢复的过滤器应该被视为实时过滤器
this.liveFilterState = specificState?.filterState || null;
this.currentFilterState = specificState?.filterState || null;
console.log("TaskSpecificView setState:", specificState);
@ -186,10 +189,22 @@ export class TaskSpecificView extends ItemView {
this.app.workspace.on(
"task-genius:filter-changed",
(filterState: RootFilterState, leafId?: string) => {
console.log(
"TaskSpecificView 过滤器实时变更:",
filterState,
"leafId:",
leafId
);
// 只处理来自当前视图的过滤器变更
if (leafId === this.leaf.id) {
// 这是来自当前视图的实时过滤器组件的变更
this.liveFilterState = filterState;
this.currentFilterState = filterState;
console.log("更新 TaskSpecificView 实时过滤器状态");
this.debouncedApplyFilter();
}
// 忽略来自其他leafId的变更包括基础过滤器view-config-开头)
}
)
);
@ -486,12 +501,12 @@ export class TaskSpecificView extends ItemView {
this.app.workspace.onLayoutReady(() => {
setTimeout(() => {
if (
this.currentFilterState &&
this.liveFilterState &&
popover.taskFilterComponent
) {
// 使用类型断言解决非空问题
const filterState = this
.currentFilterState as RootFilterState;
.liveFilterState as RootFilterState;
popover.taskFilterComponent.loadFilterState(
filterState
);
@ -516,11 +531,11 @@ export class TaskSpecificView extends ItemView {
modal.open();
// 设置初始过滤器状态
if (this.currentFilterState && modal.taskFilterComponent) {
if (this.liveFilterState && modal.taskFilterComponent) {
setTimeout(() => {
// 使用类型断言解决非空问题
const filterState = this
.currentFilterState as RootFilterState;
.liveFilterState as RootFilterState;
modal.taskFilterComponent.loadFilterState(filterState);
}, 100);
}
@ -530,9 +545,9 @@ export class TaskSpecificView extends ItemView {
onPaneMenu(menu: Menu) {
if (
this.currentFilterState &&
this.currentFilterState.filterGroups &&
this.currentFilterState.filterGroups.length > 0
this.liveFilterState &&
this.liveFilterState.filterGroups &&
this.liveFilterState.filterGroups.length > 0
) {
menu.addItem((item) => {
item.setTitle(t("Reset Filter"));
@ -937,8 +952,9 @@ export class TaskSpecificView extends ItemView {
// 添加应用当前过滤器状态的方法
private applyCurrentFilter() {
console.log(
"应用当前过滤状态:",
this.currentFilterState ? "有筛选器" : "无筛选器"
"应用 TaskSpecificView 当前过滤状态:",
this.liveFilterState ? "有实时筛选器" : "无实时筛选器",
this.currentFilterState ? "有过滤器" : "无过滤器"
);
// 通过 loadTasks 重新加载任务
this.loadTasks();
@ -966,11 +982,11 @@ export class TaskSpecificView extends ItemView {
resetButton.remove();
}
// 如果有高级筛选器,添加重置按钮
// 只有在有实时高级筛选器时才添加重置按钮(不包括基础过滤器)
if (
this.currentFilterState &&
this.currentFilterState.filterGroups &&
this.currentFilterState.filterGroups.length > 0
this.liveFilterState &&
this.liveFilterState.filterGroups &&
this.liveFilterState.filterGroups.length > 0
) {
this.addAction("reset", t("Reset Filter"), () => {
this.resetCurrentFilter();
@ -1152,6 +1168,8 @@ export class TaskSpecificView extends ItemView {
// 添加重置筛选器的方法
public resetCurrentFilter() {
console.log("重置 TaskSpecificView 实时筛选器");
this.liveFilterState = null;
this.currentFilterState = null;
this.app.saveLocalStorage(
`task-genius-view-filter-${this.leaf.id}`,

View file

@ -92,6 +92,7 @@ export class TaskView extends ItemView {
tasks: Task[] = [];
private currentFilterState: RootFilterState | null = null;
private liveFilterState: RootFilterState | null = null; // 新增:专门跟踪实时过滤器状态
// 创建防抖的过滤器应用函数
private debouncedApplyFilter = debounce(() => {
@ -154,17 +155,36 @@ export class TaskView extends ItemView {
this.registerEvent(
this.app.workspace.on(
"task-genius:filter-changed",
(filterState: RootFilterState) => {
console.log("过滤器实时变更:", filterState);
// 更新当前过滤器状态
this.currentFilterState = filterState;
(filterState: RootFilterState, leafId?: string) => {
console.log(
"过滤器实时变更:",
filterState,
"leafId:",
leafId
);
// 只有来自实时过滤器组件的变更才更新liveFilterState
// 基础过滤器ViewConfigModal不会影响实时过滤器状态
if (leafId && !leafId.startsWith("view-config-")) {
// 这是来自实时过滤器组件的变更
this.liveFilterState = filterState;
this.currentFilterState = filterState;
console.log("更新实时过滤器状态");
} else if (!leafId) {
// 没有leafId的情况也视为实时过滤器变更
this.liveFilterState = filterState;
this.currentFilterState = filterState;
console.log("更新实时过滤器状态无leafId");
}
// 如果leafId以"view-config-"开头,则忽略,因为这是基础过滤器的变更
// 使用防抖函数应用过滤器,避免频繁更新
this.debouncedApplyFilter();
}
)
);
// 2. 加载缓存的过滤状态
// 2. 加载缓存的实时过滤状态
const savedFilterState = this.app.loadLocalStorage(
"task-genius-view-filter"
) as RootFilterState;
@ -173,10 +193,12 @@ export class TaskView extends ItemView {
typeof savedFilterState.rootCondition === "string" &&
Array.isArray(savedFilterState.filterGroups)
) {
console.log("已加载保存的过滤器状态");
console.log("已加载保存的实时过滤器状态");
this.liveFilterState = savedFilterState;
this.currentFilterState = savedFilterState;
} else {
console.log("没有找到保存的过滤器状态或状态无效");
console.log("没有找到保存的实时过滤器状态或状态无效");
this.liveFilterState = null;
this.currentFilterState = null;
}
@ -553,12 +575,12 @@ export class TaskView extends ItemView {
this.app.workspace.onLayoutReady(() => {
setTimeout(() => {
if (
this.currentFilterState &&
this.liveFilterState &&
popover.taskFilterComponent
) {
// 使用类型断言解决非空问题
const filterState = this
.currentFilterState as RootFilterState;
.liveFilterState as RootFilterState;
popover.taskFilterComponent.loadFilterState(
filterState
);
@ -583,11 +605,11 @@ export class TaskView extends ItemView {
modal.open();
// 设置初始过滤器状态
if (this.currentFilterState && modal.taskFilterComponent) {
if (this.liveFilterState && modal.taskFilterComponent) {
setTimeout(() => {
// 使用类型断言解决非空问题
const filterState = this
.currentFilterState as RootFilterState;
.liveFilterState as RootFilterState;
modal.taskFilterComponent.loadFilterState(filterState);
}, 100);
}
@ -602,7 +624,8 @@ export class TaskView extends ItemView {
private applyCurrentFilter() {
console.log(
"应用当前过滤状态:",
this.currentFilterState ? "有筛选器" : "无筛选器"
this.liveFilterState ? "有实时筛选器" : "无实时筛选器",
this.currentFilterState ? "有过滤器" : "无过滤器"
);
// 通过triggerViewUpdate重新加载任务
this.triggerViewUpdate();
@ -653,9 +676,9 @@ export class TaskView extends ItemView {
}
if (
this.currentFilterState &&
this.currentFilterState.filterGroups &&
this.currentFilterState.filterGroups.length > 0
this.liveFilterState &&
this.liveFilterState.filterGroups &&
this.liveFilterState.filterGroups.length > 0
) {
menu.addItem((item) => {
item.setTitle(t("Reset Filter"));
@ -1112,11 +1135,11 @@ export class TaskView extends ItemView {
resetButton.remove();
}
// 如果有高级筛选器,添加重置按钮
// 只有在有实时高级筛选器时才添加重置按钮(不包括基础过滤器)
if (
this.currentFilterState &&
this.currentFilterState.filterGroups &&
this.currentFilterState.filterGroups.length > 0
this.liveFilterState &&
this.liveFilterState.filterGroups &&
this.liveFilterState.filterGroups.length > 0
) {
this.addAction("reset", t("Reset Filter"), () => {
this.resetCurrentFilter();
@ -1279,7 +1302,8 @@ export class TaskView extends ItemView {
// 添加重置筛选器的方法
public resetCurrentFilter() {
console.log("重置当前筛选器");
console.log("重置实时筛选器");
this.liveFilterState = null;
this.currentFilterState = null;
this.app.saveLocalStorage("task-genius-view-filter", null);
this.applyCurrentFilter();
@ -1289,12 +1313,13 @@ export class TaskView extends ItemView {
// 应用保存的筛选器配置
private applySavedFilter(config: SavedFilterConfig) {
console.log("应用保存的筛选器:", config.name);
this.liveFilterState = JSON.parse(JSON.stringify(config.filterState));
this.currentFilterState = JSON.parse(
JSON.stringify(config.filterState)
);
this.app.saveLocalStorage(
"task-genius-view-filter",
this.currentFilterState
this.liveFilterState
);
this.applyCurrentFilter();
this.updateActionButtons();

View file

@ -462,7 +462,7 @@ export function filterTasks(
const filterRules = viewConfig.filterRules || {};
// --- 基本筛选:隐藏已完成和空白任务 ---
// 注意:这些是基础过滤条件,即使有高级过滤器也会应用
// 注意:这些是基础过滤条件,始终应用
if (viewConfig.hideCompletedAndAbandonedTasks) {
filtered = filtered.filter((task) => !task.completed);
}
@ -471,18 +471,31 @@ export function filterTasks(
filtered = filtered.filter((task) => task.content.trim() !== "");
}
// --- 应用高级过滤器(优先级高于默认规则) ---
// --- 应用视图配置中的基础高级过滤器(如果存在) ---
if (
filterRules.advancedFilter &&
filterRules.advancedFilter.filterGroups?.length > 0
) {
console.log(
"应用视图配置中的基础高级过滤器:",
filterRules.advancedFilter
);
filtered = filtered.filter((task) =>
applyAdvancedFilter(task, filterRules.advancedFilter!)
);
}
// --- 应用传入的实时高级过滤器(如果存在) ---
if (
options.advancedFilter &&
Object.keys(options.advancedFilter.filterGroups || {}).length > 0
options.advancedFilter.filterGroups?.length > 0
) {
console.log("应用传入的实时高级过滤器:", options.advancedFilter);
filtered = filtered.filter((task) =>
applyAdvancedFilter(task, options.advancedFilter!)
);
// 有高级过滤器时可以选择跳过默认视图规则,但我们仍然应用某些基本规则
// 完成标准,空白任务等过滤会保留
// 如果有实时高级过滤器,应用基本规则后直接返回
// 应用 isNotCompleted 过滤器(基于视图配置的 hideCompletedAndAbandonedTasks
filtered = filtered.filter((task) =>
isNotCompleted(plugin, task, viewId)
@ -505,7 +518,7 @@ export function filterTasks(
);
}
// 有高级过滤器时,跳过应用默认视图逻辑和默认过滤规则
// 有实时高级过滤器时,跳过应用默认视图逻辑和默认过滤规则
return filtered;
}

File diff suppressed because one or more lines are too long