Merge remote-tracking branch 'upstream/master' into master-windows-changes

This commit is contained in:
LAGonauta 2023-01-30 08:53:45 -03:00
commit 3d61f175a6
172 changed files with 19166 additions and 17433 deletions

View file

@ -7,7 +7,7 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- run: sudo apt-get update - run: sudo apt-get update
- run: sudo apt-get remove libunwind-14-dev - run: sudo apt-get remove libunwind-14-dev
- run: sudo apt-get install -y build-essential gettext cmake valac libgee-0.8-dev libsqlite3-dev libgtk-4-dev libnotify-dev libgpgme-dev libsoup2.4-dev libgcrypt20-dev libqrencode-dev libgspell-1-dev libnice-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libsrtp2-dev libwebrtc-audio-processing-dev - run: sudo apt-get install -y build-essential gettext cmake valac libgee-0.8-dev libsqlite3-dev libgtk-4-dev libnotify-dev libgpgme-dev libsoup2.4-dev libgcrypt20-dev libqrencode-dev libgspell-1-dev libnice-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libsrtp2-dev libwebrtc-audio-processing-dev libadwaita-1-dev
- run: ./configure --with-tests --with-libsignal-in-tree - run: ./configure --with-tests --with-libsignal-in-tree
- run: make - run: make
- run: build/xmpp-vala-test - run: build/xmpp-vala-test

11
cmake/FindAdwaita.cmake Normal file
View file

@ -0,0 +1,11 @@
include(PkgConfigWithFallback)
find_pkg_config_with_fallback(Adwaita
PKG_CONFIG_NAME libadwaita-1
LIB_NAMES libadwaita-1
INCLUDE_NAMES adwaita.h
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Adwaita
REQUIRED_VARS Adwaita_LIBRARY
VERSION_VAR Adwaita_VERSION)

View file

@ -42,9 +42,10 @@ public class Conversation : Object {
public enum Setting { DEFAULT, ON, OFF } public enum Setting { DEFAULT, ON, OFF }
public Setting send_typing { get; set; default = Setting.DEFAULT; } public Setting send_typing { get; set; default = Setting.DEFAULT; }
public Setting send_marker { get; set; default = Setting.DEFAULT; } public Setting send_marker { get; set; default = Setting.DEFAULT; }
public int pinned { get; set; default = 0; }
private Database? db; private Database? db;
public Conversation(Jid jid, Account account, Type type) { public Conversation(Jid jid, Account account, Type type) {
@ -74,6 +75,7 @@ public class Conversation : Object {
notify_setting = (NotifySetting) row[db.conversation.notification]; notify_setting = (NotifySetting) row[db.conversation.notification];
send_typing = (Setting) row[db.conversation.send_typing]; send_typing = (Setting) row[db.conversation.send_typing];
send_marker = (Setting) row[db.conversation.send_marker]; send_marker = (Setting) row[db.conversation.send_marker];
pinned = row[db.conversation.pinned];
notify.connect(on_update); notify.connect(on_update);
} }
@ -91,7 +93,8 @@ public class Conversation : Object {
.value(db.conversation.active_last_changed, (long) active_last_changed.to_unix()) .value(db.conversation.active_last_changed, (long) active_last_changed.to_unix())
.value(db.conversation.notification, notify_setting) .value(db.conversation.notification, notify_setting)
.value(db.conversation.send_typing, send_typing) .value(db.conversation.send_typing, send_typing)
.value(db.conversation.send_marker, send_marker); .value(db.conversation.send_marker, send_marker)
.value(db.conversation.pinned, pinned);
if (read_up_to != null) { if (read_up_to != null) {
insert.value(db.conversation.read_up_to, read_up_to.id); insert.value(db.conversation.read_up_to, read_up_to.id);
} }
@ -197,6 +200,8 @@ public class Conversation : Object {
update.set(db.conversation.send_typing, send_typing); break; update.set(db.conversation.send_typing, send_typing); break;
case "send-marker": case "send-marker":
update.set(db.conversation.send_marker, send_marker); break; update.set(db.conversation.send_marker, send_marker); break;
case "pinned":
update.set(db.conversation.pinned, pinned); break;
} }
update.perform(); update.perform();
} }

View file

