diff --git a/lang/default.json b/lang/default.json index b540a94307..15fc89e383 100644 --- a/lang/default.json +++ b/lang/default.json @@ -586,6 +586,9 @@ "defaultMessage": "Notifications", "description": "src/views/Me/Settings/Settings/SettingsTabs/index.tsx" }, + "6gXdHy": { + "defaultMessage": "Share" + }, "6kMb9Z": { "defaultMessage": "On-chain records" }, @@ -785,6 +788,10 @@ "9WRlF4": { "defaultMessage": "Send" }, + "9ZBatB": { + "defaultMessage": "Quote", + "description": "src/components/TextSelectionPopover/index.tsx" + }, "9aorag": { "defaultMessage": "Unlike collection" }, @@ -862,6 +869,10 @@ "AlHYvk": { "defaultMessage": "{type} edited" }, + "Aq0aMp": { + "defaultMessage": "Only participants can join the discussion.", + "description": "src/views/CampaignDetail/Discussion" + }, "At8Qd2": { "defaultMessage": "Account", "description": "src/views/Me/Settings/Settings/SettingsTabs/index.tsx" @@ -1605,6 +1616,10 @@ "Mgl1bT": { "defaultMessage": "OAuth authorize" }, + "Mh+PgK": { + "defaultMessage": "No discussion yet", + "description": "src/views/CampaignDetail/Discussion" + }, "Mn7GEf": { "defaultMessage": "Selected activities related to you in the past 24 hours", "description": "src/views/Me/Settings/Notifications/Email.tsx" @@ -1863,6 +1878,108 @@ "Qlzm0s": { "defaultMessage": "mentioned you in a moment at" }, + "QuoteImage.download": { + "defaultMessage": "Download" + }, + "QuoteImage.onWall": { + "defaultMessage": "On the wall ✓" + }, + "QuoteImage.postToWall": { + "defaultMessage": "Post to wall" + }, + "QuoteImage.postedToWall": { + "defaultMessage": "Posted to the quote wall" + }, + "QuoteImage.size.portrait": { + "defaultMessage": "Portrait 4:5" + }, + "QuoteImage.size.square": { + "defaultMessage": "Square 1:1" + }, + "QuoteImage.size.story": { + "defaultMessage": "Story 9:16" + }, + "QuoteImage.sizeLabel": { + "defaultMessage": "Size" + }, + "QuoteImage.sizeNote.portrait": { + "defaultMessage": "IG post · most eye-catching" + }, + "QuoteImage.sizeNote.square": { + "defaultMessage": "IG / FB post" + }, + "QuoteImage.sizeNote.story": { + "defaultMessage": "IG / FB story · Threads" + }, + "QuoteImage.style.coral": { + "defaultMessage": "Coral" + }, + "QuoteImage.style.ink": { + "defaultMessage": "Ink" + }, + "QuoteImage.style.mint": { + "defaultMessage": "Mint" + }, + "QuoteImage.style.pine": { + "defaultMessage": "Pine" + }, + "QuoteImage.style.sky": { + "defaultMessage": "Sky" + }, + "QuoteImage.style.slate": { + "defaultMessage": "Slate" + }, + "QuoteImage.style.violet": { + "defaultMessage": "Violet" + }, + "QuoteImage.style.warm": { + "defaultMessage": "Cream" + }, + "QuoteImage.styleLabel": { + "defaultMessage": "Style" + }, + "QuoteImage.title": { + "defaultMessage": "Share Quote" + }, + "QuoteImage.truncated": { + "defaultMessage": "You selected {original} characters; only the first {max} are shown. A concise quote works best." + }, + "QuoteImage.wallFailed": { + "defaultMessage": "Failed to post to the wall" + }, + "QuoteImage.wallQuota": { + "defaultMessage": "Wall quota reached for today — come back tomorrow!" + }, + "QuoteWall.confirmRetract": { + "defaultMessage": "Confirm retract" + }, + "QuoteWall.fullWall": { + "defaultMessage": "Full wall →" + }, + "QuoteWall.museum": { + "defaultMessage": "Full wall / Museum →" + }, + "QuoteWall.retract": { + "defaultMessage": "Retract" + }, + "QuoteWall.retractFailed": { + "defaultMessage": "Failed to retract" + }, + "QuoteWall.retracted": { + "defaultMessage": "Quote retracted from the wall" + }, + "QuoteWall.shuffle": { + "defaultMessage": "🔀 Shuffle" + }, + "QuoteWall.title": { + "defaultMessage": "Quote wall" + }, + "QuoteWall.toArticle": { + "defaultMessage": "To article ↩" + }, + "QuoteWall.viewAll": { + "defaultMessage": "View all {count} quotes" + }, "QvPc1q": { "defaultMessage": "Upload Cover" }, @@ -2155,6 +2272,10 @@ "defaultMessage": "Drafts", "description": "src/views/Me/Works/WorksTabs/index.tsx" }, + "Vj0Hbd": { + "defaultMessage": "View all {count} comments", + "description": "src/views/CampaignDetail/Discussion" + }, "VmYzLr": { "defaultMessage": "{total} members" }, @@ -2427,6 +2548,10 @@ "aKEiNd": { "defaultMessage": "You missed the registration period, you can still join as a latecomer. Apply earlier next time for the chance to get the badge." }, + "aLkBs2": { + "defaultMessage": "Discussion", + "description": "src/views/CampaignDetail/Discussion" + }, "aOFCqL": { "defaultMessage": "Most comments", "description": "src/views/Me/Works/Published/SortTabs.tsx" @@ -2486,6 +2611,10 @@ "defaultMessage": "Your article {articleTitle} has been listed as a feature of event in 7 days. Come and view more wonderful articles!", "description": "src/components/Notice/CampaignArticleNotice/CampaignArticleFeaturedNotice.tsx" }, + "b3aGfp": { + "defaultMessage": "Share your thoughts with other participants", + "description": "src/views/CampaignDetail/Discussion" + }, "b6x6lm": { "defaultMessage": "Enter a clear and concise title" }, @@ -2922,6 +3051,10 @@ "iIitRg": { "defaultMessage": "Tag not bookmarked yet" }, + "iJfVZG": { + "defaultMessage": "Quote card", + "description": "src/components/TextSelectionPopover/index.tsx" + }, "iNZdM/": { "defaultMessage": "Switch to support creators with the Optimism network {br} Make support more convenient and affordable", "description": "src/components/Forms/PaymentForm/SwitchNetwork/index.tsx" @@ -2929,6 +3062,9 @@ "iSM+et": { "defaultMessage": "All rights reserved" }, + "iSUeWj": { + "defaultMessage": "Comment sent" + }, "iTcMqz": { "defaultMessage": "Under the moonlight, dreams are about to come true. The Moonlight Dream badge signifies your participation in the Nomad Matters.", "description": "src/views/User/UserProfile/BadgeNomadLabel/index.tsx" diff --git a/lang/en.json b/lang/en.json index 7b8296a987..13f7c3b43a 100644 --- a/lang/en.json +++ b/lang/en.json @@ -586,6 +586,9 @@ "defaultMessage": "Notifications", "description": "src/views/Me/Settings/Settings/SettingsTabs/index.tsx" }, + "6gXdHy": { + "defaultMessage": "Share" + }, "6kMb9Z": { "defaultMessage": "On-chain records" }, @@ -785,6 +788,10 @@ "9WRlF4": { "defaultMessage": "Send" }, + "9ZBatB": { + "defaultMessage": "Quote", + "description": "src/components/TextSelectionPopover/index.tsx" + }, "9aorag": { "defaultMessage": "Unlike collection" }, @@ -862,6 +869,10 @@ "AlHYvk": { "defaultMessage": "{type} edited" }, + "Aq0aMp": { + "defaultMessage": "Only participants can join the discussion.", + "description": "src/views/CampaignDetail/Discussion" + }, "At8Qd2": { "defaultMessage": "Account", "description": "src/views/Me/Settings/Settings/SettingsTabs/index.tsx" @@ -1605,6 +1616,10 @@ "Mgl1bT": { "defaultMessage": "OAuth authorize" }, + "Mh+PgK": { + "defaultMessage": "No discussion yet", + "description": "src/views/CampaignDetail/Discussion" + }, "Mn7GEf": { "defaultMessage": "Selected activities related to you in the past 24 hours", "description": "src/views/Me/Settings/Notifications/Email.tsx" @@ -1863,6 +1878,108 @@ "Qlzm0s": { "defaultMessage": "mentioned you in a moment at" }, + "QuoteImage.download": { + "defaultMessage": "Download" + }, + "QuoteImage.onWall": { + "defaultMessage": "On the wall ✓" + }, + "QuoteImage.postToWall": { + "defaultMessage": "Post to wall" + }, + "QuoteImage.postedToWall": { + "defaultMessage": "Posted to the quote wall" + }, + "QuoteImage.size.portrait": { + "defaultMessage": "Portrait 4:5" + }, + "QuoteImage.size.square": { + "defaultMessage": "Square 1:1" + }, + "QuoteImage.size.story": { + "defaultMessage": "Story 9:16" + }, + "QuoteImage.sizeLabel": { + "defaultMessage": "Size" + }, + "QuoteImage.sizeNote.portrait": { + "defaultMessage": "IG post · most eye-catching" + }, + "QuoteImage.sizeNote.square": { + "defaultMessage": "IG / FB post" + }, + "QuoteImage.sizeNote.story": { + "defaultMessage": "IG / FB story · Threads" + }, + "QuoteImage.style.coral": { + "defaultMessage": "Coral" + }, + "QuoteImage.style.ink": { + "defaultMessage": "Ink" + }, + "QuoteImage.style.mint": { + "defaultMessage": "Mint" + }, + "QuoteImage.style.pine": { + "defaultMessage": "Pine" + }, + "QuoteImage.style.sky": { + "defaultMessage": "Sky" + }, + "QuoteImage.style.slate": { + "defaultMessage": "Slate" + }, + "QuoteImage.style.violet": { + "defaultMessage": "Violet" + }, + "QuoteImage.style.warm": { + "defaultMessage": "Cream" + }, + "QuoteImage.styleLabel": { + "defaultMessage": "Style" + }, + "QuoteImage.title": { + "defaultMessage": "Share Quote" + }, + "QuoteImage.truncated": { + "defaultMessage": "You selected {original} characters; only the first {max} are shown. A concise quote works best." + }, + "QuoteImage.wallFailed": { + "defaultMessage": "Failed to post to the wall" + }, + "QuoteImage.wallQuota": { + "defaultMessage": "Wall quota reached for today — come back tomorrow!" + }, + "QuoteWall.confirmRetract": { + "defaultMessage": "Confirm retract" + }, + "QuoteWall.fullWall": { + "defaultMessage": "Full wall →" + }, + "QuoteWall.museum": { + "defaultMessage": "Full wall / Museum →" + }, + "QuoteWall.retract": { + "defaultMessage": "Retract" + }, + "QuoteWall.retractFailed": { + "defaultMessage": "Failed to retract" + }, + "QuoteWall.retracted": { + "defaultMessage": "Quote retracted from the wall" + }, + "QuoteWall.shuffle": { + "defaultMessage": "🔀 Shuffle" + }, + "QuoteWall.title": { + "defaultMessage": "Quote wall" + }, + "QuoteWall.toArticle": { + "defaultMessage": "To article ↩" + }, + "QuoteWall.viewAll": { + "defaultMessage": "View all {count} quotes" + }, "QvPc1q": { "defaultMessage": "Upload Cover" }, @@ -2155,6 +2272,10 @@ "defaultMessage": "Drafts", "description": "src/views/Me/Works/WorksTabs/index.tsx" }, + "Vj0Hbd": { + "defaultMessage": "View all {count} comments", + "description": "src/views/CampaignDetail/Discussion" + }, "VmYzLr": { "defaultMessage": "{total} members" }, @@ -2427,6 +2548,10 @@ "aKEiNd": { "defaultMessage": "You missed the registration period, you can still join as a latecomer. Apply earlier next time for the chance to get the badge." }, + "aLkBs2": { + "defaultMessage": "Discussion", + "description": "src/views/CampaignDetail/Discussion" + }, "aOFCqL": { "defaultMessage": "Most comments", "description": "src/views/Me/Works/Published/SortTabs.tsx" @@ -2486,6 +2611,10 @@ "defaultMessage": "Your article {articleTitle} has been listed as a feature of event in 7 days. Come and view more wonderful articles!", "description": "src/components/Notice/CampaignArticleNotice/CampaignArticleFeaturedNotice.tsx" }, + "b3aGfp": { + "defaultMessage": "Share your thoughts with other participants", + "description": "src/views/CampaignDetail/Discussion" + }, "b6x6lm": { "defaultMessage": "Enter a clear and concise title" }, @@ -2922,6 +3051,10 @@ "iIitRg": { "defaultMessage": "Tag not bookmarked yet" }, + "iJfVZG": { + "defaultMessage": "Quote card", + "description": "src/components/TextSelectionPopover/index.tsx" + }, "iNZdM/": { "defaultMessage": "Switch to support creators with the Optimism network {br} Make support more convenient and affordable", "description": "src/components/Forms/PaymentForm/SwitchNetwork/index.tsx" @@ -2929,6 +3062,9 @@ "iSM+et": { "defaultMessage": "All rights reserved" }, + "iSUeWj": { + "defaultMessage": "Comment sent" + }, "iTcMqz": { "defaultMessage": "Under the moonlight, dreams are about to come true. The Moonlight Dream badge signifies your participation in the Nomad Matters.", "description": "src/views/User/UserProfile/BadgeNomadLabel/index.tsx" diff --git a/lang/zh-Hans.json b/lang/zh-Hans.json index 842476d4c7..cf68cff145 100644 --- a/lang/zh-Hans.json +++ b/lang/zh-Hans.json @@ -586,6 +586,9 @@ "defaultMessage": "通知", "description": "src/views/Me/Settings/Settings/SettingsTabs/index.tsx" }, + "6gXdHy": { + "defaultMessage": "Share" + }, "6kMb9Z": { "defaultMessage": "链上记录" }, @@ -785,6 +788,10 @@ "9WRlF4": { "defaultMessage": "送出" }, + "9ZBatB": { + "defaultMessage": "Quote", + "description": "src/components/TextSelectionPopover/index.tsx" + }, "9aorag": { "defaultMessage": "取消喜欢选集" }, @@ -862,6 +869,10 @@ "AlHYvk": { "defaultMessage": "{type}已编辑" }, + "Aq0aMp": { + "defaultMessage": "Only participants can join the discussion.", + "description": "src/views/CampaignDetail/Discussion" + }, "At8Qd2": { "defaultMessage": "账号", "description": "src/views/Me/Settings/Settings/SettingsTabs/index.tsx" @@ -1605,6 +1616,10 @@ "Mgl1bT": { "defaultMessage": "应用授权" }, + "Mh+PgK": { + "defaultMessage": "No discussion yet", + "description": "src/views/CampaignDetail/Discussion" + }, "Mn7GEf": { "defaultMessage": "精选过去 24 小时与你有关的消息", "description": "src/views/Me/Settings/Notifications/Email.tsx" @@ -1863,6 +1878,108 @@ "Qlzm0s": { "defaultMessage": "在动态中提及了你" }, + "QuoteImage.download": { + "defaultMessage": "Download" + }, + "QuoteImage.onWall": { + "defaultMessage": "On the wall ✓" + }, + "QuoteImage.postToWall": { + "defaultMessage": "Post to wall" + }, + "QuoteImage.postedToWall": { + "defaultMessage": "Posted to the quote wall" + }, + "QuoteImage.size.portrait": { + "defaultMessage": "Portrait 4:5" + }, + "QuoteImage.size.square": { + "defaultMessage": "Square 1:1" + }, + "QuoteImage.size.story": { + "defaultMessage": "Story 9:16" + }, + "QuoteImage.sizeLabel": { + "defaultMessage": "Size" + }, + "QuoteImage.sizeNote.portrait": { + "defaultMessage": "IG post · most eye-catching" + }, + "QuoteImage.sizeNote.square": { + "defaultMessage": "IG / FB post" + }, + "QuoteImage.sizeNote.story": { + "defaultMessage": "IG / FB story · Threads" + }, + "QuoteImage.style.coral": { + "defaultMessage": "Coral" + }, + "QuoteImage.style.ink": { + "defaultMessage": "Ink" + }, + "QuoteImage.style.mint": { + "defaultMessage": "Mint" + }, + "QuoteImage.style.pine": { + "defaultMessage": "Pine" + }, + "QuoteImage.style.sky": { + "defaultMessage": "Sky" + }, + "QuoteImage.style.slate": { + "defaultMessage": "Slate" + }, + "QuoteImage.style.violet": { + "defaultMessage": "Violet" + }, + "QuoteImage.style.warm": { + "defaultMessage": "Cream" + }, + "QuoteImage.styleLabel": { + "defaultMessage": "Style" + }, + "QuoteImage.title": { + "defaultMessage": "Share Quote" + }, + "QuoteImage.truncated": { + "defaultMessage": "You selected {original} characters; only the first {max} are shown. A concise quote works best." + }, + "QuoteImage.wallFailed": { + "defaultMessage": "Failed to post to the wall" + }, + "QuoteImage.wallQuota": { + "defaultMessage": "Wall quota reached for today — come back tomorrow!" + }, + "QuoteWall.confirmRetract": { + "defaultMessage": "Confirm retract" + }, + "QuoteWall.fullWall": { + "defaultMessage": "Full wall →" + }, + "QuoteWall.museum": { + "defaultMessage": "Full wall / Museum →" + }, + "QuoteWall.retract": { + "defaultMessage": "Retract" + }, + "QuoteWall.retractFailed": { + "defaultMessage": "Failed to retract" + }, + "QuoteWall.retracted": { + "defaultMessage": "Quote retracted from the wall" + }, + "QuoteWall.shuffle": { + "defaultMessage": "🔀 Shuffle" + }, + "QuoteWall.title": { + "defaultMessage": "Quote wall" + }, + "QuoteWall.toArticle": { + "defaultMessage": "To article ↩" + }, + "QuoteWall.viewAll": { + "defaultMessage": "View all {count} quotes" + }, "QvPc1q": { "defaultMessage": "上传封面" }, @@ -2155,6 +2272,10 @@ "defaultMessage": "草稿", "description": "src/views/Me/Works/WorksTabs/index.tsx" }, + "Vj0Hbd": { + "defaultMessage": "View all {count} comments", + "description": "src/views/CampaignDetail/Discussion" + }, "VmYzLr": { "defaultMessage": "{total} 個成員" }, @@ -2427,6 +2548,10 @@ "aKEiNd": { "defaultMessage": "错过报名期没关系,仍然可以用晚鸟身份参与,一起书写人生故事。下次早点报名,就有机会获得大满贯徽章!" }, + "aLkBs2": { + "defaultMessage": "Discussion", + "description": "src/views/CampaignDetail/Discussion" + }, "aOFCqL": { "defaultMessage": "最多评论", "description": "src/views/Me/Works/Published/SortTabs.tsx" @@ -2486,6 +2611,10 @@ "defaultMessage": "你的作品 {articleTitle} 已被列为活动精选之作,快来看看更多精彩好文!", "description": "src/components/Notice/CampaignArticleNotice/CampaignArticleFeaturedNotice.tsx" }, + "b3aGfp": { + "defaultMessage": "Share your thoughts with other participants", + "description": "src/views/CampaignDetail/Discussion" + }, "b6x6lm": { "defaultMessage": "输入简单明了的标题" }, @@ -2922,6 +3051,10 @@ "iIitRg": { "defaultMessage": "尚未收藏标签" }, + "iJfVZG": { + "defaultMessage": "Quote card", + "description": "src/components/TextSelectionPopover/index.tsx" + }, "iNZdM/": { "defaultMessage": "切换后即可支持创作者,采用 Optimism 网络{br}让支持更方便且费用低廉", "description": "src/components/Forms/PaymentForm/SwitchNetwork/index.tsx" @@ -2929,6 +3062,9 @@ "iSM+et": { "defaultMessage": "作者保留所有权利" }, + "iSUeWj": { + "defaultMessage": "Comment sent" + }, "iTcMqz": { "defaultMessage": "月色之下,梦想即将实现。月之梦徽章纪念你曾参与「游牧者计划」。", "description": "src/views/User/UserProfile/BadgeNomadLabel/index.tsx" diff --git a/lang/zh-Hant.json b/lang/zh-Hant.json index 91a22de82e..0f0042126b 100644 --- a/lang/zh-Hant.json +++ b/lang/zh-Hant.json @@ -586,6 +586,9 @@ "defaultMessage": "通知", "description": "src/views/Me/Settings/Settings/SettingsTabs/index.tsx" }, + "6gXdHy": { + "defaultMessage": "Share" + }, "6kMb9Z": { "defaultMessage": "鏈上紀錄" }, @@ -785,6 +788,10 @@ "9WRlF4": { "defaultMessage": "送出" }, + "9ZBatB": { + "defaultMessage": "Quote", + "description": "src/components/TextSelectionPopover/index.tsx" + }, "9aorag": { "defaultMessage": "取消喜歡選集" }, @@ -862,6 +869,10 @@ "AlHYvk": { "defaultMessage": "{type}已編輯" }, + "Aq0aMp": { + "defaultMessage": "Only participants can join the discussion.", + "description": "src/views/CampaignDetail/Discussion" + }, "At8Qd2": { "defaultMessage": "帳號", "description": "src/views/Me/Settings/Settings/SettingsTabs/index.tsx" @@ -1605,6 +1616,10 @@ "Mgl1bT": { "defaultMessage": "應用授權" }, + "Mh+PgK": { + "defaultMessage": "No discussion yet", + "description": "src/views/CampaignDetail/Discussion" + }, "Mn7GEf": { "defaultMessage": "精選過去 24 小時與你有關的消息", "description": "src/views/Me/Settings/Notifications/Email.tsx" @@ -1863,6 +1878,108 @@ "Qlzm0s": { "defaultMessage": "在動態中提及了你" }, + "QuoteImage.download": { + "defaultMessage": "Download" + }, + "QuoteImage.onWall": { + "defaultMessage": "On the wall ✓" + }, + "QuoteImage.postToWall": { + "defaultMessage": "Post to wall" + }, + "QuoteImage.postedToWall": { + "defaultMessage": "Posted to the quote wall" + }, + "QuoteImage.size.portrait": { + "defaultMessage": "Portrait 4:5" + }, + "QuoteImage.size.square": { + "defaultMessage": "Square 1:1" + }, + "QuoteImage.size.story": { + "defaultMessage": "Story 9:16" + }, + "QuoteImage.sizeLabel": { + "defaultMessage": "Size" + }, + "QuoteImage.sizeNote.portrait": { + "defaultMessage": "IG post · most eye-catching" + }, + "QuoteImage.sizeNote.square": { + "defaultMessage": "IG / FB post" + }, + "QuoteImage.sizeNote.story": { + "defaultMessage": "IG / FB story · Threads" + }, + "QuoteImage.style.coral": { + "defaultMessage": "Coral" + }, + "QuoteImage.style.ink": { + "defaultMessage": "Ink" + }, + "QuoteImage.style.mint": { + "defaultMessage": "Mint" + }, + "QuoteImage.style.pine": { + "defaultMessage": "Pine" + }, + "QuoteImage.style.sky": { + "defaultMessage": "Sky" + }, + "QuoteImage.style.slate": { + "defaultMessage": "Slate" + }, + "QuoteImage.style.violet": { + "defaultMessage": "Violet" + }, + "QuoteImage.style.warm": { + "defaultMessage": "Cream" + }, + "QuoteImage.styleLabel": { + "defaultMessage": "Style" + }, + "QuoteImage.title": { + "defaultMessage": "Share Quote" + }, + "QuoteImage.truncated": { + "defaultMessage": "You selected {original} characters; only the first {max} are shown. A concise quote works best." + }, + "QuoteImage.wallFailed": { + "defaultMessage": "Failed to post to the wall" + }, + "QuoteImage.wallQuota": { + "defaultMessage": "Wall quota reached for today — come back tomorrow!" + }, + "QuoteWall.confirmRetract": { + "defaultMessage": "Confirm retract" + }, + "QuoteWall.fullWall": { + "defaultMessage": "Full wall →" + }, + "QuoteWall.museum": { + "defaultMessage": "Full wall / Museum →" + }, + "QuoteWall.retract": { + "defaultMessage": "Retract" + }, + "QuoteWall.retractFailed": { + "defaultMessage": "Failed to retract" + }, + "QuoteWall.retracted": { + "defaultMessage": "Quote retracted from the wall" + }, + "QuoteWall.shuffle": { + "defaultMessage": "🔀 Shuffle" + }, + "QuoteWall.title": { + "defaultMessage": "Quote wall" + }, + "QuoteWall.toArticle": { + "defaultMessage": "To article ↩" + }, + "QuoteWall.viewAll": { + "defaultMessage": "View all {count} quotes" + }, "QvPc1q": { "defaultMessage": "上傳封面" }, @@ -2155,6 +2272,10 @@ "defaultMessage": "草稿", "description": "src/views/Me/Works/WorksTabs/index.tsx" }, + "Vj0Hbd": { + "defaultMessage": "View all {count} comments", + "description": "src/views/CampaignDetail/Discussion" + }, "VmYzLr": { "defaultMessage": "{total} 個成員" }, @@ -2427,6 +2548,10 @@ "aKEiNd": { "defaultMessage": "錯過報名期沒關係,仍然可以用晚鳥身份參與,一起書寫人生故事。下次早點報名,就有機會獲得大滿貫徽章!" }, + "aLkBs2": { + "defaultMessage": "Discussion", + "description": "src/views/CampaignDetail/Discussion" + }, "aOFCqL": { "defaultMessage": "最多評論", "description": "src/views/Me/Works/Published/SortTabs.tsx" @@ -2486,6 +2611,10 @@ "defaultMessage": "你的作品 {articleTitle} 已被列為活動精選,快來看看更多精彩好文!", "description": "src/components/Notice/CampaignArticleNotice/CampaignArticleFeaturedNotice.tsx" }, + "b3aGfp": { + "defaultMessage": "Share your thoughts with other participants", + "description": "src/views/CampaignDetail/Discussion" + }, "b6x6lm": { "defaultMessage": "輸入簡單明瞭的標題" }, @@ -2922,6 +3051,10 @@ "iIitRg": { "defaultMessage": "尚未收藏標籤" }, + "iJfVZG": { + "defaultMessage": "Quote card", + "description": "src/components/TextSelectionPopover/index.tsx" + }, "iNZdM/": { "defaultMessage": "切換後即可支持創作者,採用 Optimism 網路{br}讓支持更方便且費用低廉", "description": "src/components/Forms/PaymentForm/SwitchNetwork/index.tsx" @@ -2929,6 +3062,9 @@ "iSM+et": { "defaultMessage": "作者保留所有權利" }, + "iSUeWj": { + "defaultMessage": "Comment sent" + }, "iTcMqz": { "defaultMessage": "月色之下,夢想即將實現。月之夢徽章紀念你曾參與「遊牧者計畫」。", "description": "src/views/User/UserProfile/BadgeNomadLabel/index.tsx" diff --git a/package-lock.json b/package-lock.json index 9310f52953..8569df9d60 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "matters-web", - "version": "6.7.0", + "version": "6.11.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "matters-web", - "version": "6.7.0", + "version": "6.11.1", "license": "Apache-2.0", "dependencies": { "@apollo/client": "^3.13.8", @@ -47,6 +47,7 @@ "formik": "^2.4.6", "graphql": "^16.11.0", "graphql-tag": "^2.12.6", + "html-to-image": "^1.11.13", "husky": "^9.1.7", "js-base64": "^3.7.7", "js-cookie": "^3.0.5", @@ -61,6 +62,7 @@ "number-precision": "^1.6.0", "path-to-regexp": "^8.2.0", "photoswipe": "^5.4.4", + "qrcode": "^1.5.4", "react": "^18.3.1", "react-aria-components": "^1.10.1", "react-beautiful-dnd": "^13.1.1", @@ -109,6 +111,7 @@ "@types/jump.js": "^1.0.6", "@types/lodash": "^4.17.17", "@types/nprogress": "0.2.3", + "@types/qrcode": "^1.5.5", "@types/react": "^18.3.22", "@types/react-beautiful-dnd": "^13.1.8", "@types/react-dom": "^18.3.7", @@ -12200,6 +12203,149 @@ "qrcode": "1.5.3" } }, + "node_modules/@reown/appkit-ui/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@reown/appkit-ui/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/@reown/appkit-ui/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@reown/appkit-ui/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@reown/appkit-ui/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@reown/appkit-ui/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@reown/appkit-ui/node_modules/qrcode": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.3.tgz", + "integrity": "sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg==", + "license": "MIT", + "dependencies": { + "dijkstrajs": "^1.0.1", + "encode-utf8": "^1.0.3", + "pngjs": "^5.0.0", + "yargs": "^15.3.1" + }, + "bin": { + "qrcode": "bin/qrcode" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@reown/appkit-ui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@reown/appkit-ui/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "license": "ISC" + }, + "node_modules/@reown/appkit-ui/node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "license": "MIT", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@reown/appkit-ui/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/@reown/appkit-utils": { "version": "1.7.8", "resolved": "https://registry.npmjs.org/@reown/appkit-utils/-/appkit-utils-1.7.8.tgz", @@ -16572,6 +16718,16 @@ "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", "license": "MIT" }, + "node_modules/@types/qrcode": { + "version": "1.5.6", + "resolved": "https://registry.npmjs.org/@types/qrcode/-/qrcode-1.5.6.tgz", + "integrity": "sha512-te7NQcV2BOvdj2b1hCAHzAoMNuj65kNBMz0KBaxM6c3VGBOhU0dURQKOtH8CFNI/dsKkwlv32p26qYQTWoB5bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/react": { "version": "18.3.23", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.23.tgz", @@ -27351,6 +27507,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/html-to-image": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/html-to-image/-/html-to-image-1.11.13.tgz", + "integrity": "sha512-cuOPoI7WApyhBElTTb9oqsawRvZ0rHhaHwghRLlTuffoD1B2aDemlCruLeZrUIIdvG7gs9xeELEPm6PhuASqrg==", + "license": "MIT" + }, "node_modules/html-url-attributes": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz", @@ -35637,13 +35799,12 @@ } }, "node_modules/qrcode": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.3.tgz", - "integrity": "sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz", + "integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==", "license": "MIT", "dependencies": { "dijkstrajs": "^1.0.1", - "encode-utf8": "^1.0.3", "pngjs": "^5.0.0", "yargs": "^15.3.1" }, @@ -50934,6 +51095,107 @@ "@reown/appkit-wallet": "1.7.8", "lit": "3.3.0", "qrcode": "1.5.3" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + }, + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "requires": { + "p-limit": "^2.2.0" + } + }, + "qrcode": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.3.tgz", + "integrity": "sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg==", + "requires": { + "dijkstrajs": "^1.0.1", + "encode-utf8": "^1.0.3", + "pngjs": "^5.0.0", + "yargs": "^15.3.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" + }, + "yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + } + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } } }, "@reown/appkit-utils": { @@ -53424,6 +53686,15 @@ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==" }, + "@types/qrcode": { + "version": "1.5.6", + "resolved": "https://registry.npmjs.org/@types/qrcode/-/qrcode-1.5.6.tgz", + "integrity": "sha512-te7NQcV2BOvdj2b1hCAHzAoMNuj65kNBMz0KBaxM6c3VGBOhU0dURQKOtH8CFNI/dsKkwlv32p26qYQTWoB5bw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/react": { "version": "18.3.23", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.23.tgz", @@ -60545,6 +60816,11 @@ "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", "dev": true }, + "html-to-image": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/html-to-image/-/html-to-image-1.11.13.tgz", + "integrity": "sha512-cuOPoI7WApyhBElTTb9oqsawRvZ0rHhaHwghRLlTuffoD1B2aDemlCruLeZrUIIdvG7gs9xeELEPm6PhuASqrg==" + }, "html-url-attributes": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz", @@ -65822,12 +66098,11 @@ "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==" }, "qrcode": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.3.tgz", - "integrity": "sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz", + "integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==", "requires": { "dijkstrajs": "^1.0.1", - "encode-utf8": "^1.0.3", "pngjs": "^5.0.0", "yargs": "^15.3.1" }, diff --git a/package.json b/package.json index d2c462d426..043f09a8a3 100644 --- a/package.json +++ b/package.json @@ -81,6 +81,7 @@ "formik": "^2.4.6", "graphql": "^16.11.0", "graphql-tag": "^2.12.6", + "html-to-image": "^1.11.13", "husky": "^9.1.7", "js-base64": "^3.7.7", "js-cookie": "^3.0.5", @@ -95,6 +96,7 @@ "number-precision": "^1.6.0", "path-to-regexp": "^8.2.0", "photoswipe": "^5.4.4", + "qrcode": "^1.5.4", "react": "^18.3.1", "react-aria-components": "^1.10.1", "react-beautiful-dnd": "^13.1.1", @@ -143,6 +145,7 @@ "@types/jump.js": "^1.0.6", "@types/lodash": "^4.17.17", "@types/nprogress": "0.2.3", + "@types/qrcode": "^1.5.5", "@types/react": "^18.3.22", "@types/react-beautiful-dnd": "^13.1.8", "@types/react-dom": "^18.3.7", diff --git a/public/static/images/seven-day-book-logo-dark.svg b/public/static/images/seven-day-book-logo-dark.svg new file mode 100644 index 0000000000..96e18fa5c5 --- /dev/null +++ b/public/static/images/seven-day-book-logo-dark.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/public/static/images/seven-day-book-logo-white.svg b/public/static/images/seven-day-book-logo-white.svg new file mode 100644 index 0000000000..65f5a9c033 --- /dev/null +++ b/public/static/images/seven-day-book-logo-white.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/common/enums/externalLinks.ts b/src/common/enums/externalLinks.ts index e5ff12bc70..62112e7561 100644 --- a/src/common/enums/externalLinks.ts +++ b/src/common/enums/externalLinks.ts @@ -14,6 +14,7 @@ export const EXTERNAL_LINKS = { isProd ? `https://liker.land/${likerId}/civic?utm_source=Matters` : `https://rinkeby.liker.land/${likerId}/civic?utm_source=Matters`, + SEVEN_DAY_BOOK_QUOTE_WALL: 'https://freewriting.matters.town/memo-wall', PLANET: 'https://www.planetable.xyz/', ENS_DOCS: 'https://docs.ens.domains/', METAMASK: 'https://metamask.io/download/', diff --git a/src/common/enums/index.ts b/src/common/enums/index.ts index 9a7c853655..c249722555 100644 --- a/src/common/enums/index.ts +++ b/src/common/enums/index.ts @@ -67,6 +67,8 @@ export const MAX_ARTICLE_COLLECT_LENGTH = 3 export const MAX_MOMENT_CONTENT_LENGTH = 240 export const MAX_MOMENT_COMMENT_LENGTH = 240 +// campaign discussion comment length cap (matches 短動態 = 240) +export const MAX_CAMPAIGN_COMMENT_LENGTH = 240 export const MAX_FIGURE_CAPTION_LENGTH = 100 export const MAX_TAG_CONTENT_LENGTH = 50 diff --git a/src/common/enums/text.ts b/src/common/enums/text.ts index 963c3d2ef1..a9e5569b5c 100644 --- a/src/common/enums/text.ts +++ b/src/common/enums/text.ts @@ -3,16 +3,19 @@ export const COMMENT_TYPE_TEXT = { article: '評論', circleBroadcast: '廣播', circleDiscussion: '眾聊', + campaignDiscussion: '留言', }, zh_hans: { article: '评论', circleBroadcast: '广播', circleDiscussion: '众聊', + campaignDiscussion: '留言', }, en: { article: 'comment', circleBroadcast: 'broadcast', circleDiscussion: 'thread', + campaignDiscussion: 'comment', }, } diff --git a/src/common/utils/analytics.ts b/src/common/utils/analytics.ts index a29187e50a..10a7e47565 100644 --- a/src/common/utils/analytics.ts +++ b/src/common/utils/analytics.ts @@ -90,6 +90,10 @@ export interface ClickButtonProp { | 'edited' | 'appreciate' | 'article_content_quote' + | 'article_content_quote_image' + | 'quote_image_download' + | 'quote_image_share' + | 'quote_post_to_wall' | 'comment_open' | 'comment_close' | 'comment_placeholder' diff --git a/src/common/utils/route.ts b/src/common/utils/route.ts index 299535876d..457fce7892 100644 --- a/src/common/utils/route.ts +++ b/src/common/utils/route.ts @@ -48,7 +48,12 @@ interface CampaignStageArgs { interface CommentArgs { id: string - type: 'article' | 'circleDiscussion' | 'circleBroadcast' | 'moment' // comment type: article/discussion/broadcast + type: + | 'article' + | 'circleDiscussion' + | 'circleBroadcast' + | 'moment' + | 'campaignDiscussion' // comment type: article/discussion/broadcast/campaign parentComment?: { id: string } | null diff --git a/src/components/CircleComment/Content/index.tsx b/src/components/CircleComment/Content/index.tsx index 07981b1db2..adcbbeada6 100644 --- a/src/components/CircleComment/Content/index.tsx +++ b/src/components/CircleComment/Content/index.tsx @@ -63,6 +63,10 @@ export const CircleCommentContent = ({ const { content, state } = comment const isBlocked = comment.author?.isBlocked + // campaign discussion: collapse long comments after fewer lines (tunable), + // since they are capped at 240 chars and would never hit the default of 10 + const expandLimit = type === 'campaignDiscussion' ? 4 : limit + const contentClasses = classNames({ [styles.content]: true, [size ? styles[`size${size}`] : '']: !!size, @@ -96,7 +100,7 @@ export const CircleCommentContent = ({ <> { const { isArchived, isBanned, isFrozen } = viewer const circle = comment.node.__typename === 'Circle' ? comment.node : undefined + const campaign = + comment.node.__typename === 'WritingChallenge' ? comment.node : undefined const targetAuthor = circle?.owner const isTargetAuthor = viewer.id === targetAuthor?.id @@ -222,7 +230,8 @@ const DropdownActions = (props: DropdownActionsProps) => { BaseDropdownActions as React.ComponentType, CircleCommentFormDialog, { - circleId: circle?.id || '', + circleId: circle?.id, + campaignId: campaign?.id, type, commentId: comment.id, defaultContent: comment.content, diff --git a/src/components/CircleComment/FooterActions/ReplyButton/index.tsx b/src/components/CircleComment/FooterActions/ReplyButton/index.tsx index 178176b3d6..605c5f0ac9 100644 --- a/src/components/CircleComment/FooterActions/ReplyButton/index.tsx +++ b/src/components/CircleComment/FooterActions/ReplyButton/index.tsx @@ -44,6 +44,9 @@ const fragments = { id } } + ... on WritingChallenge { + id + } } parentComment { id @@ -86,6 +89,7 @@ const ReplyButton = ({ const { id, parentComment, author, node } = comment const circle = node.__typename === 'Circle' ? node : undefined + const campaign = node.__typename === 'WritingChallenge' ? node : undefined const submitCallback = () => { if (replySubmitCallback) { @@ -126,7 +130,8 @@ const ReplyButton = ({ return ( = ({ replyToId, parentId, circleId, + campaignId, type, defaultContent, @@ -65,7 +68,7 @@ const CommentForm: React.FC = ({ const formStorageKey = formStorage.genCircleCommentKey({ authorId: viewer.id, - circleId, + circleId: circleId ?? campaignId ?? '', type, commentId, parentId, @@ -77,7 +80,12 @@ const CommentForm: React.FC = ({ defaultContent || '' ) - const isValid = stripHtml(content).length > 0 + // campaign discussion comments are capped at 240 chars (like 短動態) + const maxLength = + type === 'campaignDiscussion' ? MAX_CAMPAIGN_COMMENT_LENGTH : undefined + const contentLength = stripHtml(content).length + const isOverLength = maxLength !== undefined && contentLength > maxLength + const isValid = contentLength > 0 && !isOverLength const handleSubmit = async (event?: React.FormEvent) => { const mentions = dom.getAttributes('data-id', content) @@ -88,6 +96,7 @@ const CommentForm: React.FC = ({ content, replyTo: replyToId, circleId, + campaignId, parentId, type, mentions, @@ -181,6 +190,14 @@ const CommentForm: React.FC = ({ window.dispatchEvent(new CustomEvent(formStorageKey)) } /> + {maxLength !== undefined && ( +

+ {contentLength} / {maxLength} +

+ )} diff --git a/src/components/Dialogs/CircleCommentFormDialog/CommentForm/styles.module.css b/src/components/Dialogs/CircleCommentFormDialog/CommentForm/styles.module.css index 2e64c69459..a8a31b19bc 100644 --- a/src/components/Dialogs/CircleCommentFormDialog/CommentForm/styles.module.css +++ b/src/components/Dialogs/CircleCommentFormDialog/CommentForm/styles.module.css @@ -11,3 +11,14 @@ flex-grow: 1; overflow-y: auto; } + +.counter { + margin-top: var(--sp8); + font-size: var(--text12); + color: var(--color-grey); + text-align: right; +} + +.counter[data-over='true'] { + color: var(--color-red); +} diff --git a/src/components/Forms/CircleCommentForm/index.tsx b/src/components/Forms/CircleCommentForm/index.tsx index 769b42eb03..b3b7b35781 100644 --- a/src/components/Forms/CircleCommentForm/index.tsx +++ b/src/components/Forms/CircleCommentForm/index.tsx @@ -3,6 +3,7 @@ import dynamic from 'next/dynamic' import { useContext, useState } from 'react' import { useIntl } from 'react-intl' +import { MAX_CAMPAIGN_COMMENT_LENGTH } from '~/common/enums' import { dom, formStorage, stripHtml } from '~/common/utils' import { Button, @@ -24,13 +25,18 @@ const CommentEditor = dynamic(() => import('~/components/Editor/Comment'), { loading: () => , }) -export type CircleCommentFormType = 'circleDiscussion' | 'circleBroadcast' +export type CircleCommentFormType = + | 'circleDiscussion' + | 'circleBroadcast' + | 'campaignDiscussion' export interface CircleCommentFormProps { commentId?: string replyToId?: string parentId?: string - circleId: string + // exactly one of circleId / campaignId is set, depending on `type` + circleId?: string + campaignId?: string type: CircleCommentFormType defaultContent?: string | null @@ -44,6 +50,7 @@ export const CircleCommentForm: React.FC = ({ replyToId, parentId, circleId, + campaignId, type, defaultContent, @@ -64,7 +71,7 @@ export const CircleCommentForm: React.FC = ({ const formStorageKey = formStorage.genCircleCommentKey({ authorId: viewer.id, - circleId, + circleId: circleId ?? campaignId ?? '', type, commentId, parentId, @@ -77,7 +84,13 @@ export const CircleCommentForm: React.FC = ({ defaultContent || '' ) - const isValid = stripHtml(content).length > 0 + // campaign discussion comments are capped at 240 chars (like 短動態) + const maxLength = + type === 'campaignDiscussion' ? MAX_CAMPAIGN_COMMENT_LENGTH : undefined + const contentLength = stripHtml(content).length + const isOverLength = + maxLength !== undefined && contentLength > maxLength + const isValid = contentLength > 0 && !isOverLength const handleSubmit = async (event?: React.FormEvent) => { const mentions = dom.getAttributes('data-id', content) @@ -87,6 +100,7 @@ export const CircleCommentForm: React.FC = ({ content, replyTo: replyToId, circleId, + campaignId, parentId, type, mentions, @@ -161,6 +175,14 @@ export const CircleCommentForm: React.FC = ({