feat: spacing tokens, actionable failure copy, unified focus ring, 44px touch targets, press feedback
This commit is contained in:
@@ -28,6 +28,7 @@ import AppDialog, { type AppDialogOptions } from './components/AppDialog.vue'
|
||||
import { shanghaiDateKey, useTaskDueClock, watchShanghaiDateRollover } from './lib/task-due-clock'
|
||||
import { readTodaySectionCollapse, writeTodaySectionCollapse, type TodaySectionCollapse } from './lib/today-section-collapse'
|
||||
import { loadTaskOpenTotal } from './lib/task-open-total'
|
||||
import { failureHint } from './failureHint'
|
||||
|
||||
type FolderItem = { id: string; name: string }
|
||||
type TaskList = { id: string; folder_id: string | null; name: string; is_inbox: boolean }
|
||||
@@ -470,7 +471,7 @@ async function api(path: string, options: RequestInit = {}) {
|
||||
...options,
|
||||
})
|
||||
if (!response.ok) {
|
||||
let message = '请求失败'
|
||||
let message = '请求失败,请检查网络后重试'
|
||||
try { const body = await response.json(); message = formatApiErrorDetail(body.detail) } catch { /* noop */ }
|
||||
const requestError = new Error(message) as Error & { status: number }
|
||||
requestError.status = response.status
|
||||
@@ -483,7 +484,7 @@ function toast(message: string) {
|
||||
notice.value = message
|
||||
window.setTimeout(() => { if (notice.value === message) notice.value = '' }, 2400)
|
||||
}
|
||||
function fail(reason: unknown) { error.value = reason instanceof Error ? reason.message : '请求失败' }
|
||||
function fail(reason: unknown) { error.value = failureHint('请求失败', reason) }
|
||||
|
||||
async function syncBrowserTimezone(currentTimezone?: string) {
|
||||
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone
|
||||
@@ -1138,7 +1139,7 @@ async function saveSelectedTaskChanges() {
|
||||
toast('已保存')
|
||||
} catch (reason) {
|
||||
if (recurrenceLoadToken !== selectionToken || selectedTask.value?.id !== taskId) return
|
||||
selectedRepeatError.value = reason instanceof Error ? reason.message : '保存失败'
|
||||
selectedRepeatError.value = failureHint('保存失败', reason)
|
||||
fail(reason)
|
||||
} finally {
|
||||
savingSelectedTask.value = false
|
||||
@@ -1443,7 +1444,7 @@ async function confirmPurgeList() {
|
||||
focusPurgeListTrigger()
|
||||
toast('清单已永久删除')
|
||||
} catch (reason) {
|
||||
purgeListError.value = reason instanceof Error ? reason.message : '永久删除失败'
|
||||
purgeListError.value = failureHint('永久删除失败', reason)
|
||||
} finally {
|
||||
purgeListSubmitting.value = false
|
||||
}
|
||||
@@ -1512,7 +1513,7 @@ async function saveListEditor() {
|
||||
listEditorFolderId.value = current.folder_id ?? ''
|
||||
}
|
||||
listEditorError.value = '名称已保存,但移动文件夹失败,请重试。'
|
||||
} else listEditorError.value = reason instanceof Error ? reason.message : '保存失败'
|
||||
} else listEditorError.value = reason instanceof Error ? reason.message : '保存失败,请检查网络后重试'
|
||||
} finally { listEditorBusy.value = false }
|
||||
}
|
||||
async function archiveListFromEditor() {
|
||||
@@ -1534,7 +1535,7 @@ async function archiveListFromEditor() {
|
||||
}
|
||||
toast('清单已归档')
|
||||
} catch (reason) {
|
||||
listEditorError.value = reason instanceof Error ? reason.message : '归档失败'
|
||||
listEditorError.value = failureHint('归档失败', reason)
|
||||
} finally { listEditorBusy.value = false }
|
||||
}
|
||||
function toggleFolder(id: string) { const next = new Set(expandedFolders.value); next.has(id) ? next.delete(id) : next.add(id); expandedFolders.value = next }
|
||||
|
||||
Reference in New Issue
Block a user