4
.gitignore
vendored
@ -29,9 +29,11 @@ filcnaplo_premium/.flutter-plugins
|
|||||||
filcnaplo_premium/.flutter-plugins-dependencies
|
filcnaplo_premium/.flutter-plugins-dependencies
|
||||||
filcnaplo_premium/pubspec.lock
|
filcnaplo_premium/pubspec.lock
|
||||||
filcnaplo_premium/.dart_tool/
|
filcnaplo_premium/.dart_tool/
|
||||||
filcnaplo_premium/android/
|
|
||||||
|
|
||||||
.vscode
|
.vscode
|
||||||
.github
|
.github
|
||||||
.idea
|
.idea
|
||||||
.gitmodules
|
.gitmodules
|
||||||
|
|
||||||
|
filcnaplo/.DS_Store
|
||||||
|
.DS_Store
|
||||||
|
3
.gitmodules
vendored
@ -0,0 +1,3 @@
|
|||||||
|
[submodule "filcnaplo_premium"]
|
||||||
|
path = filcnaplo_premium
|
||||||
|
url = git@github.com:refilc/naplo-plus.git
|
@ -4,7 +4,7 @@
|
|||||||
# This file should be version controlled and should not be manually edited.
|
# This file should be version controlled and should not be manually edited.
|
||||||
|
|
||||||
version:
|
version:
|
||||||
revision: "efbf63d9c66b9f6ec30e9ad4611189aa80003d31"
|
revision: "b0366e0a3f089e15fd89c97604ab402fe26b724c"
|
||||||
channel: "stable"
|
channel: "stable"
|
||||||
|
|
||||||
project_type: app
|
project_type: app
|
||||||
@ -13,17 +13,17 @@ project_type: app
|
|||||||
migration:
|
migration:
|
||||||
platforms:
|
platforms:
|
||||||
- platform: root
|
- platform: root
|
||||||
create_revision: efbf63d9c66b9f6ec30e9ad4611189aa80003d31
|
create_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
|
||||||
base_revision: efbf63d9c66b9f6ec30e9ad4611189aa80003d31
|
base_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
|
||||||
- platform: linux
|
- platform: linux
|
||||||
create_revision: efbf63d9c66b9f6ec30e9ad4611189aa80003d31
|
create_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
|
||||||
base_revision: efbf63d9c66b9f6ec30e9ad4611189aa80003d31
|
base_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
|
||||||
- platform: macos
|
- platform: macos
|
||||||
create_revision: efbf63d9c66b9f6ec30e9ad4611189aa80003d31
|
create_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
|
||||||
base_revision: efbf63d9c66b9f6ec30e9ad4611189aa80003d31
|
base_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
|
||||||
- platform: windows
|
- platform: windows
|
||||||
create_revision: efbf63d9c66b9f6ec30e9ad4611189aa80003d31
|
create_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
|
||||||
base_revision: efbf63d9c66b9f6ec30e9ad4611189aa80003d31
|
base_revision: b0366e0a3f089e15fd89c97604ab402fe26b724c
|
||||||
|
|
||||||
# User provided section
|
# User provided section
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools" package="hu.refilc.naplo">
|
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"
|
<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"
|
<activity android:exported="true" android:name="hu.refilc.naplo.MainActivity"
|
||||||
android:launchMode="singleTop" android:theme="@style/LaunchTheme"
|
android:launchMode="singleTop" android:theme="@style/LaunchTheme"
|
||||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||||
@ -13,6 +13,7 @@
|
|||||||
<meta-data android:name="io.flutter.embedding.android.NormalTheme"
|
<meta-data android:name="io.flutter.embedding.android.NormalTheme"
|
||||||
android:resource="@style/NormalTheme" />
|
android:resource="@style/NormalTheme" />
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
<!-- commented bc of dynamic app icons -->
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
@ -39,6 +40,69 @@
|
|||||||
</activity>
|
</activity>
|
||||||
<meta-data android:name="flutterEmbedding" android:value="2" />
|
<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"
|
<receiver android:name="hu.refilc.naplo.widget_timetable.WidgetTimetable"
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
Before Width: | Height: | Size: 185 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 185 KiB After Width: | Height: | Size: 13 KiB |
BIN
filcnaplo/assets/launch_icons/refilc_concept.png
Normal file
After Width: | Height: | Size: 145 KiB |
BIN
filcnaplo/assets/launch_icons/refilc_default.png
Normal file
After Width: | Height: | Size: 1.1 MiB |
BIN
filcnaplo/assets/launch_icons/refilc_overcomplicated.png
Normal file
After Width: | Height: | Size: 1.5 MiB |
BIN
filcnaplo/assets/launch_icons/refilc_pride.png
Normal file
After Width: | Height: | Size: 133 KiB |
@ -17,6 +17,14 @@
|
|||||||
3127F7A828EAEE8500C2EFB3 /* lesson_model.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3127F7A728EAEE8500C2EFB3 /* lesson_model.swift */; };
|
3127F7A828EAEE8500C2EFB3 /* lesson_model.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3127F7A728EAEE8500C2EFB3 /* lesson_model.swift */; };
|
||||||
373A6ECB5FC71FE9D8AF2EDB /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F0ADD56276103500A3016C8 /* Pods_Runner.framework */; };
|
373A6ECB5FC71FE9D8AF2EDB /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F0ADD56276103500A3016C8 /* Pods_Runner.framework */; };
|
||||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||||
|
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 */; };
|
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
||||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
||||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
707F8089D970F81C480F73C4 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
||||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
@ -122,6 +138,21 @@
|
|||||||
path = livecard;
|
path = livecard;
|
||||||
sourceTree = "<group>";
|
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 */ = {
|
6640A963014A9D4F31026053 /* Frameworks */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@ -178,6 +209,7 @@
|
|||||||
97C146F01CF9000F007C117D /* Runner */ = {
|
97C146F01CF9000F007C117D /* Runner */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
3B44611F2AE6DF7200AAE6FD /* App Icons */,
|
||||||
3127F73928EAEC3200C2EFB3 /* Runner.entitlements */,
|
3127F73928EAEC3200C2EFB3 /* Runner.entitlements */,
|
||||||
97C146FA1CF9000F007C117D /* Main.storyboard */,
|
97C146FA1CF9000F007C117D /* Main.storyboard */,
|
||||||
97C146FD1CF9000F007C117D /* Assets.xcassets */,
|
97C146FD1CF9000F007C117D /* Assets.xcassets */,
|
||||||
@ -286,10 +318,18 @@
|
|||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
3B44612A2AE6E0FF00AAE6FD /* refilc_concept@3x.png in Resources */,
|
||||||
|
3B44612F2AE6E0FF00AAE6FD /* refilc_pride@3x.png in Resources */,
|
||||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
|
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
|
||||||
|
3B44612E2AE6E0FF00AAE6FD /* refilc_pride@2x.png in Resources */,
|
||||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
|
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
|
||||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
|
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
|
||||||
97C146FC1CF9000F007C117D /* Main.storyboard 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;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
@ -2,6 +2,59 @@
|
|||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
|
<key>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>
|
<key>BGTaskSchedulerPermittedIdentifiers</key>
|
||||||
<array>
|
<array>
|
||||||
<string>com.transistorsoft.fetch</string>
|
<string>com.transistorsoft.fetch</string>
|
||||||
|
@ -163,6 +163,8 @@ Future loginAPI({
|
|||||||
Provider.of<ExamProvider>(context, listen: false).fetch(),
|
Provider.of<ExamProvider>(context, listen: false).fetch(),
|
||||||
Provider.of<HomeworkProvider>(context, listen: false).fetch(),
|
Provider.of<HomeworkProvider>(context, listen: false).fetch(),
|
||||||
Provider.of<MessageProvider>(context, listen: false).fetchAll(),
|
Provider.of<MessageProvider>(context, listen: false).fetchAll(),
|
||||||
|
Provider.of<MessageProvider>(context, listen: false)
|
||||||
|
.fetchAllRecipients(),
|
||||||
Provider.of<NoteProvider>(context, listen: false).fetch(),
|
Provider.of<NoteProvider>(context, listen: false).fetch(),
|
||||||
Provider.of<EventProvider>(context, listen: false).fetch(),
|
Provider.of<EventProvider>(context, listen: false).fetch(),
|
||||||
Provider.of<AbsenceProvider>(context, listen: false).fetch(),
|
Provider.of<AbsenceProvider>(context, listen: false).fetch(),
|
||||||
|
@ -34,7 +34,8 @@ Future<void> syncAll(BuildContext context) {
|
|||||||
print("INFO Syncing all");
|
print("INFO Syncing all");
|
||||||
|
|
||||||
UserProvider user = Provider.of<UserProvider>(context, listen: false);
|
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 = [];
|
List<Future<void>> tasks = [];
|
||||||
int taski = 0;
|
int taski = 0;
|
||||||
@ -47,10 +48,14 @@ Future<void> syncAll(BuildContext context) {
|
|||||||
|
|
||||||
tasks = [
|
tasks = [
|
||||||
syncStatus(Provider.of<GradeProvider>(context, listen: false).fetch()),
|
syncStatus(Provider.of<GradeProvider>(context, listen: false).fetch()),
|
||||||
syncStatus(Provider.of<TimetableProvider>(context, listen: false).fetch(week: Week.current())),
|
syncStatus(Provider.of<TimetableProvider>(context, listen: false)
|
||||||
|
.fetch(week: Week.current())),
|
||||||
syncStatus(Provider.of<ExamProvider>(context, listen: false).fetch()),
|
syncStatus(Provider.of<ExamProvider>(context, listen: false).fetch()),
|
||||||
syncStatus(Provider.of<HomeworkProvider>(context, listen: false).fetch(from: DateTime.now().subtract(const Duration(days: 30)))),
|
syncStatus(Provider.of<HomeworkProvider>(context, listen: false)
|
||||||
|
.fetch(from: DateTime.now().subtract(const Duration(days: 30)))),
|
||||||
syncStatus(Provider.of<MessageProvider>(context, listen: false).fetchAll()),
|
syncStatus(Provider.of<MessageProvider>(context, listen: false).fetchAll()),
|
||||||
|
syncStatus(
|
||||||
|
Provider.of<MessageProvider>(context, listen: false).fetchAllRecipients()),
|
||||||
syncStatus(Provider.of<NoteProvider>(context, listen: false).fetch()),
|
syncStatus(Provider.of<NoteProvider>(context, listen: false).fetch()),
|
||||||
syncStatus(Provider.of<EventProvider>(context, listen: false).fetch()),
|
syncStatus(Provider.of<EventProvider>(context, listen: false).fetch()),
|
||||||
syncStatus(Provider.of<AbsenceProvider>(context, listen: false).fetch()),
|
syncStatus(Provider.of<AbsenceProvider>(context, listen: false).fetch()),
|
||||||
@ -58,14 +63,17 @@ Future<void> syncAll(BuildContext context) {
|
|||||||
// Sync student
|
// Sync student
|
||||||
syncStatus(() async {
|
syncStatus(() async {
|
||||||
if (user.user == null) return;
|
if (user.user == null) return;
|
||||||
Map? studentJson = await Provider.of<KretaClient>(context, listen: false).getAPI(KretaAPI.student(user.instituteCode!));
|
Map? studentJson = await Provider.of<KretaClient>(context, listen: false)
|
||||||
|
.getAPI(KretaAPI.student(user.instituteCode!));
|
||||||
if (studentJson == null) return;
|
if (studentJson == null) return;
|
||||||
Student student = Student.fromJson(studentJson);
|
Student student = Student.fromJson(studentJson);
|
||||||
|
|
||||||
user.user?.name = student.name;
|
user.user?.name = student.name;
|
||||||
|
|
||||||
// Store user
|
// Store user
|
||||||
await Provider.of<DatabaseProvider>(context, listen: false).store.storeUser(user.user!);
|
await Provider.of<DatabaseProvider>(context, listen: false)
|
||||||
|
.store
|
||||||
|
.storeUser(user.user!);
|
||||||
}()),
|
}()),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
// ignore_for_file: deprecated_member_use
|
||||||
|
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:math';
|
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/client/client.dart';
|
||||||
import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
|
import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
|
||||||
import 'package:filcnaplo_premium/providers/goal_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/cupertino.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@ -62,11 +64,10 @@ class App extends StatelessWidget {
|
|||||||
final DatabaseProvider database;
|
final DatabaseProvider database;
|
||||||
|
|
||||||
const App(
|
const App(
|
||||||
{Key? key,
|
{super.key,
|
||||||
required this.database,
|
required this.database,
|
||||||
required this.settings,
|
required this.settings,
|
||||||
required this.user})
|
required this.user});
|
||||||
: super(key: key);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -34,7 +34,7 @@ const settingsDB = DatabaseStruct("settings", {
|
|||||||
"renamed_subjects_italics": int, "renamed_teachers_enabled": int,
|
"renamed_subjects_italics": int, "renamed_teachers_enabled": int,
|
||||||
"renamed_teachers_italics": int,
|
"renamed_teachers_italics": int,
|
||||||
"live_activity_color": String,
|
"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
|
// DON'T FORGET TO UPDATE DEFAULT VALUES IN `initDB` MIGRATION OR ELSE PARENTS WILL COMPLAIN ABOUT THEIR CHILDREN MISSING
|
||||||
// YOU'VE BEEN WARNED!!!
|
// YOU'VE BEEN WARNED!!!
|
||||||
@ -45,7 +45,7 @@ const usersDB = DatabaseStruct("users", {
|
|||||||
});
|
});
|
||||||
const userDataDB = DatabaseStruct("user_data", {
|
const userDataDB = DatabaseStruct("user_data", {
|
||||||
"id": String, "grades": String, "timetable": String, "exams": String,
|
"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,
|
"events": String, "absences": String, "group_averages": String,
|
||||||
// renamed subjects // non kreta data
|
// renamed subjects // non kreta data
|
||||||
"renamed_subjects": String,
|
"renamed_subjects": String,
|
||||||
@ -101,7 +101,8 @@ Future<Database> initDB(DatabaseProvider database) async {
|
|||||||
);
|
);
|
||||||
await migrateDB(db, struct: userDataDB, defaultValues: {
|
await migrateDB(db, struct: userDataDB, defaultValues: {
|
||||||
"grades": "[]", "timetable": "[]", "exams": "[]", "homework": "[]",
|
"grades": "[]", "timetable": "[]", "exams": "[]", "homework": "[]",
|
||||||
"messages": "[]", "notes": "[]", "events": "[]", "absences": "[]",
|
"messages": "[]", "recipients": "[]", "notes": "[]", "events": "[]",
|
||||||
|
"absences": "[]",
|
||||||
"group_averages": "[]",
|
"group_averages": "[]",
|
||||||
// renamed subjects // non kreta data
|
// renamed subjects // non kreta data
|
||||||
"renamed_subjects": "{}",
|
"renamed_subjects": "{}",
|
||||||
|
@ -122,6 +122,19 @@ class UserDatabaseQuery {
|
|||||||
return messages;
|
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 {
|
Future<List<Note>> getNotes({required String userId}) async {
|
||||||
List<Map> userData =
|
List<Map> userData =
|
||||||
await db.query("user_data", where: "id = ?", whereArgs: [userId]);
|
await db.query("user_data", where: "id = ?", whereArgs: [userId]);
|
||||||
|
@ -86,6 +86,13 @@ class UserDatabaseStore {
|
|||||||
where: "id = ?", whereArgs: [userId]);
|
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 {
|
Future<void> storeNotes(List<Note> notes, {required String userId}) async {
|
||||||
String notesJson = jsonEncode(notes.map((e) => e.json).toList());
|
String notesJson = jsonEncode(notes.map((e) => e.json).toList());
|
||||||
await db.update("user_data", {"notes": notesJson},
|
await db.update("user_data", {"notes": notesJson},
|
||||||
|
@ -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/attachment.dart';
|
||||||
import 'package:filcnaplo_kreta_api/models/homework.dart';
|
import 'package:filcnaplo_kreta_api/models/homework.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:open_file/open_file.dart';
|
import 'package:open_filex/open_filex.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
extension AttachmentHelper on Attachment {
|
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();
|
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 "";
|
if (!await StorageHelper.write("$downloads/$name", data)) return "";
|
||||||
|
|
||||||
return "$downloads/$name";
|
return "$downloads/$name";
|
||||||
@ -28,19 +32,24 @@ extension AttachmentHelper on Attachment {
|
|||||||
String downloads = await StorageHelper.downloadsPath();
|
String downloads = await StorageHelper.downloadsPath();
|
||||||
|
|
||||||
if (!await File("$downloads/$name").exists()) await download(context);
|
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;
|
return result.type == ResultType.done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension HomeworkAttachmentHelper on HomeworkAttachment {
|
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();
|
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 ?? "");
|
String url = downloadUrl(
|
||||||
Uint8List data = await Provider.of<KretaClient>(context, listen: false).getAPI(url, rawResponse: true);
|
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 "";
|
if (!await StorageHelper.write("$downloads/$name", data)) return "";
|
||||||
|
|
||||||
return "$downloads/$name";
|
return "$downloads/$name";
|
||||||
@ -50,7 +59,7 @@ extension HomeworkAttachmentHelper on HomeworkAttachment {
|
|||||||
String downloads = await StorageHelper.downloadsPath();
|
String downloads = await StorageHelper.downloadsPath();
|
||||||
|
|
||||||
if (!await File("$downloads/$name").exists()) await download(context);
|
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;
|
return result.type == ResultType.done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import 'dart:typed_data';
|
|||||||
import 'package:filcnaplo/api/client.dart';
|
import 'package:filcnaplo/api/client.dart';
|
||||||
import 'package:filcnaplo/helpers/storage_helper.dart';
|
import 'package:filcnaplo/helpers/storage_helper.dart';
|
||||||
import 'package:filcnaplo/models/release.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';
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
|
|
||||||
enum UpdateState { none, preparing, downloading, installing }
|
enum UpdateState { none, preparing, downloading, installing }
|
||||||
@ -37,7 +37,7 @@ extension UpdateHelper on Release {
|
|||||||
(await Permission.manageExternalStorage.request().isGranted &&
|
(await Permission.manageExternalStorage.request().isGranted &&
|
||||||
await Permission.requestInstallPackages.request().isGranted);
|
await Permission.requestInstallPackages.request().isGranted);
|
||||||
if (installPerms) {
|
if (installPerms) {
|
||||||
var result = await OpenFile.open(apk.path);
|
var result = await OpenFilex.open(apk.path);
|
||||||
|
|
||||||
if (result.type != ResultType.done) {
|
if (result.type != ResultType.done) {
|
||||||
// ignore: avoid_print
|
// ignore: avoid_print
|
||||||
|
@ -17,6 +17,7 @@ import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
|||||||
void main() async {
|
void main() async {
|
||||||
// Initalize
|
// Initalize
|
||||||
WidgetsBinding binding = WidgetsFlutterBinding.ensureInitialized();
|
WidgetsBinding binding = WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
// ignore: deprecated_member_use
|
||||||
binding.renderView.automaticSystemUiAdjustment = false;
|
binding.renderView.automaticSystemUiAdjustment = false;
|
||||||
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
||||||
// Startup
|
// Startup
|
||||||
@ -63,7 +64,7 @@ class Startup {
|
|||||||
await flutterLocalNotificationsPlugin
|
await flutterLocalNotificationsPlugin
|
||||||
.resolvePlatformSpecificImplementation<
|
.resolvePlatformSpecificImplementation<
|
||||||
AndroidFlutterLocalNotificationsPlugin>()!
|
AndroidFlutterLocalNotificationsPlugin>()!
|
||||||
.requestPermission();
|
.requestNotificationsPermission();
|
||||||
} else if (Platform.isIOS) {
|
} else if (Platform.isIOS) {
|
||||||
await flutterLocalNotificationsPlugin
|
await flutterLocalNotificationsPlugin
|
||||||
.resolvePlatformSpecificImplementation<
|
.resolvePlatformSpecificImplementation<
|
||||||
|
@ -79,6 +79,7 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
bool _renamedTeachersItalics;
|
bool _renamedTeachersItalics;
|
||||||
Color _liveActivityColor;
|
Color _liveActivityColor;
|
||||||
String _welcomeMessage;
|
String _welcomeMessage;
|
||||||
|
String _appIcon;
|
||||||
|
|
||||||
SettingsProvider({
|
SettingsProvider({
|
||||||
DatabaseProvider? database,
|
DatabaseProvider? database,
|
||||||
@ -126,6 +127,7 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
required bool renameTeachersItalics,
|
required bool renameTeachersItalics,
|
||||||
required Color liveActivityColor,
|
required Color liveActivityColor,
|
||||||
required String welcomeMessage,
|
required String welcomeMessage,
|
||||||
|
required String appIcon,
|
||||||
}) : _database = database,
|
}) : _database = database,
|
||||||
_language = language,
|
_language = language,
|
||||||
_startPage = startPage,
|
_startPage = startPage,
|
||||||
@ -170,7 +172,8 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
_renamedTeachersEnabled = renameTeachersEnabled,
|
_renamedTeachersEnabled = renameTeachersEnabled,
|
||||||
_renamedTeachersItalics = renameTeachersItalics,
|
_renamedTeachersItalics = renameTeachersItalics,
|
||||||
_liveActivityColor = liveActivityColor,
|
_liveActivityColor = liveActivityColor,
|
||||||
_welcomeMessage = welcomeMessage;
|
_welcomeMessage = welcomeMessage,
|
||||||
|
_appIcon = appIcon;
|
||||||
|
|
||||||
factory SettingsProvider.fromMap(Map map,
|
factory SettingsProvider.fromMap(Map map,
|
||||||
{required DatabaseProvider database}) {
|
{required DatabaseProvider database}) {
|
||||||
@ -235,6 +238,7 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
renameTeachersItalics: map["renamed_teachers_italics"] == 1,
|
renameTeachersItalics: map["renamed_teachers_italics"] == 1,
|
||||||
liveActivityColor: Color(map["live_activity_color"]),
|
liveActivityColor: Color(map["live_activity_color"]),
|
||||||
welcomeMessage: map["welcome_message"],
|
welcomeMessage: map["welcome_message"],
|
||||||
|
appIcon: map["app_icon"],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,6 +291,7 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
"renamed_teachers_italics": _renamedTeachersItalics ? 1 : 0,
|
"renamed_teachers_italics": _renamedTeachersItalics ? 1 : 0,
|
||||||
"live_activity_color": _liveActivityColor.value,
|
"live_activity_color": _liveActivityColor.value,
|
||||||
"welcome_message": _welcomeMessage,
|
"welcome_message": _welcomeMessage,
|
||||||
|
"app_icon": _appIcon,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -343,6 +348,7 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
renameTeachersItalics: false,
|
renameTeachersItalics: false,
|
||||||
liveActivityColor: const Color(0xFF676767),
|
liveActivityColor: const Color(0xFF676767),
|
||||||
welcomeMessage: '',
|
welcomeMessage: '',
|
||||||
|
appIcon: 'refilc_default',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -394,6 +400,7 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
bool get renamedTeachersItalics => _renamedTeachersItalics;
|
bool get renamedTeachersItalics => _renamedTeachersItalics;
|
||||||
Color get liveActivityColor => _liveActivityColor;
|
Color get liveActivityColor => _liveActivityColor;
|
||||||
String get welcomeMessage => _welcomeMessage;
|
String get welcomeMessage => _welcomeMessage;
|
||||||
|
String get appIcon => _appIcon;
|
||||||
|
|
||||||
Future<void> update({
|
Future<void> update({
|
||||||
bool store = true,
|
bool store = true,
|
||||||
@ -441,6 +448,7 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
bool? renamedTeachersItalics,
|
bool? renamedTeachersItalics,
|
||||||
Color? liveActivityColor,
|
Color? liveActivityColor,
|
||||||
String? welcomeMessage,
|
String? welcomeMessage,
|
||||||
|
String? appIcon,
|
||||||
}) async {
|
}) async {
|
||||||
if (language != null && language != _language) _language = language;
|
if (language != null && language != _language) _language = language;
|
||||||
if (startPage != null && startPage != _startPage) _startPage = startPage;
|
if (startPage != null && startPage != _startPage) _startPage = startPage;
|
||||||
@ -568,6 +576,10 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
if (welcomeMessage != null && welcomeMessage != _welcomeMessage) {
|
if (welcomeMessage != null && welcomeMessage != _welcomeMessage) {
|
||||||
_welcomeMessage = welcomeMessage;
|
_welcomeMessage = welcomeMessage;
|
||||||
}
|
}
|
||||||
|
if (appIcon != null && appIcon != _appIcon) {
|
||||||
|
_appIcon = appIcon;
|
||||||
|
}
|
||||||
|
// store or not
|
||||||
if (store) await _database?.store.storeSettings(this);
|
if (store) await _database?.store.storeSettings(this);
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ import 'package:provider/provider.dart';
|
|||||||
const List<FilterType> homeFilters = [
|
const List<FilterType> homeFilters = [
|
||||||
FilterType.all,
|
FilterType.all,
|
||||||
FilterType.grades,
|
FilterType.grades,
|
||||||
|
FilterType.exams,
|
||||||
FilterType.messages,
|
FilterType.messages,
|
||||||
FilterType.absences
|
FilterType.absences
|
||||||
];
|
];
|
||||||
|
@ -87,13 +87,13 @@ Widget _defaultItemBuilder(Color color, bool isCurrentColor, void Function() cha
|
|||||||
// The blocky color picker you can alter the layout and shape.
|
// The blocky color picker you can alter the layout and shape.
|
||||||
class BlockPicker extends StatefulWidget {
|
class BlockPicker extends StatefulWidget {
|
||||||
BlockPicker({
|
BlockPicker({
|
||||||
Key? key,
|
super.key,
|
||||||
required this.pickerColor,
|
required this.pickerColor,
|
||||||
required this.onColorChanged,
|
required this.onColorChanged,
|
||||||
this.useInShowDialog = true,
|
this.useInShowDialog = true,
|
||||||
this.layoutBuilder = _defaultLayoutBuilder,
|
this.layoutBuilder = _defaultLayoutBuilder,
|
||||||
this.itemBuilder = _defaultItemBuilder,
|
this.itemBuilder = _defaultItemBuilder,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
final Color? pickerColor;
|
final Color? pickerColor;
|
||||||
final ValueChanged<Color> onColorChanged;
|
final ValueChanged<Color> onColorChanged;
|
@ -7,16 +7,18 @@
|
|||||||
///
|
///
|
||||||
/// You can create your own layout by importing `picker.dart`.
|
/// You can create your own layout by importing `picker.dart`.
|
||||||
|
|
||||||
|
// ignore_for_file: use_build_context_synchronously
|
||||||
|
|
||||||
library hsv_picker;
|
library hsv_picker;
|
||||||
|
|
||||||
import 'package:filcnaplo/models/shared_theme.dart';
|
import 'package:filcnaplo/models/shared_theme.dart';
|
||||||
import 'package:filcnaplo_mobile_ui/common/custom_snack_bar.dart';
|
import 'package:filcnaplo_mobile_ui/common/custom_snack_bar.dart';
|
||||||
import 'package:filcnaplo_premium/providers/share_provider.dart';
|
import 'package:filcnaplo_kreta_api/providers/share_provider.dart';
|
||||||
import 'package:filcnaplo_premium/ui/mobile/flutter_colorpicker/block_picker.dart';
|
import 'package:filcnaplo/ui/flutter_colorpicker/block_picker.dart';
|
||||||
import 'package:filcnaplo_premium/ui/mobile/flutter_colorpicker/palette.dart';
|
import 'package:filcnaplo/ui/flutter_colorpicker/palette.dart';
|
||||||
import 'package:filcnaplo_premium/ui/mobile/flutter_colorpicker/utils.dart';
|
import 'package:filcnaplo/ui/flutter_colorpicker/utils.dart';
|
||||||
import 'package:filcnaplo_premium/ui/mobile/settings/theme.dart';
|
import 'package:filcnaplo_mobile_ui/screens/settings/theme_screen.dart';
|
||||||
import 'package:filcnaplo_premium/ui/mobile/settings/theme.i18n.dart';
|
import 'package:filcnaplo_mobile_ui/screens/settings/theme_screen.i18n.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:filcnaplo/theme/colors/colors.dart';
|
import 'package:filcnaplo/theme/colors/colors.dart';
|
||||||
@ -24,7 +26,7 @@ import 'package:provider/provider.dart';
|
|||||||
|
|
||||||
class FilcColorPicker extends StatefulWidget {
|
class FilcColorPicker extends StatefulWidget {
|
||||||
const FilcColorPicker({
|
const FilcColorPicker({
|
||||||
Key? key,
|
super.key,
|
||||||
required this.colorMode,
|
required this.colorMode,
|
||||||
required this.pickerColor,
|
required this.pickerColor,
|
||||||
required this.onColorChanged,
|
required this.onColorChanged,
|
||||||
@ -53,7 +55,7 @@ class FilcColorPicker extends StatefulWidget {
|
|||||||
this.colorHistory,
|
this.colorHistory,
|
||||||
this.onHistoryChanged,
|
this.onHistoryChanged,
|
||||||
required this.onThemeIdProvided,
|
required this.onThemeIdProvided,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
final CustomColorMode colorMode;
|
final CustomColorMode colorMode;
|
||||||
final Color pickerColor;
|
final Color pickerColor;
|
||||||
@ -78,10 +80,10 @@ class FilcColorPicker extends StatefulWidget {
|
|||||||
final void Function(SharedTheme theme) onThemeIdProvided;
|
final void Function(SharedTheme theme) onThemeIdProvided;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_FilcColorPickerState createState() => _FilcColorPickerState();
|
FilcColorPickerState createState() => FilcColorPickerState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _FilcColorPickerState extends State<FilcColorPicker> {
|
class FilcColorPickerState extends State<FilcColorPicker> {
|
||||||
final idController = TextEditingController();
|
final idController = TextEditingController();
|
||||||
|
|
||||||
late final ShareProvider shareProvider;
|
late final ShareProvider shareProvider;
|
@ -3,6 +3,7 @@
|
|||||||
// FROM: https://pub.dev/packages/flutter_colorpicker
|
// FROM: https://pub.dev/packages/flutter_colorpicker
|
||||||
// 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
|
/// The components of HSV Color Picker
|
||||||
///
|
///
|
||||||
/// Try to create a Color Picker with other layout on your own :)
|
/// Try to create a Color Picker with other layout on your own :)
|
||||||
@ -317,11 +318,11 @@ class ColorPickerInput extends StatefulWidget {
|
|||||||
const ColorPickerInput(
|
const ColorPickerInput(
|
||||||
this.color,
|
this.color,
|
||||||
this.onColorChanged, {
|
this.onColorChanged, {
|
||||||
Key? key,
|
super.key,
|
||||||
this.enableAlpha = true,
|
this.enableAlpha = true,
|
||||||
this.embeddedText = false,
|
this.embeddedText = false,
|
||||||
this.disable = false,
|
this.disable = false,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
final Color color;
|
final Color color;
|
||||||
final ValueChanged<Color> onColorChanged;
|
final ValueChanged<Color> onColorChanged;
|
||||||
@ -330,10 +331,10 @@ class ColorPickerInput extends StatefulWidget {
|
|||||||
final bool disable;
|
final bool disable;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_ColorPickerInputState createState() => _ColorPickerInputState();
|
ColorPickerInputState createState() => ColorPickerInputState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ColorPickerInputState extends State<ColorPickerInput> {
|
class ColorPickerInputState extends State<ColorPickerInput> {
|
||||||
TextEditingController textEditingController = TextEditingController();
|
TextEditingController textEditingController = TextEditingController();
|
||||||
int inputColor = 0;
|
int inputColor = 0;
|
||||||
|
|
||||||
@ -346,11 +347,7 @@ class _ColorPickerInputState extends State<ColorPickerInput> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (inputColor != widget.color.value) {
|
if (inputColor != widget.color.value) {
|
||||||
textEditingController.text = '#' +
|
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') : ''}';
|
||||||
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(
|
return Padding(
|
||||||
padding: const EdgeInsets.only(top: 6.0, left: 12.0, right: 12.0),
|
padding: const EdgeInsets.only(top: 6.0, left: 12.0, right: 12.0),
|
||||||
@ -516,10 +513,10 @@ class ColorPickerSlider extends StatelessWidget {
|
|||||||
this.onColorChanged,
|
this.onColorChanged,
|
||||||
this.onColorChangeEnd,
|
this.onColorChangeEnd,
|
||||||
this.onProblem, {
|
this.onProblem, {
|
||||||
Key? key,
|
super.key,
|
||||||
this.displayThumbColor = false,
|
this.displayThumbColor = false,
|
||||||
this.fullThumbColor = false,
|
this.fullThumbColor = false,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
final TrackType trackType;
|
final TrackType trackType;
|
||||||
final HSVColor hsvColor;
|
final HSVColor hsvColor;
|
||||||
@ -657,13 +654,13 @@ class ColorPickerSlider extends StatelessWidget {
|
|||||||
class ColorIndicator extends StatelessWidget {
|
class ColorIndicator extends StatelessWidget {
|
||||||
const ColorIndicator(
|
const ColorIndicator(
|
||||||
this.hsvColor, {
|
this.hsvColor, {
|
||||||
Key? key,
|
super.key,
|
||||||
this.currentHsvColor,
|
this.currentHsvColor,
|
||||||
this.icon,
|
this.icon,
|
||||||
this.width = 50.0,
|
this.width = 50.0,
|
||||||
this.height = 50.0,
|
this.height = 50.0,
|
||||||
this.adaptive = false,
|
this.adaptive = false,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
final HSVColor hsvColor;
|
final HSVColor hsvColor;
|
||||||
final HSVColor? currentHsvColor;
|
final HSVColor? currentHsvColor;
|
||||||
@ -711,8 +708,8 @@ class ColorPickerArea extends StatelessWidget {
|
|||||||
this.onColorChanged,
|
this.onColorChanged,
|
||||||
this.onChangeEnd,
|
this.onChangeEnd,
|
||||||
this.paletteType, {
|
this.paletteType, {
|
||||||
Key? key,
|
super.key,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
final HSVColor hsvColor;
|
final HSVColor hsvColor;
|
||||||
final ValueChanged<HSVColor> onColorChanged;
|
final ValueChanged<HSVColor> onColorChanged;
|
@ -3,6 +3,7 @@
|
|||||||
// FROM: https://pub.dev/packages/flutter_colorpicker
|
// FROM: https://pub.dev/packages/flutter_colorpicker
|
||||||
// FROM: https://pub.dev/packages/flutter_colorpicker
|
// FROM: https://pub.dev/packages/flutter_colorpicker
|
||||||
|
|
||||||
|
// ignore: dangling_library_doc_comments
|
||||||
/// Common function lib
|
/// Common function lib
|
||||||
|
|
||||||
import 'dart:math';
|
import 'dart:math';
|
@ -10,14 +10,20 @@ import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
|||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class GradeTile extends StatelessWidget {
|
class GradeTile extends StatelessWidget {
|
||||||
const GradeTile(this.grade,
|
const GradeTile(
|
||||||
{Key? key, this.onTap, this.padding, this.censored = false})
|
this.grade, {
|
||||||
: super(key: key);
|
super.key,
|
||||||
|
this.onTap,
|
||||||
|
this.padding,
|
||||||
|
this.censored = false,
|
||||||
|
this.viewOverride = false,
|
||||||
|
});
|
||||||
|
|
||||||
final Grade grade;
|
final Grade grade;
|
||||||
final void Function()? onTap;
|
final void Function()? onTap;
|
||||||
final EdgeInsetsGeometry? padding;
|
final EdgeInsetsGeometry? padding;
|
||||||
final bool censored;
|
final bool censored;
|
||||||
|
final bool viewOverride;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -26,7 +32,8 @@ class GradeTile extends StatelessWidget {
|
|||||||
bool isTitleItalic = false;
|
bool isTitleItalic = false;
|
||||||
bool isSubtitleItalic = false;
|
bool isSubtitleItalic = false;
|
||||||
EdgeInsets leadingPadding = EdgeInsets.zero;
|
EdgeInsets leadingPadding = EdgeInsets.zero;
|
||||||
bool isSubjectView = SubjectGradesContainer.of(context) != null;
|
bool isSubjectView =
|
||||||
|
SubjectGradesContainer.of(context) != null || viewOverride;
|
||||||
String subjectName =
|
String subjectName =
|
||||||
grade.subject.renamedTo ?? grade.subject.name.capital();
|
grade.subject.renamedTo ?? grade.subject.name.capital();
|
||||||
String modeDescription = grade.mode.description.capital();
|
String modeDescription = grade.mode.description.capital();
|
||||||
@ -187,7 +194,7 @@ class GradeTile extends StatelessWidget {
|
|||||||
class GradeValueWidget extends StatelessWidget {
|
class GradeValueWidget extends StatelessWidget {
|
||||||
const GradeValueWidget(
|
const GradeValueWidget(
|
||||||
this.value, {
|
this.value, {
|
||||||
Key? key,
|
super.key,
|
||||||
this.size = 38.0,
|
this.size = 38.0,
|
||||||
this.fill = false,
|
this.fill = false,
|
||||||
this.contrast = false,
|
this.contrast = false,
|
||||||
@ -196,7 +203,7 @@ class GradeValueWidget extends StatelessWidget {
|
|||||||
this.complemented = false,
|
this.complemented = false,
|
||||||
this.nocolor = false,
|
this.nocolor = false,
|
||||||
this.color,
|
this.color,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
final GradeValue value;
|
final GradeValue value;
|
||||||
final double size;
|
final double size;
|
||||||
|
@ -16,8 +16,7 @@ import 'package:provider/provider.dart';
|
|||||||
import 'lesson_tile.i18n.dart';
|
import 'lesson_tile.i18n.dart';
|
||||||
|
|
||||||
class LessonTile extends StatelessWidget {
|
class LessonTile extends StatelessWidget {
|
||||||
const LessonTile(this.lesson, {Key? key, this.onTap, this.swapDesc = false})
|
const LessonTile(this.lesson, {super.key, this.onTap, this.swapDesc = false});
|
||||||
: super(key: key);
|
|
||||||
|
|
||||||
final Lesson lesson;
|
final Lesson lesson;
|
||||||
final bool swapDesc;
|
final bool swapDesc;
|
||||||
@ -287,8 +286,7 @@ enum LessonSubtileType { homework, exam, absence }
|
|||||||
|
|
||||||
class LessonSubtile extends StatelessWidget {
|
class LessonSubtile extends StatelessWidget {
|
||||||
const LessonSubtile(
|
const LessonSubtile(
|
||||||
{Key? key, this.onPressed, required this.title, required this.type})
|
{super.key, this.onPressed, required this.title, required this.type});
|
||||||
: super(key: key);
|
|
||||||
|
|
||||||
final Function()? onPressed;
|
final Function()? onPressed;
|
||||||
final String title;
|
final String title;
|
||||||
|
@ -11,12 +11,12 @@ import 'package:provider/provider.dart';
|
|||||||
class MessageTile extends StatelessWidget {
|
class MessageTile extends StatelessWidget {
|
||||||
const MessageTile(
|
const MessageTile(
|
||||||
this.message, {
|
this.message, {
|
||||||
Key? key,
|
super.key,
|
||||||
this.messages,
|
this.messages,
|
||||||
this.padding,
|
this.padding,
|
||||||
this.onTap,
|
this.onTap,
|
||||||
this.censored = false,
|
this.censored = false,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
final Message message;
|
final Message message;
|
||||||
final List<Message>? messages;
|
final List<Message>? messages;
|
||||||
|
@ -3,7 +3,7 @@ description: "Nem hivatalos e-napló alkalmazás az e-Kréta rendszerhez"
|
|||||||
homepage: https://refilc.hu
|
homepage: https://refilc.hu
|
||||||
publish_to: "none"
|
publish_to: "none"
|
||||||
|
|
||||||
version: 4.4.0+233
|
version: 4.5.0+236
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.17.0 <3.0.0"
|
sdk: ">=2.17.0 <3.0.0"
|
||||||
@ -25,21 +25,22 @@ dependencies:
|
|||||||
|
|
||||||
flutter_localizations:
|
flutter_localizations:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
i18n_extension: ^9.0.0
|
i18n_extension: ^10.0.1
|
||||||
sqflite: ^2.2.0+2
|
sqflite: ^2.2.0+2
|
||||||
intl: ^0.18.0
|
intl: ^0.18.0
|
||||||
provider: ^5.0.0
|
provider: ^5.0.0
|
||||||
http: ^0.13.3
|
http: ^0.13.3
|
||||||
uuid: ^3.0.4
|
uuid: ^4.2.1
|
||||||
html: ^0.15.0
|
html: ^0.15.0
|
||||||
open_file:
|
open_filex: ^4.3.4
|
||||||
git:
|
# open_file:
|
||||||
url: https://github.com/crazecoder/open_file
|
# git:
|
||||||
ref: master
|
# url: https://github.com/crazecoder/open_file
|
||||||
|
# ref: master
|
||||||
path_provider: ^2.0.2
|
path_provider: ^2.0.2
|
||||||
permission_handler: ^10.2.0
|
permission_handler: ^11.0.1
|
||||||
share_plus: ^7.0.2
|
share_plus: ^7.0.2
|
||||||
connectivity_plus: ^4.0.1
|
connectivity_plus: ^5.0.2
|
||||||
flutter_displaymode: ^0.6.0
|
flutter_displaymode: ^0.6.0
|
||||||
quick_actions: ^1.0.1
|
quick_actions: ^1.0.1
|
||||||
animated_list_plus: ^0.5.0
|
animated_list_plus: ^0.5.0
|
||||||
@ -53,9 +54,9 @@ dependencies:
|
|||||||
lottie: ^1.4.3
|
lottie: ^1.4.3
|
||||||
rive: ^0.9.1
|
rive: ^0.9.1
|
||||||
animated_background: ^2.0.0
|
animated_background: ^2.0.0
|
||||||
dropdown_button2: ^1.8.9
|
dropdown_button2: ^1.9.4
|
||||||
home_widget: ^0.1.6
|
home_widget: ^0.1.6
|
||||||
flutter_expandable_fab: ^1.8.1
|
flutter_expandable_fab: ^2.0.0
|
||||||
uni_links: ^0.5.1
|
uni_links: ^0.5.1
|
||||||
url_launcher: ^6.1.6
|
url_launcher: ^6.1.6
|
||||||
workmanager: ^0.5.1
|
workmanager: ^0.5.1
|
||||||
@ -63,7 +64,7 @@ dependencies:
|
|||||||
image_picker: ^0.8.6
|
image_picker: ^0.8.6
|
||||||
animations: ^2.0.1
|
animations: ^2.0.1
|
||||||
background_fetch: ^1.1.5
|
background_fetch: ^1.1.5
|
||||||
flutter_local_notifications: ^14.1.0
|
flutter_local_notifications: ^16.2.0
|
||||||
package_info_plus: ^4.0.2
|
package_info_plus: ^4.0.2
|
||||||
screenshot: ^2.1.0
|
screenshot: ^2.1.0
|
||||||
flutter_staggered_grid_view: ^0.7.0
|
flutter_staggered_grid_view: ^0.7.0
|
||||||
@ -73,7 +74,7 @@ dependencies:
|
|||||||
url: https://github.com/kimaah/image_crop.git
|
url: https://github.com/kimaah/image_crop.git
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_lints: ^2.0.1
|
flutter_lints: ^3.0.1
|
||||||
flutter_launcher_icons: "^0.13.1"
|
flutter_launcher_icons: "^0.13.1"
|
||||||
flutter_native_splash: "^2.3.0"
|
flutter_native_splash: "^2.3.0"
|
||||||
sqflite_common_ffi: ^2.0.0+3
|
sqflite_common_ffi: ^2.0.0+3
|
||||||
@ -87,6 +88,7 @@ flutter:
|
|||||||
- assets/animations/
|
- assets/animations/
|
||||||
- assets/images/
|
- assets/images/
|
||||||
- assets/images/subject_covers/
|
- assets/images/subject_covers/
|
||||||
|
- assets/launch_icons/
|
||||||
|
|
||||||
fonts:
|
fonts:
|
||||||
- family: FilcIcons
|
- family: FilcIcons
|
||||||
|
@ -31,6 +31,11 @@ bool FlutterWindow::OnCreate() {
|
|||||||
this->Show();
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,19 +61,26 @@ class FilterBar extends StatelessWidget implements PreferredSizeWidget {
|
|||||||
// avoid fading over selected tab
|
// avoid fading over selected tab
|
||||||
return ShaderMask(
|
return ShaderMask(
|
||||||
shaderCallback: (Rect bounds) {
|
shaderCallback: (Rect bounds) {
|
||||||
final Color bg = Theme.of(context).scaffoldBackgroundColor;
|
final Color bg =
|
||||||
|
Theme.of(context).scaffoldBackgroundColor;
|
||||||
final double index = controller.animation!.value;
|
final double index = controller.animation!.value;
|
||||||
return LinearGradient(begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [
|
return LinearGradient(
|
||||||
index < 0.2 ? Colors.transparent : bg,
|
begin: Alignment.topLeft,
|
||||||
Colors.transparent,
|
end: Alignment.bottomRight,
|
||||||
Colors.transparent,
|
colors: [
|
||||||
index > controller.length - 1.2 ? Colors.transparent : bg
|
index < 0.2 ? Colors.transparent : bg,
|
||||||
], stops: const [
|
Colors.transparent,
|
||||||
0,
|
Colors.transparent,
|
||||||
0.1,
|
index > controller.length - 1.2
|
||||||
0.9,
|
? Colors.transparent
|
||||||
1
|
: bg
|
||||||
]).createShader(bounds);
|
],
|
||||||
|
stops: const [
|
||||||
|
0,
|
||||||
|
0.1,
|
||||||
|
0.9,
|
||||||
|
1
|
||||||
|
]).createShader(bounds);
|
||||||
},
|
},
|
||||||
blendMode: BlendMode.dstOut,
|
blendMode: BlendMode.dstOut,
|
||||||
child: child);
|
child: child);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:animations/animations.dart';
|
import 'package:animations/animations.dart';
|
||||||
|
import 'package:filcnaplo/models/settings.dart';
|
||||||
import 'package:filcnaplo/utils/format.dart';
|
import 'package:filcnaplo/utils/format.dart';
|
||||||
import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
|
import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
|
||||||
import 'package:filcnaplo/helpers/average_helper.dart';
|
import 'package:filcnaplo/helpers/average_helper.dart';
|
||||||
@ -56,6 +57,7 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
|
|||||||
// Providers
|
// Providers
|
||||||
late GradeProvider gradeProvider;
|
late GradeProvider gradeProvider;
|
||||||
late GradeCalculatorProvider calculatorProvider;
|
late GradeCalculatorProvider calculatorProvider;
|
||||||
|
late SettingsProvider settingsProvider;
|
||||||
|
|
||||||
late double average;
|
late double average;
|
||||||
late Widget gradeGraph;
|
late Widget gradeGraph;
|
||||||
@ -142,6 +144,7 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
gradeProvider = Provider.of<GradeProvider>(context);
|
gradeProvider = Provider.of<GradeProvider>(context);
|
||||||
calculatorProvider = Provider.of<GradeCalculatorProvider>(context);
|
calculatorProvider = Provider.of<GradeCalculatorProvider>(context);
|
||||||
|
settingsProvider = Provider.of<SettingsProvider>(context);
|
||||||
|
|
||||||
List<Grade> subjectGrades = getSubjectGrades(widget.subject).toList();
|
List<Grade> subjectGrades = getSubjectGrades(widget.subject).toList();
|
||||||
average = AverageHelper.averageEvals(subjectGrades);
|
average = AverageHelper.averageEvals(subjectGrades);
|
||||||
@ -244,7 +247,8 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
|
|||||||
subject: widget.subject, context: context),
|
subject: widget.subject, context: context),
|
||||||
scrollController: _scrollController,
|
scrollController: _scrollController,
|
||||||
title: widget.subject.renamedTo ?? widget.subject.name.capital(),
|
title: widget.subject.renamedTo ?? widget.subject.name.capital(),
|
||||||
italic: widget.subject.isRenamed,
|
italic: widget.subject.isRenamed &&
|
||||||
|
settingsProvider.renamedSubjectsItalics,
|
||||||
child: SubjectGradesContainer(
|
child: SubjectGradesContainer(
|
||||||
child: CupertinoScrollbar(
|
child: CupertinoScrollbar(
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
|
@ -21,7 +21,7 @@ import 'package:filcnaplo_desktop_ui/pages/grades/grade_subject_view.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:filcnaplo/helpers/average_helper.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';
|
import 'grades_page.i18n.dart';
|
||||||
|
|
||||||
class GradesPage extends StatefulWidget {
|
class GradesPage extends StatefulWidget {
|
||||||
@ -41,14 +41,15 @@ class _GradesPageState extends State<GradesPage> {
|
|||||||
|
|
||||||
int avgDropValue = 0;
|
int avgDropValue = 0;
|
||||||
|
|
||||||
List<Grade> getSubjectGrades(GradeSubject subject, {int days = 0}) => gradeProvider
|
List<Grade> getSubjectGrades(GradeSubject subject, {int days = 0}) =>
|
||||||
.grades
|
gradeProvider.grades
|
||||||
.where((e) =>
|
.where((e) =>
|
||||||
e.subject == subject &&
|
e.subject == subject &&
|
||||||
e.type == GradeType.midYear &&
|
e.type == GradeType.midYear &&
|
||||||
(days == 0 ||
|
(days == 0 ||
|
||||||
e.date.isBefore(DateTime.now().subtract(Duration(days: days)))))
|
e.date
|
||||||
.toList();
|
.isBefore(DateTime.now().subtract(Duration(days: days)))))
|
||||||
|
.toList();
|
||||||
|
|
||||||
void generateTiles() {
|
void generateTiles() {
|
||||||
List<GradeSubject> subjects = gradeProvider.grades
|
List<GradeSubject> subjects = gradeProvider.grades
|
||||||
@ -144,7 +145,8 @@ class _GradesPageState extends State<GradesPage> {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: StatisticsTile(
|
child: StatisticsTile(
|
||||||
outline: true,
|
outline: true,
|
||||||
title: AutoSizeText( // https://discord.com/channels/1111649116020285532/1153397476578050130
|
title: AutoSizeText(
|
||||||
|
// https://discord.com/channels/1111649116020285532/1153397476578050130
|
||||||
"classavg".i18n,
|
"classavg".i18n,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
@ -208,7 +210,7 @@ class _GradesPageState extends State<GradesPage> {
|
|||||||
title: Row(
|
title: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
PremiumAverageSelector(
|
AverageSelector(
|
||||||
value: avgDropValue,
|
value: avgDropValue,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
setState(() {
|
setState(() {
|
||||||
|
@ -57,9 +57,9 @@ class _LoginScreenState extends State<LoginScreen> {
|
|||||||
|
|
||||||
FilcAPI.getSchools().then((schools) {
|
FilcAPI.getSchools().then((schools) {
|
||||||
if (schools != null) {
|
if (schools != null) {
|
||||||
schoolController.update(() {
|
schoolController.update(() {
|
||||||
schoolController.schools = schools;
|
schoolController.schools = schools;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
ElegantNotification.error(
|
ElegantNotification.error(
|
||||||
background: Colors.white,
|
background: Colors.white,
|
||||||
@ -239,9 +239,9 @@ class _LoginScreenState extends State<LoginScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
SchoolInput(
|
SchoolInput(
|
||||||
scroll: _scrollController,
|
scroll: _scrollController,
|
||||||
controller: schoolController,
|
controller: schoolController,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -321,8 +321,8 @@ class _LoginScreenState extends State<LoginScreen> {
|
|||||||
|
|
||||||
if (username == "" ||
|
if (username == "" ||
|
||||||
password ==
|
password ==
|
||||||
"" /*||
|
"" ||
|
||||||
schoolController.selectedSchool == null*/
|
schoolController.selectedSchool == null
|
||||||
) {
|
) {
|
||||||
return setState(() => _loginState = LoginState.missingFields);
|
return setState(() => _loginState = LoginState.missingFields);
|
||||||
}
|
}
|
||||||
@ -332,8 +332,7 @@ class _LoginScreenState extends State<LoginScreen> {
|
|||||||
loginAPI(
|
loginAPI(
|
||||||
username: username,
|
username: username,
|
||||||
password: password,
|
password: password,
|
||||||
instituteCode: 'shit',
|
instituteCode: schoolController.selectedSchool!.instituteCode,
|
||||||
// instituteCode: schoolController.selectedSchool!.instituteCode,
|
|
||||||
context: context,
|
context: context,
|
||||||
onLogin: (user) {
|
onLogin: (user) {
|
||||||
ElegantNotification.success(
|
ElegantNotification.success(
|
||||||
|
@ -62,6 +62,8 @@ class _SidebarState extends State<Sidebar> {
|
|||||||
Provider.of<ExamProvider>(context, listen: false).restore(),
|
Provider.of<ExamProvider>(context, listen: false).restore(),
|
||||||
Provider.of<HomeworkProvider>(context, listen: false).restore(),
|
Provider.of<HomeworkProvider>(context, listen: false).restore(),
|
||||||
Provider.of<MessageProvider>(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<NoteProvider>(context, listen: false).restore(),
|
||||||
Provider.of<EventProvider>(context, listen: false).restore(),
|
Provider.of<EventProvider>(context, listen: false).restore(),
|
||||||
Provider.of<AbsenceProvider>(context, listen: false).restore(),
|
Provider.of<AbsenceProvider>(context, listen: false).restore(),
|
||||||
|
@ -38,8 +38,7 @@ import 'package:provider/provider.dart';
|
|||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
import 'settings_screen.i18n.dart';
|
import 'settings_screen.i18n.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:filcnaplo_premium/ui/mobile/settings/nickname.dart';
|
import 'package:filcnaplo_mobile_ui/screens/settings/user/nickname.dart';
|
||||||
import 'package:filcnaplo_premium/ui/mobile/settings/icon_pack.dart';
|
|
||||||
|
|
||||||
class SettingsScreen extends StatefulWidget {
|
class SettingsScreen extends StatefulWidget {
|
||||||
const SettingsScreen({Key? key}) : super(key: key);
|
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<ExamProvider>(context, listen: false).restore(),
|
||||||
Provider.of<HomeworkProvider>(context, listen: false).restore(),
|
Provider.of<HomeworkProvider>(context, listen: false).restore(),
|
||||||
Provider.of<MessageProvider>(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<NoteProvider>(context, listen: false).restore(),
|
||||||
Provider.of<EventProvider>(context, listen: false).restore(),
|
Provider.of<EventProvider>(context, listen: false).restore(),
|
||||||
Provider.of<AbsenceProvider>(context, listen: false).restore(),
|
Provider.of<AbsenceProvider>(context, listen: false).restore(),
|
||||||
@ -400,9 +401,9 @@ class _SettingsScreenState extends State<SettingsScreen>
|
|||||||
if (v) {
|
if (v) {
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) =>
|
builder: (context) => PopScope(
|
||||||
WillPopScope(
|
onPopInvoked: (didPop) =>
|
||||||
onWillPop: () async => false,
|
false,
|
||||||
child: AlertDialog(
|
child: AlertDialog(
|
||||||
shape:
|
shape:
|
||||||
RoundedRectangleBorder(
|
RoundedRectangleBorder(
|
||||||
@ -586,7 +587,8 @@ class _SettingsScreenState extends State<SettingsScreen>
|
|||||||
.secondary,
|
.secondary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const PremiumIconPackSelector(),
|
// we need icon pack selector here
|
||||||
|
// const PremiumIconPackSelector(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -21,23 +21,14 @@ class KretaAPI {
|
|||||||
static String groups(String iss) =>
|
static String groups(String iss) =>
|
||||||
BaseKreta.kreta(iss) + KretaApiEndpoints.groups;
|
BaseKreta.kreta(iss) + KretaApiEndpoints.groups;
|
||||||
static String groupAverages(String iss, String uid) =>
|
static String groupAverages(String iss, String uid) =>
|
||||||
BaseKreta.kreta(iss) +
|
"${BaseKreta.kreta(iss)}${KretaApiEndpoints.groupAverages}?oktatasiNevelesiFeladatUid=$uid";
|
||||||
KretaApiEndpoints.groupAverages +
|
|
||||||
"?oktatasiNevelesiFeladatUid=" +
|
|
||||||
uid;
|
|
||||||
static String averages(String iss, String uid) =>
|
static String averages(String iss, String uid) =>
|
||||||
BaseKreta.kreta(iss) +
|
"${BaseKreta.kreta(iss)}${KretaApiEndpoints.averages}?oktatasiNevelesiFeladatUid=$uid";
|
||||||
KretaApiEndpoints.averages +
|
|
||||||
"?oktatasiNevelesiFeladatUid=" +
|
|
||||||
uid;
|
|
||||||
static String timetable(String iss, {DateTime? start, DateTime? end}) =>
|
static String timetable(String iss, {DateTime? start, DateTime? end}) =>
|
||||||
BaseKreta.kreta(iss) +
|
BaseKreta.kreta(iss) +
|
||||||
KretaApiEndpoints.timetable +
|
KretaApiEndpoints.timetable +
|
||||||
(start != null && end != null
|
(start != null && end != null
|
||||||
? "?datumTol=" +
|
? "?datumTol=${start.toUtc().toIso8601String()}&datumIg=${end.toUtc().toIso8601String()}"
|
||||||
start.toUtc().toIso8601String() +
|
|
||||||
"&datumIg=" +
|
|
||||||
end.toUtc().toIso8601String()
|
|
||||||
: "");
|
: "");
|
||||||
static String exams(String iss) =>
|
static String exams(String iss) =>
|
||||||
BaseKreta.kreta(iss) + KretaApiEndpoints.exams;
|
BaseKreta.kreta(iss) + KretaApiEndpoints.exams;
|
||||||
@ -46,7 +37,7 @@ class KretaAPI {
|
|||||||
KretaApiEndpoints.homework +
|
KretaApiEndpoints.homework +
|
||||||
(id != null ? "/$id" : "") +
|
(id != null ? "/$id" : "") +
|
||||||
(id == null && start != null
|
(id == null && start != null
|
||||||
? "?datumTol=" + DateFormat('yyyy-MM-dd').format(start)
|
? "?datumTol=${DateFormat('yyyy-MM-dd').format(start)}"
|
||||||
: "");
|
: "");
|
||||||
static String capabilities(String iss) =>
|
static String capabilities(String iss) =>
|
||||||
BaseKreta.kreta(iss) + KretaApiEndpoints.capabilities;
|
BaseKreta.kreta(iss) + KretaApiEndpoints.capabilities;
|
||||||
@ -55,29 +46,27 @@ class KretaAPI {
|
|||||||
BaseKreta.kreta(iss) +
|
BaseKreta.kreta(iss) +
|
||||||
KretaApiEndpoints.downloadHomeworkAttachments(uid, type);
|
KretaApiEndpoints.downloadHomeworkAttachments(uid, type);
|
||||||
static String subjects(String iss, String uid) =>
|
static String subjects(String iss, String uid) =>
|
||||||
BaseKreta.kreta(iss) +
|
"${BaseKreta.kreta(iss)}${KretaApiEndpoints.subjects}?oktatasiNevelesiFeladatUid=$uid";
|
||||||
KretaApiEndpoints.subjects +
|
// Structure:
|
||||||
"?oktatasiNevelesiFeladatUid=" + uid;
|
// {
|
||||||
// Structure:
|
// "Uid": 000,
|
||||||
// {
|
// "Tantargy": {
|
||||||
// "Uid": 000,
|
// "Uid": 000,
|
||||||
// "Tantargy": {
|
// "Nev": "Irodalom",
|
||||||
// "Uid": 000,
|
// "Kategoria": {
|
||||||
// "Nev": "Irodalom",
|
// "Uid": "000,magyar_nyelv_es_irodalom",
|
||||||
// "Kategoria": {
|
// "Nev": "magyar_nyelv_es_irodalom",
|
||||||
// "Uid": "000,magyar_nyelv_es_irodalom",
|
// "Leiras": "Magyar nyelv és irodalom"
|
||||||
// "Nev": "magyar_nyelv_es_irodalom",
|
// },
|
||||||
// "Leiras": "Magyar nyelv és irodalom"
|
// "SortIndex": 0,
|
||||||
// },
|
// },
|
||||||
// "SortIndex": 0,
|
// "Atlag": null, // float
|
||||||
// },
|
// "AtlagAlakulasaIdoFuggvenyeben": Array[], // no idea what this is
|
||||||
// "Atlag": null, // float
|
// "SulyozottOsztalyzatOsszege": null, // int | float
|
||||||
// "AtlagAlakulasaIdoFuggvenyeben": Array[], // no idea what this is
|
// "SulyozottOsztalyzatSzama": null, // int | float
|
||||||
// "SulyozottOsztalyzatOsszege": null, // int | float
|
// "SortIndex": 0
|
||||||
// "SulyozottOsztalyzatSzama": null, // int | float
|
// }
|
||||||
// "SortIndex": 0
|
// refer to https://discord.com/channels/1111649116020285532/1111798771513303102/1148368925969612920
|
||||||
// }
|
|
||||||
// refer to https://discord.com/channels/1111649116020285532/1111798771513303102/1148368925969612920
|
|
||||||
|
|
||||||
// ADMIN API
|
// ADMIN API
|
||||||
static const sendMessage =
|
static const sendMessage =
|
||||||
@ -90,8 +79,10 @@ class KretaAPI {
|
|||||||
BaseKreta.kretaAdmin + KretaAdminEndpoints.recipientCategories;
|
BaseKreta.kretaAdmin + KretaAdminEndpoints.recipientCategories;
|
||||||
static const availableCategories =
|
static const availableCategories =
|
||||||
BaseKreta.kretaAdmin + KretaAdminEndpoints.availableCategories;
|
BaseKreta.kretaAdmin + KretaAdminEndpoints.availableCategories;
|
||||||
static const recipientsTeacher =
|
static const recipientTeachers =
|
||||||
BaseKreta.kretaAdmin + KretaAdminEndpoints.recipientsTeacher;
|
BaseKreta.kretaAdmin + KretaAdminEndpoints.recipientTeachers;
|
||||||
|
static const recipientDirectorate =
|
||||||
|
BaseKreta.kretaAdmin + KretaAdminEndpoints.recipientDirectorate;
|
||||||
static const uploadAttachment =
|
static const uploadAttachment =
|
||||||
BaseKreta.kretaAdmin + KretaAdminEndpoints.uploadAttachment;
|
BaseKreta.kretaAdmin + KretaAdminEndpoints.uploadAttachment;
|
||||||
static String downloadAttachment(String id) =>
|
static String downloadAttachment(String id) =>
|
||||||
@ -129,7 +120,8 @@ class KretaApiEndpoints {
|
|||||||
static const capabilities = "/ellenorzo/V3/Sajat/Intezmenyek";
|
static const capabilities = "/ellenorzo/V3/Sajat/Intezmenyek";
|
||||||
static String downloadHomeworkAttachments(String uid, String type) =>
|
static String downloadHomeworkAttachments(String uid, String type) =>
|
||||||
"/ellenorzo/V3/Sajat/Csatolmany/$uid";
|
"/ellenorzo/V3/Sajat/Csatolmany/$uid";
|
||||||
static const subjects = "/ellenorzo/V3/Sajat/Ertekelesek/Atlagok/TantargyiAtlagok";
|
static const subjects =
|
||||||
|
"/ellenorzo/V3/Sajat/Ertekelesek/Atlagok/TantargyiAtlagok";
|
||||||
}
|
}
|
||||||
|
|
||||||
class KretaAdminEndpoints {
|
class KretaAdminEndpoints {
|
||||||
@ -141,7 +133,8 @@ class KretaAdminEndpoints {
|
|||||||
"/api/v1/kommunikacio/postaladaelemek/$id";
|
"/api/v1/kommunikacio/postaladaelemek/$id";
|
||||||
static const recipientCategories = "/api/v1/adatszotarak/cimzetttipusok";
|
static const recipientCategories = "/api/v1/adatszotarak/cimzetttipusok";
|
||||||
static const availableCategories = "/api/v1/kommunikacio/cimezhetotipusok";
|
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 const uploadAttachment = "/ideiglenesfajlok";
|
||||||
static String downloadAttachment(String id) =>
|
static String downloadAttachment(String id) =>
|
||||||
"/api/v1/dokumentumok/uzenetek/$id";
|
"/api/v1/dokumentumok/uzenetek/$id";
|
||||||
|
@ -139,6 +139,9 @@ class KretaClient {
|
|||||||
if (!headerMap.containsKey("content-type")) {
|
if (!headerMap.containsKey("content-type")) {
|
||||||
headerMap["content-type"] = "application/json";
|
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);
|
res = await client.post(Uri.parse(url), headers: headerMap, body: body);
|
||||||
@ -153,6 +156,7 @@ class KretaClient {
|
|||||||
if (res == null) throw "Login error";
|
if (res == null) throw "Login error";
|
||||||
|
|
||||||
if (json) {
|
if (json) {
|
||||||
|
print(jsonDecode(res.body));
|
||||||
return jsonDecode(res.body);
|
return jsonDecode(res.body);
|
||||||
} else {
|
} else {
|
||||||
return res.body;
|
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 {
|
Future<void> refreshLogin() async {
|
||||||
if (_loginRefreshing) return;
|
if (_loginRefreshing) return;
|
||||||
_loginRefreshing = true;
|
_loginRefreshing = true;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// ignore_for_file: avoid_print
|
// ignore_for_file: avoid_print, use_build_context_synchronously
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
@ -154,9 +154,9 @@ class TimetableController extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < days.length; i++) {
|
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;
|
int minIndex = 0, maxIndex = 0;
|
||||||
|
|
||||||
if (lessonIndexes.isNotEmpty) {
|
if (lessonIndexes.isNotEmpty) {
|
||||||
@ -170,7 +170,7 @@ class TimetableController extends ChangeNotifier {
|
|||||||
// Fill missing indexes with empty spaces
|
// Fill missing indexes with empty spaces
|
||||||
for (var i in List<int>.generate(
|
for (var i in List<int>.generate(
|
||||||
maxIndex - minIndex + 1, (int i) => minIndex + i)) {
|
maxIndex - minIndex + 1, (int i) => minIndex + i)) {
|
||||||
List<Lesson> indexLessons = _getLessonsByIndex(_day, i);
|
List<Lesson> indexLessons = _getLessonsByIndex(day0, i);
|
||||||
|
|
||||||
// Empty lesson
|
// Empty lesson
|
||||||
if (indexLessons.isEmpty) {
|
if (indexLessons.isEmpty) {
|
||||||
@ -193,13 +193,13 @@ class TimetableController extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Additional lessons
|
// Additional lessons
|
||||||
day.addAll(_day.where((l) =>
|
day.addAll(day0.where((l) =>
|
||||||
int.tryParse(l.lessonIndex) == null && l.subject.id != ''));
|
int.tryParse(l.lessonIndex) == null && l.subject.id != ''));
|
||||||
|
|
||||||
day.sort((a, b) => a.start.compareTo(b.start));
|
day.sort((a, b) => a.start.compareTo(b.start));
|
||||||
|
|
||||||
// Special Dates
|
// Special Dates
|
||||||
for (var l in _day) {
|
for (var l in day0) {
|
||||||
l.subject.id == '' ? day.insert(0, l) : null;
|
l.subject.id == '' ? day.insert(0, l) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
// ignore_for_file: no_leading_underscores_for_local_identifiers
|
||||||
|
|
||||||
import 'package:filcnaplo/utils/format.dart';
|
import 'package:filcnaplo/utils/format.dart';
|
||||||
import 'category.dart';
|
import 'category.dart';
|
||||||
import 'subject.dart';
|
import 'subject.dart';
|
||||||
|
@ -68,13 +68,21 @@ class Message {
|
|||||||
messageId: message["azonosito"],
|
messageId: message["azonosito"],
|
||||||
seen: json["isElolvasva"] ?? false,
|
seen: json["isElolvasva"] ?? false,
|
||||||
deleted: json["isToroltElem"] ?? 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(),
|
author: (message["feladoNev"] ?? "").trim(),
|
||||||
content: message["szoveg"].replaceAll("\r", "") ?? "",
|
content: message["szoveg"].replaceAll("\r", "") ?? "",
|
||||||
subject: message["targy"] ?? "",
|
subject: message["targy"] ?? "",
|
||||||
type: type,
|
type: type,
|
||||||
recipients: (message["cimzettLista"] as List).cast<Map>().map((Map recipient) => Recipient.fromJson(recipient)).toList(),
|
recipients: (message["cimzettLista"] as List)
|
||||||
attachments: (message["csatolmanyok"] as List).cast<Map>().map((Map attachment) => Attachment.fromJson(attachment)).toList(),
|
.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"],
|
replyId: message["elozoUzenetAzonosito"],
|
||||||
conversationId: message["beszelgetesAzonosito"],
|
conversationId: message["beszelgetesAzonosito"],
|
||||||
json: json,
|
json: json,
|
||||||
@ -105,3 +113,100 @@ class Conversation {
|
|||||||
|
|
||||||
Message get newest => _messages.first;
|
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) {
|
||||||
|
print(json);
|
||||||
|
return SendRecipient(
|
||||||
|
id: int.parse(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 }
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
// ignore_for_file: no_leading_underscores_for_local_identifiers
|
||||||
|
|
||||||
import 'package:filcnaplo_kreta_api/controllers/timetable_controller.dart';
|
import 'package:filcnaplo_kreta_api/controllers/timetable_controller.dart';
|
||||||
|
|
||||||
class Week {
|
class Week {
|
||||||
|
@ -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/user_provider.dart';
|
||||||
import 'package:filcnaplo/api/providers/database_provider.dart';
|
import 'package:filcnaplo/api/providers/database_provider.dart';
|
||||||
import 'package:filcnaplo/models/user.dart';
|
import 'package:filcnaplo/models/user.dart';
|
||||||
@ -43,12 +45,14 @@ class AbsenceProvider with ChangeNotifier {
|
|||||||
(await _database.query.getSettings(_database)).renamedSubjectsEnabled
|
(await _database.query.getSettings(_database)).renamedSubjectsEnabled
|
||||||
? await _database.userQuery.renamedSubjects(
|
? await _database.userQuery.renamedSubjects(
|
||||||
userId:
|
userId:
|
||||||
|
// ignore: use_build_context_synchronously
|
||||||
Provider.of<UserProvider>(_context, listen: false).user!.id)
|
Provider.of<UserProvider>(_context, listen: false).user!.id)
|
||||||
: {};
|
: {};
|
||||||
Map<String, String> renamedTeachers =
|
Map<String, String> renamedTeachers =
|
||||||
(await _database.query.getSettings(_database)).renamedTeachersEnabled
|
(await _database.query.getSettings(_database)).renamedTeachersEnabled
|
||||||
? await _database.userQuery.renamedTeachers(
|
? await _database.userQuery.renamedTeachers(
|
||||||
userId:
|
userId:
|
||||||
|
// ignore: use_build_context_synchronously
|
||||||
Provider.of<UserProvider>(_context, listen: false).user!.id)
|
Provider.of<UserProvider>(_context, listen: false).user!.id)
|
||||||
: {};
|
: {};
|
||||||
|
|
||||||
|
@ -38,17 +38,19 @@ class ExamProvider with ChangeNotifier {
|
|||||||
|
|
||||||
// for renamed subjects
|
// for renamed subjects
|
||||||
Future<void> convertBySettings() async {
|
Future<void> convertBySettings() async {
|
||||||
final _database = Provider.of<DatabaseProvider>(_context, listen: false);
|
final database = Provider.of<DatabaseProvider>(_context, listen: false);
|
||||||
Map<String, String> renamedSubjects =
|
Map<String, String> renamedSubjects =
|
||||||
(await _database.query.getSettings(_database)).renamedSubjectsEnabled
|
(await database.query.getSettings(database)).renamedSubjectsEnabled
|
||||||
? await _database.userQuery.renamedSubjects(
|
? await database.userQuery.renamedSubjects(
|
||||||
userId:
|
userId:
|
||||||
|
// ignore: use_build_context_synchronously
|
||||||
Provider.of<UserProvider>(_context, listen: false).user!.id)
|
Provider.of<UserProvider>(_context, listen: false).user!.id)
|
||||||
: {};
|
: {};
|
||||||
Map<String, String> renamedTeachers =
|
Map<String, String> renamedTeachers =
|
||||||
(await _database.query.getSettings(_database)).renamedTeachersEnabled
|
(await database.query.getSettings(database)).renamedTeachersEnabled
|
||||||
? await _database.userQuery.renamedTeachers(
|
? await database.userQuery.renamedTeachers(
|
||||||
userId:
|
userId:
|
||||||
|
// ignore: use_build_context_synchronously
|
||||||
Provider.of<UserProvider>(_context, listen: false).user!.id)
|
Provider.of<UserProvider>(_context, listen: false).user!.id)
|
||||||
: {};
|
: {};
|
||||||
|
|
||||||
|
@ -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/user_provider.dart';
|
||||||
import 'package:filcnaplo/api/providers/database_provider.dart';
|
import 'package:filcnaplo/api/providers/database_provider.dart';
|
||||||
import 'package:filcnaplo/models/user.dart';
|
import 'package:filcnaplo/models/user.dart';
|
||||||
@ -9,17 +13,22 @@ import 'package:provider/provider.dart';
|
|||||||
|
|
||||||
class MessageProvider with ChangeNotifier {
|
class MessageProvider with ChangeNotifier {
|
||||||
late List<Message> _messages;
|
late List<Message> _messages;
|
||||||
|
late List<SendRecipient> _recipients;
|
||||||
late BuildContext _context;
|
late BuildContext _context;
|
||||||
|
|
||||||
List<Message> get messages => _messages;
|
List<Message> get messages => _messages;
|
||||||
|
List<SendRecipient> get recipients => _recipients;
|
||||||
|
|
||||||
MessageProvider({
|
MessageProvider({
|
||||||
List<Message> initialMessages = const [],
|
List<Message> initialMessages = const [],
|
||||||
required BuildContext context,
|
required BuildContext context,
|
||||||
}) {
|
}) {
|
||||||
_messages = List.castFrom(initialMessages);
|
_messages = List.castFrom(initialMessages);
|
||||||
|
_recipients = [];
|
||||||
_context = context;
|
_context = context;
|
||||||
|
|
||||||
if (_messages.isEmpty) restore();
|
if (_messages.isEmpty) restore();
|
||||||
|
if (_recipients.isEmpty) restoreRecipients();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> restore() async {
|
Future<void> restore() async {
|
||||||
@ -27,27 +36,33 @@ class MessageProvider with ChangeNotifier {
|
|||||||
|
|
||||||
// Load messages from the database
|
// Load messages from the database
|
||||||
if (userId != null) {
|
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;
|
_messages = dbMessages;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetches all types of Messages
|
// 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
|
// Fetches Messages from the Kreta API then stores them in the database
|
||||||
Future<void> fetch({MessageType type = MessageType.inbox}) async {
|
Future<void> fetch({MessageType type = MessageType.inbox}) async {
|
||||||
// Check Message Type
|
// Check Message Type
|
||||||
if (type == MessageType.draft) return;
|
if (type == MessageType.draft) return;
|
||||||
String messageType = ["beerkezett", "elkuldott", "torolt"].elementAt(type.index);
|
String messageType =
|
||||||
|
["beerkezett", "elkuldott", "torolt"].elementAt(type.index);
|
||||||
|
|
||||||
// Check User
|
// Check User
|
||||||
User? user = Provider.of<UserProvider>(_context, listen: false).user;
|
User? user = Provider.of<UserProvider>(_context, listen: false).user;
|
||||||
if (user == null) throw "Cannot fetch Messages for User null";
|
if (user == null) throw "Cannot fetch Messages for User null";
|
||||||
|
|
||||||
// Get messages
|
// 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}";
|
if (messagesJson == null) throw "Cannot fetch Messages for User ${user.id}";
|
||||||
|
|
||||||
// Parse messages
|
// Parse messages
|
||||||
@ -55,8 +70,12 @@ class MessageProvider with ChangeNotifier {
|
|||||||
await Future.wait(List.generate(messagesJson.length, (index) {
|
await Future.wait(List.generate(messagesJson.length, (index) {
|
||||||
return () async {
|
return () async {
|
||||||
Map message = messagesJson.cast<Map>()[index];
|
Map message = messagesJson.cast<Map>()[index];
|
||||||
Map? messageJson = await Provider.of<KretaClient>(_context, listen: false).getAPI(KretaAPI.message(message["azonosito"].toString()));
|
Map? messageJson =
|
||||||
if (messageJson != null) messages.add(Message.fromJson(messageJson, forceType: type));
|
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";
|
if (user == null) throw "Cannot store Messages for User null";
|
||||||
|
|
||||||
String userId = user.id;
|
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();
|
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';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,8 +65,14 @@ class TimetableProvider with ChangeNotifier {
|
|||||||
User? user = _user.user;
|
User? user = _user.user;
|
||||||
if (user == null) throw "Cannot fetch Lessons for User null";
|
if (user == null) throw "Cannot fetch Lessons for User null";
|
||||||
String iss = user.instituteCode;
|
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 (lessonsJson == null) {
|
||||||
if (kDebugMode) print('Cannot fetch Lessons for User ${user.id}');
|
if (kDebugMode) print('Cannot fetch Lessons for User ${user.id}');
|
||||||
|
@ -11,7 +11,10 @@ dependencies:
|
|||||||
path: ../filcnaplo/
|
path: ../filcnaplo/
|
||||||
http: ^0.13.3
|
http: ^0.13.3
|
||||||
provider: ^5.0.0
|
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:
|
dev_dependencies:
|
||||||
flutter_lints: ^1.0.0
|
flutter_lints: ^3.0.1
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class ActionButton extends StatelessWidget {
|
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 Color? activeColor;
|
||||||
final void Function()? onTap;
|
final void Function()? onTap;
|
||||||
|
@ -4,8 +4,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:i18n_extension/i18n_widget.dart';
|
import 'package:i18n_extension/i18n_widget.dart';
|
||||||
|
|
||||||
class AverageDisplay extends StatelessWidget {
|
class AverageDisplay extends StatelessWidget {
|
||||||
const AverageDisplay({Key? key, this.average = 0.0, this.border = false})
|
const AverageDisplay({super.key, this.average = 0.0, this.border = false});
|
||||||
: super(key: key);
|
|
||||||
|
|
||||||
final double average;
|
final double average;
|
||||||
final bool border;
|
final bool border;
|
||||||
|
@ -2,7 +2,7 @@ import 'package:filcnaplo/theme/colors/colors.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class BetaChip extends StatelessWidget {
|
class BetaChip extends StatelessWidget {
|
||||||
const BetaChip({Key? key, this.disabled = false}) : super(key: key);
|
const BetaChip({super.key, this.disabled = false});
|
||||||
|
|
||||||
final bool disabled;
|
final bool disabled;
|
||||||
|
|
||||||
@ -12,6 +12,12 @@ class BetaChip extends StatelessWidget {
|
|||||||
height: 25,
|
height: 25,
|
||||||
child: AnimatedContainer(
|
child: AnimatedContainer(
|
||||||
duration: const Duration(milliseconds: 200),
|
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(
|
child: Padding(
|
||||||
padding: const EdgeInsets.only(left: 8, right: 8),
|
padding: const EdgeInsets.only(left: 8, right: 8),
|
||||||
child: Center(
|
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),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ import 'package:filcnaplo/theme/colors/colors.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class BottomCard extends StatelessWidget {
|
class BottomCard extends StatelessWidget {
|
||||||
const BottomCard({Key? key, this.child}) : super(key: key);
|
const BottomCard({super.key, this.child});
|
||||||
|
|
||||||
final Widget? child;
|
final Widget? child;
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ import 'package:filcnaplo_mobile_ui/common/bottom_sheet_menu/rounded_bottom_shee
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class BottomSheetMenu extends StatelessWidget {
|
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;
|
final List<Widget> items;
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ import 'package:filcnaplo_mobile_ui/common/panel/panel_button.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class BottomSheetMenuItem extends StatelessWidget {
|
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 void Function()? onPressed;
|
||||||
final Widget? title;
|
final Widget? title;
|
||||||
|
@ -2,7 +2,7 @@ import 'package:filcnaplo/theme/colors/colors.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class RoundedBottomSheet extends StatelessWidget {
|
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 Widget? child;
|
||||||
final double borderRadius;
|
final double borderRadius;
|
||||||
|
@ -10,6 +10,7 @@ SnackBar CustomSnackBar({
|
|||||||
Duration? duration,
|
Duration? duration,
|
||||||
}) {
|
}) {
|
||||||
// backgroundColor > Brightness > Theme Background
|
// backgroundColor > Brightness > Theme Background
|
||||||
|
// ignore: no_leading_underscores_for_local_identifiers
|
||||||
Color _backgroundColor = backgroundColor ?? (AppColors.fromBrightness(brightness ?? Theme.of(context).brightness).highlight);
|
Color _backgroundColor = backgroundColor ?? (AppColors.fromBrightness(brightness ?? Theme.of(context).brightness).highlight);
|
||||||
Color textColor = AppColors.fromBrightness(brightness ?? Theme.of(context).brightness).text;
|
Color textColor = AppColors.fromBrightness(brightness ?? Theme.of(context).brightness).text;
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ import 'package:filcnaplo/theme/colors/colors.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class Detail extends StatelessWidget {
|
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 title;
|
||||||
final String description;
|
final String description;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class DialogButton extends StatelessWidget {
|
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 String label;
|
||||||
final Function()? onTap;
|
final Function()? onTap;
|
||||||
|
@ -4,7 +4,7 @@ class Dot extends StatelessWidget {
|
|||||||
final Color color;
|
final Color color;
|
||||||
final double size;
|
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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -17,7 +17,7 @@ List<String> faces = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
class Empty extends StatelessWidget {
|
class Empty extends StatelessWidget {
|
||||||
const Empty({Key? key, this.subtitle}) : super(key: key);
|
const Empty({super.key, this.subtitle});
|
||||||
|
|
||||||
final String? subtitle;
|
final String? subtitle;
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ class Empty extends StatelessWidget {
|
|||||||
children: subtitle != null
|
children: subtitle != null
|
||||||
? [
|
? [
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: "\n" + subtitle!,
|
text: "\n${subtitle!}",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 18.0,
|
fontSize: 18.0,
|
||||||
height: 2.0,
|
height: 2.0,
|
||||||
|
@ -5,7 +5,7 @@ import 'package:flutter/material.dart';
|
|||||||
|
|
||||||
class FilterBar extends StatefulWidget implements PreferredSizeWidget {
|
class FilterBar extends StatefulWidget implements PreferredSizeWidget {
|
||||||
const FilterBar({
|
const FilterBar({
|
||||||
Key? key,
|
super.key,
|
||||||
required this.items,
|
required this.items,
|
||||||
required this.controller,
|
required this.controller,
|
||||||
this.onTap,
|
this.onTap,
|
||||||
@ -13,8 +13,8 @@ class FilterBar extends StatefulWidget implements PreferredSizeWidget {
|
|||||||
this.disableFading = false,
|
this.disableFading = false,
|
||||||
this.scrollable = true,
|
this.scrollable = true,
|
||||||
this.censored = false,
|
this.censored = false,
|
||||||
}) : assert(items.length == controller.length),
|
this.tabAlignment = TabAlignment.start,
|
||||||
super(key: key);
|
}) : assert(items.length == controller.length);
|
||||||
|
|
||||||
final List<Widget> items;
|
final List<Widget> items;
|
||||||
final TabController controller;
|
final TabController controller;
|
||||||
@ -23,6 +23,7 @@ class FilterBar extends StatefulWidget implements PreferredSizeWidget {
|
|||||||
final bool disableFading;
|
final bool disableFading;
|
||||||
final bool scrollable;
|
final bool scrollable;
|
||||||
final bool censored;
|
final bool censored;
|
||||||
|
final TabAlignment tabAlignment;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
final Size preferredSize = const Size.fromHeight(42.0);
|
final Size preferredSize = const Size.fromHeight(42.0);
|
||||||
@ -37,7 +38,9 @@ class _FilterBarState extends State<FilterBar> {
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
censoredItemsWidth = List.generate(widget.items.length, (index) => 25 + Random().nextDouble() * 50).toList();
|
censoredItemsWidth = List.generate(
|
||||||
|
widget.items.length, (index) => 25 + Random().nextDouble() * 50)
|
||||||
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -67,18 +70,21 @@ class _FilterBarState extends State<FilterBar> {
|
|||||||
tabs: widget.censored
|
tabs: widget.censored
|
||||||
? censoredItemsWidth
|
? censoredItemsWidth
|
||||||
.map(
|
.map(
|
||||||
(e) => Container(
|
(e) => Tab(
|
||||||
width: e,
|
child: Container(
|
||||||
height: 15,
|
width: e,
|
||||||
decoration: BoxDecoration(
|
height: 15,
|
||||||
color: AppColors.of(context).text.withOpacity(.45),
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(8.0),
|
color: AppColors.of(context).text.withOpacity(.45),
|
||||||
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.toList()
|
.toList()
|
||||||
: widget.items,
|
: widget.items,
|
||||||
onTap: widget.onTap,
|
onTap: widget.onTap,
|
||||||
|
tabAlignment: widget.tabAlignment,
|
||||||
);
|
);
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
@ -93,19 +99,26 @@ class _FilterBarState extends State<FilterBar> {
|
|||||||
// avoid fading over selected tab
|
// avoid fading over selected tab
|
||||||
return ShaderMask(
|
return ShaderMask(
|
||||||
shaderCallback: (Rect bounds) {
|
shaderCallback: (Rect bounds) {
|
||||||
final Color bg = Theme.of(context).scaffoldBackgroundColor;
|
final Color bg =
|
||||||
|
Theme.of(context).scaffoldBackgroundColor;
|
||||||
final double index = widget.controller.animation!.value;
|
final double index = widget.controller.animation!.value;
|
||||||
return LinearGradient(begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [
|
return LinearGradient(
|
||||||
index < 0.2 ? Colors.transparent : bg,
|
begin: Alignment.topLeft,
|
||||||
Colors.transparent,
|
end: Alignment.bottomRight,
|
||||||
Colors.transparent,
|
colors: [
|
||||||
index > widget.controller.length - 1.2 ? Colors.transparent : bg
|
index < 0.2 ? Colors.transparent : bg,
|
||||||
], stops: const [
|
Colors.transparent,
|
||||||
0,
|
Colors.transparent,
|
||||||
0.1,
|
index > widget.controller.length - 1.2
|
||||||
0.9,
|
? Colors.transparent
|
||||||
1
|
: bg
|
||||||
]).createShader(bounds);
|
],
|
||||||
|
stops: const [
|
||||||
|
0,
|
||||||
|
0.1,
|
||||||
|
0.9,
|
||||||
|
1
|
||||||
|
]).createShader(bounds);
|
||||||
},
|
},
|
||||||
blendMode: BlendMode.dstOut,
|
blendMode: BlendMode.dstOut,
|
||||||
child: child);
|
child: child);
|
||||||
|
@ -4,7 +4,7 @@ import 'package:filcnaplo/utils/format.dart';
|
|||||||
|
|
||||||
class HeroScrollView extends StatefulWidget {
|
class HeroScrollView extends StatefulWidget {
|
||||||
const HeroScrollView(
|
const HeroScrollView(
|
||||||
{Key? key,
|
{super.key,
|
||||||
required this.child,
|
required this.child,
|
||||||
required this.title,
|
required this.title,
|
||||||
required this.icon,
|
required this.icon,
|
||||||
@ -12,8 +12,7 @@ class HeroScrollView extends StatefulWidget {
|
|||||||
this.navBarItems = const [],
|
this.navBarItems = const [],
|
||||||
this.onClose,
|
this.onClose,
|
||||||
this.iconSize = 64.0,
|
this.iconSize = 64.0,
|
||||||
this.scrollController})
|
this.scrollController});
|
||||||
: super(key: key);
|
|
||||||
|
|
||||||
final Widget child;
|
final Widget child;
|
||||||
final String title;
|
final String title;
|
||||||
@ -25,10 +24,10 @@ class HeroScrollView extends StatefulWidget {
|
|||||||
final bool italic;
|
final bool italic;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_HeroScrollViewState createState() => _HeroScrollViewState();
|
HeroScrollViewState createState() => HeroScrollViewState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _HeroScrollViewState extends State<HeroScrollView> {
|
class HeroScrollViewState extends State<HeroScrollView> {
|
||||||
late ScrollController _scrollController;
|
late ScrollController _scrollController;
|
||||||
|
|
||||||
bool showBarTitle = false;
|
bool showBarTitle = false;
|
||||||
@ -69,6 +68,7 @@ class _HeroScrollViewState extends State<HeroScrollView> {
|
|||||||
surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
|
surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
|
||||||
title: AnimatedOpacity(
|
title: AnimatedOpacity(
|
||||||
opacity: showBarTitle ? 1.0 : 0.0,
|
opacity: showBarTitle ? 1.0 : 0.0,
|
||||||
|
duration: const Duration(milliseconds: 200),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Icon(widget.icon,
|
Icon(widget.icon,
|
||||||
@ -86,8 +86,7 @@ class _HeroScrollViewState extends State<HeroScrollView> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
)),
|
||||||
duration: const Duration(milliseconds: 200)),
|
|
||||||
leading: BackButton(
|
leading: BackButton(
|
||||||
color: AppColors.of(context).text,
|
color: AppColors.of(context).text,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
|
@ -4,11 +4,11 @@ import 'package:flutter/material.dart';
|
|||||||
|
|
||||||
class MaterialActionButton extends StatelessWidget {
|
class MaterialActionButton extends StatelessWidget {
|
||||||
const MaterialActionButton({
|
const MaterialActionButton({
|
||||||
Key? key,
|
super.key,
|
||||||
required this.child,
|
required this.child,
|
||||||
this.onPressed,
|
this.onPressed,
|
||||||
this.backgroundColor,
|
this.backgroundColor,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
final Widget child;
|
final Widget child;
|
||||||
final Function()? onPressed;
|
final Function()? onPressed;
|
||||||
@ -19,17 +19,17 @@ class MaterialActionButton extends StatelessWidget {
|
|||||||
return RawMaterialButton(
|
return RawMaterialButton(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||||
shape: const StadiumBorder(),
|
shape: const StadiumBorder(),
|
||||||
child: DefaultTextStyle(
|
|
||||||
child: child,
|
|
||||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
color: backgroundColor != null ? ColorUtils.foregroundColor(backgroundColor!) : null,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
fillColor: backgroundColor ?? AppColors.of(context).text.withOpacity(.15),
|
fillColor: backgroundColor ?? AppColors.of(context).text.withOpacity(.15),
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
highlightElevation: 0,
|
highlightElevation: 0,
|
||||||
onPressed: onPressed,
|
onPressed: onPressed,
|
||||||
|
child: DefaultTextStyle(
|
||||||
|
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: backgroundColor != null ? ColorUtils.foregroundColor(backgroundColor!) : null,
|
||||||
|
),
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ import 'package:filcnaplo/theme/colors/colors.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class NewContentIndicator extends StatelessWidget {
|
class NewContentIndicator extends StatelessWidget {
|
||||||
const NewContentIndicator({Key? key, this.size = 64.0}) : super(key: key);
|
const NewContentIndicator({super.key, this.size = 64.0});
|
||||||
|
|
||||||
final double size;
|
final double size;
|
||||||
|
|
||||||
|
@ -5,8 +5,7 @@ import 'package:provider/provider.dart';
|
|||||||
|
|
||||||
class Panel extends StatelessWidget {
|
class Panel extends StatelessWidget {
|
||||||
const Panel(
|
const Panel(
|
||||||
{Key? key, this.child, this.title, this.padding, this.hasShadow = true})
|
{super.key, this.child, this.title, this.padding, this.hasShadow = true});
|
||||||
: super(key: key);
|
|
||||||
|
|
||||||
final Widget? child;
|
final Widget? child;
|
||||||
final Widget? title;
|
final Widget? title;
|
||||||
@ -48,7 +47,7 @@ class Panel extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class PanelTitle extends StatelessWidget {
|
class PanelTitle extends StatelessWidget {
|
||||||
const PanelTitle({Key? key, required this.title}) : super(key: key);
|
const PanelTitle({super.key, required this.title});
|
||||||
|
|
||||||
final Widget title;
|
final Widget title;
|
||||||
|
|
||||||
@ -67,7 +66,7 @@ class PanelTitle extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class PanelHeader extends StatelessWidget {
|
class PanelHeader extends StatelessWidget {
|
||||||
const PanelHeader({Key? key, required this.padding}) : super(key: key);
|
const PanelHeader({super.key, required this.padding});
|
||||||
|
|
||||||
final EdgeInsetsGeometry padding;
|
final EdgeInsetsGeometry padding;
|
||||||
|
|
||||||
@ -95,7 +94,7 @@ class PanelHeader extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class PanelBody extends StatelessWidget {
|
class PanelBody extends StatelessWidget {
|
||||||
const PanelBody({Key? key, this.child, this.padding}) : super(key: key);
|
const PanelBody({super.key, this.child, this.padding});
|
||||||
|
|
||||||
final Widget? child;
|
final Widget? child;
|
||||||
final EdgeInsetsGeometry? padding;
|
final EdgeInsetsGeometry? padding;
|
||||||
@ -123,7 +122,7 @@ class PanelBody extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class PanelFooter extends StatelessWidget {
|
class PanelFooter extends StatelessWidget {
|
||||||
const PanelFooter({Key? key, required this.padding}) : super(key: key);
|
const PanelFooter({super.key, required this.padding});
|
||||||
|
|
||||||
final EdgeInsetsGeometry padding;
|
final EdgeInsetsGeometry padding;
|
||||||
|
|
||||||
|
@ -2,13 +2,13 @@ import 'package:flutter/material.dart';
|
|||||||
|
|
||||||
class PanelActionButton extends StatelessWidget {
|
class PanelActionButton extends StatelessWidget {
|
||||||
const PanelActionButton({
|
const PanelActionButton({
|
||||||
Key? key,
|
super.key,
|
||||||
this.onPressed,
|
this.onPressed,
|
||||||
this.padding = const EdgeInsets.symmetric(horizontal: 14.0),
|
this.padding = const EdgeInsets.symmetric(horizontal: 14.0),
|
||||||
this.leading,
|
this.leading,
|
||||||
this.title,
|
this.title,
|
||||||
this.trailing,
|
this.trailing,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
final void Function()? onPressed;
|
final void Function()? onPressed;
|
||||||
final EdgeInsetsGeometry padding;
|
final EdgeInsetsGeometry padding;
|
||||||
|
@ -5,7 +5,7 @@ import 'package:flutter/material.dart';
|
|||||||
|
|
||||||
class PanelButton extends StatelessWidget {
|
class PanelButton extends StatelessWidget {
|
||||||
const PanelButton({
|
const PanelButton({
|
||||||
Key? key,
|
super.key,
|
||||||
this.onPressed,
|
this.onPressed,
|
||||||
this.padding = const EdgeInsets.symmetric(horizontal: 14.0),
|
this.padding = const EdgeInsets.symmetric(horizontal: 14.0),
|
||||||
this.leading,
|
this.leading,
|
||||||
@ -13,7 +13,7 @@ class PanelButton extends StatelessWidget {
|
|||||||
this.trailing,
|
this.trailing,
|
||||||
this.background = false,
|
this.background = false,
|
||||||
this.trailingDivider = false,
|
this.trailingDivider = false,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
final void Function()? onPressed;
|
final void Function()? onPressed;
|
||||||
final EdgeInsetsGeometry padding;
|
final EdgeInsetsGeometry padding;
|
||||||
|
@ -5,9 +5,9 @@ import 'package:provider/provider.dart';
|
|||||||
|
|
||||||
class EmptyCard extends StatefulWidget {
|
class EmptyCard extends StatefulWidget {
|
||||||
const EmptyCard({
|
const EmptyCard({
|
||||||
Key? key,
|
super.key,
|
||||||
required this.text,
|
required this.text,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
final String text;
|
final String text;
|
||||||
|
|
||||||
|
@ -18,9 +18,9 @@ import 'personality_card.i18n.dart';
|
|||||||
|
|
||||||
class PersonalityCard extends StatefulWidget {
|
class PersonalityCard extends StatefulWidget {
|
||||||
const PersonalityCard({
|
const PersonalityCard({
|
||||||
Key? key,
|
super.key,
|
||||||
required this.user,
|
required this.user,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
final UserProvider user;
|
final UserProvider user;
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ import 'package:provider/provider.dart';
|
|||||||
import 'package:wtf_sliding_sheet/wtf_sliding_sheet.dart';
|
import 'package:wtf_sliding_sheet/wtf_sliding_sheet.dart';
|
||||||
|
|
||||||
class ProfileButton extends StatelessWidget {
|
class ProfileButton extends StatelessWidget {
|
||||||
const ProfileButton({Key? key, required this.child}) : super(key: key);
|
const ProfileButton({super.key, required this.child});
|
||||||
|
|
||||||
final ProfileImage child;
|
final ProfileImage child;
|
||||||
|
|
||||||
@ -35,6 +35,8 @@ class ProfileButton extends StatelessWidget {
|
|||||||
Provider.of<ExamProvider>(context, listen: false).restore(),
|
Provider.of<ExamProvider>(context, listen: false).restore(),
|
||||||
Provider.of<HomeworkProvider>(context, listen: false).restore(),
|
Provider.of<HomeworkProvider>(context, listen: false).restore(),
|
||||||
Provider.of<MessageProvider>(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<NoteProvider>(context, listen: false).restore(),
|
||||||
Provider.of<EventProvider>(context, listen: false).restore(),
|
Provider.of<EventProvider>(context, listen: false).restore(),
|
||||||
Provider.of<AbsenceProvider>(context, listen: false).restore(),
|
Provider.of<AbsenceProvider>(context, listen: false).restore(),
|
||||||
|
@ -8,7 +8,7 @@ import 'package:filcnaplo/utils/color.dart';
|
|||||||
|
|
||||||
class ProfileImage extends StatefulWidget {
|
class ProfileImage extends StatefulWidget {
|
||||||
const ProfileImage({
|
const ProfileImage({
|
||||||
Key? key,
|
super.key,
|
||||||
this.onTap,
|
this.onTap,
|
||||||
this.onDoubleTap,
|
this.onDoubleTap,
|
||||||
this.onLongPress,
|
this.onLongPress,
|
||||||
@ -20,7 +20,7 @@ class ProfileImage extends StatefulWidget {
|
|||||||
this.role = Role.student,
|
this.role = Role.student,
|
||||||
this.censored = false,
|
this.censored = false,
|
||||||
this.profilePictureString = "",
|
this.profilePictureString = "",
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
final void Function()? onTap;
|
final void Function()? onTap;
|
||||||
final void Function()? onDoubleTap;
|
final void Function()? onDoubleTap;
|
||||||
@ -176,7 +176,7 @@ class _ProfileImageState extends State<ProfileImage> {
|
|||||||
children: [
|
children: [
|
||||||
if (widget.name != null && (widget.name?.trim().length ?? 0) > 0)
|
if (widget.name != null && (widget.name?.trim().length ?? 0) > 0)
|
||||||
Hero(
|
Hero(
|
||||||
tag: widget.heroTag! + "background",
|
tag: "${widget.heroTag!}background",
|
||||||
transitionOnUserGestures: true,
|
transitionOnUserGestures: true,
|
||||||
child: Material(
|
child: Material(
|
||||||
clipBehavior: Clip.hardEdge,
|
clipBehavior: Clip.hardEdge,
|
||||||
@ -197,27 +197,27 @@ class _ProfileImageState extends State<ProfileImage> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
Hero(
|
Hero(
|
||||||
tag: widget.heroTag! + "child",
|
tag: "${widget.heroTag!}child",
|
||||||
transitionOnUserGestures: true,
|
transitionOnUserGestures: true,
|
||||||
child: Material(
|
child: Material(
|
||||||
clipBehavior: Clip.hardEdge,
|
clipBehavior: Clip.hardEdge,
|
||||||
shape: profilePicture != null ? const CircleBorder() : null,
|
shape: profilePicture != null ? const CircleBorder() : null,
|
||||||
child: profilePicture ?? child,
|
|
||||||
type: MaterialType.transparency,
|
type: MaterialType.transparency,
|
||||||
|
child: profilePicture ?? child,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
// Badge
|
// Badge
|
||||||
if (widget.badge)
|
if (widget.badge)
|
||||||
Hero(
|
Hero(
|
||||||
tag: widget.heroTag! + "new_content_indicator",
|
tag: "${widget.heroTag!}new_content_indicator",
|
||||||
child: NewContentIndicator(size: widget.radius * 2),
|
child: NewContentIndicator(size: widget.radius * 2),
|
||||||
),
|
),
|
||||||
|
|
||||||
// Role indicator
|
// Role indicator
|
||||||
if (widget.role == Role.parent)
|
if (widget.role == Role.parent)
|
||||||
Hero(
|
Hero(
|
||||||
tag: widget.heroTag! + "role_indicator",
|
tag: "${widget.heroTag!}role_indicator",
|
||||||
child: FittedBox(
|
child: FittedBox(
|
||||||
fit: BoxFit.fitHeight,
|
fit: BoxFit.fitHeight,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
|
@ -2,8 +2,7 @@ import 'package:flutter/material.dart';
|
|||||||
|
|
||||||
class ProgressBar extends StatelessWidget {
|
class ProgressBar extends StatelessWidget {
|
||||||
const ProgressBar(
|
const ProgressBar(
|
||||||
{Key? key, required this.value, this.backgroundColor, this.height = 8.0})
|
{super.key, required this.value, this.backgroundColor, this.height = 8.0});
|
||||||
: super(key: key);
|
|
||||||
|
|
||||||
final double value;
|
final double value;
|
||||||
final Color? backgroundColor;
|
final Color? backgroundColor;
|
||||||
|
@ -7,12 +7,11 @@ class RoundBorderIcon extends StatelessWidget {
|
|||||||
final Widget icon;
|
final Widget icon;
|
||||||
|
|
||||||
const RoundBorderIcon(
|
const RoundBorderIcon(
|
||||||
{Key? key,
|
{super.key,
|
||||||
this.color = Colors.black,
|
this.color = Colors.black,
|
||||||
this.width = 1.5,
|
this.width = 1.5,
|
||||||
this.padding = 5.0,
|
this.padding = 5.0,
|
||||||
required this.icon})
|
required this.icon});
|
||||||
: super(key: key);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -3,7 +3,7 @@ import 'package:filcnaplo_mobile_ui/common/soon_alert/soon_alert.i18n.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class SoonAlert extends StatelessWidget {
|
class SoonAlert extends StatelessWidget {
|
||||||
const SoonAlert({Key? key}) : super(key: key);
|
const SoonAlert({super.key});
|
||||||
|
|
||||||
static show({required BuildContext context}) =>
|
static show({required BuildContext context}) =>
|
||||||
showDialog(context: context, builder: (context) => const SoonAlert());
|
showDialog(context: context, builder: (context) => const SoonAlert());
|
||||||
|
@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:i18n_extension/i18n_widget.dart';
|
import 'package:i18n_extension/i18n_widget.dart';
|
||||||
|
|
||||||
class TrendDisplay<T extends num> extends StatelessWidget {
|
class TrendDisplay<T extends num> extends StatelessWidget {
|
||||||
const TrendDisplay({Key? key, required this.current, required this.previous, this.padding}) : super(key: key);
|
const TrendDisplay({super.key, required this.current, required this.previous, this.padding});
|
||||||
|
|
||||||
final T current;
|
final T current;
|
||||||
final T previous;
|
final T previous;
|
||||||
|
@ -59,12 +59,12 @@ enum _ViewableLocation {
|
|||||||
|
|
||||||
class Viewable extends StatefulWidget {
|
class Viewable extends StatefulWidget {
|
||||||
const Viewable({
|
const Viewable({
|
||||||
Key? key,
|
super.key,
|
||||||
required this.view,
|
required this.view,
|
||||||
required this.tile,
|
required this.tile,
|
||||||
this.actions = const [],
|
this.actions = const [],
|
||||||
this.previewBuilder,
|
this.previewBuilder,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
final Widget tile;
|
final Widget tile;
|
||||||
final Widget view;
|
final Widget view;
|
||||||
@ -255,12 +255,11 @@ class _ViewableState extends State<Viewable> with TickerProviderStateMixin {
|
|||||||
|
|
||||||
class _DecoyChild extends StatefulWidget {
|
class _DecoyChild extends StatefulWidget {
|
||||||
const _DecoyChild({
|
const _DecoyChild({
|
||||||
Key? key,
|
|
||||||
this.beginRect,
|
this.beginRect,
|
||||||
required this.controller,
|
required this.controller,
|
||||||
this.endRect,
|
this.endRect,
|
||||||
this.child,
|
this.child,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
final Rect? beginRect;
|
final Rect? beginRect;
|
||||||
final AnimationController controller;
|
final AnimationController controller;
|
||||||
@ -364,17 +363,13 @@ class _ViewableRoute<T> extends PopupRoute<T> {
|
|||||||
required _ViewableLocation contextMenuLocation,
|
required _ViewableLocation contextMenuLocation,
|
||||||
this.barrierLabel,
|
this.barrierLabel,
|
||||||
_ViewablePreviewBuilderChildless? builder,
|
_ViewablePreviewBuilderChildless? builder,
|
||||||
ui.ImageFilter? filter,
|
super.filter,
|
||||||
required Rect previousChildRect,
|
required Rect previousChildRect,
|
||||||
RouteSettings? settings,
|
super.settings,
|
||||||
}) : _actions = actions,
|
}) : _actions = actions,
|
||||||
_builder = builder,
|
_builder = builder,
|
||||||
_contextMenuLocation = contextMenuLocation,
|
_contextMenuLocation = contextMenuLocation,
|
||||||
_previousChildRect = previousChildRect,
|
_previousChildRect = previousChildRect;
|
||||||
super(
|
|
||||||
filter: filter,
|
|
||||||
settings: settings,
|
|
||||||
);
|
|
||||||
|
|
||||||
static const Color _kModalBarrierColor = Color(0x6604040F);
|
static const Color _kModalBarrierColor = Color(0x6604040F);
|
||||||
|
|
||||||
@ -607,7 +602,6 @@ class _ViewableRoute<T> extends PopupRoute<T> {
|
|||||||
|
|
||||||
class _ContextMenuRouteStatic extends StatefulWidget {
|
class _ContextMenuRouteStatic extends StatefulWidget {
|
||||||
const _ContextMenuRouteStatic({
|
const _ContextMenuRouteStatic({
|
||||||
Key? key,
|
|
||||||
this.actions,
|
this.actions,
|
||||||
required this.child,
|
required this.child,
|
||||||
this.childGlobalKey,
|
this.childGlobalKey,
|
||||||
@ -615,7 +609,7 @@ class _ContextMenuRouteStatic extends StatefulWidget {
|
|||||||
this.onDismiss,
|
this.onDismiss,
|
||||||
required this.orientation,
|
required this.orientation,
|
||||||
this.sheetGlobalKey,
|
this.sheetGlobalKey,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
final List<Widget>? actions;
|
final List<Widget>? actions;
|
||||||
final Widget child;
|
final Widget child;
|
||||||
@ -899,9 +893,9 @@ class _ContextMenuRouteStaticState extends State<_ContextMenuRouteStatic> with T
|
|||||||
|
|
||||||
class _ViewableSheet extends StatelessWidget {
|
class _ViewableSheet extends StatelessWidget {
|
||||||
const _ViewableSheet({
|
const _ViewableSheet({
|
||||||
Key? key,
|
super.key,
|
||||||
required this.actions,
|
required this.actions,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
final List<Widget> actions;
|
final List<Widget> actions;
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
||||||
|
|
||||||
class AbsenceDisplay extends StatelessWidget {
|
class AbsenceDisplay extends StatelessWidget {
|
||||||
const AbsenceDisplay(this.excused, this.unexcused, this.pending, {Key? key}) : super(key: key);
|
const AbsenceDisplay(this.excused, this.unexcused, this.pending, {super.key});
|
||||||
|
|
||||||
final int excused;
|
final int excused;
|
||||||
final int unexcused;
|
final int unexcused;
|
||||||
|
@ -9,13 +9,12 @@ import 'package:provider/provider.dart';
|
|||||||
|
|
||||||
class AbsenceSubjectTile extends StatelessWidget {
|
class AbsenceSubjectTile extends StatelessWidget {
|
||||||
const AbsenceSubjectTile(this.subject,
|
const AbsenceSubjectTile(this.subject,
|
||||||
{Key? key,
|
{super.key,
|
||||||
this.percentage = 0.0,
|
this.percentage = 0.0,
|
||||||
this.excused = 0,
|
this.excused = 0,
|
||||||
this.unexcused = 0,
|
this.unexcused = 0,
|
||||||
this.pending = 0,
|
this.pending = 0,
|
||||||
this.onTap})
|
this.onTap});
|
||||||
: super(key: key);
|
|
||||||
|
|
||||||
final GradeSubject subject;
|
final GradeSubject subject;
|
||||||
final void Function()? onTap;
|
final void Function()? onTap;
|
||||||
@ -62,11 +61,11 @@ class AbsenceSubjectTile extends StatelessWidget {
|
|||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
children: [
|
children: [
|
||||||
const Opacity(
|
const Opacity(
|
||||||
|
opacity: 0,
|
||||||
child: Text("100%",
|
child: Text("100%",
|
||||||
style: TextStyle(fontFamily: "monospace")),
|
style: TextStyle(fontFamily: "monospace"))),
|
||||||
opacity: 0),
|
|
||||||
Text(
|
Text(
|
||||||
percentage.round().toString() + "%",
|
"${percentage.round()}%",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
// fontFamily: "monospace",
|
// fontFamily: "monospace",
|
||||||
color: getColorByPercentage(percentage, context: context),
|
color: getColorByPercentage(percentage, context: context),
|
||||||
|
@ -10,8 +10,7 @@ import 'absence_tile.i18n.dart';
|
|||||||
|
|
||||||
class AbsenceTile extends StatelessWidget {
|
class AbsenceTile extends StatelessWidget {
|
||||||
const AbsenceTile(this.absence,
|
const AbsenceTile(this.absence,
|
||||||
{Key? key, this.onTap, this.elevation = 0.0, this.padding})
|
{super.key, this.onTap, this.elevation = 0.0, this.padding});
|
||||||
: super(key: key);
|
|
||||||
|
|
||||||
final Absence absence;
|
final Absence absence;
|
||||||
final void Function()? onTap;
|
final void Function()? onTap;
|
||||||
|
@ -18,8 +18,7 @@ import 'absence_view.i18n.dart';
|
|||||||
|
|
||||||
class AbsenceView extends StatelessWidget {
|
class AbsenceView extends StatelessWidget {
|
||||||
const AbsenceView(this.absence,
|
const AbsenceView(this.absence,
|
||||||
{Key? key, this.outsideContext, this.viewable = false})
|
{super.key, this.outsideContext, this.viewable = false});
|
||||||
: super(key: key);
|
|
||||||
|
|
||||||
final Absence absence;
|
final Absence absence;
|
||||||
final BuildContext? outsideContext;
|
final BuildContext? outsideContext;
|
||||||
@ -90,9 +89,7 @@ class AbsenceView extends StatelessWidget {
|
|||||||
if (absence.delay > 0)
|
if (absence.delay > 0)
|
||||||
Detail(
|
Detail(
|
||||||
title: "delay".i18n,
|
title: "delay".i18n,
|
||||||
description: absence.delay.toString() +
|
description: "${absence.delay} ${"minutes".i18n.plural(absence.delay)}",
|
||||||
" " +
|
|
||||||
"minutes".i18n.plural(absence.delay),
|
|
||||||
),
|
),
|
||||||
if (absence.lessonIndex != null)
|
if (absence.lessonIndex != null)
|
||||||
Detail(
|
Detail(
|
||||||
|
@ -15,7 +15,7 @@ import 'package:filcnaplo/utils/reverse_search.dart';
|
|||||||
import 'absence_view.i18n.dart';
|
import 'absence_view.i18n.dart';
|
||||||
|
|
||||||
class AbsenceViewable extends StatelessWidget {
|
class AbsenceViewable extends StatelessWidget {
|
||||||
const AbsenceViewable(this.absence, {Key? key, this.padding}) : super(key: key);
|
const AbsenceViewable(this.absence, {super.key, this.padding});
|
||||||
|
|
||||||
final Absence absence;
|
final Absence absence;
|
||||||
final EdgeInsetsGeometry? padding;
|
final EdgeInsetsGeometry? padding;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class AbsenceGroupContainer extends InheritedWidget {
|
class AbsenceGroupContainer extends InheritedWidget {
|
||||||
const AbsenceGroupContainer({Key? key, required Widget child}) : super(key: key, child: child);
|
const AbsenceGroupContainer({super.key, required super.child});
|
||||||
|
|
||||||
static AbsenceGroupContainer? of(BuildContext context) => context.dependOnInheritedWidgetOfExactType<AbsenceGroupContainer>();
|
static AbsenceGroupContainer? of(BuildContext context) => context.dependOnInheritedWidgetOfExactType<AbsenceGroupContainer>();
|
||||||
|
|
||||||
|
@ -11,8 +11,7 @@ import 'absence_group_tile.i18n.dart';
|
|||||||
|
|
||||||
class AbsenceGroupTile extends StatelessWidget {
|
class AbsenceGroupTile extends StatelessWidget {
|
||||||
const AbsenceGroupTile(this.absences,
|
const AbsenceGroupTile(this.absences,
|
||||||
{Key? key, this.showDate = false, this.padding})
|
{super.key, this.showDate = false, this.padding});
|
||||||
: super(key: key);
|
|
||||||
|
|
||||||
final List<AbsenceViewable> absences;
|
final List<AbsenceViewable> absences;
|
||||||
final bool showDate;
|
final bool showDate;
|
||||||
|
@ -5,7 +5,7 @@ import 'package:filcnaplo_mobile_ui/common/panel/panel_button.dart';
|
|||||||
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
||||||
|
|
||||||
class AdTile extends StatelessWidget {
|
class AdTile extends StatelessWidget {
|
||||||
const AdTile(this.ad, {Key? key, this.onTap, this.padding}) : super(key: key);
|
const AdTile(this.ad, {super.key, this.onTap, this.padding});
|
||||||
|
|
||||||
final Ad ad;
|
final Ad ad;
|
||||||
final Function()? onTap;
|
final Function()? onTap;
|
||||||
|
@ -5,7 +5,7 @@ import 'package:url_launcher/url_launcher.dart';
|
|||||||
import 'ad_tile.dart';
|
import 'ad_tile.dart';
|
||||||
|
|
||||||
class AdViewable extends StatelessWidget {
|
class AdViewable extends StatelessWidget {
|
||||||
const AdViewable(this.ad, {Key? key}) : super(key: key);
|
const AdViewable(this.ad, {super.key});
|
||||||
|
|
||||||
final Ad ad;
|
final Ad ad;
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ import 'package:filcnaplo/theme/colors/colors.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class CardHandle extends StatelessWidget {
|
class CardHandle extends StatelessWidget {
|
||||||
const CardHandle({Key? key, this.child}) : super(key: key);
|
const CardHandle({super.key, this.child});
|
||||||
|
|
||||||
final Widget? child;
|
final Widget? child;
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
|||||||
import 'certification_card.i18n.dart';
|
import 'certification_card.i18n.dart';
|
||||||
|
|
||||||
class CertificationCard extends StatelessWidget {
|
class CertificationCard extends StatelessWidget {
|
||||||
const CertificationCard(this.grades, {Key? key, required this.gradeType, this.padding}) : super(key: key);
|
const CertificationCard(this.grades, {super.key, required this.gradeType, this.padding});
|
||||||
|
|
||||||
final List<Grade> grades;
|
final List<Grade> grades;
|
||||||
final GradeType gradeType;
|
final GradeType gradeType;
|
||||||
|
@ -11,7 +11,7 @@ import 'package:provider/provider.dart';
|
|||||||
import 'certification_tile.i18n.dart';
|
import 'certification_tile.i18n.dart';
|
||||||
|
|
||||||
class CertificationTile extends StatelessWidget {
|
class CertificationTile extends StatelessWidget {
|
||||||
const CertificationTile(this.grade, {Key? key, this.onTap, this.padding}) : super(key: key);
|
const CertificationTile(this.grade, {super.key, this.onTap, this.padding});
|
||||||
|
|
||||||
final Function()? onTap;
|
final Function()? onTap;
|
||||||
final Grade grade;
|
final Grade grade;
|
||||||
|
@ -8,7 +8,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
||||||
|
|
||||||
class CertificationView extends StatelessWidget {
|
class CertificationView extends StatelessWidget {
|
||||||
const CertificationView(this.grades, {Key? key, required this.gradeType}) : super(key: key);
|
const CertificationView(this.grades, {super.key, required this.gradeType});
|
||||||
|
|
||||||
final List<Grade> grades;
|
final List<Grade> grades;
|
||||||
final GradeType gradeType;
|
final GradeType gradeType;
|
||||||
@ -26,6 +26,9 @@ class CertificationView extends StatelessWidget {
|
|||||||
icon: FeatherIcons.award,
|
icon: FeatherIcons.award,
|
||||||
iconSize: 50,
|
iconSize: 50,
|
||||||
child: ListView(
|
child: ListView(
|
||||||
|
shrinkWrap: true,
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 24.0),
|
||||||
|
physics: const BouncingScrollPhysics(),
|
||||||
children: [
|
children: [
|
||||||
SafeArea(
|
SafeArea(
|
||||||
child: Panel(
|
child: Panel(
|
||||||
@ -35,9 +38,6 @@ class CertificationView extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
shrinkWrap: true,
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 24.0),
|
|
||||||
physics: const BouncingScrollPhysics(),
|
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,10 +5,10 @@ class CustomSwitch extends StatelessWidget {
|
|||||||
final bool value;
|
final bool value;
|
||||||
|
|
||||||
const CustomSwitch({
|
const CustomSwitch({
|
||||||
Key? key,
|
super.key,
|
||||||
required this.onChanged,
|
required this.onChanged,
|
||||||
required this.value,
|
required this.value,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -4,7 +4,7 @@ import 'package:filcnaplo_mobile_ui/common/profile_image/profile_image.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class EventTile extends StatelessWidget {
|
class EventTile extends StatelessWidget {
|
||||||
const EventTile(this.event, {Key? key, this.onTap, this.padding}) : super(key: key);
|
const EventTile(this.event, {super.key, this.onTap, this.padding});
|
||||||
|
|
||||||
final Event event;
|
final Event event;
|
||||||
final void Function()? onTap;
|
final void Function()? onTap;
|
||||||
|
@ -6,7 +6,7 @@ import 'package:flutter_custom_tabs/flutter_custom_tabs.dart';
|
|||||||
import 'package:flutter_linkify/flutter_linkify.dart';
|
import 'package:flutter_linkify/flutter_linkify.dart';
|
||||||
|
|
||||||
class EventView extends StatelessWidget {
|
class EventView extends StatelessWidget {
|
||||||
const EventView(this.event, {Key? key}) : super(key: key);
|
const EventView(this.event, {super.key});
|
||||||
|
|
||||||
final Event event;
|
final Event event;
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import 'package:filcnaplo_mobile_ui/common/widgets/event/event_view.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class EventViewable extends StatelessWidget {
|
class EventViewable extends StatelessWidget {
|
||||||
const EventViewable(this.event, {Key? key}) : super(key: key);
|
const EventViewable(this.event, {super.key});
|
||||||
|
|
||||||
final Event event;
|
final Event event;
|
||||||
|
|
||||||
|
@ -6,8 +6,7 @@ import 'package:filcnaplo/utils/format.dart';
|
|||||||
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
||||||
|
|
||||||
class ExamTile extends StatelessWidget {
|
class ExamTile extends StatelessWidget {
|
||||||
const ExamTile(this.exam, {Key? key, this.onTap, this.padding})
|
const ExamTile(this.exam, {super.key, this.onTap, this.padding});
|
||||||
: super(key: key);
|
|
||||||
|
|
||||||
final Exam exam;
|
final Exam exam;
|
||||||
final void Function()? onTap;
|
final void Function()? onTap;
|
||||||
|
@ -8,7 +8,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'exam_view.i18n.dart';
|
import 'exam_view.i18n.dart';
|
||||||
|
|
||||||
class ExamView extends StatelessWidget {
|
class ExamView extends StatelessWidget {
|
||||||
const ExamView(this.exam, {Key? key}) : super(key: key);
|
const ExamView(this.exam, {super.key});
|
||||||
|
|
||||||
final Exam exam;
|
final Exam exam;
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ import 'package:filcnaplo_mobile_ui/common/widgets/exam/exam_view.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class ExamViewable extends StatelessWidget {
|
class ExamViewable extends StatelessWidget {
|
||||||
const ExamViewable(this.exam, {Key? key}) : super(key: key);
|
const ExamViewable(this.exam, {super.key});
|
||||||
|
|
||||||
final Exam exam;
|
final Exam exam;
|
||||||
|
|
||||||
|
@ -9,12 +9,11 @@ import 'package:provider/provider.dart';
|
|||||||
|
|
||||||
class GradeSubjectTile extends StatelessWidget {
|
class GradeSubjectTile extends StatelessWidget {
|
||||||
const GradeSubjectTile(this.subject,
|
const GradeSubjectTile(this.subject,
|
||||||
{Key? key,
|
{super.key,
|
||||||
this.average = 0.0,
|
this.average = 0.0,
|
||||||
this.groupAverage = 0.0,
|
this.groupAverage = 0.0,
|
||||||
this.onTap,
|
this.onTap,
|
||||||
this.averageBefore = 0.0})
|
this.averageBefore = 0.0});
|
||||||
: super(key: key);
|
|
||||||
|
|
||||||
final GradeSubject subject;
|
final GradeSubject subject;
|
||||||
final void Function()? onTap;
|
final void Function()? onTap;
|
||||||
|