diff --git a/web/graphql/schema.json b/web/graphql/schema.json index 2e7095c..384ccb7 100644 --- a/web/graphql/schema.json +++ b/web/graphql/schema.json @@ -59,6 +59,57 @@ }, "subscriptionType": null, "types": [ + { + "description": null, + "enumValues": null, + "fields": [ + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "filename", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "contentType", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "contentId", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + ], + "inputFields": null, + "interfaces": [], + "kind": "OBJECT", + "name": "Attachment", + "possibleTypes": null + }, { "description": null, "enumValues": null, @@ -140,6 +191,49 @@ "name": "Float", "possibleTypes": null }, + { + "description": null, + "enumValues": null, + "fields": [ + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "key", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "value", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + ], + "inputFields": null, + "interfaces": [], + "kind": "OBJECT", + "name": "Header", + "possibleTypes": null + }, { "description": null, "enumValues": null, @@ -175,6 +269,30 @@ "ofType": null } } + }, + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "headers", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Header", + "ofType": null + } + } + } + } } ], "inputFields": null, @@ -307,6 +425,30 @@ "ofType": null } }, + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "headers", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Header", + "ofType": null + } + } + } + } + }, { "args": [], "deprecationReason": null, @@ -338,6 +480,30 @@ "ofType": null } } + }, + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "attachments", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Attachment", + "ofType": null + } + } + } + } } ], "inputFields": null, diff --git a/web/graphql/show_thread.graphql b/web/graphql/show_thread.graphql index 41c7d04..45a17aa 100644 --- a/web/graphql/show_thread.graphql +++ b/web/graphql/show_thread.graphql @@ -32,6 +32,11 @@ query ShowThreadQuery($threadId: String!) { } } path + attachments { + filename + contentType + contentId + } } } tags { diff --git a/web/src/view/mod.rs b/web/src/view/mod.rs index 9eae79e..acc69e3 100644 --- a/web/src/view/mod.rs +++ b/web/src/view/mod.rs @@ -21,6 +21,7 @@ mod legacy; mod mobile; mod tablet; +const MAX_RAW_MESSAGE_SIZE: usize = 100_000; fn set_title(title: &str) { seed::document().set_title(&format!("lb: {}", title)); } @@ -250,6 +251,18 @@ fn view_addresses(addrs: &[impl Email]) -> Vec> { addrs.into_iter().map(view_address).collect::>() } +fn raw_text_message(contents: &str) -> Node { + let (contents, truncated_msg) = if contents.len() > MAX_RAW_MESSAGE_SIZE { + ( + &contents[..MAX_RAW_MESSAGE_SIZE], + Some(div!["... contents truncated"]), + ) + } else { + (contents, None) + }; + div![C!["view-part-text-plain"], contents, truncated_msg,] +} + fn thread(thread: &ShowThreadQueryThread) -> Node { // TODO(wathiede): show per-message subject if it changes significantly from top-level subject set_title(&thread.subject); @@ -279,7 +292,7 @@ fn thread(thread: &ShowThreadQueryThread) -> Node { contents, content_tree, }, - ) => div![C!["view-part-text-plain"], contents, pre![content_tree]], + ) => div![raw_text_message(&contents), pre![content_tree]], ShowThreadQueryThreadMessagesBody::Html( ShowThreadQueryThreadMessagesBodyOnHtml { contents, @@ -290,12 +303,12 @@ fn thread(thread: &ShowThreadQueryThread) -> Node { raw![contents], IF!(!msg.attachments.is_empty() => div![ - C!["attachments"], - br![], - h2!["Attachments"], - msg.attachments - .iter() - .map(|a| div!["Filename: ", &a.filename, " ", &a.content_type]) + C!["attachments"], + br![], + h2!["Attachments"], + msg.attachments + .iter() + .map(|a| div!["Filename: ", &a.filename, " ", &a.content_type]) ]), pre![content_tree] ],