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