feat: 新增动态页 - #494
Conversation
✅ Deploy Preview for demo-firefly ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Reviewer's Guide添加了一个全新的动态/瞬间功能:专用页面、侧边栏小组件、内容集合、创建脚本、i18n 文案和 API;同时优化分页的样式/行为,并集成动态专属统计和评论路由。 动态内嵌评论的加载与主题切换序列图sequenceDiagram
participant User
participant DynamicInlineComments
participant ParentWindow as Parent_window
participant Iframe as Comments_iframe
User->>DynamicInlineComments: click data-comment-toggle
DynamicInlineComments->>DynamicInlineComments: toggle()
alt first_open
DynamicInlineComments->>DynamicInlineComments: load(panel)
DynamicInlineComments->>Iframe: create_iframe_src_/dynamic/comments
DynamicInlineComments->>Iframe: attach_load_listener
end
Iframe-->>DynamicInlineComments: load_event
DynamicInlineComments->>Iframe: postMessage type_dynamic-comment-theme
Iframe->>ParentWindow: postMessage type_dynamic-comment-height
ParentWindow->>DynamicInlineComments: message_event
DynamicInlineComments->>DynamicInlineComments: handleMessage()
DynamicInlineComments->>Iframe: set_height_via_style
ParentWindow->>Iframe: message_event_type_dynamic-comment-theme
Iframe->>Iframe: toggle_dark_class_and_dataset_theme
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your Experience访问你的 dashboard 以:
Getting HelpOriginal review guide in EnglishReviewer's GuideAdds a new dynamic/moments feature with a dedicated page, sidebar widget, content collection, creation script, i18n strings and API, while refining pagination styling/behavior and integrating dynamic-specific stats and comment routing. Sequence diagram for dynamic inline comments loading and themingsequenceDiagram
participant User
participant DynamicInlineComments
participant ParentWindow as Parent_window
participant Iframe as Comments_iframe
User->>DynamicInlineComments: click data-comment-toggle
DynamicInlineComments->>DynamicInlineComments: toggle()
alt first_open
DynamicInlineComments->>DynamicInlineComments: load(panel)
DynamicInlineComments->>Iframe: create_iframe_src_/dynamic/comments
DynamicInlineComments->>Iframe: attach_load_listener
end
Iframe-->>DynamicInlineComments: load_event
DynamicInlineComments->>Iframe: postMessage type_dynamic-comment-theme
Iframe->>ParentWindow: postMessage type_dynamic-comment-height
ParentWindow->>DynamicInlineComments: message_event
DynamicInlineComments->>DynamicInlineComments: handleMessage()
DynamicInlineComments->>Iframe: set_height_via_style
ParentWindow->>Iframe: message_event_type_dynamic-comment-theme
Iframe->>Iframe: toggle_dark_class_and_dataset_theme
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - 我发现了 4 个问题,并且给出了一些总体反馈:
DynamicFeed.svelte中的时区偏移格式化逻辑与date-utils中新的formatTimezoneOffset辅助函数重复;建议复用这个共享工具函数,以保持格式一致并避免重复代码。scripts/new-dynamic.js通过对siteConfig.ts源文件使用正则来解析时区,这种做法在配置重构时非常脆弱;与其抓取 TypeScript 源码,不如从一个小的 JSON/配置模块或环境变量中读取配置,会更加稳健。
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- `DynamicFeed.svelte` 中的时区偏移格式化逻辑与 `date-utils` 中新的 `formatTimezoneOffset` 辅助函数重复;建议复用这个共享工具函数,以保持格式一致并避免重复代码。
- `scripts/new-dynamic.js` 通过对 `siteConfig.ts` 源文件使用正则来解析时区,这种做法在配置重构时非常脆弱;与其抓取 TypeScript 源码,不如从一个小的 JSON/配置模块或环境变量中读取配置,会更加稳健。
## Individual Comments
### Comment 1
<location path="src/components/comment/Disqus.astro" line_range="21-24" />
<code_context>
<div id="disqus_thread"></div>
<script is:inline define:vars={{ shortname, identifier, url, title }}>
+ const requestedPath = new URLSearchParams(window.location.search).get("path")
+ if (requestedPath) {
+ identifier = requestedPath.replace(/^\/+|\/+$/g, "")
+ url = new URL(requestedPath, window.location.origin).href
+ }
// @ts-ignore
</code_context>
<issue_to_address>
**issue (bug_risk):** 由于 `identifier` 和 `url` 是通过 `define:vars` 注入的常量,重新赋值会失败。
因为 `define:vars` 在浏览器中会把这些绑定生成为 `const`,所以在存在 `requestedPath` 时重新给 `identifier` 和 `url` 赋值会抛出 `Assignment to constant variable`,从而阻止 Disqus 初始化。可以改为引入单独的可变本地变量(例如 `let effectiveIdentifier = identifier; let effectiveUrl = url;`),根据 `requestedPath` 更新这些变量,并在 `disqus_config` 中使用它们,而不是修改注入的常量。
</issue_to_address>
### Comment 2
<location path="src/components/pages/dynamic/DynamicFeed.svelte" line_range="143-152" />
<code_context>
+ history.replaceState(history.state, "", permalink);
+ });
+ });
+ const time = root.querySelector<HTMLTimeElement>("[data-dynamic-time]");
+ if (time) {
+ const date = new Date(entry.published);
+ time.dateTime = date.toISOString();
+ time.textContent = new Intl.DateTimeFormat(
+ document.documentElement.lang || undefined,
+ {
+ year: "numeric",
+ month: "2-digit",
+ day: "2-digit",
+ hour: "2-digit",
+ minute: "2-digit",
+ second: "2-digit",
+ },
+ ).format(date);
+ const timezoneName = new Intl.DateTimeFormat("en-US", {
+ timeZone: timezone,
+ timeZoneName: "longOffset",
+ })
+ .formatToParts(date)
+ .find((part) => part.type === "timeZoneName")?.value;
+ const timezoneLabel =
+ !timezoneName || timezoneName === "GMT"
+ ? "UTC"
</code_context>
<issue_to_address>
**suggestion:** `DynamicFeed` 中的时区格式化逻辑与 `formatTimezoneOffset` 重复,且未来可能出现差异。
目前的 `timezoneLabel` 逻辑(使用 `Intl.DateTimeFormat` 和字符串处理)与 `date-utils.ts` 中的 `formatTimezoneOffset` 功能重复,这会带来风险:如果将来只更新其中一个实现(例如处理非整点偏移或本地化变更),输出就会不一致。请通过复用 `formatTimezoneOffset` 或抽取一个供二者共享的辅助函数来集中管理这部分行为。
建议实现:
```
event.ctrlKey ||
event.shiftKey ||
event.altKey
)
return;
event.preventDefault();
event.stopPropagation();
history.replaceState(history.state, "", permalink);
});
});
const time = root.querySelector<HTMLTimeElement>("[data-dynamic-time]");
if (time) {
const date = new Date(entry.published);
time.dateTime = date.toISOString();
time.textContent = new Intl.DateTimeFormat(
document.documentElement.lang || undefined,
{
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
},
).format(date);
time.textContent += ` ${formatTimezoneOffset(timezone, date)}`;
}
const content = root.querySelector<HTMLElement>("[data-dynamic-content]");
if (content) {
content.id = `${anchorId}-content`;
```
1. 在 `DynamicFeed.svelte` 顶部添加对 `formatTimezoneOffset` 的导入,并使用指向 `date-utils.ts` 的正确相对路径,例如:
```ts
import { formatTimezoneOffset } from "../../../utils/date-utils";
```
根据你实际的项目结构调整路径。
2. 确认 `formatTimezoneOffset` 的函数签名与这里的用法一致。如果它目前只接受 `Date` 或只接受时区字符串(比如仅接受 `Date` 或仅接受时区 ID),请相应地调整调用 `formatTimezoneOffset(timezone, date)`,或者扩展 `date-utils.ts`,提供一个既能使用时区标识又能使用 `Date` 实例进行格式化的辅助函数。
3. 如果 `formatTimezoneOffset` 目前在其它地方的使用不带 `Date` 参数,可以考虑统一它的 API(例如 `formatTimezoneOffset(date: Date, timeZone?: string)`),并更新现有调用点,以保证整个应用中的行为一致。
</issue_to_address>
### Comment 3
<location path="src/config/sidebarConfig.ts" line_range="105-114" />
<code_context>
// 右侧边栏组件配置列表
rightComponents: [
+ {
+ // 组件类型:最新动态组件
+ type: "dynamic",
+ // 是否启用该组件
+ enable: true,
+ // 组件位置
+ position: "top",
+ // 是否在文章详情页显示
+ showOnPostPage: true,
+ // 组件专属配置
+ specificConfig: {
+ dynamic: {
+ // 显示的最新动态数量
+ limit: 2,
+ },
+ },
+ },
{
// 组件类型:站点统计组件
</code_context>
<issue_to_address>
**question (bug_risk):** `rightComponents` 中的 `dynamic` 小部件被配置了两次,可能导致重复的界面显示。
`rightComponents` 中存在两个 `dynamic` 条目,而且配置几乎完全相同(`enable: true`、`showOnPostPage: true`、`limit: 2`)。除非布局引擎对它们有特殊处理,否则这很可能会让该小部件被渲染两次。如果你并不希望重复显示,请移除其中一个条目,并根据需要调整剩余小部件的位置。
</issue_to_address>
### Comment 4
<location path="src/content/dynamic/2026-07-15-010756.md" line_range="7-13" />
<code_context>
+
+今天天气真不错,流萤真可爱。
+
+
+
+
+
+
+
+
</code_context>
<issue_to_address>
**nitpick:** 建议为每张图片使用更具描述性且彼此不同的替代文本,而不是重复使用 `图片一`。
目前所有图片都使用相同的替代文本。为了提升无障碍体验并支持屏幕阅读器,请为每张图片提供独立且具有描述性的替代文本,以体现它们各自的具体内容。
</issue_to_address>帮我变得更有用!请在每条评论上点 👍 或 👎,我会根据你的反馈改进后续的代码审查。
Original comment in English
Hey - I've found 4 issues, and left some high level feedback:
- The timezone offset formatting logic in DynamicFeed.svelte duplicates the new formatTimezoneOffset helper in date-utils; consider reusing the shared utility to keep formatting consistent and avoid duplicated code.
- scripts/new-dynamic.js parses timezone from siteConfig.ts using a regex on the source file, which is brittle to config refactors; it would be more robust to read from a small JSON/config module or environment variable instead of scraping TypeScript.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The timezone offset formatting logic in DynamicFeed.svelte duplicates the new formatTimezoneOffset helper in date-utils; consider reusing the shared utility to keep formatting consistent and avoid duplicated code.
- scripts/new-dynamic.js parses timezone from siteConfig.ts using a regex on the source file, which is brittle to config refactors; it would be more robust to read from a small JSON/config module or environment variable instead of scraping TypeScript.
## Individual Comments
### Comment 1
<location path="src/components/comment/Disqus.astro" line_range="21-24" />
<code_context>
<div id="disqus_thread"></div>
<script is:inline define:vars={{ shortname, identifier, url, title }}>
+ const requestedPath = new URLSearchParams(window.location.search).get("path")
+ if (requestedPath) {
+ identifier = requestedPath.replace(/^\/+|\/+$/g, "")
+ url = new URL(requestedPath, window.location.origin).href
+ }
// @ts-ignore
</code_context>
<issue_to_address>
**issue (bug_risk):** Reassigning `identifier` and `url` will fail because they are constants injected via `define:vars`.
Because `define:vars` emits these bindings as `const` in the browser, reassigning `identifier` and `url` when `requestedPath` is present will throw `Assignment to constant variable` and prevent Disqus from initializing. Instead, introduce separate mutable locals (e.g. `let effectiveIdentifier = identifier; let effectiveUrl = url;`), update those based on `requestedPath`, and use them inside `disqus_config` rather than modifying the injected constants.
</issue_to_address>
### Comment 2
<location path="src/components/pages/dynamic/DynamicFeed.svelte" line_range="143-152" />
<code_context>
+ history.replaceState(history.state, "", permalink);
+ });
+ });
+ const time = root.querySelector<HTMLTimeElement>("[data-dynamic-time]");
+ if (time) {
+ const date = new Date(entry.published);
+ time.dateTime = date.toISOString();
+ time.textContent = new Intl.DateTimeFormat(
+ document.documentElement.lang || undefined,
+ {
+ year: "numeric",
+ month: "2-digit",
+ day: "2-digit",
+ hour: "2-digit",
+ minute: "2-digit",
+ second: "2-digit",
+ },
+ ).format(date);
+ const timezoneName = new Intl.DateTimeFormat("en-US", {
+ timeZone: timezone,
+ timeZoneName: "longOffset",
+ })
+ .formatToParts(date)
+ .find((part) => part.type === "timeZoneName")?.value;
+ const timezoneLabel =
+ !timezoneName || timezoneName === "GMT"
+ ? "UTC"
</code_context>
<issue_to_address>
**suggestion:** Timezone formatting logic in `DynamicFeed` duplicates `formatTimezoneOffset` and could diverge over time.
The `timezoneLabel` logic (using `Intl.DateTimeFormat` and string manipulation) duplicates `formatTimezoneOffset` in `date-utils.ts`, which risks inconsistent output if only one is updated (e.g., for non-`:00` offsets or locale changes). Please centralize this behavior by reusing `formatTimezoneOffset` or extracting a shared helper used by both.
Suggested implementation:
```
event.ctrlKey ||
event.shiftKey ||
event.altKey
)
return;
event.preventDefault();
event.stopPropagation();
history.replaceState(history.state, "", permalink);
});
});
const time = root.querySelector<HTMLTimeElement>("[data-dynamic-time]");
if (time) {
const date = new Date(entry.published);
time.dateTime = date.toISOString();
time.textContent = new Intl.DateTimeFormat(
document.documentElement.lang || undefined,
{
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
},
).format(date);
time.textContent += ` ${formatTimezoneOffset(timezone, date)}`;
}
const content = root.querySelector<HTMLElement>("[data-dynamic-content]");
if (content) {
content.id = `${anchorId}-content`;
```
1. Add an import for `formatTimezoneOffset` at the top of `DynamicFeed.svelte`, using the correct relative path to `date-utils.ts`, for example:
```ts
import { formatTimezoneOffset } from "../../../utils/date-utils";
```
Adjust the path to match your actual project structure.
2. Ensure the `formatTimezoneOffset` signature matches the usage here. If it currently accepts a `Date` or timezone string differently (e.g., only a `Date` or only a timezone ID), update the call `formatTimezoneOffset(timezone, date)` accordingly, or extend `date-utils.ts` to expose a helper that can format using both the timezone identifier and the `Date` instance.
3. If `formatTimezoneOffset` is currently used elsewhere without a `Date` argument, consider standardizing its API (e.g., `formatTimezoneOffset(date: Date, timeZone?: string)`) and updating existing call sites to keep behavior consistent across the app.
</issue_to_address>
### Comment 3
<location path="src/config/sidebarConfig.ts" line_range="105-114" />
<code_context>
// 右侧边栏组件配置列表
rightComponents: [
+ {
+ // 组件类型:最新动态组件
+ type: "dynamic",
+ // 是否启用该组件
+ enable: true,
+ // 组件位置
+ position: "top",
+ // 是否在文章详情页显示
+ showOnPostPage: true,
+ // 组件专属配置
+ specificConfig: {
+ dynamic: {
+ // 显示的最新动态数量
+ limit: 2,
+ },
+ },
+ },
{
// 组件类型:站点统计组件
</code_context>
<issue_to_address>
**question (bug_risk):** The `dynamic` widget is configured twice in `rightComponents`, which may lead to duplicate UI.
There are two `dynamic` entries in `rightComponents` with effectively the same configuration (`enable: true`, `showOnPostPage: true`, `limit: 2`). Unless the layout engine treats them differently, this will likely render the widget twice. If you don’t intend duplication, remove one entry and adjust the remaining widget’s position as needed.
</issue_to_address>
### Comment 4
<location path="src/content/dynamic/2026-07-15-010756.md" line_range="7-13" />
<code_context>
+
+今天天气真不错,流萤真可爱。
+
+
+
+
+
+
+
+
</code_context>
<issue_to_address>
**nitpick:** Consider using more descriptive and/or distinct alt text for each image instead of repeating `图片一`.
All images currently use the same alt text. To improve accessibility and support screen readers, please give each image a distinct, descriptive alt text that reflects its specific content.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| const requestedPath = new URLSearchParams(window.location.search).get("path") | ||
| if (requestedPath) { | ||
| identifier = requestedPath.replace(/^\/+|\/+$/g, "") | ||
| url = new URL(requestedPath, window.location.origin).href |
There was a problem hiding this comment.
issue (bug_risk): 由于 identifier 和 url 是通过 define:vars 注入的常量,重新赋值会失败。
因为 define:vars 在浏览器中会把这些绑定生成为 const,所以在存在 requestedPath 时重新给 identifier 和 url 赋值会抛出 Assignment to constant variable,从而阻止 Disqus 初始化。可以改为引入单独的可变本地变量(例如 let effectiveIdentifier = identifier; let effectiveUrl = url;),根据 requestedPath 更新这些变量,并在 disqus_config 中使用它们,而不是修改注入的常量。
Original comment in English
issue (bug_risk): Reassigning identifier and url will fail because they are constants injected via define:vars.
Because define:vars emits these bindings as const in the browser, reassigning identifier and url when requestedPath is present will throw Assignment to constant variable and prevent Disqus from initializing. Instead, introduce separate mutable locals (e.g. let effectiveIdentifier = identifier; let effectiveUrl = url;), update those based on requestedPath, and use them inside disqus_config rather than modifying the injected constants.
| const time = root.querySelector<HTMLTimeElement>("[data-dynamic-time]"); | ||
| if (time) { | ||
| const date = new Date(entry.published); | ||
| time.dateTime = date.toISOString(); | ||
| time.textContent = new Intl.DateTimeFormat( | ||
| document.documentElement.lang || undefined, | ||
| { | ||
| year: "numeric", | ||
| month: "2-digit", | ||
| day: "2-digit", |
There was a problem hiding this comment.
suggestion: DynamicFeed 中的时区格式化逻辑与 formatTimezoneOffset 重复,且未来可能出现差异。
目前的 timezoneLabel 逻辑(使用 Intl.DateTimeFormat 和字符串处理)与 date-utils.ts 中的 formatTimezoneOffset 功能重复,这会带来风险:如果将来只更新其中一个实现(例如处理非整点偏移或本地化变更),输出就会不一致。请通过复用 formatTimezoneOffset 或抽取一个供二者共享的辅助函数来集中管理这部分行为。
建议实现:
event.ctrlKey ||
event.shiftKey ||
event.altKey
)
return;
event.preventDefault();
event.stopPropagation();
history.replaceState(history.state, "", permalink);
});
});
const time = root.querySelector<HTMLTimeElement>("[data-dynamic-time]");
if (time) {
const date = new Date(entry.published);
time.dateTime = date.toISOString();
time.textContent = new Intl.DateTimeFormat(
document.documentElement.lang || undefined,
{
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
},
).format(date);
time.textContent += ` ${formatTimezoneOffset(timezone, date)}`;
}
const content = root.querySelector<HTMLElement>("[data-dynamic-content]");
if (content) {
content.id = `${anchorId}-content`;
- 在
DynamicFeed.svelte顶部添加对formatTimezoneOffset的导入,并使用指向date-utils.ts的正确相对路径,例如:根据你实际的项目结构调整路径。import { formatTimezoneOffset } from "../../../utils/date-utils";
- 确认
formatTimezoneOffset的函数签名与这里的用法一致。如果它目前只接受Date或只接受时区字符串(比如仅接受Date或仅接受时区 ID),请相应地调整调用formatTimezoneOffset(timezone, date),或者扩展date-utils.ts,提供一个既能使用时区标识又能使用Date实例进行格式化的辅助函数。 - 如果
formatTimezoneOffset目前在其它地方的使用不带Date参数,可以考虑统一它的 API(例如formatTimezoneOffset(date: Date, timeZone?: string)),并更新现有调用点,以保证整个应用中的行为一致。
Original comment in English
suggestion: Timezone formatting logic in DynamicFeed duplicates formatTimezoneOffset and could diverge over time.
The timezoneLabel logic (using Intl.DateTimeFormat and string manipulation) duplicates formatTimezoneOffset in date-utils.ts, which risks inconsistent output if only one is updated (e.g., for non-:00 offsets or locale changes). Please centralize this behavior by reusing formatTimezoneOffset or extracting a shared helper used by both.
Suggested implementation:
event.ctrlKey ||
event.shiftKey ||
event.altKey
)
return;
event.preventDefault();
event.stopPropagation();
history.replaceState(history.state, "", permalink);
});
});
const time = root.querySelector<HTMLTimeElement>("[data-dynamic-time]");
if (time) {
const date = new Date(entry.published);
time.dateTime = date.toISOString();
time.textContent = new Intl.DateTimeFormat(
document.documentElement.lang || undefined,
{
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
},
).format(date);
time.textContent += ` ${formatTimezoneOffset(timezone, date)}`;
}
const content = root.querySelector<HTMLElement>("[data-dynamic-content]");
if (content) {
content.id = `${anchorId}-content`;
- Add an import for
formatTimezoneOffsetat the top ofDynamicFeed.svelte, using the correct relative path todate-utils.ts, for example:Adjust the path to match your actual project structure.import { formatTimezoneOffset } from "../../../utils/date-utils";
- Ensure the
formatTimezoneOffsetsignature matches the usage here. If it currently accepts aDateor timezone string differently (e.g., only aDateor only a timezone ID), update the callformatTimezoneOffset(timezone, date)accordingly, or extenddate-utils.tsto expose a helper that can format using both the timezone identifier and theDateinstance. - If
formatTimezoneOffsetis currently used elsewhere without aDateargument, consider standardizing its API (e.g.,formatTimezoneOffset(date: Date, timeZone?: string)) and updating existing call sites to keep behavior consistent across the app.
| { | ||
| // 组件类型:最新动态组件 | ||
| type: "dynamic", | ||
| // 是否启用该组件 | ||
| enable: true, | ||
| // 组件位置 | ||
| position: "top", | ||
| // 是否在文章详情页显示 | ||
| showOnPostPage: true, | ||
| // 组件专属配置 |
There was a problem hiding this comment.
question (bug_risk): rightComponents 中的 dynamic 小部件被配置了两次,可能导致重复的界面显示。
rightComponents 中存在两个 dynamic 条目,而且配置几乎完全相同(enable: true、showOnPostPage: true、limit: 2)。除非布局引擎对它们有特殊处理,否则这很可能会让该小部件被渲染两次。如果你并不希望重复显示,请移除其中一个条目,并根据需要调整剩余小部件的位置。
Original comment in English
question (bug_risk): The dynamic widget is configured twice in rightComponents, which may lead to duplicate UI.
There are two dynamic entries in rightComponents with effectively the same configuration (enable: true, showOnPostPage: true, limit: 2). Unless the layout engine treats them differently, this will likely render the widget twice. If you don’t intend duplication, remove one entry and adjust the remaining widget’s position as needed.
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  |
There was a problem hiding this comment.
nitpick: 建议为每张图片使用更具描述性且彼此不同的替代文本,而不是重复使用 图片一。
目前所有图片都使用相同的替代文本。为了提升无障碍体验并支持屏幕阅读器,请为每张图片提供独立且具有描述性的替代文本,以体现它们各自的具体内容。
Original comment in English
nitpick: Consider using more descriptive and/or distinct alt text for each image instead of repeating 图片一.
All images currently use the same alt text. To improve accessibility and support screen readers, please give each image a distinct, descriptive alt text that reflects its specific content.
|
@sourcery-ai review |
关联 #483, #451
Summary by Sourcery
添加一个可配置的「动态 / 瞬间」页面,包含列表、画廊、行内评论以及基于 API 的内容流;并将其集成到导航栏、侧边栏、统计信息和评论系统中,同时调整分页和音乐小组件的行为。
New Features:
Enhancements:
Build:
Documentation:
Original summary in English
Summary by Sourcery
Add a configurable dynamic/moments page with list, gallery, inline comments, and API-backed feed, integrate it into navigation, sidebar, stats, and comments, and adjust pagination and music widget behavior.
New Features:
Enhancements:
Build:
Documentation: