Compare commits

..

155 Commits
4.3.0 ... 4.5.1

Author SHA1 Message Date
Márton Kiss
88717d5925 Merge pull request #82 from refilc/dev
Dev
2023-12-26 00:21:09 +01:00
Kima
6cb86245cb fixed little thingies 2023-12-26 00:15:29 +01:00
Kima
8f393cd9c5 changed version string 2023-12-26 00:12:45 +01:00
Kima
38d892d9a1 temp removed app icon change button 2023-12-26 00:07:49 +01:00
Márton Kiss
fb70b2be38 Merge pull request #81 from refilc/dev
Dev
2023-12-26 00:06:19 +01:00
Kima
a5e368d983 added back everything to refilc+ submodule 2023-12-26 00:05:45 +01:00
Kima
de3fa0c71d added submodule back 2023-12-26 00:00:45 +01:00
Kima
cbece0e841 temp removed submodule 2023-12-25 23:51:36 +01:00
Kima
ac77f26eb2 idk test 2023-12-25 23:43:41 +01:00
Kima
52b4a9429b fixed message sending error 2023-12-25 23:36:51 +01:00
Márton Kiss
588bc2567e Merge pull request #80 from refilc/dev
Dev
2023-12-25 22:09:31 +01:00
Márton Kiss
d2d36c3d0f Merge branch 'master' into dev 2023-12-25 22:09:22 +01:00
Kima
8ef2bee62e why 2023-12-25 21:59:12 +01:00
Kima
30bde8b040 Merge branch 'dev' of github.com:refilc/naplo into dev 2023-12-25 21:59:00 +01:00
Kima
042522dc5a idk windows something 2023-12-25 21:58:58 +01:00
ReinerRego
fdc9276170 what 2023-12-23 02:16:44 +01:00
ReinerRego
413494a9ac Merge branch 'dev' of github.com:refilc/naplo into dev 2023-12-23 02:15:56 +01:00
Kima
8e3996e2f0 hide bottom sheet after msg sent 2023-12-23 00:05:51 +01:00
Kima
f46610314d fixed msg sending and added error handler 2023-12-23 00:05:12 +01:00
Kima
fdc6209656 updated version string (probably last time before update) 2023-12-22 22:22:53 +01:00
Kima
6def864b1f fixed renamed subjects italic font 2023-12-22 22:04:11 +01:00
Kima
fc40793534 fixed goal planner limit 2023-12-22 21:54:35 +01:00
Kima
f533c5d4f5 changed open_file to open_filex fort (fixed some issues maybe) 2023-12-22 21:31:59 +01:00
Kima
3a44a2f9bc fixed teacher rename error 2023-12-22 21:01:57 +01:00
Kima
1bf512991b fixed teacher rename error 2023-12-22 21:01:47 +01:00
ReinerRego
fb8b3ae73f changed login screen desktop 2023-12-22 19:21:18 +01:00
Kima
50d2d44ac2 fixed smth in message sending 2023-12-21 21:55:34 +01:00
Kima
b929766b14 something idk 2023-12-21 21:17:49 +01:00
Kima
d34371bfff finally "fixed" all shit issues in vscode 2023-12-21 21:17:38 +01:00
Kima
6bac82f7d6 fixed warnings (super.key, etc) 2023-12-12 22:57:16 +01:00
Kima
fc3f538e6b added translation to message sending 2023-12-12 22:42:22 +01:00
Kima
939e33feeb almost finished send message ui and functionality 2023-12-12 21:55:30 +01:00
Kima
a175a9ea1c fixed warnings and added bottom sheet to message sending 2023-12-12 20:39:17 +01:00
Kima
969aec0f11 finished message sending api ig 2023-12-12 19:45:51 +01:00
Kima
871c93050c added almost everything to provider 2023-12-12 19:07:39 +01:00
Kima
7f9c22bdcd added db shit to recipient storing 2023-12-12 19:01:01 +01:00
Kima
c06e9bc807 fixed warnings 2023-12-10 22:49:55 +01:00
Kima
7b7f603d9c finished sendable message base class gn 2023-12-10 22:47:25 +01:00
Kima
f4a6a0ceb0 lot of work in message sending thing 2023-12-10 22:42:39 +01:00
Kima
adc8deffa9 startend msg sending api thingie 2023-12-10 20:37:40 +01:00
Kima
3484230ced commented dropdown cuz not used currently 2023-12-10 19:33:25 +01:00
ReinerRego
40740b80d0 done i think 2023-12-09 21:12:14 +01:00
ReinerRego
20f20218e0 updated and added dropdownbutton 2023-12-09 20:03:58 +01:00
Kima
68c9745ce0 added gitignore to git 2023-12-09 19:59:46 +01:00
ReinerRego
70c8ac1876 added exam filter finally 2023-12-09 19:58:43 +01:00
Kima
bdfec4230b fixed app close on back button 2023-12-09 18:05:17 +01:00
Kima
093063b438 updated version string 2023-12-09 17:53:12 +01:00
Kima
bcab128332 fixed another weird shit 2023-12-09 17:39:56 +01:00
Kima
56500406e5 fixed things that were fucked up by pub upgrade 2023-12-09 17:23:21 +01:00
Kima
9f5e57eec6 fixed other shit 2023-12-09 17:01:00 +01:00
Kima
5079e0cb29 fixed weird warnings 2023-12-09 16:52:52 +01:00
Kima
646948012d fixed translation 2023-12-09 16:48:33 +01:00
Kima
399069537f maybe fixed timetable clear bug on kreten api error 2023-12-09 16:13:36 +01:00
Kima
1c49ffd57f temp removed app icon shit 2023-12-09 16:02:31 +01:00
Kima
8df3623d91 Merge branch 'dev' of github.com:refilc/naplo into dev 2023-12-09 15:42:24 +01:00
Kima
61ad26e047 updatet smth 2023-12-09 15:42:22 +01:00
Kima
51a6492477 CONVERT KEY TO SUPER PARAMETER KYS 2023-12-09 15:42:02 +01:00
ReinerRego
7d26a8bc33 changed gitmodules 2023-12-09 14:07:36 +01:00
Kima
e243b5c186 added adfghsdhg 2023-12-08 21:22:03 +01:00
Kima
043785fe35 why the hell was widget code in gitignore 2023-12-08 21:19:29 +01:00
Kima
72332b5000 remove unused temp files 2023-12-08 21:17:53 +01:00
Kima
e73aa6c1b0 fixed build shit 2023-12-08 21:16:21 +01:00
Kima
3410e410d2 fully finished total grade calculator 2023-11-21 21:47:09 +01:00
Kima
aba39505d9 half-working total average calculator done :3 2023-11-19 23:21:10 +01:00
Kima
ebf9c8526d icon 2023-11-18 22:35:25 +01:00
Kima
f5ab4bbc98 perfect 2023-11-18 22:01:36 +01:00
Kima
1764bb0f01 refilc+ smth 2023-11-18 21:28:54 +01:00
Kima
271e47619e idk smth old commit 2023-11-18 10:59:06 +01:00
ReinerRego
cd0c821bae wrong api lol 2023-11-14 22:43:16 +01:00
ReinerRego
6a1cb9f3eb made linux and uncommnented login from desktop ui 2023-11-14 22:42:55 +01:00
Kima
c6c5759a2c finished custom app icon option 2023-10-23 19:43:13 +02:00
Kima
b94ed46c8a app icon db and other things 2023-10-23 17:54:16 +02:00
Kima
b0eb78218a updated gitignore 2023-10-23 16:08:15 +02:00
Kima
1ac618c29f some progress in custom app icon thingie 2023-10-21 23:49:21 +02:00
Kima
7840a07c95 added gitignore to rfplus 2023-10-21 22:33:21 +02:00
Kima
3f5b8ab607 started doing app icon change 2023-10-21 22:20:16 +02:00
Kima
41fe5a3d05 csinaltam ezt meg azt pusz 2023-10-21 21:39:02 +02:00
Kima
af87e5ed36 smth 2023-10-21 21:33:58 +02:00
Kima
797963e63d removed shit 2023-10-21 21:22:59 +02:00
Kima
6a1eafe980 added submodule 2023-10-21 21:22:43 +02:00
Kima
5e7414ada8 renamed folder so i can add it as a submodule 2023-10-21 21:17:27 +02:00
Kima
8e391c9c7f Merge branch 'dev' of github.com:refilc/naplo into dev 2023-10-21 21:11:42 +02:00
Kima
316039463f moved non-premium features from premium folder 2023-10-21 21:11:39 +02:00
Márton Kiss
8e320b235c removed sebrhq from readme 2023-10-21 11:23:05 +02:00
Pearoo
be28c50ffc Make room number bigger for live card 2023-10-19 09:39:52 +02:00
Márton Kiss
82db2e2091 Merge pull request #75 from refilc/dev
added gitignore
2023-10-15 20:57:27 +02:00
Kima
774f63aa89 added gitignore 2023-10-15 20:57:00 +02:00
Márton Kiss
8375e1877a Merge pull request #74 from refilc/dev
changed build number to final
2023-10-15 20:34:10 +02:00
Kima
b00fab090c changed build number to final 2023-10-15 20:33:31 +02:00
Márton Kiss
382961971d Merge pull request #73 from refilc/dev
Dev
2023-10-15 20:29:14 +02:00
Kima
04c5c819f8 remove trailing from app icon option 2023-10-15 19:59:00 +02:00
Kima
6249015bef Revert "Some localization changes"
This reverts commit be4737f9db.
2023-10-15 19:54:17 +02:00
Kima
2fade7117b Merge branch 'dev' of github.com:refilc/naplo into dev 2023-10-15 19:48:23 +02:00
Kima
49c396e746 fixed error reporting 2023-10-15 19:48:20 +02:00
Pearoo
be4737f9db Some localization changes 2023-10-15 18:43:29 +02:00
Kima
d27c059b23 fixed height glitch on grades page 2023-10-15 17:20:08 +02:00
Kima
21a5771211 temp removed icon color tab 2023-10-15 16:35:50 +02:00
Kima
501d83c229 Merge branch 'dev' of github.com:refilc/naplo into dev 2023-10-15 16:08:26 +02:00
Kima
6651bbf14a fixed typo 2023-10-15 16:08:23 +02:00
Pearoo
ddf1944883 Fix typo in failure_warning 2023-10-15 16:03:02 +02:00
Kima
bf0eeb83e4 changed "default" to "dynamic" at welcome message 2023-10-15 15:15:13 +02:00
Kima
d41c39849b changed build number 2023-10-15 15:14:07 +02:00
Kima
25294dd4a7 added "soon alert" widget 2023-10-15 15:03:09 +02:00
Kima
d0f347c80d added app icon change option to settings 2023-10-15 15:02:59 +02:00
Kima
44464e1946 moved "secret settings" after account list 2023-10-15 14:41:31 +02:00
Kima
5a371d7200 added "send message" button to messages screen 2023-10-15 14:36:43 +02:00
Kima
27fefb4c27 fixed homework provider finally 2023-10-15 14:29:25 +02:00
Kima
efe58eeea9 added clear goal button to goal planning 2023-10-15 13:46:58 +02:00
Kima
8e629ef596 added textfield clear to enterid in theme menu 2023-10-15 13:18:25 +02:00
Kima
d188cefc07 fixed theme share with new options 2023-10-15 13:15:55 +02:00
Kima
c5b6f92b0e commented subject provider 2023-10-15 12:55:14 +02:00
Kima
2d5cbe8799 changed old subject type to gradesubject 2023-10-15 12:14:06 +02:00
Pearoo
c7c3b421f4 Added subjects API endpoint
Also added JSON structure in comments
No implementation yet, will be used in the future
Kudos @sleddev
2023-10-15 11:42:35 +02:00
Kima
adfa653062 changed version string 2023-10-12 21:48:16 +02:00
Kima
86f7cf3b2e fixed subject icon things 2023-10-12 21:10:14 +02:00
Kima
1cc885e4b7 fixed exam subject rename thing 2023-10-12 21:06:53 +02:00
Kima
a4207b8348 fixed livecard italic font bug 2023-10-12 20:58:23 +02:00
Kima
3e600f69f0 fix shadow thing on timetable 2023-10-12 20:54:07 +02:00
Kima
205d90523c added check everywhere to shadow effect 2023-10-12 20:38:32 +02:00
Kima
906de6dd45 changed shadow effect toggle icon to moon 2023-10-12 20:10:04 +02:00
Kima
3ff0927834 added toggle for shadow effect to settings screen 2023-10-12 20:08:23 +02:00
Kima
14e5614adc done icon color changer in settings 2023-10-12 19:51:41 +02:00
Kima
6ed89b2a1e added missing translation 2023-10-12 19:26:41 +02:00
Kima
5272ac5a01 added icon color changer everywhere 2023-10-12 19:24:40 +02:00
Kima
46e6120af3 added things to db and theme share 2023-10-12 19:14:40 +02:00
Kima
600bf7d763 removed import dsklfjnu 2023-10-12 19:10:54 +02:00
Kima
10750f898f added shadow effect and icon color option to sp 2023-10-12 19:10:32 +02:00
Pearoo
1d5ebe7bbd Fix cancelled vs. delayed card
Fixes https://discord.com/channels/1111649116020285532/1154687576758829097
Implements 9845a35 from `cancelled-bugfix` branch
Deletes `cancelled-bugfix` branch
2023-10-10 07:01:57 +02:00
Pearoo
2aa8db8f42 Merge pull request #70 from refilc/dev
Implement 6388932
2023-10-10 06:47:55 +02:00
Pearoo
f95d4582be Implement 6388932 2023-10-09 07:37:40 +02:00
Pearoo
63889325cf Add good student disclaimer german localisation
Fixes https://discord.com/channels/1111649116020285532/1160698590033870848
2023-10-09 07:26:29 +02:00
Márton Kiss
acbffd6d72 Merge pull request #69 from refilc/dev
69-es szamu pr haha 😏
2023-10-08 17:00:13 +02:00
Kima
b19da9cb66 finally fixed kreten error shit sdfadfsdfhsdfgh 2023-10-08 16:55:06 +02:00
Kima
fd80aec51f added upgrade-pub.sh to upgrade pub packages 2023-10-08 16:24:59 +02:00
Kima
5776622276 settings account tiles now showing nickname 2023-10-08 12:44:45 +02:00
Kima
69ea3e1a7f update version string 2023-10-08 12:03:08 +02:00
Kima
3d451f6f91 fixed the fix lol 2023-10-08 11:52:39 +02:00
Kima
387e2e46db fixed i18n error spam on home screen (welcome msg) 2023-10-08 11:51:09 +02:00
Kima
a7f1681902 someone commented birthday greeting, fuck yourself 2023-10-08 11:48:09 +02:00
Kima
4b127bdf56 fixed homewrok not showing up 2023-10-08 11:46:00 +02:00
Kima
dbb6125ab5 fixed live card not showing on android 2023-10-08 11:42:27 +02:00
Kima
b6d4ac6168 maybe fixed error shit 2023-10-08 11:33:09 +02:00
Kima
9d20d08838 fixed goal planner done popup 2023-10-07 19:41:33 +02:00
Kima
f39ac80770 fixed app bricking with welcome message thing 2023-10-05 21:54:57 +02:00
Kima
41991b3b66 change log message bc livecard is shit but idk why 2023-10-05 21:30:24 +02:00
ReinerRego
53ec3e567a Merge pull request #68 from TMarccci/dev
Xcode 15, iOS 17 - Bug Fix+Others
2023-10-05 00:07:41 +02:00
Tihanyi Marcell
176608bfc5 Xcode 15, iOS 17 - Bug Fix+Others 2023-10-04 23:25:00 +02:00
ReinerRego
92b4094550 started fixing desktop ui 2023-10-04 14:10:17 +02:00
Márton Kiss
45c6fccb89 Merge pull request #66 from TMarccci/master
Added a few subjects to helper
2023-09-28 21:37:56 +02:00
Tihanyi Marcell
014329d7fe Added a few subjects to helper 2023-09-28 21:28:30 +02:00
Márton Kiss
dca01d0ed0 Merge pull request #65 from sleddev/dev
timetable italics + instituteCode search + theme preview background color
2023-09-28 21:17:50 +02:00
SledDev
493adaa5f2 fixed background color in theme preview 2023-09-28 20:15:09 +02:00
SledDev
8451983163 find schools by instituteCode 2023-09-28 19:41:43 +02:00
SledDev
2b7e143812 fixed fullscreen timetable italics 2023-09-28 19:12:56 +02:00
Pearoo
9845a35c6e Fix english absence error + comment bugreports 2023-09-28 18:17:24 +02:00
273 changed files with 3574 additions and 5562 deletions

85
.gitignore vendored
View File

