implemented dual Nextcloud push registration with separate general and talk apptypes to ensure reliable Talk notification delivery; introduced stacked MessagingStyle notifications for chat threads with support for circular conversation avatars and disk caching

This commit is contained in:
2026-07-05 22:48:04 +02:00
parent 35e144799e
commit 483fea62ba
31 changed files with 2807 additions and 320 deletions
+74
View File
@@ -0,0 +1,74 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:marianum_mobile/push/chat_thread_store.dart';
import 'package:marianum_mobile/push/push_actions.dart';
void main() {
group('PushActions.finishReply', () {
const token = 'chat1';
final thread = [
const ThreadMessage(nid: 1, sender: 'Max', text: 'Hi', timestampMs: 1),
const ThreadMessage(nid: 2, sender: 'Max', text: 'Da?', timestampMs: 2),
];
test(
'successful reply removes the notification via chat cleanup',
() async {
var cleanups = 0;
var renders = 0;
var cancels = 0;
await PushActions.finishReply(
chatToken: token,
sent: true,
cleanupChat: (t) async {
expect(t, token);
cleanups++;
},
loadThread: (_) async => thread,
renderSilent: (_, _) async => renders++,
cancelNotification: (_) async => cancels++,
);
expect(cleanups, 1);
expect(renders, 0);
expect(cancels, 0);
},
);
test('failed reply re-renders the unchanged thread exactly once', () async {
var cleanups = 0;
var renders = 0;
List<ThreadMessage>? rendered;
await PushActions.finishReply(
chatToken: token,
sent: false,
cleanupChat: (_) async => cleanups++,
loadThread: (_) async => thread,
renderSilent: (t, messages) async {
expect(t, token);
renders++;
rendered = messages;
},
cancelNotification: (_) async => fail('must not cancel'),
);
expect(cleanups, 0);
expect(renders, 1);
// History unchanged — same messages, no self entry appended.
expect(rendered!.map((m) => m.nid), [1, 2]);
});
test(
'failed reply with empty history cancels to stop the spinner',
() async {
var cancels = 0;
await PushActions.finishReply(
chatToken: token,
sent: false,
cleanupChat: (_) async => fail('must not cleanup'),
loadThread: (_) async => const [],
renderSilent: (_, _) async => fail('nothing to render'),
cancelNotification: (_) async => cancels++,
);
expect(cancels, 1);
},
);
});
}