Logging framework

This commit is contained in:
2025-02-27 22:58:31 +08:00
parent 1b41c847a6
commit 32bf834108
11 changed files with 173 additions and 15 deletions

3
lib/logger.dart Normal file
View File

@ -0,0 +1,3 @@
import 'package:talker/talker.dart';
final logging = Talker();

View File

@ -20,6 +20,7 @@ import 'package:relative_time/relative_time.dart';
import 'package:responsive_framework/responsive_framework.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:surface/firebase_options.dart';
import 'package:surface/logger.dart';
import 'package:surface/providers/channel.dart';
import 'package:surface/providers/chat_call.dart';
import 'package:surface/providers/config.dart';
@ -235,7 +236,7 @@ class _AppSplashScreenState extends State<_AppSplashScreen> with TrayListener {
await inAppReview.requestReview();
prefs.setBool('rating_requested', true);
} else {
log('Unable request app review, unavailable');
logging.error('Unable request app review, unavailable');
}
}
} else {
@ -263,17 +264,18 @@ class _AppSplashScreenState extends State<_AppSplashScreen> with TrayListener {
int.tryParse(remoteVersionString.split('+').last) ?? 0;
final localBuildNumber =
int.tryParse(localVersionString.split('+').last) ?? 0;
log("[Update] Local: $localVersionString, Remote: $remoteVersionString");
logging.info(
"[Update] Local: $localVersionString, Remote: $remoteVersionString");
if ((remoteVersion > localVersion ||
remoteBuildNumber > localBuildNumber) &&
mounted) {
final config = context.read<ConfigProvider>();
config.setUpdate(
remoteVersionString, resp.data?['body'] ?? 'No changelog');
log("[Update] Update available: $remoteVersionString");
logging.info("[Update] Update available: $remoteVersionString");
}
} catch (e) {
log('[Error] Unable to check update: $e');
logging.error('[Error] Unable to check update...', e);
if (mounted) context.showErrorDialog('Unable to check update: $e');
}
}
@ -306,7 +308,7 @@ class _AppSplashScreenState extends State<_AppSplashScreen> with TrayListener {
if (!mounted) return;
final sticker = context.read<SnStickerProvider>();
await sticker.listSticker();
log('[Bootstrap] Everything initialized!');
logging.info('[Bootstrap] Everything initialized!');
} catch (err) {
if (!mounted) return;
await context.showErrorDialog(err);

View File

@ -21,6 +21,7 @@ import 'package:surface/screens/chat/room.dart';
import 'package:surface/screens/explore.dart';
import 'package:surface/screens/friend.dart';
import 'package:surface/screens/home.dart';
import 'package:surface/screens/logging.dart';
import 'package:surface/screens/news/news_detail.dart';
import 'package:surface/screens/news/news_list.dart';
import 'package:surface/screens/notification.dart';
@ -249,6 +250,11 @@ final _appRoutes = [
),
],
),
GoRoute(
path: '/debug/logging',
name: 'debugLogging',
builder: (context, state) => const DebugLoggingScreen(),
),
GoRoute(
path: '/album',
name: 'album',

82
lib/screens/logging.dart Normal file
View File

@ -0,0 +1,82 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:material_symbols_icons/symbols.dart';
import 'package:styled_widget/styled_widget.dart';
import 'package:surface/logger.dart';
import 'package:surface/widgets/navigation/app_scaffold.dart';
import 'package:talker/talker.dart';
final Map<LogLevel, IconData> kLogLevelIcons = {
LogLevel.error: Symbols.error,
LogLevel.critical: Symbols.error,
LogLevel.warning: Symbols.warning,
LogLevel.info: Symbols.info,
LogLevel.debug: Symbols.info_i,
LogLevel.verbose: Symbols.info_i,
};
final Map<LogLevel, Color> kLogLevelColors = {
LogLevel.error: Colors.red,
LogLevel.critical: Colors.red,
LogLevel.warning: Colors.orange,
LogLevel.info: Colors.blue,
LogLevel.debug: Colors.green,
LogLevel.verbose: Colors.green,
};
final Map<LogLevel, bool> kLogLevelFilled = {
LogLevel.error: false,
LogLevel.critical: true,
LogLevel.warning: true,
LogLevel.info: true,
LogLevel.debug: false,
LogLevel.verbose: false,
};
class DebugLoggingScreen extends StatelessWidget {
const DebugLoggingScreen({super.key});
@override
Widget build(BuildContext context) {
return AppScaffold(
appBar: AppBar(
leading: const PageBackButton(),
title: Text('debugLogging').tr(),
),
body: SelectionArea(
child: ListView.builder(
padding: EdgeInsets.zero,
itemCount: logging.history.length,
itemBuilder: (context, index) {
final log = logging.history[index];
return ListTile(
leading: Icon(
kLogLevelIcons[log.logLevel ?? LogLevel.debug] ?? Symbols.help,
color: kLogLevelColors[log.logLevel ?? LogLevel.debug],
fill: (kLogLevelFilled[log.logLevel ?? LogLevel.debug] ?? false)
? 1
: 0,
),
title: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
log.message ?? 'unknown'.tr(),
style: GoogleFonts.robotoMono(fontSize: 13),
),
if (log.error != null)
Text(
log.error!.toString(),
style: GoogleFonts.robotoMono(fontSize: 13),
).bold(),
],
),
subtitle: Text(log.time.toString()).fontSize(11),
);
},
),
),
);
}
}

View File

@ -664,6 +664,16 @@ class _SettingsScreenState extends State<SettingsScreen> {
);
},
),
ListTile(
title: Text('runtimeLogsOpen').tr(),
subtitle: Text('runtimeLogsDescription').tr(),
contentPadding: const EdgeInsets.symmetric(horizontal: 24),
leading: const Icon(Symbols.receipt_long),
trailing: const Icon(Symbols.chevron_right),
onTap: () async {
GoRouter.of(context).pushNamed('debugLogging');
},
),
ListTile(
title: Text('settingsMiscAbout').tr(),
subtitle: Text('settingsMiscAboutDescription').tr(),