Skip to content

feat(quote-wall): post-to-wall + campaign quote wall#5966

Closed
yingshinlee wants to merge 8 commits into
thematters:developfrom
yingshinlee:feat/quote-wall
Closed

feat(quote-wall): post-to-wall + campaign quote wall#5966
yingshinlee wants to merge 8 commits into
thematters:developfrom
yingshinlee:feat/quote-wall

Conversation

@yingshinlee

Copy link
Copy Markdown
Collaborator

這是什麼

金句牆前端:文章頁金句卡片加「上牆」鈕,活動頁顯示金句牆(桌機右欄/手機入口+彈窗、洗牌、收回)。階段 3。

此分支疊在前兩個 feature 之上(含金句產生器 #5965 與留言區 #5964 的改動),且依賴後端金句牆 PR(matters-server feat/quote-wall)。建議的合併順序:留言區後端 → 留言區前端 → 金句產生器 → 金句牆後端 → 金句牆前端。

改動

範圍 內容
components/GQL/mutations/putQuote.ts(新) PUT_QUOTE / DELETE_QUOTE
components/QuoteImageDialog/Content.tsx 卡片對話框加「上牆」鈕(僅活動文章顯示);額度用完顯示溫和提示(ACTION_LIMIT_EXCEEDED)
components/TextSelectionPopover/index.tsx 傳 articleId / canPostToWall 給對話框
views/CampaignDetail/QuoteWall/(新) index.tsx(精簡模組+chip 入口)、Dialog.tsx(整面牆+洗牌)、QuoteCard.tsx(便利貼卡+回原文+收回)、gql.tsstyles.module.css
views/CampaignDetail/index.tsx 桌機右欄、手機 chip 掛上金句牆(在留言區上方)
common/enums/externalLinks.ts 博物館金句牆連結

行為

  • 上牆:金句卡片對話框(既有 8 風格 × 3 尺寸)多一顆綠色「上牆」;成功顯示「已上牆」、超額顯示「今天的上牆額度用完了,明天再來」。
  • 活動頁金句牆:桌機右欄顯示最新 3 張便利貼+「看全部 N 則」;手機是一行入口(✨ 金句牆 N)點開彈出整面牆。牆上有「🔀 洗牌」(重新隨機抽樣)與「整面牆/博物館 →」。
  • 回原文:每張卡片點擊回到來源文章。
  • 收回:貼的人或原文作者可收回(軟刪除)。
  • 牆上無金句時整個模組自動隱藏。

⚠️ Merge 前

需 node ≥ 22 跑 codegen(PutQuoteMutationCampaignQuotesQueryQuoteWallQuoteFragment 等型別)+ formatjs 抽字(新文案)+ typecheck。Draft。

部署與 QA(測試站 https://matters.icu/ 先行)

桌機氣泡/手機底部列上牆、ARR 文章不可上牆(非作者)、超額提示、活動頁牆桌機右欄/手機彈窗、洗牌、回原文、收回(貼者/作者)、空牆隱藏。

🤖 Generated with Claude Code

yingshinlee and others added 7 commits June 9, 2026 23:49
Let readers select text in an article and generate a shareable quote
image (download as JPG / Web Share). Extends the existing
TextSelectionPopover with a second button next to "quote to comment".

- New component: src/components/QuoteImageDialog (Card / Content / presets / gql)
  - 6 neutral color presets + 3 sizes (1:1, 4:5, 9:16) with platform hints
  - auto font-scaling + 80-char cap so long selections never overflow
  - QR code (qrcode) links back to the article; rendered via html-to-image
  - 七日書 (WritingChallenge) articles automatically swap the Matters
    wordmark for the seven-day-book logo (silent detection via campaigns)
- TextSelectionPopover: add icon-only "金句圖" button, thread article in
- ArticleDetail/Content + gql: pass article + spread QuoteImageArticle fragment
- analytics: register quote_image_* click events
- deps: html-to-image, qrcode (+ @types/qrcode)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- CampaignDetail/Discussion: compact module (desktop right aside) with input
  box + latest 3 comments + view-all dialog; mobile renders a one-line chip
  entry that opens the dialog
- reuse CircleComment family: CircleCommentForm/Dialog accept campaignId and
  type campaignDiscussion; ReplyButton/DropdownActions resolve campaign node
- 240-char cap with counter on campaign comments (matches moments)
- layout: cover height halved (23.26% -> 12%), side participants avatars
  trimmed 60 -> 12 to make room for the discussion module

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- TextSelectionPopover: new variant='bottomBar' for mobile — fixed bottom
  action bar (Quote / Quote card) so it never fights with the iOS/Android
  native selection menu; selection detected via debounced selectionchange
- mount bottomBar on ArticleDetail/Content under Media lessThan md
  (previously the feature was desktop-only)
- license gate: hide quote-card button when article license is ARR
  (all rights reserved) unless the viewer is the author; CC licenses pass
  (card already quotes faithfully with author + link attribution)
- add license to QuoteImageArticle fragment

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- QuoteImageDialog: 'Post to wall' button (campaign articles only) via
  putQuote; gentle quota-reached toast on ACTION_LIMIT_EXCEEDED
- CampaignDetail/QuoteWall: compact module (desktop right aside) + chip
  entry (mobile) + full-wall dialog with shuffle (random refetch)
- QuoteCard: sticky-note card linking back to the source article; retract
  action for the poster or the source article's author (soft delete)
- museum link (freewriting.matters.town/memo-wall) in EXTERNAL_LINKS
- mount quote wall above discussion in the campaign aside / mobile chips

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 11, 2026

Copy link
Copy Markdown

@yingshinlee is attempting to deploy a commit to the DimensionDev Team on Vercel.

A member of the Team first needs to authorize it.

… frontend

- route.ts: add campaignDiscussion to CommentArgs.type union
- drop broken Extract<…, { __typename }> narrowing in Discussion + QuoteWall
  (campaign generates as a single object with optional __typename -> never)
- QuoteWall gql: $first must be the constrained scalar first_Int_min_0_max_50,
  not Int -- this validation error had blocked codegen for all quote types
- analytics: register quote_post_to_wall click event
- QuoteImageDialog: remove dead closeDialog prop wiring
- sync package-lock for html-to-image / @types/qrcode
- align formatjs ids, fix stylelint, extract i18n strings

Verified locally on Node 22 against staging schema:
gen:type + tsc + eslint + stylelint all pass with 0 errors.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@mashbean

Copy link
Copy Markdown
Contributor

改以 upstream 分支重開為 #5969。原因:fork PR 的 CI 拿不到 secrets、required check 不會跑。內容已整併進 #5969

@mashbean mashbean closed this Jun 14, 2026
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.

2 participants