Commit bc71300f authored by Robert Schroll's avatar Robert Schroll Committed by Jim Nelson

New behavior for hiding quoted text

In their hidden state, quotes will be limited in length, with a link to
extend them.  Only long quotes will be hidden; short ones will be
displayed in their entirety.  Note that the threshold for hiding a quote
is larger than the size of the hidden quote.  This ensures that there
will always be a noticable expansion of a quote when it is shown.  (This
also accounts for the fact that the height we measure includes padding.)

We can only measure the size of a quote once it is actually shown as
part of the document.  Notably, we can't figure out the sizes of quotes
in hidden emails.  Therefore, we also decide which quotes in an email
need to be hidden when the email is unhidden.  However, showing and then
hiding quotes can lead to content flashing, so we start all quotes off
in the hidden state, and remove this if they turn out to be short
enough.
parent 310df30e
......@@ -34,6 +34,7 @@ public class ConversationViewer : Gtk.Box {
private const string REPLACED_IMAGE_CLASS = "replaced_inline_image";
private const string DATA_IMAGE_CLASS = "data_inline_image";
private const int MAX_INLINE_IMAGE_MAJOR_DIM = 1024;
private const int QUOTE_SIZE_THRESHOLD = 120;
private enum SearchState {
// Search/find states.
......@@ -558,6 +559,9 @@ public class ConversationViewer : Gtk.Box {
Idle.add(() => {
try {
div_message.get_class_list().add("animate");
// This will only affect any open emails. Those in the hidden state will have
// their quotes set when they're opened.
unset_controllable_quotes(div_message);
} catch (Error error) {
debug("Could not enable animation class: %s", error.message);
}
......@@ -1119,12 +1123,14 @@ public class ConversationViewer : Gtk.Box {
return;
WebKit.DOM.DOMTokenList class_list = email_element.get_class_list();
if (class_list.contains("compressed"))
if (class_list.contains("compressed")) {
decompress_emails(email_element);
else if (class_list.contains("hide"))
} else if (class_list.contains("hide")) {
class_list.remove("hide");
else
unset_controllable_quotes(email_element);
} else {
class_list.add("hide");
}
} catch (Error error) {
warning("Error toggling message: %s", error.message);
}
......@@ -1614,34 +1620,23 @@ public class ConversationViewer : Gtk.Box {
private WebKit.DOM.HTMLDivElement create_quote_container() throws Error {
WebKit.DOM.HTMLDivElement quote_container = web_view.create_div();
quote_container.set_attribute("class", "quote_container");
quote_container.set_inner_html("%s%s%s".printf("<div class=\"shower\">[show]</div>",
"<div class=\"hider\">[hide]</div>", "<div class=\"quote\"></div>"));
quote_container.set_attribute("class", "quote_container controllable hide");
quote_container.set_inner_html(
"""<div class="shower"><input type="button" value=" " /></div>""" +
"""<div class="hider"><input type="button" value=" " /></div>""" +
"""<div class="quote"></div>""");
return quote_container;
}
private string set_up_quotes(string text) {
try {
// Extract any quote containers from the signature block and make them controllable.
WebKit.DOM.HTMLElement container = web_view.create_div();
container.set_inner_html(text);
WebKit.DOM.NodeList quote_list = container.query_selector_all(".signature .quote_container");
for (int i = 0; i < quote_list.length; ++i) {
WebKit.DOM.Element quote = quote_list.item(i) as WebKit.DOM.Element;
quote.set_attribute("class", "quote_container controllable hide");
container.append_child(quote);
private void unset_controllable_quotes(WebKit.DOM.HTMLElement element) throws GLib.Error {
WebKit.DOM.NodeList quote_list = element.query_selector_all(".quote_container.controllable");
for (int i = 0; i < quote_list.length; ++i) {
WebKit.DOM.Element quote_container = quote_list.item(i) as WebKit.DOM.Element;
long scroll_height = quote_container.query_selector(".quote").scroll_height;
// If the message is hidden, scroll_height will be 0.
if (scroll_height > 0 && scroll_height < QUOTE_SIZE_THRESHOLD) {
quote_container.set_attribute("class", "quote_container");
}
// If there is only one quote container in the message, set it up as controllable.
quote_list = container.query_selector_all(".quote_container");
if (quote_list.length == 1) {
((WebKit.DOM.Element) quote_list.item(0)).set_attribute("class",
"quote_container controllable hide");
}
return container.get_inner_html();
} catch (Error error) {
debug("Error adjusting final quote block: %s", error.message);
return text;
}
}
......@@ -1732,7 +1727,7 @@ public class ConversationViewer : Gtk.Box {
}
// Now return the whole message.
return set_up_quotes(container.get_inner_html());
return container.get_inner_html();
} catch (Error e) {
debug("Error modifying HTML message: %s", e.message);
return text;
......
......@@ -487,12 +487,24 @@ body.nohide .email .compressed_note > span {
}
.quote_container {
position: relative;
margin: 5px 0;
padding: 12px;
color: #303030;
background-color: #e8e8e8;/* recv-quoted */
border-radius: 4px;
}
.quote_container .quote {
overflow: hidden;
position: relative;
z-index: 0;
}
body:not(.nohide) .quote_container.controllable .quote {
max-height: 80px;
}
body:not(.nohide) .quote_container.controllable.show .quote {
max-height: none;
}
.email.sent .quote_container {
background-color: #e8e8e8;/* sent-quoted */
......@@ -500,30 +512,38 @@ body.nohide .email .compressed_note > span {
.quote_container > .shower,
.quote_container > .hider {
color: #777;
font-family: sans-serif;
font-size: 75%;
cursor: pointer;
position: absolute;
z-index: 1;
bottom: -7px;
left: 0;
right: 0;
padding: 0 20%;
display: none;
}
.quote_container > .shower > input,
.quote_container > .hider > input {
width: 100%;
height: 15px;
padding: 0;
font-size: 7px;
color: #888;
}
.quote_container > .shower:hover > input,
.quote_container > .hider:hover > input {
color: #000;
}
body:not(.nohide) .quote_container.controllable {
margin-bottom: 7px;
}
body:not(.nohide) .quote_container.controllable > .shower {
display: block;
}
.quote_container.controllable > .hider,
body:not(.nohide) .quote_container.controllable > .quote {
display: none;
}
body:not(.nohide) .quote_container.controllable.show > .shower {
display: none;
}
body:not(.nohide) .quote_container.controllable.show > .hider,
body:not(.nohide) .quote_container.controllable.show > .quote {
body:not(.nohide) .quote_container.controllable.show > .hider {
display: block;
}
.quote_container > .shower:hover,
.quote_container > .hider:hover {
color: black;
}
#message_container {
position: absolute;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment