Compare commits
2 Commits
37338232c2
...
15ea565601
Author | SHA1 | Date | |
---|---|---|---|
15ea565601 | |||
89158497e5 |
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
build/bin
|
||||
frontend/dist
|
||||
frontend/node_modules
|
||||
frontend/node_modules
|
||||
frontend/wailsjs/go
|
||||
|
@ -1,15 +1,44 @@
|
||||
import { createSignal, onMount } from "solid-js";
|
||||
import { For, createResource, createSignal, onMount } from "solid-js";
|
||||
import { GetRandomAlbums } from "../../wailsjs/go/main/App";
|
||||
import {main} from "../../wailsjs/go/models";
|
||||
|
||||
export function Home() {
|
||||
const [hidden, setHidden] = createSignal(true);
|
||||
const [albums] = createResource(GetRandomAlbums);
|
||||
|
||||
onMount(() => {
|
||||
// Fade in the UI
|
||||
setTimeout(() => setHidden(false) , 150);
|
||||
});
|
||||
|
||||
|
||||
return (
|
||||
<div class={`min-h-screen ${hidden() ? "opacity-0" : "opacity-100"} transition-opacity`}>
|
||||
Home :D
|
||||
<div class="py-10 h-64 overflow-scroll whitespace-nowrap">
|
||||
<For each={albums()}>
|
||||
{(album) => <Album album={album} />}
|
||||
</For>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function Album(props: {album: main.Album}) {
|
||||
return (
|
||||
<div class="inline-block mx-2 p-1 w-32 rounded bg-zinc-900">
|
||||
<img
|
||||
class="inline-block rounded w-30 h-30 min-w-30 min-h-30"
|
||||
src={props.album.mediumImageUrl}
|
||||
alt=""
|
||||
/>
|
||||
<br />
|
||||
<div class="text-sm overflow-hidden overflow-ellipsis pt-1">
|
||||
{props.album.name}
|
||||
</div>
|
||||
<div class="text-xs overflow-hidden overflow-ellipsis opacity-50">
|
||||
{props.album.albumArtist}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -72,7 +72,11 @@ export function Login() {
|
||||
</label>
|
||||
<br />
|
||||
<div class="text-center">
|
||||
<button type="submit" class="btn btn-primary">Login</button>
|
||||
<button type="submit" class={`btn btn-primary ${loading() ? "animate-pulse" : ""}`}
|
||||
disabled={loading()}
|
||||
>
|
||||
Login
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<Show when={error() !== ""}>
|
||||
|
@ -5,6 +5,13 @@ export default {
|
||||
content: [
|
||||
"./src/**/*.{js,jsx,ts,tsx}",
|
||||
],
|
||||
theme: {
|
||||
extend: {
|
||||
spacing: {
|
||||
"30": "7.5rem",
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
daisyui,
|
||||
],
|
||||
|
3
frontend/wailsjs/go/main/App.d.ts
vendored
3
frontend/wailsjs/go/main/App.d.ts
vendored
@ -1,5 +1,8 @@
|
||||
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||
// This file is automatically generated. DO NOT EDIT
|
||||
import {main} from '../models';
|
||||
|
||||
export function GetRandomAlbums():Promise<Array<main.Album>>;
|
||||
|
||||
export function Greet(arg1:string):Promise<string>;
|
||||
|
||||
|
@ -2,6 +2,10 @@
|
||||
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||
// This file is automatically generated. DO NOT EDIT
|
||||
|
||||
export function GetRandomAlbums() {
|
||||
return window['go']['main']['App']['GetRandomAlbums']();
|
||||
}
|
||||
|
||||
export function Greet(arg1) {
|
||||
return window['go']['main']['App']['Greet'](arg1);
|
||||
}
|
||||
|
61
session.go
61
session.go
@ -4,29 +4,25 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
"github.com/go-resty/resty/v2"
|
||||
)
|
||||
|
||||
type AuthSuccess struct {
|
||||
Id string `json:"id"`
|
||||
IsAdmin bool `json:"isAdmin"`
|
||||
Name string `json:"name"`
|
||||
SubsonicSalt string `json:"subsonicSalt"`
|
||||
SubsonicToken string `json:"subsonicToken"`
|
||||
Token string `json:"token"`
|
||||
Username string `json:"username"`
|
||||
}
|
||||
|
||||
type AuthError struct {
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
var LoggedUser AuthSuccess
|
||||
var randomAlbumWaitGroup sync.WaitGroup
|
||||
var randomAlbums []Album
|
||||
|
||||
// (Tries to) login to a remote navidrome server
|
||||
func (a *App) Login(server, username, password string) (bool, error) {
|
||||
log.Print("begin Login to server")
|
||||
client := resty.New()
|
||||
|
||||
// TODO: check server for leading https and ending /, normalize
|
||||
// TODO: check server for leading https and trailing /, normalize
|
||||
|
||||
successData := AuthSuccess{}
|
||||
errorData := AuthError{}
|
||||
@ -45,6 +41,13 @@ func (a *App) Login(server, username, password string) (bool, error) {
|
||||
|
||||
if response.IsSuccess() {
|
||||
log.Printf("%+v", successData)
|
||||
|
||||
// Set global session
|
||||
LoggedUser = successData
|
||||
// Begin to load the list of albums on the background
|
||||
randomAlbumWaitGroup.Add(1)
|
||||
go loadAlbums(server)
|
||||
|
||||
return true, nil
|
||||
} else if response.IsError() {
|
||||
log.Printf("%+v", errorData)
|
||||
@ -54,3 +57,39 @@ func (a *App) Login(server, username, password string) (bool, error) {
|
||||
return false, errors.New("invalid state")
|
||||
}
|
||||
}
|
||||
|
||||
// Waits for the random albums to be loaded, and returns them.
|
||||
// This function assumes that the random albums are being loaded in the background.
|
||||
func (a *App) GetRandomAlbums() ([]Album, error) {
|
||||
log.Printf("Waiting for loading group...")
|
||||
randomAlbumWaitGroup.Wait()
|
||||
log.Printf("Waiting group finished")
|
||||
|
||||
return randomAlbums, nil
|
||||
}
|
||||
|
||||
// Loads a list of random albums from the server.
|
||||
func loadAlbums(serverUrl string) {
|
||||
defer randomAlbumWaitGroup.Done()
|
||||
log.Print("begin loadAlbums")
|
||||
client := resty.New()
|
||||
|
||||
var errorData AuthError
|
||||
response, err := client.R().
|
||||
SetHeader("x-nd-authorization", fmt.Sprintf("Bearer %s", LoggedUser.Token)).
|
||||
SetResult(&randomAlbums).
|
||||
SetError(&errorData).
|
||||
Get(fmt.Sprintf("%s/api/album?_end=20&_order=DESC&_sort=random&_start=0", serverUrl))
|
||||
|
||||
if err != nil {
|
||||
log.Print("Get albums error")
|
||||
}
|
||||
|
||||
if response.IsSuccess() {
|
||||
log.Print("Get albums success")
|
||||
// TODO: Begin to load album artwork in the background
|
||||
// Album artwork comes from the url /rest/getCoverArt.view
|
||||
}
|
||||
|
||||
// TODO: Do the loading
|
||||
}
|
||||
|
54
types.go
Normal file
54
types.go
Normal file
@ -0,0 +1,54 @@
|
||||
package main
|
||||
|
||||
import "time"
|
||||
|
||||
// The result of a Login
|
||||
type AuthSuccess struct {
|
||||
Id string `json:"id"`
|
||||
IsAdmin bool `json:"isAdmin"`
|
||||
Name string `json:"name"`
|
||||
SubsonicSalt string `json:"subsonicSalt"`
|
||||
SubsonicToken string `json:"subsonicToken"`
|
||||
Token string `json:"token"`
|
||||
Username string `json:"username"`
|
||||
}
|
||||
|
||||
// An album as defined by the server
|
||||
type Album struct {
|
||||
PlayCount int `json:"playCount"`
|
||||
PlayDate time.Time `json:"playDate"`
|
||||
Rating int `json:"rating"`
|
||||
Starred bool `json:"starred"`
|
||||
StarredAt time.Time `json:"starredAt"`
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
EmbedArtPath string `json:"embedArtPath"`
|
||||
ArtistID string `json:"artistId"`
|
||||
Artist string `json:"artist"`
|
||||
AlbumArtistID string `json:"albumArtistId"`
|
||||
AlbumArtist string `json:"albumArtist"`
|
||||
AllArtistIds string `json:"allArtistIds"`
|
||||
MaxYear int `json:"maxYear"`
|
||||
MinYear int `json:"minYear"`
|
||||
Compilation bool `json:"compilation"`
|
||||
SongCount int `json:"songCount"`
|
||||
Duration float64 `json:"duration"`
|
||||
Size int `json:"size"`
|
||||
Genre string `json:"genre"`
|
||||
Genres []struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
} `json:"genres"`
|
||||
FullText string `json:"fullText"`
|
||||
OrderAlbumName string `json:"orderAlbumName"`
|
||||
OrderAlbumArtistName string `json:"orderAlbumArtistName"`
|
||||
ImageFiles string `json:"imageFiles"`
|
||||
Paths string `json:"paths"`
|
||||
SmallImageURL string `json:"smallImageUrl"`
|
||||
MediumImageURL string `json:"mediumImageUrl"`
|
||||
LargeImageURL string `json:"largeImageUrl"`
|
||||
ExternalURL string `json:"externalUrl"`
|
||||
ExternalInfoUpdatedAt time.Time `json:"externalInfoUpdatedAt"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
}
|
Loading…
Reference in New Issue
Block a user