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:
parent
701ec16835
commit
f01bb84671
12 changed files with 44 additions and 14 deletions
|
@ -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
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
2
web/public/robots.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
User-agent: *
|
||||||
|
Disallow: /
|
2
web/publish.sh
Executable file
2
web/publish.sh
Executable file
|
@ -0,0 +1,2 @@
|
||||||
|
#!/bin/bash
|
||||||
|
rsync -aP build/* lw1.at:/srv/server/hnreader/static
|
|
@ -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},
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -84,6 +84,9 @@ pre {
|
||||||
background: lightgray;
|
background: lightgray;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.load-more {
|
||||||
|
height: 50px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.comments {
|
.comments {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
|
|
Loading…
Reference in a new issue