minecodex 0.1.18 → 0.1.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -22,6 +22,13 @@ distributed under MineCodex's MIT License.
|
|
|
22
22
|
(`icons/xiaomi.svg`), licensed under CC0 1.0. The Xiaomi brand mark remains
|
|
23
23
|
the property of Xiaomi Corporation.
|
|
24
24
|
|
|
25
|
+
## Meta logo (provider mark)
|
|
26
|
+
|
|
27
|
+
`assets/providers/muse.svg` is the official Meta Platforms logo rendered in the
|
|
28
|
+
same 24×24 provider-mark style (Lobe Icons) as the other provider icons in this
|
|
29
|
+
folder. The Meta mark remains the property of Meta Platforms, Inc.; the SVG
|
|
30
|
+
wrapper is distributed under MineCodex's MIT License.
|
|
31
|
+
|
|
25
32
|
## Lucide
|
|
26
33
|
|
|
27
34
|
Lucide icons distributed by MineCodex include the Model Slider UI icons, Notes action and
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Meta</title><path d="M6.897 4h-.024l-.031 2.615h.022c1.715 0 3.046 1.357 5.94 6.246l.175.297.012.02 1.62-2.438-.012-.019a48.763 48.763 0 00-1.098-1.716 28.01 28.01 0 00-1.175-1.629C10.413 4.932 8.812 4 6.896 4z" fill="url(#lobe-icons-meta-0-_R_0_)"></path><path d="M6.873 4C4.95 4.01 3.247 5.258 2.02 7.17a4.352 4.352 0 00-.01.017l2.254 1.231.011-.017c.718-1.083 1.61-1.774 2.568-1.785h.021L6.896 4h-.023z" fill="url(#lobe-icons-meta-1-_R_0_)"></path><path d="M2.019 7.17l-.011.017C1.2 8.447.598 9.995.274 11.664l-.005.022 2.534.6.004-.022c.27-1.467.786-2.828 1.456-3.845l.011-.017L2.02 7.17z" fill="url(#lobe-icons-meta-2-_R_0_)"></path><path d="M2.807 12.264l-2.533-.6-.005.022c-.177.918-.267 1.851-.269 2.786v.023l2.598.233v-.023a12.591 12.591 0 01.21-2.44z" fill="url(#lobe-icons-meta-3-_R_0_)"></path><path d="M2.677 15.537a5.462 5.462 0 01-.079-.813v-.022L0 14.468v.024a8.89 8.89 0 00.146 1.652l2.535-.585a4.106 4.106 0 01-.004-.022z" fill="url(#lobe-icons-meta-4-_R_0_)"></path><path d="M3.27 16.89c-.284-.31-.484-.756-.589-1.328l-.004-.021-2.535.585.004.021c.192 1.01.568 1.85 1.106 2.487l.014.017 2.018-1.745a2.106 2.106 0 01-.015-.016z" fill="url(#lobe-icons-meta-5-_R_0_)"></path><path d="M10.78 9.654c-1.528 2.35-2.454 3.825-2.454 3.825-2.035 3.2-2.739 3.917-3.871 3.917a1.545 1.545 0 01-1.186-.508l-2.017 1.744.014.017C2.01 19.518 3.058 20 4.356 20c1.963 0 3.374-.928 5.884-5.33l1.766-3.13a41.283 41.283 0 00-1.227-1.886z" fill="#0082FB"></path><path d="M13.502 5.946l-.016.016c-.4.43-.786.908-1.16 1.416.378.483.768 1.024 1.175 1.63.48-.743.928-1.345 1.367-1.807l.016-.016-1.382-1.24z" fill="url(#lobe-icons-meta-6-_R_0_)"></path><path d="M20.918 5.713C19.853 4.633 18.583 4 17.225 4c-1.432 0-2.637.787-3.723 1.944l-.016.016 1.382 1.24.016-.017c.715-.747 1.408-1.12 2.176-1.12.826 0 1.6.39 2.27 1.075l.015.016 1.589-1.425-.016-.016z" fill="#0082FB"></path><path d="M23.998 14.125c-.06-3.467-1.27-6.566-3.064-8.396l-.016-.016-1.588 1.424.015.016c1.35 1.392 2.277 3.98 2.361 6.971v.023h2.292v-.022z" fill="url(#lobe-icons-meta-7-_R_0_)"></path><path d="M23.998 14.15v-.023h-2.292v.022c.004.14.006.282.006.424 0 .815-.121 1.474-.368 1.95l-.011.022 1.708 1.782.013-.02c.62-.96.946-2.293.946-3.91 0-.083 0-.165-.002-.247z" fill="url(#lobe-icons-meta-8-_R_0_)"></path><path d="M21.344 16.52l-.011.02c-.214.402-.519.67-.917.787l.778 2.462a3.493 3.493 0 00.438-.182 3.558 3.558 0 001.366-1.218l.044-.065.012-.02-1.71-1.784z" fill="url(#lobe-icons-meta-9-_R_0_)"></path><path d="M19.92 17.393c-.262 0-.492-.039-.718-.14l-.798 2.522c.449.153.927.222 1.46.222.492 0 .943-.073 1.352-.215l-.78-2.462c-.167.05-.341.075-.517.073z" fill="url(#lobe-icons-meta-10-_R_0_)"></path><path d="M18.323 16.534l-.014-.017-1.836 1.914.016.017c.637.682 1.246 1.105 1.937 1.337l.797-2.52c-.291-.125-.573-.353-.9-.731z" fill="url(#lobe-icons-meta-11-_R_0_)"></path><path d="M18.309 16.515c-.55-.642-1.232-1.712-2.303-3.44l-1.396-2.336-.011-.02-1.62 2.438.012.02.989 1.668c.959 1.61 1.74 2.774 2.493 3.585l.016.016 1.834-1.914a2.353 2.353 0 01-.014-.017z" fill="url(#lobe-icons-meta-12-_R_0_)"></path><defs><linearGradient id="lobe-icons-meta-0-_R_0_" x1="75.897%" x2="26.312%" y1="89.199%" y2="12.194%"><stop offset=".06%" stop-color="#0867DF"></stop><stop offset="45.39%" stop-color="#0668E1"></stop><stop offset="85.91%" stop-color="#0064E0"></stop></linearGradient><linearGradient id="lobe-icons-meta-1-_R_0_" x1="21.67%" x2="97.068%" y1="75.874%" y2="23.985%"><stop offset="13.23%" stop-color="#0064DF"></stop><stop offset="99.88%" stop-color="#0064E0"></stop></linearGradient><linearGradient id="lobe-icons-meta-2-_R_0_" x1="38.263%" x2="60.895%" y1="89.127%" y2="16.131%"><stop offset="1.47%" stop-color="#0072EC"></stop><stop offset="68.81%" stop-color="#0064DF"></stop></linearGradient><linearGradient id="lobe-icons-meta-3-_R_0_" x1="47.032%" x2="52.15%" y1="90.19%" y2="15.745%"><stop offset="7.31%" stop-color="#007CF6"></stop><stop offset="99.43%" stop-color="#0072EC"></stop></linearGradient><linearGradient id="lobe-icons-meta-4-_R_0_" x1="52.155%" x2="47.591%" y1="58.301%" y2="37.004%"><stop offset="7.31%" stop-color="#007FF9"></stop><stop offset="100%" stop-color="#007CF6"></stop></linearGradient><linearGradient id="lobe-icons-meta-5-_R_0_" x1="37.689%" x2="61.961%" y1="12.502%" y2="63.624%"><stop offset="7.31%" stop-color="#007FF9"></stop><stop offset="100%" stop-color="#0082FB"></stop></linearGradient><linearGradient id="lobe-icons-meta-6-_R_0_" x1="34.808%" x2="62.313%" y1="68.859%" y2="23.174%"><stop offset="27.99%" stop-color="#007FF8"></stop><stop offset="91.41%" stop-color="#0082FB"></stop></linearGradient><linearGradient id="lobe-icons-meta-7-_R_0_" x1="43.762%" x2="57.602%" y1="6.235%" y2="98.514%"><stop offset="0%" stop-color="#0082FB"></stop><stop offset="99.95%" stop-color="#0081FA"></stop></linearGradient><linearGradient id="lobe-icons-meta-8-_R_0_" x1="60.055%" x2="39.88%" y1="4.661%" y2="69.077%"><stop offset="6.19%" stop-color="#0081FA"></stop><stop offset="100%" stop-color="#0080F9"></stop></linearGradient><linearGradient id="lobe-icons-meta-9-_R_0_" x1="30.282%" x2="61.081%" y1="59.32%" y2="33.244%"><stop offset="0%" stop-color="#027AF3"></stop><stop offset="100%" stop-color="#0080F9"></stop></linearGradient><linearGradient id="lobe-icons-meta-10-_R_0_" x1="20.433%" x2="82.112%" y1="50.001%" y2="50.001%"><stop offset="0%" stop-color="#0377EF"></stop><stop offset="99.94%" stop-color="#0279F1"></stop></linearGradient><linearGradient id="lobe-icons-meta-11-_R_0_" x1="40.303%" x2="72.394%" y1="35.298%" y2="57.811%"><stop offset=".19%" stop-color="#0471E9"></stop><stop offset="100%" stop-color="#0377EF"></stop></linearGradient><linearGradient id="lobe-icons-meta-12-_R_0_" x1="32.254%" x2="68.003%" y1="19.719%" y2="84.908%"><stop offset="27.65%" stop-color="#0867DF"></stop><stop offset="100%" stop-color="#0471E9"></stop></linearGradient></defs></svg>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"id": "model-slider",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.12",
|
|
5
5
|
"label": {
|
|
6
6
|
"en": "Model Slider",
|
|
7
7
|
"zh-CN": "模型滑条"
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
"xai": "xAI",
|
|
23
23
|
"zhipu": "Zhipu AI",
|
|
24
24
|
"google": "Google",
|
|
25
|
+
"meta": "Meta",
|
|
25
26
|
"anthropic": "Anthropic",
|
|
26
27
|
"openai": "OpenAI"
|
|
27
28
|
},
|
|
@@ -50,6 +51,7 @@
|
|
|
50
51
|
{ "id": "minimax", "keywords": ["minimax"], "icon": { "resource": "assets/providers/minimax.svg" } },
|
|
51
52
|
{ "id": "qwen", "keywords": ["qwen", "qwq"], "icon": { "resource": "assets/providers/qwen.svg" } },
|
|
52
53
|
{ "id": "hunyuan", "keywords": ["hunyuan"], "icon": { "resource": "assets/providers/hunyuan.svg" } },
|
|
54
|
+
{ "id": "muse", "keywords": ["muse", "muse-spark"], "icon": { "resource": "assets/providers/muse.svg" } },
|
|
53
55
|
{ "id": "zhipu", "keywords": ["zhipu", "chatglm", "glm"], "icon": { "resource": "assets/providers/zhipu.svg" } },
|
|
54
56
|
{ "id": "openai", "keywords": ["openai", "gpt", "codex", "o1", "o3", "o4"], "icon": { "resource": "assets/providers/openai.svg" } }
|
|
55
57
|
]
|
package/package.json
CHANGED
|
@@ -298,6 +298,12 @@ export function createInjectionSource(features, {
|
|
|
298
298
|
let modelSelectorTriggerObserver = null;
|
|
299
299
|
let modelSelectorObservedTrigger = null;
|
|
300
300
|
let modelSelectorNativeFastIcons = null;
|
|
301
|
+
// Fast 图标来源标记:bundle 静态提取 vs DOM 克隆,DOM 克隆优先以保持像素一致。
|
|
302
|
+
let modelSelectorNativeFastIconSources = null;
|
|
303
|
+
// DOM 克隆可见性门控:仅在 Fast 控件从无到有时扫描一次,常驻会话不逐帧扫描。
|
|
304
|
+
let modelSelectorFastControlVisible = false;
|
|
305
|
+
// 持久化脏标记:仅在图标实际变化时写一次 localStorage。
|
|
306
|
+
let modelSelectorNativeFastIconsDirty = false;
|
|
301
307
|
const modelSelectorStyle = document.createElement("style");
|
|
302
308
|
modelSelectorStyle.setAttribute("data-codex-model-slider-style", "");
|
|
303
309
|
modelSelectorStyle.textContent = `
|
|
@@ -376,6 +382,17 @@ export function createInjectionSource(features, {
|
|
|
376
382
|
if (modelSelectorFeature) {
|
|
377
383
|
document.documentElement.setAttribute("data-codex-model-slider-catalog-ready", "");
|
|
378
384
|
document.documentElement.append(modelSelectorStyle);
|
|
385
|
+
// 启动阶段就解析 Fast 图标:先读持久化的原生克隆,再从 app bundle 静态提取兜底,
|
|
386
|
+
// 避免首次会话必须等用户点开弹窗后 DOM 里才出现图标。
|
|
387
|
+
const persistedIcons = loadPersistedNativeFastIcons();
|
|
388
|
+
if (persistedIcons) {
|
|
389
|
+
modelSelectorNativeFastIcons = persistedIcons;
|
|
390
|
+
modelSelectorNativeFastIconSources = {};
|
|
391
|
+
for (const state of Object.keys(persistedIcons)) {
|
|
392
|
+
modelSelectorNativeFastIconSources[state] = "persisted";
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
void loadNativeFastIconFromBundle();
|
|
379
396
|
}
|
|
380
397
|
|
|
381
398
|
for (const feature of pageScriptFeatures) {
|
|
@@ -649,28 +666,149 @@ export function createInjectionSource(features, {
|
|
|
649
666
|
return null;
|
|
650
667
|
}
|
|
651
668
|
|
|
669
|
+
const modelSelectorFastIconStorageKey = "codex-model-slider:fast-icons:v1";
|
|
670
|
+
|
|
671
|
+
function persistNativeFastIcons() {
|
|
672
|
+
if (!modelSelectorNativeFastIcons || !modelSelectorNativeFastIconsDirty) return;
|
|
673
|
+
try {
|
|
674
|
+
const payload = {};
|
|
675
|
+
for (const [state, template] of Object.entries(modelSelectorNativeFastIcons)) {
|
|
676
|
+
payload[state] = template.outerHTML;
|
|
677
|
+
}
|
|
678
|
+
localStorage.setItem(modelSelectorFastIconStorageKey, JSON.stringify(payload));
|
|
679
|
+
modelSelectorNativeFastIconsDirty = false;
|
|
680
|
+
} catch {
|
|
681
|
+
// localStorage 不可用时静默降级,仅本次会话内生效。
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
function loadPersistedNativeFastIcons() {
|
|
686
|
+
try {
|
|
687
|
+
const payload = JSON.parse(localStorage.getItem(modelSelectorFastIconStorageKey) ?? "null");
|
|
688
|
+
if (!payload || typeof payload !== "object") return null;
|
|
689
|
+
const icons = {};
|
|
690
|
+
for (const [state, markup] of Object.entries(payload)) {
|
|
691
|
+
if (typeof markup !== "string") continue;
|
|
692
|
+
const container = document.createElement("template");
|
|
693
|
+
container.innerHTML = markup;
|
|
694
|
+
const svg = container.content.querySelector("svg");
|
|
695
|
+
if (svg) icons[state] = svg;
|
|
696
|
+
}
|
|
697
|
+
return Object.keys(icons).length ? icons : null;
|
|
698
|
+
} catch {
|
|
699
|
+
return null;
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
function extractFastIconPath(source, prefix) {
|
|
704
|
+
const match = String(source).match(new RegExp(`d:\`(${prefix}[^\`]*)\``));
|
|
705
|
+
return match?.[1] ?? null;
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
async function loadNativeFastIconFromBundle() {
|
|
709
|
+
// 两个图标均已就绪(持久化或 DOM 克隆)时不再拉取整包 app-initial 资源。
|
|
710
|
+
if (modelSelectorNativeFastIcons?.active && modelSelectorNativeFastIcons?.inactive) return;
|
|
711
|
+
const sourceLink = document.querySelector('link[href*="/assets/app-initial-"][href$=".js"]');
|
|
712
|
+
if (!sourceLink?.href) return;
|
|
713
|
+
try {
|
|
714
|
+
const source = await fetch(sourceLink.href).then((response) => response.text());
|
|
715
|
+
if (!modelSelectorNativeFastIcons) {
|
|
716
|
+
modelSelectorNativeFastIcons = {};
|
|
717
|
+
modelSelectorNativeFastIconSources = {};
|
|
718
|
+
}
|
|
719
|
+
let gained = false;
|
|
720
|
+
const define = (state, prefix, definition) => {
|
|
721
|
+
if (modelSelectorNativeFastIcons[state]) return;
|
|
722
|
+
const path = extractFastIconPath(source, prefix);
|
|
723
|
+
if (!path) return;
|
|
724
|
+
const svg = createModelSelectorIcon({
|
|
725
|
+
viewBox: definition.viewBox,
|
|
726
|
+
markup: definition.transform
|
|
727
|
+
? `<g transform="${definition.transform}"><path d="${path}" fill="currentColor" /></g>`
|
|
728
|
+
: `<path d="${path}" fill="currentColor" />`,
|
|
729
|
+
}, { brand: true });
|
|
730
|
+
if (!svg) return;
|
|
731
|
+
modelSelectorNativeFastIcons[state] = svg;
|
|
732
|
+
modelSelectorNativeFastIconSources[state] = "bundle";
|
|
733
|
+
gained = true;
|
|
734
|
+
};
|
|
735
|
+
define("active", "M11\\.9125 21\\.4125", { viewBox: "0 0 24 24" });
|
|
736
|
+
define("inactive", "M7\\.38 16\\.2207", { viewBox: "0 0 20 20", transform: "translate(2.43 1.609)" });
|
|
737
|
+
if (gained) {
|
|
738
|
+
modelSelectorNativeFastIconsDirty = true;
|
|
739
|
+
persistNativeFastIcons();
|
|
740
|
+
applyNativeFastIconsToShells();
|
|
741
|
+
queueEnsure();
|
|
742
|
+
}
|
|
743
|
+
} catch {
|
|
744
|
+
// 私有资源移动时保持原生控件不变,等待 DOM 克隆兜底。
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
function hasVisibleFastControl() {
|
|
749
|
+
return Boolean(
|
|
750
|
+
document.querySelector("[data-codex-model-slider-fast]")
|
|
751
|
+
|| document.querySelector('[class*="_FastModeToggle_"]')
|
|
752
|
+
|| document.querySelector('[class*="_ModelPickerTriggerFastIndicator_"] svg'),
|
|
753
|
+
);
|
|
754
|
+
}
|
|
755
|
+
|
|
652
756
|
function captureNativeFastIcon() {
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
const
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
757
|
+
// Fast 图标只在 Fast 控件渲染后才出现在 DOM(打开菜单或 GPT 模型);
|
|
758
|
+
// 只在控件可见性从无到有时做一次全页扫描(升级为 DOM 克隆),
|
|
759
|
+
// 常驻会话不逐帧扫描整个文档;缺图标时由 bundle/持久化兜底。
|
|
760
|
+
const visible = hasVisibleFastControl();
|
|
761
|
+
const justBecameVisible = visible && !modelSelectorFastControlVisible;
|
|
762
|
+
modelSelectorFastControlVisible = visible;
|
|
763
|
+
if (visible && justBecameVisible) {
|
|
764
|
+
const capture = (state, pathPrefix) => {
|
|
765
|
+
const current = modelSelectorNativeFastIcons?.[state];
|
|
766
|
+
const currentSource = modelSelectorNativeFastIconSources?.[state];
|
|
767
|
+
if (current && currentSource === "dom") return;
|
|
768
|
+
const path = Array.from(document.querySelectorAll("svg path")).find(
|
|
769
|
+
(candidate) => candidate.getAttribute("d")?.startsWith(pathPrefix),
|
|
770
|
+
);
|
|
771
|
+
const svg = path?.closest("svg");
|
|
772
|
+
if (!svg) return;
|
|
773
|
+
const template = svg.cloneNode(true);
|
|
774
|
+
template.removeAttribute("id");
|
|
775
|
+
template.removeAttribute("width");
|
|
776
|
+
template.removeAttribute("height");
|
|
777
|
+
if (!modelSelectorNativeFastIcons) {
|
|
778
|
+
modelSelectorNativeFastIcons = {};
|
|
779
|
+
modelSelectorNativeFastIconSources = {};
|
|
780
|
+
}
|
|
781
|
+
modelSelectorNativeFastIcons[state] = template;
|
|
782
|
+
modelSelectorNativeFastIconSources[state] = "dom";
|
|
783
|
+
modelSelectorNativeFastIconsDirty = true;
|
|
784
|
+
};
|
|
785
|
+
capture("active", "M11.9125 21.4125");
|
|
786
|
+
capture("inactive", "M7.38 16.2207");
|
|
787
|
+
}
|
|
788
|
+
const ready = Boolean(
|
|
789
|
+
modelSelectorNativeFastIcons?.active && modelSelectorNativeFastIcons?.inactive,
|
|
790
|
+
);
|
|
791
|
+
if (ready) {
|
|
792
|
+
persistNativeFastIcons();
|
|
793
|
+
applyNativeFastIconsToShells();
|
|
794
|
+
}
|
|
669
795
|
return modelSelectorNativeFastIcons;
|
|
670
796
|
}
|
|
671
797
|
|
|
798
|
+
function applyNativeFastIconsToShells() {
|
|
799
|
+
document.querySelectorAll("[data-codex-model-slider-fast]").forEach((button) => {
|
|
800
|
+
const content = button.querySelector("[data-codex-model-slider-fast-content]");
|
|
801
|
+
// 幂等补装:只给还没有图标的按钮补上,避免每次 ensure 都重建节点。
|
|
802
|
+
if (!content || content.querySelector("svg")) return;
|
|
803
|
+
const icon = createNativeFastIcon(button.getAttribute("aria-pressed") === "true");
|
|
804
|
+
if (icon) content.replaceChildren(icon);
|
|
805
|
+
});
|
|
806
|
+
}
|
|
807
|
+
|
|
672
808
|
function createNativeFastIcon(active) {
|
|
673
|
-
|
|
809
|
+
// 直接读取已就绪的图标存储(启动时由 bundle/持久化填充,运行期由
|
|
810
|
+
// captureNativeFastIcon 升级为 DOM 克隆),避免再次触发捕获造成递归。
|
|
811
|
+
const template = modelSelectorNativeFastIcons?.[active ? "active" : "inactive"];
|
|
674
812
|
if (!template) return null;
|
|
675
813
|
const icon = template.cloneNode(true);
|
|
676
814
|
icon.setAttribute("aria-hidden", "true");
|
|
@@ -1240,18 +1378,19 @@ export function createInjectionSource(features, {
|
|
|
1240
1378
|
}
|
|
1241
1379
|
|
|
1242
1380
|
function enhanceModelItem(item, menu, selector, index) {
|
|
1243
|
-
if (item.querySelector("[data-codex-model-slider-row]")) return;
|
|
1244
1381
|
const observedRaw = modelItemRawValue(item);
|
|
1245
1382
|
if (!observedRaw) return;
|
|
1246
|
-
if (!modelSelectorOriginalItems.has(item)) modelSelectorOriginalItems.set(item, item.innerHTML);
|
|
1247
1383
|
const observedIdentity = modelIdentity(observedRaw);
|
|
1248
1384
|
const nativeDescriptor = nativeModelDescriptorForItem(item, observedRaw);
|
|
1249
1385
|
const catalogModel = catalogModelFor(observedIdentity, selector);
|
|
1250
1386
|
const raw = catalogModel?.slug ?? nativeDescriptor?.slug ?? observedRaw;
|
|
1387
|
+
// 先刷新 dataset:React 原地复用菜单节点时,raw/排序/收藏键不能基于过期值。
|
|
1251
1388
|
item.dataset.codexModelSliderRaw = raw;
|
|
1252
1389
|
item.dataset.codexModelSliderItem = "";
|
|
1253
1390
|
item.dataset.codexModelSliderOrder = String(index);
|
|
1254
1391
|
item.dataset.codexModelSliderIdentitySource = catalogModel ? "catalog" : nativeDescriptor ? "native" : "visible";
|
|
1392
|
+
if (item.querySelector("[data-codex-model-slider-row]")) return;
|
|
1393
|
+
if (!modelSelectorOriginalItems.has(item)) modelSelectorOriginalItems.set(item, item.innerHTML);
|
|
1255
1394
|
|
|
1256
1395
|
const identity = modelIdentity(raw);
|
|
1257
1396
|
const display = modelDisplayLabel(identity, selector);
|
|
@@ -1955,7 +2094,6 @@ export function createInjectionSource(features, {
|
|
|
1955
2094
|
function ensureModelSelector() {
|
|
1956
2095
|
const selector = modelSelectorFeature?.modelSelector;
|
|
1957
2096
|
if (!selector) return;
|
|
1958
|
-
captureNativeFastIcon();
|
|
1959
2097
|
pruneModelSubmenuPositionObservers();
|
|
1960
2098
|
if (!modelSelectorStyle.isConnected) document.head?.append(modelSelectorStyle);
|
|
1961
2099
|
enhanceComposerModelTrigger(selector);
|
|
@@ -1967,11 +2105,17 @@ export function createInjectionSource(features, {
|
|
|
1967
2105
|
returnToNativeModelSlider();
|
|
1968
2106
|
}, 80);
|
|
1969
2107
|
}
|
|
1970
|
-
|
|
2108
|
+
} else {
|
|
2109
|
+
enhanceNativeModelPicker(parentMenu, selector);
|
|
2110
|
+
const submenu = nativeModelSubmenu(parentMenu);
|
|
2111
|
+
if (submenu) enhanceNativeModelSubmenu(submenu, selector);
|
|
2112
|
+
}
|
|
2113
|
+
try {
|
|
2114
|
+
// 图标工作与菜单增强解耦:放在最后并隔离异常,任何失败都不影响标签与菜单。
|
|
2115
|
+
captureNativeFastIcon();
|
|
2116
|
+
} catch (error) {
|
|
2117
|
+
console.warn("[codex-personal] fast icon capture failed", error);
|
|
1971
2118
|
}
|
|
1972
|
-
enhanceNativeModelPicker(parentMenu, selector);
|
|
1973
|
-
const submenu = nativeModelSubmenu(parentMenu);
|
|
1974
|
-
if (submenu) enhanceNativeModelSubmenu(submenu, selector);
|
|
1975
2119
|
}
|
|
1976
2120
|
|
|
1977
2121
|
function restoreModelSelectorEnhancements() {
|
|
@@ -2277,16 +2421,23 @@ export function createInjectionSource(features, {
|
|
|
2277
2421
|
]);
|
|
2278
2422
|
for (const element of selected) {
|
|
2279
2423
|
if (element.hasAttribute(entryMarker) || alreadySuppressed.has(element)) continue;
|
|
2280
|
-
|
|
2424
|
+
const selection = {
|
|
2281
2425
|
element,
|
|
2282
2426
|
ariaCurrent: element.getAttribute("aria-current"),
|
|
2283
2427
|
threadSelected: element.getAttribute("data-app-action-sidebar-thread-selected"),
|
|
2428
|
+
hadPrimaryGhost: element.classList.contains("bg-primary-ghost-hover"),
|
|
2429
|
+
hadHoverPrimaryGhost: element.classList.contains("hover:bg-primary-ghost-hover"),
|
|
2284
2430
|
hadActiveClass: element.classList.contains("bg-token-list-hover-background"),
|
|
2285
2431
|
hadHoverClass: element.classList.contains("hover:bg-token-list-hover-background"),
|
|
2286
|
-
}
|
|
2432
|
+
};
|
|
2433
|
+
suppressedSelections.push(selection);
|
|
2287
2434
|
element.removeAttribute("aria-current");
|
|
2288
2435
|
element.removeAttribute("data-app-action-sidebar-thread-selected");
|
|
2436
|
+
// 原生选中态(灰底)现在由 bg-primary-ghost-hover 承载,需一并移除;
|
|
2437
|
+
// 旧 token 类仍保留处理,以便兼容旧主题。
|
|
2438
|
+
element.classList.remove("bg-primary-ghost-hover");
|
|
2289
2439
|
element.classList.remove("bg-token-list-hover-background");
|
|
2440
|
+
if (!selection.hadHoverPrimaryGhost) element.classList.add("hover:bg-primary-ghost-hover");
|
|
2290
2441
|
element.classList.add("hover:bg-token-list-hover-background");
|
|
2291
2442
|
}
|
|
2292
2443
|
}
|
|
@@ -2299,6 +2450,8 @@ export function createInjectionSource(features, {
|
|
|
2299
2450
|
if (selection.threadSelected !== null) {
|
|
2300
2451
|
element.setAttribute("data-app-action-sidebar-thread-selected", selection.threadSelected);
|
|
2301
2452
|
}
|
|
2453
|
+
element.classList.toggle("bg-primary-ghost-hover", Boolean(selection.hadPrimaryGhost));
|
|
2454
|
+
element.classList.toggle("hover:bg-primary-ghost-hover", Boolean(selection.hadHoverPrimaryGhost));
|
|
2302
2455
|
element.classList.toggle("bg-token-list-hover-background", selection.hadActiveClass);
|
|
2303
2456
|
element.classList.toggle("hover:bg-token-list-hover-background", selection.hadHoverClass);
|
|
2304
2457
|
}
|
|
@@ -2310,6 +2463,7 @@ export function createInjectionSource(features, {
|
|
|
2310
2463
|
const entry = findEntry(feature.id);
|
|
2311
2464
|
if (!entry) continue;
|
|
2312
2465
|
const selected = feature.id === activePageFeatureId;
|
|
2466
|
+
entry.classList.toggle("bg-primary-ghost-hover", selected);
|
|
2313
2467
|
entry.classList.toggle("bg-token-list-hover-background", selected);
|
|
2314
2468
|
entry.classList.toggle("hover:bg-token-list-hover-background", !selected);
|
|
2315
2469
|
if (selected) entry.setAttribute("aria-current", "page");
|