updating profile and minor issues

This commit is contained in:
otsmr 2025-10-26 22:49:36 +01:00
parent 746887b845
commit 7fe0f16a5c
15 changed files with 124 additions and 176 deletions

View file

@ -1,4 +1,5 @@
import 'package:drift/drift.dart';
import 'package:twonly/globals.dart';
import 'package:twonly/src/database/tables/contacts.table.dart';
import 'package:twonly/src/database/twonly.db.dart';
import 'package:twonly/src/database/twonly_database_old.dart' as old;
@ -45,6 +46,15 @@ class ContactsDao extends DatabaseAccessor<TwonlyDB> with _$ContactsDaoMixin {
final contact = await getContactByUserId(userId).getSingleOrNull();
if (contact != null) {
await updatePushUser(contact);
final group = await twonlyDB.groupsDao.getDirectChat(userId);
if (group != null) {
await twonlyDB.groupsDao.updateGroup(
group.groupId,
GroupsCompanion(
groupName: Value(getContactDisplayName(contact)),
),
);
}
}
}
}

View file

@ -26,8 +26,7 @@ class Messages extends Table {
BlobColumn get downloadToken => blob().nullable()();
TextColumn get quotesMessageId =>
text().nullable().references(Messages, #messageId)();
TextColumn get quotesMessageId => text().nullable()();
BoolColumn get isDeletedFromSender =>
boolean().withDefault(const Constant(false))();

View file

@ -2265,10 +2265,7 @@ class $MessagesTable extends Messages with TableInfo<$MessagesTable, Message> {
@override
late final GeneratedColumn<String> quotesMessageId = GeneratedColumn<String>(
'quotes_message_id', aliasedName, true,
type: DriftSqlType.string,
requiredDuringInsert: false,
defaultConstraints: GeneratedColumn.constraintIsAlways(
'REFERENCES messages (message_id)'));
type: DriftSqlType.string, requiredDuringInsert: false);
static const VerificationMeta _isDeletedFromSenderMeta =
const VerificationMeta('isDeletedFromSender');
@override
@ -8207,21 +8204,6 @@ final class $$MessagesTableReferences
manager.$state.copyWith(prefetchedData: [item]));
}
static $MessagesTable _quotesMessageIdTable(_$TwonlyDB db) =>
db.messages.createAlias($_aliasNameGenerator(
db.messages.quotesMessageId, db.messages.messageId));
$$MessagesTableProcessedTableManager? get quotesMessageId {
final $_column = $_itemColumn<String>('quotes_message_id');
if ($_column == null) return null;
final manager = $$MessagesTableTableManager($_db, $_db.messages)
.filter((f) => f.messageId.sqlEquals($_column));
final item = $_typedResult.readTableOrNull(_quotesMessageIdTable($_db));
if (item == null) return manager;
return ProcessedTableManager(
manager.$state.copyWith(prefetchedData: [item]));
}
static MultiTypedResultKey<$MessageHistoriesTable, List<MessageHistory>>
_messageHistoriesRefsTable(_$TwonlyDB db) =>
MultiTypedResultKey.fromTable(db.messageHistories,
@ -8315,6 +8297,10 @@ class $$MessagesTableFilterComposer
ColumnFilters<Uint8List> get downloadToken => $composableBuilder(
column: $table.downloadToken, builder: (column) => ColumnFilters(column));
ColumnFilters<String> get quotesMessageId => $composableBuilder(
column: $table.quotesMessageId,
builder: (column) => ColumnFilters(column));
ColumnFilters<bool> get isDeletedFromSender => $composableBuilder(
column: $table.isDeletedFromSender,
builder: (column) => ColumnFilters(column));
@ -8394,26 +8380,6 @@ class $$MessagesTableFilterComposer
return composer;
}
$$MessagesTableFilterComposer get quotesMessageId {
final $$MessagesTableFilterComposer composer = $composerBuilder(
composer: this,
getCurrentColumn: (t) => t.quotesMessageId,
referencedTable: $db.messages,
getReferencedColumn: (t) => t.messageId,
builder: (joinBuilder,
{$addJoinBuilderToRootComposer,
$removeJoinBuilderFromRootComposer}) =>
$$MessagesTableFilterComposer(
$db: $db,
$table: $db.messages,
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
joinBuilder: joinBuilder,
$removeJoinBuilderFromRootComposer:
$removeJoinBuilderFromRootComposer,
));
return composer;
}
Expression<bool> messageHistoriesRefs(
Expression<bool> Function($$MessageHistoriesTableFilterComposer f) f) {
final $$MessageHistoriesTableFilterComposer composer = $composerBuilder(
@ -8524,6 +8490,10 @@ class $$MessagesTableOrderingComposer
column: $table.downloadToken,
builder: (column) => ColumnOrderings(column));
ColumnOrderings<String> get quotesMessageId => $composableBuilder(
column: $table.quotesMessageId,
builder: (column) => ColumnOrderings(column));
ColumnOrderings<bool> get isDeletedFromSender => $composableBuilder(
column: $table.isDeletedFromSender,
builder: (column) => ColumnOrderings(column));
@ -8602,26 +8572,6 @@ class $$MessagesTableOrderingComposer
));
return composer;
}
$$MessagesTableOrderingComposer get quotesMessageId {
final $$MessagesTableOrderingComposer composer = $composerBuilder(
composer: this,
getCurrentColumn: (t) => t.quotesMessageId,
referencedTable: $db.messages,
getReferencedColumn: (t) => t.messageId,
builder: (joinBuilder,
{$addJoinBuilderToRootComposer,
$removeJoinBuilderFromRootComposer}) =>
$$MessagesTableOrderingComposer(
$db: $db,
$table: $db.messages,
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
joinBuilder: joinBuilder,
$removeJoinBuilderFromRootComposer:
$removeJoinBuilderFromRootComposer,
));
return composer;
}
}
class $$MessagesTableAnnotationComposer
@ -8648,6 +8598,9 @@ class $$MessagesTableAnnotationComposer
GeneratedColumn<Uint8List> get downloadToken => $composableBuilder(
column: $table.downloadToken, builder: (column) => column);
GeneratedColumn<String> get quotesMessageId => $composableBuilder(
column: $table.quotesMessageId, builder: (column) => column);
GeneratedColumn<bool> get isDeletedFromSender => $composableBuilder(
column: $table.isDeletedFromSender, builder: (column) => column);
@ -8726,26 +8679,6 @@ class $$MessagesTableAnnotationComposer
return composer;
}
$$MessagesTableAnnotationComposer get quotesMessageId {
final $$MessagesTableAnnotationComposer composer = $composerBuilder(
composer: this,
getCurrentColumn: (t) => t.quotesMessageId,
referencedTable: $db.messages,
getReferencedColumn: (t) => t.messageId,
builder: (joinBuilder,
{$addJoinBuilderToRootComposer,
$removeJoinBuilderFromRootComposer}) =>
$$MessagesTableAnnotationComposer(
$db: $db,
$table: $db.messages,
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
joinBuilder: joinBuilder,
$removeJoinBuilderFromRootComposer:
$removeJoinBuilderFromRootComposer,
));
return composer;
}
Expression<T> messageHistoriesRefs<T extends Object>(
Expression<T> Function($$MessageHistoriesTableAnnotationComposer a) f) {
final $$MessageHistoriesTableAnnotationComposer composer = $composerBuilder(
@ -8846,7 +8779,6 @@ class $$MessagesTableTableManager extends RootTableManager<
{bool groupId,
bool senderId,
bool mediaId,
bool quotesMessageId,
bool messageHistoriesRefs,
bool reactionsRefs,
bool receiptsRefs,
@ -8941,7 +8873,6 @@ class $$MessagesTableTableManager extends RootTableManager<
{groupId = false,
senderId = false,
mediaId = false,
quotesMessageId = false,
messageHistoriesRefs = false,
reactionsRefs = false,
receiptsRefs = false,
@ -8997,17 +8928,6 @@ class $$MessagesTableTableManager extends RootTableManager<
$$MessagesTableReferences._mediaIdTable(db).mediaId,
) as T;
}
if (quotesMessageId) {
state = state.withJoin(
currentTable: table,
currentColumn: table.quotesMessageId,
referencedTable:
$$MessagesTableReferences._quotesMessageIdTable(db),
referencedColumn: $$MessagesTableReferences
._quotesMessageIdTable(db)
.messageId,
) as T;
}
return state;
},
@ -9086,7 +9006,6 @@ typedef $$MessagesTableProcessedTableManager = ProcessedTableManager<
{bool groupId,
bool senderId,
bool mediaId,
bool quotesMessageId,
bool messageHistoriesRefs,
bool reactionsRefs,
bool receiptsRefs,

View file

@ -341,5 +341,6 @@
"reportUserReason": "Meldegrund",
"reportUser": "Benutzer melden",
"newDeviceRegistered": "Du hast dich auf einem anderen Gerät angemeldet. Daher wurdest du hier abgemeldet.",
"tabToRemoveEmoji": "Tippen um zu entfernen"
"tabToRemoveEmoji": "Tippen um zu entfernen",
"quotedMessageWasDeleted": "Die zitierte Nachricht wurde gelöscht."
}

View file

@ -497,5 +497,6 @@
"reportUserReason": "Reporting reason",
"reportUser": "Report user",
"newDeviceRegistered": "You have logged in on another device. You have therefore been logged out here.",
"tabToRemoveEmoji": "Tab to remove"
"tabToRemoveEmoji": "Tab to remove",
"quotedMessageWasDeleted": "The quoted message has been deleted."
}

