Compare commits

..

No commits in common. 'master' and 'v2.7.10' have entirely different histories.

  1. 7
      CHANGELOG.txt
  2. 4
      android/app/build.gradle
  3. 4
      android/build.gradle
  4. 2
      android/gradle/wrapper/gradle-wrapper.properties
  5. 4
      codemagic.yaml
  6. 2
      ios/Flutter/AppFrameworkInfo.plist
  7. 2
      ios/Podfile
  8. 34
      ios/Podfile.lock
  9. 76
      ios/Runner.xcodeproj/project.pbxproj
  10. 2
      ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
  11. 3
      ios/Runner.xcworkspace/contents.xcworkspacedata
  12. 2
      ios/Runner/Info.plist
  13. 8
      lib/api/station_data.dart
  14. 2
      lib/api/train_data.dart
  15. 2
      lib/components/select_train_suggestions/select_train_suggestions.dart
  16. 5
      lib/components/select_train_suggestions/select_train_suggestions_cupertino.dart
  17. 5
      lib/components/select_train_suggestions/select_train_suggestions_fluent.dart
  18. 3
      lib/components/select_train_suggestions/select_train_suggestions_material.dart
  19. 2
      lib/components/slim_app_bar.dart
  20. 39
      lib/components/train_id_text_span.dart
  21. 110
      lib/main.dart
  22. 7
      lib/models.dart
  23. 2
      lib/models/station_arrdep.freezed.dart
  24. 4
      lib/models/station_data.freezed.dart
  25. 2
      lib/models/station_status.freezed.dart
  26. 3
      lib/models/station_train.freezed.dart
  27. 3
      lib/models/stations_result.freezed.dart
  28. 373
      lib/models/train_data.dart
  29. 2365
      lib/models/train_data.freezed.dart
  30. 217
      lib/models/train_data.g.dart
  31. 2
      lib/models/trains_result.freezed.dart
  32. 94
      lib/models/ui_timezone.dart
  33. 1
      lib/pages/settings/setings_page.dart
  34. 21
      lib/pages/settings/settings_page_cupertino.dart
  35. 23
      lib/pages/settings/settings_page_fluent.dart
  36. 23
      lib/pages/settings/settings_page_material.dart
  37. 3
      lib/pages/station_arrdep_page/view_station/view_station.dart
  38. 43
      lib/pages/station_arrdep_page/view_station/view_station_cupertino.dart
  39. 49
      lib/pages/station_arrdep_page/view_station/view_station_fluent.dart
  40. 51
      lib/pages/station_arrdep_page/view_station/view_station_material.dart
  41. 111
      lib/pages/train_info_page/view_train/train_info.dart
  42. 113
      lib/pages/train_info_page/view_train/train_info_cupertino.dart
  43. 332
      lib/pages/train_info_page/view_train/train_info_cupertino_DisplayTrainStation.dart
  44. 20
      lib/pages/train_info_page/view_train/train_info_fluent.dart
  45. 368
      lib/pages/train_info_page/view_train/train_info_fluent_DisplayTrainStation.dart
  46. 143
      lib/pages/train_info_page/view_train/train_info_material.dart
  47. 406
      lib/pages/train_info_page/view_train/train_info_material_DisplayTrainStation.dart
  48. 47
      lib/providers.dart
  49. 120
      lib/providers.g.dart
  50. 15
      lib/utils/state_to_string.dart
  51. 4
      linux/flutter/generated_plugin_registrant.cc
  52. 1
      linux/flutter/generated_plugins.cmake
  53. 1
      macos/Flutter/Flutter-Debug.xcconfig
  54. 1
      macos/Flutter/Flutter-Release.xcconfig
  55. 40
      macos/Podfile
  56. 41
      macos/Podfile.lock
  57. 71
      macos/Runner.xcodeproj/project.pbxproj
  58. 2
      macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
  59. 3
      macos/Runner.xcworkspace/contents.xcworkspacedata
  60. 649
      pubspec.lock
  61. 15
      pubspec.yaml
  62. 3
      windows/flutter/generated_plugin_registrant.cc
  63. 1
      windows/flutter/generated_plugins.cmake

7
CHANGELOG.txt

@ -1,10 +1,3 @@
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 v2.7.10
Add about page to Fluent UI. Add about page to Fluent UI.
Add settings page, allowing changing between UIs. Add settings page, allowing changing between UIs.

4
android/app/build.gradle

@ -32,7 +32,7 @@ if (keystorePropertiesFile.exists()) {
} }
android { android {
compileSdkVersion 33 compileSdkVersion 31
compileOptions { compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_1_8
@ -51,7 +51,7 @@ android {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "ro.dcdev.infotren" applicationId "ro.dcdev.infotren"
minSdkVersion 16 minSdkVersion 16
targetSdkVersion 33 targetSdkVersion 31
versionCode flutterVersionCode.toInteger() versionCode flutterVersionCode.toInteger()
versionName flutterVersionName versionName flutterVersionName
} }

4
android/build.gradle

@ -6,7 +6,7 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:7.4.2' classpath 'com.android.tools.build:gradle:4.1.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
} }
} }
@ -24,6 +24,6 @@ subprojects {
project.evaluationDependsOn(':app') project.evaluationDependsOn(':app')
} }
tasks.register("clean", Delete) { task clean(type: Delete) {
delete rootProject.buildDir delete rootProject.buildDir
} }

2
android/gradle/wrapper/gradle-wrapper.properties vendored

@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.2-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip

4
codemagic.yaml

@ -30,8 +30,8 @@ workflows:
- | - |
#! /bin/sh #! /bin/sh
pwd=$(pwd) pwd=$(pwd)
mkdir -p build/ios/Payload mkdir -p build/ios/Payload/infotren.app
cp -r build/ios/iphoneos/Runner.app build/ios/Payload cp -r build/ios/iphoneos/Runner.app/* build/ios/Payload/infotren.app
mkdir -p build/ios/ipa mkdir -p build/ios/ipa
cd build/ios cd build/ios
zip -r Payload.zip Payload zip -r Payload.zip Payload

2
ios/Flutter/AppFrameworkInfo.plist

@ -21,6 +21,6 @@
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1.0</string> <string>1.0</string>
<key>MinimumOSVersion</key> <key>MinimumOSVersion</key>
<string>11.0</string> <string>9.0</string>
</dict> </dict>
</plist> </plist>

2
ios/Podfile

@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project # Uncomment this line to define a global platform for your project
# platform :ios, '11.0' # platform :ios, '9.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency. # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true' ENV['COCOAPODS_DISABLE_STATS'] = 'true'

34
ios/Podfile.lock

@ -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

76
ios/Runner.xcodeproj/project.pbxproj

@ -13,7 +13,6 @@
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 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 */ /* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */ /* Begin PBXCopyFilesBuildPhase section */
@ -32,11 +31,7 @@
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
@ -54,7 +49,6 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
AF5528149967EA996B5AA109 /* Pods_Runner.framework in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -78,8 +72,6 @@
9740EEB11CF90186004384FC /* Flutter */, 9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */, 97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */, 97C146EF1CF9000F007C117D /* Products */,
B55F9B76DFEAB456725329A0 /* Pods */,
E56598AA51C5533E6B51BD5A /* Frameworks */,
); );
sourceTree = "<group>"; sourceTree = "<group>";
}; };
@ -106,25 +98,6 @@
path = Runner; path = Runner;
sourceTree = "<group>"; 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 */ /* End PBXGroup section */
/* Begin PBXNativeTarget section */ /* Begin PBXNativeTarget section */
@ -132,14 +105,12 @@
isa = PBXNativeTarget; isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = ( buildPhases = (
2B2F3198BD0D2214C77EC99E /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */, 9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */, 97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */, 97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */, 97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */, 9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
D71FC49A789443CEBF7C5C70 /* [CP] Embed Pods Frameworks */,
); );
buildRules = ( buildRules = (
); );
@ -156,7 +127,7 @@
97C146E61CF9000F007C117D /* Project object */ = { 97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastUpgradeCheck = 1300; LastUpgradeCheck = 1020;
ORGANIZATIONNAME = ""; ORGANIZATIONNAME = "";
TargetAttributes = { TargetAttributes = {
97C146ED1CF9000F007C117D = { 97C146ED1CF9000F007C117D = {
@ -198,28 +169,6 @@
/* End PBXResourcesBuildPhase section */ /* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase 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 */ = { 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
@ -248,23 +197,6 @@
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 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 */ /* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */
@ -340,7 +272,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0; IPHONEOS_DEPLOYMENT_TARGET = 9.0;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos; SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos; SUPPORTED_PLATFORMS = iphoneos;
@ -419,7 +351,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0; IPHONEOS_DEPLOYMENT_TARGET = 9.0;
MTL_ENABLE_DEBUG_INFO = YES; MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos; SDKROOT = iphoneos;
@ -468,7 +400,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0; IPHONEOS_DEPLOYMENT_TARGET = 9.0;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos; SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos; SUPPORTED_PLATFORMS = iphoneos;

2
ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1300" LastUpgradeVersion = "1020"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

3
ios/Runner.xcworkspace/contents.xcworkspacedata generated

@ -4,7 +4,4 @@
<FileRef <FileRef
location = "group:Runner.xcodeproj"> location = "group:Runner.xcodeproj">
</FileRef> </FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace> </Workspace>

2
ios/Runner/Info.plist

@ -43,7 +43,5 @@
</array> </array>
<key>UIViewControllerBasedStatusBarAppearance</key> <key>UIViewControllerBasedStatusBarAppearance</key>
<false/> <false/>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
</dict> </dict>
</plist> </plist>

8
lib/api/station_data.dart

@ -4,11 +4,7 @@ import 'package:http/http.dart' as http;
import 'package:info_tren/api/common.dart'; import 'package:info_tren/api/common.dart';
import 'package:info_tren/models.dart'; import 'package:info_tren/models.dart';
Future<StationData> getStationData(String stationName, [DateTime? date]) async { Future<StationData> getStationData(String stationName) async {
final uri = Uri.https(authority, 'v3/stations/$stationName'); final response = await http.get(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)); return StationData.fromJson(jsonDecode(response.body));
} }

2
lib/api/train_data.dart

@ -4,7 +4,7 @@ import 'package:info_tren/models.dart';
Future<TrainData> getTrain(String trainNumber, {DateTime? date}) async { Future<TrainData> getTrain(String trainNumber, {DateTime? date}) async {
date ??= DateTime.now(); date ??= DateTime.now();
final response = await http.get(Uri.https(authority, 'v3/trains/$trainNumber', { final response = await http.get(Uri.https(authority, 'v2/train/$trainNumber', {
'date': date.toUtc().toIso8601String(), 'date': date.toUtc().toIso8601String(),
}),); }),);
return trainDataFromJson(response.body); return trainDataFromJson(response.body);

2
lib/components/select_train_suggestions/select_train_suggestions.dart

@ -1,3 +1,4 @@
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:hooks_riverpod/hooks_riverpod.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_cupertino.dart';
@ -5,6 +6,7 @@ import 'package:info_tren/components/select_train_suggestions/select_train_sugge
import 'package:info_tren/components/select_train_suggestions/select_train_suggestions_material.dart'; import 'package:info_tren/components/select_train_suggestions/select_train_suggestions_material.dart';
import 'package:info_tren/models.dart'; import 'package:info_tren/models.dart';
import 'package:info_tren/providers.dart'; import 'package:info_tren/providers.dart';
import 'package:info_tren/utils/default_ui_design.dart';
class SelectTrainSuggestions extends ConsumerWidget { class SelectTrainSuggestions extends ConsumerWidget {
final List<TrainsResult> choices; final List<TrainsResult> choices;

5
lib/components/select_train_suggestions/select_train_suggestions_cupertino.dart

@ -1,7 +1,6 @@
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:info_tren/components/cupertino_divider.dart'; import 'package:info_tren/components/cupertino_divider.dart';
import 'package:info_tren/components/select_train_suggestions/select_train_suggestions.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'; import 'package:info_tren/models.dart';
class SelectTrainSuggestionsCupertino extends SelectTrainSuggestionsShared { class SelectTrainSuggestionsCupertino extends SelectTrainSuggestionsShared {
@ -70,8 +69,8 @@ class OperatorAutocompleteTileCupertino extends OperatorAutocompleteTile {
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(fontSize: 10, fontWeight: FontWeight.w200), style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(fontSize: 10, fontWeight: FontWeight.w200),
textAlign: TextAlign.left, textAlign: TextAlign.left,
), ),
Text.rich( Text(
trainIdSpan(rank: train.rank, number: train.number), "${train.rank} ${train.number}",
textAlign: TextAlign.left, textAlign: TextAlign.left,
), ),
], ],

5
lib/components/select_train_suggestions/select_train_suggestions_fluent.dart

@ -1,6 +1,5 @@
import 'package:fluent_ui/fluent_ui.dart'; import 'package:fluent_ui/fluent_ui.dart';
import 'package:info_tren/components/select_train_suggestions/select_train_suggestions.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'; import 'package:info_tren/models.dart';
class SelectTrainSuggestionsFluent extends SelectTrainSuggestionsShared { class SelectTrainSuggestionsFluent extends SelectTrainSuggestionsShared {
@ -69,8 +68,8 @@ class OperatorAutocompleteTileFluent extends OperatorAutocompleteTile {
style: FluentTheme.of(context).typography.body?.copyWith(fontSize: 10, fontWeight: FontWeight.w200), style: FluentTheme.of(context).typography.body?.copyWith(fontSize: 10, fontWeight: FontWeight.w200),
textAlign: TextAlign.left, textAlign: TextAlign.left,
), ),
Text.rich( Text(
trainIdSpan(rank: train.rank, number: train.number), "${train.rank} ${train.number}",
textAlign: TextAlign.left, textAlign: TextAlign.left,
), ),
], ],

3
lib/components/select_train_suggestions/select_train_suggestions_material.dart

@ -1,6 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:info_tren/components/select_train_suggestions/select_train_suggestions.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'; import 'package:info_tren/models.dart';
class SelectTrainSuggestionsMaterial extends SelectTrainSuggestionsShared { class SelectTrainSuggestionsMaterial extends SelectTrainSuggestionsShared {
@ -45,7 +44,7 @@ class OperatorAutocompleteTileMaterial extends OperatorAutocompleteTile {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ListTile( return ListTile(
dense: true, dense: true,
title: Text.rich(trainIdSpan(rank: train.rank, number: train.number)), title: Text("${train.rank} ${train.number}"),
subtitle: Text(operatorName), subtitle: Text(operatorName),
onTap: () { onTap: () {
onTrainSelected(train.number); onTrainSelected(train.number);

2
lib/components/slim_app_bar.dart

@ -44,7 +44,7 @@ class SlimAppBar extends StatelessWidget {
title, title,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: style:
Theme.of(context).textTheme.titleSmall?.copyWith(color: Theme.of(context).textTheme.titleLarge?.color) ?? Theme.of(context).appBarTheme.textTheme?.bodySmall?.copyWith(color: Theme.of(context).appBarTheme.textTheme?.bodyMedium?.color) ??
Theme.of(context).textTheme.bodySmall?.copyWith(color: Theme.of(context).textTheme.bodyMedium?.color), Theme.of(context).textTheme.bodySmall?.copyWith(color: Theme.of(context).textTheme.bodyMedium?.color),
), ),
), ),

39
lib/components/train_id_text_span.dart

@ -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,
);

110
lib/main.dart

@ -1,6 +1,5 @@
import 'dart:io'; import 'dart:io';
import 'package:dynamic_color/dynamic_color.dart';
import 'package:fluent_ui/fluent_ui.dart' as f; import 'package:fluent_ui/fluent_ui.dart' as f;
import 'package:flutter/cupertino.dart' as c; import 'package:flutter/cupertino.dart' as c;
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
@ -18,11 +17,8 @@ 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/pages/train_info_page/select_train/select_train.dart';
import 'package:info_tren/providers.dart'; import 'package:info_tren/providers.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:timezone/data/latest.dart';
void main() async { void main() async {
WidgetsFlutterBinding.ensureInitialized();
initializeTimeZones();
final sharedPreferences = await SharedPreferences.getInstance(); final sharedPreferences = await SharedPreferences.getInstance();
runApp( runApp(
ProviderScope( ProviderScope(
@ -109,82 +105,52 @@ class StartPoint extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final uiDesign = ref.watch(uiDesignProvider); final uiDesign = ref.watch(uiDesignProvider);
if (uiDesign == UiDesign.CUPERTINO) { if (uiDesign == UiDesign.CUPERTINO) {
return DynamicColorBuilder( return AnnotatedRegion(
builder: (lightScheme, darkScheme) { value: const SystemUiOverlayStyle(
return AnnotatedRegion( statusBarBrightness: c.Brightness.dark,
value: const SystemUiOverlayStyle( ),
statusBarBrightness: c.Brightness.dark, child: c.CupertinoApp(
), title: appTitle,
child: c.CupertinoApp( theme: c.CupertinoThemeData(
title: appTitle, primaryColor: m.Colors.blue.shade600,
theme: c.CupertinoThemeData( brightness: c.Brightness.dark,
primaryColor: darkScheme?.primary ?? m.Colors.blue.shade600, // textTheme: CupertinoTextThemeData(
brightness: c.Brightness.dark, // textStyle: TextStyle(
// textTheme: CupertinoTextThemeData( // fontFamily: 'Atkinson Hyperlegible',
// textStyle: TextStyle( // ),
// fontFamily: 'Atkinson Hyperlegible', // ),
// ), ),
// ), scrollBehavior: Platform.isLinux ? const DragCupertinoScrollBevahior() : null,
), routes: routes,
scrollBehavior: Platform.isLinux ? const DragCupertinoScrollBevahior() : null, ),
routes: routes,
),
);
}
); );
} }
else if (uiDesign == UiDesign.FLUENT) { else if (uiDesign == UiDesign.FLUENT) {
return DynamicColorBuilder( return f.FluentApp(
builder: (lightScheme, darkScheme) { title: appTitle,
return f.FluentApp( theme: f.ThemeData(
title: appTitle, brightness: f.Brightness.dark,
theme: f.FluentThemeData( accentColor: f.Colors.blue,
brightness: f.Brightness.light, ),
accentColor: lightScheme != null ? f.AccentColor.swatch({ routes: routes,
'normal': lightScheme.primary, scrollBehavior: Platform.isLinux ? const DragFluentScrollBevahior() : const f.FluentScrollBehavior(),
}) : 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(),
);
}
); );
} }
else { else {
return DynamicColorBuilder( return m.MaterialApp(
builder: (lightScheme, darkScheme) { title: appTitle,
lightScheme ??= m.ColorScheme.fromSwatch( theme: m.ThemeData(
brightness: m.Brightness.light, primarySwatch: m.Colors.blue,
primarySwatch: m.Colors.blue, colorScheme: m.ColorScheme.fromSwatch(
);
darkScheme ??= m.ColorScheme.fromSwatch(
brightness: m.Brightness.dark, brightness: m.Brightness.dark,
primarySwatch: m.Colors.blue, primarySwatch: m.Colors.blue,
); accentColor: m.Colors.blue.shade700,
),
useMaterial3: true,
return m.MaterialApp( // fontFamily: 'Atkinson Hyperlegible',
title: appTitle, ),
theme: m.ThemeData( scrollBehavior: Platform.isLinux ? const DragMaterialScrollBevahior() : null,
colorScheme: lightScheme, routes: routes,
useMaterial3: true,
// fontFamily: 'Atkinson Hyperlegible',
),
darkTheme: m.ThemeData(
colorScheme: darkScheme,
useMaterial3: true,
// fontFamily: 'Atkinson Hyperlegible',
),
scrollBehavior: Platform.isLinux ? const DragMaterialScrollBevahior() : null,
routes: routes,
);
}
); );
} }
} }

7
lib/models.dart

@ -4,11 +4,10 @@ export 'package:info_tren/models/station_data.dart';
export 'package:info_tren/models/station_status.dart'; export 'package:info_tren/models/station_status.dart';
export 'package:info_tren/models/station_train.dart'; export 'package:info_tren/models/station_train.dart';
export 'package:info_tren/models/stations_result.dart'; export 'package:info_tren/models/stations_result.dart';
export 'package:info_tren/models/train_data.dart'; export 'package:info_tren/models/train_data.dart' hide State;
export 'package:info_tren/models/trains_result.dart'; export 'package:info_tren/models/trains_result.dart';
export 'package:info_tren/models/ui_design.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; import 'package:info_tren/models/train_data.dart' show State;
typedef TrainDataState = TrainDataStatusState; typedef TrainDataState = State;

2
lib/models/station_arrdep.freezed.dart

@ -1,7 +1,7 @@
// coverage:ignore-file // coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND // GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint // 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 // 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
part of 'station_arrdep.dart'; part of 'station_arrdep.dart';

4
lib/models/station_data.freezed.dart

@ -1,7 +1,7 @@
// coverage:ignore-file // coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND // GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint // 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 // 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
part of 'station_data.dart'; part of 'station_data.dart';
@ -158,7 +158,6 @@ class _$_StationData implements _StationData {
List<StationArrDep>? get arrivals { List<StationArrDep>? get arrivals {
final value = _arrivals; final value = _arrivals;
if (value == null) return null; if (value == null) return null;
if (_arrivals is EqualUnmodifiableListView) return _arrivals;
// ignore: implicit_dynamic_type // ignore: implicit_dynamic_type
return EqualUnmodifiableListView(value); return EqualUnmodifiableListView(value);
} }
@ -168,7 +167,6 @@ class _$_StationData implements _StationData {
List<StationArrDep>? get departures { List<StationArrDep>? get departures {
final value = _departures; final value = _departures;
if (value == null) return null; if (value == null) return null;
if (_departures is EqualUnmodifiableListView) return _departures;
// ignore: implicit_dynamic_type // ignore: implicit_dynamic_type
return EqualUnmodifiableListView(value); return EqualUnmodifiableListView(value);
} }

2
lib/models/station_status.freezed.dart

@ -1,7 +1,7 @@
// coverage:ignore-file // coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND // GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint // 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 // 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
part of 'station_status.dart'; part of 'station_status.dart';

3
lib/models/station_train.freezed.dart

@ -1,7 +1,7 @@
// coverage:ignore-file // coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND // GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint // 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 // 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
part of 'station_train.dart'; part of 'station_train.dart';
@ -189,7 +189,6 @@ class _$_StationTrain implements _StationTrain {
List<String>? get route { List<String>? get route {
final value = _route; final value = _route;
if (value == null) return null; if (value == null) return null;
if (_route is EqualUnmodifiableListView) return _route;
// ignore: implicit_dynamic_type // ignore: implicit_dynamic_type
return EqualUnmodifiableListView(value); return EqualUnmodifiableListView(value);
} }

3
lib/models/stations_result.freezed.dart

@ -1,7 +1,7 @@
// coverage:ignore-file // coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND // GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint // 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 // 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
part of 'stations_result.dart'; part of 'stations_result.dart';
@ -121,7 +121,6 @@ class _$_StationsResult implements _StationsResult {
List<String>? get stoppedAtBy { List<String>? get stoppedAtBy {
final value = _stoppedAtBy; final value = _stoppedAtBy;
if (value == null) return null; if (value == null) return null;
if (_stoppedAtBy is EqualUnmodifiableListView) return _stoppedAtBy;
// ignore: implicit_dynamic_type // ignore: implicit_dynamic_type
return EqualUnmodifiableListView(value); return EqualUnmodifiableListView(value);
} }

373
lib/models/train_data.dart

@ -4,118 +4,181 @@
import 'dart:convert'; 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)); TrainData trainDataFromJson(String str) => TrainData.fromJson(json.decode(str));
String trainDataToJson(TrainData data) => json.encode(data.toJson()); String trainDataToJson(TrainData data) => json.encode(data.toJson());
/// Results of scrapping InfoFer website for train info /// Results of scrapping InfoFer website for train info
@freezed class TrainData {
class TrainData with _$TrainData { TrainData({
const TrainData._(); required this.date,
required this.number,
const factory TrainData({ required this.operator,
required String rank, required this.rank,
required String number, required this.route,
required String date, required this.stations,
required String operator, this.status,
required List<TrainDataGroup> groups, });
}) = _TrainData;
final String date;
factory TrainData.fromJson(Map<String, dynamic> json) => _$TrainDataFromJson(json); final String number;
final String operator;
TrainDataGroup get idealGroup { final String rank;
var result = groups.first; final Route route;
final List<Station> stations;
for (final group in groups) { final TrainDataStatus? status;
if (result.stations.map((s) => s.linkName).toSet().difference(group.stations.map((s) => s.linkName).toSet()).isEmpty) {
result = group; factory TrainData.fromJson(Map<String, dynamic> json) => TrainData(
} date: json["date"],
} number: json["number"],
operator: json["operator"],
return result; rank: json["rank"],
} route: Route.fromJson(json["route"]),
stations: List<Station>.from(
List<TrainDataStation> get stations => idealGroup.stations; json["stations"].map((x) => Station.fromJson(x))),
TrainDataRoute get route => idealGroup.route; status: json["status"] == null
TrainDataStatus? get status => idealGroup.status; ? null
} : TrainDataStatus.fromJson(json["status"]),
);
@freezed Map<String, dynamic> toJson() => {
class TrainDataGroup with _$TrainDataGroup { "date": date,
const factory TrainDataGroup({ "number": number,
required TrainDataRoute route, "operator": operator,
required List<TrainDataStation> stations, "rank": rank,
TrainDataStatus? status, "route": route.toJson(),
}) = _TrainDataGroup; "stations": List<dynamic>.from(stations.map((x) => x.toJson())),
"status": status?.toJson(),
factory TrainDataGroup.fromJson(Map<String, dynamic> json) => _$TrainDataGroupFromJson(json); };
} }
/// Route of the train /// Route of the train
@freezed class Route {
class TrainDataRoute with _$TrainDataRoute { Route({
const factory TrainDataRoute({ required this.from,
required String from, required this.to,
required String to, });
}) = _TrainDataRoute;
final String from;
factory TrainDataRoute.fromJson(Map<String, dynamic> json) => _$TrainDataRouteFromJson(json); 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 Station {
class TrainDataStation with _$TrainDataStation { Station({
const factory TrainDataStation({ this.arrival,
required String name, this.departure,
required String linkName, required this.km,
required int km, required this.name,
int? stoppingTime, this.platform,
String? platform, this.stoppingTime,
StationArrDepTime? arrival, });
StationArrDepTime? departure,
@TrainDataNoteConverter() final StationArrDepTime? arrival;
required List<TrainDataNote> notes, final StationArrDepTime? departure;
}) = _TrainDataStation; final int km;
final String name;
factory TrainDataStation.fromJson(Map<String, dynamic> json) => _$TrainDataStationFromJson(json); 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"],
stoppingTime:
json["stoppingTime"],
);
Map<String, dynamic> toJson() => {
"arrival": arrival?.toJson(),
"departure": departure?.toJson(),
"km": km,
"name": name,
"platform": platform,
"stoppingTime": stoppingTime,
};
} }
@freezed class StationArrDepTime {
class StationArrDepTime with _$StationArrDepTime { StationArrDepTime({
const factory StationArrDepTime({ required this.scheduleTime,
required DateTime scheduleTime, this.status,
StationArrDepTimeStatus? status, });
}) = _StationArrDepTime;
final DateTime scheduleTime;
final StationArrDepTimeStatus? status;
factory StationArrDepTime.fromJson(Map<String, dynamic> json) => _$StationArrDepTimeFromJson(json); factory StationArrDepTime.fromJson(Map<String, dynamic> json) =>
StationArrDepTime(
scheduleTime: DateTime.parse(json["scheduleTime"] as String),
status: json["status"] == null ? null : StationArrDepTimeStatus.fromJson(json["status"]),
);
Map<String, dynamic> toJson() => {
"scheduleTime": scheduleTime.toIso8601String(),
"status": status?.toJson(),
};
} }
@freezed class StationArrDepTimeStatus {
class StationArrDepTimeStatus with _$StationArrDepTimeStatus { StationArrDepTimeStatus({
const factory StationArrDepTimeStatus({ required this.delay,
required int delay, required this.real,
required bool real, });
required bool cancelled,
}) = _StationArrDepTimeStatus; final int delay;
final bool real;
factory StationArrDepTimeStatus.fromJson(Map<String, dynamic> json) =>
StationArrDepTimeStatus(
delay: json["delay"],
real: json["real"],
);
factory StationArrDepTimeStatus.fromJson(Map<String, dynamic> json) => _$StationArrDepTimeStatusFromJson(json); Map<String, dynamic> toJson() => {
"delay": delay,
"real": real,
};
} }
@freezed class TrainDataStatus {
class TrainDataStatus with _$TrainDataStatus { TrainDataStatus({
const TrainDataStatus._(); required this.delay,
required this.state,
required this.station,
});
final int delay;
final State state;
final String station;
const factory TrainDataStatus({ factory TrainDataStatus.fromJson(Map<String, dynamic> json) =>
required int delay, TrainDataStatus(
required String station, delay: json["delay"],
required TrainDataStatusState state, state: stateValues.map[json["state"]]!,
}) = _TrainDataStatus; station: json["station"],
);
factory TrainDataStatus.fromJson(Map<String, dynamic> json) => _$TrainDataStatusFromJson(json); Map<String, dynamic> toJson() => {
"delay": delay,
"state": stateValues.reverse[state],
"station": station,
};
@override @override
String toString() { String toString() {
@ -127,118 +190,38 @@ class TrainDataStatus with _$TrainDataStatus {
result += '${delay.abs()} min'; result += '${delay.abs()} min';
} }
result += ' la '; result += ' la ';
result += switch (state) { switch (state) {
TrainDataStatusState.passing => 'trecerea fără oprire prin', case State.PASSING:
TrainDataStatusState.arrival => 'sosirea în', result += 'trecerea fără oprire prin';
TrainDataStatusState.departure => 'plecarea din', break;
}; case State.ARRIVAL:
result += 'sosirea în';
break;
case State.DEPARTURE:
result += 'plecarea din';
break;
}
result += station; result += station;
return result; return result;
} }
} }
enum TrainDataStatusState { passing, arrival, departure } enum State { PASSING, ARRIVAL, DEPARTURE }
abstract class TrainDataNote { final stateValues = EnumValues({
final String kind; "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() => { EnumValues(this.map);
"kind": kind,
};
}
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<T, String> get reverse {
Map<String, dynamic> toJson(TrainDataNote object) { reverseMap ??= map.map((k, v) => MapEntry(v, k));
return object.toJson(); 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'),
);
}

2365
lib/models/train_data.freezed.dart

File diff suppressed because it is too large Load Diff

217
lib/models/train_data.g.dart

@ -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,
};

2
lib/models/trains_result.freezed.dart

@ -1,7 +1,7 @@
// coverage:ignore-file // coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND // GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint // 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 // 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
part of 'trains_result.dart'; part of 'trains_result.dart';

94
lib/models/ui_timezone.dart

@ -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
lib/pages/settings/setings_page.dart

@ -31,7 +31,6 @@ class SettingsPage extends ConsumerWidget {
abstract class SettingsPageShared extends StatelessWidget { abstract class SettingsPageShared extends StatelessWidget {
final String pageTitle = 'Setări'; final String pageTitle = 'Setări';
final String appearanceTitle = 'Aspect'; final String appearanceTitle = 'Aspect';
final String timeZoneTitle = 'Fus orar';
const SettingsPageShared({super.key}); const SettingsPageShared({super.key});

21
lib/pages/settings/settings_page_cupertino.dart

@ -1,5 +1,6 @@
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:info_tren/components/cupertino_listtile.dart';
import 'package:info_tren/models.dart'; import 'package:info_tren/models.dart';
import 'package:info_tren/pages/settings/setings_page.dart'; import 'package:info_tren/pages/settings/setings_page.dart';
import 'package:info_tren/providers.dart'; import 'package:info_tren/providers.dart';
@ -66,26 +67,6 @@ class SettingsPageCupertino extends SettingsPageShared {
); );
}, },
), ),
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'));
}
},
);
},
),
], ],
), ),
); );

23
lib/pages/settings/settings_page_fluent.dart

@ -34,29 +34,6 @@ class SettingsPageFluent extends SettingsPageShared {
); );
}, },
), ),
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);
}
},
),
);
},
),
], ],
), ),
), ),

23
lib/pages/settings/settings_page_material.dart

@ -35,29 +35,6 @@ class SettingsPageMaterial extends SettingsPageShared {
); );
}, },
), ),
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);
}
},
),
);
},
),
], ],
), ),
), ),

3
lib/pages/station_arrdep_page/view_station/view_station.dart

@ -43,9 +43,8 @@ class ViewStationPage extends HookConsumerWidget {
class ViewStationArguments { class ViewStationArguments {
final String stationName; final String stationName;
final DateTime? date;
const ViewStationArguments({required this.stationName, this.date}); const ViewStationArguments({required this.stationName});
} }
abstract class ViewStationPageShared extends StatelessWidget { abstract class ViewStationPageShared extends StatelessWidget {

43
lib/pages/station_arrdep_page/view_station/view_station_cupertino.dart

@ -3,7 +3,6 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:info_tren/components/loading/loading.dart'; import 'package:info_tren/components/loading/loading.dart';
import 'package:info_tren/components/refresh_future_builder.dart'; import 'package:info_tren/components/refresh_future_builder.dart';
import 'package:info_tren/components/sliver_persistent_header_padding.dart'; import 'package:info_tren/components/sliver_persistent_header_padding.dart';
import 'package:info_tren/components/train_id_text_span.dart';
import 'package:info_tren/models.dart'; import 'package:info_tren/models.dart';
import 'package:info_tren/pages/station_arrdep_page/view_station/view_station.dart'; import 'package:info_tren/pages/station_arrdep_page/view_station/view_station.dart';
import 'package:info_tren/providers.dart'; import 'package:info_tren/providers.dart';
@ -67,7 +66,18 @@ class ViewStationPageCupertino extends ViewStationPageShared {
onTap: () => onTrainTapped(context, item.train), onTap: () => onTrainTapped(context, item.train),
child: CupertinoFormRow( child: CupertinoFormRow(
prefix: Text.rich( prefix: Text.rich(
trainIdSpan(rank: item.train.rank, number: item.train.number), TextSpan(
children: [
TextSpan(
text: item.train.rank,
style: TextStyle(
color: item.train.rank.startsWith('IR') ? const Color.fromARGB(255, 255, 0, 0) : null,
),
),
const TextSpan(text: ' '),
TextSpan(text: item.train.number,),
],
),
), ),
helper: Text.rich( helper: Text.rich(
TextSpan( TextSpan(
@ -78,13 +88,7 @@ class ViewStationPageCupertino extends ViewStationPageShared {
], ],
), ),
), ),
child: Consumer( child: Text('${item.time.toLocal().hour.toString().padLeft(2, '0')}:${item.time.toLocal().minute.toString().padLeft(2, '0')}'),
builder: (context, ref, _) {
final tz = ref.watch(uiTimeZoneProvider);
final time = tz.convertDateTime(item.time);
return Text('${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}');
},
),
), ),
); );
} }
@ -95,7 +99,18 @@ class ViewStationPageCupertino extends ViewStationPageShared {
onTap: () => onTrainTapped(context, item.train), onTap: () => onTrainTapped(context, item.train),
child: CupertinoFormRow( child: CupertinoFormRow(
prefix: Text.rich( prefix: Text.rich(
trainIdSpan(rank: item.train.rank, number: item.train.number), TextSpan(
children: [
TextSpan(
text: item.train.rank,
style: TextStyle(
color: item.train.rank.startsWith('IR') ? const Color.fromARGB(255, 255, 0, 0) : null,
),
),
const TextSpan(text: ' '),
TextSpan(text: item.train.number,),
],
),
), ),
helper: Text.rich( helper: Text.rich(
TextSpan( TextSpan(
@ -106,13 +121,7 @@ class ViewStationPageCupertino extends ViewStationPageShared {
], ],
), ),
), ),
child: Consumer( child: Text('${item.time.toLocal().hour.toString().padLeft(2, '0')}:${item.time.toLocal().minute.toString().padLeft(2, '0')}'),
builder: (context, ref, _) {
final tz = ref.watch(uiTimeZoneProvider);
final time = tz.convertDateTime(item.time);
return Text('${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}');
},
),
), ),
); );
} }

49
lib/pages/station_arrdep_page/view_station/view_station_fluent.dart

