| 
									
										
										
										
											2023-01-08 06:21:09 +00:00
										 |  |  | import type { mastodon } from 'masto' | 
					
						
							| 
									
										
										
										
											2022-12-01 06:46:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-28 21:44:23 +00:00
										 |  |  | type Action = 'reblogged' | 'favourited' | 'bookmarked' | 'pinned' | 'muted' | 
					
						
							| 
									
										
										
										
											2022-12-01 06:46:26 +00:00
										 |  |  | type CountField = 'reblogsCount' | 'favouritesCount' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export interface StatusActionsProps { | 
					
						
							| 
									
										
										
										
											2023-01-08 06:21:09 +00:00
										 |  |  |   status: mastodon.v1.Status | 
					
						
							| 
									
										
										
										
											2022-12-01 06:46:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export function useStatusActions(props: StatusActionsProps) { | 
					
						
							| 
									
										
										
										
											2023-01-08 06:21:09 +00:00
										 |  |  |   let status = $ref<mastodon.v1.Status>({ ...props.status }) | 
					
						
							| 
									
										
										
										
											2023-01-15 08:38:02 +00:00
										 |  |  |   const { client } = $(useMasto()) | 
					
						
							| 
									
										
										
										
											2022-12-01 06:46:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   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, | 
					
						
							| 
									
										
										
										
											2022-12-28 21:44:23 +00:00
										 |  |  |     muted: false, | 
					
						
							| 
									
										
										
										
											2022-12-01 06:46:26 +00:00
										 |  |  |   }) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-08 06:21:09 +00:00
										 |  |  |   async function toggleStatusAction(action: Action, fetchNewStatus: () => Promise<mastodon.v1.Status>, countField?: CountField) { | 
					
						
							| 
									
										
										
										
											2022-12-02 02:18:57 +00:00
										 |  |  |     // check login
 | 
					
						
							|  |  |  |     if (!checkLogin()) | 
					
						
							|  |  |  |       return | 
					
						
							| 
									
										
										
										
											2023-01-08 13:24:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-12 18:48:52 +00:00
										 |  |  |     const prevCount = countField ? status[countField] : undefined | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-02 16:55:52 +00:00
										 |  |  |     isLoading[action] = true | 
					
						
							| 
									
										
										
										
											2023-01-12 18:48:52 +00:00
										 |  |  |     const isCancel = status[action] | 
					
						
							| 
									
										
										
										
											2022-12-02 16:55:52 +00:00
										 |  |  |     fetchNewStatus().then((newStatus) => { | 
					
						
							| 
									
										
										
										
											2023-01-12 18:48:52 +00:00
										 |  |  |       // when the action is cancelled, the count is not updated highly likely (if they're the same)
 | 
					
						
							|  |  |  |       // issue of Mastodon API
 | 
					
						
							|  |  |  |       if (isCancel && countField && prevCount === newStatus[countField]) | 
					
						
							|  |  |  |         newStatus[countField] -= 1 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-02 16:55:52 +00:00
										 |  |  |       Object.assign(status, newStatus) | 
					
						
							| 
									
										
										
										
											2022-12-25 14:52:37 +00:00
										 |  |  |       cacheStatus(newStatus, undefined, true) | 
					
						
							| 
									
										
										
										
											2022-12-02 16:55:52 +00:00
										 |  |  |     }).finally(() => { | 
					
						
							|  |  |  |       isLoading[action] = false | 
					
						
							|  |  |  |     }) | 
					
						
							| 
									
										
										
										
											2022-12-02 02:18:57 +00:00
										 |  |  |     // Optimistic update
 | 
					
						
							| 
									
										
										
										
											2022-12-01 06:46:26 +00:00
										 |  |  |     status[action] = !status[action] | 
					
						
							| 
									
										
										
										
											2022-12-25 14:52:37 +00:00
										 |  |  |     cacheStatus(status, undefined, true) | 
					
						
							| 
									
										
										
										
											2022-12-01 06:46:26 +00:00
										 |  |  |     if (countField) | 
					
						
							|  |  |  |       status[countField] += status[action] ? 1 : -1 | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-01-08 13:24:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   const canReblog = $computed(() => | 
					
						
							|  |  |  |     status.visibility !== 'direct' | 
					
						
							|  |  |  |     && (status.visibility !== 'private' || status.account.id === currentUser.value?.account.id), | 
					
						
							|  |  |  |   ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-01 06:46:26 +00:00
										 |  |  |   const toggleReblog = () => toggleStatusAction( | 
					
						
							|  |  |  |     'reblogged', | 
					
						
							| 
									
										
										
										
											2023-01-15 08:38:02 +00:00
										 |  |  |     () => client.v1.statuses[status.reblogged ? 'unreblog' : 'reblog'](status.id).then((res) => { | 
					
						
							| 
									
										
										
										
											2022-12-01 06:46:26 +00:00
										 |  |  |       if (status.reblogged) | 
					
						
							|  |  |  |       // returns the original status
 | 
					
						
							|  |  |  |         return res.reblog! | 
					
						
							|  |  |  |       return res | 
					
						
							|  |  |  |     }), | 
					
						
							|  |  |  |     'reblogsCount', | 
					
						
							|  |  |  |   ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const toggleFavourite = () => toggleStatusAction( | 
					
						
							|  |  |  |     'favourited', | 
					
						
							| 
									
										
										
										
											2023-01-15 08:38:02 +00:00
										 |  |  |     () => client.v1.statuses[status.favourited ? 'unfavourite' : 'favourite'](status.id), | 
					
						
							| 
									
										
										
										
											2022-12-01 06:46:26 +00:00
										 |  |  |     'favouritesCount', | 
					
						
							|  |  |  |   ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const toggleBookmark = () => toggleStatusAction( | 
					
						
							|  |  |  |     'bookmarked', | 
					
						
							| 
									
										
										
										
											2023-01-15 08:38:02 +00:00
										 |  |  |     () => client.v1.statuses[status.bookmarked ? 'unbookmark' : 'bookmark'](status.id), | 
					
						
							| 
									
										
										
										
											2022-12-01 06:46:26 +00:00
										 |  |  |   ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const togglePin = async () => toggleStatusAction( | 
					
						
							|  |  |  |     'pinned', | 
					
						
							| 
									
										
										
										
											2023-01-15 08:38:02 +00:00
										 |  |  |     () => client.v1.statuses[status.pinned ? 'unpin' : 'pin'](status.id), | 
					
						
							| 
									
										
										
										
											2022-12-01 06:46:26 +00:00
										 |  |  |   ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-28 21:44:23 +00:00
										 |  |  |   const toggleMute = async () => toggleStatusAction( | 
					
						
							|  |  |  |     'muted', | 
					
						
							| 
									
										
										
										
											2023-01-15 08:38:02 +00:00
										 |  |  |     () => client.v1.statuses[status.muted ? 'unmute' : 'mute'](status.id), | 
					
						
							| 
									
										
										
										
											2022-12-28 21:44:23 +00:00
										 |  |  |   ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-01 06:46:26 +00:00
										 |  |  |   return { | 
					
						
							|  |  |  |     status: $$(status), | 
					
						
							|  |  |  |     isLoading: $$(isLoading), | 
					
						
							| 
									
										
										
										
											2023-01-08 13:24:59 +00:00
										 |  |  |     canReblog: $$(canReblog), | 
					
						
							| 
									
										
										
										
											2022-12-28 21:44:23 +00:00
										 |  |  |     toggleMute, | 
					
						
							| 
									
										
										
										
											2022-12-01 06:46:26 +00:00
										 |  |  |     toggleReblog, | 
					
						
							|  |  |  |     toggleFavourite, | 
					
						
							|  |  |  |     toggleBookmark, | 
					
						
							|  |  |  |     togglePin, | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } |