Default Comment Sort Setting

This commit is contained in:
spikecodes 2021-01-07 08:38:05 -08:00
parent 7e96bb3d80
commit 3444989f9a
13 changed files with 77 additions and 42 deletions

View File

@ -12,7 +12,7 @@ base64 = "0.13.0"
actix-web = { version = "3.3.2", features = ["rustls"] }
reqwest = { version = "0.10", default_features = false, features = ["rustls-tls"] }
askama = "0.10.5"
serde = "1.0.118"
serde = { version = "1.0.118", default_features = false, features = ["derive"] }
serde_json = "1.0"
async-recursion = "0.3.1"
url = "2.2.0"

View File

@ -80,9 +80,6 @@ async fn main() -> std::io::Result<()> {
.route("/r/{sub}/comments/{id}/{title}/{comment_id}/", web::get().to(post::item))
})
.bind(&address)
.map(|x| {
x
})
.unwrap_or_else(|_| panic!("Cannot bind to the address: {}", address))
.run()
.await

View File

@ -14,12 +14,18 @@ struct PostTemplate {
comments: Vec<Comment>,
post: Post,
sort: String,
layout: String,
}
pub async fn item(req: HttpRequest) -> HttpResponse {
// Build Reddit API path
let path = format!("{}.json?{}&raw_json=1", req.path(), req.query_string());
let sort = param(&path, "sort");
// Set sort to sort query parameter or otherwise default sort
let sort = if param(&path, "sort").is_empty() {
cookie(req.to_owned(), "comment_sort")
} else {
param(&path, "sort")
};
// Log the post ID being fetched in debug mode
#[cfg(debug_assertions)]
@ -34,14 +40,7 @@ pub async fn item(req: HttpRequest) -> HttpResponse {
let comments = parse_comments(&res[1]).await;
// Use the Post and Comment structs to generate a website to show users
let s = PostTemplate {
comments,
post,
sort,
layout: cookie(req, "layout"),
}
.render()
.unwrap();
let s = PostTemplate { comments, post, sort }.render().unwrap();
HttpResponse::Ok().content_type("text/html").body(s)
}
// If the Reddit API returns an error, exit and send error page to user

View File

@ -6,27 +6,33 @@ use time::{Duration, OffsetDateTime};
// STRUCTS
#[derive(Template)]
#[template(path = "settings.html", escape = "none")]
#[template(path = "settings.html")]
struct SettingsTemplate {
layout: String,
comment_sort: String,
}
#[derive(serde::Deserialize)]
pub struct Preferences {
pub struct SettingsForm {
layout: Option<String>,
comment_sort: Option<String>,
}
// FUNCTIONS
// Retrieve cookies from request "Cookie" header
pub async fn get(req: HttpRequest) -> HttpResponse {
let s = SettingsTemplate { layout: cookie(req, "layout") }.render().unwrap();
let s = SettingsTemplate {
layout: cookie(req.to_owned(), "layout"),
comment_sort: cookie(req, "comment_sort"),
}
.render()
.unwrap();
HttpResponse::Ok().content_type("text/html").body(s)
}
// Set cookies using response "Set-Cookie" header
pub async fn set(req: HttpRequest, form: Form<Preferences>) -> HttpResponse {
pub async fn set(req: HttpRequest, form: Form<SettingsForm>) -> HttpResponse {
let mut response = HttpResponse::Found();
match &form.layout {
@ -40,6 +46,17 @@ pub async fn set(req: HttpRequest, form: Form<Preferences>) -> HttpResponse {
None => response.del_cookie(&actix_web::HttpMessage::cookie(&req, "layout").unwrap()),
};
match &form.comment_sort {
Some(value) => response.cookie(
Cookie::build("comment_sort", value)
.path("/")
.http_only(true)
.expires(OffsetDateTime::now_utc() + Duration::weeks(52))
.finish(),
),
None => response.del_cookie(&actix_web::HttpMessage::cookie(&req, "comment_sort").unwrap()),
};
response
.content_type("text/html")
.set_header("Location", "/settings")

View File

@ -20,17 +20,16 @@ struct WikiTemplate {
sub: String,
wiki: String,
page: String,
layout: String,
}
// SERVICES
pub async fn page(req: HttpRequest) -> HttpResponse {
let path = format!("{}.json?{}", req.path(), req.query_string());
let sub = req.match_info().get("sub").unwrap_or("popular").to_string();
let sub_name = req.match_info().get("sub").unwrap_or("popular").to_string();
let sort = req.match_info().get("sort").unwrap_or("hot").to_string();
let sub_result = if !&sub.contains('+') && sub != "popular" {
subreddit(&sub).await.unwrap_or_default()
let sub = if !&sub_name.contains('+') && sub_name != "popular" {
subreddit(&sub_name).await.unwrap_or_default()
} else {
Subreddit::default()
};
@ -38,8 +37,8 @@ pub async fn page(req: HttpRequest) -> HttpResponse {
match fetch_posts(&path, String::new()).await {
Ok((posts, after)) => {
let s = SubredditTemplate {
sub: sub_result,
posts: posts,
sub,
posts,
sort: (sort, param(&path, "t")),
ends: (param(&path, "after"), after),
layout: cookie(req, "layout"),
@ -63,7 +62,6 @@ pub async fn wiki(req: HttpRequest) -> HttpResponse {
sub: sub.to_string(),
wiki: rewrite_url(res["data"]["content_html"].as_str().unwrap_or_default()),
page: page.to_string(),
layout: String::new(),
}
.render()
.unwrap();

View File

@ -94,7 +94,6 @@ pub struct Params {
#[template(path = "error.html", escape = "none")]
pub struct ErrorTemplate {
pub message: String,
pub layout: String,
}
//
@ -180,7 +179,9 @@ pub async fn fetch_posts(path: &str, fallback_title: String) -> Result<(Vec<Post
// Send a request to the url
match request(&path).await {
// If success, receive JSON in response
Ok(response) => { res = response; }
Ok(response) => {
res = response;
}
// If the Reddit API returns an error, exit this function
Err(msg) => return Err(msg),
}
@ -245,12 +246,7 @@ pub async fn fetch_posts(path: &str, fallback_title: String) -> Result<(Vec<Post
//
pub async fn error(msg: String) -> HttpResponse {
let body = ErrorTemplate {
message: msg,
layout: String::new(),
}
.render()
.unwrap_or_default();
let body = ErrorTemplate { message: msg }.render().unwrap_or_default();
HttpResponse::NotFound().content_type("text/html").body(body)
}

View File

@ -622,6 +622,7 @@ input[type="submit"]:hover { color: var(--accent); }
#prefs {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
padding: 20px;
@ -629,8 +630,20 @@ input[type="submit"]:hover { color: var(--accent); }
border-radius: 5px;
}
#prefs > select {
#prefs > div {
display: flex;
justify-content: space-between;
width: 100%;
align-items: center;
}
#prefs > div:not(:last-of-type) {
margin-bottom: 10px;
}
#prefs select {
border-radius: 5px;
box-shadow: var(--shadow);
margin-left: 20px;
}

View File

@ -11,7 +11,7 @@
<link rel="stylesheet" href="/style.css">
{% endblock %}
</head>
<body {% if layout != "" %}id="{{ layout }}"{% endif %}>
<body id="{% block layout %}{% endblock %}">
<!-- NAVIGATION BAR -->
<nav>
<p id="logo">

View File

@ -88,7 +88,7 @@
<!-- SORT FORM -->
<form id="sort">
<select name="sort">
{% call utils::options(sort, ["confidence", "top", "new", "controversial", "old"], "") %}
{% call utils::options(sort, ["confidence", "top", "new", "controversial", "old"], "confidence") %}
</select><input id="sort_submit" type="submit" value="&rarr;">
</form>

View File

@ -3,6 +3,8 @@
{% block title %}Libreddit: search results - {{ params.q }}{% endblock %}
{% block layout %}{% if layout != "" %}{{ layout }}{% endif %}{% endblock %}
{% block content %}
<div id="column_one">
<form id="search_sort">

View File

@ -11,11 +11,19 @@
<main>
<form id="settings" action="/settings" method="POST">
<div id="prefs">
<div id="layout">
<label for="layout">Layout:</label>
<select name="layout">
{% call utils::options(layout, ["card", "clean", "compact"], "clean") %}
</select>
</div>
<div id="comment_sort">
<label for="comment_sort">Default comment sort:</label>
<select name="comment_sort">
{% call utils::options(comment_sort, ["confidence", "top", "new", "controversial", "old"], "confidence") %}
</select>
</div>
</div>
<input id="save" type="submit" value="Save">
</form>
</main>

View File

@ -11,6 +11,8 @@
{% call utils::search(["/r/", sub.name.as_str()].concat(), "") %}
{% endblock %}
{% block layout %}{% if layout != "" %}{{ layout }}{% endif %}{% endblock %}
{% block body %}
<main>
<div id="column_one">

View File

@ -6,6 +6,9 @@
{% endblock %}
{% block title %}{{ user.name.replace("u/", "") }} (u/{{ user.name }}) - Libreddit{% endblock %}
{% block layout %}{% if layout != "" %}{{ layout }}{% endif %}{% endblock %}
{% block body %}
<main style="max-width: 1000px;">
<div id="column_one">