Merge dev into main (v0.59.1)
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 30s
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 30s
This commit is contained in:
commit
f22a18c89d
6 files changed
+55
-7
No files matched your search
+8
-1
@@ -6,6 +6,12 @@ Das Format folgt [Keep a Changelog](https://keepachangelog.com/de/1.1.0/), die V
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [0.59.1] - 2026-11-02
|
||||
|
||||
### Fixed
|
||||
- Desktop: Das Layout verschiebt sich nicht mehr um ein paar Pixel, wenn eine Seite scrollbar wird (z. B. ein breites Kanban-Board) oder beim Wechsel zwischen Seiten mit und ohne Scrollbalken. Der Platz für den Scrollbalken bleibt immer frei.
|
||||
- Aufgaben: Beim Wechsel der Aufgabenliste blitzten kurz die Aufgaben der vorherigen Liste auf, besonders beim Wechsel zwischen Listen- und Kanban-Ansicht. Jetzt erscheint die neue Liste sofort mit ihren Aufgaben.
|
||||
|
||||
## [0.59.0] - 2026-11-02
|
||||
|
||||
### Added
|
||||
@@ -853,7 +859,8 @@ Das Format folgt [Keep a Changelog](https://keepachangelog.com/de/1.1.0/), die V
|
||||
- Geteilte Listen (Einkaufs-, Pack- und Checklisten) mit `#Kategorie`-Gruppierung, Mengenangaben und Echtzeit-Abhaken.
|
||||
- Benutzer-, Gruppen- und Admin-Verwaltung (Ersteinrichtungs-Assistent, Einladungscodes, Profilbilder, persönliche API-Keys & Webhook-Ingest `/api/v1/webhooks/ingest`, JSON-Datenexport) sowie CSS-Theme-Engine mit 4 Themes (`Dark`, `Light`, `High Contrast`, `Soft`) und PWA-Unterstützung.
|
||||
|
||||
[Unreleased]: https://git.dsit.me/sandrodach/MindSift/compare/v0.59.0...dev
|
||||
[Unreleased]: https://git.dsit.me/sandrodach/MindSift/compare/v0.59.1...dev
|
||||
[0.59.1]: https://git.dsit.me/sandrodach/MindSift/compare/v0.59.0...v0.59.1
|
||||
[0.59.0]: https://git.dsit.me/sandrodach/MindSift/compare/v0.58.0...v0.59.0
|
||||
[0.58.0]: https://git.dsit.me/sandrodach/MindSift/compare/v0.57.0...v0.58.0
|
||||
[0.57.0]: https://git.dsit.me/sandrodach/MindSift/compare/v0.56.0...v0.57.0
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
[](#)
|
||||
[](#-schnellstart)
|
||||
[](#-deine-daten-gehören-dir)
|
||||
[](CHANGELOG.md)
|
||||
[](CHANGELOG.md)
|
||||
|
||||
**MindSift** ist eine selbst gehostete Schaltstelle für spontane Gedanken, Aufgaben mit Kanban-Board, hierarchische Outliner-Notizen, die mehrere Personen gleichzeitig bearbeiten können, und gemeinsame Listen. Alles läuft als ein einzelner Container mit eingebetteter SQLite-Datenbank, auf deinem eigenen Server.
|
||||
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "mindsift-frontend",
|
||||
"version": "0.59.0",
|
||||
"version": "0.59.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "mindsift-frontend",
|
||||
"version": "0.59.0",
|
||||
"version": "0.59.1",
|
||||
"license": "AGPL-3.0-only",
|
||||
"dependencies": {
|
||||
"@fontsource-variable/inter": "5.3.0",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "mindsift-frontend",
|
||||
"private": true,
|
||||
"version": "0.59.0",
|
||||
"version": "0.59.1",
|
||||
"license": "AGPL-3.0-only",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -173,7 +173,7 @@ export const TasksView: React.FC<TasksViewProps> = ({
|
||||
const [filter, setFilter] = useState<'open' | 'done' | 'discarded'>('open');
|
||||
const [tasks, setTasks] = useState<Thought[]>([]);
|
||||
const [taskLists, setTaskLists] = useState<TaskList[]>([]);
|
||||
const [selectedListId, setSelectedListId] = useState<string>(
|
||||
const [selectedListId, setSelectedListIdState] = useState<string>(
|
||||
() => remembered.listId || 'all'
|
||||
);
|
||||
const viewMode: ViewMode = viewModes[selectedListId] || 'list';
|
||||
@@ -304,6 +304,10 @@ export const TasksView: React.FC<TasksViewProps> = ({
|
||||
]);
|
||||
if (seq !== loadSeqRef.current) return; // a newer reload is under way
|
||||
loadedListRef.current = listId;
|
||||
listCacheRef.current.set(listId, {
|
||||
tasks: Array.isArray(allTasks) ? allTasks : [],
|
||||
trash: Array.isArray(trash) ? trash : [],
|
||||
});
|
||||
setTasks(Array.isArray(allTasks) ? allTasks : []);
|
||||
setTaskLists(Array.isArray(allLists) ? allLists : []);
|
||||
// The remembered list was deleted or unshared meanwhile
|
||||
@@ -327,6 +331,33 @@ export const TasksView: React.FC<TasksViewProps> = ({
|
||||
const selectedListIdRef = useRef(selectedListId);
|
||||
selectedListIdRef.current = selectedListId;
|
||||
|
||||
// Last known tasks of every list opened in this session. Switching lists shows them in the same render
|
||||
// as the new list's view (list or Kanban), so the board never flashes the previous list's tasks; the
|
||||
// reload then brings them up to date. A list not opened yet takes its share of "Alle Aufgaben".
|
||||
const listCacheRef = useRef(new Map<string, { tasks: Thought[]; trash: TrashedTask[] }>());
|
||||
useEffect(() => {
|
||||
if (!loading && loadedListRef.current === selectedListId) {
|
||||
listCacheRef.current.set(selectedListId, { tasks, trash: taskTrash });
|
||||
}
|
||||
}, [tasks, taskTrash, loading, selectedListId]);
|
||||
const setSelectedListId = useCallback((id: string) => {
|
||||
if (id === selectedListIdRef.current) return;
|
||||
const cache = listCacheRef.current;
|
||||
let known = cache.get(id);
|
||||
const all = cache.get('all');
|
||||
if (!known && id !== 'all' && all) {
|
||||
known = {
|
||||
tasks: all.tasks.filter((t) => t.taskListId === id),
|
||||
trash: all.trash.filter((t) => t.taskListId === id),
|
||||
};
|
||||
}
|
||||
setTasks(known ? known.tasks : []);
|
||||
setTaskTrash(known ? known.trash : []);
|
||||
setLoading(!known);
|
||||
loadedListRef.current = known ? id : null;
|
||||
setSelectedListIdState(id);
|
||||
}, []);
|
||||
|
||||
const onRefreshStatsRef = useRef(onRefreshStats);
|
||||
onRefreshStatsRef.current = onRefreshStats;
|
||||
// The realtime handler is registered once; it must reload with the current list, not the first one
|
||||
@@ -1371,7 +1402,9 @@ export const TasksView: React.FC<TasksViewProps> = ({
|
||||
try {
|
||||
await api.deleteTaskList(listId);
|
||||
setTaskLists((prev) => prev.filter((l) => l.id !== listId));
|
||||
setSelectedListId('all');
|
||||
// Plain switch: the deleted list's tasks belong to "Alle Aufgaben" anyway (and the menu effect keeps
|
||||
// this handler out of its dependencies)
|
||||
setSelectedListIdState('all');
|
||||
} catch (err: any) {
|
||||
alert(err.message);
|
||||
}
|
||||
@@ -1568,6 +1601,7 @@ export const TasksView: React.FC<TasksViewProps> = ({
|
||||
groupBy,
|
||||
defaultGroupBy,
|
||||
setViewMode,
|
||||
setSelectedListId,
|
||||
sortBy,
|
||||
openTasks.length,
|
||||
doneTasks.length,
|
||||
|
||||
@@ -29,6 +29,13 @@
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
/* Room for the scrollbar is always kept: pages that scroll (e.g. a wide Kanban board) and pages that do
|
||||
not keep the same width, so nothing shifts when switching tabs. Overlay scrollbars (phones) are not
|
||||
affected. */
|
||||
html {
|
||||
scrollbar-gutter: stable;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--bg-app);
|
||||
color: var(--text-main);
|
||||
|
||||
Reference in new issue
Block a user