[UI] Added navigation crumbs to the file browser.

This commit is contained in:
Fabio Manganiello 2023-11-12 15:53:46 +01:00
parent 724f625963
commit 6dfe2324c1
Signed by: blacklight
GPG key ID: D90FBA7F76362774

View file

@ -2,7 +2,25 @@
<div class="browser-container"> <div class="browser-container">
<Loading v-if="loading" /> <Loading v-if="loading" />
<div class="row item" @click="path = (path || '') + '/..'" v-if="path?.length && path !== '/'"> <div class="nav" ref="nav">
<span class="path"
v-for="(token, i) in pathTokens"
:key="i"
@click="path = pathTokens.slice(0, i + 1).join('/').slice(1)">
<span class="token">
{{ token }}
</span>
<span class="separator" v-if="(i > 0 || pathTokens.length > 1) && i < pathTokens.length - 1">
<i class="fa fa-chevron-right" />
</span>
</span>
</div>
<div class="items" ref="items">
<div class="row item"
@click="onBack"
v-if="(path?.length && path !== '/') || hasBack">
<div class="col-10 left side"> <div class="col-10 left side">
<i class="icon fa fa-folder" /> <i class="icon fa fa-folder" />
<span class="name">..</span> <span class="name">..</span>
@ -21,11 +39,12 @@
<Dropdown> <Dropdown>
<DropdownItem icon-class="fa fa-play" text="Play" <DropdownItem icon-class="fa fa-play" text="Play"
@click="$emit('play', {type: 'file', url: `file://${file.path}`})" @click="$emit('play', {type: 'file', url: `file://${file.path}`})"
v-if="isMedia && mediaExtensions.has(file.name.split('.').pop())" /> v-if="isMedia && mediaExtensions.has(file.name.split('.').pop()?.toLowerCase())" />
</Dropdown> </Dropdown>
</div> </div>
</div> </div>
</div> </div>
</div>
</template> </template>
<script> <script>
@ -39,9 +58,14 @@ export default {
name: "Browser", name: "Browser",
components: {DropdownItem, Dropdown, Loading}, components: {DropdownItem, Dropdown, Loading},
mixins: [Utils, MediaUtils], mixins: [Utils, MediaUtils],
emits: ['path-change'], emits: ['back', 'path-change', 'play'],
props: { props: {
hasBack: {
type: Boolean,
default: false,
},
initialPath: { initialPath: {
type: String, type: String,
}, },
@ -71,11 +95,24 @@ export default {
return this.files.filter((file) => (file?.name || '').toLowerCase().indexOf(this.filter.toLowerCase()) >= 0) return this.files.filter((file) => (file?.name || '').toLowerCase().indexOf(this.filter.toLowerCase()) >= 0)
}, },
pathTokens() {
if (!this.path?.length)
return ['/']
return ['/', ...this.path.split(/(?<!\\)\//).slice(1)]
},
}, },
methods: { methods: {
async refresh() { async refresh() {
this.loading = true this.loading = true
this.$nextTick(() => {
// Scroll to the end of the path navigator
this.$refs.nav.scrollLeft = 99999
// Scroll to the top of the items list
this.$refs.items.scrollTop = 0
})
try { try {
this.files = await this.request('file.list', {path: this.path}) this.files = await this.request('file.list', {path: this.path})
@ -84,6 +121,13 @@ export default {
this.loading = false this.loading = false
} }
}, },
onBack() {
if (!this.path?.length || this.path === '/')
this.$emit('back')
else
this.path = [...this.pathTokens].slice(0, -1).join('/').slice(1)
},
}, },
mounted() { mounted() {
@ -96,12 +140,50 @@ export default {
<style lang="scss" scoped> <style lang="scss" scoped>
@import "src/style/items"; @import "src/style/items";
$nav-height: 2.5em;
.browser-container { .browser-container {
height: 100%;
display: flex;
flex-direction: column;
.item { .item {
.actions { .actions {
display: inline-flex; display: inline-flex;
justify-content: right; justify-content: right;
} }
} }
.nav {
width: 100%;
height: $nav-height;
padding: 0.5em 1em;
background: $tab-bg;
box-shadow: $border-shadow-bottom;
white-space: nowrap;
overflow: hidden;
.path {
cursor: pointer;
.token {
&:hover {
color: $default-hover-fg;
text-decoration: underline;
}
}
.separator {
font-size: 1em;
width: 1.2em;
padding: 0 1em;
}
}
}
.items {
height: calc(100% - #{$nav-height});
overflow: auto;
}
} }
</style> </style>