@@ -35,7 +35,8 @@ class GlobalSettings extends Table {
35
35
.nullable ()();
36
36
37
37
// 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).
39
40
// That way is more convenient, when it works, because
40
41
// it avoids a migration and therefore several added copies of our schema
41
42
// in the Drift generated files.
@@ -50,6 +51,9 @@ class GlobalSettings extends Table {
50
51
/// referring to a possible setting from [BoolGlobalSetting] .
51
52
/// For settings in [BoolGlobalSetting] without a row in this table,
52
53
/// the setting's value is that of [BoolGlobalSetting.default_] .
54
+ ///
55
+ /// See also:
56
+ /// - [IntGlobalSettings] , the int-valued counterpart of this table.
53
57
@DataClassName ('BoolGlobalSettingRow' )
54
58
class BoolGlobalSettings extends Table {
55
59
/// The setting's name, a possible name from [BoolGlobalSetting] .
@@ -73,6 +77,37 @@ class BoolGlobalSettings extends Table {
73
77
Set <Column <Object >>? get primaryKey => {name};
74
78
}
75
79
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
+
76
111
/// The table of [Account] records in the app's database.
77
112
class Accounts extends Table {
78
113
/// The ID of this account in the app's local database.
@@ -116,7 +151,7 @@ class UriConverter extends TypeConverter<Uri, String> {
116
151
@override Uri fromSql (String fromDb) => Uri .parse (fromDb);
117
152
}
118
153
119
- @DriftDatabase (tables: [GlobalSettings , BoolGlobalSettings , Accounts ])
154
+ @DriftDatabase (tables: [GlobalSettings , BoolGlobalSettings , IntGlobalSettings , Accounts ])
120
155
class AppDatabase extends _$AppDatabase {
121
156
AppDatabase (super .e);
122
157
@@ -129,7 +164,7 @@ class AppDatabase extends _$AppDatabase {
129
164
// information on using the build_runner.
130
165
// * Write a migration in `_migrationSteps` below.
131
166
// * Write tests.
132
- static const int latestSchemaVersion = 9 ; // See note.
167
+ static const int latestSchemaVersion = 11 ; // See note.
133
168
134
169
@override
135
170
int get schemaVersion => latestSchemaVersion;
@@ -200,7 +235,30 @@ class AppDatabase extends _$AppDatabase {
200
235
// assume there wasn't also the legacy app before that.
201
236
await m.database.update (schema.globalSettings).write (
202
237
RawValuesInsertable ({'legacy_upgrade_state' : Constant ('noLegacy' )}));
203
- }
238
+ },
239
+ from9To10: (m, schema) async {
240
+ await m.createTable (schema.intGlobalSettings);
241
+ },
242
+ from10To11: (Migrator m, Schema11 schema) async {
243
+ // To provide a smooth experience for users when they first install a new
244
+ // version of the app with support for the "last visited account" feature,
245
+ // we set the first available account as the last visited one. This way,
246
+ // the user is still taken straight to the first account, just as they
247
+ // were used to before, instead of being shown the "choose account" page.
248
+ final firstAccountId = await (m.database.selectOnly (schema.accounts)
249
+ ..addColumns ([schema.accounts.id])
250
+ ..limit (1 )
251
+ ).map ((row) => row.read (schema.accounts.id)).getSingleOrNull ();
252
+ if (firstAccountId == null ) return ;
253
+
254
+ // Like `globalStore.setLastVisitedAccount(firstAccountId)`,
255
+ // as of the schema at the time of this migration.
256
+ await m.database.into (schema.intGlobalSettings).insert (
257
+ RawValuesInsertable ({
258
+ 'name' : Variable ('lastVisitedAccountId' ),
259
+ 'value' : Variable (firstAccountId),
260
+ }));
261
+ },
204
262
);
205
263
206
264
Future <void > _createLatestSchema (Migrator m) async {
@@ -256,6 +314,14 @@ class AppDatabase extends _$AppDatabase {
256
314
return result;
257
315
}
258
316
317
+ Future <Map <IntGlobalSetting , int >> getIntGlobalSettings () async {
318
+ return {
319
+ for (final row in await select (intGlobalSettings).get ())
320
+ if (IntGlobalSetting .byName (row.name) case final setting? )
321
+ setting: row.value
322
+ };
323
+ }
324
+
259
325
Future <int > createAccount (AccountsCompanion values) async {
260
326
try {
261
327
return await into (accounts).insert (values);
0 commit comments