Skip to content

Commit 24f4e44

Browse files
committed
settings: Make general int global settings, so as to add without migrations
1 parent f13e07b commit 24f4e44

File tree

16 files changed

+2172
-11
lines changed

16 files changed

+2172
-11
lines changed

lib/model/database.dart

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ class GlobalSettings extends Table {
3535
.nullable()();
3636

3737
// If adding a new column to this table, consider whether [BoolGlobalSettings]
38-
// can do the job instead (by adding a value to the [BoolGlobalSetting] enum).
38+
// or [IntGlobalSettings] can do the job instead (by adding a value to the
39+
// [BoolGlobalSetting] or [IntGlobalSetting] enum).
3940
// That way is more convenient, when it works, because
4041
// it avoids a migration and therefore several added copies of our schema
4142
// in the Drift generated files.
@@ -50,6 +51,9 @@ class GlobalSettings extends Table {
5051
/// referring to a possible setting from [BoolGlobalSetting].
5152
/// For settings in [BoolGlobalSetting] without a row in this table,
5253
/// the setting's value is that of [BoolGlobalSetting.default_].
54+
///
55+
/// See also:
56+
/// - [IntGlobalSettings], the int-valued counterpart of this table.
5357
@DataClassName('BoolGlobalSettingRow')
5458
class BoolGlobalSettings extends Table {
5559
/// The setting's name, a possible name from [BoolGlobalSetting].
@@ -73,6 +77,37 @@ class BoolGlobalSettings extends Table {
7377
Set<Column<Object>>? get primaryKey => {name};
7478
}
7579

80+
/// The table of the user's int-valued, account-independent settings.
81+
///
82+
/// These apply across all the user's accounts on this client
83+
/// (i.e. on this install of the app on this device).
84+
///
85+
/// Each row is a [IntGlobalSettingRow],
86+
/// referring to a possible setting from [IntGlobalSetting].
87+
/// For settings in [IntGlobalSetting] without a row in this table,
88+
/// the setting's value is `null`.
89+
///
90+
/// See also:
91+
/// - [BoolGlobalSettings], the bool-valued counterpart of this table.
92+
@DataClassName('IntGlobalSettingRow')
93+
class IntGlobalSettings extends Table {
94+
/// The setting's name, a possible name from [IntGlobalSetting].
95+
///
96+
/// The table may have rows where [name] is not the name of any
97+
/// enum value in [IntGlobalSetting].
98+
/// This happens if the app has previously run at a future or modified
99+
/// version which had additional values in that enum,
100+
/// and the user set one of those additional settings.
101+
/// The app ignores any such unknown rows.
102+
TextColumn get name => text()();
103+
104+
/// The user's chosen value for the setting.
105+
IntColumn get value => integer()();
106+
107+
@override
108+
Set<Column<Object>>? get primaryKey => {name};
109+
}
110+
76111
/// The table of [Account] records in the app's database.
77112
class Accounts extends Table {
78113
/// The ID of this account in the app's local database.
@@ -116,7 +151,7 @@ class UriConverter extends TypeConverter<Uri, String> {
116151
@override Uri fromSql(String fromDb) => Uri.parse(fromDb);
117152
}
118153

119-
@DriftDatabase(tables: [GlobalSettings, BoolGlobalSettings, Accounts])
154+
@DriftDatabase(tables: [GlobalSettings, BoolGlobalSettings, IntGlobalSettings, Accounts])
120155
class AppDatabase extends _$AppDatabase {
121156
AppDatabase(super.e);
122157

@@ -129,7 +164,7 @@ class AppDatabase extends _$AppDatabase {
129164
// information on using the build_runner.
130165
// * Write a migration in `_migrationSteps` below.
131166
// * Write tests.
132-
static const int latestSchemaVersion = 9; // See note.
167+
static const int latestSchemaVersion = 10; // See note.
133168

134169
@override
135170
int get schemaVersion => latestSchemaVersion;
@@ -200,7 +235,29 @@ class AppDatabase extends _$AppDatabase {
200235
// assume there wasn't also the legacy app before that.
201236
await m.database.update(schema.globalSettings).write(
202237
RawValuesInsertable({'legacy_upgrade_state': Constant('noLegacy')}));
203-
}
238+
},
239+
from9To10: (m, schema) async {
240+
await m.createTable(schema.intGlobalSettings);
241+
242+
// To provide a smooth experience for users when they first install a new
243+
// version of the app with support for the "last visited account" feature,
244+
// we set the first available account as the last visited one. This way,
245+
// the user is still taken straight to the first account, just as they
246+
// were used to before, instead of being shown the "choose account" page.
247+
final firstAccountId = await (m.database.selectOnly(schema.accounts)
248+
..addColumns([schema.accounts.id])
249+
..limit(1)
250+
).map((row) => row.read(schema.accounts.id)).getSingleOrNull();
251+
if (firstAccountId == null) return;
252+
253+
// Like `globalStore.setLastVisitedAccount(firstAccountId)`,
254+
// as of the schema at the time of this migration.
255+
await m.database.into(schema.intGlobalSettings).insert(
256+
RawValuesInsertable({
257+
'name': Variable('lastVisitedAccountId'),
258+
'value': Variable(firstAccountId),
259+
}));
260+
},
204261
);
205262

206263
Future<void> _createLatestSchema(Migrator m) async {
@@ -256,6 +313,14 @@ class AppDatabase extends _$AppDatabase {
256313
return result;
257314
}
258315

316+
Future<Map<IntGlobalSetting, int>> getIntGlobalSettings() async {
317+
return {
318+
for (final row in await select(intGlobalSettings).get())
319+
if (IntGlobalSetting.byName(row.name) case final setting?)
320+
setting: row.value
321+
};
322+
}
323+
259324
Future<int> createAccount(AccountsCompanion values) async {
260325
try {
261326
return await into(accounts).insert(values);

0 commit comments

Comments
 (0)