Added files
This commit is contained in:
parent
690bd18675
commit
63f719a806
@ -0,0 +1,235 @@
|
||||
From 3b6dd303323cfc5b7bebe5b1d88170f1030f2de2 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Sat, 5 Sep 2020 14:13:01 +1000
|
||||
Subject: [PATCH 001/124] Geary.Db.Context: Update access to
|
||||
DatabaseConnections
|
||||
|
||||
Ensure internal code can access a DatabaseConnection from context
|
||||
objects to get access to connection-specific code, but make the
|
||||
polymorphic context accessors internal so transactions can't access
|
||||
them.
|
||||
---
|
||||
src/engine/db/db-connection.vala | 5 +++--
|
||||
src/engine/db/db-context.vala | 8 ++++----
|
||||
src/engine/db/db-database-connection.vala | 8 ++++----
|
||||
src/engine/db/db-database.vala | 8 ++++----
|
||||
src/engine/db/db-result.vala | 8 ++++----
|
||||
src/engine/db/db-statement.vala | 19 ++++++++++++-------
|
||||
src/engine/db/db-transaction-connection.vala | 11 +----------
|
||||
src/engine/imap-db/imap-db-attachment.vala | 2 +-
|
||||
8 files changed, 33 insertions(+), 36 deletions(-)
|
||||
|
||||
diff --git a/src/engine/db/db-connection.vala b/src/engine/db/db-connection.vala
|
||||
index 4f0859e1..ebce27dc 100644
|
||||
--- a/src/engine/db/db-connection.vala
|
||||
+++ b/src/engine/db/db-connection.vala
|
||||
@@ -18,7 +18,7 @@
|
||||
* A connection will be automatically closed when its last reference
|
||||
* is dropped.
|
||||
*/
|
||||
-public interface Geary.Db.Connection : Context {
|
||||
+public interface Geary.Db.Connection : BaseObject {
|
||||
|
||||
private const string PRAGMA_FOREIGN_KEYS = "foreign_keys";
|
||||
private const string PRAGMA_RECURSIVE_TRIGGERS = "recursive_triggers";
|
||||
@@ -278,7 +278,8 @@ public interface Geary.Db.Connection : Context {
|
||||
*
|
||||
* @see exec
|
||||
*/
|
||||
- public abstract Result query(string sql, GLib.Cancellable? cancellable = null)
|
||||
+ public abstract Result query(string sql,
|
||||
+ GLib.Cancellable? cancellable = null)
|
||||
throws GLib.Error;
|
||||
|
||||
/**
|
||||
diff --git a/src/engine/db/db-context.vala b/src/engine/db/db-context.vala
|
||||
index 9bbb8503..a59f6c4c 100644
|
||||
--- a/src/engine/db/db-context.vala
|
||||
+++ b/src/engine/db/db-context.vala
|
||||
@@ -37,19 +37,19 @@ public abstract class Geary.Db.Context : BaseObject, Logging.Source {
|
||||
private weak Logging.Source? _logging_parent = null;
|
||||
|
||||
|
||||
- public virtual Database? get_database() {
|
||||
+ internal virtual Database? get_database() {
|
||||
return get_connection() != null ? get_connection().database : null;
|
||||
}
|
||||
|
||||
- public virtual Connection? get_connection() {
|
||||
+ internal virtual DatabaseConnection? get_connection() {
|
||||
return get_statement() != null ? get_statement().connection : null;
|
||||
}
|
||||
|
||||
- public virtual Statement? get_statement() {
|
||||
+ internal virtual Statement? get_statement() {
|
||||
return get_result() != null ? get_result().statement : null;
|
||||
}
|
||||
|
||||
- public virtual Result? get_result() {
|
||||
+ internal virtual Result? get_result() {
|
||||
return null;
|
||||
}
|
||||
|
||||
diff --git a/src/engine/db/db-database-connection.vala b/src/engine/db/db-database-connection.vala
|
||||
index 4e7ceb78..dd311bea 100644
|
||||
--- a/src/engine/db/db-database-connection.vala
|
||||
+++ b/src/engine/db/db-database-connection.vala
|
||||
@@ -255,13 +255,13 @@ public class Geary.Db.DatabaseConnection : Context, Connection {
|
||||
return yield job.wait_for_completion_async();
|
||||
}
|
||||
|
||||
- public override Connection? get_connection() {
|
||||
- return this;
|
||||
- }
|
||||
-
|
||||
/** {@inheritDoc} */
|
||||
public override Logging.State to_logging_state() {
|
||||
return new Logging.State(this, "%u", this.cx_number);
|
||||
}
|
||||
|
||||
+ internal override DatabaseConnection? get_connection() {
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
}
|
||||
diff --git a/src/engine/db/db-database.vala b/src/engine/db/db-database.vala
|
||||
index 592bd306..a807e7ba 100644
|
||||
--- a/src/engine/db/db-database.vala
|
||||
+++ b/src/engine/db/db-database.vala
|
||||
@@ -358,10 +358,6 @@ public class Geary.Db.Database : Context {
|
||||
}
|
||||
|
||||
|
||||
- public override Database? get_database() {
|
||||
- return this;
|
||||
- }
|
||||
-
|
||||
/** {@inheritDoc} */
|
||||
public override Logging.State to_logging_state() {
|
||||
return new Logging.State(
|
||||
@@ -386,6 +382,10 @@ public class Geary.Db.Database : Context {
|
||||
this.thread_pool.add(new_job);
|
||||
}
|
||||
|
||||
+ internal override Database? get_database() {
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
/**
|
||||
* Hook for subclasses to modify a new SQLite connection before use.
|
||||
*
|
||||
diff --git a/src/engine/db/db-result.vala b/src/engine/db/db-result.vala
|
||||
index 1ec3ed55..64c78756 100644
|
||||
--- a/src/engine/db/db-result.vala
|
||||
+++ b/src/engine/db/db-result.vala
|
||||
@@ -294,15 +294,15 @@ public class Geary.Db.Result : Geary.Db.Context {
|
||||
return column;
|
||||
}
|
||||
|
||||
- public override Result? get_result() {
|
||||
- return this;
|
||||
- }
|
||||
-
|
||||
/** {@inheritDoc} */
|
||||
public override Logging.State to_logging_state() {
|
||||
return new Logging.State(this, this.finished ? "finished" : "not finished");
|
||||
}
|
||||
|
||||
+ internal override Result? get_result() {
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
[PrintfFormat]
|
||||
private void log_result(string fmt, ...) {
|
||||
if (Db.Context.enable_sql_logging) {
|
||||
diff --git a/src/engine/db/db-statement.vala b/src/engine/db/db-statement.vala
|
||||
index 0a36dfb1..088b882b 100644
|
||||
--- a/src/engine/db/db-statement.vala
|
||||
+++ b/src/engine/db/db-statement.vala
|
||||
@@ -13,7 +13,7 @@ public class Geary.Db.Statement : Context {
|
||||
get { return this.stmt.sql(); }
|
||||
}
|
||||
|
||||
- public Connection connection { get; private set; }
|
||||
+ internal DatabaseConnection connection { get; private set; }
|
||||
|
||||
internal Sqlite.Statement stmt;
|
||||
|
||||
@@ -36,9 +36,14 @@ public class Geary.Db.Statement : Context {
|
||||
|
||||
private Gee.HashSet<Memory.Buffer> held_buffers = new Gee.HashSet<Memory.Buffer>();
|
||||
|
||||
- internal Statement(Connection connection, string sql) throws DatabaseError {
|
||||
+ internal Statement(DatabaseConnection connection, string sql)
|
||||
+ throws DatabaseError {
|
||||
this.connection = connection;
|
||||
- throw_on_error("Statement.ctor", connection.db.prepare_v2(sql, -1, out stmt, null), sql);
|
||||
+ throw_on_error(
|
||||
+ "Statement.ctor",
|
||||
+ connection.db.prepare_v2(sql, -1, out stmt, null),
|
||||
+ sql
|
||||
+ );
|
||||
}
|
||||
|
||||
/** Returns SQL for the statement with bound parameters expanded. */
|
||||
@@ -271,13 +276,13 @@ public class Geary.Db.Statement : Context {
|
||||
return this;
|
||||
}
|
||||
|
||||
- public override Statement? get_statement() {
|
||||
- return this;
|
||||
- }
|
||||
-
|
||||
/** {@inheritDoc} */
|
||||
public override Logging.State to_logging_state() {
|
||||
return new Logging.State(this, this.sql);
|
||||
}
|
||||
|
||||
+ internal override Statement? get_statement() {
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
}
|
||||
diff --git a/src/engine/db/db-transaction-connection.vala b/src/engine/db/db-transaction-connection.vala
|
||||
index 48244dbc..ebdd18b4 100644
|
||||
--- a/src/engine/db/db-transaction-connection.vala
|
||||
+++ b/src/engine/db/db-transaction-connection.vala
|
||||
@@ -9,7 +9,7 @@
|
||||
/**
|
||||
* A connection to the database for transactions.
|
||||
*/
|
||||
-internal class Geary.Db.TransactionConnection : Context, Connection {
|
||||
+internal class Geary.Db.TransactionConnection : BaseObject, Connection {
|
||||
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@@ -54,13 +54,4 @@ internal class Geary.Db.TransactionConnection : Context, Connection {
|
||||
this.db_cx.exec_file(file, cancellable);
|
||||
}
|
||||
|
||||
- public override Connection? get_connection() {
|
||||
- return this;
|
||||
- }
|
||||
-
|
||||
- /** {@inheritDoc} */
|
||||
- public override Logging.State to_logging_state() {
|
||||
- return new Logging.State(this, "");
|
||||
- }
|
||||
-
|
||||
}
|
||||
diff --git a/src/engine/imap-db/imap-db-attachment.vala b/src/engine/imap-db/imap-db-attachment.vala
|
||||
index d8e8f9db..fa94b630 100644
|
||||
--- a/src/engine/imap-db/imap-db-attachment.vala
|
||||
+++ b/src/engine/imap-db/imap-db-attachment.vala
|
||||
@@ -245,7 +245,7 @@ private class Geary.ImapDB.Attachment : Geary.Attachment {
|
||||
}
|
||||
|
||||
// Ensure they're dead, Jim.
|
||||
- Db.Statement stmt = new Db.Statement(cx, """
|
||||
+ Db.Statement stmt = cx.prepare("""
|
||||
DELETE FROM MessageAttachmentTable WHERE message_id = ?
|
||||
""");
|
||||
stmt.bind_rowid(0, message_id);
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,35 @@
|
||||
From e6fd0fe1742bd2143c1fa16fa30e82a5ea7996ed Mon Sep 17 00:00:00 2001
|
||||
From: Adrien Plazas <kekun.plazas@laposte.net>
|
||||
Date: Thu, 23 Apr 2020 10:11:06 +0200
|
||||
Subject: [PATCH 1/8] accounts-editor: Wrap the welcome panel labels
|
||||
|
||||
This helps the accounts editor fit in narrow screens.
|
||||
---
|
||||
ui/accounts_editor_list_pane.ui | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/ui/accounts_editor_list_pane.ui b/ui/accounts_editor_list_pane.ui
|
||||
index 59f8c632..a40604e3 100644
|
||||
--- a/ui/accounts_editor_list_pane.ui
|
||||
+++ b/ui/accounts_editor_list_pane.ui
|
||||
@@ -60,6 +60,8 @@
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="label" translatable="yes">To get started, select an email provider below.</property>
|
||||
+ <property name="xalign">0</property>
|
||||
+ <property name="wrap">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
@@ -73,6 +75,8 @@
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">end</property>
|
||||
<property name="label" translatable="yes">Welcome to Geary</property>
|
||||
+ <property name="xalign">0</property>
|
||||
+ <property name="wrap">True</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,66 @@
|
||||
From c0a89a86e48667b17dcae934e5f3b15a2475abf3 Mon Sep 17 00:00:00 2001
|
||||
From: Julian Sparber <julian@sparber.net>
|
||||
Date: Thu, 22 Oct 2020 15:47:09 +0200
|
||||
Subject: [PATCH 1/2] conversation-email-row: use is-expanded to add/remove css
|
||||
class
|
||||
|
||||
---
|
||||
.../conversation-viewer/conversation-list-box.vala | 12 +++++++++---
|
||||
1 file changed, 9 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/client/conversation-viewer/conversation-list-box.vala b/src/client/conversation-viewer/conversation-list-box.vala
|
||||
index 3eb8240b..f860a2df 100644
|
||||
--- a/src/client/conversation-viewer/conversation-list-box.vala
|
||||
+++ b/src/client/conversation-viewer/conversation-list-box.vala
|
||||
@@ -284,6 +284,7 @@ public class ConversationListBox : Gtk.ListBox, Geary.BaseInterface {
|
||||
}
|
||||
protected set {
|
||||
this._is_expanded = value;
|
||||
+ notify_property("is-expanded");
|
||||
}
|
||||
}
|
||||
private bool _is_expanded = false;
|
||||
@@ -301,6 +302,7 @@ public class ConversationListBox : Gtk.ListBox, Geary.BaseInterface {
|
||||
protected ConversationRow(Geary.Email? email) {
|
||||
base_ref();
|
||||
this.email = email;
|
||||
+ notify["is-expanded"].connect(update_css_class);
|
||||
show();
|
||||
}
|
||||
|
||||
@@ -325,6 +327,13 @@ public class ConversationListBox : Gtk.ListBox, Geary.BaseInterface {
|
||||
this.size_allocate.connect(on_size_allocate);
|
||||
}
|
||||
|
||||
+ private void update_css_class() {
|
||||
+ if (this.is_expanded)
|
||||
+ get_style_context().add_class(EXPANDED_CLASS);
|
||||
+ else
|
||||
+ get_style_context().remove_class(EXPANDED_CLASS);
|
||||
+ }
|
||||
+
|
||||
protected inline void set_style_context_class(string class_name, bool value) {
|
||||
if (value) {
|
||||
get_style_context().add_class(class_name);
|
||||
@@ -392,10 +401,8 @@ public class ConversationListBox : Gtk.ListBox, Geary.BaseInterface {
|
||||
|
||||
private inline void update_row_expansion() {
|
||||
if (this.is_expanded || this.is_pinned) {
|
||||
- get_style_context().add_class(EXPANDED_CLASS);
|
||||
this.view.expand_email();
|
||||
} else {
|
||||
- get_style_context().remove_class(EXPANDED_CLASS);
|
||||
this.view.collapse_email();
|
||||
}
|
||||
}
|
||||
@@ -436,7 +443,6 @@ public class ConversationListBox : Gtk.ListBox, Geary.BaseInterface {
|
||||
base(view.referred);
|
||||
this.view = view;
|
||||
this.is_expanded = true;
|
||||
- get_style_context().add_class(EXPANDED_CLASS);
|
||||
add(this.view);
|
||||
}
|
||||
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,34 @@
|
||||
From 0923de098f2e9ae6a94c5bb82e26b7d80c5181dc Mon Sep 17 00:00:00 2001
|
||||
From: Julian Sparber <julian@sparber.net>
|
||||
Date: Fri, 9 Oct 2020 15:55:57 +0200
|
||||
Subject: [PATCH 1/6] main-window: remove shadow from folder/conversation list
|
||||
|
||||
---
|
||||
ui/application-main-window.ui | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/ui/application-main-window.ui b/ui/application-main-window.ui
|
||||
index 547b063f..c55e42ab 100644
|
||||
--- a/ui/application-main-window.ui
|
||||
+++ b/ui/application-main-window.ui
|
||||
@@ -49,7 +49,7 @@
|
||||
<property name="can_focus">False</property>
|
||||
<property name="vexpand">True</property>
|
||||
<property name="label_xalign">0</property>
|
||||
- <property name="shadow_type">in</property>
|
||||
+ <property name="shadow_type">none</property>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="folder_list_scrolled">
|
||||
<property name="width_request">100</property>
|
||||
@@ -95,7 +95,7 @@
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label_xalign">0</property>
|
||||
- <property name="shadow_type">in</property>
|
||||
+ <property name="shadow_type">none</property>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="conversation_list_scrolled">
|
||||
<property name="width_request">250</property>
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,46 @@
|
||||
From a1d31847b115e8ac81520226ff121fabc1f2e2ef Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Sat, 5 Sep 2020 14:15:28 +1000
|
||||
Subject: [PATCH 002/124] Geary.Db.Result: Log large elapsed query times as a
|
||||
warning
|
||||
|
||||
Help ensure that long-running queries get some visibility during
|
||||
development.
|
||||
---
|
||||
src/engine/db/db-result.vala | 19 ++++++++++++++++---
|
||||
1 file changed, 16 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/engine/db/db-result.vala b/src/engine/db/db-result.vala
|
||||
index 64c78756..300d3afa 100644
|
||||
--- a/src/engine/db/db-result.vala
|
||||
+++ b/src/engine/db/db-result.vala
|
||||
@@ -38,10 +38,23 @@ public class Geary.Db.Result : Geary.Db.Context {
|
||||
check_cancelled("Result.next", cancellable);
|
||||
|
||||
if (!finished) {
|
||||
- Timer timer = new Timer();
|
||||
+ var timer = new GLib.Timer();
|
||||
finished = throw_on_error("Result.next", statement.stmt.step(), statement.sql) != Sqlite.ROW;
|
||||
- if (timer.elapsed() > 1.0)
|
||||
- debug("\n\nDB QUERY STEP \"%s\"\nelapsed=%lf\n\n", statement.sql, timer.elapsed());
|
||||
+ var elapsed = timer.elapsed();
|
||||
+ var threshold = (get_connection().busy_timeout * 1000.0) / 2.0;
|
||||
+ if (threshold > 0 && elapsed > threshold) {
|
||||
+ warning(
|
||||
+ "Step for \"%s\" took elapsed time: %lfs (>50%)",
|
||||
+ statement.sql,
|
||||
+ elapsed
|
||||
+ );
|
||||
+ } else if (elapsed > 1.0) {
|
||||
+ debug(
|
||||
+ "Step for \"%s\" took elapsed time: %lfs (>1s)",
|
||||
+ statement.sql,
|
||||
+ elapsed
|
||||
+ );
|
||||
+ }
|
||||
|
||||
log_result(finished ? "NO ROW" : "ROW");
|
||||
}
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,24 @@
|
||||
From c128b1be5f571315ae8a0f34cd9d00fd20c30cdc Mon Sep 17 00:00:00 2001
|
||||
From: Adrien Plazas <kekun.plazas@laposte.net>
|
||||
Date: Mon, 27 Apr 2020 10:42:16 +0200
|
||||
Subject: [PATCH 2/8] accounts-editor-add-pane: Drop the useless shadow
|
||||
|
||||
---
|
||||
ui/accounts_editor_add_pane.ui | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/ui/accounts_editor_add_pane.ui b/ui/accounts_editor_add_pane.ui
|
||||
index 0c01a4c1..336b73ea 100644
|
||||
--- a/ui/accounts_editor_add_pane.ui
|
||||
+++ b/ui/accounts_editor_add_pane.ui
|
||||
@@ -89,7 +89,6 @@
|
||||
<property name="vexpand">True</property>
|
||||
<property name="vadjustment">pane_adjustment</property>
|
||||
<property name="hscrollbar_policy">never</property>
|
||||
- <property name="shadow_type">in</property>
|
||||
<child>
|
||||
<object class="GtkViewport">
|
||||
<property name="visible">True</property>
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,235 @@
|
||||
From 51da28b7c0ec32883b923f82b3d85ba4285dc623 Mon Sep 17 00:00:00 2001
|
||||
From: Julian Sparber <julian@sparber.net>
|
||||
Date: Fri, 23 Oct 2020 13:05:19 +0200
|
||||
Subject: [PATCH 2/2] conversation-list-box: remove shadow and make the rows
|
||||
rounded
|
||||
|
||||
This also makes the expander row look like in HdyExpander row.
|
||||
---
|
||||
.../conversation-list-box.vala | 56 +++++++++++++++++
|
||||
.../conversation-web-view.vala | 26 ++++++++
|
||||
ui/geary.css | 61 ++++++++++++-------
|
||||
3 files changed, 120 insertions(+), 23 deletions(-)
|
||||
|
||||
diff --git a/src/client/conversation-viewer/conversation-list-box.vala b/src/client/conversation-viewer/conversation-list-box.vala
|
||||
index f860a2df..f94ddea9 100644
|
||||
--- a/src/client/conversation-viewer/conversation-list-box.vala
|
||||
+++ b/src/client/conversation-viewer/conversation-list-box.vala
|
||||
@@ -332,6 +332,33 @@ public class ConversationListBox : Gtk.ListBox, Geary.BaseInterface {
|
||||
get_style_context().add_class(EXPANDED_CLASS);
|
||||
else
|
||||
get_style_context().remove_class(EXPANDED_CLASS);
|
||||
+
|
||||
+ update_previous_sibling_css_class();
|
||||
+ }
|
||||
+
|
||||
+ // This is mostly taken form libhandy HdyExpanderRow
|
||||
+ private Gtk.Widget? get_previous_sibling() {
|
||||
+ if (this.parent is Gtk.Container) {
|
||||
+ var siblings = this.parent.get_children();
|
||||
+ unowned List<weak Gtk.Widget> l;
|
||||
+ for (l = siblings; l != null && l.next != null && l.next.data != this; l = l.next);
|
||||
+
|
||||
+ if (l != null && l.next != null && l.next.data == this) {
|
||||
+ return l.data;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ private void update_previous_sibling_css_class() {
|
||||
+ var previous_sibling = get_previous_sibling();
|
||||
+ if (previous_sibling != null) {
|
||||
+ if (this.is_expanded)
|
||||
+ previous_sibling.get_style_context().add_class("geary-expanded-previous-sibling");
|
||||
+ else
|
||||
+ previous_sibling.get_style_context().remove_class("geary-expanded-previous-sibling");
|
||||
+ }
|
||||
}
|
||||
|
||||
protected inline void set_style_context_class(string class_name, bool value) {
|
||||
@@ -675,9 +702,14 @@ public class ConversationListBox : Gtk.ListBox, Geary.BaseInterface {
|
||||
|
||||
this.selection_mode = NONE;
|
||||
|
||||
+ get_style_context().add_class("content");
|
||||
get_style_context().add_class("background");
|
||||
get_style_context().add_class("conversation-listbox");
|
||||
|
||||
+ /* we need to update the previous sibling style class when rows are added or removed */
|
||||
+ add.connect(update_previous_sibling_css_class);
|
||||
+ remove.connect(update_previous_sibling_css_class);
|
||||
+
|
||||
set_adjustment(adjustment);
|
||||
set_sort_func(ConversationListBox.on_sort);
|
||||
|
||||
@@ -703,6 +735,30 @@ public class ConversationListBox : Gtk.ListBox, Geary.BaseInterface {
|
||||
base.destroy();
|
||||
}
|
||||
|
||||
+ // For some reason insert doesn't emit the add event
|
||||
+ public new void insert(Gtk.Widget child, int position) {
|
||||
+ base.insert(child, position);
|
||||
+ update_previous_sibling_css_class();
|
||||
+ }
|
||||
+
|
||||
+ // This is mostly taken form libhandy HdyExpanderRow
|
||||
+ private void update_previous_sibling_css_class() {
|
||||
+ var siblings = this.get_children();
|
||||
+ unowned List<weak Gtk.Widget> l;
|
||||
+ for (l = siblings; l != null && l.next != null && l.next.data != this; l = l.next) {
|
||||
+ if (l != null && l.next != null) {
|
||||
+ var row = l.next.data as ConversationRow;
|
||||
+ if (row != null) {
|
||||
+ if (row.is_expanded) {
|
||||
+ l.data.get_style_context().add_class("geary-expanded-previous-sibling");
|
||||
+ } else {
|
||||
+ l.data.get_style_context().remove_class("geary-expanded-previous-sibling");
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
public async void load_conversation(Gee.Collection<Geary.EmailIdentifier> scroll_to,
|
||||
Geary.SearchQuery? query)
|
||||
throws GLib.Error {
|
||||
diff --git a/src/client/conversation-viewer/conversation-web-view.vala b/src/client/conversation-viewer/conversation-web-view.vala
|
||||
index a1ba21a6..ad11415e 100644
|
||||
--- a/src/client/conversation-viewer/conversation-web-view.vala
|
||||
+++ b/src/client/conversation-viewer/conversation-web-view.vala
|
||||
@@ -197,6 +197,32 @@ public class ConversationWebView : Components.WebView {
|
||||
}
|
||||
|
||||
|
||||
+ // Clip round bottom corner
|
||||
+ // This is based on
|
||||
+ // https://gitlab.gnome.org/GNOME/gnome-weather/-/commit/9b6336454cc90669d1ee8387bdfc6627e3659e83
|
||||
+ public override bool draw(Cairo.Context cr) {
|
||||
+ var frameWidth = this.get_allocated_width();
|
||||
+ var frameHeight = this.get_allocated_height();
|
||||
+ var borderRadius = 8;
|
||||
+
|
||||
+ var arc0 = 0.0;
|
||||
+ var arc1 = Math.PI * 0.5;
|
||||
+ var arc2 = Math.PI;
|
||||
+
|
||||
+ cr.new_sub_path();
|
||||
+ cr.line_to(frameWidth, 0);
|
||||
+ cr.arc(frameWidth - borderRadius, frameHeight - borderRadius, borderRadius, arc0, arc1);
|
||||
+ cr.arc(borderRadius, frameHeight - borderRadius, borderRadius, arc1, arc2);
|
||||
+ cr.line_to(0, 0);
|
||||
+ cr.close_path();
|
||||
+
|
||||
+ cr.clip();
|
||||
+ cr.fill();
|
||||
+ base.draw(cr);
|
||||
+
|
||||
+ return Gdk.EVENT_PROPAGATE;
|
||||
+ }
|
||||
+
|
||||
public override void get_preferred_height(out int minimum_height,
|
||||
out int natural_height) {
|
||||
// XXX clamp height to something not too outrageous so we
|
||||
diff --git a/ui/geary.css b/ui/geary.css
|
||||
index 2d1d48c3..78ade7c0 100644
|
||||
--- a/ui/geary.css
|
||||
+++ b/ui/geary.css
|
||||
@@ -77,39 +77,44 @@ row.geary-folder-popover-list-row > label {
|
||||
/* ConversationListBox */
|
||||
|
||||
.conversation-listbox {
|
||||
- padding: 0 12px;
|
||||
+ padding: 12px;
|
||||
}
|
||||
+
|
||||
.conversation-listbox > row {
|
||||
- margin: 0;
|
||||
- border: 1px solid @borders;
|
||||
- border-bottom-width: 0;
|
||||
padding: 0;
|
||||
- box-shadow: 0 4px 8px 1px rgba(0,0,0,0.4);
|
||||
-}
|
||||
-.conversation-listbox > row > box {
|
||||
- background: @theme_base_color;
|
||||
- transition: background 0.25s;
|
||||
-}
|
||||
-.conversation-listbox > row:hover > box {
|
||||
- background: shade(@theme_base_color, 0.96);
|
||||
-}
|
||||
-.conversation-listbox > row.geary-expanded {
|
||||
- margin-bottom: 6px;
|
||||
- border-bottom-width: 1px;
|
||||
}
|
||||
+
|
||||
.conversation-listbox *.geary-matched *.geary-match {
|
||||
color: @theme_selected_fg_color;
|
||||
background: @theme_selected_bg_color;
|
||||
-;}
|
||||
+}
|
||||
+
|
||||
.conversation-listbox > row.geary-loading {
|
||||
border-top-width: 0px;
|
||||
padding: 6px;
|
||||
}
|
||||
-.conversation-listbox > row:first-child:not(.geary-loading) {
|
||||
- margin-top: 12px;
|
||||
+
|
||||
+.conversation-listbox.content > row:last-child,
|
||||
+.conversation-listbox.content > row.geary-expanded-previous-sibling,
|
||||
+.conversation-listbox.content > row.geary-expanded {
|
||||
+ border-width: 1px;
|
||||
}
|
||||
-.conversation-listbox > row:last-child {
|
||||
- margin-bottom: 12px;
|
||||
+
|
||||
+.geary-expanded, .geary-expanded + row {
|
||||
+ border-top-left-radius: 8px;
|
||||
+ -gtk-outline-top-left-radius: 7px;
|
||||
+ border-top-right-radius: 8px;
|
||||
+ -gtk-outline-top-right-radius: 7px;
|
||||
+ margin-top: 6px;
|
||||
+}
|
||||
+
|
||||
+.geary-expanded,
|
||||
+.geary-expanded-previous-sibling {
|
||||
+ border-bottom-left-radius: 8px;
|
||||
+ -gtk-outline-bottom-left-radius: 7px;
|
||||
+ border-bottom-right-radius: 8px;
|
||||
+ -gtk-outline-bottom-right-radius: 7px;
|
||||
+ margin-bottom: 6px
|
||||
}
|
||||
|
||||
/* ConversationEmail */
|
||||
@@ -119,6 +124,14 @@ row.geary-folder-popover-list-row > label {
|
||||
transition: border 0.25s;
|
||||
}
|
||||
|
||||
+.geary-expanded > .geary_email grid.geary-message-summary,
|
||||
+.geary-expanded + row > .geary_email grid.geary-message-summary {
|
||||
+ border-top-left-radius: 8px;
|
||||
+ -gtk-outline-top-left-radius: 7px;
|
||||
+ border-top-right-radius: 8px;
|
||||
+ -gtk-outline-top-right-radius: 7px;
|
||||
+}
|
||||
+
|
||||
/* ConversationMessage */
|
||||
|
||||
.geary-message infobar box {
|
||||
@@ -198,8 +211,10 @@ grid.geary-message-summary {
|
||||
/* Composer */
|
||||
|
||||
.geary-composer-embed headerbar {
|
||||
- border-top: 1px solid @borders;
|
||||
- border-radius: 0px;
|
||||
+ border-top-left-radius: 8px;
|
||||
+ -gtk-outline-top-left-radius: 7px;
|
||||
+ border-top-right-radius: 8px;
|
||||
+ -gtk-outline-top-right-radius: 7px;
|
||||
}
|
||||
|
||||
.geary-attachments-box > box > box {
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,258 @@
|
||||
From 40824723c63d869535f89e628289fdb46cbf9c49 Mon Sep 17 00:00:00 2001
|
||||
From: Julian Sparber <julian@sparber.net>
|
||||
Date: Fri, 9 Oct 2020 17:20:31 +0200
|
||||
Subject: [PATCH 2/6] conversation-viewer: move actions to the bottom when they
|
||||
don't fit
|
||||
|
||||
---
|
||||
.../application/application-main-window.vala | 8 ++-
|
||||
.../components-conversation-action-bar.vala | 12 ++--
|
||||
src/client/components/main-toolbar.vala | 63 +++++++++++++++----
|
||||
.../conversation-viewer.vala | 1 -
|
||||
ui/application-main-window.ui | 18 ++++++
|
||||
ui/components-conversation-action-bar.ui | 21 ++++++-
|
||||
6 files changed, 100 insertions(+), 23 deletions(-)
|
||||
|
||||
diff --git a/src/client/application/application-main-window.vala b/src/client/application/application-main-window.vala
|
||||
index 90d5b249..19f04492 100644
|
||||
--- a/src/client/application/application-main-window.vala
|
||||
+++ b/src/client/application/application-main-window.vala
|
||||
@@ -334,6 +334,10 @@ public class Application.MainWindow :
|
||||
[GtkChild]
|
||||
private Gtk.ScrolledWindow conversation_list_scrolled;
|
||||
[GtkChild]
|
||||
+ private Gtk.Box conversation_viewer_box;
|
||||
+ [GtkChild]
|
||||
+ private Components.ConversationActionBar conversation_viewer_action_bar;
|
||||
+ [GtkChild]
|
||||
private Gtk.SizeGroup folder_size_group;
|
||||
[GtkChild]
|
||||
private Gtk.SizeGroup folder_separator_size_group;
|
||||
@@ -1266,7 +1270,7 @@ public class Application.MainWindow :
|
||||
|
||||
this.conversation_viewer.hexpand = true;
|
||||
this.conversation_size_group.add_widget(this.conversation_viewer);
|
||||
- this.main_leaflet.add_with_properties(this.conversation_viewer, "name", "conversation", null);
|
||||
+ this.conversation_viewer_box.add(this.conversation_viewer);
|
||||
|
||||
|
||||
// Setup conversation actions
|
||||
@@ -1279,7 +1283,7 @@ public class Application.MainWindow :
|
||||
BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL);
|
||||
|
||||
// Main toolbar
|
||||
- this.main_toolbar = new MainToolbar(config);
|
||||
+ this.main_toolbar = new MainToolbar(config, conversation_viewer_action_bar);
|
||||
this.main_toolbar.add_to_size_groups(this.folder_size_group,
|
||||
this.folder_separator_size_group,
|
||||
this.conversations_size_group,
|
||||
diff --git a/src/client/components/components-conversation-action-bar.vala b/src/client/components/components-conversation-action-bar.vala
|
||||
index cb574521..cd868b21 100644
|
||||
--- a/src/client/components/components-conversation-action-bar.vala
|
||||
+++ b/src/client/components/components-conversation-action-bar.vala
|
||||
@@ -12,7 +12,7 @@ public class Components.ConversationActionBar : Gtk.Revealer {
|
||||
private ulong owner_notify;
|
||||
|
||||
[GtkChild]
|
||||
- private Gtk.Box action_box;
|
||||
+ public Gtk.Box action_box;
|
||||
|
||||
public ConversationActionBar() {
|
||||
}
|
||||
@@ -23,17 +23,17 @@ public class Components.ConversationActionBar : Gtk.Revealer {
|
||||
*/
|
||||
public void add_conversation_actions(Components.ConversationActions actions) {
|
||||
if (actions.owner == this)
|
||||
- return;
|
||||
+ return;
|
||||
|
||||
actions.take_ownership(this);
|
||||
action_box.pack_start(actions.mark_copy_move_buttons, false, false);
|
||||
action_box.pack_end(actions.archive_trash_delete_buttons, false, false);
|
||||
reveal_child = true;
|
||||
this.owner_notify = actions.notify["owner"].connect(() => {
|
||||
- if (actions.owner != this) {
|
||||
- reveal_child = false;
|
||||
- actions.disconnect (this.owner_notify);
|
||||
- }
|
||||
+ if (actions.owner != this) {
|
||||
+ reveal_child = false;
|
||||
+ actions.disconnect (this.owner_notify);
|
||||
+ }
|
||||
});
|
||||
}
|
||||
}
|
||||
diff --git a/src/client/components/main-toolbar.vala b/src/client/components/main-toolbar.vala
|
||||
index 6458b7fb..f216238a 100644
|
||||
--- a/src/client/components/main-toolbar.vala
|
||||
+++ b/src/client/components/main-toolbar.vala
|
||||
@@ -17,6 +17,11 @@ public class MainToolbar : Hdy.Leaflet {
|
||||
// Search bar
|
||||
public bool search_open { get; set; default = false; }
|
||||
|
||||
+ private ulong owner_notify;
|
||||
+ private Gtk.Widget? reply_forward_buttons;
|
||||
+ private Gtk.Widget? archive_trash_delete_buttons;
|
||||
+ private Components.ConversationActionBar conversation_viewer_action_bar;
|
||||
+
|
||||
[GtkChild]
|
||||
private Hdy.Leaflet conversations_leaflet;
|
||||
|
||||
@@ -47,11 +52,14 @@ public class MainToolbar : Hdy.Leaflet {
|
||||
|
||||
Gtk.SizeGroup conversation_group;
|
||||
|
||||
- public MainToolbar(Application.Configuration config) {
|
||||
+ public MainToolbar(Application.Configuration config,
|
||||
+ Components.ConversationActionBar action_bar) {
|
||||
if (config.desktop_environment != UNITY) {
|
||||
this.bind_property("account", this.conversations_header, "title", BindingFlags.SYNC_CREATE);
|
||||
this.bind_property("folder", this.conversations_header, "subtitle", BindingFlags.SYNC_CREATE);
|
||||
}
|
||||
+ this.conversation_viewer_action_bar = action_bar;
|
||||
+ conversation_header.size_allocate.connect(on_size_allocate);
|
||||
|
||||
// Assemble the main/mark menus
|
||||
Gtk.Builder builder = new Gtk.Builder.from_resource("/org/gnome/Geary/main-toolbar-menus.ui");
|
||||
@@ -63,17 +71,6 @@ public class MainToolbar : Hdy.Leaflet {
|
||||
BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL);
|
||||
}
|
||||
|
||||
- public void add_conversation_actions(Components.ConversationActions actions) {
|
||||
- if (actions.owner == this)
|
||||
- return;
|
||||
-
|
||||
- actions.take_ownership(this);
|
||||
- conversation_header.pack_start(actions.mark_copy_move_buttons);
|
||||
- conversation_header.pack_start(actions.reply_forward_buttons);
|
||||
- conversation_header.pack_end(actions.find_button);
|
||||
- conversation_header.pack_end(actions.archive_trash_delete_buttons);
|
||||
- }
|
||||
-
|
||||
public void set_conversation_header(Gtk.HeaderBar header) {
|
||||
remove(conversation_header);
|
||||
this.header_group.add_gtk_header_bar(header);
|
||||
@@ -111,4 +108,46 @@ public class MainToolbar : Hdy.Leaflet {
|
||||
conversations_group.add_swipeable(this.conversations_leaflet);
|
||||
conversation_group.add_swipeable(this);
|
||||
}
|
||||
+
|
||||
+ private void on_size_allocate() {
|
||||
+ if (reply_forward_buttons != null && archive_trash_delete_buttons != null)
|
||||
+ if (conversation_viewer_action_bar.reveal_child && get_allocated_width() > 600) {
|
||||
+ conversation_viewer_action_bar.reveal_child = false;
|
||||
+ remove_action_parent();
|
||||
+ conversation_header.pack_start(reply_forward_buttons);
|
||||
+ conversation_header.pack_end(archive_trash_delete_buttons);
|
||||
+ } else if (!conversation_viewer_action_bar.reveal_child && get_allocated_width() < 600) {
|
||||
+ remove_action_parent();
|
||||
+ conversation_viewer_action_bar.action_box.pack_start(reply_forward_buttons, false, false);
|
||||
+ conversation_viewer_action_bar.action_box.pack_end(archive_trash_delete_buttons, false, false);
|
||||
+ conversation_viewer_action_bar.reveal_child = true;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private void remove_action_parent() {
|
||||
+ if (reply_forward_buttons != null && reply_forward_buttons.parent != null)
|
||||
+ reply_forward_buttons.parent.remove(reply_forward_buttons);
|
||||
+ if (archive_trash_delete_buttons != null && archive_trash_delete_buttons.parent != null)
|
||||
+ archive_trash_delete_buttons.parent.remove(archive_trash_delete_buttons);
|
||||
+ }
|
||||
+
|
||||
+ public void add_conversation_actions(Components.ConversationActions actions) {
|
||||
+ if (actions.owner != this) {
|
||||
+ actions.take_ownership(this);
|
||||
+ conversation_header.pack_start(actions.mark_copy_move_buttons);
|
||||
+ conversation_header.pack_end(actions.find_button);
|
||||
+
|
||||
+ reply_forward_buttons = actions.reply_forward_buttons;
|
||||
+ archive_trash_delete_buttons = actions.archive_trash_delete_buttons;
|
||||
+ on_size_allocate();
|
||||
+ this.owner_notify = actions.notify["owner"].connect(() => {
|
||||
+ if (actions.owner != this) {
|
||||
+ conversation_viewer_action_bar.reveal_child = false;
|
||||
+ reply_forward_buttons = null;
|
||||
+ archive_trash_delete_buttons = null;
|
||||
+ actions.disconnect (this.owner_notify);
|
||||
+ }
|
||||
+ });
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
diff --git a/src/client/conversation-viewer/conversation-viewer.vala b/src/client/conversation-viewer/conversation-viewer.vala
|
||||
index a5098764..74706f8c 100644
|
||||
--- a/src/client/conversation-viewer/conversation-viewer.vala
|
||||
+++ b/src/client/conversation-viewer/conversation-viewer.vala
|
||||
@@ -532,5 +532,4 @@ public class ConversationViewer : Gtk.Stack, Geary.BaseInterface {
|
||||
}
|
||||
}
|
||||
}
|
||||
-
|
||||
}
|
||||
diff --git a/ui/application-main-window.ui b/ui/application-main-window.ui
|
||||
index c55e42ab..1b41310d 100644
|
||||
--- a/ui/application-main-window.ui
|
||||
+++ b/ui/application-main-window.ui
|
||||
@@ -137,6 +137,24 @@
|
||||
<property name="navigatable">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
+ <child>
|
||||
+ <object class="GtkBox" id="conversation_viewer_box">
|
||||
+ <property name="visible">True</property>
|
||||
+ <property name="can_focus">False</property>
|
||||
+ <property name="orientation">vertical</property>
|
||||
+ <child>
|
||||
+ <object class="ComponentsConversationActionBar" id="conversation_viewer_action_bar">
|
||||
+ <property name="visible">True</property>
|
||||
+ </object>
|
||||
+ <packing>
|
||||
+ <property name="pack_type">end</property>
|
||||
+ </packing>
|
||||
+ </child>
|
||||
+ </object>
|
||||
+ <packing>
|
||||
+ <property name="name">conversation</property>
|
||||
+ </packing>
|
||||
+ </child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
diff --git a/ui/components-conversation-action-bar.ui b/ui/components-conversation-action-bar.ui
|
||||
index ae49683f..6fc03f44 100644
|
||||
--- a/ui/components-conversation-action-bar.ui
|
||||
+++ b/ui/components-conversation-action-bar.ui
|
||||
@@ -11,11 +11,28 @@
|
||||
<property name="can_focus">False</property>
|
||||
<property name="transition_type">slide-up</property>
|
||||
<child>
|
||||
- <object class="GtkBox" id="action_box">
|
||||
+ <object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
- <property name="margin">6</property>
|
||||
+ <property name="orientation">vertical</property>
|
||||
+ <child>
|
||||
+ <object class="GtkSeparator">
|
||||
+ <property name="visible">True</property>
|
||||
+ <property name="can_focus">False</property>
|
||||
+ </object>
|
||||
+ </child>
|
||||
+ <child>
|
||||
+ <object class="GtkBox" id="action_box">
|
||||
+ <property name="visible">True</property>
|
||||
+ <property name="can_focus">False</property>
|
||||
+ <property name="hexpand">True</property>
|
||||
+ <property name="margin_top">6</property>
|
||||
+ <property name="margin_bottom">6</property>
|
||||
+ <property name="margin_start">6</property>
|
||||
+ <property name="margin_end">6</property>
|
||||
+ </object>
|
||||
+ </child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,102 @@
|
||||
From 485868d570ef95283c541a1a180fca88fec7a9ef Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Tue, 8 Sep 2020 08:34:23 +1000
|
||||
Subject: [PATCH 003/124] Geary.Db.DatabaseConnection: Check elapsed time for
|
||||
exec statements
|
||||
|
||||
Re-work elapsed timer to be usable in other context objects, use it
|
||||
for timing exec query execution.
|
||||
---
|
||||
src/engine/db/db-context.vala | 13 +++++++++++++
|
||||
src/engine/db/db-database-connection.vala | 9 ++++++---
|
||||
src/engine/db/db-result.vala | 23 +++++------------------
|
||||
3 files changed, 24 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/src/engine/db/db-context.vala b/src/engine/db/db-context.vala
|
||||
index a59f6c4c..6713f6c8 100644
|
||||
--- a/src/engine/db/db-context.vala
|
||||
+++ b/src/engine/db/db-context.vala
|
||||
@@ -61,6 +61,19 @@ public abstract class Geary.Db.Context : BaseObject, Logging.Source {
|
||||
/** {@inheritDoc} */
|
||||
public abstract Logging.State to_logging_state();
|
||||
|
||||
+
|
||||
+ protected inline void check_elapsed(string message,
|
||||
+ GLib.Timer timer)
|
||||
+ throws DatabaseError {
|
||||
+ var elapsed = timer.elapsed();
|
||||
+ var threshold = (get_connection().busy_timeout * 1000.0) / 2.0;
|
||||
+ if (threshold > 0 && elapsed > threshold) {
|
||||
+ warning("%s: elapsed time: %lfs (>50%)", message, elapsed);
|
||||
+ } else if (elapsed > 1.0) {
|
||||
+ debug("%s: elapsed time: %lfs (>1s)", message, elapsed);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
protected inline int throw_on_error(string? method, int result, string? raw = null) throws DatabaseError {
|
||||
return Db.throw_on_error(this, method, result, raw);
|
||||
}
|
||||
diff --git a/src/engine/db/db-database-connection.vala b/src/engine/db/db-database-connection.vala
|
||||
index dd311bea..d58911e4 100644
|
||||
--- a/src/engine/db/db-database-connection.vala
|
||||
+++ b/src/engine/db/db-database-connection.vala
|
||||
@@ -137,7 +137,9 @@ public class Geary.Db.DatabaseConnection : Context, Connection {
|
||||
}
|
||||
|
||||
check_cancelled("Connection.exec", cancellable);
|
||||
- throw_on_error("Connection.exec", db.exec(sql), sql);
|
||||
+ var timer = new GLib.Timer();
|
||||
+ throw_on_error("Connection.exec_file", this.db.exec(sql), sql);
|
||||
+ check_elapsed("Query \"%s\"".printf(sql), timer);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@@ -147,8 +149,9 @@ public class Geary.Db.DatabaseConnection : Context, Connection {
|
||||
|
||||
string sql;
|
||||
FileUtils.get_contents(file.get_path(), out sql);
|
||||
-
|
||||
- exec(sql, cancellable);
|
||||
+ var timer = new GLib.Timer();
|
||||
+ throw_on_error("Connection.exec_file", this.db.exec(sql), sql);
|
||||
+ check_elapsed(file.get_path(), timer);
|
||||
}
|
||||
|
||||
/**
|
||||
diff --git a/src/engine/db/db-result.vala b/src/engine/db/db-result.vala
|
||||
index 300d3afa..b5382179 100644
|
||||
--- a/src/engine/db/db-result.vala
|
||||
+++ b/src/engine/db/db-result.vala
|
||||
@@ -39,24 +39,11 @@ public class Geary.Db.Result : Geary.Db.Context {
|
||||
|
||||
if (!finished) {
|
||||
var timer = new GLib.Timer();
|
||||
- finished = throw_on_error("Result.next", statement.stmt.step(), statement.sql) != Sqlite.ROW;
|
||||
- var elapsed = timer.elapsed();
|
||||
- var threshold = (get_connection().busy_timeout * 1000.0) / 2.0;
|
||||
- if (threshold > 0 && elapsed > threshold) {
|
||||
- warning(
|
||||
- "Step for \"%s\" took elapsed time: %lfs (>50%)",
|
||||
- statement.sql,
|
||||
- elapsed
|
||||
- );
|
||||
- } else if (elapsed > 1.0) {
|
||||
- debug(
|
||||
- "Step for \"%s\" took elapsed time: %lfs (>1s)",
|
||||
- statement.sql,
|
||||
- elapsed
|
||||
- );
|
||||
- }
|
||||
-
|
||||
- log_result(finished ? "NO ROW" : "ROW");
|
||||
+ this.finished = throw_on_error(
|
||||
+ "Result.next", statement.stmt.step(), statement.sql
|
||||
+ ) != Sqlite.ROW;
|
||||
+ check_elapsed("Result.next", timer);
|
||||
+ log_result(this.finished ? "NO ROW" : "ROW");
|
||||
}
|
||||
|
||||
return !finished;
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,26 @@
|
||||
From bab1759af038ecf08658b3664bf74428f47559e9 Mon Sep 17 00:00:00 2001
|
||||
From: Adrien Plazas <kekun.plazas@laposte.net>
|
||||
Date: Mon, 27 Apr 2020 10:43:07 +0200
|
||||
Subject: [PATCH 3/8] accounts-editor-add-pane: Reduce the minimum entry width
|
||||
|
||||
This will help the pane fit in narrower widths.
|
||||
---
|
||||
src/client/accounts/accounts-editor-add-pane.vala | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/client/accounts/accounts-editor-add-pane.vala b/src/client/accounts/accounts-editor-add-pane.vala
|
||||
index a4a333cd..468e348f 100644
|
||||
--- a/src/client/accounts/accounts-editor-add-pane.vala
|
||||
+++ b/src/client/accounts/accounts-editor-add-pane.vala
|
||||
@@ -526,7 +526,7 @@ private abstract class Accounts.EntryRow : AddPaneRow<Gtk.Entry> {
|
||||
|
||||
this.value.text = initial_value ?? "";
|
||||
this.value.placeholder_text = placeholder ?? "";
|
||||
- this.value.width_chars = 32;
|
||||
+ this.value.width_chars = 16;
|
||||
|
||||
this.undo = new Components.EntryUndo(this.value);
|
||||
}
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,64 @@
|
||||
From ee3e56aa1f3a71457b43a79b233ba3200e4e78d2 Mon Sep 17 00:00:00 2001
|
||||
From: Julian Sparber <julian@sparber.net>
|
||||
Date: Mon, 12 Oct 2020 16:35:22 +0200
|
||||
Subject: [PATCH 3/6] conversation-viewer: allow one email per line
|
||||
|
||||
---
|
||||
ui/conversation-message.ui | 6 ------
|
||||
1 file changed, 6 deletions(-)
|
||||
|
||||
diff --git a/ui/conversation-message.ui b/ui/conversation-message.ui
|
||||
index 95560939..d68817b2 100644
|
||||
--- a/ui/conversation-message.ui
|
||||
+++ b/ui/conversation-message.ui
|
||||
@@ -157,7 +157,6 @@
|
||||
<property name="valign">baseline</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="column_spacing">2</property>
|
||||
- <property name="min_children_per_line">1</property>
|
||||
<property name="max_children_per_line">4</property>
|
||||
<property name="selection_mode">none</property>
|
||||
<signal name="child-activated" handler="on_address_box_child_activated" swapped="no"/>
|
||||
@@ -218,7 +217,6 @@
|
||||
<property name="valign">start</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="column_spacing">2</property>
|
||||
- <property name="min_children_per_line">2</property>
|
||||
<property name="max_children_per_line">4</property>
|
||||
<property name="selection_mode">none</property>
|
||||
<signal name="child-activated" handler="on_address_box_child_activated" swapped="no"/>
|
||||
@@ -263,7 +261,6 @@
|
||||
<property name="valign">start</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="column_spacing">2</property>
|
||||
- <property name="min_children_per_line">2</property>
|
||||
<property name="max_children_per_line">4</property>
|
||||
<property name="selection_mode">none</property>
|
||||
<signal name="child-activated" handler="on_address_box_child_activated" swapped="no"/>
|
||||
@@ -328,7 +325,6 @@
|
||||
<property name="valign">start</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="column_spacing">2</property>
|
||||
- <property name="min_children_per_line">2</property>
|
||||
<property name="max_children_per_line">4</property>
|
||||
<property name="selection_mode">none</property>
|
||||
<signal name="child-activated" handler="on_address_box_child_activated" swapped="no"/>
|
||||
@@ -373,7 +369,6 @@
|
||||
<property name="valign">start</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="column_spacing">2</property>
|
||||
- <property name="min_children_per_line">2</property>
|
||||
<property name="max_children_per_line">4</property>
|
||||
<property name="selection_mode">none</property>
|
||||
<signal name="child-activated" handler="on_address_box_child_activated" swapped="no"/>
|
||||
@@ -418,7 +413,6 @@
|
||||
<property name="valign">start</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="column_spacing">2</property>
|
||||
- <property name="min_children_per_line">2</property>
|
||||
<property name="max_children_per_line">4</property>
|
||||
<property name="selection_mode">none</property>
|
||||
<signal name="child-activated" handler="on_address_box_child_activated" swapped="no"/>
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,66 @@
|
||||
From 0fa0d0ea4d8db54166c131dee7b509d3984c2e2f Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Wed, 9 Sep 2020 18:30:22 +1000
|
||||
Subject: [PATCH 004/124] Geary.Db.Statement: Minor code cleanup
|
||||
|
||||
Make `sql` a proper auto property. Remove expanded sql workaround.
|
||||
Minor code style cleanup.
|
||||
---
|
||||
src/engine/db/db-statement.vala | 17 ++++++-----------
|
||||
1 file changed, 6 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/src/engine/db/db-statement.vala b/src/engine/db/db-statement.vala
|
||||
index 088b882b..4d792b42 100644
|
||||
--- a/src/engine/db/db-statement.vala
|
||||
+++ b/src/engine/db/db-statement.vala
|
||||
@@ -9,15 +9,16 @@ private extern string? sqlite3_expanded_sql(Sqlite.Statement stmt);
|
||||
|
||||
public class Geary.Db.Statement : Context {
|
||||
|
||||
- public string sql {
|
||||
- get { return this.stmt.sql(); }
|
||||
- }
|
||||
+
|
||||
+ public string sql { get; private set; }
|
||||
|
||||
internal DatabaseConnection connection { get; private set; }
|
||||
|
||||
internal Sqlite.Statement stmt;
|
||||
|
||||
private Gee.HashMap<string, int>? column_map = null;
|
||||
+ private Gee.HashSet<Memory.Buffer> held_buffers = new Gee.HashSet<Memory.Buffer>();
|
||||
+
|
||||
|
||||
/**
|
||||
* Fired when the Statement is executed the first time (after creation or after a reset).
|
||||
@@ -34,11 +35,11 @@ public class Geary.Db.Statement : Context {
|
||||
*/
|
||||
public signal void bindings_cleared();
|
||||
|
||||
- private Gee.HashSet<Memory.Buffer> held_buffers = new Gee.HashSet<Memory.Buffer>();
|
||||
|
||||
internal Statement(DatabaseConnection connection, string sql)
|
||||
throws DatabaseError {
|
||||
this.connection = connection;
|
||||
+ this.sql = sql;
|
||||
throw_on_error(
|
||||
"Statement.ctor",
|
||||
connection.db.prepare_v2(sql, -1, out stmt, null),
|
||||
@@ -48,13 +49,7 @@ public class Geary.Db.Statement : Context {
|
||||
|
||||
/** Returns SQL for the statement with bound parameters expanded. */
|
||||
public string? get_expanded_sql() {
|
||||
- // Replace all this with `Sqlite.Statement.expanded_sql` is
|
||||
- // readily available. See:
|
||||
- // https://gitlab.gnome.org/GNOME/vala/merge_requests/74
|
||||
- string* sqlite = sqlite3_expanded_sql(this.stmt);
|
||||
- string? sql = sqlite;
|
||||
- Sqlite.Memory.free((void*) sqlite);
|
||||
- return sql;
|
||||
+ return this.stmt.expanded_sql();
|
||||
}
|
||||
|
||||
/**
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,28 @@
|
||||
From 84c94463cd806ac5dbb1692ef3c04107b5a5f12f Mon Sep 17 00:00:00 2001
|
||||
From: Adrien Plazas <kekun.plazas@laposte.net>
|
||||
Date: Mon, 27 Apr 2020 10:43:45 +0200
|
||||
Subject: [PATCH 4/8] accounts-editor-eit-pane: Ellipsize the account row label
|
||||
|
||||
This will help the pane fit in narrower widths.
|
||||
---
|
||||
src/client/accounts/accounts-editor-edit-pane.vala | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/client/accounts/accounts-editor-edit-pane.vala b/src/client/accounts/accounts-editor-edit-pane.vala
|
||||
index 2722db6e..5b944333 100644
|
||||
--- a/src/client/accounts/accounts-editor-edit-pane.vala
|
||||
+++ b/src/client/accounts/accounts-editor-edit-pane.vala
|
||||
@@ -376,7 +376,9 @@ private class Accounts.MailboxRow : AccountRow<EditorEditPane,Gtk.Label> {
|
||||
|
||||
public MailboxRow(Geary.AccountInformation account,
|
||||
Geary.RFC822.MailboxAddress mailbox) {
|
||||
- base(account, "", new Gtk.Label(""));
|
||||
+ var label = new Gtk.Label("");
|
||||
+ label.ellipsize = Pango.EllipsizeMode.END;
|
||||
+ base(account, "", label);
|
||||
this.mailbox = mailbox;
|
||||
enable_drag();
|
||||
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,558 @@
|
||||
From 7d164ce964aa4118d019a741f9abf821f1897985 Mon Sep 17 00:00:00 2001
|
||||
From: Julian Sparber <julian@sparber.net>
|
||||
Date: Tue, 13 Oct 2020 15:46:39 +0200
|
||||
Subject: [PATCH 4/6] compnents-info-bar: use custom infobar so that the
|
||||
buttons reflow
|
||||
|
||||
---
|
||||
po/POTFILES.in | 1 +
|
||||
.../application/application-main-window.vala | 2 +-
|
||||
.../components/components-info-bar-stack.vala | 34 ++--
|
||||
.../components/components-info-bar.vala | 153 ++++++++++++++++--
|
||||
.../conversation-list-box.vala | 4 +-
|
||||
.../conversation-message.vala | 4 +-
|
||||
ui/components-info-bar.ui | 83 ++++++++++
|
||||
ui/geary.css | 4 +
|
||||
ui/org.gnome.Geary.gresource.xml | 1 +
|
||||
9 files changed, 248 insertions(+), 38 deletions(-)
|
||||
create mode 100644 ui/components-info-bar.ui
|
||||
|
||||
diff --git a/po/POTFILES.in b/po/POTFILES.in
|
||||
index cd8b339d..6ab344dc 100644
|
||||
--- a/po/POTFILES.in
|
||||
+++ b/po/POTFILES.in
|
||||
@@ -460,6 +460,7 @@ ui/components-attachment-view.ui
|
||||
ui/components-conversation-actions.ui
|
||||
ui/components-conversation-action-bar.ui
|
||||
ui/components-in-app-notification.ui
|
||||
+ui/components-info-bar.ui
|
||||
ui/components-inspector-error-view.ui
|
||||
ui/components-inspector-log-view.ui
|
||||
ui/components-inspector.ui
|
||||
diff --git a/src/client/application/application-main-window.vala b/src/client/application/application-main-window.vala
|
||||
index 19f04492..27526e0e 100644
|
||||
--- a/src/client/application/application-main-window.vala
|
||||
+++ b/src/client/application/application-main-window.vala
|
||||
@@ -889,7 +889,7 @@ public class Application.MainWindow :
|
||||
}
|
||||
|
||||
/** Displays an infobar in the window. */
|
||||
- public void show_info_bar(Gtk.InfoBar info_bar) {
|
||||
+ public void show_info_bar(Components.InfoBar info_bar) {
|
||||
if (!this.info_bars.has_current) {
|
||||
this.info_bars.add(info_bar);
|
||||
}
|
||||
diff --git a/src/client/components/components-info-bar-stack.vala b/src/client/components/components-info-bar-stack.vala
|
||||
index cbe63e05..83339210 100644
|
||||
--- a/src/client/components/components-info-bar-stack.vala
|
||||
+++ b/src/client/components/components-info-bar-stack.vala
|
||||
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
- * A stack-like widget for displaying Gtk InfoBar widgets.
|
||||
+ * A stack-like widget for displaying Components.InfoBar widgets.
|
||||
*
|
||||
* The stack ensures only one info bar is shown at once, shows a frame
|
||||
* around the info bar, and manages revealing and hiding itself and
|
||||
@@ -40,7 +40,7 @@ public class Components.InfoBarStack : Gtk.Frame, Geary.BaseInterface {
|
||||
}
|
||||
|
||||
|
||||
- private class SingletonQueue : Gee.AbstractQueue<Gtk.InfoBar> {
|
||||
+ private class SingletonQueue : Gee.AbstractQueue<Components.InfoBar> {
|
||||
|
||||
public override bool read_only {
|
||||
get { return false; }
|
||||
@@ -62,10 +62,10 @@ public class Components.InfoBarStack : Gtk.Frame, Geary.BaseInterface {
|
||||
get { return (this.element != null) ? 0 : 1; }
|
||||
}
|
||||
|
||||
- private Gtk.InfoBar? element = null;
|
||||
+ private Components.InfoBar? element = null;
|
||||
|
||||
|
||||
- public override bool add(Gtk.InfoBar to_add) {
|
||||
+ public override bool add(Components.InfoBar to_add) {
|
||||
var added = false;
|
||||
if (this.element != to_add) {
|
||||
this.element = to_add;
|
||||
@@ -78,20 +78,20 @@ public class Components.InfoBarStack : Gtk.Frame, Geary.BaseInterface {
|
||||
this.element = null;
|
||||
}
|
||||
|
||||
- public override bool contains(Gtk.InfoBar other) {
|
||||
+ public override bool contains(Components.InfoBar other) {
|
||||
return (this.element == other);
|
||||
}
|
||||
|
||||
- public override Gee.Iterator<Gtk.InfoBar> iterator() {
|
||||
+ public override Gee.Iterator<Components.InfoBar> iterator() {
|
||||
// This sucks but it won't ever be used so oh well
|
||||
return (
|
||||
this.element == null
|
||||
- ? Gee.Collection.empty<Gtk.InfoBar>().iterator()
|
||||
+ ? Gee.Collection.empty<Components.InfoBar>().iterator()
|
||||
: Geary.Collection.single(this.element).iterator()
|
||||
);
|
||||
}
|
||||
|
||||
- public override bool remove(Gtk.InfoBar to_remove) {
|
||||
+ public override bool remove(Components.InfoBar to_remove) {
|
||||
var removed = false;
|
||||
if (this.element == to_remove) {
|
||||
this.element = null;
|
||||
@@ -100,11 +100,11 @@ public class Components.InfoBarStack : Gtk.Frame, Geary.BaseInterface {
|
||||
return removed;
|
||||
}
|
||||
|
||||
- public override Gtk.InfoBar peek() {
|
||||
+ public override Components.InfoBar peek() {
|
||||
return this.element;
|
||||
}
|
||||
|
||||
- public override Gtk.InfoBar poll() {
|
||||
+ public override Components.InfoBar poll() {
|
||||
var element = this.element;
|
||||
this.element = null;
|
||||
return element;
|
||||
@@ -126,7 +126,7 @@ public class Components.InfoBarStack : Gtk.Frame, Geary.BaseInterface {
|
||||
* @see algorithm
|
||||
* @see StackType.PRIORITY_QUEUE
|
||||
*/
|
||||
- public static int priority_queue_comparator(Gtk.InfoBar a, Gtk.InfoBar b) {
|
||||
+ public static int priority_queue_comparator(Components.InfoBar a, Components.InfoBar b) {
|
||||
return (
|
||||
b.get_data<int>(PRIORITY_QUEUE_KEY) -
|
||||
a.get_data<int>(PRIORITY_QUEUE_KEY)
|
||||
@@ -150,11 +150,11 @@ public class Components.InfoBarStack : Gtk.Frame, Geary.BaseInterface {
|
||||
}
|
||||
|
||||
/** Returns the currently displayed info bar, if any. */
|
||||
- public Gtk.InfoBar? current_info_bar {
|
||||
- get { return get_child() as Gtk.InfoBar; }
|
||||
+ public Components.InfoBar? current_info_bar {
|
||||
+ get { return get_child() as Components.InfoBar; }
|
||||
}
|
||||
|
||||
- private Gee.Queue<Gtk.InfoBar> available;
|
||||
+ private Gee.Queue<Components.InfoBar> available;
|
||||
private int last_allocated_height = 0;
|
||||
|
||||
|
||||
@@ -175,7 +175,7 @@ public class Components.InfoBarStack : Gtk.Frame, Geary.BaseInterface {
|
||||
* stack constructed, the info bar may or may not be revealed
|
||||
* immediately.
|
||||
*/
|
||||
- public new void add(Gtk.InfoBar to_add) {
|
||||
+ public new void add(Components.InfoBar to_add) {
|
||||
if (this.available.offer(to_add)) {
|
||||
update();
|
||||
}
|
||||
@@ -188,7 +188,7 @@ public class Components.InfoBarStack : Gtk.Frame, Geary.BaseInterface {
|
||||
* replaced with the next info bar added. If the only info bar
|
||||
* present is removed, the stack also hides itself.
|
||||
*/
|
||||
- public new void remove(Gtk.InfoBar to_remove) {
|
||||
+ public new void remove(Components.InfoBar to_remove) {
|
||||
if (this.available.remove(to_remove)) {
|
||||
update();
|
||||
}
|
||||
@@ -234,7 +234,7 @@ public class Components.InfoBarStack : Gtk.Frame, Geary.BaseInterface {
|
||||
this.available = new SingletonQueue();
|
||||
break;
|
||||
case PRIORITY_QUEUE:
|
||||
- this.available = new Gee.PriorityQueue<Gtk.InfoBar>(
|
||||
+ this.available = new Gee.PriorityQueue<Components.InfoBar>(
|
||||
InfoBarStack.priority_queue_comparator
|
||||
);
|
||||
break;
|
||||
diff --git a/src/client/components/components-info-bar.vala b/src/client/components/components-info-bar.vala
|
||||
index 05124c00..4ab6b56d 100644
|
||||
--- a/src/client/components/components-info-bar.vala
|
||||
+++ b/src/client/components/components-info-bar.vala
|
||||
@@ -8,9 +8,11 @@
|
||||
/**
|
||||
* A standard info bar widget with status message and description.
|
||||
*/
|
||||
-public class Components.InfoBar : Gtk.InfoBar {
|
||||
+[GtkTemplate (ui = "/org/gnome/Geary/components-info-bar.ui")]
|
||||
+public class Components.InfoBar : Gtk.Box {
|
||||
|
||||
|
||||
+ public signal void response(int response_id);
|
||||
/**
|
||||
* A short, human-readable status message.
|
||||
*
|
||||
@@ -26,11 +28,38 @@ public class Components.InfoBar : Gtk.InfoBar {
|
||||
*/
|
||||
public Gtk.Label? description { get; private set; default = null; }
|
||||
|
||||
+ public bool show_close_button { get; set; default = false;}
|
||||
+ public bool revealed { get; set; }
|
||||
+ private Gtk.MessageType _message_type;
|
||||
+ public Gtk.MessageType message_type {
|
||||
+ get {
|
||||
+ return _message_type;
|
||||
+ }
|
||||
+ set {
|
||||
+ _set_message_type(value);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
|
||||
private Plugin.InfoBar? plugin = null;
|
||||
private string? plugin_action_group_name = null;
|
||||
private Gtk.Button? plugin_primary_button = null;
|
||||
|
||||
+ [GtkChild]
|
||||
+ private Gtk.Revealer revealer;
|
||||
+
|
||||
+ [GtkChild]
|
||||
+ private Gtk.Box action_area;
|
||||
+
|
||||
+ [GtkChild]
|
||||
+ private Gtk.Box content_area;
|
||||
+
|
||||
+ [GtkChild]
|
||||
+ private Gtk.Button close_button;
|
||||
+
|
||||
+ static construct {
|
||||
+ set_css_name("infobar");
|
||||
+ }
|
||||
|
||||
/**
|
||||
* Constructs a new info bar.
|
||||
@@ -43,6 +72,20 @@ public class Components.InfoBar : Gtk.InfoBar {
|
||||
public InfoBar(string status, string? description = null) {
|
||||
this.status = new Gtk.Label(status);
|
||||
this.status.halign = START;
|
||||
+ this.status.xalign = 0;
|
||||
+
|
||||
+ _message_type = Gtk.MessageType.OTHER;
|
||||
+ _set_message_type(Gtk.MessageType.INFO);
|
||||
+
|
||||
+ this.bind_property("revealed",
|
||||
+ this.revealer,
|
||||
+ "reveal-child",
|
||||
+ BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL);
|
||||
+
|
||||
+ this.bind_property("show-close-button",
|
||||
+ this.close_button,
|
||||
+ "visible",
|
||||
+ BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL);
|
||||
|
||||
var attrs = new Pango.AttrList();
|
||||
attrs.change(Pango.attr_weight_new(BOLD));
|
||||
@@ -57,11 +100,8 @@ public class Components.InfoBar : Gtk.InfoBar {
|
||||
this.description = new Gtk.Label(description);
|
||||
this.description.halign = START;
|
||||
this.description.valign = START;
|
||||
-
|
||||
- // Set the description to be ellipsised and set and the
|
||||
- // tool-tip to be the same, in case it is too long for the
|
||||
- // info bar's width
|
||||
- this.description.ellipsize = END;
|
||||
+ this.description.xalign = 0;
|
||||
+ this.description.wrap = true;
|
||||
this.description.tooltip_text = description;
|
||||
}
|
||||
|
||||
@@ -85,15 +125,28 @@ public class Components.InfoBar : Gtk.InfoBar {
|
||||
this.plugin_action_group_name = action_group_name;
|
||||
this.show_close_button = plugin.show_close_button;
|
||||
|
||||
+ _message_type = Gtk.MessageType.OTHER;
|
||||
+ _set_message_type(Gtk.MessageType.INFO);
|
||||
+
|
||||
+ this.bind_property("revealed",
|
||||
+ this.revealer,
|
||||
+ "reveal-child",
|
||||
+ BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL);
|
||||
+
|
||||
+ this.bind_property("show-close-button",
|
||||
+ this.close_button,
|
||||
+ "visible",
|
||||
+ BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL);
|
||||
+
|
||||
plugin.notify["status"].connect(
|
||||
() => { this.status.label = plugin.status; }
|
||||
- );
|
||||
+ );
|
||||
plugin.notify["description"].connect(
|
||||
() => { this.description.label = plugin.description; }
|
||||
- );
|
||||
+ );
|
||||
plugin.notify["primary-button"].connect(
|
||||
() => { this.update_plugin_primary_button(); }
|
||||
- );
|
||||
+ );
|
||||
|
||||
var secondaries = plugin.secondary_buttons.bidir_list_iterator();
|
||||
bool has_prev = secondaries.last();
|
||||
@@ -108,11 +161,12 @@ public class Components.InfoBar : Gtk.InfoBar {
|
||||
show_all();
|
||||
}
|
||||
|
||||
- /* {@inheritDoc} */
|
||||
- public override void response(int response) {
|
||||
- if (response == Gtk.ResponseType.CLOSE && this.plugin != null) {
|
||||
+ [GtkCallback]
|
||||
+ public void on_close_button_clicked() {
|
||||
+ if (this.plugin != null) {
|
||||
this.plugin.close_activated();
|
||||
}
|
||||
+ response(Gtk.ResponseType.CLOSE);
|
||||
}
|
||||
|
||||
/* {@inheritDoc} */
|
||||
@@ -120,10 +174,22 @@ public class Components.InfoBar : Gtk.InfoBar {
|
||||
this.plugin = null;
|
||||
}
|
||||
|
||||
- // GTK 3.24.16 fixed the binding for this, but that and the VAPI
|
||||
- // change has yet to trickle down to common distros like F31
|
||||
- public new Gtk.Box get_action_area() {
|
||||
- return (Gtk.Box) base.get_action_area();
|
||||
+ public Gtk.Box get_action_area() {
|
||||
+ return this.action_area;
|
||||
+ }
|
||||
+
|
||||
+ public Gtk.Box get_content_area() {
|
||||
+ return this.content_area;
|
||||
+ }
|
||||
+
|
||||
+ public Gtk.Button add_button(string button_text, int response_id) {
|
||||
+ var button = new Gtk.Button.with_mnemonic(button_text);
|
||||
+ button.clicked.connect(() => {
|
||||
+ response(response_id);
|
||||
+ });
|
||||
+ get_action_area().add(button);
|
||||
+ button.visible = true;
|
||||
+ return button;
|
||||
}
|
||||
|
||||
private void update_plugin_primary_button() {
|
||||
@@ -162,4 +228,59 @@ public class Components.InfoBar : Gtk.InfoBar {
|
||||
return button;
|
||||
}
|
||||
|
||||
+ private void _set_message_type(Gtk.MessageType message_type) {
|
||||
+ if (this._message_type != message_type) {
|
||||
+ Gtk.StyleContext context = this.get_style_context();
|
||||
+ const string[] type_class = {
|
||||
+ Gtk.STYLE_CLASS_INFO,
|
||||
+ Gtk.STYLE_CLASS_WARNING,
|
||||
+ Gtk.STYLE_CLASS_QUESTION,
|
||||
+ Gtk.STYLE_CLASS_ERROR,
|
||||
+ null
|
||||
+ };
|
||||
+
|
||||
+ if (type_class[this._message_type] != null)
|
||||
+ context.remove_class(type_class[this._message_type]);
|
||||
+
|
||||
+ this._message_type = message_type;
|
||||
+
|
||||
+ var atk_obj = this.get_accessible();
|
||||
+ if (atk_obj is Atk.Object) {
|
||||
+ string name = null;
|
||||
+
|
||||
+ atk_obj.set_role(Atk.Role.INFO_BAR);
|
||||
+
|
||||
+ switch (message_type) {
|
||||
+ case Gtk.MessageType.INFO:
|
||||
+ name = _("Information");
|
||||
+ break;
|
||||
+
|
||||
+ case Gtk.MessageType.QUESTION:
|
||||
+ name = _("Question");
|
||||
+ break;
|
||||
+
|
||||
+ case Gtk.MessageType.WARNING:
|
||||
+ name = _("Warning");
|
||||
+ break;
|
||||
+
|
||||
+ case Gtk.MessageType.ERROR:
|
||||
+ name = _("Error");
|
||||
+ break;
|
||||
+
|
||||
+ case Gtk.MessageType.OTHER:
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ warning("Unknown GtkMessageType %u", message_type);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (name != null)
|
||||
+ atk_obj.set_name(name);
|
||||
+ }
|
||||
+
|
||||
+ if (type_class[this._message_type] != null)
|
||||
+ context.add_class(type_class[this._message_type]);
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
diff --git a/src/client/conversation-viewer/conversation-list-box.vala b/src/client/conversation-viewer/conversation-list-box.vala
|
||||
index 3eb8240b..7d0c94af 100644
|
||||
--- a/src/client/conversation-viewer/conversation-list-box.vala
|
||||
+++ b/src/client/conversation-viewer/conversation-list-box.vala
|
||||
@@ -936,7 +936,7 @@ public class ConversationListBox : Gtk.ListBox, Geary.BaseInterface {
|
||||
|
||||
/** Adds an info bar to the given email, if any. */
|
||||
public void add_email_info_bar(Geary.EmailIdentifier id,
|
||||
- Gtk.InfoBar info_bar) {
|
||||
+ Components.InfoBar info_bar) {
|
||||
var row = this.email_rows.get(id);
|
||||
if (row != null) {
|
||||
row.view.primary_message.info_bars.add(info_bar);
|
||||
@@ -945,7 +945,7 @@ public class ConversationListBox : Gtk.ListBox, Geary.BaseInterface {
|
||||
|
||||
/** Adds an info bar to the given email, if any. */
|
||||
public void remove_email_info_bar(Geary.EmailIdentifier id,
|
||||
- Gtk.InfoBar info_bar) {
|
||||
+ Components.InfoBar info_bar) {
|
||||
var row = this.email_rows.get(id);
|
||||
if (row != null) {
|
||||
row.view.primary_message.info_bars.remove(info_bar);
|
||||
diff --git a/src/client/conversation-viewer/conversation-message.vala b/src/client/conversation-viewer/conversation-message.vala
|
||||
index 109c4a1c..868fea7e 100644
|
||||
--- a/src/client/conversation-viewer/conversation-message.vala
|
||||
+++ b/src/client/conversation-viewer/conversation-message.vala
|
||||
@@ -380,7 +380,7 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
|
||||
[GtkChild]
|
||||
private Gtk.ProgressBar body_progress;
|
||||
|
||||
- private Gtk.InfoBar? remote_images_info_bar = null;
|
||||
+ private Components.InfoBar? remote_images_info_bar = null;
|
||||
|
||||
private Gtk.Widget? body_placeholder = null;
|
||||
|
||||
@@ -1460,7 +1460,7 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
|
||||
}
|
||||
}
|
||||
|
||||
- private void on_remote_images_response(Gtk.InfoBar info_bar, int response_id) {
|
||||
+ private void on_remote_images_response(Components.InfoBar info_bar, int response_id) {
|
||||
switch (response_id) {
|
||||
case 1:
|
||||
// Show images for the message
|
||||
diff --git a/ui/components-info-bar.ui b/ui/components-info-bar.ui
|
||||
new file mode 100644
|
||||
index 00000000..11dcfe37
|
||||
--- /dev/null
|
||||
+++ b/ui/components-info-bar.ui
|
||||
@@ -0,0 +1,83 @@
|
||||
+<?xml version="1.0" encoding="UTF-8"?>
|
||||
+<interface>
|
||||
+ <requires lib="gtk+" version="3.20"/>
|
||||
+ <template class="ComponentsInfoBar" parent="GtkBox">
|
||||
+ <property name="visible">True</property>
|
||||
+ <property name="can_focus">False</property>
|
||||
+ <child>
|
||||
+ <object class="GtkRevealer" id="revealer">
|
||||
+ <property name="visible">True</property>
|
||||
+ <property name="can_focus">False</property>
|
||||
+ <property name="transition_type">slide-down</property>
|
||||
+ <child>
|
||||
+ <object class="GtkBox">
|
||||
+ <property name="visible">True</property>
|
||||
+ <property name="can_focus">False</property>
|
||||
+ <child>
|
||||
+ <object class="GtkFlowBox">
|
||||
+ <property name="visible">True</property>
|
||||
+ <property name="can_focus">False</property>
|
||||
+ <property name="hexpand">True</property>
|
||||
+ <property name="selection-mode">none</property>
|
||||
+ <property name="max_children_per_line">2</property>
|
||||
+ <property name="border-width">12</property>
|
||||
+ <child>
|
||||
+ <object class="GtkFlowBoxChild">
|
||||
+ <property name="visible">True</property>
|
||||
+ <property name="can_focus">True</property>
|
||||
+ <child>
|
||||
+ <object class="GtkBox" id="content_area">
|
||||
+ <property name="visible">True</property>
|
||||
+ <property name="can_focus">False</property>
|
||||
+ <property name="spacing">16</property>
|
||||
+ </object>
|
||||
+ </child>
|
||||
+ </object>
|
||||
+ </child>
|
||||
+ <child>
|
||||
+ <object class="GtkFlowBoxChild">
|
||||
+ <property name="visible">True</property>
|
||||
+ <property name="can_focus">True</property>
|
||||
+ <child>
|
||||
+ <object class="GtkButtonBox" id="action_area">
|
||||
+ <property name="visible">True</property>
|
||||
+ <property name="can_focus">False</property>
|
||||
+ <property name="layout_style">end</property>
|
||||
+ <property name="spacing">6</property>
|
||||
+ </object>
|
||||
+ </child>
|
||||
+ </object>
|
||||
+ </child>
|
||||
+ </object>
|
||||
+ </child>
|
||||
+ <child>
|
||||
+ <object class="GtkButton" id="close_button">
|
||||
+ <property name="can_focus">True</property>
|
||||
+ <property name="receives_default">True</property>
|
||||
+ <property name="halign">end</property>
|
||||
+ <property name="valign">center</property>
|
||||
+ <property name="margin">6</property>
|
||||
+ <property name="no_show_all">True</property>
|
||||
+ <signal name="clicked" handler="on_close_button_clicked" swapped="no"/>
|
||||
+ <style>
|
||||
+ <class name="titlebutton"/>
|
||||
+ <class name="close"/>
|
||||
+ </style>
|
||||
+ <child>
|
||||
+ <object class="GtkImage">
|
||||
+ <property name="visible">True</property>
|
||||
+ <property name="can_focus">False</property>
|
||||
+ <property name="icon_name">window-close-symbolic</property>
|
||||
+ </object>
|
||||
+ </child>
|
||||
+ </object>
|
||||
+ <packing>
|
||||
+ <property name="pack_type">end</property>
|
||||
+ </packing>
|
||||
+ </child>
|
||||
+ </object>
|
||||
+ </child>
|
||||
+ </object>
|
||||
+ </child>
|
||||
+ </template>
|
||||
+</interface>
|
||||
diff --git a/ui/geary.css b/ui/geary.css
|
||||
index 2d1d48c3..e38d135a 100644
|
||||
--- a/ui/geary.css
|
||||
+++ b/ui/geary.css
|
||||
@@ -62,6 +62,10 @@ geary-conversation-viewer {
|
||||
border-right-width: 0;
|
||||
}
|
||||
|
||||
+infobar flowboxchild {
|
||||
+ padding: 0px;
|
||||
+}
|
||||
+
|
||||
/* FolderPopover */
|
||||
|
||||
row.geary-folder-popover-list-row {
|
||||
diff --git a/ui/org.gnome.Geary.gresource.xml b/ui/org.gnome.Geary.gresource.xml
|
||||
index 0b9e900f..fbd7899d 100644
|
||||
--- a/ui/org.gnome.Geary.gresource.xml
|
||||
+++ b/ui/org.gnome.Geary.gresource.xml
|
||||
@@ -16,6 +16,7 @@
|
||||
<file compressed="true" preprocess="xml-stripblanks">components-conversation-action-bar.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">components-conversation-actions.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">components-in-app-notification.ui</file>
|
||||
+ <file compressed="true" preprocess="xml-stripblanks">components-info-bar.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">components-inspector.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">components-inspector-error-view.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">components-inspector-log-view.ui</file>
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,150 @@
|
||||
From 940ca83195ba1f145a70b9dd0246f4d5aa2a069d Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Wed, 9 Sep 2020 18:33:44 +1000
|
||||
Subject: [PATCH 005/124] Geary.Db.Context: Remove separate `logging_parent`
|
||||
property
|
||||
|
||||
Since each context type already has access to the object that is its
|
||||
context parent, don't bother with a stand-alone `logging_parent`
|
||||
property, just have context types implement it and return the
|
||||
appropriate object.
|
||||
---
|
||||
src/engine/db/db-context.vala | 8 +-------
|
||||
src/engine/db/db-database-connection.vala | 6 +++++-
|
||||
src/engine/db/db-database.vala | 10 ++++++++--
|
||||
src/engine/db/db-result.vala | 6 ++++--
|
||||
src/engine/db/db-statement.vala | 5 +++++
|
||||
5 files changed, 23 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/src/engine/db/db-context.vala b/src/engine/db/db-context.vala
|
||||
index 6713f6c8..2ba8b305 100644
|
||||
--- a/src/engine/db/db-context.vala
|
||||
+++ b/src/engine/db/db-context.vala
|
||||
@@ -33,8 +33,7 @@ public abstract class Geary.Db.Context : BaseObject, Logging.Source {
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
- public Logging.Source? logging_parent { get { return _logging_parent; } }
|
||||
- private weak Logging.Source? _logging_parent = null;
|
||||
+ public abstract Logging.Source? logging_parent { get; }
|
||||
|
||||
|
||||
internal virtual Database? get_database() {
|
||||
@@ -53,11 +52,6 @@ public abstract class Geary.Db.Context : BaseObject, Logging.Source {
|
||||
return null;
|
||||
}
|
||||
|
||||
- /** {@inheritDoc} */
|
||||
- public void set_logging_parent(Logging.Source parent) {
|
||||
- this._logging_parent = parent;
|
||||
- }
|
||||
-
|
||||
/** {@inheritDoc} */
|
||||
public abstract Logging.State to_logging_state();
|
||||
|
||||
diff --git a/src/engine/db/db-database-connection.vala b/src/engine/db/db-database-connection.vala
|
||||
index d58911e4..54d36160 100644
|
||||
--- a/src/engine/db/db-database-connection.vala
|
||||
+++ b/src/engine/db/db-database-connection.vala
|
||||
@@ -66,6 +66,11 @@ public class Geary.Db.DatabaseConnection : Context, Connection {
|
||||
public Database database { get { return this._database; } }
|
||||
private weak Database _database;
|
||||
|
||||
+ /** {@inheritDoc} */
|
||||
+ public override Logging.Source? logging_parent {
|
||||
+ get { return this._database; }
|
||||
+ }
|
||||
+
|
||||
/** {@inheritDoc} */
|
||||
internal Sqlite.Database db { get { return this._db; } }
|
||||
private Sqlite.Database _db;
|
||||
@@ -119,7 +124,6 @@ public class Geary.Db.DatabaseConnection : Context, Connection {
|
||||
/** {@inheritDoc} */
|
||||
public Statement prepare(string sql) throws DatabaseError {
|
||||
var prepared = new Statement(this, sql);
|
||||
- prepared.set_logging_parent(this);
|
||||
return prepared;
|
||||
}
|
||||
|
||||
diff --git a/src/engine/db/db-database.vala b/src/engine/db/db-database.vala
|
||||
index a807e7ba..df5bed21 100644
|
||||
--- a/src/engine/db/db-database.vala
|
||||
+++ b/src/engine/db/db-database.vala
|
||||
@@ -57,6 +57,10 @@ public class Geary.Db.Database : Context {
|
||||
}
|
||||
}
|
||||
|
||||
+ /** {@inheritDoc} */
|
||||
+ public override Logging.Source? logging_parent { get { return _logging_parent; } }
|
||||
+ private weak Logging.Source? _logging_parent = null;
|
||||
+
|
||||
private DatabaseConnection? primary = null;
|
||||
private int outstanding_async_jobs = 0;
|
||||
private ThreadPool<TransactionAsyncJob>? thread_pool = null;
|
||||
@@ -143,7 +147,6 @@ public class Geary.Db.Database : Context {
|
||||
var cx = new DatabaseConnection(
|
||||
this, Sqlite.OPEN_READWRITE, cancellable
|
||||
);
|
||||
- cx.set_logging_parent(this);
|
||||
|
||||
try {
|
||||
// drop existing test table (in case created in prior failed open)
|
||||
@@ -233,7 +236,6 @@ public class Geary.Db.Database : Context {
|
||||
DatabaseConnection cx = new DatabaseConnection(
|
||||
this, sqlite_flags, cancellable
|
||||
);
|
||||
- cx.set_logging_parent(this);
|
||||
prepare_connection(cx);
|
||||
return cx;
|
||||
}
|
||||
@@ -357,6 +359,10 @@ public class Geary.Db.Database : Context {
|
||||
return yield job.wait_for_completion_async();
|
||||
}
|
||||
|
||||
+ /** Sets the logging parent context object for this database. */
|
||||
+ public void set_logging_parent(Logging.Source parent) {
|
||||
+ this._logging_parent = parent;
|
||||
+ }
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public override Logging.State to_logging_state() {
|
||||
diff --git a/src/engine/db/db-result.vala b/src/engine/db/db-result.vala
|
||||
index b5382179..8c40c475 100644
|
||||
--- a/src/engine/db/db-result.vala
|
||||
+++ b/src/engine/db/db-result.vala
|
||||
@@ -10,12 +10,14 @@ public class Geary.Db.Result : Geary.Db.Context {
|
||||
|
||||
public Statement statement { get; private set; }
|
||||
|
||||
+ /** {@inheritDoc} */
|
||||
+ public override Logging.Source? logging_parent {
|
||||
+ get { return this.statement; }
|
||||
+ }
|
||||
|
||||
// This results in an automatic first next().
|
||||
internal Result(Statement statement, Cancellable? cancellable) throws Error {
|
||||
this.statement = statement;
|
||||
- set_logging_parent(statement);
|
||||
-
|
||||
statement.was_reset.connect(on_query_finished);
|
||||
statement.bindings_cleared.connect(on_query_finished);
|
||||
|
||||
diff --git a/src/engine/db/db-statement.vala b/src/engine/db/db-statement.vala
|
||||
index 4d792b42..072692ff 100644
|
||||
--- a/src/engine/db/db-statement.vala
|
||||
+++ b/src/engine/db/db-statement.vala
|
||||
@@ -12,6 +12,11 @@ public class Geary.Db.Statement : Context {
|
||||
|
||||
public string sql { get; private set; }
|
||||
|
||||
+ /** {@inheritDoc} */
|
||||
+ public override Logging.Source? logging_parent {
|
||||
+ get { return this.connection; }
|
||||
+ }
|
||||
+
|
||||
internal DatabaseConnection connection { get; private set; }
|
||||
|
||||
internal Sqlite.Statement stmt;
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,38 @@
|
||||
From 7c9d1258c6a952c7b7f79f34feb3225dea3fcc15 Mon Sep 17 00:00:00 2001
|
||||
From: Arnaud Ferraris <arnaud.ferraris@collabora.com>
|
||||
Date: Wed, 25 Mar 2020 14:40:11 +0100
|
||||
Subject: [PATCH 5/8] accounts-editor: make window usable on phones
|
||||
|
||||
---
|
||||
ui/accounts_editor.ui | 2 +-
|
||||
ui/accounts_editor_list_pane.ui | 1 +
|
||||
2 files changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/ui/accounts_editor.ui b/ui/accounts_editor.ui
|
||||
index 4e23cdd5..04581e8d 100644
|
||||
--- a/ui/accounts_editor.ui
|
||||
+++ b/ui/accounts_editor.ui
|
||||
@@ -5,7 +5,7 @@
|
||||
<template class="AccountsEditor" parent="GtkDialog">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="modal">True</property>
|
||||
- <property name="default_width">700</property>
|
||||
+ <property name="default_width">360</property>
|
||||
<property name="default_height">450</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<child type="titlebar">
|
||||
diff --git a/ui/accounts_editor_list_pane.ui b/ui/accounts_editor_list_pane.ui
|
||||
index a40604e3..b3946196 100644
|
||||
--- a/ui/accounts_editor_list_pane.ui
|
||||
+++ b/ui/accounts_editor_list_pane.ui
|
||||
@@ -59,6 +59,7 @@
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">start</property>
|
||||
+ <property name="wrap">True</property>
|
||||
<property name="label" translatable="yes">To get started, select an email provider below.</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="wrap">True</property>
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,37 @@
|
||||
From d1800de4dac6911b414b223318c6b12549e3a887 Mon Sep 17 00:00:00 2001
|
||||
From: Julian Sparber <julian@sparber.net>
|
||||
Date: Wed, 21 Oct 2020 11:18:19 +0200
|
||||
Subject: [PATCH 5/6] conversation-viewer: don't show action-bar when in
|
||||
composer
|
||||
|
||||
---
|
||||
src/client/components/main-toolbar.vala | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/client/components/main-toolbar.vala b/src/client/components/main-toolbar.vala
|
||||
index f216238a..8255c93b 100644
|
||||
--- a/src/client/components/main-toolbar.vala
|
||||
+++ b/src/client/components/main-toolbar.vala
|
||||
@@ -60,6 +60,7 @@ public class MainToolbar : Hdy.Leaflet {
|
||||
}
|
||||
this.conversation_viewer_action_bar = action_bar;
|
||||
conversation_header.size_allocate.connect(on_size_allocate);
|
||||
+ conversation_header.notify["parent"].connect(on_size_allocate);
|
||||
|
||||
// Assemble the main/mark menus
|
||||
Gtk.Builder builder = new Gtk.Builder.from_resource("/org/gnome/Geary/main-toolbar-menus.ui");
|
||||
@@ -110,7 +111,10 @@ public class MainToolbar : Hdy.Leaflet {
|
||||
}
|
||||
|
||||
private void on_size_allocate() {
|
||||
- if (reply_forward_buttons != null && archive_trash_delete_buttons != null)
|
||||
+ /* Only show the action_bar when the conversation_header is shown */
|
||||
+ if (conversation_header.parent == null)
|
||||
+ conversation_viewer_action_bar.reveal_child = false;
|
||||
+ else if (reply_forward_buttons != null && archive_trash_delete_buttons != null)
|
||||
if (conversation_viewer_action_bar.reveal_child && get_allocated_width() > 600) {
|
||||
conversation_viewer_action_bar.reveal_child = false;
|
||||
remove_action_parent();
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,28 @@
|
||||
From e39853db6215ac720dd047f48d940236cdbaa7f1 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Wed, 9 Sep 2020 18:38:08 +1000
|
||||
Subject: [PATCH 006/124] Geary.ImapEngine.GenericAccount: Set database logging
|
||||
parent per account
|
||||
|
||||
Set the database's logging parent so its log statements are associated
|
||||
with its account in the inspector.
|
||||
---
|
||||
src/engine/imap-engine/imap-engine-generic-account.vala | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/src/engine/imap-engine/imap-engine-generic-account.vala b/src/engine/imap-engine/imap-engine-generic-account.vala
|
||||
index 2bd087b1..ef1ba7b4 100644
|
||||
--- a/src/engine/imap-engine/imap-engine-generic-account.vala
|
||||
+++ b/src/engine/imap-engine/imap-engine-generic-account.vala
|
||||
@@ -79,6 +79,8 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account {
|
||||
base(config, imap, smtp);
|
||||
|
||||
this.local = local;
|
||||
+ this.local.db.set_logging_parent(this);
|
||||
+
|
||||
this.contact_store = new ContactStoreImpl(local.db);
|
||||
|
||||
imap.min_pool_size = IMAP_MIN_POOL_SIZE;
|
||||
--
|
||||
2.29.2
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,49 @@
|
||||
From 805eb739e94e84ff3566283b9a89dcacc7b871e8 Mon Sep 17 00:00:00 2001
|
||||
From: Julian Sparber <julian@sparber.net>
|
||||
Date: Thu, 22 Oct 2020 12:33:58 +0200
|
||||
Subject: [PATCH 6/6] in-app-notification: wrap text and add start/end margin
|
||||
|
||||
This makes sure that the in-app-notification fits also small window
|
||||
sizes and eventually wraps the text to a new.
|
||||
---
|
||||
ui/components-in-app-notification.ui | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/ui/components-in-app-notification.ui b/ui/components-in-app-notification.ui
|
||||
index 54a1dafd..adbb3e2f 100644
|
||||
--- a/ui/components-in-app-notification.ui
|
||||
+++ b/ui/components-in-app-notification.ui
|
||||
@@ -5,6 +5,8 @@
|
||||
<property name="visible">False</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">start</property>
|
||||
+ <property name="margin-start">12</property>
|
||||
+ <property name="margin-end">12</property>
|
||||
<signal name="notify::child-revealed" handler="on_child_revealed" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkBox" id="layout">
|
||||
@@ -17,18 +19,21 @@
|
||||
<child>
|
||||
<object class="GtkLabel" id="message_label">
|
||||
<property name="visible">True</property>
|
||||
+ <property name="wrap">True</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="action_button">
|
||||
<property name="visible">False</property>
|
||||
<property name="can_focus">False</property>
|
||||
+ <property name="valign">center</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="close_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
+ <property name="valign">center</property>
|
||||
<signal name="clicked" handler="close" swapped="no"/>
|
||||
<style>
|
||||
<class name="flat"/>
|
||||
--
|
||||
2.29.2
|
||||
|
157
mail-client/geary/files/0007-Geary.Db-Update-SQL-logging.patch
Normal file
157
mail-client/geary/files/0007-Geary.Db-Update-SQL-logging.patch
Normal file
@ -0,0 +1,157 @@
|
||||
From 0f60c285df50586058f9368c29f7b288c8076b76 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Wed, 9 Sep 2020 18:48:43 +1000
|
||||
Subject: [PATCH 007/124] Geary.Db: Update SQL logging
|
||||
|
||||
Ensure all code paths that execute SQL are logging it if enabled, and
|
||||
clean up the log formatting.
|
||||
|
||||
Add new `enable_result_logging` static property to control result
|
||||
logging separately from SQL logging, so we can get SQL logged without
|
||||
having to see email. Clean up result formatting, and keep track of the
|
||||
current result row number and log that as context.
|
||||
---
|
||||
src/engine/db/db-context.vala | 17 ++++++++++----
|
||||
src/engine/db/db-database-connection.vala | 14 +++++++-----
|
||||
src/engine/db/db-result.vala | 27 +++++++++++++----------
|
||||
3 files changed, 37 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/src/engine/db/db-context.vala b/src/engine/db/db-context.vala
|
||||
index 2ba8b305..7b8b9d65 100644
|
||||
--- a/src/engine/db/db-context.vala
|
||||
+++ b/src/engine/db/db-context.vala
|
||||
@@ -16,16 +16,25 @@
|
||||
public abstract class Geary.Db.Context : BaseObject, Logging.Source {
|
||||
|
||||
|
||||
+ /** The GLib logging domain used by this class. */
|
||||
+ public const string LOGGING_DOMAIN = Logging.DOMAIN + ".Db";
|
||||
+
|
||||
+
|
||||
/**
|
||||
- * Determines if SQL queries and results will be logged.
|
||||
+ * Determines if SQL queries will be logged.
|
||||
*
|
||||
- * This will cause extremely verbose logging, so enable with care.
|
||||
+ * This will cause verbose logging, so enable with care.
|
||||
*/
|
||||
public static bool enable_sql_logging = false;
|
||||
|
||||
|
||||
- /** The GLib logging domain used by this class. */
|
||||
- public const string LOGGING_DOMAIN = Logging.DOMAIN + ".Db";
|
||||
+ /**
|
||||
+ * Determines if SQL results will be logged.
|
||||
+ *
|
||||
+ * This will cause extremely verbose logging, so enable with extra care.
|
||||
+ */
|
||||
+ public static bool enable_result_logging = false;
|
||||
+
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public string logging_domain {
|
||||
diff --git a/src/engine/db/db-database-connection.vala b/src/engine/db/db-database-connection.vala
|
||||
index 54d36160..29d52fd1 100644
|
||||
--- a/src/engine/db/db-database-connection.vala
|
||||
+++ b/src/engine/db/db-database-connection.vala
|
||||
@@ -123,8 +123,10 @@ public class Geary.Db.DatabaseConnection : Context, Connection {
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public Statement prepare(string sql) throws DatabaseError {
|
||||
- var prepared = new Statement(this, sql);
|
||||
- return prepared;
|
||||
+ if (Db.Context.enable_sql_logging) {
|
||||
+ debug(sql);
|
||||
+ }
|
||||
+ return new Statement(this, sql);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@@ -136,11 +138,10 @@ public class Geary.Db.DatabaseConnection : Context, Connection {
|
||||
/** {@inheritDoc} */
|
||||
public void exec(string sql, GLib.Cancellable? cancellable = null)
|
||||
throws GLib.Error {
|
||||
+ check_cancelled("Connection.exec", cancellable);
|
||||
if (Db.Context.enable_sql_logging) {
|
||||
- debug("exec:\n\t%s", sql);
|
||||
+ debug(sql);
|
||||
}
|
||||
-
|
||||
- check_cancelled("Connection.exec", cancellable);
|
||||
var timer = new GLib.Timer();
|
||||
throw_on_error("Connection.exec_file", this.db.exec(sql), sql);
|
||||
check_elapsed("Query \"%s\"".printf(sql), timer);
|
||||
@@ -150,6 +151,9 @@ public class Geary.Db.DatabaseConnection : Context, Connection {
|
||||
public void exec_file(GLib.File file, GLib.Cancellable? cancellable = null)
|
||||
throws GLib.Error {
|
||||
check_cancelled("Connection.exec_file", cancellable);
|
||||
+ if (Db.Context.enable_sql_logging) {
|
||||
+ debug(file.get_path());
|
||||
+ }
|
||||
|
||||
string sql;
|
||||
FileUtils.get_contents(file.get_path(), out sql);
|
||||
diff --git a/src/engine/db/db-result.vala b/src/engine/db/db-result.vala
|
||||
index 8c40c475..14dc71a9 100644
|
||||
--- a/src/engine/db/db-result.vala
|
||||
+++ b/src/engine/db/db-result.vala
|
||||
@@ -8,8 +8,12 @@ public class Geary.Db.Result : Geary.Db.Context {
|
||||
public bool finished { get; private set; default = false; }
|
||||
|
||||
|
||||
+ /** The statement this result was generated from. */
|
||||
public Statement statement { get; private set; }
|
||||
|
||||
+ /** The current row represented by this result. */
|
||||
+ public uint64 row { get; private set; default = 0; }
|
||||
+
|
||||
/** {@inheritDoc} */
|
||||
public override Logging.Source? logging_parent {
|
||||
get { return this.statement; }
|
||||
@@ -39,7 +43,8 @@ public class Geary.Db.Result : Geary.Db.Context {
|
||||
public bool next(Cancellable? cancellable = null) throws Error {
|
||||
check_cancelled("Result.next", cancellable);
|
||||
|
||||
- if (!finished) {
|
||||
+ if (!this.finished) {
|
||||
+ this.row++;
|
||||
var timer = new GLib.Timer();
|
||||
this.finished = throw_on_error(
|
||||
"Result.next", statement.stmt.step(), statement.sql
|
||||
@@ -298,7 +303,12 @@ public class Geary.Db.Result : Geary.Db.Context {
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public override Logging.State to_logging_state() {
|
||||
- return new Logging.State(this, this.finished ? "finished" : "not finished");
|
||||
+ return new Logging.State(
|
||||
+ this,
|
||||
+ "%llu, %s",
|
||||
+ this.row,
|
||||
+ this.finished ? "finished" : "!finished"
|
||||
+ );
|
||||
}
|
||||
|
||||
internal override Result? get_result() {
|
||||
@@ -306,16 +316,9 @@ public class Geary.Db.Result : Geary.Db.Context {
|
||||
}
|
||||
|
||||
[PrintfFormat]
|
||||
- private void log_result(string fmt, ...) {
|
||||
- if (Db.Context.enable_sql_logging) {
|
||||
- Statement? stmt = get_statement();
|
||||
- if (stmt != null) {
|
||||
- debug("%s\n\t<%s>",
|
||||
- fmt.vprintf(va_list()),
|
||||
- (stmt != null) ? "%.100s".printf(stmt.sql) : "no sql");
|
||||
- } else {
|
||||
- debug(fmt.vprintf(va_list()));
|
||||
- }
|
||||
+ private inline void log_result(string fmt, ...) {
|
||||
+ if (Db.Context.enable_result_logging) {
|
||||
+ debug(fmt.vprintf(va_list()));
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,354 @@
|
||||
From a30afb9e861450f042fd0d1e52ab6b965a247065 Mon Sep 17 00:00:00 2001
|
||||
From: Julian Sparber <julian@sparber.net>
|
||||
Date: Wed, 14 Oct 2020 14:44:26 +0200
|
||||
Subject: [PATCH 7/8] account-editor: replace remove confirm view with dialog
|
||||
|
||||
---
|
||||
po/POTFILES.in | 1 -
|
||||
.../accounts/accounts-editor-edit-pane.vala | 23 ++-
|
||||
.../accounts/accounts-editor-remove-pane.vala | 74 --------
|
||||
src/client/meson.build | 1 -
|
||||
ui/accounts_editor_remove_pane.ui | 159 ------------------
|
||||
ui/geary.css | 8 +
|
||||
ui/org.gnome.Geary.gresource.xml | 1 -
|
||||
7 files changed, 30 insertions(+), 237 deletions(-)
|
||||
delete mode 100644 src/client/accounts/accounts-editor-remove-pane.vala
|
||||
delete mode 100644 ui/accounts_editor_remove_pane.ui
|
||||
|
||||
diff --git a/po/POTFILES.in b/po/POTFILES.in
|
||||
index cd8b339d..d9dcb0b7 100644
|
||||
--- a/po/POTFILES.in
|
||||
+++ b/po/POTFILES.in
|
||||
@@ -9,7 +9,6 @@ src/client/accounts/accounts-editor.vala
|
||||
src/client/accounts/accounts-editor-add-pane.vala
|
||||
src/client/accounts/accounts-editor-edit-pane.vala
|
||||
src/client/accounts/accounts-editor-list-pane.vala
|
||||
-src/client/accounts/accounts-editor-remove-pane.vala
|
||||
src/client/accounts/accounts-editor-row.vala
|
||||
src/client/accounts/accounts-editor-servers-pane.vala
|
||||
src/client/accounts/accounts-manager.vala
|
||||
diff --git a/src/client/accounts/accounts-editor-edit-pane.vala b/src/client/accounts/accounts-editor-edit-pane.vala
|
||||
index 5b944333..405dc7ba 100644
|
||||
--- a/src/client/accounts/accounts-editor-edit-pane.vala
|
||||
+++ b/src/client/accounts/accounts-editor-edit-pane.vala
|
||||
@@ -217,7 +217,28 @@ internal class Accounts.EditorEditPane :
|
||||
[GtkCallback]
|
||||
private void on_remove_account_clicked() {
|
||||
if (!this.editor.accounts.is_goa_account(account)) {
|
||||
- this.editor.push(new EditorRemovePane(this.editor, this.account));
|
||||
+ var button = new Gtk.Button.with_mnemonic(_("Remove Account"));
|
||||
+ button.get_style_context().add_class(Gtk.STYLE_CLASS_DESTRUCTIVE_ACTION);
|
||||
+ button.show();
|
||||
+
|
||||
+ var dialog = new Gtk.MessageDialog(this.editor,
|
||||
+ Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT,
|
||||
+ Gtk.MessageType.WARNING,
|
||||
+ Gtk.ButtonsType.NONE,
|
||||
+ _("Remove Account: %s"),
|
||||
+ account.primary_mailbox.address);
|
||||
+ dialog.secondary_text = _("This will remove it from Geary and delete locally cached email data from your computer. Nothing will be deleted from your service provider.");
|
||||
+
|
||||
+ dialog.add_button (_("_Cancel"), Gtk.ResponseType.CANCEL);
|
||||
+ dialog.add_action_widget(button, Gtk.ResponseType.ACCEPT);
|
||||
+
|
||||
+ dialog.response.connect((response_id) => {
|
||||
+ if (response_id == Gtk.ResponseType.ACCEPT)
|
||||
+ this.editor.remove_account(this.account);
|
||||
+
|
||||
+ dialog.destroy();
|
||||
+ });
|
||||
+ dialog.show();
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/client/accounts/accounts-editor-remove-pane.vala b/src/client/accounts/accounts-editor-remove-pane.vala
|
||||
deleted file mode 100644
|
||||
index 2a6844cd..00000000
|
||||
--- a/src/client/accounts/accounts-editor-remove-pane.vala
|
||||
+++ /dev/null
|
||||
@@ -1,74 +0,0 @@
|
||||
-/*
|
||||
- * Copyright 2018-2019 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.
|
||||
- */
|
||||
-
|
||||
-/**
|
||||
- * An account editor pane for removing an account from the client.
|
||||
- */
|
||||
-[GtkTemplate (ui = "/org/gnome/Geary/accounts_editor_remove_pane.ui")]
|
||||
-internal class Accounts.EditorRemovePane : Gtk.Grid, EditorPane, AccountPane {
|
||||
-
|
||||
-
|
||||
- /** {@inheritDoc} */
|
||||
- internal weak Accounts.Editor editor { get; set; }
|
||||
-
|
||||
- /** {@inheritDoc} */
|
||||
- internal Geary.AccountInformation account { get ; protected set; }
|
||||
-
|
||||
- /** {@inheritDoc} */
|
||||
- internal Gtk.Widget initial_widget {
|
||||
- get { return this.remove_button; }
|
||||
- }
|
||||
-
|
||||
- /** {@inheritDoc} */
|
||||
- internal bool is_operation_running { get; protected set; default = false; }
|
||||
-
|
||||
- /** {@inheritDoc} */
|
||||
- internal GLib.Cancellable? op_cancellable {
|
||||
- get; protected set; default = null;
|
||||
- }
|
||||
-
|
||||
- [GtkChild]
|
||||
- private Gtk.HeaderBar header;
|
||||
-
|
||||
- [GtkChild]
|
||||
- private Gtk.Label warning_label;
|
||||
-
|
||||
- [GtkChild]
|
||||
- private Gtk.Button remove_button;
|
||||
-
|
||||
-
|
||||
- public EditorRemovePane(Editor editor, Geary.AccountInformation account) {
|
||||
- this.editor = editor;
|
||||
- this.account = account;
|
||||
-
|
||||
- this.warning_label.set_text(
|
||||
- this.warning_label.get_text().printf(account.display_name)
|
||||
- );
|
||||
-
|
||||
- connect_account_signals();
|
||||
- }
|
||||
-
|
||||
- ~EditorRemovePane() {
|
||||
- disconnect_account_signals();
|
||||
- }
|
||||
-
|
||||
- /** {@inheritDoc} */
|
||||
- internal Gtk.HeaderBar get_header() {
|
||||
- return this.header;
|
||||
- }
|
||||
-
|
||||
- [GtkCallback]
|
||||
- private void on_remove_button_clicked() {
|
||||
- this.editor.remove_account(this.account);
|
||||
- }
|
||||
-
|
||||
- [GtkCallback]
|
||||
- private void on_back_button_clicked() {
|
||||
- this.editor.pop();
|
||||
- }
|
||||
-
|
||||
-}
|
||||
diff --git a/src/client/meson.build b/src/client/meson.build
|
||||
index 4efadc6d..6514adca 100644
|
||||
--- a/src/client/meson.build
|
||||
+++ b/src/client/meson.build
|
||||
@@ -38,7 +38,6 @@ client_vala_sources = files(
|
||||
'accounts/accounts-editor-add-pane.vala',
|
||||
'accounts/accounts-editor-edit-pane.vala',
|
||||
'accounts/accounts-editor-list-pane.vala',
|
||||
- 'accounts/accounts-editor-remove-pane.vala',
|
||||
'accounts/accounts-editor-row.vala',
|
||||
'accounts/accounts-editor-servers-pane.vala',
|
||||
'accounts/accounts-signature-web-view.vala',
|
||||
diff --git a/ui/accounts_editor_remove_pane.ui b/ui/accounts_editor_remove_pane.ui
|
||||
deleted file mode 100644
|
||||
index 7edf4c13..00000000
|
||||
--- a/ui/accounts_editor_remove_pane.ui
|
||||
+++ /dev/null
|
||||
@@ -1,159 +0,0 @@
|
||||
-<?xml version="1.0" encoding="UTF-8"?>
|
||||
-<!-- Generated with glade 3.22.1 -->
|
||||
-<interface>
|
||||
- <requires lib="gtk+" version="3.20"/>
|
||||
- <template class="AccountsEditorRemovePane" parent="GtkGrid">
|
||||
- <property name="visible">True</property>
|
||||
- <property name="can_focus">False</property>
|
||||
- <property name="valign">center</property>
|
||||
- <child>
|
||||
- <object class="HdyClamp">
|
||||
- <property name="visible">True</property>
|
||||
- <property name="can_focus">False</property>
|
||||
- <property name="margin">24</property>
|
||||
- <child>
|
||||
- <object class="GtkGrid">
|
||||
- <property name="visible">True</property>
|
||||
- <property name="can_focus">False</property>
|
||||
- <property name="valign">start</property>
|
||||
- <property name="vexpand">True</property>
|
||||
- <property name="row_spacing">32</property>
|
||||
- <child>
|
||||
- <object class="GtkButtonBox">
|
||||
- <property name="visible">True</property>
|
||||
- <property name="can_focus">False</property>
|
||||
- <property name="layout_style">end</property>
|
||||
- <child>
|
||||
- <object class="GtkButton" id="remove_button">
|
||||
- <property name="label" translatable="yes" comments="This is the remove account button in the account settings.">Remove Account</property>
|
||||
- <property name="visible">True</property>
|
||||
- <property name="can_focus">True</property>
|
||||
- <property name="receives_default">True</property>
|
||||
- <property name="tooltip_text" translatable="yes">Remove this account from Geary</property>
|
||||
- <signal name="clicked" handler="on_remove_button_clicked" swapped="no"/>
|
||||
- <style>
|
||||
- <class name="destructive-action"/>
|
||||
- </style>
|
||||
- </object>
|
||||
- <packing>
|
||||
- <property name="expand">True</property>
|
||||
- <property name="fill">True</property>
|
||||
- <property name="position">1</property>
|
||||
- </packing>
|
||||
- </child>
|
||||
- <style>
|
||||
- <class name="geary-settings"/>
|
||||
- </style>
|
||||
- </object>
|
||||
- <packing>
|
||||
- <property name="left_attach">0</property>
|
||||
- <property name="top_attach">1</property>
|
||||
- </packing>
|
||||
- </child>
|
||||
- <child>
|
||||
- <object class="GtkGrid">
|
||||
- <property name="visible">True</property>
|
||||
- <property name="can_focus">False</property>
|
||||
- <property name="row_spacing">6</property>
|
||||
- <property name="column_spacing">18</property>
|
||||
- <child>
|
||||
- <object class="GtkImage">
|
||||
- <property name="visible">True</property>
|
||||
- <property name="can_focus">False</property>
|
||||
- <property name="icon_name">dialog-warning-symbolic</property>
|
||||
- <property name="icon_size">6</property>
|
||||
- </object>
|
||||
- <packing>
|
||||
- <property name="left_attach">0</property>
|
||||
- <property name="top_attach">0</property>
|
||||
- <property name="height">2</property>
|
||||
- </packing>
|
||||
- </child>
|
||||
- <child>
|
||||
- <object class="GtkLabel" id="warning_label">
|
||||
- <property name="visible">True</property>
|
||||
- <property name="can_focus">False</property>
|
||||
- <property name="halign">start</property>
|
||||
- <property name="vexpand">True</property>
|
||||
- <property name="label" translatable="yes" comments="This title is shown to users when confirming if they want to remove an account. The string substitution is replaced with the account's name.">Confirm removing: %s</property>
|
||||
- <attributes>
|
||||
- <attribute name="weight" value="bold"/>
|
||||
- </attributes>
|
||||
- <style>
|
||||
- <class name="title"/>
|
||||
- </style>
|
||||
- </object>
|
||||
- <packing>
|
||||
- <property name="left_attach">1</property>
|
||||
- <property name="top_attach">0</property>
|
||||
- </packing>
|
||||
- </child>
|
||||
- <child>
|
||||
- <object class="GtkLabel">
|
||||
- <property name="visible">True</property>
|
||||
- <property name="can_focus">False</property>
|
||||
- <property name="halign">start</property>
|
||||
- <property name="label" translatable="yes">Removing an account will remove it from Geary and delete locally cached email data from your computer, but not from your service provider.</property>
|
||||
- <property name="wrap">True</property>
|
||||
- <property name="xalign">0</property>
|
||||
- </object>
|
||||
- <packing>
|
||||
- <property name="left_attach">1</property>
|
||||
- <property name="top_attach">1</property>
|
||||
- </packing>
|
||||
- </child>
|
||||
- </object>
|
||||
- <packing>
|
||||
- <property name="left_attach">0</property>
|
||||
- <property name="top_attach">0</property>
|
||||
- </packing>
|
||||
- </child>
|
||||
- <style>
|
||||
- <class name="geary-accounts-editor-pane-content"/>
|
||||
- </style>
|
||||
- </object>
|
||||
- </child>
|
||||
- </object>
|
||||
- <packing>
|
||||
- <property name="left_attach">0</property>
|
||||
- <property name="top_attach">0</property>
|
||||
- </packing>
|
||||
- </child>
|
||||
- <style>
|
||||
- <class name="geary-accounts-editor-pane"/>
|
||||
- </style>
|
||||
- </template>
|
||||
- <object class="GtkHeaderBar" id="header">
|
||||
- <property name="visible">True</property>
|
||||
- <property name="can_focus">False</property>
|
||||
- <property name="title" translatable="yes">Remove account</property>
|
||||
- <property name="subtitle" translatable="yes">Account name</property>
|
||||
- <property name="show_close_button">True</property>
|
||||
- <child>
|
||||
- <object class="GtkGrid">
|
||||
- <property name="visible">True</property>
|
||||
- <property name="can_focus">False</property>
|
||||
- <child>
|
||||
- <object class="GtkButton" id="back_button">
|
||||
- <property name="visible">True</property>
|
||||
- <property name="can_focus">True</property>
|
||||
- <property name="receives_default">True</property>
|
||||
- <signal name="clicked" handler="on_back_button_clicked" swapped="no"/>
|
||||
- <child>
|
||||
- <object class="GtkImage">
|
||||
- <property name="visible">True</property>
|
||||
- <property name="can_focus">False</property>
|
||||
- <property name="no_show_all">True</property>
|
||||
- <property name="icon_name">go-previous-symbolic</property>
|
||||
- </object>
|
||||
- </child>
|
||||
- </object>
|
||||
- <packing>
|
||||
- <property name="left_attach">0</property>
|
||||
- <property name="top_attach">0</property>
|
||||
- </packing>
|
||||
- </child>
|
||||
- </object>
|
||||
- </child>
|
||||
- </object>
|
||||
-</interface>
|
||||
diff --git a/ui/geary.css b/ui/geary.css
|
||||
index ca3cf640..3877038f 100644
|
||||
--- a/ui/geary.css
|
||||
+++ b/ui/geary.css
|
||||
@@ -334,6 +334,14 @@ popover.geary-editor > grid > button.geary-setting-remove {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
+dialog.geary-remove-confirm .dialog-vbox {
|
||||
+ margin: 12px;
|
||||
+}
|
||||
+
|
||||
+dialog.geary-remove-confirm .dialog-action-box {
|
||||
+ margin: 6px;
|
||||
+}
|
||||
+
|
||||
/* FolderList.Tree */
|
||||
|
||||
treeview.sidebar:drop(active).after,
|
||||
diff --git a/ui/org.gnome.Geary.gresource.xml b/ui/org.gnome.Geary.gresource.xml
|
||||
index 0b9e900f..efdc87d6 100644
|
||||
--- a/ui/org.gnome.Geary.gresource.xml
|
||||
+++ b/ui/org.gnome.Geary.gresource.xml
|
||||
@@ -5,7 +5,6 @@
|
||||
<file compressed="true" preprocess="xml-stripblanks">accounts_editor_add_pane.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">accounts_editor_edit_pane.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">accounts_editor_list_pane.ui</file>
|
||||
- <file compressed="true" preprocess="xml-stripblanks">accounts_editor_remove_pane.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">accounts_editor_servers_pane.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">application-main-window.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">certificate_warning_dialog.glade</file>
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,262 @@
|
||||
From 915a38faca33caf04cab2398a52d743dea554359 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Fri, 11 Sep 2020 00:00:02 +1000
|
||||
Subject: [PATCH 008/124] Geary.ImapDb.Account: Slice up search table
|
||||
population work better
|
||||
|
||||
Although populating the search table had been broken up into batches
|
||||
of 50 email, it was still search for and loading every single message
|
||||
id in both the MessageTable and MessageSearchTable, doing a manual
|
||||
join, and then updating the batch, for *each* batch, and in a RW
|
||||
transaction.
|
||||
|
||||
Break this up so that the ids are loaded and joined only once, the
|
||||
queries happens in a RO transaction, the manual join happens in a side
|
||||
thread, leaving each RW transaction only having to load the messages
|
||||
and update the search index for up to 50 messages.
|
||||
---
|
||||
src/engine/imap-db/imap-db-account.vala | 205 ++++++++++++++----------
|
||||
1 file changed, 120 insertions(+), 85 deletions(-)
|
||||
|
||||
diff --git a/src/engine/imap-db/imap-db-account.vala b/src/engine/imap-db/imap-db-account.vala
|
||||
index 99244dc2..54522b90 100644
|
||||
--- a/src/engine/imap-db/imap-db-account.vala
|
||||
+++ b/src/engine/imap-db/imap-db-account.vala
|
||||
@@ -955,8 +955,78 @@ private class Geary.ImapDB.Account : BaseObject {
|
||||
|
||||
public async void populate_search_table(Cancellable? cancellable) {
|
||||
debug("%s: Populating search table", account_information.id);
|
||||
+ // Since all queries involved can be quite extensive and this
|
||||
+ // is not a time-critical operation, split them up
|
||||
+
|
||||
+ var search_ids = new Gee.HashSet<int64?>(
|
||||
+ Collection.int64_hash_func,
|
||||
+ Collection.int64_equal_func
|
||||
+ );
|
||||
+ var message_ids = new Gee.HashSet<int64?>(
|
||||
+ Collection.int64_hash_func,
|
||||
+ Collection.int64_equal_func
|
||||
+ );
|
||||
+ var unindexed_message_ids = new Gee.HashSet<int64?>(
|
||||
+ Collection.int64_hash_func,
|
||||
+ Collection.int64_equal_func
|
||||
+ );
|
||||
+
|
||||
try {
|
||||
- while (!yield populate_search_table_batch_async(50, cancellable)) {
|
||||
+ yield this.db.exec_transaction_async(
|
||||
+ RO,
|
||||
+ (cx, cancellable) => {
|
||||
+ // Embedding a SELECT within a SELECT is painfully slow
|
||||
+ // with SQLite, and a LEFT OUTER JOIN will still take in
|
||||
+ // the order of seconds, so manually perform the operation
|
||||
+
|
||||
+ var result = cx.prepare(
|
||||
+ "SELECT docid FROM MessageSearchTable"
|
||||
+ ).exec(cancellable);
|
||||
+ while (!result.finished) {
|
||||
+ search_ids.add(result.rowid_at(0));
|
||||
+ result.next(cancellable);
|
||||
+ }
|
||||
+
|
||||
+ var stmt = cx.prepare(
|
||||
+ "SELECT id FROM MessageTable WHERE (fields & ?) = ?"
|
||||
+ );
|
||||
+ stmt.bind_uint(0, Geary.ImapDB.Folder.REQUIRED_FTS_FIELDS);
|
||||
+ stmt.bind_uint(1, Geary.ImapDB.Folder.REQUIRED_FTS_FIELDS);
|
||||
+ result = stmt.exec(cancellable);
|
||||
+ while (!result.finished) {
|
||||
+ message_ids.add(result.rowid_at(0));
|
||||
+ result.next(cancellable);
|
||||
+ }
|
||||
+
|
||||
+ return DONE;
|
||||
+ },
|
||||
+ cancellable
|
||||
+ );
|
||||
+
|
||||
+ // Run this in a separate thread since it could be quite a
|
||||
+ // substantial process for large accounts
|
||||
+ yield Nonblocking.Concurrent.global.schedule_async(
|
||||
+ () => {
|
||||
+ foreach (int64 message_id in message_ids) {
|
||||
+ if (!search_ids.contains(message_id)) {
|
||||
+ unindexed_message_ids.add(message_id);
|
||||
+ }
|
||||
+ }
|
||||
+ },
|
||||
+ cancellable
|
||||
+ );
|
||||
+
|
||||
+ debug("%s: Found %d missing messages to populate",
|
||||
+ this.account_information.id,
|
||||
+ unindexed_message_ids.size
|
||||
+ );
|
||||
+
|
||||
+ // Do the actual updating in batches since these require
|
||||
+ // RW transactions
|
||||
+ while (!unindexed_message_ids.is_empty) {
|
||||
+ yield populate_search_table_batch_async(
|
||||
+ 50, unindexed_message_ids, cancellable
|
||||
+ );
|
||||
// With multiple accounts, meaning multiple background threads
|
||||
// doing such CPU- and disk-heavy work, this process can cause
|
||||
// the main thread to slow to a crawl. This delay means the
|
||||
@@ -965,105 +1035,70 @@ private class Geary.ImapDB.Account : BaseObject {
|
||||
yield Geary.Scheduler.sleep_ms_async(50);
|
||||
}
|
||||
} catch (Error e) {
|
||||
- debug("Error populating %s search table: %s", account_information.id, e.message);
|
||||
+ debug("%s: Error populating search table: %s", account_information.id, e.message);
|
||||
}
|
||||
|
||||
debug("%s: Done populating search table", account_information.id);
|
||||
}
|
||||
|
||||
- private static Gee.HashSet<int64?> do_build_rowid_set(Db.Result result, Cancellable? cancellable)
|
||||
- throws Error {
|
||||
- Gee.HashSet<int64?> rowid_set = new Gee.HashSet<int64?>(Collection.int64_hash_func,
|
||||
- Collection.int64_equal_func);
|
||||
- while (!result.finished) {
|
||||
- rowid_set.add(result.rowid_at(0));
|
||||
- result.next(cancellable);
|
||||
- }
|
||||
-
|
||||
- return rowid_set;
|
||||
- }
|
||||
-
|
||||
- private async bool populate_search_table_batch_async(int limit, Cancellable? cancellable)
|
||||
- throws Error {
|
||||
+ private async void populate_search_table_batch_async(
|
||||
+ int limit,
|
||||
+ Gee.HashSet<int64?> unindexed_message_ids,
|
||||
+ GLib.Cancellable? cancellable
|
||||
+ ) throws GLib.Error {
|
||||
check_open();
|
||||
- debug("%s: Searching for up to %d missing indexed messages...", account_information.id,
|
||||
- limit);
|
||||
-
|
||||
- int count = 0, total_unindexed = 0;
|
||||
- yield db.exec_transaction_async(Db.TransactionType.RW, (cx, cancellable) => {
|
||||
- // Embedding a SELECT within a SELECT is painfully slow
|
||||
- // with SQLite, and a LEFT OUTER JOIN will still take in
|
||||
- // the order of seconds, so manually perform the operation
|
||||
|
||||
- Db.Statement stmt = cx.prepare("""
|
||||
- SELECT docid FROM MessageSearchTable
|
||||
- """);
|
||||
- Gee.HashSet<int64?> search_ids = do_build_rowid_set(stmt.exec(cancellable), cancellable);
|
||||
-
|
||||
- stmt = cx.prepare("""
|
||||
- SELECT id FROM MessageTable WHERE (fields & ?) = ?
|
||||
- """);
|
||||
- stmt.bind_uint(0, Geary.ImapDB.Folder.REQUIRED_FTS_FIELDS);
|
||||
- stmt.bind_uint(1, Geary.ImapDB.Folder.REQUIRED_FTS_FIELDS);
|
||||
- Gee.HashSet<int64?> message_ids = do_build_rowid_set(stmt.exec(cancellable), cancellable);
|
||||
-
|
||||
- // This is hard to calculate correctly without doing a
|
||||
- // join (which we should above, but is currently too
|
||||
- // slow), and if we do get it wrong the progress monitor
|
||||
- // will crash and burn, so just something too big to fail
|
||||
- // for now. See Bug 776383.
|
||||
- total_unindexed = message_ids.size;
|
||||
-
|
||||
- // chaff out any MessageTable entries not present in the MessageSearchTable ... since
|
||||
- // we're given a limit, stuff messages req'ing search into separate set and stop when limit
|
||||
- // reached
|
||||
- Gee.HashSet<int64?> unindexed_message_ids = new Gee.HashSet<int64?>(Collection.int64_hash_func,
|
||||
- Collection.int64_equal_func);
|
||||
- foreach (int64 message_id in message_ids) {
|
||||
- if (search_ids.contains(message_id))
|
||||
- continue;
|
||||
-
|
||||
- unindexed_message_ids.add(message_id);
|
||||
- if (unindexed_message_ids.size >= limit)
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- // For all remaining MessageTable rowid's, generate search table entry
|
||||
- foreach (int64 message_id in unindexed_message_ids) {
|
||||
- try {
|
||||
- Geary.Email.Field search_fields = Geary.Email.REQUIRED_FOR_MESSAGE |
|
||||
- Geary.Email.Field.ORIGINATORS | Geary.Email.Field.RECEIVERS |
|
||||
- Geary.Email.Field.SUBJECT;
|
||||
+ uint count = 0;
|
||||
+ var iter = unindexed_message_ids.iterator();
|
||||
+ yield this.db.exec_transaction_async(
|
||||
+ RW,
|
||||
+ (cx, cancellable) => {
|
||||
+ while (iter.has_next() && count < limit) {
|
||||
+ iter.next();
|
||||
+ int64 message_id = iter.get();
|
||||
+ try {
|
||||
+ Email.Field search_fields = (
|
||||
+ Email.REQUIRED_FOR_MESSAGE |
|
||||
+ Email.Field.ORIGINATORS |
|
||||
+ Email.Field.RECEIVERS |
|
||||
+ Email.Field.SUBJECT
|
||||
+ );
|
||||
|
||||
- Geary.Email.Field db_fields;
|
||||
- MessageRow row = Geary.ImapDB.Folder.do_fetch_message_row(
|
||||
- cx, message_id, search_fields, out db_fields, cancellable);
|
||||
- Geary.Email email = row.to_email(new Geary.ImapDB.EmailIdentifier(message_id, null));
|
||||
- Attachment.add_attachments(
|
||||
- cx, this.db.attachments_path, email, message_id, cancellable
|
||||
- );
|
||||
+ Email.Field db_fields;
|
||||
+ MessageRow row = Geary.ImapDB.Folder.do_fetch_message_row(
|
||||
+ cx, message_id, search_fields, out db_fields, cancellable
|
||||
+ );
|
||||
+ Email email = row.to_email(
|
||||
+ new Geary.ImapDB.EmailIdentifier(message_id, null)
|
||||
+ );
|
||||
+ Attachment.add_attachments(
|
||||
+ cx, this.db.attachments_path, email, message_id, cancellable
|
||||
+ );
|
||||
+ Geary.ImapDB.Folder.do_add_email_to_search_table(
|
||||
+ cx, message_id, email, cancellable
|
||||
+ );
|
||||
+ } catch (GLib.Error e) {
|
||||
+ // This is a somewhat serious issue since we rely on
|
||||
+ // there always being a row in the search table for
|
||||
+ // every message.
|
||||
+ warning(
|
||||
+ "Error populating message %s for indexing: %s",
|
||||
+ message_id.to_string(),
|
||||
+ e.message
|
||||
+ );
|
||||
+ }
|
||||
|
||||
- Geary.ImapDB.Folder.do_add_email_to_search_table(cx, message_id, email, cancellable);
|
||||
- } catch (Error e) {
|
||||
- // This is a somewhat serious issue since we rely on
|
||||
- // there always being a row in the search table for
|
||||
- // every message.
|
||||
- warning("Error adding message %s to the search table: %s", message_id.to_string(),
|
||||
- e.message);
|
||||
+ iter.remove();
|
||||
+ ++count;
|
||||
}
|
||||
|
||||
- ++count;
|
||||
- }
|
||||
-
|
||||
- return Db.TransactionOutcome.DONE;
|
||||
+ return COMMIT;
|
||||
}, cancellable);
|
||||
|
||||
if (count > 0) {
|
||||
- debug("%s: Found %d/%d missing indexed messages, %d remaining...",
|
||||
- account_information.id, count, limit, total_unindexed);
|
||||
+ debug("%s: Populated %u missing indexed messages...",
|
||||
+ account_information.id, count);
|
||||
}
|
||||
-
|
||||
- return (count < limit);
|
||||
}
|
||||
|
||||
//
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,41 @@
|
||||
From 17afbca1727cc7780358239c7cafc8de1742bb0c Mon Sep 17 00:00:00 2001
|
||||
From: Julian Sparber <julian@sparber.net>
|
||||
Date: Tue, 20 Oct 2020 12:20:45 +0200
|
||||
Subject: [PATCH 8/8] account-editor: don't show close button for edit/servers
|
||||
pane
|
||||
|
||||
This makes it consistent with the other panes.
|
||||
---
|
||||
ui/accounts_editor_edit_pane.ui | 2 +-
|
||||
ui/accounts_editor_servers_pane.ui | 2 +-
|
||||
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/ui/accounts_editor_edit_pane.ui b/ui/accounts_editor_edit_pane.ui
|
||||
index 33b4a9e8..ce9bcb9a 100644
|
||||
--- a/ui/accounts_editor_edit_pane.ui
|
||||
+++ b/ui/accounts_editor_edit_pane.ui
|
||||
@@ -8,7 +8,7 @@
|
||||
<property name="title" translatable="yes">Edit Account</property>
|
||||
<property name="subtitle" translatable="yes">Account Name</property>
|
||||
<property name="has_subtitle">False</property>
|
||||
- <property name="show_close_button">True</property>
|
||||
+ <property name="show_close_button">False</property>
|
||||
<child>
|
||||
<object class="GtkGrid">
|
||||
<property name="visible">True</property>
|
||||
diff --git a/ui/accounts_editor_servers_pane.ui b/ui/accounts_editor_servers_pane.ui
|
||||
index a01eba5b..77ba674e 100644
|
||||
--- a/ui/accounts_editor_servers_pane.ui
|
||||
+++ b/ui/accounts_editor_servers_pane.ui
|
||||
@@ -7,7 +7,7 @@
|
||||
<property name="can_focus">False</property>
|
||||
<property name="title" translatable="yes">Server Settings</property>
|
||||
<property name="subtitle" translatable="yes">Account Name</property>
|
||||
- <property name="show_close_button">True</property>
|
||||
+ <property name="show_close_button">False</property>
|
||||
<child>
|
||||
<object class="GtkGrid">
|
||||
<property name="visible">True</property>
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,34 @@
|
||||
From 3d8b86dd4e46939dc1a839873a2d049d650d0491 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Sat, 12 Sep 2020 12:02:49 +1000
|
||||
Subject: [PATCH 009/124] Geary.ImapDB.Folder: Drop create/merge batch size
|
||||
down
|
||||
|
||||
We've had reports on Matrix that existing batch transactions in
|
||||
`create_or_merge_email_async` are taking up to 30s to run, which is
|
||||
getting uncomfortably close to the 60s timeout.
|
||||
|
||||
Drop the batch size down from 25 to 10 to reduce the chance that this
|
||||
will eventually fail with a "database is locked" error.
|
||||
|
||||
See #921 for context.
|
||||
---
|
||||
src/engine/imap-db/imap-db-folder.vala | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/engine/imap-db/imap-db-folder.vala b/src/engine/imap-db/imap-db-folder.vala
|
||||
index 4b015cd1..2c2d4015 100644
|
||||
--- a/src/engine/imap-db/imap-db-folder.vala
|
||||
+++ b/src/engine/imap-db/imap-db-folder.vala
|
||||
@@ -40,7 +40,7 @@ private class Geary.ImapDB.Folder : BaseObject, Geary.ReferenceSemantics {
|
||||
private const int LIST_EMAIL_METADATA_COUNT = 100;
|
||||
private const int LIST_EMAIL_FIELDS_CHUNK_COUNT = 500;
|
||||
private const int REMOVE_COMPLETE_LOCATIONS_CHUNK_COUNT = 500;
|
||||
- private const int CREATE_MERGE_EMAIL_CHUNK_COUNT = 25;
|
||||
+ private const int CREATE_MERGE_EMAIL_CHUNK_COUNT = 10;
|
||||
private const int OLD_MSG_DETACH_BATCH_SIZE = 1000;
|
||||
|
||||
// When old messages beyond the period set in the account preferences are removed this number
|
||||
--
|
||||
2.29.2
|
||||
|
405
mail-client/geary/files/0010-Update-Friulian-translation.patch
Normal file
405
mail-client/geary/files/0010-Update-Friulian-translation.patch
Normal file
@ -0,0 +1,405 @@
|
||||
From 56b77cf0d7595c1ccd0846d410a16cb5d5c540b8 Mon Sep 17 00:00:00 2001
|
||||
From: Fabio Tomat <f.t.public@gmail.com>
|
||||
Date: Mon, 14 Sep 2020 19:32:40 +0000
|
||||
Subject: [PATCH 010/124] Update Friulian translation
|
||||
|
||||
---
|
||||
po/fur.po | 103 +++++++++++++++++++++++++++++-------------------------
|
||||
1 file changed, 55 insertions(+), 48 deletions(-)
|
||||
|
||||
diff --git a/po/fur.po b/po/fur.po
|
||||
index f680a065..fd5e3639 100644
|
||||
--- a/po/fur.po
|
||||
+++ b/po/fur.po
|
||||
@@ -7,8 +7,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: geary master\n"
|
||||
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/geary/issues\n"
|
||||
-"POT-Creation-Date: 2020-08-29 01:59+0000\n"
|
||||
-"PO-Revision-Date: 2020-09-08 16:21+0200\n"
|
||||
+"POT-Creation-Date: 2020-09-13 04:23+0000\n"
|
||||
+"PO-Revision-Date: 2020-09-14 21:31+0200\n"
|
||||
"Last-Translator: Fabio Tomat <f.t.public@gmail.com>\n"
|
||||
"Language-Team: Friulian <fur@li.org>\n"
|
||||
"Language: fur\n"
|
||||
@@ -232,6 +232,8 @@ msgid ""
|
||||
"Enables shortcuts for email actions that do not require pressing <Ctrl> to "
|
||||
"emulate those used by Gmail."
|
||||
msgstr ""
|
||||
+"Al abilite lis scurtis pes azions e-mail che no àn bisugne de pression di "
|
||||
+"<Ctrl> par emulâ chês dopradis di Gmail."
|
||||
|
||||
#: desktop/org.gnome.Geary.gschema.xml:82
|
||||
msgid "Languages that shall be used in the spell checker"
|
||||
@@ -242,16 +244,23 @@ msgid ""
|
||||
"A list of POSIX locales, with the empty list disabling spell checking and "
|
||||
"the null list using desktop languages by default."
|
||||
msgstr ""
|
||||
+"Une liste di localizazions POSIX, cuntune liste vueide si disabilite il "
|
||||
+"control ortografic e cuntune liste nule si dopre lis lenghis predefinidis "
|
||||
+"dal scritori."
|
||||
|
||||
#: desktop/org.gnome.Geary.gschema.xml:90
|
||||
msgid "Languages that are displayed in the spell checker popover"
|
||||
msgstr ""
|
||||
+"Lis lenghis che a vegnin mostradis intal ricuadri a comparse dal control "
|
||||
+"ortografic"
|
||||
|
||||
#: desktop/org.gnome.Geary.gschema.xml:91
|
||||
msgid ""
|
||||
"List of languages that are always displayed in the popover of the spell "
|
||||
"checker."
|
||||
msgstr ""
|
||||
+"Liste di lenghis che a vegnin simpri mostradis intal ricuadri a comparse dal "
|
||||
+"control ortografic."
|
||||
|
||||
#: desktop/org.gnome.Geary.gschema.xml:96
|
||||
msgid "Notify of new mail at startup"
|
||||
@@ -285,6 +294,7 @@ msgstr ""
|
||||
msgid ""
|
||||
"Acceptable values are “exact”, “conservative”, “aggressive”, and “horizon”."
|
||||
msgstr ""
|
||||
+"I valôrs ametûts a son “exact”, “conservative”, “aggressive”, e “horizon”."
|
||||
|
||||
#: desktop/org.gnome.Geary.gschema.xml:120
|
||||
msgid "Zoom of conversation viewer"
|
||||
@@ -304,13 +314,15 @@ msgstr "La ultime dimension regjistrade dal barcon dal redatôr distacât."
|
||||
|
||||
#: desktop/org.gnome.Geary.gschema.xml:132
|
||||
msgid "Undo sending email delay"
|
||||
-msgstr ""
|
||||
+msgstr "Anule ritart di spedizion e-mail"
|
||||
|
||||
#: desktop/org.gnome.Geary.gschema.xml:133
|
||||
msgid ""
|
||||
"The number of seconds to wait before sending an email. Set to zero or less "
|
||||
"to disable."
|
||||
msgstr ""
|
||||
+"Il numar di seconts di spietâ prime di inviâ une e-mail. Met a zero o mancul "
|
||||
+"par disabilitâ."
|
||||
|
||||
#: desktop/org.gnome.Geary.gschema.xml:139
|
||||
msgid "Brief notification display time"
|
||||
@@ -320,7 +332,7 @@ msgstr ""
|
||||
msgid ""
|
||||
"The length of time in seconds for which brief notifications should be "
|
||||
"displayed."
|
||||
-msgstr ""
|
||||
+msgstr "La lungjece temporâl in seconts che si à di mostrâ lis notifichis."
|
||||
|
||||
#: desktop/org.gnome.Geary.gschema.xml:146
|
||||
msgid "List of optional plugins"
|
||||
@@ -332,12 +344,13 @@ msgstr "I plugin listâts achì a vignaran cjariâts al inviament."
|
||||
|
||||
#: desktop/org.gnome.Geary.gschema.xml:152
|
||||
msgid "Whether we migrated the old settings"
|
||||
-msgstr ""
|
||||
+msgstr "Indiche se o ven migrât lis impostazions vecjis"
|
||||
|
||||
#: desktop/org.gnome.Geary.gschema.xml:153
|
||||
msgid ""
|
||||
"False to check for the old “org.yorba.geary”-schema and copy its values."
|
||||
msgstr ""
|
||||
+"Fals par controlâ il vecjo scheme “org.yorba.geary” e copiâ i siei valôrs."
|
||||
|
||||
#. Translators: In-app notification label, when
|
||||
#. the app had a problem pinning an otherwise
|
||||
@@ -772,11 +785,11 @@ msgstr "Salve pueste inviade sul servidôr"
|
||||
#: src/client/accounts/accounts-editor-servers-pane.vala:961
|
||||
#, c-format
|
||||
msgid "%s using OAuth2"
|
||||
-msgstr ""
|
||||
+msgstr "%s doprant OAuth2"
|
||||
|
||||
#: src/client/accounts/accounts-editor-servers-pane.vala:971
|
||||
msgid "Use receiving server login"
|
||||
-msgstr ""
|
||||
+msgstr "Dopre acès dal servidôr di ricezion"
|
||||
|
||||
#. Translators: File name used in save chooser when saving
|
||||
#. attachments that do not otherwise have a name.
|
||||
@@ -822,12 +835,12 @@ msgstr "Visite il sît web di Geary"
|
||||
#. / Command line option
|
||||
#: src/client/application/application-client.vala:97
|
||||
msgid "Print debug logging"
|
||||
-msgstr ""
|
||||
+msgstr "Stampe i regjistris di debug"
|
||||
|
||||
#. / Command line option
|
||||
#: src/client/application/application-client.vala:100
|
||||
msgid "Start with the main window hidden (deprecated)"
|
||||
-msgstr ""
|
||||
+msgstr "Partìs cul barcon principâl platât (deplorât)"
|
||||
|
||||
#. / Command line option
|
||||
#: src/client/application/application-client.vala:103
|
||||
@@ -960,13 +973,13 @@ msgstr "Fabio Tomat <f.t.public@gmail.com>, 2020"
|
||||
|
||||
#. / Warning printed to the console when a deprecated
|
||||
#. / command line option is used.
|
||||
-#: src/client/application/application-client.vala:1047
|
||||
+#: src/client/application/application-client.vala:1045
|
||||
msgid "The `--hidden` option is deprecated and will be removed in the future."
|
||||
msgstr "La opzion `--hidden` e je deplorade e un doman e vignarà gjavade."
|
||||
|
||||
#. / Command line warning, string substitution
|
||||
#. / is the given argument
|
||||
-#: src/client/application/application-client.vala:1080
|
||||
+#: src/client/application/application-client.vala:1078
|
||||
#, c-format
|
||||
msgid "Unrecognised program argument: “%s”"
|
||||
msgstr "Argoment di program no ricognossût: “%s”"
|
||||
@@ -1322,7 +1335,7 @@ msgstr "Salve come"
|
||||
|
||||
#: src/client/components/components-inspector.vala:230
|
||||
#: src/client/dialogs/dialogs-problem-details-dialog.vala:224
|
||||
-#: ui/accounts_editor_servers_pane.ui:17
|
||||
+#: ui/accounts_editor_servers_pane.ui:17 ui/composer-headerbar.ui:61
|
||||
msgid "Cancel"
|
||||
msgstr "Anule"
|
||||
|
||||
@@ -2208,10 +2221,8 @@ msgstr "Compile e invie modei di e-mail doprant un sfuei di calcul"
|
||||
#. Translators: Info bar label for starting sending a mail
|
||||
#. merge
|
||||
#: src/client/plugin/mail-merge/mail-merge.vala:118
|
||||
-#, fuzzy
|
||||
-#| msgid "StartTLS"
|
||||
msgid "Start"
|
||||
-msgstr "StartTLS"
|
||||
+msgstr "Scomence"
|
||||
|
||||
#. Translators: Info bar label for pausing sending a mail
|
||||
#. merge
|
||||
@@ -2379,21 +2390,21 @@ msgstr "%A"
|
||||
#. / http://developer.gnome.org/glib/2.32/glib-GDateTime.html#g-date-time-format
|
||||
#: src/client/util/util-date.vala:218
|
||||
msgid "%a, %b %-e, %Y at %l:%M %P"
|
||||
-msgstr ""
|
||||
+msgstr "%a, %-e di %b dal %Y aes %l:%M %P"
|
||||
|
||||
#. / 24 hours format for the datetime that a message being
|
||||
#. / replied to was received See
|
||||
#. / http://developer.gnome.org/glib/2.32/glib-GDateTime.html#g-date-time-format
|
||||
#: src/client/util/util-date.vala:224
|
||||
msgid "%a, %b %-e, %Y at %H:%M"
|
||||
-msgstr ""
|
||||
+msgstr "%a, %-e di %b dal %Y aes %H:%M"
|
||||
|
||||
#. / Format for the datetime that a message being replied to
|
||||
#. / was received See
|
||||
#. / http://developer.gnome.org/glib/2.32/glib-GDateTime.html#g-date-time-format
|
||||
#: src/client/util/util-date.vala:230
|
||||
msgid "%a, %b %-e, %Y at %X"
|
||||
-msgstr ""
|
||||
+msgstr "%a, %-e di %b dal %Y aes %X"
|
||||
|
||||
#. Translators: Label used when an email has a missing or
|
||||
#. an empty subject
|
||||
@@ -2426,7 +2437,7 @@ msgstr[1] "%s e altris %d"
|
||||
#: src/client/util/util-email.vala:193
|
||||
#, c-format
|
||||
msgid "On %1$s, %2$s wrote:"
|
||||
-msgstr ""
|
||||
+msgstr "Ai %1$s, %2$s al/e à scrit:"
|
||||
|
||||
#. / The quoted header for a message being replied to (in case the date is not known).
|
||||
#. / %s will be replaced by the original sender.
|
||||
@@ -2721,7 +2732,6 @@ msgstr ""
|
||||
#. put the most common localized name to the front for the
|
||||
#. default. English names do not need to be included.
|
||||
#: src/engine/imap-engine/imap-engine-generic-account.vala:1030
|
||||
-#, fuzzy
|
||||
msgid "Trash | Rubbish | Rubbish Bin"
|
||||
msgstr "Scovacere | Refudum | Bidon"
|
||||
|
||||
@@ -2811,7 +2821,7 @@ msgstr "Account"
|
||||
|
||||
#: ui/accounts_editor_list_pane.ui:62
|
||||
msgid "To get started, select an email provider below."
|
||||
-msgstr ""
|
||||
+msgstr "Par scomençâ, selezione un furnidôr di e-mail chi sot."
|
||||
|
||||
#: ui/accounts_editor_list_pane.ui:75
|
||||
msgid "Welcome to Geary"
|
||||
@@ -2855,27 +2865,27 @@ msgstr "_No sta fidâti di chest servidôr"
|
||||
|
||||
#: ui/composer-editor.ui:100
|
||||
msgid "Bold text"
|
||||
-msgstr ""
|
||||
+msgstr "Test neret"
|
||||
|
||||
#: ui/composer-editor.ui:124
|
||||
msgid "Italic text"
|
||||
-msgstr ""
|
||||
+msgstr "Test corsîf"
|
||||
|
||||
#: ui/composer-editor.ui:148
|
||||
msgid "Underline text"
|
||||
-msgstr ""
|
||||
+msgstr "Test sotlineât"
|
||||
|
||||
#: ui/composer-editor.ui:172
|
||||
msgid "Strikethrough text"
|
||||
-msgstr ""
|
||||
+msgstr "Test stricât"
|
||||
|
||||
#: ui/composer-editor.ui:205
|
||||
msgid "Insert bulleted list"
|
||||
-msgstr ""
|
||||
+msgstr "Inserìs liste pontade"
|
||||
|
||||
#: ui/composer-editor.ui:229
|
||||
msgid "Insert numbered list"
|
||||
-msgstr ""
|
||||
+msgstr "Inserìs liste numerade"
|
||||
|
||||
#: ui/composer-editor.ui:262
|
||||
msgid "Indent or quote text"
|
||||
@@ -2887,7 +2897,7 @@ msgstr ""
|
||||
|
||||
#: ui/composer-editor.ui:315
|
||||
msgid "Remove text formatting"
|
||||
-msgstr ""
|
||||
+msgstr "Gjave formatazion dal test"
|
||||
|
||||
#: ui/composer-editor.ui:334
|
||||
msgid "Change font type"
|
||||
@@ -2915,7 +2925,7 @@ msgstr "Cambie dimension dal caratar"
|
||||
|
||||
#: ui/composer-editor.ui:447
|
||||
msgid "Insert or update text link"
|
||||
-msgstr ""
|
||||
+msgstr "Inserìs o inzorne il colegament dal test"
|
||||
|
||||
#: ui/composer-editor.ui:471
|
||||
msgid "Insert an image"
|
||||
@@ -3034,7 +3044,7 @@ msgstr "Salve e siere"
|
||||
#. Note that this button and the Update button will never be shown at the same time to the user.
|
||||
#: ui/composer-link-popover.ui:42
|
||||
msgid "Insert the new link with this URL"
|
||||
-msgstr ""
|
||||
+msgstr "Inserìs il gnûf colegament cun chest URL"
|
||||
|
||||
#: ui/composer-link-popover.ui:43
|
||||
msgid "Add"
|
||||
@@ -3047,7 +3057,7 @@ msgstr "URL colegament"
|
||||
#. Note that this button and the Insert button will never be shown at the same time to the user.
|
||||
#: ui/composer-link-popover.ui:61
|
||||
msgid "Update this link’s URL"
|
||||
-msgstr ""
|
||||
+msgstr "Inzorne chest URL dal link"
|
||||
|
||||
#: ui/composer-link-popover.ui:62
|
||||
msgid "Update"
|
||||
@@ -3127,7 +3137,7 @@ msgstr "Detais:"
|
||||
#. Tooltip for problem report button
|
||||
#: ui/components-inspector.ui:19 ui/problem-details-dialog.ui:24
|
||||
msgid "Search for matching log entries"
|
||||
-msgstr ""
|
||||
+msgstr "Cîr vôs di regjistri corispondentis"
|
||||
|
||||
#. Tooltip for inspector button
|
||||
#: ui/components-inspector.ui:35
|
||||
@@ -3143,7 +3153,7 @@ msgstr ""
|
||||
#. Tooltip for problem report button
|
||||
#: ui/components-inspector.ui:81 ui/problem-details-dialog.ui:51
|
||||
msgid "Save logs entries and details"
|
||||
-msgstr ""
|
||||
+msgstr "Salve vôs dai regjistris e detais"
|
||||
|
||||
#. Tooltip for inspector button
|
||||
#. Tooltip for problem report button
|
||||
@@ -3182,10 +3192,8 @@ msgstr "Cjarie simpri lis imagjins rimotis"
|
||||
|
||||
#. Title label on contact popover
|
||||
#: ui/conversation-contact-popover.ui:264
|
||||
-#, fuzzy
|
||||
-#| msgid "Email address"
|
||||
msgid "Deceptive email address"
|
||||
-msgstr "Direzion e-mail"
|
||||
+msgstr "Direzion e-mail ingjanose"
|
||||
|
||||
#. Contact popover label
|
||||
#: ui/conversation-contact-popover.ui:294
|
||||
@@ -3245,7 +3253,6 @@ msgstr "Sposte messaç te _Scovacere"
|
||||
|
||||
#. Translators: Menu item to delete a single, specific message
|
||||
#: ui/conversation-email-menus.ui:57
|
||||
-#| msgid "Autoselect next message"
|
||||
msgid "_Delete message…"
|
||||
msgstr "_Elimine messaç…"
|
||||
|
||||
@@ -3256,23 +3263,23 @@ msgstr "_Viôt sorzint"
|
||||
|
||||
#: ui/conversation-message-link-popover.ui:54
|
||||
msgid "But actually goes to:"
|
||||
-msgstr ""
|
||||
+msgstr "Ma invezit al va su:"
|
||||
|
||||
#: ui/conversation-message-link-popover.ui:84
|
||||
msgid "The link appears to go to:"
|
||||
-msgstr ""
|
||||
+msgstr "Al semee che il colegament al ledi su:"
|
||||
|
||||
#: ui/conversation-message-link-popover.ui:96
|
||||
msgid "Deceptive link found"
|
||||
-msgstr ""
|
||||
+msgstr "Colegament ingjanôs cjatât"
|
||||
|
||||
#: ui/conversation-message-link-popover.ui:111
|
||||
msgid "The email sender may be leading you to the wrong web site."
|
||||
-msgstr ""
|
||||
+msgstr "Il mitent de e-mail al podarès puartâti su sîts web sbaliâts."
|
||||
|
||||
#: ui/conversation-message-link-popover.ui:124
|
||||
msgid "If unsure, contact the sender and ask before continuing."
|
||||
-msgstr ""
|
||||
+msgstr "Se no si è sigûrs, contatâ il mitent e domandâ prime di continuâ."
|
||||
|
||||
#: ui/conversation-message-menus.ui:7
|
||||
msgid "_Open Link"
|
||||
@@ -3611,27 +3618,27 @@ msgstr "Modifiche cun test formatât"
|
||||
#: ui/gtk/help-overlay.ui:468
|
||||
msgctxt "shortcut window"
|
||||
msgid "Paste without formatting"
|
||||
-msgstr ""
|
||||
+msgstr "Tache cence formatazion"
|
||||
|
||||
#: ui/gtk/help-overlay.ui:475
|
||||
msgctxt "shortcut window"
|
||||
msgid "Bold text"
|
||||
-msgstr ""
|
||||
+msgstr "Met test in neret"
|
||||
|
||||
#: ui/gtk/help-overlay.ui:482
|
||||
msgctxt "shortcut window"
|
||||
msgid "Italicize text"
|
||||
-msgstr ""
|
||||
+msgstr "Met test in corsîf"
|
||||
|
||||
#: ui/gtk/help-overlay.ui:489
|
||||
msgctxt "shortcut window"
|
||||
msgid "Underline text"
|
||||
-msgstr ""
|
||||
+msgstr "Sotlinie il test"
|
||||
|
||||
#: ui/gtk/help-overlay.ui:496
|
||||
msgctxt "shortcut window"
|
||||
msgid "Strike text"
|
||||
-msgstr ""
|
||||
+msgstr "Striche il test"
|
||||
|
||||
#: ui/gtk/help-overlay.ui:503
|
||||
msgctxt "shortcut window"
|
||||
@@ -3711,7 +3718,7 @@ msgstr "_Autentiche"
|
||||
|
||||
#: ui/upgrade_dialog.glade:60
|
||||
msgid "Geary update in progress…"
|
||||
-msgstr ""
|
||||
+msgstr "Inzornament di Geary in vore…"
|
||||
|
||||
#~ msgid "mail-send"
|
||||
#~ msgstr "mail-send"
|
||||
--
|
||||
2.29.2
|
||||
|
180
mail-client/geary/files/0011-Update-Friulian-translation.patch
Normal file
180
mail-client/geary/files/0011-Update-Friulian-translation.patch
Normal file
@ -0,0 +1,180 @@
|
||||
From 4a4e6a6992fc1349fd532ad35b0c787992024162 Mon Sep 17 00:00:00 2001
|
||||
From: Fabio Tomat <f.t.public@gmail.com>
|
||||
Date: Tue, 15 Sep 2020 05:20:06 +0000
|
||||
Subject: [PATCH 011/124] Update Friulian translation
|
||||
|
||||
---
|
||||
po/fur.po | 46 +++++++++++++++++++++++-----------------------
|
||||
1 file changed, 23 insertions(+), 23 deletions(-)
|
||||
|
||||
diff --git a/po/fur.po b/po/fur.po
|
||||
index fd5e3639..1db111d0 100644
|
||||
--- a/po/fur.po
|
||||
+++ b/po/fur.po
|
||||
@@ -7,8 +7,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: geary master\n"
|
||||
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/geary/issues\n"
|
||||
-"POT-Creation-Date: 2020-09-13 04:23+0000\n"
|
||||
-"PO-Revision-Date: 2020-09-14 21:31+0200\n"
|
||||
+"POT-Creation-Date: 2020-09-14 19:33+0000\n"
|
||||
+"PO-Revision-Date: 2020-09-15 07:19+0200\n"
|
||||
"Last-Translator: Fabio Tomat <f.t.public@gmail.com>\n"
|
||||
"Language-Team: Friulian <fur@li.org>\n"
|
||||
"Language: fur\n"
|
||||
@@ -288,7 +288,7 @@ msgstr "Vêr par scrivi lis e-mail in HTML; fals pal test sempliç."
|
||||
|
||||
#: desktop/org.gnome.Geary.gschema.xml:114
|
||||
msgid "Advisory strategy for full-text searching"
|
||||
-msgstr ""
|
||||
+msgstr "Strategjie consultive pe ricercje di tescj complets"
|
||||
|
||||
#: desktop/org.gnome.Geary.gschema.xml:115
|
||||
msgid ""
|
||||
@@ -326,7 +326,7 @@ msgstr ""
|
||||
|
||||
#: desktop/org.gnome.Geary.gschema.xml:139
|
||||
msgid "Brief notification display time"
|
||||
-msgstr ""
|
||||
+msgstr "Timp di visualizazion des notifichis"
|
||||
|
||||
#: desktop/org.gnome.Geary.gschema.xml:140
|
||||
msgid ""
|
||||
@@ -580,7 +580,7 @@ msgstr "Discjarie pueste"
|
||||
#: src/client/accounts/accounts-editor-edit-pane.vala:822
|
||||
#, c-format
|
||||
msgid "Change download period back to: %s"
|
||||
-msgstr ""
|
||||
+msgstr "Tornâ al precedent periodi di discjariament: %s"
|
||||
|
||||
#: src/client/accounts/accounts-editor-edit-pane.vala:843
|
||||
msgid "Everything"
|
||||
@@ -850,18 +850,18 @@ msgstr "Abilite l'ispetôr WebKitGTK intes viodudis web"
|
||||
#. / Command line option
|
||||
#: src/client/application/application-client.vala:106
|
||||
msgid "Log conversation monitoring"
|
||||
-msgstr ""
|
||||
+msgstr "Regjistre il monitorament des conversazions"
|
||||
|
||||
#. / Command line option
|
||||
#: src/client/application/application-client.vala:109
|
||||
msgid "Log IMAP network deserialization"
|
||||
-msgstr ""
|
||||
+msgstr "Regjistre la deserializazion de rêt IMAP"
|
||||
|
||||
#. / Command line option. "Normalization" can also be called
|
||||
#. / "synchronization".
|
||||
#: src/client/application/application-client.vala:113
|
||||
msgid "Log folder normalization"
|
||||
-msgstr ""
|
||||
+msgstr "Regjistre la sincronizazion de cartele"
|
||||
|
||||
#. / Command line option
|
||||
#: src/client/application/application-client.vala:116
|
||||
@@ -873,7 +873,7 @@ msgstr "Regjistre ativitât di rêt IMAP"
|
||||
#. / also be called the IMAP events queue.
|
||||
#: src/client/application/application-client.vala:121
|
||||
msgid "Log IMAP replay queue"
|
||||
-msgstr ""
|
||||
+msgstr "Regjistre la code di events IMAP"
|
||||
|
||||
#. / Command line option
|
||||
#: src/client/application/application-client.vala:124
|
||||
@@ -897,10 +897,8 @@ msgstr "Vierç un gnûf barcon"
|
||||
|
||||
#. / Command line option
|
||||
#: src/client/application/application-client.vala:135
|
||||
-#, fuzzy
|
||||
-#| msgid "Failed to store certificate"
|
||||
msgid "Revoke all pinned TLS server certificates"
|
||||
-msgstr "No si è rivâts a archiviâ il certificât"
|
||||
+msgstr "Revoche ducj i certificâts di servidôr TLS fissâts"
|
||||
|
||||
#. / Command line option
|
||||
#: src/client/application/application-client.vala:138
|
||||
@@ -2268,10 +2266,8 @@ msgid "Messaging Menu"
|
||||
msgstr "Menù di messaç"
|
||||
|
||||
#: src/client/plugin/messaging-menu/messaging-menu.plugin.desktop.in:5
|
||||
-#, fuzzy
|
||||
-#| msgid "Show notifications for new mail"
|
||||
msgid "Displays Unity Messaging Menu notifications for new email"
|
||||
-msgstr "Mostre lis notifichis pe gnove pueste"
|
||||
+msgstr "Al mostre lis notifichis di gnove pueste tal menù dai messaçs di Unity"
|
||||
|
||||
#: src/client/plugin/messaging-menu/messaging-menu.vala:79
|
||||
#, c-format
|
||||
@@ -2838,6 +2834,8 @@ msgid ""
|
||||
"Removing an account will remove it from Geary and delete locally cached "
|
||||
"email data from your computer, but not from your service provider."
|
||||
msgstr ""
|
||||
+"Gjavant un account si lu gjavarà di Geary e si eliminarà dal computer i dâts "
|
||||
+"e-mail te cache locâl, ma no dal gjestôr/furnidôr dal servizi."
|
||||
|
||||
#: ui/accounts_editor_remove_pane.ui:122
|
||||
msgid "Remove account"
|
||||
@@ -2889,11 +2887,11 @@ msgstr "Inserìs liste numerade"
|
||||
|
||||
#: ui/composer-editor.ui:262
|
||||
msgid "Indent or quote text"
|
||||
-msgstr ""
|
||||
+msgstr "Indentâ o citâ test"
|
||||
|
||||
#: ui/composer-editor.ui:286
|
||||
msgid "Un-indent or unquote text"
|
||||
-msgstr ""
|
||||
+msgstr "Gjavâ la indintidure o la citazion dal test"
|
||||
|
||||
#: ui/composer-editor.ui:315
|
||||
msgid "Remove text formatting"
|
||||
@@ -3128,6 +3126,10 @@ msgid ""
|
||||
"channels</a> or attach to a <a href=\"https://wiki.gnome.org/Apps/Geary/"
|
||||
"ReportingABug\">new bug report</a>."
|
||||
msgstr ""
|
||||
+"Se il probleme al è grivi o al persist, salve e invie chescj detais a un dai "
|
||||
+"<a href=\"https://wiki.gnome.org/Apps/Geary/Contact\">canâi di contat</a> o "
|
||||
+"zonte suntune <a href=\"https://wiki.gnome.org/Apps/Geary/ReportingABug"
|
||||
+"\">gnove segnalazion di erôr</a>."
|
||||
|
||||
#: ui/components-inspector-error-view.ui:47
|
||||
msgid "Details:"
|
||||
@@ -3142,12 +3144,12 @@ msgstr "Cîr vôs di regjistri corispondentis"
|
||||
#. Tooltip for inspector button
|
||||
#: ui/components-inspector.ui:35
|
||||
msgid "Toggle appending new log entries"
|
||||
-msgstr ""
|
||||
+msgstr "Ativâ/disativâ la zonte di gnovis vôs di regjistri"
|
||||
|
||||
#. Tooltip for inspector button
|
||||
#: ui/components-inspector.ui:55
|
||||
msgid "Add a marker entry to the log"
|
||||
-msgstr ""
|
||||
+msgstr "Zonte une vôs-marcadôr al regjistri"
|
||||
|
||||
#. Tooltip for inspector button
|
||||
#. Tooltip for problem report button
|
||||
@@ -3423,7 +3425,7 @@ msgstr "Bute vie conversazions"
|
||||
#: ui/gtk/help-overlay.ui:87 ui/gtk/help-overlay.ui:340
|
||||
msgctxt "shortcut window"
|
||||
msgid "Junk conversations"
|
||||
-msgstr ""
|
||||
+msgstr "Conversazions malvoludis"
|
||||
|
||||
#: ui/gtk/help-overlay.ui:95 ui/gtk/help-overlay.ui:347
|
||||
msgctxt "shortcut window"
|
||||
@@ -3526,11 +3528,9 @@ msgid "Select next/previous conversation"
|
||||
msgstr "Selezione la prossime/precedente conversazion"
|
||||
|
||||
#: ui/gtk/help-overlay.ui:248
|
||||
-#, fuzzy
|
||||
-#| msgid "Autoselect next message"
|
||||
msgctxt "shortcut window"
|
||||
msgid "Focus next/previous message"
|
||||
-msgstr "Selezione in automatic il prossim messaç"
|
||||
+msgstr "Met a fûc (il stât atîf) il prossim/precedent messaç"
|
||||
|
||||
#: ui/gtk/help-overlay.ui:260
|
||||
msgid "Single-key Shortcuts"
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,34 @@
|
||||
From acabdc9e73e7a6e23f14540ac2485783161eecc4 Mon Sep 17 00:00:00 2001
|
||||
From: Fabio Tomat <f.t.public@gmail.com>
|
||||
Date: Tue, 15 Sep 2020 05:52:24 +0000
|
||||
Subject: [PATCH 012/124] Update Friulian translation
|
||||
|
||||
---
|
||||
po/fur.po | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/po/fur.po b/po/fur.po
|
||||
index 1db111d0..d13465ba 100644
|
||||
--- a/po/fur.po
|
||||
+++ b/po/fur.po
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Project-Id-Version: geary master\n"
|
||||
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/geary/issues\n"
|
||||
"POT-Creation-Date: 2020-09-14 19:33+0000\n"
|
||||
-"PO-Revision-Date: 2020-09-15 07:19+0200\n"
|
||||
+"PO-Revision-Date: 2020-09-15 07:51+0200\n"
|
||||
"Last-Translator: Fabio Tomat <f.t.public@gmail.com>\n"
|
||||
"Language-Team: Friulian <fur@li.org>\n"
|
||||
"Language: fur\n"
|
||||
@@ -2491,7 +2491,7 @@ msgstr "Inviade"
|
||||
|
||||
#: src/client/util/util-i18n.vala:280
|
||||
msgid "Starred"
|
||||
-msgstr "Preferidis"
|
||||
+msgstr "Preferide"
|
||||
|
||||
#: src/client/util/util-i18n.vala:283
|
||||
msgid "Important"
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,34 @@
|
||||
From e957f0f8a7310950d36837b9945a09ad7a97e63c Mon Sep 17 00:00:00 2001
|
||||
From: Fabio Tomat <f.t.public@gmail.com>
|
||||
Date: Tue, 15 Sep 2020 06:56:54 +0000
|
||||
Subject: [PATCH 013/124] Update Friulian translation
|
||||
|
||||
---
|
||||
po/fur.po | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/po/fur.po b/po/fur.po
|
||||
index d13465ba..b5e17eec 100644
|
||||
--- a/po/fur.po
|
||||
+++ b/po/fur.po
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Project-Id-Version: geary master\n"
|
||||
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/geary/issues\n"
|
||||
"POT-Creation-Date: 2020-09-14 19:33+0000\n"
|
||||
-"PO-Revision-Date: 2020-09-15 07:51+0200\n"
|
||||
+"PO-Revision-Date: 2020-09-15 08:56+0200\n"
|
||||
"Last-Translator: Fabio Tomat <f.t.public@gmail.com>\n"
|
||||
"Language-Team: Friulian <fur@li.org>\n"
|
||||
"Language: fur\n"
|
||||
@@ -1181,7 +1181,7 @@ msgstr "Si lavore fûr rêt"
|
||||
#: src/client/application/application-main-window.vala:542
|
||||
msgid "You will not be able to send or receive email until re-connected."
|
||||
msgstr ""
|
||||
-"No tu podarâs inviâ o ricevi e-mail fintremai che no tu tornarâs a coneti."
|
||||
+"No tu podarâs inviâ o ricevi e-mail fintremai che no tu ti tornarâs a coneti."
|
||||
|
||||
#. Translators: An info bar status label
|
||||
#: src/client/application/application-main-window.vala:549
|
||||
--
|
||||
2.29.2
|
||||
|
3505
mail-client/geary/files/0014-Update-Croatian-translation.patch
Normal file
3505
mail-client/geary/files/0014-Update-Croatian-translation.patch
Normal file
File diff suppressed because it is too large
Load Diff
2893
mail-client/geary/files/0015-Update-Croatian-translation.patch
Normal file
2893
mail-client/geary/files/0015-Update-Croatian-translation.patch
Normal file
File diff suppressed because it is too large
Load Diff
3209
mail-client/geary/files/0016-Update-Slovak-translation.patch
Normal file
3209
mail-client/geary/files/0016-Update-Slovak-translation.patch
Normal file
File diff suppressed because it is too large
Load Diff
276
mail-client/geary/files/0017-Update-Slovak-translation.patch
Normal file
276
mail-client/geary/files/0017-Update-Slovak-translation.patch
Normal file
@ -0,0 +1,276 @@
|
||||
From 5942e30377f7e47abe60236ceac100384bf74add Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Du=C5=A1an=20Kazik?= <prescott66@gmail.com>
|
||||
Date: Mon, 21 Sep 2020 11:52:17 +0000
|
||||
Subject: [PATCH 017/124] Update Slovak translation
|
||||
|
||||
(cherry picked from commit 2028c9dea3f1d8f6c5dcfdd44f5f1990121e0983)
|
||||
---
|
||||
po/sk.po | 71 ++++++++++++++++++++++++++------------------------------
|
||||
1 file changed, 33 insertions(+), 38 deletions(-)
|
||||
|
||||
diff --git a/po/sk.po b/po/sk.po
|
||||
index 8fc3e1f4..dc0138c2 100644
|
||||
--- a/po/sk.po
|
||||
+++ b/po/sk.po
|
||||
@@ -10,8 +10,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: geary-0.4.1\n"
|
||||
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/geary/issues\n"
|
||||
-"POT-Creation-Date: 2020-08-29 01:59+0000\n"
|
||||
-"PO-Revision-Date: 2020-09-16 13:28+0200\n"
|
||||
+"POT-Creation-Date: 2020-09-19 08:49+0000\n"
|
||||
+"PO-Revision-Date: 2020-09-21 13:51+0200\n"
|
||||
"Last-Translator: Dušan Kazik <prescott66@gmail.com>\n"
|
||||
"Language-Team: Slovak <gnome-sk-list@gnome.org>\n"
|
||||
"Language: sk\n"
|
||||
@@ -212,6 +212,8 @@ msgstr "Automaticky vybrať ďalšiu správu"
|
||||
#: desktop/org.gnome.Geary.gschema.xml:63
|
||||
msgid "True if we should autoselect the next available conversation."
|
||||
msgstr ""
|
||||
+"Nastavte na True, ak by sme mali automaticky vybrať nasledujúci dostupný "
|
||||
+"rozhovor."
|
||||
|
||||
#: desktop/org.gnome.Geary.gschema.xml:68
|
||||
msgid "Display message previews"
|
||||
@@ -219,7 +221,7 @@ msgstr "Zobraziť náhľady správ"
|
||||
|
||||
#: desktop/org.gnome.Geary.gschema.xml:69
|
||||
msgid "True if we should display a short preview of each message."
|
||||
-msgstr ""
|
||||
+msgstr "Nastavte na True, ak by sme mali zobraziť krátky náhľad každej správy."
|
||||
|
||||
#: desktop/org.gnome.Geary.gschema.xml:74
|
||||
msgid "Use single key shortcuts"
|
||||
@@ -261,7 +263,7 @@ msgstr "Nastavením na True, bude oznamovaná nová pošta po spustení."
|
||||
|
||||
#: desktop/org.gnome.Geary.gschema.xml:102
|
||||
msgid "Ask when opening an attachment"
|
||||
-msgstr ""
|
||||
+msgstr "Opýtať sa pri otváraní prílohy"
|
||||
|
||||
#: desktop/org.gnome.Geary.gschema.xml:103
|
||||
msgid "True to ask when opening an attachment."
|
||||
@@ -290,7 +292,7 @@ msgstr "Priblíženie prehliadača konverzácií"
|
||||
|
||||
#: desktop/org.gnome.Geary.gschema.xml:121
|
||||
msgid "The zoom to apply on the conservation view."
|
||||
-msgstr ""
|
||||
+msgstr "Priblíženie, ktoré sa má použiť pre zobrazenie rozhovorov."
|
||||
|
||||
#: desktop/org.gnome.Geary.gschema.xml:126
|
||||
msgid "Size of detached composer window"
|
||||
@@ -298,7 +300,7 @@ msgstr "Veľkosť odpojeného okna tvorcu správ"
|
||||
|
||||
#: desktop/org.gnome.Geary.gschema.xml:127
|
||||
msgid "The last recorded size of the detached composer window."
|
||||
-msgstr ""
|
||||
+msgstr "Posledná zaznamenaná veľkosť odpojeného okna tvorcu správ."
|
||||
|
||||
#: desktop/org.gnome.Geary.gschema.xml:132
|
||||
msgid "Undo sending email delay"
|
||||
@@ -314,13 +316,15 @@ msgstr ""
|
||||
|
||||
#: desktop/org.gnome.Geary.gschema.xml:139
|
||||
msgid "Brief notification display time"
|
||||
-msgstr ""
|
||||
+msgstr "Doba zobrazenia stručného oznámenia"
|
||||
|
||||
#: desktop/org.gnome.Geary.gschema.xml:140
|
||||
msgid ""
|
||||
"The length of time in seconds for which brief notifications should be "
|
||||
"displayed."
|
||||
msgstr ""
|
||||
+"Dĺžka trvania v sekundách, počas ktorého by mali byť zobrazované stručné "
|
||||
+"oznámenia."
|
||||
|
||||
#: desktop/org.gnome.Geary.gschema.xml:146
|
||||
msgid "List of optional plugins"
|
||||
@@ -958,13 +962,13 @@ msgstr "Dušan Kazik <prescott66@gmail.com>"
|
||||
|
||||
#. / Warning printed to the console when a deprecated
|
||||
#. / command line option is used.
|
||||
-#: src/client/application/application-client.vala:1047
|
||||
+#: src/client/application/application-client.vala:1045
|
||||
msgid "The `--hidden` option is deprecated and will be removed in the future."
|
||||
msgstr "Voľba „--hidden“ je zastaraná a bude v budúcnosti odstránená."
|
||||
|
||||
#. / Command line warning, string substitution
|
||||
#. / is the given argument
|
||||
-#: src/client/application/application-client.vala:1080
|
||||
+#: src/client/application/application-client.vala:1078
|
||||
#, c-format
|
||||
msgid "Unrecognised program argument: “%s”"
|
||||
msgstr "Nerozpoznaný parameter programu: „%s“"
|
||||
@@ -1140,21 +1144,21 @@ msgstr ""
|
||||
#: src/client/application/application-controller.vala:1501
|
||||
#, c-format
|
||||
msgid "Email sent to %s"
|
||||
-msgstr "Email pre %s bol odoslaný"
|
||||
+msgstr "Email pre príjemcu %s bol odoslaný"
|
||||
|
||||
#. / Translators: The label for an in-app notification. The
|
||||
#. / string substitution is a list of recipients of the email.
|
||||
#: src/client/application/application-controller.vala:2491
|
||||
#, c-format
|
||||
msgid "Email to %s queued for delivery"
|
||||
-msgstr "Email pre %s bol zaradený do fronty na doručenie"
|
||||
+msgstr "Email pre príjemcu %s bol zaradený do fronty na doručenie"
|
||||
|
||||
#. / Translators: The label for an in-app notification. The
|
||||
#. / string substitution is a list of recipients of the email.
|
||||
#: src/client/application/application-controller.vala:2555
|
||||
#, c-format
|
||||
msgid "Email to %s saved"
|
||||
-msgstr "Email pre %s bol uložený"
|
||||
+msgstr "Email pre príjemcu %s bol uložený"
|
||||
|
||||
#. / Translators: A label for an in-app notification.
|
||||
#: src/client/application/application-controller.vala:2570
|
||||
@@ -1167,7 +1171,7 @@ msgstr "Nepodarilo sa obnoviť tvorcu správ"
|
||||
#: src/client/application/application-controller.vala:2613
|
||||
#, c-format
|
||||
msgid "Email to %s discarded"
|
||||
-msgstr "Email pre %s bol zahodený"
|
||||
+msgstr "Email pre príjemcu %s bol zahodený"
|
||||
|
||||
#. Translators: An info bar status label
|
||||
#: src/client/application/application-main-window.vala:540
|
||||
@@ -1334,7 +1338,7 @@ msgstr "Uložiť ako"
|
||||
|
||||
#: src/client/components/components-inspector.vala:230
|
||||
#: src/client/dialogs/dialogs-problem-details-dialog.vala:224
|
||||
-#: ui/accounts_editor_servers_pane.ui:17
|
||||
+#: ui/accounts_editor_servers_pane.ui:17 ui/composer-headerbar.ui:61
|
||||
msgid "Cancel"
|
||||
msgstr "Zrušiť"
|
||||
|
||||
@@ -2185,7 +2189,6 @@ msgstr "Vytvára opakovane použiteľné šablóny na odosielanie emailov"
|
||||
#. included.
|
||||
#: src/client/plugin/email-templates/email-templates.vala:29
|
||||
#: src/client/plugin/mail-merge/mail-merge.vala:29
|
||||
-#| msgid "Sent | Sent Mail | Sent Email | Sent E-Mail"
|
||||
msgid "Templates | Template Mail | Template Email | Template E-Mail"
|
||||
msgstr "Šablóny | Poštová šablóna | Šablóna emailu | Šablóna e-mailu"
|
||||
|
||||
@@ -2195,11 +2198,12 @@ msgstr "Šablóny | Poštová šablóna | Šablóna emailu | Šablóna e-mailu"
|
||||
msgid "Templates"
|
||||
msgstr "Šablóny"
|
||||
|
||||
+# DK: šablóna
|
||||
#. Translators: Info bar button label for creating a
|
||||
#. new email template
|
||||
#: src/client/plugin/email-templates/email-templates.vala:282
|
||||
msgid "New"
|
||||
-msgstr "Nový"
|
||||
+msgstr "Nová"
|
||||
|
||||
#. Translators: Infobar status label for an email template
|
||||
#: src/client/plugin/email-templates/email-templates.vala:293
|
||||
@@ -2233,11 +2237,11 @@ msgstr "Upraviť"
|
||||
#: src/client/plugin/mail-merge/mail-merge.vala:389
|
||||
#: src/client/plugin/mail-merge/mail-merge.vala:488
|
||||
msgid "Mail Merge"
|
||||
-msgstr ""
|
||||
+msgstr "Zlúčenie pošty"
|
||||
|
||||
#: src/client/plugin/mail-merge/mail-merge.plugin.desktop.in:6
|
||||
msgid "Fill in and send email templates using a spreadsheet"
|
||||
-msgstr ""
|
||||
+msgstr "Vyplní šablóny emailov na odoslanie pomocou tabuľkového súboru"
|
||||
|
||||
#. Translators: Info bar label for starting sending a mail
|
||||
#. merge
|
||||
@@ -2258,21 +2262,21 @@ msgstr "Pozastaviť"
|
||||
#, c-format
|
||||
msgid "Sent %u of %u"
|
||||
msgid_plural "Sent %u of %u"
|
||||
-msgstr[0] ""
|
||||
-msgstr[1] ""
|
||||
-msgstr[2] ""
|
||||
+msgstr[0] "Odoslaných %u emailov z %u"
|
||||
+msgstr[1] "Odoslaný %u email z %u"
|
||||
+msgstr[2] "Odoslané %u emaily z %u"
|
||||
|
||||
#. Translators: Infobar status label for an email mail merge
|
||||
#. template
|
||||
#: src/client/plugin/mail-merge/mail-merge.vala:324
|
||||
msgid "Mail merge template"
|
||||
-msgstr ""
|
||||
+msgstr "Šablóna pre zlúčenie pošty"
|
||||
|
||||
#. Translators: Info bar button label for performing a
|
||||
#. mail-merge on an email template
|
||||
#: src/client/plugin/mail-merge/mail-merge.vala:328
|
||||
msgid "Merge"
|
||||
-msgstr ""
|
||||
+msgstr "Zlúčiť"
|
||||
|
||||
#. / Translators: Action bar menu button label for
|
||||
#. / mail-merge plugin
|
||||
@@ -2290,10 +2294,8 @@ msgid "Messaging Menu"
|
||||
msgstr "Ponuka správ"
|
||||
|
||||
#: src/client/plugin/messaging-menu/messaging-menu.plugin.desktop.in:5
|
||||
-#, fuzzy
|
||||
-#| msgid "Show notifications for new mail"
|
||||
msgid "Displays Unity Messaging Menu notifications for new email"
|
||||
-msgstr "Zobraziť upozornenia pre novú poštu"
|
||||
+msgstr "Zobrazí oznámenia pre novú poštu v ponuke správ prostredia Unity"
|
||||
|
||||
#: src/client/plugin/messaging-menu/messaging-menu.vala:79
|
||||
#, c-format
|
||||
@@ -2301,14 +2303,12 @@ msgid "%s — New Messages"
|
||||
msgstr "%s — Nové správy"
|
||||
|
||||
#: src/client/plugin/sent-sound/sent-sound.plugin.desktop.in:4
|
||||
-#, fuzzy
|
||||
-#| msgid "not found"
|
||||
msgid "Sent Sound"
|
||||
-msgstr "nenájdené"
|
||||
+msgstr "Zvuk po odoslaní"
|
||||
|
||||
#: src/client/plugin/sent-sound/sent-sound.plugin.desktop.in:5
|
||||
msgid "Plays the desktop sent-mail sound when an email is sent"
|
||||
-msgstr ""
|
||||
+msgstr "Prehrá systémový zvuk po odoslaní emailu"
|
||||
|
||||
#. Translators: Info bar button label for emptying
|
||||
#. trash/spam folders
|
||||
@@ -3190,7 +3190,7 @@ msgstr "Prepne pridávanie nových položiek záznamu"
|
||||
#. Tooltip for inspector button
|
||||
#: ui/components-inspector.ui:55
|
||||
msgid "Add a marker entry to the log"
|
||||
-msgstr ""
|
||||
+msgstr "Pridá značku do záznamu"
|
||||
|
||||
#. Tooltip for inspector button
|
||||
#. Tooltip for problem report button
|
||||
@@ -3237,10 +3237,8 @@ msgstr "Vždy načítať vzdialené obrázky"
|
||||
|
||||
#. Title label on contact popover
|
||||
#: ui/conversation-contact-popover.ui:264
|
||||
-#, fuzzy
|
||||
-#| msgid "Remove email address"
|
||||
msgid "Deceptive email address"
|
||||
-msgstr "Odstráni emailové adresy"
|
||||
+msgstr "Podvodná emailová adresa"
|
||||
|
||||
#. Contact popover label
|
||||
#: ui/conversation-contact-popover.ui:294
|
||||
@@ -3662,12 +3660,9 @@ msgid "Unquote text"
|
||||
msgstr "Zrušenie citácie textu"
|
||||
|
||||
#: ui/gtk/help-overlay.ui:464
|
||||
-#, fuzzy
|
||||
-#| msgctxt "shortcut window"
|
||||
-#| msgid "Rich text mode"
|
||||
msgctxt "shortcut window"
|
||||
msgid "Rich text editing"
|
||||
-msgstr "Formátovanie textu"
|
||||
+msgstr "Úprava formátovaného textu"
|
||||
|
||||
#: ui/gtk/help-overlay.ui:468
|
||||
msgctxt "shortcut window"
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,75 @@
|
||||
From 571c10add8f8b0ad33031935f5de1bd6ff6fed2b Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Mustieles <daniel.mustieles@gmail.com>
|
||||
Date: Wed, 23 Sep 2020 09:26:43 +0200
|
||||
Subject: [PATCH 018/124] Updated Spanish translation
|
||||
|
||||
---
|
||||
po/es.po | 16 ++++++++--------
|
||||
1 file changed, 8 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/po/es.po b/po/es.po
|
||||
index c387333b..fc6a4f53 100644
|
||||
--- a/po/es.po
|
||||
+++ b/po/es.po
|
||||
@@ -18,8 +18,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: geary-0.4.1\n"
|
||||
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/geary/issues\n"
|
||||
-"POT-Creation-Date: 2020-08-29 01:59+0000\n"
|
||||
-"PO-Revision-Date: 2020-08-26 10:09+0200\n"
|
||||
+"POT-Creation-Date: 2020-09-21 11:52+0000\n"
|
||||
+"PO-Revision-Date: 2020-09-23 09:16+0200\n"
|
||||
"Last-Translator: Daniel Mustieles <daniel.mustieles@gmail.com>\n"
|
||||
"Language-Team: Spanish - Spain <gnome-es-list@gnome.org>\n"
|
||||
"Language: es_ES\n"
|
||||
@@ -27,7 +27,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
-"X-Generator: Gtranslator 3.36.0\n"
|
||||
+"X-Generator: Gtranslator 3.38.0\n"
|
||||
|
||||
#: desktop/geary-attach.contract.desktop.in:3
|
||||
msgid "Send by email"
|
||||
@@ -982,13 +982,13 @@ msgstr ""
|
||||
|
||||
#. / Warning printed to the console when a deprecated
|
||||
#. / command line option is used.
|
||||
-#: src/client/application/application-client.vala:1047
|
||||
+#: src/client/application/application-client.vala:1045
|
||||
msgid "The `--hidden` option is deprecated and will be removed in the future."
|
||||
msgstr "La opción «--hidden» está obsoleta y se eliminará en el futuro."
|
||||
|
||||
#. / Command line warning, string substitution
|
||||
#. / is the given argument
|
||||
-#: src/client/application/application-client.vala:1080
|
||||
+#: src/client/application/application-client.vala:1078
|
||||
#, c-format
|
||||
msgid "Unrecognised program argument: “%s”"
|
||||
msgstr "Opción de la línea de comandos no reconocida: «%s»"
|
||||
@@ -1345,7 +1345,7 @@ msgstr "Guardar como"
|
||||
|
||||
#: src/client/components/components-inspector.vala:230
|
||||
#: src/client/dialogs/dialogs-problem-details-dialog.vala:224
|
||||
-#: ui/accounts_editor_servers_pane.ui:17
|
||||
+#: ui/accounts_editor_servers_pane.ui:17 ui/composer-headerbar.ui:61
|
||||
msgid "Cancel"
|
||||
msgstr "Cancelar"
|
||||
|
||||
@@ -2248,11 +2248,11 @@ msgstr "Pausar"
|
||||
#. folder. The first string substitution the number of email
|
||||
#. already sent, the second is the total number to send.
|
||||
#: src/client/plugin/mail-merge/mail-merge.vala:240
|
||||
-#, fuzzy, c-format
|
||||
+#, c-format
|
||||
#| msgid "Sent %u of %u"
|
||||
msgid "Sent %u of %u"
|
||||
msgid_plural "Sent %u of %u"
|
||||
-msgstr[0] "Enviados %u de %u"
|
||||
+msgstr[0] "Enviado %u de %u"
|
||||
msgstr[1] "Enviados %u de %u"
|
||||
|
||||
#. Translators: Infobar status label for an email mail merge
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,31 @@
|
||||
From 7f7c55e79a0ec40ec3fae5c86568e4c1b6cc37df Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Fri, 25 Sep 2020 08:25:34 +1000
|
||||
Subject: [PATCH 020/124] Application.CertificateManager: Fix critical when no
|
||||
GCR trust stores
|
||||
|
||||
Ensure GCR store not null before accessing it.
|
||||
---
|
||||
src/client/application/application-certificate-manager.vala | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/client/application/application-certificate-manager.vala b/src/client/application/application-certificate-manager.vala
|
||||
index ff0e7785..d9e40fcd 100644
|
||||
--- a/src/client/application/application-certificate-manager.vala
|
||||
+++ b/src/client/application/application-certificate-manager.vala
|
||||
@@ -74,8 +74,10 @@ public class Application.CertificateManager : GLib.Object {
|
||||
bool has_rw_store = false;
|
||||
if (has_uris) {
|
||||
Gck.Slot? store = Gcr.pkcs11_get_trust_store_slot();
|
||||
- has_rw_store = !store.has_flags(CKF_WRITE_PROTECTED);
|
||||
- debug("GCR store is R/W: %s", has_rw_store.to_string());
|
||||
+ if (store != null) {
|
||||
+ has_rw_store = !store.has_flags(CKF_WRITE_PROTECTED);
|
||||
+ debug("GCR store is R/W: %s", has_rw_store.to_string());
|
||||
+ }
|
||||
}
|
||||
|
||||
return has_rw_store;
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,46 @@
|
||||
From 0475d29f84ef13861fdc5ee2e747c00644c002fc Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Fri, 25 Sep 2020 08:27:36 +1000
|
||||
Subject: [PATCH 021/124] Application.CertificateManager: Warn when GCR not
|
||||
able to access stores
|
||||
|
||||
At least let people know somehow their GCR setup is lacking.
|
||||
---
|
||||
.../application-certificate-manager.vala | 14 +++++++++++++-
|
||||
1 file changed, 13 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/client/application/application-certificate-manager.vala b/src/client/application/application-certificate-manager.vala
|
||||
index d9e40fcd..3add2206 100644
|
||||
--- a/src/client/application/application-certificate-manager.vala
|
||||
+++ b/src/client/application/application-certificate-manager.vala
|
||||
@@ -68,7 +68,13 @@ public class Application.CertificateManager : GLib.Object {
|
||||
!Geary.String.is_empty(Gcr.pkcs11_get_trust_store_uri()) &&
|
||||
Gcr.pkcs11_get_trust_lookup_uris().length > 0
|
||||
);
|
||||
- debug("GCR slot URIs found: %s", has_uris.to_string());
|
||||
+ if (has_uris) {
|
||||
+ debug("GCR slot URIs found: %s", has_uris.to_string());
|
||||
+ } else {
|
||||
+ warning(
|
||||
+ "No GCR slot URIs found, GCR certificate pinning unavailable"
|
||||
+ );
|
||||
+ }
|
||||
}
|
||||
|
||||
bool has_rw_store = false;
|
||||
@@ -77,6 +83,12 @@ public class Application.CertificateManager : GLib.Object {
|
||||
if (store != null) {
|
||||
has_rw_store = !store.has_flags(CKF_WRITE_PROTECTED);
|
||||
debug("GCR store is R/W: %s", has_rw_store.to_string());
|
||||
+ } else {
|
||||
+ warning("No GCR store found, GCR certificate pinning unavailable");
|
||||
+ }
|
||||
+
|
||||
+ if (!has_rw_store) {
|
||||
+ warning("GCR store is not RW, GCR certificate pinning unavailable");
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,35 @@
|
||||
From 2093aa32292e11455648d62d8b7a992532aac04e Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Wed, 23 Sep 2020 08:44:04 +1000
|
||||
Subject: [PATCH 022/124] Geary.Imap.Session: Avoid critical when client
|
||||
session logged out
|
||||
|
||||
If the client session is being logging out but some other tasks is
|
||||
still attempting to use it, getting a mailbox will assume at least
|
||||
one personal namespace exists, but it will have been cleared.
|
||||
|
||||
Add a check and throw an exception if none are present, so at least
|
||||
it is handled in a well defined way.
|
||||
|
||||
Fixes #986
|
||||
---
|
||||
src/engine/imap/transport/imap-client-session.vala | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/src/engine/imap/transport/imap-client-session.vala b/src/engine/imap/transport/imap-client-session.vala
|
||||
index f42112f2..81d892ef 100644
|
||||
--- a/src/engine/imap/transport/imap-client-session.vala
|
||||
+++ b/src/engine/imap/transport/imap-client-session.vala
|
||||
@@ -599,6 +599,9 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
||||
}
|
||||
if (ns == null) {
|
||||
// fall back to the default personal namespace
|
||||
+ if (this.personal_namespaces.is_empty) {
|
||||
+ throw new ImapError.UNAVAILABLE("No personal namespace");
|
||||
+ }
|
||||
ns = this.personal_namespaces[0];
|
||||
}
|
||||
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,47 @@
|
||||
From 1c951f890840b91885d5f3752bb8bc3fdfc26324 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Wed, 23 Sep 2020 08:48:45 +1000
|
||||
Subject: [PATCH 023/124] Geary.Imap.SessionObject: Ensure the session is
|
||||
connected when accessed
|
||||
|
||||
Ensure the client session is connected as well as non-null when being
|
||||
accessed, so that if being logged out it is also treated as being
|
||||
disconnected.
|
||||
---
|
||||
src/engine/imap/api/imap-session-object.vala | 16 ++++++++++------
|
||||
1 file changed, 10 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/src/engine/imap/api/imap-session-object.vala b/src/engine/imap/api/imap-session-object.vala
|
||||
index 4937d462..ee1ac09f 100644
|
||||
--- a/src/engine/imap/api/imap-session-object.vala
|
||||
+++ b/src/engine/imap/api/imap-session-object.vala
|
||||
@@ -83,16 +83,20 @@ public abstract class Geary.Imap.SessionObject : BaseObject, Logging.Source {
|
||||
}
|
||||
|
||||
/**
|
||||
- * Obtains IMAP session the server for use by this object.
|
||||
+ * Returns a valid IMAP client session for use by this object.
|
||||
*
|
||||
- * @throws ImapError.NOT_CONNECTED if the session with the server
|
||||
- * server has been dropped via {@link close}, or because
|
||||
- * the connection was lost.
|
||||
+ * @throws ImapError.NOT_CONNECTED if the client session has been
|
||||
+ * dropped via {@link close}, if the client session is logging out
|
||||
+ * or has been closed, or because the connection to the server was
|
||||
+ * lost.
|
||||
*/
|
||||
protected ClientSession claim_session()
|
||||
throws ImapError {
|
||||
- if (this.session == null) {
|
||||
- throw new ImapError.NOT_CONNECTED("IMAP object has no session");
|
||||
+ if (this.session == null ||
|
||||
+ this.session.get_protocol_state() == NOT_CONNECTED) {
|
||||
+ throw new ImapError.NOT_CONNECTED(
|
||||
+ "IMAP object has no session or is not connected"
|
||||
+ );
|
||||
}
|
||||
return this.session;
|
||||
}
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,101 @@
|
||||
From b209f84e5895d7ae3b9ca200f36343d162914932 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Wed, 23 Sep 2020 09:11:50 +1000
|
||||
Subject: [PATCH 024/124] Geary.Imap.FolderSession: Ensure client session is
|
||||
selected when accessed
|
||||
|
||||
Ensure the underlying ClientSession object is in the SELECTED state
|
||||
for the correct mailbox when obtaining it.
|
||||
---
|
||||
src/engine/imap/api/imap-folder-session.vala | 31 ++++++++++++++++----
|
||||
src/engine/imap/api/imap-session-object.vala | 2 +-
|
||||
2 files changed, 26 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/src/engine/imap/api/imap-folder-session.vala b/src/engine/imap/api/imap-folder-session.vala
|
||||
index 092c06cd..98db3088 100644
|
||||
--- a/src/engine/imap/api/imap-folder-session.vala
|
||||
+++ b/src/engine/imap/api/imap-folder-session.vala
|
||||
@@ -38,6 +38,8 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
||||
/** Determines if this folder accepts custom IMAP flags. */
|
||||
public Trillian accepts_user_flags { get; private set; default = Trillian.UNKNOWN; }
|
||||
|
||||
+ private MailboxSpecifier mailbox;
|
||||
+
|
||||
private Quirks quirks;
|
||||
|
||||
private Nonblocking.Mutex cmd_mutex = new Nonblocking.Mutex();
|
||||
@@ -107,9 +109,9 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
||||
session.search.connect(on_search);
|
||||
session.status_response_received.connect(on_status_response);
|
||||
|
||||
- MailboxSpecifier mailbox = session.get_mailbox_for_path(folder.path);
|
||||
+ this.mailbox = session.get_mailbox_for_path(folder.path);
|
||||
StatusResponse? response = yield session.select_async(
|
||||
- mailbox, cancellable
|
||||
+ this.mailbox, cancellable
|
||||
);
|
||||
throw_on_not_ok(response, "SELECT " + this.folder.path.to_string());
|
||||
|
||||
@@ -1107,8 +1109,6 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
||||
Geary.EmailFlags? flags,
|
||||
GLib.DateTime? date_received)
|
||||
throws GLib.Error {
|
||||
- ClientSession session = claim_session();
|
||||
-
|
||||
MessageFlags? msg_flags = null;
|
||||
if (flags != null) {
|
||||
Imap.EmailFlags imap_flags = Imap.EmailFlags.from_api_email_flags(flags);
|
||||
@@ -1121,9 +1121,8 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
||||
if (date_received != null)
|
||||
internaldate = new InternalDate.from_date_time(date_received);
|
||||
|
||||
- MailboxSpecifier mailbox = session.get_mailbox_for_path(this.folder.path);
|
||||
AppendCommand cmd = new AppendCommand(
|
||||
- mailbox,
|
||||
+ this.mailbox,
|
||||
msg_flags,
|
||||
internaldate,
|
||||
message.get_rfc822_buffer(),
|
||||
@@ -1161,6 +1160,26 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
||||
);
|
||||
}
|
||||
|
||||
+ /**
|
||||
+ * Returns a valid IMAP client session for use by this object.
|
||||
+ *
|
||||
+ * In addition to the checks made by {@link
|
||||
+ * SessionObject.claim_session}, this method also ensures that the
|
||||
+ * IMAP session is in the SELECTED state for the correct mailbox.
|
||||
+ */
|
||||
+ protected override ClientSession claim_session()
|
||||
+ throws ImapError {
|
||||
+ var session = base.claim_session();
|
||||
+ if (session.get_protocol_state() != SELECTED &&
|
||||
+ !this.mailbox.equal_to(session.selected_mailbox)) {
|
||||
+ throw new ImapError.NOT_CONNECTED(
|
||||
+ "IMAP object no longer SELECTED for %s",
|
||||
+ this.mailbox.to_string()
|
||||
+ );
|
||||
+ }
|
||||
+ return session;
|
||||
+ }
|
||||
+
|
||||
// HACK: See https://bugzilla.gnome.org/show_bug.cgi?id=714902
|
||||
//
|
||||
// Detect when a server has returned a BAD response to FETCH
|
||||
diff --git a/src/engine/imap/api/imap-session-object.vala b/src/engine/imap/api/imap-session-object.vala
|
||||
index ee1ac09f..d47c6950 100644
|
||||
--- a/src/engine/imap/api/imap-session-object.vala
|
||||
+++ b/src/engine/imap/api/imap-session-object.vala
|
||||
@@ -90,7 +90,7 @@ public abstract class Geary.Imap.SessionObject : BaseObject, Logging.Source {
|
||||
* or has been closed, or because the connection to the server was
|
||||
* lost.
|
||||
*/
|
||||
- protected ClientSession claim_session()
|
||||
+ protected virtual ClientSession claim_session()
|
||||
throws ImapError {
|
||||
if (this.session == null ||
|
||||
this.session.get_protocol_state() == NOT_CONNECTED) {
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,134 @@
|
||||
From ac425f57b134c2264723e20ea15319ab615f0f9d Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Wed, 23 Sep 2020 09:17:28 +1000
|
||||
Subject: [PATCH 025/124] Geary.Imap.SessionObject: Rename `claim_session` to
|
||||
`get_session`
|
||||
|
||||
Don't over-sell what it does.
|
||||
---
|
||||
src/engine/imap/api/imap-account-session.vala | 10 +++++-----
|
||||
src/engine/imap/api/imap-folder-session.vala | 14 +++++++-------
|
||||
src/engine/imap/api/imap-session-object.vala | 2 +-
|
||||
3 files changed, 13 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/src/engine/imap/api/imap-account-session.vala b/src/engine/imap/api/imap-account-session.vala
|
||||
index 238bd85c..813d9e5e 100644
|
||||
--- a/src/engine/imap/api/imap-account-session.vala
|
||||
+++ b/src/engine/imap/api/imap-account-session.vala
|
||||
@@ -45,7 +45,7 @@ internal class Geary.Imap.AccountSession : Geary.Imap.SessionObject {
|
||||
*/
|
||||
public async FolderPath get_default_personal_namespace(Cancellable? cancellable)
|
||||
throws Error {
|
||||
- ClientSession session = claim_session();
|
||||
+ ClientSession session = get_session();
|
||||
Gee.List<Namespace> personal = session.get_personal_namespaces();
|
||||
if (personal.is_empty) {
|
||||
throw new ImapError.INVALID("No personal namespace found");
|
||||
@@ -69,7 +69,7 @@ internal class Geary.Imap.AccountSession : Geary.Imap.SessionObject {
|
||||
public bool is_folder_path_valid(FolderPath? path) throws GLib.Error {
|
||||
bool is_valid = false;
|
||||
if (path != null) {
|
||||
- ClientSession session = claim_session();
|
||||
+ ClientSession session = get_session();
|
||||
try {
|
||||
session.get_mailbox_for_path(path);
|
||||
is_valid = true;
|
||||
@@ -94,7 +94,7 @@ internal class Geary.Imap.AccountSession : Geary.Imap.SessionObject {
|
||||
Geary.Folder.SpecialUse? use,
|
||||
Cancellable? cancellable)
|
||||
throws Error {
|
||||
- ClientSession session = claim_session();
|
||||
+ ClientSession session = get_session();
|
||||
MailboxSpecifier mailbox = session.get_mailbox_for_path(path);
|
||||
bool can_create_special = session.capabilities.has_capability(Capabilities.CREATE_SPECIAL_USE);
|
||||
CreateCommand cmd = (
|
||||
@@ -125,7 +125,7 @@ internal class Geary.Imap.AccountSession : Geary.Imap.SessionObject {
|
||||
public async Imap.Folder fetch_folder_async(FolderPath path,
|
||||
Cancellable? cancellable)
|
||||
throws Error {
|
||||
- ClientSession session = claim_session();
|
||||
+ ClientSession session = get_session();
|
||||
Imap.Folder? folder = this.folders.get(path);
|
||||
if (folder == null) {
|
||||
Gee.List<MailboxInformation>? mailboxes = yield send_list_async(
|
||||
@@ -169,7 +169,7 @@ internal class Geary.Imap.AccountSession : Geary.Imap.SessionObject {
|
||||
fetch_child_folders_async(FolderPath parent,
|
||||
GLib.Cancellable? cancellable)
|
||||
throws GLib.Error {
|
||||
- ClientSession session = claim_session();
|
||||
+ ClientSession session = get_session();
|
||||
Gee.List<Imap.Folder> children = new Gee.ArrayList<Imap.Folder>();
|
||||
Gee.List<MailboxInformation> mailboxes = yield send_list_async(
|
||||
session, parent, true, cancellable
|
||||
diff --git a/src/engine/imap/api/imap-folder-session.vala b/src/engine/imap/api/imap-folder-session.vala
|
||||
index 98db3088..8b4212e6 100644
|
||||
--- a/src/engine/imap/api/imap-folder-session.vala
|
||||
+++ b/src/engine/imap/api/imap-folder-session.vala
|
||||
@@ -127,7 +127,7 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
||||
*/
|
||||
public async void enable_idle(Cancellable? cancellable)
|
||||
throws Error {
|
||||
- ClientSession session = claim_session();
|
||||
+ ClientSession session = get_session();
|
||||
int token = yield this.cmd_mutex.claim_async(cancellable);
|
||||
Error? cmd_err = null;
|
||||
try {
|
||||
@@ -303,7 +303,7 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
||||
Gee.Set<Imap.UID>? search_results,
|
||||
GLib.Cancellable? cancellable)
|
||||
throws GLib.Error {
|
||||
- ClientSession session = claim_session();
|
||||
+ ClientSession session = get_session();
|
||||
Gee.Map<Command, StatusResponse>? responses = null;
|
||||
int token = yield this.cmd_mutex.claim_async(cancellable);
|
||||
|
||||
@@ -648,7 +648,7 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
||||
public async void remove_email_async(Gee.List<MessageSet> msg_sets,
|
||||
GLib.Cancellable? cancellable)
|
||||
throws GLib.Error {
|
||||
- ClientSession session = claim_session();
|
||||
+ ClientSession session = get_session();
|
||||
Gee.List<MessageFlag> flags = new Gee.ArrayList<MessageFlag>();
|
||||
flags.add(MessageFlag.DELETED);
|
||||
|
||||
@@ -721,7 +721,7 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
||||
FolderPath destination,
|
||||
GLib.Cancellable? cancellable)
|
||||
throws GLib.Error {
|
||||
- ClientSession session = claim_session();
|
||||
+ ClientSession session = get_session();
|
||||
|
||||
MailboxSpecifier mailbox = session.get_mailbox_for_path(destination);
|
||||
CopyCommand cmd = new CopyCommand(msg_set, mailbox, cancellable);
|
||||
@@ -1164,12 +1164,12 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
||||
* Returns a valid IMAP client session for use by this object.
|
||||
*
|
||||
* In addition to the checks made by {@link
|
||||
- * SessionObject.claim_session}, this method also ensures that the
|
||||
+ * SessionObject.get_session}, this method also ensures that the
|
||||
* IMAP session is in the SELECTED state for the correct mailbox.
|
||||
*/
|
||||
- protected override ClientSession claim_session()
|
||||
+ protected override ClientSession get_session()
|
||||
throws ImapError {
|
||||
- var session = base.claim_session();
|
||||
+ var session = base.get_session();
|
||||
if (session.get_protocol_state() != SELECTED &&
|
||||
!this.mailbox.equal_to(session.selected_mailbox)) {
|
||||
throw new ImapError.NOT_CONNECTED(
|
||||
diff --git a/src/engine/imap/api/imap-session-object.vala b/src/engine/imap/api/imap-session-object.vala
|
||||
index d47c6950..4a46ae1e 100644
|
||||
--- a/src/engine/imap/api/imap-session-object.vala
|
||||
+++ b/src/engine/imap/api/imap-session-object.vala
|
||||
@@ -90,7 +90,7 @@ public abstract class Geary.Imap.SessionObject : BaseObject, Logging.Source {
|
||||
* or has been closed, or because the connection to the server was
|
||||
* lost.
|
||||
*/
|
||||
- protected virtual ClientSession claim_session()
|
||||
+ protected virtual ClientSession get_session()
|
||||
throws ImapError {
|
||||
if (this.session == null ||
|
||||
this.session.get_protocol_state() == NOT_CONNECTED) {
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,154 @@
|
||||
From ed4ba33127795a7ffefb6517ed57185ef44fe1c7 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Sun, 27 Sep 2020 15:58:40 +1000
|
||||
Subject: [PATCH 026/124] Geary.State.Machine: Support GObject notify signal
|
||||
for state changes
|
||||
|
||||
Modernise the API a bit by using properties instead of explicit
|
||||
getters/setters, an hence support GObject notify signals when the
|
||||
state property changes.
|
||||
---
|
||||
.../imap/transport/imap-client-session.vala | 9 ++---
|
||||
.../imap/transport/imap-deserializer.vala | 4 +-
|
||||
src/engine/state/state-machine.vala | 37 ++++++-------------
|
||||
3 files changed, 18 insertions(+), 32 deletions(-)
|
||||
|
||||
diff --git a/src/engine/imap/transport/imap-client-session.vala b/src/engine/imap/transport/imap-client-session.vala
|
||||
index 81d892ef..91137f1e 100644
|
||||
--- a/src/engine/imap/transport/imap-client-session.vala
|
||||
+++ b/src/engine/imap/transport/imap-client-session.vala
|
||||
@@ -483,11 +483,10 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
||||
};
|
||||
|
||||
fsm = new Geary.State.Machine(machine_desc, mappings, on_ignored_transition);
|
||||
- fsm.set_logging(false);
|
||||
}
|
||||
|
||||
~ClientSession() {
|
||||
- switch (fsm.get_state()) {
|
||||
+ switch (fsm.state) {
|
||||
case State.NOT_CONNECTED:
|
||||
case State.CLOSED:
|
||||
// no problem-o
|
||||
@@ -782,7 +781,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
||||
|
||||
private bool on_greeting_timeout() {
|
||||
// if still in CONNECTING state, the greeting never arrived
|
||||
- if (fsm.get_state() == State.CONNECTING)
|
||||
+ if (fsm.state == State.CONNECTING)
|
||||
fsm.issue(Event.TIMEOUT);
|
||||
|
||||
return false;
|
||||
@@ -1645,12 +1644,12 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
||||
return (this.selected_mailbox == null)
|
||||
? new Logging.State(
|
||||
this,
|
||||
- this.fsm.get_state_string(fsm.get_state())
|
||||
+ this.fsm.get_state_string(fsm.state)
|
||||
)
|
||||
: new Logging.State(
|
||||
this,
|
||||
"%s:%s selected %s",
|
||||
- this.fsm.get_state_string(fsm.get_state()),
|
||||
+ this.fsm.get_state_string(fsm.state),
|
||||
this.selected_mailbox.to_string(),
|
||||
this.selected_readonly ? "RO" : "RW"
|
||||
);
|
||||
diff --git a/src/engine/imap/transport/imap-deserializer.vala b/src/engine/imap/transport/imap-deserializer.vala
|
||||
index 249f7c85..559a5e78 100644
|
||||
--- a/src/engine/imap/transport/imap-deserializer.vala
|
||||
+++ b/src/engine/imap/transport/imap-deserializer.vala
|
||||
@@ -294,7 +294,7 @@ public class Geary.Imap.Deserializer : BaseObject, Logging.Source {
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public Logging.State to_logging_state() {
|
||||
- return new Logging.State(this, fsm.get_state_string(fsm.get_state()));
|
||||
+ return new Logging.State(this, fsm.get_state_string(fsm.state));
|
||||
}
|
||||
|
||||
/** Sets the connection's logging parent. */
|
||||
@@ -429,7 +429,7 @@ public class Geary.Imap.Deserializer : BaseObject, Logging.Source {
|
||||
}
|
||||
|
||||
private Mode get_mode() {
|
||||
- switch (fsm.get_state()) {
|
||||
+ switch (fsm.state) {
|
||||
case State.LITERAL_DATA:
|
||||
return Mode.BLOCK;
|
||||
|
||||
diff --git a/src/engine/state/state-machine.vala b/src/engine/state/state-machine.vala
|
||||
index 351babb8..ef32555d 100644
|
||||
--- a/src/engine/state/state-machine.vala
|
||||
+++ b/src/engine/state/state-machine.vala
|
||||
@@ -5,13 +5,20 @@
|
||||
*/
|
||||
|
||||
public class Geary.State.Machine : BaseObject {
|
||||
+
|
||||
+ /** The state machine's current state. */
|
||||
+ public uint state { get; private set; }
|
||||
+
|
||||
+ /** Determines if the state machine crashes your app when mis-configured. */
|
||||
+ public bool abort_on_no_transition { get; set; default = true; }
|
||||
+
|
||||
+ /** Determines if transition logging is enabled. */
|
||||
+ public bool logging { get; private set; default = false; }
|
||||
+
|
||||
private Geary.State.MachineDescriptor descriptor;
|
||||
- private uint state;
|
||||
private Mapping[,] transitions;
|
||||
private unowned Transition? default_transition;
|
||||
private bool locked = false;
|
||||
- private bool abort_on_no_transition = true;
|
||||
- private bool logging = false;
|
||||
private unowned PostTransition? post_transition = null;
|
||||
private void *post_user = null;
|
||||
private Object? post_object = null;
|
||||
@@ -39,26 +46,6 @@ public class Geary.State.Machine : BaseObject {
|
||||
}
|
||||
}
|
||||
|
||||
- public uint get_state() {
|
||||
- return state;
|
||||
- }
|
||||
-
|
||||
- public bool get_abort_on_no_transition() {
|
||||
- return abort_on_no_transition;
|
||||
- }
|
||||
-
|
||||
- public void set_abort_on_no_transition(bool abort) {
|
||||
- abort_on_no_transition = abort;
|
||||
- }
|
||||
-
|
||||
- public void set_logging(bool logging) {
|
||||
- this.logging = logging;
|
||||
- }
|
||||
-
|
||||
- public bool is_logging() {
|
||||
- return logging;
|
||||
- }
|
||||
-
|
||||
public uint issue(uint event, void *user = null, Object? object = null, Error? err = null) {
|
||||
assert(event < descriptor.event_count);
|
||||
assert(state < descriptor.state_count);
|
||||
@@ -70,7 +57,7 @@ public class Geary.State.Machine : BaseObject {
|
||||
string msg = "%s: No transition defined for %s@%s".printf(to_string(),
|
||||
descriptor.get_event_string(event), descriptor.get_state_string(state));
|
||||
|
||||
- if (get_abort_on_no_transition())
|
||||
+ if (this.abort_on_no_transition)
|
||||
error(msg);
|
||||
else
|
||||
critical(msg);
|
||||
@@ -96,7 +83,7 @@ public class Geary.State.Machine : BaseObject {
|
||||
}
|
||||
locked = false;
|
||||
|
||||
- if (is_logging())
|
||||
+ if (this.logging)
|
||||
message("%s: %s", to_string(), get_transition_string(old_state, event, state));
|
||||
|
||||
// Perform post-transition if registered
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,561 @@
|
||||
From 41be8693d4481d6a50f49e3bf6698e9103d0bfa7 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Sun, 27 Sep 2020 16:00:35 +1000
|
||||
Subject: [PATCH 027/124] Geary.Imap.ClientSession: Treat logout as disconnect
|
||||
|
||||
Convert `get_protocol_state` to an automatic property, so that rather
|
||||
than requiring explcit signals for lifecycle events, a GObject notify
|
||||
signal can be used instead.
|
||||
|
||||
Convert disconnect signal to a property so it can be accessed if needed.
|
||||
|
||||
Convert code listening to the disconnect signal to listen to notify
|
||||
signals for `protocol_state` instead, and hence also treat the session
|
||||
as disconnected when a logout is in progress.
|
||||
|
||||
Fixes #986
|
||||
---
|
||||
src/engine/imap/api/imap-client-service.vala | 38 +++---
|
||||
src/engine/imap/api/imap-folder-session.vala | 2 +-
|
||||
src/engine/imap/api/imap-session-object.vala | 26 ++--
|
||||
.../imap/transport/imap-client-session.vala | 118 ++++++++++--------
|
||||
.../transport/imap-client-session-test.vala | 40 +++---
|
||||
test/integration/imap/client-session.vala | 2 +-
|
||||
6 files changed, 130 insertions(+), 96 deletions(-)
|
||||
|
||||
diff --git a/src/engine/imap/api/imap-client-service.vala b/src/engine/imap/api/imap-client-service.vala
|
||||
index e0aad41b..da3598f3 100644
|
||||
--- a/src/engine/imap/api/imap-client-service.vala
|
||||
+++ b/src/engine/imap/api/imap-client-service.vala
|
||||
@@ -252,7 +252,7 @@ public class Geary.Imap.ClientService : Geary.ClientService {
|
||||
if (!disconnect) {
|
||||
// If the session has a mailbox selected, close it before
|
||||
// adding it back to the pool
|
||||
- ClientSession.ProtocolState proto = session.get_protocol_state();
|
||||
+ ClientSession.ProtocolState proto = session.protocol_state;
|
||||
if (proto == ClientSession.ProtocolState.SELECTED ||
|
||||
proto == ClientSession.ProtocolState.SELECTING) {
|
||||
// always close mailbox to return to authorized state
|
||||
@@ -263,7 +263,7 @@ public class Geary.Imap.ClientService : Geary.ClientService {
|
||||
session.to_string(), imap_error.message);
|
||||
disconnect = true;
|
||||
}
|
||||
- if (session.get_protocol_state() != AUTHORIZED) {
|
||||
+ if (session.protocol_state != AUTHORIZED) {
|
||||
// Closing it didn't leave it in the desired
|
||||
// state, so drop it
|
||||
disconnect = true;
|
||||
@@ -393,7 +393,7 @@ public class Geary.Imap.ClientService : Geary.ClientService {
|
||||
/** Determines if a session is valid, disposing of it if not. */
|
||||
private async bool check_session(ClientSession target, bool claiming) {
|
||||
bool valid = false;
|
||||
- switch (target.get_protocol_state()) {
|
||||
+ switch (target.protocol_state) {
|
||||
case ClientSession.ProtocolState.AUTHORIZED:
|
||||
case ClientSession.ProtocolState.CLOSING_MAILBOX:
|
||||
valid = true;
|
||||
@@ -472,7 +472,7 @@ public class Geary.Imap.ClientService : Geary.ClientService {
|
||||
|
||||
// Only bother tracking disconnects and enabling keeping alive
|
||||
// now the session is properly established.
|
||||
- new_session.disconnected.connect(on_disconnected);
|
||||
+ new_session.notify["disconnected"].connect(on_session_disconnected);
|
||||
new_session.enable_keepalives(selected_keepalive_sec,
|
||||
unselected_keepalive_sec,
|
||||
selected_with_idle_keepalive_sec);
|
||||
@@ -509,7 +509,7 @@ public class Geary.Imap.ClientService : Geary.ClientService {
|
||||
}
|
||||
|
||||
private async void disconnect_session(ClientSession session) {
|
||||
- if (session.get_protocol_state() != NOT_CONNECTED) {
|
||||
+ if (session.protocol_state != NOT_CONNECTED) {
|
||||
debug("Logging out session: %s", session.to_string());
|
||||
// No need to remove it after logging out, the
|
||||
// disconnected handler will do that for us.
|
||||
@@ -548,21 +548,27 @@ public class Geary.Imap.ClientService : Geary.ClientService {
|
||||
}
|
||||
|
||||
if (removed) {
|
||||
- session.disconnected.disconnect(on_disconnected);
|
||||
+ session.notify["disconnected"].connect(on_session_disconnected);
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
- private void on_disconnected(ClientSession session,
|
||||
- ClientSession.DisconnectReason reason) {
|
||||
- debug(
|
||||
- "Session disconnected: %s: %s",
|
||||
- session.to_string(), reason.to_string()
|
||||
- );
|
||||
- this.remove_session_async.begin(
|
||||
- session,
|
||||
- (obj, res) => { this.remove_session_async.end(res); }
|
||||
- );
|
||||
+ private void on_session_disconnected(GLib.Object source,
|
||||
+ GLib.ParamSpec param) {
|
||||
+ var session = source as ClientSession;
|
||||
+ if (session != null &&
|
||||
+ session.protocol_state == NOT_CONNECTED &&
|
||||
+ session.disconnected != null) {
|
||||
+ debug(
|
||||
+ "Session disconnected: %s: %s",
|
||||
+ session.to_string(),
|
||||
+ session.disconnected.to_string()
|
||||
+ );
|
||||
+ this.remove_session_async.begin(
|
||||
+ session,
|
||||
+ (obj, res) => { this.remove_session_async.end(res); }
|
||||
+ );
|
||||
+ }
|
||||
}
|
||||
|
||||
}
|
||||
diff --git a/src/engine/imap/api/imap-folder-session.vala b/src/engine/imap/api/imap-folder-session.vala
|
||||
index 8b4212e6..8a2290cb 100644
|
||||
--- a/src/engine/imap/api/imap-folder-session.vala
|
||||
+++ b/src/engine/imap/api/imap-folder-session.vala
|
||||
@@ -1170,7 +1170,7 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
||||
protected override ClientSession get_session()
|
||||
throws ImapError {
|
||||
var session = base.get_session();
|
||||
- if (session.get_protocol_state() != SELECTED &&
|
||||
+ if (session.protocol_state != SELECTED &&
|
||||
!this.mailbox.equal_to(session.selected_mailbox)) {
|
||||
throw new ImapError.NOT_CONNECTED(
|
||||
"IMAP object no longer SELECTED for %s",
|
||||
diff --git a/src/engine/imap/api/imap-session-object.vala b/src/engine/imap/api/imap-session-object.vala
|
||||
index 4a46ae1e..80695fca 100644
|
||||
--- a/src/engine/imap/api/imap-session-object.vala
|
||||
+++ b/src/engine/imap/api/imap-session-object.vala
|
||||
@@ -39,7 +39,7 @@ public abstract class Geary.Imap.SessionObject : BaseObject, Logging.Source {
|
||||
*/
|
||||
protected SessionObject(ClientSession session) {
|
||||
this.session = session;
|
||||
- this.session.disconnected.connect(on_disconnected);
|
||||
+ this.session.notify["protocol-state"].connect(on_session_state_change);
|
||||
}
|
||||
|
||||
~SessionObject() {
|
||||
@@ -63,7 +63,9 @@ public abstract class Geary.Imap.SessionObject : BaseObject, Logging.Source {
|
||||
this.session = null;
|
||||
|
||||
if (old_session != null) {
|
||||
- old_session.disconnected.disconnect(on_disconnected);
|
||||
+ old_session.notify["protocol-state"].disconnect(
|
||||
+ on_session_state_change
|
||||
+ );
|
||||
}
|
||||
|
||||
return old_session;
|
||||
@@ -93,7 +95,7 @@ public abstract class Geary.Imap.SessionObject : BaseObject, Logging.Source {
|
||||
protected virtual ClientSession get_session()
|
||||
throws ImapError {
|
||||
if (this.session == null ||
|
||||
- this.session.get_protocol_state() == NOT_CONNECTED) {
|
||||
+ this.session.protocol_state == NOT_CONNECTED) {
|
||||
throw new ImapError.NOT_CONNECTED(
|
||||
"IMAP object has no session or is not connected"
|
||||
);
|
||||
@@ -101,11 +103,19 @@ public abstract class Geary.Imap.SessionObject : BaseObject, Logging.Source {
|
||||
return this.session;
|
||||
}
|
||||
|
||||
- private void on_disconnected(ClientSession.DisconnectReason reason) {
|
||||
- debug("Disconnected %s", reason.to_string());
|
||||
-
|
||||
- close();
|
||||
- disconnected(reason);
|
||||
+ private void on_session_state_change() {
|
||||
+ if (this.session != null &&
|
||||
+ this.session.protocol_state == NOT_CONNECTED) {
|
||||
+ // Disconnect reason will null when the session is being
|
||||
+ // logged out but the logout command has not yet been
|
||||
+ // completed.
|
||||
+ var reason = (
|
||||
+ this.session.disconnected ??
|
||||
+ ClientSession.DisconnectReason.LOCAL_CLOSE
|
||||
+ );
|
||||
+ close();
|
||||
+ disconnected(reason);
|
||||
+ }
|
||||
}
|
||||
|
||||
}
|
||||
diff --git a/src/engine/imap/transport/imap-client-session.vala b/src/engine/imap/transport/imap-client-session.vala
|
||||
index 91137f1e..ba125616 100644
|
||||
--- a/src/engine/imap/transport/imap-client-session.vala
|
||||
+++ b/src/engine/imap/transport/imap-client-session.vala
|
||||
@@ -90,7 +90,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
||||
*
|
||||
* See [[http://tools.ietf.org/html/rfc3501#section-3]]
|
||||
*
|
||||
- * @see get_protocol_state
|
||||
+ * @see protocol_state
|
||||
*/
|
||||
public enum ProtocolState {
|
||||
NOT_CONNECTED,
|
||||
@@ -230,6 +230,55 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
||||
"Geary.Imap.ClientSession", State.NOT_CONNECTED, State.COUNT, Event.COUNT,
|
||||
state_to_string, event_to_string);
|
||||
|
||||
+
|
||||
+ /**
|
||||
+ * Returns the current IMAP protocol state for the session.
|
||||
+ */
|
||||
+ public ProtocolState protocol_state {
|
||||
+ get {
|
||||
+ var state = ProtocolState.NOT_CONNECTED;
|
||||
+ switch (fsm.state) {
|
||||
+ case State.NOT_CONNECTED:
|
||||
+ case State.LOGOUT:
|
||||
+ case State.CLOSED:
|
||||
+ state = NOT_CONNECTED;
|
||||
+ break;
|
||||
+
|
||||
+ case State.NOAUTH:
|
||||
+ state = UNAUTHORIZED;
|
||||
+ break;
|
||||
+
|
||||
+ case State.AUTHORIZED:
|
||||
+ state = AUTHORIZED;
|
||||
+ break;
|
||||
+
|
||||
+ case State.SELECTED:
|
||||
+ state = SELECTED;
|
||||
+ break;
|
||||
+
|
||||
+ case State.CONNECTING:
|
||||
+ state = CONNECTING;
|
||||
+ break;
|
||||
+
|
||||
+ case State.AUTHORIZING:
|
||||
+ state = AUTHORIZING;
|
||||
+ break;
|
||||
+
|
||||
+ case State.SELECTING:
|
||||
+ state = SELECTING;
|
||||
+ break;
|
||||
+
|
||||
+ case State.CLOSING_MAILBOX:
|
||||
+ state = CLOSING_MAILBOX;
|
||||
+ break;
|
||||
+ }
|
||||
+ return state;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /** Specifies the reason the session was disconnected, if any. */
|
||||
+ public DisconnectReason? disconnected { get; private set; default = null; }
|
||||
+
|
||||
/**
|
||||
* Set of IMAP extensions reported as being supported by the server.
|
||||
*
|
||||
@@ -330,9 +379,6 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
||||
// Connection state changes
|
||||
//
|
||||
|
||||
- /** Emitted when the session is disconnected for any reason. */
|
||||
- public signal void disconnected(DisconnectReason reason);
|
||||
-
|
||||
/** Emitted when an IMAP command status response is received. */
|
||||
public signal void status_response_received(StatusResponse status_response);
|
||||
|
||||
@@ -482,7 +528,14 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
||||
new Geary.State.Mapping(State.CLOSED, Event.RECV_ERROR, Geary.State.nop),
|
||||
};
|
||||
|
||||
- fsm = new Geary.State.Machine(machine_desc, mappings, on_ignored_transition);
|
||||
+ this.fsm = new Geary.State.Machine(
|
||||
+ machine_desc,
|
||||
+ mappings,
|
||||
+ on_ignored_transition
|
||||
+ );
|
||||
+ this.fsm.notify["state"].connect(
|
||||
+ () => this.notify_property("protocol_state")
|
||||
+ );
|
||||
}
|
||||
|
||||
~ClientSession() {
|
||||
@@ -493,7 +546,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
||||
break;
|
||||
|
||||
default:
|
||||
- warning("ClientSession ref dropped while still active");
|
||||
+ GLib.warning("ClientSession ref dropped while still active");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -636,43 +689,6 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
||||
return delim;
|
||||
}
|
||||
|
||||
- /**
|
||||
- * Returns the current {@link ProtocolState} of the {@link ClientSession} and, if selected,
|
||||
- * the current mailbox.
|
||||
- */
|
||||
- public ProtocolState get_protocol_state() {
|
||||
- switch (fsm.get_state()) {
|
||||
- case State.NOT_CONNECTED:
|
||||
- case State.LOGOUT:
|
||||
- case State.CLOSED:
|
||||
- return ProtocolState.NOT_CONNECTED;
|
||||
-
|
||||
- case State.NOAUTH:
|
||||
- return ProtocolState.UNAUTHORIZED;
|
||||
-
|
||||
- case State.AUTHORIZED:
|
||||
- return ProtocolState.AUTHORIZED;
|
||||
-
|
||||
- case State.SELECTED:
|
||||
- return ProtocolState.SELECTED;
|
||||
-
|
||||
- case State.CONNECTING:
|
||||
- return ProtocolState.CONNECTING;
|
||||
-
|
||||
- case State.AUTHORIZING:
|
||||
- return ProtocolState.AUTHORIZING;
|
||||
-
|
||||
- case State.SELECTING:
|
||||
- return ProtocolState.SELECTING;
|
||||
-
|
||||
- case State.CLOSING_MAILBOX:
|
||||
- return ProtocolState.CLOSING_MAILBOX;
|
||||
-
|
||||
- default:
|
||||
- assert_not_reached();
|
||||
- }
|
||||
- }
|
||||
-
|
||||
// Some commands require waiting for a completion response in order to shift the state machine's
|
||||
// State; this allocates such a wait, returning false if another command is outstanding also
|
||||
// waiting for one to finish
|
||||
@@ -1197,7 +1213,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
||||
public void enable_idle()
|
||||
throws GLib.Error {
|
||||
if (this.is_idle_supported) {
|
||||
- switch (get_protocol_state()) {
|
||||
+ switch (this.protocol_state) {
|
||||
case ProtocolState.AUTHORIZING:
|
||||
case ProtocolState.AUTHORIZED:
|
||||
case ProtocolState.SELECTED:
|
||||
@@ -1218,7 +1234,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
||||
unschedule_keepalive();
|
||||
|
||||
uint seconds;
|
||||
- switch (get_protocol_state()) {
|
||||
+ switch (this.protocol_state) {
|
||||
case ProtocolState.NOT_CONNECTED:
|
||||
case ProtocolState.CONNECTING:
|
||||
return;
|
||||
@@ -1555,10 +1571,11 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
||||
MachineParams params = (MachineParams) object;
|
||||
|
||||
assert(params.cmd is LogoutCommand);
|
||||
- if (!reserve_state_change_cmd(params, state, event))
|
||||
- return state;
|
||||
+ if (reserve_state_change_cmd(params, state, event)) {
|
||||
+ state = State.LOGOUT;
|
||||
+ }
|
||||
|
||||
- return State.LOGOUT;
|
||||
+ return state;
|
||||
}
|
||||
|
||||
private uint on_logging_out_recv_status(uint state,
|
||||
@@ -1625,7 +1642,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
||||
}
|
||||
|
||||
drop_connection();
|
||||
- disconnected(DisconnectReason.LOCAL_CLOSE);
|
||||
+ this.disconnected = DisconnectReason.LOCAL_CLOSE;
|
||||
|
||||
if (disconnect_err != null)
|
||||
throw disconnect_err;
|
||||
@@ -1661,6 +1678,8 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
||||
}
|
||||
|
||||
private async void do_disconnect(DisconnectReason reason) {
|
||||
+ this.disconnected = reason;
|
||||
+
|
||||
try {
|
||||
yield this.cx.disconnect_async();
|
||||
} catch (GLib.Error err) {
|
||||
@@ -1668,7 +1687,6 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
||||
}
|
||||
|
||||
drop_connection();
|
||||
- disconnected(reason);
|
||||
}
|
||||
|
||||
//
|
||||
diff --git a/test/engine/imap/transport/imap-client-session-test.vala b/test/engine/imap/transport/imap-client-session-test.vala
|
||||
index 2aed9211..c9a4165c 100644
|
||||
--- a/test/engine/imap/transport/imap-client-session-test.vala
|
||||
+++ b/test/engine/imap/transport/imap-client-session-test.vala
|
||||
@@ -44,17 +44,17 @@ class Geary.Imap.ClientSessionTest : TestCase {
|
||||
this.server.add_script_line(WAIT_FOR_DISCONNECT, "");
|
||||
|
||||
var test_article = new ClientSession(new_endpoint(), new Quirks());
|
||||
- assert_true(test_article.get_protocol_state() == NOT_CONNECTED);
|
||||
+ assert_true(test_article.protocol_state == NOT_CONNECTED);
|
||||
|
||||
test_article.connect_async.begin(
|
||||
CONNECT_TIMEOUT, null, this.async_completion
|
||||
);
|
||||
test_article.connect_async.end(async_result());
|
||||
- assert_true(test_article.get_protocol_state() == UNAUTHORIZED);
|
||||
+ assert_true(test_article.protocol_state == UNAUTHORIZED);
|
||||
|
||||
test_article.disconnect_async.begin(null, this.async_completion);
|
||||
test_article.disconnect_async.end(async_result());
|
||||
- assert_true(test_article.get_protocol_state() == NOT_CONNECTED);
|
||||
+ assert_true(test_article.protocol_state == NOT_CONNECTED);
|
||||
|
||||
TestServer.Result result = this.server.wait_for_script(this.main_loop);
|
||||
assert_true(
|
||||
@@ -148,13 +148,13 @@ class Geary.Imap.ClientSessionTest : TestCase {
|
||||
this.server.add_script_line(WAIT_FOR_DISCONNECT, "");
|
||||
|
||||
var test_article = new ClientSession(new_endpoint(), new Quirks());
|
||||
- assert_true(test_article.get_protocol_state() == NOT_CONNECTED);
|
||||
+ assert_true(test_article.protocol_state == NOT_CONNECTED);
|
||||
|
||||
test_article.connect_async.begin(
|
||||
CONNECT_TIMEOUT, null, this.async_completion
|
||||
);
|
||||
test_article.connect_async.end(async_result());
|
||||
- assert_true(test_article.get_protocol_state() == UNAUTHORIZED);
|
||||
+ assert_true(test_article.protocol_state == UNAUTHORIZED);
|
||||
|
||||
test_article.login_async.begin(
|
||||
new Credentials(PASSWORD, "test", "password"),
|
||||
@@ -162,11 +162,11 @@ class Geary.Imap.ClientSessionTest : TestCase {
|
||||
this.async_completion
|
||||
);
|
||||
test_article.login_async.end(async_result());
|
||||
- assert_true(test_article.get_protocol_state() == AUTHORIZED);
|
||||
+ assert_true(test_article.protocol_state == AUTHORIZED);
|
||||
|
||||
test_article.disconnect_async.begin(null, this.async_completion);
|
||||
test_article.disconnect_async.end(async_result());
|
||||
- assert_true(test_article.get_protocol_state() == NOT_CONNECTED);
|
||||
+ assert_true(test_article.protocol_state == NOT_CONNECTED);
|
||||
|
||||
TestServer.Result result = this.server.wait_for_script(this.main_loop);
|
||||
assert_true(
|
||||
@@ -185,17 +185,17 @@ class Geary.Imap.ClientSessionTest : TestCase {
|
||||
this.server.add_script_line(DISCONNECT, "");
|
||||
|
||||
var test_article = new ClientSession(new_endpoint(), new Quirks());
|
||||
- assert_true(test_article.get_protocol_state() == NOT_CONNECTED);
|
||||
+ assert_true(test_article.protocol_state == NOT_CONNECTED);
|
||||
|
||||
test_article.connect_async.begin(
|
||||
CONNECT_TIMEOUT, null, this.async_completion
|
||||
);
|
||||
test_article.connect_async.end(async_result());
|
||||
- assert_true(test_article.get_protocol_state() == UNAUTHORIZED);
|
||||
+ assert_true(test_article.protocol_state == UNAUTHORIZED);
|
||||
|
||||
test_article.logout_async.begin(null, this.async_completion);
|
||||
test_article.logout_async.end(async_result());
|
||||
- assert_true(test_article.get_protocol_state() == NOT_CONNECTED);
|
||||
+ assert_true(test_article.protocol_state == NOT_CONNECTED);
|
||||
|
||||
TestServer.Result result = this.server.wait_for_script(this.main_loop);
|
||||
assert_true(
|
||||
@@ -216,13 +216,13 @@ class Geary.Imap.ClientSessionTest : TestCase {
|
||||
this.server.add_script_line(DISCONNECT, "");
|
||||
|
||||
var test_article = new ClientSession(new_endpoint(), new Quirks());
|
||||
- assert_true(test_article.get_protocol_state() == NOT_CONNECTED);
|
||||
+ assert_true(test_article.protocol_state == NOT_CONNECTED);
|
||||
|
||||
test_article.connect_async.begin(
|
||||
CONNECT_TIMEOUT, null, this.async_completion
|
||||
);
|
||||
test_article.connect_async.end(async_result());
|
||||
- assert_true(test_article.get_protocol_state() == UNAUTHORIZED);
|
||||
+ assert_true(test_article.protocol_state == UNAUTHORIZED);
|
||||
|
||||
test_article.login_async.begin(
|
||||
new Credentials(PASSWORD, "test", "password"),
|
||||
@@ -230,11 +230,11 @@ class Geary.Imap.ClientSessionTest : TestCase {
|
||||
this.async_completion
|
||||
);
|
||||
test_article.login_async.end(async_result());
|
||||
- assert_true(test_article.get_protocol_state() == AUTHORIZED);
|
||||
+ assert_true(test_article.protocol_state == AUTHORIZED);
|
||||
|
||||
test_article.logout_async.begin(null, this.async_completion);
|
||||
test_article.logout_async.end(async_result());
|
||||
- assert_true(test_article.get_protocol_state() == NOT_CONNECTED);
|
||||
+ assert_true(test_article.protocol_state == NOT_CONNECTED);
|
||||
|
||||
TestServer.Result result = this.server.wait_for_script(this.main_loop);
|
||||
assert_true(
|
||||
@@ -261,13 +261,13 @@ class Geary.Imap.ClientSessionTest : TestCase {
|
||||
this.server.add_script_line(WAIT_FOR_DISCONNECT, "");
|
||||
|
||||
var test_article = new ClientSession(new_endpoint(), new Quirks());
|
||||
- assert_true(test_article.get_protocol_state() == NOT_CONNECTED);
|
||||
+ assert_true(test_article.protocol_state == NOT_CONNECTED);
|
||||
|
||||
test_article.connect_async.begin(
|
||||
CONNECT_TIMEOUT, null, this.async_completion
|
||||
);
|
||||
test_article.connect_async.end(async_result());
|
||||
- assert_true(test_article.get_protocol_state() == UNAUTHORIZED);
|
||||
+ assert_true(test_article.protocol_state == UNAUTHORIZED);
|
||||
|
||||
test_article.initiate_session_async.begin(
|
||||
new Credentials(PASSWORD, "test", "password"),
|
||||
@@ -305,13 +305,13 @@ class Geary.Imap.ClientSessionTest : TestCase {
|
||||
this.server.add_script_line(WAIT_FOR_DISCONNECT, "");
|
||||
|
||||
var test_article = new ClientSession(new_endpoint(), new Quirks());
|
||||
- assert_true(test_article.get_protocol_state() == NOT_CONNECTED);
|
||||
+ assert_true(test_article.protocol_state == NOT_CONNECTED);
|
||||
|
||||
test_article.connect_async.begin(
|
||||
CONNECT_TIMEOUT, null, this.async_completion
|
||||
);
|
||||
test_article.connect_async.end(async_result());
|
||||
- assert_true(test_article.get_protocol_state() == UNAUTHORIZED);
|
||||
+ assert_true(test_article.protocol_state == UNAUTHORIZED);
|
||||
|
||||
test_article.initiate_session_async.begin(
|
||||
new Credentials(PASSWORD, "test", "password"),
|
||||
@@ -368,13 +368,13 @@ class Geary.Imap.ClientSessionTest : TestCase {
|
||||
this.server.add_script_line(WAIT_FOR_DISCONNECT, "");
|
||||
|
||||
var test_article = new ClientSession(new_endpoint(), new Quirks());
|
||||
- assert_true(test_article.get_protocol_state() == NOT_CONNECTED);
|
||||
+ assert_true(test_article.protocol_state == NOT_CONNECTED);
|
||||
|
||||
test_article.connect_async.begin(
|
||||
CONNECT_TIMEOUT, null, this.async_completion
|
||||
);
|
||||
test_article.connect_async.end(async_result());
|
||||
- assert_true(test_article.get_protocol_state() == UNAUTHORIZED);
|
||||
+ assert_true(test_article.protocol_state == UNAUTHORIZED);
|
||||
|
||||
test_article.initiate_session_async.begin(
|
||||
new Credentials(PASSWORD, "test", "password"),
|
||||
diff --git a/test/integration/imap/client-session.vala b/test/integration/imap/client-session.vala
|
||||
index ca813b79..257d7319 100644
|
||||
--- a/test/integration/imap/client-session.vala
|
||||
+++ b/test/integration/imap/client-session.vala
|
||||
@@ -34,7 +34,7 @@ class Integration.Imap.ClientSession : TestCase {
|
||||
}
|
||||
|
||||
public override void tear_down() throws GLib.Error {
|
||||
- if (this.session.get_protocol_state() != NOT_CONNECTED) {
|
||||
+ if (this.session.protocol_state != NOT_CONNECTED) {
|
||||
this.session.disconnect_async.begin(null, this.async_completion);
|
||||
this.session.disconnect_async.end(async_result());
|
||||
}
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,79 @@
|
||||
From bd85c4f1a82c14fad0f909e5b1058c73d5b56c92 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Sun, 27 Sep 2020 19:57:52 +1000
|
||||
Subject: [PATCH 028/124] Composer.Widget: Fix criticals when "mailto:" has
|
||||
empty body
|
||||
|
||||
---
|
||||
src/client/composer/composer-widget.vala | 13 +++++++++----
|
||||
test/client/composer/composer-widget-test.vala | 10 ++++++++++
|
||||
2 files changed, 19 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/client/composer/composer-widget.vala b/src/client/composer/composer-widget.vala
|
||||
index ecc3fbfd..dab8cfd8 100644
|
||||
--- a/src/client/composer/composer-widget.vala
|
||||
+++ b/src/client/composer/composer-widget.vala
|
||||
@@ -575,8 +575,11 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
|
||||
Gee.HashMultiMap<string, string> headers = new Gee.HashMultiMap<string, string>();
|
||||
if (mailto.has_prefix(MAILTO_URI_PREFIX)) {
|
||||
// Parse the mailto link.
|
||||
+ string? email = null;
|
||||
string[] parts = mailto.substring(MAILTO_URI_PREFIX.length).split("?", 2);
|
||||
- string email = Uri.unescape_string(parts[0]);
|
||||
+ if (parts.length > 0) {
|
||||
+ email = Uri.unescape_string(parts[0]);
|
||||
+ }
|
||||
string[] params = parts.length == 2 ? parts[1].split("&") : new string[0];
|
||||
foreach (string param in params) {
|
||||
string[] param_parts = param.split("=", 2);
|
||||
@@ -587,14 +590,16 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
|
||||
}
|
||||
|
||||
// Assemble the headers.
|
||||
- if (email.length > 0 && headers.contains("to"))
|
||||
+ if (!Geary.String.is_empty_or_whitespace(email) &&
|
||||
+ headers.contains("to")) {
|
||||
this.to = "%s,%s".printf(
|
||||
email, Geary.Collection.first(headers.get("to"))
|
||||
);
|
||||
- else if (email.length > 0)
|
||||
+ } else if (!Geary.String.is_empty_or_whitespace(email)) {
|
||||
this.to = email;
|
||||
- else if (headers.contains("to"))
|
||||
+ } else if (headers.contains("to")) {
|
||||
this.to = Geary.Collection.first(headers.get("to"));
|
||||
+ }
|
||||
|
||||
if (headers.contains("cc"))
|
||||
this.cc = Geary.Collection.first(headers.get("cc"));
|
||||
diff --git a/test/client/composer/composer-widget-test.vala b/test/client/composer/composer-widget-test.vala
|
||||
index c35b52e4..6b31c943 100644
|
||||
--- a/test/client/composer/composer-widget-test.vala
|
||||
+++ b/test/client/composer/composer-widget-test.vala
|
||||
@@ -92,6 +92,7 @@ public class Composer.WidgetTest : TestCase {
|
||||
add_test("load_empty_body", load_empty_body);
|
||||
add_test("load_empty_body_to", load_empty_body_to);
|
||||
add_test("load_mailto", load_mailto);
|
||||
+ add_test("load_mailto_empty", load_mailto_empty);
|
||||
add_test("load_context_edit", load_context_edit);
|
||||
add_test("load_context_reply_sender", load_context_reply_sender);
|
||||
add_test("load_context_reply_sender_with_reply_to", load_context_reply_sender_with_reply_to);
|
||||
@@ -164,6 +165,15 @@ public class Composer.WidgetTest : TestCase {
|
||||
assert_equal(widget.to, "mailto@example.com");
|
||||
}
|
||||
|
||||
+ public void load_mailto_empty() throws GLib.Error {
|
||||
+ var widget = new Widget(this.application, this.config, this.account);
|
||||
+
|
||||
+ widget.load_mailto.begin("mailto:", this.async_completion);
|
||||
+ widget.load_mailto.end(async_result());
|
||||
+
|
||||
+ assert_equal(widget.to, "");
|
||||
+ }
|
||||
+
|
||||
public void load_context_edit() throws GLib.Error {
|
||||
var widget = new Widget(this.application, this.config, this.account);
|
||||
var email = load_email(MESSAGE_WITH_REPLY_TO);
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,58 @@
|
||||
From 70186163e8bcf1a0644669fe7c9b2b56dceef9b5 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Sun, 27 Sep 2020 22:46:40 +1000
|
||||
Subject: [PATCH 029/124] Composer.Widget: Fix critical when immediately
|
||||
detaching a new composer
|
||||
|
||||
New composers have no associated GLib Application instance, so when the
|
||||
main window is already showing a composer and another is opened, the
|
||||
new composer has no application to pass its window.
|
||||
|
||||
Fix by requiring `Composer.detach` be passed an application instance
|
||||
and find an appropriate instance at each call site.
|
||||
---
|
||||
src/client/application/application-main-window.vala | 2 +-
|
||||
src/client/composer/composer-widget.vala | 6 ++----
|
||||
2 files changed, 3 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/src/client/application/application-main-window.vala b/src/client/application/application-main-window.vala
|
||||
index e8428459..73b50e33 100644
|
||||
--- a/src/client/application/application-main-window.vala
|
||||
+++ b/src/client/application/application-main-window.vala
|
||||
@@ -875,7 +875,7 @@ public class Application.MainWindow :
|
||||
*/
|
||||
internal void show_composer(Composer.Widget composer) {
|
||||
if (this.has_composer) {
|
||||
- composer.detach();
|
||||
+ composer.detach(this.application);
|
||||
} else {
|
||||
// See if the currently displayed conversation contains
|
||||
// any of the composer's referred emails (preferring the
|
||||
diff --git a/src/client/composer/composer-widget.vala b/src/client/composer/composer-widget.vala
|
||||
index dab8cfd8..37e93fb4 100644
|
||||
--- a/src/client/composer/composer-widget.vala
|
||||
+++ b/src/client/composer/composer-widget.vala
|
||||
@@ -785,10 +785,8 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
|
||||
}
|
||||
|
||||
/** Detaches the composer and opens it in a new window. */
|
||||
- public void detach() {
|
||||
+ public void detach(Application.Client application) {
|
||||
Gtk.Widget? focused_widget = null;
|
||||
- var application = this.container.top_window.application as Application.Client;
|
||||
-
|
||||
if (this.container != null) {
|
||||
focused_widget = this.container.top_window.get_focus();
|
||||
this.container.close();
|
||||
@@ -2374,7 +2372,7 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
|
||||
}
|
||||
|
||||
private void on_detach() {
|
||||
- detach();
|
||||
+ detach(this.container.top_window.application as Application.Client);
|
||||
}
|
||||
|
||||
private void on_add_attachment() {
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,126 @@
|
||||
From 6fb365ebd45e283f770cde341c6332af66051ab6 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Sun, 27 Sep 2020 23:37:50 +1000
|
||||
Subject: [PATCH 030/124] Geary.RFC822.Message: Fix plain text file attachment
|
||||
line ending conversion
|
||||
|
||||
Since RFC822 requires CRLF for line endings, it's not possible for a MUA
|
||||
to determine the correct line ending for text attachments that use the
|
||||
default or quoted-printable transfer encoding.
|
||||
|
||||
As such, always use a binary encoding for all non-body message parts
|
||||
(which for now means always use Base64) so that line endings are
|
||||
explicitly encoded and hence always decoded correctly.
|
||||
|
||||
Fixes #1001
|
||||
---
|
||||
src/engine/rfc822/rfc822-message.vala | 65 +++++++++++++--------------
|
||||
1 file changed, 30 insertions(+), 35 deletions(-)
|
||||
|
||||
diff --git a/src/engine/rfc822/rfc822-message.vala b/src/engine/rfc822/rfc822-message.vala
|
||||
index 51563caf..e6cc17a4 100644
|
||||
--- a/src/engine/rfc822/rfc822-message.vala
|
||||
+++ b/src/engine/rfc822/rfc822-message.vala
|
||||
@@ -494,7 +494,7 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
|
||||
FileQueryInfoFlags.NONE
|
||||
);
|
||||
|
||||
- GMime.Part part = new GMime.Part.with_type("text", "plain");
|
||||
+ GMime.Part part = new GMime.Part();
|
||||
part.set_disposition(disposition.serialize());
|
||||
part.set_filename(file.get_basename());
|
||||
|
||||
@@ -504,10 +504,26 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
|
||||
);
|
||||
part.set_content_type(content_type);
|
||||
|
||||
+ // Always use a binary encoding since even when attaching
|
||||
+ // text/plain parts, the line ending must always be preserved
|
||||
+ // and this is not possible without a binary encoding. See
|
||||
+ // https://gitlab.gnome.org/GNOME/geary/-/issues/1001
|
||||
+ //
|
||||
+ // TODO: The actual content encoding should be set based on
|
||||
+ // the IMAP/SMTP server's supported encoding. For example, if
|
||||
+ // 8-bit or binary is supported, then those should be used
|
||||
+ // instead of Base64.
|
||||
+ part.set_content_encoding(BASE64);
|
||||
+
|
||||
GMime.StreamGIO stream = new GMime.StreamGIO(file);
|
||||
stream.set_owner(false);
|
||||
+ part.set_content(
|
||||
+ new GMime.DataWrapper.with_stream(
|
||||
+ stream, GMime.ContentEncoding.BINARY
|
||||
+ )
|
||||
+ );
|
||||
|
||||
- return yield finalise_attachment_part(stream, part, content_type, cancellable);
|
||||
+ return part;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -540,50 +556,29 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
|
||||
);
|
||||
}
|
||||
|
||||
- GMime.Part part = new GMime.Part.with_type("text", "plain");
|
||||
+ GMime.Part part = new GMime.Part();
|
||||
part.set_disposition(disposition.serialize());
|
||||
part.set_filename(basename);
|
||||
part.set_content_type(content_type);
|
||||
|
||||
- GMime.StreamMem stream = Utils.create_stream_mem(buffer);
|
||||
-
|
||||
- return yield finalise_attachment_part(stream, part, content_type, cancellable);
|
||||
- }
|
||||
-
|
||||
- /**
|
||||
- * Set encoding and content object on GMime part
|
||||
- */
|
||||
- private async GMime.Part finalise_attachment_part(GMime.Stream stream,
|
||||
- GMime.Part part,
|
||||
- GMime.ContentType content_type,
|
||||
- GLib.Cancellable? cancellable)
|
||||
- throws GLib.Error {
|
||||
-
|
||||
- // Text parts should be scanned fully to determine best
|
||||
- // (i.e. most compact) transport encoding to use, but
|
||||
- // that's usually fine since they tend to be
|
||||
- // small. Non-text parts are nearly always going to be
|
||||
- // binary, so we just assume they require Base64.
|
||||
+ // Always use a binary encoding since even when attaching
|
||||
+ // text/plain parts, the line ending must always be preserved
|
||||
+ // and this is not possible without a binary encoding. See
|
||||
+ // https://gitlab.gnome.org/GNOME/geary/-/issues/1001
|
||||
//
|
||||
- // XXX We should be setting the content encoding lazily
|
||||
- // though because if sending via a MTA that supports 8-bit
|
||||
- // or binary transfer modes, we can avoid using a content
|
||||
- // encoding altogether.
|
||||
- GMime.ContentEncoding encoding = BASE64;
|
||||
- if (content_type.is_type("text", Mime.ContentType.WILDCARD)) {
|
||||
- encoding = yield Utils.get_best_encoding(
|
||||
- stream,
|
||||
- GMime.EncodingConstraint.7BIT,
|
||||
- cancellable
|
||||
- );
|
||||
- }
|
||||
+ // TODO: The actual content encoding should be set based on
|
||||
+ // the IMAP/SMTP server's supported encoding. For example, if
|
||||
+ // 8-bit or binary is supported, then those should be used
|
||||
+ // instead of Base64.
|
||||
+ part.set_content_encoding(BASE64);
|
||||
|
||||
- part.set_content_encoding(encoding);
|
||||
+ GMime.StreamMem stream = Utils.create_stream_mem(buffer);
|
||||
part.set_content(
|
||||
new GMime.DataWrapper.with_stream(
|
||||
stream, GMime.ContentEncoding.BINARY
|
||||
)
|
||||
);
|
||||
+
|
||||
return part;
|
||||
}
|
||||
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,31 @@
|
||||
From b5abd3f9664c396ad57f177750973695c58e8b7f Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Mon, 28 Sep 2020 08:53:35 +1000
|
||||
Subject: [PATCH 031/124] build: Fix build failure due to missing client API
|
||||
|
||||
Don't use client lib vala ags when building the web process extension,
|
||||
since that will cause it to also write a VAPI with the same name as
|
||||
the client lib, causing the build to fail if the web process side wins
|
||||
that race.
|
||||
|
||||
Fixes #985
|
||||
---
|
||||
src/meson.build | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/meson.build b/src/meson.build
|
||||
index 87760e74..225777e8 100644
|
||||
--- a/src/meson.build
|
||||
+++ b/src/meson.build
|
||||
@@ -72,7 +72,7 @@ web_process = library('geary-web-process',
|
||||
webkit2gtk_web_extension,
|
||||
],
|
||||
include_directories: config_h_dir,
|
||||
- vala_args: client_vala_args,
|
||||
+ vala_args: geary_vala_args,
|
||||
c_args: geary_c_args,
|
||||
install: true,
|
||||
install_dir: web_extensions_dir
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,62 @@
|
||||
From 836a9ad3847d42087c4daeec81e84b7b7936714a Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Mon, 28 Sep 2020 22:26:23 +1000
|
||||
Subject: [PATCH 032/124] FormattedConversationData: Fix font settings being
|
||||
ignored under Flatpak
|
||||
|
||||
Get the interface font from Gtk.Settings instead of GLib.Settings since
|
||||
the latter can't actually access desktop settings under Flatpak.
|
||||
|
||||
Partial fix for #989
|
||||
|
||||
See also GNOME/glib#2213
|
||||
---
|
||||
.../formatted-conversation-data.vala | 16 +++++++++++++---
|
||||
1 file changed, 13 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/client/conversation-list/formatted-conversation-data.vala b/src/client/conversation-list/formatted-conversation-data.vala
|
||||
index f2b635f8..b21a931f 100644
|
||||
--- a/src/client/conversation-list/formatted-conversation-data.vala
|
||||
+++ b/src/client/conversation-list/formatted-conversation-data.vala
|
||||
@@ -100,6 +100,8 @@ public class FormattedConversationData : Geary.BaseObject {
|
||||
public Geary.Email? preview { get; private set; default = null; }
|
||||
|
||||
private Application.Configuration config;
|
||||
+
|
||||
+ private Gtk.Settings? gtk;
|
||||
private Pango.FontDescription font;
|
||||
|
||||
private Geary.App.Conversation? conversation = null;
|
||||
@@ -115,13 +117,13 @@ public class FormattedConversationData : Geary.BaseObject {
|
||||
Geary.Email preview,
|
||||
Gee.List<Geary.RFC822.MailboxAddress> account_owner_emails) {
|
||||
this.config = config;
|
||||
+ this.gtk = Gtk.Settings.get_default();
|
||||
this.conversation = conversation;
|
||||
this.account_owner_emails = account_owner_emails;
|
||||
this.use_to = conversation.base_folder.used_as.is_outgoing();
|
||||
|
||||
- this.font = Pango.FontDescription.from_string(
|
||||
- this.config.gnome_interface.get_string("font-name")
|
||||
- );
|
||||
+ this.gtk.notify["gtk-font-name"].connect(this.update_font);
|
||||
+ update_font();
|
||||
|
||||
// Load preview-related data.
|
||||
update_date_string();
|
||||
@@ -472,4 +474,12 @@ public class FormattedConversationData : Geary.BaseObject {
|
||||
return ink_rect;
|
||||
}
|
||||
|
||||
+ private void update_font() {
|
||||
+ var name = "Cantarell 11";
|
||||
+ if (this.gtk != null) {
|
||||
+ name = this.gtk.gtk_font_name;
|
||||
+ }
|
||||
+ this.font = Pango.FontDescription.from_string(name);
|
||||
+ }
|
||||
+
|
||||
}
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,64 @@
|
||||
From bfbc7f5d70f724010a9789ecefca6c1aa9f22962 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Tue, 29 Sep 2020 23:01:38 +1000
|
||||
Subject: [PATCH 033/124] client: Fix not all folders being displayed in
|
||||
additional main windows
|
||||
|
||||
Application.MainWindow: Sort folders already available in an account
|
||||
by path so that FolderListTree is able to add them all successfully.
|
||||
|
||||
Application.FolderContext: Implement Gee.Comparable so instances can
|
||||
be sorted.
|
||||
|
||||
Fixes #1004
|
||||
---
|
||||
src/client/application/application-folder-context.vala | 7 ++++++-
|
||||
src/client/application/application-main-window.vala | 7 ++++++-
|
||||
2 files changed, 12 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/client/application/application-folder-context.vala b/src/client/application/application-folder-context.vala
|
||||
index b85c901b..4ed47cf5 100644
|
||||
--- a/src/client/application/application-folder-context.vala
|
||||
+++ b/src/client/application/application-folder-context.vala
|
||||
@@ -9,7 +9,8 @@
|
||||
/**
|
||||
* Collects application state related to a single folder.
|
||||
*/
|
||||
-public class Application.FolderContext : Geary.BaseObject {
|
||||
+public class Application.FolderContext : Geary.BaseObject,
|
||||
+ Gee.Comparable<FolderContext> {
|
||||
|
||||
|
||||
/** Specifies different kinds of displayable email counts. */
|
||||
@@ -41,6 +42,10 @@ public class Application.FolderContext : Geary.BaseObject {
|
||||
update();
|
||||
}
|
||||
|
||||
+ public int compare_to(FolderContext other) {
|
||||
+ return this.folder.path.compare_to(other.folder.path);
|
||||
+ }
|
||||
+
|
||||
private void update() {
|
||||
this.display_name = Util.I18n.to_folder_display_name(this.folder);
|
||||
|
||||
diff --git a/src/client/application/application-main-window.vala b/src/client/application/application-main-window.vala
|
||||
index 73b50e33..47749019 100644
|
||||
--- a/src/client/application/application-main-window.vala
|
||||
+++ b/src/client/application/application-main-window.vala
|
||||
@@ -1010,7 +1010,12 @@ public class Application.MainWindow :
|
||||
to_add.commands.undone.connect(on_command_undo);
|
||||
to_add.commands.redone.connect(on_command_redo);
|
||||
|
||||
- add_folders(to_add.get_folders());
|
||||
+ // Sort the folders so FolderListTree adds them all
|
||||
+ // correctly
|
||||
+ var added = new Gee.TreeSet<FolderContext>();
|
||||
+ added.add_all(to_add.get_folders());
|
||||
+
|
||||
+ add_folders(added);
|
||||
this.accounts.add(to_add);
|
||||
}
|
||||
}
|
||||
--
|
||||
2.29.2
|
||||
|
6014
mail-client/geary/files/0034-Update-Hebrew-translation.patch
Normal file
6014
mail-client/geary/files/0034-Update-Hebrew-translation.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,251 @@
|
||||
From aaa2934acfb53243d21a4a68ac6486951ae4b045 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Sat, 3 Oct 2020 21:06:43 +1000
|
||||
Subject: [PATCH 035/124] meson_options.txt: Update to use meson best practices
|
||||
and clean up
|
||||
|
||||
Convert to use meson features for features. Reorganise and rename
|
||||
options for consistency. Make descriptions a bit less redundant.
|
||||
---
|
||||
desktop/meson.build | 2 +-
|
||||
meson.build | 27 +++++++---------
|
||||
meson_options.txt | 71 ++++++++++++++++++++++++------------------
|
||||
src/engine/meson.build | 2 +-
|
||||
src/meson.build | 4 +--
|
||||
test/meson.build | 2 +-
|
||||
6 files changed, 57 insertions(+), 51 deletions(-)
|
||||
|
||||
diff --git a/desktop/meson.build b/desktop/meson.build
|
||||
index f0c8a660..712db358 100644
|
||||
--- a/desktop/meson.build
|
||||
+++ b/desktop/meson.build
|
||||
@@ -77,7 +77,7 @@ endif
|
||||
# Contractor file (Elementary OS)
|
||||
#
|
||||
|
||||
-if install_contractor_file
|
||||
+if get_option('contractor').enabled()
|
||||
# Call msgfmt manually since gettext won't otherwise translate the
|
||||
# Description field. See merge req !50.
|
||||
msgfmt = find_program('msgfmt')
|
||||
diff --git a/meson.build b/meson.build
|
||||
index 240eacaa..82f0439d 100644
|
||||
--- a/meson.build
|
||||
+++ b/meson.build
|
||||
@@ -4,13 +4,6 @@ project('geary', [ 'vala', 'c' ],
|
||||
meson_version: '>= 0.50',
|
||||
)
|
||||
|
||||
-# Build-time configuration options
|
||||
-enable_valadoc = get_option('valadoc')
|
||||
-install_contractor_file = get_option('contractor')
|
||||
-iso_3166_xml = get_option('iso_3166_xml')
|
||||
-iso_639_xml = get_option('iso_639_xml')
|
||||
-reference_tracking = get_option('ref_tracking')
|
||||
-
|
||||
# Build type
|
||||
if get_option('profile') == 'development'
|
||||
profile = '.Devel'
|
||||
@@ -92,13 +85,13 @@ libpeas_gtk = dependency('libpeas-gtk-1.0', version: '>= 1.24.0')
|
||||
libsecret = dependency('libsecret-1', version: '>= 0.11')
|
||||
libsoup = dependency('libsoup-2.4', version: '>= 2.48')
|
||||
libunwind_dep = dependency(
|
||||
- 'libunwind', version: '>= 1.1', required: not get_option('libunwind_optional')
|
||||
+ 'libunwind', version: '>= 1.1', required: get_option('libunwind')
|
||||
)
|
||||
libunwind_generic_dep = dependency(
|
||||
- 'libunwind-generic', version: '>= 1.1', required: not get_option('libunwind_optional')
|
||||
+ 'libunwind-generic', version: '>= 1.1', required: get_option('libunwind')
|
||||
)
|
||||
libxml = dependency('libxml-2.0', version: '>= 2.7.8')
|
||||
-libytnef = dependency('libytnef', version: '>= 1.9.3', required: get_option('tnef-support'))
|
||||
+libytnef = dependency('libytnef', version: '>= 1.9.3', required: get_option('tnef'))
|
||||
posix = valac.find_library('posix')
|
||||
webkit2gtk_web_extension = dependency('webkit2gtk-web-extension-4.0', version: '>=' + target_webkit)
|
||||
|
||||
@@ -153,27 +146,31 @@ endif
|
||||
# Build glue
|
||||
#
|
||||
|
||||
+valadoc = find_program('valadoc', required: get_option('valadoc'))
|
||||
+
|
||||
vala_unit_proj = subproject(
|
||||
'vala-unit',
|
||||
default_options: [
|
||||
'install=false',
|
||||
- 'valadoc=@0@'.format(enable_valadoc)
|
||||
+ 'valadoc=@0@'.format(valadoc.found())
|
||||
]
|
||||
)
|
||||
vala_unit_dep = vala_unit_proj.get_variable('vala_unit_dep')
|
||||
|
||||
-if enable_valadoc
|
||||
- valadoc = find_program('valadoc')
|
||||
-endif
|
||||
-
|
||||
# Language detection
|
||||
+
|
||||
iso_codes_dir = iso_codes.get_pkgconfig_variable('prefix')/'share'/'xml'/'iso-codes'
|
||||
+
|
||||
+iso_639_xml = get_option('iso_639_xml')
|
||||
if iso_639_xml == ''
|
||||
iso_639_xml = iso_codes_dir / 'iso_639.xml'
|
||||
endif
|
||||
+
|
||||
+iso_3166_xml = get_option('iso_3166_xml')
|
||||
if iso_3166_xml == ''
|
||||
iso_3166_xml = iso_codes_dir / 'iso_3166.xml'
|
||||
endif
|
||||
+
|
||||
files(iso_639_xml, iso_3166_xml) # Check to make sure these exist
|
||||
|
||||
# Post-install scripts
|
||||
diff --git a/meson_options.txt b/meson_options.txt
|
||||
index a18438d4..968c2541 100644
|
||||
--- a/meson_options.txt
|
||||
+++ b/meson_options.txt
|
||||
@@ -1,11 +1,18 @@
|
||||
#
|
||||
# General build options
|
||||
#
|
||||
+
|
||||
option(
|
||||
- 'contractor',
|
||||
- type: 'boolean',
|
||||
- value: false,
|
||||
- description: 'Whether to install the contractor file (Elementary OS-specific).'
|
||||
+ 'profile',
|
||||
+ type: 'combo',
|
||||
+ value: 'default',
|
||||
+ choices: ['default','development','beta'],
|
||||
+ description: 'Specifies the application type to be built'
|
||||
+)
|
||||
+option(
|
||||
+ 'revno',
|
||||
+ type: 'string',
|
||||
+ description: 'Custom revision string (default extracted from "git describe")'
|
||||
)
|
||||
option(
|
||||
'iso_639_xml',
|
||||
@@ -19,41 +26,43 @@ option(
|
||||
value: '',
|
||||
description: 'Full path to the ISO 3166 XML file.'
|
||||
)
|
||||
-option(
|
||||
- 'libunwind_optional',
|
||||
- type: 'boolean',
|
||||
- value: false,
|
||||
- description: 'Determines if libunwind is required.'
|
||||
-)
|
||||
-option(
|
||||
- 'tnef-support',
|
||||
- type: 'boolean',
|
||||
- value: true,
|
||||
- description: 'Whether to support TNEF attachments (requires libytnef).'
|
||||
-)
|
||||
option(
|
||||
'valadoc',
|
||||
- type: 'boolean',
|
||||
- value: false,
|
||||
- description: 'Whether to build the documentation (requires valadoc).'
|
||||
+ type: 'feature',
|
||||
+ value: 'auto',
|
||||
+ description: 'Build API documentation'
|
||||
)
|
||||
|
||||
+#
|
||||
# Development options
|
||||
+#
|
||||
+
|
||||
option(
|
||||
- 'profile',
|
||||
- type: 'combo',
|
||||
- value: 'default',
|
||||
- choices: ['default','development','beta'],
|
||||
- description: 'Specifies the application type to be built'
|
||||
+ 'ref_tracking',
|
||||
+ type: 'feature',
|
||||
+ value: 'disabled',
|
||||
+ description: 'Enable Geary.BaseObject reference tracking'
|
||||
+)
|
||||
+
|
||||
+#
|
||||
+# Optional features
|
||||
+#
|
||||
+
|
||||
+option(
|
||||
+ 'contractor',
|
||||
+ type: 'feature',
|
||||
+ value: 'disabled',
|
||||
+ description: 'Install an Elementary OS a contractor file'
|
||||
)
|
||||
option(
|
||||
- 'ref_tracking',
|
||||
- type: 'boolean',
|
||||
- value: false,
|
||||
- description: 'Whether to use explicit reference tracking.'
|
||||
+ 'libunwind',
|
||||
+ type: 'feature',
|
||||
+ value: 'enabled',
|
||||
+ description: 'Use libunwind for back traces in problem reports.'
|
||||
)
|
||||
option(
|
||||
- 'revno',
|
||||
- type: 'string',
|
||||
- description: 'Custom revision string (default extracted from "git describe")'
|
||||
+ 'tnef',
|
||||
+ type: 'feature',
|
||||
+ value: 'enabled',
|
||||
+ description: 'Support Microsoft-proprietary TNEF attachments.'
|
||||
)
|
||||
diff --git a/src/engine/meson.build b/src/engine/meson.build
|
||||
index 0efd773e..1133f7b8 100644
|
||||
--- a/src/engine/meson.build
|
||||
+++ b/src/engine/meson.build
|
||||
@@ -349,7 +349,7 @@ if libunwind_dep.found()
|
||||
]
|
||||
endif
|
||||
|
||||
-if get_option('tnef-support')
|
||||
+if libytnef.found()
|
||||
engine_dependencies += libytnef
|
||||
engine_vala_args += [
|
||||
'-D', 'WITH_TNEF_SUPPORT'
|
||||
diff --git a/src/meson.build b/src/meson.build
|
||||
index 225777e8..14f08c18 100644
|
||||
--- a/src/meson.build
|
||||
+++ b/src/meson.build
|
||||
@@ -33,7 +33,7 @@ endif
|
||||
|
||||
# Symbols for valac's preprocessor must be defined as compiler args,
|
||||
# not in the code or in config.h
|
||||
-if reference_tracking
|
||||
+if get_option('ref_tracking').enabled()
|
||||
geary_vala_args += [ '--define=REF_TRACKING' ]
|
||||
endif
|
||||
|
||||
@@ -157,7 +157,7 @@ foreach dir : valadoc_vapi_dirs
|
||||
valadoc_vapidir_args += '--vapidir=@0@'.format(dir)
|
||||
endforeach
|
||||
|
||||
-if enable_valadoc
|
||||
+if valadoc.found()
|
||||
docs = custom_target('valadoc',
|
||||
build_by_default: true,
|
||||
depends: [client_lib, engine_lib],
|
||||
diff --git a/test/meson.build b/test/meson.build
|
||||
index fe3040dd..a32b2a82 100644
|
||||
--- a/test/meson.build
|
||||
+++ b/test/meson.build
|
||||
@@ -118,7 +118,7 @@ test_engine_dependencies += engine_dependencies
|
||||
|
||||
test_engine_vala_args = geary_vala_args
|
||||
|
||||
-if get_option('tnef-support')
|
||||
+if libytnef.found()
|
||||
test_engine_dependencies += libytnef
|
||||
test_engine_vala_args += [
|
||||
'-D', 'WITH_TNEF_SUPPORT'
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,143 @@
|
||||
From 23bd2507a7512664802db41b88ad375298d6b7d0 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Sat, 3 Oct 2020 21:59:01 +1000
|
||||
Subject: [PATCH 036/124] build: Update how build profiles are handled
|
||||
|
||||
Default to development build profile if a `.git` directory exists, else
|
||||
error out of build configuration.
|
||||
|
||||
This make `auto` the default build profile and if set and a `.git`
|
||||
directory is present default to `development`, else raise an error.
|
||||
Add some docs to INSTALL describing build profiles and update how they
|
||||
are used in the source to match.
|
||||
---
|
||||
INSTALL | 26 +++++++++++++++--
|
||||
meson.build | 28 +++++++++++++------
|
||||
meson_options.txt | 8 ++++--
|
||||
.../application/application-main-window.vala | 2 +-
|
||||
4 files changed, 50 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/INSTALL b/INSTALL
|
||||
index 6572303f..e445a409 100644
|
||||
--- a/INSTALL
|
||||
+++ b/INSTALL
|
||||
@@ -15,6 +15,28 @@ repository:
|
||||
A convenience Makefile for development only is also provided. To use
|
||||
it, simply invoke make from the top-level directory.
|
||||
|
||||
+Build profiles
|
||||
+--------------
|
||||
+
|
||||
+Geary can be built using a number of different build profiles, which
|
||||
+determine things like the application id, the location of stored data,
|
||||
+the name of the application and other visual elements that distinguish
|
||||
+release builds from other types.
|
||||
+
|
||||
+These can be set at build configuration time using the Meson `setup`
|
||||
+and `configure` commands, using the standard `-Dprofile=…` option. See
|
||||
+the `profile` option in `meson_options.txt` for the current list of
|
||||
+supported types.
|
||||
+
|
||||
+Maintainers must select the `release` build profile when packaging
|
||||
+non-test release builds, otherwise Geary will using branding and data
|
||||
+locations intended for development only.
|
||||
+
|
||||
+Note that setting the profile does not alter such things as cmopiler
|
||||
+options, use the standard Meson `--buildtype` argument for that.
|
||||
+
|
||||
+If built from
|
||||
+
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
@@ -94,5 +116,5 @@ the initial configuration step:
|
||||
meson --prefix=/usr -C build
|
||||
|
||||
---
|
||||
-Copyright 2016 Software Freedom Conservancy Inc.
|
||||
-Copyright 2018 Michael Gratton <mike@vee.net>
|
||||
+Copyright © 2016 Software Freedom Conservancy Inc.
|
||||
+Copyright © 2018-2020 Michael Gratton <mike@vee.net>
|
||||
diff --git a/meson.build b/meson.build
|
||||
index 82f0439d..1dc9e3aa 100644
|
||||
--- a/meson.build
|
||||
+++ b/meson.build
|
||||
@@ -4,16 +4,26 @@ project('geary', [ 'vala', 'c' ],
|
||||
meson_version: '>= 0.50',
|
||||
)
|
||||
|
||||
-# Build type
|
||||
-if get_option('profile') == 'development'
|
||||
- profile = '.Devel'
|
||||
+# Determine the type of build
|
||||
+profile = get_option('profile')
|
||||
+appid_suffix = ''
|
||||
+name_suffix = ''
|
||||
+if profile == 'auto'
|
||||
+ if run_command('[', '-d', '.git', ']').returncode() == 0
|
||||
+ profile = 'development'
|
||||
+ else
|
||||
+ error('No build profile specified, see INSTALL')
|
||||
+ endif
|
||||
+endif
|
||||
+
|
||||
+if profile == 'development'
|
||||
+ appid_suffix = '.Devel'
|
||||
name_suffix = ' (Development)'
|
||||
-elif get_option('profile') == 'beta'
|
||||
- profile = '.Beta'
|
||||
+elif profile == 'beta'
|
||||
+ appid_suffix = '.Beta'
|
||||
name_suffix = ' (Beta)'
|
||||
-else
|
||||
- profile = ''
|
||||
- name_suffix = ''
|
||||
+elif profile != 'release'
|
||||
+ error('Unknown build profile specified, see INSTALL')
|
||||
endif
|
||||
|
||||
# Configurable install dirs
|
||||
@@ -120,7 +130,7 @@ libmessagingmenu_dep = dependency('messaging-menu', version: '>= 12.10', require
|
||||
#
|
||||
|
||||
# Build variables
|
||||
-geary_id = 'org.gnome.Geary@0@'.format(profile)
|
||||
+geary_id = 'org.gnome.Geary@0@'.format(appid_suffix)
|
||||
geary_version = meson.project_version()
|
||||
revno = get_option('revno')
|
||||
if revno == ''
|
||||
diff --git a/meson_options.txt b/meson_options.txt
|
||||
index 968c2541..fcb8b9bf 100644
|
||||
--- a/meson_options.txt
|
||||
+++ b/meson_options.txt
|
||||
@@ -5,8 +5,12 @@
|
||||
option(
|
||||
'profile',
|
||||
type: 'combo',
|
||||
- value: 'default',
|
||||
- choices: ['default','development','beta'],
|
||||
+ choices: [
|
||||
+ 'auto',
|
||||
+ 'development',
|
||||
+ 'beta',
|
||||
+ 'release'
|
||||
+ ],
|
||||
description: 'Specifies the application type to be built'
|
||||
)
|
||||
option(
|
||||
diff --git a/src/client/application/application-main-window.vala b/src/client/application/application-main-window.vala
|
||||
index 47749019..aba5fa26 100644
|
||||
--- a/src/client/application/application-main-window.vala
|
||||
+++ b/src/client/application/application-main-window.vala
|
||||
@@ -487,7 +487,7 @@ public class Application.MainWindow :
|
||||
load_config(application.config);
|
||||
restore_saved_window_state();
|
||||
|
||||
- if (_PROFILE != "") {
|
||||
+ if (_PROFILE != "release") {
|
||||
this.get_style_context().add_class("devel");
|
||||
}
|
||||
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,43 @@
|
||||
From 456b6cd55ab4feb5c4c079df2b6aacbcfb69f246 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Sat, 3 Oct 2020 22:04:12 +1000
|
||||
Subject: [PATCH 037/124] Application.Client: Sort external const
|
||||
alphabetically
|
||||
|
||||
---
|
||||
src/client/application/application-client.vala | 14 +++++++-------
|
||||
1 file changed, 7 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/src/client/application/application-client.vala b/src/client/application/application-client.vala
|
||||
index 2bf4e094..7a450fa2 100644
|
||||
--- a/src/client/application/application-client.vala
|
||||
+++ b/src/client/application/application-client.vala
|
||||
@@ -7,18 +7,18 @@
|
||||
*/
|
||||
|
||||
// Defined by CMake build script.
|
||||
-extern const string _INSTALL_PREFIX;
|
||||
-extern const string _GSETTINGS_DIR;
|
||||
-extern const string _WEB_EXTENSIONS_DIR;
|
||||
-extern const string _PLUGINS_DIR;
|
||||
-extern const string _SOURCE_ROOT_DIR;
|
||||
-extern const string _BUILD_ROOT_DIR;
|
||||
extern const string GETTEXT_PACKAGE;
|
||||
extern const string _APP_ID;
|
||||
+extern const string _BUILD_ROOT_DIR;
|
||||
+extern const string _GSETTINGS_DIR;
|
||||
+extern const string _INSTALL_PREFIX;
|
||||
extern const string _NAME_SUFFIX;
|
||||
+extern const string _PLUGINS_DIR;
|
||||
extern const string _PROFILE;
|
||||
-extern const string _VERSION;
|
||||
extern const string _REVNO;
|
||||
+extern const string _SOURCE_ROOT_DIR;
|
||||
+extern const string _VERSION;
|
||||
+extern const string _WEB_EXTENSIONS_DIR;
|
||||
|
||||
|
||||
/**
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,317 @@
|
||||
From c240884f521da7356d9c5792a7568abc2dba5b38 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Sat, 3 Oct 2020 23:31:35 +1000
|
||||
Subject: [PATCH 038/124] Rename INSTALLING to BUILDING.md
|
||||
|
||||
Renamed since most people want to know how to build Geary when they
|
||||
get its source, not install it. Use MD extension to get formatting in
|
||||
gitlab.
|
||||
---
|
||||
BUILDING.md | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
INSTALL | 120 ---------------------------------------------------
|
||||
README.md | 9 ++--
|
||||
meson.build | 4 +-
|
||||
4 files changed, 129 insertions(+), 126 deletions(-)
|
||||
create mode 100644 BUILDING.md
|
||||
delete mode 100644 INSTALL
|
||||
|
||||
diff --git a/BUILDING.md b/BUILDING.md
|
||||
new file mode 100644
|
||||
index 00000000..c00b1901
|
||||
--- /dev/null
|
||||
+++ b/BUILDING.md
|
||||
@@ -0,0 +1,122 @@
|
||||
+Building and running Geary
|
||||
+==========================
|
||||
+
|
||||
+Geary uses the [Meson](http://mesonbuild.com) and
|
||||
+[Ninja](https://ninja-build.org) build systems. You will need these
|
||||
+and a number of other development libraries installed to build
|
||||
+Geary. See the Dependencies section below for a list of packages to
|
||||
+install.
|
||||
+
|
||||
+Building, running, tests and documentation
|
||||
+------------------------------------------
|
||||
+
|
||||
+To build Geary, run the following commands from the top-level
|
||||
+directory of the source code repository:
|
||||
+
|
||||
+```
|
||||
+meson build
|
||||
+ninja -C build
|
||||
+```
|
||||
+
|
||||
+Once built, Geary can be run directly from the build directory without
|
||||
+being installed:
|
||||
+
|
||||
+```
|
||||
+./build/src/geary
|
||||
+```
|
||||
+
|
||||
+Note that certain desktop integration (such as being listed in an
|
||||
+application menu) requires full installation to work correctly.
|
||||
+
|
||||
+To run the unit tests, use the Meson `test` command:
|
||||
+
|
||||
+```
|
||||
+meson test -C build
|
||||
+```
|
||||
+
|
||||
+API documentation will be built if `valadoc` is installed.
|
||||
+
|
||||
+Consult the Meson documentation for information about configuring the
|
||||
+build, installing, and so on.
|
||||
+
|
||||
+Build profiles
|
||||
+--------------
|
||||
+
|
||||
+Geary can be built using a number of different build profiles, which
|
||||
+determine things like the application id, the location of stored data,
|
||||
+the name of the application, icon and other visual elements.
|
||||
+
|
||||
+These can be set at build configuration time using the Meson `setup`
|
||||
+and `configure` commands, using the standard `-Dprofile=…` option. See
|
||||
+the `profile` option in `meson_options.txt` for the current list of
|
||||
+supported types.
|
||||
+
|
||||
+Maintainers must use the `release` build profile when packaging Geary,
|
||||
+otherwise when run it will use branding and data locations intended
|
||||
+for development only.
|
||||
+
|
||||
+Note that setting the profile does not alter such things as compiler
|
||||
+options, use the standard Meson `--buildtype` argument for that.
|
||||
+
|
||||
+Consult the Meson documentation for more information about configuring
|
||||
+options.
|
||||
+
|
||||
+Dependencies
|
||||
+------------
|
||||
+
|
||||
+Building Geary requires the following major libraries and tools:
|
||||
+
|
||||
+ * GTK+ 3
|
||||
+ * WebKitGTK+ 2
|
||||
+ * SQLite 3
|
||||
+ * Vala
|
||||
+
|
||||
+See the `meson.build` file in the top-level directory for the complete
|
||||
+list of required dependencies and minimum versions.
|
||||
+
|
||||
+Geary also requires SQLite to be built with the compiler flag
|
||||
+`-DSQLITE_ENABLE_FTS3`.
|
||||
+
|
||||
+All required libraries and tools are available from major Linux
|
||||
+distribution's package repositories:
|
||||
+
|
||||
+Installing dependencies on Fedora
|
||||
+---------------------------------
|
||||
+
|
||||
+Install them by running this command:
|
||||
+
|
||||
+```
|
||||
+sudo dnf install meson vala desktop-file-utils enchant2-devel \
|
||||
+ folks-devel gcr-devel glib2-devel gmime30-devel \
|
||||
+ gnome-online-accounts-devel gspell-devel gsound-devel \
|
||||
+ gtk3-devel iso-codes-devel itstool json-glib-devel \
|
||||
+ libappstream-glib-devel libgee-devel libhandy1-devel \
|
||||
+ libpeas-devel libsecret-devel libunwind-devel libxml2-devel \
|
||||
+ libytnef-devel sqlite-devel webkitgtk4-devel
|
||||
+```
|
||||
+
|
||||
+Installing dependencies on Ubuntu/Debian
|
||||
+----------------------------------------
|
||||
+
|
||||
+Install them by running this command:
|
||||
+
|
||||
+```
|
||||
+sudo apt-get install meson build-essential valac \
|
||||
+ desktop-file-utils iso-codes gettext itstool \
|
||||
+ libappstream-glib-dev libenchant-2-dev libfolks-dev \
|
||||
+ libgcr-3-dev libgee-0.8-dev libglib2.0-dev libgmime-3.0-dev \
|
||||
+ libgoa-1.0-dev libgspell-1-dev libgsound-dev libgtk-3-dev \
|
||||
+ libjson-glib-dev libhandy-1-dev libpeas-dev libsecret-1-dev \
|
||||
+ libsqlite3-dev libunwind-dev libwebkit2gtk-4.0-dev libxml2-dev \
|
||||
+ libytnef0-dev
|
||||
+```
|
||||
+
|
||||
+And for Ubuntu Messaging Menu integration:
|
||||
+
|
||||
+```
|
||||
+sudo apt-get install libmessaging-menu-dev
|
||||
+```
|
||||
+
|
||||
+---
|
||||
+Copyright © 2016 Software Freedom Conservancy Inc.
|
||||
+Copyright © 2018-2020 Michael Gratton <mike@vee.net>
|
||||
diff --git a/INSTALL b/INSTALL
|
||||
deleted file mode 100644
|
||||
index e445a409..00000000
|
||||
--- a/INSTALL
|
||||
+++ /dev/null
|
||||
@@ -1,120 +0,0 @@
|
||||
-Building & Installing Geary
|
||||
-===========================
|
||||
-
|
||||
-Building
|
||||
---------
|
||||
-
|
||||
-Geary uses the Meson <http://mesonbuild.com> and Ninja
|
||||
-<https://ninja-build.org> build systems. To build Geary, run the
|
||||
-following commands from the top-level directory of the source code
|
||||
-repository:
|
||||
-
|
||||
- meson build
|
||||
- ninja -C build
|
||||
-
|
||||
-A convenience Makefile for development only is also provided. To use
|
||||
-it, simply invoke make from the top-level directory.
|
||||
-
|
||||
-Build profiles
|
||||
---------------
|
||||
-
|
||||
-Geary can be built using a number of different build profiles, which
|
||||
-determine things like the application id, the location of stored data,
|
||||
-the name of the application and other visual elements that distinguish
|
||||
-release builds from other types.
|
||||
-
|
||||
-These can be set at build configuration time using the Meson `setup`
|
||||
-and `configure` commands, using the standard `-Dprofile=…` option. See
|
||||
-the `profile` option in `meson_options.txt` for the current list of
|
||||
-supported types.
|
||||
-
|
||||
-Maintainers must select the `release` build profile when packaging
|
||||
-non-test release builds, otherwise Geary will using branding and data
|
||||
-locations intended for development only.
|
||||
-
|
||||
-Note that setting the profile does not alter such things as cmopiler
|
||||
-options, use the standard Meson `--buildtype` argument for that.
|
||||
-
|
||||
-If built from
|
||||
-
|
||||
-Dependencies
|
||||
-------------
|
||||
-
|
||||
-Building Geary requires the following major libraries and tools:
|
||||
-
|
||||
- * GTK+ 3
|
||||
- * WebKitGTK+ 2
|
||||
- * SQLite 3
|
||||
- * Vala
|
||||
-
|
||||
-See the `meson.build` file in the top-level directory for the complete
|
||||
-list of required dependencies and minimum versions.
|
||||
-
|
||||
-Geary also requires SQLite to be built with the compiler flag
|
||||
-`-DSQLITE_ENABLE_FTS3`.
|
||||
-
|
||||
-All required libraries and tools are available from major Linux
|
||||
-distribution's package repositories:
|
||||
-
|
||||
-Installing dependencies on Fedora
|
||||
----------------------------------
|
||||
-
|
||||
-Install them by running this command:
|
||||
-
|
||||
- sudo dnf install meson vala desktop-file-utils enchant2-devel \
|
||||
- folks-devel gcr-devel glib2-devel gmime30-devel \
|
||||
- gnome-online-accounts-devel gspell-devel gsound-devel \
|
||||
- gtk3-devel iso-codes-devel itstool json-glib-devel \
|
||||
- libappstream-glib-devel libgee-devel libhandy1-devel \
|
||||
- libpeas-devel libsecret-devel libunwind-devel libxml2-devel \
|
||||
- libytnef-devel sqlite-devel webkitgtk4-devel
|
||||
-
|
||||
-Installing dependencies on Ubuntu/Debian
|
||||
-----------------------------------------
|
||||
-
|
||||
-Install them by running this command:
|
||||
-
|
||||
- sudo apt-get install meson build-essential valac \
|
||||
- desktop-file-utils iso-codes gettext itstool \
|
||||
- libappstream-glib-dev libenchant-2-dev libfolks-dev \
|
||||
- libgcr-3-dev libgee-0.8-dev libglib2.0-dev libgmime-3.0-dev \
|
||||
- libgoa-1.0-dev libgspell-1-dev libgsound-dev libgtk-3-dev \
|
||||
- libjson-glib-dev libhandy-1-dev libpeas-dev libsecret-1-dev \
|
||||
- libsqlite3-dev libunwind-dev libwebkit2gtk-4.0-dev libxml2-dev \
|
||||
- libytnef0-dev
|
||||
-
|
||||
-And for Ubuntu Messaging Menu integration:
|
||||
-
|
||||
- sudo apt-get install libmessaging-menu-dev
|
||||
-
|
||||
-Running
|
||||
--------
|
||||
-
|
||||
-If you wish to try Geary before installing it, you may execute it directly
|
||||
-from its build directory:
|
||||
-
|
||||
- ./build/src/geary
|
||||
-
|
||||
-Note that certain desktop integration (such as being listed in an
|
||||
-application menu) requires full installation.
|
||||
-
|
||||
-Installation
|
||||
-------------
|
||||
-
|
||||
-After Geary has built, install it by invoking the install target:
|
||||
-
|
||||
- ninja -C build install
|
||||
-
|
||||
-After installation, it can be uninstalled in the same way:
|
||||
-
|
||||
- ninja -C build uninstall
|
||||
-
|
||||
-By default, Geary will install under /usr/local. To install to a
|
||||
-different directory, set pass the --prefix to meson when performing
|
||||
-the initial configuration step:
|
||||
-
|
||||
- meson --prefix=/usr -C build
|
||||
-
|
||||
----
|
||||
-Copyright © 2016 Software Freedom Conservancy Inc.
|
||||
-Copyright © 2018-2020 Michael Gratton <mike@vee.net>
|
||||
diff --git a/README.md b/README.md
|
||||
index d99cd8aa..73c4e595 100644
|
||||
--- a/README.md
|
||||
+++ b/README.md
|
||||
@@ -17,11 +17,12 @@ for more information.
|
||||
|
||||
![Geary displaying a conversation](https://wiki.gnome.org/Apps/Geary?action=AttachFile&do=get&target=geary-3-32-main-window.png)
|
||||
|
||||
-Installation & Licensing
|
||||
-------------------------
|
||||
+Building & Licensing
|
||||
+--------------------
|
||||
|
||||
-Please consult the [INSTALL](./INSTALL) and [COPYING](./COPYING) files
|
||||
-for more information.
|
||||
+Please consult the [BUILDING.md](./BUILDING.md) and
|
||||
+[COPYING](./COPYING) files for more information about building Geary
|
||||
+and the licence granted by its copyright holders for redistribution.
|
||||
|
||||
Getting in Touch
|
||||
----------------
|
||||
diff --git a/meson.build b/meson.build
|
||||
index 1dc9e3aa..54bccfec 100644
|
||||
--- a/meson.build
|
||||
+++ b/meson.build
|
||||
@@ -12,7 +12,7 @@ if profile == 'auto'
|
||||
if run_command('[', '-d', '.git', ']').returncode() == 0
|
||||
profile = 'development'
|
||||
else
|
||||
- error('No build profile specified, see INSTALL')
|
||||
+ error('No build profile specified, see BUILDING.md')
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -23,7 +23,7 @@ elif profile == 'beta'
|
||||
appid_suffix = '.Beta'
|
||||
name_suffix = ' (Beta)'
|
||||
elif profile != 'release'
|
||||
- error('Unknown build profile specified, see INSTALL')
|
||||
+ error('Unknown build profile specified, see BUILDING.md')
|
||||
endif
|
||||
|
||||
# Configurable install dirs
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,43 @@
|
||||
From 436c22a4ada3538f7a624c654557471ef0099530 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Sat, 3 Oct 2020 23:33:41 +1000
|
||||
Subject: [PATCH 039/124] README.md: Minor improvements
|
||||
|
||||
---
|
||||
README.md | 9 +++++----
|
||||
1 file changed, 5 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/README.md b/README.md
|
||||
index 73c4e595..6ffcb86b 100644
|
||||
--- a/README.md
|
||||
+++ b/README.md
|
||||
@@ -6,7 +6,7 @@ Geary: Send and receive email
|
||||
|
||||
Geary is an email application built around conversations, for the
|
||||
GNOME 3 desktop. It allows you to read, find and send email with a
|
||||
-straightforward, modern interface.
|
||||
+straight-forward, modern interface.
|
||||
|
||||
Visit https://wiki.gnome.org/Apps/Geary for more information.
|
||||
|
||||
@@ -31,7 +31,8 @@ Getting in Touch
|
||||
* Support and discussion: See the `geary` tag on [GNOME Discourse](https://discourse.gnome.org/tags/c/applications/7/geary)
|
||||
* Matrix channel: [#geary:gnome.org](https://gnome.element.io/#/room/#geary:gnome.org)
|
||||
|
||||
-**Code Of Conduct**
|
||||
+Code Of Conduct
|
||||
+---------------
|
||||
|
||||
We follow the [Contributor Covenant](./code-of-conduct.md) as our
|
||||
Code of Conduct. All communications in project spaces are expected to
|
||||
@@ -48,5 +49,5 @@ Want to help improve Geary? Here are some ways to contribute:
|
||||
* Donate: https://wiki.gnome.org/Apps/Geary/Donate
|
||||
|
||||
---
|
||||
-Copyright 2016 Software Freedom Conservancy Inc.
|
||||
-Copyright 2017-2020 Michael Gratton <mike@vee.net>
|
||||
+Copyright © 2016 Software Freedom Conservancy Inc.
|
||||
+Copyright © 2017-2020 Michael Gratton <mike@vee.net>
|
||||
--
|
||||
2.29.2
|
||||
|
582
mail-client/geary/files/0041-Update-Indonesian-translation.patch
Normal file
582
mail-client/geary/files/0041-Update-Indonesian-translation.patch
Normal file
@ -0,0 +1,582 @@
|
||||
From d2a0694866dffb73c2f42471577fb96d05e69489 Mon Sep 17 00:00:00 2001
|
||||
From: Kukuh Syafaat <kukuhsyafaat@gnome.org>
|
||||
Date: Sun, 4 Oct 2020 08:34:11 +0000
|
||||
Subject: [PATCH 041/124] Update Indonesian translation
|
||||
|
||||
---
|
||||
po/id.po | 198 ++++++++++++++++++++++++++++---------------------------
|
||||
1 file changed, 102 insertions(+), 96 deletions(-)
|
||||
|
||||
diff --git a/po/id.po b/po/id.po
|
||||
index d01d1604..0e195fee 100644
|
||||
--- a/po/id.po
|
||||
+++ b/po/id.po
|
||||
@@ -11,8 +11,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: geary mainline\n"
|
||||
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/geary/issues\n"
|
||||
-"POT-Creation-Date: 2020-08-18 09:04+0000\n"
|
||||
-"PO-Revision-Date: 2020-08-21 23:43+0700\n"
|
||||
+"POT-Creation-Date: 2020-08-27 12:37+0000\n"
|
||||
+"PO-Revision-Date: 2020-08-28 22:22+0700\n"
|
||||
"Last-Translator: Kukuh Syafaat <kukuhsyafaat@gnome.org>\n"
|
||||
"Language-Team: Indonesian\n"
|
||||
"Language: id\n"
|
||||
@@ -48,7 +48,7 @@ msgstr "Surel"
|
||||
#: desktop/geary-autostart.desktop.in.in:5
|
||||
#: desktop/org.gnome.Geary.appdata.xml.in.in:15
|
||||
#: desktop/org.gnome.Geary.desktop.in.in:5
|
||||
-#: src/client/application/application-client.vala:32
|
||||
+#: src/client/application/application-client.vala:33
|
||||
msgid "Send and receive email"
|
||||
msgstr "Kirim dan terima surel"
|
||||
|
||||
@@ -813,143 +813,143 @@ msgstr "Berkas telah ada di \"%s\". Kalau ditimpa isi sebelumnya hilang."
|
||||
msgid "_Replace"
|
||||
msgstr "Timp_a"
|
||||
|
||||
-#: src/client/application/application-client.vala:33
|
||||
+#: src/client/application/application-client.vala:34
|
||||
msgid "Copyright 2016 Software Freedom Conservancy Inc."
|
||||
msgstr "Hak Cipta 2016 Software Freedom Conservancy Inc."
|
||||
|
||||
-#: src/client/application/application-client.vala:34
|
||||
+#: src/client/application/application-client.vala:35
|
||||
msgid "Copyright 2016-2020 Geary Development Team."
|
||||
msgstr "Hak Cipta 2016-2020 Tim Pengembang Geary."
|
||||
|
||||
-#: src/client/application/application-client.vala:36
|
||||
+#: src/client/application/application-client.vala:37
|
||||
msgid "Visit the Geary web site"
|
||||
msgstr "Kunjungi situs web Geary"
|
||||
|
||||
#. / Command line option
|
||||
-#: src/client/application/application-client.vala:96
|
||||
+#: src/client/application/application-client.vala:97
|
||||
msgid "Print debug logging"
|
||||
msgstr "Cetak log awakutu"
|
||||
|
||||
#. / Command line option
|
||||
-#: src/client/application/application-client.vala:99
|
||||
+#: src/client/application/application-client.vala:100
|
||||
msgid "Start with the main window hidden (deprecated)"
|
||||
msgstr "Mulai Geary dengan jendela utama tersembunyi (usang)"
|
||||
|
||||
#. / Command line option
|
||||
-#: src/client/application/application-client.vala:102
|
||||
+#: src/client/application/application-client.vala:103
|
||||
msgid "Enable WebKitGTK Inspector in web views"
|
||||
msgstr "Fungsikan WebKitGTK Inspector dalam tilikan web"
|
||||
|
||||
#. / Command line option
|
||||
-#: src/client/application/application-client.vala:105
|
||||
+#: src/client/application/application-client.vala:106
|
||||
msgid "Log conversation monitoring"
|
||||
msgstr "Catat pemantauan percakapan"
|
||||
|
||||
#. / Command line option
|
||||
-#: src/client/application/application-client.vala:108
|
||||
+#: src/client/application/application-client.vala:109
|
||||
msgid "Log IMAP network deserialization"
|
||||
msgstr "Log deserialisasi jaringan IMAP"
|
||||
|
||||
#. / Command line option. "Normalization" can also be called
|
||||
#. / "synchronization".
|
||||
-#: src/client/application/application-client.vala:112
|
||||
+#: src/client/application/application-client.vala:113
|
||||
msgid "Log folder normalization"
|
||||
msgstr "Catat normalisasi map"
|
||||
|
||||
#. / Command line option
|
||||
-#: src/client/application/application-client.vala:115
|
||||
+#: src/client/application/application-client.vala:116
|
||||
msgid "Log IMAP network activity"
|
||||
msgstr "Log aktivitas jaringan IMAP"
|
||||
|
||||
#. / Command line option. The IMAP replay queue is how changes
|
||||
#. / on the server are replicated on the client. It could
|
||||
#. / also be called the IMAP events queue.
|
||||
-#: src/client/application/application-client.vala:120
|
||||
+#: src/client/application/application-client.vala:121
|
||||
msgid "Log IMAP replay queue"
|
||||
msgstr "Catat antrian putar ulang IMAP"
|
||||
|
||||
#. / Command line option
|
||||
-#: src/client/application/application-client.vala:123
|
||||
+#: src/client/application/application-client.vala:124
|
||||
msgid "Log SMTP network activity"
|
||||
msgstr "Log aktivitas jaringan SMTP"
|
||||
|
||||
#. / Command line option
|
||||
-#: src/client/application/application-client.vala:126
|
||||
+#: src/client/application/application-client.vala:127
|
||||
msgid "Log database queries (generates lots of messages)"
|
||||
msgstr "Catat kuiri basis data (menimbulkan banyak pesan)"
|
||||
|
||||
#. / Command line option
|
||||
-#: src/client/application/application-client.vala:129
|
||||
+#: src/client/application/application-client.vala:130
|
||||
msgid "Perform a graceful quit"
|
||||
msgstr "Keluar secara anggun"
|
||||
|
||||
-#: src/client/application/application-client.vala:131
|
||||
+#: src/client/application/application-client.vala:132
|
||||
msgid "Open a new window"
|
||||
msgstr "Buka suatu jendela baru"
|
||||
|
||||
#. / Command line option
|
||||
-#: src/client/application/application-client.vala:134
|
||||
+#: src/client/application/application-client.vala:135
|
||||
msgid "Revoke all pinned TLS server certificates"
|
||||
msgstr "Cabut semua sertifikat peladen TLS yang di-pin"
|
||||
|
||||
#. / Command line option
|
||||
-#: src/client/application/application-client.vala:137
|
||||
+#: src/client/application/application-client.vala:138
|
||||
msgid "Display program version"
|
||||
msgstr "Tampilkan versi program"
|
||||
|
||||
#. / Application runtime information label
|
||||
-#: src/client/application/application-client.vala:261
|
||||
+#: src/client/application/application-client.vala:262
|
||||
msgid "Geary version"
|
||||
msgstr "Versi Geary"
|
||||
|
||||
#. / Application runtime information label
|
||||
-#: src/client/application/application-client.vala:263
|
||||
+#: src/client/application/application-client.vala:264
|
||||
msgid "Geary revision"
|
||||
msgstr "Revisi Geary"
|
||||
|
||||
#. / Application runtime information label
|
||||
-#: src/client/application/application-client.vala:265
|
||||
+#: src/client/application/application-client.vala:266
|
||||
msgid "GTK version"
|
||||
msgstr "Versi GTK"
|
||||
|
||||
#. / Applciation runtime information label
|
||||
-#: src/client/application/application-client.vala:272
|
||||
+#: src/client/application/application-client.vala:273
|
||||
msgid "GLib version"
|
||||
msgstr "Versi GLib"
|
||||
|
||||
#. / Application runtime information label
|
||||
-#: src/client/application/application-client.vala:279
|
||||
+#: src/client/application/application-client.vala:280
|
||||
msgid "WebKitGTK version"
|
||||
msgstr "Versi WebKitGTK"
|
||||
|
||||
#. / Application runtime information label
|
||||
-#: src/client/application/application-client.vala:286
|
||||
+#: src/client/application/application-client.vala:287
|
||||
msgid "Desktop environment"
|
||||
msgstr "Lingkungan desktop"
|
||||
|
||||
#. Translators: This is the file type displayed for
|
||||
#. attachments with unknown file types.
|
||||
-#: src/client/application/application-client.vala:288
|
||||
+#: src/client/application/application-client.vala:289
|
||||
#: src/client/components/components-attachment-pane.vala:91
|
||||
msgid "Unknown"
|
||||
msgstr "Tak dikenal"
|
||||
|
||||
#. / Application runtime information label
|
||||
-#: src/client/application/application-client.vala:318
|
||||
+#: src/client/application/application-client.vala:293
|
||||
msgid "Distribution name"
|
||||
msgstr "Nama distribusi"
|
||||
|
||||
#. / Application runtime information label
|
||||
-#: src/client/application/application-client.vala:323
|
||||
+#: src/client/application/application-client.vala:298
|
||||
msgid "Distribution release"
|
||||
msgstr "Rilis distribusi"
|
||||
|
||||
#. / Application runtime information label
|
||||
-#: src/client/application/application-client.vala:331
|
||||
+#: src/client/application/application-client.vala:303
|
||||
msgid "Installation prefix"
|
||||
msgstr "Prefiks instalasi"
|
||||
|
||||
-#: src/client/application/application-client.vala:584
|
||||
+#: src/client/application/application-client.vala:558
|
||||
#, c-format
|
||||
msgid "About %s"
|
||||
msgstr "Tentang %s"
|
||||
@@ -957,7 +957,7 @@ msgstr "Tentang %s"
|
||||
#. Translators: add your name and email address to receive
|
||||
#. credit in the About dialog For example: Yamada Taro
|
||||
#. <yamada.taro@example.com>
|
||||
-#: src/client/application/application-client.vala:588
|
||||
+#: src/client/application/application-client.vala:562
|
||||
msgid "translator-credits"
|
||||
msgstr ""
|
||||
"Andika Triwidada <andika@gmail.com>, 2012, 2013, 2016, 2017, 2019, 2020\n"
|
||||
@@ -966,13 +966,13 @@ msgstr ""
|
||||
|
||||
#. / Warning printed to the console when a deprecated
|
||||
#. / command line option is used.
|
||||
-#: src/client/application/application-client.vala:1066
|
||||
+#: src/client/application/application-client.vala:1046
|
||||
msgid "The `--hidden` option is deprecated and will be removed in the future."
|
||||
msgstr "Opsi '--hidden' usang dan akan dihapus di masa mendatang."
|
||||
|
||||
#. / Command line warning, string substitution
|
||||
#. / is the given argument
|
||||
-#: src/client/application/application-client.vala:1099
|
||||
+#: src/client/application/application-client.vala:1079
|
||||
#, c-format
|
||||
msgid "Unrecognised program argument: “%s”"
|
||||
msgstr "Argumen program tidak dikenal: \"%s\""
|
||||
@@ -1079,12 +1079,12 @@ msgid_plural "Conversations un-labelled as %s"
|
||||
msgstr[0] "Label %s dihapus dari percakapan"
|
||||
msgstr[1] "Label %s dihapus dari percakapan"
|
||||
|
||||
-#: src/client/application/application-controller.vala:1297
|
||||
+#: src/client/application/application-controller.vala:1320
|
||||
#, c-format
|
||||
msgid "Unable to open the database for %s"
|
||||
msgstr "Tak bisa membuka basis data bagi %s"
|
||||
|
||||
-#: src/client/application/application-controller.vala:1298
|
||||
+#: src/client/application/application-controller.vala:1321
|
||||
#, c-format
|
||||
msgid ""
|
||||
"There was an error opening the local mail database for this account. This is "
|
||||
@@ -1108,20 +1108,20 @@ msgstr ""
|
||||
"Membangun ulang basis data akan menghancurkan semua surel lokal dan "
|
||||
"lampirannya. <b>Surat pada peladen Anda tak akan terpengaruh.</b>"
|
||||
|
||||
-#: src/client/application/application-controller.vala:1300
|
||||
+#: src/client/application/application-controller.vala:1323
|
||||
msgid "_Rebuild"
|
||||
msgstr "_Bangun Ulang"
|
||||
|
||||
-#: src/client/application/application-controller.vala:1300
|
||||
+#: src/client/application/application-controller.vala:1323
|
||||
msgid "E_xit"
|
||||
msgstr "_Keluar"
|
||||
|
||||
-#: src/client/application/application-controller.vala:1310
|
||||
+#: src/client/application/application-controller.vala:1333
|
||||
#, c-format
|
||||
msgid "Unable to rebuild database for “%s”"
|
||||
msgstr "Tak bisa membangun ulang basis data bagi \"%s\""
|
||||
|
||||
-#: src/client/application/application-controller.vala:1311
|
||||
+#: src/client/application/application-controller.vala:1334
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Error during rebuild:\n"
|
||||
@@ -1134,34 +1134,34 @@ msgstr ""
|
||||
|
||||
#. / Translators: The label for an in-app notification. The
|
||||
#. / string substitution is a list of recipients of the email.
|
||||
-#: src/client/application/application-controller.vala:1478
|
||||
+#: src/client/application/application-controller.vala:1501
|
||||
#, c-format
|
||||
msgid "Email sent to %s"
|
||||
msgstr "Surel dikirim ke %s"
|
||||
|
||||
#. / Translators: The label for an in-app notification. The
|
||||
#. / string substitution is a list of recipients of the email.
|
||||
-#: src/client/application/application-controller.vala:2509
|
||||
+#: src/client/application/application-controller.vala:2491
|
||||
#, c-format
|
||||
msgid "Email to %s queued for delivery"
|
||||
msgstr "Surel ke %s diantrikan untuk pengiriman"
|
||||
|
||||
#. / Translators: The label for an in-app notification. The
|
||||
#. / string substitution is a list of recipients of the email.
|
||||
-#: src/client/application/application-controller.vala:2573
|
||||
+#: src/client/application/application-controller.vala:2555
|
||||
#, c-format
|
||||
msgid "Email to %s saved"
|
||||
msgstr "Surel ke %s disimpan"
|
||||
|
||||
#. / Translators: A label for an in-app notification.
|
||||
-#: src/client/application/application-controller.vala:2588
|
||||
-#: src/client/application/application-controller.vala:2646
|
||||
+#: src/client/application/application-controller.vala:2570
|
||||
+#: src/client/application/application-controller.vala:2628
|
||||
msgid "Composer could not be restored"
|
||||
msgstr "Penyusun tidak dapat dipulihkan"
|
||||
|
||||
#. / Translators: The label for an in-app notification. The
|
||||
#. / string substitution is a list of recipients of the email.
|
||||
-#: src/client/application/application-controller.vala:2631
|
||||
+#: src/client/application/application-controller.vala:2613
|
||||
#, c-format
|
||||
msgid "Email to %s discarded"
|
||||
msgstr "Surel ke %s dibuang"
|
||||
@@ -1304,7 +1304,7 @@ msgstr "Pemeriksa"
|
||||
#. / Translators: Title for Inspector logs pane
|
||||
#. / Translators: Title for problem report dialog logs pane
|
||||
#: src/client/components/components-inspector.vala:93
|
||||
-#: src/client/dialogs/dialogs-problem-details-dialog.vala:102
|
||||
+#: src/client/dialogs/dialogs-problem-details-dialog.vala:101
|
||||
msgid "Logs"
|
||||
msgstr "Log"
|
||||
|
||||
@@ -1312,21 +1312,21 @@ msgstr "Log"
|
||||
#. / Translators: Title for problem report system information
|
||||
#. / pane
|
||||
#: src/client/components/components-inspector.vala:97
|
||||
-#: src/client/dialogs/dialogs-problem-details-dialog.vala:105
|
||||
+#: src/client/dialogs/dialogs-problem-details-dialog.vala:104
|
||||
msgid "System"
|
||||
msgstr "Sistem"
|
||||
|
||||
#. Button label for saving problem report information
|
||||
#: src/client/components/components-inspector.vala:226
|
||||
#: src/client/components/components-inspector.vala:229
|
||||
-#: src/client/dialogs/dialogs-problem-details-dialog.vala:221
|
||||
-#: src/client/dialogs/dialogs-problem-details-dialog.vala:224
|
||||
-#: ui/problem-details-dialog.ui:42
|
||||
+#: src/client/dialogs/dialogs-problem-details-dialog.vala:220
|
||||
+#: src/client/dialogs/dialogs-problem-details-dialog.vala:223
|
||||
+#: ui/problem-details-dialog.ui:47
|
||||
msgid "Save As"
|
||||
msgstr "Simpan sebagai"
|
||||
|
||||
#: src/client/components/components-inspector.vala:230
|
||||
-#: src/client/dialogs/dialogs-problem-details-dialog.vala:225
|
||||
+#: src/client/dialogs/dialogs-problem-details-dialog.vala:224
|
||||
#: ui/accounts_editor_servers_pane.ui:17
|
||||
msgid "Cancel"
|
||||
msgstr "Batal"
|
||||
@@ -1375,7 +1375,7 @@ msgid "Preferences"
|
||||
msgstr "Preferensi"
|
||||
|
||||
#. / Translators: Preferences page title
|
||||
-#: src/client/components/components-preferences-window.vala:252
|
||||
+#: src/client/components/components-preferences-window.vala:250
|
||||
msgid "Plugins"
|
||||
msgstr "Pengaya"
|
||||
|
||||
@@ -1448,6 +1448,22 @@ msgstr "Lihat rincian teknis tentang kesalahan tersebut"
|
||||
msgid "_Retry"
|
||||
msgstr "_Ulangi"
|
||||
|
||||
+#: src/client/components/components-reflow-box.c:454
|
||||
+msgid "Spacing"
|
||||
+msgstr "Jarak"
|
||||
+
|
||||
+#: src/client/components/components-reflow-box.c:455
|
||||
+msgid "Spacing between children"
|
||||
+msgstr "Jarak antara anak"
|
||||
+
|
||||
+#: src/client/components/components-reflow-box.c:470
|
||||
+msgid "Row spacing"
|
||||
+msgstr "Jarak antar baris"
|
||||
+
|
||||
+#: src/client/components/components-reflow-box.c:471
|
||||
+msgid "Spacing between rows of children"
|
||||
+msgstr "Jarak antar baris anak "
|
||||
+
|
||||
#. / Translators: Search entry placeholder text
|
||||
#: src/client/components/components-search-bar.vala:12
|
||||
#: src/client/folder-list/folder-list-search-branch.vala:53
|
||||
@@ -1551,7 +1567,7 @@ msgid "_OK"
|
||||
msgstr "_OK"
|
||||
|
||||
#: src/client/components/stock.vala:19
|
||||
-#: src/client/plugin/mail-merge/mail-merge.vala:388
|
||||
+#: src/client/plugin/mail-merge/mail-merge.vala:392
|
||||
#: ui/password-dialog.glade:196
|
||||
msgid "_Cancel"
|
||||
msgstr "Ba_tal"
|
||||
@@ -1577,7 +1593,7 @@ msgid "_Help"
|
||||
msgstr "_Bantuan"
|
||||
|
||||
#: src/client/components/stock.vala:26
|
||||
-#: src/client/plugin/mail-merge/mail-merge.vala:387
|
||||
+#: src/client/plugin/mail-merge/mail-merge.vala:391
|
||||
#: ui/components-attachment-pane-menus.ui:7
|
||||
msgid "_Open"
|
||||
msgstr "_Buka"
|
||||
@@ -2038,8 +2054,8 @@ msgstr "Terjadi galat saat memroses sertifikat peladen"
|
||||
#. / Translators: Title for problem report dialog error
|
||||
#. / information pane
|
||||
#. Dialog title for displaying technical details of a problem. Same as the button that invokes it.
|
||||
-#: src/client/dialogs/dialogs-problem-details-dialog.vala:100
|
||||
-#: ui/problem-details-dialog.ui:12
|
||||
+#: src/client/dialogs/dialogs-problem-details-dialog.vala:99
|
||||
+#: ui/problem-details-dialog.ui:17
|
||||
msgid "Details"
|
||||
msgstr "Detail"
|
||||
|
||||
@@ -2091,12 +2107,6 @@ msgid_plural "%d results"
|
||||
msgstr[0] "%d hasil"
|
||||
msgstr[1] "%d hasil"
|
||||
|
||||
-#. Translators: This is an internal plugin so this name does not need
|
||||
-#. to be tanslated
|
||||
-#: src/client/plugin/desktop-notifications/desktop-notifications.plugin.desktop.in:6
|
||||
-msgid "Desktop Notifications"
|
||||
-msgstr "Pemberitahuan Desktop"
|
||||
-
|
||||
#. / Notification body when a message as been received
|
||||
#. / and other unread messages have not been
|
||||
#. / seen. First string substitution is the message
|
||||
@@ -2194,17 +2204,11 @@ msgstr "Kirim"
|
||||
#. Translators: Info bar button label for editing a draft
|
||||
#. email
|
||||
#: src/client/plugin/email-templates/email-templates.vala:305
|
||||
-#: src/client/plugin/mail-merge/mail-merge.vala:332
|
||||
+#: src/client/plugin/mail-merge/mail-merge.vala:336
|
||||
#: src/client/plugin/special-folders/special-folders.vala:187
|
||||
msgid "Edit"
|
||||
msgstr "Sunting"
|
||||
|
||||
-#. Translators: This is an internal plugin so this name does not need
|
||||
-#. to be tanslated
|
||||
-#: src/client/plugin/folder-highlight/folder-highlight.plugin.desktop.in:6
|
||||
-msgid "Folder Highlight"
|
||||
-msgstr "Sorot Folder"
|
||||
-
|
||||
#. / Translators: Menu item label for invoking mail
|
||||
#. / merge in composer
|
||||
#. / Translators: File chooser title after invoking mail
|
||||
@@ -2212,9 +2216,9 @@ msgstr "Sorot Folder"
|
||||
#. Translators: The name of the folder used to
|
||||
#. display merged email
|
||||
#: src/client/plugin/mail-merge/mail-merge.plugin.desktop.in:5
|
||||
-#: src/client/plugin/mail-merge/mail-merge.vala:284
|
||||
-#: src/client/plugin/mail-merge/mail-merge.vala:385
|
||||
-#: src/client/plugin/mail-merge/mail-merge.vala:484
|
||||
+#: src/client/plugin/mail-merge/mail-merge.vala:288
|
||||
+#: src/client/plugin/mail-merge/mail-merge.vala:389
|
||||
+#: src/client/plugin/mail-merge/mail-merge.vala:488
|
||||
msgid "Mail Merge"
|
||||
msgstr "Gabungan Surat"
|
||||
|
||||
@@ -2237,31 +2241,33 @@ msgstr "Jeda"
|
||||
#. Translators: Info bar description for the mail merge
|
||||
#. folder. The first string substitution the number of email
|
||||
#. already sent, the second is the total number to send.
|
||||
-#: src/client/plugin/mail-merge/mail-merge.vala:239
|
||||
+#: src/client/plugin/mail-merge/mail-merge.vala:240
|
||||
#, c-format
|
||||
msgid "Sent %u of %u"
|
||||
-msgstr "Terkirim %u dari %u"
|
||||
+msgid_plural "Sent %u of %u"
|
||||
+msgstr[0] "Terkirim %u dari %u"
|
||||
+msgstr[1] "Terkirim %u dari %u"
|
||||
|
||||
#. Translators: Infobar status label for an email mail merge
|
||||
#. template
|
||||
-#: src/client/plugin/mail-merge/mail-merge.vala:320
|
||||
+#: src/client/plugin/mail-merge/mail-merge.vala:324
|
||||
msgid "Mail merge template"
|
||||
msgstr "Templat gabungan surat"
|
||||
|
||||
#. Translators: Info bar button label for performing a
|
||||
#. mail-merge on an email template
|
||||
-#: src/client/plugin/mail-merge/mail-merge.vala:324
|
||||
+#: src/client/plugin/mail-merge/mail-merge.vala:328
|
||||
msgid "Merge"
|
||||
msgstr "Gabung"
|
||||
|
||||
#. / Translators: Action bar menu button label for
|
||||
#. / mail-merge plugin
|
||||
-#: src/client/plugin/mail-merge/mail-merge.vala:373
|
||||
+#: src/client/plugin/mail-merge/mail-merge.vala:377
|
||||
msgid "Insert field"
|
||||
msgstr "Sisipkan bidang"
|
||||
|
||||
#. / Translators: File chooser filer label
|
||||
-#: src/client/plugin/mail-merge/mail-merge.vala:392
|
||||
+#: src/client/plugin/mail-merge/mail-merge.vala:396
|
||||
msgid "Comma separated values (CSV)"
|
||||
msgstr "Nilai yang dipisahkan koma (CSV)"
|
||||
|
||||
@@ -2278,12 +2284,6 @@ msgstr "Menampilkan pemberitahuan Menu Perpesanan Unity atas surat baru"
|
||||
msgid "%s — New Messages"
|
||||
msgstr "%s - Pesan Baru"
|
||||
|
||||
-#. Translators: This is an internal plugin so this name does not need
|
||||
-#. to be tanslated.
|
||||
-#: src/client/plugin/notification-badge/notification-badge.plugin.desktop.in:6
|
||||
-msgid "Notification Badge"
|
||||
-msgstr "Lencana Pemberitahuan"
|
||||
-
|
||||
#: src/client/plugin/sent-sound/sent-sound.plugin.desktop.in:4
|
||||
msgid "Sent Sound"
|
||||
msgstr "Suara Terkirim"
|
||||
@@ -2292,12 +2292,6 @@ msgstr "Suara Terkirim"
|
||||
msgid "Plays the desktop sent-mail sound when an email is sent"
|
||||
msgstr "Memutar suara surat-terkirim desktopk etika surel dikirim"
|
||||
|
||||
-#. Translators: This is an internal plugin so this name does not need
|
||||
-#. to be tanslated.
|
||||
-#: src/client/plugin/special-folders/special-folders.plugin.desktop.in:6
|
||||
-msgid "Special Folders"
|
||||
-msgstr "Folder Khusus"
|
||||
-
|
||||
#. Translators: Info bar button label for emptying
|
||||
#. trash/spam folders
|
||||
#: src/client/plugin/special-folders/special-folders.vala:167
|
||||
@@ -3130,7 +3124,7 @@ msgstr "Buka lampiran yang dipilih"
|
||||
msgid "Save _All"
|
||||
msgstr "Simpan Semu_a"
|
||||
|
||||
-#: ui/components-inspector-error-view.ui:33
|
||||
+#: ui/components-inspector-error-view.ui:31
|
||||
msgid ""
|
||||
"If the problem is serious or persists, please save and send these details to "
|
||||
"one of the <a href=\"https://wiki.gnome.org/Apps/Geary/Contact\">contact "
|
||||
@@ -3142,13 +3136,13 @@ msgstr ""
|
||||
"lampirkan ke sebuah <a href=\"https://wiki.gnome.org/Apps/Geary/ReportingABug"
|
||||
"\">laporan kutu baru</a>."
|
||||
|
||||
-#: ui/components-inspector-error-view.ui:49
|
||||
+#: ui/components-inspector-error-view.ui:47
|
||||
msgid "Details:"
|
||||
msgstr "Detail:"
|
||||
|
||||
#. Tooltip for inspector button
|
||||
#. Tooltip for problem report button
|
||||
-#: ui/components-inspector.ui:19 ui/problem-details-dialog.ui:19
|
||||
+#: ui/components-inspector.ui:19 ui/problem-details-dialog.ui:24
|
||||
msgid "Search for matching log entries"
|
||||
msgstr "Cari entri log yang cocok"
|
||||
|
||||
@@ -3164,13 +3158,13 @@ msgstr "Tambahkan entri penanda ke log"
|
||||
|
||||
#. Tooltip for inspector button
|
||||
#. Tooltip for problem report button
|
||||
-#: ui/components-inspector.ui:81 ui/problem-details-dialog.ui:46
|
||||
+#: ui/components-inspector.ui:81 ui/problem-details-dialog.ui:51
|
||||
msgid "Save logs entries and details"
|
||||
msgstr "Simpan entri log dan rincian"
|
||||
|
||||
#. Tooltip for inspector button
|
||||
#. Tooltip for problem report button
|
||||
-#: ui/components-inspector.ui:101 ui/problem-details-dialog.ui:62
|
||||
+#: ui/components-inspector.ui:101 ui/problem-details-dialog.ui:67
|
||||
msgid "Copy to clipboard"
|
||||
msgstr "Salin ke papan klip"
|
||||
|
||||
@@ -3731,6 +3725,18 @@ msgstr "Otentik_asikan"
|
||||
msgid "Geary update in progress…"
|
||||
msgstr "Pemutakhiran Geary sedang berlangsung…"
|
||||
|
||||
+#~ msgid "Desktop Notifications"
|
||||
+#~ msgstr "Pemberitahuan Desktop"
|
||||
+
|
||||
+#~ msgid "Folder Highlight"
|
||||
+#~ msgstr "Sorot Folder"
|
||||
+
|
||||
+#~ msgid "Notification Badge"
|
||||
+#~ msgstr "Lencana Pemberitahuan"
|
||||
+
|
||||
+#~ msgid "Special Folders"
|
||||
+#~ msgstr "Folder Khusus"
|
||||
+
|
||||
#~ msgid "Displays desktop notifications when new email is delivered"
|
||||
#~ msgstr "Menampilkan pemberitahuan desktop ketika ada surat baru terkirim"
|
||||
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,23 @@
|
||||
From d5512753459d6c1324fae48b1e6fc08526515932 Mon Sep 17 00:00:00 2001
|
||||
From: Jordi Mas <jmas@softcatala.org>
|
||||
Date: Wed, 7 Oct 2020 08:14:38 +0200
|
||||
Subject: [PATCH 043/124] Fix accute in Catalan translation
|
||||
|
||||
---
|
||||
help/ca/ca.po | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/help/ca/ca.po b/help/ca/ca.po
|
||||
index ae243358..dbacd7ea 100644
|
||||
--- a/help/ca/ca.po
|
||||
+++ b/help/ca/ca.po
|
||||
@@ -1508,5 +1508,5 @@ msgid ""
|
||||
msgstr ""
|
||||
"En el mode text pla, el text es justificarà automàticament mitjançant salts "
|
||||
"de línies de manera que no tinguin més de 74 caràcters d'ample i, el text "
|
||||
-"sagnat es justificarà i se citarà utilitzant el caràcter \">,\" per a cada"
|
||||
+"sagnat es justificarà i se citarà utilitzant el caràcter \">\" per a cada"
|
||||
" nivell de cita."
|
||||
--
|
||||
2.29.2
|
||||
|
3431
mail-client/geary/files/0044-Update-Greek-translation.patch
Normal file
3431
mail-client/geary/files/0044-Update-Greek-translation.patch
Normal file
File diff suppressed because it is too large
Load Diff
172
mail-client/geary/files/0045-Drop-saving-the-paned-width.patch
Normal file
172
mail-client/geary/files/0045-Drop-saving-the-paned-width.patch
Normal file
@ -0,0 +1,172 @@
|
||||
From a1f74d24ff11869f108dc42016a648ce45999b70 Mon Sep 17 00:00:00 2001
|
||||
From: Adrien Plazas <kekun.plazas@laposte.net>
|
||||
Date: Thu, 16 Jan 2020 13:28:13 +0100
|
||||
Subject: [PATCH 045/124] Drop saving the paned width
|
||||
|
||||
This is needed to replace GtkPaned by HdyLeaflet. This breaks syncing
|
||||
the size of the headerbar with the rest of the window, it will be fixed
|
||||
in a later commit.
|
||||
---
|
||||
desktop/org.gnome.Geary.gschema.xml | 24 -------------------
|
||||
.../application-configuration.vala | 22 -----------------
|
||||
.../application/application-main-window.vala | 17 -------------
|
||||
src/client/components/main-toolbar.vala | 9 -------
|
||||
4 files changed, 72 deletions(-)
|
||||
|
||||
diff --git a/desktop/org.gnome.Geary.gschema.xml b/desktop/org.gnome.Geary.gschema.xml
|
||||
index bbbadc36..9850dffd 100644
|
||||
--- a/desktop/org.gnome.Geary.gschema.xml
|
||||
+++ b/desktop/org.gnome.Geary.gschema.xml
|
||||
@@ -21,24 +21,6 @@
|
||||
<description>The last recorded height of the application window.</description>
|
||||
</key>
|
||||
|
||||
- <key name="folder-list-pane-position" type="i">
|
||||
- <default>100</default>
|
||||
- <summary>Position of folder list pane</summary>
|
||||
- <description>Position of the folder list Paned grabber.</description>
|
||||
- </key>
|
||||
-
|
||||
- <key name="folder-list-pane-position-horizontal" type="i">
|
||||
- <default>-1</default>
|
||||
- <summary>Position of folder list pane when horizontal</summary>
|
||||
- <description>Position of the folder list Paned grabber in the horizontal orientation.</description>
|
||||
- </key>
|
||||
-
|
||||
- <key name="folder-list-pane-position-vertical" type="i">
|
||||
- <default>200</default>
|
||||
- <summary>Position of folder list pane when vertical</summary>
|
||||
- <description>Position of the folder list Paned grabber in the vertical orientation.</description>
|
||||
- </key>
|
||||
-
|
||||
<key name="folder-list-pane-horizontal" type="b">
|
||||
<default>true</default>
|
||||
<summary>Orientation of the folder list pane</summary>
|
||||
@@ -51,12 +33,6 @@
|
||||
<description>True if the formatting toolbar in the composer is shown.</description>
|
||||
</key>
|
||||
|
||||
- <key name="messages-pane-position" type="i">
|
||||
- <default>250</default>
|
||||
- <summary>Position of message list pane</summary>
|
||||
- <description>Position of the message list Paned grabber.</description>
|
||||
- </key>
|
||||
-
|
||||
<key name="autoselect" type="b">
|
||||
<default>true</default>
|
||||
<summary>Autoselect next message</summary>
|
||||
diff --git a/src/client/application/application-configuration.vala b/src/client/application/application-configuration.vala
|
||||
index 00c359c9..51a11bbf 100644
|
||||
--- a/src/client/application/application-configuration.vala
|
||||
+++ b/src/client/application/application-configuration.vala
|
||||
@@ -20,11 +20,7 @@ public class Application.Configuration : Geary.BaseObject {
|
||||
public const string CONVERSATION_VIEWER_ZOOM_KEY = "conversation-viewer-zoom";
|
||||
public const string DISPLAY_PREVIEW_KEY = "display-preview";
|
||||
public const string FOLDER_LIST_PANE_HORIZONTAL_KEY = "folder-list-pane-horizontal";
|
||||
- public const string FOLDER_LIST_PANE_POSITION_HORIZONTAL_KEY = "folder-list-pane-position-horizontal";
|
||||
- public const string FOLDER_LIST_PANE_POSITION_KEY = "folder-list-pane-position";
|
||||
- public const string FOLDER_LIST_PANE_POSITION_VERTICAL_KEY = "folder-list-pane-position-vertical";
|
||||
public const string FORMATTING_TOOLBAR_VISIBLE = "formatting-toolbar-visible";
|
||||
- public const string MESSAGES_PANE_POSITION_KEY = "messages-pane-position";
|
||||
public const string OPTIONAL_PLUGINS = "optional-plugins";
|
||||
public const string SEARCH_STRATEGY_KEY = "search-strategy";
|
||||
public const string SINGLE_KEY_SHORTCUTS = "single-key-shortcuts";
|
||||
@@ -90,19 +86,6 @@ public class Application.Configuration : Geary.BaseObject {
|
||||
get { return settings.get_boolean(WINDOW_MAXIMIZE_KEY); }
|
||||
}
|
||||
|
||||
- public int folder_list_pane_position_old {
|
||||
- get { return settings.get_int(FOLDER_LIST_PANE_POSITION_KEY); }
|
||||
- }
|
||||
-
|
||||
- public int folder_list_pane_position_horizontal {
|
||||
- get { return settings.get_int(FOLDER_LIST_PANE_POSITION_HORIZONTAL_KEY); }
|
||||
- set { settings.set_int(FOLDER_LIST_PANE_POSITION_HORIZONTAL_KEY, value); }
|
||||
- }
|
||||
-
|
||||
- public int folder_list_pane_position_vertical {
|
||||
- get { return settings.get_int(FOLDER_LIST_PANE_POSITION_VERTICAL_KEY); }
|
||||
- }
|
||||
-
|
||||
public bool folder_list_pane_horizontal {
|
||||
get { return settings.get_boolean(FOLDER_LIST_PANE_HORIZONTAL_KEY); }
|
||||
}
|
||||
@@ -112,11 +95,6 @@ public class Application.Configuration : Geary.BaseObject {
|
||||
set { settings.set_boolean(FORMATTING_TOOLBAR_VISIBLE, value); }
|
||||
}
|
||||
|
||||
- public int messages_pane_position {
|
||||
- get { return settings.get_int(MESSAGES_PANE_POSITION_KEY); }
|
||||
- set { settings.set_int(MESSAGES_PANE_POSITION_KEY, value); }
|
||||
- }
|
||||
-
|
||||
public bool autoselect {
|
||||
get { return settings.get_boolean(AUTOSELECT_KEY); }
|
||||
}
|
||||
diff --git a/src/client/application/application-main-window.vala b/src/client/application/application-main-window.vala
|
||||
index 47749019..48f8bae6 100644
|
||||
--- a/src/client/application/application-main-window.vala
|
||||
+++ b/src/client/application/application-main-window.vala
|
||||
@@ -1130,15 +1130,10 @@ public class Application.MainWindow :
|
||||
// This code both loads AND saves the pane positions with live updating. This is more
|
||||
// resilient against crashes because the value in dconf changes *immediately*, and
|
||||
// stays saved in the event of a crash.
|
||||
- config.bind(Configuration.MESSAGES_PANE_POSITION_KEY, this.conversations_paned, "position");
|
||||
config.bind(Configuration.WINDOW_WIDTH_KEY, this, "window-width");
|
||||
config.bind(Configuration.WINDOW_HEIGHT_KEY, this, "window-height");
|
||||
config.bind(Configuration.WINDOW_MAXIMIZE_KEY, this, "window-maximized");
|
||||
// Update to layout
|
||||
- if (config.folder_list_pane_position_horizontal == -1) {
|
||||
- config.folder_list_pane_position_horizontal = config.folder_list_pane_position_old;
|
||||
- config.messages_pane_position += config.folder_list_pane_position_old;
|
||||
- }
|
||||
config.settings.changed[
|
||||
Configuration.FOLDER_LIST_PANE_HORIZONTAL_KEY
|
||||
].connect(on_change_orientation);
|
||||
@@ -1655,23 +1650,11 @@ public class Application.MainWindow :
|
||||
this.folder_paned.orientation = horizontal ? Gtk.Orientation.HORIZONTAL :
|
||||
Gtk.Orientation.VERTICAL;
|
||||
|
||||
- int folder_list_width =
|
||||
- this.application.config.folder_list_pane_position_horizontal;
|
||||
if (horizontal) {
|
||||
- if (!initial)
|
||||
- this.conversations_paned.position += folder_list_width;
|
||||
this.folder_box.pack_start(status_bar, false, false);
|
||||
} else {
|
||||
- if (!initial)
|
||||
- this.conversations_paned.position -= folder_list_width;
|
||||
this.conversation_list_box.pack_start(status_bar, false, false);
|
||||
}
|
||||
-
|
||||
- this.application.config.bind(
|
||||
- horizontal
|
||||
- ? Configuration.FOLDER_LIST_PANE_POSITION_HORIZONTAL_KEY
|
||||
- : Configuration.FOLDER_LIST_PANE_POSITION_VERTICAL_KEY,
|
||||
- this.folder_paned, "position");
|
||||
}
|
||||
|
||||
private void update_headerbar() {
|
||||
diff --git a/src/client/components/main-toolbar.vala b/src/client/components/main-toolbar.vala
|
||||
index 31f87df6..aa263253 100644
|
||||
--- a/src/client/components/main-toolbar.vala
|
||||
+++ b/src/client/components/main-toolbar.vala
|
||||
@@ -59,15 +59,6 @@ public class MainToolbar : Gtk.Box {
|
||||
|
||||
|
||||
public MainToolbar(Application.Configuration config) {
|
||||
- // Sync headerbar width with left pane
|
||||
- config.bind(
|
||||
- Application.Configuration.MESSAGES_PANE_POSITION_KEY,
|
||||
- this,
|
||||
- "left-pane-width",
|
||||
- SettingsBindFlags.GET
|
||||
- );
|
||||
- this.bind_property("left-pane-width", this.folder_header, "width-request", BindingFlags.SYNC_CREATE);
|
||||
-
|
||||
if (config.desktop_environment != UNITY) {
|
||||
this.bind_property("account", this.folder_header, "title", BindingFlags.SYNC_CREATE);
|
||||
this.bind_property("folder", this.folder_header, "subtitle", BindingFlags.SYNC_CREATE);
|
||||
--
|
||||
2.29.2
|
||||
|
150
mail-client/geary/files/0046-Drop-the-2-panes-mode.patch
Normal file
150
mail-client/geary/files/0046-Drop-the-2-panes-mode.patch
Normal file
@ -0,0 +1,150 @@
|
||||
From fb311e1c822fb41782c7ff07525c77732a52a971 Mon Sep 17 00:00:00 2001
|
||||
From: Adrien Plazas <kekun.plazas@laposte.net>
|
||||
Date: Thu, 16 Jan 2020 13:17:58 +0100
|
||||
Subject: [PATCH 046/124] Drop the 2-panes mode
|
||||
|
||||
This won't be needed to save horizontal space when using HdyLeaflet, and
|
||||
it would make porting to it harder.
|
||||
---
|
||||
desktop/org.gnome.Geary.gschema.xml | 6 -----
|
||||
.../application-configuration.vala | 5 ----
|
||||
.../application/application-main-window.vala | 27 ++-----------------
|
||||
.../components-preferences-window.vala | 16 -----------
|
||||
4 files changed, 2 insertions(+), 52 deletions(-)
|
||||
|
||||
diff --git a/desktop/org.gnome.Geary.gschema.xml b/desktop/org.gnome.Geary.gschema.xml
|
||||
index 9850dffd..89354dc2 100644
|
||||
--- a/desktop/org.gnome.Geary.gschema.xml
|
||||
+++ b/desktop/org.gnome.Geary.gschema.xml
|
||||
@@ -21,12 +21,6 @@
|
||||
<description>The last recorded height of the application window.</description>
|
||||
</key>
|
||||
|
||||
- <key name="folder-list-pane-horizontal" type="b">
|
||||
- <default>true</default>
|
||||
- <summary>Orientation of the folder list pane</summary>
|
||||
- <description>True if the folder list Paned is in the horizontal orientation.</description>
|
||||
- </key>
|
||||
-
|
||||
<key name="formatting-toolbar-visible" type="b">
|
||||
<default>false</default>
|
||||
<summary>Show/hide formatting toolbar</summary>
|
||||
diff --git a/src/client/application/application-configuration.vala b/src/client/application/application-configuration.vala
|
||||
index 51a11bbf..48542df6 100644
|
||||
--- a/src/client/application/application-configuration.vala
|
||||
+++ b/src/client/application/application-configuration.vala
|
||||
@@ -19,7 +19,6 @@ public class Application.Configuration : Geary.BaseObject {
|
||||
public const string COMPOSE_AS_HTML_KEY = "compose-as-html";
|
||||
public const string CONVERSATION_VIEWER_ZOOM_KEY = "conversation-viewer-zoom";
|
||||
public const string DISPLAY_PREVIEW_KEY = "display-preview";
|
||||
- public const string FOLDER_LIST_PANE_HORIZONTAL_KEY = "folder-list-pane-horizontal";
|
||||
public const string FORMATTING_TOOLBAR_VISIBLE = "formatting-toolbar-visible";
|
||||
public const string OPTIONAL_PLUGINS = "optional-plugins";
|
||||
public const string SEARCH_STRATEGY_KEY = "search-strategy";
|
||||
@@ -86,10 +85,6 @@ public class Application.Configuration : Geary.BaseObject {
|
||||
get { return settings.get_boolean(WINDOW_MAXIMIZE_KEY); }
|
||||
}
|
||||
|
||||
- public bool folder_list_pane_horizontal {
|
||||
- get { return settings.get_boolean(FOLDER_LIST_PANE_HORIZONTAL_KEY); }
|
||||
- }
|
||||
-
|
||||
public bool formatting_toolbar_visible {
|
||||
get { return settings.get_boolean(FORMATTING_TOOLBAR_VISIBLE); }
|
||||
set { settings.set_boolean(FORMATTING_TOOLBAR_VISIBLE, value); }
|
||||
diff --git a/src/client/application/application-main-window.vala b/src/client/application/application-main-window.vala
|
||||
index 48f8bae6..0bec6614 100644
|
||||
--- a/src/client/application/application-main-window.vala
|
||||
+++ b/src/client/application/application-main-window.vala
|
||||
@@ -511,7 +511,8 @@ public class Application.MainWindow :
|
||||
});
|
||||
|
||||
setup_layout(application.config);
|
||||
- on_change_orientation();
|
||||
+ this.folder_paned.orientation = Gtk.Orientation.HORIZONTAL;
|
||||
+ this.folder_box.pack_start(status_bar, false, false);
|
||||
|
||||
update_command_actions();
|
||||
update_conversation_actions(NONE);
|
||||
@@ -1133,10 +1134,6 @@ public class Application.MainWindow :
|
||||
config.bind(Configuration.WINDOW_WIDTH_KEY, this, "window-width");
|
||||
config.bind(Configuration.WINDOW_HEIGHT_KEY, this, "window-height");
|
||||
config.bind(Configuration.WINDOW_MAXIMIZE_KEY, this, "window-maximized");
|
||||
- // Update to layout
|
||||
- config.settings.changed[
|
||||
- Configuration.FOLDER_LIST_PANE_HORIZONTAL_KEY
|
||||
- ].connect(on_change_orientation);
|
||||
}
|
||||
|
||||
private void restore_saved_window_state() {
|
||||
@@ -1637,26 +1634,6 @@ public class Application.MainWindow :
|
||||
}
|
||||
}
|
||||
|
||||
- private void on_change_orientation() {
|
||||
- bool horizontal = this.application.config.folder_list_pane_horizontal;
|
||||
- bool initial = true;
|
||||
-
|
||||
- if (this.status_bar.parent != null) {
|
||||
- this.status_bar.parent.remove(status_bar);
|
||||
- initial = false;
|
||||
- }
|
||||
-
|
||||
- GLib.Settings.unbind(this.folder_paned, "position");
|
||||
- this.folder_paned.orientation = horizontal ? Gtk.Orientation.HORIZONTAL :
|
||||
- Gtk.Orientation.VERTICAL;
|
||||
-
|
||||
- if (horizontal) {
|
||||
- this.folder_box.pack_start(status_bar, false, false);
|
||||
- } else {
|
||||
- this.conversation_list_box.pack_start(status_bar, false, false);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
private void update_headerbar() {
|
||||
update_title();
|
||||
if (this.selected_folder != null) {
|
||||
diff --git a/src/client/components/components-preferences-window.vala b/src/client/components/components-preferences-window.vala
|
||||
index b1bdfd7b..ea978a3a 100644
|
||||
--- a/src/client/components/components-preferences-window.vala
|
||||
+++ b/src/client/components/components-preferences-window.vala
|
||||
@@ -136,16 +136,6 @@ public class Components.PreferencesWindow : Hdy.PreferencesWindow {
|
||||
display_preview_row.activatable_widget = display_preview;
|
||||
display_preview_row.add(display_preview);
|
||||
|
||||
- var three_pane_view = new Gtk.Switch();
|
||||
- three_pane_view.valign = CENTER;
|
||||
-
|
||||
- var three_pane_view_row = new Hdy.ActionRow();
|
||||
- /// Translators: Preferences label
|
||||
- three_pane_view_row.title = _("Use _three pane view");
|
||||
- three_pane_view_row.use_underline = true;
|
||||
- three_pane_view_row.activatable_widget = three_pane_view;
|
||||
- three_pane_view_row.add(three_pane_view);
|
||||
-
|
||||
var single_key_shortucts = new Gtk.Switch();
|
||||
single_key_shortucts.valign = CENTER;
|
||||
|
||||
@@ -180,7 +170,6 @@ public class Components.PreferencesWindow : Hdy.PreferencesWindow {
|
||||
//group.description = _("General application preferences");
|
||||
group.add(autoselect_row);
|
||||
group.add(display_preview_row);
|
||||
- group.add(three_pane_view_row);
|
||||
group.add(single_key_shortucts_row);
|
||||
group.add(startup_notifications_row);
|
||||
|
||||
@@ -210,11 +199,6 @@ public class Components.PreferencesWindow : Hdy.PreferencesWindow {
|
||||
display_preview,
|
||||
"state"
|
||||
);
|
||||
- config.bind(
|
||||
- Application.Configuration.FOLDER_LIST_PANE_HORIZONTAL_KEY,
|
||||
- three_pane_view,
|
||||
- "state"
|
||||
- );
|
||||
config.bind(
|
||||
Application.Configuration.SINGLE_KEY_SHORTCUTS,
|
||||
single_key_shortucts,
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,186 @@
|
||||
From 850efb72380b3e2adc9f29af45a16bc1bd6e884b Mon Sep 17 00:00:00 2001
|
||||
From: Adrien Plazas <kekun.plazas@laposte.net>
|
||||
Date: Fri, 17 Jan 2020 18:51:39 +0100
|
||||
Subject: [PATCH 047/124] application-main-window: Move the conversations
|
||||
searchbar
|
||||
|
||||
Move it at above the conversations but not above the folders. This is
|
||||
needed to properly split the 3 panes.
|
||||
---
|
||||
.../application/application-main-window.vala | 4 +-
|
||||
ui/application-main-window.ui | 105 +++++++-----------
|
||||
2 files changed, 44 insertions(+), 65 deletions(-)
|
||||
|
||||
diff --git a/src/client/application/application-main-window.vala b/src/client/application/application-main-window.vala
|
||||
index 0bec6614..43289e33 100644
|
||||
--- a/src/client/application/application-main-window.vala
|
||||
+++ b/src/client/application/application-main-window.vala
|
||||
@@ -317,8 +317,6 @@ public class Application.MainWindow :
|
||||
[GtkChild]
|
||||
private Gtk.Box main_layout;
|
||||
[GtkChild]
|
||||
- private Gtk.Box search_bar_box;
|
||||
- [GtkChild]
|
||||
private Gtk.Paned folder_paned;
|
||||
[GtkChild]
|
||||
private Gtk.Paned conversations_paned;
|
||||
@@ -1210,7 +1208,7 @@ public class Application.MainWindow :
|
||||
// Search bar
|
||||
this.search_bar = new SearchBar(this.application.engine);
|
||||
this.search_bar.search_text_changed.connect(on_search);
|
||||
- this.search_bar_box.pack_start(this.search_bar, false, false, 0);
|
||||
+ this.conversation_list_box.pack_start(this.search_bar, false, false, 0);
|
||||
|
||||
// Folder list
|
||||
this.folder_list.folder_selected.connect(on_folder_selected);
|
||||
diff --git a/ui/application-main-window.ui b/ui/application-main-window.ui
|
||||
index f429a5ee..4a948294 100644
|
||||
--- a/ui/application-main-window.ui
|
||||
+++ b/ui/application-main-window.ui
|
||||
@@ -28,100 +28,81 @@
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<child>
|
||||
- <object class="GtkBox" id="search_bar_box">
|
||||
+ <object class="GtkPaned" id="folder_paned">
|
||||
<property name="visible">True</property>
|
||||
- <property name="can_focus">False</property>
|
||||
- <property name="orientation">vertical</property>
|
||||
+ <property name="can_focus">True</property>
|
||||
<child>
|
||||
- <object class="GtkPaned" id="folder_paned">
|
||||
+ <object class="GtkBox" id="folder_box">
|
||||
<property name="visible">True</property>
|
||||
- <property name="can_focus">True</property>
|
||||
+ <property name="can_focus">False</property>
|
||||
+ <property name="orientation">vertical</property>
|
||||
<child>
|
||||
- <object class="GtkBox" id="folder_box">
|
||||
+ <object class="GtkFrame" id="folder_frame">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
- <property name="orientation">vertical</property>
|
||||
+ <property name="label_xalign">0</property>
|
||||
+ <property name="shadow_type">in</property>
|
||||
<child>
|
||||
- <object class="GtkFrame" id="folder_frame">
|
||||
+ <object class="GtkScrolledWindow" id="folder_list_scrolled">
|
||||
+ <property name="width_request">100</property>
|
||||
<property name="visible">True</property>
|
||||
- <property name="can_focus">False</property>
|
||||
- <property name="label_xalign">0</property>
|
||||
- <property name="shadow_type">in</property>
|
||||
- <child>
|
||||
- <object class="GtkScrolledWindow" id="folder_list_scrolled">
|
||||
- <property name="width_request">100</property>
|
||||
- <property name="visible">True</property>
|
||||
- <property name="can_focus">True</property>
|
||||
- <property name="hscrollbar_policy">never</property>
|
||||
- </object>
|
||||
- </child>
|
||||
- <style>
|
||||
- <class name="geary-folder-frame"/>
|
||||
- </style>
|
||||
+ <property name="can_focus">True</property>
|
||||
+ <property name="hscrollbar_policy">never</property>
|
||||
</object>
|
||||
- <packing>
|
||||
- <property name="expand">True</property>
|
||||
- <property name="fill">True</property>
|
||||
- <property name="position">0</property>
|
||||
- </packing>
|
||||
</child>
|
||||
+ <style>
|
||||
+ <class name="geary-folder-frame"/>
|
||||
+ </style>
|
||||
</object>
|
||||
<packing>
|
||||
- <property name="resize">False</property>
|
||||
- <property name="shrink">False</property>
|
||||
+ <property name="expand">True</property>
|
||||
+ <property name="fill">True</property>
|
||||
+ <property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
+ </object>
|
||||
+ <packing>
|
||||
+ <property name="resize">False</property>
|
||||
+ <property name="shrink">False</property>
|
||||
+ </packing>
|
||||
+ </child>
|
||||
+ <child>
|
||||
+ <object class="GtkBox" id="conversation_list_box">
|
||||
+ <property name="visible">True</property>
|
||||
+ <property name="can_focus">False</property>
|
||||
+ <property name="orientation">vertical</property>
|
||||
<child>
|
||||
- <object class="GtkBox" id="conversation_list_box">
|
||||
+ <object class="GtkFrame" id="conversation_frame">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
- <property name="orientation">vertical</property>
|
||||
+ <property name="label_xalign">0</property>
|
||||
+ <property name="shadow_type">in</property>
|
||||
<child>
|
||||
- <object class="GtkFrame">
|
||||
+ <object class="GtkScrolledWindow" id="conversation_list_scrolled">
|
||||
+ <property name="width_request">250</property>
|
||||
<property name="visible">True</property>
|
||||
- <property name="can_focus">False</property>
|
||||
- <property name="label_xalign">0</property>
|
||||
- <property name="shadow_type">in</property>
|
||||
- <child>
|
||||
- <object class="GtkScrolledWindow" id="conversation_list_scrolled">
|
||||
- <property name="width_request">250</property>
|
||||
- <property name="visible">True</property>
|
||||
- <property name="can_focus">True</property>
|
||||
- </object>
|
||||
- </child>
|
||||
- <style>
|
||||
- <class name="geary-conversation-frame"/>
|
||||
- </style>
|
||||
+ <property name="can_focus">True</property>
|
||||
</object>
|
||||
- <packing>
|
||||
- <property name="expand">True</property>
|
||||
- <property name="fill">True</property>
|
||||
- <property name="pack_type">end</property>
|
||||
- <property name="position">0</property>
|
||||
- </packing>
|
||||
</child>
|
||||
<style>
|
||||
- <class name="geary-conversation-list-box"/>
|
||||
+ <class name="geary-conversation-frame"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
- <property name="resize">True</property>
|
||||
- <property name="shrink">False</property>
|
||||
+ <property name="expand">True</property>
|
||||
+ <property name="fill">True</property>
|
||||
+ <property name="pack_type">end</property>
|
||||
+ <property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
- <style>
|
||||
- <class name="geary-sidebar-pane-separator"/>
|
||||
- </style>
|
||||
</object>
|
||||
<packing>
|
||||
- <property name="expand">True</property>
|
||||
- <property name="fill">True</property>
|
||||
- <property name="pack_type">end</property>
|
||||
- <property name="position">0</property>
|
||||
+ <property name="resize">True</property>
|
||||
+ <property name="shrink">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<style>
|
||||
- <class name="sidebar"/>
|
||||
+ <class name="geary-sidebar-pane-separator"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,206 @@
|
||||
From 94ab7e5ac6b282e07edf8966da5c69e4fdba0cc8 Mon Sep 17 00:00:00 2001
|
||||
From: Adrien Plazas <kekun.plazas@laposte.net>
|
||||
Date: Sat, 18 Jan 2020 09:16:32 +0100
|
||||
Subject: [PATCH 048/124] main-toolbar: Split the folder header
|
||||
|
||||
Split it into a folder header and a conversations header. This is needed
|
||||
to properly split the 3 panes.
|
||||
|
||||
Fixes https://gitlab.gnome.org/GNOME/geary/issues/442.
|
||||
---
|
||||
src/client/components/main-toolbar.vala | 12 ++-
|
||||
ui/main-toolbar.ui | 108 +++++++++++++++---------
|
||||
2 files changed, 77 insertions(+), 43 deletions(-)
|
||||
|
||||
diff --git a/src/client/components/main-toolbar.vala b/src/client/components/main-toolbar.vala
|
||||
index aa263253..4ee02079 100644
|
||||
--- a/src/client/components/main-toolbar.vala
|
||||
+++ b/src/client/components/main-toolbar.vala
|
||||
@@ -28,10 +28,14 @@ public class MainToolbar : Gtk.Box {
|
||||
[GtkChild]
|
||||
private Gtk.HeaderBar folder_header;
|
||||
[GtkChild]
|
||||
- private Gtk.ToggleButton search_conversations_button;
|
||||
- [GtkChild]
|
||||
private Gtk.MenuButton main_menu_button;
|
||||
|
||||
+ // Conversations header elements
|
||||
+ [GtkChild]
|
||||
+ private Gtk.HeaderBar conversations_header;
|
||||
+ [GtkChild]
|
||||
+ private Gtk.ToggleButton search_conversations_button;
|
||||
+
|
||||
// Conversation header elements
|
||||
[GtkChild]
|
||||
private Gtk.HeaderBar conversation_header;
|
||||
@@ -60,8 +64,8 @@ public class MainToolbar : Gtk.Box {
|
||||
|
||||
public MainToolbar(Application.Configuration config) {
|
||||
if (config.desktop_environment != UNITY) {
|
||||
- this.bind_property("account", this.folder_header, "title", BindingFlags.SYNC_CREATE);
|
||||
- this.bind_property("folder", this.folder_header, "subtitle", BindingFlags.SYNC_CREATE);
|
||||
+ this.bind_property("account", this.conversations_header, "title", BindingFlags.SYNC_CREATE);
|
||||
+ this.bind_property("folder", this.conversations_header, "subtitle", BindingFlags.SYNC_CREATE);
|
||||
}
|
||||
|
||||
// Assemble the main/mark menus
|
||||
diff --git a/ui/main-toolbar.ui b/ui/main-toolbar.ui
|
||||
index 874f5b4b..732a01b9 100644
|
||||
--- a/ui/main-toolbar.ui
|
||||
+++ b/ui/main-toolbar.ui
|
||||
@@ -11,68 +11,97 @@
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
- <object class="GtkHeaderBar" id="folder_header">
|
||||
+ <object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
- <property name="show_close_button" bind-source="MainToolbar" bind-property="show_close_button" bind-flags="sync-create"/>
|
||||
<child>
|
||||
- <object class="GtkButton" id="compose_new_message_button">
|
||||
+ <object class="GtkHeaderBar" id="folder_header">
|
||||
<property name="visible">True</property>
|
||||
- <property name="can_focus">True</property>
|
||||
- <property name="focus_on_click">False</property>
|
||||
- <property name="receives_default">False</property>
|
||||
- <property name="tooltip_text" translatable="yes" context="tooltip">Compose Message</property>
|
||||
- <property name="action_name">app.compose</property>
|
||||
- <property name="always_show_image">True</property>
|
||||
+ <property name="can_focus">False</property>
|
||||
+ <property name="show_close_button" bind-source="MainToolbar" bind-property="show_close_button" bind-flags="sync-create"/>
|
||||
+ <property name="title">Mail</property>
|
||||
<child>
|
||||
- <object class="GtkImage" id="compose_new_message_image">
|
||||
+ <object class="GtkMenuButton" id="main_menu_button">
|
||||
<property name="visible">True</property>
|
||||
- <property name="can_focus">False</property>
|
||||
- <property name="icon_name">text-editor-symbolic</property>
|
||||
+ <property name="can_focus">True</property>
|
||||
+ <property name="focus_on_click">False</property>
|
||||
+ <property name="receives_default">False</property>
|
||||
+ <property name="always_show_image">True</property>
|
||||
+ <child>
|
||||
+ <object class="GtkImage" id="main_menu_image">
|
||||
+ <property name="visible">True</property>
|
||||
+ <property name="can_focus">False</property>
|
||||
+ <property name="icon_name">open-menu-symbolic</property>
|
||||
+ </object>
|
||||
+ </child>
|
||||
</object>
|
||||
+ <packing>
|
||||
+ <property name="pack_type">end</property>
|
||||
+ <property name="position">1</property>
|
||||
+ </packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
- <object class="GtkMenuButton" id="main_menu_button">
|
||||
+ <object class="GtkSeparator" id="folder_separator">
|
||||
<property name="visible">True</property>
|
||||
- <property name="can_focus">True</property>
|
||||
- <property name="focus_on_click">False</property>
|
||||
- <property name="receives_default">False</property>
|
||||
- <property name="always_show_image">True</property>
|
||||
- <child>
|
||||
- <object class="GtkImage" id="main_menu_image">
|
||||
- <property name="visible">True</property>
|
||||
- <property name="can_focus">False</property>
|
||||
- <property name="icon_name">open-menu-symbolic</property>
|
||||
- </object>
|
||||
- </child>
|
||||
+ <property name="can_focus">False</property>
|
||||
+ <property name="orientation">vertical</property>
|
||||
+ <style>
|
||||
+ <class name="sidebar"/>
|
||||
+ </style>
|
||||
</object>
|
||||
<packing>
|
||||
- <property name="pack_type">end</property>
|
||||
+ <property name="expand">False</property>
|
||||
+ <property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
- <object class="GtkToggleButton" id="search_conversations_button">
|
||||
+ <object class="GtkHeaderBar" id="conversations_header">
|
||||
<property name="visible">True</property>
|
||||
- <property name="can_focus">True</property>
|
||||
- <property name="focus_on_click">False</property>
|
||||
- <property name="receives_default">False</property>
|
||||
- <property name="tooltip_text" translatable="yes">Toggle search bar</property>
|
||||
- <property name="always_show_image">True</property>
|
||||
+ <property name="can_focus">False</property>
|
||||
+ <property name="show_close_button" bind-source="MainToolbar" bind-property="show_close_button" bind-flags="sync-create"/>
|
||||
<child>
|
||||
- <object class="GtkImage" id="search_conversations_image">
|
||||
+ <object class="GtkButton" id="compose_new_message_button">
|
||||
<property name="visible">True</property>
|
||||
- <property name="can_focus">False</property>
|
||||
- <property name="icon_name">preferences-system-search-symbolic</property>
|
||||
+ <property name="can_focus">True</property>
|
||||
+ <property name="focus_on_click">False</property>
|
||||
+ <property name="receives_default">False</property>
|
||||
+ <property name="tooltip_text" translatable="yes" context="tooltip">Compose Message</property>
|
||||
+ <property name="action_name">app.compose</property>
|
||||
+ <property name="always_show_image">True</property>
|
||||
+ <child>
|
||||
+ <object class="GtkImage" id="compose_new_message_image">
|
||||
+ <property name="visible">True</property>
|
||||
+ <property name="can_focus">False</property>
|
||||
+ <property name="icon_name">text-editor-symbolic</property>
|
||||
+ </object>
|
||||
+ </child>
|
||||
</object>
|
||||
</child>
|
||||
+ <child>
|
||||
+ <object class="GtkToggleButton" id="search_conversations_button">
|
||||
+ <property name="visible">True</property>
|
||||
+ <property name="can_focus">True</property>
|
||||
+ <property name="focus_on_click">False</property>
|
||||
+ <property name="receives_default">False</property>
|
||||
+ <property name="tooltip_text" translatable="yes">Toggle search bar</property>
|
||||
+ <property name="always_show_image">True</property>
|
||||
+ <child>
|
||||
+ <object class="GtkImage" id="search_conversations_image">
|
||||
+ <property name="visible">True</property>
|
||||
+ <property name="can_focus">False</property>
|
||||
+ <property name="icon_name">preferences-system-search-symbolic</property>
|
||||
+ </object>
|
||||
+ </child>
|
||||
+ </object>
|
||||
+ <packing>
|
||||
+ <property name="pack_type">end</property>
|
||||
+ <property name="position">3</property>
|
||||
+ </packing>
|
||||
+ </child>
|
||||
</object>
|
||||
- <packing>
|
||||
- <property name="pack_type">end</property>
|
||||
- <property name="position">3</property>
|
||||
- </packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
@@ -82,7 +111,7 @@
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
- <object class="GtkSeparator" id="header_separator">
|
||||
+ <object class="GtkSeparator" id="conversations_separator">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
@@ -342,6 +371,7 @@
|
||||
<object class="HdyHeaderGroup" id="header_group">
|
||||
<headerbars>
|
||||
<headerbar name="folder_header"/>
|
||||
+ <headerbar name="conversations_header"/>
|
||||
<headerbar name="conversation_header"/>
|
||||
</headerbars>
|
||||
</object>
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,55 @@
|
||||
From 7d4a61d431e072dbcacda2d089b587fe52257da6 Mon Sep 17 00:00:00 2001
|
||||
From: Adrien Plazas <kekun.plazas@laposte.net>
|
||||
Date: Thu, 16 Jan 2020 13:50:03 +0100
|
||||
Subject: [PATCH 049/124] main-toolbar: Add add_to_size_groups()
|
||||
|
||||
This will be used to sync requests of the panes.
|
||||
---
|
||||
src/client/components/main-toolbar.vala | 18 ++++++++++++++++++
|
||||
1 file changed, 18 insertions(+)
|
||||
|
||||
diff --git a/src/client/components/main-toolbar.vala b/src/client/components/main-toolbar.vala
|
||||
index 4ee02079..6ea472a8 100644
|
||||
--- a/src/client/components/main-toolbar.vala
|
||||
+++ b/src/client/components/main-toolbar.vala
|
||||
@@ -30,12 +30,18 @@ public class MainToolbar : Gtk.Box {
|
||||
[GtkChild]
|
||||
private Gtk.MenuButton main_menu_button;
|
||||
|
||||
+ [GtkChild]
|
||||
+ private Gtk.Separator folder_separator;
|
||||
+
|
||||
// Conversations header elements
|
||||
[GtkChild]
|
||||
private Gtk.HeaderBar conversations_header;
|
||||
[GtkChild]
|
||||
private Gtk.ToggleButton search_conversations_button;
|
||||
|
||||
+ [GtkChild]
|
||||
+ private Gtk.Separator conversations_separator;
|
||||
+
|
||||
// Conversation header elements
|
||||
[GtkChild]
|
||||
private Gtk.HeaderBar conversation_header;
|
||||
@@ -105,6 +111,18 @@ public class MainToolbar : Gtk.Box {
|
||||
update_conversation_buttons();
|
||||
}
|
||||
|
||||
+ public void add_to_size_groups(Gtk.SizeGroup folder_group,
|
||||
+ Gtk.SizeGroup folder_separator_group,
|
||||
+ Gtk.SizeGroup conversations_group,
|
||||
+ Gtk.SizeGroup conversations_separator_group,
|
||||
+ Gtk.SizeGroup conversation_group) {
|
||||
+ folder_group.add_widget(folder_header);
|
||||
+ folder_separator_group.add_widget(folder_separator);
|
||||
+ conversations_group.add_widget(conversations_header);
|
||||
+ conversations_separator_group.add_widget(conversations_separator);
|
||||
+ conversation_group.add_widget(conversation_header);
|
||||
+ }
|
||||
+
|
||||
// Updates tooltip text depending on number of conversations selected.
|
||||
private void update_conversation_buttons() {
|
||||
this.mark_message_button.tooltip_text = ngettext(
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,82 @@
|
||||
From edfb1a2cf371ab743cbf804cbc4d34b7e4cfb8c6 Mon Sep 17 00:00:00 2001
|
||||
From: Adrien Plazas <kekun.plazas@laposte.net>
|
||||
Date: Thu, 16 Jan 2020 13:52:03 +0100
|
||||
Subject: [PATCH 050/124] application-main-window: Sync the pane size request
|
||||
|
||||
Bind each pane's elements minimum size requests via size groups.
|
||||
---
|
||||
.../application/application-main-window.vala | 17 +++++++++++++++
|
||||
ui/application-main-window.ui | 21 +++++++++++++++++++
|
||||
2 files changed, 38 insertions(+)
|
||||
|
||||
diff --git a/src/client/application/application-main-window.vala b/src/client/application/application-main-window.vala
|
||||
index 43289e33..4c6d1038 100644
|
||||
--- a/src/client/application/application-main-window.vala
|
||||
+++ b/src/client/application/application-main-window.vala
|
||||
@@ -328,6 +328,17 @@ public class Application.MainWindow :
|
||||
private Gtk.Box conversation_list_box;
|
||||
[GtkChild]
|
||||
private Gtk.ScrolledWindow conversation_list_scrolled;
|
||||
+ [GtkChild]
|
||||
+ private Gtk.SizeGroup folder_size_group;
|
||||
+ [GtkChild]
|
||||
+ private Gtk.SizeGroup folder_separator_size_group;
|
||||
+ [GtkChild]
|
||||
+ private Gtk.SizeGroup conversations_size_group;
|
||||
+ [GtkChild]
|
||||
+ private Gtk.SizeGroup conversations_separator_size_group;
|
||||
+ [GtkChild]
|
||||
+ private Gtk.SizeGroup conversation_size_group;
|
||||
+
|
||||
[GtkChild]
|
||||
private Gtk.Overlay overlay;
|
||||
|
||||
@@ -1239,9 +1250,15 @@ public class Application.MainWindow :
|
||||
);
|
||||
|
||||
this.conversations_paned.pack2(this.conversation_viewer, true, false);
|
||||
+ this.conversation_size_group.add_widget(this.conversation_viewer);
|
||||
|
||||
// Main toolbar
|
||||
this.main_toolbar = new MainToolbar(config);
|
||||
+ this.main_toolbar.add_to_size_groups(this.folder_size_group,
|
||||
+ this.folder_separator_size_group,
|
||||
+ this.conversations_size_group,
|
||||
+ this.conversations_separator_size_group,
|
||||
+ this.conversation_size_group);
|
||||
this.main_toolbar.move_folder_menu.folder_selected.connect(on_move_conversation);
|
||||
this.main_toolbar.copy_folder_menu.folder_selected.connect(on_copy_conversation);
|
||||
this.main_toolbar.bind_property("search-open", this.search_bar, "search-mode-enabled",
|
||||
diff --git a/ui/application-main-window.ui b/ui/application-main-window.ui
|
||||
index 4a948294..872f31bd 100644
|
||||
--- a/ui/application-main-window.ui
|
||||
+++ b/ui/application-main-window.ui
|
||||
@@ -138,4 +138,25 @@
|
||||
<class name="geary-main-window"/>
|
||||
</style>
|
||||
</template>
|
||||
+ <object class="GtkSizeGroup" id="folder_size_group">
|
||||
+ <property name="mode">horizontal</property>
|
||||
+ <widgets>
|
||||
+ <widget name="folder_box"/>
|
||||
+ </widgets>
|
||||
+ </object>
|
||||
+ <object class="GtkSizeGroup" id="folder_separator_size_group">
|
||||
+ <property name="mode">horizontal</property>
|
||||
+ </object>
|
||||
+ <object class="GtkSizeGroup" id="conversations_size_group">
|
||||
+ <property name="mode">horizontal</property>
|
||||
+ <widgets>
|
||||
+ <widget name="conversation_list_box"/>
|
||||
+ </widgets>
|
||||
+ </object>
|
||||
+ <object class="GtkSizeGroup" id="conversations_separator_size_group">
|
||||
+ <property name="mode">horizontal</property>
|
||||
+ </object>
|
||||
+ <object class="GtkSizeGroup" id="conversation_size_group">
|
||||
+ <property name="mode">horizontal</property>
|
||||
+ </object>
|
||||
</interface>
|
||||
--
|
||||
2.29.2
|
||||
|
338
mail-client/geary/files/0051-Use-leaflets-in-the-UI.patch
Normal file
338
mail-client/geary/files/0051-Use-leaflets-in-the-UI.patch
Normal file
@ -0,0 +1,338 @@
|
||||
From 12a7101ba55bb646161e9997485036744121f542 Mon Sep 17 00:00:00 2001
|
||||
From: Adrien Plazas <kekun.plazas@laposte.net>
|
||||
Date: Thu, 24 Oct 2019 14:36:04 +0200
|
||||
Subject: [PATCH 051/124] Use leaflets in the UI
|
||||
|
||||
There is no way to navigate into the app, but it's a start.
|
||||
|
||||
v2: replace expand with child vexpand
|
||||
---
|
||||
.../application/application-main-window.vala | 8 +--
|
||||
src/client/components/main-toolbar.vala | 5 +-
|
||||
.../conversation-viewer.vala | 4 ++
|
||||
ui/application-main-window.ui | 52 ++++++++++++++-----
|
||||
ui/geary.css | 11 ++++
|
||||
ui/main-toolbar.ui | 33 +++++++-----
|
||||
6 files changed, 81 insertions(+), 32 deletions(-)
|
||||
|
||||
diff --git a/src/client/application/application-main-window.vala b/src/client/application/application-main-window.vala
|
||||
index 4c6d1038..b56079cf 100644
|
||||
--- a/src/client/application/application-main-window.vala
|
||||
+++ b/src/client/application/application-main-window.vala
|
||||
@@ -317,9 +317,9 @@ public class Application.MainWindow :
|
||||
[GtkChild]
|
||||
private Gtk.Box main_layout;
|
||||
[GtkChild]
|
||||
- private Gtk.Paned folder_paned;
|
||||
+ private Hdy.Leaflet main_leaflet;
|
||||
[GtkChild]
|
||||
- private Gtk.Paned conversations_paned;
|
||||
+ private Hdy.Leaflet conversations_leaflet;
|
||||
[GtkChild]
|
||||
private Gtk.Box folder_box;
|
||||
[GtkChild]
|
||||
@@ -520,7 +520,6 @@ public class Application.MainWindow :
|
||||
});
|
||||
|
||||
setup_layout(application.config);
|
||||
- this.folder_paned.orientation = Gtk.Orientation.HORIZONTAL;
|
||||
this.folder_box.pack_start(status_bar, false, false);
|
||||
|
||||
update_command_actions();
|
||||
@@ -1249,8 +1248,9 @@ public class Application.MainWindow :
|
||||
on_conversation_view_added
|
||||
);
|
||||
|
||||
- this.conversations_paned.pack2(this.conversation_viewer, true, false);
|
||||
+ this.conversation_viewer.hexpand = true;
|
||||
this.conversation_size_group.add_widget(this.conversation_viewer);
|
||||
+ this.main_leaflet.add_with_properties(this.conversation_viewer, "name", "conversation", null);
|
||||
|
||||
// Main toolbar
|
||||
this.main_toolbar = new MainToolbar(config);
|
||||
diff --git a/src/client/components/main-toolbar.vala b/src/client/components/main-toolbar.vala
|
||||
index 6ea472a8..286546d5 100644
|
||||
--- a/src/client/components/main-toolbar.vala
|
||||
+++ b/src/client/components/main-toolbar.vala
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
// Draws the main toolbar.
|
||||
[GtkTemplate (ui = "/org/gnome/Geary/main-toolbar.ui")]
|
||||
-public class MainToolbar : Gtk.Box {
|
||||
+public class MainToolbar : Hdy.Leaflet {
|
||||
// How wide the left pane should be. Auto-synced with our settings
|
||||
public int left_pane_width { get; set; }
|
||||
// Used to form the title of the folder header
|
||||
@@ -97,7 +97,8 @@ public class MainToolbar : Gtk.Box {
|
||||
public void set_conversation_header(Gtk.HeaderBar header) {
|
||||
conversation_header.hide();
|
||||
this.header_group.add_gtk_header_bar(header);
|
||||
- pack_start(header, true, true);
|
||||
+ header.hexpand = true;
|
||||
+ add(header);
|
||||
}
|
||||
|
||||
public void remove_conversation_header(Gtk.HeaderBar header) {
|
||||
diff --git a/src/client/conversation-viewer/conversation-viewer.vala b/src/client/conversation-viewer/conversation-viewer.vala
|
||||
index f04a1d26..eec5f6a4 100644
|
||||
--- a/src/client/conversation-viewer/conversation-viewer.vala
|
||||
+++ b/src/client/conversation-viewer/conversation-viewer.vala
|
||||
@@ -68,6 +68,10 @@ public class ConversationViewer : Gtk.Stack, Geary.BaseInterface {
|
||||
public signal void conversation_removed(ConversationListBox list);
|
||||
|
||||
|
||||
+ static construct {
|
||||
+ set_css_name("geary-conversation-viewer");
|
||||
+ }
|
||||
+
|
||||
/**
|
||||
* Constructs a new conversation view instance.
|
||||
*/
|
||||
diff --git a/ui/application-main-window.ui b/ui/application-main-window.ui
|
||||
index 872f31bd..f7bb884e 100644
|
||||
--- a/ui/application-main-window.ui
|
||||
+++ b/ui/application-main-window.ui
|
||||
@@ -24,13 +24,18 @@
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
- <object class="GtkPaned" id="conversations_paned">
|
||||
+ <object class="HdyLeaflet" id="main_leaflet">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
+ <property name="can_swipe_back">True</property>
|
||||
+ <property name="transition_type">over</property>
|
||||
<child>
|
||||
- <object class="GtkPaned" id="folder_paned">
|
||||
+ <object class="HdyLeaflet" id="conversations_leaflet">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
+ <property name="hexpand_set">True</property>
|
||||
+ <property name="can_swipe_back">True</property>
|
||||
+ <property name="transition_type">over</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="folder_box">
|
||||
<property name="visible">True</property>
|
||||
@@ -40,6 +45,7 @@
|
||||
<object class="GtkFrame" id="folder_frame">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
+ <property name="vexpand">True</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<child>
|
||||
@@ -55,15 +61,26 @@
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
- <property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
- <property name="resize">False</property>
|
||||
- <property name="shrink">False</property>
|
||||
+ <property name="name">folder</property>
|
||||
+ </packing>
|
||||
+ </child>
|
||||
+ <child>
|
||||
+ <object class="GtkSeparator" id="folder_separator">
|
||||
+ <property name="visible">True</property>
|
||||
+ <property name="can_focus">False</property>
|
||||
+ <property name="orientation">vertical</property>
|
||||
+ <style>
|
||||
+ <class name="sidebar"/>
|
||||
+ </style>
|
||||
+ </object>
|
||||
+ <packing>
|
||||
+ <property name="navigatable">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
@@ -97,22 +114,27 @@
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
- <property name="resize">True</property>
|
||||
- <property name="shrink">False</property>
|
||||
+ <property name="name">conversations</property>
|
||||
</packing>
|
||||
</child>
|
||||
+ </object>
|
||||
+ <packing>
|
||||
+ <property name="name">conversations</property>
|
||||
+ </packing>
|
||||
+ </child>
|
||||
+ <child>
|
||||
+ <object class="GtkSeparator" id="conversations_separator">
|
||||
+ <property name="visible">True</property>
|
||||
+ <property name="can_focus">False</property>
|
||||
+ <property name="orientation">vertical</property>
|
||||
<style>
|
||||
<class name="geary-sidebar-pane-separator"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
- <property name="resize">False</property>
|
||||
- <property name="shrink">False</property>
|
||||
+ <property name="navigatable">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
- <child>
|
||||
- <placeholder/>
|
||||
- </child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
@@ -146,6 +168,9 @@
|
||||
</object>
|
||||
<object class="GtkSizeGroup" id="folder_separator_size_group">
|
||||
<property name="mode">horizontal</property>
|
||||
+ <widgets>
|
||||
+ <widget name="folder_separator"/>
|
||||
+ </widgets>
|
||||
</object>
|
||||
<object class="GtkSizeGroup" id="conversations_size_group">
|
||||
<property name="mode">horizontal</property>
|
||||
@@ -155,6 +180,9 @@
|
||||
</object>
|
||||
<object class="GtkSizeGroup" id="conversations_separator_size_group">
|
||||
<property name="mode">horizontal</property>
|
||||
+ <widgets>
|
||||
+ <widget name="conversations_separator"/>
|
||||
+ </widgets>
|
||||
</object>
|
||||
<object class="GtkSizeGroup" id="conversation_size_group">
|
||||
<property name="mode">horizontal</property>
|
||||
diff --git a/ui/geary.css b/ui/geary.css
|
||||
index 0ddfab30..2d1d48c3 100644
|
||||
--- a/ui/geary.css
|
||||
+++ b/ui/geary.css
|
||||
@@ -12,12 +12,23 @@
|
||||
border-left-width: 0;
|
||||
border-top-width: 0;
|
||||
border-right-width: 0;
|
||||
+ min-width: 300px;
|
||||
}
|
||||
.geary-conversation-frame > border {
|
||||
border-left-width: 0;
|
||||
border-top-width: 0;
|
||||
border-right-width: 0;
|
||||
+ min-width: 360px;
|
||||
}
|
||||
+
|
||||
+treeview.sidebar {
|
||||
+ border: none;
|
||||
+}
|
||||
+
|
||||
+geary-conversation-viewer {
|
||||
+ min-width: 360px;
|
||||
+}
|
||||
+
|
||||
/* For 3-pane mode only */
|
||||
.geary-sidebar-pane-separator.vertical .conversation-frame > border {
|
||||
border-bottom-width: 0;
|
||||
diff --git a/ui/main-toolbar.ui b/ui/main-toolbar.ui
|
||||
index 732a01b9..441cd146 100644
|
||||
--- a/ui/main-toolbar.ui
|
||||
+++ b/ui/main-toolbar.ui
|
||||
@@ -7,13 +7,18 @@
|
||||
<property name="can_focus">False</property>
|
||||
<property name="icon_name">mail-archive-symbolic</property>
|
||||
</object>
|
||||
- <template class="MainToolbar" parent="GtkBox">
|
||||
+ <template class="MainToolbar" parent="HdyLeaflet">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
+ <property name="can_swipe_back">True</property>
|
||||
+ <property name="transition_type">over</property>
|
||||
<child>
|
||||
- <object class="GtkBox">
|
||||
+ <object class="HdyLeaflet" id="conversations_leaflet">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
+ <property name="can_swipe_back">True</property>
|
||||
+ <property name="transition_type">over</property>
|
||||
+ <property name="hexpand_set">True</property>
|
||||
<child>
|
||||
<object class="GtkHeaderBar" id="folder_header">
|
||||
<property name="visible">True</property>
|
||||
@@ -41,6 +46,9 @@
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
+ <packing>
|
||||
+ <property name="name">folder</property>
|
||||
+ </packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparator" id="folder_separator">
|
||||
@@ -52,15 +60,14 @@
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
- <property name="expand">False</property>
|
||||
- <property name="fill">True</property>
|
||||
- <property name="position">1</property>
|
||||
+ <property name="navigatable">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkHeaderBar" id="conversations_header">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
+ <property name="hexpand">True</property>
|
||||
<property name="show_close_button" bind-source="MainToolbar" bind-property="show_close_button" bind-flags="sync-create"/>
|
||||
<child>
|
||||
<object class="GtkButton" id="compose_new_message_button">
|
||||
@@ -102,12 +109,13 @@
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
+ <packing>
|
||||
+ <property name="name">conversations</property>
|
||||
+ </packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
- <property name="expand">False</property>
|
||||
- <property name="fill">True</property>
|
||||
- <property name="position">0</property>
|
||||
+ <property name="name">conversations</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
@@ -120,15 +128,14 @@
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
- <property name="expand">False</property>
|
||||
- <property name="fill">True</property>
|
||||
- <property name="position">1</property>
|
||||
+ <property name="navigatable">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkHeaderBar" id="conversation_header">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
+ <property name="hexpand">True</property>
|
||||
<property name="show_close_button" bind-source="MainToolbar" bind-property="show_close_button" bind-flags="sync-create"/>
|
||||
<child>
|
||||
<object class="GtkBox" id="reply_forward_buttons">
|
||||
@@ -362,9 +369,7 @@
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
- <property name="expand">True</property>
|
||||
- <property name="fill">True</property>
|
||||
- <property name="position">2</property>
|
||||
+ <property name="name">conversation</property>
|
||||
</packing>
|
||||
</child>
|
||||
</template>
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,40 @@
|
||||
From 2139636d82b67414dd22170894bb61d2e9d1b415 Mon Sep 17 00:00:00 2001
|
||||
From: Adrien Plazas <kekun.plazas@laposte.net>
|
||||
Date: Sat, 18 Jan 2020 12:58:18 +0100
|
||||
Subject: [PATCH 052/124] main-toolbar: Add add_to_swipe_groups()
|
||||
|
||||
This will be used to sync the swipe state of the leaflets.
|
||||
---
|
||||
src/client/components/main-toolbar.vala | 9 +++++++++
|
||||
1 file changed, 9 insertions(+)
|
||||
|
||||
diff --git a/src/client/components/main-toolbar.vala b/src/client/components/main-toolbar.vala
|
||||
index 286546d5..c7bdab8f 100644
|
||||
--- a/src/client/components/main-toolbar.vala
|
||||
+++ b/src/client/components/main-toolbar.vala
|
||||
@@ -24,6 +24,9 @@ public class MainToolbar : Hdy.Leaflet {
|
||||
public int selected_conversations { get; set; }
|
||||
|
||||
|
||||
+ [GtkChild]
|
||||
+ private Hdy.Leaflet conversations_leaflet;
|
||||
+
|
||||
// Folder header elements
|
||||
[GtkChild]
|
||||
private Gtk.HeaderBar folder_header;
|
||||
@@ -124,6 +127,12 @@ public class MainToolbar : Hdy.Leaflet {
|
||||
conversation_group.add_widget(conversation_header);
|
||||
}
|
||||
|
||||
+ public void add_to_swipe_groups(Hdy.SwipeGroup conversations_group,
|
||||
+ Hdy.SwipeGroup conversation_group) {
|
||||
+ conversations_group.add_swipeable(this.conversations_leaflet);
|
||||
+ conversation_group.add_swipeable(this);
|
||||
+ }
|
||||
+
|
||||
// Updates tooltip text depending on number of conversations selected.
|
||||
private void update_conversation_buttons() {
|
||||
this.mark_message_button.tooltip_text = ngettext(
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,58 @@
|
||||
From 28e319267446fe96c070b85d6a20096f787fcdcc Mon Sep 17 00:00:00 2001
|
||||
From: Adrien Plazas <kekun.plazas@laposte.net>
|
||||
Date: Sat, 18 Jan 2020 13:04:10 +0100
|
||||
Subject: [PATCH 053/124] application-main-window: Sync the leaflets' swipe
|
||||
state
|
||||
|
||||
This keeps the swiping state of the leaflets in sync.
|
||||
---
|
||||
src/client/application/application-main-window.vala | 6 ++++++
|
||||
ui/application-main-window.ui | 10 ++++++++++
|
||||
2 files changed, 16 insertions(+)
|
||||
|
||||
diff --git a/src/client/application/application-main-window.vala b/src/client/application/application-main-window.vala
|
||||
index b56079cf..3af1b6aa 100644
|
||||
--- a/src/client/application/application-main-window.vala
|
||||
+++ b/src/client/application/application-main-window.vala
|
||||
@@ -338,6 +338,10 @@ public class Application.MainWindow :
|
||||
private Gtk.SizeGroup conversations_separator_size_group;
|
||||
[GtkChild]
|
||||
private Gtk.SizeGroup conversation_size_group;
|
||||
+ [GtkChild]
|
||||
+ private Hdy.SwipeGroup conversations_swipe_group;
|
||||
+ [GtkChild]
|
||||
+ private Hdy.SwipeGroup conversation_swipe_group;
|
||||
|
||||
[GtkChild]
|
||||
private Gtk.Overlay overlay;
|
||||
@@ -1259,6 +1263,8 @@ public class Application.MainWindow :
|
||||
this.conversations_size_group,
|
||||
this.conversations_separator_size_group,
|
||||
this.conversation_size_group);
|
||||
+ this.main_toolbar.add_to_swipe_groups(this.conversations_swipe_group,
|
||||
+ this.conversation_swipe_group);
|
||||
this.main_toolbar.move_folder_menu.folder_selected.connect(on_move_conversation);
|
||||
this.main_toolbar.copy_folder_menu.folder_selected.connect(on_copy_conversation);
|
||||
this.main_toolbar.bind_property("search-open", this.search_bar, "search-mode-enabled",
|
||||
diff --git a/ui/application-main-window.ui b/ui/application-main-window.ui
|
||||
index f7bb884e..fe66491b 100644
|
||||
--- a/ui/application-main-window.ui
|
||||
+++ b/ui/application-main-window.ui
|
||||
@@ -187,4 +187,14 @@
|
||||
<object class="GtkSizeGroup" id="conversation_size_group">
|
||||
<property name="mode">horizontal</property>
|
||||
</object>
|
||||
+ <object class="HdySwipeGroup" id="conversations_swipe_group">
|
||||
+ <swipeables>
|
||||
+ <swipeable name="conversations_leaflet"/>
|
||||
+ </swipeables>
|
||||
+ </object>
|
||||
+ <object class="HdySwipeGroup" id="conversation_swipe_group">
|
||||
+ <swipeables>
|
||||
+ <swipeable name="main_leaflet"/>
|
||||
+ </swipeables>
|
||||
+ </object>
|
||||
</interface>
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,66 @@
|
||||
From 115b055e7b3dd267c44efacaf3fc7272a81d9d96 Mon Sep 17 00:00:00 2001
|
||||
From: Julian Sparber <julian@sparber.net>
|
||||
Date: Mon, 5 Oct 2020 17:20:14 +0200
|
||||
Subject: [PATCH 054/124] main-window: Add leaflet navigation with Alt+Arrow
|
||||
keys
|
||||
|
||||
---
|
||||
.../application/application-main-window.vala | 35 +++++++++++++++++--
|
||||
1 file changed, 33 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/client/application/application-main-window.vala b/src/client/application/application-main-window.vala
|
||||
index 3af1b6aa..bb5a9404 100644
|
||||
--- a/src/client/application/application-main-window.vala
|
||||
+++ b/src/client/application/application-main-window.vala
|
||||
@@ -1797,7 +1797,20 @@ public class Application.MainWindow :
|
||||
|
||||
private void focus_next_pane() {
|
||||
var focus = get_focus();
|
||||
- if (focus != null) {
|
||||
+
|
||||
+ if (main_leaflet.folded) {
|
||||
+ if (main_leaflet.visible_child_name == "conversations") {
|
||||
+ if (conversations_leaflet.folded &&
|
||||
+ conversations_leaflet.visible_child_name == "folder" ||
|
||||
+ focus == this.folder_list) {
|
||||
+ conversations_leaflet.navigate(Hdy.NavigationDirection.FORWARD);
|
||||
+ focus = this.conversation_list_view;
|
||||
+ } else {
|
||||
+ main_leaflet.navigate(Hdy.NavigationDirection.FORWARD);
|
||||
+ focus = this.conversation_viewer.visible_child;
|
||||
+ }
|
||||
+ }
|
||||
+ } else if (focus != null) {
|
||||
if (focus == this.folder_list ||
|
||||
focus.is_ancestor(this.folder_list)) {
|
||||
focus = this.conversation_list_view;
|
||||
@@ -1819,7 +1832,25 @@ public class Application.MainWindow :
|
||||
|
||||
private void focus_previous_pane() {
|
||||
var focus = get_focus();
|
||||
- if (focus != null) {
|
||||
+
|
||||
+ if (main_leaflet.folded) {
|
||||
+ if (main_leaflet.visible_child_name == "conversations") {
|
||||
+ if (conversations_leaflet.folded) {
|
||||
+ if (conversations_leaflet.visible_child_name == "conversations") {
|
||||
+ conversations_leaflet.navigate(Hdy.NavigationDirection.BACK);
|
||||
+ focus = this.folder_list;
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (focus == this.conversation_list_view)
|
||||
+ focus = this.folder_list;
|
||||
+ else
|
||||
+ focus = this.conversation_list_view;
|
||||
+ }
|
||||
+ } else {
|
||||
+ main_leaflet.navigate(Hdy.NavigationDirection.BACK);
|
||||
+ focus = this.conversation_list_view;
|
||||
+ }
|
||||
+ } else if (focus != null) {
|
||||
if (focus == this.folder_list ||
|
||||
focus.is_ancestor(this.folder_list)) {
|
||||
focus = this.conversation_viewer.visible_child;
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,103 @@
|
||||
From 28a19775b8689f08c4e6c280e9414547d23d42c7 Mon Sep 17 00:00:00 2001
|
||||
From: Julian Sparber <julian@sparber.net>
|
||||
Date: Wed, 30 Sep 2020 17:38:24 +0200
|
||||
Subject: [PATCH 055/124] main-toolbar: Add back buttons for leaflet navigation
|
||||
|
||||
---
|
||||
.../application/application-main-window.vala | 2 +
|
||||
ui/main-toolbar.ui | 52 +++++++++++++++++++
|
||||
2 files changed, 54 insertions(+)
|
||||
|
||||
diff --git a/src/client/application/application-main-window.vala b/src/client/application/application-main-window.vala
|
||||
index bb5a9404..c3cf2d58 100644
|
||||
--- a/src/client/application/application-main-window.vala
|
||||
+++ b/src/client/application/application-main-window.vala
|
||||
@@ -31,6 +31,7 @@ public class Application.MainWindow :
|
||||
public const string ACTION_TOGGLE_JUNK = "toggle-conversation-junk";
|
||||
public const string ACTION_TRASH_CONVERSATION = "trash-conversation";
|
||||
public const string ACTION_ZOOM = "zoom";
|
||||
+ public const string ACTION_NAVIGATION_BACK = "navigation-back";
|
||||
|
||||
private const ActionEntry[] EDIT_ACTIONS = {
|
||||
{ Action.Edit.UNDO, on_undo },
|
||||
@@ -42,6 +43,7 @@ public class Application.MainWindow :
|
||||
|
||||
{ ACTION_FIND_IN_CONVERSATION, on_find_in_conversation_action },
|
||||
{ ACTION_SEARCH, on_search_activated },
|
||||
+ { ACTION_NAVIGATION_BACK, focus_previous_pane},
|
||||
// Message actions
|
||||
{ ACTION_REPLY_CONVERSATION, on_reply_conversation },
|
||||
{ ACTION_REPLY_ALL_CONVERSATION, on_reply_all_conversation },
|
||||
diff --git a/ui/main-toolbar.ui b/ui/main-toolbar.ui
|
||||
index 441cd146..871aba25 100644
|
||||
--- a/ui/main-toolbar.ui
|
||||
+++ b/ui/main-toolbar.ui
|
||||
@@ -69,6 +69,32 @@
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="show_close_button" bind-source="MainToolbar" bind-property="show_close_button" bind-flags="sync-create"/>
|
||||
+ <child>
|
||||
+ <object class="GtkButton" id="conversations_back">
|
||||
+ <property name="can_focus">False</property>
|
||||
+ <property name="receives_default">False</property>
|
||||
+ <property name="valign">center</property>
|
||||
+ <property name="use-underline">True</property>
|
||||
+ <property name="visible" bind-source="conversations_leaflet" bind-property="folded" bind-flags="sync-create"/>
|
||||
+ <property name="action_name">win.navigation-back</property>
|
||||
+ <style>
|
||||
+ <class name="image-button"/>
|
||||
+ </style>
|
||||
+ <child internal-child="accessible">
|
||||
+ <object class="AtkObject" id="a11y-conversations-back">
|
||||
+ <property name="accessible-name" translatable="yes">Back</property>
|
||||
+ </object>
|
||||
+ </child>
|
||||
+ <child>
|
||||
+ <object class="GtkImage" id="conversations_back_image">
|
||||
+ <property name="visible">True</property>
|
||||
+ <property name="can_focus">False</property>
|
||||
+ <property name="icon_name">go-previous-symbolic</property>
|
||||
+ <property name="icon_size">1</property>
|
||||
+ </object>
|
||||
+ </child>
|
||||
+ </object>
|
||||
+ </child>
|
||||
<child>
|
||||
<object class="GtkButton" id="compose_new_message_button">
|
||||
<property name="visible">True</property>
|
||||
@@ -137,6 +163,32 @@
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="show_close_button" bind-source="MainToolbar" bind-property="show_close_button" bind-flags="sync-create"/>
|
||||
+ <child>
|
||||
+ <object class="GtkButton" id="conversation_back">
|
||||
+ <property name="can_focus">False</property>
|
||||
+ <property name="receives_default">False</property>
|
||||
+ <property name="valign">center</property>
|
||||
+ <property name="use-underline">True</property>
|
||||
+ <property name="visible" bind-source="MainToolbar" bind-property="folded" bind-flags="sync-create"/>
|
||||
+ <property name="action_name">win.navigation-back</property>
|
||||
+ <style>
|
||||
+ <class name="image-button"/>
|
||||
+ </style>
|
||||
+ <child internal-child="accessible">
|
||||
+ <object class="AtkObject" id="a11y-conversation-back">
|
||||
+ <property name="accessible-name" translatable="yes">Back</property>
|
||||
+ </object>
|
||||
+ </child>
|
||||
+ <child>
|
||||
+ <object class="GtkImage" id="conversation_back_image">
|
||||
+ <property name="visible">True</property>
|
||||
+ <property name="can_focus">False</property>
|
||||
+ <property name="icon_name">go-previous-symbolic</property>
|
||||
+ <property name="icon_size">1</property>
|
||||
+ </object>
|
||||
+ </child>
|
||||
+ </object>
|
||||
+ </child>
|
||||
<child>
|
||||
<object class="GtkBox" id="reply_forward_buttons">
|
||||
<property name="visible">True</property>
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,132 @@
|
||||
From 49823ec05414e11275f313fb0ca5a48fcab7ddda Mon Sep 17 00:00:00 2001
|
||||
From: Julian Sparber <julian@sparber.net>
|
||||
Date: Tue, 6 Oct 2020 10:41:33 +0200
|
||||
Subject: [PATCH 056/124] application-main-window: add navigation via signle
|
||||
click on folder/conversation
|
||||
|
||||
Opening a conversation in a new window is currently disabled, because we
|
||||
need a new key/button combination.
|
||||
---
|
||||
src/client/application/application-main-window.vala | 11 +++++++++++
|
||||
.../conversation-list/conversation-list-view.vala | 1 +
|
||||
src/client/folder-list/folder-list-tree.vala | 10 ++++++++++
|
||||
src/client/sidebar/sidebar-tree.vala | 11 +++++++++++
|
||||
4 files changed, 33 insertions(+)
|
||||
|
||||
diff --git a/src/client/application/application-main-window.vala b/src/client/application/application-main-window.vala
|
||||
index c3cf2d58..97960660 100644
|
||||
--- a/src/client/application/application-main-window.vala
|
||||
+++ b/src/client/application/application-main-window.vala
|
||||
@@ -1230,6 +1230,7 @@ public class Application.MainWindow :
|
||||
this.folder_list.folder_selected.connect(on_folder_selected);
|
||||
this.folder_list.move_conversation.connect(on_move_conversation);
|
||||
this.folder_list.copy_conversation.connect(on_copy_conversation);
|
||||
+ this.folder_list.folder_activated.connect(on_folder_activated);
|
||||
this.folder_list_scrolled.add(this.folder_list);
|
||||
|
||||
// Conversation list
|
||||
@@ -2135,7 +2136,16 @@ public class Application.MainWindow :
|
||||
}
|
||||
}
|
||||
|
||||
+ private void on_folder_activated(Geary.Folder? folder) {
|
||||
+ if (folder != null)
|
||||
+ focus_next_pane();
|
||||
+ }
|
||||
+
|
||||
private void on_conversation_activated(Geary.App.Conversation activated) {
|
||||
+ if (main_leaflet.folded) {
|
||||
+ focus_next_pane();
|
||||
+ }
|
||||
+ /* TODO: find correct UX for opening the conversation in a new window
|
||||
if (this.selected_folder != null) {
|
||||
if (this.selected_folder.used_as != DRAFTS) {
|
||||
this.application.new_window.begin(
|
||||
@@ -2154,6 +2164,7 @@ public class Application.MainWindow :
|
||||
);
|
||||
}
|
||||
}
|
||||
+ */
|
||||
}
|
||||
|
||||
private void on_find_in_conversation_action() {
|
||||
diff --git a/src/client/conversation-list/conversation-list-view.vala b/src/client/conversation-list/conversation-list-view.vala
|
||||
index a4d5cca6..dcced90d 100644
|
||||
--- a/src/client/conversation-list/conversation-list-view.vala
|
||||
+++ b/src/client/conversation-list/conversation-list-view.vala
|
||||
@@ -42,6 +42,7 @@ public class ConversationListView : Gtk.TreeView, Geary.BaseInterface {
|
||||
base_ref();
|
||||
set_show_expanders(false);
|
||||
set_headers_visible(false);
|
||||
+ set_activate_on_single_click(true);
|
||||
|
||||
this.config = config;
|
||||
|
||||
diff --git a/src/client/folder-list/folder-list-tree.vala b/src/client/folder-list/folder-list-tree.vala
|
||||
index fb91347e..f820d12f 100644
|
||||
--- a/src/client/folder-list/folder-list-tree.vala
|
||||
+++ b/src/client/folder-list/folder-list-tree.vala
|
||||
@@ -16,6 +16,7 @@ public class FolderList.Tree : Sidebar.Tree, Geary.BaseInterface {
|
||||
|
||||
|
||||
public signal void folder_selected(Geary.Folder? folder);
|
||||
+ public signal void folder_activated(Geary.Folder? folder);
|
||||
public signal void copy_conversation(Geary.Folder folder);
|
||||
public signal void move_conversation(Geary.Folder folder);
|
||||
|
||||
@@ -30,7 +31,9 @@ public class FolderList.Tree : Sidebar.Tree, Geary.BaseInterface {
|
||||
public Tree() {
|
||||
base(TARGET_ENTRY_LIST, Gdk.DragAction.COPY | Gdk.DragAction.MOVE, drop_handler);
|
||||
base_ref();
|
||||
+ set_activate_on_single_click(true);
|
||||
entry_selected.connect(on_entry_selected);
|
||||
+ entry_activated.connect(on_entry_activated);
|
||||
|
||||
// GtkTreeView binds Ctrl+N to "move cursor to next". Not so interested in that, so we'll
|
||||
// remove it.
|
||||
@@ -87,6 +90,13 @@ public class FolderList.Tree : Sidebar.Tree, Geary.BaseInterface {
|
||||
}
|
||||
}
|
||||
|
||||
+ private void on_entry_activated(Sidebar.SelectableEntry selectable) {
|
||||
+ AbstractFolderEntry? entry = selectable as AbstractFolderEntry;
|
||||
+ if (entry != null) {
|
||||
+ folder_activated(entry.folder);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
public void set_user_folders_root_name(Geary.Account account, string name) {
|
||||
if (account_branches.has_key(account))
|
||||
account_branches.get(account).user_folder_group.rename(name);
|
||||
diff --git a/src/client/sidebar/sidebar-tree.vala b/src/client/sidebar/sidebar-tree.vala
|
||||
index a5f95092..78d73e98 100644
|
||||
--- a/src/client/sidebar/sidebar-tree.vala
|
||||
+++ b/src/client/sidebar/sidebar-tree.vala
|
||||
@@ -80,6 +80,8 @@ public class Sidebar.Tree : Gtk.TreeView {
|
||||
|
||||
public signal void entry_selected(Sidebar.SelectableEntry selectable);
|
||||
|
||||
+ public signal void entry_activated(Sidebar.SelectableEntry selectable);
|
||||
+
|
||||
public signal void selected_entry_removed(Sidebar.SelectableEntry removed);
|
||||
|
||||
public signal void branch_added(Sidebar.Branch branch);
|
||||
@@ -298,6 +300,15 @@ public class Sidebar.Tree : Gtk.TreeView {
|
||||
return true;
|
||||
}
|
||||
|
||||
+ public override void row_activated(Gtk.TreePath path, Gtk.TreeViewColumn column) {
|
||||
+ EntryWrapper? wrapper = get_wrapper_at_path(path);
|
||||
+ if (wrapper != null) {
|
||||
+ Sidebar.SelectableEntry? selectable = wrapper.entry as Sidebar.SelectableEntry;
|
||||
+ if (selectable != null)
|
||||
+ entry_activated(selectable);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
public override void cursor_changed() {
|
||||
Gtk.TreePath? path = get_selected_path();
|
||||
if (path == null) {
|
||||
--
|
||||
2.29.2
|
||||
|
35
mail-client/geary/files/0057-toolbar-header-group.patch
Normal file
35
mail-client/geary/files/0057-toolbar-header-group.patch
Normal file
@ -0,0 +1,35 @@
|
||||
From d97d86cbc73dc0dc565494c1083b5052457afe04 Mon Sep 17 00:00:00 2001
|
||||
From: Adrien Plazas <kekun.plazas@laposte.net>
|
||||
Date: Wed, 16 Sep 2020 13:19:00 +0200
|
||||
Subject: [PATCH 057/124] toolbar header group
|
||||
|
||||
---
|
||||
ui/main-toolbar.ui | 9 ++++++++-
|
||||
1 file changed, 8 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/ui/main-toolbar.ui b/ui/main-toolbar.ui
|
||||
index 871aba25..5d58af6f 100644
|
||||
--- a/ui/main-toolbar.ui
|
||||
+++ b/ui/main-toolbar.ui
|
||||
@@ -425,10 +425,17 @@
|
||||
</packing>
|
||||
</child>
|
||||
</template>
|
||||
- <object class="HdyHeaderGroup" id="header_group">
|
||||
+ <object class="HdyHeaderGroup" id="conversations_header_group">
|
||||
+ <property name="decorate-all" bind-source="conversations_leaflet" bind-property="folded" bind-flags="sync-create"/>
|
||||
<headerbars>
|
||||
<headerbar name="folder_header"/>
|
||||
<headerbar name="conversations_header"/>
|
||||
+ </headerbars>
|
||||
+ </object>
|
||||
+ <object class="HdyHeaderGroup" id="header_group">
|
||||
+ <property name="decorate-all" bind-source="MainToolbar" bind-property="folded" bind-flags="sync-create"/>
|
||||
+ <headerbars>
|
||||
+ <headerbar name="conversations_header_group"/>
|
||||
<headerbar name="conversation_header"/>
|
||||
</headerbars>
|
||||
</object>
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,72 @@
|
||||
From 1f2896e9a7ba02c0a909c91bb551e596d2d72230 Mon Sep 17 00:00:00 2001
|
||||
From: Julian Sparber <julian@sparber.net>
|
||||
Date: Thu, 1 Oct 2020 10:40:41 +0200
|
||||
Subject: [PATCH 058/124] composer: Switch leaflet to composer when folded
|
||||
|
||||
---
|
||||
src/client/application/application-main-window.vala | 2 ++
|
||||
src/client/components/main-toolbar.vala | 13 +++++++++++--
|
||||
2 files changed, 13 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/client/application/application-main-window.vala b/src/client/application/application-main-window.vala
|
||||
index 97960660..c2b0954b 100644
|
||||
--- a/src/client/application/application-main-window.vala
|
||||
+++ b/src/client/application/application-main-window.vala
|
||||
@@ -916,6 +916,8 @@ public class Application.MainWindow :
|
||||
} else {
|
||||
this.conversation_viewer.do_compose(composer);
|
||||
}
|
||||
+ // Show the correct leaflet
|
||||
+ this.main_leaflet.set_visible_child_name("conversation");
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/client/components/main-toolbar.vala b/src/client/components/main-toolbar.vala
|
||||
index c7bdab8f..0ecb599a 100644
|
||||
--- a/src/client/components/main-toolbar.vala
|
||||
+++ b/src/client/components/main-toolbar.vala
|
||||
@@ -64,6 +64,8 @@ public class MainToolbar : Hdy.Leaflet {
|
||||
[GtkChild]
|
||||
private Hdy.HeaderGroup header_group;
|
||||
|
||||
+ Gtk.SizeGroup conversation_group;
|
||||
+
|
||||
private bool show_trash_button = true;
|
||||
|
||||
// Load these at construction time
|
||||
@@ -98,16 +100,22 @@ public class MainToolbar : Hdy.Leaflet {
|
||||
}
|
||||
|
||||
public void set_conversation_header(Gtk.HeaderBar header) {
|
||||
- conversation_header.hide();
|
||||
+ remove(conversation_header);
|
||||
this.header_group.add_gtk_header_bar(header);
|
||||
header.hexpand = true;
|
||||
+ conversation_group.remove_widget(conversation_header);
|
||||
+ conversation_group.add_widget(header);
|
||||
add(header);
|
||||
+ child_set(header, "name", "conversation", null);
|
||||
}
|
||||
|
||||
public void remove_conversation_header(Gtk.HeaderBar header) {
|
||||
remove(header);
|
||||
this.header_group.remove_gtk_header_bar(header);
|
||||
- conversation_header.show();
|
||||
+ conversation_group.remove_widget(header);
|
||||
+ conversation_group.add_widget(conversation_header);
|
||||
+ add(conversation_header);
|
||||
+ child_set(conversation_header, "name", "conversation", null);
|
||||
}
|
||||
|
||||
public void update_trash_button(bool show_trash) {
|
||||
@@ -125,6 +133,7 @@ public class MainToolbar : Hdy.Leaflet {
|
||||
conversations_group.add_widget(conversations_header);
|
||||
conversations_separator_group.add_widget(conversations_separator);
|
||||
conversation_group.add_widget(conversation_header);
|
||||
+ this.conversation_group = conversation_group;
|
||||
}
|
||||
|
||||
public void add_to_swipe_groups(Hdy.SwipeGroup conversations_group,
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,163 @@
|
||||
From 0b743ab0d396cbbaad5aebaebed235ecd0f1a564 Mon Sep 17 00:00:00 2001
|
||||
From: Julian Sparber <julian@sparber.net>
|
||||
Date: Tue, 6 Oct 2020 13:34:30 +0200
|
||||
Subject: [PATCH 059/124] conversation-list: use shift+activate to open
|
||||
conversation in new window
|
||||
|
||||
Open on shift+double click and shift+space/enter the selected
|
||||
conversation in a new window.
|
||||
---
|
||||
.../application/application-main-window.vala | 14 ++---
|
||||
.../conversation-list-view.vala | 61 ++++++++++++++++---
|
||||
2 files changed, 58 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/src/client/application/application-main-window.vala b/src/client/application/application-main-window.vala
|
||||
index c2b0954b..01b7b9c6 100644
|
||||
--- a/src/client/application/application-main-window.vala
|
||||
+++ b/src/client/application/application-main-window.vala
|
||||
@@ -2143,17 +2143,16 @@ public class Application.MainWindow :
|
||||
focus_next_pane();
|
||||
}
|
||||
|
||||
- private void on_conversation_activated(Geary.App.Conversation activated) {
|
||||
- if (main_leaflet.folded) {
|
||||
- focus_next_pane();
|
||||
- }
|
||||
- /* TODO: find correct UX for opening the conversation in a new window
|
||||
- if (this.selected_folder != null) {
|
||||
+ private void on_conversation_activated(Geary.App.Conversation activated, bool single) {
|
||||
+ if (single) {
|
||||
+ if (main_leaflet.folded)
|
||||
+ focus_next_pane();
|
||||
+ } else if (this.selected_folder != null) {
|
||||
if (this.selected_folder.used_as != DRAFTS) {
|
||||
this.application.new_window.begin(
|
||||
this.selected_folder,
|
||||
this.conversation_list_view.copy_selected()
|
||||
- );
|
||||
+ );
|
||||
} else {
|
||||
// TODO: Determine how to map between conversations
|
||||
// and drafts correctly.
|
||||
@@ -2166,7 +2165,6 @@ public class Application.MainWindow :
|
||||
);
|
||||
}
|
||||
}
|
||||
- */
|
||||
}
|
||||
|
||||
private void on_find_in_conversation_action() {
|
||||
diff --git a/src/client/conversation-list/conversation-list-view.vala b/src/client/conversation-list/conversation-list-view.vala
|
||||
index dcced90d..0baa66b4 100644
|
||||
--- a/src/client/conversation-list/conversation-list-view.vala
|
||||
+++ b/src/client/conversation-list/conversation-list-view.vala
|
||||
@@ -17,6 +17,7 @@ public class ConversationListView : Gtk.TreeView, Geary.BaseInterface {
|
||||
private Geary.Scheduler.Scheduled? scheduled_update_visible_conversations = null;
|
||||
private Gee.Set<Geary.App.Conversation> selected = new Gee.HashSet<Geary.App.Conversation>();
|
||||
private Geary.IdleManager selection_update;
|
||||
+ private Gtk.GestureMultiPress gesture;
|
||||
|
||||
// Determines if the next folder scan should avoid selecting a
|
||||
// conversation when autoselect is enabled
|
||||
@@ -26,7 +27,7 @@ public class ConversationListView : Gtk.TreeView, Geary.BaseInterface {
|
||||
public signal void conversations_selected(Gee.Set<Geary.App.Conversation> selected);
|
||||
|
||||
// Signal for when a conversation has been double-clicked, or selected and enter is pressed.
|
||||
- public signal void conversation_activated(Geary.App.Conversation activated);
|
||||
+ public signal void conversation_activated(Geary.App.Conversation activated, bool single = false);
|
||||
|
||||
public virtual signal void load_more() {
|
||||
enable_load_more = false;
|
||||
@@ -42,7 +43,6 @@ public class ConversationListView : Gtk.TreeView, Geary.BaseInterface {
|
||||
base_ref();
|
||||
set_show_expanders(false);
|
||||
set_headers_visible(false);
|
||||
- set_activate_on_single_click(true);
|
||||
|
||||
this.config = config;
|
||||
|
||||
@@ -53,11 +53,13 @@ public class ConversationListView : Gtk.TreeView, Geary.BaseInterface {
|
||||
Gtk.TreeSelection selection = get_selection();
|
||||
selection.set_mode(Gtk.SelectionMode.MULTIPLE);
|
||||
style_updated.connect(on_style_changed);
|
||||
- row_activated.connect(on_row_activated);
|
||||
|
||||
notify["vadjustment"].connect(on_vadjustment_changed);
|
||||
|
||||
+ key_press_event.connect(on_key_press);
|
||||
button_press_event.connect(on_button_press);
|
||||
+ gesture = new Gtk.GestureMultiPress(this);
|
||||
+ gesture.pressed.connect(on_gesture_pressed);
|
||||
|
||||
// Set up drag and drop.
|
||||
Gtk.drag_source_set(this, Gdk.ModifierType.BUTTON1_MASK, FolderList.Tree.TARGET_ENTRY_LIST,
|
||||
@@ -270,6 +272,53 @@ public class ConversationListView : Gtk.TreeView, Geary.BaseInterface {
|
||||
return parent.get_vadjustment();
|
||||
}
|
||||
|
||||
+ private void on_gesture_pressed(int n_press, double x, double y) {
|
||||
+ if (gesture.get_current_button() != Gdk.BUTTON_PRIMARY)
|
||||
+ return;
|
||||
+
|
||||
+ Gtk.TreePath? path;
|
||||
+ get_path_at_pos((int) x, (int) y, out path, null, null, null);
|
||||
+
|
||||
+ // If the user clicked in an empty area, do nothing.
|
||||
+ if (path == null)
|
||||
+ return;
|
||||
+
|
||||
+ Geary.App.Conversation? c = get_model().get_conversation_at_path(path);
|
||||
+ if (c == null)
|
||||
+ return;
|
||||
+
|
||||
+ Gdk.Event event = gesture.get_last_event(gesture.get_current_sequence());
|
||||
+ Gdk.ModifierType modifiers = Gtk.accelerator_get_default_mod_mask();
|
||||
+
|
||||
+ Gdk.ModifierType state_mask;
|
||||
+ event.get_state(out state_mask);
|
||||
+
|
||||
+ if ((state_mask & modifiers) == 0 && n_press == 1) {
|
||||
+ conversation_activated(c, true);
|
||||
+ } else if ((state_mask & modifiers) == Gdk.ModifierType.SHIFT_MASK && n_press == 2) {
|
||||
+ conversation_activated(c);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private bool on_key_press(Gdk.EventKey event) {
|
||||
+ if (this.selected.size != 1)
|
||||
+ return false;
|
||||
+
|
||||
+ Geary.App.Conversation? c = this.selected.to_array()[0];
|
||||
+ if (c == null)
|
||||
+ return false;
|
||||
+
|
||||
+ Gdk.ModifierType modifiers = Gtk.accelerator_get_default_mod_mask();
|
||||
+
|
||||
+ if (event.keyval == Gdk.Key.Return ||
|
||||
+ event.keyval == Gdk.Key.ISO_Enter ||
|
||||
+ event.keyval == Gdk.Key.KP_Enter ||
|
||||
+ event.keyval == Gdk.Key.space ||
|
||||
+ event.keyval == Gdk.Key.KP_Space)
|
||||
+ conversation_activated(c, !((event.state & modifiers) == Gdk.ModifierType.SHIFT_MASK));
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
private bool on_button_press(Gdk.EventButton event) {
|
||||
// Get the coordinates on the cell as well as the clicked path.
|
||||
int cell_x;
|
||||
@@ -576,12 +625,6 @@ public class ConversationListView : Gtk.TreeView, Geary.BaseInterface {
|
||||
return false;
|
||||
}
|
||||
|
||||
- private void on_row_activated(Gtk.TreePath path) {
|
||||
- Geary.App.Conversation? c = get_model().get_conversation_at_path(path);
|
||||
- if (c != null)
|
||||
- conversation_activated(c);
|
||||
- }
|
||||
-
|
||||
// Enable/disable hover effect on all selected cells.
|
||||
private void set_hover_selected(bool hover) {
|
||||
ConversationListCellRenderer.set_hover_selected(hover);
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,65 @@
|
||||
From d6c546e2d555d20e1dd259117822b4d4c8b7152c Mon Sep 17 00:00:00 2001
|
||||
From: Julian Sparber <julian@sparber.net>
|
||||
Date: Tue, 6 Oct 2020 17:31:49 +0200
|
||||
Subject: [PATCH 060/124] composer: close the composer when navigating back
|
||||
|
||||
---
|
||||
src/client/application/application-main-window.vala | 11 +++++++++++
|
||||
src/client/composer/composer-widget.vala | 5 +++++
|
||||
ui/application-main-window.ui | 2 ++
|
||||
3 files changed, 18 insertions(+)
|
||||
|
||||
diff --git a/src/client/application/application-main-window.vala b/src/client/application/application-main-window.vala
|
||||
index 01b7b9c6..e1e55d0e 100644
|
||||
--- a/src/client/application/application-main-window.vala
|
||||
+++ b/src/client/application/application-main-window.vala
|
||||
@@ -1955,6 +1955,17 @@ public class Application.MainWindow :
|
||||
return Gdk.EVENT_STOP;
|
||||
}
|
||||
|
||||
+ [GtkCallback]
|
||||
+ private void on_main_leaflet_visible_child_changed() {
|
||||
+ if (main_leaflet.child_transition_running)
|
||||
+ return;
|
||||
+
|
||||
+ if (main_leaflet.visible_child_name == "conversations" && main_leaflet.folded)
|
||||
+ if (this.conversation_viewer.current_composer != null) {
|
||||
+ this.conversation_viewer.current_composer.activate_close_action();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
private void on_offline_infobar_response() {
|
||||
this.info_bars.remove(this.offline_infobar);
|
||||
}
|
||||
diff --git a/src/client/composer/composer-widget.vala b/src/client/composer/composer-widget.vala
|
||||
index 37e93fb4..17430021 100644
|
||||
--- a/src/client/composer/composer-widget.vala
|
||||
+++ b/src/client/composer/composer-widget.vala
|
||||
@@ -1361,6 +1361,11 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
|
||||
}
|
||||
}
|
||||
|
||||
+ /* Activate the close action */
|
||||
+ public void activate_close_action() {
|
||||
+ this.actions.activate_action(ACTION_CLOSE, null);
|
||||
+ }
|
||||
+
|
||||
internal void set_mode(PresentationMode new_mode) {
|
||||
this.current_mode = new_mode;
|
||||
this.header.set_mode(new_mode);
|
||||
diff --git a/ui/application-main-window.ui b/ui/application-main-window.ui
|
||||
index fe66491b..cbaacbcf 100644
|
||||
--- a/ui/application-main-window.ui
|
||||
+++ b/ui/application-main-window.ui
|
||||
@@ -29,6 +29,8 @@
|
||||
<property name="can_focus">True</property>
|
||||
<property name="can_swipe_back">True</property>
|
||||
<property name="transition_type">over</property>
|
||||
+ <signal name="notify::visible-child" handler="on_main_leaflet_visible_child_changed" swapped="no"/>
|
||||
+ <signal name="notify::child-transition-running" handler="on_main_leaflet_visible_child_changed" swapped="no"/>
|
||||
<child>
|
||||
<object class="HdyLeaflet" id="conversations_leaflet">
|
||||
<property name="visible">True</property>
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,34 @@
|
||||
From f8f223da46716a0a888ef5a5a0840fb69dbc7067 Mon Sep 17 00:00:00 2001
|
||||
From: Julian Sparber <julian@sparber.net>
|
||||
Date: Wed, 7 Oct 2020 10:36:50 +0200
|
||||
Subject: [PATCH 061/124] main-window: Block forward navigation when viewer is
|
||||
empty
|
||||
|
||||
Empty viewer includes: - no selected conversation
|
||||
- no conversation in folder
|
||||
- selected more then one conversation
|
||||
---
|
||||
src/client/application/application-main-window.vala | 7 +++++--
|
||||
1 file changed, 5 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/client/application/application-main-window.vala b/src/client/application/application-main-window.vala
|
||||
index e1e55d0e..3b7c29e7 100644
|
||||
--- a/src/client/application/application-main-window.vala
|
||||
+++ b/src/client/application/application-main-window.vala
|
||||
@@ -1811,8 +1811,11 @@ public class Application.MainWindow :
|
||||
conversations_leaflet.navigate(Hdy.NavigationDirection.FORWARD);
|
||||
focus = this.conversation_list_view;
|
||||
} else {
|
||||
- main_leaflet.navigate(Hdy.NavigationDirection.FORWARD);
|
||||
- focus = this.conversation_viewer.visible_child;
|
||||
+ if (this.main_toolbar.selected_conversations == 1 &&
|
||||
+ this.selected_folder.properties.email_total > 0) {
|
||||
+ main_leaflet.navigate(Hdy.NavigationDirection.FORWARD);
|
||||
+ focus = this.conversation_viewer.visible_child;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
} else if (focus != null) {
|
||||
--
|
||||
2.29.2
|
||||
|
2102
mail-client/geary/files/0062-Update-Swedish-translation.patch
Normal file
2102
mail-client/geary/files/0062-Update-Swedish-translation.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,139 @@
|
||||
From 51b8c501be7d952e0023a72b24c91254b98fc48c Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Sat, 10 Oct 2020 23:55:02 +1100
|
||||
Subject: [PATCH 063/124] Util.Email: Use a single unambiguous date format for
|
||||
reply quote dates
|
||||
|
||||
Rather than using the UI pref for 12/24h clocks, use a single format
|
||||
string that should be reasonably unambiguous and that includes the
|
||||
time zone.
|
||||
|
||||
Fixes #888
|
||||
---
|
||||
src/client/composer/composer-widget.vala | 9 +--
|
||||
src/client/util/util-email.vala | 78 ++++++++++++++----------
|
||||
2 files changed, 49 insertions(+), 38 deletions(-)
|
||||
|
||||
diff --git a/src/client/composer/composer-widget.vala b/src/client/composer/composer-widget.vala
|
||||
index 37e93fb4..503727a9 100644
|
||||
--- a/src/client/composer/composer-widget.vala
|
||||
+++ b/src/client/composer/composer-widget.vala
|
||||
@@ -740,7 +740,7 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
|
||||
);
|
||||
add_recipients_and_ids(type, full_context);
|
||||
complete_quote = Util.Email.quote_email_for_reply(
|
||||
- full_context, quote, this.config.clock_format, HTML
|
||||
+ full_context, quote, HTML
|
||||
);
|
||||
if (!Geary.String.is_empty(quote)) {
|
||||
this.top_posting = false;
|
||||
@@ -1291,12 +1291,7 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
|
||||
// Always use reply styling, since forward styling doesn't
|
||||
// work for inline quotes
|
||||
this.editor.body.insert_html(
|
||||
- Util.Email.quote_email_for_reply(
|
||||
- referred,
|
||||
- to_quote,
|
||||
- this.config.clock_format,
|
||||
- Geary.RFC822.TextFormat.HTML
|
||||
- )
|
||||
+ Util.Email.quote_email_for_reply(referred, to_quote, HTML)
|
||||
);
|
||||
}
|
||||
|
||||
diff --git a/src/client/util/util-email.vala b/src/client/util/util-email.vala
|
||||
index a18a45cf..4a1754a7 100644
|
||||
--- a/src/client/util/util-email.vala
|
||||
+++ b/src/client/util/util-email.vala
|
||||
@@ -177,41 +177,57 @@ namespace Util.Email {
|
||||
*/
|
||||
public string quote_email_for_reply(Geary.Email email,
|
||||
string? quote,
|
||||
- Util.Date.ClockFormat clock_format,
|
||||
Geary.RFC822.TextFormat format) {
|
||||
- if (email.body == null && quote == null)
|
||||
- return "";
|
||||
-
|
||||
string quoted = "";
|
||||
+ if (email.body != null || quote != null) {
|
||||
+ /// GLib g_date_time_format format string for the date and
|
||||
+ /// time that a message being replied to was
|
||||
+ /// received. This should be roughly similar to an RFC
|
||||
+ /// 822-style date header value with optional additional
|
||||
+ /// punctuation for readability. Note that this date may
|
||||
+ /// be sent to someone in a different locale than the
|
||||
+ /// sender, so should be unambiguous (for example, do not
|
||||
+ /// use mm/dd/yyyy since it could be confused with
|
||||
+ /// dd/mm/yyyy) and must include the time zone.
|
||||
+ string date_format = _("%a, %b %-e %Y at %X %Z");
|
||||
|
||||
- string DATE_FORMAT = Util.Date.get_full_date(clock_format);
|
||||
-
|
||||
- if (email.date != null && email.from != null) {
|
||||
- /// The quoted header for a message being replied to.
|
||||
- /// %1$s will be substituted for the date, and %2$s will be substituted for
|
||||
- /// the original sender.
|
||||
- string QUOTED_LABEL = _("On %1$s, %2$s wrote:");
|
||||
- quoted += QUOTED_LABEL.printf(email.date.value.format(DATE_FORMAT),
|
||||
- Geary.RFC822.Utils.email_addresses_for_reply(email.from, format));
|
||||
-
|
||||
- } else if (email.from != null) {
|
||||
- /// The quoted header for a message being replied to (in case the date is not known).
|
||||
- /// %s will be replaced by the original sender.
|
||||
- string QUOTED_LABEL = _("%s wrote:");
|
||||
- quoted += QUOTED_LABEL.printf(Geary.RFC822.Utils.email_addresses_for_reply(email.from, format));
|
||||
-
|
||||
- } else if (email.date != null) {
|
||||
- /// The quoted header for a message being replied to (in case the sender is not known).
|
||||
- /// %s will be replaced by the original date
|
||||
- string QUOTED_LABEL = _("On %s:");
|
||||
- quoted += QUOTED_LABEL.printf(email.date.value.format(DATE_FORMAT));
|
||||
- }
|
||||
+ if (email.date != null && email.from != null) {
|
||||
+ /// The quoted header for a message being replied to.
|
||||
+ /// %1$s will be substituted for the date, and %2$s
|
||||
+ /// will be substituted for the original sender.
|
||||
+ string QUOTED_LABEL = _("On %1$s, %2$s wrote:");
|
||||
+ quoted += QUOTED_LABEL.printf(
|
||||
+ email.date.value.format(date_format),
|
||||
+ Geary.RFC822.Utils.email_addresses_for_reply(
|
||||
+ email.from, format
|
||||
+ )
|
||||
+ );
|
||||
+ } else if (email.from != null) {
|
||||
+ /// The quoted header for a message being replied to
|
||||
+ /// (in case the date is not known). %s will be
|
||||
+ /// replaced by the original sender.
|
||||
+ string QUOTED_LABEL = _("%s wrote:");
|
||||
+ quoted += QUOTED_LABEL.printf(
|
||||
+ Geary.RFC822.Utils.email_addresses_for_reply(
|
||||
+ email.from, format
|
||||
+ )
|
||||
+ );
|
||||
+ } else if (email.date != null) {
|
||||
+ /// The quoted header for a message being replied to
|
||||
+ /// (in case the sender is not known). %s will be
|
||||
+ /// replaced by the original date
|
||||
+ string QUOTED_LABEL = _("On %s:");
|
||||
+ quoted += QUOTED_LABEL.printf(
|
||||
+ email.date.value.format(date_format)
|
||||
+ );
|
||||
+ }
|
||||
|
||||
- quoted += "<br />";
|
||||
- try {
|
||||
- quoted += quote_body(email, quote, true, format);
|
||||
- } catch (Error err) {
|
||||
- debug("Failed to quote body for replying: %s".printf(err.message));
|
||||
+ quoted += "<br />";
|
||||
+ try {
|
||||
+ quoted += quote_body(email, quote, true, format);
|
||||
+ } catch (Error err) {
|
||||
+ debug("Failed to quote body for replying: %s".printf(err.message));
|
||||
+ }
|
||||
}
|
||||
|
||||
return quoted;
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,49 @@
|
||||
From 4be51e01c02f57fe68121603888ca012000d845d Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Sat, 10 Oct 2020 23:57:11 +1100
|
||||
Subject: [PATCH 064/124] Util.Date: Remove now unused function
|
||||
|
||||
---
|
||||
src/client/util/util-date.vala | 28 ----------------------------
|
||||
1 file changed, 28 deletions(-)
|
||||
|
||||
diff --git a/src/client/util/util-date.vala b/src/client/util/util-date.vala
|
||||
index 88948916..322a4cf2 100644
|
||||
--- a/src/client/util/util-date.vala
|
||||
+++ b/src/client/util/util-date.vala
|
||||
@@ -208,32 +208,4 @@ public string get_clock_format(ClockFormat clock_format) {
|
||||
return xlat_pretty_clocks[clock_format.to_index()];
|
||||
}
|
||||
|
||||
-public string get_full_date(ClockFormat clock_format) {
|
||||
- var value = "";
|
||||
- switch (clock_format) {
|
||||
- case TWELVE_HOURS:
|
||||
- /// 12 hours format for datetime that a message being replied
|
||||
- /// to was received See
|
||||
- /// http://developer.gnome.org/glib/2.32/glib-GDateTime.html#g-date-time-format
|
||||
- value = _("%a, %b %-e, %Y at %l:%M %P");
|
||||
- break;
|
||||
- case TWENTY_FOUR_HOURS:
|
||||
- /// 24 hours format for the datetime that a message being
|
||||
- /// replied to was received See
|
||||
- /// http://developer.gnome.org/glib/2.32/glib-GDateTime.html#g-date-time-format
|
||||
- value = _("%a, %b %-e, %Y at %H:%M");
|
||||
- break;
|
||||
- case LOCALE_DEFAULT:
|
||||
- /// Format for the datetime that a message being replied to
|
||||
- /// was received See
|
||||
- /// http://developer.gnome.org/glib/2.32/glib-GDateTime.html#g-date-time-format
|
||||
- value = _("%a, %b %-e, %Y at %X");
|
||||
- break;
|
||||
- case TOTAL:
|
||||
- // noop
|
||||
- break;
|
||||
- }
|
||||
- return value;
|
||||
-}
|
||||
-
|
||||
}
|
||||
--
|
||||
2.29.2
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,187 @@
|
||||
From 70a40893a3f41483fbc607512d311f4c0c44c79a Mon Sep 17 00:00:00 2001
|
||||
From: Julian Sparber <julian@sparber.net>
|
||||
Date: Thu, 8 Oct 2020 14:50:58 +0200
|
||||
Subject: [PATCH 066/124] action-bar: Add an action bar to the conversations
|
||||
list (2-panel)
|
||||
|
||||
This moves the actions from the headerbar to the action bar at the
|
||||
bottom of the conversations list when multiple conversations are
|
||||
selected. This changes is needed so that the user can still interact
|
||||
with the conversations when folded.
|
||||
This also hides the actions from the Headerbar and action bar when
|
||||
no conversation is selected.
|
||||
---
|
||||
po/POTFILES.in | 2 +
|
||||
.../application/application-main-window.vala | 19 +++++++++
|
||||
.../components-conversation-action-bar.vala | 39 +++++++++++++++++++
|
||||
src/client/meson.build | 1 +
|
||||
ui/components-conversation-action-bar.ui | 22 +++++++++++
|
||||
ui/org.gnome.Geary.gresource.xml | 1 +
|
||||
6 files changed, 84 insertions(+)
|
||||
create mode 100644 src/client/components/components-conversation-action-bar.vala
|
||||
create mode 100644 ui/components-conversation-action-bar.ui
|
||||
|
||||
diff --git a/po/POTFILES.in b/po/POTFILES.in
|
||||
index 7ef4e050..68e3ca34 100644
|
||||
--- a/po/POTFILES.in
|
||||
+++ b/po/POTFILES.in
|
||||
@@ -40,6 +40,7 @@ src/client/client-action.vala
|
||||
src/client/components/client-web-view.vala
|
||||
src/client/components/components-attachment-pane.vala
|
||||
src/client/components/components-conversation-actions.vala
|
||||
+src/client/components/components-conversation-action-bar.vala
|
||||
src/client/components/components-entry-undo.vala
|
||||
src/client/components/components-in-app-notification.vala
|
||||
src/client/components/components-info-bar-stack.vala
|
||||
@@ -457,6 +458,7 @@ ui/components-attachment-pane.ui
|
||||
ui/components-attachment-pane-menus.ui
|
||||
ui/components-attachment-view.ui
|
||||
ui/components-conversation-actions.ui
|
||||
+ui/components-conversation-action-bar.ui
|
||||
ui/components-in-app-notification.ui
|
||||
ui/components-inspector-error-view.ui
|
||||
ui/components-inspector-log-view.ui
|
||||
diff --git a/src/client/application/application-main-window.vala b/src/client/application/application-main-window.vala
|
||||
index 20fc3758..0e6a89e1 100644
|
||||
--- a/src/client/application/application-main-window.vala
|
||||
+++ b/src/client/application/application-main-window.vala
|
||||
@@ -351,6 +351,8 @@ public class Application.MainWindow :
|
||||
[GtkChild]
|
||||
private Gtk.Overlay overlay;
|
||||
|
||||
+ private Components.ConversationActionBar action_bar;
|
||||
+
|
||||
private Components.InfoBarStack info_bars =
|
||||
new Components.InfoBarStack(SINGLE);
|
||||
|
||||
@@ -1308,6 +1310,12 @@ public class Application.MainWindow :
|
||||
this.spinner.set_progress_monitor(progress_monitor);
|
||||
this.status_bar.add(this.spinner);
|
||||
this.status_bar.show_all();
|
||||
+
|
||||
+ // Action bar
|
||||
+ this.action_bar = new Components.ConversationActionBar();
|
||||
+ this.conversation_list_box.add_with_properties(action_bar,
|
||||
+ "pack-type", Gtk.PackType.END,
|
||||
+ "position", 0);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@@ -1740,6 +1748,17 @@ public class Application.MainWindow :
|
||||
);
|
||||
|
||||
this.update_context_dependent_actions.begin(sensitive);
|
||||
+ switch (count) {
|
||||
+ case NONE:
|
||||
+ conversation_actions.take_ownership(null);
|
||||
+ break;
|
||||
+ case SINGLE:
|
||||
+ this.main_toolbar.add_conversation_actions(this.conversation_actions);
|
||||
+ break;
|
||||
+ case MULTIPLE:
|
||||
+ this.action_bar.add_conversation_actions(this.conversation_actions);
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
|
||||
private async void update_context_dependent_actions(bool sensitive) {
|
||||
diff --git a/src/client/components/components-conversation-action-bar.vala b/src/client/components/components-conversation-action-bar.vala
|
||||
new file mode 100644
|
||||
index 00000000..cb574521
|
||||
--- /dev/null
|
||||
+++ b/src/client/components/components-conversation-action-bar.vala
|
||||
@@ -0,0 +1,39 @@
|
||||
+/*
|
||||
+ * Copyright © 2016 Software Freedom Conservancy Inc.
|
||||
+ * Copyright © 2020 Purism SPC
|
||||
+ *
|
||||
+ * This software is licensed under the GNU Lesser General Public License
|
||||
+ * (version 2.1 or later). See the COPYING file in this distribution.
|
||||
+ */
|
||||
+
|
||||
+// Draws the conversation action bar.
|
||||
+[GtkTemplate (ui = "/org/gnome/Geary/components-conversation-action-bar.ui")]
|
||||
+public class Components.ConversationActionBar : Gtk.Revealer {
|
||||
+ private ulong owner_notify;
|
||||
+
|
||||
+ [GtkChild]
|
||||
+ private Gtk.Box action_box;
|
||||
+
|
||||
+ public ConversationActionBar() {
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * This takes ownership of the ConversationActions and places some of
|
||||
+ * the buttons into the ActionBar.
|
||||
+ */
|
||||
+ public void add_conversation_actions(Components.ConversationActions actions) {
|
||||
+ if (actions.owner == this)
|
||||
+ return;
|
||||
+
|
||||
+ actions.take_ownership(this);
|
||||
+ action_box.pack_start(actions.mark_copy_move_buttons, false, false);
|
||||
+ action_box.pack_end(actions.archive_trash_delete_buttons, false, false);
|
||||
+ reveal_child = true;
|
||||
+ this.owner_notify = actions.notify["owner"].connect(() => {
|
||||
+ if (actions.owner != this) {
|
||||
+ reveal_child = false;
|
||||
+ actions.disconnect (this.owner_notify);
|
||||
+ }
|
||||
+ });
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/client/meson.build b/src/client/meson.build
|
||||
index ed0d6b33..c0eb0c16 100644
|
||||
--- a/src/client/meson.build
|
||||
+++ b/src/client/meson.build
|
||||
@@ -49,6 +49,7 @@ client_vala_sources = files(
|
||||
'components/client-web-view.vala',
|
||||
'components/components-attachment-pane.vala',
|
||||
'components/components-conversation-actions.vala',
|
||||
+ 'components/components-conversation-action-bar.vala',
|
||||
'components/components-entry-undo.vala',
|
||||
'components/components-info-bar-stack.vala',
|
||||
'components/components-info-bar.vala',
|
||||
diff --git a/ui/components-conversation-action-bar.ui b/ui/components-conversation-action-bar.ui
|
||||
new file mode 100644
|
||||
index 00000000..ae49683f
|
||||
--- /dev/null
|
||||
+++ b/ui/components-conversation-action-bar.ui
|
||||
@@ -0,0 +1,22 @@
|
||||
+<?xml version="1.0" encoding="UTF-8"?>
|
||||
+<interface>
|
||||
+ <requires lib="gtk+" version="3.20"/>
|
||||
+ <object class="GtkImage" id="archive_image">
|
||||
+ <property name="visible">True</property>
|
||||
+ <property name="can_focus">False</property>
|
||||
+ <property name="icon_name">mail-archive-symbolic</property>
|
||||
+ </object>
|
||||
+ <template class="ComponentsConversationActionBar" parent="GtkRevealer">
|
||||
+ <property name="visible">True</property>
|
||||
+ <property name="can_focus">False</property>
|
||||
+ <property name="transition_type">slide-up</property>
|
||||
+ <child>
|
||||
+ <object class="GtkBox" id="action_box">
|
||||
+ <property name="visible">True</property>
|
||||
+ <property name="can_focus">False</property>
|
||||
+ <property name="hexpand">True</property>
|
||||
+ <property name="margin">6</property>
|
||||
+ </object>
|
||||
+ </child>
|
||||
+ </template>
|
||||
+</interface>
|
||||
diff --git a/ui/org.gnome.Geary.gresource.xml b/ui/org.gnome.Geary.gresource.xml
|
||||
index 481bbff4..e064d331 100644
|
||||
--- a/ui/org.gnome.Geary.gresource.xml
|
||||
+++ b/ui/org.gnome.Geary.gresource.xml
|
||||
@@ -14,6 +14,7 @@
|
||||
<file compressed="true" preprocess="xml-stripblanks">components-attachment-pane.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">components-attachment-pane-menus.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">components-attachment-view.ui</file>
|
||||
+ <file compressed="true" preprocess="xml-stripblanks">components-conversation-action-bar.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">components-conversation-actions.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">components-in-app-notification.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">components-inspector.ui</file>
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,34 @@
|
||||
From 0010550ad6f7d053b83f1857215294ce2b69f833 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Mon, 12 Oct 2020 23:22:47 +1100
|
||||
Subject: [PATCH 067/124] Application.Client: Work around libhandy bug when
|
||||
opening main windows
|
||||
|
||||
GNOME/libhandy#305
|
||||
---
|
||||
src/client/application/application-client.vala | 9 +++++++++
|
||||
1 file changed, 9 insertions(+)
|
||||
|
||||
diff --git a/src/client/application/application-client.vala b/src/client/application/application-client.vala
|
||||
index 2bf4e094..46469086 100644
|
||||
--- a/src/client/application/application-client.vala
|
||||
+++ b/src/client/application/application-client.vala
|
||||
@@ -892,6 +892,15 @@ public class Application.Client : Gtk.Application {
|
||||
}
|
||||
|
||||
private MainWindow new_main_window(bool select_first_inbox) {
|
||||
+ // Work around warning caused by GNOME/libhandy#305 which
|
||||
+ // makes it a pita to run with G_DEBUG=fatal-warnings. Remove
|
||||
+ // once the fix for that issue has been released and packaged.
|
||||
+ GLib.Test.expect_message(
|
||||
+ "GLib-GObject",
|
||||
+ LEVEL_WARNING,
|
||||
+ "g_object_weak_unref: couldn't find weak ref *"
|
||||
+ );
|
||||
+
|
||||
MainWindow window = new MainWindow(this);
|
||||
this.controller.register_window(window);
|
||||
window.focus_in_event.connect(on_main_window_focus_in);
|
||||
--
|
||||
2.29.2
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,330 @@
|
||||
From 1ba2bd0f5ba655b38aff63d6332b0bb52c704119 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Wed, 26 Aug 2020 15:20:12 +1000
|
||||
Subject: [PATCH 069/124] Util.JS: Support converting between JSC.Value and
|
||||
GLib.Variant objects
|
||||
|
||||
Add `variant_to_value` and `value_to_variant` methods, document them
|
||||
and add tests.
|
||||
---
|
||||
src/client/util/util-js.vala | 159 +++++++++++++++++++++++++++++
|
||||
test/client/util/util-js-test.vala | 125 +++++++++++++++++++++++
|
||||
2 files changed, 284 insertions(+)
|
||||
|
||||
diff --git a/src/client/util/util-js.vala b/src/client/util/util-js.vala
|
||||
index 52c9428b..2f05a3e2 100644
|
||||
--- a/src/client/util/util-js.vala
|
||||
+++ b/src/client/util/util-js.vala
|
||||
@@ -127,6 +127,165 @@ namespace Util.JS {
|
||||
}
|
||||
}
|
||||
|
||||
+ /**
|
||||
+ * Converts a JS value to a GLib variant.
|
||||
+ *
|
||||
+ * Simple value objects (string, number, and Boolean values),
|
||||
+ * arrays of these, and objects with these types as properties are
|
||||
+ * supported. Arrays are converted to arrays of variants, and
|
||||
+ * objects to dictionaries containing string keys and variant
|
||||
+ * values. Null or undefined values are returned as an empty maybe
|
||||
+ * variant type, since it is not possible to determine the actual
|
||||
+ * type.
|
||||
+ *
|
||||
+ * Throws a type error if the given value's type is not supported.
|
||||
+ */
|
||||
+ public inline GLib.Variant value_to_variant(JSC.Value value)
|
||||
+ throws Error {
|
||||
+ if (value.is_null() || value.is_undefined()) {
|
||||
+ return new GLib.Variant.maybe(GLib.VariantType.VARIANT, null);
|
||||
+ }
|
||||
+ if (value.is_boolean()) {
|
||||
+ return new GLib.Variant.boolean(value.to_boolean());
|
||||
+ }
|
||||
+ if (value.is_number()) {
|
||||
+ return new GLib.Variant.double(value.to_double());
|
||||
+ }
|
||||
+ if (value.is_string()) {
|
||||
+ return new GLib.Variant.string(value.to_string());
|
||||
+ }
|
||||
+ if (value.is_array()) {
|
||||
+ int len = to_int32(value.object_get_property("length"));
|
||||
+ GLib.Variant[] values = new GLib.Variant[len];
|
||||
+ for (int i = 0; i < len; i++) {
|
||||
+ values[i] = new GLib.Variant.variant(
|
||||
+ value_to_variant(value.object_get_property_at_index(i))
|
||||
+ );
|
||||
+ }
|
||||
+ return new GLib.Variant.array(GLib.VariantType.VARIANT, values);
|
||||
+ }
|
||||
+ if (value.is_object()) {
|
||||
+ GLib.VariantDict dict = new GLib.VariantDict();
|
||||
+ string[] names = value.object_enumerate_properties();
|
||||
+ if (names != null) {
|
||||
+ foreach (var name in names) {
|
||||
+ try {
|
||||
+ dict.insert_value(
|
||||
+ name,
|
||||
+ new GLib.Variant.variant(
|
||||
+ value_to_variant(
|
||||
+ value.object_get_property(name)
|
||||
+ )
|
||||
+ )
|
||||
+ );
|
||||
+ } catch (Error.TYPE err) {
|
||||
+ // ignored
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ return dict.end();
|
||||
+ }
|
||||
+ throw new Error.TYPE("Unsupported JS type: %s", value.to_string());
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Converts a GLib variant to a JS value.
|
||||
+ *
|
||||
+ * Simple value objects (string, number, and Boolean values),
|
||||
+ * arrays and tuples of these, and dictionaries with string keys
|
||||
+ * are supported. Tuples and arrays are converted to JS arrays,
|
||||
+ * and dictionaries or tuples containing dictionary entries are
|
||||
+ * converted to JS objects.
|
||||
+ *
|
||||
+ * Throws a type error if the given variant's type is not supported.
|
||||
+ */
|
||||
+ public inline JSC.Value variant_to_value(JSC.Context context,
|
||||
+ GLib.Variant variant)
|
||||
+ throws Error.TYPE {
|
||||
+ JSC.Value? value = null;
|
||||
+ GLib.Variant.Class type = variant.classify();
|
||||
+ if (type == MAYBE) {
|
||||
+ GLib.Variant? maybe = variant.get_maybe();
|
||||
+ if (maybe != null) {
|
||||
+ value = variant_to_value(context, maybe);
|
||||
+ } else {
|
||||
+ value = new JSC.Value.null(context);
|
||||
+ }
|
||||
+ } else if (type == VARIANT) {
|
||||
+ value = variant_to_value(context, variant.get_variant());
|
||||
+ } else if (type == STRING) {
|
||||
+ value = new JSC.Value.string(context, variant.get_string());
|
||||
+ } else if (type == BOOLEAN) {
|
||||
+ value = new JSC.Value.boolean(context, variant.get_boolean());
|
||||
+ } else if (type == DOUBLE) {
|
||||
+ value = new JSC.Value.number(context, variant.get_double());
|
||||
+ } else if (type == INT64) {
|
||||
+ value = new JSC.Value.number(context, (double) variant.get_int64());
|
||||
+ } else if (type == INT32) {
|
||||
+ value = new JSC.Value.number(context, (double) variant.get_int32());
|
||||
+ } else if (type == INT16) {
|
||||
+ value = new JSC.Value.number(context, (double) variant.get_int16());
|
||||
+ } else if (type == UINT64) {
|
||||
+ value = new JSC.Value.number(context, (double) variant.get_uint64());
|
||||
+ } else if (type == UINT32) {
|
||||
+ value = new JSC.Value.number(context, (double) variant.get_uint32());
|
||||
+ } else if (type == UINT16) {
|
||||
+ value = new JSC.Value.number(context, (double) variant.get_uint16());
|
||||
+ } else if (type == BYTE) {
|
||||
+ value = new JSC.Value.number(context, (double) variant.get_byte());
|
||||
+ } else if (type == ARRAY ||
|
||||
+ type == TUPLE) {
|
||||
+ size_t len = variant.n_children();
|
||||
+ if (len == 0) {
|
||||
+ if (type == ARRAY ||
|
||||
+ type == TUPLE) {
|
||||
+ value = new JSC.Value.array_from_garray(context, null);
|
||||
+ } else {
|
||||
+ value = new JSC.Value.object(context, null, null);
|
||||
+ }
|
||||
+ } else {
|
||||
+ var first = variant.get_child_value(0);
|
||||
+ if (first.classify() == DICT_ENTRY) {
|
||||
+ value = new JSC.Value.object(context, null, null);
|
||||
+ for (size_t i = 0; i < len; i++) {
|
||||
+ var entry = variant.get_child_value(i);
|
||||
+ if (entry.classify() != DICT_ENTRY) {
|
||||
+ throw new Error.TYPE(
|
||||
+ "Variant mixes dict entries with others: %s",
|
||||
+ variant.print(true)
|
||||
+ );
|
||||
+ }
|
||||
+ var key = entry.get_child_value(0);
|
||||
+ if (key.classify() != STRING) {
|
||||
+ throw new Error.TYPE(
|
||||
+ "Dict entry key is not a string: %s",
|
||||
+ entry.print(true)
|
||||
+ );
|
||||
+ }
|
||||
+ value.object_set_property(
|
||||
+ key.get_string(),
|
||||
+ variant_to_value(context, entry.get_child_value(1))
|
||||
+ );
|
||||
+ }
|
||||
+ } else {
|
||||
+ var values = new GLib.GenericArray<JSC.Value>((uint) len);
|
||||
+ for (size_t i = 0; i < len; i++) {
|
||||
+ values.add(
|
||||
+ variant_to_value(context, variant.get_child_value(i))
|
||||
+ );
|
||||
+ }
|
||||
+ value = new JSC.Value.array_from_garray(context, values);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ if (value == null) {
|
||||
+ throw new Error.TYPE(
|
||||
+ "Unsupported variant type %s", variant.print(true)
|
||||
+ );
|
||||
+ }
|
||||
+ return value;
|
||||
+ }
|
||||
+
|
||||
/**
|
||||
* Escapes a string so as to be safe to use as a JS string literal.
|
||||
*
|
||||
diff --git a/test/client/util/util-js-test.vala b/test/client/util/util-js-test.vala
|
||||
index 1fbe5276..16a01d83 100644
|
||||
--- a/test/client/util/util-js-test.vala
|
||||
+++ b/test/client/util/util-js-test.vala
|
||||
@@ -7,9 +7,23 @@
|
||||
|
||||
public class Util.JS.Test : TestCase {
|
||||
|
||||
+
|
||||
+ private JSC.Context? context = null;
|
||||
+
|
||||
+
|
||||
public Test() {
|
||||
base("Util.JS.Test");
|
||||
add_test("escape_string", escape_string);
|
||||
+ add_test("to_variant", to_variant);
|
||||
+ add_test("to_value", to_value);
|
||||
+ }
|
||||
+
|
||||
+ public override void set_up() throws GLib.Error {
|
||||
+ this.context = new JSC.Context();
|
||||
+ }
|
||||
+
|
||||
+ public override void tear_down() throws GLib.Error {
|
||||
+ this.context = null;
|
||||
}
|
||||
|
||||
public void escape_string() throws GLib.Error {
|
||||
@@ -21,4 +35,115 @@ public class Util.JS.Test : TestCase {
|
||||
|
||||
assert(Util.JS.escape_string("something…\n") == """something…\n""");
|
||||
}
|
||||
+
|
||||
+ public void to_variant() throws GLib.Error {
|
||||
+ assert_equal(
|
||||
+ value_to_variant(new JSC.Value.null(this.context)).print(true),
|
||||
+ "@mv nothing"
|
||||
+ );
|
||||
+ assert_equal(
|
||||
+ value_to_variant(new JSC.Value.string(this.context, "test")).print(true),
|
||||
+ "'test'"
|
||||
+ );
|
||||
+ assert_equal(
|
||||
+ value_to_variant(new JSC.Value.number(this.context, 1.0)).print(true),
|
||||
+ "1.0"
|
||||
+ );
|
||||
+ assert_equal(
|
||||
+ value_to_variant(new JSC.Value.boolean(this.context, true)).print(true),
|
||||
+ "true"
|
||||
+ );
|
||||
+ assert_equal(
|
||||
+ value_to_variant(new JSC.Value.boolean(this.context, false)).print(true),
|
||||
+ "false"
|
||||
+ );
|
||||
+
|
||||
+ var value = new JSC.Value.array_from_garray(this.context, null);
|
||||
+ assert_equal(
|
||||
+ value_to_variant(value).print(true),
|
||||
+ "@av []"
|
||||
+ );
|
||||
+ var array = new GLib.GenericArray<JSC.Value>();
|
||||
+ array.add(new JSC.Value.string(this.context, "test"));
|
||||
+ value = new JSC.Value.array_from_garray(this.context, array);
|
||||
+ assert_equal(
|
||||
+ value_to_variant(value).print(true),
|
||||
+ "[<'test'>]"
|
||||
+ );
|
||||
+ value = new JSC.Value.object(this.context, null, null);
|
||||
+ assert_equal(
|
||||
+ value_to_variant(value).print(true),
|
||||
+ "@a{sv} {}"
|
||||
+ );
|
||||
+ value.object_set_property(
|
||||
+ "test", new JSC.Value.boolean(this.context, true)
|
||||
+ );
|
||||
+ assert_equal(
|
||||
+ value_to_variant(value).print(true),
|
||||
+ "{'test': <<true>>}"
|
||||
+ );
|
||||
+ }
|
||||
+
|
||||
+ public void to_value() throws GLib.Error {
|
||||
+ var variant = new GLib.Variant.maybe(GLib.VariantType.STRING, null);
|
||||
+ var value = variant_to_value(this.context, variant);
|
||||
+ assert_true(value.is_null(), variant.print(true));
|
||||
+
|
||||
+ variant = new GLib.Variant.string("test");
|
||||
+ value = variant_to_value(this.context, variant);
|
||||
+ assert_true(value.is_string(), variant.print(true));
|
||||
+ assert_equal(value.to_string(), "test", variant.print(true));
|
||||
+
|
||||
+ variant = new GLib.Variant.int32(42);
|
||||
+ value = variant_to_value(this.context, variant);
|
||||
+ assert_true(value.is_number(), variant.print(true));
|
||||
+ assert_equal<int32?>(value.to_int32(), 42, variant.print(true));
|
||||
+
|
||||
+ variant = new GLib.Variant.double(42.0);
|
||||
+ value = variant_to_value(this.context, variant);
|
||||
+ assert_true(value.is_number(), variant.print(true));
|
||||
+ assert_within(value.to_double(), 42.0, 0.0000001, variant.print(true));
|
||||
+
|
||||
+ variant = new GLib.Variant.boolean(true);
|
||||
+ value = variant_to_value(this.context, variant);
|
||||
+ assert_true(value.is_boolean(), variant.print(true));
|
||||
+ assert_true(value.to_boolean(), variant.print(true));
|
||||
+
|
||||
+ variant = new GLib.Variant.boolean(false);
|
||||
+ value = variant_to_value(this.context, variant);
|
||||
+ assert_true(value.is_boolean(), variant.print(true));
|
||||
+ assert_false(value.to_boolean(), variant.print(true));
|
||||
+
|
||||
+ variant = new GLib.Variant.strv({"test"});
|
||||
+ value = variant_to_value(this.context, variant);
|
||||
+ assert_true(value.is_array(), variant.print(true));
|
||||
+ assert_true(
|
||||
+ value.object_get_property_at_index(0).is_string(),
|
||||
+ variant.print(true)
|
||||
+ );
|
||||
+ assert_equal(
|
||||
+ value.object_get_property_at_index(0).to_string(),
|
||||
+ "test",
|
||||
+ variant.print(true)
|
||||
+ );
|
||||
+
|
||||
+ var dict = new GLib.VariantDict();
|
||||
+ variant = dict.end();
|
||||
+ value = variant_to_value(this.context, variant);
|
||||
+ assert_true(value.is_object(), variant.print(true));
|
||||
+
|
||||
+ dict = new GLib.VariantDict();
|
||||
+ dict.insert_value("test", new GLib.Variant.boolean(true));
|
||||
+ variant = dict.end();
|
||||
+ value = variant_to_value(this.context, variant);
|
||||
+ assert_true(value.is_object(), variant.print(true));
|
||||
+ assert_true(
|
||||
+ value.object_get_property("test").is_boolean(),
|
||||
+ value.to_string()
|
||||
+ );
|
||||
+ assert_true(
|
||||
+ value.object_get_property("test").to_boolean(),
|
||||
+ value.to_string()
|
||||
+ );
|
||||
+ }
|
||||
}
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,644 @@
|
||||
From ff565bc6efc83badbecfb48d2fbb457f4d2f681c Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Thu, 27 Aug 2020 12:12:22 +1000
|
||||
Subject: [PATCH 070/124] Components.WebView: Convert to using messages for JS
|
||||
method invocation
|
||||
|
||||
Use WebKitGTK UserMessage objects for invoking JS methods rather than
|
||||
serialising to JS strings and running those. This is possibly slightly
|
||||
less efficient, but removes the onus on serialising to and parsing from
|
||||
JS and once switched over from message handlers to UserMessage objects
|
||||
will be using a single uniform IPC interface for both.
|
||||
---
|
||||
.../components/components-web-view.vala | 97 +++++++++++++++++--
|
||||
src/client/composer/composer-web-view.vala | 67 ++++++-------
|
||||
src/client/composer/composer-widget.vala | 19 ++--
|
||||
.../conversation-web-view.vala | 15 ++-
|
||||
src/client/util/util-js.vala | 36 ++++---
|
||||
.../web-process/web-process-extension.vala | 53 ++++++++++
|
||||
test/js/components-page-state-test.vala | 45 +++++++++
|
||||
ui/components-web-view.js | 10 ++
|
||||
8 files changed, 268 insertions(+), 74 deletions(-)
|
||||
|
||||
diff --git a/src/client/components/components-web-view.vala b/src/client/components/components-web-view.vala
|
||||
index 4bda1c11..368b6a8d 100644
|
||||
--- a/src/client/components/components-web-view.vala
|
||||
+++ b/src/client/components/components-web-view.vala
|
||||
@@ -370,9 +370,7 @@ public abstract class Components.WebView : WebKit.WebView, Geary.BaseInterface {
|
||||
* Returns the view's content as an HTML string.
|
||||
*/
|
||||
public async string? get_html() throws Error {
|
||||
- return Util.JS.to_string(
|
||||
- yield call(Util.JS.callable("geary.getHtml"), null)
|
||||
- );
|
||||
+ return yield call_returning<string?>(Util.JS.callable("getHtml"), null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -410,7 +408,7 @@ public abstract class Components.WebView : WebKit.WebView, Geary.BaseInterface {
|
||||
* Load any remote images previously that were blocked.
|
||||
*/
|
||||
public void load_remote_images() {
|
||||
- this.call.begin(Util.JS.callable("geary.loadRemoteImages"), null);
|
||||
+ this.call_void.begin(Util.JS.callable("loadRemoteImages"), null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -455,21 +453,100 @@ public abstract class Components.WebView : WebKit.WebView, Geary.BaseInterface {
|
||||
public new async void set_editable(bool enabled,
|
||||
Cancellable? cancellable)
|
||||
throws Error {
|
||||
- yield call(
|
||||
- Util.JS.callable("geary.setEditable").bool(enabled), cancellable
|
||||
+ yield call_void(
|
||||
+ Util.JS.callable("setEditable").bool(enabled), cancellable
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes a {@link Util.JS.Callable} on this web view.
|
||||
+ *
|
||||
+ * This calls the given callable on the `geary` object for the
|
||||
+ * current view, any returned value are ignored.
|
||||
*/
|
||||
- protected async JSC.Value call(Util.JS.Callable target,
|
||||
+ protected async void call_void(Util.JS.Callable target,
|
||||
GLib.Cancellable? cancellable)
|
||||
throws GLib.Error {
|
||||
- WebKit.JavascriptResult result = yield run_javascript(
|
||||
- target.to_string(), cancellable
|
||||
+ yield send_message_to_page(
|
||||
+ target.to_message(), cancellable
|
||||
);
|
||||
- return result.get_js_value();
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Invokes a {@link Util.JS.Callable} on this web view.
|
||||
+ *
|
||||
+ * This calls the given callable on the `geary` object for the
|
||||
+ * current view. The value returned by the call is returned by
|
||||
+ * this method.
|
||||
+ *
|
||||
+ * The type parameter `T` must match the type returned by the
|
||||
+ * call, else an error is thrown. Only simple nullable value types
|
||||
+ * are supported for T, for more complex return types (arrays,
|
||||
+ * dictionaries, etc) specify {@link GLib.Variant} for `T` and
|
||||
+ * manually parse that.
|
||||
+ */
|
||||
+ protected async T call_returning<T>(Util.JS.Callable target,
|
||||
+ GLib.Cancellable? cancellable)
|
||||
+ throws GLib.Error {
|
||||
+ WebKit.UserMessage? response = yield send_message_to_page(
|
||||
+ target.to_message(), cancellable
|
||||
+ );
|
||||
+ if (response == null) {
|
||||
+ throw new Util.JS.Error.TYPE(
|
||||
+ "Method call did not return a value: %s", target.to_string()
|
||||
+ );
|
||||
+ }
|
||||
+ GLib.Variant? param = response.parameters;
|
||||
+ T ret_value = null;
|
||||
+ var ret_type = typeof(T);
|
||||
+ if (ret_type == typeof(GLib.Variant)) {
|
||||
+ ret_value = param;
|
||||
+ } else {
|
||||
+ if (param != null && param.get_type().is_maybe()) {
|
||||
+ param = param.get_maybe();
|
||||
+ }
|
||||
+ if (param != null) {
|
||||
+ // Since these replies are coming from JS via
|
||||
+ // Util.JS.value_to_variant, they will only be one of
|
||||
+ // string, double, bool, array or dict
|
||||
+ var param_type = param.classify();
|
||||
+ if (ret_type == typeof(string) && param_type == STRING) {
|
||||
+ ret_value = param.get_string();
|
||||
+ } else if (ret_type == typeof(bool) && param_type == BOOLEAN) {
|
||||
+ ret_value = (bool?) param.get_boolean();
|
||||
+ } else if (ret_type == typeof(int) && param_type == DOUBLE) {
|
||||
+ ret_value = (int?) ((int) param.get_double());
|
||||
+ } else if (ret_type == typeof(short) && param_type == DOUBLE) {
|
||||
+ ret_value = (short?) ((short) param.get_double());
|
||||
+ } else if (ret_type == typeof(char) && param_type == DOUBLE) {
|
||||
+ ret_value = (char?) ((char) param.get_double());
|
||||
+ } else if (ret_type == typeof(long) && param_type == DOUBLE) {
|
||||
+ ret_value = (long?) ((long) param.get_double());
|
||||
+ } else if (ret_type == typeof(int64) && param_type == DOUBLE) {
|
||||
+ ret_value = (int64?) ((int64) param.get_double());
|
||||
+ } else if (ret_type == typeof(uint) && param_type == DOUBLE) {
|
||||
+ ret_value = (uint?) ((uint) param.get_double());
|
||||
+ } else if (ret_type == typeof(uchar) && param_type == DOUBLE) {
|
||||
+ ret_value = (uchar?) ((uchar) param.get_double());
|
||||
+ } else if (ret_type == typeof(ushort) && param_type == DOUBLE) {
|
||||
+ ret_value = (ushort?) ((ushort) param.get_double());
|
||||
+ } else if (ret_type == typeof(ulong) && param_type == DOUBLE) {
|
||||
+ ret_value = (ulong?) ((ulong) param.get_double());
|
||||
+ } else if (ret_type == typeof(uint64) && param_type == DOUBLE) {
|
||||
+ ret_value = (uint64?) ((uint64) param.get_double());
|
||||
+ } else if (ret_type == typeof(double) && param_type == DOUBLE) {
|
||||
+ ret_value = (double?) param.get_double();
|
||||
+ } else if (ret_type == typeof(float) && param_type == DOUBLE) {
|
||||
+ ret_value = (float?) ((float) param.get_double());
|
||||
+ } else {
|
||||
+ throw new Util.JS.Error.TYPE(
|
||||
+ "%s is not a supported type for %s",
|
||||
+ ret_type.name(), param_type.to_string()
|
||||
+ );
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ return ret_value;
|
||||
}
|
||||
|
||||
/**
|
||||
diff --git a/src/client/composer/composer-web-view.vala b/src/client/composer/composer-web-view.vala
|
||||
index f8ecccf6..24a2740c 100644
|
||||
--- a/src/client/composer/composer-web-view.vala
|
||||
+++ b/src/client/composer/composer-web-view.vala
|
||||
@@ -202,8 +202,8 @@ public class Composer.WebView : Components.WebView {
|
||||
* Returns the view's content as HTML without being cleaned.
|
||||
*/
|
||||
public async string? get_html_for_draft() throws Error {
|
||||
- return Util.JS.to_string(
|
||||
- yield call(Util.JS.callable("geary.getHtml").bool(false), null)
|
||||
+ return yield call_returning<string?>(
|
||||
+ Util.JS.callable("getHtml").bool(false), null
|
||||
);
|
||||
}
|
||||
|
||||
@@ -213,8 +213,8 @@ public class Composer.WebView : Components.WebView {
|
||||
public void set_rich_text(bool enabled) {
|
||||
this.is_rich_text = enabled;
|
||||
if (this.is_content_loaded) {
|
||||
- this.call.begin(
|
||||
- Util.JS.callable("geary.setRichText").bool(enabled), null
|
||||
+ this.call_void.begin(
|
||||
+ Util.JS.callable("setRichText").bool(enabled), null
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -223,14 +223,14 @@ public class Composer.WebView : Components.WebView {
|
||||
* Undoes the last edit operation.
|
||||
*/
|
||||
public void undo() {
|
||||
- this.call.begin(Util.JS.callable("geary.undo"), null);
|
||||
+ this.call_void.begin(Util.JS.callable("undo"), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Redoes the last undone edit operation.
|
||||
*/
|
||||
public void redo() {
|
||||
- this.call.begin(Util.JS.callable("geary.redo"), null);
|
||||
+ this.call_void.begin(Util.JS.callable("redo"), null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -239,9 +239,9 @@ public class Composer.WebView : Components.WebView {
|
||||
* Returns an id to be used to refer to the selection in
|
||||
* subsequent calls.
|
||||
*/
|
||||
- public async string save_selection() throws Error {
|
||||
- return Util.JS.to_string(
|
||||
- yield call(Util.JS.callable("geary.saveSelection"), null)
|
||||
+ public async string? save_selection() throws Error {
|
||||
+ return yield call_returning<string?>(
|
||||
+ Util.JS.callable("saveSelection"), null
|
||||
);
|
||||
}
|
||||
|
||||
@@ -249,9 +249,7 @@ public class Composer.WebView : Components.WebView {
|
||||
* Removes a saved selection.
|
||||
*/
|
||||
public void free_selection(string id) {
|
||||
- this.call.begin(
|
||||
- Util.JS.callable("geary.freeSelection").string(id), null
|
||||
- );
|
||||
+ this.call_void.begin(Util.JS.callable("freeSelection").string(id), null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -357,9 +355,9 @@ public class Composer.WebView : Components.WebView {
|
||||
* will be inserted wrapping the selection.
|
||||
*/
|
||||
public void insert_link(string href, string selection_id) {
|
||||
- this.call.begin(
|
||||
+ this.call_void.begin(
|
||||
Util.JS.callable(
|
||||
- "geary.insertLink"
|
||||
+ "insertLink"
|
||||
).string(href).string(selection_id),
|
||||
null
|
||||
);
|
||||
@@ -373,8 +371,8 @@ public class Composer.WebView : Components.WebView {
|
||||
* unlinked section.
|
||||
*/
|
||||
public void delete_link(string selection_id) {
|
||||
- this.call.begin(
|
||||
- Util.JS.callable("geary.deleteLink").string(selection_id),
|
||||
+ this.call_void.begin(
|
||||
+ Util.JS.callable("deleteLink").string(selection_id),
|
||||
null
|
||||
);
|
||||
}
|
||||
@@ -396,23 +394,23 @@ public class Composer.WebView : Components.WebView {
|
||||
* Indents the line at the current text cursor location.
|
||||
*/
|
||||
public void indent_line() {
|
||||
- this.call.begin(Util.JS.callable("geary.indentLine"), null);
|
||||
+ this.call_void.begin(Util.JS.callable("indentLine"), null);
|
||||
}
|
||||
|
||||
public void insert_olist() {
|
||||
- this.call.begin(Util.JS.callable("geary.insertOrderedList"), null);
|
||||
+ this.call_void.begin(Util.JS.callable("insertOrderedList"), null);
|
||||
}
|
||||
|
||||
public void insert_ulist() {
|
||||
- this.call.begin(Util.JS.callable("geary.insertUnorderedList"), null);
|
||||
+ this.call_void.begin(Util.JS.callable("insertUnorderedList"), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the signature block if it has not been deleted.
|
||||
*/
|
||||
public new void update_signature(string signature) {
|
||||
- this.call.begin(
|
||||
- Util.JS.callable("geary.updateSignature").string(signature), null
|
||||
+ this.call_void.begin(
|
||||
+ Util.JS.callable("updateSignature").string(signature), null
|
||||
);
|
||||
}
|
||||
|
||||
@@ -420,22 +418,21 @@ public class Composer.WebView : Components.WebView {
|
||||
* Removes the quoted message (if any) from the composer.
|
||||
*/
|
||||
public void delete_quoted_message() {
|
||||
- this.call.begin(Util.JS.callable("geary.deleteQuotedMessage"), null);
|
||||
+ this.call_void.begin(Util.JS.callable("deleteQuotedMessage"), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the editor content contains an attachment keyword.
|
||||
*/
|
||||
- public async bool contains_attachment_keywords(string keyword_spec,
|
||||
- string subject) {
|
||||
+ public async bool? contains_attachment_keywords(string keyword_spec,
|
||||
+ string subject) {
|
||||
try {
|
||||
- return Util.JS.to_bool(
|
||||
- yield call(
|
||||
- Util.JS.callable("geary.containsAttachmentKeyword")
|
||||
- .string(keyword_spec)
|
||||
- .string(subject),
|
||||
- null)
|
||||
- );
|
||||
+ return yield call_returning<bool?>(
|
||||
+ Util.JS.callable("containsAttachmentKeyword")
|
||||
+ .string(keyword_spec)
|
||||
+ .string(subject),
|
||||
+ null
|
||||
+ );
|
||||
} catch (Error err) {
|
||||
debug("Error checking or attachment keywords: %s", err.message);
|
||||
return false;
|
||||
@@ -449,7 +446,7 @@ public class Composer.WebView : Components.WebView {
|
||||
* this.
|
||||
*/
|
||||
public async void clean_content() throws Error {
|
||||
- this.call.begin(Util.JS.callable("geary.cleanContent"), null);
|
||||
+ this.call_void.begin(Util.JS.callable("cleanContent"), null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -459,10 +456,10 @@ public class Composer.WebView : Components.WebView {
|
||||
const int MAX_BREAKABLE_LEN = 72; // F=F recommended line limit
|
||||
const int MAX_UNBREAKABLE_LEN = 998; // SMTP line limit
|
||||
|
||||
- string body_text = Util.JS.to_string(
|
||||
- yield call(Util.JS.callable("geary.getText"), null)
|
||||
+ string? body_text = yield call_returning<string?>(
|
||||
+ Util.JS.callable("getText"), null
|
||||
);
|
||||
- string[] lines = body_text.split("\n");
|
||||
+ string[] lines = (body_text ?? "").split("\n");
|
||||
GLib.StringBuilder flowed = new GLib.StringBuilder.sized(body_text.length);
|
||||
foreach (string line in lines) {
|
||||
// Strip trailing whitespace, so it doesn't look like a
|
||||
diff --git a/src/client/composer/composer-widget.vala b/src/client/composer/composer-widget.vala
|
||||
index 4c4d0caf..9148a88e 100644
|
||||
--- a/src/client/composer/composer-widget.vala
|
||||
+++ b/src/client/composer/composer-widget.vala
|
||||
@@ -1450,15 +1450,16 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
|
||||
confirmation = _("Send message with an empty subject?");
|
||||
} else if (!has_body && !has_attachment) {
|
||||
confirmation = _("Send message with an empty body?");
|
||||
- } else if (!has_attachment &&
|
||||
- yield this.editor.body.contains_attachment_keywords(
|
||||
- string.join(
|
||||
- "|",
|
||||
- ATTACHMENT_KEYWORDS,
|
||||
- ATTACHMENT_KEYWORDS_LOCALISED
|
||||
- ),
|
||||
- this.subject)) {
|
||||
- confirmation = _("Send message without an attachment?");
|
||||
+ } else if (!has_attachment) {
|
||||
+ var keywords = string.join(
|
||||
+ "|", ATTACHMENT_KEYWORDS, ATTACHMENT_KEYWORDS_LOCALISED
|
||||
+ );
|
||||
+ var contains = yield this.editor.body.contains_attachment_keywords(
|
||||
+ keywords, this.subject
|
||||
+ );
|
||||
+ if (contains != null && contains) {
|
||||
+ confirmation = _("Send message without an attachment?");
|
||||
+ }
|
||||
}
|
||||
if (confirmation != null) {
|
||||
ConfirmationDialog dialog = new ConfirmationDialog(container.top_window,
|
||||
diff --git a/src/client/conversation-viewer/conversation-web-view.vala b/src/client/conversation-viewer/conversation-web-view.vala
|
||||
index ffa36394..d77af642 100644
|
||||
--- a/src/client/conversation-viewer/conversation-web-view.vala
|
||||
+++ b/src/client/conversation-viewer/conversation-web-view.vala
|
||||
@@ -89,20 +89,18 @@ public class ConversationWebView : Components.WebView {
|
||||
* Returns the current selection, for prefill as find text.
|
||||
*/
|
||||
public async string? get_selection_for_find() throws Error{
|
||||
- JSC.Value result = yield call(
|
||||
- Util.JS.callable("geary.getSelectionForFind"), null
|
||||
+ return yield call_returning<string?>(
|
||||
+ Util.JS.callable("getSelectionForFind"), null
|
||||
);
|
||||
- return Util.JS.to_string(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current selection, for quoting in a message.
|
||||
*/
|
||||
public async string? get_selection_for_quoting() throws Error {
|
||||
- JSC.Value result = yield call(
|
||||
- Util.JS.callable("geary.getSelectionForQuoting"), null
|
||||
+ return yield call_returning<string?>(
|
||||
+ Util.JS.callable("getSelectionForQuoting"), null
|
||||
);
|
||||
- return Util.JS.to_string(result);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,10 +108,9 @@ public class ConversationWebView : Components.WebView {
|
||||
*/
|
||||
public async int? get_anchor_target_y(string anchor_body)
|
||||
throws GLib.Error {
|
||||
- JSC.Value result = yield call(
|
||||
- Util.JS.callable("geary.getAnchorTargetY").string(anchor_body), null
|
||||
+ return yield call_returning<int?>(
|
||||
+ Util.JS.callable("getAnchorTargetY").string(anchor_body), null
|
||||
);
|
||||
- return (int) Util.JS.to_int32(result);
|
||||
}
|
||||
|
||||
/**
|
||||
diff --git a/src/client/util/util-js.vala b/src/client/util/util-js.vala
|
||||
index 2f05a3e2..d2ce9f2e 100644
|
||||
--- a/src/client/util/util-js.vala
|
||||
+++ b/src/client/util/util-js.vala
|
||||
@@ -348,40 +348,54 @@ namespace Util.JS {
|
||||
*/
|
||||
public class Callable {
|
||||
|
||||
- private string base_name;
|
||||
- private string[] safe_args = new string[0];
|
||||
+ private string name;
|
||||
+ private GLib.Variant[] args = {};
|
||||
|
||||
|
||||
- public Callable(string base_name) {
|
||||
- this.base_name = base_name;
|
||||
+ public Callable(string name) {
|
||||
+ this.name = name;
|
||||
+ }
|
||||
+
|
||||
+ public WebKit.UserMessage to_message() {
|
||||
+ GLib.Variant? args = null;
|
||||
+ if (this.args.length == 1) {
|
||||
+ args = this.args[0];
|
||||
+ } else if (this.args.length > 1) {
|
||||
+ args = new GLib.Variant.tuple(this.args);
|
||||
+ }
|
||||
+ return new WebKit.UserMessage(this.name, args);
|
||||
}
|
||||
|
||||
public string to_string() {
|
||||
- return base_name + "(" + global::string.joinv(",", safe_args) + ");";
|
||||
+ string[] args = new string[this.args.length];
|
||||
+ for (int i = 0; i < args.length; i++) {
|
||||
+ args[i] = this.args[i].print(true);
|
||||
+ }
|
||||
+ return this.name + "(" + global::string.joinv(",", args) + ")";
|
||||
}
|
||||
|
||||
public Callable string(string value) {
|
||||
- add_param("\"" + escape_string(value) + "\"");
|
||||
+ add_param(new GLib.Variant.string(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Callable double(double value) {
|
||||
- add_param(value.to_string());
|
||||
+ add_param(new GLib.Variant.double(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Callable int(int value) {
|
||||
- add_param(value.to_string());
|
||||
+ add_param(new GLib.Variant.int32(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Callable bool(bool value) {
|
||||
- add_param(value ? "true" : "false");
|
||||
+ add_param(new GLib.Variant.boolean(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
- private inline void add_param(string value) {
|
||||
- this.safe_args += value;
|
||||
+ private inline void add_param(GLib.Variant value) {
|
||||
+ this.args += value;
|
||||
}
|
||||
|
||||
}
|
||||
diff --git a/src/client/web-process/web-process-extension.vala b/src/client/web-process/web-process-extension.vala
|
||||
index 4bba5154..86f7f44c 100644
|
||||
--- a/src/client/web-process/web-process-extension.vala
|
||||
+++ b/src/client/web-process/web-process-extension.vala
|
||||
@@ -30,6 +30,10 @@ public void webkit_web_extension_initialize_with_user_data(WebKit.WebExtension e
|
||||
*/
|
||||
public class GearyWebExtension : Object {
|
||||
|
||||
+ private const string PAGE_STATE_OBJECT_NAME = "geary";
|
||||
+ private const string MESSAGE_RETURN_VALUE_NAME = "__return__";
|
||||
+ private const string MESSAGE_EXCEPTION_NAME = "__exception__";
|
||||
+
|
||||
private const string[] ALLOWED_SCHEMES = { "cid", "geary", "data", "blob" };
|
||||
|
||||
private const string REMOTE_LOAD_VAR = "_gearyAllowRemoteResourceLoads";
|
||||
@@ -157,6 +161,55 @@ public class GearyWebExtension : Object {
|
||||
page.get_editor().selection_changed.connect(() => {
|
||||
selection_changed(page);
|
||||
});
|
||||
+ page.user_message_received.connect(on_page_message_received);
|
||||
+ }
|
||||
+
|
||||
+ private bool on_page_message_received(WebKit.WebPage page,
|
||||
+ WebKit.UserMessage message) {
|
||||
+ WebKit.Frame frame = page.get_main_frame();
|
||||
+ JSC.Context context = frame.get_js_context();
|
||||
+ JSC.Value page_state = context.get_value(PAGE_STATE_OBJECT_NAME);
|
||||
+
|
||||
+ try {
|
||||
+ JSC.Value[]? call_param = null;
|
||||
+ GLib.Variant? message_param = message.parameters;
|
||||
+ if (message_param != null) {
|
||||
+ if (message_param.is_container()) {
|
||||
+ size_t len = message_param.n_children();
|
||||
+ call_param = new JSC.Value[len];
|
||||
+ for (size_t i = 0; i < len; i++) {
|
||||
+ call_param[i] = Util.JS.variant_to_value(
|
||||
+ context,
|
||||
+ message_param.get_child_value(i)
|
||||
+ );
|
||||
+ }
|
||||
+ } else {
|
||||
+ call_param = {
|
||||
+ Util.JS.variant_to_value(context, message_param)
|
||||
+ };
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ JSC.Value ret = page_state.object_invoke_methodv(
|
||||
+ message.name, call_param
|
||||
+ );
|
||||
+
|
||||
+ // Must send a reply, even for void calls, otherwise
|
||||
+ // WebKitGTK will complain. So return a message return
|
||||
+ // rain hail or shine.
|
||||
+ // https://bugs.webkit.org/show_bug.cgi?id=215880
|
||||
+
|
||||
+ message.send_reply(
|
||||
+ new WebKit.UserMessage(
|
||||
+ MESSAGE_RETURN_VALUE_NAME,
|
||||
+ Util.JS.value_to_variant(ret)
|
||||
+ )
|
||||
+ );
|
||||
+ } catch (GLib.Error err) {
|
||||
+ debug("Failed to handle message: %s", err.message);
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
}
|
||||
|
||||
}
|
||||
diff --git a/test/js/components-page-state-test.vala b/test/js/components-page-state-test.vala
|
||||
index 5ec75746..562c6cda 100644
|
||||
--- a/test/js/components-page-state-test.vala
|
||||
+++ b/test/js/components-page-state-test.vala
|
||||
@@ -14,12 +14,24 @@ class Components.PageStateTest : WebViewTestCase<WebView> {
|
||||
base(config);
|
||||
}
|
||||
|
||||
+ public new async void call_void(Util.JS.Callable callable)
|
||||
+ throws GLib.Error {
|
||||
+ yield base.call_void(callable, null);
|
||||
+ }
|
||||
+
|
||||
+ public new async string call_returning(Util.JS.Callable callable)
|
||||
+ throws GLib.Error {
|
||||
+ return yield base.call_returning<string>(callable, null);
|
||||
+ }
|
||||
+
|
||||
}
|
||||
|
||||
|
||||
public PageStateTest() {
|
||||
base("Components.PageStateTest");
|
||||
add_test("content_loaded", content_loaded);
|
||||
+ add_test("call_void", call_void);
|
||||
+ add_test("call_returning", call_returning);
|
||||
|
||||
try {
|
||||
WebView.load_resources(GLib.File.new_for_path("/tmp"));
|
||||
@@ -45,6 +57,30 @@ class Components.PageStateTest : WebViewTestCase<WebView> {
|
||||
assert(content_loaded_triggered);
|
||||
}
|
||||
|
||||
+ public void call_void() throws GLib.Error {
|
||||
+ load_body_fixture("OHHAI");
|
||||
+ var test_article = this.test_view as TestWebView;
|
||||
+
|
||||
+ test_article.call_void.begin(
|
||||
+ new Util.JS.Callable("testVoid"), this.async_completion
|
||||
+ );
|
||||
+ test_article.call_void.end(this.async_result());
|
||||
+ assert_test_result("void");
|
||||
+ }
|
||||
+
|
||||
+ public void call_returning() throws GLib.Error {
|
||||
+ load_body_fixture("OHHAI");
|
||||
+ var test_article = this.test_view as TestWebView;
|
||||
+
|
||||
+ test_article.call_returning.begin(
|
||||
+ new Util.JS.Callable("testReturn").string("check 1-2"),
|
||||
+ this.async_completion
|
||||
+ );
|
||||
+ string ret = test_article.call_returning.end(this.async_result());
|
||||
+ assert_equal(ret, "check 1-2");
|
||||
+ assert_test_result("check 1-2");
|
||||
+ }
|
||||
+
|
||||
protected override WebView set_up_test_view() {
|
||||
WebKit.UserScript test_script;
|
||||
test_script = new WebKit.UserScript(
|
||||
@@ -60,4 +96,13 @@ class Components.PageStateTest : WebViewTestCase<WebView> {
|
||||
return view;
|
||||
}
|
||||
|
||||
+ private void assert_test_result(string expected)
|
||||
+ throws GLib.Error {
|
||||
+ string? result = Util.JS.to_string(
|
||||
+ run_javascript("geary.testResult")
|
||||
+ .get_js_value()
|
||||
+ );
|
||||
+ assert_equal(result, expected);
|
||||
+ }
|
||||
+
|
||||
}
|
||||
diff --git a/ui/components-web-view.js b/ui/components-web-view.js
|
||||
index 80e86d7c..289abca0 100644
|
||||
--- a/ui/components-web-view.js
|
||||
+++ b/ui/components-web-view.js
|
||||
@@ -87,6 +87,8 @@ PageState.prototype = {
|
||||
window.addEventListener("transitionend", function(e) {
|
||||
queuePreferredHeightUpdate();
|
||||
}, false); // load does not bubble
|
||||
+
|
||||
+ this.testResult = null;
|
||||
},
|
||||
getPreferredHeight: function() {
|
||||
// Return the scroll height of the HTML element since the BODY
|
||||
@@ -184,5 +186,13 @@ PageState.prototype = {
|
||||
this.hasSelection = hasSelection;
|
||||
window.webkit.messageHandlers.selectionChanged.postMessage(hasSelection);
|
||||
}
|
||||
+ },
|
||||
+ // Methods below are for unit tests.
|
||||
+ testVoid: function() {
|
||||
+ this.testResult = "void";
|
||||
+ },
|
||||
+ testReturn: function(value) {
|
||||
+ this.testResult = value;
|
||||
+ return value;
|
||||
}
|
||||
};
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,266 @@
|
||||
From c813aa5707acc5226a57dca82449dc709969d05a Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Thu, 27 Aug 2020 16:18:45 +1000
|
||||
Subject: [PATCH 071/124] Components.WebView: Check for pass up exceptions when
|
||||
calling JS code
|
||||
|
||||
Update web extension to check for errors when invoking page state
|
||||
methods and pass a message back if found. Check for this, decode and
|
||||
throw a vala error in the WebView if found.
|
||||
---
|
||||
.../components/components-web-view.vala | 56 ++++++++++++++---
|
||||
.../web-process/web-process-extension.vala | 39 ++++++++++--
|
||||
test/js/components-page-state-test.vala | 60 +++++++++++++++++++
|
||||
ui/components-web-view.js | 4 ++
|
||||
4 files changed, 146 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/src/client/components/components-web-view.vala b/src/client/components/components-web-view.vala
|
||||
index 368b6a8d..2b373170 100644
|
||||
--- a/src/client/components/components-web-view.vala
|
||||
+++ b/src/client/components/components-web-view.vala
|
||||
@@ -26,6 +26,10 @@ public abstract class Components.WebView : WebKit.WebView, Geary.BaseInterface {
|
||||
/** URI Scheme and delimiter for images loaded by Content-ID. */
|
||||
public const string CID_URL_PREFIX = "cid:";
|
||||
|
||||
+ // Keep these in sync with GearyWebExtension
|
||||
+ private const string MESSAGE_RETURN_VALUE_NAME = "__return__";
|
||||
+ private const string MESSAGE_EXCEPTION_NAME = "__exception__";
|
||||
+
|
||||
// WebKit message handler names
|
||||
private const string COMMAND_STACK_CHANGED = "commandStackChanged";
|
||||
private const string CONTENT_LOADED = "contentLoaded";
|
||||
@@ -467,9 +471,7 @@ public abstract class Components.WebView : WebKit.WebView, Geary.BaseInterface {
|
||||
protected async void call_void(Util.JS.Callable target,
|
||||
GLib.Cancellable? cancellable)
|
||||
throws GLib.Error {
|
||||
- yield send_message_to_page(
|
||||
- target.to_message(), cancellable
|
||||
- );
|
||||
+ yield call_impl(target, cancellable);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -488,12 +490,10 @@ public abstract class Components.WebView : WebKit.WebView, Geary.BaseInterface {
|
||||
protected async T call_returning<T>(Util.JS.Callable target,
|
||||
GLib.Cancellable? cancellable)
|
||||
throws GLib.Error {
|
||||
- WebKit.UserMessage? response = yield send_message_to_page(
|
||||
- target.to_message(), cancellable
|
||||
- );
|
||||
+ WebKit.UserMessage? response = yield call_impl(target, cancellable);
|
||||
if (response == null) {
|
||||
throw new Util.JS.Error.TYPE(
|
||||
- "Method call did not return a value: %s", target.to_string()
|
||||
+ "Method call %s did not return a value", target.to_string()
|
||||
);
|
||||
}
|
||||
GLib.Variant? param = response.parameters;
|
||||
@@ -612,6 +612,48 @@ public abstract class Components.WebView : WebKit.WebView, Geary.BaseInterface {
|
||||
"monospace-font", SettingsBindFlags.DEFAULT);
|
||||
}
|
||||
|
||||
+ private async WebKit.UserMessage? call_impl(Util.JS.Callable target,
|
||||
+ GLib.Cancellable? cancellable)
|
||||
+ throws GLib.Error {
|
||||
+ WebKit.UserMessage? response = yield send_message_to_page(
|
||||
+ target.to_message(), cancellable
|
||||
+ );
|
||||
+ if (response != null) {
|
||||
+ var response_name = response.name;
|
||||
+ if (response_name == MESSAGE_EXCEPTION_NAME) {
|
||||
+ var exception = new GLib.VariantDict(response.parameters);
|
||||
+ var name = exception.lookup_value("name", GLib.VariantType.STRING) as string;
|
||||
+ var message = exception.lookup_value("message", GLib.VariantType.STRING) as string;
|
||||
+ var backtrace = exception.lookup_value("backtrace_string", GLib.VariantType.STRING) as string;
|
||||
+ var source = exception.lookup_value("source_uri", GLib.VariantType.STRING) as string;
|
||||
+ var line = exception.lookup_value("line_number", GLib.VariantType.UINT32);
|
||||
+ var column = exception.lookup_value("column_number", GLib.VariantType.UINT32);
|
||||
+
|
||||
+ var log_message = "Method call %s raised %s exception at %s:%d:%d: %s".printf(
|
||||
+ target.to_string(),
|
||||
+ name ?? "unknown",
|
||||
+ source ?? "unknown",
|
||||
+ (line != null ? (int) line.get_uint32() : -1),
|
||||
+ (column != null ? (int) column.get_uint32() : -1),
|
||||
+ message ?? "unknown"
|
||||
+ );
|
||||
+ debug(log_message);
|
||||
+ if (backtrace != null) {
|
||||
+ debug(backtrace);
|
||||
+ }
|
||||
+
|
||||
+ throw new Util.JS.Error.EXCEPTION(log_message);
|
||||
+ } else if (response_name != MESSAGE_RETURN_VALUE_NAME) {
|
||||
+ throw new Util.JS.Error.TYPE(
|
||||
+ "Method call %s returned unknown name: %s",
|
||||
+ target.to_string(),
|
||||
+ response_name
|
||||
+ );
|
||||
+ }
|
||||
+ }
|
||||
+ return response;
|
||||
+ }
|
||||
+
|
||||
private void handle_cid_request(WebKit.URISchemeRequest request) {
|
||||
if (!handle_internal_response(request)) {
|
||||
request.finish_error(new FileError.NOENT("Unknown CID"));
|
||||
diff --git a/src/client/web-process/web-process-extension.vala b/src/client/web-process/web-process-extension.vala
|
||||
index 86f7f44c..7aa6dd3c 100644
|
||||
--- a/src/client/web-process/web-process-extension.vala
|
||||
+++ b/src/client/web-process/web-process-extension.vala
|
||||
@@ -31,6 +31,8 @@ public void webkit_web_extension_initialize_with_user_data(WebKit.WebExtension e
|
||||
public class GearyWebExtension : Object {
|
||||
|
||||
private const string PAGE_STATE_OBJECT_NAME = "geary";
|
||||
+
|
||||
+ // Keep these in sync with Components.WebView
|
||||
private const string MESSAGE_RETURN_VALUE_NAME = "__return__";
|
||||
private const string MESSAGE_EXCEPTION_NAME = "__exception__";
|
||||
|
||||
@@ -199,12 +201,37 @@ public class GearyWebExtension : Object {
|
||||
// rain hail or shine.
|
||||
// https://bugs.webkit.org/show_bug.cgi?id=215880
|
||||
|
||||
- message.send_reply(
|
||||
- new WebKit.UserMessage(
|
||||
- MESSAGE_RETURN_VALUE_NAME,
|
||||
- Util.JS.value_to_variant(ret)
|
||||
- )
|
||||
- );
|
||||
+ JSC.Exception? thrown = context.get_exception();
|
||||
+ if (thrown != null) {
|
||||
+ var detail = new GLib.VariantDict();
|
||||
+ if (thrown.get_message() != null) {
|
||||
+ detail.insert_value("name", new GLib.Variant.string(thrown.get_name()));
|
||||
+ }
|
||||
+ if (thrown.get_message() != null) {
|
||||
+ detail.insert_value("message", new GLib.Variant.string(thrown.get_message()));
|
||||
+ }
|
||||
+ if (thrown.get_backtrace_string() != null) {
|
||||
+ detail.insert_value("backtrace_string", new GLib.Variant.string(thrown.get_backtrace_string()));
|
||||
+ }
|
||||
+ if (thrown.get_source_uri() != null) {
|
||||
+ detail.insert_value("source_uri", new GLib.Variant.string(thrown.get_source_uri()));
|
||||
+ }
|
||||
+ detail.insert_value("line_number", new GLib.Variant.uint32(thrown.get_line_number()));
|
||||
+ detail.insert_value("column_number", new GLib.Variant.uint32(thrown.get_column_number()));
|
||||
+ message.send_reply(
|
||||
+ new WebKit.UserMessage(
|
||||
+ MESSAGE_EXCEPTION_NAME,
|
||||
+ detail.end()
|
||||
+ )
|
||||
+ );
|
||||
+ } else {
|
||||
+ message.send_reply(
|
||||
+ new WebKit.UserMessage(
|
||||
+ MESSAGE_RETURN_VALUE_NAME,
|
||||
+ Util.JS.value_to_variant(ret)
|
||||
+ )
|
||||
+ );
|
||||
+ }
|
||||
} catch (GLib.Error err) {
|
||||
debug("Failed to handle message: %s", err.message);
|
||||
}
|
||||
diff --git a/test/js/components-page-state-test.vala b/test/js/components-page-state-test.vala
|
||||
index 562c6cda..bf952416 100644
|
||||
--- a/test/js/components-page-state-test.vala
|
||||
+++ b/test/js/components-page-state-test.vala
|
||||
@@ -31,7 +31,9 @@ class Components.PageStateTest : WebViewTestCase<WebView> {
|
||||
base("Components.PageStateTest");
|
||||
add_test("content_loaded", content_loaded);
|
||||
add_test("call_void", call_void);
|
||||
+ add_test("call_void_throws", call_void_throws);
|
||||
add_test("call_returning", call_returning);
|
||||
+ add_test("call_returning_throws", call_returning_throws);
|
||||
|
||||
try {
|
||||
WebView.load_resources(GLib.File.new_for_path("/tmp"));
|
||||
@@ -68,6 +70,35 @@ class Components.PageStateTest : WebViewTestCase<WebView> {
|
||||
assert_test_result("void");
|
||||
}
|
||||
|
||||
+ public void call_void_throws() throws GLib.Error {
|
||||
+ load_body_fixture("OHHAI");
|
||||
+ var test_article = this.test_view as TestWebView;
|
||||
+
|
||||
+ try {
|
||||
+ test_article.call_void.begin(
|
||||
+ new Util.JS.Callable("testThrow").string("void message"),
|
||||
+ this.async_completion
|
||||
+ );
|
||||
+ test_article.call_void.end(this.async_result());
|
||||
+ assert_not_reached();
|
||||
+ } catch (Util.JS.Error.EXCEPTION err) {
|
||||
+ assert_string(
|
||||
+ err.message
|
||||
+ ).contains(
|
||||
+ "testThrow"
|
||||
+ // WebKitGTK doesn't actually pass any details through:
|
||||
+ // https://bugs.webkit.org/show_bug.cgi?id=215877
|
||||
+ // ).contains(
|
||||
+ // "Error"
|
||||
+ // ).contains(
|
||||
+ // "void message"
|
||||
+ // ).contains(
|
||||
+ // "components-web-view.js"
|
||||
+ );
|
||||
+ assert_test_result("void message");
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
public void call_returning() throws GLib.Error {
|
||||
load_body_fixture("OHHAI");
|
||||
var test_article = this.test_view as TestWebView;
|
||||
@@ -81,6 +112,35 @@ class Components.PageStateTest : WebViewTestCase<WebView> {
|
||||
assert_test_result("check 1-2");
|
||||
}
|
||||
|
||||
+ public void call_returning_throws() throws GLib.Error {
|
||||
+ load_body_fixture("OHHAI");
|
||||
+ var test_article = this.test_view as TestWebView;
|
||||
+
|
||||
+ try {
|
||||
+ test_article.call_returning.begin(
|
||||
+ new Util.JS.Callable("testThrow").string("return message"),
|
||||
+ this.async_completion
|
||||
+ );
|
||||
+ test_article.call_returning.end(this.async_result());
|
||||
+ assert_not_reached();
|
||||
+ } catch (Util.JS.Error.EXCEPTION err) {
|
||||
+ assert_string(
|
||||
+ err.message
|
||||
+ ).contains(
|
||||
+ "testThrow"
|
||||
+ // WebKitGTK doesn't actually pass any details through:
|
||||
+ // https://bugs.webkit.org/show_bug.cgi?id=215877
|
||||
+ // ).contains(
|
||||
+ // "Error"
|
||||
+ // ).contains(
|
||||
+ // "return message"
|
||||
+ // ).contains(
|
||||
+ // "components-web-view.js"
|
||||
+ );
|
||||
+ assert_test_result("return message");
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
protected override WebView set_up_test_view() {
|
||||
WebKit.UserScript test_script;
|
||||
test_script = new WebKit.UserScript(
|
||||
diff --git a/ui/components-web-view.js b/ui/components-web-view.js
|
||||
index 289abca0..0f932a19 100644
|
||||
--- a/ui/components-web-view.js
|
||||
+++ b/ui/components-web-view.js
|
||||
@@ -194,5 +194,9 @@ PageState.prototype = {
|
||||
testReturn: function(value) {
|
||||
this.testResult = value;
|
||||
return value;
|
||||
+ },
|
||||
+ testThrow: function(value) {
|
||||
+ this.testResult = value;
|
||||
+ throw this.testResult;
|
||||
}
|
||||
};
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,88 @@
|
||||
From db69807836cb2485af0941a83f57451c034b21a0 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Fri, 28 Aug 2020 09:44:46 +1000
|
||||
Subject: [PATCH 072/124] GearyWebExtension: Add factory method for error user
|
||||
messages
|
||||
|
||||
---
|
||||
.../web-process/web-process-extension.vala | 56 +++++++++++++------
|
||||
1 file changed, 38 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/src/client/web-process/web-process-extension.vala b/src/client/web-process/web-process-extension.vala
|
||||
index 7aa6dd3c..89d9a1e3 100644
|
||||
--- a/src/client/web-process/web-process-extension.vala
|
||||
+++ b/src/client/web-process/web-process-extension.vala
|
||||
@@ -145,6 +145,37 @@ public class GearyWebExtension : Object {
|
||||
return ret;
|
||||
}
|
||||
|
||||
+ private WebKit.UserMessage to_exception_message(string? name,
|
||||
+ string? message,
|
||||
+ string? backtrace = null,
|
||||
+ string? source = null,
|
||||
+ int line_number = -1,
|
||||
+ int column_number = -1) {
|
||||
+ var detail = new GLib.VariantDict();
|
||||
+ if (name != null) {
|
||||
+ detail.insert_value("name", new GLib.Variant.string(name));
|
||||
+ }
|
||||
+ if (message != null) {
|
||||
+ detail.insert_value("message", new GLib.Variant.string(message));
|
||||
+ }
|
||||
+ if (backtrace != null) {
|
||||
+ detail.insert_value("backtrace", new GLib.Variant.string(backtrace));
|
||||
+ }
|
||||
+ if (source != null) {
|
||||
+ detail.insert_value("source", new GLib.Variant.string(source));
|
||||
+ }
|
||||
+ if (line_number > 0) {
|
||||
+ detail.insert_value("line_number", new GLib.Variant.uint32(line_number));
|
||||
+ }
|
||||
+ if (column_number > 0) {
|
||||
+ detail.insert_value("column_number", new GLib.Variant.uint32(column_number));
|
||||
+ }
|
||||
+ return new WebKit.UserMessage(
|
||||
+ MESSAGE_EXCEPTION_NAME,
|
||||
+ detail.end()
|
||||
+ );
|
||||
+ }
|
||||
+
|
||||
private void on_page_created(WebKit.WebExtension extension,
|
||||
WebKit.WebPage page) {
|
||||
WebKit.Frame frame = page.get_main_frame();
|
||||
@@ -203,25 +234,14 @@ public class GearyWebExtension : Object {
|
||||
|
||||
JSC.Exception? thrown = context.get_exception();
|
||||
if (thrown != null) {
|
||||
- var detail = new GLib.VariantDict();
|
||||
- if (thrown.get_message() != null) {
|
||||
- detail.insert_value("name", new GLib.Variant.string(thrown.get_name()));
|
||||
- }
|
||||
- if (thrown.get_message() != null) {
|
||||
- detail.insert_value("message", new GLib.Variant.string(thrown.get_message()));
|
||||
- }
|
||||
- if (thrown.get_backtrace_string() != null) {
|
||||
- detail.insert_value("backtrace_string", new GLib.Variant.string(thrown.get_backtrace_string()));
|
||||
- }
|
||||
- if (thrown.get_source_uri() != null) {
|
||||
- detail.insert_value("source_uri", new GLib.Variant.string(thrown.get_source_uri()));
|
||||
- }
|
||||
- detail.insert_value("line_number", new GLib.Variant.uint32(thrown.get_line_number()));
|
||||
- detail.insert_value("column_number", new GLib.Variant.uint32(thrown.get_column_number()));
|
||||
message.send_reply(
|
||||
- new WebKit.UserMessage(
|
||||
- MESSAGE_EXCEPTION_NAME,
|
||||
- detail.end()
|
||||
+ to_exception_message(
|
||||
+ thrown.get_name(),
|
||||
+ thrown.get_message(),
|
||||
+ thrown.get_backtrace_string(),
|
||||
+ thrown.get_source_uri(),
|
||||
+ (int) thrown.get_line_number(),
|
||||
+ (int) thrown.get_column_number()
|
||||
)
|
||||
);
|
||||
} else {
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,223 @@
|
||||
From 6162785d997fcfa4efaf6ec83670b2fab8cca6bd Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Fri, 28 Aug 2020 09:49:46 +1000
|
||||
Subject: [PATCH 073/124] GearyWebExtension: Add support for sending messages
|
||||
from JS to client
|
||||
|
||||
Define a vala-backed JS class in the extension and make that available
|
||||
to pages when they are registered. Add some helper JS to PageState for
|
||||
defining message sending functions. Listen for these in
|
||||
Components.WebView and dispatch to the registered callback for it.
|
||||
---
|
||||
.../components/components-web-view.vala | 55 ++++++++++++++++
|
||||
.../web-process/web-process-extension.vala | 63 +++++++++++++++++++
|
||||
ui/components-web-view.js | 9 +++
|
||||
3 files changed, 127 insertions(+)
|
||||
|
||||
diff --git a/src/client/components/components-web-view.vala b/src/client/components/components-web-view.vala
|
||||
index 2b373170..c746c441 100644
|
||||
--- a/src/client/components/components-web-view.vala
|
||||
+++ b/src/client/components/components-web-view.vala
|
||||
@@ -198,6 +198,24 @@ public abstract class Components.WebView : WebKit.WebView, Geary.BaseInterface {
|
||||
/** Delegate for UserContentManager message callbacks. */
|
||||
public delegate void JavaScriptMessageHandler(WebKit.JavascriptResult js_result);
|
||||
|
||||
+ /**
|
||||
+ * Delegate for message handler callbacks.
|
||||
+ *
|
||||
+ * @see register_message_callback
|
||||
+ */
|
||||
+ protected delegate void MessageCallback(GLib.Variant? parameters);
|
||||
+
|
||||
+ // Work around for not being able to put delegates in a Gee collection.
|
||||
+ private class MessageCallable {
|
||||
+
|
||||
+ public unowned MessageCallback handler;
|
||||
+
|
||||
+ public MessageCallable(MessageCallback handler) {
|
||||
+ this.handler = handler;
|
||||
+ }
|
||||
+
|
||||
+ }
|
||||
+
|
||||
/**
|
||||
* Determines if the view's content has been fully loaded.
|
||||
*
|
||||
@@ -263,6 +281,8 @@ public abstract class Components.WebView : WebKit.WebView, Geary.BaseInterface {
|
||||
|
||||
private Gee.List<ulong> registered_message_handlers =
|
||||
new Gee.LinkedList<ulong>();
|
||||
+ private Gee.Map<string,MessageCallable> message_handlers =
|
||||
+ new Gee.HashMap<string,MessageCallable>();
|
||||
|
||||
private double webkit_reported_height = 0;
|
||||
|
||||
@@ -359,6 +379,7 @@ public abstract class Components.WebView : WebKit.WebView, Geary.BaseInterface {
|
||||
this.user_content_manager.disconnect(id);
|
||||
}
|
||||
this.registered_message_handlers.clear();
|
||||
+ this.message_handlers.clear();
|
||||
base.destroy();
|
||||
}
|
||||
|
||||
@@ -568,6 +589,14 @@ public abstract class Components.WebView : WebKit.WebView, Geary.BaseInterface {
|
||||
}
|
||||
}
|
||||
|
||||
+ /**
|
||||
+ * Registers a callback for a specific WebKit user message.
|
||||
+ */
|
||||
+ protected void register_message_callback(string name,
|
||||
+ MessageCallback handler) {
|
||||
+ this.message_handlers.set(name, new MessageCallable(handler));
|
||||
+ }
|
||||
+
|
||||
private void init(Application.Configuration config) {
|
||||
// XXX get the allow prefix from the extension somehow
|
||||
|
||||
@@ -595,6 +624,8 @@ public abstract class Components.WebView : WebKit.WebView, Geary.BaseInterface {
|
||||
SELECTION_CHANGED, on_selection_changed
|
||||
);
|
||||
|
||||
+ this.user_message_received.connect(this.on_message_received);
|
||||
+
|
||||
// Manage zoom level, ensure it's sane
|
||||
config.bind(Application.Configuration.CONVERSATION_VIEWER_ZOOM_KEY, this, "zoom_level");
|
||||
if (this.zoom_level < ZOOM_MIN) {
|
||||
@@ -803,6 +834,30 @@ public abstract class Components.WebView : WebKit.WebView, Geary.BaseInterface {
|
||||
}
|
||||
}
|
||||
|
||||
+ private bool on_message_received(WebKit.UserMessage message) {
|
||||
+ if (message.name == MESSAGE_EXCEPTION_NAME) {
|
||||
+ var detail = new GLib.VariantDict(message.parameters);
|
||||
+ var name = detail.lookup_value("name", GLib.VariantType.STRING) as string;
|
||||
+ var log_message = detail.lookup_value("message", GLib.VariantType.STRING) as string;
|
||||
+ warning(
|
||||
+ "Error sending message from JS: %s: %s",
|
||||
+ name ?? "unknown",
|
||||
+ log_message ?? "unknown"
|
||||
+ );
|
||||
+ } else if (this.message_handlers.has_key(message.name)) {
|
||||
+ debug(
|
||||
+ "Message received: %s(%s)",
|
||||
+ message.name,
|
||||
+ message.parameters != null ? message.parameters.print(true) : ""
|
||||
+ );
|
||||
+ MessageCallable callback = this.message_handlers.get(message.name);
|
||||
+ callback.handler(message.parameters);
|
||||
+ } else {
|
||||
+ warning("Message with unknown handler received: %s", message.name);
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
}
|
||||
|
||||
// XXX this needs to be moved into the libsoup bindings
|
||||
diff --git a/src/client/web-process/web-process-extension.vala b/src/client/web-process/web-process-extension.vala
|
||||
index 89d9a1e3..31f2b0f0 100644
|
||||
--- a/src/client/web-process/web-process-extension.vala
|
||||
+++ b/src/client/web-process/web-process-extension.vala
|
||||
@@ -38,6 +38,8 @@ public class GearyWebExtension : Object {
|
||||
|
||||
private const string[] ALLOWED_SCHEMES = { "cid", "geary", "data", "blob" };
|
||||
|
||||
+ private const string EXTENSION_CLASS_VAR = "_GearyWebExtension";
|
||||
+ private const string EXTENSION_CLASS_SEND = "send";
|
||||
private const string REMOTE_LOAD_VAR = "_gearyAllowRemoteResourceLoads";
|
||||
|
||||
private WebKit.WebExtension extension;
|
||||
@@ -180,6 +182,25 @@ public class GearyWebExtension : Object {
|
||||
WebKit.WebPage page) {
|
||||
WebKit.Frame frame = page.get_main_frame();
|
||||
JSC.Context context = frame.get_js_context();
|
||||
+
|
||||
+ var extension_class = context.register_class(
|
||||
+ this.get_type().name(),
|
||||
+ null,
|
||||
+ null,
|
||||
+ null
|
||||
+ );
|
||||
+ extension_class.add_method(
|
||||
+ EXTENSION_CLASS_SEND,
|
||||
+ (instance, values) => {
|
||||
+ return this.on_page_send_message(page, values);
|
||||
+ },
|
||||
+ GLib.Type.NONE
|
||||
+ );
|
||||
+ context.set_value(
|
||||
+ EXTENSION_CLASS_VAR,
|
||||
+ new JSC.Value.object(context, extension_class, extension_class)
|
||||
+ );
|
||||
+
|
||||
context.set_value(
|
||||
REMOTE_LOAD_VAR,
|
||||
new JSC.Value.boolean(context, false)
|
||||
@@ -259,4 +280,46 @@ public class GearyWebExtension : Object {
|
||||
return true;
|
||||
}
|
||||
|
||||
+ private bool on_page_send_message(WebKit.WebPage page,
|
||||
+ GLib.GenericArray<JSC.Value> args) {
|
||||
+ WebKit.UserMessage? message = null;
|
||||
+ if (args.length > 0) {
|
||||
+ var name = args.get(0).to_string();
|
||||
+ GLib.Variant? parameters = null;
|
||||
+ if (args.length > 1) {
|
||||
+ JSC.Value param_value = args.get(1);
|
||||
+ try {
|
||||
+ int len = Util.JS.to_int32(
|
||||
+ param_value.object_get_property("length")
|
||||
+ );
|
||||
+ if (len == 1) {
|
||||
+ parameters = Util.JS.value_to_variant(
|
||||
+ param_value.object_get_property_at_index(0)
|
||||
+ );
|
||||
+ } else if (len > 1) {
|
||||
+ parameters = Util.JS.value_to_variant(param_value);
|
||||
+ }
|
||||
+ } catch (Util.JS.Error err) {
|
||||
+ message = to_exception_message(
|
||||
+ this.get_type().name(), err.message
|
||||
+ );
|
||||
+ }
|
||||
+ }
|
||||
+ if (message == null) {
|
||||
+ message = new WebKit.UserMessage(name, parameters);
|
||||
+ }
|
||||
+ }
|
||||
+ if (message == null) {
|
||||
+ var log_message = "Not enough parameters for JS call to %s.%s()".printf(
|
||||
+ EXTENSION_CLASS_VAR,
|
||||
+ EXTENSION_CLASS_SEND
|
||||
+ );
|
||||
+ debug(log_message);
|
||||
+ message = to_exception_message(this.get_type().name(), log_message);
|
||||
+ }
|
||||
+
|
||||
+ page.send_message_to_view.begin(message, null);
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
}
|
||||
diff --git a/ui/components-web-view.js b/ui/components-web-view.js
|
||||
index 0f932a19..35e82dfc 100644
|
||||
--- a/ui/components-web-view.js
|
||||
+++ b/ui/components-web-view.js
|
||||
@@ -200,3 +200,12 @@ PageState.prototype = {
|
||||
throw this.testResult;
|
||||
}
|
||||
};
|
||||
+
|
||||
+let MessageSender = function(name) {
|
||||
+ return function() {
|
||||
+ // Since typeof(arguments) == 'object', convert to an array so
|
||||
+ // that Components.WebView.MessageCallback callbacks get
|
||||
+ // arrays or tuples rather than dicts as arguments
|
||||
+ _GearyWebExtension.send(name, Array.from(arguments));
|
||||
+ };
|
||||
+};
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,275 @@
|
||||
From 89453931bf6743049644274fc730a10e7bd2a53d Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Fri, 28 Aug 2020 11:20:27 +1000
|
||||
Subject: [PATCH 074/124] Util.Js: Improve JSC Value to GLib.Variant conversion
|
||||
|
||||
Stop needlessly wrapping object members and array elements in
|
||||
variant variants.
|
||||
|
||||
Don't wrap object values in variants since the code is already using
|
||||
vardicts for these. Return a variant array if a JS array contains values
|
||||
of all the same type and don't wrap these in variants, else return
|
||||
a tuple, which don't need to be wrapped either.
|
||||
---
|
||||
src/client/util/util-js.vala | 160 +++++++++++++++++++++--------
|
||||
test/client/util/util-js-test.vala | 28 ++++-
|
||||
2 files changed, 143 insertions(+), 45 deletions(-)
|
||||
|
||||
diff --git a/src/client/util/util-js.vala b/src/client/util/util-js.vala
|
||||
index d2ce9f2e..095f9da4 100644
|
||||
--- a/src/client/util/util-js.vala
|
||||
+++ b/src/client/util/util-js.vala
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
- * Copyright 2017,2019 Michael James Gratton <mike@vee.net>
|
||||
+ * Copyright © 2017-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.
|
||||
@@ -25,6 +25,64 @@ namespace Util.JS {
|
||||
TYPE
|
||||
}
|
||||
|
||||
+ /** Supported types of JSC values. */
|
||||
+ public enum JscType {
|
||||
+
|
||||
+ /** Specifies an unsupported value type. */
|
||||
+ UNKNOWN,
|
||||
+
|
||||
+ /** Specifies a JavaScript `undefined` value. */
|
||||
+ UNDEFINED,
|
||||
+
|
||||
+ /** Specifies a JavaScript `null` value. */
|
||||
+ NULL,
|
||||
+ FUNCTION,
|
||||
+ STRING,
|
||||
+ NUMBER,
|
||||
+ BOOLEAN,
|
||||
+ ARRAY,
|
||||
+ CONSTRUCTOR,
|
||||
+ OBJECT;
|
||||
+
|
||||
+ /**
|
||||
+ * Determines the type of a JSC value.
|
||||
+ *
|
||||
+ * Returns the type of the given value, or {@link UNKNOWN} if
|
||||
+ * it could not be determined.
|
||||
+ */
|
||||
+ public static JscType to_type(JSC.Value value) {
|
||||
+ if (value.is_undefined()) {
|
||||
+ return UNDEFINED;
|
||||
+ }
|
||||
+ if (value.is_null()) {
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ if (value.is_string()) {
|
||||
+ return STRING;
|
||||
+ }
|
||||
+ if (value.is_number()) {
|
||||
+ return NUMBER;
|
||||
+ }
|
||||
+ if (value.is_boolean()) {
|
||||
+ return BOOLEAN;
|
||||
+ }
|
||||
+ if (value.is_array()) {
|
||||
+ return ARRAY;
|
||||
+ }
|
||||
+ if (value.is_object()) {
|
||||
+ return OBJECT;
|
||||
+ }
|
||||
+ if (value.is_function()) {
|
||||
+ return FUNCTION;
|
||||
+ }
|
||||
+ if (value.is_constructor()) {
|
||||
+ return CONSTRUCTOR;
|
||||
+ }
|
||||
+ return UNKNOWN;
|
||||
+ }
|
||||
+
|
||||
+ }
|
||||
+
|
||||
/**
|
||||
* Returns a JSC Value as a bool.
|
||||
*
|
||||
@@ -132,60 +190,80 @@ namespace Util.JS {
|
||||
*
|
||||
* Simple value objects (string, number, and Boolean values),
|
||||
* arrays of these, and objects with these types as properties are
|
||||
- * supported. Arrays are converted to arrays of variants, and
|
||||
- * objects to dictionaries containing string keys and variant
|
||||
- * values. Null or undefined values are returned as an empty maybe
|
||||
- * variant type, since it is not possible to determine the actual
|
||||
- * type.
|
||||
+ * supported. Arrays containing objects of the same type are
|
||||
+ * converted to arrays, otherwise they are converted to tuples,
|
||||
+ * empty arrays are converted to the unit tuple, and objects are
|
||||
+ * converted to vardict containing property names as keys and
|
||||
+ * values. Null and undefined values are returned as an empty
|
||||
+ * maybe variant type, since it is not possible to determine the
|
||||
+ * actual type.
|
||||
*
|
||||
* Throws a type error if the given value's type is not supported.
|
||||
*/
|
||||
public inline GLib.Variant value_to_variant(JSC.Value value)
|
||||
throws Error {
|
||||
- if (value.is_null() || value.is_undefined()) {
|
||||
- return new GLib.Variant.maybe(GLib.VariantType.VARIANT, null);
|
||||
- }
|
||||
- if (value.is_boolean()) {
|
||||
- return new GLib.Variant.boolean(value.to_boolean());
|
||||
- }
|
||||
- if (value.is_number()) {
|
||||
- return new GLib.Variant.double(value.to_double());
|
||||
- }
|
||||
- if (value.is_string()) {
|
||||
- return new GLib.Variant.string(value.to_string());
|
||||
- }
|
||||
- if (value.is_array()) {
|
||||
+ GLib.Variant? variant = null;
|
||||
+ switch (JscType.to_type(value)) {
|
||||
+ case UNDEFINED:
|
||||
+ case NULL:
|
||||
+ variant = new GLib.Variant.maybe(GLib.VariantType.VARIANT, null);
|
||||
+ break;
|
||||
+
|
||||
+ case STRING:
|
||||
+ variant = new GLib.Variant.string(value.to_string());
|
||||
+ break;
|
||||
+
|
||||
+ case NUMBER:
|
||||
+ variant = new GLib.Variant.double(value.to_double());
|
||||
+ break;
|
||||
+
|
||||
+ case BOOLEAN:
|
||||
+ variant = new GLib.Variant.boolean(value.to_boolean());
|
||||
+ break;
|
||||
+
|
||||
+ case ARRAY:
|
||||
int len = to_int32(value.object_get_property("length"));
|
||||
- GLib.Variant[] values = new GLib.Variant[len];
|
||||
- for (int i = 0; i < len; i++) {
|
||||
- values[i] = new GLib.Variant.variant(
|
||||
- value_to_variant(value.object_get_property_at_index(i))
|
||||
- );
|
||||
+ if (len == 0) {
|
||||
+ variant = new GLib.Variant.tuple({});
|
||||
+ } else {
|
||||
+ JSC.Value element = value.object_get_property_at_index(0);
|
||||
+ var first_type = JscType.to_type(element);
|
||||
+ var all_same_type = true;
|
||||
+ var values = new GLib.Variant[len];
|
||||
+ values[0] = value_to_variant(element);
|
||||
+ for (int i = 1; i < len; i++) {
|
||||
+ element = value.object_get_property_at_index(i);
|
||||
+ values[i] = value_to_variant(element);
|
||||
+ all_same_type &= (first_type == JscType.to_type(element));
|
||||
+ }
|
||||
+ if (!all_same_type) {
|
||||
+ variant = new GLib.Variant.tuple(values);
|
||||
+ } else {
|
||||
+ variant = new GLib.Variant.array(
|
||||
+ values[0].get_type(), values
|
||||
+ );
|
||||
+ }
|
||||
}
|
||||
- return new GLib.Variant.array(GLib.VariantType.VARIANT, values);
|
||||
- }
|
||||
- if (value.is_object()) {
|
||||
+ break;
|
||||
+
|
||||
+ case OBJECT:
|
||||
GLib.VariantDict dict = new GLib.VariantDict();
|
||||
string[] names = value.object_enumerate_properties();
|
||||
if (names != null) {
|
||||
foreach (var name in names) {
|
||||
- try {
|
||||
- dict.insert_value(
|
||||
- name,
|
||||
- new GLib.Variant.variant(
|
||||
- value_to_variant(
|
||||
- value.object_get_property(name)
|
||||
- )
|
||||
- )
|
||||
- );
|
||||
- } catch (Error.TYPE err) {
|
||||
- // ignored
|
||||
- }
|
||||
+ dict.insert_value(
|
||||
+ name,
|
||||
+ value_to_variant(value.object_get_property(name))
|
||||
+ );
|
||||
}
|
||||
}
|
||||
- return dict.end();
|
||||
+ variant = dict.end();
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ throw new Error.TYPE("Unsupported JS type: %s", value.to_string());
|
||||
}
|
||||
- throw new Error.TYPE("Unsupported JS type: %s", value.to_string());
|
||||
+ return variant;
|
||||
}
|
||||
|
||||
/**
|
||||
diff --git a/test/client/util/util-js-test.vala b/test/client/util/util-js-test.vala
|
||||
index 16a01d83..f1da043d 100644
|
||||
--- a/test/client/util/util-js-test.vala
|
||||
+++ b/test/client/util/util-js-test.vala
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
- * Copyright 2017 Michael Gratton <mike@vee.net>
|
||||
+ * Copyright © 2017-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.
|
||||
@@ -61,15 +61,35 @@ public class Util.JS.Test : TestCase {
|
||||
var value = new JSC.Value.array_from_garray(this.context, null);
|
||||
assert_equal(
|
||||
value_to_variant(value).print(true),
|
||||
- "@av []"
|
||||
+ "()"
|
||||
);
|
||||
+
|
||||
var array = new GLib.GenericArray<JSC.Value>();
|
||||
array.add(new JSC.Value.string(this.context, "test"));
|
||||
value = new JSC.Value.array_from_garray(this.context, array);
|
||||
assert_equal(
|
||||
value_to_variant(value).print(true),
|
||||
- "[<'test'>]"
|
||||
+ "['test']"
|
||||
);
|
||||
+
|
||||
+ array = new GLib.GenericArray<JSC.Value>();
|
||||
+ array.add(new JSC.Value.string(this.context, "test1"));
|
||||
+ array.add(new JSC.Value.string(this.context, "test2"));
|
||||
+ value = new JSC.Value.array_from_garray(this.context, array);
|
||||
+ assert_equal(
|
||||
+ value_to_variant(value).print(true),
|
||||
+ "['test1', 'test2']"
|
||||
+ );
|
||||
+
|
||||
+ array = new GLib.GenericArray<JSC.Value>();
|
||||
+ array.add(new JSC.Value.string(this.context, "test"));
|
||||
+ array.add(new JSC.Value.boolean(this.context, true));
|
||||
+ value = new JSC.Value.array_from_garray(this.context, array);
|
||||
+ assert_equal(
|
||||
+ value_to_variant(value).print(true),
|
||||
+ "('test', true)"
|
||||
+ );
|
||||
+
|
||||
value = new JSC.Value.object(this.context, null, null);
|
||||
assert_equal(
|
||||
value_to_variant(value).print(true),
|
||||
@@ -80,7 +100,7 @@ public class Util.JS.Test : TestCase {
|
||||
);
|
||||
assert_equal(
|
||||
value_to_variant(value).print(true),
|
||||
- "{'test': <<true>>}"
|
||||
+ "{'test': <true>}"
|
||||
);
|
||||
}
|
||||
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,234 @@
|
||||
From fb96676fbd4ab7f413071f18cbf444cd7a953b77 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Fri, 28 Aug 2020 11:25:28 +1000
|
||||
Subject: [PATCH 075/124] =?UTF-8?q?Components.WebView:=20Convert=20to=20us?=
|
||||
=?UTF-8?q?ing=20messages=20for=20JS=20=E2=86=92=20client=20comms?=
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
---
|
||||
.../components/components-web-view.vala | 79 +++++++++----------
|
||||
ui/components-web-view.js | 25 +++---
|
||||
2 files changed, 53 insertions(+), 51 deletions(-)
|
||||
|
||||
diff --git a/src/client/components/components-web-view.vala b/src/client/components/components-web-view.vala
|
||||
index c746c441..a5cdfe33 100644
|
||||
--- a/src/client/components/components-web-view.vala
|
||||
+++ b/src/client/components/components-web-view.vala
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
- * Copyright 2016 Software Freedom Conservancy Inc.
|
||||
- * Copyright 2016-2019 Michael Gratton <mike@vee.net>
|
||||
+ * Copyright © 2016 Software Freedom Conservancy Inc.
|
||||
+ * Copyright © 2016-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.
|
||||
@@ -31,12 +31,12 @@ public abstract class Components.WebView : WebKit.WebView, Geary.BaseInterface {
|
||||
private const string MESSAGE_EXCEPTION_NAME = "__exception__";
|
||||
|
||||
// WebKit message handler names
|
||||
- private const string COMMAND_STACK_CHANGED = "commandStackChanged";
|
||||
- private const string CONTENT_LOADED = "contentLoaded";
|
||||
- private const string DOCUMENT_MODIFIED = "documentModified";
|
||||
- private const string PREFERRED_HEIGHT_CHANGED = "preferredHeightChanged";
|
||||
- private const string REMOTE_IMAGE_LOAD_BLOCKED = "remoteImageLoadBlocked";
|
||||
- private const string SELECTION_CHANGED = "selectionChanged";
|
||||
+ private const string COMMAND_STACK_CHANGED = "command_stack_changed";
|
||||
+ private const string CONTENT_LOADED = "content_loaded";
|
||||
+ private const string DOCUMENT_MODIFIED = "document_modified";
|
||||
+ private const string PREFERRED_HEIGHT_CHANGED = "preferred_height_changed";
|
||||
+ private const string REMOTE_IMAGE_LOAD_BLOCKED = "remote_image_load_blocked";
|
||||
+ private const string SELECTION_CHANGED = "selection_changed";
|
||||
|
||||
private const double ZOOM_DEFAULT = 1.0;
|
||||
private const double ZOOM_FACTOR = 0.1;
|
||||
@@ -605,22 +605,22 @@ public abstract class Components.WebView : WebKit.WebView, Geary.BaseInterface {
|
||||
warning("Web process crashed: %s", reason.to_string());
|
||||
});
|
||||
|
||||
- register_message_handler(
|
||||
+ register_message_callback(
|
||||
COMMAND_STACK_CHANGED, on_command_stack_changed
|
||||
);
|
||||
- register_message_handler(
|
||||
+ register_message_callback(
|
||||
CONTENT_LOADED, on_content_loaded
|
||||
);
|
||||
- register_message_handler(
|
||||
+ register_message_callback(
|
||||
DOCUMENT_MODIFIED, on_document_modified
|
||||
);
|
||||
- register_message_handler(
|
||||
+ register_message_callback(
|
||||
PREFERRED_HEIGHT_CHANGED, on_preferred_height_changed
|
||||
);
|
||||
- register_message_handler(
|
||||
+ register_message_callback(
|
||||
REMOTE_IMAGE_LOAD_BLOCKED, on_remote_image_load_blocked
|
||||
);
|
||||
- register_message_handler(
|
||||
+ register_message_callback(
|
||||
SELECTION_CHANGED, on_selection_changed
|
||||
);
|
||||
|
||||
@@ -783,12 +783,12 @@ public abstract class Components.WebView : WebKit.WebView, Geary.BaseInterface {
|
||||
return false;
|
||||
}
|
||||
|
||||
- private void on_preferred_height_changed(WebKit.JavascriptResult result) {
|
||||
+ private void on_preferred_height_changed(GLib.Variant? parameters) {
|
||||
double height = this.webkit_reported_height;
|
||||
- try {
|
||||
- height = Util.JS.to_double(result.get_js_value());
|
||||
- } catch (Util.JS.Error err) {
|
||||
- debug("Could not get preferred height: %s", err.message);
|
||||
+ if (parameters != null && parameters.classify() == DOUBLE) {
|
||||
+ height = parameters.get_double();
|
||||
+ } else {
|
||||
+ warning("Could not get JS preferred height");
|
||||
}
|
||||
|
||||
if (this.webkit_reported_height != height) {
|
||||
@@ -797,40 +797,39 @@ public abstract class Components.WebView : WebKit.WebView, Geary.BaseInterface {
|
||||
}
|
||||
}
|
||||
|
||||
- private void on_command_stack_changed(WebKit.JavascriptResult result) {
|
||||
- try {
|
||||
- string[] values =
|
||||
- Util.JS.to_string(result.get_js_value()).split(",");
|
||||
- command_stack_changed(values[0] == "true", values[1] == "true");
|
||||
- } catch (Util.JS.Error err) {
|
||||
- debug("Could not get command stack state: %s", err.message);
|
||||
+ private void on_command_stack_changed(GLib.Variant? parameters) {
|
||||
+ if (parameters != null &&
|
||||
+ parameters.is_container() &&
|
||||
+ parameters.n_children() == 2) {
|
||||
+ GLib.Variant can_undo = parameters.get_child_value(0);
|
||||
+ GLib.Variant can_redo = parameters.get_child_value(1);
|
||||
+ command_stack_changed(
|
||||
+ can_undo.classify() == BOOLEAN && can_undo.get_boolean(),
|
||||
+ can_redo.classify() == BOOLEAN && can_redo.get_boolean()
|
||||
+ );
|
||||
+ } else {
|
||||
+ warning("Could not get JS command stack state");
|
||||
}
|
||||
}
|
||||
|
||||
- private void on_document_modified(WebKit.JavascriptResult result) {
|
||||
+ private void on_document_modified(GLib.Variant? parameters) {
|
||||
document_modified();
|
||||
}
|
||||
|
||||
- private void on_remote_image_load_blocked(WebKit.JavascriptResult result) {
|
||||
+ private void on_remote_image_load_blocked(GLib.Variant? parameters) {
|
||||
remote_image_load_blocked();
|
||||
}
|
||||
|
||||
- private void on_content_loaded(WebKit.JavascriptResult result) {
|
||||
+ private void on_content_loaded(GLib.Variant? parameters) {
|
||||
this.is_content_loaded = true;
|
||||
content_loaded();
|
||||
}
|
||||
|
||||
- private void on_selection_changed(WebKit.JavascriptResult result) {
|
||||
- try {
|
||||
- bool has_selection = Util.JS.to_bool(result.get_js_value());
|
||||
- // Avoid firing multiple notifies if the value hasn't
|
||||
- // changed
|
||||
- if (this.has_selection != has_selection) {
|
||||
- this.has_selection = has_selection;
|
||||
- }
|
||||
- selection_changed(has_selection);
|
||||
- } catch (Util.JS.Error err) {
|
||||
- debug("Could not get selection content: %s", err.message);
|
||||
+ private void on_selection_changed(GLib.Variant? parameters) {
|
||||
+ if (parameters != null && parameters.classify() == BOOLEAN) {
|
||||
+ selection_changed(parameters.get_boolean());
|
||||
+ } else {
|
||||
+ warning("Could not get JS selection value");
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/ui/components-web-view.js b/ui/components-web-view.js
|
||||
index 35e82dfc..29b6acd5 100644
|
||||
--- a/ui/components-web-view.js
|
||||
+++ b/ui/components-web-view.js
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
- * Copyright 2016 Michael Gratton <mike@vee.net>
|
||||
+ * Copyright © 2016-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.
|
||||
@@ -20,6 +20,13 @@ PageState.prototype = {
|
||||
this.hasSelection = false;
|
||||
this.lastPreferredHeight = 0;
|
||||
|
||||
+ this._selectionChanged = MessageSender("selection_changed");
|
||||
+ this._contentLoaded = MessageSender("content_loaded");
|
||||
+ this._remoteImageLoadBlocked = MessageSender("remote_image_load_blocked");
|
||||
+ this._preferredHeightChanged = MessageSender("preferred_height_changed");
|
||||
+ this._commandStackChanged = MessageSender("command_stack_changed");
|
||||
+ this._documentModified = MessageSender("document_modified");
|
||||
+
|
||||
let state = this;
|
||||
|
||||
// Set up an observer to keep track of modifications made to
|
||||
@@ -106,7 +113,7 @@ PageState.prototype = {
|
||||
// be vaguegly correct when notifying of the HTML load
|
||||
// completing.
|
||||
this.updatePreferredHeight();
|
||||
- window.webkit.messageHandlers.contentLoaded.postMessage(null);
|
||||
+ this._contentLoaded();
|
||||
},
|
||||
loadRemoteImages: function() {
|
||||
window._gearyAllowRemoteResourceLoads = true;
|
||||
@@ -142,7 +149,7 @@ PageState.prototype = {
|
||||
this.bodyObserver.disconnect();
|
||||
},
|
||||
remoteImageLoadBlocked: function() {
|
||||
- window.webkit.messageHandlers.remoteImageLoadBlocked.postMessage(null);
|
||||
+ this._remoteImageLoadBlocked();
|
||||
},
|
||||
/**
|
||||
* Sends "preferredHeightChanged" message if it has changed.
|
||||
@@ -160,9 +167,7 @@ PageState.prototype = {
|
||||
// shrink again, leading to visual flicker.
|
||||
if (this.isLoaded && height > 0 && height != this.lastPreferredHeight) {
|
||||
this.lastPreferredHeight = height;
|
||||
- window.webkit.messageHandlers.preferredHeightChanged.postMessage(
|
||||
- height
|
||||
- );
|
||||
+ this._preferredHeightChanged(height);
|
||||
}
|
||||
},
|
||||
checkCommandStack: function() {
|
||||
@@ -172,19 +177,17 @@ PageState.prototype = {
|
||||
if (canUndo != this.undoEnabled || canRedo != this.redoEnabled) {
|
||||
this.undoEnabled = canUndo;
|
||||
this.redoEnabled = canRedo;
|
||||
- window.webkit.messageHandlers.commandStackChanged.postMessage(
|
||||
- this.undoEnabled + "," + this.redoEnabled
|
||||
- );
|
||||
+ this._commandStackChanged(this.undoEnabled, this.redoEnabled);
|
||||
}
|
||||
},
|
||||
documentModified: function(element) {
|
||||
- window.webkit.messageHandlers.documentModified.postMessage(null);
|
||||
+ this._documentModified();
|
||||
},
|
||||
selectionChanged: function() {
|
||||
let hasSelection = !window.getSelection().isCollapsed;
|
||||
if (this.hasSelection != hasSelection) {
|
||||
this.hasSelection = hasSelection;
|
||||
- window.webkit.messageHandlers.selectionChanged.postMessage(hasSelection);
|
||||
+ this._selectionChanged(hasSelection);
|
||||
}
|
||||
},
|
||||
// Methods below are for unit tests.
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,185 @@
|
||||
From 3655f4896f2b33f47a94c8e7dc4f9623ba42fc2e Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Fri, 28 Aug 2020 11:38:06 +1000
|
||||
Subject: [PATCH 076/124] =?UTF-8?q?Composer.WebView:=20Convert=20to=20usin?=
|
||||
=?UTF-8?q?g=20messages=20for=20JS=20=E2=86=92=20client=20comms?=
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
---
|
||||
src/client/composer/composer-web-view.vala | 75 ++++++++++------------
|
||||
ui/composer-web-view.js | 18 ++++--
|
||||
2 files changed, 45 insertions(+), 48 deletions(-)
|
||||
|
||||
diff --git a/src/client/composer/composer-web-view.vala b/src/client/composer/composer-web-view.vala
|
||||
index 24a2740c..57b7e1e4 100644
|
||||
--- a/src/client/composer/composer-web-view.vala
|
||||
+++ b/src/client/composer/composer-web-view.vala
|
||||
@@ -33,8 +33,8 @@ public class Composer.WebView : Components.WebView {
|
||||
private const string SPACER = "<div><br /></div>";
|
||||
|
||||
// WebKit message handler names
|
||||
- private const string CURSOR_CONTEXT_CHANGED = "cursorContextChanged";
|
||||
- private const string DRAG_DROP_RECEIVED = "dragDropReceived";
|
||||
+ private const string CURSOR_CONTEXT_CHANGED = "cursor_context_changed";
|
||||
+ private const string DRAG_DROP_RECEIVED = "drag_drop_received";
|
||||
|
||||
/**
|
||||
* Encapsulates editing-related state for a specific DOM node.
|
||||
@@ -152,8 +152,8 @@ public class Composer.WebView : Components.WebView {
|
||||
this.user_content_manager.add_style_sheet(WebView.app_style);
|
||||
this.user_content_manager.add_script(WebView.app_script);
|
||||
|
||||
- register_message_handler(CURSOR_CONTEXT_CHANGED, on_cursor_context_changed);
|
||||
- register_message_handler(DRAG_DROP_RECEIVED, on_drag_drop_received);
|
||||
+ register_message_callback(CURSOR_CONTEXT_CHANGED, on_cursor_context_changed);
|
||||
+ register_message_callback(DRAG_DROP_RECEIVED, on_drag_drop_received);
|
||||
|
||||
// XXX this is a bit of a hack given the docs for is_empty,
|
||||
// above
|
||||
@@ -530,50 +530,43 @@ public class Composer.WebView : Components.WebView {
|
||||
return ret;
|
||||
}
|
||||
|
||||
- private void on_cursor_context_changed(WebKit.JavascriptResult result) {
|
||||
- try {
|
||||
- cursor_context_changed(
|
||||
- new EditContext(Util.JS.to_string(result.get_js_value()))
|
||||
- );
|
||||
- } catch (Util.JS.Error err) {
|
||||
- debug("Could not get text cursor style: %s", err.message);
|
||||
+ private void on_cursor_context_changed(GLib.Variant? parameters) {
|
||||
+ if (parameters != null && parameters.classify() == STRING) {
|
||||
+ cursor_context_changed(new EditContext(parameters as string));
|
||||
+ } else {
|
||||
+ warning("Could not get text cursor style");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a dropped image
|
||||
*/
|
||||
- private void on_drag_drop_received(WebKit.JavascriptResult result) {
|
||||
-
|
||||
- try {
|
||||
- JSC.Value object = result.get_js_value();
|
||||
- string filename = Util.JS.to_string(
|
||||
- Util.JS.get_property(object, "fileName")
|
||||
- );
|
||||
- string filename_unescaped = GLib.Uri.unescape_string(filename);
|
||||
-
|
||||
- string file_type = Util.JS.to_string(
|
||||
- Util.JS.get_property(object, "fileType")
|
||||
- );
|
||||
-
|
||||
- string content_base64 = Util.JS.to_string(
|
||||
- Util.JS.get_property(object, "content")
|
||||
- );
|
||||
- uint8[] image = GLib.Base64.decode(content_base64);
|
||||
-
|
||||
- if (image.length == 0) {
|
||||
- warning("%s is empty", filename);
|
||||
- return;
|
||||
- }
|
||||
+ private void on_drag_drop_received(GLib.Variant? parameters) {
|
||||
+ var dict = new GLib.VariantDict(parameters);
|
||||
+ string file_name = dict.lookup_value(
|
||||
+ "fileName", GLib.VariantType.STRING
|
||||
+ ).get_string();
|
||||
+ string file_name_unescaped = GLib.Uri.unescape_string(file_name);
|
||||
+
|
||||
+ string file_type = dict.lookup_value(
|
||||
+ "fileType", GLib.VariantType.STRING
|
||||
+ ).get_string();
|
||||
+
|
||||
+ string content_base64 = dict.lookup_value(
|
||||
+ "content", GLib.VariantType.STRING
|
||||
+ ).get_string();
|
||||
+ uint8[] image = GLib.Base64.decode(content_base64);
|
||||
+
|
||||
+ if (image.length == 0) {
|
||||
+ warning("%s is empty", file_name);
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
- // A simple check to see if the file looks like an image. A problem here
|
||||
- // will be this accepting types which won't be supported by WebKit
|
||||
- // or recipients.
|
||||
- if (file_type.index_of("image/") == 0) {
|
||||
- image_file_dropped(filename_unescaped, file_type, image);
|
||||
- }
|
||||
- } catch (Util.JS.Error err) {
|
||||
- debug("Could not get deceptive link param: %s", err.message);
|
||||
+ // A simple check to see if the file looks like an image. A problem here
|
||||
+ // will be this accepting types which won't be supported by WebKit
|
||||
+ // or recipients.
|
||||
+ if (file_type.index_of("image/") == 0) {
|
||||
+ image_file_dropped(file_name_unescaped, file_type, image);
|
||||
}
|
||||
}
|
||||
}
|
||||
diff --git a/ui/composer-web-view.js b/ui/composer-web-view.js
|
||||
index ca918990..4fe34ad0 100644
|
||||
--- a/ui/composer-web-view.js
|
||||
+++ b/ui/composer-web-view.js
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
- * Copyright 2016 Software Freedom Conservancy Inc.
|
||||
- * Copyright 2016 Michael Gratton <mike@vee.net>
|
||||
+ * Copyright © 2016 Software Freedom Conservancy Inc.
|
||||
+ * Copyright © 2016-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.
|
||||
@@ -35,6 +35,9 @@ ComposerPageState.prototype = {
|
||||
this.nextSelectionId = 0;
|
||||
this.cursorContext = null;
|
||||
|
||||
+ this._cursorContextChanged = MessageSender("cursor_context_changed");
|
||||
+ this._dragDropReceived = MessageSender("drag_drop_received");
|
||||
+
|
||||
document.addEventListener("click", function(e) {
|
||||
if (e.target.tagName == "A") {
|
||||
e.preventDefault();
|
||||
@@ -99,7 +102,9 @@ ComposerPageState.prototype = {
|
||||
}, true);
|
||||
|
||||
// Handle file drag & drop
|
||||
- document.body.addEventListener("drop", state.handleFileDrop, true);
|
||||
+ document.body.addEventListener("drop", function(e) {
|
||||
+ state.handleFileDrop(e);
|
||||
+ }, true);
|
||||
document.body.addEventListener("allowDrop", function(e) {
|
||||
ev.preventDefault();
|
||||
}, true);
|
||||
@@ -346,9 +351,7 @@ ComposerPageState.prototype = {
|
||||
let newContext = new EditContext(cursor);
|
||||
if (!newContext.equals(this.cursorContext)) {
|
||||
this.cursorContext = newContext;
|
||||
- window.webkit.messageHandlers.cursorContextChanged.postMessage(
|
||||
- newContext.encode()
|
||||
- );
|
||||
+ this._cursorContextChanged(newContext.encode());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -396,13 +399,14 @@ ComposerPageState.prototype = {
|
||||
continue;
|
||||
|
||||
const reader = new FileReader();
|
||||
+ const state = this;
|
||||
reader.onload = (function(filename, imageType) { return function(loadEvent) {
|
||||
// Remove prefixed file type and encoding type
|
||||
var parts = loadEvent.target.result.split(",");
|
||||
if (parts.length < 2)
|
||||
return;
|
||||
|
||||
- window.webkit.messageHandlers.dragDropReceived.postMessage({
|
||||
+ state._dragDropReceived({
|
||||
fileName: encodeURIComponent(filename),
|
||||
fileType: imageType,
|
||||
content: parts[1]
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,142 @@
|
||||
From 7b0146274ccaad18115a66ded6753cb68bd22357 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Fri, 28 Aug 2020 11:45:35 +1000
|
||||
Subject: [PATCH 077/124] =?UTF-8?q?Conversation.WebView:=20Convert=20to=20?=
|
||||
=?UTF-8?q?using=20messages=20for=20JS=20=E2=86=92=20client=20comms?=
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
---
|
||||
.../conversation-web-view.vala | 71 +++++++++----------
|
||||
ui/conversation-web-view.js | 4 +-
|
||||
2 files changed, 38 insertions(+), 37 deletions(-)
|
||||
|
||||
diff --git a/src/client/conversation-viewer/conversation-web-view.vala b/src/client/conversation-viewer/conversation-web-view.vala
|
||||
index d77af642..a1ba21a6 100644
|
||||
--- a/src/client/conversation-viewer/conversation-web-view.vala
|
||||
+++ b/src/client/conversation-viewer/conversation-web-view.vala
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
- * Copyright 2016 Software Freedom Conservancy Inc.
|
||||
- * Copyright 2017 Michael Gratton <mike@vee.net>
|
||||
+ * Copyright © 2016 Software Freedom Conservancy Inc.
|
||||
+ * Copyright © 2017-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.
|
||||
@@ -9,7 +9,7 @@
|
||||
public class ConversationWebView : Components.WebView {
|
||||
|
||||
|
||||
- private const string DECEPTIVE_LINK_CLICKED = "deceptiveLinkClicked";
|
||||
+ private const string DECEPTIVE_LINK_CLICKED = "deceptive_link_clicked";
|
||||
|
||||
// Key codes we don't forward on to the super class on key press
|
||||
// since we want to override them elsewhere, especially
|
||||
@@ -221,48 +221,47 @@ public class ConversationWebView : Components.WebView {
|
||||
}
|
||||
|
||||
private void init() {
|
||||
- register_message_handler(
|
||||
+ register_message_callback(
|
||||
DECEPTIVE_LINK_CLICKED, on_deceptive_link_clicked
|
||||
);
|
||||
|
||||
this.notify["preferred-height"].connect(() => queue_resize());
|
||||
}
|
||||
|
||||
- private void on_deceptive_link_clicked(WebKit.JavascriptResult result) {
|
||||
- try {
|
||||
- JSC.Value object = result.get_js_value();
|
||||
- uint reason = (uint) Util.JS.to_int32(
|
||||
- Util.JS.get_property(object, "reason")
|
||||
- );
|
||||
-
|
||||
- string href = Util.JS.to_string(
|
||||
- Util.JS.get_property(object, "href")
|
||||
- );
|
||||
+ private void on_deceptive_link_clicked(GLib.Variant? parameters) {
|
||||
+ var dict = new GLib.VariantDict(parameters);
|
||||
+ uint reason = (uint) dict.lookup_value(
|
||||
+ "reason", GLib.VariantType.DOUBLE
|
||||
+ ).get_double();
|
||||
|
||||
- string text = Util.JS.to_string(
|
||||
- Util.JS.get_property(object, "text")
|
||||
- );
|
||||
-
|
||||
- JSC.Value js_location = Util.JS.get_property(object, "location");
|
||||
+ string href = dict.lookup_value(
|
||||
+ "href", GLib.VariantType.STRING
|
||||
+ ).get_string();
|
||||
|
||||
- Gdk.Rectangle location = Gdk.Rectangle();
|
||||
- location.x = Util.JS.to_int32(
|
||||
- Util.JS.get_property(js_location, "x")
|
||||
- );
|
||||
- location.y = Util.JS.to_int32(
|
||||
- Util.JS.get_property(js_location, "y")
|
||||
- );
|
||||
- location.width = Util.JS.to_int32(
|
||||
- Util.JS.get_property(js_location, "width")
|
||||
- );
|
||||
- location.height = Util.JS.to_int32(
|
||||
- Util.JS.get_property(js_location, "height")
|
||||
- );
|
||||
+ string text = dict.lookup_value(
|
||||
+ "text", GLib.VariantType.STRING
|
||||
+ ).get_string();
|
||||
|
||||
- deceptive_link_clicked((DeceptiveText) reason, text, href, location);
|
||||
- } catch (Util.JS.Error err) {
|
||||
- debug("Could not get deceptive link param: %s", err.message);
|
||||
- }
|
||||
+ Gdk.Rectangle location = Gdk.Rectangle();
|
||||
+ var location_dict = new GLib.VariantDict(
|
||||
+ dict.lookup_value("location", GLib.VariantType.VARDICT)
|
||||
+ );
|
||||
+ location.x = (int) location_dict.lookup_value(
|
||||
+ "x", GLib.VariantType.DOUBLE
|
||||
+ ).get_double();
|
||||
+ location.y = (int) location_dict.lookup_value(
|
||||
+ "y", GLib.VariantType.DOUBLE
|
||||
+ ).get_double();
|
||||
+ location.width = (int) location_dict.lookup_value(
|
||||
+ "width", GLib.VariantType.DOUBLE
|
||||
+ ).get_double();
|
||||
+ location.height = (int) location_dict.lookup_value(
|
||||
+ "height", GLib.VariantType.DOUBLE
|
||||
+ ).get_double();
|
||||
+
|
||||
+ deceptive_link_clicked(
|
||||
+ (DeceptiveText) reason, text, href, location
|
||||
+ );
|
||||
}
|
||||
|
||||
}
|
||||
diff --git a/ui/conversation-web-view.js b/ui/conversation-web-view.js
|
||||
index 451db288..1d730d47 100644
|
||||
--- a/ui/conversation-web-view.js
|
||||
+++ b/ui/conversation-web-view.js
|
||||
@@ -26,6 +26,8 @@ ConversationPageState.prototype = {
|
||||
init: function() {
|
||||
PageState.prototype.init.apply(this, []);
|
||||
|
||||
+ this._deceptiveLinkClicked = MessageSender("deceptive_link_clicked");
|
||||
+
|
||||
let state = this;
|
||||
document.addEventListener("click", function(e) {
|
||||
if (e.target.tagName == "A" &&
|
||||
@@ -267,7 +269,7 @@ ConversationPageState.prototype = {
|
||||
let reason = ConversationPageState.isDeceptiveText(text, href);
|
||||
if (reason != ConversationPageState.NOT_DECEPTIVE) {
|
||||
cancelClick = true;
|
||||
- window.webkit.messageHandlers.deceptiveLinkClicked.postMessage({
|
||||
+ this._deceptiveLinkClicked({
|
||||
reason: reason,
|
||||
text: text,
|
||||
href: href,
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,138 @@
|
||||
From 7950ce50c6bdb6ca77561a00d1afb9bc689278cf Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Fri, 28 Aug 2020 11:59:11 +1000
|
||||
Subject: [PATCH 078/124] GearyWebExtension: Untangle extension and JS
|
||||
interaction a bit
|
||||
|
||||
Move selection changed event listener into JS so it doesn't have to
|
||||
cross the JS/native boundary twice.
|
||||
|
||||
Move sending remote load blocked from JS to the extension since we can
|
||||
do that directly now and again so the JS/native boundary doesn't need
|
||||
to be double-crossed again.
|
||||
---
|
||||
.../web-process/web-process-extension.vala | 60 ++-----------------
|
||||
ui/components-web-view.js | 8 +--
|
||||
2 files changed, 8 insertions(+), 60 deletions(-)
|
||||
|
||||
diff --git a/src/client/web-process/web-process-extension.vala b/src/client/web-process/web-process-extension.vala
|
||||
index 31f2b0f0..6eed7746 100644
|
||||
--- a/src/client/web-process/web-process-extension.vala
|
||||
+++ b/src/client/web-process/web-process-extension.vala
|
||||
@@ -77,7 +77,10 @@ public class GearyWebExtension : Object {
|
||||
if (should_load_remote_images(page)) {
|
||||
should_load = true;
|
||||
} else {
|
||||
- remote_image_load_blocked(page);
|
||||
+ page.send_message_to_view.begin(
|
||||
+ new WebKit.UserMessage("remote_image_load_blocked", null),
|
||||
+ null
|
||||
+ );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,54 +102,6 @@ public class GearyWebExtension : Object {
|
||||
return should_load;
|
||||
}
|
||||
|
||||
- private void remote_image_load_blocked(WebKit.WebPage page) {
|
||||
- WebKit.Frame frame = page.get_main_frame();
|
||||
- JSC.Context context = frame.get_js_context();
|
||||
- try {
|
||||
- execute_script(
|
||||
- context,
|
||||
- "geary.remoteImageLoadBlocked();",
|
||||
- GLib.Log.FILE,
|
||||
- GLib.Log.METHOD,
|
||||
- GLib.Log.LINE
|
||||
- );
|
||||
- } catch (Error err) {
|
||||
- debug(
|
||||
- "Error calling PageState::remoteImageLoadBlocked: %s",
|
||||
- err.message
|
||||
- );
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- private void selection_changed(WebKit.WebPage page) {
|
||||
- WebKit.Frame frame = page.get_main_frame();
|
||||
- JSC.Context context = frame.get_js_context();
|
||||
- try {
|
||||
- execute_script(
|
||||
- context,
|
||||
- "geary.selectionChanged();",
|
||||
- GLib.Log.FILE,
|
||||
- GLib.Log.METHOD,
|
||||
- GLib.Log.LINE
|
||||
- );
|
||||
- } catch (Error err) {
|
||||
- debug("Error calling PageStates::selectionChanged: %s", err.message);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- private JSC.Value execute_script(JSC.Context context,
|
||||
- string script,
|
||||
- string file_name,
|
||||
- string method_name,
|
||||
- int line_number)
|
||||
- throws Util.JS.Error {
|
||||
- JSC.Value ret = context.evaluate_with_source_uri(
|
||||
- script, -1, "geary:%s/%s".printf(file_name, method_name), line_number
|
||||
- );
|
||||
- Util.JS.check_exception(context);
|
||||
- return ret;
|
||||
- }
|
||||
-
|
||||
private WebKit.UserMessage to_exception_message(string? name,
|
||||
string? message,
|
||||
string? backtrace = null,
|
||||
@@ -208,13 +163,6 @@ public class GearyWebExtension : Object {
|
||||
|
||||
page.console_message_sent.connect(on_console_message);
|
||||
page.send_request.connect(on_send_request);
|
||||
- // XXX investigate whether the earliest supported
|
||||
- // version of WK supports the DOM "selectionchanged"
|
||||
- // event, and if so use that rather that doing it in
|
||||
- // here in the extension
|
||||
- page.get_editor().selection_changed.connect(() => {
|
||||
- selection_changed(page);
|
||||
- });
|
||||
page.user_message_received.connect(on_page_message_received);
|
||||
}
|
||||
|
||||
diff --git a/ui/components-web-view.js b/ui/components-web-view.js
|
||||
index 29b6acd5..d0998a67 100644
|
||||
--- a/ui/components-web-view.js
|
||||
+++ b/ui/components-web-view.js
|
||||
@@ -22,7 +22,6 @@ PageState.prototype = {
|
||||
|
||||
this._selectionChanged = MessageSender("selection_changed");
|
||||
this._contentLoaded = MessageSender("content_loaded");
|
||||
- this._remoteImageLoadBlocked = MessageSender("remote_image_load_blocked");
|
||||
this._preferredHeightChanged = MessageSender("preferred_height_changed");
|
||||
this._commandStackChanged = MessageSender("command_stack_changed");
|
||||
this._documentModified = MessageSender("document_modified");
|
||||
@@ -46,6 +45,10 @@ PageState.prototype = {
|
||||
state.loaded();
|
||||
});
|
||||
|
||||
+ document.addEventListener("selectionchange", function(e) {
|
||||
+ state.selectionChanged();
|
||||
+ });
|
||||
+
|
||||
// Coalesce multiple calls to updatePreferredHeight using a
|
||||
// timeout to avoid the overhead of multiple JS messages sent
|
||||
// to the app and hence view multiple resizes being queued.
|
||||
@@ -148,9 +151,6 @@ PageState.prototype = {
|
||||
stopBodyObserver: function() {
|
||||
this.bodyObserver.disconnect();
|
||||
},
|
||||
- remoteImageLoadBlocked: function() {
|
||||
- this._remoteImageLoadBlocked();
|
||||
- },
|
||||
/**
|
||||
* Sends "preferredHeightChanged" message if it has changed.
|
||||
*/
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,43 @@
|
||||
From eba82a1fbda18c2e567bd143862e7d687982b973 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Fri, 28 Aug 2020 12:01:22 +1000
|
||||
Subject: [PATCH 079/124] GearyWebExtension: Trivial code clean up
|
||||
|
||||
---
|
||||
src/client/web-process/web-process-extension.vala | 7 +++----
|
||||
1 file changed, 3 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/client/web-process/web-process-extension.vala b/src/client/web-process/web-process-extension.vala
|
||||
index 6eed7746..6785903e 100644
|
||||
--- a/src/client/web-process/web-process-extension.vala
|
||||
+++ b/src/client/web-process/web-process-extension.vala
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
- * Copyright 2016 Michael Gratton <mike@vee.net>
|
||||
+ * Copyright © 2016-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.
|
||||
@@ -13,9 +13,9 @@ public void webkit_web_extension_initialize_with_user_data(WebKit.WebExtension e
|
||||
bool logging_enabled = data.get_boolean();
|
||||
|
||||
Geary.Logging.init();
|
||||
- GLib.Log.set_writer_func(Geary.Logging.default_log_writer);
|
||||
if (logging_enabled) {
|
||||
- Geary.Logging.log_to(stdout);
|
||||
+ GLib.Log.set_writer_func(Geary.Logging.default_log_writer);
|
||||
+ Geary.Logging.log_to(GLib.stdout);
|
||||
}
|
||||
|
||||
debug("Initialising...");
|
||||
@@ -50,7 +50,6 @@ public class GearyWebExtension : Object {
|
||||
extension.page_created.connect(on_page_created);
|
||||
}
|
||||
|
||||
- // XXX Conditionally enable while we still depend on WK2 <2.12
|
||||
private void on_console_message(WebKit.WebPage page,
|
||||
WebKit.ConsoleMessage message) {
|
||||
string source = message.get_source_id();
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,82 @@
|
||||
From 47b134a04eeb502fadb80e6ae2340178645396bd Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Fri, 28 Aug 2020 12:05:23 +1000
|
||||
Subject: [PATCH 080/124] Components.WebView: Remove now-unused message handler
|
||||
infrastructure
|
||||
|
||||
---
|
||||
.../components/components-web-view.vala | 30 +------------------
|
||||
1 file changed, 1 insertion(+), 29 deletions(-)
|
||||
|
||||
diff --git a/src/client/components/components-web-view.vala b/src/client/components/components-web-view.vala
|
||||
index a5cdfe33..904c5358 100644
|
||||
--- a/src/client/components/components-web-view.vala
|
||||
+++ b/src/client/components/components-web-view.vala
|
||||
@@ -195,9 +195,6 @@ public abstract class Components.WebView : WebKit.WebView, Geary.BaseInterface {
|
||||
}
|
||||
|
||||
|
||||
- /** Delegate for UserContentManager message callbacks. */
|
||||
- public delegate void JavaScriptMessageHandler(WebKit.JavascriptResult js_result);
|
||||
-
|
||||
/**
|
||||
* Delegate for message handler callbacks.
|
||||
*
|
||||
@@ -279,8 +276,6 @@ public abstract class Components.WebView : WebKit.WebView, Geary.BaseInterface {
|
||||
private Gee.Map<string,Geary.Memory.Buffer> internal_resources =
|
||||
new Gee.HashMap<string,Geary.Memory.Buffer>();
|
||||
|
||||
- private Gee.List<ulong> registered_message_handlers =
|
||||
- new Gee.LinkedList<ulong>();
|
||||
private Gee.Map<string,MessageCallable> message_handlers =
|
||||
new Gee.HashMap<string,MessageCallable>();
|
||||
|
||||
@@ -357,7 +352,7 @@ public abstract class Components.WebView : WebKit.WebView, Geary.BaseInterface {
|
||||
* The new view will use the same WebProcess, settings and content
|
||||
* manager as the given related view's.
|
||||
*
|
||||
- * @see WebKit.WebView.with_related_view
|
||||
+ * @see WebKit.WebView.WebView.with_related_view
|
||||
*/
|
||||
protected WebView.with_related_view(Application.Configuration config,
|
||||
WebView related) {
|
||||
@@ -375,10 +370,6 @@ public abstract class Components.WebView : WebKit.WebView, Geary.BaseInterface {
|
||||
}
|
||||
|
||||
public override void destroy() {
|
||||
- foreach (ulong id in this.registered_message_handlers) {
|
||||
- this.user_content_manager.disconnect(id);
|
||||
- }
|
||||
- this.registered_message_handlers.clear();
|
||||
this.message_handlers.clear();
|
||||
base.destroy();
|
||||
}
|
||||
@@ -570,25 +561,6 @@ public abstract class Components.WebView : WebKit.WebView, Geary.BaseInterface {
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
- /**
|
||||
- * Convenience function for registering and connecting JS messages.
|
||||
- */
|
||||
- protected inline void register_message_handler(string name,
|
||||
- JavaScriptMessageHandler handler) {
|
||||
- // XXX can't use the delegate directly, see b.g.o Bug
|
||||
- // 604781. However the workaround below creates a circular
|
||||
- // reference, causing WebView instances to leak. So to
|
||||
- // work around that we need to record handler ids and
|
||||
- // disconnect them when being destroyed.
|
||||
- ulong id = this.user_content_manager.script_message_received[name].connect(
|
||||
- (result) => { handler(result); }
|
||||
- );
|
||||
- this.registered_message_handlers.add(id);
|
||||
- if (!this.user_content_manager.register_script_message_handler(name)) {
|
||||
- debug("Failed to register script message handler: %s", name);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
/**
|
||||
* Registers a callback for a specific WebKit user message.
|
||||
*/
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,26 @@
|
||||
From 92e842bf083d3185e6ee94b09eab710fb2374fac Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Fri, 28 Aug 2020 12:06:07 +1000
|
||||
Subject: [PATCH 081/124] ConversationViewer.ConversationMessage: Fix valadoc
|
||||
warning
|
||||
|
||||
---
|
||||
src/client/conversation-viewer/conversation-message.vala | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/client/conversation-viewer/conversation-message.vala b/src/client/conversation-viewer/conversation-message.vala
|
||||
index a11ece01..109c4a1c 100644
|
||||
--- a/src/client/conversation-viewer/conversation-message.vala
|
||||
+++ b/src/client/conversation-viewer/conversation-message.vala
|
||||
@@ -666,7 +666,7 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
|
||||
/**
|
||||
* Adds a set of internal resources to web_view.
|
||||
*
|
||||
- * @see add_internal_resource
|
||||
+ * @see Components.WebView.add_internal_resources
|
||||
*/
|
||||
public void add_internal_resources(Gee.Map<string,Geary.Memory.Buffer> res) {
|
||||
if (this.web_view == null)
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,103 @@
|
||||
From 0609fbc3d7cec05a4e5fbf4c5ca9377ea802344b Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Fri, 28 Aug 2020 12:06:36 +1000
|
||||
Subject: [PATCH 082/124] Util.JS: Remove now-unused code
|
||||
|
||||
---
|
||||
src/client/util/util-js.vala | 50 ------------------------------
|
||||
test/client/util/util-js-test.vala | 11 -------
|
||||
2 files changed, 61 deletions(-)
|
||||
|
||||
diff --git a/src/client/util/util-js.vala b/src/client/util/util-js.vala
|
||||
index 095f9da4..193b3c7a 100644
|
||||
--- a/src/client/util/util-js.vala
|
||||
+++ b/src/client/util/util-js.vala
|
||||
@@ -364,56 +364,6 @@ namespace Util.JS {
|
||||
return value;
|
||||
}
|
||||
|
||||
- /**
|
||||
- * Escapes a string so as to be safe to use as a JS string literal.
|
||||
- *
|
||||
- * This does not append opening or closing quotes.
|
||||
- */
|
||||
- public string escape_string(string value) {
|
||||
- StringBuilder builder = new StringBuilder.sized(value.length);
|
||||
- for (int i = 0; i < value.length; i++) {
|
||||
- if (value.valid_char(i)) {
|
||||
- unichar c = value.get_char(i);
|
||||
- switch (c) {
|
||||
- case '\x00':
|
||||
- builder.append("\x00");
|
||||
- break;
|
||||
- case '\'':
|
||||
- builder.append("\\\'");
|
||||
- break;
|
||||
- case '"':
|
||||
- builder.append("\\\"");
|
||||
- break;
|
||||
- case '\\':
|
||||
- builder.append("\\\\");
|
||||
- break;
|
||||
- case '\n':
|
||||
- builder.append("\\n");
|
||||
- break;
|
||||
- case '\r':
|
||||
- builder.append("\\r");
|
||||
- break;
|
||||
- case '\x0b':
|
||||
- builder.append("\x0b");
|
||||
- break;
|
||||
- case '\t':
|
||||
- builder.append("\\t");
|
||||
- break;
|
||||
- case '\b':
|
||||
- builder.append("\\b");
|
||||
- break;
|
||||
- case '\f':
|
||||
- builder.append("\\f");
|
||||
- break;
|
||||
- default:
|
||||
- builder.append_unichar(c);
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
- return (string) builder.data;
|
||||
- }
|
||||
-
|
||||
/**
|
||||
* Convenience method for returning a new Callable instance.
|
||||
*/
|
||||
diff --git a/test/client/util/util-js-test.vala b/test/client/util/util-js-test.vala
|
||||
index f1da043d..9fea3cd7 100644
|
||||
--- a/test/client/util/util-js-test.vala
|
||||
+++ b/test/client/util/util-js-test.vala
|
||||
@@ -13,7 +13,6 @@ public class Util.JS.Test : TestCase {
|
||||
|
||||
public Test() {
|
||||
base("Util.JS.Test");
|
||||
- add_test("escape_string", escape_string);
|
||||
add_test("to_variant", to_variant);
|
||||
add_test("to_value", to_value);
|
||||
}
|
||||
@@ -26,16 +25,6 @@ public class Util.JS.Test : TestCase {
|
||||
this.context = null;
|
||||
}
|
||||
|
||||
- public void escape_string() throws GLib.Error {
|
||||
- assert(Util.JS.escape_string("\n") == """\n""");
|
||||
- assert(Util.JS.escape_string("\r") == """\r""");
|
||||
- assert(Util.JS.escape_string("\t") == """\t""");
|
||||
- assert(Util.JS.escape_string("\'") == """\'""");
|
||||
- assert(Util.JS.escape_string("\"") == """\"""");
|
||||
-
|
||||
- assert(Util.JS.escape_string("something…\n") == """something…\n""");
|
||||
- }
|
||||
-
|
||||
public void to_variant() throws GLib.Error {
|
||||
assert_equal(
|
||||
value_to_variant(new JSC.Value.null(this.context)).print(true),
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,130 @@
|
||||
From 1d80ed2034512aca7e355921c0b942d4cf651b94 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Fri, 28 Aug 2020 12:07:59 +1000
|
||||
Subject: [PATCH 083/124] ComposerPageState: Use CSS for managing focus with
|
||||
composer body parts
|
||||
|
||||
Now that the `:focus-within` pseudoclass is supported, use this rather
|
||||
than some custom JS to update custom HTML classes. This also prevents
|
||||
spurious mutation events from firing.
|
||||
---
|
||||
test/js/composer-page-state-test.vala | 24 ++++++++----------------
|
||||
ui/composer-web-view.css | 6 +++---
|
||||
ui/composer-web-view.js | 25 -------------------------
|
||||
3 files changed, 11 insertions(+), 44 deletions(-)
|
||||
|
||||
diff --git a/test/js/composer-page-state-test.vala b/test/js/composer-page-state-test.vala
|
||||
index 1a2e2df3..5a0a8b3c 100644
|
||||
--- a/test/js/composer-page-state-test.vala
|
||||
+++ b/test/js/composer-page-state-test.vala
|
||||
@@ -11,7 +11,7 @@ class Composer.PageStateTest : Components.WebViewTestCase<Composer.WebView> {
|
||||
"""<div id="geary-body" dir="auto">%s<div><br></div><div><br></div></div><div id="geary-signature" dir="auto"></div>""";
|
||||
public const string DIRTY_BODY_TEMPLATE =
|
||||
"""
|
||||
-<div id="geary-body" dir="auto" class="geary-focus" contenteditable="true">%s<div><br></div><div><br></div></div>
|
||||
+<div id="geary-body" dir="auto" contenteditable="true">%s<div><br></div><div><br></div></div>
|
||||
<div id="geary-signature" class="geary-no-display" dir="auto" contenteditable="true"></div>
|
||||
""";
|
||||
public const string CLEAN_BODY_TEMPLATE = """<div id="geary-body" dir="auto">%s<div><br></div><div><br></div></div>""";
|
||||
@@ -227,7 +227,7 @@ some text
|
||||
}
|
||||
}
|
||||
|
||||
- public void clean_content() throws Error {
|
||||
+ public void clean_content() throws GLib.Error {
|
||||
// XXX split these up into multiple tests
|
||||
load_body_fixture("""
|
||||
http://example1.com
|
||||
@@ -257,20 +257,12 @@ unknown://example6.com
|
||||
I can send email through smtp.gmail.com:587 or through <a href="https://www.gmail.com/">https://www.gmail.com/</a>
|
||||
""";
|
||||
|
||||
- try {
|
||||
- run_javascript("geary.cleanContent();");
|
||||
- string result = Util.JS.to_string(
|
||||
- run_javascript("window.document.body.innerHTML;")
|
||||
- .get_js_value()
|
||||
- );
|
||||
- assert(result == DIRTY_BODY_TEMPLATE.printf(expected));
|
||||
- } catch (Util.JS.Error err) {
|
||||
- print("Util.JS.Error: %s\n", err.message);
|
||||
- assert_not_reached();
|
||||
- } catch (Error err) {
|
||||
- print("WKError: %s\n", err.message);
|
||||
- assert_not_reached();
|
||||
- }
|
||||
+ run_javascript("geary.cleanContent();");
|
||||
+ string result = Util.JS.to_string(
|
||||
+ run_javascript("window.document.body.innerHTML;")
|
||||
+ .get_js_value()
|
||||
+ );
|
||||
+ assert_equal(result, DIRTY_BODY_TEMPLATE.printf(expected));
|
||||
}
|
||||
|
||||
public void get_html() throws Error {
|
||||
diff --git a/ui/composer-web-view.css b/ui/composer-web-view.css
|
||||
index 3cecfb3b..07ae6869 100644
|
||||
--- a/ui/composer-web-view.css
|
||||
+++ b/ui/composer-web-view.css
|
||||
@@ -43,12 +43,12 @@ body > div#geary-quote {
|
||||
padding: 6px !important;
|
||||
}
|
||||
|
||||
-body > div.geary-focus {
|
||||
+body > div:focus-within {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
-body > div#geary-signature.geary-focus,
|
||||
-body > div#geary-quote.geary-focus {
|
||||
+body > div#geary-signature:focus-within,
|
||||
+body > div#geary-quote:focus-within {
|
||||
outline: 1px dashed #ccc !important;
|
||||
}
|
||||
|
||||
diff --git a/ui/composer-web-view.js b/ui/composer-web-view.js
|
||||
index 4fe34ad0..5ee4105e 100644
|
||||
--- a/ui/composer-web-view.js
|
||||
+++ b/ui/composer-web-view.js
|
||||
@@ -123,7 +123,6 @@ ComposerPageState.prototype = {
|
||||
|
||||
// Focus within the HTML document
|
||||
document.body.focus();
|
||||
- this.updateFocusClass(this.bodyPart);
|
||||
|
||||
// Set text cursor at appropriate position
|
||||
let cursor = document.getElementById("cursormarker");
|
||||
@@ -354,30 +353,6 @@ ComposerPageState.prototype = {
|
||||
this._cursorContextChanged(newContext.encode());
|
||||
}
|
||||
}
|
||||
-
|
||||
- while (cursor != null) {
|
||||
- let parent = cursor.parentNode;
|
||||
- if (parent == document.body) {
|
||||
- this.updateFocusClass(cursor);
|
||||
- break;
|
||||
- }
|
||||
- cursor = parent;
|
||||
- }
|
||||
- },
|
||||
- /**
|
||||
- * Work around WebKit note yet supporting :focus-inside pseudoclass.
|
||||
- */
|
||||
- updateFocusClass: function(newFocus) {
|
||||
- if (this.focusedPart != null) {
|
||||
- this.focusedPart.classList.remove("geary-focus");
|
||||
- this.focusedPart = null;
|
||||
- }
|
||||
- if (newFocus == this.bodyPart ||
|
||||
- newFocus == this.signaturePart ||
|
||||
- newFocus == this.quotePart) {
|
||||
- this.focusedPart = newFocus;
|
||||
- this.focusedPart.classList.add("geary-focus");
|
||||
- }
|
||||
},
|
||||
containedInPart: function(target) {
|
||||
let inPart = false;
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,26 @@
|
||||
From 3f7c054db085a846b550c2cbc9fb71b352add2b9 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Sat, 29 Aug 2020 12:57:08 +1000
|
||||
Subject: [PATCH 084/124] build: Bump WebKitGTK min version to include
|
||||
UserMessage support
|
||||
|
||||
---
|
||||
meson.build | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/meson.build b/meson.build
|
||||
index 240eacaa..9b55b24d 100644
|
||||
--- a/meson.build
|
||||
+++ b/meson.build
|
||||
@@ -53,7 +53,7 @@ valac = meson.get_compiler('vala')
|
||||
target_vala = '0.48.6'
|
||||
target_glib = '2.64'
|
||||
target_gtk = '3.24.7'
|
||||
-target_webkit = '2.26'
|
||||
+target_webkit = '2.28'
|
||||
|
||||
if not valac.version().version_compare('>=' + target_vala)
|
||||
error('Vala does not meet minimum required version: ' + target_vala)
|
||||
--
|
||||
2.29.2
|
||||
|
1546
mail-client/geary/files/0085-Update-Ukrainian-translation.patch
Normal file
1546
mail-client/geary/files/0085-Update-Ukrainian-translation.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,32 @@
|
||||
From 4db6d01e2356a5c9542ee394ecfaea5aaf6ccab8 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Gratton <mike@vee.net>
|
||||
Date: Tue, 13 Oct 2020 18:49:57 +1100
|
||||
Subject: [PATCH 086/124] client: Remove perf relnote, it's not really that
|
||||
noteworthy
|
||||
|
||||
---
|
||||
desktop/org.gnome.Geary.appdata.xml.in.in | 8 --------
|
||||
1 file changed, 8 deletions(-)
|
||||
|
||||
diff --git a/desktop/org.gnome.Geary.appdata.xml.in.in b/desktop/org.gnome.Geary.appdata.xml.in.in
|
||||
index 471b69c4..7c1ddcab 100644
|
||||
--- a/desktop/org.gnome.Geary.appdata.xml.in.in
|
||||
+++ b/desktop/org.gnome.Geary.appdata.xml.in.in
|
||||
@@ -88,14 +88,6 @@
|
||||
<translation type="gettext">geary</translation>
|
||||
|
||||
<releases>
|
||||
- <release version="3.40" date="">
|
||||
- <description>
|
||||
- <p>Enhancements included in this release:</p>
|
||||
- <ul>
|
||||
- <li>Conversation loading performance improvements</li>
|
||||
- </ul>
|
||||
- </description>
|
||||
- </release>
|
||||
<release version="3.38" date="2020-09-13">
|
||||
<description>
|
||||
<p>Enhancements included in this release:</p>
|
||||
--
|
||||
2.29.2
|
||||
|
973
mail-client/geary/files/0087-Update-Turkish-translation.patch
Normal file
973
mail-client/geary/files/0087-Update-Turkish-translation.patch
Normal file
@ -0,0 +1,973 @@
|
||||
From 1f623bf100b78667e94a75d02a2a4a43512b827c Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Emin=20Tufan=20=C3=87etin?= <etcetin@gmail.com>
|
||||
Date: Tue, 13 Oct 2020 13:48:40 +0000
|
||||
Subject: [PATCH 087/124] Update Turkish translation
|
||||
|
||||
---
|
||||
po/tr.po | 409 +++++++++++++++++++++++++++----------------------------
|
||||
1 file changed, 201 insertions(+), 208 deletions(-)
|
||||
|
||||
diff --git a/po/tr.po b/po/tr.po
|
||||
index f96666c5..51f95638 100644
|
||||
--- a/po/tr.po
|
||||
+++ b/po/tr.po
|
||||
@@ -16,8 +16,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: geary.mainline\n"
|
||||
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/geary/issues\n"
|
||||
-"POT-Creation-Date: 2020-08-30 09:31+0000\n"
|
||||
-"PO-Revision-Date: 2020-08-30 12:32+0300\n"
|
||||
+"POT-Creation-Date: 2020-10-12 10:41+0000\n"
|
||||
+"PO-Revision-Date: 2020-10-13 16:47+0300\n"
|
||||
"Last-Translator: Emin Tufan Çetin <etcetin@gmail.com>\n"
|
||||
"Language-Team: Turkish <gnome-turk@gnome.org>\n"
|
||||
"Language: tr\n"
|
||||
@@ -25,7 +25,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
-"X-Generator: Poedit 2.4\n"
|
||||
+"X-Generator: Poedit 2.4.1\n"
|
||||
|
||||
#: desktop/geary-attach.contract.desktop.in:3
|
||||
msgid "Send by email"
|
||||
@@ -40,7 +40,7 @@ msgstr "Dosyaları Geary kullanarak gönderin"
|
||||
#: desktop/org.gnome.Geary.appdata.xml.in.in:11
|
||||
#: desktop/org.gnome.Geary.desktop.in.in:3
|
||||
#: src/client/accounts/accounts-editor-servers-pane.vala:560
|
||||
-#: src/client/application/application-main-window.vala:608
|
||||
+#: src/client/application/application-main-window.vala:628
|
||||
msgid "Geary"
|
||||
msgstr "Geary"
|
||||
|
||||
@@ -161,75 +161,34 @@ msgid "The last recorded height of the application window."
|
||||
msgstr "Uygulama penceresinin kaydedilen son yüksekliği."
|
||||
|
||||
#: desktop/org.gnome.Geary.gschema.xml:26
|
||||
-msgid "Position of folder list pane"
|
||||
-msgstr "Klasör listesi bölmesinin konumu"
|
||||
-
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:27
|
||||
-msgid "Position of the folder list Paned grabber."
|
||||
-msgstr "Klasör listesi bölmesi yakalayıcının konumu."
|
||||
-
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:32
|
||||
-msgid "Position of folder list pane when horizontal"
|
||||
-msgstr "Klasör listesi bölmesinin yataykenki konumu"
|
||||
-
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:33
|
||||
-msgid ""
|
||||
-"Position of the folder list Paned grabber in the horizontal orientation."
|
||||
-msgstr "Yatay yönelimde klasör listesi bölmesi yakalayıcının konumu."
|
||||
-
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:38
|
||||
-msgid "Position of folder list pane when vertical"
|
||||
-msgstr "Klasör listesi bölmesinin dikeykenki konumu"
|
||||
-
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:39
|
||||
-msgid "Position of the folder list Paned grabber in the vertical orientation."
|
||||
-msgstr "Dikey yönelimde klasör listesi bölmesi yakalayıcının konumu."
|
||||
-
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:44
|
||||
-msgid "Orientation of the folder list pane"
|
||||
-msgstr "Klasör listesi bölmesinin konumlandırması"
|
||||
-
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:45
|
||||
-msgid "True if the folder list Paned is in the horizontal orientation."
|
||||
-msgstr "Eğer klasör listesi bölmesi yatay yönelimdeyse doğru."
|
||||
-
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:50
|
||||
msgid "Show/hide formatting toolbar"
|
||||
msgstr "Biçimlendirme araç çubuğunu göster/gizle"
|
||||
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:51
|
||||
+#: desktop/org.gnome.Geary.gschema.xml:27
|
||||
msgid "True if the formatting toolbar in the composer is shown."
|
||||
msgstr "Eğer oluşturucudaki biçimlendirme araç çubuğu gösterilecekse doğru."
|
||||
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:56
|
||||
-msgid "Position of message list pane"
|
||||
-msgstr "İleti listesi bölmesinin konumu"
|
||||
-
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:57
|
||||
-msgid "Position of the message list Paned grabber."
|
||||
-msgstr "İleti listesi bölmesi yakalayıcının konumu."
|
||||
-
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:62
|
||||
+#: desktop/org.gnome.Geary.gschema.xml:32
|
||||
msgid "Autoselect next message"
|
||||
msgstr "Sonraki iletiyi kendiliğinden seç"
|
||||
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:63
|
||||
+#: desktop/org.gnome.Geary.gschema.xml:33
|
||||
msgid "True if we should autoselect the next available conversation."
|
||||
msgstr "Eğer sonraki uygun konuşmayı kendiliğinden seçmemiz gerekiyorsa doğru."
|
||||
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:68
|
||||
+#: desktop/org.gnome.Geary.gschema.xml:38
|
||||
msgid "Display message previews"
|
||||
msgstr "İleti ön izlemelerini göster"
|
||||
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:69
|
||||
+#: desktop/org.gnome.Geary.gschema.xml:39
|
||||
msgid "True if we should display a short preview of each message."
|
||||
msgstr "Her iletinin kısa bir ön izlemesini göstermemiz gerekiyorsa doğru."
|
||||
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:74
|
||||
+#: desktop/org.gnome.Geary.gschema.xml:44
|
||||
msgid "Use single key shortcuts"
|
||||
msgstr "Tek tuşlu kısayolları kullan"
|
||||
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:75
|
||||
+#: desktop/org.gnome.Geary.gschema.xml:45
|
||||
msgid ""
|
||||
"Enables shortcuts for email actions that do not require pressing <Ctrl> to "
|
||||
"emulate those used by Gmail."
|
||||
@@ -237,11 +196,11 @@ msgstr ""
|
||||
"Gmailʼin kullandığına benzemek için eposta eylemlerinde <Ctrl>ʼye basmayı "
|
||||
"gerektirmeyen kısayolları etkinleştirir."
|
||||
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:82
|
||||
+#: desktop/org.gnome.Geary.gschema.xml:52
|
||||
msgid "Languages that shall be used in the spell checker"
|
||||
msgstr "Yazım denetleyicide kullanılacak diller"
|
||||
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:83
|
||||
+#: desktop/org.gnome.Geary.gschema.xml:53
|
||||
msgid ""
|
||||
"A list of POSIX locales, with the empty list disabling spell checking and "
|
||||
"the null list using desktop languages by default."
|
||||
@@ -249,11 +208,11 @@ msgstr ""
|
||||
"POSIX yerellerinin listesi, boş listeyle imla denetimi devre dışı bırakılır "
|
||||
"ve butlan (null) listeyle öntanımlı olarak masaüstü dillerini kullanılır."
|
||||
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:90
|
||||
+#: desktop/org.gnome.Geary.gschema.xml:60
|
||||
msgid "Languages that are displayed in the spell checker popover"
|
||||
msgstr "Yazım denetleyici açılır penceresinde gösterilecek diller"
|
||||
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:91
|
||||
+#: desktop/org.gnome.Geary.gschema.xml:61
|
||||
msgid ""
|
||||
"List of languages that are always displayed in the popover of the spell "
|
||||
"checker."
|
||||
@@ -261,62 +220,62 @@ msgstr ""
|
||||
"Yazım denetleyicinin açılır penceresinde her zaman gösterilecek dillerin "
|
||||
"listesi."
|
||||
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:96
|
||||
+#: desktop/org.gnome.Geary.gschema.xml:66
|
||||
msgid "Notify of new mail at startup"
|
||||
msgstr "Başlangıçta yeni postanın bildirilmesi"
|
||||
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:97
|
||||
+#: desktop/org.gnome.Geary.gschema.xml:67
|
||||
msgid "True to notify of new mail at startup."
|
||||
msgstr "Başlangıçta yeni postaların bildirilmesi için doğru."
|
||||
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:102
|
||||
+#: desktop/org.gnome.Geary.gschema.xml:72
|
||||
msgid "Ask when opening an attachment"
|
||||
msgstr "Ek açarken sor"
|
||||
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:103
|
||||
+#: desktop/org.gnome.Geary.gschema.xml:73
|
||||
msgid "True to ask when opening an attachment."
|
||||
msgstr "Eki açarken sormak için doğru."
|
||||
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:108
|
||||
+#: desktop/org.gnome.Geary.gschema.xml:78
|
||||
msgid "Whether to compose emails in HTML"
|
||||
msgstr "E-postaların HTML’de oluşturulup oluşturulmayacağı"
|
||||
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:109
|
||||
+#: desktop/org.gnome.Geary.gschema.xml:79
|
||||
msgid "True to compose emails in HTML; false for plain text."
|
||||
msgstr "E-postaları HTML’de oluşturmak için doğru, düz metin için yanlış."
|
||||
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:114
|
||||
+#: desktop/org.gnome.Geary.gschema.xml:84
|
||||
msgid "Advisory strategy for full-text searching"
|
||||
msgstr "Tam metin arama için tavsiye niteliğinde izlem"
|
||||
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:115
|
||||
+#: desktop/org.gnome.Geary.gschema.xml:85
|
||||
msgid ""
|
||||
"Acceptable values are “exact”, “conservative”, “aggressive”, and “horizon”."
|
||||
msgstr ""
|
||||
"Kabul edilebilir değerler şunlardır: “exact” (birebir), "
|
||||
"“conservative” (ılımlı), “aggressive” (sert) ve “horizon”."
|
||||
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:120
|
||||
+#: desktop/org.gnome.Geary.gschema.xml:90
|
||||
msgid "Zoom of conversation viewer"
|
||||
msgstr "Konuşma göstericisinin yakınlaşması"
|
||||
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:121
|
||||
+#: desktop/org.gnome.Geary.gschema.xml:91
|
||||
msgid "The zoom to apply on the conservation view."
|
||||
msgstr "Konuşma görünümünde uygulanacak yakınlaşma."
|
||||
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:126
|
||||
+#: desktop/org.gnome.Geary.gschema.xml:96
|
||||
msgid "Size of detached composer window"
|
||||
msgstr "Ayrılan oluşturucu penceresinin boyutu"
|
||||
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:127
|
||||
+#: desktop/org.gnome.Geary.gschema.xml:97
|
||||
msgid "The last recorded size of the detached composer window."
|
||||
msgstr "Ayrılmış oluşturucu penceresinin kaydedilen son boyutu."
|
||||
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:132
|
||||
+#: desktop/org.gnome.Geary.gschema.xml:102
|
||||
msgid "Undo sending email delay"
|
||||
msgstr "Eposta göndermeyi geri alma gecikmesi"
|
||||
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:133
|
||||
+#: desktop/org.gnome.Geary.gschema.xml:103
|
||||
msgid ""
|
||||
"The number of seconds to wait before sending an email. Set to zero or less "
|
||||
"to disable."
|
||||
@@ -324,29 +283,29 @@ msgstr ""
|
||||
"Eposta gönderilmeden önce beklenecek saniye. Devre dışı bırakmak için sıfır "
|
||||
"veya daha azına belirleyin."
|
||||
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:139
|
||||
+#: desktop/org.gnome.Geary.gschema.xml:109
|
||||
msgid "Brief notification display time"
|
||||
msgstr "Özet bildirim gösterim zamanı"
|
||||
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:140
|
||||
+#: desktop/org.gnome.Geary.gschema.xml:110
|
||||
msgid ""
|
||||
"The length of time in seconds for which brief notifications should be "
|
||||
"displayed."
|
||||
msgstr "Özet bildirimlerin gösterileceği zamanın saniye türünde uzunluğu."
|
||||
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:146
|
||||
+#: desktop/org.gnome.Geary.gschema.xml:116
|
||||
msgid "List of optional plugins"
|
||||
msgstr "İsteğe bağlı eklenti listesi"
|
||||
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:147
|
||||
+#: desktop/org.gnome.Geary.gschema.xml:117
|
||||
msgid "Plugins listed here will be loaded on startup."
|
||||
msgstr "Burada listelenen eklentiler başlangıçta yüklenecek."
|
||||
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:152
|
||||
+#: desktop/org.gnome.Geary.gschema.xml:122
|
||||
msgid "Whether we migrated the old settings"
|
||||
msgstr "Eski ayarları taşıyıp taşımayacağımız"
|
||||
|
||||
-#: desktop/org.gnome.Geary.gschema.xml:153
|
||||
+#: desktop/org.gnome.Geary.gschema.xml:123
|
||||
msgid ""
|
||||
"False to check for the old “org.yorba.geary”-schema and copy its values."
|
||||
msgstr ""
|
||||
@@ -622,12 +581,12 @@ msgid_plural "%d days back"
|
||||
msgstr[0] "%d gün öncesinden"
|
||||
|
||||
#: src/client/accounts/accounts-editor-list-pane.vala:255
|
||||
-#: src/client/application/application-main-window.vala:2061
|
||||
+#: src/client/application/application-main-window.vala:2129
|
||||
msgid "Undo"
|
||||
msgstr "Geri Al"
|
||||
|
||||
#: src/client/accounts/accounts-editor-list-pane.vala:264
|
||||
-#: src/client/application/application-main-window.vala:2044
|
||||
+#: src/client/application/application-main-window.vala:2112
|
||||
msgid "Redo"
|
||||
msgstr "Yinele"
|
||||
|
||||
@@ -722,7 +681,7 @@ msgstr "TLS"
|
||||
#. account
|
||||
#. Translators: An info bar button label
|
||||
#: src/client/accounts/accounts-editor-row.vala:539
|
||||
-#: src/client/application/application-main-window.vala:554
|
||||
+#: src/client/application/application-main-window.vala:574
|
||||
msgid "Login"
|
||||
msgstr "Giriş"
|
||||
|
||||
@@ -974,13 +933,13 @@ msgstr ""
|
||||
|
||||
#. / Warning printed to the console when a deprecated
|
||||
#. / command line option is used.
|
||||
-#: src/client/application/application-client.vala:1047
|
||||
+#: src/client/application/application-client.vala:1045
|
||||
msgid "The `--hidden` option is deprecated and will be removed in the future."
|
||||
msgstr "`--hidden` seçeneği terk edilmiştir ve gelecekte kaldırılacaktır."
|
||||
|
||||
#. / Command line warning, string substitution
|
||||
#. / is the given argument
|
||||
-#: src/client/application/application-client.vala:1080
|
||||
+#: src/client/application/application-client.vala:1078
|
||||
#, c-format
|
||||
msgid "Unrecognised program argument: “%s”"
|
||||
msgstr "Tanınmayan program argümanı: “%s”"
|
||||
@@ -1165,54 +1124,54 @@ msgid "Email to %s discarded"
|
||||
msgstr "Şun(lar)a gidecek eposta gözden çıkarıldı: %s"
|
||||
|
||||
#. Translators: An info bar status label
|
||||
-#: src/client/application/application-main-window.vala:540
|
||||
+#: src/client/application/application-main-window.vala:560
|
||||
msgid "Working offline"
|
||||
msgstr "Çevrim dışı çalışıyor"
|
||||
|
||||
#. Translators: An info bar description label
|
||||
-#: src/client/application/application-main-window.vala:542
|
||||
+#: src/client/application/application-main-window.vala:562
|
||||
msgid "You will not be able to send or receive email until re-connected."
|
||||
msgstr "Yeniden bağlanana dek e-posta gönderemez veya alamazsınız."
|
||||
|
||||
#. Translators: An info bar status label
|
||||
-#: src/client/application/application-main-window.vala:549
|
||||
+#: src/client/application/application-main-window.vala:569
|
||||
msgid "Login problem"
|
||||
msgstr "Giriş sorunu"
|
||||
|
||||
#. Translators: An info bar description label
|
||||
-#: src/client/application/application-main-window.vala:551
|
||||
+#: src/client/application/application-main-window.vala:571
|
||||
msgid "An account has reported an incorrect login or password."
|
||||
msgstr "Hesap yanlış bir giriş veya parola bildirdi."
|
||||
|
||||
#. Translators: An info bar button tool-tip
|
||||
-#: src/client/application/application-main-window.vala:558
|
||||
+#: src/client/application/application-main-window.vala:578
|
||||
msgid "Retry login, you will be prompted for your password"
|
||||
msgstr "Giriş yapmayı yeniden dene, parola girmeniz istenecek"
|
||||
|
||||
#. Translators: An info bar status label
|
||||
-#: src/client/application/application-main-window.vala:565
|
||||
+#: src/client/application/application-main-window.vala:585
|
||||
msgid "Security problem"
|
||||
msgstr "Güvenlik sorunu"
|
||||
|
||||
#. Translators: An info bar description label
|
||||
-#: src/client/application/application-main-window.vala:567
|
||||
+#: src/client/application/application-main-window.vala:587
|
||||
msgid "An account has reported an untrusted server."
|
||||
msgstr "Hesap, güvenilmeyen bir sunucu bildirdi."
|
||||
|
||||
#. Translators: An info bar button label
|
||||
-#: src/client/application/application-main-window.vala:570
|
||||
+#: src/client/application/application-main-window.vala:590
|
||||
msgid "Check"
|
||||
msgstr "Gözden geçir"
|
||||
|
||||
#. Translators: An info bar button tool-tip
|
||||
-#: src/client/application/application-main-window.vala:574
|
||||
+#: src/client/application/application-main-window.vala:594
|
||||
msgid "Check the security details for the connection"
|
||||
msgstr "Bağlantı güvenlik ayrıntılarını gözden geçirin"
|
||||
|
||||
#. / Translators: Main window title, first string
|
||||
#. / substitution being the currently selected folder name,
|
||||
#. / the second being the selected account name.
|
||||
-#: src/client/application/application-main-window.vala:617
|
||||
+#: src/client/application/application-main-window.vala:637
|
||||
#, c-format
|
||||
msgid "%s — %s"
|
||||
msgstr "%s — %s"
|
||||
@@ -1220,47 +1179,47 @@ msgstr "%s — %s"
|
||||
#. Translators: The name of the folder group containing
|
||||
#. folders created by people (as opposed to special-use
|
||||
#. folders)
|
||||
-#: src/client/application/application-main-window.vala:996
|
||||
+#: src/client/application/application-main-window.vala:1019
|
||||
#: src/client/folder-list/folder-list-account-branch.vala:43
|
||||
msgid "Labels"
|
||||
msgstr "Etiketler"
|
||||
|
||||
-#: src/client/application/application-main-window.vala:1293
|
||||
+#: src/client/application/application-main-window.vala:1337
|
||||
#, c-format
|
||||
msgid "Empty all email from your %s folder?"
|
||||
msgstr "%s klasörünüzdeki tüm e-postaları boşalt?"
|
||||
|
||||
-#: src/client/application/application-main-window.vala:1294
|
||||
+#: src/client/application/application-main-window.vala:1338
|
||||
msgid "This removes the email from Geary and your email server."
|
||||
msgstr "Bu işlem e-postayı Geary’den ve e-posta sunucunuzdan kaldırır."
|
||||
|
||||
-#: src/client/application/application-main-window.vala:1295
|
||||
+#: src/client/application/application-main-window.vala:1339
|
||||
msgid "This cannot be undone."
|
||||
msgstr "Bu geri alınamaz."
|
||||
|
||||
-#: src/client/application/application-main-window.vala:1296
|
||||
+#: src/client/application/application-main-window.vala:1340
|
||||
#, c-format
|
||||
msgid "Empty %s"
|
||||
msgstr "%s boşalt"
|
||||
|
||||
#. / Translators: Primary text for a confirmation dialog
|
||||
-#: src/client/application/application-main-window.vala:1353
|
||||
+#: src/client/application/application-main-window.vala:1397
|
||||
msgid "Do you want to permanently delete this conversation?"
|
||||
msgid_plural "Do you want to permanently delete these conversations?"
|
||||
msgstr[0] "Bu konuşmaları kalıcı olarak silmek istiyor musunuz?"
|
||||
|
||||
-#: src/client/application/application-main-window.vala:1358
|
||||
-#: src/client/application/application-main-window.vala:1373
|
||||
+#: src/client/application/application-main-window.vala:1402
|
||||
+#: src/client/application/application-main-window.vala:1417
|
||||
msgid "Delete"
|
||||
msgstr "Sil"
|
||||
|
||||
#. / Translators: Primary text for a confirmation dialog
|
||||
-#: src/client/application/application-main-window.vala:1368
|
||||
+#: src/client/application/application-main-window.vala:1412
|
||||
msgid "Do you want to permanently delete this message?"
|
||||
msgid_plural "Do you want to permanently delete these messages?"
|
||||
msgstr[0] "Bu ileti(ler)i kalıcı olarak silmek istiyor musunuz?"
|
||||
|
||||
-#: src/client/application/application-main-window.vala:1691
|
||||
+#: src/client/application/application-main-window.vala:1703
|
||||
#, c-format
|
||||
msgid "%s (%d)"
|
||||
msgstr "%s (%d)"
|
||||
@@ -1271,7 +1230,7 @@ msgstr "%s (%d)"
|
||||
#. Document (100.9MB)
|
||||
#. / In the composer, the filename followed by its filesize, i.e. "notes.txt (1.12KB)"
|
||||
#: src/client/components/components-attachment-pane.vala:107
|
||||
-#: src/client/composer/composer-widget.vala:1784
|
||||
+#: src/client/composer/composer-widget.vala:1792
|
||||
#, c-format
|
||||
msgid "%s (%s)"
|
||||
msgstr "%s (%s)"
|
||||
@@ -1292,6 +1251,36 @@ msgstr ""
|
||||
msgid "Don’t _ask me again"
|
||||
msgstr "Yeniden _sorma"
|
||||
|
||||
+#: src/client/components/components-conversation-actions.vala:90
|
||||
+msgid "Mark conversation"
|
||||
+msgid_plural "Mark conversations"
|
||||
+msgstr[0] "Konuşmayı imle"
|
||||
+
|
||||
+#: src/client/components/components-conversation-actions.vala:95
|
||||
+msgid "Add label to conversation"
|
||||
+msgid_plural "Add label to conversations"
|
||||
+msgstr[0] "Konuşmayı etiketle"
|
||||
+
|
||||
+#: src/client/components/components-conversation-actions.vala:100
|
||||
+msgid "Move conversation"
|
||||
+msgid_plural "Move conversations"
|
||||
+msgstr[0] "Konuşmayı taşı"
|
||||
+
|
||||
+#: src/client/components/components-conversation-actions.vala:105
|
||||
+msgid "Archive conversation"
|
||||
+msgid_plural "Archive conversations"
|
||||
+msgstr[0] "Konuşmayı arşivle"
|
||||
+
|
||||
+#: src/client/components/components-conversation-actions.vala:116
|
||||
+msgid "Move conversation to Trash"
|
||||
+msgid_plural "Move conversations to Trash"
|
||||
+msgstr[0] "Konuşmayı Çöpʼe taşı"
|
||||
+
|
||||
+#: src/client/components/components-conversation-actions.vala:126
|
||||
+msgid "Delete conversation"
|
||||
+msgid_plural "Delete conversations"
|
||||
+msgstr[0] "Konuşmayı sil"
|
||||
+
|
||||
#: src/client/components/components-inspector.vala:78
|
||||
msgid "Inspector"
|
||||
msgstr "İnceleyici"
|
||||
@@ -1322,7 +1311,7 @@ msgstr "Farklı Kaydet"
|
||||
|
||||
#: src/client/components/components-inspector.vala:230
|
||||
#: src/client/dialogs/dialogs-problem-details-dialog.vala:224
|
||||
-#: ui/accounts_editor_servers_pane.ui:17
|
||||
+#: ui/accounts_editor_servers_pane.ui:17 ui/composer-headerbar.ui:61
|
||||
msgid "Cancel"
|
||||
msgstr "İptal Et"
|
||||
|
||||
@@ -1338,15 +1327,10 @@ msgstr "Konuşma ön izlemesini _göster"
|
||||
|
||||
#. / Translators: Preferences label
|
||||
#: src/client/components/components-preferences-window.vala:144
|
||||
-msgid "Use _three pane view"
|
||||
-msgstr "_Üç bölmeli görünümü kullan"
|
||||
-
|
||||
-#. / Translators: Preferences label
|
||||
-#: src/client/components/components-preferences-window.vala:154
|
||||
msgid "Use _single key email shortcuts"
|
||||
msgstr "_Tek tuşlu eposta kısayolları kullan"
|
||||
|
||||
-#: src/client/components/components-preferences-window.vala:156
|
||||
+#: src/client/components/components-preferences-window.vala:146
|
||||
msgid ""
|
||||
"Enable keyboard shortcuts for email actions that do not require pressing "
|
||||
"<Ctrl>"
|
||||
@@ -1355,22 +1339,22 @@ msgstr ""
|
||||
"etkinleştir"
|
||||
|
||||
#. / Translators: Preferences label
|
||||
-#: src/client/components/components-preferences-window.vala:167
|
||||
+#: src/client/components/components-preferences-window.vala:157
|
||||
msgid "_Watch for new mail when closed"
|
||||
msgstr "Kapatıldığında yeni postayı _gözetle"
|
||||
|
||||
#. / Translators: Preferences tooltip
|
||||
-#: src/client/components/components-preferences-window.vala:171
|
||||
+#: src/client/components/components-preferences-window.vala:161
|
||||
msgid "Geary will keep running after all windows are closed"
|
||||
msgstr "Geary, tüm pencereler kapatıldıktan sonra çalışmayı sürdürecek"
|
||||
|
||||
#. / Translators: Preferences page title
|
||||
-#: src/client/components/components-preferences-window.vala:189
|
||||
+#: src/client/components/components-preferences-window.vala:178
|
||||
msgid "Preferences"
|
||||
msgstr "Tercihler"
|
||||
|
||||
#. / Translators: Preferences page title
|
||||
-#: src/client/components/components-preferences-window.vala:250
|
||||
+#: src/client/components/components-preferences-window.vala:234
|
||||
msgid "Plugins"
|
||||
msgstr "Eklentiler"
|
||||
|
||||
@@ -1489,36 +1473,6 @@ msgstr "Sunucu adı gerekli"
|
||||
msgid "Could not look up server name"
|
||||
msgstr "Sunucu adı yoklanamıyor"
|
||||
|
||||
-#: src/client/components/main-toolbar.vala:116
|
||||
-msgid "Mark conversation"
|
||||
-msgid_plural "Mark conversations"
|
||||
-msgstr[0] "Konuşmayı imle"
|
||||
-
|
||||
-#: src/client/components/main-toolbar.vala:121
|
||||
-msgid "Add label to conversation"
|
||||
-msgid_plural "Add label to conversations"
|
||||
-msgstr[0] "Konuşmayı etiketle"
|
||||
-
|
||||
-#: src/client/components/main-toolbar.vala:126
|
||||
-msgid "Move conversation"
|
||||
-msgid_plural "Move conversations"
|
||||
-msgstr[0] "Konuşmayı taşı"
|
||||
-
|
||||
-#: src/client/components/main-toolbar.vala:131
|
||||
-msgid "Archive conversation"
|
||||
-msgid_plural "Archive conversations"
|
||||
-msgstr[0] "Konuşmayı arşivle"
|
||||
-
|
||||
-#: src/client/components/main-toolbar.vala:142
|
||||
-msgid "Move conversation to Trash"
|
||||
-msgid_plural "Move conversations to Trash"
|
||||
-msgstr[0] "Konuşmayı Çöpʼe taşı"
|
||||
-
|
||||
-#: src/client/components/main-toolbar.vala:152
|
||||
-msgid "Delete conversation"
|
||||
-msgid_plural "Delete conversations"
|
||||
-msgstr[0] "Konuşmayı sil"
|
||||
-
|
||||
#. / Displayed in the space-limited status bar while a message is in the process of being sent.
|
||||
#: src/client/components/status-bar.vala:26
|
||||
msgid "Sending…"
|
||||
@@ -1650,92 +1604,92 @@ msgstr ""
|
||||
#. Translators: This dialog text is displayed to the
|
||||
#. user when closing a composer where the options are
|
||||
#. Keep, Discard or Cancel.
|
||||
-#: src/client/composer/composer-widget.vala:862
|
||||
+#: src/client/composer/composer-widget.vala:865
|
||||
msgid "Do you want to keep or discard this draft message?"
|
||||
msgstr "Bu iletiyi saklamak mı yoksa gözden çıkarmak mı istersiniz?"
|
||||
|
||||
#. Translators: This dialog text is displayed to the
|
||||
#. user when closing a composer where the options are
|
||||
#. only Discard or Cancel.
|
||||
-#: src/client/composer/composer-widget.vala:888
|
||||
+#: src/client/composer/composer-widget.vala:891
|
||||
msgid "Do you want to discard this draft message?"
|
||||
msgstr "Bu taslak iletiyi gözden çıkarmak istiyor musunuz?"
|
||||
|
||||
-#: src/client/composer/composer-widget.vala:1440
|
||||
+#: src/client/composer/composer-widget.vala:1448
|
||||
msgid "Send message with an empty subject and body?"
|
||||
msgstr "İleti konusu ve gövdesi olmadan gönderilsin mi?"
|
||||
|
||||
-#: src/client/composer/composer-widget.vala:1442
|
||||
+#: src/client/composer/composer-widget.vala:1450
|
||||
msgid "Send message with an empty subject?"
|
||||
msgstr "İleti konusu olmadan gönderilsin mi?"
|
||||
|
||||
-#: src/client/composer/composer-widget.vala:1444
|
||||
+#: src/client/composer/composer-widget.vala:1452
|
||||
msgid "Send message with an empty body?"
|
||||
msgstr "İleti, ileti gövdesi olmadan gönderilsin mi?"
|
||||
|
||||
-#: src/client/composer/composer-widget.vala:1453
|
||||
+#: src/client/composer/composer-widget.vala:1461
|
||||
msgid "Send message without an attachment?"
|
||||
msgstr "İleti eki olmadan gönderilsin mi?"
|
||||
|
||||
-#: src/client/composer/composer-widget.vala:1772
|
||||
+#: src/client/composer/composer-widget.vala:1780
|
||||
#, c-format
|
||||
msgid "“%s” already attached for delivery."
|
||||
msgstr "“%s” gönderim için zaten eklendi."
|
||||
|
||||
-#: src/client/composer/composer-widget.vala:1804
|
||||
-#: src/client/composer/composer-widget.vala:1854
|
||||
+#: src/client/composer/composer-widget.vala:1812
|
||||
+#: src/client/composer/composer-widget.vala:1862
|
||||
#, c-format
|
||||
msgid "“%s” is an empty file."
|
||||
msgstr "“%s” boş bir dosya."
|
||||
|
||||
-#: src/client/composer/composer-widget.vala:1842
|
||||
+#: src/client/composer/composer-widget.vala:1850
|
||||
#, c-format
|
||||
msgid "“%s” could not be found."
|
||||
msgstr "“%s” bulunamadı."
|
||||
|
||||
-#: src/client/composer/composer-widget.vala:1848
|
||||
+#: src/client/composer/composer-widget.vala:1856
|
||||
#, c-format
|
||||
msgid "“%s” is a folder."
|
||||
msgstr "“%s” bir klasör."
|
||||
|
||||
-#: src/client/composer/composer-widget.vala:1867
|
||||
+#: src/client/composer/composer-widget.vala:1875
|
||||
#, c-format
|
||||
msgid "“%s” could not be opened for reading."
|
||||
msgstr "“%s” okuma için açılamadı."
|
||||
|
||||
-#: src/client/composer/composer-widget.vala:1875
|
||||
+#: src/client/composer/composer-widget.vala:1883
|
||||
msgid "Cannot add attachment"
|
||||
msgstr "Eklenti eklenemiyor"
|
||||
|
||||
#. Translators: This is the name of the file chooser filter
|
||||
#. when inserting an image in the composer.
|
||||
-#: src/client/composer/composer-widget.vala:1946
|
||||
+#: src/client/composer/composer-widget.vala:1954
|
||||
msgid "Images"
|
||||
msgstr "Resimler"
|
||||
|
||||
#. Translators: Human-readable version of the RFC 822 To header
|
||||
-#: src/client/composer/composer-widget.vala:2010
|
||||
+#: src/client/composer/composer-widget.vala:2018
|
||||
#: src/client/conversation-viewer/conversation-email.vala:542
|
||||
#: src/client/util/util-email.vala:249 ui/conversation-message.ui:312
|
||||
msgid "To:"
|
||||
msgstr "Kime:"
|
||||
|
||||
#. Translators: Human-readable version of the RFC 822 CC header
|
||||
-#: src/client/composer/composer-widget.vala:2016
|
||||
+#: src/client/composer/composer-widget.vala:2024
|
||||
#: src/client/conversation-viewer/conversation-email.vala:547
|
||||
#: src/client/util/util-email.vala:254 ui/conversation-message.ui:357
|
||||
msgid "Cc:"
|
||||
msgstr "Cc:"
|
||||
|
||||
#. Translators: Human-readable version of the RFC 822 BCC header
|
||||
-#: src/client/composer/composer-widget.vala:2022
|
||||
+#: src/client/composer/composer-widget.vala:2030
|
||||
#: src/client/conversation-viewer/conversation-email.vala:552
|
||||
#: ui/conversation-message.ui:402
|
||||
msgid "Bcc:"
|
||||
msgstr "Bcc:"
|
||||
|
||||
#. Translators: Human-readable version of the RFC 822 Reply-To header
|
||||
-#: src/client/composer/composer-widget.vala:2028
|
||||
+#: src/client/composer/composer-widget.vala:2036
|
||||
msgid "Reply-To: "
|
||||
msgstr "Şuna Yanıtla: "
|
||||
|
||||
@@ -1744,7 +1698,7 @@ msgstr "Şuna Yanıtla: "
|
||||
#. printf argument will be the alternate email address,
|
||||
#. and the second will be the account's primary email
|
||||
#. address.
|
||||
-#: src/client/composer/composer-widget.vala:2146
|
||||
+#: src/client/composer/composer-widget.vala:2154
|
||||
#, c-format
|
||||
msgid "%1$s via %2$s"
|
||||
msgstr "%2$s aracılığıyla %1$s"
|
||||
@@ -1762,49 +1716,49 @@ msgid "Search for more languages"
|
||||
msgstr "Daha çok dil için ara"
|
||||
|
||||
#. / Translators: Context menu item
|
||||
-#: src/client/conversation-list/conversation-list-view.vala:339
|
||||
+#: src/client/conversation-list/conversation-list-view.vala:389
|
||||
msgid "Move conversation to _Trash"
|
||||
msgid_plural "Move conversations to _Trash"
|
||||
msgstr[0] "Konuşmayı _Çöpʼe taşı"
|
||||
|
||||
#. / Translators: Context menu item
|
||||
-#: src/client/conversation-list/conversation-list-view.vala:351
|
||||
+#: src/client/conversation-list/conversation-list-view.vala:401
|
||||
msgid "_Delete conversation"
|
||||
msgid_plural "_Delete conversations"
|
||||
msgstr[0] "Konuşmayı _sil"
|
||||
|
||||
-#: src/client/conversation-list/conversation-list-view.vala:364
|
||||
+#: src/client/conversation-list/conversation-list-view.vala:414
|
||||
#: ui/main-toolbar-menus.ui:5
|
||||
msgid "Mark as _Read"
|
||||
msgstr "_Okundu olarak imle"
|
||||
|
||||
-#: src/client/conversation-list/conversation-list-view.vala:372
|
||||
+#: src/client/conversation-list/conversation-list-view.vala:422
|
||||
#: ui/main-toolbar-menus.ui:9
|
||||
msgid "Mark as _Unread"
|
||||
msgstr "Ok_unmamış olarak imle"
|
||||
|
||||
-#: src/client/conversation-list/conversation-list-view.vala:380
|
||||
+#: src/client/conversation-list/conversation-list-view.vala:430
|
||||
#: ui/main-toolbar-menus.ui:17
|
||||
msgid "U_nstar"
|
||||
msgstr "Y_ıldızı kaldır"
|
||||
|
||||
-#: src/client/conversation-list/conversation-list-view.vala:387
|
||||
+#: src/client/conversation-list/conversation-list-view.vala:437
|
||||
#: ui/main-toolbar-menus.ui:13
|
||||
msgid "_Star"
|
||||
msgstr "_Yıldızla"
|
||||
|
||||
#. Translators: Menu item to reply to a specific message.
|
||||
-#: src/client/conversation-list/conversation-list-view.vala:396
|
||||
+#: src/client/conversation-list/conversation-list-view.vala:446
|
||||
#: ui/conversation-email-menus.ui:9
|
||||
msgid "_Reply"
|
||||
msgstr "_Yanıtla"
|
||||
|
||||
-#: src/client/conversation-list/conversation-list-view.vala:402
|
||||
+#: src/client/conversation-list/conversation-list-view.vala:452
|
||||
msgid "R_eply All"
|
||||
msgstr "Tümüne _Yanıtla"
|
||||
|
||||
#. Translators: Menu item to forward a specific message.
|
||||
-#: src/client/conversation-list/conversation-list-view.vala:408
|
||||
+#: src/client/conversation-list/conversation-list-view.vala:458
|
||||
#: ui/conversation-email-menus.ui:21
|
||||
msgid "_Forward"
|
||||
msgstr "_Yönlendir"
|
||||
@@ -1894,25 +1848,25 @@ msgstr "Gönderenden her zaman göster"
|
||||
|
||||
#. Translators: Title label for placeholder when no
|
||||
#. conversations have been selected.
|
||||
-#: src/client/conversation-viewer/conversation-viewer.vala:83
|
||||
+#: src/client/conversation-viewer/conversation-viewer.vala:87
|
||||
msgid "No conversations selected"
|
||||
msgstr "Konuşma seçilmedi"
|
||||
|
||||
#. Translators: Sub-title label for placeholder when no
|
||||
#. conversations have been selected.
|
||||
-#: src/client/conversation-viewer/conversation-viewer.vala:87
|
||||
+#: src/client/conversation-viewer/conversation-viewer.vala:91
|
||||
msgid "Selecting a conversation from the list will display it here"
|
||||
msgstr "Listeden bir ileti seçtiğinizde burada gösterilecek"
|
||||
|
||||
#. Translators: Title label for placeholder when multiple
|
||||
#. conversations have been selected.
|
||||
-#: src/client/conversation-viewer/conversation-viewer.vala:96
|
||||
+#: src/client/conversation-viewer/conversation-viewer.vala:100
|
||||
msgid "Multiple conversations selected"
|
||||
msgstr "Birden çok konuşma seçildi"
|
||||
|
||||
#. Translators: Sub-title label for placeholder when multiple
|
||||
#. conversations have been selected.
|
||||
-#: src/client/conversation-viewer/conversation-viewer.vala:100
|
||||
+#: src/client/conversation-viewer/conversation-viewer.vala:104
|
||||
msgid "Choosing an action will apply to all selected conversations"
|
||||
msgstr "Bir eylem seçtiğinizde tüm seçili konuşmalara uygulanacaktır"
|
||||
|
||||
@@ -1920,20 +1874,20 @@ msgstr "Bir eylem seçtiğinizde tüm seçili konuşmalara uygulanacaktır"
|
||||
#. conversations have exist in a folder.
|
||||
#. Translators: Title label for placeholder when no
|
||||
#. conversations have been found in a search.
|
||||
-#: src/client/conversation-viewer/conversation-viewer.vala:109
|
||||
-#: src/client/conversation-viewer/conversation-viewer.vala:122
|
||||
+#: src/client/conversation-viewer/conversation-viewer.vala:113
|
||||
+#: src/client/conversation-viewer/conversation-viewer.vala:126
|
||||
msgid "No conversations found"
|
||||
msgstr "Konuşma bulunamadı"
|
||||
|
||||
#. Translators: Sub-title label for placeholder when no
|
||||
#. conversations have exist in a folder.
|
||||
-#: src/client/conversation-viewer/conversation-viewer.vala:113
|
||||
+#: src/client/conversation-viewer/conversation-viewer.vala:117
|
||||
msgid "This folder does not contain any conversations"
|
||||
msgstr "Bu klasör herhangi bir konuşma içermiyor"
|
||||
|
||||
#. Translators: Sub-title label for placeholder when no
|
||||
#. conversations have been found in a search.
|
||||
-#: src/client/conversation-viewer/conversation-viewer.vala:126
|
||||
+#: src/client/conversation-viewer/conversation-viewer.vala:130
|
||||
msgid "Your search returned no results, try refining your search terms"
|
||||
msgstr "Aramanız sonuçsuz kaldı, arama terimlerinizi arıtmayı deneyin"
|
||||
|
||||
@@ -2652,7 +2606,7 @@ msgstr "okunmadı"
|
||||
#. Draft mailbox. Separate names using a vertical bar and
|
||||
#. put the most common localized name to the front for the
|
||||
#. default. English names do not need to be included.
|
||||
-#: src/engine/imap-engine/imap-engine-generic-account.vala:996
|
||||
+#: src/engine/imap-engine/imap-engine-generic-account.vala:998
|
||||
msgid "Drafts | Draft"
|
||||
msgstr "Taslaklar | Taslak"
|
||||
|
||||
@@ -2660,14 +2614,14 @@ msgstr "Taslaklar | Taslak"
|
||||
#. Sent mailbox. Separate names using a vertical bar and
|
||||
#. put the most common localized name to the front for the
|
||||
#. default. English names do not need to be included.
|
||||
-#: src/engine/imap-engine/imap-engine-generic-account.vala:1005
|
||||
+#: src/engine/imap-engine/imap-engine-generic-account.vala:1007
|
||||
msgid "Sent | Sent Mail | Sent Email | Sent E-Mail"
|
||||
msgstr ""
|
||||
"Gönderilmiş | Gönderilmiş Posta | Gönderilmiş Eposta | Gönderilmiş E-Posta"
|
||||
|
||||
#. The localised name(s) of the Sent folder name as used
|
||||
#. by MS Outlook/Exchange.
|
||||
-#: src/engine/imap-engine/imap-engine-generic-account.vala:1010
|
||||
+#: src/engine/imap-engine/imap-engine-generic-account.vala:1012
|
||||
msgctxt "Outlook localised name"
|
||||
msgid "Sent Items"
|
||||
msgstr "Gönderilmiş Ögeler"
|
||||
@@ -2676,7 +2630,7 @@ msgstr "Gönderilmiş Ögeler"
|
||||
#. Junk/Spam mailbox. Separate names using a vertical bar
|
||||
#. and put the most common localized name to the front for
|
||||
#. the default. English names do not need to be included.
|
||||
-#: src/engine/imap-engine/imap-engine-generic-account.vala:1020
|
||||
+#: src/engine/imap-engine/imap-engine-generic-account.vala:1022
|
||||
msgid ""
|
||||
"Junk | Spam | Junk Mail | Junk Email | Junk E-Mail | Bulk Mail | Bulk Email "
|
||||
"| Bulk E-Mail"
|
||||
@@ -2688,13 +2642,13 @@ msgstr ""
|
||||
#. Trash mailbox. Separate names using a vertical bar and
|
||||
#. put the most common localized name to the front for the
|
||||
#. default. English names do not need to be included.
|
||||
-#: src/engine/imap-engine/imap-engine-generic-account.vala:1030
|
||||
+#: src/engine/imap-engine/imap-engine-generic-account.vala:1032
|
||||
msgid "Trash | Rubbish | Rubbish Bin"
|
||||
msgstr "Çöp | Çöp | Çöp Kutusu"
|
||||
|
||||
#. The localised name(s) of the Trash folder name as used
|
||||
#. by MS Outlook/Exchange.
|
||||
-#: src/engine/imap-engine/imap-engine-generic-account.vala:1035
|
||||
+#: src/engine/imap-engine/imap-engine-generic-account.vala:1037
|
||||
msgctxt "Outlook localised name"
|
||||
msgid "Deleted Items"
|
||||
msgstr "Silinen Ögeler"
|
||||
@@ -2703,7 +2657,7 @@ msgstr "Silinen Ögeler"
|
||||
#. Archive mailbox. Separate names using a vertical bar
|
||||
#. and put the most common localized name to the front for
|
||||
#. the default. English names do not need to be included.
|
||||
-#: src/engine/imap-engine/imap-engine-generic-account.vala:1045
|
||||
+#: src/engine/imap-engine/imap-engine-generic-account.vala:1047
|
||||
msgid "Archive | Archives"
|
||||
msgstr "Arşiv | Arşivler"
|
||||
|
||||
@@ -3079,6 +3033,26 @@ msgstr "Seçilen ekleri aç"
|
||||
msgid "Save _All"
|
||||
msgstr "_Tümünü Kaydet"
|
||||
|
||||
+#: ui/components-conversation-actions.ui:85
|
||||
+msgid "Reply"
|
||||
+msgstr "Yanıtla"
|
||||
+
|
||||
+#: ui/components-conversation-actions.ui:108
|
||||
+msgid "Reply All"
|
||||
+msgstr "Tümüne Yanıtla"
|
||||
+
|
||||
+#: ui/components-conversation-actions.ui:131
|
||||
+msgid "Forward"
|
||||
+msgstr "Yönlendir"
|
||||
+
|
||||
+#: ui/components-conversation-actions.ui:163
|
||||
+msgid "_Archive"
|
||||
+msgstr "_Arşivle"
|
||||
+
|
||||
+#: ui/components-conversation-actions.ui:211
|
||||
+msgid "Toggle find bar"
|
||||
+msgstr "Bulma çubuğunu aç"
|
||||
+
|
||||
#: ui/components-inspector-error-view.ui:31
|
||||
msgid ""
|
||||
"If the problem is serious or persists, please save and send these details to "
|
||||
@@ -3616,35 +3590,19 @@ msgctxt "shortcut window"
|
||||
msgid "Insert a link"
|
||||
msgstr "Bağlantı yerleştir"
|
||||
|
||||
-#: ui/main-toolbar.ui:24
|
||||
+#: ui/main-toolbar.ui:85 ui/main-toolbar.ui:179
|
||||
+msgid "Back"
|
||||
+msgstr "Geri"
|
||||
+
|
||||
+#: ui/main-toolbar.ui:104
|
||||
msgctxt "tooltip"
|
||||
msgid "Compose Message"
|
||||
msgstr "İleti Oluştur"
|
||||
|
||||
-#: ui/main-toolbar.ui:62
|
||||
+#: ui/main-toolbar.ui:122
|
||||
msgid "Toggle search bar"
|
||||
msgstr "Arama çubuğunu aç"
|
||||
|
||||
-#: ui/main-toolbar.ui:114
|
||||
-msgid "Reply"
|
||||
-msgstr "Yanıtla"
|
||||
-
|
||||
-#: ui/main-toolbar.ui:137
|
||||
-msgid "Reply All"
|
||||
-msgstr "Tümüne Yanıtla"
|
||||
-
|
||||
-#: ui/main-toolbar.ui:160
|
||||
-msgid "Forward"
|
||||
-msgstr "Yönlendir"
|
||||
-
|
||||
-#: ui/main-toolbar.ui:265
|
||||
-msgid "Toggle find bar"
|
||||
-msgstr "Bulma çubuğunu aç"
|
||||
-
|
||||
-#: ui/main-toolbar.ui:286
|
||||
-msgid "_Archive"
|
||||
-msgstr "_Arşivle"
|
||||
-
|
||||
#: ui/main-toolbar-menus.ui:21
|
||||
msgid "Toggle as _Junk"
|
||||
msgstr "_Gereksiz olarak imle"
|
||||
@@ -3681,6 +3639,41 @@ msgstr "_Kimlik Doğrula"
|
||||
msgid "Geary update in progress…"
|
||||
msgstr "Geary güncellemesi sürüyor…"
|
||||
|
||||
+#~ msgid "Position of folder list pane"
|
||||
+#~ msgstr "Klasör listesi bölmesinin konumu"
|
||||
+
|
||||
+#~ msgid "Position of the folder list Paned grabber."
|
||||
+#~ msgstr "Klasör listesi bölmesi yakalayıcının konumu."
|
||||
+
|
||||
+#~ msgid "Position of folder list pane when horizontal"
|
||||
+#~ msgstr "Klasör listesi bölmesinin yataykenki konumu"
|
||||
+
|
||||
+#~ msgid ""
|
||||
+#~ "Position of the folder list Paned grabber in the horizontal orientation."
|
||||
+#~ msgstr "Yatay yönelimde klasör listesi bölmesi yakalayıcının konumu."
|
||||
+
|
||||
+#~ msgid "Position of folder list pane when vertical"
|
||||
+#~ msgstr "Klasör listesi bölmesinin dikeykenki konumu"
|
||||
+
|
||||
+#~ msgid ""
|
||||
+#~ "Position of the folder list Paned grabber in the vertical orientation."
|
||||
+#~ msgstr "Dikey yönelimde klasör listesi bölmesi yakalayıcının konumu."
|
||||
+
|
||||
+#~ msgid "Orientation of the folder list pane"
|
||||
+#~ msgstr "Klasör listesi bölmesinin konumlandırması"
|
||||
+
|
||||
+#~ msgid "True if the folder list Paned is in the horizontal orientation."
|
||||
+#~ msgstr "Eğer klasör listesi bölmesi yatay yönelimdeyse doğru."
|
||||
+
|
||||
+#~ msgid "Position of message list pane"
|
||||
+#~ msgstr "İleti listesi bölmesinin konumu"
|
||||
+
|
||||
+#~ msgid "Position of the message list Paned grabber."
|
||||
+#~ msgstr "İleti listesi bölmesi yakalayıcının konumu."
|
||||
+
|
||||
+#~ msgid "Use _three pane view"
|
||||
+#~ msgstr "_Üç bölmeli görünümü kullan"
|
||||
+
|
||||
#~ msgid "Desktop Notifications"
|
||||
#~ msgstr "Masaüstü Bildirimleri"
|
||||
|
||||
--
|
||||
2.29.2
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user