Compare commits

...

5 Commits

Author SHA1 Message Date
0e33eee393
reset currentLessonNo
Some checks failed
Firka/firka/pipeline/head There was a failure building this commit
2025-04-25 22:58:33 +02:00
49072f389e
fix centering 2025-04-25 22:14:04 +02:00
78ab1a6c3e
fix: make icon nullable 2025-04-25 21:41:17 +02:00
1f07ef4935
fix: getIconType 2025-04-25 21:40:01 +02:00
a39fc60470
debug: add server changer 2025-04-25 15:42:27 +02:00
8 changed files with 829 additions and 47 deletions

View File

@ -0,0 +1,12 @@
import 'package:isar/isar.dart';
part 'app_settings_model.g.dart';
@collection
class AppSettingsModel {
Id? id;
bool? useCustomHost;
String? customHost;
AppSettingsModel();
}

View File

@ -0,0 +1,571 @@
// 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'customHost': PropertySchema(
id: 0,
name: r'customHost',
type: IsarType.string,
),
r'useCustomHost': PropertySchema(
id: 1,
name: r'useCustomHost',
type: IsarType.bool,
)
},
estimateSize: _appSettingsModelEstimateSize,
serialize: _appSettingsModelSerialize,
deserialize: _appSettingsModelDeserialize,
deserializeProp: _appSettingsModelDeserializeProp,
idName: r'ignored',
indexes: {},
links: {},
embeddedSchemas: {},
getId: _appSettingsModelGetId,
getLinks: _appSettingsModelGetLinks,
attach: _appSettingsModelAttach,
version: '3.1.0+1',
);
int _appSettingsModelEstimateSize(
AppSettingsModel object,
List<int> offsets,
Map<Type, List<int>> allOffsets,
) {
var bytesCount = offsets.last;
{
final value = object.customHost;
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.writeString(offsets[0], object.customHost);
writer.writeBool(offsets[1], object.useCustomHost);
}
AppSettingsModel _appSettingsModelDeserialize(
Id id,
IsarReader reader,
List<int> offsets,
Map<Type, List<int>> allOffsets,
) {
final object = AppSettingsModel();
object.customHost = reader.readStringOrNull(offsets[0]);
object.id = id;
object.useCustomHost = reader.readBoolOrNull(offsets[1]);
return object;
}
P _appSettingsModelDeserializeProp<P>(
IsarReader reader,
int propertyId,
int offset,
Map<Type, List<int>> allOffsets,
) {
switch (propertyId) {
case 0:
return (reader.readStringOrNull(offset)) as P;
case 1:
return (reader.readBoolOrNull(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> anyIgnored() {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(const IdWhereClause.any());
});
}
}
extension AppSettingsModelQueryWhere
on QueryBuilder<AppSettingsModel, AppSettingsModel, QWhereClause> {
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterWhereClause>
ignoredEqualTo(Id ignored) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(IdWhereClause.between(
lower: ignored,
upper: ignored,
));
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterWhereClause>
ignoredNotEqualTo(Id ignored) {
return QueryBuilder.apply(this, (query) {
if (query.whereSort == Sort.asc) {
return query
.addWhereClause(
IdWhereClause.lessThan(upper: ignored, includeUpper: false),
)
.addWhereClause(
IdWhereClause.greaterThan(lower: ignored, includeLower: false),
);
} else {
return query
.addWhereClause(
IdWhereClause.greaterThan(lower: ignored, includeLower: false),
)
.addWhereClause(
IdWhereClause.lessThan(upper: ignored, includeUpper: false),
);
}
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterWhereClause>
ignoredGreaterThan(Id ignored, {bool include = false}) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(
IdWhereClause.greaterThan(lower: ignored, includeLower: include),
);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterWhereClause>
ignoredLessThan(Id ignored, {bool include = false}) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(
IdWhereClause.lessThan(upper: ignored, includeUpper: include),
);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterWhereClause>
ignoredBetween(
Id lowerIgnored,
Id upperIgnored, {
bool includeLower = true,
bool includeUpper = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(IdWhereClause.between(
lower: lowerIgnored,
includeLower: includeLower,
upper: upperIgnored,
includeUpper: includeUpper,
));
});
}
}
extension AppSettingsModelQueryFilter
on QueryBuilder<AppSettingsModel, AppSettingsModel, QFilterCondition> {
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
customHostIsNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(const FilterCondition.isNull(
property: r'customHost',
));
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
customHostIsNotNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(const FilterCondition.isNotNull(
property: r'customHost',
));
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
customHostEqualTo(
String? value, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.equalTo(
property: r'customHost',
value: value,
caseSensitive: caseSensitive,
));
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
customHostGreaterThan(
String? value, {
bool include = false,
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.greaterThan(
include: include,
property: r'customHost',
value: value,
caseSensitive: caseSensitive,
));
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
customHostLessThan(
String? value, {
bool include = false,
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.lessThan(
include: include,
property: r'customHost',
value: value,
caseSensitive: caseSensitive,
));
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
customHostBetween(
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'customHost',
lower: lower,
includeLower: includeLower,
upper: upper,
includeUpper: includeUpper,
caseSensitive: caseSensitive,
));
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
customHostStartsWith(
String value, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.startsWith(
property: r'customHost',
value: value,
caseSensitive: caseSensitive,
));
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
customHostEndsWith(
String value, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.endsWith(
property: r'customHost',
value: value,
caseSensitive: caseSensitive,
));
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
customHostContains(String value, {bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.contains(
property: r'customHost',
value: value,
caseSensitive: caseSensitive,
));
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
customHostMatches(String pattern, {bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.matches(
property: r'customHost',
wildcard: pattern,
caseSensitive: caseSensitive,
));
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
customHostIsEmpty() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.equalTo(
property: r'customHost',
value: '',
));
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
customHostIsNotEmpty() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.greaterThan(
property: r'customHost',
value: '',
));
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
ignoredIsNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(const FilterCondition.isNull(
property: r'ignored',
));
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
ignoredIsNotNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(const FilterCondition.isNotNull(
property: r'ignored',
));
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
ignoredEqualTo(Id? value) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.equalTo(
property: r'ignored',
value: value,
));
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
ignoredGreaterThan(
Id? value, {
bool include = false,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.greaterThan(
include: include,
property: r'ignored',
value: value,
));
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
ignoredLessThan(
Id? value, {
bool include = false,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.lessThan(
include: include,
property: r'ignored',
value: value,
));
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
ignoredBetween(
Id? lower,
Id? upper, {
bool includeLower = true,
bool includeUpper = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.between(
property: r'ignored',
lower: lower,
includeLower: includeLower,
upper: upper,
includeUpper: includeUpper,
));
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
useCustomHostIsNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(const FilterCondition.isNull(
property: r'useCustomHost',
));
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
useCustomHostIsNotNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(const FilterCondition.isNotNull(
property: r'useCustomHost',
));
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterFilterCondition>
useCustomHostEqualTo(bool? value) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.equalTo(
property: r'useCustomHost',
value: 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>
sortByCustomHost() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'customHost', Sort.asc);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterSortBy>
sortByCustomHostDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'customHost', Sort.desc);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterSortBy>
sortByUseCustomHost() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'useCustomHost', Sort.asc);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterSortBy>
sortByUseCustomHostDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'useCustomHost', Sort.desc);
});
}
}
extension AppSettingsModelQuerySortThenBy
on QueryBuilder<AppSettingsModel, AppSettingsModel, QSortThenBy> {
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterSortBy>
thenByCustomHost() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'customHost', Sort.asc);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterSortBy>
thenByCustomHostDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'customHost', Sort.desc);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterSortBy>
thenByIgnored() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'ignored', Sort.asc);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterSortBy>
thenByIgnoredDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'ignored', Sort.desc);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterSortBy>
thenByUseCustomHost() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'useCustomHost', Sort.asc);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QAfterSortBy>
thenByUseCustomHostDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'useCustomHost', Sort.desc);
});
}
}
extension AppSettingsModelQueryWhereDistinct
on QueryBuilder<AppSettingsModel, AppSettingsModel, QDistinct> {
QueryBuilder<AppSettingsModel, AppSettingsModel, QDistinct>
distinctByCustomHost({bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addDistinctBy(r'customHost', caseSensitive: caseSensitive);
});
}
QueryBuilder<AppSettingsModel, AppSettingsModel, QDistinct>
distinctByUseCustomHost() {
return QueryBuilder.apply(this, (query) {
return query.addDistinctBy(r'useCustomHost');
});
}
}
extension AppSettingsModelQueryProperty
on QueryBuilder<AppSettingsModel, AppSettingsModel, QQueryProperty> {
QueryBuilder<AppSettingsModel, int, QQueryOperations> ignoredProperty() {
return QueryBuilder.apply(this, (query) {
return query.addPropertyName(r'ignored');
});
}
QueryBuilder<AppSettingsModel, String?, QQueryOperations>
customHostProperty() {
return QueryBuilder.apply(this, (query) {
return query.addPropertyName(r'customHost');
});
}
QueryBuilder<AppSettingsModel, bool?, QQueryOperations>
useCustomHostProperty() {
return QueryBuilder.apply(this, (query) {
return query.addPropertyName(r'useCustomHost');
});
}
}

