mirror of
https://codeberg.org/Hyperpipe/Hyperpipe
synced 2025-06-27 20:58:01 +02:00
Changes:
- Scroll To Top for Albums and Artists ( closes #123 ) - Opt-in for Prefers Reduced Motion ( closes #124 ) - Thumbnails for local playlists - Better SW caching
This commit is contained in:
parent
e905bb0d9a
commit
1e59c18acd
11 changed files with 83 additions and 24 deletions
|
@ -107,6 +107,9 @@ onBeforeMount(() => {
|
||||||
if (store.theme) document.body.setAttribute('data-theme', store.theme);
|
if (store.theme) document.body.setAttribute('data-theme', store.theme);
|
||||||
if (store.compact == 'true') document.body.setAttribute('data-compact', '');
|
if (store.compact == 'true') document.body.setAttribute('data-compact', '');
|
||||||
|
|
||||||
|
/* Prefers Reduced Motion */
|
||||||
|
if (store.prm == 'true') document.body.classList.add('prm');
|
||||||
|
|
||||||
/* Set the default locale if set */
|
/* Set the default locale if set */
|
||||||
if (store.locale) setupLocale(store.locale);
|
if (store.locale) setupLocale(store.locale);
|
||||||
|
|
||||||
|
|
|
@ -310,11 +310,15 @@ img {
|
||||||
transform: translateX(var(--translate)) translateY(var(--translate));
|
transform: translateX(var(--translate)) translateY(var(--translate));
|
||||||
box-shadow: var(--shadow);
|
box-shadow: var(--shadow);
|
||||||
}
|
}
|
||||||
|
.prm .pop,
|
||||||
|
.prm .pop-2 {
|
||||||
|
transform: none;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
.popup-wrap {
|
.popup-wrap {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.popup {
|
.popup {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
{
|
{
|
||||||
"date": "2023-05-01"
|
"date": "2023-05-20"
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { ref, reactive, watch, onMounted } from 'vue';
|
||||||
import AlbumItem from './AlbumItem.vue';
|
import AlbumItem from './AlbumItem.vue';
|
||||||
import Modal from './Modal.vue';
|
import Modal from './Modal.vue';
|
||||||
|
|
||||||
import { useRand } from '@/scripts/colors.js';
|
import { useRand, parseThumb } from '@/scripts/colors.js';
|
||||||
import { useStore } from '@/scripts/util.js';
|
import { useStore } from '@/scripts/util.js';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -53,14 +53,19 @@ const list = ref([]),
|
||||||
password: undefined,
|
password: undefined,
|
||||||
playlists: [],
|
playlists: [],
|
||||||
create: false,
|
create: false,
|
||||||
});
|
}),
|
||||||
|
proxy = ref('');
|
||||||
|
|
||||||
const pathname = url => new URL(url).pathname;
|
const pathname = url => new URL(url).pathname;
|
||||||
|
|
||||||
const Open = async key => {
|
const setProxy = async () => {
|
||||||
|
const { imageProxyUrl } = await getJsonPiped('/config');
|
||||||
|
proxy.value = imageProxyUrl;
|
||||||
|
},
|
||||||
|
Open = async key => {
|
||||||
console.log(key);
|
console.log(key);
|
||||||
|
|
||||||
const { imageProxyUrl } = await getJsonPiped('/config');
|
if (!proxy.value) await setProxy();
|
||||||
|
|
||||||
useGetPlaylist(key, res => {
|
useGetPlaylist(key, res => {
|
||||||
console.log(res);
|
console.log(res);
|
||||||
|
@ -72,10 +77,7 @@ const Open = async key => {
|
||||||
...i,
|
...i,
|
||||||
...{
|
...{
|
||||||
playlistId: key,
|
playlistId: key,
|
||||||
thumbnail: `${imageProxyUrl}/vi_webp/${i.url.replace(
|
thumbnail: parseThumb(i.url, proxy.value),
|
||||||
'/watch?v=',
|
|
||||||
'',
|
|
||||||
)}/maxresdefault.webp?host=i.ytimg.com`,
|
|
||||||
},
|
},
|
||||||
})),
|
})),
|
||||||
});
|
});
|
||||||
|
@ -84,16 +86,18 @@ const Open = async key => {
|
||||||
} else alert('No songs to play!');
|
} else alert('No songs to play!');
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
List = () => {
|
List = async () => {
|
||||||
|
if (!proxy.value) await setProxy();
|
||||||
|
|
||||||
useListPlaylists(res => {
|
useListPlaylists(res => {
|
||||||
list.value = res;
|
list.value = res;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
Create = () => {
|
Create = () => {
|
||||||
if (text.value) {
|
if (text.value) {
|
||||||
useCreatePlaylist(text.value, [], () => {
|
useCreatePlaylist(text.value, [], async () => {
|
||||||
List();
|
|
||||||
show.new = false;
|
show.new = false;
|
||||||
|
await List();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -122,7 +126,7 @@ const Open = async key => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
List();
|
await List();
|
||||||
|
|
||||||
for (let i of data) {
|
for (let i of data) {
|
||||||
const pl = list.value.find(p => p.name == i.name);
|
const pl = list.value.find(p => p.name == i.name);
|
||||||
|
@ -137,13 +141,13 @@ const Open = async key => {
|
||||||
}
|
}
|
||||||
} else useCreatePlaylist(i.name, i.urls);
|
} else useCreatePlaylist(i.name, i.urls);
|
||||||
|
|
||||||
List();
|
await List();
|
||||||
}
|
}
|
||||||
|
|
||||||
show.import = false;
|
show.import = false;
|
||||||
},
|
},
|
||||||
Export = () => {
|
Export = async () => {
|
||||||
List();
|
await List();
|
||||||
|
|
||||||
const base = JSON.stringify(
|
const base = JSON.stringify(
|
||||||
{
|
{
|
||||||
|
@ -174,8 +178,8 @@ const Open = async key => {
|
||||||
|
|
||||||
console.log(conn);
|
console.log(conn);
|
||||||
|
|
||||||
conn.on('open', () => {
|
conn.on('open', async () => {
|
||||||
List();
|
await List();
|
||||||
conn.send(list.value);
|
conn.send(list.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -281,7 +285,7 @@ watch(
|
||||||
watch(auth, getPlaylists);
|
watch(auth, getPlaylists);
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
List();
|
await List();
|
||||||
await getPlaylists();
|
await getPlaylists();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -422,6 +426,7 @@ onMounted(async () => {
|
||||||
:key="i.name"
|
:key="i.name"
|
||||||
:name="i.name"
|
:name="i.name"
|
||||||
:author="t('title.songs') + ' • ' + i.urls.length"
|
:author="t('title.songs') + ' • ' + i.urls.length"
|
||||||
|
:art="parseThumb(i.urls[0]?.url, proxy)"
|
||||||
:grad="useRand()"
|
:grad="useRand()"
|
||||||
@open-album="Open(i.name)" />
|
@open-album="Open(i.name)" />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -22,7 +22,8 @@ const { t, setupLocale } = useI18n(),
|
||||||
instances = ref([]),
|
instances = ref([]),
|
||||||
hypInstances = ref([]),
|
hypInstances = ref([]),
|
||||||
next = ref(false),
|
next = ref(false),
|
||||||
compact = ref(false);
|
compact = ref(false),
|
||||||
|
prm = ref(false);
|
||||||
|
|
||||||
getJson('https://piped-instances.kavin.rocks')
|
getJson('https://piped-instances.kavin.rocks')
|
||||||
.then(i => i || getJson('https://instances.tokhmi.xyz'))
|
.then(i => i || getJson('https://instances.tokhmi.xyz'))
|
||||||
|
@ -70,6 +71,12 @@ function setCodec(codec) {
|
||||||
window.audioPlayer.configure('preferredAudioCodecs', codec.split(':'));
|
window.audioPlayer.configure('preferredAudioCodecs', codec.split(':'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setPRM(prm) {
|
||||||
|
setStore('prm', prm);
|
||||||
|
if (prm) document.body.classList.add('prm');
|
||||||
|
else document.body.classList.remove('prm');
|
||||||
|
}
|
||||||
|
|
||||||
function getStoreBool(key, ele, def) {
|
function getStoreBool(key, ele, def) {
|
||||||
ele.value = getStore(key) || def;
|
ele.value = getStore(key) || def;
|
||||||
}
|
}
|
||||||
|
@ -108,6 +115,7 @@ const verifyApi = computed(() =>
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getStoreBool('next', next, true);
|
getStoreBool('next', next, true);
|
||||||
getStoreBool('compact', compact, false);
|
getStoreBool('compact', compact, false);
|
||||||
|
getStoreBool('prm', prm, false);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -137,6 +145,17 @@ onMounted(() => {
|
||||||
<label for="pref-chk-compact">{{ t('pref.compact') }}</label>
|
<label for="pref-chk-compact">{{ t('pref.compact') }}</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="left">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
name="pref-chk-prm"
|
||||||
|
id="pref-chk-prm"
|
||||||
|
class="input"
|
||||||
|
@change="setPRM($event.target.checked)"
|
||||||
|
v-model="prm" />
|
||||||
|
<label for="pref-chk-prm">{{ t('pref.prm') }}</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
<h2>Language</h2>
|
<h2>Language</h2>
|
||||||
|
|
||||||
<select
|
<select
|
||||||
|
|
|
@ -177,4 +177,9 @@ span.bi-three-dots-vertical {
|
||||||
width: 70px;
|
width: 70px;
|
||||||
height: 70px;
|
height: 70px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.prm .card {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0.5rem;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -236,7 +236,10 @@ async function Like() {
|
||||||
<button
|
<button
|
||||||
id="vol-btn"
|
id="vol-btn"
|
||||||
aria-label="Volume Buttons"
|
aria-label="Volume Buttons"
|
||||||
@click="showme.vol = !showme.vol; showme.menu = false"
|
@click="
|
||||||
|
showme.vol = !showme.vol;
|
||||||
|
showme.menu = false;
|
||||||
|
"
|
||||||
class="popup-wrap bi bi-volume-up clickable">
|
class="popup-wrap bi bi-volume-up clickable">
|
||||||
<Transition name="fade">
|
<Transition name="fade">
|
||||||
<div v-if="showme.vol" id="vol" class="popup">
|
<div v-if="showme.vol" id="vol" class="popup">
|
||||||
|
@ -255,7 +258,10 @@ async function Like() {
|
||||||
<button
|
<button
|
||||||
class="bi bi-three-dots clickable"
|
class="bi bi-three-dots clickable"
|
||||||
aria-label="More Controls"
|
aria-label="More Controls"
|
||||||
@click="showme.menu = !showme.menu; showme.vol = false"></button>
|
@click="
|
||||||
|
showme.menu = !showme.menu;
|
||||||
|
showme.vol = false;
|
||||||
|
"></button>
|
||||||
<Transition name="fade">
|
<Transition name="fade">
|
||||||
<div id="menu" v-if="showme.menu" class="popup">
|
<div id="menu" v-if="showme.menu" class="popup">
|
||||||
<button
|
<button
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
"dracula": "Dracula",
|
"dracula": "Dracula",
|
||||||
"nord": "Nord",
|
"nord": "Nord",
|
||||||
"compact": "Compact View",
|
"compact": "Compact View",
|
||||||
|
"prm": "Prefers Reduced Motion",
|
||||||
"tab": "Default Tab",
|
"tab": "Default Tab",
|
||||||
"player": "Audio Player",
|
"player": "Audio Player",
|
||||||
"auto_queue": "Automatically Queue Songs",
|
"auto_queue": "Automatically Queue Songs",
|
||||||
|
|
|
@ -10,3 +10,11 @@ export function useRand() {
|
||||||
const i = Math.floor(Math.random() * c.length);
|
const i = Math.floor(Math.random() * c.length);
|
||||||
return c[i];
|
return c[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const parseThumb = (url, proxy) =>
|
||||||
|
url && proxy
|
||||||
|
? `${proxy}/vi_webp/${url.replace(
|
||||||
|
'/watch?v=',
|
||||||
|
'',
|
||||||
|
)}/maxresdefault.webp?host=i.ytimg.com`
|
||||||
|
: '/1x1.png';
|
||||||
|
|
|
@ -60,6 +60,7 @@ export const useResults = defineStore('results', () => {
|
||||||
|
|
||||||
useRoute(e);
|
useRoute(e);
|
||||||
useNav().state.page = 'home';
|
useNav().state.page = 'home';
|
||||||
|
document.body.scrollIntoView();
|
||||||
|
|
||||||
next.value =
|
next.value =
|
||||||
json.nextpage && json.nextpage != 'null'
|
json.nextpage && json.nextpage != 'null'
|
||||||
|
@ -123,6 +124,7 @@ export const useArtist = defineStore('artist', () => {
|
||||||
|
|
||||||
useRoute('/channel/' + e);
|
useRoute('/channel/' + e);
|
||||||
useNav().state.page = 'home';
|
useNav().state.page = 'home';
|
||||||
|
document.body.scrollIntoView();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getArtistNext(i, { id, params, click, visit }) {
|
async function getArtistNext(i, { id, params, click, visit }) {
|
||||||
|
|
|
@ -11,7 +11,13 @@ export default defineConfig({
|
||||||
VitePWA({
|
VitePWA({
|
||||||
registerType: 'autoUpdate',
|
registerType: 'autoUpdate',
|
||||||
workbox: {
|
workbox: {
|
||||||
globPatterns: ['**/*.{css,html,png,svg}', 'manifest.webmanifest', '**/index*.js', '**/shaka*.js'],
|
globPatterns: [
|
||||||
|
'**/*.{css,html,png,svg}',
|
||||||
|
'manifest.webmanifest',
|
||||||
|
'**/index*.js',
|
||||||
|
'**/shaka*.js',
|
||||||
|
'**/[A-Z]*.js',
|
||||||
|
],
|
||||||
},
|
},
|
||||||
manifest: {
|
manifest: {
|
||||||
name: 'Hyperpipe',
|
name: 'Hyperpipe',
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue