Merge branch 'dev' into master

This commit is contained in:
Márton Kiss
2025-01-03 15:26:35 +01:00
committed by GitHub
15 changed files with 715 additions and 29 deletions

View File

@@ -54,6 +54,9 @@ class FilcAPI {
static const payment = "$baseUrl/v4/payment";
static const stripeSheet = "$payment/stripe-sheet";
// Cloud Sync
static const cloudSyncApi = "$baseUrl/v4/me/cloud-sync";
static Future<bool> checkConnectivity() async =>
(await Connectivity().checkConnectivity())[0] != ConnectivityResult.none;
@@ -390,6 +393,32 @@ class FilcAPI {
return null;
}
// cloud sync
static Future<Map?> cloudSync(Map<String, String> data, String token) async {
try {
var client = http.Client();
http.Response res = await client.post(
Uri.parse(cloudSyncApi),
body: data,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Bearer $token',
},
);
if (res.statusCode != 200) {
throw "HTTP ${res.statusCode}: ${res.body}";
}
return jsonDecode(res.body);
} on Exception catch (error, stacktrace) {
log("ERROR: FilcAPI.cloudSync: $error $stacktrace");
}
return null;
}
}
class ErrorReport {

View File

@@ -56,6 +56,9 @@ const settingsDB = DatabaseStruct("settings", {
"uwu_mode": int,
"new_popups": int,
"unseen_new_features": String,
"cloud_sync_enabled": int,
"cloud_sync_token": String,
"local_updated_at": String,
// quick settings
"q_timetable_lesson_num": int, "q_timetable_sub_tiles": int,
"q_subjects_sub_tiles": int,

View File

@@ -0,0 +1,22 @@
class CloudSyncData {
Map settings;
List<String> deviceIds;
String reFilcPlusId;
Map json;
CloudSyncData({
this.settings = const {},
this.deviceIds = const [],
this.reFilcPlusId = "",
required this.json,
});
factory CloudSyncData.fromJson(Map json) {
return CloudSyncData(
settings: json['settings'] ?? {},
deviceIds: List<String>.from(json['device_ids'] ?? []),
reFilcPlusId: json['refilc_plus_id'] ?? "",
json: json,
);
}
}

View File

@@ -109,6 +109,9 @@ class SettingsProvider extends ChangeNotifier {
bool _uwuMode;
bool _newPopups;
List<String> _unseenNewFeatures;
bool _cloudSyncEnabled;
String _cloudSyncToken;
DateTime _updatedAt;
// quick settings
bool _qTimetableLessonNum;
bool _qTimetableSubTiles;
@@ -184,6 +187,9 @@ class SettingsProvider extends ChangeNotifier {
required bool uwuMode,
required bool newPopups,
required List<String> unseenNewFeatures,
required bool cloudSyncEnabled,
required String cloudSyncToken,
required DateTime updatedAt,
required bool qTimetableLessonNum,
required bool qTimetableSubTiles,
required bool qSubjectsSubTiles,
@@ -256,6 +262,9 @@ class SettingsProvider extends ChangeNotifier {
_uwuMode = uwuMode,
_newPopups = newPopups,
_unseenNewFeatures = unseenNewFeatures,
_cloudSyncEnabled = cloudSyncEnabled,
_cloudSyncToken = cloudSyncToken,
_updatedAt = updatedAt,
_qTimetableLessonNum = qTimetableLessonNum,
_qTimetableSubTiles = qTimetableSubTiles,
_qSubjectsSubTiles = qSubjectsSubTiles;
@@ -347,6 +356,9 @@ class SettingsProvider extends ChangeNotifier {
uwuMode: map['uwu_mode'] == 1,
newPopups: map['new_popups'] == 1,
unseenNewFeatures: jsonDecode(map["unseen_new_features"]).cast<String>(),
cloudSyncEnabled: map['cloud_sync_enabled'] == 1,
cloudSyncToken: map['cloud_sync_token'],
updatedAt: DateTime.tryParse(map['local_updated_at']) ?? DateTime.now(),
qTimetableLessonNum: map['q_timetable_lesson_num'] == 1,
qTimetableSubTiles: map['q_timetable_sub_tiles'] == 1,
qSubjectsSubTiles: map['q_subjects_sub_tiles'] == 1,
@@ -426,6 +438,9 @@ class SettingsProvider extends ChangeNotifier {
"uwu_mode": _uwuMode ? 1 : 0,
"new_popups": _newPopups ? 1 : 0,
"unseen_new_features": jsonEncode(_unseenNewFeatures),
"cloud_sync_enabled": _cloudSyncEnabled ? 1 : 0,
"cloud_sync_token": _cloudSyncToken,
"local_updated_at": _updatedAt.toIso8601String(),
"q_timetable_lesson_num": _qTimetableLessonNum ? 1 : 0,
"q_timetable_sub_tiles": _qTimetableSubTiles ? 1 : 0,
"q_subjects_sub_tiles": _qSubjectsSubTiles ? 1 : 0,
@@ -509,6 +524,9 @@ class SettingsProvider extends ChangeNotifier {
uwuMode: false,
newPopups: true,
unseenNewFeatures: ['grade_exporting'],
cloudSyncEnabled: false,
cloudSyncToken: '',
updatedAt: DateTime.now(),
qTimetableLessonNum: true,
qTimetableSubTiles: true,
qSubjectsSubTiles: true,
@@ -583,6 +601,9 @@ class SettingsProvider extends ChangeNotifier {
bool get uwuMode => _uwuMode;
bool get newPopups => _newPopups;
List<String> get unseenNewFeatures => _unseenNewFeatures;
bool get cloudSyncEnabled => _cloudSyncEnabled;
String get cloudSyncToken => _cloudSyncToken;
DateTime get updatedAt => _updatedAt;
bool get qTimetableLessonNum => _qTimetableLessonNum;
bool get qTimetableSubTiles => _qTimetableSubTiles;
bool get qSubjectsSubTiles => _qSubjectsSubTiles;
@@ -597,6 +618,7 @@ class SettingsProvider extends ChangeNotifier {
List<Color>? gradeColors,
bool? newsEnabled,
String? seenNewsId,
String? seenNews, // only for restoring from map
bool? notificationsEnabled,
bool? notificationsGradesEnabled,
bool? notificationsAbsencesEnabled,
@@ -653,6 +675,8 @@ class SettingsProvider extends ChangeNotifier {
bool? uwuMode,
bool? newPopups,
List<String>? unseenNewFeatures,
bool? cloudSyncEnabled,
String? cloudSyncToken,
bool? qTimetableLessonNum,
bool? qTimetableSubTiles,
bool? qSubjectsSubTiles,
@@ -675,6 +699,7 @@ class SettingsProvider extends ChangeNotifier {
tempList.add(seenNewsId);
_seenNews = tempList.join(',');
}
if (seenNews != null && seenNews != _seenNews) _seenNews = seenNews;
if (notificationsEnabled != null &&
notificationsEnabled != _notificationsEnabled) {
_notificationsEnabled = notificationsEnabled;
@@ -850,6 +875,12 @@ class SettingsProvider extends ChangeNotifier {
if (unseenNewFeatures != null && unseenNewFeatures != _unseenNewFeatures) {
_unseenNewFeatures = unseenNewFeatures;
}
if (cloudSyncEnabled != null && cloudSyncEnabled != _cloudSyncEnabled) {
_cloudSyncEnabled = cloudSyncEnabled;
}
if (cloudSyncToken != null && cloudSyncToken != _cloudSyncToken) {
_cloudSyncToken = cloudSyncToken;
}
if (qTimetableLessonNum != null &&
qTimetableLessonNum != _qTimetableLessonNum) {
_qTimetableLessonNum = qTimetableLessonNum;
@@ -861,11 +892,115 @@ class SettingsProvider extends ChangeNotifier {
if (qSubjectsSubTiles != null && qSubjectsSubTiles != _qSubjectsSubTiles) {
_qSubjectsSubTiles = qSubjectsSubTiles;
}
// change updated at time
_updatedAt = DateTime.now();
// store or not
if (store) await _database?.store.storeSettings(this);
notifyListeners();
}
Future<void> updateFromMap({
required Map<dynamic, dynamic> map,
bool store = true,
}) async {
print(map);
await update(
store: store,
language: map["language"],
startPage: Pages.values[map["start_page"] ?? _startPage.index],
rounding: map["rounding"],
theme: ThemeMode.values[map["theme"] ?? _theme.index],
accentColor:
AccentColor.values[map["accent_color"] ?? _accentColor.index],
gradeColors: [
Color(map["grade_color1"] ?? _gradeColors[0].value),
Color(map["grade_color2"] ?? _gradeColors[1].value),
Color(map["grade_color3"] ?? _gradeColors[2].value),
Color(map["grade_color4"] ?? _gradeColors[3].value),
Color(map["grade_color5"] ?? _gradeColors[4].value),
],
newsEnabled: map["news"] == 1,
seenNews: map["seen_news"],
notificationsEnabled: map["notifications"] == 1,
notificationsGradesEnabled: map["notifications_grades"] == 1,
notificationsAbsencesEnabled: map["notifications_absences"] == 1,
notificationsMessagesEnabled: map["notifications_messages"] == 1,
notificationsLessonsEnabled: map["notifications_lessons"] == 1,
notificationsBitfield: map["notifications_bitfield"],
notificationPollInterval: map["notification_poll_interval"],
developerMode: map["developer_mode"] == 1,
vibrate:
VibrationStrength.values[map["vibration_strength"] ?? _vibrate.index],
abWeeks: map["ab_weeks"] == 1,
swapABweeks: map["swap_ab_weeks"] == 1,
updateChannel:
UpdateChannel.values[map["update_channel"] ?? _updateChannel.index],
config: Config.fromJson(jsonDecode(map["config"] ?? "{}")),
xFilcId: map["x_filc_id"],
analyticsEnabled: map["analytics_enabled"] == 1,
graphClassAvg: map["graph_class_avg"] == 1,
goodStudent: false,
presentationMode: map["presentation_mode"] == 1,
bellDelayEnabled: map["bell_delay_enabled"] == 1,
bellDelay: map["bell_delay"],
gradeOpeningFun: map["grade_opening_fun"] == 1,
iconPack: Map.fromEntries(
IconPack.values.map((e) => MapEntry(e.name, e)))[map["icon_pack"]]!,
customAccentColor:
Color(map["custom_accent_color"] ?? _customAccentColor.value),
customBackgroundColor:
Color(map["custom_background_color"] ?? _customBackgroundColor.value),
customHighlightColor:
Color(map["custom_highlight_color"] ?? _customHighlightColor.value),
customIconColor:
Color(map["custom_icon_color"] ?? _customIconColor.value),
customTextColor:
Color(map["custom_text_color"] ?? _customTextColor.value),
shadowEffect: map["shadow_effect"] == 1,
premiumScopes:
jsonDecode(map["premium_scopes"] ?? _premiumScopes).cast<String>(),
premiumAccessToken: map["premium_token"],
premiumLogin: map["premium_login"],
lastAccountId: map["last_account_id"],
renamedSubjectsEnabled: map["renamed_subjects_enabled"] == 1,
renamedSubjectsItalics: map["renamed_subjects_italics"] == 1,
renamedTeachersEnabled: map["renamed_teachers_enabled"] == 1,
renamedTeachersItalics: map["renamed_teachers_italics"] == 1,
liveActivityColor:
Color(map["live_activity_color"] ?? _liveActivityColor),
welcomeMessage: map["welcome_message"],
appIcon: map["app_icon"],
currentThemeId: map['current_theme_id'],
currentThemeDisplayName: map['current_theme_display_name'],
currentThemeCreator: map['current_theme_creator'],
showBreaks: map['show_breaks'] == 1,
// pinSetGeneral: map['general_s_pin'],
// pinSetPersonalize: map['personalize_s_pin'],
// pinSetNotify: map['notify_s_pin'],
// pinSetExtras: map['extras_s_pin'],
fontFamily: map['font_family'],
titleOnlyFont: map['title_only_font'] == 1,
plusSessionId: map['plus_session_id'],
calSyncRoomLocation: map['cal_sync_room_location'],
calSyncShowExams: map['cal_sync_show_exams'] == 1,
calSyncShowTeacher: map['cal_sync_show_teacher'] == 1,
calSyncRenamed: map['cal_sync_renamed'] == 1,
calendarId: map['calendar_id'],
navShadow: map['nav_shadow'] == 1,
newColors: map['new_colors'] == 1,
uwuMode: map['uwu_mode'] == 1,
newPopups: map['new_popups'] == 1,
unseenNewFeatures:
jsonDecode(map["unseen_new_features"] ?? "[]").cast<String>(),
cloudSyncEnabled: map['cloud_sync_enabled'] == 1,
cloudSyncToken: map['cloud_sync_token'],
qTimetableLessonNum: map['q_timetable_lesson_num'] == 1,
qTimetableSubTiles: map['q_timetable_sub_tiles'] == 1,
qSubjectsSubTiles: map['q_subjects_sub_tiles'] == 1,
);
}
void exportJson() {
String sets = json.encode(toMap());
Clipboard.setData(ClipboardData(text: sets));

View File

@@ -21,6 +21,10 @@ class User {
String accessToken;
DateTime accessTokenExpire;
String refreshToken;
// cloud sync
// String qwidAccessToken;
// DateTime? qwidAccessTokenExpire;
// String qwidRefreshToken;
String get displayName => nickname != '' ? nickname : name;
bool get hasStreak => gradeStreak > 0;
@@ -39,6 +43,9 @@ class User {
required this.accessToken,
required this.accessTokenExpire,
required this.refreshToken,
// this.qwidAccessToken = "",
// this.qwidAccessTokenExpire,
// this.qwidRefreshToken = "",
}) {
if (id != null) {
this.id = id;
@@ -74,6 +81,11 @@ class User {
? map["access_token_expire"]
: DateTime.now().toIso8601String()),
refreshToken: map["refresh_token"] ?? "",
// qwidAccessToken: map["qwid_access_token"] ?? "",
// qwidAccessTokenExpire: map["qwid_access_token_expire"] != ""
// ? DateTime.parse(map["qwid_access_token_expire"])
// : null,
// qwidRefreshToken: map["qwid_refresh_token"] ?? "",
);
}
@@ -92,6 +104,11 @@ class User {
"access_token": accessToken,
"access_token_expire": accessTokenExpire.toIso8601String(),
"refresh_token": refreshToken,
// "qwid_access_token": qwidAccessToken,
// "qwid_access_token_expire": qwidAccessTokenExpire != null
// ? qwidAccessTokenExpire!.toIso8601String()
// : "",
// "qwid_refresh_token": qwidRefreshToken,
};
}

View File

@@ -49,7 +49,7 @@ dependencies:
crypto: ^3.0.2
elegant_notification: ^2.2.0
flutter_feather_icons: ^2.0.0+1
live_activities: ^1.7.4
# live_activities: ^1.7.4
animated_flip_counter: ^0.3.4
lottie: ^3.1.0
rive: ^0.12.4
@@ -62,10 +62,10 @@ dependencies:
flutter_expandable_fab: ^2.0.0
uni_links: ^0.5.1
url_launcher: ^6.1.6
workmanager:
git:
url: https://github.com/refilc/flutter_workmanager.git
ref: v0.5.1
# workmanager:
# git:
# url: https://github.com/refilc/flutter_workmanager.git
# ref: v0.5.1
flutter_svg: ^2.0.10+1
image_picker: ^1.0.7
animations: ^2.0.1