Compare commits
2 Commits
83c8cdaa34
...
ac123ad0d7
| Author | SHA1 | Date | |
|---|---|---|---|
| ac123ad0d7 | |||
| 3a9d4dd2fc |
@@ -109,8 +109,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.row-updated {
|
.row-updated {
|
||||||
margin-top: 2px;
|
margin-top: 4px;
|
||||||
padding: 4px 8px;
|
padding: 2px 8px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
background-color: var(--color-background-highlight);
|
background-color: var(--color-background-highlight);
|
||||||
border-radius: var(--border-radius);
|
border-radius: var(--border-radius);
|
||||||
|
|||||||
@@ -1,34 +1,20 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Content from "$lib/viewport/content.svelte";
|
import Content from "$lib/viewport/content.svelte";
|
||||||
import LinkRow, { type LinkRowEntry } from "$lib/lists/link-row.svelte";
|
import LinkRow from "$lib/lists/link-row.svelte";
|
||||||
|
|
||||||
import { posts as devlogPosts } from "./projects/projectn5/devlog/posts";
|
import { posts as devlogPosts } from "./projects/projectn5/devlog/posts";
|
||||||
import { posts as blogPosts } from "./blog/posts";
|
import { posts as blogPosts } from "./blog/posts";
|
||||||
import IndieButton from "$lib/components/indie-button.svelte";
|
// import IndieButton from "$lib/components/indie-button.svelte";
|
||||||
import { buttons } from "$lib/components/indie-button";
|
// import { buttons } from "$lib/components/indie-button";
|
||||||
import { getContext, onMount, setContext } from "svelte";
|
import { getContext, onMount, setContext } from "svelte";
|
||||||
import { getLatestFeedItem } from "./feed/feed";
|
import { getLatestPostDate } from "./feed/feed";
|
||||||
|
|
||||||
let latestDevlogDate = devlogPosts[0].post.date;
|
let latestDevlogDate = devlogPosts[0].post.date;
|
||||||
let latestBlogDate = blogPosts[0].post.date;
|
let latestBlogDate = blogPosts[0].post.date;
|
||||||
let latestFeedDate = $state("a");
|
|
||||||
|
|
||||||
let latestStatusContent = $state("fetching status...");
|
let latestStatusContent = $state("fetching status...");
|
||||||
let latestStatusTimestamp = $state("?");
|
let latestStatusTimestamp = $state("?");
|
||||||
|
|
||||||
async function getLatestFeedDate() {
|
|
||||||
await getLatestFeedItem(
|
|
||||||
).then((response) => {
|
|
||||||
// remove time, only keep date. thanks again sweden
|
|
||||||
latestFeedDate = new Date(
|
|
||||||
response.metadata.posted
|
|
||||||
).toLocaleString("sv-SE").substring(
|
|
||||||
0,
|
|
||||||
response.metadata.posted.indexOf("T")
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getLatestStatus() {
|
async function getLatestStatus() {
|
||||||
await fetch(`https://back.natconf.dev/netstatus/latestStatus`, {
|
await fetch(`https://back.natconf.dev/netstatus/latestStatus`, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
@@ -46,7 +32,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
getLatestFeedDate();
|
|
||||||
getLatestStatus();
|
getLatestStatus();
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
@@ -123,7 +108,7 @@
|
|||||||
{
|
{
|
||||||
title: "Creative Feed",
|
title: "Creative Feed",
|
||||||
description: `the small things I make find a home here.`,
|
description: `the small things I make find a home here.`,
|
||||||
latestUpdate: latestFeedDate,
|
latestUpdate: getLatestPostDate(),
|
||||||
img: "feed/banner.webp",
|
img: "feed/banner.webp",
|
||||||
altText: "A blue screen with the text 'how do you do art ? 1. face your fears 2. become your heroes'. The 'art' looks to have been edited in. The music artist Porter Robinson is standing in the bottom right corner.",
|
altText: "A blue screen with the text 'how do you do art ? 1. face your fears 2. become your heroes'. The 'art' looks to have been edited in. The music artist Porter Robinson is standing in the bottom right corner.",
|
||||||
link: "feed",
|
link: "feed",
|
||||||
@@ -193,7 +178,7 @@
|
|||||||
gap: 16px;
|
gap: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-container {
|
/* .button-container {
|
||||||
flex: 2;
|
flex: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,7 +186,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
} */
|
||||||
|
|
||||||
.webring {
|
.webring {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -46,16 +46,16 @@
|
|||||||
|
|
||||||
{@render pageButtons(data.currentPage)}
|
{@render pageButtons(data.currentPage)}
|
||||||
|
|
||||||
{#each data.feedEntries as entry}
|
{#each data.feedPosts as post}
|
||||||
<h2>{entry.title}</h2>
|
<h2>{post.metadata.title}</h2>
|
||||||
<p class="subtitle">{entry.subtitle}</p>
|
<p class="subtitle">{post.metadata.subtitle}</p>
|
||||||
<p class="subtitle">{entry.date}</p>
|
<p class="subtitle">{post.metadata.date}</p>
|
||||||
<svelte:component this={entry.content} />
|
<svelte:component this={post.content} />
|
||||||
{#if entry.images && entry.images.length > 0}
|
{#if post.metadata.images && post.metadata.images.length > 0}
|
||||||
<div class="image-gallery">
|
<div class="image-gallery">
|
||||||
{#each entry.images as i, index}
|
{#each post.metadata.images as i, index}
|
||||||
<a class="image-gallery-link" href="{entry.path}/{i}.webp">
|
<a class="image-gallery-link" href="{post.metadata.id}/{i.src}">
|
||||||
<img class="image-gallery-img" loading="lazy" src="{entry.path}/{i}.webp" alt={entry.imageAlts[index]}>
|
<img class="image-gallery-img" loading="lazy" src="{post.metadata.id}/{i.src}" alt={i.alt}>
|
||||||
</a>
|
</a>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,13 +1,9 @@
|
|||||||
import { entries } from './feed';
|
import { entries, type FeedEntry } from './feed';
|
||||||
|
|
||||||
interface FeedEntry {
|
interface FeedPost {
|
||||||
path: string;
|
path: string;
|
||||||
content: any;
|
content: any;
|
||||||
title: string;
|
metadata: FeedEntry;
|
||||||
subtitle: string;
|
|
||||||
date: string;
|
|
||||||
images: string[];
|
|
||||||
imageAlts: string[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let entriesPerPage = 8;
|
let entriesPerPage = 8;
|
||||||
@@ -21,7 +17,7 @@ export async function load({ params, url }) {
|
|||||||
|
|
||||||
// TODO check if index exceeds maximum permitted and redirect (to max page?)
|
// TODO check if index exceeds maximum permitted and redirect (to max page?)
|
||||||
|
|
||||||
let feedEntries: FeedEntry[] = [];
|
let feedPosts: FeedPost[] = [];
|
||||||
let start = (pageIndex - 1) * entriesPerPage;
|
let start = (pageIndex - 1) * entriesPerPage;
|
||||||
|
|
||||||
for (let i = start; i < start + entriesPerPage; i += 1) {
|
for (let i = start; i < start + entriesPerPage; i += 1) {
|
||||||
@@ -29,26 +25,23 @@ export async function load({ params, url }) {
|
|||||||
if (i >= entries.length) {
|
if (i >= entries.length) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
let pathArray = entries[i].split("/");
|
let e = entries[i];
|
||||||
|
let pathArray = e.id.split("/");
|
||||||
let path = `./${pathArray[0]}/${pathArray[1]}`;
|
let path = `./${pathArray[0]}/${pathArray[1]}`;
|
||||||
// Vite complains if I don't do this even though it's stupid
|
// Vite complains if I don't do this even though it's stupid
|
||||||
let page = await import(`./${pathArray[0]}/${pathArray[1]}.md`);
|
let page = await import(`./${pathArray[0]}/${pathArray[1]}.md`);
|
||||||
let md = page.metadata;
|
let md = page.metadata;
|
||||||
|
|
||||||
let date = md.date;
|
// let date = e.date;
|
||||||
// prevent SvelteKit from being smart and formatting a YYYY-MM-DD string to a Date object or similar
|
// prevent SvelteKit from being 'smart' and formatting a YYYY-MM-DD string to a Date object or similar
|
||||||
if ((date as string).endsWith("0Z")) {
|
// if ((date as string).endsWith("0Z")) {
|
||||||
date = date.split("T")[0];
|
// date = date.split("T")[0];
|
||||||
}
|
// }
|
||||||
|
|
||||||
feedEntries.push({
|
feedPosts.push({
|
||||||
path,
|
path,
|
||||||
content: page.default,
|
content: page.default,
|
||||||
title: md.title,
|
metadata: e,
|
||||||
subtitle: md.subtitle,
|
|
||||||
date: date,
|
|
||||||
images: md.images,
|
|
||||||
imageAlts: md.imageAlts,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,6 +51,6 @@ export async function load({ params, url }) {
|
|||||||
return {
|
return {
|
||||||
currentPage,
|
currentPage,
|
||||||
maxPages,
|
maxPages,
|
||||||
feedEntries,
|
feedPosts,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -1,28 +1,3 @@
|
|||||||
---
|
|
||||||
title: Nintendo Handheld Repairs
|
|
||||||
subtitle: it's been 8 years...
|
|
||||||
date: 2026-04-16 – 2026-04-23
|
|
||||||
posted: 2026-04-24
|
|
||||||
images:
|
|
||||||
- cardboard
|
|
||||||
- knifetoswitch
|
|
||||||
- 3dsopen
|
|
||||||
- thread
|
|
||||||
- threadsuccess
|
|
||||||
- 3dsfunctional
|
|
||||||
imageAlts:
|
|
||||||
- A Nintendo Switch with its back removed. The SD card reader connector is obstructed by a pink piece of cardboard.
|
|
||||||
- The SD card reader connector of a Nintendo Switch currently being stabbed with a knife in an attempt at repair.
|
|
||||||
- A 2011 Nintendo 3DS with its back covers removed on both the top and the bottom half.
|
|
||||||
- The hinge of a 3DS with some ribbon cables halfway pulled through.
|
|
||||||
- The hinge of a 3DS with three ribbon cables successfully pulled through.
|
|
||||||
- A functional 2011 Nintendo 3DS on the home screen, displaying the game "Zelda Four Swords Anniversary Edition"
|
|
||||||
# - The back of a Samsung Galaxy S20 FE lying face-down on a deskmat. Toothpicks, cotton pads, and a metal spudger are lying nearby.
|
|
||||||
# - A white phone back that's half-scratched off to reveal the clear plastic.
|
|
||||||
# - An entirely clear phone back.
|
|
||||||
# - A Samsung Galaxy S20 FE with a clear back inside a clear phone case. The phone has a sticker in the middle of the back that shows a lantern with leaves around it.
|
|
||||||
---
|
|
||||||
|
|
||||||
I disassembled my Switch because I wanted to check whether the battery was swollen inside. It's had some battery issues (although they seem to have gone away lately). During reassembly, I put too much force on the SD card reader and broke it. Ordered a new part, replaced it, but turns out I broke the board-side connector too. It doesn't grip the ribbon cable like it should. Squishing some cardboard in there to keep the cable connected and level with the board helped. I was worried it would fail, but it's been a couple of days now and it still works flawlessly. Just in time, too; I started playing the new Tomodachi Life and need the storage for all the screenshots and videos I'm capturing.
|
I disassembled my Switch because I wanted to check whether the battery was swollen inside. It's had some battery issues (although they seem to have gone away lately). During reassembly, I put too much force on the SD card reader and broke it. Ordered a new part, replaced it, but turns out I broke the board-side connector too. It doesn't grip the ribbon cable like it should. Squishing some cardboard in there to keep the cable connected and level with the board helped. I was worried it would fail, but it's been a couple of days now and it still works flawlessly. Just in time, too; I started playing the new Tomodachi Life and need the storage for all the screenshots and videos I'm capturing.
|
||||||
|
|
||||||
I also decided to tackle my 2011 3DS again. It broke in 2018: I was playing Super Mario Maker on the couch when it suddenly made a pop sound and turned off. When I disassembled it, I found that not only have I left the 3DS in a dismal state the last time I opened it -- most of the cables weren't even connected, not to mention the missing Y button, the removed battery due to swelling and the broken shoulder buttons --, but the ribbon cable connecting the speakers and top screen backlight had a *tear!* Finally, I knew what the problem may be!
|
I also decided to tackle my 2011 3DS again. It broke in 2018: I was playing Super Mario Maker on the couch when it suddenly made a pop sound and turned off. When I disassembled it, I found that not only have I left the 3DS in a dismal state the last time I opened it -- most of the cables weren't even connected, not to mention the missing Y button, the removed battery due to swelling and the broken shoulder buttons --, but the ribbon cable connecting the speakers and top screen backlight had a *tear!* Finally, I knew what the problem may be!
|
||||||
|
|||||||
@@ -1,20 +1,3 @@
|
|||||||
---
|
|
||||||
title: Transparent Phone Back
|
|
||||||
subtitle: nowhere to hide!
|
|
||||||
date: 2026-04-11 – 2026-04-12
|
|
||||||
posted: 2026-04-12
|
|
||||||
images:
|
|
||||||
- scratching
|
|
||||||
- halfway
|
|
||||||
- clear
|
|
||||||
- final
|
|
||||||
imageAlts:
|
|
||||||
- The back of a Samsung Galaxy S20 FE lying face-down on a deskmat. Toothpicks, cotton pads, and a metal spudger are lying nearby.
|
|
||||||
- A white phone back that's half-scratched off to reveal the clear plastic.
|
|
||||||
- An entirely clear phone back.
|
|
||||||
- A Samsung Galaxy S20 FE with a clear back inside a clear phone case. The phone has a sticker in the middle of the back that shows a lantern with leaves around it.
|
|
||||||
---
|
|
||||||
|
|
||||||
Inspired by Nothing phones and cool dbrand skins from way back, I gave my phone a clear back mod! I've grown a bit tired of the white back and wanted to do something cool and unique instead of just buying a new back and sticking that on there. I've been using this phone for 5 years and the glue has been struggling hard to hold onto the back, so I didn't feel bad doing this.
|
Inspired by Nothing phones and cool dbrand skins from way back, I gave my phone a clear back mod! I've grown a bit tired of the white back and wanted to do something cool and unique instead of just buying a new back and sticking that on there. I've been using this phone for 5 years and the glue has been struggling hard to hold onto the back, so I didn't feel bad doing this.
|
||||||
|
|
||||||
This was arduous and took a lot of time too (5 hours). I used a metal spudger, bamboo toothpicks, and cottons swabs and pads soaked in acetone-free nail polish remover to remove the two paint layers slowly but surely, being careful not to scratch the back too much. It revealed a slightly cloudly but actually decently transparent back that still preserved its slightly pearlescent purple glow!
|
This was arduous and took a lot of time too (5 hours). I used a metal spudger, bamboo toothpicks, and cottons swabs and pads soaked in acetone-free nail polish remover to remove the two paint layers slowly but surely, being careful not to scratch the back too much. It revealed a slightly cloudly but actually decently transparent back that still preserved its slightly pearlescent purple glow!
|
||||||
|
|||||||
@@ -1,8 +1,78 @@
|
|||||||
export let entries: string[] = [
|
export interface FeedEntry {
|
||||||
"electronics/nintendo-repairs",
|
id: string;
|
||||||
"electronics/trans-phone",
|
title: string;
|
||||||
|
subtitle: string;
|
||||||
|
date: string;
|
||||||
|
posted: string;
|
||||||
|
images: FeedImage[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FeedImage {
|
||||||
|
src: string;
|
||||||
|
alt: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export let entries: FeedEntry[] = [
|
||||||
|
{
|
||||||
|
id: "electronics/nintendo-repairs",
|
||||||
|
title: "Nintendo Handheld Repairs",
|
||||||
|
subtitle: "it's been 8 years...",
|
||||||
|
date: "2026-04-16 – 2026-04-23",
|
||||||
|
posted: "2026-04-24",
|
||||||
|
images: [
|
||||||
|
{
|
||||||
|
src: "cardboard.webp",
|
||||||
|
alt: "A Nintendo Switch with its back removed. The SD card reader connector is obstructed by a pink piece of cardboard.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: "knifetoswitch.webp",
|
||||||
|
alt: "The SD card reader connector of a Nintendo Switch currently being stabbed with a knife in an attempt at repair.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: "3dsopen.webp",
|
||||||
|
alt: "A 2011 Nintendo 3DS with its back covers removed on both the top and the bottom half.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: "thread.webp",
|
||||||
|
alt: "The hinge of a 3DS with some ribbon cables halfway pulled through.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: "threadsuccess.webp",
|
||||||
|
alt: "The hinge of a 3DS with three ribbon cables successfully pulled through.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: "3dsfunctional.webp",
|
||||||
|
alt: "A functional 2011 Nintendo 3DS on the home screen, displaying the game 'Zelda: Four Swords Anniversary Edition'",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "electronics/trans-phone",
|
||||||
|
title: "Transparent Phone Back",
|
||||||
|
subtitle: "nowhere to hide!",
|
||||||
|
date: "2026-04-11 – 2026-04-12",
|
||||||
|
posted: "2026-04-12",
|
||||||
|
images: [
|
||||||
|
{
|
||||||
|
src: "scratching.webp",
|
||||||
|
alt: "The back of a Samsung Galaxy S20 FE lying face-down on a deskmat. Toothpicks, cotton pads, and a metal spudger are lying nearby.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: "halfway.webp",
|
||||||
|
alt: "A white phone back that's half-scratched off to reveal the clear plastic.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: "clear.webp",
|
||||||
|
alt: "An entirely clear phone back.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: "final.webp",
|
||||||
|
alt: "A Samsung Galaxy S20 FE with a clear back inside a clear phone case. The phone has a sticker in the middle of the back that shows a lantern with leaves around it.",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export function getLatestFeedItem(): Promise<any> {
|
export function getLatestPostDate(): string {
|
||||||
return import(`./${entries[0]}.md`);
|
return entries[0].posted;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user