feat: brand retheme to m8chat.au blues, fix black logo, v1.6.0+8

- m8logo.svg: inline fills (flutter_svg ignores <style> blocks; logo rendered black)
- theme.dart v2.0.0: purple -> site palette (#1265ED / #3B8BFF / navy darks)
- app_config.dart: appVersion 1.3.0 -> 1.6.0 (profile screen showed stale version)
- manifest.json: theme/background colours to match
- Remove em-dashes from user-visible UI strings (global style rule)
- chat_screen.dart: fix use_build_context_synchronously in _leaveRoom
- Deployed to app2.m8chat.au after full functionality audit (all green)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-03 05:16:11 +10:00
parent 3865391829
commit 3568b17f0f
14 changed files with 61 additions and 62 deletions

View File

@@ -1,24 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- Version: 1.1.0 | Updated: 2026-07-03 -->
<!-- Fills inlined as attributes: flutter_svg does not parse <style> blocks,
which made the whole logo render black in the app. -->
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 429 429"> <svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 429 429">
<!-- Generator: Adobe Illustrator 29.3.0, SVG Export Plug-In . SVG Version: 2.1.0 Build 100) --> <path fill="#1466eb" d="M70.64,352.36c-3.51-2.16,1.51-50.04-.33-57.17-.72-2.41-16.56-9.68-20.12-11.88-54.87-34.03-34.77-110.33,1.79-150.82,55.72-61.71,140.84-65.99,217.72-49.69,48.91,10.37,149.12,46.91,145.84,109.25-2.02,38.32-56.82,85.23-88.37,102.62-66.49,36.67-140.36,36.21-212.2,16.21-2.19.3-16.47,21.54-19.5,25.09-3.72,4.36-18.49,20.3-24.83,16.39ZM314.5,196.52c15.07-5.73,19.34-26.28,12.4-39.91-14.75-28.96-81.5-25.08-84.39,11.41-.63,8.02,3.12,19.38,8.95,25.02,2.58,2.49,7.86,3.06,4.98,5.91-4.11,4.07-8.05,4.76-11.77,11.23-23.76,41.34,43.05,66.64,75.74,40.74,14.99-11.88,16.47-35.84,1.56-48.38-2.18-1.83-5.36-2.8-6.85-3.96-.97-.76-.79-.82-.62-2.05ZM118.5,139.5h-36v120h23v-88l31.16,86.34.79,1.21,23.9.32,31.14-86.86v85.5c0,.11,1.39,1.5,1.5,1.5h21.5v-120h-34.5c-11.09,24.47-16.9,52.95-27.47,77.53-1.08,2.52-3.04,6.59-5.02,8.47l-30.01-86Z"/>
<defs>
<style>
.st0 {
fill: #f8fbfe;
}
.st1 {
fill: #1466eb;
}
</style>
</defs>
<path class="st1" d="M70.64,352.36c-3.51-2.16,1.51-50.04-.33-57.17-.72-2.41-16.56-9.68-20.12-11.88-54.87-34.03-34.77-110.33,1.79-150.82,55.72-61.71,140.84-65.99,217.72-49.69,48.91,10.37,149.12,46.91,145.84,109.25-2.02,38.32-56.82,85.23-88.37,102.62-66.49,36.67-140.36,36.21-212.2,16.21-2.19.3-16.47,21.54-19.5,25.09-3.72,4.36-18.49,20.3-24.83,16.39ZM314.5,196.52c15.07-5.73,19.34-26.28,12.4-39.91-14.75-28.96-81.5-25.08-84.39,11.41-.63,8.02,3.12,19.38,8.95,25.02,2.58,2.49,7.86,3.06,4.98,5.91-4.11,4.07-8.05,4.76-11.77,11.23-23.76,41.34,43.05,66.64,75.74,40.74,14.99-11.88,16.47-35.84,1.56-48.38-2.18-1.83-5.36-2.8-6.85-3.96-.97-.76-.79-.82-.62-2.05ZM118.5,139.5h-36v120h23v-88l31.16,86.34.79,1.21,23.9.32,31.14-86.86v85.5c0,.11,1.39,1.5,1.5,1.5h21.5v-120h-34.5c-11.09,24.47-16.9,52.95-27.47,77.53-1.08,2.52-3.04,6.59-5.02,8.47l-30.01-86Z"/>
<g> <g>
<path class="st0" d="M118.5,139.5l30.01,86c1.98-1.88,3.94-5.94,5.02-8.47,10.56-24.59,16.37-53.06,27.47-77.53h34.5v120h-21.5c-.11,0-1.5-1.39-1.5-1.5v-85.5l-31.14,86.86-23.9-.32-.79-1.21-31.16-86.34v88h-23v-120h36Z"/> <path fill="#f8fbfe" d="M118.5,139.5l30.01,86c1.98-1.88,3.94-5.94,5.02-8.47,10.56-24.59,16.37-53.06,27.47-77.53h34.5v120h-21.5c-.11,0-1.5-1.39-1.5-1.5v-85.5l-31.14,86.86-23.9-.32-.79-1.21-31.16-86.34v88h-23v-120h36Z"/>
<g> <g>
<path class="st0" d="M314.5,196.52c-.17,1.23-.35,1.29.62,2.05,1.48,1.17,4.67,2.13,6.85,3.96,14.91,12.55,13.43,36.51-1.56,48.38-32.68,25.9-99.5.6-75.74-40.74,3.72-6.47,7.66-7.16,11.77-11.23,2.88-2.86-2.4-3.42-4.98-5.91-5.84-5.64-9.59-17-8.95-25.02,2.88-36.49,69.63-40.37,84.39-11.41,6.95,13.63,2.68,34.19-12.4,39.91ZM281.26,156.76c-20.8,2.86-20.27,28.16-1.17,30.66,10.68,1.4,26.97-.71,27.32-14.51.36-14.27-14.74-17.71-26.15-16.15ZM279.26,207.76c-8.99,1.29-15.54,7.92-15.55,17.24-.02,22.72,41.87,22.15,44.72,3.94,3.04-19.37-13.32-23.45-29.17-21.18Z"/> <path fill="#f8fbfe" d="M314.5,196.52c-.17,1.23-.35,1.29.62,2.05,1.48,1.17,4.67,2.13,6.85,3.96,14.91,12.55,13.43,36.51-1.56,48.38-32.68,25.9-99.5.6-75.74-40.74,3.72-6.47,7.66-7.16,11.77-11.23,2.88-2.86-2.4-3.42-4.98-5.91-5.84-5.64-9.59-17-8.95-25.02,2.88-36.49,69.63-40.37,84.39-11.41,6.95,13.63,2.68,34.19-12.4,39.91ZM281.26,156.76c-20.8,2.86-20.27,28.16-1.17,30.66,10.68,1.4,26.97-.71,27.32-14.51.36-14.27-14.74-17.71-26.15-16.15ZM279.26,207.76c-8.99,1.29-15.54,7.92-15.55,17.24-.02,22.72,41.87,22.15,44.72,3.94,3.04-19.37-13.32-23.45-29.17-21.18Z"/>
<path class="st1" d="M279.26,207.76c15.85-2.28,32.21,1.81,29.17,21.18-2.86,18.21-44.75,18.78-44.72-3.94,0-9.32,6.57-15.95,15.55-17.24Z"/> <path fill="#1466eb" d="M279.26,207.76c15.85-2.28,32.21,1.81,29.17,21.18-2.86,18.21-44.75,18.78-44.72-3.94,0-9.32,6.57-15.95,15.55-17.24Z"/>
<path class="st1" d="M281.26,156.76c11.41-1.57,26.51,1.88,26.15,16.15-.35,13.8-16.64,15.91-27.32,14.51-19.1-2.5-19.63-27.8,1.17-30.66Z"/> <path fill="#1466eb" d="M281.26,156.76c11.41-1.57,26.51,1.88,26.15,16.15-.35,13.8-16.64,15.91-27.32,14.51-19.1-2.5-19.63-27.8,1.17-30.66Z"/>
</g> </g>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -68,4 +68,10 @@
- **Decision:** Changed _clearCallMemberEvent to send {} instead of {'memberships': []} - **Decision:** Changed _clearCallMemberEvent to send {} instead of {'memberships': []}
- **Rationale:** Element X sends {} when ending calls (verified from DB). Our {'memberships': []} wasn't being recognised. - **Rationale:** Element X sends {} when ending calls (verified from DB). Our {'memberships': []} wasn't being recognised.
- **Files affected:** livekit_service.dart - **Files affected:** livekit_service.dart
- **Status:** Deployed. NOT YET TESTED. - **Status:** Deployed. NOT YET TESTED.
### 2026-07-03 05:20 — Functionality audit + brand retheme (v1.6.0+8)
- **Decision:** Retheme app from purple (#5C35C9) to m8chat.au brand blues taken from the site's Elementor kit: brandBlue #1265ED, accentBlue #3B8BFF, navy darks derived from Ancop Blue #010B46.
- **Rationale:** Full audit (2026-07-03) found look and feel did not match m8chat.au. Logo rendered black because flutter_svg does not parse SVG <style> blocks; fills now inlined as attributes in m8logo.svg. Profile screen showed stale hardcoded appVersion 1.3.0. UI strings contained em-dashes (global style rule violation).
- **Audit results:** Backend all healthy (client API, livekit JWT, Jitsi external_api.js, push gateway, TURN 3478/5349). Full E2E pass in headless Chromium: login, rooms, spaces, profile, conference, help tabs, room open, message send verified on Synapse. Disposable audit users created and erased via admin API.
- **Files affected:** assets/images/m8logo.svg, lib/app/theme.dart (2.0.0), lib/core/config/app_config.dart (2.1.0), web/manifest.json, pubspec.yaml (1.6.0+8), em-dash fixes in 8 presentation/util files, chat_screen.dart lint fix (_leaveRoom context param).
- **Status:** Done — built, deployed to app2.m8chat.au (backup public_html.bak.20260703_pre160.tar.gz), visually verified light+dark.

View File

@@ -1,25 +1,27 @@
// Version: 1.0.0 | Created: 2026-04-01 // Version: 2.0.0 | Created: 2026-04-01 | Updated: 2026-07-03
// M8Chat brand theme — dark and light variants. // M8Chat brand theme — dark and light variants.
// Primary brand colour: #5C35C9 (deep purple). Accent: #7B5CF6. // Palette from the m8chat.au Elementor kit (kit post 8):
// Accent #1 "#1265ED", Blue Element "#3B8BFF", Ancop Blue "#010B46".
// v2.0.0 replaces the old purple scheme, which did not match the website.
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
/// M8Chat brand colours. /// M8Chat brand colours.
abstract final class M8Colours { abstract final class M8Colours {
static const Color brandPurple = Color(0xFF5C35C9); static const Color brandBlue = Color(0xFF1265ED);
static const Color accentPurple = Color(0xFF7B5CF6); static const Color accentBlue = Color(0xFF3B8BFF);
static const Color darkBackground = Color(0xFF0F0F1A); static const Color darkBackground = Color(0xFF0A0F2E);
static const Color darkSurface = Color(0xFF1A1A2E); static const Color darkSurface = Color(0xFF131A42);
static const Color darkSurfaceVariant = Color(0xFF22223A); static const Color darkSurfaceVariant = Color(0xFF1C2452);
static const Color onDarkSurface = Color(0xFFE8E8F0); static const Color onDarkSurface = Color(0xFFE8ECF5);
static const Color subtleText = Color(0xFF9898B0); static const Color subtleText = Color(0xFF96A0C2);
static const Color errorRed = Color(0xFFCF6679); static const Color errorRed = Color(0xFFCF6679);
static const Color unreadGreen = Color(0xFF4CAF50); static const Color unreadGreen = Color(0xFF4CAF50);
} }
/// Dark theme — default for M8Chat. /// Dark theme — default for M8Chat.
ThemeData buildDarkTheme() { ThemeData buildDarkTheme() {
const seed = M8Colours.brandPurple; const seed = M8Colours.brandBlue;
final scheme = final scheme =
ColorScheme.fromSeed( ColorScheme.fromSeed(
@@ -28,7 +30,7 @@ ThemeData buildDarkTheme() {
).copyWith( ).copyWith(
surface: M8Colours.darkBackground, surface: M8Colours.darkBackground,
surfaceContainerHighest: M8Colours.darkSurface, surfaceContainerHighest: M8Colours.darkSurface,
primary: M8Colours.accentPurple, primary: M8Colours.accentBlue,
onSurface: M8Colours.onDarkSurface, onSurface: M8Colours.onDarkSurface,
error: M8Colours.errorRed, error: M8Colours.errorRed,
); );
@@ -45,7 +47,7 @@ ThemeData buildDarkTheme() {
), ),
navigationBarTheme: NavigationBarThemeData( navigationBarTheme: NavigationBarThemeData(
backgroundColor: M8Colours.darkSurface, backgroundColor: M8Colours.darkSurface,
indicatorColor: M8Colours.accentPurple.withAlpha(51), indicatorColor: M8Colours.accentBlue.withAlpha(51),
labelTextStyle: WidgetStateProperty.all( labelTextStyle: WidgetStateProperty.all(
const TextStyle(fontSize: 12, color: M8Colours.onDarkSurface), const TextStyle(fontSize: 12, color: M8Colours.onDarkSurface),
), ),
@@ -59,14 +61,14 @@ ThemeData buildDarkTheme() {
), ),
focusedBorder: OutlineInputBorder( focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
borderSide: const BorderSide(color: M8Colours.accentPurple, width: 2), borderSide: const BorderSide(color: M8Colours.accentBlue, width: 2),
), ),
labelStyle: const TextStyle(color: M8Colours.subtleText), labelStyle: const TextStyle(color: M8Colours.subtleText),
hintStyle: const TextStyle(color: M8Colours.subtleText), hintStyle: const TextStyle(color: M8Colours.subtleText),
), ),
elevatedButtonTheme: ElevatedButtonThemeData( elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: M8Colours.accentPurple, backgroundColor: M8Colours.accentBlue,
foregroundColor: Colors.white, foregroundColor: Colors.white,
minimumSize: const Size.fromHeight(52), minimumSize: const Size.fromHeight(52),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
@@ -97,7 +99,7 @@ ThemeData buildDarkTheme() {
/// Light theme — follows system preference if user selects it. /// Light theme — follows system preference if user selects it.
ThemeData buildLightTheme() { ThemeData buildLightTheme() {
const seed = M8Colours.brandPurple; const seed = M8Colours.brandBlue;
final scheme = ColorScheme.fromSeed( final scheme = ColorScheme.fromSeed(
seedColor: seed, seedColor: seed,

View File

@@ -1,4 +1,4 @@
// Version: 2.0.0 | Created: 2026-04-01 | Updated: 2026-04-11 // Version: 2.1.0 | Created: 2026-04-01 | Updated: 2026-07-03
// App-wide constants. Change matrixBaseUrl for different environments. // App-wide constants. Change matrixBaseUrl for different environments.
abstract final class AppConfig { abstract final class AppConfig {
@@ -11,7 +11,7 @@ abstract final class AppConfig {
'turns:matrix.m8chat.au:5349', 'turns:matrix.m8chat.au:5349',
]; ];
static const String appName = 'M8Chat'; static const String appName = 'M8Chat';
static const String appVersion = '1.3.0'; static const String appVersion = '1.6.0';
// Jitsi conferencing // Jitsi conferencing
static const String jitsiDomain = 'conf.m8chat.au'; static const String jitsiDomain = 'conf.m8chat.au';

View File

@@ -1,4 +1,4 @@
// Version: 1.3.0 | Created: 2026-04-01 | Updated: 2026-04-27 // Version: 1.3.1 | Created: 2026-04-01 | Updated: 2026-07-03
// Full chat screen — timeline + input + typing indicators + read receipts // Full chat screen — timeline + input + typing indicators + read receipts
// + long-press context menu (reply, react, copy, delete) + room options sheet. // + long-press context menu (reply, react, copy, delete) + room options sheet.
@@ -265,7 +265,7 @@ class _RoomOptionsSheet extends ConsumerStatefulWidget {
class _RoomOptionsSheetState extends ConsumerState<_RoomOptionsSheet> { class _RoomOptionsSheetState extends ConsumerState<_RoomOptionsSheet> {
bool _leaving = false; bool _leaving = false;
Future<void> _leaveRoom(BuildContext context) async { Future<void> _leaveRoom() async {
final confirmed = await showDialog<bool>( final confirmed = await showDialog<bool>(
context: context, context: context,
builder: (_) => AlertDialog( builder: (_) => AlertDialog(
@@ -421,7 +421,7 @@ class _RoomOptionsSheetState extends ConsumerState<_RoomOptionsSheet> {
style: TextStyle(color: theme.colorScheme.error), style: TextStyle(color: theme.colorScheme.error),
), ),
enabled: !_leaving, enabled: !_leaving,
onTap: () => _leaveRoom(context), onTap: _leaveRoom,
), ),
], ],
), ),

View File

@@ -1,4 +1,4 @@
// Version: 1.3.0 | Created: 2026-04-01 | Updated: 2026-04-27 // Version: 1.3.1 | Created: 2026-04-01 | Updated: 2026-07-03
// Message bubble widget. Handles text, images, files, redacted, replies. // Message bubble widget. Handles text, images, files, redacted, replies.
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
@@ -145,7 +145,7 @@ class _MessageContentBody extends StatelessWidget {
const SizedBox(width: 6), const SizedBox(width: 6),
Flexible( Flexible(
child: Text( child: Text(
'Encrypted — use Element to read', 'Encrypted. Use Element to read',
style: TextStyle( style: TextStyle(
color: textColour.withAlpha(153), color: textColour.withAlpha(153),
fontStyle: FontStyle.italic, fontStyle: FontStyle.italic,

View File

@@ -1,4 +1,4 @@
// Version: 1.1.0 | Created: 2026-04-11 | Updated: 2026-04-11 // Version: 1.1.1 | Created: 2026-04-11 | Updated: 2026-07-03
// Help tab with in-app guidance for common tasks and troubleshooting. // Help tab with in-app guidance for common tasks and troubleshooting.
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@@ -36,7 +36,7 @@ class HelpTab extends ConsumerWidget {
// --- Encrypted messages --- // --- Encrypted messages ---
_HelpCard( _HelpCard(
icon: Icons.lock_outline, icon: Icons.lock_outline,
title: 'I see "Encrypted — use Element to read"', title: 'I see "Encrypted. Use Element to read"',
children: [ children: [
const _HelpParagraph( const _HelpParagraph(
'This means your device does not have the keys needed to ' 'This means your device does not have the keys needed to '
@@ -98,7 +98,7 @@ class HelpTab extends ConsumerWidget {
'1. Set up security: go to Profile > Security & Privacy ' '1. Set up security: go to Profile > Security & Privacy '
'> Security setup. This creates your encryption keys and ' '> Security setup. This creates your encryption keys and '
'backs them up.\n' 'backs them up.\n'
'2. Save your recovery key — you will need it if you ever ' '2. Save your recovery key. You will need it if you ever '
'log in on a new device.\n' 'log in on a new device.\n'
'3. Start chatting. Tap the pencil icon at the top right ' '3. Start chatting. Tap the pencil icon at the top right '
'to search for users and start a conversation.', 'to search for users and start a conversation.',
@@ -156,7 +156,7 @@ class HelpTab extends ConsumerWidget {
_HelpSubheading('Who can read my messages?'), _HelpSubheading('Who can read my messages?'),
_HelpParagraph( _HelpParagraph(
'Only you and the people in the conversation. M8Chat uses ' 'Only you and the people in the conversation. M8Chat uses '
'end-to-end encryption — not even the server operator can ' 'end-to-end encryption. Not even the server operator can '
'read your messages.', 'read your messages.',
), ),
SizedBox(height: 8), SizedBox(height: 8),

View File

@@ -1,4 +1,4 @@
// Version: 1.0.0 | Created: 2026-04-05 // Version: 1.0.1 | Created: 2026-04-05 | Updated: 2026-07-03
// Welcome/landing screen — first thing unauthenticated users see. // Welcome/landing screen — first thing unauthenticated users see.
// Two paths: join a Jitsi conference (no login) or sign in for Matrix chat. // Two paths: join a Jitsi conference (no login) or sign in for Matrix chat.
@@ -67,7 +67,7 @@ class _WelcomeScreenState extends State<WelcomeScreen> {
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
Text( Text(
'Chat and conference all in one place', 'Chat and conference, all in one place',
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: theme.textTheme.bodyMedium?.copyWith( style: theme.textTheme.bodyMedium?.copyWith(
color: theme.colorScheme.onSurface.withAlpha(153), color: theme.colorScheme.onSurface.withAlpha(153),
@@ -84,7 +84,7 @@ class _WelcomeScreenState extends State<WelcomeScreen> {
isDark: isDark, isDark: isDark,
icon: Icons.videocam_outlined, icon: Icons.videocam_outlined,
title: 'Join a Conference', title: 'Join a Conference',
subtitle: 'Paste your meeting link to join instantly — no account needed.', subtitle: 'Paste your meeting link to join instantly. No account needed.',
child: Column( child: Column(
children: [ children: [
TextField( TextField(

View File

@@ -1,4 +1,4 @@
// Version: 1.0.0 | Created: 2026-04-11 // Version: 1.0.1 | Created: 2026-04-11 | Updated: 2026-07-03
// Dialog for entering a recovery key to restore encrypted message keys // Dialog for entering a recovery key to restore encrypted message keys
// from the server-side key backup (SSSS / Secure Secret Storage). // from the server-side key backup (SSSS / Secure Secret Storage).
@@ -147,7 +147,7 @@ class _KeyRestoreDialogState extends State<_KeyRestoreDialog> {
SizedBox(height: 16), SizedBox(height: 16),
Text( Text(
'Message keys have been restored. ' 'Message keys have been restored. '
'Go back to your rooms — previously encrypted ' 'Go back to your rooms. Previously encrypted '
'messages should now be readable.', 'messages should now be readable.',
), ),
], ],

View File

@@ -1,4 +1,4 @@
// Version: 1.4.0 | Created: 2026-04-01 | Updated: 2026-04-11 // Version: 1.4.1 | Created: 2026-04-01 | Updated: 2026-07-03
// Profile screen. Shows current user info and logout button. // Profile screen. Shows current user info and logout button.
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@@ -89,7 +89,7 @@ class ProfileScreen extends ConsumerWidget {
title: const Text('End-to-end encryption'), title: const Text('End-to-end encryption'),
subtitle: Text( subtitle: Text(
client.encryptionEnabled client.encryptionEnabled
? 'Active — messages are encrypted' ? 'Active. Messages are encrypted'
: 'Not available in this browser', : 'Not available in this browser',
), ),
enabled: false, enabled: false,
@@ -108,7 +108,7 @@ class ProfileScreen extends ConsumerWidget {
if (restored && context.mounted) { if (restored && context.mounted) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
const SnackBar( const SnackBar(
content: Text('Keys restored — reopen rooms ' content: Text('Keys restored. Reopen rooms '
'to see decrypted messages.'), 'to see decrypted messages.'),
), ),
); );
@@ -121,7 +121,7 @@ class ProfileScreen extends ConsumerWidget {
title: const Text('Security setup'), title: const Text('Security setup'),
subtitle: Text( subtitle: Text(
client.encryption?.crossSigning.enabled == true client.encryption?.crossSigning.enabled == true
? 'Cross-signing active — device verified' ? 'Cross-signing active. Device verified'
: 'Set up cross-signing and key backup', : 'Set up cross-signing and key backup',
), ),
enabled: client.encryptionEnabled, enabled: client.encryptionEnabled,

View File

@@ -1,4 +1,4 @@
// Version: 1.0.0 | Created: 2026-04-11 // Version: 1.0.1 | Created: 2026-04-11 | Updated: 2026-07-03
// Security setup dialog: drives the Matrix SDK Bootstrap to set up // Security setup dialog: drives the Matrix SDK Bootstrap to set up
// SSSS, cross-signing, and online key backup in one flow. // SSSS, cross-signing, and online key backup in one flow.
// For new users: creates everything, shows recovery key. // For new users: creates everything, shows recovery key.
@@ -298,7 +298,7 @@ class _SecuritySetupDialogState extends State<_SecuritySetupDialog> {
children: [ children: [
const Text( const Text(
'Your recovery key has been created. Save it somewhere ' 'Your recovery key has been created. Save it somewhere '
'safe — you will need it to restore your messages on ' 'safe. You will need it to restore your messages on '
'new devices.', 'new devices.',
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
@@ -389,7 +389,7 @@ class _SecuritySetupDialogState extends State<_SecuritySetupDialog> {
onPressed: () async { onPressed: () async {
await _restoreKeys(); await _restoreKeys();
}, },
child: const Text('I saved it continue'), child: const Text('I saved it, continue'),
), ),
], ],
_Phase.done => [ _Phase.done => [

View File

@@ -1,4 +1,4 @@
// Version: 1.1.0 | Created: 2026-04-02 | Updated: 2026-04-10 // Version: 1.1.1 | Created: 2026-04-02 | Updated: 2026-07-03
// Shared utility for generating a last-message preview string from a Room. // Shared utility for generating a last-message preview string from a Room.
// Used by both RoomsRepository and SyncPersistenceService to avoid duplication. // Used by both RoomsRepository and SyncPersistenceService to avoid duplication.
@@ -12,7 +12,7 @@ String? lastMessagePreview(Room room) {
return switch (lastEvent.type) { return switch (lastEvent.type) {
EventTypes.Message => lastEvent.body, EventTypes.Message => lastEvent.body,
EventTypes.Encrypted => '\u{1F512} Encrypted — use Element to read', EventTypes.Encrypted => '\u{1F512} Encrypted. Use Element to read',
EventTypes.Sticker => 'Sticker', EventTypes.Sticker => 'Sticker',
_ => null, _ => null,
}; };

View File

@@ -1,7 +1,7 @@
name: m8chat_app name: m8chat_app
description: "M8Chat — Matrix chat client for Android, iOS, and Web." description: "M8Chat — Matrix chat client for Android, iOS, and Web."
publish_to: 'none' publish_to: 'none'
version: 1.5.0+7 version: 1.6.0+8
environment: environment:
sdk: '>=3.11.0 <4.0.0' sdk: '>=3.11.0 <4.0.0'

View File

@@ -3,8 +3,8 @@
"short_name": "M8Chat", "short_name": "M8Chat",
"start_url": ".", "start_url": ".",
"display": "standalone", "display": "standalone",
"background_color": "#0F0F1A", "background_color": "#0A0F2E",
"theme_color": "#5C35C9", "theme_color": "#1265ED",
"description": "M8Chat — secure chat and conferencing.", "description": "M8Chat — secure chat and conferencing.",
"orientation": "portrait-primary", "orientation": "portrait-primary",
"prefer_related_applications": false, "prefer_related_applications": false,