fix shortcut ordering

This commit is contained in:
otsmr 2026-05-13 13:41:50 +02:00
parent 3d1b38192e
commit a1ca45c2b9
4 changed files with 87 additions and 59 deletions

View file

@ -14,11 +14,7 @@ class ShortcutsDao extends DatabaseAccessor<TwonlyDB> with _$ShortcutsDaoMixin {
ShortcutsDao(super.db); ShortcutsDao(super.db);
Stream<List<Shortcut>> watchAllShortcuts() { Stream<List<Shortcut>> watchAllShortcuts() {
return (select(shortcuts)..orderBy([ return select(shortcuts).watch();
(t) =>
OrderingTerm(expression: t.usageCounter, mode: OrderingMode.desc),
]))
.watch();
} }
Future<Shortcut?> getShortcutByEmoji(String emoji) { Future<Shortcut?> getShortcutByEmoji(String emoji) {

View file

@ -37,11 +37,12 @@ void callbackDispatcher() {
await AppEnvironment.init(); await AppEnvironment.init();
switch (task) { switch (task) {
case 'eu.twonly.periodic_task': case 'eu.twonly.periodic_task':
// if (await initBackgroundExecution()) { // if (await initBackgroundExecution()) {
// await handlePeriodicTask(); // await handlePeriodicTask();
// } // }
break; break;
case 'eu.twonly.processing_task': case 'eu.twonly.processing_task':
case _ when task.startsWith('progressing_finish_uploads_'):
if (await initBackgroundExecution()) { if (await initBackgroundExecution()) {
await handleProcessingTask(); await handleProcessingTask();
} }

View file

@ -96,23 +96,21 @@ Future<void> incFlameCounter(
final group = await twonlyDB.groupsDao.getGroup(groupId); final group = await twonlyDB.groupsDao.getGroup(groupId);
if (group == null) return; if (group == null) return;
if (group.isDirectChat) { final contacts = await twonlyDB.groupsDao.getGroupContact(
final contacts = await twonlyDB.groupsDao.getGroupContact( group.groupId,
group.groupId, );
); for (final contact in contacts) {
for (final contact in contacts) { await twonlyDB.contactsDao.updateContact(
await twonlyDB.contactsDao.updateContact( contact.userId,
contact.userId, ContactsCompanion(
ContactsCompanion( mediaReceivedCounter: Value(
mediaReceivedCounter: Value( contacts.first.mediaReceivedCounter + (received ? 1 : 0),
contacts.first.mediaReceivedCounter + (received ? 1 : 0),
),
mediaSendCounter: Value(
contacts.first.mediaSendCounter + (received ? 0 : 1),
),
), ),
); mediaSendCounter: Value(
} contacts.first.mediaSendCounter + (received ? 0 : 1),
),
),
);
} }
final totalMediaCounter = group.totalMediaCounter + 1; final totalMediaCounter = group.totalMediaCounter + 1;

View file

@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:collection'; import 'dart:collection';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:twonly/locator.dart'; import 'package:twonly/locator.dart';
@ -20,6 +21,41 @@ class ShortcutRowComp extends StatefulWidget {
} }
class _ShortcutRowCompState extends State<ShortcutRowComp> { class _ShortcutRowCompState extends State<ShortcutRowComp> {
List<Shortcut> _shortcuts = [];
late StreamSubscription<List<Shortcut>> shortcutSub;
@override
void initState() {
super.initState();
unawaited(initAsync());
}
Future<void> initAsync() async {
shortcutSub = twonlyDB.shortcutsDao.watchAllShortcuts().listen((shortcuts) {
if (_shortcuts.isEmpty) {
shortcuts.sort((a, b) => b.usageCounter.compareTo(a.usageCounter));
_shortcuts = shortcuts;
} else {
final map = {for (final s in shortcuts) s.id: s};
final updated = <Shortcut>[];
for (final old in _shortcuts) {
if (map.containsKey(old.id)) {
updated.add(map.remove(old.id)!);
}
}
updated.addAll(map.values);
_shortcuts = updated;
}
if (mounted) setState(() {});
});
}
@override
void dispose() {
unawaited(shortcutSub.cancel());
super.dispose();
}
Future<void> _openCreateDialog() async { Future<void> _openCreateDialog() async {
await context.navPush(const AddNewShortcutView()); await context.navPush(const AddNewShortcutView());
} }
@ -27,6 +63,9 @@ class _ShortcutRowCompState extends State<ShortcutRowComp> {
Future<void> _applyShortcut(Shortcut shortcut) async { Future<void> _applyShortcut(Shortcut shortcut) async {
await twonlyDB.shortcutsDao.incrementUsage(shortcut.id); await twonlyDB.shortcutsDao.incrementUsage(shortcut.id);
final members = await twonlyDB.shortcutsDao.getShortcutMembers(shortcut.id); final members = await twonlyDB.shortcutsDao.getShortcutMembers(shortcut.id);
for (final groupId in widget.selectedGroupIds.toList()) {
widget.updateSelectedGroupIds(groupId, false);
}
for (final m in members) { for (final m in members) {
widget.updateSelectedGroupIds(m.groupId, true); widget.updateSelectedGroupIds(m.groupId, true);
} }
@ -36,46 +75,40 @@ class _ShortcutRowCompState extends State<ShortcutRowComp> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return SizedBox( return SizedBox(
height: 40, height: 40,
child: StreamBuilder<List<Shortcut>>( child: ListView(
stream: twonlyDB.shortcutsDao.watchAllShortcuts(), scrollDirection: Axis.horizontal,
builder: (context, snapshot) { children: [
final shortcuts = snapshot.data ?? []; Row(
return ListView(
scrollDirection: Axis.horizontal,
children: [ children: [
Row( ActionChip(
children: [ padding: EdgeInsets.zero,
ActionChip( onPressed: _openCreateDialog,
label: _shortcuts.isEmpty
? Text(
context.lang.createShortcut,
style: const TextStyle(fontSize: 9),
)
: const Icon(Icons.add_reaction_outlined, size: 20),
shape: const StadiumBorder(),
),
for (final shortcut in _shortcuts)
GestureDetector(
onLongPress: () {
context.navPush(AddNewShortcutView(shortcut: shortcut));
},
child: ActionChip(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
onPressed: _openCreateDialog, onPressed: () => _applyShortcut(shortcut),
label: shortcuts.isEmpty label: Text(
? Text( shortcut.emoji,
context.lang.createShortcut, style: const TextStyle(fontSize: 18),
style: const TextStyle(fontSize: 9), ),
)
: const Icon(Icons.add_reaction_outlined, size: 20),
shape: const StadiumBorder(), shape: const StadiumBorder(),
), ),
for (final shortcut in shortcuts) ),
GestureDetector(
onLongPress: () {
context.navPush(AddNewShortcutView(shortcut: shortcut));
},
child: ActionChip(
padding: EdgeInsets.zero,
onPressed: () => _applyShortcut(shortcut),
label: Text(
shortcut.emoji,
style: const TextStyle(fontSize: 18),
),
shape: const StadiumBorder(),
),
),
],
),
], ],
); ),
}, ],
), ),
); );
} }