Remove useless pagination routes (#351)

Rocket 0.4 let us have routes with optional query parameter
This commit is contained in:
Baptiste Gelez 2018-12-13 22:20:19 +01:00 committed by GitHub
parent e139008d35
commit b0089e59b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 105 additions and 155 deletions

View File

@ -79,7 +79,6 @@ fn main() {
rocket::ignite()
.mount("/", routes![
routes::blogs::paginated_details,
routes::blogs::details,
routes::blogs::activity_details,
routes::blogs::outbox,
@ -93,17 +92,12 @@ fn main() {
routes::comments::activity_pub,
routes::instance::index,
routes::instance::paginated_local,
routes::instance::local,
routes::instance::paginated_feed,
routes::instance::feed,
routes::instance::paginated_federated,
routes::instance::federated,
routes::instance::admin,
routes::instance::admin_instances,
routes::instance::admin_instances_paginated,
routes::instance::admin_users,
routes::instance::admin_users_paginated,
routes::instance::ban,
routes::instance::toggle_block,
routes::instance::update_settings,
@ -122,12 +116,10 @@ fn main() {
routes::medias::delete,
routes::medias::set_avatar,
routes::notifications::paginated_notifications,
routes::notifications::notifications,
routes::notifications::notifications_auth,
routes::posts::details,
routes::posts::details_response,
routes::posts::activity_details,
routes::posts::edit,
routes::posts::update,
@ -142,20 +134,17 @@ fn main() {
routes::search::search,
routes::session::new,
routes::session::new_message,
routes::session::create,
routes::session::delete,
routes::static_files,
routes::tags::tag,
routes::tags::paginated_tag,
routes::user::me,
routes::user::details,
routes::user::dashboard,
routes::user::dashboard_auth,
routes::user::followers_paginated,
routes::user::followers,
routes::user::edit,
routes::user::edit_auth,

View File

@ -24,7 +24,8 @@ use template_utils::Ructe;
use Searcher;
#[get("/~/<name>?<page>", rank = 2)]
pub fn paginated_details(intl: I18n, name: String, conn: DbConn, user: Option<User>, page: Page) -> Result<Ructe, Ructe> {
pub fn details(intl: I18n, name: String, conn: DbConn, user: Option<User>, page: Option<Page>) -> Result<Ructe, Ructe> {
let page = page.unwrap_or_default();
let blog = Blog::find_by_fqn(&*conn, &name)
.ok_or_else(|| render!(errors::not_found(&(&*conn, &intl.catalog, user.clone()))))?;
let posts = Post::blog_page(&*conn, &blog, page.limits());
@ -44,11 +45,6 @@ pub fn paginated_details(intl: I18n, name: String, conn: DbConn, user: Option<Us
)))
}
#[get("/~/<name>", rank = 3)]
pub fn details(intl: I18n, name: String, conn: DbConn, user: Option<User>) -> Result<Ructe, Ructe> {
paginated_details(intl, name, conn, user, Page::first())
}
#[get("/~/<name>", rank = 1)]
pub fn activity_details(name: String, conn: DbConn, _ap: ApRequest) -> Option<ActivityStream<CustomGroup>> {
let blog = Blog::find_local(&*conn, &name)?;
@ -118,7 +114,7 @@ pub fn create(conn: DbConn, form: LenientForm<NewBlogForm>, user: User, intl: I1
is_owner: true
});
Ok(Redirect::to(uri!(details: name = slug.clone())))
Ok(Redirect::to(uri!(details: name = slug.clone(), page = _)))
} else {
Err(render!(blogs::new(
&(&*conn, &intl.catalog, Some(user)),

View File

@ -57,7 +57,7 @@ pub fn create(blog_name: String, slug: String, form: LenientForm<NewCommentForm>
let user_clone = user.clone();
worker.execute(move || broadcast(&user_clone, new_comment, dest));
Redirect::to(uri!(super::posts::details: blog = blog_name, slug = slug))
Redirect::to(uri!(super::posts::details: blog = blog_name, slug = slug, responding_to = _))
})
.map_err(|errors| {
// TODO: de-duplicate this code

View File

@ -25,13 +25,13 @@ use Searcher;
pub fn index(conn: DbConn, user: Option<User>, intl: I18n) -> Ructe {
match Instance::get_local(&*conn) {
Some(inst) => {
let federated = Post::get_recents_page(&*conn, Page::first().limits());
let local = Post::get_instance_page(&*conn, inst.id, Page::first().limits());
let federated = Post::get_recents_page(&*conn, Page::default().limits());
let local = Post::get_instance_page(&*conn, inst.id, Page::default().limits());
let user_feed = user.clone().map(|user| {
let followed = user.get_following(&*conn);
let mut in_feed = followed.into_iter().map(|u| u.id).collect::<Vec<i32>>();
in_feed.push(user.id);
Post::user_feed_page(&*conn, in_feed, Page::first().limits())
Post::user_feed_page(&*conn, in_feed, Page::default().limits())
});
render!(instance::index(
@ -53,7 +53,8 @@ pub fn index(conn: DbConn, user: Option<User>, intl: I18n) -> Ructe {
}
#[get("/local?<page>")]
pub fn paginated_local(conn: DbConn, user: Option<User>, page: Page, intl: I18n) -> Ructe {
pub fn local(conn: DbConn, user: Option<User>, page: Option<Page>, intl: I18n) -> Ructe {
let page = page.unwrap_or_default();
let instance = Instance::get_local(&*conn).expect("instance::paginated_local: local instance not found error");
let articles = Post::get_instance_page(&*conn, instance.id, page.limits());
render!(instance::local(
@ -65,18 +66,9 @@ pub fn paginated_local(conn: DbConn, user: Option<User>, page: Page, intl: I18n)
))
}
#[get("/local")]
pub fn local(conn: DbConn, user: Option<User>, intl: I18n) -> Ructe {
paginated_local(conn, user, Page::first(), intl)
}
#[get("/feed")]
pub fn feed(conn: DbConn, user: User, intl: I18n) -> Ructe {
paginated_feed(conn, user, Page::first(), intl)
}
#[get("/feed?<page>")]
pub fn paginated_feed(conn: DbConn, user: User, page: Page, intl: I18n) -> Ructe {
pub fn feed(conn: DbConn, user: User, page: Option<Page>, intl: I18n) -> Ructe {
let page = page.unwrap_or_default();
let followed = user.get_following(&*conn);
let mut in_feed = followed.into_iter().map(|u| u.id).collect::<Vec<i32>>();
in_feed.push(user.id);
@ -89,13 +81,9 @@ pub fn paginated_feed(conn: DbConn, user: User, page: Page, intl: I18n) -> Ructe
))
}
#[get("/federated")]
pub fn federated(conn: DbConn, user: Option<User>, intl: I18n) -> Ructe {
paginated_federated(conn, user, Page::first(), intl)
}
#[get("/federated?<page>")]
pub fn paginated_federated(conn: DbConn, user: Option<User>, page: Page, intl: I18n) -> Ructe {
pub fn federated(conn: DbConn, user: Option<User>, page: Option<Page>, intl: I18n) -> Ructe {
let page = page.unwrap_or_default();
let articles = Post::get_recents_page(&*conn, page.limits());
render!(instance::federated(
&(&*conn, &intl.catalog, user),
@ -156,13 +144,9 @@ pub fn update_settings(conn: DbConn, admin: Admin, form: LenientForm<InstanceSet
})
}
#[get("/admin/instances")]
pub fn admin_instances(admin: Admin, conn: DbConn, intl: I18n) -> Ructe {
admin_instances_paginated(admin, conn, Page::first(), intl)
}
#[get("/admin/instances?<page>")]
pub fn admin_instances_paginated(admin: Admin, conn: DbConn, page: Page, intl: I18n) -> Ructe {
pub fn admin_instances(admin: Admin, conn: DbConn, page: Option<Page>, intl: I18n) -> Ructe {
let page = page.unwrap_or_default();
let instances = Instance::page(&*conn, page.limits());
render!(instance::list(
&(&*conn, &intl.catalog, Some(admin.0)),
@ -179,16 +163,12 @@ pub fn toggle_block(_admin: Admin, conn: DbConn, id: i32) -> Redirect {
inst.toggle_block(&*conn);
}
Redirect::to(uri!(admin_instances))
}
#[get("/admin/users")]
pub fn admin_users(admin: Admin, conn: DbConn, intl: I18n) -> Ructe {
admin_users_paginated(admin, conn, Page::first(), intl)
Redirect::to(uri!(admin_instances: page = _))
}
#[get("/admin/users?<page>")]
pub fn admin_users_paginated(admin: Admin, conn: DbConn, page: Page, intl: I18n) -> Ructe {
pub fn admin_users(admin: Admin, conn: DbConn, page: Option<Page>, intl: I18n) -> Ructe {
let page = page.unwrap_or_default();
render!(instance::users(
&(&*conn, &intl.catalog, Some(admin.0)),
User::get_local_page(&*conn, page.limits()),
@ -202,7 +182,7 @@ pub fn ban(_admin: Admin, conn: DbConn, id: i32, searcher: Searcher) -> Redirect
if let Some(u) = User::get(&*conn, id) {
u.delete(&*conn, &searcher);
}
Redirect::to(uri!(admin_users))
Redirect::to(uri!(admin_users: page = _))
}
#[post("/inbox", data = "<data>")]

View File

@ -36,7 +36,7 @@ pub fn create(blog: String, slug: String, user: User, conn: DbConn, worker: Work
worker.execute(move || broadcast(&user, delete_act, dest));
}
Some(Redirect::to(uri!(super::posts::details: blog = blog, slug = slug)))
Some(Redirect::to(uri!(super::posts::details: blog = blog, slug = slug, responding_to = _)))
}
#[post("/~/<blog>/<slug>/like", rank = 2)]

View File

@ -1,6 +1,6 @@
use atom_syndication::{ContentBuilder, Entry, EntryBuilder, LinkBuilder, Person, PersonBuilder};
use rocket::{
http::RawStr,
http::{RawStr, uri::{FromUriParam, Query}},
request::FromFormValue,
response::NamedFile,
};
@ -10,7 +10,7 @@ use plume_models::{Connection, posts::Post};
const ITEMS_PER_PAGE: i32 = 12;
#[derive(Copy, Clone)]
#[derive(Copy, Clone, UriDisplayQuery)]
pub struct Page(i32);
impl<'v> FromFormValue<'v> for Page {
@ -23,11 +23,15 @@ impl<'v> FromFormValue<'v> for Page {
}
}
impl Page {
pub fn first() -> Page {
Page(1)
}
impl FromUriParam<Query, Option<Page>> for Page {
type Target = Page;
fn from_uri_param(val: Option<Page>) -> Page {
val.unwrap_or_default()
}
}
impl Page {
/// Computes the total number of pages needed to display n_items
pub fn total(n_items: i32) -> i32 {
if n_items % ITEMS_PER_PAGE == 0 {
@ -42,6 +46,12 @@ impl Page {
}
}
impl Default for Page {
fn default() -> Self {
Page(1)
}
}
pub fn post_to_atom(post: Post, conn: &Connection) -> Entry {
EntryBuilder::default()
.title(format!("<![CDATA[{}]]>", post.title))

View File

@ -7,7 +7,8 @@ use routes::Page;
use template_utils::Ructe;
#[get("/notifications?<page>")]
pub fn paginated_notifications(conn: DbConn, user: User, page: Page, intl: I18n) -> Ructe {
pub fn notifications(conn: DbConn, user: User, page: Option<Page>, intl: I18n) -> Ructe {
let page = page.unwrap_or_default();
render!(notifications::index(
&(&*conn, &intl.catalog, Some(user.clone())),
Notification::page_for_user(&*conn, &user, page.limits()),
@ -16,15 +17,10 @@ pub fn paginated_notifications(conn: DbConn, user: User, page: Page, intl: I18n)
))
}
#[get("/notifications")]
pub fn notifications(conn: DbConn, user: User, intl: I18n) -> Ructe {
paginated_notifications(conn, user, Page::first(), intl)
}
#[get("/notifications", rank = 2)]
pub fn notifications_auth(i18n: I18n) -> Flash<Redirect>{
#[get("/notifications?<page>", rank = 2)]
pub fn notifications_auth(i18n: I18n, page: Option<Page>) -> Flash<Redirect>{
utils::requires_login(
i18n!(i18n.catalog, "You need to be logged in order to see your notifications"),
uri!(notifications)
uri!(notifications: page = page)
)
}

View File

@ -26,14 +26,8 @@ use template_utils::Ructe;
use Worker;
use Searcher;
// See: https://github.com/SergioBenitez/Rocket/pull/454
#[get("/~/<blog>/<slug>", rank = 5)]
pub fn details(blog: String, slug: String, conn: DbConn, user: Option<User>, intl: I18n) -> Result<Ructe, Ructe> {
details_response(blog, slug, conn, user, None, intl)
}
#[get("/~/<blog>/<slug>?<responding_to>", rank = 4)]
pub fn details_response(blog: String, slug: String, conn: DbConn, user: Option<User>, responding_to: Option<i32>, intl: I18n) -> Result<Ructe, Ructe> {
pub fn details(blog: String, slug: String, conn: DbConn, user: Option<User>, responding_to: Option<i32>, intl: I18n) -> Result<Ructe, Ructe> {
let blog = Blog::find_by_fqn(&*conn, &blog).ok_or_else(|| render!(errors::not_found(&(&*conn, &intl.catalog, user.clone()))))?;
let post = Post::find_by_slug(&*conn, &slug, blog.id).ok_or_else(|| render!(errors::not_found(&(&*conn, &intl.catalog, user.clone()))))?;
if post.published || post.get_authors(&*conn).into_iter().any(|a| a.id == user.clone().map(|u| u.id).unwrap_or(0)) {
@ -205,7 +199,7 @@ pub fn update(blog: String, slug: String, user: User, conn: DbConn, form: Lenien
if errors.is_empty() {
if !user.is_author_in(&*conn, &b) {
// actually it's not "Ok"…
Ok(Redirect::to(uri!(super::blogs::details: name = blog)))
Ok(Redirect::to(uri!(super::blogs::details: name = blog, page = _)))
} else {
let (content, mentions, hashtags) = utils::md_to_html(form.content.to_string().as_ref());
@ -252,7 +246,7 @@ pub fn update(blog: String, slug: String, user: User, conn: DbConn, form: Lenien
}
}
Ok(Redirect::to(uri!(details: blog = blog, slug = new_slug)))
Ok(Redirect::to(uri!(details: blog = blog, slug = new_slug, responding_to = _)))
}
} else {
let medias = Media::for_user(&*conn, user.id);
@ -313,7 +307,7 @@ pub fn create(blog_name: String, form: LenientForm<NewPostForm>, user: User, con
if errors.is_empty() {
if !user.is_author_in(&*conn, &blog) {
// actually it's not "Ok"…
Ok(Redirect::to(uri!(super::blogs::details: name = blog_name)))
Ok(Redirect::to(uri!(super::blogs::details: name = blog_name, page = _)))
} else {
let (content, mentions, hashtags) = utils::md_to_html(form.content.to_string().as_ref());
@ -367,7 +361,7 @@ pub fn create(blog_name: String, form: LenientForm<NewPostForm>, user: User, con
worker.execute(move || broadcast(&user, act, dest));
}
Ok(Redirect::to(uri!(details: blog = blog_name, slug = slug)))
Ok(Redirect::to(uri!(details: blog = blog_name, slug = slug, responding_to = _)))
}
} else {
let medias = Media::for_user(&*conn, user.id);
@ -391,15 +385,15 @@ pub fn delete(blog_name: String, slug: String, conn: DbConn, user: User, worker:
if let Some(post) = post {
if !post.get_authors(&*conn).into_iter().any(|a| a.id == user.id) {
Redirect::to(uri!(details: blog = blog_name.clone(), slug = slug.clone()))
Redirect::to(uri!(details: blog = blog_name.clone(), slug = slug.clone(), responding_to = _))
} else {
let dest = User::one_by_instance(&*conn);
let delete_activity = post.delete(&(&conn, &searcher));
worker.execute(move || broadcast(&user, delete_activity, dest));
Redirect::to(uri!(super::blogs::details: name = blog_name))
Redirect::to(uri!(super::blogs::details: name = blog_name, page = _))
}
} else {
Redirect::to(uri!(super::blogs::details: name = blog_name))
Redirect::to(uri!(super::blogs::details: name = blog_name, page = _))
}
}

View File

@ -37,7 +37,7 @@ pub fn create(blog: String, slug: String, user: User, conn: DbConn, worker: Work
worker.execute(move || broadcast(&user, delete_act, dest));
}
Some(Redirect::to(uri!(super::posts::details: blog = blog, slug = slug)))
Some(Redirect::to(uri!(super::posts::details: blog = blog, slug = slug, responding_to = _)))
}
#[post("/~/<blog>/<slug>/reshare", rank=1)]

View File

@ -55,7 +55,7 @@ macro_rules! param_to_query {
#[get("/search?<query..>")]
pub fn search(query: Form<SearchQuery>, conn: DbConn, searcher: Searcher, user: Option<User>, intl: I18n) -> Ructe {
let page = query.page.unwrap_or(Page::first());
let page = query.page.unwrap_or_default();
let mut parsed_query = Query::from_str(&query.q.as_ref().map(|q| q.as_str()).unwrap_or_default());
param_to_query!(query, parsed_query; normal: title, subtitle, content, tag,
@ -71,7 +71,7 @@ pub fn search(query: Form<SearchQuery>, conn: DbConn, searcher: Searcher, user:
))
} else {
let res = searcher.search_document(&conn, parsed_query, page.limits());
let next_page = if res.is_empty() { 0 } else { page.0+1 };
let next_page = if res.is_empty() { 0 } else { page.0 + 1 };
render!(search::result(
&(&*conn, &intl.catalog, user),
&str_query,

View File

@ -14,27 +14,16 @@ use plume_models::{
users::{User, AUTH_COOKIE}
};
#[get("/login")]
pub fn new(user: Option<User>, conn: DbConn, intl: I18n) -> Ructe {
render!(session::login(
&(&*conn, &intl.catalog, user),
None,
&LoginForm::default(),
ValidationErrors::default()
))
}
#[get("/login?<m>")]
pub fn new_message(user: Option<User>, m: String, conn: DbConn, intl: I18n) -> Ructe {
pub fn new(user: Option<User>, conn: DbConn, m: Option<String>, intl: I18n) -> Ructe {
render!(session::login(
&(&*conn, &intl.catalog, user),
Some(m),
m,
&LoginForm::default(),
ValidationErrors::default()
))
}
#[derive(Default, FromForm, Validate, Serialize)]
pub struct LoginForm {
#[validate(length(min = "1", message = "We need an email or a username to identify you"))]

View File

@ -8,13 +8,9 @@ use plume_models::{
use routes::Page;
use template_utils::Ructe;
#[get("/tag/<name>")]
pub fn tag(user: Option<User>, conn: DbConn, name: String, intl: I18n) -> Ructe {
paginated_tag(user, conn, name, Page::first(), intl)
}
#[get("/tag/<name>?<page>")]
pub fn paginated_tag(user: Option<User>, conn: DbConn, name: String, page: Page, intl: I18n) -> Ructe {
pub fn tag(user: Option<User>, conn: DbConn, name: String, page: Option<Page>, intl: I18n) -> Ructe {
let page = page.unwrap_or_default();
let posts = Post::list_by_tag(&*conn, name.clone(), page.limits());
render!(tags::index(
&(&*conn, &intl.catalog, user),

View File

@ -165,7 +165,8 @@ pub fn follow_auth(name: String, i18n: I18n) -> Flash<Redirect> {
}
#[get("/@/<name>/followers?<page>")]
pub fn followers_paginated(name: String, conn: DbConn, account: Option<User>, page: Page, intl: I18n) -> Result<Ructe, Ructe> {
pub fn followers(name: String, conn: DbConn, account: Option<User>, page: Option<Page>, intl: I18n) -> Result<Ructe, Ructe> {
let page = page.unwrap_or_default();
let user = User::find_by_fqn(&*conn, &name).ok_or_else(|| render!(errors::not_found(&(&*conn, &intl.catalog, account.clone()))))?;
let followers_count = user.get_followers(&*conn).len(); // TODO: count in DB
@ -181,11 +182,6 @@ pub fn followers_paginated(name: String, conn: DbConn, account: Option<User>, pa
)))
}
#[get("/@/<name>/followers", rank = 2)]
pub fn followers(name: String, conn: DbConn, account: Option<User>, intl: I18n) -> Result<Ructe, Ructe> {
followers_paginated(name, conn, account, Page::first(), intl)
}
#[get("/@/<name>", rank = 1)]
pub fn activity_details(
name: String,
@ -331,7 +327,7 @@ pub fn create(conn: DbConn, form: LenientForm<NewUserForm>, intl: I18n) -> Resul
form.email.to_string(),
User::hash_pass(&form.password),
).update_boxes(&*conn);
Redirect::to(uri!(super::session::new))
Redirect::to(uri!(super::session::new: m = _))
})
.map_err(|err| {
render!(users::new(

View File

@ -34,7 +34,7 @@
<i class="icon icon-home" aria-label="@i18n!(ctx.1, "Dashboard")"></i>
<span class="mobile-label">@i18n!(ctx.1, "Dashboard")</span>
</a>
<a href="@uri!(notifications::notifications)">
<a href="@uri!(notifications::notifications: page = _)">
<i class="icon icon-bell" aria-label="@i18n!(ctx.1, "Notifications")"></i>
<span class="mobile-label">@i18n!(ctx.1, "Notifications")</span>
</a>
@ -47,7 +47,7 @@
<span class="mobile-label">@i18n!(ctx.1, "My account")</span>
</a>
} else {
<a href="@uri!(session::new)">
<a href="@uri!(session::new: m = _)">
<i class="icon icon-log-in"></i>
<span class="mobile-label">@i18n!(ctx.1, "Log In")</span>
</a>

View File

@ -8,7 +8,7 @@
@(ctx: BaseContext, blog: Blog, fqn: String, authors: &Vec<User>, total_articles: usize, page: i32, n_pages: i32, is_author: bool, posts: Vec<Post>)
@:base(ctx, blog.title.as_ref(), {}, {
<a href="@uri!(blogs::details: name = &fqn)">@blog.title</a>
<a href="@uri!(blogs::details: name = &fqn, page = _)">@blog.title</a>
}, {
<div class="hidden">
@for author in authors {

View File

@ -12,8 +12,8 @@
@tabs(&[
(&uri!(instance::admin).to_string(), i18n!(ctx.1, "Configuration"), true),
(&uri!(instance::admin_instances).to_string(), i18n!(ctx.1, "Instances"), false),
(&uri!(instance::admin_users).to_string(), i18n!(ctx.1, "Users"), false),
(&uri!(instance::admin_instances: page = _).to_string(), i18n!(ctx.1, "Instances"), false),
(&uri!(instance::admin_users: page = _).to_string(), i18n!(ctx.1, "Users"), false),
])
<form method="post" action="@uri!(instance::update_settings)">

View File

@ -12,15 +12,15 @@
@if let Some(_) = ctx.2 {
@tabs(&[
(&uri!(instance::index).to_string(), i18n!(ctx.1, "Latest articles"), false),
(&uri!(instance::feed).to_string(), i18n!(ctx.1, "Your feed"), false),
(&uri!(instance::federated).to_string(), i18n!(ctx.1, "Federated feed"), true),
(&uri!(instance::local).to_string(), i18n!(ctx.1, "Local feed"), false),
(&uri!(instance::feed: _).to_string(), i18n!(ctx.1, "Your feed"), false),
(&uri!(instance::federated: _).to_string(), i18n!(ctx.1, "Federated feed"), true),
(&uri!(instance::local: _).to_string(), i18n!(ctx.1, "Local feed"), false),
])
} else {
@tabs(&[
(&uri!(instance::index).to_string(), i18n!(ctx.1, "Latest articles"), false),
(&uri!(instance::federated).to_string(), i18n!(ctx.1, "Federated feed"), true),
(&uri!(instance::local).to_string(), i18n!(ctx.1, "Local feed"), false),
(&uri!(instance::federated: _).to_string(), i18n!(ctx.1, "Federated feed"), true),
(&uri!(instance::local: _).to_string(), i18n!(ctx.1, "Local feed"), false),
])
}

View File

@ -10,9 +10,9 @@
@tabs(&[
(&uri!(instance::index).to_string(), i18n!(ctx.1, "Latest articles"), false),
(&uri!(instance::feed).to_string(), i18n!(ctx.1, "Your feed"), true),
(&uri!(instance::federated).to_string(), i18n!(ctx.1, "Federated feed"), false),
(&uri!(instance::local).to_string(), i18n!(ctx.1, "Local feed"), false),
(&uri!(instance::feed: _).to_string(), i18n!(ctx.1, "Your feed"), true),
(&uri!(instance::federated: _).to_string(), i18n!(ctx.1, "Federated feed"), false),
(&uri!(instance::local: _).to_string(), i18n!(ctx.1, "Local feed"), false),
])
@if !articles.is_empty() {

View File

@ -12,24 +12,24 @@
@if ctx.2.is_some() {
@tabs(&[
(&uri!(instance::index).to_string(), i18n!(ctx.1, "Latest articles"), true),
(&uri!(instance::feed).to_string(), i18n!(ctx.1, "Your feed"), false),
(&uri!(instance::federated).to_string(), i18n!(ctx.1, "Federated feed"), false),
(&uri!(instance::local).to_string(), i18n!(ctx.1, "Local feed"), false),
(&uri!(instance::feed: _).to_string(), i18n!(ctx.1, "Your feed"), false),
(&uri!(instance::federated: _).to_string(), i18n!(ctx.1, "Federated feed"), false),
(&uri!(instance::local: _).to_string(), i18n!(ctx.1, "Local feed"), false),
])
@:home_feed(ctx, user_feed.unwrap_or_default(), &uri!(instance::feed).to_string(), "Your feed")
@:home_feed(ctx, federated, &uri!(instance::federated).to_string(), "Federated feed")
@:home_feed(ctx, local, &uri!(instance::local).to_string(), "Local feed")
@:home_feed(ctx, user_feed.unwrap_or_default(), &uri!(instance::feed: _).to_string(), "Your feed")
@:home_feed(ctx, federated, &uri!(instance::federated: _).to_string(), "Federated feed")
@:home_feed(ctx, local, &uri!(instance::local: _).to_string(), "Local feed")
@:instance_description(ctx, instance, n_users, n_articles)
} else {
@tabs(&[
(&uri!(instance::index).to_string(), i18n!(ctx.1, "Latest articles"), true),
(&uri!(instance::federated).to_string(), i18n!(ctx.1, "Federated feed"), false),
(&uri!(instance::local).to_string(), i18n!(ctx.1, "Local feed"), false),
(&uri!(instance::federated: _).to_string(), i18n!(ctx.1, "Federated feed"), false),
(&uri!(instance::local: _).to_string(), i18n!(ctx.1, "Local feed"), false),
])
@:home_feed(ctx, federated, &uri!(instance::federated).to_string(), "Federated feed")
@:home_feed(ctx, local, &uri!(instance::local).to_string(), "Local feed")
@:home_feed(ctx, federated, &uri!(instance::federated: _).to_string(), "Federated feed")
@:home_feed(ctx, local, &uri!(instance::local: _).to_string(), "Local feed")
@:instance_description(ctx, instance, n_users, n_articles)
}
})

View File

@ -10,8 +10,8 @@
@tabs(&[
(&uri!(instance::admin).to_string(), i18n!(ctx.1, "Configuration"), false),
(&uri!(instance::admin_instances).to_string(), i18n!(ctx.1, "Instances"), true),
(&uri!(instance::admin_users).to_string(), i18n!(ctx.1, "Users"), false),
(&uri!(instance::admin_instances: page = _).to_string(), i18n!(ctx.1, "Instances"), true),
(&uri!(instance::admin_users: page = _).to_string(), i18n!(ctx.1, "Users"), false),
])
<div class="list">

View File

@ -13,15 +13,15 @@
@if let Some(_) = ctx.2 {
@tabs(&[
(&uri!(instance::index).to_string(), i18n!(ctx.1, "Latest articles"), false),
(&uri!(instance::feed).to_string(), i18n!(ctx.1, "Your feed"), false),
(&uri!(instance::federated).to_string(), i18n!(ctx.1, "Federated feed"), false),
(&uri!(instance::local).to_string(), i18n!(ctx.1, "Local feed"), true),
(&uri!(instance::feed: _).to_string(), i18n!(ctx.1, "Your feed"), false),
(&uri!(instance::federated: _).to_string(), i18n!(ctx.1, "Federated feed"), false),
(&uri!(instance::local: _).to_string(), i18n!(ctx.1, "Local feed"), true),
])
} else {
@tabs(&[
(&uri!(instance::index).to_string(), i18n!(ctx.1, "Latest articles"), false),
(&uri!(instance::federated).to_string(), i18n!(ctx.1, "Federated feed"), false),
(&uri!(instance::local).to_string(), i18n!(ctx.1, "Local feed"), true),
(&uri!(instance::federated: _).to_string(), i18n!(ctx.1, "Federated feed"), false),
(&uri!(instance::local: _).to_string(), i18n!(ctx.1, "Local feed"), true),
])
}

View File

@ -10,8 +10,8 @@
@tabs(&[
(&uri!(instance::admin).to_string(), i18n!(ctx.1, "Configuration"), false),
(&uri!(instance::admin_instances).to_string(), i18n!(ctx.1, "Instances"), false),
(&uri!(instance::admin_users).to_string(), i18n!(ctx.1, "Users"), true),
(&uri!(instance::admin_instances: page = _).to_string(), i18n!(ctx.1, "Instances"), false),
(&uri!(instance::admin_users: page = _).to_string(), i18n!(ctx.1, "Users"), true),
])
<div class="list">

View File

@ -8,7 +8,11 @@
@if article.cover_id.is_some() {
<div class="cover" style="background-image: url('@Html(article.cover_url(ctx.0).unwrap_or_default())')"></div>
}
<h3 class="p-name"><a class="u-url" href="@uri!(posts::details: blog = article.get_blog(ctx.0).get_fqn(ctx.0), slug = &article.slug)">@article.title</a></h3>
<h3 class="p-name">
<a class="u-url" href="@uri!(posts::details: blog = article.get_blog(ctx.0).get_fqn(ctx.0), slug = &article.slug, responding_to = _)">
@article.title
</a>
</h3>
<main>
<p class="p-summary">@article.subtitle</p>
</main>
@ -21,7 +25,7 @@
@if article.published {
<span class="dt-published" datetime="@article.creation_date.format("%F %T")">@article.creation_date.format("%B %e, %Y")</span>
}
<a href="@uri!(blogs::details: name = article.get_blog(ctx.0).get_fqn(ctx.0))">@article.get_blog(ctx.0).title</a>
<a href="@uri!(blogs::details: name = article.get_blog(ctx.0).get_fqn(ctx.0), page = _)">@article.get_blog(ctx.0).title</a>
@if !article.published {
⋅ @i18n!(ctx.1, "Draft")
}

View File

@ -17,10 +17,10 @@
@if article.cover_id.is_some() {
<meta property="og:image" content="@Html(article.cover_url(ctx.0).unwrap_or_default())"/>
}
<meta property="og:url" content="@uri!(posts::details: blog = blog.get_fqn(ctx.0), slug = &article.slug)"/>
<meta property="og:url" content="@uri!(posts::details: blog = blog.get_fqn(ctx.0), slug = &article.slug, responding_to = _)"/>
<meta property="og:description" content="@article.subtitle"/>
}, {
<a href="@uri!(blogs::details: name = blog.get_fqn(ctx.0))">@blog.title</a>
<a href="@uri!(blogs::details: name = blog.get_fqn(ctx.0), page = _)">@blog.title</a>
}, {
<div class="h-entry">
<h1 class="article p-name">@&article.title</h1>
@ -63,7 +63,7 @@
<ul class="tags">
@for tag in tags {
@if !tag.is_hashtag {
<li><a class="p-category" href="@uri!(tags::tag: name = &tag.tag)">@tag.tag</a></li>
<li><a class="p-category" href="@uri!(tags::tag: name = &tag.tag, page = _)">@tag.tag</a></li>
} else {
<span class="hidden p-category">@tag.tag</span>
}
@ -116,14 +116,14 @@
<p aria-label="@i18n!(ctx.1, "One like", "{0} likes", &n_likes)" title="@i18n!(ctx.1, "One like", "{0} likes", n_likes)">
@n_likes
</p>
<a href="@uri!(session::new_message: m = i18n!(ctx.1, "Login to like"))" class="action">@icon!("heart") @i18n!(ctx.1, "Add yours")</a>
<a href="@uri!(session::new: m = i18n!(ctx.1, "Login to like"))" class="action">@icon!("heart") @i18n!(ctx.1, "Add yours")</a>
</div>
<div class="reshares">
<p aria-label="@i18n!(ctx.1, "One boost", "{0} boost", &n_reshares)" title="@i18n!(ctx.1, "One boost", "{0} boosts", n_reshares)">
@n_reshares
</p>
<a href="@uri!(session::new_message: m = i18n!(ctx.1, "Login to boost"))" class="action">@icon!("repeat") @i18n!(ctx.1, "Boost")</a>
<a href="@uri!(session::new: m = i18n!(ctx.1, "Login to boost"))" class="action">@icon!("repeat") @i18n!(ctx.1, "Boost")</a>
</div>
</div>
}

View File

@ -17,7 +17,7 @@
<div class="cards">
@for blog in blogs {
<div class="card">
<h3><a href="@uri!(blogs::details: name = blog.actor_id)">@blog.title</a></h3>
<h3><a href="@uri!(blogs::details: name = blog.actor_id, page = _)">@blog.title</a></h3>
</div>
}
</div>

View File

@ -11,7 +11,7 @@
@tabs(&[
(&uri!(user::details: name= user.get_fqn(ctx.0)).to_string(), i18n!(ctx.1, "Articles"), true),
(&uri!(user::followers: name = user.get_fqn(ctx.0)).to_string(), i18n!(ctx.1, "Followers"), false)
(&uri!(user::followers: name = user.get_fqn(ctx.0), page = _).to_string(), i18n!(ctx.1, "Followers"), false)
])
@if !recents.is_empty() {

View File

@ -10,7 +10,7 @@
@tabs(&[
(&uri!(user::details: name= user.get_fqn(ctx.0)).to_string(), i18n!(ctx.1, "Articles"), false),
(&uri!(user::followers: name = user.get_fqn(ctx.0)).to_string(), i18n!(ctx.1, "Followers"), true)
(&uri!(user::followers: name = user.get_fqn(ctx.0), page = _).to_string(), i18n!(ctx.1, "Followers"), true)
])
<div class="cards">