Compare commits
189 Commits
3.0.0-beta
...
3.3.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ee475f8ee8 | ||
|
|
3c431cbce1 | ||
|
|
708c411339 | ||
|
|
1e9247652a | ||
|
|
551ed6ebdb | ||
|
|
c86ac68007 | ||
|
|
d309f11f19 | ||
|
|
e4acd4f872 | ||
|
|
3ee91e7543 | ||
|
|
f147ae328e | ||
|
|
aab1f605d4 | ||
|
|
c71a6d9468 | ||
|
|
165f836d93 | ||
|
|
6356206291 | ||
|
|
bf8ca49f98 | ||
|
|
0fca636311 | ||
|
|
8673a9e42a | ||
|
|
0390d0df39 | ||
|
|
4ec2f74fee | ||
|
|
e2078db34b | ||
|
|
1f39bdc301 | ||
|
|
029e841d7b | ||
|
|
6a16f93884 | ||
|
|
cfc0229f09 | ||
|
|
a68dd759d8 | ||
|
|
e7d0e3805d | ||
|
|
d617d9ef47 | ||
|
|
2564224a6e | ||
|
|
5c2b690bc8 | ||
|
|
ff72d146c0 | ||
|
|
088b6e4580 | ||
|
|
66793607e8 | ||
|
|
c91e792c6c | ||
|
|
16d0bd4163 | ||
|
|
e559338483 | ||
|
|
f2c29aa81b | ||
|
|
e44a3b7330 | ||
|
|
64606311bf | ||
|
|
43c4d2e454 | ||
|
|
9b579ad196 | ||
|
|
425a4aaa91 | ||
|
|
506c04aea9 | ||
|
|
cd18cfb220 | ||
|
|
f071e59e7a | ||
|
|
49f3a447b3 | ||
|
|
339dbea1ef | ||
|
|
79f6ef4c50 | ||
|
|
ae18fbab2e | ||
|
|
9003e13aa1 | ||
|
|
e58f4859b4 | ||
|
|
be809c6aaf | ||
|
|
a6b012035b | ||
|
|
a0ef512c55 | ||
|
|
4e1c1be6e4 | ||
|
|
92a93941ab | ||
|
|
ece621455c | ||
|
|
0787f97a6f | ||
|
|
c74975e3bc | ||
|
|
4b669b0069 | ||
|
|
d24286b61c | ||
|
|
40f3d2159a | ||
|
|
8df77b5c06 | ||
|
|
fd88b5ee55 | ||
|
|
ceaafb4897 | ||
|
|
6617882892 | ||
|
|
1b16b748d4 | ||
|
|
7014255b89 | ||
|
|
d86f2fffe5 | ||
|
|
de1b0444b6 | ||
|
|
bd1a8358f6 | ||
|
|
8a670b3a4c | ||
|
|
2917a2e913 | ||
|
|
414c183399 | ||
|
|
428d6ff975 | ||
|
|
c418a61133 | ||
|
|
7e83d7b969 | ||
|
|
bdf6cc20c7 | ||
|
|
da089da22b | ||
|
|
fa3c0954c4 | ||
|
|
f4843211f5 | ||
|
|
5e1727eadd | ||
|
|
dd103e7474 | ||
|
|
aa61301b17 | ||
|
|
af360fda53 | ||
|
|
a56453ab9d | ||
|
|
c9aed14d7c | ||
|
|
0cef766ee6 | ||
|
|
c8cd6bf9b8 | ||
|
|
d9e8b4f4ed | ||
|
|
8ab96a32c3 | ||
|
|
22c8a285ab | ||
|
|
d819245e31 | ||
|
|
6b55721ec5 | ||
|
|
13062c4a9b | ||
|
|
2188eaf1c6 | ||
|
|
922d252c57 | ||
|
|
7a5290efe5 | ||
|
|
d1e6cc1fbb | ||
|
|
b6a8696911 | ||
|
|
f7efd65f5e | ||
|
|
9963f65ab2 | ||
|
|
8d8c3a54c2 | ||
|
|
c49d93c7b1 | ||
|
|
b0a7ab20d9 | ||
|
|
59a9e0e236 | ||
|
|
e83202ba29 | ||
|
|
d4489dd9d4 | ||
|
|
debb4cac5b | ||
|
|
acbdf2aecb | ||
|
|
5d9ea4311a | ||
|
|
8aa24d7a32 | ||
|
|
9fbcef357e | ||
|
|
e9423a8535 | ||
|
|
2a7265256d | ||
|
|
d5ba231fcc | ||
|
|
68d92c4462 | ||
|
|
a46f6130cb | ||
|
|
c6021e7a69 | ||
|
|
3ceb40ddb8 | ||
|
|
593292e860 | ||
|
|
ab952daa10 | ||
|
|
56b6eb3d2b | ||
|
|
26be20ac28 | ||
|
|
afd004b980 | ||
|
|
903cbba69a | ||
|
|
6eb6a0cf16 | ||
|
|
abf9f9b13d | ||
|
|
0471843919 | ||
|
|
bb83dd2137 | ||
|
|
d9b07525a4 | ||
|
|
92334406c5 | ||
|
|
506af7fa71 | ||
|
|
f5be03e5ce | ||
|
|
2047784d8f | ||
|
|
037cf1df48 | ||
|
|
8238cc0678 | ||
|
|
f52a747268 | ||
|
|
c37bdc7aff | ||
|
|
9015ff2d6b | ||
|
|
a801503838 | ||
|
|
b0565ddcd9 | ||
|
|
d8b6ba9a64 | ||
|
|
549570a48c | ||
|
|
930e8d86b8 | ||
|
|
4aff7df96f | ||
|
|
c839ac178a | ||
|
|
2c7efc0a18 | ||
|
|
5252813721 | ||
|
|
15d3daefed | ||
|
|
0729c13362 | ||
|
|
4bb978ba63 | ||
|
|
d9c071b5ae | ||
|
|
6ffe4b6c33 | ||
|
|
7bd5d8bd5a | ||
|
|
c0ffa5d726 | ||
|
|
befb107183 | ||
|
|
e56488094e | ||
|
|
74831c3e56 | ||
|
|
9d3347d680 | ||
|
|
25100ab7d9 | ||
|
|
b509adcbc9 | ||
|
|
d421ae9031 | ||
|
|
c3b79fcb3f | ||
|
|
3cf57ac6d4 | ||
|
|
d72bf84a36 | ||
|
|
638b8c9413 | ||
|
|
d5bdca698b | ||
|
|
ea6b2ec73d | ||
|
|
7ffb58c9ac | ||
|
|
eaf2e2a6c4 | ||
|
|
8cf642fb72 | ||
|
|
47245b4551 | ||
|
|
2b25abaf4d | ||
|
|
adef77b5ed | ||
|
|
8cc3107faf | ||
|
|
3284c5ba5a | ||
|
|
942a92f1f4 | ||
|
|
ae3272e6da | ||
|
|
67768b9de9 | ||
|
|
aba24c0c2a | ||
|
|
c55a5b9fe7 | ||
|
|
fee63a2205 | ||
|
|
9bcf9eb391 | ||
|
|
fa9a61657b | ||
|
|
33e4595e09 | ||
|
|
91582c3b37 | ||
|
|
61de95970e | ||
|
|
e36347510f | ||
|
|
e1429dedae |
4
.gitignore
vendored
@@ -1,5 +1,7 @@
|
|||||||
# See https://www.dartlang.org/guides/libraries/private-files
|
# See https://www.dartlang.org/guides/libraries/private-files
|
||||||
|
|
||||||
|
termek.txt
|
||||||
|
|
||||||
# Files and directories created by pub
|
# Files and directories created by pub
|
||||||
.dart_tool/
|
.dart_tool/
|
||||||
.packages
|
.packages
|
||||||
@@ -19,3 +21,5 @@ doc/api/
|
|||||||
*.js_
|
*.js_
|
||||||
*.js.deps
|
*.js.deps
|
||||||
*.js.map
|
*.js.map
|
||||||
|
|
||||||
|
*.txt
|
||||||
5
.vscode/launch.json
vendored
@@ -8,7 +8,10 @@
|
|||||||
"name": "filcnaplo",
|
"name": "filcnaplo",
|
||||||
"cwd": "filcnaplo",
|
"cwd": "filcnaplo",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"type": "dart"
|
"type": "dart",
|
||||||
|
"toolArgs": [
|
||||||
|
"--dart-define=APPVER=$(cat pubspec.yaml | grep version: | cut -d' ' -f2 | cut -d+ -f1)"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
39
CONTRIBUTING.md
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
|
||||||
|
# Contributing Guide
|
||||||
|
Köszönjük, ha programozással segíted a munkánkat!
|
||||||
|
A folytatáshoz szükséged lesz egy Linuxot vagy Windowst futtató számítógépre, minimális programozási tapasztalatra és egy kis angoltudásra.
|
||||||
|
Segít, ha nem csak kicsit tudsz programozni, és ha ismered a Gitet és a GitHubot ;)
|
||||||
|
|
||||||
|
## Miben segítsek?
|
||||||
|
Kérünk, **olyan dologgal járulj hozzá** a Filchez, ami valószínűleg **sok embernek hasznos lesz** majd. Szeretnénk egy minél teljeskörűbb iskolai asszisztenst létrehozni, de az iskolaspecifikus, vagy külön neked hasznos funkciók helye inkább legyen a saját forkod.
|
||||||
|
|
||||||
|
Fontos, hogy **mielőtt egy nagy volumenű projektbe belekezdesz, futtasd meg ötletedet a [Discord szerverünkön](https://filcnaplo.hu/discord),** ahol még azelőtt tudunk tanácsot adni, mielőtt sok-sok órát beleöltél volna egy esetleg felesleges dologba.
|
||||||
|
|
||||||
|
A legjobban annak örülünk, ha az [Issues](https://github.com/filcnaplo/filcnaplo/issues) oldalról szemezgetsz, **ha lehet, a [priority taggel megjelöltekkel kezdd](https://github.com/filcnaplo/filcnaplo/issues?q=is%3Aissue+is%3Aopen+label%3Apriority),** vagy ha új vagy a Flutterhez, ajánljuk figyelmedbe [ezeket a viszonylag könnyen javítható hibákat](https://github.com/filcnaplo/filcnaplo/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) (ha épp van ilyen).
|
||||||
|
|
||||||
|
## Hogyan segítsek?
|
||||||
|
|
||||||
|
Nem ígérhetünk itt sem programozás-, sem git-kurzust, de a projektspecifikus dolgokat leírjuk, és segítünk a Flutter feltelepítésében.
|
||||||
|
|
||||||
|
A Filc a Google által pár éve létrehozott **[Fluttert](https://flutter.dev/)** használja, aminek nyelve a **[Dart](https://dart.dev/)**. Ha ismered a C#-ot, Javát, C++t, vagy egyéb hasonló nyelvet, **nem fog gondot okozni a használata.** A felhasználói felület létrehozásában az is segíthet, ha foglalkoztál már korábban weboldalakkal.
|
||||||
|
Ha még nem használtál Fluttert, mindenképp böngészd át a [YouTube csatornájukat](https://www.youtube.com/channel/UCwXdFgeE9KYzlDdR7TG9cMw).
|
||||||
|
Könnyen tudsz kódot, vagy akár UI-t is tesztelni a [DartPad](https://dartpad.dev/) oldalon.
|
||||||
|
|
||||||
|
#### [Segítség a Flutter telepítéséhez és a forráskód futtatásához](/.github/SETUP.md)
|
||||||
|
Fontos: **Legyél a flutter beta verzióján!** Írd be: `flutter channel beta`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Ha nem értesz a Githez, ajánljuk figyelmedbe [ezt a cikket](https://medium.com/envienta-magyarorsz%C3%A1g/git-%C3%A9s-github-gyorstalpal%C3%B3-f2d78a732deb). Viszont arra kérünk, a Git használatát ne a Filcen próbáld ki először, hozz létre előbb egy saját Repót, és abba tesztelgess. Ha már nagyjából kitapasztaltad, várjuk hozzájárulásodat.
|
||||||
|
|
||||||
|
Készíts egy forkot a saját fiókod alá.
|
||||||
|
A Filc legfrissebb, épp fejlesztés alatt álló verzióját a [dev brancen](https://github.com/filcnaplo/filcnaplo/tree/dev) találod, kérjük ide commitolj, és ide célozd a forkodból a Pull Requested. Írd le benne, mit változtattál, és ha lehet, csatolj képernyőképet is.
|
||||||
|
Minél gyakrabban készíts minél részletesebben elnevezett commitokat, hogy el tudjunk tájékozódni az általad beküldött kódon.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Az általad fejlesztett funkciók mellé a changelogban odakerül GitHub felhasználóneved.
|
||||||
|
Ha jelentős és rendszeres hozzájáruló vagy, Discordon megkapod a `DEV` rangot.
|
||||||
|
|
||||||
|
Ha bárhol elakadtál, keress minket Discordon.
|
||||||
|
Jó fejlesztést kívánunk!
|
||||||
19
README.md
@@ -5,21 +5,20 @@
|
|||||||
|
|
||||||
#### Nem hivatalos e-napló alkalmazás az eKRÉTA rendszerhez
|
#### Nem hivatalos e-napló alkalmazás az eKRÉTA rendszerhez
|
||||||
|
|
||||||
[](http://filcnaplo.hu/discord) [](https://codemagic.io/apps/612cc79b35b443d1b2c638ec/612cc79b35b443d1b2c638eb/latest_build)
|
[](https://github.com/filc/naplo/releases) [](http://filcnaplo.hu/discord) [](https://codemagic.io/apps/612cc79b35b443d1b2c638ec/612cc79b35b443d1b2c638eb/latest_build)
|
||||||
|
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
### Clone the project:
|
### Clone the project
|
||||||
|
|
||||||
```
|
```sh
|
||||||
$ git clone --recursive https://github.com/filc/naplo
|
git clone --recursive https://github.com/filc/naplo
|
||||||
$ cd naplo
|
cd naplo
|
||||||
```
|
```
|
||||||
|
|
||||||
### Run the app:
|
### Run the app
|
||||||
|
|
||||||
```
|
```sh
|
||||||
$ cd filcnaplo
|
cd filcnaplo
|
||||||
$ flutter run
|
flutter run
|
||||||
```
|
```
|
||||||
|
|||||||
15
changelog.md
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
- Újra dizájnolt jegy, stb. nézet
|
||||||
|
- Offline tárolt osztályátlagok
|
||||||
|
- Csengő késésének beállítása
|
||||||
|
- Óra végén a hátralévő idő másodperc pontos kijelzése
|
||||||
|
- Vissza gombra főoldalra ugrás
|
||||||
|
- Eddigi hiányzott órák százalékos kijelzése
|
||||||
|
- Hiányzások tantárgy szerinti rendezése
|
||||||
|
- Lapozás legyintéssel a tabok között
|
||||||
|
- Hiányzások jelzése az órarenben
|
||||||
|
- Fordítás javítások
|
||||||
|
- Mai határidős házifeladatok javítása
|
||||||
|
- Jobb autofill bejelentkezésnél (thegergo02)
|
||||||
|
- Felhasználóváltásnál órarend frissítése
|
||||||
|
- Design javítások
|
||||||
|
- Hibajavítások
|
||||||
1
filcnaplo/.gitignore
vendored
@@ -8,7 +8,6 @@
|
|||||||
.buildlog/
|
.buildlog/
|
||||||
.history
|
.history
|
||||||
.svn/
|
.svn/
|
||||||
build.sh
|
|
||||||
|
|
||||||
# IntelliJ related
|
# IntelliJ related
|
||||||
*.iml
|
*.iml
|
||||||
|
|||||||
29
filcnaplo/analysis_options.yaml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# This file configures the analyzer, which statically analyzes Dart code to
|
||||||
|
# check for errors, warnings, and lints.
|
||||||
|
#
|
||||||
|
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
|
||||||
|
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
|
||||||
|
# invoked from the command line by running `flutter analyze`.
|
||||||
|
|
||||||
|
# The following line activates a set of recommended lints for Flutter apps,
|
||||||
|
# packages, and plugins designed to encourage good coding practices.
|
||||||
|
include: package:flutter_lints/flutter.yaml
|
||||||
|
|
||||||
|
linter:
|
||||||
|
# The lint rules applied to this project can be customized in the
|
||||||
|
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
|
||||||
|
# included above or to enable additional rules. A list of all available lints
|
||||||
|
# and their documentation is published at
|
||||||
|
# https://dart-lang.github.io/linter/lints/index.html.
|
||||||
|
#
|
||||||
|
# Instead of disabling a lint rule for the entire project in the
|
||||||
|
# section below, it can also be suppressed for a single line of code
|
||||||
|
# or a specific dart file by using the `// ignore: name_of_lint` and
|
||||||
|
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
|
||||||
|
# producing the lint.
|
||||||
|
rules:
|
||||||
|
# avoid_print: false # Uncomment to disable the `avoid_print` rule
|
||||||
|
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
|
||||||
|
|
||||||
|
# Additional information about this file can be found at
|
||||||
|
# https://dart.dev/guides/language/analysis-options
|
||||||
1
filcnaplo/android/.gitignore
vendored
@@ -9,3 +9,4 @@ GeneratedPluginRegistrant.java
|
|||||||
# Remember to never publicly share your keystore.
|
# Remember to never publicly share your keystore.
|
||||||
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
|
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
|
||||||
key.properties
|
key.properties
|
||||||
|
.project
|
||||||
@@ -52,6 +52,7 @@ android {
|
|||||||
versionCode flutterVersionCode.toInteger()
|
versionCode flutterVersionCode.toInteger()
|
||||||
versionName flutterVersionName
|
versionName flutterVersionName
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
multiDexEnabled true
|
||||||
}
|
}
|
||||||
|
|
||||||
signingConfigs {
|
signingConfigs {
|
||||||
@@ -77,6 +78,7 @@ flutter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
implementation 'com.android.support:multidex:2.0.1'
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||||
androidTestImplementation 'androidx.test:runner:1.1.1'
|
androidTestImplementation 'androidx.test:runner:1.1.1'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
<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: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" />
|
||||||
<meta-data android:name="io.flutter.embedding.android.SplashScreenDrawable" android:resource="@drawable/launch_background" />
|
|
||||||
<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"/>
|
||||||
|
|||||||
BIN
filcnaplo/android/app/src/main/res/drawable/ic_absences.png
Normal file
|
After Width: | Height: | Size: 8.0 KiB |
BIN
filcnaplo/android/app/src/main/res/drawable/ic_grades.png
Normal file
|
After Width: | Height: | Size: 5.7 KiB |
BIN
filcnaplo/android/app/src/main/res/drawable/ic_home.png
Normal file
|
After Width: | Height: | Size: 6.3 KiB |
BIN
filcnaplo/android/app/src/main/res/drawable/ic_messages.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
filcnaplo/android/app/src/main/res/drawable/ic_timetable.png
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
@@ -1,9 +1,9 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = '1.3.50'
|
ext.kotlin_version = '1.6.10'
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
compileSdkVersion = 30
|
compileSdkVersion = 31
|
||||||
targetSdkVersion = 30
|
targetSdkVersion = 31
|
||||||
appCompatVersion = "1.1.0"
|
appCompatVersion = "1.1.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ buildscript {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:3.6.3'
|
classpath 'com.android.tools.build:gradle:4.1.0'
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -33,8 +33,8 @@ 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 30
|
compileSdkVersion 31
|
||||||
buildToolsVersion '30.0.3'
|
buildToolsVersion '31.0.0'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
filcnaplo/assets/fonts/SpaceMono/SpaceMono-Bold.ttf
Normal file
BIN
filcnaplo/assets/fonts/SpaceMono/SpaceMono-BoldItalic.ttf
Normal file
BIN
filcnaplo/assets/fonts/SpaceMono/SpaceMono-Italic.ttf
Normal file
BIN
filcnaplo/assets/fonts/SpaceMono/SpaceMono-Regular.ttf
Normal file
@@ -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 |
19
filcnaplo/build.sh
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#!/bin/fish
|
||||||
|
|
||||||
|
# With build number
|
||||||
|
function get_version_bn
|
||||||
|
cat pubspec.yaml | grep version: | cut -d' ' -f2
|
||||||
|
end
|
||||||
|
|
||||||
|
function get_version
|
||||||
|
cat pubspec.yaml | grep version: | cut -d' ' -f2 | cut -d+ -f1
|
||||||
|
end
|
||||||
|
|
||||||
|
if test -e /mnt/enc/keys/filc3.properties
|
||||||
|
set -x ANDROID_SIGNING /mnt/enc/keys/filc3.properties
|
||||||
|
end
|
||||||
|
|
||||||
|
flutter build apk --release --dart-define=APPVER=(get_version) --no-tree-shake-icons
|
||||||
|
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>8.0</string>
|
<string>9.0</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
|
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
|
||||||
#include "Generated.xcconfig"
|
#include "Generated.xcconfig"
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
|
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
|
||||||
#include "Generated.xcconfig"
|
#include "Generated.xcconfig"
|
||||||
|
|||||||
41
filcnaplo/ios/Podfile
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
# Uncomment this line to define a global platform for your project
|
||||||
|
# platform :ios, '9.0'
|
||||||
|
|
||||||
|
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||||
|
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||||
|
|
||||||
|
project 'Runner', {
|
||||||
|
'Debug' => :debug,
|
||||||
|
'Profile' => :release,
|
||||||
|
'Release' => :release,
|
||||||
|
}
|
||||||
|
|
||||||
|
def flutter_root
|
||||||
|
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
|
||||||
|
unless File.exist?(generated_xcode_build_settings_path)
|
||||||
|
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
|
||||||
|
end
|
||||||
|
|
||||||
|
File.foreach(generated_xcode_build_settings_path) do |line|
|
||||||
|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
|
||||||
|
return matches[1].strip if matches
|
||||||
|
end
|
||||||
|
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
|
||||||
|
end
|
||||||
|
|
||||||
|
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
|
||||||
|
|
||||||
|
flutter_ios_podfile_setup
|
||||||
|
|
||||||
|
target 'Runner' do
|
||||||
|
use_frameworks!
|
||||||
|
use_modular_headers!
|
||||||
|
|
||||||
|
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
|
||||||
|
end
|
||||||
|
|
||||||
|
post_install do |installer|
|
||||||
|
installer.pods_project.targets.each do |target|
|
||||||
|
flutter_additional_ios_build_settings(target)
|
||||||
|
end
|
||||||
|
end
|
||||||
123
filcnaplo/ios/Podfile.lock
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
PODS:
|
||||||
|
- DKImagePickerController/Core (4.3.2):
|
||||||
|
- DKImagePickerController/ImageDataManager
|
||||||
|
- DKImagePickerController/Resource
|
||||||
|
- DKImagePickerController/ImageDataManager (4.3.2)
|
||||||
|
- DKImagePickerController/PhotoGallery (4.3.2):
|
||||||
|
- DKImagePickerController/Core
|
||||||
|
- DKPhotoGallery
|
||||||
|
- DKImagePickerController/Resource (4.3.2)
|
||||||
|
- DKPhotoGallery (0.0.17):
|
||||||
|
- DKPhotoGallery/Core (= 0.0.17)
|
||||||
|
- DKPhotoGallery/Model (= 0.0.17)
|
||||||
|
- DKPhotoGallery/Preview (= 0.0.17)
|
||||||
|
- DKPhotoGallery/Resource (= 0.0.17)
|
||||||
|
- SDWebImage
|
||||||
|
- SwiftyGif
|
||||||
|
- DKPhotoGallery/Core (0.0.17):
|
||||||
|
- DKPhotoGallery/Model
|
||||||
|
- DKPhotoGallery/Preview
|
||||||
|
- SDWebImage
|
||||||
|
- SwiftyGif
|
||||||
|
- DKPhotoGallery/Model (0.0.17):
|
||||||
|
- SDWebImage
|
||||||
|
- SwiftyGif
|
||||||
|
- DKPhotoGallery/Preview (0.0.17):
|
||||||
|
- DKPhotoGallery/Model
|
||||||
|
- DKPhotoGallery/Resource
|
||||||
|
- SDWebImage
|
||||||
|
- SwiftyGif
|
||||||
|
- DKPhotoGallery/Resource (0.0.17):
|
||||||
|
- SDWebImage
|
||||||
|
- SwiftyGif
|
||||||
|
- file_picker (0.0.1):
|
||||||
|
- DKImagePickerController/PhotoGallery
|
||||||
|
- Flutter
|
||||||
|
- Flutter (1.0.0)
|
||||||
|
- flutter_custom_tabs (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- FMDB (2.7.5):
|
||||||
|
- FMDB/standard (= 2.7.5)
|
||||||
|
- FMDB/standard (2.7.5)
|
||||||
|
- open_file (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- package_info_plus (0.4.5):
|
||||||
|
- Flutter
|
||||||
|
- path_provider (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- "permission_handler (5.1.0+2)":
|
||||||
|
- Flutter
|
||||||
|
- SDWebImage (5.11.1):
|
||||||
|
- SDWebImage/Core (= 5.11.1)
|
||||||
|
- SDWebImage/Core (5.11.1)
|
||||||
|
- share_plus (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- sqflite (0.0.2):
|
||||||
|
- Flutter
|
||||||
|
- FMDB (>= 2.7.5)
|
||||||
|
- SwiftyGif (5.4.0)
|
||||||
|
- url_launcher (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
|
||||||
|
DEPENDENCIES:
|
||||||
|
- file_picker (from `.symlinks/plugins/file_picker/ios`)
|
||||||
|
- Flutter (from `Flutter`)
|
||||||
|
- flutter_custom_tabs (from `.symlinks/plugins/flutter_custom_tabs/ios`)
|
||||||
|
- open_file (from `.symlinks/plugins/open_file/ios`)
|
||||||
|
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
||||||
|
- path_provider (from `.symlinks/plugins/path_provider/ios`)
|
||||||
|
- permission_handler (from `.symlinks/plugins/permission_handler/ios`)
|
||||||
|
- share_plus (from `.symlinks/plugins/share_plus/ios`)
|
||||||
|
- sqflite (from `.symlinks/plugins/sqflite/ios`)
|
||||||
|
- url_launcher (from `.symlinks/plugins/url_launcher/ios`)
|
||||||
|
|
||||||
|
SPEC REPOS:
|
||||||
|
trunk:
|
||||||
|
- DKImagePickerController
|
||||||
|
- DKPhotoGallery
|
||||||
|
- FMDB
|
||||||
|
- SDWebImage
|
||||||
|
- SwiftyGif
|
||||||
|
|
||||||
|
EXTERNAL SOURCES:
|
||||||
|
file_picker:
|
||||||
|
:path: ".symlinks/plugins/file_picker/ios"
|
||||||
|
Flutter:
|
||||||
|
:path: Flutter
|
||||||
|
flutter_custom_tabs:
|
||||||
|
:path: ".symlinks/plugins/flutter_custom_tabs/ios"
|
||||||
|
open_file:
|
||||||
|
:path: ".symlinks/plugins/open_file/ios"
|
||||||
|
package_info_plus:
|
||||||
|
:path: ".symlinks/plugins/package_info_plus/ios"
|
||||||
|
path_provider:
|
||||||
|
:path: ".symlinks/plugins/path_provider/ios"
|
||||||
|
permission_handler:
|
||||||
|
:path: ".symlinks/plugins/permission_handler/ios"
|
||||||
|
share_plus:
|
||||||
|
:path: ".symlinks/plugins/share_plus/ios"
|
||||||
|
sqflite:
|
||||||
|
:path: ".symlinks/plugins/sqflite/ios"
|
||||||
|
url_launcher:
|
||||||
|
:path: ".symlinks/plugins/url_launcher/ios"
|
||||||
|
|
||||||
|
SPEC CHECKSUMS:
|
||||||
|
DKImagePickerController: b5eb7f7a388e4643264105d648d01f727110fc3d
|
||||||
|
DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179
|
||||||
|
file_picker: 3e6c3790de664ccf9b882732d9db5eaf6b8d4eb1
|
||||||
|
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
|
||||||
|
flutter_custom_tabs: 7a10a08686955cb748e5d26e0ae586d30689bf89
|
||||||
|
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
|
||||||
|
open_file: 02eb5cb6b21264bd3a696876f5afbfb7ca4f4b7d
|
||||||
|
package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e
|
||||||
|
path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c
|
||||||
|
permission_handler: ccb20a9fad0ee9b1314a52b70b76b473c5f8dab0
|
||||||
|
SDWebImage: a7f831e1a65eb5e285e3fb046a23fcfbf08e696d
|
||||||
|
share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68
|
||||||
|
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
|
||||||
|
SwiftyGif: 5d4af95df24caf1c570dbbcb32a3b8a0763bc6d7
|
||||||
|
url_launcher: 6fef411d543ceb26efce54b05a0a40bfd74cbbef
|
||||||
|
|
||||||
|
PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
|
||||||
|
|
||||||
|
COCOAPODS: 1.11.0
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
/* 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 */; };
|
||||||
|
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 */; };
|
||||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
||||||
@@ -31,10 +32,13 @@
|
|||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
||||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
||||||
|
1F0ADD56276103500A3016C8 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
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>"; };
|
||||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
||||||
|
80777CF254888CE770D5F909 /* 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>"; };
|
||||||
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
|
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
|
||||||
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
|
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
|
||||||
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
@@ -42,6 +46,7 @@
|
|||||||
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||||
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
98578F0EBCC6D3FF8391AAEB /* 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 */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
@@ -49,12 +54,32 @@
|
|||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
373A6ECB5FC71FE9D8AF2EDB /* Pods_Runner.framework in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
/* End PBXFrameworksBuildPhase section */
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
/* Begin PBXGroup section */
|
||||||
|
6640A963014A9D4F31026053 /* Frameworks */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
1F0ADD56276103500A3016C8 /* Pods_Runner.framework */,
|
||||||
|
);
|
||||||
|
name = Frameworks;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
91FEB6212755D596FFFFEC73 /* Pods */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
80777CF254888CE770D5F909 /* Pods-Runner.debug.xcconfig */,
|
||||||
|
98578F0EBCC6D3FF8391AAEB /* Pods-Runner.release.xcconfig */,
|
||||||
|
707F8089D970F81C480F73C4 /* Pods-Runner.profile.xcconfig */,
|
||||||
|
);
|
||||||
|
name = Pods;
|
||||||
|
path = Pods;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
9740EEB11CF90186004384FC /* Flutter */ = {
|
9740EEB11CF90186004384FC /* Flutter */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -72,6 +97,8 @@
|
|||||||
9740EEB11CF90186004384FC /* Flutter */,
|
9740EEB11CF90186004384FC /* Flutter */,
|
||||||
97C146F01CF9000F007C117D /* Runner */,
|
97C146F01CF9000F007C117D /* Runner */,
|
||||||
97C146EF1CF9000F007C117D /* Products */,
|
97C146EF1CF9000F007C117D /* Products */,
|
||||||
|
91FEB6212755D596FFFFEC73 /* Pods */,
|
||||||
|
6640A963014A9D4F31026053 /* Frameworks */,
|
||||||
);
|
);
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
@@ -105,12 +132,14 @@
|
|||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
|
779338C8D92BCBC36F75F791 /* [CP] Check Pods Manifest.lock */,
|
||||||
9740EEB61CF901F6004384FC /* Run Script */,
|
9740EEB61CF901F6004384FC /* Run Script */,
|
||||||
97C146EA1CF9000F007C117D /* Sources */,
|
97C146EA1CF9000F007C117D /* Sources */,
|
||||||
97C146EB1CF9000F007C117D /* Frameworks */,
|
97C146EB1CF9000F007C117D /* Frameworks */,
|
||||||
97C146EC1CF9000F007C117D /* Resources */,
|
97C146EC1CF9000F007C117D /* Resources */,
|
||||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||||
|
71459C0EB905E05018E3D78F /* [CP] Embed Pods Frameworks */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
@@ -183,6 +212,45 @@
|
|||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
|
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
|
||||||
};
|
};
|
||||||
|
71459C0EB905E05018E3D78F /* [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;
|
||||||
|
};
|
||||||
|
779338C8D92BCBC36F75F791 /* [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;
|
||||||
|
};
|
||||||
9740EEB61CF901F6004384FC /* Run Script */ = {
|
9740EEB61CF901F6004384FC /* Run Script */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
|
|||||||
@@ -4,4 +4,7 @@
|
|||||||
<FileRef
|
<FileRef
|
||||||
location = "group:Runner.xcodeproj">
|
location = "group:Runner.xcodeproj">
|
||||||
</FileRef>
|
</FileRef>
|
||||||
|
<FileRef
|
||||||
|
location = "group:Pods/Pods.xcodeproj">
|
||||||
|
</FileRef>
|
||||||
</Workspace>
|
</Workspace>
|
||||||
|
|||||||
BIN
filcnaplo/ios/Runner/Assets.xcassets/AppIcon.appiconset/100.png
Normal file
|
After Width: | Height: | Size: 9.4 KiB |
BIN
filcnaplo/ios/Runner/Assets.xcassets/AppIcon.appiconset/1024.png
Normal file
|
After Width: | Height: | Size: 620 KiB |
BIN
filcnaplo/ios/Runner/Assets.xcassets/AppIcon.appiconset/114.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
filcnaplo/ios/Runner/Assets.xcassets/AppIcon.appiconset/120.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
filcnaplo/ios/Runner/Assets.xcassets/AppIcon.appiconset/144.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
filcnaplo/ios/Runner/Assets.xcassets/AppIcon.appiconset/152.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
filcnaplo/ios/Runner/Assets.xcassets/AppIcon.appiconset/167.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
filcnaplo/ios/Runner/Assets.xcassets/AppIcon.appiconset/180.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
filcnaplo/ios/Runner/Assets.xcassets/AppIcon.appiconset/20.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
filcnaplo/ios/Runner/Assets.xcassets/AppIcon.appiconset/29.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
filcnaplo/ios/Runner/Assets.xcassets/AppIcon.appiconset/40.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
filcnaplo/ios/Runner/Assets.xcassets/AppIcon.appiconset/50.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
filcnaplo/ios/Runner/Assets.xcassets/AppIcon.appiconset/57.png
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
BIN
filcnaplo/ios/Runner/Assets.xcassets/AppIcon.appiconset/58.png
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
filcnaplo/ios/Runner/Assets.xcassets/AppIcon.appiconset/60.png
Normal file
|
After Width: | Height: | Size: 4.7 KiB |
BIN
filcnaplo/ios/Runner/Assets.xcassets/AppIcon.appiconset/72.png
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
BIN
filcnaplo/ios/Runner/Assets.xcassets/AppIcon.appiconset/76.png
Normal file
|
After Width: | Height: | Size: 6.5 KiB |
BIN
filcnaplo/ios/Runner/Assets.xcassets/AppIcon.appiconset/80.png
Normal file
|
After Width: | Height: | Size: 6.9 KiB |
BIN
filcnaplo/ios/Runner/Assets.xcassets/AppIcon.appiconset/87.png
Normal file
|
After Width: | Height: | Size: 7.7 KiB |
@@ -1,118 +1,204 @@
|
|||||||
{
|
{
|
||||||
"images": [
|
"images": [
|
||||||
{
|
{
|
||||||
"size" : "20x20",
|
"size": "60x60",
|
||||||
|
"expected-size": "180",
|
||||||
|
"filename": "180.png",
|
||||||
|
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||||
"idiom": "iphone",
|
"idiom": "iphone",
|
||||||
"filename" : "Icon-App-20x20@2x.png",
|
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "20x20",
|
|
||||||
"idiom" : "iphone",
|
|
||||||
"filename" : "Icon-App-20x20@3x.png",
|
|
||||||
"scale" : "3x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "29x29",
|
|
||||||
"idiom" : "iphone",
|
|
||||||
"filename" : "Icon-App-29x29@1x.png",
|
|
||||||
"scale" : "1x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "29x29",
|
|
||||||
"idiom" : "iphone",
|
|
||||||
"filename" : "Icon-App-29x29@2x.png",
|
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "29x29",
|
|
||||||
"idiom" : "iphone",
|
|
||||||
"filename" : "Icon-App-29x29@3x.png",
|
|
||||||
"scale": "3x"
|
"scale": "3x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size": "40x40",
|
"size": "40x40",
|
||||||
|
"expected-size": "80",
|
||||||
|
"filename": "80.png",
|
||||||
|
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||||
"idiom": "iphone",
|
"idiom": "iphone",
|
||||||
"filename" : "Icon-App-40x40@2x.png",
|
|
||||||
"scale": "2x"
|
"scale": "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size": "40x40",
|
"size": "40x40",
|
||||||
|
"expected-size": "120",
|
||||||
|
"filename": "120.png",
|
||||||
|
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||||
"idiom": "iphone",
|
"idiom": "iphone",
|
||||||
"filename" : "Icon-App-40x40@3x.png",
|
|
||||||
"scale": "3x"
|
"scale": "3x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size": "60x60",
|
"size": "60x60",
|
||||||
|
"expected-size": "120",
|
||||||
|
"filename": "120.png",
|
||||||
|
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||||
"idiom": "iphone",
|
"idiom": "iphone",
|
||||||
"filename" : "Icon-App-60x60@2x.png",
|
|
||||||
"scale": "2x"
|
"scale": "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "60x60",
|
"size": "57x57",
|
||||||
|
"expected-size": "57",
|
||||||
|
"filename": "57.png",
|
||||||
|
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||||
|
"idiom": "iphone",
|
||||||
|
"scale": "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size": "29x29",
|
||||||
|
"expected-size": "58",
|
||||||
|
"filename": "58.png",
|
||||||
|
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||||
|
"idiom": "iphone",
|
||||||
|
"scale": "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size": "29x29",
|
||||||
|
"expected-size": "29",
|
||||||
|
"filename": "29.png",
|
||||||
|
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||||
|
"idiom": "iphone",
|
||||||
|
"scale": "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size": "29x29",
|
||||||
|
"expected-size": "87",
|
||||||
|
"filename": "87.png",
|
||||||
|
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||||
"idiom": "iphone",
|
"idiom": "iphone",
|
||||||
"filename" : "Icon-App-60x60@3x.png",
|
|
||||||
"scale": "3x"
|
"scale": "3x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "20x20",
|
"size": "57x57",
|
||||||
"idiom" : "ipad",
|
"expected-size": "114",
|
||||||
"filename" : "Icon-App-20x20@1x.png",
|
"filename": "114.png",
|
||||||
"scale" : "1x"
|
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||||
|
"idiom": "iphone",
|
||||||
|
"scale": "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size": "20x20",
|
"size": "20x20",
|
||||||
"idiom" : "ipad",
|
"expected-size": "40",
|
||||||
"filename" : "Icon-App-20x20@2x.png",
|
"filename": "40.png",
|
||||||
|
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||||
|
"idiom": "iphone",
|
||||||
"scale": "2x"
|
"scale": "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "29x29",
|
"size": "20x20",
|
||||||
"idiom" : "ipad",
|
"expected-size": "60",
|
||||||
"filename" : "Icon-App-29x29@1x.png",
|
"filename": "60.png",
|
||||||
"scale" : "1x"
|
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||||
},
|
"idiom": "iphone",
|
||||||
{
|
"scale": "3x"
|
||||||
"size" : "29x29",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename" : "Icon-App-29x29@2x.png",
|
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "40x40",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename" : "Icon-App-40x40@1x.png",
|
|
||||||
"scale" : "1x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "40x40",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename" : "Icon-App-40x40@2x.png",
|
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "76x76",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename" : "Icon-App-76x76@1x.png",
|
|
||||||
"scale" : "1x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "76x76",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename" : "Icon-App-76x76@2x.png",
|
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "83.5x83.5",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename" : "Icon-App-83.5x83.5@2x.png",
|
|
||||||
"scale" : "2x"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size": "1024x1024",
|
"size": "1024x1024",
|
||||||
|
"filename": "1024.png",
|
||||||
|
"expected-size": "1024",
|
||||||
"idiom": "ios-marketing",
|
"idiom": "ios-marketing",
|
||||||
"filename" : "Icon-App-1024x1024@1x.png",
|
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||||
"scale": "1x"
|
"scale": "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size": "40x40",
|
||||||
|
"expected-size": "80",
|
||||||
|
"filename": "80.png",
|
||||||
|
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||||
|
"idiom": "ipad",
|
||||||
|
"scale": "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size": "72x72",
|
||||||
|
"expected-size": "72",
|
||||||
|
"filename": "72.png",
|
||||||
|
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||||
|
"idiom": "ipad",
|
||||||
|
"scale": "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size": "76x76",
|
||||||
|
"expected-size": "152",
|
||||||
|
"filename": "152.png",
|
||||||
|
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||||
|
"idiom": "ipad",
|
||||||
|
"scale": "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size": "50x50",
|
||||||
|
"expected-size": "100",
|
||||||
|
"filename": "100.png",
|
||||||
|
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||||
|
"idiom": "ipad",
|
||||||
|
"scale": "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size": "29x29",
|
||||||
|
"expected-size": "58",
|
||||||
|
"filename": "58.png",
|
||||||
|
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||||
|
"idiom": "ipad",
|
||||||
|
"scale": "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size": "76x76",
|
||||||
|
"expected-size": "76",
|
||||||
|
"filename": "76.png",
|
||||||
|
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||||
|
"idiom": "ipad",
|
||||||
|
"scale": "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size": "29x29",
|
||||||
|
"expected-size": "29",
|
||||||
|
"filename": "29.png",
|
||||||
|
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||||
|
"idiom": "ipad",
|
||||||
|
"scale": "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size": "50x50",
|
||||||
|
"expected-size": "50",
|
||||||
|
"filename": "50.png",
|
||||||
|
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||||
|
"idiom": "ipad",
|
||||||
|
"scale": "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size": "72x72",
|
||||||
|
"expected-size": "144",
|
||||||
|
"filename": "144.png",
|
||||||
|
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||||
|
"idiom": "ipad",
|
||||||
|
"scale": "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size": "40x40",
|
||||||
|
"expected-size": "40",
|
||||||
|
"filename": "40.png",
|
||||||
|
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||||
|
"idiom": "ipad",
|
||||||
|
"scale": "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size": "83.5x83.5",
|
||||||
|
"expected-size": "167",
|
||||||
|
"filename": "167.png",
|
||||||
|
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||||
|
"idiom": "ipad",
|
||||||
|
"scale": "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size": "20x20",
|
||||||
|
"expected-size": "20",
|
||||||
|
"filename": "20.png",
|
||||||
|
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||||
|
"idiom": "ipad",
|
||||||
|
"scale": "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size": "20x20",
|
||||||
|
"expected-size": "40",
|
||||||
|
"filename": "40.png",
|
||||||
|
"folder": "Assets.xcassets/AppIcon.appiconset/",
|
||||||
|
"idiom": "ipad",
|
||||||
|
"scale": "2x"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"info": {
|
"info": {
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 86 KiB |
|
Before Width: | Height: | Size: 512 B |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 852 B |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 8.2 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 6.5 KiB |
|
Before Width: | Height: | Size: 7.2 KiB |
6
filcnaplo/ios/Runner/Assets.xcassets/Contents.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Before Width: | Height: | Size: 70 B After Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 25 KiB |
21
filcnaplo/ios/Runner/Assets.xcassets/ic_absences.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "icon.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
filcnaplo/ios/Runner/Assets.xcassets/ic_absences.imageset/icon.png
vendored
Normal file
|
After Width: | Height: | Size: 570 B |
21
filcnaplo/ios/Runner/Assets.xcassets/ic_grades.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "icon.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
filcnaplo/ios/Runner/Assets.xcassets/ic_grades.imageset/icon.png
vendored
Normal file
|
After Width: | Height: | Size: 404 B |
21
filcnaplo/ios/Runner/Assets.xcassets/ic_messages.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "icon.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
filcnaplo/ios/Runner/Assets.xcassets/ic_messages.imageset/icon.png
vendored
Normal file
|
After Width: | Height: | Size: 347 B |
21
filcnaplo/ios/Runner/Assets.xcassets/ic_timetable.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "icon.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
filcnaplo/ios/Runner/Assets.xcassets/ic_timetable.imageset/icon.png
vendored
Normal file
|
After Width: | Height: | Size: 422 B |
@@ -39,6 +39,6 @@
|
|||||||
</scenes>
|
</scenes>
|
||||||
<resources>
|
<resources>
|
||||||
<image name="LaunchImage" width="512" height="512"/>
|
<image name="LaunchImage" width="512" height="512"/>
|
||||||
<image name="LaunchBackground" width="1" height="1"/>
|
<image name="LaunchBackground" width="1080" height="1920"/>
|
||||||
</resources>
|
</resources>
|
||||||
</document>
|
</document>
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
<key>CFBundleInfoDictionaryVersion</key>
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
<string>6.0</string>
|
<string>6.0</string>
|
||||||
<key>CFBundleName</key>
|
<key>CFBundleName</key>
|
||||||
<string>filcnaplo</string>
|
<string>Filc Napló</string>
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
@@ -48,5 +48,9 @@
|
|||||||
<string>https</string>
|
<string>https</string>
|
||||||
<string>http</string>
|
<string>http</string>
|
||||||
</array>
|
</array>
|
||||||
|
<key>NSPhotoLibraryUsageDescription</key>
|
||||||
|
<string>The app requires the photo library to set a custom profile picture.</string>
|
||||||
|
<key>ITSAppUsesNonExemptEncryption</key>
|
||||||
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
8
filcnaplo/ios/Runner/Runner.entitlements
Normal file
@@ -0,0 +1,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">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>aps-environment</key>
|
||||||
|
<string>production</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -1,49 +1,84 @@
|
|||||||
|
// ignore_for_file: avoid_print
|
||||||
|
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
import 'package:filcnaplo/models/config.dart';
|
import 'package:filcnaplo/models/config.dart';
|
||||||
import 'package:filcnaplo/models/news.dart';
|
import 'package:filcnaplo/models/news.dart';
|
||||||
import 'package:filcnaplo/models/release.dart';
|
import 'package:filcnaplo/models/release.dart';
|
||||||
|
import 'package:filcnaplo/models/settings.dart';
|
||||||
|
import 'package:filcnaplo/models/supporter.dart';
|
||||||
import 'package:filcnaplo_kreta_api/models/school.dart';
|
import 'package:filcnaplo_kreta_api/models/school.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
|
import 'package:connectivity_plus/connectivity_plus.dart';
|
||||||
|
|
||||||
class FilcAPI {
|
class FilcAPI {
|
||||||
static const SCHOOL_LIST = "https://filcnaplo.hu/v2/school_list.json";
|
// Public API
|
||||||
static const CONFIG = "https://filcnaplo.hu/v2/config.json";
|
static const schoolList = "https://filcnaplo.hu/v2/school_list.json";
|
||||||
static const NEWS = "https://filcnaplo.hu/v2/news.json";
|
static const news = "https://filcnaplo.hu/v2/news.json";
|
||||||
static const REPO = "filc/naplo";
|
static const supporters = "https://filcnaplo.hu/v2/supporters.json";
|
||||||
static const RELEASES = "https://api.github.com/repos/$REPO/releases";
|
|
||||||
|
// Private API
|
||||||
|
static const config = "https://api.filcnaplo.hu/config";
|
||||||
|
static const reportApi = "https://api.filcnaplo.hu/report";
|
||||||
|
|
||||||
|
// Updates
|
||||||
|
static const repo = "filc/naplo";
|
||||||
|
static const releases = "https://api.github.com/repos/$repo/releases";
|
||||||
|
|
||||||
|
static Future<bool> checkConnectivity() async => (await Connectivity().checkConnectivity()) != ConnectivityResult.none;
|
||||||
|
|
||||||
static Future<List<School>?> getSchools() async {
|
static Future<List<School>?> getSchools() async {
|
||||||
try {
|
try {
|
||||||
http.Response res = await http.get(Uri.parse(SCHOOL_LIST));
|
http.Response res = await http.get(Uri.parse(schoolList));
|
||||||
|
|
||||||
if (res.statusCode == 200) {
|
if (res.statusCode == 200) {
|
||||||
return (jsonDecode(res.body) as List).cast<Map>().map((json) => School.fromJson(json)).toList();
|
List<School> schools = (jsonDecode(res.body) as List).cast<Map>().map((json) => School.fromJson(json)).toList();
|
||||||
|
schools.add(School(
|
||||||
|
city: "Tiszabura",
|
||||||
|
instituteCode: "supporttest-reni-tiszabura-teszt01",
|
||||||
|
name: "FILC Éles Reni tiszabura-teszt",
|
||||||
|
));
|
||||||
|
return schools;
|
||||||
} else {
|
} else {
|
||||||
throw "HTTP ${res.statusCode}: ${res.body}";
|
throw "HTTP ${res.statusCode}: ${res.body}";
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
print("ERROR: FilcAPI.getSchools: $error");
|
print("ERROR: FilcAPI.getSchools: $error");
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<Config?> getConfig() async {
|
static Future<Config?> getConfig(SettingsProvider settings) async {
|
||||||
|
final userAgent = SettingsProvider.defaultSettings().config.userAgent;
|
||||||
|
|
||||||
|
Map<String, String> headers = {
|
||||||
|
"x-filc-id": settings.xFilcId,
|
||||||
|
"user-agent": userAgent,
|
||||||
|
};
|
||||||
|
|
||||||
|
log("[CONFIG] x-filc-id: \"${settings.xFilcId}\"");
|
||||||
|
log("[CONFIG] user-agent: \"$userAgent\"");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
http.Response res = await http.get(Uri.parse(CONFIG));
|
http.Response res = await http.get(Uri.parse(config), headers: headers);
|
||||||
|
|
||||||
if (res.statusCode == 200) {
|
if (res.statusCode == 200) {
|
||||||
return Config.fromJson(jsonDecode(res.body));
|
return Config.fromJson(jsonDecode(res.body));
|
||||||
} else {
|
} else if (res.statusCode == 429) {
|
||||||
throw "HTTP ${res.statusCode}: ${res.body}";
|
res = await http.get(Uri.parse(config));
|
||||||
|
if (res.statusCode == 200) return Config.fromJson(jsonDecode(res.body));
|
||||||
}
|
}
|
||||||
|
throw "HTTP ${res.statusCode}: ${res.body}";
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
print("ERROR: FilcAPI.getConfig: $error");
|
print("ERROR: FilcAPI.getConfig: $error");
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<List<News>?> getNews() async {
|
static Future<List<News>?> getNews() async {
|
||||||
try {
|
try {
|
||||||
http.Response res = await http.get(Uri.parse(NEWS));
|
http.Response res = await http.get(Uri.parse(news));
|
||||||
|
|
||||||
if (res.statusCode == 200) {
|
if (res.statusCode == 200) {
|
||||||
return (jsonDecode(res.body) as List).cast<Map>().map((e) => News.fromJson(e)).toList();
|
return (jsonDecode(res.body) as List).cast<Map>().map((e) => News.fromJson(e)).toList();
|
||||||
@@ -53,11 +88,27 @@ class FilcAPI {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
print("ERROR: FilcAPI.getNews: $error");
|
print("ERROR: FilcAPI.getNews: $error");
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<Supporters?> getSupporters() async {
|
||||||
|
try {
|
||||||
|
http.Response res = await http.get(Uri.parse(supporters));
|
||||||
|
|
||||||
|
if (res.statusCode == 200) {
|
||||||
|
return Supporters.fromJson(jsonDecode(res.body));
|
||||||
|
} else {
|
||||||
|
throw "HTTP ${res.statusCode}: ${res.body}";
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
print("ERROR: FilcAPI.getSupporters: $error");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<List<Release>?> getReleases() async {
|
static Future<List<Release>?> getReleases() async {
|
||||||
try {
|
try {
|
||||||
http.Response res = await http.get(Uri.parse(RELEASES));
|
http.Response res = await http.get(Uri.parse(releases));
|
||||||
|
|
||||||
if (res.statusCode == 200) {
|
if (res.statusCode == 200) {
|
||||||
return (jsonDecode(res.body) as List).cast<Map>().map((e) => Release.fromJson(e)).toList();
|
return (jsonDecode(res.body) as List).cast<Map>().map((e) => Release.fromJson(e)).toList();
|
||||||
@@ -67,10 +118,11 @@ class FilcAPI {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
print("ERROR: FilcAPI.getReleases: $error");
|
print("ERROR: FilcAPI.getReleases: $error");
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<http.StreamedResponse?> downloadRelease(Release release) {
|
static Future<http.StreamedResponse?> downloadRelease(Release release) {
|
||||||
if (release.downloads.length > 0) {
|
if (release.downloads.isNotEmpty) {
|
||||||
try {
|
try {
|
||||||
var client = http.Client();
|
var client = http.Client();
|
||||||
var request = http.Request('GET', Uri.parse(release.downloads.first));
|
var request = http.Request('GET', Uri.parse(release.downloads.first));
|
||||||
@@ -82,4 +134,35 @@ class FilcAPI {
|
|||||||
|
|
||||||
return Future.value(null);
|
return Future.value(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<void> sendReport(ErrorReport report) async {
|
||||||
|
try {
|
||||||
|
http.Response res = await http.post(Uri.parse(reportApi), body: {
|
||||||
|
"os": report.os,
|
||||||
|
"version": report.version,
|
||||||
|
"error": report.error,
|
||||||
|
"stack_trace": report.stack,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (res.statusCode != 200) {
|
||||||
|
throw "HTTP ${res.statusCode}: ${res.body}";
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
print("ERROR: FilcAPI.sendReport: $error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ErrorReport {
|
||||||
|
String stack;
|
||||||
|
String os;
|
||||||
|
String version;
|
||||||
|
String error;
|
||||||
|
|
||||||
|
ErrorReport({
|
||||||
|
required this.stack,
|
||||||
|
required this.os,
|
||||||
|
required this.version,
|
||||||
|
required this.error,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
// ignore_for_file: avoid_print
|
||||||
|
|
||||||
|
import 'package:filcnaplo/utils/jwt.dart';
|
||||||
import 'package:filcnaplo_kreta_api/providers/absence_provider.dart';
|
import 'package:filcnaplo_kreta_api/providers/absence_provider.dart';
|
||||||
import 'package:filcnaplo_kreta_api/providers/event_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/exam_provider.dart';
|
||||||
@@ -10,10 +13,8 @@ import 'package:filcnaplo/api/providers/user_provider.dart';
|
|||||||
import 'package:filcnaplo/api/providers/database_provider.dart';
|
import 'package:filcnaplo/api/providers/database_provider.dart';
|
||||||
import 'package:filcnaplo/models/settings.dart';
|
import 'package:filcnaplo/models/settings.dart';
|
||||||
import 'package:filcnaplo/models/user.dart';
|
import 'package:filcnaplo/models/user.dart';
|
||||||
import 'package:filcnaplo/utils/jwt.dart';
|
|
||||||
import 'package:filcnaplo_kreta_api/client/api.dart';
|
import 'package:filcnaplo_kreta_api/client/api.dart';
|
||||||
import 'package:filcnaplo_kreta_api/client/client.dart';
|
import 'package:filcnaplo_kreta_api/client/client.dart';
|
||||||
import 'package:filcnaplo_kreta_api/models/message.dart';
|
|
||||||
import 'package:filcnaplo_kreta_api/models/student.dart';
|
import 'package:filcnaplo_kreta_api/models/student.dart';
|
||||||
import 'package:filcnaplo_kreta_api/models/week.dart';
|
import 'package:filcnaplo_kreta_api/models/week.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@@ -65,12 +66,14 @@ Future loginApi({
|
|||||||
try {
|
try {
|
||||||
Provider.of<KretaClient>(context, listen: false).accessToken = res["access_token"];
|
Provider.of<KretaClient>(context, listen: false).accessToken = res["access_token"];
|
||||||
Map? studentJson = await Provider.of<KretaClient>(context, listen: false).getAPI(KretaAPI.student(instituteCode));
|
Map? studentJson = await Provider.of<KretaClient>(context, listen: false).getAPI(KretaAPI.student(instituteCode));
|
||||||
|
Student student = Student.fromJson(studentJson!);
|
||||||
var user = User(
|
var user = User(
|
||||||
username: username,
|
username: username,
|
||||||
password: password,
|
password: password,
|
||||||
instituteCode: instituteCode,
|
instituteCode: instituteCode,
|
||||||
name: JwtUtils.getNameFromJWT(res["access_token"]) ?? "?",
|
name: student.name,
|
||||||
student: Student.fromJson(studentJson!),
|
student: student,
|
||||||
|
role: JwtUtils.getRoleFromJWT(res["access_token"])!,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (onLogin != null) onLogin(user);
|
if (onLogin != null) onLogin(user);
|
||||||
@@ -82,14 +85,16 @@ Future loginApi({
|
|||||||
|
|
||||||
// Get user data
|
// Get user data
|
||||||
try {
|
try {
|
||||||
await Provider.of<GradeProvider>(context, listen: false).fetch();
|
await Future.wait([
|
||||||
await Provider.of<TimetableProvider>(context, listen: false).fetch(week: Week.current());
|
Provider.of<GradeProvider>(context, listen: false).fetch(),
|
||||||
await Provider.of<ExamProvider>(context, listen: false).fetch();
|
Provider.of<TimetableProvider>(context, listen: false).fetch(week: Week.current()),
|
||||||
await Provider.of<HomeworkProvider>(context, listen: false).fetch();
|
Provider.of<ExamProvider>(context, listen: false).fetch(),
|
||||||
await Provider.of<MessageProvider>(context, listen: false).fetch(type: MessageType.inbox);
|
Provider.of<HomeworkProvider>(context, listen: false).fetch(),
|
||||||
await Provider.of<NoteProvider>(context, listen: false).fetch();
|
Provider.of<MessageProvider>(context, listen: false).fetchAll(),
|
||||||
await Provider.of<EventProvider>(context, listen: false).fetch();
|
Provider.of<NoteProvider>(context, listen: false).fetch(),
|
||||||
await Provider.of<AbsenceProvider>(context, listen: false).fetch();
|
Provider.of<EventProvider>(context, listen: false).fetch(),
|
||||||
|
Provider.of<AbsenceProvider>(context, listen: false).fetch(),
|
||||||
|
]);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
print("WARNING: failed to fetch user data: $error");
|
print("WARNING: failed to fetch user data: $error");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
|
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';
|
||||||
|
import 'package:sqflite_common_ffi/sqflite_ffi.dart';
|
||||||
|
|
||||||
class DatabaseProvider {
|
class DatabaseProvider {
|
||||||
// late Database _database;
|
// late Database _database;
|
||||||
@@ -10,8 +13,14 @@ class DatabaseProvider {
|
|||||||
late UserDatabaseStore userStore;
|
late UserDatabaseStore userStore;
|
||||||
|
|
||||||
Future<void> init() async {
|
Future<void> init() async {
|
||||||
var db = await openDatabase("app.db");
|
Database db;
|
||||||
// _database = db;
|
|
||||||
|
if (Platform.isLinux || Platform.isWindows) {
|
||||||
|
db = await databaseFactoryFfi.openDatabase("app.db");
|
||||||
|
} else {
|
||||||
|
db = await openDatabase("app.db");
|
||||||
|
}
|
||||||
|
|
||||||
query = DatabaseQuery(db: db);
|
query = DatabaseQuery(db: db);
|
||||||
store = DatabaseStore(db: db);
|
store = DatabaseStore(db: db);
|
||||||
userQuery = UserDatabaseQuery(db: db);
|
userQuery = UserDatabaseQuery(db: db);
|
||||||
|
|||||||
@@ -72,10 +72,11 @@ class NewsProvider extends ChangeNotifier {
|
|||||||
|
|
||||||
Provider.of<SettingsProvider>(_context, listen: false).update(_context, newsState: _state);
|
Provider.of<SettingsProvider>(_context, listen: false).update(_context, newsState: _state);
|
||||||
|
|
||||||
if (_fresh > 0)
|
if (_fresh > 0) {
|
||||||
show = true;
|
show = true;
|
||||||
else
|
} else {
|
||||||
show = false;
|
show = false;
|
||||||
|
}
|
||||||
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|||||||
75
filcnaplo/lib/api/providers/status_provider.dart
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
import 'package:connectivity_plus/connectivity_plus.dart';
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
|
||||||
|
enum Status { network, maintenance, syncing }
|
||||||
|
|
||||||
|
class StatusProvider extends ChangeNotifier {
|
||||||
|
final List<Status> _stack = [];
|
||||||
|
double _progress = 0.0;
|
||||||
|
|
||||||
|
StatusProvider() {
|
||||||
|
_handleNetworkChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
Status? getStatus() => _stack.isNotEmpty ? _stack[0] : null;
|
||||||
|
// Status progress from 0.0 to 1.0
|
||||||
|
double get progress => _progress;
|
||||||
|
|
||||||
|
void _handleNetworkChanges() {
|
||||||
|
Connectivity().onConnectivityChanged.listen((event) {
|
||||||
|
if (event == ConnectivityResult.none) {
|
||||||
|
if (!_stack.contains(Status.network)) {
|
||||||
|
_stack.insert(0, Status.network);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (_stack.contains(Status.network)) {
|
||||||
|
_stack.remove(Status.network);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void triggerRequest(http.Response res) {
|
||||||
|
if (res.headers.containsKey("x-maintenance-mode") || res.statusCode == 503) {
|
||||||
|
if (!_stack.contains(Status.maintenance)) {
|
||||||
|
_stack.insert(0, Status.maintenance);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (_stack.contains(Status.maintenance)) {
|
||||||
|
_stack.remove(Status.maintenance);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void triggerSync({required int current, required int max}) {
|
||||||
|
double prev = _progress;
|
||||||
|
|
||||||
|
if (!_stack.contains(Status.syncing)) {
|
||||||
|
_stack.add(Status.syncing);
|
||||||
|
_progress = 0.0;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (max == 0) {
|
||||||
|
_progress = 0.0;
|
||||||
|
} else {
|
||||||
|
_progress = current / max;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_progress == 1.0) {
|
||||||
|
notifyListeners();
|
||||||
|
// Wait for animation
|
||||||
|
Future.delayed(const Duration(milliseconds: 250), () {
|
||||||
|
_stack.remove(Status.syncing);
|
||||||
|
notifyListeners();
|
||||||
|
});
|
||||||
|
} else if (progress != prev) {
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
69
filcnaplo/lib/api/providers/sync.dart
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
import 'package:filcnaplo/api/providers/database_provider.dart';
|
||||||
|
import 'package:filcnaplo/api/providers/status_provider.dart';
|
||||||
|
import 'package:filcnaplo/api/providers/user_provider.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/client/api.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/client/client.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/student.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/week.dart';
|
||||||
|
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:flutter/widgets.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
// Mutex
|
||||||
|
bool lock = false;
|
||||||
|
|
||||||
|
Future<void> syncAll(BuildContext context) {
|
||||||
|
if (lock) return Future.value();
|
||||||
|
// Lock
|
||||||
|
lock = true;
|
||||||
|
|
||||||
|
// ignore: avoid_print
|
||||||
|
print("INFO Syncing all");
|
||||||
|
|
||||||
|
UserProvider user = Provider.of<UserProvider>(context, listen: false);
|
||||||
|
StatusProvider statusProvider = Provider.of<StatusProvider>(context, listen: false);
|
||||||
|
|
||||||
|
List<Future<void>> tasks = [];
|
||||||
|
int taski = 0;
|
||||||
|
|
||||||
|
Future<void> _syncStatus(Future<void> future) async {
|
||||||
|
await future.onError((error, stackTrace) => null);
|
||||||
|
taski++;
|
||||||
|
statusProvider.triggerSync(current: taski, max: tasks.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks = [
|
||||||
|
_syncStatus(Provider.of<GradeProvider>(context, listen: false).fetch()),
|
||||||
|
_syncStatus(Provider.of<TimetableProvider>(context, listen: false).fetch(week: Week.current())),
|
||||||
|
_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<MessageProvider>(context, listen: false).fetchAll()),
|
||||||
|
_syncStatus(Provider.of<NoteProvider>(context, listen: false).fetch()),
|
||||||
|
_syncStatus(Provider.of<EventProvider>(context, listen: false).fetch()),
|
||||||
|
_syncStatus(Provider.of<AbsenceProvider>(context, listen: false).fetch()),
|
||||||
|
|
||||||
|
// Sync student
|
||||||
|
_syncStatus(() async {
|
||||||
|
if (user.user == null) return;
|
||||||
|
Map? studentJson = await Provider.of<KretaClient>(context, listen: false).getAPI(KretaAPI.student(user.instituteCode!));
|
||||||
|
if (studentJson == null) return;
|
||||||
|
Student student = Student.fromJson(studentJson);
|
||||||
|
|
||||||
|
user.user?.name = student.name;
|
||||||
|
|
||||||
|
// Store user
|
||||||
|
await Provider.of<DatabaseProvider>(context, listen: false).store.storeUser(user.user!);
|
||||||
|
}()),
|
||||||
|
];
|
||||||
|
|
||||||
|
return Future.wait(tasks)
|
||||||
|
// Unlock
|
||||||
|
.then((value) => lock = false);
|
||||||
|
}
|
||||||
@@ -3,14 +3,12 @@ import 'dart:io';
|
|||||||
import 'package:filcnaplo/api/client.dart';
|
import 'package:filcnaplo/api/client.dart';
|
||||||
import 'package:filcnaplo/models/release.dart';
|
import 'package:filcnaplo/models/release.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:package_info_plus/package_info_plus.dart';
|
|
||||||
|
|
||||||
class UpdateProvider extends ChangeNotifier {
|
class UpdateProvider extends ChangeNotifier {
|
||||||
// Private
|
// Private
|
||||||
late List<Release> _releases;
|
late List<Release> _releases;
|
||||||
bool _available = false;
|
bool _available = false;
|
||||||
bool get available => _available && _releases.length > 0;
|
bool get available => _available && _releases.isNotEmpty;
|
||||||
PackageInfo? _packageInfo;
|
|
||||||
|
|
||||||
// Public
|
// Public
|
||||||
List<Release> get releases => _releases;
|
List<Release> get releases => _releases;
|
||||||
@@ -20,9 +18,10 @@ class UpdateProvider extends ChangeNotifier {
|
|||||||
required BuildContext context,
|
required BuildContext context,
|
||||||
}) {
|
}) {
|
||||||
_releases = List.castFrom(initialReleases);
|
_releases = List.castFrom(initialReleases);
|
||||||
PackageInfo.fromPlatform().then((value) => _packageInfo = value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const currentVersion = String.fromEnvironment("APPVER", defaultValue: "1.0");
|
||||||
|
|
||||||
Future<void> fetch() async {
|
Future<void> fetch() async {
|
||||||
if (!Platform.isAndroid) return;
|
if (!Platform.isAndroid) return;
|
||||||
|
|
||||||
@@ -30,9 +29,10 @@ class UpdateProvider extends ChangeNotifier {
|
|||||||
_releases.sort((a, b) => -a.version.compareTo(b.version));
|
_releases.sort((a, b) => -a.version.compareTo(b.version));
|
||||||
|
|
||||||
// Check for new releases
|
// Check for new releases
|
||||||
if (_releases.length > 0) {
|
if (_releases.isNotEmpty) {
|
||||||
print("INFO: New update: ${releases.first.version}");
|
_available = _releases.first.version.compareTo(Version.fromString(currentVersion)) == 1;
|
||||||
_available = _packageInfo != null && _releases.first.version.compareTo(Version.fromString(_packageInfo?.version ?? "")) == 1;
|
// ignore: avoid_print
|
||||||
|
if (_available) print("INFO: New update: ${releases.first.version}");
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import 'package:filcnaplo_kreta_api/models/student.dart';
|
|||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
||||||
class UserProvider with ChangeNotifier {
|
class UserProvider with ChangeNotifier {
|
||||||
Map<String, User> _users = {};
|
final Map<String, User> _users = {};
|
||||||
String? _selectedUserId;
|
String? _selectedUserId;
|
||||||
User? get user => _users[_selectedUserId];
|
User? get user => _users[_selectedUserId];
|
||||||
|
|
||||||
@@ -13,6 +13,7 @@ class UserProvider with ChangeNotifier {
|
|||||||
String? get name => user?.name;
|
String? get name => user?.name;
|
||||||
String? get username => user?.username;
|
String? get username => user?.username;
|
||||||
String? get password => user?.password;
|
String? get password => user?.password;
|
||||||
|
Role? get role => user?.role;
|
||||||
Student? get student => user?.student;
|
Student? get student => user?.student;
|
||||||
|
|
||||||
void setUser(String userId) {
|
void setUser(String userId) {
|
||||||
@@ -22,7 +23,9 @@ class UserProvider with ChangeNotifier {
|
|||||||
|
|
||||||
void addUser(User user) {
|
void addUser(User user) {
|
||||||
_users[user.id] = user;
|
_users[user.id] = user;
|
||||||
print("DEBUG: Added User: ${user.id} ${user.name}");
|
if (kDebugMode) {
|
||||||
|
print("DEBUG: Added User: ${user.id}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeUser(String userId) {
|
void removeUser(String userId) {
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
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/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/models/config.dart';
|
import 'package:filcnaplo/models/config.dart';
|
||||||
import 'package:filcnaplo/theme.dart';
|
import 'package:filcnaplo/theme.dart';
|
||||||
import 'package:filcnaplo_kreta_api/client/client.dart';
|
import 'package:filcnaplo_kreta_api/client/client.dart';
|
||||||
@@ -14,6 +19,7 @@ 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';
|
||||||
|
|
||||||
// Providers
|
// Providers
|
||||||
@@ -29,6 +35,7 @@ import 'package:filcnaplo_kreta_api/providers/timetable_provider.dart';
|
|||||||
import 'package:filcnaplo/api/providers/user_provider.dart';
|
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';
|
||||||
|
|
||||||
class App extends StatelessWidget {
|
class App extends StatelessWidget {
|
||||||
final SettingsProvider settings;
|
final SettingsProvider settings;
|
||||||
@@ -36,25 +43,31 @@ class App extends StatelessWidget {
|
|||||||
final DatabaseProvider database;
|
final DatabaseProvider database;
|
||||||
|
|
||||||
App({Key? key, required this.database, required this.settings, required this.user}) : super(key: key) {
|
App({Key? key, required this.database, required this.settings, required this.user}) : super(key: key) {
|
||||||
if (user.getUsers().length > 0) user.setUser(user.getUsers().first.id);
|
if (user.getUsers().isNotEmpty) user.setUser(user.getUsers().first.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
setSystemChrome(context);
|
setSystemChrome(context);
|
||||||
|
|
||||||
WidgetsBinding.instance?.addPostFrameCallback((_) {
|
// Set high refresh mode #28
|
||||||
FilcAPI.getConfig().then((Config? config) {
|
if (Platform.isAndroid) FlutterDisplayMode.setHighRefreshRate();
|
||||||
settings.update(context, database: database, config: config ?? Config.fromJson({}));
|
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
FilcAPI.getConfig(settings).then((Config? config) {
|
||||||
|
if (config != null) settings.update(context, database: database, config: config);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
CorePalette? corePalette;
|
||||||
|
|
||||||
return I18n(
|
return I18n(
|
||||||
initialLocale: Locale(settings.language, settings.language),
|
initialLocale: Locale(settings.language, settings.language.toUpperCase()),
|
||||||
child: MultiProvider(
|
child: MultiProvider(
|
||||||
providers: [
|
providers: [
|
||||||
ChangeNotifierProvider<SettingsProvider>(create: (_) => settings),
|
ChangeNotifierProvider<SettingsProvider>(create: (_) => settings),
|
||||||
ChangeNotifierProvider<UserProvider>(create: (_) => user),
|
ChangeNotifierProvider<UserProvider>(create: (_) => user),
|
||||||
|
ChangeNotifierProvider<StatusProvider>(create: (context) => StatusProvider()),
|
||||||
Provider<KretaClient>(create: (context) => KretaClient(context: context, userAgent: settings.config.userAgent)),
|
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)),
|
||||||
@@ -74,24 +87,57 @@ class App extends StatelessWidget {
|
|||||||
ChangeNotifierProvider<GradeCalculatorProvider>(create: (context) => GradeCalculatorProvider(context)),
|
ChangeNotifierProvider<GradeCalculatorProvider>(create: (context) => GradeCalculatorProvider(context)),
|
||||||
],
|
],
|
||||||
child: Consumer<ThemeModeObserver>(
|
child: Consumer<ThemeModeObserver>(
|
||||||
builder: (context, themeMode, child) => MaterialApp(
|
builder: (context, themeMode, child) {
|
||||||
|
return FutureBuilder<CorePalette?>(
|
||||||
|
future: DynamicColorPlugin.getCorePalette(),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
corePalette = snapshot.data;
|
||||||
|
return MaterialApp(
|
||||||
|
builder: (context, child) {
|
||||||
|
// Limit font size scaling to 1.0
|
||||||
|
double textScaleFactor = min(MediaQuery.of(context).textScaleFactor, 1.0);
|
||||||
|
|
||||||
|
return MediaQuery(
|
||||||
|
data: MediaQuery.of(context).copyWith(textScaleFactor: textScaleFactor),
|
||||||
|
child: SafeArea(
|
||||||
|
top: false,
|
||||||
|
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: [
|
localizationsDelegates: const [
|
||||||
GlobalMaterialLocalizations.delegate,
|
GlobalMaterialLocalizations.delegate,
|
||||||
GlobalWidgetsLocalizations.delegate,
|
GlobalWidgetsLocalizations.delegate,
|
||||||
GlobalCupertinoLocalizations.delegate,
|
GlobalCupertinoLocalizations.delegate,
|
||||||
],
|
],
|
||||||
supportedLocales: [
|
supportedLocales: const [
|
||||||
const Locale('en'),
|
Locale('en', 'EN'),
|
||||||
const Locale('hu'),
|
Locale('hu', 'HU'),
|
||||||
const Locale('de'),
|
Locale('de', 'DE'),
|
||||||
],
|
],
|
||||||
|
localeListResolutionCallback: (locales, supported) {
|
||||||
|
Locale locale = const Locale('hu', 'HU');
|
||||||
|
|
||||||
|
for (var loc in locales ?? []) {
|
||||||
|
if (supported.contains(loc)) {
|
||||||
|
locale = loc;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return locale;
|
||||||
|
},
|
||||||
onGenerateRoute: (settings) => rootNavigator(settings),
|
onGenerateRoute: (settings) => rootNavigator(settings),
|
||||||
initialRoute: user.getUsers().length > 0 ? "navigation" : "login"),
|
initialRoute: user.getUsers().isNotEmpty ? "navigation" : "login",
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -101,16 +147,17 @@ class App extends StatelessWidget {
|
|||||||
// if platform == android || platform == ios
|
// if platform == android || platform == ios
|
||||||
switch (route.name) {
|
switch (route.name) {
|
||||||
case "login_back":
|
case "login_back":
|
||||||
return CupertinoPageRoute(builder: (context) => LoginScreen(back: true));
|
return CupertinoPageRoute(builder: (context) => const LoginScreen(back: true));
|
||||||
case "login":
|
case "login":
|
||||||
return _rootRoute(LoginScreen());
|
return _rootRoute(const LoginScreen());
|
||||||
case "navigation":
|
case "navigation":
|
||||||
return _rootRoute(Navigation());
|
return _rootRoute(const NavigationScreen());
|
||||||
case "login_to_navigation":
|
case "login_to_navigation":
|
||||||
return loginRoute(Navigation());
|
return loginRoute(const NavigationScreen());
|
||||||
case "settings":
|
case "settings":
|
||||||
return settingsRoute(SettingsScreen());
|
return settingsRoute(const SettingsScreen());
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
// else if platform == windows || ...
|
// else if platform == windows || ...
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,71 +1,126 @@
|
|||||||
|
// ignore_for_file: avoid_print
|
||||||
|
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
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';
|
||||||
|
import 'package:sqflite_common_ffi/sqflite_ffi.dart';
|
||||||
|
|
||||||
|
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, // 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,
|
||||||
|
});
|
||||||
|
const usersDB = DatabaseStruct(
|
||||||
|
"users", {"id": String, "name": String, "username": String, "password": String, "institute_code": String, "student": String, "role": int});
|
||||||
|
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
|
||||||
|
});
|
||||||
|
|
||||||
|
Future<void> createTable(Database db, DatabaseStruct struct) => db.execute("CREATE TABLE IF NOT EXISTS ${struct.table} ($struct)");
|
||||||
|
|
||||||
Future<Database> initDB() async {
|
Future<Database> initDB() async {
|
||||||
// await deleteDatabase('app.db'); // for debugging
|
Database db;
|
||||||
var db = await openDatabase('app.db');
|
|
||||||
|
|
||||||
var settingsDB = await createSettingsTable(db);
|
if (Platform.isLinux || Platform.isWindows) {
|
||||||
|
sqfliteFfiInit();
|
||||||
|
db = await databaseFactoryFfi.openDatabase("app.db");
|
||||||
|
} else {
|
||||||
|
db = await openDatabase("app.db");
|
||||||
|
}
|
||||||
|
|
||||||
// Create table Users
|
await createTable(db, settingsDB);
|
||||||
await db.execute("CREATE TABLE IF NOT EXISTS users (id TEXT NOT NULL, name TEXT, username TEXT, password TEXT, institute_code TEXT, student TEXT)");
|
await createTable(db, usersDB);
|
||||||
await db.execute("CREATE TABLE IF NOT EXISTS user_data ("
|
await createTable(db, userDataDB);
|
||||||
"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().toMap());
|
||||||
}
|
}
|
||||||
|
|
||||||
await migrateDB(db, settingsDB.struct.keys);
|
// Migrate Databases
|
||||||
|
try {
|
||||||
|
await migrateDB(
|
||||||
|
db,
|
||||||
|
struct: settingsDB,
|
||||||
|
defaultValues: SettingsProvider.defaultSettings().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
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
print("ERROR: migrateDB: $error");
|
||||||
|
}
|
||||||
|
|
||||||
return db;
|
return db;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<DatabaseStruct> createSettingsTable(Database db) async {
|
Future<void> migrateDB(
|
||||||
var settingsDB = DatabaseStruct({
|
Database db, {
|
||||||
"language": String, "start_page": int, "rounding": int, "theme": int, "accent_color": int, "news": int, "news_state": int, "developer_mode": int,
|
required DatabaseStruct struct,
|
||||||
"update_channel": int, "config": String, // general
|
required Map<String, Object?> defaultValues,
|
||||||
"grade_color1": int, "grade_color2": int, "grade_color3": int, "grade_color4": int, "grade_color5": int, // grade colors
|
}) async {
|
||||||
"vibrate": int, "vibration_strength": int, "ab_weeks": int, "swap_ab_weeks": int,
|
var originalRows = await db.query(struct.table);
|
||||||
"notifications": int, "notifications_bitfield": int, "notification_poll_interval": int, // notifications
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create table Settings
|
if (originalRows.isEmpty) {
|
||||||
await db.execute("CREATE TABLE IF NOT EXISTS settings ($settingsDB)");
|
await db.execute("drop table ${struct.table}");
|
||||||
|
await createTable(db, struct);
|
||||||
return settingsDB;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> migrateDB(Database db, Iterable<String> keys) async {
|
List<Map<String, dynamic>> migrated = [];
|
||||||
var settings = (await db.query("settings"))[0];
|
|
||||||
|
|
||||||
bool migrationRequired = keys.any((key) => !settings.containsKey(key) || settings[key] == null);
|
// go through each row and add missing keys or delete non existing keys
|
||||||
|
await Future.forEach<Map<String, Object?>>(originalRows, (original) async {
|
||||||
|
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) {
|
||||||
var defaultSettings = SettingsProvider.defaultSettings();
|
print("INFO: Migrating ${struct.table}");
|
||||||
var settingsCopy = Map<String, dynamic>.from(settings);
|
var copy = Map<String, Object?>.from(original);
|
||||||
|
|
||||||
// Delete settings
|
|
||||||
await db.execute("drop table settings");
|
|
||||||
|
|
||||||
// Fill missing columns
|
// Fill missing columns
|
||||||
keys.forEach((key) {
|
for (var key in struct.struct.keys) {
|
||||||
if (!keys.contains(key)) {
|
if (!original.containsKey(key) || original[key] == null) {
|
||||||
print("debug: dropping $key");
|
print("DEBUG: migrating $key");
|
||||||
settingsCopy.remove(key);
|
copy[key] = defaultValues[key];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!settings.containsKey(key) || settings[key] == null) {
|
for (var key in original.keys) {
|
||||||
print("DEBUG: migrating $key");
|
if (!struct.struct.keys.contains(key)) {
|
||||||
settingsCopy[key] = defaultSettings.toMap()[key];
|
print("DEBUG: dropping $key");
|
||||||
|
copy.remove(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
migrated.add(copy);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Recreate settings
|
// replace the old table with the migrated one
|
||||||
await createSettingsTable(db);
|
if (migrated.isNotEmpty) {
|
||||||
await db.insert("settings", settingsCopy);
|
// Delete table
|
||||||
|
await db.execute("drop table ${struct.table}");
|
||||||
|
|
||||||
|
// Recreate table
|
||||||
|
await createTable(db, struct);
|
||||||
|
await Future.forEach(migrated, (Map<String, Object?> copy) async {
|
||||||
|
await db.insert(struct.table, copy);
|
||||||
|
});
|
||||||
|
|
||||||
print("INFO: Database migrated");
|
print("INFO: Database migrated");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
import 'package:filcnaplo/models/subject_lesson_count.dart';
|
||||||
import 'package:filcnaplo/models/user.dart';
|
import 'package:filcnaplo/models/user.dart';
|
||||||
import 'package:sqflite/sqflite.dart';
|
import 'package:sqflite_common/sqlite_api.dart';
|
||||||
|
|
||||||
// Models
|
// Models
|
||||||
import 'package:filcnaplo/models/settings.dart';
|
import 'package:filcnaplo/models/settings.dart';
|
||||||
@@ -13,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 DatabaseQuery {
|
class DatabaseQuery {
|
||||||
DatabaseQuery({required this.db});
|
DatabaseQuery({required this.db});
|
||||||
@@ -28,9 +30,9 @@ class DatabaseQuery {
|
|||||||
Future<UserProvider> getUsers() async {
|
Future<UserProvider> getUsers() async {
|
||||||
var userProvider = UserProvider();
|
var userProvider = UserProvider();
|
||||||
List<Map> usersMap = await db.query("users");
|
List<Map> usersMap = await db.query("users");
|
||||||
usersMap.forEach((user) {
|
for (var user in usersMap) {
|
||||||
userProvider.addUser(User.fromMap(user));
|
userProvider.addUser(User.fromMap(user));
|
||||||
});
|
}
|
||||||
return userProvider;
|
return userProvider;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -42,7 +44,7 @@ class UserDatabaseQuery {
|
|||||||
|
|
||||||
Future<List<Grade>> getGrades({required String userId}) async {
|
Future<List<Grade>> getGrades({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.length == 0) return [];
|
if (userData.isEmpty) return [];
|
||||||
String? gradesJson = userData.elementAt(0)["grades"] as String?;
|
String? gradesJson = userData.elementAt(0)["grades"] as String?;
|
||||||
if (gradesJson == null) return [];
|
if (gradesJson == null) return [];
|
||||||
List<Grade> grades = (jsonDecode(gradesJson) as List).map((e) => Grade.fromJson(e)).toList();
|
List<Grade> grades = (jsonDecode(gradesJson) as List).map((e) => Grade.fromJson(e)).toList();
|
||||||
@@ -51,7 +53,7 @@ class UserDatabaseQuery {
|
|||||||
|
|
||||||
Future<List<Lesson>> getLessons({required String userId}) async {
|
Future<List<Lesson>> getLessons({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.length == 0) return [];
|
if (userData.isEmpty) return [];
|
||||||
String? lessonsJson = userData.elementAt(0)["timetable"] as String?;
|
String? lessonsJson = userData.elementAt(0)["timetable"] as String?;
|
||||||
if (lessonsJson == null) return [];
|
if (lessonsJson == null) return [];
|
||||||
List<Lesson> lessons = (jsonDecode(lessonsJson) as List).map((e) => Lesson.fromJson(e)).toList();
|
List<Lesson> lessons = (jsonDecode(lessonsJson) as List).map((e) => Lesson.fromJson(e)).toList();
|
||||||
@@ -60,7 +62,7 @@ class UserDatabaseQuery {
|
|||||||
|
|
||||||
Future<List<Exam>> getExams({required String userId}) async {
|
Future<List<Exam>> getExams({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.length == 0) return [];
|
if (userData.isEmpty) return [];
|
||||||
String? examsJson = userData.elementAt(0)["exams"] as String?;
|
String? examsJson = userData.elementAt(0)["exams"] as String?;
|
||||||
if (examsJson == null) return [];
|
if (examsJson == null) return [];
|
||||||
List<Exam> exams = (jsonDecode(examsJson) as List).map((e) => Exam.fromJson(e)).toList();
|
List<Exam> exams = (jsonDecode(examsJson) as List).map((e) => Exam.fromJson(e)).toList();
|
||||||
@@ -69,7 +71,7 @@ class UserDatabaseQuery {
|
|||||||
|
|
||||||
Future<List<Homework>> getHomework({required String userId}) async {
|
Future<List<Homework>> getHomework({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.length == 0) return [];
|
if (userData.isEmpty) return [];
|
||||||
String? homeworkJson = userData.elementAt(0)["homework"] as String?;
|
String? homeworkJson = userData.elementAt(0)["homework"] as String?;
|
||||||
if (homeworkJson == null) return [];
|
if (homeworkJson == null) return [];
|
||||||
List<Homework> homework = (jsonDecode(homeworkJson) as List).map((e) => Homework.fromJson(e)).toList();
|
List<Homework> homework = (jsonDecode(homeworkJson) as List).map((e) => Homework.fromJson(e)).toList();
|
||||||
@@ -78,7 +80,7 @@ class UserDatabaseQuery {
|
|||||||
|
|
||||||
Future<List<Message>> getMessages({required String userId}) async {
|
Future<List<Message>> getMessages({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.length == 0) return [];
|
if (userData.isEmpty) return [];
|
||||||
String? messagesJson = userData.elementAt(0)["messages"] as String?;
|
String? messagesJson = userData.elementAt(0)["messages"] as String?;
|
||||||
if (messagesJson == null) return [];
|
if (messagesJson == null) return [];
|
||||||
List<Message> messages = (jsonDecode(messagesJson) as List).map((e) => Message.fromJson(e)).toList();
|
List<Message> messages = (jsonDecode(messagesJson) as List).map((e) => Message.fromJson(e)).toList();
|
||||||
@@ -87,7 +89,7 @@ class UserDatabaseQuery {
|
|||||||
|
|
||||||
Future<List<Note>> getNotes({required String userId}) async {
|
Future<List<Note>> getNotes({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.length == 0) return [];
|
if (userData.isEmpty) return [];
|
||||||
String? notesJson = userData.elementAt(0)["notes"] as String?;
|
String? notesJson = userData.elementAt(0)["notes"] as String?;
|
||||||
if (notesJson == null) return [];
|
if (notesJson == null) return [];
|
||||||
List<Note> notes = (jsonDecode(notesJson) as List).map((e) => Note.fromJson(e)).toList();
|
List<Note> notes = (jsonDecode(notesJson) as List).map((e) => Note.fromJson(e)).toList();
|
||||||
@@ -96,7 +98,7 @@ class UserDatabaseQuery {
|
|||||||
|
|
||||||
Future<List<Event>> getEvents({required String userId}) async {
|
Future<List<Event>> getEvents({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.length == 0) return [];
|
if (userData.isEmpty) return [];
|
||||||
String? eventsJson = userData.elementAt(0)["events"] as String?;
|
String? eventsJson = userData.elementAt(0)["events"] as String?;
|
||||||
if (eventsJson == null) return [];
|
if (eventsJson == null) return [];
|
||||||
List<Event> events = (jsonDecode(eventsJson) as List).map((e) => Event.fromJson(e)).toList();
|
List<Event> events = (jsonDecode(eventsJson) as List).map((e) => Event.fromJson(e)).toList();
|
||||||
@@ -105,10 +107,28 @@ 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.length == 0) 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'package:sqflite/sqflite.dart';
|
import 'package:filcnaplo/models/subject_lesson_count.dart';
|
||||||
|
import 'package:sqflite_common/sqlite_api.dart';
|
||||||
|
|
||||||
// Models
|
// Models
|
||||||
import 'package:filcnaplo/models/settings.dart';
|
import 'package:filcnaplo/models/settings.dart';
|
||||||
@@ -12,6 +13,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});
|
||||||
@@ -24,7 +26,7 @@ class DatabaseStore {
|
|||||||
|
|
||||||
Future<void> storeUser(User user) async {
|
Future<void> storeUser(User user) async {
|
||||||
List userRes = await db.query("users", where: "id = ?", whereArgs: [user.id]);
|
List userRes = await db.query("users", where: "id = ?", whereArgs: [user.id]);
|
||||||
if (userRes.length > 0) {
|
if (userRes.isNotEmpty) {
|
||||||
await db.update("users", user.toMap(), where: "id = ?", whereArgs: [user.id]);
|
await db.update("users", user.toMap(), where: "id = ?", whereArgs: [user.id]);
|
||||||
} else {
|
} else {
|
||||||
await db.insert("users", user.toMap());
|
await db.insert("users", user.toMap());
|
||||||
@@ -43,43 +45,54 @@ 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]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 = "";
|
||||||
@@ -15,7 +16,7 @@ class DatabaseStruct {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return "${name} ${typeName.toUpperCase()}";
|
return "$name ${typeName.toUpperCase()} ${name == 'id' ? 'NOT NULL' : ''}";
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
|
import 'package:filcnaplo/api/providers/user_provider.dart';
|
||||||
import 'package:filcnaplo/helpers/storage_helper.dart';
|
import 'package:filcnaplo/helpers/storage_helper.dart';
|
||||||
import 'package:filcnaplo_kreta_api/client/client.dart';
|
import 'package:filcnaplo_kreta_api/client/client.dart';
|
||||||
import 'package:filcnaplo_kreta_api/models/attachment.dart';
|
import 'package:filcnaplo_kreta_api/models/attachment.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/homework.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:open_file/open_file.dart';
|
import 'package:open_file/open_file.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
@@ -28,3 +30,25 @@ extension AttachmentHelper on Attachment {
|
|||||||
return result.type == ResultType.done;
|
return result.type == ResultType.done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension HomeworkAttachmentHelper on HomeworkAttachment {
|
||||||
|
Future<String> download(BuildContext context, {bool overwrite = false}) async {
|
||||||
|
String downloads = await StorageHelper.downloadsPath();
|
||||||
|
|
||||||
|
if (!overwrite && await File("$downloads/$name").exists()) return "$downloads/$name";
|
||||||
|
|
||||||
|
String url = downloadUrl(Provider.of<UserProvider>(context, listen: false).instituteCode ?? "");
|
||||||
|
Uint8List data = await Provider.of<KretaClient>(context, listen: false).getAPI(url, rawResponse: true);
|
||||||
|
if (!await StorageHelper.write("$downloads/$name", data)) return "";
|
||||||
|
|
||||||
|
return "$downloads/$name";
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> open(BuildContext context) async {
|
||||||
|
String downloads = await StorageHelper.downloadsPath();
|
||||||
|
|
||||||
|
if (!await File("$downloads/$name").exists()) await download(context);
|
||||||
|
var result = await OpenFile.open("$downloads/$name");
|
||||||
|
return result.type == ResultType.done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,14 +6,15 @@ 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) ||
|
(e.value.value == 0) ||
|
||||||
(ignoreInFinal.contains(e.gradeType?.id)));
|
(ignoreInFinal.contains(e.gradeType?.id)));
|
||||||
|
}
|
||||||
|
|
||||||
grades.forEach((e) {
|
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
|
grades
|
||||||
|
|||||||
36
filcnaplo/lib/helpers/quick_actions.dart
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:quick_actions/quick_actions.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/common/screens.i18n.dart';
|
||||||
|
|
||||||
|
const QuickActions quickActions = QuickActions();
|
||||||
|
|
||||||
|
void setupQuickActions() {
|
||||||
|
quickActions.setShortcutItems(<ShortcutItem>[
|
||||||
|
ShortcutItem(type: 'action_grades', localizedTitle: 'grades'.i18n, icon: 'ic_grades'),
|
||||||
|
ShortcutItem(type: 'action_timetable', localizedTitle: 'timetable'.i18n, icon: 'ic_timetable'),
|
||||||
|
ShortcutItem(type: 'action_messages', localizedTitle: 'messages'.i18n, icon: 'ic_messages'),
|
||||||
|
ShortcutItem(type: 'action_absences', localizedTitle: 'absences'.i18n, icon: 'ic_absences')
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleQuickActions(BuildContext context, void Function(String) callback) {
|
||||||
|
quickActions.initialize((shortcutType) {
|
||||||
|
switch (shortcutType) {
|
||||||
|
case 'action_home':
|
||||||
|
callback("home");
|
||||||
|
break;
|
||||||
|
case 'action_grades':
|
||||||
|
callback("grades");
|
||||||
|
break;
|
||||||
|
case 'action_timetable':
|
||||||
|
callback("timetable");
|
||||||
|
break;
|
||||||
|
case 'action_messages':
|
||||||
|
callback("messages");
|
||||||
|
break;
|
||||||
|
case 'action_absences':
|
||||||
|
callback("absences");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
// ignore_for_file: avoid_print
|
||||||
|
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
|
|||||||
@@ -7,16 +7,16 @@ class SubjectIcon {
|
|||||||
static IconData? lookup({Subject? subject, String? subjectName}) {
|
static IconData? lookup({Subject? subject, String? subjectName}) {
|
||||||
assert(!(subject == null && subjectName == null));
|
assert(!(subject == null && subjectName == null));
|
||||||
|
|
||||||
String name = subject?.name.toLowerCase().specialChars() ?? subjectName ?? "";
|
String name = (subject?.name ?? subjectName ?? "").toLowerCase().specialChars().trim();
|
||||||
String category = subject?.category.description.toLowerCase().specialChars() ?? "";
|
String category = subject?.category.description.toLowerCase().specialChars() ?? "";
|
||||||
|
|
||||||
// todo: check for categories
|
// todo: check for categories
|
||||||
if (RegExp("mate(k|matika)").hasMatch(name) || category == "matematika") return Icons.calculate_outlined;
|
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("magyar nyelv|nyelvtan").hasMatch(name)) return Icons.spellcheck_outlined;
|
||||||
if (RegExp("irodalom").hasMatch(name)) return Icons.menu_book_outlined;
|
if (RegExp("irodalom").hasMatch(name)) return Icons.menu_book_outlined;
|
||||||
if (RegExp("rajz|muvtori|muveszet|kultura").hasMatch(name)) return Icons.palette_outlined;
|
|
||||||
if (RegExp("tor(i|tenelem)").hasMatch(name)) return Icons.hourglass_empty_outlined;
|
if (RegExp("tor(i|tenelem)").hasMatch(name)) return Icons.hourglass_empty_outlined;
|
||||||
if (RegExp("foldrajz").hasMatch(name)) return Icons.public_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("fizika").hasMatch(name)) return Icons.emoji_objects_outlined;
|
||||||
if (RegExp("^enek|zene|szolfezs|zongora|korus").hasMatch(name)) return Icons.music_note_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("^tes(i|tneveles)|sport").hasMatch(name)) return Icons.sports_soccer_outlined;
|
||||||
@@ -25,7 +25,7 @@ class SubjectIcon {
|
|||||||
if (RegExp("kornyezet|termeszet(tudomany|ismeret)|hon( es nep)?ismeret").hasMatch(name)) return Icons.eco_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("(hit|erkolcs)tan|vallas|etika").hasMatch(name)) return Icons.favorite_border_outlined;
|
||||||
if (RegExp("penzugy").hasMatch(name)) return Icons.savings_outlined;
|
if (RegExp("penzugy").hasMatch(name)) return Icons.savings_outlined;
|
||||||
if (RegExp("informatika|szoftver|iroda").hasMatch(name)) return Icons.computer_outlined;
|
if (RegExp("informatika|szoftver|iroda|digitalis").hasMatch(name)) return Icons.computer_outlined;
|
||||||
if (RegExp("prog").hasMatch(name)) return Icons.code_outlined;
|
if (RegExp("prog").hasMatch(name)) return Icons.code_outlined;
|
||||||
if (RegExp("halozat").hasMatch(name)) return Icons.wifi_tethering_outlined;
|
if (RegExp("halozat").hasMatch(name)) return Icons.wifi_tethering_outlined;
|
||||||
if (RegExp("szinhaz").hasMatch(name)) return Icons.theater_comedy_outlined;
|
if (RegExp("szinhaz").hasMatch(name)) return Icons.theater_comedy_outlined;
|
||||||
@@ -35,7 +35,7 @@ class SubjectIcon {
|
|||||||
if (RegExp("technika").hasMatch(name)) return Icons.build_outlined;
|
if (RegExp("technika").hasMatch(name)) return Icons.build_outlined;
|
||||||
if (RegExp("tanc").hasMatch(name)) return Icons.speaker_outlined;
|
if (RegExp("tanc").hasMatch(name)) return Icons.speaker_outlined;
|
||||||
if (RegExp("filozofia").hasMatch(name)) return Icons.psychology_outlined;
|
if (RegExp("filozofia").hasMatch(name)) return Icons.psychology_outlined;
|
||||||
if (RegExp("osztaly(fonoki|kozosseg)").hasMatch(name)) return Icons.groups_outlined;
|
if (RegExp("osztaly(fonoki|kozosseg)").hasMatch(name) || name == "ofo") return Icons.groups_outlined;
|
||||||
if (RegExp("gazdasag").hasMatch(name)) return Icons.account_balance_outlined;
|
if (RegExp("gazdasag").hasMatch(name)) return Icons.account_balance_outlined;
|
||||||
if (RegExp("szorgalom").hasMatch(name)) return Icons.verified_outlined;
|
if (RegExp("szorgalom").hasMatch(name)) return Icons.verified_outlined;
|
||||||
if (RegExp("magatartas").hasMatch(name)) return Icons.emoji_people_outlined;
|
if (RegExp("magatartas").hasMatch(name)) return Icons.emoji_people_outlined;
|
||||||
|
|||||||