Merge pull request #242 from arabcoders/dev
Add support for --match-filter
This commit is contained in:
commit
8305518a01
5 changed files with 173 additions and 21 deletions
|
|
@ -465,6 +465,13 @@ def arg_converter(args: str) -> dict:
|
||||||
if "postprocessors" in diff:
|
if "postprocessors" in diff:
|
||||||
diff["postprocessors"] = [pp for pp in diff["postprocessors"] if pp not in default_opts["postprocessors"]]
|
diff["postprocessors"] = [pp for pp in diff["postprocessors"] if pp not in default_opts["postprocessors"]]
|
||||||
|
|
||||||
|
if "match_filter" in diff:
|
||||||
|
import inspect
|
||||||
|
|
||||||
|
matchFilter = inspect.getclosurevars(diff["match_filter"].func).nonlocals["filters"]
|
||||||
|
if isinstance(matchFilter, set):
|
||||||
|
diff["match_filter"] = {"filters": list(matchFilter)}
|
||||||
|
|
||||||
from .encoder import Encoder
|
from .encoder import Encoder
|
||||||
|
|
||||||
return json.loads(json.dumps(diff, cls=Encoder))
|
return json.loads(json.dumps(diff, cls=Encoder))
|
||||||
|
|
@ -691,7 +698,7 @@ def get(
|
||||||
if not path:
|
if not path:
|
||||||
return data
|
return data
|
||||||
|
|
||||||
# If data is not a dict or list, attempt to convert it (similar to PHP's get_object_vars).
|
# If data is not a dict or list, attempt to convert it.
|
||||||
if not isinstance(data, dict | list):
|
if not isinstance(data, dict | list):
|
||||||
try:
|
try:
|
||||||
data = vars(data)
|
data = vars(data)
|
||||||
|
|
|
||||||
|
|
@ -142,4 +142,14 @@ class YTDLPOpts(metaclass=Singleton):
|
||||||
|
|
||||||
data["impersonate"] = ImpersonateTarget.from_str(data["impersonate"])
|
data["impersonate"] = ImpersonateTarget.from_str(data["impersonate"])
|
||||||
|
|
||||||
|
if (
|
||||||
|
"match_filter" in data
|
||||||
|
and isinstance(data["match_filter"], dict)
|
||||||
|
and "filters" in data["match_filter"]
|
||||||
|
and len(data["match_filter"]["filters"]) > 0
|
||||||
|
):
|
||||||
|
from yt_dlp.utils import match_filter_func
|
||||||
|
|
||||||
|
data["match_filter"] = match_filter_func(data["match_filter"]["filters"])
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
|
||||||
|
|
@ -286,3 +286,7 @@ hr {
|
||||||
max-height: unset !important;
|
max-height: unset !important;
|
||||||
width: unset !important;
|
width: unset !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.is-auto {
|
||||||
|
unicode-bidi: embed;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@
|
||||||
<NuxtLink class="button is-dark has-tooltip-bottom" to="/browser">
|
<NuxtLink class="button is-dark has-tooltip-bottom" to="/browser">
|
||||||
<span class="icon-text">
|
<span class="icon-text">
|
||||||
<span class="icon"><i class="fa-solid fa-folder-tree" /></span>
|
<span class="icon"><i class="fa-solid fa-folder-tree" /></span>
|
||||||
<span class="is-hidden-mobile">Browser</span>
|
<span class="is-hidden-mobile">Files</span>
|
||||||
</span>
|
</span>
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,20 @@
|
||||||
</span>
|
</span>
|
||||||
<div class="is-pulled-right">
|
<div class="is-pulled-right">
|
||||||
<div class="field is-grouped">
|
<div class="field is-grouped">
|
||||||
|
<div class="control has-icons-left" v-if="show_filter">
|
||||||
|
<input type="search" v-model.lazy="search" class="input" id="search" placeholder="Filter">
|
||||||
|
<span class="icon is-left">
|
||||||
|
<i class="fas fa-filter"></i>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="control">
|
||||||
|
<button class="button is-danger is-light" @click="toggleFilter"
|
||||||
|
v-tooltip.bottom="'Filter content'">
|
||||||
|
<span class="icon"><i class="fas fa-filter" /></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<p class="control">
|
<p class="control">
|
||||||
<button class="button is-info" @click="reloadContent(path, true)" :class="{ 'is-loading': isLoading }"
|
<button class="button is-info" @click="reloadContent(path, true)" :class="{ 'is-loading': isLoading }"
|
||||||
:disabled="!socket.isConnected || isLoading">
|
:disabled="!socket.isConnected || isLoading">
|
||||||
|
|
@ -40,26 +54,47 @@
|
||||||
style="min-width: 1300px; table-layout: fixed;">
|
style="min-width: 1300px; table-layout: fixed;">
|
||||||
<thead>
|
<thead>
|
||||||
<tr class="has-text-centered is-unselectable">
|
<tr class="has-text-centered is-unselectable">
|
||||||
<th width="5%">#</th>
|
<th width="5%" @click="changeSort('type')">
|
||||||
<th width="55%">Name</th>
|
#
|
||||||
<th width="10%">Size</th>
|
<span class="icon" v-if="'type' === sort_by">
|
||||||
<th width="15%">Created</th>
|
<i class="fas"
|
||||||
<th width="15%">Modified</th>
|
:class="{ 'fa-sort-up': 'desc' === sort_order, 'fa-sort-down': 'asc' === sort_order }" />
|
||||||
|
</span>
|
||||||
|
</th>
|
||||||
|
<th width="70%" @click="changeSort('name')">
|
||||||
|
Name
|
||||||
|
<span class="icon" v-if="'name' === sort_by">
|
||||||
|
<i class="fas"
|
||||||
|
:class="{ 'fa-sort-up': 'desc' === sort_order, 'fa-sort-down': 'asc' === sort_order }" />
|
||||||
|
</span>
|
||||||
|
|
||||||
|
</th>
|
||||||
|
<th width="10%" @click="changeSort('size')">
|
||||||
|
Size
|
||||||
|
<span class="icon" v-if="'size' === sort_by">
|
||||||
|
<i class="fas"
|
||||||
|
:class="{ 'fa-sort-up': 'desc' === sort_order, 'fa-sort-down': 'asc' === sort_order }" />
|
||||||
|
</span>
|
||||||
|
|
||||||
|
</th>
|
||||||
|
<th width="15%" @click="changeSort('date')">
|
||||||
|
Date
|
||||||
|
<span class="icon" v-if="'date' === sort_by">
|
||||||
|
<i class="fas"
|
||||||
|
:class="{ 'fa-sort-up': 'desc' === sort_order, 'fa-sort-down': 'asc' === sort_order }" />
|
||||||
|
</span>
|
||||||
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr v-for="item in items" :key="item.path">
|
<tr v-for="item in filteredItems" :key="item.path">
|
||||||
<td class="has-text-centered is-vcentered">
|
<td class="has-text-centered is-vcentered user-hint" v-tooltip="item.name">
|
||||||
<span class="icon">
|
<span class="icon"><i class="fas fa-2x fa-solid" :class="setIcon(item)" /></span>
|
||||||
<i class="fas fa-solid"
|
|
||||||
:class="{ 'fa-file': 'file' === item.type, 'fa-folder': 'dir' === item.type }" />
|
|
||||||
</span>
|
|
||||||
</td>
|
</td>
|
||||||
<td class="is-text-overflow is-vcentered">
|
<td class="is-text-overflow is-vcentered">
|
||||||
<div class="field is-grouped">
|
<div class="field is-grouped">
|
||||||
<div class="control is-text-overflow is-expanded" v-tooltip="item.name">
|
<div class="control is-text-overflow is-expanded">
|
||||||
<a :href="`/browser/${item.path}`" v-if="'dir' === item.type"
|
<a :href="`/browser/${item.path}`" v-if="'dir' === item.type" @click.prevent="handleClick(item)">
|
||||||
@click.prevent="reloadContent(item.path)">
|
|
||||||
{{ item.name }}
|
{{ item.name }}
|
||||||
</a>
|
</a>
|
||||||
<a :href="makeDownload({}, { filename: item.path, folder: '' })"
|
<a :href="makeDownload({}, { filename: item.path, folder: '' })"
|
||||||
|
|
@ -80,11 +115,6 @@
|
||||||
<td class="has-text-centered is-text-overflow is-unselectable">
|
<td class="has-text-centered is-text-overflow is-unselectable">
|
||||||
{{ 'file' === item.type ? formatBytes(item.size) : 'Dir' }}
|
{{ 'file' === item.type ? formatBytes(item.size) : 'Dir' }}
|
||||||
</td>
|
</td>
|
||||||
<td class="has-text-centered is-text-overflow is-unselectable">
|
|
||||||
<span :data-datetime="item.ctime" v-tooltip="moment(item.ctime).format('MMMM Do YYYY, h:mm:ss a')">
|
|
||||||
{{ moment(item.ctime).fromNow() }}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td class="has-text-centered is-text-overflow is-unselectable">
|
<td class="has-text-centered is-text-overflow is-unselectable">
|
||||||
<span :data-datetime="item.mtime" v-tooltip="moment(item.mtime).format('MMMM Do YYYY, h:mm:ss a')">
|
<span :data-datetime="item.mtime" v-tooltip="moment(item.mtime).format('MMMM Do YYYY, h:mm:ss a')">
|
||||||
{{ moment(item.mtime).fromNow() }}
|
{{ moment(item.mtime).fromNow() }}
|
||||||
|
|
@ -137,6 +167,59 @@ const path = ref(`/${route.params.slug?.length > 0 ? route.params.slug?.join('/'
|
||||||
const bg_enable = useStorage('random_bg', true)
|
const bg_enable = useStorage('random_bg', true)
|
||||||
const bg_opacity = useStorage('random_bg_opacity', 0.85)
|
const bg_opacity = useStorage('random_bg_opacity', 0.85)
|
||||||
|
|
||||||
|
const sort_by = useStorage('sort_by', 'name')
|
||||||
|
const sort_order = useStorage('sort_order', 'asc')
|
||||||
|
|
||||||
|
const search = ref('')
|
||||||
|
const show_filter = ref(false)
|
||||||
|
|
||||||
|
const filteredItems = computed(() => {
|
||||||
|
if (!search.value) {
|
||||||
|
return sortedItems(items.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchLower = search.value.toLowerCase()
|
||||||
|
return sortedItems(items.value.filter(item => {
|
||||||
|
return item.name.toLowerCase().includes(searchLower)
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
|
||||||
|
const sortedItems = items => {
|
||||||
|
|
||||||
|
if (!items || items.length < 1) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('name' === sort_by.value) {
|
||||||
|
return items.sort((a, b) => {
|
||||||
|
return 'asc' === sort_order.value ? a.name.localeCompare(b.name) : b.name.localeCompare(a.name)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sort_by.value === 'size') {
|
||||||
|
return items.sort((a, b) => {
|
||||||
|
return 'asc' === sort_order.value ? a.size - b.size : b.size - a.size
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sort_by.value === 'date') {
|
||||||
|
return items.sort((a, b) => {
|
||||||
|
let aDate = new Date(a.mtime)
|
||||||
|
let bDate = new Date(b.mtime)
|
||||||
|
return 'asc' === sort_order.value ? aDate - bDate : bDate - aDate
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sort_by.value === 'type') {
|
||||||
|
return items.sort((a, b) => {
|
||||||
|
return 'asc' === sort_order.value ? a.content_type.localeCompare(b.content_type) : b.content_type.localeCompare(a.content_type)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return items
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const model_item = ref()
|
const model_item = ref()
|
||||||
const closeModel = () => model_item.value = null
|
const closeModel = () => model_item.value = null
|
||||||
|
|
||||||
|
|
@ -193,6 +276,11 @@ const handleClick = item => {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('dir' === item.content_type) {
|
if ('dir' === item.content_type) {
|
||||||
|
if (search.value) {
|
||||||
|
search.value = ''
|
||||||
|
show_filter.value = false
|
||||||
|
}
|
||||||
|
|
||||||
reloadContent(item.path)
|
reloadContent(item.path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -310,4 +398,47 @@ watch(model_item, v => {
|
||||||
|
|
||||||
document.querySelector('body').setAttribute("style", `opacity: ${v ? 1 : bg_opacity.value}`)
|
document.querySelector('body').setAttribute("style", `opacity: ${v ? 1 : bg_opacity.value}`)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const setIcon = item => {
|
||||||
|
if ('dir' === item.content_type) {
|
||||||
|
return 'fa-folder'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (['video', 'audio'].includes(item.content_type)) {
|
||||||
|
return 'fa-file-video'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (['text', 'subtitle', 'metadata'].includes(item.content_type)) {
|
||||||
|
return 'fa-file-alt'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (['image'].includes(item.content_type)) {
|
||||||
|
return 'fa-file-image'
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'fa-file'
|
||||||
|
}
|
||||||
|
|
||||||
|
const changeSort = by => {
|
||||||
|
if (!['name', 'size', 'date', 'type'].includes(by)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (by !== sort_by.value) {
|
||||||
|
sort_by.value = by
|
||||||
|
}
|
||||||
|
|
||||||
|
sort_order.value = 'asc' === sort_order.value ? 'desc' : 'asc'
|
||||||
|
}
|
||||||
|
|
||||||
|
const toggleFilter = () => {
|
||||||
|
show_filter.value = !show_filter.value
|
||||||
|
if (!show_filter.value) {
|
||||||
|
search.value = ''
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
awaitElement('#search', e => e.focus())
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue