forked from Plume/Plume
Slightly improve the media experience (#452)
* Slightly improve the media experience - Use a grid to display the list of media - Add icons for non-image media preview - Paginate the gallery - Add links to the gallery in the editor and in the profile settings to make it more discoverable when you need it Fixes #432 * Allow video and audio tags in SafeString Otherwise we can't display their preview, nor show them in articles Also show controls by default for these two elements * Show fallback images for audio and unknown files, to make them more visible * Add a new constructor to SafeString when the input is trusted and doesn't need to be escaped. And use it to generate media previews. * Make it possible to insert video/audio in articles
This commit is contained in:
parent
a5e0486da0
commit
eff2698664
27 changed files with 677 additions and 58 deletions
|
@ -7,6 +7,7 @@ trim_trailing_whitespace = true
|
|||
|
||||
[*.{js,rs,css,tera,html}]
|
||||
charset = utf-8
|
||||
indent_size = 4
|
||||
|
||||
[*.{rs,tera,css,html}]
|
||||
indent_style = space
|
||||
|
|
|
@ -45,6 +45,17 @@ pub enum MediaCategory {
|
|||
Unknown,
|
||||
}
|
||||
|
||||
impl MediaCategory {
|
||||
pub fn to_string(&self) -> &str {
|
||||
match *self {
|
||||
MediaCategory::Image => "image",
|
||||
MediaCategory::Audio => "audio",
|
||||
MediaCategory::Video => "video",
|
||||
MediaCategory::Unknown => "unknown",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Media {
|
||||
insert!(medias, NewMedia);
|
||||
get!(medias);
|
||||
|
@ -56,6 +67,23 @@ impl Media {
|
|||
.map_err(Error::from)
|
||||
}
|
||||
|
||||
pub fn page_for_user(conn: &Connection, user: &User, (min, max): (i32, i32)) -> Result<Vec<Media>> {
|
||||
medias::table
|
||||
.filter(medias::owner_id.eq(user.id))
|
||||
.offset(min as i64)
|
||||
.limit((max - min) as i64)
|
||||
.load::<Media>(conn)
|
||||
.map_err(Error::from)
|
||||
}
|
||||
|
||||
pub fn count_for_user(conn: &Connection, user: &User) -> Result<i64> {
|
||||
medias::table
|
||||
.filter(medias::owner_id.eq(user.id))
|
||||
.count()
|
||||
.get_result(conn)
|
||||
.map_err(Error::from)
|
||||
}
|
||||
|
||||
pub fn category(&self) -> MediaCategory {
|
||||
match &*self
|
||||
.file_path
|
||||
|
@ -71,41 +99,25 @@ impl Media {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn preview_html(&self, conn: &Connection) -> Result<SafeString> {
|
||||
let url = self.url(conn)?;
|
||||
Ok(match self.category() {
|
||||
MediaCategory::Image => SafeString::new(&format!(
|
||||
r#"<img src="{}" alt="{}" title="{}" class=\"preview\">"#,
|
||||
url, escape(&self.alt_text), escape(&self.alt_text)
|
||||
)),
|
||||
MediaCategory::Audio => SafeString::new(&format!(
|
||||
r#"<audio src="{}" title="{}" class="preview"></audio>"#,
|
||||
url, escape(&self.alt_text)
|
||||
)),
|
||||
MediaCategory::Video => SafeString::new(&format!(
|
||||
r#"<video src="{}" title="{}" class="preview"></video>"#,
|
||||
url, escape(&self.alt_text)
|
||||
)),
|
||||
MediaCategory::Unknown => SafeString::new(""),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn html(&self, conn: &Connection) -> Result<SafeString> {
|
||||
let url = self.url(conn)?;
|
||||
Ok(match self.category() {
|
||||
MediaCategory::Image => SafeString::new(&format!(
|
||||
MediaCategory::Image => SafeString::trusted(&format!(
|
||||
r#"<img src="{}" alt="{}" title="{}">"#,
|
||||
url, escape(&self.alt_text), escape(&self.alt_text)
|
||||
)),
|
||||
MediaCategory::Audio => SafeString::new(&format!(
|
||||
r#"<audio src="{}" title="{}"></audio>"#,
|
||||
MediaCategory::Audio => SafeString::trusted(&format!(
|
||||
r#"<div class="media-preview audio"></div><audio src="{}" title="{}" controls></audio>"#,
|
||||
url, escape(&self.alt_text)
|
||||
)),
|
||||
MediaCategory::Video => SafeString::new(&format!(
|
||||
r#"<video src="{}" title="{}"></video>"#,
|
||||
MediaCategory::Video => SafeString::trusted(&format!(
|
||||
r#"<video src="{}" title="{}" controls></video>"#,
|
||||
url, escape(&self.alt_text)
|
||||
)),
|
||||
MediaCategory::Unknown => SafeString::new(""),
|
||||
MediaCategory::Unknown => SafeString::trusted(&format!(
|
||||
r#"<a href="{}" class="media-preview unknown"></a>"#,
|
||||
url,
|
||||
)),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -19,12 +19,20 @@ lazy_static! {
|
|||
static ref CLEAN: Builder<'static> = {
|
||||
let mut b = Builder::new();
|
||||
b.add_generic_attributes(iter::once("id"))
|
||||
.add_tags(iter::once("iframe"))
|
||||
.add_tags(&[ "iframe", "video", "audio" ])
|
||||
.id_prefix(Some("postcontent-"))
|
||||
.url_relative(UrlRelative::Custom(Box::new(url_add_prefix)))
|
||||
.add_tag_attributes(
|
||||
"iframe",
|
||||
["width", "height", "src", "frameborder"].iter().map(|&v| v),
|
||||
[ "width", "height", "src", "frameborder" ].iter().map(|&v| v),
|
||||
)
|
||||
.add_tag_attributes(
|
||||
"video",
|
||||
[ "src", "title", "controls" ].iter(),
|
||||
)
|
||||
.add_tag_attributes(
|
||||
"audio",
|
||||
[ "src", "title", "controls" ].iter(),
|
||||
);
|
||||
b
|
||||
};
|
||||
|
@ -53,6 +61,18 @@ impl SafeString {
|
|||
value: CLEAN.clean(&value).to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new `SafeString`, but without escaping the given value.
|
||||
///
|
||||
/// Only use when you are sure you can trust the input (when the HTML
|
||||
/// is entirely generated by Plume, not depending on user-inputed data).
|
||||
/// Prefer `SafeString::new` as much as possible.
|
||||
pub fn trusted(value: impl AsRef<str>) -> Self {
|
||||
SafeString {
|
||||
value: value.as_ref().to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set(&mut self, value: &str) {
|
||||
self.value = CLEAN.clean(value).to_string();
|
||||
}
|
||||
|
|
|
@ -236,6 +236,13 @@ msgstr "تعديل حسابك"
|
|||
msgid "Your Profile"
|
||||
msgstr "ملفك الشخصي"
|
||||
|
||||
msgid "To change your avatar, upload it in your gallery and select from there."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Upload an avatar"
|
||||
msgstr "استخدمها كصورة رمزية"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Display name"
|
||||
msgstr "الاسم العلني"
|
||||
|
@ -526,6 +533,15 @@ msgstr "العنوان الثانوي"
|
|||
msgid "Content"
|
||||
msgstr "المحتوى"
|
||||
|
||||
msgid ""
|
||||
"You can upload medias to your gallery, and copy their Markdown code in your "
|
||||
"articles to insert them."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Upload media"
|
||||
msgstr "إرسال"
|
||||
|
||||
# src/template_utils.rs:144
|
||||
msgid "Tags, separated by commas"
|
||||
msgstr ""
|
||||
|
@ -719,9 +735,17 @@ msgstr "إرسال"
|
|||
msgid "You don't have any media yet."
|
||||
msgstr "ليس لديك أية وسائط بعد."
|
||||
|
||||
#, fuzzy
|
||||
msgid "Content warning: {0}"
|
||||
msgstr "تحذير عن المحتوى"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "حذف"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Details"
|
||||
msgstr "تفاصيل الصورة"
|
||||
|
||||
msgid "Media upload"
|
||||
msgstr "إرسال الوسائط"
|
||||
|
||||
|
|
|
@ -248,6 +248,13 @@ msgstr "Ändere deinen Account"
|
|||
msgid "Your Profile"
|
||||
msgstr "Dein Profil"
|
||||
|
||||
msgid "To change your avatar, upload it in your gallery and select from there."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Upload an avatar"
|
||||
msgstr "Als Avatar verwenden"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Display name"
|
||||
msgstr "Anzeigename"
|
||||
|
@ -541,6 +548,15 @@ msgstr "Untertitel"
|
|||
msgid "Content"
|
||||
msgstr "Inhalt"
|
||||
|
||||
msgid ""
|
||||
"You can upload medias to your gallery, and copy their Markdown code in your "
|
||||
"articles to insert them."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Upload media"
|
||||
msgstr "Hochladen"
|
||||
|
||||
# src/template_utils.rs:143
|
||||
msgid "Tags, separated by commas"
|
||||
msgstr ""
|
||||
|
@ -736,9 +752,16 @@ msgstr "Hochladen"
|
|||
msgid "You don't have any media yet."
|
||||
msgstr "Derzeit sind noch keine Mediendateien hochgeladen."
|
||||
|
||||
#, fuzzy
|
||||
msgid "Content warning: {0}"
|
||||
msgstr "Warnhinweis zum Inhalt"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Löschen"
|
||||
|
||||
msgid "Details"
|
||||
msgstr ""
|
||||
|
||||
msgid "Media upload"
|
||||
msgstr "Hochladen von Mediendateien"
|
||||
|
||||
|
|
|
@ -241,6 +241,12 @@ msgstr ""
|
|||
msgid "Your Profile"
|
||||
msgstr ""
|
||||
|
||||
msgid "To change your avatar, upload it in your gallery and select from there."
|
||||
msgstr ""
|
||||
|
||||
msgid "Upload an avatar"
|
||||
msgstr ""
|
||||
|
||||
# src/template_utils.rs:144
|
||||
msgid "Display name"
|
||||
msgstr ""
|
||||
|
@ -518,6 +524,14 @@ msgstr ""
|
|||
msgid "Content"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"You can upload medias to your gallery, and copy their Markdown code in your "
|
||||
"articles to insert them."
|
||||
msgstr ""
|
||||
|
||||
msgid "Upload media"
|
||||
msgstr ""
|
||||
|
||||
# src/template_utils.rs:144
|
||||
msgid "Tags, separated by commas"
|
||||
msgstr ""
|
||||
|
@ -683,9 +697,15 @@ msgstr ""
|
|||
msgid "You don't have any media yet."
|
||||
msgstr ""
|
||||
|
||||
msgid "Content warning: {0}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete"
|
||||
msgstr ""
|
||||
|
||||
msgid "Details"
|
||||
msgstr ""
|
||||
|
||||
msgid "Media upload"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -229,6 +229,12 @@ msgstr "Edita tu cuenta"
|
|||
msgid "Your Profile"
|
||||
msgstr "Tu perfil"
|
||||
|
||||
msgid "To change your avatar, upload it in your gallery and select from there."
|
||||
msgstr ""
|
||||
|
||||
msgid "Upload an avatar"
|
||||
msgstr ""
|
||||
|
||||
# src/template_utils.rs:144
|
||||
msgid "Display name"
|
||||
msgstr ""
|
||||
|
@ -503,6 +509,14 @@ msgstr ""
|
|||
msgid "Content"
|
||||
msgstr "Contenido"
|
||||
|
||||
msgid ""
|
||||
"You can upload medias to your gallery, and copy their Markdown code in your "
|
||||
"articles to insert them."
|
||||
msgstr ""
|
||||
|
||||
msgid "Upload media"
|
||||
msgstr ""
|
||||
|
||||
# src/template_utils.rs:144
|
||||
msgid "Tags, separated by commas"
|
||||
msgstr ""
|
||||
|
@ -672,9 +686,15 @@ msgstr ""
|
|||
msgid "You don't have any media yet."
|
||||
msgstr ""
|
||||
|
||||
msgid "Content warning: {0}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete"
|
||||
msgstr ""
|
||||
|
||||
msgid "Details"
|
||||
msgstr ""
|
||||
|
||||
msgid "Media upload"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -247,6 +247,13 @@ msgstr "Modifier votre compte"
|
|||
msgid "Your Profile"
|
||||
msgstr "Votre profil"
|
||||
|
||||
msgid "To change your avatar, upload it in your gallery and select from there."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Upload an avatar"
|
||||
msgstr "Utiliser comme avatar"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Display name"
|
||||
msgstr "Nom affiché"
|
||||
|
@ -536,6 +543,15 @@ msgstr "Sous-titre"
|
|||
msgid "Content"
|
||||
msgstr "Contenu"
|
||||
|
||||
msgid ""
|
||||
"You can upload medias to your gallery, and copy their Markdown code in your "
|
||||
"articles to insert them."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Upload media"
|
||||
msgstr "Téléverser"
|
||||
|
||||
# src/template_utils.rs:143
|
||||
msgid "Tags, separated by commas"
|
||||
msgstr ""
|
||||
|
@ -730,9 +746,16 @@ msgstr "Téléverser"
|
|||
msgid "You don't have any media yet."
|
||||
msgstr "Vous n’avez pas encore de média."
|
||||
|
||||
#, fuzzy
|
||||
msgid "Content warning: {0}"
|
||||
msgstr "Avertissement"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Supprimer"
|
||||
|
||||
msgid "Details"
|
||||
msgstr ""
|
||||
|
||||
msgid "Media upload"
|
||||
msgstr "Téléversement de média"
|
||||
|
||||
|
|
|
@ -247,6 +247,13 @@ msgstr "Edite a súa conta"
|
|||
msgid "Your Profile"
|
||||
msgstr "O seu perfil"
|
||||
|
||||
msgid "To change your avatar, upload it in your gallery and select from there."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Upload an avatar"
|
||||
msgstr "Utilizar como avatar"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Display name"
|
||||
msgstr "Nome mostrado"
|
||||
|
@ -536,6 +543,15 @@ msgstr "Subtítulo"
|
|||
msgid "Content"
|
||||
msgstr "Contido"
|
||||
|
||||
msgid ""
|
||||
"You can upload medias to your gallery, and copy their Markdown code in your "
|
||||
"articles to insert them."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Upload media"
|
||||
msgstr "Subir"
|
||||
|
||||
# src/template_utils.rs:143
|
||||
msgid "Tags, separated by commas"
|
||||
msgstr ""
|
||||
|
@ -726,9 +742,16 @@ msgstr "Subir"
|
|||
msgid "You don't have any media yet."
|
||||
msgstr "Aínda non ten medios"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Content warning: {0}"
|
||||
msgstr "Aviso sobre o contido"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Eliminar"
|
||||
|
||||
msgid "Details"
|
||||
msgstr ""
|
||||
|
||||
msgid "Media upload"
|
||||
msgstr "Subir medios"
|
||||
|
||||
|
|
|
@ -247,6 +247,13 @@ msgstr "Modifica il tuo account"
|
|||
msgid "Your Profile"
|
||||
msgstr "Il tuo Profilo"
|
||||
|
||||
msgid "To change your avatar, upload it in your gallery and select from there."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Upload an avatar"
|
||||
msgstr "Usa come avatar"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Display name"
|
||||
msgstr "Nome Visualizzato"
|
||||
|
@ -539,6 +546,15 @@ msgstr "Sottotitolo"
|
|||
msgid "Content"
|
||||
msgstr "Contenuto"
|
||||
|
||||
msgid ""
|
||||
"You can upload medias to your gallery, and copy their Markdown code in your "
|
||||
"articles to insert them."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Upload media"
|
||||
msgstr "Carica"
|
||||
|
||||
# src/template_utils.rs:143
|
||||
msgid "Tags, separated by commas"
|
||||
msgstr ""
|
||||
|
@ -733,9 +749,16 @@ msgstr "Carica"
|
|||
msgid "You don't have any media yet."
|
||||
msgstr "Non hai ancora nessun media."
|
||||
|
||||
#, fuzzy
|
||||
msgid "Content warning: {0}"
|
||||
msgstr "Avviso di contenuto sensibile"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Elimina"
|
||||
|
||||
msgid "Details"
|
||||
msgstr ""
|
||||
|
||||
msgid "Media upload"
|
||||
msgstr "Caricamento di un media"
|
||||
|
||||
|
|
|
@ -240,6 +240,13 @@ msgstr "自分のアカウントを編集"
|
|||
msgid "Your Profile"
|
||||
msgstr "自分のプロフィール"
|
||||
|
||||
msgid "To change your avatar, upload it in your gallery and select from there."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Upload an avatar"
|
||||
msgstr "アバターとして使う"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Display name"
|
||||
msgstr "表示名"
|
||||
|
@ -531,6 +538,15 @@ msgstr "サブタイトル"
|
|||
msgid "Content"
|
||||
msgstr "コメント"
|
||||
|
||||
msgid ""
|
||||
"You can upload medias to your gallery, and copy their Markdown code in your "
|
||||
"articles to insert them."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Upload media"
|
||||
msgstr "アップロード"
|
||||
|
||||
# src/template_utils.rs:144
|
||||
msgid "Tags, separated by commas"
|
||||
msgstr ""
|
||||
|
@ -709,9 +725,17 @@ msgstr "アップロード"
|
|||
msgid "You don't have any media yet."
|
||||
msgstr "メディアがまだありません。"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Content warning: {0}"
|
||||
msgstr "コンテンツの警告"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "削除"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Details"
|
||||
msgstr "メディアの詳細"
|
||||
|
||||
msgid "Media upload"
|
||||
msgstr "メディアのアップロード"
|
||||
|
||||
|
|
|
@ -253,6 +253,12 @@ msgstr "Rediger kontoen din"
|
|||
msgid "Your Profile"
|
||||
msgstr "Din profil"
|
||||
|
||||
msgid "To change your avatar, upload it in your gallery and select from there."
|
||||
msgstr ""
|
||||
|
||||
msgid "Upload an avatar"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Display name"
|
||||
msgstr "Visningsnavn"
|
||||
|
@ -565,6 +571,15 @@ msgstr "Tittel"
|
|||
msgid "Content"
|
||||
msgstr "Innhold"
|
||||
|
||||
msgid ""
|
||||
"You can upload medias to your gallery, and copy their Markdown code in your "
|
||||
"articles to insert them."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Upload media"
|
||||
msgstr "Din kommentar"
|
||||
|
||||
# src/template_utils.rs:143
|
||||
msgid "Tags, separated by commas"
|
||||
msgstr ""
|
||||
|
@ -748,9 +763,16 @@ msgstr ""
|
|||
msgid "You don't have any media yet."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Content warning: {0}"
|
||||
msgstr "Innhold"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr ""
|
||||
|
||||
msgid "Details"
|
||||
msgstr ""
|
||||
|
||||
msgid "Media upload"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -222,6 +222,13 @@ msgstr "Edytuj swoje konto"
|
|||
msgid "Your Profile"
|
||||
msgstr "Twój profil"
|
||||
|
||||
msgid "To change your avatar, upload it in your gallery and select from there."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Upload an avatar"
|
||||
msgstr "Użyj jako awataru"
|
||||
|
||||
msgid "Display name"
|
||||
msgstr "Nazwa wyświetlana"
|
||||
|
||||
|
@ -505,6 +512,15 @@ msgstr "Podtytuł"
|
|||
msgid "Content"
|
||||
msgstr "Zawartość"
|
||||
|
||||
msgid ""
|
||||
"You can upload medias to your gallery, and copy their Markdown code in your "
|
||||
"articles to insert them."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Upload media"
|
||||
msgstr "Wyślij"
|
||||
|
||||
# src/template_utils.rs:143
|
||||
msgid "Tags, separated by commas"
|
||||
msgstr "Tagi, oddzielone przecinkami"
|
||||
|
@ -678,9 +694,17 @@ msgstr "Wyślij"
|
|||
msgid "You don't have any media yet."
|
||||
msgstr "Nie masz żadnej zawartości multimedialnej."
|
||||
|
||||
#, fuzzy
|
||||
msgid "Content warning: {0}"
|
||||
msgstr "Ostrzeżenie o zawartości"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Usuń"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Details"
|
||||
msgstr "Szczegóły zawartości multimedialnej"
|
||||
|
||||
msgid "Media upload"
|
||||
msgstr "Wysyłanie zawartości multimedialnej"
|
||||
|
||||
|
|
|
@ -239,6 +239,12 @@ msgstr ""
|
|||
msgid "Your Profile"
|
||||
msgstr ""
|
||||
|
||||
msgid "To change your avatar, upload it in your gallery and select from there."
|
||||
msgstr ""
|
||||
|
||||
msgid "Upload an avatar"
|
||||
msgstr ""
|
||||
|
||||
# src/template_utils.rs:144
|
||||
msgid "Display name"
|
||||
msgstr ""
|
||||
|
@ -510,6 +516,12 @@ msgstr ""
|
|||
msgid "Content"
|
||||
msgstr ""
|
||||
|
||||
msgid "You can upload medias to your gallery, and copy their Markdown code in your articles to insert them."
|
||||
msgstr ""
|
||||
|
||||
msgid "Upload media"
|
||||
msgstr ""
|
||||
|
||||
# src/template_utils.rs:144
|
||||
msgid "Tags, separated by commas"
|
||||
msgstr ""
|
||||
|
@ -668,9 +680,15 @@ msgstr ""
|
|||
msgid "You don't have any media yet."
|
||||
msgstr ""
|
||||
|
||||
msgid "Content warning: {0}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete"
|
||||
msgstr ""
|
||||
|
||||
msgid "Details"
|
||||
msgstr ""
|
||||
|
||||
msgid "Media upload"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -235,6 +235,13 @@ msgstr "Editar sua conta"
|
|||
msgid "Your Profile"
|
||||
msgstr "Seu Perfil"
|
||||
|
||||
msgid "To change your avatar, upload it in your gallery and select from there."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Upload an avatar"
|
||||
msgstr "Utilizar como avatar"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Display name"
|
||||
msgstr "Nome exibido"
|
||||
|
@ -526,6 +533,15 @@ msgstr "Subtítulo"
|
|||
msgid "Content"
|
||||
msgstr "Conteúdo"
|
||||
|
||||
msgid ""
|
||||
"You can upload medias to your gallery, and copy their Markdown code in your "
|
||||
"articles to insert them."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Upload media"
|
||||
msgstr "Carregar"
|
||||
|
||||
# src/template_utils.rs:144
|
||||
msgid "Tags, separated by commas"
|
||||
msgstr ""
|
||||
|
@ -701,9 +717,17 @@ msgstr "Carregar"
|
|||
msgid "You don't have any media yet."
|
||||
msgstr "Você ainda não tem nenhuma mídia."
|
||||
|
||||
#, fuzzy
|
||||
msgid "Content warning: {0}"
|
||||
msgstr "Alerta de conteúdo"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Suprimir"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Details"
|
||||
msgstr "Detalhes da mídia"
|
||||
|
||||
msgid "Media upload"
|
||||
msgstr "Carregamento de mídia"
|
||||
|
||||
|
|
|
@ -252,6 +252,13 @@ msgstr "Редактировать ваш аккаунт"
|
|||
msgid "Your Profile"
|
||||
msgstr "Ваш профиль"
|
||||
|
||||
msgid "To change your avatar, upload it in your gallery and select from there."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Upload an avatar"
|
||||
msgstr "Использовать как аватар"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Display name"
|
||||
msgstr "Имя для отображения"
|
||||
|
@ -543,6 +550,15 @@ msgstr "Подзаголовок"
|
|||
msgid "Content"
|
||||
msgstr "Содержимое"
|
||||
|
||||
msgid ""
|
||||
"You can upload medias to your gallery, and copy their Markdown code in your "
|
||||
"articles to insert them."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Upload media"
|
||||
msgstr "Загрузить"
|
||||
|
||||
# src/template_utils.rs:143
|
||||
msgid "Tags, separated by commas"
|
||||
msgstr ""
|
||||
|
@ -740,9 +756,17 @@ msgstr "Загрузить"
|
|||
msgid "You don't have any media yet."
|
||||
msgstr "Пока что вы не можете загружать медиафайлы."
|
||||
|
||||
#, fuzzy
|
||||
msgid "Content warning: {0}"
|
||||
msgstr "Предупреждение о контенте"
|
||||
|
||||
msgid "Delete"
|
||||
msgstr "Удалить"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Details"
|
||||
msgstr "Детали медиафайла"
|
||||
|
||||
msgid "Media upload"
|
||||
msgstr "Загрузка медиафайлов"
|
||||
|
||||
|
|
|
@ -5,14 +5,17 @@ use rocket_i18n::I18n;
|
|||
use std::fs;
|
||||
use plume_models::{Error, db_conn::DbConn, medias::*, users::User};
|
||||
use template_utils::Ructe;
|
||||
use routes::errors::ErrorPage;
|
||||
use routes::{Page, errors::ErrorPage};
|
||||
|
||||
#[get("/medias")]
|
||||
pub fn list(user: User, conn: DbConn, intl: I18n) -> Result<Ructe, ErrorPage> {
|
||||
let medias = Media::for_user(&*conn, user.id)?;
|
||||
#[get("/medias?<page>")]
|
||||
pub fn list(user: User, conn: DbConn, intl: I18n, page: Option<Page>) -> Result<Ructe, ErrorPage> {
|
||||
let page = page.unwrap_or_default();
|
||||
let medias = Media::page_for_user(&*conn, &user, page.limits())?;
|
||||
Ok(render!(medias::index(
|
||||
&(&*conn, &intl.catalog, Some(user)),
|
||||
medias
|
||||
&(&*conn, &intl.catalog, Some(user.clone())),
|
||||
medias,
|
||||
page.0,
|
||||
Page::total(Media::count_for_user(&*conn, &user)? as i32)
|
||||
)))
|
||||
}
|
||||
|
||||
|
@ -109,7 +112,7 @@ pub fn delete(id: i32, user: User, conn: DbConn) -> Result<Redirect, ErrorPage>
|
|||
if media.owner_id == user.id {
|
||||
media.delete(&*conn)?;
|
||||
}
|
||||
Ok(Redirect::to(uri!(list)))
|
||||
Ok(Redirect::to(uri!(list: page = _)))
|
||||
}
|
||||
|
||||
#[post("/medias/<id>/avatar")]
|
||||
|
|
|
@ -307,6 +307,10 @@ figure {
|
|||
figcaption {
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
audio, video {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.preview {
|
||||
|
@ -318,6 +322,30 @@ figure {
|
|||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.media-preview {
|
||||
min-height: 8em;
|
||||
|
||||
&:not(.image) {
|
||||
background-color: #7765E3;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-size: 4em;
|
||||
}
|
||||
|
||||
&.unknown {
|
||||
background-image: url('/static/images/unknown-file.svg');
|
||||
display: block;
|
||||
}
|
||||
|
||||
&.audio {
|
||||
background-image: url('/static/images/audio-file.svg');
|
||||
}
|
||||
|
||||
&.video {
|
||||
background-image: url('/static/images/video-file.svg');
|
||||
}
|
||||
}
|
||||
|
||||
/// Avatars
|
||||
.avatar {
|
||||
background-position: center;
|
||||
|
|
65
static/images/audio-file.svg
Normal file
65
static/images/audio-file.svg
Normal file
|
@ -0,0 +1,65 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="feather feather-headphones"
|
||||
version="1.1"
|
||||
id="svg6"
|
||||
sodipodi:docname="audio-file.svg"
|
||||
inkscape:version="0.92.3 (2405546, 2018-03-11)">
|
||||
<metadata
|
||||
id="metadata12">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs10" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
id="namedview8"
|
||||
showgrid="false"
|
||||
inkscape:zoom="9.8333333"
|
||||
inkscape:cx="12"
|
||||
inkscape:cy="12"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="30"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg6" />
|
||||
<path
|
||||
d="M3 18v-6a9 9 0 0 1 18 0v6"
|
||||
id="path2"
|
||||
style="stroke:#ffffff;stroke-opacity:1" />
|
||||
<path
|
||||
d="M21 19a2 2 0 0 1-2 2h-1a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2h3zM3 19a2 2 0 0 0 2 2h1a2 2 0 0 0 2-2v-3a2 2 0 0 0-2-2H3z"
|
||||
id="path4"
|
||||
style="stroke:#ffffff;stroke-opacity:1" />
|
||||
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
65
static/images/unknown-file.svg
Normal file
65
static/images/unknown-file.svg
Normal file
|
@ -0,0 +1,65 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="feather feather-file"
|
||||
version="1.1"
|
||||
id="svg6"
|
||||
sodipodi:docname="unknown-file.svg"
|
||||
inkscape:version="0.92.3 (2405546, 2018-03-11)">
|
||||
<metadata
|
||||
id="metadata12">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs10" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
id="namedview8"
|
||||
showgrid="false"
|
||||
inkscape:zoom="9.8333333"
|
||||
inkscape:cx="12"
|
||||
inkscape:cy="12"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="30"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg6" />
|
||||
<path
|
||||
d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"
|
||||
id="path2"
|
||||
style="stroke:#ffffff;stroke-opacity:1" />
|
||||
<polyline
|
||||
points="13 2 13 9 20 9"
|
||||
id="polyline4"
|
||||
style="stroke:#ffffff;stroke-opacity:1" />
|
||||
</svg>
|
After Width: | Height: | Size: 1.8 KiB |
115
static/images/video-file.svg
Normal file
115
static/images/video-file.svg
Normal file
|
@ -0,0 +1,115 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="feather feather-film"
|
||||
version="1.1"
|
||||
id="svg18"
|
||||
sodipodi:docname="video-file.svg"
|
||||
inkscape:version="0.92.3 (2405546, 2018-03-11)">
|
||||
<metadata
|
||||
id="metadata24">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs22" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
id="namedview20"
|
||||
showgrid="false"
|
||||
inkscape:zoom="9.8333333"
|
||||
inkscape:cx="12"
|
||||
inkscape:cy="12"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="30"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg18" />
|
||||
<rect
|
||||
x="2"
|
||||
y="2"
|
||||
width="20"
|
||||
height="20"
|
||||
rx="2.18"
|
||||
ry="2.18"
|
||||
id="rect2"
|
||||
style="stroke:#ffffff;stroke-opacity:1" />
|
||||
<line
|
||||
x1="7"
|
||||
y1="2"
|
||||
x2="7"
|
||||
y2="22"
|
||||
id="line4"
|
||||
style="stroke:#ffffff;stroke-opacity:1" />
|
||||
<line
|
||||
x1="17"
|
||||
y1="2"
|
||||
x2="17"
|
||||
y2="22"
|
||||
id="line6"
|
||||
style="stroke:#ffffff;stroke-opacity:1" />
|
||||
<line
|
||||
x1="2"
|
||||
y1="12"
|
||||
x2="22"
|
||||
y2="12"
|
||||
id="line8"
|
||||
style="stroke:#ffffff;stroke-opacity:1" />
|
||||
<line
|
||||
x1="2"
|
||||
y1="7"
|
||||
x2="7"
|
||||
y2="7"
|
||||
id="line10"
|
||||
style="stroke:#ffffff;stroke-opacity:1" />
|
||||
<line
|
||||
x1="2"
|
||||
y1="17"
|
||||
x2="7"
|
||||
y2="17"
|
||||
id="line12"
|
||||
style="stroke:#ffffff;stroke-opacity:1" />
|
||||
<line
|
||||
x1="17"
|
||||
y1="17"
|
||||
x2="22"
|
||||
y2="17"
|
||||
id="line14"
|
||||
style="stroke:#ffffff;stroke-opacity:1" />
|
||||
<line
|
||||
x1="17"
|
||||
y1="7"
|
||||
x2="22"
|
||||
y2="7"
|
||||
id="line16"
|
||||
style="stroke:#ffffff;stroke-opacity:1" />
|
||||
</svg>
|
After Width: | Height: | Size: 2.6 KiB |
|
@ -9,7 +9,7 @@
|
|||
@:base(ctx, i18n!(ctx.1, "Media details"), {}, {}, {
|
||||
<h1>@i18n!(ctx.1, "Media details")</h1>
|
||||
<section>
|
||||
<a href="@uri!(medias::list)">@i18n!(ctx.1, "Go back to the gallery")</a>
|
||||
<a href="@uri!(medias::list: page = _)">@i18n!(ctx.1, "Go back to the gallery")</a>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
@use plume_models::medias::Media;
|
||||
@use plume_models::safe_string::SafeString;
|
||||
@use plume_models::medias::*;
|
||||
@use templates::base;
|
||||
@use template_utils::*;
|
||||
@use routes::*;
|
||||
|
||||
@(ctx: BaseContext, medias: Vec<Media>)
|
||||
@(ctx: BaseContext, medias: Vec<Media>, page: i32, n_pages: i32)
|
||||
|
||||
@:base(ctx, i18n!(ctx.1, "Your media"), {}, {}, {
|
||||
<h1>@i18n!(ctx.1, "Your media")</h1>
|
||||
|
@ -12,22 +11,33 @@
|
|||
<a href="@uri!(medias::new)" class="inline-block button">@i18n!(ctx.1, "Upload")</a>
|
||||
</div>
|
||||
|
||||
<section>
|
||||
@if medias.is_empty() {
|
||||
<p>@i18n!(ctx.1, "You don't have any media yet.")</p>
|
||||
}
|
||||
<div class="list">
|
||||
|
||||
<div class="cards spaced">
|
||||
@for media in medias {
|
||||
<div class="card flex">
|
||||
@Html(media.preview_html(ctx.0).unwrap_or(SafeString::new("")))
|
||||
<main class="grow">
|
||||
<p><a href="@uri!(medias::details: id = media.id)">@media.alt_text</a></p>
|
||||
<div class="card">
|
||||
<div class="cover media-preview @media.category().to_string()"
|
||||
@if media.category() == MediaCategory::Image {
|
||||
style="background-image: url('@media.url(ctx.0).unwrap_or_default()')"
|
||||
}
|
||||
></div>
|
||||
<main>
|
||||
<p class="p-summary">@media.alt_text</p>
|
||||
@if let Some(cw) = media.content_warning {
|
||||
<p>@i18n!(ctx.1, "Content warning: {0}"; cw)</p>
|
||||
}
|
||||
</main>
|
||||
<footer>
|
||||
<form action="@uri!(medias::delete: id = media.id)" class="inline" method="POST">
|
||||
<input type="submit" value="@i18n!(ctx.1, "Delete")"/>
|
||||
</form>
|
||||
—
|
||||
<a href="@uri!(medias::details: id = media.id)">@i18n!(ctx.1, "Details")</a>
|
||||
</footer>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</section>
|
||||
@paginate(ctx.1, page, n_pages)
|
||||
})
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
<main>
|
||||
<p class="p-summary">@article.subtitle</p>
|
||||
</main>
|
||||
<p class="author">
|
||||
<footer class="authors">
|
||||
@Html(i18n!(ctx.1, "By {0}"; format!(
|
||||
"<a class=\"p-author h-card\" href=\"{}\">{}</a>",
|
||||
uri!(user::details: name = article.get_authors(ctx.0).unwrap_or_default()[0].get_fqn(ctx.0)),
|
||||
|
@ -29,6 +29,6 @@
|
|||
@if !article.published {
|
||||
⋅ @i18n!(ctx.1, "Draft")
|
||||
}
|
||||
</p>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -27,6 +27,10 @@
|
|||
<label for="plume-editor">@i18n!(ctx.1, "Content")<small>@i18n!(ctx.1, "Markdown syntax is supported")</small></label>
|
||||
<textarea id="plume-editor" name="content" rows="20">@form.content</textarea>
|
||||
<small id="editor-left">@content_len</small>
|
||||
<p>
|
||||
@i18n!(ctx.1, "You can upload medias to your gallery, and copy their Markdown code in your articles to insert them.")
|
||||
<a href="@uri!(medias::new)">@i18n!(ctx.1, "Upload media")</a>
|
||||
</p>
|
||||
|
||||
@input!(ctx.1, tags (optional text), "Tags, separated by commas", form, errors.clone(), "")
|
||||
|
||||
|
|
|
@ -37,6 +37,6 @@
|
|||
|
||||
<section>
|
||||
<h2>@i18n!(ctx.1, "Your media")</h2>
|
||||
<a class="button" href="@uri!(medias::list)">@i18n!(ctx.1, "Go to your gallery")</a>
|
||||
<a class="button" href="@uri!(medias::list: page = _)">@i18n!(ctx.1, "Go to your gallery")</a>
|
||||
</section>
|
||||
})
|
||||
|
|
|
@ -9,6 +9,10 @@
|
|||
@:base(ctx, i18n!(ctx.1, "Edit your account"), {}, {}, {
|
||||
@if let Some(u) = ctx.2.clone() {
|
||||
<h1>@i18n!(ctx.1, "Your Profile")</h1>
|
||||
<p>
|
||||
@i18n!(ctx.1, "To change your avatar, upload it in your gallery and select from there.")
|
||||
<a href="@uri!(medias::new)">@i18n!(ctx.1, "Upload an avatar")</a>
|
||||
</p>
|
||||
<form method="post" action="@uri!(user::update: _name = u.username.clone())">
|
||||
<!-- Rocket hack to use various HTTP methods -->
|
||||
<input type=hidden name="_method" value="put">
|
||||
|
|
Loading…
Reference in a new issue