refactor(app): studysets and settings are written in the newest schema
Decided 2026-10-07: the codecs write the newest schema every time, as before, rather than the oldest one that holds what is there. An older app loses sight of a studyset or of the settings once a newer one has written them, until it is updated too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
a822763df8
commit
ad28a5d8c2
4 changed files with 19 additions and 26 deletions
|
|
@ -19,22 +19,17 @@ import 'package:halkyon_learn_flutter/src/feature/tag/model/tag.dart';
|
|||
// layout (the widgets' order and those hidden, by name). Schema 4 added the
|
||||
// Pomodoro timer's profiles and the one chosen, left out while as they come.
|
||||
// Older schemas read with what they lack as it comes.
|
||||
//
|
||||
// Settings whose Pomodoro profiles are as they come are still written in
|
||||
// schema 3: an app that knows only schema 3 skips a schema 4 payload whole,
|
||||
// and would lose every setting.
|
||||
|
||||
/// The newest schema this app writes.
|
||||
/// The schema this app writes.
|
||||
const settingsSchemaVersion = 4;
|
||||
|
||||
/// Encodes [settings] into their payload, in the oldest schema that holds
|
||||
/// them.
|
||||
/// Encodes [settings] into their payload.
|
||||
ByteData encodeSettingsPayload(PersonSettings settings) {
|
||||
const defaults = StudyOptions();
|
||||
final study = settings.study;
|
||||
final pomodoro = settings.pomodoro;
|
||||
return encodePayload(
|
||||
pomodoro == const PomodoroSettings() ? 3 : settingsSchemaVersion,
|
||||
settingsSchemaVersion,
|
||||
{
|
||||
'studyTags': {
|
||||
for (final MapEntry(key: studysetId, value: tags)
|
||||
|
|
|
|||
|
|
@ -13,18 +13,13 @@ import 'package:halkyon_learn_flutter/src/feature/studyset/model/studyset_conten
|
|||
// without them. Schema 3 added the study options (`study`: new cards and
|
||||
// reviews a day, 0 for no limit, and the order), left out when the studyset
|
||||
// has none.
|
||||
//
|
||||
// A studyset without study options is still written in schema 2: an app that
|
||||
// knows only schema 2 skips a schema 3 payload whole, and would lose sight of
|
||||
// every studyset edited on a newer app otherwise.
|
||||
|
||||
/// The newest schema this app writes.
|
||||
/// The schema this app writes.
|
||||
const studysetSchemaVersion = 3;
|
||||
|
||||
/// Encodes a studyset's content into its payload, in the oldest schema that
|
||||
/// holds it.
|
||||
/// Encodes a studyset's content into its payload.
|
||||
ByteData encodeStudysetPayload(StudysetContent content) => encodePayload(
|
||||
content.studyOptions == null ? 2 : studysetSchemaVersion,
|
||||
studysetSchemaVersion,
|
||||
{
|
||||
'title': content.title,
|
||||
'description': content.description.toJson(),
|
||||
|
|
|
|||
|
|
@ -181,11 +181,14 @@ void main() {
|
|||
expect(decodeSettingsPayload(payload), settings);
|
||||
});
|
||||
|
||||
test('as they come, are written in the third schema, which older apps '
|
||||
'read', () {
|
||||
final payload = encodeSettingsPayload(const PersonSettings());
|
||||
test('as they come, are left out, in the fourth schema all the same', () {
|
||||
final payload = decodePayload(
|
||||
encodeSettingsPayload(const PersonSettings()),
|
||||
newestSchema: 4,
|
||||
);
|
||||
|
||||
expect(decodePayload(payload, newestSchema: 4)['schemaVersion'], 3);
|
||||
expect(payload['schemaVersion'], 4);
|
||||
expect(payload.keys, isNot(contains('pomodoro')));
|
||||
});
|
||||
|
||||
test('that are malformed read as they come, keeping the other '
|
||||
|
|
|
|||
|
|
@ -70,13 +70,13 @@ void main() {
|
|||
expect(json(payload)['schemaVersion'], studysetSchemaVersion);
|
||||
});
|
||||
|
||||
test('without study options still writes the second schema, which '
|
||||
'older apps read', () {
|
||||
test('without study options writes the third schema all the same', () {
|
||||
final payload = encodeStudysetPayload(
|
||||
StudysetContent(title: 'Japanese', description: RichContent.empty()),
|
||||
);
|
||||
|
||||
expect(json(payload)['schemaVersion'], 2);
|
||||
expect(json(payload)['schemaVersion'], 3);
|
||||
expect(json(payload).keys, isNot(contains('study')));
|
||||
});
|
||||
|
||||
test('keeps the study options', () {
|
||||
|
|
|
|||
Loading…
Reference in a new issue