diff --git a/components/status/StatusActions.vue b/components/status/StatusActions.vue
index ea3272ba..de9ca77d 100644
--- a/components/status/StatusActions.vue
+++ b/components/status/StatusActions.vue
@@ -1,115 +1,21 @@
@@ -182,83 +81,5 @@ function editStatus() {
@click="toggleBookmark()"
/>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/components/status/StatusActionsMore.vue b/components/status/StatusActionsMore.vue
new file mode 100644
index 00000000..e45618a8
--- /dev/null
+++ b/components/status/StatusActionsMore.vue
@@ -0,0 +1,206 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/status/StatusCard.vue b/components/status/StatusCard.vue
index 88f0336c..7bb7b208 100644
--- a/components/status/StatusCard.vue
+++ b/components/status/StatusCard.vue
@@ -63,12 +63,12 @@ const timeago = useTimeAgo(() => status.createdAt, timeAgoOptions)
-
+
-
@@ -99,7 +100,7 @@ const timeago = useTimeAgo(() => status.createdAt, timeAgoOptions)
:actions="false"
/>
-
+
diff --git a/components/status/StatusDetails.vue b/components/status/StatusDetails.vue
index 42a80164..8127a981 100644
--- a/components/status/StatusDetails.vue
+++ b/components/status/StatusDetails.vue
@@ -18,7 +18,8 @@ const visibility = $computed(() => STATUS_VISIBILITIES.find(v => v.value === sta
-
+
+
diff --git a/composables/masto.ts b/composables/masto.ts
index 72ec095c..a16c0465 100644
--- a/composables/masto.ts
+++ b/composables/masto.ts
@@ -103,7 +103,7 @@ export function getStatusRoute(status: Status) {
})
}
-export function getStatusPermalinkRouteRoute(status: Status) {
+export function getStatusPermalinkRoute(status: Status) {
return status.url
? useRouter().resolve({
name: 'permalink',
diff --git a/composables/status.ts b/composables/status.ts
new file mode 100644
index 00000000..9f771a53
--- /dev/null
+++ b/composables/status.ts
@@ -0,0 +1,77 @@
+import type { Status } from 'masto'
+
+type Action = 'reblogged' | 'favourited' | 'bookmarked' | 'pinned'
+type CountField = 'reblogsCount' | 'favouritesCount'
+
+export interface StatusActionsProps {
+ status: Status
+}
+
+export function useStatusActions(props: StatusActionsProps) {
+ let status = $ref({ ...props.status })
+
+ watch(
+ () => props.status,
+ val => status = { ...val },
+ { deep: true, immediate: true },
+ )
+
+ // Use different states to let the user press different actions right after the other
+ const isLoading = $ref({
+ reblogged: false,
+ favourited: false,
+ bookmarked: false,
+ pinned: false,
+ translation: false,
+ })
+
+ async function toggleStatusAction(action: Action, newStatus: Promise, countField?: CountField) {
+ // Optimistic update
+ status[action] = !status[action]
+ if (countField)
+ status[countField] += status[action] ? 1 : -1
+
+ try {
+ isLoading[action] = true
+ Object.assign(status, await newStatus)
+ }
+ finally {
+ isLoading[action] = false
+ }
+ }
+ const toggleReblog = () => toggleStatusAction(
+ 'reblogged',
+ useMasto().statuses[status.reblogged ? 'unreblog' : 'reblog'](status.id).then((res) => {
+ if (status.reblogged)
+ // returns the original status
+ return res.reblog!
+ return res
+ }),
+ 'reblogsCount',
+ )
+
+ const toggleFavourite = () => toggleStatusAction(
+ 'favourited',
+ useMasto().statuses[status.favourited ? 'unfavourite' : 'favourite'](status.id),
+ 'favouritesCount',
+ )
+
+ const toggleBookmark = () => toggleStatusAction(
+ 'bookmarked',
+ useMasto().statuses[status.bookmarked ? 'unbookmark' : 'bookmark'](status.id),
+ )
+
+ const togglePin = async () => toggleStatusAction(
+ 'pinned',
+ useMasto().statuses[status.pinned ? 'unpin' : 'pin'](status.id),
+ )
+
+ return {
+ status: $$(status),
+ isLoading: $$(isLoading),
+ toggleReblog,
+ toggleFavourite,
+ toggleBookmark,
+ togglePin,
+ }
+}
diff --git a/locales/en-US.json b/locales/en-US.json
index b0f26f8f..70578fcf 100644
--- a/locales/en-US.json
+++ b/locales/en-US.json
@@ -18,10 +18,13 @@
},
"action": {
"bookmark": "Bookmark",
+ "bookmarked": "Bookmarked",
"boost": "Boost",
+ "boosted": "Boosted",
"compose": "Compose",
"enter_app": "Enter App",
"favourite": "Favourite",
+ "favourited": "Favourited",
"more": "More",
"publish": "Publish!",
"reply": "Reply",
diff --git a/locales/zh-CN.json b/locales/zh-CN.json
index 6a41dec8..3fb21eec 100644
--- a/locales/zh-CN.json
+++ b/locales/zh-CN.json
@@ -18,10 +18,13 @@
},
"action": {
"bookmark": "收藏",
+ "bookmarked": "已收藏",
"boost": "转发",
+ "boosted": "已转发",
"compose": "撰写",
"enter_app": "进入应用",
"favourite": "喜欢",
+ "favourited": "已喜欢",
"more": "更多",
"publish": "发布!",
"reply": "回复",
@@ -99,6 +102,7 @@
"placeholder": {
"default_1": "在想些什么?",
"reply_to_account": "回复 {0}",
+ "replying": "回复",
"the_thread": "这个帖子"
},
"state": {