feat: logs page in settings

This commit is contained in:
Kingkor Roy Tirtho 2023-06-19 22:36:05 +06:00
parent 4a75f3dbd1
commit b78e7f57a0
9 changed files with 167 additions and 77 deletions

View File

@ -8,6 +8,7 @@ import 'package:spotube/pages/lyrics/mini_lyrics.dart';
import 'package:spotube/pages/search/search.dart'; import 'package:spotube/pages/search/search.dart';
import 'package:spotube/pages/settings/blacklist.dart'; import 'package:spotube/pages/settings/blacklist.dart';
import 'package:spotube/pages/settings/about.dart'; import 'package:spotube/pages/settings/about.dart';
import 'package:spotube/pages/settings/logs.dart';
import 'package:spotube/utils/platform.dart'; import 'package:spotube/utils/platform.dart';
import 'package:spotube/components/shared/spotube_page_route.dart'; import 'package:spotube/components/shared/spotube_page_route.dart';
import 'package:spotube/pages/album/album.dart'; import 'package:spotube/pages/album/album.dart';
@ -83,10 +84,16 @@ final router = GoRouter(
child: const BlackListPage(), child: const BlackListPage(),
), ),
), ),
GoRoute(
path: "logs",
pageBuilder: (context, state) => SpotubeSlidePage(
child: const LogsPage(),
),
),
GoRoute( GoRoute(
path: "about", path: "about",
pageBuilder: (context, state) => const SpotubePage( pageBuilder: (context, state) => SpotubeSlidePage(
child: AboutSpotube(), child: const AboutSpotube(),
), ),
), ),
], ],

View File

@ -87,4 +87,6 @@ abstract class SpotubeIcons {
static const volumeLow = FeatherIcons.volume; static const volumeLow = FeatherIcons.volume;
static const volumeMute = FeatherIcons.volumeX; static const volumeMute = FeatherIcons.volumeX;
static const timer = FeatherIcons.clock; static const timer = FeatherIcons.clock;
static const logs = FeatherIcons.fileText;
static const clipboard = FeatherIcons.clipboard;
} }

View File

@ -244,5 +244,7 @@
"mins": "{minutes} Minutes", "mins": "{minutes} Minutes",
"hours": "{hours} Hours", "hours": "{hours} Hours",
"hour": "{hours} Hour", "hour": "{hours} Hour",
"custom_hours": "Custom Hours" "custom_hours": "Custom Hours",
"logs": "Logs",
"developers": "Developers"
} }

View File

