Quality filter for content frontent (#1469)
This commit is contained in:
parent
b50b5cb661
commit
b59f71ef0f
|
@ -2,6 +2,7 @@ from dynamic_preferences import types
|
||||||
from dynamic_preferences.registries import global_preferences_registry
|
from dynamic_preferences.registries import global_preferences_registry
|
||||||
|
|
||||||
music = types.Section("music")
|
music = types.Section("music")
|
||||||
|
quality_filters = types.Section("quality_filters")
|
||||||
|
|
||||||
|
|
||||||
@global_preferences_registry.register
|
@global_preferences_registry.register
|
||||||
|
@ -76,3 +77,85 @@ class MbSyncTags(types.BooleanPreference):
|
||||||
"the track, artist and album objects."
|
"the track, artist and album objects."
|
||||||
)
|
)
|
||||||
default = False
|
default = False
|
||||||
|
|
||||||
|
|
||||||
|
# quality_filters section. Note that the default False is not applied in the fronted
|
||||||
|
# (the filter will onlyu be use if set to True)
|
||||||
|
@global_preferences_registry.register
|
||||||
|
class BitrateFilter(types.ChoicePreference):
|
||||||
|
show_in_api = True
|
||||||
|
section = quality_filters
|
||||||
|
name = "bitrate_filter"
|
||||||
|
verbose_name = "Upload Quality Filter"
|
||||||
|
default = "low"
|
||||||
|
choices = [
|
||||||
|
("low", "Allow all audio qualities"),
|
||||||
|
("medium", "Medium : Do not allow low quality"),
|
||||||
|
("high", "High : only allow high and very-high audio qualities"),
|
||||||
|
("very_high", "Very High : only allow very-high audio quality"),
|
||||||
|
]
|
||||||
|
help_text = (
|
||||||
|
"The main page content can be filtered based on audio quality. "
|
||||||
|
"This will exclude lower quality, higher qualities are never excluded. "
|
||||||
|
"Quality Table can be found in the docs."
|
||||||
|
)
|
||||||
|
field_kwargs = {"choices": choices, "required": False}
|
||||||
|
|
||||||
|
|
||||||
|
@global_preferences_registry.register
|
||||||
|
class HasMbid(types.BooleanPreference):
|
||||||
|
show_in_api = True
|
||||||
|
section = quality_filters
|
||||||
|
name = "has_mbid"
|
||||||
|
verbose_name = "Musicbrainz Ids filter"
|
||||||
|
help_text = "Should we filter out metadata without Musicbrainz Ids ?"
|
||||||
|
default = False
|
||||||
|
|
||||||
|
|
||||||
|
@global_preferences_registry.register
|
||||||
|
class Format(types.MultipleChoicePreference):
|
||||||
|
show_in_api = True
|
||||||
|
section = quality_filters
|
||||||
|
name = "format"
|
||||||
|
verbose_name = "Allowed Audio Format"
|
||||||
|
default = (["aac", "aif", "aiff", "flac", "mp3", "ogg", "opus"],)
|
||||||
|
choices = [
|
||||||
|
("ogg", "ogg"),
|
||||||
|
("opus", "opus"),
|
||||||
|
("flac", "flac"),
|
||||||
|
("aif", "aif"),
|
||||||
|
("aiff", "aiff"),
|
||||||
|
("aac", "aac"),
|
||||||
|
("mp3", "mp3"),
|
||||||
|
]
|
||||||
|
help_text = "Witch audio format to allow"
|
||||||
|
|
||||||
|
|
||||||
|
@global_preferences_registry.register
|
||||||
|
class AlbumArt(types.BooleanPreference):
|
||||||
|
show_in_api = True
|
||||||
|
section = quality_filters
|
||||||
|
name = "has_cover"
|
||||||
|
verbose_name = "Album art Filter"
|
||||||
|
help_text = "Only Albums with a cover will be displayed in the home page"
|
||||||
|
default = False
|
||||||
|
|
||||||
|
|
||||||
|
@global_preferences_registry.register
|
||||||
|
class Tags(types.BooleanPreference):
|
||||||
|
show_in_api = True
|
||||||
|
section = quality_filters
|
||||||
|
name = "has_tags"
|
||||||
|
verbose_name = "Tags Filter"
|
||||||
|
help_text = "Only content with at least one tag will be displayed"
|
||||||
|
default = False
|
||||||
|
|
||||||
|
|
||||||
|
@global_preferences_registry.register
|
||||||
|
class ReleaseDate(types.BooleanPreference):
|
||||||
|
show_in_api = True
|
||||||
|
section = quality_filters
|
||||||
|
name = "has_release_date"
|
||||||
|
verbose_name = "Release date Filter"
|
||||||
|
help_text = "Only content with a release date will be displayed"
|
||||||
|
default = False
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Quality filter for content frontend (#1469)
|
|
@ -1,6 +1,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import { ref, computed } from 'vue'
|
import { ref, computed } from 'vue'
|
||||||
|
import { useStore } from '~/store'
|
||||||
|
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
|
||||||
|
@ -20,6 +21,9 @@ withDefaults(defineProps<Props>(), {
|
||||||
scope: 'all'
|
scope: 'all'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const store = useStore()
|
||||||
|
const qualityFilters = computed(() => store.getters['instance/qualityFilters'])
|
||||||
|
|
||||||
const artists = ref([])
|
const artists = ref([])
|
||||||
|
|
||||||
const logger = useLogger()
|
const logger = useLogger()
|
||||||
|
@ -63,7 +67,7 @@ fetchData()
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<track-widget
|
<track-widget
|
||||||
:url="'history/listenings/'"
|
:url="'history/listenings/'"
|
||||||
:filters="{ scope, ordering: '-creation_date' }"
|
:filters="{ scope, ordering: '-creation_date', ...qualityFilters}"
|
||||||
:websocket-handlers="['Listen']"
|
:websocket-handlers="['Listen']"
|
||||||
>
|
>
|
||||||
<template #title>
|
<template #title>
|
||||||
|
@ -95,7 +99,7 @@ fetchData()
|
||||||
<div class="ui section hidden divider" />
|
<div class="ui section hidden divider" />
|
||||||
<div class="ui stackable one column grid">
|
<div class="ui stackable one column grid">
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<album-widget :filters="{scope: scope, playable: true, ordering: '-creation_date'}">
|
<album-widget :filters="{scope: scope, playable: true, ordering: '-creation_date', ...qualityFilters}">
|
||||||
<template #title>
|
<template #title>
|
||||||
{{ $t('components.library.Home.header.recentlyAdded') }}
|
{{ $t('components.library.Home.header.recentlyAdded') }}
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -3374,6 +3374,7 @@
|
||||||
"moderation": "Moderation",
|
"moderation": "Moderation",
|
||||||
"music": "Music",
|
"music": "Music",
|
||||||
"playlists": "Playlists",
|
"playlists": "Playlists",
|
||||||
|
"qualityFilters": "Explore page quality filters",
|
||||||
"sections": "Sections",
|
"sections": "Sections",
|
||||||
"security": "Security",
|
"security": "Security",
|
||||||
"settings": "Instance Settings",
|
"settings": "Instance Settings",
|
||||||
|
|
|
@ -104,6 +104,12 @@ interface ModerationSettings {
|
||||||
signup_approval_enabled: { value: boolean }
|
signup_approval_enabled: { value: boolean }
|
||||||
signup_form_customization: { value: null }
|
signup_form_customization: { value: null }
|
||||||
}
|
}
|
||||||
|
interface QualityFiltersSettings {
|
||||||
|
[key: string]: any;
|
||||||
|
|
||||||
|
bitrate_filter: { value: number }
|
||||||
|
has_mbid: { value: boolean }
|
||||||
|
}
|
||||||
|
|
||||||
interface SubsonicSettings {
|
interface SubsonicSettings {
|
||||||
enabled: { value: boolean }
|
enabled: { value: boolean }
|
||||||
|
@ -117,6 +123,7 @@ interface Settings {
|
||||||
instance: InstanceSettings
|
instance: InstanceSettings
|
||||||
users: UsersSettings
|
users: UsersSettings
|
||||||
moderation: ModerationSettings
|
moderation: ModerationSettings
|
||||||
|
quality_filters: QualityFiltersSettings
|
||||||
subsonic: SubsonicSettings
|
subsonic: SubsonicSettings
|
||||||
ui: UISettings
|
ui: UISettings
|
||||||
}
|
}
|
||||||
|
@ -189,6 +196,10 @@ const store: Module<State, RootState> = {
|
||||||
},
|
},
|
||||||
signup_form_customization: { value: null }
|
signup_form_customization: { value: null }
|
||||||
},
|
},
|
||||||
|
quality_filters: {
|
||||||
|
bitrate_filter: { value: 0 },
|
||||||
|
has_mbid: { value: false }
|
||||||
|
},
|
||||||
subsonic: {
|
subsonic: {
|
||||||
enabled: {
|
enabled: {
|
||||||
value: true
|
value: true
|
||||||
|
@ -233,7 +244,22 @@ const store: Module<State, RootState> = {
|
||||||
},
|
},
|
||||||
url: (state) => new URL(state.instanceUrl ?? DEFAULT_INSTANCE_URL),
|
url: (state) => new URL(state.instanceUrl ?? DEFAULT_INSTANCE_URL),
|
||||||
domain: (_state, getters) => getters.url.hostname,
|
domain: (_state, getters) => getters.url.hostname,
|
||||||
defaultInstance: () => DEFAULT_INSTANCE_URL
|
defaultInstance: () => DEFAULT_INSTANCE_URL,
|
||||||
|
qualityFilters: (state) => {
|
||||||
|
const qualityFilters = state.settings.quality_filters
|
||||||
|
const filteredQualityFilters: Record<string, any> = {}
|
||||||
|
|
||||||
|
for (const key in qualityFilters) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(qualityFilters, key)) {
|
||||||
|
if (qualityFilters[key].value === false) {
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
filteredQualityFilters[key] = qualityFilters[key].value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return filteredQualityFilters
|
||||||
|
}
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
setUrl ({ commit }, url) {
|
setUrl ({ commit }, url) {
|
||||||
|
|
|
@ -61,6 +61,18 @@ const groups = computed(() => [
|
||||||
{ name: 'music__only_allow_musicbrainz_tagged_files' },
|
{ name: 'music__only_allow_musicbrainz_tagged_files' },
|
||||||
{ name: 'music__sync_musicbrainz_tags' },
|
{ name: 'music__sync_musicbrainz_tags' },
|
||||||
{ name: 'music__musicbrainz_genre_update' }
|
{ name: 'music__musicbrainz_genre_update' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('views.admin.Settings.header.qualityFilters'),
|
||||||
|
id: 'qualityFilters',
|
||||||
|
settings: [
|
||||||
|
{ name: 'quality_filters__has_cover' },
|
||||||
|
{ name: 'quality_filters__has_tags' },
|
||||||
|
{ name: 'quality_filters__has_mbid' },
|
||||||
|
{ name: 'quality_filters__format' },
|
||||||
|
{ name: 'quality_filters__bitrate_filter' },
|
||||||
|
{ name: 'quality_filters__has_release_date' }
|
||||||
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue