Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions docs/DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,12 @@ AI 打标签的建议在应用或放弃前一直存着,刷新或重开分拣
- 内置播放框的 UP 标签行只给关注数据里有的 UP:在关注的可以加标签;已取消关注的只显示原来的标签、没有「+ 标签」;从没关注过的整行不显示。为什么:UP 标签挂在关注列表的 UP 上,没关注的人没有地方挂;另存一份「打了标签但没关注的 UP」会多出一套看不见、不跟着刷新的数据。视频投稿同理反过来:那些视频不在收藏夹,只能给 UP 打标签,不能给视频打。
- B站 自动连播到下一个视频时,两种模式的内置播放框都跟着它:粉色卡片、标签行和 T 都换到新视频。关注里认不出新视频的 UP(不在视频投稿、也不在 UP 卡片的最近投稿里)时,UP 标签行不显示,T 不做事。为什么:留在前一个视频上,T 会给前一个 UP 打标签。

### 专注模式

- 右上角的图标按钮是 36×36 的正圆,按钮组的右边缘和字幕栏的右边缘对齐。
- 字幕行的时间戳比正文轻:`--mdg-faint`、常规字重、等宽数字。
- 设置面板里的控件都是 28px 高;「跟随」「章节」是勾选框加文字,外面不套框。

### B站 页面上的标记

#### 定下来的决定(改之前先问用户)
Expand Down Expand Up @@ -359,6 +365,9 @@ B站 页面上的 AI 判断照上表:值得留绿、可清理红、拿不准

- 设置页各节按这个顺序排:读字幕、笔记格式、观看进度、AI 平台、分拣台、MCP、Obsidian、数据与存储、高级。用到 AI 的三节(AI 平台、分拣台、MCP)挨在一起,和 AI 无关的观看进度排在它们前面;MCP 排在分拣台后面,因为它的开关管分拣台和收藏。为什么:按和 AI 有没有关系分组,找 AI 相关的设置不用跳着看(2026-11-10 用户定)。
- 设置页「AI 平台」的「视频」「网页」是页签,照 B站 空间页的页签:16px,当前的加粗、下面 3px 粉线,旁边小灰字写用在哪(「B站 · YouTube」「其他网站」),一次只显示一组;左右方向键切换。每次打开设置页在「视频」。为什么:两组的项同名,摆在一起分不清在改哪一组(2026-10-22 用户定)。
- 设置页的输入框、下拉框和同一行里的按钮都是 32px 高(`--control-h`)。左侧目录的当前项照「颜色」表:灰底、左边一道粉线、字是 `--text`。
- 设置页 Obsidian 的「测试连接」在 Key 输入框右边,结果写在「Local REST API Key」名字下面(成功绿字、失败红字),没测过时不占位置。2026-11-14 用户定:填完 Key 手就在那里,也和 Obsidian 插件自己「左名字右输入框」的设置页对得上。
- 弹窗里能滚动的框(字幕预览)有边框,不能滚动的(「详情」)只有底色。2026-11-14 用户定:边框表示这里可以滚动。

#### 定下来的决定(改之前先问用户)

