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:
@@ -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 |
@@ -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.
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|||||||
@@ -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,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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),
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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.',
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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 => [
|
||||||
|
|||||||
@@ -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,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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'
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user