fixed most reported bugs

This commit is contained in:
Kima 2023-05-30 19:27:16 +02:00
parent f5682e9137
commit d1507f5eae
23 changed files with 1570 additions and 1124 deletions

24
.vscode/launch.json vendored
View File

@ -1,7 +1,4 @@
{ {
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{ {
@ -10,8 +7,27 @@
"request": "launch", "request": "launch",
"type": "dart", "type": "dart",
"toolArgs": [ "toolArgs": [
"--dart-define=APPVER=$(cat pubspec.yaml | grep version: | cut -d' ' -f2 | cut -d+ -f1) --release" "--dart-define=APPVER=$(cat pubspec.yaml | grep version: | cut -d' ' -f2 | cut -d+ -f1)"
] ]
},
{
"name": "filcnaplo release",
"cwd": "filcnaplo release",
"request": "launch",
"type": "dart",
"flutterMode": "release",
"program": "lib/main.dart",
"toolArgs": [
"--dart-define=APPVER=$(cat pubspec.yaml | grep version: | cut -d' ' -f2 | cut -d+ -f1)"
]
},
{
"name": "Flutter",
"program": "lib/main.dart",
"cwd": "filcnaplo",
"request": "launch",
"type": "dart",
"flutterMode": "release"
} }
] ]
} }

View File

@ -0,0 +1,15 @@
// This is a generated file; do not edit or check into version control.
FLUTTER_ROOT=/Users/kima/development/flutter
FLUTTER_APPLICATION_PATH=/Users/kima/Documents/refilc/app/naplo/filcnaplo
COCOAPODS_PARALLEL_CODE_SIGN=true
FLUTTER_TARGET=/Users/kima/Documents/refilc/app/naplo/filcnaplo/lib/main.dart
FLUTTER_BUILD_DIR=build
FLUTTER_BUILD_NAME=3.5.1
FLUTTER_BUILD_NUMBER=197
EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386
EXCLUDED_ARCHS[sdk=iphoneos*]=armv7
DART_DEFINES=RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ==,RkxVVFRFUl9XRUJfQ0FOVkFTS0lUX1VSTD1odHRwczovL3d3dy5nc3RhdGljLmNvbS9mbHV0dGVyLWNhbnZhc2tpdC9iNGZiMTEyMTRkZDJkZGE2Y2UwMTJkZDk4ZWE0OThlOWU4YjkxMjYyLw==
DART_OBFUSCATION=false
TRACK_WIDGET_CREATION=true
TREE_SHAKE_ICONS=false
PACKAGE_CONFIG=/Users/kima/Documents/refilc/app/naplo/filcnaplo/.dart_tool/package_config.json

View File

