Skip to content

Commit

Permalink
Merge pull request #68 from zaanposni/release/1.19.0
Browse files Browse the repository at this point in the history
Release/1.19.0
  • Loading branch information
zaanposni authored Nov 30, 2024
2 parents 6c497c9 + 84378e7 commit 55491e6
Show file tree
Hide file tree
Showing 19 changed files with 322 additions and 126 deletions.
6 changes: 3 additions & 3 deletions src/imageresizer/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ app.get("/cdn/:dir/:filename", async (req: Request<{ dir: string; filename: stri
}

// Validate parameters
const validFormats = ["avif", "webp", "jpg"];
const validFormats = ["avif", "jpg"];
const validWidths = ["150", "300", "768", "1024", "original"];

if (width && !validWidths.includes(width.toString())) {
Expand All @@ -57,11 +57,11 @@ app.get("/cdn/:dir/:filename", async (req: Request<{ dir: string; filename: stri

if (format && !validFormats.includes(format.toString())) {
logger.error(`Invalid format parameter: "${format}"`);
res.status(400).send("Invalid format parameter, must be one of: avif, webp, jpg");
res.status(400).send("Invalid format parameter, must be one of: avif, jpg");
return;
}

const targetFormat = (format as "avif" | "webp" | "jpg") || "jpg";
const targetFormat = (format as "avif" | "jpg") || "jpg";
const targetWidth = width ? (width === "original" ? undefined : parseInt(width.toString())) : undefined;

const originalFilePath = path.join(cdnFiles, filename);
Expand Down
50 changes: 42 additions & 8 deletions src/nginx/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,37 @@ events { worker_connections 1024; }

http {
include mime.types;

gzip on;
gzip_disable "msie6";

gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_min_length 256;
gzip_types
application/atom+xml
application/geo+json
application/javascript
application/x-javascript
application/json
application/ld+json
application/manifest+json
application/rdf+xml
application/rss+xml
application/xhtml+xml
application/xml
font/eot
font/otf
font/ttf
image/svg+xml
text/css
text/javascript
text/plain
text/xml;

limit_req_zone $http_x_forwarded_for zone=myhigherlimit:10m rate=10r/s;
limit_req_zone $http_x_forwarded_for zone=mylimit:10m rate=3r/s;

Expand All @@ -17,16 +48,9 @@ http {
listen 80;
listen [::]:80;

root /var/www/data;
index index.html;

access_log /var/log/nginx/access_custom.log compression;
access_log /dev/stdout compression;

location ~ /\.ht {
deny all;
}

location ^~ /cdn/ {
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $http_x_forwarded_for;
Expand All @@ -43,6 +67,16 @@ http {
proxy_pass http://frontend:3000;
}

location ~ /(brammen\.jpg|chris\.jpg|jay\.jpg|peter\.jpg|sep\.jpg|ps\.png|reddit\-logo\.svg|threads\-logo\.svg|twitch\-logo\.svg)$ {
limit_req zone=mylimit burst=50 nodelay;

proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $http_x_forwarded_for;
proxy_pass http://frontend:3000;

expires 365d;
}

location / {
limit_req zone=mylimit burst=50 nodelay;

Expand All @@ -51,4 +85,4 @@ http {
proxy_pass http://frontend:3000;
}
}
}
}
23 changes: 11 additions & 12 deletions src/psaggregator/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/psaggregator/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "psaggregator",
"version": "1.18.0",
"version": "1.19.0",
"scripts": {
"dev": "vite dev",
"build": "vite build",
Expand Down
7 changes: 6 additions & 1 deletion src/psaggregator/src/lib/components/BigHeader.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@
<div class="flex items-center gap-x-4 border-b p-4">
<div>
<a href="/">
<img src="/ps.png" alt="psaggregator logo, pietsmiet logo turned upside down, green game controller" class="h-8 w-8" />
<img
src="/ps.png"
alt="psaggregator logo, pietsmiet logo turned upside down, green game controller"
class="h-8 w-8"
height="100"
width="100" />
</a>
</div>
<div class="flex grow flex-nowrap items-center justify-between">
Expand Down
30 changes: 23 additions & 7 deletions src/psaggregator/src/lib/components/CDNImage.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,28 @@
let classes = "";
export { classes as class };
function getPreferredImageFormat() {
let imageSrc = "";
function supportsAVIF() {
return new Promise((resolve) => {
const avifImage =
"data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAAB0AAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAIAAAACAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQ0MAAAAABNjb2xybmNseAACAAIAAYAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAACVtZGF0EgAKCBgANogQEAwgMg8f8D///8WfhwB8+ErK42A=";
const img = new Image();
img.onload = () => resolve(true);
img.onerror = () => resolve(false);
img.src = avifImage;
});
}
async function getPreferredImageFormat() {
if (!browser || !window || !window.matchMedia) {
return "jpg";
}
if (window.matchMedia && window.matchMedia("(image-avif)").matches) {
if (await supportsAVIF()) {
return "avif";
} else if (window.matchMedia && window.matchMedia("(image-webp)").matches) {
return "webp";
}
return "jpg"; // fallback
}
Expand Down Expand Up @@ -50,9 +62,13 @@
return "300"; // fallback
}
$: imageSrc = `${src}?format=${getPreferredImageFormat()}&width=${getPreferredImageSize()}`;
async function calculateImageSrc(src: string | null | undefined) {
imageSrc = `${src}?format=${await getPreferredImageFormat()}&width=${getPreferredImageSize()}`;
}
$: browser && calculateImageSrc(src);
</script>

{#if browser}
<img src={imageSrc} alt={alt ?? "unknown"} title={title ?? alt ?? "unknown"} {loading} class={style} />
{#if imageSrc}
<img src={imageSrc} alt={alt ?? "unknown"} title={title ?? alt ?? "unknown"} {loading} class={classes} {style} />
{/if}
9 changes: 8 additions & 1 deletion src/psaggregator/src/lib/components/InstagramPost.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import CdnImage from "./CDNImage.svelte";
export let post: Information & { InformationResource: InformationResource[] };
export let loading: "lazy" | "eager" = "lazy";
let video: HTMLVideoElement;
$: isVideoOnly =
Expand Down Expand Up @@ -59,7 +60,13 @@
{/each}
</div>
{:else if post.imageUri}
<CdnImage size="large" class="m-4 rounded-xl md:m-8" src={post.imageUri} alt={"community post attachment"} title={post.text} />
<CdnImage
size="large"
class="m-4 rounded-xl md:m-8"
src={post.imageUri}
alt={"community post attachment"}
title={post.text}
{loading} />
{/if}
</div>
</Card.Root>
104 changes: 56 additions & 48 deletions src/psaggregator/src/lib/components/InstagramStoriesContainer.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -184,62 +184,70 @@

<MediaQuery query="(min-width: 768px)" let:matches>
{#if active}
<div class="absolute left-0 top-0 z-10 flex h-full w-full flex-col bg-black">
<div
class="max-w-screen absolute left-0 top-0 z-10 flex h-screen max-h-screen w-screen flex-col overflow-hidden bg-black pt-12 lg:pt-12">
<div
class="story-container flex h-full w-full flex-col overflow-hidden lg:mx-auto lg:w-1/2"
class="story-container max-w-screen flex h-screen max-h-screen w-screen flex-col overflow-hidden lg:mx-auto lg:w-1/2"
class:pause={touchStartX}
on:touchstart={touchStartHandler}
on:touchend={touchEndHandler}>
<div class="progress-container flex w-full px-2 pt-4" bind:this={progressContainer}>
{#each stories as story, index}
{@const duration =
story.InformationResource?.length && story.InformationResource[0].videoDuration
? story.InformationResource[0].videoDuration
: 15}
<div
style="animation-duration: {duration}s"
class:active={currentIndex === index}
class:passed={currentIndex > index}
class="progress"
on:animationend={playNext}
on:click={() => {
playSpecific(index);
}}
on:keydown={void 0}
role="button"
tabindex="0">
</div>
{/each}
</div>
<div class="mt-2 flex w-full items-center justify-between px-2">
<div class="flex items-center gap-x-2">
<img src="{filterKey}.jpg" alt={filterKey} class="h-12 w-12 rounded-full object-cover" />
<span class="text-sm font-bold text-white">{titleCase(filterKey)}</span>
<div class="max-w-screen lg:max-w-1/2 absolute top-12 z-10 w-screen lg:top-0 lg:w-1/2">
<div class="progress-container flex w-full max-w-full px-2 pt-4" bind:this={progressContainer}>
{#each stories as story, index}
{@const duration =
story.InformationResource?.length && story.InformationResource[0].videoDuration
? story.InformationResource[0].videoDuration
: 15}
<div
style="animation-duration: {duration}s"
class:active={currentIndex === index}
class:passed={currentIndex > index}
class="progress"
on:animationend={playNext}
on:click={() => {
playSpecific(index);
}}
on:keydown={void 0}
role="button"
tabindex="0">
</div>
{/each}
</div>
<div class="flex items-center gap-x-2">
{#if selectedStory && selectedStory.InformationResource?.length && selectedStory.InformationResource[0].videoUri}
<button
on:click={(e) => {
video.muted = !video.muted;
e.stopPropagation();
}}>
{#if video}
{#if video.muted}
<VolumeMute class="h-8 w-8" />
{:else}
<VolumeUp class="h-8 w-8" />
<div class="mt-2 flex w-full items-center justify-between px-2">
<div class="flex items-center gap-x-2">
<img
src="{filterKey}.jpg"
alt={filterKey}
class="aspect-square h-12 w-12 rounded-full object-cover"
width="64"
height="64" />
<span class="text-sm font-bold text-white">{titleCase(filterKey)}</span>
</div>
<div class="flex items-center gap-x-2">
{#if selectedStory && selectedStory.InformationResource?.length && selectedStory.InformationResource[0].videoUri}
<button
on:click={(e) => {
video.muted = !video.muted;
e.stopPropagation();
}}>
{#if video}
{#if video.muted}
<VolumeMute class="h-8 w-8" />
{:else}
<VolumeUp class="h-8 w-8" />
{/if}
{/if}
{/if}
</button>
{/if}
<button on:click={() => (active = false)}>
<CloseLarge class="h-8 w-8" />
</button>
{/if}
<button on:click={() => (active = false)}>
<CloseLarge class="h-8 w-8" />
</button>
</div>
</div>
</div>
<div
bind:this={storyView}
class="flex h-full w-full items-center justify-center overflow-y-auto py-2 md:py-8"
class="flex w-full justify-center overflow-hidden"
on:click={clickImageHandler}
on:keydown={void 0}
role="button"
Expand All @@ -253,14 +261,14 @@
loop
muted
playsinline
class="h-full w-full object-contain"></video>
class="rounded-[20px] object-contain"></video>
{:else}
<CdnImage
size="full"
src={selectedStory.imageUri}
alt={selectedStory.text}
title={selectedStory.text}
class="h-full w-full object-contain" />
class="rounded-[20px] object-contain" />
{/if}
{/if}
</div>
Expand All @@ -278,7 +286,7 @@
on:keydown={void 0}
role="button"
tabindex="0">
<img class="h-full w-full rounded-full object-cover" src="{filterKey}.jpg" alt={filterKey} />
<img class="h-full w-full rounded-full object-cover" src="{filterKey}.jpg" alt={filterKey} width="64" height="64" />
</div>
{/if}
</MediaQuery>
Loading

0 comments on commit 55491e6

Please sign in to comment.