Compare commits
	
		
			No commits in common. "master" and "transition_webview_to_api" have entirely different histories.
		
	
	
		
			master
			...
			transition
		
	
		
					 185 changed files with 2001 additions and 15667 deletions
				
			
		
							
								
								
									
										23
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										23
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -25,15 +25,10 @@
 | 
			
		|||
.dart_tool/
 | 
			
		||||
.flutter-plugins
 | 
			
		||||
.flutter-plugins-dependencies
 | 
			
		||||
**/generated_plugin_registrant.dart
 | 
			
		||||
.packages
 | 
			
		||||
.pub-cache/
 | 
			
		||||
.pub/
 | 
			
		||||
build/
 | 
			
		||||
flutter_*.png
 | 
			
		||||
linked_*.ds
 | 
			
		||||
unlinked.ds
 | 
			
		||||
unlinked_spec.ds
 | 
			
		||||
/build/
 | 
			
		||||
 | 
			
		||||
# Android related
 | 
			
		||||
**/android/**/gradle-wrapper.jar
 | 
			
		||||
| 
						 | 
				
			
			@ -43,8 +38,6 @@ unlinked_spec.ds
 | 
			
		|||
**/android/gradlew.bat
 | 
			
		||||
**/android/local.properties
 | 
			
		||||
**/android/**/GeneratedPluginRegistrant.java
 | 
			
		||||
**/android/key.properties
 | 
			
		||||
*.jks
 | 
			
		||||
 | 
			
		||||
# iOS/XCode related
 | 
			
		||||
**/ios/**/*.mode1v3
 | 
			
		||||
| 
						 | 
				
			
			@ -63,32 +56,18 @@ unlinked_spec.ds
 | 
			
		|||
**/ios/**/profile
 | 
			
		||||
**/ios/**/xcuserdata
 | 
			
		||||
**/ios/.generated/
 | 
			
		||||
**/ios/Flutter/.last_build_id
 | 
			
		||||
**/ios/Flutter/App.framework
 | 
			
		||||
**/ios/Flutter/Flutter.framework
 | 
			
		||||
**/ios/Flutter/Flutter.podspec
 | 
			
		||||
**/ios/Flutter/Generated.xcconfig
 | 
			
		||||
**/ios/Flutter/ephemeral
 | 
			
		||||
**/ios/Flutter/app.flx
 | 
			
		||||
**/ios/Flutter/app.zip
 | 
			
		||||
**/ios/Flutter/flutter_assets/
 | 
			
		||||
**/ios/Flutter/flutter_export_environment.sh
 | 
			
		||||
**/ios/ServiceDefinitions.json
 | 
			
		||||
**/ios/Runner/GeneratedPluginRegistrant.*
 | 
			
		||||
 | 
			
		||||
# macOS
 | 
			
		||||
**/macos/Flutter/GeneratedPluginRegistrant.swift
 | 
			
		||||
 | 
			
		||||
# Coverage
 | 
			
		||||
coverage/
 | 
			
		||||
 | 
			
		||||
# Symbols
 | 
			
		||||
app.*.symbols
 | 
			
		||||
 | 
			
		||||
# Exceptions to above rules.
 | 
			
		||||
!**/ios/**/default.mode1v3
 | 
			
		||||
!**/ios/**/default.mode2v3
 | 
			
		||||
!**/ios/**/default.pbxuser
 | 
			
		||||
!**/ios/**/default.perspectivev3
 | 
			
		||||
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
 | 
			
		||||
!/dev/ci/**/Gemfile.lock
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										24
									
								
								.metadata
									
										
									
									
									
								
							
							
						
						
									
										24
									
								
								.metadata
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,30 +1,10 @@
 | 
			
		|||
# This file tracks properties of this Flutter project.
 | 
			
		||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
 | 
			
		||||
#
 | 
			
		||||
# This file should be version controlled.
 | 
			
		||||
# This file should be version controlled and should not be manually edited.
 | 
			
		||||
 | 
			
		||||
version:
 | 
			
		||||
  revision: 52b3dc25f6471c27b2144594abb11c741cb88f57
 | 
			
		||||
  revision: b712a172f9694745f50505c93340883493b505e5
 | 
			
		||||
  channel: stable
 | 
			
		||||
 | 
			
		||||
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'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										24
									
								
								.vscode/launch.json
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										24
									
								
								.vscode/launch.json
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -7,11 +7,7 @@
 | 
			
		|||
		{
 | 
			
		||||
			"name": "Current Device",
 | 
			
		||||
			"request": "launch",
 | 
			
		||||
			"type": "dart",
 | 
			
		||||
			"args": [
 | 
			
		||||
				"--dart-define",
 | 
			
		||||
				"DOWNLOAD=apk"
 | 
			
		||||
			]
 | 
			
		||||
			"type": "dart"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"name": "info_tren (profile mode)",
 | 
			
		||||
| 
						 | 
				
			
			@ -30,28 +26,12 @@
 | 
			
		|||
			"request": "launch",
 | 
			
		||||
			"type": "dart",
 | 
			
		||||
			"deviceId": "iphone"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"name": "macOS",
 | 
			
		||||
			"request": "launch",
 | 
			
		||||
			"type": "dart",
 | 
			
		||||
			"deviceId": "macOS"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"name": "Samsung",
 | 
			
		||||
			"request": "launch",
 | 
			
		||||
			"type": "dart",
 | 
			
		||||
			"deviceId": "SM"
 | 
			
		||||
		}
 | 
			
		||||
	],
 | 
			
		||||
	"compounds": [
 | 
			
		||||
		{
 | 
			
		||||
			"name": "All Devices",
 | 
			
		||||
			"configurations": ["Android Emulator", "iPhone", "macOS"]
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"name": "Mac + Samsung",
 | 
			
		||||
			"configurations": ["macOS", "Samsung"]
 | 
			
		||||
			"configurations": ["Android Emulator", "iPhone"]
 | 
			
		||||
		}
 | 
			
		||||
	]
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										38
									
								
								CHANGELOG.TXT
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								CHANGELOG.TXT
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,38 @@
 | 
			
		|||
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
 | 
			
		||||
							
								
								
									
										122
									
								
								CHANGELOG.txt
									
										
									
									
									
								
							
							
						
						
									
										122
									
								
								CHANGELOG.txt
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,122 +0,0 @@
 | 
			
		|||
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
 | 
			
		||||
| 
						 | 
				
			
			@ -25,48 +25,32 @@ apply plugin: 'com.android.application'
 | 
			
		|||
apply plugin: 'kotlin-android'
 | 
			
		||||
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
 | 
			
		||||
 | 
			
		||||
def keystoreProperties = new Properties()
 | 
			
		||||
def keystorePropertiesFile = rootProject.file('key.properties')
 | 
			
		||||
if (keystorePropertiesFile.exists()) {
 | 
			
		||||
    keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
android {
 | 
			
		||||
    compileSdkVersion 33
 | 
			
		||||
 | 
			
		||||
    compileOptions {
 | 
			
		||||
        sourceCompatibility JavaVersion.VERSION_1_8
 | 
			
		||||
        targetCompatibility JavaVersion.VERSION_1_8
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    kotlinOptions {
 | 
			
		||||
        jvmTarget = '1.8'
 | 
			
		||||
    }
 | 
			
		||||
    compileSdkVersion 28
 | 
			
		||||
 | 
			
		||||
    sourceSets {
 | 
			
		||||
        main.java.srcDirs += 'src/main/kotlin'
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    defaultConfig {
 | 
			
		||||
        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
 | 
			
		||||
        applicationId "ro.dcdev.infotren"
 | 
			
		||||
        minSdkVersion 16
 | 
			
		||||
        targetSdkVersion 33
 | 
			
		||||
        versionCode flutterVersionCode.toInteger()
 | 
			
		||||
        versionName flutterVersionName
 | 
			
		||||
    lintOptions {
 | 
			
		||||
        disable 'InvalidPackage'
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    signingConfigs {
 | 
			
		||||
        release {
 | 
			
		||||
            keyAlias keystoreProperties['keyAlias']
 | 
			
		||||
            keyPassword keystoreProperties['keyPassword']
 | 
			
		||||
            storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
 | 
			
		||||
            storePassword keystoreProperties['storePassword']
 | 
			
		||||
        }
 | 
			
		||||
    defaultConfig {
 | 
			
		||||
        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
 | 
			
		||||
        applicationId "xyz.dcdevelop.infotren"
 | 
			
		||||
        minSdkVersion 16
 | 
			
		||||
        targetSdkVersion 28
 | 
			
		||||
        versionCode flutterVersionCode.toInteger()
 | 
			
		||||
        versionName flutterVersionName
 | 
			
		||||
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    buildTypes {
 | 
			
		||||
        release {
 | 
			
		||||
            signingConfig signingConfigs.release
 | 
			
		||||
            // TODO: Add your own signing config for the release build.
 | 
			
		||||
            // Signing with the debug keys for now, so `flutter run --release` works.
 | 
			
		||||
            signingConfig signingConfigs.debug
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -77,4 +61,7 @@ flutter {
 | 
			
		|||
 | 
			
		||||
dependencies {
 | 
			
		||||
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
 | 
			
		||||
    testImplementation 'junit:junit:4.12'
 | 
			
		||||
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
 | 
			
		||||
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    package="ro.dcdev.infotren">
 | 
			
		||||
    package="ml.dandevelop.info_tren">
 | 
			
		||||
    <!-- Flutter needs it to communicate with the running application
 | 
			
		||||
         to allow setting breakpoints, to provide hot reload, etc.
 | 
			
		||||
    -->
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,41 +1,38 @@
 | 
			
		|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    package="ro.dcdev.infotren">
 | 
			
		||||
   <uses-permission android:name="android.permission.INTERNET"/>
 | 
			
		||||
   <application
 | 
			
		||||
    package="ml.dandevelop.info_tren">
 | 
			
		||||
 | 
			
		||||
    <uses-permission android:name="android.permission.INTERNET"/>
 | 
			
		||||
 | 
			
		||||
    <!-- io.flutter.app.FlutterApplication is an android.app.Application that
 | 
			
		||||
         calls FlutterMain.startInitialization(this); in its onCreate method.
 | 
			
		||||
         In most cases you can leave this as-is, but you if you want to provide
 | 
			
		||||
         additional functionality it is fine to subclass or reimplement
 | 
			
		||||
         FlutterApplication and put your custom class here. -->
 | 
			
		||||
    <application
 | 
			
		||||
        android:label="Info Tren"
 | 
			
		||||
        android:icon="@mipmap/ic_launcher">
 | 
			
		||||
        <activity
 | 
			
		||||
            android:name=".MainActivity"
 | 
			
		||||
            android:exported="true"
 | 
			
		||||
            android:launchMode="singleTop"
 | 
			
		||||
            android:theme="@style/LaunchTheme"
 | 
			
		||||
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
 | 
			
		||||
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
 | 
			
		||||
            android:hardwareAccelerated="true"
 | 
			
		||||
            android:windowSoftInputMode="adjustResize">
 | 
			
		||||
            <!-- Specifies an Android theme to apply to this Activity as soon as
 | 
			
		||||
                 the Android process has started. This theme is visible to the user
 | 
			
		||||
                 while the Flutter UI initializes. After that, this theme continues
 | 
			
		||||
                 to determine the Window background behind the Flutter UI. -->
 | 
			
		||||
            android:windowSoftInputMode="adjustResize"
 | 
			
		||||
            android:screenOrientation="portrait">
 | 
			
		||||
            <!-- Specify that the launch screen should continue being displayed -->
 | 
			
		||||
            <!-- until Flutter renders its first frame. -->
 | 
			
		||||
            <meta-data
 | 
			
		||||
              android:name="io.flutter.embedding.android.NormalTheme"
 | 
			
		||||
              android:resource="@style/NormalTheme"
 | 
			
		||||
              />
 | 
			
		||||
            <!-- Displays an Android View that continues showing the launch screen
 | 
			
		||||
                 Drawable until Flutter paints its first frame, then this splash
 | 
			
		||||
                 screen fades out. A splash screen is useful to avoid any visual
 | 
			
		||||
                 gap between the end of Android's launch screen and the painting of
 | 
			
		||||
                 Flutter's first frame. -->
 | 
			
		||||
            <meta-data
 | 
			
		||||
              android:name="io.flutter.embedding.android.SplashScreenDrawable"
 | 
			
		||||
              android:resource="@drawable/launch_background"
 | 
			
		||||
              />
 | 
			
		||||
                android:name="io.flutter.embedding.android.SplashScreenDrawable"
 | 
			
		||||
                android:resource="@drawable/launch_background" />
 | 
			
		||||
            <!-- This keeps the window background of the activity showing
 | 
			
		||||
                 until Flutter renders its first frame. It can be removed if
 | 
			
		||||
                 there is no splash screen (such as the default splash screen
 | 
			
		||||
                 defined in @style/LaunchTheme). -->
 | 
			
		||||
            <intent-filter>
 | 
			
		||||
                <action android:name="android.intent.action.MAIN"/>
 | 
			
		||||
                <category android:name="android.intent.category.LAUNCHER"/>
 | 
			
		||||
            </intent-filter>
 | 
			
		||||
        </activity>
 | 
			
		||||
        <!-- Don't delete the meta-data below.
 | 
			
		||||
             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
 | 
			
		||||
        <meta-data
 | 
			
		||||
            android:name="flutterEmbedding"
 | 
			
		||||
            android:value="2" />
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package ro.dcdev.infotren
 | 
			
		||||
package ml.dandevelop.info_tren
 | 
			
		||||
 | 
			
		||||
import io.flutter.embedding.android.FlutterActivity
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,6 @@
 | 
			
		|||
package xyz.dcdevelop.info_tren
 | 
			
		||||
 | 
			
		||||
import io.flutter.embedding.android.FlutterActivity
 | 
			
		||||
 | 
			
		||||
class MainActivity: FlutterActivity() {
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,18 +1,8 @@
 | 
			
		|||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<resources>
 | 
			
		||||
    <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
 | 
			
		||||
    <style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
 | 
			
		||||
    <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
 | 
			
		||||
        <!-- Show a splash screen on the activity. Automatically removed when
 | 
			
		||||
             Flutter draws its first frame -->
 | 
			
		||||
        <item name="android:windowBackground">@drawable/launch_background</item>
 | 
			
		||||
    </style>
 | 
			
		||||
    <!-- Theme applied to the Android Window as soon as the process has started.
 | 
			
		||||
         This theme determines the color of the Android Window while your
 | 
			
		||||
         Flutter UI initializes, as well as behind your Flutter UI while its
 | 
			
		||||
         running.
 | 
			
		||||
         
 | 
			
		||||
         This Theme is only used starting with V2 of Flutter's Android embedding. -->
 | 
			
		||||
    <style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
 | 
			
		||||
        <item name="android:windowBackground">?android:colorBackground</item>
 | 
			
		||||
    </style>
 | 
			
		||||
</resources>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    package="ro.dcdev.info_tren">
 | 
			
		||||
    package="ml.dandevelop.info_tren">
 | 
			
		||||
    <!-- Flutter needs it to communicate with the running application
 | 
			
		||||
         to allow setting breakpoints, to provide hot reload, etc.
 | 
			
		||||
    -->
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,12 +1,12 @@
 | 
			
		|||
buildscript {
 | 
			
		||||
    ext.kotlin_version = '1.7.10'
 | 
			
		||||
    ext.kotlin_version = '1.2.71'
 | 
			
		||||
    repositories {
 | 
			
		||||
        google()
 | 
			
		||||
        mavenCentral()
 | 
			
		||||
        jcenter()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    dependencies {
 | 
			
		||||
        classpath 'com.android.tools.build:gradle:7.4.2'
 | 
			
		||||
        classpath 'com.android.tools.build:gradle:3.2.1'
 | 
			
		||||
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -14,16 +14,18 @@ buildscript {
 | 
			
		|||
allprojects {
 | 
			
		||||
    repositories {
 | 
			
		||||
        google()
 | 
			
		||||
        mavenCentral()
 | 
			
		||||
        jcenter()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
rootProject.buildDir = '../build'
 | 
			
		||||
subprojects {
 | 
			
		||||
    project.buildDir = "${rootProject.buildDir}/${project.name}"
 | 
			
		||||
}
 | 
			
		||||
subprojects {
 | 
			
		||||
    project.evaluationDependsOn(':app')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
tasks.register("clean", Delete) {
 | 
			
		||||
task clean(type: Delete) {
 | 
			
		||||
    delete rootProject.buildDir
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,2 @@
 | 
			
		|||
org.gradle.jvmargs=-Xmx1536M
 | 
			
		||||
android.useAndroidX=true
 | 
			
		||||
android.enableJetifier=true
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
 | 
			
		|||
distributionPath=wrapper/dists
 | 
			
		||||
zipStoreBase=GRADLE_USER_HOME
 | 
			
		||||
zipStorePath=wrapper/dists
 | 
			
		||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.2-all.zip
 | 
			
		||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,11 +1,15 @@
 | 
			
		|||
include ':app'
 | 
			
		||||
 | 
			
		||||
def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
 | 
			
		||||
def properties = new Properties()
 | 
			
		||||
def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
 | 
			
		||||
 | 
			
		||||
assert localPropertiesFile.exists()
 | 
			
		||||
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
 | 
			
		||||
def plugins = new Properties()
 | 
			
		||||
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
 | 
			
		||||
if (pluginsFile.exists()) {
 | 
			
		||||
    pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
def flutterSdkPath = properties.getProperty("flutter.sdk")
 | 
			
		||||
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
 | 
			
		||||
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
 | 
			
		||||
plugins.each { name, path ->
 | 
			
		||||
    def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
 | 
			
		||||
    include ":$name"
 | 
			
		||||
    project(":$name").projectDir = pluginDirectory
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										1
									
								
								assets/lines/atc.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								assets/lines/atc.json
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
{"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}]}
 | 
			
		||||
							
								
								
									
										1
									
								
								assets/lines/cfr.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								assets/lines/cfr.json
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										6
									
								
								assets/lines/files.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								assets/lines/files.txt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,6 @@
 | 
			
		|||
atc.json
 | 
			
		||||
cfr.json
 | 
			
		||||
interregional.json
 | 
			
		||||
rc.json
 | 
			
		||||
st.json
 | 
			
		||||
tfc.json
 | 
			
		||||
							
								
								
									
										1
									
								
								assets/lines/interregional.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								assets/lines/interregional.json
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										1
									
								
								assets/lines/rc.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								assets/lines/rc.json
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										1
									
								
								assets/lines/st.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								assets/lines/st.json
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
{"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}]}
 | 
			
		||||
							
								
								
									
										1
									
								
								assets/lines/tfc.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								assets/lines/tfc.json
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										216
									
								
								codemagic.yaml
									
										
									
									
									
								
							
							
						
						
									
										216
									
								
								codemagic.yaml
									
										
									
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| 
						 | 
				
			
			@ -21,6 +21,6 @@
 | 
			
		|||
  <key>CFBundleVersion</key>
 | 
			
		||||
  <string>1.0</string>
 | 
			
		||||
  <key>MinimumOSVersion</key>
 | 
			
		||||
  <string>11.0</string>
 | 
			
		||||
  <string>9.0</string>
 | 
			
		||||
</dict>
 | 
			
		||||
</plist>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,2 +1 @@
 | 
			
		|||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
 | 
			
		||||
#include "Generated.xcconfig"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,2 +1 @@
 | 
			
		|||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
 | 
			
		||||
#include "Generated.xcconfig"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										14
									
								
								ios/Flutter/flutter_export_environment.sh
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										14
									
								
								ios/Flutter/flutter_export_environment.sh
									
										
									
									
									
										Executable file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,14 @@
 | 
			
		|||
#!/bin/sh
 | 
			
		||||
# This is a generated file; do not edit or check into version control.
 | 
			
		||||
export "FLUTTER_ROOT=/usr/local/Caskroom/flutter/2.2.3/flutter"
 | 
			
		||||
export "FLUTTER_APPLICATION_PATH=/Users/dan.cojocaru/info_tren"
 | 
			
		||||
export "COCOAPODS_PARALLEL_CODE_SIGN=true"
 | 
			
		||||
export "FLUTTER_TARGET=/Users/dan.cojocaru/info_tren/lib/main.dart"
 | 
			
		||||
export "FLUTTER_BUILD_DIR=build"
 | 
			
		||||
export "FLUTTER_BUILD_NAME=2.0.6"
 | 
			
		||||
export "FLUTTER_BUILD_NUMBER=2.0.6"
 | 
			
		||||
export "DART_DEFINES=Zmx1dHRlci5pbnNwZWN0b3Iuc3RydWN0dXJlZEVycm9ycz10cnVl,RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ=="
 | 
			
		||||
export "DART_OBFUSCATION=false"
 | 
			
		||||
export "TRACK_WIDGET_CREATION=true"
 | 
			
		||||
export "TREE_SHAKE_ICONS=false"
 | 
			
		||||
export "PACKAGE_CONFIG=/Users/dan.cojocaru/info_tren/.dart_tool/package_config.json"
 | 
			
		||||
							
								
								
									
										41
									
								
								ios/Podfile
									
										
									
									
									
								
							
							
						
						
									
										41
									
								
								ios/Podfile
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,41 +0,0 @@
 | 
			
		|||
# Uncomment this line to define a global platform for your project
 | 
			
		||||
# platform :ios, '11.0'
 | 
			
		||||
 | 
			
		||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
 | 
			
		||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
 | 
			
		||||
 | 
			
		||||
project 'Runner', {
 | 
			
		||||
  'Debug' => :debug,
 | 
			
		||||
  'Profile' => :release,
 | 
			
		||||
  'Release' => :release,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
def flutter_root
 | 
			
		||||
  generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
 | 
			
		||||
  unless File.exist?(generated_xcode_build_settings_path)
 | 
			
		||||
    raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  File.foreach(generated_xcode_build_settings_path) do |line|
 | 
			
		||||
    matches = line.match(/FLUTTER_ROOT\=(.*)/)
 | 
			
		||||
    return matches[1].strip if matches
 | 
			
		||||
  end
 | 
			
		||||
  raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
 | 
			
		||||
 | 
			
		||||
flutter_ios_podfile_setup
 | 
			
		||||
 | 
			
		||||
target 'Runner' do
 | 
			
		||||
  use_frameworks!
 | 
			
		||||
  use_modular_headers!
 | 
			
		||||
 | 
			
		||||
  flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
post_install do |installer|
 | 
			
		||||
  installer.pods_project.targets.each do |target|
 | 
			
		||||
    flutter_additional_ios_build_settings(target)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1,34 +0,0 @@
 | 
			
		|||
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
 | 
			
		||||
| 
						 | 
				
			
			@ -13,7 +13,6 @@
 | 
			
		|||
		97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
 | 
			
		||||
		97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
 | 
			
		||||
		97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
 | 
			
		||||
		AF5528149967EA996B5AA109 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6E6EB5FA5AA2228D5622CD62 /* Pods_Runner.framework */; };
 | 
			
		||||
/* End PBXBuildFile section */
 | 
			
		||||
 | 
			
		||||
/* Begin PBXCopyFilesBuildPhase section */
 | 
			
		||||
| 
						 | 
				
			
			@ -32,11 +31,7 @@
 | 
			
		|||
/* Begin PBXFileReference section */
 | 
			
		||||
		1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
 | 
			
		||||
		1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
 | 
			
		||||
		2088AE25E07C211FFB9CE536 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
 | 
			
		||||
		2F80AD107B0E1CC9E1C01A5A /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
 | 
			
		||||
		3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
 | 
			
		||||
		5DA42B3CD8940DB121C028E8 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
 | 
			
		||||
		6E6EB5FA5AA2228D5622CD62 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 | 
			
		||||
		74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
 | 
			
		||||
		74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
 | 
			
		||||
		7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
 | 
			
		||||
| 
						 | 
				
			
			@ -54,7 +49,6 @@
 | 
			
		|||
			isa = PBXFrameworksBuildPhase;
 | 
			
		||||
			buildActionMask = 2147483647;
 | 
			
		||||
			files = (
 | 
			
		||||
				AF5528149967EA996B5AA109 /* Pods_Runner.framework in Frameworks */,
 | 
			
		||||
			);
 | 
			
		||||
			runOnlyForDeploymentPostprocessing = 0;
 | 
			
		||||
		};
 | 
			
		||||
| 
						 | 
				
			
			@ -78,8 +72,6 @@
 | 
			
		|||
				9740EEB11CF90186004384FC /* Flutter */,
 | 
			
		||||
				97C146F01CF9000F007C117D /* Runner */,
 | 
			
		||||
				97C146EF1CF9000F007C117D /* Products */,
 | 
			
		||||
				B55F9B76DFEAB456725329A0 /* Pods */,
 | 
			
		||||
				E56598AA51C5533E6B51BD5A /* Frameworks */,
 | 
			
		||||
			);
 | 
			
		||||
			sourceTree = "<group>";
 | 
			
		||||
		};
 | 
			
		||||
| 
						 | 
				
			
			@ -106,25 +98,6 @@
 | 
			
		|||
			path = Runner;
 | 
			
		||||
			sourceTree = "<group>";
 | 
			
		||||
		};
 | 
			
		||||
		B55F9B76DFEAB456725329A0 /* Pods */ = {
 | 
			
		||||
			isa = PBXGroup;
 | 
			
		||||
			children = (
 | 
			
		||||
				2F80AD107B0E1CC9E1C01A5A /* Pods-Runner.debug.xcconfig */,
 | 
			
		||||
				2088AE25E07C211FFB9CE536 /* Pods-Runner.release.xcconfig */,
 | 
			
		||||
				5DA42B3CD8940DB121C028E8 /* Pods-Runner.profile.xcconfig */,
 | 
			
		||||
			);
 | 
			
		||||
			name = Pods;
 | 
			
		||||
			path = Pods;
 | 
			
		||||
			sourceTree = "<group>";
 | 
			
		||||
		};
 | 
			
		||||
		E56598AA51C5533E6B51BD5A /* Frameworks */ = {
 | 
			
		||||
			isa = PBXGroup;
 | 
			
		||||
			children = (
 | 
			
		||||
				6E6EB5FA5AA2228D5622CD62 /* Pods_Runner.framework */,
 | 
			
		||||
			);
 | 
			
		||||
			name = Frameworks;
 | 
			
		||||
			sourceTree = "<group>";
 | 
			
		||||
		};
 | 
			
		||||
/* End PBXGroup section */
 | 
			
		||||
 | 
			
		||||
/* Begin PBXNativeTarget section */
 | 
			
		||||
| 
						 | 
				
			
			@ -132,14 +105,12 @@
 | 
			
		|||
			isa = PBXNativeTarget;
 | 
			
		||||
			buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
 | 
			
		||||
			buildPhases = (
 | 
			
		||||
				2B2F3198BD0D2214C77EC99E /* [CP] Check Pods Manifest.lock */,
 | 
			
		||||
				9740EEB61CF901F6004384FC /* Run Script */,
 | 
			
		||||
				97C146EA1CF9000F007C117D /* Sources */,
 | 
			
		||||
				97C146EB1CF9000F007C117D /* Frameworks */,
 | 
			
		||||
				97C146EC1CF9000F007C117D /* Resources */,
 | 
			
		||||
				9705A1C41CF9048500538489 /* Embed Frameworks */,
 | 
			
		||||
				3B06AD1E1E4923F5004D2608 /* Thin Binary */,
 | 
			
		||||
				D71FC49A789443CEBF7C5C70 /* [CP] Embed Pods Frameworks */,
 | 
			
		||||
			);
 | 
			
		||||
			buildRules = (
 | 
			
		||||
			);
 | 
			
		||||
| 
						 | 
				
			
			@ -156,7 +127,7 @@
 | 
			
		|||
		97C146E61CF9000F007C117D /* Project object */ = {
 | 
			
		||||
			isa = PBXProject;
 | 
			
		||||
			attributes = {
 | 
			
		||||
				LastUpgradeCheck = 1300;
 | 
			
		||||
				LastUpgradeCheck = 1020;
 | 
			
		||||
				ORGANIZATIONNAME = "";
 | 
			
		||||
				TargetAttributes = {
 | 
			
		||||
					97C146ED1CF9000F007C117D = {
 | 
			
		||||
| 
						 | 
				
			
			@ -198,28 +169,6 @@
 | 
			
		|||
/* End PBXResourcesBuildPhase section */
 | 
			
		||||
 | 
			
		||||
/* Begin PBXShellScriptBuildPhase section */
 | 
			
		||||
		2B2F3198BD0D2214C77EC99E /* [CP] Check Pods Manifest.lock */ = {
 | 
			
		||||
			isa = PBXShellScriptBuildPhase;
 | 
			
		||||
			buildActionMask = 2147483647;
 | 
			
		||||
			files = (
 | 
			
		||||
			);
 | 
			
		||||
			inputFileListPaths = (
 | 
			
		||||
			);
 | 
			
		||||
			inputPaths = (
 | 
			
		||||
				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
 | 
			
		||||
				"${PODS_ROOT}/Manifest.lock",
 | 
			
		||||
			);
 | 
			
		||||
			name = "[CP] Check Pods Manifest.lock";
 | 
			
		||||
			outputFileListPaths = (
 | 
			
		||||
			);
 | 
			
		||||
			outputPaths = (
 | 
			
		||||
				"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
 | 
			
		||||
			);
 | 
			
		||||
			runOnlyForDeploymentPostprocessing = 0;
 | 
			
		||||
			shellPath = /bin/sh;
 | 
			
		||||
			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
 | 
			
		||||
			showEnvVarsInLog = 0;
 | 
			
		||||
		};
 | 
			
		||||
		3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
 | 
			
		||||
			isa = PBXShellScriptBuildPhase;
 | 
			
		||||
			buildActionMask = 2147483647;
 | 
			
		||||
| 
						 | 
				
			
			@ -248,23 +197,6 @@
 | 
			
		|||
			shellPath = /bin/sh;
 | 
			
		||||
			shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
 | 
			
		||||
		};
 | 
			
		||||
		D71FC49A789443CEBF7C5C70 /* [CP] Embed Pods Frameworks */ = {
 | 
			
		||||
			isa = PBXShellScriptBuildPhase;
 | 
			
		||||
			buildActionMask = 2147483647;
 | 
			
		||||
			files = (
 | 
			
		||||
			);
 | 
			
		||||
			inputFileListPaths = (
 | 
			
		||||
				"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
 | 
			
		||||
			);
 | 
			
		||||
			name = "[CP] Embed Pods Frameworks";
 | 
			
		||||
			outputFileListPaths = (
 | 
			
		||||
				"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
 | 
			
		||||
			);
 | 
			
		||||
			runOnlyForDeploymentPostprocessing = 0;
 | 
			
		||||
			shellPath = /bin/sh;
 | 
			
		||||
			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
 | 
			
		||||
			showEnvVarsInLog = 0;
 | 
			
		||||
		};
 | 
			
		||||
/* End PBXShellScriptBuildPhase section */
 | 
			
		||||
 | 
			
		||||
/* Begin PBXSourcesBuildPhase section */
 | 
			
		||||
| 
						 | 
				
			
			@ -340,7 +272,7 @@
 | 
			
		|||
				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 | 
			
		||||
				GCC_WARN_UNUSED_FUNCTION = YES;
 | 
			
		||||
				GCC_WARN_UNUSED_VARIABLE = YES;
 | 
			
		||||
				IPHONEOS_DEPLOYMENT_TARGET = 11.0;
 | 
			
		||||
				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
 | 
			
		||||
				MTL_ENABLE_DEBUG_INFO = NO;
 | 
			
		||||
				SDKROOT = iphoneos;
 | 
			
		||||
				SUPPORTED_PLATFORMS = iphoneos;
 | 
			
		||||
| 
						 | 
				
			
			@ -356,7 +288,6 @@
 | 
			
		|||
				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 | 
			
		||||
				CLANG_ENABLE_MODULES = YES;
 | 
			
		||||
				CURRENT_PROJECT_VERSION = 2.0.7;
 | 
			
		||||
				DEVELOPMENT_TEAM = NF9A3KMT8Q;
 | 
			
		||||
				ENABLE_BITCODE = NO;
 | 
			
		||||
				INFOPLIST_FILE = Runner/Info.plist;
 | 
			
		||||
				LD_RUNPATH_SEARCH_PATHS = (
 | 
			
		||||
| 
						 | 
				
			
			@ -364,7 +295,7 @@
 | 
			
		|||
					"@executable_path/Frameworks",
 | 
			
		||||
				);
 | 
			
		||||
				MARKETING_VERSION = 2.0.7;
 | 
			
		||||
				PRODUCT_BUNDLE_IDENTIFIER = ro.dcdev.infotren;
 | 
			
		||||
				PRODUCT_BUNDLE_IDENTIFIER = xyz.dcdevelop.infotren;
 | 
			
		||||
				PRODUCT_NAME = "$(TARGET_NAME)";
 | 
			
		||||
				SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
 | 
			
		||||
				SWIFT_VERSION = 5.0;
 | 
			
		||||
| 
						 | 
				
			
			@ -419,7 +350,7 @@
 | 
			
		|||
				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 | 
			
		||||
				GCC_WARN_UNUSED_FUNCTION = YES;
 | 
			
		||||
				GCC_WARN_UNUSED_VARIABLE = YES;
 | 
			
		||||
				IPHONEOS_DEPLOYMENT_TARGET = 11.0;
 | 
			
		||||
				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
 | 
			
		||||
				MTL_ENABLE_DEBUG_INFO = YES;
 | 
			
		||||
				ONLY_ACTIVE_ARCH = YES;
 | 
			
		||||
				SDKROOT = iphoneos;
 | 
			
		||||
| 
						 | 
				
			
			@ -468,7 +399,7 @@
 | 
			
		|||
				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 | 
			
		||||
				GCC_WARN_UNUSED_FUNCTION = YES;
 | 
			
		||||
				GCC_WARN_UNUSED_VARIABLE = YES;
 | 
			
		||||
				IPHONEOS_DEPLOYMENT_TARGET = 11.0;
 | 
			
		||||
				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
 | 
			
		||||
				MTL_ENABLE_DEBUG_INFO = NO;
 | 
			
		||||
				SDKROOT = iphoneos;
 | 
			
		||||
				SUPPORTED_PLATFORMS = iphoneos;
 | 
			
		||||
| 
						 | 
				
			
			@ -486,7 +417,6 @@
 | 
			
		|||
				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 | 
			
		||||
				CLANG_ENABLE_MODULES = YES;
 | 
			
		||||
				CURRENT_PROJECT_VERSION = 2.0.7;
 | 
			
		||||
				DEVELOPMENT_TEAM = NF9A3KMT8Q;
 | 
			
		||||
				ENABLE_BITCODE = NO;
 | 
			
		||||
				INFOPLIST_FILE = Runner/Info.plist;
 | 
			
		||||
				LD_RUNPATH_SEARCH_PATHS = (
 | 
			
		||||
| 
						 | 
				
			
			@ -494,7 +424,7 @@
 | 
			
		|||
					"@executable_path/Frameworks",
 | 
			
		||||
				);
 | 
			
		||||
				MARKETING_VERSION = 2.0.7;
 | 
			
		||||
				PRODUCT_BUNDLE_IDENTIFIER = ro.dcdev.infotren;
 | 
			
		||||
				PRODUCT_BUNDLE_IDENTIFIER = xyz.dcdevelop.infotren;
 | 
			
		||||
				PRODUCT_NAME = "$(TARGET_NAME)";
 | 
			
		||||
				SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
 | 
			
		||||
				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
 | 
			
		||||
| 
						 | 
				
			
			@ -510,7 +440,6 @@
 | 
			
		|||
				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 | 
			
		||||
				CLANG_ENABLE_MODULES = YES;
 | 
			
		||||
				CURRENT_PROJECT_VERSION = 2.0.7;
 | 
			
		||||
				DEVELOPMENT_TEAM = NF9A3KMT8Q;
 | 
			
		||||
				ENABLE_BITCODE = NO;
 | 
			
		||||
				INFOPLIST_FILE = Runner/Info.plist;
 | 
			
		||||
				LD_RUNPATH_SEARCH_PATHS = (
 | 
			
		||||
| 
						 | 
				
			
			@ -518,7 +447,7 @@
 | 
			
		|||
					"@executable_path/Frameworks",
 | 
			
		||||
				);
 | 
			
		||||
				MARKETING_VERSION = 2.0.7;
 | 
			
		||||
				PRODUCT_BUNDLE_IDENTIFIER = ro.dcdev.infotren;
 | 
			
		||||
				PRODUCT_BUNDLE_IDENTIFIER = xyz.dcdevelop.infotren;
 | 
			
		||||
				PRODUCT_NAME = "$(TARGET_NAME)";
 | 
			
		||||
				SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
 | 
			
		||||
				SWIFT_VERSION = 5.0;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<Scheme
 | 
			
		||||
   LastUpgradeVersion = "1300"
 | 
			
		||||
   LastUpgradeVersion = "1020"
 | 
			
		||||
   version = "1.3">
 | 
			
		||||
   <BuildAction
 | 
			
		||||
      parallelizeBuildables = "YES"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										3
									
								
								ios/Runner.xcworkspace/contents.xcworkspacedata
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										3
									
								
								ios/Runner.xcworkspace/contents.xcworkspacedata
									
										
									
										generated
									
									
									
								
							| 
						 | 
				
			
			@ -4,7 +4,4 @@
 | 
			
		|||
   <FileRef
 | 
			
		||||
      location = "group:Runner.xcodeproj">
 | 
			
		||||
   </FileRef>
 | 
			
		||||
   <FileRef
 | 
			
		||||
      location = "group:Pods/Pods.xcodeproj">
 | 
			
		||||
   </FileRef>
 | 
			
		||||
</Workspace>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,7 +43,5 @@
 | 
			
		|||
	</array>
 | 
			
		||||
	<key>UIViewControllerBasedStatusBarAppearance</key>
 | 
			
		||||
	<false/>
 | 
			
		||||
	<key>CADisableMinimumFrameDurationOnPhone</key>
 | 
			
		||||
	<true/>
 | 
			
		||||
</dict>
 | 
			
		||||
</plist>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1 +0,0 @@
 | 
			
		|||
const authority = 'scraper.infotren.dcdev.ro';
 | 
			
		||||
| 
						 | 
				
			
			@ -1,18 +0,0 @@
 | 
			
		|||
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,14 +0,0 @@
 | 
			
		|||
import 'dart:convert';
 | 
			
		||||
 | 
			
		||||
import 'package:http/http.dart' as http;
 | 
			
		||||
import 'package:info_tren/api/common.dart';
 | 
			
		||||
import 'package:info_tren/models.dart';
 | 
			
		||||
 | 
			
		||||
Future<StationData> getStationData(String stationName, [DateTime? date]) async {
 | 
			
		||||
  final uri = Uri.https(authority, 'v3/stations/$stationName');
 | 
			
		||||
  if (date != null) {
 | 
			
		||||
    uri.queryParameters['date'] = date.toIso8601String();
 | 
			
		||||
  }
 | 
			
		||||
  final response = await http.get(uri);
 | 
			
		||||
  return StationData.fromJson(jsonDecode(response.body));
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,11 +0,0 @@
 | 
			
		|||
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<StationsResult>> get stations async {
 | 
			
		||||
  final result = await http.get(Uri.https(authority, 'v2/stations'));
 | 
			
		||||
  final data = jsonDecode(result.body) as List<dynamic>;
 | 
			
		||||
  return data.map((e) => StationsResult.fromJson(e)).toList(growable: false,);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,11 +1,9 @@
 | 
			
		|||
import 'package:http/http.dart' as http;
 | 
			
		||||
import 'package:info_tren/api/common.dart';
 | 
			
		||||
import 'package:info_tren/models.dart';
 | 
			
		||||
import 'package:info_tren/models/train_data.dart';
 | 
			
		||||
 | 
			
		||||
Future<TrainData> getTrain(String trainNumber, {DateTime? date}) async {
 | 
			
		||||
  date ??= DateTime.now();
 | 
			
		||||
  final response = await http.get(Uri.https(authority, 'v3/trains/$trainNumber', {
 | 
			
		||||
    'date': date.toUtc().toIso8601String(),
 | 
			
		||||
  }),);
 | 
			
		||||
const AUTHORITY = 'scraper.infotren.dcdevelop.xyz';
 | 
			
		||||
 | 
			
		||||
Future<TrainData> getTrain(int trainNumber) async {
 | 
			
		||||
  final response = await http.get(Uri.https(AUTHORITY, 'train/$trainNumber'));
 | 
			
		||||
  return trainDataFromJson(response.body);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,11 +0,0 @@
 | 
			
		|||
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,);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,59 +0,0 @@
 | 
			
		|||
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);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,80 +0,0 @@
 | 
			
		|||
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,
 | 
			
		||||
              ),
 | 
			
		||||
            ),
 | 
			
		||||
          ],
 | 
			
		||||
        ),
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,80 +0,0 @@
 | 
			
		|||
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,
 | 
			
		||||
              ),
 | 
			
		||||
            ),
 | 
			
		||||
          ],
 | 
			
		||||
        ),
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,79 +0,0 @@
 | 
			
		|||
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,
 | 
			
		||||
              ),
 | 
			
		||||
            ),
 | 
			
		||||
          ],
 | 
			
		||||
        ),
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -4,8 +4,8 @@ import 'package:info_tren/pages/train_info_page/train_info_constants.dart';
 | 
			
		|||
class CupertinoDivider extends StatelessWidget {
 | 
			
		||||
  final Color color;
 | 
			
		||||
 | 
			
		||||
  const CupertinoDivider({Key? key, Color? color}):
 | 
			
		||||
  color = color ?? foregroundDarkGrey,
 | 
			
		||||
  CupertinoDivider({Key? key, Color? color}):
 | 
			
		||||
  color = color ?? FOREGROUND_DARK_GREY,
 | 
			
		||||
  super(key: key);
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
| 
						 | 
				
			
			@ -33,8 +33,8 @@ class CupertinoDivider extends StatelessWidget {
 | 
			
		|||
class CupertinoVerticalDivider extends StatelessWidget {
 | 
			
		||||
  final Color color;
 | 
			
		||||
 | 
			
		||||
  const CupertinoVerticalDivider({Key? key, Color? color}):
 | 
			
		||||
  color = color ?? foregroundDarkGrey,
 | 
			
		||||
  CupertinoVerticalDivider({Key? key, Color? color}):
 | 
			
		||||
  color = color ?? FOREGROUND_DARK_GREY,
 | 
			
		||||
  super(key: key);
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,58 +0,0 @@
 | 
			
		|||
import 'package:flutter/cupertino.dart';
 | 
			
		||||
 | 
			
		||||
class CupertinoListTile extends StatelessWidget {
 | 
			
		||||
  final Widget? leading;
 | 
			
		||||
  final Widget? title;
 | 
			
		||||
  final Widget? subtitle;
 | 
			
		||||
  final Widget? trailing;
 | 
			
		||||
  final void Function()? onTap;
 | 
			
		||||
 | 
			
		||||
  const CupertinoListTile({ super.key, this.leading, this.title, this.subtitle, this.trailing, this.onTap, });
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    return GestureDetector(
 | 
			
		||||
      onTap: onTap,
 | 
			
		||||
      behavior: HitTestBehavior.opaque,
 | 
			
		||||
      child: Row(
 | 
			
		||||
        mainAxisSize: MainAxisSize.max,
 | 
			
		||||
        children: [
 | 
			
		||||
          if (leading != null)
 | 
			
		||||
            Padding(
 | 
			
		||||
              padding: const EdgeInsets.all(8.0),
 | 
			
		||||
              child: leading!,
 | 
			
		||||
            ),
 | 
			
		||||
          Expanded(
 | 
			
		||||
            child: Padding(
 | 
			
		||||
              padding: const EdgeInsets.all(8.0),
 | 
			
		||||
              child: Column(
 | 
			
		||||
                mainAxisSize: MainAxisSize.min,
 | 
			
		||||
                crossAxisAlignment: CrossAxisAlignment.start,
 | 
			
		||||
                children: [
 | 
			
		||||
                  if (title != null)
 | 
			
		||||
                    title!,
 | 
			
		||||
                  if (subtitle != null)
 | 
			
		||||
                    CupertinoTheme(
 | 
			
		||||
                      data: CupertinoTheme.of(context).copyWith(
 | 
			
		||||
                        textTheme: CupertinoTextThemeData(
 | 
			
		||||
                          textStyle: TextStyle(
 | 
			
		||||
                            fontSize: CupertinoTheme.of(context).textTheme.textStyle.fontSize! - 2,
 | 
			
		||||
                          )
 | 
			
		||||
                        )
 | 
			
		||||
                      ),
 | 
			
		||||
                      child: subtitle!,
 | 
			
		||||
                    ),
 | 
			
		||||
                ],
 | 
			
		||||
              ),
 | 
			
		||||
            ),
 | 
			
		||||
          ),
 | 
			
		||||
          if (trailing != null)
 | 
			
		||||
            Padding(
 | 
			
		||||
              padding: const EdgeInsets.all(8.0),
 | 
			
		||||
              child: trailing!,
 | 
			
		||||
            ),
 | 
			
		||||
        ],
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
import 'package:flutter/cupertino.dart';
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
import 'package:info_tren/models.dart';
 | 
			
		||||
import 'package:info_tren/models/ui_design.dart';
 | 
			
		||||
import 'package:info_tren/utils/default_ui_design.dart';
 | 
			
		||||
 | 
			
		||||
class FutureDisplay<T> extends StatelessWidget {
 | 
			
		||||
| 
						 | 
				
			
			@ -9,7 +9,7 @@ class FutureDisplay<T> extends StatelessWidget {
 | 
			
		|||
  final Widget Function<T>(BuildContext context, T data) builder;
 | 
			
		||||
  final Widget Function(BuildContext context, Object error, StackTrace? st)? errorBuilder;
 | 
			
		||||
 | 
			
		||||
  const FutureDisplay({Key? key, required this.future, required this.builder, this.errorBuilder, this.uiDesign}): super(key: key);
 | 
			
		||||
  FutureDisplay({Key? key, required this.future, required this.builder, this.errorBuilder, this.uiDesign}): super(key: key);
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
| 
						 | 
				
			
			@ -24,10 +24,10 @@ class FutureDisplay<T> extends StatelessWidget {
 | 
			
		|||
        Widget loadingWidget;
 | 
			
		||||
        switch (uiDesign) {
 | 
			
		||||
          case UiDesign.MATERIAL:
 | 
			
		||||
            loadingWidget = const CircularProgressIndicator();
 | 
			
		||||
            loadingWidget = CircularProgressIndicator();
 | 
			
		||||
            break;
 | 
			
		||||
          case UiDesign.CUPERTINO:
 | 
			
		||||
            loadingWidget = const CupertinoActivityIndicator();
 | 
			
		||||
            loadingWidget = CupertinoActivityIndicator();
 | 
			
		||||
            break;
 | 
			
		||||
          default:
 | 
			
		||||
            throw UnmatchedUiDesignException(uiDesign);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,27 +1,24 @@
 | 
			
		|||
import 'package:flutter/widgets.dart';
 | 
			
		||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
			
		||||
import 'package:info_tren/components/loading/loading_cupertino.dart';
 | 
			
		||||
import 'package:info_tren/components/loading/loading_fluent.dart';
 | 
			
		||||
import 'package:info_tren/components/loading/loading_material.dart';
 | 
			
		||||
import 'package:info_tren/models.dart';
 | 
			
		||||
import 'package:info_tren/providers.dart';
 | 
			
		||||
import 'package:info_tren/models/ui_design.dart';
 | 
			
		||||
import 'package:info_tren/utils/default_ui_design.dart';
 | 
			
		||||
 | 
			
		||||
class Loading extends ConsumerWidget {
 | 
			
		||||
  static const defaultText = 'Loading...';
 | 
			
		||||
class Loading extends StatelessWidget {
 | 
			
		||||
  static const DEFAULT_TEXT = 'Loading...';
 | 
			
		||||
  
 | 
			
		||||
  final UiDesign? uiDesign;
 | 
			
		||||
  final String? text;
 | 
			
		||||
  const Loading({ super.key, this.text, });
 | 
			
		||||
  const Loading({ Key? key, this.text, this.uiDesign }) : super(key: key);
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context, WidgetRef ref) {
 | 
			
		||||
    final uiDesign = ref.watch(uiDesignProvider);
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    final uiDesign = this.uiDesign ?? defaultUiDesign;
 | 
			
		||||
    switch (uiDesign) {
 | 
			
		||||
      case UiDesign.MATERIAL:
 | 
			
		||||
        return LoadingMaterial(text: text ?? defaultText,);
 | 
			
		||||
        return LoadingMaterial(text: text ?? DEFAULT_TEXT,);
 | 
			
		||||
      case UiDesign.CUPERTINO:
 | 
			
		||||
        return LoadingCupertino(text: text ?? defaultText,);
 | 
			
		||||
      case UiDesign.FLUENT:
 | 
			
		||||
        return LoadingFluent(text: text ?? defaultText,);
 | 
			
		||||
        return LoadingCupertino(text: text ?? DEFAULT_TEXT,);
 | 
			
		||||
      default:
 | 
			
		||||
        throw UnmatchedUiDesignException(uiDesign);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -30,5 +27,5 @@ class Loading extends ConsumerWidget {
 | 
			
		|||
 | 
			
		||||
abstract class LoadingCommon extends StatelessWidget {
 | 
			
		||||
  final String text;
 | 
			
		||||
  const LoadingCommon({required this.text, super.key,});
 | 
			
		||||
  LoadingCommon({required this.text});
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,8 +1,9 @@
 | 
			
		|||
import 'package:flutter/cupertino.dart';
 | 
			
		||||
import 'package:flutter/src/widgets/framework.dart';
 | 
			
		||||
import 'package:info_tren/components/loading/loading.dart';
 | 
			
		||||
 | 
			
		||||
class LoadingCupertino extends LoadingCommon {
 | 
			
		||||
  const LoadingCupertino({required super.text, super.key,});
 | 
			
		||||
  LoadingCupertino({required String text}) : super(text: text,);
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
| 
						 | 
				
			
			@ -11,8 +12,8 @@ class LoadingCupertino extends LoadingCommon {
 | 
			
		|||
        crossAxisAlignment: CrossAxisAlignment.center,
 | 
			
		||||
        mainAxisSize: MainAxisSize.min,
 | 
			
		||||
        children: [
 | 
			
		||||
          const Padding(
 | 
			
		||||
            padding: EdgeInsets.all(8.0),
 | 
			
		||||
          Padding(
 | 
			
		||||
            padding: const EdgeInsets.all(8.0),
 | 
			
		||||
            child: CupertinoActivityIndicator(),
 | 
			
		||||
          ),
 | 
			
		||||
          Padding(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,26 +0,0 @@
 | 
			
		|||
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),
 | 
			
		||||
          ),
 | 
			
		||||
        ],
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
 | 
			
		|||
import 'package:info_tren/components/loading/loading.dart';
 | 
			
		||||
 | 
			
		||||
class LoadingMaterial extends LoadingCommon {
 | 
			
		||||
  const LoadingMaterial({required super.text, super.key});
 | 
			
		||||
  LoadingMaterial({required String text}) : super(text: text,);
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
| 
						 | 
				
			
			@ -11,8 +11,8 @@ class LoadingMaterial extends LoadingCommon {
 | 
			
		|||
        crossAxisAlignment: CrossAxisAlignment.center,
 | 
			
		||||
        mainAxisSize: MainAxisSize.min,
 | 
			
		||||
        children: [
 | 
			
		||||
          const Padding(
 | 
			
		||||
            padding: EdgeInsets.all(8.0),
 | 
			
		||||
          Padding(
 | 
			
		||||
            padding: const EdgeInsets.all(8.0),
 | 
			
		||||
            child: CircularProgressIndicator(),
 | 
			
		||||
          ),
 | 
			
		||||
          Padding(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,10 +1,9 @@
 | 
			
		|||
import 'package:flutter/widgets.dart';
 | 
			
		||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
			
		||||
 | 
			
		||||
class RefreshFutureBuilder<T> extends StatefulWidget {
 | 
			
		||||
  final Future<T> Function()? futureCreator;
 | 
			
		||||
  final T? initialData;
 | 
			
		||||
  final Widget Function(BuildContext context, Future Function() refresh, Future Function(Future<T> Function()) replaceFuture, RefreshFutureBuilderSnapshot<T> snapshot) builder;
 | 
			
		||||
  final Widget Function(BuildContext context, Future Function() refresh, RefreshFutureBuilderSnapshot<T> snapshot) builder;
 | 
			
		||||
 | 
			
		||||
  const RefreshFutureBuilder({ Key? key, this.futureCreator, this.initialData, required this.builder }) : super(key: key);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -15,12 +14,11 @@ class RefreshFutureBuilder<T> extends StatefulWidget {
 | 
			
		|||
class _RefreshFutureBuilderState<T> extends State<RefreshFutureBuilder<T>> {
 | 
			
		||||
  late RefreshFutureBuilderSnapshot<T> snapshot;
 | 
			
		||||
  Future<T> Function()? futureCreator;
 | 
			
		||||
  bool _disposed = false;
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  void initState() {
 | 
			
		||||
    super.initState();
 | 
			
		||||
    snapshot = widget.initialData != null ? RefreshFutureBuilderSnapshot.initial(widget.initialData as T) : const RefreshFutureBuilderSnapshot.nothing();
 | 
			
		||||
    snapshot = widget.initialData != null ? RefreshFutureBuilderSnapshot.initial(widget.initialData!) : RefreshFutureBuilderSnapshot.nothing();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
| 
						 | 
				
			
			@ -40,7 +38,7 @@ class _RefreshFutureBuilderState<T> extends State<RefreshFutureBuilder<T>> {
 | 
			
		|||
    setState(() {
 | 
			
		||||
      switch (snapshot.state) {
 | 
			
		||||
        case RefreshFutureBuilderState.none:
 | 
			
		||||
          snapshot = const RefreshFutureBuilderSnapshot.waiting();
 | 
			
		||||
          snapshot = RefreshFutureBuilderSnapshot.waiting();
 | 
			
		||||
          break;
 | 
			
		||||
        case RefreshFutureBuilderState.initial:
 | 
			
		||||
          snapshot = RefreshFutureBuilderSnapshot.refresh(snapshot.data);
 | 
			
		||||
| 
						 | 
				
			
			@ -48,7 +46,7 @@ class _RefreshFutureBuilderState<T> extends State<RefreshFutureBuilder<T>> {
 | 
			
		|||
        case RefreshFutureBuilderState.waiting:
 | 
			
		||||
          return;
 | 
			
		||||
        case RefreshFutureBuilderState.error:
 | 
			
		||||
          snapshot = const RefreshFutureBuilderSnapshot.waiting();
 | 
			
		||||
          snapshot = RefreshFutureBuilderSnapshot.refresh(null, snapshot.error, snapshot.stackTrace);
 | 
			
		||||
          break;
 | 
			
		||||
        case RefreshFutureBuilderState.done:
 | 
			
		||||
          snapshot = RefreshFutureBuilderSnapshot.refresh(snapshot.data);
 | 
			
		||||
| 
						 | 
				
			
			@ -63,17 +61,11 @@ class _RefreshFutureBuilderState<T> extends State<RefreshFutureBuilder<T>> {
 | 
			
		|||
    });
 | 
			
		||||
    try {
 | 
			
		||||
      final data = await futureCreator!();
 | 
			
		||||
      if (_disposed) {
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      setState(() {
 | 
			
		||||
        snapshot = RefreshFutureBuilderSnapshot.withData(data);
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
    catch (e, st) {
 | 
			
		||||
      if (_disposed) {
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      setState(() {
 | 
			
		||||
        if (snapshot.state == RefreshFutureBuilderState.waiting) {
 | 
			
		||||
          snapshot = RefreshFutureBuilderSnapshot.withError(e, st);
 | 
			
		||||
| 
						 | 
				
			
			@ -85,23 +77,11 @@ class _RefreshFutureBuilderState<T> extends State<RefreshFutureBuilder<T>> {
 | 
			
		|||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Future replaceFutureCreator(Future<T> Function() newFutureCreator) {
 | 
			
		||||
    futureCreator = newFutureCreator;
 | 
			
		||||
    return runFuture();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  void dispose() {
 | 
			
		||||
    _disposed = true;
 | 
			
		||||
    super.dispose();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    return widget.builder(
 | 
			
		||||
      context, 
 | 
			
		||||
      runFuture,
 | 
			
		||||
      replaceFutureCreator,
 | 
			
		||||
      snapshot,
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -135,41 +115,3 @@ enum RefreshFutureBuilderState {
 | 
			
		|||
  refreshing,
 | 
			
		||||
  refreshError,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class RefreshFutureBuilderProviderAdapter<T> extends ConsumerWidget {
 | 
			
		||||
  final Provider<AsyncValue<T>> futureProvider;
 | 
			
		||||
  final Future Function()? refresh;
 | 
			
		||||
  final Widget Function(BuildContext context, Future Function() refresh, Future Function(Future<T> Function()) replaceFuture, RefreshFutureBuilderSnapshot<T> snapshot) builder;
 | 
			
		||||
 | 
			
		||||
  const RefreshFutureBuilderProviderAdapter({required this.futureProvider, required this.builder, this.refresh, super.key});
 | 
			
		||||
  
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context, WidgetRef ref) {
 | 
			
		||||
    final value = ref.watch(futureProvider);
 | 
			
		||||
 | 
			
		||||
    return builder(
 | 
			
		||||
      context,
 | 
			
		||||
      refresh ?? () async {
 | 
			
		||||
        ref.invalidate(futureProvider);
 | 
			
		||||
      },
 | 
			
		||||
      (_) => throw UnimplementedError('Cannot replace the future when adapting a FutureProvider'),
 | 
			
		||||
      value.when(
 | 
			
		||||
        data: (data) => value.isLoading || value.isRefreshing 
 | 
			
		||||
          ? RefreshFutureBuilderSnapshot.refresh(data)
 | 
			
		||||
          : RefreshFutureBuilderSnapshot.withData(data), 
 | 
			
		||||
        error: (error, st) => value.isLoading || value.isRefreshing 
 | 
			
		||||
          ? RefreshFutureBuilderSnapshot.refreshError(value.hasValue ? value.value : null, value.error, value.stackTrace)
 | 
			
		||||
          : RefreshFutureBuilderSnapshot.withError(error, st), 
 | 
			
		||||
        loading: () {
 | 
			
		||||
          if (value.hasValue) {
 | 
			
		||||
            return RefreshFutureBuilderSnapshot.refresh(value.value, value.error, value.stackTrace);
 | 
			
		||||
          }
 | 
			
		||||
          else if (value.hasError) {
 | 
			
		||||
            return RefreshFutureBuilderSnapshot.refreshError(value.value, value.error, value.stackTrace);
 | 
			
		||||
          } 
 | 
			
		||||
          return const RefreshFutureBuilderSnapshot.waiting();
 | 
			
		||||
        },
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,75 +1,113 @@
 | 
			
		|||
import 'dart:convert';
 | 
			
		||||
 | 
			
		||||
import 'package:flutter/widgets.dart';
 | 
			
		||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
			
		||||
import 'package:info_tren/components/select_train_suggestions/select_train_suggestions_cupertino.dart';
 | 
			
		||||
import 'package:info_tren/components/select_train_suggestions/select_train_suggestions_fluent.dart';
 | 
			
		||||
import 'package:info_tren/components/select_train_suggestions/select_train_suggestions_material.dart';
 | 
			
		||||
import 'package:info_tren/models.dart';
 | 
			
		||||
import 'package:info_tren/providers.dart';
 | 
			
		||||
import 'package:info_tren/models/train_operator_lines.dart';
 | 
			
		||||
import 'package:info_tren/models/ui_design.dart';
 | 
			
		||||
import 'package:info_tren/utils/default_ui_design.dart';
 | 
			
		||||
import 'package:tuple/tuple.dart';
 | 
			
		||||
 | 
			
		||||
class SelectTrainSuggestions extends ConsumerWidget {
 | 
			
		||||
  final List<TrainsResult> choices;
 | 
			
		||||
  final String? currentInput;
 | 
			
		||||
  final void Function(String trainNumber) onTrainSelected;
 | 
			
		||||
class SelectTrainSuggestions extends StatefulWidget {
 | 
			
		||||
  final UiDesign? uiDesign;
 | 
			
		||||
  final String userInput;
 | 
			
		||||
  final void Function(int trainNumber) onTrainSelected;
 | 
			
		||||
 | 
			
		||||
  const SelectTrainSuggestions({ Key? key, required this.uiDesign, required this.userInput, required this.onTrainSelected }) : super(key: key);
 | 
			
		||||
 | 
			
		||||
  const SelectTrainSuggestions({required this.choices, this.currentInput, required this.onTrainSelected, super.key, });
 | 
			
		||||
  
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context, WidgetRef ref) {
 | 
			
		||||
    final uiDesign = ref.watch(uiDesignProvider);
 | 
			
		||||
 | 
			
		||||
  SelectTrainSuggestionsState createState() {
 | 
			
		||||
    final uiDesign = this.uiDesign ?? defaultUiDesign;
 | 
			
		||||
    switch(uiDesign) {
 | 
			
		||||
      case UiDesign.MATERIAL:
 | 
			
		||||
        return SelectTrainSuggestionsMaterial(
 | 
			
		||||
          choices: choices,
 | 
			
		||||
          onTrainSelected: onTrainSelected,
 | 
			
		||||
          currentInput: currentInput,
 | 
			
		||||
        );
 | 
			
		||||
        return SelectTrainSuggestionsStateMaterial();
 | 
			
		||||
      case UiDesign.CUPERTINO:
 | 
			
		||||
        return SelectTrainSuggestionsCupertino(
 | 
			
		||||
          choices: choices,
 | 
			
		||||
          onTrainSelected: onTrainSelected,
 | 
			
		||||
          currentInput: currentInput,
 | 
			
		||||
        );
 | 
			
		||||
      case UiDesign.FLUENT:
 | 
			
		||||
        return SelectTrainSuggestionsFluent(
 | 
			
		||||
          choices: choices,
 | 
			
		||||
          onTrainSelected: onTrainSelected,
 | 
			
		||||
          currentInput: currentInput,
 | 
			
		||||
        );
 | 
			
		||||
        return SelectTrainSuggestionsStateCupertino();
 | 
			
		||||
      default:
 | 
			
		||||
        throw UnmatchedUiDesignException(uiDesign);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
abstract class SelectTrainSuggestionsShared extends StatelessWidget {
 | 
			
		||||
  String getUseCurrentInputWidgetText(String currentInput) => 'Caută trenul cu numărul $currentInput';
 | 
			
		||||
  Widget getUseCurrentInputWidget(String currentInput, void Function(String) onTrainSelected);
 | 
			
		||||
abstract class SelectTrainSuggestionsState extends State<SelectTrainSuggestions> {
 | 
			
		||||
  late String userInput;
 | 
			
		||||
 | 
			
		||||
  final List<TrainsResult> choices;
 | 
			
		||||
  final String? currentInput;
 | 
			
		||||
  final void Function(String trainNumber) onTrainSelected;
 | 
			
		||||
  List<TrainOperatorLines> operators = [];
 | 
			
		||||
 | 
			
		||||
  const SelectTrainSuggestionsShared({
 | 
			
		||||
    required this.choices, 
 | 
			
		||||
    this.currentInput, 
 | 
			
		||||
    required this.onTrainSelected, 
 | 
			
		||||
    super.key,
 | 
			
		||||
  });
 | 
			
		||||
  Future loadOperators(BuildContext context) async {
 | 
			
		||||
    operators = [];
 | 
			
		||||
 | 
			
		||||
    final operatorsString = await DefaultAssetBundle.of(context).loadString("assets/lines/files.txt");
 | 
			
		||||
    final operatorsFilesList = operatorsString.split("\n");
 | 
			
		||||
 | 
			
		||||
    final decoder = JsonDecoder();
 | 
			
		||||
 | 
			
		||||
    for (final operatorFile in operatorsFilesList) {
 | 
			
		||||
      final operatorString = await DefaultAssetBundle.of(context).loadString("assets/lines/$operatorFile");
 | 
			
		||||
      final operatorData = decoder.convert(operatorString);
 | 
			
		||||
      final _operator = TrainOperatorLines.fromJson(operatorData);
 | 
			
		||||
      operators.add(_operator);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  void initState() {
 | 
			
		||||
    super.initState();
 | 
			
		||||
    userInput = widget.userInput;
 | 
			
		||||
 | 
			
		||||
    loadOperators(context).then((_) {
 | 
			
		||||
      setState(() {});
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  void didChangeDependencies() {
 | 
			
		||||
    super.didChangeDependencies();
 | 
			
		||||
    if (userInput != widget.userInput) {
 | 
			
		||||
      setState(() {
 | 
			
		||||
        userInput = widget.userInput;
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  String getUseCurrentInputWidgetText(int currentInput) => 'Caută trenul cu numărul $currentInput';
 | 
			
		||||
  Widget getUseCurrentInputWidget(int currentInput, void Function(int) onTrainSelected);
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    var slivers = choices.map((c) => c.company).toSet().map((operator) => OperatorAutocompleteSliver(
 | 
			
		||||
      operatorName: operator, 
 | 
			
		||||
      trains: choices.where((c) => c.company == operator).toList(), 
 | 
			
		||||
      onTrainSelected: onTrainSelected,
 | 
			
		||||
    var sliversTuple = operators.map(
 | 
			
		||||
      (op) => Tuple2(
 | 
			
		||||
        getFilteredLines(op, userInput), 
 | 
			
		||||
        op.operator, 
 | 
			
		||||
      )
 | 
			
		||||
    ).where((tuple) => tuple.item1.isNotEmpty).toList();
 | 
			
		||||
    if (userInput.isNotEmpty) sliversTuple.sort((a, b) {
 | 
			
		||||
      final aTrain = a.item1.first;
 | 
			
		||||
      final bTrain = b.item1.first;
 | 
			
		||||
 | 
			
		||||
      final inputAsRegExp = RegExp(userInput);
 | 
			
		||||
 | 
			
		||||
      final matchOnA = inputAsRegExp.firstMatch(aTrain.number)!;
 | 
			
		||||
      final matchOnB = inputAsRegExp.firstMatch(bTrain.number)!;
 | 
			
		||||
 | 
			
		||||
      if (matchOnA.start != matchOnB.start) return matchOnA.start - matchOnB.start;
 | 
			
		||||
 | 
			
		||||
      if (aTrain.number.length != bTrain.number.length) return aTrain.number.length - bTrain.number.length;
 | 
			
		||||
 | 
			
		||||
      return aTrain.number.compareTo(bTrain.number);
 | 
			
		||||
    });
 | 
			
		||||
    var slivers = sliversTuple.map((tuple) => OperatorAutocompleteSliver(
 | 
			
		||||
      uiDesign: widget.uiDesign,
 | 
			
		||||
      operatorName: tuple.item2, 
 | 
			
		||||
      trains: tuple.item1, 
 | 
			
		||||
      onTrainSelected: widget.onTrainSelected,
 | 
			
		||||
    )).toList();
 | 
			
		||||
 | 
			
		||||
    return CustomScrollView(
 | 
			
		||||
      slivers: <Widget>[
 | 
			
		||||
        ...slivers,
 | 
			
		||||
        SliverToBoxAdapter(
 | 
			
		||||
          child: currentInput != null && int.tryParse(currentInput!) != null ? getUseCurrentInputWidget(currentInput!, onTrainSelected) : Container(),
 | 
			
		||||
          child: int.tryParse(userInput) != null ? getUseCurrentInputWidget(int.parse(userInput), widget.onTrainSelected) : Container(),
 | 
			
		||||
        ),
 | 
			
		||||
        SliverToBoxAdapter(
 | 
			
		||||
          child: Container(
 | 
			
		||||
| 
						 | 
				
			
			@ -79,21 +117,44 @@ abstract class SelectTrainSuggestionsShared extends StatelessWidget {
 | 
			
		|||
      ],
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  List<TrainOperatorTrainDescription> getFilteredLines(TrainOperatorLines _operator, String currentInput) {
 | 
			
		||||
    if (currentInput.isNotEmpty) {
 | 
			
		||||
      final filteredLines = _operator.trains
 | 
			
		||||
        .where((elem) => elem.number.contains(currentInput))
 | 
			
		||||
        .toList();
 | 
			
		||||
 | 
			
		||||
      filteredLines.sort((a, b) {
 | 
			
		||||
        final inputAsRegExp = RegExp(currentInput);
 | 
			
		||||
 | 
			
		||||
        final matchOnA = inputAsRegExp.firstMatch(a.number)!;
 | 
			
		||||
        final matchOnB = inputAsRegExp.firstMatch(b.number)!;
 | 
			
		||||
 | 
			
		||||
        if (matchOnA.start != matchOnB.start) return matchOnA.start - matchOnB.start;
 | 
			
		||||
 | 
			
		||||
        if (a.number.length != b.number.length) return a.number.length - b.number.length;
 | 
			
		||||
 | 
			
		||||
        return a.number.compareTo(b.number);
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      return filteredLines;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      return _operator.trains;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class OperatorAutocompleteSliver extends ConsumerWidget {
 | 
			
		||||
class OperatorAutocompleteSliver extends StatelessWidget {
 | 
			
		||||
  final UiDesign? uiDesign;
 | 
			
		||||
  final String operatorName;
 | 
			
		||||
  final List<TrainsResult> trains;
 | 
			
		||||
  final void Function(String) onTrainSelected;
 | 
			
		||||
  final List<TrainOperatorTrainDescription> trains;
 | 
			
		||||
  final void Function(int) onTrainSelected;
 | 
			
		||||
 | 
			
		||||
  const OperatorAutocompleteSliver({ 
 | 
			
		||||
    super.key, 
 | 
			
		||||
    required this.operatorName, 
 | 
			
		||||
    required this.trains, 
 | 
			
		||||
    required this.onTrainSelected, 
 | 
			
		||||
  });
 | 
			
		||||
  const OperatorAutocompleteSliver({ Key? key, required this.uiDesign, required this.operatorName, required this.trains, required this.onTrainSelected }) : super(key: key);
 | 
			
		||||
 | 
			
		||||
  Widget mapTrainToItem(TrainsResult train, UiDesign uiDesign) {
 | 
			
		||||
  Widget mapTrainToItem(TrainOperatorTrainDescription train) {
 | 
			
		||||
    final uiDesign = this.uiDesign ?? defaultUiDesign;
 | 
			
		||||
    switch (uiDesign) {
 | 
			
		||||
      case UiDesign.MATERIAL:
 | 
			
		||||
        return OperatorAutocompleteTileMaterial(
 | 
			
		||||
| 
						 | 
				
			
			@ -107,20 +168,13 @@ class OperatorAutocompleteSliver extends ConsumerWidget {
 | 
			
		|||
          operatorName: operatorName,
 | 
			
		||||
          train: train,
 | 
			
		||||
        );
 | 
			
		||||
      case UiDesign.FLUENT:
 | 
			
		||||
        return OperatorAutocompleteTileFluent(
 | 
			
		||||
          onTrainSelected: onTrainSelected,
 | 
			
		||||
          operatorName: operatorName,
 | 
			
		||||
          train: train,
 | 
			
		||||
        );
 | 
			
		||||
      default:
 | 
			
		||||
        throw UnmatchedUiDesignException(uiDesign);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context, WidgetRef ref) {
 | 
			
		||||
    final uiDesign = ref.watch(uiDesignProvider);
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    if (trains.isEmpty) {
 | 
			
		||||
      return SliverToBoxAdapter(child: Container(),);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -128,14 +182,14 @@ class OperatorAutocompleteSliver extends ConsumerWidget {
 | 
			
		|||
    return SliverPrototypeExtentList(
 | 
			
		||||
      prototypeItem: Column(
 | 
			
		||||
        children: <Widget>[
 | 
			
		||||
          mapTrainToItem(const TrainsResult(company: 'Company', number: '123', rank: 'R'), uiDesign),
 | 
			
		||||
          mapTrainToItem(TrainOperatorTrainDescription()),
 | 
			
		||||
        ],
 | 
			
		||||
      ),
 | 
			
		||||
      delegate: SliverChildBuilderDelegate(
 | 
			
		||||
        (context, index) {
 | 
			
		||||
          return Column(
 | 
			
		||||
            children: <Widget>[
 | 
			
		||||
              mapTrainToItem(trains[index], uiDesign),
 | 
			
		||||
              mapTrainToItem(trains[index]),
 | 
			
		||||
            ],
 | 
			
		||||
          );
 | 
			
		||||
        },
 | 
			
		||||
| 
						 | 
				
			
			@ -148,8 +202,8 @@ class OperatorAutocompleteSliver extends ConsumerWidget {
 | 
			
		|||
 | 
			
		||||
abstract class OperatorAutocompleteTile extends StatelessWidget {
 | 
			
		||||
  final String operatorName;
 | 
			
		||||
  final TrainsResult train;
 | 
			
		||||
  final void Function(String) onTrainSelected;
 | 
			
		||||
  final TrainOperatorTrainDescription train;
 | 
			
		||||
  final void Function(int) onTrainSelected;
 | 
			
		||||
 | 
			
		||||
  const OperatorAutocompleteTile({ Key? key, required this.onTrainSelected, required this.operatorName, required this.train }) : super(key: key);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,46 +1,40 @@
 | 
			
		|||
import 'package:flutter/cupertino.dart';
 | 
			
		||||
import 'package:info_tren/components/cupertino_divider.dart';
 | 
			
		||||
import 'package:flutter/material.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 SelectTrainSuggestionsCupertino extends SelectTrainSuggestionsShared {
 | 
			
		||||
  const SelectTrainSuggestionsCupertino({
 | 
			
		||||
    super.key, 
 | 
			
		||||
    required super.choices, 
 | 
			
		||||
    required super.onTrainSelected, 
 | 
			
		||||
    super.currentInput,
 | 
			
		||||
  });
 | 
			
		||||
import 'package:info_tren/models/train_operator_lines.dart';
 | 
			
		||||
 | 
			
		||||
class SelectTrainSuggestionsStateCupertino extends SelectTrainSuggestionsState {
 | 
			
		||||
  @override
 | 
			
		||||
  Widget getUseCurrentInputWidget(String currentInput, void Function(String) onTrainSelected) {
 | 
			
		||||
  Widget getUseCurrentInputWidget(int currentInput, void Function(int p1) onTrainSelected) {
 | 
			
		||||
    return Column(
 | 
			
		||||
      mainAxisSize: MainAxisSize.min,
 | 
			
		||||
      children: <Widget>[
 | 
			
		||||
        Padding(
 | 
			
		||||
          padding: const EdgeInsets.all(0),
 | 
			
		||||
          child: Column(
 | 
			
		||||
            mainAxisSize: MainAxisSize.min,
 | 
			
		||||
            children: <Widget>[
 | 
			
		||||
              CupertinoButton(
 | 
			
		||||
                child: Text(getUseCurrentInputWidgetText(currentInput)),
 | 
			
		||||
                onPressed: () => onTrainSelected(currentInput),
 | 
			
		||||
              ),
 | 
			
		||||
            ],
 | 
			
		||||
          )
 | 
			
		||||
        GestureDetector(
 | 
			
		||||
          onTap: () {
 | 
			
		||||
            onTrainSelected(currentInput);
 | 
			
		||||
          },
 | 
			
		||||
          child: Padding(
 | 
			
		||||
            padding: const EdgeInsets.all(8),
 | 
			
		||||
            child: Column(
 | 
			
		||||
              mainAxisSize: MainAxisSize.min,
 | 
			
		||||
              children: <Widget>[
 | 
			
		||||
                Text(getUseCurrentInputWidgetText(currentInput)),
 | 
			
		||||
              ],
 | 
			
		||||
            )
 | 
			
		||||
          ),
 | 
			
		||||
        ),
 | 
			
		||||
        const CupertinoDivider(),
 | 
			
		||||
        Divider(),
 | 
			
		||||
      ],
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class OperatorAutocompleteTileCupertino extends OperatorAutocompleteTile {
 | 
			
		||||
  const OperatorAutocompleteTileCupertino({
 | 
			
		||||
  OperatorAutocompleteTileCupertino({
 | 
			
		||||
    Key? key, 
 | 
			
		||||
    required String operatorName, 
 | 
			
		||||
    required void Function(String) onTrainSelected, 
 | 
			
		||||
    required TrainsResult train
 | 
			
		||||
    required void Function(int) onTrainSelected, 
 | 
			
		||||
    required TrainOperatorTrainDescription train
 | 
			
		||||
  }): super(
 | 
			
		||||
    onTrainSelected: onTrainSelected,
 | 
			
		||||
    operatorName: operatorName,
 | 
			
		||||
| 
						 | 
				
			
			@ -50,37 +44,31 @@ class OperatorAutocompleteTileCupertino extends OperatorAutocompleteTile {
 | 
			
		|||
 | 
			
		||||
  @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: CupertinoTheme.of(context).textTheme.textStyle.copyWith(fontSize: 10, fontWeight: FontWeight.w200),
 | 
			
		||||
                    textAlign: TextAlign.left,
 | 
			
		||||
                  ),
 | 
			
		||||
                  Text.rich(
 | 
			
		||||
                    trainIdSpan(rank: train.rank, number: train.number),
 | 
			
		||||
                    textAlign: TextAlign.left,
 | 
			
		||||
                  ),
 | 
			
		||||
                ],
 | 
			
		||||
    return GestureDetector(
 | 
			
		||||
      onTap: () {
 | 
			
		||||
        onTrainSelected(train.internalNumber);
 | 
			
		||||
      },
 | 
			
		||||
      child: Padding(
 | 
			
		||||
        padding: const EdgeInsets.fromLTRB(16, 2, 16, 2),
 | 
			
		||||
        child: SizedBox(
 | 
			
		||||
          width: double.infinity,
 | 
			
		||||
          child: Column(
 | 
			
		||||
            mainAxisSize: MainAxisSize.min,
 | 
			
		||||
            crossAxisAlignment: CrossAxisAlignment.stretch,
 | 
			
		||||
            children: <Widget>[
 | 
			
		||||
              Text(
 | 
			
		||||
                operatorName,
 | 
			
		||||
                style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(fontSize: 10, fontWeight: FontWeight.w200),
 | 
			
		||||
                textAlign: TextAlign.left,
 | 
			
		||||
              ),
 | 
			
		||||
            ),
 | 
			
		||||
              Text(
 | 
			
		||||
                "${train.rang} ${train.number}",
 | 
			
		||||
                textAlign: TextAlign.left,
 | 
			
		||||
              ),
 | 
			
		||||
            ],
 | 
			
		||||
          ),
 | 
			
		||||
        ),
 | 
			
		||||
        const CupertinoDivider(),
 | 
			
		||||
      ],
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,85 +0,0 @@
 | 
			
		|||
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(),
 | 
			
		||||
      ],
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,18 +1,10 @@
 | 
			
		|||
import 'package:flutter/material.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 SelectTrainSuggestionsMaterial extends SelectTrainSuggestionsShared {
 | 
			
		||||
  const SelectTrainSuggestionsMaterial({
 | 
			
		||||
    super.key, 
 | 
			
		||||
    required super.choices, 
 | 
			
		||||
    required super.onTrainSelected, 
 | 
			
		||||
    super.currentInput,
 | 
			
		||||
  });
 | 
			
		||||
import 'package:info_tren/models/train_operator_lines.dart';
 | 
			
		||||
 | 
			
		||||
class SelectTrainSuggestionsStateMaterial extends SelectTrainSuggestionsState {
 | 
			
		||||
  @override
 | 
			
		||||
  Widget getUseCurrentInputWidget(String currentInput, void Function(String) onTrainSelected) {
 | 
			
		||||
  Widget getUseCurrentInputWidget(int currentInput, void Function(int) onTrainSelected) {
 | 
			
		||||
    return Column(
 | 
			
		||||
      mainAxisSize: MainAxisSize.min,
 | 
			
		||||
      children: <Widget>[
 | 
			
		||||
| 
						 | 
				
			
			@ -22,18 +14,18 @@ class SelectTrainSuggestionsMaterial extends SelectTrainSuggestionsShared {
 | 
			
		|||
            onTrainSelected(currentInput);
 | 
			
		||||
          },
 | 
			
		||||
        ),
 | 
			
		||||
        const Divider(),
 | 
			
		||||
        Divider(),
 | 
			
		||||
      ],
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class OperatorAutocompleteTileMaterial extends OperatorAutocompleteTile {
 | 
			
		||||
  const OperatorAutocompleteTileMaterial({
 | 
			
		||||
  OperatorAutocompleteTileMaterial({
 | 
			
		||||
    Key? key, 
 | 
			
		||||
    required String operatorName, 
 | 
			
		||||
    required void Function(String) onTrainSelected, 
 | 
			
		||||
    required TrainsResult train
 | 
			
		||||
    required void Function(int) onTrainSelected, 
 | 
			
		||||
    required TrainOperatorTrainDescription train
 | 
			
		||||
  }): super(
 | 
			
		||||
    onTrainSelected: onTrainSelected,
 | 
			
		||||
    operatorName: operatorName,
 | 
			
		||||
| 
						 | 
				
			
			@ -45,10 +37,10 @@ class OperatorAutocompleteTileMaterial extends OperatorAutocompleteTile {
 | 
			
		|||
  Widget build(BuildContext context) {
 | 
			
		||||
    return ListTile(
 | 
			
		||||
      dense: true,
 | 
			
		||||
      title: Text.rich(trainIdSpan(rank: train.rank, number: train.number)),
 | 
			
		||||
      title: Text("${train.rang} ${train.number}"),
 | 
			
		||||
      subtitle: Text(operatorName),
 | 
			
		||||
      onTap: () {
 | 
			
		||||
        onTrainSelected(train.number);
 | 
			
		||||
        onTrainSelected(train.internalNumber);
 | 
			
		||||
      },
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,11 +5,10 @@ class SlimAppBar extends StatelessWidget {
 | 
			
		|||
  final double size;
 | 
			
		||||
  // final Function onBackTap;
 | 
			
		||||
 | 
			
		||||
  const SlimAppBar({
 | 
			
		||||
  SlimAppBar({
 | 
			
		||||
    required this.title, 
 | 
			
		||||
    this.size = 24,
 | 
			
		||||
    // this.onBackTap,
 | 
			
		||||
    super.key,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
| 
						 | 
				
			
			@ -19,7 +18,7 @@ class SlimAppBar extends StatelessWidget {
 | 
			
		|||
      height: size,
 | 
			
		||||
      child: Container(
 | 
			
		||||
        color: 
 | 
			
		||||
          Theme.of(context).appBarTheme.backgroundColor ??
 | 
			
		||||
          Theme.of(context).appBarTheme.color ??
 | 
			
		||||
          Theme.of(context).primaryColor,
 | 
			
		||||
        child: InkWell(
 | 
			
		||||
          onTap: (ModalRoute.of(context)?.canPop ?? false) 
 | 
			
		||||
| 
						 | 
				
			
			@ -29,11 +28,11 @@ class SlimAppBar extends StatelessWidget {
 | 
			
		|||
            mainAxisSize: MainAxisSize.max,
 | 
			
		||||
            crossAxisAlignment: CrossAxisAlignment.stretch,
 | 
			
		||||
            children: <Widget>[
 | 
			
		||||
              SizedBox(
 | 
			
		||||
              Container(
 | 
			
		||||
                height: size,
 | 
			
		||||
                width: size,
 | 
			
		||||
                child: (ModalRoute.of(context)?.canPop ?? false)
 | 
			
		||||
                  ? const BackButtonIcon()
 | 
			
		||||
                  ? BackButtonIcon()
 | 
			
		||||
                  : null,
 | 
			
		||||
              ),
 | 
			
		||||
              Expanded(
 | 
			
		||||
| 
						 | 
				
			
			@ -44,13 +43,13 @@ class SlimAppBar extends StatelessWidget {
 | 
			
		|||
                      title,
 | 
			
		||||
                      textAlign: TextAlign.center,
 | 
			
		||||
                      style: 
 | 
			
		||||
                        Theme.of(context).textTheme.titleSmall?.copyWith(color: Theme.of(context).textTheme.titleLarge?.color) ??
 | 
			
		||||
                        Theme.of(context).textTheme.bodySmall?.copyWith(color: Theme.of(context).textTheme.bodyMedium?.color),
 | 
			
		||||
                        Theme.of(context).appBarTheme.textTheme?.caption?.copyWith(color: Theme.of(context).appBarTheme.textTheme?.bodyText2?.color) ??
 | 
			
		||||
                        Theme.of(context).textTheme.caption?.copyWith(color: Theme.of(context).textTheme.bodyText2?.color),
 | 
			
		||||
                    ),
 | 
			
		||||
                  ),
 | 
			
		||||
                ),
 | 
			
		||||
              ),
 | 
			
		||||
              SizedBox(
 | 
			
		||||
              Container(
 | 
			
		||||
                height: size,
 | 
			
		||||
                width: size,
 | 
			
		||||
              ),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,38 +0,0 @@
 | 
			
		|||
import 'package:flutter/material.dart';
 | 
			
		||||
 | 
			
		||||
class SliverPersistentHeaderPadding extends StatelessWidget {
 | 
			
		||||
  final double maxHeight;
 | 
			
		||||
 | 
			
		||||
  const SliverPersistentHeaderPadding({required this.maxHeight, super.key,});
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    return SliverPersistentHeader(
 | 
			
		||||
      delegate: _SliverPersistentHeaderPaddingDelegate(maxHeight: maxHeight,),
 | 
			
		||||
      floating: false,
 | 
			
		||||
      pinned: false,
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class _SliverPersistentHeaderPaddingDelegate extends SliverPersistentHeaderDelegate {
 | 
			
		||||
  final double maxHeight;
 | 
			
		||||
 | 
			
		||||
  const _SliverPersistentHeaderPaddingDelegate({required this.maxHeight});
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
 | 
			
		||||
    return Container();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  double get maxExtent => maxHeight;
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  double get minExtent => 0;
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) {
 | 
			
		||||
    return oldDelegate.maxExtent != maxExtent;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,39 +0,0 @@
 | 
			
		|||
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,
 | 
			
		||||
);
 | 
			
		||||
							
								
								
									
										209
									
								
								lib/main.dart
									
										
									
									
									
								
							
							
						
						
									
										209
									
								
								lib/main.dart
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,190 +1,73 @@
 | 
			
		|||
import 'dart:io';
 | 
			
		||||
import 'dart:io' show Platform;
 | 
			
		||||
 | 
			
		||||
import 'package:dynamic_color/dynamic_color.dart';
 | 
			
		||||
import 'package:fluent_ui/fluent_ui.dart' as f;
 | 
			
		||||
import 'package:flutter/cupertino.dart' as c;
 | 
			
		||||
import 'package:flutter/gestures.dart';
 | 
			
		||||
import 'package:flutter/material.dart' as m;
 | 
			
		||||
import 'package:flutter/services.dart';
 | 
			
		||||
import 'package:flutter/widgets.dart';
 | 
			
		||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
			
		||||
import 'package:info_tren/models.dart';
 | 
			
		||||
import 'package:info_tren/pages/about/about_page.dart';
 | 
			
		||||
import 'package:flutter/cupertino.dart';
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
// import 'package:flutter_redux/flutter_redux.dart';
 | 
			
		||||
import 'package:info_tren/models/ui_design.dart';
 | 
			
		||||
import 'package:info_tren/pages/main/main_page.dart';
 | 
			
		||||
import 'package:info_tren/pages/settings/setings_page.dart';
 | 
			
		||||
import 'package:info_tren/pages/station_arrdep_page/select_station/select_station.dart';
 | 
			
		||||
import 'package:info_tren/pages/station_arrdep_page/view_station/view_station.dart';
 | 
			
		||||
import 'package:info_tren/pages/train_info_page/view_train/train_info.dart';
 | 
			
		||||
import 'package:info_tren/pages/train_info_page/select_train/select_train.dart';
 | 
			
		||||
import 'package:info_tren/providers.dart';
 | 
			
		||||
import 'package:shared_preferences/shared_preferences.dart';
 | 
			
		||||
import 'package:timezone/data/latest.dart';
 | 
			
		||||
 | 
			
		||||
void main() async {
 | 
			
		||||
  WidgetsFlutterBinding.ensureInitialized();
 | 
			
		||||
  initializeTimeZones();
 | 
			
		||||
  final sharedPreferences = await SharedPreferences.getInstance();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void main() {
 | 
			
		||||
  // final store = createStore();
 | 
			
		||||
  // runApp(
 | 
			
		||||
  //   StoreProvider(
 | 
			
		||||
  //     store: store,
 | 
			
		||||
  //     child: StartPoint(),
 | 
			
		||||
  //   )
 | 
			
		||||
  // );
 | 
			
		||||
  runApp(
 | 
			
		||||
    ProviderScope(
 | 
			
		||||
      overrides: [
 | 
			
		||||
        sharedPreferencesProvider.overrideWithValue(sharedPreferences),
 | 
			
		||||
      ],
 | 
			
		||||
      child: const StartPoint(),
 | 
			
		||||
    ),
 | 
			
		||||
    StartPoint(),
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Map<String, WidgetBuilder> get routes => {
 | 
			
		||||
Map<String, WidgetBuilder> routesByUiDesign(UiDesign uiDesign) => {
 | 
			
		||||
  Navigator.defaultRouteName: (context) {
 | 
			
		||||
    return const MainPage();
 | 
			
		||||
  },
 | 
			
		||||
  AboutPage.routeName: (context) {
 | 
			
		||||
    return const AboutPage();
 | 
			
		||||
  },
 | 
			
		||||
  SettingsPage.routeName: (context) {
 | 
			
		||||
    return const SettingsPage();
 | 
			
		||||
    return MainPage(uiDesign: uiDesign,);
 | 
			
		||||
  },
 | 
			
		||||
  SelectTrainPage.routeName: (context) {
 | 
			
		||||
    return const SelectTrainPage();
 | 
			
		||||
    return SelectTrainPage(uiDesign: uiDesign);
 | 
			
		||||
  },
 | 
			
		||||
  TrainInfo.routeName: (context) {
 | 
			
		||||
    final args = ModalRoute.of(context)!.settings.arguments as TrainInfoArguments;
 | 
			
		||||
    return ProviderScope(
 | 
			
		||||
      overrides: [
 | 
			
		||||
        trainInfoArgumentsProvider.overrideWithValue(args),
 | 
			
		||||
      ],
 | 
			
		||||
      child: const TrainInfo(),
 | 
			
		||||
    );
 | 
			
		||||
  },
 | 
			
		||||
  SelectStationPage.routeName: (context) {
 | 
			
		||||
    return const SelectStationPage();
 | 
			
		||||
  },
 | 
			
		||||
  ViewStationPage.routeName: (context) {
 | 
			
		||||
    final args = ModalRoute.of(context)!.settings.arguments as ViewStationArguments;
 | 
			
		||||
    return ProviderScope(
 | 
			
		||||
      overrides: [
 | 
			
		||||
        viewStationArgumentsProvider.overrideWithValue(args),
 | 
			
		||||
      ],
 | 
			
		||||
      child: const ViewStationPage(),
 | 
			
		||||
    return TrainInfo(
 | 
			
		||||
      trainNumber: ModalRoute.of(context)!.settings.arguments as int,
 | 
			
		||||
    );
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class DragFluentScrollBevahior extends f.FluentScrollBehavior {
 | 
			
		||||
  const DragFluentScrollBevahior();
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Set<PointerDeviceKind> get dragDevices => {
 | 
			
		||||
    PointerDeviceKind.mouse,
 | 
			
		||||
    PointerDeviceKind.touch,
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class DragCupertinoScrollBevahior extends c.CupertinoScrollBehavior {
 | 
			
		||||
  const DragCupertinoScrollBevahior();
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Set<PointerDeviceKind> get dragDevices => {
 | 
			
		||||
    PointerDeviceKind.mouse,
 | 
			
		||||
    PointerDeviceKind.touch,
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class DragMaterialScrollBevahior extends m.MaterialScrollBehavior {
 | 
			
		||||
  const DragMaterialScrollBevahior();
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Set<PointerDeviceKind> get dragDevices => {
 | 
			
		||||
    PointerDeviceKind.mouse,
 | 
			
		||||
    PointerDeviceKind.touch,
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class StartPoint extends ConsumerWidget {
 | 
			
		||||
class StartPoint extends StatelessWidget {
 | 
			
		||||
  final String appTitle = 'Info Tren';
 | 
			
		||||
 | 
			
		||||
  const StartPoint({super.key});
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context, WidgetRef ref) {
 | 
			
		||||
    final uiDesign = ref.watch(uiDesignProvider);
 | 
			
		||||
    if (uiDesign == UiDesign.CUPERTINO) {
 | 
			
		||||
      return DynamicColorBuilder(
 | 
			
		||||
        builder: (lightScheme, darkScheme) {
 | 
			
		||||
          return AnnotatedRegion(
 | 
			
		||||
            value: const SystemUiOverlayStyle(
 | 
			
		||||
              statusBarBrightness: c.Brightness.dark,
 | 
			
		||||
            ),
 | 
			
		||||
            child: c.CupertinoApp(
 | 
			
		||||
              title: appTitle,
 | 
			
		||||
              theme: c.CupertinoThemeData(
 | 
			
		||||
                primaryColor: darkScheme?.primary ?? m.Colors.blue.shade600,
 | 
			
		||||
                brightness: c.Brightness.dark,
 | 
			
		||||
                // textTheme: CupertinoTextThemeData(
 | 
			
		||||
                //   textStyle: TextStyle(
 | 
			
		||||
                //     fontFamily: 'Atkinson Hyperlegible',
 | 
			
		||||
                //   ),
 | 
			
		||||
                // ),
 | 
			
		||||
              ),
 | 
			
		||||
              scrollBehavior: Platform.isLinux ? const DragCupertinoScrollBevahior() : null,
 | 
			
		||||
              routes: routes,
 | 
			
		||||
            ),
 | 
			
		||||
          );
 | 
			
		||||
        }
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
    else if (uiDesign == UiDesign.FLUENT) {
 | 
			
		||||
      return DynamicColorBuilder(
 | 
			
		||||
        builder: (lightScheme, darkScheme) {
 | 
			
		||||
          return f.FluentApp(
 | 
			
		||||
            title: appTitle,
 | 
			
		||||
            theme: f.FluentThemeData(
 | 
			
		||||
              brightness: f.Brightness.light,
 | 
			
		||||
              accentColor: lightScheme != null ? f.AccentColor.swatch({
 | 
			
		||||
                'normal': lightScheme.primary,
 | 
			
		||||
              }) : f.Colors.blue,
 | 
			
		||||
            ),
 | 
			
		||||
            darkTheme: f.FluentThemeData(
 | 
			
		||||
              brightness: f.Brightness.dark,
 | 
			
		||||
              accentColor: darkScheme != null ? f.AccentColor.swatch({
 | 
			
		||||
                'normal': darkScheme.primary,
 | 
			
		||||
              }) : f.Colors.blue,
 | 
			
		||||
            ),
 | 
			
		||||
            routes: routes,
 | 
			
		||||
            scrollBehavior: Platform.isLinux ? const DragFluentScrollBevahior() : const f.FluentScrollBehavior(),
 | 
			
		||||
          );
 | 
			
		||||
        }
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    if (Platform.isIOS) {
 | 
			
		||||
      return CupertinoApp(
 | 
			
		||||
        title: appTitle,
 | 
			
		||||
        theme: CupertinoThemeData(
 | 
			
		||||
          primaryColor: Colors.blue.shade600,
 | 
			
		||||
          brightness: Brightness.dark,
 | 
			
		||||
          // textTheme: CupertinoTextThemeData(
 | 
			
		||||
          //   textStyle: TextStyle(
 | 
			
		||||
          //     fontFamily: 'Atkinson Hyperlegible',
 | 
			
		||||
          //   ),
 | 
			
		||||
          // ),
 | 
			
		||||
        ),
 | 
			
		||||
        routes: routesByUiDesign(UiDesign.CUPERTINO),
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      return DynamicColorBuilder(
 | 
			
		||||
        builder: (lightScheme, darkScheme) {
 | 
			
		||||
          lightScheme ??= m.ColorScheme.fromSwatch(
 | 
			
		||||
            brightness: m.Brightness.light,
 | 
			
		||||
            primarySwatch: m.Colors.blue,
 | 
			
		||||
          );
 | 
			
		||||
          darkScheme ??= m.ColorScheme.fromSwatch(
 | 
			
		||||
            brightness: m.Brightness.dark,
 | 
			
		||||
            primarySwatch: m.Colors.blue,
 | 
			
		||||
          );
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
          return m.MaterialApp(
 | 
			
		||||
            title: appTitle,
 | 
			
		||||
            theme: m.ThemeData(
 | 
			
		||||
              colorScheme: lightScheme,
 | 
			
		||||
              useMaterial3: true,
 | 
			
		||||
              // fontFamily: 'Atkinson Hyperlegible',
 | 
			
		||||
            ),
 | 
			
		||||
            darkTheme: m.ThemeData(
 | 
			
		||||
              colorScheme: darkScheme,
 | 
			
		||||
              useMaterial3: true,
 | 
			
		||||
              // fontFamily: 'Atkinson Hyperlegible',
 | 
			
		||||
            ),
 | 
			
		||||
            scrollBehavior: Platform.isLinux ? const DragMaterialScrollBevahior() : null,
 | 
			
		||||
            routes: routes,
 | 
			
		||||
          );
 | 
			
		||||
        }
 | 
			
		||||
      return MaterialApp(
 | 
			
		||||
        title: appTitle,
 | 
			
		||||
        theme: ThemeData(
 | 
			
		||||
          primarySwatch: Colors.blue,
 | 
			
		||||
          brightness: Brightness.dark,
 | 
			
		||||
          primaryColor: Colors.blue.shade600,
 | 
			
		||||
          accentColor: Colors.blue.shade700,
 | 
			
		||||
          // fontFamily: 'Atkinson Hyperlegible',
 | 
			
		||||
        ),
 | 
			
		||||
        routes: routesByUiDesign(UiDesign.MATERIAL),
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,14 +0,0 @@
 | 
			
		|||
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;
 | 
			
		||||
| 
						 | 
				
			
			@ -1,83 +0,0 @@
 | 
			
		|||
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);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,18 +0,0 @@
 | 
			
		|||
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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1,241 +0,0 @@
 | 
			
		|||
// 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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,23 +0,0 @@
 | 
			
		|||
// 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,17 +0,0 @@
 | 
			
		|||
import 'package:freezed_annotation/freezed_annotation.dart';
 | 
			
		||||
import 'package:info_tren/models.dart';
 | 
			
		||||
 | 
			
		||||
part 'station_data.g.dart';
 | 
			
		||||
part 'station_data.freezed.dart';
 | 
			
		||||
 | 
			
		||||
@freezed
 | 
			
		||||
class StationData with _$StationData {
 | 
			
		||||
  const factory StationData({
 | 
			
		||||
    required String date, 
 | 
			
		||||
    required String stationName, 
 | 
			
		||||
    required List<StationArrDep>? arrivals, 
 | 
			
		||||
    required List<StationArrDep>? departures,
 | 
			
		||||
  }) = _StationData;
 | 
			
		||||
 | 
			
		||||
  factory StationData.fromJson(Map<String, dynamic> json) => _$StationDataFromJson(json);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,239 +0,0 @@
 | 
			
		|||
// 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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,27 +0,0 @@
 | 
			
		|||
// GENERATED CODE - DO NOT MODIFY BY HAND
 | 
			
		||||
 | 
			
		||||
part of 'station_data.dart';
 | 
			
		||||
 | 
			
		||||
// **************************************************************************
 | 
			
		||||
// JsonSerializableGenerator
 | 
			
		||||
// **************************************************************************
 | 
			
		||||
 | 
			
		||||
_$_StationData _$$_StationDataFromJson(Map<String, dynamic> json) =>
 | 
			
		||||
    _$_StationData(
 | 
			
		||||
      date: json['date'] as String,
 | 
			
		||||
      stationName: json['stationName'] as String,
 | 
			
		||||
      arrivals: (json['arrivals'] as List<dynamic>?)
 | 
			
		||||
          ?.map((e) => StationArrDep.fromJson(e as Map<String, dynamic>))
 | 
			
		||||
          .toList(),
 | 
			
		||||
      departures: (json['departures'] as List<dynamic>?)
 | 
			
		||||
          ?.map((e) => StationArrDep.fromJson(e as Map<String, dynamic>))
 | 
			
		||||
          .toList(),
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
Map<String, dynamic> _$$_StationDataToJson(_$_StationData instance) =>
 | 
			
		||||
    <String, dynamic>{
 | 
			
		||||
      'date': instance.date,
 | 
			
		||||
      'stationName': instance.stationName,
 | 
			
		||||
      'arrivals': instance.arrivals,
 | 
			
		||||
      'departures': instance.departures,
 | 
			
		||||
    };
 | 
			
		||||
| 
						 | 
				
			
			@ -1,17 +0,0 @@
 | 
			
		|||
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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1,210 +0,0 @@
 | 
			
		|||
// 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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,23 +0,0 @@
 | 
			
		|||
// 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,
 | 
			
		||||
    };
 | 
			
		||||
| 
						 | 
				
			
			@ -1,19 +0,0 @@
 | 
			
		|||
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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1,268 +0,0 @@
 | 
			
		|||
// 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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,28 +0,0 @@
 | 
			
		|||
// 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 +0,0 @@
 | 
			
		|||
import 'package:freezed_annotation/freezed_annotation.dart';
 | 
			
		||||
 | 
			
		||||
part 'stations_result.g.dart';
 | 
			
		||||
part 'stations_result.freezed.dart';
 | 
			
		||||
 | 
			
		||||
@freezed
 | 
			
		||||
class StationsResult with _$StationsResult {
 | 
			
		||||
  const factory StationsResult({
 | 
			
		||||
    required String name, 
 | 
			
		||||
    List<String>? stoppedAtBy,
 | 
			
		||||
  }) = _StationsResult;
 | 
			
		||||
 | 
			
		||||
  factory StationsResult.fromJson(Map<String, dynamic> json) => _$StationsResultFromJson(json);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,179 +0,0 @@
 | 
			
		|||
// 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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,21 +0,0 @@
 | 
			
		|||
// GENERATED CODE - DO NOT MODIFY BY HAND
 | 
			
		||||
 | 
			
		||||
part of 'stations_result.dart';
 | 
			
		||||
 | 
			
		||||
// **************************************************************************
 | 
			
		||||
// JsonSerializableGenerator
 | 
			
		||||
// **************************************************************************
 | 
			
		||||
 | 
			
		||||
_$_StationsResult _$$_StationsResultFromJson(Map<String, dynamic> json) =>
 | 
			
		||||
    _$_StationsResult(
 | 
			
		||||
      name: json['name'] as String,
 | 
			
		||||
      stoppedAtBy: (json['stoppedAtBy'] as List<dynamic>?)
 | 
			
		||||
          ?.map((e) => e as String)
 | 
			
		||||
          .toList(),
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
Map<String, dynamic> _$$_StationsResultToJson(_$_StationsResult instance) =>
 | 
			
		||||
    <String, dynamic>{
 | 
			
		||||
      'name': instance.name,
 | 
			
		||||
      'stoppedAtBy': instance.stoppedAtBy,
 | 
			
		||||
    };
 | 
			
		||||
| 
						 | 
				
			
			@ -4,118 +4,181 @@
 | 
			
		|||
 | 
			
		||||
import 'dart:convert';
 | 
			
		||||
 | 
			
		||||
import 'package:freezed_annotation/freezed_annotation.dart';
 | 
			
		||||
 | 
			
		||||
part 'train_data.freezed.dart';
 | 
			
		||||
part 'train_data.g.dart';
 | 
			
		||||
 | 
			
		||||
TrainData trainDataFromJson(String str) => TrainData.fromJson(json.decode(str));
 | 
			
		||||
 | 
			
		||||
String trainDataToJson(TrainData data) => json.encode(data.toJson());
 | 
			
		||||
 | 
			
		||||
/// Results of scrapping InfoFer website for train info
 | 
			
		||||
@freezed
 | 
			
		||||
class TrainData with _$TrainData {
 | 
			
		||||
  const TrainData._();
 | 
			
		||||
  
 | 
			
		||||
  const factory TrainData({
 | 
			
		||||
    required String rank,
 | 
			
		||||
    required String number,
 | 
			
		||||
    required String date,
 | 
			
		||||
    required String operator,
 | 
			
		||||
    required List<TrainDataGroup> groups,
 | 
			
		||||
  }) = _TrainData;
 | 
			
		||||
class TrainData {
 | 
			
		||||
  TrainData({
 | 
			
		||||
    required this.date,
 | 
			
		||||
    required this.number,
 | 
			
		||||
    required this.operator,
 | 
			
		||||
    required this.rank,
 | 
			
		||||
    required this.route,
 | 
			
		||||
    required this.stations,
 | 
			
		||||
    this.status,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  factory TrainData.fromJson(Map<String, dynamic> json) => _$TrainDataFromJson(json);
 | 
			
		||||
  
 | 
			
		||||
  TrainDataGroup get idealGroup {
 | 
			
		||||
    var result = groups.first;
 | 
			
		||||
    
 | 
			
		||||
    for (final group in groups) {
 | 
			
		||||
      if (result.stations.map((s) => s.linkName).toSet().difference(group.stations.map((s) => s.linkName).toSet()).isEmpty) {
 | 
			
		||||
        result = group;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  final String date;
 | 
			
		||||
  final String number;
 | 
			
		||||
  final String operator;
 | 
			
		||||
  final String rank;
 | 
			
		||||
  final Route route;
 | 
			
		||||
  final List<Station> stations;
 | 
			
		||||
  final TrainDataStatus? status;
 | 
			
		||||
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  List<TrainDataStation> get stations => idealGroup.stations;
 | 
			
		||||
  TrainDataRoute get route => idealGroup.route;
 | 
			
		||||
  TrainDataStatus? get status => idealGroup.status;
 | 
			
		||||
}
 | 
			
		||||
  factory TrainData.fromJson(Map<String, dynamic> json) => TrainData(
 | 
			
		||||
        date: json["date"],
 | 
			
		||||
        number: json["number"],
 | 
			
		||||
        operator: json["operator"],
 | 
			
		||||
        rank: json["rank"],
 | 
			
		||||
        route: Route.fromJson(json["route"]),
 | 
			
		||||
        stations: List<Station>.from(
 | 
			
		||||
            json["stations"].map((x) => Station.fromJson(x))),
 | 
			
		||||
        status: json["status"] == null
 | 
			
		||||
            ? null
 | 
			
		||||
            : TrainDataStatus.fromJson(json["status"]),
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
@freezed
 | 
			
		||||
class TrainDataGroup with _$TrainDataGroup {
 | 
			
		||||
  const factory TrainDataGroup({
 | 
			
		||||
    required TrainDataRoute route,
 | 
			
		||||
    required List<TrainDataStation> stations,
 | 
			
		||||
    TrainDataStatus? status,
 | 
			
		||||
  }) = _TrainDataGroup;
 | 
			
		||||
  
 | 
			
		||||
  factory TrainDataGroup.fromJson(Map<String, dynamic> json) => _$TrainDataGroupFromJson(json);
 | 
			
		||||
  Map<String, dynamic> toJson() => {
 | 
			
		||||
        "date": date,
 | 
			
		||||
        "number": number,
 | 
			
		||||
        "operator": operator,
 | 
			
		||||
        "rank": rank,
 | 
			
		||||
        "route": route.toJson(),
 | 
			
		||||
        "stations": List<dynamic>.from(stations.map((x) => x.toJson())),
 | 
			
		||||
        "status": status?.toJson(),
 | 
			
		||||
      };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Route of the train
 | 
			
		||||
@freezed
 | 
			
		||||
class TrainDataRoute with _$TrainDataRoute {
 | 
			
		||||
  const factory TrainDataRoute({
 | 
			
		||||
    required String from,
 | 
			
		||||
    required String to,
 | 
			
		||||
  }) = _TrainDataRoute;
 | 
			
		||||
class Route {
 | 
			
		||||
  Route({
 | 
			
		||||
    required this.from,
 | 
			
		||||
    required this.to,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  factory TrainDataRoute.fromJson(Map<String, dynamic> json) => _$TrainDataRouteFromJson(json);
 | 
			
		||||
  final String from;
 | 
			
		||||
  final String to;
 | 
			
		||||
 | 
			
		||||
  factory Route.fromJson(Map<String, dynamic> json) => Route(
 | 
			
		||||
        from: json["from"],
 | 
			
		||||
        to: json["to"],
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
  Map<String, dynamic> toJson() => {
 | 
			
		||||
        "from": from,
 | 
			
		||||
        "to": to,
 | 
			
		||||
      };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@freezed
 | 
			
		||||
class TrainDataStation with _$TrainDataStation {
 | 
			
		||||
  const factory TrainDataStation({
 | 
			
		||||
    required String name,
 | 
			
		||||
    required String linkName,
 | 
			
		||||
    required int km,
 | 
			
		||||
    int? stoppingTime,
 | 
			
		||||
    String? platform,
 | 
			
		||||
    StationArrDepTime? arrival,
 | 
			
		||||
    StationArrDepTime? departure,
 | 
			
		||||
    @TrainDataNoteConverter()
 | 
			
		||||
    required List<TrainDataNote> notes,
 | 
			
		||||
  }) = _TrainDataStation;
 | 
			
		||||
class Station {
 | 
			
		||||
  Station({
 | 
			
		||||
    this.arrival,
 | 
			
		||||
    this.departure,
 | 
			
		||||
    required this.km,
 | 
			
		||||
    required this.name,
 | 
			
		||||
    this.platform,
 | 
			
		||||
    this.stoppingTime,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  factory TrainDataStation.fromJson(Map<String, dynamic> json) => _$TrainDataStationFromJson(json);
 | 
			
		||||
  final StationArrDepTime? arrival;
 | 
			
		||||
  final StationArrDepTime? departure;
 | 
			
		||||
  final int km;
 | 
			
		||||
  final String name;
 | 
			
		||||
  final String? platform;
 | 
			
		||||
  final int? stoppingTime;
 | 
			
		||||
 | 
			
		||||
  factory Station.fromJson(Map<String, dynamic> json) => Station(
 | 
			
		||||
        arrival: json["arrival"] == null
 | 
			
		||||
            ? null
 | 
			
		||||
            : StationArrDepTime.fromJson(json["arrival"]),
 | 
			
		||||
        departure: json["departure"] == null
 | 
			
		||||
            ? null
 | 
			
		||||
            : StationArrDepTime.fromJson(json["departure"]),
 | 
			
		||||
        km: json["km"],
 | 
			
		||||
        name: json["name"],
 | 
			
		||||
        platform: json["platform"] == null ? null : json["platform"],
 | 
			
		||||
        stoppingTime:
 | 
			
		||||
            json["stoppingTime"] == null ? null : json["stoppingTime"],
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
  Map<String, dynamic> toJson() => {
 | 
			
		||||
        "arrival": arrival?.toJson(),
 | 
			
		||||
        "departure": departure?.toJson(),
 | 
			
		||||
        "km": km,
 | 
			
		||||
        "name": name,
 | 
			
		||||
        "platform": platform == null ? null : platform,
 | 
			
		||||
        "stoppingTime": stoppingTime == null ? null : stoppingTime,
 | 
			
		||||
      };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@freezed
 | 
			
		||||
class StationArrDepTime with _$StationArrDepTime {
 | 
			
		||||
  const factory StationArrDepTime({
 | 
			
		||||
    required DateTime scheduleTime,
 | 
			
		||||
    StationArrDepTimeStatus? status,
 | 
			
		||||
  }) = _StationArrDepTime;
 | 
			
		||||
class StationArrDepTime {
 | 
			
		||||
  StationArrDepTime({
 | 
			
		||||
    required this.scheduleTime,
 | 
			
		||||
    this.status,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  factory StationArrDepTime.fromJson(Map<String, dynamic> json) => _$StationArrDepTimeFromJson(json);
 | 
			
		||||
  final String scheduleTime;
 | 
			
		||||
  final StationArrDepTimeStatus? status;
 | 
			
		||||
 | 
			
		||||
  factory StationArrDepTime.fromJson(Map<String, dynamic> json) =>
 | 
			
		||||
      StationArrDepTime(
 | 
			
		||||
        scheduleTime: json["scheduleTime"],
 | 
			
		||||
        status: json["status"] == null ? null : StationArrDepTimeStatus.fromJson(json["status"]),
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
  Map<String, dynamic> toJson() => {
 | 
			
		||||
        "scheduleTime": scheduleTime,
 | 
			
		||||
        "status": status?.toJson(),
 | 
			
		||||
      };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@freezed
 | 
			
		||||
class StationArrDepTimeStatus with _$StationArrDepTimeStatus {
 | 
			
		||||
  const factory StationArrDepTimeStatus({
 | 
			
		||||
    required int delay,
 | 
			
		||||
    required bool real,
 | 
			
		||||
    required bool cancelled,
 | 
			
		||||
  }) = _StationArrDepTimeStatus;
 | 
			
		||||
class StationArrDepTimeStatus {
 | 
			
		||||
  StationArrDepTimeStatus({
 | 
			
		||||
    required this.delay,
 | 
			
		||||
    required this.real,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  factory StationArrDepTimeStatus.fromJson(Map<String, dynamic> json) => _$StationArrDepTimeStatusFromJson(json);
 | 
			
		||||
  final int delay;
 | 
			
		||||
  final bool real;
 | 
			
		||||
 | 
			
		||||
  factory StationArrDepTimeStatus.fromJson(Map<String, dynamic> json) =>
 | 
			
		||||
      StationArrDepTimeStatus(
 | 
			
		||||
        delay: json["delay"],
 | 
			
		||||
        real: json["real"],
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
  Map<String, dynamic> toJson() => {
 | 
			
		||||
        "delay": delay,
 | 
			
		||||
        "real": real,
 | 
			
		||||
      };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@freezed
 | 
			
		||||
class TrainDataStatus with _$TrainDataStatus {
 | 
			
		||||
  const TrainDataStatus._();
 | 
			
		||||
class TrainDataStatus {
 | 
			
		||||
  TrainDataStatus({
 | 
			
		||||
    required this.delay,
 | 
			
		||||
    required this.state,
 | 
			
		||||
    required this.station,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  const factory TrainDataStatus({
 | 
			
		||||
    required int delay,
 | 
			
		||||
    required String station,
 | 
			
		||||
    required TrainDataStatusState state,
 | 
			
		||||
  }) = _TrainDataStatus;
 | 
			
		||||
  final int delay;
 | 
			
		||||
  final State state;
 | 
			
		||||
  final String station;
 | 
			
		||||
 | 
			
		||||
  factory TrainDataStatus.fromJson(Map<String, dynamic> json) => _$TrainDataStatusFromJson(json);
 | 
			
		||||
  factory TrainDataStatus.fromJson(Map<String, dynamic> json) =>
 | 
			
		||||
      TrainDataStatus(
 | 
			
		||||
        delay: json["delay"],
 | 
			
		||||
        state: stateValues.map[json["state"]]!,
 | 
			
		||||
        station: json["station"],
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
  Map<String, dynamic> toJson() => {
 | 
			
		||||
        "delay": delay,
 | 
			
		||||
        "state": stateValues.reverse[state],
 | 
			
		||||
        "station": station,
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  String toString() {
 | 
			
		||||
| 
						 | 
				
			
			@ -127,118 +190,40 @@ class TrainDataStatus with _$TrainDataStatus {
 | 
			
		|||
      result += '${delay.abs()} min';
 | 
			
		||||
    }
 | 
			
		||||
    result += ' la ';
 | 
			
		||||
    result += switch (state) {
 | 
			
		||||
      TrainDataStatusState.passing => 'trecerea fără oprire prin',
 | 
			
		||||
      TrainDataStatusState.arrival => 'sosirea în',
 | 
			
		||||
      TrainDataStatusState.departure => 'plecarea din',
 | 
			
		||||
    };
 | 
			
		||||
    switch (state) {
 | 
			
		||||
      case State.PASSING:
 | 
			
		||||
        result += 'trecerea fără oprire prin';
 | 
			
		||||
        break;
 | 
			
		||||
      case State.ARRIVAL:
 | 
			
		||||
        result += 'sosirea în';
 | 
			
		||||
        break;
 | 
			
		||||
      case State.DEPARTURE:
 | 
			
		||||
        result += 'plecarea din';
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    result += station;
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
enum TrainDataStatusState { passing, arrival, departure }
 | 
			
		||||
enum State { PASSING, ARRIVAL, DEPARTURE }
 | 
			
		||||
 | 
			
		||||
abstract class TrainDataNote {
 | 
			
		||||
  final String kind;
 | 
			
		||||
final stateValues = EnumValues({
 | 
			
		||||
  "arrival": State.ARRIVAL,
 | 
			
		||||
  "departure": State.DEPARTURE,
 | 
			
		||||
  "passing": State.PASSING
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
  const TrainDataNote({required this.kind});
 | 
			
		||||
class EnumValues<T> {
 | 
			
		||||
  Map<String, T> map;
 | 
			
		||||
  Map<T, String>? reverseMap;
 | 
			
		||||
 | 
			
		||||
  Map<String, dynamic> toJson() => {
 | 
			
		||||
    "kind": kind,
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
  EnumValues(this.map);
 | 
			
		||||
 | 
			
		||||
class TrainDataNoteConverter implements JsonConverter<TrainDataNote, Map<String, dynamic>> {
 | 
			
		||||
  const TrainDataNoteConverter();
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  TrainDataNote fromJson(Map<String, dynamic> json) {
 | 
			
		||||
    return switch(json['kind']) {
 | 
			
		||||
      'trainNumberChange' => TrainDataNoteTrainNumberChange.fromJson(json),
 | 
			
		||||
      'departsAs' => TrainDataNoteDepartsAs.fromJson(json),
 | 
			
		||||
      'detachingWagons' => TrainDataNoteDetachingWagons.fromJson(json),
 | 
			
		||||
      'receivingWagons' => TrainDataNoteReceivingWagons.fromJson(json),
 | 
			
		||||
      _ => TrainDataNoteUnknown.fromJson(json),
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Map<String, dynamic> toJson(TrainDataNote object) {
 | 
			
		||||
    return object.toJson();
 | 
			
		||||
  Map<T, String> get reverse {
 | 
			
		||||
    if (reverseMap == null) {
 | 
			
		||||
      reverseMap = map.map((k, v) => new MapEntry(v, k));
 | 
			
		||||
    }
 | 
			
		||||
    return reverseMap!;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@freezed
 | 
			
		||||
class TrainDataNoteTrainNumberChange with _$TrainDataNoteTrainNumberChange implements TrainDataNote {
 | 
			
		||||
  @Implements<TrainDataNote>()
 | 
			
		||||
  const factory TrainDataNoteTrainNumberChange({
 | 
			
		||||
    // base
 | 
			
		||||
    @Default("trainNumberChange")
 | 
			
		||||
    String kind,
 | 
			
		||||
    // impl
 | 
			
		||||
    required String rank,
 | 
			
		||||
    required String number,
 | 
			
		||||
  }) = _TrainDataNoteTrainNumberChange;  
 | 
			
		||||
  
 | 
			
		||||
  factory TrainDataNoteTrainNumberChange.fromJson(Map<String, dynamic> json) => _$TrainDataNoteTrainNumberChangeFromJson(json);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@freezed
 | 
			
		||||
class TrainDataNoteDepartsAs with _$TrainDataNoteDepartsAs implements TrainDataNote {
 | 
			
		||||
  @Implements<TrainDataNote>()
 | 
			
		||||
  const factory TrainDataNoteDepartsAs({
 | 
			
		||||
    // base
 | 
			
		||||
    @Default("departsAs")
 | 
			
		||||
    String kind,
 | 
			
		||||
    // impl
 | 
			
		||||
    required String rank,
 | 
			
		||||
    required String number,
 | 
			
		||||
    required DateTime departureDate,
 | 
			
		||||
  }) = _TrainDataNoteDepartsAs;  
 | 
			
		||||
  
 | 
			
		||||
  factory TrainDataNoteDepartsAs.fromJson(Map<String, dynamic> json) => _$TrainDataNoteDepartsAsFromJson(json);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@freezed
 | 
			
		||||
class TrainDataNoteDetachingWagons with _$TrainDataNoteDetachingWagons implements TrainDataNote {
 | 
			
		||||
  @Implements<TrainDataNote>()
 | 
			
		||||
  const factory TrainDataNoteDetachingWagons({
 | 
			
		||||
    // base
 | 
			
		||||
    @Default("detachingWagons")
 | 
			
		||||
    String kind,
 | 
			
		||||
    // impl
 | 
			
		||||
    required String station,
 | 
			
		||||
  }) = _TrainDataNoteDetachingWagons;  
 | 
			
		||||
  
 | 
			
		||||
  factory TrainDataNoteDetachingWagons.fromJson(Map<String, dynamic> json) => _$TrainDataNoteDetachingWagonsFromJson(json);
 | 
			
		||||
}
 | 
			
		||||
@freezed
 | 
			
		||||
class TrainDataNoteReceivingWagons with _$TrainDataNoteReceivingWagons implements TrainDataNote {
 | 
			
		||||
  @Implements<TrainDataNote>()
 | 
			
		||||
  const factory TrainDataNoteReceivingWagons({
 | 
			
		||||
    // base
 | 
			
		||||
    @Default("receivingWagons")
 | 
			
		||||
    String kind,
 | 
			
		||||
    // impl
 | 
			
		||||
    required String station,
 | 
			
		||||
  }) = _TrainDataNoteReceivingWagons;  
 | 
			
		||||
  
 | 
			
		||||
  factory TrainDataNoteReceivingWagons.fromJson(Map<String, dynamic> json) => _$TrainDataNoteReceivingWagonsFromJson(json);
 | 
			
		||||
}
 | 
			
		||||
  
 | 
			
		||||
@freezed
 | 
			
		||||
class TrainDataNoteUnknown with _$TrainDataNoteUnknown implements TrainDataNote {
 | 
			
		||||
  @Implements<TrainDataNote>()
 | 
			
		||||
  const factory TrainDataNoteUnknown({
 | 
			
		||||
    // base
 | 
			
		||||
    required String kind,
 | 
			
		||||
    // impl
 | 
			
		||||
    required Map<String, dynamic> extra,
 | 
			
		||||
  }) = _TrainDataNoteUnknown;
 | 
			
		||||
  
 | 
			
		||||
  factory TrainDataNoteUnknown.fromJson(Map<String, dynamic> json) => TrainDataNoteUnknown(
 | 
			
		||||
    kind: json['kind'], 
 | 
			
		||||
    extra: Map.from(json)..remove('kind'),
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
				
			
			@ -1,217 +0,0 @@
 | 
			
		|||
// 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,
 | 
			
		||||
    };
 | 
			
		||||
							
								
								
									
										42
									
								
								lib/models/train_operator_lines.dart
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								lib/models/train_operator_lines.dart
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,42 @@
 | 
			
		|||
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);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										42
									
								
								lib/models/train_operator_lines.g.dart
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								lib/models/train_operator_lines.g.dart
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,42 @@
 | 
			
		|||
// 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,
 | 
			
		||||
    };
 | 
			
		||||
| 
						 | 
				
			
			@ -1,15 +0,0 @@
 | 
			
		|||
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);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,187 +0,0 @@
 | 
			
		|||
// 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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,21 +0,0 @@
 | 
			
		|||
// 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,
 | 
			
		||||
    };
 | 
			
		||||
| 
						 | 
				
			
			@ -1,15 +1,6 @@
 | 
			
		|||
enum UiDesign {
 | 
			
		||||
  MATERIAL,
 | 
			
		||||
  CUPERTINO,
 | 
			
		||||
  FLUENT,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extension UIName on UiDesign {
 | 
			
		||||
  String get userInterfaceName => (const {
 | 
			
		||||
    UiDesign.MATERIAL: 'Material',
 | 
			
		||||
    UiDesign.CUPERTINO: 'Cupertino',
 | 
			
		||||
    UiDesign.FLUENT: 'Fluent',
 | 
			
		||||
  })[this]!;
 | 
			
		||||
  CUPERTINO
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class UnmatchedUiDesignException implements Exception {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,94 +0,0 @@
 | 
			
		|||
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}';
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,80 +0,0 @@
 | 
			
		|||
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();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,137 +0,0 @@
 | 
			
		|||
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(),
 | 
			
		||||
                ],
 | 
			
		||||
              ],
 | 
			
		||||
            ),
 | 
			
		||||
          );
 | 
			
		||||
        }
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,198 +0,0 @@
 | 
			
		|||
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,
 | 
			
		||||
                  ),
 | 
			
		||||
                ),
 | 
			
		||||
              ),
 | 
			
		||||
            ],
 | 
			
		||||
          ],
 | 
			
		||||
        ),
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,199 +0,0 @@
 | 
			
		|||
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,
 | 
			
		||||
                  ),
 | 
			
		||||
                ),
 | 
			
		||||
              ),
 | 
			
		||||
            ],
 | 
			
		||||
          ],
 | 
			
		||||
        ),
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,29 +1,24 @@
 | 
			
		|||
import 'package:flutter/widgets.dart';
 | 
			
		||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
			
		||||
import 'package:info_tren/models.dart';
 | 
			
		||||
import 'package:info_tren/pages/about/about_page.dart';
 | 
			
		||||
import 'package:info_tren/models/ui_design.dart';
 | 
			
		||||
import 'package:info_tren/pages/main/main_page_cupertino.dart';
 | 
			
		||||
import 'package:info_tren/pages/main/main_page_fluent.dart';
 | 
			
		||||
import 'package:info_tren/pages/main/main_page_material.dart';
 | 
			
		||||
import 'package:info_tren/pages/settings/setings_page.dart';
 | 
			
		||||
import 'package:info_tren/pages/station_arrdep_page/select_station/select_station.dart';
 | 
			
		||||
import 'package:info_tren/pages/train_info_page/select_train/select_train.dart';
 | 
			
		||||
import 'package:info_tren/providers.dart';
 | 
			
		||||
import 'package:info_tren/utils/default_ui_design.dart';
 | 
			
		||||
 | 
			
		||||
class MainPage extends ConsumerWidget {
 | 
			
		||||
  const MainPage({super.key,});
 | 
			
		||||
class MainPage extends StatelessWidget {
 | 
			
		||||
  final UiDesign? uiDesign;
 | 
			
		||||
 | 
			
		||||
  const MainPage({ Key? key, this.uiDesign }) : super(key: key);
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context, WidgetRef ref) {
 | 
			
		||||
    final uiDesign = ref.watch(uiDesignProvider);
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    final uiDesign = this.uiDesign ?? defaultUiDesign;
 | 
			
		||||
    
 | 
			
		||||
    switch (uiDesign) {
 | 
			
		||||
      case UiDesign.MATERIAL:
 | 
			
		||||
        return const MainPageMaterial();
 | 
			
		||||
        return MainPageMaterial();
 | 
			
		||||
      case UiDesign.CUPERTINO:
 | 
			
		||||
        return const MainPageCupertino();
 | 
			
		||||
      case UiDesign.FLUENT:
 | 
			
		||||
        return const MainPageFluent();
 | 
			
		||||
        return MainPageCupertino();
 | 
			
		||||
      default:
 | 
			
		||||
        throw UnmatchedUiDesignException(uiDesign);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -32,43 +27,21 @@ class MainPage extends ConsumerWidget {
 | 
			
		|||
 | 
			
		||||
abstract class MainPageShared extends StatelessWidget {
 | 
			
		||||
  final String pageTitle = 'Info Tren';
 | 
			
		||||
  final String moreOptionsText = 'Mai multe opțiuni';
 | 
			
		||||
 | 
			
		||||
  const MainPageShared({super.key});
 | 
			
		||||
 | 
			
		||||
  List<MainPageAction> get popupMenu => [
 | 
			
		||||
    MainPageAction(
 | 
			
		||||
      name: 'Setări',
 | 
			
		||||
      action: (context) {
 | 
			
		||||
        Navigator.of(context).pushNamed(SettingsPage.routeName);
 | 
			
		||||
      },
 | 
			
		||||
    ),
 | 
			
		||||
    MainPageAction(
 | 
			
		||||
      name: 'Despre aplicație',
 | 
			
		||||
      action: (context) {
 | 
			
		||||
        Navigator.of(context).pushNamed(AboutPage.routeName);
 | 
			
		||||
      },
 | 
			
		||||
    ),
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  List<MainPageAction> get options => [
 | 
			
		||||
    MainPageAction(
 | 
			
		||||
  List<MainPageOption> get options => [
 | 
			
		||||
    MainPageOption(
 | 
			
		||||
      name: 'Informații despre tren',
 | 
			
		||||
      description: 'Află informații despre parcursul unui anumit tren',
 | 
			
		||||
      action: (context) {
 | 
			
		||||
      action: (BuildContext context) {
 | 
			
		||||
        onTrainInfoPageInvoke(context);
 | 
			
		||||
      },
 | 
			
		||||
    ),
 | 
			
		||||
    MainPageAction(
 | 
			
		||||
    MainPageOption(
 | 
			
		||||
      name: 'Tabelă plecari/sosiri',
 | 
			
		||||
      description: 'Vezi trenurile care pleacă și sosesc dintr-o gară',
 | 
			
		||||
      action: (context) {
 | 
			
		||||
        onStationBoardPageInvoke(context);
 | 
			
		||||
      },
 | 
			
		||||
      // TODO: Implement departure/arrival
 | 
			
		||||
      action: null,
 | 
			
		||||
    ),
 | 
			
		||||
    MainPageAction(
 | 
			
		||||
    MainPageOption(
 | 
			
		||||
      name: 'Planificare rută',
 | 
			
		||||
      description: 'Găsește trenurile disponibile pentru călătoria între două gări',
 | 
			
		||||
      // TODO: Implement route planning
 | 
			
		||||
      action: null,
 | 
			
		||||
    ),
 | 
			
		||||
| 
						 | 
				
			
			@ -79,7 +52,7 @@ abstract class MainPageShared extends StatelessWidget {
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  onStationBoardPageInvoke(BuildContext context) {
 | 
			
		||||
    Navigator.of(context).pushNamed(SelectStationPage.routeName);
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  onRoutePlanPageInvoke(BuildContext context) {
 | 
			
		||||
| 
						 | 
				
			
			@ -87,14 +60,9 @@ abstract class MainPageShared extends StatelessWidget {
 | 
			
		|||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class MainPageAction {
 | 
			
		||||
class MainPageOption {
 | 
			
		||||
  final String name;
 | 
			
		||||
  final String? description;
 | 
			
		||||
  final void Function(BuildContext context)? action;
 | 
			
		||||
 | 
			
		||||
  MainPageAction({
 | 
			
		||||
    required this.name,
 | 
			
		||||
    this.action,
 | 
			
		||||
    this.description,
 | 
			
		||||
  });
 | 
			
		||||
  MainPageOption({required this.name, this.action});
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,64 +2,19 @@ import 'package:flutter/cupertino.dart';
 | 
			
		|||
import 'package:info_tren/pages/main/main_page.dart';
 | 
			
		||||
 | 
			
		||||
class MainPageCupertino extends MainPageShared {
 | 
			
		||||
  const MainPageCupertino({super.key});
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    return CupertinoPageScaffold(
 | 
			
		||||
      navigationBar: CupertinoNavigationBar(
 | 
			
		||||
        middle: Text(pageTitle),
 | 
			
		||||
        trailing: CupertinoButton(
 | 
			
		||||
          padding: EdgeInsets.zero,
 | 
			
		||||
          onPressed: () {
 | 
			
		||||
            showCupertinoModalPopup(
 | 
			
		||||
              context: context, 
 | 
			
		||||
              builder: (context) {
 | 
			
		||||
                return CupertinoActionSheet(
 | 
			
		||||
                  actions: popupMenu.map((m) => CupertinoActionSheetAction(
 | 
			
		||||
                    onPressed: () {
 | 
			
		||||
                      Navigator.of(context).pop();
 | 
			
		||||
                      m.action?.call(context);
 | 
			
		||||
                    }, 
 | 
			
		||||
                    child: Text(m.name),
 | 
			
		||||
                  )).toList(),
 | 
			
		||||
                  cancelButton: CupertinoActionSheetAction(
 | 
			
		||||
                    onPressed: () {
 | 
			
		||||
                      Navigator.of(context).pop();
 | 
			
		||||
                    },
 | 
			
		||||
                    child: const Text('Anulare'),
 | 
			
		||||
                  ),
 | 
			
		||||
                );
 | 
			
		||||
              },
 | 
			
		||||
            );
 | 
			
		||||
          },
 | 
			
		||||
          child: const Icon(CupertinoIcons.ellipsis_circle),
 | 
			
		||||
        ),
 | 
			
		||||
      ),
 | 
			
		||||
      child: SafeArea(
 | 
			
		||||
        child: Center(
 | 
			
		||||
          child: Column(
 | 
			
		||||
            mainAxisSize: MainAxisSize.min,
 | 
			
		||||
            children: options.map((option) => CupertinoButton.filled(
 | 
			
		||||
              child: Text(option.name),
 | 
			
		||||
              onPressed: option.action == null ? null : () => option.action!(context),
 | 
			
		||||
              child: Text.rich(
 | 
			
		||||
                TextSpan(
 | 
			
		||||
                  children: [
 | 
			
		||||
                    TextSpan(text: option.name),
 | 
			
		||||
                    if (option.description != null) ...[
 | 
			
		||||
                      const TextSpan(text: '\n'),
 | 
			
		||||
                      TextSpan(
 | 
			
		||||
                        text: option.description,
 | 
			
		||||
                        style: const TextStyle(
 | 
			
		||||
                          inherit: true,
 | 
			
		||||
                          fontSize: 14,
 | 
			
		||||
                        ),
 | 
			
		||||
                      ),
 | 
			
		||||
                    ],
 | 
			
		||||
                  ],
 | 
			
		||||
                ),
 | 
			
		||||
                textAlign: TextAlign.center,
 | 
			
		||||
              ),
 | 
			
		||||
            )).map((w) => Padding(
 | 
			
		||||
              padding: const EdgeInsets.fromLTRB(4, 2, 4, 2),
 | 
			
		||||
              child: SizedBox(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,89 +0,0 @@
 | 
			
		|||
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(),
 | 
			
		||||
          ),
 | 
			
		||||
        ),
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -2,55 +2,23 @@ import 'package:flutter/material.dart';
 | 
			
		|||
import 'package:info_tren/pages/main/main_page.dart';
 | 
			
		||||
 | 
			
		||||
class MainPageMaterial extends MainPageShared {
 | 
			
		||||
  const MainPageMaterial({super.key});
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    return Scaffold(
 | 
			
		||||
      appBar: AppBar(
 | 
			
		||||
        title: Text(pageTitle),
 | 
			
		||||
        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);
 | 
			
		||||
            },
 | 
			
		||||
          ),
 | 
			
		||||
        ],
 | 
			
		||||
      ),
 | 
			
		||||
      body: SafeArea(
 | 
			
		||||
        child: Center(
 | 
			
		||||
          child: Column(
 | 
			
		||||
            mainAxisSize: MainAxisSize.min,
 | 
			
		||||
            children: options.map((option) => Card(
 | 
			
		||||
              color: option.action != null ? Theme.of(context).colorScheme.secondaryContainer : null,
 | 
			
		||||
              child: InkWell(
 | 
			
		||||
                onTap: option.action != null ? () => option.action!(context) : null,
 | 
			
		||||
                child: Column(
 | 
			
		||||
                  children: [
 | 
			
		||||
                    Padding(
 | 
			
		||||
                      padding: const EdgeInsets.all(8.0),
 | 
			
		||||
                      child: Text(
 | 
			
		||||
                        option.name,
 | 
			
		||||
                        style: Theme.of(context).textTheme.headlineMedium?.copyWith(
 | 
			
		||||
                          color: Theme.of(context).colorScheme.onSecondaryContainer,
 | 
			
		||||
                        ),
 | 
			
		||||
                        textAlign: TextAlign.center,
 | 
			
		||||
                      ),
 | 
			
		||||
                    ),
 | 
			
		||||
                    Padding(
 | 
			
		||||
                      padding: const EdgeInsets.all(8.0),
 | 
			
		||||
                      child: Text(option.description!),
 | 
			
		||||
                    ),
 | 
			
		||||
                  ],
 | 
			
		||||
                ),
 | 
			
		||||
            children: options.map((option) => ElevatedButton(
 | 
			
		||||
              child: Text(
 | 
			
		||||
                option.name,
 | 
			
		||||
                style: Theme.of(context).textTheme.button?.copyWith(fontSize: 18),
 | 
			
		||||
              ),
 | 
			
		||||
              onPressed: option.action != null ? () => option.action!(context) : null,
 | 
			
		||||
            )).map((w) => Padding(
 | 
			
		||||
              padding: const EdgeInsets.fromLTRB(4, 2, 4, 2),
 | 
			
		||||
              child: SizedBox(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,38 +0,0 @@
 | 
			
		|||
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});
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,96 +0,0 @@
 | 
			
		|||
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'));
 | 
			
		||||
                        }
 | 
			
		||||
                      },
 | 
			
		||||
                    );
 | 
			
		||||
                  },
 | 
			
		||||
                ),
 | 
			
		||||
              ],
 | 
			
		||||
            ),
 | 
			
		||||
          );
 | 
			
		||||
        },
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,65 +0,0 @@
 | 
			
		|||
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);
 | 
			
		||||
                      }
 | 
			
		||||
                    },
 | 
			
		||||
                  ),
 | 
			
		||||
                );
 | 
			
		||||
              },
 | 
			
		||||
            ),
 | 
			
		||||
          ],
 | 
			
		||||
        ),
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,66 +0,0 @@
 | 
			
		|||
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);
 | 
			
		||||
                      }
 | 
			
		||||
                    },
 | 
			
		||||
                  ),
 | 
			
		||||
                );
 | 
			
		||||
              },
 | 
			
		||||
            ),
 | 
			
		||||
          ],
 | 
			
		||||
        ),
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,92 +0,0 @@
 | 
			
		|||
import 'package:flutter/widgets.dart';
 | 
			
		||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
			
		||||
import 'package:info_tren/models.dart';
 | 
			
		||||
import 'package:info_tren/pages/station_arrdep_page/select_station/select_station_cupertino.dart';
 | 
			
		||||
import 'package:info_tren/pages/station_arrdep_page/select_station/select_station_fluent.dart';
 | 
			
		||||
import 'package:info_tren/pages/station_arrdep_page/select_station/select_station_material.dart';
 | 
			
		||||
import 'package:info_tren/pages/station_arrdep_page/view_station/view_station.dart';
 | 
			
		||||
import 'package:info_tren/providers.dart';
 | 
			
		||||
import 'package:info_tren/api/stations.dart' as api_stations;
 | 
			
		||||
 | 
			
		||||
class SelectStationPage extends ConsumerWidget {
 | 
			
		||||
  const SelectStationPage({ super.key });
 | 
			
		||||
 | 
			
		||||
  static String routeName = '/stationArrDep/selectStation';
 | 
			
		||||
  
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context, WidgetRef ref) {
 | 
			
		||||
    final uiDesign = ref.watch(uiDesignProvider);
 | 
			
		||||
    switch (uiDesign) {
 | 
			
		||||
      case UiDesign.MATERIAL:
 | 
			
		||||
        return const SelectStationPageMaterial();
 | 
			
		||||
      case UiDesign.CUPERTINO:
 | 
			
		||||
        return const SelectStationPageCupertino();
 | 
			
		||||
      case UiDesign.FLUENT:
 | 
			
		||||
        return const SelectStationPageFluent();
 | 
			
		||||
      default:
 | 
			
		||||
        throw UnmatchedUiDesignException(uiDesign);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
abstract class SelectStationPageShared extends StatefulWidget {
 | 
			
		||||
  const SelectStationPageShared({super.key});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
abstract class SelectStationPageState extends State<SelectStationPageShared> {
 | 
			
		||||
  static const pageTitle = 'Plecări/sosiri stație';
 | 
			
		||||
  static const textFieldLabel = 'Numele stației';
 | 
			
		||||
  static const roToEn = {
 | 
			
		||||
    'ă': 'a',
 | 
			
		||||
    'â': 'a',
 | 
			
		||||
    'î': 'i',
 | 
			
		||||
    'ș': 's',
 | 
			
		||||
    'ț': 't',
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  final textEditingController = TextEditingController();
 | 
			
		||||
 | 
			
		||||
  List<String> stations = [];
 | 
			
		||||
 | 
			
		||||
  List<String> get filteredStations {
 | 
			
		||||
    final filter = textEditingController.text
 | 
			
		||||
      .trim()
 | 
			
		||||
      .toLowerCase()
 | 
			
		||||
      .replaceAllMapped(RegExp(r'[ăâîșț]'), (match) => roToEn[match[0]!]!);
 | 
			
		||||
    if (filter.isEmpty) {
 | 
			
		||||
      return stations;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    return stations.where(
 | 
			
		||||
      (e) => e
 | 
			
		||||
        .toLowerCase()
 | 
			
		||||
        .replaceAllMapped(RegExp(r'[ăâîșț]'), (match) { 
 | 
			
		||||
          return roToEn[match[0]!]!;
 | 
			
		||||
        })
 | 
			
		||||
        .contains(filter)
 | 
			
		||||
    ).toList(growable: false);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  void initState() {
 | 
			
		||||
    api_stations.stations.then((value) {
 | 
			
		||||
      setState(() {
 | 
			
		||||
        stations = value.map((e) => e.name).toList(growable: false,);
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    super.initState();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void onTextChanged(String newText) {
 | 
			
		||||
    setState(() {});
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void onSuggestionSelected(String suggestion) {
 | 
			
		||||
    Navigator.of(context).pushNamed(
 | 
			
		||||
      ViewStationPage.routeName, 
 | 
			
		||||
      arguments: ViewStationArguments(stationName: suggestion),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
	Add table
		
		Reference in a new issue