Merge branch 'develop'
This commit is contained in:
commit
df2f7b7216
195 changed files with 62285 additions and 12895 deletions
|
@ -12,7 +12,7 @@
|
|||
<div class="icon"><%- include("../svg/plus.svg") %></div>
|
||||
<div class="name">{{app.getLz('action.createPlaylist')}}</div>
|
||||
</button>
|
||||
<sidebar-playlist :playlist-select="playlistSelect" v-for="item in $root.getPlaylistFolderChildren('p.playlistsroot')" :item="item">
|
||||
<sidebar-playlist :playlist-select="playlistSelect" :relate-media-items="relateItems" v-for="item in $root.getPlaylistFolderChildren('p.playlistsroot')" :item="item">
|
||||
</sidebar-playlist>
|
||||
</div>
|
||||
<div class="modal-search">
|
||||
|
@ -42,6 +42,7 @@
|
|||
searchQuery: "",
|
||||
focused: "",
|
||||
app: this.$root,
|
||||
relateItems: []
|
||||
}
|
||||
},
|
||||
props: {
|
||||
|
@ -51,6 +52,7 @@
|
|||
}
|
||||
},
|
||||
mounted() {
|
||||
this.relateItems = [this.$root.selectedMediaItems[0].id]
|
||||
this.search()
|
||||
this.$refs.searchInput.focus()
|
||||
this.$refs.searchInput.addEventListener('keydown', (e) => {
|
||||
|
|
|
@ -57,9 +57,32 @@
|
|||
platformInfo: {requiresCDMAttachOnStart: !0, maxSecurityLevel: d, keySystemConfig: h},
|
||||
appData: {serviceName: "Apple Music"}
|
||||
}
|
||||
|
||||
this.hls.attachMedia(this.$refs.video);
|
||||
this.hls.loadSource(this.video);
|
||||
this.hls.loadLevel = parseInt(app.cfg.visual.animated_artwork_qualityLevel || 1);
|
||||
let u = this.hls;
|
||||
var quality = app.cfg.visual.animated_artwork_qualityLevel;
|
||||
setTimeout(() => {
|
||||
let levelsnum = u.levels.map((level)=>{return level.width})
|
||||
if (levelsnum.length > 0) {
|
||||
let qualities = []
|
||||
let qualities2 = []
|
||||
for (let i = 0; i < levelsnum.length; i++) {
|
||||
if (qualities2.indexOf(levelsnum[i]) == -1) {
|
||||
qualities.push({level: i, quality: levelsnum[i]})
|
||||
qualities2.push(levelsnum[i])
|
||||
}
|
||||
}
|
||||
let actualnum = Math.floor(qualities[qualities.length -1 ].level * (quality / 4))
|
||||
if (quality != 0 ){
|
||||
quality = qualities[Math.min(actualnum,qualities.length -1 )].level
|
||||
}
|
||||
if (quality == 4 ){
|
||||
quality = qualities[qualities.length - 1].level
|
||||
}
|
||||
}
|
||||
try{
|
||||
this.hls.loadLevel = parseInt( quality || 1);} catch(e){}},200)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
45
src/renderer/views/components/artist-chip.ejs
Normal file
45
src/renderer/views/components/artist-chip.ejs
Normal file
|
@ -0,0 +1,45 @@
|
|||
<script type="text/x-template" id="artist-chip">
|
||||
<div class="artist-chip" @click.self="route" tabindex="0">
|
||||
<div class="artist-chip__image">
|
||||
<mediaitem-artwork v-if="artist.id != null" :url="artist.attributes.artwork.url" :size="32"></mediaitem-artwork>
|
||||
</div>
|
||||
<div class="artist-chip__name">
|
||||
<span>{{ item.attributes.name }}</span>
|
||||
</div>
|
||||
<button @click="$root.followArtistById(artist.id, true)" title="Follow" v-if="!$root.followingArtist(artist.id)" class="artist-chip__follow codicon codicon-add"></button>
|
||||
<button @click="$root.followArtistById(artist.id, false)" title="Following" v-else class="artist-chip__follow codicon codicon-check"></button>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('artist-chip', {
|
||||
props: {
|
||||
item: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data: function() {
|
||||
return {
|
||||
artist: {
|
||||
id: null
|
||||
}
|
||||
}
|
||||
},
|
||||
template: '#artist-chip',
|
||||
async mounted() {
|
||||
let artistId = this.item.id
|
||||
if(typeof this.item.relationships.catalog == "object") {
|
||||
artistId = this.item.relationships.catalog.data[0].id
|
||||
}
|
||||
app.mk.api.v3.music(`/v1/catalog/${app.mk.storefrontId}/artists/${artistId}`).then(response => {
|
||||
this.artist = response.data.data[0];
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
route() {
|
||||
app.appRoute(`artist/${this.artist.id}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
87
src/renderer/views/components/audio-controls.ejs
Normal file
87
src/renderer/views/components/audio-controls.ejs
Normal file
|
@ -0,0 +1,87 @@
|
|||
<script type="text/x-template" id="audio-controls">
|
||||
<div class="modal-fullscreen addtoplaylist-panel" @click.self="app.resetState()"
|
||||
@contextmenu.self="app.resetState()">
|
||||
<div class="modal-window">
|
||||
<div class="modal-header">
|
||||
<div class="modal-title">{{app.getLz('term.audioControls')}}</div>
|
||||
<button class="close-btn" @click="app.resetState()"></button>
|
||||
</div>
|
||||
<div class="modal-content">
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
{{app.getLz('term.volume')}}
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto percent">
|
||||
<input type="number"
|
||||
style="width: 100%; text-align: center; margin-right: 5px;" min="0"
|
||||
step="5" v-model="volume"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
{{app.getLz('settings.option.audio.volumeStep')}}
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto percent">
|
||||
<input type="number" style="width: 100%; text-align: center; margin-right: 5px;" min="0"
|
||||
v-model="volumeStep"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
{{app.getLz('settings.option.audio.maxVolume')}}
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto percent">
|
||||
<input type="number" style="width: 100%; text-align: center; margin-right: 5px;" min="0"
|
||||
v-model="maxVolume"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('audio-controls', {
|
||||
template: '#audio-controls',
|
||||
data: function () {
|
||||
return {
|
||||
app: this.$root,
|
||||
maxVolume: this.$root.cfg.audio.maxVolume * 100,
|
||||
volumeStep: this.$root.cfg.audio.volumeStep * 100,
|
||||
volume: this.$root.cfg.audio.volume * 100
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
maxVolume: function (newValue, _oldValue) {
|
||||
if (newValue > 100) {
|
||||
newValue = 100
|
||||
} else {
|
||||
newValue = Math.round(newValue)
|
||||
}
|
||||
this.$root.cfg.audio.maxVolume = newValue / 100
|
||||
this.maxVolume = newValue
|
||||
console.log(newValue, _oldValue)
|
||||
},
|
||||
volume: function (newValue, _oldValue) {
|
||||
if (newValue > this.maxVolume) {
|
||||
newValue = 100
|
||||
} else {
|
||||
newValue = Math.round(newValue)
|
||||
}
|
||||
this.$root.mk.volume = newValue / 100
|
||||
this.volume = newValue
|
||||
console.log(newValue, _oldValue)
|
||||
},
|
||||
volumeStep: function (newValue, _oldValue) {
|
||||
if (newValue > this.maxVolume) {
|
||||
newValue = 100
|
||||
} else {
|
||||
newValue = Math.round(newValue)
|
||||
}
|
||||
this.$root.cfg.audio.volumeStep = newValue / 100
|
||||
this.volumeStep = newValue
|
||||
console.log(newValue, _oldValue)
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
|
@ -13,10 +13,20 @@
|
|||
<div class="name">{{app.getLz('term.equalizer')}}</div>
|
||||
</button>
|
||||
<button class="playlist-item"
|
||||
@click="openSpacialAudio()" style="width:100%;">
|
||||
@click="openSpatialAudio()" style="width:100%;">
|
||||
<div class="icon"><%- include("../svg/speaker.svg") %></div>
|
||||
<div class="name">{{app.getLz('settings.option.audio.enableAdvancedFunctionality.audioSpatialization')}}</div>
|
||||
</button>
|
||||
<button class="playlist-item"
|
||||
@click="openAudioControls" style="width:100%;">
|
||||
<div class="icon"><%- include("../svg/speaker.svg") %></div>
|
||||
<div class="name">{{app.getLz('term.audioControls')}}</div>
|
||||
</button>
|
||||
<button class="playlist-item"
|
||||
@click="$root.appRoute('audiolabs')" style="width:100%;">
|
||||
<div class="icon"><%- include("../svg/speaker.svg") %></div>
|
||||
<div class="name">{{app.getLz('settings.option.audio.audioLab')}}</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -38,14 +48,19 @@
|
|||
app.modals.equalizer = true
|
||||
app.modals.audioSettings = false
|
||||
},
|
||||
openSpacialAudio() {
|
||||
if(app.cfg.audio.spatial) {
|
||||
openSpatialAudio() {
|
||||
if(app.cfg.audio.spatial === true && app.cfg.audio.maikiwiAudio.spatial === false) {
|
||||
app.modals.spatialProperties = true
|
||||
app.modals.audioSettings = false
|
||||
} else {
|
||||
notyf.error(app.getLz('spatial.notTurnedOn'))
|
||||
}
|
||||
},
|
||||
openAudioControls() {
|
||||
app.modals.audioControls = true
|
||||
app.modals.audioSettings = false
|
||||
},
|
||||
},
|
||||
}
|
||||
});
|
||||
);
|
||||
</script>
|
107
src/renderer/views/components/castmenu.ejs
Normal file
107
src/renderer/views/components/castmenu.ejs
Normal file
|
@ -0,0 +1,107 @@
|
|||
<script type="text/x-template" id="castmenu">
|
||||
<div class="spatialproperties-panel castmenu modal-fullscreen" >
|
||||
<div class="modal-window">
|
||||
<div class="modal-header">
|
||||
<div class="modal-title">Cast To Devices</div>
|
||||
<button class="close-btn" @click="close()"></button>
|
||||
</div>
|
||||
<div class="modal-content" style="overflow-y: overlay; padding: 3%">
|
||||
<div class="md-labeltext">Chromecast</div>
|
||||
<div class="md-option-container" style="margin-top: 12px;margin-bottom: 12px;">
|
||||
<template v-if="!scanning">
|
||||
<template v-for="(device) in devices.cast">
|
||||
<div class="md-option-line" style="cursor: pointer" @click="setCast(device)">
|
||||
<div class="md-option-segment">
|
||||
{{ device.name }}
|
||||
<br>
|
||||
<small>{{ device.host }}</small>
|
||||
</div>
|
||||
<div class="md-option-segment_auto" style="display: flex;justify-content: center;align-items: center" v-if="activeCasts.includes(device)">
|
||||
Connected
|
||||
</div>
|
||||
<div class="md-option-segment_auto" v-else style="display: flex;justify-content: center;align-items: center">
|
||||
<svg width="20" height="20" viewBox="0 0 34 34" fill="#fff" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" class="castPlayIndicator"><path d="M28.228,18.327l-16.023,8.983c-0.99,0.555 -2.205,-0.17 -2.205,-1.318l0,-17.984c0,-1.146 1.215,-1.873 2.205,-1.317l16.023,8.982c1.029,0.577 1.029,2.077 0,2.654Z" style="fill-rule:nonzero"></path></svg>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="md-option-line" style="cursor: pointer">
|
||||
<div class="md-option-segment">
|
||||
Scanning...
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class="md-labeltext" style="opacity:0.5;">AirPlay</div>
|
||||
<div class="md-option-container" style="margin-top: 12px;margin-bottom: 12px;opacity:0.5;">
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
AirPlay is still under development
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-footer">
|
||||
<div class="row">
|
||||
<div class="col" v-if="activeCasts.length != 0">
|
||||
<button style="width:100%" @click="stopCasting()" class="md-btn md-btn-block md-btn-primary">Stop casting to all devices</button>
|
||||
</div>
|
||||
<div class="col">
|
||||
<button style="width:100%" class="md-btn md-btn-block" @click="scan()">Scan</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
<script>
|
||||
Vue.component('castmenu', {
|
||||
template: '#castmenu',
|
||||
data: function () {
|
||||
return {
|
||||
devices: {
|
||||
cast: [],
|
||||
airplay: []
|
||||
},
|
||||
scanning: false,
|
||||
activeCasts: this.$root.activeCasts,
|
||||
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.scan();
|
||||
},
|
||||
watch:{
|
||||
activeCasts: function (newVal, oldVal) {
|
||||
this.$root.activeCasts = this.activeCasts;
|
||||
}},
|
||||
methods: {
|
||||
close() {
|
||||
this.$root.modals.castMenu = false
|
||||
},
|
||||
scan() {
|
||||
let self = this;
|
||||
this.scanning = true;
|
||||
ipcRenderer.send('getChromeCastDevices', '');
|
||||
setTimeout(() => {
|
||||
self.devices.cast = ipcRenderer.sendSync("getKnownCastDevices");
|
||||
self.scanning = false;
|
||||
}, 2000);
|
||||
console.log(this.devices);
|
||||
// vm.$forceUpdate();
|
||||
},
|
||||
setCast(device) {
|
||||
CiderAudio.sendAudio();
|
||||
this.activeCasts.push(device);
|
||||
ipcRenderer.send('performGCCast', device, "Cider", "Playing ...", "Test build", '');
|
||||
},
|
||||
stopCasting() {
|
||||
CiderAudio.stopAudio();
|
||||
ipcRenderer.send('stopGCast', '');
|
||||
this.activeCasts = [];
|
||||
// vm.$forceUpdate();
|
||||
},
|
||||
}
|
||||
});
|
||||
</script>
|
|
@ -5,11 +5,11 @@
|
|||
<div class="modal-title">{{$root.getLz('term.equalizer')}}</div>
|
||||
<button class="close-btn" @click="close()"></button>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<select class="md-select" style="width:220px;text-align:center;margin-right:19.75em" v-model="$root.cfg.audio.equalizer.preset" v-on:change="changePreset($root.cfg.audio.equalizer.preset)">
|
||||
<optgroup label="User Presets">
|
||||
<select class="md-select" style="width:220px;text-align:center;margin-right:245px" v-model="$root.cfg.audio.equalizer.preset" v-on:change="changePreset($root.cfg.audio.equalizer.preset)">
|
||||
<optgroup :label="$root.getLz('term.userPresets')">
|
||||
<option v-for="preset in $root.cfg.audio.equalizer.presets" :value="preset.preset">{{preset.name}}</option>
|
||||
</optgroup>
|
||||
<optgroup label="Default Presets">
|
||||
<optgroup :label="$root.getLz('term.defaultPresets')">
|
||||
<option v-for="preset in defaultPresets" :value="preset.preset">{{preset.name}}</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
|
@ -23,11 +23,6 @@
|
|||
<input tabindex="0" type="range" class="eq-slider mini" orient="vertical" min="-15" max="15" step="1" v-model="$root.cfg.audio.equalizer.vibrantBass" @change="changeVibrantBass()">
|
||||
Vibrant Bass
|
||||
</div>
|
||||
<div class="input-container mini">
|
||||
<input tabindex="0" type="number" class="eq-freq" orient="vertical" min="-12" max="12" step="0.1" v-model="$root.cfg.audio.equalizer.preamp" @change="changePreamp()">
|
||||
<input tabindex="0" type="range" class="eq-slider mini" orient="vertical" min="-12" max="12" step="0.1" v-model="$root.cfg.audio.equalizer.preamp" @change="changePreamp()">
|
||||
Preamp
|
||||
</div>
|
||||
<div class="input-container mini">
|
||||
{{$root.cfg.audio.equalizer.mix}}
|
||||
<input tabindex="0" type="range" class="eq-slider mini" orient="vertical" min="0" max="2" step="0.1" v-model="$root.cfg.audio.equalizer.mix" @change="changeMix()">
|
||||
|
@ -128,7 +123,6 @@
|
|||
this.frequencies = []
|
||||
this.gain = []
|
||||
this.Q = []
|
||||
this.preamp = 0
|
||||
this.mix = 1
|
||||
this.vibrantBass = 0
|
||||
this.userGenerated = true
|
||||
|
@ -140,27 +134,15 @@
|
|||
'frequencies': [32, 63, 125, 250, 500, 1000, 2000, 4000, 8000, 16000],
|
||||
'gain': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
'Q': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||
'preamp': 0,
|
||||
'mix': 1,
|
||||
'vibrantBass': 0,
|
||||
'userGenerated': false
|
||||
},{
|
||||
'preset': 'warmth',
|
||||
'name': 'Warmth',
|
||||
'frequencies': [32, 75, 125, 197, 500, 1000, 2000, 3040, 8000, 16000],
|
||||
'gain': [0, 2.1, 0, 0.8, 0, 0, 0, -1.5, 0, 0],
|
||||
'Q': [1, 0.7, 1, 1.5, 1, 1, 1, 2, 1, 1],
|
||||
'preamp': 0,
|
||||
'mix': 1,
|
||||
'vibrantBass': 0,
|
||||
'userGenerated': false
|
||||
}, {
|
||||
'preset': 'boostBrightness',
|
||||
'name': 'Boost Brightness',
|
||||
'frequencies': [32, 63, 125, 250, 466, 1000, 2000, 4000, 8000, 20000],
|
||||
'gain': [0, 0, 0, 0, -2, 0, 0, 0, 0, 10],
|
||||
'Q': [1, 1, 1, 1, 0.6, 1, 1, 1, 1, 0.1],
|
||||
'preamp': 0,
|
||||
'preset': 'boostAiriness',
|
||||
'name': 'Boost Airiness',
|
||||
'frequencies': [1169, 1733, 5962, 8688, 14125, 18628, 18628, 19000, 19500, 20000],
|
||||
'gain': [-1.41, 0.25, 3.33, 0.22, -0.53, 0.2, 3.64, 0, 0, 0],
|
||||
'Q': [0.405, 2.102, 0.025, 2.5, 7.071, 1.768, 1.146, 1, 1, 1],
|
||||
'mix': 1,
|
||||
'vibrantBass': 0,
|
||||
'userGenerated': false
|
||||
|
@ -170,7 +152,6 @@
|
|||
'frequencies': [32, 75, 125, 220, 700, 1000, 2000, 4000, 10000, 16000],
|
||||
'gain': [0, -8, 0, -0.1, -3, 0, 0, 0, 4, 0],
|
||||
'Q': [1, 0.2, 1, 2.0, 1.4, 1, 1, 1, 0.1, 1],
|
||||
'preamp': 0,
|
||||
'mix': 1,
|
||||
'vibrantBass': 0,
|
||||
'userGenerated': false
|
||||
|
@ -180,7 +161,6 @@
|
|||
'frequencies': [20, 63, 125, 250, 400, 1000, 2000, 4000, 8000, 20000],
|
||||
'gain': [-22, 0, 0, 0, -3, 0, 1.8, 0, 0, 3.5],
|
||||
'Q': [0.3, 1, 1, 1, 2.0, 1, 0.7, 1, 1, 0.8],
|
||||
'preamp': 0,
|
||||
'mix': 1,
|
||||
'vibrantBass': 0,
|
||||
'userGenerated': false
|
||||
|
@ -190,7 +170,6 @@
|
|||
'frequencies': [20, 63, 155, 250, 500, 1000, 2000, 5000, 11000, 16000],
|
||||
'gain': [-15, 0, -3, 0, 0, 0, 0, 3.1, 0, 0],
|
||||
'Q': [0.5, 1, 2, 1, 1, 1, 1, 1.5, 0.1, 1],
|
||||
'preamp': 0,
|
||||
'mix': 1,
|
||||
'vibrantBass': 0,
|
||||
'userGenerated': false
|
||||
|
@ -200,7 +179,6 @@
|
|||
'frequencies': [32, 63, 125, 250, 500, 1128, 2000, 4057, 8000, 16000],
|
||||
'gain': [0, 0, 0, 0, 0, 2, 0, -6.4, 0, 0],
|
||||
'Q': [1, 1, 1, 1, 1, 2, 1, 1, 1, 1],
|
||||
'preamp': 0,
|
||||
'mix': 1,
|
||||
'vibrantBass': 0,
|
||||
'userGenerated': false
|
||||
|
@ -210,29 +188,16 @@
|
|||
'frequencies': [35, 63, 125, 250, 500, 800, 2000, 4000, 8000, 20000],
|
||||
'gain': [5, 0, 0, 0, 0, -5, 0, 0, 0, 5],
|
||||
'Q': [0.1, 1, 1, 1, 1, 0.6, 1, 1, 1, 0.2],
|
||||
'preamp': 0,
|
||||
'mix': 1,
|
||||
'vibrantBass': 0,
|
||||
'userGenerated': false
|
||||
},
|
||||
{
|
||||
'preset': 'bassBoostGentle',
|
||||
'name': 'Gentle Bass Boost',
|
||||
'frequencies': [45.53,88.06,116.18,161.3,247.05,295.6,365.79,495.13,716.85,960.76],
|
||||
'gain': [-0.36,4.07,-1.3,1.92,0.77,-0.53,-1.33,0.44,0.46,-0.5],
|
||||
'Q': [1.768,0.625,5,8.409,10,16.82,5.946,7.071,20,10],
|
||||
'preamp': -2,
|
||||
'mix': 1,
|
||||
'vibrantBass': 0,
|
||||
'userGenerated': false
|
||||
},
|
||||
{
|
||||
'preset': 'bassBoostSurgical',
|
||||
'name': 'Surgical Bass Boost',
|
||||
'frequencies': [32, 63, 125, 250, 500, 1000, 2000, 4000, 8000, 16000],
|
||||
'gain': [2.7, 2.2, 1.6, 1.4, 0.6, 0, 0, 0, 0, 0],
|
||||
'Q': [1.4, 1.4, 1.4, 1.4, 1.4, 1, 1, 1, 1, 1],
|
||||
'preamp': 0,
|
||||
'mix': 1,
|
||||
'vibrantBass': 0,
|
||||
'userGenerated': false
|
||||
|
@ -242,7 +207,6 @@
|
|||
'frequencies': [32, 63, 160, 250, 500, 1000, 2000, 3500, 8000, 20000],
|
||||
'gain': [2.7, 2.2, 1.6, 1.4, 0.6, 0, 0, 0, 0, 0],
|
||||
'Q': [0.7, 0.7, 0.7, 0.7, 0.7, 1, 1, 1, 1, 1],
|
||||
'preamp': 0,
|
||||
'mix': 1,
|
||||
'vibrantBass': 0,
|
||||
'userGenerated': false
|
||||
|
@ -273,15 +237,15 @@
|
|||
"import": {
|
||||
"icon": "./assets/feather/share.svg",
|
||||
"name": app.getLz('action.import'),
|
||||
"action": function () {
|
||||
this.importPreset()
|
||||
action: () => {
|
||||
notyf.error("Not implemented yet")
|
||||
}
|
||||
},
|
||||
"export": {
|
||||
"icon": "./assets/feather/share.svg",
|
||||
"name": app.getLz('action.export'),
|
||||
"action": function () {
|
||||
this.exportPreset()
|
||||
action: () => {
|
||||
notyf.error("Not implemented yet")
|
||||
}
|
||||
},
|
||||
}
|
||||
|
@ -330,13 +294,20 @@
|
|||
app.resetState()
|
||||
},
|
||||
changeVibrantBass() {
|
||||
app.cfg.audio.vibrantBass.multiplier = app.cfg.audio.equalizer.vibrantBass / 10
|
||||
for (var i = 0; i < 21; i++) {
|
||||
CiderAudio.audioNodes.vibrantbassNode[i].gain.value = app.cfg.audio.vibrantBass.gain[i] * (app.cfg.audio.equalizer.vibrantBass / 10);
|
||||
}
|
||||
},
|
||||
changePreamp() {
|
||||
CiderAudio.audioNodes.preampNode.gain.value = app.cfg.audio.equalizer.preamp;
|
||||
app.cfg.audio.maikiwiAudio.vibrantBass.multiplier = app.cfg.audio.equalizer.vibrantBass / 10
|
||||
if (app.cfg.audio.equalizer.vibrantBass !== '0') {
|
||||
try {
|
||||
for (var i = 0; i < 21; i++) {
|
||||
CiderAudio.audioNodes.vibrantbassNode[i].gain.value = app.cfg.audio.maikiwiAudio.vibrantBass.gain[i] * (app.cfg.audio.equalizer.vibrantBass / 10);
|
||||
}}
|
||||
catch(e) {
|
||||
CiderAudio.hierarchical_loading();
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
CiderAudio.hierarchical_loading();
|
||||
}
|
||||
},
|
||||
changeMix() {
|
||||
for (var i = 0; i < 10; i++) {
|
||||
|
@ -357,7 +328,6 @@
|
|||
'frequencies': [32, 63, 125, 250, 500, 1000, 2000, 4000, 8000, 16000],
|
||||
'gain': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
'Q': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||
'preamp': 0,
|
||||
'mix': 1,
|
||||
'vibrantBass': 0,
|
||||
})
|
||||
|
@ -375,7 +345,6 @@
|
|||
newPreset.frequencies = eqSettings.frequencies
|
||||
newPreset.gain = eqSettings.gain
|
||||
newPreset.Q = eqSettings.Q
|
||||
newPreset.preamp = eqSettings.preamp
|
||||
newPreset.mix = eqSettings.mix
|
||||
newPreset.vibrantBass = eqSettings.vibrantBass
|
||||
app.cfg.audio.equalizer.presets.push(newPreset)
|
||||
|
@ -393,14 +362,13 @@
|
|||
preset.frequencies = app.cfg.audio.equalizer.frequencies
|
||||
preset.gain = app.cfg.audio.equalizer.gain
|
||||
preset.Q = app.cfg.audio.equalizer.Q
|
||||
preset.preamp = app.cfg.audio.equalizer.preamp
|
||||
preset.mix = app.cfg.audio.equalizer.mix
|
||||
preset.vibrantBass = app.cfg.audio.equalizer.vibrantBass
|
||||
notyf.success("Saved Preset")
|
||||
},
|
||||
exportPreset() {
|
||||
const preset = app.cfg.audio.equalizer.presets.find(p => p.preset == app.cfg.audio.equalizer.preset)
|
||||
const jsonObj = {"name": preset.name, "author": app.chrome.userinfo.attributes.name, "frequency": preset.frequencies, "gain": preset.gain, "q": preset.Q, "preamp": preset.preamp, "mix": preset.mix, "vibrantBass": preset.vibrantBass};
|
||||
const jsonObj = {"name": preset.name, "author": app.chrome.userinfo.attributes.name, "frequency": preset.frequencies, "gain": preset.gain, "q": preset.Q, "mix": preset.mix, "vibrantBass": preset.vibrantBass};
|
||||
ipcRenderer.send("export-eq", jsonObj)
|
||||
},
|
||||
importPreset() {
|
||||
|
@ -411,7 +379,6 @@
|
|||
newPreset.frequencies = result.frequency
|
||||
newPreset.gain = result.gain
|
||||
newPreset.Q = result.q
|
||||
newPreset.preamp = result.preamp
|
||||
newPreset.mix = result.mix
|
||||
newPreset.vibrantBass = result.vibrantBass
|
||||
app.cfg.audio.equalizer.presets.push(newPreset)
|
||||
|
@ -423,7 +390,6 @@
|
|||
},
|
||||
applyPreset(preset) {
|
||||
Object.assign(this.$root.cfg.audio.equalizer, preset)
|
||||
this.changePreamp()
|
||||
this.changeVibrantBass()
|
||||
for (var i = 0; i < 10; i++) {
|
||||
this.changeGain(i)
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
<div class="background">
|
||||
<div class="bgArtworkMaterial">
|
||||
<div class="bg-artwork-container">
|
||||
<img v-if="(app.cfg.visual.bg_artwork_rotation || app.animateBackground)" class="bg-artwork a" :src="image.replace('600x600','30x30') ?? ''">
|
||||
<img v-if="(app.cfg.visual.bg_artwork_rotation || app.animateBackground)" class="bg-artwork b" :src="image.replace('600x600','30x30') ?? ''">
|
||||
<img v-if="!(app.cfg.visual.bg_artwork_rotation || app.animateBackground)" class="bg-artwork no-animation" :src="image.replace('600x600','30x30') ?? ''">
|
||||
<img v-if="(app.cfg.visual.bg_artwork_rotation && app.animateBackground)" class="bg-artwork a" :src="(image ?? '').replace('{w}','30').replace('{h}','30')">
|
||||
<img v-if="(app.cfg.visual.bg_artwork_rotation && app.animateBackground)" class="bg-artwork b" :src="(image ?? '').replace('{w}','30').replace('{h}','30')">
|
||||
<img v-if="!(app.cfg.visual.bg_artwork_rotation && app.animateBackground)" class="bg-artwork no-animation" :src="(image ?? '').replace('{w}','30').replace('{h}','30')">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -14,7 +14,7 @@
|
|||
<div class="artwork" @click="app.fullscreen(false)">
|
||||
<mediaitem-artwork
|
||||
:size="600"
|
||||
:url="image ?? ''"
|
||||
:url="(image ?? '').replace('{w}','600').replace('{h}','600') "
|
||||
></mediaitem-artwork>
|
||||
</div>
|
||||
<div class="controls-parents">
|
||||
|
@ -41,8 +41,8 @@
|
|||
<div class="song-progress">
|
||||
<div class="song-duration" style="justify-content: space-between; height: 1px;"
|
||||
:style="[app.chrome.progresshover ? {'display': 'flex'} : {'display' : 'none'} ]">
|
||||
<p style="width: auto">{{ app.convertToMins(app.getSongProgress()) }}</p>
|
||||
<p style="width: auto">{{ app.convertToMins(app.mk.currentPlaybackDuration) }}</p>
|
||||
<p style="width: auto">{{ app.convertTime(app.getSongProgress()) }}</p>
|
||||
<p style="width: auto">{{ app.convertTime(app.mk.currentPlaybackDuration) }}</p>
|
||||
</div>
|
||||
|
||||
<input type="range" step="0.01" min="0" :style="app.progressBarStyle()"
|
||||
|
@ -66,7 +66,7 @@
|
|||
<button class="playback-button play" @click="app.mk.play()" v-else></button>
|
||||
</div>
|
||||
<div class="app-chrome-item">
|
||||
<button class="playback-button next" @click="app.mk.skipToNextItem()"></button>
|
||||
<button class="playback-button next" @click="app.skipToNextItem()"></button>
|
||||
</div>
|
||||
<div class="app-chrome-item">
|
||||
<button class="playback-button--small repeat" v-if="app.mk.repeatMode == 0"
|
||||
|
@ -80,8 +80,9 @@
|
|||
<div class="app-chrome-item volume display--large">
|
||||
<div class="input-container">
|
||||
<button class="volume-button--small volume" @click="app.muteButtonPressed()" :class="{'active': app.cfg.audio.volume == 0}"></button>
|
||||
<input type="range" class="slider" @wheel="app.volumeWheel" step="0.01" min="0" :max="$root.cfg.audio.maxVolume" v-model="app.mk.volume"
|
||||
v-if="typeof app.mk.volume != 'undefined'" @change="app.checkMuteChange()">
|
||||
<input type="range" class="slider" @wheel="app.volumeWheel" :step="app.cfg.audio.volumeStep" min="0" :max="app.cfg.audio.maxVolume" v-model="app.mk.volume"
|
||||
v-if="typeof app.mk.volume != 'undefined'" @change="app.checkMuteChange()"
|
||||
v-b-tooltip.hover :title="`${(Math.log10(app.mk.volume) * 20).toFixed(2)} dB`">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('hello-world', {
|
||||
var hw = Vue.component('hello-world', {
|
||||
template: '#hello-world',
|
||||
methods: {
|
||||
sayHello: function () {
|
||||
|
|
69
src/renderer/views/components/listitem-horizontal.ejs
Normal file
69
src/renderer/views/components/listitem-horizontal.ejs
Normal file
|
@ -0,0 +1,69 @@
|
|||
<script type="text/x-template" id="listitem-horizontal">
|
||||
<div class="listitem-horizontal">
|
||||
<vue-horizontal>
|
||||
<div v-for="items in itemPages">
|
||||
<mediaitem-list-item
|
||||
v-for="(song, index) in items" :show-library-status="showLibraryStatus" :parent="'listitem-hr' + simplifiedParent"
|
||||
:index="song.index"
|
||||
:item="song"></mediaitem-list-item>
|
||||
</div>
|
||||
</vue-horizontal>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('listitem-horizontal', {
|
||||
template: '#listitem-horizontal',
|
||||
name: "listitem-horizontal",
|
||||
props: {
|
||||
items: {
|
||||
type: Array,
|
||||
required: true
|
||||
},
|
||||
showLibraryStatus: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
itemPages: [],
|
||||
simplifiedParent : []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// give every item an id
|
||||
this.items.forEach(function (item, index) {
|
||||
item.id = index;
|
||||
});
|
||||
// split items into pages
|
||||
this.itemPages = app.arrayToChunk(this.items, 4);
|
||||
try{
|
||||
this.simplifiedParent = JSON.stringify(this.items.map ( function(x){return x.attributes.playParams}));
|
||||
console.log("simplifiedParent: " + this.simplifiedParent);
|
||||
}
|
||||
catch (e){}
|
||||
|
||||
},
|
||||
watch: {
|
||||
items: function (items) {
|
||||
// give every item an id
|
||||
this.items.forEach(function (item, index) {
|
||||
item.id = index;
|
||||
});
|
||||
// split items into pages
|
||||
this.itemPages = app.arrayToChunk(this.items, 4);
|
||||
try{
|
||||
this.simplifiedParent = JSON.stringify(this.items.map ( function(x){return x.attributes.playParams}));
|
||||
console.log("simplifiedParent: " + this.simplifiedParent);
|
||||
}
|
||||
catch (e){}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
sayHello: function () {
|
||||
alert('Hello world!');
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
|
@ -1,5 +1,5 @@
|
|||
<script type="text/x-template" id="mediaitem-artwork">
|
||||
<div class="mediaitem-artwork" :class="[{'rounded': (type == 'artists')}, classes]" :key="url">
|
||||
<div class="mediaitem-artwork" @contextmenu="contextMenu" :class="[{'rounded': (type == 'artists')}, classes]" :key="url">
|
||||
<img :src="app.getMediaItemArtwork(url, size, width)"
|
||||
decoding="async"
|
||||
:style="{background: bgcolor}"
|
||||
|
@ -61,6 +61,19 @@
|
|||
this.getClasses()
|
||||
},
|
||||
methods: {
|
||||
contextMenu(event) {
|
||||
let self = this
|
||||
app.showMenuPanel({
|
||||
items: {
|
||||
"save": {
|
||||
name: "Open artwork in browser",
|
||||
action: () => {
|
||||
window.open(app.getMediaItemArtwork(self.url, 1024, 1024))
|
||||
}
|
||||
}
|
||||
}
|
||||
}, event)
|
||||
},
|
||||
getVideoPriority() {
|
||||
if(app.cfg.visual.animated_artwork == "always") {
|
||||
return true;
|
||||
|
|
|
@ -12,24 +12,30 @@
|
|||
@mouseenter="checkLibrary"
|
||||
@mouseover="showInLibrary = true"
|
||||
@mouseleave="showInLibrary = false"
|
||||
@dblclick="route()"
|
||||
@controller-click="route()"
|
||||
tabindex="0"
|
||||
:class="[{'mediaitem-selected': app.select_hasMediaItem(guid)}, addClasses]">
|
||||
<template v-if="isVisible">
|
||||
<div class="isLibrary" v-if="showLibraryStatus == true">
|
||||
<div v-if="showInLibrary" :style="{display: (showInLibrary ? 'block' : 'none'), 'margin-left':'11px'}">
|
||||
<button @click="addToLibrary()" v-if="!addedToLibrary">
|
||||
<button @click="addToLibrary()" v-if="!addedToLibrary && (showIndex == false ||(showIndex == true && showIndexPlaylist != false))">
|
||||
<div class="svg-icon" :style="{'--color': 'var(--keyColor)', '--url': 'url(./assets/feather/plus.svg)'}"></div>
|
||||
</button>
|
||||
<button v-else-if='!(showArtwork == true && (showIndex == false ||(showIndex == true && showIndexPlaylist != false)))' @click="playTrack()" style="width: 44px;margin-left: -11px;">
|
||||
<%- include("../svg/play.svg") %>
|
||||
</button>
|
||||
</div>
|
||||
<div v-if="!(app.mk.isPlaying && (((app.mk.nowPlayingItem._songId ?? app.mk.nowPlayingItem.id ) == item.attributes.playParams.id) || (app.mk.nowPlayingItem.id == item.id ))) && showIndex" :style="{display: ((showIndex && !showInLibrary) ? 'block' : 'none'), 'margin-left':'11px'}">
|
||||
<div v-if="!(app.mk.isPlaying && (((app.mk.nowPlayingItem._songId ?? (app.mk.nowPlayingItem.songId ?? app.mk.nowPlayingItem.id )) == item.attributes.playParams.id) || (app.mk.nowPlayingItem.id == item.id ))) && showIndex" :style="{display: ((showIndex && !showInLibrary) ? 'block' : 'none'), 'margin-left':'11px'}">
|
||||
<div>
|
||||
<div>{{ (item.attributes && !showIndexPlaylist) ? (item.attributes.trackNumber ?? '') : ((index * 1 + 1 ) ?? '')}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="app.mk.isPlaying && (((app.mk.nowPlayingItem._songId ?? app.mk.nowPlayingItem.id ) == item.attributes.playParams.id) || (app.mk.nowPlayingItem.id == item.id))" :style="{display: (showInLibrary ? 'none' : 'block')}">
|
||||
<div v-if="app.mk.isPlaying && (((app.mk.nowPlayingItem._songId ?? (app.mk.nowPlayingItem.songId ?? app.mk.nowPlayingItem.id )) == item.attributes.playParams.id) || (app.mk.nowPlayingItem.id == item.id))" :style="{display: (showInLibrary ? 'none' : 'block')}">
|
||||
<div class="loadbar-sound"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="artwork" v-if="showArtwork == true">
|
||||
<div class="artwork" v-if="showArtwork == true && (showIndex == false ||(showIndex == true && showIndexPlaylist != false)) ">
|
||||
<mediaitem-artwork
|
||||
:url="item.attributes.artwork ? item.attributes.artwork.url : ''"
|
||||
:size="48"
|
||||
|
@ -37,9 +43,9 @@
|
|||
:type="item.type"></mediaitem-artwork>
|
||||
<button class="overlay-play" @click="playTrack()"><%- include("../svg/play.svg") %></button>
|
||||
</div>
|
||||
<div class="info-rect text-overflow-elipsis" :style="{'padding-left': (showArtwork ? '' : '16px')}"
|
||||
<div class="info-rect" :style="{'padding-left': (showArtwork ? '' : '16px')}"
|
||||
@dblclick="route()">
|
||||
<div class="title">
|
||||
<div class="title text-overflow-elipsis">
|
||||
{{ item.attributes.name }}
|
||||
</div>
|
||||
<div class="subtitle text-overflow-elipsis" style="-webkit-box-orient: horizontal;">
|
||||
|
@ -71,6 +77,9 @@
|
|||
<div class="duration" v-if="displayDuration" @dblclick="route()">
|
||||
{{ msToMinSec(item.attributes.durationInMillis ?? 0) }}
|
||||
</div>
|
||||
<div class="duration" v-if="item.attributes.playCount" @dblclick="route()">
|
||||
{{ item.attributes.playCount }}
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</script>
|
||||
|
@ -90,17 +99,17 @@
|
|||
}
|
||||
},
|
||||
props: {
|
||||
'item': {type: Object, required: true},
|
||||
'parent': {type: String, required: false},
|
||||
'index': {type: Number, required: false, default: -1},
|
||||
'show-artwork': {type: Boolean, default: true},
|
||||
'show-library-status': {type: Boolean, default: true},
|
||||
'show-meta-data': {type: Boolean, default: false},
|
||||
'show-duration': {type: Boolean, default: true},
|
||||
'showIndex': {type: Boolean, required: false},
|
||||
'showIndexPlaylist': {type: Boolean, required: false},
|
||||
'contextExt': {type: Object, required: false},
|
||||
'class-list': {type: String, required: false, default: ""},
|
||||
'item': { type: Object, required: true },
|
||||
'parent': { type: String, required: false },
|
||||
'index': { type: Number, required: false, default: -1 },
|
||||
'show-artwork': { type: Boolean, default: true },
|
||||
'show-library-status': { type: Boolean, default: true },
|
||||
'show-meta-data': { type: Boolean, default: false },
|
||||
'show-duration': { type: Boolean, default: true },
|
||||
'showIndex': { type: Boolean, required: false },
|
||||
'showIndexPlaylist': { type: Boolean, required: false },
|
||||
'contextExt': { type: Object, required: false },
|
||||
'class-list': { type: String, required: false, default: "" },
|
||||
},
|
||||
mounted() {
|
||||
let duration = this.item.attributes.durationInMillis ?? 0
|
||||
|
@ -115,21 +124,21 @@
|
|||
return color
|
||||
},
|
||||
async checkLibrary() {
|
||||
if(this.addedToLibrary) {return this.addedToLibrary}
|
||||
if(this.item.type.includes("library-playlists") || this.item.type.includes("station")) {
|
||||
if (this.addedToLibrary) { return this.addedToLibrary }
|
||||
if (this.item.type.includes("library-playlists") || this.item.type.includes("station")) {
|
||||
this.addedToLibrary = true
|
||||
return
|
||||
}
|
||||
this.$root.inLibrary([this.item]).then(res => {
|
||||
this.addedToLibrary = res[0].attributes.inLibrary
|
||||
this.addedToLibrary = res[0]?.attributes?.inLibrary ?? false
|
||||
})
|
||||
return this.addedToLibrary
|
||||
},
|
||||
getClasses() {
|
||||
if(this.classList) {
|
||||
if (this.classList) {
|
||||
this.addClasses = {}
|
||||
let classList = this.classList.split(' ')
|
||||
for(let i = 0; i < classList.length; i++) {
|
||||
for (let i = 0; i < classList.length; i++) {
|
||||
this.addClasses[classList[i]] = true
|
||||
}
|
||||
}
|
||||
|
@ -259,7 +268,7 @@
|
|||
for (let kind in itemsToPlay) {
|
||||
let ids = itemsToPlay[kind]
|
||||
if (ids.length > 0) {
|
||||
app.mk.playNext({[kind + "s"]: itemsToPlay[kind]})
|
||||
app.mk.playNext({ [kind + "s"]: itemsToPlay[kind] })
|
||||
}
|
||||
}
|
||||
console.log(itemsToPlay)
|
||||
|
@ -281,7 +290,7 @@
|
|||
for (let kind in itemsToPlay) {
|
||||
let ids = itemsToPlay[kind]
|
||||
if (ids.length > 0) {
|
||||
app.mk.playLater({[kind + "s"]: itemsToPlay[kind]})
|
||||
app.mk.playLater({ [kind + "s"]: itemsToPlay[kind] })
|
||||
}
|
||||
}
|
||||
app.selectedMediaItems = []
|
||||
|
@ -363,7 +372,7 @@
|
|||
"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.playNext({ [self.item.attributes.playParams.kind ?? self.item.type]: self.item.attributes.playParams.id ?? self.item.id })
|
||||
app.mk.queue._reindex()
|
||||
app.selectedMediaItems = []
|
||||
}
|
||||
|
@ -372,7 +381,7 @@
|
|||
"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.playLater({ [self.item.attributes.playParams.kind ?? self.item.type]: self.item.attributes.playParams.id ?? self.item.id })
|
||||
app.mk.queue._reindex()
|
||||
app.selectedMediaItems = []
|
||||
}
|
||||
|
@ -381,7 +390,7 @@
|
|||
"icon": "./assets/feather/radio.svg",
|
||||
"name": app.getLz('action.startRadio'),
|
||||
"action": function () {
|
||||
app.mk.setStationQueue({song: self.item.attributes.playParams.id ?? self.item.id}).then(() => {
|
||||
app.mk.setStationQueue({ song: self.item.attributes.playParams.id ?? self.item.id }).then(() => {
|
||||
app.mk.play()
|
||||
app.selectedMediaItems = []
|
||||
})
|
||||
|
@ -405,12 +414,26 @@
|
|||
"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)})
|
||||
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)}
|
||||
} 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -430,31 +453,31 @@
|
|||
try {
|
||||
await this.checkLibrary().then(res => {
|
||||
console.log(res)
|
||||
if(res) {
|
||||
if (res) {
|
||||
menus.normal.items.find(x => x.id == 'addToLibrary').hidden = true
|
||||
menus.normal.items.find(x => x.id == 'removeFromLibrary').hidden = false
|
||||
}else{
|
||||
} else {
|
||||
menus.normal.items.find(x => x.id == 'addToLibrary').disabled = false
|
||||
}
|
||||
})
|
||||
|
||||
}catch(e) {
|
||||
} 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) {
|
||||
|
||||
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) {
|
||||
console.log(err)
|
||||
}
|
||||
},
|
||||
visibilityChanged: function (isVisible, entry) {
|
||||
|
@ -474,7 +497,7 @@
|
|||
},
|
||||
async removeFromLibrary() {
|
||||
let item = this.item
|
||||
let params = {"fields[songs]": "inLibrary", "fields[albums]": "inLibrary", "relate": "library"}
|
||||
let params = { "fields[songs]": "inLibrary", "fields[albums]": "inLibrary", "relate": "library" }
|
||||
let id = item.id ?? item.attributes.playParams.id
|
||||
let res = await app.mkapi(item.attributes.playParams.kind ?? item.type, item.attributes.playParams.isLibrary ?? false, item.attributes.playParams.id ?? item.id, params);
|
||||
if (res && res.relationships && res.relationships.library && res.relationships.library.data && res.relationships.library.data.length > 0) {
|
||||
|
@ -502,10 +525,10 @@
|
|||
let truekind = (!kind.endsWith("s")) ? (kind + "s") : kind;
|
||||
console.log(item, parent, childIndex, kind, id, isLibrary, kind == "playlists", id.startsWith("p.") || id.startsWith("pl.u"))
|
||||
app.mk.stop().then(() => {
|
||||
if (parent != null && childIndex != null) {
|
||||
app.queueParentandplayChild(parent, childIndex, item);
|
||||
}
|
||||
else if (kind.includes("playlist") && (id.startsWith("p.") || id.startsWith("pl."))){
|
||||
if (parent != null && childIndex != null) {
|
||||
app.queueParentandplayChild(parent, childIndex, item);
|
||||
}
|
||||
else if (kind.includes("playlist") && (id.startsWith("p.") || id.startsWith("pl."))) {
|
||||
function shuffleArray(array) {
|
||||
for (var i = array.length - 1; i > 0; i--) {
|
||||
var j = Math.floor(Math.random() * (i + 1));
|
||||
|
@ -514,58 +537,59 @@
|
|||
array[j] = temp;
|
||||
}
|
||||
}
|
||||
app.mk.setQueue({[truekind]: [item.attributes.playParams.id ?? item.id]}).then(function () {
|
||||
app.mk.play().then(function (){
|
||||
var playlistId = id
|
||||
function getPlaylist(id, isLibrary){
|
||||
if (isLibrary){
|
||||
return this.app.mk.api.v3.music(`/v1/me/library/playlists/${id}`)
|
||||
} else { return this.app.mk.api.v3.music(`/v1/catalog/${app.mk.storefrontId}/playlists/${id}`)}
|
||||
app.mk.setQueue({ [truekind]: [item.attributes.playParams.id ?? item.id] , parameters : {l : this.app.mklang} }).then(function () {
|
||||
app.mk.play().then(function () {
|
||||
var playlistId = id
|
||||
function getPlaylist(id, isLibrary) {
|
||||
if (isLibrary) {
|
||||
return this.app.mk.api.v3.music(`/v1/me/library/playlists/${id}`)
|
||||
} else { return this.app.mk.api.v3.music(`/v1/catalog/${app.mk.storefrontId}/playlists/${id}`) }
|
||||
}
|
||||
try {
|
||||
getPlaylist(id, isLibrary).then(res => {
|
||||
//let query = res.relationships.tracks.data.map(item => new MusicKit.MediaItem(item));
|
||||
//if (app.mk.shuffleMode == 1){shuffleArray(query); }
|
||||
// console.log(query)
|
||||
// app.mk.queue.append(query)
|
||||
if (!res.data.relationships.tracks.next) {
|
||||
return
|
||||
} else {
|
||||
getPlaylistTracks(res.data.relationships.tracks.next)
|
||||
}
|
||||
try {
|
||||
getPlaylist(id, isLibrary).then(res => {
|
||||
//let query = res.relationships.tracks.data.map(item => new MusicKit.MediaItem(item));
|
||||
//if (app.mk.shuffleMode == 1){shuffleArray(query); }
|
||||
// console.log(query)
|
||||
// app.mk.queue.append(query)
|
||||
if (!res.data.relationships.tracks.next) {
|
||||
return
|
||||
} else {
|
||||
getPlaylistTracks(res.data.relationships.tracks.next)
|
||||
}
|
||||
|
||||
function getPlaylistTracks(next) {
|
||||
app.apiCall(app.musicBaseUrl + next, res => {
|
||||
// if (res.id != playlistId || next.includes(playlistId)) {
|
||||
// return
|
||||
// }
|
||||
console.log('nextres', res)
|
||||
let query = res.data.map(item => new MusicKit.MediaItem(item))
|
||||
if (app.mk.shuffleMode == 1){shuffleArray(query); console.log('shf')}
|
||||
app.mk.queue.append(query)
|
||||
function getPlaylistTracks(next) {
|
||||
app.apiCall(app.musicBaseUrl + next, res => {
|
||||
// if (res.id != playlistId || next.includes(playlistId)) {
|
||||
// return
|
||||
// }
|
||||
console.log('nextres', res)
|
||||
let query = res.data.map(item => new MusicKit.MediaItem(item))
|
||||
if (app.mk.shuffleMode == 1) { shuffleArray(query); console.log('shf') }
|
||||
app.mk.queue.append(query)
|
||||
|
||||
if (res.next) {
|
||||
getPlaylistTracks(res.next)
|
||||
}
|
||||
})
|
||||
if (res.next) {
|
||||
getPlaylistTracks(res.next)
|
||||
}
|
||||
})
|
||||
} catch (e) {}
|
||||
}
|
||||
})
|
||||
} catch (e) { }
|
||||
|
||||
|
||||
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
else {
|
||||
app.playMediaItemById(item.attributes.playParams.id ?? item.id, item.attributes.playParams.kind ?? item.type, item.attributes.playParams.isLibrary ?? false, item.attributes.url)
|
||||
}})
|
||||
}
|
||||
else {
|
||||
app.playMediaItemById(item.attributes.playParams.id ?? item.id, item.attributes.playParams.kind ?? item.type, item.attributes.playParams.isLibrary ?? false, item.attributes.url)
|
||||
}
|
||||
})
|
||||
},
|
||||
route(){
|
||||
route() {
|
||||
let kind = (this.item.attributes.playParams ? (this.item.attributes.playParams.kind ?? (this.item.type ?? '')) : (this.item.type ?? ''));
|
||||
if (kind.toLowerCase().includes('album') || kind.toLowerCase().includes('playlist')){
|
||||
if (kind.toLowerCase().includes('album') || kind.toLowerCase().includes('playlist')) {
|
||||
app.routeView(this.item)
|
||||
} else {
|
||||
this.playTrack()
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
<script type="text/x-template" id="mediaitem-scroller-horizontal-large">
|
||||
<div class="cd-hmedia-scroller">
|
||||
<template >
|
||||
<mediaitem-square :item="item"
|
||||
v-for="item in items"></mediaitem-square>
|
||||
</template>
|
||||
</div>
|
||||
<vue-horizontal>
|
||||
<mediaitem-square :item="item"
|
||||
v-for="item in items"></mediaitem-square>
|
||||
</vue-horizontal>
|
||||
</script>
|
||||
|
||||
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
<script type="text/x-template" id="mediaitem-scroller-horizontal-mvview">
|
||||
<div class="cd-hmedia-scroller">
|
||||
<vue-horizontal>
|
||||
<template v-if="browsesp">
|
||||
<mediaitem-mvview-sp
|
||||
:item="item ? (item.attributes.kind ? item : ((item.relationships && item.relationships.contents ) ? item.relationships.contents.data[0] : item)) : []"
|
||||
:item="item ? ((item.attributes?.kind != null || item.attributes?.type == 'editorial-elements') ? item : ((item.relationships && item.relationships.contents ) ? item.relationships.contents.data[0] : item)) : []"
|
||||
:imagesize="imagesize"
|
||||
:badge="item.attributes" v-for="item in items"></mediaitem-mvview-sp>
|
||||
</template>
|
||||
<template v-else>
|
||||
<mediaitem-square :kind="kind" size="600"
|
||||
:item="item ? (item.attributes.kind ? item : ((item.relationships && item.relationships.contents ) ? item.relationships.contents.data[0] : item)) : []"
|
||||
:item="item ? ((item.attributes?.kind != null || item.type == 'editorial-elements') ? item : ((item.relationships && item.relationships.contents ) ? item.relationships.contents.data[0] : item)) : []"
|
||||
:imagesize="imagesize"
|
||||
v-for="item in items"></mediaitem-square>
|
||||
</template>
|
||||
</div>
|
||||
</vue-horizontal>
|
||||
</script>
|
||||
|
||||
|
||||
|
@ -43,6 +43,8 @@
|
|||
app: this.$root,
|
||||
}
|
||||
},
|
||||
methods: {}
|
||||
// mounted(){
|
||||
// console.log('hes',this.items)
|
||||
// }
|
||||
});
|
||||
</script>
|
|
@ -1,9 +1,11 @@
|
|||
<script type="text/x-template" id="mediaitem-scroller-horizontal-sp">
|
||||
<div class="cd-hmedia-scroller hmedia-scroller-card">
|
||||
<template>
|
||||
<mediaitem-square kind="card" :item="item" size="300"
|
||||
v-for="item in items"></mediaitem-square>
|
||||
</template>
|
||||
<vue-horizontal>
|
||||
<template>
|
||||
<mediaitem-square kind="card" :item="item" size="300"
|
||||
v-for="item in items"></mediaitem-square>
|
||||
</template>
|
||||
</vue-horizontal>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
<script type="text/x-template" id="mediaitem-scroller-horizontal">
|
||||
<template>
|
||||
<div class="cd-hmedia-scroller" :class="kind">
|
||||
<slot></slot>
|
||||
<mediaitem-square :kind="kind" :item="item"
|
||||
v-for="item in items"></mediaitem-square>
|
||||
</div>
|
||||
</template>
|
||||
<vue-horizontal>
|
||||
<slot></slot>
|
||||
<mediaitem-square :kind="kind" :item="item" v-for="item in items"></mediaitem-square>
|
||||
</vue-horizontal>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
|
@ -22,7 +19,7 @@
|
|||
defualt: ""
|
||||
}
|
||||
},
|
||||
data: function () {
|
||||
data: function() {
|
||||
return {
|
||||
app: this.$root,
|
||||
}
|
||||
|
|
|
@ -1,244 +0,0 @@
|
|||
<script type="text/x-template" id="mediaitem-square-large">
|
||||
<div ref="main" style="position: relative; display: inline-flex;" @contextmenu="contextMenu">
|
||||
<div @click.self='app.routeView(item)'
|
||||
class="cd-mediaitem-square-large" ref="main2">
|
||||
<div class="artwork">
|
||||
<mediaitem-artwork
|
||||
:url="item.attributes.artwork ? item.attributes.artwork.url : ''"
|
||||
:video="(item.attributes != null && item.attributes.editorialVideo != null) ? (item.attributes.editorialVideo.motionDetailSquare ? item.attributes.editorialVideo.motionDetailSquare.video : (item.attributes.editorialVideo.motionSquareVideo1x1 ? item.attributes.editorialVideo.motionSquareVideo1x1.video : '')) : '' "
|
||||
size="300"
|
||||
:type="item.type"></mediaitem-artwork>
|
||||
</div>
|
||||
<div class="cd-mediaitem-square-large-overlay" @click.self='app.routeView(item)'>
|
||||
<div class="button" style="
|
||||
border-radius: 50%;
|
||||
background: rgba(50,50,50,0.7);"
|
||||
:style="[(!(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('radioStation') && !(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('song')) ? {'margin': '140px','position': 'absolute',
|
||||
width: '40px',
|
||||
height: '40px',} :
|
||||
{margin: '35px', 'position': 'absolute',
|
||||
width: '120px',
|
||||
height: '120px',}]" @click="app.playMediaItem(item)">
|
||||
<%- include("../svg/play.svg") %>
|
||||
</div>
|
||||
<div class="button" style="
|
||||
border-radius: 50%;
|
||||
background: rgba(50,50,50,0.7);"
|
||||
:style="[(!(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('radioStation') && !(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('song')) ? {'position': 'absolute','margin': '140px',
|
||||
width: '40px', 'margin-left': '10px',
|
||||
height: '40px',} :
|
||||
{display: 'none',margin: '35px','position': 'absolute',
|
||||
width: '120px',
|
||||
height: '120px',}]" @click="clickContext() ">
|
||||
<%- include("../svg/more.svg") %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="title text-overflow-elipsis" @click='app.routeView(item)'>
|
||||
{{ item.attributes.name ?? '' }}
|
||||
</div>
|
||||
<div class="subtitle text-overflow-elipsis item-navigate" v-if="item.attributes.artistName" :style = "{'z-index': ((item.attributes.editorialNotes == null) && item.attributes.artistName) ? '4' : ''}" @click="if(item.attributes.artistName)app.searchAndNavigate(item,'artist')">
|
||||
{{ item.attributes.artistName ?? '' }}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="cd-mediaitem-square-large-overlay" @click.self='app.routeView(item)' tabindex="0">
|
||||
<div class="button" style="
|
||||
border-radius: 50%;
|
||||
background: rgba(50,50,50,0.7);"
|
||||
:style="[(!(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('radioStation') && !(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('song')) ? {'margin': '140px','position': 'absolute',
|
||||
width: '40px',
|
||||
height: '40px',} :
|
||||
{margin: '35px','position': 'absolute',
|
||||
width: '120px',
|
||||
height: '120px',}]" @click="app.playMediaItem(item)">
|
||||
<%- include("../svg/play.svg") %>
|
||||
</div>
|
||||
<div class="button" style="
|
||||
border-radius: 50%;
|
||||
background: rgba(50,50,50,0.7);"
|
||||
:style="[(!(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('radioStation') && !(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('song')) ? {'position': 'absolute','margin': '140px',
|
||||
width: '40px', 'margin-left': '10px',
|
||||
height: '40px',} :
|
||||
{display: 'none',margin: '35px','position': 'absolute',
|
||||
width: '120px',
|
||||
height: '120px',}]" @click="console.log('as');contextMenu()">
|
||||
<%- include("../svg/more.svg") %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('mediaitem-square-large', {
|
||||
template: '#mediaitem-square-large',
|
||||
props: ['item'],
|
||||
data: function () {
|
||||
return {
|
||||
isVisible: false,
|
||||
addedToLibrary: false,
|
||||
app: this.$root,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
clickContext() {
|
||||
var evt = document.createEvent('MouseEvent');
|
||||
var rect = this.$refs.main2.getBoundingClientRect();
|
||||
evt.initMouseEvent(
|
||||
"contextmenu",
|
||||
true /* bubble */, true /* cancelable */,
|
||||
window, null,
|
||||
0, 0, rect.x + 100, rect.y + 100, /* coordinates */
|
||||
false, false, false, false, /* modifier keys */
|
||||
0 /*left*/, null
|
||||
);
|
||||
this.$refs.main.dispatchEvent(evt);
|
||||
},
|
||||
async isInLibrary() {
|
||||
if (this.item.type && !this.item.type.includes("library")) {
|
||||
var params = {
|
||||
"fields[playlists]": "inLibrary",
|
||||
"fields[albums]": "inLibrary",
|
||||
"relate": "library",
|
||||
"extend": this.revisedRandId()
|
||||
}
|
||||
var res = await app.mkapi(this.item.attributes.playParams.kind ?? this.item.type, this.item.attributes.playParams.isLibrary ?? false, this.item.attributes.playParams.id ?? this.item.id, params);
|
||||
this.addedToLibrary = (res && res.attributes && res.attributes.inLibrary) ? res.attributes.inLibrary : false
|
||||
} else {
|
||||
this.addedToLibrary = true
|
||||
}
|
||||
},
|
||||
async removeFromLibrary(id) {
|
||||
var params = {
|
||||
"fields[playlists]": "inLibrary",
|
||||
"fields[songs]": "inLibrary",
|
||||
"fields[albums]": "inLibrary",
|
||||
"relate": "library",
|
||||
"extend": this.revisedRandId()
|
||||
}
|
||||
var id = this.item.id ?? this.item.attributes.playParams.id
|
||||
var res = await app.mkapi(this.item.attributes.playParams.kind ?? this.item.type, this.item.attributes.playParams.isLibrary ?? false, this.item.attributes.playParams.id ?? this.item.id, params);
|
||||
if (res && res.relationships && res.relationships.library && res.relationships.library.data && res.relationships.library.data.length > 0) {
|
||||
id = res.relationships.library.data[0].id
|
||||
}
|
||||
let kind = this.item.attributes.playParams.kind ?? this.item.type ?? '';
|
||||
var truekind = (!kind.endsWith("s")) ? (kind + "s") : kind;
|
||||
app.mk.api.v3.music(`v1/me/library/${truekind}/${id.toString()}`,{},
|
||||
{
|
||||
fetchOptions: {
|
||||
method: "DELETE"
|
||||
}})
|
||||
this.addedToLibrary = true
|
||||
},
|
||||
async contextMenu(event) {
|
||||
if (!event) { event = this.$refs.main } else { console.log(event) }
|
||||
let self = this
|
||||
let useMenu = "normal"
|
||||
await this.isInLibrary()
|
||||
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: this.$root.getLz('action.playTracksNext').replace("${app.selectedMediaItems.length}", app.selectedMediaItems.length),
|
||||
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),
|
||||
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: {
|
||||
items: [
|
||||
{
|
||||
"name": "Play Next",
|
||||
"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": "Play Later",
|
||||
"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 = []
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "addToPlaylist",
|
||||
"name": "Add to Playlist...",
|
||||
"action": function () {
|
||||
app.promptAddToPlaylist()
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": (this.addedToLibrary) ? "Remove from Library..." : "Add to Library...",
|
||||
"action": async function () {
|
||||
let item_id = self.item.attributes.playParams.id ?? self.item.id;
|
||||
let data_type = self.item.attributes.playParams.kind ?? self.item.type;
|
||||
if (self.addedToLibrary != true) {
|
||||
console.log("add");
|
||||
app.addToLibrary(item_id);
|
||||
self.addedToLibrary = true
|
||||
} else {
|
||||
console.log("remove");
|
||||
await self.removeFromLibrary(item_id);
|
||||
self.addedToLibrary = false
|
||||
}
|
||||
;
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": this.$root.getLz('term.share'),
|
||||
"action": function () {
|
||||
self.app.copyToClipboard(self.item.attributes.url)
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
CiderContextMenu.Create(event, menus[useMenu])
|
||||
},
|
||||
}
|
||||
});
|
||||
</script>
|
|
@ -1,293 +0,0 @@
|
|||
<script type="text/x-template" id="mediaitem-square-sp">
|
||||
<div ref="main" style="position: relative; display: inline-flex;" @contextmenu="contextMenu" v-observe-visibility="{callback: visibilityChanged}" width="250px">
|
||||
<div @click.self='app.routeView(item)' v-if="isVisible"
|
||||
class="cd-mediaitem-square-sp" ref="main2"
|
||||
:style="{'--spcolor' : (item.attributes.artwork.bgColor != null) ? ('#'+item.attributes.artwork.bgColor) : `black`}">
|
||||
<div class="artwork">
|
||||
<mediaitem-artwork
|
||||
:url="item.attributes.artwork ? item.attributes.artwork.url : ''"
|
||||
size="300"
|
||||
:video="(item.attributes != null && item.attributes.editorialVideo != null) ? (item.attributes.editorialVideo.motionDetailSquare ? item.attributes.editorialVideo.motionDetailSquare.video : (item.attributes.editorialVideo.motionSquareVideo1x1 ? item.attributes.editorialVideo.motionSquareVideo1x1.video : '')) : '' "
|
||||
:type="item.type"></mediaitem-artwork>
|
||||
</div>
|
||||
<div class="cd-mediaitem-square-large-overlay" @click.self='app.routeView(item)'>
|
||||
<div class="button" style="
|
||||
border-radius: 50%;
|
||||
background: rgba(50,50,50,0.7);"
|
||||
:style="[(!(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('radioStation') && !(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('song')) ? {'margin': '153px','position': 'absolute','margin-left': '153px',
|
||||
width: '30px',
|
||||
height: '30px',} :
|
||||
{margin: '35px',display:'none',
|
||||
width: '120px',
|
||||
height: '120px',}]" @click="clickContext()">
|
||||
<%- include("../svg/more.svg") %>
|
||||
</div>
|
||||
<div class="button" style="
|
||||
border-radius: 50%;
|
||||
background: rgba(50,50,50,0.7);"
|
||||
:style="[(!(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('radioStation') && !(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('song')) ? {'position': 'absolute','margin': '153px',
|
||||
width: '30px', 'margin-left': '8px',
|
||||
height: '30px',} :
|
||||
{margin: '35px','position': 'absolute',
|
||||
width: '120px',
|
||||
height: '120px',}]" @click="app.playMediaItem(item)">
|
||||
<%- include("../svg/play.svg") %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="title text-overflow-elipsis"
|
||||
:style="{'color' : (item.attributes.artwork.textColor1 != null) ? ('#'+item.attributes.artwork.textColor1) : `#eee`}"
|
||||
style="font-weight: 600">
|
||||
{{ item.attributes.name }}
|
||||
</div>
|
||||
<div class="subtitle text-overflow-elipsis "
|
||||
:class="{'item-navigate': ((item.attributes.editorialNotes == null) && item.attributes.artistName)}"
|
||||
:style="{ 'z-index': ((item.attributes.editorialNotes == null) && item.attributes.artistName) ? '4' : '' ,'color' : (item.attributes.artwork.textColor1 != null) ? ('#'+item.attributes.artwork.textColor1) : `#eee`}"
|
||||
style="padding-left: 4px;padding-right: 4px; display: -webkit-box;-webkit-box-orient: vertical; -webkit-line-clamp: 2;white-space: normal;"
|
||||
@click="subtitleSearchNavigate(item)"
|
||||
>
|
||||
{{ (item.attributes.editorialNotes != null) ? item.attributes.editorialNotes.short
|
||||
:(item.attributes.artistName ?? '') }}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="cd-mediaitem-square-large-overlay" @click.self='app.routeView(item)' tabindex="0" v-if="isVisible">
|
||||
<div class="button" style="
|
||||
border-radius: 50%;
|
||||
background: rgba(50,50,50,0.7);"
|
||||
:style="[(!(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('radioStation') && !(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('song')) ? {'margin': '153px','position': 'absolute','margin-left': '153px',
|
||||
width: '30px',
|
||||
height: '30px',} :
|
||||
{margin: '35px','position': 'absolute', display: 'none',
|
||||
width: '120px',
|
||||
height: '120px',}]" @click="clickContext()">
|
||||
<%- include("../svg/more.svg") %>
|
||||
</div>
|
||||
<div class="button" style="
|
||||
border-radius: 50%;
|
||||
background: rgba(50,50,50,0.7);"
|
||||
:style="[(!(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('radioStation') && !(item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')): (item.type ?? '')).includes('song')) ? {'position': 'absolute','margin': '153px',
|
||||
width: '30px', 'margin-left': '8px',
|
||||
height: '30px',} :
|
||||
{margin: '35px','position': 'absolute',
|
||||
width: '120px',
|
||||
height: '120px',}]" @click="app.playMediaItem(item)">
|
||||
<%- include("../svg/play.svg") %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('mediaitem-square-sp', {
|
||||
template: '#mediaitem-square-sp',
|
||||
props: ['item'],
|
||||
data: function () {
|
||||
return {
|
||||
app: this.$root,
|
||||
isVisible: true,
|
||||
addedToLibrary : false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
revisedRandId() {
|
||||
return Math.random().toString(36).replace(/[^a-z]+/g, '').substr(2, 10);
|
||||
},
|
||||
async isInLibrary() {
|
||||
if (this.item.type && !this.item.type.includes("library")) {
|
||||
var params = {"fields[playlists]": "inLibrary", "fields[albums]": "inLibrary", "relate": "library", "extend": this.revisedRandId()}
|
||||
var res = await app.mkapi(this.item.attributes.playParams.kind ?? this.item.type, this.item.attributes.playParams.isLibrary ?? false, this.item.attributes.playParams.id ?? this.item.id, params);
|
||||
res = res.data.data[0]
|
||||
this.addedToLibrary = (res && res.attributes && res.attributes.inLibrary) ? res.attributes.inLibrary : false
|
||||
} else {
|
||||
this.addedToLibrary = true
|
||||
}
|
||||
},
|
||||
async removeFromLibrary(id) {
|
||||
var params = {"fields[playlists]": "inLibrary","fields[songs]": "inLibrary", "fields[albums]": "inLibrary", "relate": "library", "extend": this.revisedRandId()}
|
||||
var id = this.item.id ?? this.item.attributes.playParams.id
|
||||
var res = await app.mkapi(this.item.attributes.playParams.kind ?? this.item.type, this.item.attributes.playParams.isLibrary ?? false, this.item.attributes.playParams.id ?? this.item.id, params);
|
||||
res = res.data.data[0]
|
||||
if (res && res.relationships && res.relationships.library && res.relationships.library.data && res.relationships.library.data.length > 0) {
|
||||
id = res.relationships.library.data[0].id
|
||||
}
|
||||
let kind = this.item.attributes.playParams.kind ?? this.item.type ?? '';
|
||||
var truekind = (!kind.endsWith("s")) ? (kind + "s") : kind;
|
||||
app.mk.api.v3.music(`v1/me/library/${truekind}/${id.toString()}`,{},
|
||||
{
|
||||
fetchOptions: {
|
||||
method: "DELETE"
|
||||
}})
|
||||
this.addedToLibrary = true
|
||||
},
|
||||
subtitleSearchNavigate(item) {
|
||||
if((item.attributes.editorialNotes == null) && item.attributes.artistName)app.searchAndNavigate(item,'artist')
|
||||
},
|
||||
clickContext() {
|
||||
var evt = document.createEvent('MouseEvent');
|
||||
var rect = this.$refs.main2.getBoundingClientRect();
|
||||
evt.initMouseEvent(
|
||||
"contextmenu",
|
||||
true /* bubble */, true /* cancelable */,
|
||||
window, null,
|
||||
0, 0, rect.x + 100, rect.y + 100, /* coordinates */
|
||||
false, false, false, false, /* modifier keys */
|
||||
0 /*left*/, null
|
||||
);
|
||||
this.$refs.main.dispatchEvent(evt);
|
||||
}
|
||||
,
|
||||
visibilityChanged: function (isVisible, entry) {
|
||||
this.isVisible = isVisible
|
||||
},
|
||||
async contextMenu(event) {
|
||||
if (!event) {
|
||||
event = this.$refs.main
|
||||
} else {
|
||||
console.log(event)
|
||||
}
|
||||
let self = this
|
||||
let useMenu = "normal"
|
||||
await this.isInLibrary()
|
||||
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),
|
||||
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),
|
||||
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: {
|
||||
items: [
|
||||
|
||||
{
|
||||
"name": "Play Next",
|
||||
"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": "Play Later",
|
||||
"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 = []
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "addToPlaylist",
|
||||
"name": "Add to Playlist...",
|
||||
"action": function () {
|
||||
app.promptAddToPlaylist()
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "love",
|
||||
"name": "Love",
|
||||
"disabled": true,
|
||||
"action": function () {
|
||||
app.love(self.item)
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "unlove",
|
||||
"name": "Unlove",
|
||||
"disabled": true,
|
||||
"action": function () {
|
||||
app.unlove(self.item)
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "dislike",
|
||||
"name": "Dislike",
|
||||
"disabled": true,
|
||||
"action": function () {
|
||||
app.dislike(self.item)
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "undo_dislike",
|
||||
"name": "Undo dislike",
|
||||
"disabled": true,
|
||||
"action": function () {
|
||||
app.unlove(self.item)
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": (this.addedToLibrary) ? "Remove from Library..." : "Add to Library...",
|
||||
"action": async function () {
|
||||
let item_id = self.item.attributes.playParams.id ?? self.item.id;
|
||||
let data_type = self.item.attributes.playParams.kind ?? self.item.type;
|
||||
if (self.addedToLibrary != true) { console.log("add"); app.addToLibrary(item_id); self.addedToLibrary = true}
|
||||
else { console.log("remove"); await self.removeFromLibrary(item_id); self.addedToLibrary = false};
|
||||
}
|
||||
},
|
||||
|
||||
]
|
||||
}
|
||||
}
|
||||
let rating = await app.getRating(self.item)
|
||||
if(rating == 0) {
|
||||
menus.normal.items.find(x => x.id == 'love').disabled = false
|
||||
menus.normal.items.find(x => x.id == 'dislike').disabled = false
|
||||
}else if(rating == 1) {
|
||||
menus.normal.items.find(x => x.id == 'unlove').disabled = false
|
||||
}else if(rating == -1) {
|
||||
menus.normal.items.find(x => x.id == 'undo_dislike').disabled = false
|
||||
}
|
||||
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"
|
||||
})
|
||||
}
|
||||
CiderContextMenu.Create(event, menus[useMenu])
|
||||
},
|
||||
}
|
||||
});
|
||||
</script>
|
|
@ -1,10 +1,17 @@
|
|||
<script type="text/x-template" id="mediaitem-square">
|
||||
<div tabindex="0"
|
||||
<div
|
||||
tabindex="0"
|
||||
@click.self="app.routeView(item)"
|
||||
@controller-click="app.routeView(item)"
|
||||
@contextmenu.self="contextMenu"
|
||||
class="cd-mediaitem-square" :class="getClasses()" @contextmenu="contextMenu"
|
||||
v-observe-visibility="{callback: visibilityChanged}"
|
||||
:style="{'--spcolor': getBgColor()}">
|
||||
<template v-if="isVisible">
|
||||
<div class="artwork-container">
|
||||
<div class="unavailable-overlay" v-if="unavailable">
|
||||
<div class="codicon codicon-circle-slash"></div>
|
||||
</div>
|
||||
<div class="artwork" @click='app.routeView(item)'>
|
||||
<mediaitem-artwork
|
||||
:url="getArtworkUrl()"
|
||||
|
@ -12,6 +19,7 @@
|
|||
:size="size"
|
||||
shadow="subtle"
|
||||
:bgcolor="getBgColor()"
|
||||
:video-priority="forceVideo"
|
||||
:type="item.type"></mediaitem-artwork>
|
||||
</div>
|
||||
<button class="menu-btn" v-if="!nomenu.includes(item.type)"
|
||||
|
@ -28,7 +36,7 @@
|
|||
</div>
|
||||
<div class="info-rect" :class="{'info-rect-card': kind == 'card'}" :style="{'--bgartwork': getArtworkUrl(size, true)}">
|
||||
<div class="title" v-if="item.attributes.artistNames == null || kind!= 'card'" @click='app.routeView(item)'>
|
||||
<div class="item-navigate text-overflow-elipsis">{{ item.attributes.name }}</div>
|
||||
<div class="item-navigate text-overflow-elipsis">{{ item.attributes?.name ?? (item.relationships?.contents?.data[0]?.attributes?.name ?? '') }}</div>
|
||||
<div class="explicit-icon" v-if="item.attributes && item.attributes.contentRating == 'explicit'" style= "background-image: url(./assets/explicit.svg);height: 12px;width: 12px;filter: contrast(0);background-repeat: no-repeat;margin-top: 2.63px;margin-left: 4px;"></div>
|
||||
</div>
|
||||
<div class="subtitle item-navigate text-overflow-elipsis" @click="getSubtitleNavigation()"
|
||||
|
@ -57,6 +65,10 @@
|
|||
type: String,
|
||||
default: '190'
|
||||
},
|
||||
forceVideo: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
'contextExt': {type: Object, required: false},
|
||||
},
|
||||
data: function () {
|
||||
|
@ -64,15 +76,25 @@
|
|||
isVisible: false,
|
||||
addedToLibrary: false,
|
||||
guid: this.uuidv4(),
|
||||
noplay: ["apple-curators"],
|
||||
nomenu: ["artists", "stations", "apple-curators"],
|
||||
noplay: ["apple-curators", "editorial-elements"],
|
||||
nomenu: ["artists", "stations", "apple-curators", "editorial-elements"],
|
||||
app: this.$root,
|
||||
badges: this.$root.socialBadges.badgeMap,
|
||||
itemBadges: []
|
||||
itemBadges: [],
|
||||
unavailable: false
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
await this.getBadges()
|
||||
if(typeof this.item.attributes.playParams == "object") {
|
||||
if(this.item.attributes.playParams.kind.includes("radioStation") && (this.item.attributes.playParams.streamingKind == 1 || this.item.attributes.playParams.streamingKind == 2)) {
|
||||
this.unavailable = true
|
||||
}
|
||||
}else{
|
||||
if(this.item.type == "music-movies" || this.item.type == "tv-episodes") {
|
||||
this.unavailable = true
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getBgColor() {
|
||||
|
@ -127,7 +149,7 @@
|
|||
},
|
||||
async getBadges() {
|
||||
const self = this
|
||||
const id = (this.item.attributes.playParams ? this.item.attributes.playParams.id : null) || this.item.id
|
||||
const id = ((this.item.attributes?.playParams ?? false) ? this.item.attributes?.playParams.id : null) || this.item.id
|
||||
if (id && this.badges[id]) {
|
||||
let friends = this.badges[id]
|
||||
if (friends) {
|
||||
|
@ -140,17 +162,19 @@
|
|||
}
|
||||
},
|
||||
revisedRandId() {
|
||||
return Math.random().toString(36).replace(/[^a-z]+/g, '').substr(2, 10);
|
||||
return Math.random().toString(36).replace(/[^a-z]+/g, '').slice(2, 10);
|
||||
},
|
||||
async isInLibrary() {
|
||||
if (this.item.type && !this.item.type.includes("library")) {
|
||||
var params = {
|
||||
"fields[playlists]": "inLibrary",
|
||||
"fields[albums]": "inLibrary",
|
||||
"relate": "library",
|
||||
let params = {
|
||||
relate:"library",
|
||||
"fields":"inLibrary",
|
||||
"extend": this.revisedRandId()
|
||||
}
|
||||
var res = await app.mkapi(this.item.attributes.playParams.kind ?? this.item.type, this.item.attributes.playParams.isLibrary ?? false, this.item.attributes.playParams.id ?? this.item.id, params);
|
||||
let kind = this.item.type ?? this.item.attributes.playParams.kind
|
||||
let truekind = (!kind.endsWith("s")) ? (kind + "s") : kind;
|
||||
if (truekind == "musicVideos") {truekind = "music-videos"}
|
||||
let res = await app.mk.api.v3.music(`/v1/catalog/${app.mk.storefrontId}/?ids[${truekind}]=${this.item.attributes.playParams.id ?? this.item.id}`,params);
|
||||
res = res.data.data[0]
|
||||
this.addedToLibrary = (res && res.attributes && res.attributes.inLibrary) ? res.attributes.inLibrary : false
|
||||
} else {
|
||||
|
@ -158,21 +182,20 @@
|
|||
}
|
||||
},
|
||||
async removeFromLibrary(id) {
|
||||
var params = {
|
||||
"fields[playlists]": "inLibrary",
|
||||
"fields[songs]": "inLibrary",
|
||||
"fields[albums]": "inLibrary",
|
||||
"relate": "library",
|
||||
"extend": this.revisedRandId()
|
||||
}
|
||||
var id = this.item.id ?? this.item.attributes.playParams.id
|
||||
var res = await app.mkapi(this.item.attributes.playParams.kind ?? this.item.type, this.item.attributes.playParams.isLibrary ?? false, this.item.attributes.playParams.id ?? this.item.id, params);
|
||||
let params = {
|
||||
relate:"library",
|
||||
"fields":"inLibrary",
|
||||
"extend": this.revisedRandId()
|
||||
}
|
||||
let kind = this.item.type ?? this.item.attributes.playParams.kind
|
||||
let truekind = (!kind.endsWith("s")) ? (kind + "s") : kind;
|
||||
if (truekind == "musicVideos") {truekind = "music-videos"}
|
||||
let res = await app.mk.api.v3.music(`/v1/catalog/${app.mk.storefrontId}/?ids[${truekind}]=${this.item.attributes.playParams.id ?? this.item.id}`,params);
|
||||
res= res.data.data[0]
|
||||
if (res && res.relationships && res.relationships.library && res.relationships.library.data && res.relationships.library.data.length > 0) {
|
||||
id = res.relationships.library.data[0].id
|
||||
}
|
||||
let kind = this.item.attributes.playParams.kind ?? this.item.type ?? '';
|
||||
var truekind = (!kind.endsWith("s")) ? (kind + "s") : kind;
|
||||
|
||||
app.mk.api.v3.music(`v1/me/library/${truekind}/${id.toString()}`,{},
|
||||
{
|
||||
fetchOptions: {
|
||||
|
@ -192,7 +215,7 @@
|
|||
}
|
||||
switch (this.kind) {
|
||||
case "385":
|
||||
artwork = this.item.attributes.editorialArtwork.subscriptionHero.url
|
||||
artwork = this.item.attributes.editorialArtwork?.subscriptionHero?.url ?? (this.item.attributes.artwork?.url ?? (this.item.relationships?.contents?.data[0]?.attributes?.editorialArtwork?.subscriptionHero?.url ?? ''))
|
||||
break;
|
||||
}
|
||||
if(!includeUrl) {
|
||||
|
@ -202,7 +225,12 @@
|
|||
}
|
||||
},
|
||||
getClasses() {
|
||||
let type = this.item.type
|
||||
let type = []
|
||||
try{
|
||||
type = this.item.type
|
||||
|
||||
}catch(e) {console.log('sd',this.item)}
|
||||
|
||||
if (this.kind != "") {
|
||||
type = this.kind
|
||||
}
|
||||
|
@ -210,6 +238,7 @@
|
|||
default:
|
||||
return []
|
||||
break;
|
||||
case "editorial-elements":
|
||||
case "card":
|
||||
return ["mediaitem-card"]
|
||||
break;
|
||||
|
@ -402,6 +431,18 @@
|
|||
}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)}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
</div>
|
||||
<div class="menu-header-body" v-if="Object.keys(content.headerItems).length != 0">
|
||||
<template v-for="item in content.headerItems">
|
||||
<button class="menu-option-header" :class="getClasses(item)" :title="item.name"
|
||||
<button class="menu-option-header" :class="getClasses(item)" v-b-tooltip.hover :title="item.name"
|
||||
v-if="canDisplay(item)" :style="getItemStyle(item)" @click="action(item)">
|
||||
<div class="sidebar-icon" style="margin: 0;" v-if="item.icon">
|
||||
<div class="svg-icon" :style="{'--url': 'url(' + item.icon + ')'}"></div>
|
||||
|
|
|
@ -6,11 +6,15 @@
|
|||
<span id="mini-pin">📌</span>
|
||||
</div>
|
||||
<div class="player-exit" title="Close" @click="app.miniPlayer(false)">
|
||||
<svg fill="#323232e3" xmlns="http://www.w3.org/2000/svg" width="21" height="21" viewBox="0 0 21 21"
|
||||
aria-role="presentation" focusable="false">
|
||||
<path
|
||||
d="M10.5 21C4.724 21 0 16.275 0 10.5S4.724 0 10.5 0 21 4.725 21 10.5 16.276 21 10.5 21zm-3.543-5.967a.96.96 0 00.693-.295l2.837-2.842 2.85 2.842c.167.167.41.295.693.295.552 0 1.001-.461 1.001-1.012 0-.281-.115-.512-.295-.704L11.899 10.5l2.85-2.855a.875.875 0 00.295-.68c0-.55-.45-.998-1.001-.998a.871.871 0 00-.668.295l-2.888 2.855-2.862-2.843a.891.891 0 00-.668-.281.99.99 0 00-1.001.986c0 .269.116.512.295.678L9.088 10.5l-2.837 2.843a.926.926 0 00-.295.678c0 .551.45 1.012 1.001 1.012z"
|
||||
fill-rule="nonzero"/>
|
||||
<svg fill="#323232e3" width="21" height="21" viewBox="0 0 21 21" aria-role="presentation" focusable="false" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<radialGradient gradientUnits="userSpaceOnUse" cx="10.5" cy="10.5" r="10.5" id="gradient-0">
|
||||
<stop offset="0" style="stop-color: rgba(168, 163, 163, 1)"/>
|
||||
<stop offset="1" style="stop-color: rgba(118, 111, 111, 1)"/>
|
||||
</radialGradient>
|
||||
</defs>
|
||||
<path d="M10.5 21C4.724 21 0 16.275 0 10.5S4.724 0 10.5 0 21 4.725 21 10.5 16.276 21 10.5 21zm-3.543-5.967a.96.96 0 00.693-.295l2.837-2.842 2.85 2.842c.167.167.41.295.693.295.552 0 1.001-.461 1.001-1.012 0-.281-.115-.512-.295-.704L11.899 10.5l2.85-2.855a.875.875 0 00.295-.68c0-.55-.45-.998-1.001-.998a.871.871 0 00-.668.295l-2.888 2.855-2.862-2.843a.891.891 0 00-.668-.281.99.99 0 00-1.001.986c0 .269.116.512.295.678L9.088 10.5l-2.837 2.843a.926.926 0 00-.295.678c0 .551.45 1.012 1.001 1.012z"
|
||||
fill-rule="nonzero" style="stroke-miterlimit: 11; vector-effect: non-scaling-stroke; stroke-width: 31px; fill: url(#gradient-0);"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="col artwork-col">
|
||||
|
@ -44,8 +48,8 @@
|
|||
<div class="song-progress">
|
||||
<div class="song-duration" style="justify-content: space-between; height: 1px; margin-bottom: 1px;"
|
||||
:style="[app.chrome.progresshover ? {'display': 'flex'} : {'display' : 'none'} ]">
|
||||
<p style="width: auto">{{ app.convertToMins(app.getSongProgress()) }}</p>
|
||||
<p style="width: auto">{{ app.convertToMins(app.mk.currentPlaybackDuration) }}</p>
|
||||
<p style="width: auto">{{ app.convertTime(app.getSongProgress()) }}</p>
|
||||
<p style="width: auto">{{ app.convertTime(app.mk.currentPlaybackDuration) }}</p>
|
||||
</div>
|
||||
|
||||
<input type="range" step="0.01" min="0" :style="app.progressBarStyle()"
|
||||
|
@ -69,7 +73,7 @@
|
|||
<button class="playback-button play" @click="app.mk.play()" v-else></button>
|
||||
</div>
|
||||
<div class="app-chrome-item">
|
||||
<button class="playback-button next" @click="app.mk.skipToNextItem()"></button>
|
||||
<button class="playback-button next" @click="app.skipToNextItem()"></button>
|
||||
</div>
|
||||
<div class="app-chrome-item">
|
||||
<button class="playback-button--small repeat" v-if="app.mk.repeatMode == 0"
|
||||
|
@ -83,7 +87,7 @@
|
|||
<div class="app-chrome-item volume display--large">
|
||||
<div class="input-container">
|
||||
<button class="volume-button--small volume" @click="app.muteButtonPressed()" :class="{'active': app.cfg.audio.volume == 0}"></button>
|
||||
<input type="range" class="slider" @wheel="app.volumeWheel" step="0.01" min="0" max="1" v-model="app.mk.volume"
|
||||
<input type="range" class="slider" @wheel="app.volumeWheel" :step="app.cfg.audio.volumeStep" min="0" :max="app.cfg.audio.maxVolume" v-model="app.mk.volume"
|
||||
v-if="typeof app.mk.volume != 'undefined'" @change="app.checkMuteChange()">
|
||||
</div>
|
||||
</div>
|
||||
|
@ -151,6 +155,9 @@
|
|||
beforeDestroy() {
|
||||
window.removeEventListener('keyup', this.onEscapeKeyUp)
|
||||
},
|
||||
mounted() {
|
||||
app.pinMiniPlayer(true)
|
||||
},
|
||||
methods: {
|
||||
onEscapeKeyUp(event) {
|
||||
if (event.which === 27) {
|
||||
|
|
39
src/renderer/views/components/plugin-menu.ejs
Normal file
39
src/renderer/views/components/plugin-menu.ejs
Normal file
|
@ -0,0 +1,39 @@
|
|||
<script type="text/x-template" id="plugin-menu">
|
||||
<div class="modal-fullscreen addtoplaylist-panel" @click.self="app.resetState()" @contextmenu.self="app.resetState()">
|
||||
<div class="modal-window">
|
||||
<div class="modal-header">
|
||||
<div class="modal-title">{{$root.getLz('term.pluginMenu')}}</div>
|
||||
<button class="close-btn" @click="app.resetState()"></button>
|
||||
</div>
|
||||
<div class="modal-content">
|
||||
<span class="playlist-item" v-if="!app.pluginInstalled">
|
||||
<span class="icon"><%- include("../svg/x.svg") %></span>
|
||||
<span class="name" style="top: 0.5px;">{{$root.getLz('term.pluginMenu.none')}}</span>
|
||||
</span>
|
||||
<button class="playlist-item" @click="entry.onClick(); closeMenu();" v-for="entry in app.pluginMenuEntries">
|
||||
<span class="icon"><%- include("../svg/grid.svg") %></span>
|
||||
<span class="name" style="top: 0.5px;">{{ entry.name }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('plugin-menu', {
|
||||
template: '#plugin-menu',
|
||||
data: function () {
|
||||
return {
|
||||
app: this.$root,
|
||||
}
|
||||
},
|
||||
props: {},
|
||||
mounted() {},
|
||||
methods: {
|
||||
closeMenu() {
|
||||
app.modals.pluginMenu = false
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
</script>
|
|
@ -1,65 +0,0 @@
|
|||
<script type="text/x-template" id="queue-item">
|
||||
<template>
|
||||
<div v-observe-visibility="{callback: visibilityChanged}"
|
||||
@contextmenu="contextMenu"
|
||||
class="cd-mediaitem-list-item">
|
||||
<template v-if="isVisible">
|
||||
<div class="artwork">
|
||||
<mediaitem-artwork
|
||||
:url="item.attributes.artwork ? item.attributes.artwork.url : ''"
|
||||
size="34"
|
||||
:type="item.type"></mediaitem-artwork>
|
||||
</div>
|
||||
<div class="info-rect" :style="{'padding-left': '16px'}">
|
||||
<div class="title text-overflow-elipsis">
|
||||
{{ item.attributes.name }}
|
||||
</div>
|
||||
<div class="subtitle text-overflow-elipsis" style="-webkit-box-orient: horizontal;">
|
||||
<template v-if="item.attributes.artistName" >
|
||||
<div class="artist item-navigate text-overflow-elipsis" @click="app.searchAndNavigate(item,'artist')">
|
||||
{{ item.attributes.artistName }}
|
||||
</div>
|
||||
<template v-if="item.attributes.albumName"> — </template>
|
||||
<template v-if="item.attributes.albumName">
|
||||
<div class="artist item-navigate text-overflow-elipsis" @click="app.searchAndNavigate(item,'album')">
|
||||
{{ item.attributes.albumName }}
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="duration">
|
||||
{{ msToMinSec(item.attributes.durationInMillis ?? 0) }}
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('queue-item', {
|
||||
template: '#queue-item',
|
||||
props: ['item'],
|
||||
data: function () {
|
||||
return {}
|
||||
},
|
||||
methods: {
|
||||
contextMenu(event) {
|
||||
let self = this
|
||||
CiderContextMenu.Create(event, {
|
||||
items: [{
|
||||
"name": $root.getLz('action.removeFromQueue'),
|
||||
"action": function () {
|
||||
|
||||
}
|
||||
}]
|
||||
});
|
||||
},
|
||||
msToMinSec(ms) {
|
||||
var minutes = Math.floor(ms / 60000);
|
||||
var seconds = ((ms % 60000) / 1000).toFixed(0);
|
||||
return minutes + ":" + (seconds < 10 ? '0' : '') + seconds;
|
||||
},
|
||||
}
|
||||
});
|
||||
</script>
|
|
@ -8,7 +8,10 @@
|
|||
<button class="autoplay" :style="{'background': app.mk.autoplayEnabled ? 'var(--keyColor)' : ''}" @click="app.mk.autoplayEnabled = !app.mk.autoplayEnabled"> <img class="infinity"></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="queue-body">
|
||||
<div class="queue-body" v-if="page == 'history'">
|
||||
<mediaitem-list-item :show-library-status="false" v-for="item in history" :item="item"></mediaitem-list-item>
|
||||
</div>
|
||||
<div class="queue-body" v-if="page == 'queue'">
|
||||
<draggable v-model="queueItems" @start="drag=true" @end="drag=false;move()">
|
||||
<template v-for="(queueItem, position) in queueItems">
|
||||
<div v-if="position <= queuePosition" style="display: none;">{{ position }}</div>
|
||||
|
@ -33,7 +36,11 @@
|
|||
</draggable>
|
||||
</div>
|
||||
<div class="queue-footer">
|
||||
<button class="md-btn" style="width:100%;" v-if="queueItems.length > 1" @click="app.mk.clearQueue();updateQueue()">{{app.getLz('term.clearAll')}}</button>
|
||||
<div class="btn-group" style="width:100%;">
|
||||
<button class="md-btn md-btn-small" :class="{'md-btn-primary': (page == 'queue')}" @click="page = 'queue'">{{app.getLz('term.queue')}}</button>
|
||||
<button class="md-btn md-btn-small" :class="{'md-btn-primary': (page == 'history')}" @click="getHistory();page = 'history'">{{app.getLz('term.history')}}</button>
|
||||
</div>
|
||||
<button class="md-btn md-btn-small" style="width:100%;margin-top:6px;" v-if="queueItems.length > 1" @click="app.mk.clearQueue();updateQueue()">{{app.getLz('term.clearAll')}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
@ -49,6 +56,8 @@
|
|||
queueItems: [],
|
||||
selected: -1,
|
||||
selectedItems: [],
|
||||
history: [],
|
||||
page: "queue",
|
||||
app: this.$root
|
||||
}
|
||||
},
|
||||
|
@ -56,6 +65,10 @@
|
|||
this.updateQueue()
|
||||
},
|
||||
methods: {
|
||||
async getHistory() {
|
||||
let history = await app.mk.api.v3.music(`/v1/me/recent/played/tracks`, { l : this.$root.mklang})
|
||||
this.history = history.data.data
|
||||
},
|
||||
select(e, position) {
|
||||
if(e.ctrlKey || e.shiftKey) {
|
||||
if(this.selectedItems.indexOf(position) == -1) {
|
||||
|
@ -81,8 +94,8 @@
|
|||
self.queueItems.splice(position, 1)
|
||||
app.mk.queue._queueItems = self.queueItems;
|
||||
app.mk.queue._reindex()
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": app.getLz('action.startRadio'),
|
||||
"action": function () {
|
||||
|
@ -93,6 +106,18 @@
|
|||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": app.getLz('action.goToArtist'),
|
||||
"action": function () {
|
||||
app.searchAndNavigate(item,'artist')
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": app.getLz('action.goToAlbum'),
|
||||
"action": function () {
|
||||
app.searchAndNavigate(item,'album')
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
multiple: {
|
||||
|
|
88
src/renderer/views/components/share-sheet.ejs
Normal file
88
src/renderer/views/components/share-sheet.ejs
Normal file
|
@ -0,0 +1,88 @@
|
|||
<script type="text/x-template" id="add-to-playlist">
|
||||
<template>
|
||||
<div class="modal-fullscreen addtoplaylist-panel" @click.self="app.resetState()" @contextmenu.self="app.resetState()">
|
||||
<div class="modal-window">
|
||||
<div class="modal-header">
|
||||
<div class="modal-title">{{app.getLz('action.addToPlaylist')}}</div>
|
||||
<button class="close-btn" @click="app.resetState()"></button>
|
||||
</div>
|
||||
<div class="modal-content">
|
||||
<button class="playlist-item"
|
||||
@click="app.addSelectedToNewPlaylist()" style="width:100%;">
|
||||
<div class="icon"><%- include("../svg/plus.svg") %></div>
|
||||
<div class="name">{{app.getLz('action.createPlaylist')}}</div>
|
||||
</button>
|
||||
<sidebar-playlist :playlist-select="playlistSelect" v-for="item in $root.getPlaylistFolderChildren('p.playlistsroot')" :item="item">
|
||||
</sidebar-playlist>
|
||||
</div>
|
||||
<div class="modal-search">
|
||||
<div class="search-input-container" style="width:100%;margin: 16px 0;">
|
||||
<div class="search-input--icon"></div>
|
||||
<input type="search"
|
||||
ref="searchInput"
|
||||
style="width:100%;"
|
||||
spellcheck="false"
|
||||
:placeholder="app.getLz('term.search') + '...'"
|
||||
v-model="searchQuery"
|
||||
@input="search()"
|
||||
class="search-input">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('add-to-playlist', {
|
||||
template: '#add-to-playlist',
|
||||
data: function () {
|
||||
return {
|
||||
playlistSorted: [],
|
||||
searchQuery: "",
|
||||
focused: "",
|
||||
app: this.$root,
|
||||
}
|
||||
},
|
||||
props: {
|
||||
playlists: {
|
||||
type: Array,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.search()
|
||||
this.$refs.searchInput.focus()
|
||||
this.$refs.searchInput.addEventListener('keydown', (e) => {
|
||||
if (e.keyCode == 13) {
|
||||
if (this.focused != "") {
|
||||
this.addToPlaylist(this.focused)
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
playlistSelect(playlist) {
|
||||
if(playlist.type != "library-playlist-folders") {
|
||||
this.addToPlaylist(playlist.id)
|
||||
}
|
||||
},
|
||||
addToPlaylist(id) {
|
||||
app.addSelectedToPlaylist(id)
|
||||
},
|
||||
search() {
|
||||
this.focused = ""
|
||||
if (this.searchQuery == "") {
|
||||
this.playlistSorted = this.playlists
|
||||
} else {
|
||||
this.playlistSorted = this.playlists.filter(playlist => {
|
||||
return playlist.attributes.name.toLowerCase().indexOf(this.searchQuery.toLowerCase()) > -1
|
||||
})
|
||||
if (this.playlistSorted.length == 1) {
|
||||
this.focused = this.playlistSorted[0].id
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
||||
</script>
|
|
@ -9,13 +9,14 @@
|
|||
:href="item.href"
|
||||
@click='clickEvent()'>
|
||||
<template v-if="!renaming">
|
||||
<div class="sidebar-icon" v-html="icon"></div> {{ item.attributes.name }}
|
||||
<div class="sidebar-icon" :key="item.id" v-html="icon"></div> {{ item.attributes.name }}
|
||||
<small class="presentNotice" v-if="hasRelatedMediaItems">(Track present)</small>
|
||||
</template>
|
||||
<input type="text" v-model="item.attributes.name" class="pl-rename-field" @blur="rename()" @keydown.enter="rename()" v-else>
|
||||
</button>
|
||||
<div class="folder-body" v-if="item.type === 'library-playlist-folders' && folderOpened">
|
||||
<template v-if="children.length != 0">
|
||||
<sidebar-playlist v-for="item in children" :playlist-select="playlistSelect" :item="item" :key="item.id"></sidebar-playlist>
|
||||
<sidebar-playlist v-for="item in children" :relate-media-items="relateMediaItems" :playlist-select="playlistSelect" :item="item" :key="item.id"></sidebar-playlist>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="spinner"></div>
|
||||
|
@ -35,6 +36,13 @@
|
|||
playlistSelect: {
|
||||
type: Function,
|
||||
required: false
|
||||
},
|
||||
relateMediaItems: {
|
||||
type: Array,
|
||||
required: false,
|
||||
default () {
|
||||
return []
|
||||
}
|
||||
}
|
||||
},
|
||||
data: function () {
|
||||
|
@ -43,7 +51,8 @@
|
|||
children: [],
|
||||
playlistRoot: "p.playlistsroot",
|
||||
renaming: false,
|
||||
icon: ""
|
||||
icon: "",
|
||||
hasRelatedMediaItems: false
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
|
@ -52,6 +61,12 @@
|
|||
} else {
|
||||
this.icon = await this.$root.getSvgIcon("./assets/feather/folder.svg")
|
||||
}
|
||||
let playlistMap = this.$root.playlists.trackMapping
|
||||
if(this.relateMediaItems.length != 0) {
|
||||
if(playlistMap[this.relateMediaItems[0]].includes(this.item.id)) {
|
||||
this.hasRelatedMediaItems = true
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
clickEvent() {
|
||||
|
@ -189,7 +204,7 @@
|
|||
openPlaylist(item) {
|
||||
this.$root.appRoute(`playlist_` + item.id);
|
||||
this.$root.showingPlaylist = [];
|
||||
this.$root.getPlaylistFromID(this.$root.page.substring(9))
|
||||
this.$root.getPlaylistFromID(this.$root.page.substring(9), true)
|
||||
},
|
||||
getPlaylistChildren(item) {
|
||||
let self = this
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue