forked from firka/student-legacy
commit
4b93c891c8
@ -53,9 +53,14 @@ class FilcAPI {
|
|||||||
.map((json) => School.fromJson(json))
|
.map((json) => School.fromJson(json))
|
||||||
.toList();
|
.toList();
|
||||||
schools.add(School(
|
schools.add(School(
|
||||||
city: "Tiszabura",
|
city: "Stockholm",
|
||||||
instituteCode: "supporttest-reni-tiszabura-teszt01",
|
instituteCode: "refilc-test-sweden",
|
||||||
name: "FILC Éles Reni tiszabura-teszt",
|
name: "reFilc Test SE - Leo Ekström High School",
|
||||||
|
));
|
||||||
|
schools.add(School(
|
||||||
|
city: "Madrid",
|
||||||
|
instituteCode: "refilc-test-spain",
|
||||||
|
name: "reFilc Test ES - Emilio Obrero University",
|
||||||
));
|
));
|
||||||
return schools;
|
return schools;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// ignore_for_file: avoid_print, use_build_context_synchronously
|
// ignore_for_file: avoid_print, use_build_context_synchronously
|
||||||
|
|
||||||
import 'package:filcnaplo/utils/jwt.dart';
|
import 'package:filcnaplo/utils/jwt.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/school.dart';
|
||||||
import 'package:filcnaplo_kreta_api/providers/absence_provider.dart';
|
import 'package:filcnaplo_kreta_api/providers/absence_provider.dart';
|
||||||
import 'package:filcnaplo_kreta_api/providers/event_provider.dart';
|
import 'package:filcnaplo_kreta_api/providers/event_provider.dart';
|
||||||
import 'package:filcnaplo_kreta_api/providers/exam_provider.dart';
|
import 'package:filcnaplo_kreta_api/providers/exam_provider.dart';
|
||||||
@ -20,6 +21,7 @@ import 'package:filcnaplo_kreta_api/models/week.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:filcnaplo/api/nonce.dart';
|
import 'package:filcnaplo/api/nonce.dart';
|
||||||
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
enum LoginState {
|
enum LoginState {
|
||||||
missingFields,
|
missingFields,
|
||||||
@ -47,87 +49,141 @@ Future loginAPI({
|
|||||||
void Function(User)? onLogin,
|
void Function(User)? onLogin,
|
||||||
void Function()? onSuccess,
|
void Function()? onSuccess,
|
||||||
}) async {
|
}) async {
|
||||||
Provider.of<KretaClient>(context, listen: false).userAgent =
|
Future testLogin(School school) async {
|
||||||
Provider.of<SettingsProvider>(context, listen: false).config.userAgent;
|
var user = User(
|
||||||
|
username: username,
|
||||||
|
password: password,
|
||||||
|
instituteCode: instituteCode,
|
||||||
|
name: 'Teszt Lajos',
|
||||||
|
student: Student(
|
||||||
|
birth: DateTime.now(),
|
||||||
|
id: const Uuid().v4(),
|
||||||
|
name: 'Teszt Lajos',
|
||||||
|
school: school,
|
||||||
|
yearId: '1',
|
||||||
|
parents: ['Teszt András', 'Teszt Linda'],
|
||||||
|
json: {"a": "b"},
|
||||||
|
address: '1117 Budapest, Gábor Dénes utca 4.',
|
||||||
|
),
|
||||||
|
role: Role.parent,
|
||||||
|
);
|
||||||
|
|
||||||
Map<String, String> headers = {
|
if (onLogin != null) onLogin(user);
|
||||||
"content-type": "application/x-www-form-urlencoded",
|
|
||||||
};
|
|
||||||
|
|
||||||
String nonceStr = await Provider.of<KretaClient>(context, listen: false)
|
// store test user in db
|
||||||
.getAPI(KretaAPI.nonce, json: false);
|
await Provider.of<DatabaseProvider>(context, listen: false)
|
||||||
|
.store
|
||||||
|
.storeUser(user);
|
||||||
|
Provider.of<UserProvider>(context, listen: false).addUser(user);
|
||||||
|
Provider.of<UserProvider>(context, listen: false).setUser(user.id);
|
||||||
|
|
||||||
Nonce nonce = getNonce(nonceStr, username, instituteCode);
|
if (onSuccess != null) onSuccess();
|
||||||
headers.addAll(nonce.header());
|
|
||||||
|
|
||||||
Map? res = await Provider.of<KretaClient>(context, listen: false)
|
return LoginState.success;
|
||||||
.postAPI(KretaAPI.login,
|
}
|
||||||
headers: headers,
|
|
||||||
body: User.loginBody(
|
|
||||||
username: username,
|
|
||||||
password: password,
|
|
||||||
instituteCode: instituteCode,
|
|
||||||
));
|
|
||||||
if (res != null) {
|
|
||||||
if (res.containsKey("error")) {
|
|
||||||
if (res["error"] == "invalid_grant") {
|
|
||||||
return LoginState.invalidGrant;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (res.containsKey("access_token")) {
|
|
||||||
try {
|
|
||||||
Provider.of<KretaClient>(context, listen: false).accessToken =
|
|
||||||
res["access_token"];
|
|
||||||
Map? studentJson =
|
|
||||||
await Provider.of<KretaClient>(context, listen: false)
|
|
||||||
.getAPI(KretaAPI.student(instituteCode));
|
|
||||||
Student student = Student.fromJson(studentJson!);
|
|
||||||
var user = User(
|
|
||||||
username: username,
|
|
||||||
password: password,
|
|
||||||
instituteCode: instituteCode,
|
|
||||||
name: student.name,
|
|
||||||
student: student,
|
|
||||||
role: JwtUtils.getRoleFromJWT(res["access_token"])!,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (onLogin != null) onLogin(user);
|
// if institute matches one of test things do test login
|
||||||
|
if (instituteCode == 'refilc-test-sweden') {
|
||||||
|
School school = School(
|
||||||
|
city: "Stockholm",
|
||||||
|
instituteCode: "refilc-test-sweden",
|
||||||
|
name: "reFilc Test SE - Leo Ekström High School",
|
||||||
|
);
|
||||||
|
|
||||||
// Store User in the database
|
await testLogin(school);
|
||||||
await Provider.of<DatabaseProvider>(context, listen: false)
|
} else if (instituteCode == 'refilc-test-spain') {
|
||||||
.store
|
School school = School(
|
||||||
.storeUser(user);
|
city: "Madrid",
|
||||||
Provider.of<UserProvider>(context, listen: false).addUser(user);
|
instituteCode: "refilc-test-spain",
|
||||||
Provider.of<UserProvider>(context, listen: false).setUser(user.id);
|
name: "reFilc Test ES - Emilio Obrero University",
|
||||||
|
);
|
||||||
|
|
||||||
// Get user data
|
await testLogin(school);
|
||||||
|
} else {
|
||||||
|
// normal login from here
|
||||||
|
Provider.of<KretaClient>(context, listen: false).userAgent =
|
||||||
|
Provider.of<SettingsProvider>(context, listen: false).config.userAgent;
|
||||||
|
|
||||||
|
Map<String, String> headers = {
|
||||||
|
"content-type": "application/x-www-form-urlencoded",
|
||||||
|
};
|
||||||
|
|
||||||
|
String nonceStr = await Provider.of<KretaClient>(context, listen: false)
|
||||||
|
.getAPI(KretaAPI.nonce, json: false);
|
||||||
|
|
||||||
|
Nonce nonce = getNonce(nonceStr, username, instituteCode);
|
||||||
|
headers.addAll(nonce.header());
|
||||||
|
|
||||||
|
Map? res = await Provider.of<KretaClient>(context, listen: false)
|
||||||
|
.postAPI(KretaAPI.login,
|
||||||
|
headers: headers,
|
||||||
|
body: User.loginBody(
|
||||||
|
username: username,
|
||||||
|
password: password,
|
||||||
|
instituteCode: instituteCode,
|
||||||
|
));
|
||||||
|
if (res != null) {
|
||||||
|
if (res.containsKey("error")) {
|
||||||
|
if (res["error"] == "invalid_grant") {
|
||||||
|
return LoginState.invalidGrant;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (res.containsKey("access_token")) {
|
||||||
try {
|
try {
|
||||||
await Future.wait([
|
Provider.of<KretaClient>(context, listen: false).accessToken =
|
||||||
Provider.of<GradeProvider>(context, listen: false).fetch(),
|
res["access_token"];
|
||||||
Provider.of<TimetableProvider>(context, listen: false)
|
Map? studentJson =
|
||||||
.fetch(week: Week.current()),
|
await Provider.of<KretaClient>(context, listen: false)
|
||||||
Provider.of<ExamProvider>(context, listen: false).fetch(),
|
.getAPI(KretaAPI.student(instituteCode));
|
||||||
Provider.of<HomeworkProvider>(context, listen: false).fetch(),
|
Student student = Student.fromJson(studentJson!);
|
||||||
Provider.of<MessageProvider>(context, listen: false).fetchAll(),
|
var user = User(
|
||||||
Provider.of<NoteProvider>(context, listen: false).fetch(),
|
username: username,
|
||||||
Provider.of<EventProvider>(context, listen: false).fetch(),
|
password: password,
|
||||||
Provider.of<AbsenceProvider>(context, listen: false).fetch(),
|
instituteCode: instituteCode,
|
||||||
]);
|
name: student.name,
|
||||||
|
student: student,
|
||||||
|
role: JwtUtils.getRoleFromJWT(res["access_token"])!,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (onLogin != null) onLogin(user);
|
||||||
|
|
||||||
|
// Store User in the database
|
||||||
|
await Provider.of<DatabaseProvider>(context, listen: false)
|
||||||
|
.store
|
||||||
|
.storeUser(user);
|
||||||
|
Provider.of<UserProvider>(context, listen: false).addUser(user);
|
||||||
|
Provider.of<UserProvider>(context, listen: false).setUser(user.id);
|
||||||
|
|
||||||
|
// Get user data
|
||||||
|
try {
|
||||||
|
await Future.wait([
|
||||||
|
Provider.of<GradeProvider>(context, listen: false).fetch(),
|
||||||
|
Provider.of<TimetableProvider>(context, listen: false)
|
||||||
|
.fetch(week: Week.current()),
|
||||||
|
Provider.of<ExamProvider>(context, listen: false).fetch(),
|
||||||
|
Provider.of<HomeworkProvider>(context, listen: false).fetch(),
|
||||||
|
Provider.of<MessageProvider>(context, listen: false).fetchAll(),
|
||||||
|
Provider.of<NoteProvider>(context, listen: false).fetch(),
|
||||||
|
Provider.of<EventProvider>(context, listen: false).fetch(),
|
||||||
|
Provider.of<AbsenceProvider>(context, listen: false).fetch(),
|
||||||
|
]);
|
||||||
|
} catch (error) {
|
||||||
|
print("WARNING: failed to fetch user data: $error");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (onSuccess != null) onSuccess();
|
||||||
|
|
||||||
|
return LoginState.success;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
print("WARNING: failed to fetch user data: $error");
|
print("ERROR: loginAPI: $error");
|
||||||
|
// maybe check debug mode
|
||||||
|
// ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("ERROR: $error")));
|
||||||
|
return LoginState.failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (onSuccess != null) onSuccess();
|
|
||||||
|
|
||||||
return LoginState.success;
|
|
||||||
} catch (error) {
|
|
||||||
print("ERROR: loginAPI: $error");
|
|
||||||
// maybe check debug mode
|
|
||||||
// ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("ERROR: $error")));
|
|
||||||
return LoginState.failed;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return LoginState.failed;
|
return LoginState.failed;
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:connectivity_plus/connectivity_plus.dart';
|
import 'package:connectivity_plus/connectivity_plus.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
@ -12,6 +14,7 @@ class StatusProvider extends ChangeNotifier {
|
|||||||
|
|
||||||
StatusProvider() {
|
StatusProvider() {
|
||||||
_handleNetworkChanges();
|
_handleNetworkChanges();
|
||||||
|
_handleDNSFailure();
|
||||||
Connectivity().checkConnectivity().then((value) => _networkType = value);
|
Connectivity().checkConnectivity().then((value) => _networkType = value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,6 +27,7 @@ class StatusProvider extends ChangeNotifier {
|
|||||||
_networkType = event;
|
_networkType = event;
|
||||||
if (event == ConnectivityResult.none) {
|
if (event == ConnectivityResult.none) {
|
||||||
if (!_stack.contains(Status.network)) {
|
if (!_stack.contains(Status.network)) {
|
||||||
|
_stack.remove(Status.apiError);
|
||||||
_stack.insert(0, Status.network);
|
_stack.insert(0, Status.network);
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
@ -36,6 +40,31 @@ class StatusProvider extends ChangeNotifier {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _handleDNSFailure() {
|
||||||
|
try {
|
||||||
|
InternetAddress.lookup('api.refilc.hu').then((status) {
|
||||||
|
if (status.isEmpty) {
|
||||||
|
if (!_stack.contains(Status.network)) {
|
||||||
|
_stack.remove(Status.apiError);
|
||||||
|
_stack.insert(0, Status.network);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (_stack.contains(Status.network)) {
|
||||||
|
_stack.remove(Status.network);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} on SocketException catch (_) {
|
||||||
|
if (!_stack.contains(Status.network)) {
|
||||||
|
_stack.remove(Status.apiError);
|
||||||
|
_stack.insert(0, Status.network);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void triggerRequest(http.Response res) {
|
void triggerRequest(http.Response res) {
|
||||||
if (res.headers.containsKey("x-maintenance-mode") ||
|
if (res.headers.containsKey("x-maintenance-mode") ||
|
||||||
res.statusCode == 503) {
|
res.statusCode == 503) {
|
||||||
@ -50,6 +79,7 @@ class StatusProvider extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_stack.contains(Status.network)) return;
|
||||||
if (res.body == "invalid_grant" ||
|
if (res.body == "invalid_grant" ||
|
||||||
res.body.replaceAll(' ', '') == '' ||
|
res.body.replaceAll(' ', '') == '' ||
|
||||||
res.statusCode == 400) {
|
res.statusCode == 400) {
|
||||||
|
@ -33,6 +33,7 @@ const settingsDB = DatabaseStruct("settings", {
|
|||||||
"renamed_subjects_italics": int, "renamed_teachers_enabled": int,
|
"renamed_subjects_italics": int, "renamed_teachers_enabled": int,
|
||||||
"renamed_teachers_italics": int,
|
"renamed_teachers_italics": int,
|
||||||
"live_activity_color": String,
|
"live_activity_color": String,
|
||||||
|
"welcome_message": String,
|
||||||
});
|
});
|
||||||
// DON'T FORGET TO UPDATE DEFAULT VALUES IN `initDB` MIGRATION OR ELSE PARENTS WILL COMPLAIN ABOUT THEIR CHILDREN MISSING
|
// DON'T FORGET TO UPDATE DEFAULT VALUES IN `initDB` MIGRATION OR ELSE PARENTS WILL COMPLAIN ABOUT THEIR CHILDREN MISSING
|
||||||
// YOU'VE BEEN WARNED!!!
|
// YOU'VE BEEN WARNED!!!
|
||||||
|
@ -20,7 +20,6 @@ class Ad {
|
|||||||
});
|
});
|
||||||
|
|
||||||
factory Ad.fromJson(Map json) {
|
factory Ad.fromJson(Map json) {
|
||||||
print(json);
|
|
||||||
return Ad(
|
return Ad(
|
||||||
title: json['title'] ?? 'Ad',
|
title: json['title'] ?? 'Ad',
|
||||||
description: json['description'] ?? '',
|
description: json['description'] ?? '',
|
||||||
|
@ -76,6 +76,7 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
bool _renamedTeachersEnabled;
|
bool _renamedTeachersEnabled;
|
||||||
bool _renamedTeachersItalics;
|
bool _renamedTeachersItalics;
|
||||||
Color _liveActivityColor;
|
Color _liveActivityColor;
|
||||||
|
String _welcomeMessage;
|
||||||
|
|
||||||
SettingsProvider({
|
SettingsProvider({
|
||||||
DatabaseProvider? database,
|
DatabaseProvider? database,
|
||||||
@ -120,6 +121,7 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
required bool renameTeachersEnabled,
|
required bool renameTeachersEnabled,
|
||||||
required bool renameTeachersItalics,
|
required bool renameTeachersItalics,
|
||||||
required Color liveActivityColor,
|
required Color liveActivityColor,
|
||||||
|
required String welcomeMessage,
|
||||||
}) : _database = database,
|
}) : _database = database,
|
||||||
_language = language,
|
_language = language,
|
||||||
_startPage = startPage,
|
_startPage = startPage,
|
||||||
@ -161,7 +163,8 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
_renamedSubjectsItalics = renameSubjectsItalics,
|
_renamedSubjectsItalics = renameSubjectsItalics,
|
||||||
_renamedTeachersEnabled = renameTeachersEnabled,
|
_renamedTeachersEnabled = renameTeachersEnabled,
|
||||||
_renamedTeachersItalics = renameTeachersItalics,
|
_renamedTeachersItalics = renameTeachersItalics,
|
||||||
_liveActivityColor = liveActivityColor;
|
_liveActivityColor = liveActivityColor,
|
||||||
|
_welcomeMessage = welcomeMessage;
|
||||||
|
|
||||||
factory SettingsProvider.fromMap(Map map,
|
factory SettingsProvider.fromMap(Map map,
|
||||||
{required DatabaseProvider database}) {
|
{required DatabaseProvider database}) {
|
||||||
@ -223,6 +226,7 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
renameTeachersEnabled: map["renamed_teachers_enabled"] == 1,
|
renameTeachersEnabled: map["renamed_teachers_enabled"] == 1,
|
||||||
renameTeachersItalics: map["renamed_teachers_italics"] == 1,
|
renameTeachersItalics: map["renamed_teachers_italics"] == 1,
|
||||||
liveActivityColor: Color(map["live_activity_color"]),
|
liveActivityColor: Color(map["live_activity_color"]),
|
||||||
|
welcomeMessage: map["welcome_message"],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,6 +276,7 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
"renamed_teachers_enabled": _renamedTeachersEnabled ? 1 : 0,
|
"renamed_teachers_enabled": _renamedTeachersEnabled ? 1 : 0,
|
||||||
"renamed_teachers_italics": _renamedTeachersItalics ? 1 : 0,
|
"renamed_teachers_italics": _renamedTeachersItalics ? 1 : 0,
|
||||||
"live_activity_color": _liveActivityColor.value,
|
"live_activity_color": _liveActivityColor.value,
|
||||||
|
"welcome_message": _welcomeMessage,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -325,6 +330,7 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
renameTeachersEnabled: false,
|
renameTeachersEnabled: false,
|
||||||
renameTeachersItalics: false,
|
renameTeachersItalics: false,
|
||||||
liveActivityColor: const Color(0xFF676767),
|
liveActivityColor: const Color(0xFF676767),
|
||||||
|
welcomeMessage: '',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -373,6 +379,7 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
bool get renamedTeachersEnabled => _renamedTeachersEnabled;
|
bool get renamedTeachersEnabled => _renamedTeachersEnabled;
|
||||||
bool get renamedTeachersItalics => _renamedTeachersItalics;
|
bool get renamedTeachersItalics => _renamedTeachersItalics;
|
||||||
Color get liveActivityColor => _liveActivityColor;
|
Color get liveActivityColor => _liveActivityColor;
|
||||||
|
String get welcomeMessage => _welcomeMessage;
|
||||||
|
|
||||||
Future<void> update({
|
Future<void> update({
|
||||||
bool store = true,
|
bool store = true,
|
||||||
@ -417,6 +424,7 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
bool? renamedTeachersEnabled,
|
bool? renamedTeachersEnabled,
|
||||||
bool? renamedTeachersItalics,
|
bool? renamedTeachersItalics,
|
||||||
Color? liveActivityColor,
|
Color? liveActivityColor,
|
||||||
|
String? welcomeMessage,
|
||||||
}) async {
|
}) async {
|
||||||
if (language != null && language != _language) _language = language;
|
if (language != null && language != _language) _language = language;
|
||||||
if (startPage != null && startPage != _startPage) _startPage = startPage;
|
if (startPage != null && startPage != _startPage) _startPage = startPage;
|
||||||
@ -535,6 +543,9 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
if (liveActivityColor != null && liveActivityColor != _liveActivityColor) {
|
if (liveActivityColor != null && liveActivityColor != _liveActivityColor) {
|
||||||
_liveActivityColor = liveActivityColor;
|
_liveActivityColor = liveActivityColor;
|
||||||
}
|
}
|
||||||
|
if (welcomeMessage != null && welcomeMessage != _welcomeMessage) {
|
||||||
|
_welcomeMessage = welcomeMessage;
|
||||||
|
}
|
||||||
if (store) await _database?.store.storeSettings(this);
|
if (store) await _database?.store.storeSettings(this);
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
@ -93,4 +93,13 @@ class User {
|
|||||||
"refresh_user_data": "false",
|
"refresh_user_data": "false",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Map<String, Object?> logoutBody({
|
||||||
|
required String refreshToken,
|
||||||
|
}) {
|
||||||
|
return {
|
||||||
|
"refresh_token": refreshToken,
|
||||||
|
"client_id": KretaAPI.clientId,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ description: "Nem hivatalos e-napló alkalmazás az e-Kréta rendszerhez"
|
|||||||
homepage: https://refilc.hu
|
homepage: https://refilc.hu
|
||||||
publish_to: "none"
|
publish_to: "none"
|
||||||
|
|
||||||
version: 4.2.3+223
|
version: 4.2.4+224
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.17.0 <3.0.0"
|
sdk: ">=2.17.0 <3.0.0"
|
||||||
|
@ -176,13 +176,16 @@ class _SidebarState extends State<Sidebar> {
|
|||||||
String? userId = user.id;
|
String? userId = user.id;
|
||||||
if (userId == null) return;
|
if (userId == null) return;
|
||||||
|
|
||||||
// Delete User
|
// revoke refresh token
|
||||||
|
await Provider.of<KretaClient>(context, listen: false).logout();
|
||||||
|
|
||||||
|
// delete user from app
|
||||||
user.removeUser(userId);
|
user.removeUser(userId);
|
||||||
await Provider.of<DatabaseProvider>(context, listen: false)
|
await Provider.of<DatabaseProvider>(context, listen: false)
|
||||||
.store
|
.store
|
||||||
.removeUser(userId);
|
.removeUser(userId);
|
||||||
|
|
||||||
// If no other Users left, go back to LoginScreen
|
// if no other users left, go back to login screen
|
||||||
if (user.getUsers().isNotEmpty) {
|
if (user.getUsers().isNotEmpty) {
|
||||||
user.setUser(user.getUsers().first.id);
|
user.setUser(user.getUsers().first.id);
|
||||||
restore().then((_) => user.setUser(user.getUsers().first.id));
|
restore().then((_) => user.setUser(user.getUsers().first.id));
|
||||||
|
@ -5,7 +5,7 @@ extension SettingsLocalization on String {
|
|||||||
{
|
{
|
||||||
"en_en": {
|
"en_en": {
|
||||||
"personal_details": "Personal Details",
|
"personal_details": "Personal Details",
|
||||||
"open_dkt": "Open DKT",
|
"open_dkt": "Open DCS",
|
||||||
"edit_nickname": "Edit Nickname",
|
"edit_nickname": "Edit Nickname",
|
||||||
"edit_profile_picture": "Edit Profile Picture",
|
"edit_profile_picture": "Edit Profile Picture",
|
||||||
"remove_profile_picture": "Remove Profile Picture",
|
"remove_profile_picture": "Remove Profile Picture",
|
||||||
@ -39,7 +39,8 @@ extension SettingsLocalization on String {
|
|||||||
"done": "Done",
|
"done": "Done",
|
||||||
"reset": "Reset",
|
"reset": "Reset",
|
||||||
"open": "Open",
|
"open": "Open",
|
||||||
"data_collected": "Data collected: Platform (eg. Android), App version (eg. 3.0.0), Unique Install Identifier",
|
"data_collected":
|
||||||
|
"Data collected: Platform (eg. Android), App version (eg. 3.0.0), Unique Install Identifier",
|
||||||
"Analytics": "Analytics",
|
"Analytics": "Analytics",
|
||||||
"Anonymous Usage Analytics": "Anonymous Usage Analytics",
|
"Anonymous Usage Analytics": "Anonymous Usage Analytics",
|
||||||
"graph_class_avg": "Class average on graph",
|
"graph_class_avg": "Class average on graph",
|
||||||
@ -98,7 +99,8 @@ extension SettingsLocalization on String {
|
|||||||
"done": "Kész",
|
"done": "Kész",
|
||||||
"reset": "Visszaállítás",
|
"reset": "Visszaállítás",
|
||||||
"open": "Megnyitás",
|
"open": "Megnyitás",
|
||||||
"data_collected": "Gyűjtött adat: Platform (pl. Android), App verzió (pl. 3.0.0), Egyedi telepítési azonosító",
|
"data_collected":
|
||||||
|
"Gyűjtött adat: Platform (pl. Android), App verzió (pl. 3.0.0), Egyedi telepítési azonosító",
|
||||||
"Analytics": "Analitika",
|
"Analytics": "Analitika",
|
||||||
"Anonymous Usage Analytics": "Névtelen használati analitika",
|
"Anonymous Usage Analytics": "Névtelen használati analitika",
|
||||||
"graph_class_avg": "Osztályátlag a grafikonon",
|
"graph_class_avg": "Osztályátlag a grafikonon",
|
||||||
@ -123,7 +125,7 @@ extension SettingsLocalization on String {
|
|||||||
},
|
},
|
||||||
"de_de": {
|
"de_de": {
|
||||||
"personal_details": "Persönliche Angaben",
|
"personal_details": "Persönliche Angaben",
|
||||||
"open_dkt": "Öffnen DKT",
|
"open_dkt": "Öffnen RDZ",
|
||||||
"edit_nickname": "Spitznamen bearbeiten",
|
"edit_nickname": "Spitznamen bearbeiten",
|
||||||
"edit_profile_picture": "Profilbild bearbeiten",
|
"edit_profile_picture": "Profilbild bearbeiten",
|
||||||
"remove_profile_picture": "Profilbild entfernen",
|
"remove_profile_picture": "Profilbild entfernen",
|
||||||
@ -157,7 +159,8 @@ extension SettingsLocalization on String {
|
|||||||
"done": "Fertig",
|
"done": "Fertig",
|
||||||
"reset": "Zurücksetzen",
|
"reset": "Zurücksetzen",
|
||||||
"open": "Öffnen",
|
"open": "Öffnen",
|
||||||
"data_collected": "Erhobene Daten: Plattform (z.B. Android), App version (z.B. 3.0.0), Eindeutige Installationskennung",
|
"data_collected":
|
||||||
|
"Erhobene Daten: Plattform (z.B. Android), App version (z.B. 3.0.0), Eindeutige Installationskennung",
|
||||||
"Analytics": "Analytik",
|
"Analytics": "Analytik",
|
||||||
"Anonymous Usage Analytics": "Anonyme Nutzungsanalyse",
|
"Anonymous Usage Analytics": "Anonyme Nutzungsanalyse",
|
||||||
"graph_class_avg": "Klassendurchschnitt in der Grafik",
|
"graph_class_avg": "Klassendurchschnitt in der Grafik",
|
||||||
|
@ -3,6 +3,7 @@ import 'package:intl/intl.dart';
|
|||||||
class KretaAPI {
|
class KretaAPI {
|
||||||
// IDP API
|
// IDP API
|
||||||
static const login = BaseKreta.kretaIdp + KretaApiEndpoints.token;
|
static const login = BaseKreta.kretaIdp + KretaApiEndpoints.token;
|
||||||
|
static const logout = BaseKreta.kretaIdp + KretaApiEndpoints.revoke;
|
||||||
static const nonce = BaseKreta.kretaIdp + KretaApiEndpoints.nonce;
|
static const nonce = BaseKreta.kretaIdp + KretaApiEndpoints.nonce;
|
||||||
static const clientId = "kreta-ellenorzo-mobile-android";
|
static const clientId = "kreta-ellenorzo-mobile-android";
|
||||||
|
|
||||||
@ -86,6 +87,7 @@ class BaseKreta {
|
|||||||
|
|
||||||
class KretaApiEndpoints {
|
class KretaApiEndpoints {
|
||||||
static const token = "/connect/token";
|
static const token = "/connect/token";
|
||||||
|
static const revoke = "/connect/revocation";
|
||||||
static const nonce = "/nonce";
|
static const nonce = "/nonce";
|
||||||
static const notes = "/ellenorzo/V3/Sajat/Feljegyzesek";
|
static const notes = "/ellenorzo/V3/Sajat/Feljegyzesek";
|
||||||
static const events = "/ellenorzo/V3/Sajat/FaliujsagElemek";
|
static const events = "/ellenorzo/V3/Sajat/FaliujsagElemek";
|
||||||
|
@ -26,6 +26,8 @@ class KretaClient {
|
|||||||
late final UserProvider _user;
|
late final UserProvider _user;
|
||||||
late final StatusProvider _status;
|
late final StatusProvider _status;
|
||||||
|
|
||||||
|
bool _loginRefreshing = false;
|
||||||
|
|
||||||
KretaClient({
|
KretaClient({
|
||||||
this.accessToken,
|
this.accessToken,
|
||||||
required SettingsProvider settings,
|
required SettingsProvider settings,
|
||||||
@ -164,6 +166,9 @@ class KretaClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> refreshLogin() async {
|
Future<void> refreshLogin() async {
|
||||||
|
if (_loginRefreshing) return;
|
||||||
|
_loginRefreshing = true;
|
||||||
|
|
||||||
User? loginUser = _user.user;
|
User? loginUser = _user.user;
|
||||||
if (loginUser == null) return;
|
if (loginUser == null) return;
|
||||||
|
|
||||||
@ -182,13 +187,15 @@ class KretaClient {
|
|||||||
print("DEBUG: refreshLogin: ${loginUser.id} ${loginUser.name}");
|
print("DEBUG: refreshLogin: ${loginUser.id} ${loginUser.name}");
|
||||||
}
|
}
|
||||||
|
|
||||||
Map? loginRes = await postAPI(KretaAPI.login,
|
Map? loginRes = await postAPI(
|
||||||
headers: headers,
|
KretaAPI.login,
|
||||||
body: User.loginBody(
|
headers: headers,
|
||||||
username: loginUser.username,
|
body: User.loginBody(
|
||||||
password: loginUser.password,
|
username: loginUser.username,
|
||||||
instituteCode: loginUser.instituteCode,
|
password: loginUser.password,
|
||||||
));
|
instituteCode: loginUser.instituteCode,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
if (loginRes != null) {
|
if (loginRes != null) {
|
||||||
if (loginRes.containsKey("access_token")) {
|
if (loginRes.containsKey("access_token")) {
|
||||||
@ -215,5 +222,25 @@ class KretaClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_loginRefreshing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> logout() async {
|
||||||
|
User? loginUser = _user.user;
|
||||||
|
if (loginUser == null) return;
|
||||||
|
|
||||||
|
Map<String, String> headers = {
|
||||||
|
"content-type": "application/x-www-form-urlencoded",
|
||||||
|
};
|
||||||
|
|
||||||
|
await postAPI(
|
||||||
|
KretaAPI.logout,
|
||||||
|
headers: headers,
|
||||||
|
body: User.logoutBody(
|
||||||
|
refreshToken: refreshToken!,
|
||||||
|
),
|
||||||
|
json: false,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import 'package:filcnaplo_kreta_api/client/api.dart';
|
|||||||
import 'package:filcnaplo_kreta_api/client/client.dart';
|
import 'package:filcnaplo_kreta_api/client/client.dart';
|
||||||
import 'package:filcnaplo_kreta_api/models/lesson.dart';
|
import 'package:filcnaplo_kreta_api/models/lesson.dart';
|
||||||
import 'package:filcnaplo_kreta_api/models/week.dart';
|
import 'package:filcnaplo_kreta_api/models/week.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
||||||
class TimetableProvider with ChangeNotifier {
|
class TimetableProvider with ChangeNotifier {
|
||||||
Map<Week, List<Lesson>> lessons = {};
|
Map<Week, List<Lesson>> lessons = {};
|
||||||
@ -69,14 +69,14 @@ class TimetableProvider with ChangeNotifier {
|
|||||||
.getAPI(KretaAPI.timetable(iss, start: week.start, end: week.end));
|
.getAPI(KretaAPI.timetable(iss, start: week.start, end: week.end));
|
||||||
|
|
||||||
if (lessonsJson == null) {
|
if (lessonsJson == null) {
|
||||||
|
if (kDebugMode) print('Cannot fetch Lessons for User ${user.id}');
|
||||||
|
|
||||||
return;
|
return;
|
||||||
// throw "Cannot fetch Lessons for User ${user.id}";
|
// throw "Cannot fetch Lessons for User ${user.id}";
|
||||||
} else {
|
} else {
|
||||||
List<Lesson> lessonsList =
|
List<Lesson> lessonsList =
|
||||||
lessonsJson.map((e) => Lesson.fromJson(e)).toList();
|
lessonsJson.map((e) => Lesson.fromJson(e)).toList();
|
||||||
|
|
||||||
if (lessons.isEmpty) return;
|
|
||||||
|
|
||||||
lessons[week] = lessonsList;
|
lessons[week] = lessonsList;
|
||||||
|
|
||||||
await store();
|
await store();
|
||||||
|
@ -13,9 +13,6 @@ class AdTile extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
print('geic');
|
|
||||||
print(ad);
|
|
||||||
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: padding ?? const EdgeInsets.symmetric(horizontal: 8.0),
|
padding: padding ?? const EdgeInsets.symmetric(horizontal: 8.0),
|
||||||
child: PanelButton(
|
child: PanelButton(
|
||||||
@ -38,12 +35,15 @@ class AdTile extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
leading: ad.logoUrl != null
|
leading: ad.logoUrl != null
|
||||||
? Image.network(
|
? ClipRRect(
|
||||||
ad.logoUrl.toString(),
|
borderRadius: BorderRadius.circular(50.0),
|
||||||
errorBuilder: (context, error, stackTrace) {
|
child: Image.network(
|
||||||
ad.logoUrl = null;
|
ad.logoUrl.toString(),
|
||||||
return const SizedBox();
|
errorBuilder: (context, error, stackTrace) {
|
||||||
},
|
ad.logoUrl = null;
|
||||||
|
return const SizedBox();
|
||||||
|
},
|
||||||
|
),
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
trailing: const Icon(FeatherIcons.externalLink),
|
trailing: const Icon(FeatherIcons.externalLink),
|
||||||
|
@ -30,6 +30,7 @@ import 'package:provider/provider.dart';
|
|||||||
import 'home_page.i18n.dart';
|
import 'home_page.i18n.dart';
|
||||||
import 'package:filcnaplo/ui/filter/widgets.dart';
|
import 'package:filcnaplo/ui/filter/widgets.dart';
|
||||||
import 'package:filcnaplo/ui/filter/sort.dart';
|
import 'package:filcnaplo/ui/filter/sort.dart';
|
||||||
|
import 'package:i18n_extension/i18n_extension.dart';
|
||||||
|
|
||||||
class HomePage extends StatefulWidget {
|
class HomePage extends StatefulWidget {
|
||||||
const HomePage({Key? key}) : super(key: key);
|
const HomePage({Key? key}) : super(key: key);
|
||||||
@ -94,6 +95,13 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
|
|||||||
|
|
||||||
void setGreeting() {
|
void setGreeting() {
|
||||||
DateTime now = DateTime.now();
|
DateTime now = DateTime.now();
|
||||||
|
List<String> nameParts = user.displayName?.split(" ") ?? ["?"];
|
||||||
|
if (!settings.presentationMode) {
|
||||||
|
firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
|
||||||
|
} else {
|
||||||
|
firstName = "János";
|
||||||
|
}
|
||||||
|
|
||||||
if (now.isBefore(DateTime(now.year, DateTime.august, 31)) &&
|
if (now.isBefore(DateTime(now.year, DateTime.august, 31)) &&
|
||||||
now.isAfter(DateTime(now.year, DateTime.june, 14))) {
|
now.isAfter(DateTime(now.year, DateTime.june, 14))) {
|
||||||
greeting = "goodrest";
|
greeting = "goodrest";
|
||||||
@ -104,16 +112,16 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
|
|||||||
Future.delayed(const Duration(seconds: 1))
|
Future.delayed(const Duration(seconds: 1))
|
||||||
.then((value) => mounted ? _confettiController?.play() : null);
|
.then((value) => mounted ? _confettiController?.play() : null);
|
||||||
}
|
}
|
||||||
} else if (now.month == user.student?.birth.month &&
|
// } else if (now.month == user.student?.birth.month &&
|
||||||
now.day == user.student?.birth.day) {
|
// now.day == user.student?.birth.day) {
|
||||||
greeting = "happybirthday";
|
// greeting = "happybirthday";
|
||||||
|
|
||||||
if (NavigationScreen.of(context)?.init("confetti") ?? false) {
|
// if (NavigationScreen.of(context)?.init("confetti") ?? false) {
|
||||||
_confettiController =
|
// _confettiController =
|
||||||
ConfettiController(duration: const Duration(seconds: 3));
|
// ConfettiController(duration: const Duration(seconds: 3));
|
||||||
Future.delayed(const Duration(seconds: 1))
|
// Future.delayed(const Duration(seconds: 1))
|
||||||
.then((value) => mounted ? _confettiController?.play() : null);
|
// .then((value) => mounted ? _confettiController?.play() : null);
|
||||||
}
|
// }
|
||||||
} else if (now.isAfter(DateTime(now.year, DateTime.may, 28)) &&
|
} else if (now.isAfter(DateTime(now.year, DateTime.may, 28)) &&
|
||||||
now.isBefore(DateTime(now.year, DateTime.may, 30))) {
|
now.isBefore(DateTime(now.year, DateTime.may, 30))) {
|
||||||
greeting = "refilcopen";
|
greeting = "refilcopen";
|
||||||
@ -130,6 +138,12 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
|
|||||||
greeting = "merryxmas";
|
greeting = "merryxmas";
|
||||||
} else if (now.month == DateTime.january && now.day == 1) {
|
} else if (now.month == DateTime.january && now.day == 1) {
|
||||||
greeting = "happynewyear";
|
greeting = "happynewyear";
|
||||||
|
} else if (settings.welcomeMessage.replaceAll(' ', '') != '') {
|
||||||
|
greeting = settings.welcomeMessage;
|
||||||
|
greeting = localizeFill(
|
||||||
|
settings.welcomeMessage,
|
||||||
|
[firstName],
|
||||||
|
);
|
||||||
} else if (now.hour >= 18) {
|
} else if (now.hour >= 18) {
|
||||||
greeting = "goodevening";
|
greeting = "goodevening";
|
||||||
} else if (now.hour >= 10) {
|
} else if (now.hour >= 10) {
|
||||||
@ -155,13 +169,6 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
|
|||||||
|
|
||||||
setGreeting();
|
setGreeting();
|
||||||
|
|
||||||
List<String> nameParts = user.displayName?.split(" ") ?? ["?"];
|
|
||||||
if (!settings.presentationMode) {
|
|
||||||
firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
|
|
||||||
} else {
|
|
||||||
firstName = "János";
|
|
||||||
}
|
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: Stack(
|
body: Stack(
|
||||||
children: [
|
children: [
|
||||||
|
@ -13,7 +13,8 @@ extension Localization on String {
|
|||||||
"welcome": "Welcome, %s!",
|
"welcome": "Welcome, %s!",
|
||||||
"missing_fields": "Missing Fields!",
|
"missing_fields": "Missing Fields!",
|
||||||
"invalid_grant":
|
"invalid_grant":
|
||||||
"Invalid Username/Password! (Try adding spaces after Username)",
|
// "Invalid Username/Password! (Try adding spaces after Username)",
|
||||||
|
"Invalid Username/Password!",
|
||||||
"error": "Failed to log in.",
|
"error": "Failed to log in.",
|
||||||
"schools_error": "Failed to get schools."
|
"schools_error": "Failed to get schools."
|
||||||
},
|
},
|
||||||
@ -27,7 +28,8 @@ extension Localization on String {
|
|||||||
"welcome": "Üdv, %s!",
|
"welcome": "Üdv, %s!",
|
||||||
"missing_fields": "Hiányzó adatok!",
|
"missing_fields": "Hiányzó adatok!",
|
||||||
"invalid_grant":
|
"invalid_grant":
|
||||||
"Helytelen Felhasználónév/Jelszó! (Próbálj szóközöket írni a Felhasználónév után)",
|
// "Helytelen Felhasználónév/Jelszó! (Próbálj szóközöket írni a Felhasználónév után)",
|
||||||
|
"Helytelen Felhasználónév/Jelszó!",
|
||||||
"error": "Sikertelen bejelentkezés.",
|
"error": "Sikertelen bejelentkezés.",
|
||||||
"schools_error": "Nem sikerült lekérni az iskolákat."
|
"schools_error": "Nem sikerült lekérni az iskolákat."
|
||||||
},
|
},
|
||||||
|
@ -43,6 +43,7 @@ import 'package:filcnaplo_premium/ui/mobile/settings/profile_pic.dart';
|
|||||||
import 'package:filcnaplo_premium/ui/mobile/settings/icon_pack.dart';
|
import 'package:filcnaplo_premium/ui/mobile/settings/icon_pack.dart';
|
||||||
import 'package:filcnaplo_premium/ui/mobile/settings/modify_subject_names.dart';
|
import 'package:filcnaplo_premium/ui/mobile/settings/modify_subject_names.dart';
|
||||||
import 'package:filcnaplo_premium/ui/mobile/settings/modify_teacher_names.dart';
|
import 'package:filcnaplo_premium/ui/mobile/settings/modify_teacher_names.dart';
|
||||||
|
import 'package:filcnaplo_premium/ui/mobile/settings/welcome_message.dart';
|
||||||
|
|
||||||
class SettingsScreen extends StatefulWidget {
|
class SettingsScreen extends StatefulWidget {
|
||||||
const SettingsScreen({Key? key}) : super(key: key);
|
const SettingsScreen({Key? key}) : super(key: key);
|
||||||
@ -206,7 +207,7 @@ class _SettingsScreenState extends State<SettingsScreen>
|
|||||||
opacity: 1 - _hideContainersController.value,
|
opacity: 1 - _hideContainersController.value,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
const SizedBox(height: 32.0),
|
const SizedBox(height: 45.0),
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
@ -454,6 +455,7 @@ class _SettingsScreenState extends State<SettingsScreen>
|
|||||||
Material(
|
Material(
|
||||||
type: MaterialType.transparency,
|
type: MaterialType.transparency,
|
||||||
child: MenuNotifications(settings: settings)),
|
child: MenuNotifications(settings: settings)),
|
||||||
|
WelcomeMessagePanelButton(settings, user),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -73,6 +73,9 @@ extension SettingsLocalization on String {
|
|||||||
"devsettings": "Developer Settings",
|
"devsettings": "Developer Settings",
|
||||||
"devmode": "Developer Mode",
|
"devmode": "Developer Mode",
|
||||||
"copy_jwt": "Copy JWT",
|
"copy_jwt": "Copy JWT",
|
||||||
|
"welcome_msg": "Welcome Message",
|
||||||
|
"default": "Default",
|
||||||
|
"edit_welcome_msg": "Edit welcome message",
|
||||||
},
|
},
|
||||||
"hu_hu": {
|
"hu_hu": {
|
||||||
"personal_details": "Személyes információk",
|
"personal_details": "Személyes információk",
|
||||||
@ -144,6 +147,9 @@ extension SettingsLocalization on String {
|
|||||||
"devsettings": "Fejlesztői Beállítások",
|
"devsettings": "Fejlesztői Beállítások",
|
||||||
"devmode": "Fejlesztői mód",
|
"devmode": "Fejlesztői mód",
|
||||||
"copy_jwt": "JWT másolása",
|
"copy_jwt": "JWT másolása",
|
||||||
|
"welcome_msg": "Üdvözlő üzenet",
|
||||||
|
"default": "Alapértelmezett",
|
||||||
|
"edit_welcome_msg": "Üdvözlő üzenet szerkesztése",
|
||||||
},
|
},
|
||||||
"de_de": {
|
"de_de": {
|
||||||
"personal_details": "Persönliche Angaben",
|
"personal_details": "Persönliche Angaben",
|
||||||
@ -214,6 +220,9 @@ extension SettingsLocalization on String {
|
|||||||
"devsettings": "Entwickleroptionen",
|
"devsettings": "Entwickleroptionen",
|
||||||
"devmode": "Entwicklermodus",
|
"devmode": "Entwicklermodus",
|
||||||
"copy_jwt": "JWT kopieren",
|
"copy_jwt": "JWT kopieren",
|
||||||
|
"welcome_msg": "Willkommensnachricht",
|
||||||
|
"default": "Standard",
|
||||||
|
"edit_welcome_msg": "Begrüßungsnachricht bearbeiten",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -82,12 +82,12 @@ class PremiumAuth {
|
|||||||
//}
|
//}
|
||||||
|
|
||||||
// Skip premium check when disconnected
|
// Skip premium check when disconnected
|
||||||
//try {
|
// try {
|
||||||
// final status = await InternetAddress.lookup('github.com');
|
// final status = await InternetAddress.lookup('github.com');
|
||||||
// if (status.isEmpty) return false;
|
// if (status.isEmpty) return false;
|
||||||
//} on SocketException catch (_) {
|
// } on SocketException catch (_) {
|
||||||
// return false;
|
// return false;
|
||||||
//}
|
// }
|
||||||
|
|
||||||
//for (int tries = 0; tries < 3; tries++) {
|
//for (int tries = 0; tries < 3; tries++) {
|
||||||
// try {
|
// try {
|
||||||
|
@ -8,6 +8,7 @@ import 'package:filcnaplo/ui/widgets/message/message_tile.dart';
|
|||||||
import 'package:filcnaplo_kreta_api/models/grade.dart';
|
import 'package:filcnaplo_kreta_api/models/grade.dart';
|
||||||
import 'package:filcnaplo_kreta_api/models/homework.dart';
|
import 'package:filcnaplo_kreta_api/models/homework.dart';
|
||||||
import 'package:filcnaplo_kreta_api/models/message.dart';
|
import 'package:filcnaplo_kreta_api/models/message.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/common/action_button.dart';
|
||||||
import 'package:filcnaplo_mobile_ui/common/filter_bar.dart';
|
import 'package:filcnaplo_mobile_ui/common/filter_bar.dart';
|
||||||
import 'package:filcnaplo_mobile_ui/common/panel/panel.dart';
|
import 'package:filcnaplo_mobile_ui/common/panel/panel.dart';
|
||||||
import 'package:filcnaplo_mobile_ui/common/widgets/grade/new_grades.dart';
|
import 'package:filcnaplo_mobile_ui/common/widgets/grade/new_grades.dart';
|
||||||
@ -268,10 +269,32 @@ class _PremiumCustomAccentColorSettingState
|
|||||||
// ),
|
// ),
|
||||||
// ),
|
// ),
|
||||||
// );
|
// );
|
||||||
SharedTheme theme =
|
showDialog(
|
||||||
await shareProvider.shareCurrentTheme(context);
|
context: context,
|
||||||
Share.share(theme.id,
|
builder: (context) => WillPopScope(
|
||||||
subject: 'reFilc Téma / reFilc Theme');
|
onWillPop: () async => false,
|
||||||
|
child: AlertDialog(
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(12.0)),
|
||||||
|
title: Text("attention".i18n),
|
||||||
|
content: Text("share_disclaimer".i18n),
|
||||||
|
actions: [
|
||||||
|
ActionButton(
|
||||||
|
label: "understand".i18n,
|
||||||
|
onTap: () async {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
SharedTheme theme = await shareProvider
|
||||||
|
.shareCurrentTheme(context);
|
||||||
|
Share.share(
|
||||||
|
theme.id,
|
||||||
|
subject: 'share_subj_theme'.i18n,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
icon: const Icon(
|
icon: const Icon(
|
||||||
FeatherIcons.share2,
|
FeatherIcons.share2,
|
||||||
|
@ -14,6 +14,10 @@ extension SettingsLocalization on String {
|
|||||||
"enter_id": "Enter ID",
|
"enter_id": "Enter ID",
|
||||||
"theme_id": "Theme ID...",
|
"theme_id": "Theme ID...",
|
||||||
"theme_not_found": "Theme not found!",
|
"theme_not_found": "Theme not found!",
|
||||||
|
"attention": "Attention!",
|
||||||
|
"share_disclaimer":
|
||||||
|
"By sharing the theme, you agree that the nickname you set and all settings of the theme will be shared publicly.",
|
||||||
|
"understand": "I understand",
|
||||||
},
|
},
|
||||||
"hu_hu": {
|
"hu_hu": {
|
||||||
"theme_prev": "Előnézet",
|
"theme_prev": "Előnézet",
|
||||||
@ -26,6 +30,10 @@ extension SettingsLocalization on String {
|
|||||||
"enter_id": "ID megadása",
|
"enter_id": "ID megadása",
|
||||||
"theme_id": "Téma azonosító...",
|
"theme_id": "Téma azonosító...",
|
||||||
"theme_not_found": "A téma nem található!",
|
"theme_not_found": "A téma nem található!",
|
||||||
|
"attention": "Figyelem!",
|
||||||
|
"share_disclaimer":
|
||||||
|
"A téma megosztásával elfogadod, hogy az általad beállított becenév és a téma minden beállítása nyilvánosan megosztásra kerüljön.",
|
||||||
|
"understand": "Értem",
|
||||||
},
|
},
|
||||||
"de_de": {
|
"de_de": {
|
||||||
"theme_prev": "Vorschau",
|
"theme_prev": "Vorschau",
|
||||||
@ -39,6 +47,10 @@ extension SettingsLocalization on String {
|
|||||||
"enter_id": "Geben Sie die ID ein",
|
"enter_id": "Geben Sie die ID ein",
|
||||||
"theme_id": "Themen-ID...",
|
"theme_id": "Themen-ID...",
|
||||||
"theme_not_found": "Thema nicht gefunden!",
|
"theme_not_found": "Thema nicht gefunden!",
|
||||||
|
"attention": "Achtung!",
|
||||||
|
"share_disclaimer":
|
||||||
|
"Durch das Teilen des Themes erklären Sie sich damit einverstanden, dass der von Ihnen festgelegte Spitzname und alle Einstellungen des Themes öffentlich geteilt werden.",
|
||||||
|
"understand": "Ich verstehe",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
142
filcnaplo_premium/lib/ui/mobile/settings/welcome_message.dart
Normal file
142
filcnaplo_premium/lib/ui/mobile/settings/welcome_message.dart
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
import 'package:filcnaplo/api/providers/user_provider.dart';
|
||||||
|
import 'package:filcnaplo/models/settings.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/common/panel/panel_button.dart';
|
||||||
|
import 'package:filcnaplo_premium/models/premium_scopes.dart';
|
||||||
|
import 'package:filcnaplo_premium/providers/premium_provider.dart';
|
||||||
|
import 'package:filcnaplo_premium/ui/mobile/premium/upsell.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/screens/settings/settings_screen.i18n.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:i18n_extension/i18n_extension.dart';
|
||||||
|
|
||||||
|
// ignore: must_be_immutable
|
||||||
|
class WelcomeMessagePanelButton extends StatelessWidget {
|
||||||
|
late SettingsProvider settingsProvider;
|
||||||
|
late UserProvider user;
|
||||||
|
|
||||||
|
WelcomeMessagePanelButton(this.settingsProvider, this.user, {Key? key})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
String finalName = ((user.nickname ?? '') != ''
|
||||||
|
? user.nickname
|
||||||
|
: (user.displayName ?? '') != ''
|
||||||
|
? user.displayName
|
||||||
|
: 'János') ??
|
||||||
|
'János';
|
||||||
|
|
||||||
|
return PanelButton(
|
||||||
|
onPressed: () {
|
||||||
|
if (!Provider.of<PremiumProvider>(context, listen: false)
|
||||||
|
.hasScope(PremiumScopes.all)) {
|
||||||
|
PremiumLockedFeatureUpsell.show(
|
||||||
|
context: context, feature: PremiumFeature.profile);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => WelcomeMessageEditor(settingsProvider));
|
||||||
|
},
|
||||||
|
title: Text("welcome_msg".i18n),
|
||||||
|
leading: const Icon(FeatherIcons.smile),
|
||||||
|
trailing: SizedBox(
|
||||||
|
width: 100,
|
||||||
|
child: Expanded(
|
||||||
|
child: Text(
|
||||||
|
settingsProvider.welcomeMessage.replaceAll(' ', '') != ''
|
||||||
|
? localizeFill(
|
||||||
|
settingsProvider.welcomeMessage,
|
||||||
|
[finalName],
|
||||||
|
)
|
||||||
|
: 'default'.i18n,
|
||||||
|
style: const TextStyle(fontSize: 14.0),
|
||||||
|
textAlign: TextAlign.end,
|
||||||
|
softWrap: true,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore: must_be_immutable
|
||||||
|
class WelcomeMessageEditor extends StatefulWidget {
|
||||||
|
late SettingsProvider settingsProvider;
|
||||||
|
|
||||||
|
WelcomeMessageEditor(this.settingsProvider, {Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<WelcomeMessageEditor> createState() => _WelcomeMessageEditorState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _WelcomeMessageEditorState extends State<WelcomeMessageEditor> {
|
||||||
|
final _welcomeMsg = TextEditingController();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_welcomeMsg.text =
|
||||||
|
widget.settingsProvider.welcomeMessage.replaceAll('%s', '%name%');
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: Text("edit_welcome_msg".i18n),
|
||||||
|
content: TextField(
|
||||||
|
controller: _welcomeMsg,
|
||||||
|
autofocus: true,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
border: const OutlineInputBorder(),
|
||||||
|
label: Text('welcome_msg'.i18n),
|
||||||
|
suffixIcon: IconButton(
|
||||||
|
icon: const Icon(FeatherIcons.x),
|
||||||
|
onPressed: () {
|
||||||
|
setState(() {
|
||||||
|
_welcomeMsg.text = "";
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
child: Text(
|
||||||
|
"cancel".i18n,
|
||||||
|
style: const TextStyle(fontWeight: FontWeight.w500),
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).maybePop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
child: Text(
|
||||||
|
"done".i18n,
|
||||||
|
style: const TextStyle(fontWeight: FontWeight.w500),
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
// var trimmed = _welcomeMsg.text.trim();
|
||||||
|
|
||||||
|
// var defLen = trimmed.length;
|
||||||
|
// var replacedLen = trimmed.replaceAll('%s', '').length;
|
||||||
|
|
||||||
|
// if (defLen - 2 > replacedLen) {
|
||||||
|
// print('fuck yourself rn');
|
||||||
|
// }
|
||||||
|
var finalText = _welcomeMsg.text
|
||||||
|
.trim()
|
||||||
|
.replaceAll('%s', '')
|
||||||
|
.replaceFirst('%name%', '%s');
|
||||||
|
|
||||||
|
widget.settingsProvider
|
||||||
|
.update(welcomeMessage: finalText, store: true);
|
||||||
|
Navigator.of(context).pop(true);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user