Skip to content

Commit

Permalink
refactor: improved hackernews demo
Browse files Browse the repository at this point in the history
  • Loading branch information
jonasgeiler committed Apr 20, 2024
1 parent 7f3aa6b commit 9450577
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 47 deletions.
2 changes: 1 addition & 1 deletion src/app.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
%sveltekit.head%
</head>
<body data-sveltekit-preload-data="hover">
<div>%sveltekit.body%</div>
<main id="app">%sveltekit.body%</main>
</body>
</html>
146 changes: 100 additions & 46 deletions src/routes/demos/hacker-news/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@
import VirtualList from '$lib/VirtualList.svelte';
import InfiniteLoading from 'svelte-infinite-loading';
const api = 'https://hn.algolia.com/api/v1/search_by_date?tags=story';
const api =
'https://hn.algolia.com/api/v1/search_by_date' +
'?tags=story' +
`&numericFilters=created_at_i<=${Math.floor(Date.now() / 1000)}`;
let page = 1;
let listHeight = 0;
let list = [];
function infiniteHandler({ detail: { loaded, complete } }) {
function infiniteHandler({ detail: { loaded, complete, error } }) {
fetch(`${api}&page=${page}`)
.then((response) => response.json())
.then((data) => {
Expand All @@ -19,56 +22,97 @@
} else {
complete();
}
});
})
.catch(() => error());
}
function formatSite(url) {
const domain = new URL(url).hostname;
return domain.startsWith('www.') ? domain.slice(4) : domain;
}
const dateFormatter = new Intl.RelativeTimeFormat('en', { style: 'long' });
function formatCreatedAt(createdAt) {
const seconds = Math.floor((new Date() - new Date(createdAt)) / 1000);
if (seconds <= 60) {
return dateFormatter.format(-seconds, 'second');
} else if (seconds <= 3600) {
return dateFormatter.format(-Math.floor(seconds / 60), 'minute');
} else if (seconds <= 86400) {
return dateFormatter.format(-Math.floor(seconds / 3600), 'hour');
} else if (seconds <= 604800) {
return dateFormatter.format(-Math.floor(seconds / 86400), 'day');
} else if (seconds <= 2592000) {
return dateFormatter.format(-Math.floor(seconds / 604800), 'week');
} else if (seconds <= 31536000) {
return dateFormatter.format(-Math.floor(seconds / 2592000), 'month');
} else {
return dateFormatter.format(-Math.floor(seconds / 31536000), 'year');
}
}
</script>

<div class="app">
<header class="hacker-news-header">
<a target="_blank" href="http://www.ycombinator.com/">
<img src="https://news.ycombinator.com/y18.gif" alt="Logo" />
</a>
<header class="hacker-news-header">
<a target="_blank" href="https://news.ycombinator.com/">
<img src="https://news.ycombinator.com/y18.svg" alt="Logo" />
<span>Hacker News</span>
</header>
</a>
</header>

<div class="list" bind:offsetHeight={listHeight}>
<VirtualList height={listHeight} itemSize={42} itemCount={list.length}>
<div slot="item" let:index let:style {style} class="hacker-news-item" data-num={index + 1}>
<a target="_blank" href={list[index].url}>{list[index].title}</a>
<p>
<span>{list[index].points}</span>
points by
<a target="_blank" href="https://news.ycombinator.com/user?id={list[index].author}"
>{list[index].author}</a
>
|
<a target="_blank" href="https://news.ycombinator.com/item?id={list[index].objectID}"
>{list[index].num_comments} comments</a
>
</p>
</div>
<div class="hacker-news-list" bind:offsetHeight={listHeight} style="height:100%">
<VirtualList height={listHeight} itemSize={42} itemCount={list.length}>
<div slot="item" let:index let:style {style} class="hacker-news-item" data-num={index + 1}>
<a
href={list[index].url || `https://news.ycombinator.com/item?id=${list[index].story_id}`}
target="_blank">{list[index].title}</a
>
{#if list[index].url}
<span>
(<a
href="https://news.ycombinator.com/from?site={formatSite(list[index].url)}"
target="_blank">{formatSite(list[index].url)}</a
>)</span
>
{/if}
<p>
{list[index].points} points by
<a href="https://news.ycombinator.com/user?id={list[index].author}" target="_blank"
>{list[index].author}</a
>
<a
title={list[index].created_at}
href="https://news.ycombinator.com/item?id={list[index].story_id}"
target="_blank">{formatCreatedAt(list[index].created_at)}</a
>
|
<a target="_blank" href="https://news.ycombinator.com/item?id={list[index].story_id}"
>{list[index].num_comments} comments</a
>
</p>
</div>

<div slot="footer">
<InfiniteLoading on:infinite={infiniteHandler} />
</div>
</VirtualList>
</div>
<div slot="footer">
<InfiniteLoading on:infinite={infiniteHandler} />
</div>
</VirtualList>
</div>

<style>
:global(html),
:global(body),
:global(#app) {
height: 100%;
}
:global(body) {
font-family: Verdana, Geneva, sans-serif;
font-size: 14px;
padding: 28px 0 0 0;
background-color: #f6f6ef;
}
.app {
height: 100%;
width: 100%;
display: flex;
}
.list {
.hacker-news-list {
flex-grow: 1;
}
.list :global(.virtual-list-wrapper) {
.hacker-news-list :global(.virtual-list-wrapper) {
overflow: visible;
overflow-x: hidden;
white-space: nowrap;
Expand All @@ -82,15 +126,17 @@
line-height: 14px;
background-color: #f60;
}
.hacker-news-header img {
.hacker-news-header > a {
text-decoration: none;
}
.hacker-news-header > a > img {
border: 1px solid #fff;
vertical-align: middle;
}
.hacker-news-header span {
font-family: Verdana, Geneva, sans-serif;
font-size: 14px;
.hacker-news-header > a > span {
font-weight: bold;
vertical-align: middle;
color: #fff;
}
.hacker-news-item {
padding: 10px 10px 10px 40px;
Expand All @@ -108,18 +154,26 @@
.hacker-news-item > a {
color: #333;
}
.hacker-news-item > a:hover {
.hacker-news-item > a:hover,
.hacker-news-item > a:active {
color: #000;
}
.hacker-news-item p {
.hacker-news-item > a:visited {
color: #888;
}
.hacker-news-item > p {
margin: 0;
font-size: 12px;
}
.hacker-news-item p,
.hacker-news-item p a {
.hacker-news-item > span,
.hacker-news-item > span > a,
.hacker-news-item > p,
.hacker-news-item > p > a {
color: #888;
}
.hacker-news-item p a:not(:hover) {
.hacker-news-item > a:not(:hover):not(:active),
.hacker-news-item > span > a:not(:hover):not(:active),
.hacker-news-item > p > a:not(:hover):not(:active) {
text-decoration: none;
}
</style>

0 comments on commit 9450577

Please sign in to comment.