@@ -1,52 +1,39 @@
# See https://www.dartlang.org/guides/libraries/private-files
.gitignore
filcnaplo/.flutter-plugins
filcnaplo/.flutter-plugins-dependencies
filcnaplo/pubspec.lock
filcnaplo/.dart_tool/
filcnaplo/android/
filcnaplo/ios/
filcnaplo/windows/
filcnaplo/linux/
filcnaplo/macos/
filcnaplo/build/
termek.txt
filcnaplo_desktop_ui/.flutter-plugins
filcnaplo_desktop_ui/.flutter-plugins-dependencies
filcnaplo_desktop_ui/pubspec.lock
filcnaplo_desktop_ui/.dart_tool/
filcnaplo_kreta_api/.flutter-plugins
filcnaplo_kreta_api/.flutter-plugins-dependencies
filcnaplo_kreta_api/pubspec.lock
filcnaplo_kreta_api/.dart_tool/
filcnaplo_mobile_ui/.flutter-plugins
filcnaplo_mobile_ui/.flutter-plugins-dependencies
filcnaplo_mobile_ui/pubspec.lock
filcnaplo_mobile_ui/.dart_tool/
filcnaplo_premium/.flutter-plugins
filcnaplo_premium/.flutter-plugins-dependencies
filcnaplo_premium/pubspec.lock
filcnaplo_premium/.dart_tool/
.vscode
.github
.idea
.gitmodules
filcnaplo/.DS_Store
.DS_Store
filc3.properties
local.properties
# Files and directories created by pub
.dart_tool/
.packages
build/
# If you're building an application, you may want to check-in your pubspec.lock
pubspec.lock
# Directory created by dartdoc
# If you don't generate documentation locally you can remove this line.
doc/api/
# Avoid committing generated Javascript files:
*.dart.js
*.info.json # Produced by the --dump-info flag.
*.js # When generated by dart2js. Don't specify *.js if your
# project includes source files written in JavaScript.
*.js_
*.js.deps
*.js.map
*.txt
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/*
filcnaplo/ios/Podfile.lock
.vscode/
key.properties
.flutter-plugins*
filcnaplo/ios/Flutter/flutter_export_environment 4.sh
filcnaplo/ios/Flutter/Generated 4.xcconfig

3
.gitmodules vendored
View File

@@ -0,0 +1,3 @@
[submodule "naplo-plus"]
path = filcnaplo_premium
url = git@github.com:refilc/naplo-plus.git

3
.idea/.gitignore generated vendored
View File

@@ -1,3 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml

40
.vscode/launch.json vendored
View File

@@ -1,40 +0,0 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "filcnaplo",
"cwd": "filcnaplo",
"request": "launch",
"type": "dart",
"toolArgs": [
"--dart-define=APPVER=$(cat pubspec.yaml | grep version: | cut -d' ' -f2 | cut -d+ -f1)"
]
},
// {
// "name": "filcnaplo release",
// "cwd": "filcnaplo release",
// "request": "launch",
// "type": "dart",
// "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"
},
{
"name": "Flutter (release)",
"program": "lib/main.dart",
"cwd": "filcnaplo",
"request": "launch",
"type": "dart",
"flutterMode": "release"
}
]
}

View File

@@ -43,7 +43,7 @@ Az összes (ugyan azon verzióhoz tartozó) contribution meg fog jelenni a relea
**vrolandd, TMarccci:** head developer
**dwe., xou, SebRHQ:** designer
**dwe., xou:** designer
**Péter:** video editor

91
filcnaplo/.gitignore vendored
View File

@@ -1,47 +1,44 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
/build/
# Web related
lib/generated_plugin_registrant.dart
# Symbolication related
app.*.symbols
# Obfuscation related
app.*.map.json
# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release
key.properties
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
migrate_working_dir/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
/build/
# Symbolication related
app.*.symbols
# Obfuscation related
app.*.map.json
# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release

View File

@@ -1,11 +1,11 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled.
# This file should be version controlled and should not be manually edited.
version:
revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
channel: stable
revision: "b0366e0a3f089e15fd89c97604ab402fe26b724c"
channel: "stable"
project_type: app
@@ -13,11 +13,17 @@ project_type: app
migration:
platforms:
- platform: root
create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
- platform: web
create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
create_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
base_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
- platform: linux
create_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
base_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
- platform: macos
create_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
base_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
- platform: windows
create_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
base_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
# User provided section

View File

@@ -1,12 +0,0 @@
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
# Remember to never publicly share your keystore.
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
key.properties
.project

View File

@@ -1,7 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" package="hu.refilc.naplo">
<application android:name="${applicationName}" android:label="reFilc" tools:replace="android:label" android:icon="@mipmap/ic_launcher"
android:requestLegacyExternalStorage="true">
android:requestLegacyExternalStorage="true" android:enableOnBackInvokedCallback="false">
<activity android:exported="true" android:name="hu.refilc.naplo.MainActivity"
android:launchMode="singleTop" android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
@@ -13,7 +13,8 @@
<meta-data android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<!-- commented bc of dynamic app icons -->
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter android:autoVerify="true">
@@ -39,6 +40,69 @@
</activity>
<meta-data android:name="flutterEmbedding" android:value="2" />
<!-- custom app icon thingies from here -->
<!-- <activity-alias
android:label="reFilc"
android:icon="@drawable/launch_ic_refilc_default"
android:name=".MainActivityAlias"
android:enabled="true"
android:exported="true"
android:targetActivity=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:label="reFilc"
android:icon="@drawable/launch_ic_refilc_default"
android:name=".MainActivityAliasrefilc_default"
android:enabled="false"
android:exported="true"
android:targetActivity=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:label="reFilc"
android:icon="@drawable/launch_ic_refilc_overcomplicated"
android:name=".MainActivityAliasrefilc_overcomplicated"
android:enabled="false"
android:exported="true"
android:targetActivity=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:label="reFilc"
android:icon="@drawable/launch_ic_refilc_concept"
android:name=".MainActivityAliasrefilc_concept"
android:enabled="false"
android:exported="true"
android:targetActivity=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:label="reFilc"
android:icon="@drawable/launch_ic_refilc_pride"
android:name=".MainActivityAliasrefilc_pride"
android:enabled="false"
android:exported="true"
android:targetActivity=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias> -->
<!-- end of custom app icon thingies -->
<receiver android:name="hu.refilc.naplo.widget_timetable.WidgetTimetable"
android:exported="true">
<intent-filter>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 185 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -136,7 +136,7 @@
android:layout_below="@id/iv_1"
android:layout_marginHorizontal="15dp"
android:fontFamily="@font/montserrat_medium"
android:text="A widget használatához, bejelentkezés szükséges."
android:text="A widget használatához bejelentkezés szükséges."
android:textColor="@color/black"
android:paddingTop="10dp"
android:textSize="17sp"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 185 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -1,93 +0,0 @@
Copyright 2011 The Montserrat Project Authors (https://github.com/JulietaUla/Montserrat)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

View File

@@ -1,33 +0,0 @@
*.mode1v3
*.mode2v3
*.moved-aside
*.pbxuser
*.perspectivev3
**/*sync/
.sconsign.dblite
.tags*
**/.vagrant/
**/DerivedData/
Icon?
**/Pods/
**/.symlinks/
profile
xcuserdata
**/.generated/
Flutter/App.framework
Flutter/Flutter.framework
Flutter/Flutter.podspec
Flutter/Generated.xcconfig
Flutter/ephemeral/
Flutter/app.flx
Flutter/app.zip
Flutter/flutter_assets/
Flutter/flutter_export_environment.sh
ServiceDefinitions.json
Runner/GeneratedPluginRegistrant.*
# Exceptions to above rules.
!default.mode1v3
!default.mode2v3
!default.pbxuser
!default.perspectivev3

View File

@@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '11.0'
platform :ios, '12.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
@@ -39,5 +39,8 @@ end
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
target.build_configurations.each do |config|
config.build_settings.delete 'IPHONEOS_DEPLOYMENT_TARGET'
end
end
end

View File

@@ -17,6 +17,14 @@
3127F7A828EAEE8500C2EFB3 /* lesson_model.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3127F7A728EAEE8500C2EFB3 /* lesson_model.swift */; };
373A6ECB5FC71FE9D8AF2EDB /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F0ADD56276103500A3016C8 /* Pods_Runner.framework */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
3B4461282AE6E0FF00AAE6FD /* refilc_default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3B4461202AE6E0FF00AAE6FD /* refilc_default@2x.png */; };
3B4461292AE6E0FF00AAE6FD /* refilc_concept@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3B4461212AE6E0FF00AAE6FD /* refilc_concept@2x.png */; };
3B44612A2AE6E0FF00AAE6FD /* refilc_concept@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3B4461222AE6E0FF00AAE6FD /* refilc_concept@3x.png */; };
3B44612B2AE6E0FF00AAE6FD /* refilc_overcomplicated@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3B4461232AE6E0FF00AAE6FD /* refilc_overcomplicated@2x.png */; };
3B44612C2AE6E0FF00AAE6FD /* refilc_default@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3B4461242AE6E0FF00AAE6FD /* refilc_default@3x.png */; };
3B44612D2AE6E0FF00AAE6FD /* refilc_overcomplicated@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3B4461252AE6E0FF00AAE6FD /* refilc_overcomplicated@3x.png */; };
3B44612E2AE6E0FF00AAE6FD /* refilc_pride@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3B4461262AE6E0FF00AAE6FD /* refilc_pride@2x.png */; };
3B44612F2AE6E0FF00AAE6FD /* refilc_pride@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3B4461272AE6E0FF00AAE6FD /* refilc_pride@3x.png */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
@@ -73,6 +81,14 @@
3127F7A728EAEE8500C2EFB3 /* lesson_model.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = lesson_model.swift; sourceTree = "<group>"; };
317DE77A294F6FFB002E323E /* livecard.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = livecard.entitlements; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
3B4461202AE6E0FF00AAE6FD /* refilc_default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "refilc_default@2x.png"; path = "../../../../../../../../../Downloads/iloveimg-resized/refilc_default@2x.png"; sourceTree = "<group>"; };
3B4461212AE6E0FF00AAE6FD /* refilc_concept@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "refilc_concept@2x.png"; path = "../../../../../../../../../Downloads/iloveimg-resized/refilc_concept@2x.png"; sourceTree = "<group>"; };
3B4461222AE6E0FF00AAE6FD /* refilc_concept@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "refilc_concept@3x.png"; path = "../../../../../../../../../Downloads/iloveimg-resized (1)/refilc_concept@3x.png"; sourceTree = "<group>"; };
3B4461232AE6E0FF00AAE6FD /* refilc_overcomplicated@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "refilc_overcomplicated@2x.png"; path = "../../../../../../../../../Downloads/iloveimg-resized/refilc_overcomplicated@2x.png"; sourceTree = "<group>"; };
3B4461242AE6E0FF00AAE6FD /* refilc_default@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "refilc_default@3x.png"; path = "../../../../../../../../../Downloads/iloveimg-resized (1)/refilc_default@3x.png"; sourceTree = "<group>"; };
3B4461252AE6E0FF00AAE6FD /* refilc_overcomplicated@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "refilc_overcomplicated@3x.png"; path = "../../../../../../../../../Downloads/iloveimg-resized (1)/refilc_overcomplicated@3x.png"; sourceTree = "<group>"; };
3B4461262AE6E0FF00AAE6FD /* refilc_pride@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "refilc_pride@2x.png"; path = "../../../../../../../../../Downloads/iloveimg-resized/refilc_pride@2x.png"; sourceTree = "<group>"; };
3B4461272AE6E0FF00AAE6FD /* refilc_pride@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "refilc_pride@3x.png"; path = "../../../../../../../../../Downloads/iloveimg-resized (1)/refilc_pride@3x.png"; 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>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
@@ -122,6 +138,21 @@
path = livecard;
sourceTree = "<group>";
};
3B44611F2AE6DF7200AAE6FD /* App Icons */ = {
isa = PBXGroup;
children = (
3B4461212AE6E0FF00AAE6FD /* refilc_concept@2x.png */,
3B4461222AE6E0FF00AAE6FD /* refilc_concept@3x.png */,
3B4461202AE6E0FF00AAE6FD /* refilc_default@2x.png */,
3B4461242AE6E0FF00AAE6FD /* refilc_default@3x.png */,
3B4461232AE6E0FF00AAE6FD /* refilc_overcomplicated@2x.png */,
3B4461252AE6E0FF00AAE6FD /* refilc_overcomplicated@3x.png */,
3B4461262AE6E0FF00AAE6FD /* refilc_pride@2x.png */,
3B4461272AE6E0FF00AAE6FD /* refilc_pride@3x.png */,
);
path = "App Icons";
sourceTree = "<group>";
};
6640A963014A9D4F31026053 /* Frameworks */ = {
isa = PBXGroup;
children = (
@@ -178,6 +209,7 @@
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
3B44611F2AE6DF7200AAE6FD /* App Icons */,
3127F73928EAEC3200C2EFB3 /* Runner.entitlements */,
97C146FA1CF9000F007C117D /* Main.storyboard */,
97C146FD1CF9000F007C117D /* Assets.xcassets */,
@@ -286,10 +318,18 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
3B44612A2AE6E0FF00AAE6FD /* refilc_concept@3x.png in Resources */,
3B44612F2AE6E0FF00AAE6FD /* refilc_pride@3x.png in Resources */,
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
3B44612E2AE6E0FF00AAE6FD /* refilc_pride@2x.png in Resources */,
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
3B44612C2AE6E0FF00AAE6FD /* refilc_default@3x.png in Resources */,
3B4461292AE6E0FF00AAE6FD /* refilc_concept@2x.png in Resources */,
3B4461282AE6E0FF00AAE6FD /* refilc_default@2x.png in Resources */,
3B44612D2AE6E0FF00AAE6FD /* refilc_overcomplicated@3x.png in Resources */,
3B44612B2AE6E0FF00AAE6FD /* refilc_overcomplicated@2x.png in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@@ -2,6 +2,59 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleAlternateIcons</key>
<dict>
<key>refilc_pride</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>refilc_pride</string>
</array>
<key>UIPrerenderedIcon</key>
<false/>
</dict>
<key>refilc_overcomplicated</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>refilc_overcomplicated</string>
</array>
<key>UIPrerenderedIcon</key>
<false/>
</dict>
<key>refilc_concept</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>refilc_concept</string>
</array>
<key>UIPrerenderedIcon</key>
<false/>
</dict>
<key>refilc_default</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>refilc_default</string>
</array>
<key>UIPrerenderedIcon</key>
<false/>
</dict>
</dict>
<key>CFBundleIcons</key>
<dict>
<key>CFBundlePrimaryIcon</key>
<dict>
<key>CFBundleIconName</key>
<string></string>
<key>CFBundleIconFiles</key>
<array>
<string></string>
</array>
<key>UIPrerenderedIcon</key>
<false/>
</dict>
</dict>
<key>BGTaskSchedulerPermittedIdentifiers</key>
<array>
<string>com.transistorsoft.fetch</string>

View File

@@ -190,12 +190,22 @@ class FilcAPI {
static Future<void> sendReport(ErrorReport report) async {
try {
http.Response res = await http.post(Uri.parse(reportApi), body: {
Map body = {
"os": report.os,
"version": report.version,
"error": report.error,
"stack_trace": report.stack,
});
};
var client = http.Client();
http.Response res = await client.post(
Uri.parse(reportApi),
body: body,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
);
if (res.statusCode != 200) {
throw "HTTP ${res.statusCode}: ${res.body}";
@@ -213,6 +223,8 @@ class FilcAPI {
theme.json['background_color'] = theme.backgroundColor.value.toString();
theme.json['panels_color'] = theme.panelsColor.value.toString();
theme.json['accent_color'] = theme.accentColor.value.toString();
theme.json['icon_color'] = theme.iconColor.value.toString();
theme.json['shadow_effect'] = theme.shadowEffect.toString();
// set linked grade colors
theme.json['grade_colors_id'] = theme.gradeColors.id;

View File

@@ -163,6 +163,8 @@ Future loginAPI({
Provider.of<ExamProvider>(context, listen: false).fetch(),
Provider.of<HomeworkProvider>(context, listen: false).fetch(),
Provider.of<MessageProvider>(context, listen: false).fetchAll(),
Provider.of<MessageProvider>(context, listen: false)
.fetchAllRecipients(),
Provider.of<NoteProvider>(context, listen: false).fetch(),
Provider.of<EventProvider>(context, listen: false).fetch(),
Provider.of<AbsenceProvider>(context, listen: false).fetch(),

View File

@@ -51,7 +51,7 @@ class LiveCardProvider extends ChangeNotifier {
_liveActivitiesPlugin.areActivitiesEnabled().then((value) {
// Console log
if (kDebugMode) {
print("Live card enabled: $value");
print("iOS LiveActivity enabled: $value");
}
if (value) {
@@ -62,13 +62,13 @@ class LiveCardProvider extends ChangeNotifier {
});
}
});
_timer = Timer.periodic(const Duration(seconds: 1), (timer) => update());
_delay = settings.bellDelayEnabled
? Duration(seconds: settings.bellDelay)
: Duration.zero;
update();
}
_timer = Timer.periodic(const Duration(seconds: 1), (timer) => update());
_delay = settings.bellDelayEnabled
? Duration(seconds: settings.bellDelay)
: Duration.zero;
update();
}
@override
@@ -196,7 +196,7 @@ class LiveCardProvider extends ChangeNotifier {
}
} catch (e) {
if (kDebugMode) {
print('ERROR: Unable to create or update iOS LiveCard!');
print('ERROR: Unable to create or update iOS LiveActivity!');
}
}
}

View File

@@ -79,11 +79,12 @@ class StatusProvider extends ChangeNotifier {
}
}
if (_stack.contains(Status.network)) return;
if (res.body == "invalid_grant" ||
if (res.body == 'invalid_grant' ||
res.body.replaceAll(' ', '') == '' ||
res.statusCode == 400) {
if (!_stack.contains(Status.apiError)) {
if (!_stack.contains(Status.apiError) &&
!_stack.contains(Status.network)) {
if (res.statusCode == 401) return;
_stack.insert(0, Status.apiError);
notifyListeners();
}

View File

@@ -34,7 +34,8 @@ Future<void> syncAll(BuildContext context) {
print("INFO Syncing all");
UserProvider user = Provider.of<UserProvider>(context, listen: false);
StatusProvider statusProvider = Provider.of<StatusProvider>(context, listen: false);
StatusProvider statusProvider =
Provider.of<StatusProvider>(context, listen: false);
List<Future<void>> tasks = [];
int taski = 0;
@@ -47,10 +48,14 @@ Future<void> syncAll(BuildContext context) {
tasks = [
syncStatus(Provider.of<GradeProvider>(context, listen: false).fetch()),
syncStatus(Provider.of<TimetableProvider>(context, listen: false).fetch(week: Week.current())),
syncStatus(Provider.of<TimetableProvider>(context, listen: false)
.fetch(week: Week.current())),
syncStatus(Provider.of<ExamProvider>(context, listen: false).fetch()),
syncStatus(Provider.of<HomeworkProvider>(context, listen: false).fetch(from: DateTime.now().subtract(const Duration(days: 30)))),
syncStatus(Provider.of<HomeworkProvider>(context, listen: false)
.fetch(from: DateTime.now().subtract(const Duration(days: 30)))),
syncStatus(Provider.of<MessageProvider>(context, listen: false).fetchAll()),
syncStatus(
Provider.of<MessageProvider>(context, listen: false).fetchAllRecipients()),
syncStatus(Provider.of<NoteProvider>(context, listen: false).fetch()),
syncStatus(Provider.of<EventProvider>(context, listen: false).fetch()),
syncStatus(Provider.of<AbsenceProvider>(context, listen: false).fetch()),
@@ -58,14 +63,17 @@ Future<void> syncAll(BuildContext context) {
// Sync student
syncStatus(() async {
if (user.user == null) return;
Map? studentJson = await Provider.of<KretaClient>(context, listen: false).getAPI(KretaAPI.student(user.instituteCode!));
Map? studentJson = await Provider.of<KretaClient>(context, listen: false)
.getAPI(KretaAPI.student(user.instituteCode!));
if (studentJson == null) return;
Student student = Student.fromJson(studentJson);
user.user?.name = student.name;
// Store user
await Provider.of<DatabaseProvider>(context, listen: false).store.storeUser(user.user!);
await Provider.of<DatabaseProvider>(context, listen: false)
.store
.storeUser(user.user!);
}()),
];

View File

@@ -1,3 +1,5 @@
// ignore_for_file: deprecated_member_use
import 'dart:io';
import 'dart:math';
@@ -14,7 +16,7 @@ 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:filcnaplo_premium/providers/goal_provider.dart';
import 'package:filcnaplo_premium/providers/share_provider.dart';
import 'package:filcnaplo_kreta_api/providers/share_provider.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
@@ -62,11 +64,10 @@ class App extends StatelessWidget {
final DatabaseProvider database;
const App(
{Key? key,
{super.key,
required this.database,
required this.settings,
required this.user})
: super(key: key);
required this.user});
@override
Widget build(BuildContext context) {
@@ -131,6 +132,7 @@ class App extends StatelessWidget {
create: (context) => HomeworkProvider(
context: context,
database: database,
user: user,
),
),
ChangeNotifierProvider<MessageProvider>(

View File

@@ -15,7 +15,8 @@ const settingsDB = DatabaseStruct("settings", {
"accent_color": int, "news": int, "seen_news": String,
"developer_mode": int,
"update_channel": int, "config": String, "custom_accent_color": int,
"custom_background_color": int, "custom_highlight_color": int, // general
"custom_background_color": int, "custom_highlight_color": int,
"custom_icon_color": int, "shadow_effect": int, // general
"grade_color1": int, "grade_color2": int, "grade_color3": int,
"grade_color4": int, "grade_color5": int, // grade colors
"vibration_strength": int, "ab_weeks": int, "swap_ab_weeks": int,
@@ -33,7 +34,7 @@ const settingsDB = DatabaseStruct("settings", {
"renamed_subjects_italics": int, "renamed_teachers_enabled": int,
"renamed_teachers_italics": int,
"live_activity_color": String,
"welcome_message": String,
"welcome_message": String, "app_icon": String,
});
// DON'T FORGET TO UPDATE DEFAULT VALUES IN `initDB` MIGRATION OR ELSE PARENTS WILL COMPLAIN ABOUT THEIR CHILDREN MISSING
// YOU'VE BEEN WARNED!!!
@@ -44,7 +45,7 @@ const usersDB = DatabaseStruct("users", {
});
const userDataDB = DatabaseStruct("user_data", {
"id": String, "grades": String, "timetable": String, "exams": String,
"homework": String, "messages": String, "notes": String,
"homework": String, "messages": String, "recipients": String, "notes": String,
"events": String, "absences": String, "group_averages": String,
// renamed subjects // non kreta data
"renamed_subjects": String,
@@ -100,7 +101,8 @@ Future<Database> initDB(DatabaseProvider database) async {
);
await migrateDB(db, struct: userDataDB, defaultValues: {
"grades": "[]", "timetable": "[]", "exams": "[]", "homework": "[]",
"messages": "[]", "notes": "[]", "events": "[]", "absences": "[]",
"messages": "[]", "recipients": "[]", "notes": "[]", "events": "[]",
"absences": "[]",
"group_averages": "[]",
// renamed subjects // non kreta data
"renamed_subjects": "{}",

View File

@@ -122,6 +122,19 @@ class UserDatabaseQuery {
return messages;
}
Future<List<SendRecipient>> getRecipients({required String userId}) async {
List<Map> userData =
await db.query("user_data", where: "id = ?", whereArgs: [userId]);
if (userData.isEmpty) return [];
String? recipientsJson = userData.elementAt(0)["recipients"] as String?;
if (recipientsJson == null) return [];
List<SendRecipient> recipients = (jsonDecode(recipientsJson) as List)
.map((e) =>
SendRecipient.fromJson(e, SendRecipientType.fromJson(e['tipus'])))
.toList();
return recipients;
}
Future<List<Note>> getNotes({required String userId}) async {
List<Map> userData =
await db.query("user_data", where: "id = ?", whereArgs: [userId]);

View File

@@ -86,6 +86,13 @@ class UserDatabaseStore {
where: "id = ?", whereArgs: [userId]);
}
Future<void> storeRecipients(List<SendRecipient> recipients,
{required String userId}) async {
String recipientsJson = jsonEncode(recipients.map((e) => e.json).toList());
await db.update("user_data", {"recipients": recipientsJson},
where: "id = ?", whereArgs: [userId]);
}
Future<void> storeNotes(List<Note> notes, {required String userId}) async {
String notesJson = jsonEncode(notes.map((e) => e.json).toList());
await db.update("user_data", {"notes": notesJson},

View File

@@ -9,16 +9,20 @@ import 'package:filcnaplo_kreta_api/client/client.dart';
import 'package:filcnaplo_kreta_api/models/attachment.dart';
import 'package:filcnaplo_kreta_api/models/homework.dart';
import 'package:flutter/widgets.dart';
import 'package:open_file/open_file.dart';
import 'package:open_filex/open_filex.dart';
import 'package:provider/provider.dart';
extension AttachmentHelper on Attachment {
Future<String> download(BuildContext context, {bool overwrite = false}) async {
Future<String> download(BuildContext context,
{bool overwrite = false}) async {
String downloads = await StorageHelper.downloadsPath();
if (!overwrite && await File("$downloads/$name").exists()) return "$downloads/$name";
if (!overwrite && await File("$downloads/$name").exists()) {
return "$downloads/$name";
}
Uint8List data = await Provider.of<KretaClient>(context, listen: false).getAPI(downloadUrl, rawResponse: true);
Uint8List data = await Provider.of<KretaClient>(context, listen: false)
.getAPI(downloadUrl, rawResponse: true);
if (!await StorageHelper.write("$downloads/$name", data)) return "";
return "$downloads/$name";
@@ -28,19 +32,24 @@ extension AttachmentHelper on Attachment {
String downloads = await StorageHelper.downloadsPath();
if (!await File("$downloads/$name").exists()) await download(context);
var result = await OpenFile.open("$downloads/$name");
var result = await OpenFilex.open("$downloads/$name");
return result.type == ResultType.done;
}
}
extension HomeworkAttachmentHelper on HomeworkAttachment {
Future<String> download(BuildContext context, {bool overwrite = false}) async {
Future<String> download(BuildContext context,
{bool overwrite = false}) async {
String downloads = await StorageHelper.downloadsPath();
if (!overwrite && await File("$downloads/$name").exists()) return "$downloads/$name";
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);
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";
@@ -50,7 +59,7 @@ extension HomeworkAttachmentHelper on HomeworkAttachment {
String downloads = await StorageHelper.downloadsPath();
if (!await File("$downloads/$name").exists()) await download(context);
var result = await OpenFile.open("$downloads/$name");
var result = await OpenFilex.open("$downloads/$name");
return result.type == ResultType.done;
}
}

View File

@@ -195,7 +195,7 @@ class NotificationsHelper {
if (userProvider.getUsers().length == 1) {
await flutterLocalNotificationsPlugin.show(
absence.id.hashCode,
"title_absence".i18n,
"title_absence".i18n, // https://discord.com/channels/1111649116020285532/1153273625206591528
"body_absence".i18n.fill(
[
DateFormat("yyyy-MM-dd").format(absence.date),
@@ -210,7 +210,7 @@ class NotificationsHelper {
} else {
await flutterLocalNotificationsPlugin.show(
absence.id.hashCode,
"title_absence".i18n,
"title_absence".i18n, // https://discord.com/channels/1111649116020285532/1153273625206591528
"body_absence_multiuser".i18n.fill(
[
userProvider.displayName!,

View File

@@ -22,7 +22,8 @@ class SubjectIconData {
});
}
SubjectIconVariants createIcon({required IconData material, required IconData cupertino}) {
SubjectIconVariants createIcon(
{required IconData material, required IconData cupertino}) {
return {
IconPack.material: material,
IconPack.cupertino: cupertino,
@@ -30,82 +31,224 @@ SubjectIconVariants createIcon({required IconData material, required IconData cu
}
class SubjectIcon {
static String resolveName({Subject? subject, String? subjectName}) => _resolve(subject: subject, subjectName: subjectName).name;
static IconData resolveVariant({Subject? subject, String? subjectName, required BuildContext context}) =>
_resolve(subject: subject, subjectName: subjectName).data[Provider.of<SettingsProvider>(context, listen: false).iconPack]!;
static String resolveName({GradeSubject? subject, String? subjectName}) =>
_resolve(subject: subject, subjectName: subjectName).name;
static IconData resolveVariant(
{GradeSubject? subject,
String? subjectName,
required BuildContext context}) =>
_resolve(subject: subject, subjectName: subjectName).data[
Provider.of<SettingsProvider>(context, listen: false).iconPack]!;
static SubjectIconData _resolve({Subject? subject, String? subjectName}) {
static SubjectIconData _resolve(
{GradeSubject? subject, String? subjectName}) {
assert(!(subject == null && subjectName == null));
String name = (subject?.name ?? subjectName ?? "").toLowerCase().specialChars().trim();
String category = subject?.category.description.toLowerCase().specialChars() ?? "";
String name = (subject?.name ?? subjectName ?? "")
.toLowerCase()
.specialChars()
.trim();
String category =
subject?.category.description.toLowerCase().specialChars() ?? "";
// todo: check for categories
if (RegExp("mate(k|matika)").hasMatch(name) || category == "matematika") {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.function, material: Icons.calculate_outlined), name: "function");
} else if (RegExp("magyar nyelv|nyelvtan").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.textformat_alt, material: Icons.spellcheck_outlined), name: "textformat.alt");
} else if (RegExp("irodalom").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.book, material: Icons.menu_book_outlined), name: "book");
} else if (RegExp("tor(i|tenelem)").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.compass, material: Icons.hourglass_empty_outlined), name: "safari");
} else if (RegExp("foldrajz").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.map, material: Icons.public_outlined), name: "map");
} else if (RegExp("rajz|muvtori|muveszet|vizualis").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.paintbrush, material: Icons.palette_outlined), name: "paintbrush");
} else if (RegExp("fizika").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.lightbulb, material: Icons.emoji_objects_outlined), name: "lightbulb");
} else if (RegExp("^enek|zene|szolfezs|zongora|korus").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.music_note, material: Icons.music_note_outlined), name: "music.note");
} else if (RegExp("^tes(i|tneveles)|sport").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.sportscourt, material: Icons.sports_soccer_outlined), name: "sportscourt");
} else if (RegExp("kemia").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.lab_flask, material: Icons.science_outlined), name: "testtube.2");
} else if (RegExp("biologia").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.paw, material: Icons.pets_outlined), name: "pawprint");
} else if (RegExp("kornyezet|termeszet ?(tudomany|ismeret)|hon( es nep)?ismeret").hasMatch(name)) {
return SubjectIconData(
data: createIcon(cupertino: CupertinoIcons.arrow_3_trianglepath, material: Icons.eco_outlined), name: "arrow.3.trianglepath");
data: createIcon(
cupertino: CupertinoIcons.function,
material: Icons.calculate_outlined),
name: "function");
} else if (RegExp("magyar nyelv|nyelvtan").hasMatch(name)) {
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.textformat_alt,
material: Icons.spellcheck_outlined),
name: "textformat.alt");
} else if (RegExp("irodalom").hasMatch(name)) {
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.book,
material: Icons.menu_book_outlined),
name: "book");
} else if (RegExp("tor(i|tenelem)").hasMatch(name)) {
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.compass,
material: Icons.hourglass_empty_outlined),
name: "safari");
} else if (RegExp("foldrajz").hasMatch(name)) {
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.map, material: Icons.public_outlined),
name: "map");
} else if (RegExp("rajz|muvtori|muveszet|vizualis").hasMatch(name)) {
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.paintbrush,
material: Icons.palette_outlined),
name: "paintbrush");
} else if (RegExp("fizika").hasMatch(name)) {
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.lightbulb,
material: Icons.emoji_objects_outlined),
name: "lightbulb");
} else if (RegExp("^enek|zene|szolfezs|zongora|korus").hasMatch(name)) {
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.music_note,
material: Icons.music_note_outlined),
name: "music.note");
} else if (RegExp("^tes(i|tneveles)|sport").hasMatch(name)) {
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.sportscourt,
material: Icons.sports_soccer_outlined),
name: "sportscourt");
} else if (RegExp("kemia").hasMatch(name)) {
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.lab_flask,
material: Icons.science_outlined),
name: "testtube.2");
} else if (RegExp("biologia").hasMatch(name)) {
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.paw, material: Icons.pets_outlined),
name: "pawprint");
} else if (RegExp(
"kornyezet|termeszet ?(tudomany|ismeret)|hon( es nep)?ismeret")
.hasMatch(name)) {
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.arrow_3_trianglepath,
material: Icons.eco_outlined),
name: "arrow.3.trianglepath");
} else if (RegExp("(hit|erkolcs)tan|vallas|etika").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.heart, material: Icons.favorite_border_outlined), name: "heart");
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.heart,
material: Icons.favorite_border_outlined),
name: "heart");
} else if (RegExp("penzugy").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.money_dollar, material: Icons.savings_outlined), name: "dollarsign");
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.money_dollar,
material: Icons.savings_outlined),
name: "dollarsign");
} else if (RegExp("informatika|szoftver|iroda|digitalis").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.device_laptop, material: Icons.computer_outlined), name: "laptopcomputer");
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.device_laptop,
material: Icons.computer_outlined),
name: "laptopcomputer");
} else if (RegExp("prog").hasMatch(name)) {
return SubjectIconData(
data: createIcon(cupertino: CupertinoIcons.chevron_left_slash_chevron_right, material: Icons.code_outlined),
data: createIcon(
cupertino: CupertinoIcons.chevron_left_slash_chevron_right,
material: Icons.code_outlined),
name: "chevron.left.forwardslash.chevron.right");
} else if (RegExp("halozat").hasMatch(name)) {
return SubjectIconData(
data: createIcon(cupertino: CupertinoIcons.antenna_radiowaves_left_right, material: Icons.wifi_tethering_outlined),
data: createIcon(
cupertino: CupertinoIcons.antenna_radiowaves_left_right,
material: Icons.wifi_tethering_outlined),
name: "antenna.radiowaves.left.and.right");
} else if (RegExp("szinhaz").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.hifispeaker, material: Icons.theater_comedy_outlined), name: "hifispeaker");
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.hifispeaker,
material: Icons.theater_comedy_outlined),
name: "hifispeaker");
} else if (RegExp("film|media").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.film, material: Icons.theaters_outlined), name: "film");
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.film,
material: Icons.theaters_outlined),
name: "film");
} else if (RegExp("elektro(tech)?nika").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.bolt, material: Icons.electrical_services_outlined), name: "bolt");
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.bolt,
material: Icons.electrical_services_outlined),
name: "bolt");
} else if (RegExp("gepesz|mernok|ipar").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.wrench, material: Icons.precision_manufacturing_outlined), name: "wrench");
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.wrench,
material: Icons.precision_manufacturing_outlined),
name: "wrench");
} else if (RegExp("technika").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.hammer, material: Icons.build_outlined), name: "hammer");
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.hammer, material: Icons.build_outlined),
name: "hammer");
} else if (RegExp("tanc").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.music_mic, material: Icons.speaker_outlined), name: "music.mic");
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.music_mic,
material: Icons.speaker_outlined),
name: "music.mic");
} else if (RegExp("filozofia").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.bubble_left, material: Icons.psychology_outlined), name: "bubble.left");
} else if (RegExp("osztaly(fonoki|kozosseg)").hasMatch(name) || name == "ofo") {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.group, material: Icons.groups_outlined), name: "person.3");
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.bubble_left,
material: Icons.psychology_outlined),
name: "bubble.left");
} else if (RegExp("osztaly(fonoki|kozosseg)").hasMatch(name) ||
name == "ofo") {
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.group, material: Icons.groups_outlined),
name: "person.3");
} else if (RegExp("gazdasag").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.chart_pie, material: Icons.account_balance_outlined), name: "chart.pie");
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.chart_pie,
material: Icons.account_balance_outlined),
name: "chart.pie");
} else if (RegExp("szorgalom").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.checkmark_seal, material: Icons.verified_outlined), name: "checkmark.seal");
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.checkmark_seal,
material: Icons.verified_outlined),
name: "checkmark.seal");
} else if (RegExp("magatartas").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.smiley, material: Icons.emoji_people_outlined), name: "face.smiling");
} else if (RegExp("angol|nemet|francia|olasz|orosz|spanyol|latin|kinai|nyelv").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.globe, material: Icons.translate_outlined), name: "globe");
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.smiley,
material: Icons.emoji_people_outlined),
name: "face.smiling");
} else if (RegExp(
"angol|nemet|francia|olasz|orosz|spanyol|latin|kinai|nyelv")
.hasMatch(name)) {
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.globe,
material: Icons.translate_outlined),
name: "globe");
} else if (RegExp("linux").hasMatch(name)) {
return SubjectIconData(data: createIcon(material: FilcIcons.linux, cupertino: FilcIcons.linux));
return SubjectIconData(
data: createIcon(
material: FilcIcons.linux, cupertino: FilcIcons.linux));
} else if (RegExp("adatbazis").hasMatch(name)) {
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.table_badge_more,
material: Icons.table_chart),
name: "table.badge.more");
} else if (RegExp("asztali alkalmazasok").hasMatch(name)) {
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.macwindow,
material: Icons.desktop_windows_outlined),
name: "macwindow");
} else if (RegExp("projekt").hasMatch(name)) {
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.person_3_fill,
material: Icons.groups_3),
name: "person.3.fill");
}
return SubjectIconData();
@@ -113,10 +256,13 @@ class SubjectIcon {
}
class ShortSubject {
static String resolve({Subject? subject, String? subjectName}) {
static String resolve({GradeSubject? subject, String? subjectName}) {
assert(!(subject == null && subjectName == null));
String name = (subject?.name ?? subjectName ?? "").toLowerCase().specialChars().trim();
String name = (subject?.name ?? subjectName ?? "")
.toLowerCase()
.specialChars()
.trim();
// String category = subject?.category.description.toLowerCase().specialChars() ?? "";
if (RegExp("magyar irodalom").hasMatch(name)) {
@@ -131,7 +277,9 @@ class ShortSubject {
return "Tesi";
} else if (RegExp("tortenelem").hasMatch(name)) {
return "Töri";
} else if (RegExp("(angol|nemet|francia|olasz|orosz|spanyol|latin|kinai) nyelv").hasMatch(name)) {
} else if (RegExp(
"(angol|nemet|francia|olasz|orosz|spanyol|latin|kinai) nyelv")
.hasMatch(name)) {
return (subject?.name ?? subjectName ?? "?").replaceAll(" nyelv", "");
} else if (RegExp("informatika").hasMatch(name)) {
return "Infó";

View File

@@ -5,7 +5,7 @@ import 'dart:typed_data';
import 'package:filcnaplo/api/client.dart';
import 'package:filcnaplo/helpers/storage_helper.dart';
import 'package:filcnaplo/models/release.dart';
import 'package:open_file/open_file.dart';
import 'package:open_filex/open_filex.dart';
import 'package:permission_handler/permission_handler.dart';
enum UpdateState { none, preparing, downloading, installing }
@@ -37,7 +37,7 @@ extension UpdateHelper on Release {
(await Permission.manageExternalStorage.request().isGranted &&
await Permission.requestInstallPackages.request().isGranted);
if (installPerms) {
var result = await OpenFile.open(apk.path);
var result = await OpenFilex.open(apk.path);
if (result.type != ResultType.done) {
// ignore: avoid_print

View File

@@ -17,6 +17,7 @@ import 'package:flutter_local_notifications/flutter_local_notifications.dart';
void main() async {
// Initalize
WidgetsBinding binding = WidgetsFlutterBinding.ensureInitialized();
// ignore: deprecated_member_use
binding.renderView.automaticSystemUiAdjustment = false;
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
// Startup
@@ -63,7 +64,7 @@ class Startup {
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()!
.requestPermission();
.requestNotificationsPermission();
} else if (Platform.isIOS) {
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<

View File

@@ -67,6 +67,8 @@ class SettingsProvider extends ChangeNotifier {
Color _customAccentColor;
Color _customBackgroundColor;
Color _customHighlightColor;
Color _customIconColor;
bool _shadowEffect;
List<String> _premiumScopes;
String _premiumAccessToken;
String _premiumLogin;
@@ -77,6 +79,7 @@ class SettingsProvider extends ChangeNotifier {
bool _renamedTeachersItalics;
Color _liveActivityColor;
String _welcomeMessage;
String _appIcon;
SettingsProvider({
DatabaseProvider? database,
@@ -112,6 +115,8 @@ class SettingsProvider extends ChangeNotifier {
required Color customAccentColor,
required Color customBackgroundColor,
required Color customHighlightColor,
required Color customIconColor,
required bool shadowEffect,
required List<String> premiumScopes,
required String premiumAccessToken,
required String premiumLogin,
@@ -122,6 +127,7 @@ class SettingsProvider extends ChangeNotifier {
required bool renameTeachersItalics,
required Color liveActivityColor,
required String welcomeMessage,
required String appIcon,
}) : _database = database,
_language = language,
_startPage = startPage,
@@ -155,6 +161,8 @@ class SettingsProvider extends ChangeNotifier {
_customAccentColor = customAccentColor,
_customBackgroundColor = customBackgroundColor,
_customHighlightColor = customHighlightColor,
_customIconColor = customIconColor,
_shadowEffect = shadowEffect,
_premiumScopes = premiumScopes,
_premiumAccessToken = premiumAccessToken,
_premiumLogin = premiumLogin,
@@ -164,7 +172,8 @@ class SettingsProvider extends ChangeNotifier {
_renamedTeachersEnabled = renameTeachersEnabled,
_renamedTeachersItalics = renameTeachersItalics,
_liveActivityColor = liveActivityColor,
_welcomeMessage = welcomeMessage;
_welcomeMessage = welcomeMessage,
_appIcon = appIcon;
factory SettingsProvider.fromMap(Map map,
{required DatabaseProvider database}) {
@@ -217,6 +226,8 @@ class SettingsProvider extends ChangeNotifier {
customAccentColor: Color(map["custom_accent_color"]),
customBackgroundColor: Color(map["custom_background_color"]),
customHighlightColor: Color(map["custom_highlight_color"]),
customIconColor: Color(map["custom_icon_color"]),
shadowEffect: map["shadow_effect"] == 1,
premiumScopes: jsonDecode(map["premium_scopes"]).cast<String>(),
premiumAccessToken: map["premium_token"],
premiumLogin: map["premium_login"],
@@ -227,6 +238,7 @@ class SettingsProvider extends ChangeNotifier {
renameTeachersItalics: map["renamed_teachers_italics"] == 1,
liveActivityColor: Color(map["live_activity_color"]),
welcomeMessage: map["welcome_message"],
appIcon: map["app_icon"],
);
}
@@ -267,6 +279,8 @@ class SettingsProvider extends ChangeNotifier {
"custom_accent_color": _customAccentColor.value,
"custom_background_color": _customBackgroundColor.value,
"custom_highlight_color": _customHighlightColor.value,
"custom_icon_color": _customIconColor.value,
"shadow_effect": _shadowEffect ? 1 : 0,
"premium_scopes": jsonEncode(_premiumScopes),
"premium_token": _premiumAccessToken,
"premium_login": _premiumLogin,
@@ -277,6 +291,7 @@ class SettingsProvider extends ChangeNotifier {
"renamed_teachers_italics": _renamedTeachersItalics ? 1 : 0,
"live_activity_color": _liveActivityColor.value,
"welcome_message": _welcomeMessage,
"app_icon": _appIcon,
};
}
@@ -321,6 +336,8 @@ class SettingsProvider extends ChangeNotifier {
customAccentColor: const Color(0xff3D7BF4),
customBackgroundColor: const Color(0xff000000),
customHighlightColor: const Color(0xff222222),
customIconColor: const Color(0x00000000),
shadowEffect: true,
premiumScopes: [PremiumScopes.all],
premiumAccessToken: "igen",
premiumLogin: "igen",
@@ -331,6 +348,7 @@ class SettingsProvider extends ChangeNotifier {
renameTeachersItalics: false,
liveActivityColor: const Color(0xFF676767),
welcomeMessage: '',
appIcon: 'refilc_default',
);
}
@@ -370,6 +388,8 @@ class SettingsProvider extends ChangeNotifier {
: _customAccentColor;
Color? get customBackgroundColor => _customBackgroundColor;
Color? get customHighlightColor => _customHighlightColor;
Color? get customIconColor => _customIconColor;
bool get shadowEffect => _shadowEffect;
List<String> get premiumScopes => _premiumScopes;
String get premiumAccessToken => _premiumAccessToken;
String get premiumLogin => _premiumLogin;
@@ -380,6 +400,7 @@ class SettingsProvider extends ChangeNotifier {
bool get renamedTeachersItalics => _renamedTeachersItalics;
Color get liveActivityColor => _liveActivityColor;
String get welcomeMessage => _welcomeMessage;
String get appIcon => _appIcon;
Future<void> update({
bool store = true,
@@ -415,6 +436,8 @@ class SettingsProvider extends ChangeNotifier {
Color? customAccentColor,
Color? customBackgroundColor,
Color? customHighlightColor,
Color? customIconColor,
bool? shadowEffect,
List<String>? premiumScopes,
String? premiumAccessToken,
String? premiumLogin,
@@ -425,6 +448,7 @@ class SettingsProvider extends ChangeNotifier {
bool? renamedTeachersItalics,
Color? liveActivityColor,
String? welcomeMessage,
String? appIcon,
}) async {
if (language != null && language != _language) _language = language;
if (startPage != null && startPage != _startPage) _startPage = startPage;
@@ -511,6 +535,12 @@ class SettingsProvider extends ChangeNotifier {
customHighlightColor != _customHighlightColor) {
_customHighlightColor = customHighlightColor;
}
if (customIconColor != null && customIconColor != _customIconColor) {
_customIconColor = customIconColor;
}
if (shadowEffect != null && shadowEffect != _shadowEffect) {
_shadowEffect = shadowEffect;
}
if (premiumScopes != null && premiumScopes != _premiumScopes) {
_premiumScopes = premiumScopes;
}
@@ -546,6 +576,10 @@ class SettingsProvider extends ChangeNotifier {
if (welcomeMessage != null && welcomeMessage != _welcomeMessage) {
_welcomeMessage = welcomeMessage;
}
if (appIcon != null && appIcon != _appIcon) {
_appIcon = appIcon;
}
// store or not
if (store) await _database?.store.storeSettings(this);
notifyListeners();
}

View File

@@ -8,6 +8,8 @@ class SharedTheme {
Color backgroundColor;
Color panelsColor;
Color accentColor;
Color iconColor;
bool shadowEffect;
SharedGradeColors gradeColors;
SharedTheme({
@@ -18,6 +20,8 @@ class SharedTheme {
required this.backgroundColor,
required this.panelsColor,
required this.accentColor,
required this.iconColor,
required this.shadowEffect,
required this.gradeColors,
});
@@ -30,6 +34,8 @@ class SharedTheme {
backgroundColor: Color(json['background_color']),
panelsColor: Color(json['panels_color']),
accentColor: Color(json['accent_color']),
iconColor: Color(json['icon_color']),
shadowEffect: json['shadow_effect'] ?? true,
gradeColors: gradeColors,
);
}

View File

@@ -5,17 +5,21 @@ enum SubjectLessonCountUpdateState { ready, updating }
class SubjectLessonCount {
DateTime lastUpdated;
Map<Subject, int> subjects;
Map<GradeSubject, int> subjects;
SubjectLessonCountUpdateState state;
SubjectLessonCount({required this.lastUpdated, required this.subjects, this.state = SubjectLessonCountUpdateState.ready});
SubjectLessonCount(
{required this.lastUpdated,
required this.subjects,
this.state = SubjectLessonCountUpdateState.ready});
factory SubjectLessonCount.fromMap(Map json) {
return SubjectLessonCount(
lastUpdated: DateTime.fromMillisecondsSinceEpoch(json["last_updated"] ?? 0),
lastUpdated:
DateTime.fromMillisecondsSinceEpoch(json["last_updated"] ?? 0),
subjects: ((json["subjects"] as Map?) ?? {}).map(
(key, value) => MapEntry(
Subject(id: key, name: "", category: Category.fromJson({})),
GradeSubject(id: key, name: "", category: Category.fromJson({})),
value,
),
),

View File

@@ -35,6 +35,7 @@ import 'package:provider/provider.dart';
const List<FilterType> homeFilters = [
FilterType.all,
FilterType.grades,
FilterType.exams,
FilterType.messages,
FilterType.absences
];
@@ -214,19 +215,21 @@ Widget filterItemBuilder(
child: DecoratedBox(
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
offset: const Offset(0, 21),
blurRadius: 23.0,
color: Theme.of(context).shadowColor.withOpacity(
Theme.of(context).shadowColor.opacity *
CurvedAnimation(
parent: CurvedAnimation(
parent: animation,
curve: Curves.easeInOutCubic),
curve: const Interval(2 / 3, 1.0),
).value,
),
),
if (Provider.of<SettingsProvider>(context, listen: false)
.shadowEffect)
BoxShadow(
offset: const Offset(0, 21),
blurRadius: 23.0,
color: Theme.of(context).shadowColor.withOpacity(
Theme.of(context).shadowColor.opacity *
CurvedAnimation(
parent: CurvedAnimation(
parent: animation,
curve: Curves.easeInOutCubic),
curve: const Interval(2 / 3, 1.0),
).value,
),
),
],
),
child: child,

View File

@@ -87,13 +87,13 @@ Widget _defaultItemBuilder(Color color, bool isCurrentColor, void Function() cha
// The blocky color picker you can alter the layout and shape.
class BlockPicker extends StatefulWidget {
BlockPicker({
Key? key,
super.key,
required this.pickerColor,
required this.onColorChanged,
this.useInShowDialog = true,
this.layoutBuilder = _defaultLayoutBuilder,
this.itemBuilder = _defaultItemBuilder,
}) : super(key: key);
});
final Color? pickerColor;
final ValueChanged<Color> onColorChanged;

View File

@@ -7,16 +7,18 @@
///
/// You can create your own layout by importing `picker.dart`.
// ignore_for_file: use_build_context_synchronously
library hsv_picker;
import 'package:filcnaplo/models/shared_theme.dart';
import 'package:filcnaplo_mobile_ui/common/custom_snack_bar.dart';
import 'package:filcnaplo_premium/providers/share_provider.dart';
import 'package:filcnaplo_premium/ui/mobile/flutter_colorpicker/block_picker.dart';
import 'package:filcnaplo_premium/ui/mobile/flutter_colorpicker/palette.dart';
import 'package:filcnaplo_premium/ui/mobile/flutter_colorpicker/utils.dart';
import 'package:filcnaplo_premium/ui/mobile/settings/theme.dart';
import 'package:filcnaplo_premium/ui/mobile/settings/theme.i18n.dart';
import 'package:filcnaplo_kreta_api/providers/share_provider.dart';
import 'package:filcnaplo/ui/flutter_colorpicker/block_picker.dart';
import 'package:filcnaplo/ui/flutter_colorpicker/palette.dart';
import 'package:filcnaplo/ui/flutter_colorpicker/utils.dart';
import 'package:filcnaplo_mobile_ui/screens/settings/theme_screen.dart';
import 'package:filcnaplo_mobile_ui/screens/settings/theme_screen.i18n.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:filcnaplo/theme/colors/colors.dart';
@@ -24,7 +26,7 @@ import 'package:provider/provider.dart';
class FilcColorPicker extends StatefulWidget {
const FilcColorPicker({
Key? key,
super.key,
required this.colorMode,
required this.pickerColor,
required this.onColorChanged,
@@ -53,7 +55,7 @@ class FilcColorPicker extends StatefulWidget {
this.colorHistory,
this.onHistoryChanged,
required this.onThemeIdProvided,
}) : super(key: key);
});
final CustomColorMode colorMode;
final Color pickerColor;
@@ -78,10 +80,10 @@ class FilcColorPicker extends StatefulWidget {
final void Function(SharedTheme theme) onThemeIdProvided;
@override
_FilcColorPickerState createState() => _FilcColorPickerState();
FilcColorPickerState createState() => FilcColorPickerState();
}
class _FilcColorPickerState extends State<FilcColorPicker> {
class FilcColorPickerState extends State<FilcColorPicker> {
final idController = TextEditingController();
late final ShareProvider shareProvider;
@@ -262,6 +264,7 @@ class _FilcColorPickerState extends State<FilcColorPicker> {
if (theme != null) {
widget.onThemeIdProvided(theme);
idController.clear();
} else {
ScaffoldMessenger.of(context).showSnackBar(
CustomSnackBar(

View File

@@ -3,6 +3,7 @@
// FROM: https://pub.dev/packages/flutter_colorpicker
// FROM: https://pub.dev/packages/flutter_colorpicker
// ignore: dangling_library_doc_comments
/// The components of HSV Color Picker
///
/// Try to create a Color Picker with other layout on your own :)
@@ -317,11 +318,11 @@ class ColorPickerInput extends StatefulWidget {
const ColorPickerInput(
this.color,
this.onColorChanged, {
Key? key,
super.key,
this.enableAlpha = true,
this.embeddedText = false,
this.disable = false,
}) : super(key: key);
});
final Color color;
final ValueChanged<Color> onColorChanged;
@@ -330,10 +331,10 @@ class ColorPickerInput extends StatefulWidget {
final bool disable;
@override
_ColorPickerInputState createState() => _ColorPickerInputState();
ColorPickerInputState createState() => ColorPickerInputState();
}
class _ColorPickerInputState extends State<ColorPickerInput> {
class ColorPickerInputState extends State<ColorPickerInput> {
TextEditingController textEditingController = TextEditingController();
int inputColor = 0;
@@ -346,11 +347,7 @@ class _ColorPickerInputState extends State<ColorPickerInput> {
@override
Widget build(BuildContext context) {
if (inputColor != widget.color.value) {
textEditingController.text = '#' +
widget.color.red.toRadixString(16).toUpperCase().padLeft(2, '0') +
widget.color.green.toRadixString(16).toUpperCase().padLeft(2, '0') +
widget.color.blue.toRadixString(16).toUpperCase().padLeft(2, '0') +
(widget.enableAlpha ? widget.color.alpha.toRadixString(16).toUpperCase().padLeft(2, '0') : '');
textEditingController.text = '#${widget.color.red.toRadixString(16).toUpperCase().padLeft(2, '0')}${widget.color.green.toRadixString(16).toUpperCase().padLeft(2, '0')}${widget.color.blue.toRadixString(16).toUpperCase().padLeft(2, '0')}${widget.enableAlpha ? widget.color.alpha.toRadixString(16).toUpperCase().padLeft(2, '0') : ''}';
}
return Padding(
padding: const EdgeInsets.only(top: 6.0, left: 12.0, right: 12.0),
@@ -516,10 +513,10 @@ class ColorPickerSlider extends StatelessWidget {
this.onColorChanged,
this.onColorChangeEnd,
this.onProblem, {
Key? key,
super.key,
this.displayThumbColor = false,
this.fullThumbColor = false,
}) : super(key: key);
});
final TrackType trackType;
final HSVColor hsvColor;
@@ -657,13 +654,13 @@ class ColorPickerSlider extends StatelessWidget {
class ColorIndicator extends StatelessWidget {
const ColorIndicator(
this.hsvColor, {
Key? key,
super.key,
this.currentHsvColor,
this.icon,
this.width = 50.0,
this.height = 50.0,
this.adaptive = false,
}) : super(key: key);
});
final HSVColor hsvColor;
final HSVColor? currentHsvColor;
@@ -711,8 +708,8 @@ class ColorPickerArea extends StatelessWidget {
this.onColorChanged,
this.onChangeEnd,
this.paletteType, {
Key? key,
}) : super(key: key);
super.key,
});
final HSVColor hsvColor;
final ValueChanged<HSVColor> onColorChanged;

View File

@@ -3,6 +3,7 @@
// FROM: https://pub.dev/packages/flutter_colorpicker
// FROM: https://pub.dev/packages/flutter_colorpicker
// ignore: dangling_library_doc_comments
/// Common function lib
import 'dart:math';

View File

@@ -10,14 +10,20 @@ import 'package:flutter_feather_icons/flutter_feather_icons.dart';
import 'package:provider/provider.dart';
class GradeTile extends StatelessWidget {
const GradeTile(this.grade,
{Key? key, this.onTap, this.padding, this.censored = false})
: super(key: key);
const GradeTile(
this.grade, {
super.key,
this.onTap,
this.padding,
this.censored = false,
this.viewOverride = false,
});
final Grade grade;
final void Function()? onTap;
final EdgeInsetsGeometry? padding;
final bool censored;
final bool viewOverride;
@override
Widget build(BuildContext context) {
@@ -26,7 +32,8 @@ class GradeTile extends StatelessWidget {
bool isTitleItalic = false;
bool isSubtitleItalic = false;
EdgeInsets leadingPadding = EdgeInsets.zero;
bool isSubjectView = SubjectGradesContainer.of(context) != null;
bool isSubjectView =
SubjectGradesContainer.of(context) != null || viewOverride;
String subjectName =
grade.subject.renamedTo ?? grade.subject.name.capital();
String modeDescription = grade.mode.description.capital();
@@ -34,8 +41,7 @@ class GradeTile extends StatelessWidget {
GradeCalculatorProvider calculatorProvider =
Provider.of<GradeCalculatorProvider>(context, listen: false);
SettingsProvider settingsProvider =
Provider.of<SettingsProvider>(context);
SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
// Test order:
// description
// mode
@@ -50,7 +56,8 @@ class GradeTile extends StatelessWidget {
}
} else {
title = subjectName;
isTitleItalic = grade.subject.isRenamed && settingsProvider.renamedSubjectsItalics;
isTitleItalic =
grade.subject.isRenamed && settingsProvider.renamedSubjectsItalics;
}
// Test order:
@@ -62,7 +69,9 @@ class GradeTile extends StatelessWidget {
? modeDescription
: ""
: subjectName;
isSubtitleItalic = isSubjectView ? false : grade.subject.isRenamed && settingsProvider.renamedSubjectsItalics;
isSubtitleItalic = isSubjectView
? false
: grade.subject.isRenamed && settingsProvider.renamedSubjectsItalics;
} else {
subtitle = grade.value.valueName.split("(")[0];
}
@@ -127,9 +136,7 @@ class GradeTile extends StatelessWidget {
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontWeight: FontWeight.w600,
fontStyle: isTitleItalic
? FontStyle.italic
: null),
fontStyle: isTitleItalic ? FontStyle.italic : null),
),
subtitle: subtitle != ""
? censored
@@ -149,7 +156,10 @@ class GradeTile extends StatelessWidget {
subtitle,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontWeight: FontWeight.w500, fontStyle: isSubtitleItalic ? FontStyle.italic : null),
style: TextStyle(
fontWeight: FontWeight.w500,
fontStyle:
isSubtitleItalic ? FontStyle.italic : null),
)
: null,
trailing: isSubjectView
@@ -184,7 +194,7 @@ class GradeTile extends StatelessWidget {
class GradeValueWidget extends StatelessWidget {
const GradeValueWidget(
this.value, {
Key? key,
super.key,
this.size = 38.0,
this.fill = false,
this.contrast = false,
@@ -193,7 +203,7 @@ class GradeValueWidget extends StatelessWidget {
this.complemented = false,
this.nocolor = false,
this.color,
}) : super(key: key);
});
final GradeValue value;
final double size;
@@ -210,8 +220,8 @@ class GradeValueWidget extends StatelessWidget {
GradeValue value = this.value;
bool isSubjectView = SubjectGradesContainer.of(context) != null;
Color color =
this.color ?? gradeColor(context: context, value: value.value, nocolor: nocolor);
Color color = this.color ??
gradeColor(context: context, value: value.value, nocolor: nocolor);
Widget valueText;
final percentage = value.percentage;
@@ -283,7 +293,9 @@ class GradeValueWidget extends StatelessWidget {
color: color.withOpacity(contrast ? 1.0 : .25),
shape: BoxShape.circle,
boxShadow: [
if (shadow)
if (shadow &&
Provider.of<SettingsProvider>(context, listen: false)
.shadowEffect)
BoxShadow(
color: color,
blurRadius: 62.0,

View File

@@ -16,8 +16,7 @@ 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, {super.key, this.onTap, this.swapDesc = false});
final Lesson lesson;
final bool swapDesc;
@@ -287,8 +286,7 @@ enum LessonSubtileType { homework, exam, absence }
class LessonSubtile extends StatelessWidget {
const LessonSubtile(
{Key? key, this.onPressed, required this.title, required this.type})
: super(key: key);
{super.key, this.onPressed, required this.title, required this.type});
final Function()? onPressed;
final String title;

View File

@@ -11,12 +11,12 @@ import 'package:provider/provider.dart';
class MessageTile extends StatelessWidget {
const MessageTile(
this.message, {
Key? key,
super.key,
this.messages,
this.padding,
this.onTap,
this.censored = false,
}) : super(key: key);
});
final Message message;
final List<Message>? messages;

View File

@@ -1 +0,0 @@
flutter/ephemeral

View File

@@ -1,116 +0,0 @@
cmake_minimum_required(VERSION 3.10)
project(runner LANGUAGES CXX)
set(BINARY_NAME "filcnaplo")
set(APPLICATION_ID "hu.filc.filcnaplo")
cmake_policy(SET CMP0063 NEW)
set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")
# Root filesystem for cross-building.
if(FLUTTER_TARGET_PLATFORM_SYSROOT)
set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT})
set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
endif()
# Configure build options.
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE "Debug" CACHE
STRING "Flutter build mode" FORCE)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
"Debug" "Profile" "Release")
endif()
# Compilation settings that should be applied to most targets.
function(APPLY_STANDARD_SETTINGS TARGET)
target_compile_features(${TARGET} PUBLIC cxx_std_14)
target_compile_options(${TARGET} PRIVATE -Wall -Werror)
target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>")
target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>")
endfunction()
set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
# Flutter library and tool build rules.
add_subdirectory(${FLUTTER_MANAGED_DIR})
# System-level dependencies.
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")
# Application build
add_executable(${BINARY_NAME}
"main.cc"
"my_application.cc"
"${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
)
apply_standard_settings(${BINARY_NAME})
target_link_libraries(${BINARY_NAME} PRIVATE flutter)
target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
add_dependencies(${BINARY_NAME} flutter_assemble)
# Only the install-generated bundle's copy of the executable will launch
# correctly, since the resources must in the right relative locations. To avoid
# people trying to run the unbundled copy, put it in a subdirectory instead of
# the default top-level location.
set_target_properties(${BINARY_NAME}
PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run"
)
# Generated plugin build rules, which manage building the plugins and adding
# them to the application.
include(flutter/generated_plugins.cmake)
# === Installation ===
# By default, "installing" just makes a relocatable bundle in the build
# directory.
set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle")
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
endif()
# Start with a clean build bundle directory every time.
install(CODE "
file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\")
" COMPONENT Runtime)
set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
COMPONENT Runtime)
install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
COMPONENT Runtime)
install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
if(PLUGIN_BUNDLED_LIBRARIES)
install(FILES "${PLUGIN_BUNDLED_LIBRARIES}"
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
endif()
# Fully re-copy the assets directory on each build to avoid having stale files
# from a previous install.
set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
install(CODE "
file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
" COMPONENT Runtime)
install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
# Install the AOT library on non-Debug builds only.
if(NOT CMAKE_BUILD_TYPE MATCHES "Debug")
install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
endif()

View File

@@ -1,87 +0,0 @@
cmake_minimum_required(VERSION 3.10)
set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
# Configuration provided via flutter tool.
include(${EPHEMERAL_DIR}/generated_config.cmake)
# TODO: Move the rest of this into files in ephemeral. See
# https://github.com/flutter/flutter/issues/57146.
# Serves the same purpose as list(TRANSFORM ... PREPEND ...),
# which isn't available in 3.10.
function(list_prepend LIST_NAME PREFIX)
set(NEW_LIST "")
foreach(element ${${LIST_NAME}})
list(APPEND NEW_LIST "${PREFIX}${element}")
endforeach(element)
set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE)
endfunction()
# === Flutter Library ===
# System-level dependencies.
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)
set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so")
# Published to parent scope for install step.
set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE)
list(APPEND FLUTTER_LIBRARY_HEADERS
"fl_basic_message_channel.h"
"fl_binary_codec.h"
"fl_binary_messenger.h"
"fl_dart_project.h"
"fl_engine.h"
"fl_json_message_codec.h"
"fl_json_method_codec.h"
"fl_message_codec.h"
"fl_method_call.h"
"fl_method_channel.h"
"fl_method_codec.h"
"fl_method_response.h"
"fl_plugin_registrar.h"
"fl_plugin_registry.h"
"fl_standard_message_codec.h"
"fl_standard_method_codec.h"
"fl_string_codec.h"
"fl_value.h"
"fl_view.h"
"flutter_linux.h"
)
list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/")
add_library(flutter INTERFACE)
target_include_directories(flutter INTERFACE
"${EPHEMERAL_DIR}"
)
target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}")
target_link_libraries(flutter INTERFACE
PkgConfig::GTK
PkgConfig::GLIB
PkgConfig::GIO
)
add_dependencies(flutter flutter_assemble)
# === Flutter tool backend ===
# _phony_ is a non-existent file to force this command to run every time,
# since currently there's no way to get a full input/output list from the
# flutter tool.
add_custom_command(
OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
${CMAKE_CURRENT_BINARY_DIR}/_phony_
COMMAND ${CMAKE_COMMAND} -E env
${FLUTTER_TOOL_ENVIRONMENT}
"${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh"
${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE}
VERBATIM
)
add_custom_target(flutter_assemble DEPENDS
"${FLUTTER_LIBRARY}"
${FLUTTER_LIBRARY_HEADERS}
)

View File

@@ -1,7 +0,0 @@
# Flutter-related
**/Flutter/ephemeral/
**/Pods/
# Xcode-related
**/dgph
**/xcuserdata/

View File

@@ -1,2 +0,0 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "ephemeral/Flutter-Generated.xcconfig"

View File

@@ -1,2 +0,0 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "ephemeral/Flutter-Generated.xcconfig"

View File

@@ -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.3.0+226
version: 4.5.1+238
environment:
sdk: ">=2.17.0 <3.0.0"
@@ -25,21 +25,22 @@ dependencies:
flutter_localizations:
sdk: flutter
i18n_extension: ^9.0.0
i18n_extension: ^10.0.1
sqflite: ^2.2.0+2
intl: ^0.18.0
provider: ^5.0.0
http: ^0.13.3
uuid: ^3.0.4
uuid: ^4.2.1
html: ^0.15.0
open_file:
git:
url: https://github.com/crazecoder/open_file
ref: master
open_filex: ^4.3.4
# open_file:
# git:
# url: https://github.com/crazecoder/open_file
# ref: master
path_provider: ^2.0.2
permission_handler: ^10.2.0
permission_handler: ^11.0.1
share_plus: ^7.0.2
connectivity_plus: ^4.0.1
connectivity_plus: ^5.0.2
flutter_displaymode: ^0.6.0
quick_actions: ^1.0.1
animated_list_plus: ^0.5.0
@@ -53,9 +54,9 @@ dependencies:
lottie: ^1.4.3
rive: ^0.9.1
animated_background: ^2.0.0
dropdown_button2: ^1.8.9
dropdown_button2: ^1.9.4
home_widget: ^0.1.6
flutter_expandable_fab: ^1.8.1
flutter_expandable_fab: ^2.0.0
uni_links: ^0.5.1
url_launcher: ^6.1.6
workmanager: ^0.5.1
@@ -63,7 +64,7 @@ dependencies:
image_picker: ^0.8.6
animations: ^2.0.1
background_fetch: ^1.1.5
flutter_local_notifications: ^14.1.0
flutter_local_notifications: ^16.2.0
package_info_plus: ^4.0.2
screenshot: ^2.1.0
flutter_staggered_grid_view: ^0.7.0
@@ -73,7 +74,7 @@ dependencies:
url: https://github.com/kimaah/image_crop.git
dev_dependencies:
flutter_lints: ^2.0.1
flutter_lints: ^3.0.1
flutter_launcher_icons: "^0.13.1"
flutter_native_splash: "^2.3.0"
sqflite_common_ffi: ^2.0.0+3
@@ -87,6 +88,7 @@ flutter:
- assets/animations/
- assets/images/
- assets/images/subject_covers/
- assets/launch_icons/
fonts:
- family: FilcIcons

View File

@@ -1,17 +0,0 @@
flutter/ephemeral/
# Visual Studio user-specific files.
*.suo
*.user
*.userosscache
*.sln.docstates
# Visual Studio build-related files.
x64/
x86/
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/

View File

@@ -31,6 +31,11 @@ bool FlutterWindow::OnCreate() {
this->Show();
});
// Flutter can complete the first frame before the "show window" callback is
// registered. The following call ensures a frame is pending to ensure the
// window is shown. It is a no-op if the first frame hasn't completed yet.
flutter_controller_->ForceRedraw();
return true;
}

View File

@@ -1,47 +0,0 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
/build/
# Web related
lib/generated_plugin_registrant.dart
# Symbolication related
app.*.symbols
# Obfuscation related
app.*.map.json
# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release
pubspec.lock

View File

@@ -61,19 +61,26 @@ class FilterBar extends StatelessWidget implements PreferredSizeWidget {
// avoid fading over selected tab
return ShaderMask(
shaderCallback: (Rect bounds) {
final Color bg = Theme.of(context).scaffoldBackgroundColor;
final Color bg =
Theme.of(context).scaffoldBackgroundColor;
final double index = controller.animation!.value;
return LinearGradient(begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [
index < 0.2 ? Colors.transparent : bg,
Colors.transparent,
Colors.transparent,
index > controller.length - 1.2 ? Colors.transparent : bg
], stops: const [
0,
0.1,
0.9,
1
]).createShader(bounds);
return LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
index < 0.2 ? Colors.transparent : bg,
Colors.transparent,
Colors.transparent,
index > controller.length - 1.2
? Colors.transparent
: bg
],
stops: const [
0,
0.1,
0.9,
1
]).createShader(bounds);
},
blendMode: BlendMode.dstOut,
child: child);

View File

@@ -31,7 +31,7 @@ import 'absences_page.i18n.dart';
enum AbsenceFilter { absences, delays, misses }
class SubjectAbsence {
Subject subject;
GradeSubject subject;
List<Absence> absences;
double percentage;
@@ -56,7 +56,7 @@ class _AbsencesPageState extends State<AbsencesPage>
late String firstName;
late TabController _tabController;
late List<SubjectAbsence> absences = [];
final Map<Subject, Lesson> _lessonCount = {};
final Map<GradeSubject, Lesson> _lessonCount = {};
@override
void initState() {
@@ -87,7 +87,7 @@ class _AbsencesPageState extends State<AbsencesPage>
}
void buildSubjectAbsences() {
Map<Subject, SubjectAbsence> _absences = {};
Map<GradeSubject, SubjectAbsence> _absences = {};
for (final absence in absenceProvider.absences) {
if (absence.delay != 0) continue;

View File

@@ -1,6 +1,7 @@
import 'dart:math';
import 'package:animations/animations.dart';
import 'package:filcnaplo/models/settings.dart';
import 'package:filcnaplo/utils/format.dart';
import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
import 'package:filcnaplo/helpers/average_helper.dart';
@@ -32,7 +33,7 @@ class GradeSubjectView extends StatefulWidget {
const GradeSubjectView(this.subject, {Key? key, this.groupAverage = 0.0})
: super(key: key);
final Subject subject;
final GradeSubject subject;
final double groupAverage;
void push(BuildContext context, {bool root = false}) {
@@ -56,13 +57,14 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
// Providers
late GradeProvider gradeProvider;
late GradeCalculatorProvider calculatorProvider;
late SettingsProvider settingsProvider;
late double average;
late Widget gradeGraph;
bool gradeCalcMode = false;
List<Grade> getSubjectGrades(Subject subject) => !gradeCalcMode
List<Grade> getSubjectGrades(GradeSubject subject) => !gradeCalcMode
? gradeProvider.grades.where((e) => e.subject == subject).toList()
: calculatorProvider.grades.where((e) => e.subject == subject).toList();
@@ -142,6 +144,7 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
Widget build(BuildContext context) {
gradeProvider = Provider.of<GradeProvider>(context);
calculatorProvider = Provider.of<GradeCalculatorProvider>(context);
settingsProvider = Provider.of<SettingsProvider>(context);
List<Grade> subjectGrades = getSubjectGrades(widget.subject).toList();
average = AverageHelper.averageEvals(subjectGrades);
@@ -244,7 +247,8 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
subject: widget.subject, context: context),
scrollController: _scrollController,
title: widget.subject.renamedTo ?? widget.subject.name.capital(),
italic: widget.subject.isRenamed,
italic: widget.subject.isRenamed &&
settingsProvider.renamedSubjectsItalics,
child: SubjectGradesContainer(
child: CupertinoScrollbar(
child: ListView.builder(

View File

@@ -21,7 +21,7 @@ import 'package:filcnaplo_desktop_ui/pages/grades/grade_subject_view.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:filcnaplo/helpers/average_helper.dart';
import 'package:filcnaplo_premium/ui/mobile/grades/average_selector.dart';
import 'package:filcnaplo_mobile_ui/pages/grades/average_selector.dart';
import 'grades_page.i18n.dart';
class GradesPage extends StatefulWidget {
@@ -41,24 +41,25 @@ class _GradesPageState extends State<GradesPage> {
int avgDropValue = 0;
List<Grade> getSubjectGrades(Subject subject, {int days = 0}) => gradeProvider
.grades
.where((e) =>
e.subject == subject &&
e.type == GradeType.midYear &&
(days == 0 ||
e.date.isBefore(DateTime.now().subtract(Duration(days: days)))))
.toList();
List<Grade> getSubjectGrades(GradeSubject subject, {int days = 0}) =>
gradeProvider.grades
.where((e) =>
e.subject == subject &&
e.type == GradeType.midYear &&
(days == 0 ||
e.date
.isBefore(DateTime.now().subtract(Duration(days: days)))))
.toList();
void generateTiles() {
List<Subject> subjects = gradeProvider.grades
List<GradeSubject> subjects = gradeProvider.grades
.map((e) => e.subject)
.toSet()
.toList()
..sort((a, b) => a.name.compareTo(b.name));
List<Widget> tiles = [];
Map<Subject, double> subjectAvgs = {};
Map<GradeSubject, double> subjectAvgs = {};
tiles.addAll(subjects.map((subject) {
List<Grade> subjectGrades = getSubjectGrades(subject);
@@ -145,6 +146,7 @@ class _GradesPageState extends State<GradesPage> {
child: StatisticsTile(
outline: true,
title: AutoSizeText(
// https://discord.com/channels/1111649116020285532/1153397476578050130
"classavg".i18n,
textAlign: TextAlign.center,
maxLines: 2,
@@ -208,7 +210,7 @@ class _GradesPageState extends State<GradesPage> {
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
PremiumAverageSelector(
AverageSelector(
value: avgDropValue,
onChanged: (value) {
setState(() {

View File

@@ -16,7 +16,7 @@ extension Localization on String {
"7_days_average": "Weekly Average",
"subjectavg": "Subject Average",
"classavg": "Class Average",
"fail_warning": "Faliure warning",
"fail_warning": "Failure warning",
"fail_warning_description": "You are failing %d subject(s)",
},
"hu_hu": {

View File

@@ -7,7 +7,7 @@ import 'package:filcnaplo/api/client.dart';
import 'package:filcnaplo/api/login.dart';
import 'package:filcnaplo_mobile_ui/screens/login/login_button.dart';
import 'package:filcnaplo_mobile_ui/screens/login/login_input.dart';
// import 'package:filcnaplo_desktop_ui/screens/login/school_input/school_input.dart';
import 'package:filcnaplo_desktop_ui/screens/login/school_input/school_input.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_acrylic/flutter_acrylic.dart';
@@ -36,8 +36,8 @@ class LoginScreen extends StatefulWidget {
class _LoginScreenState extends State<LoginScreen> {
final usernameController = TextEditingController();
final passwordController = TextEditingController();
// final schoolController = SchoolInputController();
// final _scrollController = ScrollController();
final schoolController = SchoolInputController();
final _scrollController = ScrollController();
LoginState _loginState = LoginState.normal;
bool showBack = false;
@@ -57,9 +57,9 @@ class _LoginScreenState extends State<LoginScreen> {
FilcAPI.getSchools().then((schools) {
if (schools != null) {
// schoolController.update(() {
// schoolController.schools = schools;
// });
schoolController.update(() {
schoolController.schools = schools;
});
} else {
ElegantNotification.error(
background: Colors.white,
@@ -238,10 +238,10 @@ class _LoginScreenState extends State<LoginScreen> {
),
),
),
// SchoolInput(
// scroll: _scrollController,
// controller: schoolController,
// ),
SchoolInput(
scroll: _scrollController,
controller: schoolController,
),
],
),
),
@@ -321,8 +321,8 @@ class _LoginScreenState extends State<LoginScreen> {
if (username == "" ||
password ==
"" /*||
schoolController.selectedSchool == null*/
"" ||
schoolController.selectedSchool == null
) {
return setState(() => _loginState = LoginState.missingFields);
}
@@ -332,8 +332,7 @@ class _LoginScreenState extends State<LoginScreen> {
loginAPI(
username: username,
password: password,
instituteCode: 'shit',
// instituteCode: schoolController.selectedSchool!.instituteCode,
instituteCode: schoolController.selectedSchool!.instituteCode,
context: context,
onLogin: (user) {
ElegantNotification.success(

View File

@@ -0,0 +1,122 @@
import 'package:filcnaplo_mobile_ui/screens/login/login_input.dart';
import 'package:filcnaplo_mobile_ui/screens/login/school_input/school_input_overlay.dart';
import 'package:filcnaplo_desktop_ui/screens/login/school_input/school_input_tile.dart';
import 'package:filcnaplo_mobile_ui/screens/login/school_input/school_search.dart';
import 'package:flutter/material.dart';
import 'package:filcnaplo_kreta_api/models/school.dart';
class SchoolInput extends StatefulWidget {
const SchoolInput({Key? key, required this.controller, required this.scroll})
: super(key: key);
final SchoolInputController controller;
final ScrollController scroll;
@override
_SchoolInputState createState() => _SchoolInputState();
}
class _SchoolInputState extends State<SchoolInput> {
final _focusNode = FocusNode();
final _layerLink = LayerLink();
late SchoolInputOverlay overlay;
@override
void initState() {
super.initState();
widget.controller.update = (fn) {
if (mounted) setState(fn);
};
overlay = SchoolInputOverlay(layerLink: _layerLink);
// Show school list when focused
_focusNode.addListener(() {
if (_focusNode.hasFocus) {
WidgetsBinding.instance
.addPostFrameCallback((_) => overlay.createOverlayEntry(context));
Future.delayed(const Duration(milliseconds: 100)).then((value) {
if (mounted && widget.scroll.hasClients) {
widget.scroll.animateTo(widget.scroll.offset + 500,
duration: const Duration(milliseconds: 500),
curve: Curves.ease);
}
});
} else {
overlay.entry?.remove();
}
});
// LoginInput TextField listener
widget.controller.textController.addListener(() {
String text = widget.controller.textController.text;
if (text.isEmpty) {
overlay.children = null;
return;
}
List<School> results =
searchSchools(widget.controller.schools ?? [], text);
setState(() {
overlay.children = results
.map((School e) => SchoolInputTile(
school: e,
onTap: () => _selectSchool(e),
))
.toList();
});
Overlay.of(context).setState(() {});
});
}
void _selectSchool(School school) {
FocusScope.of(context).requestFocus(FocusNode());
setState(() {
widget.controller.selectedSchool = school;
widget.controller.textController.text = school.name;
});
}
@override
Widget build(BuildContext context) {
return CompositedTransformTarget(
link: _layerLink,
child: widget.controller.schools == null
? Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(vertical: 10.0),
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.15),
borderRadius: BorderRadius.circular(12.0),
),
child: const Center(
child: SizedBox(
height: 28.0,
width: 28.0,
child: CircularProgressIndicator(
color: Colors.white,
),
),
),
)
: LoginInput(
style: LoginInputStyle.school,
focusNode: _focusNode,
onClear: () {
widget.controller.selectedSchool = null;
FocusScope.of(context).requestFocus(_focusNode);
},
controller: widget.controller.textController,
),
);
}
}
class SchoolInputController {
final textController = TextEditingController();
School? selectedSchool;
List<School>? schools;
late void Function(void Function()) update;
}

View File

@@ -0,0 +1,65 @@
import 'package:filcnaplo_kreta_api/models/school.dart';
import 'package:flutter/material.dart';
class SchoolInputTile extends StatelessWidget {
const SchoolInputTile({Key? key, required this.school, this.onTap})
: super(key: key);
final School school;
final Function()? onTap;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(4.0),
child: GestureDetector(
onPanDown: (e) {
onTap!();
},
child: InkWell(
onTapDown: (e) {},
borderRadius: BorderRadius.circular(6.0),
child: Padding(
padding: const EdgeInsets.all(6.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// School name
Padding(
padding: const EdgeInsets.only(bottom: 4.0),
child: Text(
school.name,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: const TextStyle(fontWeight: FontWeight.w600),
),
),
Row(
children: [
// School id
Expanded(
child: Text(
school.instituteCode,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
// School city
Expanded(
child: Text(
school.city,
textAlign: TextAlign.right,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
],
),
],
),
),
),
),
);
}
}

View File

@@ -62,6 +62,8 @@ class _SidebarState extends State<Sidebar> {
Provider.of<ExamProvider>(context, listen: false).restore(),
Provider.of<HomeworkProvider>(context, listen: false).restore(),
Provider.of<MessageProvider>(context, listen: false).restore(),
Provider.of<MessageProvider>(context, listen: false)
.restoreRecipients(),
Provider.of<NoteProvider>(context, listen: false).restore(),
Provider.of<EventProvider>(context, listen: false).restore(),
Provider.of<AbsenceProvider>(context, listen: false).restore(),

View File

@@ -38,8 +38,7 @@ import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart';
import 'settings_screen.i18n.dart';
import 'package:flutter/services.dart';
import 'package:filcnaplo_premium/ui/mobile/settings/nickname.dart';
import 'package:filcnaplo_premium/ui/mobile/settings/icon_pack.dart';
import 'package:filcnaplo_mobile_ui/screens/settings/user/nickname.dart';
class SettingsScreen extends StatefulWidget {
const SettingsScreen({Key? key}) : super(key: key);
@@ -68,6 +67,8 @@ class _SettingsScreenState extends State<SettingsScreen>
Provider.of<ExamProvider>(context, listen: false).restore(),
Provider.of<HomeworkProvider>(context, listen: false).restore(),
Provider.of<MessageProvider>(context, listen: false).restore(),
Provider.of<MessageProvider>(context, listen: false)
.restoreRecipients(),
Provider.of<NoteProvider>(context, listen: false).restore(),
Provider.of<EventProvider>(context, listen: false).restore(),
Provider.of<AbsenceProvider>(context, listen: false).restore(),
@@ -400,9 +401,9 @@ class _SettingsScreenState extends State<SettingsScreen>
if (v) {
showDialog(
context: context,
builder: (context) =>
WillPopScope(
onWillPop: () async => false,
builder: (context) => PopScope(
onPopInvoked: (didPop) =>
false,
child: AlertDialog(
shape:
RoundedRectangleBorder(
@@ -586,7 +587,8 @@ class _SettingsScreenState extends State<SettingsScreen>
.secondary,
),
),
const PremiumIconPackSelector(),
// we need icon pack selector here
// const PremiumIconPackSelector(),
],
),
),

View File

@@ -1,47 +0,0 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
/build/
# Web related
lib/generated_plugin_registrant.dart
# Symbolication related
app.*.symbols
# Obfuscation related
app.*.map.json
# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release
pubspec.lock

View File

@@ -21,23 +21,14 @@ class KretaAPI {
static String groups(String iss) =>
BaseKreta.kreta(iss) + KretaApiEndpoints.groups;
static String groupAverages(String iss, String uid) =>
BaseKreta.kreta(iss) +
KretaApiEndpoints.groupAverages +
"?oktatasiNevelesiFeladatUid=" +
uid;
"${BaseKreta.kreta(iss)}${KretaApiEndpoints.groupAverages}?oktatasiNevelesiFeladatUid=$uid";
static String averages(String iss, String uid) =>
BaseKreta.kreta(iss) +
KretaApiEndpoints.averages +
"?oktatasiNevelesiFeladatUid=" +
uid;
"${BaseKreta.kreta(iss)}${KretaApiEndpoints.averages}?oktatasiNevelesiFeladatUid=$uid";
static String timetable(String iss, {DateTime? start, DateTime? end}) =>
BaseKreta.kreta(iss) +
KretaApiEndpoints.timetable +
(start != null && end != null
? "?datumTol=" +
start.toUtc().toIso8601String() +
"&datumIg=" +
end.toUtc().toIso8601String()
? "?datumTol=${start.toUtc().toIso8601String()}&datumIg=${end.toUtc().toIso8601String()}"
: "");
static String exams(String iss) =>
BaseKreta.kreta(iss) + KretaApiEndpoints.exams;
@@ -46,7 +37,7 @@ class KretaAPI {
KretaApiEndpoints.homework +
(id != null ? "/$id" : "") +
(id == null && start != null
? "?datumTol=" + DateFormat('yyyy-MM-dd').format(start)
? "?datumTol=${DateFormat('yyyy-MM-dd').format(start)}"
: "");
static String capabilities(String iss) =>
BaseKreta.kreta(iss) + KretaApiEndpoints.capabilities;
@@ -54,6 +45,28 @@ class KretaAPI {
String iss, String uid, String type) =>
BaseKreta.kreta(iss) +
KretaApiEndpoints.downloadHomeworkAttachments(uid, type);
static String subjects(String iss, String uid) =>
"${BaseKreta.kreta(iss)}${KretaApiEndpoints.subjects}?oktatasiNevelesiFeladatUid=$uid";
// Structure:
// {
// "Uid": 000,
// "Tantargy": {
// "Uid": 000,
// "Nev": "Irodalom",
// "Kategoria": {
// "Uid": "000,magyar_nyelv_es_irodalom",
// "Nev": "magyar_nyelv_es_irodalom",
// "Leiras": "Magyar nyelv és irodalom"
// },
// "SortIndex": 0,
// },
// "Atlag": null, // float
// "AtlagAlakulasaIdoFuggvenyeben": Array[], // no idea what this is
// "SulyozottOsztalyzatOsszege": null, // int | float
// "SulyozottOsztalyzatSzama": null, // int | float
// "SortIndex": 0
// }
// refer to https://discord.com/channels/1111649116020285532/1111798771513303102/1148368925969612920
// ADMIN API
static const sendMessage =
@@ -66,8 +79,10 @@ class KretaAPI {
BaseKreta.kretaAdmin + KretaAdminEndpoints.recipientCategories;
static const availableCategories =
BaseKreta.kretaAdmin + KretaAdminEndpoints.availableCategories;
static const recipientsTeacher =
BaseKreta.kretaAdmin + KretaAdminEndpoints.recipientsTeacher;
static const recipientTeachers =
BaseKreta.kretaAdmin + KretaAdminEndpoints.recipientTeachers;
static const recipientDirectorate =
BaseKreta.kretaAdmin + KretaAdminEndpoints.recipientDirectorate;
static const uploadAttachment =
BaseKreta.kretaAdmin + KretaAdminEndpoints.uploadAttachment;
static String downloadAttachment(String id) =>
@@ -105,6 +120,8 @@ class KretaApiEndpoints {
static const capabilities = "/ellenorzo/V3/Sajat/Intezmenyek";
static String downloadHomeworkAttachments(String uid, String type) =>
"/ellenorzo/V3/Sajat/Csatolmany/$uid";
static const subjects =
"/ellenorzo/V3/Sajat/Ertekelesek/Atlagok/TantargyiAtlagok";
}
class KretaAdminEndpoints {
@@ -116,7 +133,8 @@ class KretaAdminEndpoints {
"/api/v1/kommunikacio/postaladaelemek/$id";
static const recipientCategories = "/api/v1/adatszotarak/cimzetttipusok";
static const availableCategories = "/api/v1/kommunikacio/cimezhetotipusok";
static const recipientsTeacher = "/api/v1/kreta/alkalmazottak/tanar";
static const recipientTeachers = "/api/v1/kreta/alkalmazottak/tanar";
static const recipientDirectorate = "/api/v1/kreta/alkalmazottak/igazgatosag";
static const uploadAttachment = "/ideiglenesfajlok";
static String downloadAttachment(String id) =>
"/api/v1/dokumentumok/uzenetek/$id";

View File

@@ -139,6 +139,9 @@ class KretaClient {
if (!headerMap.containsKey("content-type")) {
headerMap["content-type"] = "application/json";
}
if (url.contains('kommunikacio/uzenetek')) {
headerMap["X-Uzenet-Lokalizacio"] = "hu-HU";
}
}
res = await client.post(Uri.parse(url), headers: headerMap, body: body);
@@ -153,6 +156,7 @@ class KretaClient {
if (res == null) throw "Login error";
if (json) {
print(jsonDecode(res.body));
return jsonDecode(res.body);
} else {
return res.body;
@@ -165,6 +169,69 @@ class KretaClient {
}
}
Future<dynamic> sendFilesAPI(
String url, {
Map<String, String>? headers,
bool autoHeader = true,
Map<String, String>? body,
}) async {
Map<String, String> headerMap;
if (headers != null) {
headerMap = headers;
} else {
headerMap = {};
}
try {
http.StreamedResponse? res;
for (int i = 0; i < 3; i++) {
if (autoHeader) {
if (!headerMap.containsKey("authorization") && accessToken != null) {
headerMap["authorization"] = "Bearer $accessToken";
}
if (!headerMap.containsKey("user-agent") && userAgent != null) {
headerMap["user-agent"] = "$userAgent";
}
if (!headerMap.containsKey("content-type")) {
headerMap["content-type"] = "multipart/form-data";
}
if (url.contains('kommunikacio/uzenetek')) {
headerMap["X-Uzenet-Lokalizacio"] = "hu-HU";
}
}
var request = http.MultipartRequest("POST", Uri.parse(url));
// request.files.add(value)
request.fields.addAll(body ?? {});
request.headers.addAll(headers ?? {});
res = await request.send();
if (res.statusCode == 401) {
await refreshLogin();
headerMap.remove("authorization");
} else {
break;
}
}
if (res == null) throw "Login error";
print(res.statusCode);
return res.statusCode;
} on http.ClientException catch (error) {
print(
"ERROR: KretaClient.postAPI ($url) ClientException: ${error.message}");
} catch (error) {
print("ERROR: KretaClient.postAPI ($url) ${error.runtimeType}: $error");
}
}
Future<void> refreshLogin() async {
if (_loginRefreshing) return;
_loginRefreshing = true;

View File

@@ -1,4 +1,4 @@
// ignore_for_file: avoid_print
// ignore_for_file: avoid_print, use_build_context_synchronously
import 'dart:async';
import 'dart:developer';
@@ -154,9 +154,9 @@ class TimetableController extends ChangeNotifier {
}
for (int i = 0; i < days.length; i++) {
List<Lesson> _day = List.castFrom(days[i]);
List<Lesson> day0 = List.castFrom(days[i]);
List<int> lessonIndexes = _getIndexes(_day);
List<int> lessonIndexes = _getIndexes(day0);
int minIndex = 0, maxIndex = 0;
if (lessonIndexes.isNotEmpty) {
@@ -170,7 +170,7 @@ class TimetableController extends ChangeNotifier {
// Fill missing indexes with empty spaces
for (var i in List<int>.generate(
maxIndex - minIndex + 1, (int i) => minIndex + i)) {
List<Lesson> indexLessons = _getLessonsByIndex(_day, i);
List<Lesson> indexLessons = _getLessonsByIndex(day0, i);
// Empty lesson
if (indexLessons.isEmpty) {
@@ -193,13 +193,13 @@ class TimetableController extends ChangeNotifier {
}
// Additional lessons
day.addAll(_day.where((l) =>
day.addAll(day0.where((l) =>
int.tryParse(l.lessonIndex) == null && l.subject.id != ''));
day.sort((a, b) => a.start.compareTo(b.start));
// Special Dates
for (var l in _day) {
for (var l in day0) {
l.subject.id == '' ? day.insert(0, l) : null;
}

View File

@@ -13,7 +13,7 @@ class Absence {
Category? justification;
Category? type;
Category? mode;
Subject subject;
GradeSubject subject;
DateTime lessonStart;
DateTime lessonEnd;
int? lessonIndex;
@@ -83,7 +83,7 @@ class Absence {
: null,
type: json["Tipus"] != null ? Category.fromJson(json["Tipus"]) : null,
mode: json["Mod"] != null ? Category.fromJson(json["Mod"]) : null,
subject: Subject.fromJson(json["Tantargy"] ?? {}),
subject: GradeSubject.fromJson(json["Tantargy"] ?? {}),
lessonStart: lessonStart,
lessonEnd: lessonEnd,
lessonIndex: lessonIndex,

View File

@@ -1,3 +1,5 @@
import 'package:filcnaplo_kreta_api/models/subject.dart';
import 'category.dart';
import 'teacher.dart';
@@ -6,8 +8,9 @@ class Exam {
DateTime date;
DateTime writeDate;
Category? mode;
int? subjectIndex;
String subjectName;
// int? subjectIndex;
// String subjectName;
GradeSubject subject;
Teacher teacher;
String description;
String group;
@@ -18,8 +21,9 @@ class Exam {
required this.date,
required this.writeDate,
this.mode,
this.subjectIndex,
required this.subjectName,
// this.subjectIndex,
// required this.subjectName,
required this.subject,
required this.teacher,
required this.description,
required this.group,
@@ -36,8 +40,9 @@ class Exam {
? DateTime.parse(json["Datum"]).toLocal()
: DateTime(0),
mode: json["Modja"] != null ? Category.fromJson(json["Modja"]) : null,
subjectIndex: json["OrarendiOraOraszama"],
subjectName: json["TantargyNeve"] ?? "",
// subjectIndex: json["OrarendiOraOraszama"],
// subjectName: json["TantargyNeve"] ?? "",
subject: GradeSubject.fromJson(json["Tantargy"] ?? {}),
teacher: Teacher.fromString((json["RogzitoTanarNeve"] ?? "").trim()),
description: (json["Temaja"] ?? "").trim(),
group: json["OsztalyCsoport"] != null

View File

@@ -1,3 +1,5 @@
// ignore_for_file: no_leading_underscores_for_local_identifiers
import 'package:filcnaplo/utils/format.dart';
import 'category.dart';
import 'subject.dart';
@@ -12,7 +14,7 @@ class Grade {
String description;
GradeType type;
String groupId;
Subject subject;
GradeSubject subject;
Category? gradeType;
Category mode;
DateTime writeDate;
@@ -57,7 +59,7 @@ class Grade {
? Category.getGradeType(json["Tipus"]["Nev"])
: GradeType.unknown,
groupId: (json["OsztalyCsoport"] ?? {})["Uid"] ?? "",
subject: Subject.fromJson(json["Tantargy"] ?? {}),
subject: GradeSubject.fromJson(json["Tantargy"] ?? {}),
gradeType: json["ErtekFajta"] != null
? Category.fromJson(json["ErtekFajta"])
: null,

View File

@@ -3,7 +3,7 @@ import 'package:filcnaplo_kreta_api/models/subject.dart';
class GroupAverage {
String uid;
double average;
Subject subject;
GradeSubject subject;
Map json;
GroupAverage({required this.uid, required this.average, required this.subject, this.json = const {}});
@@ -12,7 +12,7 @@ class GroupAverage {
return GroupAverage(
uid: json["Uid"] ?? "",
average: json["OsztalyCsoportAtlag"] ?? 0,
subject: Subject.fromJson(json["Tantargy"] ?? {}),
subject: GradeSubject.fromJson(json["Tantargy"] ?? {}),
json: json,
);
}

View File

@@ -12,7 +12,7 @@ class Homework {
bool homeworkEnabled;
Teacher teacher;
String content;
Subject subject;
GradeSubject subject;
String group;
List<HomeworkAttachment> attachments;
String id;
@@ -48,7 +48,7 @@ class Homework {
homeworkEnabled: json["IsTanuloHaziFeladatEnabled"] ?? false,
teacher: Teacher.fromString((json["RogzitoTanarNeve"] ?? "").trim()),
content: (json["Szoveg"] ?? "").trim(),
subject: Subject.fromJson(json["Tantargy"] ?? {}),
subject: GradeSubject.fromJson(json["Tantargy"] ?? {}),
group: json["OsztalyCsoport"] != null
? json["OsztalyCsoport"]["Uid"] ?? ""
: "",

View File

@@ -6,7 +6,7 @@ class Lesson {
Map? json;
Category? status;
DateTime date;
Subject subject;
GradeSubject subject;
String lessonIndex;
int? lessonYearIndex;
Teacher? substituteTeacher;
@@ -68,7 +68,7 @@ class Lesson {
date: json["Datum"] != null
? DateTime.parse(json["Datum"]).toLocal()
: DateTime(0),
subject: Subject.fromJson(json["Tantargy"] ?? {}),
subject: GradeSubject.fromJson(json["Tantargy"] ?? {}),
lessonIndex: json["Oraszam"] != null ? json["Oraszam"].toString() : "+",
lessonYearIndex: json["OraEvesSorszama"],
substituteTeacher: json["HelyettesTanarNeve"] != null

View File

@@ -68,13 +68,21 @@ class Message {
messageId: message["azonosito"],
seen: json["isElolvasva"] ?? false,
deleted: json["isToroltElem"] ?? false,
date: message["kuldesDatum"] != null ? DateTime.parse(message["kuldesDatum"]).toLocal() : DateTime(0),
date: message["kuldesDatum"] != null
? DateTime.parse(message["kuldesDatum"]).toLocal()
: DateTime(0),
author: (message["feladoNev"] ?? "").trim(),
content: message["szoveg"].replaceAll("\r", "") ?? "",
subject: message["targy"] ?? "",
type: type,
recipients: (message["cimzettLista"] as List).cast<Map>().map((Map recipient) => Recipient.fromJson(recipient)).toList(),
attachments: (message["csatolmanyok"] as List).cast<Map>().map((Map attachment) => Attachment.fromJson(attachment)).toList(),
recipients: (message["cimzettLista"] as List)
.cast<Map>()
.map((Map recipient) => Recipient.fromJson(recipient))
.toList(),
attachments: (message["csatolmanyok"] as List)
.cast<Map>()
.map((Map attachment) => Attachment.fromJson(attachment))
.toList(),
replyId: message["elozoUzenetAzonosito"],
conversationId: message["beszelgetesAzonosito"],
json: json,
@@ -105,3 +113,99 @@ class Conversation {
Message get newest => _messages.first;
}
// sendable message object and it's things
class SendMessage {
Map? json;
int id;
int lastMessageId;
String? subject;
String text;
DateTime sentDate;
String senderRank;
String senderName;
List<Attachment>? attachments;
List<SendRecipient> recipients;
SendMessage({
required this.id,
required this.lastMessageId,
this.subject,
required this.text,
required this.sentDate,
required this.senderRank,
required this.senderName,
this.attachments,
required this.recipients,
});
}
class SendRecipient {
Map? json;
int? id;
int? kretaId;
String? name;
SendRecipientType type;
SendRecipient({
required this.id,
required this.kretaId,
required this.name,
required this.type,
this.json,
});
factory SendRecipient.fromJson(Map json, SendRecipientType type) {
return SendRecipient(
id: json['kretaAzonosito'] ?? 0,
kretaId: json['kretaAzonosito'],
name: json['nev'],
type: type,
json: json,
);
}
Object get kretaJson => {
'azonosito': kretaId ?? 0,
'kretaAzonosito': kretaId ?? 0,
'nev': name ?? 'Teszt Lajos',
'tipus': {
'azonosito': type.id,
'kod': type.code,
'leiras': type.description,
'nev': type.name,
'rovidNev': type.shortName,
}
};
}
class SendRecipientType {
Map? json;
int id;
String code;
String description;
String name;
String shortName;
SendRecipientType({
required this.id,
required this.code,
required this.description,
required this.name,
required this.shortName,
this.json,
});
factory SendRecipientType.fromJson(Map json) {
return SendRecipientType(
id: json['azonosito'],
code: json['kod'],
description: json['leiras'],
name: json['nev'],
shortName: json['rovidNev'],
json: json,
);
}
}
enum AddresseeType { teachers, directorate }

View File

@@ -1,6 +1,6 @@
import 'category.dart';
class Subject {
class GradeSubject {
String id;
Category category;
String name;
@@ -8,11 +8,16 @@ class Subject {
bool get isRenamed => renamedTo != null;
Subject({required this.id, required this.category, required this.name, this.renamedTo});
GradeSubject({
required this.id,
required this.category,
required this.name,
this.renamedTo,
});
factory Subject.fromJson(Map json) {
factory GradeSubject.fromJson(Map json) {
final id = json["Uid"] ?? "";
return Subject(
return GradeSubject(
id: id,
category: Category.fromJson(json["Kategoria"] ?? {}),
name: (json["Nev"] ?? "").trim(),
@@ -21,7 +26,7 @@ class Subject {
@override
bool operator ==(other) {
if (other is! Subject) return false;
if (other is! GradeSubject) return false;
return id == other.id;
}

View File

@@ -1,3 +1,5 @@
// ignore_for_file: no_leading_underscores_for_local_identifiers
import 'package:filcnaplo_kreta_api/controllers/timetable_controller.dart';
class Week {

View File

@@ -1,3 +1,5 @@
// ignore_for_file: no_leading_underscores_for_local_identifiers
import 'package:filcnaplo/api/providers/user_provider.dart';
import 'package:filcnaplo/api/providers/database_provider.dart';
import 'package:filcnaplo/models/user.dart';
@@ -43,12 +45,14 @@ class AbsenceProvider with ChangeNotifier {
(await _database.query.getSettings(_database)).renamedSubjectsEnabled
? await _database.userQuery.renamedSubjects(
userId:
// ignore: use_build_context_synchronously
Provider.of<UserProvider>(_context, listen: false).user!.id)
: {};
Map<String, String> renamedTeachers =
(await _database.query.getSettings(_database)).renamedTeachersEnabled
? await _database.userQuery.renamedTeachers(
userId:
// ignore: use_build_context_synchronously
Provider.of<UserProvider>(_context, listen: false).user!.id)
: {};

View File

@@ -27,19 +27,51 @@ class ExamProvider with ChangeNotifier {
// Load exams from the database
if (userId != null) {
var dbExams = await Provider.of<DatabaseProvider>(_context, listen: false).userQuery.getExams(userId: userId);
var dbExams = await Provider.of<DatabaseProvider>(_context, listen: false)
.userQuery
.getExams(userId: userId);
_exams = dbExams;
notifyListeners();
await convertBySettings();
}
}
// for renamed subjects
Future<void> convertBySettings() async {
final database = Provider.of<DatabaseProvider>(_context, listen: false);
Map<String, String> renamedSubjects =
(await database.query.getSettings(database)).renamedSubjectsEnabled
? await database.userQuery.renamedSubjects(
userId:
// ignore: use_build_context_synchronously
Provider.of<UserProvider>(_context, listen: false).user!.id)
: {};
Map<String, String> renamedTeachers =
(await database.query.getSettings(database)).renamedTeachersEnabled
? await database.userQuery.renamedTeachers(
userId:
// ignore: use_build_context_synchronously
Provider.of<UserProvider>(_context, listen: false).user!.id)
: {};
for (Exam exam in _exams) {
exam.subject.renamedTo =
renamedSubjects.isNotEmpty ? renamedSubjects[exam.subject.id] : null;
exam.teacher.renamedTo =
renamedTeachers.isNotEmpty ? renamedTeachers[exam.teacher.id] : null;
}
notifyListeners();
}
// Fetches Exams from the Kreta API then stores them in the database
Future<void> fetch() async {
User? user = Provider.of<UserProvider>(_context, listen: false).user;
if (user == null) throw "Cannot fetch Exams for User null";
String iss = user.instituteCode;
List? examsJson = await Provider.of<KretaClient>(_context, listen: false).getAPI(KretaAPI.exams(iss));
List? examsJson = await Provider.of<KretaClient>(_context, listen: false)
.getAPI(KretaAPI.exams(iss));
if (examsJson == null) throw "Cannot fetch Exams for User ${user.id}";
List<Exam> exams = examsJson.map((e) => Exam.fromJson(e)).toList();
@@ -52,8 +84,11 @@ class ExamProvider with ChangeNotifier {
if (user == null) throw "Cannot store Exams for User null";
String userId = user.id;
await Provider.of<DatabaseProvider>(_context, listen: false).userStore.storeExams(exams, userId: userId);
await Provider.of<DatabaseProvider>(_context, listen: false)
.userStore
.storeExams(exams, userId: userId);
_exams = exams;
notifyListeners();
await convertBySettings();
}
}

View File

@@ -1,6 +1,6 @@
import 'package:filcnaplo/api/providers/user_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_kreta_api/client/api.dart';
import 'package:filcnaplo_kreta_api/client/client.dart';
@@ -11,7 +11,7 @@ import 'package:provider/provider.dart';
class HomeworkProvider with ChangeNotifier {
// Private
late final SettingsProvider _settings;
// late final SettingsProvider _settings;
late final UserProvider _user;
late final DatabaseProvider _database;
@@ -24,10 +24,12 @@ class HomeworkProvider with ChangeNotifier {
List<Homework> initialHomework = const [],
required BuildContext context,
required DatabaseProvider database,
required UserProvider user,
}) {
_homework = List.castFrom(initialHomework);
_context = context;
_database = database;
_user = user;
if (_homework.isEmpty) restore();
}
@@ -78,9 +80,11 @@ class HomeworkProvider with ChangeNotifier {
List? homeworkJson = [];
try {
homeworkJson = await Provider.of<KretaClient>(_context, listen: false)
Iterable hwjson = await Provider.of<KretaClient>(_context, listen: false)
.getAPI(KretaAPI.homework(iss, start: from));
homeworkJson = List.from(hwjson.map((model) => model));
} catch (e) {
if (kDebugMode) print(e);
// error fetcing homework (unknown error)
}
@@ -93,15 +97,15 @@ class HomeworkProvider with ChangeNotifier {
await Future.forEach(homeworkJson.cast<Map>(), (Map hw) async {
Map? e = await Provider.of<KretaClient>(_context, listen: false)
.getAPI(KretaAPI.homework(iss, id: hw["Uid"]));
Map<String, String> renamedSubjects = _settings.renamedSubjectsEnabled
? await _database.userQuery.renamedSubjects(userId: _user.user!.id)
: {};
// Map<String, String> renamedSubjects = _settings.renamedSubjectsEnabled
// ? await _database.userQuery.renamedSubjects(userId: _user.user!.id)
// : {};
if (e != null) {
Homework hw = Homework.fromJson(e);
hw.subject.renamedTo =
renamedSubjects.isNotEmpty ? renamedSubjects[hw.subject.id] : null;
homework.add(hw);
Homework hmwrk = Homework.fromJson(e);
// hw.subject.renamedTo =
// renamedSubjects.isNotEmpty ? renamedSubjects[hw.subject.id] : null;
homework.add(hmwrk);
}
});
@@ -110,6 +114,7 @@ class HomeworkProvider with ChangeNotifier {
if (db) await store(homework);
_homework = homework;
notifyListeners();
await convertBySettings();
}
// Stores Homework in the database

View File

@@ -1,3 +1,7 @@
// ignore_for_file: use_build_context_synchronously
import 'dart:convert';
import 'dart:math';
import 'package:filcnaplo/api/providers/user_provider.dart';
import 'package:filcnaplo/api/providers/database_provider.dart';
import 'package:filcnaplo/models/user.dart';
@@ -9,17 +13,22 @@ import 'package:provider/provider.dart';
class MessageProvider with ChangeNotifier {
late List<Message> _messages;
late List<SendRecipient> _recipients;
late BuildContext _context;
List<Message> get messages => _messages;
List<SendRecipient> get recipients => _recipients;
MessageProvider({
List<Message> initialMessages = const [],
required BuildContext context,
}) {
_messages = List.castFrom(initialMessages);
_recipients = [];
_context = context;
if (_messages.isEmpty) restore();
if (_recipients.isEmpty) restoreRecipients();
}
Future<void> restore() async {
@@ -27,27 +36,33 @@ class MessageProvider with ChangeNotifier {
// Load messages from the database
if (userId != null) {
var dbMessages = await Provider.of<DatabaseProvider>(_context, listen: false).userQuery.getMessages(userId: userId);
var dbMessages =
await Provider.of<DatabaseProvider>(_context, listen: false)
.userQuery
.getMessages(userId: userId);
_messages = dbMessages;
notifyListeners();
}
}
// Fetches all types of Messages
Future<void> fetchAll() => Future.forEach(MessageType.values, (MessageType v) => fetch(type: v));
Future<void> fetchAll() =>
Future.forEach(MessageType.values, (MessageType v) => fetch(type: v));
// Fetches Messages from the Kreta API then stores them in the database
Future<void> fetch({MessageType type = MessageType.inbox}) async {
// Check Message Type
if (type == MessageType.draft) return;
String messageType = ["beerkezett", "elkuldott", "torolt"].elementAt(type.index);
String messageType =
["beerkezett", "elkuldott", "torolt"].elementAt(type.index);
// Check User
User? user = Provider.of<UserProvider>(_context, listen: false).user;
if (user == null) throw "Cannot fetch Messages for User null";
// Get messages
List? messagesJson = await Provider.of<KretaClient>(_context, listen: false).getAPI(KretaAPI.messages(messageType));
List? messagesJson = await Provider.of<KretaClient>(_context, listen: false)
.getAPI(KretaAPI.messages(messageType));
if (messagesJson == null) throw "Cannot fetch Messages for User ${user.id}";
// Parse messages
@@ -55,8 +70,12 @@ class MessageProvider with ChangeNotifier {
await Future.wait(List.generate(messagesJson.length, (index) {
return () async {
Map message = messagesJson.cast<Map>()[index];
Map? messageJson = await Provider.of<KretaClient>(_context, listen: false).getAPI(KretaAPI.message(message["azonosito"].toString()));
if (messageJson != null) messages.add(Message.fromJson(messageJson, forceType: type));
Map? messageJson =
await Provider.of<KretaClient>(_context, listen: false)
.getAPI(KretaAPI.message(message["azonosito"].toString()));
if (messageJson != null) {
messages.add(Message.fromJson(messageJson, forceType: type));
}
}();
}));
@@ -73,8 +92,177 @@ class MessageProvider with ChangeNotifier {
if (user == null) throw "Cannot store Messages for User null";
String userId = user.id;
await Provider.of<DatabaseProvider>(_context, listen: false).userStore.storeMessages(_messages, userId: userId);
await Provider.of<DatabaseProvider>(_context, listen: false)
.userStore
.storeMessages(_messages, userId: userId);
notifyListeners();
}
// restore recipients
Future<void> restoreRecipients() async {
String? userId = Provider.of<UserProvider>(_context, listen: false).id;
// Load messages from the database
if (userId != null) {
var dbRecipients =
await Provider.of<DatabaseProvider>(_context, listen: false)
.userQuery
.getRecipients(userId: userId);
_recipients = dbRecipients;
notifyListeners();
}
}
// fetch all recipients
Future<void> fetchAllRecipients() => Future.forEach(
AddresseeType.values, (AddresseeType v) => fetchRecipients(type: v));
// fetch recipients
Future<void> fetchRecipients(
{AddresseeType type = AddresseeType.teachers}) async {
Map<AddresseeType, SendRecipientType> addressable = {};
// check user
User? user = Provider.of<UserProvider>(_context, listen: false).user;
if (user == null) throw "Cannot fetch Messages for User null";
// get categories
List? availableCategoriesJson =
await Provider.of<KretaClient>(_context, listen: false)
.getAPI(KretaAPI.recipientCategories);
// print(availableCategoriesJson);
// get recipients
List? recipientTeachersJson =
await Provider.of<KretaClient>(_context, listen: false)
.getAPI(KretaAPI.recipientTeachers);
List? recipientDirectorateJson =
await Provider.of<KretaClient>(_context, listen: false)
.getAPI(KretaAPI.recipientDirectorate);
if (availableCategoriesJson == null ||
recipientTeachersJson == null ||
recipientDirectorateJson == null) {
throw "Cannot fetch Recipients for User ${user.id}";
}
for (var e in availableCategoriesJson) {
// print(e);
switch (e['kod']) {
case 'TANAR':
addressable
.addAll({AddresseeType.teachers: SendRecipientType.fromJson(e)});
break;
case 'IGAZGATOSAG':
addressable.addAll(
{AddresseeType.directorate: SendRecipientType.fromJson(e)});
break;
default:
break;
}
}
// parse recipients
List<SendRecipient> recipients = [];
if (addressable.containsKey(AddresseeType.teachers) &&
type == AddresseeType.teachers) {
recipients.addAll(recipientTeachersJson.map((e) =>
SendRecipient.fromJson(e, addressable[AddresseeType.teachers]!)));
}
if (addressable.containsKey(AddresseeType.directorate) &&
type == AddresseeType.directorate) {
recipients.addAll(recipientDirectorateJson.map((e) =>
SendRecipient.fromJson(e, addressable[AddresseeType.directorate]!)));
}
// if (kDebugMode) {
// print(addressable);
// print(recipients);
// print(recipients.first.json);
// }
await storeRecipients(recipients, type);
}
// store recipients
Future<void> storeRecipients(
List<SendRecipient> recipients, AddresseeType type) async {
_recipients.removeWhere((r) => (type == AddresseeType.teachers
? (r.type.code == 'TANAR')
: (type == AddresseeType.directorate
? (r.type.code == 'IGAZGATOSAG')
: r.type.code != '')));
_recipients.addAll(recipients);
User? user = Provider.of<UserProvider>(_context, listen: false).user;
if (user == null) throw "Cannot store Recipients for User null";
String userId = user.id;
await Provider.of<DatabaseProvider>(_context, listen: false)
.userStore
.storeRecipients(_recipients, userId: userId);
notifyListeners();
}
// send message
Future<String?> sendMessage({
required List<SendRecipient> recipients,
String subject = "Nincs tárgy",
required String messageText,
}) async {
List<Object> recipientList = [];
User? user = Provider.of<UserProvider>(_context, listen: false).user;
if (user == null) throw "Cannot send Message as User null";
// for (var r in recipients) {
// recipientList.add({
// "azonosito": r.id ?? "",
// "kretaAzonosito": r.kretaId ?? "",
// "nev": r.name ?? "Teszt Lajos",
// "tipus": {
// "kod": r.type.code,
// "leiras": r.type.description,
// "azonosito": r.type.id,
// "nev": r.type.name,
// "rovidNev": r.type.shortName,
// }
// });
// }
recipientList.addAll(recipients.map((e) => e.kretaJson));
Map body = {
"cimzettLista": recipientList,
"csatolmanyok": [],
"azonosito": (Random().nextInt(10000) + 10000),
"feladoNev": user.name,
"feladoTitulus": user.role == Role.parent ? "Szülő" : "Diák",
"kuldesDatum": DateTime.now().toIso8601String(),
"targy": subject,
"szoveg": messageText,
// "elozoUzenetAzonosito": 0,
};
Map<String, String> headers = {
"content-type": "application/json",
};
var res = await Provider.of<KretaClient>(_context, listen: false).postAPI(
KretaAPI.sendMessage,
autoHeader: true,
json: true,
body: json.encode(body),
headers: headers,
);
if (res!['hibakod'] == 'UzenetKuldesEngedelyRule') {
return 'send_permission_error';
}
return 'successfully_sent';
}
}

View File

@@ -40,6 +40,11 @@ class ShareProvider extends ChangeNotifier {
SettingsProvider.defaultSettings().customAccentColor)
?.value ??
const Color(0xFF3D7BF4).value,
'icon_color': (settings.customIconColor ??
SettingsProvider.defaultSettings().customIconColor)
?.value ??
const Color(0x00000000).value,
'shadow_effect': settings.shadowEffect,
};
SharedTheme theme = SharedTheme.fromJson(themeJson, gradeColors);

View File

@@ -0,0 +1,165 @@
// import 'package:filcnaplo/api/providers/user_provider.dart';
// import 'package:filcnaplo/api/providers/database_provider.dart';
// import 'package:filcnaplo/models/settings.dart';
// import 'package:filcnaplo/models/user.dart';
// import 'package:filcnaplo_kreta_api/client/api.dart';
// import 'package:filcnaplo_kreta_api/client/client.dart';
// import 'package:filcnaplo_kreta_api/models/grade.dart';
// import 'package:filcnaplo_kreta_api/models/group_average.dart';
// import 'package:filcnaplo_kreta_api/providers/grade_provider.i18n.dart';
// import 'package:flutter/material.dart';
// class SubjectProvider with ChangeNotifier {
// // Private
// late List<Grade> _grades;
// late DateTime _lastSeen;
// late String _groups;
// List<GroupAverage> _groupAvg = [];
// late final SettingsProvider _settings;
// late final UserProvider _user;
// late final DatabaseProvider _database;
// late final KretaClient _kreta;
// // Public
// List<Grade> get grades => _grades;
// DateTime get lastSeenDate =>
// _settings.gradeOpeningFun ? _lastSeen : DateTime(3000);
// String get groups => _groups;
// List<GroupAverage> get groupAverages => _groupAvg;
// SubjectProvider({
// List<Grade> initialGrades = const [],
// required SettingsProvider settings,
// required UserProvider user,
// required DatabaseProvider database,
// required KretaClient kreta,
// }) {
// _settings = settings;
// _user = user;
// _database = database;
// _kreta = kreta;
// _grades = List.castFrom(initialGrades);
// _lastSeen = DateTime.now();
// if (_grades.isEmpty) restore();
// }
// Future<void> seenAll() async {
// String? userId = _user.id;
// if (userId != null) {
// final userStore = _database.userStore;
// userStore.storeLastSeenGrade(DateTime.now(), userId: userId);
// _lastSeen = DateTime.now();
// }
// }
// Future<void> restore() async {
// String? userId = _user.id;
// // Load grades from the database
// if (userId != null) {
// final userQuery = _database.userQuery;
// _grades = await userQuery.getGrades(userId: userId);
// await convertBySettings();
// _groupAvg = await userQuery.getGroupAverages(userId: userId);
// notifyListeners();
// DateTime lastSeenDB = await userQuery.lastSeenGrade(userId: userId);
// if (lastSeenDB.millisecondsSinceEpoch == 0 ||
// lastSeenDB.year == 0 ||
// !_settings.gradeOpeningFun) {
// _lastSeen = DateTime.now();
// await seenAll();
// } else {
// _lastSeen = lastSeenDB;
// }
// notifyListeners();
// }
// }
// // good student mode, renamed subjects
// Future<void> convertBySettings() async {
// Map<String, String> renamedSubjects = _settings.renamedSubjectsEnabled
// ? await _database.userQuery.renamedSubjects(userId: _user.user!.id)
// : {};
// Map<String, String> renamedTeachers = _settings.renamedTeachersEnabled
// ? await _database.userQuery.renamedTeachers(userId: _user.user!.id)
// : {};
// for (Grade grade in _grades) {
// grade.subject.renamedTo =
// renamedSubjects.isNotEmpty ? renamedSubjects[grade.subject.id] : null;
// grade.teacher.renamedTo =
// renamedTeachers.isNotEmpty ? renamedTeachers[grade.teacher.id] : null;
// grade.value.value =
// _settings.goodStudent ? 5 : grade.json!["SzamErtek"] ?? 0;
// grade.value.valueName = _settings.goodStudent
// ? "Jeles".i18n
// : '${grade.json!["SzovegesErtek"]}'
// .replaceAll(RegExp(r'[(]+[12345]?[)]'), '')
// .i18n;
// grade.value.shortName = _settings.goodStudent
// ? "Jeles".i18n
// : '${grade.json!["SzovegesErtekelesRovidNev"]}' != "null" &&
// '${grade.json!["SzovegesErtekelesRovidNev"]}' != "-" &&
// '${grade.json!["SzovegesErtekelesRovidNev"]}'
// .replaceAll(RegExp(r'[0123456789]+[%]?'), '') !=
// ""
// ? '${grade.json!["SzovegesErtekelesRovidNev"]}'.i18n
// : grade.value.valueName;
// }
// notifyListeners();
// }
// // fetch subjects from kreten then store them
// Future<void> fetch() async {
// User? user = _user.user;
// if (user == null) throw "Cannot fetch Subjects for User null";
// String iss = user.instituteCode;
// List? gradesJson = await _kreta.getAPI(KretaAPI.subjects(iss, ""));
// if (gradesJson == null) throw "Cannot fetch Subjects for User ${user.id}";
// List<Grade> grades = gradesJson.map((e) => Grade.fromJson(e)).toList();
// if (grades.isNotEmpty || _grades.isNotEmpty) await store(grades);
// List? groupsJson = await _kreta.getAPI(KretaAPI.groups(iss));
// if (groupsJson == null || groupsJson.isEmpty) {
// throw "Cannot fetch Groups for User ${user.id}";
// }
// _groups = (groupsJson[0]["OktatasNevelesiFeladat"] ?? {})["Uid"] ?? "";
// List? groupAvgJson =
// await _kreta.getAPI(KretaAPI.groupAverages(iss, _groups));
// if (groupAvgJson == null) {
// throw "Cannot fetch Class Averages for User ${user.id}";
// }
// final groupAvgs =
// groupAvgJson.map((e) => GroupAverage.fromJson(e)).toList();
// await storeGroupAvg(groupAvgs);
// }
// // store subjects in db
// Future<void> store(List<Grade> grades) async {
// User? user = _user.user;
// if (user == null) throw "Cannot store Grades for User null";
// String userId = user.id;
// await _database.userStore.storeGrades(grades, userId: userId);
// _grades = grades;
// await convertBySettings();
// }
// Future<void> storeGroupAvg(List<GroupAverage> groupAvgs) async {
// _groupAvg = groupAvgs;
// User? user = _user.user;
// if (user == null) throw "Cannot store Grades for User null";
// String userId = user.id;
// await _database.userStore.storeGroupAverages(groupAvgs, userId: userId);
// notifyListeners();
// }
// }

View File

@@ -65,8 +65,14 @@ class TimetableProvider with ChangeNotifier {
User? user = _user.user;
if (user == null) throw "Cannot fetch Lessons for User null";
String iss = user.instituteCode;
List? lessonsJson = await _kreta
.getAPI(KretaAPI.timetable(iss, start: week.start, end: week.end));
List? lessonsJson;
try {
lessonsJson = await _kreta
.getAPI(KretaAPI.timetable(iss, start: week.start, end: week.end));
} catch (e) {
lessonsJson = null;
}
if (lessonsJson == null) {
if (kDebugMode) print('Cannot fetch Lessons for User ${user.id}');

View File

@@ -11,7 +11,10 @@ dependencies:
path: ../filcnaplo/
http: ^0.13.3
provider: ^5.0.0
file_picker: ^5.3.2
file_picker: ^6.1.1
intl: ^0.18.1
i18n_extension: ^10.0.1
uuid: ^4.2.1
dev_dependencies:
flutter_lints: ^1.0.0
flutter_lints: ^3.0.1

View File

@@ -1,47 +0,0 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
/build/
# Web related
lib/generated_plugin_registrant.dart
# Symbolication related
app.*.symbols
# Obfuscation related
app.*.map.json
# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release
pubspec.lock

View File

@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
class ActionButton extends StatelessWidget {
const ActionButton({Key? key, required this.label, this.activeColor, this.onTap}) : super(key: key);
const ActionButton({super.key, required this.label, this.activeColor, this.onTap});
final Color? activeColor;
final void Function()? onTap;

View File

@@ -4,8 +4,7 @@ import 'package:flutter/material.dart';
import 'package:i18n_extension/i18n_widget.dart';
class AverageDisplay extends StatelessWidget {
const AverageDisplay({Key? key, this.average = 0.0, this.border = false})
: super(key: key);
const AverageDisplay({super.key, this.average = 0.0, this.border = false});
final double average;
final bool border;

View File

@@ -2,7 +2,7 @@ import 'package:filcnaplo/theme/colors/colors.dart';
import 'package:flutter/material.dart';
class BetaChip extends StatelessWidget {
const BetaChip({Key? key, this.disabled = false}) : super(key: key);
const BetaChip({super.key, this.disabled = false});
final bool disabled;
@@ -12,6 +12,12 @@ class BetaChip extends StatelessWidget {
height: 25,
child: AnimatedContainer(
duration: const Duration(milliseconds: 200),
decoration: BoxDecoration(
color: !disabled
? Theme.of(context).colorScheme.secondary
: AppColors.of(context).text.withOpacity(.25),
borderRadius: BorderRadius.circular(40),
),
child: Padding(
padding: const EdgeInsets.only(left: 8, right: 8),
child: Center(
@@ -29,12 +35,6 @@ class BetaChip extends StatelessWidget {
),
),
),
decoration: BoxDecoration(
color: !disabled
? Theme.of(context).colorScheme.secondary
: AppColors.of(context).text.withOpacity(.25),
borderRadius: BorderRadius.circular(40),
),
),
);
}

View File

@@ -2,7 +2,7 @@ import 'package:filcnaplo/theme/colors/colors.dart';
import 'package:flutter/material.dart';
class BottomCard extends StatelessWidget {
const BottomCard({Key? key, this.child}) : super(key: key);
const BottomCard({super.key, this.child});
final Widget? child;

View File

@@ -2,7 +2,7 @@ import 'package:filcnaplo_mobile_ui/common/bottom_sheet_menu/rounded_bottom_shee
import 'package:flutter/material.dart';
class BottomSheetMenu extends StatelessWidget {
const BottomSheetMenu({Key? key, this.items = const []}) : super(key: key);
const BottomSheetMenu({super.key, this.items = const []});
final List<Widget> items;

View File

@@ -2,7 +2,7 @@ import 'package:filcnaplo_mobile_ui/common/panel/panel_button.dart';
import 'package:flutter/material.dart';
class BottomSheetMenuItem extends StatelessWidget {
const BottomSheetMenuItem({Key? key, required this.onPressed, required this.title, this.icon}) : super(key: key);
const BottomSheetMenuItem({super.key, required this.onPressed, required this.title, this.icon});
final void Function()? onPressed;
final Widget? title;

View File

@@ -2,7 +2,7 @@ import 'package:filcnaplo/theme/colors/colors.dart';
import 'package:flutter/material.dart';
class RoundedBottomSheet extends StatelessWidget {
const RoundedBottomSheet({Key? key, this.child, this.borderRadius = 12.0, this.shrink = true, this.showHandle = true}) : super(key: key);
const RoundedBottomSheet({super.key, this.child, this.borderRadius = 12.0, this.shrink = true, this.showHandle = true});
final Widget? child;
final double borderRadius;

View File

@@ -10,6 +10,7 @@ SnackBar CustomSnackBar({
Duration? duration,
}) {
// backgroundColor > Brightness > Theme Background
// ignore: no_leading_underscores_for_local_identifiers
Color _backgroundColor = backgroundColor ?? (AppColors.fromBrightness(brightness ?? Theme.of(context).brightness).highlight);
Color textColor = AppColors.fromBrightness(brightness ?? Theme.of(context).brightness).text;

View File

@@ -2,7 +2,7 @@ import 'package:filcnaplo/theme/colors/colors.dart';
import 'package:flutter/material.dart';
class Detail extends StatelessWidget {
const Detail({Key? key, required this.title, required this.description, this.maxLines = 3}) : super(key: key);
const Detail({super.key, required this.title, required this.description, this.maxLines = 3});
final String title;
final String description;

View File

@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
class DialogButton extends StatelessWidget {
const DialogButton({Key? key, required this.label, this.onTap}) : super(key: key);
const DialogButton({super.key, required this.label, this.onTap});
final String label;
final Function()? onTap;

View File

@@ -4,7 +4,7 @@ class Dot extends StatelessWidget {
final Color color;
final double size;
const Dot({Key? key, this.color = Colors.grey, this.size = 16.0}) : super(key: key);
const Dot({super.key, this.color = Colors.grey, this.size = 16.0});
@override
Widget build(BuildContext context) {

Some files were not shown because too many files have changed in this diff Show More