diff --git a/crates/api_common/src/site.rs b/crates/api_common/src/site.rs index b92dd40ce..912fbd343 100644 --- a/crates/api_common/src/site.rs +++ b/crates/api_common/src/site.rs @@ -162,6 +162,7 @@ pub struct CreateSite { pub private_instance: Option, pub default_theme: Option, pub default_post_listing_type: Option, + pub default_sort_type: Option, pub legal_information: Option, pub application_email_admins: Option, pub hide_modlog_mod_names: Option, @@ -221,6 +222,8 @@ pub struct EditSite { /// The default theme. Usually "browser" pub default_theme: Option, pub default_post_listing_type: Option, + /// The default sort, usually "active" + pub default_sort_type: Option, /// An optional page of legal information pub legal_information: Option, /// Whether to email admins when receiving a new application. diff --git a/crates/api_crud/src/site/create.rs b/crates/api_crud/src/site/create.rs index 88e91a694..b5441bffe 100644 --- a/crates/api_crud/src/site/create.rs +++ b/crates/api_crud/src/site/create.rs @@ -93,6 +93,7 @@ pub async fn create_site( private_instance: data.private_instance, default_theme: data.default_theme.clone(), default_post_listing_type: data.default_post_listing_type, + default_sort_type: data.default_sort_type, legal_information: diesel_option_overwrite(data.legal_information.clone()), application_email_admins: data.application_email_admins, hide_modlog_mod_names: data.hide_modlog_mod_names, @@ -192,7 +193,7 @@ mod tests { use crate::site::create::validate_create_payload; use lemmy_api_common::site::CreateSite; - use lemmy_db_schema::{source::local_site::LocalSite, ListingType, RegistrationMode}; + use lemmy_db_schema::{source::local_site::LocalSite, ListingType, RegistrationMode, SortType}; use lemmy_utils::error::LemmyErrorType; #[test] @@ -214,6 +215,7 @@ mod tests { None::, None::, None::, + None::, None::, None::, None::, @@ -237,6 +239,7 @@ mod tests { None::, None::, None::, + None::, None::, None::, None::, @@ -260,6 +263,7 @@ mod tests { None::, None::, None::, + None::, Some(String::from("(zeta|alpha)")), None::, None::, @@ -283,6 +287,7 @@ mod tests { None::, None::, Some(ListingType::Subscribed), + None::, None::, None::, None::, @@ -306,6 +311,7 @@ mod tests { None::, None::, None::, + None::, None::, Some(true), Some(true), @@ -329,6 +335,7 @@ mod tests { None::, None::, None::, + None::, None::, None::, Some(true), @@ -352,6 +359,7 @@ mod tests { None::, None::, None::, + None::, None::, None::, None::, @@ -409,6 +417,7 @@ mod tests { None::, None::, None::, + None::, None::, None::, None::, @@ -431,6 +440,7 @@ mod tests { Some(String::new()), Some(String::new()), Some(ListingType::All), + Some(SortType::Active), Some(String::new()), Some(false), Some(true), @@ -453,6 +463,7 @@ mod tests { None::, None::, None::, + None::, Some(String::new()), None::, None::, @@ -475,6 +486,7 @@ mod tests { None::, None::, None::, + None::, None::, None::, None::, @@ -524,6 +536,7 @@ mod tests { site_description: Option, site_sidebar: Option, site_listing_type: Option, + site_sort_type: Option, site_slur_filter_regex: Option, site_is_private: Option, site_is_federated: Option, @@ -544,6 +557,7 @@ mod tests { private_instance: site_is_private, default_theme: None, default_post_listing_type: site_listing_type, + default_sort_type: site_sort_type, legal_information: None, application_email_admins: None, hide_modlog_mod_names: None, diff --git a/crates/api_crud/src/site/update.rs b/crates/api_crud/src/site/update.rs index 46bd1e49f..17e81937e 100644 --- a/crates/api_crud/src/site/update.rs +++ b/crates/api_crud/src/site/update.rs @@ -92,6 +92,7 @@ pub async fn update_site( private_instance: data.private_instance, default_theme: data.default_theme.clone(), default_post_listing_type: data.default_post_listing_type, + default_sort_type: data.default_sort_type, legal_information: diesel_option_overwrite(data.legal_information.clone()), application_email_admins: data.application_email_admins, hide_modlog_mod_names: data.hide_modlog_mod_names, @@ -227,7 +228,7 @@ mod tests { use crate::site::update::validate_update_payload; use lemmy_api_common::site::EditSite; - use lemmy_db_schema::{source::local_site::LocalSite, ListingType, RegistrationMode}; + use lemmy_db_schema::{source::local_site::LocalSite, ListingType, RegistrationMode, SortType}; use lemmy_utils::error::LemmyErrorType; #[test] @@ -248,6 +249,7 @@ mod tests { None::, None::, None::, + None::, None::, None::, None::, @@ -270,6 +272,7 @@ mod tests { None::, None::, None::, + None::, Some(String::from("(zeta|alpha)")), None::, None::, @@ -292,6 +295,7 @@ mod tests { None::, None::, Some(ListingType::Subscribed), + None::, None::, None::, None::, @@ -314,6 +318,7 @@ mod tests { None::, None::, None::, + None::, None::, Some(true), Some(true), @@ -336,6 +341,7 @@ mod tests { None::, None::, None::, + None::, None::, None::, Some(true), @@ -358,6 +364,7 @@ mod tests { None::, None::, None::, + None::, None::, None::, None::, @@ -411,6 +418,7 @@ mod tests { None::, None::, None::, + None::, None::, None::, None::, @@ -432,6 +440,7 @@ mod tests { Some(String::new()), Some(String::new()), Some(ListingType::All), + Some(SortType::Active), Some(String::new()), Some(false), Some(true), @@ -453,6 +462,7 @@ mod tests { None::, None::, None::, + None::, Some(String::new()), None::, None::, @@ -474,6 +484,7 @@ mod tests { None::, None::, None::, + None::, None::, None::, None::, @@ -521,6 +532,7 @@ mod tests { site_description: Option, site_sidebar: Option, site_listing_type: Option, + site_sort_type: Option, site_slur_filter_regex: Option, site_is_private: Option, site_is_federated: Option, @@ -541,6 +553,7 @@ mod tests { private_instance: site_is_private, default_theme: None, default_post_listing_type: site_listing_type, + default_sort_type: site_sort_type, legal_information: None, application_email_admins: None, hide_modlog_mod_names: None, diff --git a/crates/apub/src/api/list_comments.rs b/crates/apub/src/api/list_comments.rs index 7d1de019e..3ae85cdcc 100644 --- a/crates/apub/src/api/list_comments.rs +++ b/crates/apub/src/api/list_comments.rs @@ -48,9 +48,10 @@ pub async fn list_comments( let listing_type = Some(listing_type_with_default( data.type_, + local_user_view.as_ref().map(|u| &u.local_user), &local_site, community_id, - )?); + )); // If a parent_id is given, fetch the comment to get the path let parent_path = if let Some(parent_id) = parent_id { diff --git a/crates/apub/src/api/list_posts.rs b/crates/apub/src/api/list_posts.rs index d4ed566c4..5285acaa7 100644 --- a/crates/apub/src/api/list_posts.rs +++ b/crates/apub/src/api/list_posts.rs @@ -1,5 +1,5 @@ use crate::{ - api::listing_type_with_default, + api::{listing_type_with_default, sort_type_with_default}, fetcher::resolve_actor_identifier, objects::community::ApubCommunity, }; @@ -27,8 +27,6 @@ pub async fn list_posts( check_private_instance(&local_user_view, &local_site.local_site)?; - let sort = data.sort; - let page = data.page; let limit = data.limit; let community_id = if let Some(name) = &data.community_name { @@ -45,11 +43,20 @@ pub async fn list_posts( return Err(LemmyError::from(LemmyErrorType::ContradictingFilters)); } + let local_user_ref = local_user_view.as_ref().map(|u| &u.local_user); let listing_type = Some(listing_type_with_default( data.type_, + local_user_ref, &local_site.local_site, community_id, - )?); + )); + + let sort = Some(sort_type_with_default( + data.sort, + local_user_ref, + &local_site.local_site, + )); + // parse pagination token let page_after = if let Some(pa) = &data.page_cursor { Some(pa.read(&mut context.pool()).await?) diff --git a/crates/apub/src/api/mod.rs b/crates/apub/src/api/mod.rs index 59586e477..dab2ace06 100644 --- a/crates/apub/src/api/mod.rs +++ b/crates/apub/src/api/mod.rs @@ -1,5 +1,9 @@ -use lemmy_db_schema::{newtypes::CommunityId, source::local_site::LocalSite, ListingType}; -use lemmy_utils::error::LemmyError; +use lemmy_db_schema::{ + newtypes::CommunityId, + source::{local_site::LocalSite, local_user::LocalUser}, + ListingType, + SortType, +}; pub mod list_comments; pub mod list_posts; @@ -12,15 +16,33 @@ pub mod user_settings_backup; /// Returns default listing type, depending if the query is for frontpage or community. fn listing_type_with_default( type_: Option, + local_user: Option<&LocalUser>, local_site: &LocalSite, community_id: Option, -) -> Result { +) -> ListingType { // On frontpage use listing type from param or admin configured default - let listing_type = if community_id.is_none() { - type_.unwrap_or(local_site.default_post_listing_type) + if community_id.is_none() { + type_.unwrap_or( + local_user + .map(|u| u.default_listing_type) + .unwrap_or(local_site.default_post_listing_type), + ) } else { // inside of community show everything ListingType::All - }; - Ok(listing_type) + } +} + +/// Returns a default instance-level sort type, if none is given by the user. +/// Order is type, local user default, then site default. +fn sort_type_with_default( + type_: Option, + local_user: Option<&LocalUser>, + local_site: &LocalSite, +) -> SortType { + type_.unwrap_or( + local_user + .map(|u| u.default_sort_type) + .unwrap_or(local_site.default_sort_type), + ) } diff --git a/crates/db_schema/src/schema.rs b/crates/db_schema/src/schema.rs index de54c379c..19f9183a5 100644 --- a/crates/db_schema/src/schema.rs +++ b/crates/db_schema/src/schema.rs @@ -354,6 +354,7 @@ diesel::table! { use super::sql_types::ListingTypeEnum; use super::sql_types::RegistrationModeEnum; use super::sql_types::PostListingModeEnum; + use super::sql_types::SortTypeEnum; local_site (id) { id -> Int4, @@ -382,6 +383,7 @@ diesel::table! { reports_email_admins -> Bool, federation_signed_fetch -> Bool, default_post_listing_mode -> PostListingModeEnum, + default_sort_type -> SortTypeEnum, } } diff --git a/crates/db_schema/src/source/local_site.rs b/crates/db_schema/src/source/local_site.rs index ea3dbc179..05583c065 100644 --- a/crates/db_schema/src/source/local_site.rs +++ b/crates/db_schema/src/source/local_site.rs @@ -5,6 +5,7 @@ use crate::{ ListingType, PostListingMode, RegistrationMode, + SortType, }; use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; @@ -65,8 +66,10 @@ pub struct LocalSite { /// Whether to sign outgoing Activitypub fetches with private key of local instance. Some /// Fediverse instances and platforms require this. pub federation_signed_fetch: bool, - /// Default value for [LocalUser.post_listing_mode] + /// Default value for [LocalSite.post_listing_mode] pub default_post_listing_mode: PostListingMode, + /// Default value for [LocalUser.post_listing_mode] + pub default_sort_type: SortType, } #[derive(Clone, TypedBuilder)] @@ -97,6 +100,7 @@ pub struct LocalSiteInsertForm { pub reports_email_admins: Option, pub federation_signed_fetch: Option, pub default_post_listing_mode: Option, + pub default_sort_type: Option, } #[derive(Clone, Default)] @@ -125,4 +129,5 @@ pub struct LocalSiteUpdateForm { pub updated: Option>>, pub federation_signed_fetch: Option, pub default_post_listing_mode: Option, + pub default_sort_type: Option, } diff --git a/migrations/2024-02-15-171358_default_instance_sort_type/down.sql b/migrations/2024-02-15-171358_default_instance_sort_type/down.sql new file mode 100644 index 000000000..8ba51592b --- /dev/null +++ b/migrations/2024-02-15-171358_default_instance_sort_type/down.sql @@ -0,0 +1,3 @@ +ALTER TABLE local_site + DROP COLUMN default_sort_type; + diff --git a/migrations/2024-02-15-171358_default_instance_sort_type/up.sql b/migrations/2024-02-15-171358_default_instance_sort_type/up.sql new file mode 100644 index 000000000..f2bcddcff --- /dev/null +++ b/migrations/2024-02-15-171358_default_instance_sort_type/up.sql @@ -0,0 +1,3 @@ +ALTER TABLE local_site + ADD COLUMN default_sort_type sort_type_enum DEFAULT 'Active' NOT NULL; +