Compare commits

...
Author SHA1 Message Date
7792a1aae4
bug fixes 2026-09-10 15:34:31 -04:00
06720238b8
more reliable UP deregistration with proper cross-platform support 2026-09-10 15:34:31 -04:00
69959b9e11
add wip deregistering 2026-09-10 15:34:31 -04:00
32527e1241
smarter notif logic 2026-09-10 15:34:31 -04:00
c4542ba406
include avatars on notifs 2026-09-10 15:34:31 -04:00
454353ca5e
send notifications natively 2026-09-10 15:34:31 -04:00
35df8f61a2
override webcrypto deps 2026-09-10 15:34:24 -04:00
d771b886d9
pass pushes to gomuks 2026-09-10 15:34:02 -04:00
30ca08d911
working registration 2026-09-10 15:34:02 -04:00
2c107dd92f
slight cleanup
`onNewEndpoint` is still not getting called for some reason (help appreciated)
2026-09-10 15:33:45 -04:00
c73167a3af
add UnifiedPushAllowedController 2026-09-10 15:33:45 -04:00
0e05245c50
support for registering pushers 2026-09-10 15:33:45 -04:00
6e42902322
run GomuksInit on an Isolate
Fixes #70
2026-09-10 15:32:30 -04:00
c105a6035c
use dot shorthands where possible in generate script 2026-09-10 15:21:53 -04:00
3d7ef9b32f
actually generate bindings
Yes `ffigen`, I did actually want you to generate the bindings, not a file consisting only of comments. Crazy, right?
2026-09-10 15:20:56 -04:00
51ef66174a
fix generate script to work with new ffigen 2026-09-10 15:15:12 -04:00
1efb68ebe0
bump deps, remove unwanted and now un-needed analyzer rule
Fixes #69
2026-09-10 15:09:47 -04:00
32 changed files with 921 additions and 261 deletions

View file

@ -11,6 +11,8 @@
"muks", "muks",
"prefs", "prefs",
"unban", "unban",
"unredact" "unifiedpush",
"unredact",
"webpush"
] ]
} }

View file

@ -190,6 +190,12 @@ dart scripts/generate.dart
> export CPATH="$(clang -v 2>&1 | grep "Selected GCC installation" | rev | cut -d' ' -f1 | rev)/include" > export CPATH="$(clang -v 2>&1 | grep "Selected GCC installation" | rev | cut -d' ' -f1 | rev)/include"
> ``` > ```
Build webcrypto:
```sh
flutter pub run webcrypto:setup
```
Build generated files, and watch for new changes: Build generated files, and watch for new changes:
```sh ```sh

View file

@ -2,7 +2,6 @@ analyzer:
errors: errors:
invalid_annotation_target: ignore invalid_annotation_target: ignore
avoid_print: ignore avoid_print: ignore
annotate_overrides: ignore
exclude: exclude:
- "build/**" - "build/**"
- "**/*.g.dart" - "**/*.g.dart"

View file

@ -20,16 +20,21 @@ android {
ndkVersion = flutter.ndkVersion ndkVersion = flutter.ndkVersion
compileOptions { compileOptions {
isCoreLibraryDesugaringEnabled = true
sourceCompatibility = JavaVersion.VERSION_21 sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21 targetCompatibility = JavaVersion.VERSION_21
} }
defaultConfig { defaultConfig {
applicationId = "nexus.federated.nexus" applicationId = "nexus.federated.nexus"
minSdk = 29 minSdk = 29
targetSdk = flutter.targetSdkVersion targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode versionCode = flutter.versionCode
versionName = flutter.versionName versionName = flutter.versionName
multiDexEnabled = true
} }
signingConfigs { signingConfigs {
@ -63,6 +68,11 @@ android {
} }
} }
dependencies {
implementation("org.unifiedpush.android:embedded-fcm-distributor:3.1.0")
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.4")
}
kotlin { kotlin {
compilerOptions { compilerOptions {
jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_21 jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_21

View file

@ -7,6 +7,7 @@ import UIKit
_ application: UIApplication, _ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool { ) -> Bool {
UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
return super.application(application, didFinishLaunchingWithOptions: launchOptions) return super.application(application, didFinishLaunchingWithOptions: launchOptions)
} }

View file

@ -1,3 +1,4 @@
import "dart:async";
import "dart:ffi"; import "dart:ffi";
import "dart:io"; import "dart:io";
import "dart:isolate"; import "dart:isolate";
@ -15,11 +16,13 @@ import "package:nexus/controllers/sync_status.dart";
import "package:nexus/controllers/top_level_spaces.dart"; import "package:nexus/controllers/top_level_spaces.dart";
import "package:nexus/helpers/extensions/gomuks_buffer.dart"; import "package:nexus/helpers/extensions/gomuks_buffer.dart";
import "package:nexus/main.dart"; import "package:nexus/main.dart";
import "package:nexus/models/capabilities.dart";
import "package:nexus/models/content/message.dart"; import "package:nexus/models/content/message.dart";
import "package:nexus/models/event.dart"; import "package:nexus/models/event.dart";
import "package:nexus/models/oauth_auth_code_response.dart"; import "package:nexus/models/oauth_auth_code_response.dart";
import "package:nexus/models/open_graph_data.dart"; import "package:nexus/models/open_graph_data.dart";
import "package:nexus/models/paginate.dart"; import "package:nexus/models/paginate.dart";
import "package:nexus/models/requests/deregister_pusher.dart";
import "package:nexus/models/requests/download_media.dart"; import "package:nexus/models/requests/download_media.dart";
import "package:nexus/models/requests/get_event.dart"; import "package:nexus/models/requests/get_event.dart";
import "package:nexus/models/requests/get_related_events.dart"; import "package:nexus/models/requests/get_related_events.dart";
@ -31,6 +34,7 @@ import "package:nexus/models/requests/oauth/get_auth_url.dart";
import "package:nexus/models/requests/oauth/register_client.dart"; import "package:nexus/models/requests/oauth/register_client.dart";
import "package:nexus/models/requests/paginate.dart"; import "package:nexus/models/requests/paginate.dart";
import "package:nexus/models/requests/redact_event.dart"; import "package:nexus/models/requests/redact_event.dart";
import "package:nexus/models/requests/register_pusher.dart";
import "package:nexus/models/requests/report.dart"; import "package:nexus/models/requests/report.dart";
import "package:nexus/models/requests/send_event.dart"; import "package:nexus/models/requests/send_event.dart";
import "package:nexus/models/requests/send_message.dart"; import "package:nexus/models/requests/send_message.dart";
@ -49,6 +53,7 @@ import "package:path_provider/path_provider.dart";
class ClientController extends AsyncNotifier<int> { class ClientController extends AsyncNotifier<int> {
@override @override
Future<int> build() async { Future<int> build() async {
final handle = await Isolate.run(() async {
final Pointer<Char> root; final Pointer<Char> root;
if (Platform.isAndroid || Platform.isIOS) { if (Platform.isAndroid || Platform.isIOS) {
final dir = await getApplicationSupportDirectory(); final dir = await getApplicationSupportDirectory();
@ -57,7 +62,8 @@ class ClientController extends AsyncNotifier<int> {
root = nullptr.cast(); root = nullptr.cast();
} }
final handle = GomuksInit(root); return GomuksInit(root);
});
final callable = final callable =
NativeCallable< NativeCallable<
@ -154,18 +160,15 @@ class ClientController extends AsyncNotifier<int> {
throw Exception("GomuksStart returned error code $errorCode"); throw Exception("GomuksStart returned error code $errorCode");
} }
Future<dynamic> _sendCommand( Future<dynamic> callGomuksMethod(
String command, [ Map<String, dynamic> data,
Map<String, dynamic> data = const {}, FutureOr<GomuksResponse> Function(int handle, GomuksBorrowedBuffer data)
]) async { callback,
) async {
final bufferPointer = data.toGomuksBufferPtr(); final bufferPointer = data.toGomuksBufferPtr();
final handle = await future; final handle = await future;
final response = await Isolate.run( final response = await Isolate.run(
() => GomuksSubmitCommand( () => callback(handle, bufferPointer.ref),
handle,
command.toNativeUtf8().cast<Char>(),
bufferPointer.ref,
),
); );
calloc.free(bufferPointer); calloc.free(bufferPointer);
@ -178,6 +181,24 @@ class ClientController extends AsyncNotifier<int> {
return json; return json;
} }
Future<Event?> handlePush(Map<String, dynamic> data) async {
final response = await callGomuksMethod(
data,
(handle, data) async => GomuksHandlePush(handle, data),
);
return response == null ? null : .fromJson(response);
}
Future<dynamic> _sendCommand(
String command, [
Map<String, dynamic> data = const {},
]) => callGomuksMethod(
data,
(handle, data) async =>
GomuksSubmitCommand(handle, command.toNativeUtf8().cast<Char>(), data),
);
Future<void> redactEvent(RedactEventRequest report) => Future<void> redactEvent(RedactEventRequest report) =>
_sendCommand("redact_event", report.toJson()); _sendCommand("redact_event", report.toJson());
@ -279,6 +300,15 @@ class ClientController extends AsyncNotifier<int> {
Future<void> setAccountData(SetAccountDataRequest request) => Future<void> setAccountData(SetAccountDataRequest request) =>
_sendCommand("set_account_data", request.toJson()); _sendCommand("set_account_data", request.toJson());
Future<void> registerPusher(RegisterPusherRequest request) =>
_sendCommand("register_homeserver_push", request.toJson());
Future<void> deregisterPusher(DeregisterPusherRequest request) =>
_sendCommand("register_homeserver_push", {
...request.toJson(),
"kind": null,
});
Future<MessageContent> uploadMedia(UploadMediaRequest request) async => Future<MessageContent> uploadMedia(UploadMediaRequest request) async =>
.fromJson(await _sendCommand("upload_media", request.toJson())); .fromJson(await _sendCommand("upload_media", request.toJson()));
@ -316,6 +346,10 @@ class ClientController extends AsyncNotifier<int> {
Future<SpecVersionsResponse> getSpecVersions() async => Future<SpecVersionsResponse> getSpecVersions() async =>
.fromJson(await _sendCommand("get_versions")); .fromJson(await _sendCommand("get_versions"));
Future<Capabilities> getCapabilities() async => Capabilities.fromJson(
(await _sendCommand("get_capabilities"))["capabilities"],
);
Future<Uri?> discoverHomeserver(Uri homeserver) async { Future<Uri?> discoverHomeserver(Uri homeserver) async {
try { try {
final response = await _sendCommand("discover_homeserver", { final response = await _sendCommand("discover_homeserver", {

View file

@ -4,6 +4,7 @@ import "package:nexus/controllers/shared_prefs.dart";
class KeyController(final String key) extends Notifier<String?> { class KeyController(final String key) extends Notifier<String?> {
static const String spaceKey = "space"; static const String spaceKey = "space";
static const String roomKey = "room"; static const String roomKey = "room";
static const String pushKeyKey = "pushKey";
@override @override
String? build() => String? build() =>

View file

@ -0,0 +1,120 @@
import "dart:io";
import "package:material_ui/material_ui.dart";
import "package:nexus/main.dart";
import "package:flutter_local_notifications/flutter_local_notifications.dart";
// ignore: implementation_imports
import "package:flutter_local_notifications_linux/src/model/hint.dart";
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:nexus/pages/notifications.dart";
class NotificationsController
extends AsyncNotifier<FlutterLocalNotificationsPlugin> {
@override
Future<FlutterLocalNotificationsPlugin> build() async {
final notifications = FlutterLocalNotificationsPlugin();
final darwin = DarwinInitializationSettings();
await notifications.initialize(
settings: .new(
windows: .new(
appName: "Nexus",
appUserModelId: "nexus.federated.nexus",
guid: "dde78daf-130f-4e46-a80a-e31deeab45d7",
),
android: .new("ic_launcher_foreground"),
iOS: darwin,
macOS: darwin,
linux: .new(defaultActionName: "Open"),
),
onDidReceiveNotificationResponse: (details) {
if (details.payload case final eventId?) {
if (navigatorKey.currentContext case final context?) {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => NotificationsPage(eventId: eventId),
),
);
}
}
},
);
return notifications;
}
Future<bool> requestPermissions() async {
final controller = await future;
if (Platform.isIOS) {
return await controller
.resolvePlatformSpecificImplementation<
IOSFlutterLocalNotificationsPlugin
>()
?.requestPermissions(alert: true, badge: true, sound: true) ??
true;
} else if (Platform.isMacOS) {
return await controller
.resolvePlatformSpecificImplementation<
MacOSFlutterLocalNotificationsPlugin
>()
?.requestPermissions(alert: true, badge: true, sound: true) ??
true;
} else if (Platform.isAndroid) {
return await controller
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin
>()
?.requestNotificationsPermission() ??
true;
}
return true;
}
Future<void> send({
required int id,
required String title,
String? body,
File? icon,
String? payload,
}) async {
final notificationDetails = NotificationDetails(
android: .new(
"messages",
"Messages",
largeIcon: icon == null ? null : FilePathAndroidBitmap(icon.path),
),
linux: .new(
customHints: icon == null
? null
: [
.new(
name: "image-path",
value: LinuxHintStringValue(icon.path),
),
],
),
// TODO: See if icons can be added to iOS, macOS, and Windows notifications (#68)
iOS: .new(),
macOS: .new(),
windows: .new(),
);
final controller = await future;
await controller.show(
id: id,
title: title,
body: body,
notificationDetails: notificationDetails,
payload: payload,
);
}
static final provider =
AsyncNotifierProvider<
NotificationsController,
FlutterLocalNotificationsPlugin
>(NotificationsController.new);
}

View file

@ -0,0 +1,30 @@
import "dart:convert";
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<String?> {
@override
String? build() => json.decode(
ref.watch(KeyController.provider(KeyController.pushKeyKey)) ?? "{}",
)[instance];
Future<void> set(String? value) async {
final provider = KeyController.provider(KeyController.pushKeyKey);
final notifier = ref.watch(provider.notifier);
final prefs = IMap(json.decode(ref.watch(provider) ?? "{}"));
state = value;
notifier.set(
json.encode(
prefs.add(instance, value).where((_, value) => value != null).unlock,
),
);
}
static final provider =
NotifierProvider.family<PushKeyController, String?, String>(
PushKeyController.new,
);
}

View file

@ -1,15 +1,19 @@
import "dart:io"; import "dart:io";
import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:flutter_hooks/flutter_hooks.dart";
import "package:hooks_riverpod/hooks_riverpod.dart";
import "package:material_ui/material_ui.dart"; import "package:material_ui/material_ui.dart";
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:intl/intl.dart"; import "package:intl/intl.dart";
import "package:m3e_buttons/m3e_buttons.dart"; import "package:m3e_buttons/m3e_buttons.dart";
import "package:nexus/controllers/account_data.dart"; import "package:nexus/controllers/account_data.dart";
import "package:nexus/controllers/client.dart"; import "package:nexus/controllers/client.dart";
import "package:nexus/controllers/client_state.dart"; import "package:nexus/controllers/client_state.dart";
import "package:nexus/controllers/notifications.dart";
import "package:nexus/controllers/settings.dart"; import "package:nexus/controllers/settings.dart";
import "package:nexus/controllers/unified_push.dart";
import "package:nexus/controllers/spec_versions.dart"; import "package:nexus/controllers/spec_versions.dart";
import "package:nexus/controllers/unified_push_allowed.dart";
import "package:nexus/models/account_data.dart"; import "package:nexus/models/account_data.dart";
import "package:nexus/models/settings_category.dart"; import "package:nexus/models/settings_category.dart";
import "package:nexus/main.dart"; import "package:nexus/main.dart";
@ -95,6 +99,90 @@ class SettingsSectionsController
if (ref.watch(ClientStateController.provider)?.isLoggedIn == true) if (ref.watch(ClientStateController.provider)?.isLoggedIn == true)
"Account": .new([ "Account": .new([
.new(title: "Profile", icon: Icons.person, settings: .new([])), .new(title: "Profile", icon: Icons.person, settings: .new([])),
.new(
title: "Notifications",
icon: Icons.notifications,
settings: .new([
.new(
title: "Push notifications",
description: "Enable push notifications using Web Push",
builder: (title, description, icon) => HookConsumer(
builder: (context, ref, _) {
final loading = useState(false);
final pusherRegistered = ref.watch(
UnifiedPushController.provider,
);
final unifiedPushAllowed = ref.watch(
UnifiedPushAllowedController.provider,
);
return SwitchListTile(
title: Text(title),
subtitle: Text(
unifiedPushAllowed.maybeWhen(
data: (data) => data,
orElse: () => null,
) ??
description,
),
secondary: Icon(icon),
value: pusherRegistered.maybeWhen(
data: (value) => value,
orElse: () => false,
),
onChanged: loading.value
? null
: unifiedPushAllowed.maybeWhen(
data: (data) => data == null,
orElse: () => false,
)
? pusherRegistered.maybeWhen(
data: (_) => (value) async {
try {
loading.value = true;
if (value) {
if (await ref
.watch(
NotificationsController
.provider
.notifier,
)
.requestPermissions()) {
await ref
.watch(
UnifiedPushController
.provider
.notifier,
)
.register();
} else {
// TODO: Handle not granted
}
} else {
await ref
.watch(
UnifiedPushController
.provider
.notifier,
)
.deregister();
}
} catch (error, stackTrace) {
showError(error, stackTrace);
} finally {
loading.value = false;
}
},
orElse: () => null,
)
: null,
);
},
),
icon: Icons.notification_add,
),
]),
),
.new( .new(
title: "Safety", title: "Safety",
icon: Icons.gpp_good, icon: Icons.gpp_good,
@ -166,6 +254,8 @@ class SettingsSectionsController
onPressed: () async { onPressed: () async {
Navigator.of(context) Navigator.of(context)
.popUntil((route) => route.isFirst); .popUntil((route) => route.isFirst);
Navigator.of(context)
.popUntil((route) => route.isFirst);
await WidgetsBinding.instance.endOfFrame; await WidgetsBinding.instance.endOfFrame;

View file

@ -0,0 +1,164 @@
import "dart:convert";
import "dart:io";
import "package:flutter/foundation.dart";
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:intl/intl.dart";
import "package:nexus/controllers/key.dart";
import "package:nexus/controllers/notifications.dart";
import "package:nexus/controllers/push_key.dart";
import "package:nexus/controllers/rooms.dart";
import "package:nexus/main.dart";
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";
class UnifiedPushController extends AsyncNotifier<bool> {
@override
Future<bool> build() async {
final client = ref.watch(ClientController.provider.notifier);
final registered = await UnifiedPush.initialize(
linuxOptions: .new(
dbusName: "nexus.federated.nexus.UnifiedPush",
storage: UnifiedPushStorageSharedPreferences(),
background: isInBackground,
),
onNewEndpoint: (endpoint, instance) async {
final pushKey = endpoint.pubKeySet!.pubKey;
await ref
.watch(PushKeyController.provider(instance).notifier)
.set(pushKey);
await client.registerPusher(
.new(
appDisplayName: "Nexus",
appId: "nexus.federated.nexus",
data: PusherData.webPush(
url: Uri.parse(endpoint.url),
auth: endpoint.pubKeySet!.auth,
),
deviceDisplayName:
"Nexus on ${toBeginningOfSentenceCase(Platform.operatingSystem)}",
kind: .webPush,
lang: "en",
pushKey: pushKey,
),
);
},
onMessage: (message, instance) async {
if (message.decrypted == false) {
throw Exception(
"Failed to decrypt notification. Try toggling off and on UnifiedPush in settings.",
);
}
final event = await client.handlePush(
json.decode(String.fromCharCodes(message.content)),
);
if (event == null ||
event.unreadType?.shouldNotify != true ||
(!isInBackground &&
await windowManager.isFocused().onError((_, _) => false) &&
ref.watch(KeyController.provider(KeyController.roomKey)) ==
event.roomId)) {
return;
}
final room = ref.read(
RoomsController.provider.select((rooms) => rooms[event.roomId]),
);
final avatar = room?.metadata?.avatar;
final icon = avatar == null
? null
: await ref
.read(ClientController.provider.notifier)
.downloadMedia(.new(mxc: avatar, isAvatar: true));
await ref
.read(NotificationsController.provider.notifier)
.send(
id: event.eventId.hashCode & 0x7fffffff,
title: room?.metadata?.name ?? "New Event",
icon: icon,
payload: event.eventId,
body: switch (event.content) {
MessageContent(:final body?) ||
StickerContent(:final body) => body,
_ => null,
},
);
if (isInBackground) exit(0);
},
onRegistrationFailed: (error, instance) => throw error,
onUnregistered: (instance) async {
await ref
.watch(PushKeyController.provider(instance).notifier)
.set(null);
ref.invalidateSelf();
},
);
if (registered) {
// Needs to be registered every startup
await register(true);
}
return registered;
}
Future<void> register([bool alreadyRegistered = false]) async {
final clientState = ref.watch(ClientStateController.provider);
if (clientState?.deviceId == null) ref.invalidateSelf();
final capabilities = await ref
.watch(ClientController.provider.notifier)
.getCapabilities();
if (capabilities.webpush?.vapid == null) {
throw UnsupportedError(
"Your homeserver does not support MSC4174 (Web Push), and therefore cannot send notifications to Nexus.",
);
}
if (!alreadyRegistered &&
!await UnifiedPush.tryUseCurrentOrDefaultDistributor()) {
throw Exception("No UnifiedPush distributors found");
}
await UnifiedPush.register(
instance: clientState!.deviceId!,
vapid: capabilities.webpush?.vapid,
);
if (!alreadyRegistered) ref.invalidateSelf();
}
Future<void> deregister() async {
final clientState = ref.watch(ClientStateController.provider);
final key = ref.watch(PushKeyController.provider(clientState!.deviceId!));
if (key != null) {
await ref
.watch(ClientController.provider.notifier)
.deregisterPusher(.new(appId: "nexus.federated.nexus", pushKey: key));
} else {
debugPrint(
"No matching pushKey found. Skipping deregistration from homeserver.",
);
}
await UnifiedPush.unregister(clientState.deviceId!);
ref.invalidateSelf();
}
static final provider = AsyncNotifierProvider<UnifiedPushController, bool>(
UnifiedPushController.new,
);
}

View file

@ -0,0 +1,33 @@
import "dart:io";
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:nexus/controllers/client.dart";
import "package:unifiedpush/unifiedpush.dart";
class UnifiedPushAllowedController extends AsyncNotifier<String?> {
@override
Future<String?> build() async {
if (!await UnifiedPush.tryUseCurrentOrDefaultDistributor()) {
return "No valid distributors found. Try installing ${Platform.isLinux
? "KUnifiedPush"
: Platform.isAndroid
? "Google Play Services or NTFY"
: "NTFY"}.";
}
final capabilities = await ref
.watch(ClientController.provider.notifier)
.getCapabilities();
if (capabilities.webpush?.vapid == null) {
return "Your homeserver does not support MSC4174 (Web Push), and therefore cannot send notifications to Nexus.";
}
return null;
}
static final provider =
AsyncNotifierProvider.autoDispose<UnifiedPushAllowedController, String?>(
UnifiedPushAllowedController.new,
);
}

View file

@ -8,8 +8,10 @@ import "package:media_kit/media_kit.dart";
import "package:nexus/controllers/client.dart"; import "package:nexus/controllers/client.dart";
import "package:nexus/controllers/client_state.dart"; import "package:nexus/controllers/client_state.dart";
import "package:nexus/controllers/multi_provider.dart"; import "package:nexus/controllers/multi_provider.dart";
import "package:nexus/controllers/notifications.dart";
import "package:nexus/controllers/settings.dart"; import "package:nexus/controllers/settings.dart";
import "package:nexus/controllers/shared_prefs.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/better_when.dart";
import "package:nexus/helpers/extensions/scheme_to_theme.dart"; import "package:nexus/helpers/extensions/scheme_to_theme.dart";
import "package:nexus/helpers/font_licenses.dart"; import "package:nexus/helpers/font_licenses.dart";
@ -22,6 +24,7 @@ import "package:window_manager/window_manager.dart";
import "package:material_ui/material_ui.dart"; import "package:material_ui/material_ui.dart";
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>(); final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
late final bool isInBackground;
final class Logger extends ProviderObserver { final class Logger extends ProviderObserver {
@override @override
@ -45,6 +48,7 @@ void showError(Object error, [StackTrace? stackTrace]) {
error.toString().contains("Invalid source") || error.toString().contains("Invalid source") ||
error.toString().contains("UTF-16") || error.toString().contains("UTF-16") ||
error.toString().contains("HTTP request failed") || error.toString().contains("HTTP request failed") ||
error.toString().contains("'_nextFrame != null': is not true.") ||
error.toString().contains("Invalid image data")) { error.toString().contains("Invalid image data")) {
return; return;
} }
@ -62,7 +66,7 @@ void showError(Object error, [StackTrace? stackTrace]) {
} }
} }
void main() async { void main(List<String> args) async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
MediaKit.ensureInitialized(); MediaKit.ensureInitialized();
@ -77,11 +81,14 @@ void main() async {
await windowManager.setMinimumSize(Size.square(500)); await windowManager.setMinimumSize(Size.square(500));
} }
isInBackground = args.contains("--unifiedpush-bg");
LicenseRegistry.addLicense(() => Stream.fromIterable(fontLicenses)); LicenseRegistry.addLicense(() => Stream.fromIterable(fontLicenses));
FlutterError.onError = (FlutterErrorDetails details) => FlutterError.onError = (FlutterErrorDetails details) =>
showError(details.exception.toString(), details.stack); showError(details.exception.toString(), details.stack);
if (!isInBackground) {
runApp( runApp(
ProviderScope( ProviderScope(
retry: (_, _) => null, retry: (_, _) => null,
@ -90,12 +97,14 @@ void main() async {
// ignore: dead_code // ignore: dead_code
if (false && kDebugMode) Logger(), if (false && kDebugMode) Logger(),
], ],
child: const App(), child: App(isInBackground),
), ),
); );
} }
}
class const App({super.key}) extends StatelessWidget { class const App(final bool isInBackground, {super.key})
extends StatelessWidget {
@override @override
Widget build(BuildContext context) => DynamicColorBuilder( Widget build(BuildContext context) => DynamicColorBuilder(
builder: (lightDynamic, darkDynamic) => Consumer( builder: (lightDynamic, darkDynamic) => Consumer(
@ -138,6 +147,8 @@ class const App({super.key}) extends StatelessWidget {
IListConst([ IListConst([
SharedPrefsController.provider, SharedPrefsController.provider,
ClientController.provider, ClientController.provider,
NotificationsController.provider,
UnifiedPushController.provider,
]), ]),
), ),
) )

View file

@ -0,0 +1,25 @@
import "package:freezed_annotation/freezed_annotation.dart";
part "capabilities.freezed.dart";
part "capabilities.g.dart";
@Freezed(toJson: false, fromJson: false)
@JsonSerializable()
class const Capabilities({
@JsonKey(name: "org.matrix.msc4174.webpush") final WebPush? webpush,
}) with _$Capabilities {
Map<String, Object?> toJson() => _$CapabilitiesToJson(this);
factory Capabilities.fromJson(Map<String, Object?> json) =>
_$CapabilitiesFromJson(json);
}
@Freezed(toJson: false, fromJson: false)
@JsonSerializable()
class const WebPush({required final bool enabled, final String? vapid})
with _$WebPush {
Map<String, Object?> toJson() => _$WebPushToJson(this);
factory WebPush.fromJson(Map<String, Object?> json) =>
_$WebPushFromJson(json);
}

View file

@ -10,6 +10,7 @@ class const ClientState({
required final bool isLoggedIn, required final bool isLoggedIn,
required final bool isVerified, required final bool isVerified,
required final String? userId, required final String? userId,
required final String? deviceId,
required final String? homeserverUrl, required final String? homeserverUrl,
}) with _$ClientState { }) with _$ClientState {
Map<String, Object?> toJson() => _$ClientStateToJson(this); Map<String, Object?> toJson() => _$ClientStateToJson(this);

View file

@ -1,4 +1,4 @@
import "package:freezed_annotation/freezed_annotation.dart"; import "package:freezed_annotation/freezed_annotation.dart";
@JsonEnum(fieldRename: FieldRename.snake) @JsonEnum(fieldRename: .snake)
enum JoinRule { public, knock, invite, private, restricted, knockRestricted } enum JoinRule { public, knock, invite, private, restricted, knockRestricted }

View file

@ -1,4 +1 @@
import "package:freezed_annotation/freezed_annotation.dart";
@JsonEnum()
enum MembershipAction { ban, kick, unban, invite } enum MembershipAction { ban, kick, unban, invite }

View file

@ -1,4 +1 @@
import "package:freezed_annotation/freezed_annotation.dart";
@JsonEnum()
enum MembershipStatus { leave, invite, ban, join, knock } enum MembershipStatus { leave, invite, ban, join, knock }

View file

@ -0,0 +1,13 @@
import "package:freezed_annotation/freezed_annotation.dart";
part "deregister_pusher.freezed.dart";
part "deregister_pusher.g.dart";
@Freezed(toJson: false, fromJson: false)
@JsonSerializable()
class const DeregisterPusherRequest({
required final String appId,
@JsonKey(name: "pushkey") required final String pushKey,
}) with _$DeregisterPusherRequest {
Map<String, Object?> toJson() => _$DeregisterPusherRequestToJson(this);
}

View file

@ -0,0 +1,56 @@
import "package:freezed_annotation/freezed_annotation.dart";
part "register_pusher.freezed.dart";
part "register_pusher.g.dart";
@Freezed(toJson: false, fromJson: false)
@JsonSerializable()
class const RegisterPusherRequest({
required final String appDisplayName,
required final String appId,
final bool append = false,
required final PusherData data,
required final String deviceDisplayName,
required final PusherKind kind,
required final String lang,
/// TODO: What does this do?
final String? profileTag,
@JsonKey(name: "pushkey") required final String pushKey,
}) with _$RegisterPusherRequest {
Map<String, Object?> toJson() => _$RegisterPusherRequestToJson(this);
}
@freezed
sealed class PusherData with _$PusherData {
const factory PusherData.http({
required Uri url,
@Default(PushFormat.eventIdOnly) PushFormat format,
}) = HttpPusherData;
const factory PusherData.webPush({
required Uri url,
@Default(PushFormat.eventIdOnly) PushFormat format,
/// `data.auth`: RFC8291 authentication secret.
required String auth,
}) = WebPushPusherData;
factory PusherData.fromJson(Map<String, Object?> json) =>
_$PusherDataFromJson(json);
}
@JsonEnum(fieldRename: .snake)
enum PushFormat {
@JsonValue(null)
all,
eventIdOnly,
}
enum PusherKind {
http,
email,
@JsonValue("org.matrix.msc4174.webpush")
webPush,
}

View file

@ -0,0 +1,14 @@
import "package:material_ui/material_ui.dart";
import "package:hooks_riverpod/hooks_riverpod.dart";
import "package:nexus/widgets/appbar.dart";
class const NotificationsPage({final String? eventId, super.key})
extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
return Scaffold(
appBar: Appbar(title: Text("Notifications")),
body: Placeholder(),
);
}
}

View file

@ -39,7 +39,7 @@ final class const Appbar({
: (_) => windowManager.startDragging(), : (_) => windowManager.startDragging(),
), ),
child: AppBar( child: AppBar(
leading: InkWell(onTap: onTap, child: leading), leading: leading == null ? null : InkWell(onTap: onTap, child: leading),
backgroundColor: backgroundColor, backgroundColor: backgroundColor,
scrolledUnderElevation: scrolledUnderElevation, scrolledUnderElevation: scrolledUnderElevation,
actionsPadding: const .symmetric(horizontal: 8), actionsPadding: const .symmetric(horizontal: 8),

View file

@ -13,6 +13,7 @@
#include <media_kit_video/media_kit_video_plugin.h> #include <media_kit_video/media_kit_video_plugin.h>
#include <screen_retriever_linux/screen_retriever_linux_plugin.h> #include <screen_retriever_linux/screen_retriever_linux_plugin.h>
#include <url_launcher_linux/url_launcher_plugin.h> #include <url_launcher_linux/url_launcher_plugin.h>
#include <webcrypto/webcrypto_plugin.h>
#include <window_manager/window_manager_plugin.h> #include <window_manager/window_manager_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) { void fl_register_plugins(FlPluginRegistry* registry) {
@ -37,6 +38,9 @@ void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
g_autoptr(FlPluginRegistrar) webcrypto_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "WebcryptoPlugin");
webcrypto_plugin_register_with_registrar(webcrypto_registrar);
g_autoptr(FlPluginRegistrar) window_manager_registrar = g_autoptr(FlPluginRegistrar) window_manager_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "WindowManagerPlugin"); fl_plugin_registry_get_registrar_for_plugin(registry, "WindowManagerPlugin");
window_manager_plugin_register_with_registrar(window_manager_registrar); window_manager_plugin_register_with_registrar(window_manager_registrar);

View file

@ -10,6 +10,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
media_kit_video media_kit_video
screen_retriever_linux screen_retriever_linux
url_launcher_linux url_launcher_linux
webcrypto
window_manager window_manager
) )

View file

@ -45,7 +45,6 @@ pkgs.mkShell {
GRADLE_OPTS = "-Dorg.gradle.project.android.aapt2FromMavenOverride=${ANDROID_HOME}/build-tools/36.0.0/aapt2"; GRADLE_OPTS = "-Dorg.gradle.project.android.aapt2FromMavenOverride=${ANDROID_HOME}/build-tools/36.0.0/aapt2";
} }
// lib.optionalAttrs pkgs.stdenv.isLinux { // lib.optionalAttrs pkgs.stdenv.isLinux {
CPATH = lib.makeSearchPath "include" [ pkgs.glibc.dev ];
LD_LIBRARY_PATH = "./build/native_assets/linux:${lib.makeLibraryPath [ pkgs.zlib ]}"; LD_LIBRARY_PATH = "./build/native_assets/linux:${lib.makeLibraryPath [ pkgs.zlib ]}";
}; };
} }

View file

@ -1,5 +1,6 @@
#include "my_application.h" #include "my_application.h"
#include <cstdlib>
#include <flutter_linux/flutter_linux.h> #include <flutter_linux/flutter_linux.h>
#ifdef GDK_WINDOWING_X11 #ifdef GDK_WINDOWING_X11
#include <gdk/gdkx.h> #include <gdk/gdkx.h>
@ -72,6 +73,7 @@ static void my_application_activate(GApplication* application) {
gdk_rgba_parse(&background_color, "#000000"); gdk_rgba_parse(&background_color, "#000000");
fl_view_set_background_color(view, &background_color); fl_view_set_background_color(view, &background_color);
gtk_widget_show(GTK_WIDGET(view)); gtk_widget_show(GTK_WIDGET(view));
if (std::getenv("FLUTTER_HEADLESS")) gtk_widget_hide(GTK_WIDGET(window));
gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
// Show the window when Flutter renders. // Show the window when Flutter renders.

View file

@ -8,6 +8,7 @@ import Foundation
import app_links import app_links
import dynamic_color import dynamic_color
import file_selector_macos import file_selector_macos
import flutter_local_notifications
import media_kit_libs_macos_video import media_kit_libs_macos_video
import media_kit_video import media_kit_video
import package_info_plus import package_info_plus
@ -15,12 +16,14 @@ import screen_retriever_macos
import shared_preferences_foundation import shared_preferences_foundation
import url_launcher_macos import url_launcher_macos
import wakelock_plus import wakelock_plus
import webcrypto
import window_manager import window_manager
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
AppLinksMacosPlugin.register(with: registry.registrar(forPlugin: "AppLinksMacosPlugin")) AppLinksMacosPlugin.register(with: registry.registrar(forPlugin: "AppLinksMacosPlugin"))
DynamicColorPlugin.register(with: registry.registrar(forPlugin: "DynamicColorPlugin")) DynamicColorPlugin.register(with: registry.registrar(forPlugin: "DynamicColorPlugin"))
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
MediaKitLibsMacosVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitLibsMacosVideoPlugin")) MediaKitLibsMacosVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitLibsMacosVideoPlugin"))
MediaKitVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitVideoPlugin")) MediaKitVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitVideoPlugin"))
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
@ -28,5 +31,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin")) WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin"))
WebcryptoPlugin.register(with: registry.registrar(forPlugin: "WebcryptoPlugin"))
WindowManagerPlugin.register(with: registry.registrar(forPlugin: "WindowManagerPlugin")) WindowManagerPlugin.register(with: registry.registrar(forPlugin: "WindowManagerPlugin"))
} }

View file

@ -5,42 +5,42 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: _fe_analyzer_shared name: _fe_analyzer_shared
sha256: "1b0e6a07425a3e460666e88bf1c949ccc7bb0116ad562ce94a1eca60fe820725" sha256: fe18c7e37d5acb3b43224fa255281dec007970d6fd01f6d76fcd88ed3777a117
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "103.0.0" version: "107.0.0"
analysis_server_plugin: analysis_server_plugin:
dependency: transitive dependency: transitive
description: description:
name: analysis_server_plugin name: analysis_server_plugin
sha256: c58b2a05b260a023eefd0848496ff6b113a318c6c95dad4215165a4bd54ae600 sha256: fc372bb4778b901afe4dea2e7f71ec74e6cbe772999d9961a4d8e382bc4fa49c
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.3.18" version: "0.3.22"
analyzer: analyzer:
dependency: transitive dependency: transitive
description: description:
name: analyzer name: analyzer
sha256: "61c04d0c1bfed555c681ea079519933f071a5a026578ff73c4ff0df2d3462e5e" sha256: f2dde9e50c23fc95b846b4ef334e98c3ae8c0effd5d2453b02fc9fb3f8939791
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "13.3.0" version: "14.3.0"
analyzer_buffer: analyzer_buffer:
dependency: transitive dependency: transitive
description: description:
name: analyzer_buffer name: analyzer_buffer
sha256: "445b77e2054fa3e8c8a8ef1b5e9e6b23bb8028fffd34b5e60eaef315b7750674" sha256: f890a2e708e38fbf4238ad2f9fd3d506538acdddb0cd8eb2c3e8c7bd17784b57
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.3.3" version: "0.3.4"
analyzer_plugin: analyzer_plugin:
dependency: transitive dependency: transitive
description: description:
name: analyzer_plugin name: analyzer_plugin
sha256: c2a75baf1657171cc7872db96a12b07e385873cf7a73f2b4f7638e9d0701ee53 sha256: "521fbb02dada7d99d0fc6d10e4b501a07ae1d39ff2a850afbd0ec2279fb81f5c"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.14.12" version: "0.14.16"
app_links: app_links:
dependency: "direct main" dependency: "direct main"
description: description:
@ -77,10 +77,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: archive name: archive
sha256: be169cf6ac481e052c4538715d88841d567150dfe1df38aaec76461a4e7b39f2 sha256: ace891da0862b0e4cabbb064ee3fd87b2728b898949fdb366d83fe98342c9f19
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.1.0" version: "4.2.0"
args: args:
dependency: transitive dependency: transitive
description: description:
@ -117,34 +117,34 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: build name: build
sha256: b94f5da9ed3d081fd4ecc426c260998b5f4f4eb2f6d89b7e5472edef0b2b2a1b sha256: "8a5c5761af8e31748bba3c82f68925ace40f3225c3eea25be9beb57eca7cd7a8"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.0.10" version: "4.0.11"
build_config: build_config:
dependency: transitive dependency: transitive
description: description:
name: build_config name: build_config
sha256: "94eaf6708fe64408c632ef2689ca3777b112f9421306ccf4f8c84d7c5c9f83f8" sha256: d466ed2dc9c6cd1d169948879b84ee061eb5e22c64a7c6089879c6296d272a8d
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.2" version: "1.3.3"
build_daemon: build_daemon:
dependency: transitive dependency: transitive
description: description:
name: build_daemon name: build_daemon
sha256: "79e05eaf15a48d7230b053a4363b8eaac0cc234bbd0134c3229455481f55cbc6" sha256: e1d40ef3f7934986d5da2271b1ba07794921ce263e44d622fb6c406d76589e33
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.1.5" version: "4.1.6"
build_runner: build_runner:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: build_runner name: build_runner
sha256: "90363d438bd9f84a4d5bbb83352251f57d2d9d771bc95a44e6a33fe25fa52774" sha256: "894c243f6bc32015fec466ce30a6925bd537a77a426ee5bf481120477eb3de67"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.16.0" version: "2.16.1"
built_collection: built_collection:
dependency: transitive dependency: transitive
description: description:
@ -157,10 +157,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: built_value name: built_value
sha256: "31b24be6615ec7fcf70b3aa5a7469fe35826485e639a16dd7eb83ba30e4cc6a8" sha256: f87ea98192116f7093cb214551ce1929caae0681fdba282b3d8b4462adee7bb7
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "8.12.7" version: "8.13.0"
button_m3e: button_m3e:
dependency: transitive dependency: transitive
description: description:
@ -185,14 +185,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.4" version: "2.0.4"
cli_config:
dependency: transitive
description:
name: cli_config
sha256: ac20a183a07002b700f0c25e61b7ee46b23c309d76ab7b7640a028f18e4d99ec
url: "https://pub.dev"
source: hosted
version: "0.2.0"
cli_util: cli_util:
dependency: transitive dependency: transitive
description: description:
@ -205,18 +197,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: clock name: clock
sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b sha256: e51d50bca3217c9a9fa2b41a30e4a38971133f5f9ec7a3d57bae095007f1d28e
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.1.2" version: "1.1.3"
code_assets: code_assets:
dependency: "direct main" dependency: "direct main"
description: description:
name: code_assets name: code_assets
sha256: bf394f466ba9205f1812a0433b392d6af280f155f56651eda7c18cc32ed493b8 sha256: cfd4f5f575a49c5f10ca856e9846073f1e6c3ee94912377eea5f6cefc5272941
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.2.1" version: "2.0.0"
collection: collection:
dependency: "direct main" dependency: "direct main"
description: description:
@ -241,22 +233,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.2" version: "3.1.2"
coverage:
dependency: transitive
description:
name: coverage
sha256: "956a3de0725ca232ad353565a8290d3357592bf4250f6f298a185e2d949c5d3d"
url: "https://pub.dev"
source: hosted
version: "1.15.1"
cross_file: cross_file:
dependency: transitive dependency: transitive
description: description:
name: cross_file name: cross_file
sha256: "92c9c43c383bfa1c32079d3bc492d55d6d4318044b7b47edaff8971cbb555c51" sha256: f141ea4f277af142a0356955707f6556f37b03947d39d55585981a06ca437bd6
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.3.5+4" version: "0.3.5+5"
crypto: crypto:
dependency: transitive dependency: transitive
description: description:
@ -277,18 +261,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: cupertino_ui name: cupertino_ui
sha256: "7ed8ce4159d342eec4c65f4ea6eec57adaf9365404378541f38efc1da20a5b3d" sha256: e9dfe7fac704028f8928cbe4028a0be5e8a709498e8daf8247de99e99a32aef3
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.0" version: "1.0.2"
dart_style: dart_style:
dependency: transitive dependency: transitive
description: description:
name: dart_style name: dart_style
sha256: "3f88fc9c96c568d631356507355a2d1e983ee000c9ac008bdcb39b5bf53ce777" sha256: "82ade9fc4273f29ed673e33166944465225b4f7fc5d4aaef48605cc751c18fc1"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.12" version: "3.1.13"
dbus: dbus:
dependency: transitive dependency: transitive
description: description:
@ -382,10 +366,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: ffigen name: ffigen
sha256: "56fc0be88937409839a59c133dfdee4165e80da324c9e39f59013060249ffb44" sha256: "31b2ca630cede89babbbf31688d20b735967c51bf60572b06ec16718e5a7f1ec"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "21.0.0" version: "22.0.0"
file: file:
dependency: transitive dependency: transitive
description: description:
@ -406,34 +390,34 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: file_selector_android name: file_selector_android
sha256: "1d45e9910f68c16eb0c74f0b10097ad81aed516ea28054c027137e8f7d75e840" sha256: "7c76473740e33a11343c8fce88166049230850d2f19cd8a652ea935fcb8c9206"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.5.2+9" version: "0.5.2+10"
file_selector_ios: file_selector_ios:
dependency: transitive dependency: transitive
description: description:
name: file_selector_ios name: file_selector_ios
sha256: e2ecf2885c121691ce13b60db3508f53c01f869fb6e8dc5c1cfa771e4c46aeca sha256: "97269e5307a0ab813b1fa2430bada0a96e0afb74848417f8676f64ba5de0051c"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.5.3+5" version: "0.5.3+6"
file_selector_linux: file_selector_linux:
dependency: transitive dependency: transitive
description: description:
name: file_selector_linux name: file_selector_linux
sha256: "2567f398e06ac72dcf2e98a0c95df2a9edd03c2c2e0cacd4780f20cdf56263a0" sha256: da76400e7872ce7637ffdce12749ec24169c25f6195c28372208e65a24bcd2ab
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.9.4" version: "0.9.4+1"
file_selector_macos: file_selector_macos:
dependency: transitive dependency: transitive
description: description:
name: file_selector_macos name: file_selector_macos
sha256: "5e0bbe9c312416f1787a68259ea1505b52f258c587f12920422671807c4d618a" sha256: d57c62362766b5e7ae739448650b66c6aab7a68ba7ecc65e04018652645ae0f4
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.9.5" version: "0.9.5+1"
file_selector_platform_interface: file_selector_platform_interface:
dependency: transitive dependency: transitive
description: description:
@ -454,10 +438,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: file_selector_windows name: file_selector_windows
sha256: "62197474ae75893a62df75939c777763d39c2bc5f73ce5b88497208bc269abfd" sha256: fbefc5fb92c6d3cbe8d284a2cd971b593bb07d2cd6da8557b81a862250b4acec
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.9.3+5" version: "0.9.3+6"
fixnum: fixnum:
dependency: transitive dependency: transitive
description: description:
@ -511,6 +495,46 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.0.0" version: "6.0.0"
flutter_local_notifications:
dependency: "direct main"
description:
name: flutter_local_notifications
sha256: "1447ba911c60f2ba3f25dae1af151ec187162566b0f57e37771bf0b400f013ad"
url: "https://pub.dev"
source: hosted
version: "22.3.0"
flutter_local_notifications_linux:
dependency: "direct main"
description:
name: flutter_local_notifications_linux
sha256: "9ca97e63776f29ab1b955725c09999fc2c150523269db150c39274f2a43c5a8b"
url: "https://pub.dev"
source: hosted
version: "8.0.1"
flutter_local_notifications_platform_interface:
dependency: transitive
description:
name: flutter_local_notifications_platform_interface
sha256: "43c3761d916c9bd3d5c7ebbc44d82f4990329840c0c5d62ad5260cc1b5d399bd"
url: "https://pub.dev"
source: hosted
version: "12.2.0"
flutter_local_notifications_web:
dependency: transitive
description:
name: flutter_local_notifications_web
sha256: "516afaf97a2d1e67a036c6617321b00d205d72f7a67b6eccf936cd565f985878"
url: "https://pub.dev"
source: hosted
version: "1.0.0"
flutter_local_notifications_windows:
dependency: transitive
description:
name: flutter_local_notifications_windows
sha256: "6f43bdd03b171b7a90f22647506fea33e2bb12294b7c7c7a3d690e960a382945"
url: "https://pub.dev"
source: hosted
version: "3.1.1"
flutter_localizations: flutter_localizations:
dependency: "direct main" dependency: "direct main"
description: flutter description: flutter
@ -528,10 +552,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_riverpod name: flutter_riverpod
sha256: "56e81e662e6e54e59b231da57e90ac0d06ac67d8e3f2273c129a37ae6282b40c" sha256: "2b7f9d2a3c730ac1a98221b420cef966b990fca7ab546ede324642ca57a533e3"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.4.2" version: "3.4.3"
flutter_svg: flutter_svg:
dependency: "direct main" dependency: "direct main"
description: description:
@ -554,10 +578,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_widget_from_html_core name: flutter_widget_from_html_core
sha256: "7ff010b116f6abc16429923e616fbc727f3f65ef4cee12ffdb280aeecbc21e7f" sha256: "530f2e3cc57be1a00f8bfae1b0000064e8a6df0cf1fb4d48a80f85afde9b39b7"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.17.2" version: "0.17.4"
fluttertagger: fluttertagger:
dependency: "direct main" dependency: "direct main"
description: description:
@ -570,10 +594,10 @@ packages:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: freezed name: freezed
sha256: "27585a6c2b9ac28ffb7b45d87fd1502332af1eb90e1c9f5eb1acb24c71d26e17" sha256: "541a82723c84298f3ca46a6c2186935aa21ad529ad1f1423d67af18040494f51"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.0.0" version: "4.0.1"
freezed_annotation: freezed_annotation:
dependency: "direct main" dependency: "direct main"
description: description:
@ -582,14 +606,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.0" version: "3.1.0"
frontend_server_client:
dependency: transitive
description:
name: frontend_server_client
sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694
url: "https://pub.dev"
source: hosted
version: "4.0.0"
get_x_storage: get_x_storage:
dependency: transitive dependency: transitive
description: description:
@ -602,10 +618,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: glob name: glob
sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de sha256: "218aeb56050c714f62a3182775320dfa04602b55074873e24e31bbd39bda96fb"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.3" version: "2.2.0"
graphs: graphs:
dependency: transitive dependency: transitive
description: description:
@ -634,18 +650,18 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: hooks_riverpod name: hooks_riverpod
sha256: fce693abc6289c8bb42348eae520b979f7edbaae0c1b77b946ef058d0693f6f6 sha256: d58e1e14aa112ca9c56d54effb7d0d717b2d3f96dad3cdd1fce16f8740450700
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.4.2" version: "3.4.3"
html: html:
dependency: transitive dependency: transitive
description: description:
name: html name: html
sha256: "6d1264f2dffa1b1101c25a91dff0dc2daee4c18e87cd8538729773c073dbf602" sha256: "43b67b8f43321ab066817dfac5619596c98bb1b61624e77203bb4351785f9699"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.15.6" version: "0.15.7"
http: http:
dependency: "direct main" dependency: "direct main"
description: description:
@ -698,10 +714,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: image_picker_android name: image_picker_android
sha256: "6f3a1995eafb000333174fae92202622033b0ee7fd917a6cd3730295264df84a" sha256: "1c0c38790306fda4ed774095620444333e56a2b6bc8fc98f3a35c9398781cf54"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.8.13+19" version: "0.8.13+22"
image_picker_for_web: image_picker_for_web:
dependency: transitive dependency: transitive
description: description:
@ -714,10 +730,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: image_picker_ios name: image_picker_ios
sha256: b9c4a438a9ff4f60808c9cf0039b93a42bb6c2211ef6ebb647394b2b3fa84588 sha256: ee3885b6fcd71958fbc79770dd194c63371439d536d69c47b279171a486482ae
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.8.13+6" version: "0.8.13+7"
image_picker_linux: image_picker_linux:
dependency: transitive dependency: transitive
description: description:
@ -762,10 +778,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: io name: io
sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b sha256: "2635216ca6a737e60de577ffa1a48a0bec76ca8a62917cfc1bb88c14c570646f"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.5" version: "1.1.0"
js: js:
dependency: transitive dependency: transitive
description: description:
@ -851,10 +867,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: m3e_buttons name: m3e_buttons
sha256: "001031f1b72ef19643a8a6a531aafcfb31a06b53456b6f60014403c125e67056" sha256: "6bf60389eb7c838ac0402dba3657738ae1b015e312bc955ad8330ac17695a516"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.0" version: "1.0.2"
m3e_card_list: m3e_card_list:
dependency: "direct main" dependency: "direct main"
description: description:
@ -891,10 +907,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: material_ui name: material_ui
sha256: "4f3f38b9953df0a87d6bf5f21880029f77c47048487d5339410c39936be4683b" sha256: fbfb53cab6c4629438feeade5f3d305f72944bc9d9f25786b19106d32b80ec45
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.1" version: "1.2.0"
measure_size: measure_size:
dependency: "direct main" dependency: "direct main"
description: description:
@ -979,10 +995,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: mime name: mime
sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" sha256: bd47de35f07e27267e69c8c8b22edf9473bfee170a60d60fcc93730c5144b7f6
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.0" version: "2.1.0"
motor: motor:
dependency: transitive dependency: transitive
description: description:
@ -995,10 +1011,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: native_toolchain_c name: native_toolchain_c
sha256: a1c26117c48cebe5677b0cf0e33a980a79a7c5577effc86f52e5a0d309cdcb60 sha256: "9d233b6f2d9c52e1a2b5fbe70451d2c10ac674d3bb419d0ec8de14989d437c26"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.19.3" version: "0.19.4"
navigation_rail_m3e: navigation_rail_m3e:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1008,30 +1024,22 @@ packages:
url: "https://github.com/Henry-Hiles/material_3_expressive" url: "https://github.com/Henry-Hiles/material_3_expressive"
source: git source: git
version: "0.3.5" version: "0.3.5"
node_preamble:
dependency: transitive
description:
name: node_preamble
sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db"
url: "https://pub.dev"
source: hosted
version: "2.0.2"
objective_c: objective_c:
dependency: transitive dependency: transitive
description: description:
name: objective_c name: objective_c
sha256: b7fb95a6d9a4f009edd63dc5ac69f07420b23a16161c6dd8660290b59c602e8e sha256: ad56fd53a78ff6b1472fa59ff2a4e8b8ccabafc586fc263a1dfad0b99b5553e3
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "9.5.0" version: "9.6.0"
package_config: package_config:
dependency: transitive dependency: transitive
description: description:
name: package_config name: package_config
sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc sha256: ffcf4cf3d6c0b74ac43708d9f56625506e8a68aa935abe9d267a7330f320eb5d
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.0" version: "3.0.0"
package_info_plus: package_info_plus:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1124,10 +1132,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: platform name: platform
sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" sha256: a36d119c13416516a7b5913fbe8af8531e11633d784c550b2125f76c758524ec
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.6" version: "3.2.0"
plugin_platform_interface: plugin_platform_interface:
dependency: transitive dependency: transitive
description: description:
@ -1148,10 +1156,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: pool name: pool
sha256: "978783255c543aa3586a1b3c21f6e9d720eb315376a915872c61ef8b5c20177d" sha256: "4177f68c237ea2128d1bee66ac17b2ce05ba3dbaafcbdd54c5d40a39d0b6b11c"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.5.2" version: "1.5.3"
posix: posix:
dependency: transitive dependency: transitive
description: description:
@ -1160,22 +1168,30 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.5.2" version: "6.5.2"
process:
dependency: transitive
description:
name: process
sha256: "4242ba3508d37e01808bdf71ad1d5bb93a8d671bf2e7450e6b1b353fb0808891"
url: "https://pub.dev"
source: hosted
version: "5.0.6"
pub_semver: pub_semver:
dependency: transitive dependency: transitive
description: description:
name: pub_semver name: pub_semver
sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" sha256: "261236774e8b1d69cfc6b9eabbc96c40f25e7a2d6b171f3385d4f65d5734fb24"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.0" version: "2.2.1"
pubspec_parse: pubspec_parse:
dependency: transitive dependency: transitive
description: description:
name: pubspec_parse name: pubspec_parse
sha256: "0560ba233314abbed0a48a2956f7f022cce7c3e1e73df540277da7544cad4082" sha256: c38b81cbf34450b67e0265d73433569d12e34782e30ed769c9cc99c9d5f2e796
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.5.0" version: "1.6.0"
quiver: quiver:
dependency: transitive dependency: transitive
description: description:
@ -1196,26 +1212,26 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: riverpod name: riverpod
sha256: "84351b3472a447f7b89f961f95c73287009d58c59d8cc1267425d995f78e50f1" sha256: "484dfc873ea4c4f4240e5635444fa066f87b07862b7279ebd004a2b71fba4b7a"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.4.2" version: "3.4.3"
riverpod_analyzer_utils: riverpod_analyzer_utils:
dependency: transitive dependency: transitive
description: description:
name: riverpod_analyzer_utils name: riverpod_analyzer_utils
sha256: "46a8dd0461080fde8f886f65f87580758dae8495e352f9ea6a09953abc3df7bd" sha256: bb13cb3985815840cc103eda1027158358c5fdc00f308fc6f76574d0594107af
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.0-dev.11" version: "1.0.0-dev.12"
riverpod_lint: riverpod_lint:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: riverpod_lint name: riverpod_lint
sha256: "7d37414a82b0f52f3d8e440320830d9a8c59620663884b2bb5baaca26296c995" sha256: "215cb3cd54a97e09bc3512535fa4e8bedd3bf2a06dc2ae015ac8e0050fc71bd1"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.8" version: "3.1.9"
rxdart: rxdart:
dependency: transitive dependency: transitive
description: description:
@ -1284,18 +1300,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_android name: shared_preferences_android
sha256: "0634e64bd719f89c012f392938e173521f535d3ecaf66558fa94a056d22b5cc7" sha256: "1e12aafe408aa50da80edfd679a2a6bf63ba7ab37c7fa98286da459a757b3399"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.27" version: "2.4.28"
shared_preferences_foundation: shared_preferences_foundation:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_foundation name: shared_preferences_foundation
sha256: "4e7eaffc2b17ba398759f1151415869a34771ba11ebbccd1b0145472a619a64f" sha256: "2ec3934efa51e46117f23031cc141b8fc878e8525b94ec1ea4f7f586cf1b47ea"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.5.6" version: "2.5.7"
shared_preferences_linux: shared_preferences_linux:
dependency: transitive dependency: transitive
description: description:
@ -1336,22 +1352,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.4.2" version: "1.4.2"
shelf_packages_handler:
dependency: transitive
description:
name: shelf_packages_handler
sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e"
url: "https://pub.dev"
source: hosted
version: "3.0.2"
shelf_static:
dependency: transitive
description:
name: shelf_static
sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3
url: "https://pub.dev"
source: hosted
version: "1.1.3"
shelf_web_socket: shelf_web_socket:
dependency: transitive dependency: transitive
description: description:
@ -1369,10 +1369,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: source_gen name: source_gen
sha256: a603f1fb984a7391ae5978d1b92bfaaa08b350dca5c825256f925818f7943bf5 sha256: "11b6047da8e4eb6c643ccac3d0fda3f9c9e11651695f7da24a85ade8aff15a44"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.2.4" version: "4.3.0"
source_helper: source_helper:
dependency: transitive dependency: transitive
description: description:
@ -1381,22 +1381,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.13" version: "1.3.13"
source_map_stack_trace:
dependency: transitive
description:
name: source_map_stack_trace
sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b
url: "https://pub.dev"
source: hosted
version: "2.1.2"
source_maps:
dependency: transitive
description:
name: source_maps
sha256: "14c2945847669b44089bb1222f66873d7ff7103c58911917f2a63c5a62327898"
url: "https://pub.dev"
source: hosted
version: "0.10.14"
source_span: source_span:
dependency: transitive dependency: transitive
description: description:
@ -1409,10 +1393,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: stack_trace name: stack_trace
sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" sha256: "277654b3034d17ac6f9f1cb5595db011b1d5d41e8806866db28e0abaa101c490"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.12.1" version: "1.12.2"
state_notifier: state_notifier:
dependency: transitive dependency: transitive
description: description:
@ -1433,10 +1417,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: stream_transform name: stream_transform
sha256: ad47125e588cfd37a9a7f86c7d6356dde8dfe89d071d293f80ca9e9273a33871 sha256: a00e5f18bffc764f923e7dec1038527f7fe7a1791361a7117f0358193f13d53a
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.1" version: "2.1.2"
string_scanner: string_scanner:
dependency: transitive dependency: transitive
description: description:
@ -1457,10 +1441,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: synchronized name: synchronized
sha256: "3a7b5d17422dd0f8d5c6c14feaa5a1c65638b9455f871a96f08437562c046931" sha256: "397b146f97613b83d84bdccb439bc8d0f3aebb6c1d14a9641e6f24201c490b2d"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.4.1+2" version: "3.4.2"
term_glyph: term_glyph:
dependency: transitive dependency: transitive
description: description:
@ -1469,14 +1453,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.2.2" version: "1.2.2"
test:
dependency: transitive
description:
name: test
sha256: ca578dc12bb8b2f40b67b7d3bd2fac4f31c01a6ff7130a14e2597b919934507f
url: "https://pub.dev"
source: hosted
version: "1.31.1"
test_api: test_api:
dependency: transitive dependency: transitive
description: description:
@ -1485,14 +1461,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.12" version: "0.7.12"
test_core:
dependency: transitive
description:
name: test_core
sha256: d2e98ec12998368dc59ddd47ab709f2cd55acd6b66dc7db764455a44082f4bc5
url: "https://pub.dev"
source: hosted
version: "0.6.18"
timeago: timeago:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1501,6 +1469,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.7.1" version: "3.7.1"
timezone:
dependency: transitive
description:
name: timezone
sha256: "981d1020d6ef8fe1e7b3de5054e5b25579ae7c403d7734adc508ffc47668e9cb"
url: "https://pub.dev"
source: hosted
version: "0.11.1"
typed_data: typed_data:
dependency: transitive dependency: transitive
description: description:
@ -1509,6 +1485,54 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.4.0" version: "1.4.0"
unifiedpush:
dependency: "direct main"
description:
name: unifiedpush
sha256: "8ed9767f750a1dc6159a77e2171641d0cb825dc87682d1ce1b8618689b79f58e"
url: "https://pub.dev"
source: hosted
version: "6.2.0"
unifiedpush_android:
dependency: transitive
description:
name: unifiedpush_android
sha256: a902e505e91c8e28b54b379bb27f255f66df409274a97af24d6719f12f0d13dc
url: "https://pub.dev"
source: hosted
version: "3.5.0"
unifiedpush_linux:
dependency: transitive
description:
name: unifiedpush_linux
sha256: c062d5eedd1cec70bcd33270cc4e01ae0ff6501f33d471167c06b34a968adfeb
url: "https://pub.dev"
source: hosted
version: "1.0.0"
unifiedpush_platform_interface:
dependency: transitive
description:
name: unifiedpush_platform_interface
sha256: "83372bc8d794b8b12ef6993b518d7be907dcfc2191bdf6de0ece5c4445d89880"
url: "https://pub.dev"
source: hosted
version: "4.0.0"
unifiedpush_storage_interface:
dependency: transitive
description:
name: unifiedpush_storage_interface
sha256: b8d423a4695efc616aa21d8ab48fb5ef99d6288c68b56282b8faac1579ceabd9
url: "https://pub.dev"
source: hosted
version: "1.0.0"
unifiedpush_storage_shared_preferences:
dependency: "direct main"
description:
name: unifiedpush_storage_shared_preferences
sha256: eda9c52bac0058f81e0d9c65e33eedc12c5901d2e68ad47fdf68175ddf00a3b4
url: "https://pub.dev"
source: hosted
version: "1.0.0"
universal_platform: universal_platform:
dependency: transitive dependency: transitive
description: description:
@ -1537,34 +1561,34 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_android name: url_launcher_android
sha256: b413d49b73867ac08dd2f9890efd3cc11f2a0e577618d50843440a1fb3776c32 sha256: "611e87fb320b70d1dd721dc46af89c98aceccea9b31fde49e084591414e0c610"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.3.32" version: "6.3.33"
url_launcher_ios: url_launcher_ios:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_ios name: url_launcher_ios
sha256: "580fe5dfb51671ae38191d316e027f6b76272b026370708c2d898799750a02b0" sha256: "8faa1aab294f1ab4040b43660c887b0418d5fa4f0cffef76a484e6aa1092eb4a"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.4.1" version: "6.4.2"
url_launcher_linux: url_launcher_linux:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_linux name: url_launcher_linux
sha256: d5e14138b3bc193a0f63c10a53c94b91d399df0512b1f29b94a043db7482384a sha256: "10f86fef4c2c43563fa6c211ff9cf757adf4d3ab762c56bd430664a947d70cd0"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.2.2" version: "3.2.3"
url_launcher_macos: url_launcher_macos:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_macos name: url_launcher_macos
sha256: "368adf46f71ad3c21b8f06614adb38346f193f3a59ba8fe9a2fd74133070ba18" sha256: "5e835a3b869c2d70325349c81c5a45c28e20791265b67b2669da6b08c5cd5201"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.2.5" version: "3.2.6"
url_launcher_platform_interface: url_launcher_platform_interface:
dependency: transitive dependency: transitive
description: description:
@ -1585,10 +1609,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_windows name: url_launcher_windows
sha256: "712c70ab1b99744ff066053cbe3e80c73332b38d46e5e945c98689b2e66fc15f" sha256: "6c5ad3f22cd4c38e089b81963b3cd7bb83b111b2df5dce008bb066162f42e429"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.5" version: "3.1.6"
uuid: uuid:
dependency: transitive dependency: transitive
description: description:
@ -1641,18 +1665,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: wakelock_plus name: wakelock_plus
sha256: "7253bca0fcf40d8413ddfcf4d2a1fa0a82475e79be25a4f2c564b695c9351486" sha256: "22b3e7e937721de70e63c85e7139f4ac781dc22863b9262431a53ac030eb074b"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.7.0" version: "1.8.0"
wakelock_plus_platform_interface: wakelock_plus_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: wakelock_plus_platform_interface name: wakelock_plus_platform_interface
sha256: "0618d1799f0b28bcf98255b4ee8313e6fc4d38589dc4ee5fe5840d57d1aff6da" sha256: "764c25504562abc8ac3406f5d175f126b276e6ba916c7c2675690b73368ca384"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.6.0" version: "1.7.0"
watcher: watcher:
dependency: transitive dependency: transitive
description: description:
@ -1685,14 +1709,22 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.3" version: "3.0.3"
webkit_inspection_protocol: webcrypto:
dependency: transitive dependency: "direct dev"
description: description:
name: webkit_inspection_protocol name: webcrypto
sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572" sha256: "6b43001c4110856ff7fa5e5e65e7b2d44bec1d8b54a4d84d5fa2c7622267c5c1"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.2.1" version: "0.6.0"
webpush_encryption:
dependency: transitive
description:
name: webpush_encryption
sha256: "5b83272b91acda6ae515fcd980c94f06bf413702282497c5a68f5dfc64fed27f"
url: "https://pub.dev"
source: hosted
version: "1.0.1"
win32: win32:
dependency: transitive dependency: transitive
description: description:
@ -1729,10 +1761,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: yaml name: yaml
sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce sha256: f67cdd8e07d3c6329146aaef1ba043542b3134c12489f553ca9a7435d1068aea
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.3" version: "3.1.4"
yaml_edit: yaml_edit:
dependency: transitive dependency: transitive
description: description:

View file

@ -31,8 +31,8 @@ dependencies:
sdk: flutter sdk: flutter
flutter_localizations: flutter_localizations:
sdk: flutter sdk: flutter
flutter_riverpod: 3.4.2 flutter_riverpod: 3.4.3
hooks_riverpod: 3.4.2 hooks_riverpod: 3.4.3
intl: 0.20.3 intl: 0.20.3
fast_immutable_collections: 11.2.0 fast_immutable_collections: 11.2.0
path_provider: 2.1.6 path_provider: 2.1.6
@ -44,7 +44,7 @@ dependencies:
collection: 1.19.1 collection: 1.19.1
window_manager: 0.5.2 window_manager: 0.5.2
color_hash: 1.0.1 color_hash: 1.0.1
flutter_widget_from_html_core: 0.17.2 flutter_widget_from_html_core: 0.17.4
flutter_svg: 2.3.0 flutter_svg: 2.3.0
json_annotation: 4.12.0 json_annotation: 4.12.0
shared_preferences: 2.5.5 shared_preferences: 2.5.5
@ -52,9 +52,9 @@ dependencies:
dynamic_polls: 0.0.8 dynamic_polls: 0.0.8
flutter_hooks: 0.21.3+1 flutter_hooks: 0.21.3+1
ffi: 2.2.0 ffi: 2.2.0
hooks: ^2.2.0 hooks: 2.2.0
code_assets: 1.2.1 code_assets: 2.0.0
ffigen: 21.0.0 ffigen: 22.0.0
timeago: 3.7.1 timeago: 3.7.1
http: 1.6.0 http: 1.6.0
flutter_linkify: 6.0.0 flutter_linkify: 6.0.0
@ -68,7 +68,7 @@ dependencies:
media_kit_video: 2.0.1 media_kit_video: 2.0.1
media_kit_libs_video: 1.0.7 media_kit_libs_video: 1.0.7
measure_size: 5.0.2 measure_size: 5.0.2
m3e_buttons: 1.0.0 m3e_buttons: 1.0.2
navigation_rail_m3e: navigation_rail_m3e:
git: git:
url: https://github.com/Henry-Hiles/material_3_expressive url: https://github.com/Henry-Hiles/material_3_expressive
@ -78,15 +78,21 @@ dependencies:
package_info_plus: 10.2.1 package_info_plus: 10.2.1
app_links: 7.2.1 app_links: 7.2.1
file_selector: 1.1.0 file_selector: 1.1.0
material_ui: 1.0.1 material_ui: 1.2.0
unifiedpush: 6.2.0
unifiedpush_storage_shared_preferences: 1.0.0
flutter_local_notifications: 22.3.0
flutter_local_notifications_linux: 8.0.1
dev_dependencies: dev_dependencies:
build_runner: 2.16.0 build_runner: 2.16.1
flutter_lints: 6.0.0 flutter_lints: 6.0.0
freezed: 4.0.0 freezed: 4.0.1
riverpod_lint: 3.1.8 riverpod_lint: 3.1.9
flutter_launcher_icons: 0.14.4 flutter_launcher_icons: 0.14.4
json_serializable: 6.14.1 json_serializable: 6.14.1
# Transitive dep but needed for commands
webcrypto: any
flutter_launcher_icons: flutter_launcher_icons:
image_path: assets/icon.png image_path: assets/icon.png

View file

@ -1,4 +1,5 @@
import "dart:io"; import "dart:io";
import "package:ffigen/ffigen.dart"; import "package:ffigen/ffigen.dart";
import "package:path/path.dart"; import "package:path/path.dart";
import "package:nexus/helpers/extensions/get_xcode_sdk.dart"; import "package:nexus/helpers/extensions/get_xcode_sdk.dart";
@ -10,17 +11,19 @@ void main(List<String> args) async {
final libclangPath = Platform.environment["LIBCLANG_PATH"]; final libclangPath = Platform.environment["LIBCLANG_PATH"];
FfiGenerator( FfiGenerator(
output: Output( output: .new(
dartFile: Platform.script.resolve("../lib/src/third_party/gomuks.g.dart"), dart: .new(
path: Platform.script.resolve("../lib/src/third_party/gomuks.g.dart"),
), ),
headers: Headers( ),
visitors: [.new(func: (node) => node.isIncluded = true)],
input: .new(
entryPoints: [File(join(repoDir.path, "pkg", "ffi", "gomuksffi.h")).uri], entryPoints: [File(join(repoDir.path, "pkg", "ffi", "gomuksffi.h")).uri],
compilerOptions: [ compilerOptions: [
"--no-warnings", "--no-warnings",
if (Platform.isMacOS) "-I${await getXCodeTool()}/usr/include", if (Platform.isMacOS) "-I${await getXCodeTool()}/usr/include",
], ],
), ),
functions: Functions.includeAll,
).generate( ).generate(
libclangDylib: libclangPath == null libclangDylib: libclangPath == null
? null ? null

View file

@ -13,6 +13,7 @@
#include <media_kit_video/media_kit_video_plugin_c_api.h> #include <media_kit_video/media_kit_video_plugin_c_api.h>
#include <screen_retriever_windows/screen_retriever_windows_plugin_c_api.h> #include <screen_retriever_windows/screen_retriever_windows_plugin_c_api.h>
#include <url_launcher_windows/url_launcher_windows.h> #include <url_launcher_windows/url_launcher_windows.h>
#include <webcrypto/webcrypto_plugin.h>
#include <window_manager/window_manager_plugin.h> #include <window_manager/window_manager_plugin.h>
void RegisterPlugins(flutter::PluginRegistry* registry) { void RegisterPlugins(flutter::PluginRegistry* registry) {
@ -30,6 +31,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
registry->GetRegistrarForPlugin("ScreenRetrieverWindowsPluginCApi")); registry->GetRegistrarForPlugin("ScreenRetrieverWindowsPluginCApi"));
UrlLauncherWindowsRegisterWithRegistrar( UrlLauncherWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("UrlLauncherWindows")); registry->GetRegistrarForPlugin("UrlLauncherWindows"));
WebcryptoPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("WebcryptoPlugin"));
WindowManagerPluginRegisterWithRegistrar( WindowManagerPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("WindowManagerPlugin")); registry->GetRegistrarForPlugin("WindowManagerPlugin"));
} }

View file

@ -10,10 +10,12 @@ list(APPEND FLUTTER_PLUGIN_LIST
media_kit_video media_kit_video
screen_retriever_windows screen_retriever_windows
url_launcher_windows url_launcher_windows
webcrypto
window_manager window_manager
) )
list(APPEND FLUTTER_FFI_PLUGIN_LIST list(APPEND FLUTTER_FFI_PLUGIN_LIST
flutter_local_notifications_windows
) )
set(PLUGIN_BUNDLED_LIBRARIES) set(PLUGIN_BUNDLED_LIBRARIES)