From 9464a21cb6d0aad54a7cd6264a877db0e7bf0b95 Mon Sep 17 00:00:00 2001 From: Paul <35733278+PAException@users.noreply.github.com> Date: Fri, 24 Nov 2023 22:13:28 +0100 Subject: [PATCH 1/9] Added issue templates --- .github/ISSUE_TEMPLATE/bug-report.md | 32 +++++++++++++++++++++++ .github/ISSUE_TEMPLATE/feature_request.md | 20 ++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug-report.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md new file mode 100644 index 0000000..8ba00f3 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -0,0 +1,32 @@ +--- +name: Bug report +about: Create a report to help us improve +title: "[BUG] " +labels: bug, in triage +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Smartphone (please complete the following information):** + - Device: [e.g. iPhone6] + - OS: [e.g. iOS8.1] + - Version [e.g. 22] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..8211e3b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea +title: '' +labels: feature, in triage +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. From e3d0f124fe821b1c76ec711c5fe886bb92a31ca9 Mon Sep 17 00:00:00 2001 From: Paul Huerkamp <35733278+PAException@users.noreply.github.com> Date: Wed, 29 Nov 2023 00:03:35 +0100 Subject: [PATCH 2/9] Fixed most common errors of v1.0.0 --- lib/src/backend/api/request_service.dart | 26 ++++++++++++------- .../database/nosql/base/collection.dart | 5 ++-- .../database/nosql/base/references.dart | 8 ++++++ .../database/nosql/local_nosql_database.dart | 8 ++++-- .../database/nosql/storage/storage_cache.dart | 10 +++---- .../database/nosql/storage/storage_state.dart | 2 +- .../nosql/storage/storage_streams.dart | 24 ++++++++++------- .../services/firebase/firebase_config.dart | 15 ++++++++++- lib/src/view/pages/article/article_card.dart | 10 ++++++- .../settings/subject/subject_extended.dart | 8 +++--- .../view/pages/timetable/timetable_page.dart | 2 +- 11 files changed, 82 insertions(+), 36 deletions(-) diff --git a/lib/src/backend/api/request_service.dart b/lib/src/backend/api/request_service.dart index 059549b..1178b07 100644 --- a/lib/src/backend/api/request_service.dart +++ b/lib/src/backend/api/request_service.dart @@ -46,12 +46,12 @@ class RequestService { var prepareTime = stopwatch.elapsedMilliseconds; //Execute request - return _request(request).timeout(timeout, onTimeout: () { - //On timeout return response with status = 999 - return http.Response("", 999); - - //TODO? create retry service? (callback?), exponential backoff? - }).then((response) { + //TODO? create retry service? (callback?), exponential backoff? + //On timeout or error return response with status = 999 + return _request(request) + .onError((error, stackTrace) => http.Response("", 999)) + .timeout(timeout, onTimeout: () => http.Response("", 999)) + .then((response) { stopwatch.stop(); RequestAnalysis analysis; @@ -125,7 +125,15 @@ class RequestAnalysis { final int? responseSize; final bool timedOut; - const RequestAnalysis({required this.prepareTime, required this.responseTime, required this.responseSize, required this.timedOut,}) : assert(timedOut || responseTime != null); - - const RequestAnalysis.timedOut(this.prepareTime) : timedOut = true, responseTime = null, responseSize = null; + const RequestAnalysis({ + required this.prepareTime, + required this.responseTime, + required this.responseSize, + required this.timedOut, + }) : assert(timedOut || responseTime != null); + + const RequestAnalysis.timedOut(this.prepareTime) + : timedOut = true, + responseTime = null, + responseSize = null; } diff --git a/lib/src/backend/database/nosql/base/collection.dart b/lib/src/backend/database/nosql/base/collection.dart index a44d2a5..e689ceb 100644 --- a/lib/src/backend/database/nosql/base/collection.dart +++ b/lib/src/backend/database/nosql/base/collection.dart @@ -31,8 +31,9 @@ class Collection<T> extends CollectionReference<T> { //TODO docs Future<List<Document<T>>> documents() async { - var cached = _storage.state.getCachedCollection(this); - if (cached != null) return cached.map((e) => e.storage(_storage)).toList(); + var cached = _storage.state.getCachedCollection<T>(this); + print(cached.runtimeType); + if (cached != null) return cached.cast<DocumentReference<T>>().map((e) => e.storage(_storage)).cast<Document<T>>().toList(); var collectionData = await _storage.getCollection(path); _storage.state.cacheCollection(this, collectionData); diff --git a/lib/src/backend/database/nosql/base/references.dart b/lib/src/backend/database/nosql/base/references.dart index beb585e..9e17fa8 100644 --- a/lib/src/backend/database/nosql/base/references.dart +++ b/lib/src/backend/database/nosql/base/references.dart @@ -33,6 +33,8 @@ abstract class Reference<T> { @override int get hashCode => path.hashCode; + + Reference<D> cast<D>(Parser<D> parser); } /// Same as Reference<T>, but only to documents. @@ -55,6 +57,9 @@ class DocumentReference<T> extends Reference<T> { ); } + @override + DocumentReference<D> cast<D>(Parser<D> parser) => DocumentReference<D>(path, parser); + /// Makes the reference concrete, links a storage to the reference. @nonVirtual Document<T> storage(Storage storage) => Document<T>.ref(storage, this); @@ -76,6 +81,9 @@ class CollectionReference<T> extends Reference<T> { parser, ); + @override + CollectionReference<D> cast<D>(Parser<D> parser) => CollectionReference<D>(path, parser); + /// Makes the reference concrete, links a storage to the reference. @nonVirtual Collection<T> storage(Storage storage) => Collection<T>.ref(storage, this); diff --git a/lib/src/backend/database/nosql/local_nosql_database.dart b/lib/src/backend/database/nosql/local_nosql_database.dart index 8e8b250..34c4718 100644 --- a/lib/src/backend/database/nosql/local_nosql_database.dart +++ b/lib/src/backend/database/nosql/local_nosql_database.dart @@ -102,7 +102,9 @@ class LocalNosqlDatabase { ); //Save new stream and return - latest.then((value) => newController.add(value)); + latest.then((value) { + if (!newController.isClosed) newController.add(value); + }); return (_documentSnapshots[path] = newController).stream; } @@ -124,7 +126,9 @@ class LocalNosqlDatabase { ); //Save new stream and return - latest.then((value) => newController.add(value)); + latest.then((value) { + if (!newController.isClosed) newController.add(value); + }); return (_collectionSnapshots[path] = newController).stream; } } diff --git a/lib/src/backend/database/nosql/storage/storage_cache.dart b/lib/src/backend/database/nosql/storage/storage_cache.dart index c01cde4..d507d9f 100644 --- a/lib/src/backend/database/nosql/storage/storage_cache.dart +++ b/lib/src/backend/database/nosql/storage/storage_cache.dart @@ -14,7 +14,7 @@ class StorageCache { /// Writes the data of the document to the cache and also references the /// document in the collection cache if possible. - void setDocument(DocumentReference document, Map<String, dynamic> data) { + void setDocument<T>(DocumentReference<T> document, Map<String, dynamic> data) { debugPrint("[${document.id}] updating cached document: $data"); //Update document cache _documentCache[document] = data; @@ -60,12 +60,12 @@ class StorageCache { } //TODO docs - void setCollection(CollectionReference collection, CollectionData collectionData) { + void setCollection<T>(CollectionReference<T> collection, CollectionData collectionData) { debugPrint("[${collection.id}] setting cached collection: $collectionData"); //Map collection data to document references var documents = collectionData.mapToList((key, value) { - var document = DocumentReference(key, collection.parser); + var document = DocumentReference<T>(key, collection.parser); //Update each document setDocument(document, value); @@ -80,9 +80,9 @@ class StorageCache { List<DocumentReference<T>>? getCollection<T>(CollectionReference<T> collection) { debugPrint("[${collection.id}] getting cached collection"); - var refs = _collectionCache[collection]?.toList() ?? []; + var refs = _collectionCache[collection]; - return refs.cast<DocumentReference<T>>(); + return refs?.map((e) => e.cast(collection.parser)).toList() ?? []; } /// Returns if the data to the given reference, document or collection, diff --git a/lib/src/backend/database/nosql/storage/storage_state.dart b/lib/src/backend/database/nosql/storage/storage_state.dart index 62a9e01..bb5664a 100644 --- a/lib/src/backend/database/nosql/storage/storage_state.dart +++ b/lib/src/backend/database/nosql/storage/storage_state.dart @@ -100,7 +100,7 @@ class StorageState { List<DocumentReference<T>>? getCachedCollection<T>( CollectionReference<T> collection, ) { - return _cache.getCollection(collection); + return _cache.getCollection<T>(collection); } //TODO docs diff --git a/lib/src/backend/database/nosql/storage/storage_streams.dart b/lib/src/backend/database/nosql/storage/storage_streams.dart index 47831a7..c03966f 100644 --- a/lib/src/backend/database/nosql/storage/storage_streams.dart +++ b/lib/src/backend/database/nosql/storage/storage_streams.dart @@ -102,11 +102,13 @@ class StorageStreams { var stream = createNativeStream.call(document.path); _documentSubscriptions[document] = stream.listen(handleData); } else { - _dispatchDocument( - document: document, - data: _latestDocumentData[document], - intercept: intercept, - ); + Future.doWhile(() => _latestDocumentData[document] == null).then((_) { + _dispatchDocument( + document: document, + data: _latestDocumentData[document], + intercept: intercept, + ); + }); } return newController.stream; @@ -153,11 +155,13 @@ class StorageStreams { //Save the stream subscription _collectionSubscriptions[collection] = stream.listen(handleData); } else { - _dispatchCollection( - collection: collection, - collectionData: _latestCollectionData[collection]!, - intercept: intercept, - ); + Future.doWhile(() => _latestCollectionData[collection] == null).then((_) { + _dispatchCollection( + collection: collection, + collectionData: _latestCollectionData[collection]!, + intercept: intercept, + ); + }); } return newController.stream; diff --git a/lib/src/services/firebase/firebase_config.dart b/lib/src/services/firebase/firebase_config.dart index c4c3f50..5531ba1 100644 --- a/lib/src/services/firebase/firebase_config.dart +++ b/lib/src/services/firebase/firebase_config.dart @@ -3,6 +3,7 @@ */ import 'dart:io'; +import 'dart:math'; import 'package:engelsburg_planer/src/backend/database/nosql/model/settings/substitute_settings.dart'; import 'package:engelsburg_planer/src/backend/database/state/user_state.dart'; @@ -148,6 +149,18 @@ class FirebaseConfig { fetchTimeout: const Duration(minutes: 1), minimumFetchInterval: const Duration(hours: 1), )); - remoteConfig.fetchAndActivate(); + + int backOff = 0; + Future.doWhile(() async { + try { + await remoteConfig.fetchAndActivate(); + + return true; + } catch (_) { + await Future.delayed(Duration(seconds: pow(2, backOff++).toInt())); + + return false; + } + }); } } diff --git a/lib/src/view/pages/article/article_card.dart b/lib/src/view/pages/article/article_card.dart index fea889f..f1f20dc 100644 --- a/lib/src/view/pages/article/article_card.dart +++ b/lib/src/view/pages/article/article_card.dart @@ -245,7 +245,15 @@ class ShareIconButton extends StatelessWidget { if (url == null) return Container(); return TapDebouncer( - onTap: () => Share.share(url!), + onTap: () async { + final box = context.findRenderObject() as RenderBox?; + + var result = await Share.shareWithResult( + url!, + sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size, + ); + if (result.status == ShareResultStatus.success) onShare?.call(); + }, builder: (context, onTap) => IconButton( onPressed: onTap, tooltip: context.l10n.share, diff --git a/lib/src/view/pages/settings/subject/subject_extended.dart b/lib/src/view/pages/settings/subject/subject_extended.dart index 1fdf5ce..ff8a84b 100644 --- a/lib/src/view/pages/settings/subject/subject_extended.dart +++ b/lib/src/view/pages/settings/subject/subject_extended.dart @@ -125,7 +125,7 @@ class _ExtendedSubjectPageState extends State<ExtendedSubjectPage> icon: const Icon(Icons.delete), color: Theme.of(context).colorScheme.onSurface, onPressed: () => context.dialog(const ConfirmDeleteSubjectDialog()).then((value) { - if (!value) return; + if (!(value ?? false)) return; widget.subjectDoc.delete(); Timetable.entries().defaultStorage(context).documents().then((items) { @@ -513,8 +513,8 @@ class _ExtendedSubjectListTileState extends State<ExtendedSubjectListTile> @override Widget build(BuildContext context) { super.build(context); - var subject = widget.subject.data!; - _customNameController ??= TextEditingController(text: subject.parsedName(context)); + var subject = widget.subject.data; + _customNameController ??= TextEditingController(text: subject?.parsedName(context) ?? context.l10n.noSubjectSelected); return ListTile( leading: Padding( @@ -578,7 +578,7 @@ class _ExtendedSubjectListTileState extends State<ExtendedSubjectListTile> }, ), ), - subtitle: Text([ + subtitle: subject == null ? null : Text([ if (subject.customName != null) BaseSubject.get(subject).l10n(context)!, BaseSubject.get(subject).l10nGroup(context), ].join(" - ")), diff --git a/lib/src/view/pages/timetable/timetable_page.dart b/lib/src/view/pages/timetable/timetable_page.dart index 6a2a81a..164c061 100644 --- a/lib/src/view/pages/timetable/timetable_page.dart +++ b/lib/src/view/pages/timetable/timetable_page.dart @@ -45,7 +45,7 @@ class TimetablePageState extends State<TimetablePage> { if (_animating != null) return; //Remove all - _timetable.forIndexed( + List.of(_timetable).forIndexed( (index, element) { _timetable.removeAt(index); _animatedList.currentState?.removeItem( From f3005badfd34277d119f5269c81a16f237fc6488 Mon Sep 17 00:00:00 2001 From: Paul Huerkamp <35733278+PAException@users.noreply.github.com> Date: Fri, 1 Dec 2023 11:40:08 +0100 Subject: [PATCH 3/9] Added automatic build script --- build.sh | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100755 build.sh diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..4edac87 --- /dev/null +++ b/build.sh @@ -0,0 +1,67 @@ +#!/bin/bash + +####################################### +# Flutter Version Increment and Build Script +####################################### + +# Script Usage: +# - This script increments the version number in the Flutter project's pubspec.yaml file. +# - It provides options to increment the MAJOR, MINOR, or PATCH version components. +# - Release builds for iOS and Android can be disabled using the --no-build option. + +# Usage: +# ./build.sh [OPTIONS] + +# Available Options: +# --major Increment the MAJOR version component. +# --minor Increment the MINOR version component. +# --patch Increment the PATCH version component. +# --no-build Disable release builds for iOS and Android. + +# Function to increment version components in pubspec.yaml +increment_flutter_version() { + PUBSPEC_FILE="pubspec.yaml" + CURRENT_VERSION=$(awk '/version:/ {print $2}' "$PUBSPEC_FILE" | tr -d "'") + MAJOR=$(echo "$CURRENT_VERSION" | cut -d. -f1) + MINOR=$(echo "$CURRENT_VERSION" | cut -d. -f2) + PATCH=$(echo "$CURRENT_VERSION" | cut -d. -f3 | cut -d+ -f1) + BUILD=$(echo "$CURRENT_VERSION" | cut -d+ -f2) + + if [ "$1" == "--major" ]; then + NEW_VERSION="$((MAJOR + 1)).0.0+0" + elif [ "$1" == "--minor" ]; then + NEW_VERSION="$MAJOR.$((MINOR + 1)).0+0" + elif [ "$1" == "--patch" ]; then + NEW_VERSION="$MAJOR.$MINOR.$((PATCH + 1))+0" + else + NEW_VERSION="$MAJOR.$MINOR.$PATCH+$((BUILD + 1))" + fi + + awk -v current_version="$CURRENT_VERSION" -v new_version="$NEW_VERSION" \ + '$1 == "version:" && $2 == current_version { $2 = new_version } { print }' \ + "$PUBSPEC_FILE" > temp && mv temp "$PUBSPEC_FILE" + + echo "Flutter version incremented to $NEW_VERSION" +} + +# Function to execute Flutter release builds for iOS and Android +execute_flutter_release_builds() { + flutter build ipa --release + flutter build appbundle --release +} + +# Increment version regardless of --no-build presence +if [ "$1" == "--major" ] || [ "$1" == "--minor" ] || [ "$1" == "--patch" ]; then + increment_flutter_version "$1" +elif [ "$2" == "--major" ] || [ "$2" == "--minor" ] || [ "$2" == "--patch" ]; then + increment_flutter_version "$2" +else + increment_flutter_version +fi + +# Check for --no-build option to disable release builds +if [[ "$1" == "--no-build" || "$2" == "--no-build" ]]; then + echo "Release builds disabled." +else + execute_flutter_release_builds +fi From b257d1828bc6591aea7d4532179cb282b901968b Mon Sep 17 00:00:00 2001 From: Paul Huerkamp <35733278+PAException@users.noreply.github.com> Date: Fri, 1 Dec 2023 12:33:37 +0100 Subject: [PATCH 4/9] Migrated textScaleFactor to textScaler --- lib/src/backend/database/nosql/base/collection.dart | 1 - lib/src/view/pages/article/article_saved_page.dart | 4 ++-- lib/src/view/pages/grade/grade_average_circle.dart | 2 +- lib/src/view/pages/grade/grade_page.dart | 1 - lib/src/view/pages/home_page.dart | 2 +- .../pages/settings/settings_substitute_page.dart | 2 +- .../settings/subject/settings_subject_page.dart | 2 +- .../pages/settings/subject/subject_extended.dart | 2 +- .../pages/settings/subject/subject_select_page.dart | 2 +- lib/src/view/pages/substitute/substitute_card.dart | 4 ++-- .../pages/substitute/substitute_message_card.dart | 2 +- lib/src/view/pages/substitute/substitute_page.dart | 4 ++-- lib/src/view/pages/substitute/substitute_tab.dart | 4 ++-- lib/src/view/pages/task/task_card.dart | 2 +- lib/src/view/pages/task/task_card_landscape.dart | 8 ++++---- lib/src/view/pages/task/task_page.dart | 4 ++-- lib/src/view/pages/timetable/timetable_card.dart | 12 ++++++------ lib/src/view/pages/timetable/timetable_page.dart | 8 ++++---- 18 files changed, 32 insertions(+), 34 deletions(-) diff --git a/lib/src/backend/database/nosql/base/collection.dart b/lib/src/backend/database/nosql/base/collection.dart index e689ceb..703cac2 100644 --- a/lib/src/backend/database/nosql/base/collection.dart +++ b/lib/src/backend/database/nosql/base/collection.dart @@ -32,7 +32,6 @@ class Collection<T> extends CollectionReference<T> { //TODO docs Future<List<Document<T>>> documents() async { var cached = _storage.state.getCachedCollection<T>(this); - print(cached.runtimeType); if (cached != null) return cached.cast<DocumentReference<T>>().map((e) => e.storage(_storage)).cast<Document<T>>().toList(); var collectionData = await _storage.getCollection(path); diff --git a/lib/src/view/pages/article/article_saved_page.dart b/lib/src/view/pages/article/article_saved_page.dart index 2e2e48c..ab82831 100644 --- a/lib/src/view/pages/article/article_saved_page.dart +++ b/lib/src/view/pages/article/article_saved_page.dart @@ -53,7 +53,7 @@ class SavedArticlePage extends StatelessWidget { padding: const EdgeInsets.only(top: 30), child: Text( context.l10n.noArticlesSaved, - textScaleFactor: 1.2, + textScaler: const TextScaler.linear(1.2), style: TextStyle( color: DefaultTextStyle.of(context).style.color!.withOpacity(3 / 4), ), @@ -95,7 +95,7 @@ class SavedArticlePage extends StatelessWidget { padding: const EdgeInsets.only(top: 30), child: Text( context.l10n.noArticlesSaved, - textScaleFactor: 1.2, + textScaler: const TextScaler.linear(1.2), style: TextStyle( color: DefaultTextStyle.of(context).style.color!.withOpacity(3 / 4), ), diff --git a/lib/src/view/pages/grade/grade_average_circle.dart b/lib/src/view/pages/grade/grade_average_circle.dart index f5d9294..b75c216 100644 --- a/lib/src/view/pages/grade/grade_average_circle.dart +++ b/lib/src/view/pages/grade/grade_average_circle.dart @@ -51,7 +51,7 @@ class _AverageGradeCircleState extends State<AverageGradeCircle> with TickerProv child: Center( child: Text( (widget.average * animation).roundToPlaces(1).toString(), - textScaleFactor: 3, + textScaler: const TextScaler.linear(3), style: TextStyle( color: widget.percent >= (1 / 3) ? null : Colors.red, ), diff --git a/lib/src/view/pages/grade/grade_page.dart b/lib/src/view/pages/grade/grade_page.dart index 487d54f..ff2d90e 100644 --- a/lib/src/view/pages/grade/grade_page.dart +++ b/lib/src/view/pages/grade/grade_page.dart @@ -209,7 +209,6 @@ class GradesPage extends StatelessWidget { .roundToPlaces(2) .toString(), textAlign: TextAlign.right, - textScaleFactor: 1, style: const TextStyle( fontWeight: FontWeight.w600), ) diff --git a/lib/src/view/pages/home_page.dart b/lib/src/view/pages/home_page.dart index d619d19..1ecd5ab 100644 --- a/lib/src/view/pages/home_page.dart +++ b/lib/src/view/pages/home_page.dart @@ -265,7 +265,7 @@ class HomePageDrawer extends StatelessWidget { Expanded( child: Text( context.l10n.appTitle, - textScaleFactor: 1.5, + textScaler: const TextScaler.linear(1.5), textAlign: TextAlign.center, ), ), diff --git a/lib/src/view/pages/settings/settings_substitute_page.dart b/lib/src/view/pages/settings/settings_substitute_page.dart index 646213f..9a970e9 100644 --- a/lib/src/view/pages/settings/settings_substitute_page.dart +++ b/lib/src/view/pages/settings/settings_substitute_page.dart @@ -31,7 +31,7 @@ class SubstituteSettingsPage extends StatelessWidget { title: Text( "${context.l10n.filterBy}:", style: const TextStyle(fontWeight: FontWeight.bold), - textScaleFactor: 1.2, + textScaler: const TextScaler.linear(1.2), ), ), SwitchExpandable( diff --git a/lib/src/view/pages/settings/subject/settings_subject_page.dart b/lib/src/view/pages/settings/subject/settings_subject_page.dart index 636bde2..d3600d2 100644 --- a/lib/src/view/pages/settings/subject/settings_subject_page.dart +++ b/lib/src/view/pages/settings/subject/settings_subject_page.dart @@ -105,7 +105,7 @@ class _SubjectTileState extends State<SubjectTile> { return ListTile( title: Text( subject?.data?.parsedName(context) ?? widget.baseSubject.l10n(context)!, - textScaleFactor: 1.2, + textScaler: const TextScaler.linear(1.2), ), leading: Disabled( disabled: !enabled, diff --git a/lib/src/view/pages/settings/subject/subject_extended.dart b/lib/src/view/pages/settings/subject/subject_extended.dart index ff8a84b..66c0109 100644 --- a/lib/src/view/pages/settings/subject/subject_extended.dart +++ b/lib/src/view/pages/settings/subject/subject_extended.dart @@ -446,7 +446,7 @@ class _ExtendedSubjectPageState extends State<ExtendedSubjectPage> title: Text(grade.name ?? "${i + 1}. $gradeTypeName"), trailing: Text( grade.value(config.usePoints).toString(), - textScaleFactor: 1.5, + textScaler: const TextScaler.linear(1.5), ), subtitle: Text(grade.created.formatEEEEddMM(context)), onTap: () { diff --git a/lib/src/view/pages/settings/subject/subject_select_page.dart b/lib/src/view/pages/settings/subject/subject_select_page.dart index ea14b47..3756c2d 100644 --- a/lib/src/view/pages/settings/subject/subject_select_page.dart +++ b/lib/src/view/pages/settings/subject/subject_select_page.dart @@ -79,7 +79,7 @@ class SelectSubjectPage extends CompactStatelessWidget { ), title: Text( subject?.parsedName(context) ?? "Subject deleted", - textScaleFactor: 1.2, + textScaler: const TextScaler.linear(1.2), ), onTap: () => context.pop(result: subjects[index]), ); diff --git a/lib/src/view/pages/substitute/substitute_card.dart b/lib/src/view/pages/substitute/substitute_card.dart index 67e07c5..0a59e34 100644 --- a/lib/src/view/pages/substitute/substitute_card.dart +++ b/lib/src/view/pages/substitute/substitute_card.dart @@ -52,14 +52,14 @@ class SubstituteCard extends StatelessWidget { children: [ Text( lesson, - textScaleFactor: 1.8, + textScaler: const TextScaler.linear(1.8), ), ], ), ), title: Text( substitute.type.name(context), - textScaleFactor: 1.25, + textScaler: const TextScaler.linear(1.2), ), subtitle: SummarizedSubstituteText(substitute: substitute), ), diff --git a/lib/src/view/pages/substitute/substitute_message_card.dart b/lib/src/view/pages/substitute/substitute_message_card.dart index 7fb5b42..8c38a97 100644 --- a/lib/src/view/pages/substitute/substitute_message_card.dart +++ b/lib/src/view/pages/substitute/substitute_message_card.dart @@ -36,7 +36,7 @@ class SubstituteMessageCardState extends State<SubstituteMessageCard> { padding: const EdgeInsets.all(10), child: Text( widget.substituteMessage.date!.formatEEEEddMM(context), - textScaleFactor: 2, + textScaler: const TextScaler.linear(2), ), ), const Divider(height: 10, thickness: 5), diff --git a/lib/src/view/pages/substitute/substitute_page.dart b/lib/src/view/pages/substitute/substitute_page.dart index 4eec8d0..71dbe8f 100644 --- a/lib/src/view/pages/substitute/substitute_page.dart +++ b/lib/src/view/pages/substitute/substitute_page.dart @@ -84,7 +84,7 @@ class _SubstitutePageContentState extends State<SubstitutePageContent> Text( context.l10n.substitutes, textAlign: TextAlign.center, - textScaleFactor: 2, + textScaler: const TextScaler.linear(2), ), const Expanded(child: SubstituteTab()), ], @@ -96,7 +96,7 @@ class _SubstitutePageContentState extends State<SubstitutePageContent> Text( context.l10n.substituteMessages, textAlign: TextAlign.center, - textScaleFactor: 2, + textScaler: const TextScaler.linear(2), ), const Expanded(child: SubstituteMessageTab()), ], diff --git a/lib/src/view/pages/substitute/substitute_tab.dart b/lib/src/view/pages/substitute/substitute_tab.dart index 9cf36b2..3de5b15 100644 --- a/lib/src/view/pages/substitute/substitute_tab.dart +++ b/lib/src/view/pages/substitute/substitute_tab.dart @@ -103,7 +103,7 @@ class _SubstituteTabState extends State<SubstituteTab> { substitutes[index] .date! .formatEEEEddMM(context), - textScaleFactor: 2, + textScaler: const TextScaler.linear(2), textAlign: TextAlign.start, style: const TextStyle( fontWeight: FontWeight.w500), @@ -165,7 +165,7 @@ class SubstituteState extends StatelessWidget { return Center( child: Text( "${context.l10n.stateOf} ${date.format(context, "dd.MM., HH:mm")}", - textScaleFactor: 1.2, + textScaler: const TextScaler.linear(1.2), )); } } diff --git a/lib/src/view/pages/task/task_card.dart b/lib/src/view/pages/task/task_card.dart index f0e1f47..92c0732 100644 --- a/lib/src/view/pages/task/task_card.dart +++ b/lib/src/view/pages/task/task_card.dart @@ -90,7 +90,7 @@ class TaskCard extends StatelessWidget { child: Text( task.title, maxLines: 3, - textScaleFactor: 1.2, + textScaler: const TextScaler.linear(1.2), overflow: TextOverflow.fade, ), ), diff --git a/lib/src/view/pages/task/task_card_landscape.dart b/lib/src/view/pages/task/task_card_landscape.dart index 7211aff..ae2e03b 100644 --- a/lib/src/view/pages/task/task_card_landscape.dart +++ b/lib/src/view/pages/task/task_card_landscape.dart @@ -36,7 +36,7 @@ class TaskCardLandscape extends StatelessWidget { children: [ Text( task.title, - textScaleFactor: 1.6, + textScaler: const TextScaler.linear(1.6), overflow: TextOverflow.ellipsis, maxLines: 1, ), @@ -69,7 +69,7 @@ class TaskCardLandscape extends StatelessWidget { const SizedBox(width: 6), Text( subject.parsedName(context), - textScaleFactor: 1.6, + textScaler: const TextScaler.linear(1.6), overflow: TextOverflow.ellipsis, maxLines: 1, ), @@ -83,7 +83,7 @@ class TaskCardLandscape extends StatelessWidget { fit: FlexFit.tight, child: Text( context.l10n.fromDate(task.created.formatEEEEddMM(context)), - textScaleFactor: 1.6, + textScaler: const TextScaler.linear(1.6), textAlign: TextAlign.center, overflow: TextOverflow.ellipsis, maxLines: 1, @@ -95,7 +95,7 @@ class TaskCardLandscape extends StatelessWidget { child: task.due != null ? Text( context.l10n.toDate(task.due!.formatEEEEddMM(context)), - textScaleFactor: 1.6, + textScaler: const TextScaler.linear(1.6), textAlign: TextAlign.center, overflow: TextOverflow.ellipsis, maxLines: 1, diff --git a/lib/src/view/pages/task/task_page.dart b/lib/src/view/pages/task/task_page.dart index 4ede76b..45e85d4 100644 --- a/lib/src/view/pages/task/task_page.dart +++ b/lib/src/view/pages/task/task_page.dart @@ -40,7 +40,7 @@ class _TaskPageState extends State<TaskPage> { onChanged: (value) => setState(() => showAll = value), title: Text( context.l10n.showDoneTasks, - textScaleFactor: 1.2, + textScaler: const TextScaler.linear(1.2), overflow: TextOverflow.ellipsis, maxLines: 1, softWrap: false, @@ -61,7 +61,7 @@ class _TaskPageState extends State<TaskPage> { children: [ Text( context.l10n.noTasksFound, - textScaleFactor: 1.2, + textScaler: const TextScaler.linear(1.2), ), Padding( padding: const EdgeInsets.all(12), diff --git a/lib/src/view/pages/timetable/timetable_card.dart b/lib/src/view/pages/timetable/timetable_card.dart index 1320895..9c9d777 100644 --- a/lib/src/view/pages/timetable/timetable_card.dart +++ b/lib/src/view/pages/timetable/timetable_card.dart @@ -27,7 +27,7 @@ class TimetableDate extends StatelessWidget { child: Center( child: Text( editing ? date.formatEEEE(context) : date.formatEEEEddMMToNow(context), - textScaleFactor: 2, + textScaler: const TextScaler.linear(2), textAlign: TextAlign.center, ), ), @@ -50,7 +50,7 @@ class TimetableBreak extends StatelessWidget { color: Theme.of(context).colorScheme.background, child: Text( context.l10n.break_, - textScaleFactor: 1.2, + textScaler: const TextScaler.linear(1.2), style: Theme.of(context).textTheme.bodySmall, ), ), @@ -83,7 +83,7 @@ class TimetableFreeHour extends StatelessWidget { child: Center( child: Text( "$count $name", - textScaleFactor: 1.8, + textScaler: const TextScaler.linear(1.8), style: Theme.of(context).textTheme.bodySmall, ), ), @@ -110,7 +110,7 @@ class TimetableNoEntries extends StatelessWidget { Text( context.l10n.noTimetable, style: Theme.of(context).textTheme.bodySmall, - textScaleFactor: 1.2, + textScaler: const TextScaler.linear(1.2), ), Padding( padding: const EdgeInsets.all(12), @@ -167,12 +167,12 @@ class TimetableCard extends StatelessWidget { minVerticalPadding: 8, leading: Center( widthFactor: 1, - child: Text(entry.lesson.toString(), textScaleFactor: 1.8), + child: Text(entry.lesson.toString(), textScaler: const TextScaler.linear(1.8)), ), title: subject != null ? Text( subject.parsedName(context), - textScaleFactor: 1.25 + textScaler: const TextScaler.linear(1.2) ) : null, subtitle: TimetableSubtitle( entry: entry, diff --git a/lib/src/view/pages/timetable/timetable_page.dart b/lib/src/view/pages/timetable/timetable_page.dart index 164c061..ce6b993 100644 --- a/lib/src/view/pages/timetable/timetable_page.dart +++ b/lib/src/view/pages/timetable/timetable_page.dart @@ -335,13 +335,13 @@ class TimetablePageState extends State<TimetablePage> { children: [ Text( context.l10n.timetable, - textScaleFactor: 2, + textScaler: const TextScaler.linear(2), ), Padding( padding: const EdgeInsets.only(left: 4.0), child: Text( _getSubtitle(), - textScaleFactor: 1.2, + textScaler: const TextScaler.linear(1.2), style: Theme.of(context).textTheme.bodySmall, ), ), @@ -430,13 +430,13 @@ class TimetablePageState extends State<TimetablePage> { children: [ Text( context.l10n.timetable, - textScaleFactor: 2, + textScaler: const TextScaler.linear(2), ), Padding( padding: const EdgeInsets.only(left: 4.0), child: Text( _getSubtitle(), - textScaleFactor: 1.2, + textScaler: const TextScaler.linear(1.2), style: Theme.of(context).textTheme.bodySmall, ), ), From a2eb1bb9bf97fc2bb80aa2f4f05e4604d4b58623 Mon Sep 17 00:00:00 2001 From: Paul Huerkamp <35733278+PAException@users.noreply.github.com> Date: Fri, 1 Dec 2023 12:41:44 +0100 Subject: [PATCH 5/9] Fixed dart analyzer lints --- lib/main.dart | 1 - lib/src/services/oauth.dart | 1 - lib/src/view/pages/article/article_extended.dart | 1 - lib/src/view/pages/introduction.dart | 6 ++++-- .../view/pages/settings/settings_notifications_page.dart | 2 -- lib/src/view/pages/substitute/substitute_card.dart | 1 - lib/src/view/pages/timetable/timetable_extended.dart | 8 +++----- lib/src/view/widgets/app_icon.dart | 1 - 8 files changed, 7 insertions(+), 14 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 2274972..7791f27 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,6 @@ import 'package:engelsburg_planer/src/services/data_service.dart'; import 'package:engelsburg_planer/src/services/isolated_worker.dart'; import 'package:flutter/material.dart'; import 'package:hive_flutter/hive_flutter.dart'; -import 'package:logging/logging.dart'; import 'package:provider/provider.dart'; /// Initialize and run app diff --git a/lib/src/services/oauth.dart b/lib/src/services/oauth.dart index 538ea98..44d3ee8 100644 --- a/lib/src/services/oauth.dart +++ b/lib/src/services/oauth.dart @@ -8,7 +8,6 @@ import 'package:engelsburg_planer/src/utils/extensions.dart'; import 'package:engelsburg_planer/src/utils/global_context.dart'; import 'package:engelsburg_planer/src/view/pages/auth/auth_page.dart'; import 'package:firebase_auth/firebase_auth.dart'; -import 'package:firebase_auth_platform_interface/src/auth_provider.dart'; import 'package:flutter/foundation.dart'; import 'package:google_sign_in/google_sign_in.dart'; diff --git a/lib/src/view/pages/article/article_extended.dart b/lib/src/view/pages/article/article_extended.dart index 756ae68..2634882 100644 --- a/lib/src/view/pages/article/article_extended.dart +++ b/lib/src/view/pages/article/article_extended.dart @@ -11,7 +11,6 @@ import 'package:engelsburg_planer/src/services/firebase/analytics.dart'; import 'package:engelsburg_planer/src/utils/extensions.dart'; import 'package:engelsburg_planer/src/view/pages/article/article_card.dart'; import 'package:engelsburg_planer/src/view/widgets/special/network_status.dart'; -import 'package:engelsburg_planer/src/view/widgets/util/util_widgets.dart'; import 'package:engelsburg_planer/src/view/widgets/util/wrap_if.dart'; import 'package:flutter/material.dart'; import 'package:flutter_spinkit/flutter_spinkit.dart'; diff --git a/lib/src/view/pages/introduction.dart b/lib/src/view/pages/introduction.dart index 9f64b50..dc52730 100644 --- a/lib/src/view/pages/introduction.dart +++ b/lib/src/view/pages/introduction.dart @@ -147,6 +147,8 @@ class _IntroductionPageState extends State<IntroductionPage> { userType: selectedUserType!, extra: extra, ); + + GoRouter router = GoRouter.of(context); await config.configure(appConfiguration); NotificationSettings.ref() .defaultStorage(globalContext()) @@ -155,9 +157,9 @@ class _IntroductionPageState extends State<IntroductionPage> { Analytics.introduction.complete(); if (appConfiguration.userType == UserType.student) { - globalContext().go("/settings/subject?callbackUrl=/article"); + router.go("/settings/subject?callbackUrl=/article"); } else { - globalContext().go("/article"); + router.go("/article"); } } } diff --git a/lib/src/view/pages/settings/settings_notifications_page.dart b/lib/src/view/pages/settings/settings_notifications_page.dart index 1c85b60..5d2bdfe 100644 --- a/lib/src/view/pages/settings/settings_notifications_page.dart +++ b/lib/src/view/pages/settings/settings_notifications_page.dart @@ -20,8 +20,6 @@ class NotificationSettingsPage extends StatelessWidget { doc: NotificationSettings.ref().defaultStorage(context), errorBuilder: (context, doc, error) => Text(error.toString()), itemBuilder: (context, doc, settings) { - print(settings); - return ListView( padding: const EdgeInsets.all(8.0), children: [ diff --git a/lib/src/view/pages/substitute/substitute_card.dart b/lib/src/view/pages/substitute/substitute_card.dart index 0a59e34..03cc45b 100644 --- a/lib/src/view/pages/substitute/substitute_card.dart +++ b/lib/src/view/pages/substitute/substitute_card.dart @@ -6,7 +6,6 @@ import 'package:engelsburg_planer/src/backend/api/model/substitutes.dart'; import 'package:engelsburg_planer/src/utils/extensions.dart'; import 'package:engelsburg_planer/src/view/pages/substitute/substitute_extended.dart'; import 'package:flutter/material.dart'; -import 'package:hive/hive.dart'; class SubstituteCard extends StatelessWidget { const SubstituteCard({super.key, required this.substitute, this.endLesson}); diff --git a/lib/src/view/pages/timetable/timetable_extended.dart b/lib/src/view/pages/timetable/timetable_extended.dart index 9a3198f..e7da3d2 100644 --- a/lib/src/view/pages/timetable/timetable_extended.dart +++ b/lib/src/view/pages/timetable/timetable_extended.dart @@ -109,11 +109,9 @@ class _ExtendedTimetableCardState extends State<ExtendedTimetableCard> { _teacherController.text = entry.teacher ?? ""; _roomController.text = entry.room ?? ""; - return WillPopScope( - onWillPop: () async { - savePossibleChanges(); - return true; - }, + return PopScope( + canPop: true, + onPopInvoked: (_) => savePossibleChanges(), child: Scaffold( extendBodyBehindAppBar: true, appBar: AppBar( diff --git a/lib/src/view/widgets/app_icon.dart b/lib/src/view/widgets/app_icon.dart index f094fbb..4bcb085 100644 --- a/lib/src/view/widgets/app_icon.dart +++ b/lib/src/view/widgets/app_icon.dart @@ -3,7 +3,6 @@ */ import 'package:engelsburg_planer/src/utils/constants.dart'; -import 'package:engelsburg_planer/src/view/widgets/util/wrap_if.dart'; import 'package:flutter/material.dart'; class AppIcon extends StatelessWidget { From d00dccd2b55e89f5c7d9beb8fff348a66c69dd72 Mon Sep 17 00:00:00 2001 From: Paul Huerkamp <35733278+PAException@users.noreply.github.com> Date: Fri, 1 Dec 2023 14:07:32 +0100 Subject: [PATCH 6/9] Modified build script --- build.sh | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/build.sh b/build.sh index 4edac87..35b70e9 100755 --- a/build.sh +++ b/build.sh @@ -48,9 +48,18 @@ increment_flutter_version() { execute_flutter_release_builds() { flutter build ipa --release flutter build appbundle --release + + # Ensure release directory exists; create if not present + mkdir -p ./release + + # Copy IPA file to release directory + cp build/ios/ipa/*.ipa ./release + + # Copy App Bundle file to release directory + cp build/app/outputs/bundle/release/*.aab ./release } -# Increment version regardless of --no-build presence +# Increment version based on provided options if [ "$1" == "--major" ] || [ "$1" == "--minor" ] || [ "$1" == "--patch" ]; then increment_flutter_version "$1" elif [ "$2" == "--major" ] || [ "$2" == "--minor" ] || [ "$2" == "--patch" ]; then From 9d3c6c3a3e7f1821c754066b814fc4109b44b39f Mon Sep 17 00:00:00 2001 From: Paul Huerkamp <35733278+PAException@users.noreply.github.com> Date: Thu, 30 Nov 2023 23:48:55 +0100 Subject: [PATCH 7/9] Added logger implementation --- lib/main.dart | 8 ++- .../backend/database/nosql/base/document.dart | 3 - .../database/nosql/base/references.dart | 5 +- .../database/nosql/storage/storage_cache.dart | 14 ++-- .../nosql/storage/storage_delayed_writer.dart | 11 ++-- .../database/nosql/storage/storage_state.dart | 12 ++-- .../nosql/storage/storage_streams.dart | 23 +++---- lib/src/backend/database/state/app_state.dart | 1 + .../backend/database/state/network_state.dart | 5 +- .../services/firebase/firebase_config.dart | 22 +++++-- lib/src/utils/logger.dart | 65 +++++++++++++++++++ 11 files changed, 127 insertions(+), 42 deletions(-) create mode 100644 lib/src/utils/logger.dart diff --git a/lib/main.dart b/lib/main.dart index 7791f27..3e41285 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -17,12 +17,16 @@ import 'package:engelsburg_planer/src/services/firebase/firebase_config.dart'; import 'package:engelsburg_planer/src/utils/extensions.dart'; import 'package:engelsburg_planer/src/services/data_service.dart'; import 'package:engelsburg_planer/src/services/isolated_worker.dart'; +import 'package:engelsburg_planer/src/utils/logger.dart'; import 'package:flutter/material.dart'; import 'package:hive_flutter/hive_flutter.dart'; import 'package:provider/provider.dart'; /// Initialize and run app void main() async { + Logger.rootLevel = Level.fine; + + Logger.forType<EngelsburgPlaner>().info("Starting app..."); WidgetsFlutterBinding.ensureInitialized(); await InitializingPriority.instant.initialize(); @@ -68,6 +72,8 @@ extension InitializingPriorityUtils on InitializingPriority{ Future initialize() { return toInitialize.entries.where((entry) => entry.value == this).asyncMap( (entry) async => await Future.value(entry.key.call()), - ); + ).then((value) { + Logger.forType<EngelsburgPlaner>().info("Initialized '$name' priority"); + }); } } diff --git a/lib/src/backend/database/nosql/base/document.dart b/lib/src/backend/database/nosql/base/document.dart index 77ea919..149960d 100644 --- a/lib/src/backend/database/nosql/base/document.dart +++ b/lib/src/backend/database/nosql/base/document.dart @@ -127,7 +127,4 @@ class Document<T> extends DocumentReference<T> { /// the operation was successful. Future<bool> copyTo(Storage target) async => target.setDocument(path, tryParseTypedData(await load())); - - @override - String toString() => 'Document{path: ${super.path}, data: $data}'; } diff --git a/lib/src/backend/database/nosql/base/references.dart b/lib/src/backend/database/nosql/base/references.dart index 9e17fa8..4dfdc2b 100644 --- a/lib/src/backend/database/nosql/base/references.dart +++ b/lib/src/backend/database/nosql/base/references.dart @@ -2,6 +2,8 @@ * Copyright (c) Paul Huerkamp 2023. All rights reserved. */ +import 'dart:ui'; + import 'package:engelsburg_planer/src/backend/database/nosql/base/collection.dart'; import 'package:engelsburg_planer/src/backend/database/nosql/base/document.dart'; import 'package:engelsburg_planer/src/backend/database/nosql/storage/storage.dart'; @@ -26,7 +28,8 @@ abstract class Reference<T> { String get id => path.split("/").last; @override - String toString() => 'Reference{path: $path}'; + @keepToString + String toString() => path; @override bool operator ==(Object other) => other is Reference && path == other.path; diff --git a/lib/src/backend/database/nosql/storage/storage_cache.dart b/lib/src/backend/database/nosql/storage/storage_cache.dart index d507d9f..9de8a89 100644 --- a/lib/src/backend/database/nosql/storage/storage_cache.dart +++ b/lib/src/backend/database/nosql/storage/storage_cache.dart @@ -5,17 +5,17 @@ import 'package:engelsburg_planer/src/backend/database/nosql/base/references.dart'; import 'package:engelsburg_planer/src/backend/database/nosql/storage/storage.dart'; import 'package:engelsburg_planer/src/utils/extensions.dart'; -import 'package:flutter/foundation.dart'; +import 'package:engelsburg_planer/src/utils/logger.dart'; //TODO docs -class StorageCache { +class StorageCache with Logs<Storage> { final Map<DocumentReference, Map<String, dynamic>> _documentCache = {}; final Map<CollectionReference, Set<DocumentReference>> _collectionCache = {}; /// Writes the data of the document to the cache and also references the /// document in the collection cache if possible. void setDocument<T>(DocumentReference<T> document, Map<String, dynamic> data) { - debugPrint("[${document.id}] updating cached document: $data"); + logger.trace("Updating cached document: $document"); //Update document cache _documentCache[document] = data; @@ -33,14 +33,14 @@ class StorageCache { //TODO docs Map<String, dynamic>? getDocument(DocumentReference document) { var data = _documentCache[document]; - if (data != null) debugPrint("[${document.id}] getting cached document: $data"); + if (data != null) logger.trace("getting cached document: $document"); return data; } //TODO docs void removeDocument(DocumentReference document) { - debugPrint("[${document.id}] removing cached document"); + logger.trace("removing cached document: $document"); _documentCache.remove(document); //Update parent collection @@ -61,7 +61,7 @@ class StorageCache { //TODO docs void setCollection<T>(CollectionReference<T> collection, CollectionData collectionData) { - debugPrint("[${collection.id}] setting cached collection: $collectionData"); + logger.trace("setting cached collection: $collection"); //Map collection data to document references var documents = collectionData.mapToList((key, value) { @@ -78,7 +78,7 @@ class StorageCache { //TODO docs List<DocumentReference<T>>? getCollection<T>(CollectionReference<T> collection) { - debugPrint("[${collection.id}] getting cached collection"); + logger.trace("getting cached collection: $collection"); var refs = _collectionCache[collection]; diff --git a/lib/src/backend/database/nosql/storage/storage_delayed_writer.dart b/lib/src/backend/database/nosql/storage/storage_delayed_writer.dart index 5b543a9..925d898 100644 --- a/lib/src/backend/database/nosql/storage/storage_delayed_writer.dart +++ b/lib/src/backend/database/nosql/storage/storage_delayed_writer.dart @@ -6,10 +6,11 @@ import 'dart:async'; import 'package:engelsburg_planer/src/backend/database/nosql/base/document.dart'; import 'package:engelsburg_planer/src/backend/database/nosql/base/references.dart'; -import 'package:flutter/foundation.dart'; +import 'package:engelsburg_planer/src/backend/database/nosql/storage/storage.dart'; +import 'package:engelsburg_planer/src/utils/logger.dart'; /// Handles any delayed writes of documents for a specific storage. -class StorageDelayedWriter { +class StorageDelayedWriter with Logs<Storage> { /// Caches timers for delayed document updates (reference, timer) final Map<DocumentReference, Timer> _submitted = {}; @@ -18,7 +19,7 @@ class StorageDelayedWriter { void dispose(DocumentReference document) { var write = _submitted[document]; if (write != null) { - debugPrint("[${document.id}] disposing delayed write"); + logger.trace("Disposing delayed write for document: $document"); write.cancel(); _submitted.remove(document); @@ -38,9 +39,9 @@ class StorageDelayedWriter { T Function(T data)? preWrite, void Function(bool result)? postWrite, }) { - debugPrint("[${document.id}] submitted delayed write: $data"); + logger.trace("Submitted delayed write for document: $document"); delayedWrite() async { - debugPrint("[${document.id}] executing delayed write: $data"); + logger.trace("Executing delayed write for document: $document"); //Remove this timer from the submitted document writes _submitted.remove(document); diff --git a/lib/src/backend/database/nosql/storage/storage_state.dart b/lib/src/backend/database/nosql/storage/storage_state.dart index bb5664a..a8763ba 100644 --- a/lib/src/backend/database/nosql/storage/storage_state.dart +++ b/lib/src/backend/database/nosql/storage/storage_state.dart @@ -8,10 +8,10 @@ import 'package:engelsburg_planer/src/backend/database/nosql/storage/storage.dar import 'package:engelsburg_planer/src/backend/database/nosql/storage/storage_cache.dart'; import 'package:engelsburg_planer/src/backend/database/nosql/storage/storage_delayed_writer.dart'; import 'package:engelsburg_planer/src/backend/database/nosql/storage/storage_streams.dart'; -import 'package:flutter/cupertino.dart'; +import 'package:engelsburg_planer/src/utils/logger.dart'; //TODO docs -class StorageState { +class StorageState with Logs<Storage> { late final StorageCache _cache; late final StorageStreams _streams; late final StorageDelayedWriter _delayedWriter; @@ -66,7 +66,7 @@ class StorageState { _delayedWriteData.remove(document); if (result) return; - debugPrint("[${document.id}] delayed write failed"); + logger.trace("Delayed write failed for document: $document"); //Revert cache _cache.removeDocument(document); @@ -117,7 +117,7 @@ class StorageState { required DocumentReference<T> document, required Stream<DocumentData?> Function(String path) createNativeStream, }) { - debugPrint("[${document.id}] issued new document stream"); + logger.trace("Issued new stream for document: $document"); return _streams.getDocumentStream( document: document, @@ -134,6 +134,8 @@ class StorageState { required CollectionReference collection, required Stream<CollectionData> Function(String path) createNativeStream, }) { + logger.trace("Issued new stream for collection: $collection"); + return _streams.getCollectionStream( collection: collection, createNativeStream: createNativeStream, @@ -180,13 +182,11 @@ class StorageState { _cache.setCollection(collection, collectionData); //TODO updates documents twice to cache return collectionData.map((key, value) { - debugPrint("$key, $value"); value = _interceptDocumentStream( document: DocumentReference(key, collection.parser), data: value, updateIsLocal: updateIsLocal, )!; - debugPrint("AFTER: $key, $value"); return MapEntry(key, value); }); diff --git a/lib/src/backend/database/nosql/storage/storage_streams.dart b/lib/src/backend/database/nosql/storage/storage_streams.dart index c03966f..faf911c 100644 --- a/lib/src/backend/database/nosql/storage/storage_streams.dart +++ b/lib/src/backend/database/nosql/storage/storage_streams.dart @@ -6,13 +6,13 @@ import 'dart:async'; import 'package:engelsburg_planer/src/backend/database/nosql/base/references.dart'; import 'package:engelsburg_planer/src/backend/database/nosql/storage/storage.dart'; -import 'package:flutter/cupertino.dart'; +import 'package:engelsburg_planer/src/utils/logger.dart'; typedef DocumentStreamSub = StreamSubscription<DocumentData?>; typedef CollectionStreamSub = StreamSubscription<CollectionData>; //TODO docs -class StorageStreams { +class StorageStreams with Logs<Storage> { /// Caches snapshot streams of documents (reference, streams) final Map<DocumentReference, List<StreamController>> _documentStreams = {}; final Map<DocumentReference, DocumentStreamSub> _documentSubscriptions = {}; @@ -59,6 +59,8 @@ class StorageStreams { controllers.add(newController); streams[reference] = controllers; + logger.fine("Created stream controller for $reference"); + return newController; } @@ -74,7 +76,7 @@ class StorageStreams { required Stream<DocumentData?> Function(String) createNativeStream, DocumentData? Function(DocumentData? data)? intercept, }) { - debugPrint("[${document.id}] creating new document stream"); + logger.trace("Creating new document stream: $document"); //Create new stream controller and add to list var newController = _createStreamController<DocumentData?>( @@ -85,7 +87,7 @@ class StorageStreams { //Handles the data event that will be dispatched from the subscription void handleData(DocumentData? data) { - debugPrint("[${document.id}] handling new data of streamed document"); + logger.trace("Handling new data of streamed document: $document"); _latestDocumentData[document] = data; @@ -125,7 +127,7 @@ class StorageStreams { required Stream<CollectionData> Function(String) createNativeStream, CollectionData Function(CollectionData collectionData)? intercept, }) { - debugPrint("[${collection.id}] creating new collection stream"); + logger.trace("Creating new collection stream: $collection"); //Create new stream controller and add to list var newController = _createStreamController<CollectionData>( @@ -136,7 +138,7 @@ class StorageStreams { //Handles the data event that will be dispatched from the subscription void handleData(CollectionData collectionData) { - debugPrint("[${collection.id}] handling new data of streamed collection"); + logger.trace("Handling new data of streamed collection: $collection"); _latestCollectionData[collection] = collectionData; @@ -173,8 +175,7 @@ class StorageStreams { DocumentData? Function(DocumentData? data)? interceptDocument, CollectionData Function(CollectionData collectionData)? interceptCollection, }) { - debugPrint( - "[${document.id}] dispatching latest document and collections for document"); + logger.trace("Dispatching latest for document to streams: $document"); _dispatchDocument( document: document, @@ -200,7 +201,7 @@ class StorageStreams { required DocumentData? data, DocumentData? Function(DocumentData? data)? intercept, }) { - debugPrint("[${document.id}] dispatching document: $data"); + logger.trace("Dispatching document to streams: $document"); if (intercept != null) data = intercept.call(data); @@ -227,7 +228,7 @@ class StorageStreams { required CollectionData collectionData, CollectionData Function(CollectionData collectionData)? intercept, }) { - debugPrint("[${collection.id}] dispatching collection: $collectionData"); + logger.trace("Dispatching collection to streams: $collection"); if (intercept != null) collectionData = intercept.call(collectionData); @@ -240,7 +241,7 @@ class StorageStreams { /// Force disposes all streams of a document. void dispose(DocumentReference document) { - debugPrint("[${document.id}] disposing streams for document"); + logger.trace("Disposing streams for document: $document"); _documentSubscriptions[document]?.cancel(); _documentStreams[document]?.forEach((element) => element.close()); diff --git a/lib/src/backend/database/state/app_state.dart b/lib/src/backend/database/state/app_state.dart index 83621bf..c1541c1 100644 --- a/lib/src/backend/database/state/app_state.dart +++ b/lib/src/backend/database/state/app_state.dart @@ -36,6 +36,7 @@ class AppConfigState extends NullableStorableChangeNotifier<AppConfiguration> { Analytics.user.setAppConfig(config); + current = config; save(() => Pages.userType = userType!); return initialize ??= InitializingPriority.afterAppConfig.initialize(); diff --git a/lib/src/backend/database/state/network_state.dart b/lib/src/backend/database/state/network_state.dart index 09d1452..d6dddd6 100644 --- a/lib/src/backend/database/state/network_state.dart +++ b/lib/src/backend/database/state/network_state.dart @@ -2,13 +2,14 @@ * Copyright (c) Paul Huerkamp 2023. All rights reserved. */ +import 'package:engelsburg_planer/src/utils/logger.dart'; import 'package:engelsburg_planer/src/view/widgets/special/network_status.dart'; import 'package:flutter/material.dart'; enum NetworkStatus { online, loading, offline } /// Provided state to keep track of the current network status. See [NetworkStatusBar] -class NetworkState extends ChangeNotifier { +class NetworkState extends ChangeNotifier with Logs<NetworkState> { NetworkStatus _current = NetworkStatus.online; /// Get the current network status @@ -19,6 +20,8 @@ class NetworkState extends ChangeNotifier { //Don't set status to loading just while retrying timed out requests if (status == NetworkStatus.loading && _current == NetworkStatus.offline) return; + logger.info("Status of network changed to ${_current.name}"); + //Set current status and notify listeners _current = status; WidgetsBinding.instance.addPostFrameCallback((_) => notifyListeners()); diff --git a/lib/src/services/firebase/firebase_config.dart b/lib/src/services/firebase/firebase_config.dart index 5531ba1..61b0142 100644 --- a/lib/src/services/firebase/firebase_config.dart +++ b/lib/src/services/firebase/firebase_config.dart @@ -13,6 +13,7 @@ import 'package:engelsburg_planer/src/services/firebase/firebase_options.dart'; import 'package:engelsburg_planer/src/backend/api/request.dart'; import 'package:engelsburg_planer/src/backend/api/requests.dart'; import 'package:engelsburg_planer/src/utils/global_context.dart'; +import 'package:engelsburg_planer/src/utils/logger.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:firebase_remote_config/firebase_remote_config.dart'; @@ -22,6 +23,8 @@ import 'package:go_router/go_router.dart'; /// Util class for all firebase initializations and configurations. class FirebaseConfig { + static Logger<FirebaseConfig> get logger => Logger.forType<FirebaseConfig>(); + /// Initializes every used firebase service static Future<void> initialize() async { //Init the core firebaseApp @@ -29,7 +32,7 @@ class FirebaseConfig { options: DefaultFirebaseOptions.currentPlatform, ); - Crashlytics.log("Initializing firebase services"); + logger.info("Initializing firebase services"); //Init sub services Analytics.initialize(); @@ -39,6 +42,7 @@ class FirebaseConfig { /// Initialize FCM - initialNotification, tokenRefresh action static void initializeFCM() async { + logger.debug("Initializing FCM"); //Check if app was opened via a notification FirebaseMessaging.instance .getInitialMessage() @@ -75,7 +79,7 @@ class FirebaseConfig { ?.createNotificationChannel(channel); FirebaseMessaging.onMessage.listen((RemoteMessage message) { - Crashlytics.log("Received notification while the app was opened"); + logger.debug("FCM notification while opened"); //On IOS the notification is also displayed when the app is opened if (Platform.isIOS) return; @@ -102,6 +106,7 @@ class FirebaseConfig { //Push changes to server if token changes FirebaseMessaging.instance.onTokenRefresh.listen((token) async { + logger.debug("FCM token got updated"); var substituteSettings = await SubstituteSettings.ref().offline.load(); updateNotificationSettings( @@ -116,7 +121,7 @@ class FirebaseConfig { static void handleOpenedRemoteMessage(RemoteMessage? message) { if (message == null) return; - Crashlytics.log("Handling user click on notification"); + logger.debug("FCM user opened notification"); Crashlytics.set("notification_data", message.data); if (message.data.isNotEmpty) { String? link = message.data["link"]; @@ -128,6 +133,7 @@ class FirebaseConfig { /// Initialize the remote config service of firebase to use remote based configuration of the app. static Future<void> initializeRemoteConfig() async { + logger.debug("Initializing remote config"); //First activate, then fetch the remote configuration to avoid loading times for users final remoteConfig = FirebaseRemoteConfig.instance; @@ -135,8 +141,8 @@ class FirebaseConfig { //Set defaults that aren't fetched yet remoteConfig.setDefaults(const { "enable_firebase": false, - "app_store_url": "", - "play_store_url": "", + "app_store_url": "https://apps.apple.com/app/engelsburg-planer/id6469040581", + "play_store_url": "https://play.google.com/store/apps/details?id=de.paulhuerkamp.engelsburg_planer", "support_email": "engelsburg.planer@gmail.com", }); } @@ -154,12 +160,14 @@ class FirebaseConfig { Future.doWhile(() async { try { await remoteConfig.fetchAndActivate(); + logger.debug("Fetched and activated remote config"); - return true; + return false; } catch (_) { + logger.error("Couldn't fetch remote config"); await Future.delayed(Duration(seconds: pow(2, backOff++).toInt())); - return false; + return true; } }); } diff --git a/lib/src/utils/logger.dart b/lib/src/utils/logger.dart new file mode 100644 index 0000000..2cc23b7 --- /dev/null +++ b/lib/src/utils/logger.dart @@ -0,0 +1,65 @@ +// ignore_for_file: avoid_print + +/* + * Copyright (c) Paul Huerkamp 2023. All rights reserved. + */ + +import 'package:engelsburg_planer/src/services/firebase/crashlytics.dart'; +import 'package:flutter/foundation.dart'; + +@immutable +class Level { + final int value; + final String name; + + const Level(this.value, this.name); + + static const Level fine = Level(100, "fine"); + static const Level trace = Level(200, "trace"); + static const Level debug = Level(300, "debug"); + static const Level info = Level(400, "info"); + static const Level warning = Level(500, "warning"); + static const Level error = Level(600, "error"); + static const Level fatal = Level(700, "fatal"); +} + +class Logger<T> { + static final Map<Type, Logger<dynamic>> _loggers = {}; + static Level rootLevel = debugMode ? Level.debug : Level.info; + static bool debugMode = kDebugMode; + static bool analytics = !kDebugMode; + + static Logger<T> forType<T>([Level? level]) { + if (!_loggers.containsKey(T)) { + _loggers[T] = Logger<T>(level ?? rootLevel); + } else if (level != null) { + _loggers[T]!.level = level; + } + + return _loggers[T] as Logger<T>; + } + + void log(String msg, Level level) { + if (level.value < this.level.value) return; + + String composed = "[$T] ${level.name.toUpperCase()}: $msg"; + if (debugMode) print(composed); + if (analytics) Crashlytics.log(composed); + } + + void fine(String msg) => log(msg, Level.fine); + void trace(String msg) => log(msg, Level.trace); + void debug(String msg) => log(msg, Level.debug); + void info(String msg) => log(msg, Level.info); + void warning(String msg) => log(msg, Level.warning); + void error(String msg) => log(msg, Level.error); + void fatal(String msg) => log(msg, Level.fatal); + + Logger(this.level); + + Level level; +} + +mixin Logs<T> { + Logger<T> get logger => Logger.forType<T>(); +} From 0744420aed7371eb90addf8acae43d3771cc6e34 Mon Sep 17 00:00:00 2001 From: Paul Huerkamp <35733278+PAException@users.noreply.github.com> Date: Fri, 1 Dec 2023 15:18:54 +0100 Subject: [PATCH 8/9] Added more logs --- lib/main.dart | 4 ++-- lib/src/app.dart | 4 ++-- lib/src/view/pages/article/article_page.dart | 6 +++++- lib/src/view/pages/grade/grade_page.dart | 7 +++++-- lib/src/view/pages/home_page.dart | 4 +++- lib/src/view/pages/substitute/substitute_page.dart | 7 ++++++- lib/src/view/pages/task/task_page.dart | 5 ++++- lib/src/view/pages/timetable/timetable_page.dart | 5 ++++- lib/src/view/routing/page.dart | 2 +- 9 files changed, 32 insertions(+), 12 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 3e41285..3566472 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -24,9 +24,9 @@ import 'package:provider/provider.dart'; /// Initialize and run app void main() async { - Logger.rootLevel = Level.fine; - + Logger.rootLevel = Level.debug; Logger.forType<EngelsburgPlaner>().info("Starting app..."); + WidgetsFlutterBinding.ensureInitialized(); await InitializingPriority.instant.initialize(); diff --git a/lib/src/app.dart b/lib/src/app.dart index 820d7e8..dcada76 100644 --- a/lib/src/app.dart +++ b/lib/src/app.dart @@ -6,9 +6,9 @@ import 'package:engelsburg_planer/main.dart'; import 'package:engelsburg_planer/src/backend/database/state/app_state.dart'; import 'package:engelsburg_planer/src/backend/database/state/theme_state.dart'; import 'package:engelsburg_planer/src/services/firebase/analytics.dart'; -import 'package:engelsburg_planer/src/services/firebase/crashlytics.dart'; import 'package:engelsburg_planer/src/utils/extensions.dart'; import 'package:engelsburg_planer/src/utils/global_context.dart'; +import 'package:engelsburg_planer/src/utils/logger.dart'; import 'package:engelsburg_planer/src/view/routing/route_generator.dart'; import 'package:engelsburg_planer/src/view/widgets/util/util_widgets.dart'; import 'package:flutter/material.dart' hide Router; @@ -30,8 +30,8 @@ class EngelsburgPlaner extends StatelessWidget { return Consumer2<ThemeState, AppConfigState>( builder: (context, theme, config, _) { var router = AppRouter.router(context); + Logger.forType<EngelsburgPlaner>().info("Start building app..."); - Crashlytics.log("Start building app.."); return MaterialApp.router( builder: NoOverScrollEffect.get, debugShowCheckedModeBanner: false, diff --git a/lib/src/view/pages/article/article_page.dart b/lib/src/view/pages/article/article_page.dart index 1ad8a2a..7fcc771 100644 --- a/lib/src/view/pages/article/article_page.dart +++ b/lib/src/view/pages/article/article_page.dart @@ -7,6 +7,7 @@ import 'package:engelsburg_planer/src/backend/api/model/article.dart'; import 'package:engelsburg_planer/src/backend/api/requests.dart'; import 'package:engelsburg_planer/src/services/promise.dart'; import 'package:engelsburg_planer/src/utils/extensions.dart'; +import 'package:engelsburg_planer/src/utils/logger.dart'; import 'package:engelsburg_planer/src/view/pages/article/article_card.dart'; import 'package:engelsburg_planer/src/view/pages/article/article_extended.dart'; import 'package:engelsburg_planer/src/view/pages/home_page.dart'; @@ -26,7 +27,7 @@ class ArticlePage extends HomeScreenPage { Stream<Map<String, dynamic>> get update => createConnection("/article"); } -class _ArticlePageState extends HomeScreenPageState<ArticlePage> { +class _ArticlePageState extends HomeScreenPageState<ArticlePage> with Logs<ArticlePage> { /// Controls the scroll of the list view inside of the paged promise final ScrollController scrollController = ScrollController(); @@ -44,6 +45,7 @@ class _ArticlePageState extends HomeScreenPageState<ArticlePage> { void onUpdate(Map<String, dynamic> update) { //Resets the offset of the scroll if the bottomNavigationBar item is pressed while on the page if (update["resetView"] ?? false) { + logger.debug("Resetting scroll view of article page..."); scrollController.animateTo( 0, duration: const Duration(milliseconds: 300), @@ -71,6 +73,7 @@ class _ArticlePageState extends HomeScreenPageState<ArticlePage> { ); if (context.isLandscape && constraints.maxWidth > 600) { + logger.debug("Building article page in landscape mode..."); return StatefulBuilder(builder: (context, setState) { return Row( children: [ @@ -111,6 +114,7 @@ class _ArticlePageState extends HomeScreenPageState<ArticlePage> { }); } + logger.debug("Building article page in portrait mode..."); return Scaffold( floatingActionButton: floatingActionButton, body: PagedPromised<Article>( diff --git a/lib/src/view/pages/grade/grade_page.dart b/lib/src/view/pages/grade/grade_page.dart index ff2d90e..1dcc1d1 100644 --- a/lib/src/view/pages/grade/grade_page.dart +++ b/lib/src/view/pages/grade/grade_page.dart @@ -17,6 +17,7 @@ import 'package:engelsburg_planer/src/backend/database/nosql/model/subjects.dart import 'package:engelsburg_planer/src/backend/database/state/user_state.dart'; import 'package:engelsburg_planer/src/backend/database/nosql/base/document.dart'; import 'package:engelsburg_planer/src/utils/extensions.dart'; +import 'package:engelsburg_planer/src/utils/logger.dart'; import 'package:engelsburg_planer/src/view/pages/grade/grade_average_circle.dart'; import 'package:engelsburg_planer/src/view/pages/grade/grade_extended.dart'; import 'package:engelsburg_planer/src/view/pages/settings/subject/subject_extended.dart'; @@ -25,11 +26,13 @@ import 'package:engelsburg_planer/src/view/widgets/special/storage/stream_consum import 'package:engelsburg_planer/src/view/widgets/util/wrap_if.dart'; import 'package:flutter/material.dart'; -class GradesPage extends StatelessWidget { - const GradesPage({super.key}); +class GradePage extends StatelessWidget with Logs<GradePage> { + const GradePage({super.key}); @override Widget build(BuildContext context) { + logger.debug("Building grade page..."); + return StreamCollection<Subject>( collection: Subjects.entries().defaultStorage(context), itemBuilder: (context, doc, subjects) { diff --git a/lib/src/view/pages/home_page.dart b/lib/src/view/pages/home_page.dart index 1ecd5ab..d0585f7 100644 --- a/lib/src/view/pages/home_page.dart +++ b/lib/src/view/pages/home_page.dart @@ -9,6 +9,7 @@ import 'package:awesome_extensions/awesome_extensions.dart'; import 'package:engelsburg_planer/src/backend/database/state/app_state.dart'; import 'package:engelsburg_planer/src/services/firebase/crashlytics.dart'; import 'package:engelsburg_planer/src/utils/extensions.dart'; +import 'package:engelsburg_planer/src/utils/logger.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:engelsburg_planer/src/backend/database/state/user_state.dart'; @@ -57,7 +58,7 @@ void sendUpdate(String identifier, Map<String, dynamic> data) { _connections[identifier]?.add(data); } -class HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin { +class HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin, Logs<HomePage> { final pageViewKey = GlobalKey<State<PageView>>(); late final PageController _pageController; @@ -135,6 +136,7 @@ class HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin { @override Widget build(BuildContext context) { super.build(context); + logger.debug("Building home page..."); return RouteModifier( child: Consumer<AppConfigState>( diff --git a/lib/src/view/pages/substitute/substitute_page.dart b/lib/src/view/pages/substitute/substitute_page.dart index 71dbe8f..e6ed1d6 100644 --- a/lib/src/view/pages/substitute/substitute_page.dart +++ b/lib/src/view/pages/substitute/substitute_page.dart @@ -10,17 +10,20 @@ import 'package:engelsburg_planer/src/backend/database/cache/session_persistent_ import 'package:engelsburg_planer/src/backend/database/nosql/model/settings/substitute_settings.dart'; import 'package:engelsburg_planer/src/backend/database/state/user_state.dart'; import 'package:engelsburg_planer/src/utils/extensions.dart'; +import 'package:engelsburg_planer/src/utils/logger.dart'; import 'package:engelsburg_planer/src/view/widgets/special/storage/stream_selector.dart'; import 'package:flutter/material.dart'; import 'package:engelsburg_planer/src/view/pages/substitute/substitute_key_page.dart'; import 'package:engelsburg_planer/src/view/pages/substitute/substitute_message_tab.dart'; import 'package:engelsburg_planer/src/view/pages/substitute/substitute_tab.dart'; -class SubstitutesPage extends StatelessWidget { +class SubstitutesPage extends StatelessWidget with Logs<SubstitutesPage> { const SubstitutesPage({super.key}); @override Widget build(BuildContext context) { + logger.debug("Building substitutes page..."); + return StreamSelector<SubstituteSettings, bool>( doc: SubstituteSettings.ref().defaultStorage(context), selector: (substituteSettings) => substituteSettings.password != null, @@ -36,6 +39,8 @@ class SubstitutesPage extends StatelessWidget { void updateTeachers(SubstituteSettings settings) async { if (SessionPersistentData.isSet<Teachers>()) return; + logger.debug("Updating teachers..."); + var request = getTeacher(settings.password!).build(); var response = await request.api<Teachers>(Teachers.fromJson); if (response.dataNotPresent) return; diff --git a/lib/src/view/pages/task/task_page.dart b/lib/src/view/pages/task/task_page.dart index 45e85d4..e7e425b 100644 --- a/lib/src/view/pages/task/task_page.dart +++ b/lib/src/view/pages/task/task_page.dart @@ -4,6 +4,7 @@ import 'package:awesome_extensions/awesome_extensions.dart'; import 'package:engelsburg_planer/src/utils/extensions.dart'; +import 'package:engelsburg_planer/src/utils/logger.dart'; import 'package:engelsburg_planer/src/view/widgets/special/storage/collection_stream_builder.dart'; import 'package:flutter/material.dart'; import 'package:engelsburg_planer/src/backend/database/nosql/model/tasks.dart'; @@ -19,12 +20,14 @@ class TaskPage extends StatefulWidget { State<StatefulWidget> createState() => _TaskPageState(); } -class _TaskPageState extends State<TaskPage> { +class _TaskPageState extends State<TaskPage> with Logs<TaskPage> { bool showAll = false; @override Widget build(BuildContext context) { + logger.debug("Building task page..."); + return Scaffold( floatingActionButton: FloatingActionButton.extended( heroTag: StringUtils.randomAlphaNumeric(10), diff --git a/lib/src/view/pages/timetable/timetable_page.dart b/lib/src/view/pages/timetable/timetable_page.dart index ce6b993..cced85d 100644 --- a/lib/src/view/pages/timetable/timetable_page.dart +++ b/lib/src/view/pages/timetable/timetable_page.dart @@ -6,6 +6,7 @@ import 'package:awesome_extensions/awesome_extensions.dart'; import 'package:engelsburg_planer/src/backend/database/nosql/model/timetable.dart'; import 'package:engelsburg_planer/src/backend/database/nosql/base/document.dart'; import 'package:engelsburg_planer/src/utils/extensions.dart'; +import 'package:engelsburg_planer/src/utils/logger.dart'; import 'package:flutter/material.dart'; import 'package:engelsburg_planer/src/backend/api/model/substitutes.dart'; import 'package:engelsburg_planer/src/backend/database/state/user_state.dart'; @@ -25,7 +26,7 @@ class TimetablePage extends StatefulWidget { State<StatefulWidget> createState() => TimetablePageState(); } -class TimetablePageState extends State<TimetablePage> { +class TimetablePageState extends State<TimetablePage> with Logs<TimetablePage> { late final ScrollController _scrollController; final _animatedList = GlobalKey<AdvancedAnimatedListState>(); @@ -314,6 +315,8 @@ class TimetablePageState extends State<TimetablePage> { @override Widget build(BuildContext context) { + logger.debug("Building substitutes page..."); + return LayoutBuilder( builder: (context, constraints) { if (context.isLandscape && constraints.maxWidth > 500) { diff --git a/lib/src/view/routing/page.dart b/lib/src/view/routing/page.dart index 30a7f0c..4493345 100644 --- a/lib/src/view/routing/page.dart +++ b/lib/src/view/routing/page.dart @@ -287,7 +287,7 @@ class Pages { ); static final StyledRoute grades = StyledRoute.static( - page: const GradesPage(), + page: const GradePage(), path: "/grades", label: (l10n) => l10n.grades, icon: Icons.bar_chart, From 2139a75df232d82305617596f2f27191c5fc56b6 Mon Sep 17 00:00:00 2001 From: Paul Huerkamp <35733278+PAException@users.noreply.github.com> Date: Fri, 1 Dec 2023 18:47:42 +0100 Subject: [PATCH 9/9] v1.0.1 --- .gitignore | 3 +++ build.sh => build_release | 57 ++++++++++++++++++++++++--------------- pubspec.yaml | 4 +-- 3 files changed, 41 insertions(+), 23 deletions(-) rename build.sh => build_release (77%) diff --git a/.gitignore b/.gitignore index 5ac2f1a..4efae83 100644 --- a/.gitignore +++ b/.gitignore @@ -127,5 +127,8 @@ app.*.symbols **/*key.json **/*.p8 **/*.p12 +.ipa +.aab +release/ diff --git a/build.sh b/build_release similarity index 77% rename from build.sh rename to build_release index 35b70e9..aae5f5d 100755 --- a/build.sh +++ b/build_release @@ -5,19 +5,49 @@ ####################################### # Script Usage: -# - This script increments the version number in the Flutter project's pubspec.yaml file. -# - It provides options to increment the MAJOR, MINOR, or PATCH version components. +# - This script must be executed from the root of the Flutter project. +# - It increments the build number in the Flutter project's pubspec.yaml file. +# - It provides options to increment the MAJOR, MINOR, or PATCH version components in +# addition to the build number. # - Release builds for iOS and Android can be disabled using the --no-build option. +# - The appBundle and ipa file are copied to the ./release directory. # Usage: -# ./build.sh [OPTIONS] +# ./build_release [OPTIONS] # Available Options: # --major Increment the MAJOR version component. # --minor Increment the MINOR version component. # --patch Increment the PATCH version component. +# => only one of the options above can be used at a time. +# # --no-build Disable release builds for iOS and Android. +ios_release_build() { + # Build ipa + flutter build ipa --release + + # Copy IPA file to release directory + cp build/ios/ipa/*.ipa ./release +} + +android_release_build() { + # Build appBundle + flutter build appbundle --release + + # Copy App Bundle file to release directory + cp build/app/outputs/bundle/release/*.aab ./release +} + +# Function to execute Flutter release builds for iOS and Android +execute_flutter_release_builds() { + # Ensure release directory exists; create if not present + mkdir -p ./release + + ios_release_build + android_release_build +} + # Function to increment version components in pubspec.yaml increment_flutter_version() { PUBSPEC_FILE="pubspec.yaml" @@ -28,11 +58,11 @@ increment_flutter_version() { BUILD=$(echo "$CURRENT_VERSION" | cut -d+ -f2) if [ "$1" == "--major" ]; then - NEW_VERSION="$((MAJOR + 1)).0.0+0" + NEW_VERSION="$((MAJOR + 1)).0.0+$((BUILD + 1))" elif [ "$1" == "--minor" ]; then - NEW_VERSION="$MAJOR.$((MINOR + 1)).0+0" + NEW_VERSION="$MAJOR.$((MINOR + 1)).0+$((BUILD + 1))" elif [ "$1" == "--patch" ]; then - NEW_VERSION="$MAJOR.$MINOR.$((PATCH + 1))+0" + NEW_VERSION="$MAJOR.$MINOR.$((PATCH + 1))+$((BUILD + 1))" else NEW_VERSION="$MAJOR.$MINOR.$PATCH+$((BUILD + 1))" fi @@ -44,21 +74,6 @@ increment_flutter_version() { echo "Flutter version incremented to $NEW_VERSION" } -# Function to execute Flutter release builds for iOS and Android -execute_flutter_release_builds() { - flutter build ipa --release - flutter build appbundle --release - - # Ensure release directory exists; create if not present - mkdir -p ./release - - # Copy IPA file to release directory - cp build/ios/ipa/*.ipa ./release - - # Copy App Bundle file to release directory - cp build/app/outputs/bundle/release/*.aab ./release -} - # Increment version based on provided options if [ "$1" == "--major" ] || [ "$1" == "--minor" ] || [ "$1" == "--patch" ]; then increment_flutter_version "$1" diff --git a/pubspec.yaml b/pubspec.yaml index 91fb18e..2f639cd 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,7 +15,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 1.0.0+8 +version: 1.0.1+10 environment: sdk: ">=2.19.0 <3.0.0" @@ -147,4 +147,4 @@ flutter_launcher_icons: ios: true remove_alpha_ios: true image_path: "logo.png" - adaptive_icon_background: "#ffffff" \ No newline at end of file + adaptive_icon_background: "#ffffff"