@ -6,7 +6,6 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:info_tren/components/badge/badge.dart'; import 'package:info_tren/components/badge/badge.dart';
import 'package:info_tren/components/loading/loading.dart'; import 'package:info_tren/components/loading/loading.dart';
import 'package:info_tren/components/refresh_future_builder.dart'; import 'package:info_tren/components/refresh_future_builder.dart';
import 'package:info_tren/components/train_id_text_span.dart';
import 'package:info_tren/models.dart'; import 'package:info_tren/models.dart';
import 'package:info_tren/pages/station_arrdep_page/view_station/view_station.dart'; import 'package:info_tren/pages/station_arrdep_page/view_station/view_station.dart';
import 'package:info_tren/providers.dart'; import 'package:info_tren/providers.dart';
@ -142,31 +141,24 @@ class ViewStationPageFluent extends ViewStationPageShared {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
Consumer( Text(
builder: (context, ref, _) { '${item.time.toLocal().hour.toString().padLeft(2, '0')}:${item.time.toLocal().minute.toString().padLeft(2, '0')}',
final tz = ref.watch(uiTimeZoneProvider); style: TextStyle(
final time = tz.convertDateTime(item.time); inherit: true,
return Text( fontFeatures: const [
'${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}', FontFeature.tabularFigures(),
style: TextStyle( ],
inherit: true, decoration: item.status.cancelled || item.status.delay != 0 ? TextDecoration.lineThrough : null,
fontFeatures: const [ fontSize: item.status.delay != 0 ? 12 : null,
FontFeature.tabularFigures(), ),
],
decoration: item.status.cancelled || item.status.delay != 0 ? TextDecoration.lineThrough : null,
fontSize: item.status.delay != 0 ? 12 : null,
),
);
},
), ),
if (item.status.delay != 0) Consumer( if (item.status.delay != 0) Builder(
builder: (context, ref, _) { builder: (context) {
final tz = ref.watch(uiTimeZoneProvider); final newTime = item.time.add(Duration(minutes: item.status.delay));
final newTime = tz.convertDateTime(item.time.add(Duration(minutes: item.status.delay)));
final delay = item.status.delay > 0; final delay = item.status.delay > 0;
return Text( return Text(
'${newTime.hour.toString().padLeft(2, '0')}:${newTime.minute.toString().padLeft(2, '0')}', '${newTime.toLocal().hour.toString().padLeft(2, '0')}:${newTime.toLocal().minute.toString().padLeft(2, '0')}',
style: TextStyle( style: TextStyle(
inherit: true, inherit: true,
fontFeatures: const [ fontFeatures: const [
@ -185,7 +177,18 @@ class ViewStationPageFluent extends ViewStationPageShared {
child: ListTile( child: ListTile(
// isThreeLine: item.status.delay != 0, // isThreeLine: item.status.delay != 0,
title: Text.rich( title: Text.rich(
trainIdSpan(rank: item.train.rank, number: item.train.number), TextSpan(
children: [
TextSpan(
text: item.train.rank,
style: TextStyle(
color: item.train.rank.startsWith('IR') ? const Color.fromARGB(255, 255, 0, 0) : null,
),
),
const TextSpan(text: ' '),
TextSpan(text: item.train.number,),
],
),
), ),
subtitle: Text.rich( subtitle: Text.rich(
TextSpan( TextSpan(

51
lib/pages/station_arrdep_page/view_station/view_station_material.dart

@ -1,11 +1,10 @@
import 'dart:math'; import 'dart:math';
import 'dart:ui'; import 'dart:ui';
import 'package:flutter/material.dart' hide Badge; import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:info_tren/components/badge/badge.dart'; import 'package:info_tren/components/badge/badge.dart';
import 'package:info_tren/components/loading/loading.dart'; import 'package:info_tren/components/loading/loading.dart';
import 'package:info_tren/components/refresh_future_builder.dart'; import 'package:info_tren/components/refresh_future_builder.dart';
import 'package:info_tren/components/train_id_text_span.dart';
import 'package:info_tren/models.dart'; import 'package:info_tren/models.dart';
import 'package:info_tren/pages/station_arrdep_page/view_station/view_station.dart'; import 'package:info_tren/pages/station_arrdep_page/view_station/view_station.dart';
import 'package:info_tren/providers.dart'; import 'package:info_tren/providers.dart';
@ -107,31 +106,24 @@ class ViewStationPageMaterial extends ViewStationPageShared {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
Consumer( Text(
builder: (context, ref, _) { '${item.time.toLocal().hour.toString().padLeft(2, '0')}:${item.time.toLocal().minute.toString().padLeft(2, '0')}',
final tz = ref.watch(uiTimeZoneProvider); style: TextStyle(
final time = tz.convertDateTime(item.time); inherit: true,
return Text( fontFeatures: const [
'${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}', FontFeature.tabularFigures(),
style: TextStyle( ],
inherit: true, decoration: item.status.cancelled || item.status.delay != 0 ? TextDecoration.lineThrough : null,
fontFeatures: const [ fontSize: item.status.delay != 0 ? 12 : null,
FontFeature.tabularFigures(), ),
],
decoration: item.status.cancelled || item.status.delay != 0 ? TextDecoration.lineThrough : null,
fontSize: item.status.delay != 0 ? 12 : null,
),
);
},
), ),
if (item.status.delay != 0) Consumer( if (item.status.delay != 0) Builder(
builder: (context, ref, _) { builder: (context) {
final tz = ref.watch(uiTimeZoneProvider); final newTime = item.time.add(Duration(minutes: item.status.delay));
final newTime = tz.convertDateTime(item.time.add(Duration(minutes: item.status.delay)));
final delay = item.status.delay > 0; final delay = item.status.delay > 0;
return Text( return Text(
'${newTime.hour.toString().padLeft(2, '0')}:${newTime.minute.toString().padLeft(2, '0')}', '${newTime.toLocal().hour.toString().padLeft(2, '0')}:${newTime.toLocal().minute.toString().padLeft(2, '0')}',
style: TextStyle( style: TextStyle(
inherit: true, inherit: true,
fontFeatures: const [ fontFeatures: const [
@ -150,7 +142,18 @@ class ViewStationPageMaterial extends ViewStationPageShared {
child: ListTile( child: ListTile(
isThreeLine: item.status.delay != 0, isThreeLine: item.status.delay != 0,
title: Text.rich( title: Text.rich(
trainIdSpan(rank: item.train.rank, number: item.train.number), TextSpan(
children: [
TextSpan(
text: item.train.rank,
style: TextStyle(
color: item.train.rank.startsWith('IR') ? const Color.fromARGB(255, 255, 0, 0) : null,
),
),
const TextSpan(text: ' '),
TextSpan(text: item.train.number,),
],
),
), ),
subtitle: Text.rich( subtitle: Text.rich(
TextSpan( TextSpan(

111
lib/pages/train_info_page/view_train/train_info.dart

@ -1,7 +1,4 @@
import 'dart:async';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:info_tren/api/train_data.dart'; import 'package:info_tren/api/train_data.dart';
import 'package:info_tren/components/loading/loading.dart'; import 'package:info_tren/components/loading/loading.dart';
@ -12,93 +9,59 @@ import 'package:info_tren/pages/train_info_page/view_train/train_info_fluent.dar
import 'package:info_tren/pages/train_info_page/view_train/train_info_material.dart'; import 'package:info_tren/pages/train_info_page/view_train/train_info_material.dart';
import 'package:info_tren/providers.dart'; import 'package:info_tren/providers.dart';
class TrainInfo extends HookConsumerWidget {
class TrainInfo extends ConsumerWidget {
static String routeName = "/trainInfo/display"; static String routeName = "/trainInfo/display";
const TrainInfo({ const TrainInfo({super.key,});
super.key,
});
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final uiDesign = ref.watch(uiDesignProvider); final uiDesign = ref.watch(uiDesignProvider);
final args = ref.watch(trainInfoArgumentsProvider); final args = ref.watch(trainInfoArgumentsProvider);
final trainNumber = args.trainNumber; final trainNumber = args.trainNumber;
final viewYesterday = useState(false); final date = args.date;
final date = args.date ??
DateTime.now().copyWith(
hour: 12,
minute: 0,
second: 0,
millisecond: 0,
microsecond: 0,
);
final requestDate =
viewYesterday.value ? date.subtract(const Duration(days: 1)) : date;
final trainDataAsync = ref
.watch(trainInfoProvider(trainNumber: trainNumber, date: requestDate));
Future refresh() async {
ref.invalidate(
trainInfoProvider(trainNumber: trainNumber, date: requestDate),
);
await Future.delayed(const Duration(seconds: 1));
}
void onViewYesterdayTrain() { return RefreshFutureBuilder<TrainData>(
viewYesterday.value = !viewYesterday.value; futureCreator: () => getTrain(trainNumber, date: date),
} builder: (context, refresh, replaceFutureBuilder, snapshot) {
void onViewYesterdayTrain() {
replaceFutureBuilder(() => getTrain(trainNumber, date: DateTime.now().subtract(const Duration(days: 1))));
}
if ([RefreshFutureBuilderState.none, RefreshFutureBuilderState.waiting].contains(snapshot.state)) {
return TrainInfoLoading(title: trainNumber.toString(), loadingText: "Se încarcă...",);
}
else if (snapshot.state == RefreshFutureBuilderState.error) {
return TrainInfoError(title: '$trainNumber - Error', error: snapshot.error!, refresh: refresh,);
}
useEffect(() {
final handle = Timer.periodic(const Duration(minutes: 1), (timer) {
refresh();
});
return () {
handle.cancel();
};
});
return trainDataAsync.when(
data: (data) {
switch (uiDesign) { switch (uiDesign) {
case UiDesign.MATERIAL: case UiDesign.MATERIAL:
return TrainInfoMaterial( return TrainInfoMaterial(
trainData: data, trainData: snapshot.data!,
refresh: refresh, refresh: refresh,
isRefreshing: trainDataAsync.isRefreshing, isRefreshing: snapshot.state == RefreshFutureBuilderState.refreshing,
onViewYesterdayTrain: onViewYesterdayTrain, onViewYesterdayTrain: onViewYesterdayTrain,
); );
case UiDesign.CUPERTINO: case UiDesign.CUPERTINO:
return TrainInfoCupertino( return TrainInfoCupertino(
trainData: data, trainData: snapshot.data!,
refresh: refresh, refresh: refresh,
isRefreshing: trainDataAsync.isRefreshing, isRefreshing: snapshot.state == RefreshFutureBuilderState.refreshing,
onViewYesterdayTrain: onViewYesterdayTrain, onViewYesterdayTrain: onViewYesterdayTrain,
); );
case UiDesign.FLUENT: case UiDesign.FLUENT:
return TrainInfoFluent( return TrainInfoFluent(
trainData: data, trainData: snapshot.data!,
refresh: refresh, refresh: refresh,
isRefreshing: trainDataAsync.isRefreshing, isRefreshing: snapshot.state == RefreshFutureBuilderState.refreshing,
onViewYesterdayTrain: onViewYesterdayTrain, onViewYesterdayTrain: onViewYesterdayTrain,
); );
default: default:
throw UnmatchedUiDesignException(uiDesign); throw UnmatchedUiDesignException(uiDesign);
} }
}, },
error: (e, st) {
return TrainInfoError(
title: '$trainNumber - Error',
error: e,
refresh: refresh,
);
},
loading: () {
return TrainInfoLoading(
title: trainNumber.toString(),
loadingText: "Se încarcă...",
);
},
); );
} }
} }
@ -166,12 +129,10 @@ abstract class TrainInfoLoadingShared extends StatelessWidget {
final Widget loadingWidget; final Widget loadingWidget;
TrainInfoLoadingShared({ TrainInfoLoadingShared({
required this.title, required this.title,
String? loadingText, String? loadingText,
super.key, super.key,
}) : loadingWidget = Loading( }) : loadingWidget = Loading(text: loadingText,);
text: loadingText,
);
} }
class TrainInfoError extends ConsumerWidget { class TrainInfoError extends ConsumerWidget {
@ -220,12 +181,7 @@ abstract class TrainInfoErrorShared extends StatelessWidget {
final Object error; final Object error;
final Future Function()? refresh; final Future Function()? refresh;
const TrainInfoErrorShared({ const TrainInfoErrorShared({required this.title, required this.error, this.refresh, super.key,});
required this.title,
required this.error,
this.refresh,
super.key,
});
} }
class TrainInfoBody extends ConsumerWidget { class TrainInfoBody extends ConsumerWidget {
@ -290,15 +246,10 @@ abstract class TrainInfoBodyShared extends StatelessWidget {
} }
abstract class DisplayTrainYesterdayWarningCommon extends StatelessWidget { abstract class DisplayTrainYesterdayWarningCommon extends StatelessWidget {
static const trainDidNotDepart = static const trainDidNotDepart = 'Acest tren nu a plecat încă din prima gară.';
'Acest tren nu a plecat încă din prima gară.'; static const seeYesterdayTrain = 'Apasă aici pentru a vedea trenul care a plecat ieri.';
static const seeYesterdayTrain =
'Apasă aici pentru a vedea trenul care a plecat ieri.';
final void Function() onViewYesterdayTrain; final void Function() onViewYesterdayTrain;
const DisplayTrainYesterdayWarningCommon( const DisplayTrainYesterdayWarningCommon(this.onViewYesterdayTrain, {super.key,});
this.onViewYesterdayTrain, {
super.key,
});
} }

113
lib/pages/train_info_page/view_train/train_info_cupertino.dart

@ -4,7 +4,6 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'package:info_tren/components/cupertino_divider.dart'; import 'package:info_tren/components/cupertino_divider.dart';
import 'package:info_tren/components/sliver_persistent_header_padding.dart'; import 'package:info_tren/components/sliver_persistent_header_padding.dart';
import 'package:info_tren/components/train_id_text_span.dart';
import 'package:info_tren/models.dart'; import 'package:info_tren/models.dart';
import 'package:info_tren/pages/train_info_page/train_info_constants.dart'; import 'package:info_tren/pages/train_info_page/train_info_constants.dart';
import 'package:info_tren/pages/train_info_page/view_train/train_info.dart'; import 'package:info_tren/pages/train_info_page/view_train/train_info.dart';
@ -215,62 +214,59 @@ class TrainInfoBodyCupertino extends TrainInfoBodyShared {
return Row( return Row(
mainAxisSize: MainAxisSize.max, mainAxisSize: MainAxisSize.max,
children: [ children: [
SafeArea( Container(
right: false, constraints: const BoxConstraints(
child: Container( minWidth: 400,
constraints: const BoxConstraints( maxWidth: 400,
minWidth: 400, ),
maxWidth: 400, child: Column(
), mainAxisSize: MainAxisSize.max,
child: Column( children: [
mainAxisSize: MainAxisSize.max, DisplayTrainID(trainData: trainData),
children: [ DisplayTrainOperator(trainData: trainData),
DisplayTrainID(trainData: trainData), DisplayTrainRoute(trainData: trainData),
DisplayTrainOperator(trainData: trainData), DisplayTrainDeparture(trainData: trainData),
DisplayTrainRoute(trainData: trainData), const CupertinoDivider(
DisplayTrainDeparture(trainData: trainData), color: foregroundWhite,
const CupertinoDivider( ),
color: foregroundWhite, DisplayTrainLastInfo(trainData: trainData),
), const CupertinoDivider(),
DisplayTrainLastInfo(trainData: trainData), IntrinsicHeight(
const CupertinoDivider(), child: Row(
IntrinsicHeight( children: <Widget>[
child: Row( // Expanded(
children: <Widget>[ // child: DisplayTrainNextStop(trainData: trainData,),
// Expanded( // ),
// child: DisplayTrainNextStop(trainData: trainData,), Expanded(
// ), child: DisplayTrainRouteDuration(
Expanded( trainData: trainData,
child: DisplayTrainRouteDuration(
trainData: trainData,
),
),
// Expanded(
// child: DisplayTrainDestination(trainData: trainData,),
// ),
const SizedBox(
height: double.infinity,
child: CupertinoVerticalDivider(),
), ),
Expanded( ),
child: DisplayTrainRouteDistance( // Expanded(
trainData: trainData, // child: DisplayTrainDestination(trainData: trainData,),
), // ),
const SizedBox(
height: double.infinity,
child: CupertinoVerticalDivider(),
),
Expanded(
child: DisplayTrainRouteDistance(
trainData: trainData,
), ),
], ),
), ],
), ),
),
const CupertinoDivider(
color: foregroundWhite,
),
if (onViewYesterdayTrain != null && trainData.stations.first.departure!.scheduleTime.compareTo(DateTime.now()) > 0) ...[
DisplayTrainYesterdayWarningCupertino(onViewYesterdayTrain!),
const CupertinoDivider( const CupertinoDivider(
color: foregroundWhite, color: foregroundWhite,
), ),
if (onViewYesterdayTrain != null && trainData.stations.first.departure!.scheduleTime.compareTo(DateTime.now()) > 0) ...[
DisplayTrainYesterdayWarningCupertino(onViewYesterdayTrain!),
const CupertinoDivider(
color: foregroundWhite,
),
],
], ],
), ],
), ),
), ),
Expanded( Expanded(
@ -563,7 +559,18 @@ class DisplayTrainID extends StatelessWidget {
child: Padding( child: Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: Text.rich( child: Text.rich(
trainIdSpan(rank: trainData.rank, number: trainData.number), TextSpan(
children: [
TextSpan(
text: trainData.rank,
style: TextStyle(
color: trainData.rank.startsWith('IR') ? const Color.fromARGB(255, 255, 0, 0) : null,
),
),
const TextSpan(text: ' '),
TextSpan(text: trainData.number,),
],
),
style: CupertinoTheme.of(context).textTheme.navLargeTitleTextStyle, style: CupertinoTheme.of(context).textTheme.navLargeTitleTextStyle,
), ),
), ),
@ -1051,8 +1058,8 @@ class DisplayTrainYesterdayWarningCupertino extends DisplayTrainYesterdayWarning
const TextSpan(text: '\n'), const TextSpan(text: '\n'),
TextSpan( TextSpan(
text: DisplayTrainYesterdayWarningCommon.seeYesterdayTrain, text: DisplayTrainYesterdayWarningCommon.seeYesterdayTrain,
style: TextStyle( style: const TextStyle(
color: CupertinoTheme.of(context).primaryColor, color: CupertinoColors.link,
), ),
recognizer: TapGestureRecognizer() recognizer: TapGestureRecognizer()
..onTap = onViewYesterdayTrain, ..onTap = onViewYesterdayTrain,

332
lib/pages/train_info_page/view_train/train_info_cupertino_DisplayTrainStation.dart

@ -1,18 +1,11 @@
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:info_tren/components/badge/badge.dart'; import 'package:info_tren/components/badge/badge.dart';
import 'package:info_tren/components/cupertino_divider.dart';
import 'package:info_tren/components/train_id_text_span.dart';
import 'package:info_tren/models.dart'; import 'package:info_tren/models.dart';
import 'package:info_tren/providers.dart';
class DisplayTrainStation extends StatelessWidget { class DisplayTrainStation extends StatelessWidget {
final TrainDataStation station; final Station station;
const DisplayTrainStation({ const DisplayTrainStation({required this.station, super.key,});
required this.station,
super.key,
});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -20,26 +13,6 @@ class DisplayTrainStation extends StatelessWidget {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[ children: <Widget>[
if (station.notes.whereType<TrainDataNoteDepartsAs>().isNotEmpty) ...[
Builder(
builder: (context) {
final note =
station.notes.whereType<TrainDataNoteDepartsAs>().first;
return Padding(
padding: const EdgeInsets.all(2.0),
child: Text.rich(
TextSpan(
children: [
const TextSpan(text: 'Trenul pleacă cu numărul '),
trainIdSpan(rank: note.rank, number: note.number),
],
),
),
);
},
),
const CupertinoDivider(),
],
Row( Row(
mainAxisSize: MainAxisSize.max, mainAxisSize: MainAxisSize.max,
children: <Widget>[ children: <Widget>[
@ -47,38 +20,42 @@ class DisplayTrainStation extends StatelessWidget {
flex: 1, flex: 1,
child: Align( child: Align(
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
child: Builder(builder: (context) { child: Builder(
final departureStatus = station.departure?.status; builder: (context) {
final arrivalStatus = station.arrival?.status; final departureStatus = station.departure?.status;
int delay; final arrivalStatus = station.arrival?.status;
bool real; int delay;
if (departureStatus == null) { bool real;
delay = arrivalStatus?.delay ?? 0; if (departureStatus == null) {
real = arrivalStatus?.real ?? false; delay = arrivalStatus?.delay ?? 0;
} else if (arrivalStatus == null) { real = arrivalStatus?.real ?? false;
delay = departureStatus.delay; }
real = departureStatus.real; else if (arrivalStatus == null) {
} else { delay = departureStatus.delay;
delay = departureStatus.delay; real = departureStatus.real;
real = departureStatus.real;
if (!real && arrivalStatus.real) {
delay = arrivalStatus.delay;
real = arrivalStatus.real;
} }
else {
delay = departureStatus.delay;
real = departureStatus.real;
if (!real && arrivalStatus.real) {
delay = arrivalStatus.delay;
real = arrivalStatus.real;
}
}
final isDelayed = delay > 0 && real == true;
final isOnTime = delay <= 0 && real == true;
const isNotScheduled = false;
return Badge(
text: station.km.toString(),
caption: 'km',
isNotScheduled: isNotScheduled,
isDelayed: isDelayed,
isOnTime: isOnTime,
);
} }
),
final isDelayed = delay > 0 && real == true;
final isOnTime = delay <= 0 && real == true;
const isNotScheduled = false;
return Badge(
text: station.km.toString(),
caption: 'km',
isNotScheduled: isNotScheduled,
isDelayed: isDelayed,
isOnTime: isOnTime,
);
}),
), ),
), ),
Title( Title(
@ -88,9 +65,7 @@ class DisplayTrainStation extends StatelessWidget {
flex: 1, flex: 1,
child: Align( child: Align(
alignment: Alignment.centerRight, alignment: Alignment.centerRight,
child: station.platform == null child: station.platform == null ? Container() : Badge(text: station.platform!, caption: 'linia'),
? Container()
: Badge(text: station.platform!, caption: 'linia'),
), ),
), ),
], ],
@ -98,61 +73,16 @@ class DisplayTrainStation extends StatelessWidget {
Time( Time(
station: station, station: station,
), ),
if (station.notes.whereType<TrainDataNoteDetachingWagons>().isNotEmpty)
Builder(
builder: (context) {
final note =
station.notes.whereType<TrainDataNoteDetachingWagons>().first;
return Text(
'Trenul detașează vagoane către ${note.station}',
textAlign: TextAlign.center,
);
},
),
if (station.notes.whereType<TrainDataNoteReceivingWagons>().isNotEmpty)
Builder(
builder: (context) {
final note =
station.notes.whereType<TrainDataNoteReceivingWagons>().first;
return Text(
'Trenul primește vagoane de la ${note.station}',
textAlign: TextAlign.center,
);
},
),
Delay( Delay(
station: station, station: station,
), ),
if (station.notes
.whereType<TrainDataNoteTrainNumberChange>()
.isNotEmpty) ...[
const CupertinoDivider(),
Builder(
builder: (context) {
final note = station.notes
.whereType<TrainDataNoteTrainNumberChange>()
.first;
return Padding(
padding: const EdgeInsets.all(2.0),
child: Text.rich(
TextSpan(
children: [
const TextSpan(text: 'Trenul își schimbă numărul în '),
trainIdSpan(rank: note.rank, number: note.number),
],
),
),
);
},
),
],
], ],
); );
} }
} }
class Title extends StatelessWidget { class Title extends StatelessWidget {
final TrainDataStation station; final Station station;
const Title({ const Title({
required this.station, required this.station,
@ -164,19 +94,17 @@ class Title extends StatelessWidget {
return Text( return Text(
station.name, station.name,
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
fontSize: 22, fontSize: 22,
fontWeight: MediaQuery.of(context).boldText fontWeight: MediaQuery.of(context).boldText ? FontWeight.w500 : FontWeight.w300,
? FontWeight.w500 // fontStyle: items[1] == "ONI" ? FontStyle.italic : FontStyle.normal,
: FontWeight.w300, ),
// fontStyle: items[1] == "ONI" ? FontStyle.italic : FontStyle.normal,
),
textAlign: TextAlign.center, textAlign: TextAlign.center,
); );
} }
} }
class Time extends StatelessWidget { class Time extends StatelessWidget {
final TrainDataStation station; final Station station;
const Time({ const Time({
required this.station, required this.station,
@ -207,43 +135,29 @@ class Time extends StatelessWidget {
Text( Text(
"", "",
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
fontSize: 22, fontSize: 22,
), ),
),
Container(
width: 2,
),
ArrivalTime(
station: station,
),
Expanded(
child: Container(),
),
StopTime(
station: station,
),
Expanded(
child: Container(),
),
DepartureTime(
station: station,
),
Container(
width: 2,
), ),
Container(width: 2,),
ArrivalTime(station: station,),
Expanded(child: Container(),),
StopTime(station: station,),
Expanded(child: Container(),),
DepartureTime(station: station,),
Container(width: 2,),
Text( Text(
"", "",
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
fontSize: 22, fontSize: 22,
), ),
), ),
], ],
); );
} }
} }
class ArrivalTime extends ConsumerWidget { class ArrivalTime extends StatelessWidget {
final TrainDataStation station; final Station station;
final bool finalStation; final bool finalStation;
const ArrivalTime({ const ArrivalTime({
@ -253,9 +167,7 @@ class ArrivalTime extends ConsumerWidget {
}); });
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context) {
final tz = ref.watch(uiTimeZoneProvider);
if (finalStation) { if (finalStation) {
return Row( return Row(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
@ -263,29 +175,24 @@ class ArrivalTime extends ConsumerWidget {
Text( Text(
"", "",
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
fontSize: 22, fontSize: 22,
), ),
),
Container(
width: 2,
), ),
Container(width: 2,),
const Text("sosire la "), const Text("sosire la "),
ArrivalTime( ArrivalTime(station: station,),
station: station, Expanded(child: Container(),),
),
Expanded(
child: Container(),
),
], ],
); );
} else { }
else {
final delay = station.arrival!.status?.delay ?? 0; final delay = station.arrival!.status?.delay ?? 0;
final time = tz.convertDateTime(station.arrival!.scheduleTime); final time = station.arrival!.scheduleTime.toLocal();
if (delay == 0) { if (delay == 0) {
return Text( return Text("${time.hour.toString().padLeft(2, "0")}:${time.minute.toString().padLeft(2, "0")}");
"${time.hour.toString().padLeft(2, "0")}:${time.minute.toString().padLeft(2, "0")}"); }
} else if (delay > 0) { else if (delay > 0) {
final oldDate = time; final oldDate = time;
final newDate = oldDate.add(Duration(minutes: delay)); final newDate = oldDate.add(Duration(minutes: delay));
@ -295,18 +202,19 @@ class ArrivalTime extends ConsumerWidget {
Text( Text(
"${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}", "${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}",
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
decoration: TextDecoration.lineThrough, decoration: TextDecoration.lineThrough,
), ),
), ),
Text( Text(
"${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}", "${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}",
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
color: CupertinoColors.destructiveRed, color: CupertinoColors.destructiveRed,
), ),
), ),
], ],
); );
} else { }
else {
final oldDate = time; final oldDate = time;
final newDate = oldDate.add(Duration(minutes: delay)); final newDate = oldDate.add(Duration(minutes: delay));
@ -316,14 +224,14 @@ class ArrivalTime extends ConsumerWidget {
Text( Text(
"${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}", "${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}",
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
decoration: TextDecoration.lineThrough, decoration: TextDecoration.lineThrough,
), ),
), ),
Text( Text(
"${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}", "${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}",
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
color: CupertinoColors.systemGreen, color: CupertinoColors.systemGreen,
), ),
), ),
], ],
); );
@ -333,7 +241,7 @@ class ArrivalTime extends ConsumerWidget {
} }
class StopTime extends StatelessWidget { class StopTime extends StatelessWidget {
final TrainDataStation station; final Station station;
const StopTime({ const StopTime({
required this.station, required this.station,
@ -363,12 +271,14 @@ class StopTime extends StatelessWidget {
minutes ? '1 minut' : '1 secundă', minutes ? '1 minut' : '1 secundă',
textAlign: TextAlign.center, textAlign: TextAlign.center,
); );
} else if (stopsForInt < 20) { }
else if (stopsForInt < 20) {
return Text( return Text(
'$stopsForInt ${minutes ? 'minute' : 'seconde'}', '$stopsForInt ${minutes ? 'minute' : 'seconde'}',
textAlign: TextAlign.center, textAlign: TextAlign.center,
); );
} else { }
else {
return Text( return Text(
'$stopsForInt de ${minutes ? 'minute' : 'secunde'}', '$stopsForInt de ${minutes ? 'minute' : 'secunde'}',
textAlign: TextAlign.center, textAlign: TextAlign.center,
@ -381,8 +291,8 @@ class StopTime extends StatelessWidget {
} }
} }
class DepartureTime extends ConsumerWidget { class DepartureTime extends StatelessWidget {
final TrainDataStation station; final Station station;
final bool firstStation; final bool firstStation;
const DepartureTime({ const DepartureTime({
@ -392,38 +302,32 @@ class DepartureTime extends ConsumerWidget {
}); });
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context) {
final tz = ref.watch(uiTimeZoneProvider);
if (firstStation) { if (firstStation) {
return Row( return Row(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[ children: <Widget>[
Expanded( Expanded(child: Container(),),
child: Container(),
),
const Text("plecare la "), const Text("plecare la "),
DepartureTime( DepartureTime(station: station,),
station: station, Container(width: 2,),
),
Container(
width: 2,
),
Text( Text(
"", "",
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
fontSize: 22, fontSize: 22,
), ),
), ),
], ],
); );
} else { }
else {
final delay = station.departure!.status?.delay ?? 0; final delay = station.departure!.status?.delay ?? 0;
final time = tz.convertDateTime(station.departure!.scheduleTime); final time = station.departure!.scheduleTime.toLocal();
if (delay == 0) { if (delay == 0) {
return Text( return Text("${time.hour.toString().padLeft(2, "0")}:${time.minute.toString().padLeft(2, "0")}");
"${time.hour.toString().padLeft(2, "0")}:${time.minute.toString().padLeft(2, "0")}"); }
} else if (delay > 0) { else if (delay > 0) {
final oldDate = time; final oldDate = time;
final newDate = oldDate.add(Duration(minutes: delay)); final newDate = oldDate.add(Duration(minutes: delay));
@ -433,18 +337,19 @@ class DepartureTime extends ConsumerWidget {
Text( Text(
"${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}", "${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}",
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
decoration: TextDecoration.lineThrough, decoration: TextDecoration.lineThrough,
), ),
), ),
Text( Text(
"${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}", "${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}",
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
color: CupertinoColors.destructiveRed, color: CupertinoColors.destructiveRed,
), ),
), ),
], ],
); );
} else { }
else {
final oldDate = time; final oldDate = time;
final newDate = oldDate.add(Duration(minutes: delay)); final newDate = oldDate.add(Duration(minutes: delay));
@ -454,14 +359,14 @@ class DepartureTime extends ConsumerWidget {
Text( Text(
"${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}", "${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}",
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
decoration: TextDecoration.lineThrough, decoration: TextDecoration.lineThrough,
), ),
), ),
Text( Text(
"${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}", "${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}",
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
color: CupertinoColors.systemGreen, color: CupertinoColors.systemGreen,
), ),
), ),
], ],
); );
@ -471,7 +376,7 @@ class DepartureTime extends ConsumerWidget {
} }
class Delay extends StatelessWidget { class Delay extends StatelessWidget {
final TrainDataStation station; final Station station;
const Delay({ const Delay({
required this.station, required this.station,
@ -494,19 +399,20 @@ class Delay extends StatelessWidget {
return Text( return Text(
"$delay ${delay == 1 ? 'minut' : 'minute'} întârziere", "$delay ${delay == 1 ? 'minut' : 'minute'} întârziere",
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
color: CupertinoColors.destructiveRed, color: CupertinoColors.destructiveRed,
fontSize: 14, fontSize: 14,
fontStyle: FontStyle.italic, fontStyle: FontStyle.italic,
), ),
); );
} else if (delay < 0) { }
else if (delay < 0) {
return Text( return Text(
"${-delay} ${delay == -1 ? 'minut' : 'minute'} mai devreme", "${-delay} ${delay == -1 ? 'minut' : 'minute'} mai devreme",
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
color: CupertinoColors.systemGreen, color: CupertinoColors.systemGreen,
fontSize: 14, fontSize: 14,
fontStyle: FontStyle.italic, fontStyle: FontStyle.italic,
), ),
); );
} }

20
lib/pages/train_info_page/view_train/train_info_fluent.dart

@ -1,6 +1,5 @@
import 'package:fluent_ui/fluent_ui.dart'; import 'package:fluent_ui/fluent_ui.dart';
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'package:info_tren/components/train_id_text_span.dart';
import 'package:info_tren/models.dart'; import 'package:info_tren/models.dart';
import 'package:info_tren/pages/station_arrdep_page/view_station/view_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/view_train/train_info.dart';
@ -304,7 +303,22 @@ class DisplayTrainID extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Text.rich( return Text.rich(
trainIdSpan(rank: trainData.rank, number: trainData.number), TextSpan(
children: [
TextSpan(
text: trainData.rank,
style: TextStyle(
color: trainData.rank.startsWith('IR')
? const Color.fromARGB(255, 255, 0, 0)
: null,
),
),
const TextSpan(text: ' '),
TextSpan(
text: trainData.number,
),
],
),
style: FluentTheme.of(context).typography.title?.copyWith( style: FluentTheme.of(context).typography.title?.copyWith(
color: FluentTheme.of(context).typography.body?.color, color: FluentTheme.of(context).typography.body?.color,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@ -748,7 +762,7 @@ class DisplayTrainYesterdayWarningFluent
TextSpan( TextSpan(
text: DisplayTrainYesterdayWarningCommon.seeYesterdayTrain, text: DisplayTrainYesterdayWarningCommon.seeYesterdayTrain,
style: TextStyle( style: TextStyle(
color: FluentTheme.of(context).accentColor,// Colors.blue, color: Colors.blue,
), ),
recognizer: TapGestureRecognizer() recognizer: TapGestureRecognizer()
..onTap = onViewYesterdayTrain, ..onTap = onViewYesterdayTrain,

368
lib/pages/train_info_page/view_train/train_info_fluent_DisplayTrainStation.dart

@ -1,62 +1,35 @@
import 'package:fluent_ui/fluent_ui.dart'; import 'package:fluent_ui/fluent_ui.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:info_tren/components/badge/badge.dart'; import 'package:info_tren/components/badge/badge.dart';
import 'package:info_tren/components/train_id_text_span.dart';
import 'package:info_tren/models.dart'; import 'package:info_tren/models.dart';
import 'package:info_tren/providers.dart';
class DisplayTrainStation extends StatelessWidget { class DisplayTrainStation extends StatelessWidget {
final TrainDataStation station; final Station station;
final void Function()? onTap; final void Function()? onTap;
const DisplayTrainStation({ const DisplayTrainStation({required this.station, this.onTap, super.key,});
required this.station,
this.onTap,
super.key,
});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Column( return Padding(
mainAxisSize: MainAxisSize.min, padding: const EdgeInsets.all(2),
children: [ child: HoverButton(
if (station.notes.whereType<TrainDataNoteDepartsAs>().isNotEmpty) onPressed: onTap,
Builder( builder: (context, states) {
builder: (context) { return Card(
final note = padding: const EdgeInsets.all(2),
station.notes.whereType<TrainDataNoteDepartsAs>().first; child: Column(
return Padding( mainAxisSize: MainAxisSize.min,
padding: const EdgeInsets.all(2.0), crossAxisAlignment: CrossAxisAlignment.center,
child: Text.rich( children: <Widget>[
TextSpan( Row(
children: [ mainAxisSize: MainAxisSize.max,
const TextSpan(text: 'Trenul pleacă cu numărul '),
trainIdSpan(rank: note.rank, number: note.number),
],
),
),
);
},
),
Padding(
padding: const EdgeInsets.all(2),
child: HoverButton(
onPressed: onTap,
builder: (context, states) {
return Card(
padding: const EdgeInsets.all(2),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[ children: <Widget>[
Row( Expanded(
mainAxisSize: MainAxisSize.max, flex: 1,
children: <Widget>[ child: Align(
Expanded( alignment: Alignment.centerLeft,
flex: 1, child: Builder(
child: Align( builder: (context) {
alignment: Alignment.centerLeft,
child: Builder(builder: (context) {
final departureStatus = station.departure?.status; final departureStatus = station.departure?.status;
final arrivalStatus = station.arrival?.status; final arrivalStatus = station.arrival?.status;
int delay; int delay;
@ -64,10 +37,12 @@ class DisplayTrainStation extends StatelessWidget {
if (departureStatus == null) { if (departureStatus == null) {
delay = arrivalStatus?.delay ?? 0; delay = arrivalStatus?.delay ?? 0;
real = arrivalStatus?.real ?? false; real = arrivalStatus?.real ?? false;
} else if (arrivalStatus == null) { }
else if (arrivalStatus == null) {
delay = departureStatus.delay; delay = departureStatus.delay;
real = departureStatus.real; real = departureStatus.real;
} else { }
else {
delay = departureStatus.delay; delay = departureStatus.delay;
real = departureStatus.real; real = departureStatus.real;
if (!real && arrivalStatus.real) { if (!real && arrivalStatus.real) {
@ -87,94 +62,41 @@ class DisplayTrainStation extends StatelessWidget {
isDelayed: isDelayed, isDelayed: isDelayed,
isOnTime: isOnTime, isOnTime: isOnTime,
); );
}), }
),
),
Title(
station: station,
),
Expanded(
flex: 1,
child: (station.platform == null)
? Container()
: Align(
alignment: Alignment.centerRight,
child: Badge(
text: station.platform!,
caption: 'linia',
),
),
), ),
], ),
), ),
Time( Title(
station: station, station: station,
), ),
if (station.notes Expanded(
.whereType<TrainDataNoteDetachingWagons>() flex: 1,
.isNotEmpty) child: (station.platform == null)
Builder( ? Container()
builder: (context) { : Align(
final note = station.notes alignment: Alignment.centerRight,
.whereType<TrainDataNoteDetachingWagons>() child: Badge(text: station.platform!, caption: 'linia',),
.first;
return Text(
'Trenul detașează vagoane către ${note.station}',
textAlign: TextAlign.center,
);
},
),
if (station.notes
.whereType<TrainDataNoteReceivingWagons>()
.isNotEmpty)
Builder(
builder: (context) {
final note = station.notes
.whereType<TrainDataNoteReceivingWagons>()
.first;
return Text(
'Trenul primește vagoane de la ${note.station}',
textAlign: TextAlign.center,
);
},
), ),
Delay(
station: station,
), ),
], ],
), ),
); Time(
}, station: station,
),
),
if (station.notes
.whereType<TrainDataNoteTrainNumberChange>()
.isNotEmpty)
Builder(
builder: (context) {
final note = station.notes
.whereType<TrainDataNoteTrainNumberChange>()
.first;
return Padding(
padding: const EdgeInsets.all(2.0),
child: Text.rich(
TextSpan(
children: [
const TextSpan(text: 'Trenul își schimbă numărul în '),
trainIdSpan(rank: note.rank, number: note.number),
],
),
), ),
); Delay(
}, station: station,
), ),
], ],
),
);
},
),
); );
} }
} }
class Title extends StatelessWidget { class Title extends StatelessWidget {
final TrainDataStation station; final Station station;
const Title({ const Title({
required this.station, required this.station,
@ -183,22 +105,20 @@ class Title extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Text( return Text(
station.name, station.name,
style: FluentTheme.of(context).typography.body?.copyWith( style: FluentTheme.of(context).typography.body?.copyWith(
fontSize: 22, fontSize: 22,
fontWeight: MediaQuery.of(context).boldText fontWeight: MediaQuery.of(context).boldText ? FontWeight.w500 : FontWeight.w300,
? FontWeight.w500 // fontStyle: items[1] == "ONI" ? FontStyle.italic : FontStyle.normal,
: FontWeight.w300, ),
// fontStyle: items[1] == "ONI" ? FontStyle.italic : FontStyle.normal,
),
textAlign: TextAlign.center, textAlign: TextAlign.center,
); );
} }
} }
class Time extends StatelessWidget { class Time extends StatelessWidget {
final TrainDataStation station; final Station station;
const Time({ const Time({
required this.station, required this.station,
@ -229,43 +149,29 @@ class Time extends StatelessWidget {
Text( Text(
"", "",
style: FluentTheme.of(context).typography.body?.copyWith( style: FluentTheme.of(context).typography.body?.copyWith(
fontSize: 22, fontSize: 22,
), ),
),
Container(
width: 2,
),
ArrivalTime(
station: station,
),
Expanded(
child: Container(),
),
StopTime(
station: station,
),
Expanded(
child: Container(),
),
DepartureTime(
station: station,
),
Container(
width: 2,
), ),
Container(width: 2,),
ArrivalTime(station: station,),
Expanded(child: Container(),),
StopTime(station: station,),
Expanded(child: Container(),),
DepartureTime(station: station,),
Container(width: 2,),
Text( Text(
"", "",
style: FluentTheme.of(context).typography.body?.copyWith( style: FluentTheme.of(context).typography.body?.copyWith(
fontSize: 22, fontSize: 22,
), ),
), ),
], ],
); );
} }
} }
class ArrivalTime extends ConsumerWidget { class ArrivalTime extends StatelessWidget {
final TrainDataStation station; final Station station;
final bool finalStation; final bool finalStation;
const ArrivalTime({ const ArrivalTime({
@ -275,8 +181,7 @@ class ArrivalTime extends ConsumerWidget {
}); });
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context) {
final tz = ref.watch(uiTimeZoneProvider);
if (station.arrival == null) { if (station.arrival == null) {
return Container(); return Container();
} }
@ -287,29 +192,24 @@ class ArrivalTime extends ConsumerWidget {
Text( Text(
"", "",
style: FluentTheme.of(context).typography.body?.copyWith( style: FluentTheme.of(context).typography.body?.copyWith(
fontSize: 22, fontSize: 22,
), ),
),
Container(
width: 2,
), ),
Container(width: 2,),
const Text("sosire la "), const Text("sosire la "),
ArrivalTime( ArrivalTime(station: station,),
station: station, Expanded(child: Container(),),
),
Expanded(
child: Container(),
),
], ],
); );
} else { }
else {
final delay = station.arrival!.status?.delay ?? 0; final delay = station.arrival!.status?.delay ?? 0;
final time = tz.convertDateTime(station.arrival!.scheduleTime); final time = station.arrival!.scheduleTime.toLocal();
if (delay == 0) { if (delay == 0) {
return Text( return Text("${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}");
"${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}"); }
} else if (delay > 0) { else if (delay > 0) {
final oldDate = time; final oldDate = time;
final newDate = oldDate.add(Duration(minutes: delay)); final newDate = oldDate.add(Duration(minutes: delay));
@ -319,19 +219,20 @@ class ArrivalTime extends ConsumerWidget {
Text( Text(
"${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}", "${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}",
style: FluentTheme.of(context).typography.body?.copyWith( style: FluentTheme.of(context).typography.body?.copyWith(
decoration: TextDecoration.lineThrough, decoration: TextDecoration.lineThrough,
), ),
), ),
Text( Text(
"${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}", "${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}",
style: FluentTheme.of(context).typography.body?.copyWith( style: FluentTheme.of(context).typography.body?.copyWith(
// color: Colors.red.shade300, // color: Colors.red.shade300,
color: Colors.red.lighter, color: Colors.red.lighter,
), ),
), ),
], ],
); );
} else { }
else {
final oldDate = time; final oldDate = time;
final newDate = oldDate.add(Duration(minutes: delay)); final newDate = oldDate.add(Duration(minutes: delay));
@ -341,15 +242,15 @@ class ArrivalTime extends ConsumerWidget {
Text( Text(
"${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}", "${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}",
style: FluentTheme.of(context).typography.body?.copyWith( style: FluentTheme.of(context).typography.body?.copyWith(
decoration: TextDecoration.lineThrough, decoration: TextDecoration.lineThrough,
), ),
), ),
Text( Text(
"${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}", "${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}",
style: FluentTheme.of(context).typography.body?.copyWith( style: FluentTheme.of(context).typography.body?.copyWith(
// color: Colors.green.shade300, // color: Colors.green.shade300,
color: Colors.green.lighter, color: Colors.green.lighter,
), ),
), ),
], ],
); );
@ -359,7 +260,7 @@ class ArrivalTime extends ConsumerWidget {
} }
class StopTime extends StatelessWidget { class StopTime extends StatelessWidget {
final TrainDataStation station; final Station station;
const StopTime({ const StopTime({
required this.station, required this.station,
@ -388,12 +289,14 @@ class StopTime extends StatelessWidget {
"1 ${minutes ? 'minut' : 'secundă'}", "1 ${minutes ? 'minut' : 'secundă'}",
textAlign: TextAlign.center, textAlign: TextAlign.center,
); );
} else if (stopsForInt < 20) { }
else if (stopsForInt < 20) {
return Text( return Text(
"$stopsForInt ${minutes ? 'minute' : 'secunde'}", "$stopsForInt ${minutes ? 'minute' : 'secunde'}",
textAlign: TextAlign.center, textAlign: TextAlign.center,
); );
} else { }
else {
return Text( return Text(
"$stopsForInt de ${minutes ? 'minute' : 'secunde'}", "$stopsForInt de ${minutes ? 'minute' : 'secunde'}",
textAlign: TextAlign.center, textAlign: TextAlign.center,
@ -406,8 +309,8 @@ class StopTime extends StatelessWidget {
} }
} }
class DepartureTime extends ConsumerWidget { class DepartureTime extends StatelessWidget {
final TrainDataStation station; final Station station;
final bool firstStation; final bool firstStation;
const DepartureTime({ const DepartureTime({
@ -417,8 +320,7 @@ class DepartureTime extends ConsumerWidget {
}); });
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context) {
final tz = ref.watch(uiTimeZoneProvider);
if (station.departure == null) { if (station.departure == null) {
return Container(); return Container();
} }
@ -426,32 +328,27 @@ class DepartureTime extends ConsumerWidget {
return Row( return Row(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[ children: <Widget>[
Expanded( Expanded(child: Container(),),
child: Container(),
),
const Text("plecare la "), const Text("plecare la "),
DepartureTime( DepartureTime(station: station,),
station: station, Container(width: 2,),
),
Container(
width: 2,
),
Text( Text(
"", "",
style: FluentTheme.of(context).typography.body?.copyWith( style: FluentTheme.of(context).typography.body?.copyWith(
fontSize: 22, fontSize: 22,
), ),
), ),
], ],
); );
} else { }
else {
final delay = station.departure!.status?.delay ?? 0; final delay = station.departure!.status?.delay ?? 0;
final time = tz.convertDateTime(station.departure!.scheduleTime); final time = station.departure!.scheduleTime.toLocal();
if (delay == 0) { if (delay == 0) {
return Text( return Text("${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}");
"${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}"); }
} else if (delay > 0) { else if (delay > 0) {
final oldDate = time; final oldDate = time;
final newDate = oldDate.add(Duration(minutes: delay)); final newDate = oldDate.add(Duration(minutes: delay));
@ -461,19 +358,20 @@ class DepartureTime extends ConsumerWidget {
Text( Text(
"${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}", "${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}",
style: FluentTheme.of(context).typography.body?.copyWith( style: FluentTheme.of(context).typography.body?.copyWith(
decoration: TextDecoration.lineThrough, decoration: TextDecoration.lineThrough,
), ),
), ),
Text( Text(
"${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}", "${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}",
style: FluentTheme.of(context).typography.body?.copyWith( style: FluentTheme.of(context).typography.body?.copyWith(
// color: Colors.red.shade300, // color: Colors.red.shade300,
color: Colors.red.lighter, color: Colors.red.lighter,
), ),
), ),
], ],
); );
} else { }
else {
final oldDate = time; final oldDate = time;
final newDate = oldDate.add(Duration(minutes: delay)); final newDate = oldDate.add(Duration(minutes: delay));
@ -483,15 +381,15 @@ class DepartureTime extends ConsumerWidget {
Text( Text(
"${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}", "${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}",
style: FluentTheme.of(context).typography.body?.copyWith( style: FluentTheme.of(context).typography.body?.copyWith(
decoration: TextDecoration.lineThrough, decoration: TextDecoration.lineThrough,
), ),
), ),
Text( Text(
"${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}", "${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}",
style: FluentTheme.of(context).typography.body?.copyWith( style: FluentTheme.of(context).typography.body?.copyWith(
// color: Colors.green.shade300, // color: Colors.green.shade300,
color: Colors.green.lighter, color: Colors.green.lighter,
), ),
), ),
], ],
); );
@ -500,8 +398,9 @@ class DepartureTime extends ConsumerWidget {
} }
} }
class Delay extends StatelessWidget { class Delay extends StatelessWidget {
final TrainDataStation station; final Station station;
const Delay({ const Delay({
required this.station, required this.station,
@ -524,21 +423,22 @@ class Delay extends StatelessWidget {
return Text( return Text(
"$delay ${delay == 1 ? 'minut' : 'minute'} întârziere", "$delay ${delay == 1 ? 'minut' : 'minute'} întârziere",
style: FluentTheme.of(context).typography.body?.copyWith( style: FluentTheme.of(context).typography.body?.copyWith(
// color: Colors.red.shade300, // color: Colors.red.shade300,
color: Colors.red.lighter, color: Colors.red.lighter,
fontSize: 14, fontSize: 14,
fontStyle: FontStyle.italic, fontStyle: FontStyle.italic,
), ),
); );
} else if (delay < 0) { }
else if (delay < 0) {
return Text( return Text(
"${-delay} ${delay == -1 ? 'minut' : 'minute'} mai devreme", "${-delay} ${delay == -1 ? 'minut' : 'minute'} mai devreme",
style: FluentTheme.of(context).typography.body?.copyWith( style: FluentTheme.of(context).typography.body?.copyWith(
// color: Colors.green.shade300, // color: Colors.green.shade300,
color: Colors.green.lighter, color: Colors.green.lighter,
fontSize: 14, fontSize: 14,
fontStyle: FontStyle.italic, fontStyle: FontStyle.italic,
), ),
); );
} }

143
lib/pages/train_info_page/view_train/train_info_material.dart

@ -1,7 +1,6 @@
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:info_tren/components/slim_app_bar.dart'; import 'package:info_tren/components/slim_app_bar.dart';
import 'package:info_tren/components/train_id_text_span.dart';
import 'package:info_tren/models.dart'; import 'package:info_tren/models.dart';
import 'package:info_tren/pages/station_arrdep_page/view_station/view_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/view_train/train_info.dart';
@ -9,11 +8,7 @@ import 'package:info_tren/pages/train_info_page/view_train/train_info_material_D
import 'package:info_tren/utils/state_to_string.dart'; import 'package:info_tren/utils/state_to_string.dart';
class TrainInfoLoadingMaterial extends TrainInfoLoadingShared { class TrainInfoLoadingMaterial extends TrainInfoLoadingShared {
TrainInfoLoadingMaterial({ TrainInfoLoadingMaterial({required super.title, super.loadingText, super.key,});
required super.title,
super.loadingText,
super.key,
});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -81,34 +76,13 @@ class TrainInfoMaterial extends TrainInfoShared {
builder: (context) { builder: (context) {
return Scaffold( return Scaffold(
appBar: isSmallScreen(context) appBar: isSmallScreen(context)
? null ? null
: AppBar( : AppBar(
centerTitle: true, centerTitle: true,
title: Text( title: Text(
'Informații despre ${trainData.rank} ${trainData.number}', "Informații despre ${trainData.rank} ${trainData.number}",
),
actions: [
IconButton(
tooltip: 'Reîncarcă',
icon: (isRefreshing ?? false)
? const Center(
child: SizedBox(
height: 16,
width: 16,
child: CircularProgressIndicator(
strokeWidth: 2,
),
),
)
: const Icon(Icons.refresh),
onPressed: (isRefreshing ?? false)
? null
: () {
refresh?.call();
},
),
],
), ),
),
body: Column( body: Column(
children: <Widget>[ children: <Widget>[
if (isSmallScreen(context)) if (isSmallScreen(context))
@ -197,15 +171,16 @@ class TrainInfoBodyMaterial extends TrainInfoBodyShared {
if (onViewYesterdayTrain != null && if (onViewYesterdayTrain != null &&
trainData.stations.first.departure!.scheduleTime trainData.stations.first.departure!.scheduleTime
.compareTo(DateTime.now()) > .compareTo(DateTime.now()) >
0) ...[ 0)
DisplayTrainYesterdayWarningMaterial( ...[
onViewYesterdayTrain!, DisplayTrainYesterdayWarningMaterial(
), onViewYesterdayTrain!,
Divider( ),
color: Colors.white70, Divider(
height: isSmallScreen(context) ? 8 : 16, color: Colors.white70,
), height: isSmallScreen(context) ? 8 : 16,
], ),
],
], ],
), ),
), ),
@ -217,7 +192,10 @@ class TrainInfoBodyMaterial extends TrainInfoBodyShared {
), ),
SliverToBoxAdapter( SliverToBoxAdapter(
child: Container( child: Container(
height: MediaQuery.of(context).viewPadding.bottom, height: MediaQuery
.of(context)
.viewPadding
.bottom,
), ),
), ),
], ],
@ -225,7 +203,8 @@ class TrainInfoBodyMaterial extends TrainInfoBodyShared {
), ),
], ],
); );
} else { }
else {
return CustomScrollView( return CustomScrollView(
slivers: <Widget>[ slivers: <Widget>[
SliverToBoxAdapter( SliverToBoxAdapter(
@ -301,11 +280,11 @@ class TrainInfoBodyMaterial extends TrainInfoBodyShared {
), ),
if (onViewYesterdayTrain != null && if (onViewYesterdayTrain != null &&
trainData.stations.first.departure!.scheduleTime trainData.stations.first.departure!.scheduleTime
.compareTo(DateTime.now()) > .compareTo(DateTime.now()) >
0) ...[ 0) ...[
SliverToBoxAdapter( SliverToBoxAdapter(
child: child: DisplayTrainYesterdayWarningMaterial(
DisplayTrainYesterdayWarningMaterial(onViewYesterdayTrain!), onViewYesterdayTrain!),
), ),
SliverToBoxAdapter( SliverToBoxAdapter(
child: Divider( child: Divider(
@ -319,7 +298,10 @@ class TrainInfoBodyMaterial extends TrainInfoBodyShared {
), ),
SliverToBoxAdapter( SliverToBoxAdapter(
child: Container( child: Container(
height: MediaQuery.of(context).viewPadding.bottom, height: MediaQuery
.of(context)
.viewPadding
.bottom,
), ),
), ),
], ],
@ -331,15 +313,27 @@ class TrainInfoBodyMaterial extends TrainInfoBodyShared {
class DisplayTrainID extends StatelessWidget { class DisplayTrainID extends StatelessWidget {
final TrainData trainData; final TrainData trainData;
const DisplayTrainID({ const DisplayTrainID({required this.trainData, super.key,});
required this.trainData,
super.key,
});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Text.rich( return Text.rich(
trainIdSpan(rank: trainData.rank, number: trainData.number), TextSpan(
children: [
TextSpan(
text: trainData.rank,
style: TextStyle(
color: trainData.rank.startsWith('IR')
? const Color.fromARGB(255, 255, 0, 0)
: null,
),
),
const TextSpan(text: ' '),
TextSpan(
text: trainData.number,
),
],
),
style: (isSmallScreen(context) style: (isSmallScreen(context)
? Theme.of(context).textTheme.headlineMedium ? Theme.of(context).textTheme.headlineMedium
: Theme.of(context).textTheme.displaySmall) : Theme.of(context).textTheme.displaySmall)
@ -355,10 +349,7 @@ class DisplayTrainID extends StatelessWidget {
class DisplayTrainOperator extends StatelessWidget { class DisplayTrainOperator extends StatelessWidget {
final TrainData trainData; final TrainData trainData;
const DisplayTrainOperator({ const DisplayTrainOperator({required this.trainData, super.key,});
required this.trainData,
super.key,
});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -376,10 +367,7 @@ class DisplayTrainOperator extends StatelessWidget {
class DisplayTrainRoute extends StatelessWidget { class DisplayTrainRoute extends StatelessWidget {
final TrainData trainData; final TrainData trainData;
const DisplayTrainRoute({ const DisplayTrainRoute({required this.trainData, super.key,});
required this.trainData,
super.key,
});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -444,10 +432,7 @@ class DisplayTrainDeparture extends StatelessWidget {
class DisplayTrainLastInfo extends StatelessWidget { class DisplayTrainLastInfo extends StatelessWidget {
final TrainData trainData; final TrainData trainData;
const DisplayTrainLastInfo({ const DisplayTrainLastInfo({required this.trainData, super.key,});
required this.trainData,
super.key,
});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -639,10 +624,7 @@ class DisplayTrainLastInfo extends StatelessWidget {
class DisplayTrainDestination extends StatelessWidget { class DisplayTrainDestination extends StatelessWidget {
final TrainData trainData; final TrainData trainData;
const DisplayTrainDestination({ const DisplayTrainDestination({required this.trainData, super.key,});
required this.trainData,
super.key,
});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -746,10 +728,7 @@ class DisplayTrainDestination extends StatelessWidget {
class DisplayTrainRouteDistance extends StatelessWidget { class DisplayTrainRouteDistance extends StatelessWidget {
final TrainData trainData; final TrainData trainData;
const DisplayTrainRouteDistance({ const DisplayTrainRouteDistance({required this.trainData, super.key,});
required this.trainData,
super.key,
});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -786,10 +765,7 @@ class DisplayTrainRouteDistance extends StatelessWidget {
class DisplayTrainRouteDuration extends StatelessWidget { class DisplayTrainRouteDuration extends StatelessWidget {
final TrainData trainData; final TrainData trainData;
const DisplayTrainRouteDuration({ const DisplayTrainRouteDuration({required this.trainData, super.key,});
required this.trainData,
super.key,
});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -872,10 +848,7 @@ class DisplayTrainRouteDuration extends StatelessWidget {
class DisplayTrainYesterdayWarningMaterial class DisplayTrainYesterdayWarningMaterial
extends DisplayTrainYesterdayWarningCommon { extends DisplayTrainYesterdayWarningCommon {
const DisplayTrainYesterdayWarningMaterial( const DisplayTrainYesterdayWarningMaterial(super.onViewYesterdayTrain, {super.key,});
super.onViewYesterdayTrain, {
super.key,
});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -911,10 +884,7 @@ class DisplayTrainYesterdayWarningMaterial
class DisplayTrainStations extends StatelessWidget { class DisplayTrainStations extends StatelessWidget {
final TrainData trainData; final TrainData trainData;
const DisplayTrainStations({ const DisplayTrainStations({required this.trainData, super.key,});
required this.trainData,
super.key,
});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -928,8 +898,7 @@ class DisplayTrainStations extends StatelessWidget {
onTap: () { onTap: () {
Navigator.of(context).pushNamed( Navigator.of(context).pushNamed(
ViewStationPage.routeName, ViewStationPage.routeName,
arguments: ViewStationArguments( arguments: ViewStationArguments(stationName: trainData.stations[index].name),
stationName: trainData.stations[index].name),
); );
}, },
), ),

406
lib/pages/train_info_page/view_train/train_info_material_DisplayTrainStation.dart

@ -1,178 +1,100 @@
import 'package:flutter/material.dart' hide Badge; import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:info_tren/components/train_id_text_span.dart';
import 'package:info_tren/models.dart'; import 'package:info_tren/models.dart';
import 'package:info_tren/components/badge/badge.dart'; import 'package:info_tren/components/badge/badge.dart';
import 'package:info_tren/pages/train_info_page/view_train/train_info_material.dart'; import 'package:info_tren/pages/train_info_page/view_train/train_info_material.dart';
import 'package:info_tren/providers.dart';
class DisplayTrainStation extends StatelessWidget { class DisplayTrainStation extends StatelessWidget {
final TrainDataStation station; final Station station;
final void Function()? onTap; final void Function()? onTap;
const DisplayTrainStation({ const DisplayTrainStation({required this.station, this.onTap, super.key,});
required this.station,
this.onTap,
super.key,
});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Column( return Card(
mainAxisSize: MainAxisSize.min, child: InkWell(
children: [ onTap: onTap,
if (station.notes.whereType<TrainDataNoteDepartsAs>().isNotEmpty) child: Padding(
Builder( padding: const EdgeInsets.all(2),
builder: (context) { child: Column(
final note = mainAxisSize: MainAxisSize.min,
station.notes.whereType<TrainDataNoteDepartsAs>().first; crossAxisAlignment: CrossAxisAlignment.center,
return Padding( children: <Widget>[
padding: const EdgeInsets.all(2.0), Row(
child: Text.rich( mainAxisSize: MainAxisSize.max,
TextSpan(
children: [
const TextSpan(text: 'Trenul pleacă cu numărul '),
trainIdSpan(rank: note.rank, number: note.number),
],
),
),
);
},
),
Card(
child: InkWell(
onTap: onTap,
child: Padding(
padding: const EdgeInsets.all(2),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[ children: <Widget>[
Row( Expanded(
mainAxisSize: MainAxisSize.max, flex: 1,
children: <Widget>[ child: Align(
Expanded( alignment: Alignment.centerLeft,
flex: 1, child: Builder(
child: Align( builder: (context) {
alignment: Alignment.centerLeft, final departureStatus = station.departure?.status;
child: Builder(builder: (context) { final arrivalStatus = station.arrival?.status;
final departureStatus = station.departure?.status; int delay;
final arrivalStatus = station.arrival?.status; bool real;
int delay; if (departureStatus == null) {
bool real; delay = arrivalStatus?.delay ?? 0;
if (departureStatus == null) { real = arrivalStatus?.real ?? false;
delay = arrivalStatus?.delay ?? 0; }
real = arrivalStatus?.real ?? false; else if (arrivalStatus == null) {
} else if (arrivalStatus == null) { delay = departureStatus.delay;
delay = departureStatus.delay; real = departureStatus.real;
real = departureStatus.real; }
} else { else {
delay = departureStatus.delay; delay = departureStatus.delay;
real = departureStatus.real; real = departureStatus.real;
if (!real && arrivalStatus.real) { if (!real && arrivalStatus.real) {
delay = arrivalStatus.delay; delay = arrivalStatus.delay;
real = arrivalStatus.real; real = arrivalStatus.real;
}
} }
}
final isDelayed = delay > 0 && real == true;
final isOnTime = delay <= 0 && real == true; final isDelayed = delay > 0 && real == true;
const isNotScheduled = false; final isOnTime = delay <= 0 && real == true;
const isNotScheduled = false;
return Badge(
text: station.km.toString(), return Badge(
caption: 'km', text: station.km.toString(),
isNotScheduled: isNotScheduled, caption: 'km',
isDelayed: isDelayed, isNotScheduled: isNotScheduled,
isOnTime: isOnTime, isDelayed: isDelayed,
); isOnTime: isOnTime,
}), );
), }
),
Title(
station: station,
), ),
Expanded( ),
flex: 1,
child: (station.platform == null)
? Container()
: Align(
alignment: Alignment.centerRight,
child: Badge(
text: station.platform!,
caption: 'linia',
),
),
),
],
), ),
Time( Title(
station: station, station: station,
), ),
if (station.notes Expanded(
.whereType<TrainDataNoteDetachingWagons>() flex: 1,
.isNotEmpty) child: (station.platform == null)
Builder( ? Container()
builder: (context) { : Align(
final note = station.notes alignment: Alignment.centerRight,
.whereType<TrainDataNoteDetachingWagons>() child: Badge(text: station.platform!, caption: 'linia',),
.first; ),
return Text(
'Trenul detașează vagoane către ${note.station}',
textAlign: TextAlign.center,
);
},
),
if (station.notes
.whereType<TrainDataNoteReceivingWagons>()
.isNotEmpty)
Builder(
builder: (context) {
final note = station.notes
.whereType<TrainDataNoteReceivingWagons>()
.first;
return Text(
'Trenul primește vagoane de la ${note.station}',
textAlign: TextAlign.center,
);
},
),
Delay(
station: station,
), ),
], ],
), ),
), Time(
station: station,
),
Delay(
station: station,
),
],
), ),
), ),
if (station.notes ),
.whereType<TrainDataNoteTrainNumberChange>()
.isNotEmpty)
Builder(
builder: (context) {
final note = station.notes
.whereType<TrainDataNoteTrainNumberChange>()
.first;
return Padding(
padding: const EdgeInsets.all(2.0),
child: Text.rich(
TextSpan(
children: [
const TextSpan(text: 'Trenul își schimbă numărul în '),
trainIdSpan(rank: note.rank, number: note.number),
],
),
),
);
},
),
],
); );
} }
} }
class Title extends StatelessWidget { class Title extends StatelessWidget {
final TrainDataStation station; final Station station;
const Title({ const Title({
required this.station, required this.station,
@ -181,22 +103,20 @@ class Title extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Text( return Text(
station.name, station.name,
style: Theme.of(context).textTheme.bodyMedium?.copyWith( style: Theme.of(context).textTheme.bodyMedium?.copyWith(
fontSize: isSmallScreen(context) ? 18 : 22, fontSize: isSmallScreen(context) ? 18 : 22,
fontWeight: MediaQuery.of(context).boldText fontWeight: MediaQuery.of(context).boldText ? FontWeight.w500 : FontWeight.w300,
? FontWeight.w500 // fontStyle: items[1] == "ONI" ? FontStyle.italic : FontStyle.normal,
: FontWeight.w300, ),
// fontStyle: items[1] == "ONI" ? FontStyle.italic : FontStyle.normal,
),
textAlign: TextAlign.center, textAlign: TextAlign.center,
); );
} }
} }
class Time extends StatelessWidget { class Time extends StatelessWidget {
final TrainDataStation station; final Station station;
const Time({ const Time({
required this.station, required this.station,
@ -227,43 +147,29 @@ class Time extends StatelessWidget {
Text( Text(
"", "",
style: Theme.of(context).textTheme.bodyMedium?.copyWith( style: Theme.of(context).textTheme.bodyMedium?.copyWith(
fontSize: isSmallScreen(context) ? 18 : 22, fontSize: isSmallScreen(context) ? 18 : 22,
), ),
),
Container(
width: 2,
),
ArrivalTime(
station: station,
),
Expanded(
child: Container(),
),
StopTime(
station: station,
),
Expanded(
child: Container(),
),
DepartureTime(
station: station,
),
Container(
width: 2,
), ),
Container(width: 2,),
ArrivalTime(station: station,),
Expanded(child: Container(),),
StopTime(station: station,),
Expanded(child: Container(),),
DepartureTime(station: station,),
Container(width: 2,),
Text( Text(
"", "",
style: Theme.of(context).textTheme.bodyMedium?.copyWith( style: Theme.of(context).textTheme.bodyMedium?.copyWith(
fontSize: isSmallScreen(context) ? 18 : 22, fontSize: isSmallScreen(context) ? 18 : 22,
), ),
), ),
], ],
); );
} }
} }
class ArrivalTime extends ConsumerWidget { class ArrivalTime extends StatelessWidget {
final TrainDataStation station; final Station station;
final bool finalStation; final bool finalStation;
const ArrivalTime({ const ArrivalTime({
@ -273,8 +179,7 @@ class ArrivalTime extends ConsumerWidget {
}); });
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context) {
final tz = ref.watch(uiTimeZoneProvider);
if (station.arrival == null) { if (station.arrival == null) {
return Container(); return Container();
} }
@ -285,29 +190,24 @@ class ArrivalTime extends ConsumerWidget {
Text( Text(
"", "",
style: Theme.of(context).textTheme.bodyMedium?.copyWith( style: Theme.of(context).textTheme.bodyMedium?.copyWith(
fontSize: isSmallScreen(context) ? 18 : 22, fontSize: isSmallScreen(context) ? 18 : 22,
), ),
),
Container(
width: 2,
), ),
Container(width: 2,),
const Text("sosire la "), const Text("sosire la "),
ArrivalTime( ArrivalTime(station: station,),
station: station, Expanded(child: Container(),),
),
Expanded(
child: Container(),
),
], ],
); );
} else { }
else {
final delay = station.arrival!.status?.delay ?? 0; final delay = station.arrival!.status?.delay ?? 0;
final time = tz.convertDateTime(station.arrival!.scheduleTime); final time = station.arrival!.scheduleTime.toLocal();
if (delay == 0) { if (delay == 0) {
return Text( return Text("${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}");
"${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}"); }
} else if (delay > 0) { else if (delay > 0) {
final oldDate = time; final oldDate = time;
final newDate = oldDate.add(Duration(minutes: delay)); final newDate = oldDate.add(Duration(minutes: delay));
@ -317,18 +217,19 @@ class ArrivalTime extends ConsumerWidget {
Text( Text(
"${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}", "${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}",
style: Theme.of(context).textTheme.bodyMedium?.copyWith( style: Theme.of(context).textTheme.bodyMedium?.copyWith(
decoration: TextDecoration.lineThrough, decoration: TextDecoration.lineThrough,
), ),
), ),
Text( Text(
"${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}", "${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}",
style: Theme.of(context).textTheme.bodyMedium?.copyWith( style: Theme.of(context).textTheme.bodyMedium?.copyWith(
color: Colors.red.shade300, color: Colors.red.shade300,
), ),
), ),
], ],
); );
} else { }
else {
final oldDate = time; final oldDate = time;
final newDate = oldDate.add(Duration(minutes: delay)); final newDate = oldDate.add(Duration(minutes: delay));
@ -338,14 +239,14 @@ class ArrivalTime extends ConsumerWidget {
Text( Text(
"${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}", "${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}",
style: Theme.of(context).textTheme.bodyMedium?.copyWith( style: Theme.of(context).textTheme.bodyMedium?.copyWith(
decoration: TextDecoration.lineThrough, decoration: TextDecoration.lineThrough,
), ),
), ),
Text( Text(
"${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}", "${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}",
style: Theme.of(context).textTheme.bodyMedium?.copyWith( style: Theme.of(context).textTheme.bodyMedium?.copyWith(
color: Colors.green.shade300, color: Colors.green.shade300,
), ),
), ),
], ],
); );
@ -355,7 +256,7 @@ class ArrivalTime extends ConsumerWidget {
} }
class StopTime extends StatelessWidget { class StopTime extends StatelessWidget {
final TrainDataStation station; final Station station;
const StopTime({ const StopTime({
required this.station, required this.station,
@ -384,12 +285,14 @@ class StopTime extends StatelessWidget {
"1 ${minutes ? 'minut' : 'secundă'}", "1 ${minutes ? 'minut' : 'secundă'}",
textAlign: TextAlign.center, textAlign: TextAlign.center,
); );
} else if (stopsForInt < 20) { }
else if (stopsForInt < 20) {
return Text( return Text(
"$stopsForInt ${minutes ? 'minute' : 'secunde'}", "$stopsForInt ${minutes ? 'minute' : 'secunde'}",
textAlign: TextAlign.center, textAlign: TextAlign.center,
); );
} else { }
else {
return Text( return Text(
"$stopsForInt de ${minutes ? 'minute' : 'secunde'}", "$stopsForInt de ${minutes ? 'minute' : 'secunde'}",
textAlign: TextAlign.center, textAlign: TextAlign.center,
@ -402,8 +305,8 @@ class StopTime extends StatelessWidget {
} }
} }
class DepartureTime extends ConsumerWidget { class DepartureTime extends StatelessWidget {
final TrainDataStation station; final Station station;
final bool firstStation; final bool firstStation;
const DepartureTime({ const DepartureTime({
@ -413,8 +316,7 @@ class DepartureTime extends ConsumerWidget {
}); });
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context) {
final tz = ref.watch(uiTimeZoneProvider);
if (station.departure == null) { if (station.departure == null) {
return Container(); return Container();
} }
@ -422,32 +324,27 @@ class DepartureTime extends ConsumerWidget {
return Row( return Row(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[ children: <Widget>[
Expanded( Expanded(child: Container(),),
child: Container(),
),
const Text("plecare la "), const Text("plecare la "),
DepartureTime( DepartureTime(station: station,),
station: station, Container(width: 2,),
),
Container(
width: 2,
),
Text( Text(
"", "",
style: Theme.of(context).textTheme.bodyMedium?.copyWith( style: Theme.of(context).textTheme.bodyMedium?.copyWith(
fontSize: 22, fontSize: 22,
), ),
), ),
], ],
); );
} else { }
else {
final delay = station.departure!.status?.delay ?? 0; final delay = station.departure!.status?.delay ?? 0;
final time = tz.convertDateTime(station.departure!.scheduleTime); final time = station.departure!.scheduleTime.toLocal();
if (delay == 0) { if (delay == 0) {
return Text( return Text("${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}");
"${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}"); }
} else if (delay > 0) { else if (delay > 0) {
final oldDate = time; final oldDate = time;
final newDate = oldDate.add(Duration(minutes: delay)); final newDate = oldDate.add(Duration(minutes: delay));
@ -457,18 +354,19 @@ class DepartureTime extends ConsumerWidget {
Text( Text(
"${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}", "${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}",
style: Theme.of(context).textTheme.bodyMedium?.copyWith( style: Theme.of(context).textTheme.bodyMedium?.copyWith(
decoration: TextDecoration.lineThrough, decoration: TextDecoration.lineThrough,
), ),
), ),
Text( Text(
"${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}", "${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}",
style: Theme.of(context).textTheme.bodyMedium?.copyWith( style: Theme.of(context).textTheme.bodyMedium?.copyWith(
color: Colors.red.shade300, color: Colors.red.shade300,
), ),
), ),
], ],
); );
} else { }
else {
final oldDate = time; final oldDate = time;
final newDate = oldDate.add(Duration(minutes: delay)); final newDate = oldDate.add(Duration(minutes: delay));
@ -478,14 +376,14 @@ class DepartureTime extends ConsumerWidget {
Text( Text(
"${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}", "${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}",
style: Theme.of(context).textTheme.bodyMedium?.copyWith( style: Theme.of(context).textTheme.bodyMedium?.copyWith(
decoration: TextDecoration.lineThrough, decoration: TextDecoration.lineThrough,
), ),
), ),
Text( Text(
"${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}", "${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}",
style: Theme.of(context).textTheme.bodyMedium?.copyWith( style: Theme.of(context).textTheme.bodyMedium?.copyWith(
color: Colors.green.shade300, color: Colors.green.shade300,
), ),
), ),
], ],
); );
@ -494,8 +392,9 @@ class DepartureTime extends ConsumerWidget {
} }
} }
class Delay extends StatelessWidget { class Delay extends StatelessWidget {
final TrainDataStation station; final Station station;
const Delay({ const Delay({
required this.station, required this.station,
@ -518,19 +417,20 @@ class Delay extends StatelessWidget {
return Text( return Text(
"$delay ${delay == 1 ? 'minut' : 'minute'} întârziere", "$delay ${delay == 1 ? 'minut' : 'minute'} întârziere",
style: Theme.of(context).textTheme.bodyMedium?.copyWith( style: Theme.of(context).textTheme.bodyMedium?.copyWith(
color: Colors.red.shade300, color: Colors.red.shade300,
fontSize: 14, fontSize: 14,
fontStyle: FontStyle.italic, fontStyle: FontStyle.italic,
), ),
); );
} else if (delay < 0) { }
else if (delay < 0) {
return Text( return Text(
"${-delay} ${delay == -1 ? 'minut' : 'minute'} mai devreme", "${-delay} ${delay == -1 ? 'minut' : 'minute'} mai devreme",
style: Theme.of(context).textTheme.bodyMedium?.copyWith( style: Theme.of(context).textTheme.bodyMedium?.copyWith(
color: Colors.green.shade300, color: Colors.green.shade300,
fontSize: 14, fontSize: 14,
fontStyle: FontStyle.italic, fontStyle: FontStyle.italic,
), ),
); );
} }

47
lib/providers.dart

@ -1,19 +1,14 @@
import 'dart:async'; import 'dart:async';
import 'dart:developer';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:info_tren/api/station_data.dart'; import 'package:info_tren/api/station_data.dart';
import 'package:info_tren/api/train_data.dart';
import 'package:info_tren/models.dart'; import 'package:info_tren/models.dart';
import 'package:info_tren/pages/station_arrdep_page/view_station/view_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/view_train/train_info.dart';
import 'package:info_tren/utils/default_ui_design.dart'; import 'package:info_tren/utils/default_ui_design.dart';
import 'package:info_tren/utils/iterable_extensions.dart'; import 'package:info_tren/utils/iterable_extensions.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
part 'providers.g.dart';
final sharedPreferencesProvider = Provider<SharedPreferences>( final sharedPreferencesProvider = Provider<SharedPreferences>(
(_) => throw UnimplementedError('Please override in ProviderScope'), (_) => throw UnimplementedError('Please override in ProviderScope'),
); );
@ -41,47 +36,14 @@ final uiDesignProvider = StateNotifierProvider<UiDesignNotifier, UiDesign>(
(ref) => UiDesignNotifier( (ref) => UiDesignNotifier(
sharedPreferences: ref.watch(sharedPreferencesProvider), sharedPreferences: ref.watch(sharedPreferencesProvider),
), ),
dependencies: [sharedPreferencesProvider],
);
class UiTimeZoneNotifier extends StateNotifier<UiTimeZone> {
final SharedPreferences sharedPreferences;
UiTimeZoneNotifier({required this.sharedPreferences,}) : super(const RoUiTimeZone()) {
final stored = sharedPreferences.getString('uiTimeZone');
if (stored != null) {
try {
state = UiTimeZone.fromSerString(stored);
}
catch (e) {
log('Invalid UiTimeZone ser: $stored, error: $e', level: 1000);
}
}
}
void set(UiTimeZone? timeZone) async {
if (timeZone != null) {
await sharedPreferences.setString('uiTimeZone', timeZone.toSerString());
}
else {
await sharedPreferences.remove('uiTimeZone');
}
state = timeZone ?? const LocalUiTimeZone();
}
}
final uiTimeZoneProvider = StateNotifierProvider<UiTimeZoneNotifier, UiTimeZone>(
(ref) => UiTimeZoneNotifier(
sharedPreferences: ref.watch(sharedPreferencesProvider),
),
dependencies: [sharedPreferencesProvider],
); );
final trainInfoArgumentsProvider = Provider<TrainInfoArguments>( final trainInfoArgumentsProvider = Provider<TrainInfoArguments>(
(_) => throw UnimplementedError('Please override in ProviderScope'), (_) => throw UnimplementedError('Please override in ProviderScope'),
); );
final stationDataProvider = FutureProvider.family((ref, ViewStationArguments args) async { final stationDataProvider = FutureProvider.family((ref, String stationName) async {
final data = await getStationData(args.stationName, args.date); final data = await getStationData(stationName);
final timer = Timer(const Duration(minutes: 2), () { final timer = Timer(const Duration(minutes: 2), () {
ref.invalidateSelf(); ref.invalidateSelf();
@ -97,9 +59,6 @@ final viewStationArgumentsProvider = Provider<ViewStationArguments>(
); );
final viewStationDataProvider = Provider((ref) { final viewStationDataProvider = Provider((ref) {
final args = ref.watch(viewStationArgumentsProvider); final args = ref.watch(viewStationArgumentsProvider);
final data = ref.watch(stationDataProvider(args)); final data = ref.watch(stationDataProvider(args.stationName));
return data; return data;
}, dependencies: [viewStationArgumentsProvider, stationDataProvider]); }, dependencies: [viewStationArgumentsProvider, stationDataProvider]);
@Riverpod(keepAlive: true)
Future<TrainData> trainInfo(TrainInfoRef ref, {required String trainNumber, DateTime? date}) => getTrain(trainNumber, date: date);

120
lib/providers.g.dart

@ -1,120 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'providers.dart';
// **************************************************************************
// RiverpodGenerator
// **************************************************************************
String _$trainInfoHash() => r'd25aabc3ba656acf6497ec6831e11892178b22c9';
/// Copied from Dart SDK
class _SystemHash {
_SystemHash._();
static int combine(int hash, int value) {
// ignore: parameter_assignments
hash = 0x1fffffff & (hash + value);
// ignore: parameter_assignments
hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
return hash ^ (hash >> 6);
}
static int finish(int hash) {
// ignore: parameter_assignments
hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
// ignore: parameter_assignments
hash = hash ^ (hash >> 11);
return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
}
}
typedef TrainInfoRef = FutureProviderRef<TrainData>;
/// See also [trainInfo].
@ProviderFor(trainInfo)
const trainInfoProvider = TrainInfoFamily();
/// See also [trainInfo].
class TrainInfoFamily extends Family<AsyncValue<TrainData>> {
/// See also [trainInfo].
const TrainInfoFamily();
/// See also [trainInfo].
TrainInfoProvider call({
required String trainNumber,
DateTime? date,
}) {
return TrainInfoProvider(
trainNumber: trainNumber,
date: date,
);
}
@override
TrainInfoProvider getProviderOverride(
covariant TrainInfoProvider provider,
) {
return call(
trainNumber: provider.trainNumber,
date: provider.date,
);
}
static const Iterable<ProviderOrFamily>? _dependencies = null;
@override
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
@override
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
_allTransitiveDependencies;
@override
String? get name => r'trainInfoProvider';
}
/// See also [trainInfo].
class TrainInfoProvider extends FutureProvider<TrainData> {
/// See also [trainInfo].
TrainInfoProvider({
required this.trainNumber,
this.date,
}) : super.internal(
(ref) => trainInfo(
ref,
trainNumber: trainNumber,
date: date,
),
from: trainInfoProvider,
name: r'trainInfoProvider',
debugGetCreateSourceHash:
const bool.fromEnvironment('dart.vm.product')
? null
: _$trainInfoHash,
dependencies: TrainInfoFamily._dependencies,
allTransitiveDependencies: TrainInfoFamily._allTransitiveDependencies,
);
final String trainNumber;
final DateTime? date;
@override
bool operator ==(Object other) {
return other is TrainInfoProvider &&
other.trainNumber == trainNumber &&
other.date == date;
}
@override
int get hashCode {
var hash = _SystemHash.combine(0, runtimeType.hashCode);
hash = _SystemHash.combine(hash, trainNumber.hashCode);
hash = _SystemHash.combine(hash, date.hashCode);
return _SystemHash.finish(hash);
}
}
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions

15
lib/utils/state_to_string.dart

@ -1,7 +1,12 @@
import 'package:info_tren/models.dart'; import 'package:info_tren/models.dart';
String stateToString(TrainDataState state) => switch (state) { String stateToString(TrainDataState state) {
TrainDataState.passing => 'trecere fără oprire', switch(state) {
TrainDataState.arrival => 'sosire', case TrainDataState.PASSING:
TrainDataState.departure => 'plecare', return 'trecere fără oprire';
}; case TrainDataState.ARRIVAL:
return 'sosire';
case TrainDataState.DEPARTURE:
return 'plecare';
}
}

4
linux/flutter/generated_plugin_registrant.cc

@ -6,13 +6,9 @@
#include "generated_plugin_registrant.h" #include "generated_plugin_registrant.h"
#include <dynamic_color/dynamic_color_plugin.h>
#include <url_launcher_linux/url_launcher_plugin.h> #include <url_launcher_linux/url_launcher_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) { void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) dynamic_color_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "DynamicColorPlugin");
dynamic_color_plugin_register_with_registrar(dynamic_color_registrar);
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);

1
linux/flutter/generated_plugins.cmake

@ -3,7 +3,6 @@
# #
list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_PLUGIN_LIST
dynamic_color
url_launcher_linux url_launcher_linux
) )

1
macos/Flutter/Flutter-Debug.xcconfig

@ -1,2 +1 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "ephemeral/Flutter-Generated.xcconfig" #include "ephemeral/Flutter-Generated.xcconfig"

1
macos/Flutter/Flutter-Release.xcconfig

@ -1,2 +1 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "ephemeral/Flutter-Generated.xcconfig" #include "ephemeral/Flutter-Generated.xcconfig"

40
macos/Podfile

@ -1,40 +0,0 @@
platform :osx, '10.14'
# 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', 'ephemeral', '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 Flutter-Generated.xcconfig, then run \"flutter pub get\""
end
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
flutter_macos_podfile_setup
target 'Runner' do
use_frameworks!
use_modular_headers!
flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__))
end
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_macos_build_settings(target)
end
end

41
macos/Podfile.lock

@ -1,41 +0,0 @@
PODS:
- dynamic_color (0.0.2):
- FlutterMacOS
- FlutterMacOS (1.0.0)
- package_info_plus (0.0.1):
- FlutterMacOS
- shared_preferences_foundation (0.0.1):
- Flutter
- FlutterMacOS
- url_launcher_macos (0.0.1):
- FlutterMacOS
DEPENDENCIES:
- dynamic_color (from `Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos`)
- FlutterMacOS (from `Flutter/ephemeral`)
- package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`)
- shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`)
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
EXTERNAL SOURCES:
dynamic_color:
:path: Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos
FlutterMacOS:
:path: Flutter/ephemeral
package_info_plus:
:path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos
shared_preferences_foundation:
:path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin
url_launcher_macos:
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
SPEC CHECKSUMS:
dynamic_color: 2eaa27267de1ca20d879fbd6e01259773fb1670f
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce
shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126
url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95
PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7
COCOAPODS: 1.12.1

71
macos/Runner.xcodeproj/project.pbxproj

@ -3,7 +3,7 @@
archiveVersion = 1; archiveVersion = 1;
classes = { classes = {
}; };
objectVersion = 54; objectVersion = 51;
objects = { objects = {
/* Begin PBXAggregateTarget section */ /* Begin PBXAggregateTarget section */
@ -26,7 +26,6 @@
33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
520B64251BD594DD8421C698 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BE5B44A3963C12914D375BF2 /* Pods_Runner.framework */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */ /* Begin PBXContainerItemProxy section */
@ -53,7 +52,6 @@
/* End PBXCopyFilesBuildPhase section */ /* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
0796070C1CDACAE0CA888A94 /* 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>"; };
333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = "<group>"; }; 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = "<group>"; };
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = "<group>"; }; 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = "<group>"; };
33CC10ED2044A3C60003C045 /* Info Tren.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Info Tren.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 33CC10ED2044A3C60003C045 /* Info Tren.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Info Tren.app"; sourceTree = BUILT_PRODUCTS_DIR; };
@ -70,9 +68,6 @@
33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = "<group>"; }; 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
982BB43264C0B37351AE0773 /* 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>"; };
BE5B44A3963C12914D375BF2 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
FCA310A2438DD41F2A155FE5 /* 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>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@ -80,7 +75,6 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
520B64251BD594DD8421C698 /* Pods_Runner.framework in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -105,7 +99,6 @@
33CEB47122A05771004F2AC0 /* Flutter */, 33CEB47122A05771004F2AC0 /* Flutter */,
33CC10EE2044A3C60003C045 /* Products */, 33CC10EE2044A3C60003C045 /* Products */,
D73912EC22F37F3D000D13A0 /* Frameworks */, D73912EC22F37F3D000D13A0 /* Frameworks */,
EB1CD289E0F53193A2CB7A73 /* Pods */,
); );
sourceTree = "<group>"; sourceTree = "<group>";
}; };
@ -155,22 +148,10 @@
D73912EC22F37F3D000D13A0 /* Frameworks */ = { D73912EC22F37F3D000D13A0 /* Frameworks */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
BE5B44A3963C12914D375BF2 /* Pods_Runner.framework */,
); );
name = Frameworks; name = Frameworks;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
EB1CD289E0F53193A2CB7A73 /* Pods */ = {
isa = PBXGroup;
children = (
FCA310A2438DD41F2A155FE5 /* Pods-Runner.debug.xcconfig */,
0796070C1CDACAE0CA888A94 /* Pods-Runner.release.xcconfig */,
982BB43264C0B37351AE0773 /* Pods-Runner.profile.xcconfig */,
);
name = Pods;
path = Pods;
sourceTree = "<group>";
};
/* End PBXGroup section */ /* End PBXGroup section */
/* Begin PBXNativeTarget section */ /* Begin PBXNativeTarget section */
@ -178,13 +159,11 @@
isa = PBXNativeTarget; isa = PBXNativeTarget;
buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = ( buildPhases = (
85962951F5B916ED962A8FBD /* [CP] Check Pods Manifest.lock */,
33CC10E92044A3C60003C045 /* Sources */, 33CC10E92044A3C60003C045 /* Sources */,
33CC10EA2044A3C60003C045 /* Frameworks */, 33CC10EA2044A3C60003C045 /* Frameworks */,
33CC10EB2044A3C60003C045 /* Resources */, 33CC10EB2044A3C60003C045 /* Resources */,
33CC110E2044A8840003C045 /* Bundle Framework */, 33CC110E2044A8840003C045 /* Bundle Framework */,
3399D490228B24CF009A79C7 /* ShellScript */, 3399D490228B24CF009A79C7 /* ShellScript */,
907AE34F1B4BFF5379ADD9D0 /* [CP] Embed Pods Frameworks */,
); );
buildRules = ( buildRules = (
); );
@ -203,7 +182,7 @@
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastSwiftUpdateCheck = 0920; LastSwiftUpdateCheck = 0920;
LastUpgradeCheck = 1300; LastUpgradeCheck = 0930;
ORGANIZATIONNAME = ""; ORGANIZATIONNAME = "";
TargetAttributes = { TargetAttributes = {
33CC10EC2044A3C60003C045 = { 33CC10EC2044A3C60003C045 = {
@ -256,7 +235,6 @@
/* Begin PBXShellScriptBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */
3399D490228B24CF009A79C7 /* ShellScript */ = { 3399D490228B24CF009A79C7 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
); );
@ -292,45 +270,6 @@
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire";
}; };
85962951F5B916ED962A8FBD /* [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;
};
907AE34F1B4BFF5379ADD9D0 /* [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 */ /* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */
@ -405,7 +344,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.14; MACOSX_DEPLOYMENT_TARGET = 10.11;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx; SDKROOT = macosx;
SWIFT_COMPILATION_MODE = wholemodule; SWIFT_COMPILATION_MODE = wholemodule;
@ -484,7 +423,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.14; MACOSX_DEPLOYMENT_TARGET = 10.11;
MTL_ENABLE_DEBUG_INFO = YES; MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx; SDKROOT = macosx;
@ -531,7 +470,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.14; MACOSX_DEPLOYMENT_TARGET = 10.11;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx; SDKROOT = macosx;
SWIFT_COMPILATION_MODE = wholemodule; SWIFT_COMPILATION_MODE = wholemodule;

2
macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1300" LastUpgradeVersion = "1000"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

3
macos/Runner.xcworkspace/contents.xcworkspacedata generated

@ -4,7 +4,4 @@
<FileRef <FileRef
location = "group:Runner.xcodeproj"> location = "group:Runner.xcodeproj">
</FileRef> </FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace> </Workspace>

649
pubspec.lock

File diff suppressed because it is too large Load Diff

15
pubspec.yaml

@ -11,10 +11,10 @@ description: O aplicație de vizualizare a datelor puse la dispoziție de Inform
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at # Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 2.7.11 version: 2.7.10
environment: environment:
sdk: ">=3.0.0 <4.0.0" sdk: ">=2.17.0 <3.0.0"
dependencies: dependencies:
flutter: flutter:
@ -30,23 +30,18 @@ dependencies:
url_launcher: ^6.1.5 url_launcher: ^6.1.5
flutter_hooks: ^0.18.5+1 flutter_hooks: ^0.18.5+1
hooks_riverpod: ^2.0.2 hooks_riverpod: ^2.0.2
freezed_annotation: ^2.4.1 freezed_annotation: ^2.2.0
json_annotation: ^4.8.1 json_annotation: ^4.7.0
shared_preferences: ^2.0.15 shared_preferences: ^2.0.15
fluent_ui: ^4.0.3+1 fluent_ui: ^4.0.3+1
timezone: ^0.9.0
dynamic_color: ^1.6.6
riverpod_annotation: ^2.1.1
dev_dependencies: dev_dependencies:
# flutter_test: # flutter_test:
# sdk: flutter # sdk: flutter
build_runner: ^2.1.0 build_runner: ^2.1.0
json_serializable: ^6.5.4 json_serializable: ^6.5.4
freezed: ^2.4.1 freezed: 2.2.0
flutter_lints: ^2.0.1 flutter_lints: ^2.0.1
riverpod_lint: ^1.3.2
riverpod_generator: ^2.2.3
# For information on the generic Dart part of this file, see the # For information on the generic Dart part of this file, see the

3
windows/flutter/generated_plugin_registrant.cc

@ -6,12 +6,9 @@
#include "generated_plugin_registrant.h" #include "generated_plugin_registrant.h"
#include <dynamic_color/dynamic_color_plugin_c_api.h>
#include <url_launcher_windows/url_launcher_windows.h> #include <url_launcher_windows/url_launcher_windows.h>
void RegisterPlugins(flutter::PluginRegistry* registry) { void RegisterPlugins(flutter::PluginRegistry* registry) {
DynamicColorPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("DynamicColorPluginCApi"));
UrlLauncherWindowsRegisterWithRegistrar( UrlLauncherWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("UrlLauncherWindows")); registry->GetRegistrarForPlugin("UrlLauncherWindows"));
} }

1
windows/flutter/generated_plugins.cmake

@ -3,7 +3,6 @@
# #
list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_PLUGIN_LIST
dynamic_color
url_launcher_windows url_launcher_windows
) )

Loading…
Cancel
Save