From d8ea0b8aa6c540722607ce68d1e8a5a134995413 Mon Sep 17 00:00:00 2001
From: lollipopkit <10864310+lollipopkit@users.noreply.github.com>
Date: Sun, 15 Dec 2024 23:30:50 +0800
Subject: [PATCH 1/2] opt.: display err if home widget fails Fixes #614
---
android/app/build.gradle | 2 +
android/app/src/main/AndroidManifest.xml | 2 +-
.../kotlin/tech/lolli/toolbox/MainActivity.kt | 10 +-
.../tech/lolli/toolbox/widget/HomeWidget.kt | 91 +++----
.../app/src/main/res/layout/home_widget.xml | 228 ++++++++++--------
android/app/src/main/res/values/strings.xml | 4 +
lib/core/{channel/bg_run.dart => chan.dart} | 10 +-
lib/core/channel/home_widget.dart | 12 -
lib/view/page/home/home.dart | 6 +-
lib/view/page/setting/seq/srv_seq.dart | 8 +-
lib/view/page/ssh/page.dart | 6 +-
pubspec.lock | 4 +-
pubspec.yaml | 2 +-
13 files changed, 211 insertions(+), 174 deletions(-)
create mode 100644 android/app/src/main/res/values/strings.xml
rename lib/core/{channel/bg_run.dart => chan.dart} (57%)
delete mode 100644 lib/core/channel/home_widget.dart
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 27376a3f3..91fc5add8 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -86,10 +86,12 @@ android {
debug {
applicationIdSuffix '.debug'
+ resValue "string", "app_name", "SrvBxD"
}
profile {
applicationIdSuffix '.debug'
+ resValue "string", "app_name", "SrvBxP"
}
}
}
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index bd4fe308e..f4938dc5e 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -11,7 +11,7 @@
when (method.method) {
"sendToBackground" -> {
@@ -36,6 +38,12 @@ class MainActivity: FlutterFragmentActivity() {
stopService(serviceIntent)
result.success(null)
}
+ "updateHomeWidget" -> {
+ val intent = Intent(this@MainActivity, HomeWidget::class.java)
+ intent.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
+ sendBroadcast(intent)
+ result.success(null)
+ }
else -> {
result.notImplemented()
}
diff --git a/android/app/src/main/kotlin/tech/lolli/toolbox/widget/HomeWidget.kt b/android/app/src/main/kotlin/tech/lolli/toolbox/widget/HomeWidget.kt
index 4f425ada7..f233b8bdb 100644
--- a/android/app/src/main/kotlin/tech/lolli/toolbox/widget/HomeWidget.kt
+++ b/android/app/src/main/kotlin/tech/lolli/toolbox/widget/HomeWidget.kt
@@ -6,15 +6,18 @@ import android.appwidget.AppWidgetProvider
import android.content.Context
import android.content.Intent
import android.os.Build
+import android.util.Log
import android.view.View
import android.widget.RemoteViews
-import kotlinx.coroutines.DelicateCoroutinesApi
+import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
import org.json.JSONObject
import tech.lolli.toolbox.R
import java.net.URL
+import java.net.HttpURLConnection
+import java.io.FileNotFoundException
class HomeWidget : AppWidgetProvider() {
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
@@ -23,7 +26,6 @@ class HomeWidget : AppWidgetProvider() {
}
}
- @OptIn(DelicateCoroutinesApi::class)
private fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int) {
val views = RemoteViews(context.packageName, R.layout.home_widget)
val sp = context.getSharedPreferences("FlutterSharedPreferences", Context.MODE_PRIVATE)
@@ -36,6 +38,10 @@ class HomeWidget : AppWidgetProvider() {
url = gUrl
}
+ if (url.isNullOrEmpty()) {
+ Log.e("HomeWidget", "未找到 URL")
+ }
+
val intentUpdate = Intent(context, HomeWidget::class.java)
intentUpdate.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
val ids = intArrayOf(appWidgetId)
@@ -54,11 +60,11 @@ class HomeWidget : AppWidgetProvider() {
views.setOnClickPendingIntent(R.id.widget_container, pendingUpdate)
if (url.isNullOrEmpty()) {
- views.setViewVisibility(R.id.widget_cpu_label, View.INVISIBLE)
- views.setViewVisibility(R.id.widget_mem_label, View.INVISIBLE)
- views.setViewVisibility(R.id.widget_disk_label, View.INVISIBLE)
- views.setViewVisibility(R.id.widget_net_label, View.INVISIBLE)
- views.setTextViewText(R.id.widget_name, "ID: $appWidgetId")
+ views.setTextViewText(R.id.widget_name, "No URL")
+ // Update the widget to display a message for missing URL
+ views.setViewVisibility(R.id.error_message, View.VISIBLE)
+ views.setTextViewText(R.id.error_message, "Please configure the widget URL.")
+ views.setViewVisibility(R.id.widget_content, View.GONE)
appWidgetManager.updateAppWidget(appWidgetId, views)
return
} else {
@@ -68,44 +74,45 @@ class HomeWidget : AppWidgetProvider() {
views.setViewVisibility(R.id.widget_net_label, View.VISIBLE)
}
- GlobalScope.launch(Dispatchers.IO) {
+ CoroutineScope(Dispatchers.IO).launch {
try {
- val jsonStr = URL(url).readText()
- val jsonObject = JSONObject(jsonStr)
- val data = jsonObject.getJSONObject("data")
- val server = data.getString("name")
- val cpu = data.getString("cpu")
- val mem = data.getString("mem")
- val disk = data.getString("disk")
- val net = data.getString("net")
-
- GlobalScope.launch(Dispatchers.Main) main@ {
- // mem or disk is empty -> get status failed
- // (cpu | net) isEmpty -> data is not ready
- if (mem.isEmpty() || disk.isEmpty()) {
- return@main
+ val connection = URL(url).openConnection() as HttpURLConnection
+ connection.requestMethod = "GET"
+ val responseCode = connection.responseCode
+ if (responseCode == HttpURLConnection.HTTP_OK) {
+ val jsonStr = connection.inputStream.bufferedReader().use { it.readText() }
+ val jsonObject = JSONObject(jsonStr)
+ val data = jsonObject.getJSONObject("data")
+ val server = data.getString("name")
+ val cpu = data.getString("cpu")
+ val mem = data.getString("mem")
+ val disk = data.getString("disk")
+ val net = data.getString("net")
+ withContext(Dispatchers.Main) {
+ if (mem.isEmpty() || disk.isEmpty()) {
+ Log.e("HomeWidget", "获取状态失败:内存或磁盘信息为空")
+ return@withContext
+ }
+ views.setTextViewText(R.id.widget_name, server)
+ views.setTextViewText(R.id.widget_cpu, cpu)
+ views.setTextViewText(R.id.widget_mem, mem)
+ views.setTextViewText(R.id.widget_disk, disk)
+ views.setTextViewText(R.id.widget_net, net)
+ val timeStr = android.text.format.DateFormat.format("HH:mm", java.util.Date()).toString()
+ views.setTextViewText(R.id.widget_time, timeStr)
+ appWidgetManager.updateAppWidget(appWidgetId, views)
}
- views.setTextViewText(R.id.widget_name, server)
-
- views.setTextViewText(R.id.widget_cpu, cpu)
- views.setTextViewText(R.id.widget_mem, mem)
- views.setTextViewText(R.id.widget_disk, disk)
- views.setTextViewText(R.id.widget_net, net)
-
- val timeStr = android.text.format.DateFormat.format("HH:mm", java.util.Date()).toString()
- views.setTextViewText(R.id.widget_time, timeStr)
-
- appWidgetManager.updateAppWidget(appWidgetId, views)
+ } else {
+ throw FileNotFoundException("HTTP response code: $responseCode")
}
} catch (e: Exception) {
- println("ServerBoxHomeWidget: ${e.localizedMessage}")
- GlobalScope.launch(Dispatchers.Main) main@ {
- views.setViewVisibility(R.id.widget_cpu_label, View.INVISIBLE)
- views.setViewVisibility(R.id.widget_mem_label, View.INVISIBLE)
- views.setViewVisibility(R.id.widget_disk_label, View.INVISIBLE)
- views.setViewVisibility(R.id.widget_net_label, View.INVISIBLE)
- views.setTextViewText(R.id.widget_name, "ID: $appWidgetId")
- views.setTextViewText(R.id.widget_mem, e.localizedMessage)
+ Log.e("HomeWidget", "更新小部件时出错:${e.localizedMessage}", e)
+ withContext(Dispatchers.Main) {
+ views.setTextViewText(R.id.widget_name, "Error")
+ // Update the widget to display a message for data retrieval failure
+ views.setViewVisibility(R.id.error_message, View.VISIBLE)
+ views.setTextViewText(R.id.error_message, "Failed to retrieve data.")
+ views.setViewVisibility(R.id.widget_content, View.GONE)
appWidgetManager.updateAppWidget(appWidgetId, views)
}
}
diff --git a/android/app/src/main/res/layout/home_widget.xml b/android/app/src/main/res/layout/home_widget.xml
index 0d04ca951..615a320e4 100644
--- a/android/app/src/main/res/layout/home_widget.xml
+++ b/android/app/src/main/res/layout/home_widget.xml
@@ -18,122 +18,144 @@
android:maxLines="1"
tools:text="Server Name" />
-
+
-
-
-
-
+ android:paddingTop="13dp">
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+ android:paddingBottom="2.7dp"
+ android:layout_below="@id/widget_cpu_label"
+ android:gravity="center_vertical"
+ android:orientation="horizontal">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
+
-
-
+
-
+
-
+
-
+
+
+
+ ServerBox
+
\ No newline at end of file
diff --git a/lib/core/channel/bg_run.dart b/lib/core/chan.dart
similarity index 57%
rename from lib/core/channel/bg_run.dart
rename to lib/core/chan.dart
index e020b93b8..d55e4aca0 100644
--- a/lib/core/channel/bg_run.dart
+++ b/lib/core/chan.dart
@@ -1,14 +1,15 @@
import 'package:flutter/services.dart';
import 'package:server_box/data/res/misc.dart';
-abstract final class BgRunMC {
- static const _channel = MethodChannel('${Miscs.pkgName}/app_retain');
+abstract final class MethodChans {
+ static const _channel = MethodChannel('${Miscs.pkgName}/main_chan');
static void moveToBg() {
_channel.invokeMethod('sendToBackground');
}
/// TODO: try fix the fn, then uncomment it and [stopService]
+ /// Issues #639
static void startService() {
// _channel.invokeMethod('startService');
}
@@ -16,4 +17,9 @@ abstract final class BgRunMC {
static void stopService() {
// _channel.invokeMethod('stopService');
}
+
+ static void updateHomeWidget() async {
+ //if (!Stores.setting.autoUpdateHomeWidget.fetch()) return;
+ await _channel.invokeMethod('updateHomeWidget');
+ }
}
diff --git a/lib/core/channel/home_widget.dart b/lib/core/channel/home_widget.dart
deleted file mode 100644
index 5ac0828f6..000000000
--- a/lib/core/channel/home_widget.dart
+++ /dev/null
@@ -1,12 +0,0 @@
-import 'package:flutter/services.dart';
-import 'package:server_box/data/res/misc.dart';
-import 'package:server_box/data/res/store.dart';
-
-abstract final class HomeWidgetMC {
- static const _channel = MethodChannel('${Miscs.pkgName}/home_widget');
-
- static void update() {
- if (!Stores.setting.autoUpdateHomeWidget.fetch()) return;
- _channel.invokeMethod('update');
- }
-}
diff --git a/lib/view/page/home/home.dart b/lib/view/page/home/home.dart
index e74b2ccd7..e006d11c8 100644
--- a/lib/view/page/home/home.dart
+++ b/lib/view/page/home/home.dart
@@ -1,6 +1,6 @@
import 'package:fl_lib/fl_lib.dart';
import 'package:flutter/material.dart';
-import 'package:server_box/core/channel/home_widget.dart';
+import 'package:server_box/core/chan.dart';
import 'package:server_box/data/model/app/tab.dart';
import 'package:server_box/data/provider/app.dart';
import 'package:server_box/data/provider/server.dart';
@@ -76,7 +76,7 @@ class _HomePageState extends State
if (!ServerProvider.isAutoRefreshOn) {
ServerProvider.startAutoRefresh();
}
- HomeWidgetMC.update();
+ MethodChans.updateHomeWidget();
break;
case AppLifecycleState.paused:
_shouldAuth = true;
@@ -172,7 +172,7 @@ class _HomePageState extends State
context: context,
);
}
- HomeWidgetMC.update();
+ MethodChans.updateHomeWidget();
await ServerProvider.refresh();
}
diff --git a/lib/view/page/setting/seq/srv_seq.dart b/lib/view/page/setting/seq/srv_seq.dart
index b7a393dec..d74970ba4 100644
--- a/lib/view/page/setting/seq/srv_seq.dart
+++ b/lib/view/page/setting/seq/srv_seq.dart
@@ -45,20 +45,20 @@ class _ServerOrderPageState extends State {
}
Widget _buildBody() {
- final orderNode = ServerProvider.serverOrder;
- return orderNode.listenVal((order) {
+ final orders = ServerProvider.serverOrder;
+ return orders.listenVal((order) {
if (order.isEmpty) {
return Center(child: Text(libL10n.empty));
}
return ReorderableListView.builder(
footer: const SizedBox(height: 77),
onReorder: (oldIndex, newIndex) => setState(() {
- orderNode.value.move(
+ orders.value.move(
oldIndex,
newIndex,
property: Stores.setting.serverOrder,
);
- orderNode.notify();
+ orders.notify();
}),
padding: const EdgeInsets.symmetric(horizontal: 7, vertical: 3),
buildDefaultDragHandles: false,
diff --git a/lib/view/page/ssh/page.dart b/lib/view/page/ssh/page.dart
index 01e16bd67..cc485fc9c 100644
--- a/lib/view/page/ssh/page.dart
+++ b/lib/view/page/ssh/page.dart
@@ -6,7 +6,7 @@ import 'package:fl_lib/fl_lib.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
-import 'package:server_box/core/channel/bg_run.dart';
+import 'package:server_box/core/chan.dart';
import 'package:server_box/core/extension/context/locale.dart';
import 'package:server_box/core/utils/ssh_auth.dart';
import 'package:server_box/core/utils/server.dart';
@@ -84,7 +84,7 @@ class SSHPageState extends State
if (--_sshConnCount <= 0) {
WakelockPlus.disable();
if (isAndroid) {
- BgRunMC.stopService();
+ MethodChans.stopService();
}
}
}
@@ -99,7 +99,7 @@ class SSHPageState extends State
if (++_sshConnCount == 1) {
WakelockPlus.enable();
if (isAndroid) {
- BgRunMC.startService();
+ MethodChans.startService();
}
}
}
diff --git a/pubspec.lock b/pubspec.lock
index b7f4873bb..c0fd7c8de 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -478,8 +478,8 @@ packages:
dependency: "direct main"
description:
path: "."
- ref: "v1.0.224"
- resolved-ref: ce532383b50fd3bfe74017a2799510c014b0f4f4
+ ref: "v1.0.225"
+ resolved-ref: "9ca92213fea15b8c245ed2cc2958e14baea5cdbe"
url: "https://github.com/lppcg/fl_lib"
source: git
version: "0.0.1"
diff --git a/pubspec.yaml b/pubspec.yaml
index 0c7193de5..347afb6be 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -63,7 +63,7 @@ dependencies:
fl_lib:
git:
url: https://github.com/lppcg/fl_lib
- ref: v1.0.224
+ ref: v1.0.225
dependency_overrides:
# dartssh2:
From d37ebe0ee91bc67de0c5f23bdb854ac15028fc44 Mon Sep 17 00:00:00 2001
From: lollipopkit <10864310+lollipopkit@users.noreply.github.com>
Date: Sun, 15 Dec 2024 23:33:04 +0800
Subject: [PATCH 2/2] chore: en log
---
.../src/main/kotlin/tech/lolli/toolbox/widget/HomeWidget.kt | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/android/app/src/main/kotlin/tech/lolli/toolbox/widget/HomeWidget.kt b/android/app/src/main/kotlin/tech/lolli/toolbox/widget/HomeWidget.kt
index f233b8bdb..59c57e10f 100644
--- a/android/app/src/main/kotlin/tech/lolli/toolbox/widget/HomeWidget.kt
+++ b/android/app/src/main/kotlin/tech/lolli/toolbox/widget/HomeWidget.kt
@@ -39,7 +39,7 @@ class HomeWidget : AppWidgetProvider() {
}
if (url.isNullOrEmpty()) {
- Log.e("HomeWidget", "未找到 URL")
+ Log.e("HomeWidget", "URL not found")
}
val intentUpdate = Intent(context, HomeWidget::class.java)
@@ -90,7 +90,7 @@ class HomeWidget : AppWidgetProvider() {
val net = data.getString("net")
withContext(Dispatchers.Main) {
if (mem.isEmpty() || disk.isEmpty()) {
- Log.e("HomeWidget", "获取状态失败:内存或磁盘信息为空")
+ Log.e("HomeWidget", "Failed to retrieve status: Memory or disk information is empty")
return@withContext
}
views.setTextViewText(R.id.widget_name, server)
@@ -106,7 +106,7 @@ class HomeWidget : AppWidgetProvider() {
throw FileNotFoundException("HTTP response code: $responseCode")
}
} catch (e: Exception) {
- Log.e("HomeWidget", "更新小部件时出错:${e.localizedMessage}", e)
+ Log.e("HomeWidget", "Error updating widget: ${e.localizedMessage}", e)
withContext(Dispatchers.Main) {
views.setTextViewText(R.id.widget_name, "Error")
// Update the widget to display a message for data retrieval failure