diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 1ac2357..8ad6bf3 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -1038,8 +1038,8 @@ "login_enterPassword": "Enter password", "login_savePassword": "Save password", "login_savePasswordSubtitle": "Password will be stored securely on this device", - "login_repeaterDescription": "Enter the repeater password to access settings and status.", - "login_roomDescription": "Enter the room password to access settings and status.", + "login_repeaterDescription": "Enter the repeater password for guest or admin access.", + "login_roomDescription": "Enter the room password for guest or admin access.", "login_routing": "Routing", "login_routingMode": "Routing mode", "login_autoUseSavedPath": "Auto (use saved path)", @@ -1105,7 +1105,10 @@ "path_setPath": "Set Path", "repeater_management": "Repeater Management", "room_management": "Room Server Management", + "repeater_guest": "Repeater Information", + "room_guest": "Room Server Information", "repeater_managementTools": "Management Tools", + "repeater_guestTools": "Guest Tools", "repeater_status": "Status", "repeater_statusSubtitle": "View repeater status, stats, and neighbors", "repeater_telemetry": "Telemetry", diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart index efcbd0f..2c1342d 100644 --- a/lib/l10n/app_localizations.dart +++ b/lib/l10n/app_localizations.dart @@ -3438,13 +3438,13 @@ abstract class AppLocalizations { /// No description provided for @login_repeaterDescription. /// /// In en, this message translates to: - /// **'Enter the repeater password to access settings and status.'** + /// **'Enter the repeater password for guest or admin access.'** String get login_repeaterDescription; /// No description provided for @login_roomDescription. /// /// In en, this message translates to: - /// **'Enter the room password to access settings and status.'** + /// **'Enter the room password for guest or admin access.'** String get login_roomDescription; /// No description provided for @login_routing. @@ -3609,12 +3609,30 @@ abstract class AppLocalizations { /// **'Room Server Management'** String get room_management; + /// No description provided for @repeater_guest. + /// + /// In en, this message translates to: + /// **'Repeater Information'** + String get repeater_guest; + + /// No description provided for @room_guest. + /// + /// In en, this message translates to: + /// **'Room Server Information'** + String get room_guest; + /// No description provided for @repeater_managementTools. /// /// In en, this message translates to: /// **'Management Tools'** String get repeater_managementTools; + /// No description provided for @repeater_guestTools. + /// + /// In en, this message translates to: + /// **'Guest Tools'** + String get repeater_guestTools; + /// No description provided for @repeater_status. /// /// In en, this message translates to: diff --git a/lib/l10n/app_localizations_bg.dart b/lib/l10n/app_localizations_bg.dart index bb07229..ffb1728 100644 --- a/lib/l10n/app_localizations_bg.dart +++ b/lib/l10n/app_localizations_bg.dart @@ -2019,9 +2019,18 @@ class AppLocalizationsBg extends AppLocalizations { @override String get room_management => 'Управление на сървъра за стая'; + @override + String get repeater_guest => 'Repeater Information'; + + @override + String get room_guest => 'Room Server Information'; + @override String get repeater_managementTools => 'Инструменти за управление'; + @override + String get repeater_guestTools => 'Guest Tools'; + @override String get repeater_status => 'Статус'; diff --git a/lib/l10n/app_localizations_de.dart b/lib/l10n/app_localizations_de.dart index 49cf19a..f58e94a 100644 --- a/lib/l10n/app_localizations_de.dart +++ b/lib/l10n/app_localizations_de.dart @@ -2017,9 +2017,18 @@ class AppLocalizationsDe extends AppLocalizations { @override String get room_management => 'Raum-Server-Verwaltung'; + @override + String get repeater_guest => 'Repeater Information'; + + @override + String get room_guest => 'Room Server Information'; + @override String get repeater_managementTools => 'Verwaltungs-Tools'; + @override + String get repeater_guestTools => 'Guest Tools'; + @override String get repeater_status => 'Status'; diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart index e13934b..a2a88b0 100644 --- a/lib/l10n/app_localizations_en.dart +++ b/lib/l10n/app_localizations_en.dart @@ -1871,11 +1871,11 @@ class AppLocalizationsEn extends AppLocalizations { @override String get login_repeaterDescription => - 'Enter the repeater password to access settings and status.'; + 'Enter the repeater password for guest or admin access.'; @override String get login_roomDescription => - 'Enter the room password to access settings and status.'; + 'Enter the room password for guest or admin access.'; @override String get login_routing => 'Routing'; @@ -1979,9 +1979,18 @@ class AppLocalizationsEn extends AppLocalizations { @override String get room_management => 'Room Server Management'; + @override + String get repeater_guest => 'Repeater Information'; + + @override + String get room_guest => 'Room Server Information'; + @override String get repeater_managementTools => 'Management Tools'; + @override + String get repeater_guestTools => 'Guest Tools'; + @override String get repeater_status => 'Status'; diff --git a/lib/l10n/app_localizations_es.dart b/lib/l10n/app_localizations_es.dart index ddb9b6e..bdcf34c 100644 --- a/lib/l10n/app_localizations_es.dart +++ b/lib/l10n/app_localizations_es.dart @@ -2015,9 +2015,18 @@ class AppLocalizationsEs extends AppLocalizations { @override String get room_management => 'Administración del Servidor de Habitación'; + @override + String get repeater_guest => 'Repeater Information'; + + @override + String get room_guest => 'Room Server Information'; + @override String get repeater_managementTools => 'Herramientas de Gestión'; + @override + String get repeater_guestTools => 'Guest Tools'; + @override String get repeater_status => 'Estado'; diff --git a/lib/l10n/app_localizations_fr.dart b/lib/l10n/app_localizations_fr.dart index fbe106d..6689efb 100644 --- a/lib/l10n/app_localizations_fr.dart +++ b/lib/l10n/app_localizations_fr.dart @@ -2026,9 +2026,18 @@ class AppLocalizationsFr extends AppLocalizations { @override String get room_management => 'Administrattion Room Server'; + @override + String get repeater_guest => 'Repeater Information'; + + @override + String get room_guest => 'Room Server Information'; + @override String get repeater_managementTools => 'Outils de Gestion'; + @override + String get repeater_guestTools => 'Guest Tools'; + @override String get repeater_status => 'État'; diff --git a/lib/l10n/app_localizations_hu.dart b/lib/l10n/app_localizations_hu.dart index 920efd8..a274768 100644 --- a/lib/l10n/app_localizations_hu.dart +++ b/lib/l10n/app_localizations_hu.dart @@ -2030,9 +2030,18 @@ class AppLocalizationsHu extends AppLocalizations { @override String get room_management => 'Szoba-szerver kezelés'; + @override + String get repeater_guest => 'Repeater Information'; + + @override + String get room_guest => 'Room Server Information'; + @override String get repeater_managementTools => 'Menedzsmentes eszközök'; + @override + String get repeater_guestTools => 'Guest Tools'; + @override String get repeater_status => 'Állapot'; diff --git a/lib/l10n/app_localizations_it.dart b/lib/l10n/app_localizations_it.dart index b492d6a..2dae65c 100644 --- a/lib/l10n/app_localizations_it.dart +++ b/lib/l10n/app_localizations_it.dart @@ -2016,9 +2016,18 @@ class AppLocalizationsIt extends AppLocalizations { @override String get room_management => 'Gestione del Server di Camera'; + @override + String get repeater_guest => 'Repeater Information'; + + @override + String get room_guest => 'Room Server Information'; + @override String get repeater_managementTools => 'Strumenti di Gestione'; + @override + String get repeater_guestTools => 'Guest Tools'; + @override String get repeater_status => 'Stato'; diff --git a/lib/l10n/app_localizations_ja.dart b/lib/l10n/app_localizations_ja.dart index daebcba..bf47adc 100644 --- a/lib/l10n/app_localizations_ja.dart +++ b/lib/l10n/app_localizations_ja.dart @@ -1932,9 +1932,18 @@ class AppLocalizationsJa extends AppLocalizations { @override String get room_management => 'ルームサーバーの管理'; + @override + String get repeater_guest => 'Repeater Information'; + + @override + String get room_guest => 'Room Server Information'; + @override String get repeater_managementTools => '管理ツール'; + @override + String get repeater_guestTools => 'Guest Tools'; + @override String get repeater_status => 'ステータス'; diff --git a/lib/l10n/app_localizations_ko.dart b/lib/l10n/app_localizations_ko.dart index 605cc96..ef66cc4 100644 --- a/lib/l10n/app_localizations_ko.dart +++ b/lib/l10n/app_localizations_ko.dart @@ -1929,9 +1929,18 @@ class AppLocalizationsKo extends AppLocalizations { @override String get room_management => '방 서버 관리'; + @override + String get repeater_guest => 'Repeater Information'; + + @override + String get room_guest => 'Room Server Information'; + @override String get repeater_managementTools => '관리 도구'; + @override + String get repeater_guestTools => 'Guest Tools'; + @override String get repeater_status => '상태'; diff --git a/lib/l10n/app_localizations_nl.dart b/lib/l10n/app_localizations_nl.dart index 3d1644f..0779ffd 100644 --- a/lib/l10n/app_localizations_nl.dart +++ b/lib/l10n/app_localizations_nl.dart @@ -2003,9 +2003,18 @@ class AppLocalizationsNl extends AppLocalizations { @override String get room_management => 'Beheer Server Kamer'; + @override + String get repeater_guest => 'Repeater Information'; + + @override + String get room_guest => 'Room Server Information'; + @override String get repeater_managementTools => 'Beheerfuncties'; + @override + String get repeater_guestTools => 'Guest Tools'; + @override String get repeater_status => 'Status'; diff --git a/lib/l10n/app_localizations_pl.dart b/lib/l10n/app_localizations_pl.dart index f0006b1..cfffdf0 100644 --- a/lib/l10n/app_localizations_pl.dart +++ b/lib/l10n/app_localizations_pl.dart @@ -2031,9 +2031,18 @@ class AppLocalizationsPl extends AppLocalizations { @override String get room_management => 'Zarządzanie Serwerem Pokoju'; + @override + String get repeater_guest => 'Repeater Information'; + + @override + String get room_guest => 'Room Server Information'; + @override String get repeater_managementTools => 'Narzędzia Zarządzania'; + @override + String get repeater_guestTools => 'Guest Tools'; + @override String get repeater_status => 'Status'; diff --git a/lib/l10n/app_localizations_pt.dart b/lib/l10n/app_localizations_pt.dart index f4b7ffc..2abc403 100644 --- a/lib/l10n/app_localizations_pt.dart +++ b/lib/l10n/app_localizations_pt.dart @@ -2015,9 +2015,18 @@ class AppLocalizationsPt extends AppLocalizations { @override String get room_management => 'Gerenciamento de Servidor de Sala'; + @override + String get repeater_guest => 'Repeater Information'; + + @override + String get room_guest => 'Room Server Information'; + @override String get repeater_managementTools => 'Ferramentas de Gerenciamento'; + @override + String get repeater_guestTools => 'Guest Tools'; + @override String get repeater_status => 'Status'; diff --git a/lib/l10n/app_localizations_ru.dart b/lib/l10n/app_localizations_ru.dart index dcd9d9c..8002011 100644 --- a/lib/l10n/app_localizations_ru.dart +++ b/lib/l10n/app_localizations_ru.dart @@ -2019,9 +2019,18 @@ class AppLocalizationsRu extends AppLocalizations { @override String get room_management => 'Управление сервером комнат'; + @override + String get repeater_guest => 'Repeater Information'; + + @override + String get room_guest => 'Room Server Information'; + @override String get repeater_managementTools => 'Инструменты управления'; + @override + String get repeater_guestTools => 'Guest Tools'; + @override String get repeater_status => 'Статус'; diff --git a/lib/l10n/app_localizations_sk.dart b/lib/l10n/app_localizations_sk.dart index 7323ddc..aceaa69 100644 --- a/lib/l10n/app_localizations_sk.dart +++ b/lib/l10n/app_localizations_sk.dart @@ -2004,9 +2004,18 @@ class AppLocalizationsSk extends AppLocalizations { @override String get room_management => 'Správa servera miestnosti'; + @override + String get repeater_guest => 'Repeater Information'; + + @override + String get room_guest => 'Room Server Information'; + @override String get repeater_managementTools => 'Nástroje na správu'; + @override + String get repeater_guestTools => 'Guest Tools'; + @override String get repeater_status => 'Status'; diff --git a/lib/l10n/app_localizations_sl.dart b/lib/l10n/app_localizations_sl.dart index a374d4b..7f1d320 100644 --- a/lib/l10n/app_localizations_sl.dart +++ b/lib/l10n/app_localizations_sl.dart @@ -2001,9 +2001,18 @@ class AppLocalizationsSl extends AppLocalizations { @override String get room_management => 'Upravljanje stremlišča'; + @override + String get repeater_guest => 'Repeater Information'; + + @override + String get room_guest => 'Room Server Information'; + @override String get repeater_managementTools => 'Upravne orodje'; + @override + String get repeater_guestTools => 'Guest Tools'; + @override String get repeater_status => 'Status'; diff --git a/lib/l10n/app_localizations_sv.dart b/lib/l10n/app_localizations_sv.dart index 6e2f563..efa4d60 100644 --- a/lib/l10n/app_localizations_sv.dart +++ b/lib/l10n/app_localizations_sv.dart @@ -1990,9 +1990,18 @@ class AppLocalizationsSv extends AppLocalizations { @override String get room_management => 'Rumserverhantering'; + @override + String get repeater_guest => 'Repeater Information'; + + @override + String get room_guest => 'Room Server Information'; + @override String get repeater_managementTools => 'Administrationsverktyg'; + @override + String get repeater_guestTools => 'Guest Tools'; + @override String get repeater_status => 'Status'; diff --git a/lib/l10n/app_localizations_uk.dart b/lib/l10n/app_localizations_uk.dart index dd189eb..6134c64 100644 --- a/lib/l10n/app_localizations_uk.dart +++ b/lib/l10n/app_localizations_uk.dart @@ -2014,9 +2014,18 @@ class AppLocalizationsUk extends AppLocalizations { @override String get room_management => 'Адміністрування сервера кімнати'; + @override + String get repeater_guest => 'Repeater Information'; + + @override + String get room_guest => 'Room Server Information'; + @override String get repeater_managementTools => 'Інструменти керування'; + @override + String get repeater_guestTools => 'Guest Tools'; + @override String get repeater_status => 'Статус'; diff --git a/lib/l10n/app_localizations_zh.dart b/lib/l10n/app_localizations_zh.dart index b48b31d..56f235c 100644 --- a/lib/l10n/app_localizations_zh.dart +++ b/lib/l10n/app_localizations_zh.dart @@ -1890,9 +1890,18 @@ class AppLocalizationsZh extends AppLocalizations { @override String get room_management => '房间服务器管理'; + @override + String get repeater_guest => 'Repeater Information'; + + @override + String get room_guest => 'Room Server Information'; + @override String get repeater_managementTools => '管理工具'; + @override + String get repeater_guestTools => 'Guest Tools'; + @override String get repeater_status => '状态'; diff --git a/lib/screens/contacts_screen.dart b/lib/screens/contacts_screen.dart index 5a6f359..54d3299 100644 --- a/lib/screens/contacts_screen.dart +++ b/lib/screens/contacts_screen.dart @@ -961,13 +961,16 @@ class _ContactsScreenState extends State context: context, builder: (context) => RepeaterLoginDialog( repeater: repeater, - onLogin: (password) { + onLogin: (password, isAdmin) { // Navigate to repeater hub screen after successful login Navigator.push( context, MaterialPageRoute( - builder: (context) => - RepeaterHubScreen(repeater: repeater, password: password), + builder: (context) => RepeaterHubScreen( + repeater: repeater, + password: password, + isAdmin: isAdmin, + ), ), ); }, @@ -984,14 +987,18 @@ class _ContactsScreenState extends State context: context, builder: (context) => RoomLoginDialog( room: room, - onLogin: (password) { + onLogin: (password, isAdmin) { context.read().markContactRead(room.publicKeyHex); Navigator.push( context, MaterialPageRoute( builder: (context) => destination == RoomLoginDestination.management - ? RepeaterHubScreen(repeater: room, password: password) + ? RepeaterHubScreen( + repeater: room, + password: password, + isAdmin: isAdmin, + ) : ChatScreen(contact: room), ), ); diff --git a/lib/screens/map_screen.dart b/lib/screens/map_screen.dart index daf49d9..6a8acda 100644 --- a/lib/screens/map_screen.dart +++ b/lib/screens/map_screen.dart @@ -1367,13 +1367,16 @@ class _MapScreenState extends State { context: context, builder: (context) => RepeaterLoginDialog( repeater: repeater, - onLogin: (password) { + onLogin: (password, isAdmin) { // Navigate to repeater hub screen after successful login Navigator.push( context, MaterialPageRoute( - builder: (context) => - RepeaterHubScreen(repeater: repeater, password: password), + builder: (context) => RepeaterHubScreen( + repeater: repeater, + password: password, + isAdmin: isAdmin, + ), ), ); }, @@ -1386,7 +1389,8 @@ class _MapScreenState extends State { context: context, builder: (context) => RoomLoginDialog( room: room, - onLogin: (password) { + // onLogin(password, isAdmin) isAdmin not used for room caht screen + onLogin: (password, _) { // Navigate to chat screen after successful login context.read().markContactRead(room.publicKeyHex); Navigator.push( diff --git a/lib/screens/repeater_hub_screen.dart b/lib/screens/repeater_hub_screen.dart index 8a14253..0dc141c 100644 --- a/lib/screens/repeater_hub_screen.dart +++ b/lib/screens/repeater_hub_screen.dart @@ -13,11 +13,13 @@ import 'neighbors_screen.dart'; class RepeaterHubScreen extends StatelessWidget { final Contact repeater; final String password; + final bool isAdmin; const RepeaterHubScreen({ super.key, required this.repeater, required this.password, + required this.isAdmin, }); @override @@ -33,11 +35,18 @@ class RepeaterHubScreen extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ - Text( - repeater.type == advTypeRepeater - ? l10n.repeater_management - : l10n.room_management, - ), + if (isAdmin) + Text( + repeater.type == advTypeRepeater + ? l10n.repeater_management + : l10n.room_management, + ), + if (!isAdmin) + Text( + repeater.type == advTypeRepeater + ? l10n.repeater_guest + : l10n.room_guest, + ), Text( repeater.name, style: const TextStyle( @@ -113,64 +122,67 @@ class RepeaterHubScreen extends StatelessWidget { ), ), const SizedBox(height: 24), - Card( - child: Padding( - padding: const EdgeInsets.fromLTRB(16, 16, 16, 12), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - const Icon(Icons.battery_full), - const SizedBox(width: 10), - Expanded( - child: Text( - l10n.appSettings_batteryChemistry, - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, + if (isAdmin) + Card( + child: Padding( + padding: const EdgeInsets.fromLTRB(16, 16, 16, 12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + const Icon(Icons.battery_full), + const SizedBox(width: 10), + Expanded( + child: Text( + l10n.appSettings_batteryChemistry, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + ), ), ), - ), - ], - ), - const SizedBox(height: 12), - DropdownButtonFormField( - initialValue: chemistry, - isExpanded: true, - decoration: const InputDecoration( - border: UnderlineInputBorder(), - isDense: true, + ], ), - onChanged: (value) { - if (value == null) return; - settingsService.setBatteryChemistryForRepeater( - repeater.publicKeyHex, - value, - ); - }, - items: [ - DropdownMenuItem( - value: 'nmc', - child: Text(l10n.appSettings_batteryNmc), + const SizedBox(height: 12), + DropdownButtonFormField( + initialValue: chemistry, + isExpanded: true, + decoration: const InputDecoration( + border: UnderlineInputBorder(), + isDense: true, ), - DropdownMenuItem( - value: 'lifepo4', - child: Text(l10n.appSettings_batteryLifepo4), - ), - DropdownMenuItem( - value: 'lipo', - child: Text(l10n.appSettings_batteryLipo), - ), - ], - ), - ], + onChanged: (value) { + if (value == null) return; + settingsService.setBatteryChemistryForRepeater( + repeater.publicKeyHex, + value, + ); + }, + items: [ + DropdownMenuItem( + value: 'nmc', + child: Text(l10n.appSettings_batteryNmc), + ), + DropdownMenuItem( + value: 'lifepo4', + child: Text(l10n.appSettings_batteryLifepo4), + ), + DropdownMenuItem( + value: 'lipo', + child: Text(l10n.appSettings_batteryLipo), + ), + ], + ), + ], + ), ), ), - ), const SizedBox(height: 24), Text( - l10n.repeater_managementTools, + isAdmin + ? l10n.repeater_managementTools + : l10n.repeater_guestTools, style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), const SizedBox(height: 16), @@ -210,26 +222,27 @@ class RepeaterHubScreen extends StatelessWidget { ); }, ), - const SizedBox(height: 12), + if (isAdmin) const SizedBox(height: 12), // CLI button - _buildManagementCard( - context, - icon: Icons.terminal, - title: l10n.repeater_cli, - subtitle: l10n.repeater_cliSubtitle, - color: Colors.green, - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => RepeaterCliScreen( - repeater: repeater, - password: password, + if (isAdmin) + _buildManagementCard( + context, + icon: Icons.terminal, + title: l10n.repeater_cli, + subtitle: l10n.repeater_cliSubtitle, + color: Colors.green, + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => RepeaterCliScreen( + repeater: repeater, + password: password, + ), ), - ), - ); - }, - ), + ); + }, + ), const SizedBox(height: 12), // Neighbors button _buildManagementCard( @@ -248,26 +261,27 @@ class RepeaterHubScreen extends StatelessWidget { ); }, ), - const SizedBox(height: 12), + if (isAdmin) const SizedBox(height: 12), // Settings button - _buildManagementCard( - context, - icon: Icons.settings, - title: l10n.repeater_settings, - subtitle: l10n.repeater_settingsSubtitle, - color: Colors.deepOrange, - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => RepeaterSettingsScreen( - repeater: repeater, - password: password, + if (isAdmin) + _buildManagementCard( + context, + icon: Icons.settings, + title: l10n.repeater_settings, + subtitle: l10n.repeater_settingsSubtitle, + color: Colors.deepOrange, + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => RepeaterSettingsScreen( + repeater: repeater, + password: password, + ), ), - ), - ); - }, - ), + ); + }, + ), ], ), ), diff --git a/lib/widgets/repeater_login_dialog.dart b/lib/widgets/repeater_login_dialog.dart index 521cfd2..d38bd03 100644 --- a/lib/widgets/repeater_login_dialog.dart +++ b/lib/widgets/repeater_login_dialog.dart @@ -14,7 +14,7 @@ import 'path_management_dialog.dart'; class RepeaterLoginDialog extends StatefulWidget { final Contact repeater; - final Function(String password) onLogin; + final Function(String password, bool isAdmin) onLogin; const RepeaterLoginDialog({ super.key, @@ -119,6 +119,7 @@ class _RepeaterLoginDialogState extends State { : '${selection.hopCount} hops'; appLogger.info('Login routing: $selectionLabel', tag: 'RepeaterLogin'); bool? loginResult; + bool isAdmin = false; for (int attempt = 0; attempt < _maxAttempts; attempt++) { if (!mounted) return; setState(() { @@ -131,7 +132,7 @@ class _RepeaterLoginDialogState extends State { ); await _connector.sendFrame(loginFrame); - loginResult = await _awaitLoginResponse(timeout); + (loginResult, isAdmin) = await _awaitLoginResponse(timeout); if (loginResult == true) { appLogger.info( 'Login succeeded for ${repeater.name}', @@ -212,7 +213,7 @@ class _RepeaterLoginDialogState extends State { if (mounted) { Navigator.pop(context, password); - Future.microtask(() => widget.onLogin(password)); + Future.microtask(() => widget.onLogin(password, isAdmin)); } } catch (e) { final repeater = _resolveRepeater(_connector); @@ -229,17 +230,21 @@ class _RepeaterLoginDialogState extends State { } } - Future _awaitLoginResponse(Duration timeout) async { + // _awaitLoginResponse returns a record of bool, for success and if the client is an admin + Future<(bool?, bool)> _awaitLoginResponse(Duration timeout) async { final completer = Completer(); Timer? timer; StreamSubscription? subscription; final targetPrefix = widget.repeater.publicKey.sublist(0, 6); - + bool isAdmin = false; subscription = _connector.receivedFrames.listen((frame) { if (frame.isEmpty) return; final code = frame[0]; if (code != pushCodeLoginSuccess && code != pushCodeLoginFail) return; if (frame.length < 8) return; + // NOTE: a bug in the repeater firmware only ever sends 1 or 0 back, not the + // expected client permissions + isAdmin = (frame[1] == 1); final prefix = frame.sublist(2, 8); if (!listEquals(prefix, targetPrefix)) return; @@ -258,7 +263,7 @@ class _RepeaterLoginDialogState extends State { final result = await completer.future; timer.cancel(); await subscription.cancel(); - return result; + return (result, isAdmin); } @override diff --git a/lib/widgets/room_login_dialog.dart b/lib/widgets/room_login_dialog.dart index d4028a3..4d7f29e 100644 --- a/lib/widgets/room_login_dialog.dart +++ b/lib/widgets/room_login_dialog.dart @@ -15,7 +15,7 @@ import 'path_management_dialog.dart'; class RoomLoginDialog extends StatefulWidget { final Contact room; - final Function(String password) onLogin; + final Function(String password, bool isAdmin) onLogin; const RoomLoginDialog({super.key, required this.room, required this.onLogin}); @@ -115,6 +115,7 @@ class _RoomLoginDialogState extends State { : '${selection.hopCount} hops'; appLogger.info('Login routing: $selectionLabel', tag: 'RoomLogin'); bool? loginResult; + bool isAdmin = false; for (int attempt = 0; attempt < _maxAttempts; attempt++) { if (!mounted) return; setState(() { @@ -127,7 +128,7 @@ class _RoomLoginDialogState extends State { ); await _connector.sendFrame(loginFrame); - loginResult = await _awaitLoginResponse(timeout); + (loginResult, isAdmin) = await _awaitLoginResponse(timeout); if (loginResult == true) { appLogger.info('Login succeeded for ${room.name}', tag: 'RoomLogin'); break; @@ -167,7 +168,7 @@ class _RoomLoginDialogState extends State { if (mounted) { Navigator.pop(context, password); - Future.microtask(() => widget.onLogin(password)); + Future.microtask(() => widget.onLogin(password, isAdmin)); } } catch (e) { final room = _resolveRepeater(_connector); @@ -185,16 +186,20 @@ class _RoomLoginDialogState extends State { } } - Future _awaitLoginResponse(Duration timeout) async { + Future<(bool?, bool)> _awaitLoginResponse(Duration timeout) async { final completer = Completer(); Timer? timer; StreamSubscription? subscription; final targetPrefix = widget.room.publicKey.sublist(0, 6); + bool isAdmin = false; subscription = _connector.receivedFrames.listen((frame) { if (frame.isEmpty) return; final code = frame[0]; if (code != pushCodeLoginSuccess && code != pushCodeLoginFail) return; + // NOTE: a bug in the repeater firmware only ever sends 1 or 0 back, not the + // expected client permissions + isAdmin = (frame[1] == 1); if (frame.length < 8) return; final prefix = frame.sublist(2, 8); if (!listEquals(prefix, targetPrefix)) return; @@ -214,7 +219,7 @@ class _RoomLoginDialogState extends State { final result = await completer.future; timer.cancel(); await subscription.cancel(); - return result; + return (result, isAdmin); } @override diff --git a/untranslated.json b/untranslated.json index 1ebd9bc..2b4bbbc 100644 --- a/untranslated.json +++ b/untranslated.json @@ -1,69 +1,120 @@ { "bg": [ - "chat_sendMessage" + "chat_sendMessage", + "repeater_guest", + "room_guest", + "repeater_guestTools" ], "de": [ - "chat_sendMessage" + "chat_sendMessage", + "repeater_guest", + "room_guest", + "repeater_guestTools" ], "es": [ - "chat_sendMessage" + "chat_sendMessage", + "repeater_guest", + "room_guest", + "repeater_guestTools" ], "fr": [ - "chat_sendMessage" + "chat_sendMessage", + "repeater_guest", + "room_guest", + "repeater_guestTools" ], "hu": [ - "chat_sendMessage" + "chat_sendMessage", + "repeater_guest", + "room_guest", + "repeater_guestTools" ], "it": [ - "chat_sendMessage" + "chat_sendMessage", + "repeater_guest", + "room_guest", + "repeater_guestTools" ], "ja": [ - "chat_sendMessage" + "chat_sendMessage", + "repeater_guest", + "room_guest", + "repeater_guestTools" ], "ko": [ - "chat_sendMessage" + "chat_sendMessage", + "repeater_guest", + "room_guest", + "repeater_guestTools" ], "nl": [ - "chat_sendMessage" + "chat_sendMessage", + "repeater_guest", + "room_guest", + "repeater_guestTools" ], "pl": [ - "chat_sendMessage" + "chat_sendMessage", + "repeater_guest", + "room_guest", + "repeater_guestTools" ], "pt": [ - "chat_sendMessage" + "chat_sendMessage", + "repeater_guest", + "room_guest", + "repeater_guestTools" ], "ru": [ - "chat_sendMessage" + "chat_sendMessage", + "repeater_guest", + "room_guest", + "repeater_guestTools" ], "sk": [ - "chat_sendMessage" + "chat_sendMessage", + "repeater_guest", + "room_guest", + "repeater_guestTools" ], "sl": [ - "chat_sendMessage" + "chat_sendMessage", + "repeater_guest", + "room_guest", + "repeater_guestTools" ], "sv": [ - "chat_sendMessage" + "chat_sendMessage", + "repeater_guest", + "room_guest", + "repeater_guestTools" ], "uk": [ - "chat_sendMessage" + "chat_sendMessage", + "repeater_guest", + "room_guest", + "repeater_guestTools" ], "zh": [ - "chat_sendMessage" + "chat_sendMessage", + "repeater_guest", + "room_guest", + "repeater_guestTools" ] }