Compare commits

..

No commits in common. "e4111dc06ee0a05a0894fb43219490e652b6bd98" and "975766302a6a8f4a3847235acf8214aa78764de3" have entirely different histories.

13 changed files with 210 additions and 272 deletions

View File

@ -3,12 +3,10 @@
<v-card-text>
<div class="mb-3 flex flex-row gap-4">
<nuxt-link :to="`/users/${post.publisher?.name}`">
<v-avatar :image="getAttachmentUrl(post.publisher?.avatar)" icon="mdi-account-circle" />
<v-avatar :image="post.publisher?.avatar" />
</nuxt-link>
<div class="flex flex-col">
<span
>{{ post.publisher?.nick }} <span class="text-xs">@{{ post.publisher?.name }}</span></span
>
<span>{{ post.publisher?.nick }} <span class="text-xs">@{{ post.publisher?.name }}</span></span>
<span v-if="post.body?.title" class="text-md">{{ post.body?.title }}</span>
<span v-if="post.body?.description" class="text-sm">{{ post.body?.description }}</span>
<span v-if="!post.body?.title && !post.body?.description" class="text-sm">
@ -31,7 +29,7 @@
/>
</div>
<article v-if="(post.type == 'story' || props.forceShowContent) && post.body?.content" class="text-base prose max-w-none">
<article v-if="post.type == 'story' || props.forceShowContent" class="text-base prose max-w-none">
<m-d-c :value="post.body?.content"></m-d-c>
</article>
@ -43,19 +41,24 @@
</v-card>
<div class="text-sm flex flex-col">
<span class="flex flex-row gap-1">
<span> {{ post.metric.reply_count }} {{ post.metric.reply_count > 1 ? "replies" : "reply" }}, </span>
<span>
{{ post.metric.reaction_count }} {{ post.metric.reaction_count > 1 ? "reactions" : "reaction" }}
</span>
</span>
<span class="flex flex-row gap-1">
<span>
{{ post.metric.reply_count }} {{ post.metric.reply_count > 1 ? "replies" : "reply" }},
</span>
<span>
{{ post.metric.reaction_count }} {{ post.metric.reaction_count > 1 ? "reactions" : "reaction" }}
</span>
</span>
<span>
{{ post.type.startsWith("a") ? "An" : "A" }} {{ post.type }} posted on
{{ new Date(post.published_at).toLocaleString() }}
</span>
{{ post.type.startsWith("a") ? "An" : "A" }} {{ post.type }} posted on
{{ new Date(post.published_at).toLocaleString() }}
</span>
</div>
<div v-if="post.tags?.length > 0" class="text-xs text-grey flex flex-row gap-1 mt-3">
<div
v-if="post.tags?.length > 0"
class="text-xs text-grey flex flex-row gap-1 mt-3"
>
<nuxt-link
v-for="tag in post.tags"
:to="`/posts/tags/${tag.alias}`"
@ -70,12 +73,10 @@
</template>
<script setup lang="ts">
const props = defineProps<{ post: any; forceShowContent?: boolean; noClickableAttachment?: boolean }>()
const props = defineProps<{ post: any, forceShowContent?: boolean, noClickableAttachment?: boolean }>()
const config = useRuntimeConfig()
const { t } = useI18n()
const url = computed(() =>
props.post.alias ? `/posts/${props.post.area_alias}/${props.post.alias}` : `/posts/${props.post.id}`,
)
const url = computed(() => props.post.alias ? `/posts/${props.post.area_alias}/${props.post.alias}` : `/posts/${props.post.id}`)
</script>

View File

