diff --git a/filcnaplo/assets/fonts/SpaceMono/SpaceMono-Bold.ttf b/filcnaplo/assets/fonts/SpaceMono/SpaceMono-Bold.ttf new file mode 100644 index 0000000..18b8aea Binary files /dev/null and b/filcnaplo/assets/fonts/SpaceMono/SpaceMono-Bold.ttf differ diff --git a/filcnaplo/assets/fonts/SpaceMono/SpaceMono-BoldItalic.ttf b/filcnaplo/assets/fonts/SpaceMono/SpaceMono-BoldItalic.ttf new file mode 100644 index 0000000..51fcc39 Binary files /dev/null and b/filcnaplo/assets/fonts/SpaceMono/SpaceMono-BoldItalic.ttf differ diff --git a/filcnaplo/assets/fonts/SpaceMono/SpaceMono-Italic.ttf b/filcnaplo/assets/fonts/SpaceMono/SpaceMono-Italic.ttf new file mode 100644 index 0000000..119c545 Binary files /dev/null and b/filcnaplo/assets/fonts/SpaceMono/SpaceMono-Italic.ttf differ diff --git a/filcnaplo/assets/fonts/SpaceMono/SpaceMono-Regular.ttf b/filcnaplo/assets/fonts/SpaceMono/SpaceMono-Regular.ttf new file mode 100644 index 0000000..3374aca Binary files /dev/null and b/filcnaplo/assets/fonts/SpaceMono/SpaceMono-Regular.ttf differ diff --git a/filcnaplo/lib/api/client.dart b/filcnaplo/lib/api/client.dart index 8005fd0..460c4ba 100644 --- a/filcnaplo/lib/api/client.dart +++ b/filcnaplo/lib/api/client.dart @@ -3,15 +3,23 @@ import 'dart:convert'; import 'package:filcnaplo/models/config.dart'; import 'package:filcnaplo/models/news.dart'; import 'package:filcnaplo/models/release.dart'; +import 'package:filcnaplo/models/settings.dart'; import 'package:filcnaplo/models/supporter.dart'; import 'package:filcnaplo_kreta_api/models/school.dart'; +import 'package:flutter/cupertino.dart'; import 'package:http/http.dart' as http; class FilcAPI { + // Public API static const SCHOOL_LIST = "https://filcnaplo.hu/v2/school_list.json"; - static const CONFIG = "https://filcnaplo.hu/v2/config.json"; static const NEWS = "https://filcnaplo.hu/v2/news.json"; static const SUPPORTERS = "https://filcnaplo.hu/v2/supporters.json"; + + // Private API + static const CONFIG = "https://api.filcnaplo.hu/config"; + static const REPORT = "https://api.filcnaplo.hu/report"; + + // Updates static const REPO = "filc/naplo"; static const RELEASES = "https://api.github.com/repos/$REPO/releases"; @@ -35,15 +43,22 @@ class FilcAPI { } } - static Future getConfig() async { + static Future getConfig(SettingsProvider settings) async { + Map headers = { + "x-filc-id": settings.xFilcId, + "user-agent": settings.config.userAgent, + }; + try { - http.Response res = await http.get(Uri.parse(CONFIG)); + http.Response res = await http.get(Uri.parse(CONFIG), headers: headers); if (res.statusCode == 200) { return Config.fromJson(jsonDecode(res.body)); - } else { - throw "HTTP ${res.statusCode}: ${res.body}"; + } else if (res.statusCode == 429) { + res = await http.get(Uri.parse(CONFIG)); + if (res.statusCode == 200) return Config.fromJson(jsonDecode(res.body)); } + throw "HTTP ${res.statusCode}: ${res.body}"; } catch (error) { print("ERROR: FilcAPI.getConfig: $error"); } @@ -104,4 +119,35 @@ class FilcAPI { return Future.value(null); } + + static Future sendReport(ErrorReport report) async { + try { + http.Response res = await http.post(Uri.parse(REPORT), body: { + "os": report.os, + "version": report.version, + "error": report.error, + "stack_trace": report.stack, + }); + + if (res.statusCode != 200) { + throw "HTTP ${res.statusCode}: ${res.body}"; + } + } catch (error) { + print("ERROR: FilcAPI.sendReport: $error"); + } + } +} + +class ErrorReport { + String stack; + String os; + String version; + String error; + + ErrorReport({ + required this.stack, + required this.os, + required this.version, + required this.error, + }); } diff --git a/filcnaplo/lib/app.dart b/filcnaplo/lib/app.dart index 9fe579e..de1e499 100644 --- a/filcnaplo/lib/app.dart +++ b/filcnaplo/lib/app.dart @@ -46,7 +46,7 @@ class App extends StatelessWidget { setSystemChrome(context); WidgetsBinding.instance?.addPostFrameCallback((_) { - FilcAPI.getConfig().then((Config? config) { + FilcAPI.getConfig(settings).then((Config? config) { settings.update(context, database: database, config: config ?? Config.fromJson({})); }); }); diff --git a/filcnaplo/lib/database/init.dart b/filcnaplo/lib/database/init.dart index 3590cf1..49dfb0e 100644 --- a/filcnaplo/lib/database/init.dart +++ b/filcnaplo/lib/database/init.dart @@ -32,6 +32,7 @@ Future createSettingsTable(Database db) async { "grade_color1": int, "grade_color2": int, "grade_color3": int, "grade_color4": int, "grade_color5": int, // grade colors "vibration_strength": int, "ab_weeks": int, "swap_ab_weeks": int, "notifications": int, "notifications_bitfield": int, "notification_poll_interval": int, // notifications + "x_filc_id": String, }); // Create table Settings @@ -42,7 +43,7 @@ Future createSettingsTable(Database db) async { Future createUsersTable(Database db) async { var usersDB = DatabaseStruct( - {"id": String, "name": String, "username": String, "password": String, "institute_code": String, "student": String, "role": String}); + {"id": String, "name": String, "username": String, "password": String, "institute_code": String, "student": String, "role": int}); // Create table Users await db.execute("CREATE TABLE IF NOT EXISTS users ($usersDB)"); diff --git a/filcnaplo/lib/main.dart b/filcnaplo/lib/main.dart index ef24d6a..61830b7 100644 --- a/filcnaplo/lib/main.dart +++ b/filcnaplo/lib/main.dart @@ -2,10 +2,12 @@ import 'package:filcnaplo/api/providers/user_provider.dart'; import 'package:filcnaplo/api/providers/database_provider.dart'; import 'package:filcnaplo/database/init.dart'; import 'package:filcnaplo/models/settings.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:filcnaplo/app.dart'; import 'package:flutter/services.dart'; import 'package:filcnaplo_mobile_ui/screens/error_screen.dart'; +import 'package:filcnaplo_mobile_ui/screens/error_report_screen.dart'; void main() async { // Initalize @@ -39,12 +41,24 @@ class Startup { } } +bool errorShown = false; +String lastException = ''; + Widget errorBuilder(FlutterErrorDetails details) { return Builder(builder: (context) { if (Navigator.of(context).canPop()) Navigator.pop(context); WidgetsBinding.instance?.addPostFrameCallback((_) { - Navigator.of(context, rootNavigator: true).push(MaterialPageRoute(builder: (ctx) => ErrorScreen(details))); + if (!errorShown && details.exceptionAsString() != lastException) { + errorShown = true; + lastException = details.exceptionAsString(); + Navigator.of(context, rootNavigator: true).push(MaterialPageRoute(builder: (context) { + if (kReleaseMode) + return ErrorReportScreen(details); + else + return ErrorScreen(details); + })).then((_) => errorShown = false); + } }); return Container(); diff --git a/filcnaplo/lib/models/settings.dart b/filcnaplo/lib/models/settings.dart index 98918c5..cd6f0a5 100644 --- a/filcnaplo/lib/models/settings.dart +++ b/filcnaplo/lib/models/settings.dart @@ -6,6 +6,7 @@ import 'package:filcnaplo/theme.dart'; import 'package:flutter/material.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:provider/provider.dart'; +import 'package:uuid/uuid.dart'; enum Pages { home, grades, timetable, messages, absences } enum UpdateChannel { stable, beta, dev } @@ -47,6 +48,7 @@ class SettingsProvider extends ChangeNotifier { bool _swapABweeks; UpdateChannel _updateChannel; Config _config; + String _xFilcId; SettingsProvider({ required String language, @@ -66,6 +68,7 @@ class SettingsProvider extends ChangeNotifier { required bool swapABweeks, required UpdateChannel updateChannel, required Config config, + required String xFilcId, }) : _language = language, _startPage = startPage, _rounding = rounding, @@ -82,7 +85,8 @@ class SettingsProvider extends ChangeNotifier { _ABweeks = ABweeks, _swapABweeks = swapABweeks, _updateChannel = updateChannel, - _config = config { + _config = config, + _xFilcId = xFilcId { PackageInfo.fromPlatform().then((PackageInfo packageInfo) { _packageInfo = packageInfo; }); @@ -113,6 +117,7 @@ class SettingsProvider extends ChangeNotifier { swapABweeks: map["swap_ab_weeks"] == 1 ? true : false, updateChannel: UpdateChannel.values[map["update_channel"]], config: Config.fromJson(jsonDecode(map["config"] ?? "{}")), + xFilcId: map["x_filc_id"], ); } @@ -139,6 +144,7 @@ class SettingsProvider extends ChangeNotifier { "swap_ab_weeks": _swapABweeks ? 1 : 0, "notification_poll_interval": _notificationPollInterval, "config": jsonEncode(config.json), + "x_filc_id": _xFilcId, }; } @@ -167,6 +173,7 @@ class SettingsProvider extends ChangeNotifier { swapABweeks: false, updateChannel: UpdateChannel.stable, config: Config.fromJson({}), + xFilcId: Uuid().v4(), ); } @@ -189,6 +196,7 @@ class SettingsProvider extends ChangeNotifier { UpdateChannel get updateChannel => _updateChannel; PackageInfo? get packageInfo => _packageInfo; Config get config => _config; + String get xFilcId => _xFilcId; Future update( BuildContext context, { @@ -210,6 +218,7 @@ class SettingsProvider extends ChangeNotifier { bool? swapABweeks, UpdateChannel? updateChannel, Config? config, + String? xFilcId, }) async { if (language != null && language != _language) _language = language; if (startPage != null && startPage != _startPage) _startPage = startPage; @@ -229,6 +238,7 @@ class SettingsProvider extends ChangeNotifier { if (swapABweeks != null && swapABweeks != _swapABweeks) _swapABweeks = swapABweeks; if (updateChannel != null && updateChannel != _updateChannel) _updateChannel = updateChannel; if (config != null && config != _config) _config = config; + if (xFilcId != null && xFilcId != _xFilcId) _xFilcId = xFilcId; if (database == null) database = Provider.of(context, listen: false); await database.store.storeSettings(this); diff --git a/filcnaplo/pubspec.yaml b/filcnaplo/pubspec.yaml index 82ae9a4..bf0eac0 100644 --- a/filcnaplo/pubspec.yaml +++ b/filcnaplo/pubspec.yaml @@ -101,6 +101,17 @@ flutter: weight: 100 style: italic + - family: SpaceMono + fonts: + - asset: assets/fonts/SpaceMono/SpaceMono-Regular.ttf + - asset: assets/fonts/SpaceMono/SpaceMono-Bold.ttf + weight: 700 + - asset: assets/fonts/SpaceMono/SpaceMono-Italic.ttf + style: italic + - asset: assets/fonts/SpaceMono/SpaceMono-BoldItalic.ttf + weight: 700 + style: italic + flutter_icons: image_path: "assets/icons/ic_launcher.png" adaptive_icon_background: "#1F5B50" diff --git a/filcnaplo_mobile_ui b/filcnaplo_mobile_ui index 29313fe..33bfa51 160000 --- a/filcnaplo_mobile_ui +++ b/filcnaplo_mobile_ui @@ -1 +1 @@ -Subproject commit 29313fe1ee789f824eee394cf96263e02798f4bd +Subproject commit 33bfa51329b52f900835b06adc8f62b9cb16b8eb