major redesign and refactor

+ centralized urls
+ reduce max app width
+ bump up header height to 23rem
This commit is contained in:
geoffrey45
2022-09-15 12:36:30 +03:00
parent 69b8b17e84
commit 94eb198e47
17 changed files with 179 additions and 82 deletions
+2 -2
View File
@@ -3,7 +3,7 @@
<Modal /> <Modal />
<Notification /> <Notification />
<div id="tooltip"></div> <div id="tooltip"></div>
<div <section
id="app-grid" id="app-grid"
:class="{ :class="{
showAltNP: settings.use_sidebar && settings.use_alt_np, showAltNP: settings.use_sidebar && settings.use_alt_np,
@@ -19,7 +19,7 @@
<NowPlayingRight /> <NowPlayingRight />
<SearchInput v-if="settings.use_sidebar && xl" /> <SearchInput v-if="settings.use_sidebar && xl" />
<RightSideBar v-if="settings.use_sidebar && xl" /> <RightSideBar v-if="settings.use_sidebar && xl" />
</div> </section>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
+7 -4
View File
@@ -7,11 +7,14 @@
"l-sidebar content r-sidebar" "l-sidebar content r-sidebar"
"l-sidebar content r-sidebar" "l-sidebar content r-sidebar"
"l-sidebar content bottombar"; "l-sidebar content bottombar";
max-width: 2720px; max-width: 1720px;
height: calc(100vh - 1rem); height: calc(100vh);
margin: 0 auto; margin: 0 auto;
gap: 1rem; gap: 1rem;
margin: $small auto; padding: $small;
padding-right: $medium;
border-right: solid 1px $gray4;
margin-top: -$small;
} }
#app-grid.isSmall { #app-grid.isSmall {
@@ -89,7 +92,7 @@
grid-area: l-sidebar; grid-area: l-sidebar;
display: grid; display: grid;
grid-template-rows: 1fr max-content; grid-template-rows: 1fr max-content;
background-color: $gray; background-color: rgb(22, 22, 22);
height: 100vh; height: 100vh;
margin-top: -$small; margin-top: -$small;
margin-left: -$small; margin-left: -$small;
+31 -24
View File
@@ -10,23 +10,14 @@
: '', : '',
}" }"
> >
<div class="big-img noscroll" :class="{ imgSmall: widthIsSmall }">
<img :src="imguri.thumb + album.image" class="rounded" />
</div>
<div <div
class="info" class="info"
:class="{ nocontrast: album.colors ? isLight(album.colors[0]) : false }" :class="{ nocontrast: album.colors ? isLight(album.colors[0]) : false }"
> >
<div class="art"> <div class="album-info">
<img
:src="
widthIsSmall
? imguri.thumb + album.image
: imguri.artist + album.artistimg
"
class="shadow-lg"
loading="lazy"
:class="`${widthIsSmall ? 'rounded' : 'circular'}`"
/>
</div>
<div>
<div class="top"> <div class="top">
<div class="h"> <div class="h">
<span v-if="album.is_soundtrack">Soundtrack</span> <span v-if="album.is_soundtrack">Soundtrack</span>
@@ -53,9 +44,13 @@
/> />
</div> </div>
</div> </div>
<div class="art" v-if="!widthIsSmall">
<img
:src="imguri.artist + album.artistimg"
class="shadow-lg circular"
loading="lazy"
/>
</div> </div>
<div class="big-img noscroll" v-if="!widthIsSmall">
<img :src="imguri.thumb + album.image" class="rounded" />
</div> </div>
</div> </div>
</template> </template>
@@ -106,7 +101,7 @@ useVisibility(albumheaderthing, handleVisibilityState);
<style lang="scss"> <style lang="scss">
.a-header { .a-header {
display: grid; display: grid;
grid-template-columns: 1fr max-content; grid-template-columns: max-content 1fr;
gap: 1rem; gap: 1rem;
padding: 1rem; padding: 1rem;
height: 100% !important; height: 100% !important;
@@ -116,23 +111,38 @@ useVisibility(albumheaderthing, handleVisibilityState);
.big-img { .big-img {
height: calc(100%); height: calc(100%);
width: 16rem; width: 16rem;
margin: auto 0; display: flex;
align-items: flex-end;
img { img {
height: 100%; height: 16rem;
aspect-ratio: 1; aspect-ratio: 1;
} }
} }
.big-img.imgSmall {
width: 12rem;
img {
height: 12rem;
}
}
.nocontrast { .nocontrast {
color: $black; color: $black;
} }
.info { .info {
width: 100%; width: 100%;
display: grid;
grid-template-columns: 1fr max-content;
height: 100%;
align-items: flex-end;
.art {
display: flex; display: flex;
flex-direction: column; align-items: flex-end;
justify-content: space-between; }
img { img {
height: 6rem; height: 6rem;
@@ -146,6 +156,7 @@ useVisibility(albumheaderthing, handleVisibilityState);
font-size: 14px; font-size: 14px;
opacity: 0.5; opacity: 0.5;
} }
.title { .title {
font-size: 2.5rem; font-size: 2.5rem;
font-weight: 600; font-weight: 600;
@@ -158,10 +169,6 @@ useVisibility(albumheaderthing, handleVisibilityState);
} }
} }
.separator {
width: 20rem;
}
.bottom { .bottom {
margin-top: $smaller; margin-top: $smaller;
+3 -3
View File
@@ -1,6 +1,6 @@
<template> <template>
<div <div
class="table border rounded" class="table"
v-if="tracks.length" v-if="tracks.length"
ref="tracklistElem" ref="tracklistElem"
:class="{ :class="{
@@ -181,7 +181,7 @@ function getTrackList() {
.table.isSmall { .table.isSmall {
.songlist-item { .songlist-item {
grid-template-columns: 1.5rem 1.5fr 2rem 2.5rem; grid-template-columns: 1.5rem 2fr 2rem 2.5rem;
} }
.song-artists, .song-artists,
@@ -199,7 +199,7 @@ function getTrackList() {
.table.isMedium { .table.isMedium {
.songlist-item { .songlist-item {
grid-template-columns: 1.5rem 1.5fr 1fr 2rem 2.5rem; grid-template-columns: 1.5rem 2fr 1fr 2rem 2.5rem;
} }
.song-album { .song-album {
+1 -1
View File
@@ -2,7 +2,7 @@
<input <input
type="search" type="search"
class="header-input rounded-sm pad-sm" class="header-input rounded-sm pad-sm"
placeholder="search here" placeholder="Search here"
v-model.trim="source" v-model.trim="source"
id="page-search" id="page-search"
/> />
+1 -1
View File
@@ -103,7 +103,7 @@ function showMenu(e: Event) {
<style lang="scss"> <style lang="scss">
.songlist-item { .songlist-item {
display: grid; display: grid;
grid-template-columns: 1.5rem 1.5fr 1fr 1.5fr 2rem 2.5rem; grid-template-columns: 1.5rem 2fr 1fr 1.5fr 2rem 2.5rem;
align-items: center; align-items: center;
justify-content: flex-start; justify-content: flex-start;
height: 3.75rem; height: 3.75rem;
+10 -5
View File
@@ -1,18 +1,23 @@
import { paths } from "@/config";
import state from "../state"; import state from "../state";
import { AlbumInfo, Track } from "../../interfaces"; import { AlbumInfo, Track } from "../../interfaces";
import useAxios from "./useAxios"; import useAxios from "./useAxios";
import { NotifType, useNotifStore } from "@/stores/notification"; import { NotifType, useNotifStore } from "@/stores/notification";
const getAlbumData = async (hash: string, ToastStore: typeof useNotifStore) => { const {
const url = state.settings.uri + "/album"; album: albumUrl,
albumartists: albumArtistsUrl,
albumbio: albumBioUrl
} = paths.api
const getAlbumData = async (hash: string, ToastStore: typeof useNotifStore) => {
interface AlbumData { interface AlbumData {
info: AlbumInfo; info: AlbumInfo;
tracks: Track[]; tracks: Track[];
} }
const { data, status } = await useAxios({ const { data, status } = await useAxios({
url, url: albumUrl,
props: { props: {
hash: hash, hash: hash,
}, },
@@ -31,7 +36,7 @@ const getAlbumData = async (hash: string, ToastStore: typeof useNotifStore) => {
const getAlbumArtists = async (hash: string) => { const getAlbumArtists = async (hash: string) => {
const { data, error } = await useAxios({ const { data, error } = await useAxios({
url: state.settings.uri + "/album/artists", url: albumArtistsUrl,
props: { props: {
hash: hash, hash: hash,
}, },
@@ -46,7 +51,7 @@ const getAlbumArtists = async (hash: string) => {
const getAlbumBio = async (hash: string) => { const getAlbumBio = async (hash: string) => {
const { data, status } = await useAxios({ const { data, status } = await useAxios({
url: state.settings.uri + "/album/bio", url: albumBioUrl,
props: { props: {
hash: hash, hash: hash,
}, },
+2 -2
View File
@@ -1,5 +1,5 @@
import { paths } from "@/config";
import { Folder, Track } from "@/interfaces"; import { Folder, Track } from "@/interfaces";
import state from "../state";
import useAxios from "./useAxios"; import useAxios from "./useAxios";
export default async function (path: string) { export default async function (path: string) {
@@ -9,7 +9,7 @@ export default async function (path: string) {
} }
const { data, error } = await useAxios({ const { data, error } = await useAxios({
url: `${state.settings.uri}/folder`, url: paths.api.folder,
props: { props: {
folder: path, folder: path,
}, },
+15 -8
View File
@@ -1,15 +1,24 @@
import { paths } from "@/config";
import { Artist } from "../../interfaces"; import { Artist } from "../../interfaces";
import { Playlist, Track } from "../../interfaces"; import { Playlist, Track } from "../../interfaces";
import { Notification, NotifType } from "../../stores/notification"; import { Notification, NotifType } from "../../stores/notification";
import state from "../state"; import state from "../state";
import useAxios from "./useAxios"; import useAxios from "./useAxios";
const {
new: newPlaylistUrl,
all: allPlaylistsUrl,
base: basePlaylistUrl,
artists: playlistArtistsUrl
} = paths.api.playlist;
/** /**
* Creates a new playlist on the server. * Creates a new playlist on the server.
* @param playlist_name The name of the playlist to create. * @param playlist_name The name of the playlist to create.
*/ */
async function createNewPlaylist(playlist_name: string, track?: Track) { async function createNewPlaylist(playlist_name: string, track?: Track) {
const { data, status } = await useAxios({ const { data, status } = await useAxios({
url: state.settings.uri + "/playlist/new", url: newPlaylistUrl,
props: { props: {
name: playlist_name, name: playlist_name,
}, },
@@ -44,7 +53,7 @@ async function createNewPlaylist(playlist_name: string, track?: Track) {
*/ */
async function getAllPlaylists(): Promise<Playlist[]> { async function getAllPlaylists(): Promise<Playlist[]> {
const { data, error } = await useAxios({ const { data, error } = await useAxios({
url: state.settings.uri + "/playlists", url: allPlaylistsUrl,
get: true, get: true,
}); });
@@ -58,7 +67,7 @@ async function getAllPlaylists(): Promise<Playlist[]> {
} }
async function addTrackToPlaylist(playlist: Playlist, track: Track) { async function addTrackToPlaylist(playlist: Playlist, track: Track) {
const uri = `${state.settings.uri}/playlist/${playlist.playlistid}/add`; const uri = `${basePlaylistUrl}/${playlist.playlistid}/add`;
const { status } = await useAxios({ const { status } = await useAxios({
url: uri, url: uri,
@@ -76,7 +85,7 @@ async function addTrackToPlaylist(playlist: Playlist, track: Track) {
} }
async function getPlaylist(pid: string) { async function getPlaylist(pid: string) {
const uri = state.settings.uri + "/playlist/" + pid; const uri = `${basePlaylistUrl}/${pid}`;
interface PlaylistData { interface PlaylistData {
info: Playlist; info: Playlist;
@@ -100,7 +109,7 @@ async function getPlaylist(pid: string) {
} }
async function updatePlaylist(pid: string, playlist: FormData, pStore: any) { async function updatePlaylist(pid: string, playlist: FormData, pStore: any) {
const uri = state.settings.uri + "/playlist/" + pid + "/update"; const uri = `${basePlaylistUrl}/${pid}/update`;
const { data, error } = await useAxios({ const { data, error } = await useAxios({
url: uri, url: uri,
@@ -127,10 +136,8 @@ async function updatePlaylist(pid: string, playlist: FormData, pStore: any) {
* @returns {Promise<Artist[]>} A promise that resolves to an array of artists. * @returns {Promise<Artist[]>} A promise that resolves to an array of artists.
*/ */
export async function getPlaylistArtists(pid: string): Promise<Artist[]> { export async function getPlaylistArtists(pid: string): Promise<Artist[]> {
const uri = state.settings.uri + "/playlist/artists";
const { data, error } = await useAxios({ const { data, error } = await useAxios({
url: uri, url: playlistArtistsUrl,
props: { props: {
pid: pid, pid: pid,
}, },
+13 -15
View File
@@ -1,14 +1,14 @@
import { paths } from "@/config";
import state from "../state"; import state from "../state";
import axios from "axios"; import axios from "axios";
import useAxios from "./useAxios"; import useAxios from "./useAxios";
const base_url = `${state.settings.uri}/search`; const {
tracks: searchTracksUrl,
const uris = { albums: searchAlbumsUrl,
tracks: `${base_url}/tracks?q=`, artists: searchArtistsUrl,
albums: `${base_url}/albums?q=`, load: loadMoreUrl,
artists: `${base_url}/artists?q=`, } = paths.api.search;
};
/** /**
* Fetch data from url * Fetch data from url
@@ -25,24 +25,22 @@ async function fetchData(url: string) {
} }
async function searchTracks(query: string) { async function searchTracks(query: string) {
const url = uris.tracks + encodeURIComponent(query.trim()); const url = searchTracksUrl + encodeURIComponent(query.trim());
return await fetchData(url); return await fetchData(url);
} }
async function searchAlbums(query: string) { async function searchAlbums(query: string) {
const url = uris.albums + encodeURIComponent(query.trim()); const url = searchAlbumsUrl + encodeURIComponent(query.trim());
return await fetchData(url); return await fetchData(url);
} }
async function searchArtists(query: string) { async function searchArtists(query: string) {
const url = uris.artists + encodeURIComponent(query.trim()); const url = searchArtistsUrl + encodeURIComponent(query.trim());
return await fetchData(url); return await fetchData(url);
} }
const loadmore_url = state.settings.uri + "/search/loadmore";
async function loadMoreTracks(index: number) { async function loadMoreTracks(index: number) {
const response = await axios.get(loadmore_url, { const response = await axios.get(loadMoreUrl, {
params: { params: {
type: "tracks", type: "tracks",
index: index, index: index,
@@ -53,7 +51,7 @@ async function loadMoreTracks(index: number) {
} }
async function loadMoreAlbums(index: number) { async function loadMoreAlbums(index: number) {
const response = await axios.get(loadmore_url, { const response = await axios.get(loadMoreUrl, {
params: { params: {
type: "albums", type: "albums",
index: index, index: index,
@@ -64,7 +62,7 @@ async function loadMoreAlbums(index: number) {
} }
async function loadMoreArtists(index: number) { async function loadMoreArtists(index: number) {
const response = await axios.get(loadmore_url, { const response = await axios.get(loadMoreUrl, {
params: { params: {
type: "artists", type: "artists",
index: index, index: index,
+4
View File
@@ -1,6 +1,10 @@
import { FetchProps } from "../../interfaces"; import { FetchProps } from "../../interfaces";
import axios, { AxiosError, AxiosResponse } from "axios"; import axios, { AxiosError, AxiosResponse } from "axios";
import useLoaderStore from "@/stores/loader"; import useLoaderStore from "@/stores/loader";
import { paths } from "@/config";
const url = paths.api
export default async (args: FetchProps) => { export default async (args: FetchProps) => {
let data: any = null; let data: any = null;
+3 -4
View File
@@ -1,10 +1,9 @@
import { ref } from "@vue/reactivity"; import { ref } from "@vue/reactivity";
import { reactive } from "vue";
const loading = ref(false); const loading = ref(false);
const settings = reactive({ const settings = {
uri: "http://127.0.0.1:1970", uri: "http://10.5.8.81:1970",
}); };
export default { export default {
loading, loading,
+79 -7
View File
@@ -1,13 +1,85 @@
const baseImgUrl = "http://0.0.0.0:1971" export interface D<T = string> {
[key: string]: T;
}
const domains: D = {
local: "http://localhost:",
remote: "http://10.5.86.154:",
};
const ports = {
api: 1970,
images: 1971,
};
const imageRoutes = {
thumb: "/t/",
artist: "/a/",
playlist: "/p/",
raw: "/raw/",
};
let mode: string = "remote";
function toggleMode() {
mode = mode === "local" ? "remote" : "local";
}
function getDomain() {
return domains[mode];
}
const baseImgUrl = getDomain() + ports.images;
const baseApiUrl = getDomain() + ports.api;
const paths = { const paths = {
api: "", api: {
album: baseApiUrl + "/album",
get albumartists() {
return this.album + "/artists";
},
get albumbio() {
return this.album + "/bio";
},
folder: baseApiUrl + "/folder",
playlist: {
base: baseApiUrl + "/playlist",
get new() {
return this.base + "/new";
},
get all() {
return this.base + "s";
},
get artists() {
return this.base + "/artists";
},
},
search: {
base: baseApiUrl + "/search",
get tracks() {
return this.base + "/tracks?q=";
},
get albums() {
return this.base + "/albums?q=";
},
get artists() {
return this.base + "/artists?q=";
},
get load() {
return this.base + "/loadmore";
},
},
files: baseApiUrl + "/file",
},
images: { images: {
thumb: `${baseImgUrl}/t/`, thumb: baseImgUrl + imageRoutes.thumb,
artist: `${baseImgUrl}/a/`, artist: baseImgUrl + imageRoutes.artist,
playlist: `${baseImgUrl}/p/`, playlist: baseImgUrl + imageRoutes.playlist,
raw: `${baseImgUrl}/raw/` raw: baseImgUrl + imageRoutes.raw,
}, },
}; };
export { paths }; export { paths, toggleMode };
// TODO: Add setting to toggle between extending to edges or not
+1 -1
View File
@@ -27,7 +27,7 @@ useVisibility(apheader, handleVisibilityState);
<style lang="scss"> <style lang="scss">
#ap-page { #ap-page {
display: grid; display: grid;
grid-template-rows: 18rem 1fr; grid-template-rows: 23rem 1fr;
gap: 1rem; gap: 1rem;
} }
</style> </style>
+2 -1
View File
@@ -1,3 +1,4 @@
import { paths } from "@/config";
import { defineStore } from "pinia"; import { defineStore } from "pinia";
import state from "../composables/state"; import state from "../composables/state";
import { NotifType, useNotifStore } from "./notification"; import { NotifType, useNotifStore } from "./notification";
@@ -44,7 +45,7 @@ export default defineStore("Queue", {
this.currentindex = index; this.currentindex = index;
const track = this.tracklist[index]; const track = this.tracklist[index];
this.currentid = track.trackid; this.currentid = track.trackid;
const uri = state.settings.uri + "/file/" + track.hash; const uri = `${paths.api.files}/${track.hash}`;
new Promise((resolve, reject) => { new Promise((resolve, reject) => {
audio.autoplay = true; audio.autoplay = true;
+1 -2
View File
@@ -49,5 +49,4 @@ export default function createSubPaths(
} }
} }
// function that takes 2 strings as parameters and returns a string // TODO: Fix the includes issue.
// that is the concatenation of the two strings
+2
View File
@@ -15,6 +15,8 @@ import PlaylistCard from "@/components/PlaylistsList/PlaylistCard.vue";
import usePStore from "@/stores/pages/playlists"; import usePStore from "@/stores/pages/playlists";
const pStore = usePStore(); const pStore = usePStore();
// TODO: When you add a song to playlist when you are in this page, increase the count on the card.
</script> </script>
<style lang="scss"> <style lang="scss">