Compare commits
16 Commits
4094f7edba
...
dao
Author | SHA1 | Date | |
---|---|---|---|
604b099010 | |||
c6030f8ac5 | |||
ffd696053a | |||
fb0b73ecaf | |||
1234a300e1 | |||
3153bf13f9 | |||
68443b3427 | |||
5d27744ead | |||
67d7a374d4 | |||
54d47245ae | |||
7f2cf0b49f | |||
8fe60e7ae3 | |||
b2e2eb67b0 | |||
0dc7c3ced0 | |||
13fe7e2ef4 | |||
d6e62024d7 |
143
.gitignore
vendored
143
.gitignore
vendored
@ -9,6 +9,7 @@
|
|||||||
.history
|
.history
|
||||||
.svn/
|
.svn/
|
||||||
migrate_working_dir/
|
migrate_working_dir/
|
||||||
|
bkp
|
||||||
|
|
||||||
# IntelliJ related
|
# IntelliJ related
|
||||||
*.iml
|
*.iml
|
||||||
@ -44,3 +45,145 @@ app.*.map.json
|
|||||||
/android/app/debug
|
/android/app/debug
|
||||||
/android/app/profile
|
/android/app/profile
|
||||||
/android/app/release
|
/android/app/release
|
||||||
|
|
||||||
|
|
||||||
|
# Do not remove or rename entries in this file, only add new ones
|
||||||
|
# See https://github.com/flutter/flutter/issues/128635 for more context.
|
||||||
|
|
||||||
|
# Miscellaneous
|
||||||
|
*.class
|
||||||
|
*.lock
|
||||||
|
*.log
|
||||||
|
*.pyc
|
||||||
|
*.swp
|
||||||
|
.DS_Store
|
||||||
|
.atom/
|
||||||
|
.buildlog/
|
||||||
|
.history
|
||||||
|
.svn/
|
||||||
|
|
||||||
|
# IntelliJ related
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
*.iws
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# Visual Studio Code related
|
||||||
|
.classpath
|
||||||
|
.project
|
||||||
|
.settings/
|
||||||
|
.vscode/*
|
||||||
|
|
||||||
|
# Flutter repo-specific
|
||||||
|
/bin/cache/
|
||||||
|
/bin/internal/bootstrap.bat
|
||||||
|
/bin/internal/bootstrap.sh
|
||||||
|
/bin/mingit/
|
||||||
|
/dev/benchmarks/mega_gallery/
|
||||||
|
/dev/bots/.recipe_deps
|
||||||
|
/dev/bots/android_tools/
|
||||||
|
/dev/devicelab/ABresults*.json
|
||||||
|
/dev/docs/doc/
|
||||||
|
/dev/docs/api_docs.zip
|
||||||
|
/dev/docs/flutter.docs.zip
|
||||||
|
/dev/docs/lib/
|
||||||
|
/dev/docs/pubspec.yaml
|
||||||
|
/dev/integration_tests/**/xcuserdata
|
||||||
|
/dev/integration_tests/**/Pods
|
||||||
|
/packages/flutter/coverage/
|
||||||
|
version
|
||||||
|
analysis_benchmark.json
|
||||||
|
|
||||||
|
# packages file containing multi-root paths
|
||||||
|
.packages.generated
|
||||||
|
|
||||||
|
# Flutter/Dart/Pub related
|
||||||
|
**/doc/api/
|
||||||
|
.dart_tool/
|
||||||
|
.flutter-plugins
|
||||||
|
.flutter-plugins-dependencies
|
||||||
|
**/generated_plugin_registrant.dart
|
||||||
|
.packages
|
||||||
|
.pub-preload-cache/
|
||||||
|
.pub-cache/
|
||||||
|
.pub/
|
||||||
|
build/
|
||||||
|
flutter_*.png
|
||||||
|
linked_*.ds
|
||||||
|
unlinked.ds
|
||||||
|
unlinked_spec.ds
|
||||||
|
|
||||||
|
# Android related
|
||||||
|
**/android/**/gradle-wrapper.jar
|
||||||
|
.gradle/
|
||||||
|
**/android/captures/
|
||||||
|
**/android/gradlew
|
||||||
|
**/android/gradlew.bat
|
||||||
|
**/android/local.properties
|
||||||
|
**/android/**/GeneratedPluginRegistrant.java
|
||||||
|
**/android/key.properties
|
||||||
|
*.jks
|
||||||
|
|
||||||
|
# iOS/XCode related
|
||||||
|
**/ios/**/*.mode1v3
|
||||||
|
**/ios/**/*.mode2v3
|
||||||
|
**/ios/**/*.moved-aside
|
||||||
|
**/ios/**/*.pbxuser
|
||||||
|
**/ios/**/*.perspectivev3
|
||||||
|
**/ios/**/*sync/
|
||||||
|
**/ios/**/.sconsign.dblite
|
||||||
|
**/ios/**/.tags*
|
||||||
|
**/ios/**/.vagrant/
|
||||||
|
**/ios/**/DerivedData/
|
||||||
|
**/ios/**/Icon?
|
||||||
|
**/ios/**/Pods/
|
||||||
|
**/ios/**/.symlinks/
|
||||||
|
**/ios/**/profile
|
||||||
|
**/ios/**/xcuserdata
|
||||||
|
**/ios/.generated/
|
||||||
|
**/ios/Flutter/.last_build_id
|
||||||
|
**/ios/Flutter/App.framework
|
||||||
|
**/ios/Flutter/Flutter.framework
|
||||||
|
**/ios/Flutter/Flutter.podspec
|
||||||
|
**/ios/Flutter/Generated.xcconfig
|
||||||
|
**/ios/Flutter/ephemeral
|
||||||
|
**/ios/Flutter/app.flx
|
||||||
|
**/ios/Flutter/app.zip
|
||||||
|
**/ios/Flutter/flutter_assets/
|
||||||
|
**/ios/Flutter/flutter_export_environment.sh
|
||||||
|
**/ios/ServiceDefinitions.json
|
||||||
|
**/ios/Runner/GeneratedPluginRegistrant.*
|
||||||
|
|
||||||
|
# macOS
|
||||||
|
**/Flutter/ephemeral/
|
||||||
|
**/Pods/
|
||||||
|
**/macos/Flutter/GeneratedPluginRegistrant.swift
|
||||||
|
**/macos/Flutter/ephemeral
|
||||||
|
**/xcuserdata/
|
||||||
|
|
||||||
|
# Windows
|
||||||
|
**/windows/flutter/ephemeral/
|
||||||
|
**/windows/flutter/generated_plugin_registrant.cc
|
||||||
|
**/windows/flutter/generated_plugin_registrant.h
|
||||||
|
**/windows/flutter/generated_plugins.cmake
|
||||||
|
|
||||||
|
# Linux
|
||||||
|
**/linux/flutter/ephemeral/
|
||||||
|
**/linux/flutter/generated_plugin_registrant.cc
|
||||||
|
**/linux/flutter/generated_plugin_registrant.h
|
||||||
|
**/linux/flutter/generated_plugins.cmake
|
||||||
|
|
||||||
|
# Coverage
|
||||||
|
coverage/
|
||||||
|
|
||||||
|
# Symbols
|
||||||
|
app.*.symbols
|
||||||
|
|
||||||
|
# Exceptions to above rules.
|
||||||
|
!**/ios/**/default.mode1v3
|
||||||
|
!**/ios/**/default.mode2v3
|
||||||
|
!**/ios/**/default.pbxuser
|
||||||
|
!**/ios/**/default.perspectivev3
|
||||||
|
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
|
||||||
|
!/dev/ci/**/Gemfile.lock
|
||||||
|
!.vscode/settings.json
|
34
.metadata
34
.metadata
@ -1,11 +1,11 @@
|
|||||||
# This file tracks properties of this Flutter project.
|
# This file tracks properties of this Flutter project.
|
||||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||||
#
|
#
|
||||||
# This file should be version controlled.
|
# This file should be version controlled and should not be manually edited.
|
||||||
|
|
||||||
version:
|
version:
|
||||||
revision: 9944297138845a94256f1cf37beb88ff9a8e811a
|
revision: "dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668"
|
||||||
channel: stable
|
channel: "stable"
|
||||||
|
|
||||||
project_type: app
|
project_type: app
|
||||||
|
|
||||||
@ -13,26 +13,26 @@ project_type: app
|
|||||||
migration:
|
migration:
|
||||||
platforms:
|
platforms:
|
||||||
- platform: root
|
- platform: root
|
||||||
create_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
|
create_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668
|
||||||
base_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
|
base_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668
|
||||||
- platform: android
|
- platform: android
|
||||||
create_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
|
create_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668
|
||||||
base_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
|
base_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668
|
||||||
- platform: ios
|
- platform: ios
|
||||||
create_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
|
create_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668
|
||||||
base_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
|
base_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668
|
||||||
- platform: linux
|
- platform: linux
|
||||||
create_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
|
create_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668
|
||||||
base_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
|
base_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668
|
||||||
- platform: macos
|
- platform: macos
|
||||||
create_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
|
create_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668
|
||||||
base_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
|
base_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668
|
||||||
- platform: web
|
- platform: web
|
||||||
create_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
|
create_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668
|
||||||
base_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
|
base_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668
|
||||||
- platform: windows
|
- platform: windows
|
||||||
create_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
|
create_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668
|
||||||
base_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
|
base_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668
|
||||||
|
|
||||||
# User provided section
|
# User provided section
|
||||||
|
|
||||||
|
74
.vscode/dart.code-snippets
vendored
74
.vscode/dart.code-snippets
vendored
@ -1,74 +0,0 @@
|
|||||||
{
|
|
||||||
// Place your snippets for dart here. Each snippet is defined under a snippet name and has a prefix, body and
|
|
||||||
// description. The prefix is what is used to trigger the snippet and the body will be expanded and inserted. Possible variables are:
|
|
||||||
// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders. Placeholders with the
|
|
||||||
// same ids are connected.
|
|
||||||
// Example:
|
|
||||||
// "Print to console": {
|
|
||||||
// "prefix": "log",
|
|
||||||
// "body": [
|
|
||||||
// "console.log('$1');",
|
|
||||||
// "$2"
|
|
||||||
// ],
|
|
||||||
// "description": "Log output to console"
|
|
||||||
// }
|
|
||||||
"Stateless Widget": {
|
|
||||||
"prefix": "stateless",
|
|
||||||
"body": [
|
|
||||||
"import 'package:flutter/material.dart';",
|
|
||||||
"\n",
|
|
||||||
"class ${1:MyClass} extends StatelessWidget {",
|
|
||||||
"@override",
|
|
||||||
"Widget build(BuildContext context) {",
|
|
||||||
"return Container($0);}}"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"Stateful Widget": {
|
|
||||||
"prefix": "stateful",
|
|
||||||
"body": [
|
|
||||||
"import 'package:flutter/material.dart';",
|
|
||||||
"\n",
|
|
||||||
"class ${1:MyClass} extends StatefulWidget {",
|
|
||||||
"const ${1:MyClass}({Key key, $2}) : super(key: key);",
|
|
||||||
"\n",
|
|
||||||
"@override",
|
|
||||||
"_${1:MyClass}State createState() => _${1:MyClass}State();",
|
|
||||||
"}",
|
|
||||||
"\n",
|
|
||||||
"class _${1:MyClass}State extends State<${1:MyClass}> {",
|
|
||||||
"\n",
|
|
||||||
"@override",
|
|
||||||
"void initState() {",
|
|
||||||
"super.initState();",
|
|
||||||
"}",
|
|
||||||
"\n",
|
|
||||||
"@override",
|
|
||||||
"void dispose() {",
|
|
||||||
"super.dispose();",
|
|
||||||
"}",
|
|
||||||
"\n",
|
|
||||||
"@override",
|
|
||||||
"Widget build(BuildContext context) {",
|
|
||||||
"return Container($0);}}"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"Widget Test": {
|
|
||||||
"prefix": "widgettest",
|
|
||||||
"body": [
|
|
||||||
"import 'package:flutter_test/flutter_test.dart';",
|
|
||||||
"import 'package:flutter/material.dart';",
|
|
||||||
"//import 'package:piota/${1:widgetfile}.dart';",
|
|
||||||
"\n",
|
|
||||||
"import 'ui_test_util.dart';",
|
|
||||||
"\n",
|
|
||||||
"void main() {",
|
|
||||||
"group('${2:groupname}', () {",
|
|
||||||
"final testableWidget = testWidget(${3:Container()},Size(375, 667));",
|
|
||||||
"testWidgets('${3:Container()} test', (WidgetTester tester) async {",
|
|
||||||
"final finder = find.byKey(Key('${5:keyname}'));",
|
|
||||||
"await tester.pumpWidget(testableWidget);",
|
|
||||||
"expect(finder, findsOneWidget);",
|
|
||||||
"});});}"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
@ -9,6 +9,10 @@
|
|||||||
# packages, and plugins designed to encourage good coding practices.
|
# packages, and plugins designed to encourage good coding practices.
|
||||||
include: package:flutter_lints/flutter.yaml
|
include: package:flutter_lints/flutter.yaml
|
||||||
|
|
||||||
|
analyzer:
|
||||||
|
exclude:
|
||||||
|
- "**/*.g.dart"
|
||||||
|
|
||||||
linter:
|
linter:
|
||||||
# The lint rules applied to this project can be customized in the
|
# The lint rules applied to this project can be customized in the
|
||||||
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
|
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
|
||||||
|
2
android/.gitignore
vendored
2
android/.gitignore
vendored
@ -7,7 +7,7 @@ gradle-wrapper.jar
|
|||||||
GeneratedPluginRegistrant.java
|
GeneratedPluginRegistrant.java
|
||||||
|
|
||||||
# Remember to never publicly share your keystore.
|
# Remember to never publicly share your keystore.
|
||||||
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
|
# See https://flutter.dev/to/reference-keystore
|
||||||
key.properties
|
key.properties
|
||||||
**/*.keystore
|
**/*.keystore
|
||||||
**/*.jks
|
**/*.jks
|
||||||
|
@ -1,71 +1,44 @@
|
|||||||
def localProperties = new Properties()
|
plugins {
|
||||||
def localPropertiesFile = rootProject.file('local.properties')
|
id "com.android.application"
|
||||||
if (localPropertiesFile.exists()) {
|
id "kotlin-android"
|
||||||
localPropertiesFile.withReader('UTF-8') { reader ->
|
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
|
||||||
localProperties.load(reader)
|
id "dev.flutter.flutter-gradle-plugin"
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def flutterRoot = localProperties.getProperty('flutter.sdk')
|
|
||||||
if (flutterRoot == null) {
|
|
||||||
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
|
|
||||||
}
|
|
||||||
|
|
||||||
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
|
|
||||||
if (flutterVersionCode == null) {
|
|
||||||
flutterVersionCode = '1'
|
|
||||||
}
|
|
||||||
|
|
||||||
def flutterVersionName = localProperties.getProperty('flutter.versionName')
|
|
||||||
if (flutterVersionName == null) {
|
|
||||||
flutterVersionName = '1.0'
|
|
||||||
}
|
|
||||||
|
|
||||||
apply plugin: 'com.android.application'
|
|
||||||
apply plugin: 'kotlin-android'
|
|
||||||
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion flutter.compileSdkVersion
|
namespace = "com.example.sendtrain"
|
||||||
ndkVersion flutter.ndkVersion
|
compileSdk = flutter.compileSdkVersion
|
||||||
|
ndkVersion = flutter.ndkVersion
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility JavaVersion.VERSION_1_8
|
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||||
targetCompatibility JavaVersion.VERSION_1_8
|
targetCompatibility = JavaVersion.VERSION_1_8
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = '1.8'
|
jvmTarget = JavaVersion.VERSION_1_8
|
||||||
}
|
|
||||||
|
|
||||||
sourceSets {
|
|
||||||
main.java.srcDirs += 'src/main/kotlin'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
// 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 "com.sendtrain.sendtrain"
|
applicationId = "com.example.sendtrain"
|
||||||
// You can update the following values to match your application needs.
|
// You can update the following values to match your application needs.
|
||||||
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
|
// For more information, see: https://flutter.dev/to/review-gradle-config.
|
||||||
minSdkVersion flutter.minSdkVersion
|
minSdk = flutter.minSdkVersion
|
||||||
targetSdkVersion flutter.targetSdkVersion
|
targetSdk = flutter.targetSdkVersion
|
||||||
versionCode flutterVersionCode.toInteger()
|
versionCode = flutter.versionCode
|
||||||
versionName flutterVersionName
|
versionName = flutter.versionName
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
// TODO: Add your own signing config for the release build.
|
// TODO: Add your own signing config for the release build.
|
||||||
// Signing with the debug keys for now, so `flutter run --release` works.
|
// Signing with the debug keys for now, so `flutter run --release` works.
|
||||||
signingConfig signingConfigs.debug
|
signingConfig = signingConfigs.debug
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
flutter {
|
flutter {
|
||||||
source '../..'
|
source = "../.."
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
package="com.sendtrain.sendtrain">
|
|
||||||
<!-- The INTERNET permission is required for development. Specifically,
|
<!-- The INTERNET permission is required for development. Specifically,
|
||||||
the Flutter tool needs it to communicate with the running application
|
the Flutter tool needs it to communicate with the running application
|
||||||
to allow setting breakpoints, to provide hot reload, etc.
|
to allow setting breakpoints, to provide hot reload, etc.
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
package="com.sendtrain.sendtrain">
|
|
||||||
<application
|
<application
|
||||||
android:label="SendTrain"
|
android:label="sendtrain"
|
||||||
android:name="${applicationName}"
|
android:name="${applicationName}"
|
||||||
android:icon="@mipmap/ic_launcher">
|
android:icon="@mipmap/ic_launcher">
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:launchMode="singleTop"
|
android:launchMode="singleTop"
|
||||||
|
android:taskAffinity=""
|
||||||
android:theme="@style/LaunchTheme"
|
android:theme="@style/LaunchTheme"
|
||||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||||
android:hardwareAccelerated="true"
|
android:hardwareAccelerated="true"
|
||||||
@ -31,4 +31,15 @@
|
|||||||
android:name="flutterEmbedding"
|
android:name="flutterEmbedding"
|
||||||
android:value="2" />
|
android:value="2" />
|
||||||
</application>
|
</application>
|
||||||
|
<!-- Required to query activities that can process text, see:
|
||||||
|
https://developer.android.com/training/package-visibility and
|
||||||
|
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
|
||||||
|
|
||||||
|
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
|
||||||
|
<queries>
|
||||||
|
<intent>
|
||||||
|
<action android:name="android.intent.action.PROCESS_TEXT"/>
|
||||||
|
<data android:mimeType="text/plain"/>
|
||||||
|
</intent>
|
||||||
|
</queries>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
package com.example.sendtrain
|
||||||
|
|
||||||
|
import io.flutter.embedding.android.FlutterActivity
|
||||||
|
|
||||||
|
class MainActivity: FlutterActivity()
|
@ -1,6 +0,0 @@
|
|||||||
package com.sendtrain.sendtrain
|
|
||||||
|
|
||||||
import io.flutter.embedding.android.FlutterActivity
|
|
||||||
|
|
||||||
class MainActivity: FlutterActivity() {
|
|
||||||
}
|
|
@ -1,5 +1,4 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
package="com.sendtrain.sendtrain">
|
|
||||||
<!-- The INTERNET permission is required for development. Specifically,
|
<!-- The INTERNET permission is required for development. Specifically,
|
||||||
the Flutter tool needs it to communicate with the running application
|
the Flutter tool needs it to communicate with the running application
|
||||||
to allow setting breakpoints, to provide hot reload, etc.
|
to allow setting breakpoints, to provide hot reload, etc.
|
||||||
|
@ -1,16 +1,3 @@
|
|||||||
buildscript {
|
|
||||||
ext.kotlin_version = '1.7.10'
|
|
||||||
repositories {
|
|
||||||
google()
|
|
||||||
mavenCentral()
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
classpath 'com.android.tools.build:gradle:7.2.0'
|
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
@ -18,12 +5,12 @@ allprojects {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rootProject.buildDir = '../build'
|
rootProject.buildDir = "../build"
|
||||||
subprojects {
|
subprojects {
|
||||||
project.buildDir = "${rootProject.buildDir}/${project.name}"
|
project.buildDir = "${rootProject.buildDir}/${project.name}"
|
||||||
}
|
}
|
||||||
subprojects {
|
subprojects {
|
||||||
project.evaluationDependsOn(':app')
|
project.evaluationDependsOn(":app")
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register("clean", Delete) {
|
tasks.register("clean", Delete) {
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
org.gradle.jvmargs=-Xmx1536M
|
org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=2G -XX:+HeapDumpOnOutOfMemoryError
|
||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
android.enableJetifier=true
|
android.enableJetifier=true
|
||||||
|
@ -2,4 +2,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.5-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip
|
||||||
|
@ -1,11 +1,25 @@
|
|||||||
include ':app'
|
pluginManagement {
|
||||||
|
def flutterSdkPath = {
|
||||||
|
def properties = new Properties()
|
||||||
|
file("local.properties").withInputStream { properties.load(it) }
|
||||||
|
def flutterSdkPath = properties.getProperty("flutter.sdk")
|
||||||
|
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
|
||||||
|
return flutterSdkPath
|
||||||
|
}()
|
||||||
|
|
||||||
def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
|
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
|
||||||
def properties = new Properties()
|
|
||||||
|
|
||||||
assert localPropertiesFile.exists()
|
repositories {
|
||||||
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
gradlePluginPortal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def flutterSdkPath = properties.getProperty("flutter.sdk")
|
plugins {
|
||||||
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
|
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
|
||||||
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
|
id "com.android.application" version "8.1.0" apply false
|
||||||
|
id "org.jetbrains.kotlin.android" version "2.1.0" apply false
|
||||||
|
}
|
||||||
|
|
||||||
|
include ":app"
|
||||||
|
9
build.yaml
Normal file
9
build.yaml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
targets:
|
||||||
|
$default:
|
||||||
|
builders:
|
||||||
|
drift_dev:
|
||||||
|
options:
|
||||||
|
schema_dir: lib/database/drift_schemas/
|
||||||
|
databases:
|
||||||
|
# Required: A name for the database and it's path
|
||||||
|
sendtrain: lib/database/database.dart
|
@ -1,33 +0,0 @@
|
|||||||
PODS:
|
|
||||||
- Flutter (1.0.0)
|
|
||||||
- flutter_inappwebview (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- flutter_inappwebview/Core (= 0.0.1)
|
|
||||||
- OrderedSet (~> 5.0)
|
|
||||||
- flutter_inappwebview/Core (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- OrderedSet (~> 5.0)
|
|
||||||
- OrderedSet (5.0.0)
|
|
||||||
|
|
||||||
DEPENDENCIES:
|
|
||||||
- Flutter (from `Flutter`)
|
|
||||||
- flutter_inappwebview (from `.symlinks/plugins/flutter_inappwebview/ios`)
|
|
||||||
|
|
||||||
SPEC REPOS:
|
|
||||||
trunk:
|
|
||||||
- OrderedSet
|
|
||||||
|
|
||||||
EXTERNAL SOURCES:
|
|
||||||
Flutter:
|
|
||||||
:path: Flutter
|
|
||||||
flutter_inappwebview:
|
|
||||||
:path: ".symlinks/plugins/flutter_inappwebview/ios"
|
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
|
||||||
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
|
|
||||||
flutter_inappwebview: bfd58618f49dc62f2676de690fc6dcda1d6c3721
|
|
||||||
OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c
|
|
||||||
|
|
||||||
PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3
|
|
||||||
|
|
||||||
COCOAPODS: 1.12.0
|
|
12
ios/RunnerTests/RunnerTests.swift
Normal file
12
ios/RunnerTests/RunnerTests.swift
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import Flutter
|
||||||
|
import UIKit
|
||||||
|
import XCTest
|
||||||
|
|
||||||
|
class RunnerTests: XCTestCase {
|
||||||
|
|
||||||
|
func testExample() {
|
||||||
|
// If you add code to the Runner application, consider adding tests here.
|
||||||
|
// See https://developer.apple.com/documentation/xctest for more information about using XCTest.
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
35
lib/daos/actions_dao.dart
Normal file
35
lib/daos/actions_dao.dart
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:sendtrain/database/database.dart';
|
||||||
|
|
||||||
|
part 'actions_dao.g.dart';
|
||||||
|
|
||||||
|
@DriftAccessor(tables: [Actions])
|
||||||
|
class ActionsDao extends DatabaseAccessor<AppDatabase> with _$ActionsDaoMixin {
|
||||||
|
ActionsDao(super.db);
|
||||||
|
|
||||||
|
Future<List<Action>> all() async {
|
||||||
|
return await select(actions).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Action> find(int id) async {
|
||||||
|
return await (select(actions)..where((action) => action.id.equals(id) )).getSingle();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<Action>> fromActivity(Activity activity) async {
|
||||||
|
final result = select(db.activityActions).join(
|
||||||
|
[
|
||||||
|
innerJoin(
|
||||||
|
db.actions,
|
||||||
|
db.actions.id.equalsExp(db.activityActions.actionId),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
..where(db.activityActions.activityId.equals(activity.id));
|
||||||
|
|
||||||
|
final actions = (await result.get())
|
||||||
|
.map((e) => e.readTable(db.actions))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
return actions;
|
||||||
|
}
|
||||||
|
}
|
8
lib/daos/actions_dao.g.dart
Normal file
8
lib/daos/actions_dao.g.dart
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'actions_dao.dart';
|
||||||
|
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
mixin _$ActionsDaoMixin on DatabaseAccessor<AppDatabase> {
|
||||||
|
$ActionsTable get actions => attachedDatabase.actions;
|
||||||
|
}
|
35
lib/daos/activities_dao.dart
Normal file
35
lib/daos/activities_dao.dart
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:sendtrain/database/database.dart';
|
||||||
|
|
||||||
|
part 'activities_dao.g.dart';
|
||||||
|
|
||||||
|
@DriftAccessor(tables: [Activities])
|
||||||
|
class ActivitiesDao extends DatabaseAccessor<AppDatabase> with _$ActivitiesDaoMixin {
|
||||||
|
ActivitiesDao(super.db);
|
||||||
|
|
||||||
|
Future<List<Activity>> all() async {
|
||||||
|
return await select(activities).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Activity> find(int id) async {
|
||||||
|
return await (select(activities)..where((activity) => activity.id.equals(id) )).getSingle();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<Activity>> sessionActivities(int id) async {
|
||||||
|
final result = select(db.sessionActivities).join(
|
||||||
|
[
|
||||||
|
innerJoin(
|
||||||
|
db.activities,
|
||||||
|
db.activities.id
|
||||||
|
.equalsExp(db.sessionActivities.activityId),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)..where(db.sessionActivities.sessionId.equals(id));
|
||||||
|
|
||||||
|
final activities = (await result.get())
|
||||||
|
.map((e) => e.readTable(db.activities))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
return activities;
|
||||||
|
}
|
||||||
|
}
|
8
lib/daos/activities_dao.g.dart
Normal file
8
lib/daos/activities_dao.g.dart
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'activities_dao.dart';
|
||||||
|
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
mixin _$ActivitiesDaoMixin on DatabaseAccessor<AppDatabase> {
|
||||||
|
$ActivitiesTable get activities => attachedDatabase.activities;
|
||||||
|
}
|
30
lib/daos/activity_actions_dao.dart
Normal file
30
lib/daos/activity_actions_dao.dart
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:sendtrain/database/database.dart';
|
||||||
|
|
||||||
|
part 'activity_actions_dao.g.dart';
|
||||||
|
|
||||||
|
@DriftAccessor(tables: [ActivityActions])
|
||||||
|
class ActivityActionsDao extends DatabaseAccessor<AppDatabase> with _$ActivityActionsDaoMixin {
|
||||||
|
ActivityActionsDao(super.db);
|
||||||
|
|
||||||
|
Future<List<ActivityAction>> all() => select(activityActions).get();
|
||||||
|
Stream<List<ActivityAction>> watch() => select(activityActions).watch();
|
||||||
|
Future insert(ActivityAction activityAction) => into(activityActions).insert(activityAction);
|
||||||
|
Future replace(ActivityAction activityAction) => update(activityActions).replace(activityAction);
|
||||||
|
Future remove(ActivityAction activityAction) => delete(activityActions).delete(activityAction);
|
||||||
|
|
||||||
|
// Future<List<ActivityAction>> all() async {
|
||||||
|
// return await select(activityActions).get();
|
||||||
|
// }
|
||||||
|
|
||||||
|
Future<ActivityAction> find(int id) async {
|
||||||
|
return await (select(activityActions)..where((activityAction) => activityAction.id.equals(id) )).getSingle();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<ActivityAction>> fromActivityId(int id) async {
|
||||||
|
final result = db.managers.activityActions
|
||||||
|
.filter((activityAction) => activityAction.activityId.id(id));
|
||||||
|
|
||||||
|
return result.get();
|
||||||
|
}
|
||||||
|
}
|
10
lib/daos/activity_actions_dao.g.dart
Normal file
10
lib/daos/activity_actions_dao.g.dart
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'activity_actions_dao.dart';
|
||||||
|
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
mixin _$ActivityActionsDaoMixin on DatabaseAccessor<AppDatabase> {
|
||||||
|
$ActivitiesTable get activities => attachedDatabase.activities;
|
||||||
|
$ActionsTable get actions => attachedDatabase.actions;
|
||||||
|
$ActivityActionsTable get activityActions => attachedDatabase.activityActions;
|
||||||
|
}
|
57
lib/daos/media_items_dao.dart
Normal file
57
lib/daos/media_items_dao.dart
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:sendtrain/database/database.dart';
|
||||||
|
|
||||||
|
part 'media_items_dao.g.dart';
|
||||||
|
|
||||||
|
@DriftAccessor(tables: [MediaItems])
|
||||||
|
class MediaItemsDao extends DatabaseAccessor<AppDatabase> with _$MediaItemsDaoMixin {
|
||||||
|
MediaItemsDao(super.db);
|
||||||
|
|
||||||
|
Future<List<MediaItem>> all() async {
|
||||||
|
return await select(mediaItems).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<MediaItem> find(int id) async {
|
||||||
|
return await (select(mediaItems)..where((mediaItem) => mediaItem.id.equals(id) )).getSingle();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<MediaItem>> fromActivity(Activity activity) async {
|
||||||
|
final result = select(db.objectMediaItems).join(
|
||||||
|
[
|
||||||
|
innerJoin(
|
||||||
|
db.mediaItems,
|
||||||
|
db.mediaItems.id.equalsExp(db.objectMediaItems.mediaId),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
..where(
|
||||||
|
db.objectMediaItems.objectType.equals(ObjectType.activities.name))
|
||||||
|
..where(db.objectMediaItems.objectId.equals(activity.id));
|
||||||
|
|
||||||
|
final mediaItems = (await result.get())
|
||||||
|
.map((e) => e.readTable(db.mediaItems))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
return mediaItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<MediaItem>> fromSession(Session session) async {
|
||||||
|
final result = select(db.objectMediaItems).join(
|
||||||
|
[
|
||||||
|
innerJoin(
|
||||||
|
db.mediaItems,
|
||||||
|
db.mediaItems.id.equalsExp(db.objectMediaItems.mediaId),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
..where(
|
||||||
|
db.objectMediaItems.objectType.equals(ObjectType.sessions.name))
|
||||||
|
..where(db.objectMediaItems.objectId.equals(session.id));
|
||||||
|
|
||||||
|
final mediaItems = (await result.get())
|
||||||
|
.map((e) => e.readTable(db.mediaItems))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
return mediaItems;
|
||||||
|
}
|
||||||
|
}
|
8
lib/daos/media_items_dao.g.dart
Normal file
8
lib/daos/media_items_dao.g.dart
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'media_items_dao.dart';
|
||||||
|
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
mixin _$MediaItemsDaoMixin on DatabaseAccessor<AppDatabase> {
|
||||||
|
$MediaItemsTable get mediaItems => attachedDatabase.mediaItems;
|
||||||
|
}
|
24
lib/daos/session_activities_dao.dart
Normal file
24
lib/daos/session_activities_dao.dart
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:sendtrain/database/database.dart';
|
||||||
|
|
||||||
|
part 'session_activities_dao.g.dart';
|
||||||
|
|
||||||
|
@DriftAccessor(tables: [SessionActivities])
|
||||||
|
class SessionActivitiesDao extends DatabaseAccessor<AppDatabase> with _$SessionActivitiesDaoMixin {
|
||||||
|
SessionActivitiesDao(super.db);
|
||||||
|
|
||||||
|
Future<List<SessionActivity>> all() async {
|
||||||
|
return await select(sessionActivities).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<SessionActivity> find(int id) async {
|
||||||
|
return await (select(sessionActivities)..where((sessionActivity) => sessionActivity.id.equals(id) )).getSingle();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<SessionActivity>> fromSessionId(int id) async {
|
||||||
|
final result = db.managers.sessionActivities
|
||||||
|
.filter((sessionActivity) => sessionActivity.sessionId.id(id));
|
||||||
|
|
||||||
|
return result.get();
|
||||||
|
}
|
||||||
|
}
|
11
lib/daos/session_activities_dao.g.dart
Normal file
11
lib/daos/session_activities_dao.g.dart
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'session_activities_dao.dart';
|
||||||
|
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
mixin _$SessionActivitiesDaoMixin on DatabaseAccessor<AppDatabase> {
|
||||||
|
$SessionsTable get sessions => attachedDatabase.sessions;
|
||||||
|
$ActivitiesTable get activities => attachedDatabase.activities;
|
||||||
|
$SessionActivitiesTable get sessionActivities =>
|
||||||
|
attachedDatabase.sessionActivities;
|
||||||
|
}
|
17
lib/daos/sessions_dao.dart
Normal file
17
lib/daos/sessions_dao.dart
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:sendtrain/database/database.dart';
|
||||||
|
|
||||||
|
part 'sessions_dao.g.dart';
|
||||||
|
|
||||||
|
@DriftAccessor(tables: [Sessions])
|
||||||
|
class SessionsDao extends DatabaseAccessor<AppDatabase> with _$SessionsDaoMixin {
|
||||||
|
SessionsDao(super.db);
|
||||||
|
|
||||||
|
Future<List<Session>> all() async {
|
||||||
|
return await select(sessions).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Session> find(int id) async {
|
||||||
|
return await (select(sessions)..where((session) => session.id.equals(id) )).getSingle();
|
||||||
|
}
|
||||||
|
}
|
8
lib/daos/sessions_dao.g.dart
Normal file
8
lib/daos/sessions_dao.g.dart
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'sessions_dao.dart';
|
||||||
|
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
mixin _$SessionsDaoMixin on DatabaseAccessor<AppDatabase> {
|
||||||
|
$SessionsTable get sessions => attachedDatabase.sessions;
|
||||||
|
}
|
151
lib/database/database.dart
Normal file
151
lib/database/database.dart
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:drift_flutter/drift_flutter.dart';
|
||||||
|
import 'package:sendtrain/daos/actions_dao.dart';
|
||||||
|
import 'package:sendtrain/daos/activities_dao.dart';
|
||||||
|
import 'package:sendtrain/daos/activity_actions_dao.dart';
|
||||||
|
import 'package:sendtrain/daos/media_items_dao.dart';
|
||||||
|
import 'package:sendtrain/daos/session_activities_dao.dart';
|
||||||
|
import 'package:sendtrain/daos/sessions_dao.dart';
|
||||||
|
import 'package:sendtrain/database/seed.dart';
|
||||||
|
|
||||||
|
part 'database.g.dart';
|
||||||
|
|
||||||
|
@DriftDatabase(tables: [
|
||||||
|
Sessions,
|
||||||
|
SessionActivities,
|
||||||
|
Activities,
|
||||||
|
ActivityActions,
|
||||||
|
Actions,
|
||||||
|
ObjectMediaItems,
|
||||||
|
MediaItems
|
||||||
|
], daos: [
|
||||||
|
SessionsDao,
|
||||||
|
ActivitiesDao,
|
||||||
|
MediaItemsDao,
|
||||||
|
SessionActivitiesDao,
|
||||||
|
ActivityActionsDao,
|
||||||
|
ActionsDao
|
||||||
|
])
|
||||||
|
class AppDatabase extends _$AppDatabase {
|
||||||
|
// After generating code, this class needs to define a `schemaVersion` getter
|
||||||
|
// and a constructor telling drift where the database should be stored.
|
||||||
|
// These are described in the getting started guide: https://drift.simonbinder.eu/setup/
|
||||||
|
AppDatabase() : super(_openConnection());
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get schemaVersion => 4;
|
||||||
|
|
||||||
|
@override
|
||||||
|
MigrationStrategy get migration {
|
||||||
|
return MigrationStrategy(
|
||||||
|
onCreate: (m) async {
|
||||||
|
await m.createAll().then((r) async {
|
||||||
|
await seedDb(this);
|
||||||
|
}); // create all tables
|
||||||
|
},
|
||||||
|
beforeOpen: (details) async {
|
||||||
|
/// Enable foreign_keys
|
||||||
|
await customStatement('PRAGMA foreign_keys = ON');
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static QueryExecutor _openConnection() {
|
||||||
|
// `driftDatabase` from `package:drift_flutter` stores the database in
|
||||||
|
// `getApplicationDocumentsDirectory()`.
|
||||||
|
return driftDatabase(name: 'sendtrain');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum SessionStatus { pending, started, completed, missed }
|
||||||
|
|
||||||
|
class Sessions extends Table {
|
||||||
|
IntColumn get id => integer().autoIncrement()();
|
||||||
|
TextColumn get title => text().withLength(min: 3, max: 32)();
|
||||||
|
TextColumn get content => text().named('body')();
|
||||||
|
TextColumn get status => textEnum<SessionStatus>()();
|
||||||
|
DateTimeColumn get date => dateTime().nullable()();
|
||||||
|
DateTimeColumn get createdAt =>
|
||||||
|
dateTime().withDefault(Variable(DateTime.now()))();
|
||||||
|
}
|
||||||
|
|
||||||
|
class SessionActivities extends Table {
|
||||||
|
IntColumn get id => integer().autoIncrement()();
|
||||||
|
IntColumn get sessionId => integer().references(Sessions, #id)();
|
||||||
|
IntColumn get activityId => integer().references(Activities, #id)();
|
||||||
|
IntColumn get position => integer()();
|
||||||
|
TextColumn get results => text().nullable()();
|
||||||
|
TextColumn get achievements => text().nullable()();
|
||||||
|
DateTimeColumn get createdAt =>
|
||||||
|
dateTime().withDefault(Variable(DateTime.now()))();
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ActivityCategories { fundamentals, conditioning, advanced, custom, pro }
|
||||||
|
|
||||||
|
enum ActivityType {
|
||||||
|
strength,
|
||||||
|
power,
|
||||||
|
conditioning,
|
||||||
|
hypertrophy,
|
||||||
|
endurance,
|
||||||
|
stability,
|
||||||
|
mobility,
|
||||||
|
flexibility,
|
||||||
|
rehabilitation,
|
||||||
|
technical
|
||||||
|
}
|
||||||
|
|
||||||
|
class Activities extends Table {
|
||||||
|
IntColumn get id => integer().autoIncrement()();
|
||||||
|
TextColumn get title => text().withLength(min: 3, max: 32)();
|
||||||
|
TextColumn get type => textEnum<ActivityType>()();
|
||||||
|
TextColumn get description => text().named('body')();
|
||||||
|
TextColumn get category => textEnum<ActivityCategories>()();
|
||||||
|
DateTimeColumn get createdAt =>
|
||||||
|
dateTime().withDefault(Variable(DateTime.now()))();
|
||||||
|
}
|
||||||
|
|
||||||
|
class ActivityActions extends Table {
|
||||||
|
IntColumn get id => integer().autoIncrement()();
|
||||||
|
IntColumn get activityId => integer().references(Activities, #id)();
|
||||||
|
IntColumn get actionId => integer().references(Actions, #id)();
|
||||||
|
IntColumn get position => integer()();
|
||||||
|
DateTimeColumn get createdAt =>
|
||||||
|
dateTime().withDefault(Variable(DateTime.now()))();
|
||||||
|
}
|
||||||
|
|
||||||
|
class Actions extends Table {
|
||||||
|
IntColumn get id => integer().autoIncrement()();
|
||||||
|
TextColumn get title => text().withLength(min: 3, max: 32)();
|
||||||
|
TextColumn get description => text().named('body')();
|
||||||
|
TextColumn get set => text()();
|
||||||
|
DateTimeColumn get createdAt =>
|
||||||
|
dateTime().withDefault(Variable(DateTime.now()))();
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ObjectType {
|
||||||
|
actions,
|
||||||
|
activities,
|
||||||
|
sessions,
|
||||||
|
}
|
||||||
|
|
||||||
|
class ObjectMediaItems extends Table {
|
||||||
|
IntColumn get id => integer().autoIncrement()();
|
||||||
|
IntColumn get objectId => integer()();
|
||||||
|
TextColumn get objectType => textEnum<ObjectType>()();
|
||||||
|
IntColumn get mediaId => integer().references(MediaItems, #id)();
|
||||||
|
DateTimeColumn get createdAt =>
|
||||||
|
dateTime().withDefault(Variable(DateTime.now()))();
|
||||||
|
}
|
||||||
|
|
||||||
|
enum MediaType { youtube, image }
|
||||||
|
|
||||||
|
class MediaItems extends Table {
|
||||||
|
IntColumn get id => integer().autoIncrement()();
|
||||||
|
TextColumn get title => text().withLength(min: 3, max: 32)();
|
||||||
|
TextColumn get description => text().named('body')();
|
||||||
|
TextColumn get reference => text().withLength(min: 3, max: 256)();
|
||||||
|
TextColumn get type => textEnum<MediaType>()();
|
||||||
|
DateTimeColumn get createdAt =>
|
||||||
|
dateTime().withDefault(Variable(DateTime.now()))();
|
||||||
|
}
|
4519
lib/database/database.g.dart
Normal file
4519
lib/database/database.g.dart
Normal file
File diff suppressed because it is too large
Load Diff
688
lib/database/database.steps.dart
Normal file
688
lib/database/database.steps.dart
Normal file
@ -0,0 +1,688 @@
|
|||||||
|
// dart format width=80
|
||||||
|
import 'package:drift/internal/versioned_schema.dart' as i0;
|
||||||
|
import 'package:drift/drift.dart' as i1;
|
||||||
|
import 'package:drift/drift.dart'; // ignore_for_file: type=lint,unused_import
|
||||||
|
|
||||||
|
// GENERATED BY drift_dev, DO NOT MODIFY.
|
||||||
|
final class Schema2 extends i0.VersionedSchema {
|
||||||
|
Schema2({required super.database}) : super(version: 2);
|
||||||
|
@override
|
||||||
|
late final List<i1.DatabaseSchemaEntity> entities = [
|
||||||
|
sessions,
|
||||||
|
activities,
|
||||||
|
sessionActivities,
|
||||||
|
actions,
|
||||||
|
activityActions,
|
||||||
|
mediaItems,
|
||||||
|
objectMediaItems,
|
||||||
|
];
|
||||||
|
late final Shape0 sessions = Shape0(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'sessions',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_2,
|
||||||
|
_column_3,
|
||||||
|
_column_4,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape1 activities = Shape1(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'activities',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_6,
|
||||||
|
_column_2,
|
||||||
|
_column_7,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape2 sessionActivities = Shape2(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'session_activities',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_8,
|
||||||
|
_column_9,
|
||||||
|
_column_10,
|
||||||
|
_column_11,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape3 actions = Shape3(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'actions',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_2,
|
||||||
|
_column_12,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape4 activityActions = Shape4(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'activity_actions',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_9,
|
||||||
|
_column_13,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape5 mediaItems = Shape5(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'media_items',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_2,
|
||||||
|
_column_14,
|
||||||
|
_column_6,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape6 objectMediaItems = Shape6(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'object_media_items',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_15,
|
||||||
|
_column_16,
|
||||||
|
_column_17,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
class Shape0 extends i0.VersionedTable {
|
||||||
|
Shape0({required super.source, required super.alias}) : super.aliased();
|
||||||
|
i1.GeneratedColumn<int> get id =>
|
||||||
|
columnsByName['id']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<String> get title =>
|
||||||
|
columnsByName['title']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<String> get content =>
|
||||||
|
columnsByName['body']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<String> get status =>
|
||||||
|
columnsByName['status']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<DateTime> get date =>
|
||||||
|
columnsByName['date']! as i1.GeneratedColumn<DateTime>;
|
||||||
|
i1.GeneratedColumn<DateTime> get createdAt =>
|
||||||
|
columnsByName['created_at']! as i1.GeneratedColumn<DateTime>;
|
||||||
|
}
|
||||||
|
|
||||||
|
i1.GeneratedColumn<int> _column_0(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<int>('id', aliasedName, false,
|
||||||
|
hasAutoIncrement: true,
|
||||||
|
type: i1.DriftSqlType.int,
|
||||||
|
defaultConstraints:
|
||||||
|
i1.GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT'));
|
||||||
|
i1.GeneratedColumn<String> _column_1(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<String>('title', aliasedName, false,
|
||||||
|
additionalChecks: i1.GeneratedColumn.checkTextLength(
|
||||||
|
minTextLength: 3, maxTextLength: 32),
|
||||||
|
type: i1.DriftSqlType.string);
|
||||||
|
i1.GeneratedColumn<String> _column_2(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<String>('body', aliasedName, false,
|
||||||
|
type: i1.DriftSqlType.string);
|
||||||
|
i1.GeneratedColumn<String> _column_3(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<String>('status', aliasedName, false,
|
||||||
|
type: i1.DriftSqlType.string);
|
||||||
|
i1.GeneratedColumn<DateTime> _column_4(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<DateTime>('date', aliasedName, true,
|
||||||
|
type: i1.DriftSqlType.dateTime);
|
||||||
|
i1.GeneratedColumn<DateTime> _column_5(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<DateTime>('created_at', aliasedName, false,
|
||||||
|
type: i1.DriftSqlType.dateTime, defaultValue: Variable(DateTime.now()));
|
||||||
|
|
||||||
|
class Shape1 extends i0.VersionedTable {
|
||||||
|
Shape1({required super.source, required super.alias}) : super.aliased();
|
||||||
|
i1.GeneratedColumn<int> get id =>
|
||||||
|
columnsByName['id']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<String> get title =>
|
||||||
|
columnsByName['title']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<String> get type =>
|
||||||
|
columnsByName['type']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<String> get description =>
|
||||||
|
columnsByName['body']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<String> get category =>
|
||||||
|
columnsByName['category']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<DateTime> get createdAt =>
|
||||||
|
columnsByName['created_at']! as i1.GeneratedColumn<DateTime>;
|
||||||
|
}
|
||||||
|
|
||||||
|
i1.GeneratedColumn<String> _column_6(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<String>('type', aliasedName, false,
|
||||||
|
type: i1.DriftSqlType.string);
|
||||||
|
i1.GeneratedColumn<String> _column_7(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<String>('category', aliasedName, false,
|
||||||
|
type: i1.DriftSqlType.string);
|
||||||
|
|
||||||
|
class Shape2 extends i0.VersionedTable {
|
||||||
|
Shape2({required super.source, required super.alias}) : super.aliased();
|
||||||
|
i1.GeneratedColumn<int> get id =>
|
||||||
|
columnsByName['id']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<int> get sessionId =>
|
||||||
|
columnsByName['session_id']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<int> get activityId =>
|
||||||
|
columnsByName['activity_id']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<String> get results =>
|
||||||
|
columnsByName['results']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<String> get achievements =>
|
||||||
|
columnsByName['achievements']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<DateTime> get createdAt =>
|
||||||
|
columnsByName['created_at']! as i1.GeneratedColumn<DateTime>;
|
||||||
|
}
|
||||||
|
|
||||||
|
i1.GeneratedColumn<int> _column_8(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<int>('session_id', aliasedName, false,
|
||||||
|
type: i1.DriftSqlType.int,
|
||||||
|
defaultConstraints:
|
||||||
|
i1.GeneratedColumn.constraintIsAlways('REFERENCES sessions (id)'));
|
||||||
|
i1.GeneratedColumn<int> _column_9(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<int>('activity_id', aliasedName, false,
|
||||||
|
type: i1.DriftSqlType.int,
|
||||||
|
defaultConstraints: i1.GeneratedColumn.constraintIsAlways(
|
||||||
|
'REFERENCES activities (id)'));
|
||||||
|
i1.GeneratedColumn<String> _column_10(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<String>('results', aliasedName, true,
|
||||||
|
type: i1.DriftSqlType.string);
|
||||||
|
i1.GeneratedColumn<String> _column_11(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<String>('achievements', aliasedName, true,
|
||||||
|
type: i1.DriftSqlType.string);
|
||||||
|
|
||||||
|
class Shape3 extends i0.VersionedTable {
|
||||||
|
Shape3({required super.source, required super.alias}) : super.aliased();
|
||||||
|
i1.GeneratedColumn<int> get id =>
|
||||||
|
columnsByName['id']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<String> get title =>
|
||||||
|
columnsByName['title']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<String> get description =>
|
||||||
|
columnsByName['body']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<String> get set =>
|
||||||
|
columnsByName['set']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<DateTime> get createdAt =>
|
||||||
|
columnsByName['created_at']! as i1.GeneratedColumn<DateTime>;
|
||||||
|
}
|
||||||
|
|
||||||
|
i1.GeneratedColumn<String> _column_12(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<String>('set', aliasedName, false,
|
||||||
|
type: i1.DriftSqlType.string);
|
||||||
|
|
||||||
|
class Shape4 extends i0.VersionedTable {
|
||||||
|
Shape4({required super.source, required super.alias}) : super.aliased();
|
||||||
|
i1.GeneratedColumn<int> get id =>
|
||||||
|
columnsByName['id']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<int> get activityId =>
|
||||||
|
columnsByName['activity_id']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<int> get actionId =>
|
||||||
|
columnsByName['action_id']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<DateTime> get createdAt =>
|
||||||
|
columnsByName['created_at']! as i1.GeneratedColumn<DateTime>;
|
||||||
|
}
|
||||||
|
|
||||||
|
i1.GeneratedColumn<int> _column_13(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<int>('action_id', aliasedName, false,
|
||||||
|
type: i1.DriftSqlType.int,
|
||||||
|
defaultConstraints:
|
||||||
|
i1.GeneratedColumn.constraintIsAlways('REFERENCES actions (id)'));
|
||||||
|
|
||||||
|
class Shape5 extends i0.VersionedTable {
|
||||||
|
Shape5({required super.source, required super.alias}) : super.aliased();
|
||||||
|
i1.GeneratedColumn<int> get id =>
|
||||||
|
columnsByName['id']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<String> get title =>
|
||||||
|
columnsByName['title']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<String> get description =>
|
||||||
|
columnsByName['body']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<String> get reference =>
|
||||||
|
columnsByName['reference']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<String> get type =>
|
||||||
|
columnsByName['type']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<DateTime> get createdAt =>
|
||||||
|
columnsByName['created_at']! as i1.GeneratedColumn<DateTime>;
|
||||||
|
}
|
||||||
|
|
||||||
|
i1.GeneratedColumn<String> _column_14(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<String>('reference', aliasedName, false,
|
||||||
|
additionalChecks: i1.GeneratedColumn.checkTextLength(
|
||||||
|
minTextLength: 3, maxTextLength: 256),
|
||||||
|
type: i1.DriftSqlType.string);
|
||||||
|
|
||||||
|
class Shape6 extends i0.VersionedTable {
|
||||||
|
Shape6({required super.source, required super.alias}) : super.aliased();
|
||||||
|
i1.GeneratedColumn<int> get id =>
|
||||||
|
columnsByName['id']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<int> get objectId =>
|
||||||
|
columnsByName['object_id']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<String> get objectType =>
|
||||||
|
columnsByName['object_type']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<int> get mediaId =>
|
||||||
|
columnsByName['media_id']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<DateTime> get createdAt =>
|
||||||
|
columnsByName['created_at']! as i1.GeneratedColumn<DateTime>;
|
||||||
|
}
|
||||||
|
|
||||||
|
i1.GeneratedColumn<int> _column_15(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<int>('object_id', aliasedName, false,
|
||||||
|
type: i1.DriftSqlType.int);
|
||||||
|
i1.GeneratedColumn<String> _column_16(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<String>('object_type', aliasedName, false,
|
||||||
|
type: i1.DriftSqlType.string);
|
||||||
|
i1.GeneratedColumn<int> _column_17(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<int>('media_id', aliasedName, false,
|
||||||
|
type: i1.DriftSqlType.int,
|
||||||
|
defaultConstraints: i1.GeneratedColumn.constraintIsAlways(
|
||||||
|
'REFERENCES media_items (id)'));
|
||||||
|
|
||||||
|
final class Schema3 extends i0.VersionedSchema {
|
||||||
|
Schema3({required super.database}) : super(version: 3);
|
||||||
|
@override
|
||||||
|
late final List<i1.DatabaseSchemaEntity> entities = [
|
||||||
|
sessions,
|
||||||
|
activities,
|
||||||
|
sessionActivities,
|
||||||
|
actions,
|
||||||
|
activityActions,
|
||||||
|
mediaItems,
|
||||||
|
objectMediaItems,
|
||||||
|
];
|
||||||
|
late final Shape0 sessions = Shape0(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'sessions',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_2,
|
||||||
|
_column_3,
|
||||||
|
_column_4,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape1 activities = Shape1(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'activities',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_6,
|
||||||
|
_column_2,
|
||||||
|
_column_7,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape7 sessionActivities = Shape7(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'session_activities',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_8,
|
||||||
|
_column_9,
|
||||||
|
_column_18,
|
||||||
|
_column_10,
|
||||||
|
_column_11,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape3 actions = Shape3(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'actions',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_2,
|
||||||
|
_column_12,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape8 activityActions = Shape8(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'activity_actions',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_9,
|
||||||
|
_column_13,
|
||||||
|
_column_18,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape5 mediaItems = Shape5(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'media_items',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_2,
|
||||||
|
_column_14,
|
||||||
|
_column_6,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape6 objectMediaItems = Shape6(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'object_media_items',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_15,
|
||||||
|
_column_16,
|
||||||
|
_column_17,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
class Shape7 extends i0.VersionedTable {
|
||||||
|
Shape7({required super.source, required super.alias}) : super.aliased();
|
||||||
|
i1.GeneratedColumn<int> get id =>
|
||||||
|
columnsByName['id']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<int> get sessionId =>
|
||||||
|
columnsByName['session_id']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<int> get activityId =>
|
||||||
|
columnsByName['activity_id']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<int> get postition =>
|
||||||
|
columnsByName['postition']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<String> get results =>
|
||||||
|
columnsByName['results']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<String> get achievements =>
|
||||||
|
columnsByName['achievements']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<DateTime> get createdAt =>
|
||||||
|
columnsByName['created_at']! as i1.GeneratedColumn<DateTime>;
|
||||||
|
}
|
||||||
|
|
||||||
|
i1.GeneratedColumn<int> _column_18(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<int>('postition', aliasedName, false,
|
||||||
|
type: i1.DriftSqlType.int);
|
||||||
|
|
||||||
|
class Shape8 extends i0.VersionedTable {
|
||||||
|
Shape8({required super.source, required super.alias}) : super.aliased();
|
||||||
|
i1.GeneratedColumn<int> get id =>
|
||||||
|
columnsByName['id']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<int> get activityId =>
|
||||||
|
columnsByName['activity_id']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<int> get actionId =>
|
||||||
|
columnsByName['action_id']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<int> get postition =>
|
||||||
|
columnsByName['postition']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<DateTime> get createdAt =>
|
||||||
|
columnsByName['created_at']! as i1.GeneratedColumn<DateTime>;
|
||||||
|
}
|
||||||
|
|
||||||
|
final class Schema4 extends i0.VersionedSchema {
|
||||||
|
Schema4({required super.database}) : super(version: 4);
|
||||||
|
@override
|
||||||
|
late final List<i1.DatabaseSchemaEntity> entities = [
|
||||||
|
sessions,
|
||||||
|
activities,
|
||||||
|
sessionActivities,
|
||||||
|
actions,
|
||||||
|
activityActions,
|
||||||
|
mediaItems,
|
||||||
|
objectMediaItems,
|
||||||
|
];
|
||||||
|
late final Shape0 sessions = Shape0(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'sessions',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_2,
|
||||||
|
_column_3,
|
||||||
|
_column_4,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape1 activities = Shape1(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'activities',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_6,
|
||||||
|
_column_2,
|
||||||
|
_column_7,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape9 sessionActivities = Shape9(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'session_activities',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_8,
|
||||||
|
_column_9,
|
||||||
|
_column_19,
|
||||||
|
_column_10,
|
||||||
|
_column_11,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape3 actions = Shape3(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'actions',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_2,
|
||||||
|
_column_12,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape10 activityActions = Shape10(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'activity_actions',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_9,
|
||||||
|
_column_13,
|
||||||
|
_column_19,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape5 mediaItems = Shape5(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'media_items',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_2,
|
||||||
|
_column_14,
|
||||||
|
_column_6,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape6 objectMediaItems = Shape6(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'object_media_items',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_15,
|
||||||
|
_column_16,
|
||||||
|
_column_17,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
class Shape9 extends i0.VersionedTable {
|
||||||
|
Shape9({required super.source, required super.alias}) : super.aliased();
|
||||||
|
i1.GeneratedColumn<int> get id =>
|
||||||
|
columnsByName['id']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<int> get sessionId =>
|
||||||
|
columnsByName['session_id']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<int> get activityId =>
|
||||||
|
columnsByName['activity_id']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<int> get position =>
|
||||||
|
columnsByName['position']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<String> get results =>
|
||||||
|
columnsByName['results']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<String> get achievements =>
|
||||||
|
columnsByName['achievements']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<DateTime> get createdAt =>
|
||||||
|
columnsByName['created_at']! as i1.GeneratedColumn<DateTime>;
|
||||||
|
}
|
||||||
|
|
||||||
|
i1.GeneratedColumn<int> _column_19(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<int>('position', aliasedName, false,
|
||||||
|
type: i1.DriftSqlType.int);
|
||||||
|
|
||||||
|
class Shape10 extends i0.VersionedTable {
|
||||||
|
Shape10({required super.source, required super.alias}) : super.aliased();
|
||||||
|
i1.GeneratedColumn<int> get id =>
|
||||||
|
columnsByName['id']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<int> get activityId =>
|
||||||
|
columnsByName['activity_id']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<int> get actionId =>
|
||||||
|
columnsByName['action_id']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<int> get position =>
|
||||||
|
columnsByName['position']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<DateTime> get createdAt =>
|
||||||
|
columnsByName['created_at']! as i1.GeneratedColumn<DateTime>;
|
||||||
|
}
|
||||||
|
|
||||||
|
i0.MigrationStepWithVersion migrationSteps({
|
||||||
|
required Future<void> Function(i1.Migrator m, Schema2 schema) from1To2,
|
||||||
|
required Future<void> Function(i1.Migrator m, Schema3 schema) from2To3,
|
||||||
|
required Future<void> Function(i1.Migrator m, Schema4 schema) from3To4,
|
||||||
|
}) {
|
||||||
|
return (currentVersion, database) async {
|
||||||
|
switch (currentVersion) {
|
||||||
|
case 1:
|
||||||
|
final schema = Schema2(database: database);
|
||||||
|
final migrator = i1.Migrator(database, schema);
|
||||||
|
await from1To2(migrator, schema);
|
||||||
|
return 2;
|
||||||
|
case 2:
|
||||||
|
final schema = Schema3(database: database);
|
||||||
|
final migrator = i1.Migrator(database, schema);
|
||||||
|
await from2To3(migrator, schema);
|
||||||
|
return 3;
|
||||||
|
case 3:
|
||||||
|
final schema = Schema4(database: database);
|
||||||
|
final migrator = i1.Migrator(database, schema);
|
||||||
|
await from3To4(migrator, schema);
|
||||||
|
return 4;
|
||||||
|
default:
|
||||||
|
throw ArgumentError.value('Unknown migration from $currentVersion');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
i1.OnUpgrade stepByStep({
|
||||||
|
required Future<void> Function(i1.Migrator m, Schema2 schema) from1To2,
|
||||||
|
required Future<void> Function(i1.Migrator m, Schema3 schema) from2To3,
|
||||||
|
required Future<void> Function(i1.Migrator m, Schema4 schema) from3To4,
|
||||||
|
}) =>
|
||||||
|
i0.VersionedSchema.stepByStepHelper(
|
||||||
|
step: migrationSteps(
|
||||||
|
from1To2: from1To2,
|
||||||
|
from2To3: from2To3,
|
||||||
|
from3To4: from3To4,
|
||||||
|
));
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
167
lib/database/seed.dart
Normal file
167
lib/database/seed.dart
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:sendtrain/database/database.dart';
|
||||||
|
|
||||||
|
Future<void> seedDb(AppDatabase database) async {
|
||||||
|
// seed data setup
|
||||||
|
final List<List> sessionValues = [
|
||||||
|
[
|
||||||
|
'Projecting @ Climbers Rock',
|
||||||
|
'Beta pully beta beta pinch one arm crimpy. Futuristic pinch, dyno dynamic drop knee climb. Climbing ondra slopey onsight beta ondra power endurance.'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'Moonboard @ Boardroom',
|
||||||
|
'Beta pully beta beta pinch one arm crimpy. Futuristic pinch, dyno dynamic drop knee climb. Climbing ondra slopey onsight beta ondra power endurance.'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'Off-Wall Training',
|
||||||
|
'Beta pully beta beta pinch one arm crimpy. Futuristic pinch, dyno dynamic drop knee climb. Climbing ondra slopey onsight beta ondra power endurance.'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'Climbing Outdoors',
|
||||||
|
'Beta pully beta beta pinch one arm crimpy. Futuristic pinch, dyno dynamic drop knee climb. Climbing ondra slopey onsight beta ondra power endurance.'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'Volume Session @ Gravity',
|
||||||
|
'Beta pully beta beta pinch one arm crimpy. Futuristic pinch, dyno dynamic drop knee climb. Climbing ondra slopey onsight beta ondra power endurance.'
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
final List<List> mediaItems = [
|
||||||
|
[
|
||||||
|
'https://www.climbing.com/wp-content/uploads/2022/06/campus-board-e1655470701154.jpeg',
|
||||||
|
MediaType.image
|
||||||
|
],
|
||||||
|
['BgheYcxhrsw', MediaType.youtube]
|
||||||
|
];
|
||||||
|
|
||||||
|
final List<String> actionTypes = [
|
||||||
|
"[[{\"actionID\": 0, \"name\": \"1, 3, 5\", \"type\": \"repititions\", \"amount\": 1, \"weight\": 0}, {\"actionID\": 1, \"name\": \"Rest\", \"type\": \"seconds\", \"amount\": 300}], [{\"actionID\": 2, \"name\": \"1, 3, 5\", \"type\": \"repititions\", \"amount\": 1, \"weight\": 0}, {\"actionID\": 3, \"name\": \"Rest\", \"type\": \"seconds\", \"amount\": 300}], [{\"actionID\": 4, \"name\": \"1, 3, 5\", \"type\": \"repititions\", \"amount\": 1, \"weight\": 0}, {\"actionID\": 5, \"name\": \"Rest\", \"type\": \"seconds\", \"amount\": 300}]]",
|
||||||
|
"[[{\"actionID\": 0, \"name\": \"Long Pulls\", \"type\": \"seconds\", \"amount\": 5, \"weight\": 80}, {\"actionID\": 1, \"name\": \"Rest\", \"type\": \"seconds\", \"amount\": 5}, {\"actionID\": 2, \"name\": \"Long Pulls\", \"type\": \"seconds\", \"amount\": 5, \"weights\": 80}, {\"actionID\": 3, \"name\": \"Rest\", \"type\": \"seconds\", \"amount\": 300}], [{\"actionID\": 4, \"name\": \"Long Pulls\", \"type\": \"seconds\", \"amount\": 5, \"weight\": 80}, {\"actionID\": 5, \"name\": \"Rest\", \"type\": \"seconds\", \"amount\": 5}, {\"actionID\": 6, \"name\": \"Long Pulls\", \"type\": \"seconds\", \"amount\": 5, \"weights\": 80}, {\"actionID\": 7, \"name\": \"Rest\", \"type\": \"seconds\", \"amount\": 300}], [{\"actionID\": 8, \"name\": \"Long Pulls\", \"type\": \"seconds\", \"amount\": 5, \"weight\": 80}, {\"actionID\": 9, \"name\": \"Rest\", \"type\": \"seconds\", \"amount\": 5}, {\"actionID\": 10, \"name\": \"Long Pulls\", \"type\": \"seconds\", \"amount\": 5, \"weights\": 80}, {\"actionID\": 11, \"name\": \"Rest\", \"type\": \"seconds\", \"amount\": 300}], [{\"actionID\": 12, \"name\": \"Long Pulls\", \"type\": \"seconds\", \"amount\": 5, \"weight\": 80}, {\"actionID\": 13, \"name\": \"Rest\", \"type\": \"seconds\", \"amount\": 5}, {\"actionID\": 14, \"name\": \"Long Pulls\", \"type\": \"seconds\", \"amount\": 5, \"weights\": 80}, {\"actionID\": 15, \"name\": \"Rest\", \"type\": \"seconds\", \"amount\": 300}], [{\"actionID\": 16, \"name\": \"Long Pulls\", \"type\": \"seconds\", \"amount\": 5, \"weight\": 80}, {\"actionID\": 17, \"name\": \"Rest\", \"type\": \"seconds\", \"amount\": 5}, {\"actionID\": 18, \"name\": \"Long Pulls\", \"type\": \"seconds\", \"amount\": 5, \"weights\": 80}, {\"actionID\": 19, \"name\": \"Rest\", \"type\": \"seconds\", \"amount\": 300}]]"
|
||||||
|
];
|
||||||
|
|
||||||
|
final int totalSessions = 15;
|
||||||
|
final int totalActivities = 6;
|
||||||
|
final int totalActions = 5;
|
||||||
|
final int totalMedia = 5;
|
||||||
|
final random = Random();
|
||||||
|
|
||||||
|
// seed loop
|
||||||
|
for (int i = 0; i < totalSessions; i++) {
|
||||||
|
// session things
|
||||||
|
var status = SessionStatus.completed;
|
||||||
|
if (i == 0) status = SessionStatus.started;
|
||||||
|
if (i == 1) status = SessionStatus.pending;
|
||||||
|
|
||||||
|
final sessionValue = sessionValues[random.nextInt(sessionValues.length)];
|
||||||
|
await database
|
||||||
|
.into(database.sessions)
|
||||||
|
.insert(SessionsCompanion.insert(
|
||||||
|
title: sessionValue[0],
|
||||||
|
content: sessionValue[1],
|
||||||
|
status: status,
|
||||||
|
date: Value(DateTime.now())))
|
||||||
|
.then((sessionId) async {
|
||||||
|
// activities things
|
||||||
|
for (int j = 0; j <= random.nextInt(totalActivities); j++) {
|
||||||
|
await database
|
||||||
|
.into(database.activities)
|
||||||
|
.insert(ActivitiesCompanion.insert(
|
||||||
|
title: "Test activity $j",
|
||||||
|
type: ActivityType
|
||||||
|
.values[random.nextInt(ActivityType.values.length)],
|
||||||
|
description:
|
||||||
|
"$j Beta pully beta beta pinch one arm crimpy. Futuristic pinch, dyno dynamic drop knee climb. Climbing ondra slopey onsight beta ondra power endurance.",
|
||||||
|
category: ActivityCategories
|
||||||
|
.values[random.nextInt(ActivityCategories.values.length)]))
|
||||||
|
.then((activityId) async {
|
||||||
|
// session activity relationships
|
||||||
|
await database
|
||||||
|
.into(database.sessionActivities)
|
||||||
|
.insert(SessionActivitiesCompanion.insert(
|
||||||
|
sessionId: sessionId,
|
||||||
|
activityId: activityId,
|
||||||
|
position: j,
|
||||||
|
results: Value("results json, will need to test"),
|
||||||
|
achievements: Value("comma, seperated, items"),
|
||||||
|
));
|
||||||
|
|
||||||
|
// actions
|
||||||
|
for (int k = 0; k <= random.nextInt(totalActions); k++) {
|
||||||
|
await database
|
||||||
|
.into(database.actions)
|
||||||
|
.insert(ActionsCompanion.insert(
|
||||||
|
title: 'Test action $k',
|
||||||
|
description:
|
||||||
|
'$k Beta pully beta beta pinch one arm crimpy. Futuristic pinch, dyno dynamic drop knee climb. Climbing ondra slopey onsight beta ondra power endurance.',
|
||||||
|
set: actionTypes[random.nextInt(actionTypes.length)]))
|
||||||
|
.then((actionId) async {
|
||||||
|
// add activity action association
|
||||||
|
await database.into(database.activityActions).insert(
|
||||||
|
ActivityActionsCompanion.insert(
|
||||||
|
activityId: activityId, actionId: actionId, position: k));
|
||||||
|
|
||||||
|
for (int l = 0; l <= random.nextInt(totalMedia); l++) {
|
||||||
|
final mediaItem = mediaItems[random.nextInt(mediaItems.length)];
|
||||||
|
await database
|
||||||
|
.into(database.mediaItems)
|
||||||
|
.insert(MediaItemsCompanion.insert(
|
||||||
|
title: 'Media title $l',
|
||||||
|
description:
|
||||||
|
'Media description $l Beta pully beta beta pinch one arm crimpy. Futuristic pinch, dyno dynamic drop knee climb. Climbing ondra slopey onsight beta ondra power endurance.',
|
||||||
|
reference: mediaItem[0],
|
||||||
|
type: mediaItem[1]))
|
||||||
|
.then((mediaId) async {
|
||||||
|
await database.into(database.objectMediaItems).insert(
|
||||||
|
ObjectMediaItemsCompanion.insert(
|
||||||
|
objectId: actionId,
|
||||||
|
mediaId: mediaId,
|
||||||
|
objectType: ObjectType.actions));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int m = 0; m <= random.nextInt(totalMedia); m++) {
|
||||||
|
final mediaItem = mediaItems[random.nextInt(mediaItems.length)];
|
||||||
|
await database
|
||||||
|
.into(database.mediaItems)
|
||||||
|
.insert(MediaItemsCompanion.insert(
|
||||||
|
title: 'Media title $m',
|
||||||
|
description:
|
||||||
|
'Media description $m Beta pully beta beta pinch one arm crimpy. Futuristic pinch, dyno dynamic drop knee climb. Climbing ondra slopey onsight beta ondra power endurance.',
|
||||||
|
reference: mediaItem[0],
|
||||||
|
type: mediaItem[1]))
|
||||||
|
.then((mediaId) async {
|
||||||
|
await database.into(database.objectMediaItems).insert(
|
||||||
|
ObjectMediaItemsCompanion.insert(
|
||||||
|
objectId: activityId,
|
||||||
|
mediaId: mediaId,
|
||||||
|
objectType: ObjectType.activities));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int n = 0; n <= random.nextInt(totalMedia); n++) {
|
||||||
|
final mediaItem = mediaItems[random.nextInt(mediaItems.length)];
|
||||||
|
await database
|
||||||
|
.into(database.mediaItems)
|
||||||
|
.insert(MediaItemsCompanion.insert(
|
||||||
|
title: 'Media title $n',
|
||||||
|
description:
|
||||||
|
'Media description $n Beta pully beta beta pinch one arm crimpy. Futuristic pinch, dyno dynamic drop knee climb. Climbing ondra slopey onsight beta ondra power endurance.',
|
||||||
|
reference: mediaItem[0],
|
||||||
|
type: mediaItem[1]))
|
||||||
|
.then((mediaId) async {
|
||||||
|
await database.into(database.objectMediaItems).insert(
|
||||||
|
ObjectMediaItemsCompanion.insert(
|
||||||
|
objectId: sessionId,
|
||||||
|
mediaId: mediaId,
|
||||||
|
objectType: ObjectType.sessions));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
1
lib/database/sendtrain/drift_schema_v1.json
Normal file
1
lib/database/sendtrain/drift_schema_v1.json
Normal file
File diff suppressed because one or more lines are too long
84
lib/extensions/string_extensions.dart
Normal file
84
lib/extensions/string_extensions.dart
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
List<String> exceptions = [
|
||||||
|
'a',
|
||||||
|
'abaft',
|
||||||
|
'about',
|
||||||
|
'above',
|
||||||
|
'afore',
|
||||||
|
'after',
|
||||||
|
'along',
|
||||||
|
'amid',
|
||||||
|
'among',
|
||||||
|
'an',
|
||||||
|
'apud',
|
||||||
|
'as',
|
||||||
|
'aside',
|
||||||
|
'at',
|
||||||
|
'atop',
|
||||||
|
'below',
|
||||||
|
'but',
|
||||||
|
'by',
|
||||||
|
'circa',
|
||||||
|
'down',
|
||||||
|
'for',
|
||||||
|
'from',
|
||||||
|
'given',
|
||||||
|
'in',
|
||||||
|
'into',
|
||||||
|
'lest',
|
||||||
|
'like',
|
||||||
|
'mid',
|
||||||
|
'midst',
|
||||||
|
'minus',
|
||||||
|
'near',
|
||||||
|
'next',
|
||||||
|
'of',
|
||||||
|
'off',
|
||||||
|
'on',
|
||||||
|
'onto',
|
||||||
|
'out',
|
||||||
|
'over',
|
||||||
|
'pace',
|
||||||
|
'past',
|
||||||
|
'per',
|
||||||
|
'plus',
|
||||||
|
'pro',
|
||||||
|
'qua',
|
||||||
|
'round',
|
||||||
|
'sans',
|
||||||
|
'save',
|
||||||
|
'since',
|
||||||
|
'than',
|
||||||
|
'thru',
|
||||||
|
'till',
|
||||||
|
'times',
|
||||||
|
'to',
|
||||||
|
'under',
|
||||||
|
'until',
|
||||||
|
'unto',
|
||||||
|
'up',
|
||||||
|
'upon',
|
||||||
|
'via',
|
||||||
|
'vice',
|
||||||
|
'with',
|
||||||
|
'worth',
|
||||||
|
'the","and',
|
||||||
|
'nor',
|
||||||
|
'or',
|
||||||
|
'yet',
|
||||||
|
'so'
|
||||||
|
];
|
||||||
|
|
||||||
|
extension TitleCase on String {
|
||||||
|
String toTitleCase() {
|
||||||
|
return toLowerCase().replaceAllMapped(
|
||||||
|
RegExp(
|
||||||
|
r'[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+'),
|
||||||
|
(Match match) {
|
||||||
|
|
||||||
|
// if (exceptions.contains(match[0])) {
|
||||||
|
// return match[0]!;
|
||||||
|
// }
|
||||||
|
return "${match[0]![0].toUpperCase()}${match[0]!.substring(1).toLowerCase()}";
|
||||||
|
}).replaceAll(RegExp(r'(_|-)+'), ' ');
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,11 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:sendtrain/database/database.dart';
|
||||||
import 'package:sendtrain/models/activity_timer_model.dart';
|
import 'package:sendtrain/models/activity_timer_model.dart';
|
||||||
import 'package:sendtrain/screens/activities_screen.dart';
|
import 'package:sendtrain/screens/activities_screen.dart';
|
||||||
import 'package:sendtrain/screens/sessions_screen.dart';
|
import 'package:sendtrain/screens/sessions_screen.dart';
|
||||||
|
// ignore: unused_import
|
||||||
|
import 'package:sendtrain/database/seed.dart';
|
||||||
|
|
||||||
class SendTrain extends StatelessWidget {
|
class SendTrain extends StatelessWidget {
|
||||||
const SendTrain({super.key});
|
const SendTrain({super.key});
|
||||||
@ -44,7 +47,7 @@ class _AppState extends State<App> {
|
|||||||
body: Padding(
|
body: Padding(
|
||||||
padding: const EdgeInsets.fromLTRB(0, 50, 0, 0),
|
padding: const EdgeInsets.fromLTRB(0, 50, 0, 0),
|
||||||
child: <Widget>[
|
child: <Widget>[
|
||||||
const SessionsScreen(),
|
SessionsScreen(),
|
||||||
const ActivitiesScreen(),
|
const ActivitiesScreen(),
|
||||||
Container(
|
Container(
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
@ -90,10 +93,13 @@ class _AppState extends State<App> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
runApp(
|
runApp(MultiProvider(
|
||||||
ChangeNotifierProvider(
|
providers: [
|
||||||
create: (context) => ActivityTimerModel(),
|
ChangeNotifierProvider(create: (context) => ActivityTimerModel()),
|
||||||
|
Provider<AppDatabase>(
|
||||||
|
create: (context) => AppDatabase(),
|
||||||
|
dispose: (context, db) => db.close()),
|
||||||
|
],
|
||||||
child: const SendTrain(),
|
child: const SendTrain(),
|
||||||
),
|
));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
@ -1,45 +1,66 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
|
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
|
||||||
import 'package:sendtrain/models/activity_model.dart';
|
import 'package:sendtrain/database/database.dart';
|
||||||
|
|
||||||
class ActivityTimerModel with ChangeNotifier {
|
class ActivityTimerModel with ChangeNotifier {
|
||||||
int _actionCounter = 0;
|
int _actionCounter = 0;
|
||||||
ActivityModel? _activity;
|
Activity? _activity;
|
||||||
List _sets = [];
|
List _sets = [];
|
||||||
|
List _actions = [];
|
||||||
int _currentActionNum = 0;
|
int _currentActionNum = 0;
|
||||||
int _currentSetNum = 0;
|
int _currentSetNum = 0;
|
||||||
Timer? _periodicTimer;
|
Timer? _periodicTimer;
|
||||||
double _progress = 0;
|
double _progress = 0;
|
||||||
ItemScrollController? _isc;
|
ItemScrollController? _isc;
|
||||||
|
int _totalTime = 0;
|
||||||
|
|
||||||
int get actionCount => _actionCounter;
|
int get actionCount => _actionCounter;
|
||||||
int get currentActionNum => _currentActionNum;
|
int get currentActionNum => _currentActionNum;
|
||||||
dynamic get currentAction => currentSet[_currentActionNum];
|
dynamic get currentAction => currentSet[_currentActionNum];
|
||||||
int get currentSetNum => _currentSetNum;
|
int get currentSetNum => _currentSetNum;
|
||||||
dynamic get currentSet => _sets[_currentSetNum];
|
dynamic get currentSet => _sets[_currentSetNum];
|
||||||
ActivityModel? get activity => _activity;
|
Activity? get activity => _activity;
|
||||||
List get sets => _sets;
|
List get sets => _sets;
|
||||||
Timer? get periodicTimer => _periodicTimer;
|
Timer? get periodicTimer => _periodicTimer;
|
||||||
bool get isActive => _isActive();
|
bool get isActive => _isActive();
|
||||||
double get progress => _progress;
|
double get progress => _progress;
|
||||||
|
int get totalTime => _totalTime;
|
||||||
|
|
||||||
void setup(ActivityModel activity) {
|
void setup(Activity activity, List actions) {
|
||||||
if (_activity == null || activity.id != _activity?.id) {
|
if (_activity == null || activity.id != _activity?.id) {
|
||||||
_periodicTimer?.cancel();
|
_periodicTimer?.cancel();
|
||||||
_progress = 0;
|
_progress = 0;
|
||||||
_isc = null;
|
_isc = null;
|
||||||
_activity = activity;
|
_activity = activity;
|
||||||
_sets = activity.actions[0].items();
|
// only one action for now
|
||||||
|
_sets = json.decode(actions[0].set);
|
||||||
|
_actions = actions;
|
||||||
_currentActionNum = 0;
|
_currentActionNum = 0;
|
||||||
_currentSetNum = 0;
|
_currentSetNum = 0;
|
||||||
setActionCount();
|
setActionCount();
|
||||||
|
getTotalTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
moveToIndex(_currentSetNum);
|
moveToIndex(_currentSetNum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void getTotalTime() {
|
||||||
|
int time = 0;
|
||||||
|
for(int setIndex = 0; _sets.length > setIndex; setIndex++) {
|
||||||
|
for (int actionIndex = 0; _sets[setIndex].length > actionIndex; actionIndex++) {
|
||||||
|
var action = _sets[setIndex][actionIndex];
|
||||||
|
if (action['type'] == 'seconds') {
|
||||||
|
time = time + action['amount'] as int;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_totalTime = time;
|
||||||
|
}
|
||||||
|
|
||||||
void reset() {
|
void reset() {
|
||||||
_progress = 0;
|
_progress = 0;
|
||||||
_currentActionNum = 0;
|
_currentActionNum = 0;
|
||||||
@ -89,6 +110,7 @@ class ActivityTimerModel with ChangeNotifier {
|
|||||||
case 'seconds':
|
case 'seconds':
|
||||||
if (_actionCounter > 0) {
|
if (_actionCounter > 0) {
|
||||||
_actionCounter--;
|
_actionCounter--;
|
||||||
|
_totalTime--;
|
||||||
} else {
|
} else {
|
||||||
nextAction(_currentActionNum + 1);
|
nextAction(_currentActionNum + 1);
|
||||||
setActionCount();
|
setActionCount();
|
||||||
@ -110,8 +132,8 @@ class ActivityTimerModel with ChangeNotifier {
|
|||||||
void setAction(int setNum, int actionNum, String type) {
|
void setAction(int setNum, int actionNum, String type) {
|
||||||
_currentActionNum = actionNum;
|
_currentActionNum = actionNum;
|
||||||
_currentSetNum = setNum;
|
_currentSetNum = setNum;
|
||||||
moveToIndex(_currentSetNum);
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
moveToIndex(_currentSetNum);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nextAction(int nextActionIndex) {
|
void nextAction(int nextActionIndex) {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:sendtrain/classes/activity_action.dart';
|
import 'package:sendtrain/classes/activity_action.dart';
|
||||||
|
import 'package:sendtrain/database/database.dart' hide ActivityAction;
|
||||||
import 'package:sendtrain/models/activity_model.dart';
|
import 'package:sendtrain/models/activity_model.dart';
|
||||||
|
|
||||||
import '../widgets/activities_header.dart';
|
import '../widgets/activities_header.dart';
|
||||||
@ -13,6 +14,7 @@ class ActivitiesScreen extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _ActivitiesScreenState extends State<ActivitiesScreen> {
|
class _ActivitiesScreenState extends State<ActivitiesScreen> {
|
||||||
|
final Activity? activity = null;
|
||||||
|
|
||||||
final data = ActivityModel(
|
final data = ActivityModel(
|
||||||
id: 1,
|
id: 1,
|
||||||
@ -40,23 +42,24 @@ class _ActivitiesScreenState extends State<ActivitiesScreen> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
List<Widget> activities = List.generate(10, (i) => ActivityCard(activity: data));
|
return Text("N/A");
|
||||||
|
// List<Widget> activities = List.generate(10, (i) => ActivityCard(activity: data, data: activity));
|
||||||
|
|
||||||
return Padding(
|
// return Padding(
|
||||||
padding: const EdgeInsets.fromLTRB(10, 15, 10, 0),
|
// padding: const EdgeInsets.fromLTRB(10, 15, 10, 0),
|
||||||
child: Column(
|
// child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: <Widget>[
|
// children: <Widget>[
|
||||||
const ActivitiesHeader(),
|
// const ActivitiesHeader(),
|
||||||
Expanded(
|
// Expanded(
|
||||||
child: GridView.count(
|
// child: GridView.count(
|
||||||
primary: false,
|
// primary: false,
|
||||||
padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
|
// padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
|
||||||
crossAxisSpacing: 10,
|
// crossAxisSpacing: 10,
|
||||||
mainAxisSpacing: 10,
|
// mainAxisSpacing: 10,
|
||||||
crossAxisCount: 2,
|
// crossAxisCount: 2,
|
||||||
children: activities,
|
// children: activities,
|
||||||
))
|
// ))
|
||||||
]));
|
// ]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:sendtrain/daos/sessions_dao.dart';
|
||||||
|
import 'package:sendtrain/database/database.dart';
|
||||||
import '../widgets/session_card.dart';
|
import '../widgets/session_card.dart';
|
||||||
|
|
||||||
class SessionsScreen extends StatelessWidget {
|
class SessionsScreen extends StatelessWidget {
|
||||||
@ -6,10 +9,23 @@ class SessionsScreen extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
List<Widget> previousSessions =
|
return FutureBuilder<List<Session>>(
|
||||||
List.generate(10, (i) => const SessionCard(state: 1, type: 1));
|
future: SessionsDao(Provider.of<AppDatabase>(context)).all(),
|
||||||
Widget upcomingSession = const SessionCard(state: 2);
|
builder: (context, snapshot) {
|
||||||
Widget currentSession = const SessionCard();
|
if (snapshot.hasData && snapshot.data!.isNotEmpty) {
|
||||||
|
final sessions = snapshot.data!;
|
||||||
|
final pending = sessions.where((session) =>
|
||||||
|
session.status == SessionStatus.completed ||
|
||||||
|
session.status == SessionStatus.missed);
|
||||||
|
final upcoming = sessions.firstWhere(
|
||||||
|
(session) => session.status == SessionStatus.pending);
|
||||||
|
final current = sessions.firstWhere(
|
||||||
|
(session) => session.status == SessionStatus.started);
|
||||||
|
|
||||||
|
List<Widget> previousSessions = List.generate(pending.length,
|
||||||
|
(i) => SessionCard(type: 1, session: pending.elementAt(i)));
|
||||||
|
Widget upcomingSession = SessionCard(session: upcoming);
|
||||||
|
Widget currentSession = SessionCard(session: current);
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
@ -17,19 +33,22 @@ class SessionsScreen extends StatelessWidget {
|
|||||||
const Padding(
|
const Padding(
|
||||||
padding: EdgeInsets.fromLTRB(15, 5, 0, 0),
|
padding: EdgeInsets.fromLTRB(15, 5, 0, 0),
|
||||||
child: Text(
|
child: Text(
|
||||||
style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
|
style: TextStyle(
|
||||||
|
fontSize: 25, fontWeight: FontWeight.bold),
|
||||||
'Current:')),
|
'Current:')),
|
||||||
currentSession,
|
currentSession,
|
||||||
const Padding(
|
const Padding(
|
||||||
padding: EdgeInsets.fromLTRB(15, 30, 0, 0),
|
padding: EdgeInsets.fromLTRB(15, 30, 0, 0),
|
||||||
child: Text(
|
child: Text(
|
||||||
style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
|
style: TextStyle(
|
||||||
|
fontSize: 25, fontWeight: FontWeight.bold),
|
||||||
'Upcoming:')),
|
'Upcoming:')),
|
||||||
upcomingSession,
|
upcomingSession,
|
||||||
const Padding(
|
const Padding(
|
||||||
padding: EdgeInsets.fromLTRB(15, 30, 0, 0),
|
padding: EdgeInsets.fromLTRB(15, 30, 0, 0),
|
||||||
child: Text(
|
child: Text(
|
||||||
style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
|
style: TextStyle(
|
||||||
|
fontSize: 25, fontWeight: FontWeight.bold),
|
||||||
'Previous:')),
|
'Previous:')),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
@ -41,12 +60,17 @@ class SessionsScreen extends StatelessWidget {
|
|||||||
mainAxisSpacing: 5,
|
mainAxisSpacing: 5,
|
||||||
crossAxisCount: 1,
|
crossAxisCount: 1,
|
||||||
children: previousSessions))
|
children: previousSessions))
|
||||||
// Flexible(
|
|
||||||
// child: ListView(
|
|
||||||
// scrollDirection: Axis.vertical,
|
|
||||||
// children: previousSessions,
|
|
||||||
// )),
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
return Container(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: SizedBox(
|
||||||
|
height: 50.0,
|
||||||
|
width: 50.0,
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
|
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
|
||||||
import 'package:sendtrain/classes/activity_action.dart';
|
import 'package:sendtrain/extensions/string_extensions.dart';
|
||||||
import 'package:sendtrain/models/activity_timer_model.dart';
|
import 'package:sendtrain/models/activity_timer_model.dart';
|
||||||
|
|
||||||
class ActivityActionView extends StatefulWidget {
|
class ActivityActionView extends StatefulWidget {
|
||||||
const ActivityActionView({super.key, required this.action});
|
const ActivityActionView({super.key, required this.actions});
|
||||||
final ActivityAction action;
|
final List actions;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<ActivityActionView> createState() => ActivityActionViewState();
|
State<ActivityActionView> createState() => ActivityActionViewState();
|
||||||
@ -25,7 +27,7 @@ class ActivityActionViewState extends State<ActivityActionView> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
ActivityTimerModel atm =
|
ActivityTimerModel atm =
|
||||||
Provider.of<ActivityTimerModel>(context, listen: true);
|
Provider.of<ActivityTimerModel>(context, listen: true);
|
||||||
List<List<Map<String, dynamic>>> sets = atm.activity!.actions[0].items();
|
List sets = json.decode(widget.actions[0].set);
|
||||||
|
|
||||||
// we need to set the scroll controller
|
// we need to set the scroll controller
|
||||||
// so we can update the selected item position
|
// so we can update the selected item position
|
||||||
@ -34,14 +36,14 @@ class ActivityActionViewState extends State<ActivityActionView> {
|
|||||||
return Expanded(
|
return Expanded(
|
||||||
child: ScrollablePositionedList.builder(
|
child: ScrollablePositionedList.builder(
|
||||||
padding: const EdgeInsets.fromLTRB(10, 0, 10, 20),
|
padding: const EdgeInsets.fromLTRB(10, 0, 10, 20),
|
||||||
itemCount: widget.action.activityActionSet.total,
|
itemCount: sets.length,
|
||||||
itemScrollController: itemScrollController,
|
itemScrollController: itemScrollController,
|
||||||
scrollOffsetController: scrollOffsetController,
|
scrollOffsetController: scrollOffsetController,
|
||||||
itemPositionsListener: itemPositionsListener,
|
itemPositionsListener: itemPositionsListener,
|
||||||
scrollOffsetListener: scrollOffsetListener,
|
scrollOffsetListener: scrollOffsetListener,
|
||||||
itemBuilder: (BuildContext context, int setNum) {
|
itemBuilder: (BuildContext context, int setNum) {
|
||||||
List<GestureDetector> content = [];
|
List<GestureDetector> content = [];
|
||||||
List<Map<String, dynamic>> set = sets[setNum];
|
List set = sets[setNum];
|
||||||
|
|
||||||
for (int actionNum = 0; actionNum < set.length; actionNum++) {
|
for (int actionNum = 0; actionNum < set.length; actionNum++) {
|
||||||
Map<String, dynamic> setItem = set[actionNum];
|
Map<String, dynamic> setItem = set[actionNum];
|
||||||
@ -74,7 +76,7 @@ class ActivityActionViewState extends State<ActivityActionView> {
|
|||||||
: Theme.of(context).colorScheme.surfaceContainerLow,
|
: Theme.of(context).colorScheme.surfaceContainerLow,
|
||||||
child: Text(
|
child: Text(
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
'${setItem['name']}: ${setItem['amount']} ${setItem['type']}')))
|
'${setItem['name']}: ${setItem['amount']} ${setItem['type']}'.toTitleCase())))
|
||||||
])));
|
])));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,20 +1,47 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:sendtrain/classes/media.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:sendtrain/models/activity_model.dart';
|
import 'package:sendtrain/daos/media_items_dao.dart';
|
||||||
|
import 'package:sendtrain/database/database.dart';
|
||||||
|
import 'package:sendtrain/extensions/string_extensions.dart';
|
||||||
|
import 'package:sendtrain/models/activity_timer_model.dart';
|
||||||
import 'package:sendtrain/widgets/activity_view.dart';
|
import 'package:sendtrain/widgets/activity_view.dart';
|
||||||
|
|
||||||
class ActivityCard extends StatelessWidget {
|
class ActivityCard extends StatefulWidget {
|
||||||
|
final Activity activity;
|
||||||
|
|
||||||
const ActivityCard({super.key, required this.activity});
|
const ActivityCard({super.key, required this.activity});
|
||||||
|
|
||||||
final ActivityModel activity;
|
@override
|
||||||
|
State<ActivityCard> createState() => ActivityCardState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class ActivityCardState extends State<ActivityCard> {
|
||||||
|
String formattedTime(int timeInSecond) {
|
||||||
|
int sec = timeInSecond % 60;
|
||||||
|
int min = (timeInSecond / 60).floor();
|
||||||
|
String minute = min.toString().length <= 1 ? "0$min" : "$min";
|
||||||
|
String second = sec.toString().length <= 1 ? "0$sec" : "$sec";
|
||||||
|
return "$minute:$second";
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final ActivityTimerModel atm =
|
||||||
|
Provider.of<ActivityTimerModel>(context, listen: false);
|
||||||
|
|
||||||
|
return FutureBuilder<List<MediaItem>>(
|
||||||
|
future: MediaItemsDao(Provider.of<AppDatabase>(context))
|
||||||
|
.fromActivity(widget.activity),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.hasData) {
|
||||||
|
List<MediaItem> mediaItems = snapshot.data!;
|
||||||
|
|
||||||
return Card(
|
return Card(
|
||||||
color: const Color(0xff3A5FB6),
|
color: atm.activity?.id == widget.activity.id
|
||||||
|
? Theme.of(context).colorScheme.primaryContainer
|
||||||
|
: Theme.of(context).colorScheme.surfaceContainerLow,
|
||||||
clipBehavior: Clip.hardEdge,
|
clipBehavior: Clip.hardEdge,
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
splashColor: Colors.deepPurple,
|
|
||||||
onTap: () => showGeneralDialog(
|
onTap: () => showGeneralDialog(
|
||||||
barrierColor: Colors.black.withOpacity(0.5),
|
barrierColor: Colors.black.withOpacity(0.5),
|
||||||
transitionDuration: const Duration(milliseconds: 220),
|
transitionDuration: const Duration(milliseconds: 220),
|
||||||
@ -29,7 +56,7 @@ class ActivityCard extends StatelessWidget {
|
|||||||
return SlideTransition(
|
return SlideTransition(
|
||||||
position: custom,
|
position: custom,
|
||||||
child: Dialog.fullscreen(
|
child: Dialog.fullscreen(
|
||||||
child: ActivityView(activity: activity)));
|
child: ActivityView(activity: widget.activity)));
|
||||||
},
|
},
|
||||||
barrierDismissible: true,
|
barrierDismissible: true,
|
||||||
barrierLabel: '',
|
barrierLabel: '',
|
||||||
@ -41,32 +68,79 @@ class ActivityCard extends StatelessWidget {
|
|||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
ListTile(
|
ListTile(
|
||||||
|
// visualDensity: VisualDensity(horizontal: VisualDensity.maximumDensity),
|
||||||
leading: Padding(
|
leading: Padding(
|
||||||
padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
|
padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
|
||||||
child: Container(
|
child: Container(
|
||||||
|
// padding: EdgeInsets.only(top: 5, bottom: 5),
|
||||||
width: 60,
|
width: 60,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
image: DecorationImage(
|
image: DecorationImage(
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.fill,
|
||||||
image: findMediaByType(
|
image:
|
||||||
activity.actions[0].media, 'image')),
|
findMediaByType(mediaItems, 'image')),
|
||||||
// color: Colors.blue,
|
// color: Colors.blue,
|
||||||
borderRadius:
|
borderRadius: const BorderRadius.all(
|
||||||
const BorderRadius.all(Radius.elliptical(10, 10)),
|
Radius.elliptical(8, 8)),
|
||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
title: Text(maxLines: 1, activity.title),
|
title: Consumer<ActivityTimerModel>(
|
||||||
subtitle: Text(maxLines: 2, activity.description),
|
builder: (context, atm, child) {
|
||||||
|
if (atm.activity?.id == widget.activity.id) {
|
||||||
|
return Text(
|
||||||
|
maxLines: 1,
|
||||||
|
"${widget.activity.title.toTitleCase()} (${formattedTime(atm.totalTime)})");
|
||||||
|
} else {
|
||||||
|
return Text(maxLines: 1, widget.activity.title.toTitleCase());
|
||||||
|
}
|
||||||
|
},
|
||||||
),
|
),
|
||||||
|
subtitle: Text(maxLines: 2, widget.activity.description),
|
||||||
|
trailing: IconButton(
|
||||||
|
visualDensity: VisualDensity.compact,
|
||||||
|
icon: Icon(Icons.close_rounded),
|
||||||
|
onPressed: () {
|
||||||
|
showAdaptiveDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) => AlertDialog(
|
||||||
|
title: const Text('Activity Removal'),
|
||||||
|
content: const Text(
|
||||||
|
'Would you like to permanently remove this activity from the current session?'),
|
||||||
|
actions: <Widget>[
|
||||||
|
TextButton(
|
||||||
|
onPressed: () =>
|
||||||
|
Navigator.pop(context, 'Cancel'),
|
||||||
|
child: const Text('Cancel'),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () =>
|
||||||
|
Navigator.pop(context, 'OK'),
|
||||||
|
child: const Text('OK'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)),
|
||||||
],
|
],
|
||||||
)),
|
)),
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
return Container(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: SizedBox(
|
||||||
|
height: 50.0,
|
||||||
|
width: 50.0,
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageProvider findMediaByType(List<Media>? media, String type) {
|
ImageProvider findMediaByType(List<MediaItem> media, String type) {
|
||||||
var found = media?.where((m) => m.type == 'image');
|
Iterable<MediaItem>? found = media.where((m) => m.type == MediaType.image);
|
||||||
|
|
||||||
if (found != null) {
|
if (found.isNotEmpty) {
|
||||||
return NetworkImage(found.first.reference);
|
return NetworkImage(found.first.reference);
|
||||||
} else {
|
} else {
|
||||||
// Element is not found
|
// Element is not found
|
||||||
|
@ -1,15 +1,19 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_expandable_fab/flutter_expandable_fab.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:sendtrain/classes/activity_action.dart';
|
import 'package:sendtrain/daos/actions_dao.dart';
|
||||||
import 'package:sendtrain/classes/media.dart';
|
import 'package:sendtrain/database/database.dart';
|
||||||
import 'package:sendtrain/models/activity_model.dart';
|
import 'package:sendtrain/extensions/string_extensions.dart';
|
||||||
import 'package:sendtrain/models/activity_timer_model.dart';
|
import 'package:sendtrain/models/activity_timer_model.dart';
|
||||||
import 'package:sendtrain/widgets/activity_action_view.dart';
|
import 'package:sendtrain/widgets/activity_action_view.dart';
|
||||||
import 'package:sendtrain/widgets/media_card.dart';
|
import 'package:sendtrain/widgets/activity_view_categories.dart';
|
||||||
|
import 'package:sendtrain/widgets/activity_view_media.dart';
|
||||||
|
import 'package:sendtrain/widgets/activity_view_types.dart';
|
||||||
|
|
||||||
class ActivityView extends StatefulWidget {
|
class ActivityView extends StatefulWidget {
|
||||||
const ActivityView({super.key, required this.activity});
|
const ActivityView(
|
||||||
final ActivityModel activity;
|
{super.key, required this.activity});
|
||||||
|
final Activity activity;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<ActivityView> createState() => _ActivityViewState();
|
State<ActivityView> createState() => _ActivityViewState();
|
||||||
@ -18,38 +22,88 @@ class ActivityView extends StatefulWidget {
|
|||||||
class _ActivityViewState extends State<ActivityView> {
|
class _ActivityViewState extends State<ActivityView> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
ActivityModel activity = widget.activity;
|
final Activity activity = widget.activity;
|
||||||
ActivityTimerModel atm =
|
ActivityTimerModel atm =
|
||||||
Provider.of<ActivityTimerModel>(context, listen: false);
|
Provider.of<ActivityTimerModel>(context, listen: false);
|
||||||
|
|
||||||
atm.setup(activity);
|
return FutureBuilder<List>(
|
||||||
|
future: ActionsDao(Provider.of<AppDatabase>(context))
|
||||||
|
.fromActivity(activity),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.hasData) {
|
||||||
|
List actions = snapshot.data!;
|
||||||
|
atm.setup(activity, actions);
|
||||||
|
|
||||||
return Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
return Scaffold(
|
||||||
|
floatingActionButtonLocation: ExpandableFab.location,
|
||||||
|
floatingActionButton: ExpandableFab(
|
||||||
|
distance: 70,
|
||||||
|
type: ExpandableFabType.up,
|
||||||
|
overlayStyle: ExpandableFabOverlayStyle(
|
||||||
|
color: Colors.black.withOpacity(0.5),
|
||||||
|
blur: 10,
|
||||||
|
),
|
||||||
|
children: [
|
||||||
|
FloatingActionButton.extended(
|
||||||
|
icon: const Icon(Icons.history_outlined),
|
||||||
|
label: Text('Restart'),
|
||||||
|
onPressed: () {},
|
||||||
|
),
|
||||||
|
FloatingActionButton.extended(
|
||||||
|
icon: const Icon(Icons.done_all_outlined),
|
||||||
|
label: Text('Done'),
|
||||||
|
onPressed: () {},
|
||||||
|
),
|
||||||
|
FloatingActionButton.extended(
|
||||||
|
icon: const Icon(Icons.edit_outlined),
|
||||||
|
label: Text('Edit'),
|
||||||
|
onPressed: () {},
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
body: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
AppBar(
|
AppBar(
|
||||||
|
titleSpacing: 0,
|
||||||
centerTitle: true,
|
centerTitle: true,
|
||||||
title: const Text('Activity', style: TextStyle(fontSize: 15)),
|
title: const Text('Activity',
|
||||||
|
style: TextStyle(fontSize: 15)),
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding:
|
padding: const EdgeInsets.only(
|
||||||
const EdgeInsets.only(left: 15, right: 20, top: 15, bottom: 10),
|
left: 15, right: 20, top: 15, bottom: 10),
|
||||||
child: Text(
|
child: Text(
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
style: const TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
|
style: const TextStyle(
|
||||||
activity.title)),
|
fontSize: 25, fontWeight: FontWeight.bold),
|
||||||
ActivityViewCategories(categories: activity.categories),
|
activity.title.toTitleCase())),
|
||||||
Padding(
|
Padding(
|
||||||
padding:
|
padding: const EdgeInsets.fromLTRB(10, 0, 0, 10),
|
||||||
const EdgeInsets.only(top: 0, bottom: 20, left: 15, right: 15),
|
child: Flex(direction: Axis.horizontal, children: [
|
||||||
|
ActivityViewCategories(
|
||||||
|
categories: [activity.category]),
|
||||||
|
ActivityViewTypes(types: [activity.type])
|
||||||
|
])),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
top: 0, bottom: 10, left: 15, right: 15),
|
||||||
child: Text(
|
child: Text(
|
||||||
textAlign: TextAlign.left,
|
textAlign: TextAlign.left,
|
||||||
style: const TextStyle(fontSize: 15),
|
style: const TextStyle(fontSize: 15),
|
||||||
activity.description)),
|
activity.description)),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.fromLTRB(15, 20, 0, 10),
|
||||||
|
child: Text(
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 20, fontWeight: FontWeight.bold),
|
||||||
|
'Media:')),
|
||||||
ActivityViewMedia(activity: activity),
|
ActivityViewMedia(activity: activity),
|
||||||
const Padding(
|
const Padding(
|
||||||
padding: EdgeInsets.fromLTRB(15, 30, 0, 10),
|
padding: EdgeInsets.fromLTRB(15, 30, 0, 10),
|
||||||
child: Text(
|
child: Text(
|
||||||
textAlign: TextAlign.left,
|
textAlign: TextAlign.left,
|
||||||
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
|
style: TextStyle(
|
||||||
|
fontSize: 20, fontWeight: FontWeight.bold),
|
||||||
'Actions')),
|
'Actions')),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(left: 10, right: 10),
|
padding: const EdgeInsets.only(left: 10, right: 10),
|
||||||
@ -64,39 +118,54 @@ class _ActivityViewState extends State<ActivityView> {
|
|||||||
child: Row(children: [
|
child: Row(children: [
|
||||||
Ink(
|
Ink(
|
||||||
width: 70,
|
width: 70,
|
||||||
color: Theme.of(context).colorScheme.primaryContainer,
|
color: Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.primaryContainer,
|
||||||
child: Consumer<ActivityTimerModel>(
|
child: Consumer<ActivityTimerModel>(
|
||||||
builder: (context, atm, child) {
|
builder: (context, atm, child) {
|
||||||
return IconButton(
|
return IconButton(
|
||||||
alignment: AlignmentDirectional.center,
|
alignment:
|
||||||
|
AlignmentDirectional.center,
|
||||||
icon: atm.isActive
|
icon: atm.isActive
|
||||||
? const Icon(Icons.pause_rounded)
|
? const Icon(
|
||||||
: const Icon(Icons.play_arrow_rounded),
|
Icons.pause_rounded)
|
||||||
onPressed: () =>
|
: const Icon(
|
||||||
{atm.isActive ? atm.pause() : atm.start()});
|
Icons.play_arrow_rounded),
|
||||||
|
onPressed: () => {
|
||||||
|
atm.isActive
|
||||||
|
? atm.pause()
|
||||||
|
: atm.start()
|
||||||
|
});
|
||||||
},
|
},
|
||||||
)),
|
)),
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 1,
|
flex: 1,
|
||||||
child: Stack(alignment: Alignment.center, children: [
|
child: Stack(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
children: [
|
||||||
Container(
|
Container(
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
child: Consumer<ActivityTimerModel>(
|
child: Consumer<ActivityTimerModel>(
|
||||||
builder: (context, atm, child) {
|
builder: (context, atm, child) {
|
||||||
return Text(
|
return Text(
|
||||||
style: const TextStyle(fontSize: 20),
|
style: const TextStyle(
|
||||||
|
fontSize: 20),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
'${atm.actionCount} ${atm.currentAction['type']}');
|
'${atm.actionCount} ${atm.currentAction['type']}'.toTitleCase());
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Container(
|
Container(
|
||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
padding: EdgeInsets.only(right: 10),
|
padding:
|
||||||
child: Consumer<ActivityTimerModel>(
|
EdgeInsets.only(right: 15),
|
||||||
builder: (context, atm, child) {
|
child:
|
||||||
|
Consumer<ActivityTimerModel>(
|
||||||
|
builder: (context, atm,
|
||||||
|
child) {
|
||||||
return Text(
|
return Text(
|
||||||
style: const TextStyle(fontSize: 12),
|
style: const TextStyle(
|
||||||
|
fontSize: 12),
|
||||||
textAlign: TextAlign.right,
|
textAlign: TextAlign.right,
|
||||||
'${atm.currentAction['actionID'] + 1} of ${atm.totalActions()}');
|
'${atm.currentAction['actionID'] + 1} of ${atm.totalActions()}');
|
||||||
})),
|
})),
|
||||||
@ -104,82 +173,24 @@ class _ActivityViewState extends State<ActivityView> {
|
|||||||
]))),
|
]))),
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.only(left: 14, right: 14),
|
padding: EdgeInsets.only(left: 14, right: 14),
|
||||||
child: Consumer<ActivityTimerModel>(builder: (context, atm, child) {
|
child: Consumer<ActivityTimerModel>(
|
||||||
|
builder: (context, atm, child) {
|
||||||
return LinearProgressIndicator(
|
return LinearProgressIndicator(
|
||||||
value: atm.progress,
|
value: atm.progress,
|
||||||
semanticsLabel: 'Activity Progress',
|
semanticsLabel: 'Activity Progress',
|
||||||
);
|
);
|
||||||
})),
|
})),
|
||||||
ActivityActionView(action: activity.actions[0]),
|
ActivityActionView(actions: actions),
|
||||||
]);
|
]));
|
||||||
}
|
} else {
|
||||||
}
|
return Container(
|
||||||
|
alignment: Alignment.center,
|
||||||
class ActivityViewCategories extends StatelessWidget {
|
|
||||||
const ActivityViewCategories({super.key, this.categories});
|
|
||||||
|
|
||||||
final List<String>? categories;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Column(
|
|
||||||
children: [
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(bottom: 10),
|
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 50.0,
|
||||||
child: ListView.builder(
|
width: 50.0,
|
||||||
shrinkWrap: true,
|
child: CircularProgressIndicator(),
|
||||||
scrollDirection: Axis.horizontal,
|
|
||||||
padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
|
|
||||||
itemCount: categories?.length,
|
|
||||||
itemBuilder: (BuildContext context, int index) {
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.only(right: 5),
|
|
||||||
child: ActionChip(
|
|
||||||
visualDensity: VisualDensity.compact,
|
|
||||||
avatar: const Icon(Icons.check_circle_outline),
|
|
||||||
label: Text(maxLines: 1, '${categories?[index]}'),
|
|
||||||
onPressed: () {},
|
|
||||||
));
|
));
|
||||||
},
|
}
|
||||||
))),
|
});
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ActivityViewMedia extends StatelessWidget {
|
|
||||||
const ActivityViewMedia({super.key, this.activity});
|
|
||||||
|
|
||||||
final ActivityModel? activity;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
List<Media> media = [];
|
|
||||||
|
|
||||||
for (ActivityAction action in activity!.actions) {
|
|
||||||
if (action.media!.isNotEmpty) {
|
|
||||||
media.addAll(action.media as Iterable<Media>);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Widget> mediaCards =
|
|
||||||
List.generate(media.length, (i) => MediaCard(media: media[i]));
|
|
||||||
|
|
||||||
return Column(
|
|
||||||
children: [
|
|
||||||
SizedBox(
|
|
||||||
width: double.infinity,
|
|
||||||
height: 100,
|
|
||||||
child: GridView.count(
|
|
||||||
padding: const EdgeInsets.fromLTRB(15, 0, 0, 0),
|
|
||||||
scrollDirection: Axis.horizontal,
|
|
||||||
crossAxisSpacing: 5,
|
|
||||||
mainAxisSpacing: 5,
|
|
||||||
crossAxisCount: 1,
|
|
||||||
children: mediaCards))
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
30
lib/widgets/activity_view_categories.dart
Normal file
30
lib/widgets/activity_view_categories.dart
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:sendtrain/database/database.dart';
|
||||||
|
import 'package:sendtrain/extensions/string_extensions.dart';
|
||||||
|
|
||||||
|
class ActivityViewCategories extends StatelessWidget {
|
||||||
|
const ActivityViewCategories({super.key, required this.categories});
|
||||||
|
|
||||||
|
final List<ActivityCategories> categories;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SizedBox(
|
||||||
|
height: 40,
|
||||||
|
child: ListView.builder(
|
||||||
|
shrinkWrap: true,
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
padding: const EdgeInsets.only(right: 10),
|
||||||
|
itemCount: categories.length,
|
||||||
|
itemBuilder: (BuildContext context, int index) {
|
||||||
|
return ActionChip(
|
||||||
|
visualDensity: VisualDensity.compact,
|
||||||
|
avatar: const Icon(Icons.category_rounded),
|
||||||
|
label: Text(maxLines: 1, categories[index].name.toTitleCase()),
|
||||||
|
tooltip: "Activity Category",
|
||||||
|
onPressed: () {},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
51
lib/widgets/activity_view_media.dart
Normal file
51
lib/widgets/activity_view_media.dart
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:sendtrain/daos/media_items_dao.dart';
|
||||||
|
import 'package:sendtrain/database/database.dart';
|
||||||
|
import 'package:sendtrain/widgets/media_card.dart';
|
||||||
|
|
||||||
|
class ActivityViewMedia extends StatelessWidget {
|
||||||
|
const ActivityViewMedia({super.key, required this.activity});
|
||||||
|
|
||||||
|
final Activity activity;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return FutureBuilder<List<MediaItem>>(
|
||||||
|
future: MediaItemsDao(Provider.of<AppDatabase>(context)).fromActivity(activity),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.hasData) {
|
||||||
|
List<MediaItem> mediaItems = snapshot.data!;
|
||||||
|
List<MediaCard> mediaCards = [];
|
||||||
|
|
||||||
|
for (int i = 0; i < mediaItems.length; i++) {
|
||||||
|
mediaCards.add(MediaCard(media: mediaItems[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
width: double.infinity,
|
||||||
|
height: 100,
|
||||||
|
child: GridView.count(
|
||||||
|
padding: const EdgeInsets.fromLTRB(15, 0, 0, 0),
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
crossAxisSpacing: 5,
|
||||||
|
mainAxisSpacing: 5,
|
||||||
|
crossAxisCount: 1,
|
||||||
|
children: mediaCards))
|
||||||
|
],
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return Container(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: SizedBox(
|
||||||
|
height: 50.0,
|
||||||
|
width: 50.0,
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
30
lib/widgets/activity_view_types.dart
Normal file
30
lib/widgets/activity_view_types.dart
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:sendtrain/database/database.dart';
|
||||||
|
import 'package:sendtrain/extensions/string_extensions.dart';
|
||||||
|
|
||||||
|
class ActivityViewTypes extends StatelessWidget {
|
||||||
|
const ActivityViewTypes({super.key, required this.types});
|
||||||
|
|
||||||
|
final List<ActivityType> types;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SizedBox(
|
||||||
|
height: 40,
|
||||||
|
child: ListView.builder(
|
||||||
|
shrinkWrap: true,
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
padding: const EdgeInsets.only(right: 10),
|
||||||
|
itemCount: types.length,
|
||||||
|
itemBuilder: (BuildContext context, int index) {
|
||||||
|
return ActionChip(
|
||||||
|
visualDensity: VisualDensity.compact,
|
||||||
|
avatar: const Icon(Icons.fitness_center_rounded),
|
||||||
|
label: Text(maxLines: 1, types[index].name.toTitleCase()),
|
||||||
|
tooltip: "Activity Type",
|
||||||
|
onPressed: () {},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,11 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:sendtrain/classes/media.dart';
|
import 'package:sendtrain/database/database.dart';
|
||||||
import 'package:youtube_player_flutter/youtube_player_flutter.dart';
|
import 'package:youtube_player_flutter/youtube_player_flutter.dart';
|
||||||
|
|
||||||
class MediaCard extends StatelessWidget {
|
class MediaCard extends StatelessWidget {
|
||||||
const MediaCard({super.key, required this.media});
|
const MediaCard({super.key, required this.media});
|
||||||
|
|
||||||
final Media media;
|
final MediaItem media;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -14,22 +14,22 @@ class MediaCard extends StatelessWidget {
|
|||||||
flags: const YoutubePlayerFlags(
|
flags: const YoutubePlayerFlags(
|
||||||
autoPlay: false, mute: true, showLiveFullscreenButton: false));
|
autoPlay: false, mute: true, showLiveFullscreenButton: false));
|
||||||
|
|
||||||
DecorationImage mediaImage(Media media) {
|
DecorationImage mediaImage(MediaItem media) {
|
||||||
String image = '';
|
String image = '';
|
||||||
|
|
||||||
if (media.type == "image") {
|
if (media.type == MediaType.image) {
|
||||||
image = media.reference;
|
image = media.reference;
|
||||||
} else if (media.type == "youtube") {
|
} else if (media.type == MediaType.youtube) {
|
||||||
image = 'https://img.youtube.com/vi/${media.reference}/0.jpg';
|
image = 'https://img.youtube.com/vi/${media.reference}/0.jpg';
|
||||||
}
|
}
|
||||||
|
|
||||||
return DecorationImage(image: NetworkImage(image), fit: BoxFit.cover);
|
return DecorationImage(image: NetworkImage(image), fit: BoxFit.cover);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget mediaItem(Media media) {
|
Widget mediaItem(MediaItem media) {
|
||||||
if (media.type == "image") {
|
if (media.type == MediaType.image) {
|
||||||
return Image(image: NetworkImage(media.reference));
|
return Image(image: NetworkImage(media.reference));
|
||||||
} else if (media.type == "youtube") {
|
} else if (media.type == MediaType.youtube) {
|
||||||
return YoutubePlayer(
|
return YoutubePlayer(
|
||||||
controller: controller,
|
controller: controller,
|
||||||
aspectRatio: 16 / 9,
|
aspectRatio: 16 / 9,
|
||||||
@ -62,7 +62,7 @@ class MediaCard extends StatelessWidget {
|
|||||||
mediaItem(media),
|
mediaItem(media),
|
||||||
const SizedBox(height: 15),
|
const SizedBox(height: 15),
|
||||||
Text(
|
Text(
|
||||||
'${media.description}',
|
media.description,
|
||||||
style: const TextStyle(fontSize: 20),
|
style: const TextStyle(fontSize: 20),
|
||||||
),
|
),
|
||||||
const Divider(
|
const Divider(
|
||||||
|
@ -1,170 +1,23 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:intl/date_symbol_data_local.dart';
|
import 'package:intl/date_symbol_data_local.dart';
|
||||||
import 'package:sendtrain/classes/activity_action.dart';
|
import 'package:sendtrain/database/database.dart' hide ActivityAction;
|
||||||
import 'package:sendtrain/classes/media.dart';
|
import 'package:sendtrain/extensions/string_extensions.dart';
|
||||||
import 'package:sendtrain/models/activity_model.dart';
|
|
||||||
import 'package:sendtrain/models/session_model.dart';
|
|
||||||
import 'package:sendtrain/widgets/session_view.dart';
|
import 'package:sendtrain/widgets/session_view.dart';
|
||||||
|
|
||||||
class SessionCard extends StatelessWidget {
|
class SessionCard extends StatelessWidget {
|
||||||
final int state;
|
|
||||||
final int type;
|
final int type;
|
||||||
const SessionCard({super.key, this.state = 0, this.type = 0});
|
final Session session;
|
||||||
|
const SessionCard({super.key, this.type = 0, required this.session});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
initializeDateFormatting('en');
|
initializeDateFormatting('en');
|
||||||
final DateFormat dateFormat = DateFormat('yyyy-MM-dd');
|
final DateFormat dateFormat = DateFormat('yyyy-MM-dd');
|
||||||
|
|
||||||
Color color = (state == 0)
|
Color color = (session.status == SessionStatus.started)
|
||||||
? const Color(0xff3A5FB6)
|
? Theme.of(context).colorScheme.primaryContainer
|
||||||
: ThemeData.dark(useMaterial3: true).colorScheme.surfaceBright;
|
: Theme.of(context).colorScheme.surfaceContainerLow;
|
||||||
|
|
||||||
// place holder until we can retrieve real data
|
|
||||||
final data = SessionModel(
|
|
||||||
id: 1,
|
|
||||||
title: "Projecting @ Climbers Rock",
|
|
||||||
content:
|
|
||||||
"Beta pully beta beta pinch one arm crimpy. Futuristic pinch, dyno dynamic drop knee climb. Climbing ondra slopey onsight beta ondra power endurance.",
|
|
||||||
date: DateTime.now(),
|
|
||||||
activities: [
|
|
||||||
ActivityModel(
|
|
||||||
id: 1,
|
|
||||||
title: 'Campus Board',
|
|
||||||
type: 'fundamental',
|
|
||||||
categories: ['strength', 'power'],
|
|
||||||
description:
|
|
||||||
"Campus board session, focusing on explosiveness and contact strength.",
|
|
||||||
actions: [
|
|
||||||
ActivityAction(
|
|
||||||
id: 1,
|
|
||||||
title: '1, 3, 5',
|
|
||||||
description: 'Move between the first, third, and fifth rungs, alternating hands. Rest and alternate sides, to start',
|
|
||||||
media: [
|
|
||||||
Media(
|
|
||||||
id: 1,
|
|
||||||
reference:
|
|
||||||
'https://www.climbing.com/wp-content/uploads/2022/06/campus-board-e1655470701154.jpeg',
|
|
||||||
type: 'image',
|
|
||||||
description: 'Campus board movement'),
|
|
||||||
Media(
|
|
||||||
id: 1,
|
|
||||||
reference: '7ACyeOP-Hxo',
|
|
||||||
type: 'youtube',
|
|
||||||
description: 'How to campus board')
|
|
||||||
],
|
|
||||||
activityActionSet: Set(
|
|
||||||
type: 'drop_set',
|
|
||||||
total: 3,
|
|
||||||
rest: 300000,
|
|
||||||
reps: Reps(
|
|
||||||
type: 'repititions',
|
|
||||||
tempo: [0],
|
|
||||||
amounts: [1, 1, 1],
|
|
||||||
weights: [0],
|
|
||||||
rest: 20000))),
|
|
||||||
],
|
|
||||||
resources: ['https://www.youtube.com/watch?v=bLz0xp1PEm4']),
|
|
||||||
ActivityModel(
|
|
||||||
id: 2,
|
|
||||||
title: 'Projecting',
|
|
||||||
type: 'fundamental',
|
|
||||||
categories: ['technique', 'conditioning'],
|
|
||||||
description:
|
|
||||||
"Session focused on attempting a climb at or beyond your perceived limit.",
|
|
||||||
actions: [
|
|
||||||
ActivityAction(
|
|
||||||
id: 1,
|
|
||||||
title: 'Attempt Climb',
|
|
||||||
description: 'Attempt your selected climb, if you fall off early in the climb, attempt again. 1 repitition equals roughly doing all the moves, not necessarily in 1 attempt.',
|
|
||||||
media: [
|
|
||||||
Media(
|
|
||||||
id: 1,
|
|
||||||
reference:
|
|
||||||
'https://www.climbing.com/wp-content/uploads/2022/07/Fixed-44.jpg',
|
|
||||||
type: 'image',
|
|
||||||
description: 'Projecting a climb'),
|
|
||||||
Media(
|
|
||||||
id: 1,
|
|
||||||
reference: 'BgheYcxhrsw',
|
|
||||||
type: 'youtube',
|
|
||||||
description: 'How to project climbs')
|
|
||||||
],
|
|
||||||
activityActionSet: Set(
|
|
||||||
type: 'standard',
|
|
||||||
total: 10,
|
|
||||||
rest: 300000,
|
|
||||||
reps: Reps(
|
|
||||||
type: 'repititions',
|
|
||||||
tempo: [0],
|
|
||||||
amounts: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
|
||||||
weights: [0],
|
|
||||||
rest: 0))),
|
|
||||||
],
|
|
||||||
resources: ['https://www.youtube.com/watch?v=dyAvbUvY_PU']),
|
|
||||||
ActivityModel(
|
|
||||||
id: 3,
|
|
||||||
title: 'Long Block Pulls',
|
|
||||||
type: 'Hypertrophy',
|
|
||||||
categories: ['Strength', 'Power'],
|
|
||||||
description:
|
|
||||||
"Block pull on a edge of a specific size and time to induce a hypertrophic effect on the formarms.",
|
|
||||||
actions: [
|
|
||||||
ActivityAction(
|
|
||||||
id: 1,
|
|
||||||
title: 'Long Pulls',
|
|
||||||
description: 'Select your desired weight to pull, add it to the block. You should aim for an effort level of 8-9 when reaching the end of the set time, going to failure will result in significantly extended recovery time.',
|
|
||||||
media: [
|
|
||||||
Media(
|
|
||||||
id: 1,
|
|
||||||
reference:
|
|
||||||
'https://trailandcrag.com/sites/default/files/inline-images/05-min_3.jpg',
|
|
||||||
type: 'image',
|
|
||||||
description: 'Block pull example'),
|
|
||||||
Media(
|
|
||||||
id: 1,
|
|
||||||
reference: 'sZVAEy9UmoY',
|
|
||||||
type: 'youtube',
|
|
||||||
description: 'Principals of Grip gains, and related protocols')
|
|
||||||
],
|
|
||||||
activityActionSet: Set(
|
|
||||||
type: 'alternating',
|
|
||||||
total: 5,
|
|
||||||
rest: 5000,
|
|
||||||
reps: Reps(
|
|
||||||
type: 'seconds',
|
|
||||||
tempo: [0],
|
|
||||||
amounts: [5, 5, 5, 5, 5],
|
|
||||||
weights: [80, 80, 80, 80, 80],
|
|
||||||
rest: 5000))),
|
|
||||||
],
|
|
||||||
resources: ['https://www.youtube.com/watch?v=dyAvbUvY_PU']),
|
|
||||||
],
|
|
||||||
achievements: [
|
|
||||||
'got 1 3 5 first time!',
|
|
||||||
'no pain in elbow',
|
|
||||||
'life is pain',
|
|
||||||
'new PR for pullups'
|
|
||||||
],
|
|
||||||
media: [
|
|
||||||
Media(
|
|
||||||
id: 1,
|
|
||||||
reference: 'TwS8ycTY5cc',
|
|
||||||
type: 'youtube',
|
|
||||||
description: 'Attempting crux move'),
|
|
||||||
Media(
|
|
||||||
id: 1,
|
|
||||||
reference:
|
|
||||||
'https://static.wixstatic.com/media/c83481_1dd473ad49524ae5a95d993ba10e0a50~mv2.jpg/v1/fill/w_640,h_426,al_c,q_80,usm_0.66_1.00_0.01,enc_auto/c83481_1dd473ad49524ae5a95d993ba10e0a50~mv2.jpg',
|
|
||||||
type: 'image',
|
|
||||||
description: 'Struggling on deadpoints'),
|
|
||||||
Media(
|
|
||||||
id: 1,
|
|
||||||
reference: 'TwS8ycTY5cc',
|
|
||||||
type: 'youtube',
|
|
||||||
description: 'Attempting crux move')
|
|
||||||
]);
|
|
||||||
|
|
||||||
if (type == 0) {
|
if (type == 0) {
|
||||||
return Card(
|
return Card(
|
||||||
@ -186,7 +39,7 @@ class SessionCard extends StatelessWidget {
|
|||||||
.animate(animation);
|
.animate(animation);
|
||||||
return SlideTransition(
|
return SlideTransition(
|
||||||
position: custom,
|
position: custom,
|
||||||
child: Dialog.fullscreen(child: SessionView(data: data)));
|
child: Dialog.fullscreen(child: SessionView(session: session)));
|
||||||
},
|
},
|
||||||
barrierDismissible: true,
|
barrierDismissible: true,
|
||||||
barrierLabel: '',
|
barrierLabel: '',
|
||||||
@ -212,8 +65,32 @@ class SessionCard extends StatelessWidget {
|
|||||||
BorderRadius.all(Radius.elliptical(10, 10)),
|
BorderRadius.all(Radius.elliptical(10, 10)),
|
||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
title: Text(maxLines: 1, data.title),
|
title: Text(maxLines: 1, session.title.toTitleCase()),
|
||||||
subtitle: Text(maxLines: 1, dateFormat.format(data.date)),
|
subtitle: Text(maxLines: 1, dateFormat.format(session.date as DateTime)),
|
||||||
|
trailing: IconButton(
|
||||||
|
visualDensity: VisualDensity.compact,
|
||||||
|
icon: Icon(Icons.close_rounded),
|
||||||
|
onPressed: () {
|
||||||
|
showAdaptiveDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) => AlertDialog(
|
||||||
|
title: const Text('Session Removal'),
|
||||||
|
content: const Text(
|
||||||
|
'Would you like to permanently remove this session?'),
|
||||||
|
actions: <Widget>[
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.pop(context, 'Cancel'),
|
||||||
|
child: const Text('Cancel'),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.pop(context, 'OK'),
|
||||||
|
child: const Text('OK'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
contentPadding: const EdgeInsets.fromLTRB(15, 0, 15, 15),
|
contentPadding: const EdgeInsets.fromLTRB(15, 0, 15, 15),
|
||||||
@ -221,14 +98,14 @@ class SessionCard extends StatelessWidget {
|
|||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: const TextStyle(fontWeight: FontWeight.w300),
|
style: const TextStyle(fontWeight: FontWeight.w300),
|
||||||
data.content),
|
session.content),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)),
|
)),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return Card(
|
return Card(
|
||||||
color: const Color.fromARGB(125, 0, 0, 0),
|
color: color,
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
// overlayColor: MaterialStateColor(Colors.deepPurple as int),
|
// overlayColor: MaterialStateColor(Colors.deepPurple as int),
|
||||||
splashColor: Colors.deepPurple,
|
splashColor: Colors.deepPurple,
|
||||||
@ -247,7 +124,7 @@ class SessionCard extends StatelessWidget {
|
|||||||
return SlideTransition(
|
return SlideTransition(
|
||||||
position: custom,
|
position: custom,
|
||||||
child:
|
child:
|
||||||
Dialog.fullscreen(child: SessionView(data: data)));
|
Dialog.fullscreen(child: SessionView(session: session)));
|
||||||
},
|
},
|
||||||
barrierDismissible: true,
|
barrierDismissible: true,
|
||||||
barrierLabel: '',
|
barrierLabel: '',
|
||||||
@ -274,11 +151,11 @@ class SessionCard extends StatelessWidget {
|
|||||||
ListTile(
|
ListTile(
|
||||||
title: Text(
|
title: Text(
|
||||||
maxLines: 3,
|
maxLines: 3,
|
||||||
data.title,
|
session.title.toTitleCase(),
|
||||||
textAlign: TextAlign.center),
|
textAlign: TextAlign.center),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
dateFormat.format(data.date),
|
dateFormat.format(session.date as DateTime),
|
||||||
textAlign: TextAlign.center),
|
textAlign: TextAlign.center),
|
||||||
),
|
),
|
||||||
])))));
|
])))));
|
||||||
|
@ -1,143 +1,106 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_expandable_fab/flutter_expandable_fab.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:intl/date_symbol_data_local.dart';
|
import 'package:intl/date_symbol_data_local.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:sendtrain/daos/activities_dao.dart';
|
||||||
|
|
||||||
import 'package:sendtrain/classes/media.dart';
|
import 'package:sendtrain/database/database.dart';
|
||||||
import 'package:sendtrain/models/activity_model.dart';
|
import 'package:sendtrain/extensions/string_extensions.dart';
|
||||||
import 'package:sendtrain/models/session_model.dart';
|
import 'package:sendtrain/widgets/session_view_achievements.dart';
|
||||||
import 'package:sendtrain/widgets/activity_card.dart';
|
import 'package:sendtrain/widgets/session_view_activities.dart';
|
||||||
import 'package:sendtrain/widgets/media_card.dart';
|
import 'package:sendtrain/widgets/session_view_media.dart';
|
||||||
|
|
||||||
class SessionView extends StatelessWidget {
|
class SessionView extends StatelessWidget {
|
||||||
const SessionView({super.key, required this.data});
|
const SessionView({super.key, required this.session});
|
||||||
|
|
||||||
final SessionModel data;
|
final Session session;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
initializeDateFormatting('en');
|
initializeDateFormatting('en');
|
||||||
final DateFormat dateFormat = DateFormat('yyyy-MM-dd');
|
final DateFormat dateFormat = DateFormat('yyyy-MM-dd');
|
||||||
|
|
||||||
return Column(
|
return FutureBuilder<List<Activity>>(
|
||||||
|
future: ActivitiesDao(Provider.of<AppDatabase>(context)).sessionActivities(session.id),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.hasData) {
|
||||||
|
final activities = snapshot.data!;
|
||||||
|
return Scaffold(
|
||||||
|
floatingActionButtonLocation: ExpandableFab.location,
|
||||||
|
floatingActionButton: ExpandableFab(
|
||||||
|
distance: 70,
|
||||||
|
type: ExpandableFabType.up,
|
||||||
|
overlayStyle: ExpandableFabOverlayStyle(
|
||||||
|
color: Colors.black.withOpacity(0.5),
|
||||||
|
blur: 10,
|
||||||
|
),
|
||||||
|
children: [
|
||||||
|
FloatingActionButton.extended(
|
||||||
|
icon: const Icon(Icons.history_outlined),
|
||||||
|
label: Text('Restart'),
|
||||||
|
onPressed: () {},
|
||||||
|
),
|
||||||
|
FloatingActionButton.extended(
|
||||||
|
icon: const Icon(Icons.done_all_outlined),
|
||||||
|
label: Text('Done'),
|
||||||
|
onPressed: () {},
|
||||||
|
),
|
||||||
|
FloatingActionButton.extended(
|
||||||
|
icon: const Icon(Icons.edit_outlined),
|
||||||
|
label: Text('Edit'),
|
||||||
|
onPressed: () {},
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
body: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
AppBar(
|
AppBar(
|
||||||
centerTitle: true,
|
centerTitle: true,
|
||||||
title: Text('Session @ ${dateFormat.format(data.date)}',
|
title: Text(
|
||||||
|
'Session @ ${dateFormat.format(session.date as DateTime)}',
|
||||||
style: const TextStyle(fontSize: 15)),
|
style: const TextStyle(fontSize: 15)),
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding:
|
padding: const EdgeInsets.only(
|
||||||
const EdgeInsets.only(left: 15, right: 20, top: 15, bottom: 10),
|
left: 15, right: 20, top: 15, bottom: 10),
|
||||||
child: Text(
|
child: Text(
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
style:
|
style: const TextStyle(
|
||||||
const TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
|
fontSize: 25, fontWeight: FontWeight.bold),
|
||||||
data.title)),
|
session.title.toTitleCase())),
|
||||||
SessionViewAchievements(achievements: data.achievements),
|
SessionViewAchievements(session: session),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(left: 15, right: 15),
|
padding: const EdgeInsets.only(left: 15, right: 15),
|
||||||
child: Text(
|
child: Text(
|
||||||
style: const TextStyle(fontSize: 15),
|
style: const TextStyle(fontSize: 15),
|
||||||
data.content)),
|
session.content)),
|
||||||
const Padding(
|
const Padding(
|
||||||
padding: EdgeInsets.fromLTRB(15, 30, 0, 10),
|
padding: EdgeInsets.fromLTRB(15, 30, 0, 10),
|
||||||
child: Text(
|
child: Text(
|
||||||
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
|
style: TextStyle(
|
||||||
|
fontSize: 20, fontWeight: FontWeight.bold),
|
||||||
'Media:')),
|
'Media:')),
|
||||||
SessionViewMedia(media: data.media),
|
SessionViewMedia(session: session),
|
||||||
const Padding(
|
const Padding(
|
||||||
padding: EdgeInsets.fromLTRB(15, 30, 0, 10),
|
padding: EdgeInsets.fromLTRB(15, 30, 0, 10),
|
||||||
child: Text(
|
child: Text(
|
||||||
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
|
style: TextStyle(
|
||||||
|
fontSize: 20, fontWeight: FontWeight.bold),
|
||||||
'Activites:')),
|
'Activites:')),
|
||||||
SessionViewActivities(activities: data.activities),
|
SessionViewActivities(
|
||||||
// TextButton(
|
activities: activities),
|
||||||
// onPressed: () {
|
|
||||||
// Navigator.pop(context);
|
|
||||||
// },
|
|
||||||
// child: const Text('Close'),
|
|
||||||
// ),
|
|
||||||
],
|
],
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SessionViewActivities extends StatelessWidget {
|
|
||||||
const SessionViewActivities({super.key, this.activities});
|
|
||||||
|
|
||||||
final List<ActivityModel>? activities;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Expanded(
|
|
||||||
child: ListView.builder(
|
|
||||||
// shrinkWrap: true,
|
|
||||||
padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
|
|
||||||
itemCount: activities?.length,
|
|
||||||
itemBuilder: (BuildContext context, int index) {
|
|
||||||
return ActivityCard(activity: activities![index]);
|
|
||||||
},
|
|
||||||
));
|
));
|
||||||
}
|
} else {
|
||||||
}
|
return Container(
|
||||||
|
alignment: Alignment.center,
|
||||||
class SessionViewAchievements extends StatelessWidget {
|
|
||||||
const SessionViewAchievements({super.key, this.achievements});
|
|
||||||
|
|
||||||
final List<String>? achievements;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Column(
|
|
||||||
children: [
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(bottom: 10),
|
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 50.0,
|
||||||
child: ListView.builder(
|
width: 50.0,
|
||||||
scrollDirection: Axis.horizontal,
|
child: CircularProgressIndicator(),
|
||||||
padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
|
|
||||||
itemCount: achievements?.length,
|
|
||||||
itemBuilder: (BuildContext context, int index) {
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.only(right: 5),
|
|
||||||
child: ActionChip(
|
|
||||||
visualDensity: VisualDensity.compact,
|
|
||||||
avatar: const Icon(Icons.check_circle_outline),
|
|
||||||
label: Text(maxLines: 1, '${achievements?[index]}'),
|
|
||||||
onPressed: () {},
|
|
||||||
));
|
));
|
||||||
},
|
}
|
||||||
))),
|
});
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SessionViewMedia extends StatelessWidget {
|
|
||||||
const SessionViewMedia({super.key, this.media});
|
|
||||||
|
|
||||||
final List<Media>? media;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
List<Widget> mediaCards = List.generate((media != null) ? media!.length : 0,
|
|
||||||
(i) => MediaCard(media: media![i]));
|
|
||||||
|
|
||||||
return Column(
|
|
||||||
children: [
|
|
||||||
SizedBox(
|
|
||||||
width: double.infinity,
|
|
||||||
height: 100,
|
|
||||||
child: GridView.count(
|
|
||||||
padding: const EdgeInsets.fromLTRB(15, 0, 0, 0),
|
|
||||||
scrollDirection: Axis.horizontal,
|
|
||||||
crossAxisSpacing: 5,
|
|
||||||
mainAxisSpacing: 5,
|
|
||||||
crossAxisCount: 1,
|
|
||||||
children: mediaCards))
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
68
lib/widgets/session_view_achievements.dart
Normal file
68
lib/widgets/session_view_achievements.dart
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:sendtrain/daos/session_activities_dao.dart';
|
||||||
|
import 'package:sendtrain/database/database.dart';
|
||||||
|
import 'package:sendtrain/extensions/string_extensions.dart';
|
||||||
|
|
||||||
|
class SessionViewAchievements extends StatelessWidget {
|
||||||
|
const SessionViewAchievements({super.key, required this.session});
|
||||||
|
|
||||||
|
final Session session;
|
||||||
|
|
||||||
|
List<String> getAchievements(List<SessionActivity> sessionActivities) {
|
||||||
|
List<String> achievements = [];
|
||||||
|
|
||||||
|
for (int i = 0; i < sessionActivities.length; i++) {
|
||||||
|
final SessionActivity sessionActivity = sessionActivities[i];
|
||||||
|
final List? saAchievments = sessionActivity.achievements?.split(',');
|
||||||
|
|
||||||
|
if (saAchievments != null) {
|
||||||
|
saAchievments.forEach((achievement) => achievements.add(achievement));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return achievements;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return FutureBuilder<List<SessionActivity>>(
|
||||||
|
future: SessionActivitiesDao(Provider.of<AppDatabase>(context))
|
||||||
|
.fromSessionId(session.id),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.hasData) {
|
||||||
|
final sessionActivities = snapshot.data!;
|
||||||
|
final achievements = getAchievements(sessionActivities);
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 10),
|
||||||
|
child: SizedBox(
|
||||||
|
height: 40,
|
||||||
|
child: ListView.builder(
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
|
||||||
|
itemCount: achievements.length,
|
||||||
|
itemBuilder: (BuildContext context, int index) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 5),
|
||||||
|
child: ActionChip(
|
||||||
|
visualDensity: VisualDensity.compact,
|
||||||
|
avatar:
|
||||||
|
const Icon(Icons.check_circle_outline),
|
||||||
|
label: Text(maxLines: 1, achievements[index].toTitleCase()),
|
||||||
|
onPressed: () {},
|
||||||
|
));
|
||||||
|
},
|
||||||
|
))),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return Padding(
|
||||||
|
padding: EdgeInsets.all(15),
|
||||||
|
child: CircularProgressIndicator());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
23
lib/widgets/session_view_activities.dart
Normal file
23
lib/widgets/session_view_activities.dart
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:sendtrain/database/database.dart';
|
||||||
|
import 'package:sendtrain/widgets/activity_card.dart';
|
||||||
|
|
||||||
|
class SessionViewActivities extends StatelessWidget {
|
||||||
|
const SessionViewActivities({super.key, required this.activities });
|
||||||
|
|
||||||
|
final List<Activity> activities;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Expanded(
|
||||||
|
child: ListView.builder(
|
||||||
|
// shrinkWrap: true,
|
||||||
|
padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
|
||||||
|
itemCount: activities.length,
|
||||||
|
itemBuilder: (BuildContext context, int index) {
|
||||||
|
return ActivityCard(
|
||||||
|
activity: activities[index]);
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
45
lib/widgets/session_view_media.dart
Normal file
45
lib/widgets/session_view_media.dart
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:sendtrain/daos/media_items_dao.dart';
|
||||||
|
import 'package:sendtrain/database/database.dart';
|
||||||
|
import 'package:sendtrain/widgets/media_card.dart';
|
||||||
|
|
||||||
|
class SessionViewMedia extends StatelessWidget {
|
||||||
|
const SessionViewMedia({super.key, required this.session});
|
||||||
|
|
||||||
|
final Session session;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return FutureBuilder<List<MediaItem>>(
|
||||||
|
future: MediaItemsDao(Provider.of<AppDatabase>(context))
|
||||||
|
.fromSession(session),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.hasData) {
|
||||||
|
final mediaItems = snapshot.data!;
|
||||||
|
|
||||||
|
List<Widget> mediaCards = List.generate(
|
||||||
|
mediaItems.length, (i) => MediaCard(media: mediaItems[i]));
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
width: double.infinity,
|
||||||
|
height: 100,
|
||||||
|
child: GridView.count(
|
||||||
|
padding: const EdgeInsets.fromLTRB(15, 0, 0, 0),
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
crossAxisSpacing: 5,
|
||||||
|
mainAxisSpacing: 5,
|
||||||
|
crossAxisCount: 1,
|
||||||
|
children: mediaCards))
|
||||||
|
],
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return Padding(
|
||||||
|
padding: EdgeInsets.all(15),
|
||||||
|
child: CircularProgressIndicator());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +0,0 @@
|
|||||||
//
|
|
||||||
// Generated file. Do not edit.
|
|
||||||
//
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
|
|
||||||
#include "generated_plugin_registrant.h"
|
|
||||||
|
|
||||||
|
|
||||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
//
|
|
||||||
// Generated file. Do not edit.
|
|
||||||
//
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
|
|
||||||
#ifndef GENERATED_PLUGIN_REGISTRANT_
|
|
||||||
#define GENERATED_PLUGIN_REGISTRANT_
|
|
||||||
|
|
||||||
#include <flutter_linux/flutter_linux.h>
|
|
||||||
|
|
||||||
// Registers Flutter plugins.
|
|
||||||
void fl_register_plugins(FlPluginRegistry* registry);
|
|
||||||
|
|
||||||
#endif // GENERATED_PLUGIN_REGISTRANT_
|
|
@ -1,23 +0,0 @@
|
|||||||
#
|
|
||||||
# Generated file, do not edit.
|
|
||||||
#
|
|
||||||
|
|
||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
|
||||||
)
|
|
||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
|
||||||
)
|
|
||||||
|
|
||||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
|
||||||
|
|
||||||
foreach(plugin ${FLUTTER_PLUGIN_LIST})
|
|
||||||
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
|
|
||||||
target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
|
|
||||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
|
|
||||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
|
|
||||||
endforeach(plugin)
|
|
||||||
|
|
||||||
foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
|
|
||||||
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})
|
|
||||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
|
|
||||||
endforeach(ffi_plugin)
|
|
@ -1,12 +0,0 @@
|
|||||||
//
|
|
||||||
// Generated file. Do not edit.
|
|
||||||
//
|
|
||||||
|
|
||||||
import FlutterMacOS
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
import flutter_inappwebview_macos
|
|
||||||
|
|
||||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
|
||||||
InAppWebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "InAppWebViewFlutterPlugin"))
|
|
||||||
}
|
|
12
macos/RunnerTests/RunnerTests.swift
Normal file
12
macos/RunnerTests/RunnerTests.swift
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import Cocoa
|
||||||
|
import FlutterMacOS
|
||||||
|
import XCTest
|
||||||
|
|
||||||
|
class RunnerTests: XCTestCase {
|
||||||
|
|
||||||
|
func testExample() {
|
||||||
|
// If you add code to the Runner application, consider adding tests here.
|
||||||
|
// See https://developer.apple.com/documentation/xctest for more information about using XCTest.
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -41,6 +41,9 @@ dependencies:
|
|||||||
json_annotation: ^4.9.0
|
json_annotation: ^4.9.0
|
||||||
provider: ^6.1.2
|
provider: ^6.1.2
|
||||||
scrollable_positioned_list: ^0.3.8
|
scrollable_positioned_list: ^0.3.8
|
||||||
|
drift: ^2.22.1
|
||||||
|
flutter_expandable_fab: ^2.3.0
|
||||||
|
drift_flutter: ^0.2.2
|
||||||
|
|
||||||
flutter_launcher_name:
|
flutter_launcher_name:
|
||||||
name: "SendTrain"
|
name: "SendTrain"
|
||||||
@ -57,6 +60,8 @@ dev_dependencies:
|
|||||||
flutter_lints: ^5.0.0
|
flutter_lints: ^5.0.0
|
||||||
build_runner: ^2.4.13
|
build_runner: ^2.4.13
|
||||||
json_serializable: ^6.9.0
|
json_serializable: ^6.9.0
|
||||||
|
drift_dev: ^2.22.1
|
||||||
|
test: ^1.25.7
|
||||||
|
|
||||||
# For information on the generic Dart part of this file, see the
|
# For information on the generic Dart part of this file, see the
|
||||||
# following page: https://dart.dev/tools/pub/pubspec
|
# following page: https://dart.dev/tools/pub/pubspec
|
||||||
|
29
test/drift/sendtrain/generated/schema.dart
Normal file
29
test/drift/sendtrain/generated/schema.dart
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// dart format width=80
|
||||||
|
// GENERATED CODE, DO NOT EDIT BY HAND.
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:drift/internal/migrations.dart';
|
||||||
|
import 'schema_v1.dart' as v1;
|
||||||
|
import 'schema_v2.dart' as v2;
|
||||||
|
import 'schema_v3.dart' as v3;
|
||||||
|
import 'schema_v4.dart' as v4;
|
||||||
|
|
||||||
|
class GeneratedHelper implements SchemaInstantiationHelper {
|
||||||
|
@override
|
||||||
|
GeneratedDatabase databaseForVersion(QueryExecutor db, int version) {
|
||||||
|
switch (version) {
|
||||||
|
case 1:
|
||||||
|
return v1.DatabaseAtV1(db);
|
||||||
|
case 2:
|
||||||
|
return v2.DatabaseAtV2(db);
|
||||||
|
case 3:
|
||||||
|
return v3.DatabaseAtV3(db);
|
||||||
|
case 4:
|
||||||
|
return v4.DatabaseAtV4(db);
|
||||||
|
default:
|
||||||
|
throw MissingSchemaException(version, versions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const versions = const [1, 2, 3, 4];
|
||||||
|
}
|
1916
test/drift/sendtrain/generated/schema_v1.dart
Normal file
1916
test/drift/sendtrain/generated/schema_v1.dart
Normal file
File diff suppressed because it is too large
Load Diff
1916
test/drift/sendtrain/generated/schema_v2.dart
Normal file
1916
test/drift/sendtrain/generated/schema_v2.dart
Normal file
File diff suppressed because it is too large
Load Diff
1977
test/drift/sendtrain/generated/schema_v3.dart
Normal file
1977
test/drift/sendtrain/generated/schema_v3.dart
Normal file
File diff suppressed because it is too large
Load Diff
1977
test/drift/sendtrain/generated/schema_v4.dart
Normal file
1977
test/drift/sendtrain/generated/schema_v4.dart
Normal file
File diff suppressed because it is too large
Load Diff
104
test/drift/sendtrain/migration_test.dart
Normal file
104
test/drift/sendtrain/migration_test.dart
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
// // dart format width=80
|
||||||
|
// // ignore_for_file: unused_local_variable, unused_import
|
||||||
|
// import 'package:drift/drift.dart';
|
||||||
|
// import 'package:drift_dev/api/migrations_native.dart';
|
||||||
|
// import 'package:sendtrain/database/database.dart';
|
||||||
|
// import 'package:test/test.dart';
|
||||||
|
// import 'generated/schema.dart';
|
||||||
|
|
||||||
|
// import 'generated/schema_v1.dart' as v1;
|
||||||
|
// import 'generated/schema_v2.dart' as v2;
|
||||||
|
|
||||||
|
// void main() {
|
||||||
|
// driftRuntimeOptions.dontWarnAboutMultipleDatabases = true;
|
||||||
|
// late SchemaVerifier verifier;
|
||||||
|
|
||||||
|
// setUpAll(() {
|
||||||
|
// verifier = SchemaVerifier(GeneratedHelper());
|
||||||
|
// });
|
||||||
|
|
||||||
|
// group('simple database migrations', () {
|
||||||
|
// // These simple tests verify all possible schema updates with a simple (no
|
||||||
|
// // data) migration. This is a quick way to ensure that written database
|
||||||
|
// // migrations properly alter the schema.
|
||||||
|
// final versions = GeneratedHelper.versions;
|
||||||
|
// for (final (i, fromVersion) in versions.indexed) {
|
||||||
|
// group('from $fromVersion', () {
|
||||||
|
// for (final toVersion in versions.skip(i + 1)) {
|
||||||
|
// test('to $toVersion', () async {
|
||||||
|
// final schema = await verifier.schemaAt(fromVersion);
|
||||||
|
// final db = AppDatabase(schema.newConnection());
|
||||||
|
// await verifier.migrateAndValidate(db, toVersion);
|
||||||
|
// await db.close();
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
// // The following template shows how to write tests ensuring your migrations
|
||||||
|
// // preserve existing data.
|
||||||
|
// // Testing this can be useful for migrations that change existing columns
|
||||||
|
// // (e.g. by alterating their type or constraints). Migrations that only add
|
||||||
|
// // tables or columns typically don't need these advanced tests. For more
|
||||||
|
// // information, see https://drift.simonbinder.eu/migrations/tests/#verifying-data-integrity
|
||||||
|
// // TODO: This generated template shows how these tests could be written. Adopt
|
||||||
|
// // it to your own needs when testing migrations with data integrity.
|
||||||
|
// test("migration from v1 to v2 does not corrupt data", () async {
|
||||||
|
// // Add data to insert into the old database, and the expected rows after the
|
||||||
|
// // migration.
|
||||||
|
// // TODO: Fill these lists
|
||||||
|
// final oldSessionsData = <v1.SessionsData>[];
|
||||||
|
// final expectedNewSessionsData = <v2.SessionsData>[];
|
||||||
|
|
||||||
|
// final oldActivitiesData = <v1.ActivitiesData>[];
|
||||||
|
// final expectedNewActivitiesData = <v2.ActivitiesData>[];
|
||||||
|
|
||||||
|
// final oldSessionActivitiesData = <v1.SessionActivitiesData>[];
|
||||||
|
// final expectedNewSessionActivitiesData = <v2.SessionActivitiesData>[];
|
||||||
|
|
||||||
|
// final oldActionsData = <v1.ActionsData>[];
|
||||||
|
// final expectedNewActionsData = <v2.ActionsData>[];
|
||||||
|
|
||||||
|
// final oldActivityActionsData = <v1.ActivityActionsData>[];
|
||||||
|
// final expectedNewActivityActionsData = <v2.ActivityActionsData>[];
|
||||||
|
|
||||||
|
// final oldMediaItemsData = <v1.MediaItemsData>[];
|
||||||
|
// final expectedNewMediaItemsData = <v2.MediaItemsData>[];
|
||||||
|
|
||||||
|
// final oldObjectMediaItemsData = <v1.ObjectMediaItemsData>[];
|
||||||
|
// final expectedNewObjectMediaItemsData = <v2.ObjectMediaItemsData>[];
|
||||||
|
|
||||||
|
// await verifier.testWithDataIntegrity(
|
||||||
|
// oldVersion: 1,
|
||||||
|
// newVersion: 2,
|
||||||
|
// createOld: v1.DatabaseAtV1.new,
|
||||||
|
// createNew: v2.DatabaseAtV2.new,
|
||||||
|
// openTestedDatabase: AppDatabase.new,
|
||||||
|
// createItems: (batch, oldDb) {
|
||||||
|
// batch.insertAll(oldDb.sessions, oldSessionsData);
|
||||||
|
// batch.insertAll(oldDb.activities, oldActivitiesData);
|
||||||
|
// batch.insertAll(oldDb.sessionActivities, oldSessionActivitiesData);
|
||||||
|
// batch.insertAll(oldDb.actions, oldActionsData);
|
||||||
|
// batch.insertAll(oldDb.activityActions, oldActivityActionsData);
|
||||||
|
// batch.insertAll(oldDb.mediaItems, oldMediaItemsData);
|
||||||
|
// batch.insertAll(oldDb.objectMediaItems, oldObjectMediaItemsData);
|
||||||
|
// },
|
||||||
|
// validateItems: (newDb) async {
|
||||||
|
// expect(
|
||||||
|
// expectedNewSessionsData, await newDb.select(newDb.sessions).get());
|
||||||
|
// expect(expectedNewActivitiesData,
|
||||||
|
// await newDb.select(newDb.activities).get());
|
||||||
|
// expect(expectedNewSessionActivitiesData,
|
||||||
|
// await newDb.select(newDb.sessionActivities).get());
|
||||||
|
// expect(expectedNewActionsData, await newDb.select(newDb.actions).get());
|
||||||
|
// expect(expectedNewActivityActionsData,
|
||||||
|
// await newDb.select(newDb.activityActions).get());
|
||||||
|
// expect(expectedNewMediaItemsData,
|
||||||
|
// await newDb.select(newDb.mediaItems).get());
|
||||||
|
// expect(expectedNewObjectMediaItemsData,
|
||||||
|
// await newDb.select(newDb.objectMediaItems).get());
|
||||||
|
// },
|
||||||
|
// );
|
||||||
|
// });
|
||||||
|
// }
|
@ -1,14 +0,0 @@
|
|||||||
//
|
|
||||||
// Generated file. Do not edit.
|
|
||||||
//
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
|
|
||||||
#include "generated_plugin_registrant.h"
|
|
||||||
|
|
||||||
#include <flutter_inappwebview_windows/flutter_inappwebview_windows_plugin_c_api.h>
|
|
||||||
|
|
||||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
|
||||||
FlutterInappwebviewWindowsPluginCApiRegisterWithRegistrar(
|
|
||||||
registry->GetRegistrarForPlugin("FlutterInappwebviewWindowsPluginCApi"));
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
//
|
|
||||||
// Generated file. Do not edit.
|
|
||||||
//
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
|
|
||||||
#ifndef GENERATED_PLUGIN_REGISTRANT_
|
|
||||||
#define GENERATED_PLUGIN_REGISTRANT_
|
|
||||||
|
|
||||||
#include <flutter/plugin_registry.h>
|
|
||||||
|
|
||||||
// Registers Flutter plugins.
|
|
||||||
void RegisterPlugins(flutter::PluginRegistry* registry);
|
|
||||||
|
|
||||||
#endif // GENERATED_PLUGIN_REGISTRANT_
|
|
@ -1,24 +0,0 @@
|
|||||||
#
|
|
||||||
# Generated file, do not edit.
|
|
||||||
#
|
|
||||||
|
|
||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
|
||||||
flutter_inappwebview_windows
|
|
||||||
)
|
|
||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
|
||||||
)
|
|
||||||
|
|
||||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
|
||||||
|
|
||||||
foreach(plugin ${FLUTTER_PLUGIN_LIST})
|
|
||||||
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin})
|
|
||||||
target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
|
|
||||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
|
|
||||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
|
|
||||||
endforeach(plugin)
|
|
||||||
|
|
||||||
foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
|
|
||||||
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin})
|
|
||||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
|
|
||||||
endforeach(ffi_plugin)
|
|
Reference in New Issue
Block a user