-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: ♻️ Improve Note rendering structure
- Loading branch information
1 parent
d6fe8db
commit c188d97
Showing
5 changed files
with
255 additions
and
190 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<template> | ||
<button class="group disabled:opacity-70 max-w-28 disabled:cursor-not-allowed hover:enabled:bg-dark-800 duration-200 rounded flex flex-1 flex-row items-center justify-center"> | ||
<slot /> | ||
</button> | ||
</template> | ||
|
||
<script lang="ts" setup> | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
<template> | ||
<div | ||
class="mt-6 flex flex-row items-stretch relative justify-around text-sm h-10"> | ||
<InteractionButton @click="useEvent('note:reply', note)" | ||
:disabled="!identity"> | ||
<iconify-icon width="1.25rem" height="1.25rem" icon="tabler:arrow-back-up" | ||
class="text-gray-200 group-hover:group-enabled:text-blue-600" aria-hidden="true" /> | ||
<span class="text-gray-400 mt-0.5 ml-2">{{ numberFormat(note.replies_count) }}</span> | ||
</InteractionButton> | ||
<InteractionButton @click="likeFn" :disabled="!identity"> | ||
<iconify-icon width="1.25rem" height="1.25rem" icon="tabler:heart" v-if="!note.favourited" | ||
class="size-5 text-gray-200 group-hover:group-enabled:text-primary-600" aria-hidden="true" /> | ||
<iconify-icon width="1.25rem" height="1.25rem" icon="tabler:heart-filled" v-else | ||
class="size-5 text-primary-600 group-hover:group-enabled:text-gray-200" aria-hidden="true" /> | ||
<span class="text-gray-400 mt-0.5 ml-2">{{ numberFormat(note.favourites_count) }}</span> | ||
</InteractionButton> | ||
<InteractionButton @click="reblogFn" :disabled="!identity"> | ||
<iconify-icon width="1.25rem" height="1.25rem" icon="tabler:repeat" v-if="!note.reblogged" | ||
class="size-5 text-gray-200 group-hover:group-enabled:text-green-600" aria-hidden="true" /> | ||
<iconify-icon width="1.25rem" height="1.25rem" icon="tabler:repeat" v-else | ||
class="size-5 text-green-600 group-hover:group-enabled:text-gray-200" aria-hidden="true" /> | ||
<span class="text-gray-400 mt-0.5 ml-2">{{ numberFormat(note.reblogs_count) }}</span> | ||
</InteractionButton> | ||
<InteractionButton @click="useEvent('note:quote', note)" | ||
:disabled="!identity"> | ||
<iconify-icon width="1.25rem" height="1.25rem" icon="tabler:quote" | ||
class="size-5 text-gray-200 group-hover:group-enabled:text-blue-600" aria-hidden="true" /> | ||
<span class="text-gray-400 mt-0.5 ml-2">{{ numberFormat(0) }}</span> | ||
</InteractionButton> | ||
<NoteMenu v-model:note="note" :url="url" :remove="remove" /> | ||
</div> | ||
</template> | ||
|
||
<script lang="ts" setup> | ||
import type { Status } from "@versia/client/types"; | ||
import NoteMenu from "../note-menu.vue"; | ||
import InteractionButton from "./button.vue"; | ||
defineProps<{ | ||
url: string; | ||
remove: () => Promise<void>; | ||
}>(); | ||
const note = defineModel<Status>("note", { | ||
required: true, | ||
}); | ||
const numberFormat = (number = 0) => | ||
new Intl.NumberFormat(undefined, { | ||
notation: "compact", | ||
compactDisplay: "short", | ||
maximumFractionDigits: 1, | ||
}).format(number); | ||
const likeFn = async () => { | ||
if (note.value.favourited) { | ||
const output = await client.value.unfavouriteStatus(note.value.id); | ||
if (output?.data) { | ||
note.value = output.data; | ||
} | ||
} else { | ||
const output = await client.value.favouriteStatus(note.value.id); | ||
if (output?.data) { | ||
note.value = output.data; | ||
} | ||
} | ||
}; | ||
const reblogFn = async () => { | ||
if (note.value?.reblogged) { | ||
const output = await client.value.unreblogStatus(note.value.id); | ||
if (output?.data) { | ||
note.value = output.data; | ||
} | ||
} else { | ||
const output = await client.value.reblogStatus(note.value.id); | ||
if (output?.data.reblog) { | ||
note.value = output.data.reblog; | ||
} | ||
} | ||
}; | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
<template> | ||
<AdaptiveDropdown> | ||
<template #button> | ||
<InteractionButton> | ||
<iconify-icon width="1.25rem" height="1.25rem" icon="tabler:dots" class="size-5 text-gray-200" | ||
aria-hidden="true" /> | ||
<span class="sr-only">Open menu</span> | ||
</InteractionButton> | ||
</template> | ||
|
||
<template #items> | ||
<Menu.ItemGroup> | ||
<Menu.Item value="" v-if="isMyAccount"> | ||
<ButtonDropdown @click="note && useEvent('note:edit', note)" icon="tabler:pencil" class="w-full"> | ||
Edit | ||
</ButtonDropdown> | ||
</Menu.Item> | ||
<Menu.Item value=""> | ||
<ButtonDropdown @click="copy(JSON.stringify(note, null, 4))" icon="tabler:code" | ||
class="w-full"> | ||
Copy API | ||
response | ||
</ButtonDropdown> | ||
</Menu.Item> | ||
<Menu.Item value=""> | ||
<ButtonDropdown @click="copy(url)" icon="tabler:link" class="w-full"> | ||
Copy link | ||
</ButtonDropdown> | ||
</Menu.Item> | ||
<Menu.Item value="" v-if="note?.url && isRemote"> | ||
<ButtonDropdown @click="copy(note.url)" icon="tabler:link" class="w-full"> | ||
Copy link (origin) | ||
</ButtonDropdown> | ||
</Menu.Item> | ||
<Menu.Item value="" v-if="note?.url && isRemote"> | ||
<ButtonDropdown @click="openBlank(note.url)" icon="tabler:external-link" class="w-full"> | ||
View on remote | ||
</ButtonDropdown> | ||
</Menu.Item> | ||
<Menu.Item value="" v-if="isMyAccount"> | ||
<ButtonDropdown @click="remove" icon="tabler:backspace" :disabled="!identity" | ||
class="w-full border-r-2 border-red-500"> | ||
Delete | ||
</ButtonDropdown> | ||
</Menu.Item> | ||
</Menu.ItemGroup> | ||
<hr class="border-white/10 rounded" v-if="identity" /> | ||
<Menu.ItemGroup v-if="identity"> | ||
<Menu.Item value=""> | ||
<ButtonDropdown @click="note && useEvent('note:reply', note)" icon="tabler:arrow-back-up" | ||
class="w-full"> | ||
Reply | ||
</ButtonDropdown> | ||
</Menu.Item> | ||
<Menu.Item value=""> | ||
<ButtonDropdown @click="likeFn" icon="tabler:heart" class="w-full" v-if="!note?.favourited"> | ||
Like | ||
</ButtonDropdown> | ||
<ButtonDropdown @click="likeFn" icon="tabler:heart-filled" class="w-full" v-else> | ||
Unlike | ||
</ButtonDropdown> | ||
</Menu.Item> | ||
<Menu.Item value=""> | ||
<ButtonDropdown @click="reblogFn" icon="tabler:repeat" class="w-full" v-if="!note?.reblogged"> | ||
Reblog | ||
</ButtonDropdown> | ||
<ButtonDropdown @click="reblogFn" icon="tabler:repeat" class="w-full" v-else> | ||
Unreblog | ||
</ButtonDropdown> | ||
</Menu.Item> | ||
<Menu.Item value=""> | ||
<ButtonDropdown @click="note && useEvent('note:quote', note)" icon="tabler:quote" class="w-full"> | ||
Quote | ||
</ButtonDropdown> | ||
</Menu.Item> | ||
</Menu.ItemGroup> | ||
<hr class="border-white/10 rounded" v-if="identity" /> | ||
<Menu.ItemGroup v-if="identity"> | ||
<Menu.Item value=""> | ||
<ButtonDropdown @click="note && useEvent('note:report', note)" icon="tabler:flag" class="w-full" | ||
:disabled="!permissions.includes(RolePermission.ManageOwnReports)"> | ||
Report | ||
</ButtonDropdown> | ||
</Menu.Item> | ||
<Menu.Item value="" v-if="permissions.includes(RolePermission.ManageAccounts)"> | ||
<ButtonDropdown icon="tabler:shield-bolt" class="w-full"> | ||
Open moderation panel | ||
</ButtonDropdown> | ||
</Menu.Item> | ||
</Menu.ItemGroup> | ||
</template> | ||
</AdaptiveDropdown> | ||
</template> | ||
|
||
<script lang="ts" setup> | ||
import { Menu } from "@ark-ui/vue"; | ||
import { RolePermission, type Status } from "@versia/client/types"; | ||
import ButtonDropdown from "~/components/buttons/button-dropdown.vue"; | ||
import AdaptiveDropdown from "~/components/dropdowns/AdaptiveDropdown.vue"; | ||
import InteractionButton from "./interactions/button.vue"; | ||
defineProps<{ | ||
url: string; | ||
remove: () => Promise<void>; | ||
}>(); | ||
const note = defineModel<Status>("note", { | ||
required: true, | ||
}); | ||
const openBlank = (url: string) => window.open(url, "_blank"); | ||
const { copy } = useClipboard(); | ||
const isMyAccount = computed( | ||
() => identity.value?.account.id === note.value?.account.id, | ||
); | ||
const isRemote = computed(() => note.value?.account.acct.includes("@")); | ||
const permissions = usePermissions(); | ||
const likeFn = async () => { | ||
if (!note.value) { | ||
return; | ||
} | ||
if (note.value.favourited) { | ||
const output = await client.value.unfavouriteStatus(note.value.id); | ||
if (output.data) { | ||
note.value = output.data; | ||
} | ||
} else { | ||
const output = await client.value.favouriteStatus(note.value.id); | ||
if (output.data) { | ||
note.value = output.data; | ||
} | ||
} | ||
}; | ||
const reblogFn = async () => { | ||
if (!note.value) { | ||
return; | ||
} | ||
if (note.value.reblogged) { | ||
const output = await client.value.unreblogStatus(note.value.id); | ||
if (output.data) { | ||
note.value = output.data; | ||
} | ||
} else { | ||
const output = await client.value.reblogStatus(note.value.id); | ||
if (output.data.reblog) { | ||
note.value = output.data.reblog; | ||
} | ||
} | ||
}; | ||
</script> |
Oops, something went wrong.