Allow HTML signatures
We search for HTML-like tags in signatures, and don't do much as much escaping if we find one. For .signature files detected to be HTML, we insert them without any change. User-entered signatures get their whitespace protected, even when HTML is detected. The existing code for preserving whitespace doesn't work when there's already HTML code in the text (it converts "<a b>" to "<a b>"), so instead we preserve the whitespace with CSS. A preview of the signature is added to the the UI. There's a TextView and a WebView in a Stack, and we swap between them with a StackSwitcher. Some of the packing details are changed so that these views are the thing that expands when the dialog size changes. https://bugzilla.gnome.org/show_bug.cgi?id=738895
This commit is contained in:
parent
11d8038422
commit
c87bbea3ab
5 changed files with 65 additions and 28 deletions
|
|
@ -38,7 +38,7 @@ public class AccountDialogAddEditPane : AccountDialogPane {
|
|||
add_edit_page.size_changed.connect(() => { size_changed(); } );
|
||||
|
||||
pack_start(add_edit_page);
|
||||
pack_start(button_box);
|
||||
pack_start(button_box, false, false);
|
||||
|
||||
// Default mode is Welcome.
|
||||
set_mode(AddEditPage.PageMode.WELCOME);
|
||||
|
|
|
|||
|
|
@ -173,7 +173,9 @@ public class AddEditPage : Gtk.Box {
|
|||
// Signature
|
||||
private Gtk.Box composer_container;
|
||||
private Gtk.CheckButton check_use_email_signature;
|
||||
private Gtk.Stack signature_stack;
|
||||
private Gtk.TextView textview_email_signature;
|
||||
private StylishWebView preview_webview;
|
||||
|
||||
private Gtk.Alignment other_info;
|
||||
|
||||
|
|
@ -257,7 +259,32 @@ public class AddEditPage : Gtk.Box {
|
|||
// composer options
|
||||
composer_container = (Gtk.Box) builder.get_object("composer container");
|
||||
check_use_email_signature = (Gtk.CheckButton) builder.get_object("check: use_email_signature");
|
||||
textview_email_signature = (Gtk.TextView) builder.get_object("textview: email_signature");
|
||||
|
||||
Gtk.ScrolledWindow edit_window = new Gtk.ScrolledWindow(null, null);
|
||||
edit_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC);
|
||||
edit_window.set_shadow_type(Gtk.ShadowType.IN);
|
||||
textview_email_signature = new Gtk.TextView();
|
||||
edit_window.add(textview_email_signature);
|
||||
|
||||
Gtk.ScrolledWindow preview_window = new Gtk.ScrolledWindow(null, null);
|
||||
preview_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC);
|
||||
preview_window.set_shadow_type(Gtk.ShadowType.IN);
|
||||
preview_webview = new StylishWebView();
|
||||
preview_window.add(preview_webview);
|
||||
|
||||
signature_stack = new Gtk.Stack();
|
||||
signature_stack.add_titled(edit_window, "edit_window", _("Edit"));
|
||||
signature_stack.child_set_property(edit_window, "icon-name", "text-editor-symbolic");
|
||||
signature_stack.add_titled(preview_window, "preview_window", _("Preview"));
|
||||
signature_stack.child_set_property(preview_window, "icon-name", "text-x-generic-symbolic");
|
||||
Gtk.StackSwitcher switcher = new Gtk.StackSwitcher();
|
||||
switcher.set_stack(signature_stack);
|
||||
|
||||
Gtk.Box signature_box = (Gtk.Box) builder.get_object("signature box");
|
||||
signature_box.set_spacing(4);
|
||||
signature_box.pack_start(signature_stack);
|
||||
switcher.valign = Gtk.Align.START;
|
||||
signature_box.pack_start(switcher, false, false);
|
||||
|
||||
// IMAP info widgets.
|
||||
entry_imap_host = (Gtk.Entry) builder.get_object("entry: imap host");
|
||||
|
|
@ -316,7 +343,8 @@ public class AddEditPage : Gtk.Box {
|
|||
|
||||
entry_nickname.insert_text.connect(on_nickname_insert_text);
|
||||
|
||||
check_use_email_signature.toggled.connect(() => on_use_signature_changed());
|
||||
check_use_email_signature.bind_property("active", signature_box, "sensitive");
|
||||
signature_stack.notify["visible-child-name"].connect(on_signature_stack_changed);
|
||||
|
||||
// Reset the "first update" flag when the window is mapped.
|
||||
map.connect(() => { first_ui_update = true; });
|
||||
|
|
@ -394,6 +422,7 @@ public class AddEditPage : Gtk.Box {
|
|||
combo_smtp_encryption.active = Encryption.NONE;
|
||||
use_email_signature = initial_use_email_signature;
|
||||
email_signature = initial_email_signature;
|
||||
signature_stack.set_visible_child_name("edit_window");
|
||||
|
||||
// Set defaults for IMAP info
|
||||
imap_host = initial_default_imap_host ?? "";
|
||||
|
|
@ -550,12 +579,9 @@ public class AddEditPage : Gtk.Box {
|
|||
}
|
||||
}
|
||||
|
||||
private void on_use_signature_changed() {
|
||||
if(check_use_email_signature.active == true) {
|
||||
textview_email_signature.sensitive = true;
|
||||
} else {
|
||||
textview_email_signature.sensitive = false;
|
||||
}
|
||||
private void on_signature_stack_changed() {
|
||||
if (signature_stack.visible_child_name == "preview_window")
|
||||
preview_webview.load_html_string(Geary.HTML.smart_escape(email_signature, true), "");
|
||||
}
|
||||
|
||||
private uint16 get_default_smtp_port() {
|
||||
|
|
|
|||
|
|
@ -993,6 +993,7 @@ public class ComposerWidget : Gtk.EventBox {
|
|||
set_cursor();
|
||||
return;
|
||||
}
|
||||
signature = Geary.HTML.smart_escape(signature, false);
|
||||
} catch (Error error) {
|
||||
debug("Error reading signature file %s: %s", signature_file.get_path(), error.message);
|
||||
set_cursor();
|
||||
|
|
@ -1004,16 +1005,15 @@ public class ComposerWidget : Gtk.EventBox {
|
|||
set_cursor();
|
||||
return;
|
||||
}
|
||||
signature = Geary.HTML.smart_escape(signature, true);
|
||||
}
|
||||
|
||||
signature = Geary.HTML.escape_markup(signature);
|
||||
|
||||
if (body_html == null)
|
||||
body_html = CURSOR + Geary.HTML.preserve_whitespace("\n\n" + signature);
|
||||
body_html = CURSOR + "<br /><br />" + signature;
|
||||
else if (top_posting)
|
||||
body_html = CURSOR + Geary.HTML.preserve_whitespace("\n\n" + signature) + body_html;
|
||||
body_html = CURSOR + "<br /><br />" + signature + body_html;
|
||||
else
|
||||
body_html = body_html + CURSOR + Geary.HTML.preserve_whitespace("\n\n" + signature);
|
||||
body_html = body_html + CURSOR + "<br /><br />" + signature;
|
||||
}
|
||||
|
||||
private void set_cursor() {
|
||||
|
|
|
|||
|
|
@ -88,6 +88,21 @@ public string preserve_whitespace(string? text) {
|
|||
return output;
|
||||
}
|
||||
|
||||
public string smart_escape(string? text, bool preserve_whitespace_in_html) {
|
||||
if (text == null)
|
||||
return text;
|
||||
|
||||
string res = text;
|
||||
if (!Regex.match_simple("<([A-Z]*)[^>]*>.*</(\\1)>|<[^>]*/>", res,
|
||||
RegexCompileFlags.CASELESS)) {
|
||||
res = escape_markup(res);
|
||||
preserve_whitespace_in_html = true;
|
||||
}
|
||||
if (preserve_whitespace_in_html)
|
||||
res = @"<div style='white-space: pre;'>$res</div>";
|
||||
return res;
|
||||
}
|
||||
|
||||
// Removes any text between < and >. Additionally, if input terminates in the middle of a tag,
|
||||
// the tag will be removed.
|
||||
// If the HTML is invalid, the original string will be returned.
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
<property name="step_increment">1</property>
|
||||
<property name="page_increment">10</property>
|
||||
</object>
|
||||
<object class="GtkTextBuffer" id="buffer: email_signature"/>
|
||||
<object class="GtkBox" id="container">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
|
|
@ -960,7 +959,7 @@
|
|||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="check: use_email_signature">
|
||||
<property name="label" translatable="yes">Si_gn emails:</property>
|
||||
<property name="label" translatable="yes">Si_gn emails (HTML allowed):</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
|
|
@ -976,23 +975,20 @@
|
|||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="scrolledwindow2">
|
||||
<object class="GtkBox" id="signature box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">12</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<child>
|
||||
<object class="GtkTextView" id="textview: email_signature">
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="wrap_mode">word</property>
|
||||
<property name="buffer">buffer: email_signature</property>
|
||||
</object>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
|
|
@ -1002,7 +998,7 @@
|
|||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue