~emersion/goguma

8b134471e0dceb9066a7ca1de79d03cb3de5c3ad — Simon Ser a month ago 8fc985a
notification_controller: fetch active notification messaging style

Instead of restoring a notification's messaging style from the DB,
fetch it from the Android API.
4 files changed, 93 insertions(+), 65 deletions(-)

M lib/client_controller.dart
M lib/database.dart
M lib/notification_controller.dart
M pubspec.lock
M lib/client_controller.dart => lib/client_controller.dart +5 -12
@@ 687,27 687,20 @@ class ClientController {
		if (buffer.muted) {
			return;
		}
		var needsNotification = entries.any((entry) {
		entries = entries.where((entry) {
			if (buffer.lastDeliveredTime != null && buffer.lastDeliveredTime!.compareTo(entry.time) >= 0) {
				return false;
			}
			return _shouldNotifyMessage(entry);
		});
		if (!needsNotification) {
			return;
		}

		var unread = await _db.listUnreadMessages(buffer.id);
		var notifyEntries = unread.where(_shouldNotifyMessage).toList();

		if (notifyEntries.isEmpty) {
		}).toList();
		if (entries.isEmpty) {
			return;
		}

		if (client.isChannel(buffer.name)) {
			await _notifController.showHighlight(notifyEntries, buffer);
			await _notifController.showHighlight(entries, buffer);
		} else {
			await _notifController.showDirectMessage(notifyEntries, buffer);
			await _notifController.showDirectMessage(entries, buffer);
		}
	}


M lib/database.dart => lib/database.dart +0 -11
@@ 412,15 412,4 @@ class DB {
			}));
		});
	}

	Future<List<MessageEntry>> listUnreadMessages(int buffer) async {
		var entries = await _db.rawQuery('''
			SELECT Message.id, Message.time, Message.buffer, Message.raw
			FROM Message
			LEFT JOIN Buffer ON Message.buffer = Buffer.id
			WHERE buffer = ? AND Message.time > Buffer.last_read_time
			ORDER BY time
		''', [buffer]);
		return entries.map((m) => MessageEntry.fromMap(m)).toList();
	}
}

M lib/notification_controller.dart => lib/notification_controller.dart +87 -41
@@ 19,8 19,10 @@ class _NotificationChannel {
class _ActiveNotification {
	final int id;
	final String tag;
	final String title;
	final MessagingStyleInformation? messagingStyleInfo;

	_ActiveNotification(this.id, this.tag);
	_ActiveNotification(this.id, this.tag, this.title, this.messagingStyleInfo);
}

class NotificationController {


@@ 38,24 40,43 @@ class NotificationController {

		var androidPlugin = _plugin.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>();
		if (androidPlugin != null) {
			var activeNotifs = await androidPlugin.getActiveNotifications();
			for (var notif in activeNotifs ?? <ActiveNotification>[]) {
				if (notif.tag != null) {
					_active.add(_ActiveNotification(notif.id, notif.tag!));
				}
				if (_nextId <= notif.id) {
					_nextId = notif.id + 1;
			try {
				var activeNotifs = await androidPlugin.getActiveNotifications();
				if (activeNotifs != null) {
					_populateActive(androidPlugin, activeNotifs);
				}
			} on Exception catch (err) {
				print('Failed to list active notifications: $err');
			}
		}

			var launchDetails = await _plugin.getNotificationAppLaunchDetails();
			if (launchDetails == null || !launchDetails.didNotificationLaunchApp) {
				return null;
			}
			return launchDetails.payload;
		var launchDetails = await _plugin.getNotificationAppLaunchDetails();
		if (launchDetails == null || !launchDetails.didNotificationLaunchApp) {
			return null;
		}
		return launchDetails.payload;
	}

		return null;
	void _populateActive(AndroidFlutterLocalNotificationsPlugin androidPlugin, List<ActiveNotification> activeNotifs) async {
		for (var notif in activeNotifs) {
			if (_nextId <= notif.id) {
				_nextId = notif.id + 1;
			}

			if (notif.tag == null || notif.title == null) {
				print('Found an active notification without a tag or title');
				continue;
			}

			MessagingStyleInformation? messagingStyleInfo;
			try {
				messagingStyleInfo = await androidPlugin.getActiveNotificationMessagingStyle(notif.id, tag: notif.tag);
			} on Exception catch (err) {
				print('Failed to get active notification messagign style: $err');
			}

			_active.add(_ActiveNotification(notif.id, notif.tag!, notif.title!, messagingStyleInfo));
		}
	}

	void _handleSelectNotification(String? payload) {


@@ 67,15 88,20 @@ class NotificationController {
	}

	Future<void> showDirectMessage(List<MessageEntry> entries, BufferModel buffer) async {
		var entry = entries.last;
		var entry = entries.first;
		String tag = _bufferTag(buffer);
		_ActiveNotification? replace = _getActiveWithTag(tag);

		String title;
		if (entries.length == 1) {
		if (replace == null) {
			title = 'New message from ${entry.msg.source!.name}';
		} else {
			title = '${entries.length} messages from ${entry.msg.source!.name}';
			title = _incrementTitleCount(replace.title, entries.length, ' messages from ${entry.msg.source!.name}');
		}

		List<Message> messages = replace?.messagingStyleInfo?.messages ?? [];
		messages.addAll(entries.map(_buildMessage));

		await _show(
			title: title,
			body: _getMessageBody(entry),


@@ 85,21 111,26 @@ class NotificationController {
				description: 'Private messages sent directly to you',
			),
			dateTime: entry.dateTime,
			styleInformation: _buildMessagingStyleInfo(entries, buffer, false),
			messagingStyleInfo: _buildMessagingStyleInfo(messages, buffer, false),
			tag: _bufferTag(buffer),
		);
	}

	Future<void> showHighlight(List<MessageEntry> entries, BufferModel buffer) async {
		var entry = entries.last;
		var entry = entries.first;
		String tag = _bufferTag(buffer);
		_ActiveNotification? replace = _getActiveWithTag(tag);

		String title;
		if (entries.length == 1) {
		if (replace == null) {
			title = '${entry.msg.source!.name} mentionned you in ${buffer.name}';
		} else {
			title = '${entries.length} mentions in ${buffer.name}';
			title = _incrementTitleCount(replace.title, entries.length, ' mentions in ${buffer.name}');
		}

		List<Message> messages = replace?.messagingStyleInfo?.messages ?? [];
		messages.addAll(entries.map(_buildMessage));

		await _show(
			title: title,
			body: _getMessageBody(entry),


@@ 109,7 140,7 @@ class NotificationController {
				description: 'Messages mentionning your nickname in a channel',
			),
			dateTime: entry.dateTime,
			styleInformation: _buildMessagingStyleInfo(entries, buffer, true),
			messagingStyleInfo: _buildMessagingStyleInfo(messages, buffer, true),
			tag: _bufferTag(buffer),
		);
	}


@@ 129,19 160,32 @@ class NotificationController {
		);
	}

	MessagingStyleInformation _buildMessagingStyleInfo(List<MessageEntry> entries, BufferModel buffer, bool isChannel) {
	String _incrementTitleCount(String title, int incr, String suffix) {
		int total;
		if (!title.endsWith(suffix)) {
			total = 1;
		} else {
			total = int.parse(title.substring(0, title.length - suffix.length));
		}
		total += incr;
		return '$total$suffix';
	}

	MessagingStyleInformation _buildMessagingStyleInfo(List<Message> messages, BufferModel buffer, bool isChannel) {
		// TODO: Person.key, Person.bot, Person.uri
		return MessagingStyleInformation(
			Person(name: buffer.name),
			conversationTitle: buffer.name,
			groupConversation: isChannel,
			messages: entries.map((entry) {
				return Message(
					_getMessageBody(entry),
					entry.dateTime,
					Person(name: entry.msg.source!.name),
				);
			}).toList(),
			messages: messages,
		);
	}

	Message _buildMessage(MessageEntry entry) {
		return Message(
			_getMessageBody(entry),
			entry.dateTime,
			Person(name: entry.msg.source!.name),
		);
	}



@@ 177,22 221,24 @@ class NotificationController {
		await Future.wait(futures);
	}

	_ActiveNotification? _getActiveWithTag(String tag) {
		for (var notif in _active) {
			if (notif.tag == tag) {
				return notif;
			}
		}
		return null;
	}

	Future<void> _show({
		required String title,
		String? body,
		required _NotificationChannel channel,
		required String tag,
		DateTime? dateTime,
		StyleInformation? styleInformation,
		MessagingStyleInformation? messagingStyleInfo,
	}) async {
		_ActiveNotification? replace;
		for (var notif in _active) {
			if (notif.tag == tag) {
				replace = notif;
				break;
			}
		}

		_ActiveNotification? replace = _getActiveWithTag(tag);
		int id;
		if (replace != null) {
			_active.remove(replace);


@@ 200,7 246,7 @@ class NotificationController {
		} else {
			id = _nextId++;
		}
		_active.add(_ActiveNotification(id, tag));
		_active.add(_ActiveNotification(id, tag, title, messagingStyleInfo));

		await _plugin.show(id, title, body, NotificationDetails(
			linux: LinuxNotificationDetails(


@@ 212,7 258,7 @@ class NotificationController {
				priority: Priority.high,
				category: 'msg',
				when: dateTime?.millisecondsSinceEpoch,
				styleInformation: styleInformation,
				styleInformation: messagingStyleInfo,
				tag: tag,
				enableLights: true,
			),

M pubspec.lock => pubspec.lock +1 -1
@@ 145,7 145,7 @@ packages:
      name: flutter_local_notifications
      url: "https://pub.dartlang.org"
    source: hosted
    version: "9.5.0"
    version: "9.5.2"
  flutter_local_notifications_linux:
    dependency: transitive
    description: