feat: support showing publish failed messages (#1209)
This commit is contained in:
parent
0b2b9a713b
commit
85e163a0ad
23
components/publish/PublishErrMessage.vue
Normal file
23
components/publish/PublishErrMessage.vue
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
defineProps<{
|
||||||
|
describedBy: string
|
||||||
|
}>()
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
inheritAttrs: false,
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
role="alert"
|
||||||
|
:aria-describedby="describedBy"
|
||||||
|
flex="~ col"
|
||||||
|
gap-1 text-sm
|
||||||
|
pt-1 ps-2 pe-1 pb-2
|
||||||
|
text-red-600 dark:text-red-400
|
||||||
|
border="~ base rounded red-600 dark:red-400"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
</template>
|
|
@ -34,7 +34,7 @@ const {
|
||||||
dropZoneRef,
|
dropZoneRef,
|
||||||
} = $(useUploadMediaAttachment($$(draft)))
|
} = $(useUploadMediaAttachment($$(draft)))
|
||||||
|
|
||||||
let { shouldExpanded, isExpanded, isSending, isPublishDisabled, publishDraft } = $(usePublish(
|
let { shouldExpanded, isExpanded, isSending, isPublishDisabled, publishDraft, failedMessages } = $(usePublish(
|
||||||
{
|
{
|
||||||
draftState,
|
draftState,
|
||||||
...$$({ expanded, isUploading, initialDraft: initial }),
|
...$$({ expanded, isUploading, initialDraft: initial }),
|
||||||
|
@ -160,6 +160,29 @@ defineExpose({
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<PublishErrMessage v-if="failedMessages.length > 0" described-by="publish-failed">
|
||||||
|
<head id="publish-failed" flex justify-between>
|
||||||
|
<div flex items-center gap-x-2 font-bold>
|
||||||
|
<div aria-hidden="true" i-ri:error-warning-fill />
|
||||||
|
<p>{{ $t('state.publish_failed') }}</p>
|
||||||
|
</div>
|
||||||
|
<CommonTooltip placement="bottom" :content="$t('action.clear_publish_failed')">
|
||||||
|
<button
|
||||||
|
flex rounded-4 p1 hover:bg-active cursor-pointer transition-100 :aria-label="$t('action.clear_publish_failed')"
|
||||||
|
@click="failedMessages = []"
|
||||||
|
>
|
||||||
|
<span aria-hidden="true" w="1.75em" h="1.75em" i-ri:close-line />
|
||||||
|
</button>
|
||||||
|
</CommonTooltip>
|
||||||
|
</head>
|
||||||
|
<ol ps-2 sm:ps-1>
|
||||||
|
<li v-for="(error, i) in failedMessages" :key="i" flex="~ col sm:row" gap-y-1 sm:gap-x-2>
|
||||||
|
<strong>{{ i + 1 }}.</strong>
|
||||||
|
<span>{{ error }}</span>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</PublishErrMessage>
|
||||||
|
|
||||||
<div relative flex-1 flex flex-col>
|
<div relative flex-1 flex flex-col>
|
||||||
<EditorContent
|
<EditorContent
|
||||||
:editor="editor"
|
:editor="editor"
|
||||||
|
@ -174,15 +197,9 @@ defineExpose({
|
||||||
</div>
|
</div>
|
||||||
{{ $t('state.uploading') }}
|
{{ $t('state.uploading') }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<PublishErrMessage
|
||||||
v-else-if="failedAttachments.length > 0"
|
v-else-if="failedAttachments.length > 0"
|
||||||
role="alert"
|
:described-by="isExceedingAttachmentLimit ? 'upload-failed uploads-per-post' : 'upload-failed'"
|
||||||
:aria-describedby="isExceedingAttachmentLimit ? 'upload-failed uploads-per-post' : 'upload-failed'"
|
|
||||||
flex="~ col"
|
|
||||||
gap-1 text-sm
|
|
||||||
pt-1 ps-2 pe-1 pb-2
|
|
||||||
text-red-600 dark:text-red-400
|
|
||||||
border="~ base rounded red-600 dark:red-400"
|
|
||||||
>
|
>
|
||||||
<head id="upload-failed" flex justify-between>
|
<head id="upload-failed" flex justify-between>
|
||||||
<div flex items-center gap-x-2 font-bold>
|
<div flex items-center gap-x-2 font-bold>
|
||||||
|
@ -191,10 +208,8 @@ defineExpose({
|
||||||
</div>
|
</div>
|
||||||
<CommonTooltip placement="bottom" :content="$t('action.clear_upload_failed')">
|
<CommonTooltip placement="bottom" :content="$t('action.clear_upload_failed')">
|
||||||
<button
|
<button
|
||||||
flex rounded-4 p1
|
flex rounded-4 p1 hover:bg-active cursor-pointer transition-100
|
||||||
hover:bg-active cursor-pointer transition-100
|
:aria-label="$t('action.clear_upload_failed')" @click="failedAttachments = []"
|
||||||
:aria-label="$t('action.clear_upload_failed')"
|
|
||||||
@click="failedAttachments = []"
|
|
||||||
>
|
>
|
||||||
<span aria-hidden="true" w="1.75em" h="1.75em" i-ri:close-line />
|
<span aria-hidden="true" w="1.75em" h="1.75em" i-ri:close-line />
|
||||||
</button>
|
</button>
|
||||||
|
@ -209,7 +224,7 @@ defineExpose({
|
||||||
<span>{{ error[0] }}</span>
|
<span>{{ error[0] }}</span>
|
||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
</div>
|
</PublishErrMessage>
|
||||||
|
|
||||||
<div v-if="draft.attachments.length" flex="~ col gap-2" overflow-auto>
|
<div v-if="draft.attachments.length" flex="~ col gap-2" overflow-auto>
|
||||||
<PublishAttachment
|
<PublishAttachment
|
||||||
|
@ -291,7 +306,18 @@ defineExpose({
|
||||||
</template>
|
</template>
|
||||||
</PublishVisibilityPicker>
|
</PublishVisibilityPicker>
|
||||||
|
|
||||||
<CommonTooltip id="publish-tooltip" placement="top" :content="$t('tooltip.add_publishable_content')" :disabled="!isPublishDisabled">
|
<CommonTooltip v-if="failedMessages.length > 0" id="publish-failed-tooltip" placement="top" :content="$t('tooltip.publish_failed')">
|
||||||
|
<button
|
||||||
|
btn-danger rounded-3 text-sm w-full flex="~ gap1" items-center md:w-fit aria-describedby="publish-failed-tooltip"
|
||||||
|
>
|
||||||
|
<span block>
|
||||||
|
<div block i-carbon:face-dizzy-filled />
|
||||||
|
</span>
|
||||||
|
<span>{{ $t('state.publish_failed') }}</span>
|
||||||
|
</button>
|
||||||
|
</CommonTooltip>
|
||||||
|
|
||||||
|
<CommonTooltip v-else id="publish-tooltip" placement="top" :content="$t('tooltip.add_publishable_content')" :disabled="!isPublishDisabled">
|
||||||
<button
|
<button
|
||||||
btn-solid rounded-3 text-sm w-full flex="~ gap1" items-center
|
btn-solid rounded-3 text-sm w-full flex="~ gap1" items-center
|
||||||
md:w-fit
|
md:w-fit
|
||||||
|
@ -303,6 +329,9 @@ defineExpose({
|
||||||
<span v-if="isSending" block animate-spin preserve-3d>
|
<span v-if="isSending" block animate-spin preserve-3d>
|
||||||
<div block i-ri:loader-2-fill />
|
<div block i-ri:loader-2-fill />
|
||||||
</span>
|
</span>
|
||||||
|
<span v-if="failedMessages.length" block>
|
||||||
|
<div block i-carbon:face-dizzy-filled />
|
||||||
|
</span>
|
||||||
<span v-if="draft.editingStatus">{{ $t('action.save_changes') }}</span>
|
<span v-if="draft.editingStatus">{{ $t('action.save_changes') }}</span>
|
||||||
<span v-else-if="draft.params.inReplyToId">{{ $t('action.reply') }}</span>
|
<span v-else-if="draft.params.inReplyToId">{{ $t('action.reply') }}</span>
|
||||||
<span v-else>{{ !isSending ? $t('action.publish') : $t('state.publishing') }}</span>
|
<span v-else>{{ !isSending ? $t('action.publish') : $t('state.publishing') }}</span>
|
||||||
|
|
|
@ -16,12 +16,18 @@ export const usePublish = (options: {
|
||||||
|
|
||||||
let isSending = $ref(false)
|
let isSending = $ref(false)
|
||||||
const isExpanded = $ref(false)
|
const isExpanded = $ref(false)
|
||||||
|
const failedMessages = $ref<string[]>([])
|
||||||
|
|
||||||
const shouldExpanded = $computed(() => expanded || isExpanded || !isEmpty)
|
const shouldExpanded = $computed(() => expanded || isExpanded || !isEmpty)
|
||||||
const isPublishDisabled = $computed(() => {
|
const isPublishDisabled = $computed(() => {
|
||||||
return isEmpty || isUploading || isSending || (draft.attachments.length === 0 && !draft.params.status)
|
return isEmpty || isUploading || isSending || (draft.attachments.length === 0 && !draft.params.status) || failedMessages.length > 0
|
||||||
})
|
})
|
||||||
|
|
||||||
|
watch(() => draft, () => {
|
||||||
|
if (failedMessages.length > 0)
|
||||||
|
failedMessages.length = 0
|
||||||
|
}, { deep: true })
|
||||||
|
|
||||||
async function publishDraft() {
|
async function publishDraft() {
|
||||||
let content = htmlToText(draft.params.status || '')
|
let content = htmlToText(draft.params.status || '')
|
||||||
if (draft.mentions?.length)
|
if (draft.mentions?.length)
|
||||||
|
@ -63,6 +69,7 @@ export const usePublish = (options: {
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
|
failedMessages.push((err as Error).message)
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
isSending = false
|
isSending = false
|
||||||
|
@ -74,6 +81,7 @@ export const usePublish = (options: {
|
||||||
isExpanded,
|
isExpanded,
|
||||||
shouldExpanded,
|
shouldExpanded,
|
||||||
isPublishDisabled,
|
isPublishDisabled,
|
||||||
|
failedMessages,
|
||||||
|
|
||||||
publishDraft,
|
publishDraft,
|
||||||
})
|
})
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
"boost": "Boost",
|
"boost": "Boost",
|
||||||
"boost_count": "{0}",
|
"boost_count": "{0}",
|
||||||
"boosted": "Boosted",
|
"boosted": "Boosted",
|
||||||
|
"clear_publish_failed": "Clear publish errors",
|
||||||
"clear_upload_failed": "Clear file upload errors",
|
"clear_upload_failed": "Clear file upload errors",
|
||||||
"close": "Close",
|
"close": "Close",
|
||||||
"compose": "Compose",
|
"compose": "Compose",
|
||||||
|
@ -400,6 +401,7 @@
|
||||||
"edited": "(Edited)",
|
"edited": "(Edited)",
|
||||||
"editing": "Editing",
|
"editing": "Editing",
|
||||||
"loading": "Loading...",
|
"loading": "Loading...",
|
||||||
|
"publish_failed": "Publish failed",
|
||||||
"publishing": "Publishing",
|
"publishing": "Publishing",
|
||||||
"upload_failed": "Upload failed",
|
"upload_failed": "Upload failed",
|
||||||
"uploading": "Uploading..."
|
"uploading": "Uploading..."
|
||||||
|
@ -499,6 +501,7 @@
|
||||||
"explore_links_intro": "These news stories are being talked about by people on this and other servers of the decentralized network right now.",
|
"explore_links_intro": "These news stories are being talked about by people on this and other servers of the decentralized network right now.",
|
||||||
"explore_posts_intro": "These posts from this and other servers in the decentralized network are gaining traction on this server right now.",
|
"explore_posts_intro": "These posts from this and other servers in the decentralized network are gaining traction on this server right now.",
|
||||||
"explore_tags_intro": "These hashtags are gaining traction among people on this and other servers of the decentralized network right now.",
|
"explore_tags_intro": "These hashtags are gaining traction among people on this and other servers of the decentralized network right now.",
|
||||||
|
"publish_failed": "Close failed messages at the top of editor to republish posts",
|
||||||
"toggle_code_block": "Toggle code block"
|
"toggle_code_block": "Toggle code block"
|
||||||
},
|
},
|
||||||
"user": {
|
"user": {
|
||||||
|
|
|
@ -45,7 +45,8 @@
|
||||||
"bookmarked": "已收藏",
|
"bookmarked": "已收藏",
|
||||||
"boost": "转发",
|
"boost": "转发",
|
||||||
"boosted": "已转发",
|
"boosted": "已转发",
|
||||||
"clear_upload_failed": "清除上传失败",
|
"clear_publish_failed": "清除发布失败信息",
|
||||||
|
"clear_upload_failed": "清除上传失败信息",
|
||||||
"close": "关闭",
|
"close": "关闭",
|
||||||
"compose": "撰写",
|
"compose": "撰写",
|
||||||
"confirm": "确认",
|
"confirm": "确认",
|
||||||
|
@ -374,6 +375,8 @@
|
||||||
"edited": "(已编辑)",
|
"edited": "(已编辑)",
|
||||||
"editing": "编辑中",
|
"editing": "编辑中",
|
||||||
"loading": "加载中...",
|
"loading": "加载中...",
|
||||||
|
"publish_failed": "发布失败",
|
||||||
|
"publishing": "发布中...",
|
||||||
"upload_failed": "上传失败",
|
"upload_failed": "上传失败",
|
||||||
"uploading": "上传中..."
|
"uploading": "上传中..."
|
||||||
},
|
},
|
||||||
|
@ -472,6 +475,7 @@
|
||||||
"explore_links_intro": "这些新闻故事正被本站和分布式网络上其他站点的用户谈论。",
|
"explore_links_intro": "这些新闻故事正被本站和分布式网络上其他站点的用户谈论。",
|
||||||
"explore_posts_intro": "来自本站和分布式网络上其他站点的这些嘟文正在本站引起关注。",
|
"explore_posts_intro": "来自本站和分布式网络上其他站点的这些嘟文正在本站引起关注。",
|
||||||
"explore_tags_intro": "这些标签正在本站和分布式网络上其他站点的用户中引起关注。",
|
"explore_tags_intro": "这些标签正在本站和分布式网络上其他站点的用户中引起关注。",
|
||||||
|
"publish_failed": "关闭编辑器上方的错误信息以重新发布帖文。",
|
||||||
"toggle_code_block": "切换代码块"
|
"toggle_code_block": "切换代码块"
|
||||||
},
|
},
|
||||||
"user": {
|
"user": {
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
:root {
|
:root {
|
||||||
--c-border: #eee;
|
--c-border: #eee;
|
||||||
--c-border-dark: #dccfcf;
|
--c-border-dark: #dccfcf;
|
||||||
|
--c-danger: #FF3C1B;
|
||||||
|
--c-danger-active: #B50900;
|
||||||
|
|
||||||
--rgb-bg-base: 250, 250, 250;
|
--rgb-bg-base: 250, 250, 250;
|
||||||
|
|
||||||
|
@ -32,6 +34,8 @@
|
||||||
--c-primary-active: var(--c-dark-primary-active);
|
--c-primary-active: var(--c-dark-primary-active);
|
||||||
--c-primary-light: var(--c-dark-primary-light);
|
--c-primary-light: var(--c-dark-primary-light);
|
||||||
--c-primary-fade: var(--c-dark-primary-fade);
|
--c-primary-fade: var(--c-dark-primary-fade);
|
||||||
|
--c-danger: #FF2810;
|
||||||
|
--c-danger-active: #E02F00;
|
||||||
|
|
||||||
--c-border: #222;
|
--c-border: #222;
|
||||||
--c-border-dark: #545251;
|
--c-border-dark: #545251;
|
||||||
|
|
|
@ -41,6 +41,7 @@ export default defineConfig({
|
||||||
'btn-outline': 'btn-base px-4 py-2 rounded text-$c-primary border border-$c-primary hover:bg-$c-primary hover:text-inverted',
|
'btn-outline': 'btn-base px-4 py-2 rounded text-$c-primary border border-$c-primary hover:bg-$c-primary hover:text-inverted',
|
||||||
'btn-text': 'btn-base px-4 py-2 text-$c-primary hover:text-$c-primary-active',
|
'btn-text': 'btn-base px-4 py-2 text-$c-primary hover:text-$c-primary-active',
|
||||||
'btn-action-icon': 'btn-base hover:bg-active rounded-full h9 w9 flex items-center justify-center disabled:bg-transparent disabled:text-$c-text-secondary',
|
'btn-action-icon': 'btn-base hover:bg-active rounded-full h9 w9 flex items-center justify-center disabled:bg-transparent disabled:text-$c-text-secondary',
|
||||||
|
'btn-danger': 'btn-base px-4 py-2 rounded text-white bg-$c-danger hover:bg-$c-danger-active',
|
||||||
|
|
||||||
// input
|
// input
|
||||||
'input-base-focus': 'focus:outline-none focus:border-$c-primary',
|
'input-base-focus': 'focus:outline-none focus:border-$c-primary',
|
||||||
|
@ -95,6 +96,10 @@ export default defineConfig({
|
||||||
DEFAULT: 'var(--c-primary)',
|
DEFAULT: 'var(--c-primary)',
|
||||||
active: 'var(--c-primary-active)',
|
active: 'var(--c-primary-active)',
|
||||||
},
|
},
|
||||||
|
danger: {
|
||||||
|
DEFAULT: 'var(--c-danger)',
|
||||||
|
active: 'var(--c-danger-active)',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
rules: [
|
rules: [
|
||||||
|
|
Loading…
Reference in a new issue