Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
db58b54754 | ||
|
|
7de3d211bb | ||
|
|
d3e5fc99ea | ||
|
|
17cffc0576 | ||
|
|
f38ff3b862 | ||
|
|
89e67c369e | ||
|
|
6dd68c8f5d | ||
|
|
97b01e9f14 | ||
|
|
556ba9d289 | ||
|
|
64868e85f3 | ||
|
|
30ac155b4b | ||
|
|
36bd679644 | ||
|
|
75b03b95bc | ||
|
|
ac18cf62c3 | ||
|
|
3619a7a4a7 | ||
|
|
a71b365e4a | ||
|
|
20fa9a8aef | ||
|
|
da12ac8646 | ||
|
|
4b40692fe1 | ||
|
|
26f65a4144 | ||
|
|
f8cfa04d04 | ||
|
|
82671f5ec9 | ||
|
|
5d37de897f | ||
|
|
fcb1d8d6d9 | ||
|
|
446fad4c5f | ||
|
|
0f799375a1 | ||
|
|
29aa356cd0 | ||
|
|
3abaf2f96a | ||
|
|
5b48847cf2 |
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
@@ -1 +1 @@
|
||||
patreon: filcnaplo
|
||||
github: filc
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,6 +1,7 @@
|
||||
# See https://www.dartlang.org/guides/libraries/private-files
|
||||
|
||||
termek.txt
|
||||
.DS_Store
|
||||
|
||||
# Files and directories created by pub
|
||||
.dart_tool/
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
What's new:
|
||||
|
||||
- Hibajavítások 🐛🐛🐛🐛
|
||||
- Több szín lehetőség, egyedi hexadecimális szín választás
|
||||
- Több tanuló esetén legutóbb kiválasztott tanuló mutatása indításkor
|
||||
- Hibajavítások 🐛
|
||||
- **Megérkezett a Filc Premium!** ✨
|
||||
|
||||
@@ -26,13 +26,8 @@ apply plugin: 'kotlin-android'
|
||||
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
||||
|
||||
def keystoreProperties = new Properties()
|
||||
def keystorePropertiesFile = rootProject.file("$System.env.ANDROID_SIGNING")
|
||||
if (keystorePropertiesFile.exists()) {
|
||||
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
|
||||
} else {
|
||||
keystoreProperties.load(new FileInputStream(rootProject.file("signing/signing.properties")))
|
||||
|
||||
}
|
||||
def keystorePropertiesFile = rootProject.file("$System.env.HOME/keys/filc3.properties")
|
||||
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
|
||||
|
||||
android {
|
||||
compileSdkVersion rootProject.ext.compileSdkVersion
|
||||
|
||||
@@ -6,8 +6,47 @@
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<!-- Accepts URIs that begin with https://api.filcnaplo.hu -->
|
||||
<data
|
||||
android:scheme="https"
|
||||
android:host="api.filcnaplo.hu"
|
||||
android:pathPrefix="/callback" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<meta-data android:name="flutterEmbedding" android:value="2" />
|
||||
|
||||
<!-- <receiver android:name=".WidgetTimetable.widget_timetable"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
<action android:name="list_widget.ACTION_WIDGET_CLICK_NAV_LEFT" />
|
||||
<action android:name="list_widget.ACTION_WIDGET_CLICK_NAV_RIGHT" />
|
||||
<action android:name="list_widget.ACTION_WIDGET_CLICK_NAV_TODAY" />
|
||||
<action android:name="list_widget.ACTION_WIDGET_CLICK_NAV_REFRESH" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/home_widget_test_info" />
|
||||
</receiver>
|
||||
|
||||
<service android:name=".WidgetTimetable.widget_timetable_service"
|
||||
android:permission="android.permission.BIND_REMOTEVIEWS" />
|
||||
|
||||
<receiver android:name="es.antonborri.home_widget.HomeWidgetBackgroundReceiver"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="es.antonborri.home_widget.action.BACKGROUND" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<service android:name="es.antonborri.home_widget.HomeWidgetBackgroundService"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE" android:exported="true" />
|
||||
-->
|
||||
</application>
|
||||
|
||||
<!-- Permissions -->
|
||||
|
||||
Binary file not shown.
@@ -1,4 +0,0 @@
|
||||
keyAlias=test
|
||||
keyPassword=test123
|
||||
storeFile=../signing/signing.keystore
|
||||
storePassword=test123
|
||||
Binary file not shown.
12
filcnaplo/build.sh
Normal file → Executable file
12
filcnaplo/build.sh
Normal file → Executable file
@@ -1,4 +1,4 @@
|
||||
#!/bin/fish
|
||||
#!/usr/bin/env fish
|
||||
|
||||
# With build number
|
||||
function get_version_bn
|
||||
@@ -9,11 +9,5 @@ function get_version
|
||||
cat pubspec.yaml | grep version: | cut -d' ' -f2 | cut -d+ -f1
|
||||
end
|
||||
|
||||
if test -e /mnt/enc/keys/filc3.properties
|
||||
set -x ANDROID_SIGNING /mnt/enc/keys/filc3.properties
|
||||
end
|
||||
|
||||
flutter build apk --release --dart-define=APPVER=(get_version) --no-tree-shake-icons
|
||||
cp -v "build/app/outputs/flutter-apk/app-release.apk" ~/"Desktop/hu.filc.naplo_"(get_version_bn).apk
|
||||
|
||||
notify-send "Flutter" "Apk build done."
|
||||
flutter build apk --release --dart-define=APPVER=(get_version) --no-tree-shake-icons && \
|
||||
cp -v "build/app/outputs/flutter-apk/app-release.apk" ~/"Desktop/hu.filc.naplo_"(get_version_bn).apk
|
||||
|
||||
@@ -517,7 +517,7 @@
|
||||
MARKETING_VERSION = 1.0;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = hu.filc.naplo.livecard;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = hu.filc.naplo.livecardpro;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SKIP_INSTALL = YES;
|
||||
@@ -557,7 +557,7 @@
|
||||
);
|
||||
MARKETING_VERSION = 1.0;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = hu.filc.naplo.livecard;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = hu.filc.naplo.livecardpro;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SKIP_INSTALL = YES;
|
||||
@@ -596,7 +596,7 @@
|
||||
);
|
||||
MARKETING_VERSION = 1.0;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = hu.filc.naplo.livecard;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = hu.filc.naplo.livecardpro;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SKIP_INSTALL = YES;
|
||||
|
||||
@@ -4,5 +4,9 @@
|
||||
<dict>
|
||||
<key>aps-environment</key>
|
||||
<string>development</string>
|
||||
<key>com.apple.developer.associated-domains</key>
|
||||
<array>
|
||||
<string>applinks:api.filcnaplo.hu</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -21,6 +21,8 @@ class FilcAPI {
|
||||
// Private API
|
||||
static const config = "https://api.filcnaplo.hu/config";
|
||||
static const reportApi = "https://api.filcnaplo.hu/report";
|
||||
static const premiumApi = "https://api.filcnaplo.hu/premium/activate";
|
||||
static const premiumScopesApi = "https://api.filcnaplo.hu/premium/scopes";
|
||||
|
||||
// Updates
|
||||
static const repo = "filc/naplo";
|
||||
@@ -121,19 +123,16 @@ class FilcAPI {
|
||||
return null;
|
||||
}
|
||||
|
||||
static Future<http.StreamedResponse?> downloadRelease(Release release) {
|
||||
if (release.downloads.isNotEmpty) {
|
||||
static Future<http.StreamedResponse?> downloadRelease(ReleaseDownload release) {
|
||||
try {
|
||||
var client = http.Client();
|
||||
var request = http.Request('GET', Uri.parse(release.downloads.first));
|
||||
var request = http.Request('GET', Uri.parse(release.url));
|
||||
return client.send(request);
|
||||
} catch (error) {
|
||||
print("ERROR: FilcAPI.downloadRelease: $error");
|
||||
}
|
||||
}
|
||||
|
||||
return Future.value(null);
|
||||
}
|
||||
}
|
||||
|
||||
static Future<void> sendReport(ErrorReport report) async {
|
||||
try {
|
||||
|
||||
@@ -22,8 +22,8 @@ class LiveCardProvider extends ChangeNotifier {
|
||||
|
||||
LiveCardState currentState = LiveCardState.empty;
|
||||
late Timer _timer;
|
||||
late final TimetableProvider _lessonProvider;
|
||||
late final SettingsProvider _settingsProvider;
|
||||
late final TimetableProvider _timetable;
|
||||
late final SettingsProvider _settings;
|
||||
|
||||
late Duration _delay;
|
||||
|
||||
@@ -32,13 +32,13 @@ class LiveCardProvider extends ChangeNotifier {
|
||||
Map<String, String> _lastActivity = {};
|
||||
|
||||
LiveCardProvider({
|
||||
required TimetableProvider lessonProvider,
|
||||
required SettingsProvider settingsProvider,
|
||||
}) : _lessonProvider = lessonProvider,
|
||||
_settingsProvider = settingsProvider {
|
||||
required TimetableProvider timetable,
|
||||
required SettingsProvider settings,
|
||||
}) : _timetable = timetable,
|
||||
_settings = settings {
|
||||
_timer = Timer.periodic(const Duration(seconds: 1), (timer) => update());
|
||||
lessonProvider.restore().then((_) => update());
|
||||
_delay = settingsProvider.bellDelayEnabled ? Duration(seconds: settingsProvider.bellDelay) : Duration.zero;
|
||||
timetable.restore().then((_) => update());
|
||||
_delay = settings.bellDelayEnabled ? Duration(seconds: settings.bellDelay) : Duration.zero;
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -73,7 +73,7 @@ class LiveCardProvider extends ChangeNotifier {
|
||||
switch (currentState) {
|
||||
case LiveCardState.duringLesson:
|
||||
return {
|
||||
"icon": currentLesson != null ? SubjectIcon.resolve(subject: currentLesson?.subject).name : "book",
|
||||
"icon": currentLesson != null ? SubjectIcon.resolveName(subject: currentLesson?.subject) : "book",
|
||||
"index": currentLesson != null ? '${currentLesson!.lessonIndex}. ' : "",
|
||||
"title": currentLesson != null ? ShortSubject.resolve(subject: currentLesson?.subject).capital() : "",
|
||||
"subtitle": currentLesson?.room.replaceAll("_", " ") ?? "",
|
||||
@@ -127,19 +127,20 @@ class LiveCardProvider extends ChangeNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
List<Lesson> today = _today(_lessonProvider);
|
||||
List<Lesson> today = _today(_timetable);
|
||||
|
||||
if (today.isEmpty) {
|
||||
await _lessonProvider.fetch(week: Week.current());
|
||||
today = _today(_lessonProvider);
|
||||
await _timetable.fetch(week: Week.current());
|
||||
today = _today(_timetable);
|
||||
}
|
||||
|
||||
_delay = _settingsProvider.bellDelayEnabled ? Duration(seconds: _settingsProvider.bellDelay) : Duration.zero;
|
||||
_delay = _settings.bellDelayEnabled ? Duration(seconds: _settings.bellDelay) : Duration.zero;
|
||||
|
||||
final now = _now().add(_delay);
|
||||
|
||||
// Filter cancelled lessons #20
|
||||
today = today.where((lesson) => lesson.status?.name != "Elmaradt").toList();
|
||||
// Filter label lessons #128
|
||||
today = today.where((lesson) => lesson.status?.name != "Elmaradt" && lesson.subject.id != '' && !lesson.isEmpty).toList();
|
||||
|
||||
if (today.isNotEmpty) {
|
||||
// sort
|
||||
|
||||
@@ -41,7 +41,7 @@ class NewsProvider extends ChangeNotifier {
|
||||
}
|
||||
|
||||
_state = state_;
|
||||
Provider.of<SettingsProvider>(_context, listen: false).update(_context, newsState: _state);
|
||||
Provider.of<SettingsProvider>(_context, listen: false).update(newsState: _state);
|
||||
}
|
||||
|
||||
Future<void> fetch() async {
|
||||
@@ -53,7 +53,7 @@ class NewsProvider extends ChangeNotifier {
|
||||
|
||||
if (_fresh < 0) {
|
||||
_state = news_.length;
|
||||
Provider.of<SettingsProvider>(_context, listen: false).update(_context, newsState: _state);
|
||||
Provider.of<SettingsProvider>(_context, listen: false).update(newsState: _state);
|
||||
}
|
||||
|
||||
_fresh = max(_fresh, 0);
|
||||
@@ -72,7 +72,7 @@ class NewsProvider extends ChangeNotifier {
|
||||
_fresh--;
|
||||
_state++;
|
||||
|
||||
Provider.of<SettingsProvider>(_context, listen: false).update(_context, newsState: _state);
|
||||
Provider.of<SettingsProvider>(_context, listen: false).update(newsState: _state);
|
||||
|
||||
if (_fresh > 0) {
|
||||
show = true;
|
||||
|
||||
@@ -7,9 +7,12 @@ enum Status { network, maintenance, syncing }
|
||||
class StatusProvider extends ChangeNotifier {
|
||||
final List<Status> _stack = [];
|
||||
double _progress = 0.0;
|
||||
ConnectivityResult _networkType = ConnectivityResult.none;
|
||||
ConnectivityResult get networkType => _networkType;
|
||||
|
||||
StatusProvider() {
|
||||
_handleNetworkChanges();
|
||||
Connectivity().checkConnectivity().then((value) => _networkType = value);
|
||||
}
|
||||
|
||||
Status? getStatus() => _stack.isNotEmpty ? _stack[0] : null;
|
||||
@@ -18,6 +21,7 @@ class StatusProvider extends ChangeNotifier {
|
||||
|
||||
void _handleNetworkChanges() {
|
||||
Connectivity().onConnectivityChanged.listen((event) {
|
||||
_networkType = event;
|
||||
if (event == ConnectivityResult.none) {
|
||||
if (!_stack.contains(Status.network)) {
|
||||
_stack.insert(0, Status.network);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'package:filcnaplo/models/settings.dart';
|
||||
import 'package:filcnaplo/models/user.dart';
|
||||
import 'package:filcnaplo_kreta_api/models/student.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
@@ -15,9 +16,16 @@ class UserProvider with ChangeNotifier {
|
||||
String? get password => user?.password;
|
||||
Role? get role => user?.role;
|
||||
Student? get student => user?.student;
|
||||
String? get nickname => user?.nickname;
|
||||
String? get displayName => user?.displayName;
|
||||
|
||||
final SettingsProvider _settings;
|
||||
|
||||
UserProvider({required SettingsProvider settings}) : _settings = settings;
|
||||
|
||||
void setUser(String userId) {
|
||||
_selectedUserId = userId;
|
||||
_settings.update(lastAccountId: userId);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
|
||||
@@ -45,15 +45,14 @@ import 'package:filcnaplo/api/providers/user_provider.dart';
|
||||
import 'package:filcnaplo/api/providers/update_provider.dart';
|
||||
import 'package:filcnaplo_mobile_ui/pages/grades/calculator/grade_calculator_provider.dart';
|
||||
import 'package:flutter_displaymode/flutter_displaymode.dart';
|
||||
import 'package:filcnaplo_premium/providers/premium_provider.dart';
|
||||
|
||||
class App extends StatelessWidget {
|
||||
final SettingsProvider settings;
|
||||
final UserProvider user;
|
||||
final DatabaseProvider database;
|
||||
|
||||
App({Key? key, required this.database, required this.settings, required this.user}) : super(key: key) {
|
||||
if (user.getUsers().isNotEmpty) user.setUser(user.getUsers().first.id);
|
||||
}
|
||||
const App({Key? key, required this.database, required this.settings, required this.user}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -62,20 +61,23 @@ class App extends StatelessWidget {
|
||||
// Set high refresh mode #28
|
||||
if (Platform.isAndroid) FlutterDisplayMode.setHighRefreshRate();
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
FilcAPI.getConfig(settings).then((Config? config) {
|
||||
if (config != null) settings.update(context, database: database, config: config);
|
||||
});
|
||||
});
|
||||
|
||||
CorePalette? corePalette;
|
||||
|
||||
final status = StatusProvider();
|
||||
final kreta = KretaClient(user: user, settings: settings, status: status);
|
||||
final timetable = TimetableProvider(user: user, database: database, kreta: kreta);
|
||||
final premium = PremiumProvider(settings: settings);
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
FilcAPI.getConfig(settings).then((Config? config) {
|
||||
if (config != null) settings.update(config: config);
|
||||
});
|
||||
premium.activate();
|
||||
});
|
||||
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider<PremiumProvider>(create: (_) => premium),
|
||||
ChangeNotifierProvider<SettingsProvider>(create: (_) => settings),
|
||||
ChangeNotifierProvider<UserProvider>(create: (_) => user),
|
||||
ChangeNotifierProvider<StatusProvider>(create: (_) => status),
|
||||
@@ -86,7 +88,7 @@ class App extends StatelessWidget {
|
||||
ChangeNotifierProvider<UpdateProvider>(create: (context) => UpdateProvider(context: context)),
|
||||
|
||||
// User data providers
|
||||
ChangeNotifierProvider<GradeProvider>(create: (context) => GradeProvider(context: context)),
|
||||
ChangeNotifierProvider<GradeProvider>(create: (_) => GradeProvider(settings: settings, user: user, database: database, kreta: kreta)),
|
||||
ChangeNotifierProvider<TimetableProvider>(create: (_) => timetable),
|
||||
ChangeNotifierProvider<ExamProvider>(create: (context) => ExamProvider(context: context)),
|
||||
ChangeNotifierProvider<HomeworkProvider>(create: (context) => HomeworkProvider(context: context)),
|
||||
@@ -95,8 +97,9 @@ class App extends StatelessWidget {
|
||||
ChangeNotifierProvider<EventProvider>(create: (context) => EventProvider(context: context)),
|
||||
ChangeNotifierProvider<AbsenceProvider>(create: (context) => AbsenceProvider(context: context)),
|
||||
|
||||
ChangeNotifierProvider<GradeCalculatorProvider>(create: (context) => GradeCalculatorProvider(context)),
|
||||
ChangeNotifierProvider<LiveCardProvider>(create: (context) => LiveCardProvider(lessonProvider: timetable, settingsProvider: settings))
|
||||
ChangeNotifierProvider<GradeCalculatorProvider>(
|
||||
create: (_) => GradeCalculatorProvider(settings: settings, user: user, database: database, kreta: kreta)),
|
||||
ChangeNotifierProvider<LiveCardProvider>(create: (context) => LiveCardProvider(timetable: timetable, settings: settings))
|
||||
],
|
||||
child: Consumer<ThemeModeObserver>(
|
||||
builder: (context, themeMode, child) {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:filcnaplo/api/providers/database_provider.dart';
|
||||
import 'package:filcnaplo/database/struct.dart';
|
||||
import 'package:filcnaplo/models/settings.dart';
|
||||
import 'package:sqflite/sqflite.dart';
|
||||
@@ -10,15 +11,17 @@ import 'package:sqflite_common_ffi/sqflite_ffi.dart';
|
||||
|
||||
const settingsDB = DatabaseStruct("settings", {
|
||||
"language": String, "start_page": int, "rounding": int, "theme": int, "accent_color": int, "news": int, "news_state": int, "developer_mode": int,
|
||||
"update_channel": int, "config": String, // general
|
||||
"update_channel": int, "config": String, "custom_accent_color": int, "custom_background_color": int, "custom_highlight_color": int, // general
|
||||
"grade_color1": int, "grade_color2": int, "grade_color3": int, "grade_color4": int, "grade_color5": int, // grade colors
|
||||
"vibration_strength": int, "ab_weeks": int, "swap_ab_weeks": int,
|
||||
"notifications": int, "notifications_bitfield": int, "notification_poll_interval": int, // notifications
|
||||
"x_filc_id": String, "graph_class_avg": int, "presentation_mode": int, "bell_delay": int, "bell_delay_enabled": int,
|
||||
"grade_opening_fun": int,
|
||||
"grade_opening_fun": int, "icon_pack": String, "premium_scopes": String, "premium_token": String, "last_account_id": String,
|
||||
});
|
||||
const usersDB = DatabaseStruct("users", {
|
||||
"id": String, "name": String, "username": String, "password": String, "institute_code": String, "student": String, "role": int,
|
||||
"nickname": String // premium only
|
||||
});
|
||||
const usersDB = DatabaseStruct(
|
||||
"users", {"id": String, "name": String, "username": String, "password": String, "institute_code": String, "student": String, "role": int});
|
||||
const userDataDB = DatabaseStruct("user_data", {
|
||||
"id": String, "grades": String, "timetable": String, "exams": String, "homework": String, "messages": String, "notes": String,
|
||||
"events": String, "absences": String, "group_averages": String,
|
||||
@@ -28,7 +31,7 @@ const userDataDB = DatabaseStruct("user_data", {
|
||||
|
||||
Future<void> createTable(Database db, DatabaseStruct struct) => db.execute("CREATE TABLE IF NOT EXISTS ${struct.table} ($struct)");
|
||||
|
||||
Future<Database> initDB() async {
|
||||
Future<Database> initDB(DatabaseProvider database) async {
|
||||
Database db;
|
||||
|
||||
if (Platform.isLinux || Platform.isWindows) {
|
||||
@@ -44,7 +47,7 @@ Future<Database> initDB() async {
|
||||
|
||||
if ((await db.rawQuery("SELECT COUNT(*) FROM settings"))[0].values.first == 0) {
|
||||
// Set default values for table Settings
|
||||
await db.insert("settings", SettingsProvider.defaultSettings().toMap());
|
||||
await db.insert("settings", SettingsProvider.defaultSettings(database: database).toMap());
|
||||
}
|
||||
|
||||
// Migrate Databases
|
||||
@@ -52,7 +55,7 @@ Future<Database> initDB() async {
|
||||
await migrateDB(
|
||||
db,
|
||||
struct: settingsDB,
|
||||
defaultValues: SettingsProvider.defaultSettings().toMap(),
|
||||
defaultValues: SettingsProvider.defaultSettings(database: database).toMap(),
|
||||
);
|
||||
await migrateDB(
|
||||
db,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'dart:convert';
|
||||
import 'package:filcnaplo/api/providers/database_provider.dart';
|
||||
import 'package:filcnaplo/models/subject_lesson_count.dart';
|
||||
import 'package:filcnaplo/models/user.dart';
|
||||
// ignore: depend_on_referenced_packages
|
||||
@@ -22,18 +23,24 @@ class DatabaseQuery {
|
||||
|
||||
final Database db;
|
||||
|
||||
Future<SettingsProvider> getSettings() async {
|
||||
Future<SettingsProvider> getSettings(DatabaseProvider database) async {
|
||||
Map settingsMap = (await db.query("settings")).elementAt(0);
|
||||
SettingsProvider settings = SettingsProvider.fromMap(settingsMap);
|
||||
SettingsProvider settings = SettingsProvider.fromMap(settingsMap, database: database);
|
||||
return settings;
|
||||
}
|
||||
|
||||
Future<UserProvider> getUsers() async {
|
||||
var userProvider = UserProvider();
|
||||
Future<UserProvider> getUsers(SettingsProvider settings) async {
|
||||
var userProvider = UserProvider(settings: settings);
|
||||
List<Map> usersMap = await db.query("users");
|
||||
for (var user in usersMap) {
|
||||
userProvider.addUser(User.fromMap(user));
|
||||
}
|
||||
if (userProvider.getUsers().map((e) => e.id).contains(settings.lastAccountId)) {
|
||||
userProvider.setUser(settings.lastAccountId);
|
||||
} else {
|
||||
userProvider.setUser(userProvider.getUsers().first.id);
|
||||
settings.update(lastAccountId: userProvider.id);
|
||||
}
|
||||
return userProvider;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,19 +7,14 @@ class AverageHelper {
|
||||
List<String> ignoreInFinal = ["5,SzorgalomErtek", "4,MagatartasErtek"];
|
||||
|
||||
if (finalAvg) {
|
||||
grades.removeWhere((e) =>
|
||||
(e.value.value == 0) ||
|
||||
(ignoreInFinal.contains(e.gradeType?.id)));
|
||||
grades.removeWhere((e) => (e.value.value == 0) || (ignoreInFinal.contains(e.gradeType?.id)));
|
||||
}
|
||||
|
||||
for (var e in grades) {
|
||||
average += e.value.value * ((finalAvg ? 100 : e.value.weight) / 100);
|
||||
}
|
||||
|
||||
average = average /
|
||||
grades
|
||||
.map((e) => (finalAvg ? 100 : e.value.weight) / 100)
|
||||
.fold(0.0, (a, b) => a + b);
|
||||
average = average / grades.map((e) => (finalAvg ? 100 : e.value.weight) / 100).fold(0.0, (a, b) => a + b);
|
||||
|
||||
return average.isNaN ? 0.0 : average;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'package:share_plus/share_plus.dart';
|
||||
|
||||
class ShareHelper {
|
||||
static Future<void> shareText(String text, {String? subject}) => Share.share(text, subject: subject);
|
||||
// ignore: deprecated_member_use
|
||||
static Future<void> shareFile(String path, {String? text, String? subject}) => Share.shareFiles([path], text: text, subject: subject);
|
||||
|
||||
static Future<void> shareAttachment(Attachment attachment, {required BuildContext context}) async {
|
||||
|
||||
@@ -1,20 +1,40 @@
|
||||
import 'package:filcnaplo/icons/filc_icons.dart';
|
||||
import 'package:filcnaplo/models/icon_pack.dart';
|
||||
import 'package:filcnaplo/models/settings.dart';
|
||||
import 'package:filcnaplo/utils/format.dart';
|
||||
import 'package:filcnaplo_kreta_api/models/subject.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
typedef SubjectIconVariants = Map<IconPack, IconData>;
|
||||
|
||||
class SubjectIconData {
|
||||
final IconData data;
|
||||
final SubjectIconVariants data;
|
||||
final String name; // for iOS live activities compatibilty
|
||||
|
||||
SubjectIconData({
|
||||
this.data = CupertinoIcons.rectangle_grid_2x2,
|
||||
this.data = const {
|
||||
IconPack.material: Icons.widgets_outlined,
|
||||
IconPack.cupertino: CupertinoIcons.rectangle_grid_2x2,
|
||||
},
|
||||
this.name = "square.grid.2x2",
|
||||
});
|
||||
}
|
||||
|
||||
SubjectIconVariants createIcon({required IconData material, required IconData cupertino}) {
|
||||
return {
|
||||
IconPack.material: material,
|
||||
IconPack.cupertino: cupertino,
|
||||
};
|
||||
}
|
||||
|
||||
class SubjectIcon {
|
||||
static SubjectIconData resolve({Subject? subject, String? subjectName}) {
|
||||
static String resolveName({Subject? subject, String? subjectName}) => _resolve(subject: subject, subjectName: subjectName).name;
|
||||
static IconData resolveVariant({Subject? subject, String? subjectName, required BuildContext context}) =>
|
||||
_resolve(subject: subject, subjectName: subjectName).data[Provider.of<SettingsProvider>(context, listen: false).iconPack]!;
|
||||
|
||||
static SubjectIconData _resolve({Subject? subject, String? subjectName}) {
|
||||
assert(!(subject == null && subjectName == null));
|
||||
|
||||
String name = (subject?.name ?? subjectName ?? "").toLowerCase().specialChars().trim();
|
||||
@@ -22,65 +42,70 @@ class SubjectIcon {
|
||||
|
||||
// todo: check for categories
|
||||
if (RegExp("mate(k|matika)").hasMatch(name) || category == "matematika") {
|
||||
return SubjectIconData(data: CupertinoIcons.function, name: "function");
|
||||
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.function, material: Icons.calculate_outlined), name: "function");
|
||||
} else if (RegExp("magyar nyelv|nyelvtan").hasMatch(name)) {
|
||||
return SubjectIconData(data: CupertinoIcons.textformat_alt, name: "textformat.alt");
|
||||
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.textformat_alt, material: Icons.spellcheck_outlined), name: "textformat.alt");
|
||||
} else if (RegExp("irodalom").hasMatch(name)) {
|
||||
return SubjectIconData(data: CupertinoIcons.book, name: "book");
|
||||
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.book, material: Icons.menu_book_outlined), name: "book");
|
||||
} else if (RegExp("tor(i|tenelem)").hasMatch(name)) {
|
||||
return SubjectIconData(data: CupertinoIcons.compass, name: "safari");
|
||||
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.compass, material: Icons.hourglass_empty_outlined), name: "safari");
|
||||
} else if (RegExp("foldrajz").hasMatch(name)) {
|
||||
return SubjectIconData(data: CupertinoIcons.map, name: "map");
|
||||
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.map, material: Icons.public_outlined), name: "map");
|
||||
} else if (RegExp("rajz|muvtori|muveszet|vizualis").hasMatch(name)) {
|
||||
return SubjectIconData(data: CupertinoIcons.paintbrush, name: "paintbrush");
|
||||
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.paintbrush, material: Icons.palette_outlined), name: "paintbrush");
|
||||
} else if (RegExp("fizika").hasMatch(name)) {
|
||||
return SubjectIconData(data: CupertinoIcons.lightbulb, name: "lightbulb");
|
||||
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.lightbulb, material: Icons.emoji_objects_outlined), name: "lightbulb");
|
||||
} else if (RegExp("^enek|zene|szolfezs|zongora|korus").hasMatch(name)) {
|
||||
return SubjectIconData(data: CupertinoIcons.music_note, name: "music.note");
|
||||
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.music_note, material: Icons.music_note_outlined), name: "music.note");
|
||||
} else if (RegExp("^tes(i|tneveles)|sport").hasMatch(name)) {
|
||||
return SubjectIconData(data: CupertinoIcons.sportscourt, name: "sportscourt");
|
||||
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.sportscourt, material: Icons.sports_soccer_outlined), name: "sportscourt");
|
||||
} else if (RegExp("kemia").hasMatch(name)) {
|
||||
return SubjectIconData(data: CupertinoIcons.lab_flask, name: "testtube.2");
|
||||
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.lab_flask, material: Icons.science_outlined), name: "testtube.2");
|
||||
} else if (RegExp("biologia").hasMatch(name)) {
|
||||
return SubjectIconData(data: CupertinoIcons.paw, name: "pawprint");
|
||||
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.paw, material: Icons.pets_outlined), name: "pawprint");
|
||||
} else if (RegExp("kornyezet|termeszet ?(tudomany|ismeret)|hon( es nep)?ismeret").hasMatch(name)) {
|
||||
return SubjectIconData(data: CupertinoIcons.arrow_3_trianglepath, name: "arrow.3.trianglepath");
|
||||
return SubjectIconData(
|
||||
data: createIcon(cupertino: CupertinoIcons.arrow_3_trianglepath, material: Icons.eco_outlined), name: "arrow.3.trianglepath");
|
||||
} else if (RegExp("(hit|erkolcs)tan|vallas|etika").hasMatch(name)) {
|
||||
return SubjectIconData(data: CupertinoIcons.heart, name: "heart");
|
||||
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.heart, material: Icons.favorite_border_outlined), name: "heart");
|
||||
} else if (RegExp("penzugy").hasMatch(name)) {
|
||||
return SubjectIconData(data: CupertinoIcons.money_dollar, name: "dollarsign");
|
||||
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.money_dollar, material: Icons.savings_outlined), name: "dollarsign");
|
||||
} else if (RegExp("informatika|szoftver|iroda|digitalis").hasMatch(name)) {
|
||||
return SubjectIconData(data: CupertinoIcons.device_laptop, name: "laptopcomputer");
|
||||
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.device_laptop, material: Icons.computer_outlined), name: "laptopcomputer");
|
||||
} else if (RegExp("prog").hasMatch(name)) {
|
||||
return SubjectIconData(data: CupertinoIcons.chevron_left_slash_chevron_right, name: "chevron.left.forwardslash.chevron.right");
|
||||
return SubjectIconData(
|
||||
data: createIcon(cupertino: CupertinoIcons.chevron_left_slash_chevron_right, material: Icons.code_outlined),
|
||||
name: "chevron.left.forwardslash.chevron.right");
|
||||
} else if (RegExp("halozat").hasMatch(name)) {
|
||||
return SubjectIconData(data: CupertinoIcons.antenna_radiowaves_left_right, name: "antenna.radiowaves.left.and.right");
|
||||
return SubjectIconData(
|
||||
data: createIcon(cupertino: CupertinoIcons.antenna_radiowaves_left_right, material: Icons.wifi_tethering_outlined),
|
||||
name: "antenna.radiowaves.left.and.right");
|
||||
} else if (RegExp("szinhaz").hasMatch(name)) {
|
||||
return SubjectIconData(data: CupertinoIcons.hifispeaker, name: "hifispeaker");
|
||||
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.hifispeaker, material: Icons.theater_comedy_outlined), name: "hifispeaker");
|
||||
} else if (RegExp("film|media").hasMatch(name)) {
|
||||
return SubjectIconData(data: CupertinoIcons.film, name: "film");
|
||||
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.film, material: Icons.theaters_outlined), name: "film");
|
||||
} else if (RegExp("elektro(tech)?nika").hasMatch(name)) {
|
||||
return SubjectIconData(data: CupertinoIcons.bolt, name: "bolt");
|
||||
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.bolt, material: Icons.electrical_services_outlined), name: "bolt");
|
||||
} else if (RegExp("gepesz|mernok|ipar").hasMatch(name)) {
|
||||
return SubjectIconData(data: CupertinoIcons.wrench, name: "wrench");
|
||||
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.wrench, material: Icons.precision_manufacturing_outlined), name: "wrench");
|
||||
} else if (RegExp("technika").hasMatch(name)) {
|
||||
return SubjectIconData(data: CupertinoIcons.hammer, name: "hammer");
|
||||
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.hammer, material: Icons.build_outlined), name: "hammer");
|
||||
} else if (RegExp("tanc").hasMatch(name)) {
|
||||
return SubjectIconData(data: CupertinoIcons.music_mic, name: "music.mic");
|
||||
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.music_mic, material: Icons.speaker_outlined), name: "music.mic");
|
||||
} else if (RegExp("filozofia").hasMatch(name)) {
|
||||
return SubjectIconData(data: CupertinoIcons.bubble_left, name: "bubble.left");
|
||||
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.bubble_left, material: Icons.psychology_outlined), name: "bubble.left");
|
||||
} else if (RegExp("osztaly(fonoki|kozosseg)").hasMatch(name) || name == "ofo") {
|
||||
return SubjectIconData(data: CupertinoIcons.group, name: "person.3");
|
||||
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.group, material: Icons.groups_outlined), name: "person.3");
|
||||
} else if (RegExp("gazdasag").hasMatch(name)) {
|
||||
return SubjectIconData(data: CupertinoIcons.chart_pie, name: "chart.pie");
|
||||
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.chart_pie, material: Icons.account_balance_outlined), name: "chart.pie");
|
||||
} else if (RegExp("szorgalom").hasMatch(name)) {
|
||||
return SubjectIconData(data: CupertinoIcons.checkmark_seal, name: "checkmark.seal");
|
||||
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.checkmark_seal, material: Icons.verified_outlined), name: "checkmark.seal");
|
||||
} else if (RegExp("magatartas").hasMatch(name)) {
|
||||
return SubjectIconData(data: CupertinoIcons.smiley, name: "face.smiling");
|
||||
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.smiley, material: Icons.emoji_people_outlined), name: "face.smiling");
|
||||
} else if (RegExp("angol|nemet|francia|olasz|orosz|spanyol|latin|kinai|nyelv").hasMatch(name)) {
|
||||
return SubjectIconData(data: CupertinoIcons.globe, name: "globe");
|
||||
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.globe, material: Icons.translate_outlined), name: "globe");
|
||||
} else if (RegExp("linux").hasMatch(name)) {
|
||||
return SubjectIconData(data: FilcIcons.linux);
|
||||
return SubjectIconData(data: createIcon(material: FilcIcons.linux, cupertino: FilcIcons.linux));
|
||||
}
|
||||
|
||||
return SubjectIconData();
|
||||
|
||||
@@ -40,7 +40,7 @@ extension UpdateHelper on Release {
|
||||
}
|
||||
|
||||
Future<Uint8List> download({UpdateCallback? updateCallback}) async {
|
||||
var response = await FilcAPI.downloadRelease(this);
|
||||
var response = await FilcAPI.downloadRelease(downloads.first);
|
||||
|
||||
List<List<int>> chunks = [];
|
||||
int downloaded = 0;
|
||||
|
||||
@@ -16,4 +16,7 @@ class FilcIcons {
|
||||
|
||||
/// downstairs
|
||||
static const IconData downstairs = IconData(0x03, fontFamily: iconFontFamily);
|
||||
|
||||
/// premium
|
||||
static const IconData premium = IconData(0x04, fontFamily: iconFontFamily);
|
||||
}
|
||||
|
||||
@@ -32,12 +32,12 @@ class Startup {
|
||||
late DatabaseProvider database;
|
||||
|
||||
Future<void> start() async {
|
||||
var db = await initDB();
|
||||
await db.close();
|
||||
database = DatabaseProvider();
|
||||
var db = await initDB(database);
|
||||
await db.close();
|
||||
await database.init();
|
||||
settings = await database.query.getSettings();
|
||||
user = await database.query.getUsers();
|
||||
settings = await database.query.getSettings(database);
|
||||
user = await database.query.getUsers(settings);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
1
filcnaplo/lib/models/icon_pack.dart
Normal file
1
filcnaplo/lib/models/icon_pack.dart
Normal file
@@ -0,0 +1 @@
|
||||
enum IconPack { material, cupertino }
|
||||
@@ -1,9 +1,26 @@
|
||||
class ReleaseDownload {
|
||||
String url;
|
||||
int size;
|
||||
|
||||
ReleaseDownload({
|
||||
required this.url,
|
||||
required this.size,
|
||||
});
|
||||
|
||||
factory ReleaseDownload.fromJson(Map json) {
|
||||
return ReleaseDownload(
|
||||
url: json["browser_download_url"] ?? "",
|
||||
size: json["size"] ?? 0,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class Release {
|
||||
String tag;
|
||||
Version version;
|
||||
String author;
|
||||
String body;
|
||||
List<String> downloads;
|
||||
List<ReleaseDownload> downloads;
|
||||
bool prerelease;
|
||||
|
||||
Release({
|
||||
@@ -20,7 +37,7 @@ class Release {
|
||||
tag: json["tag_name"] ?? Version.zero.toString(),
|
||||
author: json["author"] != null ? json["author"]["login"] ?? "" : "",
|
||||
body: json["body"] ?? "",
|
||||
downloads: json["assets"] != null ? json["assets"].map((a) => a["browser_download_url"] ?? "").toList().cast<String>() : [],
|
||||
downloads: json["assets"] != null ? json["assets"].map((a) => ReleaseDownload.fromJson(a)).toList().cast<ReleaseDownload>() : [],
|
||||
prerelease: json["prerelease"] ?? false,
|
||||
version: Version.fromString(json["tag_name"] ?? ""),
|
||||
);
|
||||
|
||||
@@ -3,10 +3,10 @@ import 'dart:developer';
|
||||
|
||||
import 'package:filcnaplo/api/providers/database_provider.dart';
|
||||
import 'package:filcnaplo/models/config.dart';
|
||||
import 'package:filcnaplo/models/icon_pack.dart';
|
||||
import 'package:filcnaplo/theme/colors/accent.dart';
|
||||
import 'package:filcnaplo/theme/colors/dark_mobile.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
enum Pages { home, grades, timetable, messages, absences }
|
||||
@@ -16,6 +16,8 @@ enum UpdateChannel { stable, beta, dev }
|
||||
enum VibrationStrength { off, light, medium, strong }
|
||||
|
||||
class SettingsProvider extends ChangeNotifier {
|
||||
final DatabaseProvider? _database;
|
||||
|
||||
// en_en, hu_hu, de_de
|
||||
String _language;
|
||||
Pages _startPage;
|
||||
@@ -56,8 +58,16 @@ class SettingsProvider extends ChangeNotifier {
|
||||
bool _bellDelayEnabled;
|
||||
int _bellDelay;
|
||||
bool _gradeOpeningFun;
|
||||
IconPack _iconPack;
|
||||
Color _customAccentColor;
|
||||
Color _customBackgroundColor;
|
||||
Color _customHighlightColor;
|
||||
List<String> _premiumScopes;
|
||||
String _premiumAccessToken;
|
||||
String _lastAccountId;
|
||||
|
||||
SettingsProvider({
|
||||
DatabaseProvider? database,
|
||||
required String language,
|
||||
required Pages startPage,
|
||||
required int rounding,
|
||||
@@ -82,7 +92,15 @@ class SettingsProvider extends ChangeNotifier {
|
||||
required bool bellDelayEnabled,
|
||||
required int bellDelay,
|
||||
required bool gradeOpeningFun,
|
||||
}) : _language = language,
|
||||
required IconPack iconPack,
|
||||
required Color customAccentColor,
|
||||
required Color customBackgroundColor,
|
||||
required Color customHighlightColor,
|
||||
required List<String> premiumScopes,
|
||||
required String premiumAccessToken,
|
||||
required String lastAccountId,
|
||||
}) : _database = database,
|
||||
_language = language,
|
||||
_startPage = startPage,
|
||||
_rounding = rounding,
|
||||
_theme = theme,
|
||||
@@ -105,9 +123,16 @@ class SettingsProvider extends ChangeNotifier {
|
||||
_presentationMode = presentationMode,
|
||||
_bellDelayEnabled = bellDelayEnabled,
|
||||
_bellDelay = bellDelay,
|
||||
_gradeOpeningFun = gradeOpeningFun;
|
||||
_gradeOpeningFun = gradeOpeningFun,
|
||||
_iconPack = iconPack,
|
||||
_customAccentColor = customAccentColor,
|
||||
_customBackgroundColor = customBackgroundColor,
|
||||
_customHighlightColor = customHighlightColor,
|
||||
_premiumScopes = premiumScopes,
|
||||
_premiumAccessToken = premiumAccessToken,
|
||||
_lastAccountId = lastAccountId;
|
||||
|
||||
factory SettingsProvider.fromMap(Map map) {
|
||||
factory SettingsProvider.fromMap(Map map, {required DatabaseProvider database}) {
|
||||
Map<String, Object?>? configMap;
|
||||
|
||||
try {
|
||||
@@ -117,6 +142,7 @@ class SettingsProvider extends ChangeNotifier {
|
||||
}
|
||||
|
||||
return SettingsProvider(
|
||||
database: database,
|
||||
language: map["language"],
|
||||
startPage: Pages.values[map["start_page"]],
|
||||
rounding: map["rounding"],
|
||||
@@ -147,6 +173,13 @@ class SettingsProvider extends ChangeNotifier {
|
||||
bellDelayEnabled: map["bell_delay_enabled"] == 1,
|
||||
bellDelay: map["bell_delay"],
|
||||
gradeOpeningFun: map["grade_opening_fun"] == 1,
|
||||
iconPack: Map.fromEntries(IconPack.values.map((e) => MapEntry(e.name, e)))[map["icon_pack"]]!,
|
||||
customAccentColor: Color(map["custom_accent_color"]),
|
||||
customBackgroundColor: Color(map["custom_background_color"]),
|
||||
customHighlightColor: Color(map["custom_highlight_color"]),
|
||||
premiumScopes: jsonDecode(map["premium_scopes"]).cast<String>(),
|
||||
premiumAccessToken: map["premium_token"],
|
||||
lastAccountId: map["last_account_id"],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -179,11 +212,19 @@ class SettingsProvider extends ChangeNotifier {
|
||||
"bell_delay_enabled": _bellDelayEnabled ? 1 : 0,
|
||||
"bell_delay": _bellDelay,
|
||||
"grade_opening_fun": _gradeOpeningFun ? 1 : 0,
|
||||
"icon_pack": _iconPack.name,
|
||||
"custom_accent_color": _customAccentColor.value,
|
||||
"custom_background_color": _customBackgroundColor.value,
|
||||
"custom_highlight_color": _customHighlightColor.value,
|
||||
"premium_scopes": jsonEncode(_premiumScopes),
|
||||
"premium_token": _premiumAccessToken,
|
||||
"last_account_id": _lastAccountId,
|
||||
};
|
||||
}
|
||||
|
||||
factory SettingsProvider.defaultSettings() {
|
||||
factory SettingsProvider.defaultSettings({DatabaseProvider? database}) {
|
||||
return SettingsProvider(
|
||||
database: database,
|
||||
language: "hu",
|
||||
startPage: Pages.home,
|
||||
rounding: 5,
|
||||
@@ -214,6 +255,13 @@ class SettingsProvider extends ChangeNotifier {
|
||||
bellDelayEnabled: false,
|
||||
bellDelay: 0,
|
||||
gradeOpeningFun: true,
|
||||
iconPack: IconPack.cupertino,
|
||||
customAccentColor: const Color(0xff20AC9B),
|
||||
customBackgroundColor: const Color(0xff000000),
|
||||
customHighlightColor: const Color(0xff222222),
|
||||
premiumScopes: [],
|
||||
premiumAccessToken: "",
|
||||
lastAccountId: "",
|
||||
);
|
||||
}
|
||||
|
||||
@@ -242,10 +290,15 @@ class SettingsProvider extends ChangeNotifier {
|
||||
bool get bellDelayEnabled => _bellDelayEnabled;
|
||||
int get bellDelay => _bellDelay;
|
||||
bool get gradeOpeningFun => _gradeOpeningFun;
|
||||
IconPack get iconPack => _iconPack;
|
||||
Color? get customAccentColor => _customAccentColor == accentColorMap[AccentColor.custom] ? null : _customAccentColor;
|
||||
Color? get customBackgroundColor => _customBackgroundColor;
|
||||
Color? get customHighlightColor => _customHighlightColor;
|
||||
List<String> get premiumScopes => _premiumScopes;
|
||||
String get premiumAccessToken => _premiumAccessToken;
|
||||
String get lastAccountId => _lastAccountId;
|
||||
|
||||
Future<void> update(
|
||||
BuildContext context, {
|
||||
DatabaseProvider? database,
|
||||
Future<void> update({
|
||||
bool store = true,
|
||||
String? language,
|
||||
Pages? startPage,
|
||||
@@ -271,6 +324,13 @@ class SettingsProvider extends ChangeNotifier {
|
||||
bool? bellDelayEnabled,
|
||||
int? bellDelay,
|
||||
bool? gradeOpeningFun,
|
||||
IconPack? iconPack,
|
||||
Color? customAccentColor,
|
||||
Color? customBackgroundColor,
|
||||
Color? customHighlightColor,
|
||||
List<String>? premiumScopes,
|
||||
String? premiumAccessToken,
|
||||
String? lastAccountId,
|
||||
}) async {
|
||||
if (language != null && language != _language) _language = language;
|
||||
if (startPage != null && startPage != _startPage) _startPage = startPage;
|
||||
@@ -298,9 +358,15 @@ class SettingsProvider extends ChangeNotifier {
|
||||
if (bellDelay != null && bellDelay != _bellDelay) _bellDelay = bellDelay;
|
||||
if (bellDelayEnabled != null && bellDelayEnabled != _bellDelayEnabled) _bellDelayEnabled = bellDelayEnabled;
|
||||
if (gradeOpeningFun != null && gradeOpeningFun != _gradeOpeningFun) _gradeOpeningFun = gradeOpeningFun;
|
||||
if (iconPack != null && iconPack != _iconPack) _iconPack = iconPack;
|
||||
if (customAccentColor != null && customAccentColor != _customAccentColor) _customAccentColor = customAccentColor;
|
||||
if (customBackgroundColor != null && customBackgroundColor != _customBackgroundColor) _customBackgroundColor = customBackgroundColor;
|
||||
if (customHighlightColor != null && customHighlightColor != _customHighlightColor) _customHighlightColor = customHighlightColor;
|
||||
if (premiumScopes != null && premiumScopes != _premiumScopes) _premiumScopes = premiumScopes;
|
||||
if (premiumAccessToken != null && premiumAccessToken != _premiumAccessToken) _premiumAccessToken = premiumAccessToken;
|
||||
if (lastAccountId != null && lastAccountId != _lastAccountId) _lastAccountId = lastAccountId;
|
||||
|
||||
database ??= Provider.of<DatabaseProvider>(context, listen: false);
|
||||
if (store) await database.store.storeSettings(this);
|
||||
if (store) await _database?.store.storeSettings(this);
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,9 @@ class User {
|
||||
String name;
|
||||
Student student;
|
||||
Role role;
|
||||
String nickname;
|
||||
|
||||
String get displayName => nickname != '' ? nickname : name;
|
||||
|
||||
User({
|
||||
String? id,
|
||||
@@ -22,6 +25,7 @@ class User {
|
||||
required this.instituteCode,
|
||||
required this.student,
|
||||
required this.role,
|
||||
this.nickname = "",
|
||||
}) {
|
||||
if (id != null) {
|
||||
this.id = id;
|
||||
@@ -39,6 +43,7 @@ class User {
|
||||
name: map["name"].trim(),
|
||||
student: Student.fromJson(jsonDecode(map["student"])),
|
||||
role: Role.values[map["role"] ?? 0],
|
||||
nickname: map["nickname"] ?? "",
|
||||
);
|
||||
}
|
||||
|
||||
@@ -51,6 +56,7 @@ class User {
|
||||
"name": name,
|
||||
"student": jsonEncode(student.json),
|
||||
"role": role.index,
|
||||
"nickname": nickname,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
enum AccentColor { filc, blue, green, lime, yellow, orange, red, pink, purple, adaptive }
|
||||
enum AccentColor { filc, blue, green, lime, yellow, orange, red, pink, purple, adaptive, custom }
|
||||
|
||||
Map<AccentColor, Color> accentColorMap = {
|
||||
AccentColor.filc: const Color(0xff20AC9B),
|
||||
@@ -13,4 +13,5 @@ Map<AccentColor, Color> accentColorMap = {
|
||||
AccentColor.pink: Colors.pink.shade300,
|
||||
AccentColor.purple: Colors.purple.shade300,
|
||||
AccentColor.adaptive: const Color(0xff20AC9B),
|
||||
AccentColor.custom: const Color(0xff20AC9B),
|
||||
};
|
||||
|
||||
@@ -22,8 +22,10 @@ class AppTheme {
|
||||
// Light Theme
|
||||
static ThemeData lightTheme(BuildContext context, {CorePalette? palette}) {
|
||||
var lightColors = AppColors.fromBrightness(Brightness.light);
|
||||
AccentColor accentColor = Provider.of<SettingsProvider>(context, listen: false).accentColor;
|
||||
Color accent = accentColorMap[accentColor] ?? const Color(0x00000000);
|
||||
final settings = Provider.of<SettingsProvider>(context, listen: false);
|
||||
AccentColor accentColor = settings.accentColor;
|
||||
final customAccentColor = accentColor == AccentColor.custom ? settings.customAccentColor : null;
|
||||
Color accent = customAccentColor ?? accentColorMap[accentColor] ?? const Color(0x00000000);
|
||||
|
||||
if (accentColor == AccentColor.adaptive) {
|
||||
if (palette != null) accent = _paletteAccentLight(palette)!;
|
||||
@@ -31,31 +33,35 @@ class AppTheme {
|
||||
palette = null;
|
||||
}
|
||||
|
||||
Color backgroundColor =
|
||||
accentColor == AccentColor.custom ? settings.customBackgroundColor : _paletteBackgroundLight(palette) ?? lightColors.background;
|
||||
Color highlighColor =
|
||||
accentColor == AccentColor.custom ? settings.customHighlightColor : _paletteHighlightLight(palette) ?? lightColors.highlight;
|
||||
|
||||
return ThemeData(
|
||||
brightness: Brightness.light,
|
||||
useMaterial3: false,
|
||||
fontFamily: _fontFamily,
|
||||
scaffoldBackgroundColor: _paletteBackgroundLight(palette) ?? lightColors.background,
|
||||
backgroundColor: _paletteHighlightLight(palette) ?? lightColors.highlight,
|
||||
scaffoldBackgroundColor: backgroundColor,
|
||||
backgroundColor: highlighColor,
|
||||
primaryColor: lightColors.filc,
|
||||
dividerColor: const Color(0x00000000),
|
||||
colorScheme: ColorScheme.fromSwatch(
|
||||
accentColor: accent,
|
||||
backgroundColor: _paletteBackgroundLight(palette) ?? lightColors.background,
|
||||
backgroundColor: backgroundColor,
|
||||
brightness: Brightness.light,
|
||||
cardColor: _paletteHighlightLight(palette) ?? lightColors.highlight,
|
||||
cardColor: highlighColor,
|
||||
errorColor: lightColors.red,
|
||||
primaryColorDark: lightColors.filc,
|
||||
primarySwatch: Colors.teal,
|
||||
),
|
||||
shadowColor: lightColors.shadow,
|
||||
appBarTheme: AppBarTheme(backgroundColor: _paletteBackgroundLight(palette) ?? lightColors.background),
|
||||
shadowColor: highlighColor.withOpacity(.5), //lightColors.shadow,
|
||||
appBarTheme: AppBarTheme(backgroundColor: backgroundColor),
|
||||
indicatorColor: accent,
|
||||
iconTheme: IconThemeData(color: lightColors.text.withOpacity(.75)),
|
||||
navigationBarTheme: NavigationBarThemeData(
|
||||
indicatorColor: accent.withOpacity(accentColor == AccentColor.adaptive ? 0.4 : 0.8),
|
||||
iconTheme: MaterialStateProperty.all(IconThemeData(color: lightColors.text)),
|
||||
backgroundColor: _paletteHighlightLight(palette) ?? lightColors.highlight,
|
||||
backgroundColor: highlighColor,
|
||||
labelTextStyle: MaterialStateProperty.all(TextStyle(
|
||||
fontSize: 13.0,
|
||||
fontWeight: FontWeight.w500,
|
||||
@@ -75,8 +81,10 @@ class AppTheme {
|
||||
// Dark Theme
|
||||
static ThemeData darkTheme(BuildContext context, {CorePalette? palette}) {
|
||||
var darkColors = AppColors.fromBrightness(Brightness.dark);
|
||||
AccentColor accentColor = Provider.of<SettingsProvider>(context, listen: false).accentColor;
|
||||
Color accent = accentColorMap[accentColor] ?? const Color(0x00000000);
|
||||
final settings = Provider.of<SettingsProvider>(context, listen: false);
|
||||
AccentColor accentColor = settings.accentColor;
|
||||
final customAccentColor = accentColor == AccentColor.custom ? settings.customAccentColor : null;
|
||||
Color accent = customAccentColor ?? accentColorMap[accentColor] ?? const Color(0x00000000);
|
||||
|
||||
if (accentColor == AccentColor.adaptive) {
|
||||
if (palette != null) accent = _paletteAccentDark(palette)!;
|
||||
@@ -84,31 +92,34 @@ class AppTheme {
|
||||
palette = null;
|
||||
}
|
||||
|
||||
Color backgroundColor =
|
||||
accentColor == AccentColor.custom ? settings.customBackgroundColor : _paletteBackgroundDark(palette) ?? darkColors.background;
|
||||
Color highlightColor = accentColor == AccentColor.custom ? settings.customHighlightColor : _paletteHighlightDark(palette) ?? darkColors.highlight;
|
||||
|
||||
return ThemeData(
|
||||
brightness: Brightness.dark,
|
||||
useMaterial3: false,
|
||||
fontFamily: _fontFamily,
|
||||
scaffoldBackgroundColor: _paletteBackgroundDark(palette) ?? darkColors.background,
|
||||
backgroundColor: _paletteHighlightDark(palette) ?? darkColors.highlight,
|
||||
scaffoldBackgroundColor: backgroundColor,
|
||||
backgroundColor: highlightColor,
|
||||
primaryColor: darkColors.filc,
|
||||
dividerColor: const Color(0x00000000),
|
||||
colorScheme: ColorScheme.fromSwatch(
|
||||
accentColor: accent,
|
||||
backgroundColor: _paletteBackgroundDark(palette) ?? darkColors.background,
|
||||
backgroundColor: backgroundColor,
|
||||
brightness: Brightness.dark,
|
||||
cardColor: _paletteHighlightDark(palette) ?? darkColors.highlight,
|
||||
cardColor: highlightColor,
|
||||
errorColor: darkColors.red,
|
||||
primaryColorDark: darkColors.filc,
|
||||
primarySwatch: Colors.teal,
|
||||
),
|
||||
shadowColor: darkColors.shadow,
|
||||
appBarTheme: AppBarTheme(backgroundColor: _paletteBackgroundDark(palette) ?? darkColors.background),
|
||||
shadowColor: highlightColor.withOpacity(.5), //darkColors.shadow,
|
||||
appBarTheme: AppBarTheme(backgroundColor: backgroundColor),
|
||||
indicatorColor: accent,
|
||||
iconTheme: IconThemeData(color: darkColors.text.withOpacity(.75)),
|
||||
navigationBarTheme: NavigationBarThemeData(
|
||||
indicatorColor: accent.withOpacity(accentColor == AccentColor.adaptive ? 0.4 : 0.8),
|
||||
iconTheme: MaterialStateProperty.all(IconThemeData(color: darkColors.text)),
|
||||
backgroundColor: _paletteHighlightDark(palette) ?? darkColors.highlight,
|
||||
backgroundColor: highlightColor,
|
||||
labelTextStyle: MaterialStateProperty.all(TextStyle(
|
||||
fontSize: 13.0,
|
||||
fontWeight: FontWeight.w500,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:filcnaplo/api/providers/update_provider.dart';
|
||||
import 'package:filcnaplo/theme/colors/colors.dart';
|
||||
import 'package:filcnaplo/models/settings.dart';
|
||||
import 'package:filcnaplo/ui/date_widget.dart';
|
||||
import 'package:filcnaplo/ui/filter/widgets/grades.dart' as grade_filter;
|
||||
import 'package:filcnaplo/ui/filter/widgets/certifications.dart' as certification_filter;
|
||||
@@ -12,6 +12,7 @@ import 'package:filcnaplo/ui/filter/widgets/events.dart' as event_filter;
|
||||
import 'package:filcnaplo/ui/filter/widgets/lessons.dart' as lesson_filter;
|
||||
import 'package:filcnaplo/ui/filter/widgets/update.dart' as update_filter;
|
||||
import 'package:filcnaplo/ui/filter/widgets/missed_exams.dart' as missed_exam_filter;
|
||||
import 'package:filcnaplo/ui/filter/widgets/premium.dart' as premium_filter;
|
||||
import 'package:filcnaplo_kreta_api/providers/absence_provider.dart';
|
||||
import 'package:filcnaplo_kreta_api/providers/event_provider.dart';
|
||||
import 'package:filcnaplo_kreta_api/providers/exam_provider.dart';
|
||||
@@ -20,6 +21,7 @@ import 'package:filcnaplo_kreta_api/providers/homework_provider.dart';
|
||||
import 'package:filcnaplo_kreta_api/providers/message_provider.dart';
|
||||
import 'package:filcnaplo_kreta_api/providers/note_provider.dart';
|
||||
import 'package:filcnaplo_kreta_api/providers/timetable_provider.dart';
|
||||
import 'package:filcnaplo_premium/providers/premium_provider.dart';
|
||||
import 'package:filcnaplo_mobile_ui/common/panel/panel.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:implicitly_animated_reorderable_list/transitions.dart';
|
||||
@@ -27,7 +29,7 @@ import 'package:provider/provider.dart';
|
||||
|
||||
const List<FilterType> homeFilters = [FilterType.all, FilterType.grades, FilterType.messages, FilterType.absences];
|
||||
|
||||
enum FilterType { all, grades, newGrades, messages, absences, homework, exams, notes, events, lessons, updates, certifications, missedExams }
|
||||
enum FilterType { all, grades, newGrades, messages, absences, homework, exams, notes, events, lessons, updates, certifications, missedExams, premium }
|
||||
|
||||
Future<List<DateWidget>> getFilterWidgets(FilterType activeData, {bool absencesNoExcused = false, required BuildContext context}) async {
|
||||
final gradeProvider = Provider.of<GradeProvider>(context);
|
||||
@@ -39,6 +41,8 @@ Future<List<DateWidget>> getFilterWidgets(FilterType activeData, {bool absencesN
|
||||
final noteProvider = Provider.of<NoteProvider>(context);
|
||||
final eventProvider = Provider.of<EventProvider>(context);
|
||||
final updateProvider = Provider.of<UpdateProvider>(context);
|
||||
final settingsProvider = Provider.of<SettingsProvider>(context);
|
||||
final premiumProvider = Provider.of<PremiumProvider>(context);
|
||||
|
||||
List<DateWidget> items = [];
|
||||
|
||||
@@ -55,6 +59,7 @@ Future<List<DateWidget>> getFilterWidgets(FilterType activeData, {bool absencesN
|
||||
getFilterWidgets(FilterType.updates, context: context),
|
||||
getFilterWidgets(FilterType.certifications, context: context),
|
||||
getFilterWidgets(FilterType.missedExams, context: context),
|
||||
getFilterWidgets(FilterType.premium, context: context),
|
||||
]);
|
||||
items = all.expand((x) => x).toList();
|
||||
|
||||
@@ -63,7 +68,9 @@ Future<List<DateWidget>> getFilterWidgets(FilterType activeData, {bool absencesN
|
||||
// Grades
|
||||
case FilterType.grades:
|
||||
items = grade_filter.getWidgets(gradeProvider.grades, gradeProvider.lastSeenDate);
|
||||
if (settingsProvider.gradeOpeningFun) {
|
||||
items.addAll(await getFilterWidgets(FilterType.newGrades, context: context));
|
||||
}
|
||||
break;
|
||||
|
||||
// Grades
|
||||
@@ -124,6 +131,12 @@ Future<List<DateWidget>> getFilterWidgets(FilterType activeData, {bool absencesN
|
||||
case FilterType.missedExams:
|
||||
items = missed_exam_filter.getWidgets(timetableProvider.lessons);
|
||||
break;
|
||||
|
||||
case FilterType.premium:
|
||||
final now = DateTime.now();
|
||||
final isWeekend = now.weekday == DateTime.saturday || now.weekday == DateTime.sunday;
|
||||
items = [if (!premiumProvider.hasPremium && isWeekend) premium_filter.getWidget()];
|
||||
break;
|
||||
}
|
||||
return items;
|
||||
}
|
||||
@@ -145,11 +158,11 @@ Widget filterItemBuilder(BuildContext context, Animation<double> animation, Widg
|
||||
child: DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
boxShadow: [
|
||||
if (Theme.of(context).brightness == Brightness.light)
|
||||
BoxShadow(
|
||||
offset: const Offset(0, 21),
|
||||
blurRadius: 23.0,
|
||||
color: AppColors.of(context).shadow.withOpacity(
|
||||
color: Theme.of(context).shadowColor.withOpacity(
|
||||
Theme.of(context).shadowColor.opacity *
|
||||
CurvedAnimation(
|
||||
parent: CurvedAnimation(parent: animation, curve: Curves.easeInOutCubic),
|
||||
curve: const Interval(2 / 3, 1.0),
|
||||
|
||||
@@ -8,7 +8,8 @@ import 'package:filcnaplo_desktop_ui/common/widgets/grade/grade_viewable.dart' a
|
||||
List<DateWidget> getWidgets(List<Grade> providerGrades, DateTime? lastSeenDate) {
|
||||
List<DateWidget> items = [];
|
||||
for (var grade in providerGrades) {
|
||||
if (grade.type == GradeType.midYear && (!(lastSeenDate != null && grade.date.isAfter(lastSeenDate)) || grade.value.value == 0)) {
|
||||
final surprise = (!(lastSeenDate != null && grade.date.isAfter(lastSeenDate)) || grade.value.value == 0);
|
||||
if (grade.type == GradeType.midYear && surprise) {
|
||||
items.add(DateWidget(
|
||||
key: grade.id,
|
||||
date: grade.date,
|
||||
@@ -23,7 +24,8 @@ List<DateWidget> getNewWidgets(List<Grade> providerGrades, DateTime? lastSeenDat
|
||||
List<DateWidget> items = [];
|
||||
List<Grade> newGrades = [];
|
||||
for (var grade in providerGrades) {
|
||||
if (grade.type == GradeType.midYear && !(lastSeenDate != null && !grade.date.isAfter(lastSeenDate)) && grade.value.value != 0) {
|
||||
final surprise = !(lastSeenDate != null && !grade.date.isAfter(lastSeenDate)) && grade.value.value != 0;
|
||||
if (grade.type == GradeType.midYear && surprise) {
|
||||
newGrades.add(grade);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,15 +4,12 @@ import 'package:filcnaplo_mobile_ui/common/widgets/homework/homework_viewable.da
|
||||
|
||||
List<DateWidget> getWidgets(List<Homework> providerHomework) {
|
||||
List<DateWidget> items = [];
|
||||
final now = DateTime.now();
|
||||
providerHomework.where((h) => h.deadline.hour == 0 ? _sameDate(h.deadline, now) : h.deadline.isAfter(now)).forEach((homework) {
|
||||
for (var homework in providerHomework) {
|
||||
items.add(DateWidget(
|
||||
key: homework.id,
|
||||
date: homework.deadline.year != 0 ? homework.deadline : homework.date,
|
||||
widget: mobile.HomeworkViewable(homework),
|
||||
));
|
||||
});
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
bool _sameDate(DateTime a, DateTime b) => (a.year == b.year && a.month == b.month && a.day == b.day);
|
||||
|
||||
@@ -7,7 +7,7 @@ List<DateWidget> getWidgets(List<Lesson> providerLessons) {
|
||||
providerLessons.where((l) => l.isChanged && l.start.isAfter(DateTime.now())).forEach((lesson) {
|
||||
items.add(DateWidget(
|
||||
key: lesson.id,
|
||||
date: lesson.date,
|
||||
date: DateTime(lesson.date.year, lesson.date.month, lesson.date.day, lesson.start.hour, lesson.start.minute),
|
||||
widget: mobile.ChangedLessonViewable(lesson),
|
||||
));
|
||||
});
|
||||
|
||||
16
filcnaplo/lib/ui/filter/widgets/premium.dart
Normal file
16
filcnaplo/lib/ui/filter/widgets/premium.dart
Normal file
@@ -0,0 +1,16 @@
|
||||
import 'package:filcnaplo/ui/date_widget.dart';
|
||||
import 'package:filcnaplo_premium/ui/mobile/premium/premium_banner_button.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
DateWidget getWidget() {
|
||||
return DateWidget(
|
||||
date: DateTime.now().add(const Duration(minutes: 1)),
|
||||
widget: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 6.0),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(14.0),
|
||||
child: const PremiumBannerButton(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -80,7 +80,7 @@ class GradeTile extends StatelessWidget {
|
||||
child: Padding(
|
||||
padding: leadingPadding,
|
||||
child: Icon(
|
||||
SubjectIcon.resolve(subject: grade.subject).data,
|
||||
SubjectIcon.resolveVariant(subject: grade.subject, context: context),
|
||||
size: 28.0,
|
||||
color: AppColors.of(context).text.withOpacity(.75),
|
||||
),
|
||||
@@ -129,6 +129,7 @@ class GradeValueWidget extends StatelessWidget {
|
||||
this.shadow = false,
|
||||
this.outline = false,
|
||||
this.complemented = false,
|
||||
this.nocolor = false,
|
||||
}) : super(key: key);
|
||||
|
||||
final GradeValue value;
|
||||
@@ -138,13 +139,14 @@ class GradeValueWidget extends StatelessWidget {
|
||||
final bool shadow;
|
||||
final bool outline;
|
||||
final bool complemented;
|
||||
final bool nocolor;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
GradeValue value = Provider.of<SettingsProvider>(context).goodStudent ? GradeValue(5, "Példás", "Példás", this.value.weight) : this.value;
|
||||
bool isSubjectView = SubjectGradesContainer.of(context) != null;
|
||||
|
||||
Color color = gradeColor(context: context, value: value.value);
|
||||
Color color = gradeColor(context: context, value: value.value, nocolor: nocolor);
|
||||
Widget valueText;
|
||||
final percentage = value.percentage;
|
||||
|
||||
@@ -166,7 +168,9 @@ class GradeValueWidget extends StatelessWidget {
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
);
|
||||
} else if (value.value != 0) {
|
||||
} else if (value.valueName.toLowerCase().specialChars() == 'nem irt') {
|
||||
valueText = const Icon(FeatherIcons.slash);
|
||||
} else {
|
||||
valueText = Stack(alignment: Alignment.topRight, children: [
|
||||
Transform.translate(
|
||||
offset: (value.weight >= 200) ? const Offset(2, 1.5) : Offset.zero,
|
||||
@@ -196,10 +200,6 @@ class GradeValueWidget extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
]);
|
||||
} else if (value.valueName.toLowerCase().specialChars() == 'nem irt') {
|
||||
valueText = const Icon(FeatherIcons.slash);
|
||||
} else {
|
||||
valueText = const Icon(FeatherIcons.type);
|
||||
}
|
||||
|
||||
return fill
|
||||
@@ -223,7 +223,7 @@ class GradeValueWidget extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
Color gradeColor({required BuildContext context, required num value}) {
|
||||
Color gradeColor({required BuildContext context, required num value, bool nocolor = false}) {
|
||||
int valueInt = 0;
|
||||
|
||||
var settings = Provider.of<SettingsProvider>(context, listen: false);
|
||||
@@ -236,6 +236,8 @@ Color gradeColor({required BuildContext context, required num value}) {
|
||||
}
|
||||
} catch (_) {}
|
||||
|
||||
if (nocolor) return AppColors.of(context).text;
|
||||
|
||||
switch (valueInt) {
|
||||
case 5:
|
||||
return settings.gradeColors[4];
|
||||
|
||||
@@ -29,7 +29,7 @@ extension StringFormatUtils on String {
|
||||
htmlString = htmlString.replaceAll(RegExp(r'<p ?>'), "");
|
||||
htmlString = htmlString.replaceAll(RegExp(r'</p ?>'), "\n");
|
||||
var document = parse(htmlString);
|
||||
return document.body?.text.trim() ?? "";
|
||||
return document.body?.text.trim() ?? htmlString;
|
||||
}
|
||||
|
||||
String limit(int max) {
|
||||
|
||||
@@ -3,7 +3,7 @@ description: "Nem hivatalos e-napló alkalmazás az e-Kréta rendszerhez"
|
||||
homepage: https://filcnaplo.hu
|
||||
publish_to: "none"
|
||||
|
||||
version: 3.3.4+168
|
||||
version: 3.4.1+172
|
||||
|
||||
environment:
|
||||
sdk: ">=2.16.0-80.1.beta <3.0.0"
|
||||
@@ -20,6 +20,8 @@ dependencies:
|
||||
path: "../filcnaplo_desktop_ui/"
|
||||
filcnaplo_kreta_api:
|
||||
path: "../filcnaplo_kreta_api/"
|
||||
filcnaplo_premium:
|
||||
path: "../filcnaplo_premium/"
|
||||
|
||||
flutter_localizations:
|
||||
sdk: flutter
|
||||
@@ -51,6 +53,15 @@ dependencies:
|
||||
lottie: ^1.4.3
|
||||
rive: ^0.9.1
|
||||
animated_background: ^2.0.0
|
||||
dropdown_button2: ^1.8.9
|
||||
home_widget: ^0.1.6
|
||||
flutter_expandable_fab:
|
||||
git:
|
||||
url: https://github.com/filc/flutter_expandable_fab
|
||||
ref: master
|
||||
uni_links: ^0.5.1
|
||||
url_launcher: ^6.1.6
|
||||
workmanager: ^0.5.1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_lints: ^2.0.1
|
||||
|
||||
Submodule filcnaplo_kreta_api updated: 47e98dbeae...66a65ad649
Submodule filcnaplo_mobile_ui updated: 1e32a601cb...19d78b7caa
1
filcnaplo_premium
Submodule
1
filcnaplo_premium
Submodule
Submodule filcnaplo_premium added at 3f23e52748
Reference in New Issue
Block a user