Fix auto-fixable linter issues
This commit is contained in:
parent
73b1dc8f30
commit
bbdb3dcb9d
|
@ -73,6 +73,7 @@
|
|||
"eslint-config-standard": "17.0.0",
|
||||
"eslint-plugin-html": "6.2.0",
|
||||
"eslint-plugin-import": "2.26.0",
|
||||
"eslint-plugin-n": "^15.2.4",
|
||||
"eslint-plugin-node": "11.1.0",
|
||||
"eslint-plugin-promise": "6.0.0",
|
||||
"eslint-plugin-vue": "9.2.0",
|
||||
|
|
|
@ -23,7 +23,7 @@ const shortDescription = computed(() => get(nodeinfo.value, 'metadata.shortDescr
|
|||
const stats = computed(() => {
|
||||
const users = get(nodeinfo.value, 'usage.users.activeMonth', null)
|
||||
const hours = get(nodeinfo.value, 'metadata.library.music.hours', 0)
|
||||
|
||||
|
||||
if (users === null) {
|
||||
return null
|
||||
}
|
||||
|
@ -39,8 +39,8 @@ const headerStyle = computed(() => {
|
|||
return ''
|
||||
}
|
||||
|
||||
return {
|
||||
backgroundImage: `url(${store.getters['instance/absoluteUrl'](banner.value)})`
|
||||
return {
|
||||
backgroundImage: `url(${store.getters['instance/absoluteUrl'](banner.value)})`
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
|
|
@ -53,8 +53,8 @@ const headerStyle = computed(() => {
|
|||
return ''
|
||||
}
|
||||
|
||||
return {
|
||||
backgroundImage: `url(${store.getters['instance/absoluteUrl'](banner.value)})`
|
||||
return {
|
||||
backgroundImage: `url(${store.getters['instance/absoluteUrl'](banner.value)})`
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
@ -138,7 +138,7 @@ const headerStyle = computed(() => {
|
|||
About this pod
|
||||
</translate>
|
||||
</h2>
|
||||
<sanitized-html
|
||||
<sanitized-html
|
||||
v-if="longDescription"
|
||||
:html="markdown.makeHtml(longDescription)"
|
||||
/>
|
||||
|
|
|
@ -35,7 +35,7 @@ const defaultUploadQuota = computed(() => get(nodeinfo.value, 'metadata.defaultU
|
|||
const stats = computed(() => {
|
||||
const users = get(nodeinfo.value, 'usage.users.activeMonth', null)
|
||||
const hours = get(nodeinfo.value, 'metadata.library.music.hours', 0)
|
||||
|
||||
|
||||
if (users === null) {
|
||||
return null
|
||||
}
|
||||
|
@ -48,8 +48,8 @@ const headerStyle = computed(() => {
|
|||
return ''
|
||||
}
|
||||
|
||||
return {
|
||||
backgroundImage: `url(${store.getters['instance/absoluteUrl'](banner.value)})`
|
||||
return {
|
||||
backgroundImage: `url(${store.getters['instance/absoluteUrl'](banner.value)})`
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ import { useGettext } from 'vue3-gettext'
|
|||
const path = window.location.href
|
||||
|
||||
const { $pgettext } = useGettext()
|
||||
const labels = computed(() => ({
|
||||
const labels = computed(() => ({
|
||||
title: $pgettext('Head/*/Title', 'Page Not Found')
|
||||
}))
|
||||
</script>
|
||||
|
|
|
@ -8,7 +8,7 @@ import TrackFavoriteIcon from '~/components/favorites/TrackFavoriteIcon.vue'
|
|||
import TrackPlaylistIcon from '~/components/playlists/TrackPlaylistIcon.vue'
|
||||
import Draggable from 'vuedraggable'
|
||||
import { whenever, useTimeoutFn, useWindowScroll, useWindowSize } from '@vueuse/core'
|
||||
import { useGettext } from "vue3-gettext"
|
||||
import { useGettext } from 'vue3-gettext'
|
||||
import useQueue from '~/composables/audio/useQueue'
|
||||
import usePlayer from '~/composables/audio/usePlayer'
|
||||
|
||||
|
@ -42,8 +42,8 @@ onMounted(async () => {
|
|||
|
||||
const { $pgettext } = useGettext()
|
||||
|
||||
const {
|
||||
playing,
|
||||
const {
|
||||
playing,
|
||||
loading: isLoadingAudio,
|
||||
errored,
|
||||
focused: playerFocused,
|
||||
|
@ -54,10 +54,10 @@ const {
|
|||
bufferProgress,
|
||||
currentTime,
|
||||
pause,
|
||||
resume,
|
||||
resume
|
||||
} = usePlayer()
|
||||
|
||||
const {
|
||||
const {
|
||||
focused: queueFocused,
|
||||
currentTrack,
|
||||
hasNext,
|
||||
|
|
|
@ -29,16 +29,15 @@ const type = ref(props.initialType)
|
|||
const id = ref(props.initialId)
|
||||
const errors = ref([] as string[])
|
||||
|
||||
|
||||
const { $pgettext } = useGettext()
|
||||
const labels = computed(() => ({
|
||||
title: type.value === 'rss'
|
||||
title: type.value === 'rss'
|
||||
? $pgettext('Head/Fetch/Title', 'Subscribe to a podcast RSS feed')
|
||||
: $pgettext('Head/Fetch/Title', 'Subscribe to a podcast hosted on the Fediverse'),
|
||||
fieldLabel: type.value === 'rss'
|
||||
fieldLabel: type.value === 'rss'
|
||||
? $pgettext('*/*/*', 'RSS feed location')
|
||||
: $pgettext('*/*/*', 'Fediverse object'),
|
||||
fieldPlaceholder: type.value === 'rss'
|
||||
fieldPlaceholder: type.value === 'rss'
|
||||
? $pgettext('Head/Fetch/Field.Placeholder', 'https://website.example.com/rss.xml')
|
||||
: $pgettext('Head/Fetch/Field.Placeholder', '@username@example.com')
|
||||
}))
|
||||
|
|
|
@ -8,7 +8,7 @@ interface Props {
|
|||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
tag: 'div'
|
||||
tag: 'div'
|
||||
})
|
||||
|
||||
const html = computed(() => DOMPurify.sanitize(props.html))
|
||||
|
@ -17,4 +17,4 @@ const root = () => h(props.tag, { innerHTML: html.value })
|
|||
|
||||
<template>
|
||||
<root />
|
||||
</template>
|
||||
</template>
|
||||
|
|
|
@ -39,7 +39,7 @@ const labels = computed(() => ({
|
|||
selectTrack: $pgettext('Sidebar/Player/Hidden text', 'Play this track'),
|
||||
pendingFollows: $pgettext('Sidebar/Notifications/Hidden text', 'Pending follow requests'),
|
||||
pendingReviewEdits: $pgettext('Sidebar/Moderation/Hidden text', 'Pending review edits'),
|
||||
pendingReviewReports: $pgettext('Sidebar/Moderation/Hidden text', 'Pending review reports'),
|
||||
pendingReviewReports: $pgettext('Sidebar/Moderation/Hidden text', 'Pending review reports'),
|
||||
language: $pgettext('Sidebar/Settings/Dropdown.Label/Short, Verb', 'Language'),
|
||||
theme: $pgettext('Sidebar/Settings/Dropdown.Label/Short, Verb', 'Theme'),
|
||||
addContent: $pgettext('*/Library/*/Verb', 'Add content'),
|
||||
|
@ -51,11 +51,11 @@ const expanded = ref<SidebarMenuTabs>('explore')
|
|||
|
||||
const ROUTE_MAPPINGS: Record<SidebarMenuTabs, RouteRecordName[]> = {
|
||||
explore: [
|
||||
'search',
|
||||
'library.index',
|
||||
'library.podcasts.browse',
|
||||
'library.albums.browse',
|
||||
'library.albums.detail',
|
||||
'search',
|
||||
'library.index',
|
||||
'library.podcasts.browse',
|
||||
'library.albums.browse',
|
||||
'library.albums.detail',
|
||||
'library.artists.browse',
|
||||
'library.artists.detail',
|
||||
'library.tracks.detail',
|
||||
|
@ -88,10 +88,10 @@ watchEffect(() => {
|
|||
expanded.value = store.state.auth.authenticated ? 'myLibrary' : 'explore'
|
||||
})
|
||||
|
||||
const moderationNotifications = computed(() =>
|
||||
store.state.ui.notifications.pendingReviewEdits
|
||||
+ store.state.ui.notifications.pendingReviewReports
|
||||
+ store.state.ui.notifications.pendingReviewRequests
|
||||
const moderationNotifications = computed(() =>
|
||||
store.state.ui.notifications.pendingReviewEdits +
|
||||
store.state.ui.notifications.pendingReviewReports +
|
||||
store.state.ui.notifications.pendingReviewRequests
|
||||
)
|
||||
|
||||
Promise.resolve().then(async () => {
|
||||
|
|
|
@ -53,7 +53,7 @@ const save = async () => {
|
|||
let contentType = 'application/json'
|
||||
|
||||
if (fileSettings.value.length > 0) {
|
||||
const fileSettingsIDs = fileSettings.value.map((setting) => setting.identifier)
|
||||
const fileSettingsIDs = fileSettings.value.map((setting) => setting.identifier)
|
||||
const data = settings.value.reduce((data, setting) => {
|
||||
if (fileSettingsIDs.includes(setting.identifier)) {
|
||||
const input = fileRefs[setting.identifier]
|
||||
|
@ -69,7 +69,7 @@ const save = async () => {
|
|||
}
|
||||
|
||||
return data
|
||||
}, {} as Record<string, string | File>)
|
||||
}, {} as Record<string, string | File>)
|
||||
|
||||
contentType = 'multipart/form-data'
|
||||
postData = useFormData(data)
|
||||
|
|
|
@ -7,7 +7,6 @@ import useQueue from '~/composables/audio/useQueue'
|
|||
import usePlayer from '~/composables/audio/usePlayer'
|
||||
import { computed } from 'vue'
|
||||
|
||||
|
||||
interface Props {
|
||||
// TODO (wvffle): Is it correct type?
|
||||
entry: Track
|
||||
|
|
|
@ -90,7 +90,7 @@ export default {
|
|||
const params = clone(this.filters)
|
||||
params.page_size = this.limit
|
||||
params.include_channels = true
|
||||
axios.get(url, { params: params }).then((response) => {
|
||||
axios.get(url, { params }).then((response) => {
|
||||
self.nextPage = response.data.next
|
||||
self.isLoading = false
|
||||
self.objects = self.objects.concat(response.data.results)
|
||||
|
|
|
@ -71,7 +71,7 @@ export default {
|
|||
const params = clone(this.filters)
|
||||
params.page_size = this.limit
|
||||
params.include_channels = true
|
||||
axios.get(url, { params: params }).then((response) => {
|
||||
axios.get(url, { params }).then((response) => {
|
||||
self.nextPage = response.data.next
|
||||
self.isLoading = false
|
||||
self.objects = self.objects.concat(response.data.results)
|
||||
|
|
|
@ -32,7 +32,7 @@ const iframeSrc = computed(() => {
|
|||
const bParam = !window.location.href.startsWith(instanceUrl)
|
||||
? `&b=${instanceUrl}`
|
||||
: ''
|
||||
|
||||
|
||||
return `${base}embed.html?&type=${props.type}&id=${props.id}${bParam}`
|
||||
})
|
||||
|
||||
|
|
|
@ -51,10 +51,10 @@ const props = withDefaults(defineProps<Props>(), {
|
|||
paused: () => false
|
||||
})
|
||||
|
||||
const {
|
||||
playable,
|
||||
filterableArtist,
|
||||
filterArtist,
|
||||
const {
|
||||
playable,
|
||||
filterableArtist,
|
||||
filterArtist,
|
||||
enqueue,
|
||||
enqueueNext,
|
||||
replacePlay,
|
||||
|
@ -75,14 +75,14 @@ const labels = computed(() => ({
|
|||
addToPlaylist: $pgettext('Sidebar/Player/Icon.Tooltip/Verb', 'Add to playlist…'),
|
||||
hideArtist: $pgettext('*/Queue/Dropdown/Button/Label/Short', 'Hide content from this artist'),
|
||||
replacePlay: props.track
|
||||
? $pgettext('*/Queue/Dropdown/Button/Title', 'Play track')
|
||||
: props.album
|
||||
? $pgettext('*/Queue/Dropdown/Button/Title', 'Play album')
|
||||
: props.artist
|
||||
? $pgettext('*/Queue/Dropdown/Button/Title', 'Play artist')
|
||||
: props.playlist
|
||||
? $pgettext('*/Queue/Dropdown/Button/Title', 'Play playlist')
|
||||
: $pgettext('*/Queue/Dropdown/Button/Title', 'Play tracks')
|
||||
? $pgettext('*/Queue/Dropdown/Button/Title', 'Play track')
|
||||
: props.album
|
||||
? $pgettext('*/Queue/Dropdown/Button/Title', 'Play album')
|
||||
: props.artist
|
||||
? $pgettext('*/Queue/Dropdown/Button/Title', 'Play artist')
|
||||
: props.playlist
|
||||
? $pgettext('*/Queue/Dropdown/Button/Title', 'Play playlist')
|
||||
: $pgettext('*/Queue/Dropdown/Button/Title', 'Play tracks')
|
||||
}))
|
||||
|
||||
const title = computed(() => {
|
||||
|
|
|
@ -284,7 +284,7 @@ const switchTab = () => {
|
|||
>
|
||||
{{ currentTimeFormatted }}
|
||||
</span>
|
||||
|
|
||||
|
|
||||
<span class="total">{{ durationFormatted }}</span>
|
||||
</template>
|
||||
</div>
|
||||
|
|
|
@ -125,7 +125,7 @@ export default {
|
|||
query: this.query
|
||||
}
|
||||
axios.get('search', {
|
||||
params: params
|
||||
params
|
||||
}).then((response) => {
|
||||
self.results = self.castResults(response.data)
|
||||
self.isLoading = false
|
||||
|
|
|
@ -17,7 +17,7 @@ const sliderVolume = computed({
|
|||
})
|
||||
|
||||
const { $pgettext } = useGettext()
|
||||
const labels = computed(() => ({
|
||||
const labels = computed(() => ({
|
||||
unmute: $pgettext('Sidebar/Player/Icon.Tooltip/Verb', 'Unmute'),
|
||||
mute: $pgettext('Sidebar/Player/Icon.Tooltip/Verb', 'Mute'),
|
||||
slider: $pgettext('Sidebar/Player/Icon.Tooltip/Verb', 'Adjust volume')
|
||||
|
|
|
@ -107,7 +107,7 @@ export default {
|
|||
const params = { q: this.query, ...this.filters }
|
||||
params.page_size = this.limit
|
||||
params.offset = this.offset
|
||||
axios.get(url, { params: params }).then((response) => {
|
||||
axios.get(url, { params }).then((response) => {
|
||||
self.previousPage = response.data.previous
|
||||
self.nextPage = response.data.next
|
||||
self.isLoading = false
|
||||
|
|
|
@ -103,7 +103,7 @@ export default {
|
|||
const params = { q: this.query, ...this.filters }
|
||||
params.page_size = this.limit
|
||||
params.offset = this.offset
|
||||
axios.get(url, { params: params }).then((response) => {
|
||||
axios.get(url, { params }).then((response) => {
|
||||
self.previousPage = response.data.previous
|
||||
self.nextPage = response.data.next
|
||||
self.isLoading = false
|
||||
|
|
|
@ -47,22 +47,22 @@ const store = useStore()
|
|||
const isFavorite = computed(() => store.getters['favorites/isFavorite'](props.track.id))
|
||||
|
||||
const { $pgettext } = useGettext()
|
||||
const favoriteButton = computed(() => isFavorite.value
|
||||
const favoriteButton = computed(() => isFavorite.value
|
||||
? $pgettext('Content/Track/Icon.Tooltip/Verb', 'Remove from favorites')
|
||||
: $pgettext('Content/Track/*/Verb', 'Add to favorites')
|
||||
)
|
||||
|
||||
const trackDetailsButton = computed(() => props.track.artist?.content_category === 'podcast'
|
||||
const trackDetailsButton = computed(() => props.track.artist?.content_category === 'podcast'
|
||||
? $pgettext('*/Queue/Dropdown/Button/Label/Short', 'Episode details')
|
||||
: $pgettext('*/Queue/Dropdown/Button/Label/Short', 'Track details')
|
||||
)
|
||||
|
||||
const albumDetailsButton = computed(() => props.track.artist?.content_category === 'podcast'
|
||||
const albumDetailsButton = computed(() => props.track.artist?.content_category === 'podcast'
|
||||
? $pgettext('*/Queue/Dropdown/Button/Label/Short', 'View series')
|
||||
: $pgettext('*/Queue/Dropdown/Button/Label/Short', 'View album')
|
||||
)
|
||||
|
||||
const artistDetailsButton = computed(() => props.track.artist?.content_category === 'podcast'
|
||||
const artistDetailsButton = computed(() => props.track.artist?.content_category === 'podcast'
|
||||
? $pgettext('*/Queue/Dropdown/Button/Label/Short', 'View channel')
|
||||
: $pgettext('*/Queue/Dropdown/Button/Label/Short', 'View artist')
|
||||
)
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import type { Track, Artist, Album, Playlist, Library, Channel, Actor } from '~/types'
|
||||
import type { Track, Artist, Album, Playlist, Library, Channel, Actor, /* Track, */ Cover } from '~/types'
|
||||
import type { PlayOptionsProps } from '~/composables/audio/usePlayOptions'
|
||||
import type { /* Track, */ Cover } from '~/types'
|
||||
|
||||
import axios from 'axios'
|
||||
import PlayButton from '~/components/audio/PlayButton.vue'
|
||||
|
|
|
@ -73,7 +73,6 @@ withDefaults(defineProps<Props>(), {
|
|||
</div>
|
||||
|
||||
<div :class="['track-table', 'ui', 'unstackable', 'grid', 'tablet-and-below']">
|
||||
|
||||
<!-- For each item, build a row -->
|
||||
|
||||
<track-mobile-row
|
||||
|
|
|
@ -47,22 +47,22 @@ const store = useStore()
|
|||
const isFavorite = computed(() => store.getters['favorites/isFavorite'](props.track.id))
|
||||
|
||||
const { $pgettext } = useGettext()
|
||||
const favoriteButton = computed(() => isFavorite.value
|
||||
const favoriteButton = computed(() => isFavorite.value
|
||||
? $pgettext('Content/Track/Icon.Tooltip/Verb', 'Remove from favorites')
|
||||
: $pgettext('Content/Track/*/Verb', 'Add to favorites')
|
||||
)
|
||||
|
||||
const trackDetailsButton = computed(() => props.track.artist?.content_category === 'podcast'
|
||||
const trackDetailsButton = computed(() => props.track.artist?.content_category === 'podcast'
|
||||
? $pgettext('*/Queue/Dropdown/Button/Label/Short', 'Episode details')
|
||||
: $pgettext('*/Queue/Dropdown/Button/Label/Short', 'Track details')
|
||||
)
|
||||
|
||||
const albumDetailsButton = computed(() => props.track.artist?.content_category === 'podcast'
|
||||
const albumDetailsButton = computed(() => props.track.artist?.content_category === 'podcast'
|
||||
? $pgettext('*/Queue/Dropdown/Button/Label/Short', 'View series')
|
||||
: $pgettext('*/Queue/Dropdown/Button/Label/Short', 'View album')
|
||||
)
|
||||
|
||||
const artistDetailsButton = computed(() => props.track.artist?.content_category === 'podcast'
|
||||
const artistDetailsButton = computed(() => props.track.artist?.content_category === 'podcast'
|
||||
? $pgettext('*/Queue/Dropdown/Button/Label/Short', 'View channel')
|
||||
: $pgettext('*/Queue/Dropdown/Button/Label/Short', 'View artist')
|
||||
)
|
||||
|
|
|
@ -69,9 +69,9 @@ const active = computed(() => props.track.id === currentTrack.value?.id && props
|
|||
!hover
|
||||
"
|
||||
/>
|
||||
<button
|
||||
<button
|
||||
v-else-if="
|
||||
!playing &&
|
||||
!playing &&
|
||||
active &&
|
||||
!hover
|
||||
"
|
||||
|
@ -79,9 +79,9 @@ const active = computed(() => props.track.id === currentTrack.value?.id && props
|
|||
>
|
||||
<i class="play icon" />
|
||||
</button>
|
||||
<button
|
||||
<button
|
||||
v-else-if="
|
||||
playing &&
|
||||
playing &&
|
||||
active &&
|
||||
hover
|
||||
"
|
||||
|
|
|
@ -24,7 +24,7 @@ interface Props {
|
|||
isAlbum?: boolean
|
||||
isPodcast?: boolean
|
||||
|
||||
// TODO (wvffle): Find correct type
|
||||
// TODO (wvffle): Find correct type
|
||||
filters?: object
|
||||
|
||||
nextUrl?: string | null
|
||||
|
@ -227,9 +227,9 @@ const updatePage = (page: number) => {
|
|||
|
||||
<track-row
|
||||
v-for="(track, index) in allTracks"
|
||||
:key="track.id + track.position"
|
||||
:data-track-id="track.id"
|
||||
:data-track-position="track.position"
|
||||
:key="track.id + track.position"
|
||||
:track="track"
|
||||
:index="index"
|
||||
:tracks="allTracks"
|
||||
|
|
|
@ -45,7 +45,7 @@ const fetchData = async (url = props.url) => {
|
|||
nextPage.value = response.data.next
|
||||
count.value = response.data.count
|
||||
|
||||
const newObjects = !props.isActivity
|
||||
const newObjects = !props.isActivity
|
||||
? response.data.results.map((track: Track) => { track })
|
||||
: response.data.results
|
||||
|
||||
|
@ -127,7 +127,10 @@ if (props.websocketHandlers.includes('Listen')) {
|
|||
{{ object.track.title }}
|
||||
</router-link>
|
||||
</div>
|
||||
<div v-if="object.track.artist" class="meta ellipsis">
|
||||
<div
|
||||
v-if="object.track.artist"
|
||||
class="meta ellipsis"
|
||||
>
|
||||
<span>
|
||||
<router-link
|
||||
class="discrete link"
|
||||
|
|
|
@ -18,7 +18,7 @@ const props = withDefaults(defineProps<Props>(), {
|
|||
const defaults = reactive({
|
||||
name: props.name,
|
||||
scopes: props.scopes,
|
||||
redirectUris: props.redirectUris,
|
||||
redirectUris: props.redirectUris
|
||||
})
|
||||
|
||||
const { $pgettext } = useGettext()
|
||||
|
|
|
@ -219,7 +219,7 @@ export default {
|
|||
return this.knownScopes.map(s => {
|
||||
const id = s.id
|
||||
return {
|
||||
id: id,
|
||||
id,
|
||||
icon: s.icon,
|
||||
label: self.sharedLabels.scopes[s.id].label,
|
||||
description: self.sharedLabels.scopes[s.id].description,
|
||||
|
|
|
@ -73,7 +73,10 @@
|
|||
</div>
|
||||
</div>
|
||||
<template v-if="plugin.conf?.length > 0">
|
||||
<template v-for="(field, key) in plugin.conf" :key="key">
|
||||
<template
|
||||
v-for="(field, key) in plugin.conf"
|
||||
:key="key"
|
||||
>
|
||||
<div
|
||||
v-if="field.type === 'text'"
|
||||
class="field"
|
||||
|
|
|
@ -601,7 +601,7 @@ export default {
|
|||
async fetchDraftUploads (channel) {
|
||||
const self = this
|
||||
this.draftUploads = null
|
||||
const response = await axios.get('uploads', { params: { import_status: 'draft', channel: channel } })
|
||||
const response = await axios.get('uploads', { params: { import_status: 'draft', channel } })
|
||||
this.draftUploads = response.data.results
|
||||
this.draftUploads.forEach((u) => {
|
||||
self.uploadImportData[u.uuid] = u.import_metadata
|
||||
|
|
|
@ -33,4 +33,4 @@ withDefaults(defineProps<Props>(), {
|
|||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
|
|
@ -8,4 +8,4 @@ defineProps<Props>()
|
|||
|
||||
<template>
|
||||
<span>{{ username }}</span>
|
||||
</template>
|
||||
</template>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import type { RouteWithPreferences } from '~/store/ui'
|
||||
import type { RouteWithPreferences, OrderingField } from '~/store/ui'
|
||||
import type { Track } from '~/types'
|
||||
import type { OrderingField } from '~/store/ui'
|
||||
import type { OrderingProps } from '~/composables/useOrdering'
|
||||
|
||||
import axios from 'axios'
|
||||
|
@ -77,7 +76,7 @@ const fetchFavorites = async () => {
|
|||
|
||||
try {
|
||||
logger.time('Loading user favorites')
|
||||
const response = await axios.get('tracks/', { params: params })
|
||||
const response = await axios.get('tracks/', { params })
|
||||
|
||||
results.length = 0
|
||||
results.push(...response.data.results)
|
||||
|
|
|
@ -89,7 +89,7 @@ export default {
|
|||
const params = clone({})
|
||||
params.page_size = this.limit
|
||||
params.offset = this.offset
|
||||
axios.get(url, { params: params }).then((response) => {
|
||||
axios.get(url, { params }).then((response) => {
|
||||
self.previousPage = response.data.previous
|
||||
self.nextPage = response.data.next
|
||||
self.isLoading = false
|
||||
|
|
|
@ -44,14 +44,14 @@ const fetchData = async () => {
|
|||
const albumResponse = await axios.get(`albums/${props.id}/`, { params: { refresh: 'true' } })
|
||||
const [artistResponse, tracksResponse] = await Promise.all([
|
||||
axios.get(`artists/${albumResponse.data.artist.id}/`),
|
||||
axios.get('tracks/', {
|
||||
params: {
|
||||
ordering: 'disc_number,position',
|
||||
album: props.id,
|
||||
page_size: paginateBy.value,
|
||||
page: page.value,
|
||||
include_channels: true
|
||||
}
|
||||
axios.get('tracks/', {
|
||||
params: {
|
||||
ordering: 'disc_number,position',
|
||||
album: props.id,
|
||||
page_size: paginateBy.value,
|
||||
page: page.value,
|
||||
include_channels: true
|
||||
}
|
||||
})
|
||||
])
|
||||
|
||||
|
@ -60,7 +60,6 @@ const fetchData = async () => {
|
|||
artist.value.channel.artist = artist.value
|
||||
}
|
||||
|
||||
|
||||
object.value = albumResponse.data
|
||||
if (object.value) {
|
||||
object.value.tracks = tracksResponse.data.results
|
||||
|
|
|
@ -180,4 +180,4 @@ const remove = () => emit('remove')
|
|||
</div>
|
||||
</button>
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
|
|
|
@ -80,7 +80,6 @@ const fetchData = async () => {
|
|||
nextTracksUrl.value = tracksResponse.data.next
|
||||
totalTracks.value = tracksResponse.data.count
|
||||
|
||||
|
||||
nextAlbumsUrl.value = albumsResponse.data.next
|
||||
totalAlbums.value = albumsResponse.data.count
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ export default {
|
|||
const self = this
|
||||
const params = clone(this.filters)
|
||||
params.page_size = this.limit
|
||||
axios.get(url, { params: params }).then((response) => {
|
||||
axios.get(url, { params }).then((response) => {
|
||||
self.previousPage = response.data.previous
|
||||
self.nextPage = response.data.next
|
||||
self.isLoading = false
|
||||
|
|
|
@ -36,7 +36,7 @@ const fetchData = async () => {
|
|||
}
|
||||
|
||||
try {
|
||||
const response = await axios.get('artists/', { params: params })
|
||||
const response = await axios.get('artists/', { params })
|
||||
artists.value = response.data.results
|
||||
} catch (error) {
|
||||
// TODO (wvffle): Handle error
|
||||
|
|
|
@ -58,9 +58,9 @@ const escapeHtml = (unsafe: string) => document.createTextNode(unsafe).textConte
|
|||
const subtitle = computed(() => {
|
||||
if (track.value?.attributed_to) {
|
||||
return $pgettext(
|
||||
'Content/Track/Paragraph',
|
||||
'Content/Track/Paragraph',
|
||||
'Uploaded by <a class="internal" href="%{ uploaderUrl }">%{ uploader }</a> on <time title="%{ date }" datetime="%{ date }">%{ prettyDate }</time>',
|
||||
{
|
||||
{
|
||||
uploaderUrl: attributedToUrl.value,
|
||||
uploader: escapeHtml(`@${track.value.attributed_to.full_username}`),
|
||||
date: escapeHtml(track.value.creation_date),
|
||||
|
@ -70,7 +70,7 @@ const subtitle = computed(() => {
|
|||
}
|
||||
|
||||
return $pgettext(
|
||||
'Content/Track/Paragraph',
|
||||
'Content/Track/Paragraph',
|
||||
'Uploaded on <time title="%{ date }" datetime="%{ date }">%{ prettyDate }</time>',
|
||||
{
|
||||
date: escapeHtml(track.value?.creation_date ?? ''),
|
||||
|
@ -79,7 +79,6 @@ const subtitle = computed(() => {
|
|||
)
|
||||
})
|
||||
|
||||
|
||||
const { $pgettext } = useGettext()
|
||||
const labels = computed(() => ({
|
||||
title: $pgettext('*/*/*/Noun', 'Track'),
|
||||
|
|
|
@ -19,12 +19,12 @@ interface Props {
|
|||
filter: {
|
||||
type: string
|
||||
label: string
|
||||
fields: {
|
||||
fields: {
|
||||
name: string
|
||||
placeholder: string
|
||||
type: 'list'
|
||||
subtype: 'number'
|
||||
autocomplete?: string
|
||||
autocomplete?: string
|
||||
autocomplete_qs: string
|
||||
autocomplete_fields: {
|
||||
remoteValues?: unknown
|
||||
|
@ -103,7 +103,7 @@ const fetchCandidates = async () => {
|
|||
const params = {
|
||||
filters: [{
|
||||
...clone(props.config),
|
||||
type: props.filter.type,
|
||||
type: props.filter.type
|
||||
}]
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import type { PrivacyLevel } from '~/types'
|
||||
import type { RouteWithPreferences } from '~/store/ui'
|
||||
import type { OrderingField } from '~/store/ui'
|
||||
import type { RouteWithPreferences, OrderingField } from '~/store/ui'
|
||||
import type { SmartSearchProps } from '~/composables/useSmartSearch'
|
||||
import type { OrderingProps } from '~/composables/useOrdering'
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import type { RouteWithPreferences } from '~/store/ui'
|
||||
import type { OrderingField } from '~/store/ui'
|
||||
import type { RouteWithPreferences, OrderingField } from '~/store/ui'
|
||||
import type { SmartSearchProps } from '~/composables/useSmartSearch'
|
||||
import type { OrderingProps } from '~/composables/useOrdering'
|
||||
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import type { ImportStatus, PrivacyLevel } from '~/types'
|
||||
import type { RouteWithPreferences } from '~/store/ui'
|
||||
import type { OrderingField } from '~/store/ui'
|
||||
import type { Upload } from '~/types'
|
||||
import type { ImportStatus, PrivacyLevel, Upload } from '~/types'
|
||||
import type { RouteWithPreferences, OrderingField } from '~/store/ui'
|
||||
import type { OrderingProps } from '~/composables/useOrdering'
|
||||
import type { SmartSearchProps } from '~/composables/useSmartSearch'
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ const fetchData = async () => {
|
|||
|
||||
target_account_domain: props.type === 'actor'
|
||||
? domain
|
||||
: undefined,
|
||||
: undefined
|
||||
}
|
||||
|
||||
isLoading.value = true
|
||||
|
|
|
@ -10,7 +10,6 @@ import { useStore } from '~/store'
|
|||
import SemanticModal from '~/components/semantic/Modal.vue'
|
||||
import useLogger from '~/composables/useLogger'
|
||||
|
||||
|
||||
const logger = useLogger()
|
||||
const { $pgettext } = useGettext()
|
||||
|
||||
|
|
|
@ -16,9 +16,9 @@
|
|||
<sanitized-html
|
||||
tag="span"
|
||||
class="link"
|
||||
:html="notificationData.message"
|
||||
@click="navigate"
|
||||
@keypress.enter="navigate"
|
||||
:html="notificationData.message"
|
||||
/>
|
||||
</router-link>
|
||||
<sanitized-html
|
||||
|
|
|
@ -16,7 +16,7 @@ const store = useStore()
|
|||
const images = computed(() => {
|
||||
const urls = props.playlist.album_covers.slice(0, 4).map(url => store.getters['instance/absoluteUrl'](url))
|
||||
|
||||
while (urls.length < 4) {
|
||||
while (urls.length < 4) {
|
||||
urls.push(defaultCover)
|
||||
}
|
||||
|
||||
|
|
|
@ -152,8 +152,8 @@ const insertMany = async (insertedTracks: Track[], allowDuplicates: boolean) =>
|
|||
<template>
|
||||
<div class="ui text container component-playlist-editor">
|
||||
<playlist-form
|
||||
:title="false"
|
||||
v-model:playlist="playlist"
|
||||
:title="false"
|
||||
/>
|
||||
<h3 class="ui top attached header">
|
||||
<translate translate-context="Content/Playlist/Title">
|
||||
|
|
|
@ -69,7 +69,7 @@ const submit = async () => {
|
|||
|
||||
try {
|
||||
const url = props.create ? 'playlists/' : `playlists/${playlist.value!.id}/`
|
||||
const method = props.create ? 'post' : 'patch'
|
||||
const method = props.create ? 'post' : 'patch'
|
||||
|
||||
const data = {
|
||||
name: name.value,
|
||||
|
@ -94,7 +94,6 @@ const submit = async () => {
|
|||
isLoading.value = false
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -26,7 +26,7 @@ const playlists = computed(() => store.state.playlists.playlists)
|
|||
const track = computed(() => store.state.playlists.modalTrack)
|
||||
|
||||
const { $pgettext } = useGettext()
|
||||
const labels = computed(() => ({
|
||||
const labels = computed(() => ({
|
||||
addToPlaylist: $pgettext('Popup/Playlist/Table.Button.Tooltip/Verb', 'Add to this playlist'),
|
||||
filterPlaylistField: $pgettext('Popup/Playlist/Form/Placeholder', 'Enter playlist name')
|
||||
}))
|
||||
|
@ -51,7 +51,7 @@ const duplicateTrackAddInfo = ref({} as { playlist_name?: string })
|
|||
const addToPlaylist = async (playlistId: number, allowDuplicates: boolean) => {
|
||||
lastSelectedPlaylist.value = playlistId
|
||||
|
||||
try {
|
||||
try {
|
||||
await axios.post(`playlists/${playlistId}/add/`, {
|
||||
tracks: [track.value?.id].filter(i => i),
|
||||
allow_duplicates: allowDuplicates
|
||||
|
@ -106,7 +106,10 @@ store.dispatch('playlists/fetchOwn')
|
|||
</translate>
|
||||
</h4>
|
||||
<div class="scrolling content">
|
||||
<playlist-form :create="true" :key="formKey" />
|
||||
<playlist-form
|
||||
:key="formKey"
|
||||
:create="true"
|
||||
/>
|
||||
<div class="ui divider" />
|
||||
<div v-if="playlists.length > 0">
|
||||
<div
|
||||
|
@ -249,9 +252,9 @@ store.dispatch('playlists/fetchOwn')
|
|||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
class="ui placeholder segment"
|
||||
<div
|
||||
v-else
|
||||
class="ui placeholder segment"
|
||||
>
|
||||
<div class="ui icon header">
|
||||
<i class="list icon" />
|
||||
|
|
|
@ -107,7 +107,7 @@ export default {
|
|||
const params = clone(this.filters)
|
||||
params.page_size = this.limit
|
||||
params.offset = this.offset
|
||||
axios.get(url, { params: params }).then((response) => {
|
||||
axios.get(url, { params }).then((response) => {
|
||||
self.previousPage = response.data.previous
|
||||
self.nextPage = response.data.next
|
||||
self.isLoading = false
|
||||
|
|
|
@ -27,12 +27,12 @@ const running = computed(() => {
|
|||
return false
|
||||
}
|
||||
|
||||
return store.state.radios.current?.type === props.type
|
||||
&& store.state.radios.current?.customRadioId === props.customRadioId
|
||||
&& (
|
||||
typeof props.objectId === 'string'
|
||||
|| store.state.radios.current?.objectId.fullUsername === props.objectId?.fullUsername
|
||||
)
|
||||
return store.state.radios.current?.type === props.type &&
|
||||
store.state.radios.current?.customRadioId === props.customRadioId &&
|
||||
(
|
||||
typeof props.objectId === 'string' ||
|
||||
store.state.radios.current?.objectId.fullUsername === props.objectId?.fullUsername
|
||||
)
|
||||
})
|
||||
|
||||
const { $pgettext } = useGettext()
|
||||
|
|
|
@ -3,7 +3,7 @@ import type { ContentFilter } from '~/store/moderation'
|
|||
|
||||
import { useStore } from '~/store'
|
||||
import { useGettext } from 'vue3-gettext'
|
||||
import { computed, ref } from "vue"
|
||||
import { computed, ref } from 'vue'
|
||||
import axios from 'axios'
|
||||
import usePlayer from '~/composables/audio/usePlayer'
|
||||
import useQueue from '~/composables/audio/useQueue'
|
||||
|
@ -36,8 +36,8 @@ export default (props: PlayOptionsProps) => {
|
|||
if (props.track) {
|
||||
return props.track.uploads?.length > 0
|
||||
} else if (props.artist) {
|
||||
return props.artist.tracks_count > 0
|
||||
|| props.artist.albums.some((album) => album.is_playable === true)
|
||||
return props.artist.tracks_count > 0 ||
|
||||
props.artist.albums.some((album) => album.is_playable === true)
|
||||
} else if (props.tracks) {
|
||||
return props.tracks.some((track) => (track.uploads?.length ?? 0) > 0)
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ export default (props: PlayOptionsProps) => {
|
|||
}
|
||||
|
||||
store.commit('ui/addMessage', {
|
||||
content: $npgettext('*/Queue/Message', '%{ count } track was added to your queue', '%{ count } tracks were added to your queue', tracks.length, {
|
||||
content: $npgettext('*/Queue/Message', '%{ count } track was added to your queue', '%{ count } tracks were added to your queue', tracks.length, {
|
||||
count: tracks.length.toString()
|
||||
}),
|
||||
date: new Date()
|
||||
|
@ -70,8 +70,8 @@ export default (props: PlayOptionsProps) => {
|
|||
|
||||
// when fetching artists/or album tracks, sometimes, we may have to fetch
|
||||
// multiple pages
|
||||
const response = await axios.get('tracks/', {
|
||||
params: {
|
||||
const response = await axios.get('tracks/', {
|
||||
params: {
|
||||
...params,
|
||||
page_size: 100,
|
||||
page,
|
||||
|
@ -136,7 +136,7 @@ export default (props: PlayOptionsProps) => {
|
|||
jQuery(el.value).find('.ui.dropdown').dropdown('hide')
|
||||
|
||||
const tracks = await getPlayableTracks()
|
||||
store.dispatch('queue/appendMany', { tracks: tracks }).then(() => addMessage(tracks))
|
||||
store.dispatch('queue/appendMany', { tracks }).then(() => addMessage(tracks))
|
||||
}
|
||||
|
||||
const enqueueNext = async (next = false) => {
|
||||
|
@ -188,7 +188,7 @@ export default (props: PlayOptionsProps) => {
|
|||
replacePlay()
|
||||
}
|
||||
|
||||
return {
|
||||
return {
|
||||
playable,
|
||||
filterableArtist,
|
||||
filterArtist,
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import type { Track } from "~/types"
|
||||
import type { Track } from '~/types'
|
||||
|
||||
import { useTimeoutFn, useThrottleFn, useTimeAgo, useNow, whenever } from '@vueuse/core'
|
||||
import { Howler } from 'howler'
|
||||
import { gettext } from '~/init/locale'
|
||||
import { ref, computed } from "vue"
|
||||
import { ref, computed } from 'vue'
|
||||
import { sum } from 'lodash-es'
|
||||
import store from "~/store"
|
||||
import store from '~/store'
|
||||
|
||||
const { $pgettext } = gettext
|
||||
|
||||
|
@ -25,7 +25,7 @@ const previous = () => store.dispatch('queue/previous')
|
|||
|
||||
const focused = computed(() => store.state.ui.queueFocused === 'queue')
|
||||
|
||||
//
|
||||
//
|
||||
// Track list
|
||||
//
|
||||
const tracksChangeBuffer = ref<Track[] | null>(null)
|
||||
|
@ -44,7 +44,7 @@ const reorder = (oldIndex: number, newIndex: number) => {
|
|||
tracksChangeBuffer.value = null
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// Shuffle
|
||||
//
|
||||
const isShuffling = ref(false)
|
||||
|
@ -88,12 +88,12 @@ const endsIn = useTimeAgo(computed(() => {
|
|||
}))
|
||||
|
||||
export default () => {
|
||||
return {
|
||||
return {
|
||||
currentTrack,
|
||||
currentIndex,
|
||||
hasNext,
|
||||
hasPrevious,
|
||||
isEmpty,
|
||||
isEmpty,
|
||||
isShuffling,
|
||||
|
||||
removeTrack,
|
||||
|
@ -110,4 +110,4 @@ export default () => {
|
|||
endsIn,
|
||||
focused
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import type { Track } from '~/types'
|
||||
|
||||
import { ref, computed } from "vue"
|
||||
import { ref, computed } from 'vue'
|
||||
import { Howl } from 'howler'
|
||||
import useTrackSources from '~/composables/audio/useTrackSources'
|
||||
import useSoundCache from '~/composables/audio/useSoundCache'
|
||||
import usePlayer from '~/composables/audio/usePlayer'
|
||||
import store from "~/store"
|
||||
import { createEventHook } from "@vueuse/core"
|
||||
import store from '~/store'
|
||||
import { createEventHook } from '@vueuse/core'
|
||||
|
||||
interface Sound {
|
||||
id?: number
|
||||
|
@ -152,4 +152,4 @@ export default () => {
|
|||
currentSound,
|
||||
onSoundProgress: soundProgress.on
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import type { Howl } from "howler"
|
||||
import type { Howl } from 'howler'
|
||||
|
||||
import { sortBy } from "lodash-es"
|
||||
import { reactive, watchEffect, ref } from "vue"
|
||||
import { sortBy } from 'lodash-es'
|
||||
import { reactive, watchEffect, ref } from 'vue'
|
||||
|
||||
const MAX_PRELOADED = 3
|
||||
|
||||
|
@ -15,7 +15,7 @@ const soundCache = reactive(new Map<string, CachedSound>())
|
|||
const cleaningCache = ref(false)
|
||||
|
||||
watchEffect(() => {
|
||||
let toRemove = soundCache.size - MAX_PRELOADED
|
||||
const toRemove = soundCache.size - MAX_PRELOADED
|
||||
|
||||
if (toRemove > 0 && !cleaningCache.value) {
|
||||
cleaningCache.value = true
|
||||
|
@ -33,7 +33,6 @@ watchEffect(() => {
|
|||
}
|
||||
})
|
||||
|
||||
|
||||
export default () => {
|
||||
return soundCache
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import type { Track } from "~/types"
|
||||
import type { Track } from '~/types'
|
||||
|
||||
import store from '~/store'
|
||||
import updateQueryString from '~/composables/updateQueryString'
|
||||
|
||||
export interface TrackSource {
|
||||
url: string
|
||||
url: string
|
||||
type: string
|
||||
}
|
||||
|
||||
|
@ -29,23 +29,23 @@ export default (trackData: Track): TrackSource[] => {
|
|||
sources.push({
|
||||
type: 'mp3',
|
||||
url: updateQueryString(
|
||||
store.getters['instance/absoluteUrl'](trackData.listen_url),
|
||||
'to',
|
||||
store.getters['instance/absoluteUrl'](trackData.listen_url),
|
||||
'to',
|
||||
'mp3'
|
||||
)
|
||||
})
|
||||
|
||||
const token = store.state.auth.scopedTokens.listen
|
||||
if (store.state.auth.authenticated && token !== null) {
|
||||
// we need to send the token directly in url
|
||||
// so authentication can be checked by the backend
|
||||
// because for audio files we cannot use the regular Authentication
|
||||
// header
|
||||
return sources.map(source => ({
|
||||
...source,
|
||||
url: updateQueryString(source.url, 'token', token)
|
||||
}))
|
||||
// we need to send the token directly in url
|
||||
// so authentication can be checked by the backend
|
||||
// because for audio files we cannot use the regular Authentication
|
||||
// header
|
||||
return sources.map(source => ({
|
||||
...source,
|
||||
url: updateQueryString(source.url, 'token', token)
|
||||
}))
|
||||
}
|
||||
|
||||
return sources
|
||||
}
|
||||
}
|
||||
|
|
|
@ -134,7 +134,7 @@ const report = (obj: ReportableObject) => {
|
|||
store.dispatch('moderation/report', obj.target)
|
||||
}
|
||||
|
||||
export default () => ({
|
||||
export default () => ({
|
||||
getReportableObjects,
|
||||
report
|
||||
})
|
||||
|
|
|
@ -83,7 +83,7 @@ export const install: InitModule = ({ store, router }) => {
|
|||
case 500:
|
||||
error.backendErrors.push('A server error occurred')
|
||||
break
|
||||
|
||||
|
||||
default:
|
||||
if (error.response?.data as object) {
|
||||
const data = error.response?.data as Record<string, unknown>
|
||||
|
|
|
@ -11,4 +11,4 @@ export const hasPermissions = (permission: Permission) => (to: RouteLocationNorm
|
|||
|
||||
console.log('Not authenticated. Redirecting to library.')
|
||||
next({ name: 'library.index' })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,5 +61,5 @@ export default [
|
|||
path: '/logout',
|
||||
name: 'logout',
|
||||
component: () => import('~/components/auth/Logout.vue')
|
||||
},
|
||||
] as RouteRecordRaw[]
|
||||
}
|
||||
] as RouteRecordRaw[]
|
||||
|
|
|
@ -37,5 +37,5 @@ export default [
|
|||
name: 'content.remote.index',
|
||||
component: () => import('~/views/content/remote/Home.vue')
|
||||
}]
|
||||
},
|
||||
] as RouteRecordRaw[]
|
||||
}
|
||||
] as RouteRecordRaw[]
|
||||
|
|
|
@ -104,4 +104,4 @@ export default [
|
|||
name: '404',
|
||||
component: () => import('~/components/PageNotFound.vue')
|
||||
}
|
||||
] as RouteRecordRaw[]
|
||||
] as RouteRecordRaw[]
|
||||
|
|
|
@ -178,5 +178,5 @@ export default [
|
|||
props: true
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
] as RouteRecordRaw[]
|
||||
|
|
|
@ -26,5 +26,5 @@ export default [
|
|||
name: 'settings.applications.edit',
|
||||
component: () => import('~/components/auth/ApplicationEdit.vue'),
|
||||
props: true
|
||||
},
|
||||
] as RouteRecordRaw[]
|
||||
}
|
||||
] as RouteRecordRaw[]
|
||||
|
|
|
@ -3,7 +3,7 @@ import type { RouteRecordRaw } from 'vue-router'
|
|||
import store from '~/store'
|
||||
|
||||
export default [
|
||||
{ suffix: '.full', path: '/@:username@:domain' },
|
||||
{ suffix: '.full', path: '/@:username@:domain' },
|
||||
{ suffix: '', path: '/@:username' }
|
||||
].map((route) => {
|
||||
return {
|
||||
|
@ -31,4 +31,4 @@ export default [
|
|||
}
|
||||
]
|
||||
}
|
||||
}) as RouteRecordRaw[]
|
||||
}) as RouteRecordRaw[]
|
||||
|
|
|
@ -71,7 +71,7 @@ const store: Module<State, RootState> = {
|
|||
page_size: 50,
|
||||
ordering: '-creation_date'
|
||||
}
|
||||
const promise = axios.get('favorites/tracks/all/', { params: params })
|
||||
const promise = axios.get('favorites/tracks/all/', { params })
|
||||
return promise.then((response) => {
|
||||
logger.info('Fetched a batch of ' + response.data.results.length + ' favorites')
|
||||
response.data.results.forEach((result: { track: string }) => {
|
||||
|
|
|
@ -110,7 +110,7 @@ export default createStore<RootState>({
|
|||
mbid: track.mbid,
|
||||
uploads: track.uploads,
|
||||
listen_url: track.listen_url,
|
||||
artist: artist,
|
||||
artist,
|
||||
album: {}
|
||||
}
|
||||
if (track.album) {
|
||||
|
@ -119,7 +119,7 @@ export default createStore<RootState>({
|
|||
title: track.album.title,
|
||||
mbid: track.album.mbid,
|
||||
cover: track.album.cover,
|
||||
artist: artist
|
||||
artist
|
||||
}
|
||||
}
|
||||
return data
|
||||
|
|
|
@ -60,7 +60,7 @@ const store: Module<State, RootState> = {
|
|||
commit('follows', { library: uuid, follow: null })
|
||||
}, () => {
|
||||
logger.info('Error while unsubscribing from library')
|
||||
commit('follows', { library: uuid, follow: follow })
|
||||
commit('follows', { library: uuid, follow })
|
||||
})
|
||||
}
|
||||
},
|
||||
|
|
|
@ -139,7 +139,7 @@ const store: Module<State, RootState> = {
|
|||
page_size: 100,
|
||||
ordering: '-creation_date'
|
||||
}
|
||||
promise = axios.get('moderation/content-filters/', { params: params })
|
||||
promise = axios.get('moderation/content-filters/', { params })
|
||||
}
|
||||
return promise.then((response) => {
|
||||
logger.info('Fetched a batch of ' + response.data.results.length + ' filters')
|
||||
|
|
|
@ -34,7 +34,7 @@ const store: Module<State, RootState> = {
|
|||
currentTime: 0,
|
||||
errored: false,
|
||||
bufferProgress: 0,
|
||||
looping: 0
|
||||
looping: 0
|
||||
},
|
||||
mutations: {
|
||||
reset (state) {
|
||||
|
|
|
@ -96,7 +96,7 @@ const store: Module<State, RootState> = {
|
|||
|
||||
const total = tracks.length
|
||||
tracks.forEach((track: Track, i: number) => {
|
||||
const promise = dispatch('append', { track: track, index: index })
|
||||
const promise = dispatch('append', { track, index })
|
||||
index += 1
|
||||
|
||||
if (callback && i + 1 === total) {
|
||||
|
|
|
@ -86,7 +86,7 @@ const store: Module<State, RootState> = {
|
|||
radio_type: type,
|
||||
related_object_id: objectId,
|
||||
custom_radio: customRadioId,
|
||||
config: config
|
||||
config
|
||||
}
|
||||
|
||||
if (clientOnly) {
|
||||
|
|
|
@ -3,6 +3,8 @@ import type { Store } from 'vuex'
|
|||
import type { Router } from 'vue-router'
|
||||
import type { AxiosError } from 'axios'
|
||||
import type { RootState } from '~/store'
|
||||
|
||||
// eslint-disable-next-line
|
||||
import type { ComponentPublicInstance } from '@vue/runtime-core'
|
||||
|
||||
export type FunctionRef = Element | ComponentPublicInstance | null
|
||||
|
@ -100,7 +102,6 @@ export interface Track {
|
|||
is_local: boolean
|
||||
}
|
||||
|
||||
|
||||
export interface Channel {
|
||||
id: string
|
||||
uuid: string
|
||||
|
@ -195,6 +196,7 @@ export interface Listening {
|
|||
}
|
||||
|
||||
// API stuff
|
||||
// eslint-disable-next-line
|
||||
export interface APIErrorResponse extends Record<string, APIErrorResponse | string[] | { code: string }[]> {}
|
||||
|
||||
export interface BackendError extends AxiosError {
|
||||
|
@ -360,4 +362,4 @@ export interface Note {
|
|||
author: Actor // TODO (wvffle): Check if is valid
|
||||
summary: string
|
||||
creation_date: string
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
import $ from 'jquery'
|
||||
import { tryOnMounted, useCurrentElement } from '@vueuse/core'
|
||||
|
||||
|
||||
export const getDropdown = (selector = '.ui.dropdown'): JQuery => {
|
||||
const el = useCurrentElement()
|
||||
return $(el.value).find(selector)
|
||||
|
@ -11,7 +10,7 @@ export const getDropdown = (selector = '.ui.dropdown'): JQuery => {
|
|||
|
||||
export const setupDropdown = (selector: string | HTMLElement = '.ui.dropdown') => tryOnMounted(() => {
|
||||
const el = useCurrentElement()
|
||||
const $dropdown = typeof selector === 'string'
|
||||
const $dropdown = typeof selector === 'string'
|
||||
? $(el.value).find(selector)
|
||||
: $(selector)
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ export function parseAPIErrors (responseData: APIErrorResponse, parentField?: st
|
|||
}))
|
||||
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Handle nested errors
|
||||
errors.push(...parseAPIErrors(value, fieldName))
|
||||
|
|
|
@ -286,7 +286,7 @@ export default {
|
|||
},
|
||||
fetch (params) {
|
||||
this.isLoading = true
|
||||
axios.get('federation/inbox/', { params: params }).then(response => {
|
||||
axios.get('federation/inbox/', { params }).then(response => {
|
||||
this.isLoading = false
|
||||
this.notifications = response.data
|
||||
})
|
||||
|
|
|
@ -201,9 +201,9 @@
|
|||
Description
|
||||
</translate>
|
||||
</td>
|
||||
<sanitized-html
|
||||
<sanitized-html
|
||||
tag="td"
|
||||
:html="object.artist.description.html"
|
||||
:html="object.artist.description.html"
|
||||
/>
|
||||
</tr>
|
||||
<tr v-if="object.actor.url">
|
||||
|
|
|
@ -74,7 +74,7 @@ const title = computed(() => labels.value[props.type])
|
|||
:default-query="defaultQuery"
|
||||
:ordering-config-name="null"
|
||||
/>
|
||||
<invitations-table
|
||||
<invitations-table
|
||||
v-else-if="type === 'invitations'"
|
||||
:ordering-config-name="null"
|
||||
/>
|
||||
|
@ -102,7 +102,7 @@ const title = computed(() => labels.value[props.type])
|
|||
:default-query="defaultQuery"
|
||||
:ordering-config-name="null"
|
||||
/>
|
||||
<users-table
|
||||
<users-table
|
||||
v-else-if="type === 'users'"
|
||||
:ordering-config-name="null"
|
||||
/>
|
||||
|
|
|
@ -4,7 +4,6 @@ import type { SettingsGroup as SettingsGroupType } from '~/types'
|
|||
import axios from 'axios'
|
||||
import $ from 'jquery'
|
||||
|
||||
|
||||
import SettingsGroup from '~/components/admin/SettingsGroup.vue'
|
||||
|
||||
import { useCurrentElement } from '@vueuse/core'
|
||||
|
|
|
@ -212,9 +212,9 @@
|
|||
Description
|
||||
</translate>
|
||||
</td>
|
||||
<sanitized-html
|
||||
<sanitized-html
|
||||
tag="td"
|
||||
:html="object.description.html"
|
||||
:html="object.description.html"
|
||||
/>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
|
|
@ -211,9 +211,9 @@
|
|||
Description
|
||||
</translate>
|
||||
</td>
|
||||
<sanitized-html
|
||||
<sanitized-html
|
||||
tag="td"
|
||||
:html="object.description.html"
|
||||
:html="object.description.html"
|
||||
/>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
|
|
@ -348,9 +348,9 @@ const getQuery = (field: string, value: string) => `${field}:"${value}"`
|
|||
Description
|
||||
</translate>
|
||||
</td>
|
||||
<sanitized-html
|
||||
<sanitized-html
|
||||
tag="td"
|
||||
:html="track.description.html"
|
||||
:html="track.description.html"
|
||||
/>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
|
|
@ -73,7 +73,6 @@ const fetchData = async () => {
|
|||
} else {
|
||||
await router.replace({ name: 'channels.detail', params: { id: actor.full_username } })
|
||||
}
|
||||
|
||||
}
|
||||
} catch (error) {
|
||||
// TODO (wvffle): Handle error
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import type { ImportStatus } from '~/types'
|
||||
import type { RouteWithPreferences } from '~/store/ui'
|
||||
import type { OrderingField } from '~/store/ui'
|
||||
import type { RouteWithPreferences, OrderingField } from '~/store/ui'
|
||||
import type { OrderingProps } from '~/composables/useOrdering'
|
||||
import type { SmartSearchProps } from '~/composables/useSmartSearch'
|
||||
|
||||
|
|
|
@ -34,13 +34,13 @@ const scanProgress = computed(() => Math.min(latestScan.value.processed_files *
|
|||
const scanStatus = computed(() => latestScan.value?.status ?? 'unknown')
|
||||
const canLaunchScan = computed(() => scanStatus.value !== 'pending' && scanStatus.value !== 'scanning')
|
||||
const radioPlayable = computed(() => (
|
||||
(library.value.actor.is_local || scanStatus.value === 'finished')
|
||||
&& (library.value.privacy_level === 'everyone' || library.value.follow?.approved)
|
||||
(library.value.actor.is_local || scanStatus.value === 'finished') &&
|
||||
(library.value.privacy_level === 'everyone' || library.value.follow?.approved)
|
||||
))
|
||||
|
||||
const { $pgettext } = useGettext()
|
||||
const labels = computed(() => ({
|
||||
tooltips: {
|
||||
tooltips: {
|
||||
me: $pgettext('Content/Library/Card.Help text', 'This library is private and your approval from its owner is needed to access its content'),
|
||||
everyone: $pgettext('Content/Library/Card.Help text', 'This library is public and you can access its content freely')
|
||||
}
|
||||
|
@ -364,4 +364,4 @@ watch(showScan, (shouldShow) => {
|
|||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
|
|
@ -25,10 +25,10 @@ const object = ref<Library | null>(null)
|
|||
|
||||
const isOwner = computed(() => store.state.auth.authenticated && object.value?.actor.full_username === store.state.auth.fullUsername)
|
||||
const isPlayable = computed(() => (object.value?.uploads_count ?? 0) > 0 && (
|
||||
isOwner.value
|
||||
|| object.value?.privacy_level === 'everyone'
|
||||
|| (object.value?.privacy_level === 'instance' && store.state.auth.authenticated && object.value.actor.domain === store.getters['instance/domain'])
|
||||
|| (store.getters['libraries/follow'](object.value?.uuid) || {}).approved === true
|
||||
isOwner.value ||
|
||||
object.value?.privacy_level === 'everyone' ||
|
||||
(object.value?.privacy_level === 'instance' && store.state.auth.authenticated && object.value.actor.domain === store.getters['instance/domain']) ||
|
||||
(store.getters['libraries/follow'](object.value?.uuid) || {}).approved === true
|
||||
))
|
||||
|
||||
const { $pgettext } = useGettext()
|
||||
|
|
|
@ -59,7 +59,10 @@ const updateApproved = async (follow: LibraryFollow, approved: boolean) => {
|
|||
Library contents
|
||||
</translate>
|
||||
</h2>
|
||||
<library-files-table :filters="{library: object.uuid}" :ordering-config-name="null" />
|
||||
<library-files-table
|
||||
:filters="{library: object.uuid}"
|
||||
:ordering-config-name="null"
|
||||
/>
|
||||
|
||||
<div class="ui hidden divider" />
|
||||
<h2 class="ui header">
|
||||
|
|
|
@ -44,7 +44,7 @@ const fetchData = async () => {
|
|||
try {
|
||||
const [playlistResponse, tracksResponse] = await Promise.all([
|
||||
axios.get(`playlists/${props.id}/`),
|
||||
axios.get(`playlists/${props.id}/tracks/`),
|
||||
axios.get(`playlists/${props.id}/tracks/`)
|
||||
])
|
||||
|
||||
playlist.value = playlistResponse.data
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import type { Track, Radio } from "~/types"
|
||||
import type { Track, Radio } from '~/types'
|
||||
|
||||
import axios from 'axios'
|
||||
import TrackTable from '~/components/audio/track/Table.vue'
|
||||
|
@ -35,7 +35,7 @@ const fetchData = async () => {
|
|||
const radioResponse = await axios.get(url)
|
||||
radio.value = radioResponse.data
|
||||
|
||||
const tracksResponse = await axios.get(url + 'tracks/', { params: { page: page.value }})
|
||||
const tracksResponse = await axios.get(url + 'tracks/', { params: { page: page.value } })
|
||||
totalTracks.value = tracksResponse.data.count
|
||||
tracks.value = tracksResponse.data.results
|
||||
} catch (error) {
|
||||
|
|
|
@ -2616,6 +2616,13 @@ builtin-modules@^3.1.0:
|
|||
resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6"
|
||||
integrity sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==
|
||||
|
||||
builtins@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/builtins/-/builtins-5.0.1.tgz#87f6db9ab0458be728564fa81d876d8d74552fa9"
|
||||
integrity sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==
|
||||
dependencies:
|
||||
semver "^7.0.0"
|
||||
|
||||
buntis@0.2.1:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/buntis/-/buntis-0.2.1.tgz#a043aabc7d64f2243bfaa53e34e999c2dd790e82"
|
||||
|
@ -3448,6 +3455,14 @@ eslint-plugin-es@^3.0.0:
|
|||
eslint-utils "^2.0.0"
|
||||
regexpp "^3.0.0"
|
||||
|
||||
eslint-plugin-es@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-4.1.0.tgz#f0822f0c18a535a97c3e714e89f88586a7641ec9"
|
||||
integrity sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==
|
||||
dependencies:
|
||||
eslint-utils "^2.0.0"
|
||||
regexpp "^3.0.0"
|
||||
|
||||
eslint-plugin-html@6.2.0:
|
||||
version "6.2.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-html/-/eslint-plugin-html-6.2.0.tgz#715bc00b50bbd0d996e28f953c289a5ebec69d43"
|
||||
|
@ -3474,6 +3489,20 @@ eslint-plugin-import@2.26.0:
|
|||
resolve "^1.22.0"
|
||||
tsconfig-paths "^3.14.1"
|
||||
|
||||
eslint-plugin-n@^15.2.4:
|
||||
version "15.2.4"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-n/-/eslint-plugin-n-15.2.4.tgz#d62021a0821ae650701ed459756aaf478a9b6056"
|
||||
integrity sha512-tjnVMv2fiXYMnuiIFI8QMtyUFI42SckEEWvi8h68SWGWshfqO6SSCASy24dGMGAiy7NUk6DZt90DM0iNUsmQ5w==
|
||||
dependencies:
|
||||
builtins "^5.0.1"
|
||||
eslint-plugin-es "^4.1.0"
|
||||
eslint-utils "^3.0.0"
|
||||
ignore "^5.1.1"
|
||||
is-core-module "^2.9.0"
|
||||
minimatch "^3.1.2"
|
||||
resolve "^1.10.1"
|
||||
semver "^7.3.7"
|
||||
|
||||
eslint-plugin-node@11.1.0:
|
||||
version "11.1.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz#c95544416ee4ada26740a30474eefc5402dc671d"
|
||||
|
@ -5806,7 +5835,7 @@ semver@7.0.0:
|
|||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e"
|
||||
integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==
|
||||
|
||||
semver@7.x, semver@^7.3.5, semver@^7.3.6, semver@^7.3.7:
|
||||
semver@7.x, semver@^7.0.0, semver@^7.3.5, semver@^7.3.6, semver@^7.3.7:
|
||||
version "7.3.7"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f"
|
||||
integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==
|
||||
|
|
Loading…
Reference in New Issue