324 lines
11 KiB
Vue
324 lines
11 KiB
Vue
<script setup lang="ts">
|
|
import { get } from 'lodash-es'
|
|
import AlbumWidget from '~/components/audio/album/Widget.vue'
|
|
import ChannelsWidget from '~/components/audio/ChannelsWidget.vue'
|
|
import LoginForm from '~/components/auth/LoginForm.vue'
|
|
import SignupForm from '~/components/auth/SignupForm.vue'
|
|
import useMarkdown from '~/composables/useMarkdown'
|
|
import { humanSize } from '~/utils/filters'
|
|
import { useStore } from '~/store'
|
|
import { computed } from 'vue'
|
|
import { whenever } from '@vueuse/core'
|
|
import { useI18n } from 'vue-i18n'
|
|
import { useRouter } from 'vue-router'
|
|
|
|
const { t } = useI18n()
|
|
const labels = computed(() => ({
|
|
title: t('components.Home.title')
|
|
}))
|
|
|
|
const store = useStore()
|
|
const nodeinfo = computed(() => store.state.instance.nodeinfo)
|
|
|
|
const podName = computed(() => get(nodeinfo.value, 'metadata.nodeName') || 'Funkwhale')
|
|
const banner = computed(() => get(nodeinfo.value, 'metadata.banner'))
|
|
const shortDescription = computed(() => get(nodeinfo.value, 'metadata.shortDescription'))
|
|
const longDescription = useMarkdown(() => get(nodeinfo.value, 'metadata.longDescription', ''))
|
|
const rules = computed(() => get(nodeinfo.value, 'metadata.rules'))
|
|
const contactEmail = computed(() => get(nodeinfo.value, 'metadata.contactEmail'))
|
|
const anonymousCanListen = computed(() => get(nodeinfo.value, 'metadata.library.anonymousCanListen'))
|
|
const openRegistrations = computed(() => get(nodeinfo.value, 'openRegistrations'))
|
|
const defaultUploadQuota = computed(() => get(nodeinfo.value, 'metadata.defaultUploadQuota'))
|
|
|
|
const stats = computed(() => {
|
|
const users = get(nodeinfo.value, 'usage.users.activeMonth', 0)
|
|
const hours = get(nodeinfo.value, 'metadata.library.music.hours', 0)
|
|
|
|
if (users === null) {
|
|
return null
|
|
}
|
|
|
|
return { users, hours }
|
|
})
|
|
|
|
const headerStyle = computed(() => {
|
|
if (!banner.value) {
|
|
return ''
|
|
}
|
|
|
|
return {
|
|
backgroundImage: `url(${store.getters['instance/absoluteUrl'](banner.value)})`
|
|
}
|
|
})
|
|
|
|
// TODO (wvffle): Check if needed
|
|
const router = useRouter()
|
|
whenever(() => store.state.auth.authenticated, () => {
|
|
console.log('Authenticated, redirecting to /library…')
|
|
router.push('/library')
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<main
|
|
v-title="labels.title"
|
|
class="main pusher page-home"
|
|
>
|
|
<section
|
|
:class="['ui', 'head', {'with-background': banner}, 'vertical', 'center', 'aligned', 'stripe', 'segment']"
|
|
:style="headerStyle"
|
|
>
|
|
<div class="segment-content">
|
|
<h1 class="ui center aligned large header">
|
|
<span>
|
|
{{ $t('components.Home.welcomeMessage', {podName: podName}) }}
|
|
</span>
|
|
<div
|
|
v-if="shortDescription"
|
|
class="sub header"
|
|
>
|
|
{{ shortDescription }}
|
|
</div>
|
|
</h1>
|
|
</div>
|
|
</section>
|
|
<section class="ui vertical stripe segment">
|
|
<div class="ui stackable grid">
|
|
<div class="ten wide column">
|
|
<h2 class="header">
|
|
{{ $t('components.Home.aboutPod') }}
|
|
</h2>
|
|
<div
|
|
id="pod"
|
|
class="ui raised segment"
|
|
>
|
|
<div class="ui stackable grid">
|
|
<div class="eight wide column">
|
|
<p v-if="!longDescription">
|
|
{{ $t('components.Home.noDescription') }}
|
|
</p>
|
|
<template v-if="longDescription || rules">
|
|
<sanitized-html
|
|
v-if="longDescription"
|
|
id="renderedDescription"
|
|
:html="longDescription"
|
|
/>
|
|
<div
|
|
v-if="longDescription"
|
|
class="ui hidden divider"
|
|
/>
|
|
<div class="ui relaxed list">
|
|
<div
|
|
v-if="longDescription"
|
|
class="item"
|
|
>
|
|
<i class="arrow right icon" />
|
|
<div class="content">
|
|
<router-link
|
|
class="ui link"
|
|
:to="{name: 'about'}"
|
|
>
|
|
{{ $t('components.Home.learnMore') }}
|
|
</router-link>
|
|
</div>
|
|
</div>
|
|
<div
|
|
v-if="rules"
|
|
class="item"
|
|
>
|
|
<i class="book open icon" />
|
|
<div class="content">
|
|
<router-link
|
|
v-if="rules"
|
|
class="ui link"
|
|
:to="{name: 'about', hash: '#rules'}"
|
|
>
|
|
{{ $t('components.Home.serverRules') }}
|
|
</router-link>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
<div class="eight wide column">
|
|
<template v-if="stats">
|
|
<h3 class="sub header">
|
|
{{ $t('components.Home.statistics') }}
|
|
</h3>
|
|
<p>
|
|
<i class="user icon" />
|
|
{{ $t('components.Home.activeUsers', {users: stats.users}) }}
|
|
</p>
|
|
<p>
|
|
<i class="music icon" />
|
|
{{ $t('components.Home.hoursOfMusic', {hours: stats.hours}) }}
|
|
</p>
|
|
</template>
|
|
<template v-if="contactEmail">
|
|
<h3 class="sub header">
|
|
{{ $t('components.Home.contactHeader') }}
|
|
</h3>
|
|
<i class="at icon" />
|
|
<a :href="`mailto:${contactEmail}`">{{ contactEmail }}</a>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="six wide column">
|
|
<img
|
|
class="ui image"
|
|
src="../assets/network.png"
|
|
alt=""
|
|
>
|
|
</div>
|
|
</div>
|
|
<div class="ui hidden divider" />
|
|
<div class="ui hidden divider" />
|
|
<div class="ui stackable grid">
|
|
<div class="four wide column">
|
|
<h3 class="header">
|
|
{{ $t('components.Home.aboutFunkwhale') }}
|
|
</h3>
|
|
<p>
|
|
{{ $t('components.Home.funkwhaleDescription') }}
|
|
</p>
|
|
<p>
|
|
{{ $t('components.Home.funkwhaleAddendum') }}
|
|
</p>
|
|
<a
|
|
target="_blank"
|
|
rel="noopener"
|
|
href="https://funkwhale.audio"
|
|
>
|
|
<i class="external alternate icon" />
|
|
{{ $t('components.Home.websiteLink') }}
|
|
</a>
|
|
</div>
|
|
<div class="four wide column">
|
|
<h3 class="header">
|
|
{{ $t('components.Home.loginHeader') }}
|
|
</h3>
|
|
<login-form
|
|
button-classes="success"
|
|
:show-signup="false"
|
|
/>
|
|
<div class="ui hidden clearing divider" />
|
|
</div>
|
|
<div class="four wide column">
|
|
<h3 class="header">
|
|
{{ $t('components.Home.signupHeader') }}
|
|
</h3>
|
|
<template v-if="openRegistrations">
|
|
<p>
|
|
{{ $t('components.Home.signupDescription') }}
|
|
</p>
|
|
<p v-if="defaultUploadQuota">
|
|
{{ $t('components.Home.uploadQuota', { quota: humanSize(defaultUploadQuota * 1000 * 1000) }) }}
|
|
</p>
|
|
<signup-form
|
|
button-classes="success"
|
|
:show-login="false"
|
|
/>
|
|
</template>
|
|
<div v-else>
|
|
<p>
|
|
{{ $t('components.Home.registrationsClosed') }}
|
|
</p>
|
|
<a
|
|
target="_blank"
|
|
rel="noopener"
|
|
href="https://funkwhale.audio/#get-started"
|
|
>
|
|
<i class="external alternate icon" />
|
|
{{ $t('components.Home.findOtherPod') }}
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="four wide column">
|
|
<h3 class="header">
|
|
{{ $t('components.Home.usefulLinks') }}
|
|
</h3>
|
|
<div class="ui relaxed list">
|
|
<div class="item">
|
|
<i class="headphones icon" />
|
|
<div class="content">
|
|
<router-link
|
|
v-if="anonymousCanListen"
|
|
class="header"
|
|
to="/library"
|
|
>
|
|
{{ $t('components.Home.browsePublicContent') }}
|
|
</router-link>
|
|
<div class="description">
|
|
{{ $t('components.Home.publicContentDescription') }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="item">
|
|
<i class="mobile alternate icon" />
|
|
<div class="content">
|
|
<a
|
|
class="header"
|
|
href="https://funkwhale.audio/en_US/apps"
|
|
target="_blank"
|
|
rel="noopener"
|
|
>
|
|
{{ $t('components.Home.mobileApps') }}
|
|
</a>
|
|
<div class="description">
|
|
{{ $t('components.Home.mobileAppsDescription') }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="item">
|
|
<i class="book icon" />
|
|
<div class="content">
|
|
<a
|
|
class="header"
|
|
href="https://docs.funkwhale.audio/users/index.html"
|
|
target="_blank"
|
|
rel="noopener"
|
|
>
|
|
{{ $t('components.Home.userGuides') }}
|
|
</a>
|
|
<div class="description">
|
|
{{ $t('components.Home.userGuidesDescription') }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
<section
|
|
v-if="anonymousCanListen"
|
|
class="ui vertical stripe segment"
|
|
>
|
|
<album-widget
|
|
:filters="{playable: true, ordering: '-creation_date'}"
|
|
:limit="10"
|
|
>
|
|
<template #title>
|
|
{{ $t('components.Home.recentlyAddedLabel') }}
|
|
</template>
|
|
<router-link to="/library">
|
|
{{ $t('components.Home.viewMore') }}
|
|
<div class="ui hidden divider" />
|
|
</router-link>
|
|
</album-widget>
|
|
<div class="ui hidden section divider" />
|
|
<h3 class="ui header">
|
|
{{ $t('components.Home.newChannelsLabel') }}
|
|
</h3>
|
|
<channels-widget
|
|
:show-modification-date="true"
|
|
:limit="10"
|
|
:filters="{ordering: '-creation_date', external: 'false'}"
|
|
/>
|
|
</section>
|
|
</main>
|
|
</template>
|