feat(nahravani): práce na stahování jízdenek
This commit is contained in:
parent
d0273d5be4
commit
423cab90f1
17 changed files with 1015 additions and 90 deletions
|
@ -26,7 +26,7 @@ apply plugin: 'kotlin-android'
|
|||
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
||||
|
||||
android {
|
||||
compileSdkVersion flutter.compileSdkVersion
|
||||
compileSdkVersion 33
|
||||
ndkVersion flutter.ndkVersion
|
||||
|
||||
compileOptions {
|
||||
|
@ -43,12 +43,11 @@ android {
|
|||
}
|
||||
|
||||
defaultConfig {
|
||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||
applicationId "cz.hernikplays.cvak"
|
||||
// You can update the following values to match your application needs.
|
||||
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
|
||||
minSdkVersion flutter.minSdkVersion
|
||||
targetSdkVersion flutter.targetSdkVersion
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 33
|
||||
versionCode flutterVersionCode.toInteger()
|
||||
versionName flutterVersionName
|
||||
}
|
||||
|
|
1
android/app/proguard-rules.pro
vendored
Normal file
1
android/app/proguard-rules.pro
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
-keep class androidx.lifecycle.DefaultLifecycleObserver
|
|
@ -1,7 +1,10 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"
|
||||
package="cz.hernikplays.cvak">
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32"/>
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<application
|
||||
android:label="cvak"
|
||||
android:label="Cvak"
|
||||
android:name="${applicationName}"
|
||||
android:icon="@mipmap/ic_launcher">
|
||||
<activity
|
||||
|
|
9
android/app/src/main/res/values-cs-rCZ/strings.xml
Normal file
9
android/app/src/main/res/values-cs-rCZ/strings.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="flutter_downloader_notification_started">Stahování začalo</string>
|
||||
<string name="flutter_downloader_notification_in_progress">Stahování probíhá</string>
|
||||
<string name="flutter_downloader_notification_canceled">Stahování zrušeno</string>
|
||||
<string name="flutter_downloader_notification_failed">Stahování selhalo</string>
|
||||
<string name="flutter_downloader_notification_complete">Stahování dokončeno</string>
|
||||
<string name="flutter_downloader_notification_paused">Stahování pozastaveno</string>
|
||||
</resources>
|
|
@ -1,10 +1,28 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'dart:io';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'jizdenka.dart';
|
||||
part 'ceskedrahy.g.dart';
|
||||
|
||||
/*
|
||||
Copyright (C) 2022 Matyáš Caras
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
class CeskeDrahy {
|
||||
final Map<String, String> _cookie = {};
|
||||
|
||||
|
@ -88,8 +106,24 @@ class CeskeDrahy {
|
|||
});
|
||||
var data = jsonDecode(r.body);
|
||||
var jizdenky = <CDJizdenka>[];
|
||||
SharedPreferences p = await SharedPreferences.getInstance();
|
||||
var path = p.getString("dlpath")!;
|
||||
for (var j in data["items"]) {
|
||||
jizdenky.add(CDJizdenka.fromJson(j));
|
||||
var cd = CDJizdenka.fromJson(j);
|
||||
// stáhnout obrázek
|
||||
var imgData = await http.get(Uri.parse("https://cd.cz${cd.qrUrl}"),
|
||||
headers: {"Cookie": _cookieString()});
|
||||
// TODO FIX
|
||||
if (imgData.statusCode < 400) {
|
||||
var b64Data =
|
||||
RegExp(r'src="data:image;base64,(.+?)"').firstMatch(imgData.body);
|
||||
if (b64Data != null) {
|
||||
print(b64Data.group(1));
|
||||
File("$path/${j.id}.png")
|
||||
.writeAsBytesSync(base64Decode(b64Data.group(1)!));
|
||||
}
|
||||
}
|
||||
jizdenky.add(cd);
|
||||
}
|
||||
return jizdenky;
|
||||
}
|
||||
|
@ -138,10 +172,18 @@ class CDJizdenka implements Jizdenka {
|
|||
@JsonKey(name: "serviceClass")
|
||||
final Class trida;
|
||||
|
||||
@JsonKey(name: "aztecImageUrl")
|
||||
final String qrUrl;
|
||||
|
||||
@override
|
||||
@JsonKey(name: "transactionCode")
|
||||
final String id;
|
||||
|
||||
factory CDJizdenka.fromJson(Map<String, dynamic> json) =>
|
||||
_$CDJizdenkaFromJson(json);
|
||||
|
||||
/// Connect the generated [_$PersonToJson] function to the `toJson` method.
|
||||
@override
|
||||
Map<String, dynamic> toJson() => _$CDJizdenkaToJson(this);
|
||||
|
||||
const CDJizdenka(
|
||||
|
@ -153,7 +195,9 @@ class CDJizdenka implements Jizdenka {
|
|||
required this.zeStanice,
|
||||
required this.vracena,
|
||||
required this.cena,
|
||||
required this.trida});
|
||||
required this.trida,
|
||||
required this.qrUrl,
|
||||
required this.id});
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
|
|
|
@ -19,7 +19,9 @@ CDJizdenka _$CDJizdenkaFromJson(Map<String, dynamic> json) => CDJizdenka(
|
|||
zeStanice: json['stationFrom'] as String,
|
||||
vracena: json['isRefunded'] as bool,
|
||||
cena: const _CenaPrevodnik().fromJson(json['price'] as int),
|
||||
trida: json['serviceClass'],
|
||||
trida: $enumDecode(_$ClassEnumMap, json['serviceClass']),
|
||||
qrUrl: json['aztecImageUrl'] as String,
|
||||
id: json['transactionCode'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$CDJizdenkaToJson(CDJizdenka instance) =>
|
||||
|
@ -32,7 +34,15 @@ Map<String, dynamic> _$CDJizdenkaToJson(CDJizdenka instance) =>
|
|||
'stationFrom': instance.zeStanice,
|
||||
'isRefunded': instance.vracena,
|
||||
'price': const _CenaPrevodnik().toJson(instance.cena),
|
||||
'serviceClass': instance.trida,
|
||||
'serviceClass': _$ClassEnumMap[instance.trida]!,
|
||||
'aztecImageUrl': instance.qrUrl,
|
||||
'transactionCode': instance.id,
|
||||
};
|
||||
|
||||
const _$ClassEnumMap = {
|
||||
Class.class2: 'Class2',
|
||||
Class.class1: 'Class1',
|
||||
Class.business: 'Business',
|
||||
};
|
||||
|
||||
CDSpoj _$CDSpojFromJson(Map<String, dynamic> json) => CDSpoj(
|
||||
|
|
|
@ -1,6 +1,28 @@
|
|||
import 'package:json_annotation/json_annotation.dart';
|
||||
|
||||
enum Dopravce { ceskeDrahy, regioJet }
|
||||
/*
|
||||
Copyright (C) 2022 Matyáš Caras
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
enum Dopravce {
|
||||
@JsonValue("CESKEDRAHY")
|
||||
ceskeDrahy,
|
||||
@JsonValue("REGIOJET")
|
||||
regioJet
|
||||
}
|
||||
|
||||
abstract class Jizdenka {
|
||||
final Dopravce dopravce;
|
||||
|
@ -12,6 +34,7 @@ abstract class Jizdenka {
|
|||
final String jmeno;
|
||||
final double cena;
|
||||
final Class trida;
|
||||
final String id;
|
||||
const Jizdenka(
|
||||
{required this.jmeno,
|
||||
required this.dopravce,
|
||||
|
@ -21,7 +44,13 @@ abstract class Jizdenka {
|
|||
required this.zeStanice,
|
||||
required this.doStanice,
|
||||
required this.cena,
|
||||
required this.trida});
|
||||
required this.trida,
|
||||
required this.id});
|
||||
|
||||
factory Jizdenka.fromJson(Map<String, dynamic> json) =>
|
||||
throw UnimplementedError();
|
||||
|
||||
Map<String, dynamic> toJson() => throw UnimplementedError();
|
||||
}
|
||||
|
||||
abstract class Spoj {
|
||||
|
|
92
lib/helper/bar.dart
Normal file
92
lib/helper/bar.dart
Normal file
|
@ -0,0 +1,92 @@
|
|||
import 'package:cvak/okna/domu.dart';
|
||||
import 'package:cvak/okna/nahrat.dart';
|
||||
import 'package:cvak/okna/nastaveni.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
/*
|
||||
Copyright (C) 2022 Matyáš Caras
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
AppBar bar(context, {String nadpis = "Domů"}) => AppBar(
|
||||
title: Text(nadpis),
|
||||
actions: [
|
||||
PopupMenuButton<String>(
|
||||
itemBuilder: (c) => {'Nastavení', 'O Aplikaci'}
|
||||
.map((e) => PopupMenuItem<String>(value: e, child: Text(e)))
|
||||
.toList(),
|
||||
onSelected: ((value) async {
|
||||
PackageInfo packageInfo = await PackageInfo.fromPlatform();
|
||||
switch (value) {
|
||||
case "Nastavení":
|
||||
Navigator.of(context)
|
||||
.push(MaterialPageRoute(builder: (c) => const Nastaveni()));
|
||||
break;
|
||||
case "O Aplikaci":
|
||||
showAboutDialog(
|
||||
context: context,
|
||||
applicationName: "Cvak",
|
||||
applicationLegalese:
|
||||
"Copyright ©️ 2022 Matyáš Caras\nVydáno pod licencí GNU GPLv3",
|
||||
applicationVersion: packageInfo.version,
|
||||
children: [
|
||||
TextButton(
|
||||
child: const Text("Zdrojový kód"),
|
||||
onPressed: () => launchUrl(
|
||||
Uri.parse("https://git.mnau.xyz/hernik/cvak"),
|
||||
mode: LaunchMode.externalApplication),
|
||||
)
|
||||
]);
|
||||
break;
|
||||
}
|
||||
}),
|
||||
)
|
||||
],
|
||||
);
|
||||
|
||||
Drawer drawer(int selected, BuildContext context) => Drawer(
|
||||
child: ListView(
|
||||
padding: EdgeInsets.zero,
|
||||
children: [
|
||||
const DrawerHeader(child: Text("Cvak")),
|
||||
ListTile(
|
||||
title: const Text("Domů"),
|
||||
leading: const Icon(Icons.home),
|
||||
selected: selected == 1,
|
||||
onTap: () => (selected == 1)
|
||||
? Navigator.of(context).pop()
|
||||
: Navigator.of(context).pushReplacement(MaterialPageRoute(
|
||||
builder: (c) => const DomovskaObrazovka())),
|
||||
),
|
||||
ListTile(
|
||||
title: const Text("Nová jízdenka"),
|
||||
leading: const Icon(Icons.new_label),
|
||||
selected: selected == 2,
|
||||
onTap: () => Navigator.of(context).pop(),
|
||||
),
|
||||
ListTile(
|
||||
title: const Text("Nahrát jízdenky"),
|
||||
leading: const Icon(Icons.download),
|
||||
selected: selected == 3,
|
||||
onTap: () => (selected == 3)
|
||||
? Navigator.of(context).pop()
|
||||
: Navigator.of(context).push(
|
||||
MaterialPageRoute(builder: (c) => const NahratJizdenku())),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
54
lib/helper/manager.dart
Normal file
54
lib/helper/manager.dart
Normal file
|
@ -0,0 +1,54 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:cvak/api/ceskedrahy.dart';
|
||||
import 'package:cvak/api/jizdenka.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
/*
|
||||
Copyright (C) 2022 Matyáš Caras
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
class ManazerJizdenek {
|
||||
static void ulozitJizdenku(Jizdenka j) {
|
||||
var typ = "";
|
||||
if (j is CDJizdenka) {
|
||||
typ = "cd";
|
||||
} else {
|
||||
typ = "local";
|
||||
}
|
||||
var data = {
|
||||
"type": typ,
|
||||
"data": {...j.toJson()}
|
||||
};
|
||||
getApplicationDocumentsDirectory().then((d) =>
|
||||
File("${d.path}/j_${j.id}.json").writeAsStringSync(jsonEncode(data)));
|
||||
}
|
||||
|
||||
static List<Jizdenka> nahratJizdenky() {
|
||||
var jizdenky = <Jizdenka>[];
|
||||
getApplicationDocumentsDirectory().then((d) {
|
||||
for (var file in Directory(d.path).listSync()) {
|
||||
if (!file.path.endsWith(".json")) return;
|
||||
var data = jsonDecode((file as File).readAsStringSync());
|
||||
if (data["type"] == "cd") {
|
||||
jizdenky.add(CDJizdenka.fromJson(data["data"]));
|
||||
}
|
||||
}
|
||||
});
|
||||
return jizdenky;
|
||||
}
|
||||
}
|
10
lib/helper/theme.dart
Normal file
10
lib/helper/theme.dart
Normal file
|
@ -0,0 +1,10 @@
|
|||
import 'package:flutter/rendering.dart';
|
||||
|
||||
class Vzhled {
|
||||
static const TextStyle nadpis =
|
||||
TextStyle(fontSize: 28, fontWeight: FontWeight.bold);
|
||||
static const TextStyle nadpisJizdenka =
|
||||
TextStyle(fontSize: 20, fontWeight: FontWeight.bold);
|
||||
static const Color okColor = Color.fromARGB(255, 106, 207, 110);
|
||||
static const Color errorColor = Color.fromARGB(255, 207, 106, 106);
|
||||
}
|
|
@ -1,7 +1,30 @@
|
|||
import 'package:cvak/okna/domu.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
void main() {
|
||||
/*
|
||||
Copyright (C) 2022 Matyáš Caras
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
void main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
var p = await SharedPreferences.getInstance();
|
||||
if (p.getString("dlpath") == null) {
|
||||
p.setString("dlpath", (await getApplicationDocumentsDirectory()).path);
|
||||
}
|
||||
runApp(const MyApp());
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,27 @@
|
|||
import 'package:cvak/okna/login.dart';
|
||||
import 'package:cvak/helper/bar.dart';
|
||||
import 'package:cvak/helper/manager.dart';
|
||||
import 'package:cvak/helper/theme.dart';
|
||||
import 'package:device_info_plus/device_info_plus.dart';
|
||||
import 'package:flash/flash.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
|
||||
/*
|
||||
Copyright (C) 2022 Matyáš Caras
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
class DomovskaObrazovka extends StatefulWidget {
|
||||
const DomovskaObrazovka({super.key});
|
||||
|
@ -9,19 +31,87 @@ class DomovskaObrazovka extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _DomovskaObrazovkaState extends State<DomovskaObrazovka> {
|
||||
var content = <Widget>[const CircularProgressIndicator()];
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
nacistJizdenky();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: bar(context),
|
||||
drawer: drawer(1, context),
|
||||
body: Center(
|
||||
child: SizedBox(
|
||||
child: Column(children: [
|
||||
TextButton(
|
||||
onPressed: (() => Navigator.of(context).push(
|
||||
MaterialPageRoute(builder: (c) => const LoginStranka()))),
|
||||
child: const Text("Přihlásit"))
|
||||
child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [
|
||||
const Text(
|
||||
"Vaše jízdenky",
|
||||
textAlign: TextAlign.center,
|
||||
style: Vzhled.nadpis,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 15,
|
||||
),
|
||||
...content
|
||||
]),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void nacistJizdenky() async {
|
||||
// permissions
|
||||
var androidInfo = await DeviceInfoPlugin().androidInfo;
|
||||
Map<Permission, PermissionStatus> status;
|
||||
if (androidInfo.version.sdkInt <= 32) {
|
||||
status = await [
|
||||
Permission.storage,
|
||||
].request();
|
||||
} else {
|
||||
status = await [Permission.photos].request();
|
||||
}
|
||||
|
||||
var allAccepted = true;
|
||||
status.forEach((permission, status) {
|
||||
if (status != PermissionStatus.granted) {
|
||||
allAccepted = false;
|
||||
}
|
||||
});
|
||||
|
||||
if (!allAccepted) {
|
||||
showFlash(
|
||||
context: context,
|
||||
duration: const Duration(seconds: 5),
|
||||
builder: (context, controller) => Flash.dialog(
|
||||
controller: controller,
|
||||
backgroundColor: Vzhled.errorColor,
|
||||
child: const Text(
|
||||
"Aplikace nedokáže bez oprávnění k úložišti pracovat!")));
|
||||
setState(() {
|
||||
content = [const Text("Chybí oprávnění!")];
|
||||
});
|
||||
return;
|
||||
}
|
||||
// permissions end
|
||||
|
||||
var j = ManazerJizdenek.nahratJizdenky();
|
||||
if (j.isEmpty) {
|
||||
setState(() {
|
||||
content = [const Text("Žádné uložené jízdenky :(")];
|
||||
});
|
||||
} else {
|
||||
content = [];
|
||||
for (var jizdenka in j) {
|
||||
content.add(Column(
|
||||
children: [
|
||||
Text("${jizdenka.zeStanice} - ${jizdenka.doStanice}",
|
||||
style: Vzhled.nadpisJizdenka)
|
||||
],
|
||||
));
|
||||
}
|
||||
setState(() {});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
import 'package:cvak/api/ceskedrahy.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class LoginStranka extends StatefulWidget {
|
||||
const LoginStranka({super.key});
|
||||
|
||||
@override
|
||||
State<LoginStranka> createState() => _LoginStrankaState();
|
||||
}
|
||||
|
||||
class _LoginStrankaState extends State<LoginStranka> {
|
||||
final _mailManager = TextEditingController();
|
||||
final _passManager = TextEditingController();
|
||||
var rememberMe = false;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Center(
|
||||
child: Form(
|
||||
child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(hintText: "E-mail"),
|
||||
controller: _mailManager,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 15,
|
||||
),
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(hintText: "Heslo"),
|
||||
controller: _passManager,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Row(children: [
|
||||
Checkbox(
|
||||
value: rememberMe,
|
||||
onChanged: (v) {
|
||||
rememberMe = v ?? false;
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
const Text("Zapamatovat si mě")
|
||||
]),
|
||||
const SizedBox(height: 10),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
var d = CeskeDrahy();
|
||||
// otestovat přihlášení
|
||||
try {
|
||||
await d.logIn(_mailManager.text, _passManager.text);
|
||||
} catch (e) {
|
||||
ScaffoldMessenger.of(context).clearSnackBars();
|
||||
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
|
||||
content: Text(
|
||||
"Nepodařilo se přihlásit, zkontrolujte údaje a připojení."),
|
||||
duration: Duration(seconds: 5),
|
||||
));
|
||||
}
|
||||
},
|
||||
child: const Text("Přihlásit se"))
|
||||
]),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
241
lib/okna/nahrat.dart
Normal file
241
lib/okna/nahrat.dart
Normal file
|
@ -0,0 +1,241 @@
|
|||
import 'package:cvak/helper/bar.dart';
|
||||
import 'package:cvak/helper/manager.dart';
|
||||
import 'package:cvak/helper/theme.dart';
|
||||
import 'package:flash/flash.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import '../api/ceskedrahy.dart';
|
||||
|
||||
/*
|
||||
Copyright (C) 2022 Matyáš Caras
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
class NahratJizdenku extends StatefulWidget {
|
||||
const NahratJizdenku({super.key});
|
||||
|
||||
@override
|
||||
State<NahratJizdenku> createState() => _NahratJizdenkuState();
|
||||
}
|
||||
|
||||
class _NahratJizdenkuState extends State<NahratJizdenku> {
|
||||
final supported = ["České dráhy"];
|
||||
var selected = "České dráhy";
|
||||
var content = [];
|
||||
|
||||
final _mailManager = TextEditingController();
|
||||
final _passManager = TextEditingController();
|
||||
var rememberMe = false;
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
content = [
|
||||
Form(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(hintText: "E-mail"),
|
||||
controller: _mailManager,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(
|
||||
RegExp(r'[a-zA-Z\-_0-9\.]+@{0,1}[a-zA-Z\-_0-9\.]{0,}'))
|
||||
],
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 15,
|
||||
),
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(hintText: "Heslo"),
|
||||
obscureText: true,
|
||||
controller: _passManager,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Row(children: [
|
||||
Checkbox(
|
||||
value: rememberMe,
|
||||
onChanged: (v) {
|
||||
rememberMe = v ?? false;
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
const Text("Zapamatovat si mě")
|
||||
]),
|
||||
const SizedBox(height: 10),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
var d = CeskeDrahy();
|
||||
// otestovat přihlášení
|
||||
try {
|
||||
await d.logIn(_mailManager.text, _passManager.text);
|
||||
for (var jizdenka in await d.ziskatJizdenky()) {
|
||||
ManazerJizdenek.ulozitJizdenku(jizdenka);
|
||||
}
|
||||
if (!mounted) return;
|
||||
ScaffoldMessenger.of(context).clearSnackBars();
|
||||
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
|
||||
content: Text("Jízdenky úspěšně uloženy."),
|
||||
duration: Duration(seconds: 5),
|
||||
));
|
||||
} catch (e) {
|
||||
ScaffoldMessenger.of(context).clearSnackBars();
|
||||
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
|
||||
content: Text(
|
||||
"Nepodařilo se přihlásit, zkontrolujte údaje a připojení."),
|
||||
duration: Duration(seconds: 5),
|
||||
));
|
||||
}
|
||||
},
|
||||
child: const Text("Přihlásit se"))
|
||||
],
|
||||
),
|
||||
),
|
||||
];
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
drawer: drawer(3, context),
|
||||
appBar: bar(context, nadpis: "Nahrát jízdenku"),
|
||||
body: Center(
|
||||
child: SizedBox(
|
||||
width: MediaQuery.of(context).size.width * 0.9,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Text(
|
||||
"Nahrát jízdenku z externího zdroje",
|
||||
textAlign: TextAlign.center,
|
||||
style: Vzhled.nadpis,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
DropdownButton(
|
||||
value: selected,
|
||||
items: List.generate(
|
||||
supported.length,
|
||||
(i) => DropdownMenuItem(
|
||||
value: supported[i],
|
||||
child: Text(supported[i]),
|
||||
)),
|
||||
onChanged: (v) {
|
||||
if (v == null) return;
|
||||
selected = v;
|
||||
if (v == "České dráhý") {
|
||||
content = [
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
TextField(
|
||||
controller: _mailManager,
|
||||
decoration:
|
||||
const InputDecoration(hintText: "E-mail"),
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(RegExp(
|
||||
r'[a-zA-Z\-_0-9\.]+@{0,1}[a-zA-Z\-_0-9\.]{0,}'))
|
||||
],
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 15,
|
||||
),
|
||||
TextField(
|
||||
controller: _passManager,
|
||||
decoration: const InputDecoration(
|
||||
hintText: "Heslo",
|
||||
),
|
||||
obscureText: true,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Row(children: [
|
||||
Checkbox(
|
||||
value: rememberMe,
|
||||
onChanged: (v) {
|
||||
rememberMe = v ?? false;
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
const Text("Zapamatovat si mě")
|
||||
]),
|
||||
const SizedBox(height: 10),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
var d = CeskeDrahy();
|
||||
// otestovat přihlášení
|
||||
try {
|
||||
await d.logIn(
|
||||
_mailManager.text, _passManager.text);
|
||||
for (var jizdenka
|
||||
in await d.ziskatJizdenky()) {
|
||||
ManazerJizdenek.ulozitJizdenku(jizdenka);
|
||||
}
|
||||
if (!mounted) return;
|
||||
showFlash(
|
||||
duration: const Duration(seconds: 3),
|
||||
context: context,
|
||||
builder: ((context, controller) =>
|
||||
Flash.bar(
|
||||
controller: controller,
|
||||
backgroundColor: Vzhled.okColor,
|
||||
child: const Text(
|
||||
"Jízdenky úspěšně staženy"),
|
||||
)),
|
||||
);
|
||||
} catch (e) {
|
||||
showFlash(
|
||||
duration: const Duration(seconds: 5),
|
||||
context: context,
|
||||
builder: ((context, controller) =>
|
||||
Flash.bar(
|
||||
controller: controller,
|
||||
backgroundColor: Vzhled.errorColor,
|
||||
child: const Text(
|
||||
"Chyba při stahování, zkontrolujte údaje a připojení"),
|
||||
)),
|
||||
);
|
||||
}
|
||||
},
|
||||
child: const Text("Přihlásit se"))
|
||||
],
|
||||
),
|
||||
];
|
||||
}
|
||||
setState(() {});
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
...content
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
88
lib/okna/nastaveni.dart
Normal file
88
lib/okna/nastaveni.dart
Normal file
|
@ -0,0 +1,88 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:cvak/helper/bar.dart';
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
class Nastaveni extends StatefulWidget {
|
||||
const Nastaveni({super.key});
|
||||
|
||||
@override
|
||||
State<Nastaveni> createState() => _NastaveniState();
|
||||
}
|
||||
|
||||
class _NastaveniState extends State<Nastaveni> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
nacistNastaveni();
|
||||
}
|
||||
|
||||
var content = <Widget>[const CircularProgressIndicator()];
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: bar(context, nadpis: "Nastavení"),
|
||||
body: Center(
|
||||
child: SizedBox(
|
||||
width: MediaQuery.of(context).size.width * 0.9,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: content,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void nacistNastaveni() async {
|
||||
content = [];
|
||||
SharedPreferences p = await SharedPreferences.getInstance();
|
||||
var dd = (p.getString("dlpath")!).split("/");
|
||||
content.add(Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Text(
|
||||
"Složka s uloženými QR kódy jízdenek:",
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Text(dd[dd.length - 1]),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
String? e = await FilePicker.platform.getDirectoryPath();
|
||||
if (e != null && e != "/") {
|
||||
p.setString("dlpath", e);
|
||||
nacistNastaveni();
|
||||
}
|
||||
},
|
||||
child: const Text("Změnit")),
|
||||
const SizedBox(
|
||||
width: 5,
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
p.setString(
|
||||
"dlpath", (await getApplicationDocumentsDirectory()).path);
|
||||
nacistNastaveni();
|
||||
},
|
||||
child: const Text("Výchozí"),
|
||||
),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
/*TODO: dark theme */
|
||||
height: 4,
|
||||
)
|
||||
],
|
||||
));
|
||||
setState(() {});
|
||||
}
|
||||
}
|
295
pubspec.lock
295
pubspec.lock
|
@ -155,6 +155,27 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.2.4"
|
||||
device_info_plus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: device_info_plus
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "8.0.0"
|
||||
device_info_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: device_info_plus_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "7.0.0"
|
||||
ffi:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ffi
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -162,6 +183,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.1.4"
|
||||
file_picker:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: file_picker
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "5.2.3"
|
||||
fixnum:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -169,6 +197,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
flash:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flash
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.5"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
|
@ -188,6 +223,18 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
flutter_plugin_android_lifecycle:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_plugin_android_lifecycle
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.7"
|
||||
flutter_web_plugins:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
frontend_server_client:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -250,7 +297,7 @@ packages:
|
|||
name: js
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.6.5"
|
||||
version: "0.6.4"
|
||||
json_annotation:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -314,6 +361,20 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
package_info_plus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: package_info_plus
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.2"
|
||||
package_info_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_info_plus_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -321,6 +382,90 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.2"
|
||||
path_provider:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: path_provider
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.11"
|
||||
path_provider_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_android
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.22"
|
||||
path_provider_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_ios
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.11"
|
||||
path_provider_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_linux
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.7"
|
||||
path_provider_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_macos
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.6"
|
||||
path_provider_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.5"
|
||||
path_provider_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_windows
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.3"
|
||||
permission_handler:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: permission_handler
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "10.2.0"
|
||||
permission_handler_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_android
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "10.2.0"
|
||||
permission_handler_apple:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_apple
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "9.0.7"
|
||||
permission_handler_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.9.0"
|
||||
permission_handler_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_windows
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.2"
|
||||
petitparser:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -328,6 +473,20 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "5.1.0"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: platform
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.1.0"
|
||||
plugin_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: plugin_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.3"
|
||||
pointycastle:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -342,6 +501,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.5.1"
|
||||
process:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: process
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.2.4"
|
||||
pub_semver:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -356,6 +522,62 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
shared_preferences:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: shared_preferences
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.15"
|
||||
shared_preferences_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_android
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.14"
|
||||
shared_preferences_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_ios
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
shared_preferences_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_linux
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
shared_preferences_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_macos
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.4"
|
||||
shared_preferences_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
shared_preferences_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_web
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.4"
|
||||
shared_preferences_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_windows
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
shelf:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -445,6 +667,62 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.1"
|
||||
url_launcher:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: url_launcher
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.1.7"
|
||||
url_launcher_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_android
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.0.22"
|
||||
url_launcher_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_ios
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.0.17"
|
||||
url_launcher_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_linux
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
url_launcher_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_macos
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
url_launcher_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
url_launcher_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_web
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.13"
|
||||
url_launcher_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_windows
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -466,6 +744,20 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.2.0"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.1.2"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xdg_directories
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.2.0+2"
|
||||
xml:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -482,3 +774,4 @@ packages:
|
|||
version: "3.1.1"
|
||||
sdks:
|
||||
dart: ">=2.18.4 <3.0.0"
|
||||
flutter: ">=3.0.0"
|
||||
|
|
|
@ -15,6 +15,14 @@ dependencies:
|
|||
json_serializable: ^6.5.4
|
||||
cupertino_icons: ^1.0.2
|
||||
http: ^0.13.5
|
||||
path_provider: ^2.0.11
|
||||
file_picker: ^5.2.3
|
||||
shared_preferences: ^2.0.15
|
||||
flash: ^2.0.5
|
||||
package_info_plus: ^3.0.2
|
||||
url_launcher: ^6.1.7
|
||||
permission_handler: ^10.2.0
|
||||
device_info_plus: ^8.0.0
|
||||
|
||||
dev_dependencies:
|
||||
build_runner: ^2.3.2
|
||||
|
|
Loading…
Reference in a new issue