mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-05-25 07:02:12 +00:00
shwo mutual groups
Some checks are pending
Flutter analyze & test / flutter_analyze_and_test (push) Waiting to run
Some checks are pending
Flutter analyze & test / flutter_analyze_and_test (push) Waiting to run
This commit is contained in:
parent
304190387d
commit
6f8f1efe81
7 changed files with 259 additions and 67 deletions
|
|
@ -2738,6 +2738,18 @@ abstract class AppLocalizations {
|
||||||
/// **'{username} has scanned your QR code and is now verified.'**
|
/// **'{username} has scanned your QR code and is now verified.'**
|
||||||
String secretQrTokenVerifiedSnackbar(Object username);
|
String secretQrTokenVerifiedSnackbar(Object username);
|
||||||
|
|
||||||
|
/// No description provided for @mutualGroupsTitle.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'{count, plural, =1{1 mutual group} other{{count} mutual groups}}'**
|
||||||
|
String mutualGroupsTitle(num count);
|
||||||
|
|
||||||
|
/// No description provided for @mutualGroupsSentMessages.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'{count, plural, =1{1 message sent} other{{count} messages sent}}'**
|
||||||
|
String mutualGroupsSentMessages(num count);
|
||||||
|
|
||||||
/// No description provided for @chatEntryFlameRestored.
|
/// No description provided for @chatEntryFlameRestored.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
|
|
|
||||||
|
|
@ -1528,6 +1528,28 @@ class AppLocalizationsDe extends AppLocalizations {
|
||||||
return '$username hat deinen QR-Code gescannt und ist nun verifiziert.';
|
return '$username hat deinen QR-Code gescannt und ist nun verifiziert.';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String mutualGroupsTitle(num count) {
|
||||||
|
String _temp0 = intl.Intl.pluralLogic(
|
||||||
|
count,
|
||||||
|
locale: localeName,
|
||||||
|
other: '$count gemeinsame Gruppen',
|
||||||
|
one: '1 gemeinsame Gruppe',
|
||||||
|
);
|
||||||
|
return '$_temp0';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String mutualGroupsSentMessages(num count) {
|
||||||
|
String _temp0 = intl.Intl.pluralLogic(
|
||||||
|
count,
|
||||||
|
locale: localeName,
|
||||||
|
other: '$count Nachrichten gesendet',
|
||||||
|
one: '1 Nachricht gesendet',
|
||||||
|
);
|
||||||
|
return '$_temp0';
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String chatEntryFlameRestored(Object count) {
|
String chatEntryFlameRestored(Object count) {
|
||||||
return '$count Flammen wiederhergestellt';
|
return '$count Flammen wiederhergestellt';
|
||||||
|
|
|
||||||
|
|
@ -1513,6 +1513,28 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||||
return '$username has scanned your QR code and is now verified.';
|
return '$username has scanned your QR code and is now verified.';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String mutualGroupsTitle(num count) {
|
||||||
|
String _temp0 = intl.Intl.pluralLogic(
|
||||||
|
count,
|
||||||
|
locale: localeName,
|
||||||
|
other: '$count mutual groups',
|
||||||
|
one: '1 mutual group',
|
||||||
|
);
|
||||||
|
return '$_temp0';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String mutualGroupsSentMessages(num count) {
|
||||||
|
String _temp0 = intl.Intl.pluralLogic(
|
||||||
|
count,
|
||||||
|
locale: localeName,
|
||||||
|
other: '$count messages sent',
|
||||||
|
one: '1 message sent',
|
||||||
|
);
|
||||||
|
return '$_temp0';
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String chatEntryFlameRestored(Object count) {
|
String chatEntryFlameRestored(Object count) {
|
||||||
return '$count flames restored';
|
return '$count flames restored';
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 0675e74501d6610a84273232517652db25965e3f
|
Subproject commit 3a9c589de2d2abc0042004dbfe943fa4fb2c92c7
|
||||||
|
|
@ -8,7 +8,6 @@ import 'package:twonly/locator.dart';
|
||||||
import 'package:twonly/src/constants/routes.keys.dart';
|
import 'package:twonly/src/constants/routes.keys.dart';
|
||||||
import 'package:twonly/src/database/daos/contacts.dao.dart';
|
import 'package:twonly/src/database/daos/contacts.dao.dart';
|
||||||
import 'package:twonly/src/database/twonly.db.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/services/user_discovery.service.dart';
|
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/visual/components/alert.dialog.dart';
|
import 'package:twonly/src/visual/components/alert.dialog.dart';
|
||||||
import 'package:twonly/src/visual/components/avatar_icon.comp.dart';
|
import 'package:twonly/src/visual/components/avatar_icon.comp.dart';
|
||||||
|
|
@ -17,10 +16,11 @@ import 'package:twonly/src/visual/components/select_chat_deletion_time.comp.dart
|
||||||
import 'package:twonly/src/visual/components/snackbar.dart';
|
import 'package:twonly/src/visual/components/snackbar.dart';
|
||||||
import 'package:twonly/src/visual/components/verification_badge.comp.dart';
|
import 'package:twonly/src/visual/components/verification_badge.comp.dart';
|
||||||
import 'package:twonly/src/visual/elements/better_list_title.element.dart';
|
import 'package:twonly/src/visual/elements/better_list_title.element.dart';
|
||||||
|
import 'package:twonly/src/visual/views/contact/contact_components/mutual_groups_expansion_tile.comp.dart';
|
||||||
import 'package:twonly/src/visual/views/contact/contact_components/restore_flame.comp.dart';
|
import 'package:twonly/src/visual/views/contact/contact_components/restore_flame.comp.dart';
|
||||||
|
import 'package:twonly/src/visual/views/contact/contact_components/user_discovery_contact_settings.comp.dart';
|
||||||
import 'package:twonly/src/visual/views/contact/contact_components/verification_expansion_tile.comp.dart';
|
import 'package:twonly/src/visual/views/contact/contact_components/verification_expansion_tile.comp.dart';
|
||||||
import 'package:twonly/src/visual/views/groups/group.view.dart';
|
import 'package:twonly/src/visual/views/groups/group.view.dart';
|
||||||
import 'package:twonly/src/visual/views/settings/privacy/user_discovery.view.dart';
|
|
||||||
|
|
||||||
class ContactView extends StatefulWidget {
|
class ContactView extends StatefulWidget {
|
||||||
const ContactView(this.userId, {super.key});
|
const ContactView(this.userId, {super.key});
|
||||||
|
|
@ -93,14 +93,6 @@ class _ContactViewState extends State<ContactView> {
|
||||||
);
|
);
|
||||||
if (remove) {
|
if (remove) {
|
||||||
await twonlyDB.contactsDao.deleteContactByUserId(contact.userId);
|
await twonlyDB.contactsDao.deleteContactByUserId(contact.userId);
|
||||||
// await twonlyDB.contactsDao.updateContact(
|
|
||||||
// contact.userId,
|
|
||||||
// const ContactsCompanion(
|
|
||||||
// accepted: Value(false),
|
|
||||||
// requested: Value(false),
|
|
||||||
// deletedByUser: Value(true),
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
Navigator.popUntil(context, (route) => route.isFirst);
|
Navigator.popUntil(context, (route) => route.isFirst);
|
||||||
}
|
}
|
||||||
|
|
@ -240,62 +232,13 @@ class _ContactViewState extends State<ContactView> {
|
||||||
VerificationExpansionTileComp(
|
VerificationExpansionTileComp(
|
||||||
contact: contact,
|
contact: contact,
|
||||||
),
|
),
|
||||||
if (userService.currentUser.isUserDiscoveryEnabled)
|
MutualGroupsExpansionTileComp(
|
||||||
if (userService.currentUser.userDiscoveryRequiresManualApproval &&
|
contact: contact,
|
||||||
contact.userDiscoveryManualApproved != true)
|
),
|
||||||
BetterListTile(
|
UserDiscoveryContactSettingsComp(
|
||||||
icon: FontAwesomeIcons.usersViewfinder,
|
contact: contact,
|
||||||
text: context.lang.userDiscoverySettingsTitle,
|
),
|
||||||
subtitle: Text(
|
const Divider(),
|
||||||
context.lang.contactUserDiscoveryManualApprovalPending,
|
|
||||||
style: const TextStyle(fontSize: 10),
|
|
||||||
),
|
|
||||||
trailing: TextButton(
|
|
||||||
onPressed: () async {
|
|
||||||
await twonlyDB.contactsDao.updateContact(
|
|
||||||
contact.userId,
|
|
||||||
const ContactsCompanion(
|
|
||||||
userDiscoveryManualApproved: Value(true),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
context.lang.contactUserDiscoveryManualApprovalApprove,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
else
|
|
||||||
BetterListTile(
|
|
||||||
icon: FontAwesomeIcons.usersViewfinder,
|
|
||||||
text: context.lang.userDiscoverySettingsTitle,
|
|
||||||
onTap: () => context.navPush(const UserDiscoverySettingsView()),
|
|
||||||
subtitle:
|
|
||||||
!contact.userDiscoveryExcluded &&
|
|
||||||
contact.mediaSendCounter <
|
|
||||||
userService.currentUser.requiredSendImages
|
|
||||||
? Text(
|
|
||||||
context.lang.contactUserDiscoveryImagesLeft(
|
|
||||||
userService.currentUser.requiredSendImages -
|
|
||||||
contact.mediaSendCounter,
|
|
||||||
getContactDisplayName(contact),
|
|
||||||
),
|
|
||||||
style: const TextStyle(fontSize: 9),
|
|
||||||
)
|
|
||||||
: null,
|
|
||||||
trailing: Transform.scale(
|
|
||||||
scale: 0.8,
|
|
||||||
child: Switch(
|
|
||||||
value: !contact.userDiscoveryExcluded,
|
|
||||||
onChanged: (a) async {
|
|
||||||
await UserDiscoveryService.changeExclusionForContact(
|
|
||||||
contact.userId,
|
|
||||||
!a,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
BetterListTile(
|
BetterListTile(
|
||||||
icon: FontAwesomeIcons.flag,
|
icon: FontAwesomeIcons.flag,
|
||||||
text: context.lang.reportUser,
|
text: context.lang.reportUser,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,112 @@
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
|
import 'package:twonly/locator.dart';
|
||||||
|
import 'package:twonly/src/constants/routes.keys.dart';
|
||||||
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
|
import 'package:twonly/src/visual/components/avatar_icon.comp.dart';
|
||||||
|
|
||||||
|
class MutualGroupsExpansionTileComp extends StatefulWidget {
|
||||||
|
const MutualGroupsExpansionTileComp({
|
||||||
|
required this.contact,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
final Contact contact;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<MutualGroupsExpansionTileComp> createState() =>
|
||||||
|
_MutualGroupsExpansionTileCompState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MutualGroupsExpansionTileCompState
|
||||||
|
extends State<MutualGroupsExpansionTileComp> {
|
||||||
|
List<Group> _groups = [];
|
||||||
|
late StreamSubscription<List<Group>> _streamGroups;
|
||||||
|
bool? _hasInitializedExpanded;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_streamGroups = twonlyDB.groupsDao
|
||||||
|
.watchNonDirectGroupsForMember(widget.contact.userId)
|
||||||
|
.listen((groupsList) {
|
||||||
|
if (!mounted) return;
|
||||||
|
setState(() {
|
||||||
|
_groups = groupsList;
|
||||||
|
_groups.sort((a, b) {
|
||||||
|
return b.totalMediaCounter.compareTo(a.totalMediaCounter);
|
||||||
|
});
|
||||||
|
_hasInitializedExpanded ??= true;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_streamGroups.cancel();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
if (_hasInitializedExpanded == null || _groups.isEmpty) {
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ExpansionTile(
|
||||||
|
key: PageStorageKey<String>('mutual_groups_${widget.contact.userId}'),
|
||||||
|
shape: const RoundedRectangleBorder(),
|
||||||
|
backgroundColor: context.color.surfaceContainer,
|
||||||
|
collapsedShape: const RoundedRectangleBorder(),
|
||||||
|
initiallyExpanded: _groups.length < 5,
|
||||||
|
onExpansionChanged: (expanded) {
|
||||||
|
setState(() {});
|
||||||
|
},
|
||||||
|
leading: Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 14, right: 14),
|
||||||
|
child: SizedBox(
|
||||||
|
width: 20,
|
||||||
|
height: 20,
|
||||||
|
child: Icon(
|
||||||
|
FontAwesomeIcons.userGroup,
|
||||||
|
size: 16,
|
||||||
|
color: context.color.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
title: Text(
|
||||||
|
context.lang.mutualGroupsTitle(_groups.length),
|
||||||
|
style: TextStyle(
|
||||||
|
color: context.color.onSurface,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
children: _groups.map((group) {
|
||||||
|
return ListTile(
|
||||||
|
dense: true,
|
||||||
|
contentPadding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 16,
|
||||||
|
vertical: 4,
|
||||||
|
),
|
||||||
|
leading: AvatarIcon(
|
||||||
|
group: group,
|
||||||
|
fontSize: 14,
|
||||||
|
),
|
||||||
|
title: Text(
|
||||||
|
group.groupName,
|
||||||
|
style: TextStyle(
|
||||||
|
color: context.color.onSurface,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
context.push(Routes.chatsMessages(group.groupId));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
import 'package:drift/drift.dart' hide Column;
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
|
import 'package:twonly/locator.dart';
|
||||||
|
import 'package:twonly/src/database/daos/contacts.dao.dart';
|
||||||
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
|
import 'package:twonly/src/services/user_discovery.service.dart';
|
||||||
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
|
import 'package:twonly/src/visual/elements/better_list_title.element.dart';
|
||||||
|
import 'package:twonly/src/visual/views/settings/privacy/user_discovery.view.dart';
|
||||||
|
|
||||||
|
class UserDiscoveryContactSettingsComp extends StatelessWidget {
|
||||||
|
const UserDiscoveryContactSettingsComp({
|
||||||
|
required this.contact,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
final Contact contact;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
if (!userService.currentUser.isUserDiscoveryEnabled) {
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userService.currentUser.userDiscoveryRequiresManualApproval &&
|
||||||
|
contact.userDiscoveryManualApproved != true) {
|
||||||
|
return BetterListTile(
|
||||||
|
icon: FontAwesomeIcons.usersViewfinder,
|
||||||
|
text: context.lang.userDiscoverySettingsTitle,
|
||||||
|
subtitle: Text(
|
||||||
|
context.lang.contactUserDiscoveryManualApprovalPending,
|
||||||
|
style: const TextStyle(fontSize: 10),
|
||||||
|
),
|
||||||
|
trailing: TextButton(
|
||||||
|
onPressed: () async {
|
||||||
|
await twonlyDB.contactsDao.updateContact(
|
||||||
|
contact.userId,
|
||||||
|
const ContactsCompanion(
|
||||||
|
userDiscoveryManualApproved: Value(true),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
context.lang.contactUserDiscoveryManualApprovalApprove,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return BetterListTile(
|
||||||
|
icon: FontAwesomeIcons.usersViewfinder,
|
||||||
|
text: context.lang.userDiscoverySettingsTitle,
|
||||||
|
onTap: () => context.navPush(const UserDiscoverySettingsView()),
|
||||||
|
subtitle: !contact.userDiscoveryExcluded &&
|
||||||
|
contact.mediaSendCounter <
|
||||||
|
userService.currentUser.requiredSendImages
|
||||||
|
? Text(
|
||||||
|
context.lang.contactUserDiscoveryImagesLeft(
|
||||||
|
userService.currentUser.requiredSendImages -
|
||||||
|
contact.mediaSendCounter,
|
||||||
|
getContactDisplayName(contact),
|
||||||
|
),
|
||||||
|
style: const TextStyle(fontSize: 9),
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
trailing: Transform.scale(
|
||||||
|
scale: 0.8,
|
||||||
|
child: Switch(
|
||||||
|
value: !contact.userDiscoveryExcluded,
|
||||||
|
onChanged: (a) async {
|
||||||
|
await UserDiscoveryService.changeExclusionForContact(
|
||||||
|
contact.userId,
|
||||||
|
!a,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue