Commit ef025358 authored by Andreas Heimann's avatar Andreas Heimann

removed popular tab, implemented userprofile, implemented new search api syntax

parent 61ec76cf
{ {
"name": "spinshare-client", "name": "spinshare-client",
"version": "2.4.0", "version": "2.5.0",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
...@@ -9002,9 +9002,9 @@ ...@@ -9002,9 +9002,9 @@
} }
}, },
"node-forge": { "node-forge": {
"version": "0.9.0", "version": "0.10.0",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.0.tgz", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
"integrity": "sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ==", "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==",
"dev": true "dev": true
}, },
"node-ipc": { "node-ipc": {
...@@ -11281,12 +11281,12 @@ ...@@ -11281,12 +11281,12 @@
"dev": true "dev": true
}, },
"selfsigned": { "selfsigned": {
"version": "1.10.7", "version": "1.10.8",
"resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.7.tgz", "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.8.tgz",
"integrity": "sha512-8M3wBCzeWIJnQfl43IKwOmC4H/RAp50S8DF60znzjW5GVqTcSe2vWclt7hmYVPkKPlHWOu5EaWOMZ2Y6W8ZXTA==", "integrity": "sha512-2P4PtieJeEwVgTU9QEcwIRDQ/mXJLX8/+I3ur+Pg16nS8oNbrGxEso9NyYWy8NAmXiNl4dlAp5MwoNeCWzON4w==",
"dev": true, "dev": true,
"requires": { "requires": {
"node-forge": "0.9.0" "node-forge": "^0.10.0"
} }
}, },
"semver": { "semver": {
......
...@@ -21,8 +21,6 @@ ...@@ -21,8 +21,6 @@
import { remote, ipcRenderer } from 'electron'; import { remote, ipcRenderer } from 'electron';
const { app, dialog } = remote; const { app, dialog } = remote;
import fs from 'fs';
import glob from 'glob';
import path from 'path'; import path from 'path';
import UserSettings from '@/modules/module.usersettings.js'; import UserSettings from '@/modules/module.usersettings.js';
......
...@@ -17,7 +17,41 @@ ...@@ -17,7 +17,41 @@
<i class="mdi mdi-download-outline"></i> <i class="mdi mdi-download-outline"></i>
<span class="indicator" v-show="downloadQueueCount > 0">{{ downloadQueueCount }}</span> <span class="indicator" v-show="downloadQueueCount > 0">{{ downloadQueueCount }}</span>
</div> </div>
<router-link to="/settings" class="item" v-tooltip.down="'Settings'"><i class="mdi mdi-cog-outline"></i></router-link> <div class="item item-user" tabindex="0" v-if="userData != null">
<div class="user-avatar" :style="'background-image: url(' + userData.avatar + ');'"></div>
<div class="user-actions">
<router-link :to="{ name: 'UserDetailCharts', params: { id: userData.id } }" class="user-action-item">
<i class="mdi mdi-music"></i>
<span>My Charts</span>
</router-link>
<router-link :to="{ name: 'UserDetailReviews', params: { id: userData.id } }" class="user-action-item">
<i class="mdi mdi-playlist-music"></i>
<span>My Playlists</span>
</router-link>
<router-link :to="{ name: 'UserDetailSpinPlays', params: { id: userData.id } }" class="user-action-item">
<i class="mdi mdi-thumbs-up-down"></i>
<span>My Reviews</span>
</router-link>
<router-link :to="{ name: 'UserDetailSpinPlays', params: { id: userData.id } }" class="user-action-item">
<i class="mdi mdi-youtube"></i>
<span>My SpinPlays</span>
</router-link>
<div class="user-action-spacer"></div>
<router-link to="/settings" class="user-action-item">
<i class="mdi mdi-cog"></i>
<span>App-Settings</span>
</router-link>
<div v-on:click="openExternal('https://spinsha.re/settings')" class="user-action-item">
<i class="mdi mdi-cog"></i>
<span>Account-Settings</span>
</div>
<div class="user-action-spacer"></div>
<div v-on:click="userLogout()" class="user-action-item">
<i class="mdi mdi-close-circle-outline"></i>
<span>Logout</span>
</div>
</div>
</div>
</nav> </nav>
</aside> </aside>
</template> </template>
...@@ -26,12 +60,33 @@ ...@@ -26,12 +60,33 @@
import { remote } from 'electron'; import { remote } from 'electron';
const { shell } = remote; const { shell } = remote;
import SSAPI from '@/modules/module.api.js';
import UserSettings from '@/modules/module.usersettings.js';
export default { export default {
name: 'Navigation', name: 'Navigation',
props: [ props: [
'downloadQueueCount', 'downloadQueueCount',
'downloadOverlayShown' 'downloadOverlayShown'
], ],
data: function() {
return {
userData: {}
}
},
mounted: function () {
let userSettings = new UserSettings();
if(!userSettings.get("connectProfile")) {
this.$router.replace({ name: 'Login' });
}
this.$data.userData = userSettings.get("connectProfile");
this.$root.$on("LoadIntoProfile", (data) => {
this.$data.userData = data;
});
},
methods: { methods: {
navigateBack: function() { navigateBack: function() {
this.$router.back(); this.$router.back();
...@@ -41,6 +96,13 @@ ...@@ -41,6 +96,13 @@
}, },
openExternal: function(url) { openExternal: function(url) {
shell.openExternal(url); shell.openExternal(url);
},
userLogout: function() {
let userSettings = new UserSettings();
userSettings.set("connectProfile", null);
userSettings.set("connectToken", null);
window.location.reload();
} }
} }
} }
...@@ -237,6 +299,7 @@ ...@@ -237,6 +299,7 @@
position: absolute; position: absolute;
top: 70px; top: 70px;
right: 10px; right: 10px;
overflow: hidden;
border-radius: 4px; border-radius: 4px;
background: #000; background: #000;
box-shadow: 0px 4px 12px rgba(0,0,0,0.6); box-shadow: 0px 4px 12px rgba(0,0,0,0.6);
...@@ -264,6 +327,12 @@ ...@@ -264,6 +327,12 @@
background: rgba(255,255,255,0.1); background: rgba(255,255,255,0.1);
} }
} }
& .user-action-spacer {
margin: 5px 15px;
height: 1px;
width: auto;
background: rgba(255,255,255,0.2);
}
&:after { &:after {
bottom: 100%; bottom: 100%;
......
...@@ -132,22 +132,6 @@ class SSAPI { ...@@ -132,22 +132,6 @@ class SSAPI {
}); });
} }
async getPopularSongs(_offset) {
let apiPath = this.apiBase + "songs/popular/" + _offset;
let supportedVersion = this.supportedVersion;
return axios.get(apiPath)
.then(function(response) {
if(response.data.version !== supportedVersion) {
throw new Error("Client is outdated!");
}
return response.data.data;
}).catch(function(error) {
throw new Error(error);
});
}
async getSongDetail(_songId) { async getSongDetail(_songId) {
let apiPath = this.apiBase + "song/" + _songId; let apiPath = this.apiBase + "song/" + _songId;
let supportedVersion = this.supportedVersion; let supportedVersion = this.supportedVersion;
...@@ -277,10 +261,12 @@ class SSAPI { ...@@ -277,10 +261,12 @@ class SSAPI {
} }
async search(_searchQuery) { async search(_searchQuery) {
let apiPath = this.apiBase + "search/" + _searchQuery; let apiPath = this.apiBase + "search";
let supportedVersion = this.supportedVersion; let supportedVersion = this.supportedVersion;
return axios.get(apiPath) return axios.get(apiPath, {
searchQuery: _searchQuery
})
.then(function(response) { .then(function(response) {
if(response.data.version !== supportedVersion) { if(response.data.version !== supportedVersion) {
throw new Error("Client is outdated!"); throw new Error("Client is outdated!");
...@@ -346,6 +332,22 @@ class SSAPI { ...@@ -346,6 +332,22 @@ class SSAPI {
throw new Error(error); throw new Error(error);
}); });
} }
async getConnectProfile(connectToken) {
let apiPath = this.apiBase + "connect/profile/?connectToken=" + connectToken;
let supportedVersion = this.supportedVersion;
return axios.get(apiPath)
.then(function(response) {
if(response.data.version !== supportedVersion) {
throw new Error("Client is outdated!");
}
return response.data.data;
}).catch(function(error) {
throw new Error(error);
});
}
} }
module.exports = SSAPI; module.exports = SSAPI;
...@@ -7,7 +7,6 @@ import ViewStartup from '../views/Startup.vue'; ...@@ -7,7 +7,6 @@ import ViewStartup from '../views/Startup.vue';
import ViewStartupFrontpage from '../views/StartupFrontpage.vue'; import ViewStartupFrontpage from '../views/StartupFrontpage.vue';
import ViewStartupNewSongs from '../views/StartupNewSongs.vue'; import ViewStartupNewSongs from '../views/StartupNewSongs.vue';
import ViewStartupHotSongs from '../views/StartupHotSongs.vue'; import ViewStartupHotSongs from '../views/StartupHotSongs.vue';
import ViewStartupPopularSongs from '../views/StartupPopularSongs.vue';
import ViewSearch from '../views/Search.vue'; import ViewSearch from '../views/Search.vue';
import ViewLibrary from '../views/Library.vue'; import ViewLibrary from '../views/Library.vue';
import ViewSongDetail from '../views/SongDetail.vue'; import ViewSongDetail from '../views/SongDetail.vue';
...@@ -30,11 +29,14 @@ const routes = [{ ...@@ -30,11 +29,14 @@ const routes = [{
component: ViewLogin component: ViewLogin
}, { }, {
path: '/startup', path: '/startup',
name: 'Startup',
component: ViewStartup, component: ViewStartup,
name: 'ViewStartup',
redirect: {
name: 'StartupFrontpage'
},
children: [ children: [
{ {
path: '', path: '/frontpage',
name: 'StartupFrontpage', name: 'StartupFrontpage',
component: ViewStartupFrontpage component: ViewStartupFrontpage
}, },
...@@ -47,11 +49,6 @@ const routes = [{ ...@@ -47,11 +49,6 @@ const routes = [{
path: '/hot', path: '/hot',
name: 'StartupHot', name: 'StartupHot',
component: ViewStartupHotSongs component: ViewStartupHotSongs
},
{
path: '/popular',
name: 'StartupPopular',
component: ViewStartupPopularSongs
} }
] ]
}, { }, {
......
...@@ -51,7 +51,7 @@ ...@@ -51,7 +51,7 @@
} else { } else {
ssapi.validateConnectToken(userSettings.get("connectToken")).then((data) => { ssapi.validateConnectToken(userSettings.get("connectToken")).then((data) => {
if(data) { if(data) {
this.$router.replace({ name: 'StartupFrontpage' }); this.loadIntoProfile();
} else { } else {
this.showLoginBox(); this.showLoginBox();
} }
...@@ -80,7 +80,7 @@ ...@@ -80,7 +80,7 @@
case 200: case 200:
// Successfull // Successfull
userSettings.set("connectToken", data.data); userSettings.set("connectToken", data.data);
this.$router.replace({ name: 'StartupFrontpage' }); this.loadIntoProfile();
break; break;
case 403: case 403:
case 404: case 404:
...@@ -98,6 +98,16 @@ ...@@ -98,6 +98,16 @@
this.$data.apiLoginLoading = false; this.$data.apiLoginLoading = false;
this.$data.apiLoginCodeError = false; this.$data.apiLoginCodeError = false;
this.$data.apiLoginServerError = false; this.$data.apiLoginServerError = false;
},
loadIntoProfile: function() {
let ssapi = new SSAPI();
let userSettings = new UserSettings();
ssapi.getConnectProfile(userSettings.get("connectToken")).then((data) => {
userSettings.set("connectProfile", data);
this.$root.$emit("LoadIntoProfile", data);
this.$router.replace({ name: 'StartupFrontpage' });
});
} }
}, },
watch: { watch: {
......
...@@ -97,9 +97,9 @@ ...@@ -97,9 +97,9 @@
let ssapi = new SSAPI(); let ssapi = new SSAPI();
this.$data.apiFinished = false; this.$data.apiFinished = false;
if(this.$data.searchQuery != "") { if(this.$data.searchQuery !== "") {
ssapi.search(this.$data.searchQuery).then((data) => { ssapi.search(this.$data.searchQuery).then((data) => {
if(data.status == 200) { if(data.status === 200) {
this.$data.searchResultsUsers = data.data.users; this.$data.searchResultsUsers = data.data.users;
this.$data.searchResultsSongs = data.data.songs; this.$data.searchResultsSongs = data.data.songs;
......
...@@ -2,10 +2,9 @@ ...@@ -2,10 +2,9 @@
<section class="section-startup"> <section class="section-startup">
<header> <header>
<div class="tabs"> <div class="tabs">
<router-link to="/" class="tab"><span>{{ $t('startup.tabs.frontpage') }}</span></router-link> <router-link to="/frontpage" class="tab"><span>{{ $t('startup.tabs.frontpage') }}</span></router-link>
<router-link to="/new" class="tab"><span>{{ $t('startup.tabs.new') }}</span></router-link> <router-link to="/new" class="tab"><span>{{ $t('startup.tabs.new') }}</span></router-link>
<router-link to="/hot" class="tab"><span>{{ $t('startup.tabs.hot') }}</span></router-link> <router-link to="/hot" class="tab"><span>{{ $t('startup.tabs.hot') }}</span></router-link>
<router-link to="/popular" class="tab"><span>{{ $t('startup.tabs.popular') }}</span></router-link>
</div> </div>
</header> </header>
...@@ -49,7 +48,7 @@ ...@@ -49,7 +48,7 @@
background: #272c2e; background: #272c2e;
color: rgba(255,255,255,0.75); color: rgba(255,255,255,0.75);
} }
&.router-link-exact-active { &.router-link-exact-active, &.router-link-active {
opacity: 1; opacity: 1;
color: rgba(255,255,255,1); color: rgba(255,255,255,1);
background: #212629; background: #212629;
......
<template>
<SongRow>
<template v-slot:controls>
<div :class="'button ' + (popularSongsOffset == 0 ? 'button-disabled' : '')" v-on:click="popularPrevious()"><i class="mdi mdi-chevron-left"></i> {{ $t('songrow.navigation.previous' )}}</div>
<div :class="'button ' + (popularSongs.length < 11 ? 'button-disabled' : '')" v-on:click="popularNext()">{{ $t('songrow.navigation.next' )}} <i class="mdi mdi-chevron-right"></i></div>
</template>
<template v-slot:song-list>
<SongItemPlaceholder
v-if="isPopularSongsLoading"
v-for="n in 12"
v-bind:key="n" />
<SongItem
v-if="!isPopularSongsLoading"
v-for="song in popularSongs"
v-bind:key="song.id"
v-bind="song" />
</template>
</SongRow>
</template>
<script>
import SSAPI from '@/modules/module.api.js';
import SongRow from '@/components/Song/SongRow.vue';
import SongItem from '@/components/Song/SongItem.vue';
import SongItemPlaceholder from '@/components/Song/SongItemPlaceholder.vue';
export default {
name: 'Startup',
data: function() {
return {
isPopularSongsLoading: true,
popularSongsOffset: 0,
popularSongs: []
}
},
mounted: function() {
let ssapi = new SSAPI();
ssapi.getPopularSongs(this.$data.popularSongsOffset).then((data) => {
this.$data.isPopularSongsLoading = false;
this.$data.popularSongs = data;
});
},
components: {
SongRow,
SongItem,
SongItemPlaceholder
},
methods: {
popularNext: function() {
if(this.$data.popularSongs.length > 11) {
this.$data.popularSongsOffset++;
this.updatePopular();
}
},
popularPrevious: function() {
if(this.$data.popularSongsOffset > 0) {
this.$data.popularSongsOffset--;
this.updatePopular();
}
},
updatePopular: function() {
let ssapi = new SSAPI();
this.$data.isPopularSongsLoading = true;
ssapi.getPopularSongs(this.$data.popularSongsOffset).then((data) => {
this.$data.isPopularSongsLoading = false;
this.$data.popularSongs = data;
});
}
}
}
</script>
<style scoped lang="less">
.song-row {
padding: 50px;
}
</style>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment