Commit 319c3485 authored by Andreas Heimann's avatar Andreas Heimann

client v1.0.0 finish-up

parent ffea5d5c
......@@ -35,7 +35,7 @@ bower_components
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
build/
# Dependency directories
node_modules/
......
const { app, BrowserWindow, ipcMain } = require('electron');
const { app, BrowserWindow, ipcMain, protocol } = require('electron');
const { download } = require('electron-dl');
const isDev = require('electron-is-dev');
let win;
let deeplinkingUrl;
const PROTOCOL_PREFIX = "csinstall";
app.setAsDefaultProtocolClient(PROTOCOL_PREFIX);
const gotTheLock = app.requestSingleInstanceLock();
if (!gotTheLock) {
app.quit();
} else {
app.on('second-instance', (event, commandLine, workingDirectory) => {
if (process.platform == 'win32') {
let commandLineString = commandLine.slice(1) + '';
let commandLineArgs = commandLineString.split(",");
deeplinkingUrl = commandLineArgs[commandLineArgs.length - 1].replace("spinshare-song://", "").replace("/", "");
}
if (win) {
if (win.isMinimized()) win.restore();
win.focus();
win.webContents.executeJavaScript(`NavigateToSongDetail("${deeplinkingUrl}")`);
}
});
}
function createWindow () {
win = new BrowserWindow({
title: "SpinSha.re",
width: 1300,
height: 700,
minHeight: 700,
......@@ -19,13 +38,14 @@ function createWindow () {
win.loadFile('./src/app.htm');
if(isDev) {
win.webContents.openDevTools();
}
win.setMenuBarVisibility(false);
protocol.registerHttpProtocol(PROTOCOL_PREFIX, (req, cb) => {
const fullUrl = formFullTodoUrl(req.url);
console.log(fullUrl);
});
if (process.platform == 'win32') {
deeplinkingUrl = process.argv.slice(1);
}
}
app.whenReady().then(createWindow);
......@@ -41,6 +61,13 @@ app.on('activate', () => {
createWindow();
}
});
app.on('open-url', function (event, url) {
event.preventDefault();
deeplinkingUrl = url;
});
const PROTOCOL_PREFIX_SONG = "spinshare-song";
app.setAsDefaultProtocolClient(PROTOCOL_PREFIX_SONG);
ipcMain.on("download", (event, info) => {
console.log("Download Request Received");
......
This diff is collapsed.
{
"name": "customspeens-client",
"version": "0.1.0",
"main": "main.js",
"version": "1.0.0",
"main": "./main.js",
"description": "Spin Rhythm XD Custom Songs",
"scripts": {
"start": "electron ."
"start": "electron .",
"build": "electron-builder"
},
"protocols": [
{
"name": "customspeens",
"role": "CustomSpeens",
"schemes": [
"csinstall"
]
}
],
"author": "Andreas Heimann",
"license": "MIT",
"devDependencies": {
"electron": "^8.0.1"
"electron": "^8.0.1",
"electron-builder": "^22.4.1"
},
"dependencies": {
"axios": "^0.19.2",
......@@ -28,5 +21,40 @@
"rimraf": "^3.0.2",
"uniqid": "^5.2.0",
"unzipper": "^0.10.10"
},
"build": {
"productName": "SpinShare",
"appId": "re.spinsha.client",
"directories": {
"output": "build"
},
"protocols": {
"name": "spinshare-song-deeplink",
"schemes": ["spinshare-song"]
},
"dmg": {
"contents": [
{
"x": 410,
"y": 150,
"type": "link",
"path": "/Applications"
},
{
"x": 130,
"y": 150,
"type": "file"
}
]
},
"mac": {
"icon": "build/icons/icon.icns"
},
"win": {
"icon": "build/icons/icon.ico"
},
"linux": {
"icon": "build/icons"
}
}
}
This diff is collapsed.
.download-overlay {
position: absolute;
position: fixed;
z-index: 100;
top: 0px;
left: 0px;
......@@ -14,10 +14,48 @@
width: 500px;
background: #212629;
border-radius: 6px;
position: relative;
overflow: hidden;
}
.download-overlay .download-content .download-output {
text-align: center;
.download-overlay .download-content .download-statusbar {
position: absolute;
height: 5px;
background: rgba(0, 0, 0, 0.2);
left: 0px;
right: 0px;
}
.download-overlay .download-content .download-statusbar .download-statusbar-handle {
height: 5px;
width: 0px;
background: #74b959;
transition: 1s ease-in-out width;
}
.download-overlay .download-content .download-status {
padding: 25px;
display: none;
grid-template-rows: 1fr auto;
grid-gap: 25px;
}
.download-overlay .download-content .download-status .icon {
margin: 10px auto;
width: 150px;
height: 150px;
display: flex;
justify-content: center;
align-items: center;
}
.download-overlay .download-content .download-status .icon .mdi {
font-size: 72px;
}
.download-overlay .download-content .download-status .text {
text-align: center;
font-size: 14px;
font-weight: bold;
text-transform: uppercase;
letter-spacing: 0.25em;
}
.download-overlay .download-content .download-status.active {
display: grid;
}
.download-overlay .download-content .download-actions {
display: none;
......
.download-overlay {
position: absolute;
position: fixed;
z-index: 100;
top: 0px;
left: 0px;
......@@ -14,10 +14,54 @@
width: 500px;
background: #212629;
border-radius: 6px;
position: relative;
overflow: hidden;
& .download-output {
text-align: center;
& .download-statusbar {
position: absolute;
height: 5px;
background: rgba(0,0,0,0.2);
left: 0px;
right: 0px;
& .download-statusbar-handle {
height: 5px;
width: 0px;
background: #74b959;
transition: 1s ease-in-out width;
}
}
& .download-status {
padding: 25px;
display: none;
grid-template-rows: 1fr auto;
grid-gap: 25px;
& .icon {
margin: 10px auto;
width: 150px;
height: 150px;
display: flex;
justify-content: center;
align-items: center;
& .mdi {
font-size: 72px;
}
}
& .text {
text-align: center;
font-size: 14px;
font-weight: bold;
text-transform: uppercase;
letter-spacing: 0.25em;
}
&.active {
display: grid;
}
}
& .download-actions {
......
......@@ -63,28 +63,22 @@ main aside .item.active {
main aside .item .mdi {
font-size: 22px;
}
input {
font-family: 'Open Sans', sans-serif;
font-size: 12px;
color: #222;
background: #fff;
text-transform: uppercase;
font-weight: 700;
border-radius: 4px;
padding: 7px 14px;
border: 0px;
transition: 0.2s ease-in-out all;
section {
display: none;
}
input:hover {
background: #fff;
color: #222;
cursor: pointer;
section.active {
display: block;
}
input:focus {
outline: 0;
section.section-startup {
padding: 50px;
}
input::placeholder {
color: rgba(0, 0, 0, 0.6);
section.section-startup.active {
display: grid;
grid-template-rows: auto;
grid-gap: 25px;
}
section.section-library {
padding: 50px;
}
button,
.button {
......@@ -109,20 +103,201 @@ button:focus,
.button:focus {
outline: 0;
}
section {
.song-row {
display: grid;
grid-template-rows: auto 1fr;
grid-gap: 5px;
}
.song-row .song-header {
display: grid;
grid-template-columns: 1fr auto;
}
.song-row .song-header .row-title {
letter-spacing: 0.25em;
font-size: 14px;
font-weight: bold;
text-transform: uppercase;
}
.song-row .song-header .row-title.row-title-noactions {
margin: 10px 0px;
}
.song-row .song-header .row-controls {
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 15px;
}
.song-row .song-header .row-controls .item {
width: 28px;
height: 28px;
font-size: 22px;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
}
.song-row .song-header .row-controls .item.disabled {
opacity: 0.4;
}
.song-row .song-header .row-controls .item:not(.disabled):hover {
background: rgba(255, 255, 255, 0.2);
cursor: pointer;
}
.song-row .song-list {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr;
grid-gap: 15px;
}
.song-row .song-list .song-item {
background: rgba(255, 255, 255, 0.1);
transition: 0.2s ease-in-out transform, 0.2s ease-in-out box-shadow;
overflow: hidden;
border-radius: 6px;
}
.song-row .song-list .song-item .song-cover {
background: rgba(255, 255, 255, 0.1);
background-size: cover;
width: 100%;
padding-top: 100%;
position: relative;
}
.song-row .song-list .song-item .song-cover .song-charter {
position: absolute;
top: 0px;
left: 0px;
right: 0px;
bottom: 0px;
background: linear-gradient(180deg, rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.8));
opacity: 0;
padding: 15px;
overflow: hidden;
display: grid;
transition: 0.2s ease-in-out opacity;
grid-template-columns: auto 1fr;
grid-gap: 10px;
align-items: flex-end;
}
.song-row .song-list .song-item .song-cover .song-charter .song-charter-info {
display: grid;
align-items: center;
}
.song-row .song-list .song-item .song-cover .song-charter .song-charter-info .mdi {
font-size: 18px;
}
.song-row .song-list .song-item .song-cover .song-charter .song-charter-info span {
font-size: 12px;
color: transparent;
transition: 0.2s ease-in-out color;
overflow: hidden;
white-space: nowrap;
}
.song-row .song-list .song-item .song-metadata {
padding: 15px;
}
.song-row .song-list .song-item .song-metadata .song-title {
font-weight: bold;
overflow: hidden;
white-space: nowrap;
}
.song-row .song-list .song-item .song-metadata .song-artist {
margin-top: 5px;
opacity: 0.6;
overflow: hidden;
white-space: nowrap;
}
.song-row .song-list .song-item:not(.song-item-loading):not(.song-item-local):hover {
transform: scale(1.1);
cursor: pointer;
box-shadow: 0px 4px 20px 5px rgba(0, 0, 0, 0.4);
}
.song-row .song-list .song-item:not(.song-item-loading):not(.song-item-local):hover .song-cover .song-charter {
opacity: 1;
}
.song-row .song-list .song-item.song-item-loading {
background: linear-gradient(to right, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0.1));
animation-name: songLoadingShimmer;
animation-fill-mode: forwards;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-duration: 2s;
}
.song-row .song-list .song-item.song-item-loading .song-cover {
opacity: 0;
}
.song-row .song-list .song-item.song-item-local {
opacity: 0.6;
}
.song-row .song-list .song-item.song-item-local:hover .song-cover .song-charter {
opacity: 1;
}
.song-row .song-list-noresults {
display: none;
background: rgba(255, 255, 255, 0.1);
border-radius: 6px;
padding: 25px;
opacity: 0.6;
text-align: center;
}
section.active {
.song-row .song-list-noresults.active {
display: block;
}
section.section-startup {
padding: 50px;
.user-row {
display: grid;
grid-template-rows: auto 1fr;
grid-gap: 5px;
}
section.section-startup.active {
.user-row .user-header {
display: grid;
grid-template-rows: auto;
grid-gap: 25px;
grid-template-columns: 1fr auto;
}
section.section-library {
padding: 50px;
.user-row .user-header .row-title {
letter-spacing: 0.25em;
font-size: 14px;
font-weight: bold;
text-transform: uppercase;
}
.user-row .user-header .row-title.row-title-noactions {
margin: 10px 0px;
}
.user-row .user-list {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-gap: 15px;
}
.user-item {
background: rgba(255, 255, 255, 0.1);
transition: 0.2s ease-in-out transform, 0.2s ease-in-out box-shadow;
overflow: hidden;
border-radius: 6px;
display: grid;
padding: 10px;
grid-gap: 15px;
grid-template-columns: 32px 1fr;
}
.user-item .user-avatar {
background: rgba(255, 255, 255, 0.1);
background-size: cover;
width: 32px;
height: 32px;
border-radius: 32px;
}
.user-item .user-metadata {
align-self: center;
}
.user-item .user-metadata .user-name {
font-weight: bold;
overflow: hidden;
white-space: nowrap;
}
.user-item:hover {
transform: scale(1.1);
cursor: pointer;
box-shadow: 0px 4px 20px 5px rgba(0, 0, 0, 0.4);
}
@keyframes songLoadingShimmer {
from {
background-position: 0px 0px;
}
to {
background-position: 173px 0px;
}
}
......@@ -65,28 +65,25 @@ main {
}
}
}
input {
font-family: 'Open Sans', sans-serif;
font-size: 12px;
color: #222;
background: #fff;
text-transform: uppercase;
font-weight: 700;
border-radius: 4px;
padding: 7px 14px;
border: 0px;
transition: 0.2s ease-in-out all;
section {
display: none;
&:hover {
background: #fff;
color: #222;
cursor: pointer;
&.active {
display: block;
}
&.section-startup {
padding: 50px;
&.active {
display: grid;
grid-template-rows: auto;
grid-gap: 25px;
}
&:focus {
outline: 0;
}
&::placeholder {
color: rgba(0,0,0,0.6);
&.section-library {
padding: 50px;
}
}
button, .button {
......@@ -110,24 +107,233 @@ button, .button {
outline: 0;
}
}
section {
.song-row {
display: grid;
grid-template-rows: auto 1fr;
grid-gap: 5px;
& .song-header {
display: grid;
grid-template-columns: 1fr auto;
& .row-title {
letter-spacing: 0.25em;
font-size: 14px;
font-weight: bold;
text-transform: uppercase;
&.row-title-noactions {
margin: 10px 0px;
}
}
& .row-controls {
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 15px;
& .item {
width: 28px;
height: 28px;
font-size: 22px;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
&.disabled {
opacity: 0.4;
}
&:not(.disabled):hover {
background: rgba(255,255,255,0.2);
cursor: pointer;
}
}
}
}
& .song-list {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr;
grid-gap: 15px;
& .song-item {
background: rgba(255,255,255,0.1);
transition: 0.2s ease-in-out transform, 0.2s ease-in-out box-shadow;
overflow: hidden;
border-radius: 6px;
& .song-cover {
background: rgba(255,255,255,0.1);
background-size: cover;
width: 100%;
padding-top: 100%;
position: relative;
& .song-charter {
position: absolute;
top: 0px;
left: 0px;
right: 0px;
bottom: 0px;
background: linear-gradient(180deg, rgba(0,0,0,0.2), rgba(0,0,0,0.8));
opacity: 0;
padding: 15px;
overflow: hidden;
display: grid;
transition: 0.2s ease-in-out opacity;
grid-template-columns: auto 1fr;
grid-gap: 10px;
align-items: flex-end;
& .song-charter-info {
display: grid;
align-items: center;
& .mdi {
font-size: 18px;
}
& span {
font-size: 12px;
color: transparent;
transition: 0.2s ease-in-out color;
overflow: hidden;
white-space: nowrap;
}
}
}
}
& .song-metadata {
padding: 15px;
& .song-title {
font-weight: bold;
overflow: hidden;
white-space: nowrap;
}
& .song-artist {
margin-top: 5px;
opacity: 0.6;
overflow: hidden;
white-space: nowrap;
}
}
&:not(.song-item-loading):not(.song-item-local):hover {
transform: scale(1.1);
cursor: pointer;
box-shadow: 0px 4px 20px 5px rgba(0, 0, 0, 0.4);
& .song-cover {
& .song-charter {
opacity: 1;
}
}
}
&.song-item-loading {
background: linear-gradient(to right, rgba(255,255,255,0.1), rgba(255,255,255,0.2), rgba(255,255,255,0.1));
animation-name: songLoadingShimmer;
animation-fill-mode: forwards;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-duration: 2s;
& .song-cover {
opacity: 0;
}
}
&.song-item-local {
opacity: 0.6;
&:hover {
& .song-cover {
& .song-charter {
opacity: 1;
}
}
}
}
}
}
& .song-list-noresults {
display: none;
background: rgba(255,255,255,0.1);
border-radius: 6px;
padding: 25px;
opacity: 0.6;
text-align: center;
&.active {
display: block;
}
}
}
.user-row {
display: grid;
grid-template-rows: auto 1fr;
grid-gap: 5px;
&.section-startup {
padding: 50px;
& .user-header {
display: grid;
grid-template-columns: 1fr auto;
&.active {
& .row-title {
letter-spacing: 0.25em;
font-size: 14px;
font-weight: bold;
text-transform: uppercase;
&.row-title-noactions {
margin: 10px 0px;
}
}
}
& .user-list {
display: grid;
grid-template-rows: auto;
grid-gap: 25px;
grid-template-columns: 1fr 1fr 1fr;
grid-gap: 15px;
}
}
.user-item {
background: rgba(255,255,255,0.1);
transition: 0.2s ease-in-out transform, 0.2s ease-in-out box-shadow;
overflow: hidden;
border-radius: 6px;
display: grid;
padding: 10px;
grid-gap: 15px;
grid-template-columns: 32px 1fr;
& .user-avatar {
background: rgba(255,255,255,0.1);
background-size: cover;
width: 32px;
height: 32px;
border-radius: 32px;
}
&.section-library {
padding: 50px;
& .user-metadata {
align-self: center;
& .user-name {
font-weight: bold;
overflow: hidden;
white-space: nowrap;
}
}
&:hover {
transform: scale(1.1);
cursor: pointer;
box-shadow: 0px 4px 20px 5px rgba(0, 0, 0, 0.4);
}
}
@keyframes songLoadingShimmer {
from {
background-position: 0px 0px;
}
to {
background-position: 173px 0px;
}
}
\ No newline at end of file
.section-search {
grid-template-rows: auto 1fr;
grid-gap: 25px;
padding: 50px;
}
.section-search .search-bar input {
width: 100%;
font-family: 'Open Sans', sans-serif;
font-size: 14px;
color: #fff;
background: rgba(255, 255, 255, 0.2);
border-radius: 4px;
padding: 14px 28px;
border: 0px;
transition: 0.2s ease-in-out all;
}
.section-search .search-bar input:hover {
background: rgba(255, 255, 255, 0.4);
color: #fff;
}
.section-search .search-bar input:focus {
outline: 0;
}
.section-search .search-bar input::placeholder {
color: rgba(255, 255, 255, 0.6);
}
.section-search .search-results {
display: grid;
grid-template-rows: auto auto auto 1fr;
grid-gap: 25px;
}
.section-search .search-results .search-results-users {
display: none;
}
.section-search .search-results .search-results-users.active {
display: grid;
}
.section-search .search-results .search-results-songs {
display: none;
}
.section-search .search-results .search-results-songs.active {
display: grid;
}
.section-search .search-results .search-results-noresults {
background: rgba(255, 255, 255, 0.1);
border-radius: 6px;
padding: 25px;
display: none;
}
.section-search .search-results .search-results-noresults .noresults-title {
font-size: 24px;
font-weight: bold;
margin-bottom: 10px;
}
.section-search .search-results .search-results-noresults .noresults-text {
opacity: 0.6;
}
.section-search .search-results .search-results-noresults.active {
display: block;
}
.section-search.active {
display: grid;
}
.section-search {
grid-template-rows: auto 1fr;
grid-gap: 25px;
padding: 50px;
& .search-bar {
input {
width: 100%;
font-family: 'Open Sans', sans-serif;
font-size: 14px;
color: #fff;
background: rgba(255,255,255,0.2);
border-radius: 4px;
padding: 14px 28px;
border: 0px;
transition: 0.2s ease-in-out all;
&:hover {
background: rgba(255,255,255,0.4);
color: #fff;
}
&:focus {
outline: 0;
}
&::placeholder {
color: rgba(255,255,255,0.6);
}
}
}
& .search-results {
display: grid;
grid-template-rows: auto auto auto 1fr;
grid-gap: 25px;
& .search-results-users {
display: none;
&.active {
display: grid;
}
}
& .search-results-songs {
display: none;
&.active {
display: grid;
}
}
& .search-results-noresults {
background: rgba(255,255,255,0.1);
border-radius: 6px;
padding: 25px;
display: none;
& .noresults-title {
font-size: 24px;
font-weight: bold;
margin-bottom: 10px;
}
& .noresults-text {
opacity: 0.6;
}
&.active {
display: block;
}
}
}
&.active {
display: grid;
}
}
\ No newline at end of file
......@@ -18,7 +18,7 @@
}
.section-settings .settings-box .settings-item {
display: grid;
grid-template-columns: 200px 1fr;
grid-template-columns: 170px 1fr;
grid-gap: 15px;
margin-top: 15px;
}
......
......@@ -18,7 +18,7 @@
& .settings-item {
display: grid;
grid-template-columns: 200px 1fr;
grid-template-columns: 170px 1fr;
grid-gap: 15px;
margin-top: 15px;
......
......@@ -30,6 +30,10 @@
.section-song-detail .song-detail-background .song-detail-dim .song-detail .song-meta-data .song-artist {
margin-top: 5px;
font-size: 18px;
}
.section-song-detail .song-detail-background .song-detail-dim .song-detail .song-meta-data .song-charter {
margin-top: 10px;
font-size: 14px;
opacity: 0.6;
}
.section-song-detail .song-detail-background .song-detail-dim .song-detail .song-meta-data .song-tags {
......@@ -50,28 +54,13 @@
opacity: 0.6;
cursor: pointer;
}
.section-song-detail .song-detail-background .song-detail-dim .song-detail .song-meta-data .song-charter {
.section-song-detail .song-detail-background .song-detail-dim .song-detail .song-meta-data .song-uploader {
margin-top: 15px;
display: flex;
}
.section-song-detail .song-detail-background .song-detail-dim .song-detail .song-meta-data .song-charter .song-charter-user {
justify-self: left;
background: #222;
padding: 10px 15px;
border-radius: 6px;
display: flex;
align-items: center;
transition: 0.2s ease-in-out all;
}
.section-song-detail .song-detail-background .song-detail-dim .song-detail .song-meta-data .song-charter .song-charter-user .mdi {
font-size: 22px;
}
.section-song-detail .song-detail-background .song-detail-dim .song-detail .song-meta-data .song-charter .song-charter-user span {
margin-left: 15px;
}
.section-song-detail .song-detail-background .song-detail-dim .song-detail .song-meta-data .song-charter .song-charter-user:hover {
opacity: 0.6;
cursor: pointer;
.section-song-detail .song-detail-background .song-detail-dim .song-detail .song-meta-data .song-uploader .user-item {
width: auto;
padding-right: 15px;
}
.section-song-detail .song-detail-background .song-detail-dim .song-detail.active {
display: grid;
......
......@@ -32,6 +32,10 @@
& .song-artist {
margin-top: 5px;
font-size: 18px;
}
& .song-charter {
margin-top: 10px;
font-size: 14px;
opacity: 0.6;
}
& .song-tags {
......@@ -55,30 +59,13 @@
}
}
& .song-charter {
& .song-uploader {
margin-top: 15px;
display: flex;
& .song-charter-user {
justify-self: left;
background: #222;
padding: 10px 15px;
border-radius: 6px;
display: flex;
align-items: center;
transition: 0.2s ease-in-out all;
& .mdi {
font-size: 22px;
}
& span {
margin-left: 15px;
}
&:hover {
opacity: 0.6;
cursor: pointer;
}
& .user-item {
width: auto;
padding-right: 15px;
}
}
}
......
......@@ -55,129 +55,6 @@
animation-iteration-count: infinite;
animation-duration: 1s;
}
.song-row {
display: grid;
grid-template-rows: auto 1fr;
grid-gap: 5px;
}
.song-row .song-header {
display: grid;
grid-template-columns: 1fr auto;
}
.song-row .song-header .row-title {
letter-spacing: 0.25em;
font-size: 14px;
font-weight: bold;
text-transform: uppercase;
}
.song-row .song-header .row-controls {
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 15px;
}
.song-row .song-header .row-controls .item {
width: 28px;
height: 28px;
font-size: 22px;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
}
.song-row .song-header .row-controls .item.disabled {
opacity: 0.4;
}
.song-row .song-header .row-controls .item:not(.disabled):hover {
background: rgba(255, 255, 255, 0.2);
cursor: pointer;
}
.song-row .song-list {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr;
grid-gap: 15px;
}
.song-row .song-list .song-item {
background: rgba(255, 255, 255, 0.1);
transition: 0.2s ease-in-out transform, 0.2s ease-in-out box-shadow;
overflow: hidden;
border-radius: 6px;
}
.song-row .song-list .song-item .song-cover {
background: rgba(255, 255, 255, 0.1);
background-size: cover;
width: 100%;
padding-top: 100%;
position: relative;
}
.song-row .song-list .song-item .song-cover .song-charter {
position: absolute;
top: 0px;
left: 0px;
right: 0px;
bottom: 0px;
background: linear-gradient(180deg, rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.8));
opacity: 0;
padding: 15px;
overflow: hidden;
display: grid;
transition: 0.2s ease-in-out opacity;
grid-template-columns: auto 1fr;
grid-gap: 10px;
align-items: flex-end;
}
.song-row .song-list .song-item .song-cover .song-charter .song-charter-info {
display: grid;
align-items: center;
}
.song-row .song-list .song-item .song-cover .song-charter .song-charter-info .mdi {
font-size: 18px;
}
.song-row .song-list .song-item .song-cover .song-charter .song-charter-info span {
font-size: 12px;
color: transparent;
transition: 0.2s ease-in-out color;
overflow: hidden;
white-space: nowrap;
}
.song-row .song-list .song-item .song-metadata {
padding: 15px;
}
.song-row .song-list .song-item .song-metadata .song-title {
font-weight: bold;
overflow: hidden;
white-space: nowrap;
}
.song-row .song-list .song-item .song-metadata .song-artist {
margin-top: 5px;
opacity: 0.6;
overflow: hidden;
white-space: nowrap;
}
.song-row .song-list .song-item:not(.song-item-loading):not(.song-item-local):hover {
transform: scale(1.1);
cursor: pointer;
box-shadow: 0px 4px 20px 5px rgba(0, 0, 0, 0.4);
}
.song-row .song-list .song-item:not(.song-item-loading):not(.song-item-local):hover .song-cover .song-charter {
opacity: 1;
}
.song-row .song-list .song-item.song-item-loading {
background: linear-gradient(to right, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0.1));
animation-name: songLoadingShimmer;
animation-fill-mode: forwards;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-duration: 2s;
}
.song-row .song-list .song-item.song-item-loading .song-cover {
opacity: 0;
}
.song-row .song-list .song-item.song-item-local {
opacity: 0.6;
}
.song-row .song-list .song-item.song-item-local:hover .song-cover .song-charter {
opacity: 1;
}
@keyframes adLoadingShimmer {
from {
background-position: 0px 0px;
......@@ -186,11 +63,3 @@
background-position: 544px 0px;
}
}
@keyframes songLoadingShimmer {
from {
background-position: 0px 0px;
}
to {
background-position: 173px 0px;
}
}
......@@ -60,151 +60,6 @@
}
}
}
.song-row {
display: grid;
grid-template-rows: auto 1fr;
grid-gap: 5px;
& .song-header {
display: grid;
grid-template-columns: 1fr auto;
& .row-title {
letter-spacing: 0.25em;
font-size: 14px;
font-weight: bold;
text-transform: uppercase;
}
& .row-controls {
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 15px;
& .item {
width: 28px;
height: 28px;
font-size: 22px;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
&.disabled {
opacity: 0.4;
}
&:not(.disabled):hover {
background: rgba(255,255,255,0.2);
cursor: pointer;
}
}
}
}
& .song-list {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr;
grid-gap: 15px;
& .song-item {
background: rgba(255,255,255,0.1);
transition: 0.2s ease-in-out transform, 0.2s ease-in-out box-shadow;
overflow: hidden;
border-radius: 6px;
& .song-cover {
background: rgba(255,255,255,0.1);
background-size: cover;
width: 100%;
padding-top: 100%;
position: relative;
& .song-charter {
position: absolute;
top: 0px;
left: 0px;
right: 0px;
bottom: 0px;
background: linear-gradient(180deg, rgba(0,0,0,0.2), rgba(0,0,0,0.8));
opacity: 0;
padding: 15px;
overflow: hidden;
display: grid;
transition: 0.2s ease-in-out opacity;
grid-template-columns: auto 1fr;
grid-gap: 10px;
align-items: flex-end;
& .song-charter-info {
display: grid;
align-items: center;
& .mdi {
font-size: 18px;
}
& span {
font-size: 12px;
color: transparent;
transition: 0.2s ease-in-out color;
overflow: hidden;
white-space: nowrap;
}
}
}
}
& .song-metadata {
padding: 15px;
& .song-title {
font-weight: bold;
overflow: hidden;
white-space: nowrap;
}
& .song-artist {
margin-top: 5px;
opacity: 0.6;
overflow: hidden;
white-space: nowrap;
}
}
&:not(.song-item-loading):not(.song-item-local):hover {
transform: scale(1.1);
cursor: pointer;
box-shadow: 0px 4px 20px 5px rgba(0, 0, 0, 0.4);
& .song-cover {
& .song-charter {
opacity: 1;
}
}
}
&.song-item-loading {
background: linear-gradient(to right, rgba(255,255,255,0.1), rgba(255,255,255,0.2), rgba(255,255,255,0.1));
animation-name: songLoadingShimmer;
animation-fill-mode: forwards;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-duration: 2s;
& .song-cover {
opacity: 0;
}
}
&.song-item-local {
opacity: 0.6;
&:hover {
& .song-cover {
& .song-charter {
opacity: 1;
}
}
}
}
}
}
}
@keyframes adLoadingShimmer {
from {
......@@ -214,12 +69,3 @@
background-position: 544px 0px;
}
}
\ No newline at end of file
@keyframes songLoadingShimmer {
from {
background-position: 0px 0px;
}
to {
background-position: 173px 0px;
}
}
\ No newline at end of file
.update-overlay {
position: fixed;
z-index: 100;
top: 0px;
left: 0px;
right: 0px;
bottom: 0px;
background: rgba(0, 0, 0, 0.75);
display: none;
justify-content: center;
align-items: center;
}
.update-overlay .update-content {
width: 500px;
background: #212629;
border-radius: 6px;
position: relative;
overflow: hidden;
}
.update-overlay .update-content .update-status {
padding: 25px;
display: none;
grid-template-rows: 1fr auto;
grid-gap: 25px;
}
.update-overlay .update-content .update-status .icon {
margin: 10px auto;
width: 150px;
height: 150px;
display: flex;
justify-content: center;
align-items: center;
}
.update-overlay .update-content .update-status .icon .mdi {
font-size: 72px;
}
.update-overlay .update-content .update-status .text {
text-align: center;
}
.update-overlay .update-content .update-status.active {
display: grid;
}
.update-overlay .update-content .update-actions {
display: none;
justify-content: flex-end;
padding: 25px;
background: rgba(0, 0, 0, 0.4);
}
.update-overlay .update-content .update-actions button {
margin-left: 10px;
}
.update-overlay .update-content .update-actions.active {
display: flex;
}
.update-overlay.active {
display: flex;
}
.update-overlay {
position: fixed;
z-index: 100;
top: 0px;
left: 0px;
right: 0px;
bottom: 0px;
background: rgba(0,0,0,0.75);
display: none;
justify-content: center;
align-items: center;
& .update-content {
width: 500px;
background: #212629;
border-radius: 6px;
position: relative;
overflow: hidden;
& .update-status {
padding: 25px;
display: none;
grid-template-rows: 1fr auto;
grid-gap: 25px;
& .icon {
margin: 10px auto;
width: 150px;
height: 150px;
display: flex;
justify-content: center;
align-items: center;
& .mdi {
font-size: 72px;
}
}
& .text {
text-align: center;
}
&.active {
display: grid;
}
}
& .update-actions {
display: none;
justify-content: flex-end;
padding: 25px;
background: rgba(0,0,0,0.4);
& button {
margin-left: 10px;
}
&.active {
display: flex;
}
}
}
&.active {
display: flex;
}
}
\ No newline at end of file
.section-user-detail .user-detail-background {
background-size: cover;
background-position: center;
}
.section-user-detail .user-detail-background .user-detail-dim {
backdrop-filter: blur(10px);
background: linear-gradient(180deg, rgba(0, 0, 0, 0.4), #212629);
}
.section-user-detail .user-detail-background .user-detail-dim .user-detail {
padding: 50px;
display: none;
grid-template-columns: 200px 1fr;
grid-gap: 25px;
}
.section-user-detail .user-detail-background .user-detail-dim .user-detail .user-avatar {
width: 200px;
height: 200px;
align-self: center;
background: #eee;
border-radius: 6px;
background-size: cover;
}
.section-user-detail .user-detail-background .user-detail-dim .user-detail .user-meta-data .user-name {
font-weight: bold;
font-size: 48px;
}
.section-user-detail .user-detail-background .user-detail-dim .user-detail.active {
display: grid;
}
.section-user-detail .song-row-user {
padding: 0px 50px;
margin-bottom: 50px;
display: none;
}
.section-user-detail .song-row-user.active {
display: grid;
}
.section-user-detail {
& .user-detail-background {
background-size: cover;
background-position: center;
& .user-detail-dim {
backdrop-filter: blur(10px);
background: linear-gradient(180deg, rgba(0,0,0,0.4), #212629);
& .user-detail {
padding: 50px;
display: none;
grid-template-columns: 200px 1fr;
grid-gap: 25px;
& .user-avatar {
width: 200px;
height: 200px;
align-self: center;
background: #eee;
border-radius: 6px;
background-size: cover;
}
& .user-meta-data {
& .user-name {
font-weight: bold;
font-size: 48px;
}
}
&.active {
display: grid;
}
}
}
}
& .song-row-user {
padding: 0px 50px;
margin-bottom: 50px;
display: none;
&.active {
display: grid;
}
}
}
\ No newline at end of file
// Backup Data
let currentBackupLocation = "";
let currentSRTBLocation = "";
let currentSongLocation = "";
let currentSongTrackInfo = {};
function UIOpenBackup() {
dialog.showOpenDialog({ title: "Open Backup", properties: ['openFile'], filters: [{"name": "Backup Archive", "extensions": ["zip"]}] }).then(result => {
if(!result.canceled) {
let filePath = result.filePaths[0];
let fileName = path.basename(filePath);
loadBackup(filePath, fileName).then(function(result) {
if(result) {
UIUpdateMetadata();
} else {
console.error("Backup could not be loaded!");
}
});
}
});
}
function UICopyBackup() {
copyBackup();
}
function UIUpdateMetadata() {
console.log(currentSongTrackInfo);
DOMSectionTrackinfo.classList.add("active");
DOMUISongCover.style.backgroundImage = "url(" + getSongCover(currentSongTrackInfo.albumArtReference.assetName) + ")";
DOMUISongTitle.innerHTML = currentSongTrackInfo.title;
DOMUISongSubtitle.innerHTML = currentSongTrackInfo.subtitle;
DOMUISongArtist.innerHTML = "Song by " + currentSongTrackInfo.artistName;
DOMUISongAuthor.innerHTML = "Chart by " + currentSongTrackInfo.charter;
}
let apiVersion = 1;
function UIDownloadBackup() {
DOMExternalBackupProgress.innerHTML = "";
http.get('http://localhost/www/customspeens-server/public/index.php/api/song/' + DOMExternalBackupID.value, function(response) {
let data = "";
response.on('data', function(chunk) { data += chunk; });
response.on('end', function() {
let apiResponse = JSON.parse( data );
if(apiResponse.version === apiVersion) {
console.log(apiResponse.data);
DOMExternalBackupProgress.innerHTML = "Downloading...";
// Let the main renderer download the backup
ipcRenderer.send("download", {
url: apiResponse.data.paths.zip,
properties: { directory: tempDirLocation }
});
} else {
console.error("Client is outdated!");
DOMExternalBackupProgress.innerHTML = "Client is outdated!";
}
});
});
}
\ No newline at end of file
let DOMDownloadOverlay = document.querySelector(".download-overlay");
let DOMDownloadOutput = DOMDownloadOverlay.querySelector(".download-content .download-output");
let DOMDownloadStatusBarHandle = DOMDownloadOverlay.querySelector(".download-content .download-statusbar-handle");
let DOMDownloadStatusDownloading = DOMDownloadOverlay.querySelector(".download-content .download-status-downloading");
let DOMDownloadStatusExtracting = DOMDownloadOverlay.querySelector(".download-content .download-status-extracting");
let DOMDownloadStatusInstalling = DOMDownloadOverlay.querySelector(".download-content .download-status-installing");
let DOMDownloadStatusDone = DOMDownloadOverlay.querySelector(".download-content .download-status-done");
let DOMDownloadActions = DOMDownloadOverlay.querySelector(".download-content .download-actions");
function DownloadSong(songData) {
DOMDownloadOverlay.classList.add("active");
DOMDownloadActions.classList.remove("active");
DOMDownloadOutput.innerText = "Downloading...";
DOMDownloadStatusBarHandle.style.width = "0%";
setTimeout(function() {
UpdateDownloadStatus(0);
// Send download command to main.js
ipcRenderer.send("download", {
url: songData.paths.zip,
properties: { directory: tempDirLocation }
});
console.log(songData);
}, 100);
}
function CloseDownloadOverlay() {
DOMDownloadOverlay.classList.remove("active");
DOMDownloadActions.classList.remove("active");
DOMDownloadOutput.innerText = "Downloading...";
UpdateDownloadStatus(0);
DOMDownloadStatusBarHandle.style.width = "0%";
}
ipcRenderer.on("download-complete", (event, downloadPath) => {
DOMDownloadOutput.innerText = "Extracing...";
UpdateDownloadStatus(1);
setTimeout(function() {
srxdControl.extractBackup(downloadPath, path.basename(downloadPath)).then(function(extractResult) {
DOMDownloadOutput.innerText = "Installing...";
UpdateDownloadStatus(2);
if(extractResult) {
installBackup(extractResult);
} else {
// DOMDownloadOutput.innerText = locale.get('download.status.extractingFailed');
console.error("Backup could not be loaded!");
}
});
}, 750);
});
// Install local backup folder
......@@ -45,12 +57,39 @@ async function installBackup(backupLocation) {
console.error("Couldn't copy backup!");
DOMDownloadActions.classList.add("active");
DOMDownloadOutput.innerText = "Error!";
// DOMDownloadOutput.innerText = locale.get('download.status.installingFailed');
}
console.log("Successfully copied backup!");
setTimeout(function() {
DOMDownloadActions.classList.add("active");
DOMDownloadOutput.innerText = "Done!";
UpdateDownloadStatus(3);
}, 750);
});
}
function UpdateDownloadStatus(_status) {
DOMDownloadStatusDownloading.classList.remove("active");
DOMDownloadStatusExtracting.classList.remove("active");
DOMDownloadStatusInstalling.classList.remove("active");
DOMDownloadStatusDone.classList.remove("active");
switch(_status) {
default:
case 0:
DOMDownloadStatusDownloading.classList.add("active");
DOMDownloadStatusBarHandle.style.width = "25%";
break;
case 1:
DOMDownloadStatusExtracting.classList.add("active");
DOMDownloadStatusBarHandle.style.width = "50%";
break;
case 2:
DOMDownloadStatusInstalling.classList.add("active");
DOMDownloadStatusBarHandle.style.width = "75%";
break;
case 3:
DOMDownloadStatusDone.classList.add("active");
DOMDownloadStatusBarHandle.style.width = "100%";
break;
}
}
\ No newline at end of file
const { ipcRenderer } = require('electron');
const { dialog, shell, app } = require('electron').remote;
const { dialog, shell, app, clipboard } = require('electron').remote;
const isDev = require('electron-is-dev');
const path = require('path');
const SSAPI = require( path.resolve(__dirname, './assets/js/module.api.js') );
......@@ -25,6 +25,7 @@ function detectGameDirectory() {
}
}
// Initialize User Settings
let userSettings = new UserSettings({
defaults: {
showExplicit: false,
......@@ -33,8 +34,13 @@ let userSettings = new UserSettings({
}
});
// Initialize Locale
let locale = new Locale(userSettings.get('language'));
const DOMLocaleElements = document.querySelectorAll("*[locale]");
DOMLocaleElements.forEach(function(localeElement) {
localeElement.innerHTML = locale.get(localeElement.innerHTML);
});
const DOMLocalePlaceholderElements = document.querySelectorAll("*[localePlaceholder]");
DOMLocalePlaceholderElements.forEach(function(localePlaceholderElement) {
localePlaceholderElement.placeholder = locale.get(localePlaceholderElement.placeholder);
});
\ No newline at end of file
......@@ -2,7 +2,11 @@ const axios = require('axios');
class SHAPI {
constructor() {
this.apiBase = "http://localhost/www/customspeens-server/public/index.php/api/";
if(isDev) {
this.apiBase = "https://spinsha.re/api/";
} else {
this.apiBase = "http://localhost/www/spinshare-server/public/index.php/api/";
}
this.supportedVersion = 1;
}
......@@ -38,6 +42,21 @@ class SHAPI {
});
}
async getCurrentVersion() {
let apiPath = this.apiBase + "currentVersion";
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 getNewSongs(_offset) {
let apiPath = this.apiBase + "songs/new/" + _offset;
let supportedVersion = this.supportedVersion;
......@@ -74,7 +93,37 @@ class SHAPI {
let apiPath = this.apiBase + "song/" + _songId;
let supportedVersion = this.supportedVersion;
console.log(apiPath);
return axios.get(apiPath)
.then(function(response) {
if(response.data.version !== supportedVersion) {
throw new Error("Client is outdated!");
}
return response.data;
}).catch(function(error) {
throw new Error(error);
});
}
async getUserDetail(_userId) {
let apiPath = this.apiBase + "user/" + _userId;
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;
}).catch(function(error) {
throw new Error(error);
});
}
async search(_searchQuery) {
let apiPath = this.apiBase + "search/" + _searchQuery;
let supportedVersion = this.supportedVersion;
return axios.get(apiPath)
.then(function(response) {
......
......@@ -2,6 +2,7 @@ let DOMNavigationItems = document.querySelectorAll("aside .item");
let DOMSections = document.querySelectorAll("section");
let DOMSectionSongDetail = document.querySelector(".section-song-detail");
let DOMSectionUserDetail = document.querySelector(".section-user-detail");
let currentSection = 0;
......@@ -36,6 +37,7 @@ function NavigateToSection(sectionIndex) {
break;
case 1:
// Search
InitSearch();
break;
case 2:
// Library
......@@ -48,12 +50,23 @@ function NavigateToSection(sectionIndex) {
case 4:
// SongDetail
break;
case 5:
// Connection Error
break;
case 6:
// 404 Error
break;
case 7:
// User Detail
break;
}
}
NavigateToSection(0);
function NavigateToSongDetail(songId) {
console.log("Loading Song " + songId);
// Stop audio if playing
SongDetailStopPreview();
......@@ -72,3 +85,23 @@ function NavigateToSongDetail(songId) {
SongDetailLoad(songId);
}
function NavigateToUser(userId) {
// Stop audio if playing
SongDetailStopPreview();
// Navigation
DOMNavigationItems.forEach(function(DOMNavigation) {
DOMNavigation.classList.remove("active");
});
// Section
DOMSections.forEach(function(DOMSection) {
DOMSection.classList.remove("active");
});
// Load Detail
DOMSectionUserDetail.classList.add("active");
UserDetailLoad(userId);
}
\ No newline at end of file
// Protocol
ipcRenderer.on("protocol-to-songdetail", (event, info) => {
console.log(info);
});
\ No newline at end of file
const DOMSearchBar = document.querySelector(".search-bar input");
const DOMSearchResultsUsers = document.querySelector(".search-results-users");
const DOMSearchResultsSongs = document.querySelector(".search-results-songs");
const DOMSearchResultsNoresults = document.querySelector(".search-results-noresults");
const DOMUsersList = DOMSearchResultsUsers.querySelector(".user-list");
const DOMSongsList = DOMSearchResultsSongs.querySelector(".song-list");
function InitSearch() {
SearchQuery("");
}
function SearchQuery(query) {
DOMSearchBar.value = query;
DOMSearchResultsUsers.classList.remove("active");
DOMSearchResultsSongs.classList.remove("active");
DOMSearchResultsNoresults.querySelector(".noresults-title").innerText = query;
DOMSearchResultsNoresults.classList.remove("active");
DOMUsersList.innerHTML = "";
DOMSongsList.innerHTML = "";
if(query != "") {
api.search(query).then(function(searchResults) {
if(searchResults.data.users.length == 0 && searchResults.data.songs.length == 0) {
DOMSearchResultsNoresults.classList.add("active");
} else {
if(searchResults.data.users.length > 0) {
DOMSearchResultsUsers.classList.add("active");
searchResults.data.users.forEach(function(user) {
DOMUsersList.appendChild(BuildUserDOM(user));
});
}
if(searchResults.data.songs.length > 0) {
DOMSearchResultsSongs.classList.add("active");
searchResults.data.songs.forEach(function(song) {
DOMSongsList.appendChild(BuildSongDOM(song));
});
}
}
}).catch(function(error) {
NavigateToSection(6);
console.error(error);
});
}
}
function BuildUserDOM(userItem) {
let userContainer = document.createElement("div");
userContainer.classList.add("user-item");
let userAvatar = document.createElement("div");
userAvatar.classList.add("user-avatar");
userAvatar.style.backgroundImage = "url('" + userItem.avatar + "')";
userContainer.appendChild(userAvatar);
let userMetaData = document.createElement("div");
userMetaData.classList.add("user-metadata");
let userName = document.createElement("div");
userName.classList.add("user-username");
userName.innerText = userItem.username;
userMetaData.appendChild(userName);
userContainer.appendChild(userMetaData);
userContainer.addEventListener('click', function() {
NavigateToUser(userItem.id);
});
return userContainer;
}
\ No newline at end of file
......@@ -14,10 +14,6 @@ function InitSettings() {
DOMSettingsInputGameDirectory.value = userSettings.get('gameDirectory');
}
function CheckForUpdate() {
}
function SettingsChangeLanguage() {
let selectedLanguage = DOMSettingsInputLanguage.value;
userSettings.set('language', selectedLanguage);
......
......@@ -10,8 +10,9 @@ const DOMButtonPreview = DOMSongDetailActions.querySelector(".button-preview");
const DOMSongTitle = DOMSongDetail.querySelector(".song-title");
const DOMSongSubtitle = DOMSongDetail.querySelector(".song-subtitle");
const DOMSongArtist = DOMSongDetail.querySelector(".song-artist");
const DOMSongCharter = DOMSongDetail.querySelector(".song-charter span");
const DOMSongCharter = DOMSongDetail.querySelector(".song-charter");
const DOMSongTags = DOMSongDetail.querySelector(".song-tags");
const DOMSongUploader = DOMSongDetail.querySelector(".song-uploader");
function SongDetailLoad(songId) {
currentSongId = 0;
......@@ -23,9 +24,12 @@ function SongDetailLoad(songId) {
api.getSongDetail(songId).then(function(apiResponse) {
let songData = apiResponse.data;
if(apiResponse.status == 404) {
NavigateToSection(6);
if(apiResponse.status == 404 || songData.length == 0) {
NavigateToSection(7);
} else {
api.getUserDetail(songData.uploader).then(function(uploaderResponse) {
let uploaderData = uploaderResponse.data;
DOMSongDetail.classList.add("active");
DOMSongDetailActions.classList.add("active");
......@@ -35,9 +39,12 @@ function SongDetailLoad(songId) {
DOMSongTitle.innerText = songData.title;
DOMSongSubtitle.innerText = songData.subtitle;
DOMSongArtist.innerText = songData.artist;
DOMSongCharter.innerText = songData.charter;
DOMSongCharter.innerText = locale.get('songdetail.createdBy') + " " + songData.charter;
DOMButtonPreview.innerText = "PLAY PREVIEW";
DOMSongUploader.innerHTML = "";
DOMSongUploader.appendChild(BuildUserDOM(uploaderData));
DOMButtonPreview.innerText = locale.get('songdetail.actions.playPreviewButton');
DOMSongTags.innerHTML = "";
songData.tags.forEach(function(tag) {
......@@ -46,16 +53,22 @@ function SongDetailLoad(songId) {
newTag.classList.add("tag");
newTag.innerText = tag;
newTag.addEventListener('click', function() {
NavigateToSection(1);
SearchQuery(tag);
});
DOMSongTags.appendChild(newTag);
}
});
});
}
currentSongId = songId;
currentSongData = songData;
}).catch(function(error) {
console.error(error);
NavigateToSection(5);
NavigateToSection(6);
});
}
......@@ -74,7 +87,7 @@ function SongDetailStartPreview() {
SongDetailStopPreview();
}
isPlayingPreview = true;
DOMButtonPreview.innerText = "PAUSE PREVIEW";
DOMButtonPreview.innerText = locale.get('songdetail.actions.stopPreviewButton');
DOMButtonPreview.classList.add("button-primary");
}
function SongDetailStopPreview() {
......@@ -85,7 +98,7 @@ function SongDetailStopPreview() {
currentPreviewAudio = null;
isPlayingPreview = false;
DOMButtonPreview.innerText = "PLAY PREVIEW";
DOMButtonPreview.innerText = locale.get('songdetail.actions.playPreviewButton');
DOMButtonPreview.classList.remove("button-primary");
}
......@@ -94,9 +107,9 @@ function SongDetailDownload() {
}
function SongDetailCopyLink() {
clipboard.writeText("https://spinsha.re/song/" + currentSongId);
}
function SongDetailReport() {
alert("Coming soon...");
shell.openExternal("https://spinsha.re/report/" + currentSongId);
}
\ No newline at end of file
......@@ -23,7 +23,7 @@ function InitStartup() {
DOMStaffAds.appendChild(BuildAdDOM(ad));
});
}).catch(function(error) {
NavigateToSection(5);
NavigateToSection(6);
console.error(error);
});
......@@ -84,7 +84,7 @@ function LoadNewSongs() {
DOMNewSongsList.appendChild(BuildSongDOM(song));
});
}).catch(function(error) {
NavigateToSection(5);
NavigateToSection(6);
console.error(error);
});
}
......@@ -97,7 +97,7 @@ function LoadPopularSongs() {
DOMPopularSongsList.appendChild(BuildSongDOM(song));
});
}).catch(function(error) {
NavigateToSection(5);
NavigateToSection(6);
console.error(error);
});
}
......@@ -141,14 +141,14 @@ function BuildAdDOM(adItem) {
break;
case 2:
// Search Query
// TODO
NavigateToSection(1);
SearchQuery(adItem.button.data);
break;
case 3:
// External
adButton.addEventListener('click', function() {
shell.openExternal(adItem.button.data);
});
// TODO
}
adContainer.appendChild(adButton);
......
const DOMUserDetailBackground = document.querySelector(".user-detail-background");
const DOMUserDetail = document.querySelector(".section-user-detail .user-detail");
const DOMUserDetailAvatar = document.querySelector(".section-user-detail .user-avatar");
const DOMUserSongRow = document.querySelector(".song-row-user");
const DOMUserName = DOMUserDetail.querySelector(".user-name");
const DOMUserSongsList = document.querySelector(".song-row-user .song-list");
const DOMUserSongsNoResults = document.querySelector(".song-row-user .song-list-noresults");
function UserDetailLoad(userId) {
DOMUserDetail.classList.remove("active");
DOMUserSongRow.classList.remove("active");
DOMUserSongsNoResults.classList.remove("active");
DOMUserSongsList.innerHTML = "";
api.getUserDetail(userId).then(function(apiResponse) {
let userData = apiResponse.data;
if(apiResponse.status == 404) {
NavigateToSection(7);
} else {
DOMUserDetail.classList.add("active");
DOMUserSongRow.classList.add("active");
DOMUserDetailBackground.style.backgroundImage = "url('" + userData.avatar + "')";
DOMUserDetailAvatar.style.backgroundImage = "url('" + userData.avatar + "')";
DOMUserName.innerText = userData.username;
if(userData.songs.length > 0) {
userData.songs.forEach(function(song) {
DOMUserSongsList.appendChild(BuildSongDOM(song));
});
} else {
DOMUserSongsNoResults.classList.add("active");
}
}
}).catch(function(error) {
console.error(error);
NavigateToSection(6);
});
}
\ No newline at end of file
const DOMUpdateOverlay = document.querySelector(".update-overlay");
const DOMUpdateStatusAvailable = DOMUpdateOverlay.querySelector(".update-status-available");
const DOMUpdateStatusLatest = DOMUpdateOverlay.querySelector(".update-status-latest");
const DOMUpdateActionsAvailable = DOMUpdateOverlay.querySelector(".update-actions-available");
const DOMUpdateActionsLatest = DOMUpdateOverlay.querySelector(".update-actions-latest");
// Check Updates
function CheckForUpdates(showIfLatest) {
api.getCurrentVersion().then(function(versionData) {
DOMUpdateStatusAvailable.classList.remove("active");
DOMUpdateStatusLatest.classList.remove("active");
DOMUpdateActionsAvailable.classList.remove("active");
DOMUpdateActionsLatest.classList.remove("active");
if(versionData.join(".") != app.getVersion() && !isDev) {
DOMUpdateOverlay.classList.add("active");
DOMUpdateStatusAvailable.classList.add("active");
DOMUpdateActionsAvailable.classList.add("active");
} else {
if(showIfLatest) {
DOMUpdateOverlay.classList.add("active");
DOMUpdateStatusLatest.classList.add("active");
DOMUpdateActionsLatest.classList.add("active");
}
}
}).catch(function(error) {
NavigateToSection(6);
console.error(error);
});
}
function DownloadUpdate() {
shell.openExternal("https://spinsha.re/download-client");
}
function IgnoreUpdate() {
DOMUpdateOverlay.classList.remove("active");
}
CheckForUpdates(false);
\ No newline at end of file
......@@ -2,10 +2,25 @@
"startup.newsongs.header": "Neue Songs",
"startup.popularsongs.header": "Populäre Songs",
"search.input.placeholder": "Suche nach Songs, Tags & Profilen...",
"search.results.users.header": "Nutzer",
"search.results.songs.header": "Songs",
"search.noresults.text": "Deine Suche ergab kein Ergebnis. Vergewissere dich, dass alle Wörter korrekt geschrieben wurden oder versuche es mit einem anderen Suchbegriff.",
"library.installed.header": "Installierte Songs",
"library.installed.install.title": "Installieren",
"library.installed.install.text": "Lokale .zip installieren",
"songdetail.createdBy": "Erstellt von ",
"songdetail.actions.downloadButton": "Downloaden",
"songdetail.actions.playPreviewButton": "Vorschau abspielen",
"songdetail.actions.stopPreviewButton": "Vorschau abbrechen",
"songdetail.actions.copyLinkButton": "Link Kopieren",
"songdetail.actions.reportButton": "Melden",
"userdetail.uploaded.header": "Hochgeladene Songs",
"userdetail.uploaded.noresults": "Dieser Nutzer hat noch keine Songs hochgeladen.",
"settings.general.header": "SpinShare",
"settings.general.version.label": "Version",
"settings.general.update.label": "Update",
......@@ -15,5 +30,24 @@
"settings.directories.header": "Ordner",
"settings.directories.gameDirectory.label": "Spiel-Ordner",
"settings.directories.gameDirectory.changeButton": "Ändern",
"settings.directories.gameDirectory.resetButton": "Zurücksetzen"
"settings.directories.gameDirectory.resetButton": "Zurücksetzen",
"connectionerror.server.title": "Verbindungsfehler",
"connectionerror.server.text": "Bitte überprüfe deine Internetverbindung oder versuche es später erneut. Du kannst weiterhin deine Audiothek nutzen und lokale .zip Backups installieren.",
"connectionerror.notfound.title": "404 - Nicht gefunden",
"connectionerror.notfound.text": "Entschuldigung, das konnten wir nicht finden. Es wurde entweder gelöscht oder war ohnehin nie verfügbar.",
"download.status.downloading": "Herunterladen",
"download.status.extracting": "Auspacken",
"download.status.extractingFailed": "Konnte den Song nicht auspacken!",
"download.status.installing": "Installieren",
"download.status.installingFailed": "Konnte den Song nicht installieren!",
"download.status.done": "Fertig",
"download.closeButton": "Schließen",
"update.availableText": "Ein Update ist verfügbar.",
"update.latestText": "Du hast bereits die neueste Version.",
"update.download": "Herunterladen",
"update.later": "Später",
"update.close": "Schließen"
}
\ No newline at end of file
......@@ -2,10 +2,25 @@
"startup.newsongs.header": "New Songs",
"startup.popularsongs.header": "Popular Songs",
"search.input.placeholder": "Search for songs, tags & profiles...",
"search.results.users.header": "Users",
"search.results.songs.header": "Songs",
"search.noresults.text": "Your search did not match any songs or users. Make sure, that all words are spelled correctly or try a different query.",
"library.installed.header": "Installed Songs",
"library.installed.install.title": "Install",
"library.installed.install.text": "Install a local .zip",
"songdetail.createdBy": "Created by ",
"songdetail.actions.downloadButton": "Download",
"songdetail.actions.playPreviewButton": "Play Preview",
"songdetail.actions.stopPreviewButton": "Stop Preview",
"songdetail.actions.copyLinkButton": "Copy Link",
"songdetail.actions.reportButton": "Report",
"userdetail.uploaded.header": "Uploaded Songs",
"userdetail.uploaded.noresults": "This user did not upload any songs yet.",
"settings.general.header": "SpinShare",
"settings.general.version.label": "Version",
"settings.general.update.label": "Update",
......@@ -15,5 +30,24 @@
"settings.directories.header": "Directories",
"settings.directories.gameDirectory.label": "Game Directory",
"settings.directories.gameDirectory.changeButton": "Change",
"settings.directories.gameDirectory.resetButton": "Reset"
"settings.directories.gameDirectory.resetButton": "Reset",
"connectionerror.server.title": "Connection error",
"connectionerror.server.text": "Please check your internet connection or try again later. You can still access your library and install local .zip backups.",
"connectionerror.notfound.title": "404 - Not Found",
"connectionerror.notfound.text": "Sorry, we couldn't find that. It was either removed or never available in the first place.",
"download.status.downloading": "Downloading",
"download.status.extracting": "Extracting",
"download.status.extractingFailed": "Could not extract song!",
"download.status.installing": "Installing",
"download.status.installingFailed": "Could not install song!",
"download.status.done": "Done",
"download.closeButton": "Close",
"update.availableText": "An update is available.",
"update.latestText": "You already have the latest version.",
"update.download": "Download",
"update.later": "Later",
"update.close": "Close"
}
\ 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