Skip to content

Commit

Permalink
wip; settings: Add global settings
Browse files Browse the repository at this point in the history
Signed-off-by: Zixuan James Li <[email protected]>
  • Loading branch information
PIG208 committed Dec 17, 2024
1 parent d13e4c8 commit 86b035f
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 4 deletions.
49 changes: 49 additions & 0 deletions lib/model/store.dart
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ abstract class GlobalStore extends ChangeNotifier {
/// A cache of the [Accounts] table in the underlying data store.
final Map<int, Account> _accounts;

/// A cache of the [GlobalSettingsData] singleton in the underlying data store.
GlobalSettingsData? _globalSettings;

// TODO settings (those that are per-device rather than per-account)
// TODO push token, and other data corresponding to GlobalSessionState

Expand Down Expand Up @@ -223,6 +226,40 @@ abstract class GlobalStore extends ChangeNotifier {
/// Remove an account from the underlying data store.
Future<void> doRemoveAccount(int accountId);

GlobalSettingsData? get globalSettingsSync => _globalSettings;

/// Get global settings from the store.
///
/// Use the cache if already loaded.
/// Otherwise, load it from the underlying store.
///
/// Consider checking [globalSettingsSync] before using this.
Future<GlobalSettingsData> getGlobalSettings() async {
if (globalSettingsSync != null) return globalSettingsSync!;
return await loadGlobalSettings();
}

/// Load global settings from the underlying data store, unconditionally.
///
/// This should only be called from [getGlobalSettings].
Future<GlobalSettingsData> loadGlobalSettings();

/// Update the global settings in the store, return the new version.
///
/// The global settings must already exist in the store.
Future<GlobalSettingsData> updateGlobalSettings(GlobalSettingsCompanion data) async {
assert(_globalSettings != null);
await doUpdateGlobalSettings(data);
_globalSettings = _globalSettings!.copyWithCompanion(data);
notifyListeners();
return _globalSettings!;
}

/// Update the global settings in the underlying data store.
///
/// This should only be called from [updateGlobalSettings].
Future<void> doUpdateGlobalSettings(GlobalSettingsCompanion data);

@override
String toString() => '${objectRuntimeType(this, 'GlobalStore')}#${shortHash(this)}';
}
Expand Down Expand Up @@ -835,6 +872,18 @@ class LiveGlobalStore extends GlobalStore {
assert(rowsAffected == 1);
}

@override
Future<GlobalSettingsData> loadGlobalSettings() async {
_globalSettings = await _db.ensureGlobalSettings();
return _globalSettings!;
}

@override
Future<void> doUpdateGlobalSettings(GlobalSettingsCompanion data) async {
final rowsAffected = await _db.update(_db.globalSettings).write(data);
assert(rowsAffected == 1);
}

@override
String toString() => '${objectRuntimeType(this, 'LiveGlobalStore')}#${shortHash(this)}';
}
Expand Down
10 changes: 7 additions & 3 deletions lib/widgets/content.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import '../generated/l10n/zulip_localizations.dart';
import '../model/avatar_url.dart';
import '../model/binding.dart';
import '../model/content.dart';
import '../model/database.dart';
import '../model/internal_link.dart';
import 'code_block.dart';
import 'dialog.dart';
Expand Down Expand Up @@ -1342,17 +1343,20 @@ void _launchUrl(BuildContext context, String urlString) async {
return;
}

final globalSettings = GlobalStoreWidget.of(context).globalSettingsSync;
bool launched = false;
String? errorMessage;
try {
launched = await ZulipBinding.instance.launchUrl(url,
mode: switch (defaultTargetPlatform) {
mode: switch ((globalSettings!.browserPreference, defaultTargetPlatform)) {
(BrowserPreference.embedded, _) => UrlLaunchMode.inAppBrowserView,
(BrowserPreference.external, _) => UrlLaunchMode.externalApplication,
// On iOS we prefer LaunchMode.externalApplication because (for
// HTTP URLs) LaunchMode.platformDefault uses SFSafariViewController,
// which gives an awkward UX as described here:
// https://chat.zulip.org/#narrow/stream/48-mobile/topic/in-app.20browser/near/1169118
TargetPlatform.iOS => UrlLaunchMode.externalApplication,
_ => UrlLaunchMode.platformDefault,
(BrowserPreference.none, TargetPlatform.iOS) => UrlLaunchMode.externalApplication,
(BrowserPreference.none, _) => UrlLaunchMode.platformDefault,
});
} on PlatformException catch (e) {
errorMessage = e.message;
Expand Down
13 changes: 12 additions & 1 deletion lib/widgets/theme.dart
Original file line number Diff line number Diff line change
@@ -1,16 +1,27 @@
import 'package:flutter/material.dart';

import '../api/model/model.dart';
import '../model/database.dart';
import 'content.dart';
import 'emoji_reaction.dart';
import 'message_list.dart';
import 'channel_colors.dart';
import 'store.dart';
import 'text.dart';

ThemeData zulipThemeData(BuildContext context) {
final DesignVariables designVariables;
final List<ThemeExtension> themeExtensions;
Brightness brightness = MediaQuery.platformBrightnessOf(context);
final globalSettings = GlobalStoreWidget.of(context).globalSettingsSync;
Brightness brightness;
switch (globalSettings!.themeSetting) {
case ThemeSetting.none:
brightness = MediaQuery.platformBrightnessOf(context);
case ThemeSetting.light:
brightness = Brightness.light;
case ThemeSetting.dark:
brightness = Brightness.dark;
}

// This applies Material 3's color system to produce a palette of
// appropriately matching and contrasting colors for use in a UI.
Expand Down
20 changes: 20 additions & 0 deletions test/model/test_store.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:zulip/api/model/events.dart';
import 'package:zulip/api/model/initial_snapshot.dart';
import 'package:zulip/api/model/model.dart';
import 'package:zulip/model/database.dart';
import 'package:zulip/model/store.dart';
import 'package:zulip/widgets/store.dart';

Expand Down Expand Up @@ -157,6 +158,25 @@ class TestGlobalStore extends GlobalStore {
store: store, initialSnapshot: initialSnapshot);
return Future.value(store);
}

GlobalSettingsData? _globalSettings;

@override
Future<GlobalSettingsData> loadGlobalSettings() async {
if (_globalSettings != null) {
return _globalSettings!;
}
_globalSettings = const GlobalSettingsData(
themeSetting: ThemeSetting.none,
browserPreference: BrowserPreference.none,
);
return Future.value(_globalSettings);
}

@override
Future<void> doUpdateGlobalSettings(GlobalSettingsCompanion data) async {
_globalSettings = _globalSettings!.copyWithCompanion(data);
}
}

extension PerAccountStoreTestExtension on PerAccountStore {
Expand Down

0 comments on commit 86b035f

Please sign in to comment.