vietnamese
This commit is contained in:
@@ -239,6 +239,13 @@ pub async fn call(ctx: &Ctx, widget: &str, func: &str, p: &P<'_>) -> bool {
|
||||
}
|
||||
rpc!(ctx, "Account.refreshFingerprints");
|
||||
}
|
||||
// OMEMO key backups: only the dialogs, the keys stay in the browser
|
||||
("Account", "ajaxOmemoBackup") => {
|
||||
super::dialog(ctx, &ctx.render("Account/_account_omemo_backup.html", json!({})), false, false);
|
||||
}
|
||||
("Account", "ajaxOmemoRestore") => {
|
||||
super::dialog(ctx, &ctx.render("Account/_account_omemo_restore.html", json!({})), false, false);
|
||||
}
|
||||
("Account", "ajaxChangePassword") => {
|
||||
super::dialog(ctx, &ctx.render("Account/_account_password.html", json!({})), false, false);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//! ChatActions widget: actions on a message (react, copy, reply, edit,
|
||||
//! retract, moderate), search in a discussion, URL previews.
|
||||
//! retract, moderate), search in a discussion, shared files, URL previews.
|
||||
|
||||
use serde_json::json;
|
||||
|
||||
@@ -22,9 +22,14 @@ pub async fn call(ctx: &Ctx, func: &str, p: &P<'_>) -> bool {
|
||||
}),
|
||||
);
|
||||
super::drawer(ctx, "chat_search", &html, false, false);
|
||||
send_encrypted_index(ctx, &p.str(0), p.b(1)).await;
|
||||
rpc!(ctx, "ChatActions.focusSearch");
|
||||
}
|
||||
"ajaxSearchMessages" => search(ctx, &p.str(0), &p.str(1), p.b(2)).await,
|
||||
"ajaxSearchMessages" => {
|
||||
let encrypted: Vec<i64> = p.v(3).and_then(|v| v.as_array()).map(|a| a.iter().filter_map(|m| m.as_i64()).collect()).unwrap_or_default();
|
||||
search(ctx, &p.str(0), &p.str(1), p.b(2), &encrypted).await;
|
||||
}
|
||||
"ajaxShowFiles" => show_files(ctx, &p.str(0), p.b(1)).await,
|
||||
"ajaxCopiedMessageText" => ctx.toast(&ctx.t("chatactions.copied_text", &[])),
|
||||
"ajaxHttpDaemonRetract" => retract(ctx, p.i(0).unwrap_or(0)).await,
|
||||
"ajaxHttpDaemonModerate" => moderate(ctx, p.i(0).unwrap_or(0)).await,
|
||||
@@ -117,7 +122,63 @@ async fn show_message_dialog(ctx: &Ctx, mid: i64) {
|
||||
super::dialog(ctx, &html, false, false);
|
||||
}
|
||||
|
||||
async fn search(ctx: &Ctx, jid: &str, keywords: &str, muc: bool) {
|
||||
/// The browser searches and lists the OMEMO messages itself (the server
|
||||
/// cannot read them): it gets their ids, and looks the decrypted bodies up
|
||||
async fn send_encrypted_index(ctx: &Ctx, jid: &str, muc: bool) {
|
||||
if !utils::validate_jid(jid) || !ctx.me().is_some_and(|u| u.omemoenabled) {
|
||||
return;
|
||||
}
|
||||
let index = db::encrypted_index(ctx.db(), &ctx.jid(), jid, muc).await.unwrap_or_default();
|
||||
rpc!(ctx, "ChatActions.setIndex", jid, index);
|
||||
}
|
||||
|
||||
async fn show_files(ctx: &Ctx, jid: &str, muc: bool) {
|
||||
if !utils::validate_jid(jid) {
|
||||
return;
|
||||
}
|
||||
let units = [
|
||||
ctx.t("filesize.byte", &[]),
|
||||
ctx.t("filesize.kilobyte", &[]),
|
||||
ctx.t("filesize.megabyte", &[]),
|
||||
ctx.t("filesize.gigabyte", &[]),
|
||||
ctx.t("filesize.terabyte", &[]),
|
||||
];
|
||||
let (mut images, mut videos, mut recordings, mut files) = (vec![], vec![], vec![], vec![]);
|
||||
for f in db::conversation_files(ctx.db(), &ctx.jid(), jid, muc, 500).await.unwrap_or_default() {
|
||||
// Opened by the browser: never a javascript: or data: URL
|
||||
if !f.url.starts_with("https://") && !f.url.starts_with("http://") {
|
||||
continue;
|
||||
}
|
||||
let type_ = f.type_.clone().unwrap_or_default();
|
||||
let item = json!({
|
||||
"mid": f.mid,
|
||||
"url": f.url,
|
||||
"name": f.name.clone().unwrap_or_else(|| f.url.rsplit('/').next().unwrap_or("").to_string()),
|
||||
"size": f.size.map(|s| utils::human_size(s, &units)),
|
||||
"date": ctx.prepare_date(&f.published, false, false),
|
||||
"published": f.published,
|
||||
"thumb": format!("{}picture?url={}", ctx.base_uri(), percent_encoding::utf8_percent_encode(&f.url, percent_encoding::NON_ALPHANUMERIC)),
|
||||
});
|
||||
if utils::type_is_picture(&type_) {
|
||||
images.push(item);
|
||||
} else if type_.starts_with("video/") {
|
||||
videos.push(item);
|
||||
} else if type_.starts_with("audio/") {
|
||||
recordings.push(item);
|
||||
} else {
|
||||
files.push(item);
|
||||
}
|
||||
}
|
||||
let html = ctx.render(
|
||||
"ChatActions/_chatactions_files.html",
|
||||
json!({ "jid": jid, "images": images, "videos": videos, "recordings": recordings, "files": files }),
|
||||
);
|
||||
super::drawer(ctx, "chat_files", &html, false, false);
|
||||
send_encrypted_index(ctx, jid, muc).await;
|
||||
rpc!(ctx, "ChatActions.addEncryptedFiles", jid);
|
||||
}
|
||||
|
||||
async fn search(ctx: &Ctx, jid: &str, keywords: &str, muc: bool, encrypted: &[i64]) {
|
||||
if !utils::validate_jid(jid) {
|
||||
return;
|
||||
}
|
||||
@@ -127,7 +188,7 @@ async fn search(ctx: &Ctx, jid: &str, keywords: &str, muc: bool) {
|
||||
return;
|
||||
}
|
||||
let me = ctx.jid();
|
||||
let messages = db::messages_search(ctx.db(), &me, jid, muc, &keywords, 20).await.unwrap_or_default();
|
||||
let messages = db::messages_search(ctx.db(), &me, jid, muc, &keywords, encrypted, 20).await.unwrap_or_default();
|
||||
let mut list = vec![];
|
||||
for m in &messages {
|
||||
let body = m.body.as_deref().unwrap_or("");
|
||||
@@ -136,6 +197,7 @@ async fn search(ctx: &Ctx, jid: &str, keywords: &str, muc: bool) {
|
||||
list.push(prepare_message(ctx, m, true, Some(highlighted)).await);
|
||||
}
|
||||
rpc!(ctx, "MovimTpl.fill", "#chat_search", ctx.render("ChatActions/_chatactions_search_result.html", json!({ "messages": list })));
|
||||
rpc!(ctx, "ChatActions.fillEncrypted");
|
||||
}
|
||||
|
||||
fn highlight(text: &str, keywords: &str) -> String {
|
||||
|
||||
@@ -107,10 +107,10 @@ async fn request_slot(ctx: &Ctx, name: &str, size: i64, type_: &str) {
|
||||
ctx.st(|st| {
|
||||
st.uploads.insert(
|
||||
id.clone(),
|
||||
Upload { put: put_url, headers, get, name: name.to_string(), size, type_: type_.to_string(), uploaded: false },
|
||||
Upload { put: put_url, headers, get: get.clone(), name: name.to_string(), size, type_: type_.to_string(), uploaded: false },
|
||||
)
|
||||
});
|
||||
rpc!(ctx, "Upload.request", ctx.route("upload", &[&id]), id);
|
||||
rpc!(ctx, "Upload.request", ctx.route("upload", &[&id]), id, get);
|
||||
}
|
||||
Err(e) => {
|
||||
let msg = e.to_string();
|
||||
|
||||
Reference in New Issue
Block a user