@ -77,6 +77,8 @@ PODS:
- Mantle/extobjc (2.2.0) - Mantle/extobjc (2.2.0)
- open_file (0.0.1): - open_file (0.0.1):
- Flutter - Flutter
- package_info_plus (0.4.5):
- Flutter
- path_provider_foundation (0.0.1): - path_provider_foundation (0.0.1):
- Flutter - Flutter
- FlutterMacOS - FlutterMacOS
@ -120,6 +122,7 @@ DEPENDENCIES:
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`) - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
- live_activities (from `.symlinks/plugins/live_activities/ios`) - live_activities (from `.symlinks/plugins/live_activities/ios`)
- open_file (from `.symlinks/plugins/open_file/ios`) - open_file (from `.symlinks/plugins/open_file/ios`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
- quick_actions_ios (from `.symlinks/plugins/quick_actions_ios/ios`) - quick_actions_ios (from `.symlinks/plugins/quick_actions_ios/ios`)
@ -171,6 +174,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/live_activities/ios" :path: ".symlinks/plugins/live_activities/ios"
open_file: open_file:
:path: ".symlinks/plugins/open_file/ios" :path: ".symlinks/plugins/open_file/ios"
package_info_plus:
:path: ".symlinks/plugins/package_info_plus/ios"
path_provider_foundation: path_provider_foundation:
:path: ".symlinks/plugins/path_provider_foundation/darwin" :path: ".symlinks/plugins/path_provider_foundation/darwin"
permission_handler_apple: permission_handler_apple:
@ -213,6 +218,7 @@ SPEC CHECKSUMS:
live_activities: 9ff56a06a2d43ecd68f56deeed13b18a8304789c live_activities: 9ff56a06a2d43ecd68f56deeed13b18a8304789c
Mantle: c5aa8794a29a022dfbbfc9799af95f477a69b62d Mantle: c5aa8794a29a022dfbbfc9799af95f477a69b62d
open_file: 02eb5cb6b21264bd3a696876f5afbfb7ca4f4b7d open_file: 02eb5cb6b21264bd3a696876f5afbfb7ca4f4b7d
package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e
path_provider_foundation: eaf5b3e458fc0e5fbb9940fb09980e853fe058b8 path_provider_foundation: eaf5b3e458fc0e5fbb9940fb09980e853fe058b8
permission_handler_apple: 44366e37eaf29454a1e7b1b7d736c2cceaeb17ce permission_handler_apple: 44366e37eaf29454a1e7b1b7d736c2cceaeb17ce
quick_actions_ios: 9e80dcfadfbc5d47d9cf8f47bcf428b11cf383d4 quick_actions_ios: 9e80dcfadfbc5d47d9cf8f47bcf428b11cf383d4

View File

@ -478,7 +478,7 @@
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 195; CURRENT_PROJECT_VERSION = 195;
DEVELOPMENT_TEAM = JWGEQSC9U7; DEVELOPMENT_TEAM = 48XS7JAZB7;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = reFilc; INFOPLIST_KEY_CFBundleDisplayName = reFilc;
@ -488,7 +488,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 3.6.0; MARKETING_VERSION = 3.6.0;
PRODUCT_BUNDLE_IDENTIFIER = hu.refilc.naplo; PRODUCT_BUNDLE_IDENTIFIER = com.refilc.naplo;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
@ -510,7 +510,7 @@
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = JWGEQSC9U7; DEVELOPMENT_TEAM = 48XS7JAZB7;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = livecard/Info.plist; INFOPLIST_FILE = livecard/Info.plist;
@ -526,7 +526,7 @@
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = hu.refilc.naplo.livecardpro; PRODUCT_BUNDLE_IDENTIFIER = com.refilc.naplo.livecardpro;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
@ -552,7 +552,7 @@
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = JWGEQSC9U7; DEVELOPMENT_TEAM = 48XS7JAZB7;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = livecard/Info.plist; INFOPLIST_FILE = livecard/Info.plist;
@ -567,7 +567,7 @@
); );
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = hu.refilc.naplo.livecardpro; PRODUCT_BUNDLE_IDENTIFIER = com.refilc.naplo.livecardpro;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
@ -592,7 +592,7 @@
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = JWGEQSC9U7; DEVELOPMENT_TEAM = 48XS7JAZB7;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = livecard/Info.plist; INFOPLIST_FILE = livecard/Info.plist;
@ -607,7 +607,7 @@
); );
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = hu.refilc.naplo.livecardpro; PRODUCT_BUNDLE_IDENTIFIER = com.refilc.naplo.livecardpro;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
@ -736,7 +736,7 @@
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 195; CURRENT_PROJECT_VERSION = 195;
DEVELOPMENT_TEAM = JWGEQSC9U7; DEVELOPMENT_TEAM = 48XS7JAZB7;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = reFilc; INFOPLIST_KEY_CFBundleDisplayName = reFilc;
@ -746,7 +746,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 3.6.0; MARKETING_VERSION = 3.6.0;
PRODUCT_BUNDLE_IDENTIFIER = hu.refilc.naplo; PRODUCT_BUNDLE_IDENTIFIER = com.refilc.naplo;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@ -764,7 +764,7 @@
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 195; CURRENT_PROJECT_VERSION = 195;
DEVELOPMENT_TEAM = JWGEQSC9U7; DEVELOPMENT_TEAM = 48XS7JAZB7;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = reFilc; INFOPLIST_KEY_CFBundleDisplayName = reFilc;
@ -774,7 +774,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 3.6.0; MARKETING_VERSION = 3.6.0;
PRODUCT_BUNDLE_IDENTIFIER = hu.refilc.naplo; PRODUCT_BUNDLE_IDENTIFIER = com.refilc.naplo;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;

View File

@ -3,6 +3,7 @@ import 'dart:io';
import 'package:filcnaplo/api/client.dart'; import 'package:filcnaplo/api/client.dart';
import 'package:filcnaplo/models/release.dart'; import 'package:filcnaplo/models/release.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:package_info_plus/package_info_plus.dart';
class UpdateProvider extends ChangeNotifier { class UpdateProvider extends ChangeNotifier {
// Private // Private
@ -20,9 +21,11 @@ class UpdateProvider extends ChangeNotifier {
_releases = List.castFrom(initialReleases); _releases = List.castFrom(initialReleases);
} }
static const currentVersion = String.fromEnvironment("APPVER", defaultValue: "1.0");
Future<void> fetch() async { Future<void> fetch() async {
late String currentVersion;
PackageInfo packageInfo = await PackageInfo.fromPlatform();
currentVersion = packageInfo.version;
if (!Platform.isAndroid) return; if (!Platform.isAndroid) return;
_releases = await FilcAPI.getReleases() ?? []; _releases = await FilcAPI.getReleases() ?? [];
@ -30,10 +33,30 @@ class UpdateProvider extends ChangeNotifier {
// Check for new releases // Check for new releases
if (_releases.isNotEmpty) { if (_releases.isNotEmpty) {
_available = _releases.first.version.compareTo(Version.fromString(currentVersion)) == 1; _available = _releases.first.version
.compareTo(Version.fromString(currentVersion)) ==
1;
// ignore: avoid_print // ignore: avoid_print
if (_available) print("INFO: New update: ${releases.first.version}"); if (_available) print("INFO: New update: ${releases.first.version}");
notifyListeners(); notifyListeners();
} }
} }
Future<Map> installedVersion() async {
PackageInfo packageInfo = await PackageInfo.fromPlatform();
String appName = packageInfo.appName;
String packageName = packageInfo.packageName;
String version = packageInfo.version;
String buildNumber = packageInfo.buildNumber;
Map<String, String> release = {
"app_name": appName,
"package_name": packageName,
"version": version,
"build_number": buildNumber,
};
return release;
}
} }

View File

@ -9,6 +9,7 @@ import connectivity_plus
import dynamic_color import dynamic_color
import flutter_acrylic import flutter_acrylic
import flutter_local_notifications import flutter_local_notifications
import package_info_plus
import path_provider_foundation import path_provider_foundation
import share_plus_macos import share_plus_macos
import sqflite import sqflite
@ -19,6 +20,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
DynamicColorPlugin.register(with: registry.registrar(forPlugin: "DynamicColorPlugin")) DynamicColorPlugin.register(with: registry.registrar(forPlugin: "DynamicColorPlugin"))
FlutterAcrylicPlugin.register(with: registry.registrar(forPlugin: "FlutterAcrylicPlugin")) FlutterAcrylicPlugin.register(with: registry.registrar(forPlugin: "FlutterAcrylicPlugin"))
FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin")) FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin")) SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))

View File

@ -1,4 +1,4 @@
platform :osx, '10.11' platform :osx, '10.14'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency. # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true' ENV['COCOAPODS_DISABLE_STATS'] = 'true'

View File

@ -6,11 +6,14 @@ PODS:
- FlutterMacOS - FlutterMacOS
- flutter_acrylic (0.1.0): - flutter_acrylic (0.1.0):
- FlutterMacOS - FlutterMacOS
- flutter_local_notifications (0.0.1):
- FlutterMacOS
- FlutterMacOS (1.0.0) - FlutterMacOS (1.0.0)
- FMDB (2.7.5): - FMDB (2.7.5):
- FMDB/standard (= 2.7.5) - FMDB/standard (= 2.7.5)
- FMDB/standard (2.7.5) - FMDB/standard (2.7.5)
- path_provider_macos (0.0.1): - path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS - FlutterMacOS
- ReachabilitySwift (5.0.0) - ReachabilitySwift (5.0.0)
- share_plus_macos (0.0.1): - share_plus_macos (0.0.1):
@ -25,8 +28,9 @@ DEPENDENCIES:
- connectivity_plus (from `Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos`) - connectivity_plus (from `Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos`)
- dynamic_color (from `Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos`) - dynamic_color (from `Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos`)
- flutter_acrylic (from `Flutter/ephemeral/.symlinks/plugins/flutter_acrylic/macos`) - flutter_acrylic (from `Flutter/ephemeral/.symlinks/plugins/flutter_acrylic/macos`)
- flutter_local_notifications (from `Flutter/ephemeral/.symlinks/plugins/flutter_local_notifications/macos`)
- FlutterMacOS (from `Flutter/ephemeral`) - FlutterMacOS (from `Flutter/ephemeral`)
- path_provider_macos (from `Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos`) - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
- share_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/share_plus_macos/macos`) - share_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/share_plus_macos/macos`)
- sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/macos`) - sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/macos`)
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
@ -43,10 +47,12 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos :path: Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos
flutter_acrylic: flutter_acrylic:
:path: Flutter/ephemeral/.symlinks/plugins/flutter_acrylic/macos :path: Flutter/ephemeral/.symlinks/plugins/flutter_acrylic/macos
flutter_local_notifications:
:path: Flutter/ephemeral/.symlinks/plugins/flutter_local_notifications/macos
FlutterMacOS: FlutterMacOS:
:path: Flutter/ephemeral :path: Flutter/ephemeral
path_provider_macos: path_provider_foundation:
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos :path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin
share_plus_macos: share_plus_macos:
:path: Flutter/ephemeral/.symlinks/plugins/share_plus_macos/macos :path: Flutter/ephemeral/.symlinks/plugins/share_plus_macos/macos
sqflite: sqflite:
@ -56,16 +62,17 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS: SPEC CHECKSUMS:
connectivity_plus: 18d3c32514c886e046de60e9c13895109866c747 connectivity_plus: 18d3c32514c886e046de60e9c13895109866c747
dynamic_color: 394d6a888650f8534e029b27d2f8bc5c64e44008 dynamic_color: 2eaa27267de1ca20d879fbd6e01259773fb1670f
flutter_acrylic: c3df24ae52ab6597197837ce59ef2a8542640c17 flutter_acrylic: c3df24ae52ab6597197837ce59ef2a8542640c17
FlutterMacOS: ae6af50a8ea7d6103d888583d46bd8328a7e9811 flutter_local_notifications: 3805ca215b2fb7f397d78b66db91f6a747af52e4
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
path_provider_macos: 3c0c3b4b0d4a76d2bf989a913c2de869c5641a19 path_provider_foundation: eaf5b3e458fc0e5fbb9940fb09980e853fe058b8
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825 ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
share_plus_macos: 853ee48e7dce06b633998ca0735d482dd671ade4 share_plus_macos: 853ee48e7dce06b633998ca0735d482dd671ade4
sqflite: a5789cceda41d54d23f31d6de539d65bb14100ea sqflite: a5789cceda41d54d23f31d6de539d65bb14100ea
url_launcher_macos: 597e05b8e514239626bcf4a850fcf9ef5c856ec3 url_launcher_macos: 5335912b679c073563f29d89d33d10d459f95451
PODFILE CHECKSUM: 6eac6b3292e5142cfc23bdeb71848a40ec51c14c PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7
COCOAPODS: 1.11.3 COCOAPODS: 1.12.1

View File

@ -3,7 +3,7 @@
archiveVersion = 1; archiveVersion = 1;
classes = { classes = {
}; };
objectVersion = 51; objectVersion = 54;
objects = { objects = {
/* Begin PBXAggregateTarget section */ /* Begin PBXAggregateTarget section */
@ -202,7 +202,7 @@
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastSwiftUpdateCheck = 0920; LastSwiftUpdateCheck = 0920;
LastUpgradeCheck = 1400; LastUpgradeCheck = 1300;
ORGANIZATIONNAME = ""; ORGANIZATIONNAME = "";
TargetAttributes = { TargetAttributes = {
33CC10EC2044A3C60003C045 = { 33CC10EC2044A3C60003C045 = {
@ -254,6 +254,7 @@
/* Begin PBXShellScriptBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */
3399D490228B24CF009A79C7 /* ShellScript */ = { 3399D490228B24CF009A79C7 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
); );
@ -403,7 +404,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.13; MACOSX_DEPLOYMENT_TARGET = 10.14;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx; SDKROOT = macosx;
SWIFT_COMPILATION_MODE = wholemodule; SWIFT_COMPILATION_MODE = wholemodule;
@ -431,7 +432,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MACOSX_DEPLOYMENT_TARGET = 10.13; MACOSX_DEPLOYMENT_TARGET = 10.14;
NEW_SETTING = ""; NEW_SETTING = "";
PRODUCT_BUNDLE_IDENTIFIER = hu.filc.filcnaplo; PRODUCT_BUNDLE_IDENTIFIER = hu.filc.filcnaplo;
PRODUCT_NAME = "Felt Diary"; PRODUCT_NAME = "Felt Diary";
@ -445,7 +446,7 @@
buildSettings = { buildSettings = {
CODE_SIGN_STYLE = Manual; CODE_SIGN_STYLE = Manual;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
MACOSX_DEPLOYMENT_TARGET = 10.13; MACOSX_DEPLOYMENT_TARGET = 10.14;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
}; };
name = Profile; name = Profile;
@ -495,7 +496,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.13; MACOSX_DEPLOYMENT_TARGET = 10.14;
MTL_ENABLE_DEBUG_INFO = YES; MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx; SDKROOT = macosx;
@ -543,7 +544,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.13; MACOSX_DEPLOYMENT_TARGET = 10.14;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx; SDKROOT = macosx;
SWIFT_COMPILATION_MODE = wholemodule; SWIFT_COMPILATION_MODE = wholemodule;
@ -571,7 +572,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MACOSX_DEPLOYMENT_TARGET = 10.13; MACOSX_DEPLOYMENT_TARGET = 10.14;
NEW_SETTING = ""; NEW_SETTING = "";
PRODUCT_BUNDLE_IDENTIFIER = hu.filc.filcnaplo; PRODUCT_BUNDLE_IDENTIFIER = hu.filc.filcnaplo;
PRODUCT_NAME = "Felt Diary"; PRODUCT_NAME = "Felt Diary";
@ -601,7 +602,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MACOSX_DEPLOYMENT_TARGET = 10.13; MACOSX_DEPLOYMENT_TARGET = 10.14;
NEW_SETTING = ""; NEW_SETTING = "";
PRODUCT_BUNDLE_IDENTIFIER = hu.filc.filcnaplo; PRODUCT_BUNDLE_IDENTIFIER = hu.filc.filcnaplo;
PRODUCT_NAME = "Felt Diary"; PRODUCT_NAME = "Felt Diary";
@ -615,7 +616,7 @@
buildSettings = { buildSettings = {
CODE_SIGN_STYLE = Manual; CODE_SIGN_STYLE = Manual;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
MACOSX_DEPLOYMENT_TARGET = 10.13; MACOSX_DEPLOYMENT_TARGET = 10.14;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
}; };
name = Debug; name = Debug;
@ -625,7 +626,7 @@
buildSettings = { buildSettings = {
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
MACOSX_DEPLOYMENT_TARGET = 10.13; MACOSX_DEPLOYMENT_TARGET = 10.14;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
}; };
name = Release; name = Release;

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1400" LastUpgradeVersion = "1300"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@ -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.0.0+198 version: 4.0.1+205
environment: environment:
sdk: ">=2.17.0 <3.0.0" sdk: ">=2.17.0 <3.0.0"
@ -67,6 +67,7 @@ dependencies:
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: ^14.1.0
package_info_plus: ^3.1.2
dev_dependencies: dev_dependencies:
flutter_lints: ^2.0.1 flutter_lints: ^2.0.1

View File

@ -26,16 +26,18 @@ import 'package:flutter_expandable_fab/flutter_expandable_fab.dart';
import 'package:flutter_feather_icons/flutter_feather_icons.dart'; import 'package:flutter_feather_icons/flutter_feather_icons.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'grades_page.i18n.dart'; import 'grades_page.i18n.dart';
// import 'package:filcnaplo_premium/ui/mobile/goalplanner/new_goal.dart'; //import 'package:filcnaplo_premium/ui/mobile/goal_planner/new_goal.dart';
class GradeSubjectView extends StatefulWidget { class GradeSubjectView extends StatefulWidget {
const GradeSubjectView(this.subject, {Key? key, this.groupAverage = 0.0}) : super(key: key); const GradeSubjectView(this.subject, {Key? key, this.groupAverage = 0.0})
: super(key: key);
final Subject subject; final Subject subject;
final double groupAverage; final double groupAverage;
void push(BuildContext context, {bool root = false}) { void push(BuildContext context, {bool root = false}) {
Navigator.of(context, rootNavigator: root).push(CupertinoPageRoute(builder: (context) => this)); Navigator.of(context, rootNavigator: root)
.push(CupertinoPageRoute(builder: (context) => this));
} }
@override @override
@ -70,7 +72,9 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
final gradeDates = subjectGrades.map((e) => e.date.millisecondsSinceEpoch); final gradeDates = subjectGrades.map((e) => e.date.millisecondsSinceEpoch);
final maxGradeDate = gradeDates.fold(0, max); final maxGradeDate = gradeDates.fold(0, max);
final minGradeDate = gradeDates.fold(0, min); final minGradeDate = gradeDates.fold(0, min);
if (maxGradeDate - minGradeDate < const Duration(days: 5).inMilliseconds) return false; // naplo/#78 if (maxGradeDate - minGradeDate < const Duration(days: 5).inMilliseconds) {
return false; // naplo/#78
}
return subjectGrades.where((e) => e.type == GradeType.midYear).length > 1; return subjectGrades.where((e) => e.type == GradeType.midYear).length > 1;
} }
@ -129,7 +133,8 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
), ),
); );
tiles.add(Padding(padding: EdgeInsets.only(bottom: !gradeCalcMode ? 24.0 : 250.0))); tiles.add(Padding(
padding: EdgeInsets.only(bottom: !gradeCalcMode ? 24.0 : 250.0)));
gradeTiles = List.castFrom(tiles); gradeTiles = List.castFrom(tiles);
} }
@ -142,7 +147,10 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
average = AverageHelper.averageEvals(subjectGrades); average = AverageHelper.averageEvals(subjectGrades);
final prevAvg = subjectGrades.isNotEmpty final prevAvg = subjectGrades.isNotEmpty
? AverageHelper.averageEvals(subjectGrades ? AverageHelper.averageEvals(subjectGrades
.where((e) => e.date.isBefore(subjectGrades.reduce((v, e) => e.date.isAfter(v.date) ? e : v).date.subtract(const Duration(days: 30)))) .where((e) => e.date.isBefore(subjectGrades
.reduce((v, e) => e.date.isAfter(v.date) ? e : v)
.date
.subtract(const Duration(days: 30))))
.toList()) .toList())
: 0.0; : 0.0;
@ -153,14 +161,17 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Text("annual_average".i18n), Text("annual_average".i18n),
if (average != prevAvg) TrendDisplay(current: average, previous: prevAvg), if (average != prevAvg)
TrendDisplay(current: average, previous: prevAvg),
], ],
), ),
child: Container( child: Container(
padding: const EdgeInsets.only(top: 12.0, right: 12.0), padding: const EdgeInsets.only(top: 12.0, right: 12.0),
child: Row( child: Row(
children: [ children: [
Expanded(child: GradeGraph(subjectGrades, dayThreshold: 5, classAvg: widget.groupAverage)), Expanded(
child: GradeGraph(subjectGrades,
dayThreshold: 5, classAvg: widget.groupAverage)),
Padding( Padding(
padding: const EdgeInsets.only(bottom: 24.0), padding: const EdgeInsets.only(bottom: 24.0),
child: GradesCount(grades: subjectGrades), child: GradesCount(grades: subjectGrades),
@ -174,7 +185,9 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
if (!gradeCalcMode) { if (!gradeCalcMode) {
buildTiles(subjectGrades); buildTiles(subjectGrades);
} else { } else {
List<Grade> ghostGrades = calculatorProvider.ghosts.where((e) => e.subject == widget.subject).toList(); List<Grade> ghostGrades = calculatorProvider.ghosts
.where((e) => e.subject == widget.subject)
.toList();
buildTiles(ghostGrades); buildTiles(ghostGrades);
} }
@ -182,7 +195,10 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
key: _scaffoldKey, key: _scaffoldKey,
floatingActionButtonLocation: ExpandableFab.location, floatingActionButtonLocation: ExpandableFab.location,
floatingActionButton: Visibility( floatingActionButton: Visibility(
visible: !gradeCalcMode && subjectGrades.where((e) => e.type == GradeType.midYear).isNotEmpty, visible: !gradeCalcMode &&
subjectGrades
.where((e) => e.type == GradeType.midYear)
.isNotEmpty,
child: ExpandableFab( child: ExpandableFab(
type: ExpandableFabType.up, type: ExpandableFabType.up,
distance: 50, distance: 50,
@ -215,12 +231,17 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
}, },
navBarItems: [ navBarItems: [
const SizedBox(width: 6.0), const SizedBox(width: 6.0),
if (widget.groupAverage != 0) Center(child: AverageDisplay(average: widget.groupAverage, border: true)), if (widget.groupAverage != 0)
Center(
child: AverageDisplay(
average: widget.groupAverage, border: true)),
const SizedBox(width: 6.0), const SizedBox(width: 6.0),
if (average != 0) Center(child: AverageDisplay(average: average)), if (average != 0)
Center(child: AverageDisplay(average: average)),
const SizedBox(width: 12.0), const SizedBox(width: 12.0),
], ],
icon: SubjectIcon.resolveVariant(subject: widget.subject, context: context), icon: SubjectIcon.resolveVariant(
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,
@ -240,13 +261,15 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
void gradeCalc(BuildContext context) { void gradeCalc(BuildContext context) {
// Scroll to the top of the page // Scroll to the top of the page
_scrollController.animateTo(75, duration: const Duration(milliseconds: 500), curve: Curves.ease); _scrollController.animateTo(75,
duration: const Duration(milliseconds: 500), curve: Curves.ease);
calculatorProvider.clear(); calculatorProvider.clear();
calculatorProvider.addAllGrades(gradeProvider.grades); calculatorProvider.addAllGrades(gradeProvider.grades);
_sheetController = _scaffoldKey.currentState?.showBottomSheet( _sheetController = _scaffoldKey.currentState?.showBottomSheet(
(context) => RoundedBottomSheet(child: GradeCalculator(widget.subject), borderRadius: 14.0), (context) => RoundedBottomSheet(
child: GradeCalculator(widget.subject), borderRadius: 14.0),
backgroundColor: const Color(0x00000000), backgroundColor: const Color(0x00000000),
elevation: 12.0, elevation: 12.0,
); );

View File

@ -41,13 +41,21 @@ class _GradesPageState extends State<GradesPage> {
int avgDropValue = 0; int avgDropValue = 0;
List<Grade> getSubjectGrades(Subject subject, {int days = 0}) => gradeProvider.grades List<Grade> getSubjectGrades(Subject subject, {int days = 0}) => gradeProvider
.where( .grades
(e) => e.subject == subject && e.type == GradeType.midYear && (days == 0 || e.date.isBefore(DateTime.now().subtract(Duration(days: days))))) .where((e) =>
e.subject == subject &&
e.type == GradeType.midYear &&
(days == 0 ||
e.date.isBefore(DateTime.now().subtract(Duration(days: days)))))
.toList(); .toList();
void generateTiles() { void generateTiles() {
List<Subject> subjects = gradeProvider.grades.map((e) => e.subject).toSet().toList()..sort((a, b) => a.name.compareTo(b.name)); List<Subject> subjects = gradeProvider.grades
.map((e) => e.subject)
.toSet()
.toList()
..sort((a, b) => a.name.compareTo(b.name));
List<Widget> tiles = []; List<Widget> tiles = [];
Map<Subject, double> subjectAvgs = {}; Map<Subject, double> subjectAvgs = {};
@ -59,11 +67,15 @@ class _GradesPageState extends State<GradesPage> {
double averageBefore = 0.0; double averageBefore = 0.0;
if (avgDropValue != 0) { if (avgDropValue != 0) {
List<Grade> gradesBefore = getSubjectGrades(subject, days: avgDropValue); List<Grade> gradesBefore =
averageBefore = avgDropValue == 0 ? 0.0 : AverageHelper.averageEvals(gradesBefore); getSubjectGrades(subject, days: avgDropValue);
averageBefore =
avgDropValue == 0 ? 0.0 : AverageHelper.averageEvals(gradesBefore);
} }
var nullavg = GroupAverage(average: 0.0, subject: subject, uid: "0"); var nullavg = GroupAverage(average: 0.0, subject: subject, uid: "0");
double groupAverage = gradeProvider.groupAverages.firstWhere((e) => e.subject == subject, orElse: () => nullavg).average; double groupAverage = gradeProvider.groupAverages
.firstWhere((e) => e.subject == subject, orElse: () => nullavg)
.average;
if (avg != 0) subjectAvgs[subject] = avg; if (avg != 0) subjectAvgs[subject] = avg;
@ -73,7 +85,8 @@ class _GradesPageState extends State<GradesPage> {
average: avg, average: avg,
groupAverage: avgDropValue == 0 ? groupAverage : 0.0, groupAverage: avgDropValue == 0 ? groupAverage : 0.0,
onTap: () { onTap: () {
GradeSubjectView(subject, groupAverage: groupAverage).push(context, root: true); GradeSubjectView(subject, groupAverage: groupAverage)
.push(context, root: true);
}, },
); );
})); }));
@ -81,7 +94,12 @@ class _GradesPageState extends State<GradesPage> {
if (tiles.isNotEmpty) { if (tiles.isNotEmpty) {
tiles.insert(0, yearlyGraph); tiles.insert(0, yearlyGraph);
tiles.insert(1, FailWarning(subjectAvgs: subjectAvgs)); tiles.insert(1, FailWarning(subjectAvgs: subjectAvgs));
tiles.insert(2, PanelTitle(title: Text(avgDropValue == 0 ? "Subjects".i18n : "Subjects_changes".i18n))); tiles.insert(
2,
PanelTitle(
title: Text(avgDropValue == 0
? "Subjects".i18n
: "Subjects_changes".i18n)));
tiles.insert(3, const PanelHeader(padding: EdgeInsets.only(top: 12.0))); tiles.insert(3, const PanelHeader(padding: EdgeInsets.only(top: 12.0)));
tiles.add(const PanelFooter(padding: EdgeInsets.only(bottom: 12.0))); tiles.add(const PanelFooter(padding: EdgeInsets.only(bottom: 12.0)));
tiles.add(const Padding(padding: EdgeInsets.only(bottom: 24.0))); tiles.add(const Padding(padding: EdgeInsets.only(bottom: 24.0)));
@ -95,9 +113,15 @@ class _GradesPageState extends State<GradesPage> {
); );
} }
double subjectAvg = subjectAvgs.isNotEmpty ? subjectAvgs.values.fold(0.0, (double a, double b) => a + b) / subjectAvgs.length : 0.0; double subjectAvg = subjectAvgs.isNotEmpty
? subjectAvgs.values.fold(0.0, (double a, double b) => a + b) /
subjectAvgs.length
: 0.0;
final double classAvg = gradeProvider.groupAverages.isNotEmpty final double classAvg = gradeProvider.groupAverages.isNotEmpty
? gradeProvider.groupAverages.map((e) => e.average).fold(0.0, (double a, double b) => a + b) / gradeProvider.groupAverages.length ? gradeProvider.groupAverages
.map((e) => e.average)
.fold(0.0, (double a, double b) => a + b) /
gradeProvider.groupAverages.length
: 0.0; : 0.0;
if (subjectAvg > 0) { if (subjectAvg > 0) {
@ -151,18 +175,31 @@ class _GradesPageState extends State<GradesPage> {
final double totalClassAvg = gradeProvider.groupAverages.isEmpty final double totalClassAvg = gradeProvider.groupAverages.isEmpty
? 0.0 ? 0.0
: gradeProvider.groupAverages.map((e) => e.average).fold(0.0, (double a, double b) => a + b) / gradeProvider.groupAverages.length; : gradeProvider.groupAverages
.map((e) => e.average)
.fold(0.0, (double a, double b) => a + b) /
gradeProvider.groupAverages.length;
final now = gradeProvider.grades.isNotEmpty ? gradeProvider.grades.reduce((v, e) => e.date.isAfter(v.date) ? e : v).date : DateTime.now(); final now = gradeProvider.grades.isNotEmpty
? gradeProvider.grades
.reduce((v, e) => e.date.isAfter(v.date) ? e : v)
.date
: DateTime.now();
final currentStudentAvg = AverageHelper.averageEvals(gradeProvider.grades.where((e) => e.type == GradeType.midYear).toList()); final currentStudentAvg = AverageHelper.averageEvals(gradeProvider.grades
.where((e) => e.type == GradeType.midYear)
.toList());
final prevStudentAvg = AverageHelper.averageEvals(gradeProvider.grades final prevStudentAvg = AverageHelper.averageEvals(gradeProvider.grades
.where((e) => e.type == GradeType.midYear) .where((e) => e.type == GradeType.midYear)
.where((e) => e.date.isBefore(now.subtract(const Duration(days: 30)))) .where((e) => e.date.isBefore(now.subtract(const Duration(days: 30))))
.toList()); .toList());
List<Grade> graphGrades = gradeProvider.grades List<Grade> graphGrades = gradeProvider.grades
.where((e) => e.type == GradeType.midYear && (avgDropValue == 0 || e.date.isAfter(DateTime.now().subtract(Duration(days: avgDropValue))))) .where((e) =>
e.type == GradeType.midYear &&
(avgDropValue == 0 ||
e.date.isAfter(
DateTime.now().subtract(Duration(days: avgDropValue)))))
.toList(); .toList();
yearlyGraph = Padding( yearlyGraph = Padding(
@ -183,8 +220,12 @@ class _GradesPageState extends State<GradesPage> {
children: [ children: [
// if (totalClassAvg >= 1.0) AverageDisplay(average: totalClassAvg, border: true), // if (totalClassAvg >= 1.0) AverageDisplay(average: totalClassAvg, border: true),
// const SizedBox(width: 4.0), // const SizedBox(width: 4.0),
TrendDisplay(previous: prevStudentAvg, current: currentStudentAvg), TrendDisplay(
if (gradeProvider.grades.where((e) => e.type == GradeType.midYear).isNotEmpty) AverageDisplay(average: currentStudentAvg), previous: prevStudentAvg, current: currentStudentAvg),
if (gradeProvider.grades
.where((e) => e.type == GradeType.midYear)
.isNotEmpty)
AverageDisplay(average: currentStudentAvg),
], ],
) )
], ],
@ -193,7 +234,9 @@ class _GradesPageState extends State<GradesPage> {
padding: const EdgeInsets.only(top: 12.0, right: 12.0), padding: const EdgeInsets.only(top: 12.0, right: 12.0),
child: Row( child: Row(
children: [ children: [
Expanded(child: GradeGraph(graphGrades, dayThreshold: 2, classAvg: totalClassAvg)), Expanded(
child: GradeGraph(graphGrades,
dayThreshold: 2, classAvg: totalClassAvg)),
Padding( Padding(
padding: const EdgeInsets.only(bottom: 24.0), padding: const EdgeInsets.only(bottom: 24.0),
child: GradesCount(grades: graphGrades), child: GradesCount(grades: graphGrades),
@ -210,7 +253,8 @@ class _GradesPageState extends State<GradesPage> {
body: Padding( body: Padding(
padding: const EdgeInsets.only(top: 9.0), padding: const EdgeInsets.only(top: 9.0),
child: NestedScrollView( child: NestedScrollView(
physics: const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()), physics: const BouncingScrollPhysics(
parent: AlwaysScrollableScrollPhysics()),
headerSliverBuilder: (context, _) => [ headerSliverBuilder: (context, _) => [
SliverAppBar( SliverAppBar(
centerTitle: false, centerTitle: false,
@ -223,7 +267,10 @@ class _GradesPageState extends State<GradesPage> {
padding: const EdgeInsets.only(left: 8.0), padding: const EdgeInsets.only(left: 8.0),
child: Text( child: Text(
"Grades".i18n, "Grades".i18n,
style: TextStyle(color: AppColors.of(context).text, fontSize: 32.0, fontWeight: FontWeight.bold), style: TextStyle(
color: AppColors.of(context).text,
fontSize: 32.0,
fontWeight: FontWeight.bold),
), ),
), ),
shadowColor: Theme.of(context).shadowColor, shadowColor: Theme.of(context).shadowColor,
@ -238,7 +285,8 @@ class _GradesPageState extends State<GradesPage> {
itemCount: max(subjectTiles.length, 1), itemCount: max(subjectTiles.length, 1),
itemBuilder: (context, index) { itemBuilder: (context, index) {
if (subjectTiles.isNotEmpty) { if (subjectTiles.isNotEmpty) {
EdgeInsetsGeometry panelPadding = const EdgeInsets.symmetric(horizontal: 24.0); EdgeInsetsGeometry panelPadding =
const EdgeInsets.symmetric(horizontal: 24.0);
if (subjectTiles[index].runtimeType == GradeSubjectTile) { if (subjectTiles[index].runtimeType == GradeSubjectTile) {
return Padding( return Padding(
@ -248,7 +296,8 @@ class _GradesPageState extends State<GradesPage> {
padding: const EdgeInsets.symmetric(horizontal: 8.0), padding: const EdgeInsets.symmetric(horizontal: 8.0),
)); ));
} else { } else {
return Padding(padding: panelPadding, child: subjectTiles[index]); return Padding(
padding: panelPadding, child: subjectTiles[index]);
} }
} else { } else {
return Container(); return Container();

View File

@ -57,7 +57,8 @@ class _HeroScrollViewState extends State<HeroScrollView> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return NestedScrollView( return NestedScrollView(
controller: _scrollController, controller: _scrollController,
physics: const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()), physics:
const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()),
headerSliverBuilder: (context, _) => [ headerSliverBuilder: (context, _) => [
SliverAppBar( SliverAppBar(
pinned: true, pinned: true,
@ -70,7 +71,8 @@ class _HeroScrollViewState extends State<HeroScrollView> {
opacity: showBarTitle ? 1.0 : 0.0, opacity: showBarTitle ? 1.0 : 0.0,
child: Row( child: Row(
children: [ children: [
Icon(widget.icon, color: AppColors.of(context).text.withOpacity(.8)), Icon(widget.icon,
color: AppColors.of(context).text.withOpacity(.8)),
const SizedBox(width: 8.0), const SizedBox(width: 8.0),
Expanded( Expanded(
child: Text( child: Text(
@ -78,7 +80,9 @@ class _HeroScrollViewState extends State<HeroScrollView> {
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
maxLines: 2, maxLines: 2,
style: TextStyle( style: TextStyle(
color: AppColors.of(context).text, fontWeight: FontWeight.w500, fontStyle: widget.italic ? FontStyle.italic : null), color: AppColors.of(context).text,
fontWeight: FontWeight.w500,
fontStyle: widget.italic ? FontStyle.italic : null),
), ),
), ),
], ],
@ -94,7 +98,7 @@ class _HeroScrollViewState extends State<HeroScrollView> {
} }
}), }),
actions: widget.navBarItems, actions: widget.navBarItems,
expandedHeight: 124.0, expandedHeight: 145.69,
stretch: true, stretch: true,
flexibleSpace: FlexibleSpaceBar( flexibleSpace: FlexibleSpaceBar(
background: Stack( background: Stack(

View File

@ -29,16 +29,18 @@ import 'package:flutter_expandable_fab/flutter_expandable_fab.dart';
import 'package:flutter_feather_icons/flutter_feather_icons.dart'; import 'package:flutter_feather_icons/flutter_feather_icons.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'grades_page.i18n.dart'; import 'grades_page.i18n.dart';
// import 'package:filcnaplo_premium/ui/mobile/goalplanner/new_goal.dart'; // import 'package:filcnaplo_premium/ui/mobile/goal_planner/new_goal.dart';
class GradeSubjectView extends StatefulWidget { class GradeSubjectView extends StatefulWidget {
const GradeSubjectView(this.subject, {Key? key, this.groupAverage = 0.0}) : super(key: key); const GradeSubjectView(this.subject, {Key? key, this.groupAverage = 0.0})
: super(key: key);
final Subject subject; final Subject subject;
final double groupAverage; final double groupAverage;
void push(BuildContext context, {bool root = false}) { void push(BuildContext context, {bool root = false}) {
Navigator.of(context, rootNavigator: root).push(CupertinoPageRoute(builder: (context) => this)); Navigator.of(context, rootNavigator: root)
.push(CupertinoPageRoute(builder: (context) => this));
} }
@override @override
@ -73,7 +75,8 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
final gradeDates = subjectGrades.map((e) => e.date.millisecondsSinceEpoch); final gradeDates = subjectGrades.map((e) => e.date.millisecondsSinceEpoch);
final maxGradeDate = gradeDates.fold(0, max); final maxGradeDate = gradeDates.fold(0, max);
final minGradeDate = gradeDates.fold(0, min); final minGradeDate = gradeDates.fold(0, min);
if (maxGradeDate - minGradeDate < const Duration(days: 5).inMilliseconds) return false; // naplo/#78 if (maxGradeDate - minGradeDate < const Duration(days: 5).inMilliseconds)
return false; // naplo/#78
return subjectGrades.where((e) => e.type == GradeType.midYear).length > 1; return subjectGrades.where((e) => e.type == GradeType.midYear).length > 1;
} }
@ -139,7 +142,8 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
), ),
); );
tiles.add(Padding(padding: EdgeInsets.only(bottom: !gradeCalcMode ? 24.0 : 250.0))); tiles.add(Padding(
padding: EdgeInsets.only(bottom: !gradeCalcMode ? 24.0 : 250.0)));
gradeTiles = List.castFrom(tiles); gradeTiles = List.castFrom(tiles);
} }
@ -152,7 +156,10 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
average = AverageHelper.averageEvals(subjectGrades); average = AverageHelper.averageEvals(subjectGrades);
final prevAvg = subjectGrades.isNotEmpty final prevAvg = subjectGrades.isNotEmpty
? AverageHelper.averageEvals(subjectGrades ? AverageHelper.averageEvals(subjectGrades
.where((e) => e.date.isBefore(subjectGrades.reduce((v, e) => e.date.isAfter(v.date) ? e : v).date.subtract(const Duration(days: 30)))) .where((e) => e.date.isBefore(subjectGrades
.reduce((v, e) => e.date.isAfter(v.date) ? e : v)
.date
.subtract(const Duration(days: 30))))
.toList()) .toList())
: 0.0; : 0.0;
@ -163,12 +170,14 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Text("annual_average".i18n), Text("annual_average".i18n),
if (average != prevAvg) TrendDisplay(current: average, previous: prevAvg), if (average != prevAvg)
TrendDisplay(current: average, previous: prevAvg),
], ],
), ),
child: Container( child: Container(
padding: const EdgeInsets.only(top: 16.0, right: 12.0), padding: const EdgeInsets.only(top: 16.0, right: 12.0),
child: GradeGraph(subjectGrades, dayThreshold: 5, classAvg: widget.groupAverage), child: GradeGraph(subjectGrades,
dayThreshold: 5, classAvg: widget.groupAverage),
), ),
), ),
); );
@ -176,7 +185,9 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
if (!gradeCalcMode) { if (!gradeCalcMode) {
buildTiles(subjectGrades); buildTiles(subjectGrades);
} else { } else {
List<Grade> ghostGrades = calculatorProvider.ghosts.where((e) => e.subject == widget.subject).toList(); List<Grade> ghostGrades = calculatorProvider.ghosts
.where((e) => e.subject == widget.subject)
.toList();
buildTiles(ghostGrades); buildTiles(ghostGrades);
} }
@ -184,7 +195,10 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
key: _scaffoldKey, key: _scaffoldKey,
floatingActionButtonLocation: ExpandableFab.location, floatingActionButtonLocation: ExpandableFab.location,
floatingActionButton: Visibility( floatingActionButton: Visibility(
visible: !gradeCalcMode && subjectGrades.where((e) => e.type == GradeType.midYear).isNotEmpty, visible: !gradeCalcMode &&
subjectGrades
.where((e) => e.type == GradeType.midYear)
.isNotEmpty,
child: ExpandableFab( child: ExpandableFab(
backgroundColor: Theme.of(context).colorScheme.secondary, backgroundColor: Theme.of(context).colorScheme.secondary,
type: ExpandableFabType.up, type: ExpandableFabType.up,
@ -204,14 +218,19 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
child: const Icon(FeatherIcons.flag, size: 20.0), child: const Icon(FeatherIcons.flag, size: 20.0),
backgroundColor: Theme.of(context).colorScheme.secondary, backgroundColor: Theme.of(context).colorScheme.secondary,
onPressed: () { onPressed: () {
if (!Provider.of<PremiumProvider>(context, listen: false).hasScope(PremiumScopes.goalPlanner)) { if (!Provider.of<PremiumProvider>(context, listen: false)
PremiumLockedFeatureUpsell.show(context: context, feature: PremiumFeature.goalplanner); .hasScope(PremiumScopes.goalPlanner)) {
PremiumLockedFeatureUpsell.show(
context: context, feature: PremiumFeature.goalplanner);
return; return;
} }
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("Hamarosan..."))); ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text("Hamarosan...")));
// Navigator.of(context).push(CupertinoPageRoute(builder: (context) => PremiumGoalplannerNewGoalScreen(subject: widget.subject))); //Navigator.of(context).push(CupertinoPageRoute(
//builder: (context) => PremiumGoalplannerNewGoalScreen(
// subject: widget.subject)));
}, },
), ),
], ],
@ -230,12 +249,17 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
}, },
navBarItems: [ navBarItems: [
const SizedBox(width: 6.0), const SizedBox(width: 6.0),
if (widget.groupAverage != 0) Center(child: AverageDisplay(average: widget.groupAverage, border: true)), if (widget.groupAverage != 0)
Center(
child: AverageDisplay(
average: widget.groupAverage, border: true)),
const SizedBox(width: 6.0), const SizedBox(width: 6.0),
if (average != 0) Center(child: AverageDisplay(average: average)), if (average != 0)
Center(child: AverageDisplay(average: average)),
const SizedBox(width: 12.0), const SizedBox(width: 12.0),
], ],
icon: SubjectIcon.resolveVariant(subject: widget.subject, context: context), icon: SubjectIcon.resolveVariant(
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,
@ -255,13 +279,15 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
void gradeCalc(BuildContext context) { void gradeCalc(BuildContext context) {
// Scroll to the top of the page // Scroll to the top of the page
_scrollController.animateTo(75, duration: const Duration(milliseconds: 500), curve: Curves.ease); _scrollController.animateTo(75,
duration: const Duration(milliseconds: 500), curve: Curves.ease);
calculatorProvider.clear(); calculatorProvider.clear();
calculatorProvider.addAllGrades(gradeProvider.grades); calculatorProvider.addAllGrades(gradeProvider.grades);
_sheetController = _scaffoldKey.currentState?.showBottomSheet( _sheetController = _scaffoldKey.currentState?.showBottomSheet(
(context) => RoundedBottomSheet(child: GradeCalculator(widget.subject), borderRadius: 14.0), (context) => RoundedBottomSheet(
child: GradeCalculator(widget.subject), borderRadius: 14.0),
backgroundColor: const Color(0x00000000), backgroundColor: const Color(0x00000000),
elevation: 12.0, elevation: 12.0,
); );

View File

@ -5,7 +5,8 @@ class NavItem {
final Widget icon; final Widget icon;
final Widget activeIcon; final Widget activeIcon;
const NavItem({required this.title, required this.icon, required this.activeIcon}); const NavItem(
{required this.title, required this.icon, required this.activeIcon});
} }
class NavbarItem extends StatelessWidget { class NavbarItem extends StatelessWidget {
@ -25,14 +26,16 @@ class NavbarItem extends StatelessWidget {
final Widget icon = active ? item.activeIcon : item.icon; final Widget icon = active ? item.activeIcon : item.icon;
return SafeArea( return SafeArea(
child: InkWell( child: GestureDetector(
onTap: onTap, onTap: onTap,
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 6.0), padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 6.0),
child: Container( child: Container(
padding: const EdgeInsets.all(12.0), padding: const EdgeInsets.all(12.0),
decoration: BoxDecoration( decoration: BoxDecoration(
color: active ? Theme.of(context).colorScheme.secondary.withOpacity(.4) : null, color: active
? Theme.of(context).colorScheme.secondary.withOpacity(.4)
: null,
borderRadius: BorderRadius.circular(14.0), borderRadius: BorderRadius.circular(14.0),
), ),
child: Stack( child: Stack(
@ -45,7 +48,9 @@ class NavbarItem extends StatelessWidget {
), ),
IconTheme( IconTheme(
data: IconThemeData( data: IconThemeData(
color: Theme.of(context).brightness == Brightness.light ? Colors.black.withOpacity(.5) : Colors.white.withOpacity(.3), color: Theme.of(context).brightness == Brightness.light
? Colors.black.withOpacity(.5)
: Colors.white.withOpacity(.3),
), ),
child: icon, child: icon,
), ),

View File

@ -6,7 +6,10 @@ import 'settings_screen.i18n.dart';
class PrivacyView extends StatelessWidget { class PrivacyView extends StatelessWidget {
const PrivacyView({Key? key}) : super(key: key); const PrivacyView({Key? key}) : super(key: key);
static void show(BuildContext context) => showDialog(context: context, builder: (context) => const PrivacyView(), barrierDismissible: true); static void show(BuildContext context) => showDialog(
context: context,
builder: (context) => const PrivacyView(),
barrierDismissible: true);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View File

@ -54,6 +54,9 @@ class _SettingsScreenState extends State<SettingsScreen>
int devmodeCountdown = 3; int devmodeCountdown = 3;
bool __ss = false; // secret settings bool __ss = false; // secret settings
late Future<Map> futureRelease =
Provider.of<UpdateProvider>(context).installedVersion();
late UserProvider user; late UserProvider user;
late UpdateProvider updateProvider; late UpdateProvider updateProvider;
late SettingsProvider settings; late SettingsProvider settings;
@ -150,6 +153,7 @@ class _SettingsScreenState extends State<SettingsScreen>
@override @override
void initState() { void initState() {
super.initState(); super.initState();
futureRelease = Provider.of<UpdateProvider>(context).installedVersion();
_hideContainersController = AnimationController( _hideContainersController = AnimationController(
vsync: this, duration: const Duration(milliseconds: 200)); vsync: this, duration: const Duration(milliseconds: 200));
} }
@ -877,9 +881,36 @@ class _SettingsScreenState extends State<SettingsScreen>
top: false, top: false,
child: Center( child: Center(
child: GestureDetector( child: GestureDetector(
child: const Panel( child: FutureBuilder<Map>(
title: Text("v" + future: futureRelease,
String.fromEnvironment("APPVER", defaultValue: "?"))), builder: (context, release) {
if (release.hasData) {
return DefaultTextStyle(
style: Theme.of(context)
.textTheme
.titleMedium!
.copyWith(
fontWeight: FontWeight.w600,
color: AppColors.of(context)
.text
.withOpacity(0.65)),
child: Text("v${release.data!['version']}"),
);
} else {
return DefaultTextStyle(
style: Theme.of(context)
.textTheme
.titleMedium!
.copyWith(
fontWeight: FontWeight.w600,
color: AppColors.of(context)
.text
.withOpacity(0.65)),
child: const Text("v?"),
);
}
},
),
onTap: () { onTap: () {
if (devmodeCountdown > 0) { if (devmodeCountdown > 0) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar( ScaffoldMessenger.of(context).showSnackBar(SnackBar(

View File

@ -41,7 +41,8 @@ extension SettingsLocalization on String {
"done": "Done", "done": "Done",
"reset": "Reset", "reset": "Reset",
"open": "Open", "open": "Open",
"data_collected": "Data collected: Platform (eg. Android), App version (eg. 3.0.0), Unique Install Identifier", "data_collected":
"Data collected: Platform (eg. Android), App version (eg. 3.0.0), Unique Install Identifier",
"Analytics": "Analytics", "Analytics": "Analytics",
"Anonymous Usage Analytics": "Anonymous Usage Analytics", "Anonymous Usage Analytics": "Anonymous Usage Analytics",
"graph_class_avg": "Class average on graph", "graph_class_avg": "Class average on graph",
@ -92,7 +93,7 @@ extension SettingsLocalization on String {
"about": "Névjegy", "about": "Névjegy",
"supporters": "Támogatók", "supporters": "Támogatók",
"privacy": "Adatvédelmi irányelvek", "privacy": "Adatvédelmi irányelvek",
"licenses": "Licenszek", "licenses": "Licencek",
"vibrate": "Rezgés", "vibrate": "Rezgés",
"voff": "Kikapcsolás", "voff": "Kikapcsolás",
"vlight": "Alacsony", "vlight": "Alacsony",
@ -102,7 +103,8 @@ extension SettingsLocalization on String {
"done": "Kész", "done": "Kész",
"reset": "Visszaállítás", "reset": "Visszaállítás",
"open": "Megnyitás", "open": "Megnyitás",
"data_collected": "Gyűjtött adat: Platform (pl. Android), App verzió (pl. 3.0.0), Egyedi telepítési azonosító", "data_collected":
"Gyűjtött adat: Platform (pl. Android), App verzió (pl. 3.0.0), Egyedi telepítési azonosító",
"Analytics": "Analitika", "Analytics": "Analitika",
"Anonymous Usage Analytics": "Névtelen használati analitika", "Anonymous Usage Analytics": "Névtelen használati analitika",
"graph_class_avg": "Osztályátlag a grafikonon", "graph_class_avg": "Osztályátlag a grafikonon",
@ -163,7 +165,8 @@ extension SettingsLocalization on String {
"done": "Fertig", "done": "Fertig",
"reset": "Zurücksetzen", "reset": "Zurücksetzen",
"open": "Öffnen", "open": "Öffnen",
"data_collected": "Erhobene Daten: Plattform (z.B. Android), App version (z.B. 3.0.0), Eindeutige Installationskennung", "data_collected":
"Erhobene Daten: Plattform (z.B. Android), App version (z.B. 3.0.0), Eindeutige Installationskennung",
"Analytics": "Analytik", "Analytics": "Analytik",
"Anonymous Usage Analytics": "Anonyme Nutzungsanalyse", "Anonymous Usage Analytics": "Anonyme Nutzungsanalyse",
"graph_class_avg": "Klassendurchschnitt in der Grafik", "graph_class_avg": "Klassendurchschnitt in der Grafik",

View File

@ -39,6 +39,7 @@ dependencies:
flutter_svg: ^1.1.6 flutter_svg: ^1.1.6
background_fetch: ^1.1.5 background_fetch: ^1.1.5
wtf_sliding_sheet: ^1.0.0 wtf_sliding_sheet: ^1.0.0
package_info_plus: ^3.1.2
dev_dependencies: dev_dependencies:
flutter_lints: ^1.0.0 flutter_lints: ^1.0.0

View File

@ -13,10 +13,10 @@ import 'package:filcnaplo_premium/ui/mobile/flutter_colorpicker/block_picker.dar
import 'package:filcnaplo_premium/ui/mobile/flutter_colorpicker/palette.dart'; import 'package:filcnaplo_premium/ui/mobile/flutter_colorpicker/palette.dart';
import 'package:filcnaplo_premium/ui/mobile/flutter_colorpicker/utils.dart'; import 'package:filcnaplo_premium/ui/mobile/flutter_colorpicker/utils.dart';
import 'package:filcnaplo_premium/ui/mobile/settings/theme.dart'; import 'package:filcnaplo_premium/ui/mobile/settings/theme.dart';
import 'package:filcnaplo_premium/ui/mobile/settings/theme.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';
import 'package:filcnaplo_mobile_ui/common/widgets/custom_switch.dart';
class FilcColorPicker extends StatefulWidget { class FilcColorPicker extends StatefulWidget {
const FilcColorPicker({ const FilcColorPicker({
@ -29,9 +29,16 @@ class FilcColorPicker extends StatefulWidget {
this.onHsvColorChanged, this.onHsvColorChanged,
this.paletteType = PaletteType.hsvWithHue, this.paletteType = PaletteType.hsvWithHue,
this.enableAlpha = true, this.enableAlpha = true,
@Deprecated('Use empty list in [labelTypes] to disable label.') this.showLabel = true, @Deprecated('Use empty list in [labelTypes] to disable label.')
this.labelTypes = const [ColorLabelType.rgb, ColorLabelType.hsv, ColorLabelType.hsl], this.showLabel = true,
@Deprecated('Use Theme.of(context).textTheme.bodyText1 & 2 to alter text style.') this.labelTextStyle, this.labelTypes = const [
ColorLabelType.rgb,
ColorLabelType.hsv,
ColorLabelType.hsl
],
@Deprecated(
'Use Theme.of(context).textTheme.bodyText1 & 2 to alter text style.')
this.labelTextStyle,
this.displayThumbColor = false, this.displayThumbColor = false,
this.portraitOnly = false, this.portraitOnly = false,
this.colorPickerWidth = 300.0, this.colorPickerWidth = 300.0,
@ -75,7 +82,9 @@ class _FilcColorPickerState extends State<FilcColorPicker> {
@override @override
void initState() { void initState() {
currentHsvColor = (widget.pickerHsvColor != null) ? widget.pickerHsvColor as HSVColor : HSVColor.fromColor(widget.pickerColor); currentHsvColor = (widget.pickerHsvColor != null)
? widget.pickerHsvColor as HSVColor
: HSVColor.fromColor(widget.pickerColor);
// If there's no initial text in `hexInputController`, // If there's no initial text in `hexInputController`,
if (widget.hexInputController?.text.isEmpty == true) { if (widget.hexInputController?.text.isEmpty == true) {
// set it to the current's color HEX value. // set it to the current's color HEX value.
@ -95,7 +104,9 @@ class _FilcColorPickerState extends State<FilcColorPicker> {
@override @override
void didUpdateWidget(FilcColorPicker oldWidget) { void didUpdateWidget(FilcColorPicker oldWidget) {
super.didUpdateWidget(oldWidget); super.didUpdateWidget(oldWidget);
currentHsvColor = (widget.pickerHsvColor != null) ? widget.pickerHsvColor as HSVColor : HSVColor.fromColor(widget.pickerColor); currentHsvColor = (widget.pickerHsvColor != null)
? widget.pickerHsvColor as HSVColor
: HSVColor.fromColor(widget.pickerColor);
} }
void colorPickerTextInputListener() { void colorPickerTextInputListener() {
@ -104,14 +115,17 @@ class _FilcColorPickerState extends State<FilcColorPicker> {
if (widget.hexInputController == null) return; if (widget.hexInputController == null) return;
// If a user is inserting/typing any text try to get the color value from it, // If a user is inserting/typing any text try to get the color value from it,
// and interpret its transparency, dependent on the widget's settings. // and interpret its transparency, dependent on the widget's settings.
final Color? color = colorFromHex(widget.hexInputController!.text, enableAlpha: widget.enableAlpha); final Color? color = colorFromHex(widget.hexInputController!.text,
enableAlpha: widget.enableAlpha);
// If it's the valid color: // If it's the valid color:
if (color != null) { if (color != null) {
// set it as the current color and // set it as the current color and
setState(() => currentHsvColor = HSVColor.fromColor(color)); setState(() => currentHsvColor = HSVColor.fromColor(color));
// notify with a callback. // notify with a callback.
widget.onColorChanged(color); widget.onColorChanged(color);
if (widget.onHsvColorChanged != null) widget.onHsvColorChanged!(currentHsvColor); if (widget.onHsvColorChanged != null) {
widget.onHsvColorChanged!(currentHsvColor);
}
} }
} }
@ -127,17 +141,24 @@ class _FilcColorPickerState extends State<FilcColorPicker> {
currentHsvColor, currentHsvColor,
(HSVColor color) { (HSVColor color) {
// Update text in `hexInputController` if provided. // Update text in `hexInputController` if provided.
widget.hexInputController?.text = colorToHex(color.toColor(), enableAlpha: widget.enableAlpha); widget.hexInputController?.text =
colorToHex(color.toColor(), enableAlpha: widget.enableAlpha);
setState(() => currentHsvColor = color); setState(() => currentHsvColor = color);
widget.onColorChanged(currentHsvColor.toColor()); widget.onColorChanged(currentHsvColor.toColor());
if (widget.onHsvColorChanged != null) widget.onHsvColorChanged!(currentHsvColor); if (widget.onHsvColorChanged != null) {
widget.onHsvColorChanged!(currentHsvColor);
}
}, },
() => widget.onColorChangeEnd(currentHsvColor.toColor()), () => widget.onColorChangeEnd(currentHsvColor.toColor()),
(p) { (p) {
ScaffoldMessenger.of(context).clearSnackBars(); ScaffoldMessenger.of(context).clearSnackBars();
ScaffoldMessenger.of(context).showSnackBar(SnackBar( ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text("Move the ${p == 0 ? 'Saturation (second)' : 'Value (third)'} slider first.", content: Text(
textAlign: TextAlign.center, style: TextStyle(color: AppColors.of(context).text, fontWeight: FontWeight.w600)), "Move the ${p == 0 ? 'Saturation (second)' : 'Value (third)'} slider first.",
textAlign: TextAlign.center,
style: TextStyle(
color: AppColors.of(context).text,
fontWeight: FontWeight.w600)),
backgroundColor: AppColors.of(context).background)); backgroundColor: AppColors.of(context).background));
}, },
displayThumbColor: widget.displayThumbColor, displayThumbColor: widget.displayThumbColor,
@ -146,15 +167,19 @@ class _FilcColorPickerState extends State<FilcColorPicker> {
void onColorChanging(HSVColor color) { void onColorChanging(HSVColor color) {
// Update text in `hexInputController` if provided. // Update text in `hexInputController` if provided.
widget.hexInputController?.text = colorToHex(color.toColor(), enableAlpha: widget.enableAlpha); widget.hexInputController?.text =
colorToHex(color.toColor(), enableAlpha: widget.enableAlpha);
setState(() => currentHsvColor = color); setState(() => currentHsvColor = color);
widget.onColorChanged(currentHsvColor.toColor()); widget.onColorChanged(currentHsvColor.toColor());
if (widget.onHsvColorChanged != null) widget.onHsvColorChanged!(currentHsvColor); if (widget.onHsvColorChanged != null) {
widget.onHsvColorChanged!(currentHsvColor);
}
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (MediaQuery.of(context).orientation == Orientation.portrait || widget.portraitOnly) { if (MediaQuery.of(context).orientation == Orientation.portrait ||
widget.portraitOnly) {
return Column( return Column(
children: [ children: [
if (widget.colorMode != CustomColorMode.theme) if (widget.colorMode != CustomColorMode.theme)
@ -198,7 +223,9 @@ class _FilcColorPickerState extends State<FilcColorPicker> {
(Color color) { (Color color) {
setState(() => currentHsvColor = HSVColor.fromColor(color)); setState(() => currentHsvColor = HSVColor.fromColor(color));
widget.onColorChanged(currentHsvColor.toColor()); widget.onColorChanged(currentHsvColor.toColor());
if (widget.onHsvColorChanged != null) widget.onHsvColorChanged!(currentHsvColor); if (widget.onHsvColorChanged != null) {
widget.onHsvColorChanged!(currentHsvColor);
}
}, },
enableAlpha: false, enableAlpha: false,
embeddedText: false, embeddedText: false,
@ -211,26 +238,42 @@ class _FilcColorPickerState extends State<FilcColorPicker> {
layoutBuilder: (context, colors, child) { layoutBuilder: (context, colors, child) {
return GridView.count( return GridView.count(
shrinkWrap: true, shrinkWrap: true,
crossAxisCount: widget.colorMode == CustomColorMode.theme ? 2 : 1, crossAxisCount:
widget.colorMode == CustomColorMode.theme ? 2 : 1,
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
crossAxisSpacing: 15, crossAxisSpacing: 15,
physics: const BouncingScrollPhysics(), physics: const BouncingScrollPhysics(),
mainAxisSpacing: 15, mainAxisSpacing: 15,
padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 8.0), padding: const EdgeInsets.symmetric(
children: List.generate(colors.toSet().length + (widget.colorMode == CustomColorMode.theme ? 1 : 0), (index) { horizontal: 12.0, vertical: 8.0),
children: List.generate(
colors.toSet().length +
(widget.colorMode == CustomColorMode.theme ? 1 : 0),
(index) {
if (widget.colorMode == CustomColorMode.theme) { if (widget.colorMode == CustomColorMode.theme) {
if (index == 0) { if (index == 0) {
return GestureDetector( return GestureDetector(
onTap: () => widget.onColorChangeEnd(Colors.transparent, adaptive: true), onTap: () => widget.onColorChangeEnd(
child: ColorIndicator(HSVColor.fromColor(const Color.fromARGB(255, 255, 238, 177)), Colors.transparent,
icon: CupertinoIcons.wand_stars, currentHsvColor: currentHsvColor, width: 30, height: 30, adaptive: true), adaptive: true),
child: ColorIndicator(
HSVColor.fromColor(
const Color.fromARGB(255, 255, 238, 177)),
icon: CupertinoIcons.wand_stars,
currentHsvColor: currentHsvColor,
width: 30,
height: 30,
adaptive: true),
); );
} }
index--; index--;
} }
return GestureDetector( return GestureDetector(
onTap: () => widget.onColorChangeEnd(colors[index]), onTap: () => widget.onColorChangeEnd(colors[index]),
child: ColorIndicator(HSVColor.fromColor(colors[index]), currentHsvColor: currentHsvColor, width: 30, height: 30), child: ColorIndicator(HSVColor.fromColor(colors[index]),
currentHsvColor: currentHsvColor,
width: 30,
height: 30),
); );
}), }),
); );
@ -249,22 +292,25 @@ class _FilcColorPickerState extends State<FilcColorPicker> {
isAdvancedView = !isAdvancedView; isAdvancedView = !isAdvancedView;
}), }),
child: Padding( child: Padding(
padding: const EdgeInsets.only(left: 8.0, right: 8.0, top: 8.0), padding:
const EdgeInsets.only(left: 8.0, right: 8.0, top: 8.0),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
CustomSwitch( Switch(
onChanged: (v) => setState(() => isAdvancedView = v), onChanged: (v) => setState(() => isAdvancedView = v),
value: isAdvancedView, value: isAdvancedView,
), ),
const SizedBox(width: 12.0), const SizedBox(width: 12.0),
Text( Text(
"Advanced", "advanced".i18n,
style: TextStyle( style: TextStyle(
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
fontSize: 16.0, fontSize: 16.0,
color: AppColors.of(context).text.withOpacity(isAdvancedView ? 1.0 : .5), color: AppColors.of(context)
.text
.withOpacity(isAdvancedView ? 1.0 : .5),
), ),
), ),
], ],
@ -285,7 +331,8 @@ class _FilcColorPickerState extends State<FilcColorPicker> {
const SizedBox(width: 20.0), const SizedBox(width: 20.0),
GestureDetector( GestureDetector(
onTap: () => setState(() { onTap: () => setState(() {
if (widget.onHistoryChanged != null && !colorHistory.contains(currentHsvColor.toColor())) { if (widget.onHistoryChanged != null &&
!colorHistory.contains(currentHsvColor.toColor())) {
colorHistory.add(currentHsvColor.toColor()); colorHistory.add(currentHsvColor.toColor());
widget.onHistoryChanged!(colorHistory); widget.onHistoryChanged!(colorHistory);
} }
@ -295,7 +342,11 @@ class _FilcColorPickerState extends State<FilcColorPicker> {
Column( Column(
children: <Widget>[ children: <Widget>[
//SizedBox(height: 40.0, width: 260.0, child: sliderByPaletteType()), //SizedBox(height: 40.0, width: 260.0, child: sliderByPaletteType()),
if (widget.enableAlpha) SizedBox(height: 40.0, width: 260.0, child: colorPickerSlider(TrackType.alpha)), if (widget.enableAlpha)
SizedBox(
height: 40.0,
width: 260.0,
child: colorPickerSlider(TrackType.alpha)),
], ],
), ),
const SizedBox(width: 10.0), const SizedBox(width: 10.0),
@ -305,21 +356,25 @@ class _FilcColorPickerState extends State<FilcColorPicker> {
SizedBox( SizedBox(
width: widget.colorPickerWidth, width: widget.colorPickerWidth,
height: 50, height: 50,
child: ListView(scrollDirection: Axis.horizontal, children: <Widget>[ child: ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
for (Color color in colorHistory) for (Color color in colorHistory)
Padding( Padding(
key: Key(color.hashCode.toString()), key: Key(color.hashCode.toString()),
padding: const EdgeInsets.fromLTRB(15, 18, 0, 0), padding: const EdgeInsets.fromLTRB(15, 18, 0, 0),
child: Center( child: Center(
child: GestureDetector( child: GestureDetector(
onTap: () => onColorChanging(HSVColor.fromColor(color)), onTap: () =>
onColorChanging(HSVColor.fromColor(color)),
onLongPress: () { onLongPress: () {
if (colorHistory.remove(color)) { if (colorHistory.remove(color)) {
widget.onHistoryChanged!(colorHistory); widget.onHistoryChanged!(colorHistory);
setState(() {}); setState(() {});
} }
}, },
child: ColorIndicator(HSVColor.fromColor(color), width: 30, height: 30), child: ColorIndicator(HSVColor.fromColor(color),
width: 30, height: 30),
), ),
), ),
), ),
@ -333,7 +388,9 @@ class _FilcColorPickerState extends State<FilcColorPicker> {
(Color color) { (Color color) {
setState(() => currentHsvColor = HSVColor.fromColor(color)); setState(() => currentHsvColor = HSVColor.fromColor(color));
widget.onColorChanged(currentHsvColor.toColor()); widget.onColorChanged(currentHsvColor.toColor());
if (widget.onHsvColorChanged != null) widget.onHsvColorChanged!(currentHsvColor); if (widget.onHsvColorChanged != null) {
widget.onHsvColorChanged!(currentHsvColor);
}
}, },
enableAlpha: widget.enableAlpha, enableAlpha: widget.enableAlpha,
embeddedText: false, embeddedText: false,

View File

@ -24,12 +24,15 @@ class PremiumCustomAccentColorSetting extends StatefulWidget {
const PremiumCustomAccentColorSetting({Key? key}) : super(key: key); const PremiumCustomAccentColorSetting({Key? key}) : super(key: key);
@override @override
State<PremiumCustomAccentColorSetting> createState() => _PremiumCustomAccentColorSettingState(); State<PremiumCustomAccentColorSetting> createState() =>
_PremiumCustomAccentColorSettingState();
} }
enum CustomColorMode { theme, accent, background, highlight } enum CustomColorMode { theme, saved, accent, background, highlight }
class _PremiumCustomAccentColorSettingState extends State<PremiumCustomAccentColorSetting> with TickerProviderStateMixin { class _PremiumCustomAccentColorSettingState
extends State<PremiumCustomAccentColorSetting>
with TickerProviderStateMixin {
late final SettingsProvider settings; late final SettingsProvider settings;
bool colorSelection = false; bool colorSelection = false;
bool customColorMenu = false; bool customColorMenu = false;
@ -41,42 +44,48 @@ class _PremiumCustomAccentColorSettingState extends State<PremiumCustomAccentCol
late TabController _colorsTabController; late TabController _colorsTabController;
late AnimationController _openAnimController; late AnimationController _openAnimController;
late final Animation<double> backgroundAnimation = Tween<double>(begin: 0, end: 1).animate( late final Animation<double> backgroundAnimation =
Tween<double>(begin: 0, end: 1).animate(
CurvedAnimation( CurvedAnimation(
parent: _openAnimController, parent: _openAnimController,
curve: const Interval(0.2, 1.0, curve: Curves.easeInOut), curve: const Interval(0.2, 1.0, curve: Curves.easeInOut),
), ),
); );
late final Animation<double> fullPageAnimation = Tween<double>(begin: 0, end: 1).animate( late final Animation<double> fullPageAnimation =
Tween<double>(begin: 0, end: 1).animate(
CurvedAnimation( CurvedAnimation(
parent: _openAnimController, parent: _openAnimController,
curve: const Interval(0.0, 0.6, curve: Curves.easeInOut), curve: const Interval(0.0, 0.6, curve: Curves.easeInOut),
), ),
); );
late final Animation<double> backContainerAnimation = Tween<double>(begin: 100, end: 0).animate( late final Animation<double> backContainerAnimation =
Tween<double>(begin: 100, end: 0).animate(
CurvedAnimation( CurvedAnimation(
parent: _openAnimController, parent: _openAnimController,
curve: const Interval(0.0, 0.9, curve: Curves.easeInOut), curve: const Interval(0.0, 0.9, curve: Curves.easeInOut),
), ),
); );
late final Animation<double> backContentAnimation = Tween<double>(begin: 100, end: 0).animate( late final Animation<double> backContentAnimation =
Tween<double>(begin: 100, end: 0).animate(
CurvedAnimation( CurvedAnimation(
parent: _openAnimController, parent: _openAnimController,
curve: const Interval(0.2, 1.0, curve: Curves.easeInOut), curve: const Interval(0.2, 1.0, curve: Curves.easeInOut),
), ),
); );
late final Animation<double> backContentScaleAnimation = Tween<double>(begin: 0.8, end: 0.9).animate( late final Animation<double> backContentScaleAnimation =
Tween<double>(begin: 0.8, end: 0.9).animate(
CurvedAnimation( CurvedAnimation(
parent: _openAnimController, parent: _openAnimController,
curve: const Interval(0.45, 1.0, curve: Curves.easeInOut), curve: const Interval(0.45, 1.0, curve: Curves.easeInOut),
), ),
); );
late final Animation<double> pickerContainerAnimation = Tween<double>(begin: 0, end: 1).animate( late final Animation<double> pickerContainerAnimation =
Tween<double>(begin: 0, end: 1).animate(
CurvedAnimation( CurvedAnimation(
parent: _openAnimController, parent: _openAnimController,
curve: const Interval(0.25, 0.8, curve: Curves.easeInOut), curve: const Interval(0.25, 0.8, curve: Curves.easeInOut),
@ -90,7 +99,8 @@ class _PremiumCustomAccentColorSettingState extends State<PremiumCustomAccentCol
_testTabController = TabController(length: 4, vsync: this); _testTabController = TabController(length: 4, vsync: this);
settings = Provider.of<SettingsProvider>(context, listen: false); settings = Provider.of<SettingsProvider>(context, listen: false);
_openAnimController = AnimationController(vsync: this, duration: const Duration(milliseconds: 750)); _openAnimController = AnimationController(
vsync: this, duration: const Duration(milliseconds: 750));
_openAnimController.forward(); _openAnimController.forward();
} }
@ -102,13 +112,20 @@ class _PremiumCustomAccentColorSettingState extends State<PremiumCustomAccentCol
void setTheme(ThemeMode mode, bool store) async { void setTheme(ThemeMode mode, bool store) async {
await settings.update(theme: mode, store: store); await settings.update(theme: mode, store: store);
Provider.of<ThemeModeObserver>(context, listen: false).changeTheme(mode, updateNavbarColor: false); Provider.of<ThemeModeObserver>(context, listen: false)
.changeTheme(mode, updateNavbarColor: false);
} }
Color? getCustomColor() { dynamic getCustomColor() {
switch (colorMode) { switch (colorMode) {
case CustomColorMode.theme: case CustomColorMode.theme:
return accentColorMap[settings.accentColor]; return accentColorMap[settings.accentColor];
case CustomColorMode.saved:
return [
settings.customBackgroundColor,
settings.customHighlightColor,
settings.customAccentColor
];
case CustomColorMode.background: case CustomColorMode.background:
return settings.customBackgroundColor; return settings.customBackgroundColor;
case CustomColorMode.highlight: case CustomColorMode.highlight:
@ -118,16 +135,30 @@ class _PremiumCustomAccentColorSettingState extends State<PremiumCustomAccentCol
} }
} }
void updateCustomColor(Color v, bool store) { void updateCustomColor(dynamic v, bool store) {
if (colorMode != CustomColorMode.theme) settings.update(accentColor: AccentColor.custom, store: store); if (colorMode != CustomColorMode.theme) {
settings.update(accentColor: AccentColor.custom, store: store);
}
switch (colorMode) { switch (colorMode) {
case CustomColorMode.theme: case CustomColorMode.theme:
settings.update( settings.update(
accentColor: accentColorMap.keys.firstWhere((element) => accentColorMap[element] == v, orElse: () => AccentColor.filc), store: store); accentColor: accentColorMap.keys.firstWhere(
settings.update(customBackgroundColor: AppColors.of(context).background, store: store); (element) => accentColorMap[element] == v,
settings.update(customHighlightColor: AppColors.of(context).highlight, store: store); orElse: () => AccentColor.filc),
store: store);
settings.update(
customBackgroundColor: AppColors.of(context).background,
store: store);
settings.update(
customHighlightColor: AppColors.of(context).highlight,
store: store);
settings.update(customAccentColor: v, store: store); settings.update(customAccentColor: v, store: store);
break; break;
case CustomColorMode.saved:
settings.update(customBackgroundColor: v[0], store: store);
settings.update(customHighlightColor: v[1], store: store);
settings.update(customAccentColor: v[3], store: store);
break;
case CustomColorMode.background: case CustomColorMode.background:
settings.update(customBackgroundColor: v, store: store); settings.update(customBackgroundColor: v, store: store);
break; break;
@ -142,14 +173,19 @@ class _PremiumCustomAccentColorSettingState extends State<PremiumCustomAccentCol
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
bool hasAccess = Provider.of<PremiumProvider>(context).hasScope(PremiumScopes.customColors); bool hasAccess = Provider.of<PremiumProvider>(context)
bool isBackgroundDifferent = Theme.of(context).colorScheme.background != AppColors.of(context).background; .hasScope(PremiumScopes.customColors);
bool isBackgroundDifferent = Theme.of(context).colorScheme.background !=
AppColors.of(context).background;
ThemeMode currentTheme = Theme.of(context).brightness == Brightness.light ? ThemeMode.light : ThemeMode.dark; ThemeMode currentTheme = Theme.of(context).brightness == Brightness.light
? ThemeMode.light
: ThemeMode.dark;
return WillPopScope( return WillPopScope(
onWillPop: () async { onWillPop: () async {
Provider.of<ThemeModeObserver>(context, listen: false).changeTheme(settings.theme, updateNavbarColor: true); Provider.of<ThemeModeObserver>(context, listen: false)
.changeTheme(settings.theme, updateNavbarColor: true);
return true; return true;
}, },
child: AnimatedBuilder( child: AnimatedBuilder(
@ -158,7 +194,9 @@ class _PremiumCustomAccentColorSettingState extends State<PremiumCustomAccentCol
final backgroundGradientBottomColor = isBackgroundDifferent final backgroundGradientBottomColor = isBackgroundDifferent
? Theme.of(context).colorScheme.background ? Theme.of(context).colorScheme.background
: HSVColor.fromColor(Theme.of(context).colorScheme.background) : HSVColor.fromColor(Theme.of(context).colorScheme.background)
.withValue(currentTheme == ThemeMode.dark ? 0.1 * _openAnimController.value : 1.0 - (0.1 * _openAnimController.value)) .withValue(currentTheme == ThemeMode.dark
? 0.1 * _openAnimController.value
: 1.0 - (0.1 * _openAnimController.value))
.withAlpha(1.0) .withAlpha(1.0)
.toColor(); .toColor();
@ -174,13 +212,15 @@ class _PremiumCustomAccentColorSettingState extends State<PremiumCustomAccentCol
stops: const [0.0, 0.75], stops: const [0.0, 0.75],
colors: isBackgroundDifferent colors: isBackgroundDifferent
? [ ? [
Theme.of(context) Theme.of(context).colorScheme.background.withOpacity(1 -
.colorScheme ((currentTheme == ThemeMode.dark ? 0.65 : 0.45) *
.background backgroundAnimation.value)),
.withOpacity(1 - ((currentTheme == ThemeMode.dark ? 0.65 : 0.45) * backgroundAnimation.value)),
backgroundGradientBottomColor, backgroundGradientBottomColor,
] ]
: [backgroundGradientBottomColor, backgroundGradientBottomColor], : [
backgroundGradientBottomColor,
backgroundGradientBottomColor
],
), ),
), ),
child: Opacity( child: Opacity(
@ -191,7 +231,7 @@ class _PremiumCustomAccentColorSettingState extends State<PremiumCustomAccentCol
surfaceTintColor: Theme.of(context).scaffoldBackgroundColor, surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
leading: BackButton(color: AppColors.of(context).text), leading: BackButton(color: AppColors.of(context).text),
title: Text( title: Text(
"Preview", "theme_prev".i18n,
style: TextStyle(color: AppColors.of(context).text), style: TextStyle(color: AppColors.of(context).text),
), ),
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
@ -208,20 +248,32 @@ class _PremiumCustomAccentColorSettingState extends State<PremiumCustomAccentCol
width: double.infinity, width: double.infinity,
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(24), borderRadius: BorderRadius.circular(24),
gradient: LinearGradient(begin: Alignment.topCenter, end: Alignment.bottomCenter, stops: const [ gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
stops: const [
0.35, 0.35,
0.75 0.75
], colors: [ ],
colors: [
Theme.of(context).colorScheme.background, Theme.of(context).colorScheme.background,
isBackgroundDifferent isBackgroundDifferent
? HSVColor.fromColor(Theme.of(context).colorScheme.background) ? HSVColor.fromColor(Theme.of(context)
.withSaturation( .colorScheme
(HSVColor.fromColor(Theme.of(context).colorScheme.background).saturation - 0.15).clamp(0.0, 1.0)) .background)
.withSaturation((HSVColor.fromColor(
Theme.of(context)
.colorScheme
.background)
.saturation -
0.15)
.clamp(0.0, 1.0))
.toColor() .toColor()
: backgroundGradientBottomColor, : backgroundGradientBottomColor,
]), ]),
), ),
margin: const EdgeInsets.symmetric(vertical: 30, horizontal: 20), margin: const EdgeInsets.symmetric(
vertical: 30, horizontal: 20),
), ),
), ),
), ),
@ -236,13 +288,15 @@ class _PremiumCustomAccentColorSettingState extends State<PremiumCustomAccentCol
child: SingleChildScrollView( child: SingleChildScrollView(
physics: const BouncingScrollPhysics(), physics: const BouncingScrollPhysics(),
child: Transform.translate( child: Transform.translate(
offset: Offset(0, -24 + backContentAnimation.value), offset:
Offset(0, -24 + backContentAnimation.value),
child: Transform.scale( child: Transform.scale(
scale: backContentScaleAnimation.value, scale: backContentScaleAnimation.value,
child: Column( child: Column(
children: [ children: [
Padding( Padding(
padding: const EdgeInsets.symmetric(horizontal: 32.0, vertical: 6.0), padding: const EdgeInsets.symmetric(
horizontal: 32.0, vertical: 6.0),
child: FilterBar( child: FilterBar(
items: const [ items: const [
Tab(text: "All"), Tab(text: "All"),
@ -256,26 +310,35 @@ class _PremiumCustomAccentColorSettingState extends State<PremiumCustomAccentCol
), ),
), ),
Padding( Padding(
padding: const EdgeInsets.symmetric(horizontal: 18.0, vertical: 8.0), padding: const EdgeInsets.symmetric(
horizontal: 18.0, vertical: 8.0),
child: NewGradesSurprise( child: NewGradesSurprise(
[ [
Grade.fromJson( Grade.fromJson(
{ {
"Uid": "0,Ertekeles", "Uid": "0,Ertekeles",
"RogzitesDatuma": "2022-01-01T23:00:00Z", "RogzitesDatuma":
"KeszitesDatuma": "2022-01-01T23:00:00Z", "2022-01-01T23:00:00Z",
"KeszitesDatuma":
"2022-01-01T23:00:00Z",
"LattamozasDatuma": null, "LattamozasDatuma": null,
"Tantargy": { "Tantargy": {
"Uid": "0", "Uid": "0",
"Nev": "reFilc szakirodalom", "Nev": "reFilc szakirodalom",
"Kategoria": {"Uid": "0,_", "Nev": "_", "Leiras": "Nem mondom meg"}, "Kategoria": {
"Uid": "0,_",
"Nev": "_",
"Leiras": "Nem mondom meg"
},
"SortIndex": 2 "SortIndex": 2
}, },
"Tema": "Kupak csomag vásárlás vizsga", "Tema":
"Kupak csomag vásárlás vizsga",
"Tipus": { "Tipus": {
"Uid": "0,_", "Uid": "0,_",
"Nev": "_", "Nev": "_",
"Leiras": "Évközi jegy/értékelés", "Leiras":
"Évközi jegy/értékelés",
}, },
"Mod": { "Mod": {
"Uid": "0,_", "Uid": "0,_",
@ -285,14 +348,16 @@ class _PremiumCustomAccentColorSettingState extends State<PremiumCustomAccentCol
"ErtekFajta": { "ErtekFajta": {
"Uid": "1,Osztalyzat", "Uid": "1,Osztalyzat",
"Nev": "Osztalyzat", "Nev": "Osztalyzat",
"Leiras": "Elégtelen (1) és Jeles (5) között az öt alapértelmezett érték" "Leiras":
"Elégtelen (1) és Jeles (5) között az öt alapértelmezett érték"
}, },
"ErtekeloTanarNeve": "Premium", "ErtekeloTanarNeve": "Premium",
"Jelleg": "Ertekeles", "Jelleg": "Ertekeles",
"SzamErtek": 5, "SzamErtek": 5,
"SzovegesErtek": "Jeles(5)", "SzovegesErtek": "Jeles(5)",
"SulySzazalekErteke": 100, "SulySzazalekErteke": 100,
"SzovegesErtekelesRovidNev": null, "SzovegesErtekelesRovidNev":
null,
"OsztalyCsoport": {"Uid": "0"}, "OsztalyCsoport": {"Uid": "0"},
"SortIndex": 2 "SortIndex": 2
}, },
@ -302,26 +367,35 @@ class _PremiumCustomAccentColorSettingState extends State<PremiumCustomAccentCol
), ),
), ),
Padding( Padding(
padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 6.0), padding: const EdgeInsets.symmetric(
horizontal: 24.0, vertical: 6.0),
child: Panel( child: Panel(
child: GradeTile( child: GradeTile(
Grade.fromJson( Grade.fromJson(
{ {
"Uid": "0,Ertekeles", "Uid": "0,Ertekeles",
"RogzitesDatuma": "2022-01-01T23:00:00Z", "RogzitesDatuma":
"KeszitesDatuma": "2022-01-01T23:00:00Z", "2022-01-01T23:00:00Z",
"KeszitesDatuma":
"2022-01-01T23:00:00Z",
"LattamozasDatuma": null, "LattamozasDatuma": null,
"Tantargy": { "Tantargy": {
"Uid": "0", "Uid": "0",
"Nev": "reFilc szakosztály", "Nev": "reFilc szakosztály",
"Kategoria": {"Uid": "0,_", "Nev": "_", "Leiras": "Nem mondom meg"}, "Kategoria": {
"Uid": "0,_",
"Nev": "_",
"Leiras": "Nem mondom meg"
},
"SortIndex": 2 "SortIndex": 2
}, },
"Tema": "Kupak csomag vásárlás vizsga", "Tema":
"Kupak csomag vásárlás vizsga",
"Tipus": { "Tipus": {
"Uid": "0,_", "Uid": "0,_",
"Nev": "_", "Nev": "_",
"Leiras": "Évközi jegy/értékelés", "Leiras":
"Évközi jegy/értékelés",
}, },
"Mod": { "Mod": {
"Uid": "0,_", "Uid": "0,_",
@ -331,14 +405,16 @@ class _PremiumCustomAccentColorSettingState extends State<PremiumCustomAccentCol
"ErtekFajta": { "ErtekFajta": {
"Uid": "1,Osztalyzat", "Uid": "1,Osztalyzat",
"Nev": "Osztalyzat", "Nev": "Osztalyzat",
"Leiras": "Elégtelen (1) és Jeles (5) között az öt alapértelmezett érték" "Leiras":
"Elégtelen (1) és Jeles (5) között az öt alapértelmezett érték"
}, },
"ErtekeloTanarNeve": "Premium", "ErtekeloTanarNeve": "Premium",
"Jelleg": "Ertekeles", "Jelleg": "Ertekeles",
"SzamErtek": 5, "SzamErtek": 5,
"SzovegesErtek": "Jeles(5)", "SzovegesErtek": "Jeles(5)",
"SulySzazalekErteke": 100, "SulySzazalekErteke": 100,
"SzovegesErtekelesRovidNev": null, "SzovegesErtekelesRovidNev":
null,
"OsztalyCsoport": {"Uid": "0"}, "OsztalyCsoport": {"Uid": "0"},
"SortIndex": 2 "SortIndex": 2
}, },
@ -349,7 +425,8 @@ class _PremiumCustomAccentColorSettingState extends State<PremiumCustomAccentCol
), ),
), ),
Padding( Padding(
padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 6.0), padding: const EdgeInsets.symmetric(
horizontal: 24.0, vertical: 6.0),
child: Panel( child: Panel(
child: HomeworkTile( child: HomeworkTile(
Homework.fromJson( Homework.fromJson(
@ -357,22 +434,31 @@ class _PremiumCustomAccentColorSettingState extends State<PremiumCustomAccentCol
"Uid": "0", "Uid": "0",
"Tantargy": { "Tantargy": {
"Uid": "0", "Uid": "0",
"Nev": "reFilc premium előnyei", "Nev":
"reFilc premium előnyei",
"Kategoria": { "Kategoria": {
"Uid": "0,_", "Uid": "0,_",
"Nev": "_", "Nev": "_",
"Leiras": "reFilc premium előnyei", "Leiras":
"reFilc premium előnyei",
}, },
"SortIndex": 0 "SortIndex": 0
}, },
"TantargyNeve": "reFilc premium előnyei", "TantargyNeve":
"RogzitoTanarNeve": "Kupak János", "reFilc premium előnyei",
"Szoveg": "45 perc filctollal való rajzolás", "RogzitoTanarNeve":
"FeladasDatuma": "2022-01-01T23:00:00Z", "Kupak János",
"HataridoDatuma": "2022-01-01T23:00:00Z", "Szoveg":
"RogzitesIdopontja": "2022-01-01T23:00:00Z", "45 perc filctollal való rajzolás",
"FeladasDatuma":
"2022-01-01T23:00:00Z",
"HataridoDatuma":
"2022-01-01T23:00:00Z",
"RogzitesIdopontja":
"2022-01-01T23:00:00Z",
"IsTanarRogzitette": true, "IsTanarRogzitette": true,
"IsTanuloHaziFeladatEnabled": false, "IsTanuloHaziFeladatEnabled":
false,
"IsMegoldva": false, "IsMegoldva": false,
"IsBeadhato": false, "IsBeadhato": false,
"OsztalyCsoport": {"Uid": "0"}, "OsztalyCsoport": {"Uid": "0"},
@ -385,7 +471,8 @@ class _PremiumCustomAccentColorSettingState extends State<PremiumCustomAccentCol
), ),
), ),
Padding( Padding(
padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 6.0), padding: const EdgeInsets.symmetric(
horizontal: 24.0, vertical: 6.0),
child: Panel( child: Panel(
child: MessageTile( child: MessageTile(
Message.fromJson( Message.fromJson(
@ -396,18 +483,22 @@ class _PremiumCustomAccentColorSettingState extends State<PremiumCustomAccentCol
"tipus": { "tipus": {
"azonosito": 1, "azonosito": 1,
"kod": "BEERKEZETT", "kod": "BEERKEZETT",
"rovidNev": "Beérkezett üzenet", "rovidNev":
"Beérkezett üzenet",
"nev": "Beérkezett üzenet", "nev": "Beérkezett üzenet",
"leiras": "Beérkezett üzenet" "leiras": "Beérkezett üzenet"
}, },
"uzenet": { "uzenet": {
"azonosito": 0, "azonosito": 0,
"kuldesDatum": "2022-01-01T23:00:00", "kuldesDatum":
"2022-01-01T23:00:00",
"feladoNev": "reFilc", "feladoNev": "reFilc",
"feladoTitulus": "Nagyon magas szintű személy", "feladoTitulus":
"Nagyon magas szintű személy",
"szoveg": "szoveg":
"<p>Kedves Felhasználó!</p><p><br></p><p>A prémium vásárlásakor kapott filctollal 90%-al több esély van jó jegyek szerzésére.</p>", "<p>Kedves Felhasználó!</p><p><br></p><p>A prémium vásárlásakor kapott filctollal 90%-al több esély van jó jegyek szerzésére.</p>",
"targy": "Filctoll használati útmutató", "targy":
"Filctoll használati útmutató",
"statusz": { "statusz": {
"azonosito": 2, "azonosito": 2,
"kod": "KIKULDVE", "kod": "KIKULDVE",
@ -430,7 +521,10 @@ class _PremiumCustomAccentColorSettingState extends State<PremiumCustomAccentCol
}, },
], ],
"csatolmanyok": [ "csatolmanyok": [
{"azonosito": 0, "fajlNev": "Filctoll.doc"} {
"azonosito": 0,
"fajlNev": "Filctoll.doc"
}
] ]
} }
}, },
@ -462,15 +556,19 @@ class _PremiumCustomAccentColorSettingState extends State<PremiumCustomAccentCol
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: backgroundGradientBottomColor, color: backgroundGradientBottomColor,
offset: const Offset(0, -4), offset: const Offset(0, -8),
blurRadius: 16, blurRadius: 16,
spreadRadius: 12, spreadRadius: 18,
), ),
], ],
gradient: LinearGradient(begin: Alignment.topCenter, end: Alignment.bottomCenter, stops: const [ gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
stops: const [
0.0, 0.0,
0.175 0.175
], colors: [ ],
colors: [
backgroundGradientBottomColor, backgroundGradientBottomColor,
backgroundGradientBottomColor, backgroundGradientBottomColor,
]), ]),
@ -478,52 +576,90 @@ class _PremiumCustomAccentColorSettingState extends State<PremiumCustomAccentCol
child: Column( child: Column(
children: [ children: [
Padding( Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0), padding: const EdgeInsets.symmetric(
horizontal: 8.0),
child: FilterBar( child: FilterBar(
items: [ items: [
ColorTab( ColorTab(
color: accentColorMap[settings.accentColor] ?? unknownColor, color: accentColorMap[
tab: Tab(text: "colorpicker_presets".i18n)), settings.accentColor] ??
unknownColor,
tab: Tab(
text: "colorpicker_presets"
.i18n)),
/*ColorTab(
color:
settings.customAccentColor ??
unknownColor,
tab: Tab(
text: "colorpicker_saved"
.i18n)),*/
ColorTab( ColorTab(
unlocked: hasAccess, unlocked: hasAccess,
color: settings.customBackgroundColor ?? unknownColor, color: settings
tab: Tab(text: "colorpicker_background".i18n)), .customBackgroundColor ??
unknownColor,
tab: Tab(
text: "colorpicker_background"
.i18n)),
ColorTab( ColorTab(
unlocked: hasAccess, unlocked: hasAccess,
color: settings.customHighlightColor ?? unknownColor, color: settings
tab: Tab(text: "colorpicker_panels".i18n)), .customHighlightColor ??
unknownColor,
tab: Tab(
text: "colorpicker_panels"
.i18n)),
ColorTab( ColorTab(
unlocked: hasAccess, unlocked: hasAccess,
color: settings.customAccentColor ?? unknownColor, color:
tab: Tab(text: "colorpicker_accent".i18n)), settings.customAccentColor ??
unknownColor,
tab: Tab(
text: "colorpicker_accent"
.i18n)),
], ],
onTap: (index) { onTap: (index) {
if (!hasAccess) { if (!hasAccess) {
index = 0; index = 0;
_colorsTabController.animateTo(0, duration: Duration.zero); _colorsTabController.animateTo(0,
duration: Duration.zero);
PremiumLockedFeatureUpsell.show(context: context, feature: PremiumFeature.customcolors); PremiumLockedFeatureUpsell.show(
context: context,
feature: PremiumFeature
.customcolors);
} }
switch (index) { switch (index) {
case 0: case 0:
setState(() { setState(() {
colorMode = CustomColorMode.theme; colorMode =
CustomColorMode.theme;
}); });
break; break;
/*case 1:
setState(() {
colorMode =
CustomColorMode.saved;
});
break;*/
case 1: case 1:
setState(() { setState(() {
colorMode = CustomColorMode.background; colorMode =
CustomColorMode.background;
}); });
break; break;
case 2: case 2:
setState(() { setState(() {
colorMode = CustomColorMode.highlight; colorMode =
CustomColorMode.highlight;
}); });
break; break;
case 3: case 3:
setState(() { setState(() {
colorMode = CustomColorMode.accent; colorMode =
CustomColorMode.accent;
}); });
break; break;
} }
@ -533,17 +669,29 @@ class _PremiumCustomAccentColorSettingState extends State<PremiumCustomAccentCol
), ),
), ),
Padding( Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0), padding: const EdgeInsets.symmetric(
horizontal: 12.0),
child: SafeArea( child: SafeArea(
child: FilcColorPicker( child: FilcColorPicker(
colorMode: colorMode, colorMode: colorMode,
pickerColor: colorMode == CustomColorMode.accent pickerColor: colorMode ==
? settings.customAccentColor ?? unknownColor CustomColorMode.accent
: colorMode == CustomColorMode.background ? settings.customAccentColor ??
? settings.customBackgroundColor ?? unknownColor unknownColor
: colorMode == CustomColorMode.theme : colorMode ==
? (accentColorMap[settings.accentColor] ?? AppColors.of(context).text) // idk what else CustomColorMode.background
: settings.customHighlightColor ?? unknownColor, ? settings
.customBackgroundColor ??
unknownColor
: colorMode ==
CustomColorMode.theme
? (accentColorMap[settings
.accentColor] ??
AppColors.of(context)
.text) // idk what else
: settings
.customHighlightColor ??
unknownColor,
onColorChanged: (c) { onColorChanged: (c) {
setState(() { setState(() {
updateCustomColor(c, false); updateCustomColor(c, false);
@ -553,9 +701,19 @@ class _PremiumCustomAccentColorSettingState extends State<PremiumCustomAccentCol
onColorChangeEnd: (c, {adaptive}) { onColorChangeEnd: (c, {adaptive}) {
setState(() { setState(() {
if (adaptive == true) { if (adaptive == true) {
settings.update(accentColor: AccentColor.adaptive); settings.update(
settings.update(customBackgroundColor: AppColors.of(context).background, store: true); accentColor:
settings.update(customHighlightColor: AppColors.of(context).highlight, store: true); AccentColor.adaptive);
settings.update(
customBackgroundColor:
AppColors.of(context)
.background,
store: true);
settings.update(
customHighlightColor:
AppColors.of(context)
.highlight,
store: true);
} else { } else {
updateCustomColor(c, true); updateCustomColor(c, true);
} }
@ -585,7 +743,9 @@ class _PremiumCustomAccentColorSettingState extends State<PremiumCustomAccentCol
} }
class ColorTab extends StatelessWidget { class ColorTab extends StatelessWidget {
const ColorTab({Key? key, required this.tab, required this.color, this.unlocked = true}) : super(key: key); const ColorTab(
{Key? key, required this.tab, required this.color, this.unlocked = true})
: super(key: key);
final Tab tab; final Tab tab;
final Color color; final Color color;
@ -610,7 +770,8 @@ class ColorTab extends StatelessWidget {
) )
: const Padding( : const Padding(
padding: EdgeInsets.symmetric(horizontal: 2), padding: EdgeInsets.symmetric(horizontal: 2),
child: Icon(Icons.lock, color: Color.fromARGB(255, 82, 82, 82), size: 18), child: Icon(Icons.lock,
color: Color.fromARGB(255, 82, 82, 82), size: 18),
), ),
), ),
tab tab
@ -620,7 +781,9 @@ class ColorTab extends StatelessWidget {
} }
class PremiumColorPickerItem extends StatelessWidget { class PremiumColorPickerItem extends StatelessWidget {
const PremiumColorPickerItem({Key? key, required this.label, this.onTap, required this.color}) : super(key: key); const PremiumColorPickerItem(
{Key? key, required this.label, this.onTap, required this.color})
: super(key: key);
final String label; final String label;
final void Function()? onTap; final void Function()? onTap;
@ -639,13 +802,16 @@ class PremiumColorPickerItem extends StatelessWidget {
Expanded( Expanded(
child: Text( child: Text(
label, label,
style: TextStyle(color: AppColors.of(context).text, fontWeight: FontWeight.w500), style: TextStyle(
color: AppColors.of(context).text,
fontWeight: FontWeight.w500),
), ),
), ),
Container( Container(
width: 30, width: 30,
height: 30, height: 30,
decoration: BoxDecoration(color: color, shape: BoxShape.circle, border: Border.all()), decoration: BoxDecoration(
color: color, shape: BoxShape.circle, border: Border.all()),
), ),
], ],
), ),

View File

@ -4,25 +4,32 @@ extension SettingsLocalization on String {
static final _t = Translations.byLocale("hu_hu") + static final _t = Translations.byLocale("hu_hu") +
{ {
"en_en": { "en_en": {
"theme_prev": "Preview",
"colorpicker_presets": "Presets", "colorpicker_presets": "Presets",
"colorpicker_background": "Background", "colorpicker_background": "Background",
"colorpicker_panels": "Panels", "colorpicker_panels": "Panels",
"colorpicker_accent": "Accent", "colorpicker_accent": "Accent",
"need_sub": "You need Kupak subscription to use modify this.", "need_sub": "You need Kupak subscription to use modify this.",
"advanced": "Advanced",
}, },
"hu_hu": { "hu_hu": {
"theme_prev": "Előnézet",
"colorpicker_presets": "Téma", "colorpicker_presets": "Téma",
"colorpicker_background": "Háttér", "colorpicker_background": "Háttér",
"colorpicker_panels": "Panelek", "colorpicker_panels": "Panelek",
"colorpicker_accent": "Színtónus", "colorpicker_accent": "Színtónus",
"need_sub": "A módosításhoz Kupak szintű támogatás szükséges.", "need_sub": "A módosításhoz Kupak szintű támogatás szükséges.",
"advanced": "Fejlett",
}, },
"de_de": { "de_de": {
"theme_prev": "Vorschau",
"colorpicker_presets": "Farben", "colorpicker_presets": "Farben",
"colorpicker_background": "Hintergrund", "colorpicker_background": "Hintergrund",
"colorpicker_panels": "Tafeln", "colorpicker_panels": "Tafeln",
"colorpicker_accent": "Akzent", "colorpicker_accent": "Akzent",
"need_sub": "Sie benötigen ein Kupak-Abonnement, um diese Funktion zu ändern.", "need_sub":
"Sie benötigen ein Kupak-Abonnement, um diese Funktion zu ändern.",
"advanced": "Fortschrittlich",
}, },
}; };