mirror of
https://github.com/koel/koel
synced 2025-02-16 13:28:32 +00:00
Add thumbnails/listing view mode (close #278)
This commit adds an option to change view mode (thumbnails/listing) for artists and albums views.
This commit is contained in:
parent
bad47db651
commit
f43e72355c
6 changed files with 148 additions and 13 deletions
|
@ -2,9 +2,10 @@
|
|||
<section id="albumsWrapper">
|
||||
<h1 class="heading">
|
||||
<span>Albums</span>
|
||||
<view-mode-switch :mode.sync="viewMode" :for="'albums'"></view-mode-switch>
|
||||
</h1>
|
||||
|
||||
<div class="albums main-scroll-wrap" v-el:wrapper @scroll="scrolling">
|
||||
<div class="albums main-scroll-wrap as-{{ viewMode }}" v-el:wrapper @scroll="scrolling">
|
||||
<album-item v-for="item in items
|
||||
| orderBy 'name'
|
||||
| filterBy q in 'name' 'artist.name'
|
||||
|
@ -17,12 +18,13 @@
|
|||
|
||||
<script>
|
||||
import albumItem from '../../shared/album-item.vue';
|
||||
import viewModeSwitch from '../../shared/view-mode-switch.vue';
|
||||
import infiniteScroll from '../../../mixins/infinite-scroll';
|
||||
import albumStore from '../../../stores/album';
|
||||
|
||||
export default {
|
||||
mixins: [infiniteScroll],
|
||||
components: { albumItem },
|
||||
components: { albumItem, viewModeSwitch },
|
||||
|
||||
data() {
|
||||
return {
|
||||
|
@ -30,6 +32,7 @@
|
|||
numOfItems: 9,
|
||||
state: albumStore.state,
|
||||
q: '',
|
||||
viewMode: null,
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -45,6 +48,8 @@
|
|||
*/
|
||||
'koel:ready': function () {
|
||||
this.displayMore();
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
'koel:teardown': function () {
|
||||
|
|
|
@ -2,9 +2,10 @@
|
|||
<section id="artistsWrapper">
|
||||
<h1 class="heading">
|
||||
<span>Artists</span>
|
||||
<view-mode-switch :mode.sync="viewMode" :for="'artists'"></view-mode-switch>
|
||||
</h1>
|
||||
|
||||
<div class="artists main-scroll-wrap" v-el:wrapper @scroll="scrolling">
|
||||
<div class="artists main-scroll-wrap as-{{ viewMode }}" v-el:wrapper @scroll="scrolling">
|
||||
<artist-item v-for="item in items
|
||||
| filterBy q in 'name'
|
||||
| limitBy numOfItems" :artist="item"></artist-item>
|
||||
|
@ -16,13 +17,14 @@
|
|||
|
||||
<script>
|
||||
import artistItem from '../../shared/artist-item.vue';
|
||||
import viewModeSwitch from '../../shared/view-mode-switch.vue';
|
||||
import infiniteScroll from '../../../mixins/infinite-scroll';
|
||||
import artistStore from '../../../stores/artist';
|
||||
|
||||
export default {
|
||||
mixins: [infiniteScroll],
|
||||
|
||||
components: { artistItem },
|
||||
components: { artistItem, viewModeSwitch },
|
||||
|
||||
data() {
|
||||
return {
|
||||
|
@ -30,6 +32,7 @@
|
|||
numOfItems: 9,
|
||||
state: artistStore.state,
|
||||
q: '',
|
||||
viewMode: null,
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -39,12 +42,20 @@
|
|||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
setViewMode(mode) {
|
||||
this.viewMode = mode;
|
||||
},
|
||||
},
|
||||
|
||||
events: {
|
||||
/**
|
||||
* When the application is ready, load the first batch of items.
|
||||
*/
|
||||
'koel:ready': function () {
|
||||
this.displayMore();
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
'koel:teardown': function () {
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
</span>
|
||||
<footer>
|
||||
<a class="name" @click.prevent="viewDetails">{{ album.name }}</a>
|
||||
<span class="sep">by</span>
|
||||
<a class="artist" @click.prevent="viewArtistDetails">{{ album.artist.name }}</a>
|
||||
<p class="meta">
|
||||
{{ album.songs.length }} {{ album.songs.length | pluralize 'song' }}
|
||||
|
@ -76,4 +77,13 @@
|
|||
@import "../../../sass/partials/_mixins.scss";
|
||||
|
||||
@include artist-album-card();
|
||||
|
||||
.sep {
|
||||
display: none;
|
||||
color: $color2ndText;
|
||||
|
||||
.as-list & {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
81
resources/assets/js/components/shared/view-mode-switch.vue
Normal file
81
resources/assets/js/components/shared/view-mode-switch.vue
Normal file
|
@ -0,0 +1,81 @@
|
|||
<template>
|
||||
<span class="view-modes">
|
||||
<a :class="{ active: mode === 'thumbnails' }"
|
||||
title="View as thumbnails"
|
||||
@click.prevent="setMode('thumbnails')"><i class="fa fa-th-large"></i></a>
|
||||
<a :class="{ active: mode === 'list' }"
|
||||
title="View as list"
|
||||
@click.prevent="setMode('list')"><i class="fa fa-list"></i></a>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import preferenceStore from '../../stores/preference';
|
||||
import isMobile from 'ismobilejs';
|
||||
|
||||
export default {
|
||||
props: ['mode', 'for'],
|
||||
|
||||
computed: {
|
||||
/**
|
||||
* The preference key for local storage for persistent mode.
|
||||
*
|
||||
* @return {string}
|
||||
*/
|
||||
preferenceKey() {
|
||||
return `${this.for}ViewMode`;
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
setMode(mode) {
|
||||
preferenceStore.set(this.preferenceKey, this.mode = mode);
|
||||
},
|
||||
},
|
||||
|
||||
events: {
|
||||
'koel:ready': function () {
|
||||
this.mode = preferenceStore.get(this.preferenceKey);
|
||||
|
||||
// If the value is empty, we set a default mode.
|
||||
// On mobile, the mode should be 'listing'.
|
||||
// For desktop, 'thumbnails'.
|
||||
if (!this.mode) {
|
||||
this.mode = isMobile.phone ? 'list' : 'thumbnails';
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="sass" scoped>
|
||||
@import "../../../sass/partials/_vars.scss";
|
||||
@import "../../../sass/partials/_mixins.scss";
|
||||
|
||||
.view-modes {
|
||||
display: flex;
|
||||
flex: 0 0 64px;
|
||||
border: 1px solid rgba(255, 255, 255, .2);
|
||||
height: 28px;
|
||||
border-radius: 5px;
|
||||
overflow: hidden;
|
||||
|
||||
a {
|
||||
width: 50%;
|
||||
text-align: center;
|
||||
line-height: 26px;
|
||||
font-size: 14px;
|
||||
|
||||
&.active {
|
||||
background: #fff;
|
||||
color: #111;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and(max-width: 768px) {
|
||||
flex: 0;
|
||||
width: 64px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -15,7 +15,9 @@ export default {
|
|||
equalizer: {
|
||||
preamp: 0,
|
||||
gains: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
}
|
||||
},
|
||||
artistsViewMode: null,
|
||||
albumsViewMode: null,
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,6 +17,22 @@
|
|||
width: 23.5%;
|
||||
position: relative;
|
||||
|
||||
.as-list & {
|
||||
flex-direction: row;
|
||||
display: flex;
|
||||
width: 100% !important;
|
||||
|
||||
.cover {
|
||||
flex: 0 0 80px;
|
||||
height: 80px;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
footer {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1200px) {
|
||||
width: 32%;
|
||||
}
|
||||
|
@ -51,24 +67,30 @@
|
|||
padding-top: 100%;
|
||||
position: relative;
|
||||
|
||||
.control {
|
||||
$playBtnWidth: 96px;
|
||||
display: none;
|
||||
@mixin control($playBtnWidth, $fontSize, $textIndent) {
|
||||
width: $playBtnWidth;
|
||||
height: $playBtnWidth;
|
||||
text-align: center;
|
||||
line-height: $playBtnWidth;
|
||||
font-size: 54px;
|
||||
font-size: $fontSize;
|
||||
text-indent: $textIndent;
|
||||
left: calc(50% - #{$playBtnWidth/2});
|
||||
}
|
||||
|
||||
.control {
|
||||
.as-list & {
|
||||
@include control(46px, 27px, 2px);
|
||||
}
|
||||
|
||||
@include control(96px, 54px, 5px);
|
||||
display: none;
|
||||
text-align: center;
|
||||
background: #111;
|
||||
border-radius: 50%;
|
||||
text-indent: 5px;
|
||||
opacity: .7;
|
||||
border: 1px solid transparent;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
left: calc(50% - #{$playBtnWidth/2});
|
||||
|
||||
transition: .3s;
|
||||
|
||||
&:hover {
|
||||
|
@ -127,6 +149,10 @@
|
|||
&:hover {
|
||||
color: $colorHighlight;
|
||||
}
|
||||
|
||||
.as-list & {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue