mirror of
https://github.com/koel/koel
synced 2024-11-10 14:44:13 +00:00
Better copy
This commit is contained in:
parent
4082ca77f0
commit
dc67de8335
4 changed files with 196 additions and 2 deletions
|
@ -28,7 +28,7 @@
|
|||
</ol>
|
||||
|
||||
<p class="none" v-show="!recentSongs.length">
|
||||
Your most-recent songs in this session will be displayed here.<br />
|
||||
Your recently played songs will be displayed here.<br />
|
||||
Start listening!
|
||||
</p>
|
||||
</section>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<div class="change-pwd">
|
||||
<div class="form-row">
|
||||
<p class="help">If you want to change your password, enter it below. <br>
|
||||
Otherwise, just leave the next two fields empty. It’s OK – no one will blame you.</p>
|
||||
Otherwise, just leave the next two fields empty. It’s OK – no one will judge you.</p>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
|
|
44
resources/assets/js/components/shared/song-list-header.vue
Normal file
44
resources/assets/js/components/shared/song-list-header.vue
Normal file
|
@ -0,0 +1,44 @@
|
|||
<template>
|
||||
<thead>
|
||||
<tr>
|
||||
<th @click="sort('track')" class="track-number">#
|
||||
<i class="fa fa-angle-down" v-show="sortKey === 'track' && order > 0"/>
|
||||
<i class="fa fa-angle-up" v-show="sortKey === 'track' && order < 0"/>
|
||||
</th>
|
||||
<th @click="sort('title')" class="title">Title
|
||||
<i class="fa fa-angle-down" v-show="sortKey === 'title' && order > 0"/>
|
||||
<i class="fa fa-angle-up" v-show="sortKey === 'title' && order < 0"/>
|
||||
</th>
|
||||
<th @click="sort(['album.artist.name', 'album.name', 'track'])" class="artist">Artist
|
||||
<i class="fa fa-angle-down" v-show="sortingByArtist && order > 0"/>
|
||||
<i class="fa fa-angle-up" v-show="sortingByArtist && order < 0"/>
|
||||
</th>
|
||||
<th @click="sort(['album.name', 'track'])" class="album">Album
|
||||
<i class="fa fa-angle-down" v-show="sortingByAlbum && order > 0"/>
|
||||
<i class="fa fa-angle-up" v-show="sortingByAlbum && order < 0"/>
|
||||
</th>
|
||||
<th @click="sort('length')" class="time">Time
|
||||
<i class="fa fa-angle-down" v-show="sortKey === 'length' && order > 0"/>
|
||||
<i class="fa fa-angle-up" v-show="sortKey === 'length' && order < 0"/>
|
||||
</th>
|
||||
<th class="play"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
sortKey: '',
|
||||
order: 1
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
sort (key) {
|
||||
console.log(this.$parent.$parent)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,150 @@
|
|||
<template>
|
||||
<div class="virtual-scroller" @scroll="updateVisibleItems">
|
||||
<div class="item-container" :style="itemContainerStyle">
|
||||
<table class="items song-list-wrap">
|
||||
<component class="item"
|
||||
v-for="item in visibleItems"
|
||||
:key="item.id"
|
||||
:is="renderers[item[typeField]]"
|
||||
:item="item" />
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<iframe ref="resizeObserver" class="resize-observer" tabindex="-1"></iframe>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { debounce } from 'lodash'
|
||||
|
||||
export default {
|
||||
name: 'virtual-scroller',
|
||||
props: {
|
||||
items: {
|
||||
type: Array,
|
||||
required: true
|
||||
},
|
||||
renderers: {
|
||||
required: true
|
||||
},
|
||||
itemHeight: {
|
||||
type: [Number, String],
|
||||
required: true
|
||||
},
|
||||
typeField: {
|
||||
type: String,
|
||||
default: 'type'
|
||||
},
|
||||
keyField: {
|
||||
type: String,
|
||||
default: 'id'
|
||||
}
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
visibleItems: [],
|
||||
itemContainerStyle: null
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
items () {
|
||||
this.updateVisibleItems()
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
updateVisibleItems: debounce(function () {
|
||||
const l = this.items.length
|
||||
const el = this.$el
|
||||
const scroll = {
|
||||
top: el.scrollTop,
|
||||
bottom: el.scrollTop + el.clientHeight
|
||||
}
|
||||
|
||||
this._startIndex = Math.floor(scroll.top / this.itemHeight)
|
||||
this._endIndex = Math.ceil(scroll.bottom / this.itemHeight)
|
||||
|
||||
let startIndex = this._startIndex - 1
|
||||
if (startIndex < 0) {
|
||||
startIndex = 0
|
||||
}
|
||||
|
||||
let endIndex = this._endIndex + 2
|
||||
if (endIndex > l) {
|
||||
endIndex = l
|
||||
}
|
||||
|
||||
this.visibleItems = this.items.slice(startIndex, endIndex)
|
||||
this.itemContainerStyle = {
|
||||
height: l * this.itemHeight + 'px',
|
||||
paddingTop: startIndex * this.itemHeight + 'px',
|
||||
}
|
||||
|
||||
this.$forceUpdate()
|
||||
}, 100),
|
||||
|
||||
scrollToItem (index) {
|
||||
this.$el.scrollTop = index * this.itemHeight
|
||||
},
|
||||
|
||||
addResizeHandlers () {
|
||||
const iframe = this.$refs.resizeObserver
|
||||
const w = iframe.contentWindow
|
||||
// If the iframe is re-attached to the DOM, the resize listener is removed because the
|
||||
// content is reloaded, so make sure to install the handler after the iframe is loaded.
|
||||
iframe.addEventListener('load', this.refreshResizeHandlers)
|
||||
if (w) {
|
||||
w.addEventListener('resize', this.updateVisibleItems)
|
||||
w.addEventListener('close', this.removeResizeHandlers)
|
||||
}
|
||||
},
|
||||
|
||||
removeResizeHandlers () {
|
||||
const iframe = this.$refs.resizeObserver
|
||||
const w = iframe.contentWindow
|
||||
iframe.removeEventListener('load', this.refreshResizeHandlers)
|
||||
if (w) {
|
||||
w.removeEventListener('resize', this.updateVisibleItems)
|
||||
w.removeEventListener('close', this.removeResizeHandlers)
|
||||
}
|
||||
},
|
||||
|
||||
refreshResizeHandlers () {
|
||||
this.removeResizeHandlers()
|
||||
this.addResizeHandlers()
|
||||
// The iframe size might have changed while loading, which can also
|
||||
// happen if the size has been changed while detached from the DOM.
|
||||
this.updateVisibleItems()
|
||||
},
|
||||
},
|
||||
|
||||
mounted () {
|
||||
this.updateVisibleItems()
|
||||
this.addResizeHandlers()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.virtual-scroller {
|
||||
overflow-y: auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.item-container {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.resize-observer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: -1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
}
|
||||
</style>
|
Loading…
Reference in a new issue