funkwhale/front/src/ui/modals/Upload.vue

199 lines
5.3 KiB
Vue

<script setup lang="ts">
import { computed, ref } from 'vue'
import { useI18n } from 'vue-i18n'
import { useStore } from '~/store'
import onKeyboardShortcut from '~/composables/onKeyboardShortcut'
import { useModal } from '~/ui/composables/useModal.ts'
import Modal from '~/components/ui/Modal.vue'
import Button from '~/components/ui/Button.vue'
import Layout from '~/components/ui/Layout.vue'
import Spacer from '~/components/ui/Spacer.vue'
import Alert from '~/components/ui/Alert.vue'
import Card from '~/components/ui/Card.vue'
import type { Actor, Channel, PrivacyLevel } from '~/types'
import FileUploadWidget from '~/components/library/FileUploadWidget.vue'
import type { VueUploadItem } from 'vue-upload-component'
import ChannelUpload from '~/components/channels/UploadForm.vue'
import LibraryUpload from '~/components/library/FileUpload.vue'
import LibraryWidget from '~/components/federation/LibraryWidget.vue'
const { t } = useI18n()
const store = useStore()
const { isOpen } = useModal('upload')
type UploadDestination =
| { type: 'channel', channel?: Channel | null, filter?: 'podcast' | 'music' }
| { type: 'library' }
type State =
{ uploadDestination? : UploadDestination, page: typeof pages[number], files?: string[] }
// initial state
const init = () => (
store.state.channels.uploadModalConfig.channel
? {
page: 'uploadFiles',
uploadDestination: { type: 'channel', channel: store.state.channels.uploadModalConfig.channel }
} as const
: { page: 'selectDestination' } as const
)
const state = ref<State>(init())
const pages = ['selectDestination', 'uploadFiles', 'uploadsInProgress'] as const
// Step 1
const destinationSelected = (destination: UploadDestination) =>
state.value = { ...state.value, uploadDestination: destination, page: 'uploadFiles' }
// Wait for pablo: If no channel exists, auto-create an empty channel
// Step 1.1
// Load the library for the chosen privacy level
const privacyLevel = ref<PrivacyLevel>('me')
// Lade User
const url = '`federation/actors/${object.full_username}/libraries/`'
// Step 2
const filesSelected = (e: InputEvent) => {
state.value = { ...state.value, files: [] }
}
const modalTitle = computed(() =>
({ selectDestination: 'Upload', uploadFiles: 'Select files for upload', uploadsInProgress: 'Uploading...' }
[state.value.page])
)
const channelUpload = ref()
</script>
<template>
<Modal
v-model="isOpen"
:cancel="t('components.channels.UploadModal.button.cancel')"
:title="modalTitle"
>
<!-- Page content -->
<!-- Page 1 -->
<Layout
v-if="state.page === 'selectDestination'"
flex
style="place-content:center"
>
<Card
small
solid
title="Music"
icon="bi-upload"
@click="destinationSelected({ type: 'library' })"
>
<template #image>
<i
class="bi bi-headphones solid secondary raised"
:class="$style.icon"
/>
</template>
{{ "Host music you listen to" /* TODO: Translate */ }}
</Card>
<Card
small
title="Music"
solid
icon="bi-upload primary solid"
@click="destinationSelected({ type: 'channel', filter: 'music' })"
>
<template #image>
<i
class="bi bi-music-note-beamed solid primary"
:class="$style.icon"
/>
</template>
{{ "Publish music you make" /* TODO: Translate */ }}
</Card>
<Card
small
solid
title="Podcast"
icon="bi-upload primary solid"
@click="destinationSelected({ type: 'channel', filter: 'podcast' })"
>
<template #image>
<i
class="bi bi-mic-fill solid primary"
:class="$style.icon"
/>
</template>
{{ "Publish podcasts you make" /* TODO: Translate */ }}
</Card>
</Layout>
<!-- Page 2 -->
<Layout
v-if="state.page === 'uploadFiles'"
stack
>
<!-- -->
<ChannelUpload
v-if="state.uploadDestination?.type === 'channel'"
ref="channelUpload"
:filter="state.uploadDestination.filter"
:channel="null"
/>
<!-- -->
<!-- Privacy Slider -->
<LibraryUpload
v-if="state.uploadDestination?.type === 'library'"
v-model="privacyLevel"
/>
{{ state.files }}
</Layout>
<template #actions>
<Button
v-if="state.page !== pages[0]"
secondary
:on-click="() => { state.page = pages[(pages.indexOf(state.page) || 1) - 1] }"
>
{{ t('components.channels.UploadModal.button.previous') }}
</Button>
<Spacer
h
grow
/>
<Spacer size-16 />
<Button
v-if="state.page === 'uploadFiles'"
primary
>
{{ t('components.channels.UploadModal.button.finishLater') }} /
{{ t('components.channels.UploadModal.button.update') }}
</Button>
<Button
v-if="channelUpload"
:on-click="() => channelUpload.publish()"
>
{{ t('components.channels.UploadModal.button.publish') }}
</Button>
</template>
</Modal>
</template>
<style module>
.icon {
font-size:100px;
padding:28px;
inset:0;
display:block;
text-align: center;
}
</style>