Compare commits

..
Author SHA1 Message Date
edc8b5d34d
release v1.0.0-alpha5 2026-10-19 20:47:28 -04:00
5 changed files with 67 additions and 94 deletions

View file

@ -49,7 +49,7 @@ nexus = {
This tracks the latest commit on `main`. To stay on a release instead, pin the input to its tag:
```nix
url = "git+https://git.federated.nexus/Nexus/nexus?ref=refs/tags/v1.0.0-alpha4";
url = "git+https://git.federated.nexus/Nexus/nexus?ref=refs/tags/v1.0.0-alpha5";
```
Then import the module and enable it in your NixOS configuration:

View file

@ -10,16 +10,8 @@ import "package:nexus/main.dart";
import "package:flutter_local_notifications/flutter_local_notifications.dart";
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:nexus/controllers/notification_request.dart";
import "package:nexus/models/push_notification.dart";
import "package:xdg_desktop_portal/xdg_desktop_portal.dart";
typedef NotificationMessage = ({
NotificationUser sender,
NotificationUser self,
File? senderAvatar,
bool isDm,
});
class NotificationController
extends AsyncNotifier<FlutterLocalNotificationsPlugin> {
@override
@ -148,24 +140,24 @@ class NotificationController
return true;
}
/// Passing [message] shows it as a chat message in the conversation for
/// [threadId], naming the sender in group chats.
Future<void> send({
required int id,
required String title,
required String body,
String? payload,
String? threadId,
DateTime? timestamp,
String? body,
File? icon,
String? payload,
String? senderName,
File? senderAvatar,
String? selfName,
bool isGroup = false,
bool sound = true,
NotificationMessage? message,
DateTime? timestamp,
String? threadId,
}) async {
debugPrint("Sending notification for $id");
// In DMs the title is already the sender
final sender = message == null || message.isDm ? null : message.sender;
final prefixedBody = sender == null ? body : "${sender.name}: $body";
// In DMs the title is already the sender, so only prefix in groups
final prefix = isGroup ? senderName : null;
if (Platform.isLinux) {
final portal = await ref.read(PortalController.provider.future);
@ -174,14 +166,14 @@ class NotificationController
await portal.notification.addNotification(
id.toString(),
title: title,
body: prefixedBody,
markupBody: sender == null
body: prefix == null || body == null ? body : "$prefix: $body",
markupBody: prefix == null || body == null
? null
: "<b>${escape.convert(sender.name)}</b>: ${escape.convert(body)}",
: "<b>${escape.convert(prefix)}</b>: ${escape.convert(body)}",
defaultAction: "app.event",
defaultActionTarget: payload,
sound: sound ? null : const XdgNotificationSoundSilent(),
category: message == null ? null : XdgNotificationCategory.imReceived,
category: XdgNotificationCategory.imReceived,
priority: .normal,
buttons: [
// TODO: Impl when notif daemons actualy support imReplyWithText
@ -192,13 +184,11 @@ class NotificationController
// ),
],
);
return;
}
} else {
final controller = await future;
// Append to the conversation already shown under this id, if any
final existingStyle = Platform.isAndroid && message != null
final existingStyle = Platform.isAndroid
? await controller
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin
@ -211,50 +201,28 @@ class NotificationController
presentSound: sound,
threadIdentifier: threadId,
);
await controller.show(
id: id,
title: title,
body: prefixedBody,
payload: payload,
notificationDetails: .new(
android: message == null
? .new(
"general",
"General",
silent: !sound,
when: timestamp?.millisecondsSinceEpoch,
largeIcon: icon == null
? null
: FilePathAndroidBitmap(icon.path),
styleInformation: BigTextStyleInformation(body),
)
: .new(
final notificationDetails = NotificationDetails(
android: .new(
"messages",
"Messages",
silent: !sound,
when: timestamp?.millisecondsSinceEpoch,
category: .message,
largeIcon: icon == null
largeIcon: icon == null ? null : FilePathAndroidBitmap(icon.path),
styleInformation: senderName == null || body == null
? null
: FilePathAndroidBitmap(icon.path),
styleInformation: MessagingStyleInformation(
.new(key: message.self.id, name: message.self.name),
conversationTitle: message.isDm ? null : title,
groupConversation: !message.isDm,
: MessagingStyleInformation(
.new(name: selfName ?? "You"),
conversationTitle: isGroup ? title : null,
groupConversation: isGroup,
messages: [
...?existingStyle?.messages,
.new(
body,
timestamp ?? .now(),
.new(
key: message.sender.id,
name: message.sender.name,
icon: message.senderAvatar == null
name: senderName,
icon: senderAvatar == null
? null
: BitmapFilePathAndroidIcon(
message.senderAvatar!.path,
),
: BitmapFilePathAndroidIcon(senderAvatar.path),
),
),
],
@ -269,8 +237,16 @@ class NotificationController
? null
: .new(id: threadId, title: title, arguments: payload ?? ""),
),
),
);
await controller.show(
id: id,
title: title,
body: prefix == null || body == null ? body : "$prefix: $body",
notificationDetails: notificationDetails,
payload: payload,
);
}
}
static final provider =

View file

@ -122,21 +122,17 @@ class UnifiedPushController extends AsyncNotifier<String?> {
: notification.eventId)
.hashCode &
0x7fffffff,
threadId: notification.roomId,
title: notification.roomName,
body: notification.text,
payload: notification.eventRowId.toString(),
timestamp: notification.timestamp,
icon: icon,
sound: notification.sound,
message: (
sender: pmp == null
? notification.sender
: pmp.copyWith(id: "${notification.sender.id}/${pmp.id}"),
self: notification.self,
payload: notification.eventRowId.toString(),
body: notification.text,
senderName: pmp?.name ?? notification.sender.name,
senderAvatar: senderAvatar,
isDm: notification.isDm,
),
selfName: notification.self.name,
isGroup: !notification.isDm,
sound: notification.sound,
timestamp: notification.timestamp,
threadId: notification.roomId,
);
if (isInBackground) exit(0);

View file

@ -12,7 +12,7 @@
flutter.buildFlutterApplication {
pname = "nexus";
version = "1.0.0-alpha4";
version = "1.0.0-alpha5";
inherit src;
preBuild = ''

View file

@ -1,10 +1,11 @@
name: nexus
description: "A simple and user-friendly Matrix client"
version: 1.0.0-alpha4
version: 1.0.0-alpha5
publish_to: none
flutter:
fonts:
- family: bundled-emoji
- family: bundled-sans
fonts:
- asset: assets/fonts/Inter.ttf