some progress in cloud sync and paypal support almost done

This commit is contained in:
Kima 2024-12-02 23:13:26 +01:00
parent 9e187fc04c
commit afcff10862
8 changed files with 108 additions and 31 deletions

View File

@ -395,7 +395,7 @@ class FilcAPI {
} }
// cloud sync // cloud sync
static Future<Map?> cloudSync(Map data, String token) async { static Future<Map?> cloudSync(Map<String, String> data, String token) async {
try { try {
var client = http.Client(); var client = http.Client();

View File

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

View File

@ -111,6 +111,7 @@ class SettingsProvider extends ChangeNotifier {
List<String> _unseenNewFeatures; List<String> _unseenNewFeatures;
bool _cloudSyncEnabled; bool _cloudSyncEnabled;
String _cloudSyncToken; String _cloudSyncToken;
DateTime _updatedAt;
// quick settings // quick settings
bool _qTimetableLessonNum; bool _qTimetableLessonNum;
bool _qTimetableSubTiles; bool _qTimetableSubTiles;
@ -188,6 +189,7 @@ class SettingsProvider extends ChangeNotifier {
required List<String> unseenNewFeatures, required List<String> unseenNewFeatures,
required bool cloudSyncEnabled, required bool cloudSyncEnabled,
required String cloudSyncToken, required String cloudSyncToken,
required DateTime updatedAt,
required bool qTimetableLessonNum, required bool qTimetableLessonNum,
required bool qTimetableSubTiles, required bool qTimetableSubTiles,
required bool qSubjectsSubTiles, required bool qSubjectsSubTiles,
@ -262,6 +264,7 @@ class SettingsProvider extends ChangeNotifier {
_unseenNewFeatures = unseenNewFeatures, _unseenNewFeatures = unseenNewFeatures,
_cloudSyncEnabled = cloudSyncEnabled, _cloudSyncEnabled = cloudSyncEnabled,
_cloudSyncToken = cloudSyncToken, _cloudSyncToken = cloudSyncToken,
_updatedAt = updatedAt,
_qTimetableLessonNum = qTimetableLessonNum, _qTimetableLessonNum = qTimetableLessonNum,
_qTimetableSubTiles = qTimetableSubTiles, _qTimetableSubTiles = qTimetableSubTiles,
_qSubjectsSubTiles = qSubjectsSubTiles; _qSubjectsSubTiles = qSubjectsSubTiles;
@ -355,6 +358,7 @@ class SettingsProvider extends ChangeNotifier {
unseenNewFeatures: jsonDecode(map["unseen_new_features"]).cast<String>(), unseenNewFeatures: jsonDecode(map["unseen_new_features"]).cast<String>(),
cloudSyncEnabled: map['cloud_sync_enabled'] == 1, cloudSyncEnabled: map['cloud_sync_enabled'] == 1,
cloudSyncToken: map['cloud_sync_token'], cloudSyncToken: map['cloud_sync_token'],
updatedAt: DateTime.tryParse(map['local_updated_at']) ?? DateTime.now(),
qTimetableLessonNum: map['q_timetable_lesson_num'] == 1, qTimetableLessonNum: map['q_timetable_lesson_num'] == 1,
qTimetableSubTiles: map['q_timetable_sub_tiles'] == 1, qTimetableSubTiles: map['q_timetable_sub_tiles'] == 1,
qSubjectsSubTiles: map['q_subjects_sub_tiles'] == 1, qSubjectsSubTiles: map['q_subjects_sub_tiles'] == 1,
@ -436,6 +440,7 @@ class SettingsProvider extends ChangeNotifier {
"unseen_new_features": jsonEncode(_unseenNewFeatures), "unseen_new_features": jsonEncode(_unseenNewFeatures),
"cloud_sync_enabled": _cloudSyncEnabled ? 1 : 0, "cloud_sync_enabled": _cloudSyncEnabled ? 1 : 0,
"cloud_sync_token": _cloudSyncToken, "cloud_sync_token": _cloudSyncToken,
"local_updated_at": _updatedAt.toIso8601String(),
"q_timetable_lesson_num": _qTimetableLessonNum ? 1 : 0, "q_timetable_lesson_num": _qTimetableLessonNum ? 1 : 0,
"q_timetable_sub_tiles": _qTimetableSubTiles ? 1 : 0, "q_timetable_sub_tiles": _qTimetableSubTiles ? 1 : 0,
"q_subjects_sub_tiles": _qSubjectsSubTiles ? 1 : 0, "q_subjects_sub_tiles": _qSubjectsSubTiles ? 1 : 0,
@ -521,6 +526,7 @@ class SettingsProvider extends ChangeNotifier {
unseenNewFeatures: ['grade_exporting'], unseenNewFeatures: ['grade_exporting'],
cloudSyncEnabled: false, cloudSyncEnabled: false,
cloudSyncToken: '', cloudSyncToken: '',
updatedAt: DateTime.now(),
qTimetableLessonNum: true, qTimetableLessonNum: true,
qTimetableSubTiles: true, qTimetableSubTiles: true,
qSubjectsSubTiles: true, qSubjectsSubTiles: true,
@ -597,6 +603,7 @@ class SettingsProvider extends ChangeNotifier {
List<String> get unseenNewFeatures => _unseenNewFeatures; List<String> get unseenNewFeatures => _unseenNewFeatures;
bool get cloudSyncEnabled => _cloudSyncEnabled; bool get cloudSyncEnabled => _cloudSyncEnabled;
String get cloudSyncToken => _cloudSyncToken; String get cloudSyncToken => _cloudSyncToken;
DateTime get updatedAt => _updatedAt;
bool get qTimetableLessonNum => _qTimetableLessonNum; bool get qTimetableLessonNum => _qTimetableLessonNum;
bool get qTimetableSubTiles => _qTimetableSubTiles; bool get qTimetableSubTiles => _qTimetableSubTiles;
bool get qSubjectsSubTiles => _qSubjectsSubTiles; bool get qSubjectsSubTiles => _qSubjectsSubTiles;
@ -885,6 +892,8 @@ class SettingsProvider extends ChangeNotifier {
if (qSubjectsSubTiles != null && qSubjectsSubTiles != _qSubjectsSubTiles) { if (qSubjectsSubTiles != null && qSubjectsSubTiles != _qSubjectsSubTiles) {
_qSubjectsSubTiles = qSubjectsSubTiles; _qSubjectsSubTiles = qSubjectsSubTiles;
} }
// change updated at time
_updatedAt = DateTime.now();
// store or not // store or not
if (store) await _database?.store.storeSettings(this); if (store) await _database?.store.storeSettings(this);
notifyListeners(); notifyListeners();
@ -894,19 +903,22 @@ class SettingsProvider extends ChangeNotifier {
required Map<dynamic, dynamic> map, required Map<dynamic, dynamic> map,
bool store = true, bool store = true,
}) async { }) async {
print(map);
await update( await update(
store: store, store: store,
language: map["language"], language: map["language"],
startPage: Pages.values[map["start_page"]], startPage: Pages.values[map["start_page"] ?? _startPage.index],
rounding: map["rounding"], rounding: map["rounding"],
theme: ThemeMode.values[map["theme"]], theme: ThemeMode.values[map["theme"] ?? _theme.index],
accentColor: AccentColor.values[map["accent_color"]], accentColor:
AccentColor.values[map["accent_color"] ?? _accentColor.index],
gradeColors: [ gradeColors: [
Color(map["grade_color1"]), Color(map["grade_color1"] ?? _gradeColors[0].value),
Color(map["grade_color2"]), Color(map["grade_color2"] ?? _gradeColors[1].value),
Color(map["grade_color3"]), Color(map["grade_color3"] ?? _gradeColors[2].value),
Color(map["grade_color4"]), Color(map["grade_color4"] ?? _gradeColors[3].value),
Color(map["grade_color5"]), Color(map["grade_color5"] ?? _gradeColors[4].value),
], ],
newsEnabled: map["news"] == 1, newsEnabled: map["news"] == 1,
seenNews: map["seen_news"], seenNews: map["seen_news"],
@ -918,11 +930,13 @@ class SettingsProvider extends ChangeNotifier {
notificationsBitfield: map["notifications_bitfield"], notificationsBitfield: map["notifications_bitfield"],
notificationPollInterval: map["notification_poll_interval"], notificationPollInterval: map["notification_poll_interval"],
developerMode: map["developer_mode"] == 1, developerMode: map["developer_mode"] == 1,
vibrate: VibrationStrength.values[map["vibration_strength"]], vibrate:
VibrationStrength.values[map["vibration_strength"] ?? _vibrate.index],
abWeeks: map["ab_weeks"] == 1, abWeeks: map["ab_weeks"] == 1,
swapABweeks: map["swap_ab_weeks"] == 1, swapABweeks: map["swap_ab_weeks"] == 1,
updateChannel: UpdateChannel.values[map["update_channel"]], updateChannel:
config: Config.fromJson(jsonDecode(map["config"])), UpdateChannel.values[map["update_channel"] ?? _updateChannel.index],
config: Config.fromJson(jsonDecode(map["config"] ?? "{}")),
xFilcId: map["x_filc_id"], xFilcId: map["x_filc_id"],
analyticsEnabled: map["analytics_enabled"] == 1, analyticsEnabled: map["analytics_enabled"] == 1,
graphClassAvg: map["graph_class_avg"] == 1, graphClassAvg: map["graph_class_avg"] == 1,
@ -933,13 +947,19 @@ class SettingsProvider extends ChangeNotifier {
gradeOpeningFun: map["grade_opening_fun"] == 1, gradeOpeningFun: map["grade_opening_fun"] == 1,
iconPack: Map.fromEntries( iconPack: Map.fromEntries(
IconPack.values.map((e) => MapEntry(e.name, e)))[map["icon_pack"]]!, IconPack.values.map((e) => MapEntry(e.name, e)))[map["icon_pack"]]!,
customAccentColor: Color(map["custom_accent_color"]), customAccentColor:
customBackgroundColor: Color(map["custom_background_color"]), Color(map["custom_accent_color"] ?? _customAccentColor.value),
customHighlightColor: Color(map["custom_highlight_color"]), customBackgroundColor:
customIconColor: Color(map["custom_icon_color"]), Color(map["custom_background_color"] ?? _customBackgroundColor.value),
customTextColor: Color(map["custom_text_color"]), 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, shadowEffect: map["shadow_effect"] == 1,
premiumScopes: jsonDecode(map["premium_scopes"]).cast<String>(), premiumScopes:
jsonDecode(map["premium_scopes"] ?? _premiumScopes).cast<String>(),
premiumAccessToken: map["premium_token"], premiumAccessToken: map["premium_token"],
premiumLogin: map["premium_login"], premiumLogin: map["premium_login"],
lastAccountId: map["last_account_id"], lastAccountId: map["last_account_id"],
@ -947,7 +967,8 @@ class SettingsProvider extends ChangeNotifier {
renamedSubjectsItalics: map["renamed_subjects_italics"] == 1, renamedSubjectsItalics: map["renamed_subjects_italics"] == 1,
renamedTeachersEnabled: map["renamed_teachers_enabled"] == 1, renamedTeachersEnabled: map["renamed_teachers_enabled"] == 1,
renamedTeachersItalics: map["renamed_teachers_italics"] == 1, renamedTeachersItalics: map["renamed_teachers_italics"] == 1,
liveActivityColor: Color(map["live_activity_color"]), liveActivityColor:
Color(map["live_activity_color"] ?? _liveActivityColor),
welcomeMessage: map["welcome_message"], welcomeMessage: map["welcome_message"],
appIcon: map["app_icon"], appIcon: map["app_icon"],
currentThemeId: map['current_theme_id'], currentThemeId: map['current_theme_id'],
@ -970,7 +991,8 @@ class SettingsProvider extends ChangeNotifier {
newColors: map['new_colors'] == 1, newColors: map['new_colors'] == 1,
uwuMode: map['uwu_mode'] == 1, uwuMode: map['uwu_mode'] == 1,
newPopups: map['new_popups'] == 1, newPopups: map['new_popups'] == 1,
unseenNewFeatures: jsonDecode(map["unseen_new_features"]).cast<String>(), unseenNewFeatures:
jsonDecode(map["unseen_new_features"] ?? "[]").cast<String>(),
cloudSyncEnabled: map['cloud_sync_enabled'] == 1, cloudSyncEnabled: map['cloud_sync_enabled'] == 1,
cloudSyncToken: map['cloud_sync_token'], cloudSyncToken: map['cloud_sync_token'],
qTimetableLessonNum: map['q_timetable_lesson_num'] == 1, qTimetableLessonNum: map['q_timetable_lesson_num'] == 1,

View File

@ -95,16 +95,53 @@ class PlusPlanCard extends StatelessWidget {
actions: [ actions: [
ActionButton( ActionButton(
label: "next".i18n, label: "next".i18n,
onTap: () {
// pop dialog
Navigator.of(context).pop();
// show payment option selector
showDialog(
context: context,
builder: (context) => AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12.0)),
title: Text('payment_method'.i18n),
content: Text('select_payment_method'.i18n),
actions: [
ActionButton(
label: "stripe".i18n,
onTap: () { onTap: () {
// pop dialog // pop dialog
Navigator.of(context).pop(); Navigator.of(context).pop();
// start payment process // start payment process
Navigator.of(context) Navigator.of(context)
.push(MaterialPageRoute(builder: (context) { .push(MaterialPageRoute(builder: (context) {
return PremiumActivationView(product: id); return PremiumActivationView(
product: id,
paymentProvider: "stripe",
);
})); }));
}, },
), ),
ActionButton(
label: "paypal".i18n,
onTap: () {
// pop dialog
Navigator.of(context).pop();
// start payment process
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) {
return PremiumActivationView(
product: id,
paymentProvider: "paypal",
);
}));
},
),
],
),
);
},
),
], ],
), ),
); );

View File

@ -47,11 +47,16 @@ extension SettingsLocalization on String {
"rfp_16": "Private leaks and informations about upcoming features", "rfp_16": "Private leaks and informations about upcoming features",
"rfp_17": "Grade exporting", "rfp_17": "Grade exporting",
"rfp_18": "Viewing exported grades", "rfp_18": "Viewing exported grades",
// docs popup // docs and payment method popup
"docs": "Documents", "docs": "Documents",
"docs_acceptance": "docs_acceptance":
"By pressing the \"Next\" button, you accept reFilc's Terms and Conditions for subscriptions (available at the following link: filc.one/pay-terms) and our Privacy Policy (available at the following link: filc.one/pay-privacy).", "By pressing the \"Next\" button, you accept reFilc's Terms and Conditions for subscriptions (available at the following link: filc.one/pay-terms) and our Privacy Policy (available at the following link: filc.one/pay-privacy).",
"next": "Next", "next": "Next",
"payment_method": "Payment Method",
"select_payment_method":
"Please select a preferred payment method! Credit card payments are handled by Stripe, which also supports Apple Pay, Google Pay and Revolut Pay.",
"stripe": "Credit Card",
"paypal": "PayPal",
// other // other
"and": " and ", "and": " and ",
"every": "Every ", "every": "Every ",
@ -106,11 +111,16 @@ extension SettingsLocalization on String {
"rfp_16": "Privát betekintések és információk közelgő újításokról", "rfp_16": "Privát betekintések és információk közelgő újításokról",
"rfp_17": "Jegy exportálás", "rfp_17": "Jegy exportálás",
"rfp_18": "Exportált jegyek megtekintése", "rfp_18": "Exportált jegyek megtekintése",
// docs popup // docs and payment method popup
"docs": "Dokumentumok", "docs": "Dokumentumok",
"docs_acceptance": "docs_acceptance":
"A \"Tovább\" gombra kattintva elfogadod a reFilc előfizetésekkel kapcsolatos Általános Szerződési Feltételeit (elérhető az alábbi link-en: filc.one/pay-terms), valamint Adatkezelési Tájékoztatónkat (elérhető az alábbi link-en: filc.one/pay-privacy).", "A \"Tovább\" gombra kattintva elfogadod a reFilc előfizetésekkel kapcsolatos Általános Szerződési Feltételeit (elérhető az alábbi link-en: filc.one/pay-terms), valamint Adatkezelési Tájékoztatónkat (elérhető az alábbi link-en: filc.one/pay-privacy).",
"next": "Tovább", "next": "Tovább",
"payment_method": "Fizetési mód",
"select_payment_method":
"Kérlek válassz egy fizetési módot! A bankkártyás fizetést a Stripe biztosítja, mely támogat Apple Pay-t, Google Pay-t és Revolut Pay-t is.",
"stripe": "Bankkártya",
"paypal": "PayPal",
// other // other
"and": " és ", "and": " és ",
"every": "Minden ", "every": "Minden ",
@ -167,11 +177,16 @@ extension SettingsLocalization on String {
"rfp_16": "Private Leaks und Informationen über kommende Funktionen", "rfp_16": "Private Leaks und Informationen über kommende Funktionen",
"rfp_17": "Notenexport", "rfp_17": "Notenexport",
"rfp_18": "Anzeigen exportierter Noten", "rfp_18": "Anzeigen exportierter Noten",
// docs popup // docs and payment method popup
"docs": "Dokumente", "docs": "Dokumente",
"docs_acceptance": "docs_acceptance":
"Durch Drücken der Schaltfläche \"Weiter\" akzeptieren Sie die Allgemeinen Geschäftsbedingungen von reFilc für Abonnements (verfügbar unter folgendem Link: filc.one/pay-terms) und unsere Datenschutzrichtlinie (verfügbar unter folgendem Link: filc.one/pay-privacy).", "Durch Drücken der Schaltfläche \"Weiter\" akzeptieren Sie die Allgemeinen Geschäftsbedingungen von reFilc für Abonnements (verfügbar unter folgendem Link: filc.one/pay-terms) und unsere Datenschutzrichtlinie (verfügbar unter folgendem Link: filc.one/pay-privacy).",
"next": "Weiter", "next": "Weiter",
"payment_method": "Zahlungsmethode",
"select_payment_method":
"Bitte wählen Sie eine bevorzugte Zahlungsmethode aus! Kreditkartenzahlungen werden von Stripe abgewickelt, der auch Apple Pay, Google Pay und Revolut Pay unterstützt.",
"stripe": "Kreditkarte",
"paypal": "PayPal",
// other // other
"and": " und ", "and": " und ",
"every": "Jeder ", "every": "Jeder ",

View File

@ -103,7 +103,7 @@ class _QwIDLoginWidgetState extends State<QwIDLoginWidget>
)) ))
..loadRequest( ..loadRequest(
Uri.parse( Uri.parse(
'https://qwid.qwit.dev/oauth2/authorize?client_id=c3b871fb-d922-4e23-b94d-b31f294c9253&scope=*&redirect_uri=https://api.refilc.hu/v4/oauth2/callback/app/qwid&response_type=code'), // &institute_code=${widget.selectedSchool} 'https://qwid.qwit.dev/oauth2/authorize?client_id=99aa103a-0bd7-43e0-8421-3bb0b2f6adb1&scope=*&redirect_uri=https://api.refilc.hu/v4/oauth2/callback/app/qwid&response_type=code'), // &institute_code=${widget.selectedSchool}
); );
} }

View File

@ -1,4 +1,6 @@
// import 'package:refilc/models/settings.dart'; // import 'package:refilc/models/settings.dart';
import 'dart:convert';
import 'package:refilc/api/client.dart'; import 'package:refilc/api/client.dart';
import 'package:refilc/api/providers/database_provider.dart'; import 'package:refilc/api/providers/database_provider.dart';
import 'package:refilc/api/providers/user_provider.dart'; import 'package:refilc/api/providers/user_provider.dart';
@ -193,7 +195,7 @@ class CloudSyncSettingsScreenState extends State<CloudSyncSettingsScreen> {
} else { } else {
FilcAPI.cloudSync( FilcAPI.cloudSync(
{ {
"settings": settingsProvider.toMap(), "settings": jsonEncode(settingsProvider.toMap()),
// "device_ids": [ // "device_ids": [
// settingsProvider.xFilcId, // settingsProvider.xFilcId,
// ], // ],

@ -1 +1 @@
Subproject commit bc6ccd961b8e3edf35d279d32c78113fbd1d7a5a Subproject commit 800f5ce92daafb002990cb7838e8ce4b28bc1a7d