firka: refactor file structure

This commit is contained in:
2026-02-28 07:47:33 +01:00
parent 2d2c2fbef9
commit fc9907f33d
102 changed files with 1025 additions and 5719 deletions

View File

@@ -3,21 +3,21 @@ import 'dart:convert';
import 'dart:math';
import 'package:dio/dio.dart';
import 'package:firka/helpers/api/model/all_lessons.dart';
import 'package:firka/helpers/api/model/class_group.dart';
import 'package:firka/helpers/api/model/homework.dart';
import 'package:firka/helpers/api/model/timetable.dart';
import 'package:firka/helpers/db/models/generic_cache_model.dart';
import 'package:firka/helpers/db/models/timetable_cache_model.dart';
import 'package:firka/api/model/all_lessons.dart';
import 'package:firka/api/model/class_group.dart';
import 'package:firka/api/model/homework.dart';
import 'package:firka/api/model/timetable.dart';
import 'package:firka/data/models/generic_cache_model.dart';
import 'package:firka/data/models/timetable_cache_model.dart';
import 'package:intl/intl.dart';
import 'package:isar_community/isar.dart';
import '../../../main.dart';
import '../../db/models/token_model.dart';
import '../../db/util.dart';
import '../../debug_helper.dart';
import '../../active_account_helper.dart';
import '../../watch_sync_helper.dart';
import 'package:firka/app/app_state.dart';
import 'package:firka/data/models/token_model.dart';
import 'package:firka/data/util.dart';
import 'package:firka/core/debug_helper.dart';
import 'package:firka/services/active_account_helper.dart';
import 'package:firka/services/watch_sync_helper.dart';
import '../consts.dart';
import '../exceptions/token.dart';
import '../model/grade.dart';

View File

@@ -1,9 +1,9 @@
import 'package:firka/helpers/api/model/class_group.dart';
import 'package:firka/helpers/api/model/homework.dart';
import 'package:firka/helpers/api/model/notice_board.dart';
import 'package:firka/helpers/api/model/omission.dart';
import 'package:firka/helpers/api/model/test.dart';
import 'package:firka/helpers/api/model/timetable.dart';
import 'package:firka/api/model/class_group.dart';
import 'package:firka/api/model/homework.dart';
import 'package:firka/api/model/notice_board.dart';
import 'package:firka/api/model/omission.dart';
import 'package:firka/api/model/test.dart';
import 'package:firka/api/model/timetable.dart';
import '../model/grade.dart';
import '../model/student.dart';

View File

@@ -1,5 +1,5 @@
import 'package:dio/dio.dart';
import 'package:firka/helpers/api/model/timetable.dart';
import 'package:firka/api/model/timetable.dart';
import 'package:logging/logging.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';

View File

@@ -4,7 +4,7 @@ import 'dart:math';
import 'dart:typed_data';
import 'package:crypto/crypto.dart';
import 'package:firka/main.dart';
import 'package:firka/app/app_state.dart';
class Constants {
static String get clientId {

View File

@@ -1,4 +1,4 @@
import 'package:firka/helpers/api/model/generic.dart';
import 'package:firka/api/model/generic.dart';
class ClassGroup {
final String uid;

View File

@@ -1,5 +1,5 @@
import 'package:firka/helpers/api/model/generic.dart';
import 'package:firka/helpers/api/model/subject.dart';
import 'package:firka/api/model/generic.dart';
import 'package:firka/api/model/subject.dart';
class Grade {
final String uid;

View File

@@ -1,4 +1,4 @@
import 'package:firka/helpers/api/model/subject.dart';
import 'package:firka/api/model/subject.dart';
import 'generic.dart';

View File

@@ -1,4 +1,4 @@
import 'package:firka/helpers/api/model/generic.dart';
import 'package:firka/api/model/generic.dart';
class NoticeBoardItem {
final String uid;

View File

@@ -1,5 +1,5 @@
import 'package:firka/helpers/api/model/generic.dart';
import 'package:firka/helpers/api/model/subject.dart';
import 'package:firka/api/model/generic.dart';
import 'package:firka/api/model/subject.dart';
class Omission {
final String uid;

View File

@@ -1,6 +1,6 @@
import 'package:firka/helpers/api/model/guardian.dart';
import 'package:firka/helpers/api/model/institution.dart';
import 'package:firka/helpers/json_helper.dart';
import 'package:firka/api/model/guardian.dart';
import 'package:firka/api/model/institution.dart';
import 'package:firka/core/json_helper.dart';
import 'package:intl/intl.dart';
class Student {

View File

@@ -1,4 +1,4 @@
import 'package:firka/helpers/api/model/subject.dart';
import 'package:firka/api/model/subject.dart';
import 'generic.dart';

View File

@@ -1,5 +1,5 @@
import 'package:firka/helpers/api/model/generic.dart';
import 'package:firka/helpers/api/model/subject.dart';
import 'package:firka/api/model/generic.dart';
import 'package:firka/api/model/subject.dart';
class Lesson {
final String uid;

View File

@@ -1,9 +1,9 @@
import 'package:dio/dio.dart';
import 'package:firka/helpers/api/exceptions/token.dart';
import 'package:firka/helpers/api/resp/token_grant.dart';
import 'package:firka/helpers/db/models/token_model.dart';
import 'package:firka/api/exceptions/token.dart';
import 'package:firka/api/resp/token_grant.dart';
import 'package:firka/data/models/token_model.dart';
import '../../main.dart';
import 'package:firka/app/app_state.dart';
import 'consts.dart';
Future<TokenGrantResponse> getAccessToken(String code) async {

View File

@@ -0,0 +1,66 @@
import 'dart:typed_data';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:firka/api/client/kreta_client.dart';
import 'package:firka/data/models/token_model.dart';
import 'package:firka/core/state/update_notifier.dart';
import 'package:firka/core/settings.dart';
import 'package:firka/l10n/app_localizations.dart';
import 'package:logging/logging.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:isar_community/isar.dart';
import 'dart:io';
late final Logger logger;
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
late AppInitialization initData;
bool initDone = false;
final dio = Dio();
final isBeta = true;
final ValueNotifier<bool> isLightMode = ValueNotifier<bool>(true);
final UpdateNotifier globalUpdate = UpdateNotifier();
class DeviceInfo {
String model;
String versionRelease;
String versionSdkInt;
DeviceInfo(this.model, this.versionRelease, this.versionSdkInt);
@override
String toString() {
return "DeviceInfo(model = \"$model\", versionRelease = \"$versionRelease\""
", versionSdkInt = \"$versionSdkInt\"";
}
}
class AppInitialization {
final Isar isar;
final Directory appDir;
final PackageInfo packageInfo;
final DeviceInfo devInfo;
late KretaClient client;
List<TokenModel> tokens;
bool hasWatchListener = false;
Uint8List? profilePicture;
SettingsStore settings;
UpdateNotifier settingsUpdateNotifier = UpdateNotifier();
UpdateNotifier profilePictureUpdateNotifier = UpdateNotifier();
AppLocalizations l10n;
final GlobalKey<NavigatorState> navigatorKey;
AppInitialization({
required this.isar,
required this.appDir,
required this.devInfo,
required this.packageInfo,
required this.tokens,
required this.settings,
required this.l10n,
required this.navigatorKey,
});
}

View File

@@ -0,0 +1,399 @@
import 'dart:async';
import 'dart:io';
import 'dart:ui' as ui;
import 'package:flutter/foundation.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/services.dart';
import 'package:firka/app/app_state.dart';
import 'package:firka/services/active_account_helper.dart';
import 'package:firka/api/client/kreta_client.dart';
import 'package:firka/data/models/app_settings_model.dart';
import 'package:firka/data/models/generic_cache_model.dart';
import 'package:firka/data/models/homework_cache_model.dart';
import 'package:firka/data/models/timetable_cache_model.dart';
import 'package:firka/data/models/token_model.dart';
import 'package:firka/services/live_activity_service.dart';
import 'package:firka/core/settings.dart';
import 'package:firka/services/watch_sync_helper.dart';
import 'package:firka/l10n/app_localizations_de.dart';
import 'package:firka/l10n/app_localizations_en.dart';
import 'package:firka/l10n/app_localizations_hu.dart';
import 'package:firka/core/swear_generator.dart';
import 'package:firka/ui/theme/style.dart';
import 'package:intl/intl.dart';
import 'package:logging/logging.dart';
import 'package:path/path.dart' as p;
import 'package:isar_community/isar.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:path_provider/path_provider.dart';
Isar? isarInit;
Future<Isar> initDB() async {
if (isarInit != null) return isarInit!;
final dir = await getApplicationDocumentsDirectory();
isarInit = await Isar.open(
[
TokenModelSchema,
GenericCacheModelSchema,
TimetableCacheModelSchema,
HomeworkCacheModelSchema,
AppSettingsModelSchema,
HomeworkDoneModelSchema,
],
inspector: true,
directory: dir.path,
);
return isarInit!;
}
Future<void> initLang(AppInitialization data) async {
String? languageCode;
switch ((data.settings.group("settings").subGroup("application")["language"]
as SettingsItemsRadio)
.activeIndex) {
case 1: // hu
data.l10n = AppLocalizationsHu();
languageCode = 'hu';
break;
case 2: // en
data.l10n = AppLocalizationsEn();
languageCode = 'en';
break;
case 3: // de
data.l10n = AppLocalizationsDe();
languageCode = 'de';
break;
default: // auto
switch (ui.PlatformDispatcher.instance.locale.languageCode) {
case 'hu':
data.l10n = AppLocalizationsHu();
languageCode = 'hu';
break;
case 'en':
data.l10n = AppLocalizationsEn();
languageCode = 'en';
break;
case 'de':
data.l10n = AppLocalizationsDe();
languageCode = 'de';
break;
}
break;
}
if (languageCode != null && Platform.isIOS) {
try {
await LiveActivityService.updateLanguagePreference(languageCode);
} catch (e) {
logger.warning('Failed to update language preference on backend: $e');
}
try {
await WatchSyncHelper.sendLanguageToWatch();
} catch (e) {
logger.warning('Failed to send language to Watch: $e');
}
}
}
void initTheme(AppInitialization data) {
final brightness =
SchedulerBinding.instance.platformDispatcher.platformBrightness;
switch ((data.settings.group("settings").subGroup("customization")["theme"]
as SettingsItemsRadio)
.activeIndex) {
case 1:
appStyle = lightStyle;
isLightMode.value = true;
break;
case 2:
appStyle = darkStyle;
isLightMode.value = false;
break;
default:
if (brightness == Brightness.dark) {
appStyle = darkStyle;
isLightMode.value = false;
} else {
appStyle = lightStyle;
isLightMode.value = true;
}
}
}
Future<void> _initData(AppInitialization init) async {
await init.settings.load(init.isar.appSettingsModels);
await initLang(init);
initTheme(init);
init.settings = SettingsStore(init.l10n);
await init.settings.load(init.isar.appSettingsModels);
var dispatcher = SchedulerBinding.instance.platformDispatcher;
dispatcher.onPlatformBrightnessChanged = () {
globalUpdate.update();
initTheme(init);
};
dispatcher.onLocaleChanged = () {
final languageSetting =
init.settings.group("settings").subGroup("application")["language"]
as SettingsItemsRadio;
final isAutoLanguage = languageSetting.activeIndex == 0;
if (!isAutoLanguage) {
return;
}
final previousLocale = init.l10n.localeName;
unawaited(() async {
await initLang(init);
final nextLocale = init.l10n.localeName;
if (previousLocale != nextLocale) {
logger.info(
"[Init] System locale changed in auto mode: $previousLocale -> $nextLocale",
);
}
globalUpdate.update();
}());
};
resetOldTimeTableCache(init.isar);
resetOldHomeworkCache(init.isar);
var didRunFreshInstallCleanup = false;
if (Platform.isIOS) {
try {
didRunFreshInstallCleanup =
await WatchSyncHelper.runFreshInstallCleanupIfNeeded(isar: init.isar);
if (didRunFreshInstallCleanup) {
logger.info(
'[Init] Fresh-install cleanup completed; skipping startup iCloud recovery on this launch',
);
} else {
await WatchSyncHelper.checkAndRecoverFromiCloud(
isar: init.isar,
tokens: init.tokens,
);
}
} catch (e) {
logger.warning('[Init] iCloud bootstrap/recovery failed: $e');
}
}
final allTokens = await init.isar.tokenModels.where().findAll();
init.tokens = allTokens;
if (allTokens.isNotEmpty) {
final token = pickActiveToken(tokens: allTokens, settings: init.settings);
if (token == null) {
logger.warning(
"[Init] Tokens disappeared during initialization; skipping client setup",
);
return;
}
logger.fine("Initializing kréta client as: ${token.studentId}");
init.client = KretaClient(token, init.isar);
if (Platform.isIOS) {
final expiryDate = token.expiryDate;
if (expiryDate != null && expiryDate.isAfter(DateTime.now())) {
KretaClient.clearReauthFlag();
}
unawaited(() async {
try {
await WatchSyncHelper.saveTokenToiCloud(token);
} catch (e) {
logger.warning('[Init] Failed to sync active token to iCloud: $e');
}
try {
await WatchSyncHelper.sendTokenModelToWatch(token);
} catch (e) {
logger.warning('[Init] Failed to sync active token to Watch: $e');
}
}());
}
}
final dataDir = await getApplicationDocumentsDirectory();
var pfpFile = File(p.join(dataDir.path, "profile.webp"));
if (await pfpFile.exists()) {
init.profilePicture = await pfpFile.readAsBytes();
}
}
Future<AppInitialization> initializeApp() async {
if (initDone) {
await _initData(initData);
return initData;
}
final isar = await initDB();
final tokens = await isar.tokenModels.where().findAll();
logger.finest('Token count: ${tokens.length}');
var devInfoFetched = false;
var devInfo = DeviceInfo("SM-A705FN", "11", "30");
try {
if (Platform.isAndroid) {
const channel = MethodChannel("firka.app/main");
final rawInfo = ((await channel.invokeMethod("get_info")) as String)
.split(";");
devInfo = DeviceInfo(rawInfo[0], rawInfo[1], rawInfo[2]);
devInfoFetched = true;
}
} catch (e) {
if (e is Error) {
logger.shout("Error in initializeApp()", e.toString(), e.stackTrace);
} else {
logger.shout("Error in initializeApp()", e.toString());
}
}
logger.fine("Fetched device info: ${devInfoFetched ? "yes" : "no"}");
logger.fine("Using device info: ${devInfo.toString()}");
var init = AppInitialization(
isar: isar,
appDir: await getApplicationDocumentsDirectory(),
devInfo: devInfo,
packageInfo: await PackageInfo.fromPlatform(),
tokens: tokens,
settings: SettingsStore(AppLocalizationsHu()),
l10n: AppLocalizationsHu(),
navigatorKey: navigatorKey,
);
if (Platform.isIOS) {
try {
await LiveActivityService.initialize().timeout(
const Duration(seconds: 8),
);
} on TimeoutException catch (e, st) {
logger.warning('LiveActivity init timed out: $e', e, st);
} catch (e, st) {
logger.severe('Failed to initialize LiveActivity: $e', e, st);
}
}
await _initData(init);
init.settingsUpdateNotifier.addListener(() {
logger.finest("Settings updated");
});
return init;
}
Future<void> setupLogging() async {
final jwtPattern = RegExp(
r'([A-Za-z0-9-_]+)\.([A-Za-z0-9-_]+)\.([A-Za-z0-9-_]+)',
);
final omPattern = RegExp(r'(\d{3})(\d{6})([A-Za-z0-9]?)');
final refreshTokenPattern = RegExp(
r'"(?=.{21,}$)([A-Z0-9]+-[A-Z0-9_\-.~+]*)"',
);
final docs = await getApplicationDocumentsDirectory();
Future<void> deleteOldLogFiles() async {
final docs = await getApplicationDocumentsDirectory();
final dir = Directory(docs.path);
if (!dir.existsSync()) return;
final now = DateTime.now();
final cutoff = now.subtract(Duration(days: 30));
final logFileRegex = RegExp(r'^(\d{4})_(\d{2})_(\d{2})\.log$');
for (final entity in dir.listSync()) {
if (entity is! File) continue;
final name = entity.uri.pathSegments.last;
final m = logFileRegex.firstMatch(name);
if (m == null) continue;
try {
final y = int.parse(m.group(1)!);
final mo = int.parse(m.group(2)!);
final d = int.parse(m.group(3)!);
final fileDate = DateTime(y, mo, d);
if (fileDate.isBefore(
DateTime(cutoff.year, cutoff.month, cutoff.day),
)) {
logger.info("Removing old log file: $name");
await entity.delete();
}
} catch (_) {
// ignore parse/delete errors
}
}
}
String logFilePathForDate(DateTime dt) {
final fileName = "${DateFormat("yyyy_MM_dd").format(dt)}.log";
return Directory(docs.path).uri.resolve(fileName).toFilePath();
}
File fileForDate(DateTime dt) {
final path = logFilePathForDate(dt);
final file = File(path);
if (!file.existsSync()) file.createSync(recursive: true);
return file;
}
String censorLog(String msg) {
return msg
.replaceAll(jwtPattern, '***')
.replaceAllMapped(omPattern, (match) {
return "${match.group(1)}******${match.group(3)}";
})
.replaceAll(refreshTokenPattern, '"***"');
}
hierarchicalLoggingEnabled = true;
logger.level = Level.ALL;
DateTime currentDate = DateTime.now();
IOSink sink = fileForDate(currentDate).openWrite(mode: FileMode.append);
logger.onRecord.listen((record) {
final now = DateTime.now();
if (now.year != currentDate.year ||
now.month != currentDate.month ||
now.day != currentDate.day) {
sink.flush();
sink.close();
currentDate = now;
sink = fileForDate(currentDate).openWrite(mode: FileMode.append);
}
final censored = censorLog(record.message);
final timestamp = DateFormat('yyyy-MM-dd HH:mm:ss.SSS').format(now);
final level = record.level.name;
final line = '[$timestamp] [$level] [$censored]';
sink.writeln(line);
debugPrint(
"[Firka] [${record.level.name}] ${kDebugMode ? record.message : censored}",
);
});
unawaited(deleteOldLogFiles());
try {
logger.finest('loading dirty words');
await loadDirtyWords();
logger.finest('loaded dirty words');
} catch (e, st) {
logger.severe('Failed to load dirty words: $e', e, st);
}
}

View File

@@ -0,0 +1,180 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_native_splash/flutter_native_splash.dart';
import 'package:firka/app/app_state.dart';
import 'package:firka/app/initialization.dart';
import 'package:firka/core/firka_bundle.dart';
import 'package:firka/services/watch_sync_helper.dart';
import 'package:firka/l10n/app_localizations.dart';
import 'package:firka/ui/phone/screens/debug/debug_screen.dart';
import 'package:firka/ui/phone/screens/home/home_screen.dart';
import 'package:firka/ui/phone/screens/login/login_screen.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
class InitializationScreen extends StatelessWidget {
InitializationScreen({super.key});
final Future<AppInitialization> _init = initializeApp().timeout(
const Duration(seconds: 20),
);
@override
Widget build(BuildContext context) {
return FutureBuilder<AppInitialization>(
future: _init,
builder: (context, snapshot) {
// Check if initialization is complete
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasError) {
logger.shout(
"Error in InitializationScreen",
snapshot.error.toString(),
snapshot.stackTrace,
);
FlutterNativeSplash.remove();
// Handle initialization error
return MaterialApp(
key: ValueKey('errorPage'),
home: DefaultAssetBundle(
bundle: FirkaBundle(),
child: Scaffold(
body: Center(
child: Text(
'Error initializing app: ${snapshot.error}',
style: TextStyle(color: Colors.red),
),
),
),
),
);
}
// Initialization successful, determine which screen to show
Widget screen;
assert(snapshot.data != null);
initData = snapshot.data!;
initDone = true;
FlutterNativeSplash.remove();
WatchSyncHelper.initialize();
if (Platform.isIOS) {
unawaited(() async {
try {
await WatchSyncHelper.sendLanguageToWatch();
} catch (e) {
logger.warning(
'[Init] Failed to publish language to Watch after sync init: $e',
);
}
}());
}
if (!initData.hasWatchListener) {
initData.hasWatchListener = true;
WatchSyncHelper.onWatchMessage = (msg) {
logger.finest("WatchOS IPC [Watch -> Phone]: ${msg["id"]}");
switch (msg["id"]) {
case "ping":
if (initData.tokens.isNotEmpty) {
logger.finest("WatchOS IPC [Phone -> Watch]: pong");
const watchChannel = MethodChannel('app.firka/watch_sync');
watchChannel.invokeMethod('sendMessageToWatch', {
"id": "pong",
});
navigatorKey.currentState?.push(
MaterialPageRoute(
builder: (context) => HomeScreen(
initData,
true,
model: msg["model"] as String? ?? "unknown",
),
),
);
}
}
};
}
if (snapshot.data!.tokens.isEmpty) {
screen = LoginScreen(initData, key: ValueKey('loginScreen'));
} else {
screen = HomeScreen(initData, false, key: ValueKey('homeScreen'));
}
return MaterialApp(
title: 'Firka',
key: ValueKey('firkaApp'),
navigatorKey: navigatorKey,
theme: ThemeData(
primarySwatch: Colors.lightGreen,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
localizationsDelegates: [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: AppLocalizations.supportedLocales,
home: DefaultAssetBundle(
bundle: FirkaBundle(),
child: ValueListenableBuilder<bool>(
valueListenable: isLightMode,
builder: (context, isLight, _) {
final overlay = SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
statusBarIconBrightness: isLight
? Brightness.dark
: Brightness.light,
statusBarBrightness: isLight
? Brightness.light
: Brightness.dark,
systemStatusBarContrastEnforced: false,
);
SystemChrome.setSystemUIOverlayStyle(overlay);
return AnnotatedRegion<SystemUiOverlayStyle>(
value: overlay,
child: screen,
);
},
),
),
routes: {
'/login': (context) => DefaultAssetBundle(
bundle: FirkaBundle(),
child: LoginScreen(initData, key: ValueKey('loginScreen')),
),
'/home': (context) => DefaultAssetBundle(
bundle: FirkaBundle(),
child: HomeScreen(initData, false, key: ValueKey('homeScreen')),
),
'/debug': (context) => DefaultAssetBundle(
bundle: FirkaBundle(),
child: DebugScreen(initData, key: ValueKey('debugScreen')),
),
},
);
}
return MaterialApp(
home: DefaultAssetBundle(
bundle: FirkaBundle(),
child: Scaffold(
backgroundColor: const Color(0xFF7CA120),
body: Container(),
),
),
);
},
);
}
}

View File

@@ -1,4 +1,4 @@
import 'package:firka/helpers/api/model/grade.dart';
import 'package:firka/api/model/grade.dart';
double calculateAverage(List<Grade> sortedGrades) {
double totalWeight = 0.0;

View File

@@ -1,8 +1,8 @@
import 'package:intl/intl.dart';
import '../l10n/app_localizations.dart';
import 'api/model/timetable.dart';
import 'debug_helper.dart';
import 'package:firka/api/model/timetable.dart';
import 'package:firka/core/debug_helper.dart';
import 'package:firka/l10n/app_localizations.dart';
extension TimetableExtension on Iterable<Lesson> {
List<Lesson> getAllSeqs(Lesson reference) {

View File

@@ -3,7 +3,7 @@ import 'dart:convert';
import 'dart:io';
import 'package:brotli/brotli.dart';
import 'package:firka/main.dart';
import 'package:firka/app/app_state.dart';
import 'package:flutter/services.dart';
class FirkaBundle extends CachingAssetBundle {

View File

@@ -1,6 +1,6 @@
import 'dart:ui' as ui;
import 'package:firka/main.dart';
import 'package:firka/app/app_state.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';

View File

@@ -1,6 +1,6 @@
import 'dart:io';
import 'package:firka/main.dart';
import 'package:firka/app/app_state.dart';
import 'package:image/image.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path/path.dart' as p;

View File

@@ -2,16 +2,19 @@ import 'dart:collection';
import 'dart:core';
import 'dart:io';
import 'package:firka/helpers/db/models/app_settings_model.dart';
import 'package:firka/helpers/live_activity_service.dart';
import 'package:firka/data/models/app_settings_model.dart';
import 'package:firka/services/live_activity_service.dart';
import 'package:firka/l10n/app_localizations.dart';
import 'package:firka/ui/widget/firka_icon.dart';
import 'package:firka/ui/shared/firka_icon.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:isar_community/isar.dart';
import 'package:majesticons_flutter/majesticons_flutter.dart';
import '../main.dart';
import 'package:firka/app/app_state.dart';
import 'package:firka/app/initialization.dart';
import 'package:firka/app/initialization_screen.dart';
import 'package:flutter/material.dart';
const bellRing = 1001;
const rounding1 = 1002;

View File

@@ -1,4 +1,4 @@
import 'package:firka/main.dart';
import 'package:firka/app/app_state.dart';
import 'package:flutter/widgets.dart';
abstract class FirkaState<T extends StatefulWidget> extends State<T> {

View File

@@ -1,8 +1,8 @@
import 'dart:convert';
import 'dart:io';
import 'package:firka/helpers/api/model/grade.dart';
import 'package:firka/helpers/api/model/timetable.dart';
import 'package:firka/api/model/grade.dart';
import 'package:firka/api/model/timetable.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';

View File

@@ -1,7 +1,7 @@
import 'package:isar_community/isar.dart';
import '../../debug_helper.dart';
import '../util.dart';
import 'package:firka/core/debug_helper.dart';
import 'package:firka/data/util.dart';
part 'homework_cache_model.g.dart';

View File

@@ -1,7 +1,7 @@
import 'package:isar_community/isar.dart';
import '../../debug_helper.dart';
import '../util.dart';
import 'package:firka/core/debug_helper.dart';
import 'package:firka/data/util.dart';
part 'timetable_cache_model.g.dart';

View File

@@ -2,12 +2,11 @@ import 'dart:convert';
import 'package:crypto/crypto.dart';
import 'package:dart_jsonwebtoken/dart_jsonwebtoken.dart';
import 'package:firka/helpers/api/resp/token_grant.dart';
import 'package:firka/helpers/extensions.dart';
import 'package:firka/api/resp/token_grant.dart';
import 'package:firka/core/debug_helper.dart';
import 'package:firka/core/extensions.dart';
import 'package:isar_community/isar.dart';
import '../../debug_helper.dart';
part 'token_model.g.dart';
@collection

View File

@@ -3,7 +3,7 @@ import 'dart:math';
import 'package:intl/intl.dart';
import 'package:isar_community/isar.dart';
import '../debug_helper.dart';
import 'package:firka/core/debug_helper.dart';
class DatedCacheEntry {
Id? cacheKey;

View File

@@ -1,18 +1,18 @@
import 'dart:convert';
import 'dart:io';
import 'package:firka/helpers/api/client/kreta_client.dart';
import 'package:firka/helpers/api/model/grade.dart';
import 'package:firka/helpers/api/model/timetable.dart';
import 'package:firka/helpers/db/ios_widget_helper.dart';
import 'package:firka/helpers/debug_helper.dart';
import 'package:firka/helpers/settings.dart';
import 'package:firka/main.dart';
import 'package:firka/api/client/kreta_client.dart';
import 'package:firka/api/model/grade.dart';
import 'package:firka/api/model/timetable.dart';
import 'package:firka/core/debug_helper.dart';
import 'package:firka/data/ios_widget_helper.dart';
import 'package:firka/core/settings.dart';
import 'package:firka/app/app_state.dart';
import 'package:flutter/foundation.dart';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';
import '../../ui/model/style.dart';
import 'package:firka/ui/theme/style.dart';
class WidgetCacheHelper {
static Map<String, dynamic> toJson(FirkaStyle style, List<Lesson> timetable) {

View File

@@ -1,843 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'app_settings_model.dart';
// **************************************************************************
// IsarCollectionGenerator
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
extension GetAppSettingsModelCollection on Isar {
IsarCollection<AppSettingsModel> get appSettingsModels => this.collection();
}
const AppSettingsModelSchema = CollectionSchema(
name: r'AppSettingsModel',
id: -638838212012723081,
properties: {
r'valueBool': PropertySchema(
id: 0,
name: r'valueBool',
type: IsarType.bool,
),
r'valueDouble': PropertySchema(
id: 1,
name: r'valueDouble',
type: IsarType.double,
),
r'valueIndex': PropertySchema(
id: 2,
name: r'valueIndex',
type: IsarType.long,
),
r'valueString': PropertySchema(
id: 3,
name: r'valueString',
type: IsarType.string,
),
},
estimateSize: _appSettingsModelEstimateSize,
serialize: _appSettingsModelSerialize,
deserialize: _appSettingsModelDeserialize,
deserializeProp: _appSettingsModelDeserializeProp,
idName: r'id',
indexes: {},
links: {},
embeddedSchemas: {},
getId: _appSettingsModelGetId,
getLinks: _appSettingsModelGetLinks,
attach: _appSettingsModelAttach,
version: '3.3.0',
);
int _appSettingsModelEstimateSize(
AppSettingsModel object,
List<int> offsets,
Map<Type, List<int>> allOffsets,
) {
var bytesCount = offsets.last;
{
final value = object.valueString;
if (value != null) {
bytesCount += 3 + value.length * 3;
}
}
return bytesCount;
}
void _appSettingsModelSerialize(
AppSettingsModel object,
IsarWriter writer,
List<int> offsets,
Map<Type, List<int>> allOffsets,
) {
writer.writeBool(offsets[0], object.valueBool);
writer.writeDouble(offsets[1], object.valueDouble);
writer.writeLong(offsets[2], object.valueIndex);
writer.writeString(offsets[3], object.valueString);
}
AppSettingsModel _appSettingsModelDeserialize(
Id id,
IsarReader reader,
List<int> offsets,
Map<Type, List<int>> allOffsets,
) {
final object = AppSettingsModel();
object.id = id;
object.valueBool = reader.readBoolOrNull(offsets[0]);
object.valueDouble = reader.readDoubleOrNull(offsets[1]);
object.valueIndex = reader.readLongOrNull(offsets[2]);
object.valueString = reader.readStringOrNull(offsets[3]);
return object;
}
P _appSettingsModelDeserializeProp<P>(
IsarReader reader,
int propertyId,
int offset,
Map<Type, List<int>> allOffsets,
) {
switch (propertyId) {
case 0:
return (reader.readBoolOrNull(offset)) as P;
case 1:
return (reader.readDoubleOrNull(offset)) as P;
case 2:
return (reader.readLongOrNull(offset)) as P;
case 3:
return (reader.readStringOrNull(offset)) as P;
default:
throw IsarError('Unknown property with id $propertyId');
}
}
Id _appSettingsModelGetId(AppSettingsModel object) {
return object.id ?? Isar.autoIncrement;
}
List<IsarLinkBase<dynamic>> _appSettingsModelGetLinks(AppSettingsModel object) {
return [];
}
void _appSettingsModelAttach(
IsarCollection<dynamic> col,
Id id,
AppSettingsModel object,
) {
object.id = id;
}
extension AppSettingsModelQueryWhereSort
on QueryBuilder<AppSettingsModel, AppSettingsModel, QWhere> {
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterWhere> anyId() {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(const IdWhereClause.any());
});
}
}
extension AppSettingsModelQueryWhere
on QueryBuilder<AppSettingsModel, AppSettingsModel, QWhereClause> {
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterWhereClause> idEqualTo(
Id id,
) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(IdWhereClause.between(lower: id, upper: id));
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterWhereClause>
idNotEqualTo(Id id) {
return QueryBuilder.apply(this, (query) {
if (query.whereSort == Sort.asc) {
return query
.addWhereClause(
IdWhereClause.lessThan(upper: id, includeUpper: false),
)
.addWhereClause(
IdWhereClause.greaterThan(lower: id, includeLower: false),
);
} else {
return query
.addWhereClause(
IdWhereClause.greaterThan(lower: id, includeLower: false),
)
.addWhereClause(
IdWhereClause.lessThan(upper: id, includeUpper: false),
);
}
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterWhereClause>
idGreaterThan(Id id, {bool include = false}) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(
IdWhereClause.greaterThan(lower: id, includeLower: include),
);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterWhereClause>
idLessThan(Id id, {bool include = false}) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(
IdWhereClause.lessThan(upper: id, includeUpper: include),
);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterWhereClause> idBetween(
Id lowerId,
Id upperId, {
bool includeLower = true,
bool includeUpper = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(
IdWhereClause.between(
lower: lowerId,
includeLower: includeLower,
upper: upperId,
includeUpper: includeUpper,
),
);
});
}
}
extension AppSettingsModelQueryFilter
on QueryBuilder<AppSettingsModel, AppSettingsModel, QFilterCondition> {
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
idIsNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
const FilterCondition.isNull(property: r'id'),
);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
idIsNotNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
const FilterCondition.isNotNull(property: r'id'),
);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
idEqualTo(Id? value) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.equalTo(property: r'id', value: value),
);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
idGreaterThan(Id? value, {bool include = false}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.greaterThan(
include: include,
property: r'id',
value: value,
),
);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
idLessThan(Id? value, {bool include = false}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.lessThan(
include: include,
property: r'id',
value: value,
),
);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
idBetween(
Id? lower,
Id? upper, {
bool includeLower = true,
bool includeUpper = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.between(
property: r'id',
lower: lower,
includeLower: includeLower,
upper: upper,
includeUpper: includeUpper,
),
);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
valueBoolIsNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
const FilterCondition.isNull(property: r'valueBool'),
);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
valueBoolIsNotNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
const FilterCondition.isNotNull(property: r'valueBool'),
);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
valueBoolEqualTo(bool? value) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.equalTo(property: r'valueBool', value: value),
);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
valueDoubleIsNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
const FilterCondition.isNull(property: r'valueDouble'),
);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
valueDoubleIsNotNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
const FilterCondition.isNotNull(property: r'valueDouble'),
);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
valueDoubleEqualTo(double? value, {double epsilon = Query.epsilon}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.equalTo(
property: r'valueDouble',
value: value,
epsilon: epsilon,
),
);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
valueDoubleGreaterThan(
double? value, {
bool include = false,
double epsilon = Query.epsilon,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.greaterThan(
include: include,
property: r'valueDouble',
value: value,
epsilon: epsilon,
),
);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
valueDoubleLessThan(
double? value, {
bool include = false,
double epsilon = Query.epsilon,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.lessThan(
include: include,
property: r'valueDouble',
value: value,
epsilon: epsilon,
),
);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
valueDoubleBetween(
double? lower,
double? upper, {
bool includeLower = true,
bool includeUpper = true,
double epsilon = Query.epsilon,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.between(
property: r'valueDouble',
lower: lower,
includeLower: includeLower,
upper: upper,
includeUpper: includeUpper,
epsilon: epsilon,
),
);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
valueIndexIsNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
const FilterCondition.isNull(property: r'valueIndex'),
);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
valueIndexIsNotNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
const FilterCondition.isNotNull(property: r'valueIndex'),
);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
valueIndexEqualTo(int? value) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.equalTo(property: r'valueIndex', value: value),
);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
valueIndexGreaterThan(int? value, {bool include = false}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.greaterThan(
include: include,
property: r'valueIndex',
value: value,
),
);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
valueIndexLessThan(int? value, {bool include = false}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.lessThan(
include: include,
property: r'valueIndex',
value: value,
),
);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
valueIndexBetween(
int? lower,
int? upper, {
bool includeLower = true,
bool includeUpper = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.between(
property: r'valueIndex',
lower: lower,
includeLower: includeLower,
upper: upper,
includeUpper: includeUpper,
),
);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
valueStringIsNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
const FilterCondition.isNull(property: r'valueString'),
);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
valueStringIsNotNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
const FilterCondition.isNotNull(property: r'valueString'),
);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
valueStringEqualTo(String? value, {bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.equalTo(
property: r'valueString',
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
valueStringGreaterThan(
String? value, {
bool include = false,
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.greaterThan(
include: include,
property: r'valueString',
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
valueStringLessThan(
String? value, {
bool include = false,
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.lessThan(
include: include,
property: r'valueString',
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
valueStringBetween(
String? lower,
String? upper, {
bool includeLower = true,
bool includeUpper = true,
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.between(
property: r'valueString',
lower: lower,
includeLower: includeLower,
upper: upper,
includeUpper: includeUpper,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
valueStringStartsWith(String value, {bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.startsWith(
property: r'valueString',
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
valueStringEndsWith(String value, {bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.endsWith(
property: r'valueString',
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
valueStringContains(String value, {bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.contains(
property: r'valueString',
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
valueStringMatches(String pattern, {bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.matches(
property: r'valueString',
wildcard: pattern,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
valueStringIsEmpty() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.equalTo(property: r'valueString', value: ''),
);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
valueStringIsNotEmpty() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.greaterThan(property: r'valueString', value: ''),
);
});
}
}
extension AppSettingsModelQueryObject
on QueryBuilder<AppSettingsModel, AppSettingsModel, QFilterCondition> {}
extension AppSettingsModelQueryLinks
on QueryBuilder<AppSettingsModel, AppSettingsModel, QFilterCondition> {}
extension AppSettingsModelQuerySortBy
on QueryBuilder<AppSettingsModel, AppSettingsModel, QSortBy> {
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterSortBy>
sortByValueBool() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'valueBool', Sort.asc);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterSortBy>
sortByValueBoolDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'valueBool', Sort.desc);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterSortBy>
sortByValueDouble() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'valueDouble', Sort.asc);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterSortBy>
sortByValueDoubleDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'valueDouble', Sort.desc);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterSortBy>
sortByValueIndex() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'valueIndex', Sort.asc);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterSortBy>
sortByValueIndexDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'valueIndex', Sort.desc);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterSortBy>
sortByValueString() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'valueString', Sort.asc);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterSortBy>
sortByValueStringDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'valueString', Sort.desc);
});
}
}
extension AppSettingsModelQuerySortThenBy
on QueryBuilder<AppSettingsModel, AppSettingsModel, QSortThenBy> {
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterSortBy> thenById() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'id', Sort.asc);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterSortBy>
thenByIdDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'id', Sort.desc);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterSortBy>
thenByValueBool() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'valueBool', Sort.asc);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterSortBy>
thenByValueBoolDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'valueBool', Sort.desc);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterSortBy>
thenByValueDouble() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'valueDouble', Sort.asc);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterSortBy>
thenByValueDoubleDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'valueDouble', Sort.desc);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterSortBy>
thenByValueIndex() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'valueIndex', Sort.asc);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterSortBy>
thenByValueIndexDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'valueIndex', Sort.desc);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterSortBy>
thenByValueString() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'valueString', Sort.asc);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterSortBy>
thenByValueStringDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'valueString', Sort.desc);
});
}
}
extension AppSettingsModelQueryWhereDistinct
on QueryBuilder<AppSettingsModel, AppSettingsModel, QDistinct> {
QueryBuilder<AppSettingsModel, AppSettingsModel, QDistinct>
distinctByValueBool() {
return QueryBuilder.apply(this, (query) {
return query.addDistinctBy(r'valueBool');
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QDistinct>
distinctByValueDouble() {
return QueryBuilder.apply(this, (query) {
return query.addDistinctBy(r'valueDouble');
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QDistinct>
distinctByValueIndex() {
return QueryBuilder.apply(this, (query) {
return query.addDistinctBy(r'valueIndex');
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QDistinct>
distinctByValueString({bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addDistinctBy(r'valueString', caseSensitive: caseSensitive);
});
}
}
extension AppSettingsModelQueryProperty
on QueryBuilder<AppSettingsModel, AppSettingsModel, QQueryProperty> {
QueryBuilder<AppSettingsModel, int, QQueryOperations> idProperty() {
return QueryBuilder.apply(this, (query) {
return query.addPropertyName(r'id');
});
}
QueryBuilder<AppSettingsModel, bool?, QQueryOperations> valueBoolProperty() {
return QueryBuilder.apply(this, (query) {
return query.addPropertyName(r'valueBool');
});
}
QueryBuilder<AppSettingsModel, double?, QQueryOperations>
valueDoubleProperty() {
return QueryBuilder.apply(this, (query) {
return query.addPropertyName(r'valueDouble');
});
}
QueryBuilder<AppSettingsModel, int?, QQueryOperations> valueIndexProperty() {
return QueryBuilder.apply(this, (query) {
return query.addPropertyName(r'valueIndex');
});
}
QueryBuilder<AppSettingsModel, String?, QQueryOperations>
valueStringProperty() {
return QueryBuilder.apply(this, (query) {
return query.addPropertyName(r'valueString');
});
}
}

View File

@@ -1,505 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'generic_cache_model.dart';
// **************************************************************************
// IsarCollectionGenerator
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
extension GetGenericCacheModelCollection on Isar {
IsarCollection<GenericCacheModel> get genericCacheModels => this.collection();
}
const GenericCacheModelSchema = CollectionSchema(
name: r'GenericCacheModel',
id: 3174486726793780620,
properties: {
r'cacheData': PropertySchema(
id: 0,
name: r'cacheData',
type: IsarType.string,
),
},
estimateSize: _genericCacheModelEstimateSize,
serialize: _genericCacheModelSerialize,
deserialize: _genericCacheModelDeserialize,
deserializeProp: _genericCacheModelDeserializeProp,
idName: r'cacheKey',
indexes: {},
links: {},
embeddedSchemas: {},
getId: _genericCacheModelGetId,
getLinks: _genericCacheModelGetLinks,
attach: _genericCacheModelAttach,
version: '3.3.0',
);
int _genericCacheModelEstimateSize(
GenericCacheModel object,
List<int> offsets,
Map<Type, List<int>> allOffsets,
) {
var bytesCount = offsets.last;
{
final value = object.cacheData;
if (value != null) {
bytesCount += 3 + value.length * 3;
}
}
return bytesCount;
}
void _genericCacheModelSerialize(
GenericCacheModel object,
IsarWriter writer,
List<int> offsets,
Map<Type, List<int>> allOffsets,
) {
writer.writeString(offsets[0], object.cacheData);
}
GenericCacheModel _genericCacheModelDeserialize(
Id id,
IsarReader reader,
List<int> offsets,
Map<Type, List<int>> allOffsets,
) {
final object = GenericCacheModel();
object.cacheData = reader.readStringOrNull(offsets[0]);
object.cacheKey = id;
return object;
}
P _genericCacheModelDeserializeProp<P>(
IsarReader reader,
int propertyId,
int offset,
Map<Type, List<int>> allOffsets,
) {
switch (propertyId) {
case 0:
return (reader.readStringOrNull(offset)) as P;
default:
throw IsarError('Unknown property with id $propertyId');
}
}
Id _genericCacheModelGetId(GenericCacheModel object) {
return object.cacheKey ?? Isar.autoIncrement;
}
List<IsarLinkBase<dynamic>> _genericCacheModelGetLinks(
GenericCacheModel object,
) {
return [];
}
void _genericCacheModelAttach(
IsarCollection<dynamic> col,
Id id,
GenericCacheModel object,
) {
object.cacheKey = id;
}
extension GenericCacheModelQueryWhereSort
on QueryBuilder<GenericCacheModel, GenericCacheModel, QWhere> {
QueryBuilder<GenericCacheModel, GenericCacheModel, QAfterWhere>
anyCacheKey() {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(const IdWhereClause.any());
});
}
}
extension GenericCacheModelQueryWhere
on QueryBuilder<GenericCacheModel, GenericCacheModel, QWhereClause> {
QueryBuilder<GenericCacheModel, GenericCacheModel, QAfterWhereClause>
cacheKeyEqualTo(Id cacheKey) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(
IdWhereClause.between(lower: cacheKey, upper: cacheKey),
);
});
}
QueryBuilder<GenericCacheModel, GenericCacheModel, QAfterWhereClause>
cacheKeyNotEqualTo(Id cacheKey) {
return QueryBuilder.apply(this, (query) {
if (query.whereSort == Sort.asc) {
return query
.addWhereClause(
IdWhereClause.lessThan(upper: cacheKey, includeUpper: false),
)
.addWhereClause(
IdWhereClause.greaterThan(lower: cacheKey, includeLower: false),
);
} else {
return query
.addWhereClause(
IdWhereClause.greaterThan(lower: cacheKey, includeLower: false),
)
.addWhereClause(
IdWhereClause.lessThan(upper: cacheKey, includeUpper: false),
);
}
});
}
QueryBuilder<GenericCacheModel, GenericCacheModel, QAfterWhereClause>
cacheKeyGreaterThan(Id cacheKey, {bool include = false}) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(
IdWhereClause.greaterThan(lower: cacheKey, includeLower: include),
);
});
}
QueryBuilder<GenericCacheModel, GenericCacheModel, QAfterWhereClause>
cacheKeyLessThan(Id cacheKey, {bool include = false}) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(
IdWhereClause.lessThan(upper: cacheKey, includeUpper: include),
);
});
}
QueryBuilder<GenericCacheModel, GenericCacheModel, QAfterWhereClause>
cacheKeyBetween(
Id lowerCacheKey,
Id upperCacheKey, {
bool includeLower = true,
bool includeUpper = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(
IdWhereClause.between(
lower: lowerCacheKey,
includeLower: includeLower,
upper: upperCacheKey,
includeUpper: includeUpper,
),
);
});
}
}
extension GenericCacheModelQueryFilter
on QueryBuilder<GenericCacheModel, GenericCacheModel, QFilterCondition> {
QueryBuilder<GenericCacheModel, GenericCacheModel, QAfterFilterCondition>
cacheDataIsNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
const FilterCondition.isNull(property: r'cacheData'),
);
});
}
QueryBuilder<GenericCacheModel, GenericCacheModel, QAfterFilterCondition>
cacheDataIsNotNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
const FilterCondition.isNotNull(property: r'cacheData'),
);
});
}
QueryBuilder<GenericCacheModel, GenericCacheModel, QAfterFilterCondition>
cacheDataEqualTo(String? value, {bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.equalTo(
property: r'cacheData',
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<GenericCacheModel, GenericCacheModel, QAfterFilterCondition>
cacheDataGreaterThan(
String? value, {
bool include = false,
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.greaterThan(
include: include,
property: r'cacheData',
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<GenericCacheModel, GenericCacheModel, QAfterFilterCondition>
cacheDataLessThan(
String? value, {
bool include = false,
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.lessThan(
include: include,
property: r'cacheData',
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<GenericCacheModel, GenericCacheModel, QAfterFilterCondition>
cacheDataBetween(
String? lower,
String? upper, {
bool includeLower = true,
bool includeUpper = true,
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.between(
property: r'cacheData',
lower: lower,
includeLower: includeLower,
upper: upper,
includeUpper: includeUpper,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<GenericCacheModel, GenericCacheModel, QAfterFilterCondition>
cacheDataStartsWith(String value, {bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.startsWith(
property: r'cacheData',
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<GenericCacheModel, GenericCacheModel, QAfterFilterCondition>
cacheDataEndsWith(String value, {bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.endsWith(
property: r'cacheData',
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<GenericCacheModel, GenericCacheModel, QAfterFilterCondition>
cacheDataContains(String value, {bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.contains(
property: r'cacheData',
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<GenericCacheModel, GenericCacheModel, QAfterFilterCondition>
cacheDataMatches(String pattern, {bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.matches(
property: r'cacheData',
wildcard: pattern,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<GenericCacheModel, GenericCacheModel, QAfterFilterCondition>
cacheDataIsEmpty() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.equalTo(property: r'cacheData', value: ''),
);
});
}
QueryBuilder<GenericCacheModel, GenericCacheModel, QAfterFilterCondition>
cacheDataIsNotEmpty() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.greaterThan(property: r'cacheData', value: ''),
);
});
}
QueryBuilder<GenericCacheModel, GenericCacheModel, QAfterFilterCondition>
cacheKeyIsNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
const FilterCondition.isNull(property: r'cacheKey'),
);
});
}
QueryBuilder<GenericCacheModel, GenericCacheModel, QAfterFilterCondition>
cacheKeyIsNotNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
const FilterCondition.isNotNull(property: r'cacheKey'),
);
});
}
QueryBuilder<GenericCacheModel, GenericCacheModel, QAfterFilterCondition>
cacheKeyEqualTo(Id? value) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.equalTo(property: r'cacheKey', value: value),
);
});
}
QueryBuilder<GenericCacheModel, GenericCacheModel, QAfterFilterCondition>
cacheKeyGreaterThan(Id? value, {bool include = false}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.greaterThan(
include: include,
property: r'cacheKey',
value: value,
),
);
});
}
QueryBuilder<GenericCacheModel, GenericCacheModel, QAfterFilterCondition>
cacheKeyLessThan(Id? value, {bool include = false}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.lessThan(
include: include,
property: r'cacheKey',
value: value,
),
);
});
}
QueryBuilder<GenericCacheModel, GenericCacheModel, QAfterFilterCondition>
cacheKeyBetween(
Id? lower,
Id? upper, {
bool includeLower = true,
bool includeUpper = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.between(
property: r'cacheKey',
lower: lower,
includeLower: includeLower,
upper: upper,
includeUpper: includeUpper,
),
);
});
}
}
extension GenericCacheModelQueryObject
on QueryBuilder<GenericCacheModel, GenericCacheModel, QFilterCondition> {}
extension GenericCacheModelQueryLinks
on QueryBuilder<GenericCacheModel, GenericCacheModel, QFilterCondition> {}
extension GenericCacheModelQuerySortBy
on QueryBuilder<GenericCacheModel, GenericCacheModel, QSortBy> {
QueryBuilder<GenericCacheModel, GenericCacheModel, QAfterSortBy>
sortByCacheData() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'cacheData', Sort.asc);
});
}
QueryBuilder<GenericCacheModel, GenericCacheModel, QAfterSortBy>
sortByCacheDataDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'cacheData', Sort.desc);
});
}
}
extension GenericCacheModelQuerySortThenBy
on QueryBuilder<GenericCacheModel, GenericCacheModel, QSortThenBy> {
QueryBuilder<GenericCacheModel, GenericCacheModel, QAfterSortBy>
thenByCacheData() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'cacheData', Sort.asc);
});
}
QueryBuilder<GenericCacheModel, GenericCacheModel, QAfterSortBy>
thenByCacheDataDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'cacheData', Sort.desc);
});
}
QueryBuilder<GenericCacheModel, GenericCacheModel, QAfterSortBy>
thenByCacheKey() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'cacheKey', Sort.asc);
});
}
QueryBuilder<GenericCacheModel, GenericCacheModel, QAfterSortBy>
thenByCacheKeyDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'cacheKey', Sort.desc);
});
}
}
extension GenericCacheModelQueryWhereDistinct
on QueryBuilder<GenericCacheModel, GenericCacheModel, QDistinct> {
QueryBuilder<GenericCacheModel, GenericCacheModel, QDistinct>
distinctByCacheData({bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addDistinctBy(r'cacheData', caseSensitive: caseSensitive);
});
}
}
extension GenericCacheModelQueryProperty
on QueryBuilder<GenericCacheModel, GenericCacheModel, QQueryProperty> {
QueryBuilder<GenericCacheModel, int, QQueryOperations> cacheKeyProperty() {
return QueryBuilder.apply(this, (query) {
return query.addPropertyName(r'cacheKey');
});
}
QueryBuilder<GenericCacheModel, String?, QQueryOperations>
cacheDataProperty() {
return QueryBuilder.apply(this, (query) {
return query.addPropertyName(r'cacheData');
});
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,552 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'timetable_cache_model.dart';
// **************************************************************************
// IsarCollectionGenerator
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
extension GetTimetableCacheModelCollection on Isar {
IsarCollection<TimetableCacheModel> get timetableCacheModels =>
this.collection();
}
const TimetableCacheModelSchema = CollectionSchema(
name: r'TimetableCacheModel',
id: -8626340955125680275,
properties: {
r'values': PropertySchema(
id: 0,
name: r'values',
type: IsarType.stringList,
),
},
estimateSize: _timetableCacheModelEstimateSize,
serialize: _timetableCacheModelSerialize,
deserialize: _timetableCacheModelDeserialize,
deserializeProp: _timetableCacheModelDeserializeProp,
idName: r'cacheKey',
indexes: {},
links: {},
embeddedSchemas: {},
getId: _timetableCacheModelGetId,
getLinks: _timetableCacheModelGetLinks,
attach: _timetableCacheModelAttach,
version: '3.3.0',
);
int _timetableCacheModelEstimateSize(
TimetableCacheModel object,
List<int> offsets,
Map<Type, List<int>> allOffsets,
) {
var bytesCount = offsets.last;
{
final list = object.values;
if (list != null) {
bytesCount += 3 + list.length * 3;
{
for (var i = 0; i < list.length; i++) {
final value = list[i];
bytesCount += value.length * 3;
}
}
}
}
return bytesCount;
}
void _timetableCacheModelSerialize(
TimetableCacheModel object,
IsarWriter writer,
List<int> offsets,
Map<Type, List<int>> allOffsets,
) {
writer.writeStringList(offsets[0], object.values);
}
TimetableCacheModel _timetableCacheModelDeserialize(
Id id,
IsarReader reader,
List<int> offsets,
Map<Type, List<int>> allOffsets,
) {
final object = TimetableCacheModel();
object.cacheKey = id;
object.values = reader.readStringList(offsets[0]);
return object;
}
P _timetableCacheModelDeserializeProp<P>(
IsarReader reader,
int propertyId,
int offset,
Map<Type, List<int>> allOffsets,
) {
switch (propertyId) {
case 0:
return (reader.readStringList(offset)) as P;
default:
throw IsarError('Unknown property with id $propertyId');
}
}
Id _timetableCacheModelGetId(TimetableCacheModel object) {
return object.cacheKey ?? Isar.autoIncrement;
}
List<IsarLinkBase<dynamic>> _timetableCacheModelGetLinks(
TimetableCacheModel object,
) {
return [];
}
void _timetableCacheModelAttach(
IsarCollection<dynamic> col,
Id id,
TimetableCacheModel object,
) {
object.cacheKey = id;
}
extension TimetableCacheModelQueryWhereSort
on QueryBuilder<TimetableCacheModel, TimetableCacheModel, QWhere> {
QueryBuilder<TimetableCacheModel, TimetableCacheModel, QAfterWhere>
anyCacheKey() {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(const IdWhereClause.any());
});
}
}
extension TimetableCacheModelQueryWhere
on QueryBuilder<TimetableCacheModel, TimetableCacheModel, QWhereClause> {
QueryBuilder<TimetableCacheModel, TimetableCacheModel, QAfterWhereClause>
cacheKeyEqualTo(Id cacheKey) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(
IdWhereClause.between(lower: cacheKey, upper: cacheKey),
);
});
}
QueryBuilder<TimetableCacheModel, TimetableCacheModel, QAfterWhereClause>
cacheKeyNotEqualTo(Id cacheKey) {
return QueryBuilder.apply(this, (query) {
if (query.whereSort == Sort.asc) {
return query
.addWhereClause(
IdWhereClause.lessThan(upper: cacheKey, includeUpper: false),
)
.addWhereClause(
IdWhereClause.greaterThan(lower: cacheKey, includeLower: false),
);
} else {
return query
.addWhereClause(
IdWhereClause.greaterThan(lower: cacheKey, includeLower: false),
)
.addWhereClause(
IdWhereClause.lessThan(upper: cacheKey, includeUpper: false),
);
}
});
}
QueryBuilder<TimetableCacheModel, TimetableCacheModel, QAfterWhereClause>
cacheKeyGreaterThan(Id cacheKey, {bool include = false}) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(
IdWhereClause.greaterThan(lower: cacheKey, includeLower: include),
);
});
}
QueryBuilder<TimetableCacheModel, TimetableCacheModel, QAfterWhereClause>
cacheKeyLessThan(Id cacheKey, {bool include = false}) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(
IdWhereClause.lessThan(upper: cacheKey, includeUpper: include),
);
});
}
QueryBuilder<TimetableCacheModel, TimetableCacheModel, QAfterWhereClause>
cacheKeyBetween(
Id lowerCacheKey,
Id upperCacheKey, {
bool includeLower = true,
bool includeUpper = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(
IdWhereClause.between(
lower: lowerCacheKey,
includeLower: includeLower,
upper: upperCacheKey,
includeUpper: includeUpper,
),
);
});
}
}
extension TimetableCacheModelQueryFilter
on
QueryBuilder<
TimetableCacheModel,
TimetableCacheModel,
QFilterCondition
> {
QueryBuilder<TimetableCacheModel, TimetableCacheModel, QAfterFilterCondition>
cacheKeyIsNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
const FilterCondition.isNull(property: r'cacheKey'),
);
});
}
QueryBuilder<TimetableCacheModel, TimetableCacheModel, QAfterFilterCondition>
cacheKeyIsNotNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
const FilterCondition.isNotNull(property: r'cacheKey'),
);
});
}
QueryBuilder<TimetableCacheModel, TimetableCacheModel, QAfterFilterCondition>
cacheKeyEqualTo(Id? value) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.equalTo(property: r'cacheKey', value: value),
);
});
}
QueryBuilder<TimetableCacheModel, TimetableCacheModel, QAfterFilterCondition>
cacheKeyGreaterThan(Id? value, {bool include = false}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.greaterThan(
include: include,
property: r'cacheKey',
value: value,
),
);
});
}
QueryBuilder<TimetableCacheModel, TimetableCacheModel, QAfterFilterCondition>
cacheKeyLessThan(Id? value, {bool include = false}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.lessThan(
include: include,
property: r'cacheKey',
value: value,
),
);
});
}
QueryBuilder<TimetableCacheModel, TimetableCacheModel, QAfterFilterCondition>
cacheKeyBetween(
Id? lower,
Id? upper, {
bool includeLower = true,
bool includeUpper = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.between(
property: r'cacheKey',
lower: lower,
includeLower: includeLower,
upper: upper,
includeUpper: includeUpper,
),
);
});
}
QueryBuilder<TimetableCacheModel, TimetableCacheModel, QAfterFilterCondition>
valuesIsNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
const FilterCondition.isNull(property: r'values'),
);
});
}
QueryBuilder<TimetableCacheModel, TimetableCacheModel, QAfterFilterCondition>
valuesIsNotNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
const FilterCondition.isNotNull(property: r'values'),
);
});
}
QueryBuilder<TimetableCacheModel, TimetableCacheModel, QAfterFilterCondition>
valuesElementEqualTo(String value, {bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.equalTo(
property: r'values',
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<TimetableCacheModel, TimetableCacheModel, QAfterFilterCondition>
valuesElementGreaterThan(
String value, {
bool include = false,
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.greaterThan(
include: include,
property: r'values',
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<TimetableCacheModel, TimetableCacheModel, QAfterFilterCondition>
valuesElementLessThan(
String value, {
bool include = false,
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.lessThan(
include: include,
property: r'values',
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<TimetableCacheModel, TimetableCacheModel, QAfterFilterCondition>
valuesElementBetween(
String lower,
String upper, {
bool includeLower = true,
bool includeUpper = true,
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.between(
property: r'values',
lower: lower,
includeLower: includeLower,
upper: upper,
includeUpper: includeUpper,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<TimetableCacheModel, TimetableCacheModel, QAfterFilterCondition>
valuesElementStartsWith(String value, {bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.startsWith(
property: r'values',
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<TimetableCacheModel, TimetableCacheModel, QAfterFilterCondition>
valuesElementEndsWith(String value, {bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.endsWith(
property: r'values',
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<TimetableCacheModel, TimetableCacheModel, QAfterFilterCondition>
valuesElementContains(String value, {bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.contains(
property: r'values',
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<TimetableCacheModel, TimetableCacheModel, QAfterFilterCondition>
valuesElementMatches(String pattern, {bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.matches(
property: r'values',
wildcard: pattern,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<TimetableCacheModel, TimetableCacheModel, QAfterFilterCondition>
valuesElementIsEmpty() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.equalTo(property: r'values', value: ''),
);
});
}
QueryBuilder<TimetableCacheModel, TimetableCacheModel, QAfterFilterCondition>
valuesElementIsNotEmpty() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.greaterThan(property: r'values', value: ''),
);
});
}
QueryBuilder<TimetableCacheModel, TimetableCacheModel, QAfterFilterCondition>
valuesLengthEqualTo(int length) {
return QueryBuilder.apply(this, (query) {
return query.listLength(r'values', length, true, length, true);
});
}
QueryBuilder<TimetableCacheModel, TimetableCacheModel, QAfterFilterCondition>
valuesIsEmpty() {
return QueryBuilder.apply(this, (query) {
return query.listLength(r'values', 0, true, 0, true);
});
}
QueryBuilder<TimetableCacheModel, TimetableCacheModel, QAfterFilterCondition>
valuesIsNotEmpty() {
return QueryBuilder.apply(this, (query) {
return query.listLength(r'values', 0, false, 999999, true);
});
}
QueryBuilder<TimetableCacheModel, TimetableCacheModel, QAfterFilterCondition>
valuesLengthLessThan(int length, {bool include = false}) {
return QueryBuilder.apply(this, (query) {
return query.listLength(r'values', 0, true, length, include);
});
}
QueryBuilder<TimetableCacheModel, TimetableCacheModel, QAfterFilterCondition>
valuesLengthGreaterThan(int length, {bool include = false}) {
return QueryBuilder.apply(this, (query) {
return query.listLength(r'values', length, include, 999999, true);
});
}
QueryBuilder<TimetableCacheModel, TimetableCacheModel, QAfterFilterCondition>
valuesLengthBetween(
int lower,
int upper, {
bool includeLower = true,
bool includeUpper = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.listLength(
r'values',
lower,
includeLower,
upper,
includeUpper,
);
});
}
}
extension TimetableCacheModelQueryObject
on
QueryBuilder<
TimetableCacheModel,
TimetableCacheModel,
QFilterCondition
> {}
extension TimetableCacheModelQueryLinks
on
QueryBuilder<
TimetableCacheModel,
TimetableCacheModel,
QFilterCondition
> {}
extension TimetableCacheModelQuerySortBy
on QueryBuilder<TimetableCacheModel, TimetableCacheModel, QSortBy> {}
extension TimetableCacheModelQuerySortThenBy
on QueryBuilder<TimetableCacheModel, TimetableCacheModel, QSortThenBy> {
QueryBuilder<TimetableCacheModel, TimetableCacheModel, QAfterSortBy>
thenByCacheKey() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'cacheKey', Sort.asc);
});
}
QueryBuilder<TimetableCacheModel, TimetableCacheModel, QAfterSortBy>
thenByCacheKeyDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'cacheKey', Sort.desc);
});
}
}
extension TimetableCacheModelQueryWhereDistinct
on QueryBuilder<TimetableCacheModel, TimetableCacheModel, QDistinct> {
QueryBuilder<TimetableCacheModel, TimetableCacheModel, QDistinct>
distinctByValues() {
return QueryBuilder.apply(this, (query) {
return query.addDistinctBy(r'values');
});
}
}
extension TimetableCacheModelQueryProperty
on QueryBuilder<TimetableCacheModel, TimetableCacheModel, QQueryProperty> {
QueryBuilder<TimetableCacheModel, int, QQueryOperations> cacheKeyProperty() {
return QueryBuilder.apply(this, (query) {
return query.addPropertyName(r'cacheKey');
});
}
QueryBuilder<TimetableCacheModel, List<String>?, QQueryOperations>
valuesProperty() {
return QueryBuilder.apply(this, (query) {
return query.addPropertyName(r'values');
});
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,359 +1,12 @@
import 'dart:async';
import 'dart:io';
import 'dart:ui' as ui;
import 'package:dio/dio.dart';
import 'package:firka/helpers/api/client/kreta_client.dart';
import 'package:firka/helpers/db/models/app_settings_model.dart';
import 'package:firka/helpers/db/models/generic_cache_model.dart';
import 'package:firka/helpers/db/models/timetable_cache_model.dart';
import 'package:firka/helpers/db/models/token_model.dart';
import 'package:firka/helpers/firka_bundle.dart';
import 'package:firka/helpers/settings.dart';
import 'package:firka/helpers/swear_generator.dart';
import 'package:firka/l10n/app_localizations_hu.dart';
import 'package:firka/ui/model/style.dart';
import 'package:firka/ui/phone/pages/error/error_page.dart';
import 'package:firka/ui/phone/screens/debug/debug_screen.dart';
import 'package:firka/ui/phone/screens/home/home_screen.dart';
import 'package:firka/ui/phone/screens/login/login_screen.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/services.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_native_splash/flutter_native_splash.dart';
import 'package:intl/intl.dart';
import 'package:isar_community/isar.dart';
import 'package:logging/logging.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';
import 'package:flutter_native_splash/flutter_native_splash.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'helpers/db/models/homework_cache_model.dart';
import 'helpers/update_notifier.dart';
import 'helpers/live_activity_service.dart';
import 'helpers/active_account_helper.dart';
import 'helpers/watch_sync_helper.dart';
import 'l10n/app_localizations.dart';
import 'l10n/app_localizations_de.dart';
import 'l10n/app_localizations_en.dart';
late final Logger logger;
Isar? isarInit;
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
late AppInitialization initData;
bool initDone = false;
final dio = Dio();
final isBeta = true;
class DeviceInfo {
String model;
String versionRelease;
String versionSdkInt;
DeviceInfo(this.model, this.versionRelease, this.versionSdkInt);
@override
String toString() {
return "DeviceInfo(model = \"$model\", versionRelease = \"$versionRelease\""
", versionSdkInt = \"$versionSdkInt\"";
}
}
class AppInitialization {
final Isar isar;
final Directory appDir;
final PackageInfo packageInfo;
final DeviceInfo devInfo;
late KretaClient client;
List<TokenModel> tokens;
bool hasWatchListener = false;
Uint8List? profilePicture;
SettingsStore settings;
UpdateNotifier settingsUpdateNotifier = UpdateNotifier();
UpdateNotifier profilePictureUpdateNotifier = UpdateNotifier();
AppLocalizations l10n;
final GlobalKey<NavigatorState> navigatorKey;
AppInitialization({
required this.isar,
required this.appDir,
required this.devInfo,
required this.packageInfo,
required this.tokens,
required this.settings,
required this.l10n,
required this.navigatorKey,
});
}
Future<Isar> initDB() async {
if (isarInit != null) return isarInit!;
final dir = await getApplicationDocumentsDirectory();
isarInit = await Isar.open(
[
TokenModelSchema,
GenericCacheModelSchema,
TimetableCacheModelSchema,
HomeworkCacheModelSchema,
AppSettingsModelSchema,
HomeworkDoneModelSchema,
],
inspector: true,
directory: dir.path,
);
return isarInit!;
}
Future<void> initLang(AppInitialization data) async {
String? languageCode;
switch ((data.settings.group("settings").subGroup("application")["language"]
as SettingsItemsRadio)
.activeIndex) {
case 1: // hu
data.l10n = AppLocalizationsHu();
languageCode = 'hu';
break;
case 2: // en
data.l10n = AppLocalizationsEn();
languageCode = 'en';
break;
case 3: // de
data.l10n = AppLocalizationsDe();
languageCode = 'de';
break;
default: // auto
switch (ui.PlatformDispatcher.instance.locale.languageCode) {
case 'hu':
data.l10n = AppLocalizationsHu();
languageCode = 'hu';
break;
case 'en':
data.l10n = AppLocalizationsEn();
languageCode = 'en';
break;
case 'de':
data.l10n = AppLocalizationsDe();
languageCode = 'de';
break;
}
break;
}
if (languageCode != null && Platform.isIOS) {
try {
await LiveActivityService.updateLanguagePreference(languageCode);
} catch (e) {
logger.warning('Failed to update language preference on backend: $e');
}
try {
await WatchSyncHelper.sendLanguageToWatch();
} catch (e) {
logger.warning('Failed to send language to Watch: $e');
}
}
}
void initTheme(AppInitialization data) {
final brightness =
SchedulerBinding.instance.platformDispatcher.platformBrightness;
switch ((data.settings.group("settings").subGroup("customization")["theme"]
as SettingsItemsRadio)
.activeIndex) {
case 1:
appStyle = lightStyle;
isLightMode.value = true;
break;
case 2:
appStyle = darkStyle;
isLightMode.value = false;
break;
default:
if (brightness == Brightness.dark) {
appStyle = darkStyle;
isLightMode.value = false;
} else {
appStyle = lightStyle;
isLightMode.value = true;
}
}
}
Future<void> _initData(AppInitialization init) async {
await init.settings.load(init.isar.appSettingsModels);
await initLang(init);
initTheme(init);
init.settings = SettingsStore(init.l10n);
await init.settings.load(init.isar.appSettingsModels);
var dispatcher = SchedulerBinding.instance.platformDispatcher;
dispatcher.onPlatformBrightnessChanged = () {
globalUpdate.update();
initTheme(init);
};
dispatcher.onLocaleChanged = () {
final languageSetting =
init.settings.group("settings").subGroup("application")["language"]
as SettingsItemsRadio;
final isAutoLanguage = languageSetting.activeIndex == 0;
if (!isAutoLanguage) {
return;
}
final previousLocale = init.l10n.localeName;
unawaited(() async {
await initLang(init);
final nextLocale = init.l10n.localeName;
if (previousLocale != nextLocale) {
logger.info(
"[Init] System locale changed in auto mode: $previousLocale -> $nextLocale",
);
}
globalUpdate.update();
}());
};
resetOldTimeTableCache(init.isar);
resetOldHomeworkCache(init.isar);
var didRunFreshInstallCleanup = false;
if (Platform.isIOS) {
try {
didRunFreshInstallCleanup =
await WatchSyncHelper.runFreshInstallCleanupIfNeeded(isar: init.isar);
if (didRunFreshInstallCleanup) {
logger.info(
'[Init] Fresh-install cleanup completed; skipping startup iCloud recovery on this launch',
);
} else {
await WatchSyncHelper.checkAndRecoverFromiCloud(
isar: init.isar,
tokens: init.tokens,
);
}
} catch (e) {
logger.warning('[Init] iCloud bootstrap/recovery failed: $e');
}
}
final allTokens = await init.isar.tokenModels.where().findAll();
init.tokens = allTokens;
if (allTokens.isNotEmpty) {
final token = pickActiveToken(tokens: allTokens, settings: init.settings);
if (token == null) {
logger.warning(
"[Init] Tokens disappeared during initialization; skipping client setup",
);
return;
}
logger.fine("Initializing kréta client as: ${token.studentId}");
init.client = KretaClient(token, init.isar);
if (Platform.isIOS) {
final expiryDate = token.expiryDate;
if (expiryDate != null && expiryDate.isAfter(DateTime.now())) {
KretaClient.clearReauthFlag();
}
unawaited(() async {
try {
await WatchSyncHelper.saveTokenToiCloud(token);
} catch (e) {
logger.warning('[Init] Failed to sync active token to iCloud: $e');
}
try {
await WatchSyncHelper.sendTokenModelToWatch(token);
} catch (e) {
logger.warning('[Init] Failed to sync active token to Watch: $e');
}
}());
}
}
final dataDir = await getApplicationDocumentsDirectory();
var pfpFile = File(p.join(dataDir.path, "profile.webp"));
if (await pfpFile.exists()) {
init.profilePicture = await pfpFile.readAsBytes();
}
}
Future<AppInitialization> initializeApp() async {
if (initDone) {
await _initData(initData);
return initData;
}
final isar = await initDB();
final tokens = await isar.tokenModels.where().findAll();
logger.finest('Token count: ${tokens.length}');
var devInfoFetched = false;
var devInfo = DeviceInfo("SM-A705FN", "11", "30");
try {
if (Platform.isAndroid) {
const channel = MethodChannel("firka.app/main");
final rawInfo = ((await channel.invokeMethod("get_info")) as String)
.split(";");
devInfo = DeviceInfo(rawInfo[0], rawInfo[1], rawInfo[2]);
devInfoFetched = true;
}
} catch (e) {
if (e is Error) {
logger.shout("Error in initializeApp()", e.toString(), e.stackTrace);
} else {
logger.shout("Error in initializeApp()", e.toString());
}
}
logger.fine("Fetched device info: ${devInfoFetched ? "yes" : "no"}");
logger.fine("Using device info: ${devInfo.toString()}");
var init = AppInitialization(
isar: isar,
appDir: await getApplicationDocumentsDirectory(),
devInfo: devInfo,
packageInfo: await PackageInfo.fromPlatform(),
tokens: tokens,
settings: SettingsStore(AppLocalizationsHu()),
l10n: AppLocalizationsHu(),
navigatorKey: navigatorKey,
);
if (Platform.isIOS) {
try {
await LiveActivityService.initialize().timeout(
const Duration(seconds: 8),
);
} on TimeoutException catch (e, st) {
logger.warning('LiveActivity init timed out: $e', e, st);
} catch (e, st) {
logger.severe('Failed to initialize LiveActivity: $e', e, st);
}
}
await _initData(init);
init.settingsUpdateNotifier.addListener(() {
logger.finest("Settings updated");
});
return init;
}
import 'package:firka/app/app_state.dart';
import 'package:firka/app/initialization.dart';
import 'package:firka/app/initialization_screen.dart';
import 'package:firka/ui/phone/pages/error/error_page.dart';
void main() async {
logger = Logger("Firka");
@@ -374,113 +27,8 @@ void main() async {
logger.severe("Failed to load .env: $e", e, st);
}
{
final jwtPattern = RegExp(
r'([A-Za-z0-9-_]+)\.([A-Za-z0-9-_]+)\.([A-Za-z0-9-_]+)',
);
final omPattern = RegExp(r'(\d{3})(\d{6})([A-Za-z0-9]?)');
final refreshTokenPattern = RegExp(
r'"(?=.{21,}$)([A-Z0-9]+-[A-Z0-9_\-.~+]*)"',
);
await setupLogging();
final docs = await getApplicationDocumentsDirectory();
Future<void> deleteOldLogFiles() async {
final docs = await getApplicationDocumentsDirectory();
final dir = Directory(docs.path);
if (!dir.existsSync()) return;
final now = DateTime.now();
final cutoff = now.subtract(Duration(days: 30));
final logFileRegex = RegExp(r'^(\d{4})_(\d{2})_(\d{2})\.log$');
for (final entity in dir.listSync()) {
if (entity is! File) continue;
final name = entity.uri.pathSegments.last;
final m = logFileRegex.firstMatch(name);
if (m == null) continue;
try {
final y = int.parse(m.group(1)!);
final mo = int.parse(m.group(2)!);
final d = int.parse(m.group(3)!);
final fileDate = DateTime(y, mo, d);
if (fileDate.isBefore(
DateTime(cutoff.year, cutoff.month, cutoff.day),
)) {
logger.info("Removing old log file: $name");
await entity.delete();
}
} catch (_) {
// ignore parse/delete errors
}
}
}
String logFilePathForDate(DateTime dt) {
final fileName = "${DateFormat("yyyy_MM_dd").format(dt)}.log";
return Directory(docs.path).uri.resolve(fileName).toFilePath();
}
File fileForDate(DateTime dt) {
final path = logFilePathForDate(dt);
final file = File(path);
if (!file.existsSync()) file.createSync(recursive: true);
return file;
}
String censorLog(String msg) {
return msg
.replaceAll(jwtPattern, '***')
.replaceAllMapped(omPattern, (match) {
return "${match.group(1)}******${match.group(3)}";
})
.replaceAll(refreshTokenPattern, '"***"');
}
hierarchicalLoggingEnabled = true;
logger.level = Level.ALL;
DateTime currentDate = DateTime.now();
IOSink sink = fileForDate(currentDate).openWrite(mode: FileMode.append);
logger.onRecord.listen((record) {
final now = DateTime.now();
if (now.year != currentDate.year ||
now.month != currentDate.month ||
now.day != currentDate.day) {
sink.flush();
sink.close();
currentDate = now;
sink = fileForDate(currentDate).openWrite(mode: FileMode.append);
}
final censored = censorLog(record.message);
final timestamp = DateFormat('yyyy-MM-dd HH:mm:ss.SSS').format(now);
final level = record.level.name;
final line = '[$timestamp] [$level] [$censored]';
sink.writeln(line);
debugPrint(
"[Firka] [${record.level.name}] ${kDebugMode ? record.message : censored}",
);
});
(() async {
await deleteOldLogFiles();
})();
}
try {
logger.finest('loading dirty words');
await loadDirtyWords();
logger.finest('loaded dirty words');
} catch (e, st) {
logger.severe('Failed to load dirty words: $e', e, st);
}
// Run App Initialization
runApp(InitializationScreen());
},
(error, stackTrace) {
@@ -498,174 +46,3 @@ void main() async {
},
);
}
final ValueNotifier<bool> isLightMode = ValueNotifier<bool>(true);
final UpdateNotifier globalUpdate = UpdateNotifier();
class InitializationScreen extends StatelessWidget {
InitializationScreen({super.key});
final Future<AppInitialization> _init = initializeApp().timeout(
const Duration(seconds: 20),
);
@override
Widget build(BuildContext context) {
return FutureBuilder<AppInitialization>(
future: _init,
builder: (context, snapshot) {
// Check if initialization is complete
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasError) {
logger.shout(
"Error in InitializationScreen",
snapshot.error.toString(),
snapshot.stackTrace,
);
FlutterNativeSplash.remove();
// Handle initialization error
return MaterialApp(
key: ValueKey('errorPage'),
home: DefaultAssetBundle(
bundle: FirkaBundle(),
child: Scaffold(
body: Center(
child: Text(
'Error initializing app: ${snapshot.error}',
style: TextStyle(color: Colors.red),
),
),
),
),
);
}
// Initialization successful, determine which screen to show
Widget screen;
assert(snapshot.data != null);
initData = snapshot.data!;
initDone = true;
FlutterNativeSplash.remove();
WatchSyncHelper.initialize();
if (Platform.isIOS) {
unawaited(() async {
try {
await WatchSyncHelper.sendLanguageToWatch();
} catch (e) {
logger.warning(
'[Init] Failed to publish language to Watch after sync init: $e',
);
}
}());
}
if (!initData.hasWatchListener) {
initData.hasWatchListener = true;
WatchSyncHelper.onWatchMessage = (msg) {
logger.finest("WatchOS IPC [Watch -> Phone]: ${msg["id"]}");
switch (msg["id"]) {
case "ping":
if (initData.tokens.isNotEmpty) {
logger.finest("WatchOS IPC [Phone -> Watch]: pong");
const watchChannel = MethodChannel('app.firka/watch_sync');
watchChannel.invokeMethod('sendMessageToWatch', {
"id": "pong",
});
navigatorKey.currentState?.push(
MaterialPageRoute(
builder: (context) => HomeScreen(
initData,
true,
model: msg["model"] as String? ?? "unknown",
),
),
);
}
}
};
}
if (snapshot.data!.tokens.isEmpty) {
screen = LoginScreen(initData, key: ValueKey('loginScreen'));
} else {
screen = HomeScreen(initData, false, key: ValueKey('homeScreen'));
}
return MaterialApp(
title: 'Firka',
key: ValueKey('firkaApp'),
navigatorKey: navigatorKey,
// Use the global navigator key
theme: ThemeData(
primarySwatch: Colors.lightGreen,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
localizationsDelegates: [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: AppLocalizations.supportedLocales,
home: DefaultAssetBundle(
bundle: FirkaBundle(),
child: ValueListenableBuilder<bool>(
valueListenable: isLightMode,
builder: (context, isLight, _) {
final overlay = SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
statusBarIconBrightness: isLight
? Brightness.dark
: Brightness.light,
statusBarBrightness: isLight
? Brightness.light
: Brightness.dark,
systemStatusBarContrastEnforced: false,
);
// Ensure system is updated immediately
SystemChrome.setSystemUIOverlayStyle(overlay);
return AnnotatedRegion<SystemUiOverlayStyle>(
value: overlay,
child: screen,
);
},
),
),
routes: {
'/login': (context) => DefaultAssetBundle(
bundle: FirkaBundle(),
child: LoginScreen(initData, key: ValueKey('loginScreen')),
),
'/home': (context) => DefaultAssetBundle(
bundle: FirkaBundle(),
child: HomeScreen(initData, false, key: ValueKey('homeScreen')),
),
'/debug': (context) => DefaultAssetBundle(
bundle: FirkaBundle(),
child: DebugScreen(initData, key: ValueKey('debugScreen')),
),
},
);
}
return MaterialApp(
home: DefaultAssetBundle(
bundle: FirkaBundle(),
child: Scaffold(
backgroundColor: const Color(0xFF7CA120),
body: Container(), // Covered by native splash
),
),
);
},
);
}
}

View File

@@ -1,4 +1,4 @@
import 'db/models/token_model.dart';
import 'package:firka/data/models/token_model.dart';
int resolveActiveAccountIndex(dynamic settings) {
try {

View File

@@ -1,7 +1,7 @@
import 'dart:convert';
import 'dart:io';
import 'package:flutter/services.dart';
import 'package:firka/helpers/api/model/timetable.dart';
import 'package:firka/api/model/timetable.dart';
import 'package:logging/logging.dart';
class LiveActivityManager {

View File

@@ -1,21 +1,21 @@
import 'dart:async';
import 'dart:io';
import 'package:firka/helpers/api/client/kreta_client.dart';
import 'package:firka/helpers/api/client/live_activity_backend_client.dart';
import 'package:firka/helpers/api/model/generic.dart';
import 'package:firka/helpers/api/model/timetable.dart';
import 'package:firka/helpers/db/models/app_settings_model.dart';
import 'package:firka/helpers/db/widget.dart';
import 'package:firka/helpers/live_activity_manager.dart';
import 'package:firka/helpers/active_account_helper.dart';
import 'package:firka/helpers/settings.dart';
import 'package:firka/api/client/kreta_client.dart';
import 'package:firka/api/client/live_activity_backend_client.dart';
import 'package:firka/api/model/generic.dart';
import 'package:firka/api/model/timetable.dart';
import 'package:firka/data/models/app_settings_model.dart';
import 'package:firka/data/widget.dart';
import 'package:firka/services/live_activity_manager.dart';
import 'package:firka/services/active_account_helper.dart';
import 'package:firka/core/settings.dart';
import 'package:firka/ui/phone/screens/live_activity/live_activity_consent_screen.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:logging/logging.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../main.dart';
import 'package:firka/app/app_state.dart';
/// Service that coordinates LiveActivity functionality
/// Handles timetable synchronization, device token management, and activity updates

View File

@@ -7,10 +7,10 @@ import 'package:flutter/services.dart';
import 'package:isar_community/isar.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../main.dart';
import 'active_account_helper.dart';
import 'api/client/kreta_client.dart';
import 'db/models/token_model.dart';
import 'package:firka/app/app_state.dart';
import 'package:firka/services/active_account_helper.dart';
import 'package:firka/api/client/kreta_client.dart';
import 'package:firka/data/models/token_model.dart';
/// Helper class for Watch iPhone token sync
class WatchSyncHelper {

View File

@@ -1,28 +1,28 @@
import 'package:firka/helpers/api/model/generic.dart';
import 'package:firka/helpers/api/model/grade.dart';
import 'package:firka/helpers/api/model/homework.dart';
import 'package:firka/helpers/api/model/subject.dart';
import 'package:firka/helpers/db/models/homework_cache_model.dart';
import 'package:firka/helpers/debug_helper.dart';
import 'package:firka/helpers/extensions.dart';
import 'package:firka/helpers/settings.dart';
import 'package:firka/helpers/ui/firka_shadow.dart';
import 'package:firka/ui/widget/firka_icon.dart';
import 'package:firka/api/model/generic.dart';
import 'package:firka/api/model/grade.dart';
import 'package:firka/api/model/homework.dart';
import 'package:firka/api/model/subject.dart';
import 'package:firka/data/models/homework_cache_model.dart';
import 'package:firka/core/debug_helper.dart';
import 'package:firka/core/extensions.dart';
import 'package:firka/core/settings.dart';
import 'package:firka/ui/components/firka_shadow.dart';
import 'package:firka/ui/shared/firka_icon.dart';
import 'package:flutter/material.dart';
import 'package:flutter_html/flutter_html.dart';
import 'package:flutter_svg/svg.dart';
import 'package:majesticons_flutter/majesticons_flutter.dart';
import 'package:intl/intl.dart';
import '../../main.dart';
import '../../ui/model/style.dart';
import '../../ui/phone/screens/home/home_screen.dart';
import '../../ui/phone/widgets/lesson.dart';
import '../../ui/widget/class_icon.dart';
import '../api/model/timetable.dart';
import 'firka_card.dart';
import 'grade.dart';
import '../../helpers/api/model/test.dart';
import 'package:firka/app/app_state.dart';
import 'package:firka/ui/theme/style.dart';
import 'package:firka/ui/phone/screens/home/home_screen.dart';
import 'package:firka/ui/phone/widgets/lesson.dart';
import 'package:firka/ui/shared/class_icon.dart';
import 'package:firka/api/model/timetable.dart';
import 'package:firka/ui/components/firka_card.dart';
import 'package:firka/ui/components/grade.dart';
import 'package:firka/api/model/test.dart';
Future<void> showLessonBottomSheet(
BuildContext context,

View File

@@ -1,8 +1,8 @@
import 'package:firka/helpers/ui/firka_shadow.dart';
import 'package:firka/ui/components/firka_shadow.dart';
import 'package:flutter/material.dart';
import '../../main.dart';
import '../../ui/model/style.dart';
import 'package:firka/app/app_state.dart';
import 'package:firka/ui/theme/style.dart';
enum Attach { none, bottom, top }

View File

@@ -1,7 +1,7 @@
import 'package:firka/main.dart';
import 'package:firka/app/app_state.dart';
import 'package:flutter/material.dart';
import '../../ui/model/style.dart';
import 'package:firka/ui/theme/style.dart';
class FirkaShadow extends StatelessWidget {
final Widget child;

View File

@@ -1,8 +1,8 @@
import 'package:firka/helpers/api/model/grade.dart';
import 'package:firka/api/model/grade.dart';
import 'package:flutter/material.dart';
import '../../ui/model/style.dart';
import 'grade_helpers.dart';
import 'package:firka/ui/theme/style.dart';
import 'package:firka/ui/components/grade_helpers.dart';
class GradeWidget extends StatelessWidget {
final Grade grade;

View File

@@ -1,11 +1,11 @@
import 'dart:ui';
import 'package:firka/helpers/settings.dart';
import 'package:firka/main.dart';
import 'package:firka/core/settings.dart';
import 'package:firka/app/app_state.dart';
import '../../ui/model/style.dart';
import '../api/model/grade.dart';
import '../api/model/subject.dart';
import 'package:firka/ui/theme/style.dart';
import 'package:firka/api/model/grade.dart';
import 'package:firka/api/model/subject.dart';
int roundGrade(double grade) {
final rounding = initData.settings

View File

@@ -1,8 +1,8 @@
import 'package:firka/ui/model/style.dart';
import 'package:firka/ui/theme/style.dart';
import 'package:flutter/material.dart';
import 'package:firka/helpers/image_preloader.dart';
import 'package:firka/helpers/firka_bundle.dart';
import 'package:firka/helpers/swear_generator.dart';
import 'package:firka/core/image_preloader.dart';
import 'package:firka/core/firka_bundle.dart';
import 'package:firka/core/swear_generator.dart';
class ErrorPage extends StatelessWidget {
final String exception;

View File

@@ -1,16 +1,16 @@
import 'package:firka/helpers/db/models/app_settings_model.dart';
import 'package:firka/helpers/settings.dart';
import 'package:firka/helpers/ui/firka_shadow.dart';
import 'package:firka/main.dart';
import 'package:firka/ui/model/style.dart';
import 'package:firka/data/models/app_settings_model.dart';
import 'package:firka/core/settings.dart';
import 'package:firka/ui/components/firka_shadow.dart';
import 'package:firka/app/app_state.dart';
import 'package:firka/ui/theme/style.dart';
import 'package:firka/ui/phone/screens/settings/settings_screen.dart';
import 'package:firka/ui/widget/firka_icon.dart';
import 'package:firka/ui/shared/firka_icon.dart';
import 'package:flutter/material.dart';
import 'package:majesticons_flutter/majesticons_flutter.dart';
import '../../../../helpers/firka_bundle.dart';
import '../../screens/debug/debug_screen.dart';
import '../../screens/home/home_screen.dart';
import 'package:firka/core/firka_bundle.dart';
import 'package:firka/ui/phone/screens/debug/debug_screen.dart';
import 'package:firka/ui/phone/screens/home/home_screen.dart';
void showExtrasBottomSheet(BuildContext context, AppInitialization data) {
Widget Function(double) debugBtn = (_) => const SizedBox();

View File

@@ -1,4 +1,4 @@
import 'package:firka/ui/model/style.dart';
import 'package:firka/ui/theme/style.dart';
import 'package:flutter/material.dart';
void showErrorBottomSheet(BuildContext context, String err) {

View File

@@ -1,6 +1,6 @@
import 'package:firka/helpers/settings.dart';
import 'package:firka/main.dart';
import 'package:firka/ui/model/style.dart';
import 'package:firka/core/settings.dart';
import 'package:firka/app/app_state.dart';
import 'package:firka/ui/theme/style.dart';
import 'package:firka/ui/phone/widgets/login_webview.dart';
import 'package:flutter/material.dart';

View File

@@ -1,11 +1,11 @@
import 'package:firka/helpers/debug_helper.dart';
import 'package:firka/helpers/ui/firka_card.dart';
import 'package:firka/helpers/watch_sync_helper.dart';
import 'package:firka/main.dart';
import 'package:firka/core/debug_helper.dart';
import 'package:firka/ui/components/firka_card.dart';
import 'package:firka/services/watch_sync_helper.dart';
import 'package:firka/app/app_state.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import '../../../model/style.dart';
import 'package:firka/ui/theme/style.dart';
void showWearBottomSheet(
BuildContext context,

View File

@@ -1,7 +1,7 @@
import 'package:firka/main.dart';
import 'package:firka/ui/model/style.dart';
import 'package:firka/app/app_state.dart';
import 'package:firka/ui/theme/style.dart';
import 'package:firka/ui/phone/pages/extras/main_reauth.dart';
import 'package:firka/ui/widget/firka_icon.dart';
import 'package:firka/ui/shared/firka_icon.dart';
import 'package:flutter/material.dart';
import 'package:majesticons_flutter/majesticons_flutter.dart';

View File

@@ -1,23 +1,23 @@
import 'package:firka/helpers/api/client/kreta_client.dart';
import 'package:firka/helpers/api/model/generic.dart';
import 'package:firka/helpers/average_helper.dart';
import 'package:firka/helpers/ui/firka_card.dart';
import 'package:firka/helpers/ui/grade_helpers.dart';
import 'package:firka/api/client/kreta_client.dart';
import 'package:firka/api/model/generic.dart';
import 'package:firka/core/average_helper.dart';
import 'package:firka/ui/components/firka_card.dart';
import 'package:firka/ui/components/grade_helpers.dart';
import 'package:firka/ui/phone/widgets/grade_chart.dart';
import 'package:firka/ui/widget/grade_small_card.dart';
import 'package:firka/ui/shared/grade_small_card.dart';
import 'package:flutter/material.dart';
import '../../../../helpers/api/consts.dart';
import '../../../../helpers/api/model/class_group.dart';
import '../../../../helpers/api/model/grade.dart';
import '../../../../helpers/api/model/subject.dart';
import '../../../../helpers/api/model/timetable.dart';
import '../../../../helpers/debug_helper.dart';
import '../../../../helpers/firka_state.dart';
import '../../../../helpers/update_notifier.dart';
import '../../../../main.dart';
import '../../../model/style.dart';
import '../../../widget/delayed_spinner.dart';
import 'package:firka/api/consts.dart';
import 'package:firka/api/model/class_group.dart';
import 'package:firka/api/model/grade.dart';
import 'package:firka/api/model/subject.dart';
import 'package:firka/api/model/timetable.dart';
import 'package:firka/core/debug_helper.dart';
import 'package:firka/core/state/firka_state.dart';
import 'package:firka/core/state/update_notifier.dart';
import 'package:firka/app/app_state.dart';
import 'package:firka/ui/theme/style.dart';
import 'package:firka/ui/shared/delayed_spinner.dart';
class HomeGradesScreen extends StatefulWidget {
final AppInitialization data;

View File

@@ -1,19 +1,19 @@
import 'package:firka/helpers/api/model/grade.dart';
import 'package:firka/helpers/extensions.dart';
import 'package:firka/helpers/ui/common_bottom_sheets.dart';
import 'package:firka/helpers/ui/firka_card.dart';
import 'package:firka/helpers/ui/grade.dart';
import 'package:firka/api/model/grade.dart';
import 'package:firka/core/extensions.dart';
import 'package:firka/ui/components/common_bottom_sheets.dart';
import 'package:firka/ui/components/firka_card.dart';
import 'package:firka/ui/components/grade.dart';
import 'package:firka/ui/phone/pages/home/home_grades.dart';
import 'package:firka/ui/widget/class_icon.dart';
import 'package:firka/ui/widget/firka_icon.dart';
import 'package:firka/ui/shared/class_icon.dart';
import 'package:firka/ui/shared/firka_icon.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:majesticons_flutter/majesticons_flutter.dart';
import '../../../../helpers/firka_state.dart';
import '../../../../helpers/update_notifier.dart';
import '../../../../main.dart';
import '../../../model/style.dart';
import 'package:firka/core/state/firka_state.dart';
import 'package:firka/core/state/update_notifier.dart';
import 'package:firka/app/app_state.dart';
import 'package:firka/ui/theme/style.dart';
class HomeGradesSubjectScreen extends StatefulWidget {
final AppInitialization data;

View File

@@ -1,31 +1,31 @@
import 'dart:async';
import 'package:firka/helpers/api/client/kreta_stream.dart';
import 'package:firka/helpers/api/model/grade.dart';
import 'package:firka/helpers/extensions.dart';
import 'package:firka/helpers/ui/common_bottom_sheets.dart';
import 'package:firka/api/client/kreta_stream.dart';
import 'package:firka/api/model/grade.dart';
import 'package:firka/core/extensions.dart';
import 'package:firka/ui/components/common_bottom_sheets.dart';
import 'package:firka/ui/phone/screens/message/message_screen.dart';
import 'package:firka/ui/phone/widgets/home_main_starting_soon.dart';
import 'package:firka/ui/phone/widgets/homework.dart';
import 'package:firka/ui/phone/widgets/info_board_item.dart';
import 'package:firka/ui/phone/widgets/lesson_small.dart';
import 'package:firka/ui/widget/delayed_spinner.dart';
import 'package:firka/ui/shared/delayed_spinner.dart';
import 'package:flutter/material.dart';
import 'package:majesticons_flutter/majesticons_flutter.dart';
import '../../../../helpers/api/model/homework.dart';
import '../../../../helpers/api/model/notice_board.dart';
import '../../../../helpers/api/model/student.dart';
import '../../../../helpers/api/model/test.dart';
import '../../../../helpers/api/model/timetable.dart';
import '../../../../helpers/debug_helper.dart';
import '../../../../helpers/firka_state.dart';
import '../../../../helpers/ui/firka_card.dart';
import '../../../../helpers/ui/grade.dart';
import '../../../../helpers/update_notifier.dart';
import '../../../../main.dart';
import '../../../model/style.dart';
import '../../../widget/firka_icon.dart';
import 'package:firka/api/model/homework.dart';
import 'package:firka/api/model/notice_board.dart';
import 'package:firka/api/model/student.dart';
import 'package:firka/api/model/test.dart';
import 'package:firka/api/model/timetable.dart';
import 'package:firka/core/debug_helper.dart';
import 'package:firka/core/state/firka_state.dart';
import 'package:firka/ui/components/firka_card.dart';
import 'package:firka/ui/components/grade.dart';
import 'package:firka/core/state/update_notifier.dart';
import 'package:firka/app/app_state.dart';
import 'package:firka/ui/theme/style.dart';
import 'package:firka/ui/shared/firka_icon.dart';
import '../../widgets/home_main_welcome.dart';
import '../../widgets/lesson_big.dart';

View File

@@ -1,9 +1,9 @@
import 'package:firka/ui/phone/screens/home/home_screen.dart';
import 'package:flutter/material.dart';
import '../../../../helpers/firka_state.dart';
import '../../../../helpers/update_notifier.dart';
import '../../../model/style.dart';
import 'package:firka/core/state/firka_state.dart';
import 'package:firka/core/state/update_notifier.dart';
import 'package:firka/ui/theme/style.dart';
class PageWithSubPages extends StatefulWidget {
final int pageIndex;

View File

@@ -1,27 +1,27 @@
import 'dart:async';
import 'package:carousel_slider/carousel_slider.dart';
import 'package:firka/helpers/api/client/kreta_client.dart';
import 'package:firka/helpers/api/client/kreta_stream.dart';
import 'package:firka/helpers/api/model/test.dart';
import 'package:firka/helpers/api/model/timetable.dart';
import 'package:firka/helpers/debug_helper.dart';
import 'package:firka/helpers/extensions.dart';
import 'package:firka/helpers/settings.dart';
import 'package:firka/ui/model/style.dart';
import 'package:firka/api/client/kreta_client.dart';
import 'package:firka/api/client/kreta_stream.dart';
import 'package:firka/api/model/test.dart';
import 'package:firka/api/model/timetable.dart';
import 'package:firka/core/debug_helper.dart';
import 'package:firka/core/extensions.dart';
import 'package:firka/core/settings.dart';
import 'package:firka/ui/theme/style.dart';
import 'package:firka/ui/phone/screens/settings/settings_screen.dart';
import 'package:firka/ui/phone/widgets/bubble_test.dart';
import 'package:firka/ui/widget/delayed_spinner.dart';
import 'package:firka/ui/shared/delayed_spinner.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:majesticons_flutter/majesticons_flutter.dart';
import 'package:transparent_pointer/transparent_pointer.dart';
import '../../../../helpers/api/consts.dart';
import '../../../../helpers/firka_state.dart';
import '../../../../helpers/update_notifier.dart';
import '../../../../main.dart';
import '../../../widget/firka_icon.dart';
import 'package:firka/api/consts.dart';
import 'package:firka/core/state/firka_state.dart';
import 'package:firka/core/state/update_notifier.dart';
import 'package:firka/app/app_state.dart';
import 'package:firka/ui/shared/firka_icon.dart';
import '../../widgets/bottom_tt_icon.dart';
import '../../widgets/tt_day.dart';

View File

@@ -1,21 +1,21 @@
import 'package:firka/helpers/api/consts.dart';
import 'package:firka/helpers/api/model/omission.dart';
import 'package:firka/helpers/api/model/timetable.dart';
import 'package:firka/helpers/debug_helper.dart';
import 'package:firka/helpers/extensions.dart';
import 'package:firka/helpers/settings.dart';
import 'package:firka/ui/model/style.dart';
import 'package:firka/ui/widget/delayed_spinner.dart';
import 'package:firka/api/consts.dart';
import 'package:firka/api/model/omission.dart';
import 'package:firka/api/model/timetable.dart';
import 'package:firka/core/debug_helper.dart';
import 'package:firka/core/extensions.dart';
import 'package:firka/core/settings.dart';
import 'package:firka/ui/theme/style.dart';
import 'package:firka/ui/shared/delayed_spinner.dart';
import 'package:flutter/material.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:majesticons_flutter/majesticons_flutter.dart';
import 'package:transparent_pointer/transparent_pointer.dart';
import '../../../../helpers/api/model/test.dart';
import '../../../../helpers/firka_state.dart';
import '../../../../helpers/update_notifier.dart';
import '../../../../main.dart';
import '../../../widget/firka_icon.dart';
import 'package:firka/api/model/test.dart';
import 'package:firka/core/state/firka_state.dart';
import 'package:firka/core/state/update_notifier.dart';
import 'package:firka/app/app_state.dart';
import 'package:firka/ui/shared/firka_icon.dart';
import '../../screens/settings/settings_screen.dart';
class HomeTimetableMonthlyScreen extends StatefulWidget {

View File

@@ -2,19 +2,19 @@
import 'dart:typed_data';
import 'package:firka/helpers/db/models/token_model.dart';
import 'package:firka/helpers/extensions.dart';
import 'package:firka/helpers/icon_helper.dart';
import 'package:firka/helpers/profile_picture.dart';
import 'package:firka/main.dart';
import 'package:firka/data/models/token_model.dart';
import 'package:firka/core/extensions.dart';
import 'package:firka/core/icon_helper.dart';
import 'package:firka/core/profile_picture.dart';
import 'package:firka/app/app_state.dart';
import 'package:firka/ui/phone/screens/login/login_screen.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import '../../../../helpers/debug_helper.dart';
import '../../../../helpers/firka_bundle.dart';
import '../../../../helpers/firka_state.dart';
import '../../../widget/firka_icon.dart';
import 'package:firka/core/debug_helper.dart';
import 'package:firka/core/firka_bundle.dart';
import 'package:firka/core/state/firka_state.dart';
import 'package:firka/ui/shared/firka_icon.dart';
class DebugScreen extends StatefulWidget {
final AppInitialization data;

View File

@@ -1,15 +1,15 @@
import 'dart:async';
import 'dart:io';
import 'package:firka/helpers/db/models/app_settings_model.dart';
import 'package:firka/helpers/settings.dart';
import 'package:firka/helpers/ui/firka_button.dart';
import 'package:firka/ui/model/style.dart';
import 'package:firka/data/models/app_settings_model.dart';
import 'package:firka/core/settings.dart';
import 'package:firka/ui/components/firka_button.dart';
import 'package:firka/ui/theme/style.dart';
import 'package:firka/ui/phone/screens/home/home_screen.dart';
import 'package:flutter/material.dart';
import '../../../../helpers/firka_state.dart';
import '../../../../main.dart';
import 'package:firka/core/state/firka_state.dart';
import 'package:firka/app/app_state.dart';
class BetaScreen extends StatefulWidget {
final AppInitialization data;

View File

@@ -1,16 +1,16 @@
import 'dart:async';
import 'dart:io';
import 'package:firka/helpers/api/client/kreta_client.dart';
import 'package:firka/helpers/api/client/kreta_stream.dart';
import 'package:firka/helpers/api/exceptions/token.dart';
import 'package:firka/helpers/active_account_helper.dart';
import 'package:firka/helpers/extensions.dart';
import 'package:firka/helpers/live_activity_service.dart';
import 'package:firka/helpers/settings.dart';
import 'package:firka/helpers/update_notifier.dart';
import 'package:firka/helpers/watch_sync_helper.dart';
import 'package:firka/main.dart';
import 'package:firka/ui/model/style.dart';
import 'package:firka/api/client/kreta_client.dart';
import 'package:firka/api/client/kreta_stream.dart';
import 'package:firka/api/exceptions/token.dart';
import 'package:firka/services/active_account_helper.dart';
import 'package:firka/core/extensions.dart';
import 'package:firka/services/live_activity_service.dart';
import 'package:firka/core/settings.dart';
import 'package:firka/core/state/update_notifier.dart';
import 'package:firka/services/watch_sync_helper.dart';
import 'package:firka/app/app_state.dart';
import 'package:firka/ui/theme/style.dart';
import 'package:firka/ui/phone/pages/extras/main_wear_pair.dart';
import 'package:firka/ui/phone/pages/extras/reauth_toast.dart';
import 'package:firka/ui/phone/pages/home/home_grades.dart';
@@ -26,13 +26,13 @@ import 'package:home_widget/home_widget.dart';
import 'package:majesticons_flutter/majesticons_flutter.dart';
import 'package:smart_scroll/smart_scroll.dart';
import '../../../../helpers/db/widget.dart';
import '../../../../helpers/debug_helper.dart';
import '../../../../helpers/firka_bundle.dart';
import '../../../../helpers/firka_state.dart';
import '../../../../helpers/image_preloader.dart';
import '../../../widget/delayed_spinner.dart';
import '../../../widget/firka_icon.dart';
import 'package:firka/data/widget.dart';
import 'package:firka/core/debug_helper.dart';
import 'package:firka/core/firka_bundle.dart';
import 'package:firka/core/state/firka_state.dart';
import 'package:firka/core/image_preloader.dart';
import 'package:firka/ui/shared/delayed_spinner.dart';
import 'package:firka/ui/shared/firka_icon.dart';
import '../../pages/extras/extras.dart';
import '../../pages/extras/main_error.dart';
import '../../pages/home/home_grades_subject.dart';

View File

@@ -1,10 +1,10 @@
import 'package:firka/main.dart';
import 'package:firka/ui/model/style.dart';
import 'package:firka/ui/widget/firka_icon.dart';
import 'package:firka/app/app_state.dart';
import 'package:firka/ui/theme/style.dart';
import 'package:firka/ui/shared/firka_icon.dart';
import 'package:flutter/material.dart';
import 'package:majesticons_flutter/majesticons_flutter.dart';
import '../../../../helpers/firka_state.dart';
import 'package:firka/core/state/firka_state.dart';
class FullPrivacyPolicyScreen extends StatefulWidget {
final AppInitialization data;

View File

@@ -1,15 +1,15 @@
import 'dart:typed_data';
import 'package:firka/helpers/ui/firka_button.dart';
import 'package:firka/helpers/ui/firka_card.dart';
import 'package:firka/main.dart';
import 'package:firka/ui/model/style.dart';
import 'package:firka/ui/components/firka_button.dart';
import 'package:firka/ui/components/firka_card.dart';
import 'package:firka/app/app_state.dart';
import 'package:firka/ui/theme/style.dart';
import 'package:firka/ui/phone/screens/live_activity/full_privacy_policy_screen.dart';
import 'package:firka/ui/widget/firka_icon.dart';
import 'package:firka/ui/shared/firka_icon.dart';
import 'package:flutter/material.dart';
import 'package:majesticons_flutter/majesticons_flutter.dart';
import '../../../../helpers/firka_state.dart';
import 'package:firka/core/state/firka_state.dart';
class LiveActivityConsentScreen extends StatefulWidget {
final AppInitialization data;

View File

@@ -1,17 +1,17 @@
import 'dart:math' as math;
import 'package:carousel_slider/carousel_slider.dart';
import 'package:firka/helpers/firka_bundle.dart';
import 'package:firka/main.dart';
import 'package:firka/core/firka_bundle.dart';
import 'package:firka/app/app_state.dart';
import 'package:firka/ui/phone/widgets/login_webview.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:url_launcher/url_launcher.dart';
import '../../../../helpers/firka_state.dart';
import '../../../../helpers/image_preloader.dart';
import '../../../model/style.dart';
import '../../../widget/delayed_spinner.dart';
import 'package:firka/core/state/firka_state.dart';
import 'package:firka/core/image_preloader.dart';
import 'package:firka/ui/theme/style.dart';
import 'package:firka/ui/shared/delayed_spinner.dart';
// TODO: Replace these with actual privacy policy URLs
const String _privacyUrlHungarian =

View File

@@ -1,12 +1,12 @@
import 'package:firka/helpers/extensions.dart';
import 'package:firka/main.dart';
import 'package:firka/core/extensions.dart';
import 'package:firka/app/app_state.dart';
import 'package:flutter/material.dart';
import 'package:majesticons_flutter/majesticons_flutter.dart';
import '../../../../helpers/api/model/notice_board.dart';
import '../../../../helpers/firka_bundle.dart';
import '../../../model/style.dart';
import '../../../widget/firka_icon.dart';
import 'package:firka/api/model/notice_board.dart';
import 'package:firka/core/firka_bundle.dart';
import 'package:firka/ui/theme/style.dart';
import 'package:firka/ui/shared/firka_icon.dart';
class MessageScreen extends StatelessWidget {
final AppInitialization data;

View File

@@ -2,15 +2,15 @@ import 'dart:collection';
import 'dart:io';
import 'package:dart_jsonwebtoken/dart_jsonwebtoken.dart';
import 'package:firka/helpers/db/models/app_settings_model.dart';
import 'package:firka/helpers/db/models/token_model.dart';
import 'package:firka/helpers/image_preloader.dart';
import 'package:firka/helpers/ui/firka_button.dart';
import 'package:firka/helpers/ui/firka_card.dart';
import 'package:firka/main.dart';
import 'package:firka/ui/model/style.dart';
import 'package:firka/data/models/app_settings_model.dart';
import 'package:firka/data/models/token_model.dart';
import 'package:firka/core/image_preloader.dart';
import 'package:firka/ui/components/firka_button.dart';
import 'package:firka/ui/components/firka_card.dart';
import 'package:firka/app/app_state.dart';
import 'package:firka/ui/theme/style.dart';
import 'package:firka/ui/phone/screens/login/login_screen.dart';
import 'package:firka/ui/widget/firka_icon.dart';
import 'package:firka/ui/shared/firka_icon.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
@@ -20,13 +20,14 @@ import 'package:path/path.dart' as p;
import 'package:share_plus/share_plus.dart';
import 'package:url_launcher/url_launcher_string.dart';
import '../../../../helpers/db/widget.dart';
import '../../../../helpers/firka_bundle.dart';
import '../../../../helpers/firka_state.dart';
import '../../../../helpers/api/client/kreta_client.dart';
import '../../../../helpers/settings.dart';
import '../../../../helpers/live_activity_service.dart';
import '../../../../helpers/watch_sync_helper.dart';
import 'package:firka/data/widget.dart';
import 'package:firka/core/firka_bundle.dart';
import 'package:firka/app/initialization_screen.dart';
import 'package:firka/core/state/firka_state.dart';
import 'package:firka/api/client/kreta_client.dart';
import 'package:firka/core/settings.dart';
import 'package:firka/services/live_activity_service.dart';
import 'package:firka/services/watch_sync_helper.dart';
import '../../widgets/login_webview.dart';
class SettingsScreen extends StatefulWidget {

View File

@@ -2,8 +2,8 @@ import 'dart:typed_data';
import 'package:flutter/material.dart';
import '../../model/style.dart';
import '../../widget/firka_icon.dart';
import 'package:firka/ui/theme/style.dart';
import 'package:firka/ui/shared/firka_icon.dart';
class BottomNavIconWidget extends StatelessWidget {
final void Function() onTap;

View File

@@ -1,8 +1,8 @@
import 'package:firka/helpers/extensions.dart';
import 'package:firka/core/extensions.dart';
import 'package:firka/l10n/app_localizations.dart';
import 'package:flutter/material.dart';
import '../../model/style.dart';
import 'package:firka/ui/theme/style.dart';
class BottomTimeTableNavIconWidget extends StatelessWidget {
final AppLocalizations l10n;

View File

@@ -1,9 +1,9 @@
import 'package:firka/ui/widget/firka_icon.dart';
import 'package:firka/ui/shared/firka_icon.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_svg/svg.dart';
import 'package:majesticons_flutter/majesticons_flutter.dart';
import '../../model/style.dart';
import 'package:firka/ui/theme/style.dart';
class BubbleTest extends StatelessWidget {
const BubbleTest({super.key});

View File

@@ -1,6 +1,6 @@
import 'package:firka/helpers/api/model/grade.dart';
import 'package:firka/helpers/ui/grade_helpers.dart';
import 'package:firka/ui/model/style.dart';
import 'package:firka/api/model/grade.dart';
import 'package:firka/ui/components/grade_helpers.dart';
import 'package:firka/ui/theme/style.dart';
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';

View File

@@ -1,10 +1,10 @@
import 'package:firka/helpers/ui/firka_card.dart';
import 'package:firka/ui/components/firka_card.dart';
import 'package:firka/l10n/app_localizations.dart';
import 'package:firka/ui/model/style.dart';
import 'package:firka/ui/widget/counter_digit.dart';
import 'package:firka/ui/theme/style.dart';
import 'package:firka/ui/shared/counter_digit.dart';
import 'package:flutter/material.dart';
import '../../../helpers/api/model/timetable.dart';
import 'package:firka/api/model/timetable.dart';
class StartingSoonWidget extends StatelessWidget {
final AppLocalizations l10n;

View File

@@ -1,14 +1,14 @@
import 'package:confetti/confetti.dart';
import 'package:intl/intl.dart';
import 'package:firka/helpers/extensions.dart';
import 'package:firka/core/extensions.dart';
import 'package:firka/l10n/app_localizations.dart';
import 'package:firka/ui/widget/firka_icon.dart';
import 'package:firka/ui/shared/firka_icon.dart';
import 'package:flutter/material.dart';
import 'package:majesticons_flutter/majesticons_flutter.dart';
import '../../../helpers/api/model/student.dart';
import '../../../helpers/api/model/timetable.dart';
import '../../model/style.dart';
import 'package:firka/api/model/student.dart';
import 'package:firka/api/model/timetable.dart';
import 'package:firka/ui/theme/style.dart';
class WelcomeWidget extends StatefulWidget {
final AppLocalizations l10n;

View File

@@ -1,10 +1,10 @@
import 'package:firka/helpers/api/model/homework.dart';
import 'package:firka/helpers/db/models/homework_cache_model.dart';
import 'package:firka/helpers/ui/common_bottom_sheets.dart';
import 'package:firka/helpers/ui/firka_card.dart';
import 'package:firka/main.dart';
import 'package:firka/ui/model/style.dart';
import 'package:firka/ui/widget/firka_icon.dart';
import 'package:firka/api/model/homework.dart';
import 'package:firka/data/models/homework_cache_model.dart';
import 'package:firka/ui/components/common_bottom_sheets.dart';
import 'package:firka/ui/components/firka_card.dart';
import 'package:firka/app/app_state.dart';
import 'package:firka/ui/theme/style.dart';
import 'package:firka/ui/shared/firka_icon.dart';
import 'package:flutter/material.dart';
import 'package:majesticons_flutter/majesticons_flutter.dart';

View File

@@ -1,8 +1,8 @@
import 'package:firka/helpers/ui/firka_card.dart';
import 'package:firka/ui/model/style.dart';
import 'package:firka/ui/components/firka_card.dart';
import 'package:firka/ui/theme/style.dart';
import 'package:flutter/material.dart';
import '../../../helpers/api/model/notice_board.dart';
import 'package:firka/api/model/notice_board.dart';
// TODO: Finish
class InfoBoardItemWidget extends StatelessWidget {

View File

@@ -1,18 +1,18 @@
import 'package:firka/helpers/extensions.dart';
import 'package:firka/helpers/settings.dart';
import 'package:firka/helpers/ui/firka_card.dart';
import 'package:firka/main.dart';
import 'package:firka/ui/model/style.dart';
import 'package:firka/core/extensions.dart';
import 'package:firka/core/settings.dart';
import 'package:firka/ui/components/firka_card.dart';
import 'package:firka/app/app_state.dart';
import 'package:firka/ui/theme/style.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:majesticons_flutter/majesticons_flutter.dart';
import '../../../helpers/api/model/test.dart';
import '../../../helpers/api/model/timetable.dart';
import '../../../helpers/debug_helper.dart';
import '../../../helpers/ui/common_bottom_sheets.dart';
import '../../widget/class_icon.dart';
import '../../widget/firka_icon.dart';
import 'package:firka/api/model/test.dart';
import 'package:firka/api/model/timetable.dart';
import 'package:firka/core/debug_helper.dart';
import 'package:firka/ui/components/common_bottom_sheets.dart';
import 'package:firka/ui/shared/class_icon.dart';
import 'package:firka/ui/shared/firka_icon.dart';
import 'bubble_test.dart';
class LessonWidget extends StatelessWidget {

View File

@@ -1,15 +1,15 @@
import 'package:firka/helpers/api/model/test.dart';
import 'package:firka/helpers/extensions.dart';
import 'package:firka/helpers/ui/firka_card.dart';
import 'package:firka/api/model/test.dart';
import 'package:firka/core/extensions.dart';
import 'package:firka/ui/components/firka_card.dart';
import 'package:firka/l10n/app_localizations.dart';
import 'package:firka/ui/model/style.dart';
import 'package:firka/ui/widget/firka_icon.dart';
import 'package:firka/ui/theme/style.dart';
import 'package:firka/ui/shared/firka_icon.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:majesticons_flutter/majesticons_flutter.dart';
import '../../../helpers/api/model/timetable.dart';
import '../../widget/class_icon.dart';
import 'package:firka/api/model/timetable.dart';
import 'package:firka/ui/shared/class_icon.dart';
class LessonBigWidget extends StatelessWidget {
final AppLocalizations l10n;

View File

@@ -1,11 +1,11 @@
import 'package:firka/helpers/extensions.dart';
import 'package:firka/helpers/ui/firka_card.dart';
import 'package:firka/core/extensions.dart';
import 'package:firka/ui/components/firka_card.dart';
import 'package:firka/l10n/app_localizations.dart';
import 'package:firka/ui/model/style.dart';
import 'package:firka/ui/theme/style.dart';
import 'package:flutter/material.dart';
import '../../../helpers/api/model/timetable.dart';
import '../../widget/class_icon.dart';
import 'package:firka/api/model/timetable.dart';
import 'package:firka/ui/shared/class_icon.dart';
class LessonSmallWidget extends StatelessWidget {
final AppLocalizations l10n;

View File

@@ -1,22 +1,23 @@
import 'dart:async';
import 'dart:io';
import 'package:firka/helpers/db/models/app_settings_model.dart';
import 'package:firka/helpers/live_activity_service.dart';
import 'package:firka/main.dart';
import 'package:firka/data/models/app_settings_model.dart';
import 'package:firka/services/live_activity_service.dart';
import 'package:firka/app/app_state.dart';
import 'package:flutter/material.dart';
import 'package:isar_community/isar.dart';
import 'package:webview_flutter/webview_flutter.dart';
import '../../../helpers/api/client/kreta_client.dart';
import '../../../helpers/watch_sync_helper.dart';
import '../../../helpers/api/consts.dart';
import '../../../helpers/api/token_grant.dart';
import '../../../helpers/db/models/token_model.dart';
import '../../../helpers/firka_bundle.dart';
import '../../../helpers/firka_state.dart';
import '../../../helpers/settings.dart';
import '../../../ui/model/style.dart';
import 'package:firka/api/client/kreta_client.dart';
import 'package:firka/services/watch_sync_helper.dart';
import 'package:firka/api/consts.dart';
import 'package:firka/api/token_grant.dart';
import 'package:firka/data/models/token_model.dart';
import 'package:firka/core/firka_bundle.dart';
import 'package:firka/app/initialization_screen.dart';
import 'package:firka/core/state/firka_state.dart';
import 'package:firka/core/settings.dart';
import 'package:firka/ui/theme/style.dart';
import '../pages/error/error_page.dart';
class LoginWebviewWidget extends StatefulWidget {

View File

@@ -1,7 +1,7 @@
import 'package:firka/helpers/ui/firka_card.dart';
import 'package:firka/ui/components/firka_card.dart';
import 'package:flutter/material.dart';
import '../../../helpers/api/model/notice_board.dart';
import 'package:firka/api/model/notice_board.dart';
// TODO: Finish
class NoticeBoardItemWidget extends StatelessWidget {

View File

@@ -1,9 +1,9 @@
import 'package:firka/helpers/api/model/test.dart';
import 'package:firka/helpers/api/model/timetable.dart';
import 'package:firka/helpers/extensions.dart';
import 'package:firka/helpers/ui/firka_card.dart';
import 'package:firka/main.dart';
import 'package:firka/ui/model/style.dart';
import 'package:firka/api/model/test.dart';
import 'package:firka/api/model/timetable.dart';
import 'package:firka/core/extensions.dart';
import 'package:firka/ui/components/firka_card.dart';
import 'package:firka/app/app_state.dart';
import 'package:firka/ui/theme/style.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';

View File

@@ -1,7 +1,7 @@
import 'package:firka/helpers/icon_helper.dart';
import 'package:firka/core/icon_helper.dart';
import 'package:flutter/material.dart';
import 'firka_icon.dart';
import 'package:firka/ui/shared/firka_icon.dart';
class ClassIconWidget extends StatelessWidget {
final String _uid;

View File

@@ -1,4 +1,4 @@
import 'package:firka/ui/model/style.dart';
import 'package:firka/ui/theme/style.dart';
import 'package:flutter/material.dart';
class CounterDigitWidget extends StatelessWidget {

View File

@@ -2,8 +2,8 @@ import 'dart:async';
import 'package:flutter/material.dart';
import '../../helpers/firka_state.dart';
import '../model/style.dart';
import 'package:firka/core/state/firka_state.dart';
import 'package:firka/ui/theme/style.dart';
class DelayedSpinnerWidget extends StatefulWidget {
const DelayedSpinnerWidget({super.key});

View File

@@ -1,11 +1,11 @@
import 'package:firka/helpers/api/model/grade.dart';
import 'package:firka/helpers/api/model/subject.dart';
import 'package:firka/helpers/ui/firka_card.dart';
import 'package:firka/helpers/ui/grade_helpers.dart';
import 'package:firka/ui/widget/class_icon.dart';
import 'package:firka/api/model/grade.dart';
import 'package:firka/api/model/subject.dart';
import 'package:firka/ui/components/firka_card.dart';
import 'package:firka/ui/components/grade_helpers.dart';
import 'package:firka/ui/shared/class_icon.dart';
import 'package:flutter/material.dart';
import '../model/style.dart';
import 'package:firka/ui/theme/style.dart';
class GradeSmallCard extends FirkaCard {
final List<Grade> grades;

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