show post preview

This commit is contained in:
Aravinth Manivannan 2021-11-07 13:22:10 +05:30
parent 59d0dd3a84
commit 33f02c2ece
Signed by untrusted user: realaravinth
GPG key ID: AD9F0F08E855ED88
7 changed files with 177 additions and 53 deletions

View file

@ -3,11 +3,18 @@ query GetPost($id: ID!) {
title
createdAt
readingTime
uniqueSlug
creator {
name
id
imageId
}
previewImage {
id
}
previewContent {
subtitle
}
content {
bodyModel {
paragraphs {

View file

@ -3,63 +3,84 @@ type Query {
}
schema {
query: Query
query: Query
}
type Paragraphs {
text: String!
type: String!
href: String
layout: String
iframe: IFrame
metadata: MetaData
markups: [MarkUp! ]!
type Paragraphs {
text: String!
type: String!
href: String
layout: String
iframe: IFrame
metadata: MetaData
markups: [MarkUp!]!
}
type MarkUp {
title: String
type: String!
href: String
userId: String
start: Int!
end: Int!
anchorType: String
title: String
type: String!
href: String
userId: String
start: Int!
end: Int!
anchorType: String
}
type IFrame {
mediaResource: MediaResource
mediaResource: MediaResource
}
type MediaResource{
href: String!
iframeSrc: String!
iframeWidth: Int!
iframeHeight: Int
type MediaResource {
href: String!
iframeSrc: String!
iframeWidth: Int!
iframeHeight: Int
}
type MetaData {
id: String!
originalWidth: Int
originalHeight: Int
id: String!
originalWidth: Int
originalHeight: Int
}
type BodyModel { paragraphs: [Paragraphs! ]! }
type Content { bodyModel: BodyModel! }
type User { id: String! name: String! imageId: String! }
type Post {
id: ID!
readingTime: Float!
title: String!
createdAt: Int!
content: Content!
creator: User!
type BodyModel {
paragraphs: [Paragraphs!]!
}
type Data { post: Post }
type Content {
bodyModel: BodyModel!
}
type AutogeneratedMainType { data: Data }
type User {
id: String!
name: String!
imageId: String!
}
type Post {
id: ID!
readingTime: Float!
title: String!
createdAt: Int!
content: Content!
creator: User!
previewImage: PreviewImage
previewContent: PreviewContent
uniqueSlug: String!
}
type PreviewImage {
id: String
}
type PreviewContent {
subtitle: String!
}
type Data {
post: Post
}
type AutogeneratedMainType {
data: Data
}

View file

@ -26,7 +26,7 @@ use sled::{Db, Tree};
use crate::proxy::StringUtils;
use crate::SETTINGS;
const POST_CACHE_VERSION: usize = 1;
const POST_CACHE_VERSION: usize = 2;
const GIST_CACHE_VERSION: usize = 1;
#[derive(Clone)]
@ -53,6 +53,10 @@ impl PostResp {
pub fn get_gist_id<'a>(&self, url: &'a str) -> &'a str {
url.split('/').last().unwrap()
}
pub fn get_subtitle(&self) -> &str {
self.preview_content.as_ref().unwrap().subtitle.as_str()
}
}
#[derive(Deserialize, Serialize)]
@ -111,7 +115,7 @@ impl Data {
for (tree, key, current_version) in trees {
if let Ok(Some(v)) = tree.get(key) {
let version = bincode::deserialize::<usize>(&v[..]).unwrap();
let clean = !(version == current_version);
let clean = version != current_version;
if clean {
log::info!(

View file

@ -17,6 +17,7 @@
use std::ops::{Bound, RangeBounds};
use actix_web::{http::header, web, HttpResponse, Responder};
use chrono::{TimeZone, Utc};
use futures::future::join_all;
use reqwest::header::CONTENT_TYPE;
use sailfish::TemplateOnce;
@ -110,6 +111,9 @@ impl StringUtils for str {
#[template(rm_whitespace = true)]
pub struct Post {
pub data: PostResp,
pub date: String,
pub preview_img: String,
pub reading_time: usize,
pub id: String,
pub gists: Option<Vec<(String, crate::data::GistContent)>>,
}
@ -166,7 +170,7 @@ async fn page(path: web::Path<(String, String)>, data: AppData) -> impl Responde
.unwrap()
.href;
if src.contains("gist.github.com") {
let gist_id = post_data.get_gist_id(&src);
let gist_id = post_data.get_gist_id(src);
let fut = data.get_gist(gist_id.to_owned());
futs.push(fut);
}
@ -179,10 +183,27 @@ async fn page(path: web::Path<(String, String)>, data: AppData) -> impl Responde
Some(x)
};
let date = Utc
.timestamp_millis(post_data.created_at)
.format("%b %e, %Y")
.to_string();
let reading_time = post_data.reading_time.floor() as usize;
let preview_img = post_data
.preview_image
.as_ref()
.unwrap()
.id
.as_ref()
.unwrap();
let preview_img = crate::V1_API_ROUTES.proxy.get_medium_asset(preview_img);
let page = Post {
id: id.to_owned(),
data: post_data,
date,
gists,
reading_time,
preview_img,
};
let page = page.render_once().unwrap();

View file

@ -1,4 +1,4 @@
<. let gist_id = data.get_gist_id(&src); .>
<. let gist_id = data.get_gist_id(src); .>
<. let (_, gist)= gists.as_ref().unwrap().iter().find(|(id, _)| id == gist_id).as_ref().unwrap(); .>
<. for file in &gist.files {.>
<code> <.= file.get_html_content() .> </code>

View file

@ -1,15 +1,10 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title><.= data.title .></title>
<. include!("./post_meta.html"); .>
</head>
<body>
<main class="container">
<. use chrono::{TimeZone, Utc}; .>
<. let dt = Utc.timestamp_millis(data.created_at); .>
<. let date = dt.format("%b %e, %Y").to_string(); .>
<h1><.= data.title .></h1>
<p class="meta">
<a class="author" href="https://medium.com/u/<.= data.creator.id .>" rel="noreferrer">
@ -20,7 +15,7 @@
/>
<.= data.creator.name .></a
>
on <.= &date .> &#183; <.= data.reading_time.floor() as usize .> min read
on <.= &date .> &#183; <.= reading_time .> min read
</p>
<article>
<. let paragraphs = &data.content.body_model.paragraphs; .>

76
templates/post_meta.html Normal file
View file

@ -0,0 +1,76 @@
<title><.= data.title .> | by <.= data.creator.name .> | <.= &date .></title>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width,minimum-scale=1,initial-scale=1,maximum-scale=1"
/>
<meta name="theme-color" content="#000000" />
<meta name="twitter:app:name:iphone" content="libmedium" />
<meta property="og:site_name" content="libmedium" />
<meta property="og:type" content="article" />
<meta property="article:published_time" content="2021-10-21T10:54:12.523Z" />
<meta
name="title"
content="Moscow state university network built by students | by Pavel Safronov | Oct, 2021 | libmedium"
/>
<meta property="og:title" content="<.= data.title .>" />
<meta property="twitter:title" content="<.= data.title .>" />
<meta name="twitter:app:url:iphone" content="medium://p/211539855cf9" />
<meta data-rh="true" property="al:android:app_name" content="libmedium" />
<meta name="description" content="<.= data.get_subtitle() .>" />
<meta property="og:description" content="<.= data.get_subtitle() .>" />
<meta property="twitter:description" content="<.= data.get_subtitle() .>" />
<meta
property="og:url"
content="http://<.= &*crate::SETTINGS.server.domain .>/<.= data.creator.name .>/<.= data.unique_slug .>"
/>
<meta property="og:image" content="<.= preview_img .>" />
<meta name="twitter:image:src" content="<.= preview_img .>" />
<meta name="twitter:card" content="summary_large_image" />
<meta
property="article:author"
content="https://medium.com/@<.= data.creator.id .>"
/>
<!--
<meta name="twitter:creator" content="@username" />
-->
<meta name="author" content="<.= data.creator.name .>" />
<meta
data-rh="true"
name="robots"
content="index,follow,max-image-preview:large"
/>
<meta name="twitter:label1" content="Reading time" />
<meta name="twitter:data1" content="<.= reading_time .>min read" />
<!--
<link
rel="apple-touch-icon"
sizes="152x152"
href="https://miro.medium.com/fit/c/152/152/1*sHhtYhaCe2Uc3IU0IgKwIQ.png"
/>
<link
rel="apple-touch-icon"
sizes="120x120"
href="https://miro.medium.com/fit/c/120/120/1*sHhtYhaCe2Uc3IU0IgKwIQ.png"
/>
<link
rel="apple-touch-icon"
sizes="76x76"
href="https://miro.medium.com/fit/c/76/76/1*sHhtYhaCe2Uc3IU0IgKwIQ.png"
/>
<link
rel="apple-touch-icon"
sizes="60x60"
href="https://miro.medium.com/fit/c/60/60/1*sHhtYhaCe2Uc3IU0IgKwIQ.png"
/>
<link
rel="mask-icon"
href="https://cdn-static-1.medium.com/_/fp/icons/libmedium-Avatar-500x500.svg"
color="#171717"
/>
-->
<link rel="author" href="https://medium.com/<.= data.creator.name .>" />
<link
rel="canonical"
href="http://<.= &*crate::SETTINGS.server.domain .>/<.= data.creator.name .>/<.= data.unique_slug .>"
/>