Merge remote-tracking branch 'upstream/master' into master-windows-changes
This commit is contained in:
commit
3d61f175a6
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
|
@ -7,7 +7,7 @@ jobs:
|
|||
- uses: actions/checkout@v2
|
||||
- run: sudo apt-get update
|
||||
- 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: make
|
||||
- run: build/xmpp-vala-test
|
||||
|
|
11
cmake/FindAdwaita.cmake
Normal file
11
cmake/FindAdwaita.cmake
Normal 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)
|
|
@ -42,9 +42,10 @@ public class Conversation : Object {
|
|||
|
||||
public enum Setting { DEFAULT, ON, OFF }
|
||||
public Setting send_typing { get; set; default = Setting.DEFAULT; }
|
||||
|
||||
public Setting send_marker { get; set; default = Setting.DEFAULT; }
|
||||
|
||||
public int pinned { get; set; default = 0; }
|
||||
|
||||
private Database? db;
|
||||
|
||||
public Conversation(Jid jid, Account account, Type type) {
|
||||
|
@ -74,6 +75,7 @@ public class Conversation : Object {
|
|||
notify_setting = (NotifySetting) row[db.conversation.notification];
|
||||
send_typing = (Setting) row[db.conversation.send_typing];
|
||||
send_marker = (Setting) row[db.conversation.send_marker];
|
||||
pinned = row[db.conversation.pinned];
|
||||
|
||||
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.notification, notify_setting)
|
||||
.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) {
|
||||
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;
|
||||
case "send-marker":
|
||||
update.set(db.conversation.send_marker, send_marker); break;
|
||||
case "pinned":
|
||||
update.set(db.conversation.pinned, pinned); break;
|
||||
}
|
||||
update.perform();
|
||||
}
|
||||
|
|
|
@ -154,6 +154,7 @@ public interface ConversationItemWidgetInterface: Object {
|
|||
public delegate void MessageActionEvoked(Object button, Plugins.MetaConversationItem evoked_on, Object widget);
|
||||
public class MessageAction : Object {
|
||||
public string icon_name;
|
||||
public string? tooltip;
|
||||
public Object? popover;
|
||||
public MessageActionEvoked? callback;
|
||||
}
|
||||
|
|
|
@ -44,11 +44,8 @@ public class ContentItemStore : StreamInteractionModule, Object {
|
|||
Gee.TreeSet<ContentItem> items = new Gee.TreeSet<ContentItem>(ContentItem.compare_func);
|
||||
|
||||
foreach (var row in select) {
|
||||
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]);
|
||||
items.add(get_item(conversation, id, content_type, foreign_id, time));
|
||||
ContentItem content_item = get_item_from_row(row, conversation);
|
||||
items.add(content_item);
|
||||
}
|
||||
|
||||
Gee.List<ContentItem> ret = new ArrayList<ContentItem>();
|
||||
|
@ -58,6 +55,14 @@ public class ContentItemStore : StreamInteractionModule, Object {
|
|||
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 {
|
||||
switch (content_type) {
|
||||
case 1:
|
||||
|
@ -112,6 +117,91 @@ public class ContentItemStore : StreamInteractionModule, Object {
|
|||
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) {
|
||||
Gee.List<ContentItem> items = get_n_latest(conversation, 1);
|
||||
if (items.size > 0) {
|
||||
|
|
|
@ -7,7 +7,7 @@ using Dino.Entities;
|
|||
namespace Dino {
|
||||
|
||||
public class Database : Qlite.Database {
|
||||
private const int VERSION = 24;
|
||||
private const int VERSION = 25;
|
||||
|
||||
public class AccountTable : Table {
|
||||
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> 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> pinned = new Column.Integer("pinned") { default="0", min_version=25 };
|
||||
|
||||
internal ConversationTable(Database db) {
|
||||
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});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
PageRequestResult page_result = yield get_mam_page(account, query_params, null);
|
||||
|
||||
if (page_result.page_result == PageResult.Duplicate) {
|
||||
// No new messages
|
||||
return 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.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;
|
||||
}
|
||||
|
||||
// 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.
|
||||
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;
|
||||
|
||||
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.from_id, from_id)
|
||||
.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_time, to_time)
|
||||
.perform();
|
||||
|
|
|
@ -425,24 +425,8 @@ public class MessageProcessor : StreamInteractionModule, Object {
|
|||
new_message.type_ = MessageStanza.TYPE_CHAT;
|
||||
}
|
||||
|
||||
if (message.quoted_item_id > 0) {
|
||||
ContentItem? content_item = stream_interactor.get_module(ContentItemStore.IDENTITY).get_item_by_id(conversation, message.quoted_item_id);
|
||||
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 }));
|
||||
}
|
||||
}
|
||||
}
|
||||
string? fallback = get_fallback_body_set_infos(message, new_message, conversation);
|
||||
new_message.body = fallback == null ? message.body : fallback + message.body;
|
||||
|
||||
build_message_stanza(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 {
|
||||
|
|
|
@ -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.reply, db.reply.message_id, db.message.id);
|
||||
|
||||
if (conversation.counterpart.resourcepart == null) {
|
||||
query.with_null(db.message.counterpart_resource);
|
||||
} else {
|
||||
if (conversation.counterpart.resourcepart != null) {
|
||||
query.with(db.message.counterpart_resource, "=", conversation.counterpart.resourcepart);
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@ public class Dino.Reactions : StreamInteractionModule, Object {
|
|||
public string id { get { return IDENTITY.id; } }
|
||||
|
||||
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);
|
||||
|
||||
private StreamInteractor stream_interactor;
|
||||
|
@ -27,7 +26,7 @@ public class Dino.Reactions : StreamInteractionModule, Object {
|
|||
this.db = database;
|
||||
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) {
|
||||
|
@ -35,15 +34,19 @@ public class Dino.Reactions : StreamInteractionModule, Object {
|
|||
if (!reactions.contains(reaction)) {
|
||||
reactions.add(reaction);
|
||||
}
|
||||
send_reactions(conversation, content_item, reactions);
|
||||
reaction_added(conversation.account, content_item.id, conversation.account.bare_jid, reaction);
|
||||
try {
|
||||
send_reactions(conversation, content_item, reactions);
|
||||
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) {
|
||||
Gee.List<string> reactions = get_own_reactions(conversation, content_item);
|
||||
reactions.remove(reaction);
|
||||
send_reactions(conversation, content_item, reactions);
|
||||
reaction_removed(conversation.account, content_item.id, conversation.account.bare_jid, reaction);
|
||||
try {
|
||||
send_reactions(conversation, content_item, reactions);
|
||||
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) {
|
||||
|
@ -80,35 +83,28 @@ public class Dino.Reactions : StreamInteractionModule, Object {
|
|||
return false;
|
||||
}
|
||||
|
||||
private void send_reactions(Conversation conversation, ContentItem content_item, Gee.List<string> reactions) {
|
||||
Message? message = null;
|
||||
private void send_reactions(Conversation conversation, ContentItem content_item, Gee.List<string> reactions) throws SendError {
|
||||
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;
|
||||
if (file_item != null) {
|
||||
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;
|
||||
}
|
||||
XmppStream? stream = stream_interactor.get_stream(conversation.account);
|
||||
if (stream == null) throw new SendError.NoStream("");
|
||||
|
||||
if (message == null) {
|
||||
return;
|
||||
}
|
||||
var reactions_module = stream.get_module(Xmpp.Xep.Reactions.Module.IDENTITY);
|
||||
|
||||
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) {
|
||||
stream.get_module(Xmpp.Xep.Reactions.Module.IDENTITY).send_reaction(stream, conversation.counterpart, "groupchat", message.server_id ?? message.stanza_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);
|
||||
}
|
||||
if (conversation.type_ == Conversation.Type.GROUPCHAT) {
|
||||
reactions_module.send_reaction.begin(stream, conversation.counterpart, "groupchat", message_id, reactions);
|
||||
// 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) {
|
||||
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;
|
||||
save_chat_reactions(conversation.account, conversation.account.bare_jid, content_item.id, now_millis, reactions);
|
||||
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);
|
||||
} 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);
|
||||
Conversation conversation = stream_interactor.get_module(ConversationManager.IDENTITY).get_conversation_for_message(reaction_message);
|
||||
|
||||
Message? message = get_message_for_reaction(conversation, message_id);
|
||||
var reaction_info = new ReactionInfo() { account=account, from_jid=from_jid, reactions=reactions, stanza=stanza, received_time=new DateTime.now() };
|
||||
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() { conversation=conversation, from_jid=from_jid, reactions=reactions, stanza=stanza, received_time=new DateTime.now() };
|
||||
|
||||
if (message != null) {
|
||||
process_reaction_for_message(message.id, reaction_info);
|
||||
if (content_item_id != -1) {
|
||||
process_reaction_for_message(content_item_id, reaction_info);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -267,45 +263,33 @@ public class Dino.Reactions : StreamInteractionModule, Object {
|
|||
reaction_infos[message_id].add(reaction_info);
|
||||
}
|
||||
|
||||
private void on_new_message(Message message, Conversation conversation) {
|
||||
Gee.List<ReactionInfo>? reaction_info_list = null;
|
||||
if (conversation.type_ == Conversation.Type.CHAT) {
|
||||
reaction_info_list = reaction_infos[message.stanza_id];
|
||||
} else {
|
||||
reaction_info_list = reaction_infos[message.server_id];
|
||||
}
|
||||
/*
|
||||
* When we get a new ContentItem, check if we have any reactions cached that apply to it.
|
||||
* If so, process the reactions, map and store them.
|
||||
*/
|
||||
private void on_new_item(ContentItem item, Conversation conversation) {
|
||||
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;
|
||||
|
||||
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
|
||||
ReactionInfo? reaction_info = null;
|
||||
foreach (ReactionInfo info in reaction_info_list) {
|
||||
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;
|
||||
var applicable_reactions = new ArrayList<ReactionInfo>();
|
||||
applicable_reactions.add_all_iterator(reaction_info_list.filter(info => info.conversation.equals(conversation)));
|
||||
|
||||
foreach (ReactionInfo applicable_reaction in applicable_reactions) {
|
||||
reaction_info_list.remove(applicable_reaction);
|
||||
if (reaction_info_list.is_empty) {
|
||||
reaction_infos.unset(stanza_id);
|
||||
}
|
||||
|
||||
reaction_info = info;
|
||||
debug("Got ContentItem for reaction %s", stanza_id);
|
||||
process_reaction_for_message(item.id, applicable_reaction);
|
||||
}
|
||||
if (reaction_info == null) return;
|
||||
reaction_info_list.remove(reaction_info);
|
||||
if (reaction_info_list.is_empty) {
|
||||
if (conversation.type_ == Conversation.Type.GROUPCHAT) {
|
||||
reaction_infos.unset(message.server_id);
|
||||
} else {
|
||||
reaction_infos.unset(message.stanza_id);
|
||||
}
|
||||
}
|
||||
|
||||
debug("Got message for reaction %s", message.stanza_id);
|
||||
process_reaction_for_message(message.id, reaction_info);
|
||||
}
|
||||
|
||||
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) {
|
||||
Account account = reaction_info.account;
|
||||
private void process_reaction_for_message(int content_item_id, ReactionInfo reaction_info) {
|
||||
Account account = reaction_info.conversation.account;
|
||||
MessageStanza stanza = reaction_info.stanza;
|
||||
Jid from_jid = reaction_info.from_jid;
|
||||
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
|
||||
DateTime? reaction_time = null;
|
||||
DelayedDelivery.MessageFlag? delayed_message_flag = DelayedDelivery.MessageFlag.get_flag(stanza);
|
||||
|
@ -485,7 +451,7 @@ public class Dino.ReactionUsers {
|
|||
}
|
||||
|
||||
public class Dino.ReactionInfo {
|
||||
public Account account { get; set; }
|
||||
public Conversation conversation { get; set; }
|
||||
public Jid from_jid { get; set; }
|
||||
public Gee.List<string> reactions { get; set; }
|
||||
public MessageStanza stanza { get; set; }
|
||||
|
|
|
@ -77,22 +77,7 @@ public class Dino.Replies : StreamInteractionModule, Object {
|
|||
Xep.Replies.ReplyTo? reply_to = Xep.Replies.get_reply_to(stanza);
|
||||
if (reply_to == null) return;
|
||||
|
||||
Message? quoted_message = null;
|
||||
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);
|
||||
ContentItem? quoted_content_item = stream_interactor.get_module(ContentItemStore.IDENTITY).get_content_item_for_message_id(conversation, reply_to.to_message_id);
|
||||
if (quoted_content_item == null) return;
|
||||
|
||||
set_message_is_reply_to(message, quoted_content_item);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using Dino.Entities;
|
||||
using Qlite;
|
||||
|
||||
namespace Dino {
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ find_packages(MAIN_PACKAGES REQUIRED
|
|||
GObject
|
||||
GTK4
|
||||
ICU
|
||||
Adwaita
|
||||
)
|
||||
|
||||
set(RESOURCE_LIST
|
||||
|
@ -89,7 +90,8 @@ set(RESOURCE_LIST
|
|||
unified_main_content.ui
|
||||
unified_window_placeholder.ui
|
||||
|
||||
theme.css
|
||||
style.css
|
||||
style-dark.css
|
||||
)
|
||||
|
||||
compile_gresources(
|
||||
|
@ -110,6 +112,12 @@ set(MAIN_DEFINITIONS)
|
|||
if(GTK4_VERSION VERSION_GREATER_EQUAL "4.6")
|
||||
set(MAIN_DEFINITIONS ${MAIN_DEFINITIONS} GTK_4_6)
|
||||
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
|
||||
SOURCES
|
||||
|
@ -199,7 +207,9 @@ SOURCES
|
|||
src/ui/util/label_hybrid.vala
|
||||
src/ui/util/sizing_bin.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
|
||||
${CMAKE_BINARY_DIR}/exports/xmpp-vala.vapi
|
||||
${CMAKE_BINARY_DIR}/exports/qlite.vapi
|
||||
|
|
|
@ -31,7 +31,9 @@
|
|||
<property name="halign">end</property>
|
||||
<property name="valign">start</property>
|
||||
<style>
|
||||
<class name="linked"/>
|
||||
<class name="card"/>
|
||||
<class name="toolbar"/>
|
||||
<class name="overlay-toolbar"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<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>
|
||||
<style>
|
||||
<class name="dino-left"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkMenuButton" id="add_button">
|
||||
<property name="has-frame">False</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="icon-name">list-add-symbolic</property>
|
||||
|
@ -18,6 +20,7 @@
|
|||
</child>
|
||||
<child type="end">
|
||||
<object class="GtkMenuButton" id="menu_button">
|
||||
<property name="has-frame">False</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="icon-name">open-menu-symbolic</property>
|
||||
|
|
|
@ -88,20 +88,33 @@
|
|||
</object>
|
||||
</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-duration">50</property>
|
||||
<property name="reveal-child">True</property>
|
||||
<property name="margin-start">15</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="unread_count_label">
|
||||
<property name="vexpand">False</property>
|
||||
<property name="visible">False</property>
|
||||
<property name="margin-start">15</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<attributes>
|
||||
<attribute name="scale" value="0.6"/>
|
||||
<attribute name="weight" value="PANGO_WEIGHT_BOLD"/>
|
||||
</attributes>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="unread_count_label">
|
||||
<property name="vexpand">False</property>
|
||||
<property name="visible">False</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<attributes>
|
||||
<attribute name="scale" value="0.6"/>
|
||||
<attribute name="weight" value="PANGO_WEIGHT_BOLD"/>
|
||||
</attributes>
|
||||
</object>
|
||||
</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>
|
||||
|
@ -131,7 +144,7 @@
|
|||
<property name="margin-start">5</property>
|
||||
<style>
|
||||
<class name="conversation_list_row_xbutton"/>
|
||||
<class name="circular-button"/>
|
||||
<class name="circular"/>
|
||||
<class name="flat"/>
|
||||
</style>
|
||||
<child>
|
||||
|
|
|
@ -31,7 +31,8 @@
|
|||
<property name="halign">end</property>
|
||||
<property name="valign">end</property>
|
||||
<style>
|
||||
<class name="circular-button"/>
|
||||
<class name="circular"/>
|
||||
<class name="opaque"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
|
|
|
@ -19,40 +19,13 @@
|
|||
<object class="GtkStackPage">
|
||||
<property name="name">empty</property>
|
||||
<property name="child">
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">10</property>
|
||||
<property name="valign">center</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="icon-name">system-search-symbolic</property>
|
||||
<property name="icon-size">large</property>
|
||||
<property name="pixel-size">72</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 class="AdwStatusPage">
|
||||
<style>
|
||||
<class name="compact"/>
|
||||
</style>
|
||||
<property name="icon-name">system-search-symbolic</property>
|
||||
<property name="title" translatable="1">No active search</property>
|
||||
<property name="description" translatable="1">Type to start a search</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
|
@ -61,40 +34,13 @@
|
|||
<object class="GtkStackPage">
|
||||
<property name="name">no-result</property>
|
||||
<property name="child">
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">10</property>
|
||||
<property name="valign">center</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="icon-name">face-uncertain-symbolic</property>
|
||||
<property name="icon-size">large</property>
|
||||
<property name="pixel-size">72</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 class="AdwStatusPage">
|
||||
<style>
|
||||
<class name="compact"/>
|
||||
</style>
|
||||
<property name="icon-name">face-uncertain-symbolic</property>
|
||||
<property name="title" translatable="1">No matching messages</property>
|
||||
<property name="description" translatable="1">Check the spelling or try to remove filters</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
|
|
|
@ -17,13 +17,14 @@
|
|||
<summary xml:lang="pt">Moderno cliente de chat XMPP</summary>
|
||||
<summary xml:lang="pl">Nowoczesny komunikator XMPP</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="nb">Moderne XMPP-sludreklient</summary>
|
||||
<summary xml:lang="lt">Šiuolaikinė XMPP pokalbių kliento programa</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="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="id">Aplikasi chat XMPP modern</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="es">Un cliente de XMPP moderno</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="cs">Moderní XMPP klient</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="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 l’ordenador 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="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="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="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="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>
|
||||
|
@ -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="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="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="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>
|
||||
|
@ -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="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 d’escritura.</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="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="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="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="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>
|
||||
|
@ -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="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="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="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="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>
|
||||
|
@ -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="pl">Dino pobiera historię rozmów z serwera i synchronizuje wiadomości z innymi urządzeniami.</p>
|
||||
<p xml:lang="oc">Dino recupèra l’istoric del servidor e sincroniza los messatges amb d’autres 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="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="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="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="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>
|
||||
|
@ -133,6 +140,7 @@
|
|||
<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="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="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>
|
||||
|
@ -140,13 +148,13 @@
|
|||
</description>
|
||||
<screenshots>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
</screenshots>
|
||||
<translation type="gettext">dino</translation>
|
||||
|
@ -155,21 +163,26 @@
|
|||
<url type="bugtracker">https://github.com/dino/dino/issues</url>
|
||||
<url type="donation">https://dino.im/#donate</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>
|
||||
<!-- TODO: Write this when Dino is released
|
||||
<releases>
|
||||
<release date="XXXX-XX-XX" version="X.X">
|
||||
<release date="2022-02-12" version="0.3">
|
||||
<description>
|
||||
<p>
|
||||
This is our first release. It comes with a clean UI, notifications,
|
||||
end-to-end encryption support (OMEMO and GnuPG), multi-user chats,
|
||||
and more!
|
||||
</p>
|
||||
<p>The 0.3 release is all about calls. Dino now supports calls between two or more people!</p>
|
||||
</description>
|
||||
</release>
|
||||
<release date="2020-11-12" version="0.2">
|
||||
<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>
|
||||
</release>
|
||||
</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>
|
||||
|
|
|
@ -13,13 +13,13 @@
|
|||
</description>
|
||||
<screenshots>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
</screenshots>
|
||||
<translation type="gettext">dino</translation>
|
||||
|
@ -28,22 +28,26 @@
|
|||
<url type="bugtracker">https://github.com/dino/dino/issues</url>
|
||||
<url type="donation">https://dino.im/#donate</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>
|
||||
|
||||
<!-- TODO: Write this when Dino is released
|
||||
<releases>
|
||||
<release date="XXXX-XX-XX" version="X.X">
|
||||
<release date="2022-02-12" version="0.3">
|
||||
<description>
|
||||
<p>
|
||||
This is our first release. It comes with a clean UI, notifications,
|
||||
end-to-end encryption support (OMEMO and GnuPG), multi-user chats,
|
||||
and more!
|
||||
</p>
|
||||
<p>The 0.3 release is all about calls. Dino now supports calls between two or more people!</p>
|
||||
</description>
|
||||
</release>
|
||||
<release date="2020-11-12" version="0.2">
|
||||
<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>
|
||||
</release>
|
||||
</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>
|
||||
|
|
3
main/data/style-dark.css
Normal file
3
main/data/style-dark.css
Normal file
|
@ -0,0 +1,3 @@
|
|||
.dino-main .overlay-toolbar {
|
||||
background-color: shade(@view_bg_color, 1.5);
|
||||
}
|
|
@ -3,6 +3,10 @@
|
|||
* It provides sane defaults for things that are very Dino-specific.
|
||||
*/
|
||||
|
||||
statuspage {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
window.dino-main .dino-header-right {
|
||||
background: @theme_base_color;
|
||||
}
|
||||
|
@ -39,7 +43,7 @@ window.dino-main .dino-conversation .highlight-once {
|
|||
}
|
||||
|
||||
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 {
|
||||
|
@ -88,11 +92,6 @@ window.dino-main .dino-sidebar > frame {
|
|||
transition: background .05s ease;
|
||||
}
|
||||
|
||||
window.dino-main .circular-button {
|
||||
padding: 0;
|
||||
border-radius: 1000px;
|
||||
}
|
||||
|
||||
window.dino-main .dino-conversation .message-box.edit-mode {
|
||||
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);
|
||||
}
|
||||
|
||||
/* Message Menu */
|
||||
/* Overlay Toolbar */
|
||||
|
||||
.message-menu-box {
|
||||
background-color: @theme_base_color;
|
||||
border: 1px solid alpha(@theme_fg_color, 0.15);
|
||||
border-radius: 5px;
|
||||
.dino-main .overlay-toolbar {
|
||||
padding: 2px;
|
||||
border-radius: 6px;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
.message-menu-button {
|
||||
padding: 6px;
|
||||
border: none;
|
||||
.dino-main .overlay-toolbar > * {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* Fie Widget */
|
||||
/* File Widget */
|
||||
|
||||
window.dino-main .file-box-outer,
|
||||
window.dino-main .call-box-outer {
|
||||
|
@ -149,7 +148,7 @@ window.dino-main .call-box {
|
|||
|
||||
window.dino-main .file-image-widget {
|
||||
border: 1px solid alpha(@theme_fg_color, 0.1);
|
||||
border-radius: 3px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
.dino-main .file-image-widget picture {
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
/* Call widget */
|
||||
|
||||
window.dino-main .call-box-outer.incoming {
|
||||
|
@ -185,38 +188,23 @@ window.dino-main .multiparty-participants {
|
|||
|
||||
/* Reactions */
|
||||
|
||||
window.dino-main menubutton.reaction-box image {
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
.dino-main .reaction-grid button {
|
||||
min-height: 16px;
|
||||
min-width: 30px;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
window.dino-main button.reaction-box,
|
||||
window.dino-main menubutton.reaction-box > button {
|
||||
border: 1px solid transparent;
|
||||
padding: 3px 5px ;
|
||||
border-radius: 10px;
|
||||
background-color: alpha(@theme_fg_color, 0.07);
|
||||
background-image: none;
|
||||
box-shadow: none;
|
||||
min-height: 0;
|
||||
min-width: 0;
|
||||
.dino-main .reaction-grid button.own-reaction,
|
||||
.dino-main .reaction-grid .own-reaction button {
|
||||
background-color: alpha(@accent_bg_color, 0.1);
|
||||
border: 1px solid @accent_bg_color;
|
||||
padding: 3px;
|
||||
color: @accent_color;
|
||||
}
|
||||
|
||||
window.dino-main button.reaction-box.own-reaction,
|
||||
window.dino-main menubutton.reaction-box.own-reaction > button {
|
||||
color: mix(@theme_selected_bg_color, @theme_fg_color, 0.4);
|
||||
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);
|
||||
.dino-main .reaction-grid button.own-reaction:hover,
|
||||
.dino-main .reaction-grid .own-reaction button:hover {
|
||||
background-color: alpha(@accent_bg_color, 0.2);
|
||||
}
|
||||
|
||||
/* Sidebar */
|
|
@ -1,74 +1,27 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<requires lib="gtk" version="4.0"/>
|
||||
<object class="GtkPaned" id="paned">
|
||||
<property name="shrink-start-child">False</property>
|
||||
<property name="shrink-end-child">False</property>
|
||||
<property name="resize-start-child">False</property>
|
||||
<property name="position">300</property>
|
||||
<object class="AdwLeaflet" id="leaflet">
|
||||
<property name="transition-type">slide</property>
|
||||
<property name="can-navigate-back">true</property>
|
||||
<property name="can-navigate-forward">true</property>
|
||||
<child>
|
||||
<object class="GtkStack" id="left_stack">
|
||||
<object class="GtkBox" id="left_box">
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkStackPage">
|
||||
<property name="name">content</property>
|
||||
<property name="child">
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="hscrollbar_policy">never</property>
|
||||
<child>
|
||||
<object class="DinoUiConversationSelector" id="conversation_list">
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkStackPage">
|
||||
<property name="name">placeholder</property>
|
||||
<property name="child">
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">20</property>
|
||||
<property name="margin-end">20</property>
|
||||
<property name="margin-top">20</property>
|
||||
<property name="margin-bottom">20</property>
|
||||
<property name="spacing">10</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="halign">start</property>
|
||||
<child>
|
||||
<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>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkOverlay">
|
||||
<property name="child">
|
||||
<object class="GtkStack" id="right_stack">
|
||||
<object class="GtkStack" id="left_stack">
|
||||
<property name="hexpand">False</property>
|
||||
<child>
|
||||
<object class="GtkStackPage">
|
||||
<property name="name">content</property>
|
||||
<property name="child">
|
||||
<object class="DinoUiConversationView" id="conversation_view">
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="hscrollbar_policy">never</property>
|
||||
<property name="vexpand">1</property>
|
||||
<child>
|
||||
<object class="DinoUiConversationSelector" id="conversation_list">
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
|
@ -77,54 +30,89 @@
|
|||
<object class="GtkStackPage">
|
||||
<property name="name">placeholder</property>
|
||||
<property name="child">
|
||||
<object class="GtkBox">
|
||||
<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="pixel-size">144</property>
|
||||
<property name="margin-bottom">30</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label" translatable="1">You have no open chats</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
<attributes>
|
||||
<attribute name="scale" value="1.2"></attribute>
|
||||
</attributes>
|
||||
</object>
|
||||
</child>
|
||||
<object class="AdwStatusPage">
|
||||
<style>
|
||||
<class name="compact"/>
|
||||
</style>
|
||||
<property name="margin-start">20</property>
|
||||
<property name="margin-end">20</property>
|
||||
<property name="margin-top">20</property>
|
||||
<property name="margin-bottom">20</property>
|
||||
<property name="width_request">260</property>
|
||||
|
||||
<property name="title" translatable="yes">You have no open chats</property>
|
||||
<property name="description" translatable="yes">Click + to start a chat or join a channel</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</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>
|
||||
</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>
|
||||
<object class="GtkStack" id="right_stack">
|
||||
<property name="hexpand">false</property>
|
||||
<child>
|
||||
<object class="GtkStackPage">
|
||||
<property name="name">content</property>
|
||||
<property name="child">
|
||||
<object class="DinoUiConversationView" id="conversation_view">
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkStackPage">
|
||||
<property name="name">placeholder</property>
|
||||
<property name="child">
|
||||
<object class="AdwStatusPage">
|
||||
<property name="icon-name">im.dino.Dino-symbolic</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</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>
|
||||
<object class="AdwBin" id="search_frame">
|
||||
<property name="hexpand">true</property>
|
||||
<style>
|
||||
<class name="background"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
</interface>
|
||||
|
|
|
@ -2,63 +2,47 @@
|
|||
<interface>
|
||||
<requires lib="gtk" version="4.0"/>
|
||||
<template class="DinoUiMainWindowPlaceholder">
|
||||
<property name="valign">center</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="box">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="hexpand">1</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<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 class="GtkHeaderBar">
|
||||
<property name="show-title-buttons">true</property>
|
||||
</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>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="primary_button">
|
||||
<property name="margin-top">15</property>
|
||||
<property name="halign">center</property>
|
||||
<style>
|
||||
<class name="text-button"/>
|
||||
<class name="suggested-action"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="secondary_button">
|
||||
<property name="visible">0</property>
|
||||
<property name="halign">center</property>
|
||||
<!-- <property name="no_show_all">True</property>-->
|
||||
<style>
|
||||
<class name="text-button"/>
|
||||
</style>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<child>
|
||||
<object class="AdwStatusPage" id="status_page">
|
||||
<property name="icon-name">im.dino.Dino-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="primary_button">
|
||||
<property name="halign">center</property>
|
||||
<property name="visible">False</property>
|
||||
<style>
|
||||
<class name="text-button"/>
|
||||
<class name="suggested-action"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="secondary_button">
|
||||
<property name="visible">0</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="visible">False</property>
|
||||
<style>
|
||||
<class name="text-button"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
|
|
@ -15,6 +15,7 @@ gl
|
|||
hu
|
||||
id
|
||||
ie
|
||||
is
|
||||
it
|
||||
ja
|
||||
kab
|
||||
|
@ -23,7 +24,6 @@ lb
|
|||
lt
|
||||
nb
|
||||
nl
|
||||
nl_BE
|
||||
oc
|
||||
pl
|
||||
pt
|
||||
|
|
709
main/po/ar.po
709
main/po/ar.po
File diff suppressed because it is too large
Load diff
673
main/po/ca.po
673
main/po/ca.po
File diff suppressed because it is too large
Load diff
670
main/po/cs.po
670
main/po/cs.po
File diff suppressed because it is too large
Load diff
667
main/po/da.po
667
main/po/da.po
File diff suppressed because it is too large
Load diff
683
main/po/de.po
683
main/po/de.po
File diff suppressed because it is too large
Load diff
651
main/po/dino.pot
651
main/po/dino.pot
File diff suppressed because it is too large
Load diff
678
main/po/el.po
678
main/po/el.po
File diff suppressed because it is too large
Load diff
651
main/po/en.po
651
main/po/en.po
File diff suppressed because it is too large
Load diff
694
main/po/eo.po
694
main/po/eo.po
File diff suppressed because it is too large
Load diff
761
main/po/es.po
761
main/po/es.po
File diff suppressed because it is too large
Load diff
701
main/po/eu.po
701
main/po/eu.po
File diff suppressed because it is too large
Load diff
677
main/po/fa.po
677
main/po/fa.po
File diff suppressed because it is too large
Load diff
670
main/po/fi.po
670
main/po/fi.po
File diff suppressed because it is too large
Load diff
679
main/po/fr.po
679
main/po/fr.po
File diff suppressed because it is too large
Load diff
687
main/po/gl.po
687
main/po/gl.po
File diff suppressed because it is too large
Load diff
701
main/po/hu.po
701
main/po/hu.po
File diff suppressed because it is too large
Load diff
670
main/po/id.po
670
main/po/id.po
File diff suppressed because it is too large
Load diff
671
main/po/ie.po
671
main/po/ie.po
File diff suppressed because it is too large
Load diff
1149
main/po/is.po
Normal file
1149
main/po/is.po
Normal file
File diff suppressed because it is too large
Load diff
679
main/po/it.po
679
main/po/it.po
File diff suppressed because it is too large
Load diff
683
main/po/ja.po
683
main/po/ja.po
File diff suppressed because it is too large
Load diff
667
main/po/kab.po
667
main/po/kab.po
File diff suppressed because it is too large
Load diff
1048
main/po/ko.po
1048
main/po/ko.po
File diff suppressed because it is too large
Load diff
676
main/po/lb.po
676
main/po/lb.po
File diff suppressed because it is too large
Load diff
700
main/po/lt.po
700
main/po/lt.po
File diff suppressed because it is too large
Load diff
673
main/po/nb.po
673
main/po/nb.po
File diff suppressed because it is too large
Load diff
678
main/po/nl.po
678
main/po/nl.po
File diff suppressed because it is too large
Load diff
1185
main/po/nl_BE.po
1185
main/po/nl_BE.po
File diff suppressed because it is too large
Load diff
695
main/po/oc.po
695
main/po/oc.po
File diff suppressed because it is too large
Load diff
693
main/po/pl.po
693
main/po/pl.po
File diff suppressed because it is too large
Load diff
784
main/po/pt.po
784
main/po/pt.po
File diff suppressed because it is too large
Load diff
713
main/po/pt_BR.po
713
main/po/pt_BR.po
File diff suppressed because it is too large
Load diff
678
main/po/ro.po
678
main/po/ro.po
File diff suppressed because it is too large
Load diff
694
main/po/ru.po
694
main/po/ru.po
File diff suppressed because it is too large
Load diff
690
main/po/sq.po
690
main/po/sq.po
File diff suppressed because it is too large
Load diff
677
main/po/sv.po
677
main/po/sv.po
File diff suppressed because it is too large
Load diff
653
main/po/ta.po
653
main/po/ta.po
File diff suppressed because it is too large
Load diff
674
main/po/tr.po
674
main/po/tr.po
File diff suppressed because it is too large
Load diff
683
main/po/uk.po
683
main/po/uk.po
File diff suppressed because it is too large
Load diff
699
main/po/zh_CN.po
699
main/po/zh_CN.po
File diff suppressed because it is too large
Load diff
670
main/po/zh_TW.po
670
main/po/zh_TW.po
File diff suppressed because it is too large
Load diff
|
@ -14,7 +14,7 @@ protected class RosterList {
|
|||
private ulong[] handler_ids = new ulong[0];
|
||||
|
||||
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) {
|
||||
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) {
|
||||
on_removed_roster_item(account, jid, roster_item);
|
||||
ListRow row = new ListRow.from_jid(stream_interactor, roster_item.jid, account, accounts.size > 1);
|
||||
rows[account][jid] = row;
|
||||
list_box.append(row);
|
||||
ListBoxRow list_box_row = new ListBoxRow() { child=row };
|
||||
rows[account][jid] = list_box_row;
|
||||
list_box.append(list_box_row);
|
||||
list_box.invalidate_sort();
|
||||
list_box.invalidate_filter();
|
||||
}
|
||||
|
||||
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)) {
|
||||
on_updated_roster_item(account, roster_item.jid, roster_item);
|
||||
}
|
||||
|
|
|
@ -80,7 +80,7 @@ public class SelectContactDialog : Gtk.Dialog {
|
|||
add_contact_dialog.present();
|
||||
});
|
||||
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);
|
||||
});
|
||||
select_jid_fragment.notify["done"].connect(() => {
|
||||
|
|
|
@ -4,7 +4,7 @@ using Dino.Entities;
|
|||
using Dino.Ui;
|
||||
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_ADD_CHAT = {"<Ctrl>T", 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");
|
||||
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();
|
||||
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;
|
||||
}
|
||||
}
|
||||
Gtk.AboutDialog dialog = new Gtk.AboutDialog();
|
||||
dialog.destroy_with_parent = true;
|
||||
dialog.transient_for = window;
|
||||
dialog.modal = true;
|
||||
dialog.title = _("About Dino");
|
||||
|
||||
dialog.logo_icon_name = "im.dino.Dino";
|
||||
dialog.program_name = "Dino";
|
||||
dialog.version = version;
|
||||
dialog.comments = "Dino. Communicating happiness.";
|
||||
dialog.website = "https://dino.im/";
|
||||
dialog.website_label = "dino.im";
|
||||
dialog.copyright = "Copyright © 2016-2022 - Dino Team";
|
||||
dialog.license_type = License.GPL_3_0;
|
||||
#if Adw_1_2
|
||||
Adw.AboutWindow about_window = new Adw.AboutWindow();
|
||||
about_window.application_icon = "im.dino.Dino";
|
||||
about_window.application_name = "Dino";
|
||||
#else
|
||||
Gtk.AboutDialog about_window = new Gtk.AboutDialog();
|
||||
about_window.logo_icon_name = "im.dino.Dino";
|
||||
about_window.program_name = "Dino";
|
||||
about_window.website_label = "dino.im";
|
||||
#endif
|
||||
about_window.destroy_with_parent = true;
|
||||
about_window.transient_for = window;
|
||||
about_window.modal = true;
|
||||
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()) {
|
||||
dialog.set_titlebar(null);
|
||||
about_window.set_titlebar(null);
|
||||
}
|
||||
dialog.present();
|
||||
about_window.present();
|
||||
}
|
||||
|
||||
private void show_join_muc_dialog(Account? account, string jid) {
|
||||
|
|
|
@ -74,7 +74,7 @@ public class ChatInputController : Object {
|
|||
quoted_content_item = content_item;
|
||||
var quote_model = new Quote.Model.from_content_item(content_item, conversation, stream_interactor) { can_abort = true };
|
||||
quote_model.aborted.connect(() => {
|
||||
content_item = null;
|
||||
quoted_content_item = null;
|
||||
chat_input.unset_quoted_message();
|
||||
});
|
||||
chat_input.set_quoted_message(Quote.get_widget(quote_model));
|
||||
|
@ -83,8 +83,8 @@ public class ChatInputController : Object {
|
|||
}
|
||||
|
||||
public void set_conversation(Conversation conversation) {
|
||||
this.quoted_content_item = null;
|
||||
reset_input_field_status();
|
||||
this.quoted_content_item = null;
|
||||
chat_input.unset_quoted_message();
|
||||
|
||||
this.conversation = conversation;
|
||||
|
|
|
@ -49,6 +49,12 @@ public class SettingsProvider : Plugins.ContactDetailsProvider, Object {
|
|||
combobox.active_id = get_notify_setting_id(conversation.notify_setting);
|
||||
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) {
|
||||
|
|
|
@ -37,7 +37,7 @@ public class ConversationItemSkeleton : Plugins.ConversationItemWidgetInterface,
|
|||
private uint time_update_timeout = 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.conversation = conversation;
|
||||
this.item = item;
|
||||
|
|
|
@ -9,6 +9,7 @@ namespace Dino.Ui.ConversationSummary {
|
|||
|
||||
[GtkTemplate (ui = "/im/dino/Dino/conversation_content_view/view.ui")]
|
||||
public class ConversationView : Widget, Plugins.ConversationItemCollection, Plugins.NotificationCollection {
|
||||
private const int MESSAGE_MENU_BOX_OFFSET = -20;
|
||||
|
||||
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 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.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>();
|
||||
|
@ -36,7 +37,6 @@ public class ConversationView : Widget, Plugins.ConversationItemCollection, Plug
|
|||
private double? was_page_size;
|
||||
|
||||
private Mutex reloading_mutex = Mutex();
|
||||
private bool animate = false;
|
||||
private bool firstLoad = true;
|
||||
private bool at_current_content = true;
|
||||
private bool reload_messages = true;
|
||||
|
@ -81,6 +81,15 @@ public class ConversationView : Widget, Plugins.ConversationItemCollection, Plug
|
|||
main.add_controller(main_motion_events);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -173,7 +182,7 @@ public class ConversationView : Widget, Plugins.ConversationItemCollection, Plug
|
|||
currently_highlighted.add_css_class("highlight");
|
||||
|
||||
// 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();
|
||||
button.icon_name = message_actions[i].icon_name;
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -209,6 +219,7 @@ public class ConversationView : Widget, Plugins.ConversationItemCollection, Plug
|
|||
button.clicked.connect(() => {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -231,12 +242,71 @@ public class ConversationView : Widget, Plugins.ConversationItemCollection, Plug
|
|||
});
|
||||
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();
|
||||
initialize_for_conversation_(conversation);
|
||||
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) {
|
||||
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();
|
||||
initialize_for_conversation_(conversation);
|
||||
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);
|
||||
}
|
||||
ContentMetaItem meta_item = content_populator.get_content_meta_item(content_item);
|
||||
meta_item.can_merge = false;
|
||||
Widget w = insert_new(meta_item);
|
||||
content_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.
|
||||
reload_messages = false;
|
||||
Timeout.add(700, () => {
|
||||
int h = 0, i = 0;
|
||||
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");
|
||||
scroll_and_highlight_item(meta_item, 300);
|
||||
reload_messages = true;
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
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
|
||||
Dino.Application app = Dino.Application.get_default();
|
||||
if (this.conversation != null) {
|
||||
|
@ -298,9 +360,6 @@ public class ConversationView : Widget, Plugins.ConversationItemCollection, Plug
|
|||
}
|
||||
content_populator.init(this, conversation, Plugins.WidgetType.GTK4);
|
||||
subscription_notification.init(conversation, this);
|
||||
|
||||
animate = false;
|
||||
Timeout.add(20, () => { animate = true; return false; });
|
||||
}
|
||||
|
||||
private void display_latest() {
|
||||
|
@ -330,8 +389,8 @@ public class ConversationView : Widget, Plugins.ConversationItemCollection, Plug
|
|||
public void do_insert_item(Plugins.MetaConversationItem item) {
|
||||
lock (meta_items) {
|
||||
insert_new(item);
|
||||
if (item as ContentMetaItem != null) {
|
||||
content_items.add(item);
|
||||
if (item is ContentMetaItem) {
|
||||
content_items.add((ContentMetaItem)item);
|
||||
}
|
||||
meta_items.add(item);
|
||||
}
|
||||
|
@ -347,7 +406,9 @@ public class ConversationView : Widget, Plugins.ConversationItemCollection, Plug
|
|||
widget_order.remove(skeleton.get_widget());
|
||||
item_item_skeletons.unset(item);
|
||||
|
||||
content_items.remove(item);
|
||||
if (item is ContentMetaItem) {
|
||||
content_items.remove((ContentMetaItem)item);
|
||||
}
|
||||
meta_items.remove(item);
|
||||
}
|
||||
|
||||
|
@ -386,7 +447,7 @@ public class ConversationView : Widget, Plugins.ConversationItemCollection, Plug
|
|||
Plugins.MetaConversationItem? lower_item = meta_items.lower(item);
|
||||
|
||||
// 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;
|
||||
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());
|
||||
|
@ -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) {
|
||||
int cmp1 = a.time.compare(b.time);
|
||||
if (cmp1 != 0) return cmp1;
|
||||
|
|
|
@ -10,9 +10,6 @@ namespace Dino.Ui {
|
|||
public class FileDefaultWidget : Box {
|
||||
|
||||
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 Label name_label;
|
||||
|
@ -23,12 +20,6 @@ public class FileDefaultWidget : Box {
|
|||
|
||||
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() {
|
||||
EventControllerMotion this_motion_events = new EventControllerMotion();
|
||||
this.add_controller(this_motion_events);
|
||||
|
|
|
@ -8,64 +8,70 @@ namespace Dino.Ui {
|
|||
|
||||
public class FileImageWidget : Box {
|
||||
|
||||
private ScalingImage image;
|
||||
FileDefaultWidget file_default_widget;
|
||||
FileDefaultWidgetController file_default_widget_controller;
|
||||
|
||||
public FileImageWidget() {
|
||||
this.halign = Align.START;
|
||||
|
||||
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 {
|
||||
// Load and prepare image in tread
|
||||
Thread<ScalingImage?> thread = new Thread<ScalingImage?> (null, () => {
|
||||
ScalingImage image = new ScalingImage() { halign=Align.START, visible = true, max_width = MAX_WIDTH, max_height = MAX_HEIGHT };
|
||||
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 };
|
||||
image_overlay_toolbar.add_css_class("card");
|
||||
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;
|
||||
try {
|
||||
pixbuf = new Gdk.Pixbuf.from_file(file.get_path());
|
||||
} catch (Error error) {
|
||||
warning("Can't load picture %s - %s", file.get_path(), error.message);
|
||||
Idle.add(load_from_file.callback);
|
||||
return null;
|
||||
FixedRatioPicture image = new FixedRatioPicture() { min_width=100, min_height=100, max_width=MAX_WIDTH, max_height=MAX_HEIGHT, file=file };
|
||||
GestureClick gesture_click_controller = new GestureClick();
|
||||
gesture_click_controller.button = 1; // listen for left clicks
|
||||
gesture_click_controller.released.connect((n_press, x, y) => {
|
||||
switch (gesture_click_controller.get_device().source) {
|
||||
case Gdk.InputSource.TOUCHSCREEN:
|
||||
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 = thread.join();
|
||||
if (image == null) throw new Error(-1, 0, "Error loading image");
|
||||
image.add_controller(gesture_click_controller);
|
||||
|
||||
FileInfo file_info = file.query_info("*", FileQueryInfoFlags.NONE);
|
||||
string? mime_type = Dino.Util.get_content_type(file_info);
|
||||
|
||||
file_default_widget = new FileDefaultWidget() { valign=Align.END, vexpand=false, visible=false };
|
||||
file_default_widget.image_stack.visible = false;
|
||||
file_default_widget_controller = new FileDefaultWidgetController(file_default_widget);
|
||||
file_default_widget_controller.set_file(file, file_name, mime_type);
|
||||
MenuButton button = new MenuButton();
|
||||
button.icon_name = "open-menu";
|
||||
Menu menu_model = new Menu();
|
||||
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.set_child(image);
|
||||
overlay.add_overlay(file_default_widget);
|
||||
overlay.add_overlay(image_overlay_toolbar);
|
||||
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();
|
||||
this.add_controller(this_motion_events);
|
||||
this_motion_events.enter.connect(() => {
|
||||
file_default_widget.visible = true;
|
||||
image_overlay_toolbar.visible = true;
|
||||
});
|
||||
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);
|
||||
|
|
|
@ -10,19 +10,46 @@ namespace Dino.Ui {
|
|||
public class FileMetaItem : ConversationSummary.ContentMetaItem {
|
||||
|
||||
private StreamInteractor stream_interactor;
|
||||
private FileItem file_item;
|
||||
private FileTransfer file_transfer;
|
||||
|
||||
public FileMetaItem(ContentItem content_item, StreamInteractor stream_interactor) {
|
||||
base(content_item);
|
||||
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) {
|
||||
FileItem file_item = content_item as FileItem;
|
||||
FileTransfer transfer = file_item.file_transfer;
|
||||
return new FileWidget(stream_interactor, transfer);
|
||||
FileWidget widget = new FileWidget(file_transfer);
|
||||
FileWidgetController widget_controller = new FileWidgetController(widget, file_transfer, stream_interactor);
|
||||
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 {
|
||||
|
@ -32,7 +59,6 @@ public class FileWidget : SizeRequestBox {
|
|||
DEFAULT
|
||||
}
|
||||
|
||||
private StreamInteractor stream_interactor;
|
||||
private FileTransfer file_transfer;
|
||||
public FileTransfer.State file_transfer_state { get; set; }
|
||||
public string file_transfer_mime_type { get; set; }
|
||||
|
@ -41,13 +67,24 @@ public class FileWidget : SizeRequestBox {
|
|||
private FileDefaultWidgetController default_widget_controller;
|
||||
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 {
|
||||
margin_top = 4;
|
||||
size_request_mode = SizeRequestMode.HEIGHT_FOR_WIDTH;
|
||||
}
|
||||
|
||||
public FileWidget(StreamInteractor stream_interactor, FileTransfer file_transfer) {
|
||||
this.stream_interactor = stream_interactor;
|
||||
public FileWidget(FileTransfer file_transfer) {
|
||||
this.file_transfer = file_transfer;
|
||||
|
||||
update_widget.begin();
|
||||
|
@ -88,7 +125,7 @@ public class FileWidget : SizeRequestBox {
|
|||
if (content != null) this.remove(content);
|
||||
FileDefaultWidget default_file_widget = new FileDefaultWidget();
|
||||
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;
|
||||
this.state = State.DEFAULT;
|
||||
this.append(content);
|
||||
|
@ -113,94 +150,104 @@ public class FileWidget : SizeRequestBox {
|
|||
}
|
||||
}
|
||||
|
||||
public class FileDefaultWidgetController : 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; }
|
||||
public class FileWidgetController : Object {
|
||||
|
||||
private weak Widget widget;
|
||||
private FileTransfer file_transfer;
|
||||
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;
|
||||
|
||||
widget.clicked.connect(on_clicked);
|
||||
widget.open_file.connect(open_file);
|
||||
widget.save_file_as.connect(save_file);
|
||||
widget.cancel_download.connect(cancel_download);
|
||||
}
|
||||
|
||||
public void set_file_transfer(FileTransfer file_transfer, StreamInteractor stream_interactor) {
|
||||
this.ref();
|
||||
this.widget.weak_ref(() => {
|
||||
this.widget = null;
|
||||
this.unref();
|
||||
});
|
||||
this.file_transfer = file_transfer;
|
||||
this.stream_interactor = stream_interactor;
|
||||
|
||||
widget.name_label.label = file_name = file_transfer.file_name;
|
||||
|
||||
file_transfer.bind_property("path", this, "file-transfer-path");
|
||||
file_transfer.bind_property("state", this, "file-transfer-state");
|
||||
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);
|
||||
widget.open_file.connect(open_file);
|
||||
widget.save_file_as.connect(save_file);
|
||||
widget.start_download.connect(start_download);
|
||||
widget.cancel_download.connect(cancel_download);
|
||||
}
|
||||
|
||||
private void open_file() {
|
||||
try{
|
||||
Dino.Util.launch_default_for_uri(file_uri);
|
||||
Dino.Util.launch_default_for_uri(file_transfer.get_file().get_uri());
|
||||
} 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() {
|
||||
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_current_name(file_name);
|
||||
save_dialog.set_current_name(file_transfer.file_name);
|
||||
|
||||
save_dialog.response.connect(() => {
|
||||
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) {
|
||||
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();
|
||||
}
|
||||
|
||||
private void start_download() {
|
||||
if (stream_interactor != null) {
|
||||
stream_interactor.get_module(FileManager.IDENTITY).download_file.begin(file_transfer);
|
||||
}
|
||||
}
|
||||
|
||||
private void cancel_download() {
|
||||
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() {
|
||||
switch (state) {
|
||||
case FileTransfer.State.COMPLETE:
|
||||
open_file();
|
||||
widget.activate_action("file.open", null);
|
||||
break;
|
||||
case FileTransfer.State.NOT_STARTED:
|
||||
assert(stream_interactor != null && file_transfer != null);
|
||||
stream_interactor.get_module(FileManager.IDENTITY).download_file.begin(file_transfer);
|
||||
widget.activate_action("file.download", null);
|
||||
break;
|
||||
default:
|
||||
// Clicking doesn't do anything in FAILED and IN_PROGRESS states
|
||||
|
|
|
@ -198,7 +198,7 @@ public class MessageMetaItem : ContentMetaItem {
|
|||
if (quoted_content_item != null) {
|
||||
var quote_model = new Quote.Model.from_content_item(quoted_content_item, message_item.conversation, stream_interactor);
|
||||
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);
|
||||
outer.set_widget(quote_widget, Plugins.WidgetType.GTK4, 1);
|
||||
|
@ -217,6 +217,7 @@ public class MessageMetaItem : ContentMetaItem {
|
|||
if (correction_allowed) {
|
||||
Plugins.MessageAction action1 = new Plugins.MessageAction();
|
||||
action1.icon_name = "document-edit-symbolic";
|
||||
action1.tooltip = _("Edit message");
|
||||
action1.callback = (button, content_meta_item_activated, widget) => {
|
||||
this.in_edit_mode = true;
|
||||
};
|
||||
|
@ -225,14 +226,16 @@ public class MessageMetaItem : ContentMetaItem {
|
|||
|
||||
Plugins.MessageAction reply_action = new Plugins.MessageAction();
|
||||
reply_action.icon_name = "mail-reply-sender-symbolic";
|
||||
reply_action.tooltip = _("Reply");
|
||||
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);
|
||||
|
||||
if (supports_reaction) {
|
||||
Plugins.MessageAction action2 = new Plugins.MessageAction();
|
||||
action2.icon_name = "dino-emoticon-add-symbolic";
|
||||
action2.tooltip = _("Add reaction");
|
||||
EmojiChooser chooser = new EmojiChooser();
|
||||
chooser.emoji_picked.connect((emoji) => {
|
||||
stream_interactor.get_module(Reactions.IDENTITY).add_reaction(message_item.conversation, message_item, emoji);
|
||||
|
|
|
@ -27,7 +27,8 @@ namespace Dino.Ui.Quote {
|
|||
var message = ((MessageItem) content_item).message;
|
||||
this.message = Dino.message_body_without_reply_fallback(message);
|
||||
} 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;
|
||||
|
||||
|
|
|
@ -123,9 +123,10 @@ public class ReactionsWidget : Grid {
|
|||
public ReactionsWidget() {
|
||||
this.row_spacing = this.column_spacing = 5;
|
||||
this.margin_top = 2;
|
||||
this.add_css_class("reaction-grid");
|
||||
|
||||
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);
|
||||
|
||||
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 count_label = new Label("") { use_markup=true };
|
||||
Button button = new Button();
|
||||
button.get_style_context().add_class("reaction-box");
|
||||
Box reaction_box = new Box(Orientation.HORIZONTAL, 4);
|
||||
button.add_css_class("pill");
|
||||
Box reaction_box = new Box(Orientation.HORIZONTAL, 4) { halign=Align.CENTER };
|
||||
reaction_box.append(reaction_label);
|
||||
reaction_box.append(count_label);
|
||||
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>";
|
||||
if (own) {
|
||||
reaction_buttons[reaction].get_style_context().add_class("own-reaction");
|
||||
reaction_buttons[reaction].add_css_class("own-reaction");
|
||||
} else {
|
||||
reaction_buttons[reaction].get_style_context().remove_class("own-reaction");
|
||||
reaction_buttons[reaction].remove_css_class("own-reaction");
|
||||
}
|
||||
|
||||
// Build tooltip
|
||||
|
|
|
@ -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");
|
||||
MenuButton add_button = (MenuButton) builder.get_object("add_button");
|
||||
MenuButton menu_button = (MenuButton) builder.get_object("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) {
|
||||
|
|
|
@ -38,7 +38,6 @@ public class ConversationSelector : Widget {
|
|||
|
||||
construct {
|
||||
add_css_class("sidebar");
|
||||
list_box.set_header_func(header);
|
||||
list_box.set_sort_func(sort);
|
||||
|
||||
realize.connect(() => {
|
||||
|
@ -75,6 +74,8 @@ public class ConversationSelector : Widget {
|
|||
private void add_conversation(Conversation conversation) {
|
||||
ConversationSelectorRow row;
|
||||
if (!rows.has_key(conversation)) {
|
||||
conversation.notify["pinned"].connect(list_box.invalidate_sort);
|
||||
|
||||
row = new ConversationSelectorRow(stream_interactor, conversation);
|
||||
rows[conversation] = row;
|
||||
list_box.append(row);
|
||||
|
@ -119,6 +120,8 @@ public class ConversationSelector : Widget {
|
|||
private async void remove_conversation(Conversation conversation) {
|
||||
select_fallback_conversation(conversation);
|
||||
if (rows.has_key(conversation)) {
|
||||
conversation.notify["pinned"].disconnect(list_box.invalidate_sort);
|
||||
|
||||
yield rows[conversation].colapse();
|
||||
list_box.remove(rows[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) {
|
||||
ConversationSelectorRow cr1 = row1 as ConversationSelectorRow;
|
||||
ConversationSelectorRow cr2 = row2 as ConversationSelectorRow;
|
||||
if (cr1 != null && cr2 != null) {
|
||||
Conversation c1 = cr1.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 (c2.last_active == null) return 1;
|
||||
int comp = c2.last_active.compare(c1.last_active);
|
||||
|
|
|
@ -21,7 +21,8 @@ public class ConversationSelectorRow : ListBoxRow {
|
|||
[GtkChild] protected unowned Button x_button;
|
||||
[GtkChild] protected unowned Revealer time_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;
|
||||
|
||||
public Conversation conversation { get; private set; }
|
||||
|
@ -102,8 +103,10 @@ public class ConversationSelectorRow : ListBoxRow {
|
|||
});
|
||||
image.set_conversation(stream_interactor, conversation);
|
||||
conversation.notify["read-up-to-item"].connect(() => update_read());
|
||||
conversation.notify["pinned"].connect(() => { update_pinned_icon(); });
|
||||
|
||||
update_name_label();
|
||||
update_pinned_icon();
|
||||
content_item_received();
|
||||
}
|
||||
|
||||
|
@ -135,6 +138,10 @@ public class ConversationSelectorRow : ListBoxRow {
|
|||
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) {
|
||||
if (last_content_item != null) {
|
||||
time_label.visible = true;
|
||||
|
@ -252,11 +259,11 @@ public class ConversationSelectorRow : ListBoxRow {
|
|||
StateFlags curr_flags = get_state_flags();
|
||||
if ((curr_flags & StateFlags.PRELIGHT) != 0) {
|
||||
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);
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,9 @@ public interface ConversationTitlebar : Object {
|
|||
|
||||
public abstract void insert_button(Widget button);
|
||||
public abstract Widget get_widget();
|
||||
|
||||
public abstract bool back_button_visible{ get; set; }
|
||||
public signal void back_pressed();
|
||||
}
|
||||
|
||||
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 Label title_label = new Label("") { ellipsize=EllipsizeMode.END };
|
||||
private Label subtitle_label = new Label("") { use_markup=true, ellipsize=EllipsizeMode.END, visible=false };
|
||||
private Revealer back_revealer;
|
||||
|
||||
construct {
|
||||
Box content_box = new Box(Orientation.HORIZONTAL, 0) { margin_start=15, margin_end=10, hexpand=true };
|
||||
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 };
|
||||
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? 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 subtitle_label = new Label("") { ellipsize=EllipsizeMode.END, visible=false };
|
||||
private Revealer back_revealer;
|
||||
|
||||
public ConversationTitlebarCsd() {
|
||||
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");
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ class OccupantsEntry : Plugins.ConversationTitlebarEntry, Object {
|
|||
StreamInteractor stream_interactor;
|
||||
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;
|
||||
|
||||
|
|
|
@ -151,6 +151,8 @@ public class GlobalSearch {
|
|||
}
|
||||
|
||||
private void clear_search() {
|
||||
// Scroll to top
|
||||
results_scrolled.vadjustment.value = 0;
|
||||
foreach (Widget widget in results_box_children) {
|
||||
results_box.remove(widget);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ using Dino.Entities;
|
|||
|
||||
namespace Dino.Ui {
|
||||
|
||||
public class MainWindow : Gtk.Window {
|
||||
public class MainWindow : Adw.Window {
|
||||
|
||||
public signal void conversation_selected(Conversation conversation);
|
||||
|
||||
|
@ -19,11 +19,11 @@ public class MainWindow : Gtk.Window {
|
|||
public ConversationSelector conversation_selector;
|
||||
public ConversationTitlebar conversation_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 Paned headerbar_paned = new Paned(Orientation.HORIZONTAL) { resize_start_child=false, shrink_start_child=false, shrink_end_child=false };
|
||||
public Paned paned;
|
||||
public Revealer search_revealer;
|
||||
public Adw.Leaflet leaflet;
|
||||
public Box left_box;
|
||||
public Box right_box;
|
||||
public Adw.Flap search_flap;
|
||||
public GlobalSearch global_search;
|
||||
private Stack stack = new Stack();
|
||||
private Stack left_stack;
|
||||
|
@ -35,7 +35,7 @@ public class MainWindow : Gtk.Window {
|
|||
|
||||
class construct {
|
||||
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;
|
||||
}));
|
||||
add_shortcut(shortcut);
|
||||
|
@ -51,65 +51,56 @@ public class MainWindow : Gtk.Window {
|
|||
|
||||
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);
|
||||
|
||||
setup_headerbar();
|
||||
setup_unified();
|
||||
setup_headerbar();
|
||||
setup_stack();
|
||||
|
||||
paned.bind_property("position", headerbar_paned, "position", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL);
|
||||
}
|
||||
|
||||
private void setup_unified() {
|
||||
Builder builder = new Builder.from_resource("/im/dino/Dino/unified_main_content.ui");
|
||||
paned = (Paned) builder.get_object("paned");
|
||||
box.append(paned);
|
||||
leaflet = (Adw.Leaflet) builder.get_object("leaflet");
|
||||
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");
|
||||
right_stack = (Stack) builder.get_object("right_stack");
|
||||
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.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);
|
||||
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() {
|
||||
if (Util.use_csd()) {
|
||||
conversation_list_titlebar = get_conversation_list_titlebar_csd();
|
||||
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 {
|
||||
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_titlebar = new ConversationTitlebarNoCsd();
|
||||
box.append(headerbar_paned);
|
||||
}
|
||||
headerbar_paned.set_start_child(conversation_list_titlebar);
|
||||
headerbar_paned.set_end_child(conversation_titlebar.get_widget());
|
||||
}
|
||||
|
||||
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] + ":";
|
||||
left_box.prepend(conversation_list_titlebar);
|
||||
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 setup_stack() {
|
||||
stack.add_named(box, "main");
|
||||
stack.add_named(welcome_placeholder, "welcome_placeholder");
|
||||
stack.add_named(accounts_placeholder, "accounts_placeholder");
|
||||
set_child(stack);
|
||||
set_content(stack);
|
||||
}
|
||||
|
||||
public enum StackState {
|
||||
|
@ -125,25 +116,16 @@ public class MainWindow : Gtk.Window {
|
|||
right_stack.set_visible_child_name("content");
|
||||
|
||||
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) {
|
||||
if (stack_state == StackState.CLEAN_START) {
|
||||
stack.set_visible_child_name("welcome_placeholder");
|
||||
} else if (stack_state == StackState.NO_ACTIVE_ACCOUNTS) {
|
||||
stack.set_visible_child_name("accounts_placeholder");
|
||||
}
|
||||
if (Util.use_csd()) {
|
||||
set_titlebar(placeholder_headerbar);
|
||||
}
|
||||
} else if (stack_state == StackState.NO_ACTIVE_CONVERSATIONS) {
|
||||
stack.set_visible_child_name("main");
|
||||
left_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 WelcomePlaceholder() {
|
||||
title_label.label = _("Welcome to Dino!");
|
||||
label.label = _("Sign in or create an account to get started.");
|
||||
status_page.title = _("Welcome to Dino!");
|
||||
status_page.description = _("Sign in or create an account to get started.");
|
||||
primary_button.label = _("Set up account");
|
||||
title_label.visible = true;
|
||||
secondary_button.visible = false;
|
||||
primary_button.visible = true;
|
||||
}
|
||||
}
|
||||
|
||||
public class NoAccountsPlaceholder : MainWindowPlaceholder {
|
||||
public NoAccountsPlaceholder() {
|
||||
title_label.label = _("No active accounts");
|
||||
status_page.title = _("No active accounts");
|
||||
primary_button.label = _("Manage accounts");
|
||||
title_label.visible = true;
|
||||
label.visible = false;
|
||||
secondary_button.visible = false;
|
||||
primary_button.visible = true;
|
||||
}
|
||||
}
|
||||
|
||||
[GtkTemplate (ui = "/im/dino/Dino/unified_window_placeholder.ui")]
|
||||
public class MainWindowPlaceholder : Box {
|
||||
[GtkChild] public unowned Label title_label;
|
||||
[GtkChild] public unowned Label label;
|
||||
[GtkChild] public unowned Adw.StatusPage status_page;
|
||||
[GtkChild] public unowned Button primary_button;
|
||||
[GtkChild] public unowned Button secondary_button;
|
||||
}
|
||||
|
|
|
@ -45,10 +45,10 @@ public class MainWindowController : Object {
|
|||
|
||||
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(() => {
|
||||
if (window.search_revealer.child_revealed) {
|
||||
window.search_flap.notify["reveal-flap"].connect(() => {
|
||||
if (window.search_flap.reveal_flap) {
|
||||
if (window.conversation_view.conversation_frame.conversation != null && window.global_search.search_entry.text == "") {
|
||||
reset_search_entry();
|
||||
}
|
||||
|
@ -59,7 +59,9 @@ public class MainWindowController : Object {
|
|||
window.global_search.selected_item.connect((item) => {
|
||||
select_conversation(item.conversation, false, false);
|
||||
window.conversation_view.conversation_frame.initialize_around_message(item.conversation, item);
|
||||
close_search();
|
||||
if (window.search_flap.folded) {
|
||||
close_search();
|
||||
}
|
||||
});
|
||||
|
||||
window.welcome_placeholder.primary_button.clicked.connect(() => {
|
||||
|
@ -91,16 +93,6 @@ public class MainWindowController : Object {
|
|||
|
||||
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();
|
||||
window_widget.add_controller(key_event_controller);
|
||||
// TODO GTK4: Why doesn't this work with key_pressed signal
|
||||
|
|
|
@ -419,7 +419,8 @@ public string summarize_whitespaces_to_space(string s) {
|
|||
try {
|
||||
return (/\s+/).replace_literal(s, -1, 0, " ");
|
||||
} catch (RegexError e) {
|
||||
assert_not_reached();
|
||||
critical("RegexError when summarizing whitespaces in '%s': %s", s, e.message);
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
88
main/src/ui/widgets/fixed_ratio_picture.vala
Normal file
88
main/src/ui/widgets/fixed_ratio_picture.vala
Normal 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();
|
||||
}
|
||||
}
|
59
main/src/ui/widgets/natural_size_increase.vala
Normal file
59
main/src/ui/widgets/natural_size_increase.vala
Normal 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;
|
||||
}
|
||||
}
|
|
@ -241,7 +241,9 @@
|
|||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<child>
|
||||
<object class="GtkImage" id="qrcode_image"/>
|
||||
<object class="GtkPicture" id="qrcode_picture">
|
||||
<property name="can-shrink">False</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
|
|
|
@ -20,7 +20,6 @@ lb
|
|||
lt
|
||||
nb
|
||||
nl
|
||||
nl_BE
|
||||
oc
|
||||
pl
|
||||
pt
|
||||
|
|
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\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"
|
||||
"Language-Team: Arabic <https://hosted.weblate.org/projects/dino/plugin-omemo/"
|
||||
"ar/>\n"
|
||||
|
@ -36,39 +36,39 @@ msgid ""
|
|||
"%s does not trust this device. That means, you might be missing messages."
|
||||
msgstr "%s لا يثق بهذا الجهاز. هذا يعني أنك قد تفقد بعض الرسائل."
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:35
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:34
|
||||
msgid "Manage Key"
|
||||
msgstr "إدارة المفتاح"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:36
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:35
|
||||
msgid ""
|
||||
"Compare the fingerprint, character by character, with the one shown on your "
|
||||
"contact's device."
|
||||
msgstr "قارن البصمة حرفا بحرف ، مع التي تظهر على جهاز مُراسِلك."
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:37
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:36
|
||||
msgid "Fingerprints differ"
|
||||
msgstr "البصمات غير متطابقة"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:38
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:37
|
||||
msgid "Fingerprints match"
|
||||
msgstr "البصمات متطابقة"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:39
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:82
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:88
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:38
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:81
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:87
|
||||
msgid "Cancel"
|
||||
msgstr "ألغاء"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:40
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:39
|
||||
msgid "Confirm"
|
||||
msgstr "تأكيد"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:60
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:59
|
||||
msgid "Verify key"
|
||||
msgstr "التحقق مِن المفتاح"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:61
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:60
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Future messages sent by %s from the device that uses this key will be "
|
||||
|
@ -77,11 +77,11 @@ msgstr ""
|
|||
"سيتم تمييز الرسائل القادمة المرسلة بواسطة %s من الجهاز الذي يستخدم هذا "
|
||||
"المفتاح وفقًا لذلك في نافذة الدردشة."
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:71
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:70
|
||||
msgid "Fingerprints do not match"
|
||||
msgstr "البصمات غير متطابقة"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:72
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:71
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Please verify that you are comparing the correct fingerprint. If "
|
||||
|
@ -92,69 +92,69 @@ msgstr ""
|
|||
"المحتمل أنّ حساب %s قد تعرض لاختراق وأنه مِن المستحسن التفكير في رفض هذا "
|
||||
"المفتاح."
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:124
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:123
|
||||
msgid "Verify key fingerprint"
|
||||
msgstr "التحقق مِن مفتاح البصمة"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:124
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:123
|
||||
msgid ""
|
||||
"Compare this key's fingerprint with the fingerprint displayed on the "
|
||||
"contact's device."
|
||||
msgstr "قارن بصمة هذا المفتاح مع البصمة المعروضة على جهاز مُراسِلك."
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:126
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:152
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:256
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:125
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:151
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:269
|
||||
msgid "Reject key"
|
||||
msgstr "رفض المفتاح"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:126
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:125
|
||||
msgid ""
|
||||
"Block encrypted communication with the contact's device that uses this key."
|
||||
msgstr "حظر الاتصال المشفر مع جهاز المراسل الذي يستخدم هذا المفتاح."
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:128
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:160
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:251
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:127
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:159
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:264
|
||||
msgid "Accept key"
|
||||
msgstr "اقبل المفتاح"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:128
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:127
|
||||
msgid ""
|
||||
"Allow encrypted communication with the contact's device that uses this key."
|
||||
msgstr "السماح بالاتصال المشفر بجهاز المراسل الذي يستخدم هذا المفتاح."
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:132
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:137
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:141
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:131
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:136
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:140
|
||||
#, c-format
|
||||
msgid "This key is currently %s."
|
||||
msgstr "المفتاح الآن %s."
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:132
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:131
|
||||
msgid "accepted"
|
||||
msgstr "مقبول"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:132
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:137
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:131
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:136
|
||||
#, c-format
|
||||
msgid "This means it can be used by %s to receive and send encrypted messages."
|
||||
msgstr "ذلك يعني أنه بإمكان %s أن يستخدمه لتلقي وإرسال رسائل مشفرة."
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:137
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:136
|
||||
msgid "verified"
|
||||
msgstr "تم التحقق منه"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:137
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:136
|
||||
msgid ""
|
||||
"Additionally it has been verified to match the key on the contact's device."
|
||||
msgstr "بالإضافة إلى أنه قد تم التحقق من تطابق المفتاح على جهاز المُراسِل."
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:141
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:140
|
||||
msgid "rejected"
|
||||
msgstr "مرفوض"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:141
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:140
|
||||
#, c-format
|
||||
msgid ""
|
||||
"This means it cannot be used by %s to decipher your messages, and you won't "
|
||||
|
@ -163,7 +163,7 @@ msgstr ""
|
|||
"هذا يعني أنه لن يكون بمقدور %s استخدامه لفك تشفير رسائلك، ولن ترى الرسائل "
|
||||
"المشفرة به."
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:153
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:152
|
||||
#, c-format
|
||||
msgid ""
|
||||
"You won't see encrypted messages from the device of %s that uses this key. "
|
||||
|
@ -172,7 +172,7 @@ msgstr ""
|
|||
"لن ترى الرسائل المشفرة من جهاز %s الذي يستخدم هذا المفتاح. على العكس من "
|
||||
"ذلك ، لن يتمكن هذا الجهاز من فك تشفير رسائلك بعد الآن."
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:161
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:160
|
||||
#, c-format
|
||||
msgid ""
|
||||
"You will be able to exchange encrypted messages with the device of %s that "
|
||||
|
@ -180,7 +180,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"سوف يكون بمقدورك تبادل الرسائل المشفرة مع جهاز %s الذي يستخدم هذا المفتاح."
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:167
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:166
|
||||
msgid "Back"
|
||||
msgstr "العودة"
|
||||
|
||||
|
@ -192,15 +192,6 @@ msgstr "الإدارة"
|
|||
msgid "This contact has new devices"
|
||||
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
|
||||
msgid "OMEMO trust decision required"
|
||||
msgstr "مطلوب قرار ثقة مع OMEMO"
|
||||
|
@ -210,6 +201,15 @@ msgstr "مطلوب قرار ثقة مع OMEMO"
|
|||
msgid "Did you add a new device for account %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
|
||||
msgid "Encryption"
|
||||
msgstr "التشفير"
|
||||
|
@ -225,52 +225,52 @@ msgstr[3] "%d أجهزة OMEMO"
|
|||
msgstr[4] "%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"
|
||||
msgstr "إدارة مفاتيح أوميمو"
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:47
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:49
|
||||
msgid "Automatically accept new keys"
|
||||
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."
|
||||
msgstr "سيتم قبول مفاتيح التشفير الجديدة الخاصة بهذا المراسل تلقائيًا."
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:49
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:51
|
||||
msgid "Own key"
|
||||
msgstr "مفتاحك الخاص"
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:50
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:52
|
||||
msgid "New keys"
|
||||
msgstr "المفاتيح الجديدة"
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:51
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:53
|
||||
msgid "Associated keys"
|
||||
msgstr "المفاتيح المقترِنة"
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:52
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:54
|
||||
msgid "Inactive keys"
|
||||
msgstr "المفاتيح غير المُنشَّطة"
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:84
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:86
|
||||
msgid ""
|
||||
"New encryption keys from your other devices will be accepted automatically."
|
||||
msgstr "سيتم قبول مفاتيح التشفير الجديدة من أجهزتك الأخرى تلقائيًا."
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:319
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:335
|
||||
msgid "Accepted"
|
||||
msgstr "تم قبوله"
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:324
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:340
|
||||
msgid "Rejected"
|
||||
msgstr "تم رفضه"
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:329
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:345
|
||||
msgid "Verified"
|
||||
msgstr "تم التحقق منه"
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:336
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:352
|
||||
msgid "Unused"
|
||||
msgstr "غير مستخدَم"
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: dino-omemo 20180123\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"
|
||||
"Language-Team: Catalan <ca@dodds.net>\n"
|
||||
"Language: ca\n"
|
||||
|
@ -33,11 +33,11 @@ msgid ""
|
|||
"%s does not trust this device. That means, you might be missing messages."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:35
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:34
|
||||
msgid "Manage Key"
|
||||
msgstr "Gestiona la clau"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:36
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:35
|
||||
msgid ""
|
||||
"Compare the fingerprint, character by character, with the one shown on your "
|
||||
"contact's device."
|
||||
|
@ -45,40 +45,40 @@ msgstr ""
|
|||
"Compareu l'empremta, caràcter per caràcter, amb la que es mostra al vostre "
|
||||
"dispositiu de contactes."
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:37
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:36
|
||||
msgid "Fingerprints differ"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:38
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:37
|
||||
msgid "Fingerprints match"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:39
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:82
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:88
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:38
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:81
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:87
|
||||
msgid "Cancel"
|
||||
msgstr "Cancel·la"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:40
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:39
|
||||
msgid "Confirm"
|
||||
msgstr "Confirma"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:60
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:59
|
||||
msgid "Verify key"
|
||||
msgstr "Comproveu la clau"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:61
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:60
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Future messages sent by %s from the device that uses this key will be "
|
||||
"highlighted accordingly in the chat window."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:71
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:70
|
||||
msgid "Fingerprints do not match"
|
||||
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
|
||||
msgid ""
|
||||
"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 "
|
||||
"rebutjar aquesta clau."
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:124
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:123
|
||||
#, fuzzy
|
||||
msgid "Verify key fingerprint"
|
||||
msgstr "Emprempta pròpia"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:124
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:123
|
||||
msgid ""
|
||||
"Compare this key's fingerprint with the fingerprint displayed on the "
|
||||
"contact's device."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:126
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:152
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:256
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:125
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:151
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:269
|
||||
msgid "Reject key"
|
||||
msgstr "Rebutja la clau"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:126
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:125
|
||||
msgid ""
|
||||
"Block encrypted communication with the contact's device that uses this key."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:128
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:160
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:251
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:127
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:159
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:264
|
||||
msgid "Accept key"
|
||||
msgstr "Accepta la clau"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:128
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:127
|
||||
msgid ""
|
||||
"Allow encrypted communication with the contact's device that uses this key."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:132
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:137
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:141
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:131
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:136
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:140
|
||||
#, c-format
|
||||
msgid "This key is currently %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"
|
||||
msgstr "acceptada"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:132
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:137
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:131
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:136
|
||||
#, c-format
|
||||
msgid "This means it can be used by %s to receive and send encrypted messages."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:137
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:136
|
||||
msgid "verified"
|
||||
msgstr "verificada"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:137
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:136
|
||||
msgid ""
|
||||
"Additionally it has been verified to match the key on the contact's device."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:141
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:140
|
||||
msgid "rejected"
|
||||
msgstr "rebutjada"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:141
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:140
|
||||
#, c-format
|
||||
msgid ""
|
||||
"This means it cannot be used by %s to decipher your messages, and you won't "
|
||||
"see messages encrypted with it."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:153
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:152
|
||||
#, c-format
|
||||
msgid ""
|
||||
"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."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:161
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:160
|
||||
#, c-format
|
||||
msgid ""
|
||||
"You will be able to exchange encrypted messages with the device of %s that "
|
||||
"uses this key."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:167
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:166
|
||||
msgid "Back"
|
||||
msgstr "Enrere"
|
||||
|
||||
|
@ -185,15 +185,6 @@ msgstr "Gestiona"
|
|||
msgid "This contact has new devices"
|
||||
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
|
||||
msgid "OMEMO trust decision required"
|
||||
msgstr ""
|
||||
|
@ -203,6 +194,15 @@ msgstr ""
|
|||
msgid "Did you add a new device for account %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
|
||||
msgid "Encryption"
|
||||
msgstr "Xifratge"
|
||||
|
@ -214,52 +214,52 @@ msgid_plural "%d OMEMO devices"
|
|||
msgstr[0] "%d dispositiu 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"
|
||||
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"
|
||||
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."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:49
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:51
|
||||
msgid "Own key"
|
||||
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"
|
||||
msgstr "Claus noves"
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:51
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:53
|
||||
msgid "Associated keys"
|
||||
msgstr "Claus associades"
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:52
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:54
|
||||
msgid "Inactive keys"
|
||||
msgstr "Claus inactives"
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:84
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:86
|
||||
msgid ""
|
||||
"New encryption keys from your other devices will be accepted automatically."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:319
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:335
|
||||
msgid "Accepted"
|
||||
msgstr "Acceptada"
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:324
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:340
|
||||
msgid "Rejected"
|
||||
msgstr "Rebutjada"
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:329
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:345
|
||||
msgid "Verified"
|
||||
msgstr "Verificada"
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:336
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:352
|
||||
msgid "Unused"
|
||||
msgstr "No utilitzada"
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\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"
|
||||
"Language-Team: none\n"
|
||||
"Language: cs\n"
|
||||
|
@ -37,11 +37,11 @@ msgid ""
|
|||
msgstr ""
|
||||
"%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"
|
||||
msgstr "Spravovat klíč"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:36
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:35
|
||||
msgid ""
|
||||
"Compare the fingerprint, character by character, with the one shown on your "
|
||||
"contact's device."
|
||||
|
@ -49,29 +49,29 @@ msgstr ""
|
|||
"Porovnejte otisk klíče, znak po znaku, s tím, který je zobrazen na zařízení "
|
||||
"vašeho kontaktu."
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:37
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:36
|
||||
msgid "Fingerprints differ"
|
||||
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"
|
||||
msgstr "Otisky klíčů odpovídají"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:39
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:82
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:88
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:38
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:81
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:87
|
||||
msgid "Cancel"
|
||||
msgstr "Zrušit"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:40
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:39
|
||||
msgid "Confirm"
|
||||
msgstr "Potvrdit"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:60
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:59
|
||||
msgid "Verify key"
|
||||
msgstr "Ověřit klíč"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:61
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:60
|
||||
#, c-format
|
||||
msgid ""
|
||||
"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íč, "
|
||||
"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"
|
||||
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
|
||||
msgid ""
|
||||
"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 "
|
||||
"%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"
|
||||
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 ""
|
||||
"Compare this key's fingerprint with the fingerprint displayed on the "
|
||||
"contact's device."
|
||||
msgstr ""
|
||||
"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:152
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:256
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:125
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:151
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:269
|
||||
msgid "Reject key"
|
||||
msgstr "Odmítnout klíč"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:126
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:125
|
||||
msgid ""
|
||||
"Block encrypted communication with the contact's device that uses this key."
|
||||
msgstr ""
|
||||
"Zablokujte šifrovanou komunikaci se zařízením kontaktu, které tento klíč "
|
||||
"používá."
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:128
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:160
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:251
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:127
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:159
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:264
|
||||
msgid "Accept key"
|
||||
msgstr "Přijmout klíč"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:128
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:127
|
||||
msgid ""
|
||||
"Allow encrypted communication with the contact's device that uses this key."
|
||||
msgstr ""
|
||||
"Povolit šifrovanou komunikaci se zařízením kontaktu, které používá tento "
|
||||
"klíč."
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:132
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:137
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:141
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:131
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:136
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:140
|
||||
#, c-format
|
||||
msgid "This key is currently %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"
|
||||
msgstr "akceptován"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:132
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:137
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:131
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:136
|
||||
#, c-format
|
||||
msgid "This means it can be used by %s to receive and send encrypted messages."
|
||||
msgstr ""
|
||||
"To znamená, že jej %s může používat k přijímání a odesílání šifrovaných "
|
||||
"zpráv."
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:137
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:136
|
||||
msgid "verified"
|
||||
msgstr "ověřen"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:137
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:136
|
||||
msgid ""
|
||||
"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."
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:141
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:140
|
||||
msgid "rejected"
|
||||
msgstr "odmítnut"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:141
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:140
|
||||
#, c-format
|
||||
msgid ""
|
||||
"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 "
|
||||
"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
|
||||
msgid ""
|
||||
"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í. "
|
||||
"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
|
||||
msgid ""
|
||||
"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íč "
|
||||
"používá."
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:167
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:166
|
||||
msgid "Back"
|
||||
msgstr "Zpět"
|
||||
|
||||
|
@ -202,15 +202,6 @@ msgstr "Spravovat"
|
|||
msgid "This contact has new devices"
|
||||
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
|
||||
msgid "OMEMO trust decision required"
|
||||
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?"
|
||||
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
|
||||
msgid "Encryption"
|
||||
msgstr "Šifrování"
|
||||
|
@ -232,52 +232,52 @@ msgstr[0] "%d OMEMO zařízení"
|
|||
msgstr[1] "%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"
|
||||
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"
|
||||
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."
|
||||
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"
|
||||
msgstr "Vlastní klíč"
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:50
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:52
|
||||
msgid "New keys"
|
||||
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"
|
||||
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"
|
||||
msgstr "Neaktivní klíče"
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:84
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:86
|
||||
msgid ""
|
||||
"New encryption keys from your other devices will be accepted automatically."
|
||||
msgstr ""
|
||||
"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"
|
||||
msgstr "Přijat"
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:324
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:340
|
||||
msgid "Rejected"
|
||||
msgstr "Odmítnut"
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:329
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:345
|
||||
msgid "Verified"
|
||||
msgstr "Ověřen"
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:336
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:352
|
||||
msgid "Unused"
|
||||
msgstr "Nepoužit"
|
||||
|
|
|
@ -2,7 +2,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: dino-omemo-0.0\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"
|
||||
"Language-Team: German <https://hosted.weblate.org/projects/dino/plugin-omemo/"
|
||||
"de/>\n"
|
||||
|
@ -33,11 +33,11 @@ msgid ""
|
|||
msgstr ""
|
||||
"%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"
|
||||
msgstr "Schlüssel verwalten"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:36
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:35
|
||||
msgid ""
|
||||
"Compare the fingerprint, character by character, with the one shown on your "
|
||||
"contact's device."
|
||||
|
@ -45,29 +45,29 @@ msgstr ""
|
|||
"Vergleiche den Fingerabdruck, Zeichen für Zeichen, mit dem der auf dem Gerät "
|
||||
"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"
|
||||
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"
|
||||
msgstr "Fingerabdrücke stimmen überein"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:39
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:82
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:88
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:38
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:81
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:87
|
||||
msgid "Cancel"
|
||||
msgstr "Abbrechen"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:40
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:39
|
||||
msgid "Confirm"
|
||||
msgstr "Bestätigen"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:60
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:59
|
||||
msgid "Verify key"
|
||||
msgstr "Schlüssel verifizieren"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:61
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:60
|
||||
#, c-format
|
||||
msgid ""
|
||||
"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 "
|
||||
"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"
|
||||
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
|
||||
msgid ""
|
||||
"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 "
|
||||
"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"
|
||||
msgstr "Fingerabdruck überprüfen"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:124
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:123
|
||||
msgid ""
|
||||
"Compare this key's fingerprint with the fingerprint displayed on the "
|
||||
"contact's device."
|
||||
|
@ -103,67 +103,67 @@ msgstr ""
|
|||
"Diesen Fingerabdruck mit dem Fingerabdruck vergleichen, der auf dem Gerät "
|
||||
"des Kontaktes angezeigt wird."
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:126
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:152
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:256
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:125
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:151
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:269
|
||||
msgid "Reject key"
|
||||
msgstr "Schlüssel ablehnen"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:126
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:125
|
||||
msgid ""
|
||||
"Block encrypted communication with the contact's device that uses this key."
|
||||
msgstr ""
|
||||
"Blockiert die verschlüsselte Kommunikation mit dem Gerät des Kontakts, das "
|
||||
"diesen Schlüssel verwendet."
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:128
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:160
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:251
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:127
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:159
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:264
|
||||
msgid "Accept key"
|
||||
msgstr "Schlüssel akzeptieren"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:128
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:127
|
||||
msgid ""
|
||||
"Allow encrypted communication with the contact's device that uses this key."
|
||||
msgstr ""
|
||||
"Erlaubt die verschlüsselte Kommunikation mit dem Gerät des Kontakts, das "
|
||||
"diesen Schlüssel verwendet."
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:132
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:137
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:141
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:131
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:136
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:140
|
||||
#, c-format
|
||||
msgid "This key is currently %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"
|
||||
msgstr "akzeptiert"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:132
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:137
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:131
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:136
|
||||
#, c-format
|
||||
msgid "This means it can be used by %s to receive and send encrypted messages."
|
||||
msgstr ""
|
||||
"Das bedeutet, er kann von %s zum Empfangen und Senden verschlüsselter "
|
||||
"Nachrichten verwendet werden."
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:137
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:136
|
||||
msgid "verified"
|
||||
msgstr "überprüft"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:137
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:136
|
||||
msgid ""
|
||||
"Additionally it has been verified to match the key on the contact's device."
|
||||
msgstr ""
|
||||
"Darüber hinaus wurde überprüft, dass er mit dem Schlüssel auf dem Gerät des "
|
||||
"Kontaktes übereinstimmt."
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:141
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:140
|
||||
msgid "rejected"
|
||||
msgstr "abgelehnt"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:141
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:140
|
||||
#, c-format
|
||||
msgid ""
|
||||
"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 "
|
||||
"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
|
||||
msgid ""
|
||||
"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 "
|
||||
"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
|
||||
msgid ""
|
||||
"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 "
|
||||
"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"
|
||||
msgstr "Zurück"
|
||||
|
||||
|
@ -203,15 +203,6 @@ msgstr "Verwalten"
|
|||
msgid "This contact has new devices"
|
||||
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
|
||||
msgid "OMEMO trust decision required"
|
||||
msgstr "OMEMO-Vertrauensentscheidung erforderlich"
|
||||
|
@ -221,6 +212,15 @@ msgstr "OMEMO-Vertrauensentscheidung erforderlich"
|
|||
msgid "Did you add a new device for account %s?"
|
||||
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
|
||||
msgid "Encryption"
|
||||
msgstr "Verschlüsselung"
|
||||
|
@ -232,53 +232,53 @@ msgid_plural "%d OMEMO devices"
|
|||
msgstr[0] "%d OMEMO Gerät"
|
||||
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"
|
||||
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"
|
||||
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."
|
||||
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"
|
||||
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"
|
||||
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"
|
||||
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"
|
||||
msgstr "Inaktive Schlüssel"
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:84
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:86
|
||||
msgid ""
|
||||
"New encryption keys from your other devices will be accepted automatically."
|
||||
msgstr ""
|
||||
"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"
|
||||
msgstr "Akzeptiert"
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:324
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:340
|
||||
msgid "Rejected"
|
||||
msgstr "Zurückgewiesen"
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:329
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:345
|
||||
msgid "Verified"
|
||||
msgstr "Verifiziert"
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:336
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:352
|
||||
msgid "Unused"
|
||||
msgstr "Unbenutzt"
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\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"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\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."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:35
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:34
|
||||
msgid "Manage Key"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:36
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:35
|
||||
msgid ""
|
||||
"Compare the fingerprint, character by character, with the one shown on your "
|
||||
"contact's device."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:37
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:36
|
||||
msgid "Fingerprints differ"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:38
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:37
|
||||
msgid "Fingerprints match"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:39
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:82
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:88
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:38
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:81
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:87
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:40
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:39
|
||||
msgid "Confirm"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:60
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:59
|
||||
msgid "Verify key"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:61
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:60
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Future messages sent by %s from the device that uses this key will be "
|
||||
"highlighted accordingly in the chat window."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:71
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:70
|
||||
msgid "Fingerprints do not match"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:72
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:71
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Please verify that you are comparing the correct fingerprint. If "
|
||||
|
@ -86,90 +86,90 @@ msgid ""
|
|||
"consider rejecting this key."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:124
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:123
|
||||
msgid "Verify key fingerprint"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:124
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:123
|
||||
msgid ""
|
||||
"Compare this key's fingerprint with the fingerprint displayed on the "
|
||||
"contact's device."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:126
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:152
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:256
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:125
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:151
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:269
|
||||
msgid "Reject key"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:126
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:125
|
||||
msgid ""
|
||||
"Block encrypted communication with the contact's device that uses this key."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:128
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:160
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:251
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:127
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:159
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:264
|
||||
msgid "Accept key"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:128
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:127
|
||||
msgid ""
|
||||
"Allow encrypted communication with the contact's device that uses this key."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:132
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:137
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:141
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:131
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:136
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:140
|
||||
#, c-format
|
||||
msgid "This key is currently %s."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:132
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:131
|
||||
msgid "accepted"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:132
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:137
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:131
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:136
|
||||
#, c-format
|
||||
msgid "This means it can be used by %s to receive and send encrypted messages."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:137
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:136
|
||||
msgid "verified"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:137
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:136
|
||||
msgid ""
|
||||
"Additionally it has been verified to match the key on the contact's device."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:141
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:140
|
||||
msgid "rejected"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:141
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:140
|
||||
#, c-format
|
||||
msgid ""
|
||||
"This means it cannot be used by %s to decipher your messages, and you won't "
|
||||
"see messages encrypted with it."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:153
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:152
|
||||
#, c-format
|
||||
msgid ""
|
||||
"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."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:161
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:160
|
||||
#, c-format
|
||||
msgid ""
|
||||
"You will be able to exchange encrypted messages with the device of %s that "
|
||||
"uses this key."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:167
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:166
|
||||
msgid "Back"
|
||||
msgstr ""
|
||||
|
||||
|
@ -181,15 +181,6 @@ msgstr ""
|
|||
msgid "This contact has new devices"
|
||||
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
|
||||
msgid "OMEMO trust decision required"
|
||||
msgstr ""
|
||||
|
@ -199,6 +190,15 @@ msgstr ""
|
|||
msgid "Did you add a new device for account %s?"
|
||||
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
|
||||
msgid "Encryption"
|
||||
msgstr ""
|
||||
|
@ -210,51 +210,51 @@ msgid_plural "%d OMEMO devices"
|
|||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:46
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:48
|
||||
msgid "OMEMO Key Management"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:47
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:49
|
||||
msgid "Automatically accept new keys"
|
||||
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."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:49
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:51
|
||||
msgid "Own key"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:50
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:52
|
||||
msgid "New keys"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:51
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:53
|
||||
msgid "Associated keys"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:52
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:54
|
||||
msgid "Inactive keys"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:84
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:86
|
||||
msgid ""
|
||||
"New encryption keys from your other devices will be accepted automatically."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:319
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:335
|
||||
msgid "Accepted"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:324
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:340
|
||||
msgid "Rejected"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:329
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:345
|
||||
msgid "Verified"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:336
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:352
|
||||
msgid "Unused"
|
||||
msgstr ""
|
||||
|
|
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\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"
|
||||
"Language-Team: none\n"
|
||||
"Language: el\n"
|
||||
|
@ -38,11 +38,11 @@ msgstr ""
|
|||
"%s δεν εμπιστεύεται αυτήν τη συσκευή. Αυτό σημαίνει ότι μπορεί να χάσετε "
|
||||
"μηνύματα."
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:35
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:34
|
||||
msgid "Manage Key"
|
||||
msgstr "Διαχείριση Κλειδιού"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:36
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:35
|
||||
msgid ""
|
||||
"Compare the fingerprint, character by character, with the one shown on your "
|
||||
"contact's device."
|
||||
|
@ -50,29 +50,29 @@ msgstr ""
|
|||
"Συγκρίνετε το δακτυλικό αποτύπωμα (fingerprint), χαρακτήρα προς χαρακτήρα, "
|
||||
"με αυτό που εμφανίζεται στη συσκευή της επαφής σας."
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:37
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:36
|
||||
msgid "Fingerprints differ"
|
||||
msgstr "Τα δακτυλικά αποτυπώματα (fingerprints) διαφέρουν"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:38
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:37
|
||||
msgid "Fingerprints match"
|
||||
msgstr "Τα δακτυλικά αποτυπώματα (fingerprints) ταιριάζουν"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:39
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:82
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:88
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:38
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:81
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:87
|
||||
msgid "Cancel"
|
||||
msgstr "Ακύρωση"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:40
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:39
|
||||
msgid "Confirm"
|
||||
msgstr "Επιβεβαίωση"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:60
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:59
|
||||
msgid "Verify key"
|
||||
msgstr "Επαλήθευση κλειδιού"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:61
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:60
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Future messages sent by %s from the device that uses this key will be "
|
||||
|
@ -81,11 +81,11 @@ msgstr ""
|
|||
"Μελλοντικά μηνύματα που αποστέλλονται από %s από τη συσκευή που χρησιμοποιεί "
|
||||
"αυτό το κλειδί θα επισημαίνονται ανάλογα στο παράθυρο συνομιλίας."
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:71
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:70
|
||||
msgid "Fingerprints do not match"
|
||||
msgstr "Τα δακτυλικά αποτυπώματα (fingerprints) δεν ταιριάζουν"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:72
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:71
|
||||
#, c-format
|
||||
msgid ""
|
||||
"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"
|
||||
msgstr "Επαλήθευση δακτυλικού αποτυπώματος (fingerprint) κλειδιού"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:124
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:123
|
||||
msgid ""
|
||||
"Compare this key's fingerprint with the fingerprint displayed on the "
|
||||
"contact's device."
|
||||
|
@ -109,66 +109,66 @@ msgstr ""
|
|||
"Συγκρίνετε το δακτυλικό αποτύπωμα (fingerprint) αυτού του κλειδιού με το "
|
||||
"δακτυλικό αποτύπωμα που εμφανίζεται στη συσκευή της επαφής."
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:126
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:152
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:256
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:125
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:151
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:269
|
||||
msgid "Reject key"
|
||||
msgstr "Απόρριψη κλειδιού"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:126
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:125
|
||||
msgid ""
|
||||
"Block encrypted communication with the contact's device that uses this key."
|
||||
msgstr ""
|
||||
"Αποκλεισμός κρυπτογραφημένης επικοινωνίας με τη συσκευή της επαφής που "
|
||||
"χρησιμοποιεί αυτό το κλειδί."
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:128
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:160
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:251
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:127
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:159
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:264
|
||||
msgid "Accept key"
|
||||
msgstr "Αποδοχή κλειδιού"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:128
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:127
|
||||
msgid ""
|
||||
"Allow encrypted communication with the contact's device that uses this key."
|
||||
msgstr ""
|
||||
"Να επιτρέπεται η κρυπτογραφημένη επικοινωνία με τη συσκευή της επαφής που "
|
||||
"χρησιμοποιεί αυτό το κλειδί."
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:132
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:137
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:141
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:131
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:136
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:140
|
||||
#, c-format
|
||||
msgid "This key is currently %s."
|
||||
msgstr "Αυτό το κλειδί είναι αυτή τη στιγμή %s."
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:132
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:131
|
||||
msgid "accepted"
|
||||
msgstr "δεκτό"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:132
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:137
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:131
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:136
|
||||
#, c-format
|
||||
msgid "This means it can be used by %s to receive and send encrypted messages."
|
||||
msgstr ""
|
||||
"Αυτό σημαίνει ότι μπορεί να χρησιμοποιηθεί από το %s για λήψη και αποστολή "
|
||||
"κρυπτογραφημένων μηνυμάτων."
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:137
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:136
|
||||
msgid "verified"
|
||||
msgstr "επαληθευμένο"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:137
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:136
|
||||
msgid ""
|
||||
"Additionally it has been verified to match the key on the contact's device."
|
||||
msgstr ""
|
||||
"Επιπλέον, έχει επαληθευτεί ότι ταιριάζει με το κλειδί στη συσκευή της επαφής."
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:141
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:140
|
||||
msgid "rejected"
|
||||
msgstr "απορριφθέν"
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:141
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:140
|
||||
#, c-format
|
||||
msgid ""
|
||||
"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
|
||||
msgid ""
|
||||
"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
|
||||
msgid ""
|
||||
"You will be able to exchange encrypted messages with the device of %s that "
|
||||
|
@ -197,7 +197,7 @@ msgstr ""
|
|||
"Θα μπορείτε να ανταλλάσσετε κρυπτογραφημένα μηνύματα με τη συσκευή των %s "
|
||||
"που χρησιμοποιούν αυτό το κλειδί."
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:167
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:166
|
||||
msgid "Back"
|
||||
msgstr "Πίσω"
|
||||
|
||||
|
@ -209,15 +209,6 @@ msgstr "Διαχείρηση"
|
|||
msgid "This contact has new devices"
|
||||
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
|
||||
msgid "OMEMO trust decision required"
|
||||
msgstr "Απαιτείται απόφαση εμπιστοσύνης OMEMO"
|
||||
|
@ -227,6 +218,15 @@ msgstr "Απαιτείται απόφαση εμπιστοσύνης OMEMO"
|
|||
msgid "Did you add a new device for account %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
|
||||
msgid "Encryption"
|
||||
msgstr "Κρυπτογράφηση"
|
||||
|
@ -238,54 +238,54 @@ msgid_plural "%d OMEMO devices"
|
|||
msgstr[0] "%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"
|
||||
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"
|
||||
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."
|
||||
msgstr ""
|
||||
"Τα νέα κλειδιά κρυπτογράφησης από αυτήν την επαφή θα γίνονται δεκτά αυτόματα."
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:49
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:51
|
||||
msgid "Own key"
|
||||
msgstr "Το κλειδί μου"
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:50
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:52
|
||||
msgid "New keys"
|
||||
msgstr "Νέα κλειδιά"
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:51
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:53
|
||||
msgid "Associated keys"
|
||||
msgstr "Συσχετισμένα κλειδιά"
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:52
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:54
|
||||
msgid "Inactive keys"
|
||||
msgstr "Ανενεργά κλειδιά"
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:84
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:86
|
||||
msgid ""
|
||||
"New encryption keys from your other devices will be accepted automatically."
|
||||
msgstr ""
|
||||
"Τα νέα κλειδιά κρυπτογράφησης από τις άλλες συσκευές σας θα γίνονται δεκτά "
|
||||
"αυτόματα."
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:319
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:335
|
||||
msgid "Accepted"
|
||||
msgstr "Αποδεκτά"
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:324
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:340
|
||||
msgid "Rejected"
|
||||
msgstr "Απορριφθέντα"
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:329
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:345
|
||||
msgid "Verified"
|
||||
msgstr "Επαληθευμένα"
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:336
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:352
|
||||
msgid "Unused"
|
||||
msgstr "Αχρησιμοποίητα"
|
||||
|
|
|
@ -2,7 +2,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: dino-omemo-0.0\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"
|
||||
"MIME-Version: 1.0\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."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:35
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:34
|
||||
msgid "Manage Key"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:36
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:35
|
||||
msgid ""
|
||||
"Compare the fingerprint, character by character, with the one shown on your "
|
||||
"contact's device."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:37
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:36
|
||||
msgid "Fingerprints differ"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:38
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:37
|
||||
msgid "Fingerprints match"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:39
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:82
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:88
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:38
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:81
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:87
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:40
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:39
|
||||
msgid "Confirm"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:60
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:59
|
||||
msgid "Verify key"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:61
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:60
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Future messages sent by %s from the device that uses this key will be "
|
||||
"highlighted accordingly in the chat window."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:71
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:70
|
||||
msgid "Fingerprints do not match"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:72
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:71
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Please verify that you are comparing the correct fingerprint. If "
|
||||
|
@ -76,90 +76,90 @@ msgid ""
|
|||
"consider rejecting this key."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:124
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:123
|
||||
msgid "Verify key fingerprint"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:124
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:123
|
||||
msgid ""
|
||||
"Compare this key's fingerprint with the fingerprint displayed on the "
|
||||
"contact's device."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:126
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:152
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:256
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:125
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:151
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:269
|
||||
msgid "Reject key"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:126
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:125
|
||||
msgid ""
|
||||
"Block encrypted communication with the contact's device that uses this key."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:128
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:160
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:251
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:127
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:159
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:264
|
||||
msgid "Accept key"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:128
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:127
|
||||
msgid ""
|
||||
"Allow encrypted communication with the contact's device that uses this key."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:132
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:137
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:141
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:131
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:136
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:140
|
||||
#, c-format
|
||||
msgid "This key is currently %s."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:132
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:131
|
||||
msgid "accepted"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:132
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:137
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:131
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:136
|
||||
#, c-format
|
||||
msgid "This means it can be used by %s to receive and send encrypted messages."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:137
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:136
|
||||
msgid "verified"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:137
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:136
|
||||
msgid ""
|
||||
"Additionally it has been verified to match the key on the contact's device."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:141
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:140
|
||||
msgid "rejected"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:141
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:140
|
||||
#, c-format
|
||||
msgid ""
|
||||
"This means it cannot be used by %s to decipher your messages, and you won't "
|
||||
"see messages encrypted with it."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:153
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:152
|
||||
#, c-format
|
||||
msgid ""
|
||||
"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."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:161
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:160
|
||||
#, c-format
|
||||
msgid ""
|
||||
"You will be able to exchange encrypted messages with the device of %s that "
|
||||
"uses this key."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:167
|
||||
#: plugins/omemo/src/ui/manage_key_dialog.vala:166
|
||||
msgid "Back"
|
||||
msgstr ""
|
||||
|
||||
|
@ -171,15 +171,6 @@ msgstr ""
|
|||
msgid "This contact has new devices"
|
||||
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
|
||||
msgid "OMEMO trust decision required"
|
||||
msgstr ""
|
||||
|
@ -189,6 +180,15 @@ msgstr ""
|
|||
msgid "Did you add a new device for account %s?"
|
||||
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
|
||||
msgid "Encryption"
|
||||
msgstr ""
|
||||
|
@ -200,51 +200,51 @@ msgid_plural "%d OMEMO devices"
|
|||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:46
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:48
|
||||
msgid "OMEMO Key Management"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:47
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:49
|
||||
msgid "Automatically accept new keys"
|
||||
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."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:49
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:51
|
||||
msgid "Own key"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:50
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:52
|
||||
msgid "New keys"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:51
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:53
|
||||
msgid "Associated keys"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:52
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:54
|
||||
msgid "Inactive keys"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:84
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:86
|
||||
msgid ""
|
||||
"New encryption keys from your other devices will be accepted automatically."
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:319
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:335
|
||||
msgid "Accepted"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:324
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:340
|
||||
msgid "Rejected"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:329
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:345
|
||||
msgid "Verified"
|
||||
msgstr ""
|
||||
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:336
|
||||
#: plugins/omemo/src/ui/contact_details_dialog.vala:352
|
||||
msgid "Unused"
|
||||
msgstr ""
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue