Compare commits
85 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
db58b54754 | ||
|
|
7de3d211bb | ||
|
|
d3e5fc99ea | ||
|
|
17cffc0576 | ||
|
|
f38ff3b862 | ||
|
|
89e67c369e | ||
|
|
6dd68c8f5d | ||
|
|
97b01e9f14 | ||
|
|
556ba9d289 | ||
|
|
64868e85f3 | ||
|
|
30ac155b4b | ||
|
|
36bd679644 | ||
|
|
75b03b95bc | ||
|
|
ac18cf62c3 | ||
|
|
3619a7a4a7 | ||
|
|
a71b365e4a | ||
|
|
20fa9a8aef | ||
|
|
da12ac8646 | ||
|
|
4b40692fe1 | ||
|
|
26f65a4144 | ||
|
|
f8cfa04d04 | ||
|
|
82671f5ec9 | ||
|
|
5d37de897f | ||
|
|
fcb1d8d6d9 | ||
|
|
446fad4c5f | ||
|
|
0f799375a1 | ||
|
|
29aa356cd0 | ||
|
|
3abaf2f96a | ||
|
|
5b48847cf2 | ||
|
|
b82a56ca65 | ||
|
|
94c57abdea | ||
|
|
e3c26987ec | ||
|
|
eac710a5b4 | ||
|
|
b8299c4daf | ||
|
|
7a671b6aa6 | ||
|
|
f51de83c88 | ||
|
|
d77cc081a9 | ||
|
|
18fa9a6de7 | ||
|
|
4467267e61 | ||
|
|
f39b9ffeb6 | ||
|
|
0df9de97d4 | ||
|
|
69a3090f16 | ||
|
|
818060bbcb | ||
|
|
38eb8c440b | ||
|
|
47a18c1ec2 | ||
|
|
cc33550331 | ||
|
|
4af3e51300 | ||
|
|
ea33d00f54 | ||
|
|
75eba2c83f | ||
|
|
4a81722747 | ||
|
|
ed67551164 | ||
|
|
c53502f16a | ||
|
|
d13de96ae9 | ||
|
|
53e9aca376 | ||
|
|
8a39086ca6 | ||
|
|
fd7793a20d | ||
|
|
7a793a3af0 | ||
|
|
cac21a4849 | ||
|
|
4c558157e8 | ||
|
|
043b669737 | ||
|
|
7b9ec6de2e | ||
|
|
b14821901c | ||
|
|
cc05524bea | ||
|
|
b3d791a4c3 | ||
|
|
9525d7d1df | ||
|
|
bc040185d0 | ||
|
|
65e98bf8a8 | ||
|
|
1a0558485e | ||
|
|
8f7c46d2d4 | ||
|
|
4f3d44dfed | ||
|
|
922e8984f8 | ||
|
|
ee475f8ee8 | ||
|
|
3c431cbce1 | ||
|
|
708c411339 | ||
|
|
1e9247652a | ||
|
|
551ed6ebdb | ||
|
|
c86ac68007 | ||
|
|
d309f11f19 | ||
|
|
e4acd4f872 | ||
|
|
3ee91e7543 | ||
|
|
f147ae328e | ||
|
|
aab1f605d4 | ||
|
|
c71a6d9468 | ||
|
|
165f836d93 | ||
|
|
6356206291 |
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
@@ -1 +1 @@
|
|||||||
patreon: filcnaplo
|
github: filc
|
||||||
|
|||||||
11
.github/dependabot.yml
vendored
Normal file
11
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# To get started with Dependabot version updates, you'll need to specify which
|
||||||
|
# package ecosystems to update and where the package manifests are located.
|
||||||
|
# Please see the documentation for all configuration options:
|
||||||
|
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||||
|
|
||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: "pub" # See documentation for possible values
|
||||||
|
directory: "/" # Location of package manifests
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
||||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,5 +1,8 @@
|
|||||||
# See https://www.dartlang.org/guides/libraries/private-files
|
# See https://www.dartlang.org/guides/libraries/private-files
|
||||||
|
|
||||||
|
termek.txt
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
# Files and directories created by pub
|
# Files and directories created by pub
|
||||||
.dart_tool/
|
.dart_tool/
|
||||||
.packages
|
.packages
|
||||||
@@ -19,3 +22,5 @@ doc/api/
|
|||||||
*.js_
|
*.js_
|
||||||
*.js.deps
|
*.js.deps
|
||||||
*.js.map
|
*.js.map
|
||||||
|
|
||||||
|
*.txt
|
||||||
5
.vscode/launch.json
vendored
5
.vscode/launch.json
vendored
@@ -7,8 +7,11 @@
|
|||||||
{
|
{
|
||||||
"name": "filcnaplo",
|
"name": "filcnaplo",
|
||||||
"cwd": "filcnaplo",
|
"cwd": "filcnaplo",
|
||||||
"request": "attach",
|
"request": "launch",
|
||||||
"type": "dart",
|
"type": "dart",
|
||||||
|
"toolArgs": [
|
||||||
|
"--dart-define=APPVER=$(cat pubspec.yaml | grep version: | cut -d' ' -f2 | cut -d+ -f1)"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
12
changelog.md
12
changelog.md
@@ -1,6 +1,6 @@
|
|||||||
- Órarendben dolgozatok javítása
|
What's new:
|
||||||
- Kilógó félév jelző javítása a grafikonon
|
|
||||||
- Dicséretes jegyek jelzése
|
- Több szín lehetőség, egyedi hexadecimális szín választás
|
||||||
- Üzenet & Szellem jegy animációk
|
- Több tanuló esetén legutóbb kiválasztott tanuló mutatása indításkor
|
||||||
- Design javítások
|
- Hibajavítások 🐛
|
||||||
- Kisebb hibajavítások
|
- **Megérkezett a Filc Premium!** ✨
|
||||||
|
|||||||
@@ -1,10 +1,30 @@
|
|||||||
# This file tracks properties of this Flutter project.
|
# This file tracks properties of this Flutter project.
|
||||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||||
#
|
#
|
||||||
# This file should be version controlled and should not be manually edited.
|
# This file should be version controlled.
|
||||||
|
|
||||||
version:
|
version:
|
||||||
revision: 06e2fd63574bad2edafbe4653104ed76871ee0b1
|
revision: 3c0bee85b8e43b860877922bdc411a7333db4d32
|
||||||
channel: beta
|
channel: beta
|
||||||
|
|
||||||
project_type: app
|
project_type: app
|
||||||
|
|
||||||
|
# Tracks metadata for the flutter migrate command
|
||||||
|
migration:
|
||||||
|
platforms:
|
||||||
|
- platform: root
|
||||||
|
create_revision: 3c0bee85b8e43b860877922bdc411a7333db4d32
|
||||||
|
base_revision: 3c0bee85b8e43b860877922bdc411a7333db4d32
|
||||||
|
- platform: macos
|
||||||
|
create_revision: 3c0bee85b8e43b860877922bdc411a7333db4d32
|
||||||
|
base_revision: 3c0bee85b8e43b860877922bdc411a7333db4d32
|
||||||
|
|
||||||
|
# User provided section
|
||||||
|
|
||||||
|
# List of Local paths (relative to this file) that should be
|
||||||
|
# ignored by the migrate tool.
|
||||||
|
#
|
||||||
|
# Files that are not part of the templates will be ignored by default.
|
||||||
|
unmanaged_files:
|
||||||
|
- 'lib/main.dart'
|
||||||
|
- 'ios/Runner.xcodeproj/project.pbxproj'
|
||||||
|
|||||||
@@ -26,13 +26,8 @@ apply plugin: 'kotlin-android'
|
|||||||
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
||||||
|
|
||||||
def keystoreProperties = new Properties()
|
def keystoreProperties = new Properties()
|
||||||
def keystorePropertiesFile = rootProject.file("$System.env.ANDROID_SIGNING")
|
def keystorePropertiesFile = rootProject.file("$System.env.HOME/keys/filc3.properties")
|
||||||
if (keystorePropertiesFile.exists()) {
|
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
|
||||||
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
|
|
||||||
} else {
|
|
||||||
keystoreProperties.load(new FileInputStream(rootProject.file("signing/signing.properties")))
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion rootProject.ext.compileSdkVersion
|
compileSdkVersion rootProject.ext.compileSdkVersion
|
||||||
|
|||||||
@@ -1,19 +1,62 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="hu.filc.naplo">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="hu.filc.naplo">
|
||||||
<application android:label="Filc Napló" android:icon="@mipmap/ic_launcher" android:requestLegacyExternalStorage="true">
|
<application android:label="Filc Napló" android:icon="@mipmap/ic_launcher" android:requestLegacyExternalStorage="true">
|
||||||
<activity android:exported="true" android:name=".MainActivity" android:launchMode="singleTop" android:theme="@style/LaunchTheme" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize">
|
<activity android:exported="true" android:name=".MainActivity" android:launchMode="singleTop" android:theme="@style/LaunchTheme" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize">
|
||||||
<meta-data android:name="io.flutter.embedding.android.NormalTheme" android:resource="@style/NormalTheme" />
|
<meta-data android:name="io.flutter.embedding.android.NormalTheme" android:resource="@style/NormalTheme" />
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN"/>
|
<action android:name="android.intent.action.MAIN" />
|
||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
<intent-filter android:autoVerify="true">
|
||||||
<meta-data android:name="flutterEmbedding" android:value="2" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
</application>
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
<!-- Accepts URIs that begin with https://api.filcnaplo.hu -->
|
||||||
|
<data
|
||||||
|
android:scheme="https"
|
||||||
|
android:host="api.filcnaplo.hu"
|
||||||
|
android:pathPrefix="/callback" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
<meta-data android:name="flutterEmbedding" android:value="2" />
|
||||||
|
|
||||||
<!-- Permissions -->
|
<!-- <receiver android:name=".WidgetTimetable.widget_timetable"
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
android:exported="true">
|
||||||
<uses-permission android:name="android.permission.VIBRATE" />
|
<intent-filter>
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
<action android:name="list_widget.ACTION_WIDGET_CLICK_NAV_LEFT" />
|
||||||
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
|
<action android:name="list_widget.ACTION_WIDGET_CLICK_NAV_RIGHT" />
|
||||||
|
<action android:name="list_widget.ACTION_WIDGET_CLICK_NAV_TODAY" />
|
||||||
|
<action android:name="list_widget.ACTION_WIDGET_CLICK_NAV_REFRESH" />
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="android.appwidget.provider"
|
||||||
|
android:resource="@xml/home_widget_test_info" />
|
||||||
|
</receiver>
|
||||||
|
|
||||||
|
<service android:name=".WidgetTimetable.widget_timetable_service"
|
||||||
|
android:permission="android.permission.BIND_REMOTEVIEWS" />
|
||||||
|
|
||||||
|
<receiver android:name="es.antonborri.home_widget.HomeWidgetBackgroundReceiver"
|
||||||
|
android:exported="true">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="es.antonborri.home_widget.action.BACKGROUND" />
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
|
|
||||||
|
<service android:name="es.antonborri.home_widget.HomeWidgetBackgroundService"
|
||||||
|
android:permission="android.permission.BIND_JOB_SERVICE" android:exported="true" />
|
||||||
|
-->
|
||||||
|
</application>
|
||||||
|
|
||||||
|
<!-- Permissions -->
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="android.permission.VIBRATE" />
|
||||||
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
|
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
||||||
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||||
</manifest>
|
</manifest>
|
||||||
@@ -2,8 +2,8 @@ buildscript {
|
|||||||
ext.kotlin_version = '1.6.10'
|
ext.kotlin_version = '1.6.10'
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
compileSdkVersion = 31
|
compileSdkVersion = 33
|
||||||
targetSdkVersion = 31
|
targetSdkVersion = 33
|
||||||
appCompatVersion = "1.1.0"
|
appCompatVersion = "1.1.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ subprojects {
|
|||||||
afterEvaluate {project ->
|
afterEvaluate {project ->
|
||||||
if (project.plugins.hasPlugin('android') || project.plugins.hasPlugin('android-library')) {
|
if (project.plugins.hasPlugin('android') || project.plugins.hasPlugin('android-library')) {
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 31
|
compileSdkVersion 33
|
||||||
buildToolsVersion '31.0.0'
|
buildToolsVersion '31.0.0'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
@@ -1,4 +0,0 @@
|
|||||||
keyAlias=test
|
|
||||||
keyPassword=test123
|
|
||||||
storeFile=../signing/signing.keystore
|
|
||||||
storePassword=test123
|
|
||||||
BIN
filcnaplo/assets/animations/backpack-2.riv
Normal file
BIN
filcnaplo/assets/animations/backpack-2.riv
Normal file
Binary file not shown.
1
filcnaplo/assets/animations/bell-alert.json
Normal file
1
filcnaplo/assets/animations/bell-alert.json
Normal file
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -1,5 +0,0 @@
|
|||||||
<svg width="20" height="22" viewBox="0 0 20 22" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path
|
|
||||||
d="M1 8L10 1L19 8V19C19 19.5304 18.7893 20.0391 18.4142 20.4142C18.0391 20.7893 17.5304 21 17 21H3C2.46957 21 1.96086 20.7893 1.58579 20.4142C1.21071 20.0391 1 19.5304 1 19V8Z"
|
|
||||||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 384 B |
@@ -1,3 +0,0 @@
|
|||||||
<svg width="288" height="288" viewBox="0 0 288 288" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M159.653 207.26C136.598 217.973 115.171 217.858 100.771 216.821C83.6064 215.583 69.7824 210.888 63.72 206.77C59.976 204.236 54.8928 205.215 52.3584 208.959C49.824 212.703 50.8032 217.786 54.5472 220.32C64.3104 226.93 81.5616 231.84 99.5904 233.136C102.643 233.367 105.998 233.496 109.613 233.496C125.309 233.496 145.238 231.999 166.55 222.092C170.64 220.176 172.426 215.324 170.51 211.22C168.61 207.13 163.742 205.344 159.653 207.26ZM250.574 195.135C251.352 124.057 258.667 -10.2371 122.616 0.620487C-11.7072 11.4348 23.904 153.332 21.9024 200.852C20.1312 225.994 11.7936 256.723 0 288H36.3024C40.0464 274.752 42.7824 261.634 43.9632 249.149C46.152 250.675 48.4992 252.144 51.0048 253.555C55.0656 255.96 58.5648 259.143 62.2656 262.512C70.9056 270.389 80.712 279.331 99.864 280.44C101.146 280.512 102.442 280.555 103.709 280.555C123.091 280.555 136.339 272.074 146.995 265.263C152.093 261.994 156.499 259.171 160.646 257.818C172.44 254.131 182.736 248.17 190.426 240.595C191.635 239.415 192.744 238.191 193.795 236.952C198.086 252.663 203.962 270.36 210.47 288H288C269.366 259.258 250.171 231.077 250.574 195.135ZM34.9056 156.471V156.457C33.5664 133.258 44.6688 113.761 59.688 112.882C74.7072 112.004 87.9696 130.105 89.3088 153.289C89.3088 153.303 89.3088 153.303 89.3088 153.303C89.3808 154.556 89.4096 155.794 89.4096 157.018C84.6576 158.213 80.352 159.956 76.5072 161.986C76.4928 161.813 76.4784 161.641 76.464 161.468V161.453C75.1824 148.292 68.1552 138.356 60.7536 139.249C53.3664 140.156 48.4128 151.561 49.7088 164.722C50.2704 170.468 51.912 175.594 54.216 179.482C53.64 179.929 52.0272 181.109 50.1696 182.477C48.7728 183.5 47.0592 184.738 45.0144 186.25C39.4272 178.906 35.5968 168.365 34.9056 156.471ZM187.099 213.797C186.566 226.051 170.525 237.586 155.722 242.208L155.635 242.237C149.472 244.239 143.986 247.752 138.168 251.467C128.405 257.717 118.296 264.183 103.709 264.183C102.744 264.183 101.765 264.154 100.8 264.096C87.4368 263.319 81.1872 257.631 73.2816 250.416C69.1056 246.615 64.7856 242.669 59.2272 239.415L59.0976 239.343C47.088 232.56 39.6288 224.136 39.1536 216.778C38.9232 213.135 40.5504 209.967 43.992 207.389C51.48 201.773 56.5056 198.101 59.8176 195.668C63.504 192.975 64.6272 192.168 65.448 191.376C66.0384 190.829 66.672 190.21 67.3632 189.533C74.232 182.852 85.7376 171.663 103.406 171.663C114.206 171.663 126.158 175.825 138.888 184.004C144.878 187.906 150.106 189.706 156.715 191.996C161.251 193.565 166.406 195.336 173.304 198.288L173.419 198.346C179.842 200.981 187.445 205.805 187.099 213.783V213.797ZM183.557 184.997C182.318 184.378 181.022 183.788 179.683 183.226C173.462 180.576 168.48 178.762 164.347 177.322C166.637 172.858 168.048 167.285 168.178 161.223C168.494 146.492 161.064 134.525 151.589 134.511C142.099 134.482 134.165 146.405 133.848 161.137C133.834 161.626 133.834 162.101 133.848 162.577C128.002 159.898 122.256 157.94 116.64 156.745C116.611 156.183 116.582 155.636 116.568 155.074V155.06C116.021 128.233 132.494 106.014 153.346 105.452C174.197 104.89 191.549 126.174 192.096 153.015V153.029C192.341 165.169 189.101 176.329 183.557 184.997Z" fill="black"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 3.2 KiB |
12
filcnaplo/build.sh
Normal file → Executable file
12
filcnaplo/build.sh
Normal file → Executable file
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/fish
|
#!/usr/bin/env fish
|
||||||
|
|
||||||
# With build number
|
# With build number
|
||||||
function get_version_bn
|
function get_version_bn
|
||||||
@@ -9,11 +9,5 @@ function get_version
|
|||||||
cat pubspec.yaml | grep version: | cut -d' ' -f2 | cut -d+ -f1
|
cat pubspec.yaml | grep version: | cut -d' ' -f2 | cut -d+ -f1
|
||||||
end
|
end
|
||||||
|
|
||||||
if test -e /mnt/enc/keys/filc3.properties
|
flutter build apk --release --dart-define=APPVER=(get_version) --no-tree-shake-icons && \
|
||||||
set -x ANDROID_SIGNING /mnt/enc/keys/filc3.properties
|
cp -v "build/app/outputs/flutter-apk/app-release.apk" ~/"Desktop/hu.filc.naplo_"(get_version_bn).apk
|
||||||
end
|
|
||||||
|
|
||||||
flutter build apk --release --dart-define=APPVER=(get_version)
|
|
||||||
cp -v "build/app/outputs/flutter-apk/app-release.apk" ~/"Desktop/hu.filc.naplo_"(get_version_bn).apk
|
|
||||||
|
|
||||||
notify-send "Flutter" "Apk build done."
|
|
||||||
|
|||||||
@@ -21,6 +21,6 @@
|
|||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1.0</string>
|
<string>1.0</string>
|
||||||
<key>MinimumOSVersion</key>
|
<key>MinimumOSVersion</key>
|
||||||
<string>9.0</string>
|
<string>11.0</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Uncomment this line to define a global platform for your project
|
# Uncomment this line to define a global platform for your project
|
||||||
# platform :ios, '9.0'
|
# platform :ios, '11.0'
|
||||||
|
|
||||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||||
@@ -32,6 +32,8 @@ target 'Runner' do
|
|||||||
use_modular_headers!
|
use_modular_headers!
|
||||||
|
|
||||||
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
|
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
|
||||||
|
|
||||||
|
pod 'DKImagePickerController/PhotoGallery', :git => 'https://github.com/zhangao0086/DKImagePickerController.git'
|
||||||
end
|
end
|
||||||
|
|
||||||
post_install do |installer|
|
post_install do |installer|
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
PODS:
|
PODS:
|
||||||
- DKImagePickerController/Core (4.3.2):
|
- connectivity_plus (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- ReachabilitySwift
|
||||||
|
- DKImagePickerController/Core (4.3.4):
|
||||||
- DKImagePickerController/ImageDataManager
|
- DKImagePickerController/ImageDataManager
|
||||||
- DKImagePickerController/Resource
|
- DKImagePickerController/Resource
|
||||||
- DKImagePickerController/ImageDataManager (4.3.2)
|
- DKImagePickerController/ImageDataManager (4.3.4)
|
||||||
- DKImagePickerController/PhotoGallery (4.3.2):
|
- DKImagePickerController/PhotoGallery (4.3.4):
|
||||||
- DKImagePickerController/Core
|
- DKImagePickerController/Core
|
||||||
- DKPhotoGallery
|
- DKPhotoGallery
|
||||||
- DKImagePickerController/Resource (4.3.2)
|
- DKImagePickerController/Resource (4.3.4)
|
||||||
- DKPhotoGallery (0.0.17):
|
- DKPhotoGallery (0.0.17):
|
||||||
- DKPhotoGallery/Core (= 0.0.17)
|
- DKPhotoGallery/Core (= 0.0.17)
|
||||||
- DKPhotoGallery/Model (= 0.0.17)
|
- DKPhotoGallery/Model (= 0.0.17)
|
||||||
@@ -39,85 +42,105 @@ PODS:
|
|||||||
- FMDB (2.7.5):
|
- FMDB (2.7.5):
|
||||||
- FMDB/standard (= 2.7.5)
|
- FMDB/standard (= 2.7.5)
|
||||||
- FMDB/standard (2.7.5)
|
- FMDB/standard (2.7.5)
|
||||||
|
- live_activities (0.0.1):
|
||||||
|
- Flutter
|
||||||
- open_file (0.0.1):
|
- open_file (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- package_info_plus (0.4.5):
|
- path_provider_ios (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- path_provider (0.0.1):
|
- permission_handler_apple (9.0.4):
|
||||||
- Flutter
|
- Flutter
|
||||||
- "permission_handler (5.1.0+2)":
|
- quick_actions_ios (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- SDWebImage (5.11.1):
|
- ReachabilitySwift (5.0.0)
|
||||||
- SDWebImage/Core (= 5.11.1)
|
- SDWebImage (5.13.2):
|
||||||
- SDWebImage/Core (5.11.1)
|
- SDWebImage/Core (= 5.13.2)
|
||||||
|
- SDWebImage/Core (5.13.2)
|
||||||
- share_plus (0.0.1):
|
- share_plus (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- sqflite (0.0.2):
|
- sqflite (0.0.2):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FMDB (>= 2.7.5)
|
- FMDB (>= 2.7.5)
|
||||||
- SwiftyGif (5.4.0)
|
- SwiftyGif (5.4.3)
|
||||||
- url_launcher (0.0.1):
|
- url_launcher_ios (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
|
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
|
||||||
|
- DKImagePickerController/PhotoGallery (from `https://github.com/zhangao0086/DKImagePickerController.git`)
|
||||||
- file_picker (from `.symlinks/plugins/file_picker/ios`)
|
- file_picker (from `.symlinks/plugins/file_picker/ios`)
|
||||||
- Flutter (from `Flutter`)
|
- Flutter (from `Flutter`)
|
||||||
- flutter_custom_tabs (from `.symlinks/plugins/flutter_custom_tabs/ios`)
|
- flutter_custom_tabs (from `.symlinks/plugins/flutter_custom_tabs/ios`)
|
||||||
|
- live_activities (from `.symlinks/plugins/live_activities/ios`)
|
||||||
- open_file (from `.symlinks/plugins/open_file/ios`)
|
- open_file (from `.symlinks/plugins/open_file/ios`)
|
||||||
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
- path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`)
|
||||||
- path_provider (from `.symlinks/plugins/path_provider/ios`)
|
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
|
||||||
- permission_handler (from `.symlinks/plugins/permission_handler/ios`)
|
- quick_actions_ios (from `.symlinks/plugins/quick_actions_ios/ios`)
|
||||||
- share_plus (from `.symlinks/plugins/share_plus/ios`)
|
- share_plus (from `.symlinks/plugins/share_plus/ios`)
|
||||||
- sqflite (from `.symlinks/plugins/sqflite/ios`)
|
- sqflite (from `.symlinks/plugins/sqflite/ios`)
|
||||||
- url_launcher (from `.symlinks/plugins/url_launcher/ios`)
|
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
||||||
|
|
||||||
SPEC REPOS:
|
SPEC REPOS:
|
||||||
trunk:
|
trunk:
|
||||||
- DKImagePickerController
|
|
||||||
- DKPhotoGallery
|
- DKPhotoGallery
|
||||||
- FMDB
|
- FMDB
|
||||||
|
- ReachabilitySwift
|
||||||
- SDWebImage
|
- SDWebImage
|
||||||
- SwiftyGif
|
- SwiftyGif
|
||||||
|
|
||||||
EXTERNAL SOURCES:
|
EXTERNAL SOURCES:
|
||||||
|
connectivity_plus:
|
||||||
|
:path: ".symlinks/plugins/connectivity_plus/ios"
|
||||||
|
DKImagePickerController:
|
||||||
|
:git: https://github.com/zhangao0086/DKImagePickerController.git
|
||||||
file_picker:
|
file_picker:
|
||||||
:path: ".symlinks/plugins/file_picker/ios"
|
:path: ".symlinks/plugins/file_picker/ios"
|
||||||
Flutter:
|
Flutter:
|
||||||
:path: Flutter
|
:path: Flutter
|
||||||
flutter_custom_tabs:
|
flutter_custom_tabs:
|
||||||
:path: ".symlinks/plugins/flutter_custom_tabs/ios"
|
:path: ".symlinks/plugins/flutter_custom_tabs/ios"
|
||||||
|
live_activities:
|
||||||
|
:path: ".symlinks/plugins/live_activities/ios"
|
||||||
open_file:
|
open_file:
|
||||||
:path: ".symlinks/plugins/open_file/ios"
|
:path: ".symlinks/plugins/open_file/ios"
|
||||||
package_info_plus:
|
path_provider_ios:
|
||||||
:path: ".symlinks/plugins/package_info_plus/ios"
|
:path: ".symlinks/plugins/path_provider_ios/ios"
|
||||||
path_provider:
|
permission_handler_apple:
|
||||||
:path: ".symlinks/plugins/path_provider/ios"
|
:path: ".symlinks/plugins/permission_handler_apple/ios"
|
||||||
permission_handler:
|
quick_actions_ios:
|
||||||
:path: ".symlinks/plugins/permission_handler/ios"
|
:path: ".symlinks/plugins/quick_actions_ios/ios"
|
||||||
share_plus:
|
share_plus:
|
||||||
:path: ".symlinks/plugins/share_plus/ios"
|
:path: ".symlinks/plugins/share_plus/ios"
|
||||||
sqflite:
|
sqflite:
|
||||||
:path: ".symlinks/plugins/sqflite/ios"
|
:path: ".symlinks/plugins/sqflite/ios"
|
||||||
url_launcher:
|
url_launcher_ios:
|
||||||
:path: ".symlinks/plugins/url_launcher/ios"
|
:path: ".symlinks/plugins/url_launcher_ios/ios"
|
||||||
|
|
||||||
|
CHECKOUT OPTIONS:
|
||||||
|
DKImagePickerController:
|
||||||
|
:commit: a727e44718a67e300089174e5591166045815ba4
|
||||||
|
:git: https://github.com/zhangao0086/DKImagePickerController.git
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
DKImagePickerController: b5eb7f7a388e4643264105d648d01f727110fc3d
|
connectivity_plus: 413a8857dd5d9f1c399a39130850d02fe0feaf7e
|
||||||
|
DKImagePickerController: b512c28220a2b8ac7419f21c491fc8534b7601ac
|
||||||
DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179
|
DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179
|
||||||
file_picker: 3e6c3790de664ccf9b882732d9db5eaf6b8d4eb1
|
file_picker: 817ab1d8cd2da9d2da412a417162deee3500fc95
|
||||||
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
|
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
|
||||||
flutter_custom_tabs: 7a10a08686955cb748e5d26e0ae586d30689bf89
|
flutter_custom_tabs: 7a10a08686955cb748e5d26e0ae586d30689bf89
|
||||||
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
|
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
|
||||||
|
live_activities: 9ff56a06a2d43ecd68f56deeed13b18a8304789c
|
||||||
open_file: 02eb5cb6b21264bd3a696876f5afbfb7ca4f4b7d
|
open_file: 02eb5cb6b21264bd3a696876f5afbfb7ca4f4b7d
|
||||||
package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e
|
path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02
|
||||||
path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c
|
permission_handler_apple: 44366e37eaf29454a1e7b1b7d736c2cceaeb17ce
|
||||||
permission_handler: ccb20a9fad0ee9b1314a52b70b76b473c5f8dab0
|
quick_actions_ios: 56c03753992beabaa6c598e470e12d430d6e5e2f
|
||||||
SDWebImage: a7f831e1a65eb5e285e3fb046a23fcfbf08e696d
|
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
|
||||||
|
SDWebImage: 72f86271a6f3139cc7e4a89220946489d4b9a866
|
||||||
share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68
|
share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68
|
||||||
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
|
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
|
||||||
SwiftyGif: 5d4af95df24caf1c570dbbcb32a3b8a0763bc6d7
|
SwiftyGif: 6c3eafd0ce693cad58bb63d2b2fb9bacb8552780
|
||||||
url_launcher: 6fef411d543ceb26efce54b05a0a40bfd74cbbef
|
url_launcher_ios: 839c58cdb4279282219f5e248c3321761ff3c4de
|
||||||
|
|
||||||
PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
|
PODFILE CHECKSUM: 862f939bb7e5390bdb8b2534eb81a9457ea9fbdc
|
||||||
|
|
||||||
COCOAPODS: 1.11.0
|
COCOAPODS: 1.11.3
|
||||||
|
|||||||
@@ -3,11 +3,18 @@
|
|||||||
archiveVersion = 1;
|
archiveVersion = 1;
|
||||||
classes = {
|
classes = {
|
||||||
};
|
};
|
||||||
objectVersion = 46;
|
objectVersion = 51;
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
||||||
|
3127F78D28EAEDE200C2EFB3 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3127F75528EAECC800C2EFB3 /* WidgetKit.framework */; };
|
||||||
|
3127F78E28EAEDE200C2EFB3 /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3127F75728EAECC800C2EFB3 /* SwiftUI.framework */; };
|
||||||
|
3127F79828EAEDE300C2EFB3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3127F79728EAEDE300C2EFB3 /* Assets.xcassets */; };
|
||||||
|
3127F79E28EAEDE300C2EFB3 /* livecard.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 3127F78C28EAEDE200C2EFB3 /* livecard.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||||
|
3127F7A428EAEE3D00C2EFB3 /* livecard.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = 3127F7A328EAEE3D00C2EFB3 /* livecard.intentdefinition */; };
|
||||||
|
3127F7A628EAEE5900C2EFB3 /* livecard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3127F7A528EAEE5900C2EFB3 /* livecard.swift */; };
|
||||||
|
3127F7A828EAEE8500C2EFB3 /* lesson_model.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3127F7A728EAEE8500C2EFB3 /* lesson_model.swift */; };
|
||||||
373A6ECB5FC71FE9D8AF2EDB /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F0ADD56276103500A3016C8 /* Pods_Runner.framework */; };
|
373A6ECB5FC71FE9D8AF2EDB /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F0ADD56276103500A3016C8 /* Pods_Runner.framework */; };
|
||||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
||||||
@@ -16,7 +23,28 @@
|
|||||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
|
/* Begin PBXContainerItemProxy section */
|
||||||
|
3127F79C28EAEDE300C2EFB3 /* PBXContainerItemProxy */ = {
|
||||||
|
isa = PBXContainerItemProxy;
|
||||||
|
containerPortal = 97C146E61CF9000F007C117D /* Project object */;
|
||||||
|
proxyType = 1;
|
||||||
|
remoteGlobalIDString = 3127F78B28EAEDE200C2EFB3;
|
||||||
|
remoteInfo = livecardExtension;
|
||||||
|
};
|
||||||
|
/* End PBXContainerItemProxy section */
|
||||||
|
|
||||||
/* Begin PBXCopyFilesBuildPhase section */
|
/* Begin PBXCopyFilesBuildPhase section */
|
||||||
|
3127F74F28EAEC8A00C2EFB3 /* Embed Foundation Extensions */ = {
|
||||||
|
isa = PBXCopyFilesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
dstPath = "";
|
||||||
|
dstSubfolderSpec = 13;
|
||||||
|
files = (
|
||||||
|
3127F79E28EAEDE300C2EFB3 /* livecard.appex in Embed Foundation Extensions */,
|
||||||
|
);
|
||||||
|
name = "Embed Foundation Extensions";
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
|
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
|
||||||
isa = PBXCopyFilesBuildPhase;
|
isa = PBXCopyFilesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
@@ -33,6 +61,16 @@
|
|||||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
||||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
||||||
1F0ADD56276103500A3016C8 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
1F0ADD56276103500A3016C8 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
3127F73928EAEC3200C2EFB3 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
|
||||||
|
3127F73F28EAEC8A00C2EFB3 /* IntentsUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IntentsUI.framework; path = System/Library/Frameworks/IntentsUI.framework; sourceTree = SDKROOT; };
|
||||||
|
3127F75528EAECC800C2EFB3 /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; };
|
||||||
|
3127F75728EAECC800C2EFB3 /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; };
|
||||||
|
3127F78C28EAEDE200C2EFB3 /* livecard.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = livecard.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
3127F79728EAEDE300C2EFB3 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
|
3127F79928EAEDE300C2EFB3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
3127F7A328EAEE3D00C2EFB3 /* livecard.intentdefinition */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.intentdefinition; path = livecard.intentdefinition; sourceTree = "<group>"; };
|
||||||
|
3127F7A528EAEE5900C2EFB3 /* livecard.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = livecard.swift; sourceTree = "<group>"; tabWidth = 2; };
|
||||||
|
3127F7A728EAEE8500C2EFB3 /* lesson_model.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = lesson_model.swift; sourceTree = "<group>"; };
|
||||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
||||||
707F8089D970F81C480F73C4 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
707F8089D970F81C480F73C4 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
||||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||||
@@ -50,6 +88,15 @@
|
|||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
3127F78928EAEDE200C2EFB3 /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
3127F78E28EAEDE200C2EFB3 /* SwiftUI.framework in Frameworks */,
|
||||||
|
3127F78D28EAEDE200C2EFB3 /* WidgetKit.framework in Frameworks */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
97C146EB1CF9000F007C117D /* Frameworks */ = {
|
97C146EB1CF9000F007C117D /* Frameworks */ = {
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
@@ -61,10 +108,25 @@
|
|||||||
/* End PBXFrameworksBuildPhase section */
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
/* Begin PBXGroup section */
|
||||||
|
3127F78F28EAEDE200C2EFB3 /* livecard */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
3127F7A728EAEE8500C2EFB3 /* lesson_model.swift */,
|
||||||
|
3127F7A328EAEE3D00C2EFB3 /* livecard.intentdefinition */,
|
||||||
|
3127F79728EAEDE300C2EFB3 /* Assets.xcassets */,
|
||||||
|
3127F79928EAEDE300C2EFB3 /* Info.plist */,
|
||||||
|
3127F7A528EAEE5900C2EFB3 /* livecard.swift */,
|
||||||
|
);
|
||||||
|
path = livecard;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
6640A963014A9D4F31026053 /* Frameworks */ = {
|
6640A963014A9D4F31026053 /* Frameworks */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
1F0ADD56276103500A3016C8 /* Pods_Runner.framework */,
|
1F0ADD56276103500A3016C8 /* Pods_Runner.framework */,
|
||||||
|
3127F73F28EAEC8A00C2EFB3 /* IntentsUI.framework */,
|
||||||
|
3127F75528EAECC800C2EFB3 /* WidgetKit.framework */,
|
||||||
|
3127F75728EAECC800C2EFB3 /* SwiftUI.framework */,
|
||||||
);
|
);
|
||||||
name = Frameworks;
|
name = Frameworks;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -76,7 +138,6 @@
|
|||||||
98578F0EBCC6D3FF8391AAEB /* Pods-Runner.release.xcconfig */,
|
98578F0EBCC6D3FF8391AAEB /* Pods-Runner.release.xcconfig */,
|
||||||
707F8089D970F81C480F73C4 /* Pods-Runner.profile.xcconfig */,
|
707F8089D970F81C480F73C4 /* Pods-Runner.profile.xcconfig */,
|
||||||
);
|
);
|
||||||
name = Pods;
|
|
||||||
path = Pods;
|
path = Pods;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
@@ -96,6 +157,7 @@
|
|||||||
children = (
|
children = (
|
||||||
9740EEB11CF90186004384FC /* Flutter */,
|
9740EEB11CF90186004384FC /* Flutter */,
|
||||||
97C146F01CF9000F007C117D /* Runner */,
|
97C146F01CF9000F007C117D /* Runner */,
|
||||||
|
3127F78F28EAEDE200C2EFB3 /* livecard */,
|
||||||
97C146EF1CF9000F007C117D /* Products */,
|
97C146EF1CF9000F007C117D /* Products */,
|
||||||
91FEB6212755D596FFFFEC73 /* Pods */,
|
91FEB6212755D596FFFFEC73 /* Pods */,
|
||||||
6640A963014A9D4F31026053 /* Frameworks */,
|
6640A963014A9D4F31026053 /* Frameworks */,
|
||||||
@@ -106,6 +168,7 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
97C146EE1CF9000F007C117D /* Runner.app */,
|
97C146EE1CF9000F007C117D /* Runner.app */,
|
||||||
|
3127F78C28EAEDE200C2EFB3 /* livecard.appex */,
|
||||||
);
|
);
|
||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -113,6 +176,7 @@
|
|||||||
97C146F01CF9000F007C117D /* Runner */ = {
|
97C146F01CF9000F007C117D /* Runner */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
3127F73928EAEC3200C2EFB3 /* Runner.entitlements */,
|
||||||
97C146FA1CF9000F007C117D /* Main.storyboard */,
|
97C146FA1CF9000F007C117D /* Main.storyboard */,
|
||||||
97C146FD1CF9000F007C117D /* Assets.xcassets */,
|
97C146FD1CF9000F007C117D /* Assets.xcassets */,
|
||||||
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
|
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
|
||||||
@@ -128,6 +192,23 @@
|
|||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
|
3127F78B28EAEDE200C2EFB3 /* livecard */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = 3127F79F28EAEDE300C2EFB3 /* Build configuration list for PBXNativeTarget "livecard" */;
|
||||||
|
buildPhases = (
|
||||||
|
3127F78828EAEDE200C2EFB3 /* Sources */,
|
||||||
|
3127F78928EAEDE200C2EFB3 /* Frameworks */,
|
||||||
|
3127F78A28EAEDE200C2EFB3 /* Resources */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
);
|
||||||
|
name = livecard;
|
||||||
|
productName = livecardExtension;
|
||||||
|
productReference = 3127F78C28EAEDE200C2EFB3 /* livecard.appex */;
|
||||||
|
productType = "com.apple.product-type.app-extension";
|
||||||
|
};
|
||||||
97C146ED1CF9000F007C117D /* Runner */ = {
|
97C146ED1CF9000F007C117D /* Runner */ = {
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||||
@@ -140,10 +221,12 @@
|
|||||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||||
71459C0EB905E05018E3D78F /* [CP] Embed Pods Frameworks */,
|
71459C0EB905E05018E3D78F /* [CP] Embed Pods Frameworks */,
|
||||||
|
3127F74F28EAEC8A00C2EFB3 /* Embed Foundation Extensions */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
dependencies = (
|
dependencies = (
|
||||||
|
3127F79D28EAEDE300C2EFB3 /* PBXTargetDependency */,
|
||||||
);
|
);
|
||||||
name = Runner;
|
name = Runner;
|
||||||
productName = Runner;
|
productName = Runner;
|
||||||
@@ -156,9 +239,13 @@
|
|||||||
97C146E61CF9000F007C117D /* Project object */ = {
|
97C146E61CF9000F007C117D /* Project object */ = {
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
LastUpgradeCheck = 1020;
|
LastSwiftUpdateCheck = 1410;
|
||||||
|
LastUpgradeCheck = 1300;
|
||||||
ORGANIZATIONNAME = "";
|
ORGANIZATIONNAME = "";
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
|
3127F78B28EAEDE200C2EFB3 = {
|
||||||
|
CreatedOnToolsVersion = 14.1;
|
||||||
|
};
|
||||||
97C146ED1CF9000F007C117D = {
|
97C146ED1CF9000F007C117D = {
|
||||||
CreatedOnToolsVersion = 7.3.1;
|
CreatedOnToolsVersion = 7.3.1;
|
||||||
LastSwiftMigration = 1100;
|
LastSwiftMigration = 1100;
|
||||||
@@ -179,11 +266,20 @@
|
|||||||
projectRoot = "";
|
projectRoot = "";
|
||||||
targets = (
|
targets = (
|
||||||
97C146ED1CF9000F007C117D /* Runner */,
|
97C146ED1CF9000F007C117D /* Runner */,
|
||||||
|
3127F78B28EAEDE200C2EFB3 /* livecard */,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
/* End PBXProject section */
|
/* End PBXProject section */
|
||||||
|
|
||||||
/* Begin PBXResourcesBuildPhase section */
|
/* Begin PBXResourcesBuildPhase section */
|
||||||
|
3127F78A28EAEDE200C2EFB3 /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
3127F79828EAEDE300C2EFB3 /* Assets.xcassets in Resources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
97C146EC1CF9000F007C117D /* Resources */ = {
|
97C146EC1CF9000F007C117D /* Resources */ = {
|
||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
@@ -268,6 +364,16 @@
|
|||||||
/* End PBXShellScriptBuildPhase section */
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
|
3127F78828EAEDE200C2EFB3 /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
3127F7A828EAEE8500C2EFB3 /* lesson_model.swift in Sources */,
|
||||||
|
3127F7A428EAEE3D00C2EFB3 /* livecard.intentdefinition in Sources */,
|
||||||
|
3127F7A628EAEE5900C2EFB3 /* livecard.swift in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
97C146EA1CF9000F007C117D /* Sources */ = {
|
97C146EA1CF9000F007C117D /* Sources */ = {
|
||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
@@ -279,6 +385,14 @@
|
|||||||
};
|
};
|
||||||
/* End PBXSourcesBuildPhase section */
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXTargetDependency section */
|
||||||
|
3127F79D28EAEDE300C2EFB3 /* PBXTargetDependency */ = {
|
||||||
|
isa = PBXTargetDependency;
|
||||||
|
target = 3127F78B28EAEDE200C2EFB3 /* livecard */;
|
||||||
|
targetProxy = 3127F79C28EAEDE300C2EFB3 /* PBXContainerItemProxy */;
|
||||||
|
};
|
||||||
|
/* End PBXTargetDependency section */
|
||||||
|
|
||||||
/* Begin PBXVariantGroup section */
|
/* Begin PBXVariantGroup section */
|
||||||
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
|
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
|
||||||
isa = PBXVariantGroup;
|
isa = PBXVariantGroup;
|
||||||
@@ -322,6 +436,7 @@
|
|||||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
@@ -340,7 +455,7 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SUPPORTED_PLATFORMS = iphoneos;
|
SUPPORTED_PLATFORMS = iphoneos;
|
||||||
@@ -353,12 +468,18 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
|
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
|
DEVELOPMENT_TEAM = MYUTW2GF6J;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = hu.filc.naplo;
|
PRODUCT_BUNDLE_IDENTIFIER = hu.filc.naplo;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
@@ -367,6 +488,125 @@
|
|||||||
};
|
};
|
||||||
name = Profile;
|
name = Profile;
|
||||||
};
|
};
|
||||||
|
3127F7A028EAEDE300C2EFB3 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
|
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||||
|
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEVELOPMENT_TEAM = MYUTW2GF6J;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = livecard/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = livecard;
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
|
INFOPLIST_KEY_NSSupportsLiveActivities = YES;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 16.1;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@executable_path/../../Frameworks",
|
||||||
|
);
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||||
|
MTL_FAST_MATH = YES;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = hu.filc.naplo.livecardpro;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
3127F7A128EAEDE300C2EFB3 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
|
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||||
|
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEVELOPMENT_TEAM = MYUTW2GF6J;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = livecard/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = livecard;
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
|
INFOPLIST_KEY_NSSupportsLiveActivities = YES;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 16.1;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@executable_path/../../Frameworks",
|
||||||
|
);
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
MTL_FAST_MATH = YES;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = hu.filc.naplo.livecardpro;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
3127F7A228EAEDE300C2EFB3 /* Profile */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
|
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||||
|
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEVELOPMENT_TEAM = MYUTW2GF6J;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = livecard/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = livecard;
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
|
INFOPLIST_KEY_NSSupportsLiveActivities = YES;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 16.1;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@executable_path/../../Frameworks",
|
||||||
|
);
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
MTL_FAST_MATH = YES;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = hu.filc.naplo.livecardpro;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Profile;
|
||||||
|
};
|
||||||
97C147031CF9000F007C117D /* Debug */ = {
|
97C147031CF9000F007C117D /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
@@ -390,6 +630,7 @@
|
|||||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
@@ -414,7 +655,7 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = YES;
|
MTL_ENABLE_DEBUG_INFO = YES;
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
@@ -445,6 +686,7 @@
|
|||||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
@@ -463,10 +705,11 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SUPPORTED_PLATFORMS = iphoneos;
|
SUPPORTED_PLATFORMS = iphoneos;
|
||||||
|
SWIFT_COMPILATION_MODE = wholemodule;
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
VALIDATE_PRODUCT = YES;
|
VALIDATE_PRODUCT = YES;
|
||||||
@@ -477,12 +720,18 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
|
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
|
DEVELOPMENT_TEAM = MYUTW2GF6J;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = hu.filc.naplo;
|
PRODUCT_BUNDLE_IDENTIFIER = hu.filc.naplo;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
@@ -496,12 +745,18 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
|
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
|
DEVELOPMENT_TEAM = MYUTW2GF6J;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = hu.filc.naplo;
|
PRODUCT_BUNDLE_IDENTIFIER = hu.filc.naplo;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
@@ -513,6 +768,16 @@
|
|||||||
/* End XCBuildConfiguration section */
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
/* Begin XCConfigurationList section */
|
/* Begin XCConfigurationList section */
|
||||||
|
3127F79F28EAEDE300C2EFB3 /* Build configuration list for PBXNativeTarget "livecard" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
3127F7A028EAEDE300C2EFB3 /* Debug */,
|
||||||
|
3127F7A128EAEDE300C2EFB3 /* Release */,
|
||||||
|
3127F7A228EAEDE300C2EFB3 /* Profile */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
|
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Scheme
|
<Scheme
|
||||||
LastUpgradeVersion = "1020"
|
LastUpgradeVersion = "1300"
|
||||||
version = "1.3">
|
version = "1.3">
|
||||||
<BuildAction
|
<BuildAction
|
||||||
parallelizeBuildables = "YES"
|
parallelizeBuildables = "YES"
|
||||||
@@ -27,8 +27,6 @@
|
|||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
<Testables>
|
|
||||||
</Testables>
|
|
||||||
<MacroExpansion>
|
<MacroExpansion>
|
||||||
<BuildableReference
|
<BuildableReference
|
||||||
BuildableIdentifier = "primary"
|
BuildableIdentifier = "primary"
|
||||||
@@ -38,8 +36,8 @@
|
|||||||
ReferencedContainer = "container:Runner.xcodeproj">
|
ReferencedContainer = "container:Runner.xcodeproj">
|
||||||
</BuildableReference>
|
</BuildableReference>
|
||||||
</MacroExpansion>
|
</MacroExpansion>
|
||||||
<AdditionalOptions>
|
<Testables>
|
||||||
</AdditionalOptions>
|
</Testables>
|
||||||
</TestAction>
|
</TestAction>
|
||||||
<LaunchAction
|
<LaunchAction
|
||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
@@ -61,8 +59,6 @@
|
|||||||
ReferencedContainer = "container:Runner.xcodeproj">
|
ReferencedContainer = "container:Runner.xcodeproj">
|
||||||
</BuildableReference>
|
</BuildableReference>
|
||||||
</BuildableProductRunnable>
|
</BuildableProductRunnable>
|
||||||
<AdditionalOptions>
|
|
||||||
</AdditionalOptions>
|
|
||||||
</LaunchAction>
|
</LaunchAction>
|
||||||
<ProfileAction
|
<ProfileAction
|
||||||
buildConfiguration = "Profile"
|
buildConfiguration = "Profile"
|
||||||
|
|||||||
@@ -8,6 +8,18 @@ import Flutter
|
|||||||
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
||||||
) -> Bool {
|
) -> Bool {
|
||||||
GeneratedPluginRegistrant.register(with: self)
|
GeneratedPluginRegistrant.register(with: self)
|
||||||
|
|
||||||
|
// here, Without this code the task will not work.
|
||||||
|
//SwiftFlutterForegroundTaskPlugin.setPluginRegistrantCallback(registerPlugins)
|
||||||
|
if #available(iOS 10.0, *) {
|
||||||
|
UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
|
||||||
|
}
|
||||||
|
|
||||||
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// here
|
||||||
|
func registerPlugins(registry: FlutterPluginRegistry) {
|
||||||
|
GeneratedPluginRegistrant.register(with: registry)
|
||||||
|
}
|
||||||
|
|||||||
@@ -22,6 +22,8 @@
|
|||||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
<true/>
|
<true/>
|
||||||
|
<key>NSSupportsLiveActivities</key>
|
||||||
|
<true/>
|
||||||
<key>UILaunchStoryboardName</key>
|
<key>UILaunchStoryboardName</key>
|
||||||
<string>LaunchScreen</string>
|
<string>LaunchScreen</string>
|
||||||
<key>UIMainStoryboardFile</key>
|
<key>UIMainStoryboardFile</key>
|
||||||
@@ -52,5 +54,7 @@
|
|||||||
<string>The app requires the photo library to set a custom profile picture.</string>
|
<string>The app requires the photo library to set a custom profile picture.</string>
|
||||||
<key>ITSAppUsesNonExemptEncryption</key>
|
<key>ITSAppUsesNonExemptEncryption</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
@@ -1,8 +1,12 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>aps-environment</key>
|
<key>aps-environment</key>
|
||||||
<string>production</string>
|
<string>development</string>
|
||||||
</dict>
|
<key>com.apple.developer.associated-domains</key>
|
||||||
|
<array>
|
||||||
|
<string>applinks:api.filcnaplo.hu</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"colors" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"size" : "1024x1024"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
6
filcnaplo/ios/livecard/Assets.xcassets/Contents.json
Normal file
6
filcnaplo/ios/livecard/Assets.xcassets/Contents.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"colors" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
11
filcnaplo/ios/livecard/Info.plist
Normal file
11
filcnaplo/ios/livecard/Info.plist
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>NSExtension</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSExtensionPointIdentifier</key>
|
||||||
|
<string>com.apple.widgetkit-extension</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
27
filcnaplo/ios/livecard/lesson_model.swift
Normal file
27
filcnaplo/ios/livecard/lesson_model.swift
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import Foundation
|
||||||
|
|
||||||
|
class LessonData {
|
||||||
|
var icon: String
|
||||||
|
var index: String
|
||||||
|
var title: String
|
||||||
|
var subtitle: String
|
||||||
|
var description: String
|
||||||
|
var startDate: Date
|
||||||
|
var endDate: Date
|
||||||
|
var date: ClosedRange<Date>
|
||||||
|
var nextSubject: String
|
||||||
|
var nextRoom: String
|
||||||
|
|
||||||
|
init?(JSONData data:[String: String]) {
|
||||||
|
self.icon = data["icon"]!
|
||||||
|
self.index = data["index"]!
|
||||||
|
self.title = data["title"]!
|
||||||
|
self.subtitle = data["subtitle"]!
|
||||||
|
self.description = data["description"]!
|
||||||
|
self.startDate = Date(timeIntervalSince1970: Double(data["startDate"]!)! / 1000)
|
||||||
|
self.endDate = Date(timeIntervalSince1970: Double(data["endDate"]!)! / 1000)
|
||||||
|
date = self.startDate...self.endDate
|
||||||
|
self.nextSubject = data["nextSubject"]!
|
||||||
|
self.nextRoom = data["nextRoom"]!
|
||||||
|
}
|
||||||
|
}
|
||||||
59
filcnaplo/ios/livecard/livecard.intentdefinition
Normal file
59
filcnaplo/ios/livecard/livecard.intentdefinition
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>INEnums</key>
|
||||||
|
<array/>
|
||||||
|
<key>INIntentDefinitionModelVersion</key>
|
||||||
|
<string>1.2</string>
|
||||||
|
<key>INIntentDefinitionNamespace</key>
|
||||||
|
<string>88xZPY</string>
|
||||||
|
<key>INIntentDefinitionSystemVersion</key>
|
||||||
|
<string>20A294</string>
|
||||||
|
<key>INIntentDefinitionToolsBuildVersion</key>
|
||||||
|
<string>12A6144</string>
|
||||||
|
<key>INIntentDefinitionToolsVersion</key>
|
||||||
|
<string>12.0</string>
|
||||||
|
<key>INIntents</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>INIntentCategory</key>
|
||||||
|
<string>information</string>
|
||||||
|
<key>INIntentDescriptionID</key>
|
||||||
|
<string>tVvJ9c</string>
|
||||||
|
<key>INIntentEligibleForWidgets</key>
|
||||||
|
<true/>
|
||||||
|
<key>INIntentIneligibleForSuggestions</key>
|
||||||
|
<true/>
|
||||||
|
<key>INIntentName</key>
|
||||||
|
<string>Configuration</string>
|
||||||
|
<key>INIntentResponse</key>
|
||||||
|
<dict>
|
||||||
|
<key>INIntentResponseCodes</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>INIntentResponseCodeName</key>
|
||||||
|
<string>success</string>
|
||||||
|
<key>INIntentResponseCodeSuccess</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>INIntentResponseCodeName</key>
|
||||||
|
<string>failure</string>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
<key>INIntentTitle</key>
|
||||||
|
<string>Configuration</string>
|
||||||
|
<key>INIntentTitleID</key>
|
||||||
|
<string>gpCwrM</string>
|
||||||
|
<key>INIntentType</key>
|
||||||
|
<string>Custom</string>
|
||||||
|
<key>INIntentVerb</key>
|
||||||
|
<string>View</string>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
<key>INTypes</key>
|
||||||
|
<array/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
137
filcnaplo/ios/livecard/livecard.swift
Normal file
137
filcnaplo/ios/livecard/livecard.swift
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
import ActivityKit
|
||||||
|
import WidgetKit
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
@main
|
||||||
|
struct Widgets: WidgetBundle {
|
||||||
|
var body: some Widget {
|
||||||
|
if #available(iOS 16.1, *) {
|
||||||
|
LiveCardWidget()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need to redefined live activities pipe
|
||||||
|
struct LiveActivitiesAppAttributes: ActivityAttributes, Identifiable {
|
||||||
|
public typealias LiveDeliveryData = ContentState
|
||||||
|
|
||||||
|
public struct ContentState: Codable, Hashable {
|
||||||
|
var data: Dictionary<String, String>
|
||||||
|
}
|
||||||
|
|
||||||
|
var id = UUID()
|
||||||
|
}
|
||||||
|
|
||||||
|
@available(iOSApplicationExtension 16.1, *)
|
||||||
|
struct LiveCardWidget: Widget {
|
||||||
|
var body: some WidgetConfiguration {
|
||||||
|
/// Live Activity Notification
|
||||||
|
ActivityConfiguration(for: LiveActivitiesAppAttributes.self) { context in
|
||||||
|
let lesson = LessonData(JSONData: context.state.data)
|
||||||
|
|
||||||
|
HStack(alignment: .center) {
|
||||||
|
Image(systemName: lesson!.icon)
|
||||||
|
.resizable()
|
||||||
|
.aspectRatio(contentMode: .fit)
|
||||||
|
.frame(width: CGFloat(30), height: CGFloat(30))
|
||||||
|
.padding(.leading, CGFloat(8))
|
||||||
|
|
||||||
|
VStack(alignment: .leading) {
|
||||||
|
Text(lesson!.index + lesson!.title)
|
||||||
|
.font(.title3)
|
||||||
|
.bold()
|
||||||
|
|
||||||
|
Text(lesson!.description)
|
||||||
|
.font(.subheadline)
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
HStack {
|
||||||
|
Image(systemName: "arrow.right")
|
||||||
|
.resizable()
|
||||||
|
.aspectRatio(contentMode: .fit)
|
||||||
|
.frame(width: CGFloat(12), height: CGFloat(12))
|
||||||
|
Text(lesson!.nextSubject)
|
||||||
|
.font(.caption)
|
||||||
|
Text(lesson!.nextRoom)
|
||||||
|
.font(.caption2)
|
||||||
|
}
|
||||||
|
}.padding(15)
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
Text(lesson!.subtitle)
|
||||||
|
.font(.subheadline)
|
||||||
|
.padding(.trailing, 12)
|
||||||
|
}.padding(12)
|
||||||
|
/// Dynamic Island
|
||||||
|
} dynamicIsland: { context in
|
||||||
|
let lesson = LessonData(JSONData: context.state.data)
|
||||||
|
|
||||||
|
/// Expanded
|
||||||
|
return DynamicIsland {
|
||||||
|
DynamicIslandExpandedRegion(.leading) {
|
||||||
|
VStack {
|
||||||
|
Spacer()
|
||||||
|
Image(systemName: lesson!.icon)
|
||||||
|
.resizable()
|
||||||
|
.aspectRatio(contentMode: .fit)
|
||||||
|
.frame(width: CGFloat(30), height: CGFloat(30))
|
||||||
|
.padding(.leading, CGFloat(6))
|
||||||
|
.padding(.bottom, CGFloat(6))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DynamicIslandExpandedRegion(.center) {
|
||||||
|
VStack(alignment: .leading) {
|
||||||
|
Text(lesson!.index + lesson!.title)
|
||||||
|
.lineLimit(1)
|
||||||
|
.font(.title3)
|
||||||
|
.bold()
|
||||||
|
|
||||||
|
Text(lesson!.description)
|
||||||
|
.lineLimit(2)
|
||||||
|
.font(.caption)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DynamicIslandExpandedRegion(.trailing) {
|
||||||
|
VStack {
|
||||||
|
Spacer()
|
||||||
|
Text(lesson!.subtitle)
|
||||||
|
.lineLimit(1)
|
||||||
|
.font(.subheadline)
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compact
|
||||||
|
} compactLeading: {
|
||||||
|
Label {
|
||||||
|
Text(lesson!.title)
|
||||||
|
} icon: {
|
||||||
|
Image(systemName: lesson!.icon)
|
||||||
|
}
|
||||||
|
.font(.caption2)
|
||||||
|
} compactTrailing: {
|
||||||
|
Text(timerInterval: lesson!.date, countsDown: true)
|
||||||
|
.multilineTextAlignment(.center)
|
||||||
|
.frame(width: 40)
|
||||||
|
.font(.caption2)
|
||||||
|
|
||||||
|
/// Collapsed
|
||||||
|
} minimal: {
|
||||||
|
VStack(alignment: .center) {
|
||||||
|
Image(systemName: lesson!.icon)
|
||||||
|
.resizable()
|
||||||
|
.aspectRatio(contentMode: .fit)
|
||||||
|
.frame(width: CGFloat(12), height: CGFloat(12))
|
||||||
|
|
||||||
|
Text(timerInterval: lesson!.date, countsDown: true)
|
||||||
|
.multilineTextAlignment(.center)
|
||||||
|
.monospacedDigit()
|
||||||
|
.font(.system(size: CGFloat(10)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.keylineTint(.accentColor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,6 +21,8 @@ class FilcAPI {
|
|||||||
// Private API
|
// Private API
|
||||||
static const config = "https://api.filcnaplo.hu/config";
|
static const config = "https://api.filcnaplo.hu/config";
|
||||||
static const reportApi = "https://api.filcnaplo.hu/report";
|
static const reportApi = "https://api.filcnaplo.hu/report";
|
||||||
|
static const premiumApi = "https://api.filcnaplo.hu/premium/activate";
|
||||||
|
static const premiumScopesApi = "https://api.filcnaplo.hu/premium/scopes";
|
||||||
|
|
||||||
// Updates
|
// Updates
|
||||||
static const repo = "filc/naplo";
|
static const repo = "filc/naplo";
|
||||||
@@ -121,18 +123,15 @@ class FilcAPI {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<http.StreamedResponse?> downloadRelease(Release release) {
|
static Future<http.StreamedResponse?> downloadRelease(ReleaseDownload release) {
|
||||||
if (release.downloads.isNotEmpty) {
|
try {
|
||||||
try {
|
var client = http.Client();
|
||||||
var client = http.Client();
|
var request = http.Request('GET', Uri.parse(release.url));
|
||||||
var request = http.Request('GET', Uri.parse(release.downloads.first));
|
return client.send(request);
|
||||||
return client.send(request);
|
} catch (error) {
|
||||||
} catch (error) {
|
print("ERROR: FilcAPI.downloadRelease: $error");
|
||||||
print("ERROR: FilcAPI.downloadRelease: $error");
|
return Future.value(null);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Future.value(null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<void> sendReport(ErrorReport report) async {
|
static Future<void> sendReport(ErrorReport report) async {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// ignore_for_file: avoid_print
|
// ignore_for_file: avoid_print, use_build_context_synchronously
|
||||||
|
|
||||||
import 'package:filcnaplo/utils/jwt.dart';
|
import 'package:filcnaplo/utils/jwt.dart';
|
||||||
import 'package:filcnaplo_kreta_api/providers/absence_provider.dart';
|
import 'package:filcnaplo_kreta_api/providers/absence_provider.dart';
|
||||||
@@ -23,9 +23,9 @@ import 'package:filcnaplo/api/nonce.dart';
|
|||||||
|
|
||||||
enum LoginState { missingFields, invalidGrant, failed, normal, inProgress, success }
|
enum LoginState { missingFields, invalidGrant, failed, normal, inProgress, success }
|
||||||
|
|
||||||
Nonce getNonce(BuildContext context, String nonce, String username, String instituteCode) {
|
Nonce getNonce(String nonce, String username, String instituteCode) {
|
||||||
Nonce nonceEncoder = Nonce(key: [53, 75, 109, 112, 109, 103, 100, 53, 102, 74], nonce: nonce);
|
Nonce nonceEncoder = Nonce(key: [98, 97, 83, 115, 120, 79, 119, 108, 85, 49, 106, 77], nonce: nonce);
|
||||||
nonceEncoder.encode(username.toLowerCase() + instituteCode.toLowerCase() + nonce);
|
nonceEncoder.encode(instituteCode.toUpperCase() + nonce + username.toUpperCase());
|
||||||
|
|
||||||
return nonceEncoder;
|
return nonceEncoder;
|
||||||
}
|
}
|
||||||
@@ -46,7 +46,7 @@ Future loginApi({
|
|||||||
|
|
||||||
String nonceStr = await Provider.of<KretaClient>(context, listen: false).getAPI(KretaAPI.nonce, json: false);
|
String nonceStr = await Provider.of<KretaClient>(context, listen: false).getAPI(KretaAPI.nonce, json: false);
|
||||||
|
|
||||||
Nonce nonce = getNonce(context, nonceStr, username, instituteCode);
|
Nonce nonce = getNonce(nonceStr, username, instituteCode);
|
||||||
headers.addAll(nonce.header());
|
headers.addAll(nonce.header());
|
||||||
|
|
||||||
Map? res = await Provider.of<KretaClient>(context, listen: false).postAPI(KretaAPI.login,
|
Map? res = await Provider.of<KretaClient>(context, listen: false).postAPI(KretaAPI.login,
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ class Nonce {
|
|||||||
return {
|
return {
|
||||||
"X-Authorizationpolicy-Nonce": nonce,
|
"X-Authorizationpolicy-Nonce": nonce,
|
||||||
"X-Authorizationpolicy-Key": encoded ?? "",
|
"X-Authorizationpolicy-Key": encoded ?? "",
|
||||||
"X-Authorizationpolicy-Version": "v1",
|
"X-Authorizationpolicy-Version": "v2",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import 'dart:io';
|
|||||||
import 'package:filcnaplo/database/query.dart';
|
import 'package:filcnaplo/database/query.dart';
|
||||||
import 'package:filcnaplo/database/store.dart';
|
import 'package:filcnaplo/database/store.dart';
|
||||||
import 'package:sqflite/sqflite.dart';
|
import 'package:sqflite/sqflite.dart';
|
||||||
|
// ignore: depend_on_referenced_packages
|
||||||
import 'package:sqflite_common_ffi/sqflite_ffi.dart';
|
import 'package:sqflite_common_ffi/sqflite_ffi.dart';
|
||||||
|
|
||||||
class DatabaseProvider {
|
class DatabaseProvider {
|
||||||
|
|||||||
199
filcnaplo/lib/api/providers/live_card_provider.dart
Normal file
199
filcnaplo/lib/api/providers/live_card_provider.dart
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
// ignore_for_file: no_leading_underscores_for_local_identifiers
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:filcnaplo/helpers/subject.dart';
|
||||||
|
import 'package:filcnaplo/models/settings.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/lesson.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/week.dart';
|
||||||
|
import 'package:filcnaplo/utils/format.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/providers/timetable_provider.dart';
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:live_activities/live_activities.dart';
|
||||||
|
|
||||||
|
enum LiveCardState { empty, duringLesson, duringBreak, morning, afternoon, night }
|
||||||
|
|
||||||
|
class LiveCardProvider extends ChangeNotifier {
|
||||||
|
Lesson? currentLesson;
|
||||||
|
Lesson? nextLesson;
|
||||||
|
Lesson? prevLesson;
|
||||||
|
List<Lesson>? nextLessons;
|
||||||
|
|
||||||
|
LiveCardState currentState = LiveCardState.empty;
|
||||||
|
late Timer _timer;
|
||||||
|
late final TimetableProvider _timetable;
|
||||||
|
late final SettingsProvider _settings;
|
||||||
|
|
||||||
|
late Duration _delay;
|
||||||
|
|
||||||
|
final _liveActivitiesPlugin = LiveActivities();
|
||||||
|
String? _latestActivityId;
|
||||||
|
Map<String, String> _lastActivity = {};
|
||||||
|
|
||||||
|
LiveCardProvider({
|
||||||
|
required TimetableProvider timetable,
|
||||||
|
required SettingsProvider settings,
|
||||||
|
}) : _timetable = timetable,
|
||||||
|
_settings = settings {
|
||||||
|
_timer = Timer.periodic(const Duration(seconds: 1), (timer) => update());
|
||||||
|
timetable.restore().then((_) => update());
|
||||||
|
_delay = settings.bellDelayEnabled ? Duration(seconds: settings.bellDelay) : Duration.zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_timer.cancel();
|
||||||
|
if (_latestActivityId != null && Platform.isIOS) _liveActivitiesPlugin.endActivity(_latestActivityId!);
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debugging
|
||||||
|
static DateTime _now() {
|
||||||
|
return DateTime.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
String getFloorDifference() {
|
||||||
|
final prevFloor = prevLesson!.getFloor();
|
||||||
|
final nextFloor = nextLesson!.getFloor();
|
||||||
|
if (prevFloor == null || nextFloor == null || prevFloor == nextFloor) {
|
||||||
|
return "to room";
|
||||||
|
}
|
||||||
|
if (nextFloor == 0) {
|
||||||
|
return "ground floor";
|
||||||
|
}
|
||||||
|
if (nextFloor > prevFloor) {
|
||||||
|
return "up floor";
|
||||||
|
} else {
|
||||||
|
return "down floor";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, String> toMap() {
|
||||||
|
switch (currentState) {
|
||||||
|
case LiveCardState.duringLesson:
|
||||||
|
return {
|
||||||
|
"icon": currentLesson != null ? SubjectIcon.resolveName(subject: currentLesson?.subject) : "book",
|
||||||
|
"index": currentLesson != null ? '${currentLesson!.lessonIndex}. ' : "",
|
||||||
|
"title": currentLesson != null ? ShortSubject.resolve(subject: currentLesson?.subject).capital() : "",
|
||||||
|
"subtitle": currentLesson?.room.replaceAll("_", " ") ?? "",
|
||||||
|
"description": currentLesson?.description ?? "",
|
||||||
|
"startDate": ((currentLesson?.start.millisecondsSinceEpoch ?? 0) - _delay.inMilliseconds).toString(),
|
||||||
|
"endDate": ((currentLesson?.end.millisecondsSinceEpoch ?? 0) - _delay.inMilliseconds).toString(),
|
||||||
|
"nextSubject": nextLesson != null ? ShortSubject.resolve(subject: nextLesson?.subject).capital() : "",
|
||||||
|
"nextRoom": nextLesson?.room.replaceAll("_", " ") ?? "",
|
||||||
|
};
|
||||||
|
case LiveCardState.duringBreak:
|
||||||
|
final iconFloorMap = {
|
||||||
|
"to room": "chevron.right.2",
|
||||||
|
"up floor": "arrow.up.right",
|
||||||
|
"down floor": "arrow.down.left",
|
||||||
|
"ground floor": "arrow.down.left",
|
||||||
|
};
|
||||||
|
|
||||||
|
final diff = getFloorDifference();
|
||||||
|
|
||||||
|
return {
|
||||||
|
"icon": iconFloorMap[diff] ?? "cup.and.saucer",
|
||||||
|
"title": "Szünet",
|
||||||
|
"description": "Maradj ebben a teremben.",
|
||||||
|
"startDate": ((prevLesson?.end.millisecondsSinceEpoch ?? 0) - _delay.inMilliseconds).toString(),
|
||||||
|
"endDate": ((nextLesson?.start.millisecondsSinceEpoch ?? 0) - _delay.inMilliseconds).toString(),
|
||||||
|
"nextSubject": nextLesson != null ? ShortSubject.resolve(subject: nextLesson?.subject) : "",
|
||||||
|
"nextRoom": nextLesson?.room.replaceAll("_", " ") ?? "",
|
||||||
|
"index": "",
|
||||||
|
"subtitle": "",
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void update() async {
|
||||||
|
if (Platform.isIOS) {
|
||||||
|
final cmap = toMap();
|
||||||
|
if (cmap != _lastActivity) {
|
||||||
|
_lastActivity = cmap;
|
||||||
|
|
||||||
|
if (_lastActivity != {}) {
|
||||||
|
if (_latestActivityId == null) {
|
||||||
|
_liveActivitiesPlugin.createActivity(_lastActivity).then((value) => _latestActivityId = value);
|
||||||
|
} else {
|
||||||
|
_liveActivitiesPlugin.updateActivity(_latestActivityId!, _lastActivity);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (_latestActivityId != null) _liveActivitiesPlugin.endActivity(_latestActivityId!);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Lesson> today = _today(_timetable);
|
||||||
|
|
||||||
|
if (today.isEmpty) {
|
||||||
|
await _timetable.fetch(week: Week.current());
|
||||||
|
today = _today(_timetable);
|
||||||
|
}
|
||||||
|
|
||||||
|
_delay = _settings.bellDelayEnabled ? Duration(seconds: _settings.bellDelay) : Duration.zero;
|
||||||
|
|
||||||
|
final now = _now().add(_delay);
|
||||||
|
|
||||||
|
// Filter cancelled lessons #20
|
||||||
|
// Filter label lessons #128
|
||||||
|
today = today.where((lesson) => lesson.status?.name != "Elmaradt" && lesson.subject.id != '' && !lesson.isEmpty).toList();
|
||||||
|
|
||||||
|
if (today.isNotEmpty) {
|
||||||
|
// sort
|
||||||
|
today.sort((a, b) => a.start.compareTo(b.start));
|
||||||
|
|
||||||
|
final _lesson = today.firstWhere((l) => l.start.isBefore(now) && l.end.isAfter(now), orElse: () => Lesson.fromJson({}));
|
||||||
|
|
||||||
|
if (_lesson.start.year != 0) {
|
||||||
|
currentLesson = _lesson;
|
||||||
|
} else {
|
||||||
|
currentLesson = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final _next = today.firstWhere((l) => l.start.isAfter(now), orElse: () => Lesson.fromJson({}));
|
||||||
|
nextLessons = today.where((l) => l.start.isAfter(now)).toList();
|
||||||
|
|
||||||
|
if (_next.start.year != 0) {
|
||||||
|
nextLesson = _next;
|
||||||
|
} else {
|
||||||
|
nextLesson = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final _prev = today.lastWhere((l) => l.end.isBefore(now), orElse: () => Lesson.fromJson({}));
|
||||||
|
|
||||||
|
if (_prev.start.year != 0) {
|
||||||
|
prevLesson = _prev;
|
||||||
|
} else {
|
||||||
|
prevLesson = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentLesson != null) {
|
||||||
|
currentState = LiveCardState.duringLesson;
|
||||||
|
} else if (nextLesson != null && prevLesson != null) {
|
||||||
|
currentState = LiveCardState.duringBreak;
|
||||||
|
} else if (now.hour >= 12 && now.hour < 20) {
|
||||||
|
currentState = LiveCardState.afternoon;
|
||||||
|
} else if (now.hour >= 20) {
|
||||||
|
currentState = LiveCardState.night;
|
||||||
|
} else if (now.hour >= 5 && now.hour <= 10) {
|
||||||
|
currentState = LiveCardState.morning;
|
||||||
|
} else {
|
||||||
|
currentState = LiveCardState.empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get show => currentState != LiveCardState.empty;
|
||||||
|
|
||||||
|
Duration get delay => _delay;
|
||||||
|
|
||||||
|
bool _sameDate(DateTime a, DateTime b) => (a.year == b.year && a.month == b.month && a.day == b.day);
|
||||||
|
|
||||||
|
List<Lesson> _today(TimetableProvider p) => p.lessons.where((l) => _sameDate(l.date, _now())).toList();
|
||||||
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
// ignore_for_file: use_build_context_synchronously
|
||||||
|
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:filcnaplo/api/client.dart';
|
import 'package:filcnaplo/api/client.dart';
|
||||||
@@ -39,7 +41,7 @@ class NewsProvider extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_state = state_;
|
_state = state_;
|
||||||
Provider.of<SettingsProvider>(_context, listen: false).update(_context, newsState: _state);
|
Provider.of<SettingsProvider>(_context, listen: false).update(newsState: _state);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> fetch() async {
|
Future<void> fetch() async {
|
||||||
@@ -51,7 +53,7 @@ class NewsProvider extends ChangeNotifier {
|
|||||||
|
|
||||||
if (_fresh < 0) {
|
if (_fresh < 0) {
|
||||||
_state = news_.length;
|
_state = news_.length;
|
||||||
Provider.of<SettingsProvider>(_context, listen: false).update(_context, newsState: _state);
|
Provider.of<SettingsProvider>(_context, listen: false).update(newsState: _state);
|
||||||
}
|
}
|
||||||
|
|
||||||
_fresh = max(_fresh, 0);
|
_fresh = max(_fresh, 0);
|
||||||
@@ -70,7 +72,7 @@ class NewsProvider extends ChangeNotifier {
|
|||||||
_fresh--;
|
_fresh--;
|
||||||
_state++;
|
_state++;
|
||||||
|
|
||||||
Provider.of<SettingsProvider>(_context, listen: false).update(_context, newsState: _state);
|
Provider.of<SettingsProvider>(_context, listen: false).update(newsState: _state);
|
||||||
|
|
||||||
if (_fresh > 0) {
|
if (_fresh > 0) {
|
||||||
show = true;
|
show = true;
|
||||||
|
|||||||
@@ -7,9 +7,12 @@ enum Status { network, maintenance, syncing }
|
|||||||
class StatusProvider extends ChangeNotifier {
|
class StatusProvider extends ChangeNotifier {
|
||||||
final List<Status> _stack = [];
|
final List<Status> _stack = [];
|
||||||
double _progress = 0.0;
|
double _progress = 0.0;
|
||||||
|
ConnectivityResult _networkType = ConnectivityResult.none;
|
||||||
|
ConnectivityResult get networkType => _networkType;
|
||||||
|
|
||||||
StatusProvider() {
|
StatusProvider() {
|
||||||
_handleNetworkChanges();
|
_handleNetworkChanges();
|
||||||
|
Connectivity().checkConnectivity().then((value) => _networkType = value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Status? getStatus() => _stack.isNotEmpty ? _stack[0] : null;
|
Status? getStatus() => _stack.isNotEmpty ? _stack[0] : null;
|
||||||
@@ -18,6 +21,7 @@ class StatusProvider extends ChangeNotifier {
|
|||||||
|
|
||||||
void _handleNetworkChanges() {
|
void _handleNetworkChanges() {
|
||||||
Connectivity().onConnectivityChanged.listen((event) {
|
Connectivity().onConnectivityChanged.listen((event) {
|
||||||
|
_networkType = event;
|
||||||
if (event == ConnectivityResult.none) {
|
if (event == ConnectivityResult.none) {
|
||||||
if (!_stack.contains(Status.network)) {
|
if (!_stack.contains(Status.network)) {
|
||||||
_stack.insert(0, Status.network);
|
_stack.insert(0, Status.network);
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
// ignore_for_file: use_build_context_synchronously
|
||||||
|
|
||||||
import 'package:filcnaplo/api/providers/database_provider.dart';
|
import 'package:filcnaplo/api/providers/database_provider.dart';
|
||||||
import 'package:filcnaplo/api/providers/status_provider.dart';
|
import 'package:filcnaplo/api/providers/status_provider.dart';
|
||||||
import 'package:filcnaplo/api/providers/user_provider.dart';
|
import 'package:filcnaplo/api/providers/user_provider.dart';
|
||||||
@@ -33,24 +35,24 @@ Future<void> syncAll(BuildContext context) {
|
|||||||
List<Future<void>> tasks = [];
|
List<Future<void>> tasks = [];
|
||||||
int taski = 0;
|
int taski = 0;
|
||||||
|
|
||||||
Future<void> _syncStatus(Future<void> future) async {
|
Future<void> syncStatus(Future<void> future) async {
|
||||||
await future.onError((error, stackTrace) => null);
|
await future.onError((error, stackTrace) => null);
|
||||||
taski++;
|
taski++;
|
||||||
statusProvider.triggerSync(current: taski, max: tasks.length);
|
statusProvider.triggerSync(current: taski, max: tasks.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks = [
|
tasks = [
|
||||||
_syncStatus(Provider.of<GradeProvider>(context, listen: false).fetch()),
|
syncStatus(Provider.of<GradeProvider>(context, listen: false).fetch()),
|
||||||
_syncStatus(Provider.of<TimetableProvider>(context, listen: false).fetch(week: Week.current())),
|
syncStatus(Provider.of<TimetableProvider>(context, listen: false).fetch(week: Week.current())),
|
||||||
_syncStatus(Provider.of<ExamProvider>(context, listen: false).fetch()),
|
syncStatus(Provider.of<ExamProvider>(context, listen: false).fetch()),
|
||||||
_syncStatus(Provider.of<HomeworkProvider>(context, listen: false).fetch(from: DateTime.now().subtract(const Duration(days: 30)))),
|
syncStatus(Provider.of<HomeworkProvider>(context, listen: false).fetch(from: DateTime.now().subtract(const Duration(days: 30)))),
|
||||||
_syncStatus(Provider.of<MessageProvider>(context, listen: false).fetchAll()),
|
syncStatus(Provider.of<MessageProvider>(context, listen: false).fetchAll()),
|
||||||
_syncStatus(Provider.of<NoteProvider>(context, listen: false).fetch()),
|
syncStatus(Provider.of<NoteProvider>(context, listen: false).fetch()),
|
||||||
_syncStatus(Provider.of<EventProvider>(context, listen: false).fetch()),
|
syncStatus(Provider.of<EventProvider>(context, listen: false).fetch()),
|
||||||
_syncStatus(Provider.of<AbsenceProvider>(context, listen: false).fetch()),
|
syncStatus(Provider.of<AbsenceProvider>(context, listen: false).fetch()),
|
||||||
|
|
||||||
// Sync student
|
// Sync student
|
||||||
_syncStatus(() async {
|
syncStatus(() async {
|
||||||
if (user.user == null) return;
|
if (user.user == null) return;
|
||||||
Map? studentJson = await Provider.of<KretaClient>(context, listen: false).getAPI(KretaAPI.student(user.instituteCode!));
|
Map? studentJson = await Provider.of<KretaClient>(context, listen: false).getAPI(KretaAPI.student(user.instituteCode!));
|
||||||
if (studentJson == null) return;
|
if (studentJson == null) return;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import 'package:filcnaplo/models/settings.dart';
|
||||||
import 'package:filcnaplo/models/user.dart';
|
import 'package:filcnaplo/models/user.dart';
|
||||||
import 'package:filcnaplo_kreta_api/models/student.dart';
|
import 'package:filcnaplo_kreta_api/models/student.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
@@ -15,16 +16,23 @@ class UserProvider with ChangeNotifier {
|
|||||||
String? get password => user?.password;
|
String? get password => user?.password;
|
||||||
Role? get role => user?.role;
|
Role? get role => user?.role;
|
||||||
Student? get student => user?.student;
|
Student? get student => user?.student;
|
||||||
|
String? get nickname => user?.nickname;
|
||||||
|
String? get displayName => user?.displayName;
|
||||||
|
|
||||||
|
final SettingsProvider _settings;
|
||||||
|
|
||||||
|
UserProvider({required SettingsProvider settings}) : _settings = settings;
|
||||||
|
|
||||||
void setUser(String userId) {
|
void setUser(String userId) {
|
||||||
_selectedUserId = userId;
|
_selectedUserId = userId;
|
||||||
|
_settings.update(lastAccountId: userId);
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
void addUser(User user) {
|
void addUser(User user) {
|
||||||
_users[user.id] = user;
|
_users[user.id] = user;
|
||||||
if (kDebugMode) {
|
if (kDebugMode) {
|
||||||
print("DEBUG: Added User: ${user.id} ${user.name}");
|
print("DEBUG: Added User: ${user.id}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,25 +1,36 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:dynamic_color/dynamic_color.dart';
|
||||||
import 'package:filcnaplo/api/client.dart';
|
import 'package:filcnaplo/api/client.dart';
|
||||||
|
import 'package:filcnaplo/api/providers/live_card_provider.dart';
|
||||||
import 'package:filcnaplo/api/providers/news_provider.dart';
|
import 'package:filcnaplo/api/providers/news_provider.dart';
|
||||||
import 'package:filcnaplo/api/providers/database_provider.dart';
|
import 'package:filcnaplo/api/providers/database_provider.dart';
|
||||||
import 'package:filcnaplo/api/providers/status_provider.dart';
|
import 'package:filcnaplo/api/providers/status_provider.dart';
|
||||||
import 'package:filcnaplo/models/config.dart';
|
import 'package:filcnaplo/models/config.dart';
|
||||||
import 'package:filcnaplo/theme.dart';
|
import 'package:filcnaplo/theme/observer.dart';
|
||||||
|
import 'package:filcnaplo/theme/theme.dart';
|
||||||
import 'package:filcnaplo_kreta_api/client/client.dart';
|
import 'package:filcnaplo_kreta_api/client/client.dart';
|
||||||
import 'package:filcnaplo_mobile_ui/common/system_chrome.dart';
|
|
||||||
import 'package:filcnaplo_mobile_ui/screens/login/login_route.dart';
|
|
||||||
import 'package:filcnaplo_mobile_ui/screens/login/login_screen.dart';
|
|
||||||
import 'package:filcnaplo_mobile_ui/screens/navigation/navigation_screen.dart';
|
|
||||||
import 'package:filcnaplo_mobile_ui/screens/settings/settings_route.dart';
|
|
||||||
import 'package:filcnaplo_mobile_ui/screens/settings/settings_screen.dart';
|
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
import 'package:i18n_extension/i18n_widget.dart';
|
import 'package:i18n_extension/i18n_widget.dart';
|
||||||
|
import 'package:material_color_utilities/palettes/core_palette.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
// Mobile UI
|
||||||
|
import 'package:filcnaplo_mobile_ui/common/system_chrome.dart' as mobile;
|
||||||
|
import 'package:filcnaplo_mobile_ui/screens/login/login_route.dart' as mobile;
|
||||||
|
import 'package:filcnaplo_mobile_ui/screens/login/login_screen.dart' as mobile;
|
||||||
|
import 'package:filcnaplo_mobile_ui/screens/navigation/navigation_screen.dart' as mobile;
|
||||||
|
import 'package:filcnaplo_mobile_ui/screens/settings/settings_route.dart' as mobile;
|
||||||
|
import 'package:filcnaplo_mobile_ui/screens/settings/settings_screen.dart' as mobile;
|
||||||
|
|
||||||
|
// Desktop UI
|
||||||
|
import 'package:filcnaplo_desktop_ui/screens/navigation/navigation_screen.dart' as desktop;
|
||||||
|
import 'package:filcnaplo_desktop_ui/screens/login/login_screen.dart' as desktop;
|
||||||
|
import 'package:filcnaplo_desktop_ui/screens/login/login_route.dart' as desktop;
|
||||||
|
|
||||||
// Providers
|
// Providers
|
||||||
import 'package:filcnaplo/models/settings.dart';
|
import 'package:filcnaplo/models/settings.dart';
|
||||||
import 'package:filcnaplo_kreta_api/providers/absence_provider.dart';
|
import 'package:filcnaplo_kreta_api/providers/absence_provider.dart';
|
||||||
@@ -34,70 +45,85 @@ import 'package:filcnaplo/api/providers/user_provider.dart';
|
|||||||
import 'package:filcnaplo/api/providers/update_provider.dart';
|
import 'package:filcnaplo/api/providers/update_provider.dart';
|
||||||
import 'package:filcnaplo_mobile_ui/pages/grades/calculator/grade_calculator_provider.dart';
|
import 'package:filcnaplo_mobile_ui/pages/grades/calculator/grade_calculator_provider.dart';
|
||||||
import 'package:flutter_displaymode/flutter_displaymode.dart';
|
import 'package:flutter_displaymode/flutter_displaymode.dart';
|
||||||
|
import 'package:filcnaplo_premium/providers/premium_provider.dart';
|
||||||
|
|
||||||
class App extends StatelessWidget {
|
class App extends StatelessWidget {
|
||||||
final SettingsProvider settings;
|
final SettingsProvider settings;
|
||||||
final UserProvider user;
|
final UserProvider user;
|
||||||
final DatabaseProvider database;
|
final DatabaseProvider database;
|
||||||
|
|
||||||
App({Key? key, required this.database, required this.settings, required this.user}) : super(key: key) {
|
const App({Key? key, required this.database, required this.settings, required this.user}) : super(key: key);
|
||||||
if (user.getUsers().isNotEmpty) user.setUser(user.getUsers().first.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
setSystemChrome(context);
|
mobile.setSystemChrome(context);
|
||||||
|
|
||||||
// Set high refresh mode #28
|
// Set high refresh mode #28
|
||||||
if (Platform.isAndroid) FlutterDisplayMode.setHighRefreshRate();
|
if (Platform.isAndroid) FlutterDisplayMode.setHighRefreshRate();
|
||||||
|
|
||||||
WidgetsBinding.instance?.addPostFrameCallback((_) {
|
CorePalette? corePalette;
|
||||||
|
|
||||||
|
final status = StatusProvider();
|
||||||
|
final kreta = KretaClient(user: user, settings: settings, status: status);
|
||||||
|
final timetable = TimetableProvider(user: user, database: database, kreta: kreta);
|
||||||
|
final premium = PremiumProvider(settings: settings);
|
||||||
|
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
FilcAPI.getConfig(settings).then((Config? config) {
|
FilcAPI.getConfig(settings).then((Config? config) {
|
||||||
if (config != null) settings.update(context, database: database, config: config);
|
if (config != null) settings.update(config: config);
|
||||||
});
|
});
|
||||||
|
premium.activate();
|
||||||
});
|
});
|
||||||
|
|
||||||
return I18n(
|
return MultiProvider(
|
||||||
initialLocale: Locale(settings.language, settings.language.toUpperCase()),
|
providers: [
|
||||||
child: MultiProvider(
|
ChangeNotifierProvider<PremiumProvider>(create: (_) => premium),
|
||||||
providers: [
|
ChangeNotifierProvider<SettingsProvider>(create: (_) => settings),
|
||||||
ChangeNotifierProvider<SettingsProvider>(create: (_) => settings),
|
ChangeNotifierProvider<UserProvider>(create: (_) => user),
|
||||||
ChangeNotifierProvider<UserProvider>(create: (_) => user),
|
ChangeNotifierProvider<StatusProvider>(create: (_) => status),
|
||||||
ChangeNotifierProvider<StatusProvider>(create: (context) => StatusProvider()),
|
Provider<KretaClient>(create: (_) => kreta),
|
||||||
Provider<KretaClient>(create: (context) => KretaClient(context: context, userAgent: settings.config.userAgent)),
|
Provider<DatabaseProvider>(create: (context) => database),
|
||||||
Provider<DatabaseProvider>(create: (context) => database),
|
ChangeNotifierProvider<ThemeModeObserver>(create: (context) => ThemeModeObserver(initialTheme: settings.theme)),
|
||||||
ChangeNotifierProvider<ThemeModeObserver>(create: (context) => ThemeModeObserver(initialTheme: settings.theme)),
|
ChangeNotifierProvider<NewsProvider>(create: (context) => NewsProvider(context: context)),
|
||||||
ChangeNotifierProvider<NewsProvider>(create: (context) => NewsProvider(context: context)),
|
ChangeNotifierProvider<UpdateProvider>(create: (context) => UpdateProvider(context: context)),
|
||||||
ChangeNotifierProvider<UpdateProvider>(create: (context) => UpdateProvider(context: context)),
|
|
||||||
|
|
||||||
// User data providers
|
// User data providers
|
||||||
ChangeNotifierProvider<GradeProvider>(create: (context) => GradeProvider(context: context)),
|
ChangeNotifierProvider<GradeProvider>(create: (_) => GradeProvider(settings: settings, user: user, database: database, kreta: kreta)),
|
||||||
ChangeNotifierProvider<TimetableProvider>(create: (context) => TimetableProvider(context: context)),
|
ChangeNotifierProvider<TimetableProvider>(create: (_) => timetable),
|
||||||
ChangeNotifierProvider<ExamProvider>(create: (context) => ExamProvider(context: context)),
|
ChangeNotifierProvider<ExamProvider>(create: (context) => ExamProvider(context: context)),
|
||||||
ChangeNotifierProvider<HomeworkProvider>(create: (context) => HomeworkProvider(context: context)),
|
ChangeNotifierProvider<HomeworkProvider>(create: (context) => HomeworkProvider(context: context)),
|
||||||
ChangeNotifierProvider<MessageProvider>(create: (context) => MessageProvider(context: context)),
|
ChangeNotifierProvider<MessageProvider>(create: (context) => MessageProvider(context: context)),
|
||||||
ChangeNotifierProvider<NoteProvider>(create: (context) => NoteProvider(context: context)),
|
ChangeNotifierProvider<NoteProvider>(create: (context) => NoteProvider(context: context)),
|
||||||
ChangeNotifierProvider<EventProvider>(create: (context) => EventProvider(context: context)),
|
ChangeNotifierProvider<EventProvider>(create: (context) => EventProvider(context: context)),
|
||||||
ChangeNotifierProvider<AbsenceProvider>(create: (context) => AbsenceProvider(context: context)),
|
ChangeNotifierProvider<AbsenceProvider>(create: (context) => AbsenceProvider(context: context)),
|
||||||
|
|
||||||
ChangeNotifierProvider<GradeCalculatorProvider>(create: (context) => GradeCalculatorProvider(context)),
|
ChangeNotifierProvider<GradeCalculatorProvider>(
|
||||||
],
|
create: (_) => GradeCalculatorProvider(settings: settings, user: user, database: database, kreta: kreta)),
|
||||||
child: Consumer<ThemeModeObserver>(
|
ChangeNotifierProvider<LiveCardProvider>(create: (context) => LiveCardProvider(timetable: timetable, settings: settings))
|
||||||
builder: (context, themeMode, child) {
|
],
|
||||||
return MaterialApp(
|
child: Consumer<ThemeModeObserver>(
|
||||||
|
builder: (context, themeMode, child) {
|
||||||
|
return FutureBuilder<CorePalette?>(
|
||||||
|
future: DynamicColorPlugin.getCorePalette(),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
corePalette = snapshot.data;
|
||||||
|
return MaterialApp(
|
||||||
builder: (context, child) {
|
builder: (context, child) {
|
||||||
// Limit font size scaling to 1.0
|
// Limit font size scaling to 1.0
|
||||||
double textScaleFactor = min(MediaQuery.of(context).textScaleFactor, 1.0);
|
double textScaleFactor = min(MediaQuery.of(context).textScaleFactor, 1.0);
|
||||||
|
|
||||||
return MediaQuery(
|
return I18n(
|
||||||
data: MediaQuery.of(context).copyWith(textScaleFactor: textScaleFactor),
|
initialLocale: Locale(settings.language, settings.language.toUpperCase()),
|
||||||
child: child ?? Container(),
|
child: MediaQuery(
|
||||||
|
data: MediaQuery.of(context).copyWith(textScaleFactor: textScaleFactor),
|
||||||
|
child: child ?? Container(),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
title: "Filc Napló",
|
title: "Filc Napló",
|
||||||
debugShowCheckedModeBanner: false,
|
debugShowCheckedModeBanner: false,
|
||||||
theme: AppTheme.lightTheme(context),
|
theme: AppTheme.lightTheme(context, palette: corePalette),
|
||||||
darkTheme: AppTheme.darkTheme(context),
|
darkTheme: AppTheme.darkTheme(context, palette: corePalette),
|
||||||
themeMode: themeMode.themeMode,
|
themeMode: themeMode.themeMode,
|
||||||
localizationsDelegates: const [
|
localizationsDelegates: const [
|
||||||
GlobalMaterialLocalizations.delegate,
|
GlobalMaterialLocalizations.delegate,
|
||||||
@@ -122,29 +148,43 @@ class App extends StatelessWidget {
|
|||||||
return locale;
|
return locale;
|
||||||
},
|
},
|
||||||
onGenerateRoute: (settings) => rootNavigator(settings),
|
onGenerateRoute: (settings) => rootNavigator(settings),
|
||||||
initialRoute: user.getUsers().isNotEmpty ? "navigation" : "login");
|
initialRoute: user.getUsers().isNotEmpty ? "navigation" : "login",
|
||||||
},
|
);
|
||||||
),
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Route? rootNavigator(RouteSettings route) {
|
Route? rootNavigator(RouteSettings route) {
|
||||||
// if platform == android || platform == ios
|
// if platform == android || platform == ios
|
||||||
switch (route.name) {
|
if (Platform.isAndroid || Platform.isIOS) {
|
||||||
case "login_back":
|
switch (route.name) {
|
||||||
return CupertinoPageRoute(builder: (context) => const LoginScreen(back: true));
|
case "login_back":
|
||||||
case "login":
|
return CupertinoPageRoute(builder: (context) => const mobile.LoginScreen(back: true));
|
||||||
return _rootRoute(const LoginScreen());
|
case "login":
|
||||||
case "navigation":
|
return _rootRoute(const mobile.LoginScreen());
|
||||||
return _rootRoute(const NavigationScreen());
|
case "navigation":
|
||||||
case "login_to_navigation":
|
return _rootRoute(const mobile.NavigationScreen());
|
||||||
return loginRoute(const NavigationScreen());
|
case "login_to_navigation":
|
||||||
case "settings":
|
return mobile.loginRoute(const mobile.NavigationScreen());
|
||||||
return settingsRoute(const SettingsScreen());
|
case "settings":
|
||||||
|
return mobile.settingsRoute(const mobile.SettingsScreen());
|
||||||
|
}
|
||||||
|
} else if (Platform.isWindows || Platform.isMacOS || Platform.isLinux) {
|
||||||
|
switch (route.name) {
|
||||||
|
case "login_back":
|
||||||
|
return CupertinoPageRoute(builder: (context) => const desktop.LoginScreen(back: true));
|
||||||
|
case "login":
|
||||||
|
return _rootRoute(const desktop.LoginScreen());
|
||||||
|
case "navigation":
|
||||||
|
return _rootRoute(const desktop.NavigationScreen());
|
||||||
|
case "login_to_navigation":
|
||||||
|
return desktop.loginRoute(const desktop.NavigationScreen());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
// else if platform == windows || ...
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Route _rootRoute(Widget widget) {
|
Route _rootRoute(Widget widget) {
|
||||||
|
|||||||
@@ -2,12 +2,36 @@
|
|||||||
|
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:filcnaplo/api/providers/database_provider.dart';
|
||||||
import 'package:filcnaplo/database/struct.dart';
|
import 'package:filcnaplo/database/struct.dart';
|
||||||
import 'package:filcnaplo/models/settings.dart';
|
import 'package:filcnaplo/models/settings.dart';
|
||||||
import 'package:sqflite/sqflite.dart';
|
import 'package:sqflite/sqflite.dart';
|
||||||
|
// ignore: depend_on_referenced_packages
|
||||||
import 'package:sqflite_common_ffi/sqflite_ffi.dart';
|
import 'package:sqflite_common_ffi/sqflite_ffi.dart';
|
||||||
|
|
||||||
Future<Database> initDB() async {
|
const settingsDB = DatabaseStruct("settings", {
|
||||||
|
"language": String, "start_page": int, "rounding": int, "theme": int, "accent_color": int, "news": int, "news_state": int, "developer_mode": int,
|
||||||
|
"update_channel": int, "config": String, "custom_accent_color": int, "custom_background_color": int, "custom_highlight_color": int, // general
|
||||||
|
"grade_color1": int, "grade_color2": int, "grade_color3": int, "grade_color4": int, "grade_color5": int, // grade colors
|
||||||
|
"vibration_strength": int, "ab_weeks": int, "swap_ab_weeks": int,
|
||||||
|
"notifications": int, "notifications_bitfield": int, "notification_poll_interval": int, // notifications
|
||||||
|
"x_filc_id": String, "graph_class_avg": int, "presentation_mode": int, "bell_delay": int, "bell_delay_enabled": int,
|
||||||
|
"grade_opening_fun": int, "icon_pack": String, "premium_scopes": String, "premium_token": String, "last_account_id": String,
|
||||||
|
});
|
||||||
|
const usersDB = DatabaseStruct("users", {
|
||||||
|
"id": String, "name": String, "username": String, "password": String, "institute_code": String, "student": String, "role": int,
|
||||||
|
"nickname": String // premium only
|
||||||
|
});
|
||||||
|
const userDataDB = DatabaseStruct("user_data", {
|
||||||
|
"id": String, "grades": String, "timetable": String, "exams": String, "homework": String, "messages": String, "notes": String,
|
||||||
|
"events": String, "absences": String, "group_averages": String,
|
||||||
|
// "subject_lesson_count": String, // non kreta data
|
||||||
|
"last_seen_grade": int,
|
||||||
|
});
|
||||||
|
|
||||||
|
Future<void> createTable(Database db, DatabaseStruct struct) => db.execute("CREATE TABLE IF NOT EXISTS ${struct.table} ($struct)");
|
||||||
|
|
||||||
|
Future<Database> initDB(DatabaseProvider database) async {
|
||||||
Database db;
|
Database db;
|
||||||
|
|
||||||
if (Platform.isLinux || Platform.isWindows) {
|
if (Platform.isLinux || Platform.isWindows) {
|
||||||
@@ -17,100 +41,92 @@ Future<Database> initDB() async {
|
|||||||
db = await openDatabase("app.db");
|
db = await openDatabase("app.db");
|
||||||
}
|
}
|
||||||
|
|
||||||
var settingsDB = await createSettingsTable(db);
|
await createTable(db, settingsDB);
|
||||||
|
await createTable(db, usersDB);
|
||||||
// Create table Users
|
await createTable(db, userDataDB);
|
||||||
var usersDB = await createUsersTable(db);
|
|
||||||
await db.execute("CREATE TABLE IF NOT EXISTS user_data ("
|
|
||||||
"id TEXT NOT NULL, grades TEXT, timetable TEXT, exams TEXT, homework TEXT, messages TEXT, notes TEXT, events TEXT, absences TEXT)");
|
|
||||||
|
|
||||||
if ((await db.rawQuery("SELECT COUNT(*) FROM settings"))[0].values.first == 0) {
|
if ((await db.rawQuery("SELECT COUNT(*) FROM settings"))[0].values.first == 0) {
|
||||||
// Set default values for table Settings
|
// Set default values for table Settings
|
||||||
await db.insert("settings", SettingsProvider.defaultSettings().toMap());
|
await db.insert("settings", SettingsProvider.defaultSettings(database: database).toMap());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Migrate Databases
|
// Migrate Databases
|
||||||
await migrateDB(db, "settings", settingsDB.struct.keys, SettingsProvider.defaultSettings().toMap(), createSettingsTable);
|
try {
|
||||||
await migrateDB(db, "users", usersDB.struct.keys, {"role": 0}, createUsersTable);
|
await migrateDB(
|
||||||
|
db,
|
||||||
|
struct: settingsDB,
|
||||||
|
defaultValues: SettingsProvider.defaultSettings(database: database).toMap(),
|
||||||
|
);
|
||||||
|
await migrateDB(
|
||||||
|
db,
|
||||||
|
struct: usersDB,
|
||||||
|
defaultValues: {"role": 0},
|
||||||
|
);
|
||||||
|
await migrateDB(db, struct: userDataDB, defaultValues: {
|
||||||
|
"grades": "[]", "timetable": "[]", "exams": "[]", "homework": "[]", "messages": "[]", "notes": "[]", "events": "[]", "absences": "[]",
|
||||||
|
"group_averages": "[]",
|
||||||
|
// "subject_lesson_count": "{}", // non kreta data
|
||||||
|
"last_seen_grade": 0,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
print("ERROR: migrateDB: $error");
|
||||||
|
}
|
||||||
|
|
||||||
return db;
|
return db;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<DatabaseStruct> createSettingsTable(Database db) async {
|
|
||||||
var settingsDB = DatabaseStruct({
|
|
||||||
"language": String, "start_page": int, "rounding": int, "theme": int, "accent_color": int, "news": int, "news_state": int, "developer_mode": int,
|
|
||||||
"update_channel": int, "config": String, // general
|
|
||||||
"grade_color1": int, "grade_color2": int, "grade_color3": int, "grade_color4": int, "grade_color5": int, // grade colors
|
|
||||||
"vibration_strength": int, "ab_weeks": int, "swap_ab_weeks": int,
|
|
||||||
"notifications": int, "notifications_bitfield": int, "notification_poll_interval": int, // notifications
|
|
||||||
"x_filc_id": String,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create table Settings
|
|
||||||
await db.execute("CREATE TABLE IF NOT EXISTS settings ($settingsDB)");
|
|
||||||
|
|
||||||
return settingsDB;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<DatabaseStruct> createUsersTable(Database db) async {
|
|
||||||
var usersDB = DatabaseStruct(
|
|
||||||
{"id": String, "name": String, "username": String, "password": String, "institute_code": String, "student": String, "role": int});
|
|
||||||
|
|
||||||
// Create table Users
|
|
||||||
await db.execute("CREATE TABLE IF NOT EXISTS users ($usersDB)");
|
|
||||||
|
|
||||||
return usersDB;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> migrateDB(
|
Future<void> migrateDB(
|
||||||
Database db,
|
Database db, {
|
||||||
String table,
|
required DatabaseStruct struct,
|
||||||
Iterable<String> keys,
|
required Map<String, Object?> defaultValues,
|
||||||
Map<String, Object?> defaultValues,
|
}) async {
|
||||||
Future<DatabaseStruct> Function(Database) create,
|
var originalRows = await db.query(struct.table);
|
||||||
) async {
|
|
||||||
var originalRows = await db.query(table);
|
|
||||||
|
|
||||||
if (originalRows.isEmpty) {
|
if (originalRows.isEmpty) {
|
||||||
await db.execute("drop table $table");
|
await db.execute("drop table ${struct.table}");
|
||||||
await create(db);
|
await createTable(db, struct);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Map<String, dynamic>> migrated = [];
|
List<Map<String, dynamic>> migrated = [];
|
||||||
|
|
||||||
|
// go through each row and add missing keys or delete non existing keys
|
||||||
await Future.forEach<Map<String, Object?>>(originalRows, (original) async {
|
await Future.forEach<Map<String, Object?>>(originalRows, (original) async {
|
||||||
bool migrationRequired = keys.any((key) => !original.containsKey(key) || original[key] == null);
|
bool migrationRequired = struct.struct.keys.any((key) => !original.containsKey(key) || original[key] == null) ||
|
||||||
|
original.keys.any((key) => !struct.struct.containsKey(key));
|
||||||
|
|
||||||
if (migrationRequired) {
|
if (migrationRequired) {
|
||||||
print("INFO: Migrating $table");
|
print("INFO: Migrating ${struct.table}");
|
||||||
var copy = Map<String, dynamic>.from(original);
|
var copy = Map<String, Object?>.from(original);
|
||||||
|
|
||||||
// Fill missing columns
|
// Fill missing columns
|
||||||
for (var key in keys) {
|
for (var key in struct.struct.keys) {
|
||||||
if (!keys.contains(key)) {
|
|
||||||
print("DEBUG: dropping $key");
|
|
||||||
copy.remove(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!original.containsKey(key) || original[key] == null) {
|
if (!original.containsKey(key) || original[key] == null) {
|
||||||
print("DEBUG: migrating $key");
|
print("DEBUG: migrating $key");
|
||||||
copy[key] = defaultValues[key];
|
copy[key] = defaultValues[key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (var key in original.keys) {
|
||||||
|
if (!struct.struct.keys.contains(key)) {
|
||||||
|
print("DEBUG: dropping $key");
|
||||||
|
copy.remove(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
migrated.add(copy);
|
migrated.add(copy);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// replace the old table with the migrated one
|
||||||
if (migrated.isNotEmpty) {
|
if (migrated.isNotEmpty) {
|
||||||
// Delete table
|
// Delete table
|
||||||
await db.execute("drop table $table");
|
await db.execute("drop table ${struct.table}");
|
||||||
|
|
||||||
// Recreate table
|
// Recreate table
|
||||||
await create(db);
|
await createTable(db, struct);
|
||||||
await Future.forEach(migrated, (Map<String, dynamic> copy) async {
|
await Future.forEach(migrated, (Map<String, Object?> copy) async {
|
||||||
await db.insert(table, copy);
|
await db.insert(struct.table, copy);
|
||||||
});
|
});
|
||||||
|
|
||||||
print("INFO: Database migrated");
|
print("INFO: Database migrated");
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
import 'package:filcnaplo/api/providers/database_provider.dart';
|
||||||
|
import 'package:filcnaplo/models/subject_lesson_count.dart';
|
||||||
import 'package:filcnaplo/models/user.dart';
|
import 'package:filcnaplo/models/user.dart';
|
||||||
|
// ignore: depend_on_referenced_packages
|
||||||
import 'package:sqflite_common/sqlite_api.dart';
|
import 'package:sqflite_common/sqlite_api.dart';
|
||||||
|
|
||||||
// Models
|
// Models
|
||||||
@@ -13,24 +16,31 @@ import 'package:filcnaplo_kreta_api/models/message.dart';
|
|||||||
import 'package:filcnaplo_kreta_api/models/note.dart';
|
import 'package:filcnaplo_kreta_api/models/note.dart';
|
||||||
import 'package:filcnaplo_kreta_api/models/event.dart';
|
import 'package:filcnaplo_kreta_api/models/event.dart';
|
||||||
import 'package:filcnaplo_kreta_api/models/absence.dart';
|
import 'package:filcnaplo_kreta_api/models/absence.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/group_average.dart';
|
||||||
|
|
||||||
class DatabaseQuery {
|
class DatabaseQuery {
|
||||||
DatabaseQuery({required this.db});
|
DatabaseQuery({required this.db});
|
||||||
|
|
||||||
final Database db;
|
final Database db;
|
||||||
|
|
||||||
Future<SettingsProvider> getSettings() async {
|
Future<SettingsProvider> getSettings(DatabaseProvider database) async {
|
||||||
Map settingsMap = (await db.query("settings")).elementAt(0);
|
Map settingsMap = (await db.query("settings")).elementAt(0);
|
||||||
SettingsProvider settings = SettingsProvider.fromMap(settingsMap);
|
SettingsProvider settings = SettingsProvider.fromMap(settingsMap, database: database);
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<UserProvider> getUsers() async {
|
Future<UserProvider> getUsers(SettingsProvider settings) async {
|
||||||
var userProvider = UserProvider();
|
var userProvider = UserProvider(settings: settings);
|
||||||
List<Map> usersMap = await db.query("users");
|
List<Map> usersMap = await db.query("users");
|
||||||
for (var user in usersMap) {
|
for (var user in usersMap) {
|
||||||
userProvider.addUser(User.fromMap(user));
|
userProvider.addUser(User.fromMap(user));
|
||||||
}
|
}
|
||||||
|
if (userProvider.getUsers().map((e) => e.id).contains(settings.lastAccountId)) {
|
||||||
|
userProvider.setUser(settings.lastAccountId);
|
||||||
|
} else {
|
||||||
|
userProvider.setUser(userProvider.getUsers().first.id);
|
||||||
|
settings.update(lastAccountId: userProvider.id);
|
||||||
|
}
|
||||||
return userProvider;
|
return userProvider;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -106,9 +116,36 @@ class UserDatabaseQuery {
|
|||||||
Future<List<Absence>> getAbsences({required String userId}) async {
|
Future<List<Absence>> getAbsences({required String userId}) async {
|
||||||
List<Map> userData = await db.query("user_data", where: "id = ?", whereArgs: [userId]);
|
List<Map> userData = await db.query("user_data", where: "id = ?", whereArgs: [userId]);
|
||||||
if (userData.isEmpty) return [];
|
if (userData.isEmpty) return [];
|
||||||
String? absebcesJson = userData.elementAt(0)["absences"] as String?;
|
String? absencesJson = userData.elementAt(0)["absences"] as String?;
|
||||||
if (absebcesJson == null) return [];
|
if (absencesJson == null) return [];
|
||||||
List<Absence> absebces = (jsonDecode(absebcesJson) as List).map((e) => Absence.fromJson(e)).toList();
|
List<Absence> absences = (jsonDecode(absencesJson) as List).map((e) => Absence.fromJson(e)).toList();
|
||||||
return absebces;
|
return absences;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<GroupAverage>> getGroupAverages({required String userId}) async {
|
||||||
|
List<Map> userData = await db.query("user_data", where: "id = ?", whereArgs: [userId]);
|
||||||
|
if (userData.isEmpty) return [];
|
||||||
|
String? groupAveragesJson = userData.elementAt(0)["group_averages"] as String?;
|
||||||
|
if (groupAveragesJson == null) return [];
|
||||||
|
List<GroupAverage> groupAverages = (jsonDecode(groupAveragesJson) as List).map((e) => GroupAverage.fromJson(e)).toList();
|
||||||
|
return groupAverages;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<SubjectLessonCount> getSubjectLessonCount({required String userId}) async {
|
||||||
|
List<Map> userData = await db.query("user_data", where: "id = ?", whereArgs: [userId]);
|
||||||
|
if (userData.isEmpty) return SubjectLessonCount.fromMap({});
|
||||||
|
String? lessonCountJson = userData.elementAt(0)["subject_lesson_count"] as String?;
|
||||||
|
if (lessonCountJson == null) return SubjectLessonCount.fromMap({});
|
||||||
|
SubjectLessonCount lessonCount = SubjectLessonCount.fromMap(jsonDecode(lessonCountJson) as Map);
|
||||||
|
return lessonCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<DateTime> lastSeenGrade({required String userId}) async {
|
||||||
|
List<Map> userData = await db.query("user_data", where: "id = ?", whereArgs: [userId]);
|
||||||
|
if (userData.isEmpty) return DateTime(0);
|
||||||
|
int? lastSeenDate = userData.elementAt(0)["last_seen_grade"] as int?;
|
||||||
|
if (lastSeenDate == null) return DateTime(0);
|
||||||
|
DateTime lastSeen = DateTime.fromMillisecondsSinceEpoch(lastSeenDate);
|
||||||
|
return lastSeen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
import 'package:filcnaplo/models/subject_lesson_count.dart';
|
||||||
|
// ignore: depend_on_referenced_packages
|
||||||
import 'package:sqflite_common/sqlite_api.dart';
|
import 'package:sqflite_common/sqlite_api.dart';
|
||||||
|
|
||||||
// Models
|
// Models
|
||||||
@@ -12,6 +14,7 @@ import 'package:filcnaplo_kreta_api/models/message.dart';
|
|||||||
import 'package:filcnaplo_kreta_api/models/note.dart';
|
import 'package:filcnaplo_kreta_api/models/note.dart';
|
||||||
import 'package:filcnaplo_kreta_api/models/event.dart';
|
import 'package:filcnaplo_kreta_api/models/event.dart';
|
||||||
import 'package:filcnaplo_kreta_api/models/absence.dart';
|
import 'package:filcnaplo_kreta_api/models/absence.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/group_average.dart';
|
||||||
|
|
||||||
class DatabaseStore {
|
class DatabaseStore {
|
||||||
DatabaseStore({required this.db});
|
DatabaseStore({required this.db});
|
||||||
@@ -43,43 +46,58 @@ class UserDatabaseStore {
|
|||||||
|
|
||||||
final Database db;
|
final Database db;
|
||||||
|
|
||||||
Future storeGrades(List<Grade> grades, {required String userId}) async {
|
Future<void> storeGrades(List<Grade> grades, {required String userId}) async {
|
||||||
String gradesJson = jsonEncode(grades.map((e) => e.json).toList());
|
String gradesJson = jsonEncode(grades.map((e) => e.json).toList());
|
||||||
await db.update("user_data", {"grades": gradesJson}, where: "id = ?", whereArgs: [userId]);
|
await db.update("user_data", {"grades": gradesJson}, where: "id = ?", whereArgs: [userId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future storeLessons(List<Lesson> lessons, {required String userId}) async {
|
Future<void> storeLessons(List<Lesson> lessons, {required String userId}) async {
|
||||||
String lessonsJson = jsonEncode(lessons.map((e) => e.json).toList());
|
String lessonsJson = jsonEncode(lessons.map((e) => e.json).toList());
|
||||||
await db.update("user_data", {"timetable": lessonsJson}, where: "id = ?", whereArgs: [userId]);
|
await db.update("user_data", {"timetable": lessonsJson}, where: "id = ?", whereArgs: [userId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future storeExams(List<Exam> exams, {required String userId}) async {
|
Future<void> storeExams(List<Exam> exams, {required String userId}) async {
|
||||||
String examsJson = jsonEncode(exams.map((e) => e.json).toList());
|
String examsJson = jsonEncode(exams.map((e) => e.json).toList());
|
||||||
await db.update("user_data", {"exams": examsJson}, where: "id = ?", whereArgs: [userId]);
|
await db.update("user_data", {"exams": examsJson}, where: "id = ?", whereArgs: [userId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future storeHomework(List<Homework> homework, {required String userId}) async {
|
Future<void> storeHomework(List<Homework> homework, {required String userId}) async {
|
||||||
String homeworkJson = jsonEncode(homework.map((e) => e.json).toList());
|
String homeworkJson = jsonEncode(homework.map((e) => e.json).toList());
|
||||||
await db.update("user_data", {"homework": homeworkJson}, where: "id = ?", whereArgs: [userId]);
|
await db.update("user_data", {"homework": homeworkJson}, where: "id = ?", whereArgs: [userId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future storeMessages(List<Message> messages, {required String userId}) async {
|
Future<void> storeMessages(List<Message> messages, {required String userId}) async {
|
||||||
String messagesJson = jsonEncode(messages.map((e) => e.json).toList());
|
String messagesJson = jsonEncode(messages.map((e) => e.json).toList());
|
||||||
await db.update("user_data", {"messages": messagesJson}, where: "id = ?", whereArgs: [userId]);
|
await db.update("user_data", {"messages": messagesJson}, where: "id = ?", whereArgs: [userId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future storeNotes(List<Note> notes, {required String userId}) async {
|
Future<void> storeNotes(List<Note> notes, {required String userId}) async {
|
||||||
String notesJson = jsonEncode(notes.map((e) => e.json).toList());
|
String notesJson = jsonEncode(notes.map((e) => e.json).toList());
|
||||||
await db.update("user_data", {"notes": notesJson}, where: "id = ?", whereArgs: [userId]);
|
await db.update("user_data", {"notes": notesJson}, where: "id = ?", whereArgs: [userId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future storeEvents(List<Event> events, {required String userId}) async {
|
Future<void> storeEvents(List<Event> events, {required String userId}) async {
|
||||||
String eventsJson = jsonEncode(events.map((e) => e.json).toList());
|
String eventsJson = jsonEncode(events.map((e) => e.json).toList());
|
||||||
await db.update("user_data", {"events": eventsJson}, where: "id = ?", whereArgs: [userId]);
|
await db.update("user_data", {"events": eventsJson}, where: "id = ?", whereArgs: [userId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future storeAbsences(List<Absence> absences, {required String userId}) async {
|
Future<void> storeAbsences(List<Absence> absences, {required String userId}) async {
|
||||||
String absencesJson = jsonEncode(absences.map((e) => e.json).toList());
|
String absencesJson = jsonEncode(absences.map((e) => e.json).toList());
|
||||||
await db.update("user_data", {"absences": absencesJson}, where: "id = ?", whereArgs: [userId]);
|
await db.update("user_data", {"absences": absencesJson}, where: "id = ?", whereArgs: [userId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> storeGroupAverages(List<GroupAverage> groupAverages, {required String userId}) async {
|
||||||
|
String groupAveragesJson = jsonEncode(groupAverages.map((e) => e.json).toList());
|
||||||
|
await db.update("user_data", {"group_averages": groupAveragesJson}, where: "id = ?", whereArgs: [userId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> storeSubjectLessonCount(SubjectLessonCount lessonCount, {required String userId}) async {
|
||||||
|
String lessonCountJson = jsonEncode(lessonCount.toMap());
|
||||||
|
await db.update("user_data", {"subject_lesson_count": lessonCountJson}, where: "id = ?", whereArgs: [userId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> storeLastSeenGrade(DateTime date, {required String userId}) async {
|
||||||
|
int lastSeenDate = date.millisecondsSinceEpoch;
|
||||||
|
await db.update("user_data", {"last_seen_grade": lastSeenDate}, where: "id = ?", whereArgs: [userId]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
class DatabaseStruct {
|
class DatabaseStruct {
|
||||||
|
final String table;
|
||||||
final Map<String, dynamic> struct;
|
final Map<String, dynamic> struct;
|
||||||
|
|
||||||
DatabaseStruct(this.struct);
|
const DatabaseStruct(this.table, this.struct);
|
||||||
|
|
||||||
String _toDBfield(String name, dynamic type) {
|
String _toDBfield(String name, dynamic type) {
|
||||||
String typeName = "";
|
String typeName = "";
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
// ignore_for_file: use_build_context_synchronously
|
||||||
|
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
|
|||||||
@@ -7,19 +7,14 @@ class AverageHelper {
|
|||||||
List<String> ignoreInFinal = ["5,SzorgalomErtek", "4,MagatartasErtek"];
|
List<String> ignoreInFinal = ["5,SzorgalomErtek", "4,MagatartasErtek"];
|
||||||
|
|
||||||
if (finalAvg) {
|
if (finalAvg) {
|
||||||
grades.removeWhere((e) =>
|
grades.removeWhere((e) => (e.value.value == 0) || (ignoreInFinal.contains(e.gradeType?.id)));
|
||||||
(e.value.value == 0) ||
|
|
||||||
(ignoreInFinal.contains(e.gradeType?.id)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var e in grades) {
|
for (var e in grades) {
|
||||||
average += e.value.value * ((finalAvg ? 100 : e.value.weight) / 100);
|
average += e.value.value * ((finalAvg ? 100 : e.value.weight) / 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
average = average /
|
average = average / grades.map((e) => (finalAvg ? 100 : e.value.weight) / 100).fold(0.0, (a, b) => a + b);
|
||||||
grades
|
|
||||||
.map((e) => (finalAvg ? 100 : e.value.weight) / 100)
|
|
||||||
.fold(0.0, (a, b) => a + b);
|
|
||||||
|
|
||||||
return average.isNaN ? 0.0 : average;
|
return average.isNaN ? 0.0 : average;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import 'package:share_plus/share_plus.dart';
|
|||||||
|
|
||||||
class ShareHelper {
|
class ShareHelper {
|
||||||
static Future<void> shareText(String text, {String? subject}) => Share.share(text, subject: subject);
|
static Future<void> shareText(String text, {String? subject}) => Share.share(text, subject: subject);
|
||||||
|
// ignore: deprecated_member_use
|
||||||
static Future<void> shareFile(String path, {String? text, String? subject}) => Share.shareFiles([path], text: text, subject: subject);
|
static Future<void> shareFile(String path, {String? text, String? subject}) => Share.shareFiles([path], text: text, subject: subject);
|
||||||
|
|
||||||
static Future<void> shareAttachment(Attachment attachment, {required BuildContext context}) async {
|
static Future<void> shareAttachment(Attachment attachment, {required BuildContext context}) async {
|
||||||
|
|||||||
144
filcnaplo/lib/helpers/subject.dart
Normal file
144
filcnaplo/lib/helpers/subject.dart
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
import 'package:filcnaplo/icons/filc_icons.dart';
|
||||||
|
import 'package:filcnaplo/models/icon_pack.dart';
|
||||||
|
import 'package:filcnaplo/models/settings.dart';
|
||||||
|
import 'package:filcnaplo/utils/format.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/subject.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
typedef SubjectIconVariants = Map<IconPack, IconData>;
|
||||||
|
|
||||||
|
class SubjectIconData {
|
||||||
|
final SubjectIconVariants data;
|
||||||
|
final String name; // for iOS live activities compatibilty
|
||||||
|
|
||||||
|
SubjectIconData({
|
||||||
|
this.data = const {
|
||||||
|
IconPack.material: Icons.widgets_outlined,
|
||||||
|
IconPack.cupertino: CupertinoIcons.rectangle_grid_2x2,
|
||||||
|
},
|
||||||
|
this.name = "square.grid.2x2",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
SubjectIconVariants createIcon({required IconData material, required IconData cupertino}) {
|
||||||
|
return {
|
||||||
|
IconPack.material: material,
|
||||||
|
IconPack.cupertino: cupertino,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
class SubjectIcon {
|
||||||
|
static String resolveName({Subject? subject, String? subjectName}) => _resolve(subject: subject, subjectName: subjectName).name;
|
||||||
|
static IconData resolveVariant({Subject? subject, String? subjectName, required BuildContext context}) =>
|
||||||
|
_resolve(subject: subject, subjectName: subjectName).data[Provider.of<SettingsProvider>(context, listen: false).iconPack]!;
|
||||||
|
|
||||||
|
static SubjectIconData _resolve({Subject? subject, String? subjectName}) {
|
||||||
|
assert(!(subject == null && subjectName == null));
|
||||||
|
|
||||||
|
String name = (subject?.name ?? subjectName ?? "").toLowerCase().specialChars().trim();
|
||||||
|
String category = subject?.category.description.toLowerCase().specialChars() ?? "";
|
||||||
|
|
||||||
|
// todo: check for categories
|
||||||
|
if (RegExp("mate(k|matika)").hasMatch(name) || category == "matematika") {
|
||||||
|
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.function, material: Icons.calculate_outlined), name: "function");
|
||||||
|
} else if (RegExp("magyar nyelv|nyelvtan").hasMatch(name)) {
|
||||||
|
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.textformat_alt, material: Icons.spellcheck_outlined), name: "textformat.alt");
|
||||||
|
} else if (RegExp("irodalom").hasMatch(name)) {
|
||||||
|
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.book, material: Icons.menu_book_outlined), name: "book");
|
||||||
|
} else if (RegExp("tor(i|tenelem)").hasMatch(name)) {
|
||||||
|
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.compass, material: Icons.hourglass_empty_outlined), name: "safari");
|
||||||
|
} else if (RegExp("foldrajz").hasMatch(name)) {
|
||||||
|
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.map, material: Icons.public_outlined), name: "map");
|
||||||
|
} else if (RegExp("rajz|muvtori|muveszet|vizualis").hasMatch(name)) {
|
||||||
|
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.paintbrush, material: Icons.palette_outlined), name: "paintbrush");
|
||||||
|
} else if (RegExp("fizika").hasMatch(name)) {
|
||||||
|
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.lightbulb, material: Icons.emoji_objects_outlined), name: "lightbulb");
|
||||||
|
} else if (RegExp("^enek|zene|szolfezs|zongora|korus").hasMatch(name)) {
|
||||||
|
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.music_note, material: Icons.music_note_outlined), name: "music.note");
|
||||||
|
} else if (RegExp("^tes(i|tneveles)|sport").hasMatch(name)) {
|
||||||
|
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.sportscourt, material: Icons.sports_soccer_outlined), name: "sportscourt");
|
||||||
|
} else if (RegExp("kemia").hasMatch(name)) {
|
||||||
|
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.lab_flask, material: Icons.science_outlined), name: "testtube.2");
|
||||||
|
} else if (RegExp("biologia").hasMatch(name)) {
|
||||||
|
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.paw, material: Icons.pets_outlined), name: "pawprint");
|
||||||
|
} else if (RegExp("kornyezet|termeszet ?(tudomany|ismeret)|hon( es nep)?ismeret").hasMatch(name)) {
|
||||||
|
return SubjectIconData(
|
||||||
|
data: createIcon(cupertino: CupertinoIcons.arrow_3_trianglepath, material: Icons.eco_outlined), name: "arrow.3.trianglepath");
|
||||||
|
} else if (RegExp("(hit|erkolcs)tan|vallas|etika").hasMatch(name)) {
|
||||||
|
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.heart, material: Icons.favorite_border_outlined), name: "heart");
|
||||||
|
} else if (RegExp("penzugy").hasMatch(name)) {
|
||||||
|
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.money_dollar, material: Icons.savings_outlined), name: "dollarsign");
|
||||||
|
} else if (RegExp("informatika|szoftver|iroda|digitalis").hasMatch(name)) {
|
||||||
|
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.device_laptop, material: Icons.computer_outlined), name: "laptopcomputer");
|
||||||
|
} else if (RegExp("prog").hasMatch(name)) {
|
||||||
|
return SubjectIconData(
|
||||||
|
data: createIcon(cupertino: CupertinoIcons.chevron_left_slash_chevron_right, material: Icons.code_outlined),
|
||||||
|
name: "chevron.left.forwardslash.chevron.right");
|
||||||
|
} else if (RegExp("halozat").hasMatch(name)) {
|
||||||
|
return SubjectIconData(
|
||||||
|
data: createIcon(cupertino: CupertinoIcons.antenna_radiowaves_left_right, material: Icons.wifi_tethering_outlined),
|
||||||
|
name: "antenna.radiowaves.left.and.right");
|
||||||
|
} else if (RegExp("szinhaz").hasMatch(name)) {
|
||||||
|
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.hifispeaker, material: Icons.theater_comedy_outlined), name: "hifispeaker");
|
||||||
|
} else if (RegExp("film|media").hasMatch(name)) {
|
||||||
|
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.film, material: Icons.theaters_outlined), name: "film");
|
||||||
|
} else if (RegExp("elektro(tech)?nika").hasMatch(name)) {
|
||||||
|
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.bolt, material: Icons.electrical_services_outlined), name: "bolt");
|
||||||
|
} else if (RegExp("gepesz|mernok|ipar").hasMatch(name)) {
|
||||||
|
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.wrench, material: Icons.precision_manufacturing_outlined), name: "wrench");
|
||||||
|
} else if (RegExp("technika").hasMatch(name)) {
|
||||||
|
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.hammer, material: Icons.build_outlined), name: "hammer");
|
||||||
|
} else if (RegExp("tanc").hasMatch(name)) {
|
||||||
|
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.music_mic, material: Icons.speaker_outlined), name: "music.mic");
|
||||||
|
} else if (RegExp("filozofia").hasMatch(name)) {
|
||||||
|
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.bubble_left, material: Icons.psychology_outlined), name: "bubble.left");
|
||||||
|
} else if (RegExp("osztaly(fonoki|kozosseg)").hasMatch(name) || name == "ofo") {
|
||||||
|
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.group, material: Icons.groups_outlined), name: "person.3");
|
||||||
|
} else if (RegExp("gazdasag").hasMatch(name)) {
|
||||||
|
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.chart_pie, material: Icons.account_balance_outlined), name: "chart.pie");
|
||||||
|
} else if (RegExp("szorgalom").hasMatch(name)) {
|
||||||
|
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.checkmark_seal, material: Icons.verified_outlined), name: "checkmark.seal");
|
||||||
|
} else if (RegExp("magatartas").hasMatch(name)) {
|
||||||
|
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.smiley, material: Icons.emoji_people_outlined), name: "face.smiling");
|
||||||
|
} else if (RegExp("angol|nemet|francia|olasz|orosz|spanyol|latin|kinai|nyelv").hasMatch(name)) {
|
||||||
|
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.globe, material: Icons.translate_outlined), name: "globe");
|
||||||
|
} else if (RegExp("linux").hasMatch(name)) {
|
||||||
|
return SubjectIconData(data: createIcon(material: FilcIcons.linux, cupertino: FilcIcons.linux));
|
||||||
|
}
|
||||||
|
|
||||||
|
return SubjectIconData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ShortSubject {
|
||||||
|
static String resolve({Subject? subject, String? subjectName}) {
|
||||||
|
assert(!(subject == null && subjectName == null));
|
||||||
|
|
||||||
|
String name = (subject?.name ?? subjectName ?? "").toLowerCase().specialChars().trim();
|
||||||
|
// String category = subject?.category.description.toLowerCase().specialChars() ?? "";
|
||||||
|
|
||||||
|
if (RegExp("magyar irodalom").hasMatch(name)) {
|
||||||
|
return "Irodalom";
|
||||||
|
} else if (RegExp("magyar nyelv").hasMatch(name)) {
|
||||||
|
return "Nyelvtan";
|
||||||
|
} else if (RegExp("matematika").hasMatch(name)) {
|
||||||
|
return "Matek";
|
||||||
|
} else if (RegExp("digitalis kultura").hasMatch(name)) {
|
||||||
|
return "Dig. kult.";
|
||||||
|
} else if (RegExp("testneveles").hasMatch(name)) {
|
||||||
|
return "Tesi";
|
||||||
|
} else if (RegExp("tortenelem").hasMatch(name)) {
|
||||||
|
return "Töri";
|
||||||
|
} else if (RegExp("(angol|nemet|francia|olasz|orosz|spanyol|latin|kinai) nyelv").hasMatch(name)) {
|
||||||
|
return (subject?.name ?? subjectName ?? "?").replaceAll(" nyelv", "");
|
||||||
|
} else if (RegExp("informatika").hasMatch(name)) {
|
||||||
|
return "Infó";
|
||||||
|
} else if (RegExp("osztalyfonoki").hasMatch(name)) {
|
||||||
|
return "Ofő";
|
||||||
|
}
|
||||||
|
|
||||||
|
return subject?.name.capital() ?? subjectName?.capital() ?? "?";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
import 'package:filcnaplo/icons/filc_icons.dart';
|
|
||||||
import 'package:filcnaplo/utils/format.dart';
|
|
||||||
import 'package:filcnaplo_kreta_api/models/subject.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class SubjectIcon {
|
|
||||||
static IconData? lookup({Subject? subject, String? subjectName}) {
|
|
||||||
assert(!(subject == null && subjectName == null));
|
|
||||||
|
|
||||||
String name = (subject?.name ?? subjectName ?? "").toLowerCase().specialChars().trim();
|
|
||||||
String category = subject?.category.description.toLowerCase().specialChars() ?? "";
|
|
||||||
|
|
||||||
// todo: check for categories
|
|
||||||
if (RegExp("mate(k|matika)").hasMatch(name) || category == "matematika") return Icons.calculate_outlined;
|
|
||||||
if (RegExp("magyar nyelv|nyelvtan").hasMatch(name)) return Icons.spellcheck_outlined;
|
|
||||||
if (RegExp("irodalom").hasMatch(name)) return Icons.menu_book_outlined;
|
|
||||||
if (RegExp("tor(i|tenelem)").hasMatch(name)) return Icons.hourglass_empty_outlined;
|
|
||||||
if (RegExp("foldrajz").hasMatch(name)) return Icons.public_outlined;
|
|
||||||
if (RegExp("rajz|muvtori|muveszet|vizualis").hasMatch(name)) return Icons.palette_outlined;
|
|
||||||
if (RegExp("fizika").hasMatch(name)) return Icons.emoji_objects_outlined;
|
|
||||||
if (RegExp("^enek|zene|szolfezs|zongora|korus").hasMatch(name)) return Icons.music_note_outlined;
|
|
||||||
if (RegExp("^tes(i|tneveles)|sport").hasMatch(name)) return Icons.sports_soccer_outlined;
|
|
||||||
if (RegExp("kemia").hasMatch(name)) return Icons.science_outlined;
|
|
||||||
if (RegExp("biologia").hasMatch(name)) return Icons.pets_outlined;
|
|
||||||
if (RegExp("kornyezet|termeszet(tudomany|ismeret)|hon( es nep)?ismeret").hasMatch(name)) return Icons.eco_outlined;
|
|
||||||
if (RegExp("(hit|erkolcs)tan|vallas|etika").hasMatch(name)) return Icons.favorite_border_outlined;
|
|
||||||
if (RegExp("penzugy").hasMatch(name)) return Icons.savings_outlined;
|
|
||||||
if (RegExp("informatika|szoftver|iroda|digitalis").hasMatch(name)) return Icons.computer_outlined;
|
|
||||||
if (RegExp("prog").hasMatch(name)) return Icons.code_outlined;
|
|
||||||
if (RegExp("halozat").hasMatch(name)) return Icons.wifi_tethering_outlined;
|
|
||||||
if (RegExp("szinhaz").hasMatch(name)) return Icons.theater_comedy_outlined;
|
|
||||||
if (RegExp("film|media").hasMatch(name)) return Icons.theaters_outlined;
|
|
||||||
if (RegExp("elektro(tech)?nika").hasMatch(name)) return Icons.electrical_services_outlined;
|
|
||||||
if (RegExp("gepesz|mernok|ipar").hasMatch(name)) return Icons.precision_manufacturing_outlined;
|
|
||||||
if (RegExp("technika").hasMatch(name)) return Icons.build_outlined;
|
|
||||||
if (RegExp("tanc").hasMatch(name)) return Icons.speaker_outlined;
|
|
||||||
if (RegExp("filozofia").hasMatch(name)) return Icons.psychology_outlined;
|
|
||||||
if (RegExp("osztaly(fonoki|kozosseg)").hasMatch(name)) return Icons.groups_outlined;
|
|
||||||
if (RegExp("gazdasag").hasMatch(name)) return Icons.account_balance_outlined;
|
|
||||||
if (RegExp("szorgalom").hasMatch(name)) return Icons.verified_outlined;
|
|
||||||
if (RegExp("magatartas").hasMatch(name)) return Icons.emoji_people_outlined;
|
|
||||||
if (RegExp("angol|nemet|francia|olasz|orosz|spanyol|latin|kinai|nyelv").hasMatch(name)) return Icons.translate_outlined;
|
|
||||||
if (RegExp("linux").hasMatch(name)) return FilcIcons.linux;
|
|
||||||
return Icons.widgets_outlined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -32,7 +32,7 @@ extension UpdateHelper on Release {
|
|||||||
|
|
||||||
if (result.type != ResultType.done) {
|
if (result.type != ResultType.done) {
|
||||||
// ignore: avoid_print
|
// ignore: avoid_print
|
||||||
print("ERROR: installUpdate.openFile: " + result.message);
|
print("ERROR: installUpdate.openFile: ${result.message}");
|
||||||
throw result.message;
|
throw result.message;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ extension UpdateHelper on Release {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<Uint8List> download({UpdateCallback? updateCallback}) async {
|
Future<Uint8List> download({UpdateCallback? updateCallback}) async {
|
||||||
var response = await FilcAPI.downloadRelease(this);
|
var response = await FilcAPI.downloadRelease(downloads.first);
|
||||||
|
|
||||||
List<List<int>> chunks = [];
|
List<List<int>> chunks = [];
|
||||||
int downloaded = 0;
|
int downloaded = 0;
|
||||||
|
|||||||
@@ -1,10 +1,22 @@
|
|||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
class FilcIcons {
|
class FilcIcons {
|
||||||
static const IconData home = FilcIconData(0x41);
|
FilcIcons._();
|
||||||
static const IconData linux = FilcIconData(0x42);
|
|
||||||
}
|
|
||||||
|
|
||||||
class FilcIconData extends IconData {
|
static const iconFontFamily = 'FilcIcons';
|
||||||
const FilcIconData(int codePoint) : super(codePoint, fontFamily: "FilcIcons");
|
|
||||||
|
/// home
|
||||||
|
static const IconData home = IconData(0x00, fontFamily: iconFontFamily);
|
||||||
|
|
||||||
|
/// linux
|
||||||
|
static const IconData linux = IconData(0x01, fontFamily: iconFontFamily);
|
||||||
|
|
||||||
|
/// upstairs
|
||||||
|
static const IconData upstairs = IconData(0x02, fontFamily: iconFontFamily);
|
||||||
|
|
||||||
|
/// downstairs
|
||||||
|
static const IconData downstairs = IconData(0x03, fontFamily: iconFontFamily);
|
||||||
|
|
||||||
|
/// premium
|
||||||
|
static const IconData premium = IconData(0x04, fontFamily: iconFontFamily);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,12 +32,12 @@ class Startup {
|
|||||||
late DatabaseProvider database;
|
late DatabaseProvider database;
|
||||||
|
|
||||||
Future<void> start() async {
|
Future<void> start() async {
|
||||||
var db = await initDB();
|
|
||||||
await db.close();
|
|
||||||
database = DatabaseProvider();
|
database = DatabaseProvider();
|
||||||
|
var db = await initDB(database);
|
||||||
|
await db.close();
|
||||||
await database.init();
|
await database.init();
|
||||||
settings = await database.query.getSettings();
|
settings = await database.query.getSettings(database);
|
||||||
user = await database.query.getUsers();
|
user = await database.query.getUsers(settings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ Widget errorBuilder(FlutterErrorDetails details) {
|
|||||||
return Builder(builder: (context) {
|
return Builder(builder: (context) {
|
||||||
if (Navigator.of(context).canPop()) Navigator.pop(context);
|
if (Navigator.of(context).canPop()) Navigator.pop(context);
|
||||||
|
|
||||||
WidgetsBinding.instance?.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
if (!errorShown && details.exceptionAsString() != lastException) {
|
if (!errorShown && details.exceptionAsString() != lastException) {
|
||||||
errorShown = true;
|
errorShown = true;
|
||||||
lastException = details.exceptionAsString();
|
lastException = details.exceptionAsString();
|
||||||
|
|||||||
1
filcnaplo/lib/models/icon_pack.dart
Normal file
1
filcnaplo/lib/models/icon_pack.dart
Normal file
@@ -0,0 +1 @@
|
|||||||
|
enum IconPack { material, cupertino }
|
||||||
@@ -1,9 +1,26 @@
|
|||||||
|
class ReleaseDownload {
|
||||||
|
String url;
|
||||||
|
int size;
|
||||||
|
|
||||||
|
ReleaseDownload({
|
||||||
|
required this.url,
|
||||||
|
required this.size,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory ReleaseDownload.fromJson(Map json) {
|
||||||
|
return ReleaseDownload(
|
||||||
|
url: json["browser_download_url"] ?? "",
|
||||||
|
size: json["size"] ?? 0,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class Release {
|
class Release {
|
||||||
String tag;
|
String tag;
|
||||||
Version version;
|
Version version;
|
||||||
String author;
|
String author;
|
||||||
String body;
|
String body;
|
||||||
List<String> downloads;
|
List<ReleaseDownload> downloads;
|
||||||
bool prerelease;
|
bool prerelease;
|
||||||
|
|
||||||
Release({
|
Release({
|
||||||
@@ -20,7 +37,7 @@ class Release {
|
|||||||
tag: json["tag_name"] ?? Version.zero.toString(),
|
tag: json["tag_name"] ?? Version.zero.toString(),
|
||||||
author: json["author"] != null ? json["author"]["login"] ?? "" : "",
|
author: json["author"] != null ? json["author"]["login"] ?? "" : "",
|
||||||
body: json["body"] ?? "",
|
body: json["body"] ?? "",
|
||||||
downloads: json["assets"] != null ? json["assets"].map((a) => a["browser_download_url"] ?? "").toList().cast<String>() : [],
|
downloads: json["assets"] != null ? json["assets"].map((a) => ReleaseDownload.fromJson(a)).toList().cast<ReleaseDownload>() : [],
|
||||||
prerelease: json["prerelease"] ?? false,
|
prerelease: json["prerelease"] ?? false,
|
||||||
version: Version.fromString(json["tag_name"] ?? ""),
|
version: Version.fromString(json["tag_name"] ?? ""),
|
||||||
);
|
);
|
||||||
@@ -127,7 +144,7 @@ class Version {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const zero = Version(0, 0, 0);
|
static const zero = Version(0, 0, 0);
|
||||||
static const List<String> prereleases = ["dev", "pre", "alpha", "beta", "rc"];
|
static const List<String> prereleases = ["dev", "pre", "alpha", "beta", "rc", "nightly", "test"];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode => toString().hashCode;
|
int get hashCode => toString().hashCode;
|
||||||
|
|||||||
@@ -1,17 +1,23 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
import 'package:filcnaplo/api/providers/database_provider.dart';
|
import 'package:filcnaplo/api/providers/database_provider.dart';
|
||||||
import 'package:filcnaplo/models/config.dart';
|
import 'package:filcnaplo/models/config.dart';
|
||||||
import 'package:filcnaplo/theme.dart';
|
import 'package:filcnaplo/models/icon_pack.dart';
|
||||||
|
import 'package:filcnaplo/theme/colors/accent.dart';
|
||||||
|
import 'package:filcnaplo/theme/colors/dark_mobile.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
enum Pages { home, grades, timetable, messages, absences }
|
enum Pages { home, grades, timetable, messages, absences }
|
||||||
|
|
||||||
enum UpdateChannel { stable, beta, dev }
|
enum UpdateChannel { stable, beta, dev }
|
||||||
|
|
||||||
enum VibrationStrength { off, light, medium, strong }
|
enum VibrationStrength { off, light, medium, strong }
|
||||||
|
|
||||||
class SettingsProvider extends ChangeNotifier {
|
class SettingsProvider extends ChangeNotifier {
|
||||||
|
final DatabaseProvider? _database;
|
||||||
|
|
||||||
// en_en, hu_hu, de_de
|
// en_en, hu_hu, de_de
|
||||||
String _language;
|
String _language;
|
||||||
Pages _startPage;
|
Pages _startPage;
|
||||||
@@ -46,8 +52,22 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
UpdateChannel _updateChannel;
|
UpdateChannel _updateChannel;
|
||||||
Config _config;
|
Config _config;
|
||||||
String _xFilcId;
|
String _xFilcId;
|
||||||
|
bool _graphClassAvg;
|
||||||
|
bool _goodStudent;
|
||||||
|
bool _presentationMode;
|
||||||
|
bool _bellDelayEnabled;
|
||||||
|
int _bellDelay;
|
||||||
|
bool _gradeOpeningFun;
|
||||||
|
IconPack _iconPack;
|
||||||
|
Color _customAccentColor;
|
||||||
|
Color _customBackgroundColor;
|
||||||
|
Color _customHighlightColor;
|
||||||
|
List<String> _premiumScopes;
|
||||||
|
String _premiumAccessToken;
|
||||||
|
String _lastAccountId;
|
||||||
|
|
||||||
SettingsProvider({
|
SettingsProvider({
|
||||||
|
DatabaseProvider? database,
|
||||||
required String language,
|
required String language,
|
||||||
required Pages startPage,
|
required Pages startPage,
|
||||||
required int rounding,
|
required int rounding,
|
||||||
@@ -66,7 +86,21 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
required UpdateChannel updateChannel,
|
required UpdateChannel updateChannel,
|
||||||
required Config config,
|
required Config config,
|
||||||
required String xFilcId,
|
required String xFilcId,
|
||||||
}) : _language = language,
|
required bool graphClassAvg,
|
||||||
|
required bool goodStudent,
|
||||||
|
required bool presentationMode,
|
||||||
|
required bool bellDelayEnabled,
|
||||||
|
required int bellDelay,
|
||||||
|
required bool gradeOpeningFun,
|
||||||
|
required IconPack iconPack,
|
||||||
|
required Color customAccentColor,
|
||||||
|
required Color customBackgroundColor,
|
||||||
|
required Color customHighlightColor,
|
||||||
|
required List<String> premiumScopes,
|
||||||
|
required String premiumAccessToken,
|
||||||
|
required String lastAccountId,
|
||||||
|
}) : _database = database,
|
||||||
|
_language = language,
|
||||||
_startPage = startPage,
|
_startPage = startPage,
|
||||||
_rounding = rounding,
|
_rounding = rounding,
|
||||||
_theme = theme,
|
_theme = theme,
|
||||||
@@ -83,10 +117,32 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
_swapABweeks = swapABweeks,
|
_swapABweeks = swapABweeks,
|
||||||
_updateChannel = updateChannel,
|
_updateChannel = updateChannel,
|
||||||
_config = config,
|
_config = config,
|
||||||
_xFilcId = xFilcId;
|
_xFilcId = xFilcId,
|
||||||
|
_graphClassAvg = graphClassAvg,
|
||||||
|
_goodStudent = goodStudent,
|
||||||
|
_presentationMode = presentationMode,
|
||||||
|
_bellDelayEnabled = bellDelayEnabled,
|
||||||
|
_bellDelay = bellDelay,
|
||||||
|
_gradeOpeningFun = gradeOpeningFun,
|
||||||
|
_iconPack = iconPack,
|
||||||
|
_customAccentColor = customAccentColor,
|
||||||
|
_customBackgroundColor = customBackgroundColor,
|
||||||
|
_customHighlightColor = customHighlightColor,
|
||||||
|
_premiumScopes = premiumScopes,
|
||||||
|
_premiumAccessToken = premiumAccessToken,
|
||||||
|
_lastAccountId = lastAccountId;
|
||||||
|
|
||||||
|
factory SettingsProvider.fromMap(Map map, {required DatabaseProvider database}) {
|
||||||
|
Map<String, Object?>? configMap;
|
||||||
|
|
||||||
|
try {
|
||||||
|
configMap = jsonDecode(map["config"] ?? "{}");
|
||||||
|
} catch (e) {
|
||||||
|
log("[ERROR] SettingsProvider.fromMap: $e");
|
||||||
|
}
|
||||||
|
|
||||||
factory SettingsProvider.fromMap(Map map) {
|
|
||||||
return SettingsProvider(
|
return SettingsProvider(
|
||||||
|
database: database,
|
||||||
language: map["language"],
|
language: map["language"],
|
||||||
startPage: Pages.values[map["start_page"]],
|
startPage: Pages.values[map["start_page"]],
|
||||||
rounding: map["rounding"],
|
rounding: map["rounding"],
|
||||||
@@ -99,18 +155,31 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
Color(map["grade_color4"]),
|
Color(map["grade_color4"]),
|
||||||
Color(map["grade_color5"]),
|
Color(map["grade_color5"]),
|
||||||
],
|
],
|
||||||
newsEnabled: map["news"] == 1 ? true : false,
|
newsEnabled: map["news"] == 1,
|
||||||
newsState: map["news_state"],
|
newsState: map["news_state"],
|
||||||
notificationsEnabled: map["notifications"] == 1 ? true : false,
|
notificationsEnabled: map["notifications"] == 1,
|
||||||
notificationsBitfield: map["notifications_bitfield"],
|
notificationsBitfield: map["notifications_bitfield"],
|
||||||
notificationPollInterval: map["notification_poll_interval"],
|
notificationPollInterval: map["notification_poll_interval"],
|
||||||
developerMode: map["developer_mode"] == 1 ? true : false,
|
developerMode: map["developer_mode"] == 1,
|
||||||
vibrate: VibrationStrength.values[map["vibration_strength"]],
|
vibrate: VibrationStrength.values[map["vibration_strength"]],
|
||||||
abWeeks: map["ab_weeks"] == 1 ? true : false,
|
abWeeks: map["ab_weeks"] == 1,
|
||||||
swapABweeks: map["swap_ab_weeks"] == 1 ? true : false,
|
swapABweeks: map["swap_ab_weeks"] == 1,
|
||||||
updateChannel: UpdateChannel.values[map["update_channel"]],
|
updateChannel: UpdateChannel.values[map["update_channel"]],
|
||||||
config: Config.fromJson(jsonDecode(map["config"] ?? "{}")),
|
config: Config.fromJson(configMap ?? {}),
|
||||||
xFilcId: map["x_filc_id"],
|
xFilcId: map["x_filc_id"],
|
||||||
|
graphClassAvg: map["graph_class_avg"] == 1,
|
||||||
|
goodStudent: false,
|
||||||
|
presentationMode: map["presentation_mode"] == 1,
|
||||||
|
bellDelayEnabled: map["bell_delay_enabled"] == 1,
|
||||||
|
bellDelay: map["bell_delay"],
|
||||||
|
gradeOpeningFun: map["grade_opening_fun"] == 1,
|
||||||
|
iconPack: Map.fromEntries(IconPack.values.map((e) => MapEntry(e.name, e)))[map["icon_pack"]]!,
|
||||||
|
customAccentColor: Color(map["custom_accent_color"]),
|
||||||
|
customBackgroundColor: Color(map["custom_background_color"]),
|
||||||
|
customHighlightColor: Color(map["custom_highlight_color"]),
|
||||||
|
premiumScopes: jsonDecode(map["premium_scopes"]).cast<String>(),
|
||||||
|
premiumAccessToken: map["premium_token"],
|
||||||
|
lastAccountId: map["last_account_id"],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,22 +207,35 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
"notification_poll_interval": _notificationPollInterval,
|
"notification_poll_interval": _notificationPollInterval,
|
||||||
"config": jsonEncode(config.json),
|
"config": jsonEncode(config.json),
|
||||||
"x_filc_id": _xFilcId,
|
"x_filc_id": _xFilcId,
|
||||||
|
"graph_class_avg": _graphClassAvg ? 1 : 0,
|
||||||
|
"presentation_mode": _presentationMode ? 1 : 0,
|
||||||
|
"bell_delay_enabled": _bellDelayEnabled ? 1 : 0,
|
||||||
|
"bell_delay": _bellDelay,
|
||||||
|
"grade_opening_fun": _gradeOpeningFun ? 1 : 0,
|
||||||
|
"icon_pack": _iconPack.name,
|
||||||
|
"custom_accent_color": _customAccentColor.value,
|
||||||
|
"custom_background_color": _customBackgroundColor.value,
|
||||||
|
"custom_highlight_color": _customHighlightColor.value,
|
||||||
|
"premium_scopes": jsonEncode(_premiumScopes),
|
||||||
|
"premium_token": _premiumAccessToken,
|
||||||
|
"last_account_id": _lastAccountId,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
factory SettingsProvider.defaultSettings() {
|
factory SettingsProvider.defaultSettings({DatabaseProvider? database}) {
|
||||||
return SettingsProvider(
|
return SettingsProvider(
|
||||||
|
database: database,
|
||||||
language: "hu",
|
language: "hu",
|
||||||
startPage: Pages.home,
|
startPage: Pages.home,
|
||||||
rounding: 5,
|
rounding: 5,
|
||||||
theme: ThemeMode.system,
|
theme: ThemeMode.system,
|
||||||
accentColor: AccentColor.filc,
|
accentColor: AccentColor.filc,
|
||||||
gradeColors: [
|
gradeColors: [
|
||||||
DarkAppColors().red,
|
DarkMobileAppColors().red,
|
||||||
DarkAppColors().orange,
|
DarkMobileAppColors().orange,
|
||||||
DarkAppColors().yellow,
|
DarkMobileAppColors().yellow,
|
||||||
DarkAppColors().green,
|
DarkMobileAppColors().green,
|
||||||
DarkAppColors().filc,
|
DarkMobileAppColors().filc,
|
||||||
],
|
],
|
||||||
newsEnabled: true,
|
newsEnabled: true,
|
||||||
newsState: -1,
|
newsState: -1,
|
||||||
@@ -167,6 +249,19 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
updateChannel: UpdateChannel.stable,
|
updateChannel: UpdateChannel.stable,
|
||||||
config: Config.fromJson({}),
|
config: Config.fromJson({}),
|
||||||
xFilcId: const Uuid().v4(),
|
xFilcId: const Uuid().v4(),
|
||||||
|
graphClassAvg: false,
|
||||||
|
goodStudent: false,
|
||||||
|
presentationMode: false,
|
||||||
|
bellDelayEnabled: false,
|
||||||
|
bellDelay: 0,
|
||||||
|
gradeOpeningFun: true,
|
||||||
|
iconPack: IconPack.cupertino,
|
||||||
|
customAccentColor: const Color(0xff20AC9B),
|
||||||
|
customBackgroundColor: const Color(0xff000000),
|
||||||
|
customHighlightColor: const Color(0xff222222),
|
||||||
|
premiumScopes: [],
|
||||||
|
premiumAccessToken: "",
|
||||||
|
lastAccountId: "",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,10 +284,22 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
UpdateChannel get updateChannel => _updateChannel;
|
UpdateChannel get updateChannel => _updateChannel;
|
||||||
Config get config => _config;
|
Config get config => _config;
|
||||||
String get xFilcId => _xFilcId;
|
String get xFilcId => _xFilcId;
|
||||||
|
bool get graphClassAvg => _graphClassAvg;
|
||||||
|
bool get goodStudent => _goodStudent;
|
||||||
|
bool get presentationMode => _presentationMode;
|
||||||
|
bool get bellDelayEnabled => _bellDelayEnabled;
|
||||||
|
int get bellDelay => _bellDelay;
|
||||||
|
bool get gradeOpeningFun => _gradeOpeningFun;
|
||||||
|
IconPack get iconPack => _iconPack;
|
||||||
|
Color? get customAccentColor => _customAccentColor == accentColorMap[AccentColor.custom] ? null : _customAccentColor;
|
||||||
|
Color? get customBackgroundColor => _customBackgroundColor;
|
||||||
|
Color? get customHighlightColor => _customHighlightColor;
|
||||||
|
List<String> get premiumScopes => _premiumScopes;
|
||||||
|
String get premiumAccessToken => _premiumAccessToken;
|
||||||
|
String get lastAccountId => _lastAccountId;
|
||||||
|
|
||||||
Future<void> update(
|
Future<void> update({
|
||||||
BuildContext context, {
|
bool store = true,
|
||||||
DatabaseProvider? database,
|
|
||||||
String? language,
|
String? language,
|
||||||
Pages? startPage,
|
Pages? startPage,
|
||||||
int? rounding,
|
int? rounding,
|
||||||
@@ -211,6 +318,19 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
UpdateChannel? updateChannel,
|
UpdateChannel? updateChannel,
|
||||||
Config? config,
|
Config? config,
|
||||||
String? xFilcId,
|
String? xFilcId,
|
||||||
|
bool? graphClassAvg,
|
||||||
|
bool? goodStudent,
|
||||||
|
bool? presentationMode,
|
||||||
|
bool? bellDelayEnabled,
|
||||||
|
int? bellDelay,
|
||||||
|
bool? gradeOpeningFun,
|
||||||
|
IconPack? iconPack,
|
||||||
|
Color? customAccentColor,
|
||||||
|
Color? customBackgroundColor,
|
||||||
|
Color? customHighlightColor,
|
||||||
|
List<String>? premiumScopes,
|
||||||
|
String? premiumAccessToken,
|
||||||
|
String? lastAccountId,
|
||||||
}) async {
|
}) async {
|
||||||
if (language != null && language != _language) _language = language;
|
if (language != null && language != _language) _language = language;
|
||||||
if (startPage != null && startPage != _startPage) _startPage = startPage;
|
if (startPage != null && startPage != _startPage) _startPage = startPage;
|
||||||
@@ -232,9 +352,21 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
if (updateChannel != null && updateChannel != _updateChannel) _updateChannel = updateChannel;
|
if (updateChannel != null && updateChannel != _updateChannel) _updateChannel = updateChannel;
|
||||||
if (config != null && config != _config) _config = config;
|
if (config != null && config != _config) _config = config;
|
||||||
if (xFilcId != null && xFilcId != _xFilcId) _xFilcId = xFilcId;
|
if (xFilcId != null && xFilcId != _xFilcId) _xFilcId = xFilcId;
|
||||||
|
if (graphClassAvg != null && graphClassAvg != _graphClassAvg) _graphClassAvg = graphClassAvg;
|
||||||
|
if (goodStudent != null) _goodStudent = goodStudent;
|
||||||
|
if (presentationMode != null && presentationMode != _presentationMode) _presentationMode = presentationMode;
|
||||||
|
if (bellDelay != null && bellDelay != _bellDelay) _bellDelay = bellDelay;
|
||||||
|
if (bellDelayEnabled != null && bellDelayEnabled != _bellDelayEnabled) _bellDelayEnabled = bellDelayEnabled;
|
||||||
|
if (gradeOpeningFun != null && gradeOpeningFun != _gradeOpeningFun) _gradeOpeningFun = gradeOpeningFun;
|
||||||
|
if (iconPack != null && iconPack != _iconPack) _iconPack = iconPack;
|
||||||
|
if (customAccentColor != null && customAccentColor != _customAccentColor) _customAccentColor = customAccentColor;
|
||||||
|
if (customBackgroundColor != null && customBackgroundColor != _customBackgroundColor) _customBackgroundColor = customBackgroundColor;
|
||||||
|
if (customHighlightColor != null && customHighlightColor != _customHighlightColor) _customHighlightColor = customHighlightColor;
|
||||||
|
if (premiumScopes != null && premiumScopes != _premiumScopes) _premiumScopes = premiumScopes;
|
||||||
|
if (premiumAccessToken != null && premiumAccessToken != _premiumAccessToken) _premiumAccessToken = premiumAccessToken;
|
||||||
|
if (lastAccountId != null && lastAccountId != _lastAccountId) _lastAccountId = lastAccountId;
|
||||||
|
|
||||||
database ??= Provider.of<DatabaseProvider>(context, listen: false);
|
if (store) await _database?.store.storeSettings(this);
|
||||||
await database.store.storeSettings(this);
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
31
filcnaplo/lib/models/subject_lesson_count.dart
Normal file
31
filcnaplo/lib/models/subject_lesson_count.dart
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import 'package:filcnaplo_kreta_api/models/category.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/subject.dart';
|
||||||
|
|
||||||
|
enum SubjectLessonCountUpdateState { ready, updating }
|
||||||
|
|
||||||
|
class SubjectLessonCount {
|
||||||
|
DateTime lastUpdated;
|
||||||
|
Map<Subject, int> subjects;
|
||||||
|
SubjectLessonCountUpdateState state;
|
||||||
|
|
||||||
|
SubjectLessonCount({required this.lastUpdated, required this.subjects, this.state = SubjectLessonCountUpdateState.ready});
|
||||||
|
|
||||||
|
factory SubjectLessonCount.fromMap(Map json) {
|
||||||
|
return SubjectLessonCount(
|
||||||
|
lastUpdated: DateTime.fromMillisecondsSinceEpoch(json["last_updated"] ?? 0),
|
||||||
|
subjects: ((json["subjects"] as Map?) ?? {}).map(
|
||||||
|
(key, value) => MapEntry(
|
||||||
|
Subject(id: key, name: "", category: Category.fromJson({})),
|
||||||
|
value,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map toMap() {
|
||||||
|
return {
|
||||||
|
"last_updated": lastUpdated.millisecondsSinceEpoch,
|
||||||
|
"subjects": subjects.map((key, value) => MapEntry(key.id, value)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,6 +13,9 @@ class User {
|
|||||||
String name;
|
String name;
|
||||||
Student student;
|
Student student;
|
||||||
Role role;
|
Role role;
|
||||||
|
String nickname;
|
||||||
|
|
||||||
|
String get displayName => nickname != '' ? nickname : name;
|
||||||
|
|
||||||
User({
|
User({
|
||||||
String? id,
|
String? id,
|
||||||
@@ -22,6 +25,7 @@ class User {
|
|||||||
required this.instituteCode,
|
required this.instituteCode,
|
||||||
required this.student,
|
required this.student,
|
||||||
required this.role,
|
required this.role,
|
||||||
|
this.nickname = "",
|
||||||
}) {
|
}) {
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
@@ -39,6 +43,7 @@ class User {
|
|||||||
name: map["name"].trim(),
|
name: map["name"].trim(),
|
||||||
student: Student.fromJson(jsonDecode(map["student"])),
|
student: Student.fromJson(jsonDecode(map["student"])),
|
||||||
role: Role.values[map["role"] ?? 0],
|
role: Role.values[map["role"] ?? 0],
|
||||||
|
nickname: map["nickname"] ?? "",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,6 +56,7 @@ class User {
|
|||||||
"name": name,
|
"name": name,
|
||||||
"student": jsonEncode(student.json),
|
"student": jsonEncode(student.json),
|
||||||
"role": role.index,
|
"role": role.index,
|
||||||
|
"nickname": nickname,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,4 +76,17 @@ class User {
|
|||||||
"client_id": KretaAPI.clientId,
|
"client_id": KretaAPI.clientId,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Map<String, Object?> refreshBody({
|
||||||
|
required String refreshToken,
|
||||||
|
required String instituteCode,
|
||||||
|
}) {
|
||||||
|
return {
|
||||||
|
"refresh_token": refreshToken,
|
||||||
|
"institute_code": instituteCode,
|
||||||
|
"client_id": KretaAPI.clientId,
|
||||||
|
"grant_type": "refresh_token",
|
||||||
|
"refresh_user_data": "false",
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,173 +0,0 @@
|
|||||||
import 'package:filcnaplo/models/settings.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
|
|
||||||
class AppTheme {
|
|
||||||
// Dev note: All of these could be constant variables, but this is better for
|
|
||||||
// development (you don't have to hot-restart)
|
|
||||||
|
|
||||||
static const String _fontFamily = "Montserrat";
|
|
||||||
|
|
||||||
// Light Theme
|
|
||||||
static ThemeData lightTheme(BuildContext context) {
|
|
||||||
var lightColors = LightAppColors();
|
|
||||||
Color accent = accentColorMap[Provider.of<SettingsProvider>(context, listen: false).accentColor] ?? const Color(0x00000000);
|
|
||||||
return ThemeData(
|
|
||||||
brightness: Brightness.light,
|
|
||||||
fontFamily: _fontFamily,
|
|
||||||
scaffoldBackgroundColor: lightColors.background,
|
|
||||||
backgroundColor: lightColors.highlight,
|
|
||||||
primaryColor: lightColors.filc,
|
|
||||||
dividerColor: const Color(0x00000000),
|
|
||||||
colorScheme: ColorScheme.fromSwatch(
|
|
||||||
accentColor: accent,
|
|
||||||
backgroundColor: lightColors.background,
|
|
||||||
brightness: Brightness.light,
|
|
||||||
cardColor: lightColors.highlight,
|
|
||||||
errorColor: lightColors.red,
|
|
||||||
primaryColorDark: lightColors.filc,
|
|
||||||
primarySwatch: Colors.teal,
|
|
||||||
),
|
|
||||||
shadowColor: lightColors.shadow,
|
|
||||||
appBarTheme: AppBarTheme(backgroundColor: lightColors.background),
|
|
||||||
indicatorColor: accent,
|
|
||||||
iconTheme: IconThemeData(color: lightColors.text.withOpacity(.75)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dark Theme
|
|
||||||
static ThemeData darkTheme(BuildContext context) {
|
|
||||||
var darkColors = DarkAppColors();
|
|
||||||
Color accent = accentColorMap[Provider.of<SettingsProvider>(context, listen: false).accentColor] ?? const Color(0x00000000);
|
|
||||||
return ThemeData(
|
|
||||||
brightness: Brightness.dark,
|
|
||||||
fontFamily: _fontFamily,
|
|
||||||
scaffoldBackgroundColor: darkColors.background,
|
|
||||||
backgroundColor: darkColors.highlight,
|
|
||||||
primaryColor: darkColors.filc,
|
|
||||||
dividerColor: const Color(0x00000000),
|
|
||||||
colorScheme: ColorScheme.fromSwatch(
|
|
||||||
accentColor: accent,
|
|
||||||
backgroundColor: darkColors.background,
|
|
||||||
brightness: Brightness.dark,
|
|
||||||
cardColor: darkColors.highlight,
|
|
||||||
errorColor: darkColors.red,
|
|
||||||
primaryColorDark: darkColors.filc,
|
|
||||||
primarySwatch: Colors.teal,
|
|
||||||
),
|
|
||||||
shadowColor: darkColors.shadow,
|
|
||||||
appBarTheme: AppBarTheme(backgroundColor: darkColors.background),
|
|
||||||
indicatorColor: accent,
|
|
||||||
iconTheme: IconThemeData(color: darkColors.text.withOpacity(.75)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class AppColors {
|
|
||||||
static ThemeAppColors of(BuildContext context) {
|
|
||||||
return Theme.of(context).brightness == Brightness.light ? LightAppColors() : DarkAppColors();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum AccentColor { filc, blue, green, lime, yellow, orange, red, pink, purple }
|
|
||||||
|
|
||||||
Map<AccentColor, Color> accentColorMap = {
|
|
||||||
AccentColor.filc: const Color(0xff20AC9B),
|
|
||||||
AccentColor.blue: Colors.blue.shade300,
|
|
||||||
AccentColor.green: Colors.green.shade300,
|
|
||||||
AccentColor.lime: Colors.lime.shade300,
|
|
||||||
AccentColor.yellow: Colors.yellow.shade300,
|
|
||||||
AccentColor.orange: Colors.deepOrange.shade300,
|
|
||||||
AccentColor.red: Colors.red.shade300,
|
|
||||||
AccentColor.pink: Colors.pink.shade300,
|
|
||||||
AccentColor.purple: Colors.purple.shade300,
|
|
||||||
};
|
|
||||||
|
|
||||||
abstract class ThemeAppColors {
|
|
||||||
final Color shadow = const Color(0x00000000);
|
|
||||||
final Color text = const Color(0x00000000);
|
|
||||||
final Color background = const Color(0x00000000);
|
|
||||||
final Color highlight = const Color(0x00000000);
|
|
||||||
final Color red = const Color(0x00000000);
|
|
||||||
final Color orange = const Color(0x00000000);
|
|
||||||
final Color yellow = const Color(0x00000000);
|
|
||||||
final Color green = const Color(0x00000000);
|
|
||||||
final Color filc = const Color(0x00000000);
|
|
||||||
final Color teal = const Color(0x00000000);
|
|
||||||
final Color blue = const Color(0x00000000);
|
|
||||||
final Color indigo = const Color(0x00000000);
|
|
||||||
final Color purple = const Color(0x00000000);
|
|
||||||
final Color pink = const Color(0x00000000);
|
|
||||||
}
|
|
||||||
|
|
||||||
class LightAppColors implements ThemeAppColors {
|
|
||||||
@override
|
|
||||||
final shadow = const Color(0xffE8E8E8);
|
|
||||||
@override
|
|
||||||
final text = Colors.black;
|
|
||||||
@override
|
|
||||||
final background = const Color(0xffF4F9FF);
|
|
||||||
@override
|
|
||||||
final highlight = const Color(0xffFFFFFF);
|
|
||||||
@override
|
|
||||||
final red = const Color(0xffFF3B30);
|
|
||||||
@override
|
|
||||||
final orange = const Color(0xffFF9500);
|
|
||||||
@override
|
|
||||||
final yellow = const Color(0xffFFCC00);
|
|
||||||
@override
|
|
||||||
final green = const Color(0xff34C759);
|
|
||||||
@override
|
|
||||||
final filc = const Color(0xff247665);
|
|
||||||
@override
|
|
||||||
final teal = const Color(0xff5AC8FA);
|
|
||||||
@override
|
|
||||||
final blue = const Color(0xff007AFF);
|
|
||||||
@override
|
|
||||||
final indigo = const Color(0xff5856D6);
|
|
||||||
@override
|
|
||||||
final purple = const Color(0xffAF52DE);
|
|
||||||
@override
|
|
||||||
final pink = const Color(0xffFF2D55);
|
|
||||||
}
|
|
||||||
|
|
||||||
class DarkAppColors implements ThemeAppColors {
|
|
||||||
@override
|
|
||||||
final shadow = const Color(0x00000000);
|
|
||||||
@override
|
|
||||||
final text = Colors.white;
|
|
||||||
@override
|
|
||||||
final background = const Color(0xff000000);
|
|
||||||
@override
|
|
||||||
final highlight = const Color(0xff141516);
|
|
||||||
@override
|
|
||||||
final red = const Color(0xffFF453A);
|
|
||||||
@override
|
|
||||||
final orange = const Color(0xffFF9F0A);
|
|
||||||
@override
|
|
||||||
final yellow = const Color(0xffFFD60A);
|
|
||||||
@override
|
|
||||||
final green = const Color(0xff32D74B);
|
|
||||||
@override
|
|
||||||
final filc = const Color(0xff29826F);
|
|
||||||
@override
|
|
||||||
final teal = const Color(0xff64D2FF);
|
|
||||||
@override
|
|
||||||
final blue = const Color(0xff0A84FF);
|
|
||||||
@override
|
|
||||||
final indigo = const Color(0xff5E5CE6);
|
|
||||||
@override
|
|
||||||
final purple = const Color(0xffBF5AF2);
|
|
||||||
@override
|
|
||||||
final pink = const Color(0xffFF375F);
|
|
||||||
}
|
|
||||||
|
|
||||||
class ThemeModeObserver extends ChangeNotifier {
|
|
||||||
ThemeMode _themeMode;
|
|
||||||
ThemeMode get themeMode => _themeMode;
|
|
||||||
|
|
||||||
ThemeModeObserver({ThemeMode initialTheme = ThemeMode.system}) : _themeMode = initialTheme;
|
|
||||||
|
|
||||||
void changeTheme(ThemeMode mode) {
|
|
||||||
_themeMode = mode;
|
|
||||||
notifyListeners();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
17
filcnaplo/lib/theme/colors/accent.dart
Normal file
17
filcnaplo/lib/theme/colors/accent.dart
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
enum AccentColor { filc, blue, green, lime, yellow, orange, red, pink, purple, adaptive, custom }
|
||||||
|
|
||||||
|
Map<AccentColor, Color> accentColorMap = {
|
||||||
|
AccentColor.filc: const Color(0xff20AC9B),
|
||||||
|
AccentColor.blue: Colors.blue.shade300,
|
||||||
|
AccentColor.green: Colors.green.shade400,
|
||||||
|
AccentColor.lime: Colors.lightGreen.shade400,
|
||||||
|
AccentColor.yellow: Colors.orange.shade300,
|
||||||
|
AccentColor.orange: Colors.deepOrange.shade300,
|
||||||
|
AccentColor.red: Colors.red.shade300,
|
||||||
|
AccentColor.pink: Colors.pink.shade300,
|
||||||
|
AccentColor.purple: Colors.purple.shade300,
|
||||||
|
AccentColor.adaptive: const Color(0xff20AC9B),
|
||||||
|
AccentColor.custom: const Color(0xff20AC9B),
|
||||||
|
};
|
||||||
46
filcnaplo/lib/theme/colors/colors.dart
Normal file
46
filcnaplo/lib/theme/colors/colors.dart
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:filcnaplo/theme/colors/dark_desktop.dart';
|
||||||
|
import 'package:filcnaplo/theme/colors/dark_mobile.dart';
|
||||||
|
import 'package:filcnaplo/theme/colors/light_desktop.dart';
|
||||||
|
import 'package:filcnaplo/theme/colors/light_mobile.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class AppColors {
|
||||||
|
static ThemeAppColors of(BuildContext context) => fromBrightness(Theme.of(context).brightness);
|
||||||
|
|
||||||
|
static fromBrightness(Brightness brightness) {
|
||||||
|
if (Platform.isAndroid || Platform.isIOS) {
|
||||||
|
switch (brightness) {
|
||||||
|
case Brightness.light:
|
||||||
|
return LightMobileAppColors();
|
||||||
|
case Brightness.dark:
|
||||||
|
return DarkMobileAppColors();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (brightness) {
|
||||||
|
case Brightness.light:
|
||||||
|
return LightDesktopAppColors();
|
||||||
|
case Brightness.dark:
|
||||||
|
return DarkDesktopAppColors();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class ThemeAppColors {
|
||||||
|
final Color shadow = const Color(0x00000000);
|
||||||
|
final Color text = const Color(0x00000000);
|
||||||
|
final Color background = const Color(0x00000000);
|
||||||
|
final Color highlight = const Color(0x00000000);
|
||||||
|
final Color red = const Color(0x00000000);
|
||||||
|
final Color orange = const Color(0x00000000);
|
||||||
|
final Color yellow = const Color(0x00000000);
|
||||||
|
final Color green = const Color(0x00000000);
|
||||||
|
final Color filc = const Color(0x00000000);
|
||||||
|
final Color teal = const Color(0x00000000);
|
||||||
|
final Color blue = const Color(0x00000000);
|
||||||
|
final Color indigo = const Color(0x00000000);
|
||||||
|
final Color purple = const Color(0x00000000);
|
||||||
|
final Color pink = const Color(0x00000000);
|
||||||
|
}
|
||||||
33
filcnaplo/lib/theme/colors/dark_desktop.dart
Normal file
33
filcnaplo/lib/theme/colors/dark_desktop.dart
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import 'package:filcnaplo/theme/colors/colors.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class DarkDesktopAppColors implements ThemeAppColors {
|
||||||
|
@override
|
||||||
|
final shadow = const Color(0x00000000);
|
||||||
|
@override
|
||||||
|
final text = Colors.white;
|
||||||
|
@override
|
||||||
|
final background = const Color.fromARGB(255, 42, 42, 42);
|
||||||
|
@override
|
||||||
|
final highlight = const Color.fromARGB(255, 46, 48, 50);
|
||||||
|
@override
|
||||||
|
final red = const Color(0xffFF453A);
|
||||||
|
@override
|
||||||
|
final orange = const Color(0xffFF9F0A);
|
||||||
|
@override
|
||||||
|
final yellow = const Color(0xffFFD60A);
|
||||||
|
@override
|
||||||
|
final green = const Color(0xff32D74B);
|
||||||
|
@override
|
||||||
|
final filc = const Color(0xff29826F);
|
||||||
|
@override
|
||||||
|
final teal = const Color(0xff64D2FF);
|
||||||
|
@override
|
||||||
|
final blue = const Color(0xff0A84FF);
|
||||||
|
@override
|
||||||
|
final indigo = const Color(0xff5E5CE6);
|
||||||
|
@override
|
||||||
|
final purple = const Color(0xffBF5AF2);
|
||||||
|
@override
|
||||||
|
final pink = const Color(0xffFF375F);
|
||||||
|
}
|
||||||
33
filcnaplo/lib/theme/colors/dark_mobile.dart
Normal file
33
filcnaplo/lib/theme/colors/dark_mobile.dart
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import 'package:filcnaplo/theme/colors/colors.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class DarkMobileAppColors implements ThemeAppColors {
|
||||||
|
@override
|
||||||
|
final shadow = const Color(0x00000000);
|
||||||
|
@override
|
||||||
|
final text = Colors.white;
|
||||||
|
@override
|
||||||
|
final background = const Color(0xff000000);
|
||||||
|
@override
|
||||||
|
final highlight = const Color(0xff141516);
|
||||||
|
@override
|
||||||
|
final red = const Color(0xffFF453A);
|
||||||
|
@override
|
||||||
|
final orange = const Color(0xffFF9F0A);
|
||||||
|
@override
|
||||||
|
final yellow = const Color(0xffFFD60A);
|
||||||
|
@override
|
||||||
|
final green = const Color(0xff32D74B);
|
||||||
|
@override
|
||||||
|
final filc = const Color(0xff29826F);
|
||||||
|
@override
|
||||||
|
final teal = const Color(0xff64D2FF);
|
||||||
|
@override
|
||||||
|
final blue = const Color(0xff0A84FF);
|
||||||
|
@override
|
||||||
|
final indigo = const Color(0xff5E5CE6);
|
||||||
|
@override
|
||||||
|
final purple = const Color(0xffBF5AF2);
|
||||||
|
@override
|
||||||
|
final pink = const Color(0xffFF375F);
|
||||||
|
}
|
||||||
33
filcnaplo/lib/theme/colors/light_desktop.dart
Normal file
33
filcnaplo/lib/theme/colors/light_desktop.dart
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import 'package:filcnaplo/theme/colors/colors.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class LightDesktopAppColors implements ThemeAppColors {
|
||||||
|
@override
|
||||||
|
final shadow = const Color(0xffE8E8E8);
|
||||||
|
@override
|
||||||
|
final text = Colors.black;
|
||||||
|
@override
|
||||||
|
final background = const Color(0xffF4F9FF);
|
||||||
|
@override
|
||||||
|
final highlight = const Color(0xffFFFFFF);
|
||||||
|
@override
|
||||||
|
final red = const Color(0xffFF3B30);
|
||||||
|
@override
|
||||||
|
final orange = const Color(0xffFF9500);
|
||||||
|
@override
|
||||||
|
final yellow = const Color(0xffFFCC00);
|
||||||
|
@override
|
||||||
|
final green = const Color(0xff34C759);
|
||||||
|
@override
|
||||||
|
final filc = const Color(0xff247665);
|
||||||
|
@override
|
||||||
|
final teal = const Color(0xff5AC8FA);
|
||||||
|
@override
|
||||||
|
final blue = const Color(0xff007AFF);
|
||||||
|
@override
|
||||||
|
final indigo = const Color(0xff5856D6);
|
||||||
|
@override
|
||||||
|
final purple = const Color(0xffAF52DE);
|
||||||
|
@override
|
||||||
|
final pink = const Color(0xffFF2D55);
|
||||||
|
}
|
||||||
33
filcnaplo/lib/theme/colors/light_mobile.dart
Normal file
33
filcnaplo/lib/theme/colors/light_mobile.dart
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import 'package:filcnaplo/theme/colors/colors.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class LightMobileAppColors implements ThemeAppColors {
|
||||||
|
@override
|
||||||
|
final shadow = const Color(0xffE8E8E8);
|
||||||
|
@override
|
||||||
|
final text = Colors.black;
|
||||||
|
@override
|
||||||
|
final background = const Color(0xffF4F9FF);
|
||||||
|
@override
|
||||||
|
final highlight = const Color(0xffFFFFFF);
|
||||||
|
@override
|
||||||
|
final red = const Color(0xffFF3B30);
|
||||||
|
@override
|
||||||
|
final orange = const Color(0xffFF9500);
|
||||||
|
@override
|
||||||
|
final yellow = const Color(0xffFFCC00);
|
||||||
|
@override
|
||||||
|
final green = const Color(0xff34C759);
|
||||||
|
@override
|
||||||
|
final filc = const Color(0xff247665);
|
||||||
|
@override
|
||||||
|
final teal = const Color(0xff5AC8FA);
|
||||||
|
@override
|
||||||
|
final blue = const Color(0xff007AFF);
|
||||||
|
@override
|
||||||
|
final indigo = const Color(0xff5856D6);
|
||||||
|
@override
|
||||||
|
final purple = const Color(0xffAF52DE);
|
||||||
|
@override
|
||||||
|
final pink = const Color(0xffFF2D55);
|
||||||
|
}
|
||||||
13
filcnaplo/lib/theme/observer.dart
Normal file
13
filcnaplo/lib/theme/observer.dart
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class ThemeModeObserver extends ChangeNotifier {
|
||||||
|
ThemeMode _themeMode;
|
||||||
|
ThemeMode get themeMode => _themeMode;
|
||||||
|
|
||||||
|
ThemeModeObserver({ThemeMode initialTheme = ThemeMode.system}) : _themeMode = initialTheme;
|
||||||
|
|
||||||
|
void changeTheme(ThemeMode mode) {
|
||||||
|
_themeMode = mode;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
138
filcnaplo/lib/theme/theme.dart
Normal file
138
filcnaplo/lib/theme/theme.dart
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
import 'package:filcnaplo/models/settings.dart';
|
||||||
|
import 'package:filcnaplo/theme/colors/accent.dart';
|
||||||
|
import 'package:filcnaplo/theme/colors/colors.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:material_color_utilities/material_color_utilities.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class AppTheme {
|
||||||
|
// Dev note: All of these could be constant variables, but this is better for
|
||||||
|
// development (you don't have to hot-restart)
|
||||||
|
|
||||||
|
static const String _fontFamily = "Montserrat";
|
||||||
|
|
||||||
|
static Color? _paletteAccentLight(CorePalette? palette) => palette != null ? Color(palette.primary.get(70)) : null;
|
||||||
|
static Color? _paletteHighlightLight(CorePalette? palette) => palette != null ? Color(palette.neutral.get(100)) : null;
|
||||||
|
static Color? _paletteBackgroundLight(CorePalette? palette) => palette != null ? Color(palette.neutral.get(95)) : null;
|
||||||
|
|
||||||
|
static Color? _paletteAccentDark(CorePalette? palette) => palette != null ? Color(palette.primary.get(80)) : null;
|
||||||
|
static Color? _paletteBackgroundDark(CorePalette? palette) => palette != null ? Color(palette.neutralVariant.get(10)) : null;
|
||||||
|
static Color? _paletteHighlightDark(CorePalette? palette) => palette != null ? Color(palette.neutralVariant.get(20)) : null;
|
||||||
|
|
||||||
|
// Light Theme
|
||||||
|
static ThemeData lightTheme(BuildContext context, {CorePalette? palette}) {
|
||||||
|
var lightColors = AppColors.fromBrightness(Brightness.light);
|
||||||
|
final settings = Provider.of<SettingsProvider>(context, listen: false);
|
||||||
|
AccentColor accentColor = settings.accentColor;
|
||||||
|
final customAccentColor = accentColor == AccentColor.custom ? settings.customAccentColor : null;
|
||||||
|
Color accent = customAccentColor ?? accentColorMap[accentColor] ?? const Color(0x00000000);
|
||||||
|
|
||||||
|
if (accentColor == AccentColor.adaptive) {
|
||||||
|
if (palette != null) accent = _paletteAccentLight(palette)!;
|
||||||
|
} else {
|
||||||
|
palette = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color backgroundColor =
|
||||||
|
accentColor == AccentColor.custom ? settings.customBackgroundColor : _paletteBackgroundLight(palette) ?? lightColors.background;
|
||||||
|
Color highlighColor =
|
||||||
|
accentColor == AccentColor.custom ? settings.customHighlightColor : _paletteHighlightLight(palette) ?? lightColors.highlight;
|
||||||
|
|
||||||
|
return ThemeData(
|
||||||
|
brightness: Brightness.light,
|
||||||
|
useMaterial3: false,
|
||||||
|
fontFamily: _fontFamily,
|
||||||
|
scaffoldBackgroundColor: backgroundColor,
|
||||||
|
backgroundColor: highlighColor,
|
||||||
|
primaryColor: lightColors.filc,
|
||||||
|
dividerColor: const Color(0x00000000),
|
||||||
|
colorScheme: ColorScheme.fromSwatch(
|
||||||
|
accentColor: accent,
|
||||||
|
backgroundColor: backgroundColor,
|
||||||
|
brightness: Brightness.light,
|
||||||
|
cardColor: highlighColor,
|
||||||
|
errorColor: lightColors.red,
|
||||||
|
primaryColorDark: lightColors.filc,
|
||||||
|
),
|
||||||
|
shadowColor: highlighColor.withOpacity(.5), //lightColors.shadow,
|
||||||
|
appBarTheme: AppBarTheme(backgroundColor: backgroundColor),
|
||||||
|
indicatorColor: accent,
|
||||||
|
iconTheme: IconThemeData(color: lightColors.text.withOpacity(.75)),
|
||||||
|
navigationBarTheme: NavigationBarThemeData(
|
||||||
|
indicatorColor: accent.withOpacity(accentColor == AccentColor.adaptive ? 0.4 : 0.8),
|
||||||
|
iconTheme: MaterialStateProperty.all(IconThemeData(color: lightColors.text)),
|
||||||
|
backgroundColor: highlighColor,
|
||||||
|
labelTextStyle: MaterialStateProperty.all(TextStyle(
|
||||||
|
fontSize: 13.0,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: lightColors.text.withOpacity(0.8),
|
||||||
|
)),
|
||||||
|
labelBehavior: NavigationDestinationLabelBehavior.alwaysShow,
|
||||||
|
height: 76.0,
|
||||||
|
),
|
||||||
|
sliderTheme: SliderThemeData(
|
||||||
|
inactiveTrackColor: accent.withOpacity(.3),
|
||||||
|
),
|
||||||
|
progressIndicatorTheme: ProgressIndicatorThemeData(color: accent),
|
||||||
|
expansionTileTheme: ExpansionTileThemeData(iconColor: accent),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dark Theme
|
||||||
|
static ThemeData darkTheme(BuildContext context, {CorePalette? palette}) {
|
||||||
|
var darkColors = AppColors.fromBrightness(Brightness.dark);
|
||||||
|
final settings = Provider.of<SettingsProvider>(context, listen: false);
|
||||||
|
AccentColor accentColor = settings.accentColor;
|
||||||
|
final customAccentColor = accentColor == AccentColor.custom ? settings.customAccentColor : null;
|
||||||
|
Color accent = customAccentColor ?? accentColorMap[accentColor] ?? const Color(0x00000000);
|
||||||
|
|
||||||
|
if (accentColor == AccentColor.adaptive) {
|
||||||
|
if (palette != null) accent = _paletteAccentDark(palette)!;
|
||||||
|
} else {
|
||||||
|
palette = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color backgroundColor =
|
||||||
|
accentColor == AccentColor.custom ? settings.customBackgroundColor : _paletteBackgroundDark(palette) ?? darkColors.background;
|
||||||
|
Color highlightColor = accentColor == AccentColor.custom ? settings.customHighlightColor : _paletteHighlightDark(palette) ?? darkColors.highlight;
|
||||||
|
|
||||||
|
return ThemeData(
|
||||||
|
brightness: Brightness.dark,
|
||||||
|
useMaterial3: false,
|
||||||
|
fontFamily: _fontFamily,
|
||||||
|
scaffoldBackgroundColor: backgroundColor,
|
||||||
|
backgroundColor: highlightColor,
|
||||||
|
primaryColor: darkColors.filc,
|
||||||
|
dividerColor: const Color(0x00000000),
|
||||||
|
colorScheme: ColorScheme.fromSwatch(
|
||||||
|
accentColor: accent,
|
||||||
|
backgroundColor: backgroundColor,
|
||||||
|
brightness: Brightness.dark,
|
||||||
|
cardColor: highlightColor,
|
||||||
|
errorColor: darkColors.red,
|
||||||
|
primaryColorDark: darkColors.filc,
|
||||||
|
),
|
||||||
|
shadowColor: highlightColor.withOpacity(.5), //darkColors.shadow,
|
||||||
|
appBarTheme: AppBarTheme(backgroundColor: backgroundColor),
|
||||||
|
indicatorColor: accent,
|
||||||
|
iconTheme: IconThemeData(color: darkColors.text.withOpacity(.75)),
|
||||||
|
navigationBarTheme: NavigationBarThemeData(
|
||||||
|
indicatorColor: accent.withOpacity(accentColor == AccentColor.adaptive ? 0.4 : 0.8),
|
||||||
|
iconTheme: MaterialStateProperty.all(IconThemeData(color: darkColors.text)),
|
||||||
|
backgroundColor: highlightColor,
|
||||||
|
labelTextStyle: MaterialStateProperty.all(TextStyle(
|
||||||
|
fontSize: 13.0,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: darkColors.text.withOpacity(0.8),
|
||||||
|
)),
|
||||||
|
labelBehavior: NavigationDestinationLabelBehavior.alwaysShow,
|
||||||
|
height: 76.0,
|
||||||
|
),
|
||||||
|
sliderTheme: SliderThemeData(
|
||||||
|
inactiveTrackColor: accent.withOpacity(.3),
|
||||||
|
),
|
||||||
|
progressIndicatorTheme: ProgressIndicatorThemeData(color: accent),
|
||||||
|
expansionTileTheme: ExpansionTileThemeData(iconColor: accent),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
8
filcnaplo/lib/ui/date_widget.dart
Normal file
8
filcnaplo/lib/ui/date_widget.dart
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
|
class DateWidget {
|
||||||
|
final DateTime date;
|
||||||
|
final Widget widget;
|
||||||
|
final String? key;
|
||||||
|
const DateWidget({required this.date, required this.widget, this.key});
|
||||||
|
}
|
||||||
159
filcnaplo/lib/ui/filter/sort.dart
Normal file
159
filcnaplo/lib/ui/filter/sort.dart
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
import 'package:filcnaplo/theme/colors/colors.dart';
|
||||||
|
import 'package:filcnaplo/ui/date_widget.dart';
|
||||||
|
import 'package:filcnaplo/ui/filter/widgets.dart';
|
||||||
|
import 'package:filcnaplo/ui/widgets/message/message_tile.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/message.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/common/panel/panel.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/common/widgets/absence/absence_viewable.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/common/widgets/absence_group/absence_group_tile.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:implicitly_animated_reorderable_list/implicitly_animated_reorderable_list.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/common/widgets/lesson/changed_lesson_tile.dart';
|
||||||
|
import 'package:filcnaplo/utils/format.dart';
|
||||||
|
|
||||||
|
// difference.inDays is not reliable
|
||||||
|
bool _sameDate(DateTime a, DateTime b) => (a.year == b.year && a.month == b.month && a.day == b.day);
|
||||||
|
|
||||||
|
List<Widget> sortDateWidgets(
|
||||||
|
BuildContext context, {
|
||||||
|
required List<DateWidget> dateWidgets,
|
||||||
|
bool showTitle = true,
|
||||||
|
bool showDivider = false,
|
||||||
|
bool hasShadow = false,
|
||||||
|
EdgeInsetsGeometry? padding,
|
||||||
|
}) {
|
||||||
|
dateWidgets.sort((a, b) => -a.date.compareTo(b.date));
|
||||||
|
|
||||||
|
List<Conversation> conversations = [];
|
||||||
|
List<DateWidget> convMessages = [];
|
||||||
|
|
||||||
|
// Group messages into conversations
|
||||||
|
for (var w in dateWidgets) {
|
||||||
|
if (w.widget.runtimeType == MessageTile) {
|
||||||
|
Message message = (w.widget as MessageTile).message;
|
||||||
|
|
||||||
|
if (message.conversationId != null) {
|
||||||
|
convMessages.add(w);
|
||||||
|
|
||||||
|
Conversation conv = conversations.firstWhere((e) => e.id == message.conversationId, orElse: () => Conversation(id: message.conversationId!));
|
||||||
|
conv.add(message);
|
||||||
|
if (conv.messages.length == 1) conversations.add(conv);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conversations.any((c) => c.id == message.messageId)) {
|
||||||
|
Conversation conv = conversations.firstWhere((e) => e.id == message.messageId);
|
||||||
|
convMessages.add(w);
|
||||||
|
conv.add(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove individual messages
|
||||||
|
for (var e in convMessages) {
|
||||||
|
dateWidgets.remove(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add conversations
|
||||||
|
for (var conv in conversations) {
|
||||||
|
conv.sort();
|
||||||
|
|
||||||
|
dateWidgets.add(DateWidget(
|
||||||
|
key: "${conv.newest.date.millisecondsSinceEpoch}-msg",
|
||||||
|
date: conv.newest.date,
|
||||||
|
widget: MessageTile(
|
||||||
|
conv.newest,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
dateWidgets.sort((a, b) => -a.date.compareTo(b.date));
|
||||||
|
|
||||||
|
List<List<DateWidget>> groupedDateWidgets = [[]];
|
||||||
|
for (var element in dateWidgets) {
|
||||||
|
if (groupedDateWidgets.last.isNotEmpty) {
|
||||||
|
if (!_sameDate(element.date, groupedDateWidgets.last.last.date)) {
|
||||||
|
groupedDateWidgets.add([element]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
groupedDateWidgets.last.add(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<DateWidget> items = [];
|
||||||
|
|
||||||
|
if (groupedDateWidgets.first.isNotEmpty) {
|
||||||
|
for (var elements in groupedDateWidgets) {
|
||||||
|
bool cst = showTitle;
|
||||||
|
|
||||||
|
// Group Absence Tiles
|
||||||
|
List<DateWidget> absenceTileWidgets = elements.where((element) {
|
||||||
|
return element.widget is AbsenceViewable && (element.widget as AbsenceViewable).absence.delay == 0;
|
||||||
|
}).toList();
|
||||||
|
List<AbsenceViewable> absenceTiles = absenceTileWidgets.map((e) => e.widget as AbsenceViewable).toList();
|
||||||
|
if (absenceTiles.length > 1) {
|
||||||
|
elements.removeWhere((element) => element.widget.runtimeType == AbsenceViewable && (element.widget as AbsenceViewable).absence.delay == 0);
|
||||||
|
if (elements.isEmpty) {
|
||||||
|
cst = false;
|
||||||
|
}
|
||||||
|
elements.add(DateWidget(
|
||||||
|
widget: AbsenceGroupTile(absenceTiles, showDate: !cst),
|
||||||
|
date: absenceTileWidgets.first.date,
|
||||||
|
key: "${absenceTileWidgets.first.date.millisecondsSinceEpoch}-absence-group"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bring Lesson Tiles to front & sort by index asc
|
||||||
|
List<DateWidget> lessonTiles = elements.where((element) {
|
||||||
|
return element.widget.runtimeType == ChangedLessonTile;
|
||||||
|
}).toList();
|
||||||
|
lessonTiles.sort((a, b) => (a.widget as ChangedLessonTile).lesson.lessonIndex.compareTo((b.widget as ChangedLessonTile).lesson.lessonIndex));
|
||||||
|
elements.removeWhere((element) => element.widget.runtimeType == ChangedLessonTile);
|
||||||
|
elements.insertAll(0, lessonTiles);
|
||||||
|
|
||||||
|
final date = (elements + absenceTileWidgets).first.date;
|
||||||
|
items.add(DateWidget(
|
||||||
|
date: date,
|
||||||
|
widget: Panel(
|
||||||
|
key: ValueKey(date),
|
||||||
|
padding: padding ?? const EdgeInsets.symmetric(vertical: 6.0),
|
||||||
|
title: cst ? Text(date.format(context, forceToday: true)) : null,
|
||||||
|
hasShadow: hasShadow,
|
||||||
|
child: ImplicitlyAnimatedList<DateWidget>(
|
||||||
|
areItemsTheSame: (a, b) => a.key == b.key,
|
||||||
|
spawnIsolate: false,
|
||||||
|
shrinkWrap: true,
|
||||||
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
|
itemBuilder: (context, animation, item, index) => filterItemBuilder(context, animation, item.widget, index),
|
||||||
|
items: elements,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final nh = DateTime.now();
|
||||||
|
final now = DateTime(nh.year, nh.month, nh.day).subtract(const Duration(seconds: 1));
|
||||||
|
|
||||||
|
if (showDivider && items.any((i) => i.date.isBefore(now)) && items.any((i) => i.date.isAfter(now))) {
|
||||||
|
items.add(
|
||||||
|
DateWidget(
|
||||||
|
date: now,
|
||||||
|
widget: Center(
|
||||||
|
child: Container(
|
||||||
|
margin: const EdgeInsets.symmetric(vertical: 12.0),
|
||||||
|
height: 3.0,
|
||||||
|
width: 150.0,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(12.0),
|
||||||
|
color: AppColors.of(context).text.withOpacity(.25),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort future dates asc, past dates desc
|
||||||
|
items.sort((a, b) => (a.date.isAfter(now) && b.date.isAfter(now) ? 1 : -1) * a.date.compareTo(b.date));
|
||||||
|
|
||||||
|
return items.map((e) => e.widget).toList();
|
||||||
|
}
|
||||||
179
filcnaplo/lib/ui/filter/widgets.dart
Normal file
179
filcnaplo/lib/ui/filter/widgets.dart
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
import 'package:filcnaplo/api/providers/update_provider.dart';
|
||||||
|
import 'package:filcnaplo/models/settings.dart';
|
||||||
|
import 'package:filcnaplo/ui/date_widget.dart';
|
||||||
|
import 'package:filcnaplo/ui/filter/widgets/grades.dart' as grade_filter;
|
||||||
|
import 'package:filcnaplo/ui/filter/widgets/certifications.dart' as certification_filter;
|
||||||
|
import 'package:filcnaplo/ui/filter/widgets/messages.dart' as message_filter;
|
||||||
|
import 'package:filcnaplo/ui/filter/widgets/absences.dart' as absence_filter;
|
||||||
|
import 'package:filcnaplo/ui/filter/widgets/homework.dart' as homework_filter;
|
||||||
|
import 'package:filcnaplo/ui/filter/widgets/exams.dart' as exam_filter;
|
||||||
|
import 'package:filcnaplo/ui/filter/widgets/notes.dart' as note_filter;
|
||||||
|
import 'package:filcnaplo/ui/filter/widgets/events.dart' as event_filter;
|
||||||
|
import 'package:filcnaplo/ui/filter/widgets/lessons.dart' as lesson_filter;
|
||||||
|
import 'package:filcnaplo/ui/filter/widgets/update.dart' as update_filter;
|
||||||
|
import 'package:filcnaplo/ui/filter/widgets/missed_exams.dart' as missed_exam_filter;
|
||||||
|
import 'package:filcnaplo/ui/filter/widgets/premium.dart' as premium_filter;
|
||||||
|
import 'package:filcnaplo_kreta_api/providers/absence_provider.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/providers/event_provider.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/providers/exam_provider.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/providers/homework_provider.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/providers/message_provider.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/providers/note_provider.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/providers/timetable_provider.dart';
|
||||||
|
import 'package:filcnaplo_premium/providers/premium_provider.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/common/panel/panel.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:implicitly_animated_reorderable_list/transitions.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
const List<FilterType> homeFilters = [FilterType.all, FilterType.grades, FilterType.messages, FilterType.absences];
|
||||||
|
|
||||||
|
enum FilterType { all, grades, newGrades, messages, absences, homework, exams, notes, events, lessons, updates, certifications, missedExams, premium }
|
||||||
|
|
||||||
|
Future<List<DateWidget>> getFilterWidgets(FilterType activeData, {bool absencesNoExcused = false, required BuildContext context}) async {
|
||||||
|
final gradeProvider = Provider.of<GradeProvider>(context);
|
||||||
|
final timetableProvider = Provider.of<TimetableProvider>(context);
|
||||||
|
final messageProvider = Provider.of<MessageProvider>(context);
|
||||||
|
final absenceProvider = Provider.of<AbsenceProvider>(context);
|
||||||
|
final homeworkProvider = Provider.of<HomeworkProvider>(context);
|
||||||
|
final examProvider = Provider.of<ExamProvider>(context);
|
||||||
|
final noteProvider = Provider.of<NoteProvider>(context);
|
||||||
|
final eventProvider = Provider.of<EventProvider>(context);
|
||||||
|
final updateProvider = Provider.of<UpdateProvider>(context);
|
||||||
|
final settingsProvider = Provider.of<SettingsProvider>(context);
|
||||||
|
final premiumProvider = Provider.of<PremiumProvider>(context);
|
||||||
|
|
||||||
|
List<DateWidget> items = [];
|
||||||
|
|
||||||
|
switch (activeData) {
|
||||||
|
// All
|
||||||
|
case FilterType.all:
|
||||||
|
final all = await Future.wait<List<DateWidget>>([
|
||||||
|
getFilterWidgets(FilterType.grades, context: context),
|
||||||
|
getFilterWidgets(FilterType.lessons, context: context),
|
||||||
|
getFilterWidgets(FilterType.messages, context: context),
|
||||||
|
getFilterWidgets(FilterType.absences, context: context, absencesNoExcused: true),
|
||||||
|
getFilterWidgets(FilterType.homework, context: context),
|
||||||
|
getFilterWidgets(FilterType.exams, context: context),
|
||||||
|
getFilterWidgets(FilterType.updates, context: context),
|
||||||
|
getFilterWidgets(FilterType.certifications, context: context),
|
||||||
|
getFilterWidgets(FilterType.missedExams, context: context),
|
||||||
|
getFilterWidgets(FilterType.premium, context: context),
|
||||||
|
]);
|
||||||
|
items = all.expand((x) => x).toList();
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Grades
|
||||||
|
case FilterType.grades:
|
||||||
|
items = grade_filter.getWidgets(gradeProvider.grades, gradeProvider.lastSeenDate);
|
||||||
|
if (settingsProvider.gradeOpeningFun) {
|
||||||
|
items.addAll(await getFilterWidgets(FilterType.newGrades, context: context));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Grades
|
||||||
|
case FilterType.newGrades:
|
||||||
|
items = grade_filter.getNewWidgets(gradeProvider.grades, gradeProvider.lastSeenDate);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Certifications
|
||||||
|
case FilterType.certifications:
|
||||||
|
items = certification_filter.getWidgets(gradeProvider.grades);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Messages
|
||||||
|
case FilterType.messages:
|
||||||
|
items = message_filter.getWidgets(
|
||||||
|
messageProvider.messages,
|
||||||
|
noteProvider.notes,
|
||||||
|
eventProvider.events,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Absences
|
||||||
|
case FilterType.absences:
|
||||||
|
items = absence_filter.getWidgets(absenceProvider.absences, noExcused: absencesNoExcused);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Homework
|
||||||
|
case FilterType.homework:
|
||||||
|
items = homework_filter.getWidgets(homeworkProvider.homework);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Exams
|
||||||
|
case FilterType.exams:
|
||||||
|
items = exam_filter.getWidgets(examProvider.exams);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Notes
|
||||||
|
case FilterType.notes:
|
||||||
|
items = note_filter.getWidgets(noteProvider.notes);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Events
|
||||||
|
case FilterType.events:
|
||||||
|
items = event_filter.getWidgets(eventProvider.events);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Changed Lessons
|
||||||
|
case FilterType.lessons:
|
||||||
|
items = lesson_filter.getWidgets(timetableProvider.lessons);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Updates
|
||||||
|
case FilterType.updates:
|
||||||
|
if (updateProvider.available) items = [update_filter.getWidget(updateProvider.releases.first)];
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Missed Exams
|
||||||
|
case FilterType.missedExams:
|
||||||
|
items = missed_exam_filter.getWidgets(timetableProvider.lessons);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FilterType.premium:
|
||||||
|
final now = DateTime.now();
|
||||||
|
final isWeekend = now.weekday == DateTime.saturday || now.weekday == DateTime.sunday;
|
||||||
|
items = [if (!premiumProvider.hasPremium && isWeekend) premium_filter.getWidget()];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget filterItemBuilder(BuildContext context, Animation<double> animation, Widget item, int index) {
|
||||||
|
final wrappedItem = SizeFadeTransition(
|
||||||
|
curve: Curves.easeInOutCubic,
|
||||||
|
animation: animation,
|
||||||
|
child: item,
|
||||||
|
);
|
||||||
|
return item is Panel
|
||||||
|
// Re-add & animate shadow
|
||||||
|
? AnimatedBuilder(
|
||||||
|
animation: animation,
|
||||||
|
child: wrappedItem,
|
||||||
|
builder: (context, child) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 12.0),
|
||||||
|
child: DecoratedBox(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
offset: const Offset(0, 21),
|
||||||
|
blurRadius: 23.0,
|
||||||
|
color: Theme.of(context).shadowColor.withOpacity(
|
||||||
|
Theme.of(context).shadowColor.opacity *
|
||||||
|
CurvedAnimation(
|
||||||
|
parent: CurvedAnimation(parent: animation, curve: Curves.easeInOutCubic),
|
||||||
|
curve: const Interval(2 / 3, 1.0),
|
||||||
|
).value,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
})
|
||||||
|
: wrappedItem;
|
||||||
|
}
|
||||||
15
filcnaplo/lib/ui/filter/widgets/absences.dart
Normal file
15
filcnaplo/lib/ui/filter/widgets/absences.dart
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import 'package:filcnaplo/ui/date_widget.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/absence.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/common/widgets/absence/absence_viewable.dart' as mobile;
|
||||||
|
|
||||||
|
List<DateWidget> getWidgets(List<Absence> providerAbsences, {bool noExcused = false}) {
|
||||||
|
List<DateWidget> items = [];
|
||||||
|
providerAbsences.where((a) => !noExcused || a.state != Justification.excused).forEach((absence) {
|
||||||
|
items.add(DateWidget(
|
||||||
|
key: absence.id,
|
||||||
|
date: absence.date,
|
||||||
|
widget: mobile.AbsenceViewable(absence),
|
||||||
|
));
|
||||||
|
});
|
||||||
|
return items;
|
||||||
|
}
|
||||||
24
filcnaplo/lib/ui/filter/widgets/certifications.dart
Normal file
24
filcnaplo/lib/ui/filter/widgets/certifications.dart
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import 'package:filcnaplo/ui/date_widget.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/grade.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/common/widgets/cretification/certification_card.dart' as mobile;
|
||||||
|
|
||||||
|
List<DateWidget> getWidgets(List<Grade> providerGrades) {
|
||||||
|
List<DateWidget> items = [];
|
||||||
|
for (var gradeType in GradeType.values) {
|
||||||
|
if ([GradeType.midYear, GradeType.unknown, GradeType.levelExam].contains(gradeType)) continue;
|
||||||
|
|
||||||
|
List<Grade> grades = providerGrades.where((grade) => grade.type == gradeType).toList();
|
||||||
|
if (grades.isNotEmpty) {
|
||||||
|
grades.sort((a, b) => -a.date.compareTo(b.date));
|
||||||
|
|
||||||
|
items.add(DateWidget(
|
||||||
|
date: grades.first.date,
|
||||||
|
widget: mobile.CertificationCard(
|
||||||
|
grades,
|
||||||
|
gradeType: gradeType,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
}
|
||||||
15
filcnaplo/lib/ui/filter/widgets/events.dart
Normal file
15
filcnaplo/lib/ui/filter/widgets/events.dart
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import 'package:filcnaplo/ui/date_widget.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/event.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/common/widgets/event/event_viewable.dart' as mobile;
|
||||||
|
|
||||||
|
List<DateWidget> getWidgets(List<Event> providerEvents) {
|
||||||
|
List<DateWidget> items = [];
|
||||||
|
for (var event in providerEvents) {
|
||||||
|
items.add(DateWidget(
|
||||||
|
key: event.id,
|
||||||
|
date: event.start,
|
||||||
|
widget: mobile.EventViewable(event),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
}
|
||||||
15
filcnaplo/lib/ui/filter/widgets/exams.dart
Normal file
15
filcnaplo/lib/ui/filter/widgets/exams.dart
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import 'package:filcnaplo/ui/date_widget.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/exam.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/common/widgets/exam/exam_viewable.dart' as mobile;
|
||||||
|
|
||||||
|
List<DateWidget> getWidgets(List<Exam> providerExams) {
|
||||||
|
List<DateWidget> items = [];
|
||||||
|
for (var exam in providerExams) {
|
||||||
|
items.add(DateWidget(
|
||||||
|
key: exam.id,
|
||||||
|
date: exam.writeDate.year != 0 ? exam.writeDate : exam.date,
|
||||||
|
widget: mobile.ExamViewable(exam),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
}
|
||||||
41
filcnaplo/lib/ui/filter/widgets/grades.dart
Normal file
41
filcnaplo/lib/ui/filter/widgets/grades.dart
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import 'package:filcnaplo/ui/date_widget.dart';
|
||||||
|
import 'package:filcnaplo/utils/platform.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/grade.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/common/widgets/grade/grade_viewable.dart' as mobile;
|
||||||
|
import 'package:filcnaplo_mobile_ui/common/widgets/grade/new_grades.dart' as mobile;
|
||||||
|
import 'package:filcnaplo_desktop_ui/common/widgets/grade/grade_viewable.dart' as desktop;
|
||||||
|
|
||||||
|
List<DateWidget> getWidgets(List<Grade> providerGrades, DateTime? lastSeenDate) {
|
||||||
|
List<DateWidget> items = [];
|
||||||
|
for (var grade in providerGrades) {
|
||||||
|
final surprise = (!(lastSeenDate != null && grade.date.isAfter(lastSeenDate)) || grade.value.value == 0);
|
||||||
|
if (grade.type == GradeType.midYear && surprise) {
|
||||||
|
items.add(DateWidget(
|
||||||
|
key: grade.id,
|
||||||
|
date: grade.date,
|
||||||
|
widget: PlatformUtils.isMobile ? mobile.GradeViewable(grade) : desktop.GradeViewable(grade),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<DateWidget> getNewWidgets(List<Grade> providerGrades, DateTime? lastSeenDate) {
|
||||||
|
List<DateWidget> items = [];
|
||||||
|
List<Grade> newGrades = [];
|
||||||
|
for (var grade in providerGrades) {
|
||||||
|
final surprise = !(lastSeenDate != null && !grade.date.isAfter(lastSeenDate)) && grade.value.value != 0;
|
||||||
|
if (grade.type == GradeType.midYear && surprise) {
|
||||||
|
newGrades.add(grade);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
newGrades.sort((a, b) => a.date.compareTo(b.date));
|
||||||
|
if (newGrades.isNotEmpty) {
|
||||||
|
items.add(DateWidget(
|
||||||
|
key: newGrades.last.id,
|
||||||
|
date: newGrades.last.date,
|
||||||
|
widget: mobile.NewGradesSurprise(newGrades),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
}
|
||||||
15
filcnaplo/lib/ui/filter/widgets/homework.dart
Normal file
15
filcnaplo/lib/ui/filter/widgets/homework.dart
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import 'package:filcnaplo/ui/date_widget.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/homework.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/common/widgets/homework/homework_viewable.dart' as mobile;
|
||||||
|
|
||||||
|
List<DateWidget> getWidgets(List<Homework> providerHomework) {
|
||||||
|
List<DateWidget> items = [];
|
||||||
|
for (var homework in providerHomework) {
|
||||||
|
items.add(DateWidget(
|
||||||
|
key: homework.id,
|
||||||
|
date: homework.deadline.year != 0 ? homework.deadline : homework.date,
|
||||||
|
widget: mobile.HomeworkViewable(homework),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
}
|
||||||
15
filcnaplo/lib/ui/filter/widgets/lessons.dart
Normal file
15
filcnaplo/lib/ui/filter/widgets/lessons.dart
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import 'package:filcnaplo/ui/date_widget.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/lesson.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/common/widgets/lesson/changed_lesson_viewable.dart' as mobile;
|
||||||
|
|
||||||
|
List<DateWidget> getWidgets(List<Lesson> providerLessons) {
|
||||||
|
List<DateWidget> items = [];
|
||||||
|
providerLessons.where((l) => l.isChanged && l.start.isAfter(DateTime.now())).forEach((lesson) {
|
||||||
|
items.add(DateWidget(
|
||||||
|
key: lesson.id,
|
||||||
|
date: DateTime(lesson.date.year, lesson.date.month, lesson.date.day, lesson.start.hour, lesson.start.minute),
|
||||||
|
widget: mobile.ChangedLessonViewable(lesson),
|
||||||
|
));
|
||||||
|
});
|
||||||
|
return items;
|
||||||
|
}
|
||||||
23
filcnaplo/lib/ui/filter/widgets/messages.dart
Normal file
23
filcnaplo/lib/ui/filter/widgets/messages.dart
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import 'package:filcnaplo/ui/date_widget.dart';
|
||||||
|
import 'package:filcnaplo/ui/filter/widgets/notes.dart' as note_filter;
|
||||||
|
import 'package:filcnaplo/ui/filter/widgets/events.dart' as event_filter;
|
||||||
|
import 'package:filcnaplo_kreta_api/models/event.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/message.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/note.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/common/widgets/message/message_viewable.dart' as mobile;
|
||||||
|
|
||||||
|
List<DateWidget> getWidgets(List<Message> providerMessages, List<Note> providerNotes, List<Event> providerEvents) {
|
||||||
|
List<DateWidget> items = [];
|
||||||
|
for (var message in providerMessages) {
|
||||||
|
if (message.type == MessageType.inbox) {
|
||||||
|
items.add(DateWidget(
|
||||||
|
key: "${message.id}",
|
||||||
|
date: message.date,
|
||||||
|
widget: mobile.MessageViewable(message),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
items.addAll(note_filter.getWidgets(providerNotes));
|
||||||
|
items.addAll(event_filter.getWidgets(providerEvents));
|
||||||
|
return items;
|
||||||
|
}
|
||||||
35
filcnaplo/lib/ui/filter/widgets/missed_exams.dart
Normal file
35
filcnaplo/lib/ui/filter/widgets/missed_exams.dart
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import 'package:filcnaplo/utils/format.dart';
|
||||||
|
import 'package:filcnaplo/ui/date_widget.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/lesson.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/common/widgets/missed_exam/missed_exam_viewable.dart';
|
||||||
|
|
||||||
|
List<DateWidget> getWidgets(List<Lesson> providerLessons) {
|
||||||
|
List<DateWidget> items = [];
|
||||||
|
List<Lesson> missedExams = [];
|
||||||
|
|
||||||
|
for (var lesson in providerLessons) {
|
||||||
|
final desc = lesson.description.toLowerCase().specialChars();
|
||||||
|
// Check if lesson description includes hints for an exam written during the lesson
|
||||||
|
if (!lesson.studentPresence &&
|
||||||
|
(lesson.exam != "" ||
|
||||||
|
desc.contains("dolgozat") ||
|
||||||
|
desc.contains("feleles") ||
|
||||||
|
desc.contains("temazaro") ||
|
||||||
|
desc.contains("szamonkeres") ||
|
||||||
|
desc == "tz") &&
|
||||||
|
!(desc.contains("felkeszules") || desc.contains("gyakorlas"))) {
|
||||||
|
missedExams.add(lesson);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (missedExams.isNotEmpty) {
|
||||||
|
missedExams.sort((a, b) => -a.date.compareTo(b.date));
|
||||||
|
|
||||||
|
items.add(DateWidget(
|
||||||
|
date: missedExams.first.date,
|
||||||
|
widget: MissedExamViewable(missedExams),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return items;
|
||||||
|
}
|
||||||
15
filcnaplo/lib/ui/filter/widgets/notes.dart
Normal file
15
filcnaplo/lib/ui/filter/widgets/notes.dart
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import 'package:filcnaplo/ui/date_widget.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/note.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/common/widgets/note/note_viewable.dart' as mobile;
|
||||||
|
|
||||||
|
List<DateWidget> getWidgets(List<Note> providerNotes) {
|
||||||
|
List<DateWidget> items = [];
|
||||||
|
for (var note in providerNotes) {
|
||||||
|
items.add(DateWidget(
|
||||||
|
key: note.id,
|
||||||
|
date: note.date,
|
||||||
|
widget: mobile.NoteViewable(note),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
}
|
||||||
16
filcnaplo/lib/ui/filter/widgets/premium.dart
Normal file
16
filcnaplo/lib/ui/filter/widgets/premium.dart
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import 'package:filcnaplo/ui/date_widget.dart';
|
||||||
|
import 'package:filcnaplo_premium/ui/mobile/premium/premium_banner_button.dart';
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
|
DateWidget getWidget() {
|
||||||
|
return DateWidget(
|
||||||
|
date: DateTime.now().add(const Duration(minutes: 1)),
|
||||||
|
widget: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 6.0),
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(14.0),
|
||||||
|
child: const PremiumBannerButton(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
10
filcnaplo/lib/ui/filter/widgets/update.dart
Normal file
10
filcnaplo/lib/ui/filter/widgets/update.dart
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import 'package:filcnaplo/models/release.dart';
|
||||||
|
import 'package:filcnaplo/ui/date_widget.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/common/widgets/update/update_viewable.dart' as mobile;
|
||||||
|
|
||||||
|
DateWidget getWidget(Release providerRelease) {
|
||||||
|
return DateWidget(
|
||||||
|
date: DateTime.now(),
|
||||||
|
widget: mobile.UpdateViewable(providerRelease),
|
||||||
|
);
|
||||||
|
}
|
||||||
255
filcnaplo/lib/ui/widgets/grade/grade_tile.dart
Normal file
255
filcnaplo/lib/ui/widgets/grade/grade_tile.dart
Normal file
@@ -0,0 +1,255 @@
|
|||||||
|
import 'package:filcnaplo/models/settings.dart';
|
||||||
|
import 'package:filcnaplo/theme/colors/colors.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/grade.dart';
|
||||||
|
import 'package:filcnaplo/helpers/subject.dart';
|
||||||
|
import 'package:filcnaplo/utils/format.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/pages/grades/calculator/grade_calculator_provider.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/pages/grades/subject_grades_container.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class GradeTile extends StatelessWidget {
|
||||||
|
const GradeTile(this.grade, {Key? key, this.onTap, this.padding}) : super(key: key);
|
||||||
|
|
||||||
|
final Grade grade;
|
||||||
|
final void Function()? onTap;
|
||||||
|
final EdgeInsetsGeometry? padding;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
String title;
|
||||||
|
String subtitle;
|
||||||
|
EdgeInsets leadingPadding = EdgeInsets.zero;
|
||||||
|
bool isSubjectView = SubjectGradesContainer.of(context) != null;
|
||||||
|
String subjectName = grade.subject.name.capital();
|
||||||
|
String modeDescription = grade.mode.description.capital();
|
||||||
|
String description = grade.description.capital();
|
||||||
|
|
||||||
|
GradeCalculatorProvider calculatorProvider = Provider.of<GradeCalculatorProvider>(context, listen: false);
|
||||||
|
|
||||||
|
// Test order:
|
||||||
|
// description
|
||||||
|
// mode
|
||||||
|
// value name
|
||||||
|
if (grade.type == GradeType.midYear || grade.type == GradeType.ghost) {
|
||||||
|
if (grade.description != "") {
|
||||||
|
title = description;
|
||||||
|
} else {
|
||||||
|
title = modeDescription != "" ? modeDescription : grade.value.valueName.split("(")[0];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
title = subjectName;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test order:
|
||||||
|
// subject name
|
||||||
|
// mode + weight != 100
|
||||||
|
if (grade.type == GradeType.midYear) {
|
||||||
|
subtitle = isSubjectView
|
||||||
|
? description != ""
|
||||||
|
? modeDescription
|
||||||
|
: ""
|
||||||
|
: subjectName;
|
||||||
|
} else {
|
||||||
|
subtitle = grade.value.valueName.split("(")[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subtitle != "") leadingPadding = const EdgeInsets.only(top: 2.0);
|
||||||
|
|
||||||
|
return Material(
|
||||||
|
type: MaterialType.transparency,
|
||||||
|
child: Padding(
|
||||||
|
padding: padding ?? const EdgeInsets.symmetric(horizontal: 8.0),
|
||||||
|
child: ListTile(
|
||||||
|
visualDensity: VisualDensity.compact,
|
||||||
|
contentPadding: isSubjectView
|
||||||
|
? grade.type != GradeType.ghost
|
||||||
|
? const EdgeInsets.symmetric(horizontal: 12.0)
|
||||||
|
: const EdgeInsets.only(left: 12.0, right: 4.0)
|
||||||
|
: const EdgeInsets.only(left: 8.0, right: 12.0),
|
||||||
|
onTap: onTap,
|
||||||
|
// onLongPress: kDebugMode ? () => log(jsonEncode(grade.json)) : null,
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(14.0)),
|
||||||
|
leading: isSubjectView
|
||||||
|
? GradeValueWidget(grade.value)
|
||||||
|
: SizedBox(
|
||||||
|
width: 44,
|
||||||
|
height: 44,
|
||||||
|
child: Center(
|
||||||
|
child: Padding(
|
||||||
|
padding: leadingPadding,
|
||||||
|
child: Icon(
|
||||||
|
SubjectIcon.resolveVariant(subject: grade.subject, context: context),
|
||||||
|
size: 28.0,
|
||||||
|
color: AppColors.of(context).text.withOpacity(.75),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
title: Text(
|
||||||
|
title,
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: const TextStyle(fontWeight: FontWeight.w600),
|
||||||
|
),
|
||||||
|
subtitle: subtitle != ""
|
||||||
|
? Text(
|
||||||
|
subtitle,
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: const TextStyle(fontWeight: FontWeight.w500),
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
trailing: isSubjectView
|
||||||
|
? grade.type != GradeType.ghost
|
||||||
|
? Text(grade.date.format(context), style: const TextStyle(fontWeight: FontWeight.w500))
|
||||||
|
: IconButton(
|
||||||
|
splashRadius: 24.0,
|
||||||
|
icon: Icon(FeatherIcons.trash2, color: AppColors.of(context).red),
|
||||||
|
onPressed: () {
|
||||||
|
calculatorProvider.removeGrade(grade);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
: GradeValueWidget(grade.value),
|
||||||
|
minLeadingWidth: isSubjectView ? 32.0 : 0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GradeValueWidget extends StatelessWidget {
|
||||||
|
const GradeValueWidget(
|
||||||
|
this.value, {
|
||||||
|
Key? key,
|
||||||
|
this.size = 38.0,
|
||||||
|
this.fill = false,
|
||||||
|
this.contrast = false,
|
||||||
|
this.shadow = false,
|
||||||
|
this.outline = false,
|
||||||
|
this.complemented = false,
|
||||||
|
this.nocolor = false,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final GradeValue value;
|
||||||
|
final double size;
|
||||||
|
final bool fill;
|
||||||
|
final bool contrast;
|
||||||
|
final bool shadow;
|
||||||
|
final bool outline;
|
||||||
|
final bool complemented;
|
||||||
|
final bool nocolor;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
GradeValue value = Provider.of<SettingsProvider>(context).goodStudent ? GradeValue(5, "Példás", "Példás", this.value.weight) : this.value;
|
||||||
|
bool isSubjectView = SubjectGradesContainer.of(context) != null;
|
||||||
|
|
||||||
|
Color color = gradeColor(context: context, value: value.value, nocolor: nocolor);
|
||||||
|
Widget valueText;
|
||||||
|
final percentage = value.percentage;
|
||||||
|
|
||||||
|
if (percentage) {
|
||||||
|
double multiplier = 1.0;
|
||||||
|
|
||||||
|
if (isSubjectView) multiplier = 0.75;
|
||||||
|
|
||||||
|
valueText = Text.rich(
|
||||||
|
TextSpan(
|
||||||
|
text: value.value.toString(),
|
||||||
|
children: [
|
||||||
|
TextSpan(
|
||||||
|
text: "\n%",
|
||||||
|
style: TextStyle(fontWeight: FontWeight.w700, fontSize: size / 2.5 * multiplier, height: 0.7),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
style: TextStyle(fontWeight: FontWeight.w700, fontSize: size / 1 * multiplier, height: 1),
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
);
|
||||||
|
} else if (value.valueName.toLowerCase().specialChars() == 'nem irt') {
|
||||||
|
valueText = const Icon(FeatherIcons.slash);
|
||||||
|
} else {
|
||||||
|
valueText = Stack(alignment: Alignment.topRight, children: [
|
||||||
|
Transform.translate(
|
||||||
|
offset: (value.weight >= 200) ? const Offset(2, 1.5) : Offset.zero,
|
||||||
|
child: Text(
|
||||||
|
value.value.toString(),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: value.weight == 50 ? FontWeight.w600 : FontWeight.bold,
|
||||||
|
fontSize: size,
|
||||||
|
color: contrast ? Colors.white : color,
|
||||||
|
shadows: [
|
||||||
|
if (value.weight >= 200)
|
||||||
|
Shadow(
|
||||||
|
color: (contrast ? Colors.white : color).withOpacity(.4),
|
||||||
|
offset: const Offset(-4, -3),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (complemented)
|
||||||
|
Transform.translate(
|
||||||
|
offset: const Offset(9, 1),
|
||||||
|
child: Text(
|
||||||
|
"*",
|
||||||
|
style: TextStyle(fontSize: size / 1.6, fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fill
|
||||||
|
? Container(
|
||||||
|
width: size * 1.4,
|
||||||
|
height: size * 1.4,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: color.withOpacity(contrast ? 1.0 : .25),
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
boxShadow: [
|
||||||
|
if (shadow)
|
||||||
|
BoxShadow(
|
||||||
|
color: color,
|
||||||
|
blurRadius: 62.0,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Center(child: valueText),
|
||||||
|
)
|
||||||
|
: valueText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Color gradeColor({required BuildContext context, required num value, bool nocolor = false}) {
|
||||||
|
int valueInt = 0;
|
||||||
|
|
||||||
|
var settings = Provider.of<SettingsProvider>(context, listen: false);
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (value > value.floor() + settings.rounding / 10) {
|
||||||
|
valueInt = value.ceil();
|
||||||
|
} else {
|
||||||
|
valueInt = value.floor();
|
||||||
|
}
|
||||||
|
} catch (_) {}
|
||||||
|
|
||||||
|
if (nocolor) return AppColors.of(context).text;
|
||||||
|
|
||||||
|
switch (valueInt) {
|
||||||
|
case 5:
|
||||||
|
return settings.gradeColors[4];
|
||||||
|
case 4:
|
||||||
|
return settings.gradeColors[3];
|
||||||
|
case 3:
|
||||||
|
return settings.gradeColors[2];
|
||||||
|
case 2:
|
||||||
|
return settings.gradeColors[1];
|
||||||
|
case 1:
|
||||||
|
return settings.gradeColors[0];
|
||||||
|
default:
|
||||||
|
return AppColors.of(context).text;
|
||||||
|
}
|
||||||
|
}
|
||||||
308
filcnaplo/lib/ui/widgets/lesson/lesson_tile.dart
Normal file
308
filcnaplo/lib/ui/widgets/lesson/lesson_tile.dart
Normal file
@@ -0,0 +1,308 @@
|
|||||||
|
import 'package:filcnaplo_kreta_api/providers/exam_provider.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/providers/homework_provider.dart';
|
||||||
|
import 'package:filcnaplo/theme/colors/colors.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/exam.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/homework.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/lesson.dart';
|
||||||
|
import 'package:filcnaplo/utils/format.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/common/panel/panel.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/common/widgets/exam/exam_view.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/common/widgets/homework/homework_view.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'lesson_tile.i18n.dart';
|
||||||
|
|
||||||
|
class LessonTile extends StatelessWidget {
|
||||||
|
const LessonTile(this.lesson, {Key? key, this.onTap, this.swapDesc = false}) : super(key: key);
|
||||||
|
|
||||||
|
final Lesson lesson;
|
||||||
|
final bool swapDesc;
|
||||||
|
final void Function()? onTap;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
List<Widget> subtiles = [];
|
||||||
|
|
||||||
|
Color accent = Theme.of(context).colorScheme.secondary;
|
||||||
|
bool fill = false;
|
||||||
|
bool fillLeading = false;
|
||||||
|
String lessonIndexTrailing = "";
|
||||||
|
|
||||||
|
// Only put a trailing . if its a digit
|
||||||
|
if (RegExp(r'\d').hasMatch(lesson.lessonIndex)) lessonIndexTrailing = ".";
|
||||||
|
|
||||||
|
var now = DateTime.now();
|
||||||
|
if (lesson.start.isBefore(now) && lesson.end.isAfter(now) && lesson.status?.name != "Elmaradt") {
|
||||||
|
fillLeading = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lesson.substituteTeacher != "") {
|
||||||
|
fill = true;
|
||||||
|
accent = AppColors.of(context).yellow;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lesson.status?.name == "Elmaradt") {
|
||||||
|
fill = true;
|
||||||
|
accent = AppColors.of(context).red;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lesson.isEmpty) {
|
||||||
|
accent = AppColors.of(context).text.withOpacity(0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lesson.studentPresence) {
|
||||||
|
subtiles.add(LessonSubtile(
|
||||||
|
type: LessonSubtileType.absence,
|
||||||
|
title: "absence".i18n,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lesson.homeworkId != "") {
|
||||||
|
Homework homework = Provider.of<HomeworkProvider>(context, listen: false)
|
||||||
|
.homework
|
||||||
|
.firstWhere((h) => h.id == lesson.homeworkId, orElse: () => Homework.fromJson({}));
|
||||||
|
|
||||||
|
if (homework.id != "") {
|
||||||
|
subtiles.add(LessonSubtile(
|
||||||
|
type: LessonSubtileType.homework,
|
||||||
|
title: homework.content,
|
||||||
|
onPressed: () => HomeworkView.show(homework, context: context),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lesson.exam != "") {
|
||||||
|
Exam exam = Provider.of<ExamProvider>(context, listen: false).exams.firstWhere((t) => t.id == lesson.exam, orElse: () => Exam.fromJson({}));
|
||||||
|
if (exam.id != "") {
|
||||||
|
subtiles.add(LessonSubtile(
|
||||||
|
type: LessonSubtileType.exam,
|
||||||
|
title: exam.description != "" ? exam.description : exam.mode?.description ?? "exam".i18n,
|
||||||
|
onPressed: () => ExamView.show(exam, context: context),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String description = '';
|
||||||
|
String room = '';
|
||||||
|
|
||||||
|
final cleanDesc = lesson.description.specialChars().toLowerCase().replaceAll(lesson.subject.name.specialChars().toLowerCase(), '');
|
||||||
|
|
||||||
|
if (!swapDesc) {
|
||||||
|
if (cleanDesc != "") {
|
||||||
|
description = lesson.description;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Changed lesson Description
|
||||||
|
if (lesson.isChanged) {
|
||||||
|
if (lesson.status?.name == "Elmaradt") {
|
||||||
|
description = 'cancelled'.i18n;
|
||||||
|
} else if (lesson.substituteTeacher != "") {
|
||||||
|
description = 'substitution'.i18n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
room = lesson.room.replaceAll("_", " ");
|
||||||
|
} else {
|
||||||
|
description = lesson.room.replaceAll("_", " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 2.0),
|
||||||
|
child: Material(
|
||||||
|
color: fill ? accent.withOpacity(.25) : Colors.transparent,
|
||||||
|
borderRadius: BorderRadius.circular(12.0),
|
||||||
|
child: Visibility(
|
||||||
|
visible: lesson.subject.id != '' || lesson.isEmpty,
|
||||||
|
replacement: Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 6.0),
|
||||||
|
child: PanelTitle(title: Text(lesson.name)),
|
||||||
|
),
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.only(bottom: subtiles.isEmpty ? 0.0 : 12.0),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
ListTile(
|
||||||
|
minVerticalPadding: 12.0,
|
||||||
|
dense: true,
|
||||||
|
onTap: onTap,
|
||||||
|
// onLongPress: kDebugMode ? () => log(jsonEncode(lesson.json)) : null,
|
||||||
|
visualDensity: VisualDensity.compact,
|
||||||
|
contentPadding: const EdgeInsets.symmetric(horizontal: 4.0),
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.0)),
|
||||||
|
title: Text(
|
||||||
|
!lesson.isEmpty ? lesson.subject.name.capital() : "empty".i18n,
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
fontSize: 15.5,
|
||||||
|
color: AppColors.of(context).text.withOpacity(!lesson.isEmpty ? 1.0 : 0.5),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
subtitle: description != ""
|
||||||
|
? Text(
|
||||||
|
description,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
fontSize: 14.0,
|
||||||
|
),
|
||||||
|
maxLines: 1,
|
||||||
|
softWrap: false,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
minLeadingWidth: 34.0,
|
||||||
|
leading: AspectRatio(
|
||||||
|
aspectRatio: 1,
|
||||||
|
child: Center(
|
||||||
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
lesson.lessonIndex + lessonIndexTrailing,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 30.0,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: accent,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
// Current lesson indicator
|
||||||
|
Transform.translate(
|
||||||
|
offset: const Offset(-12.0, -2.0),
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: fillLeading ? Theme.of(context).colorScheme.secondary.withOpacity(.3) : const Color(0x00000000),
|
||||||
|
borderRadius: BorderRadius.circular(12.0),
|
||||||
|
boxShadow: [
|
||||||
|
if (fillLeading)
|
||||||
|
BoxShadow(
|
||||||
|
color: Theme.of(context).colorScheme.secondary.withOpacity(.25),
|
||||||
|
blurRadius: 6.0,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
margin: const EdgeInsets.symmetric(vertical: 4.0),
|
||||||
|
width: 4.0,
|
||||||
|
height: double.infinity,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
trailing: !lesson.isEmpty
|
||||||
|
? Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
if (!swapDesc)
|
||||||
|
SizedBox(
|
||||||
|
width: 52.0,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 6.0),
|
||||||
|
child: Text(
|
||||||
|
room,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
maxLines: 2,
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: AppColors.of(context).text.withOpacity(.75),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Stack(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
children: [
|
||||||
|
// Fix alignment hack
|
||||||
|
const Opacity(opacity: 0, child: Text("EE:EE")),
|
||||||
|
Text(
|
||||||
|
"${DateFormat("H:mm").format(lesson.start)}\n${DateFormat("H:mm").format(lesson.end)}",
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: AppColors.of(context).text.withOpacity(.9),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
|
||||||
|
// Homework & Exams
|
||||||
|
...subtiles,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum LessonSubtileType { homework, exam, absence }
|
||||||
|
|
||||||
|
class LessonSubtile extends StatelessWidget {
|
||||||
|
const LessonSubtile({Key? key, this.onPressed, required this.title, required this.type}) : super(key: key);
|
||||||
|
|
||||||
|
final Function()? onPressed;
|
||||||
|
final String title;
|
||||||
|
final LessonSubtileType type;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
IconData icon;
|
||||||
|
Color iconColor = AppColors.of(context).text;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case LessonSubtileType.absence:
|
||||||
|
icon = FeatherIcons.slash;
|
||||||
|
iconColor = AppColors.of(context).red;
|
||||||
|
break;
|
||||||
|
case LessonSubtileType.exam:
|
||||||
|
icon = FeatherIcons.file;
|
||||||
|
break;
|
||||||
|
case LessonSubtileType.homework:
|
||||||
|
icon = FeatherIcons.home;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
||||||
|
child: InkWell(
|
||||||
|
onTap: onPressed,
|
||||||
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 4.0),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Center(
|
||||||
|
child: SizedBox(
|
||||||
|
width: 30.0,
|
||||||
|
child: Icon(icon, color: iconColor.withOpacity(.75), size: 20.0),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 20.0),
|
||||||
|
child: Text(
|
||||||
|
title.escapeHtml(),
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: TextStyle(fontWeight: FontWeight.w500, color: AppColors.of(context).text.withOpacity(.65)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
33
filcnaplo/lib/ui/widgets/lesson/lesson_tile.i18n.dart
Normal file
33
filcnaplo/lib/ui/widgets/lesson/lesson_tile.i18n.dart
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import 'package:i18n_extension/i18n_extension.dart';
|
||||||
|
|
||||||
|
extension Localization on String {
|
||||||
|
static final _t = Translations.byLocale("hu_hu") +
|
||||||
|
{
|
||||||
|
"en_en": {
|
||||||
|
"empty": "Free period",
|
||||||
|
"cancelled": "Cancelled",
|
||||||
|
"substitution": "Substituted",
|
||||||
|
"absence": "You were absent on this lesson",
|
||||||
|
"exam": "Exam"
|
||||||
|
},
|
||||||
|
"hu_hu": {
|
||||||
|
"empty": "Lyukasóra",
|
||||||
|
"cancelled": "Elmarad",
|
||||||
|
"substitution": "Helyettesítés",
|
||||||
|
"absence": "Hiányoztál ezen az órán",
|
||||||
|
"exam": "Dolgozat"
|
||||||
|
},
|
||||||
|
"de_de": {
|
||||||
|
"empty": "Springstunde",
|
||||||
|
"cancelled": "Abgesagte",
|
||||||
|
"substitution": "Vertretene",
|
||||||
|
"absence": "Sie waren in dieser Lektion nicht anwesend",
|
||||||
|
"exam": "Prüfung"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
String get i18n => localize(this, _t);
|
||||||
|
String fill(List<Object> params) => localizeFill(this, params);
|
||||||
|
String plural(int value) => localizePlural(value, this, _t);
|
||||||
|
String version(Object modifier) => localizeVersion(modifier, this, _t);
|
||||||
|
}
|
||||||
78
filcnaplo/lib/ui/widgets/message/message_tile.dart
Normal file
78
filcnaplo/lib/ui/widgets/message/message_tile.dart
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
import 'package:filcnaplo/models/settings.dart';
|
||||||
|
import 'package:filcnaplo/theme/colors/colors.dart';
|
||||||
|
import 'package:filcnaplo/utils/color.dart';
|
||||||
|
import 'package:filcnaplo/utils/format.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/message.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/common/profile_image/profile_image.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class MessageTile extends StatelessWidget {
|
||||||
|
const MessageTile(
|
||||||
|
this.message, {
|
||||||
|
Key? key,
|
||||||
|
this.messages,
|
||||||
|
this.padding,
|
||||||
|
this.onTap,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final Message message;
|
||||||
|
final List<Message>? messages;
|
||||||
|
final EdgeInsetsGeometry? padding;
|
||||||
|
final Function()? onTap;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Material(
|
||||||
|
type: MaterialType.transparency,
|
||||||
|
child: Padding(
|
||||||
|
padding: padding ?? const EdgeInsets.symmetric(horizontal: 8.0),
|
||||||
|
child: ListTile(
|
||||||
|
onTap: onTap,
|
||||||
|
visualDensity: VisualDensity.compact,
|
||||||
|
contentPadding: const EdgeInsets.only(left: 8.0, right: 4.0),
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(14.0)),
|
||||||
|
leading: !Provider.of<SettingsProvider>(context, listen: false).presentationMode
|
||||||
|
? ProfileImage(
|
||||||
|
name: message.author,
|
||||||
|
radius: 22.0,
|
||||||
|
backgroundColor: ColorUtils.stringToColor(message.author),
|
||||||
|
)
|
||||||
|
: ProfileImage(
|
||||||
|
name: "Béla",
|
||||||
|
radius: 22.0,
|
||||||
|
backgroundColor: Theme.of(context).colorScheme.secondary,
|
||||||
|
),
|
||||||
|
title: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
!Provider.of<SettingsProvider>(context, listen: false).presentationMode ? message.author : "Béla",
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: const TextStyle(fontWeight: FontWeight.w600, fontSize: 15.5),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (message.attachments.isNotEmpty) const Icon(FeatherIcons.paperclip, size: 16.0)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
subtitle: Text(
|
||||||
|
message.subject,
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: const TextStyle(fontWeight: FontWeight.w500, fontSize: 14.0),
|
||||||
|
),
|
||||||
|
trailing: Text(
|
||||||
|
message.date.format(context),
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
fontSize: 14.0,
|
||||||
|
color: AppColors.of(context).text.withOpacity(.75),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:filcnaplo_kreta_api/models/week.dart';
|
import 'package:filcnaplo_kreta_api/models/week.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
@@ -27,7 +29,12 @@ extension StringFormatUtils on String {
|
|||||||
htmlString = htmlString.replaceAll(RegExp(r'<p ?>'), "");
|
htmlString = htmlString.replaceAll(RegExp(r'<p ?>'), "");
|
||||||
htmlString = htmlString.replaceAll(RegExp(r'</p ?>'), "\n");
|
htmlString = htmlString.replaceAll(RegExp(r'</p ?>'), "\n");
|
||||||
var document = parse(htmlString);
|
var document = parse(htmlString);
|
||||||
return document.body?.text.trim() ?? "";
|
return document.body?.text.trim() ?? htmlString;
|
||||||
|
}
|
||||||
|
|
||||||
|
String limit(int max) {
|
||||||
|
if (length <= max) return this;
|
||||||
|
return '${substring(0, min(length, 14))}…';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
6
filcnaplo/lib/utils/platform.dart
Normal file
6
filcnaplo/lib/utils/platform.dart
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
class PlatformUtils {
|
||||||
|
static bool get isDesktop => Platform.isWindows || Platform.isMacOS || Platform.isLinux;
|
||||||
|
static bool get isMobile => !isDesktop;
|
||||||
|
}
|
||||||
37
filcnaplo/lib/utils/reverse_search.dart
Normal file
37
filcnaplo/lib/utils/reverse_search.dart
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
|
import 'package:filcnaplo_kreta_api/models/absence.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/lesson.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/week.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/providers/timetable_provider.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class ReverseSearch {
|
||||||
|
static Future<Lesson?> getLessonByAbsence(Absence absence, BuildContext context) async {
|
||||||
|
final timetableProvider = Provider.of<TimetableProvider>(context, listen: false);
|
||||||
|
|
||||||
|
List<Lesson> lessons = [];
|
||||||
|
try {
|
||||||
|
await timetableProvider.fetch(week: Week.fromDate(absence.date), db: false);
|
||||||
|
} catch (e) {
|
||||||
|
log("[ERROR] getLessonByAbsence: $e");
|
||||||
|
}
|
||||||
|
lessons = timetableProvider.lessons;
|
||||||
|
|
||||||
|
// Find absence lesson in timetable
|
||||||
|
Lesson lesson = lessons.firstWhere(
|
||||||
|
(l) => _sameDate(l.date, absence.date) && l.subject.id == absence.subject.id && l.lessonIndex == absence.lessonIndex.toString(),
|
||||||
|
orElse: () => Lesson.fromJson({'isEmpty': true}),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (lesson.isEmpty) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return lesson;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// difference.inDays is not reliable
|
||||||
|
static bool _sameDate(DateTime a, DateTime b) => (a.year == b.year && a.month == b.month && a.day == b.day);
|
||||||
|
}
|
||||||
@@ -6,9 +6,17 @@
|
|||||||
|
|
||||||
#include "generated_plugin_registrant.h"
|
#include "generated_plugin_registrant.h"
|
||||||
|
|
||||||
|
#include <dynamic_color/dynamic_color_plugin.h>
|
||||||
|
#include <flutter_acrylic/flutter_acrylic_plugin.h>
|
||||||
#include <url_launcher_linux/url_launcher_plugin.h>
|
#include <url_launcher_linux/url_launcher_plugin.h>
|
||||||
|
|
||||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||||
|
g_autoptr(FlPluginRegistrar) dynamic_color_registrar =
|
||||||
|
fl_plugin_registry_get_registrar_for_plugin(registry, "DynamicColorPlugin");
|
||||||
|
dynamic_color_plugin_register_with_registrar(dynamic_color_registrar);
|
||||||
|
g_autoptr(FlPluginRegistrar) flutter_acrylic_registrar =
|
||||||
|
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterAcrylicPlugin");
|
||||||
|
flutter_acrylic_plugin_register_with_registrar(flutter_acrylic_registrar);
|
||||||
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
|
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
|
||||||
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
|
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
|
||||||
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
|
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
|
||||||
|
|||||||
@@ -3,9 +3,14 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
|
dynamic_color
|
||||||
|
flutter_acrylic
|
||||||
url_launcher_linux
|
url_launcher_linux
|
||||||
)
|
)
|
||||||
|
|
||||||
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
|
)
|
||||||
|
|
||||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||||
|
|
||||||
foreach(plugin ${FLUTTER_PLUGIN_LIST})
|
foreach(plugin ${FLUTTER_PLUGIN_LIST})
|
||||||
@@ -14,3 +19,8 @@ foreach(plugin ${FLUTTER_PLUGIN_LIST})
|
|||||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
|
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
|
||||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
|
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
|
||||||
endforeach(plugin)
|
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)
|
||||||
|
|||||||
7
filcnaplo/macos/.gitignore
vendored
Normal file
7
filcnaplo/macos/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# Flutter-related
|
||||||
|
**/Flutter/ephemeral/
|
||||||
|
**/Pods/
|
||||||
|
|
||||||
|
# Xcode-related
|
||||||
|
**/dgph
|
||||||
|
**/xcuserdata/
|
||||||
2
filcnaplo/macos/Flutter/Flutter-Debug.xcconfig
Normal file
2
filcnaplo/macos/Flutter/Flutter-Debug.xcconfig
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
|
||||||
|
#include "ephemeral/Flutter-Generated.xcconfig"
|
||||||
2
filcnaplo/macos/Flutter/Flutter-Release.xcconfig
Normal file
2
filcnaplo/macos/Flutter/Flutter-Release.xcconfig
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
|
||||||
|
#include "ephemeral/Flutter-Generated.xcconfig"
|
||||||
24
filcnaplo/macos/Flutter/GeneratedPluginRegistrant.swift
Normal file
24
filcnaplo/macos/Flutter/GeneratedPluginRegistrant.swift
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
//
|
||||||
|
// Generated file. Do not edit.
|
||||||
|
//
|
||||||
|
|
||||||
|
import FlutterMacOS
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
import connectivity_plus
|
||||||
|
import dynamic_color
|
||||||
|
import flutter_acrylic
|
||||||
|
import path_provider_macos
|
||||||
|
import share_plus_macos
|
||||||
|
import sqflite
|
||||||
|
import url_launcher_macos
|
||||||
|
|
||||||
|
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||||
|
ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin"))
|
||||||
|
DynamicColorPlugin.register(with: registry.registrar(forPlugin: "DynamicColorPlugin"))
|
||||||
|
FlutterAcrylicPlugin.register(with: registry.registrar(forPlugin: "FlutterAcrylicPlugin"))
|
||||||
|
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||||
|
SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
|
||||||
|
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
||||||
|
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
||||||
|
}
|
||||||
40
filcnaplo/macos/Podfile
Normal file
40
filcnaplo/macos/Podfile
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
platform :osx, '10.11'
|
||||||
|
|
||||||
|
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||||
|
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||||
|
|
||||||
|
project 'Runner', {
|
||||||
|
'Debug' => :debug,
|
||||||
|
'Profile' => :release,
|
||||||
|
'Release' => :release,
|
||||||
|
}
|
||||||
|
|
||||||
|
def flutter_root
|
||||||
|
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__)
|
||||||
|
unless File.exist?(generated_xcode_build_settings_path)
|
||||||
|
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first"
|
||||||
|
end
|
||||||
|
|
||||||
|
File.foreach(generated_xcode_build_settings_path) do |line|
|
||||||
|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
|
||||||
|
return matches[1].strip if matches
|
||||||
|
end
|
||||||
|
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\""
|
||||||
|
end
|
||||||
|
|
||||||
|
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
|
||||||
|
|
||||||
|
flutter_macos_podfile_setup
|
||||||
|
|
||||||
|
target 'Runner' do
|
||||||
|
use_frameworks!
|
||||||
|
use_modular_headers!
|
||||||
|
|
||||||
|
flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__))
|
||||||
|
end
|
||||||
|
|
||||||
|
post_install do |installer|
|
||||||
|
installer.pods_project.targets.each do |target|
|
||||||
|
flutter_additional_macos_build_settings(target)
|
||||||
|
end
|
||||||
|
end
|
||||||
83
filcnaplo/macos/Podfile.lock
Normal file
83
filcnaplo/macos/Podfile.lock
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
PODS:
|
||||||
|
- connectivity_plus_macos (0.0.1):
|
||||||
|
- FlutterMacOS
|
||||||
|
- ReachabilitySwift
|
||||||
|
- dynamic_color (0.0.2):
|
||||||
|
- FlutterMacOS
|
||||||
|
- flutter_acrylic (0.1.0):
|
||||||
|
- FlutterMacOS
|
||||||
|
- flutter_local_notifications (0.0.1):
|
||||||
|
- FlutterMacOS
|
||||||
|
- FlutterMacOS (1.0.0)
|
||||||
|
- FMDB (2.7.5):
|
||||||
|
- FMDB/standard (= 2.7.5)
|
||||||
|
- FMDB/standard (2.7.5)
|
||||||
|
- path_provider_macos (0.0.1):
|
||||||
|
- FlutterMacOS
|
||||||
|
- ReachabilitySwift (5.0.0)
|
||||||
|
- share_plus_macos (0.0.1):
|
||||||
|
- FlutterMacOS
|
||||||
|
- shared_preferences_macos (0.0.1):
|
||||||
|
- FlutterMacOS
|
||||||
|
- sqflite (0.0.2):
|
||||||
|
- FlutterMacOS
|
||||||
|
- FMDB (>= 2.7.5)
|
||||||
|
- url_launcher_macos (0.0.1):
|
||||||
|
- FlutterMacOS
|
||||||
|
|
||||||
|
DEPENDENCIES:
|
||||||
|
- connectivity_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/connectivity_plus_macos/macos`)
|
||||||
|
- dynamic_color (from `Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos`)
|
||||||
|
- flutter_acrylic (from `Flutter/ephemeral/.symlinks/plugins/flutter_acrylic/macos`)
|
||||||
|
- flutter_local_notifications (from `Flutter/ephemeral/.symlinks/plugins/flutter_local_notifications/macos`)
|
||||||
|
- FlutterMacOS (from `Flutter/ephemeral`)
|
||||||
|
- path_provider_macos (from `Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos`)
|
||||||
|
- share_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/share_plus_macos/macos`)
|
||||||
|
- shared_preferences_macos (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_macos/macos`)
|
||||||
|
- sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/macos`)
|
||||||
|
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
|
||||||
|
|
||||||
|
SPEC REPOS:
|
||||||
|
trunk:
|
||||||
|
- FMDB
|
||||||
|
- ReachabilitySwift
|
||||||
|
|
||||||
|
EXTERNAL SOURCES:
|
||||||
|
connectivity_plus_macos:
|
||||||
|
:path: Flutter/ephemeral/.symlinks/plugins/connectivity_plus_macos/macos
|
||||||
|
dynamic_color:
|
||||||
|
:path: Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos
|
||||||
|
flutter_acrylic:
|
||||||
|
:path: Flutter/ephemeral/.symlinks/plugins/flutter_acrylic/macos
|
||||||
|
flutter_local_notifications:
|
||||||
|
:path: Flutter/ephemeral/.symlinks/plugins/flutter_local_notifications/macos
|
||||||
|
FlutterMacOS:
|
||||||
|
:path: Flutter/ephemeral
|
||||||
|
path_provider_macos:
|
||||||
|
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos
|
||||||
|
share_plus_macos:
|
||||||
|
:path: Flutter/ephemeral/.symlinks/plugins/share_plus_macos/macos
|
||||||
|
shared_preferences_macos:
|
||||||
|
:path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_macos/macos
|
||||||
|
sqflite:
|
||||||
|
:path: Flutter/ephemeral/.symlinks/plugins/sqflite/macos
|
||||||
|
url_launcher_macos:
|
||||||
|
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
|
||||||
|
|
||||||
|
SPEC CHECKSUMS:
|
||||||
|
connectivity_plus_macos: f6e86fd000e971d361e54b5afcadc8c8fa773308
|
||||||
|
dynamic_color: 394d6a888650f8534e029b27d2f8bc5c64e44008
|
||||||
|
flutter_acrylic: c3df24ae52ab6597197837ce59ef2a8542640c17
|
||||||
|
flutter_local_notifications: 3805ca215b2fb7f397d78b66db91f6a747af52e4
|
||||||
|
FlutterMacOS: ae6af50a8ea7d6103d888583d46bd8328a7e9811
|
||||||
|
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
|
||||||
|
path_provider_macos: 3c0c3b4b0d4a76d2bf989a913c2de869c5641a19
|
||||||
|
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
|
||||||
|
share_plus_macos: 853ee48e7dce06b633998ca0735d482dd671ade4
|
||||||
|
shared_preferences_macos: a64dc611287ed6cbe28fd1297898db1336975727
|
||||||
|
sqflite: a5789cceda41d54d23f31d6de539d65bb14100ea
|
||||||
|
url_launcher_macos: 597e05b8e514239626bcf4a850fcf9ef5c856ec3
|
||||||
|
|
||||||
|
PODFILE CHECKSUM: 6eac6b3292e5142cfc23bdeb71848a40ec51c14c
|
||||||
|
|
||||||
|
COCOAPODS: 1.11.3
|
||||||
669
filcnaplo/macos/Runner.xcodeproj/project.pbxproj
Normal file
669
filcnaplo/macos/Runner.xcodeproj/project.pbxproj
Normal file
@@ -0,0 +1,669 @@
|
|||||||
|
// !$*UTF8*$!
|
||||||
|
{
|
||||||
|
archiveVersion = 1;
|
||||||
|
classes = {
|
||||||
|
};
|
||||||
|
objectVersion = 51;
|
||||||
|
objects = {
|
||||||
|
|
||||||
|
/* Begin PBXAggregateTarget section */
|
||||||
|
33CC111A2044C6BA0003C045 /* Flutter Assemble */ = {
|
||||||
|
isa = PBXAggregateTarget;
|
||||||
|
buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */;
|
||||||
|
buildPhases = (
|
||||||
|
33CC111E2044C6BF0003C045 /* ShellScript */,
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
);
|
||||||
|
name = "Flutter Assemble";
|
||||||
|
productName = FLX;
|
||||||
|
};
|
||||||
|
/* End PBXAggregateTarget section */
|
||||||
|
|
||||||
|
/* Begin PBXBuildFile section */
|
||||||
|
335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; };
|
||||||
|
33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; };
|
||||||
|
33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
|
||||||
|
33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
|
||||||
|
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
|
||||||
|
43DE217EE63035454211B258 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8BB026B00EBE728C695C538A /* Pods_Runner.framework */; };
|
||||||
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
|
/* Begin PBXContainerItemProxy section */
|
||||||
|
33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = {
|
||||||
|
isa = PBXContainerItemProxy;
|
||||||
|
containerPortal = 33CC10E52044A3C60003C045 /* Project object */;
|
||||||
|
proxyType = 1;
|
||||||
|
remoteGlobalIDString = 33CC111A2044C6BA0003C045;
|
||||||
|
remoteInfo = FLX;
|
||||||
|
};
|
||||||
|
/* End PBXContainerItemProxy section */
|
||||||
|
|
||||||
|
/* Begin PBXCopyFilesBuildPhase section */
|
||||||
|
33CC110E2044A8840003C045 /* Bundle Framework */ = {
|
||||||
|
isa = PBXCopyFilesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
dstPath = "";
|
||||||
|
dstSubfolderSpec = 10;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
name = "Bundle Framework";
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXCopyFilesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXFileReference section */
|
||||||
|
333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = "<group>"; };
|
||||||
|
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = "<group>"; };
|
||||||
|
33CC10ED2044A3C60003C045 /* Felt Diary.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Felt Diary.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
|
33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = "<group>"; };
|
||||||
|
33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
|
||||||
|
33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = "<group>"; };
|
||||||
|
33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = "<group>"; };
|
||||||
|
33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = "<group>"; };
|
||||||
|
33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = "<group>"; };
|
||||||
|
33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = "<group>"; };
|
||||||
|
72E0977D2D8959666A33F54C /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
|
||||||
|
8BB026B00EBE728C695C538A /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
|
||||||
|
9C848561CA407DAFCC1F5699 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
C200D9112D0A790C324733AA /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
33CC10EA2044A3C60003C045 /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
43DE217EE63035454211B258 /* Pods_Runner.framework in Frameworks */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXGroup section */
|
||||||
|
33BA886A226E78AF003329D5 /* Configs */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
33E5194F232828860026EE4D /* AppInfo.xcconfig */,
|
||||||
|
9740EEB21CF90195004384FC /* Debug.xcconfig */,
|
||||||
|
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
|
||||||
|
333000ED22D3DE5D00554162 /* Warnings.xcconfig */,
|
||||||
|
);
|
||||||
|
path = Configs;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
33CC10E42044A3C60003C045 = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
33FAB671232836740065AC1E /* Runner */,
|
||||||
|
33CEB47122A05771004F2AC0 /* Flutter */,
|
||||||
|
33CC10EE2044A3C60003C045 /* Products */,
|
||||||
|
51085A7CB06D107E9E0B55D2 /* Pods */,
|
||||||
|
D1EA9707C367C55447080BD3 /* Frameworks */,
|
||||||
|
);
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
33CC10EE2044A3C60003C045 /* Products */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
33CC10ED2044A3C60003C045 /* Felt Diary.app */,
|
||||||
|
);
|
||||||
|
name = Products;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
33CC11242044D66E0003C045 /* Resources */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
33CC10F22044A3C60003C045 /* Assets.xcassets */,
|
||||||
|
33CC10F42044A3C60003C045 /* MainMenu.xib */,
|
||||||
|
33CC10F72044A3C60003C045 /* Info.plist */,
|
||||||
|
);
|
||||||
|
name = Resources;
|
||||||
|
path = ..;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
33CEB47122A05771004F2AC0 /* Flutter */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */,
|
||||||
|
33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */,
|
||||||
|
33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */,
|
||||||
|
33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */,
|
||||||
|
);
|
||||||
|
path = Flutter;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
33FAB671232836740065AC1E /* Runner */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
33CC10F02044A3C60003C045 /* AppDelegate.swift */,
|
||||||
|
33CC11122044BFA00003C045 /* MainFlutterWindow.swift */,
|
||||||
|
33E51913231747F40026EE4D /* DebugProfile.entitlements */,
|
||||||
|
33E51914231749380026EE4D /* Release.entitlements */,
|
||||||
|
33CC11242044D66E0003C045 /* Resources */,
|
||||||
|
33BA886A226E78AF003329D5 /* Configs */,
|
||||||
|
);
|
||||||
|
path = Runner;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
51085A7CB06D107E9E0B55D2 /* Pods */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
72E0977D2D8959666A33F54C /* Pods-Runner.debug.xcconfig */,
|
||||||
|
C200D9112D0A790C324733AA /* Pods-Runner.release.xcconfig */,
|
||||||
|
9C848561CA407DAFCC1F5699 /* Pods-Runner.profile.xcconfig */,
|
||||||
|
);
|
||||||
|
path = Pods;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
D1EA9707C367C55447080BD3 /* Frameworks */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
8BB026B00EBE728C695C538A /* Pods_Runner.framework */,
|
||||||
|
);
|
||||||
|
name = Frameworks;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
/* End PBXGroup section */
|
||||||
|
|
||||||
|
/* Begin PBXNativeTarget section */
|
||||||
|
33CC10EC2044A3C60003C045 /* Runner */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||||
|
buildPhases = (
|
||||||
|
FD4539A7C90013601C734851 /* [CP] Check Pods Manifest.lock */,
|
||||||
|
33CC10E92044A3C60003C045 /* Sources */,
|
||||||
|
33CC10EA2044A3C60003C045 /* Frameworks */,
|
||||||
|
33CC10EB2044A3C60003C045 /* Resources */,
|
||||||
|
33CC110E2044A8840003C045 /* Bundle Framework */,
|
||||||
|
3399D490228B24CF009A79C7 /* ShellScript */,
|
||||||
|
558B4163B66FBD35BF611538 /* [CP] Embed Pods Frameworks */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
33CC11202044C79F0003C045 /* PBXTargetDependency */,
|
||||||
|
);
|
||||||
|
name = Runner;
|
||||||
|
productName = Runner;
|
||||||
|
productReference = 33CC10ED2044A3C60003C045 /* Felt Diary.app */;
|
||||||
|
productType = "com.apple.product-type.application";
|
||||||
|
};
|
||||||
|
/* End PBXNativeTarget section */
|
||||||
|
|
||||||
|
/* Begin PBXProject section */
|
||||||
|
33CC10E52044A3C60003C045 /* Project object */ = {
|
||||||
|
isa = PBXProject;
|
||||||
|
attributes = {
|
||||||
|
LastSwiftUpdateCheck = 0920;
|
||||||
|
LastUpgradeCheck = 1400;
|
||||||
|
ORGANIZATIONNAME = "";
|
||||||
|
TargetAttributes = {
|
||||||
|
33CC10EC2044A3C60003C045 = {
|
||||||
|
CreatedOnToolsVersion = 9.2;
|
||||||
|
LastSwiftMigration = 1100;
|
||||||
|
SystemCapabilities = {
|
||||||
|
com.apple.Sandbox = {
|
||||||
|
enabled = 1;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
33CC111A2044C6BA0003C045 = {
|
||||||
|
CreatedOnToolsVersion = 9.2;
|
||||||
|
ProvisioningStyle = Manual;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */;
|
||||||
|
compatibilityVersion = "Xcode 9.3";
|
||||||
|
developmentRegion = en;
|
||||||
|
hasScannedForEncodings = 0;
|
||||||
|
knownRegions = (
|
||||||
|
en,
|
||||||
|
Base,
|
||||||
|
);
|
||||||
|
mainGroup = 33CC10E42044A3C60003C045;
|
||||||
|
productRefGroup = 33CC10EE2044A3C60003C045 /* Products */;
|
||||||
|
projectDirPath = "";
|
||||||
|
projectRoot = "";
|
||||||
|
targets = (
|
||||||
|
33CC10EC2044A3C60003C045 /* Runner */,
|
||||||
|
33CC111A2044C6BA0003C045 /* Flutter Assemble */,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
/* End PBXProject section */
|
||||||
|
|
||||||
|
/* Begin PBXResourcesBuildPhase section */
|
||||||
|
33CC10EB2044A3C60003C045 /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */,
|
||||||
|
33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXShellScriptBuildPhase section */
|
||||||
|
3399D490228B24CF009A79C7 /* ShellScript */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
);
|
||||||
|
outputFileListPaths = (
|
||||||
|
);
|
||||||
|
outputPaths = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n";
|
||||||
|
};
|
||||||
|
33CC111E2044C6BF0003C045 /* ShellScript */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
Flutter/ephemeral/FlutterInputs.xcfilelist,
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
Flutter/ephemeral/tripwire,
|
||||||
|
);
|
||||||
|
outputFileListPaths = (
|
||||||
|
Flutter/ephemeral/FlutterOutputs.xcfilelist,
|
||||||
|
);
|
||||||
|
outputPaths = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire";
|
||||||
|
};
|
||||||
|
558B4163B66FBD35BF611538 /* [CP] Embed Pods Frameworks */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
|
);
|
||||||
|
name = "[CP] Embed Pods Frameworks";
|
||||||
|
outputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
|
FD4539A7C90013601C734851 /* [CP] Check Pods Manifest.lock */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||||
|
"${PODS_ROOT}/Manifest.lock",
|
||||||
|
);
|
||||||
|
name = "[CP] Check Pods Manifest.lock";
|
||||||
|
outputFileListPaths = (
|
||||||
|
);
|
||||||
|
outputPaths = (
|
||||||
|
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
|
33CC10E92044A3C60003C045 /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */,
|
||||||
|
33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */,
|
||||||
|
335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXTargetDependency section */
|
||||||
|
33CC11202044C79F0003C045 /* PBXTargetDependency */ = {
|
||||||
|
isa = PBXTargetDependency;
|
||||||
|
target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */;
|
||||||
|
targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */;
|
||||||
|
};
|
||||||
|
/* End PBXTargetDependency section */
|
||||||
|
|
||||||
|
/* Begin PBXVariantGroup section */
|
||||||
|
33CC10F42044A3C60003C045 /* MainMenu.xib */ = {
|
||||||
|
isa = PBXVariantGroup;
|
||||||
|
children = (
|
||||||
|
33CC10F52044A3C60003C045 /* Base */,
|
||||||
|
);
|
||||||
|
name = MainMenu.xib;
|
||||||
|
path = Runner;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
/* End PBXVariantGroup section */
|
||||||
|
|
||||||
|
/* Begin XCBuildConfiguration section */
|
||||||
|
338D0CE9231458BD00FA5F75 /* Profile */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||||
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
CODE_SIGN_IDENTITY = "-";
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
DEAD_CODE_STRIPPING = YES;
|
||||||
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
|
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
|
SDKROOT = macosx;
|
||||||
|
SWIFT_COMPILATION_MODE = wholemodule;
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||||
|
};
|
||||||
|
name = Profile;
|
||||||
|
};
|
||||||
|
338D0CEA231458BD00FA5F75 /* Profile */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
|
||||||
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
|
DEAD_CODE_STRIPPING = YES;
|
||||||
|
DEVELOPMENT_TEAM = MYUTW2GF6J;
|
||||||
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = "Filc Napló";
|
||||||
|
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.education";
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/../Frameworks",
|
||||||
|
);
|
||||||
|
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||||
|
NEW_SETTING = "";
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = hu.filc.filcnaplo;
|
||||||
|
PRODUCT_NAME = "Felt Diary";
|
||||||
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
};
|
||||||
|
name = Profile;
|
||||||
|
};
|
||||||
|
338D0CEB231458BD00FA5F75 /* Profile */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
CODE_SIGN_STYLE = Manual;
|
||||||
|
DEAD_CODE_STRIPPING = YES;
|
||||||
|
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
};
|
||||||
|
name = Profile;
|
||||||
|
};
|
||||||
|
33CC10F92044A3C60003C045 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||||
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
CODE_SIGN_IDENTITY = "-";
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
DEAD_CODE_STRIPPING = YES;
|
||||||
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
ENABLE_TESTABILITY = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
|
GCC_DYNAMIC_NO_PIC = NO;
|
||||||
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
GCC_OPTIMIZATION_LEVEL = 0;
|
||||||
|
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||||
|
"DEBUG=1",
|
||||||
|
"$(inherited)",
|
||||||
|
);
|
||||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
|
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = YES;
|
||||||
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
|
SDKROOT = macosx;
|
||||||
|
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
33CC10FA2044A3C60003C045 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||||
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
CODE_SIGN_IDENTITY = "-";
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
DEAD_CODE_STRIPPING = YES;
|
||||||
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
|
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
|
SDKROOT = macosx;
|
||||||
|
SWIFT_COMPILATION_MODE = wholemodule;
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
33CC10FC2044A3C60003C045 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
|
||||||
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
|
DEAD_CODE_STRIPPING = YES;
|
||||||
|
DEVELOPMENT_TEAM = MYUTW2GF6J;
|
||||||
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = "Filc Napló";
|
||||||
|
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.education";
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/../Frameworks",
|
||||||
|
);
|
||||||
|
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||||
|
NEW_SETTING = "";
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = hu.filc.filcnaplo;
|
||||||
|
PRODUCT_NAME = "Felt Diary";
|
||||||
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
33CC10FD2044A3C60003C045 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements;
|
||||||
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
|
DEAD_CODE_STRIPPING = YES;
|
||||||
|
DEVELOPMENT_TEAM = MYUTW2GF6J;
|
||||||
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = "Filc Napló";
|
||||||
|
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.education";
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/../Frameworks",
|
||||||
|
);
|
||||||
|
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||||
|
NEW_SETTING = "";
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = hu.filc.filcnaplo;
|
||||||
|
PRODUCT_NAME = "Felt Diary";
|
||||||
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
33CC111C2044C6BA0003C045 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
CODE_SIGN_STYLE = Manual;
|
||||||
|
DEAD_CODE_STRIPPING = YES;
|
||||||
|
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
33CC111D2044C6BA0003C045 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
DEAD_CODE_STRIPPING = YES;
|
||||||
|
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
|
/* Begin XCConfigurationList section */
|
||||||
|
33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
33CC10F92044A3C60003C045 /* Debug */,
|
||||||
|
33CC10FA2044A3C60003C045 /* Release */,
|
||||||
|
338D0CE9231458BD00FA5F75 /* Profile */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
33CC10FC2044A3C60003C045 /* Debug */,
|
||||||
|
33CC10FD2044A3C60003C045 /* Release */,
|
||||||
|
338D0CEA231458BD00FA5F75 /* Profile */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
33CC111C2044C6BA0003C045 /* Debug */,
|
||||||
|
33CC111D2044C6BA0003C045 /* Release */,
|
||||||
|
338D0CEB231458BD00FA5F75 /* Profile */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
/* End XCConfigurationList section */
|
||||||
|
};
|
||||||
|
rootObject = 33CC10E52044A3C60003C045 /* Project object */;
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user