diff --git a/.gitignore b/.gitignore
index d91df7a..96d1b1f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,12 +1,7 @@
*.iml
.gradle
/local.properties
-/.idea/caches
-/.idea/libraries
-/.idea/modules.xml
-/.idea/workspace.xml
-/.idea/navEditor.xml
-/.idea/assetWizardSettings.xml
+/.idea/
.DS_Store
/build
/captures
diff --git a/.idea/AndroidProjectSystem.xml b/.idea/AndroidProjectSystem.xml
deleted file mode 100644
index d58d49b..0000000
--- a/.idea/AndroidProjectSystem.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/TaiwanStar_general_size_s_Chengwai.iml b/.idea/TaiwanStar_general_size_s_Chengwai.iml
deleted file mode 100644
index 18ec59d..0000000
--- a/.idea/TaiwanStar_general_size_s_Chengwai.iml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
deleted file mode 100644
index 1042843..0000000
--- a/.idea/gradle.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/markdown.xml b/.idea/markdown.xml
deleted file mode 100644
index b1f3d01..0000000
--- a/.idea/markdown.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
deleted file mode 100644
index a94cba3..0000000
--- a/.idea/misc.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100644
index 39c01ca..0000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml
deleted file mode 100644
index 5bd6771..0000000
--- a/.idea/runConfigurations.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..c5f3f6b
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+ "java.configuration.updateBuildConfiguration": "interactive"
+}
\ No newline at end of file
diff --git a/.idea/.gitignore b/app/src/main/java/com/unibuy/smartdevice/.idea/.gitignore
similarity index 100%
rename from .idea/.gitignore
rename to app/src/main/java/com/unibuy/smartdevice/.idea/.gitignore
diff --git a/.idea/caches/deviceStreaming.xml b/app/src/main/java/com/unibuy/smartdevice/.idea/caches/deviceStreaming.xml
similarity index 100%
rename from .idea/caches/deviceStreaming.xml
rename to app/src/main/java/com/unibuy/smartdevice/.idea/caches/deviceStreaming.xml
diff --git a/.idea/deviceManager.xml b/app/src/main/java/com/unibuy/smartdevice/.idea/deviceManager.xml
similarity index 100%
rename from .idea/deviceManager.xml
rename to app/src/main/java/com/unibuy/smartdevice/.idea/deviceManager.xml
diff --git a/app/src/main/java/com/unibuy/smartdevice/.idea/misc.xml b/app/src/main/java/com/unibuy/smartdevice/.idea/misc.xml
new file mode 100644
index 0000000..3c23ef1
--- /dev/null
+++ b/app/src/main/java/com/unibuy/smartdevice/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/unibuy/smartdevice/.idea/modules.xml b/app/src/main/java/com/unibuy/smartdevice/.idea/modules.xml
new file mode 100644
index 0000000..c50f310
--- /dev/null
+++ b/app/src/main/java/com/unibuy/smartdevice/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/app/src/main/java/com/unibuy/smartdevice/.idea/vcs.xml
similarity index 57%
rename from .idea/vcs.xml
rename to app/src/main/java/com/unibuy/smartdevice/.idea/vcs.xml
index 9661ac7..5b5df18 100644
--- a/.idea/vcs.xml
+++ b/app/src/main/java/com/unibuy/smartdevice/.idea/vcs.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/app/src/main/java/com/unibuy/smartdevice/service/MqttService.java b/app/src/main/java/com/unibuy/smartdevice/service/MqttService.java
index a4db1cc..f2489c7 100644
--- a/app/src/main/java/com/unibuy/smartdevice/service/MqttService.java
+++ b/app/src/main/java/com/unibuy/smartdevice/service/MqttService.java
@@ -24,12 +24,15 @@ import com.unibuy.smartdevice.external.mqtt.MqttManager;
import com.unibuy.smartdevice.structure.BuyStructure;
import com.unibuy.smartdevice.structure.ReportFlowInfoStructure;
import com.unibuy.smartdevice.structure.SlotStructure;
+import com.unibuy.smartdevice.structure.ProductStructure;
import com.unibuy.smartdevice.structure.mqtt.TransactionFinalizePayload;
import com.unibuy.smartdevice.tools.TransactionFinalizeBuilder;
+import com.unibuy.smartdevice.ui.tools.ImageGlide;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
+import java.util.List;
import java.util.Locale;
import java.util.UUID;
@@ -274,6 +277,62 @@ public class MqttService extends Service {
};
// 使用新架構 StarCloudAPI 執行同步
new com.unibuy.smartdevice.external.StarCloudAPI(adHandler, adHandler).downloadAdvertisement();
+ } else if ("update_products".equals(cmd)) {
+ logs.info("Executing remote product sync command...");
+
+ // 📢 在主執行緒顯示 Toast 提示使用者
+ new android.os.Handler(android.os.Looper.getMainLooper()).post(() ->
+ android.widget.Toast.makeText(getApplicationContext(),
+ "📢 商品更新中...", android.widget.Toast.LENGTH_SHORT).show());
+
+ com.unibuy.smartdevice.tools.HandlerMain productHandler = new com.unibuy.smartdevice.tools.HandlerMain(
+ getApplicationContext(), logs) {
+ @Override
+ protected void execute(Context context, int code, String message) {
+ logs.info("Product sync event: [" + code + "] " + message);
+ if (code == 200 && "商品下載成功".equals(message)) {
+ // 背景預載圖片
+ new Thread(() -> {
+ try {
+ List products = MyApp.getInstance().getProductList();
+ int total = products.size();
+ logs.info("Starting image preloading for " + total + " products...");
+
+ for (int i = 0; i < total; i++) {
+ ProductStructure p = products.get(i);
+ if (p.getProductImg() != null && !p.getProductImg().isEmpty()) {
+ try {
+ new ImageGlide(getApplicationContext()).preload(p.getProductImg());
+ } catch (Exception e) {
+ logs.info("Failed to preload image for product " + p.getProductID() + ": " + e.getMessage());
+ }
+ }
+ }
+
+ logs.info("Product sync and image preloading completed.");
+ mqttManager.publishCommandAck(cmdId, "success", "Product sync completed successfully");
+
+ new android.os.Handler(android.os.Looper.getMainLooper()).post(() ->
+ android.widget.Toast.makeText(context,
+ "✅ 商品更新完成", android.widget.Toast.LENGTH_SHORT).show());
+ } catch (Exception e) {
+ logs.error(com.unibuy.smartdevice.exception.ErrorCode.UNKNOWN_ERROR, "Error during image preloading: " + e.getMessage());
+ mqttManager.publishCommandAck(cmdId, "failed", "Image preloading error: " + e.getMessage());
+ }
+ }).start();
+ } else if (code >= 400) {
+ mqttManager.publishCommandAck(cmdId, "failed", "Product sync failed: " + message);
+ new android.os.Handler(android.os.Looper.getMainLooper()).post(() ->
+ android.widget.Toast.makeText(context,
+ "❌ 商品更新失敗: " + message, android.widget.Toast.LENGTH_LONG).show());
+ }
+ }
+ };
+
+ // 1. 清除舊圖片快取
+ ImageGlide.clearProductCache(getApplicationContext());
+ // 2. 開始下載資料
+ new com.unibuy.smartdevice.external.StarCloudAPI(productHandler, productHandler).downloadProductInfo();
} else if ("update_inventory".equals(cmd)) {
logs.info("Executing update_inventory command...");
try {
diff --git a/app/src/main/java/com/unibuy/smartdevice/ui/ProductListActivity.java b/app/src/main/java/com/unibuy/smartdevice/ui/ProductListActivity.java
index 6419fc4..59e6b58 100644
--- a/app/src/main/java/com/unibuy/smartdevice/ui/ProductListActivity.java
+++ b/app/src/main/java/com/unibuy/smartdevice/ui/ProductListActivity.java
@@ -201,6 +201,9 @@ public class ProductListActivity extends AppCompatActivityAbstract {
try {
new ImageGlide(handlerMain.getContext()).preload(product.getProductImg());
+ // 下載完成後,立即刷新該項目的 UI (使 ImageGlide 重新判斷檔案存在,由淡變亮)
+ final int index = i;
+ runOnUiThread(() -> recyclerProductListAdpter.notifyItemChanged(index));
} catch (LogsEmptyException e) {
getLogs().warning(e);
}
diff --git a/app/src/main/java/com/unibuy/smartdevice/ui/tools/ImageGlide.java b/app/src/main/java/com/unibuy/smartdevice/ui/tools/ImageGlide.java
index 3684b86..5b6b379 100644
--- a/app/src/main/java/com/unibuy/smartdevice/ui/tools/ImageGlide.java
+++ b/app/src/main/java/com/unibuy/smartdevice/ui/tools/ImageGlide.java
@@ -62,7 +62,6 @@ public class ImageGlide {
Glide.with(imageView).load(urlString)
.placeholder(R.drawable.loading)
.error(R.drawable.loading)
- .transform(new WhiteTintTransformation(128))
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
.signature(new ObjectKey(System.currentTimeMillis())) // 強制更新
.into(imageView);
@@ -71,7 +70,6 @@ public class ImageGlide {
Glide.with(imageView).load(urlString)
.placeholder(R.drawable.loading)
.error(R.drawable.loading)
- .transform(new WhiteTintTransformation(128))
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
.signature(new ObjectKey(System.currentTimeMillis())) // 強制更新
.into(imageView);
@@ -103,7 +101,6 @@ public class ImageGlide {
Glide.with(context.getApplicationContext()).load(urlString)
.placeholder(R.drawable.loading)
.error(R.drawable.loading)
- .transform(new WhiteTintTransformation(128))
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
.preload();
}
diff --git a/gradle/gradle-daemon-jvm.properties b/gradle/gradle-daemon-jvm.properties
index 3a01efc..ae79801 100644
--- a/gradle/gradle-daemon-jvm.properties
+++ b/gradle/gradle-daemon-jvm.properties
@@ -1,2 +1,12 @@
-#toolchainVendor=jetbrains
-#toolchainVersion=21
+#This file is generated by updateDaemonJvm
+toolchainUrl.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/65aaef917b9f394804f058f1861225c9/redirect
+toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/c728c5388b044fbdbbc44b0c6acee0df/redirect
+toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/65aaef917b9f394804f058f1861225c9/redirect
+toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/c728c5388b044fbdbbc44b0c6acee0df/redirect
+toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/dc463b4a8183dbcaa1b32544189c7f03/redirect
+toolchainUrl.MAC_OS.X86_64=https\://api.foojay.io/disco/v3.0/ids/cb7dc109dd590ebca2d703734d23c9d3/redirect
+toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/65aaef917b9f394804f058f1861225c9/redirect
+toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/c728c5388b044fbdbbc44b0c6acee0df/redirect
+toolchainUrl.WINDOWS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/43ee83889b87bacad5d3071ae7bbd349/redirect
+toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/2d57bdd1e17a18f83ff073919daa35ba/redirect
+toolchainVersion=17
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 54031c6..234581a 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -1,5 +1,5 @@
[versions]
-agp = "8.9.0"
+agp = "8.13.2"
junit = "4.13.2"
junitVersion = "1.2.1"
espressoCore = "3.6.1"
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index aa9cc37..70fd08f 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
#Sat Mar 22 19:54:26 CST 2025
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists