feat: Remove manual location update functionality and improve password handling in room login

This commit is contained in:
Janez T
2025-10-16 13:44:35 +02:00
parent 23c439a92e
commit 520f343261
3 changed files with 57 additions and 111 deletions

View File

@@ -29,7 +29,6 @@ class _SettingsScreenState extends State<SettingsScreen> {
late AppThemeMode _selectedTheme; late AppThemeMode _selectedTheme;
PackageInfo? _packageInfo; PackageInfo? _packageInfo;
bool _isLoadingSampleData = false; bool _isLoadingSampleData = false;
bool _isSendingLocationUpdate = false;
final LocationTrackingService _locationService = LocationTrackingService(); final LocationTrackingService _locationService = LocationTrackingService();
@override @override
@@ -234,27 +233,6 @@ class _SettingsScreenState extends State<SettingsScreen> {
} }
} }
Future<void> _sendLocationUpdateNow() async {
setState(() => _isSendingLocationUpdate = true);
try {
final success = await _locationService.broadcastLocationNow();
if (!success && mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Failed to send location update'),
backgroundColor: Colors.red,
),
);
}
} finally {
if (mounted) {
setState(() => _isSendingLocationUpdate = false);
}
}
}
Future<void> _clearSampleData() async { Future<void> _clearSampleData() async {
final confirmed = await showDialog<bool>( final confirmed = await showDialog<bool>(
context: context, context: context,
@@ -321,30 +299,6 @@ class _SettingsScreenState extends State<SettingsScreen> {
// Location Settings Section // Location Settings Section
_buildSectionHeader('Location Broadcasting'), _buildSectionHeader('Location Broadcasting'),
// Manual location update button
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child: SizedBox(
width: double.infinity,
child: ElevatedButton.icon(
onPressed: _isSendingLocationUpdate ? null : _sendLocationUpdateNow,
icon: _isSendingLocationUpdate
? const SizedBox(
width: 18,
height: 18,
child: CircularProgressIndicator(strokeWidth: 2),
)
: const Icon(Icons.my_location),
label: const Text('Broadcast Location Now'),
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 12),
),
),
),
),
const Divider(),
// Automatic tracking settings // Automatic tracking settings
SwitchListTile( SwitchListTile(
secondary: const Icon(Icons.location_on), secondary: const Icon(Icons.location_on),

View File

@@ -226,28 +226,6 @@ class ContactTile extends StatelessWidget {
), ),
const SizedBox(height: 4), const SizedBox(height: 4),
], ],
// Type label (only for rooms - hide for chat and repeater)
if (contact.type == ContactType.room) ...[
Row(
children: [
Container(
padding: const EdgeInsets.symmetric(
horizontal: 6,
vertical: 2,
),
decoration: BoxDecoration(
color: _getTypeColor(contact.type, context).withOpacity(0.2),
borderRadius: BorderRadius.circular(4),
),
child: Text(
contact.type.displayName,
style: Theme.of(context).textTheme.labelSmall,
),
),
],
),
const SizedBox(height: 4),
],
// Last seen + GPS info combined // Last seen + GPS info combined
Row( Row(
children: [ children: [

View File

@@ -35,12 +35,14 @@ class _RoomLoginSheetState extends State<RoomLoginSheet> {
super.dispose(); super.dispose();
} }
/// Load saved password for this room, or use default "hello" /// Load saved password for this room
Future<void> _loadSavedPassword() async { Future<void> _loadSavedPassword() async {
final prefs = await SharedPreferences.getInstance(); final prefs = await SharedPreferences.getInstance();
final roomKey = 'room_password_${widget.contact.publicKeyHex}'; final roomKey = 'room_password_${widget.contact.publicKeyHex}';
final savedPassword = prefs.getString(roomKey) ?? 'hello'; final savedPassword = prefs.getString(roomKey);
_passwordController.text = savedPassword; if (savedPassword != null) {
_passwordController.text = savedPassword;
}
} }
/// Save password for this room /// Save password for this room
@@ -51,19 +53,28 @@ class _RoomLoginSheetState extends State<RoomLoginSheet> {
} }
Future<void> _loginToRoom() async { Future<void> _loginToRoom() async {
final password = _passwordController.text.trim().isEmpty final password = _passwordController.text.trim();
? 'hello'
: _passwordController.text.trim();
final connectionProvider = context.read<ConnectionProvider>(); final connectionProvider = context.read<ConnectionProvider>();
final contactsProvider = context.read<ContactsProvider>(); final contactsProvider = context.read<ContactsProvider>();
if (password.isEmpty) {
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: const Text('Please enter a password'),
backgroundColor: Theme.of(context).colorScheme.error,
),
);
return;
}
if (!connectionProvider.deviceInfo.isConnected) { if (!connectionProvider.deviceInfo.isConnected) {
if (!mounted) return; if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
const SnackBar( SnackBar(
content: Text('Not connected to device'), content: const Text('Not connected to device'),
backgroundColor: Colors.red, backgroundColor: Theme.of(context).colorScheme.error,
), ),
); );
return; return;
@@ -144,7 +155,7 @@ class _RoomLoginSheetState extends State<RoomLoginSheet> {
'The room may not have advertised yet.\n' 'The room may not have advertised yet.\n'
'Try waiting for the room to broadcast.', 'Try waiting for the room to broadcast.',
), ),
backgroundColor: Colors.red, backgroundColor: Theme.of(context).colorScheme.error,
duration: const Duration(seconds: 7), duration: const Duration(seconds: 7),
), ),
); );
@@ -173,7 +184,7 @@ class _RoomLoginSheetState extends State<RoomLoginSheet> {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar( SnackBar(
content: Text('Failed to sync contacts: $e'), content: Text('Failed to sync contacts: $e'),
backgroundColor: Colors.red, backgroundColor: Theme.of(context).colorScheme.error,
), ),
); );
return; return;
@@ -203,10 +214,10 @@ class _RoomLoginSheetState extends State<RoomLoginSheet> {
if (mounted) { if (mounted) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
const SnackBar( SnackBar(
content: Text('Logged in successfully! Waiting for room messages...'), content: const Text('Logged in successfully! Waiting for room messages...'),
backgroundColor: Colors.green, backgroundColor: Theme.of(context).colorScheme.primary,
duration: Duration(seconds: 3), duration: const Duration(seconds: 3),
), ),
); );
} }
@@ -221,10 +232,10 @@ class _RoomLoginSheetState extends State<RoomLoginSheet> {
if (mounted) { if (mounted) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
const SnackBar( SnackBar(
content: Text('Login failed - incorrect password'), content: const Text('Login failed - incorrect password'),
backgroundColor: Colors.red, backgroundColor: Theme.of(context).colorScheme.error,
duration: Duration(seconds: 3), duration: const Duration(seconds: 3),
), ),
); );
} }
@@ -245,7 +256,7 @@ class _RoomLoginSheetState extends State<RoomLoginSheet> {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar( SnackBar(
content: Text('Logging in to ${widget.contact.displayName}...'), content: Text('Logging in to ${widget.contact.displayName}...'),
backgroundColor: Colors.blue, backgroundColor: Theme.of(context).colorScheme.primary,
duration: const Duration(seconds: 2), duration: const Duration(seconds: 2),
), ),
); );
@@ -258,7 +269,7 @@ class _RoomLoginSheetState extends State<RoomLoginSheet> {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar( SnackBar(
content: Text('Failed to send login: $e'), content: Text('Failed to send login: $e'),
backgroundColor: Colors.red, backgroundColor: Theme.of(context).colorScheme.error,
), ),
); );
} finally { } finally {
@@ -272,13 +283,16 @@ class _RoomLoginSheetState extends State<RoomLoginSheet> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = Theme.of(context);
final colorScheme = theme.colorScheme;
return Container( return Container(
constraints: BoxConstraints( constraints: BoxConstraints(
maxHeight: MediaQuery.of(context).size.height * 0.75, maxHeight: MediaQuery.of(context).size.height * 0.75,
), ),
decoration: const BoxDecoration( decoration: BoxDecoration(
color: Color(0xFF1E1E1E), color: colorScheme.surface,
borderRadius: BorderRadius.vertical(top: Radius.circular(20)), borderRadius: const BorderRadius.vertical(top: Radius.circular(20)),
), ),
child: Padding( child: Padding(
padding: EdgeInsets.only( padding: EdgeInsets.only(
@@ -293,25 +307,25 @@ class _RoomLoginSheetState extends State<RoomLoginSheet> {
child: Row( child: Row(
children: [ children: [
IconButton( IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.white), icon: Icon(Icons.arrow_back, color: colorScheme.onSurface),
onPressed: () => Navigator.pop(context), onPressed: () => Navigator.pop(context),
), ),
Expanded( Expanded(
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
const Text( Text(
'Login to Room', 'Login to Room',
style: TextStyle( style: TextStyle(
color: Colors.white, color: colorScheme.onSurface,
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
Text( Text(
widget.contact.displayName, widget.contact.displayName,
style: const TextStyle( style: TextStyle(
color: Colors.grey, color: colorScheme.onSurfaceVariant,
fontSize: 14, fontSize: 14,
), ),
), ),
@@ -333,19 +347,19 @@ class _RoomLoginSheetState extends State<RoomLoginSheet> {
Container( Container(
padding: const EdgeInsets.all(12), padding: const EdgeInsets.all(12),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Theme.of(context).colorScheme.primaryContainer, color: colorScheme.primaryContainer,
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
), ),
child: Row( child: Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Icon(Icons.info_outline, color: Theme.of(context).colorScheme.onPrimaryContainer, size: 20), Icon(Icons.info_outline, color: colorScheme.onPrimaryContainer, size: 20),
const SizedBox(width: 12), const SizedBox(width: 12),
Expanded( Expanded(
child: Text( child: Text(
'Enter the password to access this room. Password defaults to "hello" and will be saved for future use.', 'Enter the password to access this room. The password will be saved for future use.',
style: TextStyle( style: TextStyle(
color: Theme.of(context).colorScheme.onPrimaryContainer, color: colorScheme.onPrimaryContainer,
fontSize: 12, fontSize: 12,
), ),
), ),
@@ -362,8 +376,8 @@ class _RoomLoginSheetState extends State<RoomLoginSheet> {
// Password input (fixed at bottom) // Password input (fixed at bottom)
Container( Container(
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
decoration: const BoxDecoration( decoration: BoxDecoration(
color: Color(0xFF2D2D2D), color: colorScheme.surfaceContainerHighest,
), ),
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
@@ -375,29 +389,29 @@ class _RoomLoginSheetState extends State<RoomLoginSheet> {
obscureText: _obscurePassword, obscureText: _obscurePassword,
autofocus: true, autofocus: true,
maxLengthEnforcement: MaxLengthEnforcement.enforced, maxLengthEnforcement: MaxLengthEnforcement.enforced,
style: const TextStyle(color: Colors.white), style: TextStyle(color: colorScheme.onSurface),
decoration: InputDecoration( decoration: InputDecoration(
labelText: 'Password', labelText: 'Password',
labelStyle: const TextStyle(color: Colors.grey), labelStyle: TextStyle(color: colorScheme.onSurfaceVariant),
hintText: 'Enter room password (default: hello)', hintText: 'Enter room password',
hintStyle: const TextStyle(color: Colors.grey), hintStyle: TextStyle(color: colorScheme.onSurfaceVariant),
border: OutlineInputBorder( border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
borderSide: const BorderSide(color: Colors.grey), borderSide: BorderSide(color: colorScheme.outline),
), ),
enabledBorder: OutlineInputBorder( enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
borderSide: const BorderSide(color: Colors.grey), borderSide: BorderSide(color: colorScheme.outline),
), ),
focusedBorder: OutlineInputBorder( focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
borderSide: const BorderSide(color: Colors.white), borderSide: BorderSide(color: colorScheme.primary, width: 2),
), ),
contentPadding: const EdgeInsets.all(16), contentPadding: const EdgeInsets.all(16),
suffixIcon: IconButton( suffixIcon: IconButton(
icon: Icon( icon: Icon(
_obscurePassword ? Icons.visibility : Icons.visibility_off, _obscurePassword ? Icons.visibility : Icons.visibility_off,
color: Colors.grey, color: colorScheme.onSurfaceVariant,
), ),
onPressed: () { onPressed: () {
setState(() { setState(() {