@ -26,7 +26,6 @@ import 'package:spotube/provider/palette_provider.dart';
import 'package:spotube/provider/user_preferences_provider.dart'; import 'package:spotube/provider/user_preferences_provider.dart';
import 'package:spotube/services/audio_player/audio_player.dart'; import 'package:spotube/services/audio_player/audio_player.dart';
import 'package:spotube/themes/theme.dart'; import 'package:spotube/themes/theme.dart';
import 'package:spotube/utils/custom_toast_handler.dart';
import 'package:spotube/utils/persisted_state_notifier.dart'; import 'package:spotube/utils/persisted_state_notifier.dart';
import 'package:supabase_flutter/supabase_flutter.dart'; import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:system_theme/system_theme.dart'; import 'package:system_theme/system_theme.dart';
@ -122,16 +121,11 @@ Future<void> main(List<String> rawArgs) async {
releaseConfig: CatcherOptions( releaseConfig: CatcherOptions(
SilentReportMode(), SilentReportMode(),
[ [
if (arguments["verbose"] ?? false) if (arguments["verbose"] ?? false) ConsoleHandler(),
ConsoleHandler(
enableDeviceParameters: false,
enableApplicationParameters: false,
),
FileHandler( FileHandler(
await getLogsPath(), await getLogsPath(),
printLogs: false, printLogs: false,
), ),
CustomToastHandler(),
], ],
), ),
runAppFunction: () { runAppFunction: () {

View File

@ -0,0 +1,139 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:spotube/collections/spotube_icons.dart';
import 'package:spotube/components/settings/section_card_with_heading.dart';
import 'package:spotube/components/shared/page_window_title_bar.dart';
import 'package:spotube/extensions/context.dart';
import 'package:spotube/models/logger.dart';
class LogsPage extends HookWidget {
const LogsPage({Key? key}) : super(key: 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
Widget build(BuildContext context) {
final logs = useState<List<({DateTime? date, String body})>>([]);
final rawLogs = useRef<String>("");
final path = useRef<File?>(null);
useEffect(() {
final timer = Timer.periodic(const Duration(seconds: 5), (t) async {
path.value ??= await 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(
appBar: PageWindowTitleBar(
title: Text(context.l10n.logs),
leading: const BackButton(),
actions: [
IconButton(
icon: const Icon(SpotubeIcons.clipboard),
iconSize: 16,
onPressed: () async {
await Clipboard.setData(ClipboardData(text: rawLogs.value));
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(context.l10n.copied_to_clipboard("")),
),
);
}
},
),
],
),
body: SafeArea(
child: ListView.builder(
itemCount: logs.value.length,
itemBuilder: (context, index) {
final log = logs.value[index];
return Stack(
children: [
SectionCardWithHeading(
heading: log.date.toString(),
children: [
Padding(
padding: const EdgeInsets.all(12.0),
child: SelectableText(log.body),
),
],
),
Positioned(
right: 10,
top: 0,
child: IconButton(
icon: const Icon(SpotubeIcons.clipboard),
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

@ -406,6 +406,19 @@ class SettingsPage extends HookConsumerWidget {
), ),
], ],
), ),
SectionCardWithHeading(
heading: context.l10n.developers,
children: [
ListTile(
leading: const Icon(SpotubeIcons.logs),
title: Text(context.l10n.logs),
trailing: const Icon(SpotubeIcons.angleRight),
onTap: () {
GoRouter.of(context).push("/settings/logs");
},
)
],
),
SectionCardWithHeading( SectionCardWithHeading(
heading: context.l10n.about, heading: context.l10n.about,
children: [ children: [

View File

@ -1,58 +0,0 @@
import 'package:catcher/model/platform_type.dart';
import 'package:catcher/model/report.dart';
import 'package:catcher/model/report_handler.dart';
import 'package:flutter/material.dart';
import 'package:motion_toast/motion_toast.dart';
import 'package:spotube/collections/spotube_icons.dart';
import 'package:spotube/extensions/context.dart';
class CustomToastHandler extends ReportHandler {
CustomToastHandler();
@override
Future<bool> handle(Report error, BuildContext? context) async {
final theme = Theme.of(context!);
MotionToast(
primaryColor: theme.colorScheme.errorContainer,
icon: SpotubeIcons.error,
title: Text(
context.l10n.something_went_wrong,
style: theme.textTheme.bodyMedium?.copyWith(
fontWeight: FontWeight.bold,
color: theme.colorScheme.onError,
),
),
description: Text(
error.error.toString(),
style: theme.textTheme.bodyMedium?.copyWith(
color: theme.colorScheme.onError,
),
),
dismissable: true,
toastDuration: const Duration(seconds: 5),
borderRadius: 10,
).show(context);
return true;
}
@override
List<PlatformType> getSupportedPlatforms() => [
PlatformType.android,
PlatformType.iOS,
PlatformType.web,
PlatformType.linux,
PlatformType.macOS,
PlatformType.windows,
];
@override
bool isContextRequired() {
return true;
}
@override
bool shouldHandleWhenRejected() {
return false;
}
}

View File

@ -1134,14 +1134,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.4" version: "1.0.4"
motion_toast:
dependency: "direct main"
description:
name: motion_toast
sha256: f33fad8264d6d5359e41f2027d2d833614401c3983102e8f0aa13ccbbdcdeecd
url: "https://pub.dev"
source: hosted
version: "2.6.8"
mutex: mutex:
dependency: transitive dependency: transitive
description: description:

View File

@ -102,7 +102,6 @@ dependencies:
device_preview: ^1.1.0 device_preview: ^1.1.0
media_kit_native_event_loop: ^1.0.4 media_kit_native_event_loop: ^1.0.4
dbus: ^0.7.8 dbus: ^0.7.8
motion_toast: ^2.6.8
background_downloader: ^7.4.0 background_downloader: ^7.4.0
dev_dependencies: dev_dependencies: