refactor: logs page show full log

This commit is contained in:
Kingkor Roy Tirtho 2024-08-10 20:53:17 +06:00
parent 123eb168a3
commit 6456b43d10
3 changed files with 35 additions and 111 deletions

View File

@ -1,77 +1,23 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:spotube/collections/spotube_icons.dart'; import 'package:spotube/collections/spotube_icons.dart';
import 'package:spotube/modules/settings/section_card_with_heading.dart';
import 'package:spotube/components/inter_scrollbar/inter_scrollbar.dart'; import 'package:spotube/components/inter_scrollbar/inter_scrollbar.dart';
import 'package:spotube/components/titlebar/titlebar.dart'; import 'package:spotube/components/titlebar/titlebar.dart';
import 'package:spotube/extensions/context.dart'; import 'package:spotube/extensions/context.dart';
import 'package:spotube/services/logger/logger.dart'; import 'package:spotube/provider/logs/logs_provider.dart';
class LogsPage extends HookWidget { class LogsPage extends HookConsumerWidget {
static const name = "logs"; static const name = "logs";
const LogsPage({super.key}); const LogsPage({super.key});
List<({DateTime? date, String body})> parseLogs(String raw) {
return raw
.split(
"======================================================================",
)
.map(
(line) {
DateTime? date;
line = line
.replaceAll(
"============================== CATCHER LOG ==============================",
"",
)
.split("\n")
.map((l) {
if (l.startsWith("Crash occurred on")) {
date = DateTime.parse(
l.split("Crash occurred on")[1].trim(),
);
return "";
}
return l;
})
.where((l) => l.replaceAll("\n", "").trim().isNotEmpty)
.join("\n");
return (
date: date,
body: line,
);
},
)
.where((e) => e.date != null && e.body.isNotEmpty)
.toList()
..sort((a, b) => b.date!.compareTo(a.date!));
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context, ref) {
final controller = useScrollController(); final controller = useScrollController();
final logs = useState<List<({DateTime? date, String body})>>([]);
final rawLogs = useRef<String>("");
final path = useRef<File?>(null);
useEffect(() { final logsQuery = ref.watch(logsProvider);
final timer = Timer.periodic(const Duration(seconds: 5), (t) async {
path.value ??= await AppLogger.getLogsPath();
final raw = await path.value!.readAsString();
final hasChanged = rawLogs.value != raw;
rawLogs.value = raw;
if (hasChanged) logs.value = parseLogs(rawLogs.value);
});
return () {
timer.cancel();
};
}, []);
return Scaffold( return Scaffold(
appBar: PageWindowTitleBar( appBar: PageWindowTitleBar(
@ -82,7 +28,9 @@ class LogsPage extends HookWidget {
icon: const Icon(SpotubeIcons.clipboard), icon: const Icon(SpotubeIcons.clipboard),
iconSize: 16, iconSize: 16,
onPressed: () async { onPressed: () async {
await Clipboard.setData(ClipboardData(text: rawLogs.value)); final logsSnapshot = await ref.read(logsProvider.future);
await Clipboard.setData(ClipboardData(text: logsSnapshot));
if (context.mounted) { if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar( SnackBar(
@ -95,52 +43,22 @@ class LogsPage extends HookWidget {
], ],
), ),
body: SafeArea( body: SafeArea(
child: InterScrollbar( child: switch (logsQuery) {
controller: controller, AsyncData(:final value) => Card(
child: ListView.builder( child: InterScrollbar(
controller: controller, controller: controller,
itemCount: logs.value.length, child: Padding(
itemBuilder: (context, index) { padding: const EdgeInsets.all(8.0),
final log = logs.value[index]; child: SingleChildScrollView(
return Stack( controller: controller,
children: [ child: Text(value),
SectionCardWithHeading(
heading: log.date.toString(),
children: [
Padding(
padding: const EdgeInsets.all(12.0),
child: SelectableText(log.body),
),
],
), ),
Positioned( ),
right: 10, ),
top: 0, ),
child: IconButton( AsyncError(:final error) => Center(child: Text(error.toString())),
icon: const Icon(SpotubeIcons.clipboard), _ => const Center(child: CircularProgressIndicator()),
onPressed: () async { },
await Clipboard.setData(
ClipboardData(text: log.body),
);
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
context.l10n.copied_to_clipboard(
log.date.toString(),
),
),
),
);
}
},
),
),
],
);
},
),
),
), ),
); );
} }

View File

@ -0,0 +1,12 @@
import 'dart:convert';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:spotube/services/logger/logger.dart';
final logsProvider = StreamProvider.autoDispose((ref) async* {
final file = await AppLogger.getLogsPath();
final stream = file.openRead().transform(utf8.decoder);
await for (final line in stream) {
yield line;
}
});

View File

@ -61,8 +61,6 @@ PODS:
- sqlite3/rtree - sqlite3/rtree
- system_theme (0.0.1): - system_theme (0.0.1):
- FlutterMacOS - FlutterMacOS
- system_tray (0.0.1):
- FlutterMacOS
- tray_manager (0.0.1): - tray_manager (0.0.1):
- FlutterMacOS - FlutterMacOS
- url_launcher_macos (0.0.1): - url_launcher_macos (0.0.1):
@ -93,7 +91,6 @@ DEPENDENCIES:
- sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/darwin`) - sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/darwin`)
- sqlite3_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos`) - sqlite3_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos`)
- system_theme (from `Flutter/ephemeral/.symlinks/plugins/system_theme/macos`) - system_theme (from `Flutter/ephemeral/.symlinks/plugins/system_theme/macos`)
- system_tray (from `Flutter/ephemeral/.symlinks/plugins/system_tray/macos`)
- tray_manager (from `Flutter/ephemeral/.symlinks/plugins/tray_manager/macos`) - tray_manager (from `Flutter/ephemeral/.symlinks/plugins/tray_manager/macos`)
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
- window_manager (from `Flutter/ephemeral/.symlinks/plugins/window_manager/macos`) - window_manager (from `Flutter/ephemeral/.symlinks/plugins/window_manager/macos`)
@ -148,8 +145,6 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos :path: Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos
system_theme: system_theme:
:path: Flutter/ephemeral/.symlinks/plugins/system_theme/macos :path: Flutter/ephemeral/.symlinks/plugins/system_theme/macos
system_tray:
:path: Flutter/ephemeral/.symlinks/plugins/system_tray/macos
tray_manager: tray_manager:
:path: Flutter/ephemeral/.symlinks/plugins/tray_manager/macos :path: Flutter/ephemeral/.symlinks/plugins/tray_manager/macos
url_launcher_macos: url_launcher_macos:
@ -182,7 +177,6 @@ SPEC CHECKSUMS:
sqlite3: 292c3e1bfe89f64e51ea7fc7dab9182a017c8630 sqlite3: 292c3e1bfe89f64e51ea7fc7dab9182a017c8630
sqlite3_flutter_libs: 1be4459672f8168ded2d8667599b8e3ca5e72b83 sqlite3_flutter_libs: 1be4459672f8168ded2d8667599b8e3ca5e72b83
system_theme: c7b9f6659a5caa26c9bc2284da096781e9a6fcbc system_theme: c7b9f6659a5caa26c9bc2284da096781e9a6fcbc
system_tray: e53c972838c69589ff2e77d6d3abfd71332f9e5d
tray_manager: 9064e219c56d75c476e46b9a21182087930baf90 tray_manager: 9064e219c56d75c476e46b9a21182087930baf90
url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95 url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95
window_manager: 3a1844359a6295ab1e47659b1a777e36773cd6e8 window_manager: 3a1844359a6295ab1e47659b1a777e36773cd6e8