dsh-conversation-aurora 0.2.0 → 0.2.5
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.
- package/README.md +4 -3
- package/client.js +90 -23
- package/locale/en.json +1 -1
- package/locale/zh.json +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -30,12 +30,13 @@
|
|
|
30
30
|
|
|
31
31
|
| 快捷键 | 作用 |
|
|
32
32
|
| --- | --- |
|
|
33
|
-
| `Alt+T` |
|
|
33
|
+
| `Alt+T` | 换到下一个背景,并**固定**住(8 个循环,选择会记住) |
|
|
34
|
+
| `Alt+R` | 回到**随机**,并立刻换一个(清掉固定值) |
|
|
34
35
|
| `Alt+D` | 浅色 / 深色主题互换(走宿主 `theme.setTheme`,与「设置 → 外观」同步) |
|
|
35
36
|
|
|
36
37
|
**它只在"你干活"的时候出现**:任何工具在跑、或回合进行中,背景才播放;空闲、切会话、窗口隐藏时立刻停掉 `requestAnimationFrame` 并淡出,两侧恢复普通白纸。
|
|
37
38
|
|
|
38
|
-
|
|
39
|
+
**每个回合随机一个主题**:你发一条消息、我把这一轮做完 = 一个回合;回合内背景不变(中间停顿多久都不换),下一个回合重新随机,且不会和上一个重复。`Alt+T` 固定某个主题,`Alt+R` 回到随机并换一个。固定值存在 `localStorage` 的 `dsh.conversation-aurora.theme`。
|
|
39
40
|
|
|
40
41
|
---
|
|
41
42
|
|
|
@@ -82,7 +83,7 @@
|
|
|
82
83
|
|
|
83
84
|
## 已知限制
|
|
84
85
|
|
|
85
|
-
1. **依赖宿主的 DOM 语义属性**:`[data-conversation-content]` / `[data-tool][data-state]` / `[data-chat-running]` / `[data-streaming]
|
|
86
|
+
1. **依赖宿主的 DOM 语义属性**:`[data-conversation-content]` / `[data-tool][data-state]` / `[data-chat-running]` / `[data-streaming]`。DSH 大版本升级后如果这些改名,插件会安静地什么都不做(不会报错、不会挡交互)。
|
|
86
87
|
2. **没有"背景层"插槽**:DSH 目前没有这个扩展点,所以背景层是挂在对话画布元素内部的(`z-index:-1`)。这是刻意偏离「只能注册进 slot」的地方,随插件停用一起消失。
|
|
87
88
|
3. **切会话会静默 600ms**:避免把上一轮残留的工具行当成"正在工作",看到几秒特效。
|
|
88
89
|
4. **减少动态效果**:系统开启后只画一帧静止画面,不跑 `requestAnimationFrame`。
|
package/client.js
CHANGED
|
@@ -28,6 +28,10 @@ window.__ModuleLoader__.load({
|
|
|
28
28
|
remountWindowMs: 2000,
|
|
29
29
|
/** 切会话后的静默期,避免把上一轮的残留行当成"正在工作"。 */
|
|
30
30
|
switchQuietMs: 600,
|
|
31
|
+
/** Alt+T 换主题。 */
|
|
32
|
+
themeKey: 't',
|
|
33
|
+
/** Alt+R 回到随机,并给这个回合换一个。 */
|
|
34
|
+
randomKey: 'r',
|
|
31
35
|
};
|
|
32
36
|
|
|
33
37
|
const NS = 'dsh-stage';
|
|
@@ -97,15 +101,6 @@ body[data-ds-dark-theme] .dsh-stage__veil{
|
|
|
97
101
|
}
|
|
98
102
|
}
|
|
99
103
|
|
|
100
|
-
function hashString(text) {
|
|
101
|
-
let h = 2166136261;
|
|
102
|
-
for (let i = 0; i < text.length; i += 1) {
|
|
103
|
-
h ^= text.charCodeAt(i);
|
|
104
|
-
h = Math.imul(h, 16777619);
|
|
105
|
-
}
|
|
106
|
-
return h >>> 0;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
104
|
/** 浅色用墨色 + multiply;深色用亮色 + lighter。 */
|
|
110
105
|
function stagePalette() {
|
|
111
106
|
const dark = document.body.hasAttribute('data-ds-dark-theme');
|
|
@@ -760,6 +755,7 @@ function themeWarp(g) {
|
|
|
760
755
|
let sessionKey = null;
|
|
761
756
|
let quietUntil = 0;
|
|
762
757
|
let forcedTheme = readStore(STORAGE.theme, '');
|
|
758
|
+
let activeTheme = '';
|
|
763
759
|
let stageRaf = 0;
|
|
764
760
|
let stageTheme = null;
|
|
765
761
|
|
|
@@ -794,9 +790,28 @@ function themeWarp(g) {
|
|
|
794
790
|
if (previous !== canvas) resetForSwitch(previous !== null);
|
|
795
791
|
}
|
|
796
792
|
|
|
793
|
+
/**
|
|
794
|
+
* 回合的起点:新的 [data-streaming] / [data-chat-running] 元素出现,
|
|
795
|
+
* 或者从空闲重新开工。两者任一成立就算新回合,换一个主题。
|
|
796
|
+
*/
|
|
797
|
+
const turnMarks = new WeakSet();
|
|
798
|
+
|
|
799
|
+
function turnIsNew(running) {
|
|
800
|
+
let fresh = false;
|
|
801
|
+
const list = document.querySelectorAll('[data-streaming], [data-chat-running]');
|
|
802
|
+
for (let i = 0; i < list.length; i += 1) {
|
|
803
|
+
const el = list[i];
|
|
804
|
+
if (!turnMarks.has(el)) {
|
|
805
|
+
turnMarks.add(el);
|
|
806
|
+
fresh = true;
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
return running && (fresh || !busy);
|
|
810
|
+
}
|
|
811
|
+
|
|
797
812
|
/**
|
|
798
813
|
* 切会话:上一轮的工具行可能还挂着,历史里的失败行也会被当成新事件。
|
|
799
|
-
*
|
|
814
|
+
* 清空跟踪表、静默一小段时间,等新会话渲染稳定;顺便取该对话的主题。
|
|
800
815
|
*/
|
|
801
816
|
function resetForSwitch(quiet) {
|
|
802
817
|
tracked.clear();
|
|
@@ -807,6 +822,7 @@ function themeWarp(g) {
|
|
|
807
822
|
}
|
|
808
823
|
quietUntil = quiet ? Date.now() + TUNE.switchQuietMs : 0;
|
|
809
824
|
sessionKey = host ? host.getAttribute('data-conversation-session') || '' : null;
|
|
825
|
+
activeTheme = '';
|
|
810
826
|
syncStage();
|
|
811
827
|
}
|
|
812
828
|
|
|
@@ -870,12 +886,31 @@ function themeWarp(g) {
|
|
|
870
886
|
|
|
871
887
|
/* ---------- 背景播放 ---------- */
|
|
872
888
|
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
889
|
+
/**
|
|
890
|
+
* 主题跟着「回合」走:一个回合一个主题,回合内怎么停顿都不变,
|
|
891
|
+
* 下一个回合(你发新消息)重新随机。
|
|
892
|
+
* 按 Alt+T 固定过主题时,所有回合都用它。
|
|
893
|
+
*/
|
|
894
|
+
let lastAssigned = '';
|
|
895
|
+
|
|
896
|
+
function themeIds() {
|
|
897
|
+
const ids = [];
|
|
898
|
+
for (let i = 0; i < STAGE_THEMES.length; i += 1) ids.push(STAGE_THEMES[i].id);
|
|
899
|
+
return ids;
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
/** 随机挑一个,尽量不要和上一个回合重复。 */
|
|
903
|
+
function randomThemeId() {
|
|
904
|
+
const ids = themeIds();
|
|
905
|
+
let id = ids[(Math.random() * ids.length) | 0];
|
|
906
|
+
if (ids.length > 1 && id === lastAssigned) id = ids[(ids.indexOf(id) + 1) % ids.length];
|
|
907
|
+
lastAssigned = id;
|
|
908
|
+
return id;
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
/** 这个回合该用哪个主题(固定值优先)。 */
|
|
912
|
+
function themeForTurn() {
|
|
913
|
+
return forcedTheme || activeTheme || (activeTheme = randomThemeId());
|
|
879
914
|
}
|
|
880
915
|
|
|
881
916
|
function stopStage() {
|
|
@@ -903,7 +938,9 @@ function themeWarp(g) {
|
|
|
903
938
|
const pal = stagePalette();
|
|
904
939
|
ctx.globalCompositeOperation = pal.blend;
|
|
905
940
|
|
|
906
|
-
const id =
|
|
941
|
+
const id = themeForTurn();
|
|
942
|
+
activeTheme = id;
|
|
943
|
+
stage.dataset.theme = id;
|
|
907
944
|
let factory = STAGE_THEMES[0];
|
|
908
945
|
for (let i = 0; i < STAGE_THEMES.length; i += 1) {
|
|
909
946
|
if (STAGE_THEMES[i].id === id) factory = STAGE_THEMES[i];
|
|
@@ -941,13 +978,31 @@ function themeWarp(g) {
|
|
|
941
978
|
if (!stageRaf) startStage();
|
|
942
979
|
}
|
|
943
980
|
|
|
981
|
+
/** Alt+T:手动切到下一个,并固定住。 */
|
|
944
982
|
function cycleTheme() {
|
|
945
|
-
const ids =
|
|
946
|
-
for (let i = 0; i < STAGE_THEMES.length; i += 1) ids.push(STAGE_THEMES[i].id);
|
|
983
|
+
const ids = themeIds();
|
|
947
984
|
let at = ids.indexOf(forcedTheme);
|
|
948
|
-
if (at < 0) at = ids.indexOf(
|
|
985
|
+
if (at < 0) at = ids.indexOf(activeTheme);
|
|
986
|
+
if (at < 0) at = 0;
|
|
949
987
|
forcedTheme = ids[(at + 1) % ids.length];
|
|
950
988
|
writeStore(STORAGE.theme, forcedTheme);
|
|
989
|
+
activeTheme = forcedTheme;
|
|
990
|
+
restartIfPlaying();
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
/** Alt+R:回到随机,并给这个回合换一个新的。 */
|
|
994
|
+
function randomTheme() {
|
|
995
|
+
forcedTheme = '';
|
|
996
|
+
try {
|
|
997
|
+
window.localStorage.removeItem(STORAGE.theme);
|
|
998
|
+
} catch {
|
|
999
|
+
/* 隐私模式:本来就没写进去 */
|
|
1000
|
+
}
|
|
1001
|
+
activeTheme = randomThemeId();
|
|
1002
|
+
restartIfPlaying();
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
function restartIfPlaying() {
|
|
951
1006
|
if (stageRaf || busy) {
|
|
952
1007
|
stopStage();
|
|
953
1008
|
if (busy && !document.hidden) startStage();
|
|
@@ -975,7 +1030,15 @@ function themeWarp(g) {
|
|
|
975
1030
|
}
|
|
976
1031
|
|
|
977
1032
|
prune();
|
|
978
|
-
|
|
1033
|
+
const running = detectBusy();
|
|
1034
|
+
if (turnIsNew(running)) {
|
|
1035
|
+
activeTheme = forcedTheme || randomThemeId();
|
|
1036
|
+
if (stageRaf) {
|
|
1037
|
+
stopStage();
|
|
1038
|
+
startStage();
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
setBusy(running);
|
|
979
1042
|
} catch {
|
|
980
1043
|
/* 任何一步失败都只是不生效,不影响宿主 */
|
|
981
1044
|
}
|
|
@@ -1029,8 +1092,12 @@ function themeWarp(g) {
|
|
|
1029
1092
|
|
|
1030
1093
|
function onKeyDown(event) {
|
|
1031
1094
|
if (!event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) return;
|
|
1032
|
-
|
|
1033
|
-
|
|
1095
|
+
const key = String(event.key || '').toLowerCase();
|
|
1096
|
+
if (key === TUNE.themeKey) {
|
|
1097
|
+
cycleTheme();
|
|
1098
|
+
return;
|
|
1099
|
+
}
|
|
1100
|
+
if (key === TUNE.randomKey) randomTheme();
|
|
1034
1101
|
}
|
|
1035
1102
|
|
|
1036
1103
|
/* ---------- 启动 ---------- */
|
package/locale/en.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"meta": {
|
|
3
3
|
"title": "Conversation Backgrounds",
|
|
4
|
-
"description": "Full-canvas animated backgrounds: starfield / code rain / circuit / cat / girl / racer / snow / bubbles. Alt+T
|
|
4
|
+
"description": "Full-canvas animated backgrounds: starfield / code rain / circuit / cat / girl / racer / snow / bubbles. One random theme per turn, stable within the turn. Alt+T pins a theme, Alt+R back to random, Alt+D light/dark."
|
|
5
5
|
}
|
|
6
6
|
}
|
package/locale/zh.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"meta": {
|
|
3
3
|
"title": "对话区动效背景",
|
|
4
|
-
"description": "对话区整屏动效背景:星空 / 代码雨 / 电路 / 小猫 / 小女生 / 赛车 / 飘雪 /
|
|
4
|
+
"description": "对话区整屏动效背景:星空 / 代码雨 / 电路 / 小猫 / 小女生 / 赛车 / 飘雪 / 肥皂泡。每个回合随机一个,回合内不变。Alt+T 固定主题、Alt+R 回到随机,Alt+D 切明暗。"
|
|
5
5
|
}
|
|
6
6
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-conversation-aurora",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"description": "Full-canvas animated backgrounds for the DSH conversation pane: starfield, code rain, circuits, cat, girl, racer, snow, bubbles.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|