View File

@ -83,13 +83,13 @@ Map<ClassIcon, Uint8List> _iconMap = {
ClassIcon? getIconType(String uid, String className, String category) {
ClassIcon? icon;
if (category == "matematika") {
if (category.toLowerCase() == "matematika") {
icon = ClassIcon.mathematics;
}
if (icon == null) {
for (var desc in _descriptors.entries) {
if (desc.value.hasMatch(className)) {
if (desc.value.hasMatch(className.toLowerCase())) {
icon = desc.key;
break;
@ -100,7 +100,9 @@ ClassIcon? getIconType(String uid, String className, String category) {
return icon;
}
Uint8List getIconData(ClassIcon icon) {
Uint8List getIconData(ClassIcon? icon) {
if (icon == null) return Majesticon.alertCircleSolid;
var iconData = _iconMap[icon];
iconData ??= Majesticon.alertCircleSolid;

View File

@ -1,6 +1,7 @@
import 'dart:async';
import 'dart:io';
import 'package:firka/helpers/db/models/app_settings_model.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:firka/helpers/api/client/kreta_client.dart';
import 'package:firka/helpers/db/models/generic_cache_model.dart';
@ -35,11 +36,26 @@ class AppInitialization {
int tokenCount;
bool hasWatchListener = false;
Uint8List? profilePicture;
AppSettingsModel settings;
AppInitialization({
required this.isar,
required this.tokenCount,
required this.settings,
});
bool _writing = false;
Future<void> saveSettings() async {
while (_writing) {
await Future.delayed(const Duration(milliseconds: 50));
}
_writing = true;
await isar.writeTxn(() async {
await isar.appSettingsModels.put(settings);
});
_writing = false;
}
}
Future<Isar> initDB() async {
@ -51,7 +67,8 @@ Future<Isar> initDB() async {
TokenModelSchema,
GenericCacheModelSchema,
TimetableCacheModelSchema,
HomeworkCacheModelSchema
HomeworkCacheModelSchema,
AppSettingsModelSchema,
],
inspector: true,
directory: dir.path,
@ -63,14 +80,31 @@ Future<Isar> initDB() async {
Future<AppInitialization> initializeApp() async {
final isar = await initDB();
final tokenCount = await isar.tokenModels.count();
var settings = AppSettingsModel();
settings.id = 0;
if (kDebugMode) {
print('Token count: $tokenCount');
}
if (await isar.appSettingsModels.count() != 0) {
settings = (await isar.appSettingsModels.where().findFirst())!;
}
if (settings.useCustomHost != null && settings.useCustomHost!) {
var host = settings.customHost!;
KretaEndpoints.kretaBase = "https://$host";
KretaEndpoints.kretaIdp = KretaEndpoints.kretaBase;
KretaEndpoints.kretaLoginUrl =
"${KretaEndpoints.kretaBase}/Account/Login?ReturnUrl=%2Fconnect%2Fauthorize%2Fcallback%3Fprompt%3Dlogin%26nonce%3DwylCrqT4oN6PPgQn2yQB0euKei9nJeZ6_ffJ-VpSKZU%26response_type%3Dcode%26code_challenge_method%3DS256%26scope%3Dopenid%2520email%2520offline_access%2520kreta-ellenorzo-webapi.public%2520kreta-eugyintezes-webapi.public%2520kreta-fileservice-webapi.public%2520kreta-mobile-global-webapi.public%2520kreta-dkt-webapi.public%2520kreta-ier-webapi.public%26code_challenge%3DHByZRRnPGb-Ko_wTI7ibIba1HQ6lor0ws4bcgReuYSQ%26redirect_uri%3Dhttps%253A%252F%252Fmobil.e-kreta.hu%252Fellenorzo-student%252Fprod%252Foauthredirect%26client_id%3Dkreta-ellenorzo-student-mobile-ios%26state%3Dkreta_student_mobile%26suppressed_prompt%3Dlogin";
KretaEndpoints.tokenGrantUrl = "${KretaEndpoints.kretaBase}/connect/token";
}
var init = AppInitialization(
isar: isar,
tokenCount: tokenCount,
settings: settings,
);
resetOldTimeTableCache(isar);
@ -136,6 +170,8 @@ class InitializationScreen extends StatelessWidget {
// Check if initialization is complete
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasError) {
debugPrintStack(label: snapshot.error.toString());
// Handle initialization error
return MaterialApp(
key: ValueKey('errorPage'),

View File

@ -1,3 +1,5 @@
import 'dart:async';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:carousel_slider/carousel_slider.dart';
import 'package:firka/helpers/api/client/kreta_client.dart';
@ -10,6 +12,7 @@ import 'package:flutter/services.dart';
import 'package:webview_flutter/webview_flutter.dart';
import '../../../../helpers/api/token_grant.dart';
import '../../../model/colors.dart';
import '../home/home_screen.dart';
class LoginScreen extends StatefulWidget {
@ -23,6 +26,7 @@ class LoginScreen extends StatefulWidget {
class _LoginScreenState extends State<LoginScreen> {
late WebViewController _webViewController;
late Timer _timer;
@override
void initState() {
@ -87,6 +91,138 @@ class _LoginScreenState extends State<LoginScreen> {
));
}
@override
void dispose() {
_timer.cancel();
super.dispose();
}
void startTimer() {
_timer = Timer(const Duration(seconds: 3), () {
showModalBottomSheet(
context: context,
elevation: 100,
isScrollControlled: true,
enableDrag: true,
backgroundColor: Colors.transparent,
barrierColor: Colors.transparent,
constraints: BoxConstraints(
maxHeight: MediaQuery.of(context).size.height * 0.5,
),
builder: (BuildContext context) {
return Stack(
children: [
Positioned.fill(
child: GestureDetector(
onTap: () => Navigator.pop(context),
behavior: HitTestBehavior.opaque,
child: Container(color: Colors.transparent),
),
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
decoration: BoxDecoration(
color: appColors.card,
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Center(
child: TextFormField(
decoration: const InputDecoration(
border: UnderlineInputBorder(),
labelText: 'Kréta api hostname(:port)',
),
onChanged: (v) {
initData.settings.customHost = v;
},
),
),
SizedBox(height: 10),
Container(
width: double.infinity,
height: 48,
padding: const EdgeInsets.symmetric(vertical: 8),
decoration: ShapeDecoration(
color: const Color(0xFFA7DB21), // Accent-Accent
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
shadows: const [
BoxShadow(
color: Color(0x33647E22),
blurRadius: 2,
offset: Offset(0, 1),
spreadRadius: 0,
)
],
),
child: GestureDetector(
child: Center(
child: Text(
'Set hostname',
textAlign: TextAlign.center,
style: const TextStyle(
color: Color(0xFF394B0A), // Text-Primary
fontSize: 17,
fontFamily: 'Montserrat',
fontVariations: [
FontVariation('wght', 700),
],
letterSpacing: -0.30,
),
),
),
onTap: () {
if (initData.settings.customHost != null
&& initData.settings.customHost != "") {
var host = initData.settings.customHost!;
KretaEndpoints.kretaBase = "https://$host";
KretaEndpoints.kretaIdp = KretaEndpoints.kretaBase;
KretaEndpoints.kretaLoginUrl =
"${KretaEndpoints.kretaIdp}/Account/Login?ReturnUrl=%2Fconnect%2Fauthorize%2Fcallback%3Fprompt%3Dlogin%26nonce%3DwylCrqT4oN6PPgQn2yQB0euKei9nJeZ6_ffJ-VpSKZU%26response_type%3Dcode%26code_challenge_method%3DS256%26scope%3Dopenid%2520email%2520offline_access%2520kreta-ellenorzo-webapi.public%2520kreta-eugyintezes-webapi.public%2520kreta-fileservice-webapi.public%2520kreta-mobile-global-webapi.public%2520kreta-dkt-webapi.public%2520kreta-ier-webapi.public%26code_challenge%3DHByZRRnPGb-Ko_wTI7ibIba1HQ6lor0ws4bcgReuYSQ%26redirect_uri%3Dhttps%253A%252F%252Fmobil.e-kreta.hu%252Fellenorzo-student%252Fprod%252Foauthredirect%26client_id%3Dkreta-ellenorzo-student-mobile-ios%26state%3Dkreta_student_mobile%26suppressed_prompt%3Dlogin";
KretaEndpoints.tokenGrantUrl =
"${KretaEndpoints.kretaIdp}/connect/token";
initData.settings.useCustomHost = true;
} else {
KretaEndpoints.kretaBase = "e-kreta.hu";
KretaEndpoints.kretaIdp = "https://idp.e-kreta.hu";
KretaEndpoints.kretaLoginUrl = "${KretaEndpoints.kretaIdp}/Account/Login?ReturnUrl=%2Fconnect%2Fauthorize%2Fcallback%3Fprompt%3Dlogin%26nonce%3DwylCrqT4oN6PPgQn2yQB0euKei9nJeZ6_ffJ-VpSKZU%26response_type%3Dcode%26code_challenge_method%3DS256%26scope%3Dopenid%2520email%2520offline_access%2520kreta-ellenorzo-webapi.public%2520kreta-eugyintezes-webapi.public%2520kreta-fileservice-webapi.public%2520kreta-mobile-global-webapi.public%2520kreta-dkt-webapi.public%2520kreta-ier-webapi.public%26code_challenge%3DHByZRRnPGb-Ko_wTI7ibIba1HQ6lor0ws4bcgReuYSQ%26redirect_uri%3Dhttps%253A%252F%252Fmobil.e-kreta.hu%252Fellenorzo-student%252Fprod%252Foauthredirect%26client_id%3Dkreta-ellenorzo-student-mobile-ios%26state%3Dkreta_student_mobile%26suppressed_prompt%3Dlogin";
KretaEndpoints.tokenGrantUrl = "${KretaEndpoints.kretaIdp}/connect/token";
initData.settings.useCustomHost = false;
}
// TODO: Fix this
initData.saveSettings();
setState(() {
_webViewController.loadRequest(Uri.parse(KretaEndpoints.kretaLoginUrl));
});
Navigator.pop(context);
},
)
),
// TODO: fix this insane shitcode
SizedBox(height: MediaQuery.of(context).viewInsets.bottom * 1000),
SizedBox(height: 75),
],
),
),
),
),
],
);
},
);
});
}
@override
Widget build(BuildContext context) {
final paddingWidthHorizontal = MediaQuery.of(context).size.width -
@ -357,19 +493,27 @@ class _LoginScreenState extends State<LoginScreen> {
),
),
const SizedBox(height: 20),
Text(
AppLocalizations.of(context)!.privacyLabel,
textAlign: TextAlign.center,
style: const TextStyle(
color: Color(0x7F394C0A) /* Text-Teritary */,
fontSize: 14,
fontFamily: 'Montserrat',
fontVariations: [
FontVariation('wght', 500),
],
height: 1.30,
GestureDetector(
child: Text(
AppLocalizations.of(context)!.privacyLabel,
textAlign: TextAlign.center,
style: const TextStyle(
color: Color(0x7F394C0A) /* Text-Teritary */,
fontSize: 14,
fontFamily: 'Montserrat',
fontVariations: [
FontVariation('wght', 500),
],
height: 1.30,
),
),
),
onTapDown: (_) {
startTimer();
},
onTapUp: (_) {
_timer.cancel();
},
)
],
),
),

View File

@ -1,6 +1,7 @@
import 'dart:async';
import 'dart:math';
import 'package:firka/ui/widget/class_icon_widget.dart';
import 'package:flutter_arc_text/flutter_arc_text.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:firka/helpers/api/model/timetable.dart';
@ -72,10 +73,12 @@ class _WearHomeScreenState extends State<WearHomeScreen> {
});
}
List<Widget> buildBody(BuildContext context, WearMode mode) {
(List<Widget>, double) buildBody(BuildContext context, WearMode mode) {
ScreenUtil.init(context);
var body = List<Widget>.empty(growable: true);
if (!init) {
return body;
return (body, 255.h);
}
if (today.isEmpty && apiError != "") {
@ -85,7 +88,7 @@ class _WearHomeScreenState extends State<WearHomeScreen> {
textAlign: TextAlign.center,
));
return body;
return (body, 255.h);
}
if (today.isEmpty) {
body.add(Text(
@ -95,7 +98,7 @@ class _WearHomeScreenState extends State<WearHomeScreen> {
));
platform.invokeMethod('activity_cancel');
return body;
return (body, 255.h);
}
if (now.isAfter(today.last.end)) {
body.add(Text(
@ -105,7 +108,7 @@ class _WearHomeScreenState extends State<WearHomeScreen> {
));
platform.invokeMethod('activity_cancel');
return body;
return (body, 300.h);
}
if (now.isBefore(today.first.start)) {
var untilFirst = today.first.start.difference(now);
@ -117,13 +120,15 @@ class _WearHomeScreenState extends State<WearHomeScreen> {
));
platform.invokeMethod('activity_update');
return body;
return (body, 255.h);
}
currentLessonNo = null;
if (now.isAfter(today.first.start)
&& now.isBefore(today.last.end)) {
Lesson? currentLesson;
Lesson? lastLesson; // last as in the last lesson that you've been to
Lesson? next;
Lesson? nextLesson;
Duration? currentBreak;
Duration? currentBreakProgress;
for (int i = 0; i < today.length; i++) {
@ -131,6 +136,8 @@ class _WearHomeScreenState extends State<WearHomeScreen> {
if (now.isAfter(lesson.start) && now.isBefore(lesson.end)) {
currentLesson = lesson;
currentLessonNo = i+1;
if (i+2 < today.length) nextLesson = today[i+1];
break;
}
if (now.isAfter(lesson.end)) {
@ -172,6 +179,7 @@ class _WearHomeScreenState extends State<WearHomeScreen> {
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(height: 55.h),
Center(
child: Text(
AppLocalizations.of(context)!.breakTxt,
@ -203,7 +211,7 @@ class _WearHomeScreenState extends State<WearHomeScreen> {
));
platform.invokeMethod('activity_update');
return body;
return (body, 200.h);
} else {
var duration = currentLesson.start.difference(currentLesson.end);
var elapsed = currentLesson.start.difference(now);
@ -211,6 +219,24 @@ class _WearHomeScreenState extends State<WearHomeScreen> {
var minutes = timeLeft.inMinutes + 1;
Widget nextLessonWidget = SizedBox();
if (nextLesson != null) {
nextLessonWidget = Center(
child: Text(
"${nextLesson.name}, ${nextLesson.roomName}",
style: TextStyle(
color: wearColors.textPrimary,
fontSize: 12,
fontFamily: 'Montserrat',
fontVariations: [
FontVariation('wght', 400),
],
),
),
);
}
body.add(CustomPaint(
painter: CircularProgressPainter(
progress: elapsed.inMilliseconds / duration.inMilliseconds,
@ -222,11 +248,14 @@ class _WearHomeScreenState extends State<WearHomeScreen> {
),
child: Column(
children: [
SizedBox(height: nextLesson == null ? 20.h : 0),
Center(
child: Majesticon(
Majesticon.bookSolid, // TODO: placeholder
child: ClassIconWidget(
color: wearColors.accent,
size: 12
size: 16,
uid: currentLesson.uid,
className: currentLesson.name,
category: currentLesson.subject?.name ?? '',
).build(context),
),
const SizedBox(height: 4),
@ -257,25 +286,13 @@ class _WearHomeScreenState extends State<WearHomeScreen> {
),
),
const SizedBox(height: 8),
Center(
child: Text(
"→ meow meow :3",
style: TextStyle(
color: wearColors.textPrimary,
fontSize: 12,
fontFamily: 'Montserrat',
fontVariations: [
FontVariation('wght', 400),
],
),
),
),
nextLessonWidget,
]
)
));
platform.invokeMethod('activity_update');
return body;
return (body, 200.h);
}
}
@ -285,8 +302,6 @@ class _WearHomeScreenState extends State<WearHomeScreen> {
@override
Widget build(BuildContext context) {
ScreenUtil.init(context);
Widget titleBar = SizedBox();
if (currentLessonNo != null) {
@ -336,16 +351,18 @@ class _WearHomeScreenState extends State<WearHomeScreen> {
});
});
}
var (body, padding) = buildBody(context, mode);
return Column(
mainAxisAlignment: MainAxisAlignment.center,
// children: buildBody(context, mode),
children: <Widget>[
Container(
padding: EdgeInsets.only(top: 255.h),
padding: EdgeInsets.only(top: padding),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
...buildBody(context, mode)
...body
],
)
),

View File

@ -76,7 +76,7 @@ class CircularProgressPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
final center = Offset(screenSize.width / 2, screenSize.height / 7.4);
final center = Offset(screenSize.width / 2, screenSize.height / 4.7);
final radius = min(screenSize.width, screenSize.height) / 2 - strokeWidth / 2;
final startAngle = -pi / 2;
var sweepAngle = 2 * pi * progress;

View File

@ -22,7 +22,7 @@ class ClassIconWidget extends StatelessWidget {
Widget build(BuildContext context) {
var iconCategory = getIconType(_uid, _className, _category);
return Majesticon(getIconData(iconCategory!), color: color, size: size);
return Majesticon(getIconData(iconCategory), color: color, size: size);
}
}