Hide cw pictures behind a summary/details (#483)

* Hide cw pictures behind a summary/details
* refactor md_to_html a bit and add cw support
* use random id for cw checkbox
This commit is contained in:
fdb-hiroshima
2019-04-06 19:20:33 +02:00
committed by GitHub
parent eabe73ddc0
commit 12c2078c89
11 changed files with 239 additions and 63 deletions
+5 -2
View File
@@ -11,6 +11,7 @@ use std::collections::HashSet;
use comment_seers::{CommentSeers, NewCommentSeers};
use instance::Instance;
use medias::Media;
use mentions::Mention;
use notifications::*;
use plume_common::activity_pub::{
@@ -102,14 +103,16 @@ impl Comment {
.unwrap_or(false)
}
pub fn to_activity(&self, conn: &Connection) -> Result<Note> {
pub fn to_activity<'b>(&self, conn: &'b Connection) -> Result<Note> {
let author = User::get(conn, self.author_id)?;
let (html, mentions, _hashtags) = utils::md_to_html(
self.content.get().as_ref(),
&Instance::get_local(conn)?.public_domain,
true,
Some(Media::get_media_processor(conn, vec![&author])),
);
let author = User::get(conn, self.author_id)?;
let mut note = Note::default();
let to = vec![Id::new(PUBLIC_VISIBILTY.to_string())];
+13 -2
View File
@@ -3,6 +3,7 @@ use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl};
use std::iter::Iterator;
use ap_url;
use medias::Media;
use plume_common::utils::md_to_html;
use safe_string::SafeString;
use schema::{instances, users};
@@ -128,8 +129,18 @@ impl Instance {
short_description: SafeString,
long_description: SafeString,
) -> Result<()> {
let (sd, _, _) = md_to_html(short_description.as_ref(), &self.public_domain, true);
let (ld, _, _) = md_to_html(long_description.as_ref(), &self.public_domain, false);
let (sd, _, _) = md_to_html(
short_description.as_ref(),
&self.public_domain,
true,
Some(Media::get_media_processor(conn, vec![])),
);
let (ld, _, _) = md_to_html(
long_description.as_ref(),
&self.public_domain,
false,
Some(Media::get_media_processor(conn, vec![])),
);
diesel::update(self)
.set((
instances::name.eq(name),
+15 -3
View File
@@ -5,7 +5,7 @@ use guid_create::GUID;
use reqwest;
use std::{fs, path::Path};
use plume_common::activity_pub::Id;
use plume_common::{activity_pub::Id, utils::MediaProcessor};
use instance::Instance;
use safe_string::SafeString;
@@ -124,10 +124,9 @@ impl Media {
}
pub fn markdown(&self, conn: &Connection) -> Result<SafeString> {
let url = self.url(conn)?;
Ok(match self.category() {
MediaCategory::Image => {
SafeString::new(&format!("![{}]({})", escape(&self.alt_text), url))
SafeString::new(&format!("![{}]({})", escape(&self.alt_text), self.id))
}
MediaCategory::Audio | MediaCategory::Video => self.html(conn)?,
MediaCategory::Unknown => SafeString::new(""),
@@ -225,6 +224,19 @@ impl Media {
},
)
}
pub fn get_media_processor<'a>(conn: &'a Connection, user: Vec<&User>) -> MediaProcessor<'a> {
let uid = user.iter().map(|u| u.id).collect::<Vec<_>>();
Box::new(move |id| {
let media = Media::get(conn, id).ok()?;
// if owner is user or check is disabled
if uid.contains(&media.owner_id) || uid.is_empty() {
Some((media.url(conn).ok()?, media.content_warning))
} else {
None
}
})
}
}
#[cfg(test)]
+10 -8
View File
@@ -207,17 +207,19 @@ impl<'a> Provider<(&'a Connection, &'a Worker, &'a Searcher, Option<i32>)> for P
let domain = &Instance::get_local(&conn)
.map_err(|_| ApiError::NotFound("posts::update: Error getting local instance".into()))?
.public_domain;
let (content, mentions, hashtags) = md_to_html(
query.source.clone().unwrap_or_default().clone().as_ref(),
domain,
false,
);
let author = User::get(
conn,
user_id.expect("<Post as Provider>::create: no user_id error"),
)
.map_err(|_| ApiError::NotFound("Author not found".into()))?;
let (content, mentions, hashtags) = md_to_html(
query.source.clone().unwrap_or_default().clone().as_ref(),
domain,
false,
Some(Media::get_media_processor(conn, vec![&author])),
);
let blog = match query.blog_id {
Some(x) => x,
None => {
@@ -757,7 +759,7 @@ impl Post {
post.license = license;
}
let mut txt_hashtags = md_to_html(&post.source, "", false)
let mut txt_hashtags = md_to_html(&post.source, "", false, None)
.2
.into_iter()
.map(|s| s.to_camel_case())
@@ -995,7 +997,7 @@ impl<'a> FromActivity<LicensedArticle, (&'a Connection, &'a Searcher)> for Post
}
// save mentions and tags
let mut hashtags = md_to_html(&post.source, "", false)
let mut hashtags = md_to_html(&post.source, "", false, None)
.2
.into_iter()
.map(|s| s.to_camel_case())
+18 -2
View File
@@ -19,7 +19,7 @@ lazy_static! {
static ref CLEAN: Builder<'static> = {
let mut b = Builder::new();
b.add_generic_attributes(iter::once("id"))
.add_tags(&["iframe", "video", "audio"])
.add_tags(&["iframe", "video", "audio", "label", "input"])
.id_prefix(Some("postcontent-"))
.url_relative(UrlRelative::Custom(Box::new(url_add_prefix)))
.add_tag_attributes(
@@ -27,7 +27,23 @@ lazy_static! {
["width", "height", "src", "frameborder"].iter().cloned(),
)
.add_tag_attributes("video", ["src", "title", "controls"].iter())
.add_tag_attributes("audio", ["src", "title", "controls"].iter());
.add_tag_attributes("audio", ["src", "title", "controls"].iter())
.add_tag_attributes("label", ["for"].iter())
.add_tag_attributes("input", ["type", "checked"].iter())
.add_allowed_classes("input", ["cw-checkbox"].iter())
.add_allowed_classes("span", ["cw-container", "cw-text"].iter())
.attribute_filter(|elem, att, val| match (elem, att) {
("input", "type") => Some("checkbox".into()),
("input", "checked") => Some("checked".into()),
("label", "for") => {
if val.starts_with("postcontent-cw-") {
Some(val.into())
} else {
None
}
}
_ => Some(val.into()),
});
b
};
}
+8 -2
View File
@@ -209,7 +209,13 @@ impl User {
.set((
users::display_name.eq(name),
users::email.eq(email),
users::summary_html.eq(utils::md_to_html(&summary, "", false).0),
users::summary_html.eq(utils::md_to_html(
&summary,
"",
false,
Some(Media::get_media_processor(conn, vec![self])),
)
.0),
users::summary.eq(summary),
))
.execute(conn)?;
@@ -868,7 +874,7 @@ impl NewUser {
display_name,
is_admin,
summary: summary.to_owned(),
summary_html: SafeString::new(&utils::md_to_html(&summary, "", false).0),
summary_html: SafeString::new(&utils::md_to_html(&summary, "", false, None).0),
email: Some(email),
hashed_password: Some(password),
instance_id: Instance::get_local(conn)?.id,