Expand All @@ -374,12 +383,15 @@ B站 页面上的 AI 判断照上表:值得留绿、可清理红、拿不准
- 1024 宽时,第 2 行的搜索框和按钮换到页签下面一行。720 宽时没有左栏:左栏变成顶栏的下拉框(选项带数量),⚙ 放到第 2 行最后。
- 头部收起:第 2 行最前面有一个按钮,展开时是 ▴「收起头部」,收起时是 ▾「展开头部」,只有它收起和展开头部。收起后是一条细栏,只剩「名字 · 数量」、第 2 行的页签和右边的搜索 / 刷新 / 导出,没有封面,细栏自己是一张圆角白卡,上面留的空和展开时一样。滚动、回到顶上、焦点进到头部都不改它;切换收藏夹、页签和模式也不改。两种模式各记各的,重开分拣台后照旧;切到另一种模式时,它的收起状态当场生效,和重开分拣台一样不播动画。列表滚动后头部下沿出现阴影(展开时在第 4 行下面,收起时在细栏下面),滚回顶上就消失,说明卡片在头部底下;阴影不改收起状态。列表从头部底下穿过,收起和展开只是平移和淡出,卡片不跳;内置播放框的上沿跟着头部的下沿走。收起和展开用 0.15 秒,系统设了减少动态效果就不动画。760 及以下一样。选中栏和弹窗不管头部收没收,窗口矮也不特殊处理。不设快捷键:它是偶尔才改的布局开关,不是分拣时一直要按的。
- 内置播放框(点卡片后在右边打开的 B站 页面)没有顶栏。从上往下是:收藏夹的「视频标签」行、「UP 标签」行,然后是 B站 页面。关闭是播放框右上角骑在边框上的圆形 ×(`#viewerCloseBtn`,一半在框外,tooltip「关闭播放(Esc)」),或者按 Esc。标签行右边留出空,× 不压住标签。760 及以下内置播放框占掉列表的位置,× 还在同一个角上。
- 封面上只放时长、观看进度和「看完了」,不放 AI 判断。2026-11-14 用户定:判断行的徽标和右边按钮的颜色已经在说同一个结论。
- 当前卡片(键盘和鼠标所在的那张)只有 2px 深色框,没有阴影,和选中、播放两种状态一样只靠框。AI 没给判断时「保留」和「取消收藏」是同一种按钮样子。
- 关注的 UP 卡片和收藏夹卡片同一套间距(卡片之间 12px、内边距 12px)。关注列表上面的普通提示只有灰字和按钮,没有框;警告才有琥珀框。

#### 定下来的决定(改之前先问用户)

- 第 3、4 行开头有灰色大字「状态」「标签」,行与行之间有间距和细线。为什么:宽屏下一行两头离得太远,两行胶囊容易看混。
- 第 3 行「全部」后面有竖线,组和组之间也有竖线。
- 卡片上不放勾选框:蓝框加蓝底已经够看出选中,圆勾在小封面上会压住 AI 判断标签和「看到 X%」标签(2026-10-09 去掉)。
- 卡片上不放勾选框:蓝框加蓝底已经够看出选中,圆勾在小封面上会压住 AI 判断标签和「看到 X%」标签(2026-10-09 去掉;封面上的 AI 判断标签 2026-11-14 也去掉了)。
- 头部只由按钮收起和展开,不随滚动变(2026-10-14 用户定);封面不缩,静态排版不变。为什么:屏幕高度留给卡片,同时随时能操作筛选。头部放的是排序、筛选、标签这些长期设置,收不收由你定,跟着滚动自己变反而打断你。
- 内置播放框的关闭是右上角骑在边框上的圆形 ×,不放在标签行末尾(会像关闭那一行)。

Expand All @@ -389,7 +401,8 @@ B站 页面上的 AI 判断照上表:值得留绿、可清理红、拿不准

- 头部三行是一张白卡,和分拣台的一样(`--surface` 底、`--border` 描边、`--radius-lg` 圆角),上面留 14px、左右 16px(600 及以下都是 8px),行与行之间一道 `--border` 细线。第 2、3 行开头的行名、筛选片、右边的按钮和分拣台第 3、4 行一样。
- 卡片是分拣台的卡片:`--radius-lg` 圆角,卡片之间 12px,选中是蓝框加蓝底。标题 15px、字重 500,信息行 `--faint` 12px。星标单独一列,标题、信息行和正文左边对齐;★ 用 `--star` 黄,对着标题第一行居中。
- 卡片右上角的按钮是两列一样宽的网格,继续问是灰底;「删除 AI 对话」是 `.quiet` 红字。
- 卡片右上角的按钮是两列一样宽的网格,继续问是灰底;「删除 AI 对话」是 `.quiet` 红字,12px、22px 高,和同一行的「查看 N 轮问答」一样大。
- 第 1 行的状态文字和弹窗的状态行是同一套:进行中是转圈,失败是红框,其余是绿点加粗。2026-11-14 用户定。
- 「全选」跟在第 2 行的状态片后面、同一行最右,放不下才换到下一行靠右。为什么:分拣台 760 及以下让状态片占满一行、按钮另起一行,是因为它的状态片多;摘读记录只有两三个,另起一行会空出一条。2026-10-22 用户定
- 760 及以下:两行按钮挪到正文和问答那一行下面,从正文左边开始,标题占满整行;「删除 AI 对话」照旧在问答那一行最右。第 1 行放不下时,搜索框和「清空全部 AI 对话」一起换到下一行,搜索框占满剩下的宽度。

Expand Down
8 changes: 4 additions & 4 deletions extension/badges.css
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ span.mdg-badge.mdg-above { display: flex !important; max-width: 100%; margin: 0
gap: 8px;
margin-top: 8px;
padding: 6px 10px;
border-left: 3px solid #7c3ed1;
border-radius: 6px;
border-left: 2px solid #7c3ed1;
border-radius: 0 6px 6px 0;
background: rgba(124, 62, 209, 0.07);
font-size: 15px;
line-height: 22px;
Expand Down Expand Up @@ -186,8 +186,8 @@ span.mdg-ups.mdg-ups-line[data-mid] { display: flex !important; max-width: 100%;
gap: 6px;
margin-bottom: 8px;
padding: 8px 12px;
border-left: 3px solid #7c3ed1;
border-radius: 6px;
border-left: 2px solid #7c3ed1;
border-radius: 0 6px 6px 0;
background: var(--bg1, #fff);
color: var(--text2, #61666d);
font: 13px/18px -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", sans-serif;
Expand Down
41 changes: 18 additions & 23 deletions extension/content.css
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ html[data-mdg-reader-mode="1"][data-mdg-reader-theme="dark"] {
display: flex;
inset: 0;
justify-content: center;
padding: 18px;
padding: var(--mdg-space-4);
position: fixed;
z-index: 2147483647;
}
Expand All @@ -271,17 +271,17 @@ html[data-mdg-reader-mode="1"][data-mdg-reader-theme="dark"] {
background: var(--mdg-surface);
border: 1px solid var(--mdg-border);
border-radius: var(--mdg-radius-lg);
box-shadow: 0 20px 60px rgba(15, 23, 42, 0.22);
box-shadow: var(--mdg-lift);
color: var(--mdg-text);
font-family: var(--mdg-font-sans);
max-width: 360px;
padding: 18px;
width: calc(100vw - 36px);
padding: var(--mdg-space-4);
width: calc(100vw - 32px);
}

.mdg-confirm-title {
font-size: var(--mdg-fs-lg);
font-weight: 700;
font-weight: 600;
margin-bottom: var(--mdg-space-2);
}

Expand All @@ -300,19 +300,19 @@ html[data-mdg-reader-mode="1"][data-mdg-reader-theme="dark"] {
line-height: 1.45;
max-height: 96px;
overflow: auto;
padding: 9px 10px;
padding: var(--mdg-space-2) var(--mdg-space-3);
word-break: break-all;
}

.mdg-confirm-actions {
display: flex;
gap: var(--mdg-space-2);
justify-content: flex-end;
margin-top: 14px;
margin-top: var(--mdg-space-4);
}

.mdg-confirm-actions button {
height: 34px;
height: 32px;
padding: 0 14px;
}

Expand Down Expand Up @@ -388,7 +388,7 @@ html[data-mdg-reader-mode="1"][data-mdg-reader-theme="dark"] {
background: var(--mdg-warn-bg);
border: 1px solid var(--mdg-warn-border);
border-radius: var(--mdg-radius-md);
box-shadow: 0 12px 32px rgba(15, 23, 42, 0.18);
box-shadow: var(--mdg-shadow-float);
color: var(--mdg-warn);
font-family: var(--mdg-font-sans);
font-size: var(--mdg-fs-sm);
Expand Down Expand Up @@ -581,7 +581,6 @@ body[data-mdg-reader-mode="1"] .mdg-reading-actions {
gap: 10px;
flex-wrap: wrap;
justify-content: flex-end;
margin-right: -20px;
margin-top: -8px;
pointer-events: auto;
transition: opacity 0.2s ease;
Expand All @@ -606,10 +605,9 @@ body[data-mdg-reader-mode="1"] .mdg-reading-icon-btn {
display: inline-flex;
align-items: center;
justify-content: center;
width: 34px;
height: 34px;
min-height: 36px;
padding: 0 14px;
width: 36px;
height: 36px;
padding: 0;
border: 1px solid var(--mdg-border);
border-radius: 999px;
background: var(--mdg-surface);
Expand Down Expand Up @@ -747,11 +745,7 @@ body[data-mdg-reader-mode="1"] .mdg-reading-toggle {
align-items: center;
gap: 6px;
width: fit-content;
min-height: 32px;
padding: 0 11px;
border: 1px solid var(--mdg-border);
border-radius: 999px;
background: var(--mdg-surface);
min-height: 28px;
color: var(--mdg-text);
font-size: var(--mdg-fs-xs);
box-sizing: border-box;
Expand All @@ -765,11 +759,11 @@ body[data-mdg-reader-mode="1"] .mdg-reading-toggle input {
body[data-mdg-reader-mode="1"] .mdg-reading-select {
width: auto;
min-width: 118px;
min-height: 36px;
min-height: 28px;
margin: 0;
padding: 0 12px;
border: 1px solid var(--mdg-border);
border-radius: 999px;
border-radius: var(--mdg-radius-md);
background: var(--mdg-surface);
color: var(--mdg-text);
font-size: var(--mdg-fs-xs);
Expand Down Expand Up @@ -935,8 +929,9 @@ body[data-mdg-reader-mode="1"] .mdg-reading-item.is-active {

body[data-mdg-reader-mode="1"] .mdg-reading-time {
font-size: var(--mdg-reader-transcript-font-size);
font-weight: 600;
color: var(--mdg-text) !important;
font-weight: 400;
font-variant-numeric: tabular-nums;
color: var(--mdg-faint) !important;
padding-top: 2px;
line-height: 1.4;
}
Expand Down
16 changes: 10 additions & 6 deletions extension/history/history.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,19 @@ body { padding: 14px 16px 0; }
.rec-head, .records { max-width: 1200px; margin: 0 auto; }

/* ---------- the head: one white card as the 分拣台's, rows split by its thin rules (DESIGN 视觉设计 · 分拣台) ---------- */
.rec-head { border: 1px solid var(--border); border-radius: var(--radius-lg); background: var(--surface); box-shadow: 0 1px 2px rgba(16, 24, 40, 0.05); }
.rec-head { border: 1px solid var(--border); border-radius: var(--radius-lg); background: var(--surface); }
.rec-head > * { padding: 8px 16px; }
.rec-head > * + * { border-top: 1px solid var(--border); }
.rec-row1 { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; padding-block: 12px; }
/* The search and 清空全部 wrap as one, so the rule never starts a line. */
.rec-find { display: flex; align-items: center; gap: 12px; margin-left: auto; }
.status { color: var(--muted); font-size: var(--fs-xs); }
.status { display: inline-flex; align-items: baseline; gap: 5px; color: var(--ok); font-size: var(--fs-xs); font-weight: 600; }
.status:empty { display: none; }
.status.is-error { color: var(--danger); }
.status::before { content: ""; flex: none; width: 6px; height: 6px; border-radius: 50%; background: currentColor; transform: translateY(-1px); }
.status[aria-busy="true"] { border: 0; background: none; font-weight: 400; }
.status[aria-busy="true"]::before { width: 0.9em; height: 0.9em; margin: 0; background: none; transform: translateY(0.1em); }
.status.is-error { padding: 3px var(--space-2); border: 1px solid var(--danger-border); border-radius: var(--radius-sm); background: var(--danger-bg); color: var(--danger); font-weight: 400; }
.status.is-error::before { content: none; }
/* 清空全部 AI 对话: red text, no frame, a thin rule between it and the search. */
.rec-row1 .danger { position: relative; margin-left: 9px; border-color: transparent; background: none; color: var(--danger); }
.rec-row1 .danger:hover { background: var(--danger-bg); }
Expand Down Expand Up @@ -70,13 +74,13 @@ summary { cursor: pointer; color: var(--text-2); font-size: var(--fs-xs); }

/* Two rows of two equal columns, right-aligned: 继续问 and 复制 Markdown beside the title, 下载 .md and 写入 Obsidian beside
the meta line. */
.entry-acts { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; margin-left: 8px; }
.entry-acts { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-2); margin-left: 8px; }
.entry-acts button { width: 100%; }
/* The 「查看 N 轮问答」 line under the body and the buttons, 删除 AI 对话 at its right end (red text, no frame) and staying
on that line when the 问答 open. */
.entry > .qa { grid-row: 2; grid-column: 2 / -1; display: flex; align-items: flex-start; gap: 8px; }
.qa > details { flex: 1; min-width: 0; }
.qa > [data-act="delete"] { margin-top: -1px; color: var(--danger); }
.qa > [data-act="delete"] { height: 22px; color: var(--danger); font-size: var(--fs-xs); }
.qa > [data-act="delete"]:hover { background: var(--danger-bg); color: var(--danger); }
/* 继续问 is each card's main action: a gray fill with plain text (buttons never use blue text, DESIGN 视觉设计 · 颜色). */
button.ask { background: var(--field-bg); }
Expand All @@ -91,7 +95,7 @@ button:disabled:has(> .write-label [aria-busy="true"]) { opacity: 0.7; cursor: p
.rec-find { flex: 1 1 320px; min-width: 0; }
.rec-find .search { flex: 1 1 auto; width: auto; min-width: 0; }
/* The buttons go under the body, from its left edge, so nothing squeezes the title. */
.entry-acts { grid-row: 3; grid-column: 2; justify-self: start; margin: 10px 0 0; }
.entry-acts { grid-row: 3; grid-column: 2; justify-self: start; margin: var(--space-2) 0 0; }
}
@media (max-width: 600px) {
body { padding: 8px 8px 0; }
Expand Down
10 changes: 6 additions & 4 deletions extension/history/history.js
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,8 @@ function aiProviderId() {
}
}
const RECENT_CHECK = "在记录上逐个看,不对的按 T 或点「+ 标签」改";
const aiProgress = (text) => (TagDialogs.ai.progress(aiTags, text), setStatus(text));
// A batch's line (「AI 正在处理第 1 批…」, a wait) does not start with 正在 but is still in progress.
const aiProgress = (text) => (TagDialogs.ai.progress(aiTags, text), setStatus(text, false, null, true));
const aiTags = {
who: "记录",
sees: `标题、是视频还是网页、现有标签和你与 AI 的对话(问和答,每条记录最多 ${UI.READING_AI_CHARS} 字);没有对话的记录看分拣台的 AI 总结和备注`,
Expand Down Expand Up @@ -385,7 +386,8 @@ async function runAi({ instruction, scope, allowRemove }) {
const last = r.errors.at(-1);
// A stop for a setup or access error says so with its remedy, the dialog open or not, as the 分拣台's banner.
if (r.error) setStatus(r.proposal ? last : UI.aiTagsFailed(last), true, aiRemedy(r));
else if (open) return;
// The dialog shows the result; the last batch's line is over.
else if (open) return setStatus("");
else if (r.proposal) setStatus("AI 打标签已完成,按 I 或点「✦ AI 打标签」确认建议");
else setStatus(UI.aiTagsFailed(last), true);
}
Expand Down Expand Up @@ -642,14 +644,14 @@ function render() {

// 「正在…」 lines are in progress: aria-busy grays them (tokens.css) until the result replaces them.
// error: a failure the user must handle (red); action: { label, run }, its remedy button after the text.
function setStatus(text, error = false, action = null) {
function setStatus(text, error = false, action = null, busy = text.startsWith("正在")) {
els.status.textContent = text;
if (action) {
const btn = Object.assign(document.createElement("button"), { type: "button", className: "act-btn", textContent: action.label, onclick: action.run });
els.status.append(" ", btn);
}
els.status.classList.toggle("is-error", error);
if (text.startsWith("正在")) els.status.setAttribute("aria-busy", "true");
if (busy) els.status.setAttribute("aria-busy", "true");
else els.status.removeAttribute("aria-busy");
}

Expand Down
Loading
Loading