♻️ Moved the components to use naive ui + daisyui
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<div class="d-flex justify-center">
|
||||
<div class="flex justify-center">
|
||||
<div v-if="provider === 'cloudflare'">
|
||||
<turnstile v-if="!!apiKey" :sitekey="apiKey" @callback="handleSuccess" />
|
||||
<div v-else class="mx-auto">
|
||||
<v-progress-circular indeterminate />
|
||||
<n-spin />
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="provider === 'hcaptcha'">
|
||||
@@ -13,7 +13,7 @@
|
||||
@verify="(tk: string) => handleSuccess(tk)"
|
||||
/>
|
||||
<div v-else class="mx-auto">
|
||||
<v-progress-circular indeterminate />
|
||||
<n-spin />
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
@@ -21,8 +21,8 @@
|
||||
class="h-captcha"
|
||||
:data-sitekey="apiKey"
|
||||
/>
|
||||
<div v-else class="d-flex flex-column align-center justify-center gap-1">
|
||||
<v-icon size="32"> mdi-alert-circle-outline </v-icon>
|
||||
<div v-else class="flex flex-col items-center justify-center gap-1">
|
||||
<span class="mdi mdi-alert-circle-outline text-3xl"></span>
|
||||
<span>Captcha provider not configured correctly.</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,30 +1,17 @@
|
||||
<template>
|
||||
<v-container class="footer">
|
||||
<div class="d-flex justify-space-between align-center">
|
||||
<v-select
|
||||
:items="['English (United States)']"
|
||||
model-value="English (United States)"
|
||||
variant="plain"
|
||||
density="compact"
|
||||
hide-details
|
||||
<div class="container absolute bottom-5 left-1/2 -translate-x-1/2">
|
||||
<div class="flex justify-between items-center">
|
||||
<n-select
|
||||
:options="[{ label: 'English (United States)', value: 'en-us' }]"
|
||||
model-value="en-us"
|
||||
size="small"
|
||||
class="flex-grow-0"
|
||||
/>
|
||||
<div class="d-flex">
|
||||
<v-btn variant="text" size="small" class="text-capitalize">Help</v-btn>
|
||||
<v-btn variant="text" size="small" class="text-capitalize"
|
||||
>Privacy</v-btn
|
||||
>
|
||||
<v-btn variant="text" size="small" class="text-capitalize">Terms</v-btn>
|
||||
<div class="flex">
|
||||
<n-button text size="small">Help</n-button>
|
||||
<n-button text size="small">Privacy</n-button>
|
||||
<n-button text size="small">Terms</n-button>
|
||||
</div>
|
||||
</div>
|
||||
</v-container>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.footer {
|
||||
position: absolute;
|
||||
bottom: 20px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
<template>
|
||||
<div class="flex flex-col gap-2">
|
||||
<pub-select v-model:value="publisher" />
|
||||
<v-textarea
|
||||
v-model="content"
|
||||
<n-input
|
||||
v-model:value="content"
|
||||
type="textarea"
|
||||
placeholder="What's happended?!"
|
||||
@keydown.meta.enter.exact="submit"
|
||||
@keydown.ctrl.enter.exact="submit"
|
||||
/>
|
||||
<div class="flex justify-between">
|
||||
<v-btn type="primary" :loading="submitting" @click="submit">
|
||||
<n-button type="primary" :loading="submitting" @click="submit">
|
||||
Post
|
||||
<template #append>
|
||||
<v-icon>mdi-send</v-icon>
|
||||
<template #icon>
|
||||
<span class="mdi mdi-send"></span>
|
||||
</template>
|
||||
</v-btn>
|
||||
</n-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<v-card :flat="props.flat">
|
||||
<v-card-text :style="props.slim ? 'padding: 0' : null">
|
||||
<div :class="['card', { 'shadow-none': props.flat }]">
|
||||
<div :class="['card-body', { 'p-0': props.slim }]">
|
||||
<div :class="['flex flex-col', compact ? 'gap-1' : 'gap-3']">
|
||||
<post-header :item="props.item" :compact="compact" />
|
||||
|
||||
@@ -21,50 +21,42 @@
|
||||
</article>
|
||||
|
||||
<template v-if="showReferenced">
|
||||
<div v-if="props.item.repliedPost || props.item.repliedGone">
|
||||
<v-card
|
||||
title="Replying to"
|
||||
prepend-icon="mdi-reply"
|
||||
density="compact"
|
||||
<div v-if="props.item.repliedPost || props.item.repliedGone" class="border rounded-md">
|
||||
<div class="p-2 flex items-center gap-2">
|
||||
<span class="mdi mdi-reply"></span>
|
||||
<span class="font-bold">Replying to</span>
|
||||
</div>
|
||||
<div v-if="props.item.repliedGone" class="px-4 pb-3 text-sm opacity-60">
|
||||
Post unavailable
|
||||
</div>
|
||||
<post-item
|
||||
v-else-if="props.item.repliedPost"
|
||||
class="px-4 pb-3"
|
||||
:item="props.item.repliedPost"
|
||||
slim
|
||||
compact
|
||||
flat
|
||||
border
|
||||
>
|
||||
<div v-if="props.item.repliedGone" class="px-4 pb-3 text-sm opacity-60">
|
||||
Post unavailable
|
||||
</div>
|
||||
<post-item
|
||||
v-else-if="props.item.repliedPost"
|
||||
class="px-4 pb-3"
|
||||
:item="props.item.repliedPost"
|
||||
slim
|
||||
compact
|
||||
flat
|
||||
@react="handleReaction"
|
||||
/>
|
||||
</v-card>
|
||||
@react="handleReaction"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div v-if="props.item.forwardedPost || props.item.forwardedGone">
|
||||
<v-card
|
||||
title="Forwarded"
|
||||
prepend-icon="mdi-forward"
|
||||
density="compact"
|
||||
<div v-if="props.item.forwardedPost || props.item.forwardedGone" class="border rounded-md">
|
||||
<div class="p-2 flex items-center gap-2">
|
||||
<span class="mdi mdi-forward"></span>
|
||||
<span class="font-bold">Forwarded</span>
|
||||
</div>
|
||||
<div v-if="props.item.forwardedGone" class="px-4 pb-3 text-sm opacity-60">
|
||||
Post unavailable
|
||||
</div>
|
||||
<post-item
|
||||
v-else-if="props.item.forwardedPost"
|
||||
class="px-4 pb-3"
|
||||
:item="props.item.forwardedPost"
|
||||
slim
|
||||
compact
|
||||
flat
|
||||
border
|
||||
>
|
||||
<div v-if="props.item.forwardedGone" class="px-4 pb-3 text-sm opacity-60">
|
||||
Post unavailable
|
||||
</div>
|
||||
<post-item
|
||||
v-else-if="props.item.forwardedPost"
|
||||
class="px-4 pb-3"
|
||||
:item="props.item.forwardedPost"
|
||||
slim
|
||||
compact
|
||||
flat
|
||||
@react="handleReaction"
|
||||
/>
|
||||
</v-card>
|
||||
@react="handleReaction"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -74,22 +66,19 @@
|
||||
:max-height="640"
|
||||
/>
|
||||
|
||||
<v-lazy
|
||||
v-if="props.item.repliesCount && !compact"
|
||||
:options="{ threshold: 0.5 }"
|
||||
transition="fade-transition"
|
||||
>
|
||||
<div ref="repliesTarget">
|
||||
<replies-compact-list
|
||||
v-if="props.item.repliesCount && !compact && repliesVisible"
|
||||
:params="{ postId: props.item.id }"
|
||||
:hide-quick-reply="true"
|
||||
@react="handleReplyReaction"
|
||||
/>
|
||||
</v-lazy>
|
||||
</div>
|
||||
<div
|
||||
v-if="props.item.isTruncated"
|
||||
class="flex gap-2 text-xs opacity-80"
|
||||
class="flex gap-2 text-xs opacity-80 items-center"
|
||||
>
|
||||
<v-icon icon="mdi-dots-horizontal" size="small" />
|
||||
<span class="mdi mdi-dots-horizontal"></span>
|
||||
<p>Post truncated, tap to see details...</p>
|
||||
</div>
|
||||
|
||||
@@ -104,14 +93,15 @@
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch } from "vue"
|
||||
import { useMarkdownProcessor } from "~/composables/useMarkdownProcessor"
|
||||
import type { SnPost } from "~/types/api"
|
||||
import { useIntersectionObserver } from '@vueuse/core'
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
@@ -156,4 +146,19 @@ watch(
|
||||
},
|
||||
{ immediate: true, deep: true }
|
||||
)
|
||||
|
||||
const repliesTarget = ref(null)
|
||||
const repliesVisible = ref(false)
|
||||
|
||||
useIntersectionObserver(
|
||||
repliesTarget,
|
||||
([{ isIntersecting }]) => {
|
||||
if (isIntersecting) {
|
||||
repliesVisible.value = true
|
||||
}
|
||||
},
|
||||
{
|
||||
threshold: 0.5
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
@@ -1,38 +1,19 @@
|
||||
<template>
|
||||
<v-select
|
||||
:items="pubStore.publishers"
|
||||
item-title="nick"
|
||||
item-value="name"
|
||||
:model-value="props.value"
|
||||
@update:model-value="(v) => emits('update:value', v)"
|
||||
>
|
||||
<template #item="{ props: itemProps, item }">
|
||||
<v-list-item v-bind="itemProps">
|
||||
<template #prepend>
|
||||
<v-avatar
|
||||
:image="item.raw.picture ? `${apiBase}/drive/files/${item.raw.picture.id}` : undefined"
|
||||
size="small"
|
||||
/>
|
||||
</template>
|
||||
<v-list-item-subtitle>@{{ item.raw?.name }}</v-list-item-subtitle>
|
||||
</v-list-item>
|
||||
</template>
|
||||
<template #selection="{ item }">
|
||||
<div class="d-flex align-center">
|
||||
<v-avatar
|
||||
:image="item.raw.picture ? `${apiBase}/drive/files/${item.raw.picture.id}` : undefined"
|
||||
size="24"
|
||||
class="me-2"
|
||||
/>
|
||||
{{ item.raw?.nick }}
|
||||
</div>
|
||||
</template>
|
||||
</v-select>
|
||||
<n-select
|
||||
:options="pubStore.publishers"
|
||||
label-field="nick"
|
||||
value-field="name"
|
||||
:value="props.value"
|
||||
@update:value="(v) => emits('update:value', v)"
|
||||
:render-label="renderLabel"
|
||||
:render-tag="renderTag"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { usePubStore } from '~/stores/pub'
|
||||
import { watch } from 'vue'
|
||||
import { watch, h } from 'vue'
|
||||
import type { SelectRenderLabel, SelectRenderTag } from 'naive-ui'
|
||||
|
||||
const pubStore = usePubStore()
|
||||
const apiBase = useSolarNetworkUrl()
|
||||
@@ -40,6 +21,38 @@ const apiBase = useSolarNetworkUrl()
|
||||
const props = defineProps<{ value: string | undefined }>()
|
||||
const emits = defineEmits(['update:value'])
|
||||
|
||||
const renderLabel: SelectRenderLabel = (option) => {
|
||||
return h('div', { class: 'flex items-center' }, [
|
||||
h(NAvatar, {
|
||||
src: option.picture ? `${apiBase.value}/drive/files/${option.picture.id}` : undefined,
|
||||
size: 'small',
|
||||
class: 'mr-2'
|
||||
}),
|
||||
h('div', null, [
|
||||
h('div', null, option.nick as string),
|
||||
h('div', { class: 'text-xs text-gray-500' }, `@${option.name as string}`)
|
||||
])
|
||||
])
|
||||
}
|
||||
|
||||
const renderTag: SelectRenderTag = ({ option }) => {
|
||||
return h(
|
||||
'div',
|
||||
{
|
||||
class: 'flex items-center'
|
||||
},
|
||||
[
|
||||
h(NAvatar, {
|
||||
src: option.picture ? `${apiBase.value}/drive/files/${option.picture.id}` : undefined,
|
||||
size: 'small',
|
||||
class: 'mr-2'
|
||||
}),
|
||||
option.nick as string
|
||||
]
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
watch(
|
||||
pubStore,
|
||||
(value) => {
|
||||
|
||||
@@ -6,15 +6,15 @@
|
||||
<span>FloatingIsland</span>
|
||||
</div>
|
||||
<div class="flex flex-wrap gap-1.5">
|
||||
<a class="link" target="_blank" href="https://solsynth.dev/terms">
|
||||
<a class="hover:underline" target="_blank" href="https://solsynth.dev/terms">
|
||||
Terms of Services
|
||||
</a>
|
||||
<span class="font-bold">·</span>
|
||||
<a class="link" target="_blank" href="https://status.solsynth.dev">
|
||||
<a class="hover:underline" target="_blank" href="https://status.solsynth.dev">
|
||||
Service Status
|
||||
</a>
|
||||
<span class="font-bold">·</span>
|
||||
<nuxt-link class="link" target="_blank" to="/swagger"> API </nuxt-link>
|
||||
<nuxt-link class="hover:underline" target="_blank" to="/swagger"> API </nuxt-link>
|
||||
</div>
|
||||
<p class="mt-2 opacity-80">
|
||||
The FloatingIsland do not provides all the features the Solar Network has,
|
||||
@@ -23,9 +23,3 @@
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.link:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user