@ -5,11 +5,13 @@
</v-alert>
</v-expand-transition>
<v-data-table
<v-data-table-server
density="compact"
:headers="dataDefinitions.stickers"
:items="stickers"
:items-length="pagination.stickers.total"
:loading="reverting.stickers"
v-model:items-per-page="pagination.stickers.pageSize"
@update:options="readStickers"
item-value="id"
>
@ -72,24 +74,23 @@
<template v-slot:default="{ isActive }">
<v-card :title="`Delete sticker #${item.id}?`">
<v-card-text>
This action will delete this sticker, all content used it will no longer show your sticker. But the
attachment will still exists.
This action will delete this sticker, all content used it will no longer show your sticker.
But the attachment will still exists.
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn text="Cancel" color="grey" @click="isActive.value = false"></v-btn>
<v-btn
text="Cancel"
color="grey"
@click="isActive.value = false"
></v-btn>
<v-btn
text="Delete"
color="error"
@click="
() => {
deleteSticker(item)
isActive.value = false
}
"
@click="() => { deleteSticker(item); isActive.value = false }"
/>
</v-card-actions>
</v-card>
@ -98,7 +99,7 @@
</td>
</tr>
</template>
</v-data-table>
</v-data-table-server>
</template>
<script setup lang="ts">
@ -107,7 +108,7 @@ import { solarFetch } from "~/utils/request"
const config = useRuntimeConfig()
const { t } = useI18n()
const props = defineProps<{ packId: number; packPrefix?: string }>()
const props = defineProps<{ packId: number, packPrefix?: string }>()
const error = ref<null | string>(null)
@ -124,20 +125,34 @@ const dataDefinitions: { [id: string]: any[] } = {
const stickers = ref<any>([])
const reverting = reactive({ stickers: false })
const pagination = reactive({
stickers: { page: 1, pageSize: 5, total: 0 },
})
async function readStickers({ page, itemsPerPage }: { page?: number; itemsPerPage?: number }) {
if (itemsPerPage) pagination.stickers.pageSize = itemsPerPage
if (page) pagination.stickers.page = page
async function readStickers() {
reverting.stickers = true
const res = await solarFetch("/cgi/uc/stickers/packs/" + props.packId)
const res = await solarFetch(
"/cgi/uc/stickers?" +
new URLSearchParams({
pack: props.packId.toString(),
take: pagination.stickers.pageSize.toString(),
offset: ((pagination.stickers.page - 1) * pagination.stickers.pageSize).toString(),
}),
)
if (res.status !== 200) {
error.value = await res.text()
} else {
const data = await res.json()
stickers.value = data["stickers"]
stickers.value = data["data"]
pagination.stickers.total = data["count"]
}
reverting.stickers = false
}
onMounted(() => readStickers())
onMounted(() => readStickers({}))
const submitting = ref(false)
@ -150,7 +165,7 @@ async function deleteSticker(item: any) {
if (res.status !== 200) {
error.value = await res.text()
} else {
await readStickers()
await readStickers({})
}
submitting.value = false

View File

@ -1,10 +1,17 @@
<template>
<v-app-bar flat color="primary" scroll-behavior="hide" scroll-threshold="800">
<v-container fluid class="mx-auto d-flex align-center justify-center px-8">
<v-app-bar-nav-icon @click="openDrawer = !openDrawer" />
<v-tooltip>
<template #activator="{ props }">
<div @click="openDrawer = !openDrawer" v-bind="props" class="cursor-pointer">
<v-img class="me-4 ms-1" width="32" height="32" alt="Logo" :src="Logo" />
</div>
</template>
Open / close drawer
</v-tooltip>
<nuxt-link to="/creator" exact>
<h2>Creator Hub</h2>
<nuxt-link to="/dev" exact>
<h2 class="mt-1">Creator Hub</h2>
</nuxt-link>
<v-spacer></v-spacer>
@ -38,10 +45,12 @@
</template>
<script setup lang="ts">
import Logo from "../assets/logo-w-shadow.png"
const { t } = useI18n()
const openDrawer = ref(false)
useHead({
titleTemplate: "%s | Solsynth Creator Hub",
titleTemplate: "%s | Solsynth Creator Hub"
})
</script>

View File

@ -1,38 +1,41 @@
<template>
<v-app-bar app flat color="surface" class="app-bar-blur">
<v-container fluid class="mx-auto d-flex align-center justify-center pr-8">
<v-app-bar-nav-icon @click="openDrawer = !openDrawer" />
<v-app-bar flat color="primary">
<v-container fluid class="mx-auto d-flex align-center justify-center px-8">
<v-tooltip>
<template #activator="{ props }">
<div @click="openDrawer = !openDrawer" v-bind="props" class="cursor-pointer">
<v-img class="me-4 ms-1" width="32" height="32" alt="Logo" :src="Logo" />
</div>
</template>
Open / close drawer
</v-tooltip>
<nuxt-link to="/" exact>
<h2>Solsynth LLC</h2>
<h2 class="mt-1">Solsynth LLC</h2>
</nuxt-link>
<v-spacer></v-spacer>
<div class="flex gap-2">
<v-btn to="/products" exact prepend-icon="mdi-shape">{{ t("navProducts") }}</v-btn>
<v-btn to="/posts" exact prepend-icon="mdi-note-text">{{ t("navPosts") }}</v-btn>
<v-btn to="/gallery" exact prepend-icon="mdi-image-multiple">{{ t("navGallery") }}</v-btn>
</div>
<v-spacer></v-spacer>
<locale-select />
<user-menu />
</v-container>
</v-app-bar>
<v-navigation-drawer v-model="openDrawer" location="left" width="300" temporary order="-1">
<v-navigation-drawer v-model="openDrawer" location="left" width="300" floating>
<v-list density="compact" nav color="primary">
<v-list-item title="Knowledge Base" prepend-icon="mdi-library" to="/docs" exact />
<v-list-item title="Developer Portal" prepend-icon="mdi-code-tags" to="/dev" exact />
<v-list-item title="Creator Hub" prepend-icon="mdi-pencil" to="/creator" exact />
<v-list-item :title="t('navProducts')" prepend-icon="mdi-shape" to="/products" exact />
<v-list-item :title="t('navPosts')" prepend-icon="mdi-note-text" to="/posts" exact />
<v-list-item :title="t('navActivity')" prepend-icon="mdi-newspaper-variant-multiple-outline" to="/activity" exact />
<v-list-item :title="t('navGallery')" prepend-icon="mdi-image-multiple" to="/gallery" exact />
</v-list>
<v-divider class="border-opacity-50 my-1" />
<v-list density="compact" nav color="primary">
<v-list-item title="Code Repository" prepend-icon="mdi-git" href="https://git.solsynth.dev" target="_blank" />
<v-list-item title="Knowledge Base" prepend-icon="mdi-library" to="/docs" exact />
<v-list-item title="Developer Portal" prepend-icon="mdi-code-tags" to="/dev" exact />
<v-list-item title="Creator Hub" prepend-icon="mdi-pencil" to="/creator" exact />
</v-list>
<v-divider class="border-opacity-50 mb-4 mt-0.5" />
@ -48,16 +51,9 @@
</template>
<script setup lang="ts">
const { t } = useI18n()
import Logo from "../assets/logo-w-shadow.png"
const { t } = useI18n()
const openDrawer = ref(false)
</script>
<style lang="css" scoped>
.app-bar-blur {
-webkit-mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 1) 40%, rgba(0, 0, 0, 0.5) 65%, rgba(0, 0, 0, 0) 100%);
mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 1) 40%, rgba(0, 0, 0, 0.5) 65%, rgba(0, 0, 0, 0) 100%);
mask-repeat: no-repeat;
mask-size: 100%;
}
</style>

View File

@ -1,10 +1,17 @@
<template>
<v-app-bar flat color="primary" scroll-behavior="hide" scroll-threshold="800">
<v-container fluid class="mx-auto d-flex align-center justify-center pr-8">
<v-app-bar-nav-icon @click="openDrawer = !openDrawer" />
<v-container fluid class="mx-auto d-flex align-center justify-center px-8">
<v-tooltip>
<template #activator="{ props }">
<div @click="openDrawer = !openDrawer" v-bind="props" class="cursor-pointer">
<v-img class="me-4 ms-1" width="32" height="32" alt="Logo" :src="Logo" />
</div>
</template>
Open / close drawer
</v-tooltip>
<nuxt-link to="/dev" exact>
<h2>Developer Portal</h2>
<h2 class="mt-1">Developer Portal</h2>
</nuxt-link>
<v-spacer></v-spacer>
@ -44,6 +51,6 @@ const { t } = useI18n()
const openDrawer = ref(false)
useHead({
titleTemplate: "%s | Solsynth Dev Portal",
titleTemplate: "%s | Solsynth Dev Portal"
})
</script>

View File

@ -151,7 +151,7 @@ export default defineNuxtConfig({
"@pinia/nuxt",
"@nuxtjs/i18n",
"nuxt-schema-org",
"@vueuse/motion/nuxt",
"nuxt-gtag",
(_options, nuxt) => {
nuxt.hooks.hook("vite:extendConfig", (config) => {
// @ts-expect-error

View File

@ -17,7 +17,6 @@
"@nuxtjs/i18n": "^8.5.6",
"@nuxtjs/sitemap": "^6.1.5",
"@pinia/nuxt": "^0.5.5",
"@vueuse/motion": "^3.0.3",
"feed": "^4.2.2",
"nuxt": "^3.16.0",
"nuxt-gtag": "^2.1.0",

37
pages/activity/index.vue Normal file
View File

@ -0,0 +1,37 @@
<template>
<v-container class="content-container mx-auto">
<div class="my-3 mx-[1.5ch]">
<div class="flex gap-1">
<h1 class="text-2xl">{{ t("navActivity") }}</h1>
<v-btn size="x-small" variant="text" icon="mdi-rss" slim to="/activity/feed" />
</div>
<span>{{ t("navActivityCaption") }}</span>
</div>
<post-list class="mx-[-2.5ch]" :realm="config.public.solarRealm" />
</v-container>
</template>
<script setup lang="ts">
const { t } = useI18n()
useHead({
title: t("navActivity"),
})
useSeoMeta({
title: t("navActivity"),
ogTitle: t("navActivity"),
description: t("navActivityCaption"),
ogDescription: t("navActivityCaption"),
ogType: "website",
})
const config = useRuntimeConfig()
</script>
<style scoped>
.content-container {
max-width: 70ch !important;
}
</style>

View File

@ -6,7 +6,13 @@
</div>
<div class="flex gap-2">
<v-btn color="primary" text="New" append-icon="mdi-plus" variant="tonal" to="/creator/stickers/new" />
<v-btn
color="primary"
text="New"
append-icon="mdi-plus"
variant="tonal"
to="/creator/stickers/new"
/>
</div>
</div>
@ -18,7 +24,10 @@
<div class="mt-5">
<v-expansion-panels>
<v-expansion-panel v-for="item in data" :key="'sticker-pack#' + item.id">
<v-expansion-panel
v-for="item in data"
:key="'sticker-pack#'+item.id"
>
<template #title>
<div class="flex items-center gap-2">
<p>{{ item.name }}</p>
@ -78,17 +87,16 @@
<v-card-actions>
<v-spacer></v-spacer>
<v-btn text="Cancel" color="grey" @click="isActive.value = false"></v-btn>
<v-btn
text="Cancel"
color="grey"
@click="isActive.value = false"
></v-btn>
<v-btn
text="Delete"
color="error"
@click="
() => {
deletePack(item)
isActive.value = false
}
"
@click="() => { deletePack(item); isActive.value = false }"
/>
</v-card-actions>
</v-card>
@ -123,7 +131,6 @@ useHead({
})
const { t } = useI18n()
const ua = useUserinfo()
const loading = ref(false)
const error = ref<null | string>(null)
@ -133,7 +140,7 @@ const data = ref<any[]>([])
async function readPacks() {
loading.value = true
const res = await solarFetch(`/cgi/uc/stickers/packs?take=10&author=${ua.userinfo?.id}&offset=${data.value.length}`)
const res = await solarFetch(`/cgi/uc/stickers/packs?take=10&offset=${data.value.length}`)
if (res.status != 200) {
error.value = await res.text()
} else {

View File

@ -1,71 +1,39 @@
<template>
<v-container class="flex flex-col my-2 px-12 gap-[4rem]">
<section class="content-section flex flex-col items-center justify-center text-center px-4">
<img
v-motion="{
initial: {
y: 100,
opacity: 0,
},
enter: {
y: 0,
opacity: 1,
},
}"
:src="Logo"
alt="Company Logo"
class="w-32 h-32 mb-4"
/>
<h1 class="text-4xl font-bold">Welcome to {{ t("brandName") }}</h1>
<p class="mt-2 text-lg">Building cool, open-source, and elegant apps for human.</p>
<v-btn class="mt-4" color="primary" prepend-icon="mdi-arrow-down" href="#products">{{ t("learnMore") }}</v-btn>
</section>
<section class="content-section py-16" id="products">
<div class="container mx-auto text-center">
<h2 class="text-3xl font-bold">Our Projects</h2>
<p>Take a peek of our works.</p>
<v-card class="mt-12">
<v-row class="content-section">
<v-col cols="12" md="4" class="flex justify-start">
<div class="flex flex-col items-start">
<h1 class="text-4xl font-bold">{{ t("brandName") }}</h1>
<p class="text-lg mt-3 max-w-2/3">
{{ t("indexIntroduce") }}
</p>
<p class="text-grey mt-2">
{{ t("indexProductListHint") }}
<v-icon icon="mdi-arrow-right" size="16" class="mb-0.5" />
</p>
</div>
</v-col>
<v-col cols="12" md="8">
<v-card>
<product-carousel class="carousel-section" :products="products as any[]" />
</v-card>
</div>
</section>
</v-col>
</v-row>
<v-row class="content-section">
<v-col cols="12" md="6">
<v-card>
<v-list>
<v-list-item
title="GitHub"
subtitle="The place hosts most of our public projects' code"
prepend-icon="mdi-github"
href="https://github.com/Solsynth"
target="_blank"
/>
<v-list-item
lines="two"
title="Solsynth Code Repository"
subtitle="Our self-hosted git server, may contains some unpublished projects' code"
prepend-icon="mdi-git"
href="https://git.solsynth.dev/explore"
target="_blank"
/>
</v-list>
<v-col cols="12" md="8">
<v-card class="h-[500px]">
<activity-list class="carousel-section" />
</v-card>
</v-col>
<v-col cols="12" md="6" class="flex justify-end" order="first" order-md="last">
<v-col cols="12" md="4" class="flex justify-end" order="first" order-md="last">
<div class="text-right flex flex-col items-end">
<h2 class="text-4xl font-bold">
We<br />
Open-source
</h2>
<p class="text-md mt-3 max-w-2/3">
No software can run without the support of open source software, and our software is no exception.
Therefore, we feel it is important to contribute to open source as well.
<h2 class="text-4xl font-bold">{{ t("indexActivities") }}</h2>
<p class="text-lg mt-3 max-w-2/3">
{{ t("indexActivitiesCaption") }}
</p>
<p class="text-grey mt-2">
<v-icon icon="mdi-arrow-left" size="16" class="mb-0.5" />
Check out our GitHub
{{ t("indexActivitiesHint") }}
</p>
</div>
</v-col>
@ -74,8 +42,6 @@
</template>
<script setup lang="ts">
import Logo from "../assets/logo-w-shadow.png"
import { getLocale } from "~/utils/locale"
const { t } = useI18n()
@ -95,16 +61,13 @@ useSeoMeta({
})
const { data: products } = await useAsyncData("products", () => {
return queryContent("/products")
.where({ _locale: getLocale(), archived: { $ne: true } })
.limit(5)
.find()
return queryContent("/products").where({ _locale: getLocale(), archived: { $ne: true } }).limit(5).find()
})
</script>
<style scoped>
.carousel-section {
height: 120rem;
height: 96rem;
}
.content-section {
@ -113,10 +76,3 @@ const { data: products } = await useAsyncData("products", () => {
place-items: center;
}
</style>
<style>
body,
html {
scroll-behavior: smooth;
}
</style>

View File

@ -1,19 +1,14 @@
<template>
<v-container class="content-container mx-auto">
<div class="my-3 flex flex-row gap-4">
<nuxt-link :to="`/publishers/${post.publisher?.name}`">
<v-avatar :image="getAttachmentUrl(post.publisher?.avatar)" />
<nuxt-link :to="`/users/${post.publisher?.name}`">
<v-avatar :image="post.publisher?.avatar" />
</nuxt-link>
<div class="flex flex-col">
<span>
{{ post.publisher?.nick }}
<span class="text-xs">@{{ post.publisher?.name }}</span>
</span>
<span>{{ post.publisher?.nick }} <span class="text-xs">@{{ post.publisher?.name }}</span></span>
<span v-if="post.body?.title" class="text-md">{{ post.body?.title }}</span>
<span v-if="post.body?.description" class="text-sm">{{ post.body?.description }}</span>
<span v-if="!post.body?.title && !post.body?.description" class="text-sm">{{
post.publisher?.description
}}</span>
<span v-if="!post.body?.title && !post.body?.description" class="text-sm">{{ post.publisher?.description }}</span>
</div>
</div>
@ -25,18 +20,22 @@
/>
</v-card>
<article v-if="post.body?.content" class="text-base prose xl:text-lg mx-auto">
<article class="text-base prose xl:text-lg mx-auto">
<m-d-c :value="post.body?.content"></m-d-c>
</article>
<v-card v-if="post.body?.attachments?.length > 0" class="mb-5">
<attachment-carousel :attachments="post.body?.attachments" @update:metadata="(args) => (attachments = args)" />
<attachment-carousel :attachments="post.body?.attachments" @update:metadata="args => attachments = args" />
</v-card>
<div class="mb-3 text-sm flex flex-col">
<span class="flex flex-row gap-1">
<span> {{ post.metric.reply_count }} {{ post.metric.reply_count > 1 ? "replies" : "reply" }}, </span>
<span> {{ post.metric.reaction_count }} {{ post.metric.reaction_count > 1 ? "reactions" : "reaction" }} </span>
<span>
{{ post.metric.reply_count }} {{ post.metric.reply_count > 1 ? "replies" : "reply" }},
</span>
<span>
{{ post.metric.reaction_count }} {{ post.metric.reaction_count > 1 ? "reactions" : "reaction" }}
</span>
</span>
<span>
{{ post.type.startsWith("a") ? "An" : "A" }} {{ post.type }} posted on
@ -44,7 +43,10 @@
</span>
</div>
<div v-if="post.tags?.length > 0" class="text-xs text-grey flex flex-row gap-1 mb-3">
<div
v-if="post.tags?.length > 0"
class="text-xs text-grey flex flex-row gap-1 mb-3"
>
<nuxt-link
v-for="tag in post.tags"
:to="`/posts/tags/${tag.alias}`"
@ -106,29 +108,21 @@ if (!post.value) {
navigateTo(`/posts/${post.value.area_alias}/${post.value.alias}`)
}
const title = computed(() =>
post.value.body?.title
? `${post.value.body?.title} by @${post.value.publisher.name}`
: `Post by @${post.value.publisher.name}`,
)
const title = computed(() => post.value.body?.title ? `${post.value.body?.title} by @${post.value.publisher.name}` : `Post by @${post.value.publisher.name}`)
const description = computed(() => post.value.body?.description ?? post.value.body?.content.substring(0, 280).trim())
watch(
attachments,
(value) => {
if (post.value.body?.thumbnail) {
firstImage.value = `${config.public.solarNetworkApi}/cgi/uc/attachments/${post.value.body?.thumbnail}`
}
if (value.length > 0 && value[0].mimetype.split("/")[0] == "image") {
firstImage.value = `${config.public.solarNetworkApi}/cgi/uc/attachments/${attachments.value[0].rid}`
}
watch(attachments, (value) => {
if (post.value.body?.thumbnail) {
firstImage.value = `${config.public.solarNetworkApi}/cgi/uc/attachments/${post.value.body?.thumbnail}`
}
if (value.length > 0 && value[0].mimetype.split("/")[0] == "image") {
firstImage.value = `${config.public.solarNetworkApi}/cgi/uc/attachments/${attachments.value[0].rid}`
}
if (value.length > 0 && value[0].mimetype.split("/")[0] == "video") {
firstVideo.value = `${config.public.solarNetworkApi}/cgi/uc/attachments/${attachments.value[0].rid}`
}
},
{ immediate: true, deep: true },
)
if (value.length > 0 && value[0].mimetype.split("/")[0] == "video") {
firstVideo.value = `${config.public.solarNetworkApi}/cgi/uc/attachments/${attachments.value[0].rid}`
}
}, { immediate: true, deep: true })
useHead({
title: title.value,

View File

@ -1,73 +0,0 @@
<template>
<v-container class="mx-auto">
<v-img v-if="urlOfBanner" :src="urlOfBanner" :aspect-ratio="16 / 5" class="rounded-md mb-3" cover />
<div class="mx-[2.5ch]">
<div class="my-5 mx-4 flex flex-row gap-4">
<v-avatar :image="urlOfAvatar" />
<div class="flex flex-col">
<span
>{{ account?.nick }} <span class="text-xs">@{{ account?.name }}</span></span
>
<span class="text-sm">{{ account?.description }}</span>
</div>
</div>
<div class="mb-7">
<v-card rounded="xl" class="mx-[-5px]">
<v-tabs v-model="tab" align-tabs="start" color="primary" hide-slider>
<v-tab :value="1">{{ t("userActivity") }}</v-tab>
</v-tabs>
</v-card>
</div>
<v-row>
<v-col row="12" lg="8">
<post-list class="mx-[-2.5ch] mt-[-16px]" v-if="account" :author="account.name" />
</v-col>
<v-col row="12" lg="4" order="first" order-lg="last">
<div class="sticky top-0 h-fit">
<v-card prepend-icon="mdi-identifier" title="About">
<v-card-text>
<p><b>Description</b></p>
<p>{{ account.description }}</p>
<p class="mt-3"><b>Joined At</b></p>
<p>{{ new Date(account.created_at).toLocaleString() }}</p>
</v-card-text>
</v-card>
</div>
</v-col>
</v-row>
</div>
</v-container>
</template>
<script setup lang="ts">
definePageMeta({
alias: ["/@:name(.*)*"],
})
const { t } = useI18n()
const route = useRoute()
const config = useRuntimeConfig()
const tab = ref(1)
const { data: account } = await useFetch<any>(`${config.public.solarNetworkApi}/cgi/co/publisher/${route.params.name}`)
if (account.value == null) {
throw createError({
statusCode: 404,
statusMessage: "User Not Found",
})
}
const urlOfAvatar = computed(() =>
account.value?.avatar ? `${config.public.solarNetworkApi}/cgi/uc/attachments/${account.value.avatar}` : void 0,
)
const urlOfBanner = computed(() =>
account.value?.banner ? `${config.public.solarNetworkApi}/cgi/uc/attachments/${account.value.banner}` : void 0,
)
const externalOpenLink = computed(() => `${config.public.solianUrl}/accounts/view/${route.params.name}`)
</script>

View File

@ -14,13 +14,3 @@ export async function solarFetch(input: string, init?: RequestInit) {
},
})
}
export function getAttachmentUrl(identifier: string | undefined): string | undefined {
if (identifier == null || identifier.length == 0) {
return undefined
}
if (identifier.startsWith("http")) {
return identifier
}
return `${useRuntimeConfig().public.solarNetworkApi}/cgi/uc/attachments/${identifier}`
}