Skip to content

Commit

Permalink
Changed wording around Playlists to be Queue. Added automatic logout …
Browse files Browse the repository at this point in the history
…if user get 401 error code. Fixes issues #7 and #9
  • Loading branch information
m0ngr31 committed Aug 4, 2020
1 parent 7686a05 commit 91cd5bd
Show file tree
Hide file tree
Showing 14 changed files with 137 additions and 81 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
</p>

## About
A stylish, cross-platform desktop client for listening to music from a Jellyfin server. Inspired by Plexamp.
A stylish, cross-platform desktop client for listening to music from a Jellyfin server. Inspired by Plexamp.

## In Action

Expand Down Expand Up @@ -36,7 +36,7 @@ A stylish, cross-platform desktop client for listening to music from a Jellyfin
<img src="https://i.imgur.com/HmVRw8r.png" width="400">
</p>

### Playlist Page
### Queue Page
<p>
<img src="https://i.imgur.com/6dTb11U.png" width="400">
</p>
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "jellyamp",
"version": "0.9.6",
"version": "0.9.7",
"private": true,
"description": "Desktop client for listening to music from a Jellyfin server",
"license": "MIT",
Expand Down
6 changes: 6 additions & 0 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,19 @@
import Vue from 'vue';
import Component from 'vue-class-component';
import {Notifications} from './services/notifications';
@Component({
name: 'App',
})
export default class App extends Vue {
isElectron = window.ipcRenderer ? true : false;
distro = process.env.VUE_APP_OS;
mounted() {
Notifications.service = this.$buefy.toast;
}
close() {
if (this.isElectron) {
window.electronRemote.getCurrentWindow().close();
Expand Down
20 changes: 10 additions & 10 deletions src/components/Player.vue
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
<template>
<div v-if="player.player">
<Playlist v-if="player.showPlaylist"></Playlist>
<Queue v-if="player.showQueue"></Queue>
<div class="player" v-show="!miniPlayer" :style="`height: calc(100vh ${isElectron ? '- 26px' : ''});`">
<img class="bg-album update-img">
<div class="container">
<div class="level-bottom level is-mobile" style="padding: 15px 15px 0px 15px;">
<div level-left @click="togglePlayer()">
<b-icon level-item size="is-medium" icon="chevron-down" class="pointer"></b-icon>
</div>
<div level-right @click="player.showPlaylist = true">
<div level-right @click="player.showQueue = true">
<b-icon level-item size="is-medium" icon="playlist-music" class="pointer"></b-icon>
</div>
</div>
Expand All @@ -25,11 +25,11 @@
<div class="level-bottom level is-mobile">
<div level-item style="width: 30px"></div>
<div level-item class="middle" style="width: 100%; text-align: center">
<h6 class="title is-5 song-title">{{ player.playlist[player.index].Name }}</h6>
<h6 class="subtitle is-6 song-title">{{ player.playlist[player.index].artist }}</h6>
<h6 class="title is-5 song-title">{{ player.queue[player.index].Name }}</h6>
<h6 class="subtitle is-6 song-title">{{ player.queue[player.index].artist }}</h6>
</div>
<div level-item class="ends" style="text-align: right; width: 30px;" @click="likeSong">
<b-icon level-item :icon="`${player.playlist[player.index].loved ? 'heart' : 'heart-outline'}`" :type="`${player.playlist[player.index].loved ? 'is-danger' : ''}`" class="pointer"></b-icon>
<b-icon level-item :icon="`${player.queue[player.index].loved ? 'heart' : 'heart-outline'}`" :type="`${player.queue[player.index].loved ? 'is-danger' : ''}`" class="pointer"></b-icon>
</div>
</div>
<div class="level-bottom level is-mobile" style="margin-bottom: 0">
Expand Down Expand Up @@ -83,12 +83,12 @@
<img level-item src="../assets/logo.png" class="album-art update-img">
</div>
<div level-item class="middle" @click="miniPlayer = false">
<h6 class="title is-6 song-title">{{ player.playlist[player.index].Name }}</h6>
<h6 class="subtitle is-6 song-title">{{ player.playlist[player.index].artist }}</h6>
<h6 class="title is-6 song-title">{{ player.queue[player.index].Name }}</h6>
<h6 class="subtitle is-6 song-title">{{ player.queue[player.index].artist }}</h6>
</div>
<div level-right class="ends">
<span @click="likeSong">
<b-icon level-item :icon="`${player.playlist[player.index].loved ? 'heart' : 'heart-outline'}`" :type="`${player.playlist[player.index].loved ? 'is-danger' : ''}`"></b-icon>
<b-icon level-item :icon="`${player.queue[player.index].loved ? 'heart' : 'heart-outline'}`" :type="`${player.queue[player.index].loved ? 'is-danger' : ''}`"></b-icon>
</span>
<span @click="playPause">
<b-icon level-item :icon="`${player.playing ? 'pause' : 'play'}`"></b-icon>
Expand All @@ -106,12 +106,12 @@ import Component from 'vue-class-component';
import JellyfinService from '../services/jellyfin';
import PlayerService from '../services/player';
import Playlist from '../components/Playlist';
import Queue from '../components/Queue';
@Component({
name: 'Player',
components: {
Playlist,
Queue,
}
})
export default class Player extends Vue {
Expand Down
18 changes: 9 additions & 9 deletions src/components/Playlist.vue → src/components/Queue.vue
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
<template>
<div
class="playlist overflowY"
class="queue overflowY"
:style="`height: calc(100vh ${isElectron ? '- 26px' : ''}); top: ${isElectron ? 26 : 0}px`"
>
<div class="container">
<div class="level is-mobile">
<div class="level-left" @click="player.showPlaylist = false">
<div class="level-left" @click="player.showQueue = false">
<b-icon level-item size="is-medium" icon="chevron-left" class="pointer"></b-icon>
<p level-item class="title">Playlist</p>
<p level-item class="title">Queue</p>
</div>
</div>
<div
class="playlist-item pointer"
v-for="(song, index) of player.playlist"
class="queue-item pointer"
v-for="(song, index) of player.queue"
v-bind:key="`${song.Id}${index}`"
>
<div class="level is-mobile">
Expand Down Expand Up @@ -40,9 +40,9 @@ import JellyfinService from '../services/jellyfin';
import PlayerService from '../services/player';
@Component({
name: 'Playlist',
name: 'Queue',
})
export default class Playlist extends Vue {
export default class Queue extends Vue {
isElectron = window.ipcRenderer ? true : false;
player = PlayerService;
Expand All @@ -57,15 +57,15 @@ export default class Playlist extends Vue {
</script>

<style scoped>
.playlist {
.queue {
padding: 15px;
background-color: #000B25;
z-index: 150;
position: fixed;
width: 100%;
}
.playlist-item {
.queue-item {
height: 60px;
width: 100%;
}
Expand Down
10 changes: 9 additions & 1 deletion src/services/jellyfin.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {v4 as uuidv4 } from 'uuid';

import {getItemOrDefault, setItem} from './localstorage';
import router from '../router/index';
import {getItemOrDefault, setItem, removeItem} from './localstorage';
import {Requests} from './requests';

const cleanUrl = url => {
Expand Down Expand Up @@ -56,6 +57,13 @@ const JellyfinService = {
throw new Error('Could not login');
}
},
logout: () => {
removeItem('api-token');
removeItem('server');
removeItem('user');

router.push({name: 'Login'});
},
getUsers: async () => {
const users = await Requests.get('users/public', null, true, false);
console.log(users);
Expand Down
8 changes: 8 additions & 0 deletions src/services/localstorage.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,11 @@ export function setItem(key, data) {

localStorage.setItem(key, JSON.stringify(data));
}

export function removeItem(key) {
if (!typeof (Storage)) {
return;
}

localStorage.removeItem(key);
}
3 changes: 3 additions & 0 deletions src/services/notifications.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const Notifications = {
service: null,
};
50 changes: 25 additions & 25 deletions src/services/player.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ Vue.filter('duration', value => {
});

class Player {
playlist = [];
queue = [];
index = null;
player = null;
viewModel = null;
showPlaylist = false;
showQueue = false;
playing = true;

lastPrev = -1;
Expand All @@ -32,8 +32,8 @@ class Player {
IsPaused: false,
PositionTicks: ticks, // Convert to ticks/ns
PlayMethod: 'Transcode',
PlaySessionId: this.playlist[this.index].params.PlaySessionId,
ItemId: this.playlist[this.index].Id,
PlaySessionId: this.queue[this.index].params.PlaySessionId,
ItemId: this.queue[this.index].Id,
EventName: 'timeupdate',
};

Expand All @@ -58,25 +58,25 @@ class Player {
clearHowl() {
this.player.unload();
this.player = null;
this.playlist[this.index].howl = null;
this.queue[this.index].howl = null;
}

setPlaylist(playlist) {
setQueue(queue) {
if (this.player) {
this.player.stop();
this.player = null;
}

Howler.stop();

this.playlist = _.map(playlist, (item, index) => {
this.queue = _.map(queue, (item, index) => {
const songUrl = JellyfinService.getItemImageUrl(item);
item.thumbnailImage = songUrl ? songUrl : placeholderImg;

item.artist = item.Artists[0] || item.AlbumArtist;
item.loved = item.UserData.IsFavorite || false;

// Preload the first 3 items in the playlist
// Preload the first 3 items in the queue
if (index < 3) {
item.howl = this.createHowl(item);
}
Expand All @@ -87,8 +87,8 @@ class Player {
this.play(0);
}

injectPlaylist(playlist) {
const updatePlaylist = _.map(playlist, item => {
injectQueue(queue) {
const updateQueue = _.map(queue, item => {
const songUrl = JellyfinService.getItemImageUrl(item);
item.thumbnailImage = songUrl ? songUrl : placeholderImg;

Expand All @@ -98,15 +98,15 @@ class Player {
return item;
});

if (this.index === this.playlist.length - 1) {
this.playlist = [...this.playlist, ...updatePlaylist];
if (this.index === this.queue.length - 1) {
this.queue = [...this.queue, ...updateQueue];
} else {
this.playlist.splice(this.index + 1, 0, ...playlist);
this.queue.splice(this.index + 1, 0, ...queue);
}
}

removeItem(index) {
this.playlist.splice(index, 1);
this.queue.splice(index, 1);

if (index < this.index) {
this.index -= 1;
Expand All @@ -119,12 +119,12 @@ class Player {
}

try {
if (this.playlist[this.index].loved) {
await JellyfinService.unlikeId(this.playlist[this.index].Id);
this.playlist[this.index].loved = false;
if (this.queue[this.index].loved) {
await JellyfinService.unlikeId(this.queue[this.index].Id);
this.queue[this.index].loved = false;
} else {
await JellyfinService.likeId(this.playlist[this.index].Id);
this.playlist[this.index].loved = true;
await JellyfinService.likeId(this.queue[this.index].Id);
this.queue[this.index].loved = true;
}
} catch (e) {
console.log(e);
Expand All @@ -145,9 +145,9 @@ class Player {
if (this.viewModel && this.viewModel.$el) {
const images = this.viewModel.$el.querySelectorAll('.update-img');
images.forEach((image, index) => {
image.setAttribute('src', this.playlist[this.index].thumbnailImage);
image.setAttribute('src', this.queue[this.index].thumbnailImage);

if (this.playlist[this.index].thumbnailImage === placeholderImg && index === 0) {
if (this.queue[this.index].thumbnailImage === placeholderImg && index === 0) {
image.removeAttribute('src');
}
});
Expand Down Expand Up @@ -255,7 +255,7 @@ class Player {
}

play(index) {
if (!this.playlist.length || index < 0 || index >= this.playlist.length) {
if (!this.queue.length || index < 0 || index >= this.queue.length) {
return;
}

Expand All @@ -264,7 +264,7 @@ class Player {
}

this.index = index;
const data = this.playlist[index];
const data = this.queue[index];

if (!data.howl) {
data.howl = this.createHowl(data);
Expand Down Expand Up @@ -323,7 +323,7 @@ class Player {

const ticks = Math.round(seek * 10000000);

this.playlist[this.index].progressInTicks = ticks;
this.queue[this.index].progressInTicks = ticks;
this.updateProgress(ticks);
this.updateProgressMpris(ticks);
}
Expand All @@ -349,7 +349,7 @@ class Player {

if (dir === 'next') {
index = index + 1;
if (index >= this.playlist.length) {
if (index >= this.queue.length) {
this.clearHowl();
}
} else {
Expand Down
Loading

0 comments on commit 91cd5bd

Please sign in to comment.