+fix
This commit is contained in:
@@ -11,27 +11,13 @@
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
|
||||
<application
|
||||
android:label="family_safety_frontend"
|
||||
android:label="GeoShare"
|
||||
android:name="${applicationName}"
|
||||
android:icon="@mipmap/ic_launcher">
|
||||
<service
|
||||
android:name="com.pravera.flutter_foreground_task.service.ForegroundService"
|
||||
android:foregroundServiceType="location"
|
||||
android:exported="false" />
|
||||
<receiver
|
||||
android:name="com.pravera.flutter_foreground_task.receiver.AlarmReceiver"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="com.pravera.flutter_foreground_task.action.ALARM" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<receiver
|
||||
android:name="com.pravera.flutter_foreground_task.receiver.BootReceiver"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
class ApiConfig {
|
||||
static String _baseUrl = 'https://family-safety.onrender.com/api';
|
||||
static String _baseUrl = 'https://test';
|
||||
|
||||
static String get baseUrl => _baseUrl;
|
||||
|
||||
static void setBaseUrl(String url) {
|
||||
static void setBaseUrl(String url){
|
||||
_baseUrl = url.endsWith('/') ? url.substring(0, url.length - 1) : url;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import 'services/settings_service.dart';
|
||||
void main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
final settings = SettingsService();
|
||||
await settings.initialize();
|
||||
ApiConfig.setBaseUrl(settings.baseUrl);
|
||||
final bgGeo = BackgroundGeoService();
|
||||
await bgGeo.init();
|
||||
|
||||
@@ -30,13 +30,18 @@ class _LoginScreenState extends State<LoginScreen>
|
||||
_tabController.addListener(() {
|
||||
setState(() {});
|
||||
});
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
final settings = context.read<SettingsService>();
|
||||
_serverUrlController.text = settings.baseUrl;
|
||||
_loginController.text = settings.login ?? "";
|
||||
_passwordController.text = settings.pwd ?? "";
|
||||
if (settings.login != null && settings.pwd != null) {
|
||||
savedAuth = true;
|
||||
final authProvider = context.read<AuthProvider>();
|
||||
login(settings.login!, settings.pwd!, authProvider);
|
||||
Navigator.of(context).pushReplacementNamed('/map');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -53,15 +58,6 @@ class _LoginScreenState extends State<LoginScreen>
|
||||
Widget build(BuildContext context) {
|
||||
final authProvider = context.watch<AuthProvider>();
|
||||
final settings = context.read<SettingsService>();
|
||||
if (savedAuth) {
|
||||
login(
|
||||
_loginController.text,
|
||||
_passwordController.text,
|
||||
context,
|
||||
authProvider,
|
||||
settings,
|
||||
);
|
||||
}
|
||||
return Scaffold(
|
||||
resizeToAvoidBottomInset: true,
|
||||
body: SingleChildScrollView(
|
||||
@@ -77,7 +73,7 @@ class _LoginScreenState extends State<LoginScreen>
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
const Text(
|
||||
'Family Safety',
|
||||
'Авторизация',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 32,
|
||||
@@ -174,11 +170,13 @@ class _LoginScreenState extends State<LoginScreen>
|
||||
}
|
||||
}
|
||||
if (_tabController.index == 0) {
|
||||
print("Login...");
|
||||
try {
|
||||
await authProvider.login(
|
||||
_loginController.text,
|
||||
_passwordController.text,
|
||||
);
|
||||
settings.saveAuth(_loginController.text, _passwordController.text);
|
||||
if (!context.mounted) return;
|
||||
Navigator.of(
|
||||
context,
|
||||
@@ -233,15 +231,10 @@ class _LoginScreenState extends State<LoginScreen>
|
||||
Future<void> login(
|
||||
String login,
|
||||
String pwd,
|
||||
BuildContext ctx,
|
||||
AuthProvider authProvider,
|
||||
SettingsService settings,
|
||||
) async {
|
||||
try {
|
||||
await authProvider.login(login, pwd);
|
||||
settings.saveAuth(login, pwd);
|
||||
if (!ctx.mounted) return;
|
||||
Navigator.of(ctx).pushReplacementNamed('/map');
|
||||
} catch (e) {
|
||||
// Error is handled by provider
|
||||
}
|
||||
|
||||
+32
-10
@@ -1,4 +1,5 @@
|
||||
import 'dart:async';
|
||||
import 'package:GeoShare/services/settings_service.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_map/flutter_map.dart';
|
||||
@@ -27,7 +28,7 @@ class _MapScreenState extends State<MapScreen> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_initLocationAndShare();
|
||||
//_initLocationAndShare();
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -150,7 +151,8 @@ class _MapScreenState extends State<MapScreen> {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
builder: (context) => _WatchMenu(
|
||||
builder: (context) =>
|
||||
_WatchMenu(
|
||||
token: authProvider.token,
|
||||
onAdd: (shareId) async {
|
||||
await shareProvider.addTracking(shareId, authProvider.token);
|
||||
@@ -207,6 +209,7 @@ class _MapScreenState extends State<MapScreen> {
|
||||
final authProvider = context.watch<AuthProvider>();
|
||||
final _ = context.watch<MapProvider>();
|
||||
final shareProvider = context.watch<ShareProvider>();
|
||||
final settings = context.read<SettingsService>();
|
||||
|
||||
if (_loading) {
|
||||
return Scaffold(body: const Center(child: CircularProgressIndicator()));
|
||||
@@ -215,7 +218,8 @@ class _MapScreenState extends State<MapScreen> {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(
|
||||
'Family Safety Map\n${_center.latitude.toStringAsFixed(4)}, ${_center.longitude.toStringAsFixed(4)}',
|
||||
'Карта\n${_center.latitude.toStringAsFixed(4)}, ${_center
|
||||
.longitude.toStringAsFixed(4)}',
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
actions: [
|
||||
@@ -223,7 +227,10 @@ class _MapScreenState extends State<MapScreen> {
|
||||
icon: const Icon(Icons.refresh),
|
||||
onPressed: _updateGeolocation,
|
||||
),
|
||||
IconButton(icon: const Icon(Icons.share), onPressed: _copyShareLink),
|
||||
IconButton(icon: const Icon(Icons.share), onPressed: () {
|
||||
_initLocationAndShare();
|
||||
_copyShareLink();
|
||||
}),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.visibility),
|
||||
onPressed: _openWatchMenu,
|
||||
@@ -236,6 +243,7 @@ class _MapScreenState extends State<MapScreen> {
|
||||
await bgGeo.stop();
|
||||
bgGeo.dispose();
|
||||
authProvider.logout();
|
||||
settings.logOut();
|
||||
Navigator.of(context).pushReplacementNamed('/');
|
||||
},
|
||||
),
|
||||
@@ -287,7 +295,10 @@ class _WatchMenuState extends State<_WatchMenu> {
|
||||
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(
|
||||
bottom: MediaQuery.of(context).viewInsets.bottom,
|
||||
bottom: MediaQuery
|
||||
.of(context)
|
||||
.viewInsets
|
||||
.bottom,
|
||||
),
|
||||
child: Container(
|
||||
constraints: const BoxConstraints(maxHeight: 400),
|
||||
@@ -297,7 +308,10 @@ class _WatchMenuState extends State<_WatchMenu> {
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surfaceContainerHighest,
|
||||
color: Theme
|
||||
.of(context)
|
||||
.colorScheme
|
||||
.surfaceContainerHighest,
|
||||
borderRadius: const BorderRadius.vertical(
|
||||
top: Radius.circular(16),
|
||||
),
|
||||
@@ -354,7 +368,8 @@ class _WatchMenuState extends State<_WatchMenu> {
|
||||
title: Text(person.name),
|
||||
subtitle: hasPosition
|
||||
? Text(
|
||||
'${person.position!['y'].toStringAsFixed(4)}, ${person.position!['x'].toStringAsFixed(4)}',
|
||||
'${person.position!['y'].toStringAsFixed(4)}, ${person
|
||||
.position!['x'].toStringAsFixed(4)}',
|
||||
)
|
||||
: const Text('Нет данных'),
|
||||
trailing: IconButton(
|
||||
@@ -368,7 +383,10 @@ class _WatchMenuState extends State<_WatchMenu> {
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surfaceContainerHighest,
|
||||
color: Theme
|
||||
.of(context)
|
||||
.colorScheme
|
||||
.surfaceContainerHighest,
|
||||
borderRadius: const BorderRadius.vertical(
|
||||
bottom: Radius.circular(16),
|
||||
),
|
||||
@@ -387,7 +405,9 @@ class _WatchMenuState extends State<_WatchMenu> {
|
||||
),
|
||||
),
|
||||
onSubmitted: (value) {
|
||||
if (value.trim().isNotEmpty) {
|
||||
if (value
|
||||
.trim()
|
||||
.isNotEmpty) {
|
||||
widget.onAdd(value.trim());
|
||||
_controller.clear();
|
||||
}
|
||||
@@ -397,7 +417,9 @@ class _WatchMenuState extends State<_WatchMenu> {
|
||||
const SizedBox(width: 8),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
if (_controller.text.trim().isNotEmpty) {
|
||||
if (_controller.text
|
||||
.trim()
|
||||
.isNotEmpty) {
|
||||
widget.onAdd(_controller.text.trim());
|
||||
_controller.clear();
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ class AuthService {
|
||||
AuthService({http.Client? client}) : _client = client ?? http.Client();
|
||||
|
||||
Future<String> login(String login, String password) async {
|
||||
print(ApiConfig.loginUrl);
|
||||
final response = await _client.post(
|
||||
Uri.parse(ApiConfig.loginUrl),
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
@@ -17,6 +18,8 @@ class AuthService {
|
||||
if (response.statusCode == 200) {
|
||||
return response.body;
|
||||
} else {
|
||||
print(response.statusCode);
|
||||
print(response.body);
|
||||
throw Exception('Invalid credentials');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
class SettingsService {
|
||||
SettingsService(){initialize();}
|
||||
static const String _baseUrlKey = 'server_base_url';
|
||||
static const String _defaultBaseUrl =
|
||||
'https://family-safety.onrender.com/api';
|
||||
@@ -13,6 +12,7 @@ class SettingsService {
|
||||
String get baseUrl => _baseUrl;
|
||||
String? login;
|
||||
String? pwd;
|
||||
bool loggedIn=false;
|
||||
|
||||
Future<void> initialize() async {
|
||||
if (_initialized) return;
|
||||
@@ -34,7 +34,14 @@ class SettingsService {
|
||||
pwd = pass;
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setString(_loginKey, user);
|
||||
await prefs.setString(_loginKey, user);
|
||||
await prefs.setString(_pwdKey, pass);
|
||||
}
|
||||
Future<void> logOut() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
login = null;
|
||||
pwd = null;
|
||||
await prefs.remove(_loginKey);
|
||||
await prefs.remove(_pwdKey);
|
||||
}
|
||||
|
||||
void resetToDefault() {
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
name: family_safety_frontend
|
||||
description: "A new Flutter project."
|
||||
name: GeoShare
|
||||
description: "GeoShare"
|
||||
# The following line prevents the package from being accidentally published to
|
||||
# pub.dev using `flutter pub publish`. This is preferred for private packages.
|
||||
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
|
||||
Reference in New Issue
Block a user