@@ -8,13 +8,105 @@ library;
8
8
import 'dart:convert' ;
9
9
import 'dart:io' ;
10
10
11
+ import 'package:drift/drift.dart' as drift;
11
12
import 'package:flutter/foundation.dart' ;
12
13
import 'package:json_annotation/json_annotation.dart' ;
13
14
import 'package:path_provider/path_provider.dart' ;
14
15
import 'package:sqlite3/sqlite3.dart' ;
15
16
17
+ import '../log.dart' ;
18
+ import 'database.dart' ;
19
+ import 'settings.dart' ;
20
+
16
21
part 'legacy_app_data.g.dart' ;
17
22
23
+ Future <void > migrateLegacyAppData (AppDatabase db) async {
24
+ assert (debugLog ("Migrating legacy app data..." ));
25
+ final legacyData = await readLegacyAppData ();
26
+ if (legacyData == null ) {
27
+ assert (debugLog ("... no legacy app data found." ));
28
+ return ;
29
+ }
30
+
31
+ assert (debugLog ("Found settings: ${legacyData .settings ?.toJson ()}" ));
32
+ final settings = legacyData.settings;
33
+ if (settings != null ) {
34
+ await db.update (db.globalSettings).write (GlobalSettingsCompanion (
35
+ // TODO(#1139) apply settings.language
36
+ themeSetting: switch (settings.theme) {
37
+ // The legacy app has just two values for this setting: light and dark,
38
+ // where light is the default. Map that default to the new default,
39
+ // which is to follow the system-wide setting.
40
+ // We planned the same change for the legacy app (but were
41
+ // foiled by React Native):
42
+ // https://github.com/zulip/zulip-mobile/issues/5533
43
+ // More-recent discussion:
44
+ // https://github.com/zulip/zulip-flutter/pull/1588#discussion_r2147418577
45
+ LegacyAppThemeSetting .default_ => drift.Value .absent (),
46
+ LegacyAppThemeSetting .night => drift.Value (ThemeSetting .dark),
47
+ },
48
+ browserPreference: switch (settings.browser) {
49
+ LegacyAppBrowserPreference .embedded => drift.Value (BrowserPreference .inApp),
50
+ LegacyAppBrowserPreference .external => drift.Value (BrowserPreference .external ),
51
+ LegacyAppBrowserPreference .default_ => drift.Value .absent (),
52
+ },
53
+ markReadOnScroll: switch (settings.markMessagesReadOnScroll) {
54
+ // The legacy app's default was "always".
55
+ // In this app, that would mix poorly with the VisitFirstUnreadSetting
56
+ // default of "conversations"; so translate the old default
57
+ // to the new default of "conversations".
58
+ LegacyAppMarkMessagesReadOnScroll .always =>
59
+ drift.Value (MarkReadOnScrollSetting .conversations),
60
+ LegacyAppMarkMessagesReadOnScroll .never =>
61
+ drift.Value (MarkReadOnScrollSetting .never),
62
+ LegacyAppMarkMessagesReadOnScroll .conversationViewsOnly =>
63
+ drift.Value (MarkReadOnScrollSetting .conversations),
64
+ },
65
+ ));
66
+ }
67
+
68
+ assert (debugLog ("Found ${legacyData .accounts ?.length } accounts:" ));
69
+ for (final account in legacyData.accounts ?? < LegacyAppAccount > []) {
70
+ assert (debugLog (" account: ${account .toJson ()..['apiKey' ] = 'redacted' }" ));
71
+ if (account.apiKey.isEmpty) {
72
+ // This represents the user having logged out of this account.
73
+ // (See `Auth.apiKey` in src/api/transportTypes.js .)
74
+ // In this app, when a user logs out of an account,
75
+ // the account is removed from the accounts list. So remove this account.
76
+ assert (debugLog (" (account ignored because had been logged out)" ));
77
+ continue ;
78
+ }
79
+ if (account.userId == null
80
+ || account.zulipVersion == null
81
+ || account.zulipFeatureLevel == null ) {
82
+ // The legacy app either never loaded server data for this account,
83
+ // or last did so on an ancient version of the app.
84
+ // (See docs and comments on these properties in src/types.js .
85
+ // Specifically, the latest added of these was userId, in commit 4fdefb09b
86
+ // (#M4968), released in v27.170 in 2021-09.)
87
+ // Drop the account.
88
+ assert (debugLog (" (account ignored because missing metadata)" ));
89
+ continue ;
90
+ }
91
+ await db.createAccount (AccountsCompanion .insert (
92
+ realmUrl: account.realm,
93
+ userId: account.userId! ,
94
+ email: account.email,
95
+ apiKey: account.apiKey,
96
+ zulipVersion: account.zulipVersion! ,
97
+ // no zulipMergeBase; legacy app didn't record it
98
+ zulipFeatureLevel: account.zulipFeatureLevel! ,
99
+ // This app doesn't yet maintain ackedPushToken (#322), so avoid recording
100
+ // a value that would then be allowed to get stale. See discussion:
101
+ // https://github.com/zulip/zulip-flutter/pull/1588#discussion_r2148817025
102
+ // TODO(#322): apply ackedPushToken
103
+ // ackedPushToken: drift.Value(account.ackedPushToken),
104
+ ));
105
+ }
106
+
107
+ assert (debugLog ("Done migrating legacy app data." ));
108
+ }
109
+
18
110
Future <LegacyAppData ?> readLegacyAppData () async {
19
111
final LegacyAppDatabase db;
20
112
try {
0 commit comments