Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
funkwhale
funkwhale
Commits
1d4f2e1d
Commit
1d4f2e1d
authored
Apr 21, 2022
by
Kasper Seweryn
🥞
Committed by
Kasper Seweryn
Jul 03, 2022
Browse files
Remove files commited by accident
parent
2dbd1174
Changes
2
Hide whitespace changes
Inline
Side-by-side
front/src/AppOld.vue
deleted
100644 → 0
View file @
2dbd1174
<
template
>
<div
id=
"app"
:key=
"String($store.state.instance.instanceUrl)"
:class=
"[$store.state.ui.queueFocused ? 'queue-focused' : '',
{'has-bottom-player': $store.state.queue.tracks.length > 0}]"
>
<!-- here, we display custom stylesheets, if any -->
<link
v-for=
"url in customStylesheets"
:key=
"url"
rel=
"stylesheet"
property=
"stylesheet"
:href=
"url"
>
<sidebar
:width=
"width"
@
show:set-instance-modal=
"showSetInstanceModal = !showSetInstanceModal"
@
show:shortcuts-modal=
"showShortcutsModal = !showShortcutsModal"
/>
<set-instance-modal
:show=
"showSetInstanceModal"
@
update:show=
"showSetInstanceModal = $event"
/>
<service-messages
/>
<transition
name=
"queue"
>
<queue
v-if=
"$store.state.ui.queueFocused"
@
touch-progress=
"$refs.player.setCurrentTime($event)"
/>
</transition>
<router-view
role=
"main"
:class=
"
{hidden: $store.state.ui.queueFocused}"
/>
<player
ref=
"player"
/>
<playlist-modal
v-if=
"$store.state.auth.authenticated"
/>
<channel-upload-modal
v-if=
"$store.state.auth.authenticated"
/>
<filter-modal
v-if=
"$store.state.auth.authenticated"
/>
<report-modal
/>
<shortcuts-modal
:show=
"showShortcutsModal"
@
update:show=
"showShortcutsModal = $event"
/>
<GlobalEvents
@
keydown.h.exact=
"showShortcutsModal = !showShortcutsModal"
/>
</div>
</
template
>
<
script
>
import
axios
from
'
axios
'
import
{
uniq
,
get
}
from
'
lodash-es
'
import
{
mapState
,
mapGetters
}
from
'
vuex
'
import
{
useWebSocket
,
whenever
}
from
'
@vueuse/core
'
import
GlobalEvents
from
'
@/components/utils/global-events.vue
'
import
locales
from
'
./locales
'
import
{
getClientOnlyRadio
}
from
'
@/radios
'
import
Player
from
'
@/components/audio/Player.vue
'
import
Queue
from
'
@/components/Queue.vue
'
import
PlaylistModal
from
'
@/components/playlists/PlaylistModal.vue
'
import
ChannelUploadModal
from
'
@/components/channels/UploadModal.vue
'
import
Sidebar
from
'
@/components/Sidebar.vue
'
import
ServiceMessages
from
'
@/components/ServiceMessages.vue
'
import
SetInstanceModal
from
'
@/components/SetInstanceModal.vue
'
import
ShortcutsModal
from
'
@/components/ShortcutsModal.vue
'
import
FilterModal
from
'
@/components/moderation/FilterModal.vue
'
import
ReportModal
from
'
@/components/moderation/ReportModal.vue
'
import
{
watch
,
watchEffect
}
from
'
@vue/composition-api
'
export
default
{
name
:
'
App
'
,
components
:
{
Player
,
Queue
,
PlaylistModal
,
ChannelUploadModal
,
Sidebar
,
ServiceMessages
,
SetInstanceModal
,
ShortcutsModal
,
FilterModal
,
ReportModal
,
GlobalEvents
},
setup
(
props
,
{
root
})
{
const
store
=
root
.
$store
const
url
=
store
.
getters
[
'
instance/absoluteUrl
'
](
'
api/v1/activity
'
)
.
replace
(
/^http/
,
'
ws
'
)
const
{
data
,
status
,
open
,
close
}
=
useWebSocket
(
url
,
{
autoReconnect
:
true
,
immediate
:
false
})
watch
(()
=>
store
.
state
.
auth
.
authenticated
,
(
authenticated
)
=>
{
if
(
authenticated
)
return
open
()
close
()
})
whenever
(
data
,
()
=>
{
store
.
dispatch
(
'
ui/websocketEvent
'
,
JSON
.
parse
(
data
.
value
))
})
watchEffect
(()
=>
{
console
.
log
(
'
Websocket status:
'
,
status
.
value
)
})
},
data
()
{
return
{
instanceUrl
:
null
,
showShortcutsModal
:
false
,
showSetInstanceModal
:
false
,
initialTitle
:
document
.
title
,
width
:
window
.
innerWidth
}
},
computed
:
{
...
mapState
({
messages
:
state
=>
state
.
ui
.
messages
,
nodeinfo
:
state
=>
state
.
instance
.
nodeinfo
,
playing
:
state
=>
state
.
player
.
playing
,
bufferProgress
:
state
=>
state
.
player
.
bufferProgress
,
isLoadingAudio
:
state
=>
state
.
player
.
isLoadingAudio
,
serviceWorker
:
state
=>
state
.
ui
.
serviceWorker
}),
...
mapGetters
({
hasNext
:
'
queue/hasNext
'
,
currentTrack
:
'
queue/currentTrack
'
,
progress
:
'
player/progress
'
}),
labels
()
{
const
play
=
this
.
$pgettext
(
'
Sidebar/Player/Icon.Tooltip/Verb
'
,
'
Play track
'
)
const
pause
=
this
.
$pgettext
(
'
Sidebar/Player/Icon.Tooltip/Verb
'
,
'
Pause track
'
)
const
next
=
this
.
$pgettext
(
'
Sidebar/Player/Icon.Tooltip
'
,
'
Next track
'
)
const
expandQueue
=
this
.
$pgettext
(
'
Sidebar/Player/Icon.Tooltip/Verb
'
,
'
Expand queue
'
)
return
{
play
,
pause
,
next
,
expandQueue
}
},
suggestedInstances
()
{
const
instances
=
this
.
$store
.
state
.
instance
.
knownInstances
.
slice
(
0
)
if
(
this
.
$store
.
state
.
instance
.
frontSettings
.
defaultServerUrl
)
{
let
serverUrl
=
this
.
$store
.
state
.
instance
.
frontSettings
.
defaultServerUrl
if
(
!
serverUrl
.
endsWith
(
'
/
'
))
{
serverUrl
=
serverUrl
+
'
/
'
}
instances
.
push
(
serverUrl
)
}
instances
.
push
(
this
.
$store
.
getters
[
'
instance/defaultUrl
'
](),
'
https://demo.funkwhale.audio/
'
)
return
uniq
(
instances
.
filter
((
e
)
=>
{
return
e
}))
},
version
()
{
if
(
!
this
.
nodeinfo
)
{
return
null
}
return
get
(
this
.
nodeinfo
,
'
software.version
'
)
},
customStylesheets
()
{
if
(
this
.
$store
.
state
.
instance
.
frontSettings
)
{
return
this
.
$store
.
state
.
instance
.
frontSettings
.
additionalStylesheets
||
[]
}
return
null
},
matchDarkColorScheme
()
{
if
(
window
.
matchMedia
)
{
return
window
.
matchMedia
(
'
(prefers-color-scheme: dark)
'
)
}
return
null
}
},
watch
:
{
'
$store.state.instance.instanceUrl
'
(
v
)
{
this
.
$store
.
dispatch
(
'
instance/fetchSettings
'
)
this
.
fetchNodeInfo
()
},
'
$store.state.ui.theme
'
:
{
immediate
:
true
,
handler
(
newValue
)
{
const
matchesDark
=
this
.
matchDarkColorScheme
if
(
matchesDark
)
{
if
(
newValue
===
'
system
'
)
{
newValue
=
matchesDark
.
matches
?
'
dark
'
:
'
light
'
matchesDark
.
addEventListener
(
'
change
'
,
this
.
handleThemeChange
)
}
else
{
matchesDark
.
removeEventListener
(
'
change
'
,
this
.
handleThemeChange
)
}
}
else
{
if
(
newValue
===
'
system
'
)
{
newValue
=
'
light
'
}
}
this
.
setTheme
(
newValue
)
}
},
'
$store.state.ui.currentLanguage
'
:
{
immediate
:
true
,
handler
(
newValue
)
{
const
self
=
this
const
htmlLocale
=
newValue
.
toLowerCase
().
replace
(
'
_
'
,
'
-
'
)
document
.
documentElement
.
setAttribute
(
'
lang
'
,
htmlLocale
)
if
(
newValue
===
'
en_US
'
)
{
self
.
$language
.
current
=
'
noop
'
self
.
$language
.
current
=
newValue
return
self
.
$store
.
commit
(
'
ui/momentLocale
'
,
'
en
'
)
}
}
},
currentTrack
:
{
immediate
:
true
,
handler
(
newValue
)
{
this
.
updateDocumentTitle
()
}
},
'
$store.state.ui.pageTitle
'
:
{
immediate
:
true
,
handler
(
newValue
)
{
this
.
updateDocumentTitle
()
}
},
'
serviceWorker.updateAvailable
'
:
{
handler
(
v
)
{
if
(
!
v
)
{
return
}
const
self
=
this
this
.
$store
.
commit
(
'
ui/addMessage
'
,
{
content
:
this
.
$pgettext
(
'
App/Message/Paragraph
'
,
'
A new version of the app is available.
'
),
date
:
new
Date
(),
key
:
'
refreshApp
'
,
displayTime
:
0
,
classActions
:
'
bottom attached opaque
'
,
actions
:
[
{
text
:
this
.
$pgettext
(
'
App/Message/Paragraph
'
,
'
Update
'
),
class
:
'
primary
'
,
click
:
function
()
{
self
.
updateApp
()
}
},
{
text
:
this
.
$pgettext
(
'
App/Message/Paragraph
'
,
'
Later
'
),
class
:
'
basic
'
}
]
})
},
immediate
:
true
}
},
async
created
()
{
if
(
navigator
.
serviceWorker
)
{
navigator
.
serviceWorker
.
addEventListener
(
'
controllerchange
'
,
()
=>
{
if
(
this
.
serviceWorker
.
refreshing
)
return
this
.
$store
.
commit
(
'
ui/serviceWorker
'
,
{
refreshing
:
true
})
window
.
location
.
reload
()
}
)
}
window
.
addEventListener
(
'
resize
'
,
this
.
handleResize
)
this
.
handleResize
()
const
self
=
this
if
(
!
this
.
$store
.
state
.
ui
.
selectedLanguage
)
{
this
.
autodetectLanguage
()
}
setInterval
(()
=>
{
// used to redraw ago dates every minute
self
.
$store
.
commit
(
'
ui/computeLastDate
'
)
},
1000
*
60
)
const
urlParams
=
new
URLSearchParams
(
window
.
location
.
search
)
const
serverUrl
=
urlParams
.
get
(
'
_server
'
)
if
(
serverUrl
)
{
this
.
$store
.
commit
(
'
instance/instanceUrl
'
,
serverUrl
)
}
const
url
=
urlParams
.
get
(
'
_url
'
)
if
(
url
)
{
await
this
.
$router
.
replace
(
url
)
}
else
if
(
!
this
.
$store
.
state
.
instance
.
instanceUrl
)
{
// we have several way to guess the API server url. By order of precedence:
// 1. use the url provided in settings.json, if any
// 2. use the url specified when building via VUE_APP_INSTANCE_URL
// 3. use the current url
const
defaultInstanceUrl
=
this
.
$store
.
state
.
instance
.
frontSettings
.
defaultServerUrl
||
import
.
meta
.
env
.
VUE_APP_INSTANCE_URL
||
this
.
$store
.
getters
[
'
instance/defaultUrl
'
]()
this
.
$store
.
commit
(
'
instance/instanceUrl
'
,
defaultInstanceUrl
)
}
else
{
// needed to trigger initialization of axios / service worker
this
.
$store
.
commit
(
'
instance/instanceUrl
'
,
this
.
$store
.
state
.
instance
.
instanceUrl
)
}
await
this
.
fetchNodeInfo
()
this
.
$store
.
dispatch
(
'
instance/fetchSettings
'
)
this
.
$store
.
commit
(
'
ui/addWebsocketEventHandler
'
,
{
eventName
:
'
inbox.item_added
'
,
id
:
'
sidebarCount
'
,
handler
:
this
.
incrementNotificationCountInSidebar
})
this
.
$store
.
commit
(
'
ui/addWebsocketEventHandler
'
,
{
eventName
:
'
mutation.created
'
,
id
:
'
sidebarReviewEditCount
'
,
handler
:
this
.
incrementReviewEditCountInSidebar
})
this
.
$store
.
commit
(
'
ui/addWebsocketEventHandler
'
,
{
eventName
:
'
mutation.updated
'
,
id
:
'
sidebarReviewEditCount
'
,
handler
:
this
.
incrementReviewEditCountInSidebar
})
this
.
$store
.
commit
(
'
ui/addWebsocketEventHandler
'
,
{
eventName
:
'
report.created
'
,
id
:
'
sidebarPendingReviewReportCount
'
,
handler
:
this
.
incrementPendingReviewReportsCountInSidebar
})
this
.
$store
.
commit
(
'
ui/addWebsocketEventHandler
'
,
{
eventName
:
'
user_request.created
'
,
id
:
'
sidebarPendingReviewRequestCount
'
,
handler
:
this
.
incrementPendingReviewRequestsCountInSidebar
})
this
.
$store
.
commit
(
'
ui/addWebsocketEventHandler
'
,
{
eventName
:
'
Listen
'
,
id
:
'
handleListen
'
,
handler
:
this
.
handleListen
})
},
mounted
()
{
const
self
=
this
// slight hack to allow use to have internal links in
<
translate
>
tags
// while preserving router behaviour
document
.
documentElement
.
addEventListener
(
'
click
'
,
function
(
event
)
{
if
(
!
event
.
target
.
matches
(
'
a.internal
'
))
return
self
.
$router
.
push
(
event
.
target
.
getAttribute
(
'
href
'
))
event
.
preventDefault
()
},
false
)
this
.
$nextTick
(()
=>
{
document
.
getElementById
(
'
fake-content
'
).
classList
.
add
(
'
loaded
'
)
})
},
destroyed
()
{
this
.
$store
.
commit
(
'
ui/removeWebsocketEventHandler
'
,
{
eventName
:
'
inbox.item_added
'
,
id
:
'
sidebarCount
'
})
this
.
$store
.
commit
(
'
ui/removeWebsocketEventHandler
'
,
{
eventName
:
'
mutation.created
'
,
id
:
'
sidebarReviewEditCount
'
})
this
.
$store
.
commit
(
'
ui/removeWebsocketEventHandler
'
,
{
eventName
:
'
mutation.updated
'
,
id
:
'
sidebarReviewEditCount
'
})
this
.
$store
.
commit
(
'
ui/removeWebsocketEventHandler
'
,
{
eventName
:
'
mutation.updated
'
,
id
:
'
sidebarPendingReviewReportCount
'
})
this
.
$store
.
commit
(
'
ui/removeWebsocketEventHandler
'
,
{
eventName
:
'
user_request.created
'
,
id
:
'
sidebarPendingReviewRequestCount
'
})
this
.
$store
.
commit
(
'
ui/removeWebsocketEventHandler
'
,
{
eventName
:
'
Listen
'
,
id
:
'
handleListen
'
})
},
methods
:
{
incrementNotificationCountInSidebar
(
event
)
{
this
.
$store
.
commit
(
'
ui/incrementNotifications
'
,
{
type
:
'
inbox
'
,
count
:
1
})
},
incrementReviewEditCountInSidebar
(
event
)
{
this
.
$store
.
commit
(
'
ui/incrementNotifications
'
,
{
type
:
'
pendingReviewEdits
'
,
value
:
event
.
pending_review_count
})
},
incrementPendingReviewReportsCountInSidebar
(
event
)
{
this
.
$store
.
commit
(
'
ui/incrementNotifications
'
,
{
type
:
'
pendingReviewReports
'
,
value
:
event
.
unresolved_count
})
},
incrementPendingReviewRequestsCountInSidebar
(
event
)
{
this
.
$store
.
commit
(
'
ui/incrementNotifications
'
,
{
type
:
'
pendingReviewRequests
'
,
value
:
event
.
pending_count
})
},
handleListen
(
event
)
{
if
(
this
.
$store
.
state
.
radios
.
current
&&
this
.
$store
.
state
.
radios
.
running
)
{
const
current
=
this
.
$store
.
state
.
radios
.
current
if
(
current
.
clientOnly
&&
current
.
type
===
'
account
'
)
{
getClientOnlyRadio
(
current
).
handleListen
(
current
,
event
,
this
.
$store
)
}
}
},
async
fetchNodeInfo
()
{
const
response
=
await
axios
.
get
(
'
instance/nodeinfo/2.0/
'
)
this
.
$store
.
commit
(
'
instance/nodeinfo
'
,
response
.
data
)
},
autodetectLanguage
()
{
const
userLanguage
=
navigator
.
language
||
navigator
.
userLanguage
const
available
=
locales
.
locales
.
map
(
e
=>
{
return
e
.
code
})
let
candidate
const
matching
=
available
.
filter
((
a
)
=>
{
return
userLanguage
.
replace
(
'
-
'
,
'
_
'
)
===
a
})
const
almostMatching
=
available
.
filter
((
a
)
=>
{
return
userLanguage
.
replace
(
'
-
'
,
'
_
'
).
split
(
'
_
'
)[
0
]
===
a
.
split
(
'
_
'
)[
0
]
})
if
(
matching
.
length
>
0
)
{
candidate
=
matching
[
0
]
}
else
if
(
almostMatching
.
length
>
0
)
{
candidate
=
almostMatching
[
0
]
}
else
{
return
}
this
.
$store
.
commit
(
'
ui/currentLanguage
'
,
candidate
)
},
getTrackInformationText
(
track
)
{
const
trackTitle
=
track
.
title
const
albumArtist
=
(
track
.
album
)
?
track
.
album
.
artist
.
name
:
null
const
artistName
=
(
(
track
.
artist
)
?
track
.
artist
.
name
:
albumArtist
)
const
text
=
`♫
${
trackTitle
}
–
${
artistName
}
♫`
return
text
},
updateDocumentTitle
()
{
const
parts
=
[]
const
currentTrackPart
=
(
(
this
.
currentTrack
)
?
this
.
getTrackInformationText
(
this
.
currentTrack
)
:
null
)
if
(
currentTrackPart
)
{
parts
.
push
(
currentTrackPart
)
}
if
(
this
.
$store
.
state
.
ui
.
pageTitle
)
{
parts
.
push
(
this
.
$store
.
state
.
ui
.
pageTitle
)
}
parts
.
push
(
this
.
initialTitle
||
'
Funkwhale
'
)
document
.
title
=
parts
.
join
(
'
–
'
)
},
updateApp
()
{
this
.
$store
.
commit
(
'
ui/serviceWorker
'
,
{
updateAvailable
:
false
})
if
(
!
this
.
serviceWorker
.
registration
||
!
this
.
serviceWorker
.
registration
.
waiting
)
{
return
}
this
.
serviceWorker
.
registration
.
waiting
.
postMessage
({
command
:
'
skipWaiting
'
})
},
handleResize
()
{
this
.
width
=
window
.
innerWidth
},
handleThemeChange
(
event
)
{
this
.
setTheme
(
event
.
matches
?
'
dark
'
:
'
light
'
)
},
setTheme
(
theme
)
{
const
oldTheme
=
(
theme
===
'
light
'
)
?
'
dark
'
:
'
light
'
document
.
body
.
classList
.
remove
(
`theme-
${
oldTheme
}
`
)
document
.
body
.
classList
.
add
(
`theme-
${
theme
}
`
)
}
}
}
</
script
>
<
style
lang=
"scss"
>
@import
"style/_main"
;
</
style
>
front/src/components.d.ts
deleted
100644 → 0
View file @
2dbd1174
// generated by unplugin-vue-components
// We suggest you to commit this file into source control
// Read more: https://github.com/vuejs/vue-next/pull/3399
declare
module
'
@vue/runtime-core
'
{
export
interface
GlobalComponents
{
About
:
typeof
import
(
'
./components/About.vue
'
)[
'
default
'
]
AboutPod
:
typeof
import
(
'
./components/AboutPod.vue
'
)[
'
default
'
]
AccountsTable
:
typeof
import
(
'
./components/manage/moderation/AccountsTable.vue
'
)[
'
default
'
]
ActionFeedback
:
typeof
import
(
'
./components/common/ActionFeedback.vue
'
)[
'
default
'
]
ActionTable
:
typeof
import
(
'
./components/common/ActionTable.vue
'
)[
'
default
'
]
ActorAvatar
:
typeof
import
(
'
./components/common/ActorAvatar.vue
'
)[
'
default
'
]
ActorLink
:
typeof
import
(
'
./components/common/ActorLink.vue
'
)[
'
default
'
]
AjaxButton
:
typeof
import
(
'
./components/common/AjaxButton.vue
'
)[
'
default
'
]
AlbumBase
:
typeof
import
(
'
./components/library/AlbumBase.vue
'
)[
'
default
'
]
AlbumDetail
:
typeof
import
(
'
./components/library/AlbumDetail.vue
'
)[
'
default
'
]
AlbumDropdown
:
typeof
import
(
'
./components/library/AlbumDropdown.vue
'
)[
'
default
'
]
AlbumEdit
:
typeof
import
(
'
./components/library/AlbumEdit.vue
'
)[
'
default
'
]
AlbumForm
:
typeof
import
(
'
./components/channels/AlbumForm.vue
'
)[
'
default
'
]
AlbumModal
:
typeof
import
(
'
./components/channels/AlbumModal.vue
'
)[
'
default
'
]
Albums
:
typeof
import
(
'
./components/library/Albums.vue
'
)[
'
default
'
]
AlbumSelect
:
typeof
import
(
'
./components/channels/AlbumSelect.vue
'
)[
'
default
'
]
AlbumsTable
:
typeof
import
(
'
./components/manage/library/AlbumsTable.vue
'
)[
'
default
'
]
ApplicationEdit
:
typeof
import
(
'
./components/auth/ApplicationEdit.vue
'
)[
'
default
'
]
ApplicationForm
:
typeof
import
(
'
./components/auth/ApplicationForm.vue
'
)[
'
default
'
]
ApplicationNew
:
typeof
import
(
'
./components/auth/ApplicationNew.vue
'
)[
'
default
'
]
ArtistBase
:
typeof
import
(
'
./components/library/ArtistBase.vue
'
)[
'
default
'
]
ArtistDetail
:
typeof
import
(
'
./components/library/ArtistDetail.vue
'
)[
'
default
'
]
ArtistEdit
:
typeof
import
(
'
./components/library/ArtistEdit.vue
'
)[
'
default
'
]
ArtistLabel
:
typeof
import
(
'
./components/audio/ArtistLabel.vue
'
)[
'
default
'
]
Artists
:
typeof
import
(
'
./components/library/Artists.vue
'
)[
'
default
'
]
ArtistsTable
:
typeof
import
(
'
./components/manage/library/ArtistsTable.vue
'
)[
'
default
'
]
AttachmentInput
:
typeof
import
(
'
./components/common/AttachmentInput.vue
'
)[
'
default
'
]
Authorize
:
typeof
import
(
'
./components/auth/Authorize.vue
'
)[
'
default
'
]
Builder
:
typeof
import
(
'
./components/library/radios/Builder.vue
'
)[
'
default
'
]
Button
:
typeof
import
(
'
./components/radios/Button.vue
'
)[
'
default
'
]
Card
:
typeof
import
(
'
./components/playlists/Card.vue
'
)[
'
default
'
]
CardList
:
typeof
import
(
'
./components/playlists/CardList.vue
'
)[
'
default
'
]
ChannelCard
:
typeof
import
(
'
./components/audio/ChannelCard.vue
'
)[
'
default
'
]
ChannelEntries
:
typeof
import
(
'
./components/audio/ChannelEntries.vue
'
)[
'
default
'
]
ChannelEntryCard
:
typeof
import
(
'
./components/audio/ChannelEntryCard.vue
'
)[
'
default
'
]
ChannelForm
:
typeof
import
(
'
./components/audio/ChannelForm.vue
'
)[
'
default
'
]
ChannelSerieCard
:
typeof
import
(
'
./components/audio/ChannelSerieCard.vue
'
)[
'
default
'
]
ChannelSeries
:
typeof
import
(
'
./components/audio/ChannelSeries.vue
'
)[
'
default
'
]
ChannelsTable
:
typeof
import
(
'
./components/manage/ChannelsTable.vue
'
)[
'
default
'
]
ChannelsWidget
:
typeof
import
(
'
./components/audio/ChannelsWidget.vue
'
)[
'
default
'
]
CollapseLink
:
typeof
import
(
'
./components/common/CollapseLink.vue
'
)[
'
default
'
]
ContentForm
:
typeof
import
(
'
./components/common/ContentForm.vue
'
)[
'
default
'
]
CopyInput
:
typeof
import
(
'
./components/common/CopyInput.vue
'
)[
'
default
'
]
DangerousButton
:
typeof
import
(
'
./components/common/DangerousButton.vue
'
)[
'
default
'
]
DomainsTable
:
typeof
import
(
'
./components/manage/moderation/DomainsTable.vue
'
)[
'
default
'
]
Duration
:
typeof
import
(
'
./components/common/Duration.vue
'
)[
'
default
'
]
EditCard
:
typeof
import
(
'
./components/library/EditCard.vue
'
)[
'
default
'
]
EditDetail
:
typeof
import
(
'
./components/library/EditDetail.vue
'
)[
'
default
'
]
EditForm
:
typeof
import
(
'
./components/library/EditForm.vue
'
)[
'
default
'
]
EditList
:
typeof
import
(
'
./components/library/EditList.vue
'
)[
'
default
'
]
Editor
:
typeof
import
(
'
./components/playlists/Editor.vue
'
)[
'
default
'
]
EditsCardList
:
typeof
import
(
'
./components/manage/library/EditsCardList.vue
'
)[
'
default
'
]
EmbedWizard
:
typeof
import
(
'
./components/audio/EmbedWizard.vue
'
)[
'
default
'
]
EmptyState
:
typeof
import
(
'
./components/common/EmptyState.vue
'
)[
'
default
'
]
ExpandableDiv
:
typeof
import
(
'
./components/common/ExpandableDiv.vue
'
)[
'
default
'
]
FetchButton
:
typeof
import
(
'
./components/federation/FetchButton.vue
'
)[
'
default
'
]
FileUpload
:
typeof
import
(
'
./components/library/FileUpload.vue
'
)[
'
default
'
]
FileUploadWidget
:
typeof
import
(
'
./components/library/FileUploadWidget.vue
'
)[
'
default
'
]
Filter
:
typeof
import
(
'
./components/library/radios/Filter.vue
'
)[
'
default
'
]
FilterModal
:
typeof
import
(
'
./components/moderation/FilterModal.vue
'
)[
'
default
'
]
Footer
:
typeof
import
(
'
./components/Footer.vue
'
)[
'
default
'
]
Form
:
typeof
import
(
'
./components/playlists/Form.vue
'
)[
'
default
'
]
FsBrowser
:
typeof
import
(
'
./components/library/FsBrowser.vue
'
)[
'
default
'
]
FsLogs
:
typeof
import
(
'
./components/library/FsLogs.vue
'
)[
'
default
'
]
GlobalEvents
:
typeof
import
(
'
./components/utils/global-events.vue
'
)[
'
default
'
]
Home
:
typeof
import
(
'
./components/Home.vue
'
)[
'
default
'
]
HumanDate
:
typeof
import
(
'
./components/common/HumanDate.vue
'
)[
'
default
'
]
HumanDuration
:
typeof
import
(
'
./components/common/HumanDuration.vue
'
)[
'
default
'
]
ImportStatusModal
:
typeof
import
(
'
./components/library/ImportStatusModal.vue
'
)[
'
default
'
]
InlineSearchBar
:
typeof
import
(
'
./components/common/InlineSearchBar.vue
'
)[
'
default
'
]
InstancePolicyCard
:
typeof
import
(
'
./components/manage/moderation/InstancePolicyCard.vue
'
)[
'
default
'
]
InstancePolicyForm
:
typeof
import
(
'
./components/manage/moderation/InstancePolicyForm.vue
'
)[
'
default
'
]
InstancePolicyModal
:
typeof
import
(
'
./components/manage/moderation/InstancePolicyModal.vue
'
)[
'
default
'
]
InvitationForm
:
typeof
import
(
'
./components/manage/users/InvitationForm.vue
'
)[
'
default
'
]
InvitationsTable
:
typeof
import
(
'
./components/manage/users/InvitationsTable.vue
'
)[
'
default
'
]
LibrariesTable
:
typeof
import
(
'
./components/manage/library/LibrariesTable.vue
'
)[
'
default
'
]
Library
:
typeof
import
(
'
./components/library/Library.vue
'
)[
'
default
'
]
LibraryFollowButton
:
typeof
import
(
'
./components/audio/LibraryFollowButton.vue
'
)[
'
default
'
]
LibraryWidget
:
typeof
import
(
'
./components/federation/LibraryWidget.vue
'
)[
'
default
'
]
LicenseSelect
:
typeof
import
(
'
./components/channels/LicenseSelect.vue
'
)[
'
default
'
]
List
:
typeof
import
(
'
./components/favorites/List.vue
'
)[
'
default
'
]
LoginForm
:
typeof
import
(
'
./components/auth/LoginForm.vue
'
)[
'
default
'
]
LoginModal
:
typeof
import
(
'
./components/common/LoginModal.vue
'
)[
'
default
'
]
Logo
:
typeof
import
(
'
./components/Logo.vue
'
)[
'
default
'
]
LogoText
:
typeof
import
(
'
./components/LogoText.vue
'
)[
'
default
'
]
Logout
:
typeof
import
(
'
./components/auth/Logout.vue
'
)[
'
default
'
]
Message
:
typeof
import
(
'
./components/common/Message.vue
'
)[
'
default
'
]
MobileRow
:
typeof
import
(
'
./components/audio/podcast/MobileRow.vue
'
)[
'
default
'
]
Modal
:
typeof
import
(
'
./components/semantic/Modal.vue
'
)[
'
default
'
]
NoteForm
:
typeof
import
(
'
./components/manage/moderation/NoteForm.vue
'
)[
'
default
'
]
NotesThread
:
typeof
import
(
'
./components/manage/moderation/NotesThread.vue
'
)[
'
default
'
]
NotificationRow
:
typeof
import
(
'
./components/notifications/NotificationRow.vue
'
)[
'
default
'
]
Ordering
:
typeof
import
(
'
./components/mixins/Ordering.vue
'
)[
'
default
'
]
PageNotFound
:
typeof
import
(
'
./components/PageNotFound.vue
'
)[
'
default
'
]
Pagination
:
typeof
import
(
'
./components/Pagination.vue
'
)[
'
default
'
]
PasswordInput
:
typeof
import
(
'
./components/forms/PasswordInput.vue
'
)[
'
default
'
]
PlayButton
:
typeof
import
(
'
./components/audio/PlayButton.vue
'
)[
'
default
'
]
Player
:
typeof
import
(
'
./components/audio/Player.vue
'
)[
'
default
'
]
PlayIndicator
:
typeof
import
(
'
./components/audio/track/PlayIndicator.vue
'
)[
'
default
'
]
PlaylistModal
:
typeof
import
(
'
./components/playlists/PlaylistModal.vue
'
)[
'
default
'
]
PlayOptions
:
typeof
import
(
'
./components/mixins/PlayOptions.vue
'
)[
'
default
'
]
Plugin
:
typeof
import
(
'
./components/auth/Plugin.vue
'
)[
'
default
'
]
Podcasts
:
typeof
import
(
'
./components/library/Podcasts.vue
'
)[
'
default
'
]
Queue
:
typeof
import
(
'
./components/Queue.vue
'
)[
'
default
'
]
Radios
:
typeof
import
(
'
./components/library/Radios.vue
'
)[
'
default
'
]
RemoteSearchForm
:
typeof
import
(
'
./components/RemoteSearchForm.vue
'
)[
'
default
'
]
RenderedDescription
:
typeof
import
(
'
./components/common/RenderedDescription.vue
'
)[
'
default
'
]
Report
:
typeof
import
(
'
./components/mixins/Report.vue
'
)[
'
default
'
]
ReportCard
:
typeof
import
(
'
./components/manage/moderation/ReportCard.vue
'
)[
'
default
'
]
ReportCategoryDropdown
:
typeof
import
(
'
./components/moderation/ReportCategoryDropdown.vue
'
)[
'
default
'
]
ReportModal
:
typeof
import
(
'
./components/moderation/ReportModal.vue
'
)[
'
default
'
]
RouterLink
:
typeof
import
(
'
vue-router
'
)[
'
RouterLink
'
]
RouterView
:
typeof
import
(
'
vue-router
'
)[
'
RouterView
'
]
Row
:
typeof
import
(
'
./components/audio/podcast/Row.vue
'
)[
'
default
'
]
Search
:
typeof
import
(
'
./components/audio/Search.vue
'
)[
'
default
'
]
SearchBar
:
typeof
import
(
'
./components/audio/SearchBar.vue
'
)[
'
default
'
]
ServiceMessages
:
typeof
import
(
'
./components/ServiceMessages.vue
'
)[
'
default
'
]
SetInstanceModal
:
typeof
import
(
'
./components/SetInstanceModal.vue
'
)[
'
default
'
]
Settings
:
typeof
import
(
'
./components/auth/Settings.vue
'
)[
'
default
'
]
SettingsGroup
:
typeof
import
(
'
./components/admin/SettingsGroup.vue
'
)[
'
default
'
]
ShortcutsModal
:
typeof
import
(
'
./components/ShortcutsModal.vue
'
)[
'
default
'
]
Sidebar
:
typeof
import
(
'
./components/Sidebar.vue
'
)[
'
default
'
]