add context menu to suggestions

This commit is contained in:
vapormusic 2022-09-08 18:07:51 +07:00
parent f3e97f03ba
commit 9bbbb6d276
11 changed files with 417 additions and 97 deletions

View file

@ -90,6 +90,7 @@ export class BrowserWindow {
"components/equalizer", "components/equalizer",
"components/add-to-playlist", "components/add-to-playlist",
"components/queue", "components/queue",
"components/smarthints",
"components/mediaitem-scroller-horizontal", "components/mediaitem-scroller-horizontal",
"components/mediaitem-scroller-horizontal-large", "components/mediaitem-scroller-horizontal-large",
"components/mediaitem-scroller-horizontal-sp", "components/mediaitem-scroller-horizontal-sp",

View file

@ -42,6 +42,7 @@
"components/moreinfo-modal", "components/moreinfo-modal",
"components/equalizer", "components/equalizer",
"components/add-to-playlist", "components/add-to-playlist",
"components/smarthints",
"components/queue", "components/queue",
"components/mediaitem-scroller-horizontal", "components/mediaitem-scroller-horizontal",
"components/mediaitem-scroller-horizontal-large", "components/mediaitem-scroller-horizontal-large",

View file

@ -397,7 +397,7 @@ const CiderAudio = {
constructor() { constructor() {
super(); super();
this._bufferSize = 1024; this._bufferSize = 2048;
this._buffers = null; this._buffers = null;
this._initBuffer(); this._initBuffer();
} }

View file

@ -159,6 +159,7 @@ const app = new Vue({
miniTmpY: "", miniTmpY: "",
tmpVar: [], tmpVar: [],
notification: false, notification: false,
hintscontext: false,
chrome: { chrome: {
sidebarCollapsed: false, sidebarCollapsed: false,
nativeControls: false, nativeControls: false,

View file

@ -279,7 +279,7 @@
<div class="search-input--icon"></div> <div class="search-input--icon"></div>
<input type="search" spellcheck="false" @click="$root.appRoute('search');search.showHints = true" <input type="search" spellcheck="false" @click="$root.appRoute('search');search.showHints = true"
@focus="search.showHints = true" @focus="search.showHints = true"
@blur="setTimeout(()=>{search.showHints = false}, 300)" @blur="setTimeout(()=>{if(hintscontext != true){search.showHints = false} }, 300)"
v-on:keyup.enter="searchQuery(search.hints[search.cursor].content ?? search.hints[search.cursor].searchTerm);search.showHints = false;search.cursor = -1" @change="$root.appRoute('search');" v-on:keyup.enter="searchQuery(search.hints[search.cursor].content ?? search.hints[search.cursor].searchTerm);search.showHints = false;search.cursor = -1" @change="$root.appRoute('search');"
v-on:keyup="searchCursor" v-on:keyup="searchCursor"
@input="getSearchHints()" @input="getSearchHints()"
@ -293,34 +293,7 @@
{{ hint.displayTerm }} {{ hint.displayTerm }}
</button> </button>
<template v-for="(item, position) in search.hints.filter((a) => {return a.content != null})"> <template v-for="(item, position) in search.hints.filter((a) => {return a.content != null})">
<div class="cd-queue-item" @click="search.showHints = false;routeView(item.content);search.cursor = -1" <mediaitem-smarthints :item="item.content" :position="position"> </mediaitem-smarthints>
:class="{'hintactive': (search.cursor == position + search.hints.filter((a) => {return a.content == null}).length)}">
<div class="row">
<div class="col-auto cider-flex-center">
<div class="artwork" :class="{'circle': item.content.type == 'artists'}">
<mediaitem-artwork
:url="item.content.attributes.artwork ? item.content.attributes.artwork.url : ''"
:size="32"></mediaitem-artwork>
</div>
</div>
<div class="col queue-info">
<div class="queue-title text-overflow-elipsis">{{ item.content.attributes.name }}
</div>
<div class="queue-subtitle text-overflow-elipsis">{{
item.content.attributes.artistName }}
</div>
</div>
<div class="queue-explicit-icon cider-flex-center"
v-if="item.content.attributes.contentRating == 'explicit'">
<div class="explicit-icon"></div>
</div>
<!-- <div class="col queue-duration-info">
<div class="queue-duration cider-flex-center">
{{convertTimeToString(item.content.attributes.durationInMillis)}}
</div>
</div> -->
</div>
</div>
</template> </template>
</div> </div>
</div> </div>

View file

@ -576,7 +576,7 @@ Vue.component('mediaitem-square', {
icon: "./assets/feather/play.svg", icon: "./assets/feather/play.svg",
name: app.getLz('action.startRadio'), name: app.getLz('action.startRadio'),
action: () => { action: () => {
app.mk.setStationQueue({ artist: this.item.id }).then(() => { app.mk.setStationQueue({ artist: 'a-'+this.item.id }).then(() => {
app.mk.play() app.mk.play()
}) })
} }
@ -586,7 +586,7 @@ Vue.component('mediaitem-square', {
icon: "./assets/feather/share.svg", icon: "./assets/feather/share.svg",
name: app.getLz('term.share'), name: app.getLz('term.share'),
action: () => { action: () => {
self.app.copyToClipboard(this.item.id.attributes.url) self.app.copyToClipboard(this.item.attributes.url)
} }
}, },
{ {

View file

@ -1,5 +1,5 @@
<script type="text/x-template" id="cider-menu-panel"> <script type="text/x-template" id="cider-menu-panel">
<div class="menu-panel" @click.self="menuPanel.visible = false" @contextmenu.self="menuPanel.visible = false"> <div class="menu-panel" @click.self="menuPanel.visible = false; if($root.hintscontext){$root.hintscontext = false;focusOther()}" @contextmenu.self="menuPanel.visible = false; if($root.hintscontext){$root.hintscontext = false;focusOther()}">
<div class="menu-panel-body" ref="menubody" :style="elStyle" :class="getBodyClasses()"> <div class="menu-panel-body" ref="menubody" :style="elStyle" :class="getBodyClasses()">
<div class="menu-header-text" v-if="content.name != ''"> <div class="menu-header-text" v-if="content.name != ''">
@ -56,12 +56,22 @@
mounted() { mounted() {
if (this.event) { if (this.event) {
this.position = [this.event.clientX, this.event.clientY]; this.position = [this.event.clientX, this.event.clientY];
} this.$nextTick(() => {
this.$nextTick(() => {
// this.size = [document.querySelector(".menu-panel-body").offsetWidth, document.querySelector(".menu-panel-body").offsetHeight]; // this.size = [document.querySelector(".menu-panel-body").offsetWidth, document.querySelector(".menu-panel-body").offsetHeight];
// ugly hack // ugly hack
setTimeout(this.getStyle, 1) setTimeout(this.getStyle, 0.8)
}); });
}
else {
document.addEventListener('mouseover', event => {
this.event = event
this.position = [event.clientX, event.clientY]
console.log("pos", this.position)
this.$nextTick(() => {
setTimeout(this.getStyle, 0.8)})
},{once: true})
}
}, },
methods: { methods: {
getBodyClasses() { getBodyClasses() {
@ -78,6 +88,9 @@
return "active"; return "active";
} }
}, },
focusOther(){
document.querySelector('.search-input-container input').focus()
},
getStyle() { getStyle() {
let style = {} let style = {}
this.size = [this.$refs.menubody.offsetWidth, this.$refs.menubody.offsetHeight]; this.size = [this.$refs.menubody.offsetWidth, this.$refs.menubody.offsetHeight];
@ -132,7 +145,7 @@
action(item) { action(item) {
item.action() item.action()
if (!item["keepOpen"]) { if (!item["keepOpen"]) {
this.menuPanel.visible = false this.menuPanel.visible = false;if(app.hintscontext){ app.hintscontext = false; document.querySelector('.search-input-container input').focus(); app.search.showHints = false}
} }
} }
} }

View file

@ -9,7 +9,7 @@
spellcheck="false" spellcheck="false"
@click="$root.appRoute('search');$root.search.showHints = true" @click="$root.appRoute('search');$root.search.showHints = true"
@focus="$root.search.showHints = true" @focus="$root.search.showHints = true"
@blur="$root.setTimeout(()=>{$root.search.showHints = false}, 300)" @blur="$root.setTimeout(()=>{if($root.hintscontext != true){$root.search.showHints = false} }, 300)"
v-on:keyup.enter="$root.searchQuery($root.search.hints[$root.search.cursor].content ?? $root.search.hints[$root.search.cursor].searchTerm);$root.search.showHints = false;$root.search.cursor = -1" v-on:keyup.enter="$root.searchQuery($root.search.hints[$root.search.cursor].content ?? $root.search.hints[$root.search.cursor].searchTerm);$root.search.showHints = false;$root.search.cursor = -1"
v-on:keyup="$root.searchCursor" v-on:keyup="$root.searchCursor"
@change="$root.appRoute('search');" @change="$root.appRoute('search');"
@ -33,34 +33,7 @@
{{ hint.displayTerm }} {{ hint.displayTerm }}
</button> </button>
<template v-for="(item, position) in $root.search.hints.filter((a) => {return a.content != null})"> <template v-for="(item, position) in $root.search.hints.filter((a) => {return a.content != null})">
<div class="cd-queue-item" @click="$root.search.showHints = false;$root.routeView(item.content);$root.search.cursor = -1" <mediaitem-smarthints :item="item.content" :position="position"> </mediaitem-smarthints>
:class="{'hintactive': ($root.search.cursor == position + $root.search.hints.filter((a) => {return a.content == null}).length)}">
<div class="row">
<div class="col-auto cider-flex-center">
<div class="artwork" :class="{'circle': item.content.type == 'artists'}">
<mediaitem-artwork
:url="item.content.attributes.artwork ? item.content.attributes.artwork.url : ''"
:size="32"></mediaitem-artwork>
</div>
</div>
<div class="col queue-info">
<div class="queue-title text-overflow-elipsis">{{ item.content.attributes.name }}
</div>
<div class="queue-subtitle text-overflow-elipsis">{{
item.content.attributes.artistName }}
</div>
</div>
<div class="queue-explicit-icon cider-flex-center"
v-if="item.content.attributes.contentRating == 'explicit'">
<div class="explicit-icon"></div>
</div>
<!-- <div class="col queue-duration-info">
<div class="queue-duration cider-flex-center">
{{convertTimeToString(item.content.attributes.durationInMillis)}}
</div>
</div> -->
</div>
</div>
</template> </template>
</div> </div>
</div> </div>

View file

@ -0,0 +1,382 @@
<script type="text/x-template" id="mediaitem-smarthints">
<div class="cd-queue-item" @click="$root.search.showHints = false;$root.routeView(item);$root.search.cursor = -1;$root.search.term == ''" @contextmenu="$root.hintscontext = true;getContextMenu()"
:class="{'hintactive': ($root.search.cursor == position + $root.search.hints.filter((a) => {return a.content == null}).length)}">
<div class="row" @contextmenu="$root.hintscontext = true;getContextMenu()">
<div class="col-auto cider-flex-center" @contextmenu="$root.hintscontext = true;getContextMenu()">
<div class="artwork" :class="{'circle': item.type == 'artists'}">
<mediaitem-artwork
:url="item.attributes.artwork ? item.attributes.artwork.url : ''"
:size="32"></mediaitem-artwork>
</div>
</div>
<div class="col queue-info" @contextmenu="$root.hintscontext = true;getContextMenu()">
<div class="queue-title text-overflow-elipsis">{{ item.attributes.name }}
</div>
<div class="queue-subtitle text-overflow-elipsis">{{
item.attributes.artistName }}
</div>
</div>
<div class="queue-explicit-icon cider-flex-center"
v-if="item.attributes.contentRating == 'explicit'">
<div class="explicit-icon"></div>
</div>
<!-- <div class="col queue-duration-info">
<div class="queue-duration cider-flex-center">
{{convertTimeToString(item.content.attributes.durationInMillis)}}
</div>
</div> -->
</div>
</div>
</script>
<script>
Vue.component('mediaitem-smarthints', {
template: '#mediaitem-smarthints',
props: {
item: {
type: Object,
required: true
},
position: {
type: Number,
required: true
}
},
data: function () {
return {
app: this.$root,
guid: this.uuidv4(),
}
},
async mounted() {
},
methods: {
uuidv4() {
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
);
},
getContextMenu(event) {
if (event){
if (this.item.type === "artists") {
return this.artistMenu(event)
} else {
return this.contextMenu(event)
}
} else {
document.addEventListener('mouseover', event => {
if (this.item.type === "artists") {
return this.artistMenu(event)
} else {
return this.contextMenu(event)
}
},{once: true})}
},
async contextMenu(event) {
let self = this
let useMenu = "normal"
if (app.selectedMediaItems.length <= 1) {
app.selectedMediaItems = []
app.select_selectMediaItem(this.item.attributes.playParams.id ?? this.item.id, this.item.attributes.playParams.kind ?? this.item.type, this.index, this.guid, this.item.attributes.playParams.isLibrary ?? false)
} else {
useMenu = "multiple"
}
let menus = {
multiple: {
items: [
{
name: app.getLz('action.playTracksNext').replace("${app.selectedMediaItems.length}", app.selectedMediaItems.length),
"icon": "./assets/arrow-bend-up.svg",
action: () => {
let itemsToPlay = {}
app.selectedMediaItems.forEach(item => {
if (!itemsToPlay[item.kind]) {
itemsToPlay[item.kind] = []
}
itemsToPlay[item.kind].push(item.id)
})
// loop through itemsToPlay
for (let kind in itemsToPlay) {
let ids = itemsToPlay[kind]
if (ids.length > 0) {
app.mk.playNext({ [kind + "s"]: itemsToPlay[kind] })
}
}
console.log(itemsToPlay)
app.selectedMediaItems = []
}
},
{
name: app.getLz('action.playTracksLater').replace("${app.selectedMediaItems.length}", app.selectedMediaItems.length),
"icon": "./assets/arrow-bend-down.svg",
action: () => {
let itemsToPlay = {}
app.selectedMediaItems.forEach(item => {
if (!itemsToPlay[item.kind]) {
itemsToPlay[item.kind] = []
}
itemsToPlay[item.kind].push(item.id)
})
// loop through itemsToPlay
for (let kind in itemsToPlay) {
let ids = itemsToPlay[kind]
if (ids.length > 0) {
app.mk.playLater({ [kind + "s"]: itemsToPlay[kind] })
}
}
app.selectedMediaItems = []
}
},
]
},
normal: {
headerItems: [
{
"icon": "./assets/feather/heart.svg",
"id": "love",
"name": app.getLz('action.love'),
"hidden": false,
"disabled": true,
"action": function () {
app.love(self.item)
}
},
{
"icon": "./assets/feather/heart.svg",
"id": "unlove",
"active": true,
"name": app.getLz('action.unlove'),
"hidden": true,
"action": function () {
app.unlove(self.item)
}
},
{
"icon": "./assets/feather/thumbs-down.svg",
"id": "dislike",
"name": app.getLz('action.dislike'),
"hidden": false,
"disabled": true,
"action": function () {
app.dislike(self.item)
}
},
{
"icon": "./assets/feather/thumbs-down.svg",
"id": "undo_dislike",
"name": app.getLz('action.undoDislike'),
"active": true,
"hidden": true,
"action": function () {
app.unlove(self.item)
}
},
],
items: [
{
"icon": "./assets/feather/list.svg",
"id": "addToPlaylist",
"name": app.getLz('action.addToPlaylist'),
"action": function () {
app.promptAddToPlaylist()
}
},
{
"id": "addToLibrary",
"icon": "./assets/feather/plus.svg",
"name": app.getLz('action.addToLibrary'),
"hidden": false,
"disabled": true,
"action": function () {
let item_id = self.item.attributes.playParams.id ?? self.item.id;
let data_type = self.item.attributes.playParams.kind ?? self.item.type;
app.addToLibrary(item_id);
self.addedToLibrary = true;
}
},
{
"id": "removeFromLibrary",
"icon": "./assets/feather/x-circle.svg",
"name": app.getLz('action.removeFromLibrary'),
"hidden": true,
"action": async function () {
console.log("remove");
let item_id = self.item.attributes.playParams.id ?? self.item.id;
let data_type = self.item.attributes.playParams.kind ?? self.item.type;
await self.removeFromLibrary(item_id);
self.addedToLibrary = false
}
},
{
"name": app.getLz('action.playNext'),
"icon": "./assets/arrow-bend-up.svg",
"action": function () {
app.mk.playNext({ [self.item.attributes.playParams.kind ?? self.item.type]: self.item.attributes.playParams.id ?? self.item.id })
app.mk.queue._reindex()
app.selectedMediaItems = []
}
},
{
"name": app.getLz('action.playLater'),
"icon": "./assets/arrow-bend-down.svg",
"action": function () {
app.mk.playLater({ [self.item.attributes.playParams.kind ?? self.item.type]: self.item.attributes.playParams.id ?? self.item.id })
app.mk.queue._reindex()
app.selectedMediaItems = []
}
},
{
"icon": "./assets/feather/share.svg",
"name": app.getLz('action.share'),
"action": function () {
if (!self.item.attributes.url && self.item.relationships) {
if (self.item.relationships.catalog) {
app.mkapi(self.item.attributes.playParams.kind, false, self.item.relationships.catalog.data[0].id).then(u => {
self.app.copyToClipboard((u.data.data.length && u.data.data.length > 0) ? u.data.data[0].attributes.url : u.data.data.attributes.url)
})
}
} else {
self.app.copyToClipboard(self.item.attributes.url)
}
}
},
{
"icon": "./assets/feather/share.svg",
"name": `${app.getLz('action.share')} (song.link)`,
"action": function () {
if (!self.item.attributes.url && self.item.relationships) {
if (self.item.relationships.catalog) {
app.mkapi(self.item.attributes.playParams.kind, false, self.item.relationships.catalog.data[0].id).then(u => {
self.app.songLinkShare((u.data.data.length && u.data.data.length > 0) ? u.data.data[0].attributes.url : u.data.data.attributes.url)
})
}
} else {
self.app.songLinkShare(self.item.attributes.url)
}
}
}
]
}
}
if ((self.item.attributes.playParams.kind ?? self.item.type).includes("playlist")) {
// remove the add to playlist option by id "addToPlaylist" using the .filter() method
menus.normal.items = menus.normal.items.filter(function (item) {
return item.id != "addToPlaylist"
})
}
app.showMenuPanel(menus[useMenu], event)
try {
await this.isInLibrary().then((_) => {
if (self.addedToLibrary) {
menus.normal.items.find(x => x.id == 'addToLibrary').hidden = true
menus.normal.items.find(x => x.id == 'removeFromLibrary').hidden = false
} else {
menus.normal.items.find(x => x.id == 'addToLibrary').disabled = false
}
})
} catch (e) {
}
try {
let rating = await app.getRating(self.item)
if (rating == 0) {
menus.normal.headerItems.find(x => x.id == 'love').disabled = false
menus.normal.headerItems.find(x => x.id == 'dislike').disabled = false
} else if (rating == 1) {
menus.normal.headerItems.find(x => x.id == 'unlove').hidden = false
menus.normal.headerItems.find(x => x.id == 'love').hidden = true
} else if (rating == -1) {
menus.normal.headerItems.find(x => x.id == 'undo_dislike').hidden = false
menus.normal.headerItems.find(x => x.id == 'dislike').hidden = true
}
} catch (err) {
}
if (this.contextExt) {
if (this.contextExt.normal) {
menus.normal.items = menus.normal.items.concat(this.contextExt.normal)
}
if (this.contextExt.multiple) {
menus.multiple.items = menus.multiple.items.concat(this.contextExt.multiple)
}
}
},
async artistMenu(event) {
let self = this
let followAction = "follow"
let followActions = {
follow: {
icon: "./assets/star.svg",
name: app.getLz('action.favorite'),
action: () => {
self.$root.setArtistFavorite(this.item.id, true)
}
},
unfollow: {
icon: "./assets/star.svg",
name: app.getLz('action.removeFavorite'),
action: () => {
self.$root.setArtistFavorite(this.item.id, false)
}
}
}
if (self.app.cfg.home.followedArtists.includes(this.item.id)) {
followAction = "unfollow"
}
app.showMenuPanel({
items: [
{
icon: "./assets/feather/play.svg",
name: app.getLz('action.startRadio'),
action: () => {
app.mk.setStationQueue({ artist: 'a-'+this.item.id }).then(() => {
app.mk.play()
})
}
},
followActions[followAction],
{
icon: "./assets/feather/share.svg",
name: app.getLz('term.share'),
action: () => {
self.app.copyToClipboard(this.item.attributes.url)
}
},
{
icon: "./assets/feather/external-link.svg",
name: app.getLz('action.openArtworkInBrowser'),
action: () => {
window.open(app.getMediaItemArtwork(this.getArtworkUrl(), 1024, 1024))
}
},
]
}, event)
},
getArtworkUrl(size = -1, includeUrl = false) {
let artwork = this.item.attributes.artwork ? this.item.attributes.artwork.url : ''
if (size != -1) {
artwork = artwork.replace('{w}', size).replace('{h}', size).replace('{f}', "webp").replace('{c}', ((size === 900) ? "sr" : "cc"))
}
switch (this.kind) {
case "385":
artwork = this.item.attributes?.editorialArtwork?.subscriptionHero?.url
break;
}
if (!includeUrl) {
return artwork
} else {
return `url("${artwork}")`
}
},
},
beforeDestroy: function () {
// this.item = null;
// this.kind = null;
// this.size = null;
}
});
</script>

View file

@ -23,8 +23,10 @@
<hr> <hr>
<div class="row"> <div class="row">
<div class="col"> <div class="col">
<h4>{{ convertToHours(loaded.attributes.listenTimeInMinutes) }} <h4 @click="hourshow = !hourshow">{{convertToHours(loaded.attributes.listenTimeInMinutes)}}
{{$root.getLz('term.time.hours')}}</h4> {{$root.getLz('term.time.hours')}}
{{hourshow ? "" : (loaded.attributes.listenTimeInMinutes % 60) }}
{{hourshow ? "" : $root.getLz('term.time.minutes')}}</h4>
<h4>{{ loaded.attributes.uniqueAlbumCount }} {{$root.getLz('term.uniqueAlbums')}}</h4> <h4>{{ loaded.attributes.uniqueAlbumCount }} {{$root.getLz('term.uniqueAlbums')}}</h4>
<h4>{{ loaded.attributes.uniqueArtistCount }} {{$root.getLz('term.uniqueArtists')}}</h4> <h4>{{ loaded.attributes.uniqueArtistCount }} {{$root.getLz('term.uniqueArtists')}}</h4>
<h4>{{ loaded.attributes.uniqueSongCount }} {{$root.getLz('term.uniqueSongs')}}</h4> <h4>{{ loaded.attributes.uniqueSongCount }} {{$root.getLz('term.uniqueSongs')}}</h4>
@ -101,6 +103,7 @@
loaded: { loaded: {
id: -1 id: -1
}, },
hourshow: true,
musicTypeGenre: "" musicTypeGenre: ""
} }
}, },

View file

@ -3,7 +3,7 @@
<div class="search-input-container fs-search" v-if="$root.appMode == 'fullscreen'"> <div class="search-input-container fs-search" v-if="$root.appMode == 'fullscreen'">
<div class="search-input--icon"></div> <div class="search-input--icon"></div>
<input type="search" spellcheck="false" @focus="$root.search.showHints = true" <input type="search" spellcheck="false" @focus="$root.search.showHints = true"
@blur="$root.setTimeout(()=>{$root.search.showHints = false}, 300)" @blur="$root.setTimeout(()=>{if($root.hintscontext != true){$root.search.showHints = false} }, 300)"
v-on:keyup.enter="$root.searchQuery($root.search.hints[$root.search.cursor].content ?? $root.search.hints[$root.search.cursor].searchTerm);$root.search.showHints = false" @input="$root.getSearchHints()" v-on:keyup.enter="$root.searchQuery($root.search.hints[$root.search.cursor].content ?? $root.search.hints[$root.search.cursor].searchTerm);$root.search.showHints = false" @input="$root.getSearchHints()"
:placeholder="$root.getLz('term.search') + '...'" v-model="$root.search.term" :placeholder="$root.getLz('term.search') + '...'" v-model="$root.search.term"
class="search-input" /> class="search-input" />
@ -15,34 +15,7 @@
{{ hint.displayTerm }} {{ hint.displayTerm }}
</button> </button>
<template v-for="(item, position) in $root.search.hints.filter((a) => {return a.content != null})"> <template v-for="(item, position) in $root.search.hints.filter((a) => {return a.content != null})">
<div class="cd-queue-item" @click="$root.search.showHints = false;$root.routeView(item.content);$root.search.cursor = -1" <mediaitem-smarthints :item="item.content" :position="position"> </mediaitem-smarthints>
:class="{'hintactive': ($root.search.cursor == position + $root.search.hints.filter((a) => {return a.content == null}).length)}">
<div class="row">
<div class="col-auto cider-flex-center">
<div class="artwork" :class="{'circle': item.content.type == 'artists'}">
<mediaitem-artwork
:url="item.content.attributes.artwork ? item.content.attributes.artwork.url : ''"
:size="32"></mediaitem-artwork>
</div>
</div>
<div class="col queue-info">
<div class="queue-title text-overflow-elipsis">{{ item.content.attributes.name }}
</div>
<div class="queue-subtitle text-overflow-elipsis">{{
item.content.attributes.artistName }}
</div>
</div>
<div class="queue-explicit-icon cider-flex-center"
v-if="item.content.attributes.contentRating == 'explicit'">
<div class="explicit-icon"></div>
</div>
<!-- <div class="col queue-duration-info">
<div class="queue-duration cider-flex-center">
{{convertTimeToString(item.content.attributes.durationInMillis)}}
</div>
</div> -->
</div>
</div>
</template> </template>
</div> </div>