diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..b83039c --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,17 @@ +{ + "configurations": [ + { + "name": "Flutter", + "type": "dart", + "request": "launch", + "program": "lib/main.dart" + }, + { + "name": "Flutter (Headless)", + "type": "dart", + "request": "launch", + "program": "lib/main.dart", + "env": { "FLUTTER_HEADLESS": "1" } + } + ] +} diff --git a/lib/controllers/key.dart b/lib/controllers/key.dart index 0d02d17..77b4883 100644 --- a/lib/controllers/key.dart +++ b/lib/controllers/key.dart @@ -1,28 +1,28 @@ import "package:flutter_riverpod/flutter_riverpod.dart"; import "package:nexus/controllers/shared_prefs.dart"; -class KeyController(final String key) extends Notifier { +class KeyController(final String key) extends AsyncNotifier { static const String spaceKey = "space"; static const String roomKey = "room"; static const String pushKeyKey = "pushKey"; @override - String? build() => - ref.watch(SharedPrefsController.provider).requireValue.getString(key); + Future build() => + ref.watch(SharedPrefsController.provider).getString(key); Future set(String? value) async { - final prefs = ref.watch(SharedPrefsController.provider).requireValue; - state = value; + final prefs = ref.watch(SharedPrefsController.provider); + state = .data(value); if (value == null) { - prefs.remove(key); + await prefs.remove(key); } else { - prefs.setString(key, value); + await prefs.setString(key, value); } } static final provider = - NotifierProvider.family( + AsyncNotifierProvider.family( KeyController.new, ); } diff --git a/lib/controllers/member_list_opened.dart b/lib/controllers/member_list_opened.dart index e3509f0..f0295d8 100644 --- a/lib/controllers/member_list_opened.dart +++ b/lib/controllers/member_list_opened.dart @@ -1,22 +1,20 @@ import "package:flutter_riverpod/flutter_riverpod.dart"; import "package:nexus/controllers/shared_prefs.dart"; -class MemberListOpenedController extends Notifier { +class MemberListOpenedController extends AsyncNotifier { static const String key = "memberListOpened"; @override - bool build() => - ref.watch(SharedPrefsController.provider).requireValue.getBool(key) ?? - true; + Future build() async => + await ref.watch(SharedPrefsController.provider).getBool(key) ?? true; Future set(bool value) async { - final prefs = ref.watch(SharedPrefsController.provider).requireValue; - state = value; - - prefs.setBool(key, value); + state = .data(value); + await ref.watch(SharedPrefsController.provider).setBool(key, value); } - static final provider = NotifierProvider( - MemberListOpenedController.new, - ); + static final provider = + AsyncNotifierProvider( + MemberListOpenedController.new, + ); } diff --git a/lib/controllers/push_key.dart b/lib/controllers/push_key.dart index 7217886..e3f6b82 100644 --- a/lib/controllers/push_key.dart +++ b/lib/controllers/push_key.dart @@ -4,18 +4,19 @@ import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:flutter_riverpod/flutter_riverpod.dart"; import "package:nexus/controllers/key.dart"; -class PushKeyController(final String instance) extends Notifier { +class PushKeyController(final String instance) extends AsyncNotifier { @override - String? build() => json.decode( - ref.watch(KeyController.provider(KeyController.pushKeyKey)) ?? "{}", + Future build() async => json.decode( + await ref.watch(KeyController.provider(KeyController.pushKeyKey).future) ?? + "{}", )[instance]; Future set(String? value) async { final provider = KeyController.provider(KeyController.pushKeyKey); final notifier = ref.watch(provider.notifier); - final prefs = IMap(json.decode(ref.watch(provider) ?? "{}")); + final prefs = IMap(json.decode(await ref.watch(provider.future) ?? "{}")); - state = value; + state = .data(value); notifier.set( json.encode( prefs.add(instance, value).where((_, value) => value != null).unlock, @@ -24,7 +25,7 @@ class PushKeyController(final String instance) extends Notifier { } static final provider = - NotifierProvider.family( + AsyncNotifierProvider.family( PushKeyController.new, ); } diff --git a/lib/controllers/shared_prefs.dart b/lib/controllers/shared_prefs.dart index 876fc47..9ecb34a 100644 --- a/lib/controllers/shared_prefs.dart +++ b/lib/controllers/shared_prefs.dart @@ -1,12 +1,12 @@ import "package:flutter_riverpod/flutter_riverpod.dart"; import "package:shared_preferences/shared_preferences.dart"; -class SharedPrefsController extends AsyncNotifier { +class SharedPrefsController extends Notifier { @override - Future build() async => .getInstance(); + SharedPreferencesAsync build() => SharedPreferencesAsync(); static final provider = - AsyncNotifierProvider( + NotifierProvider( SharedPrefsController.new, ); } diff --git a/lib/controllers/unified_push.dart b/lib/controllers/unified_push.dart index 9575804..bc5f6e1 100644 --- a/lib/controllers/unified_push.dart +++ b/lib/controllers/unified_push.dart @@ -13,7 +13,6 @@ import "package:nexus/controllers/client.dart"; import "package:nexus/controllers/client_state.dart"; import "package:nexus/models/content/message.dart"; import "package:nexus/models/content/sticker.dart"; -import "package:nexus/models/requests/register_pusher.dart"; import "package:unifiedpush/unifiedpush.dart"; import "package:unifiedpush_storage_shared_preferences/storage.dart"; import "package:window_manager/window_manager.dart"; @@ -40,8 +39,8 @@ class UnifiedPushController extends AsyncNotifier { .new( appDisplayName: "Nexus", appId: "nexus.federated.nexus", - data: PusherData.webPush( - url: Uri.parse(endpoint.url), + data: .webPush( + url: .parse(endpoint.url), auth: endpoint.pubKeySet!.auth, ), deviceDisplayName: @@ -67,7 +66,9 @@ class UnifiedPushController extends AsyncNotifier { event.unreadType?.shouldNotify() != true || (!isInBackground && await windowManager.isFocused().onError((_, _) => false) && - ref.watch(KeyController.provider(KeyController.roomKey)) == + await ref.watch( + KeyController.provider(KeyController.roomKey).future, + ) == event.roomId)) { if (isInBackground) exit(0); return; @@ -146,7 +147,9 @@ class UnifiedPushController extends AsyncNotifier { Future deregister() async { final clientState = ref.watch(ClientStateController.provider); - final key = ref.watch(PushKeyController.provider(clientState!.deviceId!)); + final key = await ref.watch( + PushKeyController.provider(clientState!.deviceId!).future, + ); if (key != null) { await ref diff --git a/lib/main.dart b/lib/main.dart index 58289f0..05b840f 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -7,10 +7,11 @@ import "package:flutter_riverpod/flutter_riverpod.dart"; import "package:media_kit/media_kit.dart"; import "package:nexus/controllers/client.dart"; import "package:nexus/controllers/client_state.dart"; +import "package:nexus/controllers/key.dart"; +import "package:nexus/controllers/member_list_opened.dart"; import "package:nexus/controllers/multi_provider.dart"; import "package:nexus/controllers/notification.dart"; import "package:nexus/controllers/settings.dart"; -import "package:nexus/controllers/shared_prefs.dart"; import "package:nexus/controllers/unified_push.dart"; import "package:nexus/helpers/extensions/better_when.dart"; import "package:nexus/helpers/extensions/scheme_to_theme.dart"; @@ -81,9 +82,9 @@ void main(List args) async { await windowManager.setMinimumSize(Size.square(500)); } - isInBackground = args.contains("--unifiedpush-bg"); + isInBackground = Platform.environment["FLUTTER_HEADLESS"] != null; - LicenseRegistry.addLicense(() => Stream.fromIterable(fontLicenses)); + LicenseRegistry.addLicense(() => .fromIterable(fontLicenses)); FlutterError.onError = (FlutterErrorDetails details) => showError(details.exception.toString(), details.stack); @@ -103,14 +104,13 @@ void main(List args) async { // ignore: dead_code if (false && kDebugMode) Logger(), ], - child: App(isInBackground), + child: App(), ), ); } } -class const App(final bool isInBackground, {super.key}) - extends StatelessWidget { +class const App({super.key}) extends StatelessWidget { @override Widget build(BuildContext context) => DynamicColorBuilder( builder: (lightDynamic, darkDynamic) => Consumer( @@ -151,10 +151,12 @@ class const App(final bool isInBackground, {super.key}) .watch( MultiProviderController.provider( IListConst([ - SharedPrefsController.provider, ClientController.provider, NotificationController.provider, UnifiedPushController.provider, + MemberListOpenedController.provider, + KeyController.provider(KeyController.roomKey), + KeyController.provider(KeyController.spaceKey), ]), ), ) diff --git a/lib/pages/chat.dart b/lib/pages/chat.dart index 9469c91..fb165d3 100644 --- a/lib/pages/chat.dart +++ b/lib/pages/chat.dart @@ -14,7 +14,9 @@ class const ChatPage({super.key}) extends ConsumerWidget { final isDesktop = constraints.maxWidth > 650; final showMembersByDefault = constraints.maxWidth > 1000; final initComplete = ref.watch(InitCompleteController.provider); - final roomId = ref.watch(KeyController.provider(KeyController.roomKey)); + final roomId = ref + .watch(KeyController.provider(KeyController.roomKey)) + .requireValue; return SafeArea( child: Scaffold( diff --git a/lib/widgets/room_chat.dart b/lib/widgets/room_chat.dart index 015bbc4..d8424c9 100644 --- a/lib/widgets/room_chat.dart +++ b/lib/widgets/room_chat.dart @@ -43,7 +43,9 @@ final class const RoomChat({ final composerSize = useState(64); final userId = ref.watch(ClientStateController.provider)?.userId; - final memberListOpened = ref.watch(MemberListOpenedController.provider); + final memberListOpened = ref + .watch(MemberListOpenedController.provider) + .requireValue; final theme = Theme.of(context); final nothing = Center( diff --git a/lib/widgets/sidebar.dart b/lib/widgets/sidebar.dart index c2a0170..b2d8295 100644 --- a/lib/widgets/sidebar.dart +++ b/lib/widgets/sidebar.dart @@ -23,13 +23,13 @@ class const Sidebar({required final bool isDesktop, super.key}) final selectedSpaceProvider = KeyController.provider( KeyController.spaceKey, ); - final selectedSpaceId = ref.watch(selectedSpaceProvider); + final selectedSpaceId = ref.watch(selectedSpaceProvider).requireValue; final selectedSpaceIdNotifier = ref.watch(selectedSpaceProvider.notifier); final selectedRoomController = KeyController.provider( KeyController.roomKey, ); - final selectedRoomId = ref.watch(selectedRoomController); + final selectedRoomId = ref.watch(selectedRoomController).requireValue; final selectedRoomIdNotifier = ref.watch(selectedRoomController.notifier); final spaces = ref.watch(SpacesController.provider);