Skip to content

Dev - #136

Merged
FFFold merged 10 commits into
mainfrom
dev
Aug 27, 2026
Merged

Dev#136
FFFold merged 10 commits into
mainfrom
dev

Conversation

@FFFold

@FFFold FFFold commented Aug 27, 2026

Copy link
Copy Markdown
Owner

Type of change

  • Bug fix (a non-breaking change that fixes an issue)
  • New feature (a non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Other (please describe):

Checklist

  • I have read the CONTRIBUTING document.
  • I have checked to ensure that this Pull Request is not for personal changes.
  • I have performed a self-review of my own code.
  • My changes generate no new warnings.

Related Issue

Changes

How To Test

Screenshots (if applicable)

Additional Notes

Sourcery 摘要

将现有的社交分享控件替换为本地化的文章海报分享体验。

新功能:

  • 通过生成可下载的海报分享文章,海报包含文章元数据、图片、作者信息和二维码。
  • 在支持的语言中提供本地化的分享、海报生成、复制和下载操作。

增强功能:

  • 将现有的社交分享组件替换为专用的分享卡片和海报体验,并支持浅色和深色主题。

构建:

  • 添加二维码生成和类型依赖。
Original summary in English

Sourcery 总结

将现有的社交分享控件替换为本地化的文章海报分享体验。

新功能:

  • 添加文章海报分享功能,可生成包含文章元数据、图片、作者详细信息和二维码的可下载图片。
  • 在支持的语言中提供本地化的分享、海报生成、复制链接和下载操作。

增强功能:

  • 将现有的社交分享控件替换为主题化的分享卡片和海报对话框,支持浅色和深色模式。

构建:

  • 添加二维码生成和 TypeScript 依赖。
Original summary in English

Summary by Sourcery

Replace the existing social sharing controls with a localized article poster sharing experience.

New Features:

  • Add article poster sharing that generates downloadable images with article metadata, imagery, author details, and a QR code.
  • Provide localized sharing, poster generation, copy-link, and download actions across supported languages.

Enhancements:

  • Replace the existing social sharing controls with a themed share card and poster dialog supporting light and dark modes.

Build:

  • Add QR code generation and TypeScript dependencies.

@sourcery-ai

sourcery-ai Bot commented Aug 27, 2026

Copy link
Copy Markdown

审查者指南

介绍了一个本地化的文章分享卡片,可延迟生成可下载且支持主题的画布海报,其中包含文章元数据、图片、作者信息和二维码,同时替换之前的社交分享实现,并将该功能接入文章页面。

延迟生成文章海报的时序图

sequenceDiagram
    actor Reader
    participant SharePoster
    participant QRCode
    participant ImageLoader
    participant Canvas
    participant Browser

    Reader->>SharePoster: generatePoster()
    SharePoster->>QRCode: toDataURL(url)
    QRCode-->>SharePoster: qrCodeUrl
    SharePoster->>ImageLoader: loadImage(qrCodeUrl)
    SharePoster->>ImageLoader: loadImage(coverImage)
    SharePoster->>ImageLoader: loadImage(avatar)
    ImageLoader-->>SharePoster: loaded images
    SharePoster->>Canvas: calculateDimensions()
    SharePoster->>Canvas: draw poster content
    Canvas-->>SharePoster: canvas.toDataURL()
    SharePoster-->>Reader: display generated poster
    Reader->>SharePoster: downloadPoster()
    SharePoster->>Browser: download PNG
Loading

文件级变更

变更 详情 文件
将现有的社交分享组件替换为客户端分享海报体验。
  • 新增 Astro 分享卡片,将文章元数据传递给 Svelte 交互组件。
  • 生成带主题的画布海报,其中包含封面/头像图片、元数据、装饰元素和二维码。
  • 支持海报预览、下载、复制链接、加载/错误状态、模态框焦点恢复以及深色模式刷新。
  • 提取图片加载、文本换行、日期解析、尺寸计算和画布绘制辅助函数。
src/components/SocialShare.astro
src/components/misc/ShareCard.astro
src/components/misc/SharePoster.svelte
src/components/misc/utils/poster-renderer.ts
package.json
pnpm-lock.yaml
将海报分享集成到文章页面,并解析本地个人资料头像以支持浏览器画布渲染。
  • 将旧的分享组件调用替换为 ShareCard,并传入标题、描述、发布日期、封面、URL、站点标题、作者和头像。
  • 使用 import.meta.glob 和 Astro 图片元数据,将相对头像路径转换为可访问的 URL。
  • 添加二维码运行时依赖和 TypeScript 声明。
src/pages/posts/[...slug].astro
package.json
pnpm-lock.yaml
为新的分享流程添加本地化界面文本和样式支持。
  • 为所有受支持的语言环境添加分享、海报生成/失败、保存、复制和二维码来源文本的翻译键。
  • 定义模态框 UI 使用的内容元数据颜色变量。
src/i18n/i18nKey.ts
src/i18n/languages/en.ts
src/i18n/languages/es.ts
src/i18n/languages/id.ts
src/i18n/languages/ja.ts
src/i18n/languages/ko.ts
src/i18n/languages/th.ts
src/i18n/languages/tr.ts
src/i18n/languages/vi.ts
src/i18n/languages/zh_CN.ts
src/i18n/languages/zh_TW.ts
src/styles/variables.styl

提示和命令

与 Sourcery 交互

  • 触发新的审查: 在拉取请求中评论 @sourcery-ai review
  • 继续讨论: 直接回复 Sourcery 的审查评论。
  • 从审查评论生成 GitHub issue: 回复审查评论,请 Sourcery 根据该评论创建 issue。也可以回复审查评论并输入 @sourcery-ai issue,从中创建 issue。
  • 生成拉取请求标题: 在拉取请求标题的任意位置输入 @sourcery-ai,即可随时生成标题。也可以在拉取请求中评论 @sourcery-ai title,随时重新生成标题。
  • 生成拉取请求摘要: 在拉取请求正文中任意位置输入 @sourcery-ai summary,即可在指定位置随时生成 PR 摘要。也可以在拉取请求中评论 @sourcery-ai summary,随时重新生成摘要。
  • 生成审查者指南: 在拉取请求中评论 @sourcery-ai guide,即可随时重新生成审查者指南。
  • 解决所有 Sourcery 评论: 在拉取请求中评论 @sourcery-ai resolve,即可解决所有 Sourcery 评论。如果你已经处理完所有评论且不想再看到它们,这会很有用。
  • 忽略所有 Sourcery 审查: 在拉取请求中评论 @sourcery-ai dismiss,即可忽略所有现有的 Sourcery 审查。如果你想通过新的审查重新开始,这尤其有用——别忘了评论 @sourcery-ai review 以触发新的审查!

自定义你的使用体验

访问你的控制面板以:

  • 启用或禁用审查功能,例如 Sourcery 生成的拉取请求摘要、审查者指南等。
  • 更改审查语言。
  • 添加、删除或编辑自定义审查说明。
  • 调整其他审查设置。

获取帮助

Original review guide in English

Reviewer's Guide

Introduces a localized article-sharing card that lazily generates downloadable, theme-aware canvas posters containing article metadata, imagery, author details, and a QR code, while replacing the previous social-share implementation and wiring the feature into post pages.

Sequence diagram for lazy article poster generation

sequenceDiagram
    actor Reader
    participant SharePoster
    participant QRCode
    participant ImageLoader
    participant Canvas
    participant Browser

    Reader->>SharePoster: generatePoster()
    SharePoster->>QRCode: toDataURL(url)
    QRCode-->>SharePoster: qrCodeUrl
    SharePoster->>ImageLoader: loadImage(qrCodeUrl)
    SharePoster->>ImageLoader: loadImage(coverImage)
    SharePoster->>ImageLoader: loadImage(avatar)
    ImageLoader-->>SharePoster: loaded images
    SharePoster->>Canvas: calculateDimensions()
    SharePoster->>Canvas: draw poster content
    Canvas-->>SharePoster: canvas.toDataURL()
    SharePoster-->>Reader: display generated poster
    Reader->>SharePoster: downloadPoster()
    SharePoster->>Browser: download PNG
Loading

File-Level Changes

Change Details Files
Replaces the existing social-share component with a client-side share-poster experience.
  • Adds an Astro share card that passes article metadata into a Svelte interactive component.
  • Generates a themed canvas poster with cover/avatar images, metadata, decorative elements, and a QR code.
  • Supports poster preview, download, link copying, loading/error states, modal focus restoration, and dark-mode refresh.
  • Extracts image loading, text wrapping, date parsing, sizing, and canvas drawing helpers.
src/components/SocialShare.astro
src/components/misc/ShareCard.astro
src/components/misc/SharePoster.svelte
src/components/misc/utils/poster-renderer.ts
package.json
pnpm-lock.yaml
Integrates poster sharing into post pages and resolves local profile avatars for browser canvas rendering.
  • Replaces the old share component invocation with ShareCard and supplies title, description, publication date, cover, URL, site title, author, and avatar.
  • Uses import.meta.glob and Astro image metadata to convert relative avatar paths into served URLs.
  • Adds the QR-code runtime dependency and TypeScript declarations.
src/pages/posts/[...slug].astro
package.json
pnpm-lock.yaml
Adds localized UI strings and styling support for the new sharing workflow.
  • Adds translation keys for sharing, poster generation/failure, saving, copying, and QR-source text across all supported locales.
  • Defines the content metadata color variable used by the modal UI.
src/i18n/i18nKey.ts
src/i18n/languages/en.ts
src/i18n/languages/es.ts
src/i18n/languages/id.ts
src/i18n/languages/ja.ts
src/i18n/languages/ko.ts
src/i18n/languages/th.ts
src/i18n/languages/tr.ts
src/i18n/languages/vi.ts
src/i18n/languages/zh_CN.ts
src/i18n/languages/zh_TW.ts
src/styles/variables.styl

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

嗨——我发现了 3 个问题

AI Agent 提示词
请处理本次代码审查中的评论:

## 个别评论

### 评论 1
<location path="src/components/misc/SharePoster.svelte" line_range="96-99" />
<code_context>
+
+	const observer = new MutationObserver(() => {
+		const currentIsDark = isDarkMode();
+		if (currentIsDark !== lastIsDark) {
+			lastIsDark = currentIsDark;
+			posterImage = null;
+			errorMessage = null;
+		}
+	});
</code_context>
<issue_to_address>
**issue (bug_risk):** 当海报生成仍在进行时主题发生变化,MutationObserver 会清除 `posterImage`,但正在进行的生成任务稍后会将旧主题的画布重新赋值给 `posterImage`,因此显示的海报与当前主题不匹配。

**触发条件:** 用户在封面/头像加载或二维码导入仍处于等待状态时,在浅色和深色主题之间切换。

**建议修复:** 跟踪生成时使用的主题,或使用生成令牌,并丢弃在最近一次主题变更之前生成的结果。
</issue_to_address>

### 评论 2
<location path="src/components/misc/SharePoster.svelte" line_range="386-401" />
<code_context>
+const COPY_FEEDBACK_DURATION = 2000;
+
+async function copyLink() {
+	try {
+		if (!navigator.clipboard?.writeText) {
+			throw new Error("Clipboard API is not available");
+		}
+
+		await navigator.clipboard.writeText(url);
+		copied = true;
+		if (copyTimeout) {
+			clearTimeout(copyTimeout);
+		}
+		copyTimeout = setTimeout(() => {
+			copied = false;
+		}, COPY_FEEDBACK_DURATION);
+	} catch (error) {
+		console.error("Failed to copy link:", error);
+	}
+}
+
</code_context>
<issue_to_address>
**issue (bug_risk):** 当剪贴板 API 不可用或 `writeText` 被拒绝时,`copyLink` 只记录异常,而 UI 保持不变的“复制链接”状态,因此用户不会获知复制失败。

**触发条件:** 页面未获得剪贴板权限、处于非安全上下文,或浏览器拒绝剪贴板写入时。

**建议修复:** 在 catch 分支中设置错误或失败反馈状态,并向用户显示本地化消息。
</issue_to_address>

### 评论 3
<location path="src/components/misc/utils/poster-renderer.ts" line_range="64-67" />
<code_context>
+	const lines: string[] = [];
+	let currentLine = "";
+
+	for (const char of text) {
+		if (ctx.measureText(currentLine + char).width < maxWidth) {
+			currentLine += char;
+		} else {
+			lines.push(currentLine);
+			currentLine = char;
+		}
+	}
+
</code_context>
<issue_to_address>
**nitpick (bug_risk):** 当第一个字形宽于 `maxWidth` 时,`getLines` 会在将该字形放到下一行之前先推入一个空字符串,从而增加一个空白渲染行,并高估计算出的海报高度。

**触发条件:** 标题或描述包含宽于可用画布宽度的字形时。

**建议修复:** 仅在 `currentLine` 非空时推入它,或显式处理超宽字形,避免创建空行。

```suggestion
		} else {
			if (currentLine) {
				lines.push(currentLine);
			}
			currentLine = char;
		}
```
</issue_to_address>

Sourcery 评估

需要人工审查。 需要先处理 2 个发现;此外,此更改用大规模的客户端海报生成器替换了现有的分享行为,并添加了 qrcode 依赖,因此错误的实现可能会生成损坏或具有误导性的下载海报,还可能通过外部回退代理触发图片请求。回滚可以恢复旧 UI,但在回滚前已经下载的海报以及已经发出的代理请求仍会保留。

阻塞性发现:src/components/misc/SharePoster.svelte:99src/components/misc/SharePoster.svelte:401


Sourcery 对开源项目免费——如果您喜欢我们的审查,请考虑分享它们 ✨
帮助我变得更有用!请对每条评论点击 👍 或 👎,我会利用反馈来改进审查结果。
Original comment in English

Hey - I've found 3 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="src/components/misc/SharePoster.svelte" line_range="96-99" />
<code_context>
+
+	const observer = new MutationObserver(() => {
+		const currentIsDark = isDarkMode();
+		if (currentIsDark !== lastIsDark) {
+			lastIsDark = currentIsDark;
+			posterImage = null;
+			errorMessage = null;
+		}
+	});
</code_context>
<issue_to_address>
**issue (bug_risk):** When the theme changes while poster generation is still in progress, the mutation observer clears `posterImage`, but the in-flight generation later assigns its old-theme canvas back to `posterImage`, so the displayed poster does not match the current theme.

**Triggers:** When a cover/avatar load or QR-code import is still pending while the user switches between light and dark themes.

**Suggested fix:** Track the generation theme or use a generation token, and discard results produced before the latest theme change.
</issue_to_address>

### Comment 2
<location path="src/components/misc/SharePoster.svelte" line_range="386-401" />
<code_context>
+const COPY_FEEDBACK_DURATION = 2000;
+
+async function copyLink() {
+	try {
+		if (!navigator.clipboard?.writeText) {
+			throw new Error("Clipboard API is not available");
+		}
+
+		await navigator.clipboard.writeText(url);
+		copied = true;
+		if (copyTimeout) {
+			clearTimeout(copyTimeout);
+		}
+		copyTimeout = setTimeout(() => {
+			copied = false;
+		}, COPY_FEEDBACK_DURATION);
+	} catch (error) {
+		console.error("Failed to copy link:", error);
+	}
+}
+
</code_context>
<issue_to_address>
**issue (bug_risk):** When the Clipboard API is unavailable or `writeText` rejects, `copyLink` only logs the exception and leaves the UI in the unchanged “Copy Link” state, so the user receives no indication that copying failed.

**Triggers:** When the page is served without clipboard permission, outside a secure context, or the browser rejects the clipboard write.

**Suggested fix:** Set an error or failure-feedback state in the catch branch and render a localized message to the user.
</issue_to_address>

### Comment 3
<location path="src/components/misc/utils/poster-renderer.ts" line_range="64-67" />
<code_context>
+	const lines: string[] = [];
+	let currentLine = "";
+
+	for (const char of text) {
+		if (ctx.measureText(currentLine + char).width < maxWidth) {
+			currentLine += char;
+		} else {
+			lines.push(currentLine);
+			currentLine = char;
+		}
+	}
+
</code_context>
<issue_to_address>
**nitpick (bug_risk):** When the first glyph is wider than `maxWidth`, `getLines` pushes an empty string before placing that glyph on the next line, adding a blank rendered line and overstating the calculated poster height.

**Triggers:** When a title or description contains a glyph wider than the available canvas width.

**Suggested fix:** Only push `currentLine` when it is non-empty, or explicitly handle an over-wide glyph without creating an empty line.

```suggestion
		} else {
			if (currentLine) {
				lines.push(currentLine);
			}
			currentLine = char;
		}
```
</issue_to_address>

Sourcery assessment

Needs a human reviewer. 2 findings to address first, and this replaces the existing sharing behavior with a substantial client-side poster generator and adds the qrcode dependency, so an incorrect implementation could produce broken or misleading downloaded posters and trigger image requests through the external fallback proxy. Reverting restores the old UI, but posters already downloaded and any proxy requests made before the revert would remain.

Blocking findings: src/components/misc/SharePoster.svelte:99, src/components/misc/SharePoster.svelte:401


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread src/components/misc/SharePoster.svelte
Comment thread src/components/misc/SharePoster.svelte
Comment thread src/components/misc/utils/poster-renderer.ts

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sourcery assessment

Approved.

@FFFold
FFFold merged commit f9674f1 into main Aug 27, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant