From 51c56abe168d40d242138da6717322a0c60036bd Mon Sep 17 00:00:00 2001 From: Shiny Nematoda Date: Thu, 21 Apr 2022 18:38:21 +0530 Subject: [PATCH] Playlists, Play Next, Code Refactor --- README.md | 15 ++-- index.html | 2 + public/manifest.json | 9 +++ src/App.vue | 127 +++++++++++++++++++-------------- src/assets/base.css | 63 ++++++++++------ src/components/AlbumItem.vue | 20 +++--- src/components/Modal.vue | 104 +++++++++++++++++++++++++++ src/components/NavBar.vue | 39 ++++++++-- src/components/NewPlaylist.vue | 90 +++++++++++++++++++++++ src/components/Playlists.vue | 30 ++++---- src/components/Search.vue | 58 +++------------ src/components/SearchBar.vue | 33 +++++---- src/components/SongItem.vue | 39 +++++++--- src/components/StatusBar.vue | 92 ++++++++++++++++++------ src/scripts/colors.js | 16 +++++ src/scripts/db.js | 98 +++++++++++++++++++++++++ src/scripts/util.js | 33 +++++++++ 17 files changed, 664 insertions(+), 204 deletions(-) create mode 100644 public/manifest.json create mode 100644 src/components/Modal.vue create mode 100644 src/components/NewPlaylist.vue create mode 100644 src/scripts/colors.js create mode 100644 src/scripts/db.js create mode 100644 src/scripts/util.js diff --git a/README.md b/README.md index aa1723d..8d7f106 100644 --- a/README.md +++ b/README.md @@ -2,13 +2,15 @@ ![On Codeberg](https://codeberg.org/Hyperpipe/static/raw/branch/master/on-codeberg.svg) -A Privacy Respecting Frontend for YouTube Music inspired and built with [Piped][piped] ( and a tiny bit of messy custom scrapers ). +A Privacy Respecting Frontend for YouTube Music inspired and built with the help [Piped][piped] and YouTube's innertube API. ![YouTube Music](https://img.shields.io/badge/youtube-music-red?style=for-the-badge&logo=youtube) ![Website](https://img.shields.io/website?down_color=red&down_message=offline&label=status&style=for-the-badge&up_color=cornflowerblue&up_message=online&url=https%3A%2F%2Fhyperpipe.surge.sh) ## Usage +***HYPERPIPE IS ONLY BEING DEVELOPED, EXPECT BUGS AND MESSY CODE*** + ```sh npm install ``` @@ -35,15 +37,15 @@ npm run build ## Instances -| Instance | Country | Country (Backend) | Offical | -| ---------------------------- | ------- | ----------------- | ------- | -| [hyperpipe.surge.sh][hypipe] | πŸ‡ΊπŸ‡Έ | πŸ‡©πŸ‡ͺ | βœ… | +| Instance | Country (Backend) | +| :--------------------------: | :---------------: | +| [hyperpipe.surge.sh][hypipe] | πŸ‡©πŸ‡ͺ | ## LICENSE ### GPL v3 Only -Please refer to LICENSE. +Please refer to [LICENSE][LICENSE]. You can reach out to me on @@ -58,9 +60,10 @@ You can reach out to me on [hypipe]: https://hyperpipe.surge.sh [piped]: https://piped.kavin.rocks +[LICENSE]: https://codeberg.org/Hyperpipe/Hyperpipe/src/branch/main/LICENSE.txt [vue]: https://github.com/vuejs/core/blob/main/LICENSE [vite]: https://github.com/vitejs/vite/blob/main/LICENSE [bi]: https://github.com/twbs/icons/blob/main/LICENSE.md [hls]: https://github.com/video-dev/hls.js/blob/master/LICENSE [nord]: https://github.com/arcticicestudio/nord/blob/develop/LICENSE.md -[vuetheme]: https://github.com/vuejs/theme/blob/main/LICENSE +[vuetheme]: https://github.com/vuejs/theme/blob/main/LICENSE \ No newline at end of file diff --git a/index.html b/index.html index 9b4ec75..e1297a9 100644 --- a/index.html +++ b/index.html @@ -7,6 +7,8 @@ + + Hyperpipe diff --git a/public/manifest.json b/public/manifest.json new file mode 100644 index 0000000..8e268e3 --- /dev/null +++ b/public/manifest.json @@ -0,0 +1,9 @@ +{ + "name": "Hyperpipe", + "short_name": "Hyperpipe", + "start_url": "/", + "display": "standalone", + "background_color": "#fff", + "description": "Privacy respecting YouTube Music Frontend.", + +} \ No newline at end of file diff --git a/src/App.vue b/src/App.vue index bb0ed9f..97ae643 100644 --- a/src/App.vue +++ b/src/App.vue @@ -5,10 +5,13 @@ import NavBar from './components/NavBar.vue'; import StatusBar from './components/StatusBar.vue'; import NowPlaying from './components/NowPlaying.vue'; import Search from './components/Search.vue'; +import NewPlaylist from './components/NewPlaylist.vue'; import Playlists from './components/Playlists.vue'; import Artist from './components/Artist.vue'; import { getJson, getJsonPiped } from './scripts/fetch.js'; +import { useLazyLoad } from './scripts/util.js'; +import { useUpdatePlaylist } from './scripts/db.js' const data = reactive({ artUrl: '', @@ -36,7 +39,7 @@ const artist = reactive({ thumbnails: [], }); -const search = ref(''); +const search = ref(''), page = ref('home'); const audio = ref(null); @@ -47,6 +50,9 @@ function parseUrl() { switch (loc[3].replace(location.search, '')) { case '': + search.value = '' + page.value = 'home' + break; case 'search': search.value = loc[4]; console.log(search.value); @@ -69,17 +75,7 @@ function parseUrl() { function Toggle(e) { console.log(e, data[e]); - - if (data[e]) { - data[e] = false; - } else { - data[e] = true; - } -} - -function Update(e) { - search.value = e; - console.log('update'); + data[e] = !data[e] } function timeUpdate(t) { @@ -126,7 +122,7 @@ function playNext(u) { audio.value.src = ''; const i = data.urls.map((s) => s.url).indexOf(data.url), - next = data.urls[i + 1]; + next = data.urls[i + 1]; console.log('Index: ' + i); console.log(data.url, data.urls, next); @@ -134,6 +130,7 @@ function playNext(u) { if (data.urls.length > i && data.urls.length != 0 && next) { getSong(next.url); } else if (data.loop) { + console.log(data.url, data.urls[0]); data.url = data.urls[0].url; getSong(data.urls[0].url); } else { @@ -203,7 +200,7 @@ async function getArtist(e) { } async function getNext(hash) { - if (!data.urls || data.urls.map((s) => s.url).indexOf(data.url) <= 0) { + if (!data.urls || data.urls.map((s) => s.url).indexOf(data.url) < 0 || data.urls.length == 1) { const json = await getJson( 'https://hyperpipeapi.onrender.com/next/' + hash, ); @@ -257,7 +254,7 @@ function Stream(res) { } function audioCanPlay() { - lazyLoad(); + useLazyLoad(); audio.value.play(); data.state = 'pause'; @@ -268,12 +265,24 @@ function audioCanPlay() { document.title = `Playing: ${data.nowtitle} by ${data.nowartist}`; } +function SaveTrack(e) { + useUpdatePlaylist(e, { + url: data.url, + title: data.nowtitle + }, (e) => { + if (e === true) { + console.log('Added Song To '+ e) + } + }) +} + function setMetadata() { if ('mediaSession' in navigator) { const i = data.urls.map((u) => u.url).indexOf(data.url); let artwork = [], - album = undefined; + album = undefined; + console.log(i); if (i >= 0) { @@ -303,43 +312,19 @@ function setMetadata() { } } -function lazyLoad() { - let lazyElems; - - if ('IntersectionObserver' in window) { - lazyElems = document.querySelectorAll('.bg-img:not(.lazy)'); - - let imgObs = new IntersectionObserver((elems, obs) => { - elems.forEach((elem) => { - setTimeout(() => { - if (elem.isIntersecting) { - let ele = elem.target; - - ele.classList.add('lazy'); - imgObs.unobserve(ele); - } - }, 20); - }); - }); - - lazyElems.forEach((img) => { - imgObs.observe(img); - }); - } else { - console.log('Failed'); - } -} - onMounted(() => { - lazyLoad(); + useLazyLoad(); - document.addEventListener('scroll', lazyLoad); - document.addEventListener('resize', lazyLoad); - document.addEventListener('orientationChange', lazyLoad); + document.addEventListener('scroll', useLazyLoad); + document.addEventListener('resize', useLazyLoad); + document.addEventListener('orientationChange', useLazyLoad); window.addEventListener('popstate', parseUrl); + window.onbeforeunload = () => { - return 'Are you Sure?'; + if (data.url) { + return 'Are you Sure?'; + } }; if ('mediaSession' in navigator) { @@ -359,6 +344,33 @@ onMounted(() => { }); } + if ('indexedDB' in window) { + const req = indexedDB.open('hyperpipedb', 1) + + req.onupgradeneeded = e => { + const db = e.target.result; + console.log(db) + + if (!db.objectStoreNames.contains("playlist")) { + + const store = db.createObjectStore("playlist", { keyPath: 'name' }) + + store.createIndex('urls', 'urls', { unique: false }) + + } + } + + req.onerror = e => { + console.log("Please let me use indexedDB!!") + console.log(e) + } + + req.onsuccess = e => { + window.db = e.target.result + } + + } + parseUrl(); console.log('Mounted !'); @@ -372,6 +384,7 @@ onMounted(() => { search = e; } " + @update-page="(e) => { page = e }" :search="search" /> + + { @vol="setVolume" @list="Toggle" @loop="Toggle" + @save="SaveTrack" @change-time="setTime" :state="data.state" :time="data.time" @@ -492,10 +513,6 @@ a, } @media (min-width: 1024px) { - main .grid { - display: grid; - grid-template-columns: 1fr 1fr; - } header { margin: auto; display: flex; diff --git a/src/assets/base.css b/src/assets/base.css index 8c6beee..987feb4 100644 --- a/src/assets/base.css +++ b/src/assets/base.css @@ -141,6 +141,17 @@ button { text-transform: capitalize; } +.textbox { + padding: .5rem 1rem; + color: var(--color-text); + background: var(--color-background-mute); + border-radius: .25rem; + font-size: 1rem; + border: none; + appearence: none; + outline: none; +} + .bg-img { background-image: linear-gradient(45deg, #88c0d0, #5e81ac); background-position: center; @@ -175,25 +186,38 @@ button { } .popup-wrap { - --display: none; position: relative; } -.popup-wrap:hover, -.popup-wrap:focus, -.popup:focus, -.popup:active { - --display: flex; -} + .popup { position: absolute; - display: var(--display); + display: flex; background-color: var(--color-background); padding: 0.5rem; border-radius: 0.125rem; z-index: 999; bottom: 1.25rem; box-shadow: 0 0 0.5rem var(--color-border); - animation: fade 0.4s ease; +} + +.grid-3 { + display: grid; + grid-template-columns: 1fr; +} +@media (min-width: 530px) { + .grid-3 { + display: grid; + grid-template-columns: 1fr 1fr; + } +} +@media (min-width: 1024px) { + .grid { + display: grid; + grid-template-columns: 1fr 1fr; + } + .grid-3 { + grid-template-columns: 1fr 1fr 1fr; + } } .bars-wrap { @@ -222,22 +246,15 @@ button { } /* Animations */ -@keyframes fade { - from { - opacity: 0; - } - to { - opacity: 1; - } +.fade-enter-active, +.fade-leave-active { + transition: opacity 0.5s ease; } -@keyframes fill { - from { - width: 0; - } - to { - width: var(--width); - } +.fade-enter-from, +.fade-leave-to { + opacity: 0; } + @keyframes heightc { 50% { height: 100%; diff --git a/src/components/AlbumItem.vue b/src/components/AlbumItem.vue index 6280d2d..811c74a 100644 --- a/src/components/AlbumItem.vue +++ b/src/components/AlbumItem.vue @@ -1,23 +1,23 @@