From df6f548c76a6f7ca1831d46c09e7a5c7c42dce60 Mon Sep 17 00:00:00 2001 From: 7015725 Date: Mon, 18 May 2026 14:50:37 +0800 Subject: [PATCH] feat: add icon picker favorites --- code/th_14_panels.js | 82 ++++++++++++++++++++++++++++++++++++++++++-- manifest.json | 6 ++-- manifest.sig | 2 +- 3 files changed, 84 insertions(+), 6 deletions(-) diff --git a/code/th_14_panels.js b/code/th_14_panels.js index 7562ff0..f24ca62 100644 --- a/code/th_14_panels.js +++ b/code/th_14_panels.js @@ -4364,6 +4364,62 @@ FloatBallAppWM.prototype.showShortXIconPickerPopup = function(opts) { var wm = self.state.wm; var filterTags = ["全部", "常用", "最近", "收藏", "线框", "实心"]; var filterViews = []; + var FAVORITE_ICONS_KEY = "shortx_icon_favorites"; + var favoriteIcons = []; + var favoriteMap = {}; + + function rebuildFavoriteMap() { + favoriteMap = {}; + for (var fi = 0; fi < favoriteIcons.length; fi++) { + var fn = String(favoriteIcons[fi] || ""); + if (fn) favoriteMap[fn] = true; + } + } + + function loadFavoriteIcons() { + favoriteIcons = []; + try { + var saved = self.loadPanelState ? self.loadPanelState(FAVORITE_ICONS_KEY) : null; + var arr = saved && saved.icons ? saved.icons : []; + for (var li = 0; li < arr.length && favoriteIcons.length < 300; li++) { + var name = String(arr[li] || ""); + if (name && !favoriteMap[name]) { + favoriteIcons.push(name); + favoriteMap[name] = true; + } + } + } catch(eFavLoad) { safeLog(null, 'e', "catch " + String(eFavLoad)); } + rebuildFavoriteMap(); + } + + function saveFavoriteIcons() { + try { + if (self.savePanelState) self.savePanelState(FAVORITE_ICONS_KEY, { icons: favoriteIcons.slice(0, 300) }); + } catch(eFavSave) { safeLog(null, 'e', "catch " + String(eFavSave)); } + } + + function isFavoriteIcon(name) { + return !!favoriteMap[String(name || "")]; + } + + function toggleFavoriteIcon(name) { + name = String(name || ""); + if (!name) return false; + var next = []; + var existed = false; + for (var ti = 0; ti < favoriteIcons.length; ti++) { + var oldName = String(favoriteIcons[ti] || ""); + if (!oldName) continue; + if (oldName === name) { existed = true; continue; } + next.push(oldName); + } + if (!existed) next.unshift(name); + favoriteIcons = next.slice(0, 300); + rebuildFavoriteMap(); + saveFavoriteIcons(); + return !existed; + } + loadFavoriteIcons(); function matchesFilter(entry, f) { if (!entry) return false; @@ -4371,7 +4427,7 @@ FloatBallAppWM.prototype.showShortXIconPickerPopup = function(opts) { var n = String(entry.shortName || entry.name || "").toLowerCase(); if (f === "常用") return n.indexOf("home") >= 0 || n.indexOf("share") >= 0 || n.indexOf("search") >= 0 || n.indexOf("settings") >= 0 || n.indexOf("add") >= 0 || n.indexOf("back") >= 0 || n.indexOf("close") >= 0; if (f === "最近") return selectedName && String(entry.name) === String(selectedName); - if (f === "收藏") return false; + if (f === "收藏") return isFavoriteIcon(entry.name); if (f === "线框") return n.indexOf("outline") >= 0 || n.indexOf("line") >= 0 || n.indexOf("stroke") >= 0 || n.indexOf("border") >= 0; if (f === "实心") return n.indexOf("fill") >= 0 || n.indexOf("solid") >= 0 || n.indexOf("round") >= 0; return true; @@ -4663,7 +4719,7 @@ FloatBallAppWM.prototype.showShortXIconPickerPopup = function(opts) { if (pageItems.length === 0) { var emptyTv = new android.widget.TextView(context); - emptyTv.setText(popupState.filter === "收藏" ? "收藏夹还空着" : "没有找到这枚小图标"); + emptyTv.setText(popupState.filter === "收藏" ? "收藏夹还空着,点图标左上角 ☆ 收藏" : "没有找到这枚小图标"); emptyTv.setTextColor(subTextColor); emptyTv.setTextSize(android.util.TypedValue.COMPLEX_UNIT_SP, 14); emptyTv.setGravity(android.view.Gravity.CENTER); @@ -4707,6 +4763,28 @@ FloatBallAppWM.prototype.showShortXIconPickerPopup = function(opts) { tv.setTextColor(isSelected ? T.primaryDeep : subTextColor); cell.addView(tv, new android.widget.LinearLayout.LayoutParams(android.widget.LinearLayout.LayoutParams.MATCH_PARENT, android.widget.LinearLayout.LayoutParams.WRAP_CONTENT)); + var favBtn = new android.widget.TextView(context); + favBtn.setText(isFavoriteIcon(item.name) ? "★" : "☆"); + favBtn.setTextColor(isFavoriteIcon(item.name) ? T.primaryDeep : self.withAlpha(T.primaryDeep, 0.52)); + favBtn.setTextSize(android.util.TypedValue.COMPLEX_UNIT_SP, 13); + favBtn.setGravity(android.view.Gravity.CENTER); + favBtn.setTypeface(null, android.graphics.Typeface.BOLD); + favBtn.setBackground(self.ui.createRoundDrawable(isFavoriteIcon(item.name) ? T.primarySoft : self.withAlpha(T.card, 0.88), self.dp(9))); + favBtn.setClickable(true); + favBtn.setOnClickListener(new android.view.View.OnClickListener({ + onClick: function() { + self.touchActivity(); + var added = toggleFavoriteIcon(item.name); + try { self.toast(added ? "已收藏到小岛" : "已取消收藏"); } catch(eFavToast) {} + if (popupState.filter === "收藏") popupState.currentPage = 0; + renderGrid(); + } + })); + var favLp = new android.widget.FrameLayout.LayoutParams(self.dp(18), self.dp(18)); + favLp.gravity = android.view.Gravity.TOP | android.view.Gravity.LEFT; + favLp.setMargins(self.dp(4), self.dp(4), 0, 0); + frame.addView(favBtn, favLp); + if (isSelected) { var badge = new android.widget.TextView(context); badge.setText("✓"); diff --git a/manifest.json b/manifest.json index 25f51cf..0a52690 100644 --- a/manifest.json +++ b/manifest.json @@ -54,8 +54,8 @@ "size": 21198 }, "th_14_panels.js": { - "sha256": "e5a1166d954312f414cf517cbaa79238465bff924cb02c088df8aa563c4342c1", - "size": 258201 + "sha256": "346aa3fdfa27022bb2d61d3302533be2e38461c9140e9f09d05822d39cbb4237", + "size": 261345 }, "th_15_extra.js": { "sha256": "7db6431ad246c63e99c4c96dcf5903d38036efd6eed5c0da88bcfa0a0cd62ee0", @@ -68,5 +68,5 @@ }, "keyId": "toolhub-targets-2026-rsa3072", "schema": 2, - "version": 20260518064153 + "version": 20260518065021 } diff --git a/manifest.sig b/manifest.sig index b51e3e5..b93fe29 100644 --- a/manifest.sig +++ b/manifest.sig @@ -1 +1 @@ -pJgRh54bZL/hC/IGRyaN0cDRsAdh5+MQa6ctmurokGisbydGP2bUopScDwlBmrHIFWvLjLqnutjFzcKc8BppvHyyM03Dx57OPgBN/zIbRXffXsG2Rk/vAJGJrTfJaIY5alKfuw5QwSUpnIXojjN1D6cuEDMgrB7R9ISlAc3l2x1oB/jA7NOY+/c+sleVTefa4wQCx+QYK2echW8OAbLvY5/REPNrw7ua4YdFRUluypi3HIO3x1QlgcaRtL99JzrANMrFdxVUavqKloQ3WLFfmMx7ub485nzhTguP9Vgg2KINaLky6EfrPZQFHU5vgQZxS95+wJCFTtOicKSeCn7XQbRrjQeta9PeBXqIn0aaJ6QrOB66VIsVOqDYe5fQPOkBsxaj4dPA2j8CgM1ibyPRNqMkgt//musQYsGZpvOxWjLZyJAgY9nszWDhBX3MJXf2TFbLJPa+AWsn2AuAfVfzTvV1Od5X2UveX9EohQeHr3n3AkTuNh3FBXR9rkt87PHD +MpJ0REu6Fyj+hyD9mX5E6+lmAjh2vBuhYjCA4dVrnupMg0j9QBa04EfFQVfRu1fd4Y9MgDvZScjdP8CmZjs4znlCR3WHSKgUYxVMSKb/Tm7ZM09YvueMF3xxwgEDL4LdYB4XCWZfEfWKd94M91ON6h/B3+MgGrQnE2UYwUz1OE84cH5XL54Gm59cExB7Bh7lFASjlYeI5aRW1NY/121tbL9iz1blO7urx7T6l3/5j1wtdrQeQIGHIqdL3pYwWKjxQ2mNlyiRDgH96SuAcUd+2L6hFEnvXhCZqYDOXTILusoO8OCiveSZAFKAq26Rs5qj+g+SdkOKE0Oa5g1ehlhKPI+yZNiKfYLhbnLT0XLwi6DX8dsgcMml9f/NdWydAsnGEoF30dw2oLVoJMi+Rjq1nVnLrhpPSZIPELi4TZilg5klH6nsWegaK+DK84bf6qSBz+yBd8hrx/Hu0vzNzsdKp/woHzNfzCnHN3QaFvG3URJFjkNnvUm1bD0Q+EHwkGZY