Compare commits
34 Commits
157 changed files with 13479 additions and 2337 deletions
@ -1,10 +1,30 @@ |
|||||||
# This file tracks properties of this Flutter project. |
# This file tracks properties of this Flutter project. |
||||||
# Used by Flutter tool to assess capabilities and perform upgrades etc. |
# Used by Flutter tool to assess capabilities and perform upgrades etc. |
||||||
# |
# |
||||||
# This file should be version controlled and should not be manually edited. |
# This file should be version controlled. |
||||||
|
|
||||||
version: |
version: |
||||||
revision: b712a172f9694745f50505c93340883493b505e5 |
revision: 52b3dc25f6471c27b2144594abb11c741cb88f57 |
||||||
channel: stable |
channel: stable |
||||||
|
|
||||||
project_type: app |
project_type: app |
||||||
|
|
||||||
|
# Tracks metadata for the flutter migrate command |
||||||
|
migration: |
||||||
|
platforms: |
||||||
|
- platform: root |
||||||
|
create_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57 |
||||||
|
base_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57 |
||||||
|
- platform: windows |
||||||
|
create_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57 |
||||||
|
base_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57 |
||||||
|
|
||||||
|
# User provided section |
||||||
|
|
||||||
|
# List of Local paths (relative to this file) that should be |
||||||
|
# ignored by the migrate tool. |
||||||
|
# |
||||||
|
# Files that are not part of the templates will be ignored by default. |
||||||
|
unmanaged_files: |
||||||
|
- 'lib/main.dart' |
||||||
|
- 'ios/Runner.xcodeproj/project.pbxproj' |
||||||
|
@ -1,65 +0,0 @@ |
|||||||
v2.6.0 |
|
||||||
Added ability to view yesterday data for trains that didn't depart yet today. |
|
||||||
Fixed iOS status bar color. |
|
||||||
|
|
||||||
v2.5.0 |
|
||||||
Initial arrivals/departures support |
|
||||||
|
|
||||||
v2.4.1 |
|
||||||
Fixed DateTime (UTC -> local) |
|
||||||
|
|
||||||
v2.4.0 |
|
||||||
Moved to api v2 |
|
||||||
Added support for any train number, including train numbers starting with 0 |
|
||||||
|
|
||||||
v2.3.1 |
|
||||||
Fixed badge background when arrival is known but not departure |
|
||||||
|
|
||||||
v2.3.0 |
|
||||||
Added pull to refresh |
|
||||||
|
|
||||||
v2.2.0 |
|
||||||
Added refresh button on error |
|
||||||
|
|
||||||
v2.1.1 |
|
||||||
Fixed Android build |
|
||||||
Switched versioning format |
|
||||||
|
|
||||||
v2.0.7 |
|
||||||
Switched from WebView to API |
|
||||||
Updated app to latest Flutter |
|
||||||
Tweaks |
|
||||||
|
|
||||||
v2.0.6 |
|
||||||
Brought feature parity with iOS _(except for v2.0.2, which is iOS specific)_. |
|
||||||
|
|
||||||
|
|
||||||
v2.0.5 |
|
||||||
- increased font weight on iOS |
|
||||||
- added support for system bolt font request on iOS |
|
||||||
|
|
||||||
v2.0.4 |
|
||||||
- added original time in case of delay for iOS |
|
||||||
+ will be for Android soon |
|
||||||
+ in case there is a delay, the original time will be shown with |
|
||||||
a stroke through it and the new time will be shown below |
|
||||||
|
|
||||||
v2.0.3 |
|
||||||
- added km badge colour for iOS |
|
||||||
+ will be added for Android soon |
|
||||||
+ green for being on time |
|
||||||
+ yellow for a non planned stop |
|
||||||
+ red for a delay |
|
||||||
|
|
||||||
v2.0.2 |
|
||||||
- added translucency to the navigation bar on iOS |
|
||||||
|
|
||||||
v2.0.1 |
|
||||||
- added a little separation between the arrows and the text in the stations list |
|
||||||
- fine tuned the positioning, centering items when they are supposed to be centered |
|
||||||
- changed text from "sosește" to "sosire", in order to match "plecare" |
|
||||||
|
|
||||||
v2.0.0 |
|
||||||
Rewritten! |
|
||||||
- separate UI for Android and iOS |
|
||||||
- uses WebView to get data on device instead of relying on server |
|
@ -0,0 +1,122 @@ |
|||||||
|
v2.7.11 |
||||||
|
Add support for IC trains. |
||||||
|
Allow choosing displayed timezone. |
||||||
|
Show notes about wagon detachment, receival, or train number changes. |
||||||
|
Use system accent color if available. |
||||||
|
Use API v3. |
||||||
|
|
||||||
|
v2.7.10 |
||||||
|
Add about page to Fluent UI. |
||||||
|
Add settings page, allowing changing between UIs. |
||||||
|
Add touch scrolling on Linux. |
||||||
|
|
||||||
|
v2.7.9 |
||||||
|
Add Fluent UI for Windows and Linux. |
||||||
|
Add split view in landscape when viewing a train. |
||||||
|
Add error handling and auto refresh when viewing a station's arrivals/departures. |
||||||
|
General code fixes and migration (freezed, riverpod). |
||||||
|
|
||||||
|
v2.7.8 |
||||||
|
Added cancelled trains in departures/arrivals board. |
||||||
|
Selecting train in departures/arrivels board chooses appropriate departure date. |
||||||
|
Temporarily switched all platforms to Material. |
||||||
|
|
||||||
|
v2.7.7 |
||||||
|
Improved departures/arrivals page: |
||||||
|
- badge for platform (due to limitations in data, platform in only known when a train arrives/departs) |
||||||
|
- time deviations shown (delays or arriving early) |
||||||
|
Moved to API v3 for station data. |
||||||
|
|
||||||
|
v2.7.6 |
||||||
|
Transitioned to Material 3. |
||||||
|
Redesigned main page on Material. |
||||||
|
On Android (Material), tapping station card in train information screen opens departures/arrivals board. |
||||||
|
Added past tense to trains already arrived/departed. |
||||||
|
Fixed download button on Android. |
||||||
|
|
||||||
|
v2.7.5 |
||||||
|
Added about page and in-app changelog. |
||||||
|
On Android, added download buttons. |
||||||
|
|
||||||
|
v2.7.4 |
||||||
|
Addressed Android 12 component exporting rule. |
||||||
|
See: https://developer.android.com/about/versions/12/behavior-changes-12#exported |
||||||
|
|
||||||
|
v2.7.3 |
||||||
|
Added Android APK signing. |
||||||
|
|
||||||
|
v2.7.2 |
||||||
|
Fixed alignment of station names in train screen. |
||||||
|
|
||||||
|
v2.7.1 |
||||||
|
Switched train suggestions list from hardcoded data to server data. |
||||||
|
Added Linux build files. |
||||||
|
|
||||||
|
v2.7.0 |
||||||
|
Changed domain name for server providing the data. |
||||||
|
Changed bundle name accordingly. |
||||||
|
|
||||||
|
v2.6.0 |
||||||
|
Added ability to view yesterday data for trains that didn't depart yet today. |
||||||
|
Fixed iOS status bar color. |
||||||
|
|
||||||
|
v2.5.0 |
||||||
|
Initial arrivals/departures support |
||||||
|
|
||||||
|
v2.4.1 |
||||||
|
Fixed DateTime (UTC -> local) |
||||||
|
|
||||||
|
v2.4.0 |
||||||
|
Moved to api v2 |
||||||
|
Added support for any train number, including train numbers starting with 0 |
||||||
|
|
||||||
|
v2.3.1 |
||||||
|
Fixed badge background when arrival is known but not departure |
||||||
|
|
||||||
|
v2.3.0 |
||||||
|
Added pull to refresh |
||||||
|
|
||||||
|
v2.2.0 |
||||||
|
Added refresh button on error |
||||||
|
|
||||||
|
v2.1.1 |
||||||
|
Fixed Android build |
||||||
|
Switched versioning format |
||||||
|
|
||||||
|
v2.0.7 |
||||||
|
Switched from WebView to API |
||||||
|
Updated app to latest Flutter |
||||||
|
Tweaks |
||||||
|
|
||||||
|
v2.0.6 |
||||||
|
Brought feature parity with iOS _(except for v2.0.2, which is iOS specific)_. |
||||||
|
|
||||||
|
v2.0.5 |
||||||
|
- increased font weight on iOS |
||||||
|
- added support for system bolt font request on iOS |
||||||
|
|
||||||
|
v2.0.4 |
||||||
|
- added original time in case of delay for iOS |
||||||
|
+ will be for Android soon |
||||||
|
+ in case there is a delay, the original time will be shown with |
||||||
|
a stroke through it and the new time will be shown below |
||||||
|
|
||||||
|
v2.0.3 |
||||||
|
- added km badge colour for iOS |
||||||
|
+ will be added for Android soon |
||||||
|
+ green for being on time |
||||||
|
+ yellow for a non planned stop |
||||||
|
+ red for a delay |
||||||
|
|
||||||
|
v2.0.2 |
||||||
|
- added translucency to the navigation bar on iOS |
||||||
|
|
||||||
|
v2.0.1 |
||||||
|
- added a little separation between the arrows and the text in the stations list |
||||||
|
- fine tuned the positioning, centering items when they are supposed to be centered |
||||||
|
- changed text from "sosește" to "sosire", in order to match "plecare" |
||||||
|
|
||||||
|
v2.0.0 |
||||||
|
Rewritten! |
||||||
|
- separate UI for Android and iOS |
||||||
|
- uses WebView to get data on device instead of relying on server |
@ -1 +0,0 @@ |
|||||||
{"short_name":"ATC","operator":"Astra Trans Carpatic","data_export":"20171212","valabil":{"de_la":"20171210","pana_la":"20181208"},"versiune":"1","trenuri":[{"rang":"IR","numar":"15510","numar_intern":15510},{"rang":"IR","numar":"15511","numar_intern":15511},{"rang":"IR","numar":"15512","numar_intern":15512},{"rang":"IR","numar":"15513*","numar_intern":15513},{"rang":"IR","numar":"15513","numar_intern":15513},{"rang":"IR","numar":"15514","numar_intern":15514},{"rang":"IR","numar":"15514","numar_intern":15514},{"rang":"IR","numar":"15516","numar_intern":15516},{"rang":"IR","numar":"15520","numar_intern":15520},{"rang":"IR","numar":"15521*","numar_intern":15521},{"rang":"IR","numar":"15521","numar_intern":15521},{"rang":"IR","numar":"15522","numar_intern":15522},{"rang":"IR","numar":"15522","numar_intern":15522},{"rang":"IR","numar":"15523","numar_intern":15523},{"rang":"IR","numar":"15523","numar_intern":15523},{"rang":"IR","numar":"15527","numar_intern":15527},{"rang":"IR","numar":"15528","numar_intern":15528},{"rang":"IR","numar":"15529","numar_intern":15529},{"rang":"IR","numar":"15531","numar_intern":15531},{"rang":"IR","numar":"15532","numar_intern":15532},{"rang":"IR","numar":"15533","numar_intern":15533},{"rang":"IR","numar":"15533e","numar_intern":15533},{"rang":"IR","numar":"15534","numar_intern":15534},{"rang":"IR","numar":"15535","numar_intern":15535},{"rang":"IR","numar":"15536","numar_intern":15536},{"rang":"IR","numar":"15537-2","numar_intern":15537},{"rang":"IR","numar":"15538","numar_intern":15538},{"rang":"IR","numar":"15540","numar_intern":15540},{"rang":"IR","numar":"15541","numar_intern":15541},{"rang":"IR","numar":"15541","numar_intern":15541},{"rang":"IR","numar":"15542","numar_intern":15542},{"rang":"IR","numar":"15542","numar_intern":15542},{"rang":"IR","numar":"15543","numar_intern":15543},{"rang":"IR","numar":"15544","numar_intern":15544},{"rang":"IR","numar":"15545","numar_intern":15545},{"rang":"IR","numar":"15546*","numar_intern":15546},{"rang":"IR","numar":"15546","numar_intern":15546},{"rang":"IR","numar":"15547","numar_intern":15547},{"rang":"IR","numar":"15548","numar_intern":15548},{"rang":"IR","numar":"15549*","numar_intern":15549},{"rang":"IR","numar":"15549b","numar_intern":15549},{"rang":"IR","numar":"15551","numar_intern":15551},{"rang":"IR","numar":"15552","numar_intern":15552},{"rang":"IR","numar":"15553","numar_intern":15553},{"rang":"IR","numar":"15581","numar_intern":15581},{"rang":"IR","numar":"15582","numar_intern":15582},{"rang":"IR","numar":"15582***","numar_intern":15582},{"rang":"IR","numar":"15583","numar_intern":15583},{"rang":"IR","numar":"15590","numar_intern":15590},{"rang":"IR","numar":"15591","numar_intern":15591},{"rang":"IR","numar":"15592","numar_intern":15592},{"rang":"IR","numar":"15593","numar_intern":15593},{"rang":"R","numar":"*P18801","numar_intern":null},{"rang":"IR","numar":"*15546","numar_intern":null},{"rang":"R","numar":"**P18801","numar_intern":null},{"rang":"IR","numar":"*15591","numar_intern":null},{"rang":"R","numar":"**P18800","numar_intern":null},{"rang":"IR","numar":"15593","numar_intern":15593},{"rang":"IR","numar":"15594","numar_intern":15594},{"rang":"IR","numar":"15595-2","numar_intern":15595},{"rang":"R","numar":"18800","numar_intern":18800},{"rang":"R","numar":"18801","numar_intern":18801},{"rang":"IR","numar":"18826","numar_intern":18826},{"rang":"IR","numar":"18851","numar_intern":18851},{"rang":"IR","numar":"18852","numar_intern":18852}]} |
|
File diff suppressed because one or more lines are too long
@ -1,6 +0,0 @@ |
|||||||
atc.json |
|
||||||
cfr.json |
|
||||||
interregional.json |
|
||||||
rc.json |
|
||||||
st.json |
|
||||||
tfc.json |
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1 +0,0 @@ |
|||||||
{"short_name":"Softrans","operator":"Softrans S.R.L.","data_export":"20181212","valabil":{"de_la":"20181209","pana_la":"20191214"},"versiune":"1","trenuri":[{"rang":"IR","numar":"15931-2","numar_intern":15931},{"rang":"IR","numar":"15932","numar_intern":15932},{"rang":"IR","numar":"15933-2","numar_intern":15933},{"rang":"IR","numar":"15934","numar_intern":15934},{"rang":"IR","numar":"15935-2","numar_intern":15935},{"rang":"IR","numar":"15936","numar_intern":15936},{"rang":"IR","numar":"15982","numar_intern":15982},{"rang":"IR","numar":"15984","numar_intern":15984}]} |
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,34 @@ |
|||||||
|
PODS: |
||||||
|
- Flutter (1.0.0) |
||||||
|
- package_info_plus (0.4.5): |
||||||
|
- Flutter |
||||||
|
- shared_preferences_ios (0.0.1): |
||||||
|
- Flutter |
||||||
|
- url_launcher_ios (0.0.1): |
||||||
|
- Flutter |
||||||
|
|
||||||
|
DEPENDENCIES: |
||||||
|
- Flutter (from `Flutter`) |
||||||
|
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) |
||||||
|
- shared_preferences_ios (from `.symlinks/plugins/shared_preferences_ios/ios`) |
||||||
|
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) |
||||||
|
|
||||||
|
EXTERNAL SOURCES: |
||||||
|
Flutter: |
||||||
|
:path: Flutter |
||||||
|
package_info_plus: |
||||||
|
:path: ".symlinks/plugins/package_info_plus/ios" |
||||||
|
shared_preferences_ios: |
||||||
|
:path: ".symlinks/plugins/shared_preferences_ios/ios" |
||||||
|
url_launcher_ios: |
||||||
|
:path: ".symlinks/plugins/url_launcher_ios/ios" |
||||||
|
|
||||||
|
SPEC CHECKSUMS: |
||||||
|
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 |
||||||
|
package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e |
||||||
|
shared_preferences_ios: 548a61f8053b9b8a49ac19c1ffbc8b92c50d68ad |
||||||
|
url_launcher_ios: 839c58cdb4279282219f5e248c3321761ff3c4de |
||||||
|
|
||||||
|
PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3 |
||||||
|
|
||||||
|
COCOAPODS: 1.11.3 |
@ -1 +1 @@ |
|||||||
const authority = 'scraper.infotren.dcdevelop.xyz'; |
const authority = 'scraper.infotren.dcdev.ro'; |
@ -0,0 +1,18 @@ |
|||||||
|
import 'dart:convert'; |
||||||
|
|
||||||
|
import 'package:http/http.dart' as http; |
||||||
|
import 'package:info_tren/models.dart'; |
||||||
|
import 'package:info_tren/utils/iterable_extensions.dart'; |
||||||
|
|
||||||
|
Future<List<ChangelogEntry>> getRemoteReleases() async { |
||||||
|
final Uri uri = Uri.parse('https://gitea.dcdev.ro/api/v1/repos/kbruen/info_tren/releases'); |
||||||
|
final response = await http.get(uri); |
||||||
|
final json = jsonDecode(response.body) as List<dynamic>; |
||||||
|
return json.map((e) => ChangelogEntry( |
||||||
|
version: ChangelogVersion.parse(e['tag_name']), |
||||||
|
description: e['body'], |
||||||
|
apkLink: (e['assets'] as List<dynamic>).where((e) => (e['name'] as String).contains('.apk')).map((e) => Uri.parse(e['browser_download_url'] as String)).firstOrNull, |
||||||
|
linuxLink: (e['assets'] as List<dynamic>).where((e) => (e['name'] as String).contains('infotren-linux')).map((e) => Uri.parse(e['browser_download_url'] as String)).firstOrNull, |
||||||
|
windowsLink: (e['assets'] as List<dynamic>).where((e) => (e['name'] as String).contains('-win.zip')).map((e) => Uri.parse(e['browser_download_url'] as String)).firstOrNull, |
||||||
|
)).toList(); |
||||||
|
} |
@ -1,11 +1,11 @@ |
|||||||
import 'package:http/http.dart' as http; |
import 'package:http/http.dart' as http; |
||||||
import 'package:info_tren/api/common.dart'; |
import 'package:info_tren/api/common.dart'; |
||||||
import 'package:info_tren/models/train_data.dart'; |
import 'package:info_tren/models.dart'; |
||||||
|
|
||||||
Future<TrainData> getTrain(String trainNumber, {DateTime? date}) async { |
Future<TrainData> getTrain(String trainNumber, {DateTime? date}) async { |
||||||
date ??= DateTime.now(); |
date ??= DateTime.now(); |
||||||
final response = await http.get(Uri.https(authority, 'v2/train/$trainNumber', { |
final response = await http.get(Uri.https(authority, 'v3/trains/$trainNumber', { |
||||||
'date': date.toIso8601String(), |
'date': date.toUtc().toIso8601String(), |
||||||
}),); |
}),); |
||||||
return trainDataFromJson(response.body); |
return trainDataFromJson(response.body); |
||||||
} |
} |
@ -0,0 +1,11 @@ |
|||||||
|
import 'dart:convert'; |
||||||
|
|
||||||
|
import 'package:http/http.dart' as http; |
||||||
|
import 'package:info_tren/api/common.dart'; |
||||||
|
import 'package:info_tren/models.dart'; |
||||||
|
|
||||||
|
Future<List<TrainsResult>> get trains async { |
||||||
|
final result = await http.get(Uri.https(authority, 'v2/trains')); |
||||||
|
final data = jsonDecode(result.body) as List<dynamic>; |
||||||
|
return data.map((e) => TrainsResult.fromJson(e)).toList(growable: false,); |
||||||
|
} |
@ -0,0 +1,59 @@ |
|||||||
|
import 'package:flutter/cupertino.dart'; |
||||||
|
import 'package:flutter/material.dart'; |
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart'; |
||||||
|
import 'package:info_tren/components/badge/badge_cupertino.dart'; |
||||||
|
import 'package:info_tren/components/badge/badge_fluent.dart'; |
||||||
|
import 'package:info_tren/components/badge/badge_material.dart'; |
||||||
|
import 'package:info_tren/models.dart'; |
||||||
|
import 'package:info_tren/providers.dart'; |
||||||
|
|
||||||
|
class Badge extends ConsumerWidget { |
||||||
|
final String text; |
||||||
|
final String caption; |
||||||
|
final bool isNotScheduled; |
||||||
|
final bool isOnTime; |
||||||
|
final bool isDelayed; |
||||||
|
|
||||||
|
const Badge({ |
||||||
|
super.key, |
||||||
|
required this.text, |
||||||
|
required this.caption, |
||||||
|
this.isNotScheduled = false, |
||||||
|
this.isOnTime = false, |
||||||
|
this.isDelayed = false, |
||||||
|
}); |
||||||
|
|
||||||
|
@override |
||||||
|
Widget build(BuildContext context, WidgetRef ref) { |
||||||
|
final uiDesign = ref.watch(uiDesignProvider); |
||||||
|
|
||||||
|
switch (uiDesign) { |
||||||
|
case UiDesign.MATERIAL: |
||||||
|
return MaterialBadge( |
||||||
|
text: text, |
||||||
|
caption: caption, |
||||||
|
isNotScheduled: isNotScheduled, |
||||||
|
isOnTime: isOnTime, |
||||||
|
isDelayed: isDelayed, |
||||||
|
); |
||||||
|
case UiDesign.CUPERTINO: |
||||||
|
return CupertinoBadge( |
||||||
|
text: text, |
||||||
|
caption: caption, |
||||||
|
isNotScheduled: isNotScheduled, |
||||||
|
isOnTime: isOnTime, |
||||||
|
isDelayed: isDelayed, |
||||||
|
); |
||||||
|
case UiDesign.FLUENT: |
||||||
|
return FluentBadge( |
||||||
|
text: text, |
||||||
|
caption: caption, |
||||||
|
isNotScheduled: isNotScheduled, |
||||||
|
isOnTime: isOnTime, |
||||||
|
isDelayed: isDelayed, |
||||||
|
); |
||||||
|
default: |
||||||
|
throw UnmatchedUiDesignException(uiDesign); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,80 @@ |
|||||||
|
import 'package:flutter/cupertino.dart'; |
||||||
|
import 'package:info_tren/pages/train_info_page/train_info_constants.dart'; |
||||||
|
|
||||||
|
class CupertinoBadge extends StatelessWidget { |
||||||
|
final String text; |
||||||
|
final String caption; |
||||||
|
final bool isNotScheduled; |
||||||
|
final bool isOnTime; |
||||||
|
final bool isDelayed; |
||||||
|
|
||||||
|
const CupertinoBadge({ |
||||||
|
required this.text, |
||||||
|
required this.caption, |
||||||
|
this.isNotScheduled = false, |
||||||
|
this.isOnTime = false, |
||||||
|
this.isDelayed = false, |
||||||
|
super.key, |
||||||
|
}); |
||||||
|
|
||||||
|
@override |
||||||
|
Widget build(BuildContext context) { |
||||||
|
Color foregroundColor = foregroundWhite; |
||||||
|
Color? backgroundColor; |
||||||
|
|
||||||
|
if (isNotScheduled) { |
||||||
|
foregroundColor = const Color.fromRGBO(225, 175, 30, 1); |
||||||
|
backgroundColor = const Color.fromRGBO(80, 40, 10, 1); |
||||||
|
} |
||||||
|
else if (isOnTime) { |
||||||
|
foregroundColor = const Color.fromRGBO(130, 175, 65, 1); |
||||||
|
backgroundColor = const Color.fromRGBO(40, 80, 10, 1); |
||||||
|
} |
||||||
|
else if (isDelayed) { |
||||||
|
foregroundColor = const Color.fromRGBO(225, 75, 30, 1); |
||||||
|
backgroundColor = const Color.fromRGBO(80, 20, 10, 1); |
||||||
|
} |
||||||
|
|
||||||
|
return Padding( |
||||||
|
padding: const EdgeInsets.all(8), |
||||||
|
child: Container( |
||||||
|
decoration: BoxDecoration( |
||||||
|
borderRadius: BorderRadius.circular(10), |
||||||
|
border: Border.all( |
||||||
|
width: 2, |
||||||
|
color: foregroundColor, |
||||||
|
), |
||||||
|
color: backgroundColor, |
||||||
|
// color: CupertinoColors.activeOrange, |
||||||
|
), |
||||||
|
width: 48, |
||||||
|
height: 48, |
||||||
|
child: Column( |
||||||
|
mainAxisSize: MainAxisSize.min, |
||||||
|
children: <Widget>[ |
||||||
|
Expanded( |
||||||
|
child: Center( |
||||||
|
child: Text( |
||||||
|
text, |
||||||
|
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( |
||||||
|
fontSize: 20, |
||||||
|
fontWeight: MediaQuery.of(context).boldText ? FontWeight.w400 : FontWeight.w200, |
||||||
|
color: MediaQuery.of(context).boldText ? foregroundWhite : foregroundColor, |
||||||
|
), |
||||||
|
textAlign: TextAlign.center, |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
Text( |
||||||
|
caption, |
||||||
|
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( |
||||||
|
fontSize: 12, |
||||||
|
color: MediaQuery.of(context).boldText ? foregroundWhite : foregroundColor, |
||||||
|
), |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
), |
||||||
|
); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,80 @@ |
|||||||
|
import 'package:fluent_ui/fluent_ui.dart'; |
||||||
|
|
||||||
|
|
||||||
|
class FluentBadge extends StatelessWidget { |
||||||
|
final String text; |
||||||
|
final String caption; |
||||||
|
final bool isNotScheduled; |
||||||
|
final bool isOnTime; |
||||||
|
final bool isDelayed; |
||||||
|
|
||||||
|
const FluentBadge({ |
||||||
|
required this.text, |
||||||
|
required this.caption, |
||||||
|
this.isNotScheduled = false, |
||||||
|
this.isOnTime = false, |
||||||
|
this.isDelayed = false, |
||||||
|
super.key, |
||||||
|
}); |
||||||
|
|
||||||
|
@override |
||||||
|
Widget build(BuildContext context) { |
||||||
|
Color foregroundColor = FluentTheme.of(context).activeColor; |
||||||
|
Color? backgroundColor; |
||||||
|
|
||||||
|
if (isNotScheduled) { |
||||||
|
foregroundColor = const Color.fromRGBO(225, 175, 30, 1); |
||||||
|
backgroundColor = const Color.fromRGBO(80, 40, 10, 1); |
||||||
|
} |
||||||
|
else if (isOnTime) { |
||||||
|
foregroundColor = const Color.fromRGBO(130, 175, 65, 1); |
||||||
|
backgroundColor = const Color.fromRGBO(40, 80, 10, 1); |
||||||
|
} |
||||||
|
else if (isDelayed) { |
||||||
|
foregroundColor = const Color.fromRGBO(225, 75, 30, 1); |
||||||
|
backgroundColor = const Color.fromRGBO(80, 20, 10, 1); |
||||||
|
} |
||||||
|
|
||||||
|
return Padding( |
||||||
|
padding: const EdgeInsets.all(8), |
||||||
|
child: Container( |
||||||
|
decoration: BoxDecoration( |
||||||
|
borderRadius: BorderRadius.circular(10), |
||||||
|
border: Border.all( |
||||||
|
width: 2, |
||||||
|
color: foregroundColor, |
||||||
|
), |
||||||
|
color: backgroundColor, |
||||||
|
// color: CupertinoColors.activeOrange, |
||||||
|
), |
||||||
|
width: 48, |
||||||
|
height: 48, |
||||||
|
child: Column( |
||||||
|
mainAxisSize: MainAxisSize.min, |
||||||
|
children: <Widget>[ |
||||||
|
Expanded( |
||||||
|
child: Center( |
||||||
|
child: Text( |
||||||
|
text, |
||||||
|
style: FluentTheme.of(context).typography.bodyLarge?.copyWith( |
||||||
|
fontSize: 20, |
||||||
|
fontWeight: MediaQuery.of(context).boldText ? FontWeight.w400 : FontWeight.w200, |
||||||
|
color: MediaQuery.of(context).boldText ? Colors.white : foregroundColor, |
||||||
|
), |
||||||
|
textAlign: TextAlign.center, |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
Text( |
||||||
|
caption, |
||||||
|
style: FluentTheme.of(context).typography.body?.copyWith( |
||||||
|
fontSize: 12, |
||||||
|
color: MediaQuery.of(context).boldText ? Colors.white : foregroundColor, |
||||||
|
), |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
), |
||||||
|
); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,79 @@ |
|||||||
|
import 'package:flutter/material.dart'; |
||||||
|
import 'package:info_tren/pages/train_info_page/view_train/train_info_material.dart'; |
||||||
|
|
||||||
|
class MaterialBadge extends StatelessWidget { |
||||||
|
final String text; |
||||||
|
final String caption; |
||||||
|
final bool isNotScheduled; |
||||||
|
final bool isOnTime; |
||||||
|
final bool isDelayed; |
||||||
|
|
||||||
|
const MaterialBadge({ |
||||||
|
required this.text, |
||||||
|
required this.caption, |
||||||
|
this.isNotScheduled = false, |
||||||
|
this.isOnTime = false, |
||||||
|
this.isDelayed = false, |
||||||
|
super.key, |
||||||
|
}); |
||||||
|
|
||||||
|
@override |
||||||
|
Widget build(BuildContext context) { |
||||||
|
Color foregroundColor = Colors.white70; |
||||||
|
Color? backgroundColor; |
||||||
|
|
||||||
|
if (isNotScheduled) { |
||||||
|
foregroundColor = Colors.orange.shade300; |
||||||
|
backgroundColor = Colors.orange.shade900.withOpacity(0.3); |
||||||
|
} |
||||||
|
else if (isOnTime) { |
||||||
|
foregroundColor = Colors.green.shade300; |
||||||
|
backgroundColor = Colors.green.shade900.withOpacity(0.3); |
||||||
|
} |
||||||
|
else if (isDelayed) { |
||||||
|
foregroundColor = Colors.red.shade300; |
||||||
|
backgroundColor = Colors.red.shade900.withOpacity(0.3); |
||||||
|
} |
||||||
|
|
||||||
|
return Padding( |
||||||
|
padding: const EdgeInsets.all(8), |
||||||
|
child: Container( |
||||||
|
decoration: BoxDecoration( |
||||||
|
borderRadius: BorderRadius.circular(10), |
||||||
|
border: Border.all( |
||||||
|
width: 2, |
||||||
|
color: foregroundColor, |
||||||
|
), |
||||||
|
color: backgroundColor, |
||||||
|
), |
||||||
|
width: isSmallScreen(context) ? 42 : 48, |
||||||
|
height: isSmallScreen(context) ? 42 : 48, |
||||||
|
child: Column( |
||||||
|
mainAxisSize: MainAxisSize.min, |
||||||
|
children: <Widget>[ |
||||||
|
Expanded( |
||||||
|
child: Center( |
||||||
|
child: Text( |
||||||
|
text, |
||||||
|
style: Theme.of(context).textTheme.bodyMedium?.copyWith( |
||||||
|
fontSize: isSmallScreen(context) ? 16 : 20, |
||||||
|
fontWeight: MediaQuery.of(context).boldText ? FontWeight.w400 : FontWeight.w200, |
||||||
|
color: MediaQuery.of(context).boldText ? Colors.white70 : foregroundColor, |
||||||
|
), |
||||||
|
textAlign: TextAlign.center, |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
Text( |
||||||
|
caption, |
||||||
|
style: Theme.of(context).textTheme.bodyMedium?.copyWith( |
||||||
|
fontSize: 10, |
||||||
|
color: MediaQuery.of(context).boldText ? Colors.white70 : foregroundColor, |
||||||
|
), |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
), |
||||||
|
); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,26 @@ |
|||||||
|
import 'package:fluent_ui/fluent_ui.dart'; |
||||||
|
import 'package:info_tren/components/loading/loading.dart'; |
||||||
|
|
||||||
|
class LoadingFluent extends LoadingCommon { |
||||||
|
const LoadingFluent({required super.text, super.key}); |
||||||
|
|
||||||
|
@override |
||||||
|
Widget build(BuildContext context) { |
||||||
|
return Center( |
||||||
|
child: Column( |
||||||
|
crossAxisAlignment: CrossAxisAlignment.center, |
||||||
|
mainAxisSize: MainAxisSize.min, |
||||||
|
children: [ |
||||||
|
const Padding( |
||||||
|
padding: EdgeInsets.all(8.0), |
||||||
|
child: ProgressRing(), |
||||||
|
), |
||||||
|
Padding( |
||||||
|
padding: const EdgeInsets.all(8.0), |
||||||
|
child: Text(text), |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,85 @@ |
|||||||
|
import 'package:fluent_ui/fluent_ui.dart'; |
||||||
|
import 'package:info_tren/components/select_train_suggestions/select_train_suggestions.dart'; |
||||||
|
import 'package:info_tren/components/train_id_text_span.dart'; |
||||||
|
import 'package:info_tren/models.dart'; |
||||||
|
|
||||||
|
class SelectTrainSuggestionsFluent extends SelectTrainSuggestionsShared { |
||||||
|
const SelectTrainSuggestionsFluent({ |
||||||
|
super.key, |
||||||
|
required super.choices, |
||||||
|
required super.onTrainSelected, |
||||||
|
super.currentInput, |
||||||
|
}); |
||||||
|
|
||||||
|
@override |
||||||
|
Widget getUseCurrentInputWidget(String currentInput, void Function(String) onTrainSelected) { |
||||||
|
return Column( |
||||||
|
mainAxisSize: MainAxisSize.min, |
||||||
|
children: <Widget>[ |
||||||
|
Padding( |
||||||
|
padding: const EdgeInsets.all(0), |
||||||
|
child: Column( |
||||||
|
mainAxisSize: MainAxisSize.min, |
||||||
|
children: <Widget>[ |
||||||
|
Button( |
||||||
|
child: Text(getUseCurrentInputWidgetText(currentInput)), |
||||||
|
onPressed: () => onTrainSelected(currentInput), |
||||||
|
), |
||||||
|
], |
||||||
|
) |
||||||
|
), |
||||||
|
const Divider(), |
||||||
|
], |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
class OperatorAutocompleteTileFluent extends OperatorAutocompleteTile { |
||||||
|
const OperatorAutocompleteTileFluent({ |
||||||
|
Key? key, |
||||||
|
required String operatorName, |
||||||
|
required void Function(String) onTrainSelected, |
||||||
|
required TrainsResult train |
||||||
|
}): super( |
||||||
|
onTrainSelected: onTrainSelected, |
||||||
|
operatorName: operatorName, |
||||||
|
train: train, |
||||||
|
key: key, |
||||||
|
); |
||||||
|
|
||||||
|
@override |
||||||
|
Widget build(BuildContext context) { |
||||||
|
return Column( |
||||||
|
mainAxisSize: MainAxisSize.min, |
||||||
|
children: [ |
||||||
|
GestureDetector( |
||||||
|
onTap: () { |
||||||
|
onTrainSelected(train.number); |
||||||
|
}, |
||||||
|
child: Padding( |
||||||
|
padding: const EdgeInsets.fromLTRB(16, 4, 16, 4), |
||||||
|
child: SizedBox( |
||||||
|
width: double.infinity, |
||||||
|
child: Column( |
||||||
|
mainAxisSize: MainAxisSize.min, |
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch, |
||||||
|
children: <Widget>[ |
||||||
|
Text( |
||||||
|
operatorName, |
||||||
|
style: FluentTheme.of(context).typography.body?.copyWith(fontSize: 10, fontWeight: FontWeight.w200), |
||||||
|
textAlign: TextAlign.left, |
||||||
|
), |
||||||
|
Text.rich( |
||||||
|
trainIdSpan(rank: train.rank, number: train.number), |
||||||
|
textAlign: TextAlign.left, |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
const Divider(), |
||||||
|
], |
||||||
|
); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,39 @@ |
|||||||
|
import 'package:flutter/gestures.dart'; |
||||||
|
import 'package:flutter/rendering.dart'; |
||||||
|
|
||||||
|
TextSpan trainIdSpan({ |
||||||
|
required String rank, |
||||||
|
required String number, |
||||||
|
Locale? locale, |
||||||
|
MouseCursor? mouseCursor, |
||||||
|
void Function(PointerEnterEvent)? onEnter, |
||||||
|
void Function(PointerExitEvent)? onExit, |
||||||
|
GestureRecognizer? recognizer, |
||||||
|
String? semanticsLabel, |
||||||
|
bool? spellOut, |
||||||
|
TextStyle? style, |
||||||
|
}) => TextSpan( |
||||||
|
children: [ |
||||||
|
TextSpan( |
||||||
|
text: rank, |
||||||
|
style: TextStyle( |
||||||
|
inherit: true, |
||||||
|
color: rank.startsWith('IC') |
||||||
|
? const Color.fromARGB(255, 0, 255, 0) |
||||||
|
: rank.startsWith('IR') |
||||||
|
? const Color.fromARGB(255, 255, 0, 0) |
||||||
|
: null, |
||||||
|
), |
||||||
|
), |
||||||
|
const TextSpan(text: ' '), |
||||||
|
TextSpan(text: number), |
||||||
|
], |
||||||
|
locale: locale, |
||||||
|
mouseCursor: mouseCursor, |
||||||
|
onEnter: onEnter, |
||||||
|
onExit: onExit, |
||||||
|
recognizer: recognizer, |
||||||
|
semanticsLabel: semanticsLabel, |
||||||
|
spellOut: spellOut, |
||||||
|
style: style, |
||||||
|
); |
@ -0,0 +1,14 @@ |
|||||||
|
export 'package:info_tren/models/changelog_entry.dart'; |
||||||
|
export 'package:info_tren/models/station_arrdep.dart'; |
||||||
|
export 'package:info_tren/models/station_data.dart'; |
||||||
|
export 'package:info_tren/models/station_status.dart'; |
||||||
|
export 'package:info_tren/models/station_train.dart'; |
||||||
|
export 'package:info_tren/models/stations_result.dart'; |
||||||
|
export 'package:info_tren/models/train_data.dart'; |
||||||
|
export 'package:info_tren/models/trains_result.dart'; |
||||||
|
export 'package:info_tren/models/ui_design.dart'; |
||||||
|
export 'package:info_tren/models/ui_timezone.dart'; |
||||||
|
|
||||||
|
import 'package:info_tren/models/train_data.dart' show TrainDataStatusState; |
||||||
|
|
||||||
|
typedef TrainDataState = TrainDataStatusState; |
@ -0,0 +1,83 @@ |
|||||||
|
import 'package:quiver/core.dart'; |
||||||
|
|
||||||
|
class ChangelogEntry { |
||||||
|
final ChangelogVersion version; |
||||||
|
final String description; |
||||||
|
final Uri? apkLink; |
||||||
|
final Uri? linuxLink; |
||||||
|
final Uri? windowsLink; |
||||||
|
|
||||||
|
ChangelogEntry({ |
||||||
|
required this.version, |
||||||
|
required this.description, |
||||||
|
this.apkLink, |
||||||
|
this.linuxLink, |
||||||
|
this.windowsLink, |
||||||
|
}); |
||||||
|
|
||||||
|
factory ChangelogEntry.fromTextBlock(String text) { |
||||||
|
final lines = text.split(RegExp(r'(\r?\n)+')); |
||||||
|
return ChangelogEntry( |
||||||
|
version: ChangelogVersion.parse(lines.first), |
||||||
|
description: lines.skip(1).join('\n'), |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
static List<ChangelogEntry> fromTextFile(String text) { |
||||||
|
final blocks = text.split(RegExp(r'(\r?\n){2}')); |
||||||
|
return blocks.map(ChangelogEntry.fromTextBlock).toList(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
class ChangelogVersion implements Comparable<ChangelogVersion> { |
||||||
|
final int major; |
||||||
|
final int minor; |
||||||
|
final int patch; |
||||||
|
final String? prerelease; |
||||||
|
|
||||||
|
ChangelogVersion(this.major, this.minor, this.patch, [this.prerelease]); |
||||||
|
|
||||||
|
factory ChangelogVersion.parse(String version) { |
||||||
|
if (version.startsWith('v')) { |
||||||
|
version = version.substring(1); |
||||||
|
} |
||||||
|
String? prerelease; |
||||||
|
if (version.contains('-')) { |
||||||
|
final index = version.indexOf('-'); |
||||||
|
prerelease = version.substring(index + 1); |
||||||
|
version = version.substring(0, index); |
||||||
|
} |
||||||
|
final splitted = version.split('.').map(int.parse).toList(); |
||||||
|
return ChangelogVersion(splitted[0], splitted[1], splitted[2], prerelease); |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
String toString() { |
||||||
|
final vString = 'v$major.$minor.$patch'; |
||||||
|
return prerelease == null ? vString : '$vString-$prerelease'; |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
bool operator==(dynamic other) { |
||||||
|
if (other is! ChangelogVersion) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
return major == other.major && minor == other.minor && patch == other.patch && prerelease == other.prerelease; |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
int get hashCode { |
||||||
|
return hash3(major.hashCode, minor.hashCode, patch.hashCode); |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
int compareTo(ChangelogVersion other) { |
||||||
|
if (major != other.major) { |
||||||
|
return major.compareTo(other.major); |
||||||
|
} |
||||||
|
if (minor != other.minor) { |
||||||
|
return minor.compareTo(other.minor); |
||||||
|
} |
||||||
|
return patch.compareTo(other.patch); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,18 @@ |
|||||||
|
import 'package:freezed_annotation/freezed_annotation.dart'; |
||||||
|
import 'package:info_tren/models.dart'; |
||||||
|
|
||||||
|
part 'station_arrdep.g.dart'; |
||||||
|
part 'station_arrdep.freezed.dart'; |
||||||
|
|
||||||
|
@freezed |
||||||
|
class StationArrDep with _$StationArrDep { |
||||||
|
const factory StationArrDep({ |
||||||
|
required int? stoppingTime, |
||||||
|
required DateTime time, |
||||||
|
required StationTrain train, |
||||||
|
required StationStatus status, |
||||||
|
}) = _StationArrDep; |
||||||
|
|
||||||
|
factory StationArrDep.fromJson(Map<String, dynamic> json) => _$StationArrDepFromJson(json); |
||||||
|
} |
||||||
|
|
@ -0,0 +1,241 @@ |
|||||||
|
// coverage:ignore-file |
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND |
||||||
|
// ignore_for_file: type=lint |
||||||
|
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark |
||||||
|
|
||||||
|
part of 'station_arrdep.dart'; |
||||||
|
|
||||||
|
// ************************************************************************** |
||||||
|
// FreezedGenerator |
||||||
|
// ************************************************************************** |
||||||
|
|
||||||
|
T _$identity<T>(T value) => value; |
||||||
|
|
||||||
|
final _privateConstructorUsedError = UnsupportedError( |
||||||
|
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); |
||||||
|
|
||||||
|
StationArrDep _$StationArrDepFromJson(Map<String, dynamic> json) { |
||||||
|
return _StationArrDep.fromJson(json); |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
mixin _$StationArrDep { |
||||||
|
int? get stoppingTime => throw _privateConstructorUsedError; |
||||||
|
DateTime get time => throw _privateConstructorUsedError; |
||||||
|
StationTrain get train => throw _privateConstructorUsedError; |
||||||
|
StationStatus get status => throw _privateConstructorUsedError; |
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError; |
||||||
|
@JsonKey(ignore: true) |
||||||
|
$StationArrDepCopyWith<StationArrDep> get copyWith => |
||||||
|
throw _privateConstructorUsedError; |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
abstract class $StationArrDepCopyWith<$Res> { |
||||||
|
factory $StationArrDepCopyWith( |
||||||
|
StationArrDep value, $Res Function(StationArrDep) then) = |
||||||
|
_$StationArrDepCopyWithImpl<$Res, StationArrDep>; |
||||||
|
@useResult |
||||||
|
$Res call( |
||||||
|
{int? stoppingTime, |
||||||
|
DateTime time, |
||||||
|
StationTrain train, |
||||||
|
StationStatus status}); |
||||||
|
|
||||||
|
$StationTrainCopyWith<$Res> get train; |
||||||
|
$StationStatusCopyWith<$Res> get status; |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
class _$StationArrDepCopyWithImpl<$Res, $Val extends StationArrDep> |
||||||
|
implements $StationArrDepCopyWith<$Res> { |
||||||
|
_$StationArrDepCopyWithImpl(this._value, this._then); |
||||||
|
|
||||||
|
// ignore: unused_field |
||||||
|
final $Val _value; |
||||||
|
// ignore: unused_field |
||||||
|
final $Res Function($Val) _then; |
||||||
|
|
||||||
|
@pragma('vm:prefer-inline') |
||||||
|
@override |
||||||
|
$Res call({ |
||||||
|
Object? stoppingTime = freezed, |
||||||
|
Object? time = null, |
||||||
|
Object? train = null, |
||||||
|
Object? status = null, |
||||||
|
}) { |
||||||
|
return _then(_value.copyWith( |
||||||
|
stoppingTime: freezed == stoppingTime |
||||||
|
? _value.stoppingTime |
||||||
|
: stoppingTime // ignore: cast_nullable_to_non_nullable |
||||||
|
as int?, |
||||||
|
time: null == time |
||||||
|
? _value.time |
||||||
|
: time // ignore: cast_nullable_to_non_nullable |
||||||
|
as DateTime, |
||||||
|
train: null == train |
||||||
|
? _value.train |
||||||
|
: train // ignore: cast_nullable_to_non_nullable |
||||||
|
as StationTrain, |
||||||
|
status: null == status |
||||||
|
? _value.status |
||||||
|
: status // ignore: cast_nullable_to_non_nullable |
||||||
|
as StationStatus, |
||||||
|
) as $Val); |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
@pragma('vm:prefer-inline') |
||||||
|
$StationTrainCopyWith<$Res> get train { |
||||||
|
return $StationTrainCopyWith<$Res>(_value.train, (value) { |
||||||
|
return _then(_value.copyWith(train: value) as $Val); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
@pragma('vm:prefer-inline') |
||||||
|
$StationStatusCopyWith<$Res> get status { |
||||||
|
return $StationStatusCopyWith<$Res>(_value.status, (value) { |
||||||
|
return _then(_value.copyWith(status: value) as $Val); |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
abstract class _$$_StationArrDepCopyWith<$Res> |
||||||
|
implements $StationArrDepCopyWith<$Res> { |
||||||
|
factory _$$_StationArrDepCopyWith( |
||||||
|
_$_StationArrDep value, $Res Function(_$_StationArrDep) then) = |
||||||
|
__$$_StationArrDepCopyWithImpl<$Res>; |
||||||
|
@override |
||||||
|
@useResult |
||||||
|
$Res call( |
||||||
|
{int? stoppingTime, |
||||||
|
DateTime time, |
||||||
|
StationTrain train, |
||||||
|
StationStatus status}); |
||||||
|
|
||||||
|
@override |
||||||
|
$StationTrainCopyWith<$Res> get train; |
||||||
|
@override |
||||||
|
$StationStatusCopyWith<$Res> get status; |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
class __$$_StationArrDepCopyWithImpl<$Res> |
||||||
|
extends _$StationArrDepCopyWithImpl<$Res, _$_StationArrDep> |
||||||
|
implements _$$_StationArrDepCopyWith<$Res> { |
||||||
|
__$$_StationArrDepCopyWithImpl( |
||||||
|
_$_StationArrDep _value, $Res Function(_$_StationArrDep) _then) |
||||||
|
: super(_value, _then); |
||||||
|
|
||||||
|
@pragma('vm:prefer-inline') |
||||||
|
@override |
||||||
|
$Res call({ |
||||||
|
Object? stoppingTime = freezed, |
||||||
|
Object? time = null, |
||||||
|
Object? train = null, |
||||||
|
Object? status = null, |
||||||
|
}) { |
||||||
|
return _then(_$_StationArrDep( |
||||||
|
stoppingTime: freezed == stoppingTime |
||||||
|
? _value.stoppingTime |
||||||
|
: stoppingTime // ignore: cast_nullable_to_non_nullable |
||||||
|
as int?, |
||||||
|
time: null == time |
||||||
|
? _value.time |
||||||
|
: time // ignore: cast_nullable_to_non_nullable |
||||||
|
as DateTime, |
||||||
|
train: null == train |
||||||
|
? _value.train |
||||||
|
: train // ignore: cast_nullable_to_non_nullable |
||||||
|
as StationTrain, |
||||||
|
status: null == status |
||||||
|
? _value.status |
||||||
|
: status // ignore: cast_nullable_to_non_nullable |
||||||
|
as StationStatus, |
||||||
|
)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
@JsonSerializable() |
||||||
|
class _$_StationArrDep implements _StationArrDep { |
||||||
|
const _$_StationArrDep( |
||||||
|
{required this.stoppingTime, |
||||||
|
required this.time, |
||||||
|
required this.train, |
||||||
|
required this.status}); |
||||||
|
|
||||||
|
factory _$_StationArrDep.fromJson(Map<String, dynamic> json) => |
||||||
|
_$$_StationArrDepFromJson(json); |
||||||
|
|
||||||
|
@override |
||||||
|
final int? stoppingTime; |
||||||
|
@override |
||||||
|
final DateTime time; |
||||||
|
@override |
||||||
|
final StationTrain train; |
||||||
|
@override |
||||||
|
final StationStatus status; |
||||||
|
|
||||||
|
@override |
||||||
|
String toString() { |
||||||
|
return 'StationArrDep(stoppingTime: $stoppingTime, time: $time, train: $train, status: $status)'; |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
bool operator ==(dynamic other) { |
||||||
|
return identical(this, other) || |
||||||
|
(other.runtimeType == runtimeType && |
||||||
|
other is _$_StationArrDep && |
||||||
|
(identical(other.stoppingTime, stoppingTime) || |
||||||
|
other.stoppingTime == stoppingTime) && |
||||||
|
(identical(other.time, time) || other.time == time) && |
||||||
|
(identical(other.train, train) || other.train == train) && |
||||||
|
(identical(other.status, status) || other.status == status)); |
||||||
|
} |
||||||
|
|
||||||
|
@JsonKey(ignore: true) |
||||||
|
@override |
||||||
|
int get hashCode => |
||||||
|
Object.hash(runtimeType, stoppingTime, time, train, status); |
||||||
|
|
||||||
|
@JsonKey(ignore: true) |
||||||
|
@override |
||||||
|
@pragma('vm:prefer-inline') |
||||||
|
_$$_StationArrDepCopyWith<_$_StationArrDep> get copyWith => |
||||||
|
__$$_StationArrDepCopyWithImpl<_$_StationArrDep>(this, _$identity); |
||||||
|
|
||||||
|
@override |
||||||
|
Map<String, dynamic> toJson() { |
||||||
|
return _$$_StationArrDepToJson( |
||||||
|
this, |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
abstract class _StationArrDep implements StationArrDep { |
||||||
|
const factory _StationArrDep( |
||||||
|
{required final int? stoppingTime, |
||||||
|
required final DateTime time, |
||||||
|
required final StationTrain train, |
||||||
|
required final StationStatus status}) = _$_StationArrDep; |
||||||
|
|
||||||
|
factory _StationArrDep.fromJson(Map<String, dynamic> json) = |
||||||
|
_$_StationArrDep.fromJson; |
||||||
|
|
||||||
|
@override |
||||||
|
int? get stoppingTime; |
||||||
|
@override |
||||||
|
DateTime get time; |
||||||
|
@override |
||||||
|
StationTrain get train; |
||||||
|
@override |
||||||
|
StationStatus get status; |
||||||
|
@override |
||||||
|
@JsonKey(ignore: true) |
||||||
|
_$$_StationArrDepCopyWith<_$_StationArrDep> get copyWith => |
||||||
|
throw _privateConstructorUsedError; |
||||||
|
} |
@ -0,0 +1,23 @@ |
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND |
||||||
|
|
||||||
|
part of 'station_arrdep.dart'; |
||||||
|
|
||||||
|
// ************************************************************************** |
||||||
|
// JsonSerializableGenerator |
||||||
|
// ************************************************************************** |
||||||
|
|
||||||
|
_$_StationArrDep _$$_StationArrDepFromJson(Map<String, dynamic> json) => |
||||||
|
_$_StationArrDep( |
||||||
|
stoppingTime: json['stoppingTime'] as int?, |
||||||
|
time: DateTime.parse(json['time'] as String), |
||||||
|
train: StationTrain.fromJson(json['train'] as Map<String, dynamic>), |
||||||
|
status: StationStatus.fromJson(json['status'] as Map<String, dynamic>), |
||||||
|
); |
||||||
|
|
||||||
|
Map<String, dynamic> _$$_StationArrDepToJson(_$_StationArrDep instance) => |
||||||
|
<String, dynamic>{ |
||||||
|
'stoppingTime': instance.stoppingTime, |
||||||
|
'time': instance.time.toIso8601String(), |
||||||
|
'train': instance.train, |
||||||
|
'status': instance.status, |
||||||
|
}; |
@ -1,68 +1,17 @@ |
|||||||
import 'package:json_annotation/json_annotation.dart'; |
import 'package:freezed_annotation/freezed_annotation.dart'; |
||||||
|
import 'package:info_tren/models.dart'; |
||||||
|
|
||||||
part 'station_data.g.dart'; |
part 'station_data.g.dart'; |
||||||
|
part 'station_data.freezed.dart'; |
||||||
|
|
||||||
@JsonSerializable() |
@freezed |
||||||
class StationData { |
class StationData with _$StationData { |
||||||
final String date; |
const factory StationData({ |
||||||
final String stationName; |
required String date, |
||||||
final List<StationArrival>? arrivals; |
required String stationName, |
||||||
final List<StationDeparture>? departures; |
required List<StationArrDep>? arrivals, |
||||||
|
required List<StationArrDep>? departures, |
||||||
const StationData({required this.date, required this.stationName, required this.arrivals, required this.departures}); |
}) = _StationData; |
||||||
|
|
||||||
factory StationData.fromJson(Map<String, dynamic> json) => _$StationDataFromJson(json); |
factory StationData.fromJson(Map<String, dynamic> json) => _$StationDataFromJson(json); |
||||||
Map<String, dynamic> toJson() => _$StationDataToJson(this); |
|
||||||
} |
|
||||||
|
|
||||||
@JsonSerializable() |
|
||||||
class StationArrival { |
|
||||||
final int? stoppingTime; |
|
||||||
final DateTime time; |
|
||||||
final StationTrainArr train; |
|
||||||
|
|
||||||
const StationArrival({required this.stoppingTime, required this.time, required this.train,}); |
|
||||||
|
|
||||||
factory StationArrival.fromJson(Map<String, dynamic> json) => _$StationArrivalFromJson(json); |
|
||||||
Map<String, dynamic> toJson() => _$StationArrivalToJson(this); |
|
||||||
} |
|
||||||
|
|
||||||
@JsonSerializable() |
|
||||||
class StationDeparture { |
|
||||||
final int? stoppingTime; |
|
||||||
final DateTime time; |
|
||||||
final StationTrainDep train; |
|
||||||
|
|
||||||
const StationDeparture({required this.stoppingTime, required this.time, required this.train,}); |
|
||||||
|
|
||||||
factory StationDeparture.fromJson(Map<String, dynamic> json) => _$StationDepartureFromJson(json); |
|
||||||
Map<String, dynamic> toJson() => _$StationDepartureToJson(this); |
|
||||||
} |
|
||||||
|
|
||||||
@JsonSerializable() |
|
||||||
class StationTrainArr { |
|
||||||
final String rank; |
|
||||||
final String number; |
|
||||||
final String operator; |
|
||||||
final String origin; |
|
||||||
final List<String>? route; |
|
||||||
|
|
||||||
StationTrainArr({required this.rank, required this.number, required this.operator, required this.origin, this.route,}); |
|
||||||
|
|
||||||
factory StationTrainArr.fromJson(Map<String, dynamic> json) => _$StationTrainArrFromJson(json); |
|
||||||
Map<String, dynamic> toJson() => _$StationTrainArrToJson(this); |
|
||||||
} |
|
||||||
|
|
||||||
@JsonSerializable() |
|
||||||
class StationTrainDep { |
|
||||||
final String rank; |
|
||||||
final String number; |
|
||||||
final String operator; |
|
||||||
final String destination; |
|
||||||
final List<String>? route; |
|
||||||
|
|
||||||
StationTrainDep({required this.rank, required this.number, required this.operator, required this.destination, this.route,}); |
|
||||||
|
|
||||||
factory StationTrainDep.fromJson(Map<String, dynamic> json) => _$StationTrainDepFromJson(json); |
|
||||||
Map<String, dynamic> toJson() => _$StationTrainDepToJson(this); |
|
||||||
} |
} |
||||||
|
@ -0,0 +1,239 @@ |
|||||||
|
// coverage:ignore-file |
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND |
||||||
|
// ignore_for_file: type=lint |
||||||
|
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark |
||||||
|
|
||||||
|
part of 'station_data.dart'; |
||||||
|
|
||||||
|
// ************************************************************************** |
||||||
|
// FreezedGenerator |
||||||
|
// ************************************************************************** |
||||||
|
|
||||||
|
T _$identity<T>(T value) => value; |
||||||
|
|
||||||
|
final _privateConstructorUsedError = UnsupportedError( |
||||||
|
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); |
||||||
|
|
||||||
|
StationData _$StationDataFromJson(Map<String, dynamic> json) { |
||||||
|
return _StationData.fromJson(json); |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
mixin _$StationData { |
||||||
|
String get date => throw _privateConstructorUsedError; |
||||||
|
String get stationName => throw _privateConstructorUsedError; |
||||||
|
List<StationArrDep>? get arrivals => throw _privateConstructorUsedError; |
||||||
|
List<StationArrDep>? get departures => throw _privateConstructorUsedError; |
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError; |
||||||
|
@JsonKey(ignore: true) |
||||||
|
$StationDataCopyWith<StationData> get copyWith => |
||||||
|
throw _privateConstructorUsedError; |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
abstract class $StationDataCopyWith<$Res> { |
||||||
|
factory $StationDataCopyWith( |
||||||
|
StationData value, $Res Function(StationData) then) = |
||||||
|
_$StationDataCopyWithImpl<$Res, StationData>; |
||||||
|
@useResult |
||||||
|
$Res call( |
||||||
|
{String date, |
||||||
|
String stationName, |
||||||
|
List<StationArrDep>? arrivals, |
||||||
|
List<StationArrDep>? departures}); |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
class _$StationDataCopyWithImpl<$Res, $Val extends StationData> |
||||||
|
implements $StationDataCopyWith<$Res> { |
||||||
|
_$StationDataCopyWithImpl(this._value, this._then); |
||||||
|
|
||||||
|
// ignore: unused_field |
||||||
|
final $Val _value; |
||||||
|
// ignore: unused_field |
||||||
|
final $Res Function($Val) _then; |
||||||
|
|
||||||
|
@pragma('vm:prefer-inline') |
||||||
|
@override |
||||||
|
$Res call({ |
||||||
|
Object? date = null, |
||||||
|
Object? stationName = null, |
||||||
|
Object? arrivals = freezed, |
||||||
|
Object? departures = freezed, |
||||||
|
}) { |
||||||
|
return _then(_value.copyWith( |
||||||
|
date: null == date |
||||||
|
? _value.date |
||||||
|
: date // ignore: cast_nullable_to_non_nullable |
||||||
|
as String, |
||||||
|
stationName: null == stationName |
||||||
|
? _value.stationName |
||||||
|
: stationName // ignore: cast_nullable_to_non_nullable |
||||||
|
as String, |
||||||
|
arrivals: freezed == arrivals |
||||||
|
? _value.arrivals |
||||||
|
: arrivals // ignore: cast_nullable_to_non_nullable |
||||||
|
as List<StationArrDep>?, |
||||||
|
departures: freezed == departures |
||||||
|
? _value.departures |
||||||
|
: departures // ignore: cast_nullable_to_non_nullable |
||||||
|
as List<StationArrDep>?, |
||||||
|
) as $Val); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
abstract class _$$_StationDataCopyWith<$Res> |
||||||
|
implements $StationDataCopyWith<$Res> { |
||||||
|
factory _$$_StationDataCopyWith( |
||||||
|
_$_StationData value, $Res Function(_$_StationData) then) = |
||||||
|
__$$_StationDataCopyWithImpl<$Res>; |
||||||
|
@override |
||||||
|
@useResult |
||||||
|
$Res call( |
||||||
|
{String date, |
||||||
|
String stationName, |
||||||
|
List<StationArrDep>? arrivals, |
||||||
|
List<StationArrDep>? departures}); |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
class __$$_StationDataCopyWithImpl<$Res> |
||||||
|
extends _$StationDataCopyWithImpl<$Res, _$_StationData> |
||||||
|
implements _$$_StationDataCopyWith<$Res> { |
||||||
|
__$$_StationDataCopyWithImpl( |
||||||
|
_$_StationData _value, $Res Function(_$_StationData) _then) |
||||||
|
: super(_value, _then); |
||||||
|
|
||||||
|
@pragma('vm:prefer-inline') |
||||||
|
@override |
||||||
|
$Res call({ |
||||||
|
Object? date = null, |
||||||
|
Object? stationName = null, |
||||||
|
Object? arrivals = freezed, |
||||||
|
Object? departures = freezed, |
||||||
|
}) { |
||||||
|
return _then(_$_StationData( |
||||||
|
date: null == date |
||||||
|
? _value.date |
||||||
|
: date // ignore: cast_nullable_to_non_nullable |
||||||
|
as String, |
||||||
|
stationName: null == stationName |
||||||
|
? _value.stationName |
||||||
|
: stationName // ignore: cast_nullable_to_non_nullable |
||||||
|
as String, |
||||||
|
arrivals: freezed == arrivals |
||||||
|
? _value._arrivals |
||||||
|
: arrivals // ignore: cast_nullable_to_non_nullable |
||||||
|
as List<StationArrDep>?, |
||||||
|
departures: freezed == departures |
||||||
|
? _value._departures |
||||||
|
: departures // ignore: cast_nullable_to_non_nullable |
||||||
|
as List<StationArrDep>?, |
||||||
|
)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
@JsonSerializable() |
||||||
|
class _$_StationData implements _StationData { |
||||||
|
const _$_StationData( |
||||||
|
{required this.date, |
||||||
|
required this.stationName, |
||||||
|
required final List<StationArrDep>? arrivals, |
||||||
|
required final List<StationArrDep>? departures}) |
||||||
|
: _arrivals = arrivals, |
||||||
|
_departures = departures; |
||||||
|
|
||||||
|
factory _$_StationData.fromJson(Map<String, dynamic> json) => |
||||||
|
_$$_StationDataFromJson(json); |
||||||
|
|
||||||
|
@override |
||||||
|
final String date; |
||||||
|
@override |
||||||
|
final String stationName; |
||||||
|
final List<StationArrDep>? _arrivals; |
||||||
|
@override |
||||||
|
List<StationArrDep>? get arrivals { |
||||||
|
final value = _arrivals; |
||||||
|
if (value == null) return null; |
||||||
|
if (_arrivals is EqualUnmodifiableListView) return _arrivals; |
||||||
|
// ignore: implicit_dynamic_type |
||||||
|
return EqualUnmodifiableListView(value); |
||||||
|
} |
||||||
|
|
||||||
|
final List<StationArrDep>? _departures; |
||||||
|
@override |
||||||
|
List<StationArrDep>? get departures { |
||||||
|
final value = _departures; |
||||||
|
if (value == null) return null; |
||||||
|
if (_departures is EqualUnmodifiableListView) return _departures; |
||||||
|
// ignore: implicit_dynamic_type |
||||||
|
return EqualUnmodifiableListView(value); |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
String toString() { |
||||||
|
return 'StationData(date: $date, stationName: $stationName, arrivals: $arrivals, departures: $departures)'; |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
bool operator ==(dynamic other) { |
||||||
|
return identical(this, other) || |
||||||
|
(other.runtimeType == runtimeType && |
||||||
|
other is _$_StationData && |
||||||
|
(identical(other.date, date) || other.date == date) && |
||||||
|
(identical(other.stationName, stationName) || |
||||||
|
other.stationName == stationName) && |
||||||
|
const DeepCollectionEquality().equals(other._arrivals, _arrivals) && |
||||||
|
const DeepCollectionEquality() |
||||||
|
.equals(other._departures, _departures)); |
||||||
|
} |
||||||
|
|
||||||
|
@JsonKey(ignore: true) |
||||||
|
@override |
||||||
|
int get hashCode => Object.hash( |
||||||
|
runtimeType, |
||||||
|
date, |
||||||
|
stationName, |
||||||
|
const DeepCollectionEquality().hash(_arrivals), |
||||||
|
const DeepCollectionEquality().hash(_departures)); |
||||||
|
|
||||||
|
@JsonKey(ignore: true) |
||||||
|
@override |
||||||
|
@pragma('vm:prefer-inline') |
||||||
|
_$$_StationDataCopyWith<_$_StationData> get copyWith => |
||||||
|
__$$_StationDataCopyWithImpl<_$_StationData>(this, _$identity); |
||||||
|
|
||||||
|
@override |
||||||
|
Map<String, dynamic> toJson() { |
||||||
|
return _$$_StationDataToJson( |
||||||
|
this, |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
abstract class _StationData implements StationData { |
||||||
|
const factory _StationData( |
||||||
|
{required final String date, |
||||||
|
required final String stationName, |
||||||
|
required final List<StationArrDep>? arrivals, |
||||||
|
required final List<StationArrDep>? departures}) = _$_StationData; |
||||||
|
|
||||||
|
factory _StationData.fromJson(Map<String, dynamic> json) = |
||||||
|
_$_StationData.fromJson; |
||||||
|
|
||||||
|
@override |
||||||
|
String get date; |
||||||
|
@override |
||||||
|
String get stationName; |
||||||
|
@override |
||||||
|
List<StationArrDep>? get arrivals; |
||||||
|
@override |
||||||
|
List<StationArrDep>? get departures; |
||||||
|
@override |
||||||
|
@JsonKey(ignore: true) |
||||||
|
_$$_StationDataCopyWith<_$_StationData> get copyWith => |
||||||
|
throw _privateConstructorUsedError; |
||||||
|
} |
@ -0,0 +1,17 @@ |
|||||||
|
import 'package:freezed_annotation/freezed_annotation.dart'; |
||||||
|
|
||||||
|
part 'station_status.g.dart'; |
||||||
|
part 'station_status.freezed.dart'; |
||||||
|
|
||||||
|
@freezed |
||||||
|
class StationStatus with _$StationStatus { |
||||||
|
const factory StationStatus({ |
||||||
|
required int delay, |
||||||
|
required bool real, |
||||||
|
required bool cancelled, |
||||||
|
required String? platform, |
||||||
|
}) = _StationStatus; |
||||||
|
|
||||||
|
factory StationStatus.fromJson(Map<String, dynamic> json) => _$StationStatusFromJson(json); |
||||||
|
} |
||||||
|
|
@ -0,0 +1,210 @@ |
|||||||
|
// coverage:ignore-file |
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND |
||||||
|
// ignore_for_file: type=lint |
||||||
|
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark |
||||||
|
|
||||||
|
part of 'station_status.dart'; |
||||||
|
|
||||||
|
// ************************************************************************** |
||||||
|
// FreezedGenerator |
||||||
|
// ************************************************************************** |
||||||
|
|
||||||
|
T _$identity<T>(T value) => value; |
||||||
|
|
||||||
|
final _privateConstructorUsedError = UnsupportedError( |
||||||
|
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); |
||||||
|
|
||||||
|
StationStatus _$StationStatusFromJson(Map<String, dynamic> json) { |
||||||
|
return _StationStatus.fromJson(json); |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
mixin _$StationStatus { |
||||||
|
int get delay => throw _privateConstructorUsedError; |
||||||
|
bool get real => throw _privateConstructorUsedError; |
||||||
|
bool get cancelled => throw _privateConstructorUsedError; |
||||||
|
String? get platform => throw _privateConstructorUsedError; |
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError; |
||||||
|
@JsonKey(ignore: true) |
||||||
|
$StationStatusCopyWith<StationStatus> get copyWith => |
||||||
|
throw _privateConstructorUsedError; |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
abstract class $StationStatusCopyWith<$Res> { |
||||||
|
factory $StationStatusCopyWith( |
||||||
|
StationStatus value, $Res Function(StationStatus) then) = |
||||||
|
_$StationStatusCopyWithImpl<$Res, StationStatus>; |
||||||
|
@useResult |
||||||
|
$Res call({int delay, bool real, bool cancelled, String? platform}); |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
class _$StationStatusCopyWithImpl<$Res, $Val extends StationStatus> |
||||||
|
implements $StationStatusCopyWith<$Res> { |
||||||
|
_$StationStatusCopyWithImpl(this._value, this._then); |
||||||
|
|
||||||
|
// ignore: unused_field |
||||||
|
final $Val _value; |
||||||
|
// ignore: unused_field |
||||||
|
final $Res Function($Val) _then; |
||||||
|
|
||||||
|
@pragma('vm:prefer-inline') |
||||||
|
@override |
||||||
|
$Res call({ |
||||||
|
Object? delay = null, |
||||||
|
Object? real = null, |
||||||
|
Object? cancelled = null, |
||||||
|
Object? platform = freezed, |
||||||
|
}) { |
||||||
|
return _then(_value.copyWith( |
||||||
|
delay: null == delay |
||||||
|
? _value.delay |
||||||
|
: delay // ignore: cast_nullable_to_non_nullable |
||||||
|
as int, |
||||||
|
real: null == real |
||||||
|
? _value.real |
||||||
|
: real // ignore: cast_nullable_to_non_nullable |
||||||
|
as bool, |
||||||
|
cancelled: null == cancelled |
||||||
|
? _value.cancelled |
||||||
|
: cancelled // ignore: cast_nullable_to_non_nullable |
||||||
|
as bool, |
||||||
|
platform: freezed == platform |
||||||
|
? _value.platform |
||||||
|
: platform // ignore: cast_nullable_to_non_nullable |
||||||
|
as String?, |
||||||
|
) as $Val); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
abstract class _$$_StationStatusCopyWith<$Res> |
||||||
|
implements $StationStatusCopyWith<$Res> { |
||||||
|
factory _$$_StationStatusCopyWith( |
||||||
|
_$_StationStatus value, $Res Function(_$_StationStatus) then) = |
||||||
|
__$$_StationStatusCopyWithImpl<$Res>; |
||||||
|
@override |
||||||
|
@useResult |
||||||
|
$Res call({int delay, bool real, bool cancelled, String? platform}); |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
class __$$_StationStatusCopyWithImpl<$Res> |
||||||
|
extends _$StationStatusCopyWithImpl<$Res, _$_StationStatus> |
||||||
|
implements _$$_StationStatusCopyWith<$Res> { |
||||||
|
__$$_StationStatusCopyWithImpl( |
||||||
|
_$_StationStatus _value, $Res Function(_$_StationStatus) _then) |
||||||
|
: super(_value, _then); |
||||||
|
|
||||||
|
@pragma('vm:prefer-inline') |
||||||
|
@override |
||||||
|
$Res call({ |
||||||
|
Object? delay = null, |
||||||
|
Object? real = null, |
||||||
|
Object? cancelled = null, |
||||||
|
Object? platform = freezed, |
||||||
|
}) { |
||||||
|
return _then(_$_StationStatus( |
||||||
|
delay: null == delay |
||||||
|
? _value.delay |
||||||
|
: delay // ignore: cast_nullable_to_non_nullable |
||||||
|
as int, |
||||||
|
real: null == real |
||||||
|
? _value.real |
||||||
|
: real // ignore: cast_nullable_to_non_nullable |
||||||
|
as bool, |
||||||
|
cancelled: null == cancelled |
||||||
|
? _value.cancelled |
||||||
|
: cancelled // ignore: cast_nullable_to_non_nullable |
||||||
|
as bool, |
||||||
|
platform: freezed == platform |
||||||
|
? _value.platform |
||||||
|
: platform // ignore: cast_nullable_to_non_nullable |
||||||
|
as String?, |
||||||
|
)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
@JsonSerializable() |
||||||
|
class _$_StationStatus implements _StationStatus { |
||||||
|
const _$_StationStatus( |
||||||
|
{required this.delay, |
||||||
|
required this.real, |
||||||
|
required this.cancelled, |
||||||
|
required this.platform}); |
||||||
|
|
||||||
|
factory _$_StationStatus.fromJson(Map<String, dynamic> json) => |
||||||
|
_$$_StationStatusFromJson(json); |
||||||
|
|
||||||
|
@override |
||||||
|
final int delay; |
||||||
|
@override |
||||||
|
final bool real; |
||||||
|
@override |
||||||
|
final bool cancelled; |
||||||
|
@override |
||||||
|
final String? platform; |
||||||
|
|
||||||
|
@override |
||||||
|
String toString() { |
||||||
|
return 'StationStatus(delay: $delay, real: $real, cancelled: $cancelled, platform: $platform)'; |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
bool operator ==(dynamic other) { |
||||||
|
return identical(this, other) || |
||||||
|
(other.runtimeType == runtimeType && |
||||||
|
other is _$_StationStatus && |
||||||
|
(identical(other.delay, delay) || other.delay == delay) && |
||||||
|
(identical(other.real, real) || other.real == real) && |
||||||
|
(identical(other.cancelled, cancelled) || |
||||||
|
other.cancelled == cancelled) && |
||||||
|
(identical(other.platform, platform) || |
||||||
|
other.platform == platform)); |
||||||
|
} |
||||||
|
|
||||||
|
@JsonKey(ignore: true) |
||||||
|
@override |
||||||
|
int get hashCode => |
||||||
|
Object.hash(runtimeType, delay, real, cancelled, platform); |
||||||
|
|
||||||
|
@JsonKey(ignore: true) |
||||||
|
@override |
||||||
|
@pragma('vm:prefer-inline') |
||||||
|
_$$_StationStatusCopyWith<_$_StationStatus> get copyWith => |
||||||
|
__$$_StationStatusCopyWithImpl<_$_StationStatus>(this, _$identity); |
||||||
|
|
||||||
|
@override |
||||||
|
Map<String, dynamic> toJson() { |
||||||
|
return _$$_StationStatusToJson( |
||||||
|
this, |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
abstract class _StationStatus implements StationStatus { |
||||||
|
const factory _StationStatus( |
||||||
|
{required final int delay, |
||||||
|
required final bool real, |
||||||
|
required final bool cancelled, |
||||||
|
required final String? platform}) = _$_StationStatus; |
||||||
|
|
||||||
|
factory _StationStatus.fromJson(Map<String, dynamic> json) = |
||||||
|
_$_StationStatus.fromJson; |
||||||
|
|
||||||
|
@override |
||||||
|
int get delay; |
||||||
|
@override |
||||||
|
bool get real; |
||||||
|
@override |
||||||
|
bool get cancelled; |
||||||
|
@override |
||||||
|
String? get platform; |
||||||
|
@override |
||||||
|
@JsonKey(ignore: true) |
||||||
|
_$$_StationStatusCopyWith<_$_StationStatus> get copyWith => |
||||||
|
throw _privateConstructorUsedError; |
||||||
|
} |
@ -0,0 +1,23 @@ |
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND |
||||||
|
|
||||||
|
part of 'station_status.dart'; |
||||||
|
|
||||||
|
// ************************************************************************** |
||||||
|
// JsonSerializableGenerator |
||||||
|
// ************************************************************************** |
||||||
|
|
||||||
|
_$_StationStatus _$$_StationStatusFromJson(Map<String, dynamic> json) => |
||||||
|
_$_StationStatus( |
||||||
|
delay: json['delay'] as int, |
||||||
|
real: json['real'] as bool, |
||||||
|
cancelled: json['cancelled'] as bool, |
||||||
|
platform: json['platform'] as String?, |
||||||
|
); |
||||||
|
|
||||||
|
Map<String, dynamic> _$$_StationStatusToJson(_$_StationStatus instance) => |
||||||
|
<String, dynamic>{ |
||||||
|
'delay': instance.delay, |
||||||
|
'real': instance.real, |
||||||
|
'cancelled': instance.cancelled, |
||||||
|
'platform': instance.platform, |
||||||
|
}; |
@ -0,0 +1,19 @@ |
|||||||
|
import 'package:freezed_annotation/freezed_annotation.dart'; |
||||||
|
|
||||||
|
part 'station_train.g.dart'; |
||||||
|
part 'station_train.freezed.dart'; |
||||||
|
|
||||||
|
@freezed |
||||||
|
class StationTrain with _$StationTrain { |
||||||
|
const factory StationTrain({ |
||||||
|
required String rank, |
||||||
|
required String number, |
||||||
|
required String operator, |
||||||
|
required String terminus, |
||||||
|
List<String>? route, |
||||||
|
required DateTime departureDate, |
||||||
|
}) = _StationTrain; |
||||||
|
|
||||||
|
factory StationTrain.fromJson(Map<String, dynamic> json) => _$StationTrainFromJson(json); |
||||||
|
} |
||||||
|
|
@ -0,0 +1,268 @@ |
|||||||
|
// coverage:ignore-file |
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND |
||||||
|
// ignore_for_file: type=lint |
||||||
|
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark |
||||||
|
|
||||||
|
part of 'station_train.dart'; |
||||||
|
|
||||||
|
// ************************************************************************** |
||||||
|
// FreezedGenerator |
||||||
|
// ************************************************************************** |
||||||
|
|
||||||
|
T _$identity<T>(T value) => value; |
||||||
|
|
||||||
|
final _privateConstructorUsedError = UnsupportedError( |
||||||
|
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); |
||||||
|
|
||||||
|
StationTrain _$StationTrainFromJson(Map<String, dynamic> json) { |
||||||
|
return _StationTrain.fromJson(json); |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
mixin _$StationTrain { |
||||||
|
String get rank => throw _privateConstructorUsedError; |
||||||
|
String get number => throw _privateConstructorUsedError; |
||||||
|
String get operator => throw _privateConstructorUsedError; |
||||||
|
String get terminus => throw _privateConstructorUsedError; |
||||||
|
List<String>? get route => throw _privateConstructorUsedError; |
||||||
|
DateTime get departureDate => throw _privateConstructorUsedError; |
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError; |
||||||
|
@JsonKey(ignore: true) |
||||||
|
$StationTrainCopyWith<StationTrain> get copyWith => |
||||||
|
throw _privateConstructorUsedError; |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
abstract class $StationTrainCopyWith<$Res> { |
||||||
|
factory $StationTrainCopyWith( |
||||||
|
StationTrain value, $Res Function(StationTrain) then) = |
||||||
|
_$StationTrainCopyWithImpl<$Res, StationTrain>; |
||||||
|
@useResult |
||||||
|
$Res call( |
||||||
|
{String rank, |
||||||
|
String number, |
||||||
|
String operator, |
||||||
|
String terminus, |
||||||
|
List<String>? route, |
||||||
|
DateTime departureDate}); |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
class _$StationTrainCopyWithImpl<$Res, $Val extends StationTrain> |
||||||
|
implements $StationTrainCopyWith<$Res> { |
||||||
|
_$StationTrainCopyWithImpl(this._value, this._then); |
||||||
|
|
||||||
|
// ignore: unused_field |
||||||
|
final $Val _value; |
||||||
|
// ignore: unused_field |
||||||
|
final $Res Function($Val) _then; |
||||||
|
|
||||||
|
@pragma('vm:prefer-inline') |
||||||
|
@override |
||||||
|
$Res call({ |
||||||
|
Object? rank = null, |
||||||
|
Object? number = null, |
||||||
|
Object? operator = null, |
||||||
|
Object? terminus = null, |
||||||
|
Object? route = freezed, |
||||||
|
Object? departureDate = null, |
||||||
|
}) { |
||||||
|
return _then(_value.copyWith( |
||||||
|
rank: null == rank |
||||||
|
? _value.rank |
||||||
|
: rank // ignore: cast_nullable_to_non_nullable |
||||||
|
as String, |
||||||
|
number: null == number |
||||||
|
? _value.number |
||||||
|
: number // ignore: cast_nullable_to_non_nullable |
||||||
|
as String, |
||||||
|
operator: null == operator |
||||||
|
? _value.operator |
||||||
|
: operator // ignore: cast_nullable_to_non_nullable |
||||||
|
as String, |
||||||
|
terminus: null == terminus |
||||||
|
? _value.terminus |
||||||
|
: terminus // ignore: cast_nullable_to_non_nullable |
||||||
|
as String, |
||||||
|
route: freezed == route |
||||||
|
? _value.route |
||||||
|
: route // ignore: cast_nullable_to_non_nullable |
||||||
|
as List<String>?, |
||||||
|
departureDate: null == departureDate |
||||||
|
? _value.departureDate |
||||||
|
: departureDate // ignore: cast_nullable_to_non_nullable |
||||||
|
as DateTime, |
||||||
|
) as $Val); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
abstract class _$$_StationTrainCopyWith<$Res> |
||||||
|
implements $StationTrainCopyWith<$Res> { |
||||||
|
factory _$$_StationTrainCopyWith( |
||||||
|
_$_StationTrain value, $Res Function(_$_StationTrain) then) = |
||||||
|
__$$_StationTrainCopyWithImpl<$Res>; |
||||||
|
@override |
||||||
|
@useResult |
||||||
|
$Res call( |
||||||
|
{String rank, |
||||||
|
String number, |
||||||
|
String operator, |
||||||
|
String terminus, |
||||||
|
List<String>? route, |
||||||
|
DateTime departureDate}); |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
class __$$_StationTrainCopyWithImpl<$Res> |
||||||
|
extends _$StationTrainCopyWithImpl<$Res, _$_StationTrain> |
||||||
|
implements _$$_StationTrainCopyWith<$Res> { |
||||||
|
__$$_StationTrainCopyWithImpl( |
||||||
|
_$_StationTrain _value, $Res Function(_$_StationTrain) _then) |
||||||
|
: super(_value, _then); |
||||||
|
|
||||||
|
@pragma('vm:prefer-inline') |
||||||
|
@override |
||||||
|
$Res call({ |
||||||
|
Object? rank = null, |
||||||
|
Object? number = null, |
||||||
|
Object? operator = null, |
||||||
|
Object? terminus = null, |
||||||
|
Object? route = freezed, |
||||||
|
Object? departureDate = null, |
||||||
|
}) { |
||||||
|
return _then(_$_StationTrain( |
||||||
|
rank: null == rank |
||||||
|
? _value.rank |
||||||
|
: rank // ignore: cast_nullable_to_non_nullable |
||||||
|
as String, |
||||||
|
number: null == number |
||||||
|
? _value.number |
||||||
|
: number // ignore: cast_nullable_to_non_nullable |
||||||
|
as String, |
||||||
|
operator: null == operator |
||||||
|
? _value.operator |
||||||
|
: operator // ignore: cast_nullable_to_non_nullable |
||||||
|
as String, |
||||||
|
terminus: null == terminus |
||||||
|
? _value.terminus |
||||||
|
: terminus // ignore: cast_nullable_to_non_nullable |
||||||
|
as String, |
||||||
|
route: freezed == route |
||||||
|
? _value._route |
||||||
|
: route // ignore: cast_nullable_to_non_nullable |
||||||
|
as List<String>?, |
||||||
|
departureDate: null == departureDate |
||||||
|
? _value.departureDate |
||||||
|
: departureDate // ignore: cast_nullable_to_non_nullable |
||||||
|
as DateTime, |
||||||
|
)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
@JsonSerializable() |
||||||
|
class _$_StationTrain implements _StationTrain { |
||||||
|
const _$_StationTrain( |
||||||
|
{required this.rank, |
||||||
|
required this.number, |
||||||
|
required this.operator, |
||||||
|
required this.terminus, |
||||||
|
final List<String>? route, |
||||||
|
required this.departureDate}) |
||||||
|
: _route = route; |
||||||
|
|
||||||
|
factory _$_StationTrain.fromJson(Map<String, dynamic> json) => |
||||||
|
_$$_StationTrainFromJson(json); |
||||||
|
|
||||||
|
@override |
||||||
|
final String rank; |
||||||
|
@override |
||||||
|
final String number; |
||||||
|
@override |
||||||
|
final String operator; |
||||||
|
@override |
||||||
|
final String terminus; |
||||||
|
final List<String>? _route; |
||||||
|
@override |
||||||
|
List<String>? get route { |
||||||
|
final value = _route; |
||||||
|
if (value == null) return null; |
||||||
|
if (_route is EqualUnmodifiableListView) return _route; |
||||||
|
// ignore: implicit_dynamic_type |
||||||
|
return EqualUnmodifiableListView(value); |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
final DateTime departureDate; |
||||||
|
|
||||||
|
@override |
||||||
|
String toString() { |
||||||
|
return 'StationTrain(rank: $rank, number: $number, operator: $operator, terminus: $terminus, route: $route, departureDate: $departureDate)'; |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
bool operator ==(dynamic other) { |
||||||
|
return identical(this, other) || |
||||||
|
(other.runtimeType == runtimeType && |
||||||
|
other is _$_StationTrain && |
||||||
|
(identical(other.rank, rank) || other.rank == rank) && |
||||||
|
(identical(other.number, number) || other.number == number) && |
||||||
|
(identical(other.operator, operator) || |
||||||
|
other.operator == operator) && |
||||||
|
(identical(other.terminus, terminus) || |
||||||
|
other.terminus == terminus) && |
||||||
|
const DeepCollectionEquality().equals(other._route, _route) && |
||||||
|
(identical(other.departureDate, departureDate) || |
||||||
|
other.departureDate == departureDate)); |
||||||
|
} |
||||||
|
|
||||||
|
@JsonKey(ignore: true) |
||||||
|
@override |
||||||
|
int get hashCode => Object.hash(runtimeType, rank, number, operator, terminus, |
||||||
|
const DeepCollectionEquality().hash(_route), departureDate); |
||||||
|
|
||||||
|
@JsonKey(ignore: true) |
||||||
|
@override |
||||||
|
@pragma('vm:prefer-inline') |
||||||
|
_$$_StationTrainCopyWith<_$_StationTrain> get copyWith => |
||||||
|
__$$_StationTrainCopyWithImpl<_$_StationTrain>(this, _$identity); |
||||||
|
|
||||||
|
@override |
||||||
|
Map<String, dynamic> toJson() { |
||||||
|
return _$$_StationTrainToJson( |
||||||
|
this, |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
abstract class _StationTrain implements StationTrain { |
||||||
|
const factory _StationTrain( |
||||||
|
{required final String rank, |
||||||
|
required final String number, |
||||||
|
required final String operator, |
||||||
|
required final String terminus, |
||||||
|
final List<String>? route, |
||||||
|
required final DateTime departureDate}) = _$_StationTrain; |
||||||
|
|
||||||
|
factory _StationTrain.fromJson(Map<String, dynamic> json) = |
||||||
|
_$_StationTrain.fromJson; |
||||||
|
|
||||||
|
@override |
||||||
|
String get rank; |
||||||
|
@override |
||||||
|
String get number; |
||||||
|
@override |
||||||
|
String get operator; |
||||||
|
@override |
||||||
|
String get terminus; |
||||||
|
@override |
||||||
|
List<String>? get route; |
||||||
|
@override |
||||||
|
DateTime get departureDate; |
||||||
|
@override |
||||||
|
@JsonKey(ignore: true) |
||||||
|
_$$_StationTrainCopyWith<_$_StationTrain> get copyWith => |
||||||
|
throw _privateConstructorUsedError; |
||||||
|
} |
@ -0,0 +1,28 @@ |
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND |
||||||
|
|
||||||
|
part of 'station_train.dart'; |
||||||
|
|
||||||
|
// ************************************************************************** |
||||||
|
// JsonSerializableGenerator |
||||||
|
// ************************************************************************** |
||||||
|
|
||||||
|
_$_StationTrain _$$_StationTrainFromJson(Map<String, dynamic> json) => |
||||||
|
_$_StationTrain( |
||||||
|
rank: json['rank'] as String, |
||||||
|
number: json['number'] as String, |
||||||
|
operator: json['operator'] as String, |
||||||
|
terminus: json['terminus'] as String, |
||||||
|
route: |
||||||
|
(json['route'] as List<dynamic>?)?.map((e) => e as String).toList(), |
||||||
|
departureDate: DateTime.parse(json['departureDate'] as String), |
||||||
|
); |
||||||
|
|
||||||
|
Map<String, dynamic> _$$_StationTrainToJson(_$_StationTrain instance) => |
||||||
|
<String, dynamic>{ |
||||||
|
'rank': instance.rank, |
||||||
|
'number': instance.number, |
||||||
|
'operator': instance.operator, |
||||||
|
'terminus': instance.terminus, |
||||||
|
'route': instance.route, |
||||||
|
'departureDate': instance.departureDate.toIso8601String(), |
||||||
|
}; |
@ -1,14 +1,14 @@ |
|||||||
import 'package:json_annotation/json_annotation.dart'; |
import 'package:freezed_annotation/freezed_annotation.dart'; |
||||||
|
|
||||||
part 'stations_result.g.dart'; |
part 'stations_result.g.dart'; |
||||||
|
part 'stations_result.freezed.dart'; |
||||||
|
|
||||||
@JsonSerializable() |
@freezed |
||||||
class StationsResult { |
class StationsResult with _$StationsResult { |
||||||
final String name; |
const factory StationsResult({ |
||||||
final List<String>? stoppedAtBy; |
required String name, |
||||||
|
List<String>? stoppedAtBy, |
||||||
const StationsResult({required this.name, this.stoppedAtBy}); |
}) = _StationsResult; |
||||||
|
|
||||||
factory StationsResult.fromJson(Map<String, dynamic> json) => _$StationsResultFromJson(json); |
factory StationsResult.fromJson(Map<String, dynamic> json) => _$StationsResultFromJson(json); |
||||||
Map<String, dynamic> toJson() => _$StationsResultToJson(this); |
|
||||||
} |
} |
@ -0,0 +1,179 @@ |
|||||||
|
// coverage:ignore-file |
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND |
||||||
|
// ignore_for_file: type=lint |
||||||
|
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark |
||||||
|
|
||||||
|
part of 'stations_result.dart'; |
||||||
|
|
||||||
|
// ************************************************************************** |
||||||
|
// FreezedGenerator |
||||||
|
// ************************************************************************** |
||||||
|
|
||||||
|
T _$identity<T>(T value) => value; |
||||||
|
|
||||||
|
final _privateConstructorUsedError = UnsupportedError( |
||||||
|
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); |
||||||
|
|
||||||
|
StationsResult _$StationsResultFromJson(Map<String, dynamic> json) { |
||||||
|
return _StationsResult.fromJson(json); |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
mixin _$StationsResult { |
||||||
|
String get name => throw _privateConstructorUsedError; |
||||||
|
List<String>? get stoppedAtBy => throw _privateConstructorUsedError; |
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError; |
||||||
|
@JsonKey(ignore: true) |
||||||
|
$StationsResultCopyWith<StationsResult> get copyWith => |
||||||
|
throw _privateConstructorUsedError; |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
abstract class $StationsResultCopyWith<$Res> { |
||||||
|
factory $StationsResultCopyWith( |
||||||
|
StationsResult value, $Res Function(StationsResult) then) = |
||||||
|
_$StationsResultCopyWithImpl<$Res, StationsResult>; |
||||||
|
@useResult |
||||||
|
$Res call({String name, List<String>? stoppedAtBy}); |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
class _$StationsResultCopyWithImpl<$Res, $Val extends StationsResult> |
||||||
|
implements $StationsResultCopyWith<$Res> { |
||||||
|
_$StationsResultCopyWithImpl(this._value, this._then); |
||||||
|
|
||||||
|
// ignore: unused_field |
||||||
|
final $Val _value; |
||||||
|
// ignore: unused_field |
||||||
|
final $Res Function($Val) _then; |
||||||
|
|
||||||
|
@pragma('vm:prefer-inline') |
||||||
|
@override |
||||||
|
$Res call({ |
||||||
|
Object? name = null, |
||||||
|
Object? stoppedAtBy = freezed, |
||||||
|
}) { |
||||||
|
return _then(_value.copyWith( |
||||||
|
name: null == name |
||||||
|
? _value.name |
||||||
|
: name // ignore: cast_nullable_to_non_nullable |
||||||
|
as String, |
||||||
|
stoppedAtBy: freezed == stoppedAtBy |
||||||
|
? _value.stoppedAtBy |
||||||
|
: stoppedAtBy // ignore: cast_nullable_to_non_nullable |
||||||
|
as List<String>?, |
||||||
|
) as $Val); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
abstract class _$$_StationsResultCopyWith<$Res> |
||||||
|
implements $StationsResultCopyWith<$Res> { |
||||||
|
factory _$$_StationsResultCopyWith( |
||||||
|
_$_StationsResult value, $Res Function(_$_StationsResult) then) = |
||||||
|
__$$_StationsResultCopyWithImpl<$Res>; |
||||||
|
@override |
||||||
|
@useResult |
||||||
|
$Res call({String name, List<String>? stoppedAtBy}); |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
class __$$_StationsResultCopyWithImpl<$Res> |
||||||
|
extends _$StationsResultCopyWithImpl<$Res, _$_StationsResult> |
||||||
|
implements _$$_StationsResultCopyWith<$Res> { |
||||||
|
__$$_StationsResultCopyWithImpl( |
||||||
|
_$_StationsResult _value, $Res Function(_$_StationsResult) _then) |
||||||
|
: super(_value, _then); |
||||||
|
|
||||||
|
@pragma('vm:prefer-inline') |
||||||
|
@override |
||||||
|
$Res call({ |
||||||
|
Object? name = null, |
||||||
|
Object? stoppedAtBy = freezed, |
||||||
|
}) { |
||||||
|
return _then(_$_StationsResult( |
||||||
|
name: null == name |
||||||
|
? _value.name |
||||||
|
: name // ignore: cast_nullable_to_non_nullable |
||||||
|
as String, |
||||||
|
stoppedAtBy: freezed == stoppedAtBy |
||||||
|
? _value._stoppedAtBy |
||||||
|
: stoppedAtBy // ignore: cast_nullable_to_non_nullable |
||||||
|
as List<String>?, |
||||||
|
)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
@JsonSerializable() |
||||||
|
class _$_StationsResult implements _StationsResult { |
||||||
|
const _$_StationsResult({required this.name, final List<String>? stoppedAtBy}) |
||||||
|
: _stoppedAtBy = stoppedAtBy; |
||||||
|
|
||||||
|
factory _$_StationsResult.fromJson(Map<String, dynamic> json) => |
||||||
|
_$$_StationsResultFromJson(json); |
||||||
|
|
||||||
|
@override |
||||||
|
final String name; |
||||||
|
final List<String>? _stoppedAtBy; |
||||||
|
@override |
||||||
|
List<String>? get stoppedAtBy { |
||||||
|
final value = _stoppedAtBy; |
||||||
|
if (value == null) return null; |
||||||
|
if (_stoppedAtBy is EqualUnmodifiableListView) return _stoppedAtBy; |
||||||
|
// ignore: implicit_dynamic_type |
||||||
|
return EqualUnmodifiableListView(value); |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
String toString() { |
||||||
|
return 'StationsResult(name: $name, stoppedAtBy: $stoppedAtBy)'; |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
bool operator ==(dynamic other) { |
||||||
|
return identical(this, other) || |
||||||
|
(other.runtimeType == runtimeType && |
||||||
|
other is _$_StationsResult && |
||||||
|
(identical(other.name, name) || other.name == name) && |
||||||
|
const DeepCollectionEquality() |
||||||
|
.equals(other._stoppedAtBy, _stoppedAtBy)); |
||||||
|
} |
||||||
|
|
||||||
|
@JsonKey(ignore: true) |
||||||
|
@override |
||||||
|
int get hashCode => Object.hash( |
||||||
|
runtimeType, name, const DeepCollectionEquality().hash(_stoppedAtBy)); |
||||||
|
|
||||||
|
@JsonKey(ignore: true) |
||||||
|
@override |
||||||
|
@pragma('vm:prefer-inline') |
||||||
|
_$$_StationsResultCopyWith<_$_StationsResult> get copyWith => |
||||||
|
__$$_StationsResultCopyWithImpl<_$_StationsResult>(this, _$identity); |
||||||
|
|
||||||
|
@override |
||||||
|
Map<String, dynamic> toJson() { |
||||||
|
return _$$_StationsResultToJson( |
||||||
|
this, |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
abstract class _StationsResult implements StationsResult { |
||||||
|
const factory _StationsResult( |
||||||
|
{required final String name, |
||||||
|
final List<String>? stoppedAtBy}) = _$_StationsResult; |
||||||
|
|
||||||
|
factory _StationsResult.fromJson(Map<String, dynamic> json) = |
||||||
|
_$_StationsResult.fromJson; |
||||||
|
|
||||||
|
@override |
||||||
|
String get name; |
||||||
|
@override |
||||||
|
List<String>? get stoppedAtBy; |
||||||
|
@override |
||||||
|
@JsonKey(ignore: true) |
||||||
|
_$$_StationsResultCopyWith<_$_StationsResult> get copyWith => |
||||||
|
throw _privateConstructorUsedError; |
||||||
|
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,217 @@ |
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND |
||||||
|
|
||||||
|
part of 'train_data.dart'; |
||||||
|
|
||||||
|
// ************************************************************************** |
||||||
|
// JsonSerializableGenerator |
||||||
|
// ************************************************************************** |
||||||
|
|
||||||
|
_$_TrainData _$$_TrainDataFromJson(Map<String, dynamic> json) => _$_TrainData( |
||||||
|
rank: json['rank'] as String, |
||||||
|
number: json['number'] as String, |
||||||
|
date: json['date'] as String, |
||||||
|
operator: json['operator'] as String, |
||||||
|
groups: (json['groups'] as List<dynamic>) |
||||||
|
.map((e) => TrainDataGroup.fromJson(e as Map<String, dynamic>)) |
||||||
|
.toList(), |
||||||
|
); |
||||||
|
|
||||||
|
Map<String, dynamic> _$$_TrainDataToJson(_$_TrainData instance) => |
||||||
|
<String, dynamic>{ |
||||||
|
'rank': instance.rank, |
||||||
|
'number': instance.number, |
||||||
|
'date': instance.date, |
||||||
|
'operator': instance.operator, |
||||||
|
'groups': instance.groups, |
||||||
|
}; |
||||||
|
|
||||||
|
_$_TrainDataGroup _$$_TrainDataGroupFromJson(Map<String, dynamic> json) => |
||||||
|
_$_TrainDataGroup( |
||||||
|
route: TrainDataRoute.fromJson(json['route'] as Map<String, dynamic>), |
||||||
|
stations: (json['stations'] as List<dynamic>) |
||||||
|
.map((e) => TrainDataStation.fromJson(e as Map<String, dynamic>)) |
||||||
|
.toList(), |
||||||
|
status: json['status'] == null |
||||||
|
? null |
||||||
|
: TrainDataStatus.fromJson(json['status'] as Map<String, dynamic>), |
||||||
|
); |
||||||
|
|
||||||
|
Map<String, dynamic> _$$_TrainDataGroupToJson(_$_TrainDataGroup instance) => |
||||||
|
<String, dynamic>{ |
||||||
|
'route': instance.route, |
||||||
|
'stations': instance.stations, |
||||||
|
'status': instance.status, |
||||||
|
}; |
||||||
|
|
||||||
|
_$_TrainDataRoute _$$_TrainDataRouteFromJson(Map<String, dynamic> json) => |
||||||
|
_$_TrainDataRoute( |
||||||
|
from: json['from'] as String, |
||||||
|
to: json['to'] as String, |
||||||
|
); |
||||||
|
|
||||||
|
Map<String, dynamic> _$$_TrainDataRouteToJson(_$_TrainDataRoute instance) => |
||||||
|
<String, dynamic>{ |
||||||
|
'from': instance.from, |
||||||
|
'to': instance.to, |
||||||
|
}; |
||||||
|
|
||||||
|
_$_TrainDataStation _$$_TrainDataStationFromJson(Map<String, dynamic> json) => |
||||||
|
_$_TrainDataStation( |
||||||
|
name: json['name'] as String, |
||||||
|
linkName: json['linkName'] as String, |
||||||
|
km: json['km'] as int, |
||||||
|
stoppingTime: json['stoppingTime'] as int?, |
||||||
|
platform: json['platform'] as String?, |
||||||
|
arrival: json['arrival'] == null |
||||||
|
? null |
||||||
|
: StationArrDepTime.fromJson(json['arrival'] as Map<String, dynamic>), |
||||||
|
departure: json['departure'] == null |
||||||
|
? null |
||||||
|
: StationArrDepTime.fromJson( |
||||||
|
json['departure'] as Map<String, dynamic>), |
||||||
|
notes: (json['notes'] as List<dynamic>) |
||||||
|
.map((e) => const TrainDataNoteConverter() |
||||||
|
.fromJson(e as Map<String, dynamic>)) |
||||||
|
.toList(), |
||||||
|
); |
||||||
|
|
||||||
|
Map<String, dynamic> _$$_TrainDataStationToJson(_$_TrainDataStation instance) => |
||||||
|
<String, dynamic>{ |
||||||
|
'name': instance.name, |
||||||
|
'linkName': instance.linkName, |
||||||
|
'km': instance.km, |
||||||
|
'stoppingTime': instance.stoppingTime, |
||||||
|
'platform': instance.platform, |
||||||
|
'arrival': instance.arrival, |
||||||
|
'departure': instance.departure, |
||||||
|
'notes': |
||||||
|
instance.notes.map(const TrainDataNoteConverter().toJson).toList(), |
||||||
|
}; |
||||||
|
|
||||||
|
_$_StationArrDepTime _$$_StationArrDepTimeFromJson(Map<String, dynamic> json) => |
||||||
|
_$_StationArrDepTime( |
||||||
|
scheduleTime: DateTime.parse(json['scheduleTime'] as String), |
||||||
|
status: json['status'] == null |
||||||
|
? null |
||||||
|
: StationArrDepTimeStatus.fromJson( |
||||||
|
json['status'] as Map<String, dynamic>), |
||||||
|
); |
||||||
|
|
||||||
|
Map<String, dynamic> _$$_StationArrDepTimeToJson( |
||||||
|
_$_StationArrDepTime instance) => |
||||||
|
<String, dynamic>{ |
||||||
|
'scheduleTime': instance.scheduleTime.toIso8601String(), |
||||||
|
'status': instance.status, |
||||||
|
}; |
||||||
|
|
||||||
|
_$_StationArrDepTimeStatus _$$_StationArrDepTimeStatusFromJson( |
||||||
|
Map<String, dynamic> json) => |
||||||
|
_$_StationArrDepTimeStatus( |
||||||
|
delay: json['delay'] as int, |
||||||
|
real: json['real'] as bool, |
||||||
|
cancelled: json['cancelled'] as bool, |
||||||
|
); |
||||||
|
|
||||||
|
Map<String, dynamic> _$$_StationArrDepTimeStatusToJson( |
||||||
|
_$_StationArrDepTimeStatus instance) => |
||||||
|
<String, dynamic>{ |
||||||
|
'delay': instance.delay, |
||||||
|
'real': instance.real, |
||||||
|
'cancelled': instance.cancelled, |
||||||
|
}; |
||||||
|
|
||||||
|
_$_TrainDataStatus _$$_TrainDataStatusFromJson(Map<String, dynamic> json) => |
||||||
|
_$_TrainDataStatus( |
||||||
|
delay: json['delay'] as int, |
||||||
|
station: json['station'] as String, |
||||||
|
state: $enumDecode(_$TrainDataStatusStateEnumMap, json['state']), |
||||||
|
); |
||||||
|
|
||||||
|
Map<String, dynamic> _$$_TrainDataStatusToJson(_$_TrainDataStatus instance) => |
||||||
|
<String, dynamic>{ |
||||||
|
'delay': instance.delay, |
||||||
|
'station': instance.station, |
||||||
|
'state': _$TrainDataStatusStateEnumMap[instance.state]!, |
||||||
|
}; |
||||||
|
|
||||||
|
const _$TrainDataStatusStateEnumMap = { |
||||||
|
TrainDataStatusState.passing: 'passing', |
||||||
|
TrainDataStatusState.arrival: 'arrival', |
||||||
|
TrainDataStatusState.departure: 'departure', |
||||||
|
}; |
||||||
|
|
||||||
|
_$_TrainDataNoteTrainNumberChange _$$_TrainDataNoteTrainNumberChangeFromJson( |
||||||
|
Map<String, dynamic> json) => |
||||||
|
_$_TrainDataNoteTrainNumberChange( |
||||||
|
kind: json['kind'] as String? ?? "trainNumberChange", |
||||||
|
rank: json['rank'] as String, |
||||||
|
number: json['number'] as String, |
||||||
|
); |
||||||
|
|
||||||
|
Map<String, dynamic> _$$_TrainDataNoteTrainNumberChangeToJson( |
||||||
|
_$_TrainDataNoteTrainNumberChange instance) => |
||||||
|
<String, dynamic>{ |
||||||
|
'kind': instance.kind, |
||||||
|
'rank': instance.rank, |
||||||
|
'number': instance.number, |
||||||
|
}; |
||||||
|
|
||||||
|
_$_TrainDataNoteDepartsAs _$$_TrainDataNoteDepartsAsFromJson( |
||||||
|
Map<String, dynamic> json) => |
||||||
|
_$_TrainDataNoteDepartsAs( |
||||||
|
kind: json['kind'] as String? ?? "departsAs", |
||||||
|
rank: json['rank'] as String, |
||||||
|
number: json['number'] as String, |
||||||
|
departureDate: DateTime.parse(json['departureDate'] as String), |
||||||
|
); |
||||||
|
|
||||||
|
Map<String, dynamic> _$$_TrainDataNoteDepartsAsToJson( |
||||||
|
_$_TrainDataNoteDepartsAs instance) => |
||||||
|
<String, dynamic>{ |
||||||
|
'kind': instance.kind, |
||||||
|
'rank': instance.rank, |
||||||
|
'number': instance.number, |
||||||
|
'departureDate': instance.departureDate.toIso8601String(), |
||||||
|
}; |
||||||
|
|
||||||
|
_$_TrainDataNoteDetachingWagons _$$_TrainDataNoteDetachingWagonsFromJson( |
||||||
|
Map<String, dynamic> json) => |
||||||
|
_$_TrainDataNoteDetachingWagons( |
||||||
|
kind: json['kind'] as String? ?? "detachingWagons", |
||||||
|
station: json['station'] as String, |
||||||
|
); |
||||||
|
|
||||||
|
Map<String, dynamic> _$$_TrainDataNoteDetachingWagonsToJson( |
||||||
|
_$_TrainDataNoteDetachingWagons instance) => |
||||||
|
<String, dynamic>{ |
||||||
|
'kind': instance.kind, |
||||||
|
'station': instance.station, |
||||||
|
}; |
||||||
|
|
||||||
|
_$_TrainDataNoteReceivingWagons _$$_TrainDataNoteReceivingWagonsFromJson( |
||||||
|
Map<String, dynamic> json) => |
||||||
|
_$_TrainDataNoteReceivingWagons( |
||||||
|
kind: json['kind'] as String? ?? "receivingWagons", |
||||||
|
station: json['station'] as String, |
||||||
|
); |
||||||
|
|
||||||
|
Map<String, dynamic> _$$_TrainDataNoteReceivingWagonsToJson( |
||||||
|
_$_TrainDataNoteReceivingWagons instance) => |
||||||
|
<String, dynamic>{ |
||||||
|
'kind': instance.kind, |
||||||
|
'station': instance.station, |
||||||
|
}; |
||||||
|
|
||||||
|
_$_TrainDataNoteUnknown _$$_TrainDataNoteUnknownFromJson( |
||||||
|
Map<String, dynamic> json) => |
||||||
|
_$_TrainDataNoteUnknown( |
||||||
|
kind: json['kind'] as String, |
||||||
|
extra: json['extra'] as Map<String, dynamic>, |
||||||
|
); |
||||||
|
|
||||||
|
Map<String, dynamic> _$$_TrainDataNoteUnknownToJson( |
||||||
|
_$_TrainDataNoteUnknown instance) => |
||||||
|
<String, dynamic>{ |
||||||
|
'kind': instance.kind, |
||||||
|
'extra': instance.extra, |
||||||
|
}; |
@ -1,42 +0,0 @@ |
|||||||
import 'package:json_annotation/json_annotation.dart'; |
|
||||||
|
|
||||||
part 'train_operator_lines.g.dart'; |
|
||||||
|
|
||||||
@JsonSerializable() |
|
||||||
class TrainOperatorLines { |
|
||||||
@JsonKey(name: "short_name") |
|
||||||
final String shortName; |
|
||||||
final String operator; |
|
||||||
@JsonKey(name: "versiune") |
|
||||||
final String version; |
|
||||||
@JsonKey(name: "trenuri") |
|
||||||
final List<TrainOperatorTrainDescription> trains; |
|
||||||
|
|
||||||
TrainOperatorLines({ |
|
||||||
required this.operator, |
|
||||||
this.shortName = "", |
|
||||||
required this.version, |
|
||||||
required this.trains, |
|
||||||
}); |
|
||||||
|
|
||||||
factory TrainOperatorLines.fromJson(Map<String, dynamic> json) => _$TrainOperatorLinesFromJson(json); |
|
||||||
Map<String, dynamic> toJson() => _$TrainOperatorLinesToJson(this); |
|
||||||
} |
|
||||||
|
|
||||||
@JsonSerializable() |
|
||||||
class TrainOperatorTrainDescription { |
|
||||||
final String rang; |
|
||||||
@JsonKey(name: "numar") |
|
||||||
final String number; |
|
||||||
@JsonKey(name: "numar_intern") |
|
||||||
final int internalNumber; |
|
||||||
|
|
||||||
TrainOperatorTrainDescription({ |
|
||||||
this.number = '', |
|
||||||
this.rang = '', |
|
||||||
this.internalNumber = 0, |
|
||||||
}); |
|
||||||
|
|
||||||
factory TrainOperatorTrainDescription.fromJson(Map<String, dynamic> json) => _$TrainOperatorTrainDescriptionFromJson(json); |
|
||||||
Map<String, dynamic> toJson() => _$TrainOperatorTrainDescriptionToJson(this); |
|
||||||
} |
|
@ -1,42 +0,0 @@ |
|||||||
// GENERATED CODE - DO NOT MODIFY BY HAND |
|
||||||
|
|
||||||
part of 'train_operator_lines.dart'; |
|
||||||
|
|
||||||
// ************************************************************************** |
|
||||||
// JsonSerializableGenerator |
|
||||||
// ************************************************************************** |
|
||||||
|
|
||||||
TrainOperatorLines _$TrainOperatorLinesFromJson(Map<String, dynamic> json) => |
|
||||||
TrainOperatorLines( |
|
||||||
operator: json['operator'] as String, |
|
||||||
shortName: json['short_name'] as String? ?? "", |
|
||||||
version: json['versiune'] as String, |
|
||||||
trains: (json['trenuri'] as List<dynamic>) |
|
||||||
.map((e) => |
|
||||||
TrainOperatorTrainDescription.fromJson(e as Map<String, dynamic>)) |
|
||||||
.toList(), |
|
||||||
); |
|
||||||
|
|
||||||
Map<String, dynamic> _$TrainOperatorLinesToJson(TrainOperatorLines instance) => |
|
||||||
<String, dynamic>{ |
|
||||||
'short_name': instance.shortName, |
|
||||||
'operator': instance.operator, |
|
||||||
'versiune': instance.version, |
|
||||||
'trenuri': instance.trains, |
|
||||||
}; |
|
||||||
|
|
||||||
TrainOperatorTrainDescription _$TrainOperatorTrainDescriptionFromJson( |
|
||||||
Map<String, dynamic> json) => |
|
||||||
TrainOperatorTrainDescription( |
|
||||||
number: json['numar'] as String? ?? '', |
|
||||||
rang: json['rang'] as String? ?? '', |
|
||||||
internalNumber: json['numar_intern'] as int? ?? 0, |
|
||||||
); |
|
||||||
|
|
||||||
Map<String, dynamic> _$TrainOperatorTrainDescriptionToJson( |
|
||||||
TrainOperatorTrainDescription instance) => |
|
||||||
<String, dynamic>{ |
|
||||||
'rang': instance.rang, |
|
||||||
'numar': instance.number, |
|
||||||
'numar_intern': instance.internalNumber, |
|
||||||
}; |
|
@ -0,0 +1,15 @@ |
|||||||
|
import 'package:freezed_annotation/freezed_annotation.dart'; |
||||||
|
|
||||||
|
part 'trains_result.g.dart'; |
||||||
|
part 'trains_result.freezed.dart'; |
||||||
|
|
||||||
|
@freezed |
||||||
|
class TrainsResult with _$TrainsResult { |
||||||
|
const factory TrainsResult({ |
||||||
|
required String rank, |
||||||
|
required String number, |
||||||
|
required String company, |
||||||
|
}) = _TrainsResult; |
||||||
|
|
||||||
|
factory TrainsResult.fromJson(Map<String, dynamic> json) => _$TrainsResultFromJson(json); |
||||||
|
} |
@ -0,0 +1,187 @@ |
|||||||
|
// coverage:ignore-file |
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND |
||||||
|
// ignore_for_file: type=lint |
||||||
|
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark |
||||||
|
|
||||||
|
part of 'trains_result.dart'; |
||||||
|
|
||||||
|
// ************************************************************************** |
||||||
|
// FreezedGenerator |
||||||
|
// ************************************************************************** |
||||||
|
|
||||||
|
T _$identity<T>(T value) => value; |
||||||
|
|
||||||
|
final _privateConstructorUsedError = UnsupportedError( |
||||||
|
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); |
||||||
|
|
||||||
|
TrainsResult _$TrainsResultFromJson(Map<String, dynamic> json) { |
||||||
|
return _TrainsResult.fromJson(json); |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
mixin _$TrainsResult { |
||||||
|
String get rank => throw _privateConstructorUsedError; |
||||||
|
String get number => throw _privateConstructorUsedError; |
||||||
|
String get company => throw _privateConstructorUsedError; |
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError; |
||||||
|
@JsonKey(ignore: true) |
||||||
|
$TrainsResultCopyWith<TrainsResult> get copyWith => |
||||||
|
throw _privateConstructorUsedError; |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
abstract class $TrainsResultCopyWith<$Res> { |
||||||
|
factory $TrainsResultCopyWith( |
||||||
|
TrainsResult value, $Res Function(TrainsResult) then) = |
||||||
|
_$TrainsResultCopyWithImpl<$Res, TrainsResult>; |
||||||
|
@useResult |
||||||
|
$Res call({String rank, String number, String company}); |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
class _$TrainsResultCopyWithImpl<$Res, $Val extends TrainsResult> |
||||||
|
implements $TrainsResultCopyWith<$Res> { |
||||||
|
_$TrainsResultCopyWithImpl(this._value, this._then); |
||||||
|
|
||||||
|
// ignore: unused_field |
||||||
|
final $Val _value; |
||||||
|
// ignore: unused_field |
||||||
|
final $Res Function($Val) _then; |
||||||
|
|
||||||
|
@pragma('vm:prefer-inline') |
||||||
|
@override |
||||||
|
$Res call({ |
||||||
|
Object? rank = null, |
||||||
|
Object? number = null, |
||||||
|
Object? company = null, |
||||||
|
}) { |
||||||
|
return _then(_value.copyWith( |
||||||
|
rank: null == rank |
||||||
|
? _value.rank |
||||||
|
: rank // ignore: cast_nullable_to_non_nullable |
||||||
|
as String, |
||||||
|
number: null == number |
||||||
|
? _value.number |
||||||
|
: number // ignore: cast_nullable_to_non_nullable |
||||||
|
as String, |
||||||
|
company: null == company |
||||||
|
? _value.company |
||||||
|
: company // ignore: cast_nullable_to_non_nullable |
||||||
|
as String, |
||||||
|
) as $Val); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
abstract class _$$_TrainsResultCopyWith<$Res> |
||||||
|
implements $TrainsResultCopyWith<$Res> { |
||||||
|
factory _$$_TrainsResultCopyWith( |
||||||
|
_$_TrainsResult value, $Res Function(_$_TrainsResult) then) = |
||||||
|
__$$_TrainsResultCopyWithImpl<$Res>; |
||||||
|
@override |
||||||
|
@useResult |
||||||
|
$Res call({String rank, String number, String company}); |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
class __$$_TrainsResultCopyWithImpl<$Res> |
||||||
|
extends _$TrainsResultCopyWithImpl<$Res, _$_TrainsResult> |
||||||
|
implements _$$_TrainsResultCopyWith<$Res> { |
||||||
|
__$$_TrainsResultCopyWithImpl( |
||||||
|
_$_TrainsResult _value, $Res Function(_$_TrainsResult) _then) |
||||||
|
: super(_value, _then); |
||||||
|
|
||||||
|
@pragma('vm:prefer-inline') |
||||||
|
@override |
||||||
|
$Res call({ |
||||||
|
Object? rank = null, |
||||||
|
Object? number = null, |
||||||
|
Object? company = null, |
||||||
|
}) { |
||||||
|
return _then(_$_TrainsResult( |
||||||
|
rank: null == rank |
||||||
|
? _value.rank |
||||||
|
: rank // ignore: cast_nullable_to_non_nullable |
||||||
|
as String, |
||||||
|
number: null == number |
||||||
|
? _value.number |
||||||
|
: number // ignore: cast_nullable_to_non_nullable |
||||||
|
as String, |
||||||
|
company: null == company |
||||||
|
? _value.company |
||||||
|
: company // ignore: cast_nullable_to_non_nullable |
||||||
|
as String, |
||||||
|
)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
@JsonSerializable() |
||||||
|
class _$_TrainsResult implements _TrainsResult { |
||||||
|
const _$_TrainsResult( |
||||||
|
{required this.rank, required this.number, required this.company}); |
||||||
|
|
||||||
|
factory _$_TrainsResult.fromJson(Map<String, dynamic> json) => |
||||||
|
_$$_TrainsResultFromJson(json); |
||||||
|
|
||||||
|
@override |
||||||
|
final String rank; |
||||||
|
@override |
||||||
|
final String number; |
||||||
|
@override |
||||||
|
final String company; |
||||||
|
|
||||||
|
@override |
||||||
|
String toString() { |
||||||
|
return 'TrainsResult(rank: $rank, number: $number, company: $company)'; |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
bool operator ==(dynamic other) { |
||||||
|
return identical(this, other) || |
||||||
|
(other.runtimeType == runtimeType && |
||||||
|
other is _$_TrainsResult && |
||||||
|
(identical(other.rank, rank) || other.rank == rank) && |
||||||
|
(identical(other.number, number) || other.number == number) && |
||||||
|
(identical(other.company, company) || other.company == company)); |
||||||
|
} |
||||||
|
|
||||||
|
@JsonKey(ignore: true) |
||||||
|
@override |
||||||
|
int get hashCode => Object.hash(runtimeType, rank, number, company); |
||||||
|
|
||||||
|
@JsonKey(ignore: true) |
||||||
|
@override |
||||||
|
@pragma('vm:prefer-inline') |
||||||
|
_$$_TrainsResultCopyWith<_$_TrainsResult> get copyWith => |
||||||
|
__$$_TrainsResultCopyWithImpl<_$_TrainsResult>(this, _$identity); |
||||||
|
|
||||||
|
@override |
||||||
|
Map<String, dynamic> toJson() { |
||||||
|
return _$$_TrainsResultToJson( |
||||||
|
this, |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
abstract class _TrainsResult implements TrainsResult { |
||||||
|
const factory _TrainsResult( |
||||||
|
{required final String rank, |
||||||
|
required final String number, |
||||||
|
required final String company}) = _$_TrainsResult; |
||||||
|
|
||||||
|
factory _TrainsResult.fromJson(Map<String, dynamic> json) = |
||||||
|
_$_TrainsResult.fromJson; |
||||||
|
|
||||||
|
@override |
||||||
|
String get rank; |
||||||
|
@override |
||||||
|
String get number; |
||||||
|
@override |
||||||
|
String get company; |
||||||
|
@override |
||||||
|
@JsonKey(ignore: true) |
||||||
|
_$$_TrainsResultCopyWith<_$_TrainsResult> get copyWith => |
||||||
|
throw _privateConstructorUsedError; |
||||||
|
} |
@ -0,0 +1,21 @@ |
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND |
||||||
|
|
||||||
|
part of 'trains_result.dart'; |
||||||
|
|
||||||
|
// ************************************************************************** |
||||||
|
// JsonSerializableGenerator |
||||||
|
// ************************************************************************** |
||||||
|
|
||||||
|
_$_TrainsResult _$$_TrainsResultFromJson(Map<String, dynamic> json) => |
||||||
|
_$_TrainsResult( |
||||||
|
rank: json['rank'] as String, |
||||||
|
number: json['number'] as String, |
||||||
|
company: json['company'] as String, |
||||||
|
); |
||||||
|
|
||||||
|
Map<String, dynamic> _$$_TrainsResultToJson(_$_TrainsResult instance) => |
||||||
|
<String, dynamic>{ |
||||||
|
'rank': instance.rank, |
||||||
|
'number': instance.number, |
||||||
|
'company': instance.company, |
||||||
|
}; |
@ -0,0 +1,94 @@ |
|||||||
|
import 'package:timezone/timezone.dart' as tz; |
||||||
|
|
||||||
|
enum UiTimeZoneType { |
||||||
|
ro, |
||||||
|
local, |
||||||
|
utc, |
||||||
|
iana, |
||||||
|
} |
||||||
|
|
||||||
|
extension UITimeZoneTypeName on UiTimeZoneType { |
||||||
|
String get userInterfaceName => (const { |
||||||
|
UiTimeZoneType.iana: 'Fus orar IANA', |
||||||
|
UiTimeZoneType.local: 'Local', |
||||||
|
UiTimeZoneType.ro: 'România', |
||||||
|
UiTimeZoneType.utc: 'UTC', |
||||||
|
})[this]!; |
||||||
|
} |
||||||
|
|
||||||
|
const Map<UiTimeZoneType, UiTimeZone Function(String)> fromSerStringConstructors = { |
||||||
|
UiTimeZoneType.ro: RoUiTimeZone.fromSerString, |
||||||
|
UiTimeZoneType.local: LocalUiTimeZone.fromSerString, |
||||||
|
UiTimeZoneType.utc: UtcUiTimeZone.fromSerString, |
||||||
|
UiTimeZoneType.iana: IanaUiTimeZone.fromSerString, |
||||||
|
}; |
||||||
|
|
||||||
|
abstract class UiTimeZone { |
||||||
|
final UiTimeZoneType type; |
||||||
|
|
||||||
|
const UiTimeZone({required this.type}); |
||||||
|
|
||||||
|
DateTime convertDateTime(DateTime dt); |
||||||
|
|
||||||
|
factory UiTimeZone.fromSerString(String ser) { |
||||||
|
final arr = ser.split('\n'); |
||||||
|
return fromSerStringConstructors.map((key, value) => MapEntry(key.name, value))[arr[0]]!(ser); |
||||||
|
} |
||||||
|
|
||||||
|
String toSerString() { |
||||||
|
return '${type.name}\n'; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
class RoUiTimeZone extends UiTimeZone { |
||||||
|
static final roTz = tz.getLocation('Europe/Bucharest'); |
||||||
|
|
||||||
|
const RoUiTimeZone() : super(type: UiTimeZoneType.ro); |
||||||
|
|
||||||
|
factory RoUiTimeZone.fromSerString(String ser) => const RoUiTimeZone(); |
||||||
|
|
||||||
|
@override |
||||||
|
DateTime convertDateTime(DateTime dt) { |
||||||
|
return tz.TZDateTime.from(dt, roTz); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
class LocalUiTimeZone extends UiTimeZone { |
||||||
|
const LocalUiTimeZone() : super(type: UiTimeZoneType.local); |
||||||
|
|
||||||
|
factory LocalUiTimeZone.fromSerString(String ser) => LocalUiTimeZone(); |
||||||
|
|
||||||
|
@override |
||||||
|
DateTime convertDateTime(DateTime dt) => dt.toLocal(); |
||||||
|
} |
||||||
|
|
||||||
|
class UtcUiTimeZone extends UiTimeZone { |
||||||
|
const UtcUiTimeZone() : super(type: UiTimeZoneType.utc); |
||||||
|
|
||||||
|
factory UtcUiTimeZone.fromSerString(String ser) => UtcUiTimeZone(); |
||||||
|
|
||||||
|
@override |
||||||
|
DateTime convertDateTime(DateTime dt) => dt.toUtc(); |
||||||
|
} |
||||||
|
|
||||||
|
class IanaUiTimeZone extends UiTimeZone { |
||||||
|
late final tz.Location location; |
||||||
|
|
||||||
|
IanaUiTimeZone({required String ianaName}): super(type: UiTimeZoneType.iana) { |
||||||
|
location = tz.getLocation(ianaName); |
||||||
|
} |
||||||
|
|
||||||
|
factory IanaUiTimeZone.fromSerString(String ser) => IanaUiTimeZone( |
||||||
|
ianaName: ser.split('\n').skip(1).join('\n'), |
||||||
|
); |
||||||
|
|
||||||
|
@override |
||||||
|
DateTime convertDateTime(DateTime dt) { |
||||||
|
return tz.TZDateTime.from(dt, location); |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
String toSerString() { |
||||||
|
return '${type.name}\n${location.name}'; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,80 @@ |
|||||||
|
import 'package:flutter/widgets.dart'; |
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart'; |
||||||
|
import 'package:info_tren/api/releases.dart'; |
||||||
|
import 'package:info_tren/models.dart'; |
||||||
|
import 'package:info_tren/pages/about/about_page_cupertino.dart'; |
||||||
|
import 'package:info_tren/pages/about/about_page_fluent.dart'; |
||||||
|
import 'package:info_tren/pages/about/about_page_material.dart'; |
||||||
|
import 'package:info_tren/providers.dart'; |
||||||
|
import 'package:package_info_plus/package_info_plus.dart'; |
||||||
|
|
||||||
|
class AboutPage extends ConsumerWidget { |
||||||
|
const AboutPage({super.key}); |
||||||
|
|
||||||
|
static String routeName = '/about'; |
||||||
|
|
||||||
|
@override |
||||||
|
Widget build(BuildContext context, WidgetRef ref) { |
||||||
|
final uiDesign = ref.watch(uiDesignProvider); |
||||||
|
|
||||||
|
switch (uiDesign) { |
||||||
|
case UiDesign.MATERIAL: |
||||||
|
return const AboutPageMaterial(); |
||||||
|
case UiDesign.CUPERTINO: |
||||||
|
return const AboutPageCupertino(); |
||||||
|
case UiDesign.FLUENT: |
||||||
|
return const AboutPageFluent(); |
||||||
|
default: |
||||||
|
throw UnmatchedUiDesignException(uiDesign); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
abstract class AboutPageShared extends StatefulWidget { |
||||||
|
const AboutPageShared({super.key}); |
||||||
|
} |
||||||
|
|
||||||
|
abstract class AboutPageState<T extends AboutPageShared> extends State<T> { |
||||||
|
static const String download = String.fromEnvironment('DOWNLOAD'); |
||||||
|
|
||||||
|
final String pageTitle = 'Despre aplicație'; |
||||||
|
final String versionTitleText = 'Versiunea aplicației'; |
||||||
|
final String latestVersionText = 'Cea mai recentă versiune'; |
||||||
|
final String currentVersionText = 'Versiunea curentă'; |
||||||
|
|
||||||
|
List<ChangelogEntry> localChangelog = []; |
||||||
|
List<ChangelogEntry> remoteChangelog = []; |
||||||
|
List<ChangelogEntry> get mergedChangelogs { |
||||||
|
final logs = remoteChangelog.toList(); |
||||||
|
final versions = logs.map((log) => log.version).toSet(); |
||||||
|
for (final log in localChangelog) { |
||||||
|
if (!versions.contains(log.version)) { |
||||||
|
logs.add(log); |
||||||
|
versions.add(log.version); |
||||||
|
} |
||||||
|
} |
||||||
|
logs.sort((l1, l2) => l2.version.compareTo(l1.version)); |
||||||
|
return logs; |
||||||
|
} |
||||||
|
|
||||||
|
PackageInfo? packageInfo; |
||||||
|
|
||||||
|
@override |
||||||
|
void didChangeDependencies() { |
||||||
|
PackageInfo.fromPlatform().then((value) => setState(() { |
||||||
|
packageInfo = value; |
||||||
|
})); |
||||||
|
|
||||||
|
DefaultAssetBundle.of(context).loadString('CHANGELOG.txt').then((value) { |
||||||
|
setState(() { |
||||||
|
localChangelog = ChangelogEntry.fromTextFile(value); |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
getRemoteReleases().then((value) => setState(() { |
||||||
|
remoteChangelog = value; |
||||||
|
})); |
||||||
|
|
||||||
|
super.didChangeDependencies(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,137 @@ |
|||||||
|
import 'package:flutter/cupertino.dart'; |
||||||
|
import 'package:info_tren/components/cupertino_divider.dart'; |
||||||
|
import 'package:info_tren/pages/about/about_page.dart'; |
||||||
|
import 'package:url_launcher/url_launcher.dart'; |
||||||
|
|
||||||
|
class AboutPageCupertino extends AboutPageShared { |
||||||
|
const AboutPageCupertino({super.key}); |
||||||
|
|
||||||
|
@override |
||||||
|
State<AboutPageShared> createState() => AboutPageStateCupertino(); |
||||||
|
} |
||||||
|
|
||||||
|
class AboutPageStateCupertino extends AboutPageState<AboutPageCupertino> { |
||||||
|
@override |
||||||
|
Widget build(BuildContext context) { |
||||||
|
return CupertinoPageScaffold( |
||||||
|
navigationBar: CupertinoNavigationBar( |
||||||
|
middle: Text(pageTitle), |
||||||
|
), |
||||||
|
child: Builder( |
||||||
|
builder: (context) { |
||||||
|
final topPadding = MediaQuery.of(context).padding.top; |
||||||
|
return SingleChildScrollView( |
||||||
|
child: Column( |
||||||
|
mainAxisSize: MainAxisSize.min, |
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch, |
||||||
|
children: [ |
||||||
|
SizedBox( |
||||||
|
height: topPadding, |
||||||
|
), |
||||||
|
Center( |
||||||
|
child: Text( |
||||||
|
'Info Tren', |
||||||
|
style: CupertinoTheme.of(context).textTheme.navLargeTitleTextStyle, |
||||||
|
), |
||||||
|
), |
||||||
|
if (packageInfo != null) |
||||||
|
Center( |
||||||
|
child: Text( |
||||||
|
packageInfo!.packageName, |
||||||
|
style: const TextStyle( |
||||||
|
inherit: true, |
||||||
|
fontSize: 14, |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
const Padding( |
||||||
|
padding: EdgeInsets.symmetric(vertical: 8.0), |
||||||
|
child: CupertinoDivider(), |
||||||
|
), |
||||||
|
for (final log in mergedChangelogs) ...[ |
||||||
|
Padding( |
||||||
|
padding: const EdgeInsets.fromLTRB(8, 8, 8, 0), |
||||||
|
child: Row( |
||||||
|
crossAxisAlignment: CrossAxisAlignment.center, |
||||||
|
children: [ |
||||||
|
Expanded( |
||||||
|
child: Text( |
||||||
|
log.version.toString(), |
||||||
|
style: const TextStyle( |
||||||
|
inherit: true, |
||||||
|
fontSize: 24, |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
if (localChangelog.isNotEmpty && log.version == localChangelog.first.version) |
||||||
|
Container( |
||||||
|
decoration: BoxDecoration( |
||||||
|
border: Border.all( |
||||||
|
color: CupertinoTheme.of(context).textTheme.textStyle.color ?? CupertinoColors.inactiveGray, |
||||||
|
width: 1, |
||||||
|
), |
||||||
|
borderRadius: BorderRadius.circular(20), |
||||||
|
), |
||||||
|
child: Padding( |
||||||
|
padding: const EdgeInsets.all(4), |
||||||
|
child: Text( |
||||||
|
currentVersionText, |
||||||
|
style: const TextStyle( |
||||||
|
inherit: true, |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
if (remoteChangelog.isNotEmpty && log.version == remoteChangelog.first.version && (localChangelog.isEmpty || localChangelog.first.version != log.version)) |
||||||
|
Container( |
||||||
|
decoration: BoxDecoration( |
||||||
|
border: Border.all( |
||||||
|
color: CupertinoColors.activeGreen, |
||||||
|
width: 1, |
||||||
|
), |
||||||
|
borderRadius: BorderRadius.circular(20), |
||||||
|
), |
||||||
|
child: Padding( |
||||||
|
padding: const EdgeInsets.all(4), |
||||||
|
child: Text( |
||||||
|
latestVersionText, |
||||||
|
style: const TextStyle( |
||||||
|
inherit: true, |
||||||
|
color: CupertinoColors.activeGreen, |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
if (AboutPageState.download == 'apk' && log.apkLink != null) |
||||||
|
CupertinoButton( |
||||||
|
padding: const EdgeInsets.all(4), |
||||||
|
minSize: 0, |
||||||
|
onPressed: () { |
||||||
|
launchUrl( |
||||||
|
log.apkLink!, |
||||||
|
mode: LaunchMode.externalApplication, |
||||||
|
); |
||||||
|
}, |
||||||
|
child: const Icon(CupertinoIcons.arrow_down_circle), |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
), |
||||||
|
Padding( |
||||||
|
padding: const EdgeInsets.all(8.0), |
||||||
|
child: RichText( |
||||||
|
text: TextSpan( |
||||||
|
text: log.description, |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
const CupertinoDivider(), |
||||||
|
], |
||||||
|
], |
||||||
|
), |
||||||
|
); |
||||||
|
} |
||||||
|
), |
||||||
|
); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,198 @@ |
|||||||
|
import 'package:fluent_ui/fluent_ui.dart'; |
||||||
|
import 'package:flutter/services.dart'; |
||||||
|
import 'package:info_tren/pages/about/about_page.dart'; |
||||||
|
import 'package:url_launcher/url_launcher.dart'; |
||||||
|
|
||||||
|
class AboutPageFluent extends AboutPageShared { |
||||||
|
const AboutPageFluent({super.key}); |
||||||
|
|
||||||
|
@override |
||||||
|
State<AboutPageShared> createState() => AboutPageStateFluent(); |
||||||
|
} |
||||||
|
|
||||||
|
class AboutPageStateFluent extends AboutPageState<AboutPageFluent> { |
||||||
|
@override |
||||||
|
Widget build(BuildContext context) { |
||||||
|
return NavigationView( |
||||||
|
appBar: NavigationAppBar( |
||||||
|
title: Text(pageTitle), |
||||||
|
), |
||||||
|
content: SingleChildScrollView( |
||||||
|
child: Column( |
||||||
|
mainAxisSize: MainAxisSize.min, |
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch, |
||||||
|
children: [ |
||||||
|
Center( |
||||||
|
child: Text( |
||||||
|
'Info Tren', |
||||||
|
style: FluentTheme.of(context).typography.display, |
||||||
|
), |
||||||
|
), |
||||||
|
if (packageInfo != null) |
||||||
|
Center( |
||||||
|
child: Text( |
||||||
|
packageInfo!.packageName, |
||||||
|
style: FluentTheme.of(context).typography.caption, |
||||||
|
), |
||||||
|
), |
||||||
|
// ListTile( |
||||||
|
// title: Text(versionTitleText), |
||||||
|
// subtitle: localChangelog.isEmpty ? null : Text(localChangelog.first.title), |
||||||
|
// ), |
||||||
|
const Divider(), |
||||||
|
for (final log in mergedChangelogs) ...[ |
||||||
|
Padding( |
||||||
|
padding: const EdgeInsets.fromLTRB(8, 8, 8, 0), |
||||||
|
child: Row( |
||||||
|
crossAxisAlignment: CrossAxisAlignment.center, |
||||||
|
children: [ |
||||||
|
Expanded( |
||||||
|
child: Text( |
||||||
|
log.version.toString(), |
||||||
|
style: FluentTheme.of(context).typography.title, |
||||||
|
), |
||||||
|
), |
||||||
|
if (localChangelog.isNotEmpty && log.version == localChangelog.first.version) |
||||||
|
Container( |
||||||
|
decoration: BoxDecoration( |
||||||
|
border: Border.all( |
||||||
|
color: FluentTheme.of(context).inactiveColor, |
||||||
|
width: 1, |
||||||
|
), |
||||||
|
borderRadius: BorderRadius.circular(20), |
||||||
|
), |
||||||
|
child: Padding( |
||||||
|
padding: const EdgeInsets.all(4), |
||||||
|
child: Text( |
||||||
|
currentVersionText, |
||||||
|
style: const TextStyle( |
||||||
|
inherit: true, |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
if (remoteChangelog.isNotEmpty && log.version == remoteChangelog.first.version && (localChangelog.isEmpty || localChangelog.first.version != log.version)) |
||||||
|
Container( |
||||||
|
decoration: BoxDecoration( |
||||||
|
border: Border.all( |
||||||
|
color: Colors.green, |
||||||
|
width: 1, |
||||||
|
), |
||||||
|
borderRadius: BorderRadius.circular(20), |
||||||
|
), |
||||||
|
child: Padding( |
||||||
|
padding: const EdgeInsets.all(4), |
||||||
|
child: Text( |
||||||
|
latestVersionText, |
||||||
|
style: TextStyle( |
||||||
|
inherit: true, |
||||||
|
color: Colors.green, |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
if (AboutPageState.download == 'apk' && log.apkLink != null) |
||||||
|
GestureDetector( |
||||||
|
onSecondaryTap: () { |
||||||
|
Clipboard.setData(ClipboardData(text: log.apkLink!.toString())); |
||||||
|
// ScaffoldMessenger.of(context).showSnackBar(const SnackBar( |
||||||
|
// content: Text('Link copied to clipboard'), |
||||||
|
// )); |
||||||
|
}, |
||||||
|
onLongPress: () { |
||||||
|
Clipboard.setData(ClipboardData(text: log.apkLink!.toString())); |
||||||
|
// ScaffoldMessenger.of(context).showSnackBar(const SnackBar( |
||||||
|
// content: Text('Link copied to clipboard'), |
||||||
|
// )); |
||||||
|
}, |
||||||
|
onTap: () { |
||||||
|
launchUrl( |
||||||
|
log.apkLink!, |
||||||
|
mode: LaunchMode.externalApplication, |
||||||
|
); |
||||||
|
}, |
||||||
|
behavior: HitTestBehavior.translucent, |
||||||
|
child: const Tooltip( |
||||||
|
message: 'Download APK', |
||||||
|
child: Padding( |
||||||
|
padding: EdgeInsets.all(4), |
||||||
|
child: Icon(FluentIcons.download), |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
if (AboutPageState.download == 'linux' && log.linuxLink != null) |
||||||
|
GestureDetector( |
||||||
|
onSecondaryTap: () { |
||||||
|
Clipboard.setData(ClipboardData(text: log.linuxLink!.toString())); |
||||||
|
// ScaffoldMessenger.of(context).showSnackBar(const SnackBar( |
||||||
|
// content: Text('Link copied to clipboard'), |
||||||
|
// )); |
||||||
|
}, |
||||||
|
onLongPress: () { |
||||||
|
Clipboard.setData(ClipboardData(text: log.linuxLink!.toString())); |
||||||
|
// ScaffoldMessenger.of(context).showSnackBar(const SnackBar( |
||||||
|
// content: Text('Link copied to clipboard'), |
||||||
|
// )); |
||||||
|
}, |
||||||
|
onTap: () { |
||||||
|
launchUrl( |
||||||
|
log.linuxLink!, |
||||||
|
mode: LaunchMode.externalApplication, |
||||||
|
); |
||||||
|
}, |
||||||
|
behavior: HitTestBehavior.translucent, |
||||||
|
child: const Tooltip( |
||||||
|
message: 'Download Linux ZIP', |
||||||
|
child: Padding( |
||||||
|
padding: EdgeInsets.all(4), |
||||||
|
child: Icon(FluentIcons.download), |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
if (AboutPageState.download == 'windows' && log.windowsLink != null) |
||||||
|
GestureDetector( |
||||||
|
onSecondaryTap: () { |
||||||
|
Clipboard.setData(ClipboardData(text: log.windowsLink!.toString())); |
||||||
|
// ScaffoldMessenger.of(context).showSnackBar(const SnackBar( |
||||||
|
// content: Text('Link copied to clipboard'), |
||||||
|
// )); |
||||||
|
}, |
||||||
|
onLongPress: () { |
||||||
|
Clipboard.setData(ClipboardData(text: log.windowsLink!.toString())); |
||||||
|
// ScaffoldMessenger.of(context).showSnackBar(const SnackBar( |
||||||
|
// content: Text('Link copied to clipboard'), |
||||||
|
// )); |
||||||
|
}, |
||||||
|
onTap: () { |
||||||
|
launchUrl( |
||||||
|
log.windowsLink!, |
||||||
|
mode: LaunchMode.externalApplication, |
||||||
|
); |
||||||
|
}, |
||||||
|
behavior: HitTestBehavior.translucent, |
||||||
|
child: const Tooltip( |
||||||
|
message: 'Download Windows App ZIP', |
||||||
|
child: Padding( |
||||||
|
padding: EdgeInsets.all(4), |
||||||
|
child: Icon(FluentIcons.download), |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
), |
||||||
|
Padding( |
||||||
|
padding: const EdgeInsets.all(8.0), |
||||||
|
child: RichText( |
||||||
|
text: TextSpan( |
||||||
|
text: log.description, |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
], |
||||||
|
], |
||||||
|
), |
||||||
|
), |
||||||
|
); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,199 @@ |
|||||||
|
import 'package:flutter/material.dart'; |
||||||
|
import 'package:flutter/services.dart'; |
||||||
|
import 'package:info_tren/pages/about/about_page.dart'; |
||||||
|
import 'package:url_launcher/url_launcher.dart'; |
||||||
|
|
||||||
|
class AboutPageMaterial extends AboutPageShared { |
||||||
|
const AboutPageMaterial({super.key}); |
||||||
|
|
||||||
|
@override |
||||||
|
State<AboutPageShared> createState() => AboutPageStateMaterial(); |
||||||
|
} |
||||||
|
|
||||||
|
class AboutPageStateMaterial extends AboutPageState<AboutPageMaterial> { |
||||||
|
@override |
||||||
|
Widget build(BuildContext context) { |
||||||
|
return Scaffold( |
||||||
|
appBar: AppBar( |
||||||
|
title: Text(pageTitle), |
||||||
|
centerTitle: true, |
||||||
|
), |
||||||
|
body: SingleChildScrollView( |
||||||
|
child: Column( |
||||||
|
mainAxisSize: MainAxisSize.min, |
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch, |
||||||
|
children: [ |
||||||
|
Center( |
||||||
|
child: Text( |
||||||
|
'Info Tren', |
||||||
|
style: Theme.of(context).textTheme.displayMedium, |
||||||
|
), |
||||||
|
), |
||||||
|
if (packageInfo != null) |
||||||
|
Center( |
||||||
|
child: Text( |
||||||
|
packageInfo!.packageName, |
||||||
|
style: Theme.of(context).textTheme.bodySmall, |
||||||
|
), |
||||||
|
), |
||||||
|
// ListTile( |
||||||
|
// title: Text(versionTitleText), |
||||||
|
// subtitle: localChangelog.isEmpty ? null : Text(localChangelog.first.title), |
||||||
|
// ), |
||||||
|
const Divider(), |
||||||
|
for (final log in mergedChangelogs) ...[ |
||||||
|
Padding( |
||||||
|
padding: const EdgeInsets.fromLTRB(8, 8, 8, 0), |
||||||
|
child: Row( |
||||||
|
crossAxisAlignment: CrossAxisAlignment.center, |
||||||
|
children: [ |
||||||
|
Expanded( |
||||||
|
child: Text( |
||||||
|
log.version.toString(), |
||||||
|
style: Theme.of(context).textTheme.headlineMedium, |
||||||
|
), |
||||||
|
), |
||||||
|
if (localChangelog.isNotEmpty && log.version == localChangelog.first.version) |
||||||
|
Container( |
||||||
|
decoration: BoxDecoration( |
||||||
|
border: Border.all( |
||||||
|
color: Theme.of(context).colorScheme.onBackground, |
||||||
|
width: 1, |
||||||
|
), |
||||||
|
borderRadius: BorderRadius.circular(20), |
||||||
|
), |
||||||
|
child: Padding( |
||||||
|
padding: const EdgeInsets.all(4), |
||||||
|
child: Text( |
||||||
|
currentVersionText, |
||||||
|
style: const TextStyle( |
||||||
|
inherit: true, |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
if (remoteChangelog.isNotEmpty && log.version == remoteChangelog.first.version && (localChangelog.isEmpty || localChangelog.first.version != log.version)) |
||||||
|
Container( |
||||||
|
decoration: BoxDecoration( |
||||||
|
border: Border.all( |
||||||
|
color: Colors.green, |
||||||
|
width: 1, |
||||||
|
), |
||||||
|
borderRadius: BorderRadius.circular(20), |
||||||
|
), |
||||||
|
child: Padding( |
||||||
|
padding: const EdgeInsets.all(4), |
||||||
|
child: Text( |
||||||
|
latestVersionText, |
||||||
|
style: const TextStyle( |
||||||
|
inherit: true, |
||||||
|
color: Colors.green, |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
if (AboutPageState.download == 'apk' && log.apkLink != null) |
||||||
|
GestureDetector( |
||||||
|
onSecondaryTap: () { |
||||||
|
Clipboard.setData(ClipboardData(text: log.apkLink!.toString())); |
||||||
|
ScaffoldMessenger.of(context).showSnackBar(const SnackBar( |
||||||
|
content: Text('Link copied to clipboard'), |
||||||
|
)); |
||||||
|
}, |
||||||
|
onLongPress: () { |
||||||
|
Clipboard.setData(ClipboardData(text: log.apkLink!.toString())); |
||||||
|
ScaffoldMessenger.of(context).showSnackBar(const SnackBar( |
||||||
|
content: Text('Link copied to clipboard'), |
||||||
|
)); |
||||||
|
}, |
||||||
|
onTap: () { |
||||||
|
launchUrl( |
||||||
|
log.apkLink!, |
||||||
|
mode: LaunchMode.externalApplication, |
||||||
|
); |
||||||
|
}, |
||||||
|
behavior: HitTestBehavior.translucent, |
||||||
|
child: const Tooltip( |
||||||
|
message: 'Download APK', |
||||||
|
child: Padding( |
||||||
|
padding: EdgeInsets.all(4), |
||||||
|
child: Icon(Icons.download), |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
if (AboutPageState.download == 'linux' && log.linuxLink != null) |
||||||
|
GestureDetector( |
||||||
|
onSecondaryTap: () { |
||||||
|
Clipboard.setData(ClipboardData(text: log.linuxLink!.toString())); |
||||||
|
ScaffoldMessenger.of(context).showSnackBar(const SnackBar( |
||||||
|
content: Text('Link copied to clipboard'), |
||||||
|
)); |
||||||
|
}, |
||||||
|
onLongPress: () { |
||||||
|
Clipboard.setData(ClipboardData(text: log.linuxLink!.toString())); |
||||||
|
ScaffoldMessenger.of(context).showSnackBar(const SnackBar( |
||||||
|
content: Text('Link copied to clipboard'), |
||||||
|
)); |
||||||
|
}, |
||||||
|
onTap: () { |
||||||
|
launchUrl( |
||||||
|
log.linuxLink!, |
||||||
|
mode: LaunchMode.externalApplication, |
||||||
|
); |
||||||
|
}, |
||||||
|
behavior: HitTestBehavior.translucent, |
||||||
|
child: const Tooltip( |
||||||
|
message: 'Download Linux ZIP', |
||||||
|
child: Padding( |
||||||
|
padding: EdgeInsets.all(4), |
||||||
|
child: Icon(Icons.download), |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
if (AboutPageState.download == 'windows' && log.windowsLink != null) |
||||||
|
GestureDetector( |
||||||
|
onSecondaryTap: () { |
||||||
|
Clipboard.setData(ClipboardData(text: log.windowsLink!.toString())); |
||||||
|
ScaffoldMessenger.of(context).showSnackBar(const SnackBar( |
||||||
|
content: Text('Link copied to clipboard'), |
||||||
|
)); |
||||||
|
}, |
||||||
|
onLongPress: () { |
||||||
|
Clipboard.setData(ClipboardData(text: log.windowsLink!.toString())); |
||||||
|
ScaffoldMessenger.of(context).showSnackBar(const SnackBar( |
||||||
|
content: Text('Link copied to clipboard'), |
||||||
|
)); |
||||||
|
}, |
||||||
|
onTap: () { |
||||||
|
launchUrl( |
||||||
|
log.windowsLink!, |
||||||
|
mode: LaunchMode.externalApplication, |
||||||
|
); |
||||||
|
}, |
||||||
|
behavior: HitTestBehavior.translucent, |
||||||
|
child: const Tooltip( |
||||||
|
message: 'Download Windows App ZIP', |
||||||
|
child: Padding( |
||||||
|
padding: EdgeInsets.all(4), |
||||||
|
child: Icon(Icons.download), |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
), |
||||||
|
Padding( |
||||||
|
padding: const EdgeInsets.all(8.0), |
||||||
|
child: RichText( |
||||||
|
text: TextSpan( |
||||||
|
text: log.description, |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
], |
||||||
|
], |
||||||
|
), |
||||||
|
), |
||||||
|
); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,89 @@ |
|||||||
|
import 'package:fluent_ui/fluent_ui.dart'; |
||||||
|
import 'package:info_tren/pages/main/main_page.dart'; |
||||||
|
|
||||||
|
class MainPageFluent extends MainPageShared { |
||||||
|
const MainPageFluent({super.key}); |
||||||
|
|
||||||
|
@override |
||||||
|
Widget build(BuildContext context) { |
||||||
|
return NavigationView( |
||||||
|
appBar: NavigationAppBar( |
||||||
|
automaticallyImplyLeading: false, |
||||||
|
title: Text(pageTitle), |
||||||
|
actions: Row( |
||||||
|
mainAxisSize: MainAxisSize.min, |
||||||
|
children: popupMenu.map((i) => Center( |
||||||
|
child: SizedBox( |
||||||
|
width: 32, |
||||||
|
height: 32, |
||||||
|
child: IconButton( |
||||||
|
icon: Icon({ |
||||||
|
'Setări': FluentIcons.settings, |
||||||
|
'Despre aplicație': FluentIcons.info, |
||||||
|
}[i.name]), |
||||||
|
onPressed: i.action != null ? () => i.action!(context) : null, |
||||||
|
), |
||||||
|
), |
||||||
|
)).toList(), |
||||||
|
), |
||||||
|
// centerTitle: true, |
||||||
|
// actions: [ |
||||||
|
// PopupMenuButton<int>( |
||||||
|
// icon: const Icon(Icons.more_vert), |
||||||
|
// tooltip: moreOptionsText, |
||||||
|
// itemBuilder: (_) => popupMenu.asMap().entries.map((e) => PopupMenuItem( |
||||||
|
// value: e.key, |
||||||
|
// child: Text(e.value.name), |
||||||
|
// )).toList(), |
||||||
|
// onSelected: (index) { |
||||||
|
// popupMenu[index].action?.call(context); |
||||||
|
// }, |
||||||
|
// ), |
||||||
|
// ], |
||||||
|
), |
||||||
|
content: SafeArea( |
||||||
|
child: Center( |
||||||
|
child: Column( |
||||||
|
mainAxisSize: MainAxisSize.min, |
||||||
|
children: options.map((option) => HoverButton( |
||||||
|
onPressed: option.action != null ? () => option.action!(context) : null, |
||||||
|
builder: (context, states) { |
||||||
|
return Card( |
||||||
|
backgroundColor: option.action != null ? (states.isHovering ? FluentTheme.of(context).accentColor.dark : FluentTheme.of(context).accentColor) : null, |
||||||
|
child: Column( |
||||||
|
children: [ |
||||||
|
Padding( |
||||||
|
padding: const EdgeInsets.all(8.0), |
||||||
|
child: Text( |
||||||
|
option.name, |
||||||
|
style: FluentTheme.of(context) |
||||||
|
.typography |
||||||
|
.bodyLarge |
||||||
|
?.copyWith( |
||||||
|
color: |
||||||
|
FluentTheme.of(context).activeColor, |
||||||
|
), |
||||||
|
textAlign: TextAlign.center, |
||||||
|
), |
||||||
|
), |
||||||
|
Padding( |
||||||
|
padding: const EdgeInsets.all(8.0), |
||||||
|
child: Text(option.description!), |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
); |
||||||
|
}, |
||||||
|
)).map((w) => Padding( |
||||||
|
padding: const EdgeInsets.fromLTRB(4, 2, 4, 2), |
||||||
|
child: SizedBox( |
||||||
|
width: double.infinity, |
||||||
|
child: w, |
||||||
|
), |
||||||
|
)).toList(), |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,38 @@ |
|||||||
|
import 'package:flutter/widgets.dart'; |
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart'; |
||||||
|
import 'package:info_tren/models.dart'; |
||||||
|
import 'package:info_tren/pages/settings/settings_page_cupertino.dart'; |
||||||
|
import 'package:info_tren/pages/settings/settings_page_fluent.dart'; |
||||||
|
import 'package:info_tren/pages/settings/settings_page_material.dart'; |
||||||
|
import 'package:info_tren/providers.dart'; |
||||||
|
|
||||||
|
class SettingsPage extends ConsumerWidget { |
||||||
|
const SettingsPage({super.key,}); |
||||||
|
|
||||||
|
static const String routeName = '/settings'; |
||||||
|
|
||||||
|
@override |
||||||
|
Widget build(BuildContext context, WidgetRef ref) { |
||||||
|
final uiDesign = ref.watch(uiDesignProvider); |
||||||
|
|
||||||
|
switch (uiDesign) { |
||||||
|
case UiDesign.MATERIAL: |
||||||
|
return const SettingsPageMaterial(); |
||||||
|
case UiDesign.CUPERTINO: |
||||||
|
return const SettingsPageCupertino(); |
||||||
|
case UiDesign.FLUENT: |
||||||
|
return const SettingsPageFluent(); |
||||||
|
default: |
||||||
|
throw UnmatchedUiDesignException(uiDesign); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
abstract class SettingsPageShared extends StatelessWidget { |
||||||
|
final String pageTitle = 'Setări'; |
||||||
|
final String appearanceTitle = 'Aspect'; |
||||||
|
final String timeZoneTitle = 'Fus orar'; |
||||||
|
|
||||||
|
const SettingsPageShared({super.key}); |
||||||
|
|
||||||
|
} |
@ -0,0 +1,96 @@ |
|||||||
|
import 'package:flutter/cupertino.dart'; |
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart'; |
||||||
|
import 'package:info_tren/models.dart'; |
||||||
|
import 'package:info_tren/pages/settings/setings_page.dart'; |
||||||
|
import 'package:info_tren/providers.dart'; |
||||||
|
|
||||||
|
class SettingsPageCupertino extends SettingsPageShared { |
||||||
|
const SettingsPageCupertino({super.key,}); |
||||||
|
|
||||||
|
Future<T?> singleChoice<T>({required BuildContext context, required List<T> choices, required String Function(T) labelBuilder, String? title}) async { |
||||||
|
return await showCupertinoModalPopup<T>( |
||||||
|
context: context, |
||||||
|
builder: (context) { |
||||||
|
return CupertinoActionSheet( |
||||||
|
title: title != null ? Text(title) : null, |
||||||
|
actions: choices.map((c) => CupertinoActionSheetAction( |
||||||
|
onPressed: () { |
||||||
|
Navigator.of(context).pop(c); |
||||||
|
}, |
||||||
|
child: Text(labelBuilder(c)), |
||||||
|
)).toList(), |
||||||
|
cancelButton: CupertinoActionSheetAction( |
||||||
|
child: const Text('Anulare'), |
||||||
|
onPressed: () { |
||||||
|
Navigator.of(context).pop(); |
||||||
|
}, |
||||||
|
), |
||||||
|
); |
||||||
|
}, |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
Widget build(BuildContext context) { |
||||||
|
return CupertinoPageScaffold( |
||||||
|
navigationBar: CupertinoNavigationBar( |
||||||
|
previousPageTitle: 'Info Tren', |
||||||
|
middle: Text(pageTitle), |
||||||
|
), |
||||||
|
child: Builder( |
||||||
|
builder: (context) { |
||||||
|
final mq = MediaQuery.of(context); |
||||||
|
return SingleChildScrollView( |
||||||
|
child: Column( |
||||||
|
children: [ |
||||||
|
SizedBox( |
||||||
|
height: mq.padding.top, |
||||||
|
), |
||||||
|
Consumer( |
||||||
|
builder: (context, ref, _) { |
||||||
|
final currentUiDesign = ref.watch(uiDesignProvider); |
||||||
|
return CupertinoListTile( |
||||||
|
title: Text(appearanceTitle), |
||||||
|
trailing: Text(currentUiDesign.userInterfaceName), |
||||||
|
onTap: () async { |
||||||
|
final choice = await singleChoice( |
||||||
|
context: context, |
||||||
|
choices: UiDesign.values, |
||||||
|
labelBuilder: (UiDesign ud) => ud.userInterfaceName, |
||||||
|
title: appearanceTitle, |
||||||
|
); |
||||||
|
if (choice != null) { |
||||||
|
ref.read(uiDesignProvider.notifier).set(choice); |
||||||
|
} |
||||||
|
}, |
||||||
|
); |
||||||
|
}, |
||||||
|
), |
||||||
|
Consumer( |
||||||
|
builder: (context, ref, _) { |
||||||
|
final currentTZ = ref.watch(uiTimeZoneProvider); |
||||||
|
return CupertinoListTile( |
||||||
|
title: Text(timeZoneTitle), |
||||||
|
trailing: Text(currentTZ.type.userInterfaceName), |
||||||
|
onTap: () async { |
||||||
|
final choice = await singleChoice( |
||||||
|
context: context, |
||||||
|
choices: UiTimeZoneType.values.where((tz) => tz != UiTimeZoneType.iana).toList(), |
||||||
|
labelBuilder: (UiTimeZoneType utzt) => utzt.userInterfaceName, |
||||||
|
title: timeZoneTitle, |
||||||
|
); |
||||||
|
if (choice != null) { |
||||||
|
ref.read(uiTimeZoneProvider.notifier).set(UiTimeZone.fromSerString('${choice.name}\n')); |
||||||
|
} |
||||||
|
}, |
||||||
|
); |
||||||
|
}, |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
); |
||||||
|
}, |
||||||
|
), |
||||||
|
); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,65 @@ |
|||||||
|
import 'package:fluent_ui/fluent_ui.dart'; |
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart'; |
||||||
|
import 'package:info_tren/models.dart'; |
||||||
|
import 'package:info_tren/pages/settings/setings_page.dart'; |
||||||
|
import 'package:info_tren/providers.dart'; |
||||||
|
|
||||||
|
class SettingsPageFluent extends SettingsPageShared { |
||||||
|
const SettingsPageFluent({super.key,}); |
||||||
|
|
||||||
|
@override |
||||||
|
Widget build(BuildContext context) { |
||||||
|
return NavigationView( |
||||||
|
appBar: NavigationAppBar( |
||||||
|
title: Text(pageTitle), |
||||||
|
), |
||||||
|
content: SingleChildScrollView( |
||||||
|
child: Column( |
||||||
|
children: [ |
||||||
|
Consumer( |
||||||
|
builder: (context, ref, _) { |
||||||
|
final currentUiDesign = ref.watch(uiDesignProvider); |
||||||
|
return ListTile( |
||||||
|
title: Text(appearanceTitle), |
||||||
|
trailing: ComboBox<UiDesign>( |
||||||
|
items: UiDesign.values.map((d) => ComboBoxItem( |
||||||
|
value: d, |
||||||
|
child: Text(d.userInterfaceName), |
||||||
|
)).toList(), |
||||||
|
value: currentUiDesign, |
||||||
|
onChanged: (newUiDesign) { |
||||||
|
ref.read(uiDesignProvider.notifier).set(newUiDesign); |
||||||
|
}, |
||||||
|
), |
||||||
|
); |
||||||
|
}, |
||||||
|
), |
||||||
|
Consumer( |
||||||
|
builder: (context, ref, _) { |
||||||
|
final currentTZ = ref.watch(uiTimeZoneProvider); |
||||||
|
return ListTile( |
||||||
|
title: Text(timeZoneTitle), |
||||||
|
trailing: ComboBox<UiTimeZoneType>( |
||||||
|
items: UiTimeZoneType.values.where((tz) => tz != UiTimeZoneType.iana).map((tzt) => ComboBoxItem( |
||||||
|
value: tzt, |
||||||
|
child: Text(tzt.userInterfaceName), |
||||||
|
)).toList(), |
||||||
|
value: currentTZ.type, |
||||||
|
onChanged: (newTZ) { |
||||||
|
if (newTZ != null) { |
||||||
|
ref.read(uiTimeZoneProvider.notifier).set(UiTimeZone.fromSerString('${newTZ.name}\n')); |
||||||
|
} |
||||||
|
else { |
||||||
|
ref.read(uiTimeZoneProvider.notifier).set(null); |
||||||
|
} |
||||||
|
}, |
||||||
|
), |
||||||
|
); |
||||||
|
}, |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
), |
||||||
|
); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,66 @@ |
|||||||
|
import 'package:flutter/material.dart'; |
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart'; |
||||||
|
import 'package:info_tren/models.dart'; |
||||||
|
import 'package:info_tren/pages/settings/setings_page.dart'; |
||||||
|
import 'package:info_tren/providers.dart'; |
||||||
|
|
||||||
|
class SettingsPageMaterial extends SettingsPageShared { |
||||||
|
const SettingsPageMaterial({super.key,}); |
||||||
|
|
||||||
|
@override |
||||||
|
Widget build(BuildContext context) { |
||||||
|
return Scaffold( |
||||||
|
appBar: AppBar( |
||||||
|
title: Text(pageTitle), |
||||||
|
centerTitle: true, |
||||||
|
), |
||||||
|
body: SingleChildScrollView( |
||||||
|
child: Column( |
||||||
|
children: [ |
||||||
|
Consumer( |
||||||
|
builder: (context, ref, _) { |
||||||
|
final currentUiDesign = ref.watch(uiDesignProvider); |
||||||
|
return ListTile( |
||||||
|
title: Text(appearanceTitle), |
||||||
|
trailing: DropdownButton<UiDesign>( |
||||||
|
items: UiDesign.values.map((d) => DropdownMenuItem( |
||||||
|
value: d, |
||||||
|
child: Text(d.userInterfaceName), |
||||||
|
)).toList(), |
||||||
|
value: currentUiDesign, |
||||||
|
onChanged: (newUiDesign) { |
||||||
|
ref.read(uiDesignProvider.notifier).set(newUiDesign); |
||||||
|
}, |
||||||
|
), |
||||||
|
); |
||||||
|
}, |
||||||
|
), |
||||||
|
Consumer( |
||||||
|
builder: (context, ref, _) { |
||||||
|
final currentTZ = ref.watch(uiTimeZoneProvider); |
||||||
|
return ListTile( |
||||||
|
title: Text(timeZoneTitle), |
||||||
|
trailing: DropdownButton<UiTimeZoneType>( |
||||||
|
items: UiTimeZoneType.values.where((tz) => tz != UiTimeZoneType.iana).map((tzt) => DropdownMenuItem( |
||||||
|
value: tzt, |
||||||
|
child: Text(tzt.userInterfaceName), |
||||||
|
)).toList(), |
||||||
|
value: currentTZ.type, |
||||||
|
onChanged: (newTZ) { |
||||||
|
if (newTZ != null) { |
||||||
|
ref.read(uiTimeZoneProvider.notifier).set(UiTimeZone.fromSerString('${newTZ.name}\n')); |
||||||
|
} |
||||||
|
else { |
||||||
|
ref.read(uiTimeZoneProvider.notifier).set(null); |
||||||
|
} |
||||||
|
}, |
||||||
|
), |
||||||
|
); |
||||||
|
}, |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
), |
||||||
|
); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,59 @@ |
|||||||
|
import 'package:fluent_ui/fluent_ui.dart'; |
||||||
|
import 'package:info_tren/pages/station_arrdep_page/select_station/select_station.dart'; |
||||||
|
|
||||||
|
class SelectStationPageFluent extends SelectStationPageShared { |
||||||
|
const SelectStationPageFluent({super.key}); |
||||||
|
|
||||||
|
@override |
||||||
|
State<StatefulWidget> createState() => SelectStationPageStateFluent(); |
||||||
|
} |
||||||
|
|
||||||
|
class SelectStationPageStateFluent extends SelectStationPageState { |
||||||
|
@override |
||||||
|
Widget build(BuildContext context) { |
||||||
|
return NavigationView( |
||||||
|
appBar: const NavigationAppBar( |
||||||
|
title: Text(SelectStationPageState.pageTitle), |
||||||
|
// centerTitle: true, |
||||||
|
), |
||||||
|
content: SafeArea( |
||||||
|
bottom: false, |
||||||
|
child: Column( |
||||||
|
mainAxisSize: MainAxisSize.max, |
||||||
|
children: [ |
||||||
|
Padding( |
||||||
|
padding: const EdgeInsets.all(4), |
||||||
|
child: TextBox( |
||||||
|
controller: textEditingController, |
||||||
|
autofocus: true, |
||||||
|
placeholder: SelectStationPageState.textFieldLabel, |
||||||
|
textInputAction: TextInputAction.search, |
||||||
|
onChanged: onTextChanged, |
||||||
|
), |
||||||
|
), |
||||||
|
Expanded( |
||||||
|
child: ListView.builder( |
||||||
|
itemBuilder: (context, index) { |
||||||
|
return Column( |
||||||
|
mainAxisSize: MainAxisSize.min, |
||||||
|
children: [ |
||||||
|
ListTile( |
||||||
|
// dense: true, |
||||||
|
title: Text(filteredStations[index]), |
||||||
|
onPressed: () => onSuggestionSelected(filteredStations[index]), |
||||||
|
), |
||||||
|
const Divider( |
||||||
|
size: 1, |
||||||
|
), |
||||||
|
], |
||||||
|
); |
||||||
|
}, |
||||||
|
itemCount: filteredStations.length, |
||||||
|
), |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
), |
||||||
|
); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,264 @@ |
|||||||
|
import 'dart:math'; |
||||||
|
import 'dart:ui'; |
||||||
|
|
||||||
|
import 'package:fluent_ui/fluent_ui.dart'; |
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart'; |
||||||
|
import 'package:info_tren/components/badge/badge.dart'; |
||||||
|
import 'package:info_tren/components/loading/loading.dart'; |
||||||
|
import 'package:info_tren/components/refresh_future_builder.dart'; |
||||||
|
import 'package:info_tren/components/train_id_text_span.dart'; |
||||||
|
import 'package:info_tren/models.dart'; |
||||||
|
import 'package:info_tren/pages/station_arrdep_page/view_station/view_station.dart'; |
||||||
|
import 'package:info_tren/providers.dart'; |
||||||
|
|
||||||
|
class ViewStationPageFluent extends ViewStationPageShared { |
||||||
|
const ViewStationPageFluent({super.key, required super.tab, required super.setTab}); |
||||||
|
|
||||||
|
@override |
||||||
|
Widget buildContent(BuildContext context, Future Function() refresh, Future Function(Future<StationData> Function()) _, RefreshFutureBuilderSnapshot<StationData> snapshot) { |
||||||
|
return NavigationView( |
||||||
|
appBar: NavigationAppBar( |
||||||
|
title: Consumer( |
||||||
|
builder: (context, ref, _) { |
||||||
|
final stationName = ref.watch(viewStationArgumentsProvider.select((value) => value.stationName)); |
||||||
|
return Text(snapshot.hasData ? snapshot.data!.stationName : stationName); |
||||||
|
} |
||||||
|
), |
||||||
|
), |
||||||
|
content: snapshot.state == RefreshFutureBuilderState.waiting || snapshot.state == RefreshFutureBuilderState.refreshError |
||||||
|
? const Loading(text: ViewStationPageShared.loadingText,) |
||||||
|
: snapshot.state == RefreshFutureBuilderState.error |
||||||
|
? Padding( |
||||||
|
padding: const EdgeInsets.all(8.0), |
||||||
|
child: Center( |
||||||
|
child: Column( |
||||||
|
mainAxisSize: MainAxisSize.min, |
||||||
|
children: [ |
||||||
|
Icon( |
||||||
|
FluentIcons.error, |
||||||
|
size: 32, |
||||||
|
color: Colors.red.normal, |
||||||
|
), |
||||||
|
const Text( |
||||||
|
ViewStationPageShared.errorText, |
||||||
|
style: TextStyle( |
||||||
|
inherit: true, |
||||||
|
fontSize: 32, |
||||||
|
), |
||||||
|
), |
||||||
|
Text( |
||||||
|
snapshot.error.toString(), |
||||||
|
style: FluentTheme.of(context).typography.subtitle, |
||||||
|
), |
||||||
|
Padding( |
||||||
|
padding: const EdgeInsets.all(8.0), |
||||||
|
child: Button( |
||||||
|
onPressed: () { |
||||||
|
refresh(); |
||||||
|
}, |
||||||
|
child: const Text(ViewStationPageShared.retryText), |
||||||
|
), |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
), |
||||||
|
) |
||||||
|
: null, |
||||||
|
pane: snapshot.hasData ? NavigationPane( |
||||||
|
onChanged: onTabChange, |
||||||
|
selected: tab.index, |
||||||
|
items: [ |
||||||
|
PaneItem( |
||||||
|
body: CustomScrollView( |
||||||
|
slivers: [ |
||||||
|
SliverToBoxAdapter(child: SafeArea(left: false, bottom: false, right: false,child: Container(),),), |
||||||
|
SliverList( |
||||||
|
delegate: SliverChildBuilderDelegate( |
||||||
|
(context, index) { |
||||||
|
return tab == ViewStationPageTab.arrivals ? buildStationArrivalItem(context, snapshot.data!.arrivals![index]) : buildStationDepartureItem(context, snapshot.data!.departures![index]); |
||||||
|
}, |
||||||
|
childCount: tab == ViewStationPageTab.arrivals ? snapshot.data!.arrivals?.length ?? 0 : snapshot.data!.departures?.length ?? 0, |
||||||
|
), |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
title: const Text(ViewStationPageShared.arrivals), |
||||||
|
icon: const Icon(FluentIcons.arrow_down_right8), |
||||||
|
), |
||||||
|
PaneItem( |
||||||
|
body: CustomScrollView( |
||||||
|
slivers: [ |
||||||
|
SliverToBoxAdapter(child: SafeArea(left: false, bottom: false, right: false,child: Container(),),), |
||||||
|
SliverList( |
||||||
|
delegate: SliverChildBuilderDelegate( |
||||||
|
(context, index) { |
||||||
|
return tab == ViewStationPageTab.arrivals ? buildStationArrivalItem(context, snapshot.data!.arrivals![index]) : buildStationDepartureItem(context, snapshot.data!.departures![index]); |
||||||
|
}, |
||||||
|
childCount: tab == ViewStationPageTab.arrivals ? snapshot.data!.arrivals?.length ?? 0 : snapshot.data!.departures?.length ?? 0, |
||||||
|
), |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
title: const Text(ViewStationPageShared.departures), |
||||||
|
icon: const Icon(FluentIcons.arrow_up_right8), |
||||||
|
), |
||||||
|
], |
||||||
|
) : null, |
||||||
|
// bottomNavigationBar: snapshot.hasData ? BottomNavigationBar( |
||||||
|
// items: const [ |
||||||
|
// BottomNavigationBarItem( |
||||||
|
// icon: Icon(Icons.arrow_downward), |
||||||
|
// label: ViewStationPageShared.arrivals, |
||||||
|
// ), |
||||||
|
// BottomNavigationBarItem( |
||||||
|
// icon: Icon(Icons.arrow_upward), |
||||||
|
// label: ViewStationPageShared.departures, |
||||||
|
// ), |
||||||
|
// ], |
||||||
|
// currentIndex: tab.index, |
||||||
|
// onTap: onTabChange, |
||||||
|
// ) : null, |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
Widget buildStationItem(BuildContext context, StationArrDep item, {required bool arrival}) { |
||||||
|
return HoverButton( |
||||||
|
onPressed: () => onTrainTapped(context, item.train), |
||||||
|
builder: (context, states) { |
||||||
|
return Container( |
||||||
|
color: item.status.cancelled |
||||||
|
? Colors.red.withAlpha(100) |
||||||
|
: states.isPressing |
||||||
|
? FluentTheme.of(context).scaffoldBackgroundColor |
||||||
|
: states.isHovering |
||||||
|
? FluentTheme.of(context).inactiveBackgroundColor |
||||||
|
: null, |
||||||
|
child: Row( |
||||||
|
crossAxisAlignment: CrossAxisAlignment.center, |
||||||
|
children: [ |
||||||
|
Padding( |
||||||
|
padding: const EdgeInsets.all(8), |
||||||
|
child: Column( |
||||||
|
mainAxisSize: MainAxisSize.min, |
||||||
|
crossAxisAlignment: CrossAxisAlignment.center, |
||||||
|
children: [ |
||||||
|
Consumer( |
||||||
|
builder: (context, ref, _) { |
||||||
|
final tz = ref.watch(uiTimeZoneProvider); |
||||||
|
final time = tz.convertDateTime(item.time); |
||||||
|
return Text( |
||||||
|
'${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}', |
||||||
|
style: TextStyle( |
||||||
|
inherit: true, |
||||||
|
fontFeatures: const [ |
||||||
|
FontFeature.tabularFigures(), |
||||||
|
], |
||||||
|
decoration: item.status.cancelled || item.status.delay != 0 ? TextDecoration.lineThrough : null, |
||||||
|
fontSize: item.status.delay != 0 ? 12 : null, |
||||||
|
), |
||||||
|
); |
||||||
|
}, |
||||||
|
), |
||||||
|
if (item.status.delay != 0) Consumer( |
||||||
|
builder: (context, ref, _) { |
||||||
|
final tz = ref.watch(uiTimeZoneProvider); |
||||||
|
final newTime = tz.convertDateTime(item.time.add(Duration(minutes: item.status.delay))); |
||||||
|
final delay = item.status.delay > 0; |
||||||
|
|
||||||
|
return Text( |
||||||
|
'${newTime.hour.toString().padLeft(2, '0')}:${newTime.minute.toString().padLeft(2, '0')}', |
||||||
|
style: TextStyle( |
||||||
|
inherit: true, |
||||||
|
fontFeatures: const [ |
||||||
|
FontFeature.tabularFigures(), |
||||||
|
], |
||||||
|
color: delay ? Colors.red : Colors.green, |
||||||
|
), |
||||||
|
); |
||||||
|
}, |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
), |
||||||
|
Expanded( |
||||||
|
child: IgnorePointer( |
||||||
|
child: ListTile( |
||||||
|
// isThreeLine: item.status.delay != 0, |
||||||
|
title: Text.rich( |
||||||
|
trainIdSpan(rank: item.train.rank, number: item.train.number), |
||||||
|
), |
||||||
|
subtitle: Text.rich( |
||||||
|
TextSpan( |
||||||
|
children: [ |
||||||
|
TextSpan( |
||||||
|
text: item.status.cancelled |
||||||
|
? (arrival ? ViewStationPageShared.cancelledArrival : ViewStationPageShared.cancelledDeparture) |
||||||
|
: item.time.add(Duration(minutes: max(0, item.status.delay))).compareTo(DateTime.now()) < 0 |
||||||
|
? (arrival ? ViewStationPageShared.arrivedFrom : ViewStationPageShared.departedTo) |
||||||
|
: (arrival ? ViewStationPageShared.arrivesFrom : ViewStationPageShared.departsTo) |
||||||
|
), |
||||||
|
const TextSpan(text: ' '), |
||||||
|
TextSpan(text: item.train.terminus), |
||||||
|
if (item.status.delay != 0) ...[ |
||||||
|
const TextSpan(text: '\n'), |
||||||
|
if (item.status.delay.abs() >= 60) ...[ |
||||||
|
TextSpan(text: (item.status.delay.abs() ~/ 60).toString()), |
||||||
|
TextSpan(text: item.status.delay.abs() >= 120 ? ' ore' : ' oră'), |
||||||
|
if (item.status.delay.abs() % 60 != 0) |
||||||
|
const TextSpan(text: ' și '), |
||||||
|
], |
||||||
|
TextSpan(text: (item.status.delay.abs() % 60).toString()), |
||||||
|
TextSpan(text: item.status.delay.abs() > 1 ? ' minute' : ' minut'), |
||||||
|
const TextSpan(text: ' '), |
||||||
|
if (item.status.delay > 0) |
||||||
|
TextSpan( |
||||||
|
text: 'întârziere', |
||||||
|
style: TextStyle( |
||||||
|
inherit: true, |
||||||
|
color: Colors.red, |
||||||
|
), |
||||||
|
) |
||||||
|
else |
||||||
|
TextSpan( |
||||||
|
text: 'mai devreme', |
||||||
|
style: TextStyle( |
||||||
|
inherit: true, |
||||||
|
color: Colors.green, |
||||||
|
), |
||||||
|
), |
||||||
|
], |
||||||
|
], |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
if (item.status.platform != null) |
||||||
|
IntrinsicHeight( |
||||||
|
child: AspectRatio( |
||||||
|
aspectRatio: 1, |
||||||
|
child: Badge( |
||||||
|
text: item.status.platform!, |
||||||
|
caption: 'Linia', |
||||||
|
isOnTime: item.status.real && item.status.delay <= 0, |
||||||
|
isDelayed: item.status.real && item.status.delay > 0, |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
); |
||||||
|
}, |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
Widget buildStationArrivalItem(BuildContext context, StationArrDep item) { |
||||||
|
return buildStationItem(context, item, arrival: true); |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
Widget buildStationDepartureItem(BuildContext context, StationArrDep item) { |
||||||
|
return buildStationItem(context, item, arrival: false); |
||||||
|
} |
||||||
|
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue