Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
D
Desktop Client
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
SpinShare
Desktop Client
Commits
88725d89
Commit
88725d89
authored
May 10, 2020
by
SpinShare
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
added userdetail and manual install and fixed download queue
parent
69b916f5
Changes
15
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
593 additions
and
253 deletions
+593
-253
package-lock.json
package-lock.json
+119
-149
package.json
package.json
+1
-0
src/App.vue
src/App.vue
+58
-32
src/background.js
src/background.js
+32
-4
src/components/Song/SongInstallItem.vue
src/components/Song/SongInstallItem.vue
+2
-4
src/components/Song/SongItem.vue
src/components/Song/SongItem.vue
+25
-16
src/components/Song/SongRow.vue
src/components/Song/SongRow.vue
+2
-0
src/components/Startup/Stream.vue
src/components/Startup/Stream.vue
+70
-0
src/components/User/UserItem.vue
src/components/User/UserItem.vue
+4
-2
src/modules/module.api.js
src/modules/module.api.js
+16
-0
src/modules/module.srxd.js
src/modules/module.srxd.js
+31
-34
src/router/index.js
src/router/index.js
+5
-0
src/views/Library.vue
src/views/Library.vue
+35
-0
src/views/StartupFrontpage.vue
src/views/StartupFrontpage.vue
+23
-12
src/views/UserDetail.vue
src/views/UserDetail.vue
+170
-0
No files found.
package-lock.json
View file @
88725d89
This diff is collapsed.
Click to expand it.
package.json
View file @
88725d89
...
...
@@ -12,6 +12,7 @@
},
"main"
:
"background.js"
,
"dependencies"
:
{
"
adm-zip
"
:
"
^0.4.14
"
,
"
axios
"
:
"
^0.19.2
"
,
"
core-js
"
:
"
^3.6.4
"
,
"
electron-download-manager
"
:
"
^2.1.2
"
,
...
...
src/App.vue
View file @
88725d89
...
...
@@ -12,7 +12,7 @@
</transition>
<transition
name=
"slideDownloadOverlay"
>
<DownloadOverlay
v-if=
"showDownloadOverlay"
v-bind:downloadQueue=
"downloadQueue"
></DownloadOverlay>
<DownloadOverlay
v-if=
"showDownloadOverlay"
v-bind:downloadQueue=
"downloadQueue"
v-bind:finishedQueue=
"finishedQueue"
v-bind:failedQueue=
"failedQueue"
></DownloadOverlay>
</transition>
</div>
</
template
>
...
...
@@ -24,7 +24,6 @@
import
fs
from
'
fs
'
;
import
glob
from
'
glob
'
;
import
path
from
'
path
'
;
import
ncp
from
'
ncp
'
;
import
UserSettings
from
'
@/modules/module.usersettings.js
'
;
import
SSAPI
from
'
@/modules/module.api.js
'
;
...
...
@@ -46,6 +45,8 @@
data
:
function
()
{
return
{
downloadQueue
:
[],
finishedQueue
:
[],
failedQueue
:
[],
downloadQueueProcessing
:
false
,
showUpdateOverlay
:
false
,
showDownloadOverlay
:
false
,
...
...
@@ -53,6 +54,10 @@
}
},
mounted
:
function
()
{
document
.
addEventListener
(
'
auxclick
'
,
function
(
e
)
{
e
.
preventDefault
();
});
this
.
$root
.
$on
(
'
download
'
,
(
url
)
=>
{
this
.
addToQueue
(
url
);
});
...
...
@@ -88,15 +93,28 @@
let
srxdControl
=
new
SRXD
();
let
userSettings
=
new
UserSettings
();
let
queueItem
=
this
.
$data
.
downloadQueue
.
findIndex
(
function
(
i
)
{
return
i
.
id
===
downloadItem
.
id
;
});
console
.
info
(
"
████ #
"
+
queueItem
+
"
- '
"
+
this
.
$data
.
downloadQueue
[
queueItem
].
title
+
"
' ████
"
);
if
(
downloadItem
.
status
==
1
)
{
// Failed, add to failed Array
this
.
$data
.
failedQueue
.
push
(
queueItem
);
this
.
$data
.
downloadQueue
.
splice
(
queueItem
,
1
);
}
else
{
// Finished, unpacking
srxdControl
.
extractBackup
(
downloadItem
.
downloadPath
,
path
.
basename
(
downloadItem
.
downloadPath
)).
then
((
extractResult
)
=>
{
if
(
extractResult
)
{
this
.
installBackup
(
extractResult
,
userSettings
.
get
(
'
gameDirectory
'
)).
then
((
result
)
=>
{
if
(
extractResult
!==
false
)
{
srxdControl
.
installBackup
(
extractResult
,
userSettings
.
get
(
'
gameDirectory
'
)).
then
((
result
)
=>
{
console
.
log
(
"
[COPY] Backup installed!
"
);
this
.
$data
.
downloadQueueProcessing
=
false
;
console
.
log
(
"
Queue Remaining
:
"
+
this
.
$data
.
downloadQueue
.
length
);
console
.
log
(
"
[QUEUE] Remaining Items
:
"
+
this
.
$data
.
downloadQueue
.
length
);
this
.
$data
.
downloadQueue
.
splice
(
this
.
$data
.
downloadQueue
.
findIndex
(
function
(
i
)
{
return
i
.
id
===
downloadItem
.
id
;
}),
1
);
this
.
$data
.
finishedQueue
.
push
(
queueItem
);
this
.
$data
.
downloadQueue
.
splice
(
queueItem
,
1
);
if
(
this
.
$data
.
downloadQueue
.
length
>
0
)
{
this
.
processQueue
();
...
...
@@ -105,11 +123,32 @@
console
.
error
(
error
);
});
}
else
{
console
.
error
(
"
Backup could not be loaded!
"
);
console
.
error
(
"
[COPY] Backup could not be installed!
"
);
this
.
$data
.
downloadQueueProcessing
=
false
;
console
.
log
(
"
[QUEUE] Remaining Items:
"
+
this
.
$data
.
downloadQueue
.
length
);
this
.
$data
.
failedQueue
.
push
(
queueItem
);
this
.
$data
.
downloadQueue
.
splice
(
queueItem
,
1
);
if
(
this
.
$data
.
downloadQueue
.
length
>
0
)
{
this
.
processQueue
();
}
}
}).
catch
(
error
=>
{
console
.
error
(
error
);
this
.
$data
.
downloadQueueProcessing
=
false
;
console
.
log
(
"
[QUEUE] Remaining Items:
"
+
this
.
$data
.
downloadQueue
.
length
);
this
.
$data
.
failedQueue
.
push
(
queueItem
);
this
.
$data
.
downloadQueue
.
splice
(
queueItem
,
1
);
if
(
this
.
$data
.
downloadQueue
.
length
>
0
)
{
this
.
processQueue
();
}
});
}
});
},
methods
:
{
...
...
@@ -133,19 +172,6 @@
closeOverlays
:
function
()
{
this
.
$data
.
showUpdateOverlay
=
false
;
this
.
$data
.
showDownloadOverlay
=
false
;
},
installBackup
:
async
function
(
backupLocation
,
gameDirLocation
)
{
await
ncp
(
backupLocation
,
gameDirLocation
,
function
(
error
)
{
if
(
error
)
{
console
.
error
(
error
);
console
.
error
(
"
Couldn't copy backup!
"
);
return
true
;
}
console
.
log
(
"
Copied Backup!
"
);
});
return
true
;
}
}
}
...
...
src/background.js
View file @
88725d89
...
...
@@ -2,6 +2,10 @@ const { app, protocol, BrowserWindow, ipcMain } = require('electron');
const
DownloadManager
=
require
(
"
electron-download-manager
"
);
const
{
createProtocol
}
=
require
(
'
vue-cli-plugin-electron-builder/lib
'
);
const
isDevelopment
=
process
.
env
.
NODE_ENV
!==
'
production
'
;
const
fs
=
require
(
'
fs
'
);
const
http
=
require
(
'
http
'
);
const
path
=
require
(
'
path
'
);
const
uniqid
=
require
(
'
uniqid
'
);
let
win
;
let
deeplinkingUrl
;
...
...
@@ -73,19 +77,43 @@ if (isDevelopment) {
}
ipcMain
.
on
(
"
download
"
,
(
event
,
ipcData
)
=>
{
console
.
log
(
"
Download:
"
+
ipcData
.
queueItem
.
title
);
console
.
log
(
"
Starting download of >
"
+
ipcData
.
queueItem
.
title
);
DownloadManager
.
download
({
url
:
ipcData
.
queueItem
.
downloadPath
}
,
(
error
,
dlInfo
)
=>
{
download
(
ipcData
.
queueItem
.
downloadPath
,
uniqid
()
,
(
error
,
dlInfo
)
=>
{
if
(
error
)
{
console
.
log
(
error
);
let
downloadItem
=
{
id
:
ipcData
.
queueItem
.
id
,
status
:
1
,
downloadPath
:
null
}
win
.
webContents
.
send
(
"
download-complete
"
,
downloadItem
);
return
;
}
let
downloadItem
=
{
id
:
ipcData
.
queueItem
.
id
,
downloadPath
:
dlInfo
.
filePath
status
:
2
,
downloadPath
:
dlInfo
}
win
.
webContents
.
send
(
"
download-complete
"
,
downloadItem
);
});
});
function
download
(
url
,
fileName
,
cb
)
{
let
dest
=
path
.
join
(
app
.
getPath
(
'
temp
'
),
fileName
+
"
.zip
"
);
let
file
=
fs
.
createWriteStream
(
dest
);
let
request
=
http
.
get
(
url
,
function
(
response
)
{
response
.
pipe
(
file
);
file
.
on
(
'
finish
'
,
function
()
{
file
.
close
(
cb
(
null
,
dest
));
// async call of the callback
});
}).
on
(
'
error
'
,
function
(
err
)
{
// Handle errors
fs
.
unlink
(
dest
);
// Delete the file async. (But we don't check the result)
if
(
cb
)
cb
(
err
.
message
,
dest
);
});
};
\ No newline at end of file
src/components/Song/SongInstallItem.vue
View file @
88725d89
...
...
@@ -11,9 +11,6 @@
</
template
>
<
script
>
import
{
remote
}
from
'
electron
'
;
const
{
clipboard
}
=
remote
;
export
default
{
name
:
'
SongInstallItem
'
,
data
:
function
()
{
...
...
@@ -23,7 +20,8 @@
mounted
:
function
()
{
},
methods
:
{
install
:
function
(
e
)
{
install
:
function
()
{
this
.
$parent
.
$parent
.
$emit
(
'
install
'
);
}
}
}
...
...
src/components/Song/SongItem.vue
View file @
88725d89
<
template
>
<div
class=
"song-item"
v-on:contextmenu=
"showContextMenu($event)"
>
<div
class=
"song-item"
v-on:
auxclick=
"shortDownload($event)"
v-on:
contextmenu=
"showContextMenu($event)"
>
<router-link
:to=
"
{ name: 'SongDetail', params: { id: id } }">
<div
class=
"song-cover"
:style=
"'background-image: url(' + cover + '), url(' + require('@/assets/img/defaultAlbumArt.jpg') + ');'"
>
<div
class=
"song-charter-info"
>
...
...
@@ -61,7 +61,16 @@
{
icon
:
"
download
"
,
title
:
"
Download
"
,
method
:
()
=>
{
this
.
download
();
}
}
]});
},
download
:
function
()
{
shortDownload
:
function
(
e
)
{
e
.
preventDefault
();
if
(
e
.
which
==
2
)
{
this
.
download
(
e
);
}
},
download
:
function
(
e
)
{
e
.
preventDefault
();
this
.
$root
.
$emit
(
'
download
'
,
{
id
:
this
.
$props
.
id
,
cover
:
this
.
$props
.
cover
,
title
:
this
.
$props
.
title
,
artist
:
this
.
$props
.
artist
,
downloadPath
:
this
.
$props
.
zip
});
}
}
...
...
src/components/Song/SongRow.vue
View file @
88725d89
...
...
@@ -9,6 +9,8 @@
<div
class=
"song-list"
>
<slot
name=
"song-list"
></slot>
</div>
<div
class=
"noresults"
>
</div>
</div>
</
template
>
...
...
src/components/Startup/Stream.vue
0 → 100644
View file @
88725d89
<
template
>
<div
class=
"stream"
v-if=
"isLive"
>
<div
class=
"header"
>
<div
class=
"viewers"
><i
class=
"mdi mdi-eye-outline"
></i>
{{
viewers
}}
</div>
<div
class=
"title"
>
{{
title
}}
</div>
</div>
<div
class=
"video-container"
>
<iframe
src=
"https://player.twitch.tv/?channel=spinshare&enableExtensions=true&muted=true&player=popout&volume=1"
></iframe>
</div>
</div>
</
template
>
<
script
>
import
{
remote
}
from
'
electron
'
;
const
{
shell
}
=
remote
;
export
default
{
name
:
'
Stream
'
,
props
:
[
'
title
'
,
'
viewers
'
,
'
isLive
'
]
}
</
script
>
<
style
scoped
lang=
"less"
>
.stream {
margin-top: 50px;
& .header {
display: grid;
grid-template-columns: auto 1fr;
grid-gap: 15px;
margin-bottom: 15px;
& .viewers {
background: #ff294d;
color: #fff;
padding: 5px;
font-size: 12px;
font-weight: bold;
border-radius: 20px;
}
& .title {
letter-spacing: 0.25em;
font-size: 14px;
font-weight: bold;
text-transform: uppercase;
align-self: center;
}
}
& .video-container {
position: relative;
width: 100%;
padding-top: 50%;
& iframe {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
width: 100%;
height: 100%;
border: 0px;
}
}
}
</
style
>
src/components/User/UserItem.vue
View file @
88725d89
<
template
>
<
div
class=
"user-item"
>
<
router-link
:to=
"
{ name: 'UserDetail', params: { id: id } }"
class="user-item">
<div
class=
"user-avatar"
:style=
"'background-image: url(' + avatar + '), url(' + require('@/assets/img/defaultAvatar.jpg') + ');'"
></div>
<div
class=
"user-metadata"
>
<div
class=
"user-username"
>
{{
username
}}
</div>
</div>
</
div
>
</
router-link
>
</
template
>
<
script
>
...
...
@@ -51,6 +51,8 @@
display: grid;
padding: 10px;
grid-gap: 15px;
color: #fff;
text-decoration: none;
grid-template-columns: 32px 1fr;
& .user-avatar {
...
...
src/modules/module.api.js
View file @
88725d89
...
...
@@ -26,6 +26,22 @@ class SSAPI {
});
}
async
getStreamStatus
()
{
let
apiPath
=
this
.
apiBase
+
"
streamStatus
"
;
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
getLatestVersion
()
{
let
apiPath
=
this
.
apiBase
+
"
latestVersion/
"
+
process
.
platform
;
let
supportedVersion
=
this
.
supportedVersion
;
...
...
src/modules/module.srxd.js
View file @
88725d89
...
...
@@ -3,6 +3,8 @@ const fs = require('fs');
const
path
=
require
(
'
path
'
);
const
rimraf
=
require
(
'
rimraf
'
);
const
unzipper
=
require
(
'
unzipper
'
);
const
ncp
=
require
(
'
ncp
'
);
const
admzip
=
require
(
'
adm-zip
'
);
const
uniqid
=
require
(
'
uniqid
'
);
const
{
app
}
=
require
(
'
electron
'
).
remote
;
const
UserSettings
=
require
(
'
./module.usersettings
'
);
...
...
@@ -20,51 +22,42 @@ class SRXD {
// Extract a local backup folder
async
extractBackup
(
filePath
,
fileName
)
{
if
(
this
.
backupLocation
!=
""
)
{
console
.
log
(
"
Unload
previous Backup.
"
);
console
.
log
(
"
{EXTRACT] Unloading
previous Backup.
"
);
this
.
unloadBackup
();
}
console
.
log
(
"
Extracting Backup
.
"
);
console
.
log
(
"
[EXTRACT] Starting Extraction
.
"
);
this
.
backupLocation
=
path
.
join
(
app
.
getPath
(
'
temp
'
),
"
extract-
"
+
uniqid
());
console
.
info
(
this
.
backupLocation
);
console
.
info
(
"
[EXTRACT] Backup Location:
"
+
this
.
backupLocation
);
// Unzip to temp/CustomSpeens/Song
await
fs
.
createReadStream
(
filePath
).
pipe
(
unzipper
.
Extract
({
path
:
this
.
backupLocation
})).
promise
();
// Find SRTB & OGG files
let
srtbFilesInBackupLocation
=
this
.
getFilesFromPath
(
this
.
backupLocation
,
"
.srtb
"
);
if
(
srtbFilesInBackupLocation
.
length
<
1
)
{
console
.
error
(
"
No SRTB file found in backup.
"
);
try
{
console
.
log
(
"
[EXTRACT] Unzipping.
"
);
console
.
log
(
"
[EXTRACT]
"
+
filePath
);
console
.
log
(
"
[EXTRACT]
"
+
this
.
backupLocation
);
let
zip
=
admzip
(
filePath
);
await
zip
.
extractAllTo
(
this
.
backupLocation
,
true
);
}
catch
(
e
)
{
console
.
log
(
"
[EXTRACT] Couldn't unzip backup
"
);
console
.
error
(
e
);
return
false
;
}
// Load SRTB file
this
.
srtbLocation
=
path
.
join
(
this
.
backupLocation
,
srtbFilesInBackupLocation
[
0
]);
let
srtbFile
=
JSON
.
parse
(
fs
.
readFileSync
(
this
.
srtbLocation
)
);
let
songTrackInfo
=
""
;
srtbFile
.
largeStringValuesContainer
.
values
.
forEach
(
function
(
value
)
{
if
(
value
.
key
==
"
SO_TrackInfo_TrackInfo
"
)
{
songTrackInfo
=
value
.
val
;
}
});
this
.
songTrackInfo
=
songTrackInfo
;
// Load OGG file
let
OggFilePath
=
fs
.
existsSync
(
path
.
join
(
this
.
backupLocation
,
"
AudioClips
"
),
"
.ogg
"
)
if
(
fs
.
existsSync
(
OggFilePath
))
{
let
oggFilesInBackupLocation
=
this
.
getFilesFromPath
(
OggFilePath
);
this
.
songLocation
=
path
.
join
(
this
.
backupLocation
,
oggFilesInBackupLocation
[
0
]);
// TODO: Backup Validation
return
this
.
backupLocation
;
}
else
{
return
this
.
backupLocation
;
async
installBackup
(
backupLocation
,
gameDirLocation
)
{
await
ncp
(
backupLocation
,
gameDirLocation
,
function
(
error
)
{
if
(
error
)
{
console
.
error
(
error
);
console
.
error
(
"
[COPY] Couldn't copy backup!
"
);
return
false
;
}
console
.
info
(
"
[COPY] Done!
"
);
return
true
;
});
}
async
unloadBackup
()
{
...
...
@@ -123,7 +116,11 @@ class SRXD {
if
(
fileExtension
.
length
>
0
)
{
let
finalPath
=
path
.
join
(
this
.
userSettings
.
get
(
'
gameDirectory
'
),
"
AlbumArt
"
,
fileExtension
[
0
]);
try
{
let
base64Data
=
"
data:image/jpg;base64,
"
+
fs
.
readFileSync
(
finalPath
,
{
encoding
:
'
base64
'
});
}
catch
(
e
)
{
return
""
;
}
return
base64Data
;
}
else
{
...
...
src/router/index.js
View file @
88725d89
...
...
@@ -10,6 +10,7 @@ import ViewStartupPopularSongs from '../views/StartupPopularSongs.vue';
import
ViewSearch
from
'
../views/Search.vue
'
;
import
ViewLibrary
from
'
../views/Library.vue
'
;
import
ViewSongDetail
from
'
../views/SongDetail.vue
'
;
import
ViewUserDetail
from
'
../views/UserDetail.vue
'
;
import
ViewSettings
from
'
../views/Settings.vue
'
;
Vue
.
use
(
VueRouter
);
...
...
@@ -53,6 +54,10 @@ const routes = [{
path
:
'
/song/:id
'
,
name
:
'
SongDetail
'
,
component
:
ViewSongDetail
},,
{
path
:
'
/user/:id
'
,
name
:
'
UserDetail
'
,
component
:
ViewUserDetail
},
{
path
:
'
/settings
'
,
name
:
'
Settings
'
,
...
...
src/views/Library.vue
View file @
88725d89
...
...
@@ -20,6 +20,9 @@
</template>
<
script
>
import
{
remote
}
from
'
electron
'
;
const
{
dialog
}
=
remote
;
import
fs
from
'
fs
'
;
import
glob
from
'
glob
'
;
import
path
from
'
path
'
;
...
...
@@ -66,6 +69,9 @@
this
.
$data
.
showDeleteOverlay
=
false
;
this
.
$data
.
deleteFiles
=
""
;
});
this
.
$on
(
'
install
'
,
()
=>
{
this
.
install
();
});
},
methods
:
{
refreshLibrary
:
function
()
{
...
...
@@ -149,6 +155,35 @@
});
return
connectedFiles
;
},
install
:
function
(
e
)
{
dialog
.
showOpenDialog
({
title
:
"
Open Backup
"
,
properties
:
[
'
openFile
'
,
'
multiSelections
'
],
filters
:
[{
"
name
"
:
"
Backup Archive
"
,
"
extensions
"
:
[
"
zip
"
]}]
}).
then
(
result
=>
{
if
(
!
result
.
canceled
)
{
result
.
filePaths
.
forEach
((
rawFilePath
)
=>
{
let
filePath
=
glob
.
sync
(
rawFilePath
);
if
(
filePath
.
length
>
0
)
{
let
srxdControl
=
new
SRXD
();
let
userSettings
=
new
UserSettings
();
srxdControl
.
extractBackup
(
filePath
[
0
],
path
.
basename
(
filePath
[
0
])).
then
((
extractResult
)
=>
{
if
(
extractResult
!==
false
)
{
srxdControl
.
installBackup
(
extractResult
,
userSettings
.
get
(
'
gameDirectory
'
)).
then
((
result
)
=>
{
console
.
log
(
"
[COPY] Backup installed!
"
);
setTimeout
(()
=>
{
this
.
refreshLibrary
();
},
250
);
}).
catch
(
error
=>
{
console
.
error
(
error
);
});
}
else
{
console
.
error
(
"
[COPY] Backup could not be installed!
"
);
}
}).
catch
(
error
=>
{
console
.
error
(
error
);
});
}
});
}
});
}
}
}
...
...
src/views/StartupFrontpage.vue
View file @
88725d89
<
template
>
<div
class=
"frontpage"
>
<div
class=
"staff-promos"
>
<StaffPromoPlaceholder
v-if=
"isPromoLoading"
...
...
@@ -10,19 +11,24 @@
v-bind:key=
"staffPromo.id"
v-bind=
"staffPromo"
/>
</div>
<Stream
v-bind=
"streamStatus"
/>
</div>
</
template
>
<
script
>
import
SSAPI
from
'
@/modules/module.api.js
'
;
import
StaffPromo
from
'
@/components/Startup/StaffPromo.vue
'
;
import
StaffPromoPlaceholder
from
'
@/components/Startup/StaffPromoPlaceholder.vue
'
;
import
Stream
from
'
@/components/Startup/Stream.vue
'
;
export
default
{
name
:
'
StartupFrontpage
'
,
data
:
function
()
{
return
{
isPromoLoading
:
true
,
staffPromos
:
[]
staffPromos
:
[],
streamStatus
:
[]
}
},
mounted
:
function
()
{
...
...
@@ -32,10 +38,15 @@
this
.
$data
.
isPromoLoading
=
false
;
this
.
$data
.
staffPromos
=
data
;
});
ssapi
.
getStreamStatus
().
then
((
data
)
=>
{
this
.
$data
.
streamStatus
=
data
;
});
},
components
:
{
StaffPromo
,
StaffPromoPlaceholder
StaffPromoPlaceholder
,
Stream
},
methods
:
{
}
...
...
src/views/UserDetail.vue
0 → 100644
View file @
88725d89
<
template
>
<section
class=
"section-user-detail"
>
<div
class=
"user-detail-background"
:style=
"'background-image: url(' + avatar + '), url(' + require('@/assets/img/defaultAvatar.jpg') + ');'"
v-if=
"apiFinished"
>
<div
class=
"user-detail-dim"
>
<div
class=
"user-detail"
>
<div
class=
"user-avatar"
:style=
"'background-image: url(' + avatar + '), url(' + require('@/assets/img/defaultAvatar.jpg') + ');'"
></div>
<div
class=
"user-meta-data"
>
<div
class=
"user-name"
>
{{
username
}}
</div>
<div
class=
"user-badge user-badge-verified"
>
<i
class=
"mdi mdi-check-decagram"
></i>
</div>
<div
class=
"user-badge user-badge-patreon"
>
<i
class=
"mdi mdi-patreon"
></i>
</div>
</div>
</div>
</div>
</div>
<div
class=
"user-detail-actions"
v-if=
"apiFinished"
>
<button
class=
"button-report button"
v-on:click=
"OpenReport"
>
{{
$t
(
'
userdetail.actions.reportButton
'
)
}}
</button>
</div>
<SongRow
class=
"song-row-user"
:title=
"$t('userdetail.uploaded.header')"
v-if=
"apiFinished && songs.length > 0"
>
<template
v-slot:song-list
>
<SongItem
v-for=
"song in songs"
v-bind:key=
"song.id"
v-bind=
"song"
/>
</
template
>
</SongRow>
<Loading
v-if=
"!apiFinished"
/>
</section>
</template>
<
script
>
import
{
remote
}
from
'
electron
'
;
const
{
clipboard
,
shell
}
=
remote
;
import
SSAPI
from
'
@/modules/module.api.js
'
;
import
SongRow
from
'
@/components/Song/SongRow.vue
'
;
import
SongItem
from
'
@/components/Song/SongItem.vue
'
;
import
Loading
from
'
@/components/Loading.vue
'
;
export
default
{
name
:
'
UserDetail
'
,
components
:
{
SongRow
,
SongItem
,
Loading
},
data
:
function
()
{
return
{
apiFinished
:
false
,
id
:
0
,
username
:
""
,
isVerified
:
false
,
isPatreon
:
false
,
avatar
:
""
,
songs
:
[]
}
},
mounted
:
function
()
{
let
ssapi
=
new
SSAPI
(
process
.
env
.
NODE_ENV
===
'
development
'
);
ssapi
.
getUserDetail
(
this
.
$route
.
params
.
id
).
then
((
data
)
=>
{
this
.
$data
.
id
=
data
.
data
.
id
;
this
.
$data
.
username
=
data
.
data
.
username
;
this
.
$data
.
isVerified
=
data
.
data
.
isVerified
;
this
.
$data
.
isPatreon
=
data
.
data
.
isPatreon
;
this
.
$data
.
avatar
=
data
.
data
.
avatar
;
this
.
$data
.
songs
=
data
.
data
.
songs
;
this
.
$data
.
apiFinished
=
true
;
});
},
methods
:
{
OpenReport
:
function
()
{
shell
.
openExternal
(
"
https://spinsha.re/report/user/
"
+
this
.
$data
.
id
);
}
}
}
</
script
>
<
style
scoped
lang=
"less"
>
.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: grid;
grid-template-columns: 200px 1fr;
grid-gap: 25px;
& .user-avatar {
width: 200px;
height: 200px;
align-self: center;
background: #eee;
border-radius: 50%;
background-size: cover;
background-position: center;
}
& .user-meta-data {
display: flex;
height: 48px;
align-items: center;
& .user-name {
font-weight: bold;
font-size: 48px;
}
& .user-badge {
display: flex;
align-items: center;
justify-content: center;
font-size: 32px;
margin-left: 20px;
}
}
}
}
}
& .user-detail-actions {
padding: 50px;
padding-top: 0px;
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-gap: 25px;
& .button {
padding: 15px 0px;
font-size: 16px;
transition: 0.2s ease-in-out all, 0.1s ease-in-out transform;
&.button-primary {
background: #fff;
color: #222;
&:hover {
background: #fff;
color: #222;
}
}
&:hover {
background: rgba(255,255,255,0.2);
color: #fff;
opacity: 0.6;
transform: translateY(-4px);
}
&:active {
transform: translateY(-2px);
}
}
}
& .song-row-user {
display: grid;
padding: 50px;
}
}
</
style
>
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment