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:
parent
1b3440e2fe
commit
60d051ee7b
2 changed files with 61 additions and 27 deletions
|
|
@ -11,8 +11,9 @@ import io.flutter.embedding.engine.plugins.FlutterPlugin
|
||||||
import io.flutter.plugin.common.EventChannel
|
import io.flutter.plugin.common.EventChannel
|
||||||
import io.flutter.plugin.common.MethodCall
|
import io.flutter.plugin.common.MethodCall
|
||||||
import io.flutter.plugin.common.MethodChannel
|
import io.flutter.plugin.common.MethodChannel
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class BridgeModule : FlutterPlugin, MethodChannel.MethodCallHandler {
|
class BridgeModule : FlutterPlugin, MethodChannel.MethodCallHandler {
|
||||||
|
|
||||||
|
|
@ -174,30 +175,28 @@ class BridgeModule : FlutterPlugin, MethodChannel.MethodCallHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fetchLogs(limit: Int, result: MethodChannel.Result) {
|
private fun fetchLogs(limit: Int, result: MethodChannel.Result) {
|
||||||
Thread {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
try {
|
try {
|
||||||
val logs = runBlocking(Dispatchers.IO) {
|
val db = context?.let { AppDatabase.getInstance(it) }
|
||||||
val db = context?.let { AppDatabase.getInstance(it) }
|
val logs = if (db != null) {
|
||||||
if (db != null) {
|
val events = db.eventLogDao().getRecentEventsList(limit)
|
||||||
val events = db.eventLogDao().getRecentEventsList(limit)
|
events.map { event ->
|
||||||
events.map { event ->
|
mapOf(
|
||||||
mapOf(
|
"id" to event.id,
|
||||||
"id" to event.id,
|
"timestamp" to event.timestamp,
|
||||||
"timestamp" to event.timestamp,
|
"eventType" to event.eventType,
|
||||||
"eventType" to event.eventType,
|
"message" to event.message
|
||||||
"message" to event.message
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
emptyList()
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
emptyList()
|
||||||
}
|
}
|
||||||
mainHandler.post { result.success(logs) }
|
mainHandler.post { result.success(logs) }
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(TAG, "fetchLogs failed", e)
|
Log.e(TAG, "fetchLogs failed", e)
|
||||||
mainHandler.post { result.success(emptyList<Map<String, Any>>()) }
|
mainHandler.post { result.success(emptyList<Map<String, Any>>()) }
|
||||||
}
|
}
|
||||||
}.start()
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun openBatteryOptimizationSettings(result: MethodChannel.Result) {
|
private fun openBatteryOptimizationSettings(result: MethodChannel.Result) {
|
||||||
|
|
@ -234,21 +233,17 @@ class BridgeModule : FlutterPlugin, MethodChannel.MethodCallHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun clearLogs(result: MethodChannel.Result) {
|
private fun clearLogs(result: MethodChannel.Result) {
|
||||||
Thread {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
try {
|
try {
|
||||||
val deleted = runBlocking(Dispatchers.IO) {
|
val db = context?.let { AppDatabase.getInstance(it) }
|
||||||
val db = context?.let { AppDatabase.getInstance(it) }
|
if (db != null) {
|
||||||
if (db != null) {
|
db.eventLogDao().deleteAll()
|
||||||
db.eventLogDao().deleteAll()
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
mainHandler.post { result.success(deleted) }
|
mainHandler.post { result.success(0) }
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(TAG, "clearLogs failed", e)
|
Log.e(TAG, "clearLogs failed", e)
|
||||||
mainHandler.post { result.success(-1) }
|
mainHandler.post { result.success(-1) }
|
||||||
}
|
}
|
||||||
}.start()
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -48,6 +48,45 @@ class _StatusScreenState extends State<StatusScreen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _clearLogs() async {
|
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();
|
final result = await LocationBridge.clearLogs();
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
if (result >= 0) {
|
if (result >= 0) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue