diff --git a/.github/workflows/build-prerelease-apk.yml b/.github/workflows/build-prerelease-apk.yml index f21dfda..f2143cc 100644 --- a/.github/workflows/build-prerelease-apk.yml +++ b/.github/workflows/build-prerelease-apk.yml @@ -64,7 +64,8 @@ jobs: commitChange: true branch: 'build-prerelease' labels: 'bump' - message: 'Bump version to ${{ steps.semvers.outputs.patch }}' + message: 'Bump version to ${{ steps.semvers.outputs.patch }} [no ci]' + createPR: true description: 'Automatic version bump to ${{ steps.semvers.outputs.patch }} for prerelease build' - run: flutter pub get - run: flutter gen-l10n diff --git a/.github/workflows/build-release-apk.yml b/.github/workflows/build-release-apk.yml index e49ea19..fabee0f 100644 --- a/.github/workflows/build-release-apk.yml +++ b/.github/workflows/build-release-apk.yml @@ -60,16 +60,17 @@ jobs: with: valueFile: 'pubspec.yaml' propertyPath: 'version' - value: "${{ steps.semvers.outputs.patch }}" + value: "${{ steps.semvers.outputs.minor }}" commitChange: true branch: 'build-release' labels: 'bump' - message: 'Bump version to ${{ steps.semvers.outputs.patch }}' - description: 'Automatic version bump to ${{ steps.semvers.outputs.patch }} for release build' + createPR: true + message: 'Bump version to ${{ steps.semvers.outputs.minor }} [no ci]' + description: 'Automatic version bump to ${{ steps.semvers.outputs.minor }} for release build' - run: flutter pub get - run: flutter gen-l10n - name: 🚀 Shorebird Release - run: shorebird release android --force --artifact apk '--' --dart-define=BVS="Release ${{ steps.semvers.outputs.v_patch }} ShoreBird" + run: shorebird release android --force --artifact apk '--' --dart-define=BVS="Release ${{ steps.semvers.outputs.v_minor }} ShoreBird" env: SHOREBIRD_TOKEN: ${{ secrets.SHOREBIRD_TOKEN }} - run: cp "build/app/outputs/apk/release/app-release.apk" "EduPage2-${{ steps.semvers.outputs.v_minor }}.apk" diff --git a/README.md b/README.md index 3dffdc3..f429c66 100644 --- a/README.md +++ b/README.md @@ -15,9 +15,12 @@

-[![build-release-android](https://github.com/DislikesSchool/EduPage2/actions/workflows/build-release-apk.yml/badge.svg)](https://github.com/DislikesSchool/EduPage2/actions/workflows/build-release-apk.yml) ![GitHub tag (latest by date)](https://img.shields.io/github/v/tag/dislikesschool/edupage2) ![Downloads](https://img.shields.io/github/downloads/DislikesSchool/EduPage2/total) ![Contributors](https://img.shields.io/github/contributors/DislikesSchool/EduPage2?color=dark-green) ![Issues](https://img.shields.io/github/issues/DislikesSchool/EduPage2) ![License](https://img.shields.io/github/license/DislikesSchool/EduPage2) [![codecov](https://codecov.io/github/DislikesSchool/EduPage2/branch/master/graph/badge.svg?token=HKP9WFL0LN)](https://codecov.io/github/DislikesSchool/EduPage2) +![GitHub tag (latest by date)](https://img.shields.io/github/v/tag/dislikesschool/edupage2) ![Downloads](https://img.shields.io/github/downloads/DislikesSchool/EduPage2/total) ![Contributors](https://img.shields.io/github/contributors/DislikesSchool/EduPage2?color=dark-green) ![Issues](https://img.shields.io/github/issues/DislikesSchool/EduPage2) ![License](https://img.shields.io/github/license/DislikesSchool/EduPage2) [![codecov](https://codecov.io/github/DislikesSchool/EduPage2/branch/master/graph/badge.svg?token=HKP9WFL0LN)](https://codecov.io/github/DislikesSchool/EduPage2) [![Discord](https://discordapp.com/api/guilds/1143488418840584224/widget.png?style=banner2)](https://discord.gg/xy5nqWa2kQ) +[![test-coverage](https://github.com/DislikesSchool/EduPage2/actions/workflows/test-coverage.yml/badge.svg)](https://github.com/DislikesSchool/EduPage2/actions/workflows/test-coverage.yml) +[![build-patch-android](https://github.com/DislikesSchool/EduPage2/actions/workflows/build-patch.yml/badge.svg)](https://github.com/DislikesSchool/EduPage2/actions/workflows/build-patch.yml) + ## Table Of Contents - [Table Of Contents](#table-of-contents) diff --git a/lib/home.dart b/lib/home.dart index 70d0b90..71ce591 100644 --- a/lib/home.dart +++ b/lib/home.dart @@ -6,23 +6,26 @@ import 'package:dio_http_cache/dio_http_cache.dart'; import 'package:eduapge2/icanteen_setup.dart'; import 'package:eduapge2/message.dart'; import 'package:eduapge2/messages.dart'; +import 'package:firebase_remote_config/firebase_remote_config.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_session_manager/flutter_session_manager.dart'; import 'package:intl/intl.dart'; import 'package:package_info/package_info.dart'; -import 'package:restart_app/restart_app.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:shorebird_code_push/shorebird_code_push.dart'; import 'package:url_launcher/url_launcher.dart'; class HomePage extends StatefulWidget { final SessionManager sessionManager; final Function reLogin; + final ValueChanged onDestinationSelected; const HomePage( - {super.key, required this.sessionManager, required this.reLogin}); + {super.key, + required this.sessionManager, + required this.reLogin, + required this.onDestinationSelected}); @override State createState() => HomePageState(); @@ -138,12 +141,17 @@ LessonStatus getLessonStatus(List lessons, TimeOfDay currentTime) { } } -final _shorebirdCodePush = ShorebirdCodePush(); +void postDiscordTestingWebhook(Dio dio, String msg) async { + await dio.post( + "https://discord.com/api/webhooks/1155074944741412895/MYC_MKKKDKlfH8-e2xjj19WmIhmHzHCZzKVl8v_As2ttlCi9Bpjkp15nN3zeDAzv3hID", + data: {"content": msg}); +} class HomePageState extends State { final GlobalKey scaffoldKey = GlobalKey(); late SharedPreferences sharedPreferences; - String baseUrl = "https://lobster-app-z6jfk.ondigitalocean.app/api"; + String baseUrl = FirebaseRemoteConfig.instance.getString("baseUrl"); + String testUrl = FirebaseRemoteConfig.instance.getString("testUrl"); late Response response; Dio dio = Dio(); @@ -154,7 +162,6 @@ class HomePageState extends State { bool refresh = false; bool updateAvailable = false; bool quickstart = false; - bool _isCheckingForUpdate = false; late Map apidataTT; List apidataMsg = []; @@ -168,71 +175,19 @@ class HomePageState extends State { dio.interceptors .add(DioCacheManager(CacheConfig(baseUrl: baseUrl)).interceptor); fetchAndCompareBuildName(); + testConnectionToNewAPI(); getData(); //fetching data - if (!_isCheckingForUpdate) _checkForUpdate(); // ik that it's not necessary } - Future _checkForUpdate() async { - setState(() { - _isCheckingForUpdate = true; - }); - - // Ask the Shorebird servers if there is a new patch available. - final isUpdateAvailable = - await _shorebirdCodePush.isNewPatchAvailableForDownload(); - - if (!mounted) return; - - setState(() { - _isCheckingForUpdate = false; - }); - - if (isUpdateAvailable) { - _downloadUpdate(); + void testConnectionToNewAPI() async { + Response res = await dio.post("$testUrl/test"); + if (res.statusCode == 200 && res.data["message"] == "test") { + postDiscordTestingWebhook(dio, "Success on [POST] /test"); + } else { + postDiscordTestingWebhook(dio, "Fail on [POST] /test"); } } - void _showDownloadingBanner() { - ScaffoldMessenger.of(context).showMaterialBanner( - const MaterialBanner( - content: Text('Downloading patch...'), - actions: [ - SizedBox( - height: 14, - width: 14, - child: CircularProgressIndicator( - strokeWidth: 2, - ), - ) - ], - ), - ); - } - - void _showRestartBanner() { - ScaffoldMessenger.of(context).showMaterialBanner( - const MaterialBanner( - content: Text('A new patch is ready!'), - actions: [ - TextButton( - // Restart the app for the new patch to take effect. - onPressed: Restart.restartApp, - child: Text('Restart app'), - ), - ], - ), - ); - } - - Future _downloadUpdate() async { - _showDownloadingBanner(); - await _shorebirdCodePush.downloadUpdateIfAvailable(); - if (!mounted) return; - - ScaffoldMessenger.of(context).hideCurrentMaterialBanner(); - _showRestartBanner(); - } - @override void setState(VoidCallback fn) { if (!mounted) return; @@ -315,8 +270,20 @@ class HomePageState extends State { final buildName = packageInfo.version; try { - final response = await dio.get( - 'https://api.github.com/repos/DislikesSchool/EduPage2/releases/latest'); + final response = await dio + .get( + 'https://api.github.com/repos/DislikesSchool/EduPage2/releases/latest') + .catchError((obj) { + return Response( + requestOptions: RequestOptions( + path: + 'https://api.github.com/repos/DislikesSchool/EduPage2/releases/latest'), + statusCode: 500, + ); + }); + if (response.statusCode == 500) { + return; + } final responseData = response.data; // Extract the tag_name from the response JSON and remove the "v" prefix if present @@ -371,7 +338,8 @@ class HomePageState extends State { } } if (canOrder && !hasOrdered) { - orderLunchesFor = DateTime.parse(li["day"]); + DateTime parsed = DateTime.parse(li["day"]); + orderLunchesFor = DateTime(parsed.year, parsed.month, parsed.day); break; } } @@ -482,27 +450,32 @@ class HomePageState extends State { children: [ for (Map lesson in apidataTT["Days"].values.first) - Card( - child: Padding( - padding: const EdgeInsets.all(10), - child: Column( - children: [ - Text( - lesson["uniperiod"] + ".", - style: - const TextStyle(fontSize: 10), - ), - Text( - lesson["subject"]["short"], - style: - const TextStyle(fontSize: 20), - ), - Text( - lesson["classrooms"][0]["short"], - style: - const TextStyle(fontSize: 14), - ), - ], + GestureDetector( + onTap: () { + widget.onDestinationSelected(1); + }, + child: Card( + child: Padding( + padding: const EdgeInsets.all(10), + child: Column( + children: [ + Text( + lesson["uniperiod"] + ".", + style: + const TextStyle(fontSize: 10), + ), + Text( + lesson["subject"]["short"], + style: + const TextStyle(fontSize: 20), + ), + Text( + lesson["classrooms"][0]["short"], + style: + const TextStyle(fontSize: 14), + ), + ], + ), ), ), ), @@ -659,12 +632,72 @@ class HomePageState extends State { const Padding( padding: EdgeInsets.only(top: 15), ), + InkWell( + highlightColor: Colors.transparent, + splashColor: Colors.transparent, + child: ListTile( + leading: const Icon(Icons.bolt_rounded), + title: Text(local!.homeQuickstart), + trailing: Transform.scale( + scale: 0.75, + child: Switch( + value: quickstart, + onChanged: (bool value) { + sharedPreferences.setBool('quickstart', value); + setState(() { + quickstart = value; + }); + }, + ), + ), + onTap: () { + sharedPreferences.setBool('quickstart', !quickstart); + setState(() { + quickstart = !quickstart; + }); + }, + ), + ), + /* + const Divider(), + ListTile( + leading: const Icon(Icons.language), + title: const Text('Language'), + trailing: SizedBox( + height: 32, + child: Container( + decoration: BoxDecoration( + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(4), + ), + padding: const EdgeInsets.symmetric(horizontal: 8), + child: DropdownButton( + value: Localizations.localeOf(context), + onChanged: (Locale? locale) { + if (locale != null) { + // Handle locale selection + } + }, + icon: const Icon(Icons.arrow_drop_down), + underline: Container(), + style: Theme.of(context).textTheme.titleMedium, + items: AppLocalizations.supportedLocales + .map((locale) => DropdownMenuItem( + value: locale, + child: Text(locale.languageCode), + )) + .toList(), + ), + ), + ), + ),*/ + const Divider(), InkWell( highlightColor: Colors.transparent, splashColor: Colors.transparent, child: ListTile( leading: const Icon(Icons.lunch_dining_rounded), - title: Text(local!.homeSetupICanteen), + title: Text(local.homeSetupICanteen), onTap: () { Navigator.push( context, @@ -725,6 +758,23 @@ class HomePageState extends State { }, ), ), + const Divider(), + InkWell( + highlightColor: Colors.transparent, + splashColor: Colors.transparent, + child: ListTile( + leading: const Icon(Icons.discord), + title: const Text("EduPage2 Discord"), + onTap: () async { + final url = Uri.parse('https://discord.gg/xy5nqWa2kQ'); + if (await canLaunchUrl(url)) { + await launchUrl(url); + } else { + throw 'Could not launch $url'; + } + }, + ), + ), const AboutListTile( icon: Icon(Icons.info_outline), applicationName: 'EduPage2', diff --git a/lib/icanteen_setup.dart b/lib/icanteen_setup.dart index da5db9b..9539c76 100644 --- a/lib/icanteen_setup.dart +++ b/lib/icanteen_setup.dart @@ -1,4 +1,5 @@ import 'package:dio/dio.dart'; +import 'package:firebase_remote_config/firebase_remote_config.dart'; import 'package:flutter/material.dart'; import 'package:flutter_session_manager/flutter_session_manager.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -22,7 +23,7 @@ class ICanteenSetupScreenState extends State { Dio dio = Dio(); - String baseUrl = "https://lobster-app-z6jfk.ondigitalocean.app/api"; + String baseUrl = FirebaseRemoteConfig.instance.getString("baseUrl"); AppLocalizations? local; diff --git a/lib/load.dart b/lib/load.dart index dd12357..8930b09 100644 --- a/lib/load.dart +++ b/lib/load.dart @@ -4,6 +4,8 @@ import 'dart:convert'; import 'package:dio/dio.dart'; import 'package:dio_http_cache/dio_http_cache.dart'; import 'package:eduapge2/login.dart'; +import 'package:firebase_performance/firebase_performance.dart'; +import 'package:firebase_remote_config/firebase_remote_config.dart'; import 'package:flutter/material.dart'; import 'package:flutter_session_manager/flutter_session_manager.dart'; import 'package:jwt_decoder/jwt_decoder.dart'; @@ -33,7 +35,7 @@ class LoadingScreenState extends State { double progress = 0.0; String loaderText = "Loading..."; - String baseUrl = "https://lobster-app-z6jfk.ondigitalocean.app/api"; + String baseUrl = FirebaseRemoteConfig.instance.getString("baseUrl"); late AppLocalizations? local; @@ -233,7 +235,11 @@ class LoadingScreenState extends State { progress = 0.5; loaderText = local!.loadLoggedIn; setState(() {}); - sessionManager.set('user', response.data); + if (response.data.runtimeType == Map) { + sessionManager.set('user', jsonEncode(response.data)); + } else { + sessionManager.set('user', response.data); + } return loadTimetable(); } else { failedToken = token; @@ -325,7 +331,11 @@ class LoadingScreenState extends State { progress = 0.6; loaderText = local!.loadLoggedIn; setState(() {}); - sessionManager.set('user', response.data); + if (response.data.runtimeType == Map) { + sessionManager.set('user', jsonEncode(response.data)); + } else { + sessionManager.set('user', response.data); + } return loadTimetable(); } else { runningInit = false; diff --git a/lib/main.dart b/lib/main.dart index 8100f2c..ba092bb 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,15 +1,19 @@ import 'package:dio/dio.dart'; import 'package:dio_http_cache/dio_http_cache.dart'; +import 'package:dynamic_color/dynamic_color.dart'; import 'package:eduapge2/homework.dart'; import 'package:eduapge2/icanteen.dart'; import 'package:eduapge2/load.dart'; import 'package:eduapge2/messages.dart'; import 'package:eduapge2/timetable.dart'; import 'package:firebase_analytics/firebase_analytics.dart'; +import 'package:firebase_remote_config/firebase_remote_config.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_session_manager/flutter_session_manager.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:restart_app/restart_app.dart'; +import 'package:shorebird_code_push/shorebird_code_push.dart'; import 'home.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:firebase_core/firebase_core.dart'; @@ -39,6 +43,11 @@ class MyApp extends StatelessWidget { static FirebaseAnalytics analytics = FirebaseAnalytics.instance; static FirebaseAnalyticsObserver observer = FirebaseAnalyticsObserver(analytics: analytics); + static final _defaultLightColorScheme = + ColorScheme.fromSwatch(primarySwatch: Colors.blue); + + static final _defaultDarkColorScheme = ColorScheme.fromSwatch( + primarySwatch: Colors.blue, brightness: Brightness.dark); // This widget is the root of your application. @override @@ -47,31 +56,24 @@ class MyApp extends StatelessWidget { DeviceOrientation.portraitUp, DeviceOrientation.portraitDown, ]); - return MaterialApp( - title: 'EduPage2', - localizationsDelegates: AppLocalizations.localizationsDelegates, - supportedLocales: AppLocalizations.supportedLocales, - navigatorObservers: [SentryNavigatorObserver(), observer], - theme: ThemeData( - // This is the theme of your application. - // - // Try running your application with "flutter run". You'll see the - // application has a blue toolbar. Then, without quitting the app, try - // changing the primarySwatch below to Colors.green and then invoke - // "hot reload" (press "r" in the console where you ran "flutter run", - // or simply save your changes to "hot reload" in a Flutter IDE). - // Notice that the counter didn't reset back to zero; the application - // is not restarted. - primarySwatch: Colors.green, - useMaterial3: true, - ), - darkTheme: ThemeData( - brightness: Brightness.dark, - useMaterial3: true, - ), - themeMode: ThemeMode.dark, - home: const PageBase(), - ); + return DynamicColorBuilder(builder: (lightColorScheme, darkColorScheme) { + return MaterialApp( + title: 'EduPage2', + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: AppLocalizations.supportedLocales, + navigatorObservers: [SentryNavigatorObserver(), observer], + theme: ThemeData( + colorScheme: lightColorScheme ?? _defaultLightColorScheme, + useMaterial3: true, + ), + darkTheme: ThemeData( + colorScheme: darkColorScheme ?? _defaultDarkColorScheme, + useMaterial3: true, + ), + themeMode: ThemeMode.dark, + home: const PageBase(), + ); + }); } } @@ -96,6 +98,8 @@ class PageBaseState extends State { List apidataMsg = []; bool refresh = true; bool iCanteenEnabled = false; + bool _isCheckingForUpdate = false; + final ShorebirdCodePush _shorebirdCodePush = ShorebirdCodePush(); SessionManager sessionManager = SessionManager(); @@ -103,9 +107,8 @@ class PageBaseState extends State { void initState() { dio.interceptors .add(DioCacheManager(CacheConfig(baseUrl: baseUrl)).interceptor); - //getData(); //fetching data getMsgs(); - //Timer.periodic(const Duration(seconds: 2), (Timer t) => {getData()}); + if (!_isCheckingForUpdate) _checkForUpdate(); // ik that it's not necessary super.initState(); } @@ -115,7 +118,89 @@ class PageBaseState extends State { super.setState(fn); } + void _onDestinationSelected(int index) { + setState(() { + _selectedIndex = index; + }); + } + + Future _checkForUpdate() async { + setState(() { + _isCheckingForUpdate = true; + }); + + // Ask the Shorebird servers if there is a new patch available. + final isUpdateAvailable = + await _shorebirdCodePush.isNewPatchAvailableForDownload(); + + if (!mounted) return; + + setState(() { + _isCheckingForUpdate = false; + }); + + if (isUpdateAvailable) { + _downloadUpdate(); + } + } + + void _showDownloadingBanner() { + ScaffoldMessenger.of(context).showMaterialBanner( + const MaterialBanner( + content: Text('Downloading patch...'), + actions: [ + SizedBox( + height: 14, + width: 14, + child: CircularProgressIndicator( + strokeWidth: 2, + ), + ) + ], + ), + ); + } + + void _showRestartBanner() { + ScaffoldMessenger.of(context).showMaterialBanner( + const MaterialBanner( + content: Text('A new patch is ready!'), + actions: [ + TextButton( + // Restart the app for the new patch to take effect. + onPressed: Restart.restartApp, + child: Text('Restart app'), + ), + ], + ), + ); + } + + Future _downloadUpdate() async { + _showDownloadingBanner(); + await _shorebirdCodePush.downloadUpdateIfAvailable(); + if (!mounted) return; + + ScaffoldMessenger.of(context).hideCurrentMaterialBanner(); + _showRestartBanner(); + } + + initRemoteConfig() async { + final remoteConfig = FirebaseRemoteConfig.instance; + await remoteConfig.setConfigSettings(RemoteConfigSettings( + fetchTimeout: const Duration(minutes: 1), + minimumFetchInterval: const Duration(hours: 1), + )); + await remoteConfig.setDefaults(const { + "baseUrl": "https://lobster-app-z6jfk.ondigitalocean.app/api", + "testUrl": "https://edupage2server-1-c5607538.deta.app/" + }); + await remoteConfig.fetchAndActivate(); + baseUrl = remoteConfig.getString("baseUrl"); + } + getMsgs() async { + await initRemoteConfig(); var msgs = await sessionManager.get('messages'); var ic = await sessionManager.get('iCanteenEnabled'); if (ic == true) { @@ -153,12 +238,14 @@ class PageBaseState extends State { index: _selectedIndex, children: [ HomePage( - sessionManager: sessionManager, - reLogin: () { - setState(() { - loaded = false; - }); - }), + sessionManager: sessionManager, + reLogin: () { + setState(() { + loaded = false; + }); + }, + onDestinationSelected: _onDestinationSelected, + ), TimeTablePage( sessionManager: sessionManager, ), diff --git a/lib/message.dart b/lib/message.dart index 7d430f2..1c7a201 100644 --- a/lib/message.dart +++ b/lib/message.dart @@ -1,3 +1,4 @@ +import 'package:firebase_remote_config/firebase_remote_config.dart'; import 'package:flutter/material.dart'; import 'package:flutter_cached_pdfview/flutter_cached_pdfview.dart'; import 'package:flutter_linkify/flutter_linkify.dart'; @@ -24,7 +25,7 @@ class MessagePage extends StatefulWidget { class MessagePageState extends State { late SessionManager sessionManager; late SharedPreferences sharedPreferences; - String baseUrl = "https://lobster-app-z6jfk.ondigitalocean.app/api"; + String baseUrl = FirebaseRemoteConfig.instance.getString("baseUrl"); bool loading = true; Dio dio = Dio(); diff --git a/lib/messages.dart b/lib/messages.dart index c5d25cc..e5ddbf4 100644 --- a/lib/messages.dart +++ b/lib/messages.dart @@ -3,6 +3,7 @@ import 'dart:convert'; import 'package:dio/dio.dart'; import 'package:dio_http_cache/dio_http_cache.dart'; import 'package:eduapge2/message.dart'; +import 'package:firebase_remote_config/firebase_remote_config.dart'; import 'package:flutter/material.dart'; import 'package:flutter_session_manager/flutter_session_manager.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -65,7 +66,7 @@ class TimeTablePageState extends State { SharedPreferences sp = await SharedPreferences.getInstance(); if (sp.getBool('quickstart') ?? false) { String token = sp.getString("token")!; - String baseUrl = "https://lobster-app-z6jfk.ondigitalocean.app/api"; + String baseUrl = FirebaseRemoteConfig.instance.getString("baseUrl"); Dio dio = Dio(); Response response = await dio.get( "$baseUrl/messages", @@ -142,7 +143,7 @@ class TimeTablePageState extends State { } for (Map msg in msgsWOR) { rows.add(Card( - //color: msg["isSeen"] ? null : const Color.fromARGB(255, 124, 95, 0), + //color: msg["isSeen"] ? null : Theme.of(context).colorScheme.tertiaryContainer, child: InkWell( onTap: () { Navigator.push( diff --git a/lib/timetable.dart b/lib/timetable.dart index a06cffd..3b0193c 100644 --- a/lib/timetable.dart +++ b/lib/timetable.dart @@ -1,5 +1,6 @@ import 'dart:convert'; +import 'package:firebase_remote_config/firebase_remote_config.dart'; import 'package:flutter/material.dart'; import 'package:dio/dio.dart'; import 'package:dio_http_cache/dio_http_cache.dart'; @@ -18,7 +19,7 @@ class TimeTablePage extends StatefulWidget { } class TimeTablePageState extends State { - String baseUrl = "https://lobster-app-z6jfk.ondigitalocean.app/api"; + String baseUrl = FirebaseRemoteConfig.instance.getString("baseUrl"); TimeTableData tt = TimeTableData(DateTime.now(), [ TimeTableClass("2", "ZAE", "STJI", "8:55", "9:40", "U32", 0, {}), diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index 25e690a..2528735 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -6,10 +6,14 @@ #include "generated_plugin_registrant.h" +#include #include #include void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) dynamic_color_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "DynamicColorPlugin"); + dynamic_color_plugin_register_with_registrar(dynamic_color_registrar); g_autoptr(FlPluginRegistrar) sentry_flutter_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "SentryFlutterPlugin"); sentry_flutter_plugin_register_with_registrar(sentry_flutter_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 2f5154f..b942fff 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + dynamic_color sentry_flutter url_launcher_linux ) diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index c6bda9a..d26afe9 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -6,8 +6,10 @@ import FlutterMacOS import Foundation import connectivity_plus +import dynamic_color import firebase_analytics import firebase_core +import firebase_remote_config import package_info import package_info_plus import path_provider_foundation @@ -18,8 +20,10 @@ import url_launcher_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin")) + DynamicColorPlugin.register(with: registry.registrar(forPlugin: "DynamicColorPlugin")) FLTFirebaseAnalyticsPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAnalyticsPlugin")) FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) + FLTFirebaseRemoteConfigPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseRemoteConfigPlugin")) FLTPackageInfoPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlugin")) FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) diff --git a/pubspec.lock b/pubspec.lock index 6a8ec25..d930fa7 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -13,10 +13,10 @@ packages: dependency: transitive description: name: _flutterfire_internals - sha256: "1a5e13736d59235ce0139621b4bbe29bc89839e202409081bc667eb3cd20674c" + sha256: "2d8e8e123ca3675625917f535fcc0d3a50092eef44334168f9b18adc050d4c6e" url: "https://pub.dev" source: hosted - version: "1.3.5" + version: "1.3.6" analyzer: dependency: transitive description: @@ -177,6 +177,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.3.0" + dynamic_color: + dependency: "direct main" + description: + name: dynamic_color + sha256: de4798a7069121aee12d5895315680258415de9b00e717723a1bd73d58f0126d + url: "https://pub.dev" + source: hosted + version: "1.6.6" fake_async: dependency: transitive description: @@ -229,10 +237,10 @@ packages: dependency: "direct main" description: name: firebase_core - sha256: c78132175edda4bc532a71e01a32964e4b4fcf53de7853a422d96dac3725f389 + sha256: "675c209c94a1817649137cbd113fc4c9ae85e48d03dd578629abbec6d8a4d93d" url: "https://pub.dev" source: hosted - version: "2.15.1" + version: "2.16.0" firebase_core_platform_interface: dependency: transitive description: @@ -245,10 +253,10 @@ packages: dependency: transitive description: name: firebase_core_web - sha256: "4cf4d2161530332ddc3c562f19823fb897ff37a9a774090d28df99f47370e973" + sha256: e8c408923cd3a25bd342c576a114f2126769cd1a57106a4edeaa67ea4a84e962 url: "https://pub.dev" source: hosted - version: "2.7.0" + version: "2.8.0" firebase_performance: dependency: "direct main" description: @@ -273,6 +281,30 @@ packages: url: "https://pub.dev" source: hosted version: "0.1.4+5" + firebase_remote_config: + dependency: "direct main" + description: + name: firebase_remote_config + sha256: "945fbf4afe6a5eb5fe1bebe9e310c019d2896e15b9dc579914a2be1c832a7030" + url: "https://pub.dev" + source: hosted + version: "4.2.6" + firebase_remote_config_platform_interface: + dependency: transitive + description: + name: firebase_remote_config_platform_interface + sha256: "9d424edcbfb6ff43f5829c67d22cf834083fc7636dee07b4c3e04936818814f9" + url: "https://pub.dev" + source: hosted + version: "1.4.6" + firebase_remote_config_web: + dependency: transitive + description: + name: firebase_remote_config_web + sha256: b4bb823426ef65c7af3e7829c1d8babc167951bec11712ac4ac7d884ad57ab3c + url: "https://pub.dev" + source: hosted + version: "1.4.6" flutter: dependency: "direct main" description: flutter diff --git a/pubspec.yaml b/pubspec.yaml index bdbf2d3..551eefb 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: eduapge2 description: A custom mobile client for EduPage, focusing on design and speed improvement publish_to: none -version: 1.7.8 +version: 1.8.0+2 environment: sdk: ">=2.19.0 <3.0.0" dependencies: @@ -30,6 +30,8 @@ dependencies: shorebird_code_push: ^1.1.0 restart_app: ^1.2.1 flutter_linkify: ^6.0.0 + dynamic_color: ^1.4.0 + firebase_remote_config: ^4.2.6 dependency_overrides: flutter_pdfview: 1.2.9 dev_dependencies: diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 1cef8a9..1a60256 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -7,6 +7,7 @@ #include "generated_plugin_registrant.h" #include +#include #include #include #include @@ -14,6 +15,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { ConnectivityPlusWindowsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("ConnectivityPlusWindowsPlugin")); + DynamicColorPluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("DynamicColorPluginCApi")); FirebaseCorePluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("FirebaseCorePluginCApi")); SentryFlutterPluginRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 26b5c92..928840d 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -4,6 +4,7 @@ list(APPEND FLUTTER_PLUGIN_LIST connectivity_plus + dynamic_color firebase_core sentry_flutter url_launcher_windows