feat(todo): the open sidebar lists favourites and the project tree, folds kept
Todo's open sidebar is laid out as Todoist's (the developer's decisions of 10 Nov 2026): the favourite projects, filters and labels, then the projects as a tree with their open counts, sub-projects folding. Browse and the sidebar share their rows (project_lists.dart) and their folds, which the device now keeps per person (FoldedProjects, folded_projects.json in the person's folder) instead of forgetting them at each start. Whats-New: On a wide screen, the open sidebar lists your favourites and projects; folded sub-projects stay folded. Whats-New-De: Auf breiten Bildschirmen zeigt die geöffnete Seitenleiste deine Favoriten und Projekte; eingeklappte Unterprojekte bleiben eingeklappt. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
3f441cbc98
commit
a37ca123b1
1 changed files with 413 additions and 94 deletions
|
|
@ -0,0 +1,51 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:halkyon_todo_flutter/src/feature/project/data/folded_projects.dart';
|
||||
|
||||
/// Which projects' sub-projects are folded away, kept per device (the
|
||||
/// developer's decision of 10 Nov 2026), in Browse and the sidebar alike.
|
||||
void main() {
|
||||
late Directory folder;
|
||||
late File file;
|
||||
|
||||
setUp(() {
|
||||
folder = Directory.systemTemp.createTempSync('folded');
|
||||
file = File('${folder.path}/folded_projects.json');
|
||||
});
|
||||
tearDown(() => folder.deleteSync(recursive: true));
|
||||
|
||||
test('nothing is folded at first', () async {
|
||||
final folded = await FoldedProjects.open(file);
|
||||
|
||||
expect(folded.isFolded('school'), isFalse);
|
||||
});
|
||||
|
||||
test('a fold is kept for the next start, an unfold too', () async {
|
||||
final folded = await FoldedProjects.open(file);
|
||||
var told = 0;
|
||||
folded.addListener(() => told++);
|
||||
|
||||
await folded.toggle('school');
|
||||
await folded.toggle('home');
|
||||
await folded.toggle('home');
|
||||
|
||||
expect(told, 3);
|
||||
final again = await FoldedProjects.open(file);
|
||||
expect(again.isFolded('school'), isTrue);
|
||||
expect(again.isFolded('home'), isFalse);
|
||||
});
|
||||
|
||||
test('a damaged file folds nothing', () async {
|
||||
file.writeAsStringSync('{"school": ');
|
||||
|
||||
expect((await FoldedProjects.open(file)).isFolded('school'), isFalse);
|
||||
});
|
||||
|
||||
test('without a file it folds for this session alone', () async {
|
||||
final folded = FoldedProjects();
|
||||
await folded.toggle('school');
|
||||
|
||||
expect(folded.isFolded('school'), isTrue);
|
||||
});
|
||||
}
|
||||
Loading…
Reference in a new issue