mirror of
https://github.com/supanadit/geo-smart-app.git
synced 2024-11-22 01:46:21 +00:00
Migrate to flutter_bloc
This commit is contained in:
parent
64511fb1f7
commit
cc0fd1cd84
7
android/.gitignore
vendored
Normal file
7
android/.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
gradle-wrapper.jar
|
||||
/.gradle
|
||||
/captures/
|
||||
/gradlew
|
||||
/gradlew.bat
|
||||
/local.properties
|
||||
GeneratedPluginRegistrant.java
|
@ -0,0 +1,6 @@
|
||||
package com.example.geosmart
|
||||
|
||||
import io.flutter.embedding.android.FlutterActivity
|
||||
|
||||
class MainActivity: FlutterActivity() {
|
||||
}
|
32
ios/.gitignore
vendored
Normal file
32
ios/.gitignore
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
*.mode1v3
|
||||
*.mode2v3
|
||||
*.moved-aside
|
||||
*.pbxuser
|
||||
*.perspectivev3
|
||||
**/*sync/
|
||||
.sconsign.dblite
|
||||
.tags*
|
||||
**/.vagrant/
|
||||
**/DerivedData/
|
||||
Icon?
|
||||
**/Pods/
|
||||
**/.symlinks/
|
||||
profile
|
||||
xcuserdata
|
||||
**/.generated/
|
||||
Flutter/App.framework
|
||||
Flutter/Flutter.framework
|
||||
Flutter/Flutter.podspec
|
||||
Flutter/Generated.xcconfig
|
||||
Flutter/app.flx
|
||||
Flutter/app.zip
|
||||
Flutter/flutter_assets/
|
||||
Flutter/flutter_export_environment.sh
|
||||
ServiceDefinitions.json
|
||||
Runner/GeneratedPluginRegistrant.*
|
||||
|
||||
# Exceptions to above rules.
|
||||
!default.mode1v3
|
||||
!default.mode2v3
|
||||
!default.pbxuser
|
||||
!default.perspectivev3
|
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>PreviewsEnabled</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>PreviewsEnabled</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
3
lib/bloc/authentication/authentication.dart
Normal file
3
lib/bloc/authentication/authentication.dart
Normal file
@ -0,0 +1,3 @@
|
||||
export 'authentication_bloc.dart';
|
||||
export 'authentication_event.dart';
|
||||
export 'authentication_state.dart';
|
38
lib/bloc/authentication/authentication_bloc.dart
Normal file
38
lib/bloc/authentication/authentication_bloc.dart
Normal file
@ -0,0 +1,38 @@
|
||||
import 'package:alice/alice.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:geosmart/bloc/authentication/authentication_event.dart';
|
||||
import 'package:geosmart/bloc/authentication/authentication_state.dart';
|
||||
import 'package:geosmart/service/setting_service.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
class AuthenticationBloc
|
||||
extends Bloc<AuthenticationEvent, AuthenticationState> {
|
||||
final Alice alice;
|
||||
final Dio dio;
|
||||
|
||||
AuthenticationBloc({
|
||||
@required this.alice,
|
||||
@required this.dio,
|
||||
}) : super(AuthenticationInitial());
|
||||
|
||||
@override
|
||||
Stream<AuthenticationState> mapEventToState(
|
||||
AuthenticationEvent event,
|
||||
) async* {
|
||||
if (event is AuthenticationStarted) {
|
||||
yield AuthenticationProgress();
|
||||
final s = await SettingService().getSetting();
|
||||
if (s.isValid()) {
|
||||
yield AuthenticationSuccess();
|
||||
} else {
|
||||
yield AuthenticationFailed();
|
||||
}
|
||||
}
|
||||
|
||||
if (event is AuthenticationClear) {
|
||||
await SettingService().clearSetting();
|
||||
yield AuthenticationFailed();
|
||||
}
|
||||
}
|
||||
}
|
12
lib/bloc/authentication/authentication_event.dart
Normal file
12
lib/bloc/authentication/authentication_event.dart
Normal file
@ -0,0 +1,12 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
class AuthenticationEvent extends Equatable {
|
||||
const AuthenticationEvent();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class AuthenticationStarted extends AuthenticationEvent {}
|
||||
|
||||
class AuthenticationClear extends AuthenticationEvent {}
|
16
lib/bloc/authentication/authentication_state.dart
Normal file
16
lib/bloc/authentication/authentication_state.dart
Normal file
@ -0,0 +1,16 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
class AuthenticationState extends Equatable {
|
||||
const AuthenticationState();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class AuthenticationInitial extends AuthenticationState {}
|
||||
|
||||
class AuthenticationProgress extends AuthenticationState {}
|
||||
|
||||
class AuthenticationSuccess extends AuthenticationState {}
|
||||
|
||||
class AuthenticationFailed extends AuthenticationState {}
|
3
lib/bloc/bloc.dart
Normal file
3
lib/bloc/bloc.dart
Normal file
@ -0,0 +1,3 @@
|
||||
export 'authentication/authentication.dart';
|
||||
export 'position/position.dart';
|
||||
export 'setting/setting.dart';
|
3
lib/bloc/position/position.dart
Normal file
3
lib/bloc/position/position.dart
Normal file
@ -0,0 +1,3 @@
|
||||
export 'position_bloc.dart';
|
||||
export 'position_event.dart';
|
||||
export 'position_state.dart';
|
45
lib/bloc/position/position_bloc.dart
Normal file
45
lib/bloc/position/position_bloc.dart
Normal file
@ -0,0 +1,45 @@
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:geosmart/bloc/authentication/authentication.dart';
|
||||
import 'package:geosmart/bloc/position/position_event.dart';
|
||||
import 'package:geosmart/bloc/position/position_state.dart';
|
||||
import 'package:geosmart/service/position_service.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
class PositionBloc extends Bloc<PositionEvent, PositionState> {
|
||||
final AuthenticationBloc authenticationBloc;
|
||||
|
||||
PositionBloc({@required this.authenticationBloc})
|
||||
: super(PositionTrackingIdle());
|
||||
|
||||
@override
|
||||
Stream<PositionState> mapEventToState(PositionEvent event) async* {
|
||||
if (event is PositionStartTracking) {
|
||||
yield PositionTrackingStarted();
|
||||
}
|
||||
if (event is PositionStopTracking) {
|
||||
try {
|
||||
await PositionService(
|
||||
dio: authenticationBloc.dio,
|
||||
).stopTracking();
|
||||
yield PositionTrackingIdle();
|
||||
} catch (e) {
|
||||
yield PositionTrackingFailed();
|
||||
}
|
||||
}
|
||||
if (event is PositionSend) {
|
||||
try {
|
||||
PositionService(
|
||||
dio: authenticationBloc.dio,
|
||||
).sendPosition(
|
||||
event.lat,
|
||||
event.lng,
|
||||
);
|
||||
} catch (_) {
|
||||
await PositionService(
|
||||
dio: authenticationBloc.dio,
|
||||
).stopTracking();
|
||||
yield PositionTrackingFailed();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
25
lib/bloc/position/position_event.dart
Normal file
25
lib/bloc/position/position_event.dart
Normal file
@ -0,0 +1,25 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
class PositionEvent extends Equatable {
|
||||
const PositionEvent();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class PositionStartTracking extends PositionEvent {}
|
||||
|
||||
class PositionSend extends PositionEvent {
|
||||
final String lat;
|
||||
final String lng;
|
||||
|
||||
const PositionSend({this.lat, this.lng});
|
||||
|
||||
@override
|
||||
List<Object> get props => [this.lat, this.lng];
|
||||
|
||||
@override
|
||||
String toString() => "PositionSend { lat: $lat, lng: $lng }";
|
||||
}
|
||||
|
||||
class PositionStopTracking extends PositionEvent {}
|
14
lib/bloc/position/position_state.dart
Normal file
14
lib/bloc/position/position_state.dart
Normal file
@ -0,0 +1,14 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
class PositionState extends Equatable {
|
||||
const PositionState();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class PositionTrackingIdle extends PositionState {}
|
||||
|
||||
class PositionTrackingFailed extends PositionState {}
|
||||
|
||||
class PositionTrackingStarted extends PositionState {}
|
3
lib/bloc/setting/setting.dart
Normal file
3
lib/bloc/setting/setting.dart
Normal file
@ -0,0 +1,3 @@
|
||||
export 'setting_bloc.dart';
|
||||
export 'setting_event.dart';
|
||||
export 'setting_state.dart';
|
40
lib/bloc/setting/setting_bloc.dart
Normal file
40
lib/bloc/setting/setting_bloc.dart
Normal file
@ -0,0 +1,40 @@
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:geosmart/bloc/authentication/authentication.dart';
|
||||
import 'package:geosmart/bloc/setting/setting_event.dart';
|
||||
import 'package:geosmart/bloc/setting/setting_state.dart';
|
||||
import 'package:geosmart/model/setting.dart';
|
||||
import 'package:geosmart/service/setting_service.dart';
|
||||
import 'package:geosmart/service/unique_id_service.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
class SettingBloc extends Bloc<SettingEvent, SettingState> {
|
||||
final AuthenticationBloc authenticationBloc;
|
||||
|
||||
SettingBloc({@required this.authenticationBloc}) : super(SettingInitial());
|
||||
|
||||
@override
|
||||
Stream<SettingState> mapEventToState(SettingEvent event) async* {
|
||||
if (event is SettingSet) {
|
||||
yield SettingProgress();
|
||||
if (event.host != null && event.host != "") {
|
||||
try {
|
||||
final s = await UniqueIDService().getUniqueID(
|
||||
event.host,
|
||||
authenticationBloc.dio,
|
||||
);
|
||||
SettingService().setSetting(SettingModel(
|
||||
event.host,
|
||||
s.id,
|
||||
));
|
||||
yield SettingSuccess();
|
||||
} catch (_) {
|
||||
yield SettingFailed(
|
||||
message: "Make sure your host is correct and alive.",
|
||||
);
|
||||
}
|
||||
} else {
|
||||
yield SettingFailed(message: "Host cannot null or empty.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
23
lib/bloc/setting/setting_event.dart
Normal file
23
lib/bloc/setting/setting_event.dart
Normal file
@ -0,0 +1,23 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
class SettingEvent extends Equatable {
|
||||
const SettingEvent();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class SettingSet extends SettingEvent {
|
||||
final String host;
|
||||
|
||||
const SettingSet({@required this.host}) : assert(host != null && host != "");
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
|
||||
@override
|
||||
String toString() => "SettingSet { host: $host }";
|
||||
}
|
||||
|
||||
class SettingClear extends SettingEvent {}
|
26
lib/bloc/setting/setting_state.dart
Normal file
26
lib/bloc/setting/setting_state.dart
Normal file
@ -0,0 +1,26 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
class SettingState extends Equatable {
|
||||
const SettingState();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class SettingInitial extends SettingState {}
|
||||
|
||||
class SettingProgress extends SettingState {}
|
||||
|
||||
class SettingSuccess extends SettingState {}
|
||||
|
||||
class SettingFailed extends SettingState {
|
||||
final String message;
|
||||
|
||||
const SettingFailed({this.message});
|
||||
|
||||
@override
|
||||
List<Object> get props => [this.message];
|
||||
|
||||
@override
|
||||
String toString() => "SettingFailed { message: $message }";
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
class Config {
|
||||
static const String api = "http://192.168.1.7:8080";
|
||||
static const bool dynamicHostSetting = true;
|
||||
static const bool showInterceptor = true;
|
||||
}
|
||||
|
@ -1,19 +1,71 @@
|
||||
import 'package:alice/alice.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:geosmart/page/startup.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:geosmart/config.dart';
|
||||
import 'package:geosmart/page/map_page.dart';
|
||||
import 'package:geosmart/page/setting_page.dart';
|
||||
import 'package:geosmart/page/startup_page.dart';
|
||||
|
||||
void main() => runApp(MyApp());
|
||||
import 'bloc/bloc.dart';
|
||||
|
||||
void main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
final Alice alice = Alice(showNotification: Config.showInterceptor);
|
||||
final Dio dio = Dio();
|
||||
dio.interceptors.add(alice.getDioInterceptor());
|
||||
|
||||
runApp(
|
||||
MultiBlocProvider(
|
||||
providers: [
|
||||
BlocProvider<AuthenticationBloc>(
|
||||
create: (context) => AuthenticationBloc(
|
||||
alice: alice,
|
||||
dio: dio,
|
||||
)..add(AuthenticationStarted()),
|
||||
),
|
||||
BlocProvider<SettingBloc>(
|
||||
create: (context) => SettingBloc(
|
||||
authenticationBloc: BlocProvider.of<AuthenticationBloc>(
|
||||
context,
|
||||
),
|
||||
),
|
||||
),
|
||||
BlocProvider<PositionBloc>(
|
||||
create: (context) => PositionBloc(
|
||||
authenticationBloc: BlocProvider.of<AuthenticationBloc>(
|
||||
context,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
child: MyApp(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
SystemChrome.setEnabledSystemUIOverlays([]);
|
||||
return MaterialApp(
|
||||
title: 'Geo Smart App',
|
||||
navigatorKey: BlocProvider.of<AuthenticationBloc>(
|
||||
context,
|
||||
).alice.getNavigatorKey(),
|
||||
theme: ThemeData(
|
||||
primarySwatch: Colors.blue,
|
||||
),
|
||||
home: Startup(),
|
||||
home: BlocBuilder<AuthenticationBloc, AuthenticationState>(
|
||||
builder: (ctx, state) {
|
||||
if (state is AuthenticationSuccess) {
|
||||
return MapPage();
|
||||
}
|
||||
if (state is AuthenticationFailed) {
|
||||
return SettingPage();
|
||||
}
|
||||
return StartupPage();
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -12,9 +12,7 @@ class SettingModel {
|
||||
return (this.id == "" || this.id == null);
|
||||
}
|
||||
|
||||
bool isNullHostId(String operator) {
|
||||
return (operator == "and")
|
||||
? isNullHost() && isNullId()
|
||||
: isNullHost() || isNullId();
|
||||
bool isValid() {
|
||||
return (!isNullHost() && !isNullId());
|
||||
}
|
||||
}
|
||||
|
@ -1,208 +0,0 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:geolocator/geolocator.dart' as geo;
|
||||
import 'package:geosmart/model/position.dart';
|
||||
import 'package:geosmart/model/setting.dart';
|
||||
import 'package:geosmart/page/setting.dart';
|
||||
import 'package:geosmart/service/position_service.dart';
|
||||
import 'package:geosmart/service/setting_service.dart';
|
||||
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
||||
|
||||
class Map extends StatefulWidget {
|
||||
Map({Key key, this.title}) : super(key: key);
|
||||
|
||||
final String title;
|
||||
|
||||
@override
|
||||
_MapState createState() => _MapState();
|
||||
}
|
||||
|
||||
class _MapState extends State<Map> {
|
||||
Completer<GoogleMapController> _controller = Completer();
|
||||
double latitude = 0.0;
|
||||
double longitude = 0.0;
|
||||
double altitude = 0.0;
|
||||
double accuracy = 0.0;
|
||||
double bearing = 0.0;
|
||||
double speed = 0.0;
|
||||
PositionService _positionService;
|
||||
SettingService _settingService;
|
||||
bool isChecking = true;
|
||||
Position _position;
|
||||
|
||||
String id;
|
||||
String host;
|
||||
|
||||
bool isGranted = false;
|
||||
bool isTracking = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
setState(() {
|
||||
isChecking = true;
|
||||
});
|
||||
_settingService = new SettingService();
|
||||
_positionService = new PositionService();
|
||||
// geo.Geolocator()..forceAndroidLocationManager = true;
|
||||
geo.Geolocator().checkGeolocationPermissionStatus().then(
|
||||
(v) {
|
||||
setState(() {
|
||||
isGranted = true;
|
||||
});
|
||||
var geolocator = geo.Geolocator();
|
||||
var locationOptions = geo.LocationOptions(
|
||||
accuracy: geo.LocationAccuracy.high,
|
||||
);
|
||||
|
||||
geolocator
|
||||
.getPositionStream(locationOptions)
|
||||
.listen((geo.Position position) {
|
||||
if (this.id != null) {
|
||||
setState(() {
|
||||
this._position = Position(
|
||||
id: this.id,
|
||||
lat: position.latitude.toString(),
|
||||
lng: position.longitude.toString(),
|
||||
type: "user",
|
||||
);
|
||||
});
|
||||
} else {
|
||||
stopLocationService();
|
||||
settingPage();
|
||||
}
|
||||
print(
|
||||
"New position detected with lat ${position.latitude} and lng ${position.longitude}");
|
||||
sendLastPosition();
|
||||
});
|
||||
|
||||
_settingService.getSetting().then((v) {
|
||||
this.id = v.id;
|
||||
this.host = v.host;
|
||||
|
||||
if (v.isNullId()) {
|
||||
settingPage();
|
||||
}
|
||||
});
|
||||
},
|
||||
).catchError((e) {
|
||||
setState(() {
|
||||
isGranted = false;
|
||||
});
|
||||
}).whenComplete(() {
|
||||
setState(() {
|
||||
isChecking = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
static final CameraPosition _kGooglePlex = CameraPosition(
|
||||
target: LatLng(-6.914744, 107.609810),
|
||||
zoom: 14.4746,
|
||||
);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new Scaffold(
|
||||
body: Stack(
|
||||
children: <Widget>[
|
||||
GoogleMap(
|
||||
mapType: MapType.normal,
|
||||
initialCameraPosition: _kGooglePlex,
|
||||
myLocationEnabled: true,
|
||||
myLocationButtonEnabled: true,
|
||||
onMapCreated: (GoogleMapController controller) {
|
||||
_controller.complete(controller);
|
||||
},
|
||||
),
|
||||
Container(
|
||||
child: Image.asset("assets/images/logo.png"),
|
||||
width: 70,
|
||||
height: 70,
|
||||
alignment: Alignment.topLeft,
|
||||
margin: EdgeInsets.only(left: 10.0),
|
||||
),
|
||||
Container(
|
||||
child: FlatButton(
|
||||
color: (isTracking) ? Colors.redAccent : Colors.green,
|
||||
onPressed: toggleTracking,
|
||||
child: Text(
|
||||
(isChecking)
|
||||
? "Please wait"
|
||||
: ((isTracking) ? "Stop Tracking" : "Start Tracking"),
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
),
|
||||
margin: EdgeInsets.only(bottom: 50.0),
|
||||
alignment: Alignment.bottomCenter,
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
toggleTracking() {
|
||||
if (!isChecking) {
|
||||
if (isGranted) {
|
||||
if (isTracking) {
|
||||
stopLocationService();
|
||||
} else {
|
||||
sendLastPosition();
|
||||
}
|
||||
setState(() {
|
||||
isTracking = !isTracking;
|
||||
});
|
||||
} else {
|
||||
FlutterToast.showToast(
|
||||
msg: "Make sure you have turn on location services",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stopLocationService() {
|
||||
if (_positionService != null) {
|
||||
_positionService.stopTracking();
|
||||
}
|
||||
}
|
||||
|
||||
settingPage() {
|
||||
Navigator.of(context).pushReplacement(new MaterialPageRoute(
|
||||
builder: (BuildContext context) => Setting(),
|
||||
));
|
||||
}
|
||||
|
||||
sendLastPosition() async {
|
||||
SettingModel m = await _settingService.getSetting();
|
||||
print("Prepare to Send last location with ID : ${m.id} to ${m.host}");
|
||||
if (this._position != null) {
|
||||
if (this._position.isValid()) {
|
||||
if (_positionService != null) {
|
||||
print("Lat ${_position.lat}, Lng ${_position.lng}");
|
||||
if (isTracking) {
|
||||
print("Send tracking location");
|
||||
_positionService.sendPosition(
|
||||
this._position.lat.toString(),
|
||||
this._position.lng.toString(),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
FlutterToast.showToast(
|
||||
msg: "Failed to start position service",
|
||||
);
|
||||
settingPage();
|
||||
}
|
||||
} else {
|
||||
print("Invalid Position");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
stopLocationService();
|
||||
}
|
||||
}
|
139
lib/page/map_page.dart
Normal file
139
lib/page/map_page.dart
Normal file
@ -0,0 +1,139 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:geolocator/geolocator.dart' as geo;
|
||||
import 'package:geosmart/bloc/bloc.dart';
|
||||
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
||||
|
||||
class MapPage extends StatefulWidget {
|
||||
MapPage({Key key, this.title}) : super(key: key);
|
||||
|
||||
final String title;
|
||||
|
||||
@override
|
||||
_MapPageState createState() => _MapPageState();
|
||||
}
|
||||
|
||||
class _MapPageState extends State<MapPage> {
|
||||
Completer<GoogleMapController> _controller = Completer();
|
||||
bool isChecking = true;
|
||||
bool isGranted = false;
|
||||
bool isTracking = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
setState(() {
|
||||
isChecking = true;
|
||||
});
|
||||
// geo.Geolocator()..forceAndroidLocationManager = true;
|
||||
geo.Geolocator().checkGeolocationPermissionStatus().then(
|
||||
(v) {
|
||||
isGranted = true;
|
||||
var geolocator = geo.Geolocator();
|
||||
var locationOptions = geo.LocationOptions(
|
||||
accuracy: geo.LocationAccuracy.high,
|
||||
);
|
||||
|
||||
geolocator.getPositionStream(locationOptions).listen(
|
||||
(geo.Position position) {
|
||||
if (isTracking && isGranted) {
|
||||
BlocProvider.of<PositionBloc>(context).add(
|
||||
PositionSend(
|
||||
lat: position.latitude.toString(),
|
||||
lng: position.longitude.toString(),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
).catchError((e) {
|
||||
isGranted = false;
|
||||
}).whenComplete(() {
|
||||
setState(() {
|
||||
isChecking = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
static final CameraPosition _kGooglePlex = CameraPosition(
|
||||
target: LatLng(-6.914744, 107.609810),
|
||||
zoom: 14.4746,
|
||||
);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: BlocListener<PositionBloc, PositionState>(
|
||||
listener: (ctx, state) {
|
||||
if (state is PositionTrackingFailed) {
|
||||
BlocProvider.of<AuthenticationBloc>(ctx).add(
|
||||
AuthenticationClear(),
|
||||
);
|
||||
}
|
||||
if (state is PositionTrackingStarted) {
|
||||
isTracking = true;
|
||||
}
|
||||
if (state is PositionTrackingIdle) {
|
||||
isTracking = false;
|
||||
}
|
||||
},
|
||||
child: BlocBuilder<PositionBloc, PositionState>(
|
||||
builder: (ctx, state) {
|
||||
return Stack(
|
||||
children: <Widget>[
|
||||
GoogleMap(
|
||||
mapType: MapType.normal,
|
||||
initialCameraPosition: _kGooglePlex,
|
||||
myLocationEnabled: true,
|
||||
myLocationButtonEnabled: true,
|
||||
onMapCreated: (GoogleMapController controller) {
|
||||
_controller.complete(controller);
|
||||
},
|
||||
),
|
||||
Container(
|
||||
child: Image.asset("assets/images/logo.png"),
|
||||
width: 70,
|
||||
height: 70,
|
||||
alignment: Alignment.topLeft,
|
||||
margin: EdgeInsets.only(left: 10.0),
|
||||
),
|
||||
Container(
|
||||
child: FlatButton(
|
||||
color: (state is PositionTrackingStarted)
|
||||
? Colors.redAccent
|
||||
: Colors.green,
|
||||
onPressed: () async {
|
||||
if (state is PositionTrackingStarted) {
|
||||
BlocProvider.of<PositionBloc>(ctx).add(
|
||||
PositionStopTracking(),
|
||||
);
|
||||
}
|
||||
if (state is PositionTrackingIdle) {
|
||||
BlocProvider.of<PositionBloc>(ctx).add(
|
||||
PositionStartTracking(),
|
||||
);
|
||||
}
|
||||
},
|
||||
child: Text(
|
||||
(isChecking)
|
||||
? "Please wait"
|
||||
: (state is PositionTrackingStarted
|
||||
? "Stop Tracking"
|
||||
: "Start Tracking"),
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
),
|
||||
margin: EdgeInsets.only(bottom: 50.0),
|
||||
alignment: Alignment.bottomCenter,
|
||||
)
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,165 +0,0 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:geosmart/config.dart';
|
||||
import 'package:geosmart/model/setting.dart';
|
||||
import 'package:geosmart/page/map.dart';
|
||||
import 'package:geosmart/service/setting_service.dart';
|
||||
import 'package:geosmart/service/unique_id_service.dart';
|
||||
|
||||
class Setting extends StatefulWidget {
|
||||
@override
|
||||
State<StatefulWidget> createState() {
|
||||
return new _SettingState();
|
||||
}
|
||||
}
|
||||
|
||||
class _SettingState extends State<Setting> {
|
||||
final _hostController = TextEditingController();
|
||||
SettingService _settingBloc;
|
||||
UniqueIDService _uniqueIDBloc;
|
||||
String id;
|
||||
String host;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_settingBloc = new SettingService();
|
||||
|
||||
if (!Config.dynamicHostSetting) {
|
||||
_settingBloc.setSetting(new SettingModel(Config.api, null));
|
||||
}
|
||||
|
||||
_settingBloc.getSetting().then((settingModel) {
|
||||
if (!settingModel.isNullId()) {
|
||||
this.id = settingModel.id;
|
||||
}
|
||||
if (!settingModel.isNullHost()) {
|
||||
this.host = settingModel.host;
|
||||
}
|
||||
|
||||
_hostController.text = this.host;
|
||||
|
||||
if (!settingModel.isNullHost()) {
|
||||
_uniqueIDBloc = new UniqueIDService(settingModel);
|
||||
|
||||
if (_uniqueIDBloc != null) {
|
||||
this._uniqueIDBloc.getUniqueID().then((uniqueId) {
|
||||
print("Your Unique ID " + uniqueId.id.toString());
|
||||
if (uniqueId.id != null && uniqueId.id != "") {
|
||||
if (!settingModel.isNullId()) {
|
||||
mapPage();
|
||||
} else {
|
||||
this._settingBloc.setSetting(
|
||||
new SettingModel(this._hostController.text, uniqueId.id),
|
||||
);
|
||||
mapPage();
|
||||
}
|
||||
} else {
|
||||
FlutterToast.showToast(msg: "Invalid host address");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
mapPage() {
|
||||
Navigator.of(context).pushReplacement(new MaterialPageRoute(
|
||||
builder: (BuildContext context) => Map(),
|
||||
));
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Container(
|
||||
child: Center(
|
||||
child: Container(
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
image: DecorationImage(
|
||||
image: AssetImage("assets/images/server.png"),
|
||||
),
|
||||
),
|
||||
height: 200,
|
||||
),
|
||||
SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
TextField(
|
||||
controller: this._hostController,
|
||||
decoration: InputDecoration(
|
||||
labelText: "Host",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 10.0,
|
||||
),
|
||||
Container(
|
||||
width: double.infinity,
|
||||
child: FlatButton(
|
||||
color: Colors.blueAccent,
|
||||
onPressed: () {
|
||||
this
|
||||
._settingBloc
|
||||
.setSetting(
|
||||
new SettingModel(this._hostController.text, null),
|
||||
)
|
||||
.then((settingModel) {
|
||||
if (!settingModel.isNullId()) {
|
||||
this.id = settingModel.id;
|
||||
}
|
||||
if (!settingModel.isNullHost()) {
|
||||
this.host = settingModel.host;
|
||||
}
|
||||
|
||||
_hostController.text = this.host;
|
||||
|
||||
if (!settingModel.isNullHost()) {
|
||||
_uniqueIDBloc = new UniqueIDService(settingModel);
|
||||
|
||||
if (_uniqueIDBloc != null) {
|
||||
this._uniqueIDBloc.getUniqueID().then((uniqueId) {
|
||||
print("Your Unique ID " + uniqueId.id.toString());
|
||||
if (uniqueId.id != null && uniqueId.id != "") {
|
||||
if (!settingModel.isNullId()) {
|
||||
mapPage();
|
||||
} else {
|
||||
this._settingBloc.setSetting(
|
||||
new SettingModel(
|
||||
this._hostController.text,
|
||||
uniqueId.id,
|
||||
),
|
||||
);
|
||||
mapPage();
|
||||
}
|
||||
} else {
|
||||
FlutterToast.showToast(
|
||||
msg: "Invalid host address",
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
child: Text(
|
||||
"Save",
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
width: 200,
|
||||
height: 400,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
85
lib/page/setting_page.dart
Normal file
85
lib/page/setting_page.dart
Normal file
@ -0,0 +1,85 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:geosmart/bloc/bloc.dart';
|
||||
|
||||
class SettingPage extends StatefulWidget {
|
||||
@override
|
||||
State<StatefulWidget> createState() {
|
||||
return new _SettingPageState();
|
||||
}
|
||||
}
|
||||
|
||||
class _SettingPageState extends State<SettingPage> {
|
||||
final _hostController = TextEditingController();
|
||||
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
key: _scaffoldKey,
|
||||
body: BlocListener<SettingBloc, SettingState>(
|
||||
listener: (ctx, state) {
|
||||
if (state is SettingFailed) {
|
||||
_scaffoldKey.currentState.showSnackBar(SnackBar(
|
||||
content: Text(state.message),
|
||||
duration: Duration(seconds: 3),
|
||||
));
|
||||
}
|
||||
if (state is SettingSuccess) {
|
||||
BlocProvider.of<AuthenticationBloc>(ctx).add(
|
||||
AuthenticationStarted(),
|
||||
);
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
child: Center(
|
||||
child: Container(
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
image: DecorationImage(
|
||||
image: AssetImage("assets/images/server.png"),
|
||||
),
|
||||
),
|
||||
height: 200,
|
||||
),
|
||||
SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
TextField(
|
||||
controller: this._hostController,
|
||||
decoration: InputDecoration(
|
||||
labelText: "Host",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 10.0,
|
||||
),
|
||||
Container(
|
||||
width: double.infinity,
|
||||
child: FlatButton(
|
||||
color: Colors.blueAccent,
|
||||
onPressed: () {
|
||||
BlocProvider.of<SettingBloc>(context).add(
|
||||
SettingSet(host: _hostController.text),
|
||||
);
|
||||
},
|
||||
child: Text(
|
||||
"Save",
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
width: 200,
|
||||
height: 400,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:geosmart/component/loader.dart';
|
||||
import 'package:geosmart/page/map.dart';
|
||||
import 'package:geosmart/page/setting.dart';
|
||||
import 'package:geosmart/service/setting_service.dart';
|
||||
|
||||
class Startup extends StatefulWidget {
|
||||
@override
|
||||
State createState() {
|
||||
return new _StartupState();
|
||||
}
|
||||
}
|
||||
|
||||
class _StartupState extends State<Startup> {
|
||||
SettingService _settingService;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_settingService = new SettingService();
|
||||
|
||||
_settingService.getSetting().then((settingModel) {
|
||||
if (settingModel.isNullHost() && settingModel.isNullId()) {
|
||||
Navigator.of(context).pushReplacement(new MaterialPageRoute(
|
||||
builder: (BuildContext context) => Setting(),
|
||||
));
|
||||
} else {
|
||||
Navigator.of(context).pushReplacement(new MaterialPageRoute(
|
||||
builder: (BuildContext context) => Map(),
|
||||
));
|
||||
}
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Center(
|
||||
child: Container(
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Loader(),
|
||||
SizedBox(
|
||||
height: 20.0,
|
||||
),
|
||||
Text("Preparing System")
|
||||
],
|
||||
),
|
||||
height: 50,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
}
|
24
lib/page/startup_page.dart
Normal file
24
lib/page/startup_page.dart
Normal file
@ -0,0 +1,24 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:geosmart/component/loader.dart';
|
||||
|
||||
class StartupPage extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Center(
|
||||
child: Container(
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Loader(),
|
||||
SizedBox(
|
||||
height: 20.0,
|
||||
),
|
||||
Text("Preparing System")
|
||||
],
|
||||
),
|
||||
height: 50,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -2,12 +2,15 @@ import 'package:dio/dio.dart';
|
||||
import 'package:geosmart/model/position.dart';
|
||||
import 'package:geosmart/model/response.dart';
|
||||
import 'package:geosmart/service/setting_service.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
class PositionService {
|
||||
final Dio _dio = Dio();
|
||||
final Dio dio;
|
||||
final SettingService _settingBloc = SettingService();
|
||||
|
||||
PositionService();
|
||||
PositionService({
|
||||
@required this.dio,
|
||||
});
|
||||
|
||||
Future<ResponseModel> sendPosition(String lat, String lng) async {
|
||||
var m = await _settingBloc.getSetting();
|
||||
@ -18,25 +21,20 @@ class PositionService {
|
||||
lng: lng,
|
||||
);
|
||||
try {
|
||||
Response response = await _dio.post(
|
||||
Response response = await dio.post(
|
||||
m.host + "/point/set",
|
||||
data: position.toJson(),
|
||||
);
|
||||
return ResponseModel.fromJson(response.data);
|
||||
} on DioError catch (e) {
|
||||
print(e.response);
|
||||
if (e.response != null) {
|
||||
return ResponseModel.fromJson(e.response.data);
|
||||
} else {
|
||||
return ResponseModel.fromNull();
|
||||
}
|
||||
throw (e);
|
||||
}
|
||||
}
|
||||
|
||||
Future<ResponseModel> stopTracking() async {
|
||||
var m = await _settingBloc.getSetting();
|
||||
try {
|
||||
Response response = await _dio.post(
|
||||
Response response = await dio.post(
|
||||
m.host + "/point/unset",
|
||||
data: {
|
||||
"id": m.id,
|
||||
@ -45,7 +43,7 @@ class PositionService {
|
||||
);
|
||||
return ResponseModel.fromJson(response.data);
|
||||
} on DioError catch (e) {
|
||||
return ResponseModel.fromJson(e.response.data);
|
||||
throw (e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,9 +16,16 @@ class SettingService {
|
||||
return await getSetting();
|
||||
}
|
||||
|
||||
Future<SettingModel> clearSetting() async {
|
||||
SharedPreferences sharedPreferences = await this.getSharedPreferences();
|
||||
sharedPreferences.remove(_host);
|
||||
sharedPreferences.remove(_id);
|
||||
return await getSetting();
|
||||
}
|
||||
|
||||
Future<SettingModel> getSetting() async {
|
||||
SharedPreferences sharedPreferences = await this.getSharedPreferences();
|
||||
return new SettingModel(
|
||||
return SettingModel(
|
||||
sharedPreferences.getString(_host),
|
||||
sharedPreferences.getString(_id),
|
||||
);
|
||||
|
@ -1,22 +1,17 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:geosmart/model/setting.dart';
|
||||
import 'package:geosmart/model/unique_id_model.dart';
|
||||
|
||||
class UniqueIDService {
|
||||
final String _endpoint = "/id/get/unique";
|
||||
final Dio _dio = Dio();
|
||||
SettingModel _settingModel;
|
||||
|
||||
UniqueIDService(this._settingModel);
|
||||
|
||||
Future<UniqueIDModel> getUniqueID() async {
|
||||
Future<UniqueIDModel> getUniqueID(String host, Dio dio) async {
|
||||
try {
|
||||
Response response = await _dio.get(
|
||||
this._settingModel.host + _endpoint,
|
||||
Response response = await dio.get(
|
||||
host + _endpoint,
|
||||
);
|
||||
return UniqueIDModel.fromJson(response.data);
|
||||
} on DioError catch (e) {
|
||||
return UniqueIDModel.error();
|
||||
throw (e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
235
pubspec.lock
235
pubspec.lock
@ -1,6 +1,13 @@
|
||||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
alice:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: alice
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.3"
|
||||
archive:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -22,6 +29,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.4.1"
|
||||
bloc:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: bloc
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.0.1"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -36,6 +50,20 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.3"
|
||||
chewie:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: chewie
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.9.10"
|
||||
chopper:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: chopper
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.3"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -72,17 +100,52 @@ packages:
|
||||
source: hosted
|
||||
version: "3.0.9"
|
||||
equatable:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: equatable
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
version: "1.2.3"
|
||||
ffi:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ffi
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.3"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "5.2.1"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_bloc:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_bloc
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.0.1"
|
||||
flutter_local_notifications:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_local_notifications
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.4.4+2"
|
||||
flutter_local_notifications_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_local_notifications_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
flutter_plugin_android_lifecycle:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -100,13 +163,6 @@ packages:
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
fluttertoast:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: fluttertoast
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "5.0.1"
|
||||
geolocator:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -156,6 +212,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.12"
|
||||
intl:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: intl
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.16.1"
|
||||
location_permissions:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -163,6 +226,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.0+1"
|
||||
logging:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: logging
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.11.4"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -177,6 +247,34 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.8"
|
||||
nested:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: nested
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.0.4"
|
||||
open_file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: open_file
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
open_iconic_flutter:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: open_iconic_flutter
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.3.0"
|
||||
package_info:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_info
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.4.1"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -184,6 +282,34 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.6.4"
|
||||
path_provider:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.6.11"
|
||||
path_provider_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_linux
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.0.1+2"
|
||||
path_provider_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_macos
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.0.4+3"
|
||||
path_provider_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.2"
|
||||
pedantic:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -191,6 +317,20 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.9.0"
|
||||
permission_handler:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "5.0.1+1"
|
||||
permission_handler_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
petitparser:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -198,6 +338,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.4.0"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: platform
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.2.1"
|
||||
plugin_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -205,6 +352,20 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.2"
|
||||
process:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: process
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.13"
|
||||
provider:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: provider
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.3.1"
|
||||
quiver:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -219,6 +380,27 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.24.1"
|
||||
sensors:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sensors
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.4.2+2"
|
||||
shake:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shake
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.0"
|
||||
share:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: share
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.6.4+3"
|
||||
shared_preferences:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -315,6 +497,41 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.8"
|
||||
video_player:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: video_player
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.10.11+2"
|
||||
video_player_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: video_player_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.2"
|
||||
video_player_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: video_player_web
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.3+2"
|
||||
wakelock:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: wakelock
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.4+2"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xdg_directories
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.0"
|
||||
xml:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -34,7 +34,9 @@ dependencies:
|
||||
shared_preferences: ^0.5.7+3
|
||||
rxdart: ^0.24.1
|
||||
dio: ^3.0.9
|
||||
fluttertoast: ^5.0.1
|
||||
flutter_bloc: ^6.0.1
|
||||
equatable: ^1.2.3
|
||||
alice: ^0.1.3
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
Loading…
Reference in New Issue
Block a user