feat: add clear logs with confirmation dialog and fix DB dispatchers

- Add clearLogs method to BridgeModule with proper coroutine scope
- Fix fetchLogs and clearLogs using Thread+runBlocking which caused app close
- Change serviceScope from Dispatchers.Main to Dispatchers.IO
- Add error logging in fetchLogs for better diagnostics
- Add clear logs button with confirmation dialog in StatusScreen
This commit is contained in:
fiatcode 2026-05-04 08:38:25 +07:00
parent 1b3440e2fe
commit 60d051ee7b
No known key found for this signature in database
2 changed files with 61 additions and 27 deletions

View file

@ -11,8 +11,9 @@ import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.EventChannel
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class BridgeModule : FlutterPlugin, MethodChannel.MethodCallHandler {
@ -174,11 +175,10 @@ class BridgeModule : FlutterPlugin, MethodChannel.MethodCallHandler {
}
private fun fetchLogs(limit: Int, result: MethodChannel.Result) {
Thread {
CoroutineScope(Dispatchers.IO).launch {
try {
val logs = runBlocking(Dispatchers.IO) {
val db = context?.let { AppDatabase.getInstance(it) }
if (db != null) {
val logs = if (db != null) {
val events = db.eventLogDao().getRecentEventsList(limit)
events.map { event ->
mapOf(
@ -191,13 +191,12 @@ class BridgeModule : FlutterPlugin, MethodChannel.MethodCallHandler {
} else {
emptyList()
}
}
mainHandler.post { result.success(logs) }
} catch (e: Exception) {
Log.e(TAG, "fetchLogs failed", e)
mainHandler.post { result.success(emptyList<Map<String, Any>>()) }
}
}.start()
}
}
private fun openBatteryOptimizationSettings(result: MethodChannel.Result) {
@ -234,21 +233,17 @@ class BridgeModule : FlutterPlugin, MethodChannel.MethodCallHandler {
}
private fun clearLogs(result: MethodChannel.Result) {
Thread {
CoroutineScope(Dispatchers.IO).launch {
try {
val deleted = runBlocking(Dispatchers.IO) {
val db = context?.let { AppDatabase.getInstance(it) }
if (db != null) {
db.eventLogDao().deleteAll()
} else {
0
}
}
mainHandler.post { result.success(deleted) }
mainHandler.post { result.success(0) }
} catch (e: Exception) {
Log.e(TAG, "clearLogs failed", e)
mainHandler.post { result.success(-1) }
}
}.start()
}
}
}

View file

@ -48,6 +48,45 @@ class _StatusScreenState extends State<StatusScreen> {
}
Future<void> _clearLogs() async {
final confirmed = await showDialog<bool>(
context: context,
builder: (ctx) => AlertDialog(
backgroundColor: const Color(0xFF1e1e1e),
title: const Text(
'Clear Event Logs',
style: TextStyle(fontFamily: 'monospace', color: Color(0xFFe0e0e0)),
),
content: const Text(
'This will permanently delete all logged events. Continue?',
style: TextStyle(fontFamily: 'monospace', color: Color(0xFF9e9e9e)),
),
actions: [
TextButton(
onPressed: () => Navigator.pop(ctx, false),
child: const Text(
'CANCEL',
style: TextStyle(
fontFamily: 'monospace',
color: Color(0xFF616161),
),
),
),
TextButton(
onPressed: () => Navigator.pop(ctx, true),
child: const Text(
'CLEAR',
style: TextStyle(
fontFamily: 'monospace',
color: Color(0xFFff5252),
),
),
),
],
),
);
if (confirmed != true) return;
final result = await LocationBridge.clearLogs();
if (mounted) {
if (result >= 0) {