Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(page): improve rendering #1170

Merged
merged 4 commits into from
Jan 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions apps/page/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@
"vue-i18n": "9.13.1",
"ndarray": "1.0.19",
"quantize": "1.0.2",
"@heroicons/vue": "2.2.0"
"@heroicons/vue": "2.2.0",
"sanitize-html": "2.14.0"
},
"devDependencies": {
"@types/lodash-es": "4.17.12",
Expand All @@ -48,6 +49,7 @@
"typescript": "5.3.2",
"@types/get-pixels": "3.3.4",
"@types/quantize": "1.0.2",
"@types/ndarray": "1.0.14"
"@types/ndarray": "1.0.14",
"@types/sanitize-html": "2.13.0"
}
}
8 changes: 4 additions & 4 deletions apps/page/src/features/PageFooter.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<template>
<div
class="w-full bg-gray-800 p-6 mt-16 text-gray-100 font-extralight text-sm flex justify-center"
class="w-full bg-gray-800 p-6 mt-16 text-gray-100 font-extralight text-sm"
>
<div class="w-full lg:w-app px-8 block lg:flex">
<div class="w-full md:w-1/3 truncate">
<div class="w-full px-8 flex flex-col md:flex-row">
<div class="w-full md:w-1/3 truncate text-center">
{{ t('FOOTER.COPYRIGHT', { copyright: state.copyright }) }}
</div>
<div class="w-full md:w-1/3 truncate text-center" v-if="state.owner">
Expand All @@ -20,7 +20,7 @@
</span>
</div>

<div class="w-full md:w-1/3 truncate text-right">
<div class="w-full md:w-1/3 truncate text-center md:text-right">
<a
class="hover:underline"
href="https://lux.podlove.org"
Expand Down
2 changes: 1 addition & 1 deletion apps/page/src/features/feed-search/FeedSearch.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<div class="max-w-[800px] flex items-center flex-col">
<Search :query="query" @search="search" :loading="loading" class="mb-10" />
<Search :query="query" @search="search" :loading="loading" class="lg:mb-10" />
<Transition name="slide-fade">
<ul v-if="results.length > 0">
<Item
Expand Down
2 changes: 1 addition & 1 deletion apps/page/src/features/feed-search/components/Item.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<span class="absolute inset-x-0 -top-px bottom-0" />
{{ title }}
</p>
<p class="mt-1 flex text-xs/5 text-gray-500">
<p class="mt-1 text-xs/5 text-gray-500 line-clamp-4">
{{ description }}
</p>
</div>
Expand Down
8 changes: 4 additions & 4 deletions apps/page/src/features/feed-search/components/Search.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<template>
<div>
<div class="mt-2 grid grid-cols-1 podcast-search">
<div class="mt-2 grid grid-cols-1 podcast-search w-full">
<div
class="flex items-center rounded-md bg-white px-3 outline outline-1 -outline-offset-1 outline-gray-300 focus-within:outline focus-within:outline-2 focus-within:-outline-offset-2 focus-within:outline-complementary-600 w-128"
class="flex items-center rounded-md bg-white px-3 outline outline-1 -outline-offset-1 outline-gray-300 focus-within:outline focus-within:outline-2 focus-within:-outline-offset-2 focus-within:outline-complementary-600 lg:min-w-128 w-full"
>
<div class="shrink-0 select-none text-base text-gray-500 flex items-center w-6">
<LoadingIcon
Expand All @@ -18,7 +18,7 @@
</div>
<input
type="text"
class="block min-w-0 w-full grow pt-1 pb-1.5 pl-1.5 pr-1.5 text-gray-900 placeholder:text-gray-400 focus:outline focus:outline-0 text-lg font-extralight"
class="block w-full grow pt-1 pb-1.5 pl-1.5 pr-1.5 text-gray-900 placeholder:text-gray-400 focus:outline focus:outline-0 text-base lg:text-lg font-extralight min-w-64"
placeholder="Search for a Podcast or enter a Feed"
:value="query"
@input="input"
Expand All @@ -44,7 +44,7 @@ import { ref } from 'vue';

import Fyyd from './Fyyd.vue';

defineProps<{ query: string | null; loading: boolean; }>();
defineProps<{ query: string | null; loading: boolean }>();

const showPoweredBy = ref(false);

Expand Down
2 changes: 1 addition & 1 deletion apps/page/src/features/playbar/PlayBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ const state = mapState({

const playtime = computed(() => (isNumber(state.ghost) ? state.ghost : state.playtime));
const duration = computed(() => state.duration - (state.ghost ? state.ghost : state.playtime));
const link = computed(() => `/feed/${state.feed}/episodes/${state.episode}`);
const link = computed(() => `/feed/${state.feed}/episode/${state.episode}`);

const scroll = () => {
scrolledToBottom.value =
Expand Down
2 changes: 1 addition & 1 deletion apps/page/src/features/subscribe/Subscribe.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<h3 class="font-mono inline-block border-primary-400 border-b-2 mb-6">
{{ t('SUBSCRIBE_BUTTON.CLIENTS') }}
</h3>
<div class="subscribe-clients flex flex-col mb-4 sm:flex-wrap sm:flex-row">
<div class="subscribe-clients flex flex-col mb-4 sm:flex-wrap sm:flex-row min-h-36">
<div class="w-full mb-4 sm:w-40" v-for="client in items" :key="client?.id">
<a
v-if="client?.link"
Expand Down
2 changes: 1 addition & 1 deletion apps/page/src/layouts/Layout.astro
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const lang = getLanguage();
<meta name="description" content="Astro description" />
<meta name="viewport" content="width=device-width" />
<link rel="icon" type="image/svg+xml" href={favicon} />
<meta name="generator" content={Astro.generator} />
<meta name="generator" content="Podlove Lux" />
<title>{title}</title>
<meta name="description" content={description} />
<script is:inline define:vars={{ state }}>
Expand Down
2 changes: 1 addition & 1 deletion apps/page/src/lib/get-image-color.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ const convertToPixels = (pixels: ndarray.NdArray): quantize.RgbPixel[] => {
const extractColors = (
pixels: quantize.RgbPixel[]
): { primaryColor: rgbColor | null; complementaryColor: rgbColor | null } => {
const colorPalette = quantize(pixels, 2);
const colorPalette = quantize(pixels, 5);

if (!colorPalette) {
return { primaryColor: null, complementaryColor: null };
Expand Down
41 changes: 28 additions & 13 deletions apps/page/src/logic/data/feed-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { get, castArray, kebabCase, isArray } from 'lodash-es';
import { XMLParser } from 'fast-xml-parser';
import { toPlayerTime } from '@podlove/utils/time';
import webVttParser from '@podlove/webvtt-parser';
import sanitizeHtml from 'sanitize-html';

import type {
Audio,
Expand Down Expand Up @@ -55,6 +56,15 @@ const buildChapterList =
end: get(list, [index + 1, 'start'], duration) as number
});

const cleanContent = (content: string) =>
sanitizeHtml(content, {
allowedTags: ['h1', 'h2', 'h3', 'p', 'b', 'i', 'em', 'strong', 'a', 'img', 'ul', 'li', 'ol'],
allowedAttributes: {
a: ['href'],
img: ['src']
}
});

const transformShow = (data: any): Show => ({
title: get(data, ['channel', 'title'], null),
description: get(data, ['channel', 'description'], null),
Expand All @@ -70,7 +80,9 @@ const getTranscriptUrl = async (data: any): Promise<string | null> => {
[]
);

const vtt = (isArray(transcripts) ? transcripts: [transcripts]).find((item) => get(item, ['@_type'], null) === 'text/vtt');
const vtt = (isArray(transcripts) ? transcripts : [transcripts]).find(
(item) => get(item, ['@_type'], null) === 'text/vtt'
);

return get(vtt, ['@_url'], null);
};
Expand Down Expand Up @@ -119,13 +131,16 @@ const resolveEpisode =
link: get(data, 'link', null),
publicationDate: get(data, 'pubDate', null),
duration,
content: get(data, 'content:encoded', null),
content: cleanContent(get(data, 'content:encoded', null)),
poster: get(data, ['itunes:image', '@_href'], null),
contributors: castArray(get(data, ['podcast:person'], [])).map(transformPerson),
chapters: castArray(get(data, ['psc:chapters', 'psc:chapter'], []))
.map(transformChapter)
.map(buildChapterList(duration)),
transcripts: id === episodeId && transcriptUrl ? await resolveTranscripts(transcriptUrl) : (transcriptUrl || []),
transcripts:
id === episodeId && transcriptUrl
? await resolveTranscripts(transcriptUrl)
: transcriptUrl || [],
audio: transformAudio(data)
};
};
Expand All @@ -140,18 +155,18 @@ const transformAuthor = (data: any): Author => ({
const transform =
(episodeId?: number) =>
async (data: any): Promise<Podcast> => {
const episodes = castArray(get(data, ['channel', 'item'], []))
const episodes = castArray(get(data, ['channel', 'item'], []));
return {
etag: get(data, 'etag', null),
buildDate: get(data, ['channel', 'lastBuildDate'], null),
author: transformAuthor(data),
show: transformShow(data),
episodes: await Promise.all(
episodes.map(resolveEpisode(episodes.length, episodeId))
).then(episodes => episodes.filter(episode => episode.id !== null)),
hosts: castArray(get(data, ['channel', 'podcast:person'], [])).map(transformPerson)
etag: get(data, 'etag', null),
buildDate: get(data, ['channel', 'lastBuildDate'], null),
author: transformAuthor(data),
show: transformShow(data),
episodes: await Promise.all(episodes.map(resolveEpisode(episodes.length, episodeId))).then(
(episodes) => episodes.filter((episode) => episode.id !== null)
),
hosts: castArray(get(data, ['channel', 'podcast:person'], [])).map(transformPerson)
};
};
}

export default async ({
feed,
Expand Down
17 changes: 11 additions & 6 deletions apps/page/src/pages/feed/[...feed]/episode/[episodeId].astro
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ const timeline = [
.episode-content h5,
.episode-content h6 {
font-weight: 300;
letter-spacing: -0.1rem;
margin-bottom: 1rem;
margin-top: 0;
}
Expand Down Expand Up @@ -138,7 +137,7 @@ const timeline = [
.episode-content dd,
.episode-content dt,
.episode-content li {
margin-bottom: 1rem;
margin-bottom: 0.25rem;
}

.episode-content fieldset,
Expand All @@ -158,7 +157,7 @@ const timeline = [
.episode-content table,
.episode-content img,
.episode-content ul {
margin-bottom: 2.5rem;
margin-bottom: 1rem;
}

/* List */
Expand All @@ -177,10 +176,15 @@ const timeline = [
}

.episode-content ol {
list-style: decimal inside;
list-style: decimal;
}
.episode-content ul {
list-style: circle inside;
list-style: circle;
}

.episode-content ul li ul {
margin-top: 0;
margin-bottom: 0;
}

/* Links */
Expand All @@ -196,7 +200,8 @@ const timeline = [

/* Image */
.episode-content img {
max-width: 100%;
max-width: 450px;
margin: 0 auto 1rem auto;
}

/* Divider */
Expand Down
12 changes: 6 additions & 6 deletions apps/page/src/pages/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const lang = getLanguage();
<meta name="description" content="Astro description" />
<meta name="viewport" content="width=device-width" />
<link rel="icon" type="image/svg+xml" href="icon.svg" />
<meta name="generator" content={Astro.generator} />
<meta name="generator" content="Podlove Lux" />
<title>Podlove Lux</title>
<style>
:root {
Expand Down Expand Up @@ -46,15 +46,15 @@ const lang = getLanguage();
</style>
</head>
<body class="bg-gray-100">
<header>
<div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 pb-16 pt-20 text-center lg:pt-32">
<header class="w-full">
<div class="flex justify-center px-4 pb-8 pt-10 text-center lg:pt-32 lg:pb-16 w-full">
<h1
class="flex justify-center mx-auto max-w-4xl font-display text-5xl font-medium tracking-tight text-slate-900 sm:text-7xl text-complementary-900"
class="flex font-display text-5xl font-medium tracking-tight text-slate-900 sm:text-7xl text-complementary-900"
>
<img src="icon.svg" class="h-14 mr-2 mt-2.5" />
<img src="icon.svg" class="h-8 lg:h-14 mr-2 mt-2.5" />
<div class="mr-2 flex flex-col text-left">
<span class="">Podlove</span>
<span class="text-2xl ml-0.5 -mt-3">Illuminate your Feed</span>
<span class="text-xl lg:text-2xl ml-0.5 -mt-3">Illuminate your Feed</span>
</div><span class="relative whitespace-nowrap text-primary-500">Lux</span>
</h1>
</div>
Expand Down
1 change: 1 addition & 0 deletions apps/page/src/screens/archive/Hero.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
mb-4
md:mb-0 md:mr-8 md:mt-1
w-1/5
min-w-[150px]
"
>
<div
Expand Down
4 changes: 2 additions & 2 deletions apps/page/src/screens/archive/Item.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<div class="py-8 border-gray-400 border-dashed" :class="{ 'pt-0': first, 'border-b': last }">
<div class="flex">
<div class="flex mb-2 lg:mb-0">
<div class="player-tile-button w-20 h-20 mr-4 relative flex-shrink-0 mt-1">
<img
:src="state.episode.poster || state.poster"
Expand Down Expand Up @@ -29,7 +29,7 @@
<a
:href="state.link"
v-if="state.episode.title"
class="leading-tight sm:leading block text-xl uppercase whitespace-nowrap truncate"
class="leading-tight sm:leading block text-xl uppercase line-clamp-2 lg:line-clamp-1"
>{{ state.episode.mnemonic }} {{ state.episode.title }}</a
>
<div class="block md:flex">
Expand Down
6 changes: 3 additions & 3 deletions apps/page/src/screens/episodes/Navigation.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
>
<div
class="h-20 relative w-full flex items-center justify-center"
:class="{ 'bg-white -mb-4': !docked, 'bg-transparent': docked }"
:class="{ '-mb-4': !docked }"
>
<span class="w-full absolute top-0 left" v-if="!docked"></span>
</div>

<div
class="text-complementary-900 h-16 flex justify-center items-center py-4 px-8 w-full"
:class="{ 'bg-primary-700 rounded-b': docked }"
:class="{ 'bg-primary-900 rounded-b': docked }"
>
<!-- Summary -->
<button
Expand Down Expand Up @@ -51,7 +51,7 @@
</button>
</div>

<div class="h-20 relative w-full -mb-4" :class="{ 'bg-white -mb-4': !docked }">
<div class="h-20 relative w-full -mb-4" :class="{ '-mb-4': !docked }">
<span class="w-full absolute top-0 right" v-if="!docked"></span>
</div>
</div>
Expand Down
Loading
Loading