diff options
Diffstat (limited to 'packages/frontend/src/pages/about.overview.vue')
| -rw-r--r-- | packages/frontend/src/pages/about.overview.vue | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/packages/frontend/src/pages/about.overview.vue b/packages/frontend/src/pages/about.overview.vue new file mode 100644 index 0000000000..c378c0a0b8 --- /dev/null +++ b/packages/frontend/src/pages/about.overview.vue @@ -0,0 +1,210 @@ +<!-- +SPDX-FileCopyrightText: syuilo and misskey-project +SPDX-License-Identifier: AGPL-3.0-only +--> + +<template> +<div class="_gaps_m"> + <div :class="$style.banner" :style="{ backgroundImage: `url(${ instance.bannerUrl })` }"> + <div style="overflow: clip;"> + <img :src="instance.iconUrl ?? instance.faviconUrl ?? '/favicon.ico'" alt="" :class="$style.bannerIcon"/> + <div :class="$style.bannerName"> + <b>{{ instance.name ?? host }}</b> + </div> + </div> + </div> + + <MkKeyValue> + <template #key>{{ i18n.ts.description }}</template> + <template #value><div v-html="sanitizeHtml(instance.description)"></div></template> + </MkKeyValue> + + <FormSection> + <div class="_gaps_m"> + <MkKeyValue :copy="version"> + <template #key>Sharkey</template> + <template #value>{{ version }}</template> + </MkKeyValue> + <div v-html="i18n.tsx.poweredByMisskeyDescription({ name: instance.name ?? host })"> + </div> + <FormLink to="/about-sharkey"> + <template #icon><i class="ti ti-info-circle"></i></template> + {{ i18n.ts.aboutMisskey }} + </FormLink> + <FormLink v-if="instance.repositoryUrl || instance.providesTarball" :to="instance.repositoryUrl || `/tarball/sharkey-${version}.tar.gz`" external> + <template #icon><i class="ti ti-code"></i></template> + {{ i18n.ts.sourceCode }} + </FormLink> + <MkInfo v-else warn> + {{ i18n.ts.sourceCodeIsNotYetProvided }} + </MkInfo> + </div> + </FormSection> + + <FormSection> + <div class="_gaps_m"> + <FormSplit> + <MkKeyValue :copy="instance.maintainerName"> + <template #key>{{ i18n.ts.administrator }}</template> + <template #value> + <template v-if="instance.maintainerName">{{ instance.maintainerName }}</template> + <span v-else style="opacity: 0.7;">({{ i18n.ts.none }})</span> + </template> + </MkKeyValue> + <MkKeyValue :copy="instance.maintainerEmail"> + <template #key>{{ i18n.ts.contact }}</template> + <template #value> + <template v-if="instance.maintainerEmail">{{ instance.maintainerEmail }}</template> + <span v-else style="opacity: 0.7;">({{ i18n.ts.none }})</span> + </template> + </MkKeyValue> + <MkKeyValue> + <template #key>{{ i18n.ts.inquiry }}</template> + <template #value> + <MkLink v-if="instance.inquiryUrl" :url="instance.inquiryUrl" target="_blank">{{ instance.inquiryUrl }}</MkLink> + <span v-else style="opacity: 0.7;">({{ i18n.ts.none }})</span> + </template> + </MkKeyValue> + </FormSplit> + <FormLink v-if="instance.impressumUrl" :to="instance.impressumUrl" external> + <template #icon><i class="ti ti-user-shield"></i></template> + {{ i18n.ts.impressum }} + </FormLink> + <div class="_gaps_s"> + <FormLink v-if="instance.impressumUrl" :to="instance.impressumUrl" external> + <template #icon><i class="ti ti-user-shield"></i></template> + <template #default>{{ i18n.ts.impressum }}</template> + </FormLink> + <MkFolder v-if="instance.serverRules.length > 0"> + <template #icon><i class="ti ti-checkup-list"></i></template> + <template #label>{{ i18n.ts.serverRules }}</template> + <ol class="_gaps_s" :class="$style.rules"> + <li v-for="item in instance.serverRules" :key="item" :class="$style.rule"> + <div :class="$style.ruleText" v-html="sanitizeHtml(item)"></div> + </li> + </ol> + </MkFolder> + <FormLink v-if="instance.tosUrl" :to="instance.tosUrl" external> + <template #icon><i class="ti ti-license"></i></template> + <template #default>{{ i18n.ts.termsOfService }}</template> + </FormLink> + <FormLink v-if="instance.privacyPolicyUrl" :to="instance.privacyPolicyUrl" external> + <template #icon><i class="ti ti-shield-lock"></i></template> + <template #default>{{ i18n.ts.privacyPolicy }}</template> + </FormLink> + <FormLink v-if="instance.feedbackUrl" :to="instance.feedbackUrl" external> + <template #icon><i class="ti ti-message"></i></template> + <template #default>{{ i18n.ts.feedback }}</template> + </FormLink> + </div> + </div> + </FormSection> + + <FormSuspense v-slot="{ result: stats }" :p="initStats"> + <FormSection> + <template #label>{{ i18n.ts.statistics }}</template> + <FormSplit> + <MkKeyValue> + <template #key>{{ i18n.ts.users }}</template> + <template #value>{{ number(stats.originalUsersCount) }}</template> + </MkKeyValue> + <MkKeyValue> + <template #key>{{ i18n.ts.notes }}</template> + <template #value>{{ number(stats.originalNotesCount) }}</template> + </MkKeyValue> + </FormSplit> + </FormSection> + </FormSuspense> + + <FormSection> + <template #label>Well-known resources</template> + <div class="_gaps_s"> + <FormLink to="/.well-known/host-meta" external>host-meta</FormLink> + <FormLink to="/.well-known/host-meta.json" external>host-meta.json</FormLink> + <FormLink to="/.well-known/nodeinfo" external>nodeinfo</FormLink> + <FormLink to="/robots.txt" external>robots.txt</FormLink> + <FormLink to="/manifest.json" external>manifest.json</FormLink> + </div> + </FormSection> +</div> +</template> + +<script lang="ts" setup> +import sanitizeHtml from '@/scripts/sanitize-html.js'; +import { host, version } from '@/config.js'; +import { i18n } from '@/i18n.js'; +import { instance } from '@/instance.js'; +import number from '@/filters/number.js'; +import { misskeyApi } from '@/scripts/misskey-api.js'; +import FormLink from '@/components/form/link.vue'; +import FormSection from '@/components/form/section.vue'; +import FormSplit from '@/components/form/split.vue'; +import FormSuspense from '@/components/form/suspense.vue'; +import MkFolder from '@/components/MkFolder.vue'; +import MkKeyValue from '@/components/MkKeyValue.vue'; +import MkLink from '@/components/MkLink.vue'; + +const initStats = () => misskeyApi('stats', {}); +</script> + +<style lang="scss" module> +.banner { + text-align: center; + border-radius: var(--radius); + overflow: clip; + background-color: var(--panel); + background-size: cover; + background-position: center center; +} + +.bannerIcon { + display: block; + margin: 16px auto 0 auto; + height: 64px; + border-radius: var(--radius-sm);; +} + +.bannerName { + display: block; + padding: 16px; + color: #fff; + text-shadow: 0 0 8px #000; + background: linear-gradient(transparent, rgba(0, 0, 0, 0.7)); +} + +.rules { + counter-reset: item; + list-style: none; + padding: 0; + margin: 0; +} + +.rule { + display: flex; + gap: 8px; + word-break: break-word; + + &::before { + flex-shrink: 0; + display: flex; + position: sticky; + top: calc(var(--stickyTop, 0px) + 8px); + counter-increment: item; + content: counter(item); + width: 32px; + height: 32px; + line-height: 32px; + background-color: var(--accentedBg); + color: var(--accent); + font-size: 13px; + font-weight: bold; + align-items: center; + justify-content: center; + border-radius: var(--radius-ellipse); + } +} + +.ruleText { + padding-top: 6px; +} +</style> |