View file

@ -2089,6 +2089,12 @@ abstract class AppLocalizations {
/// In en, this message translates to:
/// **'Tab to remove'**
String get tabToRemoveEmoji;
/// No description provided for @quotedMessageWasDeleted.
///
/// In en, this message translates to:
/// **'The quoted message has been deleted.'**
String get quotedMessageWasDeleted;
}
class _AppLocalizationsDelegate

View file

@ -1109,4 +1109,8 @@ class AppLocalizationsDe extends AppLocalizations {
@override
String get tabToRemoveEmoji => 'Tippen um zu entfernen';
@override
String get quotedMessageWasDeleted =>
'Die zitierte Nachricht wurde gelöscht.';
}

View file

@ -1103,4 +1103,7 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get tabToRemoveEmoji => 'Tab to remove';
@override
String get quotedMessageWasDeleted => 'The quoted message has been deleted.';
}

View file

@ -214,6 +214,8 @@ Future<(Uint8List, Uint8List?)?> sendCipherText(
bool onlyReturnEncryptedData = false,
String? messageId,
}) async {
encryptedContent.senderProfileCounter = Int64(gUser.avatarCounter);
final response = pb.Message()
..type = pb.Message_Type.CIPHERTEXT
..encryptedContent = encryptedContent.writeToBuffer();

View file

@ -106,19 +106,21 @@ Future<int?> checkForProfileUpdate(
) async {
int? senderProfileCounter;
if (content.hasSenderProfileCounter() && !content.hasContactUpdate()) {
if (content.hasSenderProfileCounter()) {
senderProfileCounter = content.senderProfileCounter.toInt();
final contact = await twonlyDB.contactsDao
.getContactByUserId(fromUserId)
.getSingleOrNull();
if (contact != null) {
if (contact.senderProfileCounter < senderProfileCounter) {
await sendCipherText(
fromUserId,
EncryptedContent()
..contactUpdate = (EncryptedContent_ContactUpdate()
..type = EncryptedContent_ContactUpdate_Type.REQUEST),
);
if (!content.hasContactUpdate()) {
final contact = await twonlyDB.contactsDao
.getContactByUserId(fromUserId)
.getSingleOrNull();
if (contact != null) {
if (contact.senderProfileCounter < senderProfileCounter) {
await sendCipherText(
fromUserId,
EncryptedContent()
..contactUpdate = (EncryptedContent_ContactUpdate()
..type = EncryptedContent_ContactUpdate_Type.REQUEST),
);
}
}
}
}

View file

@ -277,7 +277,7 @@ class _ChatMessagesViewState extends State<ChatMessagesView> {
return Transform.translate(
offset: Offset(
(focusedScrollItem == i)
? (chatMessage.quotesMessageId == null)
? (chatMessage.senderId == null)
? -8
: 8
: 0,

View file

@ -57,7 +57,7 @@ class ChatTextEntry extends StatelessWidget {
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
if (measureTextWidth(text) > 270)
if (measureTextWidth(text) > 270 || message.quotesMessageId != null)
Expanded(
child: BetterText(text: text),
)

View file

@ -76,12 +76,14 @@ class _MessageSendStateIconState extends State<MessageSendStateIcon> {
@override
Widget build(BuildContext context) {
final icons = <Widget>[];
var icons = <Widget>[];
var text = '';
Widget? textWidget;
textWidget = null;
final kindsAlreadyShown = HashSet<MessageType>();
var hasLoader = false;
for (final message in widget.messages) {
if (icons.length == 2) break;
if (kindsAlreadyShown.contains(message.type)) continue;
@ -130,6 +132,7 @@ class _MessageSendStateIconState extends State<MessageSendStateIcon> {
if (mediaFile.downloadState == DownloadState.downloading) {
text = context.lang.messageSendState_Loading;
icon = getLoaderIcon(color);
hasLoader = true;
}
}
case MessageSendState.send:
@ -139,9 +142,11 @@ class _MessageSendStateIconState extends State<MessageSendStateIcon> {
case MessageSendState.sending:
icon = getLoaderIcon(color);
text = context.lang.messageSendState_Sending;
hasLoader = true;
case MessageSendState.receiving:
icon = getLoaderIcon(color);
text = context.lang.messageSendState_Received;
hasLoader = true;
}
if (message.mediaStored) {
@ -165,6 +170,11 @@ class _MessageSendStateIconState extends State<MessageSendStateIcon> {
}
}
if (hasLoader) {
icons = [icon];
break;
}
if (message.type == MessageType.media) {
icons.insert(0, icon);
} else {

View file

@ -150,53 +150,58 @@ class _ResponsePreviewState extends State<ResponsePreview> {
@override
Widget build(BuildContext context) {
if (message == null) return Container();
String? subtitle;
var color = const Color.fromARGB(233, 68, 137, 255);
var username = '';
if (message!.type == MessageType.text) {
if (message!.content != null) {
subtitle = truncateString(message!.content!);
if (message != null) {
if (message!.type == MessageType.text) {
if (message!.content != null) {
subtitle = truncateString(message!.content!);
}
}
if (message!.type == MessageType.media && mediaService != null) {
subtitle = mediaService!.mediaFile.type == MediaType.video
? context.lang.video
: context.lang.image;
}
}
if (message!.type == MessageType.media && mediaService != null) {
subtitle = mediaService!.mediaFile.type == MediaType.video
? context.lang.video
: context.lang.image;
}
var username = context.lang.you;
if (message!.senderId != null) {
username = message!.senderId.toString();
}
username = context.lang.you;
if (message!.senderId != null) {
username = message!.senderId.toString();
}
final color = getMessageColor(message!);
color = getMessageColor(message!);
if (!message!.mediaStored) {
return Container(
padding: widget.showBorder
? const EdgeInsets.only(left: 10, right: 10)
: const EdgeInsets.symmetric(horizontal: 5),
decoration: (widget.showBorder)
? BoxDecoration(
border: Border(
left: BorderSide(
color: color,
width: 2,
if (!message!.mediaStored) {
return Container(
padding: widget.showBorder
? const EdgeInsets.only(left: 10, right: 10)
: const EdgeInsets.symmetric(horizontal: 5),
decoration: (widget.showBorder)
? BoxDecoration(
border: Border(
left: BorderSide(
color: color,
width: 2,
),
),
),
)
: null,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
username,
style: const TextStyle(fontWeight: FontWeight.bold),
),
if (subtitle != null) Text(subtitle),
],
),
);
)
: null,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
username,
style: const TextStyle(fontWeight: FontWeight.bold),
),
if (subtitle != null) Text(subtitle),
],
),
);
}
} else {
username = context.lang.quotedMessageWasDeleted;
}
return Container(
@ -227,7 +232,11 @@ class _ResponsePreviewState extends State<ResponsePreview> {
if (mediaService != null)
SizedBox(
height: widget.showBorder ? 100 : 210,
child: Image.file(mediaService!.thumbnailPath),
child: Image.file(
mediaService!.mediaFile.type == MediaType.video
? mediaService!.thumbnailPath
: mediaService!.storedPath,
),
),
],
),

View file

@ -469,27 +469,6 @@ class _MediaViewerViewState extends State<MediaViewerView> {
child: Image.file(
currentMedia!.tempPath,
fit: BoxFit.contain,
frameBuilder: (
context,
child,
frame,
wasSynchronouslyLoaded,
) {
if (wasSynchronouslyLoaded) return child;
return AnimatedSwitcher(
duration: const Duration(milliseconds: 200),
child: frame != null
? child
: Container(
height: 60,
color: Colors.transparent,
width: 60,
child: const CircularProgressIndicator(
strokeWidth: 2,
),
),
);
},
),
),
],
@ -534,13 +513,16 @@ class _MediaViewerViewState extends State<MediaViewerView> {
],
),
),
if (currentMedia?.mediaFile.downloadState != DownloadState.ready)
if (currentMedia != null &&
currentMedia?.mediaFile.downloadState != DownloadState.ready)
const Positioned.fill(
child: Center(
child: SizedBox(
height: 60,
width: 60,
child: CircularProgressIndicator(strokeWidth: 6),
child: CircularProgressIndicator(
strokeWidth: 6,
),
),
),
),