feat(tag): a tag can be hidden on cards being studied

A tag's eye in Manage tags hides it on cards being studied, or shows it again: for the many tags naming where a word was met (an episode, a song), which would crowd a common word's card. A hidden tag still filters, narrows a study session and shows where tags are edited. Tag schema 2 adds 'hidden', written only for a hidden tag, so older apps go on reading every other.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-10-13 19:27:11 +02:00
commit 68945b2224
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64
2 changed files with 179 additions and 18 deletions

View file

@ -20,6 +20,29 @@ void main() {
});
});
test('a hidden tag is schema 2 and says so; any other stays schema 1, '
'which older apps read', () {
final hidden = encodeTagPayload((
name: 'あかね噺 S1 E1',
colorName: 'fern',
), hidden: true);
final shown = encodeTagPayload((name: 'あかね噺', colorName: 'fern'));
expect(decodePayload(hidden, newestSchema: tagSchemaVersion), {
'schemaVersion': 2,
'name': 'あかね噺 S1 E1',
'color': 'fern',
'hidden': true,
});
expect(tagPayloadHidden(hidden), isTrue);
expect(decodeTagPayload(hidden).name, 'あかね噺 S1 E1');
expect(
decodePayload(shown, newestSchema: tagSchemaVersion)['schemaVersion'],
1,
);
expect(tagPayloadHidden(shown), isFalse);
});
test('reads a name as another device wrote it, tidied', () {
final payload = encodePayload(1, {
'name': ' Verb form',
@ -32,7 +55,7 @@ void main() {
test('refuses a blank name, a newer schema and a blanked tag', () {
for (final payload in [
encodePayload(1, {'name': ' ', 'color': 'fern'}),
encodePayload(2, {'name': 'verb', 'color': 'fern'}),
encodePayload(3, {'name': 'verb', 'color': 'fern'}),
redactedPayload,
]) {
expect(() => decodeTagPayload(payload), throwsFormatException);

View file

@ -67,6 +67,24 @@ void main() {
});
});
test('a tag hidden on cards stays hidden when renamed, and shows again '
'when asked; one is made hidden from the start if asked', () async {
final id = await repository.create('Verb', colorName: 'fern');
await repository.setHidden(id, hidden: true);
expect((await repository.read()).byId(id)?.hidden, isTrue);
await repository.update(id, name: 'Verbs', colorName: 'plum');
expect(
(await repository.read()).byId(id),
Tag(id: id, name: 'Verbs', colorName: 'plum', hidden: true),
);
await repository.setHidden(id, hidden: false);
expect((await repository.read()).byId(id)?.hidden, isFalse);
final episode = await repository.create('あかね噺 S1 E1', hidden: true);
expect((await repository.read()).byId(episode)?.hidden, isTrue);
});
test('lists the tags by name, whatever their case', () async {
await repository.create('verb');
await repository.create('adjective');