Clean up EmailEntry API
Move into composer namespace and rename to match. Update API for consistency with style guide. Remove uneeded fields and clarify when ::modified is true. Fix call sites.
This commit is contained in:
parent
19fc5eced3
commit
b3fa1446c1
5 changed files with 138 additions and 133 deletions
|
|
@ -51,6 +51,7 @@ src/client/components/status-bar.vala
|
|||
src/client/components/stock.vala
|
||||
src/client/composer/composer-box.vala
|
||||
src/client/composer/composer-container.vala
|
||||
src/client/composer/composer-email-entry.vala
|
||||
src/client/composer/composer-embed.vala
|
||||
src/client/composer/composer-headerbar.vala
|
||||
src/client/composer/composer-link-popover.vala
|
||||
|
|
@ -58,7 +59,6 @@ src/client/composer/composer-web-view.vala
|
|||
src/client/composer/composer-widget.vala
|
||||
src/client/composer/composer-window.vala
|
||||
src/client/composer/contact-entry-completion.vala
|
||||
src/client/composer/email-entry.vala
|
||||
src/client/composer/spell-check-popover.vala
|
||||
src/client/conversation-list/conversation-list-cell-renderer.vala
|
||||
src/client/conversation-list/conversation-list-store.vala
|
||||
|
|
|
|||
113
src/client/composer/composer-email-entry.vala
Normal file
113
src/client/composer/composer-email-entry.vala
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* Copyright 2016 Software Freedom Conservancy Inc.
|
||||
* Copyright 2020 Michael Gratton <mike@vee.net>
|
||||
*
|
||||
* This software is licensed under the GNU Lesser General Public License
|
||||
* (version 2.1 or later). See the COPYING file in this distribution.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A GTK entry for entering email addresses.
|
||||
*/
|
||||
public class Composer.EmailEntry : Gtk.Entry {
|
||||
|
||||
/** The entry's list of possibly valid email addresses. */
|
||||
public Geary.RFC822.MailboxAddresses addresses {
|
||||
get { return this._addresses; }
|
||||
set {
|
||||
this._addresses = value;
|
||||
validate_addresses();
|
||||
this.is_modified = false;
|
||||
this.text = value.to_full_display();
|
||||
}
|
||||
}
|
||||
private Geary.RFC822.MailboxAddresses _addresses = new Geary.RFC822.MailboxAddresses();
|
||||
|
||||
/** Determines if the entry contains only valid email addresses. */
|
||||
public bool is_valid { get; private set; default = false; }
|
||||
|
||||
/** Determines if the entry contains any email addresses. */
|
||||
public bool is_empty {
|
||||
get {
|
||||
return this._addresses.is_empty;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the entry has been modified.
|
||||
*
|
||||
* The entry is considered to be modified only if the text has
|
||||
* been changed after it as been constructed or if modified after
|
||||
* setting {@link addresses}.
|
||||
*/
|
||||
public bool is_modified { get; private set; default = false; }
|
||||
|
||||
private weak Composer.Widget composer;
|
||||
|
||||
|
||||
public EmailEntry(Composer.Widget composer) {
|
||||
changed.connect(on_changed);
|
||||
key_press_event.connect(on_key_press);
|
||||
this.composer = composer;
|
||||
show();
|
||||
}
|
||||
|
||||
/** Marks the entry as being modified. */
|
||||
public void set_modified() {
|
||||
this.is_modified = true;
|
||||
}
|
||||
|
||||
private void validate_addresses() {
|
||||
bool is_valid = !this.addresses.is_empty;
|
||||
foreach (Geary.RFC822.MailboxAddress address in this.addresses) {
|
||||
if (!address.is_valid()) {
|
||||
is_valid = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.is_valid = is_valid;
|
||||
}
|
||||
|
||||
private void on_changed() {
|
||||
this.is_modified = true;
|
||||
|
||||
ContactEntryCompletion? completion =
|
||||
get_completion() as ContactEntryCompletion;
|
||||
if (completion != null) {
|
||||
completion.update_model();
|
||||
}
|
||||
|
||||
if (Geary.String.is_empty(text.strip())) {
|
||||
this.addresses = new Geary.RFC822.MailboxAddresses();
|
||||
this.is_valid = false;
|
||||
} else {
|
||||
this.addresses =
|
||||
new Geary.RFC822.MailboxAddresses.from_rfc822_string(text);
|
||||
this.is_valid = true;
|
||||
}
|
||||
}
|
||||
|
||||
private bool on_key_press(Gtk.Widget widget, Gdk.EventKey event) {
|
||||
bool ret = Gdk.EVENT_PROPAGATE;
|
||||
if (event.keyval == Gdk.Key.Tab) {
|
||||
ContactEntryCompletion? completion = (
|
||||
get_completion() as ContactEntryCompletion
|
||||
);
|
||||
if (completion != null) {
|
||||
completion.trigger_selection();
|
||||
composer.child_focus(Gtk.DirectionType.TAB_FORWARD);
|
||||
ret = Gdk.EVENT_STOP;
|
||||
}
|
||||
} else {
|
||||
// Keyboard shortcuts for undo/redo won't work when the
|
||||
// completion UI is visible unless we explicitly check for
|
||||
// them there. This may be related to the
|
||||
// single-key-shortcut handling hack in the MainWindow.
|
||||
Gtk.Window? window = get_toplevel() as Gtk.Window;
|
||||
if (window != null) {
|
||||
ret = window.activate_key(event);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
|
@ -255,10 +255,10 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
|
|||
/** Determines if the composer is completely empty. */
|
||||
public bool is_blank {
|
||||
get {
|
||||
return this.to_entry.empty
|
||||
&& this.cc_entry.empty
|
||||
&& this.bcc_entry.empty
|
||||
&& this.reply_to_entry.empty
|
||||
return this.to_entry.is_empty
|
||||
&& this.cc_entry.is_empty
|
||||
&& this.bcc_entry.is_empty
|
||||
&& this.reply_to_entry.is_empty
|
||||
&& this.subject_entry.buffer.length == 0
|
||||
&& this.editor.is_empty
|
||||
&& this.attached_files.size == 0;
|
||||
|
|
@ -1017,29 +1017,28 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
|
|||
else
|
||||
this.compose_type = ComposeType.REPLY_ALL;
|
||||
|
||||
this.to_entry.modified = this.cc_entry.modified = this.bcc_entry.modified = false;
|
||||
if (!to_entry.addresses.equal_to(reply_to_addresses))
|
||||
this.to_entry.modified = true;
|
||||
this.to_entry.set_modified();
|
||||
if (cc != "" && !cc_entry.addresses.equal_to(reply_cc_addresses))
|
||||
this.cc_entry.modified = true;
|
||||
this.cc_entry.set_modified();
|
||||
if (bcc != "")
|
||||
this.bcc_entry.modified = true;
|
||||
this.bcc_entry.set_modified();
|
||||
|
||||
// We're in compact inline mode, but there are modified email
|
||||
// addresses, so set us to use plain inline mode instead so
|
||||
// the modified addresses can be seen. If there are CC
|
||||
if (this.current_mode == INLINE_COMPACT && (
|
||||
this.to_entry.modified ||
|
||||
this.cc_entry.modified ||
|
||||
this.bcc_entry.modified ||
|
||||
this.reply_to_entry.modified)) {
|
||||
this.to_entry.is_modified ||
|
||||
this.cc_entry.is_modified ||
|
||||
this.bcc_entry.is_modified ||
|
||||
this.reply_to_entry.is_modified)) {
|
||||
set_mode(INLINE);
|
||||
}
|
||||
|
||||
// If there's a modified header that would normally be hidden,
|
||||
// show full fields.
|
||||
if (this.bcc_entry.modified ||
|
||||
this.reply_to_entry.modified) {
|
||||
if (this.bcc_entry.is_modified ||
|
||||
this.reply_to_entry.is_modified) {
|
||||
this.editor_actions.change_action_state(
|
||||
ACTION_SHOW_EXTENDED_HEADERS, true
|
||||
);
|
||||
|
|
@ -1402,7 +1401,7 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
|
|||
if (!modify_headers)
|
||||
return;
|
||||
|
||||
bool recipients_modified = this.to_entry.modified || this.cc_entry.modified || this.bcc_entry.modified;
|
||||
bool recipients_modified = this.to_entry.is_modified || this.cc_entry.is_modified || this.bcc_entry.is_modified;
|
||||
if (!recipients_modified) {
|
||||
if (type == ComposeType.REPLY || type == ComposeType.REPLY_ALL)
|
||||
this.to_entry.addresses = Geary.RFC822.Utils.merge_addresses(to_entry.addresses,
|
||||
|
|
@ -1414,7 +1413,6 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
|
|||
else
|
||||
this.cc_entry.addresses = Geary.RFC822.Utils.remove_addresses(this.cc_entry.addresses,
|
||||
this.to_entry.addresses);
|
||||
this.to_entry.modified = this.cc_entry.modified = false;
|
||||
}
|
||||
|
||||
if (referred.message_id != null) {
|
||||
|
|
@ -1953,16 +1951,16 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
|
|||
// To must be valid (and hence non-empty), the other email
|
||||
// fields must be either empty or valid.
|
||||
get_action(ACTION_SEND).set_enabled(
|
||||
this.to_entry.valid &&
|
||||
(this.cc_entry.empty || this.cc_entry.valid) &&
|
||||
(this.bcc_entry.empty || this.bcc_entry.valid) &&
|
||||
(this.reply_to_entry.empty || this.reply_to_entry.valid)
|
||||
this.to_entry.is_valid &&
|
||||
(this.cc_entry.is_empty || this.cc_entry.is_valid) &&
|
||||
(this.bcc_entry.is_empty || this.bcc_entry.is_valid) &&
|
||||
(this.reply_to_entry.is_empty || this.reply_to_entry.is_valid)
|
||||
);
|
||||
}
|
||||
|
||||
private void set_compact_header_recipients() {
|
||||
bool tocc = !this.to_entry.empty && !this.cc_entry.empty,
|
||||
ccbcc = !(this.to_entry.empty && this.cc_entry.empty) && !this.bcc_entry.empty;
|
||||
bool tocc = !this.to_entry.is_empty && !this.cc_entry.is_empty,
|
||||
ccbcc = !(this.to_entry.is_empty && this.cc_entry.is_empty) && !this.bcc_entry.is_empty;
|
||||
string label = this.to_entry.buffer.text + (tocc ? ", " : "")
|
||||
+ this.cc_entry.buffer.text + (ccbcc ? ", " : "") + this.bcc_entry.buffer.text;
|
||||
StringBuilder tooltip = new StringBuilder();
|
||||
|
|
@ -2145,9 +2143,9 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
|
|||
}
|
||||
|
||||
private void update_extended_headers(bool reorder=true) {
|
||||
bool cc = this.cc_entry.addresses != null;
|
||||
bool bcc = this.bcc_entry.addresses != null;
|
||||
bool reply_to = this.reply_to_entry.addresses != null;
|
||||
bool cc = !this.cc_entry.is_empty;
|
||||
bool bcc = !this.bcc_entry.is_empty;
|
||||
bool reply_to = !this.reply_to_entry.is_empty;
|
||||
|
||||
if (reorder) {
|
||||
if (cc) {
|
||||
|
|
|
|||
|
|
@ -1,106 +0,0 @@
|
|||
/* Copyright 2016 Software Freedom Conservancy Inc.
|
||||
*
|
||||
* This software is licensed under the GNU Lesser General Public License
|
||||
* (version 2.1 or later). See the COPYING file in this distribution.
|
||||
*/
|
||||
|
||||
// A custom entry for e-mail addresses
|
||||
public class EmailEntry : Gtk.Entry {
|
||||
// Whether this entry contains a valid email address
|
||||
public bool valid { get; set; default = false; }
|
||||
|
||||
public bool empty { get; set; default = true; }
|
||||
|
||||
public bool modified = false;
|
||||
|
||||
// null or valid addresses
|
||||
public Geary.RFC822.MailboxAddresses? addresses { get; set; default = null; }
|
||||
|
||||
private weak Composer.Widget composer;
|
||||
|
||||
private bool updating = false;
|
||||
|
||||
public EmailEntry(Composer.Widget composer) {
|
||||
changed.connect(on_changed);
|
||||
key_press_event.connect(on_key_press);
|
||||
this.composer = composer;
|
||||
|
||||
notify["addresses"].connect(() => {
|
||||
validate_addresses();
|
||||
if (updating)
|
||||
return;
|
||||
|
||||
updating = true;
|
||||
modified = true;
|
||||
text = (addresses == null) ? "" : addresses.to_full_display();
|
||||
updating = false;
|
||||
});
|
||||
|
||||
show();
|
||||
}
|
||||
|
||||
private void on_changed() {
|
||||
if (updating)
|
||||
return;
|
||||
modified = true;
|
||||
|
||||
ContactEntryCompletion? completion = get_completion() as ContactEntryCompletion;
|
||||
if (completion != null) {
|
||||
completion.update_model();
|
||||
}
|
||||
|
||||
if (Geary.String.is_empty(text.strip())) {
|
||||
updating = true;
|
||||
addresses = null;
|
||||
updating = false;
|
||||
valid = false;
|
||||
empty = true;
|
||||
return;
|
||||
}
|
||||
|
||||
updating = true;
|
||||
addresses = new Geary.RFC822.MailboxAddresses.from_rfc822_string(text);
|
||||
updating = false;
|
||||
}
|
||||
|
||||
private void validate_addresses() {
|
||||
if (addresses == null || addresses.size == 0) {
|
||||
valid = false;
|
||||
empty = true;
|
||||
return;
|
||||
}
|
||||
empty = false;
|
||||
|
||||
foreach (Geary.RFC822.MailboxAddress address in addresses) {
|
||||
if (!address.is_valid()) {
|
||||
valid = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
valid = true;
|
||||
}
|
||||
|
||||
private bool on_key_press(Gtk.Widget widget, Gdk.EventKey event) {
|
||||
bool ret = Gdk.EVENT_PROPAGATE;
|
||||
if (event.keyval == Gdk.Key.Tab) {
|
||||
ContactEntryCompletion? completion = (
|
||||
get_completion() as ContactEntryCompletion
|
||||
);
|
||||
if (completion != null) {
|
||||
completion.trigger_selection();
|
||||
composer.child_focus(Gtk.DirectionType.TAB_FORWARD);
|
||||
ret = Gdk.EVENT_STOP;
|
||||
}
|
||||
} else {
|
||||
// Keyboard shortcuts for undo/redo won't work when the
|
||||
// completion UI is visible unless we explicitly check for
|
||||
// them there. This may be related to the
|
||||
// single-key-shortcut handling hack in the MainWindow.
|
||||
Gtk.Window? window = get_toplevel() as Gtk.Window;
|
||||
if (window != null) {
|
||||
ret = window.activate_key(event);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
|
@ -53,6 +53,7 @@ geary_client_vala_sources = files(
|
|||
|
||||
'composer/composer-box.vala',
|
||||
'composer/composer-container.vala',
|
||||
'composer/composer-email-entry.vala',
|
||||
'composer/composer-embed.vala',
|
||||
'composer/composer-headerbar.vala',
|
||||
'composer/composer-link-popover.vala',
|
||||
|
|
@ -60,7 +61,6 @@ geary_client_vala_sources = files(
|
|||
'composer/composer-widget.vala',
|
||||
'composer/composer-window.vala',
|
||||
'composer/contact-entry-completion.vala',
|
||||
'composer/email-entry.vala',
|
||||
'composer/spell-check-popover.vala',
|
||||
|
||||
'conversation-list/conversation-list-cell-renderer.vala',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue