feat(tasks): remember list or Kanban per task list
Each task list (and "Alle Aufgaben") keeps its own view on this device; a single remembered Kanban view from before carries over to its list. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c2aff2ced6
commit
886fb2c711
1 file changed
+38
-8
@@ -92,7 +92,15 @@ const kanbanBoardStyle = (wide: boolean, columns: number): React.CSSProperties =
|
|||||||
};
|
};
|
||||||
|
|
||||||
type GroupBy = 'none' | 'list' | 'tag' | 'status' | 'priority' | 'due';
|
type GroupBy = 'none' | 'list' | 'tag' | 'status' | 'priority' | 'due';
|
||||||
type TasksSession = { listId: string; viewMode: 'list' | 'kanban'; groupAll: GroupBy; groupList: GroupBy };
|
type ViewMode = 'list' | 'kanban';
|
||||||
|
// viewModes: list or Kanban per task list ("all" for Alle Aufgaben); viewMode is the old single value
|
||||||
|
type TasksSession = {
|
||||||
|
listId: string;
|
||||||
|
viewModes: Record<string, ViewMode>;
|
||||||
|
viewMode?: ViewMode;
|
||||||
|
groupAll: GroupBy;
|
||||||
|
groupList: GroupBy;
|
||||||
|
};
|
||||||
|
|
||||||
// "Alle Aufgaben" is grouped by task list unless the user picks something else; a single list has no
|
// "Alle Aufgaben" is grouped by task list unless the user picks something else; a single list has no
|
||||||
// grouping by default (grouping it by list would give one group)
|
// grouping by default (grouping it by list would give one group)
|
||||||
@@ -123,11 +131,20 @@ export const TasksView: React.FC<TasksViewProps> = ({
|
|||||||
onInitialTaskShown,
|
onInitialTaskShown,
|
||||||
openTasksCount,
|
openTasksCount,
|
||||||
}) => {
|
}) => {
|
||||||
// Open list, view and grouping are remembered on this device (new tab, restart of the installed app)
|
// Open list, view per list and grouping are remembered on this device (new tab, restart of the
|
||||||
|
// installed app)
|
||||||
const remembered = useMemo(() => readViewMemory<TasksSession>('tasks'), []);
|
const remembered = useMemo(() => readViewMemory<TasksSession>('tasks'), []);
|
||||||
const [viewMode, setViewMode] = useState<'list' | 'kanban'>(() =>
|
const [viewModes, setViewModes] = useState<Record<string, ViewMode>>(() => {
|
||||||
remembered.viewMode === 'kanban' ? 'kanban' : 'list'
|
const out: Record<string, ViewMode> = {};
|
||||||
);
|
if (remembered.viewModes && typeof remembered.viewModes === 'object') {
|
||||||
|
for (const [id, mode] of Object.entries(remembered.viewModes)) {
|
||||||
|
if (mode === 'kanban') out[id] = 'kanban';
|
||||||
|
}
|
||||||
|
} else if (remembered.viewMode === 'kanban' && remembered.listId) {
|
||||||
|
out[remembered.listId] = 'kanban'; // stored before views were kept per list
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
});
|
||||||
const [groupAll, setGroupAll] = useState<GroupBy>(() =>
|
const [groupAll, setGroupAll] = useState<GroupBy>(() =>
|
||||||
remembered.groupAll && remembered.groupAll in GROUP_LABELS ? remembered.groupAll : DEFAULT_GROUP_ALL
|
remembered.groupAll && remembered.groupAll in GROUP_LABELS ? remembered.groupAll : DEFAULT_GROUP_ALL
|
||||||
);
|
);
|
||||||
@@ -153,13 +170,25 @@ export const TasksView: React.FC<TasksViewProps> = ({
|
|||||||
// only a convenience
|
// only a convenience
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const isKanbanWide = viewMode === 'kanban' && kanbanWide;
|
|
||||||
const [filter, setFilter] = useState<'open' | 'done' | 'discarded'>('open');
|
const [filter, setFilter] = useState<'open' | 'done' | 'discarded'>('open');
|
||||||
const [tasks, setTasks] = useState<Thought[]>([]);
|
const [tasks, setTasks] = useState<Thought[]>([]);
|
||||||
const [taskLists, setTaskLists] = useState<TaskList[]>([]);
|
const [taskLists, setTaskLists] = useState<TaskList[]>([]);
|
||||||
const [selectedListId, setSelectedListId] = useState<string>(
|
const [selectedListId, setSelectedListId] = useState<string>(
|
||||||
() => remembered.listId || 'all'
|
() => remembered.listId || 'all'
|
||||||
);
|
);
|
||||||
|
const viewMode: ViewMode = viewModes[selectedListId] || 'list';
|
||||||
|
// Only Kanban is stored; the list view is the default
|
||||||
|
const setViewMode = useCallback(
|
||||||
|
(mode: ViewMode) =>
|
||||||
|
setViewModes((prev) => {
|
||||||
|
const next = { ...prev };
|
||||||
|
if (mode === 'kanban') next[selectedListId] = 'kanban';
|
||||||
|
else delete next[selectedListId];
|
||||||
|
return next;
|
||||||
|
}),
|
||||||
|
[selectedListId]
|
||||||
|
);
|
||||||
|
const isKanbanWide = viewMode === 'kanban' && kanbanWide;
|
||||||
const isAllTasks = selectedListId === 'all';
|
const isAllTasks = selectedListId === 'all';
|
||||||
const groupBy: GroupBy = isAllTasks ? groupAll : groupList;
|
const groupBy: GroupBy = isAllTasks ? groupAll : groupList;
|
||||||
const setGroupBy = (g: GroupBy) => (isAllTasks ? setGroupAll(g) : setGroupList(g));
|
const setGroupBy = (g: GroupBy) => (isAllTasks ? setGroupAll(g) : setGroupList(g));
|
||||||
@@ -169,8 +198,8 @@ export const TasksView: React.FC<TasksViewProps> = ({
|
|||||||
.filter((id) => isAllTasks || id !== 'list')
|
.filter((id) => isAllTasks || id !== 'list')
|
||||||
.map((id) => ({ id, label: GROUP_LABELS[id] }));
|
.map((id) => ({ id, label: GROUP_LABELS[id] }));
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
writeViewMemory<TasksSession>('tasks', { listId: selectedListId, viewMode, groupAll, groupList });
|
writeViewMemory<TasksSession>('tasks', { listId: selectedListId, viewModes, groupAll, groupList });
|
||||||
}, [selectedListId, viewMode, groupAll, groupList]);
|
}, [selectedListId, viewModes, groupAll, groupList]);
|
||||||
const [teams, setTeams] = useState<Team[]>([]);
|
const [teams, setTeams] = useState<Team[]>([]);
|
||||||
const [collaborators, setCollaborators] = useState<User[]>([]);
|
const [collaborators, setCollaborators] = useState<User[]>([]);
|
||||||
// Task trash of the selected list (or all): deleted tasks and cleared or cleaned-up completed ones
|
// Task trash of the selected list (or all): deleted tasks and cleared or cleaned-up completed ones
|
||||||
@@ -1538,6 +1567,7 @@ export const TasksView: React.FC<TasksViewProps> = ({
|
|||||||
selectedTag,
|
selectedTag,
|
||||||
groupBy,
|
groupBy,
|
||||||
defaultGroupBy,
|
defaultGroupBy,
|
||||||
|
setViewMode,
|
||||||
sortBy,
|
sortBy,
|
||||||
openTasks.length,
|
openTasks.length,
|
||||||
doneTasks.length,
|
doneTasks.length,
|
||||||
|
|||||||
Reference in new issue
Block a user