diff --git a/assets/images/default_avatar.svg b/assets/images/default_avatar.svg
new file mode 100644
index 0000000..26d14d5
--- /dev/null
+++ b/assets/images/default_avatar.svg
@@ -0,0 +1,27 @@
+
+
\ No newline at end of file
diff --git a/lib/src/database/daos/contacts_dao.dart b/lib/src/database/daos/contacts_dao.dart
index f1a4123..f889628 100644
--- a/lib/src/database/daos/contacts_dao.dart
+++ b/lib/src/database/daos/contacts_dao.dart
@@ -115,15 +115,6 @@ class ContactsDao extends DatabaseAccessor
}
}
- Future newMessageExchange(int userId) {
- return updateContact(
- userId,
- ContactsCompanion(
- lastMessageExchange: Value(DateTime.now()),
- ),
- );
- }
-
Stream> watchNotAcceptedContacts() {
return (select(contacts)
..where((t) =>
diff --git a/lib/src/database/daos/messages_dao.dart b/lib/src/database/daos/messages_dao.dart
index 1c9e333..95891f4 100644
--- a/lib/src/database/daos/messages_dao.dart
+++ b/lib/src/database/daos/messages_dao.dart
@@ -193,7 +193,9 @@ class MessagesDao extends DatabaseAccessor
Future insertMessage(MessagesCompanion message) async {
try {
await (update(contacts)
- ..where((c) => c.userId.equals(message.contactId.value)))
+ ..where(
+ (c) => c.userId.equals(message.contactId.value),
+ ))
.write(ContactsCompanion(lastMessageExchange: Value(DateTime.now())));
return await into(messages).insert(message);
diff --git a/lib/src/model/json/message.dart b/lib/src/model/json/message.dart
index deeea6c..be48336 100644
--- a/lib/src/model/json/message.dart
+++ b/lib/src/model/json/message.dart
@@ -15,7 +15,7 @@ Color getMessageColorFromType(MessageContent content, BuildContext context) {
color = context.color.primary;
} else {
if (content.isVideo) {
- color = const Color.fromARGB(255, 240, 243, 33);
+ color = const Color.fromARGB(255, 243, 33, 208);
} else {
color = Colors.redAccent;
}
diff --git a/lib/src/views/chats/chat_list.view.dart b/lib/src/views/chats/chat_list.view.dart
index 0b9b070..4dab012 100644
--- a/lib/src/views/chats/chat_list.view.dart
+++ b/lib/src/views/chats/chat_list.view.dart
@@ -10,6 +10,7 @@ import 'package:twonly/globals.dart';
import 'package:twonly/src/database/daos/contacts_dao.dart';
import 'package:twonly/src/database/tables/messages_table.dart';
import 'package:twonly/src/database/twonly_database.dart';
+import 'package:twonly/src/model/json/userdata.dart';
import 'package:twonly/src/providers/connection.provider.dart';
import 'package:twonly/src/services/api/media_download.dart';
import 'package:twonly/src/utils/misc.dart';
@@ -21,14 +22,15 @@ import 'package:twonly/src/views/chats/chat_list_components/connection_info.comp
import 'package:twonly/src/views/chats/chat_list_components/feedback_btn.dart';
import 'package:twonly/src/views/chats/chat_list_components/last_message_time.dart';
import 'package:twonly/src/views/chats/chat_messages.view.dart';
+import 'package:twonly/src/views/chats/chat_messages_components/message_send_state_icon.dart';
import 'package:twonly/src/views/chats/media_viewer.view.dart';
import 'package:twonly/src/views/chats/start_new_chat.view.dart';
import 'package:twonly/src/views/components/flame.dart';
import 'package:twonly/src/views/components/initialsavatar.dart';
-import 'package:twonly/src/views/components/message_send_state_icon.dart';
import 'package:twonly/src/views/components/notification_badge.dart';
import 'package:twonly/src/views/components/user_context_menu.dart';
import 'package:twonly/src/views/settings/help/changelog.view.dart';
+import 'package:twonly/src/views/settings/profile/profile.view.dart';
import 'package:twonly/src/views/settings/settings_main.view.dart';
import 'package:twonly/src/views/settings/subscription/subscription.view.dart';
import 'package:twonly/src/views/tutorial/tutorials.dart';
@@ -43,6 +45,7 @@ class _ChatListViewState extends State {
late StreamSubscription> _contactsSub;
List _contacts = [];
List _pinnedContacts = [];
+ UserData? _user;
GlobalKey firstUserListItemKey = GlobalKey();
GlobalKey searchForOtherUsers = GlobalKey();
@@ -76,6 +79,7 @@ class _ChatListViewState extends State {
final user = await getUser();
if (user == null) return;
+ _user = user;
final changeLog = await rootBundle.loadString('CHANGELOG.md');
final changeLogHash =
(await compute(Sha256().hash, changeLog.codeUnits)).bytes;
@@ -112,6 +116,23 @@ class _ChatListViewState extends State {
return Scaffold(
appBar: AppBar(
title: Row(children: [
+ GestureDetector(
+ onTap: () async {
+ await Navigator.push(context,
+ MaterialPageRoute(builder: (context) {
+ return const ProfileView();
+ }));
+ _user = await getUser();
+ if (!mounted) return;
+ setState(() {});
+ },
+ child: ContactAvatar(
+ userData: _user,
+ fontSize: 14,
+ color: context.color.onSurface.withAlpha(20),
+ ),
+ ),
+ const SizedBox(width: 10),
const Text('twonly '),
if (planId != 'Free')
GestureDetector(
diff --git a/lib/src/views/chats/chat_messages_components/in_chat_media_viewer.dart b/lib/src/views/chats/chat_messages_components/in_chat_media_viewer.dart
index 77fed7d..1a130c2 100644
--- a/lib/src/views/chats/chat_messages_components/in_chat_media_viewer.dart
+++ b/lib/src/views/chats/chat_messages_components/in_chat_media_viewer.dart
@@ -4,7 +4,7 @@ import 'package:flutter/material.dart';
import 'package:twonly/globals.dart';
import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/model/memory_item.model.dart';
-import 'package:twonly/src/views/components/message_send_state_icon.dart';
+import 'package:twonly/src/views/chats/chat_messages_components/message_send_state_icon.dart';
import 'package:twonly/src/views/memories/memories_item_thumbnail.dart';
import 'package:twonly/src/views/memories/memories_photo_slider.view.dart';
diff --git a/lib/src/views/components/message_send_state_icon.dart b/lib/src/views/chats/chat_messages_components/message_send_state_icon.dart
similarity index 100%
rename from lib/src/views/components/message_send_state_icon.dart
rename to lib/src/views/chats/chat_messages_components/message_send_state_icon.dart
diff --git a/lib/src/views/components/initialsavatar.dart b/lib/src/views/components/initialsavatar.dart
index b5fe029..59068db 100644
--- a/lib/src/views/components/initialsavatar.dart
+++ b/lib/src/views/components/initialsavatar.dart
@@ -1,6 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
-import 'package:twonly/src/database/daos/contacts_dao.dart';
import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/model/json/userdata.dart';
import 'package:twonly/src/utils/log.dart';
@@ -11,21 +10,20 @@ class ContactAvatar extends StatelessWidget {
this.contact,
this.userData,
this.fontSize = 20,
+ this.color,
});
final Contact? contact;
final UserData? userData;
final double? fontSize;
+ final Color? color;
@override
Widget build(BuildContext context) {
- var displayName = '';
String? avatarSvg;
if (contact != null) {
- displayName = getContactDisplayName(contact!).replaceAll('\u0336', '');
avatarSvg = contact!.avatarSvg;
} else if (userData != null) {
- displayName = userData!.displayName;
avatarSvg = userData!.avatarSvg;
} else {
return Container();
@@ -33,148 +31,34 @@ class ContactAvatar extends StatelessWidget {
final proSize = (fontSize == null) ? 40 : (fontSize! * 2);
- if (avatarSvg != null) {
- return Container(
- constraints: BoxConstraints(
- minHeight: 2 * (fontSize ?? 20),
- minWidth: 2 * (fontSize ?? 20),
- maxWidth: 2 * (fontSize ?? 20),
- maxHeight: 2 * (fontSize ?? 20),
- ),
- child: Center(
- child: ClipRRect(
- borderRadius: BorderRadius.circular(12),
- child: SizedBox(
- height: proSize as double,
- width: proSize,
- child: Center(
- child: SvgPicture.string(
- avatarSvg,
- errorBuilder: (context, error, stackTrace) {
- Log.error('$error');
- return Container();
- },
- ),
- ),
+ return Container(
+ constraints: BoxConstraints(
+ minHeight: 2 * (fontSize ?? 20),
+ minWidth: 2 * (fontSize ?? 20),
+ maxWidth: 2 * (fontSize ?? 20),
+ maxHeight: 2 * (fontSize ?? 20),
+ ),
+ child: Center(
+ child: ClipRRect(
+ borderRadius: BorderRadius.circular(12),
+ child: Container(
+ height: proSize as double,
+ width: proSize,
+ color: color,
+ child: Center(
+ child: avatarSvg == null
+ ? SvgPicture.asset('assets/images/default_avatar.svg')
+ : SvgPicture.string(
+ avatarSvg,
+ errorBuilder: (context, error, stackTrace) {
+ Log.error('$error');
+ return Container();
+ },
+ ),
),
),
),
- );
- }
-
- // Extract initials from the displayName
- final nameParts = displayName.split(' ');
- var initials = nameParts.map((part) => part[0]).join().toUpperCase();
-
- if (initials.length > 2) {
- initials = initials[0] + initials[1];
- } else if (initials.length == 1) {
- initials = displayName[0] + displayName[1];
- }
-
- initials = initials.toUpperCase();
-
- // Generate a color based on the initials (you can customize this logic)
- final avatarColor = _getColorFromUsername(
- displayName, Theme.of(context).brightness == Brightness.dark);
-
- final Widget child = Text(
- initials,
- style: TextStyle(
- color: _getTextColor(avatarColor),
- fontWeight: FontWeight.normal,
- fontSize: fontSize,
),
);
-
- final isPro = initials[0] == 'T';
-
- if (isPro) {
- return Container(
- constraints: BoxConstraints(
- minHeight: 2 * (fontSize ?? 20),
- minWidth: 2 * (fontSize ?? 20),
- maxWidth: 2 * (fontSize ?? 20),
- maxHeight: 2 * (fontSize ?? 20),
- ),
- child: Center(
- child: ClipRRect(
- borderRadius: BorderRadius.circular(12),
- child: Container(
- height: proSize as double,
- width: proSize,
- //padding: EdgeInsets.symmetric(vertical: 5, horizontal: 10),
- color: avatarColor,
- child: Center(child: child),
- ),
- ),
- ),
- );
- } else {
- return CircleAvatar(
- backgroundColor: avatarColor,
- radius: fontSize,
- child: child,
- );
- }
- }
-
- Color _getTextColor(Color color) {
- const value = 100.0;
- // Ensure the value does not exceed the RGB limits
- final newRed = ((color.r * 255) - value).clamp(0, 255).round();
- final newGreen = (color.g * 255 - value).clamp(0, 255).round();
- final newBlue = (color.b * 255 - value).clamp(0, 255).round();
-
- return Color.fromARGB((color.a * 255).round(), newRed, newGreen, newBlue);
- }
-
- Color _getColorFromUsername(String displayName, bool isDarkMode) {
- // Define color lists for light and dark themes
- final lightColors = [
- Colors.red,
- Colors.green,
- Colors.blue,
- Colors.orange,
- Colors.purple,
- Colors.teal,
- Colors.amber,
- Colors.indigo,
- Colors.cyan,
- Colors.lime,
- Colors.pink,
- Colors.brown,
- Colors.grey,
- ];
-
- final darkColors = [
- const Color.fromARGB(255, 246, 227, 254), // Light Lavender
- const Color.fromARGB(255, 246, 216, 215), // Light Pink
- const Color.fromARGB(255, 226, 236, 235), // Light Teal
- const Color.fromARGB(255, 255, 224, 178), // Light Yellow
- const Color.fromARGB(255, 255, 182, 193), // Light Pink (Hot Pink)
- const Color.fromARGB(255, 173, 216, 230), // Light Blue
- const Color.fromARGB(255, 221, 160, 221), // Plum
- const Color.fromARGB(255, 255, 228, 196), // Bisque
- const Color.fromARGB(255, 240, 230, 140), // Khaki
- const Color.fromARGB(255, 255, 192, 203), // Pink
- const Color.fromARGB(255, 255, 218, 185), // Peach Puff
- const Color.fromARGB(255, 255, 160, 122), // Light Salmon
- const Color.fromARGB(255, 135, 206, 250), // Light Sky Blue
- const Color.fromARGB(255, 255, 228, 225), // Misty Rose
- const Color.fromARGB(255, 240, 248, 255), // Alice Blue
- const Color.fromARGB(255, 255, 250, 205), // Lemon Chiffon
- const Color.fromARGB(255, 255, 218, 185), // Peach Puff
- ];
-
- // Simple logic to generate a hash from initials
- final hash =
- displayName.codeUnits.fold(0, (prev, element) => prev + element);
-
- // Select the appropriate color list based on the current theme brightness
- final colors = isDarkMode ? darkColors : lightColors;
-
- // Use the hash to select a color from the list
- return colors[hash % colors.length];
}
}