Add debug mode

This commit is contained in:
problematicconsumer
2023-08-24 16:18:05 +03:30
parent 9ba970493f
commit 4563fc5584
8 changed files with 118 additions and 20 deletions

View File

@@ -78,7 +78,9 @@
"pageTitle": "logs", "pageTitle": "logs",
"clearLogsButtonText": "clear", "clearLogsButtonText": "clear",
"filterHint": "filter", "filterHint": "filter",
"allLevelsFilter": "all" "allLevelsFilter": "all",
"shareCoreLogs": "share core logs",
"shareAppLogs": "share app logs"
}, },
"settings": { "settings": {
"pageTitle": "settings", "pageTitle": "settings",
@@ -120,7 +122,9 @@
"miscellaneous": { "miscellaneous": {
"sectionTitle": "miscellaneous", "sectionTitle": "miscellaneous",
"connectionTestUrl": "connection test url", "connectionTestUrl": "connection test url",
"concurrentTestCount": "concurrent test count" "concurrentTestCount": "concurrent test count",
"debugMode": "debug mode",
"debugModeMsg": "restart the app for this to take effect"
} }
}, },
"about": { "about": {

View File

@@ -78,7 +78,9 @@
"pageTitle": "لاگ‌ها", "pageTitle": "لاگ‌ها",
"clearLogsButtonText": "پاک‌سازی", "clearLogsButtonText": "پاک‌سازی",
"filterHint": "فیلتر", "filterHint": "فیلتر",
"allLevelsFilter": "همه" "allLevelsFilter": "همه",
"shareCoreLogs": "اشتراک‌گذاری لاگ هسته",
"shareAppLogs": "اشتراک‌گذاری لاگ برنامه"
}, },
"settings": { "settings": {
"pageTitle": "تنظیمات", "pageTitle": "تنظیمات",
@@ -120,7 +122,9 @@
"miscellaneous": { "miscellaneous": {
"sectionTitle": "متفرقه", "sectionTitle": "متفرقه",
"connectionTestUrl": "لینک تست کانکشن", "connectionTestUrl": "لینک تست کانکشن",
"concurrentTestCount": "شمار تست همزمان" "concurrentTestCount": "شمار تست همزمان",
"debugMode": "دیباگ مود",
"debugModeMsg": "برای اعمال این تغییر اپ را ری‌استارت کنید"
} }
}, },
"about": { "about": {

View File

@@ -5,6 +5,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_native_splash/flutter_native_splash.dart'; import 'package:flutter_native_splash/flutter_native_splash.dart';
import 'package:hiddify/core/app/app.dart'; import 'package:hiddify/core/app/app.dart';
import 'package:hiddify/core/prefs/misc_prefs.dart';
import 'package:hiddify/core/prefs/prefs.dart'; import 'package:hiddify/core/prefs/prefs.dart';
import 'package:hiddify/data/data_providers.dart'; import 'package:hiddify/data/data_providers.dart';
import 'package:hiddify/features/common/active_profile/active_profile_notifier.dart'; import 'package:hiddify/features/common/active_profile/active_profile_notifier.dart';
@@ -41,10 +42,12 @@ Future<void> lazyBootstrap(WidgetsBinding widgetsBinding) async {
overrides: [sharedPreferencesProvider.overrideWithValue(sharedPreferences)], overrides: [sharedPreferencesProvider.overrideWithValue(sharedPreferences)],
); );
final debug = container.read(debugModeProvider) || kDebugMode;
final filesEditor = container.read(filesEditorServiceProvider); final filesEditor = container.read(filesEditorServiceProvider);
await filesEditor.init(); await filesEditor.init();
initLoggers(container.read); initLoggers(container.read, debug);
_loggy.info( _loggy.info(
"os: ${Platform.operatingSystem}(${Platform.operatingSystemVersion})", "os: ${Platform.operatingSystem}(${Platform.operatingSystemVersion})",
); );
@@ -76,9 +79,10 @@ Future<void> lazyBootstrap(WidgetsBinding widgetsBinding) async {
void initLoggers( void initLoggers(
Result Function<Result>(ProviderListenable<Result>) read, Result Function<Result>(ProviderListenable<Result>) read,
bool debug,
) { ) {
const logLevel = kDebugMode ? LogLevel.all : LogLevel.info; final logLevel = debug ? LogLevel.all : LogLevel.info;
final logToFile = !Platform.isAndroid && !Platform.isIOS; final logToFile = debug || (!Platform.isAndroid && !Platform.isIOS);
Loggy.initLoggy( Loggy.initLoggy(
logPrinter: MultiLogPrinter( logPrinter: MultiLogPrinter(
const PrettyPrinter(), const PrettyPrinter(),
@@ -86,8 +90,7 @@ void initLoggers(
? FileLogPrinter(read(filesEditorServiceProvider).appLogsPath) ? FileLogPrinter(read(filesEditorServiceProvider).appLogsPath)
: null, : null,
), ),
// ignore: avoid_redundant_argument_values logOptions: LogOptions(logLevel),
logOptions: const LogOptions(logLevel),
); );
} }

View File

@@ -8,3 +8,5 @@ final concurrentTestCountProvider = PrefNotifier.provider(
"concurrent_test_count", "concurrent_test_count",
Defaults.concurrentTestCount, Defaults.concurrentTestCount,
); );
final debugModeProvider = PrefNotifier.provider("debug_mode", false);

View File

@@ -98,7 +98,7 @@ class CoreFacadeImpl with ExceptionHandler, InfraLogger implements CoreFacade {
@override @override
Stream<Either<CoreServiceFailure, String>> watchLogs() { Stream<Either<CoreServiceFailure, String>> watchLogs() {
return singbox return singbox
.watchLogs(filesEditor.logsPath) .watchLogs(filesEditor.coreLogsPath)
.handleExceptions(CoreServiceFailure.unexpected); .handleExceptions(CoreServiceFailure.unexpected);
} }

View File

@@ -1,16 +1,22 @@
import 'dart:io';
import 'package:dartx/dartx.dart'; import 'package:dartx/dartx.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:fpdart/fpdart.dart'; import 'package:fpdart/fpdart.dart';
import 'package:gap/gap.dart'; import 'package:gap/gap.dart';
import 'package:hiddify/core/core_providers.dart'; import 'package:hiddify/core/core_providers.dart';
import 'package:hiddify/core/prefs/misc_prefs.dart';
import 'package:hiddify/domain/clash/clash.dart'; import 'package:hiddify/domain/clash/clash.dart';
import 'package:hiddify/domain/failures.dart'; import 'package:hiddify/domain/failures.dart';
import 'package:hiddify/features/common/common.dart'; import 'package:hiddify/features/common/common.dart';
import 'package:hiddify/features/logs/notifier/notifier.dart'; import 'package:hiddify/features/logs/notifier/notifier.dart';
import 'package:hiddify/services/service_providers.dart';
import 'package:hiddify/utils/utils.dart'; import 'package:hiddify/utils/utils.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:recase/recase.dart'; import 'package:recase/recase.dart';
import 'package:share_plus/share_plus.dart';
import 'package:tint/tint.dart'; import 'package:tint/tint.dart';
import 'package:url_launcher/url_launcher.dart';
class LogsPage extends HookConsumerWidget { class LogsPage extends HookConsumerWidget {
const LogsPage({super.key}); const LogsPage({super.key});
@@ -21,6 +27,45 @@ class LogsPage extends HookConsumerWidget {
final asyncState = ref.watch(logsNotifierProvider); final asyncState = ref.watch(logsNotifierProvider);
final notifier = ref.watch(logsNotifierProvider.notifier); final notifier = ref.watch(logsNotifierProvider.notifier);
final debug = ref.watch(debugModeProvider);
final List<PopupMenuEntry> popupButtons = debug || PlatformUtils.isDesktop
? [
PopupMenuItem(
child: Text(t.logs.shareCoreLogs.sentenceCase),
onTap: () async {
if (Platform.isWindows || Platform.isLinux) {
await launchUrl(
ref.read(filesEditorServiceProvider).logsDir.uri,
);
} else {
final file = XFile(
ref.read(filesEditorServiceProvider).coreLogsPath,
mimeType: "text/plain",
);
await Share.shareXFiles([file]);
}
},
),
PopupMenuItem(
child: Text(t.logs.shareAppLogs.sentenceCase),
onTap: () async {
if (Platform.isWindows || Platform.isLinux) {
await launchUrl(
ref.read(filesEditorServiceProvider).logsDir.uri,
);
} else {
final file = XFile(
ref.read(filesEditorServiceProvider).appLogsPath,
mimeType: "text/plain",
);
await Share.shareXFiles([file]);
}
},
),
]
: [];
switch (asyncState) { switch (asyncState) {
case AsyncData(value: final state): case AsyncData(value: final state):
return Scaffold( return Scaffold(
@@ -28,6 +73,14 @@ class LogsPage extends HookConsumerWidget {
// TODO: fix height // TODO: fix height
toolbarHeight: 90, toolbarHeight: 90,
title: Text(t.logs.pageTitle.titleCase), title: Text(t.logs.pageTitle.titleCase),
actions: [
if (popupButtons.isNotEmpty)
PopupMenuButton(
itemBuilder: (context) {
return popupButtons;
},
),
],
bottom: PreferredSize( bottom: PreferredSize(
preferredSize: const Size.fromHeight(36), preferredSize: const Size.fromHeight(36),
child: Padding( child: Padding(

View File

@@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:hiddify/core/core_providers.dart'; import 'package:hiddify/core/core_providers.dart';
import 'package:hiddify/core/prefs/misc_prefs.dart'; import 'package:hiddify/core/prefs/misc_prefs.dart';
import 'package:hiddify/domain/constants.dart'; import 'package:hiddify/domain/constants.dart';
@@ -16,6 +17,7 @@ class MiscellaneousSettingTiles extends HookConsumerWidget {
final connectionTestUrl = ref.watch(connectionTestUrlProvider); final connectionTestUrl = ref.watch(connectionTestUrlProvider);
final concurrentTestCount = ref.watch(concurrentTestCountProvider); final concurrentTestCount = ref.watch(concurrentTestCountProvider);
final debug = ref.watch(debugModeProvider);
return Column( return Column(
children: [ children: [
@@ -37,7 +39,7 @@ class MiscellaneousSettingTiles extends HookConsumerWidget {
subtitle: Text(concurrentTestCount.toString()), subtitle: Text(concurrentTestCount.toString()),
onTap: () async { onTap: () async {
final val = await SettingsInputDialog<int>( final val = await SettingsInputDialog<int>(
title: t.settings.miscellaneous.connectionTestUrl.titleCase, title: t.settings.miscellaneous.concurrentTestCount.titleCase,
initialValue: concurrentTestCount, initialValue: concurrentTestCount,
resetValue: Defaults.concurrentTestCount, resetValue: Defaults.concurrentTestCount,
mapTo: (value) => int.tryParse(value), mapTo: (value) => int.tryParse(value),
@@ -47,6 +49,34 @@ class MiscellaneousSettingTiles extends HookConsumerWidget {
await ref.read(concurrentTestCountProvider.notifier).update(val); await ref.read(concurrentTestCountProvider.notifier).update(val);
}, },
), ),
SwitchListTile(
title: Text(t.settings.miscellaneous.debugMode.titleCase),
value: debug,
onChanged: (value) async {
if (value) {
await showDialog<bool>(
context: context,
builder: (context) {
return AlertDialog(
title: Text(t.settings.miscellaneous.debugMode.titleCase),
content: Text(
t.settings.miscellaneous.debugModeMsg.sentenceCase,
),
actions: [
TextButton(
onPressed: () => context.pop(true),
child: Text(
MaterialLocalizations.of(context).okButtonLabel,
),
),
],
);
},
);
}
await ref.read(debugModeProvider.notifier).update(value);
},
),
], ],
); );
} }

View File

@@ -11,6 +11,7 @@ class FilesEditorService with InfraLogger {
late final Directory baseDir; late final Directory baseDir;
late final Directory workingDir; late final Directory workingDir;
late final Directory tempDir; late final Directory tempDir;
late final Directory logsDir;
late final Directory _configsDir; late final Directory _configsDir;
Future<void> init() async { Future<void> init() async {
@@ -24,10 +25,12 @@ class FilesEditorService with InfraLogger {
workingDir = await getApplicationDocumentsDirectory(); workingDir = await getApplicationDocumentsDirectory();
} }
tempDir = await getTemporaryDirectory(); tempDir = await getTemporaryDirectory();
logsDir = workingDir;
loggy.debug("base dir: ${baseDir.path}"); loggy.debug("base dir: ${baseDir.path}");
loggy.debug("working dir: ${workingDir.path}"); loggy.debug("working dir: ${workingDir.path}");
loggy.debug("temp dir: ${tempDir.path}"); loggy.debug("temp dir: ${tempDir.path}");
loggy.debug("logs dire: ${logsDir.path}");
_configsDir = _configsDir =
Directory(p.join(workingDir.path, Constants.configsFolderName)); Directory(p.join(workingDir.path, Constants.configsFolderName));
@@ -49,13 +52,12 @@ class FilesEditorService with InfraLogger {
} }
await _populateGeoAssets(); await _populateGeoAssets();
if (PlatformUtils.isDesktop) {
final logFile = File(logsPath); final coreLogFile = File(coreLogsPath);
if (await logFile.exists()) { if (await coreLogFile.exists()) {
await logFile.writeAsString(""); await coreLogFile.writeAsString("");
} else { } else {
await logFile.create(recursive: true); await coreLogFile.create(recursive: true);
}
} }
} }
@@ -68,8 +70,8 @@ class FilesEditorService with InfraLogger {
return getApplicationDocumentsDirectory(); return getApplicationDocumentsDirectory();
} }
String get appLogsPath => p.join(workingDir.path, "app.log"); String get appLogsPath => p.join(logsDir.path, "app.log");
String get logsPath => p.join(workingDir.path, "box.log"); String get coreLogsPath => p.join(logsDir.path, "box.log");
String configPath(String fileName) { String configPath(String fileName) {
return p.join(_configsDir.path, "$fileName.json"); return p.join(_configsDir.path, "$fileName.json");