diff --git a/src/App.vue b/src/App.vue index 388e089..38f6702 100644 --- a/src/App.vue +++ b/src/App.vue @@ -28,6 +28,9 @@ +
+ +
@@ -35,12 +38,12 @@ import { ref } from "@vue/reactivity"; import Navigation from "./components/LeftSidebar/Navigation.vue"; -import PinnedStuff from "./components/LeftSidebar/PinnedStuff.vue"; - +import PinnedStuff from "./components/LeftSidebar/PinnedStuff.vue" import Search from "./components/Search.vue"; import NowPlaying from "./components/RightSideBar/NowPlaying.vue"; import UpNext from "./components/RightSideBar/UpNext.vue"; import RecommendedArtist from "./components/RightSideBar/Recommendation.vue"; +import BottomBar from "@/components/BottomBar/BottomBar.vue"; import perks from "@/composables/perks.js"; @@ -52,6 +55,7 @@ export default { NowPlaying, UpNext, RecommendedArtist, + BottomBar }, setup() { diff --git a/src/assets/css/BottomBar/BottomBar.scss b/src/assets/css/BottomBar/BottomBar.scss new file mode 100644 index 0000000..bb18f0d --- /dev/null +++ b/src/assets/css/BottomBar/BottomBar.scss @@ -0,0 +1,93 @@ +.b-bar { + height: 100%; + // padding: 0 $small 0 $small; + + .prog { + display: grid; + } + + .grid { + display: grid; + height: 100%; + // grid-auto-columns: 1fr; + // grid-auto-flow: column; + grid-template-columns: 1fr 3fr 1fr; + + @include phone-only { + grid-template-columns: 1fr 9.2rem; + } + + .info { + display: flex; + padding-top: $small; + margin-left: $small; + + .art { + width: 3rem; + height: 3rem; + border-radius: $smaller; + background-image: url("../../images/eggs.jpg"); + } + + .separator { + margin: 2px; + } + + .desc { + width: calc(100% - 5rem); + margin-left: $small; + display: flex; + align-items: center; + margin-top: -$small; + + .artists { + font-size: 0.8rem; + color: $highlight-blue; + } + } + } + + .controlsx { + // border: solid 1px; + width: 100%; + overflow: hidden; + display: flex; + align-items: center; + justify-content: flex-end; + + @include phone-only { + // width: min-content; + } + + .controls-bottom { + // border: solid 1px; + + width: min-content; + + .shuffle, .fav { + @include phone-only { + display: none !important; + } + } + } + + .progress-bottom { + width: 100%; + + .durationx { + background-color: #202020; + padding: $smaller; + border-radius: .4rem; + margin: 0 $small 0 $small; + } + // display: none; + } + } + + .volume-group { + @include tablet-portrait { + display: none; + } + } + } +} diff --git a/src/assets/css/_variables.scss b/src/assets/css/_variables.scss index 414fee7..6e549e6 100644 --- a/src/assets/css/_variables.scss +++ b/src/assets/css/_variables.scss @@ -2,10 +2,11 @@ $card-dark: #08090c; $red: #df4646; -$blue: rgb(5, 80, 150); -$green: rgb(67, 148, 67); +$blue: #055096; +$green: #439443; $separator: #ffffff46; -$pink: rgb(196, 58, 58); +$pink: #c43a3a; +$highlight-blue: #006eff; // sizes $small: 0.5em; $smaller: 0.25em; diff --git a/src/assets/css/global.scss b/src/assets/css/global.scss index 743195d..a633c0d 100644 --- a/src/assets/css/global.scss +++ b/src/assets/css/global.scss @@ -79,7 +79,11 @@ button { grid-template-columns: min-content 4fr min-content; grid-template-rows: 4rem 1fr 1fr; grid-auto-flow: row; - grid-template-areas: "l-sidebar content r-sidebar" "l-sidebar content r-sidebar" "l-sidebar content r-sidebar"; + grid-template-areas: + "l-sidebar content r-sidebar" + "l-sidebar content r-sidebar" + "l-sidebar content r-sidebar" + "bottom-bar bottom-bar bottom-bar"; width: 100vw; height: 100vh; background-repeat: no-repeat; @@ -97,6 +101,13 @@ button { background-color: $card-dark; } +.bottom-bar { + grid-area: bottom-bar; + height: 4rem; + // margin: 0 $small 0 $small; + // display: none; +} + .collapsed .l-sidebar { width: 70px; transition: all 0.3s ease; @@ -263,3 +274,147 @@ button { background-color: rgb(170, 50, 50); } } + +.progress { + display: flex; + align-items: center; + position: relative; + + .duration { + position: absolute; + right: 0; + top: -1rem; + font-size: small; + } + + input { + -webkit-appearance: none; + width: 100%; + border: none; + outline: none; + background: transparent; + } + + input:focus { + outline: none; + } + + + input::-webkit-slider-runnable-track { + width: 100%; + height: 0.25rem; + cursor: pointer; + background: #252829; + // background: linear-gradient(to right, #1488cc, #2b32b2); + } + + input::-webkit-slider-thumb { + -webkit-appearance: none; + height: 1rem; + width: 1rem; + border-radius: 50%; + background: #ffffff; + cursor: pointer; + margin-top: -0.35rem; + } + + input:focus::-webkit-slider-runnable-track, + input::-moz-range-track { + background: #367ebd; + } + + input::-moz-range-thumb { + height: 1rem; + width: 1rem; + border-radius: 50%; + background: #ffffff; + cursor: pointer; + margin-top: -0.35rem; + } +} + +.controls { + display: grid; + grid-template-columns: repeat(3, 1fr); + + .nav { + display: grid; + grid-template-columns: repeat(3, 1fr); + width: 100%; + + & * { + height: 3rem; + width: 3rem; + background-size: 50%; + cursor: pointer; + border-radius: 0.5rem; + } + + #previous { + background-image: url(../../assets/icons/previous.svg); + } + + .play-pause { + background-image: url(../../assets/icons/play.svg); + } + + .isPlaying { + background-image: url(../../assets/icons/pause.svg); + } + + #next { + background-image: url(../../assets/icons/next.svg); + } + } + + .shuffle { + width: 100%; + display: flex; + align-items: center; + + & * { + height: 2rem; + width: 2rem; + background-size: 70%; + cursor: pointer; + border-radius: 0.5rem; + } + + & :first-child { + background-image: url(../../assets/icons/repeat.svg); + } + + & :last-child { + background-image: url(../../assets/icons/shuffle.svg); + } + } + + .fav { + width: 100%; + display: flex; + align-items: center; + justify-content: flex-end; + + & * { + height: 2rem; + width: 2rem; + background-size: 70%; + border-radius: 0.5rem; + cursor: pointer; + } + + & :first-child { + background-image: url(../../assets/icons/plus.svg); + } + + & :last-child { + background-image: url(../../assets/icons/heart.svg); + } + } + + .fav *:hover, + .shuffle *:hover, + .nav *:hover { + background-color: rgb(5, 80, 150); + } +} diff --git a/src/components/BottomBar/BottomBar.vue b/src/components/BottomBar/BottomBar.vue new file mode 100644 index 0000000..0607ba4 --- /dev/null +++ b/src/components/BottomBar/BottomBar.vue @@ -0,0 +1,52 @@ + + + diff --git a/src/components/BottomBar/SongCard.vue b/src/components/BottomBar/SongCard.vue new file mode 100644 index 0000000..f6db392 --- /dev/null +++ b/src/components/BottomBar/SongCard.vue @@ -0,0 +1,33 @@ + + + diff --git a/src/components/FolderView/SongList.vue b/src/components/FolderView/SongList.vue index ef41da7..9c6e47a 100644 --- a/src/components/FolderView/SongList.vue +++ b/src/components/FolderView/SongList.vue @@ -99,7 +99,7 @@ function loadAlbum(title, album_artist) { } .current * { - color: rgb(0, 110, 255); + color: $highlight-blue; } .current:hover { diff --git a/src/components/RightSideBar/NowPlaying.vue b/src/components/RightSideBar/NowPlaying.vue index ac846b8..3450bc1 100644 --- a/src/components/RightSideBar/NowPlaying.vue +++ b/src/components/RightSideBar/NowPlaying.vue @@ -101,153 +101,7 @@ export default { display: grid; grid-template-rows: 3fr 1fr; - .progress { - display: flex; - align-items: center; - height: 1.5rem; - position: relative; - - .duration { - position: absolute; - right: 0; - top: -1rem; - font-size: small; - } - - input { - -webkit-appearance: none; - width: 100%; - border: none; - outline: none; - background: transparent; - } - - input:focus { - outline: none; - } - - input::-webkit-slider-runnable-track { - width: 100%; - height: 0.25rem; - cursor: pointer; - background: #1488cc; - background: linear-gradient( - to right, - #1488cc, - #2b32b2 - ); - } - - input::-webkit-slider-thumb { - -webkit-appearance: none; - height: 1rem; - width: 1rem; - border-radius: 50%; - background: #ffffff; - cursor: pointer; - margin-top: -0.35rem; - } - - input:focus::-webkit-slider-runnable-track, - input::-moz-range-track { - background: #367ebd; - } - - input::-moz-range-thumb { - height: 1rem; - width: 1rem; - border-radius: 50%; - background: #ffffff; - cursor: pointer; - margin-top: -0.35rem; - } - } - - .controls { - display: grid; - grid-template-columns: repeat(3, 1fr); - - .nav { - display: grid; - grid-template-columns: repeat(3, 1fr); - width: 100%; - - & * { - height: 3rem; - width: 3rem; - background-size: 50%; - cursor: pointer; - border-radius: 0.5rem; - } - - #previous { - background-image: url(../../assets/icons/previous.svg); - } - - .play-pause { - background-image: url(../../assets/icons/play.svg); - } - - .isPlaying { - background-image: url(../../assets/icons/pause.svg); - } - - #next { - background-image: url(../../assets/icons/next.svg); - } - } - - .shuffle { - width: 100%; - display: flex; - align-items: center; - - & * { - height: 2rem; - width: 2rem; - background-size: 70%; - cursor: pointer; - border-radius: 0.5rem; - } - - & :first-child { - background-image: url(../../assets/icons/repeat.svg); - } - - & :last-child { - background-image: url(../../assets/icons/shuffle.svg); - } - } - - .fav { - width: 100%; - display: flex; - align-items: center; - justify-content: flex-end; - - & * { - height: 2rem; - width: 2rem; - background-size: 70%; - border-radius: 0.5rem; - cursor: pointer; - } - - & :first-child { - background-image: url(../../assets/icons/plus.svg); - } - - & :last-child { - background-image: url(../../assets/icons/heart.svg); - } - } - - .fav *:hover, - .shuffle *:hover, - .nav *:hover { - background-color: rgb(5, 80, 150); - } - } + .art-tags { display: flex; diff --git a/src/components/RightSideBar/Recommendation.vue b/src/components/RightSideBar/Recommendation.vue index a93a1e1..5fa39cb 100644 --- a/src/components/RightSideBar/Recommendation.vue +++ b/src/components/RightSideBar/Recommendation.vue @@ -22,10 +22,6 @@ export default { title: "Mockingbird", artist: "Eminem", }, - { - title: "Slim shady", - artist: "Eminem", - }, ]; const r_albums = ["Crybaby", "Everybody's Everything", "Castles II"]; diff --git a/src/composables/playAudio.js b/src/composables/playAudio.js index fa493b1..b6cac3e 100644 --- a/src/composables/playAudio.js +++ b/src/composables/playAudio.js @@ -15,7 +15,7 @@ const playAudio = (path) => { new Promise((resolve, reject) => { audio.src = full_path; - audio.onloadeddata = resolve; + audio.oncanplaythrough = resolve; audio.onerror = reject; }) .then(() => { @@ -26,6 +26,7 @@ const playAudio = (path) => { audio.ontimeupdate = () => { pos.value = (audio.currentTime / audio.duration) * 1000; + }; }) .catch((err) => console.log(err)); @@ -71,3 +72,7 @@ audio.addEventListener("ended", () => { }); export default { playAudio, playNext, playPrev, playPause, seek, pos, playing }; + + +// TODO +// Try implementing classes to play audio .ie. Make the seek, playNext, playPrev, etc the methods of a class. etc