feat(subscription): point an empty search at the WeChat link tip too

Searching for an unindexed account left the user with a two-line explanation
and nowhere to go, even though the very next thing they need — where to copy an
article link from — was already one hover away on the failure screen.

The hint component now takes its own copy, so both moments share the tooltip
while wording the advice for their own situation, and the empty-search copy
collapses to a single line naming the article link as the way forward.

Drops source_not_indexed_try_full_url, the fallback the old copy read from,
which no longer has a caller.
This commit is contained in:
dolphin
2026-07-29 21:36:39 +08:00
parent 8f47b999c6
commit 0c6f87a8a9
4 changed files with 34 additions and 17 deletions
@@ -1634,6 +1634,7 @@
"wechat_link_unrecognized_desc": "This link can't be read for now. Please make sure the link is complete and the page is accessible.",
"wechat_link_retry_hint": "Please check and fix the {{link}}, then press Enter to detect it again.",
"wechat_link_label": "WeChat article link",
"wechat_article_link_label": "WeChat article link",
"wechat_link_copy_tip": "Tap \"···\" in the top-right corner of the article and choose \"Copy Link\", or choose \"Open in Browser\" and copy the URL from the address bar.",
"channel_content_needs_approval": "Channel content requires approval to view",
"channel_create_success": "Channel created successfully",
@@ -1749,7 +1750,6 @@
"share": "Share",
"share_link_copied": "Share link copied to clipboard",
"show_unread_only": "Show unread only",
"source_not_indexed_try_full_url": "This source is not indexed yet. Try entering the full URL above to search or add.",
"sub_channel_name": "Sub-channel Name",
"sub_channel_name_default": "Sub {{index}}",
"sub_channel_name_cannot_be_empty": "Sub-channel name cannot be empty",
@@ -1837,7 +1837,7 @@
"maximum_channel_description": "Maximum 100 characters",
"maximum_channel_name": "Maximum 50 characters",
"need_one_source": "At least 1 source is required",
"no_source_collected": "This source is not indexed yet. Try entering the correct name or full URL in the box above to search or add. For unindexed official accounts, enter an article link URL.",
"no_source_collected": "This source isn't indexed yet. Paste a full web link or a {{link}} into the box above to add it.",
"private": "Private",
"public": "Public",
"publice": "Public",
@@ -1557,6 +1557,7 @@
"wechat_link_unrecognized_desc": "現在このリンクを読み取れません。リンクが完全で、ページに正常にアクセスできることをご確認ください。",
"wechat_link_retry_hint": "{{link}}を確認して修正してください。修正後、Enter キーを押すと再認識します。",
"wechat_link_label": "公式アカウントのリンク",
"wechat_article_link_label": "公式アカウント記事リンク",
"wechat_link_copy_tip": "記事右上の「···」をタップして「リンクをコピー」を選ぶか、「ブラウザで開く」を選んでアドレスバーの URL をコピーしてください。",
"channel_content_needs_approval": "このチャンネルのコンテンツを表示するには承認が必要です",
"channel_create_success": "チャンネルの作成に成功しました",
@@ -1672,7 +1673,6 @@
"share": "共有",
"share_link_copied": "共有リンクがクリップボードにコピーされました",
"show_unread_only": "未読のみ表示",
"source_not_indexed_try_full_url": "この情報源はまだインデックスされていません。上の入力欄に完全なURLを入力して検索または追加をお試しください。",
"sub_channel_name": "サブチャンネル名",
"sub_channel_name_default": "サブ{{index}}",
"sub_channel_name_cannot_be_empty": "サブチャンネル名を空にすることはできません",
@@ -1760,7 +1760,7 @@
"maximum_channel_description": "最大100文字まで入力できます",
"maximum_channel_name": "最大50文字まで入力できます",
"need_one_source": "少なくとも1つの情報源が必要です",
"no_source_collected": "この情報源はまだ収録されていません。上の入力欄に正しい名称または完全なURLを入力して検索または追加してください。未収録の公式アカウントは、記事リンクのURLを入力してください。",
"no_source_collected": "この情報源はまだ収録されていません。完全なウェブリンクまたは{{link}}を上の入力欄に貼り付けて追加してください。",
"private": "プライベート",
"public": "公開",
"publice": "公開",
@@ -1561,6 +1561,7 @@
"wechat_link_unrecognized_desc": "暂时无法读取该链接,请确认链接完整、页面可以正常访问。",
"wechat_link_retry_hint": "请检查并修改{{link}}。修改完成后,按回车重新识别。",
"wechat_link_label": "公众号链接",
"wechat_article_link_label": "公众号文章链接",
"wechat_link_copy_tip": "点击文章右上角「···」,选择「复制链接」,或选择「在浏览器打开」后复制地址栏中的链接。",
"channel_content_needs_approval": "该频道内容需申请通过后方可查看",
"channel_create_success": "频道创建成功",
@@ -1673,7 +1674,6 @@
"share": "分享",
"share_link_copied": "分享链接已复制到粘贴板",
"show_unread_only": "仅看未读",
"source_not_indexed_try_full_url": "暂时没有收录该信源,试试在上方输入框中输入完整的网址,进行检索或添加",
"sub_channel_name": "子频道名称",
"sub_channel_name_default": "子频道名称{{index}}",
"sub_channel_name_cannot_be_empty": "子频道名称不能为空",
@@ -1747,7 +1747,7 @@
"maximum_channel_name": "最多输入 50 个字符",
"maximum_character": "最多输入40个字符",
"need_one_source": "至少需添加 1 个信息源",
"no_source_collected": "暂时没有收录该信源,试试在上方输入框中输入正确名称或完整的网址,进行检索或添加吧。\n未收录的公众号需要输入该公众号文章链接网址来获取。",
"no_source_collected": "暂时没有收录该信源,试试把完整的网页链接或{{link}}粘贴到上方输入框来添加吧。",
"nofound_mathcing_member": "未搜索到相关用户",
"only_filter_criteria": "只订阅信息源中符合过滤条件的内容",
"parsed_articles": "该网站的文章列表:",
@@ -19,17 +19,26 @@ const MAX_SOURCES = 200;
const MAX_NAME_DISPLAY = 20;
/**
* "Fix the link, then press Enter" guidance shown after a WeChat article URL
* fails to resolve. The 「公众号链接」 phrase inside the sentence is highlighted
* and carries a hover tooltip explaining where to copy a valid link from.
* A sentence with one highlighted phrase that hovers open the "where do I copy
* a WeChat article link from" tooltip. Used both after a link fails to resolve
* and when a search turns up nothing — each passes its own copy, since the two
* moments word the advice differently.
*
* The sentence is one i18n key with a `{{link}}` placeholder so translators keep
* control of word order; it is split back apart on the localized phrase.
*/
export function WechatLinkRetryHint({ className }: { className?: string }) {
export function WechatLinkHint({
className,
sentenceKey,
labelKey,
}: {
className?: string;
sentenceKey: string;
labelKey: string;
}) {
const localize = useLocalize();
const linkLabel = localize("com_subscription.wechat_link_label");
const sentence = localize("com_subscription.wechat_link_retry_hint", { link: linkLabel });
const linkLabel = localize(labelKey);
const sentence = localize(sentenceKey, { link: linkLabel });
const splitAt = sentence.indexOf(linkLabel);
const highlighted = (
@@ -386,10 +395,14 @@ export function AddSourceDropdown({
<div className="mb-4">
<ListWebLinkIllustration className="mx-auto block w-[120px] h-[120px]" />
</div>
<p className="text-[14px] font-normal leading-6 text-[#999999] whitespace-pre-line">
{localize("com_subscription.no_source_collected") ||
localize("com_subscription.source_not_indexed_try_full_url")}
</p>
{/* One line: the sentence reads as a single
instruction, so it is kept unwrapped and the
panel scrolls rather than breaking it. */}
<WechatLinkHint
className="max-w-full whitespace-nowrap"
sentenceKey="com_subscription.no_source_collected"
labelKey="com_subscription.wechat_article_link_label"
/>
</div>
)}
{mgr.viewMode === "noResultUrl" && (
@@ -431,7 +444,11 @@ export function AddSourceDropdown({
<CrawlingIllustration className="w-[120px] h-[120px]" />
</div>
{mgr.wechatLinkFailed ? (
<WechatLinkRetryHint className="mb-5 max-w-[300px]" />
<WechatLinkHint
className="mb-5 max-w-[300px]"
sentenceKey="com_subscription.wechat_link_retry_hint"
labelKey="com_subscription.wechat_link_label"
/>
) : (
<p className="text-[14px] font-normal text-[#999999] mb-5">
{localize("com_subscription.detect_wechat_link") || localize("com_subscription.official_account_link_detected_adding")}