- 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:
Shiny Nematoda 2023-05-20 15:37:16 +00:00
parent e905bb0d9a
commit 1e59c18acd
11 changed files with 83 additions and 24 deletions

View file

@ -107,6 +107,9 @@ onBeforeMount(() => {
if (store.theme) document.body.setAttribute('data-theme', store.theme);
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 */
if (store.locale) setupLocale(store.locale);

View file

@ -310,11 +310,15 @@ img {
transform: translateX(var(--translate)) translateY(var(--translate));
box-shadow: var(--shadow);
}
.prm .pop,
.prm .pop-2 {
transform: none;
box-shadow: none;
}
.popup-wrap {
position: relative;
}
.popup {
position: absolute;
display: flex;

View file

@ -1,3 +1,3 @@
{
"date": "2023-05-01"
"date": "2023-05-20"
}

View file

@ -4,7 +4,7 @@ import { ref, reactive, watch, onMounted } from 'vue';
import AlbumItem from './AlbumItem.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 {
@ -53,14 +53,19 @@ const list = ref([]),
password: undefined,
playlists: [],
create: false,
});
}),
proxy = ref('');
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);
const { imageProxyUrl } = await getJsonPiped('/config');
if (!proxy.value) await setProxy();
useGetPlaylist(key, res => {
console.log(res);
@ -72,10 +77,7 @@ const Open = async key => {
...i,
...{
playlistId: key,
thumbnail: `${imageProxyUrl}/vi_webp/${i.url.replace(
'/watch?v=',
'',
)}/maxresdefault.webp?host=i.ytimg.com`,
thumbnail: parseThumb(i.url, proxy.value),
},
})),
});
@ -84,16 +86,18 @@ const Open = async key => {
} else alert('No songs to play!');
});
},
List = () => {
List = async () => {
if (!proxy.value) await setProxy();
useListPlaylists(res => {
list.value = res;
});
},
Create = () => {
if (text.value) {
useCreatePlaylist(text.value, [], () => {
List();
useCreatePlaylist(text.value, [], async () => {
show.new = false;
await List();
});
}
},
@ -122,7 +126,7 @@ const Open = async key => {
return;
}
List();
await List();
for (let i of data) {
const pl = list.value.find(p => p.name == i.name);
@ -137,13 +141,13 @@ const Open = async key => {
}
} else useCreatePlaylist(i.name, i.urls);
List();
await List();
}
show.import = false;
},
Export = () => {
List();
Export = async () => {
await List();
const base = JSON.stringify(
{
@ -174,8 +178,8 @@ const Open = async key => {
console.log(conn);
conn.on('open', () => {
List();
conn.on('open', async () => {
await List();
conn.send(list.value);
});
@ -281,7 +285,7 @@ watch(
watch(auth, getPlaylists);
onMounted(async () => {
List();
await List();
await getPlaylists();
});
</script>
@ -422,6 +426,7 @@ onMounted(async () => {
:key="i.name"
:name="i.name"
:author="t('title.songs') + ' • ' + i.urls.length"
:art="parseThumb(i.urls[0]?.url, proxy)"
:grad="useRand()"
@open-album="Open(i.name)" />
</div>

View file

@ -22,7 +22,8 @@ const { t, setupLocale } = useI18n(),
instances = ref([]),
hypInstances = ref([]),
next = ref(false),
compact = ref(false);
compact = ref(false),
prm = ref(false);
getJson('https://piped-instances.kavin.rocks')
.then(i => i || getJson('https://instances.tokhmi.xyz'))
@ -70,6 +71,12 @@ function setCodec(codec) {
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) {
ele.value = getStore(key) || def;
}
@ -108,6 +115,7 @@ const verifyApi = computed(() =>
onMounted(() => {
getStoreBool('next', next, true);
getStoreBool('compact', compact, false);
getStoreBool('prm', prm, false);
});
</script>
@ -137,6 +145,17 @@ onMounted(() => {
<label for="pref-chk-compact">{{ t('pref.compact') }}</label>
</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>
<select

View file

@ -177,4 +177,9 @@ span.bi-three-dots-vertical {
width: 70px;
height: 70px;
}
.prm .card {
margin: 0;
padding: 0.5rem;
}
</style>

View file

@ -236,7 +236,10 @@ async function Like() {
<button
id="vol-btn"
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">
<Transition name="fade">
<div v-if="showme.vol" id="vol" class="popup">
@ -255,7 +258,10 @@ async function Like() {
<button
class="bi bi-three-dots clickable"
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">
<div id="menu" v-if="showme.menu" class="popup">
<button

View file

@ -45,6 +45,7 @@
"dracula": "Dracula",
"nord": "Nord",
"compact": "Compact View",
"prm": "Prefers Reduced Motion",
"tab": "Default Tab",
"player": "Audio Player",
"auto_queue": "Automatically Queue Songs",

View file

@ -10,3 +10,11 @@ export function useRand() {
const i = Math.floor(Math.random() * c.length);
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';

View file

@ -60,6 +60,7 @@ export const useResults = defineStore('results', () => {
useRoute(e);
useNav().state.page = 'home';
document.body.scrollIntoView();
next.value =
json.nextpage && json.nextpage != 'null'
@ -123,6 +124,7 @@ export const useArtist = defineStore('artist', () => {
useRoute('/channel/' + e);
useNav().state.page = 'home';
document.body.scrollIntoView();
}
async function getArtistNext(i, { id, params, click, visit }) {

View file

@ -11,7 +11,13 @@ export default defineConfig({
VitePWA({
registerType: 'autoUpdate',
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: {
name: 'Hyperpipe',