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 extends CollectionReference {
//TODO docs
Future>> documents() async {
- var cached = _storage.state.getCachedCollection(this);
- if (cached != null) return cached.map((e) => e.storage(_storage)).toList();
+ var cached = _storage.state.getCachedCollection(this);
+ print(cached.runtimeType);
+ if (cached != null) return cached.cast>().map((e) => e.storage(_storage)).cast>().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 {
@override
int get hashCode => path.hashCode;
+
+ Reference cast(Parser parser);
}
/// Same as Reference, but only to documents.
@@ -55,6 +57,9 @@ class DocumentReference extends Reference {
);
}
+ @override
+ DocumentReference cast(Parser parser) => DocumentReference(path, parser);
+
/// Makes the reference concrete, links a storage to the reference.
@nonVirtual
Document storage(Storage storage) => Document.ref(storage, this);
@@ -76,6 +81,9 @@ class CollectionReference extends Reference {
parser,
);
+ @override
+ CollectionReference cast(Parser parser) => CollectionReference(path, parser);
+
/// Makes the reference concrete, links a storage to the reference.
@nonVirtual
Collection storage(Storage storage) => Collection.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 data) {
+ void setDocument(DocumentReference document, Map 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(CollectionReference 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(key, collection.parser);
//Update each document
setDocument(document, value);
@@ -80,9 +80,9 @@ class StorageCache {
List>? getCollection(CollectionReference collection) {
debugPrint("[${collection.id}] getting cached collection");
- var refs = _collectionCache[collection]?.toList() ?? [];
+ var refs = _collectionCache[collection];
- return refs.cast>();
+ 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>? getCachedCollection(
CollectionReference collection,
) {
- return _cache.getCollection(collection);
+ return _cache.getCollection(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
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
@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
},
),
),
- 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 {
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 extends CollectionReference {
//TODO docs
Future>> documents() async {
var cached = _storage.state.getCachedCollection(this);
- print(cached.runtimeType);
if (cached != null) return cached.cast>().map((e) => e.storage(_storage)).cast>().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 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 {
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
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 {
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
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
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 {
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 {
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 {
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 {
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 {
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 {
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 {
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 {
_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().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().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 extends DocumentReference {
/// the operation was successful.
Future 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 {
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 {
final Map> _documentCache = {};
final Map> _collectionCache = {};
/// 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 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? 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(CollectionReference 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>? getCollection(CollectionReference 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 {
/// Caches timers for delayed document updates (reference, timer)
final Map _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 {
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 document,
required Stream 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 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;
typedef CollectionStreamSub = StreamSubscription;
//TODO docs
-class StorageStreams {
+class StorageStreams with Logs {
/// Caches snapshot streams of documents (reference, streams)
final Map> _documentStreams = {};
final Map _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 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(
@@ -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 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(
@@ -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 {
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 {
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 get logger => Logger.forType();
+
/// Initializes every used firebase service
static Future 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 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 {
+ static final Map> _loggers = {};
+ static Level rootLevel = debugMode ? Level.debug : Level.info;
+ static bool debugMode = kDebugMode;
+ static bool analytics = !kDebugMode;
+
+ static Logger forType([Level? level]) {
+ if (!_loggers.containsKey(T)) {
+ _loggers[T] = Logger(level ?? rootLevel);
+ } else if (level != null) {
+ _loggers[T]!.level = level;
+ }
+
+ return _loggers[T] as Logger;
+ }
+
+ 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 {
+ Logger get logger => Logger.forType();
+}
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().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(
builder: (context, theme, config, _) {
var router = AppRouter.router(context);
+ Logger.forType().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