Skip to content
Snippets Groups Projects
Commit cf5e2324 authored by Konrad Mohrfeldt's avatar Konrad Mohrfeldt :koala:
Browse files

feat: add m3u playlist entry type

refs #291
parent 90d23f68
No related branches found
No related tags found
No related merge requests found
Pipeline #8118 passed
<template>
<AEditDialog
ref="dialog"
:title="t('playlist.editor.addM3uDialog.title')"
:save-label="t('playlist.editor.addM3uDialog.saveLabel')"
:can-save="canSave"
:save="() => emit('save', url)"
class="md:tw-w-[600px]"
>
<FormTable>
<FormGroup v-slot="attrs" :label="t('file.name')" center>
<input v-bind="attrs" v-model="name" type="text" />
</FormGroup>
</FormTable>
</AEditDialog>
</template>
<script setup lang="ts">
import { computed, onMounted, ref } from 'vue'
import { useI18n } from '@/i18n'
import FormGroup from '@/components/generic/FormGroup.vue'
import FormTable from '@/components/generic/FormTable.vue'
import AEditDialog from '@/components/generic/AEditDialog.vue'
const emit = defineEmits<{
save: [string]
}>()
const { t } = useI18n()
const dialog = ref()
const name = ref('')
const url = computed(() => 'm3u://' + name.value.trim().replace(/^m3u:\/\//i, ''))
const canSave = computed(() => /\.m3u$/i.test(name.value))
onMounted(() => dialog.value.open())
</script>
...@@ -132,6 +132,12 @@ ...@@ -132,6 +132,12 @@
{{ t('playlist.editor.control.addInput') }} {{ t('playlist.editor.control.addInput') }}
</button> </button>
</APermissionGuard> </APermissionGuard>
<APermissionGuard show-permissions="program.add__m3ufile">
<button type="button" class="btn btn-default" @click="addM3utoPlaylist">
<icon-ph-playlist-light class="tw-flex-none" />
{{ t('playlist.editor.control.addM3u') }}
</button>
</APermissionGuard>
</div> </div>
</div> </div>
</fieldset> </fieldset>
...@@ -154,6 +160,12 @@ ...@@ -154,6 +160,12 @@
<AInputUrlDialog @save="resolve($event)" @close="resolve(null)" /> <AInputUrlDialog @save="resolve($event)" @close="resolve(null)" />
</GetInputUrl> </GetInputUrl>
</APermissionGuard> </APermissionGuard>
<APermissionGuard show-permissions="programm.add__m3ufile">
<GetM3uUrl v-slot="{ resolve }">
<AM3uUrlDialog @save="resolve($event)" @close="resolve(null)" />
</GetM3uUrl>
</APermissionGuard>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
...@@ -170,6 +182,7 @@ import { ensureError, getFilenameFromURL, useAsyncFunction } from '@/util' ...@@ -170,6 +182,7 @@ import { ensureError, getFilenameFromURL, useAsyncFunction } from '@/util'
import AStreamURLDialog from '@/components/playlist/AStreamURLDialog.vue' import AStreamURLDialog from '@/components/playlist/AStreamURLDialog.vue'
import AFileUrlDialog from '@/components/playlist/AFileUrlDialog.vue' import AFileUrlDialog from '@/components/playlist/AFileUrlDialog.vue'
import AInputUrlDialog from '@/components/playlist/AInputUrlDialog.vue' import AInputUrlDialog from '@/components/playlist/AInputUrlDialog.vue'
import AM3uUrlDialog from '@/components/playlist/AM3uUrlDialog.vue'
import Loading from '@/components/generic/Loading.vue' import Loading from '@/components/generic/Loading.vue'
import AUploadProgress from '@/components/playlist/AUploadProgress.vue' import AUploadProgress from '@/components/playlist/AUploadProgress.vue'
import SaveIndicator from '@/components/generic/SaveIndicator.vue' import SaveIndicator from '@/components/generic/SaveIndicator.vue'
...@@ -201,6 +214,7 @@ const playlistStore = usePlaylistStore() ...@@ -201,6 +214,7 @@ const playlistStore = usePlaylistStore()
const GetStreamUrl = createTemplatePromise<string | null>() const GetStreamUrl = createTemplatePromise<string | null>()
const GetFileImportUrl = createTemplatePromise<string | null>() const GetFileImportUrl = createTemplatePromise<string | null>()
const GetInputUrl = createTemplatePromise<string | null>() const GetInputUrl = createTemplatePromise<string | null>()
const GetM3uUrl = createTemplatePromise<string | null>()
const entries = useCopy(() => props.playlist?.entries ?? [], { const entries = useCopy(() => props.playlist?.entries ?? [], {
save: () => updatePlaylistEntries(), save: () => updatePlaylistEntries(),
...@@ -324,6 +338,12 @@ async function addInputToPlaylist() { ...@@ -324,6 +338,12 @@ async function addInputToPlaylist() {
await updatePlaylistEntries({ uri: inputUrl }) await updatePlaylistEntries({ uri: inputUrl })
} }
async function addM3utoPlaylist() {
const m3uUrl = await GetM3uUrl.start()
if (!m3uUrl) return
await updatePlaylistEntries({ uri: m3uUrl })
}
const { fn: updatePlaylistEntries, isProcessing: isUpdatingPlaylist } = useAsyncFunction( const { fn: updatePlaylistEntries, isProcessing: isUpdatingPlaylist } = useAsyncFunction(
async function (...newEntries: Partial<PlaylistEntry>[]) { async function (...newEntries: Partial<PlaylistEntry>[]) {
try { try {
......
...@@ -44,6 +44,12 @@ ...@@ -44,6 +44,12 @@
{{ entry.uri }} {{ entry.uri }}
</span> </span>
</template> </template>
<template v-else-if="type === 'm3u'">
<icon-ph-playlist-light class="tw-flex-none" />
<span class="tw-truncate">
{{ uri.pathname.replace(/^\/*/, '') }}
</span>
</template>
</span> </span>
<span class="tw-ml-auto"> <span class="tw-ml-auto">
......
...@@ -238,6 +238,7 @@ export default { ...@@ -238,6 +238,7 @@ export default {
file: { file: {
url: 'URL', url: 'URL',
name: 'Dateiname',
unnamed: 'Unbenannte Datei', unnamed: 'Unbenannte Datei',
duration: 'Dauer', duration: 'Dauer',
durationUnknown: 'Unbekannte Dauer', durationUnknown: 'Unbekannte Dauer',
...@@ -291,6 +292,7 @@ export default { ...@@ -291,6 +292,7 @@ export default {
importFile: 'Datei von URL importieren', importFile: 'Datei von URL importieren',
addStream: 'Stream hinzufügen', addStream: 'Stream hinzufügen',
addInput: 'Eingang hinzufügen', addInput: 'Eingang hinzufügen',
addM3u: 'M3U hinzufügen',
}, },
importFileDialog: { importFileDialog: {
title: 'Datei von URL importieren', title: 'Datei von URL importieren',
...@@ -304,6 +306,10 @@ export default { ...@@ -304,6 +306,10 @@ export default {
title: 'Stream als Medienquelle hinzufügen', title: 'Stream als Medienquelle hinzufügen',
saveLabel: 'Stream hinzufügen', saveLabel: 'Stream hinzufügen',
}, },
addM3uDialog: {
title: 'M3U als Medienquelle hinzufügen',
saveLabel: 'M3U hinzufügen',
},
}, },
state: { state: {
ok: { title: 'Perfekt' }, ok: { title: 'Perfekt' },
......
...@@ -239,6 +239,7 @@ export default { ...@@ -239,6 +239,7 @@ export default {
file: { file: {
url: 'URL', url: 'URL',
name: 'Filename',
unnamed: 'Unnamed file', unnamed: 'Unnamed file',
duration: 'Duration', duration: 'Duration',
durationUnknown: 'Unknown duration', durationUnknown: 'Unknown duration',
...@@ -292,6 +293,7 @@ export default { ...@@ -292,6 +293,7 @@ export default {
importFile: 'Import file from URL', importFile: 'Import file from URL',
addStream: 'Add stream', addStream: 'Add stream',
addInput: 'Add input', addInput: 'Add input',
addM3u: 'Add M3U',
}, },
importFileDialog: { importFileDialog: {
title: 'Import file from URL', title: 'Import file from URL',
...@@ -305,6 +307,10 @@ export default { ...@@ -305,6 +307,10 @@ export default {
title: 'Add stream as media source', title: 'Add stream as media source',
saveLabel: 'Add stream', saveLabel: 'Add stream',
}, },
addM3uDialog: {
title: 'Add M3U as media source',
saveLabel: 'Add M3U',
},
}, },
state: { state: {
ok: { title: 'Perfect' }, ok: { title: 'Perfect' },
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment