mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-11 16:30:28 +00:00
feat: Remove manual location update functionality and improve password handling in room login
This commit is contained in:
@@ -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),
|
||||||
|
|||||||
@@ -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: [
|
||||||
|
|||||||
@@ -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(() {
|
||||||
|
|||||||
Reference in New Issue
Block a user