Compare commits

..

3 Commits

5 changed files with 117 additions and 49 deletions

View File

@@ -0,0 +1,67 @@
<script lang="ts">
// currently available reactions: pointing, joy
let {
reaction,
text,
}: {
reaction: string;
text: string;
} = $props();
function getReactionAlt(r: string): string {
switch (r) {
case "joy":
return ""
default:
return "placeholder reaction"
}
}
</script>
<div class="reaction-container blurred-background">
<div class="reaction-content-container">
<img src="/reactions/{reaction}.webp" alt={getReactionAlt(reaction)}>
<p>{text}</p>
</div>
</div>
<style>
.reaction-container {
max-width: 800px;
margin: 32px auto;
overflow: hidden;
}
.reaction-content-container {
display: flex;
flex-direction: row;
align-items: center;
margin: 0 64px;
padding: 16px;
border-radius: var(--border-radius);
border-left: var(--border-style) var(--border-dash-size) var(--color-text);
border-right: var(--border-style) var(--border-dash-size) var(--color-text);
gap: 16px;
}
img {
width: 160px;
}
p {
margin: 0;
}
@media screen and (max-width: 600px) {
.reaction-content-container {
flex-direction: column;
gap: 8px;
}
}
@media screen and (max-width: 450px) {
.reaction-content-container {
margin: 0 32px;
}
}
</style>

View File

@@ -31,97 +31,80 @@
} }
</script> </script>
<div class="gallery-zone"> <!-- TODO on mobile, put buttons between text and image -->
<div class="gallery-container blurred-background"> <div class="gallery-zone blurred-background">
<div class="gallery-button-container"> <div class="gallery-img-container">
<button class="gallery-button" onclick={galleryBack}>&lt;</button> <img class="gallery-img" loading="lazy" src={images[currentIndex].src} alt={images[currentIndex].alt}>
<div class="gallery-text-container"> </div>
<p class="gallery-index">{currentIndex + 1} / {images.length} :: <a href={images[currentIndex].src}>full-size</a></p> <div class="gallery-button-container">
<div class="gallery-desc-container"> <button class="gallery-button" onclick={galleryBack}>&lt;</button>
<p>&nbsp;</p> <!-- this element intentionally left blank --> <div class="gallery-text-container">
{#each images[currentIndex].desc as d} <p class="gallery-index">{currentIndex + 1} / {images.length} :: <a href={images[currentIndex].src}>full-size</a></p>
<p>{@html d}</p> <div class="gallery-desc-container">
{/each} {#each images[currentIndex].desc as d}
</div> <p>{@html d}</p>
{/each}
</div> </div>
<button class="gallery-button" onclick={galleryForward}>&gt;</button>
</div>
<div class="gallery-img-container">
<img class="gallery-img" loading="lazy" src={images[currentIndex].src} alt={images[currentIndex].alt}>
</div> </div>
<button class="gallery-button" onclick={galleryForward}>&gt;</button>
</div> </div>
</div> </div>
<style> <style>
.gallery-zone { .gallery-zone {
width: 100%; width: 100%;
} display: grid;
grid-template-columns: 5fr 4fr;
.gallery-container {
max-width: var(--media-width);
margin: 12px auto; margin: 12px auto;
border: var(--border-style) var(--border-dash-size) var(--color-highlight-alt); border: var(--border-style) var(--border-dash-size) var(--color-highlight-alt);
border-radius: var(--border-radius); border-radius: var(--border-radius);
overflow: hidden; overflow: hidden;
height: var(--media-height);
} }
.gallery-img-container { .gallery-img-container {
width: 100%; width: 100%;
height: var(--media-height);
margin: 0 auto; margin: 0 auto;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
border-right: var(--border-style) var(--border-dash-size) var(--color-highlight-alt);
} }
.gallery-img { .gallery-img {
object-fit: contain; object-fit: contain;
margin: 0; margin: 0;
width: 100%; width: 100%;
filter: brightness(100%) saturate(100%);
transition: filter var(--duration-animation) var(--anim-curve);
}
.gallery-button-container,
.gallery-text-container {
opacity: 0%;
transition: opacity var(--duration-animation) var(--anim-curve);
}
.gallery-zone:hover .gallery-button-container,
.gallery-zone:hover .gallery-text-container
{
opacity: 100%;
}
.gallery-zone:hover .gallery-img {
filter: brightness(50%) saturate(80%);
} }
.gallery-text-container { .gallery-text-container {
height: 100%;
width: 100%; width: 100%;
height: var(--media-height);
/* overflow: hidden; */
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: space-between; /* justify-content: space-between; */
margin: 8px 32px; margin: 0 16px;
overflow: scroll;
box-sizing: border-box;
} }
.gallery-index { .gallery-index {
font-family: var(--font-mono); font-family: var(--font-mono);
font-weight: 600; font-weight: 600;
font-size: 1.0rem; font-size: 1.0rem;
padding-top: 12px;
} }
.gallery-text-container p, .gallery-index a { .gallery-text-container p, .gallery-index a {
height: fit-content; height: fit-content;
font-size: 1.0rem; font-size: 1.0rem;
line-height: 1.4rem; line-height: 1.4rem;
text-shadow: 0 0 6px black, 0 0 9px black;
} }
.gallery-desc-container { .gallery-desc-container {
padding-bottom: 12px; padding-bottom: 24px;
padding-right: 12px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 4px; gap: 4px;
@@ -131,8 +114,6 @@
} }
.gallery-button-container { .gallery-button-container {
z-index: 1;
position: absolute;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
@@ -167,4 +148,21 @@
.gallery-button:hover { .gallery-button:hover {
background-color: var(--color-background-highlight-hover-alt); background-color: var(--color-background-highlight-hover-alt);
} }
@media screen and (max-width: 700px) {
.gallery-zone {
display: flex;
flex-direction: column;
height: initial;
}
.gallery-text-container {
height: initial;
}
.gallery-img-container {
border-right: none;
border-bottom: var(--border-style) var(--border-dash-size) var(--color-highlight-alt);
}
}
</style> </style>

View File

@@ -1,18 +1,21 @@
<script lang="ts"> <script lang="ts">
import ImageGallery from "$lib/lists/image-gallery.svelte"; import ImageGallery from "$lib/lists/image-gallery.svelte";
import ReactionQuote from "$lib/components/reaction-quote.svelte";
</script> </script>
**AvH-Vertretungsplan** was an app I developed back in 2019 to view the substitution plan of my school more easily, since I disliked the disorganised design of the school's website. The substitution app allowed me to be more quickly informed about my courses, as it notified me about any cancellations and changes in my schedule. It also allowed me to view the canteen offers, even though I'd never eaten at the school's canteen. **AvH-Vertretungsplan** was an app I developed back in 2019 to view the substitution plan of my school more easily, since I disliked the disorganised design of the school's website. The substitution app allowed me to be more quickly informed about my courses, as it notified me about any cancellations and changes in my schedule. It also allowed me to view the canteen offers, even though I'd never eaten at the school's canteen.
The app was initially developed in Java and later converted into Kotlin as part of my Kotlin learning effort. The backend of the app which I needed as the school website required a login to view the substitution plan ran on a Raspberry Pi 3B using a Python script that scraped the website using Selenium and sent out notifications via Firebase. The Raspberry Pi crashed often and the script was not perfect, requiring me to frequently remote into the Pi using VNC, often while I was at school, to edit the script! The app was initially developed in Java and later converted into Kotlin as part of my Kotlin learning effort. The backend of the app which I needed as the school website required a login to view the substitution plan ran on a Raspberry Pi 3B using a Python script that scraped the website using Selenium and sent out notifications via Firebase. The Raspberry Pi crashed often and the script was not perfect, requiring me to frequently remote into the Pi using VNC, often while I was at school, to edit the script!
<ReactionQuote
reaction="joy"
text="one of my favourite memories regarding this app is the time I first presented the app to my classmates. I had someone from my class help me in presenting; he did the intro, hyping up the crowd, and I followed up by showing and explaining the app. I'm still very grateful he decided to help me with this! Thanks, Leon!"
/>
Since the app was written for native Android but a few of my classmates had iPhones, I had an iOS version in the works, which was developed entirely on a MacOS VM running on my laptop and debugged using an iPhone simulator in Xcode. The app achieved feature parity with the Android version at one point, but since I lacked funding to pay the $99-a-year fee Apple charges developers, it was never published and thus abandoned. Since the app was written for native Android but a few of my classmates had iPhones, I had an iOS version in the works, which was developed entirely on a MacOS VM running on my laptop and debugged using an iPhone simulator in Xcode. The app achieved feature parity with the Android version at one point, but since I lacked funding to pay the $99-a-year fee Apple charges developers, it was never published and thus abandoned.
This app was genuinely one of my most fun projects, not only serving me as a handy tool, but also being a great playground for my programming practice, since it taught me to build UIs, use databases, and more. The app had been downloaded by 250 other students at my school, which I was and still am very proud of. This app was genuinely one of my most fun projects, not only serving me as a handy tool, but also being a great playground for my programming practice, since it taught me to build UIs, use databases, and more. The app had been downloaded by 250 other students at my school, which I was and still am very proud of.
<!-- reaction here -->
<!-- one of my favourite memories regarding this app is the time I first presented the app to my classmates. I had someone from my class help me in presenting; he did the intro, hyping up the crowd, and I followed up by showing and explaining the app. I'm still very grateful he decided to help me with this! Thanks, Leon! -->
<ImageGallery <ImageGallery
images={[ images={[
{ {

BIN
static/reactions/joy.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB