From 75787d51ff442af120cb04f2ba0a74f0e5fa62ff Mon Sep 17 00:00:00 2001 From: Sven Carstensen Date: Fri, 15 Mar 2024 09:40:13 +0100 Subject: [PATCH] Erweiterungen --- lib/content_views/main_page.dart | 15 +- lib/main.dart | 2 + lib/model/log_entry.dart | 27 ++ lib/model/log_entry.g.dart | 662 +++++++++++++++++++++++++++++++ lib/tools/mqtt_core.dart | 6 +- lib/tools/util.dart | 24 ++ 6 files changed, 731 insertions(+), 5 deletions(-) create mode 100644 lib/model/log_entry.dart create mode 100644 lib/model/log_entry.g.dart diff --git a/lib/content_views/main_page.dart b/lib/content_views/main_page.dart index 966497b..f2b8888 100644 --- a/lib/content_views/main_page.dart +++ b/lib/content_views/main_page.dart @@ -1,3 +1,4 @@ +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:isar/isar.dart'; import 'package:stadtbote/content_views/accepted_jobs_page.dart'; @@ -231,7 +232,13 @@ class _MainPageState extends State { getDefaultButton( _loggedOut ? 'Anmelden' : 'Abmelden', image: Image.asset(_loggedOut ? 'assets/anmelden.png' : 'assets/abmelden.png', width: 30, height: 30), - () async => {_logout(context)}), + () async { + if (!kDebugMode) { + _logout(context); + } else { + _test(); + } + }), Expanded( child: Container( decoration: BoxDecoration( @@ -379,4 +386,10 @@ class _MainPageState extends State { MqttCore.instance.publishPayloadMessage('session', logoutMessage.toJson()); } + + void _test() { + var otto = MyApp.isarInstance; + + Util.logInfo('message'); + } } diff --git a/lib/main.dart b/lib/main.dart index b97fd9b..3ddcaa7 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -6,6 +6,7 @@ import 'package:isar/isar.dart'; import 'package:path_provider/path_provider.dart'; import 'package:stadtbote/messages/pop_content_view_message.dart'; import 'package:stadtbote/model/enqueued_message.dart'; +import 'package:stadtbote/model/log_entry.dart'; import 'package:stadtbote/model/message.dart'; import 'package:stadtbote/model/ranking.dart'; import 'package:stadtbote/model/status.dart'; @@ -38,6 +39,7 @@ Future main() async { MessageSchema, RankingSchema, EnqueuedMessageSchema, + LogEntrySchema ], directory: dir.path); runZonedGuarded(() {}, (error, stackTrace) { diff --git a/lib/model/log_entry.dart b/lib/model/log_entry.dart new file mode 100644 index 0000000..f3b0cb7 --- /dev/null +++ b/lib/model/log_entry.dart @@ -0,0 +1,27 @@ +import 'package:isar/isar.dart'; +import 'package:json_annotation/json_annotation.dart'; + +part 'log_entry.g.dart'; + +enum LogEntrySeverityEnum { + info, + debug, + error +} + +@collection +@JsonSerializable() +class LogEntry { + late Id id = Isar.autoIncrement; + + late DateTime time; + + @enumerated + late LogEntrySeverityEnum severity; + + late String text; + + LogEntry(); + + Map toJson() => _$LogEntryToJson(this); +} \ No newline at end of file diff --git a/lib/model/log_entry.g.dart b/lib/model/log_entry.g.dart new file mode 100644 index 0000000..791b8be --- /dev/null +++ b/lib/model/log_entry.g.dart @@ -0,0 +1,662 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'log_entry.dart'; + +// ************************************************************************** +// IsarCollectionGenerator +// ************************************************************************** + +// coverage:ignore-file +// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types + +extension GetLogEntryCollection on Isar { + IsarCollection get logEntrys => this.collection(); +} + +const LogEntrySchema = CollectionSchema( + name: r'LogEntry', + id: -8268688274231935295, + properties: { + r'severity': PropertySchema( + id: 0, + name: r'severity', + type: IsarType.byte, + enumMap: _LogEntryseverityEnumValueMap, + ), + r'text': PropertySchema( + id: 1, + name: r'text', + type: IsarType.string, + ), + r'time': PropertySchema( + id: 2, + name: r'time', + type: IsarType.dateTime, + ) + }, + estimateSize: _logEntryEstimateSize, + serialize: _logEntrySerialize, + deserialize: _logEntryDeserialize, + deserializeProp: _logEntryDeserializeProp, + idName: r'id', + indexes: {}, + links: {}, + embeddedSchemas: {}, + getId: _logEntryGetId, + getLinks: _logEntryGetLinks, + attach: _logEntryAttach, + version: '3.1.0+1', +); + +int _logEntryEstimateSize( + LogEntry object, + List offsets, + Map> allOffsets, +) { + var bytesCount = offsets.last; + bytesCount += 3 + object.text.length * 3; + return bytesCount; +} + +void _logEntrySerialize( + LogEntry object, + IsarWriter writer, + List offsets, + Map> allOffsets, +) { + writer.writeByte(offsets[0], object.severity.index); + writer.writeString(offsets[1], object.text); + writer.writeDateTime(offsets[2], object.time); +} + +LogEntry _logEntryDeserialize( + Id id, + IsarReader reader, + List offsets, + Map> allOffsets, +) { + final object = LogEntry(); + object.id = id; + object.severity = + _LogEntryseverityValueEnumMap[reader.readByteOrNull(offsets[0])] ?? + LogEntrySeverityEnum.info; + object.text = reader.readString(offsets[1]); + object.time = reader.readDateTime(offsets[2]); + return object; +} + +P _logEntryDeserializeProp

( + IsarReader reader, + int propertyId, + int offset, + Map> allOffsets, +) { + switch (propertyId) { + case 0: + return (_LogEntryseverityValueEnumMap[reader.readByteOrNull(offset)] ?? + LogEntrySeverityEnum.info) as P; + case 1: + return (reader.readString(offset)) as P; + case 2: + return (reader.readDateTime(offset)) as P; + default: + throw IsarError('Unknown property with id $propertyId'); + } +} + +const _LogEntryseverityEnumValueMap = { + 'info': 0, + 'debug': 1, + 'error': 2, +}; +const _LogEntryseverityValueEnumMap = { + 0: LogEntrySeverityEnum.info, + 1: LogEntrySeverityEnum.debug, + 2: LogEntrySeverityEnum.error, +}; + +Id _logEntryGetId(LogEntry object) { + return object.id; +} + +List> _logEntryGetLinks(LogEntry object) { + return []; +} + +void _logEntryAttach(IsarCollection col, Id id, LogEntry object) { + object.id = id; +} + +extension LogEntryQueryWhereSort on QueryBuilder { + QueryBuilder anyId() { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(const IdWhereClause.any()); + }); + } +} + +extension LogEntryQueryWhere on QueryBuilder { + QueryBuilder idEqualTo(Id id) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IdWhereClause.between( + lower: id, + upper: id, + )); + }); + } + + QueryBuilder idNotEqualTo(Id id) { + return QueryBuilder.apply(this, (query) { + if (query.whereSort == Sort.asc) { + return query + .addWhereClause( + IdWhereClause.lessThan(upper: id, includeUpper: false), + ) + .addWhereClause( + IdWhereClause.greaterThan(lower: id, includeLower: false), + ); + } else { + return query + .addWhereClause( + IdWhereClause.greaterThan(lower: id, includeLower: false), + ) + .addWhereClause( + IdWhereClause.lessThan(upper: id, includeUpper: false), + ); + } + }); + } + + QueryBuilder idGreaterThan(Id id, + {bool include = false}) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause( + IdWhereClause.greaterThan(lower: id, includeLower: include), + ); + }); + } + + QueryBuilder idLessThan(Id id, + {bool include = false}) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause( + IdWhereClause.lessThan(upper: id, includeUpper: include), + ); + }); + } + + QueryBuilder idBetween( + Id lowerId, + Id upperId, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IdWhereClause.between( + lower: lowerId, + includeLower: includeLower, + upper: upperId, + includeUpper: includeUpper, + )); + }); + } +} + +extension LogEntryQueryFilter + on QueryBuilder { + QueryBuilder idEqualTo(Id value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'id', + value: value, + )); + }); + } + + QueryBuilder idGreaterThan( + Id value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'id', + value: value, + )); + }); + } + + QueryBuilder idLessThan( + Id value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'id', + value: value, + )); + }); + } + + QueryBuilder idBetween( + Id lower, + Id upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'id', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder severityEqualTo( + LogEntrySeverityEnum value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'severity', + value: value, + )); + }); + } + + QueryBuilder severityGreaterThan( + LogEntrySeverityEnum value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'severity', + value: value, + )); + }); + } + + QueryBuilder severityLessThan( + LogEntrySeverityEnum value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'severity', + value: value, + )); + }); + } + + QueryBuilder severityBetween( + LogEntrySeverityEnum lower, + LogEntrySeverityEnum upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'severity', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder textEqualTo( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'text', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder textGreaterThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'text', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder textLessThan( + String value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'text', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder textBetween( + String lower, + String upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'text', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder textStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'text', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder textEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'text', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder textContains( + String value, + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'text', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder textMatches( + String pattern, + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'text', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder textIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'text', + value: '', + )); + }); + } + + QueryBuilder textIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'text', + value: '', + )); + }); + } + + QueryBuilder timeEqualTo( + DateTime value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'time', + value: value, + )); + }); + } + + QueryBuilder timeGreaterThan( + DateTime value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'time', + value: value, + )); + }); + } + + QueryBuilder timeLessThan( + DateTime value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'time', + value: value, + )); + }); + } + + QueryBuilder timeBetween( + DateTime lower, + DateTime upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'time', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } +} + +extension LogEntryQueryObject + on QueryBuilder {} + +extension LogEntryQueryLinks + on QueryBuilder {} + +extension LogEntryQuerySortBy on QueryBuilder { + QueryBuilder sortBySeverity() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'severity', Sort.asc); + }); + } + + QueryBuilder sortBySeverityDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'severity', Sort.desc); + }); + } + + QueryBuilder sortByText() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'text', Sort.asc); + }); + } + + QueryBuilder sortByTextDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'text', Sort.desc); + }); + } + + QueryBuilder sortByTime() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'time', Sort.asc); + }); + } + + QueryBuilder sortByTimeDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'time', Sort.desc); + }); + } +} + +extension LogEntryQuerySortThenBy + on QueryBuilder { + QueryBuilder thenById() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'id', Sort.asc); + }); + } + + QueryBuilder thenByIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'id', Sort.desc); + }); + } + + QueryBuilder thenBySeverity() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'severity', Sort.asc); + }); + } + + QueryBuilder thenBySeverityDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'severity', Sort.desc); + }); + } + + QueryBuilder thenByText() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'text', Sort.asc); + }); + } + + QueryBuilder thenByTextDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'text', Sort.desc); + }); + } + + QueryBuilder thenByTime() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'time', Sort.asc); + }); + } + + QueryBuilder thenByTimeDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'time', Sort.desc); + }); + } +} + +extension LogEntryQueryWhereDistinct + on QueryBuilder { + QueryBuilder distinctBySeverity() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'severity'); + }); + } + + QueryBuilder distinctByText( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'text', caseSensitive: caseSensitive); + }); + } + + QueryBuilder distinctByTime() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'time'); + }); + } +} + +extension LogEntryQueryProperty + on QueryBuilder { + QueryBuilder idProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'id'); + }); + } + + QueryBuilder + severityProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'severity'); + }); + } + + QueryBuilder textProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'text'); + }); + } + + QueryBuilder timeProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'time'); + }); + } +} + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +LogEntry _$LogEntryFromJson(Map json) => LogEntry() + ..id = json['id'] as int + ..time = DateTime.parse(json['time'] as String) + ..severity = $enumDecode(_$LogEntrySeverityEnumEnumMap, json['severity']) + ..text = json['text'] as String; + +Map _$LogEntryToJson(LogEntry instance) => { + 'id': instance.id, + 'time': instance.time.toIso8601String(), + 'severity': _$LogEntrySeverityEnumEnumMap[instance.severity]!, + 'text': instance.text, + }; + +const _$LogEntrySeverityEnumEnumMap = { + LogEntrySeverityEnum.info: 'info', + LogEntrySeverityEnum.debug: 'debug', + LogEntrySeverityEnum.error: 'error', +}; diff --git a/lib/tools/mqtt_core.dart b/lib/tools/mqtt_core.dart index c88447e..b4d72cf 100644 --- a/lib/tools/mqtt_core.dart +++ b/lib/tools/mqtt_core.dart @@ -137,7 +137,7 @@ class MqttCore { _mqttClient.publishMessage(topic, MqttQos.exactlyOnce, buffer); - Util.logInfo("message $text send to $topic"); + Util.logInfo("message\n$text\nsend to $topic"); } publishPayloadMessage(String topic, Map payload) { @@ -165,9 +165,7 @@ class MqttCore { String payload = utf8.decode(MqttPublishPayload.bytesToStringAsString(message.payload.message).codeUnits); var topic = message.variableHeader?.topicName; - Util.logInfo('message received'); - Util.logInfo('topic: $topic'); - Util.logInfo('message: $payload'); + Util.logInfo('message received\ntopic: $topic\nmessage: $payload'); Map messageData = jsonDecode(payload); diff --git a/lib/tools/util.dart b/lib/tools/util.dart index cf6205a..95f8c8d 100644 --- a/lib/tools/util.dart +++ b/lib/tools/util.dart @@ -6,7 +6,9 @@ import 'package:flutter/services.dart'; import 'package:image_picker/image_picker.dart'; import 'package:package_info/package_info.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import 'package:stadtbote/main.dart'; import 'package:stadtbote/model/job.dart'; +import 'package:stadtbote/model/log_entry.dart'; import 'package:stadtbote/tools/constants.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:uuid/uuid.dart'; @@ -83,12 +85,34 @@ class Util { final pattern = RegExp('.{1,800}'); // 800 is the size of each chunk pattern.allMatches(text).forEach((match) => debugPrint(match.group(0))); } + + static void _persistLogMessage(String text, LogEntrySeverityEnum severity) { + var logEntry = LogEntry(); + logEntry.time = DateTime.now(); + logEntry.text = text; + logEntry.severity = severity; + + MyApp.isarInstance.writeTxnSync(() { + MyApp.isarInstance.logEntrys.putSync(logEntry); + }); + } + static logInfo(String message) { _printLongText(message); + + _persistLogMessage(message, LogEntrySeverityEnum.info); + } + + static logDebug(String message) { + _printLongText(message); + + _persistLogMessage(message, LogEntrySeverityEnum.debug); } static logException(String message) { _printLongText(message); + + _persistLogMessage(message, LogEntrySeverityEnum.error); } static int fastHash(String string) {