@ -154,6 +154,7 @@ public interface ConversationItemWidgetInterface: Object {
public delegate void MessageActionEvoked(Object button, Plugins.MetaConversationItem evoked_on, Object widget); public delegate void MessageActionEvoked(Object button, Plugins.MetaConversationItem evoked_on, Object widget);
public class MessageAction : Object { public class MessageAction : Object {
public string icon_name; public string icon_name;
public string? tooltip;
public Object? popover; public Object? popover;
public MessageActionEvoked? callback; public MessageActionEvoked? callback;
} }

View file

@ -44,11 +44,8 @@ public class ContentItemStore : StreamInteractionModule, Object {
Gee.TreeSet<ContentItem> items = new Gee.TreeSet<ContentItem>(ContentItem.compare_func); Gee.TreeSet<ContentItem> items = new Gee.TreeSet<ContentItem>(ContentItem.compare_func);
foreach (var row in select) { foreach (var row in select) {
int id = row[db.content_item.id]; ContentItem content_item = get_item_from_row(row, conversation);
int content_type = row[db.content_item.content_type]; items.add(content_item);
int foreign_id = row[db.content_item.foreign_id];
DateTime time = new DateTime.from_unix_utc(row[db.content_item.time]);
items.add(get_item(conversation, id, content_type, foreign_id, time));
} }
Gee.List<ContentItem> ret = new ArrayList<ContentItem>(); Gee.List<ContentItem> ret = new ArrayList<ContentItem>();
@ -58,6 +55,14 @@ public class ContentItemStore : StreamInteractionModule, Object {
return ret; return ret;
} }
private ContentItem get_item_from_row(Row row, Conversation conversation) throws Error {
int id = row[db.content_item.id];
int content_type = row[db.content_item.content_type];
int foreign_id = row[db.content_item.foreign_id];
DateTime time = new DateTime.from_unix_utc(row[db.content_item.time]);
return get_item(conversation, id, content_type, foreign_id, time);
}
private ContentItem get_item(Conversation conversation, int id, int content_type, int foreign_id, DateTime time) throws Error { private ContentItem get_item(Conversation conversation, int id, int content_type, int foreign_id, DateTime time) throws Error {
switch (content_type) { switch (content_type) {
case 1: case 1:
@ -112,6 +117,91 @@ public class ContentItemStore : StreamInteractionModule, Object {
return item.size > 0 ? item[0] : null; return item.size > 0 ? item[0] : null;
} }
public string? get_message_id_for_content_item(Conversation conversation, ContentItem content_item) {
Message? message = get_message_for_content_item(conversation, content_item);
if (message == null) return null;
if (message.edit_to != null) return message.edit_to;
if (conversation.type_ == Conversation.Type.CHAT) {
return message.stanza_id;
} else {
return message.server_id;
}
}
public Jid? get_message_sender_for_content_item(Conversation conversation, ContentItem content_item) {
Message? message = get_message_for_content_item(conversation, content_item);
if (message == null) return null;
// No need to look at edit_to, because it's the same sender JID.
return message.from;
}
public Message? get_message_for_content_item(Conversation conversation, ContentItem content_item) {
FileItem? file_item = content_item as FileItem;
if (file_item != null) {
if (file_item.file_transfer.provider != 0 || file_item.file_transfer.info == null) return null;
int message_db_id = int.parse(file_item.file_transfer.info);
return stream_interactor.get_module(MessageStorage.IDENTITY).get_message_by_id(message_db_id, conversation);
}
MessageItem? message_item = content_item as MessageItem;
if (message_item != null) {
return message_item.message;
}
return null;
}
public ContentItem? get_content_item_for_message_id(Conversation conversation, string message_id) {
Row? row = get_content_item_row_for_message_id(conversation, message_id);
if (row != null) {
return get_item_from_row(row, conversation);
}
return null;
}
public int get_content_item_id_for_message_id(Conversation conversation, string message_id) {
Row? row = get_content_item_row_for_message_id(conversation, message_id);
if (row != null) {
return row[db.content_item.id];
}
return -1;
}
private Row? get_content_item_row_for_message_id(Conversation conversation, string message_id) {
var content_item_row = db.content_item.select();
Message? message = null;
if (conversation.type_ == Conversation.Type.CHAT) {
message = stream_interactor.get_module(MessageStorage.IDENTITY).get_message_by_stanza_id(message_id, conversation);
} else {
message = stream_interactor.get_module(MessageStorage.IDENTITY).get_message_by_server_id(message_id, conversation);
}
if (message == null) return null;
RowOption file_transfer_row = db.file_transfer.select()
.with(db.file_transfer.account_id, "=", conversation.account.id)
.with(db.file_transfer.counterpart_id, "=", db.get_jid_id(conversation.counterpart))
.with(db.file_transfer.info, "=", message.id.to_string())
.order_by(db.file_transfer.time, "DESC")
.single().row();
if (file_transfer_row.is_present()) {
content_item_row.with(db.content_item.foreign_id, "=", file_transfer_row[db.file_transfer.id])
.with(db.content_item.content_type, "=", 2);
} else {
content_item_row.with(db.content_item.foreign_id, "=", message.id)
.with(db.content_item.content_type, "=", 1);
}
RowOption content_item_row_option = content_item_row.single().row();
if (content_item_row_option.is_present()) {
return content_item_row_option.inner;
}
return null;
}
public ContentItem? get_latest(Conversation conversation) { public ContentItem? get_latest(Conversation conversation) {
Gee.List<ContentItem> items = get_n_latest(conversation, 1); Gee.List<ContentItem> items = get_n_latest(conversation, 1);
if (items.size > 0) { if (items.size > 0) {

View file

@ -7,7 +7,7 @@ using Dino.Entities;
namespace Dino { namespace Dino {
public class Database : Qlite.Database { public class Database : Qlite.Database {
private const int VERSION = 24; private const int VERSION = 25;
public class AccountTable : Table { public class AccountTable : Table {
public Column<int> id = new Column.Integer("id") { primary_key = true, auto_increment = true }; public Column<int> id = new Column.Integer("id") { primary_key = true, auto_increment = true };
@ -244,10 +244,11 @@ public class Database : Qlite.Database {
public Column<int> notification = new Column.Integer("notification") { min_version=3 }; public Column<int> notification = new Column.Integer("notification") { min_version=3 };
public Column<int> send_typing = new Column.Integer("send_typing") { min_version=3 }; public Column<int> send_typing = new Column.Integer("send_typing") { min_version=3 };
public Column<int> send_marker = new Column.Integer("send_marker") { min_version=3 }; public Column<int> send_marker = new Column.Integer("send_marker") { min_version=3 };
public Column<int> pinned = new Column.Integer("pinned") { default="0", min_version=25 };
internal ConversationTable(Database db) { internal ConversationTable(Database db) {
base(db, "conversation"); base(db, "conversation");
init({id, account_id, jid_id, resource, active, active_last_changed, last_active, type_, encryption, read_up_to, read_up_to_item, notification, send_typing, send_marker}); init({id, account_id, jid_id, resource, active, active_last_changed, last_active, type_, encryption, read_up_to, read_up_to_item, notification, send_typing, send_marker, pinned});
} }
} }

View file

@ -204,19 +204,18 @@ public class Dino.HistorySync {
var query_params = new Xmpp.MessageArchiveManagement.V2.MamQueryParams.query_latest(mam_server, latest_message_time, latest_message_id); var query_params = new Xmpp.MessageArchiveManagement.V2.MamQueryParams.query_latest(mam_server, latest_message_time, latest_message_id);
PageRequestResult page_result = yield get_mam_page(account, query_params, null); PageRequestResult page_result = yield get_mam_page(account, query_params, null);
debug("[%s | %s] Latest page result: %s", account.bare_jid.to_string(), mam_server.to_string(), page_result.page_result.to_string());
if (page_result.page_result == PageResult.Duplicate) {
// No new messages
return null;
}
if (page_result.page_result == PageResult.Error) { if (page_result.page_result == PageResult.Error) {
debug("[%s | %s] Failed fetching latest page %s", mam_server.to_string(), mam_server.to_string(), page_result.page_result.to_string());
return null; return null;
} }
// If we get PageResult.Duplicate, we still want to update the db row to the latest message.
// Catchup finished within first page. Update latest db entry. // Catchup finished within first page. Update latest db entry.
if (page_result.page_result in new PageResult[] { PageResult.TargetReached, PageResult.NoMoreMessages } && latest_row_id != -1) { if (latest_row_id != -1 &&
page_result.page_result in new PageResult[] { PageResult.TargetReached, PageResult.NoMoreMessages, PageResult.Duplicate }) {
if (page_result.stanzas == null || page_result.stanzas.is_empty) return null; if (page_result.stanzas == null || page_result.stanzas.is_empty) return null;
string latest_mam_id = page_result.query_result.last; string latest_mam_id = page_result.query_result.last;
@ -258,7 +257,7 @@ public class Dino.HistorySync {
.value(db.mam_catchup.server_jid, mam_server.to_string()) .value(db.mam_catchup.server_jid, mam_server.to_string())
.value(db.mam_catchup.from_id, from_id) .value(db.mam_catchup.from_id, from_id)
.value(db.mam_catchup.from_time, from_time) .value(db.mam_catchup.from_time, from_time)
.value(db.mam_catchup.from_end, false) .value(db.mam_catchup.from_end, page_result.page_result == PageResult.NoMoreMessages)
.value(db.mam_catchup.to_id, to_id) .value(db.mam_catchup.to_id, to_id)
.value(db.mam_catchup.to_time, to_time) .value(db.mam_catchup.to_time, to_time)
.perform(); .perform();

View file

@ -425,24 +425,8 @@ public class MessageProcessor : StreamInteractionModule, Object {
new_message.type_ = MessageStanza.TYPE_CHAT; new_message.type_ = MessageStanza.TYPE_CHAT;
} }
if (message.quoted_item_id > 0) { string? fallback = get_fallback_body_set_infos(message, new_message, conversation);
ContentItem? content_item = stream_interactor.get_module(ContentItemStore.IDENTITY).get_item_by_id(conversation, message.quoted_item_id); new_message.body = fallback == null ? message.body : fallback + message.body;
if (content_item != null && content_item.type_ == MessageItem.TYPE) {
Message? quoted_message = stream_interactor.get_module(MessageStorage.IDENTITY).get_message_by_id(((MessageItem) content_item).message.id, conversation);
if (quoted_message != null) {
Xep.Replies.set_reply_to(new_message, new Xep.Replies.ReplyTo(quoted_message.from, quoted_message.stanza_id));
string body_with_fallback = "> " + Dino.message_body_without_reply_fallback(quoted_message);
body_with_fallback = body_with_fallback.replace("\n", "\n> ");
body_with_fallback += "\n";
long fallback_length = body_with_fallback.length;
body_with_fallback += message.body;
new_message.body = body_with_fallback;
var fallback_location = new Xep.FallbackIndication.FallbackLocation(0, (int)fallback_length);
Xep.FallbackIndication.set_fallback(new_message, new Xep.FallbackIndication.Fallback(Xep.Replies.NS_URI, new Xep.FallbackIndication.FallbackLocation[] { fallback_location }));
}
}
}
build_message_stanza(message, new_message, conversation); build_message_stanza(message, new_message, conversation);
pre_message_send(message, new_message, conversation); pre_message_send(message, new_message, conversation);
@ -487,6 +471,37 @@ public class MessageProcessor : StreamInteractionModule, Object {
} }
}); });
} }
public string? get_fallback_body_set_infos(Entities.Message message, MessageStanza new_stanza, Conversation conversation) {
if (message.quoted_item_id == 0) return null;
ContentItem? content_item = stream_interactor.get_module(ContentItemStore.IDENTITY).get_item_by_id(conversation, message.quoted_item_id);
if (content_item == null) return null;
Jid? quoted_sender = stream_interactor.get_module(ContentItemStore.IDENTITY).get_message_sender_for_content_item(conversation, content_item);
string? quoted_stanza_id = stream_interactor.get_module(ContentItemStore.IDENTITY).get_message_id_for_content_item(conversation, content_item);
if (quoted_sender != null && quoted_stanza_id != null) {
Xep.Replies.set_reply_to(new_stanza, new Xep.Replies.ReplyTo(quoted_sender, quoted_stanza_id));
}
string fallback = "> ";
if (content_item.type_ == MessageItem.TYPE) {
Message? quoted_message = ((MessageItem) content_item).message;
fallback += Dino.message_body_without_reply_fallback(quoted_message);
fallback = fallback.replace("\n", "\n> ");
} else if (content_item.type_ == FileItem.TYPE) {
FileTransfer? quoted_file = ((FileItem) content_item).file_transfer;
fallback += quoted_file.file_name;
}
fallback += "\n";
long fallback_length = fallback.length;
var fallback_location = new Xep.FallbackIndication.FallbackLocation(0, (int)fallback_length);
Xep.FallbackIndication.set_fallback(new_stanza, new Xep.FallbackIndication.Fallback(Xep.Replies.NS_URI, new Xep.FallbackIndication.FallbackLocation[] { fallback_location }));
return fallback;
}
} }
public abstract class MessageListener : Xmpp.OrderedListener { public abstract class MessageListener : Xmpp.OrderedListener {

View file

@ -116,9 +116,7 @@ public class MessageStorage : StreamInteractionModule, Object {
.outer_join_with(db.message_correction, db.message_correction.message_id, db.message.id) .outer_join_with(db.message_correction, db.message_correction.message_id, db.message.id)
.outer_join_with(db.reply, db.reply.message_id, db.message.id); .outer_join_with(db.reply, db.reply.message_id, db.message.id);
if (conversation.counterpart.resourcepart == null) { if (conversation.counterpart.resourcepart != null) {
query.with_null(db.message.counterpart_resource);
} else {
query.with(db.message.counterpart_resource, "=", conversation.counterpart.resourcepart); query.with(db.message.counterpart_resource, "=", conversation.counterpart.resourcepart);
} }

View file

@ -10,7 +10,6 @@ public class Dino.Reactions : StreamInteractionModule, Object {
public string id { get { return IDENTITY.id; } } public string id { get { return IDENTITY.id; } }
public signal void reaction_added(Account account, int content_item_id, Jid jid, string reaction); public signal void reaction_added(Account account, int content_item_id, Jid jid, string reaction);
// [Signal(detailed=true)]
public signal void reaction_removed(Account account, int content_item_id, Jid jid, string reaction); public signal void reaction_removed(Account account, int content_item_id, Jid jid, string reaction);
private StreamInteractor stream_interactor; private StreamInteractor stream_interactor;
@ -27,7 +26,7 @@ public class Dino.Reactions : StreamInteractionModule, Object {
this.db = database; this.db = database;
stream_interactor.account_added.connect(on_account_added); stream_interactor.account_added.connect(on_account_added);
stream_interactor.get_module(MessageProcessor.IDENTITY).message_sent_or_received.connect(on_new_message); stream_interactor.get_module(ContentItemStore.IDENTITY).new_item.connect(on_new_item);
} }
public void add_reaction(Conversation conversation, ContentItem content_item, string reaction) { public void add_reaction(Conversation conversation, ContentItem content_item, string reaction) {
@ -35,15 +34,19 @@ public class Dino.Reactions : StreamInteractionModule, Object {
if (!reactions.contains(reaction)) { if (!reactions.contains(reaction)) {
reactions.add(reaction); reactions.add(reaction);
} }
try {
send_reactions(conversation, content_item, reactions); send_reactions(conversation, content_item, reactions);
reaction_added(conversation.account, content_item.id, conversation.account.bare_jid, reaction); reaction_added(conversation.account, content_item.id, conversation.account.bare_jid, reaction);
} catch (SendError e) {}
} }
public void remove_reaction(Conversation conversation, ContentItem content_item, string reaction) { public void remove_reaction(Conversation conversation, ContentItem content_item, string reaction) {
Gee.List<string> reactions = get_own_reactions(conversation, content_item); Gee.List<string> reactions = get_own_reactions(conversation, content_item);
reactions.remove(reaction); reactions.remove(reaction);
try {
send_reactions(conversation, content_item, reactions); send_reactions(conversation, content_item, reactions);
reaction_removed(conversation.account, content_item.id, conversation.account.bare_jid, reaction); reaction_removed(conversation.account, content_item.id, conversation.account.bare_jid, reaction);
} catch (SendError e) {}
} }
public Gee.List<ReactionUsers> get_item_reactions(Conversation conversation, ContentItem content_item) { public Gee.List<ReactionUsers> get_item_reactions(Conversation conversation, ContentItem content_item) {
@ -80,35 +83,28 @@ public class Dino.Reactions : StreamInteractionModule, Object {
return false; return false;
} }
private void send_reactions(Conversation conversation, ContentItem content_item, Gee.List<string> reactions) { private void send_reactions(Conversation conversation, ContentItem content_item, Gee.List<string> reactions) throws SendError {
Message? message = null; string? message_id = stream_interactor.get_module(ContentItemStore.IDENTITY).get_message_id_for_content_item(conversation, content_item);
if (message_id == null) throw new SendError.Misc("No message for content_item");
FileItem? file_item = content_item as FileItem; XmppStream? stream = stream_interactor.get_stream(conversation.account);
if (file_item != null) { if (stream == null) throw new SendError.NoStream("");
int message_id = int.parse(file_item.file_transfer.info);
message = stream_interactor.get_module(MessageStorage.IDENTITY).get_message_by_id(message_id, conversation);
}
MessageItem? message_item = content_item as MessageItem;
if (message_item != null) {
message = message_item.message;
}
if (message == null) { var reactions_module = stream.get_module(Xmpp.Xep.Reactions.Module.IDENTITY);
return;
}
XmppStream stream = stream_interactor.get_stream(conversation.account);
if (conversation.type_ == Conversation.Type.GROUPCHAT || conversation.type_ == Conversation.Type.GROUPCHAT_PM) {
if (conversation.type_ == Conversation.Type.GROUPCHAT) { if (conversation.type_ == Conversation.Type.GROUPCHAT) {
stream.get_module(Xmpp.Xep.Reactions.Module.IDENTITY).send_reaction(stream, conversation.counterpart, "groupchat", message.server_id ?? message.stanza_id, reactions); reactions_module.send_reaction.begin(stream, conversation.counterpart, "groupchat", message_id, reactions);
} else if (conversation.type_ == Conversation.Type.GROUPCHAT_PM) {
stream.get_module(Xmpp.Xep.Reactions.Module.IDENTITY).send_reaction(stream, conversation.counterpart, "chat", message.server_id ?? message.stanza_id, reactions);
}
// We save the reaction when it gets reflected back to us // We save the reaction when it gets reflected back to us
} else if (conversation.type_ == Conversation.Type.GROUPCHAT_PM) {
reactions_module.send_reaction(stream, conversation.counterpart, "chat", message_id, reactions);
} else if (conversation.type_ == Conversation.Type.CHAT) { } else if (conversation.type_ == Conversation.Type.CHAT) {
stream.get_module(Xmpp.Xep.Reactions.Module.IDENTITY).send_reaction(stream, conversation.counterpart, "chat", message.stanza_id, reactions);
int64 now_millis = GLib.get_real_time () / 1000; int64 now_millis = GLib.get_real_time () / 1000;
reactions_module.send_reaction.begin(stream, conversation.counterpart, "chat", message_id, reactions, (_, res) => {
try {
reactions_module.send_reaction.end(res);
save_chat_reactions(conversation.account, conversation.account.bare_jid, content_item.id, now_millis, reactions); save_chat_reactions(conversation.account, conversation.account.bare_jid, content_item.id, now_millis, reactions);
} catch (SendError e) {}
});
} }
} }
@ -251,11 +247,11 @@ public class Dino.Reactions : StreamInteractionModule, Object {
Message reaction_message = yield stream_interactor.get_module(MessageProcessor.IDENTITY).parse_message_stanza(account, stanza); Message reaction_message = yield stream_interactor.get_module(MessageProcessor.IDENTITY).parse_message_stanza(account, stanza);
Conversation conversation = stream_interactor.get_module(ConversationManager.IDENTITY).get_conversation_for_message(reaction_message); Conversation conversation = stream_interactor.get_module(ConversationManager.IDENTITY).get_conversation_for_message(reaction_message);
Message? message = get_message_for_reaction(conversation, message_id); int content_item_id = stream_interactor.get_module(ContentItemStore.IDENTITY).get_content_item_id_for_message_id(conversation, message_id);
var reaction_info = new ReactionInfo() { account=account, from_jid=from_jid, reactions=reactions, stanza=stanza, received_time=new DateTime.now() }; var reaction_info = new ReactionInfo() { conversation=conversation, from_jid=from_jid, reactions=reactions, stanza=stanza, received_time=new DateTime.now() };
if (message != null) { if (content_item_id != -1) {
process_reaction_for_message(message.id, reaction_info); process_reaction_for_message(content_item_id, reaction_info);
return; return;
} }
@ -267,45 +263,33 @@ public class Dino.Reactions : StreamInteractionModule, Object {
reaction_infos[message_id].add(reaction_info); reaction_infos[message_id].add(reaction_info);
} }
private void on_new_message(Message message, Conversation conversation) { /*
Gee.List<ReactionInfo>? reaction_info_list = null; * When we get a new ContentItem, check if we have any reactions cached that apply to it.
if (conversation.type_ == Conversation.Type.CHAT) { * If so, process the reactions, map and store them.
reaction_info_list = reaction_infos[message.stanza_id]; */
} else { private void on_new_item(ContentItem item, Conversation conversation) {
reaction_info_list = reaction_infos[message.server_id]; string? stanza_id = stream_interactor.get_module(ContentItemStore.IDENTITY).get_message_id_for_content_item(conversation, item);
} if (stanza_id == null) return;
Gee.List<ReactionInfo>? reaction_info_list = reaction_infos[stanza_id];
if (reaction_info_list == null) return; if (reaction_info_list == null) return;
Message? message = stream_interactor.get_module(ContentItemStore.IDENTITY).get_message_for_content_item(conversation, item);
if (message == null) return;
// Check if the (or potentially which) reaction fits the message // Check if the (or potentially which) reaction fits the message
ReactionInfo? reaction_info = null; var applicable_reactions = new ArrayList<ReactionInfo>();
foreach (ReactionInfo info in reaction_info_list) { applicable_reactions.add_all_iterator(reaction_info_list.filter(info => info.conversation.equals(conversation)));
if (!info.account.equals(conversation.account)) return;
switch (info.stanza.type_) {
case MessageStanza.TYPE_CHAT:
Jid counterpart = message.from.equals_bare(conversation.account.bare_jid) ? info.stanza.from: info.stanza.to;
if (message.type_ != Message.Type.CHAT || !counterpart.equals_bare(conversation.counterpart)) continue;
break;
case MessageStanza.TYPE_GROUPCHAT:
if (message.type_ != Message.Type.GROUPCHAT || !message.from.equals_bare(conversation.counterpart)) continue;
break;
default:
break;
}
reaction_info = info; foreach (ReactionInfo applicable_reaction in applicable_reactions) {
} reaction_info_list.remove(applicable_reaction);
if (reaction_info == null) return;
reaction_info_list.remove(reaction_info);
if (reaction_info_list.is_empty) { if (reaction_info_list.is_empty) {
if (conversation.type_ == Conversation.Type.GROUPCHAT) { reaction_infos.unset(stanza_id);
reaction_infos.unset(message.server_id);
} else {
reaction_infos.unset(message.stanza_id);
}
} }
debug("Got message for reaction %s", message.stanza_id); debug("Got ContentItem for reaction %s", stanza_id);
process_reaction_for_message(message.id, reaction_info); process_reaction_for_message(item.id, applicable_reaction);
}
} }
private Message? get_message_for_reaction(Conversation conversation, string message_id) { private Message? get_message_for_reaction(Conversation conversation, string message_id) {
@ -317,30 +301,12 @@ public class Dino.Reactions : StreamInteractionModule, Object {
} }
} }
private void process_reaction_for_message(int message_db_id, ReactionInfo reaction_info) { private void process_reaction_for_message(int content_item_id, ReactionInfo reaction_info) {
Account account = reaction_info.account; Account account = reaction_info.conversation.account;
MessageStanza stanza = reaction_info.stanza; MessageStanza stanza = reaction_info.stanza;
Jid from_jid = reaction_info.from_jid; Jid from_jid = reaction_info.from_jid;
Gee.List<string> reactions = reaction_info.reactions; Gee.List<string> reactions = reaction_info.reactions;
RowOption file_transfer_row = db.file_transfer.select()
.with(db.file_transfer.account_id, "=", account.id)
.with(db.file_transfer.info, "=", message_db_id.to_string())
.single().row(); // TODO better
var content_item_row = db.content_item.select();
if (file_transfer_row.is_present()) {
content_item_row.with(db.content_item.foreign_id, "=", file_transfer_row[db.file_transfer.id])
.with(db.content_item.content_type, "=", 2);
} else {
content_item_row.with(db.content_item.foreign_id, "=", message_db_id)
.with(db.content_item.content_type, "=", 1);
}
var content_item_row_opt = content_item_row.single().row();
if (!content_item_row_opt.is_present()) return;
int content_item_id = content_item_row_opt[db.content_item.id];
// Get reaction time // Get reaction time
DateTime? reaction_time = null; DateTime? reaction_time = null;
DelayedDelivery.MessageFlag? delayed_message_flag = DelayedDelivery.MessageFlag.get_flag(stanza); DelayedDelivery.MessageFlag? delayed_message_flag = DelayedDelivery.MessageFlag.get_flag(stanza);
@ -485,7 +451,7 @@ public class Dino.ReactionUsers {
} }
public class Dino.ReactionInfo { public class Dino.ReactionInfo {
public Account account { get; set; } public Conversation conversation { get; set; }
public Jid from_jid { get; set; } public Jid from_jid { get; set; }
public Gee.List<string> reactions { get; set; } public Gee.List<string> reactions { get; set; }
public MessageStanza stanza { get; set; } public MessageStanza stanza { get; set; }

View file

@ -77,22 +77,7 @@ public class Dino.Replies : StreamInteractionModule, Object {
Xep.Replies.ReplyTo? reply_to = Xep.Replies.get_reply_to(stanza); Xep.Replies.ReplyTo? reply_to = Xep.Replies.get_reply_to(stanza);
if (reply_to == null) return; if (reply_to == null) return;
Message? quoted_message = null; ContentItem? quoted_content_item = stream_interactor.get_module(ContentItemStore.IDENTITY).get_content_item_for_message_id(conversation, reply_to.to_message_id);
if (conversation.type_ == Conversation.Type.GROUPCHAT) {
quoted_message = stream_interactor.get_module(MessageStorage.IDENTITY).get_message_by_server_id(reply_to.to_message_id, conversation);
} else {
quoted_message = stream_interactor.get_module(MessageStorage.IDENTITY).get_message_by_stanza_id(reply_to.to_message_id, conversation);
}
if (quoted_message == null) {
db.reply.upsert()
.value(db.reply.message_id, message.id, true)
.value(db.reply.quoted_message_stanza_id, reply_to.to_message_id)
.value(db.reply.quoted_message_from, reply_to.to_jid.to_string())
.perform();
return;
}
ContentItem? quoted_content_item = stream_interactor.get_module(ContentItemStore.IDENTITY).get_item_by_foreign(conversation, 1, quoted_message.id);
if (quoted_content_item == null) return; if (quoted_content_item == null) return;
set_message_is_reply_to(message, quoted_content_item); set_message_is_reply_to(message, quoted_content_item);

View file

@ -1,4 +1,5 @@
using Dino.Entities; using Dino.Entities;
using Qlite;
namespace Dino { namespace Dino {

View file

@ -11,6 +11,7 @@ find_packages(MAIN_PACKAGES REQUIRED
GObject GObject
GTK4 GTK4
ICU ICU
Adwaita
) )
set(RESOURCE_LIST set(RESOURCE_LIST
@ -89,7 +90,8 @@ set(RESOURCE_LIST
unified_main_content.ui unified_main_content.ui
unified_window_placeholder.ui unified_window_placeholder.ui
theme.css style.css
style-dark.css
) )
compile_gresources( compile_gresources(
@ -110,6 +112,12 @@ set(MAIN_DEFINITIONS)
if(GTK4_VERSION VERSION_GREATER_EQUAL "4.6") if(GTK4_VERSION VERSION_GREATER_EQUAL "4.6")
set(MAIN_DEFINITIONS ${MAIN_DEFINITIONS} GTK_4_6) set(MAIN_DEFINITIONS ${MAIN_DEFINITIONS} GTK_4_6)
endif() endif()
if(GTK4_VERSION VERSION_GREATER_EQUAL "4.8")
set(MAIN_DEFINITIONS ${MAIN_DEFINITIONS} GTK_4_8)
endif()
if(Adwaita_VERSION VERSION_GREATER_EQUAL "1.2")
set(MAIN_DEFINITIONS ${MAIN_DEFINITIONS} Adw_1_2)
endif()
vala_precompile(MAIN_VALA_C vala_precompile(MAIN_VALA_C
SOURCES SOURCES
@ -199,7 +207,9 @@ SOURCES
src/ui/util/label_hybrid.vala src/ui/util/label_hybrid.vala
src/ui/util/sizing_bin.vala src/ui/util/sizing_bin.vala
src/ui/util/size_request_box.vala src/ui/util/size_request_box.vala
src/ui/util/scaling_image.vala
src/ui/widgets/fixed_ratio_picture.vala
src/ui/widgets/natural_size_increase.vala
CUSTOM_VAPIS CUSTOM_VAPIS
${CMAKE_BINARY_DIR}/exports/xmpp-vala.vapi ${CMAKE_BINARY_DIR}/exports/xmpp-vala.vapi
${CMAKE_BINARY_DIR}/exports/qlite.vapi ${CMAKE_BINARY_DIR}/exports/qlite.vapi

View file

@ -31,7 +31,9 @@
<property name="halign">end</property> <property name="halign">end</property>
<property name="valign">start</property> <property name="valign">start</property>
<style> <style>
<class name="linked"/> <class name="card"/>
<class name="toolbar"/>
<class name="overlay-toolbar"/>
</style> </style>
</object> </object>
</child> </child>

View file

@ -1,13 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<interface> <interface>
<requires lib="gtk" version="4.0"/> <requires lib="gtk" version="4.0"/>
<object class="GtkHeaderBar" id="header_bar"> <requires lib="adw" version="1.0"/>
<object class="AdwHeaderBar" id="header_bar">
<property name="hexpand">False</property> <property name="hexpand">False</property>
<style> <style>
<class name="dino-left"/> <class name="dino-left"/>
</style> </style>
<child> <child>
<object class="GtkMenuButton" id="add_button"> <object class="GtkMenuButton" id="add_button">
<property name="has-frame">False</property>
<child> <child>
<object class="GtkImage"> <object class="GtkImage">
<property name="icon-name">list-add-symbolic</property> <property name="icon-name">list-add-symbolic</property>
@ -18,6 +20,7 @@
</child> </child>
<child type="end"> <child type="end">
<object class="GtkMenuButton" id="menu_button"> <object class="GtkMenuButton" id="menu_button">
<property name="has-frame">False</property>
<child> <child>
<object class="GtkImage"> <object class="GtkImage">
<property name="icon-name">open-menu-symbolic</property> <property name="icon-name">open-menu-symbolic</property>

View file

@ -88,15 +88,19 @@
</object> </object>
</child> </child>
<child> <child>
<object class="GtkRevealer" id="unread_count_revealer"> <object class="GtkRevealer" id="top_row_revealer">
<property name="transition-type">slide-right</property> <property name="transition-type">slide-right</property>
<property name="transition-duration">50</property> <property name="transition-duration">50</property>
<property name="reveal-child">True</property> <property name="reveal-child">True</property>
<property name="margin-start">15</property>
<child>
<object class="GtkBox">
<property name="orientation">horizontal</property>
<property name="spacing">6</property>
<child> <child>
<object class="GtkLabel" id="unread_count_label"> <object class="GtkLabel" id="unread_count_label">
<property name="vexpand">False</property> <property name="vexpand">False</property>
<property name="visible">False</property> <property name="visible">False</property>
<property name="margin-start">15</property>
<property name="xalign">0.5</property> <property name="xalign">0.5</property>
<attributes> <attributes>
<attribute name="scale" value="0.6"/> <attribute name="scale" value="0.6"/>
@ -104,6 +108,15 @@
</attributes> </attributes>
</object> </object>
</child> </child>
<child>
<object class="GtkImage" id="pinned_image">
<property name="icon-name">view-pin-symbolic</property>
<property name="pixel-size">12</property>
<property name="visible">False</property>
</object>
</child>
</object>
</child>
</object> </object>
</child> </child>
</object> </object>
@ -131,7 +144,7 @@
<property name="margin-start">5</property> <property name="margin-start">5</property>
<style> <style>
<class name="conversation_list_row_xbutton"/> <class name="conversation_list_row_xbutton"/>
<class name="circular-button"/> <class name="circular"/>
<class name="flat"/> <class name="flat"/>
</style> </style>
<child> <child>

View file

@ -31,7 +31,8 @@
<property name="halign">end</property> <property name="halign">end</property>
<property name="valign">end</property> <property name="valign">end</property>
<style> <style>
<class name="circular-button"/> <class name="circular"/>
<class name="opaque"/>
</style> </style>
<child> <child>
<object class="GtkImage"> <object class="GtkImage">

View file

@ -19,40 +19,13 @@
<object class="GtkStackPage"> <object class="GtkStackPage">
<property name="name">empty</property> <property name="name">empty</property>
<property name="child"> <property name="child">
<object class="GtkBox"> <object class="AdwStatusPage">
<property name="orientation">vertical</property> <style>
<property name="spacing">10</property> <class name="compact"/>
<property name="valign">center</property> </style>
<child>
<object class="GtkImage">
<property name="icon-name">system-search-symbolic</property> <property name="icon-name">system-search-symbolic</property>
<property name="icon-size">large</property> <property name="title" translatable="1">No active search</property>
<property name="pixel-size">72</property> <property name="description" translatable="1">Type to start a search</property>
<style>
<class name="dim-label"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="1">No active search</property>
<attributes>
<attribute name="weight" value="PANGO_WEIGHT_BOLD"></attribute>
<attribute name="scale" value="1.3"></attribute>
</attributes>
<style>
<class name="dim-label"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="1">Type to start a search</property>
<style>
<class name="dim-label"/>
</style>
</object>
</child>
</object> </object>
</property> </property>
</object> </object>
@ -61,40 +34,13 @@
<object class="GtkStackPage"> <object class="GtkStackPage">
<property name="name">no-result</property> <property name="name">no-result</property>
<property name="child"> <property name="child">
<object class="GtkBox"> <object class="AdwStatusPage">
<property name="orientation">vertical</property> <style>
<property name="spacing">10</property> <class name="compact"/>
<property name="valign">center</property> </style>
<child>
<object class="GtkImage">
<property name="icon-name">face-uncertain-symbolic</property> <property name="icon-name">face-uncertain-symbolic</property>
<property name="icon-size">large</property> <property name="title" translatable="1">No matching messages</property>
<property name="pixel-size">72</property> <property name="description" translatable="1">Check the spelling or try to remove filters</property>
<style>
<class name="dim-label"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="1">No matching messages</property>
<attributes>
<attribute name="weight" value="PANGO_WEIGHT_BOLD"></attribute>
<attribute name="scale" value="1.3"></attribute>
</attributes>
<style>
<class name="dim-label"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="1">Check the spelling or try to remove filters</property>
<style>
<class name="dim-label"/>
</style>
</object>
</child>
</object> </object>
</property> </property>
</object> </object>

View file

@ -17,13 +17,14 @@
<summary xml:lang="pt">Moderno cliente de chat XMPP</summary> <summary xml:lang="pt">Moderno cliente de chat XMPP</summary>
<summary xml:lang="pl">Nowoczesny komunikator XMPP</summary> <summary xml:lang="pl">Nowoczesny komunikator XMPP</summary>
<summary xml:lang="oc">Client XMPP modèrn</summary> <summary xml:lang="oc">Client XMPP modèrn</summary>
<summary xml:lang="nl_BE">Modernen XMPP-chatcliënt</summary>
<summary xml:lang="nl">Een moderne XMPP-chatclient</summary> <summary xml:lang="nl">Een moderne XMPP-chatclient</summary>
<summary xml:lang="nb">Moderne XMPP-sludreklient</summary> <summary xml:lang="nb">Moderne XMPP-sludreklient</summary>
<summary xml:lang="lt">Šiuolaikinė XMPP pokalbių kliento programa</summary> <summary xml:lang="lt">Šiuolaikinė XMPP pokalbių kliento programa</summary>
<summary xml:lang="lb">Modernen XMPP Chat Client</summary> <summary xml:lang="lb">Modernen XMPP Chat Client</summary>
<summary xml:lang="ko">현대 XMPP 채팅 클라이언트</summary>
<summary xml:lang="ja">現代的な XMPP チャット クライアント</summary> <summary xml:lang="ja">現代的な XMPP チャット クライアント</summary>
<summary xml:lang="it">Client di chat moderno per XMPP</summary> <summary xml:lang="it">Client di chat moderno per XMPP</summary>
<summary xml:lang="is">Nútímalegt XMPP-spjallforrit</summary>
<summary xml:lang="ie">Un modern client de conversationes XMPP</summary> <summary xml:lang="ie">Un modern client de conversationes XMPP</summary>
<summary xml:lang="id">Aplikasi chat XMPP modern</summary> <summary xml:lang="id">Aplikasi chat XMPP modern</summary>
<summary xml:lang="hu">Modern XMPP csevegőprogram</summary> <summary xml:lang="hu">Modern XMPP csevegőprogram</summary>
@ -33,6 +34,7 @@
<summary xml:lang="eu">XMPP txat bezero modernoa</summary> <summary xml:lang="eu">XMPP txat bezero modernoa</summary>
<summary xml:lang="es">Un cliente de XMPP moderno</summary> <summary xml:lang="es">Un cliente de XMPP moderno</summary>
<summary xml:lang="eo">Moderna XMPP-Retebabililo</summary> <summary xml:lang="eo">Moderna XMPP-Retebabililo</summary>
<summary xml:lang="el">Σύγχρονος XMPP Chat Client</summary>
<summary xml:lang="de">Modernes XMPP-Chat-Programm</summary> <summary xml:lang="de">Modernes XMPP-Chat-Programm</summary>
<summary xml:lang="cs">Moderní XMPP klient</summary> <summary xml:lang="cs">Moderní XMPP klient</summary>
<summary xml:lang="ca">Client de xat XMPP modern</summary> <summary xml:lang="ca">Client de xat XMPP modern</summary>
@ -50,13 +52,14 @@
<p xml:lang="pt">Dino é um moderno chat de código aberto para desktop. Ele é focado em prover uma transparente e confiável experiência Jabber/XMPP, tendo em mente a sua privacidade.</p> <p xml:lang="pt">Dino é um moderno chat de código aberto para desktop. Ele é focado em prover uma transparente e confiável experiência Jabber/XMPP, tendo em mente a sua privacidade.</p>
<p xml:lang="pl">Dino jest nowoczesnym, otwartym komunikatorem. Skupia się na prostej obsłudze sieci Jabber/XMPP dbając o twoją prywatność.</p> <p xml:lang="pl">Dino jest nowoczesnym, otwartym komunikatorem. Skupia się na prostej obsłudze sieci Jabber/XMPP dbając o twoją prywatność.</p>
<p xml:lang="oc">Dino es un client de chat liure e modèrn per lordenador de burèu. Ensaja de provesir una experiéncia neta e fisabla de Jabber/XMPP en téner en compte vòstra confidencialitat.</p> <p xml:lang="oc">Dino es un client de chat liure e modèrn per lordenador de burèu. Ensaja de provesir una experiéncia neta e fisabla de Jabber/XMPP en téner en compte vòstra confidencialitat.</p>
<p xml:lang="nl_BE">Dino is een moderne, vrije chattoepassing voor uw bureaublad. Ze biedt een eenvoudige en betrouwbare Jabber/XMPP-ervaring, met uw privacy in het achterhoofd.</p>
<p xml:lang="nl">Dino is een moderne, vrije chattoepassing voor je computer. Dino biedt een eenvoudige en betrouwbare Jabber-/XMPP-ervaring, met privacy in het achterhoofd.</p> <p xml:lang="nl">Dino is een moderne, vrije chattoepassing voor je computer. Dino biedt een eenvoudige en betrouwbare Jabber-/XMPP-ervaring, met privacy in het achterhoofd.</p>
<p xml:lang="nb">Dino er en moderne friporg-sludringsklient for skrivebordet. Det fokuserer på rask og pålitelig XMPP-opplevelse, samtidig som det hegner om personvernet.</p> <p xml:lang="nb">Dino er en moderne friporg-sludringsklient for skrivebordet. Det fokuserer på rask og pålitelig XMPP-opplevelse, samtidig som det hegner om personvernet.</p>
<p xml:lang="lt">Dino yra šiuolaikinė atvirojo kodo kliento programa skirta darbalaukiui. Jos pagrindinis dėmesys yra pateikti tvarkingą ir patikimą Jabber/XMPP patyrimą nepamirštant apie jūsų privatumą.</p> <p xml:lang="lt">Dino yra šiuolaikinė atvirojo kodo kliento programa skirta darbalaukiui. Jos pagrindinis dėmesys yra pateikti tvarkingą ir patikimą Jabber/XMPP patyrimą nepamirštant apie jūsų privatumą.</p>
<p xml:lang="lb">Dino ass e modernen, quell-offene Chat Client fir den Desktop. Hien biet eng opgeraumt a robust Jabber/XMPP Erfarung a leet ee Schwéierpunkt op Privatsphär.</p> <p xml:lang="lb">Dino ass e modernen, quell-offene Chat Client fir den Desktop. Hien biet eng opgeraumt a robust Jabber/XMPP Erfarung a leet ee Schwéierpunkt op Privatsphär.</p>
<p xml:lang="ko">Dino는 데스크탑을 위한 현대 오픈소스 채팅 클라이언트입니다. 깔끔하고 신뢰 할 수 있는 Jabber/XMPP 경험을 개인정보 보호 중시와 함께 제공할 수 있도록 주력하고 있습니다.</p>
<p xml:lang="ja">Dino はオープンソースの現代的なデスクトップ向けチャットクライアントです。プライバシーを考慮しつつ、シンプルで信頼できる Jabber/XMPP エクスペリエンスの提供を第一に考えて開発されています。</p> <p xml:lang="ja">Dino はオープンソースの現代的なデスクトップ向けチャットクライアントです。プライバシーを考慮しつつ、シンプルで信頼できる Jabber/XMPP エクスペリエンスの提供を第一に考えて開発されています。</p>
<p xml:lang="it">Dino è un client di chat per il desktop, moderno e open-source. Si concentra nel fornire un'esperienza Jabber/XMPP pulita e affidabile tenendo presente la tua privacy.</p> <p xml:lang="it">Dino è un client di chat per il desktop, moderno e open-source. Si concentra nel fornire un'esperienza Jabber/XMPP pulita e affidabile tenendo presente la tua privacy.</p>
<p xml:lang="is">Dino er nútímalegt spjallforrit og frjáls hugbúnaður fyrir skjáborðið. Það leggur áherslu á að veita hreina og áreiðanlega Jabber/XMPP upplifun með friðhelgi þína í huga.</p>
<p xml:lang="ie">Dino es un modern cliente de conversationes con fonte apert. It foca se sur provider un nett e fidibil experientie de Jabber/XMPP con un attention a confidentialitá.</p> <p xml:lang="ie">Dino es un modern cliente de conversationes con fonte apert. It foca se sur provider un nett e fidibil experientie de Jabber/XMPP con un attention a confidentialitá.</p>
<p xml:lang="id">Dino adalah aplikasi chat open source modern untuk PC. Menyediakan pengalaman Jabber / XMPP yang handal dengan tetap menjunjung privasi Anda.</p> <p xml:lang="id">Dino adalah aplikasi chat open source modern untuk PC. Menyediakan pengalaman Jabber / XMPP yang handal dengan tetap menjunjung privasi Anda.</p>
<p xml:lang="hu">A Dino egy modern, nyílt forráskódú csevegőprogram az asztali gépekre. Arra összpontosít, hogy tiszta és megbízható Jabber/XMPP-élményt nyújtson, miközben a magánszféra megőrzését is fontosnak tartja.</p> <p xml:lang="hu">A Dino egy modern, nyílt forráskódú csevegőprogram az asztali gépekre. Arra összpontosít, hogy tiszta és megbízható Jabber/XMPP-élményt nyújtson, miközben a magánszféra megőrzését is fontosnak tartja.</p>
@ -67,6 +70,7 @@
<p xml:lang="eu">Dino mahaigainerako iturburu irekiko txat bezero moderno bat da. Jabber/XMPP esperientzia garbi eta fidagarri bat ematen du zure pribatutasuna kontuan hartzeaz gain.</p> <p xml:lang="eu">Dino mahaigainerako iturburu irekiko txat bezero moderno bat da. Jabber/XMPP esperientzia garbi eta fidagarri bat ematen du zure pribatutasuna kontuan hartzeaz gain.</p>
<p xml:lang="es">Dino es un cliente de mensajería moderno y libre para escritorio y móvil. Está enfocado en proveer una experiencia Jabber/XMPP limpia y confiable teniendo la privacidad en mente.</p> <p xml:lang="es">Dino es un cliente de mensajería moderno y libre para escritorio y móvil. Está enfocado en proveer una experiencia Jabber/XMPP limpia y confiable teniendo la privacidad en mente.</p>
<p xml:lang="eo">Dino estas moderna malfermfonta retbabililo por la tabla komputilo. Ĝi celas provizi puran kaj fidindan sperton de Jabber/XMPP, protektante vian privatecon.</p> <p xml:lang="eo">Dino estas moderna malfermfonta retbabililo por la tabla komputilo. Ĝi celas provizi puran kaj fidindan sperton de Jabber/XMPP, protektante vian privatecon.</p>
<p xml:lang="el">Το Dino είναι ένας σύγχρονος πελάτης συνομιλίας ανοιχτού κώδικα για desktop υπολογιστές. Επικεντρώνεται στην παροχή μιας καθαρής και αξιόπιστης εμπειρίας Jabber/XMPP έχοντας παράλληλα υπόψη την προστασία των προσωπικών δεδομένων σας.</p>
<p xml:lang="de">Dino ist ein modernes, quelloffenes Chat-Programm für den Desktop. Es bietet ein aufgeräumtes und robustes Jabber-/XMPP-Erlebnis und legt einen Schwerpunkt auf Privatsphäre.</p> <p xml:lang="de">Dino ist ein modernes, quelloffenes Chat-Programm für den Desktop. Es bietet ein aufgeräumtes und robustes Jabber-/XMPP-Erlebnis und legt einen Schwerpunkt auf Privatsphäre.</p>
<p xml:lang="cs">Dino je moderní open-source chatovací klient pro stolní počítače. Jeho cílem je poskytování čistého a spolehlivého prostředí Jabber/XMPP s důrazem na zachování vašeho soukromí.</p> <p xml:lang="cs">Dino je moderní open-source chatovací klient pro stolní počítače. Jeho cílem je poskytování čistého a spolehlivého prostředí Jabber/XMPP s důrazem na zachování vašeho soukromí.</p>
<p xml:lang="ca">Dino és un client de xat lliure i modern per a l'escriptori. Està centrat en proveir una experiència neta i fiable de Jabber/XMPP, sempre tenint en compte la vostra privacitat.</p> <p xml:lang="ca">Dino és un client de xat lliure i modern per a l'escriptori. Està centrat en proveir una experiència neta i fiable de Jabber/XMPP, sempre tenint en compte la vostra privacitat.</p>
@ -83,13 +87,14 @@
<p xml:lang="pt">Suporte criptografia ponta a ponta com OMEMO e OpenPGP e permite configurar privacidade—características relacionadas às notificações de leitura, recebimento e escrita.</p> <p xml:lang="pt">Suporte criptografia ponta a ponta com OMEMO e OpenPGP e permite configurar privacidade—características relacionadas às notificações de leitura, recebimento e escrita.</p>
<p xml:lang="pl">Obsługuje szyfrowanie od końca do końca za pomocą OMEMO i OpenPGP, a także daje kontrolę nad funkcjami wpływającymi na prywatność, jak powiadomienia o pisaniu czy odczytaniu wiadomości.</p> <p xml:lang="pl">Obsługuje szyfrowanie od końca do końca za pomocą OMEMO i OpenPGP, a także daje kontrolę nad funkcjami wpływającymi na prywatność, jak powiadomienia o pisaniu czy odczytaniu wiadomości.</p>
<p xml:lang="oc">Compatible amb lo chiframent OMEMO e OpenPGP del cap a la fin e permet de configurar de foncionalitats ligadas amb la confidencialitat coma los acusats de lectura e las notificacions descritura.</p> <p xml:lang="oc">Compatible amb lo chiframent OMEMO e OpenPGP del cap a la fin e permet de configurar de foncionalitats ligadas amb la confidencialitat coma los acusats de lectura e las notificacions descritura.</p>
<p xml:lang="nl_BE">Ze ondersteunt eind-tot-eind-versleuteling met OMEMO en OpenPGP, en laat u toe privacygerelateerde functies, gelijk leesbevestigingen en typmeldingen, in te stellen.</p>
<p xml:lang="nl">Dino ondersteunt end-to-endversleuteling met OMEMO en OpenPGP en staat je toe privacy-gerelateerde functies, zoals leesbevestigingen en aan-het-typenmeldingen, in te stellen.</p> <p xml:lang="nl">Dino ondersteunt end-to-endversleuteling met OMEMO en OpenPGP en staat je toe privacy-gerelateerde functies, zoals leesbevestigingen en aan-het-typenmeldingen, in te stellen.</p>
<p xml:lang="nb">Det støtter ende-til-ende -kryptering med OMEMO og OpenPGP, og tillater oppsett av personvernsrelaterte funksjoner som meldingskvitteringer og skrivevarsling.</p> <p xml:lang="nb">Det støtter ende-til-ende -kryptering med OMEMO og OpenPGP, og tillater oppsett av personvernsrelaterte funksjoner som meldingskvitteringer og skrivevarsling.</p>
<p xml:lang="lt">Ji palaiko ištisinį šifravimą naudojant OMEMO ir OpenPGP bei leidžia konfigūruoti su privatumu susijusias ypatybes, tokias kaip pranešimus apie žinučių skaitymą ir rašymą.</p> <p xml:lang="lt">Ji palaiko ištisinį šifravimą naudojant OMEMO ir OpenPGP bei leidžia konfigūruoti su privatumu susijusias ypatybes, tokias kaip pranešimus apie žinučių skaitymą ir rašymą.</p>
<p xml:lang="lb">Hien ënnerstëtz Enn-zu-Enn Verschlësselung mat OMEMO an OpenPGP an enthält Privatsphäre-Astellungen zu Liesbestätegungen an Tipp-Benoriichtegungen.</p> <p xml:lang="lb">Hien ënnerstëtz Enn-zu-Enn Verschlësselung mat OMEMO an OpenPGP an enthält Privatsphäre-Astellungen zu Liesbestätegungen an Tipp-Benoriichtegungen.</p>
<p xml:lang="ko">OMEMO와 OpenPGP를 통한 종단간 암호화를 지원하며 프라이버시와 관련된 읽음 확인이나 입력 알림기능을 설정할 수 있습니다.</p>
<p xml:lang="ja">OMEMO と OpenPGP を利用したエンドツーエンド暗号化に対応しており、既読状態の送信や入力通知などのプライバシー関連の設定も可能です。</p> <p xml:lang="ja">OMEMO と OpenPGP を利用したエンドツーエンド暗号化に対応しており、既読状態の送信や入力通知などのプライバシー関連の設定も可能です。</p>
<p xml:lang="it">Support la crittografia end-to-end tramite OMEMO e OpenPGP e permette di configurare le funzioni relative alla privacy come le ricevute di lettura e le notifiche di digitazione.</p> <p xml:lang="it">Support la crittografia end-to-end tramite OMEMO e OpenPGP e permette di configurare le funzioni relative alla privacy come le ricevute di lettura e le notifiche di digitazione.</p>
<p xml:lang="is">Það styður dulkóðun frá enda til enda með OMEMO og OpenPGP og gerir kleift að stilla persónuverndartengda eiginleika eins og lestrarkvittanir og innsláttartilkynningar.</p>
<p xml:lang="ie">It supporta ciffration terminal per OMEMO e OpenPGP e permisse configurar sensitiv functiones quam confirmation de lectada e notificationes de tippada.</p> <p xml:lang="ie">It supporta ciffration terminal per OMEMO e OpenPGP e permisse configurar sensitiv functiones quam confirmation de lectada e notificationes de tippada.</p>
<p xml:lang="id">Mendukung enkripsi end-to-end dengan OMEMO dan OpenPGP, dan memungkinkan pengaturan fitur terkait privasi seperti tanda pesan dibaca dan pemberitahuan pengetikan.</p> <p xml:lang="id">Mendukung enkripsi end-to-end dengan OMEMO dan OpenPGP, dan memungkinkan pengaturan fitur terkait privasi seperti tanda pesan dibaca dan pemberitahuan pengetikan.</p>
<p xml:lang="hu">Támogatja az OMEMO és az OpenPGP használatával történő végpontok közötti titkosítást, és lehetővé teszi a magánszférához kapcsolódó funkciókat, mint például az olvasási visszaigazolást és a gépelési értesítéseket.</p> <p xml:lang="hu">Támogatja az OMEMO és az OpenPGP használatával történő végpontok közötti titkosítást, és lehetővé teszi a magánszférához kapcsolódó funkciókat, mint például az olvasási visszaigazolást és a gépelési értesítéseket.</p>
@ -98,8 +103,9 @@
<p xml:lang="fi">Se tukee päästä päähän -salausta OMEMO:n ja OpenPGP:n avulla ja mahdollistaa yksityisyyteen liittyvien ominaisuuksien, kuten lukukuittausten ja kirjoitusilmoitusten asetusten määrittämisen.</p> <p xml:lang="fi">Se tukee päästä päähän -salausta OMEMO:n ja OpenPGP:n avulla ja mahdollistaa yksityisyyteen liittyvien ominaisuuksien, kuten lukukuittausten ja kirjoitusilmoitusten asetusten määrittämisen.</p>
<p xml:lang="fa">از رمزگذاری سرتاسر با اُمیمو و اُپن‌پی‌جی‌پی پشتیبانی می‌کند و اجازه تنظیم قابلیت‌های مربوط به حریم خصوصی را می‌دهد، از جمله: رسید خوانده‌شدن پیام‌ها و اعلان در حال نوشتن بودن.</p> <p xml:lang="fa">از رمزگذاری سرتاسر با اُمیمو و اُپن‌پی‌جی‌پی پشتیبانی می‌کند و اجازه تنظیم قابلیت‌های مربوط به حریم خصوصی را می‌دهد، از جمله: رسید خوانده‌شدن پیام‌ها و اعلان در حال نوشتن بودن.</p>
<p xml:lang="eu">Amaieratik amaierarako enkriptazioa onartzen du OMEMO eta OpenPGPrekin eta pribatutasun ezaugarriak konfiguratzea baimentzen du irakurtze markak eta idazketa jakinarazpenak bezala.</p> <p xml:lang="eu">Amaieratik amaierarako enkriptazioa onartzen du OMEMO eta OpenPGPrekin eta pribatutasun ezaugarriak konfiguratzea baimentzen du irakurtze markak eta idazketa jakinarazpenak bezala.</p>
<p xml:lang="es">Soporta encriptación fin-a-fin a través de OMEMO y OpenPGP y permite configurar las características relacionadas con la privacidad, como confirmaciones de lectura y notificaciones de escritura.</p> <p xml:lang="es">Soporta cifrado fin-a-fin a través de OMEMO y OpenPGP y permite configurar características relacionadas con la privacidad, como confirmaciones de lectura y notificaciones de escritura.</p>
<p xml:lang="eo">Ĝi subtenas fin-al-finan ĉifradon per OMEMO kaj OpenPGP kaj permesas agordi funkciojn pri privateco kiel kvitancojn de legiteco kaj sciigojn pri tajpado.</p> <p xml:lang="eo">Ĝi subtenas fin-al-finan ĉifradon per OMEMO kaj OpenPGP kaj permesas agordi funkciojn pri privateco kiel kvitancojn de legiteco kaj sciigojn pri tajpado.</p>
<p xml:lang="el">Υποστηρίζει κρυπτογράφηση από άκρο σε άκρο με OMEMO και OpenPGP και επιτρέπει την ρύθμιση λειτουργιών που σχετίζονται με το απόρρητο, όπως αποδείξεις ανάγνωσης και ειδοποιήσεις πληκτρολόγησης.</p>
<p xml:lang="de">Er unterstützt Ende-zu-Ende Verschlüsselung mit OMEMO und OpenPGP und enthält Privatsphäre-Einstellungen zu Lesebestätigungen und Tippbenachrichtigungen.</p> <p xml:lang="de">Er unterstützt Ende-zu-Ende Verschlüsselung mit OMEMO und OpenPGP und enthält Privatsphäre-Einstellungen zu Lesebestätigungen und Tippbenachrichtigungen.</p>
<p xml:lang="cs">Podporuje šifrování end-to-end pomocí OMEMO a OpenPGP a umožňuje konfigurovat funkce související se soukromím, jako jsou potvrzení o přečtení a oznámení o psaní.</p> <p xml:lang="cs">Podporuje šifrování end-to-end pomocí OMEMO a OpenPGP a umožňuje konfigurovat funkce související se soukromím, jako jsou potvrzení o přečtení a oznámení o psaní.</p>
<p xml:lang="ca">Implementa xifratge punt a punt amb OMEMO i OpenPGP, i permet configurar funcionalitats relacionades amb la privacitat com per exemple rebuts de lectura i notificacions d'escriptura.</p> <p xml:lang="ca">Implementa xifratge punt a punt amb OMEMO i OpenPGP, i permet configurar funcionalitats relacionades amb la privacitat com per exemple rebuts de lectura i notificacions d'escriptura.</p>
@ -116,13 +122,14 @@
<p xml:lang="pt">Dino obtém o histórico do servidor e sincroniza mensagens com outros aparelhos.</p> <p xml:lang="pt">Dino obtém o histórico do servidor e sincroniza mensagens com outros aparelhos.</p>
<p xml:lang="pl">Dino pobiera historię rozmów z serwera i synchronizuje wiadomości z innymi urządzeniami.</p> <p xml:lang="pl">Dino pobiera historię rozmów z serwera i synchronizuje wiadomości z innymi urządzeniami.</p>
<p xml:lang="oc">Dino recupèra listoric del servidor e sincroniza los messatges amb dautres periferics.</p> <p xml:lang="oc">Dino recupèra listoric del servidor e sincroniza los messatges amb dautres periferics.</p>
<p xml:lang="nl_BE">Dino haalt de geschiedenis op van de server en synchroniseert berichten met andere apparaten.</p>
<p xml:lang="nl">Dino haalt de geschiedenis op van de server en synchroniseert berichten met andere apparaten.</p> <p xml:lang="nl">Dino haalt de geschiedenis op van de server en synchroniseert berichten met andere apparaten.</p>
<p xml:lang="nb">Dino henter historikk fra tjeneren og synkroniserer meldinger med andre enheter.</p> <p xml:lang="nb">Dino henter historikk fra tjeneren og synkroniserer meldinger med andre enheter.</p>
<p xml:lang="lt">Dino gauna istoriją iš serverio ir sinchronizuoja žinutes su kitais įrenginiais.</p> <p xml:lang="lt">Dino gauna istoriją iš serverio ir sinchronizuoja žinutes su kitais įrenginiais.</p>
<p xml:lang="lb">Dino rifft  Gespréichverläf vum Server of a synchroniséiert Noriichte mat anere Geräter.</p> <p xml:lang="lb">Dino rifft  Gespréichverläf vum Server of a synchroniséiert Noriichte mat anere Geräter.</p>
<p xml:lang="ko">Dino는 서버와 타 장치와의 메세지 동기화로부터 기록을 불러옵니다.</p>
<p xml:lang="ja">Dino はサーバーから履歴を取得し、ほかのデバイスとメッセージを同期します。</p> <p xml:lang="ja">Dino はサーバーから履歴を取得し、ほかのデバイスとメッセージを同期します。</p>
<p xml:lang="it">Dino recupera la cronologia dal server e sincronizza i messaggi con gli altri dispositivi.</p> <p xml:lang="it">Dino recupera la cronologia dal server e sincronizza i messaggi con gli altri dispositivi.</p>
<p xml:lang="is">Dino sækir feril af netþjóni og samstillir skilaboð með öðrum tækjum.</p>
<p xml:lang="ie">Dino obtene li diarium del servitore e sincronisa missages inter altri apparates.</p> <p xml:lang="ie">Dino obtene li diarium del servitore e sincronisa missages inter altri apparates.</p>
<p xml:lang="id">Dino mengambil riwayat pesan dari server dan menyinkronkan pesan dengan perangkat lain.</p> <p xml:lang="id">Dino mengambil riwayat pesan dari server dan menyinkronkan pesan dengan perangkat lain.</p>
<p xml:lang="hu">A Dino lekéri az előzményeket a kiszolgálóról, és szinkronizálja az üzeneteket a többi eszközzel.</p> <p xml:lang="hu">A Dino lekéri az előzményeket a kiszolgálóról, és szinkronizálja az üzeneteket a többi eszközzel.</p>
@ -133,6 +140,7 @@
<p xml:lang="eu">Dinok zerbitzaritik hartzen du historia eta beste gailuekin mezuak sinkronizatzen ditu.</p> <p xml:lang="eu">Dinok zerbitzaritik hartzen du historia eta beste gailuekin mezuak sinkronizatzen ditu.</p>
<p xml:lang="es">Dino recupera el historial de mensajes desde el servidor y sincroniza los mensajes con otros dispositivos.</p> <p xml:lang="es">Dino recupera el historial de mensajes desde el servidor y sincroniza los mensajes con otros dispositivos.</p>
<p xml:lang="eo">Dino prenas historion el la servilo kaj sinkronigas mesaĝojn kun aliaj aparatoj.</p> <p xml:lang="eo">Dino prenas historion el la servilo kaj sinkronigas mesaĝojn kun aliaj aparatoj.</p>
<p xml:lang="el">Το Dino ανακτά το ιστορικό από τον διακομιστή και συγχρονίζει τα μηνύματα με άλλες συσκευές.</p>
<p xml:lang="de">Dino ruft Gesprächsverläufe vom Server ab und synchronisiert Nachrichten mit anderen Geräten.</p> <p xml:lang="de">Dino ruft Gesprächsverläufe vom Server ab und synchronisiert Nachrichten mit anderen Geräten.</p>
<p xml:lang="cs">Dino načítá historii ze serveru a synchronizuje zprávy s ostatními zařízeními.</p> <p xml:lang="cs">Dino načítá historii ze serveru a synchronizuje zprávy s ostatními zařízeními.</p>
<p xml:lang="ca">Dino recupera l'historial del servidor i sincronitza els missatges amb altres dispositius.</p> <p xml:lang="ca">Dino recupera l'historial del servidor i sincronitza els missatges amb altres dispositius.</p>
@ -140,13 +148,13 @@
</description> </description>
<screenshots> <screenshots>
<screenshot type="default"> <screenshot type="default">
<image height="952" width="1601">https://dino.im/img/appdata/2022-02_screenshot-main.png</image> <image>https://dino.im/img/appdata/2022-02_screenshot-main.png</image>
</screenshot> </screenshot>
<screenshot> <screenshot>
<image height="753" width="1199">https://dino.im/img/appdata/2022-02_screenshot-call.png</image> <image>https://dino.im/img/appdata/2022-02_screenshot-call.png</image>
</screenshot> </screenshot>
<screenshot> <screenshot>
<image height="942" width="1600">https://dino.im/img/appdata/start_chat.png</image> <image>https://dino.im/img/appdata/start_chat.png</image>
</screenshot> </screenshot>
</screenshots> </screenshots>
<translation type="gettext">dino</translation> <translation type="gettext">dino</translation>
@ -155,21 +163,26 @@
<url type="bugtracker">https://github.com/dino/dino/issues</url> <url type="bugtracker">https://github.com/dino/dino/issues</url>
<url type="donation">https://dino.im/#donate</url> <url type="donation">https://dino.im/#donate</url>
<url type="translate">https://hosted.weblate.org/projects/dino/</url> <url type="translate">https://hosted.weblate.org/projects/dino/</url>
<!-- TODO: Point this to a webpage with documentation when there is one
<url type="help">http://dino.im/help/</url>
-->
<update_contact>appstream@dino.im</update_contact> <update_contact>appstream@dino.im</update_contact>
<!-- TODO: Write this when Dino is released
<releases> <releases>
<release date="XXXX-XX-XX" version="X.X"> <release date="2022-02-12" version="0.3">
<description> <description>
<p> <p>The 0.3 release is all about calls. Dino now supports calls between two or more people!</p>
This is our first release. It comes with a clean UI, notifications, </description>
end-to-end encryption support (OMEMO and GnuPG), multi-user chats, </release>
and more! <release date="2020-11-12" version="0.2">
</p> <description>
<p>The 0.2 release adds message correction, improves the file upload functionality and provides more information about message encryption.</p>
</description>
</release>
<release date="2020-01-29" version="0.1">
<description>
<p>The first Dino release! Dino is a secure and open-source application for decentralized messaging.</p>
</description> </description>
</release> </release>
</releases> </releases>
--> <content_rating type="oars-1.1">
<content_attribute id="social-chat">intense</content_attribute>
<content_attribute id="social-audio">intense</content_attribute>
</content_rating>
</component> </component>

View file

@ -13,13 +13,13 @@
</description> </description>
<screenshots> <screenshots>
<screenshot type="default"> <screenshot type="default">
<image height="952" width="1601">https://dino.im/img/appdata/2022-02_screenshot-main.png</image> <image>https://dino.im/img/appdata/2022-02_screenshot-main.png</image>
</screenshot> </screenshot>
<screenshot> <screenshot>
<image height="753" width="1199">https://dino.im/img/appdata/2022-02_screenshot-call.png</image> <image>https://dino.im/img/appdata/2022-02_screenshot-call.png</image>
</screenshot> </screenshot>
<screenshot> <screenshot>
<image height="942" width="1600">https://dino.im/img/appdata/start_chat.png</image> <image>https://dino.im/img/appdata/start_chat.png</image>
</screenshot> </screenshot>
</screenshots> </screenshots>
<translation type="gettext">dino</translation> <translation type="gettext">dino</translation>
@ -28,22 +28,26 @@
<url type="bugtracker">https://github.com/dino/dino/issues</url> <url type="bugtracker">https://github.com/dino/dino/issues</url>
<url type="donation">https://dino.im/#donate</url> <url type="donation">https://dino.im/#donate</url>
<url type="translate">https://hosted.weblate.org/projects/dino/</url> <url type="translate">https://hosted.weblate.org/projects/dino/</url>
<!-- TODO: Point this to a webpage with documentation when there is one
<url type="help">http://dino.im/help/</url>
-->
<update_contact>appstream@dino.im</update_contact> <update_contact>appstream@dino.im</update_contact>
<!-- TODO: Write this when Dino is released
<releases> <releases>
<release date="XXXX-XX-XX" version="X.X"> <release date="2022-02-12" version="0.3">
<description> <description>
<p> <p>The 0.3 release is all about calls. Dino now supports calls between two or more people!</p>
This is our first release. It comes with a clean UI, notifications, </description>
end-to-end encryption support (OMEMO and GnuPG), multi-user chats, </release>
and more! <release date="2020-11-12" version="0.2">
</p> <description>
<p>The 0.2 release adds message correction, improves the file upload functionality and provides more information about message encryption.</p>
</description>
</release>
<release date="2020-01-29" version="0.1">
<description>
<p>The first Dino release! Dino is a secure and open-source application for decentralized messaging.</p>
</description> </description>
</release> </release>
</releases> </releases>
--> <content_rating type="oars-1.1">
<content_attribute id="social-chat">intense</content_attribute>
<content_attribute id="social-audio">intense</content_attribute>
</content_rating>
</component> </component>

3
main/data/style-dark.css Normal file
View file

@ -0,0 +1,3 @@
.dino-main .overlay-toolbar {
background-color: shade(@view_bg_color, 1.5);
}

View file

@ -3,6 +3,10 @@
* It provides sane defaults for things that are very Dino-specific. * It provides sane defaults for things that are very Dino-specific.
*/ */
statuspage {
opacity: 0.5;
}
window.dino-main .dino-header-right { window.dino-main .dino-header-right {
background: @theme_base_color; background: @theme_base_color;
} }
@ -39,7 +43,7 @@ window.dino-main .dino-conversation .highlight-once {
} }
window.dino-main .dino-conversation .message-box.highlight { window.dino-main .dino-conversation .message-box.highlight {
background: alpha(@theme_fg_color, 0.04); background: @window_bg_color;
} }
window.dino-main .dino-conversation .message-box { window.dino-main .dino-conversation .message-box {
@ -88,11 +92,6 @@ window.dino-main .dino-sidebar > frame {
transition: background .05s ease; transition: background .05s ease;
} }
window.dino-main .circular-button {
padding: 0;
border-radius: 1000px;
}
window.dino-main .dino-conversation .message-box.edit-mode { window.dino-main .dino-conversation .message-box.edit-mode {
background: alpha(@theme_selected_bg_color, 0.1); background: alpha(@theme_selected_bg_color, 0.1);
} }
@ -120,20 +119,20 @@ window.dino-main .dino-quote:hover {
background: alpha(@theme_fg_color, 0.08); background: alpha(@theme_fg_color, 0.08);
} }
/* Message Menu */ /* Overlay Toolbar */
.message-menu-box { .dino-main .overlay-toolbar {
background-color: @theme_base_color; padding: 2px;
border: 1px solid alpha(@theme_fg_color, 0.15); border-radius: 6px;
border-radius: 5px; border-spacing: 0;
} }
.message-menu-button { .dino-main .overlay-toolbar > * {
padding: 6px; margin-top: 0;
border: none; margin-bottom: 0;
} }
/* Fie Widget */ /* File Widget */
window.dino-main .file-box-outer, window.dino-main .file-box-outer,
window.dino-main .call-box-outer { window.dino-main .call-box-outer {
@ -149,7 +148,7 @@ window.dino-main .call-box {
window.dino-main .file-image-widget { window.dino-main .file-image-widget {
border: 1px solid alpha(@theme_fg_color, 0.1); border: 1px solid alpha(@theme_fg_color, 0.1);
border-radius: 3px; border-radius: 6px;
} }
window.dino-main .file-image-widget .file-box-outer { window.dino-main .file-image-widget .file-box-outer {
@ -168,6 +167,10 @@ window.dino-main .file-image-widget .file-box-outer button:hover {
background: rgba(100, 100, 100, 0.5); background: rgba(100, 100, 100, 0.5);
} }
.dino-main .file-image-widget picture {
border-radius: 6px;
}
/* Call widget */ /* Call widget */
window.dino-main .call-box-outer.incoming { window.dino-main .call-box-outer.incoming {
@ -185,38 +188,23 @@ window.dino-main .multiparty-participants {
/* Reactions */ /* Reactions */
window.dino-main menubutton.reaction-box image { .dino-main .reaction-grid button {
margin-left: 5px; min-height: 16px;
margin-right: 5px; min-width: 30px;
padding: 4px;
} }
window.dino-main button.reaction-box, .dino-main .reaction-grid button.own-reaction,
window.dino-main menubutton.reaction-box > button { .dino-main .reaction-grid .own-reaction button {
border: 1px solid transparent; background-color: alpha(@accent_bg_color, 0.1);
padding: 3px 5px ; border: 1px solid @accent_bg_color;
border-radius: 10px; padding: 3px;
background-color: alpha(@theme_fg_color, 0.07); color: @accent_color;
background-image: none;
box-shadow: none;
min-height: 0;
min-width: 0;
} }
window.dino-main button.reaction-box.own-reaction, .dino-main .reaction-grid button.own-reaction:hover,
window.dino-main menubutton.reaction-box.own-reaction > button { .dino-main .reaction-grid .own-reaction button:hover {
color: mix(@theme_selected_bg_color, @theme_fg_color, 0.4); background-color: alpha(@accent_bg_color, 0.2);
border-color: @theme_selected_bg_color;
background-color: alpha(@theme_selected_bg_color, 0.05);
}
window.dino-main button.reaction-box:hover,
window.dino-main menubutton.reaction-box:hover > button {
background-color: alpha(@theme_fg_color, 0.1);
}
window.dino-main button.reaction-box.own-reaction:hover,
window.dino-main menubutton.reaction-box.own-reaction > button {
background-color: alpha(@theme_selected_bg_color, 0.2);
} }
/* Sidebar */ /* Sidebar */

View file

@ -1,19 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<interface> <interface>
<requires lib="gtk" version="4.0"/> <requires lib="gtk" version="4.0"/>
<object class="GtkPaned" id="paned"> <object class="AdwLeaflet" id="leaflet">
<property name="shrink-start-child">False</property> <property name="transition-type">slide</property>
<property name="shrink-end-child">False</property> <property name="can-navigate-back">true</property>
<property name="resize-start-child">False</property> <property name="can-navigate-forward">true</property>
<property name="position">300</property> <child>
<object class="GtkBox" id="left_box">
<property name="orientation">vertical</property>
<child> <child>
<object class="GtkStack" id="left_stack"> <object class="GtkStack" id="left_stack">
<property name="hexpand">False</property>
<child> <child>
<object class="GtkStackPage"> <object class="GtkStackPage">
<property name="name">content</property> <property name="name">content</property>
<property name="child"> <property name="child">
<object class="GtkScrolledWindow"> <object class="GtkScrolledWindow">
<property name="hscrollbar_policy">never</property> <property name="hscrollbar_policy">never</property>
<property name="vexpand">1</property>
<child> <child>
<object class="DinoUiConversationSelector" id="conversation_list"> <object class="DinoUiConversationSelector" id="conversation_list">
</object> </object>
@ -26,44 +30,43 @@
<object class="GtkStackPage"> <object class="GtkStackPage">
<property name="name">placeholder</property> <property name="name">placeholder</property>
<property name="child"> <property name="child">
<object class="GtkBox"> <object class="AdwStatusPage">
<style>
<class name="compact"/>
</style>
<property name="margin-start">20</property> <property name="margin-start">20</property>
<property name="margin-end">20</property> <property name="margin-end">20</property>
<property name="margin-top">20</property> <property name="margin-top">20</property>
<property name="margin-bottom">20</property> <property name="margin-bottom">20</property>
<property name="spacing">10</property> <property name="width_request">260</property>
<property name="valign">start</property>
<property name="halign">start</property> <property name="title" translatable="yes">You have no open chats</property>
<child> <property name="description" translatable="yes">Click + to start a chat or join a channel</property>
<object class="GtkImage" id="conversation_list_placeholder_image">
<property name="valign">start</property>
<style>
<class name="dim-label"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="wrap">1</property>
<property name="margin-top">70</property>
<property name="margin-end">50</property>
<property name="valign">end</property>
<property name="label" translatable="1">Click here to start a conversation or join a channel.</property>
<style>
<class name="dim-label"/>
</style>
</object>
</child>
</object> </object>
</property> </property>
</object> </object>
</child> </child>
</object> </object>
</child> </child>
</object>
</child>
<child>
<object class="GtkBox" id="right_box">
<property name="orientation">vertical</property>
<child>
<object class="AdwFlap" id="search_flap">
<property name="flap-position">end</property>
<property name="modal">true</property>
<property name="locked">true</property>
<property name="swipe-to-open">false</property>
<property name="fold-threshold-policy">natural</property>
<property name="hexpand">true</property>
<child type="content">
<object class="DinoUiNaturalSizeIncrease">
<property name="min-natural-width">600</property>
<child> <child>
<object class="GtkOverlay">
<property name="child">
<object class="GtkStack" id="right_stack"> <object class="GtkStack" id="right_stack">
<property name="hexpand">false</property>
<child> <child>
<object class="GtkStackPage"> <object class="GtkStackPage">
<property name="name">content</property> <property name="name">content</property>
@ -77,52 +80,37 @@
<object class="GtkStackPage"> <object class="GtkStackPage">
<property name="name">placeholder</property> <property name="name">placeholder</property>
<property name="child"> <property name="child">
<object class="GtkBox"> <object class="AdwStatusPage">
<property name="orientation">vertical</property>
<property name="hexpand">1</property>
<property name="vexpand">1</property>
<property name="halign">center</property>
<property name="valign">center</property>
<child>
<object class="GtkImage">
<property name="icon-name">im.dino.Dino-symbolic</property> <property name="icon-name">im.dino.Dino-symbolic</property>
<property name="pixel-size">144</property> <property name="hexpand">True</property>
<property name="margin-bottom">30</property> <property name="vexpand">True</property>
<style> </object>
<class name="dim-label"/> </property>
</style>
</object> </object>
</child> </child>
</object>
</child>
</object>
</child>
<child type="separator">
<object class="GtkSeparator" />
</child>
<child type="flap">
<object class="AdwClamp">
<property name="hexpand">false</property>
<property name="maximum-size">400</property>
<property name="tightening-threshold">400</property>
<child> <child>
<object class="GtkLabel"> <object class="AdwBin" id="search_frame">
<property name="label" translatable="1">You have no open chats</property> <property name="hexpand">true</property>
<style> <style>
<class name="dim-label"/> <class name="background"/>
</style> </style>
<attributes>
<attribute name="scale" value="1.2"></attribute>
</attributes>
</object> </object>
</child> </child>
</object> </object>
</property>
</object>
</child> </child>
</object> </object>
</property>
<child type="overlay">
<object class="GtkRevealer" id="search_revealer">
<property name="halign">end</property>
<property name="transition-type">slide-left</property>
<style>
<class name="dino-sidebar"/>
</style>
<property name="child">
<object class="GtkFrame" id="search_frame">
<property name="width-request">400</property>
</object>
</property>
</object>
</child> </child>
</object> </object>
</child> </child>

View file

@ -2,49 +2,31 @@
<interface> <interface>
<requires lib="gtk" version="4.0"/> <requires lib="gtk" version="4.0"/>
<template class="DinoUiMainWindowPlaceholder"> <template class="DinoUiMainWindowPlaceholder">
<property name="valign">center</property>
<child> <child>
<object class="GtkBox" id="box"> <object class="GtkBox" id="box">
<property name="orientation">vertical</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<child>
<object class="GtkHeaderBar">
<property name="show-title-buttons">true</property>
</object>
</child>
<child>
<object class="GtkBox">
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<property name="valign">center</property> <property name="valign">center</property>
<property name="halign">center</property> <property name="hexpand">True</property>
<property name="hexpand">1</property> <property name="vexpand">True</property>
<child> <child>
<object class="GtkImage"> <object class="AdwStatusPage" id="status_page">
<property name="icon-name">im.dino.Dino-symbolic</property> <property name="icon-name">im.dino.Dino-symbolic</property>
<property name="pixel-size">144</property>
<property name="margin-start">30</property>
<property name="margin-end">30</property>
<property name="margin-top">30</property>
<property name="margin-bottom">30</property>
<style>
<class name="dim-label"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel" id="title_label">
<property name="visible">0</property>
<style>
<class name="dim-label"/>
</style>
<attributes>
<attribute name="scale" value="1.3"></attribute>
</attributes>
</object>
</child>
<child>
<object class="GtkLabel" id="label">
<property name="margin-top">5</property>
<style>
<class name="dim-label"/>
</style>
</object> </object>
</child> </child>
<child> <child>
<object class="GtkButton" id="primary_button"> <object class="GtkButton" id="primary_button">
<property name="margin-top">15</property>
<property name="halign">center</property> <property name="halign">center</property>
<property name="visible">False</property>
<style> <style>
<class name="text-button"/> <class name="text-button"/>
<class name="suggested-action"/> <class name="suggested-action"/>
@ -55,7 +37,7 @@
<object class="GtkButton" id="secondary_button"> <object class="GtkButton" id="secondary_button">
<property name="visible">0</property> <property name="visible">0</property>
<property name="halign">center</property> <property name="halign">center</property>
<!-- <property name="no_show_all">True</property>--> <property name="visible">False</property>
<style> <style>
<class name="text-button"/> <class name="text-button"/>
</style> </style>
@ -63,5 +45,7 @@
</child> </child>
</object> </object>
</child> </child>
</object>
</child>
</template> </template>
</interface> </interface>

View file

@ -15,6 +15,7 @@ gl
hu hu
id id
ie ie
is
it it
ja ja
kab kab
@ -23,7 +24,6 @@ lb
lt lt
nb nb
nl nl
nl_BE
oc oc
pl pl
pt pt

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

1149
main/po/is.po Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -14,7 +14,7 @@ protected class RosterList {
private ulong[] handler_ids = new ulong[0]; private ulong[] handler_ids = new ulong[0];
private ListBox list_box = new ListBox(); private ListBox list_box = new ListBox();
private HashMap<Account, HashMap<Jid, ListRow>> rows = new HashMap<Account, HashMap<Jid, ListRow>>(Account.hash_func, Account.equals_func); private HashMap<Account, HashMap<Jid, ListBoxRow>> rows = new HashMap<Account, HashMap<Jid, ListBoxRow>>(Account.hash_func, Account.equals_func);
public RosterList(StreamInteractor stream_interactor, Gee.List<Account> accounts) { public RosterList(StreamInteractor stream_interactor, Gee.List<Account> accounts) {
this.stream_interactor = stream_interactor; this.stream_interactor = stream_interactor;
@ -47,14 +47,15 @@ protected class RosterList {
private void on_updated_roster_item(Account account, Jid jid, Roster.Item roster_item) { private void on_updated_roster_item(Account account, Jid jid, Roster.Item roster_item) {
on_removed_roster_item(account, jid, roster_item); on_removed_roster_item(account, jid, roster_item);
ListRow row = new ListRow.from_jid(stream_interactor, roster_item.jid, account, accounts.size > 1); ListRow row = new ListRow.from_jid(stream_interactor, roster_item.jid, account, accounts.size > 1);
rows[account][jid] = row; ListBoxRow list_box_row = new ListBoxRow() { child=row };
list_box.append(row); rows[account][jid] = list_box_row;
list_box.append(list_box_row);
list_box.invalidate_sort(); list_box.invalidate_sort();
list_box.invalidate_filter(); list_box.invalidate_filter();
} }
private void fetch_roster_items(Account account) { private void fetch_roster_items(Account account) {
rows[account] = new HashMap<Jid, ListRow>(Jid.hash_func, Jid.equals_func); rows[account] = new HashMap<Jid, ListBoxRow>(Jid.hash_func, Jid.equals_func);
foreach (Roster.Item roster_item in stream_interactor.get_module(RosterManager.IDENTITY).get_roster(account)) { foreach (Roster.Item roster_item in stream_interactor.get_module(RosterManager.IDENTITY).get_roster(account)) {
on_updated_roster_item(account, roster_item.jid, roster_item); on_updated_roster_item(account, roster_item.jid, roster_item);
} }

View file

@ -80,7 +80,7 @@ public class SelectContactDialog : Gtk.Dialog {
add_contact_dialog.present(); add_contact_dialog.present();
}); });
select_jid_fragment.remove_jid.connect((row) => { select_jid_fragment.remove_jid.connect((row) => {
ListRow list_row = roster_list_box.get_selected_row() as ListRow; ListRow list_row = roster_list_box.get_selected_row().child as ListRow;
stream_interactor.get_module(RosterManager.IDENTITY).remove_jid(list_row.account, list_row.jid); stream_interactor.get_module(RosterManager.IDENTITY).remove_jid(list_row.account, list_row.jid);
}); });
select_jid_fragment.notify["done"].connect(() => { select_jid_fragment.notify["done"].connect(() => {

View file

@ -4,7 +4,7 @@ using Dino.Entities;
using Dino.Ui; using Dino.Ui;
using Xmpp; using Xmpp;
public class Dino.Ui.Application : Gtk.Application, Dino.Application { public class Dino.Ui.Application : Adw.Application, Dino.Application {
private const string[] KEY_COMBINATION_QUIT = {"<Ctrl>Q", null}; private const string[] KEY_COMBINATION_QUIT = {"<Ctrl>Q", null};
private const string[] KEY_COMBINATION_ADD_CHAT = {"<Ctrl>T", null}; private const string[] KEY_COMBINATION_ADD_CHAT = {"<Ctrl>T", null};
private const string[] KEY_COMBINATION_ADD_CONFERENCE = {"<Ctrl>G", null}; private const string[] KEY_COMBINATION_ADD_CONFERENCE = {"<Ctrl>G", null};
@ -33,10 +33,6 @@ public class Dino.Ui.Application : Gtk.Application, Dino.Application {
Environment.set_application_name("Dino"); Environment.set_application_name("Dino");
Window.set_default_icon_name("im.dino.Dino"); Window.set_default_icon_name("im.dino.Dino");
CssProvider provider = new CssProvider();
provider.load_from_resource("/im/dino/Dino/theme.css");
StyleContext.add_provider_for_display(Gdk.Display.get_default(), provider, STYLE_PROVIDER_PRIORITY_APPLICATION);
create_actions(); create_actions();
add_main_option_entries(options); add_main_option_entries(options);
@ -272,25 +268,30 @@ public class Dino.Ui.Application : Gtk.Application, Dino.Application {
case "0.3": version = @"$version - <span font_style='italic'>Theikenmeer</span>"; break; case "0.3": version = @"$version - <span font_style='italic'>Theikenmeer</span>"; break;
} }
} }
Gtk.AboutDialog dialog = new Gtk.AboutDialog(); #if Adw_1_2
dialog.destroy_with_parent = true; Adw.AboutWindow about_window = new Adw.AboutWindow();
dialog.transient_for = window; about_window.application_icon = "im.dino.Dino";
dialog.modal = true; about_window.application_name = "Dino";
dialog.title = _("About Dino"); #else
Gtk.AboutDialog about_window = new Gtk.AboutDialog();
dialog.logo_icon_name = "im.dino.Dino"; about_window.logo_icon_name = "im.dino.Dino";
dialog.program_name = "Dino"; about_window.program_name = "Dino";
dialog.version = version; about_window.website_label = "dino.im";
dialog.comments = "Dino. Communicating happiness."; #endif
dialog.website = "https://dino.im/"; about_window.destroy_with_parent = true;
dialog.website_label = "dino.im"; about_window.transient_for = window;
dialog.copyright = "Copyright © 2016-2022 - Dino Team"; about_window.modal = true;
dialog.license_type = License.GPL_3_0; about_window.title = _("About Dino");
about_window.version = version;
about_window.comments = "Dino. Communicating happiness.";
about_window.website = "https://dino.im/";
about_window.copyright = "Copyright © 2016-2022 - Dino Team";
about_window.license_type = License.GPL_3_0;
if (!use_csd()) { if (!use_csd()) {
dialog.set_titlebar(null); about_window.set_titlebar(null);
} }
dialog.present(); about_window.present();
} }
private void show_join_muc_dialog(Account? account, string jid) { private void show_join_muc_dialog(Account? account, string jid) {

View file

@ -74,7 +74,7 @@ public class ChatInputController : Object {
quoted_content_item = content_item; quoted_content_item = content_item;
var quote_model = new Quote.Model.from_content_item(content_item, conversation, stream_interactor) { can_abort = true }; var quote_model = new Quote.Model.from_content_item(content_item, conversation, stream_interactor) { can_abort = true };
quote_model.aborted.connect(() => { quote_model.aborted.connect(() => {
content_item = null; quoted_content_item = null;
chat_input.unset_quoted_message(); chat_input.unset_quoted_message();
}); });
chat_input.set_quoted_message(Quote.get_widget(quote_model)); chat_input.set_quoted_message(Quote.get_widget(quote_model));
@ -83,8 +83,8 @@ public class ChatInputController : Object {
} }
public void set_conversation(Conversation conversation) { public void set_conversation(Conversation conversation) {
this.quoted_content_item = null;
reset_input_field_status(); reset_input_field_status();
this.quoted_content_item = null;
chat_input.unset_quoted_message(); chat_input.unset_quoted_message();
this.conversation = conversation; this.conversation = conversation;

View file

@ -49,6 +49,12 @@ public class SettingsProvider : Plugins.ContactDetailsProvider, Object {
combobox.active_id = get_notify_setting_id(conversation.notify_setting); combobox.active_id = get_notify_setting_id(conversation.notify_setting);
combobox.changed.connect(() => { conversation.notify_setting = get_notify_setting(combobox.active_id); } ); combobox.changed.connect(() => { conversation.notify_setting = get_notify_setting(combobox.active_id); } );
} }
Switch pinned_switch = new Switch() { valign=Align.CENTER };
string category = conversation.type_ == Conversation.Type.GROUPCHAT ? DETAILS_HEADLINE_ROOM : DETAILS_HEADLINE_CHAT;
contact_details.add(category, _("Pin conversation"), _("Pins the conversation to the top of the conversation list"), pinned_switch);
pinned_switch.state = conversation.pinned != 0;
pinned_switch.state_set.connect((state) => { conversation.pinned = state ? 1 : 0; return false; });
} }
private Conversation.Setting get_setting(string id) { private Conversation.Setting get_setting(string id) {

View file

@ -37,7 +37,7 @@ public class ConversationItemSkeleton : Plugins.ConversationItemWidgetInterface,
private uint time_update_timeout = 0; private uint time_update_timeout = 0;
private ulong updated_roster_handler_id = 0; private ulong updated_roster_handler_id = 0;
public ConversationItemSkeleton(StreamInteractor stream_interactor, Conversation conversation, Plugins.MetaConversationItem item, bool initial_item) { public ConversationItemSkeleton(StreamInteractor stream_interactor, Conversation conversation, Plugins.MetaConversationItem item) {
this.stream_interactor = stream_interactor; this.stream_interactor = stream_interactor;
this.conversation = conversation; this.conversation = conversation;
this.item = item; this.item = item;

View file

@ -9,6 +9,7 @@ namespace Dino.Ui.ConversationSummary {
[GtkTemplate (ui = "/im/dino/Dino/conversation_content_view/view.ui")] [GtkTemplate (ui = "/im/dino/Dino/conversation_content_view/view.ui")]
public class ConversationView : Widget, Plugins.ConversationItemCollection, Plugins.NotificationCollection { public class ConversationView : Widget, Plugins.ConversationItemCollection, Plugins.NotificationCollection {
private const int MESSAGE_MENU_BOX_OFFSET = -20;
public Conversation? conversation { get; private set; } public Conversation? conversation { get; private set; }
@ -23,7 +24,7 @@ public class ConversationView : Widget, Plugins.ConversationItemCollection, Plug
private Gee.List<Dino.Plugins.MessageAction>? message_actions = null; private Gee.List<Dino.Plugins.MessageAction>? message_actions = null;
private StreamInteractor stream_interactor; private StreamInteractor stream_interactor;
private Gee.TreeSet<Plugins.MetaConversationItem> content_items = new Gee.TreeSet<Plugins.MetaConversationItem>(compare_meta_items); private Gee.TreeSet<ContentMetaItem> content_items = new Gee.TreeSet<ContentMetaItem>(compare_content_meta_items);
private Gee.TreeSet<Plugins.MetaConversationItem> meta_items = new TreeSet<Plugins.MetaConversationItem>(compare_meta_items); private Gee.TreeSet<Plugins.MetaConversationItem> meta_items = new TreeSet<Plugins.MetaConversationItem>(compare_meta_items);
private Gee.HashMap<Plugins.MetaConversationItem, ConversationItemSkeleton> item_item_skeletons = new Gee.HashMap<Plugins.MetaConversationItem, ConversationItemSkeleton>(); private Gee.HashMap<Plugins.MetaConversationItem, ConversationItemSkeleton> item_item_skeletons = new Gee.HashMap<Plugins.MetaConversationItem, ConversationItemSkeleton>();
private Gee.HashMap<Plugins.MetaConversationItem, Widget> widgets = new Gee.HashMap<Plugins.MetaConversationItem, Widget>(); private Gee.HashMap<Plugins.MetaConversationItem, Widget> widgets = new Gee.HashMap<Plugins.MetaConversationItem, Widget>();
@ -36,7 +37,6 @@ public class ConversationView : Widget, Plugins.ConversationItemCollection, Plug
private double? was_page_size; private double? was_page_size;
private Mutex reloading_mutex = Mutex(); private Mutex reloading_mutex = Mutex();
private bool animate = false;
private bool firstLoad = true; private bool firstLoad = true;
private bool at_current_content = true; private bool at_current_content = true;
private bool reload_messages = true; private bool reload_messages = true;
@ -81,6 +81,15 @@ public class ConversationView : Widget, Plugins.ConversationItemCollection, Plug
main.add_controller(main_motion_events); main.add_controller(main_motion_events);
main_motion_events.motion.connect(update_highlight); main_motion_events.motion.connect(update_highlight);
// Process touch events and capture phase to allow highlighting a message without cursor
GestureClick click_controller = new GestureClick();
click_controller.touch_only = true;
click_controller.propagation_phase = Gtk.PropagationPhase.CAPTURE;
main_wrap_box.add_controller(click_controller);
click_controller.pressed.connect_after((n, x, y) => {
update_highlight(x, y);
});
return this; return this;
} }
@ -173,7 +182,7 @@ public class ConversationView : Widget, Plugins.ConversationItemCollection, Plug
currently_highlighted.add_css_class("highlight"); currently_highlighted.add_css_class("highlight");
// Move message menu // Move message menu
message_menu_box.margin_top = (int)(widget_y - 10); message_menu_box.margin_top = (int)(widget_y + MESSAGE_MENU_BOX_OFFSET);
} }
} }
@ -199,6 +208,7 @@ public class ConversationView : Widget, Plugins.ConversationItemCollection, Plug
MenuButton button = new MenuButton(); MenuButton button = new MenuButton();
button.icon_name = message_actions[i].icon_name; button.icon_name = message_actions[i].icon_name;
button.set_popover(message_actions[i].popover as Popover); button.set_popover(message_actions[i].popover as Popover);
button.tooltip_text = Util.string_if_tooltips_active(message_actions[i].tooltip);
action_buttons.add(button); action_buttons.add(button);
} }
@ -209,6 +219,7 @@ public class ConversationView : Widget, Plugins.ConversationItemCollection, Plug
button.clicked.connect(() => { button.clicked.connect(() => {
message_action.callback(button, current_meta_item, currently_highlighted); message_action.callback(button, current_meta_item, currently_highlighted);
}); });
button.tooltip_text = Util.string_if_tooltips_active(message_actions[i].tooltip);
action_buttons.add(button); action_buttons.add(button);
} }
} }
@ -231,12 +242,71 @@ public class ConversationView : Widget, Plugins.ConversationItemCollection, Plug
}); });
firstLoad = false; firstLoad = false;
} }
if (conversation == this.conversation && at_current_content) {
// Just make sure we are scrolled down
if (scrolled.vadjustment.value != scrolled.vadjustment.upper) {
scroll_animation(scrolled.vadjustment.upper).play();
}
return;
}
clear(); clear();
initialize_for_conversation_(conversation); initialize_for_conversation_(conversation);
display_latest(); display_latest();
at_current_content = true;
// Scroll to end
scrolled.vadjustment.value = scrolled.vadjustment.upper;
}
private void scroll_and_highlight_item(Plugins.MetaConversationItem target, uint duration = 500) {
Widget widget = null;
int h = 0;
foreach (Plugins.MetaConversationItem item in meta_items) {
widget = widgets[item];
if (target == item) {
break;
}
h += widget.get_allocated_height();
}
if (widget != widgets[target]) {
warning("Target item widget not reached");
return;
}
double target_height = h - scrolled.vadjustment.page_size * 1/3;
Adw.Animation animation = scroll_animation(target_height);
animation.done.connect(() => {
widget.remove_css_class("highlight-once");
widget.add_css_class("highlight-once");
Timeout.add(5000, () => {
widget.remove_css_class("highlight-once");
return false;
});
});
animation.play();
}
private Adw.Animation scroll_animation(double target) {
#if ADW_1_2
return new Adw.TimedAnimation(scrolled, scrolled.vadjustment.value, target, 500,
new Adw.PropertyAnimationTarget(scrolled.vadjustment, "value")
);
#else
return new Adw.TimedAnimation(scrolled, scrolled.vadjustment.value, target, 500,
new Adw.CallbackAnimationTarget(value => {
scrolled.vadjustment.value = value;
})
);
#endif
} }
public void initialize_around_message(Conversation conversation, ContentItem content_item) { public void initialize_around_message(Conversation conversation, ContentItem content_item) {
if (conversation == this.conversation) {
ContentMetaItem? matching_item = content_items.first_match(it => it.content_item.id == content_item.id);
if (matching_item != null) {
scroll_and_highlight_item(matching_item);
return;
}
}
clear(); clear();
initialize_for_conversation_(conversation); initialize_for_conversation_(conversation);
Gee.List<ContentMetaItem> before_items = content_populator.populate_before(conversation, content_item, 40); Gee.List<ContentMetaItem> before_items = content_populator.populate_before(conversation, content_item, 40);
@ -244,7 +314,6 @@ public class ConversationView : Widget, Plugins.ConversationItemCollection, Plug
do_insert_item(item); do_insert_item(item);
} }
ContentMetaItem meta_item = content_populator.get_content_meta_item(content_item); ContentMetaItem meta_item = content_populator.get_content_meta_item(content_item);
meta_item.can_merge = false;
Widget w = insert_new(meta_item); Widget w = insert_new(meta_item);
content_items.add(meta_item); content_items.add(meta_item);
meta_items.add(meta_item); meta_items.add(meta_item);
@ -260,23 +329,16 @@ public class ConversationView : Widget, Plugins.ConversationItemCollection, Plug
// Compute where to jump to for centered message, jump, highlight. // Compute where to jump to for centered message, jump, highlight.
reload_messages = false; reload_messages = false;
Timeout.add(700, () => { Timeout.add(700, () => {
int h = 0, i = 0; scroll_and_highlight_item(meta_item, 300);
foreach (Plugins.MetaConversationItem item in meta_items) {
Widget widget = widgets[item];
if (widget == w) {
break;
}
h += widget.get_allocated_height();
i++;
}
scrolled.vadjustment.value = h - scrolled.vadjustment.page_size * 1/3;
w.add_css_class("highlight-once");
reload_messages = true; reload_messages = true;
return false; return false;
}); });
} }
private void initialize_for_conversation_(Conversation? conversation) { private void initialize_for_conversation_(Conversation? conversation) {
if (this.conversation == conversation) {
print("Re-initialized for %s\n", conversation.counterpart.bare_jid.to_string());
}
// Deinitialize old conversation // Deinitialize old conversation
Dino.Application app = Dino.Application.get_default(); Dino.Application app = Dino.Application.get_default();
if (this.conversation != null) { if (this.conversation != null) {
@ -298,9 +360,6 @@ public class ConversationView : Widget, Plugins.ConversationItemCollection, Plug
} }
content_populator.init(this, conversation, Plugins.WidgetType.GTK4); content_populator.init(this, conversation, Plugins.WidgetType.GTK4);
subscription_notification.init(conversation, this); subscription_notification.init(conversation, this);
animate = false;
Timeout.add(20, () => { animate = true; return false; });
} }
private void display_latest() { private void display_latest() {
@ -330,8 +389,8 @@ public class ConversationView : Widget, Plugins.ConversationItemCollection, Plug
public void do_insert_item(Plugins.MetaConversationItem item) { public void do_insert_item(Plugins.MetaConversationItem item) {
lock (meta_items) { lock (meta_items) {
insert_new(item); insert_new(item);
if (item as ContentMetaItem != null) { if (item is ContentMetaItem) {
content_items.add(item); content_items.add((ContentMetaItem)item);
} }
meta_items.add(item); meta_items.add(item);
} }
@ -347,7 +406,9 @@ public class ConversationView : Widget, Plugins.ConversationItemCollection, Plug
widget_order.remove(skeleton.get_widget()); widget_order.remove(skeleton.get_widget());
item_item_skeletons.unset(item); item_item_skeletons.unset(item);
content_items.remove(item); if (item is ContentMetaItem) {
content_items.remove((ContentMetaItem)item);
}
meta_items.remove(item); meta_items.remove(item);
} }
@ -386,7 +447,7 @@ public class ConversationView : Widget, Plugins.ConversationItemCollection, Plug
Plugins.MetaConversationItem? lower_item = meta_items.lower(item); Plugins.MetaConversationItem? lower_item = meta_items.lower(item);
// Fill datastructure // Fill datastructure
ConversationItemSkeleton item_skeleton = new ConversationItemSkeleton(stream_interactor, conversation, item, !animate); ConversationItemSkeleton item_skeleton = new ConversationItemSkeleton(stream_interactor, conversation, item);
item_item_skeletons[item] = item_skeleton; item_item_skeletons[item] = item_skeleton;
int index = lower_item != null ? widget_order.index_of(item_item_skeletons[lower_item].get_widget()) + 1 : 0; int index = lower_item != null ? widget_order.index_of(item_item_skeletons[lower_item].get_widget()) + 1 : 0;
widget_order.insert(index, item_skeleton.get_widget()); widget_order.insert(index, item_skeleton.get_widget());
@ -502,6 +563,10 @@ public class ConversationView : Widget, Plugins.ConversationItemCollection, Plug
} }
} }
private static int compare_content_meta_items(ContentMetaItem a, ContentMetaItem b) {
return compare_meta_items(a, b);
}
private static int compare_meta_items(Plugins.MetaConversationItem a, Plugins.MetaConversationItem b) { private static int compare_meta_items(Plugins.MetaConversationItem a, Plugins.MetaConversationItem b) {
int cmp1 = a.time.compare(b.time); int cmp1 = a.time.compare(b.time);
if (cmp1 != 0) return cmp1; if (cmp1 != 0) return cmp1;

View file

@ -10,9 +10,6 @@ namespace Dino.Ui {
public class FileDefaultWidget : Box { public class FileDefaultWidget : Box {
public signal void clicked(); public signal void clicked();
public signal void open_file();
public signal void save_file_as();
public signal void cancel_download();
[GtkChild] public unowned Stack image_stack; [GtkChild] public unowned Stack image_stack;
[GtkChild] public unowned Label name_label; [GtkChild] public unowned Label name_label;
@ -23,12 +20,6 @@ public class FileDefaultWidget : Box {
private FileTransfer.State state; private FileTransfer.State state;
class construct {
install_action("file.open", null, (widget, action_name) => { ((FileDefaultWidget) widget).open_file(); });
install_action("file.save_as", null, (widget, action_name) => { ((FileDefaultWidget) widget).save_file_as(); });
install_action("file.cancel", null, (widget, action_name) => { ((FileDefaultWidget) widget).cancel_download(); });
}
public FileDefaultWidget() { public FileDefaultWidget() {
EventControllerMotion this_motion_events = new EventControllerMotion(); EventControllerMotion this_motion_events = new EventControllerMotion();
this.add_controller(this_motion_events); this.add_controller(this_motion_events);

View file

@ -8,64 +8,70 @@ namespace Dino.Ui {
public class FileImageWidget : Box { public class FileImageWidget : Box {
private ScalingImage image;
FileDefaultWidget file_default_widget;
FileDefaultWidgetController file_default_widget_controller;
public FileImageWidget() { public FileImageWidget() {
this.halign = Align.START; this.halign = Align.START;
this.add_css_class("file-image-widget"); this.add_css_class("file-image-widget");
this.set_cursor_from_name("zoom-in");
} }
public async void load_from_file(File file, string file_name, int MAX_WIDTH=600, int MAX_HEIGHT=300) throws GLib.Error { public async void load_from_file(File file, string file_name, int MAX_WIDTH=600, int MAX_HEIGHT=300) throws GLib.Error {
// Load and prepare image in tread Gtk.Box image_overlay_toolbar = new Gtk.Box(Orientation.HORIZONTAL, 0) { halign=Gtk.Align.END, valign=Gtk.Align.START, margin_top=10, margin_start=10, margin_end=10, margin_bottom=10, vexpand=false, visible=false };
Thread<ScalingImage?> thread = new Thread<ScalingImage?> (null, () => { image_overlay_toolbar.add_css_class("card");
ScalingImage image = new ScalingImage() { halign=Align.START, visible = true, max_width = MAX_WIDTH, max_height = MAX_HEIGHT }; image_overlay_toolbar.add_css_class("toolbar");
image_overlay_toolbar.add_css_class("overlay-toolbar");
image_overlay_toolbar.set_cursor_from_name("default");
Gdk.Pixbuf pixbuf; FixedRatioPicture image = new FixedRatioPicture() { min_width=100, min_height=100, max_width=MAX_WIDTH, max_height=MAX_HEIGHT, file=file };
try { GestureClick gesture_click_controller = new GestureClick();
pixbuf = new Gdk.Pixbuf.from_file(file.get_path()); gesture_click_controller.button = 1; // listen for left clicks
} catch (Error error) { gesture_click_controller.released.connect((n_press, x, y) => {
warning("Can't load picture %s - %s", file.get_path(), error.message); switch (gesture_click_controller.get_device().source) {
Idle.add(load_from_file.callback); case Gdk.InputSource.TOUCHSCREEN:
return null; case Gdk.InputSource.PEN:
if (n_press == 1) {
image_overlay_toolbar.visible = !image_overlay_toolbar.visible;
} else if (n_press == 2) {
this.activate_action("file.open", null);
image_overlay_toolbar.visible = false;
}
break;
default:
this.activate_action("file.open", null);
image_overlay_toolbar.visible = false;
break;
} }
pixbuf = pixbuf.apply_embedded_orientation();
image.load(pixbuf);
Idle.add(load_from_file.callback);
return image;
}); });
yield; image.add_controller(gesture_click_controller);
image = thread.join();
if (image == null) throw new Error(-1, 0, "Error loading image");
FileInfo file_info = file.query_info("*", FileQueryInfoFlags.NONE); FileInfo file_info = file.query_info("*", FileQueryInfoFlags.NONE);
string? mime_type = Dino.Util.get_content_type(file_info); string? mime_type = Dino.Util.get_content_type(file_info);
file_default_widget = new FileDefaultWidget() { valign=Align.END, vexpand=false, visible=false }; MenuButton button = new MenuButton();
file_default_widget.image_stack.visible = false; button.icon_name = "open-menu";
file_default_widget_controller = new FileDefaultWidgetController(file_default_widget); Menu menu_model = new Menu();
file_default_widget_controller.set_file(file, file_name, mime_type); menu_model.append(_("Open"), "file.open");
menu_model.append(_("Save as…"), "file.save_as");
Gtk.PopoverMenu popover_menu = new Gtk.PopoverMenu.from_model(menu_model);
button.popover = popover_menu;
image_overlay_toolbar.append(button);
Overlay overlay = new Overlay(); Overlay overlay = new Overlay();
overlay.set_child(image); overlay.set_child(image);
overlay.add_overlay(file_default_widget); overlay.add_overlay(image_overlay_toolbar);
overlay.set_measure_overlay(image, true); overlay.set_measure_overlay(image, true);
overlay.set_clip_overlay(file_default_widget, true); overlay.set_clip_overlay(image_overlay_toolbar, true);
EventControllerMotion this_motion_events = new EventControllerMotion(); EventControllerMotion this_motion_events = new EventControllerMotion();
this.add_controller(this_motion_events); this.add_controller(this_motion_events);
this_motion_events.enter.connect(() => { this_motion_events.enter.connect(() => {
file_default_widget.visible = true; image_overlay_toolbar.visible = true;
}); });
this_motion_events.leave.connect(() => { this_motion_events.leave.connect(() => {
if (file_default_widget.file_menu.popover != null && file_default_widget.file_menu.popover.visible) return; if (button.popover != null && button.popover.visible) return;
file_default_widget.visible = false; image_overlay_toolbar.visible = false;
}); });
this.append(overlay); this.append(overlay);

View file

@ -10,19 +10,46 @@ namespace Dino.Ui {
public class FileMetaItem : ConversationSummary.ContentMetaItem { public class FileMetaItem : ConversationSummary.ContentMetaItem {
private StreamInteractor stream_interactor; private StreamInteractor stream_interactor;
private FileItem file_item;
private FileTransfer file_transfer;
public FileMetaItem(ContentItem content_item, StreamInteractor stream_interactor) { public FileMetaItem(ContentItem content_item, StreamInteractor stream_interactor) {
base(content_item); base(content_item);
this.stream_interactor = stream_interactor; this.stream_interactor = stream_interactor;
this.file_item = content_item as FileItem;
this.file_transfer = file_item.file_transfer;
} }
public override Object? get_widget(Plugins.ConversationItemWidgetInterface outer, Plugins.WidgetType type) { public override Object? get_widget(Plugins.ConversationItemWidgetInterface outer, Plugins.WidgetType type) {
FileItem file_item = content_item as FileItem; FileWidget widget = new FileWidget(file_transfer);
FileTransfer transfer = file_item.file_transfer; FileWidgetController widget_controller = new FileWidgetController(widget, file_transfer, stream_interactor);
return new FileWidget(stream_interactor, transfer); return widget;
} }
public override Gee.List<Plugins.MessageAction>? get_item_actions(Plugins.WidgetType type) { return null; } public override Gee.List<Plugins.MessageAction>? get_item_actions(Plugins.WidgetType type) {
if (file_transfer.provider != 0 || file_transfer.info == null) return null;
Gee.List<Plugins.MessageAction> actions = new ArrayList<Plugins.MessageAction>();
if (stream_interactor.get_module(ContentItemStore.IDENTITY).get_message_id_for_content_item(file_item.conversation, content_item) != null) {
Plugins.MessageAction reply_action = new Plugins.MessageAction();
reply_action.icon_name = "mail-reply-sender-symbolic";
reply_action.callback = (button, content_meta_item_activated, widget) => {
GLib.Application.get_default().activate_action("quote", new GLib.Variant.tuple(new GLib.Variant[] { new GLib.Variant.int32(file_item.conversation.id), new GLib.Variant.int32(content_item.id) }));
};
actions.add(reply_action);
Plugins.MessageAction action2 = new Plugins.MessageAction();
action2.icon_name = "dino-emoticon-add-symbolic";
EmojiChooser chooser = new EmojiChooser();
chooser.emoji_picked.connect((emoji) => {
stream_interactor.get_module(Reactions.IDENTITY).add_reaction(file_item.conversation, content_item, emoji);
});
action2.popover = chooser;
actions.add(action2);
}
return actions;
}
} }
public class FileWidget : SizeRequestBox { public class FileWidget : SizeRequestBox {
@ -32,7 +59,6 @@ public class FileWidget : SizeRequestBox {
DEFAULT DEFAULT
} }
private StreamInteractor stream_interactor;
private FileTransfer file_transfer; private FileTransfer file_transfer;
public FileTransfer.State file_transfer_state { get; set; } public FileTransfer.State file_transfer_state { get; set; }
public string file_transfer_mime_type { get; set; } public string file_transfer_mime_type { get; set; }
@ -41,13 +67,24 @@ public class FileWidget : SizeRequestBox {
private FileDefaultWidgetController default_widget_controller; private FileDefaultWidgetController default_widget_controller;
private Widget? content = null; private Widget? content = null;
public signal void open_file();
public signal void save_file_as();
public signal void start_download();
public signal void cancel_download();
class construct {
install_action("file.open", null, (widget, action_name) => { ((FileWidget) widget).open_file(); });
install_action("file.save_as", null, (widget, action_name) => { ((FileWidget) widget).save_file_as(); });
install_action("file.download", null, (widget, action_name) => { ((FileWidget) widget).start_download(); });
install_action("file.cancel", null, (widget, action_name) => { ((FileWidget) widget).cancel_download(); });
}
construct { construct {
margin_top = 4; margin_top = 4;
size_request_mode = SizeRequestMode.HEIGHT_FOR_WIDTH; size_request_mode = SizeRequestMode.HEIGHT_FOR_WIDTH;
} }
public FileWidget(StreamInteractor stream_interactor, FileTransfer file_transfer) { public FileWidget(FileTransfer file_transfer) {
this.stream_interactor = stream_interactor;
this.file_transfer = file_transfer; this.file_transfer = file_transfer;
update_widget.begin(); update_widget.begin();
@ -88,7 +125,7 @@ public class FileWidget : SizeRequestBox {
if (content != null) this.remove(content); if (content != null) this.remove(content);
FileDefaultWidget default_file_widget = new FileDefaultWidget(); FileDefaultWidget default_file_widget = new FileDefaultWidget();
default_widget_controller = new FileDefaultWidgetController(default_file_widget); default_widget_controller = new FileDefaultWidgetController(default_file_widget);
default_widget_controller.set_file_transfer(file_transfer, stream_interactor); default_widget_controller.set_file_transfer(file_transfer);
content = default_file_widget; content = default_file_widget;
this.state = State.DEFAULT; this.state = State.DEFAULT;
this.append(content); this.append(content);
@ -113,94 +150,104 @@ public class FileWidget : SizeRequestBox {
} }
} }
public class FileDefaultWidgetController : Object { public class FileWidgetController : Object {
private FileDefaultWidget widget;
private FileTransfer? file_transfer;
public string file_transfer_path { get; set; }
public string file_transfer_state { get; set; }
public string file_transfer_mime_type { get; set; }
private weak Widget widget;
private FileTransfer file_transfer;
private StreamInteractor? stream_interactor; private StreamInteractor? stream_interactor;
private string file_uri;
private string file_name;
private FileTransfer.State state;
public FileDefaultWidgetController(FileDefaultWidget widget) { public FileWidgetController(FileWidget widget, FileTransfer file_transfer, StreamInteractor? stream_interactor = null) {
this.widget = widget; this.widget = widget;
this.ref();
widget.clicked.connect(on_clicked); this.widget.weak_ref(() => {
widget.open_file.connect(open_file); this.widget = null;
widget.save_file_as.connect(save_file); this.unref();
widget.cancel_download.connect(cancel_download); });
}
public void set_file_transfer(FileTransfer file_transfer, StreamInteractor stream_interactor) {
this.file_transfer = file_transfer; this.file_transfer = file_transfer;
this.stream_interactor = stream_interactor; this.stream_interactor = stream_interactor;
widget.name_label.label = file_name = file_transfer.file_name; widget.open_file.connect(open_file);
widget.save_file_as.connect(save_file);
file_transfer.bind_property("path", this, "file-transfer-path"); widget.start_download.connect(start_download);
file_transfer.bind_property("state", this, "file-transfer-state"); widget.cancel_download.connect(cancel_download);
file_transfer.bind_property("mime-type", this, "file-transfer-mime-type");
this.notify["file-transfer-path"].connect(update_file_info);
this.notify["file-transfer-state"].connect(update_file_info);
this.notify["file-transfer-mime-type"].connect(update_file_info);
update_file_info();
}
public void set_file(File file, string file_name, string? mime_type) {
file_uri = file.get_uri();
state = FileTransfer.State.COMPLETE;
widget.name_label.label = this.file_name = file_name;
widget.update_file_info(mime_type, state, -1);
}
private void update_file_info() {
file_uri = file_transfer.get_file().get_uri();
state = file_transfer.state;
widget.update_file_info(file_transfer.mime_type, file_transfer.state, file_transfer.size);
} }
private void open_file() { private void open_file() {
try{ try{
Dino.Util.launch_default_for_uri(file_uri); Dino.Util.launch_default_for_uri(file_transfer.get_file().get_uri());
} catch (Error err) { } catch (Error err) {
warning("Failed to open %s - %s", file_uri, err.message); warning("Failed to open %s - %s", file_transfer.get_file().get_uri(), err.message);
} }
} }
private void save_file() { private void save_file() {
var save_dialog = new FileChooserNative(_("Save as…"), widget.get_root() as Gtk.Window, FileChooserAction.SAVE, null, null); var save_dialog = new FileChooserNative(_("Save as…"), widget.get_root() as Gtk.Window, FileChooserAction.SAVE, null, null);
save_dialog.set_modal(true); save_dialog.set_modal(true);
save_dialog.set_current_name(file_name); save_dialog.set_current_name(file_transfer.file_name);
save_dialog.response.connect(() => { save_dialog.response.connect(() => {
try{ try{
GLib.File.new_for_uri(file_uri).copy(save_dialog.get_file(), GLib.FileCopyFlags.OVERWRITE, null); GLib.File.new_for_uri(file_transfer.get_file().get_uri()).copy(save_dialog.get_file(), GLib.FileCopyFlags.OVERWRITE, null);
} catch (Error err) { } catch (Error err) {
warning("Failed copy file %s - %s", file_uri, err.message); warning("Failed copy file %s - %s", file_transfer.get_file().get_uri(), err.message);
} }
}); });
save_dialog.show(); save_dialog.show();
} }
private void start_download() {
if (stream_interactor != null) {
stream_interactor.get_module(FileManager.IDENTITY).download_file.begin(file_transfer);
}
}
private void cancel_download() { private void cancel_download() {
file_transfer.cancellable.cancel(); file_transfer.cancellable.cancel();
} }
}
public class FileDefaultWidgetController : Object {
private FileDefaultWidget widget;
private FileTransfer? file_transfer;
public string file_transfer_state { get; set; }
public string file_transfer_mime_type { get; set; }
private FileTransfer.State state;
public FileDefaultWidgetController(FileDefaultWidget widget) {
this.widget = widget;
widget.clicked.connect(on_clicked);
this.notify["file-transfer-state"].connect(update_file_info);
this.notify["file-transfer-mime-type"].connect(update_file_info);
}
public void set_file_transfer(FileTransfer file_transfer) {
this.file_transfer = file_transfer;
widget.name_label.label = file_transfer.file_name;
file_transfer.bind_property("state", this, "file-transfer-state");
file_transfer.bind_property("mime-type", this, "file-transfer-mime-type");
update_file_info();
}
private void update_file_info() {
state = file_transfer.state;
widget.update_file_info(file_transfer.mime_type, file_transfer.state, file_transfer.size);
}
private void on_clicked() { private void on_clicked() {
switch (state) { switch (state) {
case FileTransfer.State.COMPLETE: case FileTransfer.State.COMPLETE:
open_file(); widget.activate_action("file.open", null);
break; break;
case FileTransfer.State.NOT_STARTED: case FileTransfer.State.NOT_STARTED:
assert(stream_interactor != null && file_transfer != null); widget.activate_action("file.download", null);
stream_interactor.get_module(FileManager.IDENTITY).download_file.begin(file_transfer);
break; break;
default: default:
// Clicking doesn't do anything in FAILED and IN_PROGRESS states // Clicking doesn't do anything in FAILED and IN_PROGRESS states

View file

@ -198,7 +198,7 @@ public class MessageMetaItem : ContentMetaItem {
if (quoted_content_item != null) { if (quoted_content_item != null) {
var quote_model = new Quote.Model.from_content_item(quoted_content_item, message_item.conversation, stream_interactor); var quote_model = new Quote.Model.from_content_item(quoted_content_item, message_item.conversation, stream_interactor);
quote_model.jump_to.connect(() => { quote_model.jump_to.connect(() => {
GLib.Application.get_default().activate_action("jump-to-conversation-message", new GLib.Variant.tuple(new GLib.Variant[] { new GLib.Variant.int32(message_item.conversation.id), new GLib.Variant.int32(message_item.id) })); GLib.Application.get_default().activate_action("jump-to-conversation-message", new GLib.Variant.tuple(new GLib.Variant[] { new GLib.Variant.int32(message_item.conversation.id), new GLib.Variant.int32(quoted_content_item.id) }));
}); });
var quote_widget = Quote.get_widget(quote_model); var quote_widget = Quote.get_widget(quote_model);
outer.set_widget(quote_widget, Plugins.WidgetType.GTK4, 1); outer.set_widget(quote_widget, Plugins.WidgetType.GTK4, 1);
@ -217,6 +217,7 @@ public class MessageMetaItem : ContentMetaItem {
if (correction_allowed) { if (correction_allowed) {
Plugins.MessageAction action1 = new Plugins.MessageAction(); Plugins.MessageAction action1 = new Plugins.MessageAction();
action1.icon_name = "document-edit-symbolic"; action1.icon_name = "document-edit-symbolic";
action1.tooltip = _("Edit message");
action1.callback = (button, content_meta_item_activated, widget) => { action1.callback = (button, content_meta_item_activated, widget) => {
this.in_edit_mode = true; this.in_edit_mode = true;
}; };
@ -225,14 +226,16 @@ public class MessageMetaItem : ContentMetaItem {
Plugins.MessageAction reply_action = new Plugins.MessageAction(); Plugins.MessageAction reply_action = new Plugins.MessageAction();
reply_action.icon_name = "mail-reply-sender-symbolic"; reply_action.icon_name = "mail-reply-sender-symbolic";
reply_action.tooltip = _("Reply");
reply_action.callback = (button, content_meta_item_activated, widget) => { reply_action.callback = (button, content_meta_item_activated, widget) => {
GLib.Application.get_default().activate_action("quote", new GLib.Variant.tuple(new GLib.Variant[] { new GLib.Variant.int32(message_item.conversation.id), new GLib.Variant.int32(message_item.id) })); GLib.Application.get_default().activate_action("quote", new GLib.Variant.tuple(new GLib.Variant[] { new GLib.Variant.int32(message_item.conversation.id), new GLib.Variant.int32(content_item.id) }));
}; };
actions.add(reply_action); actions.add(reply_action);
if (supports_reaction) { if (supports_reaction) {
Plugins.MessageAction action2 = new Plugins.MessageAction(); Plugins.MessageAction action2 = new Plugins.MessageAction();
action2.icon_name = "dino-emoticon-add-symbolic"; action2.icon_name = "dino-emoticon-add-symbolic";
action2.tooltip = _("Add reaction");
EmojiChooser chooser = new EmojiChooser(); EmojiChooser chooser = new EmojiChooser();
chooser.emoji_picked.connect((emoji) => { chooser.emoji_picked.connect((emoji) => {
stream_interactor.get_module(Reactions.IDENTITY).add_reaction(message_item.conversation, message_item, emoji); stream_interactor.get_module(Reactions.IDENTITY).add_reaction(message_item.conversation, message_item, emoji);

View file

@ -27,7 +27,8 @@ namespace Dino.Ui.Quote {
var message = ((MessageItem) content_item).message; var message = ((MessageItem) content_item).message;
this.message = Dino.message_body_without_reply_fallback(message); this.message = Dino.message_body_without_reply_fallback(message);
} else if (content_item.type_ == FileItem.TYPE) { } else if (content_item.type_ == FileItem.TYPE) {
this.message = "[File]"; var file_transfer = ((FileItem) content_item).file_transfer;
this.message = _("File") + ": " + file_transfer.file_name;
} }
this.message_time = content_item.time; this.message_time = content_item.time;

View file

@ -123,9 +123,10 @@ public class ReactionsWidget : Grid {
public ReactionsWidget() { public ReactionsWidget() {
this.row_spacing = this.column_spacing = 5; this.row_spacing = this.column_spacing = 5;
this.margin_top = 2; this.margin_top = 2;
this.add_css_class("reaction-grid");
add_button = new MenuButton() { tooltip_text= _("Add reaction") }; add_button = new MenuButton() { tooltip_text= _("Add reaction") };
add_button.get_style_context().add_class("reaction-box"); add_button.add_css_class("pill");
Util.menu_button_set_icon_with_size(add_button, "dino-emoticon-add-symbolic", 14); Util.menu_button_set_icon_with_size(add_button, "dino-emoticon-add-symbolic", 14);
EmojiChooser chooser = new EmojiChooser(); EmojiChooser chooser = new EmojiChooser();
@ -140,8 +141,8 @@ public class ReactionsWidget : Grid {
Label reaction_label = new Label("<span size='small'>" + reaction + "</span>") { use_markup=true }; Label reaction_label = new Label("<span size='small'>" + reaction + "</span>") { use_markup=true };
Label count_label = new Label("") { use_markup=true }; Label count_label = new Label("") { use_markup=true };
Button button = new Button(); Button button = new Button();
button.get_style_context().add_class("reaction-box"); button.add_css_class("pill");
Box reaction_box = new Box(Orientation.HORIZONTAL, 4); Box reaction_box = new Box(Orientation.HORIZONTAL, 4) { halign=Align.CENTER };
reaction_box.append(reaction_label); reaction_box.append(reaction_label);
reaction_box.append(count_label); reaction_box.append(count_label);
button.set_child(reaction_box); button.set_child(reaction_box);
@ -161,9 +162,9 @@ public class ReactionsWidget : Grid {
reaction_counts[reaction].label = "<span font_family='monospace' size='small'>" + count.to_string() + "</span>"; reaction_counts[reaction].label = "<span font_family='monospace' size='small'>" + count.to_string() + "</span>";
if (own) { if (own) {
reaction_buttons[reaction].get_style_context().add_class("own-reaction"); reaction_buttons[reaction].add_css_class("own-reaction");
} else { } else {
reaction_buttons[reaction].get_style_context().remove_class("own-reaction"); reaction_buttons[reaction].remove_css_class("own-reaction");
} }
// Build tooltip // Build tooltip

View file

@ -15,12 +15,12 @@ public class ConversationListTitlebar : Gtk.Box {
} }
} }
public static HeaderBar get_conversation_list_titlebar_csd() { public static Adw.HeaderBar get_conversation_list_titlebar_csd() {
Builder builder = new Builder.from_resource("/im/dino/Dino/conversation_list_titlebar_csd.ui"); Builder builder = new Builder.from_resource("/im/dino/Dino/conversation_list_titlebar_csd.ui");
MenuButton add_button = (MenuButton) builder.get_object("add_button"); MenuButton add_button = (MenuButton) builder.get_object("add_button");
MenuButton menu_button = (MenuButton) builder.get_object("menu_button"); MenuButton menu_button = (MenuButton) builder.get_object("menu_button");
create_add_menu(add_button, menu_button); create_add_menu(add_button, menu_button);
return (HeaderBar) builder.get_object("header_bar"); return (Adw.HeaderBar) builder.get_object("header_bar");
} }
private static void create_add_menu(MenuButton add_button, MenuButton menu_button) { private static void create_add_menu(MenuButton add_button, MenuButton menu_button) {

View file

@ -38,7 +38,6 @@ public class ConversationSelector : Widget {
construct { construct {
add_css_class("sidebar"); add_css_class("sidebar");
list_box.set_header_func(header);
list_box.set_sort_func(sort); list_box.set_sort_func(sort);
realize.connect(() => { realize.connect(() => {
@ -75,6 +74,8 @@ public class ConversationSelector : Widget {
private void add_conversation(Conversation conversation) { private void add_conversation(Conversation conversation) {
ConversationSelectorRow row; ConversationSelectorRow row;
if (!rows.has_key(conversation)) { if (!rows.has_key(conversation)) {
conversation.notify["pinned"].connect(list_box.invalidate_sort);
row = new ConversationSelectorRow(stream_interactor, conversation); row = new ConversationSelectorRow(stream_interactor, conversation);
rows[conversation] = row; rows[conversation] = row;
list_box.append(row); list_box.append(row);
@ -119,6 +120,8 @@ public class ConversationSelector : Widget {
private async void remove_conversation(Conversation conversation) { private async void remove_conversation(Conversation conversation) {
select_fallback_conversation(conversation); select_fallback_conversation(conversation);
if (rows.has_key(conversation)) { if (rows.has_key(conversation)) {
conversation.notify["pinned"].disconnect(list_box.invalidate_sort);
yield rows[conversation].colapse(); yield rows[conversation].colapse();
list_box.remove(rows[conversation]); list_box.remove(rows[conversation]);
rows.unset(conversation); rows.unset(conversation);
@ -135,20 +138,16 @@ public class ConversationSelector : Widget {
} }
} }
private void header(ListBoxRow row, ListBoxRow? before_row) {
if (row.get_header() == null && before_row != null) {
row.set_header(new Separator(Orientation.HORIZONTAL));
} else if (row.get_header() != null && before_row == null) {
row.set_header(null);
}
}
private int sort(ListBoxRow row1, ListBoxRow row2) { private int sort(ListBoxRow row1, ListBoxRow row2) {
ConversationSelectorRow cr1 = row1 as ConversationSelectorRow; ConversationSelectorRow cr1 = row1 as ConversationSelectorRow;
ConversationSelectorRow cr2 = row2 as ConversationSelectorRow; ConversationSelectorRow cr2 = row2 as ConversationSelectorRow;
if (cr1 != null && cr2 != null) { if (cr1 != null && cr2 != null) {
Conversation c1 = cr1.conversation; Conversation c1 = cr1.conversation;
Conversation c2 = cr2.conversation; Conversation c2 = cr2.conversation;
int pin_comp = c2.pinned - c1.pinned;
if (pin_comp != 0) return pin_comp;
if (c1.last_active == null) return -1; if (c1.last_active == null) return -1;
if (c2.last_active == null) return 1; if (c2.last_active == null) return 1;
int comp = c2.last_active.compare(c1.last_active); int comp = c2.last_active.compare(c1.last_active);

View file

@ -21,7 +21,8 @@ public class ConversationSelectorRow : ListBoxRow {
[GtkChild] protected unowned Button x_button; [GtkChild] protected unowned Button x_button;
[GtkChild] protected unowned Revealer time_revealer; [GtkChild] protected unowned Revealer time_revealer;
[GtkChild] protected unowned Revealer xbutton_revealer; [GtkChild] protected unowned Revealer xbutton_revealer;
[GtkChild] protected unowned Revealer unread_count_revealer; [GtkChild] protected unowned Revealer top_row_revealer;
[GtkChild] protected unowned Image pinned_image;
[GtkChild] public unowned Revealer main_revealer; [GtkChild] public unowned Revealer main_revealer;
public Conversation conversation { get; private set; } public Conversation conversation { get; private set; }
@ -102,8 +103,10 @@ public class ConversationSelectorRow : ListBoxRow {
}); });
image.set_conversation(stream_interactor, conversation); image.set_conversation(stream_interactor, conversation);
conversation.notify["read-up-to-item"].connect(() => update_read()); conversation.notify["read-up-to-item"].connect(() => update_read());
conversation.notify["pinned"].connect(() => { update_pinned_icon(); });
update_name_label(); update_name_label();
update_pinned_icon();
content_item_received(); content_item_received();
} }
@ -135,6 +138,10 @@ public class ConversationSelectorRow : ListBoxRow {
name_label.label = Util.get_conversation_display_name(stream_interactor, conversation); name_label.label = Util.get_conversation_display_name(stream_interactor, conversation);
} }
private void update_pinned_icon() {
pinned_image.visible = conversation.pinned != 0;
}
protected void update_time_label(DateTime? new_time = null) { protected void update_time_label(DateTime? new_time = null) {
if (last_content_item != null) { if (last_content_item != null) {
time_label.visible = true; time_label.visible = true;
@ -252,11 +259,11 @@ public class ConversationSelectorRow : ListBoxRow {
StateFlags curr_flags = get_state_flags(); StateFlags curr_flags = get_state_flags();
if ((curr_flags & StateFlags.PRELIGHT) != 0) { if ((curr_flags & StateFlags.PRELIGHT) != 0) {
time_revealer.set_reveal_child(false); time_revealer.set_reveal_child(false);
unread_count_revealer.set_reveal_child(false); top_row_revealer.set_reveal_child(false);
xbutton_revealer.set_reveal_child(true); xbutton_revealer.set_reveal_child(true);
} else { } else {
time_revealer.set_reveal_child(true); time_revealer.set_reveal_child(true);
unread_count_revealer.set_reveal_child(true); top_row_revealer.set_reveal_child(true);
xbutton_revealer.set_reveal_child(false); xbutton_revealer.set_reveal_child(false);
} }
} }

View file

@ -12,6 +12,9 @@ public interface ConversationTitlebar : Object {
public abstract void insert_button(Widget button); public abstract void insert_button(Widget button);
public abstract Widget get_widget(); public abstract Widget get_widget();
public abstract bool back_button_visible{ get; set; }
public signal void back_pressed();
} }
public class ConversationTitlebarNoCsd : ConversationTitlebar, Object { public class ConversationTitlebarNoCsd : ConversationTitlebar, Object {
@ -31,14 +34,27 @@ public class ConversationTitlebarNoCsd : ConversationTitlebar, Object {
} }
} }
public bool back_button_visible {
get { return back_revealer.reveal_child; }
set { back_revealer.reveal_child = value; }
}
private Box widgets_box = new Box(Orientation.HORIZONTAL, 7) { margin_start=15, valign=Align.END }; private Box widgets_box = new Box(Orientation.HORIZONTAL, 7) { margin_start=15, valign=Align.END };
private Label title_label = new Label("") { ellipsize=EllipsizeMode.END }; private Label title_label = new Label("") { ellipsize=EllipsizeMode.END };
private Label subtitle_label = new Label("") { use_markup=true, ellipsize=EllipsizeMode.END, visible=false }; private Label subtitle_label = new Label("") { use_markup=true, ellipsize=EllipsizeMode.END, visible=false };
private Revealer back_revealer;
construct { construct {
Box content_box = new Box(Orientation.HORIZONTAL, 0) { margin_start=15, margin_end=10, hexpand=true }; Box content_box = new Box(Orientation.HORIZONTAL, 0) { margin_start=15, margin_end=10, hexpand=true };
main.append(content_box); main.append(content_box);
back_revealer = new Revealer() { visible = true, transition_type = RevealerTransitionType.SLIDE_RIGHT, transition_duration = 200, can_focus = false, reveal_child = false };
Button back_button = new Button.from_icon_name("go-previous-symbolic") { visible = true, valign = Align.CENTER, use_underline = true };
back_button.get_style_context().add_class("image-button");
back_button.clicked.connect(() => back_pressed());
back_revealer.set_child(back_button);
content_box.append(back_revealer);
Box titles_box = new Box(Orientation.VERTICAL, 0) { valign=Align.CENTER, hexpand=true }; Box titles_box = new Box(Orientation.VERTICAL, 0) { valign=Align.CENTER, hexpand=true };
content_box.append(titles_box); content_box.append(titles_box);
@ -67,10 +83,15 @@ public class ConversationTitlebarCsd : ConversationTitlebar, Object {
public new string? title { get { return title_label.label; } set { title_label.label = value; } } public new string? title { get { return title_label.label; } set { title_label.label = value; } }
public new string? subtitle { get { return subtitle_label.label; } set { subtitle_label.label = value; subtitle_label.visible = (value != null); } } public new string? subtitle { get { return subtitle_label.label; } set { subtitle_label.label = value; subtitle_label.visible = (value != null); } }
public bool back_button_visible {
get { return back_revealer.reveal_child; }
set { back_revealer.reveal_child = value; }
}
public HeaderBar header_bar = new HeaderBar(); public Adw.HeaderBar header_bar = new Adw.HeaderBar();
private Label title_label = new Label("") { ellipsize=EllipsizeMode.END }; private Label title_label = new Label("") { ellipsize=EllipsizeMode.END };
private Label subtitle_label = new Label("") { ellipsize=EllipsizeMode.END, visible=false }; private Label subtitle_label = new Label("") { ellipsize=EllipsizeMode.END, visible=false };
private Revealer back_revealer;
public ConversationTitlebarCsd() { public ConversationTitlebarCsd() {
Box titles_box = new Box(Orientation.VERTICAL, 0) { valign=Align.CENTER }; Box titles_box = new Box(Orientation.VERTICAL, 0) { valign=Align.CENTER };
@ -82,6 +103,13 @@ public class ConversationTitlebarCsd : ConversationTitlebar, Object {
subtitle_label.add_css_class("dim-label"); subtitle_label.add_css_class("dim-label");
titles_box.append(subtitle_label); titles_box.append(subtitle_label);
back_revealer = new Revealer() { visible = true, transition_type = RevealerTransitionType.SLIDE_RIGHT, transition_duration = 200, can_focus = false, reveal_child = false };
Button back_button = new Button.from_icon_name("go-previous-symbolic") { visible = true, valign = Align.CENTER, use_underline = true };
back_button.get_style_context().add_class("image-button");
back_button.clicked.connect(() => back_pressed());
back_revealer.set_child(back_button);
header_bar.pack_start(back_revealer);
header_bar.set_title_widget(titles_box); header_bar.set_title_widget(titles_box);
} }

View file

@ -11,7 +11,7 @@ class OccupantsEntry : Plugins.ConversationTitlebarEntry, Object {
StreamInteractor stream_interactor; StreamInteractor stream_interactor;
private Conversation? conversation; private Conversation? conversation;
private MenuButton button = new MenuButton() { icon_name="system-users-symbolic", tooltip_text=Util.string_if_tooltips_active(_("Members")) }; private MenuButton button = new MenuButton() { icon_name="system-users-symbolic", tooltip_text=Util.string_if_tooltips_active(_("Members")), visible=false };
private OccupantMenu.View menu = null; private OccupantMenu.View menu = null;

View file

@ -151,6 +151,8 @@ public class GlobalSearch {
} }
private void clear_search() { private void clear_search() {
// Scroll to top
results_scrolled.vadjustment.value = 0;
foreach (Widget widget in results_box_children) { foreach (Widget widget in results_box_children) {
results_box.remove(widget); results_box.remove(widget);
} }

View file

@ -6,7 +6,7 @@ using Dino.Entities;
namespace Dino.Ui { namespace Dino.Ui {
public class MainWindow : Gtk.Window { public class MainWindow : Adw.Window {
public signal void conversation_selected(Conversation conversation); public signal void conversation_selected(Conversation conversation);
@ -19,11 +19,11 @@ public class MainWindow : Gtk.Window {
public ConversationSelector conversation_selector; public ConversationSelector conversation_selector;
public ConversationTitlebar conversation_titlebar; public ConversationTitlebar conversation_titlebar;
public Widget conversation_list_titlebar; public Widget conversation_list_titlebar;
public HeaderBar placeholder_headerbar = new HeaderBar() { show_title_buttons=true };
public Box box = new Box(Orientation.VERTICAL, 0) { orientation=Orientation.VERTICAL }; public Box box = new Box(Orientation.VERTICAL, 0) { orientation=Orientation.VERTICAL };
public Paned headerbar_paned = new Paned(Orientation.HORIZONTAL) { resize_start_child=false, shrink_start_child=false, shrink_end_child=false }; public Adw.Leaflet leaflet;
public Paned paned; public Box left_box;
public Revealer search_revealer; public Box right_box;
public Adw.Flap search_flap;
public GlobalSearch global_search; public GlobalSearch global_search;
private Stack stack = new Stack(); private Stack stack = new Stack();
private Stack left_stack; private Stack left_stack;
@ -35,7 +35,7 @@ public class MainWindow : Gtk.Window {
class construct { class construct {
var shortcut = new Shortcut(new KeyvalTrigger(Key.F, ModifierType.CONTROL_MASK), new CallbackAction((widget, args) => { var shortcut = new Shortcut(new KeyvalTrigger(Key.F, ModifierType.CONTROL_MASK), new CallbackAction((widget, args) => {
((MainWindow) widget).search_revealer.reveal_child = true; ((MainWindow) widget).search_flap.reveal_flap = true;
return false; return false;
})); }));
add_shortcut(shortcut); add_shortcut(shortcut);
@ -51,65 +51,56 @@ public class MainWindow : Gtk.Window {
this.add_css_class("dino-main"); this.add_css_class("dino-main");
Gtk.Settings.get_default().notify["gtk-decoration-layout"].connect(set_window_buttons);
((Widget)this).realize.connect(set_window_buttons);
((Widget)this).realize.connect(restore_window_size); ((Widget)this).realize.connect(restore_window_size);
setup_headerbar();
setup_unified(); setup_unified();
setup_headerbar();
setup_stack(); setup_stack();
paned.bind_property("position", headerbar_paned, "position", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL);
} }
private void setup_unified() { private void setup_unified() {
Builder builder = new Builder.from_resource("/im/dino/Dino/unified_main_content.ui"); Builder builder = new Builder.from_resource("/im/dino/Dino/unified_main_content.ui");
paned = (Paned) builder.get_object("paned"); leaflet = (Adw.Leaflet) builder.get_object("leaflet");
box.append(paned); box.append(leaflet);
left_box = (Box) builder.get_object("left_box");
right_box = (Box) builder.get_object("right_box");
left_stack = (Stack) builder.get_object("left_stack"); left_stack = (Stack) builder.get_object("left_stack");
right_stack = (Stack) builder.get_object("right_stack"); right_stack = (Stack) builder.get_object("right_stack");
conversation_view = (ConversationView) builder.get_object("conversation_view"); conversation_view = (ConversationView) builder.get_object("conversation_view");
search_revealer = (Revealer) builder.get_object("search_revealer"); search_flap = (Adw.Flap) builder.get_object("search_flap");
conversation_selector = ((ConversationSelector) builder.get_object("conversation_list")).init(stream_interactor); conversation_selector = ((ConversationSelector) builder.get_object("conversation_list")).init(stream_interactor);
conversation_selector.conversation_selected.connect_after(() => leaflet.navigate(Adw.NavigationDirection.FORWARD));
Frame search_frame = (Frame) builder.get_object("search_frame"); Adw.Bin search_frame = (Adw.Bin) builder.get_object("search_frame");
global_search = new GlobalSearch(stream_interactor); global_search = new GlobalSearch(stream_interactor);
search_frame.set_child(global_search.get_widget()); search_frame.set_child(global_search.get_widget());
Image conversation_list_placeholder_image = (Image) builder.get_object("conversation_list_placeholder_image");
conversation_list_placeholder_image.set_from_pixbuf(new Pixbuf.from_resource("/im/dino/Dino/dino-conversation-list-placeholder-arrow.svg"));
} }
private void setup_headerbar() { private void setup_headerbar() {
if (Util.use_csd()) { if (Util.use_csd()) {
conversation_list_titlebar = get_conversation_list_titlebar_csd(); conversation_list_titlebar = get_conversation_list_titlebar_csd();
conversation_titlebar = new ConversationTitlebarCsd(); conversation_titlebar = new ConversationTitlebarCsd();
leaflet.bind_property("folded", conversation_list_titlebar, "show-end-title-buttons", BindingFlags.SYNC_CREATE);
leaflet.bind_property("folded", conversation_titlebar.get_widget(), "show-start-title-buttons", BindingFlags.SYNC_CREATE);
} else { } else {
Label title_label = new Label("Dino");
HeaderBar titlebar = new HeaderBar() { title_widget=title_label, show_title_buttons=true };
box.prepend(titlebar);
conversation_list_titlebar = new ConversationListTitlebar(); conversation_list_titlebar = new ConversationListTitlebar();
conversation_titlebar = new ConversationTitlebarNoCsd(); conversation_titlebar = new ConversationTitlebarNoCsd();
box.append(headerbar_paned);
} }
headerbar_paned.set_start_child(conversation_list_titlebar); left_box.prepend(conversation_list_titlebar);
headerbar_paned.set_end_child(conversation_titlebar.get_widget()); right_box.prepend(conversation_titlebar.get_widget());
} leaflet.notify["folded"].connect_after(() => conversation_titlebar.back_button_visible = leaflet.folded);
conversation_titlebar.back_pressed.connect(() => leaflet.navigate(Adw.NavigationDirection.BACK));
private void set_window_buttons() {
if (!Util.use_csd()) return;
Gtk.Settings? gtk_settings = Gtk.Settings.get_default();
if (gtk_settings == null) return;
string[] buttons = gtk_settings.gtk_decoration_layout.split(":");
HeaderBar conversation_headerbar = this.conversation_titlebar.get_widget() as HeaderBar;
conversation_headerbar.decoration_layout = ((buttons.length == 2) ? ":" + buttons[1] : "");
HeaderBar conversation_list_headerbar = this.conversation_list_titlebar as HeaderBar;
conversation_list_headerbar.decoration_layout = buttons[0] + ":";
} }
private void setup_stack() { private void setup_stack() {
stack.add_named(box, "main"); stack.add_named(box, "main");
stack.add_named(welcome_placeholder, "welcome_placeholder"); stack.add_named(welcome_placeholder, "welcome_placeholder");
stack.add_named(accounts_placeholder, "accounts_placeholder"); stack.add_named(accounts_placeholder, "accounts_placeholder");
set_child(stack); set_content(stack);
} }
public enum StackState { public enum StackState {
@ -125,25 +116,16 @@ public class MainWindow : Gtk.Window {
right_stack.set_visible_child_name("content"); right_stack.set_visible_child_name("content");
stack.set_visible_child_name("main"); stack.set_visible_child_name("main");
if (Util.use_csd()) {
set_titlebar(headerbar_paned);
}
} else if (stack_state == StackState.CLEAN_START || stack_state == StackState.NO_ACTIVE_ACCOUNTS) { } else if (stack_state == StackState.CLEAN_START || stack_state == StackState.NO_ACTIVE_ACCOUNTS) {
if (stack_state == StackState.CLEAN_START) { if (stack_state == StackState.CLEAN_START) {
stack.set_visible_child_name("welcome_placeholder"); stack.set_visible_child_name("welcome_placeholder");
} else if (stack_state == StackState.NO_ACTIVE_ACCOUNTS) { } else if (stack_state == StackState.NO_ACTIVE_ACCOUNTS) {
stack.set_visible_child_name("accounts_placeholder"); stack.set_visible_child_name("accounts_placeholder");
} }
if (Util.use_csd()) {
set_titlebar(placeholder_headerbar);
}
} else if (stack_state == StackState.NO_ACTIVE_CONVERSATIONS) { } else if (stack_state == StackState.NO_ACTIVE_CONVERSATIONS) {
stack.set_visible_child_name("main"); stack.set_visible_child_name("main");
left_stack.set_visible_child_name("placeholder"); left_stack.set_visible_child_name("placeholder");
right_stack.set_visible_child_name("placeholder"); right_stack.set_visible_child_name("placeholder");
if (Util.use_csd()) {
set_titlebar(headerbar_paned);
}
} }
} }
@ -194,28 +176,24 @@ public class MainWindow : Gtk.Window {
public class WelcomePlaceholder : MainWindowPlaceholder { public class WelcomePlaceholder : MainWindowPlaceholder {
public WelcomePlaceholder() { public WelcomePlaceholder() {
title_label.label = _("Welcome to Dino!"); status_page.title = _("Welcome to Dino!");
label.label = _("Sign in or create an account to get started."); status_page.description = _("Sign in or create an account to get started.");
primary_button.label = _("Set up account"); primary_button.label = _("Set up account");
title_label.visible = true; primary_button.visible = true;
secondary_button.visible = false;
} }
} }
public class NoAccountsPlaceholder : MainWindowPlaceholder { public class NoAccountsPlaceholder : MainWindowPlaceholder {
public NoAccountsPlaceholder() { public NoAccountsPlaceholder() {
title_label.label = _("No active accounts"); status_page.title = _("No active accounts");
primary_button.label = _("Manage accounts"); primary_button.label = _("Manage accounts");
title_label.visible = true; primary_button.visible = true;
label.visible = false;
secondary_button.visible = false;
} }
} }
[GtkTemplate (ui = "/im/dino/Dino/unified_window_placeholder.ui")] [GtkTemplate (ui = "/im/dino/Dino/unified_window_placeholder.ui")]
public class MainWindowPlaceholder : Box { public class MainWindowPlaceholder : Box {
[GtkChild] public unowned Label title_label; [GtkChild] public unowned Adw.StatusPage status_page;
[GtkChild] public unowned Label label;
[GtkChild] public unowned Button primary_button; [GtkChild] public unowned Button primary_button;
[GtkChild] public unowned Button secondary_button; [GtkChild] public unowned Button secondary_button;
} }

View file

@ -45,10 +45,10 @@ public class MainWindowController : Object {
this.conversation_view_controller = new ConversationViewController(window.conversation_view, window.conversation_titlebar, stream_interactor); this.conversation_view_controller = new ConversationViewController(window.conversation_view, window.conversation_titlebar, stream_interactor);
conversation_view_controller.search_menu_entry.button.bind_property("active", window.search_revealer, "reveal_child", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL); conversation_view_controller.search_menu_entry.button.bind_property("active", window.search_flap, "reveal-flap", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL);
window.search_revealer.notify["child-revealed"].connect(() => { window.search_flap.notify["reveal-flap"].connect(() => {
if (window.search_revealer.child_revealed) { if (window.search_flap.reveal_flap) {
if (window.conversation_view.conversation_frame.conversation != null && window.global_search.search_entry.text == "") { if (window.conversation_view.conversation_frame.conversation != null && window.global_search.search_entry.text == "") {
reset_search_entry(); reset_search_entry();
} }
@ -59,7 +59,9 @@ public class MainWindowController : Object {
window.global_search.selected_item.connect((item) => { window.global_search.selected_item.connect((item) => {
select_conversation(item.conversation, false, false); select_conversation(item.conversation, false, false);
window.conversation_view.conversation_frame.initialize_around_message(item.conversation, item); window.conversation_view.conversation_frame.initialize_around_message(item.conversation, item);
if (window.search_flap.folded) {
close_search(); close_search();
}
}); });
window.welcome_placeholder.primary_button.clicked.connect(() => { window.welcome_placeholder.primary_button.clicked.connect(() => {
@ -91,16 +93,6 @@ public class MainWindowController : Object {
Widget window_widget = ((Widget) window); Widget window_widget = ((Widget) window);
GestureClick gesture_click_controller = new GestureClick();
window_widget.add_controller(gesture_click_controller);
gesture_click_controller.pressed.connect((n_press, click_x, click_y) => {
double search_x, search_y;
bool ret = window.search_revealer.translate_coordinates(window, 0, 0, out search_x, out search_y);
if (ret && click_x < search_x) {
close_search();
}
});
EventControllerKey key_event_controller = new EventControllerKey(); EventControllerKey key_event_controller = new EventControllerKey();
window_widget.add_controller(key_event_controller); window_widget.add_controller(key_event_controller);
// TODO GTK4: Why doesn't this work with key_pressed signal // TODO GTK4: Why doesn't this work with key_pressed signal

View file

@ -419,7 +419,8 @@ public string summarize_whitespaces_to_space(string s) {
try { try {
return (/\s+/).replace_literal(s, -1, 0, " "); return (/\s+/).replace_literal(s, -1, 0, " ");
} catch (RegexError e) { } catch (RegexError e) {
assert_not_reached(); critical("RegexError when summarizing whitespaces in '%s': %s", s, e.message);
return s;
} }
} }

View file

@ -1,184 +0,0 @@
using Gdk;
using Gtk;
namespace Dino.Ui {
class ScalingImage : Widget {
public int min_width { get; set; default = -1; }
public int target_width { get; set; default = -1; }
public int max_width { get; set; default = -1; }
public int min_height { get; set; default = -1; }
public int max_height { get; set; default = -1; }
private Pixbuf image;
private double image_ratio;
private int image_height = 0;
private int image_width = 0;
private int last_allocation_height = -1;
private int last_allocation_width = -1;
private int last_scale_factor = -1;
private Cairo.ImageSurface? cached_surface;
private static int8 use_image_surface = -1;
public void load(Pixbuf image) {
this.image = image;
this.image_ratio = ((double)image.height) / ((double)image.width);
this.image_height = image.height;
this.image_width = image.width;
queue_resize();
}
public override void dispose() {
base.dispose();
image = null;
cached_surface = null;
}
private void calculate_size(ref double exact_width, ref double exact_height) {
if (exact_width == -1 && exact_height == -1) {
if (target_width == -1) {
exact_width = ((double)image_width) / ((double)scale_factor);
exact_height = ((double)image_height) / ((double)scale_factor);
} else {
exact_width = target_width;
exact_height = exact_width * image_ratio;
}
} else if (exact_width != -1) {
exact_height = exact_width * image_ratio;
} else if (exact_height != -1) {
exact_width = exact_height / image_ratio;
} else {
if (exact_width * image_ratio > exact_height + scale_factor) {
exact_width = exact_height / image_ratio;
} else if (exact_height / image_ratio > exact_width + scale_factor) {
exact_height = exact_width * image_ratio;
}
}
if (max_width != -1 && exact_width > max_width) {
exact_width = max_width;
exact_height = exact_width * image_ratio;
}
if (max_height != -1 && exact_height > max_height) {
exact_height = max_height;
exact_width = exact_height / image_ratio;
}
if (exact_width < min_width) exact_width = min_width;
if (exact_height < min_height) exact_height = min_height;
}
public override void size_allocate(int width, int height, int baseline) {
if (max_width != -1) width = int.min(width, max_width);
if (max_height != -1) height = int.min(height, max_height);
height = int.max(height, min_height);
width = int.max(width, min_width);
double exact_width = width, exact_height = height;
calculate_size(ref exact_width, ref exact_height);
base.size_allocate(width, height, baseline);
if (last_allocation_height != height || last_allocation_width != width || last_scale_factor != scale_factor) {
last_allocation_height = height;
last_allocation_width = width;
last_scale_factor = scale_factor;
cached_surface = null;
}
}
public override void snapshot(Gtk.Snapshot snapshot) {
Cairo.Context context = snapshot.append_cairo(Graphene.Rect.alloc().init(0, 0, get_allocated_width(), get_allocated_height()));
draw(context);
}
public bool draw(Cairo.Context ctx_in) {
if (image == null) return false;
Cairo.Context ctx = ctx_in;
int width = this.get_allocated_width(), height = this.get_allocated_height(), base_factor = 1;
if (use_image_surface == -1) {
// TODO: detect if we have to buffer in image surface
use_image_surface = 1;
}
if (use_image_surface == 1) {
ctx_in.scale(1f / scale_factor, 1f / scale_factor);
if (cached_surface != null) {
ctx_in.set_source_surface(cached_surface, 0, 0);
ctx_in.paint();
ctx_in.set_source_rgb(0, 0, 0);
return true;
}
width *= scale_factor;
height *= scale_factor;
base_factor *= scale_factor;
cached_surface = new Cairo.ImageSurface(Cairo.Format.ARGB32, width, height);
ctx = new Cairo.Context(cached_surface);
}
double radius = 3 * base_factor;
double degrees = Math.PI / 180.0;
ctx.new_sub_path();
ctx.arc(width - radius, radius, radius, -90 * degrees, 0 * degrees);
ctx.arc(width - radius, height - radius, radius, 0 * degrees, 90 * degrees);
ctx.arc(radius, height - radius, radius, 90 * degrees, 180 * degrees);
ctx.arc(radius, radius, radius, 180 * degrees, 270 * degrees);
ctx.close_path();
ctx.clip();
Cairo.Surface buffer = sub_surface(ctx, width, height);
ctx.set_source_surface(buffer, 0, 0);
ctx.paint();
if (use_image_surface == 1) {
ctx_in.set_source_surface(ctx.get_target(), 0, 0);
ctx_in.paint();
ctx_in.set_source_rgb(0, 0, 0);
}
return true;
}
private Cairo.Surface sub_surface(Cairo.Context ctx, int width, int height) {
Cairo.Surface buffer = new Cairo.Surface.similar(ctx.get_target(), Cairo.Content.COLOR_ALPHA, width, height);
Cairo.Context bufctx = new Cairo.Context(buffer);
double w_scale = (double) width / image_width;
double h_scale = (double) height / image_height;
double scale = double.max(w_scale, h_scale);
bufctx.scale(scale, scale);
double x_off = 0, y_off = 0;
if (scale == h_scale) {
x_off = (width / scale - image_width) / 2.0;
} else {
y_off = (height / scale - image_height) / 2.0;
}
Gdk.cairo_set_source_pixbuf(bufctx, image, 0, 0);
bufctx.get_source().set_filter(Cairo.Filter.BILINEAR);
bufctx.paint();
bufctx.set_source_rgb(0, 0, 0);
return buffer;
}
public override void measure(Orientation orientation, int for_size, out int minimum, out int natural, out int minimum_baseline, out int natural_baseline) {
double natural_width = -1, natural_height = -1;
calculate_size(ref natural_width, ref natural_height);
if (orientation == Orientation.HORIZONTAL) {
natural = (int) Math.ceil(natural_width);
} else {
natural = (int) Math.ceil(natural_height);
}
if (for_size == -1) {
minimum = 0;
} else {
if (orientation == Orientation.HORIZONTAL) {
double exact_width = -1, exact_height = for_size;
calculate_size(ref exact_width, ref exact_height);
minimum = int.max((int)Math.floor(exact_width), min_width);
} else {
double exact_width = for_size, exact_height = -1;
calculate_size(ref exact_width, ref exact_height);
minimum = int.max((int)Math.floor(exact_height), min_height);
}
}
minimum_baseline = natural_baseline = -1;
}
public override SizeRequestMode get_request_mode() {
return SizeRequestMode.HEIGHT_FOR_WIDTH;
}
}
}

View file

@ -0,0 +1,88 @@
using Gdk;
using Gtk;
class Dino.Ui.FixedRatioPicture : Gtk.Widget {
public int min_width { get; set; default = -1; }
public int max_width { get; set; default = int.MAX; }
public int min_height { get; set; default = -1; }
public int max_height { get; set; default = int.MAX; }
public File file { get { return inner.file; } set { inner.file = value; } }
public Gdk.Paintable paintable { get { return inner.paintable; } set { inner.paintable = value; } }
#if GTK_4_8 && VALA_0_58
public Gtk.ContentFit content_fit { get { return inner.content_fit; } set { inner.content_fit = value; } }
#endif
private Gtk.Picture inner = new Gtk.Picture();
construct {
set_css_name("picture");
add_css_class("fixed-ratio");
inner.insert_after(this, null);
this.notify.connect(queue_resize);
}
private void measure_target_size(out int width, out int height) {
if (width_request != -1 && height_request != -1) {
width = width_request;
height = height_request;
return;
}
width = min_width;
height = min_height;
if (inner.should_layout()) {
int child_min = 0, child_nat = 0, child_min_baseline = -1, child_nat_baseline = -1;
inner.measure(Orientation.HORIZONTAL, -1, out child_min, out child_nat, out child_min_baseline, out child_nat_baseline);
width = int.max(child_nat, width);
}
width = int.min(width, max_width);
if (inner.should_layout()) {
int child_min = 0, child_nat = 0, child_min_baseline = -1, child_nat_baseline = -1;
inner.measure(Orientation.VERTICAL, width, out child_min, out child_nat, out child_min_baseline, out child_nat_baseline);
height = int.max(child_nat, height);
}
if (height > max_height) {
height = max_height;
width = min_width;
if (inner.should_layout()) {
int child_min = 0, child_nat = 0, child_min_baseline = -1, child_nat_baseline = -1;
inner.measure(Orientation.HORIZONTAL, max_height, out child_min, out child_nat, out child_min_baseline, out child_nat_baseline);
width = int.max(child_nat, width);
}
width = int.min(width, max_width);
}
}
public override void measure(Orientation orientation, int for_size, out int minimum, out int natural, out int minimum_baseline, out int natural_baseline) {
minimum_baseline = -1;
natural_baseline = -1;
int width, height;
measure_target_size(out width, out height);
if (orientation == Orientation.HORIZONTAL) {
minimum = min_width;
natural = width;
} else if (for_size == -1) {
minimum = min_height;
natural = height;
} else {
minimum = natural = height * for_size / width;
}
}
public override void size_allocate(int width, int height, int baseline) {
if (inner.should_layout()) {
inner.allocate(width, height, baseline, null);
}
}
public override SizeRequestMode get_request_mode() {
return SizeRequestMode.HEIGHT_FOR_WIDTH;
}
public override void dispose() {
inner.unparent();
base.dispose();
}
}

View file

@ -0,0 +1,59 @@
using Gtk;
public class Dino.Ui.NaturalSizeIncrease : Gtk.Widget {
public int min_natural_height { get; set; default = -1; }
public int min_natural_width { get; set; default = -1; }
construct {
this.notify.connect(queue_resize);
}
public override void measure(Orientation orientation, int for_size, out int minimum, out int natural, out int minimum_baseline, out int natural_baseline) {
minimum = 0;
if (orientation == Orientation.HORIZONTAL) {
natural = min_natural_width;
} else {
natural = min_natural_height;
}
natural = int.max(0, natural);
minimum_baseline = -1;
natural_baseline = -1;
Widget child = get_first_child();
while (child != null) {
if (child.should_layout()) {
int child_min = 0;
int child_nat = 0;
int child_min_baseline = -1;
int child_nat_baseline = -1;
child.measure(orientation, -1, out child_min, out child_nat, out child_min_baseline, out child_nat_baseline);
minimum = int.max(minimum, child_min);
natural = int.max(natural, child_nat);
if (child_min_baseline > 0) {
minimum_baseline = int.max(minimum_baseline, child_min_baseline);
}
if (child_nat_baseline > 0) {
natural_baseline = int.max(natural_baseline, child_nat_baseline);
}
}
child = child.get_next_sibling();
}
}
public override void size_allocate(int width, int height, int baseline) {
Widget child = get_first_child();
while (child != null) {
if (child.should_layout()) {
child.allocate(width, height, baseline, null);
}
child = child.get_next_sibling();
}
}
public override SizeRequestMode get_request_mode() {
Widget child = get_first_child();
if (child != null) {
return child.get_request_mode();
}
return SizeRequestMode.CONSTANT_SIZE;
}
}

View file

@ -241,7 +241,9 @@
<property name="margin-top">10</property> <property name="margin-top">10</property>
<property name="margin-bottom">10</property> <property name="margin-bottom">10</property>
<child> <child>
<object class="GtkImage" id="qrcode_image"/> <object class="GtkPicture" id="qrcode_picture">
<property name="can-shrink">False</property>
</object>
</child> </child>
</object> </object>
</property> </property>

View file

@ -20,7 +20,6 @@ lb
lt lt
nb nb
nl nl
nl_BE
oc oc
pl pl
pt pt

View file

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-02-12 22:06+0100\n" "POT-Creation-Date: 2023-01-28 14:28+0100\n"
"PO-Revision-Date: 2021-08-31 23:44+0000\n" "PO-Revision-Date: 2021-08-31 23:44+0000\n"
"Language-Team: Arabic <https://hosted.weblate.org/projects/dino/plugin-omemo/" "Language-Team: Arabic <https://hosted.weblate.org/projects/dino/plugin-omemo/"
"ar/>\n" "ar/>\n"
@ -36,39 +36,39 @@ msgid ""
"%s does not trust this device. That means, you might be missing messages." "%s does not trust this device. That means, you might be missing messages."
msgstr "%s لا يثق بهذا الجهاز. هذا يعني أنك قد تفقد بعض الرسائل." msgstr "%s لا يثق بهذا الجهاز. هذا يعني أنك قد تفقد بعض الرسائل."
#: plugins/omemo/src/ui/manage_key_dialog.vala:35 #: plugins/omemo/src/ui/manage_key_dialog.vala:34
msgid "Manage Key" msgid "Manage Key"
msgstr "إدارة المفتاح" msgstr "إدارة المفتاح"
#: plugins/omemo/src/ui/manage_key_dialog.vala:36 #: plugins/omemo/src/ui/manage_key_dialog.vala:35
msgid "" msgid ""
"Compare the fingerprint, character by character, with the one shown on your " "Compare the fingerprint, character by character, with the one shown on your "
"contact's device." "contact's device."
msgstr "قارن البصمة حرفا بحرف ، مع التي تظهر على جهاز مُراسِلك." msgstr "قارن البصمة حرفا بحرف ، مع التي تظهر على جهاز مُراسِلك."
#: plugins/omemo/src/ui/manage_key_dialog.vala:37 #: plugins/omemo/src/ui/manage_key_dialog.vala:36
msgid "Fingerprints differ" msgid "Fingerprints differ"
msgstr "البصمات غير متطابقة" msgstr "البصمات غير متطابقة"
#: plugins/omemo/src/ui/manage_key_dialog.vala:38 #: plugins/omemo/src/ui/manage_key_dialog.vala:37
msgid "Fingerprints match" msgid "Fingerprints match"
msgstr "البصمات متطابقة" msgstr "البصمات متطابقة"
#: plugins/omemo/src/ui/manage_key_dialog.vala:39 #: plugins/omemo/src/ui/manage_key_dialog.vala:38
#: plugins/omemo/src/ui/manage_key_dialog.vala:82 #: plugins/omemo/src/ui/manage_key_dialog.vala:81
#: plugins/omemo/src/ui/manage_key_dialog.vala:88 #: plugins/omemo/src/ui/manage_key_dialog.vala:87
msgid "Cancel" msgid "Cancel"
msgstr "ألغاء" msgstr "ألغاء"
#: plugins/omemo/src/ui/manage_key_dialog.vala:40 #: plugins/omemo/src/ui/manage_key_dialog.vala:39
msgid "Confirm" msgid "Confirm"
msgstr "تأكيد" msgstr "تأكيد"
#: plugins/omemo/src/ui/manage_key_dialog.vala:60 #: plugins/omemo/src/ui/manage_key_dialog.vala:59
msgid "Verify key" msgid "Verify key"
msgstr "التحقق مِن المفتاح" msgstr "التحقق مِن المفتاح"
#: plugins/omemo/src/ui/manage_key_dialog.vala:61 #: plugins/omemo/src/ui/manage_key_dialog.vala:60
#, c-format #, c-format
msgid "" msgid ""
"Future messages sent by %s from the device that uses this key will be " "Future messages sent by %s from the device that uses this key will be "
@ -77,11 +77,11 @@ msgstr ""
"سيتم تمييز الرسائل القادمة المرسلة بواسطة %s من الجهاز الذي يستخدم هذا " "سيتم تمييز الرسائل القادمة المرسلة بواسطة %s من الجهاز الذي يستخدم هذا "
"المفتاح وفقًا لذلك في نافذة الدردشة." "المفتاح وفقًا لذلك في نافذة الدردشة."
#: plugins/omemo/src/ui/manage_key_dialog.vala:71 #: plugins/omemo/src/ui/manage_key_dialog.vala:70
msgid "Fingerprints do not match" msgid "Fingerprints do not match"
msgstr "البصمات غير متطابقة" msgstr "البصمات غير متطابقة"
#: plugins/omemo/src/ui/manage_key_dialog.vala:72 #: plugins/omemo/src/ui/manage_key_dialog.vala:71
#, c-format #, c-format
msgid "" msgid ""
"Please verify that you are comparing the correct fingerprint. If " "Please verify that you are comparing the correct fingerprint. If "
@ -92,69 +92,69 @@ msgstr ""
"المحتمل أنّ حساب %s قد تعرض لاختراق وأنه مِن المستحسن التفكير في رفض هذا " "المحتمل أنّ حساب %s قد تعرض لاختراق وأنه مِن المستحسن التفكير في رفض هذا "
"المفتاح." "المفتاح."
#: plugins/omemo/src/ui/manage_key_dialog.vala:124 #: plugins/omemo/src/ui/manage_key_dialog.vala:123
msgid "Verify key fingerprint" msgid "Verify key fingerprint"
msgstr "التحقق مِن مفتاح البصمة" msgstr "التحقق مِن مفتاح البصمة"
#: plugins/omemo/src/ui/manage_key_dialog.vala:124 #: plugins/omemo/src/ui/manage_key_dialog.vala:123
msgid "" msgid ""
"Compare this key's fingerprint with the fingerprint displayed on the " "Compare this key's fingerprint with the fingerprint displayed on the "
"contact's device." "contact's device."
msgstr "قارن بصمة هذا المفتاح مع البصمة المعروضة على جهاز مُراسِلك." msgstr "قارن بصمة هذا المفتاح مع البصمة المعروضة على جهاز مُراسِلك."
#: plugins/omemo/src/ui/manage_key_dialog.vala:126 #: plugins/omemo/src/ui/manage_key_dialog.vala:125
#: plugins/omemo/src/ui/manage_key_dialog.vala:152 #: plugins/omemo/src/ui/manage_key_dialog.vala:151
#: plugins/omemo/src/ui/contact_details_dialog.vala:256 #: plugins/omemo/src/ui/contact_details_dialog.vala:269
msgid "Reject key" msgid "Reject key"
msgstr "رفض المفتاح" msgstr "رفض المفتاح"
#: plugins/omemo/src/ui/manage_key_dialog.vala:126 #: plugins/omemo/src/ui/manage_key_dialog.vala:125
msgid "" msgid ""
"Block encrypted communication with the contact's device that uses this key." "Block encrypted communication with the contact's device that uses this key."
msgstr "حظر الاتصال المشفر مع جهاز المراسل الذي يستخدم هذا المفتاح." msgstr "حظر الاتصال المشفر مع جهاز المراسل الذي يستخدم هذا المفتاح."
#: plugins/omemo/src/ui/manage_key_dialog.vala:128 #: plugins/omemo/src/ui/manage_key_dialog.vala:127
#: plugins/omemo/src/ui/manage_key_dialog.vala:160 #: plugins/omemo/src/ui/manage_key_dialog.vala:159
#: plugins/omemo/src/ui/contact_details_dialog.vala:251 #: plugins/omemo/src/ui/contact_details_dialog.vala:264
msgid "Accept key" msgid "Accept key"
msgstr "اقبل المفتاح" msgstr "اقبل المفتاح"
#: plugins/omemo/src/ui/manage_key_dialog.vala:128 #: plugins/omemo/src/ui/manage_key_dialog.vala:127
msgid "" msgid ""
"Allow encrypted communication with the contact's device that uses this key." "Allow encrypted communication with the contact's device that uses this key."
msgstr "السماح بالاتصال المشفر بجهاز المراسل الذي يستخدم هذا المفتاح." msgstr "السماح بالاتصال المشفر بجهاز المراسل الذي يستخدم هذا المفتاح."
#: plugins/omemo/src/ui/manage_key_dialog.vala:132 #: plugins/omemo/src/ui/manage_key_dialog.vala:131
#: plugins/omemo/src/ui/manage_key_dialog.vala:137 #: plugins/omemo/src/ui/manage_key_dialog.vala:136
#: plugins/omemo/src/ui/manage_key_dialog.vala:141 #: plugins/omemo/src/ui/manage_key_dialog.vala:140
#, c-format #, c-format
msgid "This key is currently %s." msgid "This key is currently %s."
msgstr "المفتاح الآن %s." msgstr "المفتاح الآن %s."
#: plugins/omemo/src/ui/manage_key_dialog.vala:132 #: plugins/omemo/src/ui/manage_key_dialog.vala:131
msgid "accepted" msgid "accepted"
msgstr "مقبول" msgstr "مقبول"
#: plugins/omemo/src/ui/manage_key_dialog.vala:132 #: plugins/omemo/src/ui/manage_key_dialog.vala:131
#: plugins/omemo/src/ui/manage_key_dialog.vala:137 #: plugins/omemo/src/ui/manage_key_dialog.vala:136
#, c-format #, c-format
msgid "This means it can be used by %s to receive and send encrypted messages." msgid "This means it can be used by %s to receive and send encrypted messages."
msgstr "ذلك يعني أنه بإمكان %s أن يستخدمه لتلقي وإرسال رسائل مشفرة." msgstr "ذلك يعني أنه بإمكان %s أن يستخدمه لتلقي وإرسال رسائل مشفرة."
#: plugins/omemo/src/ui/manage_key_dialog.vala:137 #: plugins/omemo/src/ui/manage_key_dialog.vala:136
msgid "verified" msgid "verified"
msgstr "تم التحقق منه" msgstr "تم التحقق منه"
#: plugins/omemo/src/ui/manage_key_dialog.vala:137 #: plugins/omemo/src/ui/manage_key_dialog.vala:136
msgid "" msgid ""
"Additionally it has been verified to match the key on the contact's device." "Additionally it has been verified to match the key on the contact's device."
msgstr "بالإضافة إلى أنه قد تم التحقق من تطابق المفتاح على جهاز المُراسِل." msgstr "بالإضافة إلى أنه قد تم التحقق من تطابق المفتاح على جهاز المُراسِل."
#: plugins/omemo/src/ui/manage_key_dialog.vala:141 #: plugins/omemo/src/ui/manage_key_dialog.vala:140
msgid "rejected" msgid "rejected"
msgstr "مرفوض" msgstr "مرفوض"
#: plugins/omemo/src/ui/manage_key_dialog.vala:141 #: plugins/omemo/src/ui/manage_key_dialog.vala:140
#, c-format #, c-format
msgid "" msgid ""
"This means it cannot be used by %s to decipher your messages, and you won't " "This means it cannot be used by %s to decipher your messages, and you won't "
@ -163,7 +163,7 @@ msgstr ""
"هذا يعني أنه لن يكون بمقدور %s استخدامه لفك تشفير رسائلك، ولن ترى الرسائل " "هذا يعني أنه لن يكون بمقدور %s استخدامه لفك تشفير رسائلك، ولن ترى الرسائل "
"المشفرة به." "المشفرة به."
#: plugins/omemo/src/ui/manage_key_dialog.vala:153 #: plugins/omemo/src/ui/manage_key_dialog.vala:152
#, c-format #, c-format
msgid "" msgid ""
"You won't see encrypted messages from the device of %s that uses this key. " "You won't see encrypted messages from the device of %s that uses this key. "
@ -172,7 +172,7 @@ msgstr ""
"لن ترى الرسائل المشفرة من جهاز %s الذي يستخدم هذا المفتاح. على العكس من " "لن ترى الرسائل المشفرة من جهاز %s الذي يستخدم هذا المفتاح. على العكس من "
"ذلك ، لن يتمكن هذا الجهاز من فك تشفير رسائلك بعد الآن." "ذلك ، لن يتمكن هذا الجهاز من فك تشفير رسائلك بعد الآن."
#: plugins/omemo/src/ui/manage_key_dialog.vala:161 #: plugins/omemo/src/ui/manage_key_dialog.vala:160
#, c-format #, c-format
msgid "" msgid ""
"You will be able to exchange encrypted messages with the device of %s that " "You will be able to exchange encrypted messages with the device of %s that "
@ -180,7 +180,7 @@ msgid ""
msgstr "" msgstr ""
"سوف يكون بمقدورك تبادل الرسائل المشفرة مع جهاز %s الذي يستخدم هذا المفتاح." "سوف يكون بمقدورك تبادل الرسائل المشفرة مع جهاز %s الذي يستخدم هذا المفتاح."
#: plugins/omemo/src/ui/manage_key_dialog.vala:167 #: plugins/omemo/src/ui/manage_key_dialog.vala:166
msgid "Back" msgid "Back"
msgstr "العودة" msgstr "العودة"
@ -192,15 +192,6 @@ msgstr "الإدارة"
msgid "This contact has new devices" msgid "This contact has new devices"
msgstr "لدى هذا المُراسِل أجهزة جديدة" msgstr "لدى هذا المُراسِل أجهزة جديدة"
#: plugins/omemo/src/ui/account_settings_widget.vala:42
#: plugins/omemo/src/ui/account_settings_widget.vala:45
msgid "Own fingerprint"
msgstr "بصمتك الخاصة"
#: plugins/omemo/src/ui/account_settings_widget.vala:42
msgid "Will be generated on first connection"
msgstr "سيتم توليدها عند أول اتصال"
#: plugins/omemo/src/ui/own_notifications.vala:29 #: plugins/omemo/src/ui/own_notifications.vala:29
msgid "OMEMO trust decision required" msgid "OMEMO trust decision required"
msgstr "مطلوب قرار ثقة مع OMEMO" msgstr "مطلوب قرار ثقة مع OMEMO"
@ -210,6 +201,15 @@ msgstr "مطلوب قرار ثقة مع OMEMO"
msgid "Did you add a new device for account %s?" msgid "Did you add a new device for account %s?"
msgstr "هل قمت بإضافة جهاز جديد على حساب %s؟" msgstr "هل قمت بإضافة جهاز جديد على حساب %s؟"
#: plugins/omemo/src/ui/account_settings_entry.vala:47
#: plugins/omemo/src/ui/account_settings_entry.vala:50
msgid "Own fingerprint"
msgstr "بصمتك الخاصة"
#: plugins/omemo/src/ui/account_settings_entry.vala:47
msgid "Will be generated on first connection"
msgstr "سيتم توليدها عند أول اتصال"
#: plugins/omemo/src/ui/contact_details_provider.vala:42 #: plugins/omemo/src/ui/contact_details_provider.vala:42
msgid "Encryption" msgid "Encryption"
msgstr "التشفير" msgstr "التشفير"
@ -225,52 +225,52 @@ msgstr[3] "%d أجهزة OMEMO"
msgstr[4] "%d جهاز OMEMO" msgstr[4] "%d جهاز OMEMO"
msgstr[5] "%d أجهزة OMEMO" msgstr[5] "%d أجهزة OMEMO"
#: plugins/omemo/src/ui/contact_details_dialog.vala:46 #: plugins/omemo/src/ui/contact_details_dialog.vala:48
msgid "OMEMO Key Management" msgid "OMEMO Key Management"
msgstr "إدارة مفاتيح أوميمو" msgstr "إدارة مفاتيح أوميمو"
#: plugins/omemo/src/ui/contact_details_dialog.vala:47 #: plugins/omemo/src/ui/contact_details_dialog.vala:49
msgid "Automatically accept new keys" msgid "Automatically accept new keys"
msgstr "تقبّل المفاتيح الجديدة تلقائياً" msgstr "تقبّل المفاتيح الجديدة تلقائياً"
#: plugins/omemo/src/ui/contact_details_dialog.vala:48 #: plugins/omemo/src/ui/contact_details_dialog.vala:50
msgid "New encryption keys from this contact will be accepted automatically." msgid "New encryption keys from this contact will be accepted automatically."
msgstr "سيتم قبول مفاتيح التشفير الجديدة الخاصة بهذا المراسل تلقائيًا." msgstr "سيتم قبول مفاتيح التشفير الجديدة الخاصة بهذا المراسل تلقائيًا."
#: plugins/omemo/src/ui/contact_details_dialog.vala:49 #: plugins/omemo/src/ui/contact_details_dialog.vala:51
msgid "Own key" msgid "Own key"
msgstr "مفتاحك الخاص" msgstr "مفتاحك الخاص"
#: plugins/omemo/src/ui/contact_details_dialog.vala:50 #: plugins/omemo/src/ui/contact_details_dialog.vala:52
msgid "New keys" msgid "New keys"
msgstr "المفاتيح الجديدة" msgstr "المفاتيح الجديدة"
#: plugins/omemo/src/ui/contact_details_dialog.vala:51 #: plugins/omemo/src/ui/contact_details_dialog.vala:53
msgid "Associated keys" msgid "Associated keys"
msgstr "المفاتيح المقترِنة" msgstr "المفاتيح المقترِنة"
#: plugins/omemo/src/ui/contact_details_dialog.vala:52 #: plugins/omemo/src/ui/contact_details_dialog.vala:54
msgid "Inactive keys" msgid "Inactive keys"
msgstr "المفاتيح غير المُنشَّطة" msgstr "المفاتيح غير المُنشَّطة"
#: plugins/omemo/src/ui/contact_details_dialog.vala:84 #: plugins/omemo/src/ui/contact_details_dialog.vala:86
msgid "" msgid ""
"New encryption keys from your other devices will be accepted automatically." "New encryption keys from your other devices will be accepted automatically."
msgstr "سيتم قبول مفاتيح التشفير الجديدة من أجهزتك الأخرى تلقائيًا." msgstr "سيتم قبول مفاتيح التشفير الجديدة من أجهزتك الأخرى تلقائيًا."
#: plugins/omemo/src/ui/contact_details_dialog.vala:319 #: plugins/omemo/src/ui/contact_details_dialog.vala:335
msgid "Accepted" msgid "Accepted"
msgstr "تم قبوله" msgstr "تم قبوله"
#: plugins/omemo/src/ui/contact_details_dialog.vala:324 #: plugins/omemo/src/ui/contact_details_dialog.vala:340
msgid "Rejected" msgid "Rejected"
msgstr "تم رفضه" msgstr "تم رفضه"
#: plugins/omemo/src/ui/contact_details_dialog.vala:329 #: plugins/omemo/src/ui/contact_details_dialog.vala:345
msgid "Verified" msgid "Verified"
msgstr "تم التحقق منه" msgstr "تم التحقق منه"
#: plugins/omemo/src/ui/contact_details_dialog.vala:336 #: plugins/omemo/src/ui/contact_details_dialog.vala:352
msgid "Unused" msgid "Unused"
msgstr "غير مستخدَم" msgstr "غير مستخدَم"

View file

@ -6,7 +6,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: dino-omemo 20180123\n" "Project-Id-Version: dino-omemo 20180123\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-02-12 22:06+0100\n" "POT-Creation-Date: 2023-01-28 14:28+0100\n"
"PO-Revision-Date: 2020-01-14 05:21+0000\n" "PO-Revision-Date: 2020-01-14 05:21+0000\n"
"Language-Team: Catalan <ca@dodds.net>\n" "Language-Team: Catalan <ca@dodds.net>\n"
"Language: ca\n" "Language: ca\n"
@ -33,11 +33,11 @@ msgid ""
"%s does not trust this device. That means, you might be missing messages." "%s does not trust this device. That means, you might be missing messages."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:35 #: plugins/omemo/src/ui/manage_key_dialog.vala:34
msgid "Manage Key" msgid "Manage Key"
msgstr "Gestiona la clau" msgstr "Gestiona la clau"
#: plugins/omemo/src/ui/manage_key_dialog.vala:36 #: plugins/omemo/src/ui/manage_key_dialog.vala:35
msgid "" msgid ""
"Compare the fingerprint, character by character, with the one shown on your " "Compare the fingerprint, character by character, with the one shown on your "
"contact's device." "contact's device."
@ -45,40 +45,40 @@ msgstr ""
"Compareu l'empremta, caràcter per caràcter, amb la que es mostra al vostre " "Compareu l'empremta, caràcter per caràcter, amb la que es mostra al vostre "
"dispositiu de contactes." "dispositiu de contactes."
#: plugins/omemo/src/ui/manage_key_dialog.vala:37 #: plugins/omemo/src/ui/manage_key_dialog.vala:36
msgid "Fingerprints differ" msgid "Fingerprints differ"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:38 #: plugins/omemo/src/ui/manage_key_dialog.vala:37
msgid "Fingerprints match" msgid "Fingerprints match"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:39 #: plugins/omemo/src/ui/manage_key_dialog.vala:38
#: plugins/omemo/src/ui/manage_key_dialog.vala:82 #: plugins/omemo/src/ui/manage_key_dialog.vala:81
#: plugins/omemo/src/ui/manage_key_dialog.vala:88 #: plugins/omemo/src/ui/manage_key_dialog.vala:87
msgid "Cancel" msgid "Cancel"
msgstr "Cancel·la" msgstr "Cancel·la"
#: plugins/omemo/src/ui/manage_key_dialog.vala:40 #: plugins/omemo/src/ui/manage_key_dialog.vala:39
msgid "Confirm" msgid "Confirm"
msgstr "Confirma" msgstr "Confirma"
#: plugins/omemo/src/ui/manage_key_dialog.vala:60 #: plugins/omemo/src/ui/manage_key_dialog.vala:59
msgid "Verify key" msgid "Verify key"
msgstr "Comproveu la clau" msgstr "Comproveu la clau"
#: plugins/omemo/src/ui/manage_key_dialog.vala:61 #: plugins/omemo/src/ui/manage_key_dialog.vala:60
#, c-format #, c-format
msgid "" msgid ""
"Future messages sent by %s from the device that uses this key will be " "Future messages sent by %s from the device that uses this key will be "
"highlighted accordingly in the chat window." "highlighted accordingly in the chat window."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:71 #: plugins/omemo/src/ui/manage_key_dialog.vala:70
msgid "Fingerprints do not match" msgid "Fingerprints do not match"
msgstr "Les empremtes no es corresponen" msgstr "Les empremtes no es corresponen"
#: plugins/omemo/src/ui/manage_key_dialog.vala:72 #: plugins/omemo/src/ui/manage_key_dialog.vala:71
#, c-format #, c-format
msgid "" msgid ""
"Please verify that you are comparing the correct fingerprint. If " "Please verify that you are comparing the correct fingerprint. If "
@ -89,91 +89,91 @@ msgstr ""
"coincideixen, el compte de %s podria trobar-se en perill i heu de considerar " "coincideixen, el compte de %s podria trobar-se en perill i heu de considerar "
"rebutjar aquesta clau." "rebutjar aquesta clau."
#: plugins/omemo/src/ui/manage_key_dialog.vala:124 #: plugins/omemo/src/ui/manage_key_dialog.vala:123
#, fuzzy #, fuzzy
msgid "Verify key fingerprint" msgid "Verify key fingerprint"
msgstr "Emprempta pròpia" msgstr "Emprempta pròpia"
#: plugins/omemo/src/ui/manage_key_dialog.vala:124 #: plugins/omemo/src/ui/manage_key_dialog.vala:123
msgid "" msgid ""
"Compare this key's fingerprint with the fingerprint displayed on the " "Compare this key's fingerprint with the fingerprint displayed on the "
"contact's device." "contact's device."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:126 #: plugins/omemo/src/ui/manage_key_dialog.vala:125
#: plugins/omemo/src/ui/manage_key_dialog.vala:152 #: plugins/omemo/src/ui/manage_key_dialog.vala:151
#: plugins/omemo/src/ui/contact_details_dialog.vala:256 #: plugins/omemo/src/ui/contact_details_dialog.vala:269
msgid "Reject key" msgid "Reject key"
msgstr "Rebutja la clau" msgstr "Rebutja la clau"
#: plugins/omemo/src/ui/manage_key_dialog.vala:126 #: plugins/omemo/src/ui/manage_key_dialog.vala:125
msgid "" msgid ""
"Block encrypted communication with the contact's device that uses this key." "Block encrypted communication with the contact's device that uses this key."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:128 #: plugins/omemo/src/ui/manage_key_dialog.vala:127
#: plugins/omemo/src/ui/manage_key_dialog.vala:160 #: plugins/omemo/src/ui/manage_key_dialog.vala:159
#: plugins/omemo/src/ui/contact_details_dialog.vala:251 #: plugins/omemo/src/ui/contact_details_dialog.vala:264
msgid "Accept key" msgid "Accept key"
msgstr "Accepta la clau" msgstr "Accepta la clau"
#: plugins/omemo/src/ui/manage_key_dialog.vala:128 #: plugins/omemo/src/ui/manage_key_dialog.vala:127
msgid "" msgid ""
"Allow encrypted communication with the contact's device that uses this key." "Allow encrypted communication with the contact's device that uses this key."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:132 #: plugins/omemo/src/ui/manage_key_dialog.vala:131
#: plugins/omemo/src/ui/manage_key_dialog.vala:137 #: plugins/omemo/src/ui/manage_key_dialog.vala:136
#: plugins/omemo/src/ui/manage_key_dialog.vala:141 #: plugins/omemo/src/ui/manage_key_dialog.vala:140
#, c-format #, c-format
msgid "This key is currently %s." msgid "This key is currently %s."
msgstr "Actualment, aquesta clau ha estat %s." msgstr "Actualment, aquesta clau ha estat %s."
#: plugins/omemo/src/ui/manage_key_dialog.vala:132 #: plugins/omemo/src/ui/manage_key_dialog.vala:131
msgid "accepted" msgid "accepted"
msgstr "acceptada" msgstr "acceptada"
#: plugins/omemo/src/ui/manage_key_dialog.vala:132 #: plugins/omemo/src/ui/manage_key_dialog.vala:131
#: plugins/omemo/src/ui/manage_key_dialog.vala:137 #: plugins/omemo/src/ui/manage_key_dialog.vala:136
#, c-format #, c-format
msgid "This means it can be used by %s to receive and send encrypted messages." msgid "This means it can be used by %s to receive and send encrypted messages."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:137 #: plugins/omemo/src/ui/manage_key_dialog.vala:136
msgid "verified" msgid "verified"
msgstr "verificada" msgstr "verificada"
#: plugins/omemo/src/ui/manage_key_dialog.vala:137 #: plugins/omemo/src/ui/manage_key_dialog.vala:136
msgid "" msgid ""
"Additionally it has been verified to match the key on the contact's device." "Additionally it has been verified to match the key on the contact's device."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:141 #: plugins/omemo/src/ui/manage_key_dialog.vala:140
msgid "rejected" msgid "rejected"
msgstr "rebutjada" msgstr "rebutjada"
#: plugins/omemo/src/ui/manage_key_dialog.vala:141 #: plugins/omemo/src/ui/manage_key_dialog.vala:140
#, c-format #, c-format
msgid "" msgid ""
"This means it cannot be used by %s to decipher your messages, and you won't " "This means it cannot be used by %s to decipher your messages, and you won't "
"see messages encrypted with it." "see messages encrypted with it."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:153 #: plugins/omemo/src/ui/manage_key_dialog.vala:152
#, c-format #, c-format
msgid "" msgid ""
"You won't see encrypted messages from the device of %s that uses this key. " "You won't see encrypted messages from the device of %s that uses this key. "
"Conversely, that device won't be able to decipher your messages anymore." "Conversely, that device won't be able to decipher your messages anymore."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:161 #: plugins/omemo/src/ui/manage_key_dialog.vala:160
#, c-format #, c-format
msgid "" msgid ""
"You will be able to exchange encrypted messages with the device of %s that " "You will be able to exchange encrypted messages with the device of %s that "
"uses this key." "uses this key."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:167 #: plugins/omemo/src/ui/manage_key_dialog.vala:166
msgid "Back" msgid "Back"
msgstr "Enrere" msgstr "Enrere"
@ -185,15 +185,6 @@ msgstr "Gestiona"
msgid "This contact has new devices" msgid "This contact has new devices"
msgstr "Aquest contacte té dispositius nous" msgstr "Aquest contacte té dispositius nous"
#: plugins/omemo/src/ui/account_settings_widget.vala:42
#: plugins/omemo/src/ui/account_settings_widget.vala:45
msgid "Own fingerprint"
msgstr "Empremta pròpia"
#: plugins/omemo/src/ui/account_settings_widget.vala:42
msgid "Will be generated on first connection"
msgstr "Es generarà durant la primera connexió"
#: plugins/omemo/src/ui/own_notifications.vala:29 #: plugins/omemo/src/ui/own_notifications.vala:29
msgid "OMEMO trust decision required" msgid "OMEMO trust decision required"
msgstr "" msgstr ""
@ -203,6 +194,15 @@ msgstr ""
msgid "Did you add a new device for account %s?" msgid "Did you add a new device for account %s?"
msgstr "Heu afegit un dispositiu nou per al compte %s?" msgstr "Heu afegit un dispositiu nou per al compte %s?"
#: plugins/omemo/src/ui/account_settings_entry.vala:47
#: plugins/omemo/src/ui/account_settings_entry.vala:50
msgid "Own fingerprint"
msgstr "Empremta pròpia"
#: plugins/omemo/src/ui/account_settings_entry.vala:47
msgid "Will be generated on first connection"
msgstr "Es generarà durant la primera connexió"
#: plugins/omemo/src/ui/contact_details_provider.vala:42 #: plugins/omemo/src/ui/contact_details_provider.vala:42
msgid "Encryption" msgid "Encryption"
msgstr "Xifratge" msgstr "Xifratge"
@ -214,52 +214,52 @@ msgid_plural "%d OMEMO devices"
msgstr[0] "%d dispositiu OMEMO" msgstr[0] "%d dispositiu OMEMO"
msgstr[1] "%d dispositius OMEMO" msgstr[1] "%d dispositius OMEMO"
#: plugins/omemo/src/ui/contact_details_dialog.vala:46 #: plugins/omemo/src/ui/contact_details_dialog.vala:48
msgid "OMEMO Key Management" msgid "OMEMO Key Management"
msgstr "Gestió de claus OMEMO" msgstr "Gestió de claus OMEMO"
#: plugins/omemo/src/ui/contact_details_dialog.vala:47 #: plugins/omemo/src/ui/contact_details_dialog.vala:49
msgid "Automatically accept new keys" msgid "Automatically accept new keys"
msgstr "Accepta claus noves automàticament" msgstr "Accepta claus noves automàticament"
#: plugins/omemo/src/ui/contact_details_dialog.vala:48 #: plugins/omemo/src/ui/contact_details_dialog.vala:50
msgid "New encryption keys from this contact will be accepted automatically." msgid "New encryption keys from this contact will be accepted automatically."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/contact_details_dialog.vala:49 #: plugins/omemo/src/ui/contact_details_dialog.vala:51
msgid "Own key" msgid "Own key"
msgstr "Clau pròpia" msgstr "Clau pròpia"
#: plugins/omemo/src/ui/contact_details_dialog.vala:50 #: plugins/omemo/src/ui/contact_details_dialog.vala:52
msgid "New keys" msgid "New keys"
msgstr "Claus noves" msgstr "Claus noves"
#: plugins/omemo/src/ui/contact_details_dialog.vala:51 #: plugins/omemo/src/ui/contact_details_dialog.vala:53
msgid "Associated keys" msgid "Associated keys"
msgstr "Claus associades" msgstr "Claus associades"
#: plugins/omemo/src/ui/contact_details_dialog.vala:52 #: plugins/omemo/src/ui/contact_details_dialog.vala:54
msgid "Inactive keys" msgid "Inactive keys"
msgstr "Claus inactives" msgstr "Claus inactives"
#: plugins/omemo/src/ui/contact_details_dialog.vala:84 #: plugins/omemo/src/ui/contact_details_dialog.vala:86
msgid "" msgid ""
"New encryption keys from your other devices will be accepted automatically." "New encryption keys from your other devices will be accepted automatically."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/contact_details_dialog.vala:319 #: plugins/omemo/src/ui/contact_details_dialog.vala:335
msgid "Accepted" msgid "Accepted"
msgstr "Acceptada" msgstr "Acceptada"
#: plugins/omemo/src/ui/contact_details_dialog.vala:324 #: plugins/omemo/src/ui/contact_details_dialog.vala:340
msgid "Rejected" msgid "Rejected"
msgstr "Rebutjada" msgstr "Rebutjada"
#: plugins/omemo/src/ui/contact_details_dialog.vala:329 #: plugins/omemo/src/ui/contact_details_dialog.vala:345
msgid "Verified" msgid "Verified"
msgstr "Verificada" msgstr "Verificada"
#: plugins/omemo/src/ui/contact_details_dialog.vala:336 #: plugins/omemo/src/ui/contact_details_dialog.vala:352
msgid "Unused" msgid "Unused"
msgstr "No utilitzada" msgstr "No utilitzada"

View file

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-02-12 22:06+0100\n" "POT-Creation-Date: 2023-01-28 14:28+0100\n"
"PO-Revision-Date: 2021-07-05 16:32+0000\n" "PO-Revision-Date: 2021-07-05 16:32+0000\n"
"Language-Team: none\n" "Language-Team: none\n"
"Language: cs\n" "Language: cs\n"
@ -37,11 +37,11 @@ msgid ""
msgstr "" msgstr ""
"%s nedůvěřuje tomuto zařízení. Z tohoto důvodu nemusí vidět některé zprávy." "%s nedůvěřuje tomuto zařízení. Z tohoto důvodu nemusí vidět některé zprávy."
#: plugins/omemo/src/ui/manage_key_dialog.vala:35 #: plugins/omemo/src/ui/manage_key_dialog.vala:34
msgid "Manage Key" msgid "Manage Key"
msgstr "Spravovat klíč" msgstr "Spravovat klíč"
#: plugins/omemo/src/ui/manage_key_dialog.vala:36 #: plugins/omemo/src/ui/manage_key_dialog.vala:35
msgid "" msgid ""
"Compare the fingerprint, character by character, with the one shown on your " "Compare the fingerprint, character by character, with the one shown on your "
"contact's device." "contact's device."
@ -49,29 +49,29 @@ msgstr ""
"Porovnejte otisk klíče, znak po znaku, s tím, který je zobrazen na zařízení " "Porovnejte otisk klíče, znak po znaku, s tím, který je zobrazen na zařízení "
"vašeho kontaktu." "vašeho kontaktu."
#: plugins/omemo/src/ui/manage_key_dialog.vala:37 #: plugins/omemo/src/ui/manage_key_dialog.vala:36
msgid "Fingerprints differ" msgid "Fingerprints differ"
msgstr "Otisky klíčů se liší" msgstr "Otisky klíčů se liší"
#: plugins/omemo/src/ui/manage_key_dialog.vala:38 #: plugins/omemo/src/ui/manage_key_dialog.vala:37
msgid "Fingerprints match" msgid "Fingerprints match"
msgstr "Otisky klíčů odpovídají" msgstr "Otisky klíčů odpovídají"
#: plugins/omemo/src/ui/manage_key_dialog.vala:39 #: plugins/omemo/src/ui/manage_key_dialog.vala:38
#: plugins/omemo/src/ui/manage_key_dialog.vala:82 #: plugins/omemo/src/ui/manage_key_dialog.vala:81
#: plugins/omemo/src/ui/manage_key_dialog.vala:88 #: plugins/omemo/src/ui/manage_key_dialog.vala:87
msgid "Cancel" msgid "Cancel"
msgstr "Zrušit" msgstr "Zrušit"
#: plugins/omemo/src/ui/manage_key_dialog.vala:40 #: plugins/omemo/src/ui/manage_key_dialog.vala:39
msgid "Confirm" msgid "Confirm"
msgstr "Potvrdit" msgstr "Potvrdit"
#: plugins/omemo/src/ui/manage_key_dialog.vala:60 #: plugins/omemo/src/ui/manage_key_dialog.vala:59
msgid "Verify key" msgid "Verify key"
msgstr "Ověřit klíč" msgstr "Ověřit klíč"
#: plugins/omemo/src/ui/manage_key_dialog.vala:61 #: plugins/omemo/src/ui/manage_key_dialog.vala:60
#, c-format #, c-format
msgid "" msgid ""
"Future messages sent by %s from the device that uses this key will be " "Future messages sent by %s from the device that uses this key will be "
@ -80,11 +80,11 @@ msgstr ""
"Budoucí zprávy, s odesílatelem %s, ze zařízení, které používá tento klíč, " "Budoucí zprávy, s odesílatelem %s, ze zařízení, které používá tento klíč, "
"budou odpovídajícím způsobem zvýrazněny v okně chatu." "budou odpovídajícím způsobem zvýrazněny v okně chatu."
#: plugins/omemo/src/ui/manage_key_dialog.vala:71 #: plugins/omemo/src/ui/manage_key_dialog.vala:70
msgid "Fingerprints do not match" msgid "Fingerprints do not match"
msgstr "Otisky klíčů se neshodují" msgstr "Otisky klíčů se neshodují"
#: plugins/omemo/src/ui/manage_key_dialog.vala:72 #: plugins/omemo/src/ui/manage_key_dialog.vala:71
#, c-format #, c-format
msgid "" msgid ""
"Please verify that you are comparing the correct fingerprint. If " "Please verify that you are comparing the correct fingerprint. If "
@ -94,76 +94,76 @@ msgstr ""
"Ověřte, zda porovnáváte správný otisk klíče. Pokud se otisky neshodují, účet " "Ověřte, zda porovnáváte správný otisk klíče. Pokud se otisky neshodují, účet "
"%s může být ohrožen a měli byste zvážit zamítnutí tohoto klíče." "%s může být ohrožen a měli byste zvážit zamítnutí tohoto klíče."
#: plugins/omemo/src/ui/manage_key_dialog.vala:124 #: plugins/omemo/src/ui/manage_key_dialog.vala:123
msgid "Verify key fingerprint" msgid "Verify key fingerprint"
msgstr "Ověření otisku klíče" msgstr "Ověření otisku klíče"
#: plugins/omemo/src/ui/manage_key_dialog.vala:124 #: plugins/omemo/src/ui/manage_key_dialog.vala:123
msgid "" msgid ""
"Compare this key's fingerprint with the fingerprint displayed on the " "Compare this key's fingerprint with the fingerprint displayed on the "
"contact's device." "contact's device."
msgstr "" msgstr ""
"Porovnejte otisk tohoto klíče s otiskem zobrazeným na zařízení kontaktu." "Porovnejte otisk tohoto klíče s otiskem zobrazeným na zařízení kontaktu."
#: plugins/omemo/src/ui/manage_key_dialog.vala:126 #: plugins/omemo/src/ui/manage_key_dialog.vala:125
#: plugins/omemo/src/ui/manage_key_dialog.vala:152 #: plugins/omemo/src/ui/manage_key_dialog.vala:151
#: plugins/omemo/src/ui/contact_details_dialog.vala:256 #: plugins/omemo/src/ui/contact_details_dialog.vala:269
msgid "Reject key" msgid "Reject key"
msgstr "Odmítnout klíč" msgstr "Odmítnout klíč"
#: plugins/omemo/src/ui/manage_key_dialog.vala:126 #: plugins/omemo/src/ui/manage_key_dialog.vala:125
msgid "" msgid ""
"Block encrypted communication with the contact's device that uses this key." "Block encrypted communication with the contact's device that uses this key."
msgstr "" msgstr ""
"Zablokujte šifrovanou komunikaci se zařízením kontaktu, které tento klíč " "Zablokujte šifrovanou komunikaci se zařízením kontaktu, které tento klíč "
"používá." "používá."
#: plugins/omemo/src/ui/manage_key_dialog.vala:128 #: plugins/omemo/src/ui/manage_key_dialog.vala:127
#: plugins/omemo/src/ui/manage_key_dialog.vala:160 #: plugins/omemo/src/ui/manage_key_dialog.vala:159
#: plugins/omemo/src/ui/contact_details_dialog.vala:251 #: plugins/omemo/src/ui/contact_details_dialog.vala:264
msgid "Accept key" msgid "Accept key"
msgstr "Přijmout klíč" msgstr "Přijmout klíč"
#: plugins/omemo/src/ui/manage_key_dialog.vala:128 #: plugins/omemo/src/ui/manage_key_dialog.vala:127
msgid "" msgid ""
"Allow encrypted communication with the contact's device that uses this key." "Allow encrypted communication with the contact's device that uses this key."
msgstr "" msgstr ""
"Povolit šifrovanou komunikaci se zařízením kontaktu, které používá tento " "Povolit šifrovanou komunikaci se zařízením kontaktu, které používá tento "
"klíč." "klíč."
#: plugins/omemo/src/ui/manage_key_dialog.vala:132 #: plugins/omemo/src/ui/manage_key_dialog.vala:131
#: plugins/omemo/src/ui/manage_key_dialog.vala:137 #: plugins/omemo/src/ui/manage_key_dialog.vala:136
#: plugins/omemo/src/ui/manage_key_dialog.vala:141 #: plugins/omemo/src/ui/manage_key_dialog.vala:140
#, c-format #, c-format
msgid "This key is currently %s." msgid "This key is currently %s."
msgstr "Tento klíč je v současné době %s." msgstr "Tento klíč je v současné době %s."
#: plugins/omemo/src/ui/manage_key_dialog.vala:132 #: plugins/omemo/src/ui/manage_key_dialog.vala:131
msgid "accepted" msgid "accepted"
msgstr "akceptován" msgstr "akceptován"
#: plugins/omemo/src/ui/manage_key_dialog.vala:132 #: plugins/omemo/src/ui/manage_key_dialog.vala:131
#: plugins/omemo/src/ui/manage_key_dialog.vala:137 #: plugins/omemo/src/ui/manage_key_dialog.vala:136
#, c-format #, c-format
msgid "This means it can be used by %s to receive and send encrypted messages." msgid "This means it can be used by %s to receive and send encrypted messages."
msgstr "" msgstr ""
"To znamená, že jej %s může používat k přijímání a odesílání šifrovaných " "To znamená, že jej %s může používat k přijímání a odesílání šifrovaných "
"zpráv." "zpráv."
#: plugins/omemo/src/ui/manage_key_dialog.vala:137 #: plugins/omemo/src/ui/manage_key_dialog.vala:136
msgid "verified" msgid "verified"
msgstr "ověřen" msgstr "ověřen"
#: plugins/omemo/src/ui/manage_key_dialog.vala:137 #: plugins/omemo/src/ui/manage_key_dialog.vala:136
msgid "" msgid ""
"Additionally it has been verified to match the key on the contact's device." "Additionally it has been verified to match the key on the contact's device."
msgstr "Navíc bylo ověřeno, že odpovídá klíči v zařízení kontaktu." msgstr "Navíc bylo ověřeno, že odpovídá klíči v zařízení kontaktu."
#: plugins/omemo/src/ui/manage_key_dialog.vala:141 #: plugins/omemo/src/ui/manage_key_dialog.vala:140
msgid "rejected" msgid "rejected"
msgstr "odmítnut" msgstr "odmítnut"
#: plugins/omemo/src/ui/manage_key_dialog.vala:141 #: plugins/omemo/src/ui/manage_key_dialog.vala:140
#, c-format #, c-format
msgid "" msgid ""
"This means it cannot be used by %s to decipher your messages, and you won't " "This means it cannot be used by %s to decipher your messages, and you won't "
@ -172,7 +172,7 @@ msgstr ""
"To znamená, že jej %s nemůže použít k dešifrování zpráv a vy neuvidíte " "To znamená, že jej %s nemůže použít k dešifrování zpráv a vy neuvidíte "
"zprávy šifrované tímto klíčem." "zprávy šifrované tímto klíčem."
#: plugins/omemo/src/ui/manage_key_dialog.vala:153 #: plugins/omemo/src/ui/manage_key_dialog.vala:152
#, c-format #, c-format
msgid "" msgid ""
"You won't see encrypted messages from the device of %s that uses this key. " "You won't see encrypted messages from the device of %s that uses this key. "
@ -181,7 +181,7 @@ msgstr ""
"Ze zařízení %s, které používá tento klíč, se šifrované zprávy nezobrazí. " "Ze zařízení %s, které používá tento klíč, se šifrované zprávy nezobrazí. "
"Toto zařízení už také nebude schopno rozluštit vaše zprávy." "Toto zařízení už také nebude schopno rozluštit vaše zprávy."
#: plugins/omemo/src/ui/manage_key_dialog.vala:161 #: plugins/omemo/src/ui/manage_key_dialog.vala:160
#, c-format #, c-format
msgid "" msgid ""
"You will be able to exchange encrypted messages with the device of %s that " "You will be able to exchange encrypted messages with the device of %s that "
@ -190,7 +190,7 @@ msgstr ""
"Budete si moci vyměňovat šifrované zprávy se zařízením %s, které tento klíč " "Budete si moci vyměňovat šifrované zprávy se zařízením %s, které tento klíč "
"používá." "používá."
#: plugins/omemo/src/ui/manage_key_dialog.vala:167 #: plugins/omemo/src/ui/manage_key_dialog.vala:166
msgid "Back" msgid "Back"
msgstr "Zpět" msgstr "Zpět"
@ -202,15 +202,6 @@ msgstr "Spravovat"
msgid "This contact has new devices" msgid "This contact has new devices"
msgstr "Tento kontakt má nová zařízení" msgstr "Tento kontakt má nová zařízení"
#: plugins/omemo/src/ui/account_settings_widget.vala:42
#: plugins/omemo/src/ui/account_settings_widget.vala:45
msgid "Own fingerprint"
msgstr "Otisk vlastního klíče"
#: plugins/omemo/src/ui/account_settings_widget.vala:42
msgid "Will be generated on first connection"
msgstr "Budou generovány při prvním připojení"
#: plugins/omemo/src/ui/own_notifications.vala:29 #: plugins/omemo/src/ui/own_notifications.vala:29
msgid "OMEMO trust decision required" msgid "OMEMO trust decision required"
msgstr "Vyžaduje se rozhodnutí o důvěře OMEMO" msgstr "Vyžaduje se rozhodnutí o důvěře OMEMO"
@ -220,6 +211,15 @@ msgstr "Vyžaduje se rozhodnutí o důvěře OMEMO"
msgid "Did you add a new device for account %s?" msgid "Did you add a new device for account %s?"
msgstr "Přidali jste nové zařízení pro účet %s?" msgstr "Přidali jste nové zařízení pro účet %s?"
#: plugins/omemo/src/ui/account_settings_entry.vala:47
#: plugins/omemo/src/ui/account_settings_entry.vala:50
msgid "Own fingerprint"
msgstr "Otisk vlastního klíče"
#: plugins/omemo/src/ui/account_settings_entry.vala:47
msgid "Will be generated on first connection"
msgstr "Budou generovány při prvním připojení"
#: plugins/omemo/src/ui/contact_details_provider.vala:42 #: plugins/omemo/src/ui/contact_details_provider.vala:42
msgid "Encryption" msgid "Encryption"
msgstr "Šifrování" msgstr "Šifrování"
@ -232,52 +232,52 @@ msgstr[0] "%d OMEMO zařízení"
msgstr[1] "%d OMEMO zařízení" msgstr[1] "%d OMEMO zařízení"
msgstr[2] "%d OMEMO zařízení" msgstr[2] "%d OMEMO zařízení"
#: plugins/omemo/src/ui/contact_details_dialog.vala:46 #: plugins/omemo/src/ui/contact_details_dialog.vala:48
msgid "OMEMO Key Management" msgid "OMEMO Key Management"
msgstr "OMEMO Správa klíčů" msgstr "OMEMO Správa klíčů"
#: plugins/omemo/src/ui/contact_details_dialog.vala:47 #: plugins/omemo/src/ui/contact_details_dialog.vala:49
msgid "Automatically accept new keys" msgid "Automatically accept new keys"
msgstr "Automaticky přijímat nové klíče" msgstr "Automaticky přijímat nové klíče"
#: plugins/omemo/src/ui/contact_details_dialog.vala:48 #: plugins/omemo/src/ui/contact_details_dialog.vala:50
msgid "New encryption keys from this contact will be accepted automatically." msgid "New encryption keys from this contact will be accepted automatically."
msgstr "Nové šifrovací klíče od tohoto kontaktu budou automaticky přijímány." msgstr "Nové šifrovací klíče od tohoto kontaktu budou automaticky přijímány."
#: plugins/omemo/src/ui/contact_details_dialog.vala:49 #: plugins/omemo/src/ui/contact_details_dialog.vala:51
msgid "Own key" msgid "Own key"
msgstr "Vlastní klíč" msgstr "Vlastní klíč"
#: plugins/omemo/src/ui/contact_details_dialog.vala:50 #: plugins/omemo/src/ui/contact_details_dialog.vala:52
msgid "New keys" msgid "New keys"
msgstr "Nové klíče" msgstr "Nové klíče"
#: plugins/omemo/src/ui/contact_details_dialog.vala:51 #: plugins/omemo/src/ui/contact_details_dialog.vala:53
msgid "Associated keys" msgid "Associated keys"
msgstr "Přidružené klíče" msgstr "Přidružené klíče"
#: plugins/omemo/src/ui/contact_details_dialog.vala:52 #: plugins/omemo/src/ui/contact_details_dialog.vala:54
msgid "Inactive keys" msgid "Inactive keys"
msgstr "Neaktivní klíče" msgstr "Neaktivní klíče"
#: plugins/omemo/src/ui/contact_details_dialog.vala:84 #: plugins/omemo/src/ui/contact_details_dialog.vala:86
msgid "" msgid ""
"New encryption keys from your other devices will be accepted automatically." "New encryption keys from your other devices will be accepted automatically."
msgstr "" msgstr ""
"Nové šifrovací klíče z vašich ostatních zařízení budou automaticky přijímány." "Nové šifrovací klíče z vašich ostatních zařízení budou automaticky přijímány."
#: plugins/omemo/src/ui/contact_details_dialog.vala:319 #: plugins/omemo/src/ui/contact_details_dialog.vala:335
msgid "Accepted" msgid "Accepted"
msgstr "Přijat" msgstr "Přijat"
#: plugins/omemo/src/ui/contact_details_dialog.vala:324 #: plugins/omemo/src/ui/contact_details_dialog.vala:340
msgid "Rejected" msgid "Rejected"
msgstr "Odmítnut" msgstr "Odmítnut"
#: plugins/omemo/src/ui/contact_details_dialog.vala:329 #: plugins/omemo/src/ui/contact_details_dialog.vala:345
msgid "Verified" msgid "Verified"
msgstr "Ověřen" msgstr "Ověřen"
#: plugins/omemo/src/ui/contact_details_dialog.vala:336 #: plugins/omemo/src/ui/contact_details_dialog.vala:352
msgid "Unused" msgid "Unused"
msgstr "Nepoužit" msgstr "Nepoužit"

View file

@ -2,7 +2,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: dino-omemo-0.0\n" "Project-Id-Version: dino-omemo-0.0\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-02-12 22:06+0100\n" "POT-Creation-Date: 2023-01-28 14:28+0100\n"
"PO-Revision-Date: 2020-10-10 10:49+0000\n" "PO-Revision-Date: 2020-10-10 10:49+0000\n"
"Language-Team: German <https://hosted.weblate.org/projects/dino/plugin-omemo/" "Language-Team: German <https://hosted.weblate.org/projects/dino/plugin-omemo/"
"de/>\n" "de/>\n"
@ -33,11 +33,11 @@ msgid ""
msgstr "" msgstr ""
"%s akzeptiert dieses Gerät nicht. Deshalb verpasst du vielleicht Nachrichten." "%s akzeptiert dieses Gerät nicht. Deshalb verpasst du vielleicht Nachrichten."
#: plugins/omemo/src/ui/manage_key_dialog.vala:35 #: plugins/omemo/src/ui/manage_key_dialog.vala:34
msgid "Manage Key" msgid "Manage Key"
msgstr "Schlüssel verwalten" msgstr "Schlüssel verwalten"
#: plugins/omemo/src/ui/manage_key_dialog.vala:36 #: plugins/omemo/src/ui/manage_key_dialog.vala:35
msgid "" msgid ""
"Compare the fingerprint, character by character, with the one shown on your " "Compare the fingerprint, character by character, with the one shown on your "
"contact's device." "contact's device."
@ -45,29 +45,29 @@ msgstr ""
"Vergleiche den Fingerabdruck, Zeichen für Zeichen, mit dem der auf dem Gerät " "Vergleiche den Fingerabdruck, Zeichen für Zeichen, mit dem der auf dem Gerät "
"deines Kontakts angezeigt wird." "deines Kontakts angezeigt wird."
#: plugins/omemo/src/ui/manage_key_dialog.vala:37 #: plugins/omemo/src/ui/manage_key_dialog.vala:36
msgid "Fingerprints differ" msgid "Fingerprints differ"
msgstr "Fingerabdrücke unterscheiden sich" msgstr "Fingerabdrücke unterscheiden sich"
#: plugins/omemo/src/ui/manage_key_dialog.vala:38 #: plugins/omemo/src/ui/manage_key_dialog.vala:37
msgid "Fingerprints match" msgid "Fingerprints match"
msgstr "Fingerabdrücke stimmen überein" msgstr "Fingerabdrücke stimmen überein"
#: plugins/omemo/src/ui/manage_key_dialog.vala:39 #: plugins/omemo/src/ui/manage_key_dialog.vala:38
#: plugins/omemo/src/ui/manage_key_dialog.vala:82 #: plugins/omemo/src/ui/manage_key_dialog.vala:81
#: plugins/omemo/src/ui/manage_key_dialog.vala:88 #: plugins/omemo/src/ui/manage_key_dialog.vala:87
msgid "Cancel" msgid "Cancel"
msgstr "Abbrechen" msgstr "Abbrechen"
#: plugins/omemo/src/ui/manage_key_dialog.vala:40 #: plugins/omemo/src/ui/manage_key_dialog.vala:39
msgid "Confirm" msgid "Confirm"
msgstr "Bestätigen" msgstr "Bestätigen"
#: plugins/omemo/src/ui/manage_key_dialog.vala:60 #: plugins/omemo/src/ui/manage_key_dialog.vala:59
msgid "Verify key" msgid "Verify key"
msgstr "Schlüssel verifizieren" msgstr "Schlüssel verifizieren"
#: plugins/omemo/src/ui/manage_key_dialog.vala:61 #: plugins/omemo/src/ui/manage_key_dialog.vala:60
#, c-format #, c-format
msgid "" msgid ""
"Future messages sent by %s from the device that uses this key will be " "Future messages sent by %s from the device that uses this key will be "
@ -76,11 +76,11 @@ msgstr ""
"Zukünftige Nachrichten, die von %s von dem Gerät gesendet werden, das diesen " "Zukünftige Nachrichten, die von %s von dem Gerät gesendet werden, das diesen "
"Schlüssel verwendet, werden im Chat-Fenster entsprechend hervorgehoben." "Schlüssel verwendet, werden im Chat-Fenster entsprechend hervorgehoben."
#: plugins/omemo/src/ui/manage_key_dialog.vala:71 #: plugins/omemo/src/ui/manage_key_dialog.vala:70
msgid "Fingerprints do not match" msgid "Fingerprints do not match"
msgstr "Fingerabdrücke stimmen nicht überein" msgstr "Fingerabdrücke stimmen nicht überein"
#: plugins/omemo/src/ui/manage_key_dialog.vala:72 #: plugins/omemo/src/ui/manage_key_dialog.vala:71
#, c-format #, c-format
msgid "" msgid ""
"Please verify that you are comparing the correct fingerprint. If " "Please verify that you are comparing the correct fingerprint. If "
@ -91,11 +91,11 @@ msgstr ""
"Fingerabdrücke nicht übereinstimmen, ist das Konto von %s möglicherweise " "Fingerabdrücke nicht übereinstimmen, ist das Konto von %s möglicherweise "
"kompromittiert und du solltest in Betracht ziehen, den Schlüssel abzulehnen." "kompromittiert und du solltest in Betracht ziehen, den Schlüssel abzulehnen."
#: plugins/omemo/src/ui/manage_key_dialog.vala:124 #: plugins/omemo/src/ui/manage_key_dialog.vala:123
msgid "Verify key fingerprint" msgid "Verify key fingerprint"
msgstr "Fingerabdruck überprüfen" msgstr "Fingerabdruck überprüfen"
#: plugins/omemo/src/ui/manage_key_dialog.vala:124 #: plugins/omemo/src/ui/manage_key_dialog.vala:123
msgid "" msgid ""
"Compare this key's fingerprint with the fingerprint displayed on the " "Compare this key's fingerprint with the fingerprint displayed on the "
"contact's device." "contact's device."
@ -103,67 +103,67 @@ msgstr ""
"Diesen Fingerabdruck mit dem Fingerabdruck vergleichen, der auf dem Gerät " "Diesen Fingerabdruck mit dem Fingerabdruck vergleichen, der auf dem Gerät "
"des Kontaktes angezeigt wird." "des Kontaktes angezeigt wird."
#: plugins/omemo/src/ui/manage_key_dialog.vala:126 #: plugins/omemo/src/ui/manage_key_dialog.vala:125
#: plugins/omemo/src/ui/manage_key_dialog.vala:152 #: plugins/omemo/src/ui/manage_key_dialog.vala:151
#: plugins/omemo/src/ui/contact_details_dialog.vala:256 #: plugins/omemo/src/ui/contact_details_dialog.vala:269
msgid "Reject key" msgid "Reject key"
msgstr "Schlüssel ablehnen" msgstr "Schlüssel ablehnen"
#: plugins/omemo/src/ui/manage_key_dialog.vala:126 #: plugins/omemo/src/ui/manage_key_dialog.vala:125
msgid "" msgid ""
"Block encrypted communication with the contact's device that uses this key." "Block encrypted communication with the contact's device that uses this key."
msgstr "" msgstr ""
"Blockiert die verschlüsselte Kommunikation mit dem Gerät des Kontakts, das " "Blockiert die verschlüsselte Kommunikation mit dem Gerät des Kontakts, das "
"diesen Schlüssel verwendet." "diesen Schlüssel verwendet."
#: plugins/omemo/src/ui/manage_key_dialog.vala:128 #: plugins/omemo/src/ui/manage_key_dialog.vala:127
#: plugins/omemo/src/ui/manage_key_dialog.vala:160 #: plugins/omemo/src/ui/manage_key_dialog.vala:159
#: plugins/omemo/src/ui/contact_details_dialog.vala:251 #: plugins/omemo/src/ui/contact_details_dialog.vala:264
msgid "Accept key" msgid "Accept key"
msgstr "Schlüssel akzeptieren" msgstr "Schlüssel akzeptieren"
#: plugins/omemo/src/ui/manage_key_dialog.vala:128 #: plugins/omemo/src/ui/manage_key_dialog.vala:127
msgid "" msgid ""
"Allow encrypted communication with the contact's device that uses this key." "Allow encrypted communication with the contact's device that uses this key."
msgstr "" msgstr ""
"Erlaubt die verschlüsselte Kommunikation mit dem Gerät des Kontakts, das " "Erlaubt die verschlüsselte Kommunikation mit dem Gerät des Kontakts, das "
"diesen Schlüssel verwendet." "diesen Schlüssel verwendet."
#: plugins/omemo/src/ui/manage_key_dialog.vala:132 #: plugins/omemo/src/ui/manage_key_dialog.vala:131
#: plugins/omemo/src/ui/manage_key_dialog.vala:137 #: plugins/omemo/src/ui/manage_key_dialog.vala:136
#: plugins/omemo/src/ui/manage_key_dialog.vala:141 #: plugins/omemo/src/ui/manage_key_dialog.vala:140
#, c-format #, c-format
msgid "This key is currently %s." msgid "This key is currently %s."
msgstr "Dieser Schlüssel ist aktuell %s." msgstr "Dieser Schlüssel ist aktuell %s."
#: plugins/omemo/src/ui/manage_key_dialog.vala:132 #: plugins/omemo/src/ui/manage_key_dialog.vala:131
msgid "accepted" msgid "accepted"
msgstr "akzeptiert" msgstr "akzeptiert"
#: plugins/omemo/src/ui/manage_key_dialog.vala:132 #: plugins/omemo/src/ui/manage_key_dialog.vala:131
#: plugins/omemo/src/ui/manage_key_dialog.vala:137 #: plugins/omemo/src/ui/manage_key_dialog.vala:136
#, c-format #, c-format
msgid "This means it can be used by %s to receive and send encrypted messages." msgid "This means it can be used by %s to receive and send encrypted messages."
msgstr "" msgstr ""
"Das bedeutet, er kann von %s zum Empfangen und Senden verschlüsselter " "Das bedeutet, er kann von %s zum Empfangen und Senden verschlüsselter "
"Nachrichten verwendet werden." "Nachrichten verwendet werden."
#: plugins/omemo/src/ui/manage_key_dialog.vala:137 #: plugins/omemo/src/ui/manage_key_dialog.vala:136
msgid "verified" msgid "verified"
msgstr "überprüft" msgstr "überprüft"
#: plugins/omemo/src/ui/manage_key_dialog.vala:137 #: plugins/omemo/src/ui/manage_key_dialog.vala:136
msgid "" msgid ""
"Additionally it has been verified to match the key on the contact's device." "Additionally it has been verified to match the key on the contact's device."
msgstr "" msgstr ""
"Darüber hinaus wurde überprüft, dass er mit dem Schlüssel auf dem Gerät des " "Darüber hinaus wurde überprüft, dass er mit dem Schlüssel auf dem Gerät des "
"Kontaktes übereinstimmt." "Kontaktes übereinstimmt."
#: plugins/omemo/src/ui/manage_key_dialog.vala:141 #: plugins/omemo/src/ui/manage_key_dialog.vala:140
msgid "rejected" msgid "rejected"
msgstr "abgelehnt" msgstr "abgelehnt"
#: plugins/omemo/src/ui/manage_key_dialog.vala:141 #: plugins/omemo/src/ui/manage_key_dialog.vala:140
#, c-format #, c-format
msgid "" msgid ""
"This means it cannot be used by %s to decipher your messages, and you won't " "This means it cannot be used by %s to decipher your messages, and you won't "
@ -172,7 +172,7 @@ msgstr ""
"Das bedeutet %s kann ihn nicht benutzen, um deine Nachrichten zu " "Das bedeutet %s kann ihn nicht benutzen, um deine Nachrichten zu "
"entschlüsseln, und du wirst damit verschlüsselte Nachrichten nicht sehen." "entschlüsseln, und du wirst damit verschlüsselte Nachrichten nicht sehen."
#: plugins/omemo/src/ui/manage_key_dialog.vala:153 #: plugins/omemo/src/ui/manage_key_dialog.vala:152
#, c-format #, c-format
msgid "" msgid ""
"You won't see encrypted messages from the device of %s that uses this key. " "You won't see encrypted messages from the device of %s that uses this key. "
@ -182,7 +182,7 @@ msgstr ""
"Schlüssel benutzt nicht mehr sehen. Umgekehrt kann dieses Gerät deine " "Schlüssel benutzt nicht mehr sehen. Umgekehrt kann dieses Gerät deine "
"Nachrichten nicht mehr entschlüsseln." "Nachrichten nicht mehr entschlüsseln."
#: plugins/omemo/src/ui/manage_key_dialog.vala:161 #: plugins/omemo/src/ui/manage_key_dialog.vala:160
#, c-format #, c-format
msgid "" msgid ""
"You will be able to exchange encrypted messages with the device of %s that " "You will be able to exchange encrypted messages with the device of %s that "
@ -191,7 +191,7 @@ msgstr ""
"Du wirst verschlüsselte Nachrichten mit dem Gerät von %s, welches diesen " "Du wirst verschlüsselte Nachrichten mit dem Gerät von %s, welches diesen "
"Schlüssel verwendet, austauschen können." "Schlüssel verwendet, austauschen können."
#: plugins/omemo/src/ui/manage_key_dialog.vala:167 #: plugins/omemo/src/ui/manage_key_dialog.vala:166
msgid "Back" msgid "Back"
msgstr "Zurück" msgstr "Zurück"
@ -203,15 +203,6 @@ msgstr "Verwalten"
msgid "This contact has new devices" msgid "This contact has new devices"
msgstr "Dieser Kontakt hat neue Geräte" msgstr "Dieser Kontakt hat neue Geräte"
#: plugins/omemo/src/ui/account_settings_widget.vala:42
#: plugins/omemo/src/ui/account_settings_widget.vala:45
msgid "Own fingerprint"
msgstr "Eigener Fingerabdruck"
#: plugins/omemo/src/ui/account_settings_widget.vala:42
msgid "Will be generated on first connection"
msgstr "Wird beim ersten Verbinden erzeugt"
#: plugins/omemo/src/ui/own_notifications.vala:29 #: plugins/omemo/src/ui/own_notifications.vala:29
msgid "OMEMO trust decision required" msgid "OMEMO trust decision required"
msgstr "OMEMO-Vertrauensentscheidung erforderlich" msgstr "OMEMO-Vertrauensentscheidung erforderlich"
@ -221,6 +212,15 @@ msgstr "OMEMO-Vertrauensentscheidung erforderlich"
msgid "Did you add a new device for account %s?" msgid "Did you add a new device for account %s?"
msgstr "Hast du ein neues Gerät für deinen Account %s hinzugefügt?" msgstr "Hast du ein neues Gerät für deinen Account %s hinzugefügt?"
#: plugins/omemo/src/ui/account_settings_entry.vala:47
#: plugins/omemo/src/ui/account_settings_entry.vala:50
msgid "Own fingerprint"
msgstr "Eigener Fingerabdruck"
#: plugins/omemo/src/ui/account_settings_entry.vala:47
msgid "Will be generated on first connection"
msgstr "Wird beim ersten Verbinden erzeugt"
#: plugins/omemo/src/ui/contact_details_provider.vala:42 #: plugins/omemo/src/ui/contact_details_provider.vala:42
msgid "Encryption" msgid "Encryption"
msgstr "Verschlüsselung" msgstr "Verschlüsselung"
@ -232,53 +232,53 @@ msgid_plural "%d OMEMO devices"
msgstr[0] "%d OMEMO Gerät" msgstr[0] "%d OMEMO Gerät"
msgstr[1] "%d OMEMO Geräte" msgstr[1] "%d OMEMO Geräte"
#: plugins/omemo/src/ui/contact_details_dialog.vala:46 #: plugins/omemo/src/ui/contact_details_dialog.vala:48
msgid "OMEMO Key Management" msgid "OMEMO Key Management"
msgstr "OMEMO-Schlüssel Verwaltung" msgstr "OMEMO-Schlüssel Verwaltung"
#: plugins/omemo/src/ui/contact_details_dialog.vala:47 #: plugins/omemo/src/ui/contact_details_dialog.vala:49
msgid "Automatically accept new keys" msgid "Automatically accept new keys"
msgstr "Neue Schlüssel automatisch akzeptieren" msgstr "Neue Schlüssel automatisch akzeptieren"
#: plugins/omemo/src/ui/contact_details_dialog.vala:48 #: plugins/omemo/src/ui/contact_details_dialog.vala:50
msgid "New encryption keys from this contact will be accepted automatically." msgid "New encryption keys from this contact will be accepted automatically."
msgstr "Neue Schlüssel von diesem Kontakt werden automatisch akzeptiert." msgstr "Neue Schlüssel von diesem Kontakt werden automatisch akzeptiert."
#: plugins/omemo/src/ui/contact_details_dialog.vala:49 #: plugins/omemo/src/ui/contact_details_dialog.vala:51
msgid "Own key" msgid "Own key"
msgstr "Eigener Schlüssel" msgstr "Eigener Schlüssel"
#: plugins/omemo/src/ui/contact_details_dialog.vala:50 #: plugins/omemo/src/ui/contact_details_dialog.vala:52
msgid "New keys" msgid "New keys"
msgstr "Neue Schlüssel" msgstr "Neue Schlüssel"
#: plugins/omemo/src/ui/contact_details_dialog.vala:51 #: plugins/omemo/src/ui/contact_details_dialog.vala:53
msgid "Associated keys" msgid "Associated keys"
msgstr "Zugehörige Schlüssel" msgstr "Zugehörige Schlüssel"
#: plugins/omemo/src/ui/contact_details_dialog.vala:52 #: plugins/omemo/src/ui/contact_details_dialog.vala:54
msgid "Inactive keys" msgid "Inactive keys"
msgstr "Inaktive Schlüssel" msgstr "Inaktive Schlüssel"
#: plugins/omemo/src/ui/contact_details_dialog.vala:84 #: plugins/omemo/src/ui/contact_details_dialog.vala:86
msgid "" msgid ""
"New encryption keys from your other devices will be accepted automatically." "New encryption keys from your other devices will be accepted automatically."
msgstr "" msgstr ""
"Neue Schlüssel von deinen anderen Geräten werden automatisch akzeptiert." "Neue Schlüssel von deinen anderen Geräten werden automatisch akzeptiert."
#: plugins/omemo/src/ui/contact_details_dialog.vala:319 #: plugins/omemo/src/ui/contact_details_dialog.vala:335
msgid "Accepted" msgid "Accepted"
msgstr "Akzeptiert" msgstr "Akzeptiert"
#: plugins/omemo/src/ui/contact_details_dialog.vala:324 #: plugins/omemo/src/ui/contact_details_dialog.vala:340
msgid "Rejected" msgid "Rejected"
msgstr "Zurückgewiesen" msgstr "Zurückgewiesen"
#: plugins/omemo/src/ui/contact_details_dialog.vala:329 #: plugins/omemo/src/ui/contact_details_dialog.vala:345
msgid "Verified" msgid "Verified"
msgstr "Verifiziert" msgstr "Verifiziert"
#: plugins/omemo/src/ui/contact_details_dialog.vala:336 #: plugins/omemo/src/ui/contact_details_dialog.vala:352
msgid "Unused" msgid "Unused"
msgstr "Unbenutzt" msgstr "Unbenutzt"

View file

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-02-12 22:06+0100\n" "POT-Creation-Date: 2023-01-28 14:28+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -35,50 +35,50 @@ msgid ""
"%s does not trust this device. That means, you might be missing messages." "%s does not trust this device. That means, you might be missing messages."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:35 #: plugins/omemo/src/ui/manage_key_dialog.vala:34
msgid "Manage Key" msgid "Manage Key"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:36 #: plugins/omemo/src/ui/manage_key_dialog.vala:35
msgid "" msgid ""
"Compare the fingerprint, character by character, with the one shown on your " "Compare the fingerprint, character by character, with the one shown on your "
"contact's device." "contact's device."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:37 #: plugins/omemo/src/ui/manage_key_dialog.vala:36
msgid "Fingerprints differ" msgid "Fingerprints differ"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:38 #: plugins/omemo/src/ui/manage_key_dialog.vala:37
msgid "Fingerprints match" msgid "Fingerprints match"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:39 #: plugins/omemo/src/ui/manage_key_dialog.vala:38
#: plugins/omemo/src/ui/manage_key_dialog.vala:82 #: plugins/omemo/src/ui/manage_key_dialog.vala:81
#: plugins/omemo/src/ui/manage_key_dialog.vala:88 #: plugins/omemo/src/ui/manage_key_dialog.vala:87
msgid "Cancel" msgid "Cancel"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:40 #: plugins/omemo/src/ui/manage_key_dialog.vala:39
msgid "Confirm" msgid "Confirm"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:60 #: plugins/omemo/src/ui/manage_key_dialog.vala:59
msgid "Verify key" msgid "Verify key"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:61 #: plugins/omemo/src/ui/manage_key_dialog.vala:60
#, c-format #, c-format
msgid "" msgid ""
"Future messages sent by %s from the device that uses this key will be " "Future messages sent by %s from the device that uses this key will be "
"highlighted accordingly in the chat window." "highlighted accordingly in the chat window."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:71 #: plugins/omemo/src/ui/manage_key_dialog.vala:70
msgid "Fingerprints do not match" msgid "Fingerprints do not match"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:72 #: plugins/omemo/src/ui/manage_key_dialog.vala:71
#, c-format #, c-format
msgid "" msgid ""
"Please verify that you are comparing the correct fingerprint. If " "Please verify that you are comparing the correct fingerprint. If "
@ -86,90 +86,90 @@ msgid ""
"consider rejecting this key." "consider rejecting this key."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:124 #: plugins/omemo/src/ui/manage_key_dialog.vala:123
msgid "Verify key fingerprint" msgid "Verify key fingerprint"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:124 #: plugins/omemo/src/ui/manage_key_dialog.vala:123
msgid "" msgid ""
"Compare this key's fingerprint with the fingerprint displayed on the " "Compare this key's fingerprint with the fingerprint displayed on the "
"contact's device." "contact's device."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:126 #: plugins/omemo/src/ui/manage_key_dialog.vala:125
#: plugins/omemo/src/ui/manage_key_dialog.vala:152 #: plugins/omemo/src/ui/manage_key_dialog.vala:151
#: plugins/omemo/src/ui/contact_details_dialog.vala:256 #: plugins/omemo/src/ui/contact_details_dialog.vala:269
msgid "Reject key" msgid "Reject key"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:126 #: plugins/omemo/src/ui/manage_key_dialog.vala:125
msgid "" msgid ""
"Block encrypted communication with the contact's device that uses this key." "Block encrypted communication with the contact's device that uses this key."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:128 #: plugins/omemo/src/ui/manage_key_dialog.vala:127
#: plugins/omemo/src/ui/manage_key_dialog.vala:160 #: plugins/omemo/src/ui/manage_key_dialog.vala:159
#: plugins/omemo/src/ui/contact_details_dialog.vala:251 #: plugins/omemo/src/ui/contact_details_dialog.vala:264
msgid "Accept key" msgid "Accept key"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:128 #: plugins/omemo/src/ui/manage_key_dialog.vala:127
msgid "" msgid ""
"Allow encrypted communication with the contact's device that uses this key." "Allow encrypted communication with the contact's device that uses this key."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:132 #: plugins/omemo/src/ui/manage_key_dialog.vala:131
#: plugins/omemo/src/ui/manage_key_dialog.vala:137 #: plugins/omemo/src/ui/manage_key_dialog.vala:136
#: plugins/omemo/src/ui/manage_key_dialog.vala:141 #: plugins/omemo/src/ui/manage_key_dialog.vala:140
#, c-format #, c-format
msgid "This key is currently %s." msgid "This key is currently %s."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:132 #: plugins/omemo/src/ui/manage_key_dialog.vala:131
msgid "accepted" msgid "accepted"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:132 #: plugins/omemo/src/ui/manage_key_dialog.vala:131
#: plugins/omemo/src/ui/manage_key_dialog.vala:137 #: plugins/omemo/src/ui/manage_key_dialog.vala:136
#, c-format #, c-format
msgid "This means it can be used by %s to receive and send encrypted messages." msgid "This means it can be used by %s to receive and send encrypted messages."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:137 #: plugins/omemo/src/ui/manage_key_dialog.vala:136
msgid "verified" msgid "verified"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:137 #: plugins/omemo/src/ui/manage_key_dialog.vala:136
msgid "" msgid ""
"Additionally it has been verified to match the key on the contact's device." "Additionally it has been verified to match the key on the contact's device."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:141 #: plugins/omemo/src/ui/manage_key_dialog.vala:140
msgid "rejected" msgid "rejected"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:141 #: plugins/omemo/src/ui/manage_key_dialog.vala:140
#, c-format #, c-format
msgid "" msgid ""
"This means it cannot be used by %s to decipher your messages, and you won't " "This means it cannot be used by %s to decipher your messages, and you won't "
"see messages encrypted with it." "see messages encrypted with it."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:153 #: plugins/omemo/src/ui/manage_key_dialog.vala:152
#, c-format #, c-format
msgid "" msgid ""
"You won't see encrypted messages from the device of %s that uses this key. " "You won't see encrypted messages from the device of %s that uses this key. "
"Conversely, that device won't be able to decipher your messages anymore." "Conversely, that device won't be able to decipher your messages anymore."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:161 #: plugins/omemo/src/ui/manage_key_dialog.vala:160
#, c-format #, c-format
msgid "" msgid ""
"You will be able to exchange encrypted messages with the device of %s that " "You will be able to exchange encrypted messages with the device of %s that "
"uses this key." "uses this key."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:167 #: plugins/omemo/src/ui/manage_key_dialog.vala:166
msgid "Back" msgid "Back"
msgstr "" msgstr ""
@ -181,15 +181,6 @@ msgstr ""
msgid "This contact has new devices" msgid "This contact has new devices"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/account_settings_widget.vala:42
#: plugins/omemo/src/ui/account_settings_widget.vala:45
msgid "Own fingerprint"
msgstr ""
#: plugins/omemo/src/ui/account_settings_widget.vala:42
msgid "Will be generated on first connection"
msgstr ""
#: plugins/omemo/src/ui/own_notifications.vala:29 #: plugins/omemo/src/ui/own_notifications.vala:29
msgid "OMEMO trust decision required" msgid "OMEMO trust decision required"
msgstr "" msgstr ""
@ -199,6 +190,15 @@ msgstr ""
msgid "Did you add a new device for account %s?" msgid "Did you add a new device for account %s?"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/account_settings_entry.vala:47
#: plugins/omemo/src/ui/account_settings_entry.vala:50
msgid "Own fingerprint"
msgstr ""
#: plugins/omemo/src/ui/account_settings_entry.vala:47
msgid "Will be generated on first connection"
msgstr ""
#: plugins/omemo/src/ui/contact_details_provider.vala:42 #: plugins/omemo/src/ui/contact_details_provider.vala:42
msgid "Encryption" msgid "Encryption"
msgstr "" msgstr ""
@ -210,51 +210,51 @@ msgid_plural "%d OMEMO devices"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#: plugins/omemo/src/ui/contact_details_dialog.vala:46 #: plugins/omemo/src/ui/contact_details_dialog.vala:48
msgid "OMEMO Key Management" msgid "OMEMO Key Management"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/contact_details_dialog.vala:47 #: plugins/omemo/src/ui/contact_details_dialog.vala:49
msgid "Automatically accept new keys" msgid "Automatically accept new keys"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/contact_details_dialog.vala:48 #: plugins/omemo/src/ui/contact_details_dialog.vala:50
msgid "New encryption keys from this contact will be accepted automatically." msgid "New encryption keys from this contact will be accepted automatically."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/contact_details_dialog.vala:49 #: plugins/omemo/src/ui/contact_details_dialog.vala:51
msgid "Own key" msgid "Own key"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/contact_details_dialog.vala:50 #: plugins/omemo/src/ui/contact_details_dialog.vala:52
msgid "New keys" msgid "New keys"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/contact_details_dialog.vala:51 #: plugins/omemo/src/ui/contact_details_dialog.vala:53
msgid "Associated keys" msgid "Associated keys"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/contact_details_dialog.vala:52 #: plugins/omemo/src/ui/contact_details_dialog.vala:54
msgid "Inactive keys" msgid "Inactive keys"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/contact_details_dialog.vala:84 #: plugins/omemo/src/ui/contact_details_dialog.vala:86
msgid "" msgid ""
"New encryption keys from your other devices will be accepted automatically." "New encryption keys from your other devices will be accepted automatically."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/contact_details_dialog.vala:319 #: plugins/omemo/src/ui/contact_details_dialog.vala:335
msgid "Accepted" msgid "Accepted"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/contact_details_dialog.vala:324 #: plugins/omemo/src/ui/contact_details_dialog.vala:340
msgid "Rejected" msgid "Rejected"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/contact_details_dialog.vala:329 #: plugins/omemo/src/ui/contact_details_dialog.vala:345
msgid "Verified" msgid "Verified"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/contact_details_dialog.vala:336 #: plugins/omemo/src/ui/contact_details_dialog.vala:352
msgid "Unused" msgid "Unused"
msgstr "" msgstr ""

View file

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-02-12 22:06+0100\n" "POT-Creation-Date: 2023-01-28 14:28+0100\n"
"PO-Revision-Date: 2022-02-04 09:55+0000\n" "PO-Revision-Date: 2022-02-04 09:55+0000\n"
"Language-Team: none\n" "Language-Team: none\n"
"Language: el\n" "Language: el\n"
@ -38,11 +38,11 @@ msgstr ""
"%s δεν εμπιστεύεται αυτήν τη συσκευή. Αυτό σημαίνει ότι μπορεί να χάσετε " "%s δεν εμπιστεύεται αυτήν τη συσκευή. Αυτό σημαίνει ότι μπορεί να χάσετε "
"μηνύματα." "μηνύματα."
#: plugins/omemo/src/ui/manage_key_dialog.vala:35 #: plugins/omemo/src/ui/manage_key_dialog.vala:34
msgid "Manage Key" msgid "Manage Key"
msgstr "Διαχείριση Κλειδιού" msgstr "Διαχείριση Κλειδιού"
#: plugins/omemo/src/ui/manage_key_dialog.vala:36 #: plugins/omemo/src/ui/manage_key_dialog.vala:35
msgid "" msgid ""
"Compare the fingerprint, character by character, with the one shown on your " "Compare the fingerprint, character by character, with the one shown on your "
"contact's device." "contact's device."
@ -50,29 +50,29 @@ msgstr ""
"Συγκρίνετε το δακτυλικό αποτύπωμα (fingerprint), χαρακτήρα προς χαρακτήρα, " "Συγκρίνετε το δακτυλικό αποτύπωμα (fingerprint), χαρακτήρα προς χαρακτήρα, "
"με αυτό που εμφανίζεται στη συσκευή της επαφής σας." "με αυτό που εμφανίζεται στη συσκευή της επαφής σας."
#: plugins/omemo/src/ui/manage_key_dialog.vala:37 #: plugins/omemo/src/ui/manage_key_dialog.vala:36
msgid "Fingerprints differ" msgid "Fingerprints differ"
msgstr "Τα δακτυλικά αποτυπώματα (fingerprints) διαφέρουν" msgstr "Τα δακτυλικά αποτυπώματα (fingerprints) διαφέρουν"
#: plugins/omemo/src/ui/manage_key_dialog.vala:38 #: plugins/omemo/src/ui/manage_key_dialog.vala:37
msgid "Fingerprints match" msgid "Fingerprints match"
msgstr "Τα δακτυλικά αποτυπώματα (fingerprints) ταιριάζουν" msgstr "Τα δακτυλικά αποτυπώματα (fingerprints) ταιριάζουν"
#: plugins/omemo/src/ui/manage_key_dialog.vala:39 #: plugins/omemo/src/ui/manage_key_dialog.vala:38
#: plugins/omemo/src/ui/manage_key_dialog.vala:82 #: plugins/omemo/src/ui/manage_key_dialog.vala:81
#: plugins/omemo/src/ui/manage_key_dialog.vala:88 #: plugins/omemo/src/ui/manage_key_dialog.vala:87
msgid "Cancel" msgid "Cancel"
msgstr "Ακύρωση" msgstr "Ακύρωση"
#: plugins/omemo/src/ui/manage_key_dialog.vala:40 #: plugins/omemo/src/ui/manage_key_dialog.vala:39
msgid "Confirm" msgid "Confirm"
msgstr "Επιβεβαίωση" msgstr "Επιβεβαίωση"
#: plugins/omemo/src/ui/manage_key_dialog.vala:60 #: plugins/omemo/src/ui/manage_key_dialog.vala:59
msgid "Verify key" msgid "Verify key"
msgstr "Επαλήθευση κλειδιού" msgstr "Επαλήθευση κλειδιού"
#: plugins/omemo/src/ui/manage_key_dialog.vala:61 #: plugins/omemo/src/ui/manage_key_dialog.vala:60
#, c-format #, c-format
msgid "" msgid ""
"Future messages sent by %s from the device that uses this key will be " "Future messages sent by %s from the device that uses this key will be "
@ -81,11 +81,11 @@ msgstr ""
"Μελλοντικά μηνύματα που αποστέλλονται από %s από τη συσκευή που χρησιμοποιεί " "Μελλοντικά μηνύματα που αποστέλλονται από %s από τη συσκευή που χρησιμοποιεί "
"αυτό το κλειδί θα επισημαίνονται ανάλογα στο παράθυρο συνομιλίας." "αυτό το κλειδί θα επισημαίνονται ανάλογα στο παράθυρο συνομιλίας."
#: plugins/omemo/src/ui/manage_key_dialog.vala:71 #: plugins/omemo/src/ui/manage_key_dialog.vala:70
msgid "Fingerprints do not match" msgid "Fingerprints do not match"
msgstr "Τα δακτυλικά αποτυπώματα (fingerprints) δεν ταιριάζουν" msgstr "Τα δακτυλικά αποτυπώματα (fingerprints) δεν ταιριάζουν"
#: plugins/omemo/src/ui/manage_key_dialog.vala:72 #: plugins/omemo/src/ui/manage_key_dialog.vala:71
#, c-format #, c-format
msgid "" msgid ""
"Please verify that you are comparing the correct fingerprint. If " "Please verify that you are comparing the correct fingerprint. If "
@ -97,11 +97,11 @@ msgstr ""
"μπορεί να παραβιαστεί και θα πρέπει να σκεφτείτε να απορρίψετε αυτό το " "μπορεί να παραβιαστεί και θα πρέπει να σκεφτείτε να απορρίψετε αυτό το "
"κλειδί." "κλειδί."
#: plugins/omemo/src/ui/manage_key_dialog.vala:124 #: plugins/omemo/src/ui/manage_key_dialog.vala:123
msgid "Verify key fingerprint" msgid "Verify key fingerprint"
msgstr "Επαλήθευση δακτυλικού αποτυπώματος (fingerprint) κλειδιού" msgstr "Επαλήθευση δακτυλικού αποτυπώματος (fingerprint) κλειδιού"
#: plugins/omemo/src/ui/manage_key_dialog.vala:124 #: plugins/omemo/src/ui/manage_key_dialog.vala:123
msgid "" msgid ""
"Compare this key's fingerprint with the fingerprint displayed on the " "Compare this key's fingerprint with the fingerprint displayed on the "
"contact's device." "contact's device."
@ -109,66 +109,66 @@ msgstr ""
"Συγκρίνετε το δακτυλικό αποτύπωμα (fingerprint) αυτού του κλειδιού με το " "Συγκρίνετε το δακτυλικό αποτύπωμα (fingerprint) αυτού του κλειδιού με το "
"δακτυλικό αποτύπωμα που εμφανίζεται στη συσκευή της επαφής." "δακτυλικό αποτύπωμα που εμφανίζεται στη συσκευή της επαφής."
#: plugins/omemo/src/ui/manage_key_dialog.vala:126 #: plugins/omemo/src/ui/manage_key_dialog.vala:125
#: plugins/omemo/src/ui/manage_key_dialog.vala:152 #: plugins/omemo/src/ui/manage_key_dialog.vala:151
#: plugins/omemo/src/ui/contact_details_dialog.vala:256 #: plugins/omemo/src/ui/contact_details_dialog.vala:269
msgid "Reject key" msgid "Reject key"
msgstr "Απόρριψη κλειδιού" msgstr "Απόρριψη κλειδιού"
#: plugins/omemo/src/ui/manage_key_dialog.vala:126 #: plugins/omemo/src/ui/manage_key_dialog.vala:125
msgid "" msgid ""
"Block encrypted communication with the contact's device that uses this key." "Block encrypted communication with the contact's device that uses this key."
msgstr "" msgstr ""
"Αποκλεισμός κρυπτογραφημένης επικοινωνίας με τη συσκευή της επαφής που " "Αποκλεισμός κρυπτογραφημένης επικοινωνίας με τη συσκευή της επαφής που "
"χρησιμοποιεί αυτό το κλειδί." "χρησιμοποιεί αυτό το κλειδί."
#: plugins/omemo/src/ui/manage_key_dialog.vala:128 #: plugins/omemo/src/ui/manage_key_dialog.vala:127
#: plugins/omemo/src/ui/manage_key_dialog.vala:160 #: plugins/omemo/src/ui/manage_key_dialog.vala:159
#: plugins/omemo/src/ui/contact_details_dialog.vala:251 #: plugins/omemo/src/ui/contact_details_dialog.vala:264
msgid "Accept key" msgid "Accept key"
msgstr "Αποδοχή κλειδιού" msgstr "Αποδοχή κλειδιού"
#: plugins/omemo/src/ui/manage_key_dialog.vala:128 #: plugins/omemo/src/ui/manage_key_dialog.vala:127
msgid "" msgid ""
"Allow encrypted communication with the contact's device that uses this key." "Allow encrypted communication with the contact's device that uses this key."
msgstr "" msgstr ""
"Να επιτρέπεται η κρυπτογραφημένη επικοινωνία με τη συσκευή της επαφής που " "Να επιτρέπεται η κρυπτογραφημένη επικοινωνία με τη συσκευή της επαφής που "
"χρησιμοποιεί αυτό το κλειδί." "χρησιμοποιεί αυτό το κλειδί."
#: plugins/omemo/src/ui/manage_key_dialog.vala:132 #: plugins/omemo/src/ui/manage_key_dialog.vala:131
#: plugins/omemo/src/ui/manage_key_dialog.vala:137 #: plugins/omemo/src/ui/manage_key_dialog.vala:136
#: plugins/omemo/src/ui/manage_key_dialog.vala:141 #: plugins/omemo/src/ui/manage_key_dialog.vala:140
#, c-format #, c-format
msgid "This key is currently %s." msgid "This key is currently %s."
msgstr "Αυτό το κλειδί είναι αυτή τη στιγμή %s." msgstr "Αυτό το κλειδί είναι αυτή τη στιγμή %s."
#: plugins/omemo/src/ui/manage_key_dialog.vala:132 #: plugins/omemo/src/ui/manage_key_dialog.vala:131
msgid "accepted" msgid "accepted"
msgstr "δεκτό" msgstr "δεκτό"
#: plugins/omemo/src/ui/manage_key_dialog.vala:132 #: plugins/omemo/src/ui/manage_key_dialog.vala:131
#: plugins/omemo/src/ui/manage_key_dialog.vala:137 #: plugins/omemo/src/ui/manage_key_dialog.vala:136
#, c-format #, c-format
msgid "This means it can be used by %s to receive and send encrypted messages." msgid "This means it can be used by %s to receive and send encrypted messages."
msgstr "" msgstr ""
"Αυτό σημαίνει ότι μπορεί να χρησιμοποιηθεί από το %s για λήψη και αποστολή " "Αυτό σημαίνει ότι μπορεί να χρησιμοποιηθεί από το %s για λήψη και αποστολή "
"κρυπτογραφημένων μηνυμάτων." "κρυπτογραφημένων μηνυμάτων."
#: plugins/omemo/src/ui/manage_key_dialog.vala:137 #: plugins/omemo/src/ui/manage_key_dialog.vala:136
msgid "verified" msgid "verified"
msgstr "επαληθευμένο" msgstr "επαληθευμένο"
#: plugins/omemo/src/ui/manage_key_dialog.vala:137 #: plugins/omemo/src/ui/manage_key_dialog.vala:136
msgid "" msgid ""
"Additionally it has been verified to match the key on the contact's device." "Additionally it has been verified to match the key on the contact's device."
msgstr "" msgstr ""
"Επιπλέον, έχει επαληθευτεί ότι ταιριάζει με το κλειδί στη συσκευή της επαφής." "Επιπλέον, έχει επαληθευτεί ότι ταιριάζει με το κλειδί στη συσκευή της επαφής."
#: plugins/omemo/src/ui/manage_key_dialog.vala:141 #: plugins/omemo/src/ui/manage_key_dialog.vala:140
msgid "rejected" msgid "rejected"
msgstr "απορριφθέν" msgstr "απορριφθέν"
#: plugins/omemo/src/ui/manage_key_dialog.vala:141 #: plugins/omemo/src/ui/manage_key_dialog.vala:140
#, c-format #, c-format
msgid "" msgid ""
"This means it cannot be used by %s to decipher your messages, and you won't " "This means it cannot be used by %s to decipher your messages, and you won't "
@ -178,7 +178,7 @@ msgstr ""
"αποκρυπτογράφηση των μηνυμάτων σας και δεν θα βλέπετε μηνύματα " "αποκρυπτογράφηση των μηνυμάτων σας και δεν θα βλέπετε μηνύματα "
"κρυπτογραφημένα με αυτό." "κρυπτογραφημένα με αυτό."
#: plugins/omemo/src/ui/manage_key_dialog.vala:153 #: plugins/omemo/src/ui/manage_key_dialog.vala:152
#, c-format #, c-format
msgid "" msgid ""
"You won't see encrypted messages from the device of %s that uses this key. " "You won't see encrypted messages from the device of %s that uses this key. "
@ -188,7 +188,7 @@ msgstr ""
"χρησιμοποιούν αυτό το κλειδί. Αντίθετα, αυτή η συσκευή δεν θα μπορεί πλέον " "χρησιμοποιούν αυτό το κλειδί. Αντίθετα, αυτή η συσκευή δεν θα μπορεί πλέον "
"να αποκρυπτογραφήσει τα μηνύματά σας." "να αποκρυπτογραφήσει τα μηνύματά σας."
#: plugins/omemo/src/ui/manage_key_dialog.vala:161 #: plugins/omemo/src/ui/manage_key_dialog.vala:160
#, c-format #, c-format
msgid "" msgid ""
"You will be able to exchange encrypted messages with the device of %s that " "You will be able to exchange encrypted messages with the device of %s that "
@ -197,7 +197,7 @@ msgstr ""
"Θα μπορείτε να ανταλλάσσετε κρυπτογραφημένα μηνύματα με τη συσκευή των %s " "Θα μπορείτε να ανταλλάσσετε κρυπτογραφημένα μηνύματα με τη συσκευή των %s "
"που χρησιμοποιούν αυτό το κλειδί." "που χρησιμοποιούν αυτό το κλειδί."
#: plugins/omemo/src/ui/manage_key_dialog.vala:167 #: plugins/omemo/src/ui/manage_key_dialog.vala:166
msgid "Back" msgid "Back"
msgstr "Πίσω" msgstr "Πίσω"
@ -209,15 +209,6 @@ msgstr "Διαχείρηση"
msgid "This contact has new devices" msgid "This contact has new devices"
msgstr "Αυτή η επαφή έχει νέες συσκευές" msgstr "Αυτή η επαφή έχει νέες συσκευές"
#: plugins/omemo/src/ui/account_settings_widget.vala:42
#: plugins/omemo/src/ui/account_settings_widget.vala:45
msgid "Own fingerprint"
msgstr "Το δακτυλικό μου αποτύπωμα (fingerprint)"
#: plugins/omemo/src/ui/account_settings_widget.vala:42
msgid "Will be generated on first connection"
msgstr "Θα δημιουργηθεί με την πρώτη σύνδεση"
#: plugins/omemo/src/ui/own_notifications.vala:29 #: plugins/omemo/src/ui/own_notifications.vala:29
msgid "OMEMO trust decision required" msgid "OMEMO trust decision required"
msgstr "Απαιτείται απόφαση εμπιστοσύνης OMEMO" msgstr "Απαιτείται απόφαση εμπιστοσύνης OMEMO"
@ -227,6 +218,15 @@ msgstr "Απαιτείται απόφαση εμπιστοσύνης OMEMO"
msgid "Did you add a new device for account %s?" msgid "Did you add a new device for account %s?"
msgstr "Προσθέσατε νέα συσκευή για τον λογαριασμό %s;" msgstr "Προσθέσατε νέα συσκευή για τον λογαριασμό %s;"
#: plugins/omemo/src/ui/account_settings_entry.vala:47
#: plugins/omemo/src/ui/account_settings_entry.vala:50
msgid "Own fingerprint"
msgstr "Το δακτυλικό μου αποτύπωμα (fingerprint)"
#: plugins/omemo/src/ui/account_settings_entry.vala:47
msgid "Will be generated on first connection"
msgstr "Θα δημιουργηθεί με την πρώτη σύνδεση"
#: plugins/omemo/src/ui/contact_details_provider.vala:42 #: plugins/omemo/src/ui/contact_details_provider.vala:42
msgid "Encryption" msgid "Encryption"
msgstr "Κρυπτογράφηση" msgstr "Κρυπτογράφηση"
@ -238,54 +238,54 @@ msgid_plural "%d OMEMO devices"
msgstr[0] "%d OMEMO συσκευή" msgstr[0] "%d OMEMO συσκευή"
msgstr[1] "%d OMEMO συσκευές" msgstr[1] "%d OMEMO συσκευές"
#: plugins/omemo/src/ui/contact_details_dialog.vala:46 #: plugins/omemo/src/ui/contact_details_dialog.vala:48
msgid "OMEMO Key Management" msgid "OMEMO Key Management"
msgstr "Διαχείριση κλειδιών OMEMO" msgstr "Διαχείριση κλειδιών OMEMO"
#: plugins/omemo/src/ui/contact_details_dialog.vala:47 #: plugins/omemo/src/ui/contact_details_dialog.vala:49
msgid "Automatically accept new keys" msgid "Automatically accept new keys"
msgstr "Αυτόματη αποδοχή νέων κλειδιών" msgstr "Αυτόματη αποδοχή νέων κλειδιών"
#: plugins/omemo/src/ui/contact_details_dialog.vala:48 #: plugins/omemo/src/ui/contact_details_dialog.vala:50
msgid "New encryption keys from this contact will be accepted automatically." msgid "New encryption keys from this contact will be accepted automatically."
msgstr "" msgstr ""
"Τα νέα κλειδιά κρυπτογράφησης από αυτήν την επαφή θα γίνονται δεκτά αυτόματα." "Τα νέα κλειδιά κρυπτογράφησης από αυτήν την επαφή θα γίνονται δεκτά αυτόματα."
#: plugins/omemo/src/ui/contact_details_dialog.vala:49 #: plugins/omemo/src/ui/contact_details_dialog.vala:51
msgid "Own key" msgid "Own key"
msgstr "Το κλειδί μου" msgstr "Το κλειδί μου"
#: plugins/omemo/src/ui/contact_details_dialog.vala:50 #: plugins/omemo/src/ui/contact_details_dialog.vala:52
msgid "New keys" msgid "New keys"
msgstr "Νέα κλειδιά" msgstr "Νέα κλειδιά"
#: plugins/omemo/src/ui/contact_details_dialog.vala:51 #: plugins/omemo/src/ui/contact_details_dialog.vala:53
msgid "Associated keys" msgid "Associated keys"
msgstr "Συσχετισμένα κλειδιά" msgstr "Συσχετισμένα κλειδιά"
#: plugins/omemo/src/ui/contact_details_dialog.vala:52 #: plugins/omemo/src/ui/contact_details_dialog.vala:54
msgid "Inactive keys" msgid "Inactive keys"
msgstr "Ανενεργά κλειδιά" msgstr "Ανενεργά κλειδιά"
#: plugins/omemo/src/ui/contact_details_dialog.vala:84 #: plugins/omemo/src/ui/contact_details_dialog.vala:86
msgid "" msgid ""
"New encryption keys from your other devices will be accepted automatically." "New encryption keys from your other devices will be accepted automatically."
msgstr "" msgstr ""
"Τα νέα κλειδιά κρυπτογράφησης από τις άλλες συσκευές σας θα γίνονται δεκτά " "Τα νέα κλειδιά κρυπτογράφησης από τις άλλες συσκευές σας θα γίνονται δεκτά "
"αυτόματα." "αυτόματα."
#: plugins/omemo/src/ui/contact_details_dialog.vala:319 #: plugins/omemo/src/ui/contact_details_dialog.vala:335
msgid "Accepted" msgid "Accepted"
msgstr "Αποδεκτά" msgstr "Αποδεκτά"
#: plugins/omemo/src/ui/contact_details_dialog.vala:324 #: plugins/omemo/src/ui/contact_details_dialog.vala:340
msgid "Rejected" msgid "Rejected"
msgstr "Απορριφθέντα" msgstr "Απορριφθέντα"
#: plugins/omemo/src/ui/contact_details_dialog.vala:329 #: plugins/omemo/src/ui/contact_details_dialog.vala:345
msgid "Verified" msgid "Verified"
msgstr "Επαληθευμένα" msgstr "Επαληθευμένα"
#: plugins/omemo/src/ui/contact_details_dialog.vala:336 #: plugins/omemo/src/ui/contact_details_dialog.vala:352
msgid "Unused" msgid "Unused"
msgstr "Αχρησιμοποίητα" msgstr "Αχρησιμοποίητα"

View file

@ -2,7 +2,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: dino-omemo-0.0\n" "Project-Id-Version: dino-omemo-0.0\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-02-12 22:06+0100\n" "POT-Creation-Date: 2023-01-28 14:28+0100\n"
"Language: en\n" "Language: en\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@ -25,50 +25,50 @@ msgid ""
"%s does not trust this device. That means, you might be missing messages." "%s does not trust this device. That means, you might be missing messages."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:35 #: plugins/omemo/src/ui/manage_key_dialog.vala:34
msgid "Manage Key" msgid "Manage Key"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:36 #: plugins/omemo/src/ui/manage_key_dialog.vala:35
msgid "" msgid ""
"Compare the fingerprint, character by character, with the one shown on your " "Compare the fingerprint, character by character, with the one shown on your "
"contact's device." "contact's device."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:37 #: plugins/omemo/src/ui/manage_key_dialog.vala:36
msgid "Fingerprints differ" msgid "Fingerprints differ"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:38 #: plugins/omemo/src/ui/manage_key_dialog.vala:37
msgid "Fingerprints match" msgid "Fingerprints match"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:39 #: plugins/omemo/src/ui/manage_key_dialog.vala:38
#: plugins/omemo/src/ui/manage_key_dialog.vala:82 #: plugins/omemo/src/ui/manage_key_dialog.vala:81
#: plugins/omemo/src/ui/manage_key_dialog.vala:88 #: plugins/omemo/src/ui/manage_key_dialog.vala:87
msgid "Cancel" msgid "Cancel"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:40 #: plugins/omemo/src/ui/manage_key_dialog.vala:39
msgid "Confirm" msgid "Confirm"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:60 #: plugins/omemo/src/ui/manage_key_dialog.vala:59
msgid "Verify key" msgid "Verify key"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:61 #: plugins/omemo/src/ui/manage_key_dialog.vala:60
#, c-format #, c-format
msgid "" msgid ""
"Future messages sent by %s from the device that uses this key will be " "Future messages sent by %s from the device that uses this key will be "
"highlighted accordingly in the chat window." "highlighted accordingly in the chat window."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:71 #: plugins/omemo/src/ui/manage_key_dialog.vala:70
msgid "Fingerprints do not match" msgid "Fingerprints do not match"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:72 #: plugins/omemo/src/ui/manage_key_dialog.vala:71
#, c-format #, c-format
msgid "" msgid ""
"Please verify that you are comparing the correct fingerprint. If " "Please verify that you are comparing the correct fingerprint. If "
@ -76,90 +76,90 @@ msgid ""
"consider rejecting this key." "consider rejecting this key."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:124 #: plugins/omemo/src/ui/manage_key_dialog.vala:123
msgid "Verify key fingerprint" msgid "Verify key fingerprint"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:124 #: plugins/omemo/src/ui/manage_key_dialog.vala:123
msgid "" msgid ""
"Compare this key's fingerprint with the fingerprint displayed on the " "Compare this key's fingerprint with the fingerprint displayed on the "
"contact's device." "contact's device."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:126 #: plugins/omemo/src/ui/manage_key_dialog.vala:125
#: plugins/omemo/src/ui/manage_key_dialog.vala:152 #: plugins/omemo/src/ui/manage_key_dialog.vala:151
#: plugins/omemo/src/ui/contact_details_dialog.vala:256 #: plugins/omemo/src/ui/contact_details_dialog.vala:269
msgid "Reject key" msgid "Reject key"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:126 #: plugins/omemo/src/ui/manage_key_dialog.vala:125
msgid "" msgid ""
"Block encrypted communication with the contact's device that uses this key." "Block encrypted communication with the contact's device that uses this key."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:128 #: plugins/omemo/src/ui/manage_key_dialog.vala:127
#: plugins/omemo/src/ui/manage_key_dialog.vala:160 #: plugins/omemo/src/ui/manage_key_dialog.vala:159
#: plugins/omemo/src/ui/contact_details_dialog.vala:251 #: plugins/omemo/src/ui/contact_details_dialog.vala:264
msgid "Accept key" msgid "Accept key"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:128 #: plugins/omemo/src/ui/manage_key_dialog.vala:127
msgid "" msgid ""
"Allow encrypted communication with the contact's device that uses this key." "Allow encrypted communication with the contact's device that uses this key."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:132 #: plugins/omemo/src/ui/manage_key_dialog.vala:131
#: plugins/omemo/src/ui/manage_key_dialog.vala:137 #: plugins/omemo/src/ui/manage_key_dialog.vala:136
#: plugins/omemo/src/ui/manage_key_dialog.vala:141 #: plugins/omemo/src/ui/manage_key_dialog.vala:140
#, c-format #, c-format
msgid "This key is currently %s." msgid "This key is currently %s."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:132 #: plugins/omemo/src/ui/manage_key_dialog.vala:131
msgid "accepted" msgid "accepted"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:132 #: plugins/omemo/src/ui/manage_key_dialog.vala:131
#: plugins/omemo/src/ui/manage_key_dialog.vala:137 #: plugins/omemo/src/ui/manage_key_dialog.vala:136
#, c-format #, c-format
msgid "This means it can be used by %s to receive and send encrypted messages." msgid "This means it can be used by %s to receive and send encrypted messages."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:137 #: plugins/omemo/src/ui/manage_key_dialog.vala:136
msgid "verified" msgid "verified"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:137 #: plugins/omemo/src/ui/manage_key_dialog.vala:136
msgid "" msgid ""
"Additionally it has been verified to match the key on the contact's device." "Additionally it has been verified to match the key on the contact's device."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:141 #: plugins/omemo/src/ui/manage_key_dialog.vala:140
msgid "rejected" msgid "rejected"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:141 #: plugins/omemo/src/ui/manage_key_dialog.vala:140
#, c-format #, c-format
msgid "" msgid ""
"This means it cannot be used by %s to decipher your messages, and you won't " "This means it cannot be used by %s to decipher your messages, and you won't "
"see messages encrypted with it." "see messages encrypted with it."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:153 #: plugins/omemo/src/ui/manage_key_dialog.vala:152
#, c-format #, c-format
msgid "" msgid ""
"You won't see encrypted messages from the device of %s that uses this key. " "You won't see encrypted messages from the device of %s that uses this key. "
"Conversely, that device won't be able to decipher your messages anymore." "Conversely, that device won't be able to decipher your messages anymore."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:161 #: plugins/omemo/src/ui/manage_key_dialog.vala:160
#, c-format #, c-format
msgid "" msgid ""
"You will be able to exchange encrypted messages with the device of %s that " "You will be able to exchange encrypted messages with the device of %s that "
"uses this key." "uses this key."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/manage_key_dialog.vala:167 #: plugins/omemo/src/ui/manage_key_dialog.vala:166
msgid "Back" msgid "Back"
msgstr "" msgstr ""
@ -171,15 +171,6 @@ msgstr ""
msgid "This contact has new devices" msgid "This contact has new devices"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/account_settings_widget.vala:42
#: plugins/omemo/src/ui/account_settings_widget.vala:45
msgid "Own fingerprint"
msgstr ""
#: plugins/omemo/src/ui/account_settings_widget.vala:42
msgid "Will be generated on first connection"
msgstr ""
#: plugins/omemo/src/ui/own_notifications.vala:29 #: plugins/omemo/src/ui/own_notifications.vala:29
msgid "OMEMO trust decision required" msgid "OMEMO trust decision required"
msgstr "" msgstr ""
@ -189,6 +180,15 @@ msgstr ""
msgid "Did you add a new device for account %s?" msgid "Did you add a new device for account %s?"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/account_settings_entry.vala:47
#: plugins/omemo/src/ui/account_settings_entry.vala:50
msgid "Own fingerprint"
msgstr ""
#: plugins/omemo/src/ui/account_settings_entry.vala:47
msgid "Will be generated on first connection"
msgstr ""
#: plugins/omemo/src/ui/contact_details_provider.vala:42 #: plugins/omemo/src/ui/contact_details_provider.vala:42
msgid "Encryption" msgid "Encryption"
msgstr "" msgstr ""
@ -200,51 +200,51 @@ msgid_plural "%d OMEMO devices"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#: plugins/omemo/src/ui/contact_details_dialog.vala:46 #: plugins/omemo/src/ui/contact_details_dialog.vala:48
msgid "OMEMO Key Management" msgid "OMEMO Key Management"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/contact_details_dialog.vala:47 #: plugins/omemo/src/ui/contact_details_dialog.vala:49
msgid "Automatically accept new keys" msgid "Automatically accept new keys"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/contact_details_dialog.vala:48 #: plugins/omemo/src/ui/contact_details_dialog.vala:50
msgid "New encryption keys from this contact will be accepted automatically." msgid "New encryption keys from this contact will be accepted automatically."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/contact_details_dialog.vala:49 #: plugins/omemo/src/ui/contact_details_dialog.vala:51
msgid "Own key" msgid "Own key"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/contact_details_dialog.vala:50 #: plugins/omemo/src/ui/contact_details_dialog.vala:52
msgid "New keys" msgid "New keys"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/contact_details_dialog.vala:51 #: plugins/omemo/src/ui/contact_details_dialog.vala:53
msgid "Associated keys" msgid "Associated keys"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/contact_details_dialog.vala:52 #: plugins/omemo/src/ui/contact_details_dialog.vala:54
msgid "Inactive keys" msgid "Inactive keys"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/contact_details_dialog.vala:84 #: plugins/omemo/src/ui/contact_details_dialog.vala:86
msgid "" msgid ""
"New encryption keys from your other devices will be accepted automatically." "New encryption keys from your other devices will be accepted automatically."
msgstr "" msgstr ""
#: plugins/omemo/src/ui/contact_details_dialog.vala:319 #: plugins/omemo/src/ui/contact_details_dialog.vala:335
msgid "Accepted" msgid "Accepted"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/contact_details_dialog.vala:324 #: plugins/omemo/src/ui/contact_details_dialog.vala:340
msgid "Rejected" msgid "Rejected"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/contact_details_dialog.vala:329 #: plugins/omemo/src/ui/contact_details_dialog.vala:345
msgid "Verified" msgid "Verified"
msgstr "" msgstr ""
#: plugins/omemo/src/ui/contact_details_dialog.vala:336 #: plugins/omemo/src/ui/contact_details_dialog.vala:352
msgid "Unused" msgid "Unused"
msgstr "" msgstr ""

Some files were not shown because too many files have changed in this diff Show more