diff --git a/lib/models/channel_message.dart b/lib/models/channel_message.dart index cc4dec2..04663a0 100644 --- a/lib/models/channel_message.dart +++ b/lib/models/channel_message.dart @@ -2,7 +2,15 @@ import 'dart:convert'; part 'channel_message.g.dart'; -enum ChannelAction { showOpener, hideOpener, registerFcmDevice, unregisterFcmDevice, updateNotificationCount, none } +enum ChannelAction { + showOpener, + hideOpener, + registerFcmDevice, + unregisterFcmDevice, + updateNotificationCount, + nativeConsole, + none +} class ChannelMessage { final String type; @@ -14,6 +22,7 @@ class ChannelMessage { if (type == "registerFcmDevice") return ChannelAction.registerFcmDevice; if (type == "unregisterFcmDevice") return ChannelAction.unregisterFcmDevice; if (type == "updateNotificationCount") return ChannelAction.updateNotificationCount; + if (type == "openNativeConsole") return ChannelAction.nativeConsole; return ChannelAction.none; } diff --git a/lib/pages/console.dart b/lib/pages/console.dart new file mode 100644 index 0000000..c8ff453 --- /dev/null +++ b/lib/pages/console.dart @@ -0,0 +1,29 @@ +import 'package:flutter/material.dart'; +import 'package:talker_flutter/talker_flutter.dart'; + +class ConsolePage extends StatelessWidget { + static const String routeName = '/console'; + static Talker talker = TalkerFlutter.init(); + + const ConsolePage({super.key}); + + @override + Widget build(BuildContext context) { + + return Scaffold( + body: TalkerView( + talker: talker, + theme: TalkerScreenTheme( + cardColor: Colors.grey[700]!, + backgroundColor: Colors.grey[800]!, + textColor: Colors.white, + logColors: { + TalkerLogType.error: Colors.red, + TalkerLogType.info: Colors.green, + TalkerLogType.warning: Colors.orange, + }, + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/pages/web_view.dart b/lib/pages/web_view.dart index 998f162..79ae1dd 100644 --- a/lib/pages/web_view.dart +++ b/lib/pages/web_view.dart @@ -29,6 +29,8 @@ import 'package:humhub/util/router.dart' as m; import 'package:url_launcher/url_launcher.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'console.dart'; + class WebView extends ConsumerStatefulWidget { const WebView({super.key}); static const String path = '/web_view'; @@ -275,6 +277,9 @@ class WebViewAppState extends ConsumerState { FlutterAppBadger.updateBadgeCount(message.count!); } break; + case ChannelAction.nativeConsole: + Navigator.of(context).pushNamed(ConsolePage.routeName); + break; case ChannelAction.unregisterFcmDevice: String? token = ref.read(pushTokenProvider).value ?? await FirebaseMessaging.instance.getToken(); if (token != null) { diff --git a/lib/util/intent/intent_plugin.dart b/lib/util/intent/intent_plugin.dart index 85936f6..d098c05 100644 --- a/lib/util/intent/intent_plugin.dart +++ b/lib/util/intent/intent_plugin.dart @@ -59,6 +59,7 @@ class IntentPluginState extends ConsumerState { _sub = uriLinkStream.listen((Uri? uri) async { if (!mounted && uri == null) return; _latestUri = await UrlProviderHandler.handleUniversalLink(uri!) ?? uri; + logInfo('IntentPlugin._subscribeToUriStream', _latestUri); String redirectUrl = _latestUri.toString(); if (navigatorKey.currentState != null) { tryNavigateWithOpener(redirectUrl); @@ -91,6 +92,7 @@ class IntentPluginState extends ConsumerState { if (uri == null || !mounted) return; setState(() => _initialUri = uri); _latestUri = await UrlProviderHandler.handleUniversalLink(uri) ?? uri; + logInfo('IntentPlugin._handleInitialUri', _latestUri); String? redirectUrl = _latestUri.toString(); if (navigatorKey.currentState != null) { tryNavigateWithOpener(redirectUrl); @@ -111,6 +113,7 @@ class IntentPluginState extends ConsumerState { } Future tryNavigateWithOpener(String redirectUrl) async { + logInfo('IntentPlugin.tryNavigateWithOpener', _latestUri); LoadingProvider.of(ref).showLoading(); bool isNewRouteSameAsCurrent = false; navigatorKey.currentState!.popUntil((route) { diff --git a/lib/util/log.dart b/lib/util/log.dart index b8d6956..311ee36 100644 --- a/lib/util/log.dart +++ b/lib/util/log.dart @@ -1,5 +1,7 @@ import 'package:flutter/foundation.dart'; +import 'package:humhub/pages/console.dart'; import 'package:loggy/loggy.dart'; +import 'package:talker_flutter/talker_flutter.dart' as tl; class GlobalLog extends LoggyPrinter { const GlobalLog({ @@ -34,6 +36,25 @@ class GlobalLog extends LoggyPrinter { final color = _colorize ? levelColor(record.level) ?? AnsiColor() : AnsiColor(); final prefix = levelPrefix(record.level) ?? _defaultPrefix; + tl.Talker talker = ConsolePage.talker; + // Log to Talker + switch (record.level) { + case LogLevel.debug: + talker.debug(record.message, record.error, record.stackTrace); + break; + case LogLevel.info: + talker.info(record.message, record.error, record.stackTrace); + break; + case LogLevel.warning: + talker.warning(record.message, record.error, record.stackTrace); + break; + case LogLevel.error: + talker.error(record.message, record.error, record.stackTrace); + break; + default: + talker.log(record.message); + break; + } if (kDebugMode) { print(color('$prefix$time $logLevel GLOBAL $callerFrame ${record.message}')); diff --git a/lib/util/router.dart b/lib/util/router.dart index 1316f25..c8e069e 100644 --- a/lib/util/router.dart +++ b/lib/util/router.dart @@ -4,6 +4,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:humhub/models/hum_hub.dart'; import 'package:humhub/models/manifest.dart'; +import 'package:humhub/pages/console.dart'; import 'package:humhub/pages/help/help.dart'; import 'package:humhub/pages/opener/opener.dart'; import 'package:humhub/pages/web_view.dart'; @@ -51,6 +52,13 @@ class MyRouter { ]); return const Help(); }, + + ConsolePage.routeName: (context) { + SystemChrome.setPreferredOrientations([ + DeviceOrientation.portraitUp, + ]); + return const ConsolePage(); + }, }; static Future getInitialRoute(WidgetRef ref) async { diff --git a/pubspec.lock b/pubspec.lock index 4114162..159f09a 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -25,6 +25,14 @@ packages: url: "https://pub.dev" source: hosted version: "6.4.1" + ansicolor: + dependency: transitive + description: + name: ansicolor + sha256: "50e982d500bc863e1d703448afdbf9e5a72eb48840a4f766fa361ffd6877055f" + url: "https://pub.dev" + source: hosted + version: "2.0.3" app_settings: dependency: "direct main" description: @@ -169,6 +177,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.1" + cross_file: + dependency: transitive + description: + name: cross_file + sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" + url: "https://pub.dev" + source: hosted + version: "0.3.4+2" crypto: dependency: transitive description: @@ -501,6 +517,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.0" + group_button: + dependency: transitive + description: + name: group_button + sha256: "0610fcf28ed122bfb4b410fce161a390f7f2531d55d1d65c5375982001415940" + url: "https://pub.dev" + source: hosted + version: "5.3.4" http: dependency: "direct main" description: @@ -605,6 +629,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.11.0" + mime: + dependency: transitive + description: + name: mime + sha256: "801fd0b26f14a4a58ccb09d5892c3fbdeff209594300a542492cf13fba9d247a" + url: "https://pub.dev" + source: hosted + version: "1.0.6" mockito: dependency: "direct dev" description: @@ -837,6 +869,22 @@ packages: url: "https://pub.dev" source: hosted version: "0.27.7" + share_plus: + dependency: transitive + description: + name: share_plus + sha256: ef3489a969683c4f3d0239010cc8b7a2a46543a8d139e111c06c558875083544 + url: "https://pub.dev" + source: hosted + version: "9.0.0" + share_plus_platform_interface: + dependency: transitive + description: + name: share_plus_platform_interface + sha256: "0f9e4418835d1b2c3ae78fdb918251959106cefdbc4dd43526e182f80e82f6d4" + url: "https://pub.dev" + source: hosted + version: "4.0.0" shared_preferences: dependency: "direct main" description: @@ -986,6 +1034,30 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.0+1" + talker: + dependency: transitive + description: + name: talker + sha256: "71dcd28543c04ca517ac6171d78b7953ab8f9be95a0a4248795f45f267950593" + url: "https://pub.dev" + source: hosted + version: "4.6.6" + talker_flutter: + dependency: "direct main" + description: + name: talker_flutter + sha256: a24b977f1241714f18d714e2675a97cb9ac15c18ac602edf9426dd85f15cfd60 + url: "https://pub.dev" + source: hosted + version: "4.4.0" + talker_logger: + dependency: transitive + description: + name: talker_logger + sha256: "3f8315cc46f17c8022dfb237b7e291fb7a941ce4c8865ecbe1b94f7fcb3038f4" + url: "https://pub.dev" + source: hosted + version: "4.6.6" term_glyph: dependency: transitive description: @@ -1070,10 +1142,10 @@ packages: dependency: transitive description: name: url_launcher_linux - sha256: "360fa359ab06bcb4f7c5cd3123a2a9a4d3364d4575d27c4b33468bd4497dd094" + sha256: "4e9ba368772369e3e08f231d2301b4ef72b9ff87c31192ef471b380ef29a4935" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.2.1" url_launcher_macos: dependency: transitive description: @@ -1086,26 +1158,26 @@ packages: dependency: transitive description: name: url_launcher_platform_interface - sha256: "4eae912628763eb48fc214522e58e942fd16ce195407dbf45638239523c759a6" + sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.3.2" url_launcher_web: dependency: transitive description: name: url_launcher_web - sha256: "5669882643b96bb6d5786637cac727c6e918a790053b09245fd4513b8a07df2a" + sha256: "772638d3b34c779ede05ba3d38af34657a05ac55b06279ea6edd409e323dca8e" url: "https://pub.dev" source: hosted - version: "2.0.13" + version: "2.3.3" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - sha256: e3c3b16d3104260c10eea3b0e34272aaa57921f83148b0619f74c2eced9b7ef1 + sha256: "44cf3aabcedde30f2dba119a9dea3b0f2672fbe6fa96e85536251d678216b3c4" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.1.3" uuid: dependency: transitive description: @@ -1138,6 +1210,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" + web: + dependency: transitive + description: + name: web + sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" + url: "https://pub.dev" + source: hosted + version: "0.5.1" win32: dependency: transitive description: @@ -1172,4 +1252,4 @@ packages: version: "3.1.2" sdks: dart: ">=3.3.0 <3.4.0" - flutter: ">=3.16.6" + flutter: ">=3.19.0" diff --git a/pubspec.yaml b/pubspec.yaml index 8ab0f07..28b0e2c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -63,6 +63,7 @@ dependencies: path_provider: ^2.1.4 open_file_plus: ^3.4.1+1 cached_network_image: ^3.3.1 + talker_flutter: ^4.4.0 dev_dependencies: flutter_test: