Upgrade Flutter/Dart and dependencies (#265)
* Fix new lint issues * Upgrade packages and remove `device_preview` * Regenerate splash assets * Migrate to `webview_flutter` 4.0 * Upgrade to Flutter 3.10 and Dart 3 * Update Podfile * Fix video not disposing when leaving channel * Remove `tuple` package * Upgrade packages * Upgrade packages * Update podfile * Upgrade packages * Upgrade packages
3
.gitignore
vendored
@ -32,9 +32,6 @@ migrate_working_dir/
|
||||
.pub/
|
||||
/build/
|
||||
|
||||
# Web related
|
||||
lib/generated_plugin_registrant.dart
|
||||
|
||||
# Symbolication related
|
||||
app.*.symbols
|
||||
|
||||
|
27
.metadata
@ -1,10 +1,33 @@
|
||||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled and should not be manually edited.
|
||||
# This file should be version controlled.
|
||||
|
||||
version:
|
||||
revision: f4abaa0735eba4dfd8f33f73363911d63931fe03
|
||||
revision: 84a1e904f44f9b0e9c4510138010edcc653163f8
|
||||
channel: stable
|
||||
|
||||
project_type: app
|
||||
|
||||
# Tracks metadata for the flutter migrate command
|
||||
migration:
|
||||
platforms:
|
||||
- platform: root
|
||||
create_revision: 84a1e904f44f9b0e9c4510138010edcc653163f8
|
||||
base_revision: 84a1e904f44f9b0e9c4510138010edcc653163f8
|
||||
- platform: android
|
||||
create_revision: 84a1e904f44f9b0e9c4510138010edcc653163f8
|
||||
base_revision: 84a1e904f44f9b0e9c4510138010edcc653163f8
|
||||
- platform: ios
|
||||
create_revision: 84a1e904f44f9b0e9c4510138010edcc653163f8
|
||||
base_revision: 84a1e904f44f9b0e9c4510138010edcc653163f8
|
||||
|
||||
# User provided section
|
||||
|
||||
# List of Local paths (relative to this file) that should be
|
||||
# ignored by the migrate tool.
|
||||
#
|
||||
# Files that are not part of the templates will be ignored by default.
|
||||
unmanaged_files:
|
||||
- 'lib/main.dart'
|
||||
- 'ios/Runner.xcodeproj/project.pbxproj'
|
||||
|
@ -9,9 +9,6 @@
|
||||
# packages, and plugins designed to encourage good coding practices.
|
||||
include: package:flutter_lints/flutter.yaml
|
||||
|
||||
analyzer:
|
||||
exclude: [lib/generated_plugin_registrant.dart]
|
||||
|
||||
linter:
|
||||
# The lint rules applied to this project can be customized in the
|
||||
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
|
||||
|
@ -37,7 +37,9 @@ if (keystorePropertiesFile.exists()) {
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 33
|
||||
namespace "com.tommychow.frosty"
|
||||
compileSdkVersion flutter.compileSdkVersion
|
||||
ndkVersion flutter.ndkVersion
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
|
@ -1,6 +1,6 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.tommychow.frosty">
|
||||
<!-- Flutter needs it to communicate with the running application
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- The INTERNET permission is required for development. Specifically,
|
||||
the Flutter tool needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
-->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
|
@ -1,5 +1,4 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.tommychow.frosty">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
|
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 6.0 KiB |
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 6.9 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 15 KiB |
@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
|
||||
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||
<item name="android:windowSplashScreenBackground">@drawable/launch_background</item>
|
||||
<item name="android:forceDarkAllowed">false</item>
|
||||
<item name="android:windowFullscreen">false</item>
|
||||
</style>
|
||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||
This theme determines the color of the Android Window while your
|
||||
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||
running.
|
||||
|
||||
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||
<item name="android:windowBackground">?android:colorBackground</item>
|
||||
</style>
|
||||
</resources>
|
@ -3,7 +3,7 @@
|
||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
|
||||
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||
<!-- Show a splash screen on the activity. Automatically removed when
|
||||
Flutter draws its first frame -->
|
||||
the Flutter engine draws its first frame -->
|
||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||
<item name="android:forceDarkAllowed">false</item>
|
||||
<item name="android:windowFullscreen">false</item>
|
||||
|
@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
|
||||
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||
<item name="android:forceDarkAllowed">false</item>
|
||||
<item name="android:windowFullscreen">false</item>
|
||||
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
||||
</style>
|
||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||
This theme determines the color of the Android Window while your
|
||||
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||
running.
|
||||
|
||||
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||
<item name="android:windowBackground">?android:colorBackground</item>
|
||||
</style>
|
||||
</resources>
|
@ -3,10 +3,11 @@
|
||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
|
||||
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||
<!-- Show a splash screen on the activity. Automatically removed when
|
||||
Flutter draws its first frame -->
|
||||
the Flutter engine draws its first frame -->
|
||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||
<item name="android:forceDarkAllowed">false</item>
|
||||
<item name="android:windowFullscreen">false</item>
|
||||
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
|
||||
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
||||
</style>
|
||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||
|
@ -1,6 +1,6 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.tommychow.frosty">
|
||||
<!-- Flutter needs it to communicate with the running application
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- The INTERNET permission is required for development. Specifically,
|
||||
the Flutter tool needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
-->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
|
@ -6,11 +6,11 @@ buildscript {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:7.1.2'
|
||||
classpath 'com.android.tools.build:gradle:7.3.0'
|
||||
// START: FlutterFire Configuration
|
||||
classpath 'com.google.gms:google-services:4.3.10'
|
||||
classpath 'com.google.firebase:perf-plugin:1.4.1'
|
||||
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.8.1'
|
||||
classpath 'com.google.gms:google-services:4.3.15'
|
||||
classpath 'com.google.firebase:perf-plugin:1.4.2'
|
||||
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.5'
|
||||
// END: FlutterFire Configuration
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
}
|
||||
@ -31,6 +31,6 @@ subprojects {
|
||||
project.evaluationDependsOn(':app')
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
tasks.register("clean", Delete) {
|
||||
delete rootProject.buildDir
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
#Fri Jun 23 08:50:38 CEST 2017
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip
|
||||
|
142
ios/Podfile.lock
@ -3,55 +3,55 @@ PODS:
|
||||
- Flutter
|
||||
- device_info_plus (0.0.1):
|
||||
- Flutter
|
||||
- Firebase/Analytics (10.7.0):
|
||||
- Firebase/Analytics (10.9.0):
|
||||
- Firebase/Core
|
||||
- Firebase/Core (10.7.0):
|
||||
- Firebase/Core (10.9.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseAnalytics (~> 10.7.0)
|
||||
- Firebase/CoreOnly (10.7.0):
|
||||
- FirebaseCore (= 10.7.0)
|
||||
- Firebase/Crashlytics (10.7.0):
|
||||
- FirebaseAnalytics (~> 10.9.0)
|
||||
- Firebase/CoreOnly (10.9.0):
|
||||
- FirebaseCore (= 10.9.0)
|
||||
- Firebase/Crashlytics (10.9.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseCrashlytics (~> 10.7.0)
|
||||
- Firebase/Performance (10.7.0):
|
||||
- FirebaseCrashlytics (~> 10.9.0)
|
||||
- Firebase/Performance (10.9.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebasePerformance (~> 10.7.0)
|
||||
- firebase_analytics (10.2.1):
|
||||
- Firebase/Analytics (= 10.7.0)
|
||||
- FirebasePerformance (~> 10.9.0)
|
||||
- firebase_analytics (10.4.1):
|
||||
- Firebase/Analytics (= 10.9.0)
|
||||
- firebase_core
|
||||
- Flutter
|
||||
- firebase_core (2.10.0):
|
||||
- Firebase/CoreOnly (= 10.7.0)
|
||||
- firebase_core (2.13.0):
|
||||
- Firebase/CoreOnly (= 10.9.0)
|
||||
- Flutter
|
||||
- firebase_crashlytics (3.1.2):
|
||||
- Firebase/Crashlytics (= 10.7.0)
|
||||
- firebase_crashlytics (3.3.1):
|
||||
- Firebase/Crashlytics (= 10.9.0)
|
||||
- firebase_core
|
||||
- Flutter
|
||||
- firebase_performance (0.9.1-1):
|
||||
- Firebase/Performance (= 10.7.0)
|
||||
- firebase_performance (0.9.2-1):
|
||||
- Firebase/Performance (= 10.9.0)
|
||||
- firebase_core
|
||||
- Flutter
|
||||
- FirebaseABTesting (10.9.0):
|
||||
- FirebaseCore (~> 10.0)
|
||||
- FirebaseAnalytics (10.7.0):
|
||||
- FirebaseAnalytics/AdIdSupport (= 10.7.0)
|
||||
- FirebaseAnalytics (10.9.0):
|
||||
- FirebaseAnalytics/AdIdSupport (= 10.9.0)
|
||||
- FirebaseCore (~> 10.0)
|
||||
- FirebaseInstallations (~> 10.0)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 7.8)
|
||||
- GoogleUtilities/MethodSwizzler (~> 7.8)
|
||||
- GoogleUtilities/Network (~> 7.8)
|
||||
- "GoogleUtilities/NSData+zlib (~> 7.8)"
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 7.11)
|
||||
- GoogleUtilities/MethodSwizzler (~> 7.11)
|
||||
- GoogleUtilities/Network (~> 7.11)
|
||||
- "GoogleUtilities/NSData+zlib (~> 7.11)"
|
||||
- nanopb (< 2.30910.0, >= 2.30908.0)
|
||||
- FirebaseAnalytics/AdIdSupport (10.7.0):
|
||||
- FirebaseAnalytics/AdIdSupport (10.9.0):
|
||||
- FirebaseCore (~> 10.0)
|
||||
- FirebaseInstallations (~> 10.0)
|
||||
- GoogleAppMeasurement (= 10.7.0)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 7.8)
|
||||
- GoogleUtilities/MethodSwizzler (~> 7.8)
|
||||
- GoogleUtilities/Network (~> 7.8)
|
||||
- "GoogleUtilities/NSData+zlib (~> 7.8)"
|
||||
- GoogleAppMeasurement (= 10.9.0)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 7.11)
|
||||
- GoogleUtilities/MethodSwizzler (~> 7.11)
|
||||
- GoogleUtilities/Network (~> 7.11)
|
||||
- "GoogleUtilities/NSData+zlib (~> 7.11)"
|
||||
- nanopb (< 2.30910.0, >= 2.30908.0)
|
||||
- FirebaseCore (10.7.0):
|
||||
- FirebaseCore (10.9.0):
|
||||
- FirebaseCoreInternal (~> 10.0)
|
||||
- GoogleUtilities/Environment (~> 7.8)
|
||||
- GoogleUtilities/Logger (~> 7.8)
|
||||
@ -59,7 +59,7 @@ PODS:
|
||||
- FirebaseCore (~> 10.0)
|
||||
- FirebaseCoreInternal (10.9.0):
|
||||
- "GoogleUtilities/NSData+zlib (~> 7.8)"
|
||||
- FirebaseCrashlytics (10.7.0):
|
||||
- FirebaseCrashlytics (10.9.0):
|
||||
- FirebaseCore (~> 10.5)
|
||||
- FirebaseInstallations (~> 10.0)
|
||||
- FirebaseSessions (~> 10.5)
|
||||
@ -72,7 +72,7 @@ PODS:
|
||||
- GoogleUtilities/Environment (~> 7.8)
|
||||
- GoogleUtilities/UserDefaults (~> 7.8)
|
||||
- PromisesObjC (~> 2.1)
|
||||
- FirebasePerformance (10.7.0):
|
||||
- FirebasePerformance (10.9.0):
|
||||
- FirebaseCore (~> 10.5)
|
||||
- FirebaseInstallations (~> 10.0)
|
||||
- FirebaseRemoteConfig (~> 10.0)
|
||||
@ -104,27 +104,27 @@ PODS:
|
||||
- FMDB (2.7.5):
|
||||
- FMDB/standard (= 2.7.5)
|
||||
- FMDB/standard (2.7.5)
|
||||
- GoogleAppMeasurement (10.7.0):
|
||||
- GoogleAppMeasurement/AdIdSupport (= 10.7.0)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 7.8)
|
||||
- GoogleUtilities/MethodSwizzler (~> 7.8)
|
||||
- GoogleUtilities/Network (~> 7.8)
|
||||
- "GoogleUtilities/NSData+zlib (~> 7.8)"
|
||||
- GoogleAppMeasurement (10.9.0):
|
||||
- GoogleAppMeasurement/AdIdSupport (= 10.9.0)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 7.11)
|
||||
- GoogleUtilities/MethodSwizzler (~> 7.11)
|
||||
- GoogleUtilities/Network (~> 7.11)
|
||||
- "GoogleUtilities/NSData+zlib (~> 7.11)"
|
||||
- nanopb (< 2.30910.0, >= 2.30908.0)
|
||||
- GoogleAppMeasurement/AdIdSupport (10.7.0):
|
||||
- GoogleAppMeasurement/WithoutAdIdSupport (= 10.7.0)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 7.8)
|
||||
- GoogleUtilities/MethodSwizzler (~> 7.8)
|
||||
- GoogleUtilities/Network (~> 7.8)
|
||||
- "GoogleUtilities/NSData+zlib (~> 7.8)"
|
||||
- GoogleAppMeasurement/AdIdSupport (10.9.0):
|
||||
- GoogleAppMeasurement/WithoutAdIdSupport (= 10.9.0)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 7.11)
|
||||
- GoogleUtilities/MethodSwizzler (~> 7.11)
|
||||
- GoogleUtilities/Network (~> 7.11)
|
||||
- "GoogleUtilities/NSData+zlib (~> 7.11)"
|
||||
- nanopb (< 2.30910.0, >= 2.30908.0)
|
||||
- GoogleAppMeasurement/WithoutAdIdSupport (10.7.0):
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 7.8)
|
||||
- GoogleUtilities/MethodSwizzler (~> 7.8)
|
||||
- GoogleUtilities/Network (~> 7.8)
|
||||
- "GoogleUtilities/NSData+zlib (~> 7.8)"
|
||||
- GoogleAppMeasurement/WithoutAdIdSupport (10.9.0):
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 7.11)
|
||||
- GoogleUtilities/MethodSwizzler (~> 7.11)
|
||||
- GoogleUtilities/Network (~> 7.11)
|
||||
- "GoogleUtilities/NSData+zlib (~> 7.11)"
|
||||
- nanopb (< 2.30910.0, >= 2.30908.0)
|
||||
- GoogleDataTransport (9.2.2):
|
||||
- GoogleDataTransport (9.2.3):
|
||||
- GoogleUtilities/Environment (~> 7.7)
|
||||
- nanopb (< 2.30910.0, >= 2.30908.0)
|
||||
- PromisesObjC (< 3.0, >= 1.2)
|
||||
@ -166,7 +166,7 @@ PODS:
|
||||
- shared_preferences_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- sqflite (0.0.2):
|
||||
- sqflite (0.0.3):
|
||||
- Flutter
|
||||
- FMDB (>= 2.7.5)
|
||||
- url_launcher_ios (0.0.1):
|
||||
@ -188,8 +188,8 @@ DEPENDENCIES:
|
||||
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
|
||||
- in_app_review (from `.symlinks/plugins/in_app_review/ios`)
|
||||
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
||||
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/ios`)
|
||||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/ios`)
|
||||
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
||||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||
- sqflite (from `.symlinks/plugins/sqflite/ios`)
|
||||
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
||||
- wakelock (from `.symlinks/plugins/wakelock/ios`)
|
||||
@ -240,9 +240,9 @@ EXTERNAL SOURCES:
|
||||
package_info_plus:
|
||||
:path: ".symlinks/plugins/package_info_plus/ios"
|
||||
path_provider_foundation:
|
||||
:path: ".symlinks/plugins/path_provider_foundation/ios"
|
||||
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
||||
shared_preferences_foundation:
|
||||
:path: ".symlinks/plugins/shared_preferences_foundation/ios"
|
||||
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
||||
sqflite:
|
||||
:path: ".symlinks/plugins/sqflite/ios"
|
||||
url_launcher_ios:
|
||||
@ -255,39 +255,39 @@ EXTERNAL SOURCES:
|
||||
SPEC CHECKSUMS:
|
||||
advanced_in_app_review: fe8fd50b8670cb3dbe67e4c26ca643f7aea8dbb8
|
||||
device_info_plus: e5c5da33f982a436e103237c0c85f9031142abed
|
||||
Firebase: 0219acf760880eeec8ce479895bd7767466d9f81
|
||||
firebase_analytics: e8e294333de66e5429d4aac365966281b4dbfb7d
|
||||
firebase_core: 18d44f087248303a4a8f05d0099a000c46e3c77a
|
||||
firebase_crashlytics: 621d91c0c5752e8219f8fe05a4d1e76394f4896a
|
||||
firebase_performance: 7dd98298ea2f19f480efd59ccbfcad3972ced984
|
||||
Firebase: bd152f0f3d278c4060c5c71359db08ebcfd5a3e2
|
||||
firebase_analytics: 24c9089f960ea2255654488d219cb15a913adf8e
|
||||
firebase_core: fc68c0f9eec4e800b9418deff14a7e0a504016f3
|
||||
firebase_crashlytics: 6c82b5f80f225b2429ebc5fdadde5b7e7735ed4e
|
||||
firebase_performance: 516fbfa3ace3c84add028be727ff08f15d8a3502
|
||||
FirebaseABTesting: 005b70969e2817e2a1e631e8dba29134a04c0622
|
||||
FirebaseAnalytics: f8133442ee6f8512e28ff19e62ce15398bfaeace
|
||||
FirebaseCore: e317665b9d744727a97e623edbbed009320afdd7
|
||||
FirebaseAnalytics: 5ea0db4893825e7b0149d575352cd838236313dc
|
||||
FirebaseCore: b68d3616526ec02e4d155166bbafb8eca64af557
|
||||
FirebaseCoreExtension: d3e9bba2930a8033042112397cd9f006a1bb203d
|
||||
FirebaseCoreInternal: d2b4acb827908e72eca47a9fd896767c3053921e
|
||||
FirebaseCrashlytics: 35fdd1a433b31e28adcf5c8933f4c526691a1e0b
|
||||
FirebaseCrashlytics: b60329455285aff853e54139d8ddbfe1e5f2b9f9
|
||||
FirebaseInstallations: c58489c9caacdbf27d1da60891a87318e20218e0
|
||||
FirebasePerformance: 8281bbaf08aad194001018b932115b7d58a6f00b
|
||||
FirebasePerformance: eee2f5da94fd7e5d15487649f8fe10a90c87c174
|
||||
FirebaseRemoteConfig: 5ea5834e8c518f377bf1af2d97ebd611914ebf2d
|
||||
FirebaseSessions: 44a6782502eb279a214d4adca20891353278760c
|
||||
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
|
||||
flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef
|
||||
flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
|
||||
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
|
||||
GoogleAppMeasurement: fe17c92a32207dd5cdd4e8d742767f2da74857f6
|
||||
GoogleDataTransport: 8378d1fa8ac49753ea6ce70d65a7cb70ce5f66e6
|
||||
GoogleAppMeasurement: 373bcbead1bb6a85be7a64d5d8f96284b762ea9c
|
||||
GoogleDataTransport: f0308f5905a745f94fb91fea9c6cbaf3831cb1bd
|
||||
GoogleUtilities: 9aa0ad5a7bc171f8bae016300bfcfa3fb8425749
|
||||
in_app_review: 318597b3a06c22bb46dc454d56828c85f444f99d
|
||||
nanopb: b552cce312b6c8484180ef47159bc0f65a1f0431
|
||||
package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e
|
||||
path_provider_foundation: 37748e03f12783f9de2cb2c4eadfaa25fe6d4852
|
||||
path_provider_foundation: eaf5b3e458fc0e5fbb9940fb09980e853fe058b8
|
||||
PromisesObjC: 09985d6d70fbe7878040aa746d78236e6946d2ef
|
||||
PromisesSwift: cf9eb58666a43bbe007302226e510b16c1e10959
|
||||
shared_preferences_foundation: 297b3ebca31b34ec92be11acd7fb0ba932c822ca
|
||||
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
|
||||
url_launcher_ios: ae1517e5e344f5544fb090b079e11f399dfbe4d2
|
||||
shared_preferences_foundation: e2dae3258e06f44cc55f49d42024fd8dd03c590c
|
||||
sqflite: 31f7eba61e3074736dff8807a9b41581e4f7f15a
|
||||
url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4
|
||||
wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f
|
||||
webview_flutter_wkwebview: b7e70ef1ddded7e69c796c7390ee74180182971f
|
||||
webview_flutter_wkwebview: 2e2d318f21a5e036e2c3f26171342e95908bd60a
|
||||
|
||||
PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3
|
||||
|
||||
|
@ -268,6 +268,7 @@
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
|
||||
);
|
||||
name = "Thin Binary";
|
||||
outputPaths = (
|
||||
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 6.9 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 15 KiB |
@ -55,6 +55,6 @@
|
||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||
<true/>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@ -3,7 +3,6 @@ import 'dart:convert';
|
||||
import 'package:frosty/models/badges.dart';
|
||||
import 'package:frosty/models/emotes.dart';
|
||||
import 'package:http/http.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
||||
/// The FFZ service for making API calls.
|
||||
class FFZApi {
|
||||
@ -36,7 +35,7 @@ class FFZApi {
|
||||
}
|
||||
|
||||
/// Returns a channel's FFZ room info including custom badges and emote used.
|
||||
Future<Tuple2<RoomFFZ, List<Emote>>> getRoomInfo({required String id}) async {
|
||||
Future<(RoomFFZ, List<Emote>)> getRoomInfo({required String id}) async {
|
||||
final url = Uri.parse('https://api.frankerfacez.com/v1/room/id/$id');
|
||||
|
||||
final response = await _client.get(url);
|
||||
@ -48,11 +47,12 @@ class FFZApi {
|
||||
|
||||
final emotes = emoticons.map((emote) => EmoteFFZ.fromJson(emote));
|
||||
|
||||
return Tuple2(
|
||||
roomInfo,
|
||||
emotes
|
||||
.map((emote) => Emote.fromFFZ(emote, EmoteType.ffzChannel))
|
||||
.toList());
|
||||
return (
|
||||
roomInfo,
|
||||
emotes
|
||||
.map((emote) => Emote.fromFFZ(emote, EmoteType.ffzChannel))
|
||||
.toList()
|
||||
);
|
||||
} else {
|
||||
return Future.error('Failed to get FFZ room info');
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:advanced_in_app_review/advanced_in_app_review.dart';
|
||||
import 'package:device_preview/device_preview.dart';
|
||||
import 'package:firebase_core/firebase_core.dart';
|
||||
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
@ -75,21 +74,16 @@ void main() async {
|
||||
await authStore.init();
|
||||
|
||||
runApp(
|
||||
DevicePreview(
|
||||
enabled: false,
|
||||
builder: (context) {
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
Provider<AuthStore>(create: (_) => authStore),
|
||||
Provider<SettingsStore>(create: (_) => settingsStore),
|
||||
Provider<TwitchApi>(create: (_) => twitchApiService),
|
||||
Provider<BTTVApi>(create: (_) => bttvApiService),
|
||||
Provider<FFZApi>(create: (_) => ffzApiService),
|
||||
Provider<SevenTVApi>(create: (_) => sevenTVApiService),
|
||||
],
|
||||
child: MyApp(firstRun: firstRun),
|
||||
);
|
||||
},
|
||||
MultiProvider(
|
||||
providers: [
|
||||
Provider<AuthStore>(create: (_) => authStore),
|
||||
Provider<SettingsStore>(create: (_) => settingsStore),
|
||||
Provider<TwitchApi>(create: (_) => twitchApiService),
|
||||
Provider<BTTVApi>(create: (_) => bttvApiService),
|
||||
Provider<FFZApi>(create: (_) => ffzApiService),
|
||||
Provider<SevenTVApi>(create: (_) => sevenTVApiService),
|
||||
],
|
||||
child: MyApp(firstRun: firstRun),
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -247,8 +241,6 @@ class _MyAppState extends State<MyApp> {
|
||||
final settingsStore = context.read<SettingsStore>();
|
||||
|
||||
return MaterialApp(
|
||||
useInheritedMediaQuery: true,
|
||||
locale: DevicePreview.locale(context),
|
||||
title: 'Frosty',
|
||||
theme: lightTheme,
|
||||
darkTheme: settingsStore.themeType == ThemeType.dark ||
|
||||
|
@ -157,8 +157,10 @@ abstract class ChatAssetsStoreBase with Store {
|
||||
sevenTVApi.getEmotesGlobal().catchError(onError),
|
||||
sevenTVApi.getEmotesChannel(id: channelId).catchError(onError),
|
||||
ffzApi.getRoomInfo(id: channelId).then((ffzRoom) {
|
||||
ffzRoomInfo = ffzRoom.item1;
|
||||
return ffzRoom.item2;
|
||||
final (roomInfo, emotes) = ffzRoom;
|
||||
|
||||
ffzRoomInfo = roomInfo;
|
||||
return emotes;
|
||||
}).catchError(onError),
|
||||
]).then((assets) => assets.expand((list) => list)).then((emotes) =>
|
||||
_emoteToObject = {for (final emote in emotes) emote.name: emote});
|
||||
|
@ -44,7 +44,7 @@ class ChatMessage extends StatelessWidget {
|
||||
Future<void> onLongPressMessage() async {
|
||||
HapticFeedback.lightImpact();
|
||||
|
||||
await Clipboard.setData(ClipboardData(text: ircMessage.message));
|
||||
await Clipboard.setData(ClipboardData(text: ircMessage.message ?? ''));
|
||||
|
||||
chatStore.updateNotification('Message copied');
|
||||
}
|
||||
|
@ -37,17 +37,8 @@ class _VideoState extends State<Video> with WidgetsBindingObserver {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return WebView(
|
||||
backgroundColor: Colors.black,
|
||||
initialUrl: widget.videoStore.videoUrl,
|
||||
javascriptMode: JavascriptMode.unrestricted,
|
||||
allowsInlineMediaPlayback: true,
|
||||
initialMediaPlaybackPolicy: AutoMediaPlaybackPolicy.always_allow,
|
||||
onWebViewCreated: (controller) =>
|
||||
widget.videoStore.controller = controller,
|
||||
onPageFinished: (string) => widget.videoStore.initVideo(),
|
||||
navigationDelegate: widget.videoStore.handleNavigation,
|
||||
javascriptChannels: widget.videoStore.javascriptChannels,
|
||||
return WebViewWidget(
|
||||
controller: widget.videoStore.videoWebViewController,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@ import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:device_info_plus/device_info_plus.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:frosty/apis/twitch_api.dart';
|
||||
import 'package:frosty/models/stream.dart';
|
||||
@ -11,6 +11,8 @@ import 'package:frosty/screens/settings/stores/settings_store.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:simple_pip_mode/simple_pip.dart';
|
||||
import 'package:webview_flutter/webview_flutter.dart';
|
||||
import 'package:webview_flutter_android/webview_flutter_android.dart';
|
||||
import 'package:webview_flutter_wkwebview/webview_flutter_wkwebview.dart';
|
||||
|
||||
part 'video_store.g.dart';
|
||||
|
||||
@ -29,8 +31,42 @@ abstract class VideoStoreBase with Store {
|
||||
/// The [SimplePip] instance used for initiating PiP on Android.
|
||||
final pip = SimplePip();
|
||||
|
||||
/// The video web view params used for enabling auto play.
|
||||
late final PlatformWebViewControllerCreationParams _videoWebViewParams;
|
||||
|
||||
/// The webview controller used for injecting JavaScript to control the webview and video player.
|
||||
WebViewController? controller;
|
||||
late final WebViewController videoWebViewController =
|
||||
WebViewController.fromPlatformCreationParams(_videoWebViewParams)
|
||||
..setBackgroundColor(Colors.black)
|
||||
..setJavaScriptMode(JavaScriptMode.unrestricted)
|
||||
..addJavaScriptChannel('VideoPause', onMessageReceived: (message) {
|
||||
_paused = true;
|
||||
if (Platform.isAndroid) pip.setIsPlaying(false);
|
||||
})
|
||||
..addJavaScriptChannel('VideoPlaying', onMessageReceived: (message) {
|
||||
_paused = false;
|
||||
if (Platform.isAndroid) pip.setIsPlaying(true);
|
||||
videoWebViewController.runJavaScript(
|
||||
'document.getElementsByTagName("video")[0].muted = false;');
|
||||
videoWebViewController.runJavaScript(
|
||||
'document.getElementsByTagName("video")[0].volume = 1.0;');
|
||||
})
|
||||
..setNavigationDelegate(
|
||||
NavigationDelegate(
|
||||
onPageFinished: (_) => initVideo(),
|
||||
// Used for preventing accidental navigation in the webview.
|
||||
onNavigationRequest: (request) {
|
||||
if (request.url.startsWith('https://player.twitch.tv')) {
|
||||
return NavigationDecision.navigate;
|
||||
}
|
||||
return NavigationDecision.prevent;
|
||||
},
|
||||
),
|
||||
)
|
||||
..loadRequest(Uri.parse(videoUrl));
|
||||
|
||||
// allowsInlineMediaPlayback: true,
|
||||
// initialMediaPlaybackPolicy: AutoMediaPlaybackPolicy.always_allow,
|
||||
|
||||
/// The timer that handles hiding the overlay automatically
|
||||
late Timer _overlayTimer;
|
||||
@ -38,36 +74,6 @@ abstract class VideoStoreBase with Store {
|
||||
/// Disposes the overlay reactions.
|
||||
late final ReactionDisposer _disposeOverlayReaction;
|
||||
|
||||
/// The JavaScript channels used to communicate play/pause from the webview to Flutter.
|
||||
late final javascriptChannels = {
|
||||
JavascriptChannel(
|
||||
name: 'VideoPause',
|
||||
onMessageReceived: (message) {
|
||||
_paused = true;
|
||||
if (Platform.isAndroid) pip.setIsPlaying(false);
|
||||
},
|
||||
),
|
||||
JavascriptChannel(
|
||||
name: 'VideoPlaying',
|
||||
onMessageReceived: (message) {
|
||||
_paused = false;
|
||||
if (Platform.isAndroid) pip.setIsPlaying(true);
|
||||
controller?.runJavascript(
|
||||
'document.getElementsByTagName("video")[0].muted = false;');
|
||||
controller?.runJavascript(
|
||||
'document.getElementsByTagName("video")[0].volume = 1.0;');
|
||||
},
|
||||
),
|
||||
};
|
||||
|
||||
/// Used for preventing accidental navigation in the webview.
|
||||
FutureOr<NavigationDecision> handleNavigation(NavigationRequest navigation) {
|
||||
if (navigation.url.startsWith('https://player.twitch.tv')) {
|
||||
return NavigationDecision.navigate;
|
||||
}
|
||||
return NavigationDecision.prevent;
|
||||
}
|
||||
|
||||
/// If the video is currently paused.
|
||||
///
|
||||
/// Does not pause or play the video, only used for rendering state of the overlay.
|
||||
@ -112,9 +118,25 @@ abstract class VideoStoreBase with Store {
|
||||
// Initialize a reaction that will reload the webview whenever the overlay is toggled.
|
||||
_disposeOverlayReaction = reaction(
|
||||
(_) => settingsStore.showOverlay,
|
||||
(_) => controller?.loadUrl(videoUrl),
|
||||
(_) => videoWebViewController.loadRequest(Uri.parse(videoUrl)),
|
||||
);
|
||||
|
||||
// Initialize the video webview params for iOS to enable video autoplay.
|
||||
if (WebViewPlatform.instance is WebKitWebViewPlatform) {
|
||||
_videoWebViewParams = WebKitWebViewControllerCreationParams(
|
||||
allowsInlineMediaPlayback: true,
|
||||
mediaTypesRequiringUserAction: const <PlaybackMediaTypes>{},
|
||||
);
|
||||
} else {
|
||||
_videoWebViewParams = const PlatformWebViewControllerCreationParams();
|
||||
}
|
||||
|
||||
// Initialize the video webview params for Android to enable video autoplay.
|
||||
if (videoWebViewController.platform is AndroidWebViewController) {
|
||||
(videoWebViewController.platform as AndroidWebViewController)
|
||||
.setMediaPlaybackRequiresUserGesture(false);
|
||||
}
|
||||
|
||||
updateStreamInfo();
|
||||
}
|
||||
|
||||
@ -123,9 +145,9 @@ abstract class VideoStoreBase with Store {
|
||||
Future<void> initVideo() async {
|
||||
// Add event listeners to notify the JavaScript channels when the video plays and pauses.
|
||||
try {
|
||||
controller?.runJavascript(
|
||||
videoWebViewController.runJavaScript(
|
||||
'document.getElementsByTagName("video")[0].addEventListener("pause", () => VideoPause.postMessage("video paused"));');
|
||||
controller?.runJavascript(
|
||||
videoWebViewController.runJavaScript(
|
||||
'document.getElementsByTagName("video")[0].addEventListener("playing", () => VideoPlaying.postMessage("video playing"));');
|
||||
} catch (e) {
|
||||
debugPrint(e.toString());
|
||||
@ -202,7 +224,7 @@ abstract class VideoStoreBase with Store {
|
||||
@action
|
||||
void handleRefresh() {
|
||||
HapticFeedback.lightImpact();
|
||||
controller?.reload();
|
||||
videoWebViewController.reload();
|
||||
updateStreamInfo();
|
||||
}
|
||||
|
||||
@ -210,10 +232,10 @@ abstract class VideoStoreBase with Store {
|
||||
void handlePausePlay() {
|
||||
try {
|
||||
if (_paused) {
|
||||
controller?.runJavascript(
|
||||
'document.getElementsByTagName("video")[0].play();');
|
||||
videoWebViewController
|
||||
.runJavaScript('document.getElementsByTagName("video")[0].play();');
|
||||
} else {
|
||||
controller?.runJavascript(
|
||||
videoWebViewController.runJavaScript(
|
||||
'document.getElementsByTagName("video")[0].pause();');
|
||||
}
|
||||
} catch (e) {
|
||||
@ -230,7 +252,7 @@ abstract class VideoStoreBase with Store {
|
||||
if (Platform.isAndroid) {
|
||||
pip.enterPipMode(autoEnter: true);
|
||||
} else if (Platform.isIOS) {
|
||||
controller?.runJavascript(
|
||||
videoWebViewController.runJavaScript(
|
||||
'document.getElementsByTagName("video")[0].requestPictureInPicture();');
|
||||
}
|
||||
} catch (e) {
|
||||
@ -249,7 +271,7 @@ abstract class VideoStoreBase with Store {
|
||||
|
||||
// Not ideal, but seems like the only way of disposing of the video properly.
|
||||
// Will both prevent the video from continuing to play when dismissed and closes PiP on iOS.
|
||||
if (Platform.isIOS) controller?.reload();
|
||||
if (Platform.isIOS) videoWebViewController.reload();
|
||||
|
||||
_disposeOverlayReaction();
|
||||
}
|
||||
|
@ -27,11 +27,10 @@ class OnboardingLogin extends StatelessWidget {
|
||||
appBar: const FrostyAppBar(
|
||||
title: Text('Connect with Twitch'),
|
||||
),
|
||||
body: WebView(
|
||||
initialUrl: authStore.loginUri.toString(),
|
||||
navigationDelegate: (navigation) => authStore.handleNavigation(
|
||||
navigation: navigation, routeAfter: const OnboardingSetup()),
|
||||
javascriptMode: JavascriptMode.unrestricted,
|
||||
body: WebViewWidget(
|
||||
controller: authStore.createAuthWebViewController(
|
||||
routeAfter: const OnboardingSetup(),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -34,11 +34,8 @@ class ProfileCard extends StatelessWidget {
|
||||
appBar: const FrostyAppBar(
|
||||
title: Text('Connect with Twitch'),
|
||||
),
|
||||
body: WebView(
|
||||
initialUrl: authStore.loginUri.toString(),
|
||||
navigationDelegate: (navigation) =>
|
||||
authStore.handleNavigation(navigation: navigation),
|
||||
javascriptMode: JavascriptMode.unrestricted,
|
||||
body: WebViewWidget(
|
||||
controller: authStore.createAuthWebViewController(),
|
||||
),
|
||||
);
|
||||
},
|
||||
|
@ -51,28 +51,13 @@ abstract class AuthBase with Store {
|
||||
@readonly
|
||||
String? _error;
|
||||
|
||||
/// OAuth URI for the user to login.
|
||||
final loginUri = Uri(
|
||||
scheme: 'https',
|
||||
host: 'id.twitch.tv',
|
||||
path: '/oauth2/authorize',
|
||||
queryParameters: {
|
||||
'client_id': clientId,
|
||||
'redirect_uri': 'https://twitch.tv/login',
|
||||
'response_type': 'token',
|
||||
'scope':
|
||||
'chat:read chat:edit user:read:follows user:read:blocked_users user:manage:blocked_users',
|
||||
'force_verify': 'true',
|
||||
},
|
||||
);
|
||||
|
||||
/// Navigation handler for the login webview. Fires on every navigation request (whenever the URL changes).
|
||||
FutureOr<NavigationDecision> handleNavigation(
|
||||
{required NavigationRequest navigation, Widget? routeAfter}) {
|
||||
{required NavigationRequest request, Widget? routeAfter}) {
|
||||
// Check if the URL is the redirect URI.
|
||||
if (navigation.url.startsWith('https://twitch.tv/login')) {
|
||||
if (request.url.startsWith('https://twitch.tv/login')) {
|
||||
// Extract the token from the query parameters.
|
||||
final uri = Uri.parse(navigation.url.replaceFirst('#', '?'));
|
||||
final uri = Uri.parse(request.url.replaceFirst('#', '?'));
|
||||
final token = uri.queryParameters['access_token'];
|
||||
|
||||
// Login with the provided token.
|
||||
@ -82,7 +67,7 @@ abstract class AuthBase with Store {
|
||||
// Check if the the URL has been redirected to "https://www.twitch.tv/?no-reload=true".
|
||||
// When redirected to the redirect_uri, there will be another redirect to "https://www.twitch.tv/?no-reload=true".
|
||||
// Checking for this will ensure that the user has automatically logged in to Twitch on the WebView itself.
|
||||
if (navigation.url == 'https://www.twitch.tv/?no-reload=true') {
|
||||
if (request.url == 'https://www.twitch.tv/?no-reload=true') {
|
||||
if (routeAfter != null) {
|
||||
navigatorKey.currentState?.pop();
|
||||
navigatorKey.currentState
|
||||
@ -98,6 +83,32 @@ abstract class AuthBase with Store {
|
||||
return NavigationDecision.navigate;
|
||||
}
|
||||
|
||||
WebViewController createAuthWebViewController({Widget? routeAfter}) {
|
||||
return WebViewController()
|
||||
..setJavaScriptMode(JavaScriptMode.unrestricted)
|
||||
..setNavigationDelegate(
|
||||
NavigationDelegate(
|
||||
onNavigationRequest: (request) =>
|
||||
handleNavigation(request: request, routeAfter: routeAfter),
|
||||
),
|
||||
)
|
||||
..loadRequest(
|
||||
Uri(
|
||||
scheme: 'https',
|
||||
host: 'id.twitch.tv',
|
||||
path: '/oauth2/authorize',
|
||||
queryParameters: {
|
||||
'client_id': clientId,
|
||||
'redirect_uri': 'https://twitch.tv/login',
|
||||
'response_type': 'token',
|
||||
'scope':
|
||||
'chat:read chat:edit user:read:follows user:read:blocked_users user:manage:blocked_users',
|
||||
'force_verify': 'true',
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Shows a dialog verifying that the user is sure they want to block/unblock the target user.
|
||||
Future<void> showBlockDialog(
|
||||
BuildContext context, {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class FrostyAppBar extends StatelessWidget with PreferredSizeWidget {
|
||||
class FrostyAppBar extends StatelessWidget implements PreferredSizeWidget {
|
||||
final Widget title;
|
||||
final bool? centerTitle;
|
||||
final List<Widget>? actions;
|
||||
|
@ -44,9 +44,12 @@ class BlockReportModal extends StatelessWidget {
|
||||
appBar: FrostyAppBar(
|
||||
title: Text('Report $name'),
|
||||
),
|
||||
body: WebView(
|
||||
initialUrl: 'https://www.twitch.tv/$userLogin/report',
|
||||
javascriptMode: JavascriptMode.unrestricted,
|
||||
body: WebViewWidget(
|
||||
controller: WebViewController()
|
||||
..setJavaScriptMode(JavaScriptMode.unrestricted)
|
||||
..loadRequest(
|
||||
Uri.parse('https://www.twitch.tv/$userLogin/report'),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
|
485
pubspec.lock
24
pubspec.yaml
@ -12,13 +12,13 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
# build by specifying --build-name and --build-number, respectively.
|
||||
# In Android, build-name is used as versionName while build-number used as versionCode.
|
||||
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
|
||||
# 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 is used as CFBundleVersion.
|
||||
# Read more about iOS versioning at
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
version: 3.1.1+37
|
||||
|
||||
environment:
|
||||
sdk: ">=2.15.0 <3.0.0"
|
||||
sdk: '>=3.0.0 <4.0.0'
|
||||
|
||||
# Dependencies specify other packages that your package needs in order to work.
|
||||
# To automatically upgrade your package dependencies to the latest versions
|
||||
@ -37,23 +37,21 @@ dependencies:
|
||||
cupertino_icons: ^1.0.2
|
||||
http: ^0.13.3
|
||||
web_socket_channel: ^2.1.0
|
||||
flutter_secure_storage: ^7.0.1
|
||||
intl: ^0.17.0
|
||||
flutter_secure_storage: ^8.0.0
|
||||
intl: ^0.18.1
|
||||
cached_network_image: ^3.1.0
|
||||
webview_flutter: ^3.0.0
|
||||
webview_flutter: ^4.2.0
|
||||
provider: ^6.0.1
|
||||
mobx: ^2.0.7+4
|
||||
flutter_mobx: ^2.0.0
|
||||
shared_preferences: ^2.0.8
|
||||
tuple: ^2.0.0
|
||||
flutter_svg: ^1.0.0
|
||||
flutter_svg: ^2.0.5
|
||||
url_launcher: ^6.0.17
|
||||
package_info_plus: ^3.0.2
|
||||
collection: ^1.16.0
|
||||
flutter_cache_manager: ^3.3.0
|
||||
device_info_plus: ^8.0.0
|
||||
wakelock: ^0.6.2
|
||||
device_preview: ^1.1.0
|
||||
simple_icons: ^7.10.0
|
||||
simple_pip_mode:
|
||||
git:
|
||||
@ -63,11 +61,13 @@ dependencies:
|
||||
firebase_performance: ^0.9.1+1
|
||||
firebase_analytics: ^10.2.1
|
||||
advanced_in_app_review: ^1.1.3
|
||||
webview_flutter_android: ^3.7.0
|
||||
webview_flutter_wkwebview: ^3.4.3
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
||||
|
||||
# The "flutter_lints" package below contains a set of recommended lints to
|
||||
# encourage good coding practices. The lint set provided by the package is
|
||||
# activated in the `analysis_options.yaml` file located at the root of your
|
||||
@ -78,12 +78,12 @@ dev_dependencies:
|
||||
json_serializable: ^6.0.0
|
||||
mobx_codegen: ^2.0.6
|
||||
flutter_native_splash: ^2.0.5
|
||||
flutter_launcher_icons: ^0.11.0
|
||||
flutter_launcher_icons: ^0.13.1
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://dart.dev/tools/pub/pubspec
|
||||
|
||||
# The following section is specific to Flutter.
|
||||
# The following section is specific to Flutter packages.
|
||||
flutter:
|
||||
|
||||
# The following line ensures that the Material Icons font is
|
||||
@ -113,7 +113,7 @@ flutter:
|
||||
- assets/icons/logo.svg
|
||||
|
||||
# An image asset can refer to one or more resolution-specific "variants", see
|
||||
# https://flutter.dev/assets-and-images/#resolution-aware.
|
||||
# https://flutter.dev/assets-and-images/#resolution-aware
|
||||
|
||||
# For details regarding adding assets from package dependencies, see
|
||||
# https://flutter.dev/assets-and-images/#from-packages
|
||||
|