Compare commits
58 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e31d0753d1 | ||
|
|
526c66f358 | ||
|
|
d6833a952d | ||
|
|
4760761bb7 | ||
|
|
a33e6dae3b | ||
|
|
d393181f10 | ||
|
|
12df8b82c7 | ||
|
|
1c7eba7af3 | ||
|
|
d39cdaef10 | ||
|
|
cc40fb9c0f | ||
|
|
85c6d548ad | ||
|
|
8dbf605450 | ||
|
|
2f418a7c1a | ||
|
|
5f0c82f54c | ||
|
|
4e659308e5 | ||
|
|
50e24bde17 | ||
|
|
31f7c6a465 | ||
|
|
e734579249 | ||
|
|
2cff46d628 | ||
|
|
87f3f93177 | ||
|
|
30733caa4a | ||
|
|
4e30a550e1 | ||
|
|
cb687d6b10 | ||
|
|
6c6d3a7cd8 | ||
|
|
da06e400e1 | ||
|
|
87b8cbb60f | ||
|
|
8bac300585 | ||
|
|
da7d2b9333 | ||
|
|
e1f84caf19 | ||
|
|
274da2b766 | ||
|
|
35aba35801 | ||
|
|
964e002c46 | ||
|
|
d3318e10ab | ||
|
|
4c43369d59 | ||
|
|
176243b881 | ||
|
|
ed02a340d0 | ||
|
|
2877f4fc5c | ||
|
|
fceb3bf31a | ||
|
|
9883d081ff | ||
|
|
db5a9fb197 | ||
|
|
93438ce3df | ||
|
|
95bca64fb8 | ||
|
|
7821e10869 | ||
|
|
cede3c3129 | ||
|
|
528ee862b9 | ||
|
|
d1507f5eae | ||
|
|
f5682e9137 | ||
|
|
518932c260 | ||
|
|
139d8869c2 | ||
|
|
29bf0c81dd | ||
|
|
9e510bed2d | ||
|
|
ef7437979c | ||
|
|
b1e68f18b0 | ||
|
|
5e02e697d2 | ||
|
|
bfa77fcfb6 | ||
|
|
bcf9d9688f | ||
|
|
281b9cf6c4 | ||
|
|
fb0de5a991 |
25
.gitignore
vendored
@@ -25,3 +25,28 @@ doc/api/
|
||||
*.js.map
|
||||
|
||||
*.txt
|
||||
filcnaplo/linux/flutter/generated_plugin_registrant.cc
|
||||
filcnaplo/linux/flutter/generated_plugin_registrant.h
|
||||
filcnaplo/linux/flutter/generated_plugins.cmake
|
||||
filcnaplo/macos/Flutter/GeneratedPluginRegistrant.swift
|
||||
filcnaplo/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus
|
||||
filcnaplo/windows/flutter/ephemeral/.plugin_symlinks/dynamic_color
|
||||
filcnaplo/windows/flutter/ephemeral/.plugin_symlinks/flutter_acrylic
|
||||
filcnaplo/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows
|
||||
filcnaplo/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows
|
||||
filcnaplo/windows/flutter/ephemeral/.plugin_symlinks/share_plus_windows
|
||||
filcnaplo/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows
|
||||
filcnaplo/windows/flutter/ephemeral/generated_config.cmake
|
||||
filcnaplo/windows/flutter/generated_plugin_registrant.cc
|
||||
filcnaplo/windows/flutter/generated_plugin_registrant.h
|
||||
filcnaplo/windows/flutter/generated_plugins.cmake
|
||||
filcnaplo/linux/flutter/generated_plugin_registrant.cc
|
||||
filcnaplo/linux/flutter/generated_plugin_registrant.h
|
||||
filcnaplo/linux/flutter/generated_plugins.cmake
|
||||
filcnaplo/macos/Flutter/GeneratedPluginRegistrant.swift
|
||||
filcnaplo/linux/flutter/generated_plugin_registrant.cc
|
||||
filcnaplo/linux/flutter/generated_plugin_registrant.h
|
||||
filcnaplo/linux/flutter/generated_plugins.cmake
|
||||
filcnaplo/macos/Flutter/GeneratedPluginRegistrant.swift
|
||||
.vscode/
|
||||
|
||||
24
.vscode/launch.json
vendored
@@ -1,7 +1,4 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
@@ -10,8 +7,27 @@
|
||||
"request": "launch",
|
||||
"type": "dart",
|
||||
"toolArgs": [
|
||||
"--dart-define=APPVER=$(cat pubspec.yaml | grep version: | cut -d' ' -f2 | cut -d+ -f1) --release"
|
||||
"--dart-define=APPVER=$(cat pubspec.yaml | grep version: | cut -d' ' -f2 | cut -d+ -f1)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "filcnaplo release",
|
||||
"cwd": "filcnaplo release",
|
||||
"request": "launch",
|
||||
"type": "dart",
|
||||
"flutterMode": "release",
|
||||
"program": "lib/main.dart",
|
||||
"toolArgs": [
|
||||
"--dart-define=APPVER=$(cat pubspec.yaml | grep version: | cut -d' ' -f2 | cut -d+ -f1)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Flutter",
|
||||
"program": "lib/main.dart",
|
||||
"cwd": "filcnaplo",
|
||||
"request": "launch",
|
||||
"type": "dart",
|
||||
"flutterMode": "debug"
|
||||
}
|
||||
]
|
||||
}
|
||||
10
README.md
@@ -1,11 +1,11 @@
|
||||
<p align=center>
|
||||
<img src="https://media.discordapp.net/attachments/1111727410677825596/1111790518964326510/reFilc_Logo2.png?width=671&height=671" width=150>
|
||||
<img src="https://media.discordapp.net/attachments/1111727410677825596/1113217167513624646/reFilc_Logo_Squircle.png?width=671&height=671" width=150>
|
||||
<h1 align=center><b>reFilc</b></h1>
|
||||
</p>
|
||||
|
||||
#### Nem hivatalos e-napló alkalmazás az eKRÉTA rendszerhez - tanulóktól, tanulóknak.
|
||||
|
||||
[](https://github.com/refilc/naplo/releases) [](http://dc.refilc.hu)
|
||||
[](https://github.com/refilc/naplo/releases) [](http://dc.refilc.hu)
|
||||
|
||||
## Setup
|
||||
|
||||
@@ -27,12 +27,16 @@ cd filcnaplo
|
||||
flutter run
|
||||
```
|
||||
|
||||
### Contribution
|
||||
|
||||
Az összes (ugyan azon verzióhoz tartozó) contribution meg fog jelenni a release-nél. Kérjük, írd le a Discord nevedet a Description-be, hogy adhassunk rangot.
|
||||
|
||||
-------
|
||||
|
||||
# Kudo
|
||||
|
||||
**annon:** a Filc napló készítője (ez az app a Filcen alapul)
|
||||
|
||||
**kima, chromium, peighter, mog, WolfY:** a fejlesztői csapat
|
||||
**kima, mog, WolfY:** fő fejlesztők
|
||||
|
||||
**Regő, Pearoo:** weboldal design és community management
|
||||
|
||||
@@ -44,7 +44,7 @@ android {
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
applicationId "hu.filc.naplo"
|
||||
applicationId "hu.refilc.naplo"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode flutterVersionCode.toInteger()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<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.refilc.naplo">
|
||||
<!-- Permissions -->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools" package="hu.filc.naplo">
|
||||
xmlns:tools="http://schemas.android.com/tools" package="hu.refilc.naplo">
|
||||
<application android:label="reFilc" tools:replace="android:label" android:icon="@mipmap/ic_launcher"
|
||||
android:requestLegacyExternalStorage="true">
|
||||
<activity android:exported="true" android:name=".MainActivity"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package hu.filc.naplo;
|
||||
package hu.refilc.naplo;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 103 KiB |
|
Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 7.7 KiB |
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.3 KiB |
@@ -2,4 +2,5 @@
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
<monochrome android:drawable="@mipmap/ic_launcher_monochrome" />
|
||||
</adaptive-icon>
|
||||
|
||||
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 844 B |
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 450 B |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 916 B After Width: | Height: | Size: 576 B |
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 9.2 KiB |
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 155 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 4.1 KiB |
@@ -1,4 +1,4 @@
|
||||
<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.refilc.naplo">
|
||||
<!-- Permissions -->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
|
||||
BIN
filcnaplo/assets/icons/ic_android.png
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 28 KiB |
BIN
filcnaplo/assets/icons/ic_launcher_monochrome.png
Normal file
|
After Width: | Height: | Size: 735 KiB |
|
Before Width: | Height: | Size: 123 KiB |
|
Before Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 105 KiB |
|
Before Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 104 KiB |
|
Before Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 73 KiB |
|
Before Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 102 KiB |
|
Before Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 67 KiB |
15
filcnaplo/ios/Flutter/Generated 2.xcconfig
Normal file
@@ -0,0 +1,15 @@
|
||||
// This is a generated file; do not edit or check into version control.
|
||||
FLUTTER_ROOT=/Users/kima/development/flutter
|
||||
FLUTTER_APPLICATION_PATH=/Users/kima/Documents/refilc/app/naplo/filcnaplo
|
||||
COCOAPODS_PARALLEL_CODE_SIGN=true
|
||||
FLUTTER_TARGET=/Users/kima/Documents/refilc/app/naplo/filcnaplo/lib/main.dart
|
||||
FLUTTER_BUILD_DIR=build
|
||||
FLUTTER_BUILD_NAME=3.5.1
|
||||
FLUTTER_BUILD_NUMBER=197
|
||||
EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386
|
||||
EXCLUDED_ARCHS[sdk=iphoneos*]=armv7
|
||||
DART_DEFINES=RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ==,RkxVVFRFUl9XRUJfQ0FOVkFTS0lUX1VSTD1odHRwczovL3d3dy5nc3RhdGljLmNvbS9mbHV0dGVyLWNhbnZhc2tpdC9iNGZiMTEyMTRkZDJkZGE2Y2UwMTJkZDk4ZWE0OThlOWU4YjkxMjYyLw==
|
||||
DART_OBFUSCATION=false
|
||||
TRACK_WIDGET_CREATION=true
|
||||
TREE_SHAKE_ICONS=false
|
||||
PACKAGE_CONFIG=/Users/kima/Documents/refilc/app/naplo/filcnaplo/.dart_tool/package_config.json
|
||||
@@ -77,6 +77,8 @@ PODS:
|
||||
- Mantle/extobjc (2.2.0)
|
||||
- open_file (0.0.1):
|
||||
- Flutter
|
||||
- package_info_plus (0.4.5):
|
||||
- Flutter
|
||||
- path_provider_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
@@ -120,6 +122,7 @@ DEPENDENCIES:
|
||||
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
|
||||
- live_activities (from `.symlinks/plugins/live_activities/ios`)
|
||||
- open_file (from `.symlinks/plugins/open_file/ios`)
|
||||
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
||||
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
||||
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
|
||||
- quick_actions_ios (from `.symlinks/plugins/quick_actions_ios/ios`)
|
||||
@@ -171,6 +174,8 @@ EXTERNAL SOURCES:
|
||||
:path: ".symlinks/plugins/live_activities/ios"
|
||||
open_file:
|
||||
:path: ".symlinks/plugins/open_file/ios"
|
||||
package_info_plus:
|
||||
:path: ".symlinks/plugins/package_info_plus/ios"
|
||||
path_provider_foundation:
|
||||
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
||||
permission_handler_apple:
|
||||
@@ -213,6 +218,7 @@ SPEC CHECKSUMS:
|
||||
live_activities: 9ff56a06a2d43ecd68f56deeed13b18a8304789c
|
||||
Mantle: c5aa8794a29a022dfbbfc9799af95f477a69b62d
|
||||
open_file: 02eb5cb6b21264bd3a696876f5afbfb7ca4f4b7d
|
||||
package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e
|
||||
path_provider_foundation: eaf5b3e458fc0e5fbb9940fb09980e853fe058b8
|
||||
permission_handler_apple: 44366e37eaf29454a1e7b1b7d736c2cceaeb17ce
|
||||
quick_actions_ios: 9e80dcfadfbc5d47d9cf8f47bcf428b11cf383d4
|
||||
|
||||
@@ -478,7 +478,7 @@
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 195;
|
||||
DEVELOPMENT_TEAM = JWGEQSC9U7;
|
||||
DEVELOPMENT_TEAM = 48XS7JAZB7;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = reFilc;
|
||||
@@ -488,7 +488,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 3.6.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = hu.refilc.naplo;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.refilc.naplo;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
@@ -510,7 +510,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = JWGEQSC9U7;
|
||||
DEVELOPMENT_TEAM = 48XS7JAZB7;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = livecard/Info.plist;
|
||||
@@ -526,7 +526,7 @@
|
||||
MARKETING_VERSION = 1.0;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = hu.refilc.naplo.livecardpro;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.refilc.naplo.livecardpro;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SKIP_INSTALL = YES;
|
||||
@@ -552,7 +552,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = JWGEQSC9U7;
|
||||
DEVELOPMENT_TEAM = 48XS7JAZB7;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = livecard/Info.plist;
|
||||
@@ -567,7 +567,7 @@
|
||||
);
|
||||
MARKETING_VERSION = 1.0;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = hu.refilc.naplo.livecardpro;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.refilc.naplo.livecardpro;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SKIP_INSTALL = YES;
|
||||
@@ -592,7 +592,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = JWGEQSC9U7;
|
||||
DEVELOPMENT_TEAM = 48XS7JAZB7;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = livecard/Info.plist;
|
||||
@@ -607,7 +607,7 @@
|
||||
);
|
||||
MARKETING_VERSION = 1.0;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = hu.refilc.naplo.livecardpro;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.refilc.naplo.livecardpro;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SKIP_INSTALL = YES;
|
||||
@@ -736,7 +736,7 @@
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 195;
|
||||
DEVELOPMENT_TEAM = JWGEQSC9U7;
|
||||
DEVELOPMENT_TEAM = 48XS7JAZB7;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = reFilc;
|
||||
@@ -746,7 +746,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 3.6.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = hu.refilc.naplo;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.refilc.naplo;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
@@ -764,7 +764,7 @@
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 195;
|
||||
DEVELOPMENT_TEAM = JWGEQSC9U7;
|
||||
DEVELOPMENT_TEAM = 48XS7JAZB7;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = reFilc;
|
||||
@@ -774,7 +774,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 3.6.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = hu.refilc.naplo;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.refilc.naplo;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
|
||||
|
Before Width: | Height: | Size: 610 KiB |
|
Before Width: | Height: | Size: 585 B |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 887 B |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 8.9 KiB |
|
Before Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 9.5 KiB |
|
Before Width: | Height: | Size: 11 KiB |
@@ -3,6 +3,8 @@
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.application-groups</key>
|
||||
<array/>
|
||||
<array>
|
||||
<string>group.refilcnaplo.livecard</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"size" : "1024x1024"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "reFilc_Logo.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"size" : "1024x1024"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
||||
|
After Width: | Height: | Size: 577 KiB |
@@ -13,7 +13,7 @@ class LessonData {
|
||||
var nextRoom: String
|
||||
|
||||
init?() {
|
||||
let sharedDefault = UserDefaults(suiteName: "group.filcnaplo.livecard")!
|
||||
let sharedDefault = UserDefaults(suiteName: "group.refilc.livecard")!
|
||||
|
||||
self.icon = sharedDefault.string(forKey: "icon")!
|
||||
self.index = sharedDefault.string(forKey: "index")!
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.application-groups</key>
|
||||
<array/>
|
||||
<array>
|
||||
<string>group.refilcnaplo.livecard</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -68,8 +68,6 @@ struct LockScreenLiveActivityView: View {
|
||||
.monospacedDigit()
|
||||
.padding(.trailing, CGFloat(24))
|
||||
}
|
||||
.activitySystemActionForegroundColor(.teal)
|
||||
.activityBackgroundTint(.teal)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -57,14 +57,14 @@ Future loginApi({
|
||||
String nonceStr = await Provider.of<KretaClient>(context, listen: false)
|
||||
.getAPI(KretaAPI.nonce, json: false);
|
||||
|
||||
Nonce nonce = getNonce(nonceStr, username, instituteCode);
|
||||
Nonce nonce = getNonce(nonceStr, username.replaceAll(' ', '') + ' ', instituteCode);
|
||||
headers.addAll(nonce.header());
|
||||
|
||||
Map? res = await Provider.of<KretaClient>(context, listen: false)
|
||||
.postAPI(KretaAPI.login,
|
||||
headers: headers,
|
||||
body: User.loginBody(
|
||||
username: username,
|
||||
username: username.replaceAll(' ', '') + ' ',
|
||||
password: password,
|
||||
instituteCode: instituteCode,
|
||||
));
|
||||
@@ -83,7 +83,7 @@ Future loginApi({
|
||||
.getAPI(KretaAPI.student(instituteCode));
|
||||
Student student = Student.fromJson(studentJson!);
|
||||
var user = User(
|
||||
username: username,
|
||||
username: username.replaceAll(' ', '') + ' ',
|
||||
password: password,
|
||||
instituteCode: instituteCode,
|
||||
name: student.name,
|
||||
|
||||
@@ -13,7 +13,14 @@ import 'package:flutter/foundation.dart';
|
||||
import 'package:live_activities/live_activities.dart';
|
||||
import 'package:filcnaplo_mobile_ui/pages/home/live_card/live_card.i18n.dart';
|
||||
|
||||
enum LiveCardState { empty, duringLesson, duringBreak, morning, afternoon, night }
|
||||
enum LiveCardState {
|
||||
empty,
|
||||
duringLesson,
|
||||
duringBreak,
|
||||
morning,
|
||||
afternoon,
|
||||
night
|
||||
}
|
||||
|
||||
class LiveCardProvider extends ChangeNotifier {
|
||||
Lesson? currentLesson;
|
||||
@@ -37,19 +44,39 @@ class LiveCardProvider extends ChangeNotifier {
|
||||
required SettingsProvider settings,
|
||||
}) : _timetable = timetable,
|
||||
_settings = settings {
|
||||
_liveActivitiesPlugin.init(appGroupId: "group.filcnaplo.livecard");
|
||||
_liveActivitiesPlugin.getAllActivitiesIds().then((value) {
|
||||
_latestActivityId = value.isNotEmpty ? value.first : null;
|
||||
// Check if live card is enabled .areActivitiesEnabled()
|
||||
_liveActivitiesPlugin.areActivitiesEnabled().then((value) {
|
||||
// Console log
|
||||
print("Live card enabled: $value");
|
||||
|
||||
if (value) {
|
||||
_liveActivitiesPlugin.init(appGroupId: "group.refilc.livecard");
|
||||
|
||||
_liveActivitiesPlugin.getAllActivitiesIds().then((value) {
|
||||
_latestActivityId = value.isNotEmpty ? value.first : null;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
_timer = Timer.periodic(const Duration(seconds: 1), (timer) => update());
|
||||
_delay = settings.bellDelayEnabled ? Duration(seconds: settings.bellDelay) : Duration.zero;
|
||||
_delay = settings.bellDelayEnabled
|
||||
? Duration(seconds: settings.bellDelay)
|
||||
: Duration.zero;
|
||||
update();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_timer.cancel();
|
||||
if (_latestActivityId != null && Platform.isIOS) _liveActivitiesPlugin.endActivity(_latestActivityId!);
|
||||
if (Platform.isIOS) {
|
||||
_liveActivitiesPlugin.areActivitiesEnabled().then((value) {
|
||||
if (value) {
|
||||
if (_latestActivityId != null) {
|
||||
_liveActivitiesPlugin.endActivity(_latestActivityId!);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@@ -78,14 +105,25 @@ class LiveCardProvider extends ChangeNotifier {
|
||||
switch (currentState) {
|
||||
case LiveCardState.duringLesson:
|
||||
return {
|
||||
"icon": currentLesson != null ? SubjectIcon.resolveName(subject: currentLesson?.subject) : "book",
|
||||
"index": currentLesson != null ? '${currentLesson!.lessonIndex}. ' : "",
|
||||
"title": currentLesson != null ? ShortSubject.resolve(subject: currentLesson?.subject).capital() : "",
|
||||
"icon": currentLesson != null
|
||||
? SubjectIcon.resolveName(subject: currentLesson?.subject)
|
||||
: "book",
|
||||
"index":
|
||||
currentLesson != null ? '${currentLesson!.lessonIndex}. ' : "",
|
||||
"title": currentLesson != null
|
||||
? ShortSubject.resolve(subject: currentLesson?.subject).capital()
|
||||
: "",
|
||||
"subtitle": currentLesson?.room.replaceAll("_", " ") ?? "",
|
||||
"description": currentLesson?.description ?? "",
|
||||
"startDate": ((currentLesson?.start.millisecondsSinceEpoch ?? 0) - _delay.inMilliseconds).toString(),
|
||||
"endDate": ((currentLesson?.end.millisecondsSinceEpoch ?? 0) - _delay.inMilliseconds).toString(),
|
||||
"nextSubject": nextLesson != null ? ShortSubject.resolve(subject: nextLesson?.subject).capital() : "",
|
||||
"startDate": ((currentLesson?.start.millisecondsSinceEpoch ?? 0) -
|
||||
_delay.inMilliseconds)
|
||||
.toString(),
|
||||
"endDate": ((currentLesson?.end.millisecondsSinceEpoch ?? 0) -
|
||||
_delay.inMilliseconds)
|
||||
.toString(),
|
||||
"nextSubject": nextLesson != null
|
||||
? ShortSubject.resolve(subject: nextLesson?.subject).capital()
|
||||
: "",
|
||||
"nextRoom": nextLesson?.room.replaceAll("_", " ") ?? "",
|
||||
};
|
||||
case LiveCardState.duringBreak:
|
||||
@@ -101,10 +139,19 @@ class LiveCardProvider extends ChangeNotifier {
|
||||
return {
|
||||
"icon": iconFloorMap[diff] ?? "cup.and.saucer",
|
||||
"title": "Szünet",
|
||||
"description": "go $diff".i18n.fill([diff != "to room" ? (nextLesson!.getFloor() ?? 0) : nextLesson!.room]),
|
||||
"startDate": ((prevLesson?.end.millisecondsSinceEpoch ?? 0) - _delay.inMilliseconds).toString(),
|
||||
"endDate": ((nextLesson?.start.millisecondsSinceEpoch ?? 0) - _delay.inMilliseconds).toString(),
|
||||
"nextSubject": (nextLesson != null ? ShortSubject.resolve(subject: nextLesson?.subject) : "").capital(),
|
||||
"description": "go $diff".i18n.fill([
|
||||
diff != "to room" ? (nextLesson!.getFloor() ?? 0) : nextLesson!.room
|
||||
]),
|
||||
"startDate": ((prevLesson?.end.millisecondsSinceEpoch ?? 0) -
|
||||
_delay.inMilliseconds)
|
||||
.toString(),
|
||||
"endDate": ((nextLesson?.start.millisecondsSinceEpoch ?? 0) -
|
||||
_delay.inMilliseconds)
|
||||
.toString(),
|
||||
"nextSubject": (nextLesson != null
|
||||
? ShortSubject.resolve(subject: nextLesson?.subject)
|
||||
: "")
|
||||
.capital(),
|
||||
"nextRoom": nextLesson?.room.replaceAll("_", " ") ?? "",
|
||||
"index": "",
|
||||
"subtitle": "",
|
||||
@@ -116,20 +163,34 @@ class LiveCardProvider extends ChangeNotifier {
|
||||
|
||||
void update() async {
|
||||
if (Platform.isIOS) {
|
||||
final cmap = toMap();
|
||||
if (!mapEquals(cmap, _lastActivity)) {
|
||||
_lastActivity = cmap;
|
||||
|
||||
if (_lastActivity.isNotEmpty) {
|
||||
if (_latestActivityId == null) {
|
||||
_liveActivitiesPlugin.createActivity(_lastActivity).then((value) => _latestActivityId = value);
|
||||
} else {
|
||||
_liveActivitiesPlugin.updateActivity(_latestActivityId!, _lastActivity);
|
||||
_liveActivitiesPlugin.areActivitiesEnabled().then((value) {
|
||||
if (value) {
|
||||
final cmap = toMap();
|
||||
if (!mapEquals(cmap, _lastActivity)) {
|
||||
_lastActivity = cmap;
|
||||
try {
|
||||
if (_lastActivity.isNotEmpty) {
|
||||
if (_latestActivityId == null) {
|
||||
_liveActivitiesPlugin
|
||||
.createActivity(_lastActivity)
|
||||
.then((value) => _latestActivityId = value);
|
||||
} else {
|
||||
_liveActivitiesPlugin.updateActivity(
|
||||
_latestActivityId!, _lastActivity);
|
||||
}
|
||||
} else {
|
||||
if (_latestActivityId != null) {
|
||||
_liveActivitiesPlugin.endActivity(_latestActivityId!);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
if (kDebugMode) {
|
||||
print('ERROR: Unable to create or update iOS LiveCard!');
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (_latestActivityId != null) _liveActivitiesPlugin.endActivity(_latestActivityId!);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
List<Lesson> today = _today(_timetable);
|
||||
@@ -139,19 +200,28 @@ class LiveCardProvider extends ChangeNotifier {
|
||||
today = _today(_timetable);
|
||||
}
|
||||
|
||||
_delay = _settings.bellDelayEnabled ? Duration(seconds: _settings.bellDelay) : Duration.zero;
|
||||
_delay = _settings.bellDelayEnabled
|
||||
? Duration(seconds: _settings.bellDelay)
|
||||
: Duration.zero;
|
||||
|
||||
final now = _now().add(_delay);
|
||||
|
||||
// Filter cancelled lessons #20
|
||||
// Filter label lessons #128
|
||||
today = today.where((lesson) => lesson.status?.name != "Elmaradt" && lesson.subject.id != '' && !lesson.isEmpty).toList();
|
||||
today = today
|
||||
.where((lesson) =>
|
||||
lesson.status?.name != "Elmaradt" &&
|
||||
lesson.subject.id != '' &&
|
||||
!lesson.isEmpty)
|
||||
.toList();
|
||||
|
||||
if (today.isNotEmpty) {
|
||||
// sort
|
||||
today.sort((a, b) => a.start.compareTo(b.start));
|
||||
|
||||
final _lesson = today.firstWhere((l) => l.start.isBefore(now) && l.end.isAfter(now), orElse: () => Lesson.fromJson({}));
|
||||
final _lesson = today.firstWhere(
|
||||
(l) => l.start.isBefore(now) && l.end.isAfter(now),
|
||||
orElse: () => Lesson.fromJson({}));
|
||||
|
||||
if (_lesson.start.year != 0) {
|
||||
currentLesson = _lesson;
|
||||
@@ -159,7 +229,8 @@ class LiveCardProvider extends ChangeNotifier {
|
||||
currentLesson = null;
|
||||
}
|
||||
|
||||
final _next = today.firstWhere((l) => l.start.isAfter(now), orElse: () => Lesson.fromJson({}));
|
||||
final _next = today.firstWhere((l) => l.start.isAfter(now),
|
||||
orElse: () => Lesson.fromJson({}));
|
||||
nextLessons = today.where((l) => l.start.isAfter(now)).toList();
|
||||
|
||||
if (_next.start.year != 0) {
|
||||
@@ -168,7 +239,8 @@ class LiveCardProvider extends ChangeNotifier {
|
||||
nextLesson = null;
|
||||
}
|
||||
|
||||
final _prev = today.lastWhere((l) => l.end.isBefore(now), orElse: () => Lesson.fromJson({}));
|
||||
final _prev = today.lastWhere((l) => l.end.isBefore(now),
|
||||
orElse: () => Lesson.fromJson({}));
|
||||
|
||||
if (_prev.start.year != 0) {
|
||||
prevLesson = _prev;
|
||||
@@ -198,7 +270,10 @@ class LiveCardProvider extends ChangeNotifier {
|
||||
|
||||
Duration get delay => _delay;
|
||||
|
||||
bool _sameDate(DateTime a, DateTime b) => (a.year == b.year && a.month == b.month && a.day == b.day);
|
||||
bool _sameDate(DateTime a, DateTime b) =>
|
||||
(a.year == b.year && a.month == b.month && a.day == b.day);
|
||||
|
||||
List<Lesson> _today(TimetableProvider p) => (p.getWeek(Week.current()) ?? []).where((l) => _sameDate(l.date, _now())).toList();
|
||||
List<Lesson> _today(TimetableProvider p) => (p.getWeek(Week.current()) ?? [])
|
||||
.where((l) => _sameDate(l.date, _now()))
|
||||
.toList();
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'dart:io';
|
||||
import 'package:filcnaplo/api/client.dart';
|
||||
import 'package:filcnaplo/models/release.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
|
||||
class UpdateProvider extends ChangeNotifier {
|
||||
// Private
|
||||
@@ -20,9 +21,11 @@ class UpdateProvider extends ChangeNotifier {
|
||||
_releases = List.castFrom(initialReleases);
|
||||
}
|
||||
|
||||
static const currentVersion = String.fromEnvironment("APPVER", defaultValue: "1.0");
|
||||
|
||||
Future<void> fetch() async {
|
||||
late String currentVersion;
|
||||
PackageInfo packageInfo = await PackageInfo.fromPlatform();
|
||||
currentVersion = packageInfo.version;
|
||||
|
||||
if (!Platform.isAndroid) return;
|
||||
|
||||
_releases = await FilcAPI.getReleases() ?? [];
|
||||
@@ -30,10 +33,30 @@ class UpdateProvider extends ChangeNotifier {
|
||||
|
||||
// Check for new releases
|
||||
if (_releases.isNotEmpty) {
|
||||
_available = _releases.first.version.compareTo(Version.fromString(currentVersion)) == 1;
|
||||
_available = _releases.first.version
|
||||
.compareTo(Version.fromString(currentVersion)) ==
|
||||
1;
|
||||
// ignore: avoid_print
|
||||
if (_available) print("INFO: New update: ${releases.first.version}");
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
Future<Map> installedVersion() async {
|
||||
PackageInfo packageInfo = await PackageInfo.fromPlatform();
|
||||
|
||||
String appName = packageInfo.appName;
|
||||
String packageName = packageInfo.packageName;
|
||||
String version = packageInfo.version;
|
||||
String buildNumber = packageInfo.buildNumber;
|
||||
|
||||
Map<String, String> release = {
|
||||
"app_name": appName,
|
||||
"package_name": packageName,
|
||||
"version": version,
|
||||
"build_number": buildNumber,
|
||||
};
|
||||
|
||||
return release;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import 'package:filcnaplo/models/config.dart';
|
||||
import 'package:filcnaplo/theme/observer.dart';
|
||||
import 'package:filcnaplo/theme/theme.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/client.dart';
|
||||
import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
@@ -22,13 +23,18 @@ import 'package:provider/provider.dart';
|
||||
import 'package:filcnaplo_mobile_ui/common/system_chrome.dart' as mobile;
|
||||
import 'package:filcnaplo_mobile_ui/screens/login/login_route.dart' as mobile;
|
||||
import 'package:filcnaplo_mobile_ui/screens/login/login_screen.dart' as mobile;
|
||||
import 'package:filcnaplo_mobile_ui/screens/navigation/navigation_screen.dart' as mobile;
|
||||
import 'package:filcnaplo_mobile_ui/screens/settings/settings_route.dart' as mobile;
|
||||
import 'package:filcnaplo_mobile_ui/screens/settings/settings_screen.dart' as mobile;
|
||||
import 'package:filcnaplo_mobile_ui/screens/navigation/navigation_screen.dart'
|
||||
as mobile;
|
||||
import 'package:filcnaplo_mobile_ui/screens/settings/settings_route.dart'
|
||||
as mobile;
|
||||
import 'package:filcnaplo_mobile_ui/screens/settings/settings_screen.dart'
|
||||
as mobile;
|
||||
|
||||
// Desktop UI
|
||||
import 'package:filcnaplo_desktop_ui/screens/navigation/navigation_screen.dart' as desktop;
|
||||
import 'package:filcnaplo_desktop_ui/screens/login/login_screen.dart' as desktop;
|
||||
import 'package:filcnaplo_desktop_ui/screens/navigation/navigation_screen.dart'
|
||||
as desktop;
|
||||
import 'package:filcnaplo_desktop_ui/screens/login/login_screen.dart'
|
||||
as desktop;
|
||||
import 'package:filcnaplo_desktop_ui/screens/login/login_route.dart' as desktop;
|
||||
|
||||
// Providers
|
||||
@@ -36,7 +42,6 @@ import 'package:filcnaplo/models/settings.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';
|
||||
@@ -52,7 +57,12 @@ class App extends StatelessWidget {
|
||||
final UserProvider user;
|
||||
final DatabaseProvider database;
|
||||
|
||||
const App({Key? key, required this.database, required this.settings, required this.user}) : super(key: key);
|
||||
const App(
|
||||
{Key? key,
|
||||
required this.database,
|
||||
required this.settings,
|
||||
required this.user})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -65,7 +75,8 @@ class App extends StatelessWidget {
|
||||
|
||||
final status = StatusProvider();
|
||||
final kreta = KretaClient(user: user, settings: settings, status: status);
|
||||
final timetable = TimetableProvider(user: user, database: database, kreta: kreta);
|
||||
final timetable =
|
||||
TimetableProvider(user: user, database: database, kreta: kreta);
|
||||
final premium = PremiumProvider(settings: settings);
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
@@ -83,23 +94,44 @@ class App extends StatelessWidget {
|
||||
ChangeNotifierProvider<StatusProvider>(create: (_) => status),
|
||||
Provider<KretaClient>(create: (_) => kreta),
|
||||
Provider<DatabaseProvider>(create: (context) => database),
|
||||
ChangeNotifierProvider<ThemeModeObserver>(create: (context) => ThemeModeObserver(initialTheme: settings.theme)),
|
||||
ChangeNotifierProvider<NewsProvider>(create: (context) => NewsProvider(context: context)),
|
||||
ChangeNotifierProvider<UpdateProvider>(create: (context) => UpdateProvider(context: context)),
|
||||
ChangeNotifierProvider<ThemeModeObserver>(
|
||||
create: (context) =>
|
||||
ThemeModeObserver(initialTheme: settings.theme)),
|
||||
ChangeNotifierProvider<NewsProvider>(
|
||||
create: (context) => NewsProvider(context: context)),
|
||||
ChangeNotifierProvider<UpdateProvider>(
|
||||
create: (context) => UpdateProvider(context: context)),
|
||||
|
||||
// User data providers
|
||||
ChangeNotifierProvider<GradeProvider>(create: (_) => GradeProvider(settings: settings, user: user, database: database, kreta: kreta)),
|
||||
ChangeNotifierProvider<GradeProvider>(
|
||||
create: (_) => GradeProvider(
|
||||
settings: settings,
|
||||
user: user,
|
||||
database: database,
|
||||
kreta: kreta)),
|
||||
ChangeNotifierProvider<TimetableProvider>(create: (_) => timetable),
|
||||
ChangeNotifierProvider<ExamProvider>(create: (context) => ExamProvider(context: context)),
|
||||
ChangeNotifierProvider<HomeworkProvider>(create: (context) => HomeworkProvider(context: context)),
|
||||
ChangeNotifierProvider<MessageProvider>(create: (context) => MessageProvider(context: context)),
|
||||
ChangeNotifierProvider<NoteProvider>(create: (context) => NoteProvider(context: context)),
|
||||
ChangeNotifierProvider<EventProvider>(create: (context) => EventProvider(context: context)),
|
||||
ChangeNotifierProvider<AbsenceProvider>(create: (context) => AbsenceProvider(context: context)),
|
||||
ChangeNotifierProvider<ExamProvider>(
|
||||
create: (context) => ExamProvider(context: context)),
|
||||
ChangeNotifierProvider<HomeworkProvider>(
|
||||
create: (context) => HomeworkProvider(context: context)),
|
||||
ChangeNotifierProvider<MessageProvider>(
|
||||
create: (context) => MessageProvider(context: context)),
|
||||
ChangeNotifierProvider<NoteProvider>(
|
||||
create: (context) => NoteProvider(context: context)),
|
||||
ChangeNotifierProvider<EventProvider>(
|
||||
create: (context) => EventProvider(context: context)),
|
||||
ChangeNotifierProvider<AbsenceProvider>(
|
||||
create: (context) => AbsenceProvider(context: context)),
|
||||
|
||||
ChangeNotifierProvider<GradeCalculatorProvider>(
|
||||
create: (_) => GradeCalculatorProvider(settings: settings, user: user, database: database, kreta: kreta)),
|
||||
ChangeNotifierProvider<LiveCardProvider>(create: (context) => LiveCardProvider(timetable: timetable, settings: settings))
|
||||
create: (_) => GradeCalculatorProvider(
|
||||
settings: settings,
|
||||
user: user,
|
||||
database: database,
|
||||
kreta: kreta)),
|
||||
ChangeNotifierProvider<LiveCardProvider>(
|
||||
create: (context) =>
|
||||
LiveCardProvider(timetable: timetable, settings: settings))
|
||||
],
|
||||
child: Consumer<ThemeModeObserver>(
|
||||
builder: (context, themeMode, child) {
|
||||
@@ -110,12 +142,15 @@ class App extends StatelessWidget {
|
||||
return MaterialApp(
|
||||
builder: (context, child) {
|
||||
// Limit font size scaling to 1.0
|
||||
double textScaleFactor = min(MediaQuery.of(context).textScaleFactor, 1.0);
|
||||
double textScaleFactor =
|
||||
min(MediaQuery.of(context).textScaleFactor, 1.0);
|
||||
|
||||
return I18n(
|
||||
initialLocale: Locale(settings.language, settings.language.toUpperCase()),
|
||||
initialLocale: Locale(
|
||||
settings.language, settings.language.toUpperCase()),
|
||||
child: MediaQuery(
|
||||
data: MediaQuery.of(context).copyWith(textScaleFactor: textScaleFactor),
|
||||
data: MediaQuery.of(context)
|
||||
.copyWith(textScaleFactor: textScaleFactor),
|
||||
child: child ?? Container(),
|
||||
),
|
||||
);
|
||||
@@ -148,7 +183,8 @@ class App extends StatelessWidget {
|
||||
return locale;
|
||||
},
|
||||
onGenerateRoute: (settings) => rootNavigator(settings),
|
||||
initialRoute: user.getUsers().isNotEmpty ? "navigation" : "login",
|
||||
initialRoute:
|
||||
user.getUsers().isNotEmpty ? "navigation" : "login",
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -162,7 +198,8 @@ class App extends StatelessWidget {
|
||||
if (Platform.isAndroid || Platform.isIOS) {
|
||||
switch (route.name) {
|
||||
case "login_back":
|
||||
return CupertinoPageRoute(builder: (context) => const mobile.LoginScreen(back: true));
|
||||
return CupertinoPageRoute(
|
||||
builder: (context) => const mobile.LoginScreen(back: true));
|
||||
case "login":
|
||||
return _rootRoute(const mobile.LoginScreen());
|
||||
case "navigation":
|
||||
@@ -175,7 +212,8 @@ class App extends StatelessWidget {
|
||||
} else if (Platform.isWindows || Platform.isMacOS || Platform.isLinux) {
|
||||
switch (route.name) {
|
||||
case "login_back":
|
||||
return CupertinoPageRoute(builder: (context) => const desktop.LoginScreen(back: true));
|
||||
return CupertinoPageRoute(
|
||||
builder: (context) => const desktop.LoginScreen(back: true));
|
||||
case "login":
|
||||
return _rootRoute(const desktop.LoginScreen());
|
||||
case "navigation":
|
||||
|
||||
@@ -19,13 +19,15 @@ extension UpdateHelper on Release {
|
||||
updateCallback!(-1, UpdateState.preparing);
|
||||
|
||||
String downloads = await StorageHelper.downloadsPath();
|
||||
File apk = File("$downloads/filcnaplo-$version.apk");
|
||||
File apk = File("$downloads/refilc-$version.apk");
|
||||
|
||||
if (!await apk.exists()) {
|
||||
updateCallback(-1, UpdateState.downloading);
|
||||
|
||||
var bytes = await download(updateCallback: updateCallback);
|
||||
if (!await StorageHelper.write(apk.path, bytes)) throw "failed to write apk: permission denied";
|
||||
if (!await StorageHelper.write(apk.path, bytes)) {
|
||||
throw "failed to write apk: permission denied";
|
||||
}
|
||||
}
|
||||
|
||||
updateCallback(-1, UpdateState.installing);
|
||||
@@ -50,7 +52,8 @@ extension UpdateHelper on Release {
|
||||
var completer = Completer<Uint8List>();
|
||||
|
||||
response?.stream.listen((List<int> chunk) {
|
||||
updateCallback!(downloaded / (response.contentLength ?? 0), UpdateState.downloading);
|
||||
updateCallback!(
|
||||
downloaded / (response.contentLength ?? 0), UpdateState.downloading);
|
||||
|
||||
chunks.add(chunk);
|
||||
downloaded += chunk.length;
|
||||
|
||||
@@ -9,7 +9,7 @@ class Config {
|
||||
|
||||
factory Config.fromJson(Map json) {
|
||||
return Config(
|
||||
userAgent: json["user_agent"] ?? "hu.filc.naplo/\$0/\$1/\$2",
|
||||
userAgent: json["user_agent"] ?? "hu.refilc.naplo/\$0/\$1/\$2",
|
||||
json: json,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ enum AccentColor {
|
||||
red,
|
||||
pink,
|
||||
purple,
|
||||
none,
|
||||
ogfilc,
|
||||
adaptive,
|
||||
custom
|
||||
}
|
||||
@@ -24,6 +26,8 @@ Map<AccentColor, Color> accentColorMap = {
|
||||
AccentColor.red: Colors.red.shade300,
|
||||
AccentColor.pink: Colors.pink.shade300,
|
||||
AccentColor.purple: Colors.purple.shade300,
|
||||
//AccentColor.none: Colors.black,
|
||||
AccentColor.ogfilc: const Color(0xff20AC9B),
|
||||
AccentColor.adaptive: const Color(0xFF3D7BF4),
|
||||
AccentColor.custom: const Color(0xFF3D7BF4),
|
||||
};
|
||||
|
||||
@@ -311,7 +311,7 @@ Color gradeColor(
|
||||
|
||||
switch (valueInt) {
|
||||
case 5:
|
||||
return Color(0xff3d7bf4);
|
||||
return settings.gradeColors[4];
|
||||
case 4:
|
||||
return settings.gradeColors[3];
|
||||
case 3:
|
||||
|
||||
@@ -15,7 +15,8 @@ import 'package:provider/provider.dart';
|
||||
import 'lesson_tile.i18n.dart';
|
||||
|
||||
class LessonTile extends StatelessWidget {
|
||||
const LessonTile(this.lesson, {Key? key, this.onTap, this.swapDesc = false}) : super(key: key);
|
||||
const LessonTile(this.lesson, {Key? key, this.onTap, this.swapDesc = false})
|
||||
: super(key: key);
|
||||
|
||||
final Lesson lesson;
|
||||
final bool swapDesc;
|
||||
@@ -34,7 +35,9 @@ class LessonTile extends StatelessWidget {
|
||||
if (RegExp(r'\d').hasMatch(lesson.lessonIndex)) lessonIndexTrailing = ".";
|
||||
|
||||
var now = DateTime.now();
|
||||
if (lesson.start.isBefore(now) && lesson.end.isAfter(now) && lesson.status?.name != "Elmaradt") {
|
||||
if (lesson.start.isBefore(now) &&
|
||||
lesson.end.isAfter(now) &&
|
||||
lesson.status?.name != "Elmaradt") {
|
||||
fillLeading = true;
|
||||
}
|
||||
|
||||
@@ -62,7 +65,8 @@ class LessonTile extends StatelessWidget {
|
||||
if (lesson.homeworkId != "") {
|
||||
Homework homework = Provider.of<HomeworkProvider>(context, listen: false)
|
||||
.homework
|
||||
.firstWhere((h) => h.id == lesson.homeworkId, orElse: () => Homework.fromJson({}));
|
||||
.firstWhere((h) => h.id == lesson.homeworkId,
|
||||
orElse: () => Homework.fromJson({}));
|
||||
|
||||
if (homework.id != "") {
|
||||
subtiles.add(LessonSubtile(
|
||||
@@ -74,11 +78,16 @@ class LessonTile extends StatelessWidget {
|
||||
}
|
||||
|
||||
if (lesson.exam != "") {
|
||||
Exam exam = Provider.of<ExamProvider>(context, listen: false).exams.firstWhere((t) => t.id == lesson.exam, orElse: () => Exam.fromJson({}));
|
||||
Exam exam = Provider.of<ExamProvider>(context, listen: false)
|
||||
.exams
|
||||
.firstWhere((t) => t.id == lesson.exam,
|
||||
orElse: () => Exam.fromJson({}));
|
||||
if (exam.id != "") {
|
||||
subtiles.add(LessonSubtile(
|
||||
type: LessonSubtileType.exam,
|
||||
title: exam.description != "" ? exam.description : exam.mode?.description ?? "exam".i18n,
|
||||
title: exam.description != ""
|
||||
? exam.description
|
||||
: exam.mode?.description ?? "exam".i18n,
|
||||
onPressed: () => ExamView.show(exam, context: context),
|
||||
));
|
||||
}
|
||||
@@ -87,7 +96,10 @@ class LessonTile extends StatelessWidget {
|
||||
String description = '';
|
||||
String room = '';
|
||||
|
||||
final cleanDesc = lesson.description.specialChars().toLowerCase().replaceAll(lesson.subject.name.specialChars().toLowerCase(), '');
|
||||
final cleanDesc = lesson.description
|
||||
.specialChars()
|
||||
.toLowerCase()
|
||||
.replaceAll(lesson.subject.name.specialChars().toLowerCase(), '');
|
||||
|
||||
if (!swapDesc) {
|
||||
if (cleanDesc != "") {
|
||||
@@ -131,16 +143,23 @@ class LessonTile extends StatelessWidget {
|
||||
// onLongPress: kDebugMode ? () => log(jsonEncode(lesson.json)) : null,
|
||||
visualDensity: VisualDensity.compact,
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 4.0),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.0)),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12.0)),
|
||||
title: Text(
|
||||
!lesson.isEmpty ? lesson.subject.renamedTo ?? lesson.subject.name.capital() : "empty".i18n,
|
||||
!lesson.isEmpty
|
||||
? lesson.subject.renamedTo ??
|
||||
lesson.subject.name.capital()
|
||||
: "empty".i18n,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 15.5,
|
||||
color: AppColors.of(context).text.withOpacity(!lesson.isEmpty ? 1.0 : 0.5),
|
||||
fontStyle: lesson.subject.isRenamed ? FontStyle.italic : null),
|
||||
color: AppColors.of(context)
|
||||
.text
|
||||
.withOpacity(!lesson.isEmpty ? 1.0 : 0.5),
|
||||
fontStyle:
|
||||
lesson.subject.isRenamed ? FontStyle.italic : null),
|
||||
),
|
||||
subtitle: description != ""
|
||||
? Text(
|
||||
@@ -175,12 +194,20 @@ class LessonTile extends StatelessWidget {
|
||||
offset: const Offset(-12.0, -2.0),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: fillLeading ? Theme.of(context).colorScheme.secondary.withOpacity(.3) : const Color(0x00000000),
|
||||
color: fillLeading
|
||||
? Theme.of(context)
|
||||
.colorScheme
|
||||
.secondary
|
||||
.withOpacity(.3)
|
||||
: const Color(0x00000000),
|
||||
borderRadius: BorderRadius.circular(12.0),
|
||||
boxShadow: [
|
||||
if (fillLeading)
|
||||
BoxShadow(
|
||||
color: Theme.of(context).colorScheme.secondary.withOpacity(.25),
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.secondary
|
||||
.withOpacity(.25),
|
||||
blurRadius: 6.0,
|
||||
)
|
||||
],
|
||||
@@ -210,7 +237,9 @@ class LessonTile extends StatelessWidget {
|
||||
maxLines: 2,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w500,
|
||||
color: AppColors.of(context).text.withOpacity(.75),
|
||||
color: AppColors.of(context)
|
||||
.text
|
||||
.withOpacity(.75),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -225,7 +254,9 @@ class LessonTile extends StatelessWidget {
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w500,
|
||||
color: AppColors.of(context).text.withOpacity(.9),
|
||||
color: AppColors.of(context)
|
||||
.text
|
||||
.withOpacity(.9),
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -249,7 +280,9 @@ class LessonTile extends StatelessWidget {
|
||||
enum LessonSubtileType { homework, exam, absence }
|
||||
|
||||
class LessonSubtile extends StatelessWidget {
|
||||
const LessonSubtile({Key? key, this.onPressed, required this.title, required this.type}) : super(key: key);
|
||||
const LessonSubtile(
|
||||
{Key? key, this.onPressed, required this.title, required this.type})
|
||||
: super(key: key);
|
||||
|
||||
final Function()? onPressed;
|
||||
final String title;
|
||||
@@ -285,7 +318,8 @@ class LessonSubtile extends StatelessWidget {
|
||||
Center(
|
||||
child: SizedBox(
|
||||
width: 30.0,
|
||||
child: Icon(icon, color: iconColor.withOpacity(.75), size: 20.0),
|
||||
child:
|
||||
Icon(icon, color: iconColor.withOpacity(.75), size: 20.0),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
@@ -295,7 +329,9 @@ class LessonSubtile extends StatelessWidget {
|
||||
title.escapeHtml(),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(fontWeight: FontWeight.w500, color: AppColors.of(context).text.withOpacity(.65)),
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w500,
|
||||
color: AppColors.of(context).text.withOpacity(.65)),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -9,6 +9,7 @@ import connectivity_plus
|
||||
import dynamic_color
|
||||
import flutter_acrylic
|
||||
import flutter_local_notifications
|
||||
import package_info_plus
|
||||
import path_provider_foundation
|
||||
import share_plus_macos
|
||||
import sqflite
|
||||
@@ -19,6 +20,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
DynamicColorPlugin.register(with: registry.registrar(forPlugin: "DynamicColorPlugin"))
|
||||
FlutterAcrylicPlugin.register(with: registry.registrar(forPlugin: "FlutterAcrylicPlugin"))
|
||||
FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
|
||||
FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin"))
|
||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||
SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
|
||||
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
||||
|
||||
@@ -1,40 +1,40 @@
|
||||
platform :osx, '10.11'
|
||||
|
||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||
|
||||
project 'Runner', {
|
||||
'Debug' => :debug,
|
||||
'Profile' => :release,
|
||||
'Release' => :release,
|
||||
}
|
||||
|
||||
def flutter_root
|
||||
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__)
|
||||
unless File.exist?(generated_xcode_build_settings_path)
|
||||
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first"
|
||||
end
|
||||
|
||||
File.foreach(generated_xcode_build_settings_path) do |line|
|
||||
matches = line.match(/FLUTTER_ROOT\=(.*)/)
|
||||
return matches[1].strip if matches
|
||||
end
|
||||
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\""
|
||||
end
|
||||
|
||||
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
|
||||
|
||||
flutter_macos_podfile_setup
|
||||
|
||||
target 'Runner' do
|
||||
use_frameworks!
|
||||
use_modular_headers!
|
||||
|
||||
flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__))
|
||||
end
|
||||
|
||||
post_install do |installer|
|
||||
installer.pods_project.targets.each do |target|
|
||||
flutter_additional_macos_build_settings(target)
|
||||
end
|
||||
end
|
||||
platform :osx, '10.14'
|
||||
|
||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||
|
||||
project 'Runner', {
|
||||
'Debug' => :debug,
|
||||
'Profile' => :release,
|
||||
'Release' => :release,
|
||||
}
|
||||
|
||||
def flutter_root
|
||||
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__)
|
||||
unless File.exist?(generated_xcode_build_settings_path)
|
||||
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first"
|
||||
end
|
||||
|
||||
File.foreach(generated_xcode_build_settings_path) do |line|
|
||||
matches = line.match(/FLUTTER_ROOT\=(.*)/)
|
||||
return matches[1].strip if matches
|
||||
end
|
||||
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\""
|
||||
end
|
||||
|
||||
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
|
||||
|
||||
flutter_macos_podfile_setup
|
||||
|
||||
target 'Runner' do
|
||||
use_frameworks!
|
||||
use_modular_headers!
|
||||
|
||||
flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__))
|
||||
end
|
||||
|
||||
post_install do |installer|
|
||||
installer.pods_project.targets.each do |target|
|
||||
flutter_additional_macos_build_settings(target)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,71 +1,78 @@
|
||||
PODS:
|
||||
- connectivity_plus (0.0.1):
|
||||
- FlutterMacOS
|
||||
- ReachabilitySwift
|
||||
- dynamic_color (0.0.2):
|
||||
- FlutterMacOS
|
||||
- flutter_acrylic (0.1.0):
|
||||
- FlutterMacOS
|
||||
- FlutterMacOS (1.0.0)
|
||||
- FMDB (2.7.5):
|
||||
- FMDB/standard (= 2.7.5)
|
||||
- FMDB/standard (2.7.5)
|
||||
- path_provider_macos (0.0.1):
|
||||
- FlutterMacOS
|
||||
- ReachabilitySwift (5.0.0)
|
||||
- share_plus_macos (0.0.1):
|
||||
- FlutterMacOS
|
||||
- sqflite (0.0.2):
|
||||
- FlutterMacOS
|
||||
- FMDB (>= 2.7.5)
|
||||
- url_launcher_macos (0.0.1):
|
||||
- FlutterMacOS
|
||||
|
||||
DEPENDENCIES:
|
||||
- connectivity_plus (from `Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos`)
|
||||
- dynamic_color (from `Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos`)
|
||||
- flutter_acrylic (from `Flutter/ephemeral/.symlinks/plugins/flutter_acrylic/macos`)
|
||||
- FlutterMacOS (from `Flutter/ephemeral`)
|
||||
- path_provider_macos (from `Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos`)
|
||||
- share_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/share_plus_macos/macos`)
|
||||
- sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/macos`)
|
||||
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
|
||||
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
- FMDB
|
||||
- ReachabilitySwift
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
connectivity_plus:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos
|
||||
dynamic_color:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos
|
||||
flutter_acrylic:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/flutter_acrylic/macos
|
||||
FlutterMacOS:
|
||||
:path: Flutter/ephemeral
|
||||
path_provider_macos:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos
|
||||
share_plus_macos:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/share_plus_macos/macos
|
||||
sqflite:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/sqflite/macos
|
||||
url_launcher_macos:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
connectivity_plus: 18d3c32514c886e046de60e9c13895109866c747
|
||||
dynamic_color: 394d6a888650f8534e029b27d2f8bc5c64e44008
|
||||
flutter_acrylic: c3df24ae52ab6597197837ce59ef2a8542640c17
|
||||
FlutterMacOS: ae6af50a8ea7d6103d888583d46bd8328a7e9811
|
||||
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
|
||||
path_provider_macos: 3c0c3b4b0d4a76d2bf989a913c2de869c5641a19
|
||||
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
|
||||
share_plus_macos: 853ee48e7dce06b633998ca0735d482dd671ade4
|
||||
sqflite: a5789cceda41d54d23f31d6de539d65bb14100ea
|
||||
url_launcher_macos: 597e05b8e514239626bcf4a850fcf9ef5c856ec3
|
||||
|
||||
PODFILE CHECKSUM: 6eac6b3292e5142cfc23bdeb71848a40ec51c14c
|
||||
|
||||
COCOAPODS: 1.11.3
|
||||
PODS:
|
||||
- connectivity_plus (0.0.1):
|
||||
- FlutterMacOS
|
||||
- ReachabilitySwift
|
||||
- dynamic_color (0.0.2):
|
||||
- FlutterMacOS
|
||||
- flutter_acrylic (0.1.0):
|
||||
- FlutterMacOS
|
||||
- flutter_local_notifications (0.0.1):
|
||||
- FlutterMacOS
|
||||
- FlutterMacOS (1.0.0)
|
||||
- FMDB (2.7.5):
|
||||
- FMDB/standard (= 2.7.5)
|
||||
- FMDB/standard (2.7.5)
|
||||
- path_provider_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- ReachabilitySwift (5.0.0)
|
||||
- share_plus_macos (0.0.1):
|
||||
- FlutterMacOS
|
||||
- sqflite (0.0.2):
|
||||
- FlutterMacOS
|
||||
- FMDB (>= 2.7.5)
|
||||
- url_launcher_macos (0.0.1):
|
||||
- FlutterMacOS
|
||||
|
||||
DEPENDENCIES:
|
||||
- connectivity_plus (from `Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos`)
|
||||
- dynamic_color (from `Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos`)
|
||||
- flutter_acrylic (from `Flutter/ephemeral/.symlinks/plugins/flutter_acrylic/macos`)
|
||||
- flutter_local_notifications (from `Flutter/ephemeral/.symlinks/plugins/flutter_local_notifications/macos`)
|
||||
- FlutterMacOS (from `Flutter/ephemeral`)
|
||||
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
|
||||
- share_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/share_plus_macos/macos`)
|
||||
- sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/macos`)
|
||||
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
|
||||
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
- FMDB
|
||||
- ReachabilitySwift
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
connectivity_plus:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos
|
||||
dynamic_color:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos
|
||||
flutter_acrylic:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/flutter_acrylic/macos
|
||||
flutter_local_notifications:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/flutter_local_notifications/macos
|
||||
FlutterMacOS:
|
||||
:path: Flutter/ephemeral
|
||||
path_provider_foundation:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin
|
||||
share_plus_macos:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/share_plus_macos/macos
|
||||
sqflite:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/sqflite/macos
|
||||
url_launcher_macos:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
connectivity_plus: 18d3c32514c886e046de60e9c13895109866c747
|
||||
dynamic_color: 2eaa27267de1ca20d879fbd6e01259773fb1670f
|
||||
flutter_acrylic: c3df24ae52ab6597197837ce59ef2a8542640c17
|
||||
flutter_local_notifications: 3805ca215b2fb7f397d78b66db91f6a747af52e4
|
||||
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
|
||||
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
|
||||
path_provider_foundation: eaf5b3e458fc0e5fbb9940fb09980e853fe058b8
|
||||
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
|
||||
share_plus_macos: 853ee48e7dce06b633998ca0735d482dd671ade4
|
||||
sqflite: a5789cceda41d54d23f31d6de539d65bb14100ea
|
||||
url_launcher_macos: 5335912b679c073563f29d89d33d10d459f95451
|
||||
|
||||
PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7
|
||||
|
||||
COCOAPODS: 1.12.1
|
||||
|
||||
@@ -1,87 +1,87 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1400"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
|
||||
BuildableName = "Felt Diary.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
|
||||
BuildableName = "Felt Diary.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<Testables>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
|
||||
BuildableName = "Felt Diary.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Profile"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
|
||||
BuildableName = "Felt Diary.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1300"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
|
||||
BuildableName = "Felt Diary.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
|
||||
BuildableName = "Felt Diary.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<Testables>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
|
||||
BuildableName = "Felt Diary.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Profile"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
|
||||
BuildableName = "Felt Diary.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
|
||||
@@ -3,7 +3,7 @@ description: "Nem hivatalos e-napló alkalmazás az e-Kréta rendszerhez"
|
||||
homepage: https://refilc.hu
|
||||
publish_to: "none"
|
||||
|
||||
version: 4.0.0+198
|
||||
version: 4.0.4+212
|
||||
|
||||
environment:
|
||||
sdk: ">=2.17.0 <3.0.0"
|
||||
@@ -67,6 +67,7 @@ dependencies:
|
||||
animations: ^2.0.1
|
||||
background_fetch: ^1.1.5
|
||||
flutter_local_notifications: ^14.1.0
|
||||
package_info_plus: ^3.1.2
|
||||
|
||||
dev_dependencies:
|
||||
flutter_lints: ^2.0.1
|
||||
@@ -146,11 +147,13 @@ flutter:
|
||||
weight: 700
|
||||
style: italic
|
||||
|
||||
flutter_icons:
|
||||
image_path: assets/icons/ic_launcher.png
|
||||
flutter_launcher_icons:
|
||||
image_path: assets/icons/ic_android.png
|
||||
android: true
|
||||
ios: true
|
||||
remove_alpha_ios: true
|
||||
adaptive_icon_background: "#3D7BF4"
|
||||
adaptive_icon_foreground: assets/icons/ic_android.png
|
||||
ios: false
|
||||
remove_alpha_ios: false
|
||||
|
||||
flutter_native_splash:
|
||||
color: "#3D7BF4"
|
||||
|
||||
@@ -26,16 +26,18 @@ import 'package:flutter_expandable_fab/flutter_expandable_fab.dart';
|
||||
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'grades_page.i18n.dart';
|
||||
// import 'package:filcnaplo_premium/ui/mobile/goalplanner/new_goal.dart';
|
||||
//import 'package:filcnaplo_premium/ui/mobile/goal_planner/new_goal.dart';
|
||||
|
||||
class GradeSubjectView extends StatefulWidget {
|
||||
const GradeSubjectView(this.subject, {Key? key, this.groupAverage = 0.0}) : super(key: key);
|
||||
const GradeSubjectView(this.subject, {Key? key, this.groupAverage = 0.0})
|
||||
: super(key: key);
|
||||
|
||||
final Subject subject;
|
||||
final double groupAverage;
|
||||
|
||||
void push(BuildContext context, {bool root = false}) {
|
||||
Navigator.of(context, rootNavigator: root).push(CupertinoPageRoute(builder: (context) => this));
|
||||
Navigator.of(context, rootNavigator: root)
|
||||
.push(CupertinoPageRoute(builder: (context) => this));
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -70,7 +72,9 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
|
||||
final gradeDates = subjectGrades.map((e) => e.date.millisecondsSinceEpoch);
|
||||
final maxGradeDate = gradeDates.fold(0, max);
|
||||
final minGradeDate = gradeDates.fold(0, min);
|
||||
if (maxGradeDate - minGradeDate < const Duration(days: 5).inMilliseconds) return false; // naplo/#78
|
||||
if (maxGradeDate - minGradeDate < const Duration(days: 5).inMilliseconds) {
|
||||
return false; // naplo/#78
|
||||
}
|
||||
|
||||
return subjectGrades.where((e) => e.type == GradeType.midYear).length > 1;
|
||||
}
|
||||
@@ -129,7 +133,8 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
|
||||
),
|
||||
);
|
||||
|
||||
tiles.add(Padding(padding: EdgeInsets.only(bottom: !gradeCalcMode ? 24.0 : 250.0)));
|
||||
tiles.add(Padding(
|
||||
padding: EdgeInsets.only(bottom: !gradeCalcMode ? 24.0 : 250.0)));
|
||||
gradeTiles = List.castFrom(tiles);
|
||||
}
|
||||
|
||||
@@ -142,7 +147,10 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
|
||||
average = AverageHelper.averageEvals(subjectGrades);
|
||||
final prevAvg = subjectGrades.isNotEmpty
|
||||
? AverageHelper.averageEvals(subjectGrades
|
||||
.where((e) => e.date.isBefore(subjectGrades.reduce((v, e) => e.date.isAfter(v.date) ? e : v).date.subtract(const Duration(days: 30))))
|
||||
.where((e) => e.date.isBefore(subjectGrades
|
||||
.reduce((v, e) => e.date.isAfter(v.date) ? e : v)
|
||||
.date
|
||||
.subtract(const Duration(days: 30))))
|
||||
.toList())
|
||||
: 0.0;
|
||||
|
||||
@@ -153,14 +161,17 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text("annual_average".i18n),
|
||||
if (average != prevAvg) TrendDisplay(current: average, previous: prevAvg),
|
||||
if (average != prevAvg)
|
||||
TrendDisplay(current: average, previous: prevAvg),
|
||||
],
|
||||
),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.only(top: 12.0, right: 12.0),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(child: GradeGraph(subjectGrades, dayThreshold: 5, classAvg: widget.groupAverage)),
|
||||
Expanded(
|
||||
child: GradeGraph(subjectGrades,
|
||||
dayThreshold: 5, classAvg: widget.groupAverage)),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 24.0),
|
||||
child: GradesCount(grades: subjectGrades),
|
||||
@@ -174,7 +185,9 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
|
||||
if (!gradeCalcMode) {
|
||||
buildTiles(subjectGrades);
|
||||
} else {
|
||||
List<Grade> ghostGrades = calculatorProvider.ghosts.where((e) => e.subject == widget.subject).toList();
|
||||
List<Grade> ghostGrades = calculatorProvider.ghosts
|
||||
.where((e) => e.subject == widget.subject)
|
||||
.toList();
|
||||
buildTiles(ghostGrades);
|
||||
}
|
||||
|
||||
@@ -182,7 +195,10 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
|
||||
key: _scaffoldKey,
|
||||
floatingActionButtonLocation: ExpandableFab.location,
|
||||
floatingActionButton: Visibility(
|
||||
visible: !gradeCalcMode && subjectGrades.where((e) => e.type == GradeType.midYear).isNotEmpty,
|
||||
visible: !gradeCalcMode &&
|
||||
subjectGrades
|
||||
.where((e) => e.type == GradeType.midYear)
|
||||
.isNotEmpty,
|
||||
child: ExpandableFab(
|
||||
type: ExpandableFabType.up,
|
||||
distance: 50,
|
||||
@@ -215,12 +231,17 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
|
||||
},
|
||||
navBarItems: [
|
||||
const SizedBox(width: 6.0),
|
||||
if (widget.groupAverage != 0) Center(child: AverageDisplay(average: widget.groupAverage, border: true)),
|
||||
if (widget.groupAverage != 0)
|
||||
Center(
|
||||
child: AverageDisplay(
|
||||
average: widget.groupAverage, border: true)),
|
||||
const SizedBox(width: 6.0),
|
||||
if (average != 0) Center(child: AverageDisplay(average: average)),
|
||||
if (average != 0)
|
||||
Center(child: AverageDisplay(average: average)),
|
||||
const SizedBox(width: 12.0),
|
||||
],
|
||||
icon: SubjectIcon.resolveVariant(subject: widget.subject, context: context),
|
||||
icon: SubjectIcon.resolveVariant(
|
||||
subject: widget.subject, context: context),
|
||||
scrollController: _scrollController,
|
||||
title: widget.subject.renamedTo ?? widget.subject.name.capital(),
|
||||
italic: widget.subject.isRenamed,
|
||||
@@ -240,13 +261,15 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
|
||||
|
||||
void gradeCalc(BuildContext context) {
|
||||
// Scroll to the top of the page
|
||||
_scrollController.animateTo(75, duration: const Duration(milliseconds: 500), curve: Curves.ease);
|
||||
_scrollController.animateTo(75,
|
||||
duration: const Duration(milliseconds: 500), curve: Curves.ease);
|
||||
|
||||
calculatorProvider.clear();
|
||||
calculatorProvider.addAllGrades(gradeProvider.grades);
|
||||
|
||||
_sheetController = _scaffoldKey.currentState?.showBottomSheet(
|
||||
(context) => RoundedBottomSheet(child: GradeCalculator(widget.subject), borderRadius: 14.0),
|
||||
(context) => RoundedBottomSheet(
|
||||
child: GradeCalculator(widget.subject), borderRadius: 14.0),
|
||||
backgroundColor: const Color(0x00000000),
|
||||
elevation: 12.0,
|
||||
);
|
||||
|
||||