1
0
Fork 0
mirror of https://github.com/Findus23/HNReader.git synced 2024-09-19 15:23:44 +02:00

webapp and read more improvements

This commit is contained in:
Lukas Winkler 2021-04-09 17:40:24 +02:00
parent 701ec16835
commit f01bb84671
Signed by: lukas
GPG key ID: 54DE4D798D244853
12 changed files with 44 additions and 14 deletions

View file

@ -1,3 +1,4 @@
user_agent = "HNClient (in development)" user_agent = "HNClient (in development)"
debug = True debug = True
# redis_socket = "/run/redis-hnreader/redis-server.sock" # redis_socket = "/run/redis-hnreader/redis-server.sock"
redis_socket = False

View file

@ -39,8 +39,9 @@ class HNClient:
item["kids"] = kids item["kids"] = kids
return item return item
async def get_stories(self, page: str, limit=25, offset=0): async def get_stories(self, page: str, offset=0):
key = f"hnclient_stories_{page}_{limit}" limit = 25
key = f"hnclient_stories_{page}_{offset}"
cached = self.r.get(key) cached = self.r.get(key)
if cached: if cached:
return json.loads(cached) return json.loads(cached)
@ -48,7 +49,7 @@ class HNClient:
async with self.s.get(url) as response: async with self.s.get(url) as response:
response.raise_for_status() response.raise_for_status()
stories = await response.json() stories = await response.json()
stories = stories[offset:limit] stories = stories[offset:limit + offset]
tasks = [] tasks = []
for id in stories: for id in stories:
task = asyncio.ensure_future(self.get_item(id)) task = asyncio.ensure_future(self.get_item(id))

View file

@ -47,7 +47,8 @@ async def read(request: Request):
async def topstories(request: Request): async def topstories(request: Request):
data = await api.get_stories("topstories") offset = int(request.query_params.get("offset", 0))
data = await api.get_stories("topstories", offset=offset)
return JSONResponse(data) return JSONResponse(data)

View file

@ -2,9 +2,10 @@
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"> <meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<!-- <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">-->
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="Web site created using create-snowpack-app" />
<title>Snowpack App</title> <title>Snowpack App</title>
</head> </head>
<body> <body>

2
web/public/robots.txt Normal file
View file

@ -0,0 +1,2 @@
User-agent: *
Disallow: /

2
web/publish.sh Executable file
View file

@ -0,0 +1,2 @@
#!/bin/bash
rsync -aP build/* lw1.at:/srv/server/hnreader/static

View file

@ -1,11 +1,19 @@
import {createRouter, createWebHistory} from "vue-router"; import {createRouter, createWebHashHistory, createWebHistory} from "vue-router";
import Stories from './views/Stories.vue';
import About from './views/About.vue'; import About from './views/About.vue';
import Comments from "./views/Comments.vue"; import Comments from "./views/Comments.vue";
import Reader from "./views/Reader.vue"; import Reader from "./views/Reader.vue";
import {isInStandaloneMode} from "./utils";
let history;
if (isInStandaloneMode()) {
history = createWebHashHistory()
} else {
history = createWebHistory()
}
export const router = createRouter({ export const router = createRouter({
history: createWebHistory(), history: history,
routes: [ routes: [
{path: '/', name: "about", component: About}, {path: '/', name: "about", component: About},
{path: "/comments/:item", name: "comments", component: Comments, props: true}, {path: "/comments/:item", name: "comments", component: Comments, props: true},

View file

@ -7,6 +7,7 @@ html, body {
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
background: $color;
} }
@ -14,6 +15,7 @@ html, body {
height: 100%; height: 100%;
display: flex; display: flex;
width: 100%; width: 100%;
background: white;
} }
#sidebar .stories, #mainpane .comments, #mainpane .reader { #sidebar .stories, #mainpane .comments, #mainpane .reader {

View file

@ -84,6 +84,9 @@ pre {
background: lightgray; background: lightgray;
} }
} }
.load-more {
height: 50px;
}
} }
.comments { .comments {

View file

@ -31,3 +31,6 @@ export function dateToText(timestamp: number): string {
const date = new Date(timestamp * 1000) const date = new Date(timestamp * 1000)
return date.toLocaleString() return date.toLocaleString()
} }
// @ts-ignore
export const isInStandaloneMode = () => ('standalone' in window.navigator) && (window.navigator.standalone);

View file

@ -5,7 +5,7 @@
<div>{{ prettyDate }}</div> <div>{{ prettyDate }}</div>
<div>{{ prettyAuthors }}</div> <div>{{ prettyAuthors }}</div>
<div class="reader-html" v-html="readerData.html"></div> <div class="reader-html" v-html="readerData.html"></div>
<pre class="debug"><code>{{ readerData }}</code></pre> <!-- <pre class="debug"><code>{{ readerData }}</code></pre>-->
</div> </div>
</template> </template>

View file

@ -12,7 +12,8 @@
<div class="points">{{ story.score }}</div> <div class="points">{{ story.score }}</div>
</router-link> </router-link>
</div> </div>
<pre class="debug"><code>{{ stories }}</code></pre> <div class="load-more storywrapper" @click="loadStory">LOAD MORE</div>
<!-- <pre class="debug"><code>{{ stories }}</code></pre>-->
</div> </div>
</template> </template>
@ -20,23 +21,28 @@
import {defineComponent} from "vue"; import {defineComponent} from "vue";
import {Item} from "../interfaces"; import {Item} from "../interfaces";
import {dateToText} from "../utils"; import {dateToText} from "../utils";
const STORIES_PER_LOAD = 25;
export default defineComponent({ export default defineComponent({
name: "Stories", name: "Stories",
data() { data() {
return { return {
stories: [] as Item[] stories: [] as Item[],
} }
}, },
methods: { methods: {
loadStory(): void { loadStory(): void {
fetch("/api/topstories") fetch("/api/topstories?" + new URLSearchParams({
offset: this.stories.length.toString()
}))
.then(response => { .then(response => {
if (response.ok) { if (response.ok) {
return response.json() return response.json()
} }
return Promise.reject(response) return Promise.reject(response)
}) })
.then(data => (this.stories = data)) .then(data => (this.stories.push(...data)))
}, },
isActiveStory(item: Item): boolean { isActiveStory(item: Item): boolean {
return this.$route.params.item === item.id.toString() return this.$route.params.item === item.id.toString()