Compare commits

..

125 Commits

Author SHA1 Message Date
Avently c5f08ad46a old 2024-09-06 23:09:54 +09:00
Avently f2565ef5bf last 2024-09-06 23:06:02 +09:00
Avently d4f56322f7 change 2024-09-06 22:17:31 +09:00
Avently 1a8cb55e70 revert some 2024-09-06 22:11:12 +09:00
Avently 696ddd7a0d Revert "change"
This reverts commit 9693d9e85d.
2024-09-06 22:10:42 +09:00
Avently b25de876e1 change 2024-09-06 22:09:33 +09:00
Avently d96e6314fa Revert "desktop: fix vlc dependency (#4809)"
This reverts commit 087519c39d.
2024-09-06 22:08:30 +09:00
Avently a239dee68f once 2024-09-06 21:49:53 +09:00
Avently 072d547c48 only once 2024-09-06 21:48:53 +09:00
Avently 9693d9e85d change 2024-09-06 21:45:42 +09:00
Avently c78bb5aa5d change 2024-09-06 21:37:50 +09:00
Avently ab5a13081b dispatcher 2024-09-06 21:28:24 +09:00
Diogo 041a2e21d3 initial version of swipable modal 2024-09-06 12:38:54 +01:00
Diogo a02275d28e more android checks 2024-09-06 11:41:15 +01:00
Diogo ce8b23d2ab remove android check 2024-09-06 11:39:59 +01:00
Diogo b77c357704 move bars logic to android 2024-09-06 10:08:43 +01:00
Diogo 103c0d4881 split android and desktop scaffold for picker 2024-09-06 09:45:44 +01:00
Diogo ca1be83db7 paddings 2024-09-05 23:16:13 +01:00
Diogo 7330361289 chevron and gradient 2024-09-05 22:33:52 +01:00
Diogo 6727503803 chevron same size as sun/moon 2024-09-05 18:57:50 +01:00
Diogo fd6a16f3de use bedtime moon for dark mode 2024-09-05 18:50:20 +01:00
Diogo a4db119fcf unread badge same style as chatlist 2024-09-05 18:45:18 +01:00
Diogo c1629ba5d2 remove you 2024-09-05 18:37:56 +01:00
Diogo 0e749a99c9 paddings 2024-09-05 17:12:42 +01:00
Diogo 5806b51d8a desktop paddings 2024-09-05 16:58:25 +01:00
Diogo 27e1c738e5 aligned paddings on desktop 2024-09-05 16:24:55 +01:00
Diogo 3f92e0f249 extra space in the end of user list for android 2024-09-05 14:07:42 +01:00
Diogo fbb776a14a unread badge 2024-09-05 14:04:36 +01:00
Diogo 68f53ff382 centered avatars 2024-09-05 13:57:29 +01:00
Diogo af467bccd3 center android icons with avatar 2024-09-05 13:53:27 +01:00
Diogo 45b82f752a initial desktop design 2024-09-05 13:36:03 +01:00
Diogo 366d043e72 update android space between badges 2024-09-05 13:23:55 +01:00
Diogo 1384cf2470 remove unused var 2024-09-05 12:50:59 +01:00
Diogo 2bea94fe0d fix profile creation in desktop 2024-09-05 12:49:19 +01:00
Diogo 624e49e412 always show your chat profiles in desktop 2024-09-05 11:35:13 +01:00
Diogo 140bc679ab move your chat profiles inside android specific 2024-09-05 11:33:00 +01:00
Diogo 4b61beb237 split inactive user picker between platforms 2024-09-05 11:30:15 +01:00
Diogo 0db7ab964b android paddings 2024-09-05 11:13:18 +01:00
Diogo b993c24be6 gradient 2024-09-05 10:27:20 +01:00
Diogo 3db5c4d3b1 paddings in scroller 2024-09-05 10:15:45 +01:00
Diogo f83768d2ce progress dump on new android design 2024-09-04 23:43:22 +01:00
Diogo 7f28de3b28 close drawer on swipe down 30% 2024-09-04 16:14:48 +01:00
Diogo 1b4aaa0614 move desktop/mobile connection 2024-09-04 15:48:56 +01:00
Diogo 940077a5d3 unused 2024-09-04 15:24:49 +01:00
Diogo 03bf16b97a small refactor 2024-09-04 15:24:32 +01:00
Diogo f99eaf884f remove unused code 2024-09-04 15:17:14 +01:00
Diogo 1adb9ffe79 smaller profile name 2024-09-04 15:14:14 +01:00
Diogo 3968ed2753 fix spacer for row scroll on android 2024-09-04 15:10:04 +01:00
Diogo 69da9532fa bigger profile image smaller gap to name 2024-09-04 14:49:22 +01:00
Diogo 18fa5c75dd close user picker on settings click in desktop 2024-09-04 14:43:01 +01:00
Diogo c3c9adde5c remove shading from desktop 2024-09-04 14:40:10 +01:00
Diogo ff7d1528c4 desktop menu matching size of right side modals 2024-09-04 14:30:33 +01:00
Diogo 5c2b16549f protect android calls 2024-09-04 14:13:25 +01:00
Diogo 249f887531 updated icon color 2024-09-04 14:01:06 +01:00
Diogo 3d9e032900 reset navbar colors on navigate 2024-09-04 13:53:41 +01:00
Diogo 7a92513b34 remove unused var 2024-09-04 13:19:39 +01:00
Diogo 43bc09f9cc change bar and shading on theme change 2024-09-04 13:18:20 +01:00
Diogo 2e27107646 best case bars switching working 2024-09-04 12:28:56 +01:00
Diogo a29ec774e8 improvements on status and nav color set 2024-09-04 12:12:43 +01:00
Diogo 9009744c28 use chevron icon to see all profiles 2024-09-04 11:27:42 +01:00
Diogo 3a1321e4f7 picker should always remain open 2024-09-04 11:22:25 +01:00
Diogo 4a87d85589 align avatars to top 2024-09-04 10:53:59 +01:00
Diogo ae58948ee8 separate title 2024-09-04 10:29:38 +01:00
Diogo f9778546dd gradient and horizontal scroll 2024-09-04 10:25:00 +01:00
Avently a9b24d18be color mix 2024-09-04 03:03:40 +09:00
Diogo d119477d5c broken transition change 2024-09-03 17:10:14 +01:00
Diogo bebae7209b simplify nav bar color set 2024-09-03 14:59:13 +01:00
Diogo 1ddd6a8c18 Merge branch 'master' into dc/deskto-android-new-user-picker 2024-09-03 14:51:11 +01:00
Diogo aae79ffa5f same button as ios for opening all profiles 2024-09-03 11:16:17 +01:00
Diogo 2868005d2f Merge branch 'master' into dc/deskto-android-new-user-picker 2024-09-03 10:47:47 +01:00
Diogo bd8cc1040d stop pushing shade up 2024-09-02 11:08:16 +01:00
Diogo b878fd21b3 shading colors 2024-09-02 10:25:17 +01:00
Diogo ac84e1da64 add system mode toast 2024-08-31 23:32:41 +01:00
Diogo 996d92b313 fade in fade out 2024-08-31 23:26:16 +01:00
Diogo 3329544649 animate shading 2024-08-31 23:22:04 +01:00
Diogo d663cc010a remove drawer unused code 2024-08-31 23:08:05 +01:00
Diogo a278432f5c bar colors 2024-08-31 23:04:28 +01:00
Diogo 894a9873cb remove logs 2024-08-31 22:20:29 +01:00
Diogo 56789de01e fix use from desktop 2024-08-31 22:19:14 +01:00
Diogo e08b9f69e9 center settings 2024-08-31 15:20:56 +01:00
Diogo 67ca556331 settings as modal 2024-08-31 15:12:46 +01:00
Diogo ed13bc9f27 icons 2024-08-31 14:39:11 +01:00
Diogo d098f1c5cc icon colors 2024-08-31 13:47:20 +01:00
Evgeny Poberezkin 95062075f0 Merge branch 'master' into dc/deskto-android-new-user-picker 2024-08-31 11:59:30 +01:00
Diogo 8fe4be3c0c h2 is too big 2024-08-31 08:43:01 +01:00
Diogo 1e37e77157 profile name as header 2024-08-31 08:41:07 +01:00
Diogo e609de18c5 padding 2024-08-31 08:38:28 +01:00
Diogo 2f97fa6b48 add icon for dark mode 2024-08-31 08:32:49 +01:00
Diogo f7ab32bdf8 font match 2024-08-31 08:25:54 +01:00
Diogo 1ab692a5e8 create public address 2024-08-30 23:18:59 +01:00
Diogo 4f4713e5af better switch of opacity bg 2024-08-30 23:11:33 +01:00
Diogo 421e2b34f6 simplex address -> public 2024-08-30 23:09:40 +01:00
Diogo 0365485591 device pill in app bar 2024-08-30 23:05:09 +01:00
Diogo 5d88ef08eb hosts ordering and fixes 2024-08-30 22:51:11 +01:00
Diogo e74aa5b5ea bigger space between profiles 2024-08-30 22:45:19 +01:00
Diogo b6fea51f69 change view all profiles icon 2024-08-30 22:42:24 +01:00
Diogo 50b86f7dff pills order 2024-08-30 22:22:21 +01:00
Diogo bfbe3cf062 picker positioning 2024-08-30 22:15:29 +01:00
Diogo fd1cf5f1ed hide non active devices from pills 2024-08-30 22:05:30 +01:00
Diogo bd8c91585f padding 2024-08-30 22:03:54 +01:00
Diogo 9f1f54d9e0 active is grey 2024-08-30 21:54:28 +01:00
Diogo 82ce157c65 address messaging 2024-08-30 21:51:42 +01:00
Diogo a293103ee9 Merge branch 'master' into dc/deskto-android-new-user-picker 2024-08-30 21:41:59 +01:00
Diogo 32bd3c941a simple animations and shadow 2024-08-30 17:24:53 +01:00
Diogo 4907259d2e fonts and align 2024-08-30 16:41:03 +01:00
Diogo a40dd2591b handle big names 2024-08-30 16:14:25 +01:00
Diogo f8072e057c paddings 2024-08-30 15:34:28 +01:00
Diogo 9a6a03ffc3 remove create profile from settings 2024-08-30 15:10:41 +01:00
Diogo 9ea6b4d595 picker should now open for single user 2024-08-30 14:52:09 +01:00
Diogo 019e1e1653 safe remove of you settings section 2024-08-30 14:45:54 +01:00
Diogo eddb2e250b chat database settings section 2024-08-30 14:42:08 +01:00
Diogo 27a80cb66c add unread badge to users row 2024-08-30 14:34:03 +01:00
Diogo 4f9aabce7d color changes 2024-08-30 14:29:54 +01:00
Diogo 712aade625 remove stroke 2024-08-30 14:11:20 +01:00
Diogo 46ce478676 profile picker modal for external shares 2024-08-30 13:32:44 +01:00
Diogo b78512031e icon buttons 2024-08-30 12:27:14 +01:00
Diogo 3c6eb3899f remote hosts working 2024-08-30 10:12:26 +01:00
Diogo ea01373c1a Merge branch 'master' into dc/deskto-android-new-user-picker 2024-08-30 09:43:55 +01:00
Diogo a1325a7695 cleanup 2024-08-29 17:20:30 +01:00
Diogo 48398c2119 close picker on desktop opening modals 2024-08-29 17:05:58 +01:00
Diogo ff8e55599b color mode switcher 2024-08-29 16:13:16 +01:00
Diogo 0cd1208daa android dirty layout 2024-08-29 15:16:10 +01:00
Diogo 2686544723 Merge branch 'master' into dc/deskto-android-new-user-picker 2024-08-29 13:42:26 +01:00
Diogo f7a21f9792 Merge branch 'master' into dc/deskto-android-new-user-picker 2024-08-29 11:36:12 +01:00
Diogo 96aa960bee user picker as modal 2024-08-28 10:59:24 +01:00
161 changed files with 3397 additions and 6870 deletions
-1
View File
@@ -61,7 +61,6 @@ website/package/generated*
# Ignore build tool output, e.g. code coverage
website/.nyc_output/
website/coverage/
result
# Ignore API documentation
website/api-docs/
+5
View File
@@ -15,11 +15,16 @@ class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
logger.debug("AppDelegate: didFinishLaunchingWithOptions")
application.registerForRemoteNotifications()
NotificationCenter.default.addObserver(self, selector: #selector(pasteboardChanged), name: UIPasteboard.changedNotification, object: nil)
removePasscodesIfReinstalled()
prepareForLaunch()
return true
}
@objc func pasteboardChanged() {
ChatModel.shared.pasteboardHasStrings = UIPasteboard.general.hasStrings
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let token = deviceToken.map { String(format: "%02hhx", $0) }.joined()
logger.debug("AppDelegate: didRegisterForRemoteNotificationsWithDeviceToken \(token)")
+14 -18
View File
@@ -61,7 +61,7 @@ class ItemsModel: ObservableObject {
init() {
publisher
.throttle(for: 0.2, scheduler: DispatchQueue.main, latest: true)
.throttle(for: 0.25, scheduler: DispatchQueue.main, latest: true)
.sink { self.objectWillChange.send() }
.store(in: &bag)
}
@@ -191,6 +191,7 @@ final class ChatModel: ObservableObject {
@Published var stopPreviousRecPlay: URL? = nil // coordinates currently playing source
@Published var draft: ComposeState?
@Published var draftChatId: String?
@Published var pasteboardHasStrings: Bool = UIPasteboard.general.hasStrings
@Published var networkInfo = UserNetworkInfo(networkType: .other, online: true)
var messageDelivery: Dictionary<Int64, () -> Void> = [:]
@@ -562,7 +563,6 @@ final class ChatModel: ObservableObject {
// update preview
_updateChat(cInfo.id) { chat in
self.decreaseUnreadCounter(user: self.currentUser!, by: chat.chatStats.unreadCount)
self.updateFloatingButtons(unreadCount: 0)
chat.chatStats = ChatStats()
}
// update current chat
@@ -579,12 +579,6 @@ final class ChatModel: ObservableObject {
}
}
private func updateFloatingButtons(unreadCount: Int) {
let fbm = ChatView.FloatingButtonModel.shared
fbm.totalUnread = unreadCount
fbm.objectWillChange.send()
}
func markChatItemsRead(_ cInfo: ChatInfo, aboveItem: ChatItem? = nil) {
if let cItem = aboveItem {
if chatId == cInfo.id, let i = getChatItemIndex(cItem) {
@@ -603,7 +597,6 @@ final class ChatModel: ObservableObject {
if markedCount > 0 {
chat.chatStats.unreadCount -= markedCount
self.decreaseUnreadCounter(user: self.currentUser!, by: markedCount)
self.updateFloatingButtons(unreadCount: chat.chatStats.unreadCount)
}
}
}
@@ -633,15 +626,19 @@ final class ChatModel: ObservableObject {
}
}
func markChatItemsRead(_ cInfo: ChatInfo, _ itemIds: [ChatItem.ID]) {
if self.chatId == cInfo.id {
for itemId in itemIds {
if let i = im.reversedChatItems.firstIndex(where: { $0.id == itemId }) {
markChatItemRead_(i)
func markChatItemRead(_ cInfo: ChatInfo, _ cItem: ChatItem) async {
if chatId == cInfo.id,
let itemIndex = getChatItemIndex(cItem),
im.reversedChatItems[itemIndex].isRcvNew {
await MainActor.run {
withTransaction(Transaction()) {
// update current chat
markChatItemRead_(itemIndex)
// update preview
unreadCollector.changeUnreadCounter(cInfo.id, by: -1)
}
}
}
self.unreadCollector.changeUnreadCounter(cInfo.id, by: -itemIds.count)
}
private let unreadCollector = UnreadCollector()
@@ -667,10 +664,9 @@ final class ChatModel: ObservableObject {
}
func changeUnreadCounter(_ chatId: ChatId, by count: Int) {
if chatId == ChatModel.shared.chatId {
ChatView.FloatingButtonModel.shared.totalUnread += count
DispatchQueue.main.async {
self.unreadCounts[chatId] = (self.unreadCounts[chatId] ?? 0) + count
}
self.unreadCounts[chatId] = (self.unreadCounts[chatId] ?? 0) + count
subject.send()
}
}
+72 -141
View File
@@ -357,12 +357,6 @@ func apiGetChatItemInfo(type: ChatType, id: Int64, itemId: Int64) async throws -
throw r
}
func apiPlanForwardChatItems(type: ChatType, id: Int64, itemIds: [Int64]) async throws -> ([Int64], ForwardConfirmation?) {
let r = await chatSendCmd(.apiPlanForwardChatItems(toChatType: type, toChatId: id, itemIds: itemIds))
if case let .forwardPlan(_, chatItemIds, forwardConfimation) = r { return (chatItemIds, forwardConfimation) }
throw r
}
func apiForwardChatItems(toChatType: ChatType, toChatId: Int64, fromChatType: ChatType, fromChatId: Int64, itemIds: [Int64], ttl: Int?) async -> [ChatItem]? {
let cmd: ChatCommand = .apiForwardChatItems(toChatType: toChatType, toChatId: toChatId, fromChatType: fromChatType, fromChatId: fromChatId, itemIds: itemIds, ttl: ttl)
return await processSendMessageCmd(toChatType: toChatType, cmd: cmd)
@@ -1006,10 +1000,6 @@ func apiChatRead(type: ChatType, id: Int64, itemRange: (Int64, Int64)) async thr
try await sendCommandOkResp(.apiChatRead(type: type, id: id, itemRange: itemRange))
}
func apiChatItemsRead(type: ChatType, id: Int64, itemIds: [Int64]) async throws {
try await sendCommandOkResp(.apiChatItemsRead(type: type, id: id, itemIds: itemIds))
}
func apiChatUnread(type: ChatType, id: Int64, unreadChat: Bool) async throws {
try await sendCommandOkResp(.apiChatUnread(type: type, id: id, unreadChat: unreadChat))
}
@@ -1045,122 +1035,77 @@ func standaloneFileInfo(url: String, ctrl: chat_ctrl? = nil) async -> MigrationF
}
func receiveFile(user: any UserLike, fileId: Int64, userApprovedRelays: Bool = false, auto: Bool = false) async {
await receiveFiles(
user: user,
fileIds: [fileId],
userApprovedRelays: userApprovedRelays,
if let chatItem = await apiReceiveFile(
fileId: fileId,
userApprovedRelays: userApprovedRelays || !privacyAskToApproveRelaysGroupDefault.get(),
encrypted: privacyEncryptLocalFilesGroupDefault.get(),
auto: auto
)
) {
await chatItemSimpleUpdate(user, chatItem)
}
}
func receiveFiles(user: any UserLike, fileIds: [Int64], userApprovedRelays: Bool = false, auto: Bool = false) async {
var fileIdsToApprove = [Int64]()
var srvsToApprove = Set<String>()
var otherFileErrs = [ChatResponse]()
for fileId in fileIds {
let r = await chatSendCmd(
.receiveFile(
fileId: fileId,
userApprovedRelays: userApprovedRelays || !privacyAskToApproveRelaysGroupDefault.get(),
encrypted: privacyEncryptLocalFilesGroupDefault.get(),
inline: nil
func apiReceiveFile(fileId: Int64, userApprovedRelays: Bool, encrypted: Bool, inline: Bool? = nil, auto: Bool = false) async -> AChatItem? {
let r = await chatSendCmd(.receiveFile(fileId: fileId, userApprovedRelays: userApprovedRelays, encrypted: encrypted, inline: inline))
let am = AlertManager.shared
if case let .rcvFileAccepted(_, chatItem) = r { return chatItem }
if case .rcvFileAcceptedSndCancelled = r {
logger.debug("apiReceiveFile error: sender cancelled file transfer")
if !auto {
am.showAlertMsg(
title: "Cannot receive file",
message: "Sender cancelled file transfer."
)
)
switch r {
case let .rcvFileAccepted(_, chatItem):
await chatItemSimpleUpdate(user, chatItem)
default:
if let chatError = chatError(r) {
switch chatError {
case let .fileNotApproved(fileId, unknownServers):
fileIdsToApprove.append(fileId)
srvsToApprove.formUnion(unknownServers)
default:
otherFileErrs.append(r)
}
}
}
}
if !auto {
let otherErrsStr = if otherFileErrs.isEmpty {
""
} else if otherFileErrs.count == 1 {
"\(otherFileErrs[0])"
} else if otherFileErrs.count == 2 {
"\(otherFileErrs[0])\n\(otherFileErrs[1])"
} else {
"\(otherFileErrs[0])\n\(otherFileErrs[1])\nand \(otherFileErrs.count - 2) other error(s)"
} else if let networkErrorAlert = networkErrorAlert(r) {
logger.error("apiReceiveFile network error: \(String(describing: r))")
if !auto {
am.showAlert(networkErrorAlert)
}
// If there are not approved files, alert is shown the same way both in case of singular and plural files reception
if !fileIdsToApprove.isEmpty {
let srvs = srvsToApprove
.map { s in
} else {
switch chatError(r) {
case .fileCancelled:
logger.debug("apiReceiveFile ignoring fileCancelled error")
case .fileAlreadyReceiving:
logger.debug("apiReceiveFile ignoring fileAlreadyReceiving error")
case let .fileNotApproved(fileId, unknownServers):
logger.debug("apiReceiveFile fileNotApproved error")
if !auto {
let srvs = unknownServers.map { s in
if let srv = parseServerAddress(s), !srv.hostnames.isEmpty {
srv.hostnames[0]
} else {
serverHost(s)
}
}
.sorted()
.joined(separator: ", ")
let fIds = fileIdsToApprove
await MainActor.run {
showAlert(
title: NSLocalizedString("Unknown servers!", comment: "alert title"),
message: (
NSLocalizedString("Without Tor or VPN, your IP address will be visible to these XFTP relays: \(srvs).", comment: "alert message") +
(otherErrsStr != "" ? "\n\n" + NSLocalizedString("Other file errors:\n\(otherErrsStr)", comment: "alert message") : "")
),
buttonTitle: NSLocalizedString("Download", comment: "alert button"),
buttonAction: {
Task {
logger.debug("apiReceiveFile fileNotApproved alert - in Task")
if let user = ChatModel.shared.currentUser {
await receiveFiles(user: user, fileIds: fIds, userApprovedRelays: true)
am.showAlert(Alert(
title: Text("Unknown servers!"),
message: Text("Without Tor or VPN, your IP address will be visible to these XFTP relays: \(srvs.sorted().joined(separator: ", "))."),
primaryButton: .default(
Text("Download"),
action: {
Task {
logger.debug("apiReceiveFile fileNotApproved alert - in Task")
if let user = ChatModel.shared.currentUser {
await receiveFile(user: user, fileId: fileId, userApprovedRelays: true)
}
}
}
},
cancelButton: true
)
),
secondaryButton: .cancel()
))
}
} else if otherFileErrs.count == 1 { // If there is a single other error, we differentiate on it
let errorResponse = otherFileErrs.first!
switch errorResponse {
case let .rcvFileAcceptedSndCancelled(_, rcvFileTransfer):
logger.debug("receiveFiles error: sender cancelled file transfer \(rcvFileTransfer.fileId)")
await MainActor.run {
showAlert(
NSLocalizedString("Cannot receive file", comment: "alert title"),
message: NSLocalizedString("Sender cancelled file transfer.", comment: "alert message")
)
}
default:
if let chatError = chatError(errorResponse) {
switch chatError {
case .fileCancelled, .fileAlreadyReceiving:
logger.debug("receiveFiles ignoring FileCancelled or FileAlreadyReceiving error")
default:
await MainActor.run {
showAlert(
NSLocalizedString("Error receiving file", comment: "alert title"),
message: responseError(errorResponse)
)
}
}
}
}
} else if otherFileErrs.count > 1 { // If there are multiple other errors, we show general alert
await MainActor.run {
showAlert(
NSLocalizedString("Error receiving file", comment: "alert title"),
message: NSLocalizedString("File errors:\n\(otherErrsStr)", comment: "alert message")
default:
logger.error("apiReceiveFile error: \(String(describing: r))")
if !auto {
am.showAlertMsg(
title: "Error receiving file",
message: "Error: \(responseError(r))"
)
}
}
}
return nil
}
func cancelFile(user: User, fileId: Int64) async {
@@ -1342,23 +1287,11 @@ func markChatUnread(_ chat: Chat, unreadChat: Bool = true) async {
func apiMarkChatItemRead(_ cInfo: ChatInfo, _ cItem: ChatItem) async {
do {
logger.debug("apiMarkChatItemRead: \(cItem.id)")
try await apiChatRead(type: cInfo.chatType, id: cInfo.apiId, itemRange: (cItem.id, cItem.id))
DispatchQueue.main.async {
ChatModel.shared.markChatItemsRead(cInfo, [cItem.id])
}
await ChatModel.shared.markChatItemRead(cInfo, cItem)
} catch {
logger.error("apiChatRead error: \(responseError(error))")
}
}
func apiMarkChatItemsRead(_ cInfo: ChatInfo, _ itemIds: [ChatItem.ID]) async {
do {
try await apiChatItemsRead(type: cInfo.chatType, id: cInfo.apiId, itemIds: itemIds)
DispatchQueue.main.async {
ChatModel.shared.markChatItemsRead(cInfo, itemIds)
}
} catch {
logger.error("apiChatItemsRead error: \(responseError(error))")
logger.error("apiMarkChatItemRead apiChatRead error: \(responseError(error))")
}
}
@@ -1872,25 +1805,23 @@ func processReceivedMsg(_ res: ChatResponse) async {
NtfManager.shared.notifyMessageReceived(user, cInfo, cItem)
}
}
case let .chatItemsStatusesUpdated(user, chatItems):
for chatItem in chatItems {
let cInfo = chatItem.chatInfo
let cItem = chatItem.chatItem
if !cItem.isDeletedContent && active(user) {
await MainActor.run { m.updateChatItem(cInfo, cItem, status: cItem.meta.itemStatus) }
}
if let endTask = m.messageDelivery[cItem.id] {
switch cItem.meta.itemStatus {
case .sndNew: ()
case .sndSent: endTask()
case .sndRcvd: endTask()
case .sndErrorAuth: endTask()
case .sndError: endTask()
case .sndWarning: endTask()
case .rcvNew: ()
case .rcvRead: ()
case .invalid: ()
}
case let .chatItemStatusUpdated(user, aChatItem):
let cInfo = aChatItem.chatInfo
let cItem = aChatItem.chatItem
if !cItem.isDeletedContent && active(user) {
await MainActor.run { m.updateChatItem(cInfo, cItem, status: cItem.meta.itemStatus) }
}
if let endTask = m.messageDelivery[cItem.id] {
switch cItem.meta.itemStatus {
case .sndNew: ()
case .sndSent: endTask()
case .sndRcvd: endTask()
case .sndErrorAuth: endTask()
case .sndError: endTask()
case .sndWarning: endTask()
case .rcvNew: ()
case .rcvRead: ()
case .invalid: ()
}
}
case let .chatItemUpdated(user, aChatItem):
+1 -1
View File
@@ -102,7 +102,7 @@ extension ThemeWallpaper {
public func importFromString() -> ThemeWallpaper {
if preset == nil, let image {
// Need to save image from string and to save its path
if let parsed = imageFromBase64(image),
if let parsed = UIImage(base64Encoded: image),
let filename = saveWallpaperFile(image: parsed) {
var copy = self
copy.image = nil
@@ -214,12 +214,10 @@ struct ActiveCallView: View {
ChatReceiver.shared.messagesChannel = nil
return
}
if case let .chatItemsStatusesUpdated(_, chatItems) = msg,
chatItems.contains(where: { ci in
ci.chatInfo.id == call.contact.id &&
ci.chatItem.content.isSndCall &&
ci.chatItem.meta.itemStatus.isSndRcvd
}) {
if case let .chatItemStatusUpdated(_, msg) = msg,
msg.chatInfo.id == call.contact.id,
case .sndCall = msg.chatItem.content,
case .sndRcvd = msg.chatItem.meta.itemStatus {
CallSoundsPlayer.shared.startInCallSound()
ChatReceiver.shared.messagesChannel = nil
}
@@ -38,7 +38,6 @@ struct IncomingCallView: View {
}
HStack {
ProfilePreview(profileOf: invitation.contact, color: .white)
.padding(.vertical, 6)
Spacer()
callButton("Reject", "phone.down.fill", .red) {
@@ -46,7 +46,7 @@ struct CIGroupInvitationView: View {
.foregroundColor(inProgress ? theme.colors.secondary : chatIncognito ? .indigo : theme.colors.primary)
.font(.callout)
+ Text(" ")
+ ciMetaText(chatItem.meta, chatTTL: nil, encrypted: nil, colorMode: .transparent, showStatus: false, showEdited: false, showViaProxy: showSentViaProxy, showTimesamp: showTimestamp)
+ ciMetaText(chatItem.meta, chatTTL: nil, encrypted: nil, transparent: true, showStatus: false, showEdited: false, showViaProxy: showSentViaProxy, showTimesamp: showTimestamp)
)
.overlay(DetermineWidth())
}
@@ -54,7 +54,7 @@ struct CIGroupInvitationView: View {
(
groupInvitationText()
+ Text(" ")
+ ciMetaText(chatItem.meta, chatTTL: nil, encrypted: nil, colorMode: .transparent, showStatus: false, showEdited: false, showViaProxy: showSentViaProxy, showTimesamp: showTimestamp)
+ ciMetaText(chatItem.meta, chatTTL: nil, encrypted: nil, transparent: true, showStatus: false, showEdited: false, showViaProxy: showSentViaProxy, showTimesamp: showTimestamp)
)
.overlay(DetermineWidth())
}
@@ -165,9 +165,9 @@ struct CIImageView: View {
private func fileIcon(_ icon: String, _ size: CGFloat, _ padding: CGFloat) -> some View {
Image(systemName: icon)
.resizable()
.invertedForegroundStyle()
.aspectRatio(contentMode: .fit)
.frame(width: size, height: size)
.foregroundColor(.white)
.padding(padding)
}
@@ -16,7 +16,7 @@ struct CILinkView: View {
var body: some View {
VStack(alignment: .center, spacing: 6) {
if let uiImage = imageFromBase64(linkPreview.image) {
if let uiImage = UIImage(base64Encoded: linkPreview.image) {
Image(uiImage: uiImage)
.resizable()
.scaledToFit()
@@ -18,7 +18,6 @@ struct CIMetaView: View {
var paleMetaColor = Color(UIColor.tertiaryLabel)
var showStatus = true
var showEdited = true
var invertedMaterial = false
@AppStorage(DEFAULT_SHOW_SENT_VIA_RPOXY) private var showSentViaProxy = false
@@ -26,59 +25,18 @@ struct CIMetaView: View {
if chatItem.isDeletedContent {
chatItem.timestampText.font(.caption).foregroundColor(metaColor)
} else {
ZStack {
ciMetaText(
chatItem.meta,
chatTTL: chat.chatInfo.timedMessagesTTL,
encrypted: chatItem.encryptedFile,
color: metaColor,
paleColor: paleMetaColor,
colorMode: invertedMaterial
? .invertedMaterial
: .normal,
showStatus: showStatus,
showEdited: showEdited,
showViaProxy: showSentViaProxy,
showTimesamp: showTimestamp
).invertedForegroundStyle(enabled: invertedMaterial)
if invertedMaterial {
ciMetaText(
chatItem.meta,
chatTTL: chat.chatInfo.timedMessagesTTL,
encrypted: chatItem.encryptedFile,
colorMode: .normal,
onlyOverrides: true,
showStatus: showStatus,
showEdited: showEdited,
showViaProxy: showSentViaProxy,
showTimesamp: showTimestamp
)
}
}
}
}
}
enum MetaColorMode {
// Renders provided colours
case normal
// Fully transparent meta - used for reserving space
case transparent
// Renders white on dark backgrounds and black on light ones
case invertedMaterial
func resolve(_ c: Color?) -> Color? {
switch self {
case .normal: c
case .transparent: .clear
case .invertedMaterial: nil
}
}
var statusSpacer: Text {
switch self {
case .normal, .transparent: Text(Image(systemName: "circlebadge.fill")).foregroundColor(.clear)
case .invertedMaterial: Text(" ").kerning(13)
ciMetaText(
chatItem.meta,
chatTTL: chat.chatInfo.timedMessagesTTL,
encrypted: chatItem.encryptedFile,
color: chatItem.meta.itemStatus.sndProgress == .partial
? paleMetaColor
: metaColor,
showStatus: showStatus,
showEdited: showEdited,
showViaProxy: showSentViaProxy,
showTimesamp: showTimestamp
)
}
}
}
@@ -87,77 +45,47 @@ func ciMetaText(
_ meta: CIMeta,
chatTTL: Int?,
encrypted: Bool?,
color: Color = .clear, // we use this function to reserve space without rendering meta
paleColor: Color? = nil,
color: Color = .clear,
primaryColor: Color = .accentColor,
colorMode: MetaColorMode = .normal,
onlyOverrides: Bool = false, // only render colors that differ from base
transparent: Bool = false,
showStatus: Bool = true,
showEdited: Bool = true,
showViaProxy: Bool,
showTimesamp: Bool
) -> Text {
var r = Text("")
var space: Text? = nil
let appendSpace = {
if let sp = space {
r = r + sp
space = nil
}
}
let resolved = colorMode.resolve(color)
if showEdited, meta.itemEdited {
r = r + statusIconText("pencil", resolved)
r = r + statusIconText("pencil", color)
}
if meta.disappearing {
r = r + statusIconText("timer", resolved).font(.caption2)
r = r + statusIconText("timer", color).font(.caption2)
let ttl = meta.itemTimed?.ttl
if ttl != chatTTL {
r = r + colored(Text(shortTimeText(ttl)), resolved)
r = r + Text(shortTimeText(ttl)).foregroundColor(color)
}
space = Text(" ")
r = r + Text(" ")
}
if showViaProxy, meta.sentViaProxy == true {
appendSpace()
r = r + statusIconText("arrow.forward", resolved?.opacity(0.67)).font(.caption2)
r = r + statusIconText("arrow.forward", color.opacity(0.67)).font(.caption2)
}
if showStatus {
appendSpace()
if let (image, statusColor) = meta.itemStatus.statusIcon(color, paleColor ?? color, primaryColor) {
let metaColor = if onlyOverrides && statusColor == color {
Color.clear
} else {
colorMode.resolve(statusColor)
}
r = r + colored(Text(image), metaColor)
space = Text(" ")
if let (image, statusColor) = meta.itemStatus.statusIcon(color, primaryColor) {
r = r + Text(image).foregroundColor(transparent ? .clear : statusColor) + Text(" ")
} else if !meta.disappearing {
space = colorMode.statusSpacer + Text(" ")
r = r + statusIconText("circlebadge.fill", .clear) + Text(" ")
}
}
if let enc = encrypted {
appendSpace()
r = r + statusIconText(enc ? "lock" : "lock.open", resolved)
space = Text(" ")
r = r + statusIconText(enc ? "lock" : "lock.open", color) + Text(" ")
}
if showTimesamp {
appendSpace()
r = r + colored(meta.timestampText, resolved)
r = r + meta.timestampText.foregroundColor(color)
}
return r.font(.caption)
}
private func statusIconText(_ icon: String, _ color: Color?) -> Text {
colored(Text(Image(systemName: icon)), color)
}
// Applying `foregroundColor(nil)` breaks `.invertedForegroundStyle` modifier
private func colored(_ t: Text, _ color: Color?) -> Text {
if let color {
t.foregroundColor(color)
} else {
t
}
private func statusIconText(_ icon: String, _ color: Color) -> Text {
Text(Image(systemName: icon)).foregroundColor(color)
}
struct CIMetaView_Previews: PreviewProvider {
@@ -126,7 +126,7 @@ struct CIRcvDecryptionError: View {
.foregroundColor(syncSupported ? theme.colors.primary : theme.colors.secondary)
.font(.callout)
+ Text(" ")
+ ciMetaText(chatItem.meta, chatTTL: nil, encrypted: nil, colorMode: .transparent, showViaProxy: showSentViaProxy, showTimesamp: showTimestamp)
+ ciMetaText(chatItem.meta, chatTTL: nil, encrypted: nil, transparent: true, showViaProxy: showSentViaProxy, showTimesamp: showTimestamp)
)
}
.padding(.horizontal, 12)
@@ -145,7 +145,7 @@ struct CIRcvDecryptionError: View {
.foregroundColor(.red)
.italic()
+ Text(" ")
+ ciMetaText(chatItem.meta, chatTTL: nil, encrypted: nil, colorMode: .transparent, showViaProxy: showSentViaProxy, showTimesamp: showTimestamp)
+ ciMetaText(chatItem.meta, chatTTL: nil, encrypted: nil, transparent: true, showViaProxy: showSentViaProxy, showTimesamp: showTimestamp)
}
.padding(.horizontal, 12)
CIMetaView(chat: chat, chatItem: chatItem, metaColor: theme.colors.secondary)
@@ -292,20 +292,28 @@ struct CIVideoView: View {
.clipShape(Circle())
}
private var fileSizeString: String {
if let file = chatItem.file, !videoPlaying {
" " + ByteCountFormatter.string(fromByteCount: file.fileSize, countStyle: .binary)
} else {
""
}
}
private func durationProgress() -> some View {
Text((durationText(videoPlaying ? progress : duration)) + fileSizeString)
.invertedForegroundStyle()
HStack {
Text("\(durationText(videoPlaying ? progress : duration))")
.foregroundColor(.white)
.font(.caption)
.padding(.vertical, 6)
.padding(.horizontal, 12)
.padding(.vertical, 3)
.padding(.horizontal, 6)
.background(Color.black.opacity(0.35))
.cornerRadius(10)
.padding([.top, .leading], 6)
if let file = chatItem.file, !videoPlaying {
Text("\(ByteCountFormatter.string(fromByteCount: file.fileSize, countStyle: .binary))")
.foregroundColor(.white)
.font(.caption)
.padding(.vertical, 3)
.padding(.horizontal, 6)
.background(Color.black.opacity(0.35))
.cornerRadius(10)
.padding(.top, 6)
}
}
}
private func imageView(_ img: UIImage) -> some View {
@@ -403,9 +411,9 @@ struct CIVideoView: View {
private func fileIcon(_ icon: String, _ size: CGFloat, _ padding: CGFloat) -> some View {
Image(systemName: icon)
.resizable()
.invertedForegroundStyle()
.aspectRatio(contentMode: .fit)
.frame(width: size, height: size)
.foregroundColor(.white)
.padding(smallView ? 0 : padding)
}
@@ -420,8 +428,10 @@ struct CIVideoView: View {
private func progressCircle(_ progress: Int64, _ total: Int64) -> some View {
Circle()
.trim(from: 0, to: Double(progress) / Double(total))
.stroke(style: StrokeStyle(lineWidth: 2))
.invertedForegroundStyle()
.stroke(
Color(uiColor: .white),
style: StrokeStyle(lineWidth: 2)
)
.rotationEffect(.degrees(-90))
.frame(width: 16, height: 16)
.padding([.trailing, .top], smallView ? 0 : 11)
@@ -64,17 +64,12 @@ struct FramedItemView: View {
.overlay(DetermineWidth())
}
if let content = chatItem.content.msgContent {
CIMetaView(
chat: chat,
chatItem: chatItem,
metaColor: theme.colors.secondary,
invertedMaterial: useWhiteMetaColor
)
.padding(.horizontal, 12)
.padding(.bottom, 6)
.overlay(DetermineWidth())
.accessibilityLabel("")
if chatItem.content.msgContent != nil {
CIMetaView(chat: chat, chatItem: chatItem, metaColor: useWhiteMetaColor ? Color.white : theme.colors.secondary)
.padding(.horizontal, 12)
.padding(.bottom, 6)
.overlay(DetermineWidth())
.accessibilityLabel("")
}
}
.background { chatItemFrameColorMaybeImageOrVideo(chatItem, theme).modifier(ChatTailPadding()) }
@@ -190,7 +185,7 @@ struct FramedItemView: View {
let v = ZStack(alignment: .topTrailing) {
switch (qi.content) {
case let .image(_, image):
if let uiImage = imageFromBase64(image) {
if let uiImage = UIImage(base64Encoded: image) {
ciQuotedMsgView(qi)
.padding(.trailing, 70).frame(minWidth: msgWidth, alignment: .leading)
Image(uiImage: uiImage)
@@ -202,7 +197,7 @@ struct FramedItemView: View {
ciQuotedMsgView(qi)
}
case let .video(_, image, _):
if let uiImage = imageFromBase64(image) {
if let uiImage = UIImage(base64Encoded: image) {
ciQuotedMsgView(qi)
.padding(.trailing, 70).frame(minWidth: msgWidth, alignment: .leading)
Image(uiImage: uiImage)
@@ -85,7 +85,7 @@ struct MsgContentView: View {
}
private func reserveSpaceForMeta(_ mt: CIMeta) -> Text {
(rightToLeft ? Text("\n") : Text(" ")) + ciMetaText(mt, chatTTL: chat.chatInfo.timedMessagesTTL, encrypted: nil, colorMode: .transparent, showViaProxy: showSentViaProxy, showTimesamp: showTimestamp)
(rightToLeft ? Text("\n") : Text(" ")) + ciMetaText(mt, chatTTL: chat.chatInfo.timedMessagesTTL, encrypted: nil, transparent: true, showViaProxy: showSentViaProxy, showTimesamp: showTimestamp)
}
}
@@ -14,7 +14,7 @@ struct ChatItemForwardingView: View {
@EnvironmentObject var theme: AppTheme
@Environment(\.dismiss) var dismiss
var chatItems: [ChatItem]
var ci: ChatItem
var fromChatInfo: ChatInfo
@Binding var composeState: ComposeState
@@ -73,14 +73,11 @@ struct ChatItemForwardingView: View {
}
@ViewBuilder private func forwardListChatView(_ chat: Chat) -> some View {
let prohibited = chatItems.map { ci in
chat.prohibitedByPref(
hasSimplexLink: hasSimplexLink(ci.content.msgContent?.text),
isMediaOrFileAttachment: ci.content.msgContent?.isMediaOrFileAttachment ?? false,
isVoice: ci.content.msgContent?.isVoice ?? false
)
}.contains(true)
let prohibited = chat.prohibitedByPref(
hasSimplexLink: hasSimplexLink(ci.content.msgContent?.text),
isMediaOrFileAttachment: ci.content.msgContent?.isMediaOrFileAttachment ?? false,
isVoice: ci.content.msgContent?.isVoice ?? false
)
Button {
if prohibited {
alert = SomeAlert(
@@ -96,10 +93,10 @@ struct ChatItemForwardingView: View {
composeState = ComposeState(
message: composeState.message,
preview: composeState.linkPreview != nil ? composeState.preview : .noPreview,
contextItem: .forwardingItems(chatItems: chatItems, fromChatInfo: fromChatInfo)
contextItem: .forwardingItem(chatItem: ci, fromChatInfo: fromChatInfo)
)
} else {
composeState = ComposeState.init(forwardingItems: chatItems, fromChatInfo: fromChatInfo)
composeState = ComposeState.init(forwardingItem: ci, fromChatInfo: fromChatInfo)
ItemsModel.shared.loadOpenChat(chat.id)
}
}
@@ -126,7 +123,7 @@ struct ChatItemForwardingView: View {
#Preview {
ChatItemForwardingView(
chatItems: [ChatItem.getSample(1, .directSnd, .now, "hello")],
ci: ChatItem.getSample(1, .directSnd, .now, "hello"),
fromChatInfo: .direct(contact: Contact.sampleData),
composeState: Binding.constant(ComposeState(message: "hello"))
).environmentObject(CurrentColors.toAppTheme())
@@ -72,7 +72,7 @@ struct ChatItemView: View {
default: nil
}
}
.flatMap { imageFromBase64($0) }
.flatMap { UIImage(base64Encoded: $0) }
let adjustedMaxWidth = {
if let preview, preview.size.width <= preview.size.height {
maxWidth * 0.75
+107 -317
View File
@@ -23,6 +23,7 @@ struct ChatView: View {
@Environment(\.scenePhase) var scenePhase
@State @ObservedObject var chat: Chat
@StateObject private var scrollModel = ReverseListScrollModel()
@StateObject private var floatingButtonModel: FloatingButtonModel = .shared
@State private var showChatInfoSheet: Bool = false
@State private var showAddMembersSheet: Bool = false
@State private var composeState = ComposeState()
@@ -42,7 +43,6 @@ struct ChatView: View {
@State private var showGroupLinkSheet: Bool = false
@State private var groupLink: String?
@State private var groupLinkMemberRole: GroupMemberRole = .member
@State private var forwardedChatItems: [ChatItem] = []
@State private var selectedChatItems: Set<Int64>? = nil
@State private var showDeleteSelectedMessages: Bool = false
@State private var allowToDeleteSelectedMessagesForAll: Bool = false
@@ -76,7 +76,8 @@ struct ChatView: View {
VStack(spacing: 0) {
ZStack(alignment: .bottomTrailing) {
chatItemsList()
FloatingButtons(theme: theme, scrollModel: scrollModel, chat: chat)
// TODO: Extract into a separate view, to reduce the scope of `FloatingButtonModel` updates
floatingButtons(unreadBelow: floatingButtonModel.unreadBelow, isNearBottom: floatingButtonModel.isNearBottom)
}
connectingText()
if selectedChatItems == nil {
@@ -99,8 +100,7 @@ struct ChatView: View {
if case let .group(groupInfo) = chat.chatInfo {
showModerateSelectedMessagesAlert(groupInfo)
}
},
forwardItems: forwardSelectedMessages
}
)
}
}
@@ -137,22 +137,6 @@ struct ChatView: View {
}
}
}
.sheet(isPresented: Binding(
get: { !forwardedChatItems.isEmpty },
set: { isPresented in
if !isPresented {
forwardedChatItems = []
selectedChatItems = nil
}
}
)) {
if #available(iOS 16.0, *) {
ChatItemForwardingView(chatItems: forwardedChatItems, fromChatInfo: chat.chatInfo, composeState: $composeState)
.presentationDetents([.fraction(0.8)])
} else {
ChatItemForwardingView(chatItems: forwardedChatItems, fromChatInfo: chat.chatInfo, composeState: $composeState)
}
}
.onAppear {
selectedChatItems = nil
initChatView()
@@ -357,7 +341,6 @@ struct ChatView: View {
await markChatUnread(chat, unreadChat: false)
}
}
ChatView.FloatingButtonModel.shared.totalUnread = chat.chatStats.unreadCount
}
private func searchToolbar() -> some View {
@@ -429,8 +412,7 @@ struct ChatView: View {
composeState: $composeState,
selectedMember: $selectedMember,
revealedChatItem: $revealedChatItem,
selectedChatItems: $selectedChatItems,
forwardedChatItems: $forwardedChatItems
selectedChatItems: $selectedChatItems
)
.id(ci.id) // Required to trigger `onAppear` on iOS15
} loadPage: {
@@ -445,7 +427,7 @@ struct ChatView: View {
.onChange(of: im.itemAdded) { added in
if added {
im.itemAdded = false
if FloatingButtonModel.shared.isReallyNearBottom {
if floatingButtonModel.isReallyNearBottom {
scrollModel.scrollToBottom()
}
}
@@ -471,162 +453,86 @@ struct ChatView: View {
static let shared = FloatingButtonModel()
@Published var unreadBelow: Int = 0
@Published var isNearBottom: Bool = true
@Published var date: Date?
@Published var isDateVisible: Bool = false
var totalUnread: Int = 0
var isReallyNearBottom: Bool = true
var hideDateWorkItem: DispatchWorkItem?
var isReallyNearBottom: Bool { scrollOffset.value > 0 && scrollOffset.value < 500 }
let visibleItems = PassthroughSubject<[String], Never>()
let scrollOffset = CurrentValueSubject<Double, Never>(0)
private var bag = Set<AnyCancellable>()
func updateOnListChange(_ listState: ListState) {
let im = ItemsModel.shared
let unreadBelow =
if let id = listState.bottomItemId,
let index = im.reversedChatItems.firstIndex(where: { $0.id == id })
{
im.reversedChatItems[..<index].reduce(into: 0) { unread, chatItem in
if chatItem.isRcvNew { unread += 1 }
}
} else {
0
}
let date: Date? =
if let topItemDate = listState.topItemDate {
Calendar.current.startOfDay(for: topItemDate)
} else {
nil
}
// set the counters and date indicator
DispatchQueue.main.async { [weak self] in
guard let it = self else { return }
it.setDate(visibility: true)
it.unreadBelow = unreadBelow
it.date = date
it.isReallyNearBottom = listState.scrollOffset > 0 && listState.scrollOffset < 500
}
// set floating button indication mode
let nearBottom = listState.scrollOffset < 800
if nearBottom != self.isNearBottom {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.35) { [weak self] in
self?.isNearBottom = nearBottom
}
}
// hide Date indicator after 1 second of no scrolling
hideDateWorkItem?.cancel()
let workItem = DispatchWorkItem { [weak self] in
guard let it = self else { return }
it.setDate(visibility: false)
it.hideDateWorkItem = nil
}
DispatchQueue.main.async { [weak self] in
self?.hideDateWorkItem = workItem
DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: workItem)
}
}
func resetDate() {
date = nil
isDateVisible = false
}
private func setDate(visibility isVisible: Bool) {
if isVisible {
if !isNearBottom,
!isDateVisible,
let date, !Calendar.current.isDateInToday(date) {
withAnimation { self.isDateVisible = true }
}
} else if isDateVisible {
withAnimation { self.isDateVisible = false }
}
}
}
private struct FloatingButtons: View {
let theme: AppTheme
let scrollModel: ReverseListScrollModel
let chat: Chat
@ObservedObject var model = FloatingButtonModel.shared
var body: some View {
ZStack(alignment: .top) {
if let date = model.date {
DateSeparator(date: date)
.padding(.vertical, 4).padding(.horizontal, 8)
.background(.thinMaterial)
.clipShape(Capsule())
.opacity(model.isDateVisible ? 1 : 0)
}
VStack {
let unreadAbove = model.totalUnread - model.unreadBelow
if unreadAbove > 0 {
circleButton {
unreadCountText(unreadAbove)
.font(.callout)
.foregroundColor(theme.colors.primary)
init() {
visibleItems
.receive(on: DispatchQueue.global(qos: .background))
.map { itemIds in
if let viewId = itemIds.first,
let index = ItemsModel.shared.reversedChatItems.firstIndex(where: { $0.viewId == viewId }) {
ItemsModel.shared.reversedChatItems[..<index].reduce(into: 0) { unread, chatItem in
if chatItem.isRcvNew { unread += 1 }
}
.onTapGesture {
scrollModel.scrollToNextPage()
}
.contextMenu {
Button {
Task {
await markChatRead(chat)
}
} label: {
Label("Mark read", systemImage: "checkmark")
}
}
}
Spacer()
if model.unreadBelow > 0 {
circleButton {
unreadCountText(model.unreadBelow)
.font(.callout)
.foregroundColor(theme.colors.primary)
}
.onTapGesture {
scrollModel.scrollToBottom()
}
} else if !model.isNearBottom {
circleButton {
Image(systemName: "chevron.down")
.foregroundColor(theme.colors.primary)
}
.onTapGesture { scrollModel.scrollToBottom() }
}
} else { 0 }
}
.padding()
.frame(maxWidth: .infinity, alignment: .trailing)
}
.onDisappear(perform: model.resetDate)
}
.removeDuplicates()
.receive(on: DispatchQueue.main)
.assign(to: \.unreadBelow, on: self)
.store(in: &bag)
private func circleButton<Content: View>(_ content: @escaping () -> Content) -> some View {
ZStack {
Circle()
.foregroundColor(Color(uiColor: .tertiarySystemGroupedBackground))
.frame(width: 44, height: 44)
content()
}
scrollOffset
.map { $0 < 800 }
.removeDuplicates()
// Delay the state change until scroll to bottom animation is finished
.delay(for: 0.35, scheduler: DispatchQueue.main)
.assign(to: \.isNearBottom, on: self)
.store(in: &bag)
}
}
private struct DateSeparator: View {
let date: Date
private func floatingButtons(unreadBelow: Int, isNearBottom: Bool) -> some View {
VStack {
let unreadAbove = chat.chatStats.unreadCount - unreadBelow
if unreadAbove > 0 {
circleButton {
unreadCountText(unreadAbove)
.font(.callout)
.foregroundColor(theme.colors.primary)
}
.onTapGesture {
scrollModel.scrollToNextPage()
}
.contextMenu {
Button {
Task {
await markChatRead(chat)
}
} label: {
Label("Mark read", systemImage: "checkmark")
}
}
}
Spacer()
if unreadBelow > 0 {
circleButton {
unreadCountText(unreadBelow)
.font(.callout)
.foregroundColor(theme.colors.primary)
}
.onTapGesture {
scrollModel.scrollToBottom()
}
} else if !isNearBottom {
circleButton {
Image(systemName: "chevron.down")
.foregroundColor(theme.colors.primary)
}
.onTapGesture { scrollModel.scrollToBottom() }
}
}
.padding()
}
var body: some View {
Text(String.localizedStringWithFormat(
NSLocalizedString("%@, %@", comment: "format for date separator in chat"),
date.formatted(.dateTime.weekday(.abbreviated)),
date.formatted(.dateTime.day().month(.abbreviated))
))
.font(.callout)
.fontWeight(.medium)
.foregroundStyle(.secondary)
private func circleButton<Content: View>(_ content: @escaping () -> Content) -> some View {
ZStack {
Circle()
.foregroundColor(Color(uiColor: .tertiarySystemGroupedBackground))
.frame(width: 44, height: 44)
content()
}
}
@@ -720,116 +626,6 @@ struct ChatView: View {
}
}
private func forwardSelectedMessages() {
Task {
do {
if let selectedChatItems {
let (validItems, confirmation) = try await apiPlanForwardChatItems(
type: chat.chatInfo.chatType,
id: chat.chatInfo.apiId,
itemIds: Array(selectedChatItems)
)
if let confirmation {
if validItems.count > 0 {
showAlert(
String.localizedStringWithFormat(
NSLocalizedString("Forward %d message(s)?", comment: "alert title"),
validItems.count
),
message: forwardConfirmationText(confirmation) + "\n" +
NSLocalizedString("Forward messages without files?", comment: "alert message")
) {
switch confirmation {
case let .filesNotAccepted(fileIds):
[forwardAction(validItems), downloadAction(fileIds), cancelAlertAction]
default:
[forwardAction(validItems), cancelAlertAction]
}
}
} else {
showAlert(
NSLocalizedString("Nothing to forward!", comment: "alert title"),
message: forwardConfirmationText(confirmation)
) {
switch confirmation {
case let .filesNotAccepted(fileIds):
[downloadAction(fileIds), cancelAlertAction]
default:
[okAlertAction]
}
}
}
} else {
await openForwardingSheet(validItems)
}
}
} catch {
logger.error("Plan forward chat items failed: \(error.localizedDescription)")
}
}
func forwardConfirmationText(_ fc: ForwardConfirmation) -> String {
switch fc {
case let .filesNotAccepted(fileIds):
String.localizedStringWithFormat(
NSLocalizedString("%d file(s) were not downloaded.", comment: "forward confirmation reason"),
fileIds.count
)
case let .filesInProgress(filesCount):
String.localizedStringWithFormat(
NSLocalizedString("%d file(s) are still being downloaded.", comment: "forward confirmation reason"),
filesCount
)
case let .filesMissing(filesCount):
String.localizedStringWithFormat(
NSLocalizedString("%d file(s) were deleted.", comment: "forward confirmation reason"),
filesCount
)
case let .filesFailed(filesCount):
String.localizedStringWithFormat(
NSLocalizedString("%d file(s) failed to download.", comment: "forward confirmation reason"),
filesCount
)
}
}
func forwardAction(_ items: [Int64]) -> UIAlertAction {
UIAlertAction(
title: NSLocalizedString("Forward messages", comment: "alert action"),
style: .default,
handler: { _ in Task { await openForwardingSheet(items) } }
)
}
func downloadAction(_ fileIds: [Int64]) -> UIAlertAction {
UIAlertAction(
title: NSLocalizedString("Download files", comment: "alert action"),
style: .default,
handler: { _ in
Task {
if let user = ChatModel.shared.currentUser {
await receiveFiles(user: user, fileIds: fileIds)
}
}
}
)
}
func openForwardingSheet(_ items: [Int64]) async {
let im = ItemsModel.shared
var items = Set(items)
var fci = [ChatItem]()
for reversedChatItem in im.reversedChatItems {
if items.contains(reversedChatItem.id) {
items.remove(reversedChatItem.id)
fci.insert(reversedChatItem, at: 0)
}
if items.isEmpty { break }
}
await MainActor.run { forwardedChatItems = fci }
}
}
private func loadChatItems(_ cInfo: ChatInfo) {
Task {
if loadingItems || firstPage { return }
@@ -891,14 +687,12 @@ struct ChatView: View {
@State private var showDeleteMessages = false
@State private var showChatItemInfoSheet: Bool = false
@State private var chatItemInfo: ChatItemInfo?
@State private var showTranslationSheet: Bool = false
@State private var showForwardingSheet: Bool = false
@State private var msgWidth: CGFloat = 0
@Binding var selectedChatItems: Set<Int64>?
@Binding var forwardedChatItems: [ChatItem]
@State private var allowMenu: Bool = true
@State private var markedRead = false
var revealed: Bool { chatItem == revealedChatItem }
@@ -910,7 +704,7 @@ struct ChatView: View {
let nextItem = im.reversedChatItems[i - 1]
let largeGap = !nextItem.chatDir.sameDirection(chatItem.chatDir) || nextItem.meta.itemTs.timeIntervalSince(chatItem.meta.itemTs) > 60
return (
timestamp: largeGap || formatTimestampMeta(chatItem.meta.itemTs) != formatTimestampMeta(nextItem.meta.itemTs),
timestamp: largeGap || formatTimestampText(chatItem.meta.itemTs) != formatTimestampText(nextItem.meta.itemTs),
largeGap: largeGap,
date: Calendar.current.isDate(chatItem.meta.itemTs, inSameDayAs: nextItem.meta.itemTs) ? nil : nextItem.meta.itemTs
)
@@ -949,7 +743,15 @@ struct ChatView: View {
VStack(spacing: 0) {
chatItemView(chatItem, range, prevItem, timeSeparation)
if let date = timeSeparation.date {
DateSeparator(date: date).padding(8)
Text(String.localizedStringWithFormat(
NSLocalizedString("%@, %@", comment: "format for date separator in chat"),
date.formatted(.dateTime.weekday(.abbreviated)),
date.formatted(.dateTime.day().month(.abbreviated))
))
.font(.callout)
.fontWeight(.medium)
.foregroundStyle(.secondary)
.padding(8)
}
}
.overlay {
@@ -965,16 +767,12 @@ struct ChatView: View {
}
}
.onAppear {
if markedRead {
return
} else {
markedRead = true
}
if let range {
let itemIds = unreadItemIds(range)
if !itemIds.isEmpty {
if let items = unreadItems(range) {
waitToMarkRead {
await apiMarkChatItemsRead(chat.chatInfo, itemIds)
for ci in items {
await apiMarkChatItemRead(chat.chatInfo, ci)
}
}
}
} else if chatItem.isRcvNew {
@@ -984,24 +782,24 @@ struct ChatView: View {
}
}
}
private func unreadItemIds(_ range: ClosedRange<Int>) -> [ChatItem.ID] {
private func unreadItems(_ range: ClosedRange<Int>) -> [ChatItem]? {
let im = ItemsModel.shared
return range.compactMap { i in
let items = range.compactMap { i in
if i >= 0 && i < im.reversedChatItems.count {
let ci = im.reversedChatItems[i]
return if ci.isRcvNew { ci.id } else { nil }
return if ci.isRcvNew { ci } else { nil }
} else {
return nil
}
}
return if items.isEmpty { nil } else { items }
}
private func waitToMarkRead(_ op: @Sendable @escaping () async -> Void) {
Task {
_ = try? await Task.sleep(nanoseconds: 600_000000)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.6) {
if m.chatId == chat.chatInfo.id {
await op()
Task(operation: op)
}
}
}
@@ -1209,9 +1007,12 @@ struct ChatView: View {
}) {
ChatItemInfoView(ci: ci, chatItemInfo: $chatItemInfo)
}
.sheet(isPresented: $showTranslationSheet) {
if #available(iOS 18.0, *) {
TranslateView(source: ci.text).presentationDetents([.medium, .large])
.sheet(isPresented: $showForwardingSheet) {
if #available(iOS 16.0, *) {
ChatItemForwardingView(ci: ci, fromChatInfo: chat.chatInfo, composeState: $composeState)
.presentationDetents([.fraction(0.8)])
} else {
ChatItemForwardingView(ci: ci, fromChatInfo: chat.chatInfo, composeState: $composeState)
}
}
}
@@ -1270,9 +1071,6 @@ struct ChatView: View {
shareButton(ci)
copyButton(ci)
}
if #available(iOS 18.0, *) {
if !ci.text.isEmpty { translateButton(ci) }
}
if let fileSource = fileSource, fileExists {
if case .image = ci.content.msgContent, let image = getLoadedImage(ci.file) {
if image.imageData != nil {
@@ -1357,7 +1155,7 @@ struct ChatView: View {
var forwardButton: Button<some View> {
Button {
forwardedChatItems = [chatItem]
showForwardingSheet = true
} label: {
Label(
NSLocalizedString("Forward", comment: "chat item action"),
@@ -1457,14 +1255,6 @@ struct ChatView: View {
}
}
private func translateButton(_ ci: ChatItem) -> Button<some View> {
Button {
showTranslationSheet = true
} label: {
Label("Translate", systemImage: "globe")
}
}
func saveButton(image: UIImage) -> Button<some View> {
Button {
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
@@ -18,7 +18,7 @@ struct ComposeImageView: View {
var body: some View {
HStack(alignment: .center, spacing: 8) {
let imgs: [UIImage] = images.compactMap { image in
imageFromBase64(image)
UIImage(base64Encoded: image)
}
if imgs.count == 0 {
ProgressView()
@@ -40,7 +40,7 @@ struct ComposeLinkView: View {
private func linkPreviewView(_ linkPreview: LinkPreview) -> some View {
HStack(alignment: .center, spacing: 8) {
if let uiImage = imageFromBase64(linkPreview.image) {
if let uiImage = UIImage(base64Encoded: linkPreview.image) {
Image(uiImage: uiImage)
.resizable()
.aspectRatio(contentMode: .fit)
@@ -23,7 +23,7 @@ enum ComposeContextItem {
case noContextItem
case quotedItem(chatItem: ChatItem)
case editingItem(chatItem: ChatItem)
case forwardingItems(chatItems: [ChatItem], fromChatInfo: ChatInfo)
case forwardingItem(chatItem: ChatItem, fromChatInfo: ChatInfo)
}
enum VoiceMessageRecordingState {
@@ -73,10 +73,10 @@ struct ComposeState {
}
}
init(forwardingItems: [ChatItem], fromChatInfo: ChatInfo) {
init(forwardingItem: ChatItem, fromChatInfo: ChatInfo) {
self.message = ""
self.preview = .noPreview
self.contextItem = .forwardingItems(chatItems: forwardingItems, fromChatInfo: fromChatInfo)
self.contextItem = .forwardingItem(chatItem: forwardingItem, fromChatInfo: fromChatInfo)
self.voiceMessageRecordingState = .noRecording
}
@@ -112,7 +112,7 @@ struct ComposeState {
var forwarding: Bool {
switch contextItem {
case .forwardingItems: return true
case .forwardingItem: return true
default: return false
}
}
@@ -167,13 +167,6 @@ struct ComposeState {
}
}
var manyMediaPreviews: Bool {
switch preview {
case let .mediaPreviews(mediaPreviews): return mediaPreviews.count > 1
default: return false
}
}
var attachmentDisabled: Bool {
if editing || forwarding || liveMessage != nil || inProgress { return true }
switch preview {
@@ -694,7 +687,7 @@ struct ComposeView: View {
case let .quotedItem(chatItem: quotedItem):
ContextItemView(
chat: chat,
contextItems: [quotedItem],
contextItem: quotedItem,
contextIcon: "arrowshape.turn.up.left",
cancelContextItem: { composeState = composeState.copy(contextItem: .noContextItem) }
)
@@ -702,17 +695,18 @@ struct ComposeView: View {
case let .editingItem(chatItem: editingItem):
ContextItemView(
chat: chat,
contextItems: [editingItem],
contextItem: editingItem,
contextIcon: "pencil",
cancelContextItem: { clearState() }
)
Divider()
case let .forwardingItems(chatItems, _):
case let .forwardingItem(chatItem: forwardedItem, _):
ContextItemView(
chat: chat,
contextItems: chatItems,
contextItem: forwardedItem,
contextIcon: "arrowshape.turn.up.forward",
cancelContextItem: { composeState = composeState.copy(contextItem: .noContextItem) }
cancelContextItem: { composeState = composeState.copy(contextItem: .noContextItem) },
showSender: false
)
Divider()
}
@@ -736,11 +730,10 @@ struct ComposeView: View {
}
if chat.chatInfo.contact?.nextSendGrpInv ?? false {
await sendMemberContactInvitation()
} else if case let .forwardingItems(chatItems, fromChatInfo) = composeState.contextItem {
// Composed text is send as a reply to the last forwarded item
sent = await forwardItems(chatItems, fromChatInfo, ttl).last
} else if case let .forwardingItem(ci, fromChatInfo) = composeState.contextItem {
sent = await forwardItem(ci, fromChatInfo, ttl)
if !composeState.message.isEmpty {
_ = await send(checkLinkPreview(), quoted: sent?.id, live: false, ttl: ttl)
sent = await send(checkLinkPreview(), quoted: sent?.id, live: false, ttl: ttl)
}
} else if case let .editingItem(ci) = composeState.contextItem {
sent = await updateMessage(ci, live: live)
@@ -757,28 +750,27 @@ struct ComposeView: View {
sent = await send(.text(msgText), quoted: quoted, live: live, ttl: ttl)
case .linkPreview:
sent = await send(checkLinkPreview(), quoted: quoted, live: live, ttl: ttl)
case let .mediaPreviews(media):
case let .mediaPreviews(mediaPreviews: media):
// TODO batch send: batch media previews
let last = media.count - 1
var msgs: [ComposedMessage] = []
if last >= 0 {
for i in 0..<last {
if i > 0 {
// Sleep to allow `progressByTimeout` update be rendered
try? await Task.sleep(nanoseconds: 100_000000)
}
if let (fileSource, msgContent) = mediaContent(media[i], text: "") {
msgs.append(ComposedMessage(fileSource: fileSource, msgContent: msgContent))
if case (_, .video(_, _, _)) = media[i] {
sent = await sendVideo(media[i], ttl: ttl)
} else {
sent = await sendImage(media[i], ttl: ttl)
}
_ = try? await Task.sleep(nanoseconds: 100_000000)
}
if let (fileSource, msgContent) = mediaContent(media[last], text: msgText) {
msgs.append(ComposedMessage(fileSource: fileSource, quotedItemId: quoted, msgContent: msgContent))
if case (_, .video(_, _, _)) = media[last] {
sent = await sendVideo(media[last], text: msgText, quoted: quoted, live: live, ttl: ttl)
} else {
sent = await sendImage(media[last], text: msgText, quoted: quoted, live: live, ttl: ttl)
}
}
if msgs.isEmpty {
msgs = [ComposedMessage(quotedItemId: quoted, msgContent: .text(msgText))]
if sent == nil {
sent = await send(.text(msgText), quoted: quoted, live: live, ttl: ttl)
}
sent = await send(msgs, live: live, ttl: ttl).last
case let .voicePreview(recordingFileName, duration):
stopPlayback.toggle()
let file = voiceCryptoFile(recordingFileName)
@@ -800,20 +792,6 @@ struct ComposeView: View {
}
return sent
func mediaContent(_ media: (String, UploadContent?), text: String) -> (CryptoFile?, MsgContent)? {
let (previewImage, uploadContent) = media
return switch uploadContent {
case let .simpleImage(image):
(saveImage(image), .image(text: text, image: previewImage))
case let .animatedImage(image):
(saveAnimImage(image), .image(text: text, image: previewImage))
case let .video(_, url, duration):
(moveTempFileFromURL(url), .video(text: text, image: previewImage, duration: duration))
case .none:
nil
}
}
func sending() async {
await MainActor.run { composeState.inProgress = true }
}
@@ -877,6 +855,23 @@ struct ComposeView: View {
}
}
func sendImage(_ imageData: (String, UploadContent?), text: String = "", quoted: Int64? = nil, live: Bool = false, ttl: Int?) async -> ChatItem? {
let (image, data) = imageData
if let data = data, let savedFile = saveAnyImage(data) {
return await send(.image(text: text, image: image), quoted: quoted, file: savedFile, live: live, ttl: ttl)
}
return nil
}
func sendVideo(_ imageData: (String, UploadContent?), text: String = "", quoted: Int64? = nil, live: Bool = false, ttl: Int?) async -> ChatItem? {
let (image, data) = imageData
if case let .video(_, url, duration) = data, let savedFile = moveTempFileFromURL(url) {
ChatModel.shared.filesToDelete.remove(url)
return await send(.video(text: text, image: image, duration: duration), quoted: quoted, file: savedFile, live: live, ttl: ttl)
}
return nil
}
func voiceCryptoFile(_ fileName: String) -> CryptoFile? {
if !privacyEncryptLocalFilesGroupDefault.get() {
return CryptoFile.plain(fileName)
@@ -893,22 +888,17 @@ struct ComposeView: View {
}
func send(_ mc: MsgContent, quoted: Int64?, file: CryptoFile? = nil, live: Bool = false, ttl: Int?) async -> ChatItem? {
await send(
[ComposedMessage(fileSource: file, quotedItemId: quoted, msgContent: mc)],
live: live,
ttl: ttl
).first
}
func send(_ msgs: [ComposedMessage], live: Bool, ttl: Int?) async -> [ChatItem] {
if let chatItems = chat.chatInfo.chatType == .local
? await apiCreateChatItems(noteFolderId: chat.chatInfo.apiId, composedMessages: msgs)
? await apiCreateChatItems(
noteFolderId: chat.chatInfo.apiId,
composedMessages: [ComposedMessage(fileSource: file, msgContent: mc)]
)
: await apiSendMessages(
type: chat.chatInfo.chatType,
id: chat.chatInfo.apiId,
live: live,
ttl: ttl,
composedMessages: msgs
composedMessages: [ComposedMessage(fileSource: file, quotedItemId: quoted, msgContent: mc)]
) {
await MainActor.run {
chatModel.removeLiveDummy(animated: false)
@@ -916,43 +906,33 @@ struct ComposeView: View {
chatModel.addChatItem(chat.chatInfo, chatItem)
}
}
return chatItems
// UI only supports sending one item at a time
return chatItems.first
}
for msg in msgs {
if let file = msg.fileSource {
removeFile(file.filePath)
}
if let file = file {
removeFile(file.filePath)
}
return []
return nil
}
func forwardItems(_ forwardedItems: [ChatItem], _ fromChatInfo: ChatInfo, _ ttl: Int?) async -> [ChatItem] {
func forwardItem(_ forwardedItem: ChatItem, _ fromChatInfo: ChatInfo, _ ttl: Int?) async -> ChatItem? {
if let chatItems = await apiForwardChatItems(
toChatType: chat.chatInfo.chatType,
toChatId: chat.chatInfo.apiId,
fromChatType: fromChatInfo.chatType,
fromChatId: fromChatInfo.apiId,
itemIds: forwardedItems.map { $0.id },
itemIds: [forwardedItem.id],
ttl: ttl
) {
await MainActor.run {
for chatItem in chatItems {
chatModel.addChatItem(chat.chatInfo, chatItem)
}
if forwardedItems.count != chatItems.count {
showAlert(
String.localizedStringWithFormat(
NSLocalizedString("%d messages not forwarded", comment: "alert title"),
forwardedItems.count - chatItems.count
),
message: NSLocalizedString("Messages were deleted after you selected them.", comment: "alert message")
)
}
}
return chatItems
} else {
return []
// TODO batch send: forward multiple messages
return chatItems.first
}
return nil
}
func checkLinkPreview() -> MsgContent {
@@ -969,6 +949,14 @@ struct ComposeView: View {
return .text(msgText)
}
}
func saveAnyImage(_ img: UploadContent) -> CryptoFile? {
switch img {
case let .simpleImage(image): return saveImage(image)
case let .animatedImage(image): return saveAnimImage(image)
default: return nil
}
}
}
private func startVoiceMessageRecording() async {
@@ -12,7 +12,7 @@ import SimpleXChat
struct ContextItemView: View {
@EnvironmentObject var theme: AppTheme
@ObservedObject var chat: Chat
let contextItems: [ChatItem]
let contextItem: ChatItem
let contextIcon: String
let cancelContextItem: () -> Void
var showSender: Bool = true
@@ -24,22 +24,13 @@ struct ContextItemView: View {
.aspectRatio(contentMode: .fit)
.frame(width: 16, height: 16)
.foregroundColor(theme.colors.secondary)
if let singleItem = contextItems.first, contextItems.count == 1 {
if showSender, let sender = singleItem.memberDisplayName {
VStack(alignment: .leading, spacing: 4) {
Text(sender).font(.caption).foregroundColor(theme.colors.secondary)
msgContentView(lines: 2, contextItem: singleItem)
}
} else {
msgContentView(lines: 3, contextItem: singleItem)
}
if showSender, let sender = contextItem.memberDisplayName {
VStack(alignment: .leading, spacing: 4) {
Text(sender).font(.caption).foregroundColor(theme.colors.secondary)
msgContentView(lines: 2)
}
} else {
Text(
chat.chatInfo.chatType == .local
? "Saving \(contextItems.count) messages"
: "Forwarding \(contextItems.count) messages"
)
.italic()
msgContentView(lines: 3)
}
Spacer()
Button {
@@ -54,32 +45,23 @@ struct ContextItemView: View {
.padding(12)
.frame(minHeight: 54)
.frame(maxWidth: .infinity)
.background(background)
.background(chatItemFrameColor(contextItem, theme))
}
private var background: Color {
contextItems.first
.map { chatItemFrameColor($0, theme) }
?? Color(uiColor: .tertiarySystemBackground)
}
private func msgContentView(lines: Int, contextItem: ChatItem) -> some View {
contextMsgPreview(contextItem)
private func msgContentView(lines: Int) -> some View {
contextMsgPreview()
.multilineTextAlignment(isRightToLeft(contextItem.text) ? .trailing : .leading)
.lineLimit(lines)
}
private func contextMsgPreview(_ contextItem: ChatItem) -> Text {
private func contextMsgPreview() -> Text {
return attachment() + messageText(contextItem.text, contextItem.formattedText, nil, preview: true, showSecrets: false, secondaryColor: theme.colors.secondary)
func attachment() -> Text {
let isFileLoaded = if let fileSource = getLoadedFileSource(contextItem.file) {
FileManager.default.fileExists(atPath: getAppFilePath(fileSource.filePath).path)
} else { false }
switch contextItem.content.msgContent {
case .file: return isFileLoaded ? image("doc.fill") : Text("")
case .file: return image("doc.fill")
case .image: return image("photo")
case .voice: return isFileLoaded ? image("play.fill") : Text("")
case .voice: return image("play.fill")
default: return Text("")
}
}
@@ -93,6 +75,6 @@ struct ContextItemView: View {
struct ContextItemView_Previews: PreviewProvider {
static var previews: some View {
let contextItem: ChatItem = ChatItem.getSample(1, .directSnd, .now, "hello")
return ContextItemView(chat: Chat.sampleData, contextItems: [contextItem], contextIcon: "pencil.circle", cancelContextItem: {})
return ContextItemView(chat: Chat.sampleData, contextItem: contextItem, contextIcon: "pencil.circle", cancelContextItem: {})
}
}
@@ -227,7 +227,6 @@ struct SendMessageView: View {
!composeState.editing {
if case .noContextItem = composeState.contextItem,
!composeState.voicePreview,
!composeState.manyMediaPreviews,
let send = sendLiveMessage,
let update = updateLiveMessage {
Button {
+20 -41
View File
@@ -107,14 +107,9 @@ struct ReverseList<Content: View>: UIViewControllerRepresentable {
name: notificationName,
object: nil
)
updateFloatingButtons
.throttle(for: 0.2, scheduler: DispatchQueue.global(qos: .background), latest: true)
.sink {
if let listState = DispatchQueue.main.sync(execute: { [weak self] in self?.getListState() }) {
ChatView.FloatingButtonModel.shared.updateOnListChange(listState)
}
}
.throttle(for: 0.2, scheduler: DispatchQueue.main, latest: true)
.sink { self.updateVisibleItems() }
.store(in: &bag)
}
@@ -208,35 +203,25 @@ struct ReverseList<Content: View>: UIViewControllerRepresentable {
updateFloatingButtons.send()
}
func getListState() -> ListState? {
if let visibleRows = tableView.indexPathsForVisibleRows,
visibleRows.last?.item ?? 0 < representer.items.count {
let scrollOffset: Double = tableView.contentOffset.y + InvertedTableView.inset
let topItemDate: Date? =
if let lastVisible = visibleRows.last(where: { isVisible(indexPath: $0) }) {
representer.items[lastVisible.item].meta.itemTs
} else {
nil
private func updateVisibleItems() {
let fbm = ChatView.FloatingButtonModel.shared
fbm.scrollOffset.send(tableView.contentOffset.y + InvertedTableView.inset)
fbm.visibleItems.send(
(tableView.indexPathsForVisibleRows ?? [])
.compactMap { indexPath -> String? in
guard let relativeFrame = tableView.superview?.convert(
tableView.rectForRow(at: indexPath),
from: tableView
) else { return nil }
// Checks that the cell is visible accounting for the added insets
let isVisible =
relativeFrame.maxY > InvertedTableView.inset &&
relativeFrame.minY < tableView.frame.height - InvertedTableView.inset
return indexPath.item < representer.items.count && isVisible
? representer.items[indexPath.item].viewId
: nil
}
let bottomItemId: ChatItem.ID? =
if let firstVisible = visibleRows.first(where: { isVisible(indexPath: $0) }) {
representer.items[firstVisible.item].id
} else {
nil
}
return (scrollOffset: scrollOffset, topItemDate: topItemDate, bottomItemId: bottomItemId)
}
return nil
}
private func isVisible(indexPath: IndexPath) -> Bool {
if let relativeFrame = tableView.superview?.convert(
tableView.rectForRow(at: indexPath),
from: tableView
) {
relativeFrame.maxY > InvertedTableView.inset &&
relativeFrame.minY < tableView.frame.height - InvertedTableView.inset
} else { false }
)
}
}
@@ -280,12 +265,6 @@ struct ReverseList<Content: View>: UIViewControllerRepresentable {
}
}
typealias ListState = (
scrollOffset: Double,
topItemDate: Date?,
bottomItemId: ChatItem.ID?
)
/// Manages ``ReverseList`` scrolling
class ReverseListScrollModel: ObservableObject {
/// Represents Scroll State of ``ReverseList``
@@ -32,15 +32,12 @@ struct SelectedItemsBottomToolbar: View {
var deleteItems: (Bool) -> Void
var moderateItems: () -> Void
//var shareItems: () -> Void
var forwardItems: () -> Void
@State var deleteEnabled: Bool = false
@State var deleteForEveryoneEnabled: Bool = false
@State var canModerate: Bool = false
@State var moderateEnabled: Bool = false
@State var forwardEnabled: Bool = false
@State var allButtonsDisabled = false
var body: some View {
@@ -53,7 +50,6 @@ struct SelectedItemsBottomToolbar: View {
} label: {
Image(systemName: "trash")
.resizable()
.scaledToFit()
.frame(width: 20, height: 20, alignment: .center)
.foregroundColor(!deleteEnabled || allButtonsDisabled ? theme.colors.secondary: .red)
}
@@ -65,24 +61,24 @@ struct SelectedItemsBottomToolbar: View {
} label: {
Image(systemName: "flag")
.resizable()
.scaledToFit()
.frame(width: 20, height: 20, alignment: .center)
.foregroundColor(!moderateEnabled || allButtonsDisabled ? theme.colors.secondary : .red)
}
.disabled(!moderateEnabled || allButtonsDisabled)
.opacity(canModerate ? 1 : 0)
Spacer()
Button {
forwardItems()
//shareItems()
} label: {
Image(systemName: "arrowshape.turn.up.forward")
Image(systemName: "square.and.arrow.up")
.resizable()
.scaledToFit()
.frame(width: 20, height: 20, alignment: .center)
.foregroundColor(!forwardEnabled || allButtonsDisabled ? theme.colors.secondary : theme.colors.primary)
.foregroundColor(allButtonsDisabled ? theme.colors.secondary : theme.colors.primary)
}
.disabled(!forwardEnabled || allButtonsDisabled)
.disabled(allButtonsDisabled)
.opacity(0)
}
.frame(maxHeight: .infinity)
.padding([.leading, .trailing], 12)
@@ -110,16 +106,15 @@ struct SelectedItemsBottomToolbar: View {
if let selected = selectedItems {
let me: Bool
let onlyOwnGroupItems: Bool
(deleteEnabled, deleteForEveryoneEnabled, me, onlyOwnGroupItems, forwardEnabled, selectedChatItems) = chatItems.reduce((true, true, true, true, true, [])) { (r, ci) in
(deleteEnabled, deleteForEveryoneEnabled, me, onlyOwnGroupItems, selectedChatItems) = chatItems.reduce((true, true, true, true, [])) { (r, ci) in
if selected.contains(ci.id) {
var (de, dee, me, onlyOwnGroupItems, fe, sel) = r
var (de, dee, me, onlyOwnGroupItems, sel) = r
de = de && ci.canBeDeletedForSelf
dee = dee && ci.meta.deletable && !ci.localNote
onlyOwnGroupItems = onlyOwnGroupItems && ci.chatDir == .groupSnd
me = me && ci.content.msgContent != nil && ci.memberToModerate(chatInfo) != nil
fe = fe && ci.content.msgContent != nil && ci.meta.itemDeleted == nil && !ci.isLiveDummy
sel.insert(ci.id) // we are collecting new selected items here to account for any changes in chat items list
return (de, dee, me, onlyOwnGroupItems, fe, sel)
return (de, dee, me, onlyOwnGroupItems, sel)
} else {
return r
}
@@ -1,73 +0,0 @@
//
// TranslateView.swift
// SimpleX
//
// Created by user on 19/09/2024.
// Copyright © 2024 SimpleX Chat. All rights reserved.
//
import SwiftUI
import Translation
@available(iOS 18.0, *)
struct TranslateView: View {
let source: String
@State private var supprtedLanguages = [Locale.Language]()
@State private var target: String?
@State private var configuration = TranslationSession.Configuration()
var body: some View {
NavigationStack {
List {
Section {
languagePicker("From", selection: $configuration.source)
Text(source).foregroundStyle(.secondary).lineLimit(1)
}
Section {
languagePicker("To ", selection: $configuration.target)
if let target {
Text(target)
} else {
ProgressView()
}
} footer: {
Text("\(Image(systemName: "info.circle")) Uses on device translation")
}
}
.navigationTitle("Translate")
}
.task { supprtedLanguages = await LanguageAvailability().supportedLanguages }
.translationTask(configuration) { session in
do {
target = nil
let response = try await session.translate(source)
await MainActor.run {
configuration.source = response.sourceLanguage
configuration.target = response.targetLanguage
target = response.targetText
}
} catch {
print(error)
}
}
}
@ViewBuilder
private func languagePicker(_ label: String, selection: Binding<Locale.Language?>) -> some View {
Picker(label, selection: selection) {
Text("Detect language").tag(Optional<Locale.Language>.none)
ForEach(supprtedLanguages, id: \.self) { language in
Text(title(for: language)).tag(language)
}
}
}
private func title(for language: Locale.Language) -> String {
if let code = language.languageCode,
let string = Locale.current.localizedString(forLanguageCode: code.identifier) {
string
} else {
language.minimalIdentifier
}
}
}
@@ -9,17 +9,6 @@
import SwiftUI
import SimpleXChat
enum UserPickerSheet: Identifiable {
case address
case chatPreferences
case chatProfiles
case currentProfile
case useFromDesktop
case settings
var id: Self { self }
}
struct ChatListView: View {
@EnvironmentObject var chatModel: ChatModel
@EnvironmentObject var theme: AppTheme
@@ -29,9 +18,9 @@ struct ChatListView: View {
@State private var searchText = ""
@State private var searchShowingSimplexLink = false
@State private var searchChatFilteredBySimplexLink: String? = nil
@State private var userPickerVisible = false
@State private var showConnectDesktop = false
@State private var scrollToSearchBar = false
@State private var activeUserPickerSheet: UserPickerSheet? = nil
@State private var userPickerShown: Bool = false
@AppStorage(DEFAULT_SHOW_UNREAD_AND_FAVORITES) private var showUnreadAndFavorites = false
@AppStorage(GROUP_DEFAULT_ONE_HAND_UI, store: groupDefaults) private var oneHandUI = true
@@ -57,44 +46,21 @@ struct ChatListView: View {
),
destination: chatView
) { chatListView }
}
.sheet(isPresented: $userPickerShown) {
UserPicker(activeSheet: $activeUserPickerSheet)
.sheet(item: $activeUserPickerSheet) { sheet in
if let currentUser = chatModel.currentUser {
switch sheet {
case .address:
NavigationView {
UserAddressView(shareViaProfile: currentUser.addressShared)
.navigationTitle("SimpleX address")
.navigationBarTitleDisplayMode(.large)
.modifier(ThemedBackground(grouped: true))
}
case .chatProfiles:
NavigationView {
UserProfilesView()
}
case .currentProfile:
NavigationView {
UserProfile()
.navigationTitle("Your current profile")
.modifier(ThemedBackground(grouped: true))
}
case .chatPreferences:
NavigationView {
PreferencesView(profile: currentUser.profile, preferences: currentUser.fullPreferences, currentPreferences: currentUser.fullPreferences)
.navigationTitle("Your preferences")
.navigationBarTitleDisplayMode(.large)
.modifier(ThemedBackground(grouped: true))
}
case .useFromDesktop:
ConnectDesktopView(viaSettings: false)
case .settings:
SettingsView(showSettings: $showSettings)
.navigationBarTitleDisplayMode(.large)
}
if userPickerVisible {
Rectangle().fill(.white.opacity(0.001)).onTapGesture {
withAnimation {
userPickerVisible.toggle()
}
}
}
UserPicker(
showSettings: $showSettings,
showConnectDesktop: $showConnectDesktop,
userPickerVisible: $userPickerVisible
)
}
.sheet(isPresented: $showConnectDesktop) {
ConnectDesktopView()
}
}
@@ -107,7 +73,7 @@ struct ChatListView: View {
.navigationBarHidden(searchMode || oneHandUI)
}
.scaleEffect(x: 1, y: oneHandUI ? -1 : 1, anchor: .center)
.onDisappear() { activeUserPickerSheet = nil }
.onDisappear() { withAnimation { userPickerVisible = false } }
.refreshable {
AlertManager.shared.showAlert(Alert(
title: Text("Reconnect servers?"),
@@ -198,7 +164,7 @@ struct ChatListView: View {
let user = chatModel.currentUser ?? User.sampleData
ZStack(alignment: .topTrailing) {
ProfileImage(imageStr: user.image, size: 32, color: Color(uiColor: .quaternaryLabel))
.padding([.top, .trailing], 3)
.padding(.trailing, 4)
let allRead = chatModel.users
.filter { u in !u.user.activeUser && !u.user.hidden }
.allSatisfy { u in u.unreadCount == 0 }
@@ -207,7 +173,13 @@ struct ChatListView: View {
}
}
.onTapGesture {
userPickerShown = true
if chatModel.users.filter({ u in u.user.activeUser || !u.user.hidden }).count > 1 {
withAnimation {
userPickerVisible.toggle()
}
} else {
showSettings = true
}
}
}
@@ -297,7 +269,7 @@ struct ChatListView: View {
}
}
private func unreadBadge(size: CGFloat = 18) -> some View {
private func unreadBadge(_ text: Text? = Text(" "), size: CGFloat = 18) -> some View {
Circle()
.frame(width: size, height: size)
.foregroundColor(theme.colors.primary)
@@ -302,7 +302,7 @@ struct ChatPreviewView: View {
case let .link(_, preview):
smallContentPreview(size: dynamicMediaSize) {
ZStack(alignment: .topTrailing) {
Image(uiImage: imageFromBase64(preview.image) ?? UIImage(systemName: "arrow.up.right")!)
Image(uiImage: UIImage(base64Encoded: preview.image) ?? UIImage(systemName: "arrow.up.right")!)
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: dynamicMediaSize, height: dynamicMediaSize)
@@ -323,12 +323,12 @@ struct ChatPreviewView: View {
}
case let .image(_, image):
smallContentPreview(size: dynamicMediaSize) {
CIImageView(chatItem: ci, preview: imageFromBase64(image), maxWidth: dynamicMediaSize, smallView: true, showFullScreenImage: $showFullscreenGallery)
CIImageView(chatItem: ci, preview: UIImage(base64Encoded: image), maxWidth: dynamicMediaSize, smallView: true, showFullScreenImage: $showFullscreenGallery)
.environmentObject(ReverseListScrollModel())
}
case let .video(_,image, duration):
smallContentPreview(size: dynamicMediaSize) {
CIVideoView(chatItem: ci, preview: imageFromBase64(image), duration: duration, maxWidth: dynamicMediaSize, videoWidth: nil, smallView: true, showFullscreenPlayer: $showFullscreenGallery)
CIVideoView(chatItem: ci, preview: UIImage(base64Encoded: image), duration: duration, maxWidth: dynamicMediaSize, videoWidth: nil, smallView: true, showFullscreenPlayer: $showFullscreenGallery)
.environmentObject(ReverseListScrollModel())
}
case let .voice(_, duration):
@@ -407,18 +407,12 @@ struct ServersSummaryView: View {
struct SubscriptionStatusIndicatorView: View {
@EnvironmentObject var m: ChatModel
@EnvironmentObject var theme: AppTheme
var subs: SMPServerSubs
var hasSess: Bool
var body: some View {
let (color, variableValue, opacity, _) = subscriptionStatusColorAndPercentage(
online: m.networkInfo.online,
usesProxy: networkUseOnionHostsGroupDefault.get() != .no || groupDefaults.string(forKey: GROUP_DEFAULT_NETWORK_SOCKS_PROXY) != nil,
subs: subs,
hasSess: hasSess,
primaryColor: theme.colors.primary
)
let onionHosts = networkUseOnionHostsGroupDefault.get()
let (color, variableValue, opacity, _) = subscriptionStatusColorAndPercentage(m.networkInfo.online, onionHosts, subs, hasSess)
if #available(iOS 16.0, *) {
Image(systemName: "dot.radiowaves.up.forward", variableValue: variableValue)
.foregroundColor(color)
@@ -431,32 +425,26 @@ struct SubscriptionStatusIndicatorView: View {
struct SubscriptionStatusPercentageView: View {
@EnvironmentObject var m: ChatModel
@EnvironmentObject var theme: AppTheme
var subs: SMPServerSubs
var hasSess: Bool
var body: some View {
let (_, _, _, statusPercent) = subscriptionStatusColorAndPercentage(
online: m.networkInfo.online,
usesProxy: networkUseOnionHostsGroupDefault.get() != .no || groupDefaults.string(forKey: GROUP_DEFAULT_NETWORK_SOCKS_PROXY) != nil,
subs: subs,
hasSess: hasSess,
primaryColor: theme.colors.primary
)
let onionHosts = networkUseOnionHostsGroupDefault.get()
let (_, _, _, statusPercent) = subscriptionStatusColorAndPercentage(m.networkInfo.online, onionHosts, subs, hasSess)
Text(verbatim: "\(Int(floor(statusPercent * 100)))%")
.foregroundColor(.secondary)
.font(.caption)
}
}
func subscriptionStatusColorAndPercentage(online: Bool, usesProxy: Bool, subs: SMPServerSubs, hasSess: Bool, primaryColor: Color) -> (Color, Double, Double, Double) {
func subscriptionStatusColorAndPercentage(_ online: Bool, _ onionHosts: OnionHosts, _ subs: SMPServerSubs, _ hasSess: Bool) -> (Color, Double, Double, Double) {
func roundedToQuarter(_ n: Double) -> Double {
n >= 1 ? 1
: n <= 0 ? 0
: (n * 4).rounded() / 4
}
let activeColor: Color = usesProxy ? .indigo : primaryColor
let activeColor: Color = onionHosts == .require ? .indigo : .accentColor
let noConnColorAndPercent: (Color, Double, Double, Double) = (Color(uiColor: .tertiaryLabel), 1, 1, 0)
let activeSubsRounded = roundedToQuarter(subs.shareOfActive)
+139 -188
View File
@@ -8,228 +8,179 @@ import SimpleXChat
struct UserPicker: View {
@EnvironmentObject var m: ChatModel
@Environment(\.scenePhase) var scenePhase
@EnvironmentObject var theme: AppTheme
@Environment(\.dynamicTypeSize) private var userFont: DynamicTypeSize
@Environment(\.scenePhase) private var scenePhase: ScenePhase
@Environment(\.colorScheme) private var colorScheme: ColorScheme
@Environment(\.dismiss) private var dismiss: DismissAction
@Binding var activeSheet: UserPickerSheet?
@State private var switchingProfile = false
@Binding var showSettings: Bool
@Binding var showConnectDesktop: Bool
@Binding var userPickerVisible: Bool
@State var scrollViewContentSize: CGSize = .zero
@State var disableScrolling: Bool = true
private let menuButtonHeight: CGFloat = 68
@State var chatViewNameWidth: CGFloat = 0
var body: some View {
if #available(iOS 16.0, *) {
let v = viewBody.presentationDetents([.height(420)])
if #available(iOS 16.4, *) {
v.scrollBounceBehavior(.basedOnSize)
} else {
v
}
} else {
viewBody
}
}
private var viewBody: some View {
let otherUsers = m.users.filter { u in !u.user.hidden && u.user.userId != m.currentUser?.userId }
return List {
Section(header: Text("You").foregroundColor(theme.colors.secondary)) {
if let user = m.currentUser {
openSheetOnTap(label: {
ZStack {
let v = ProfilePreview(profileOf: user)
.foregroundColor(.primary)
.padding(.leading, -8)
if #available(iOS 16.0, *) {
v
} else {
v.padding(.vertical, 4)
VStack {
Spacer().frame(height: 1)
VStack(spacing: 0) {
ScrollView {
ScrollViewReader { sp in
let users = m.users
.filter({ u in u.user.activeUser || !u.user.hidden })
.sorted { u, _ in u.user.activeUser }
VStack(spacing: 0) {
ForEach(users) { u in
userView(u)
Divider()
if u.user.activeUser { Divider() }
}
}
}) {
activeSheet = .currentProfile
}
openSheetOnTap(title: m.userAddress == nil ? "Create SimpleX address" : "Your SimpleX address", icon: "qrcode") {
activeSheet = .address
}
openSheetOnTap(title: "Chat preferences", icon: "switch.2") {
activeSheet = .chatPreferences
}
}
}
Section {
if otherUsers.isEmpty {
openSheetOnTap(title: "Your chat profiles", icon: "person.crop.rectangle.stack") {
activeSheet = .chatProfiles
}
} else {
let v = userPickerRow(otherUsers, size: 44)
.padding(.leading, -11)
if #available(iOS 16.0, *) {
v
} else {
v.padding(.vertical, 4)
}
}
openSheetOnTap(title: "Use from desktop", icon: "desktopcomputer") {
activeSheet = .useFromDesktop
}
ZStack(alignment: .trailing) {
openSheetOnTap(title: "Settings", icon: "gearshape") {
activeSheet = .settings
}
Label {} icon: {
Image(systemName: colorScheme == .light ? "sun.max" : "moon.fill")
.resizable()
.symbolRenderingMode(.monochrome)
.foregroundColor(theme.colors.secondary)
.frame(maxWidth: 20, maxHeight: 20)
}
.onTapGesture {
if (colorScheme == .light) {
ThemeManager.applyTheme(systemDarkThemeDefault.get())
} else {
ThemeManager.applyTheme(DefaultTheme.LIGHT.themeName)
.overlay {
GeometryReader { geo -> Color in
DispatchQueue.main.async {
scrollViewContentSize = geo.size
let scenes = UIApplication.shared.connectedScenes
if let windowScene = scenes.first as? UIWindowScene {
let layoutFrame = windowScene.windows[0].safeAreaLayoutGuide.layoutFrame
disableScrolling = scrollViewContentSize.height + menuButtonHeight + 10 < layoutFrame.height
}
}
return Color.clear
}
}
.onChange(of: userPickerVisible) { visible in
if visible, let u = users.first {
sp.scrollTo(u.id)
}
}
}
.onLongPressGesture {
ThemeManager.applyTheme(DefaultTheme.SYSTEM_THEME_NAME)
}
.simultaneousGesture(DragGesture(minimumDistance: disableScrolling ? 0 : 10000000))
.frame(maxHeight: scrollViewContentSize.height)
menuButton("Use from desktop", icon: "desktopcomputer") {
showConnectDesktop = true
withAnimation {
userPickerVisible.toggle()
}
}
Divider()
menuButton("Settings", icon: "gearshape") {
showSettings = true
withAnimation {
userPickerVisible.toggle()
}
}
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
.clipShape(RoundedRectangle(cornerRadius: 16))
.background(
Rectangle()
.fill(theme.colors.surface)
.cornerRadius(16)
.shadow(color: .black.opacity(0.12), radius: 24, x: 0, y: 0)
)
.onPreferenceChange(DetermineWidth.Key.self) { chatViewNameWidth = $0 }
.frame(maxWidth: chatViewNameWidth > 0 ? min(300, chatViewNameWidth + 130) : 300)
.padding(8)
.opacity(userPickerVisible ? 1.0 : 0.0)
.onAppear {
// This check prevents the call of listUsers after the app is suspended, and the database is closed.
if case .active = scenePhase {
// This check prevents the call of listUsers after the app is suspended, and the database is closed.
if case .active = scenePhase {
Task {
do {
let users = try await listUsersAsync()
await MainActor.run { m.users = users }
} catch {
logger.error("Error loading users \(responseError(error))")
}
}
}
}
}
private func userView(_ u: UserInfo) -> some View {
let user = u.user
return Button(action: {
if user.activeUser {
showSettings = true
withAnimation {
userPickerVisible.toggle()
}
} else {
Task {
do {
let users = try await listUsersAsync()
await MainActor.run { m.users = users }
try await changeActiveUserAsync_(user.userId, viewPwd: nil)
await MainActor.run { userPickerVisible = false }
} catch {
logger.error("Error loading users \(responseError(error))")
}
}
}
}
.modifier(ThemedBackground(grouped: true))
.disabled(switchingProfile)
}
private func userPickerRow(_ users: [UserInfo], size: CGFloat) -> some View {
HStack(spacing: 6) {
let s = ScrollView(.horizontal) {
HStack(spacing: 27) {
ForEach(users) { u in
if !u.user.hidden && u.user.userId != m.currentUser?.userId {
userView(u, size: size)
await MainActor.run {
AlertManager.shared.showAlertMsg(
title: "Error switching profile!",
message: "Error: \(responseError(error))"
)
}
}
}
.padding(.leading, 4)
.padding(.trailing, 22)
}
ZStack(alignment: .trailing) {
if #available(iOS 16.0, *) {
s.scrollIndicators(.hidden)
} else {
s
}, label: {
HStack(spacing: 0) {
ProfileImage(imageStr: user.image, size: 44, color: Color(uiColor: .tertiarySystemFill))
.padding(.trailing, 12)
Text(user.chatViewName)
.fontWeight(user.activeUser ? .medium : .regular)
.foregroundColor(theme.colors.onBackground)
.overlay(DetermineWidth())
Spacer()
if user.activeUser {
Image(systemName: "checkmark")
} else if u.unreadCount > 0 {
unreadCounter(u.unreadCount, color: user.showNtfs ? theme.colors.primary : theme.colors.secondary)
} else if !user.showNtfs {
Image(systemName: "speaker.slash")
}
LinearGradient(
colors: [.clear, .black],
startPoint: .leading,
endPoint: .trailing
)
.frame(width: size, height: size + 3)
.blendMode(.destinationOut)
.allowsHitTesting(false)
}
.compositingGroup()
.padding(.top, -3) // to fit unread badge
Spacer()
Image(systemName: "chevron.right")
.foregroundColor(theme.colors.secondary)
.padding(.trailing, 4)
.onTapGesture {
activeSheet = .chatProfiles
}
}
.padding(.trailing)
.padding([.leading, .vertical], 12)
})
.buttonStyle(PressedButtonStyle(defaultColor: theme.colors.surface, pressedColor: Color(uiColor: .secondarySystemFill)))
}
private func userView(_ u: UserInfo, size: CGFloat) -> some View {
ZStack(alignment: .topTrailing) {
ProfileImage(imageStr: u.user.image, size: size, color: Color(uiColor: .tertiarySystemGroupedBackground))
.padding([.top, .trailing], 3)
if (u.unreadCount > 0) {
unreadBadge(u)
}
}
.frame(width: size)
.onTapGesture {
switchingProfile = true
Task {
do {
try await changeActiveUserAsync_(u.user.userId, viewPwd: nil)
await MainActor.run {
switchingProfile = false
dismiss()
}
} catch {
await MainActor.run {
switchingProfile = false
AlertManager.shared.showAlertMsg(
title: "Error switching profile!",
message: "Error: \(responseError(error))"
)
}
}
}
}
}
private func openSheetOnTap(title: LocalizedStringKey, icon: String, action: @escaping () -> Void) -> some View {
openSheetOnTap(label: {
ZStack(alignment: .leading) {
Image(systemName: icon).frame(maxWidth: 24, maxHeight: 24, alignment: .center)
private func menuButton(_ title: LocalizedStringKey, icon: String, action: @escaping () -> Void) -> some View {
Button(action: action) {
HStack(spacing: 0) {
Text(title)
.overlay(DetermineWidth())
Spacer()
Image(systemName: icon)
.symbolRenderingMode(.monochrome)
.foregroundColor(theme.colors.secondary)
Text(title)
.foregroundColor(.primary)
.padding(.leading, 36)
}
}, action: action)
}
private func openSheetOnTap<V: View>(label: () -> V, action: @escaping () -> Void) -> some View {
Button(action: action, label: label)
.frame(maxWidth: .infinity, alignment: .leading)
.contentShape(Rectangle())
}
private func unreadBadge(_ u: UserInfo) -> some View {
let size = dynamicSize(userFont).chatInfoSize
return unreadCountText(u.unreadCount)
.font(userFont <= .xxxLarge ? .caption : .caption2)
.foregroundColor(.white)
.padding(.horizontal, dynamicSize(userFont).unreadPadding)
.frame(minWidth: size, minHeight: size)
.background(u.user.showNtfs ? theme.colors.primary : theme.colors.secondary)
.cornerRadius(dynamicSize(userFont).unreadCorner)
.padding(.horizontal)
.padding(.vertical, 22)
.frame(height: menuButtonHeight)
}
.buttonStyle(PressedButtonStyle(defaultColor: theme.colors.surface, pressedColor: Color(uiColor: .secondarySystemFill)))
}
}
private func unreadCounter(_ unread: Int, color: Color) -> some View {
unreadCountText(unread)
.font(.caption)
.foregroundColor(.white)
.padding(.horizontal, 4)
.frame(minWidth: 18, minHeight: 18)
.background(color)
.cornerRadius(10)
}
struct UserPicker_Previews: PreviewProvider {
static var previews: some View {
@State var activeSheet: UserPickerSheet?
let m = ChatModel()
m.users = [UserInfo.sampleData, UserInfo.sampleData]
return UserPicker(
activeSheet: $activeSheet
showSettings: Binding.constant(false),
showConnectDesktop: Binding.constant(false),
userPickerVisible: Binding.constant(true)
)
.environmentObject(m)
}
@@ -270,12 +270,12 @@ struct DatabaseView: View {
case let .archiveImportedWithErrors(errs):
return Alert(
title: Text("Chat database imported"),
message: Text("Restart the app to use imported chat database") + Text(verbatim: "\n") + Text("Some non-fatal errors occurred during import:") + archiveErrorsText(errs)
message: Text("Restart the app to use imported chat database") + Text(verbatim: "\n\n") + Text("Some non-fatal errors occurred during import:") + archiveErrorsText(errs)
)
case let .archiveExportedWithErrors(archivePath, errs):
return Alert(
title: Text("Chat database exported"),
message: Text("You may save the exported archive.") + Text(verbatim: "\n") + Text("Some file(s) were not exported:") + archiveErrorsText(errs),
message: Text("You may save the exported archive.") + Text(verbatim: "\n\n") + Text("Some file(s) were not exported:") + archiveErrorsText(errs),
dismissButton: .default(Text("Continue")) {
showShareSheet(items: [archivePath])
}
@@ -1,21 +0,0 @@
//
// Test.swift
// SimpleX (iOS)
//
// Created by Levitating Pineapple on 31/08/2024.
// Copyright © 2024 SimpleX Chat. All rights reserved.
//
import SwiftUI
extension View {
@ViewBuilder
func invertedForegroundStyle(enabled: Bool = true) -> some View {
if enabled {
foregroundStyle(Material.ultraThin)
.environment(\.colorScheme, .dark)
.grayscale(1)
.contrast(-20)
} else { self }
}
}
@@ -20,7 +20,7 @@ struct ProfileImage: View {
@AppStorage(DEFAULT_PROFILE_IMAGE_CORNER_RADIUS) private var radius = defaultProfileImageCorner
var body: some View {
if let uiImage = imageFromBase64(imageStr) {
if let uiImage = UIImage(base64Encoded: imageStr) {
clipProfileImage(Image(uiImage: uiImage), size: size, radius: radius, blurred: blurred)
} else {
let c = color.asAnotherColorFromSecondaryVariant(theme)
+5 -53
View File
@@ -8,63 +8,15 @@
import SwiftUI
func getTopViewController() -> UIViewController? {
func showShareSheet(items: [Any], completed: (() -> Void)? = nil) {
let keyWindowScene = UIApplication.shared.connectedScenes.first { $0.activationState == .foregroundActive } as? UIWindowScene
if let keyWindow = keyWindowScene?.windows.filter(\.isKeyWindow).first,
let rootViewController = keyWindow.rootViewController {
// Find the top-most presented view controller
var topController = rootViewController
while let presentedViewController = topController.presentedViewController {
topController = presentedViewController
}
return topController
}
return nil
}
func showShareSheet(items: [Any], completed: (() -> Void)? = nil) {
if let topController = getTopViewController() {
let presentedViewController = keyWindow.rootViewController?.presentedViewController ?? keyWindow.rootViewController {
let activityViewController = UIActivityViewController(activityItems: items, applicationActivities: nil)
if let completed = completed {
activityViewController.completionWithItemsHandler = { _, _, _, _ in
completed()
}
}
topController.present(activityViewController, animated: true)
}
}
func showAlert(
title: String,
message: String? = nil,
buttonTitle: String,
buttonAction: @escaping () -> Void,
cancelButton: Bool
) -> Void {
if let topController = getTopViewController() {
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: buttonTitle, style: .default) { _ in
buttonAction()
})
if cancelButton {
alert.addAction(cancelAlertAction)
let handler: UIActivityViewController.CompletionWithItemsHandler = { _,_,_,_ in completed() }
activityViewController.completionWithItemsHandler = handler
}
topController.present(alert, animated: true)
presentedViewController.present(activityViewController, animated: true)
}
}
func showAlert(
_ title: String,
message: String? = nil,
actions: () -> [UIAlertAction] = { [okAlertAction] }
) {
if let topController = getTopViewController() {
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
for action in actions() { alert.addAction(action) }
topController.present(alert, animated: true)
}
}
let okAlertAction = UIAlertAction(title: NSLocalizedString("Ok", comment: "alert button"), style: .default)
let cancelAlertAction = UIAlertAction(title: NSLocalizedString("Cancel", comment: "alert button"), style: .cancel)
@@ -24,7 +24,6 @@ private enum MigrationFromState: Equatable {
}
private enum MigrateFromDeviceViewAlert: Identifiable {
case finishMigration(_ fileId: Int64, _ ctrl: chat_ctrl)
case deleteChat(_ title: LocalizedStringKey = "Delete chat profile?", _ text: LocalizedStringKey = "This action cannot be undone - your profile, contacts, messages and files will be irreversibly lost.")
case startChat(_ title: LocalizedStringKey = "Start chat?", _ text: LocalizedStringKey = "Warning: starting chat on multiple devices is not supported and will cause message delivery failures")
@@ -39,7 +38,6 @@ private enum MigrateFromDeviceViewAlert: Identifiable {
var id: String {
switch self {
case .finishMigration: return "finishMigration"
case let .deleteChat(title, text): return "\(title) \(text)"
case let .startChat(title, text): return "\(title) \(text)"
@@ -58,6 +56,8 @@ private enum MigrateFromDeviceViewAlert: Identifiable {
struct MigrateFromDevice: View {
@EnvironmentObject var m: ChatModel
@EnvironmentObject var theme: AppTheme
@Environment(\.dismiss) var dismiss: DismissAction
@Binding var showSettings: Bool
@Binding var showProgressOnSettings: Bool
@State private var migrationState: MigrationFromState = .chatStopInProgress
@State private var useKeychain = storeDBPassphraseGroupDefault.get()
@@ -106,6 +106,9 @@ struct MigrateFromDevice: View {
finishedView(chatDeletion)
}
}
.modifier(BackButton(label: "Back", disabled: $backDisabled) {
dismiss()
})
.onChange(of: migrationState) { state in
backDisabled = switch migrationState {
case .chatStopInProgress, .archiving, .linkShown, .finished: true
@@ -135,15 +138,6 @@ struct MigrateFromDevice: View {
}
.alert(item: $alert) { alert in
switch alert {
case let .finishMigration(fileId, ctrl):
return Alert(
title: Text("Remove archive?"),
message: Text("The uploaded database archive will be permanently removed from the servers."),
primaryButton: .destructive(Text("Continue")) {
finishMigration(fileId, ctrl)
},
secondaryButton: .cancel()
)
case let .startChat(title, text):
return Alert(
title: Text(title),
@@ -177,7 +171,7 @@ struct MigrateFromDevice: View {
case let .archiveExportedWithErrors(archivePath, errs):
return Alert(
title: Text("Chat database exported"),
message: Text("You may migrate the exported database.") + Text(verbatim: "\n") + Text("Some file(s) were not exported:") + archiveErrorsText(errs),
message: Text("You may migrate the exported database.") + Text(verbatim: "\n\n") + Text("Some file(s) were not exported:") + archiveErrorsText(errs),
dismissButton: .default(Text("Continue")) {
Task { await uploadArchive(path: archivePath) }
}
@@ -324,7 +318,7 @@ struct MigrateFromDevice: View {
Text("Cancel migration").foregroundColor(.red)
}
}
Button(action: { alert = .finishMigration(fileId, ctrl) }) {
Button(action: { finishMigration(fileId, ctrl) }) {
settingsRow("checkmark", color: theme.colors.secondary) {
Text("Finalize migration").foregroundColor(theme.colors.primary)
}
@@ -529,15 +523,9 @@ struct MigrateFromDevice: View {
}
case let .sndStandaloneFileComplete(_, fileTransferMeta, rcvURIs):
let cfg = getNetCfg()
let proxy: NetworkProxy? = if cfg.socksProxy == nil {
nil
} else {
networkProxyDefault.get()
}
let data = MigrationFileLinkData.init(
networkConfig: MigrationFileLinkData.NetworkConfig(
socksProxy: cfg.socksProxy,
networkProxy: proxy,
hostMode: cfg.hostMode,
requiredHostMode: cfg.requiredHostMode
)
@@ -602,7 +590,7 @@ struct MigrateFromDevice: View {
} catch let error {
fatalError("Error starting chat \(responseError(error))")
}
dismissAllSheets(animated: true)
showSettings = false
}
} catch let error {
alert = .error(title: "Error deleting database", error: responseError(error))
@@ -625,7 +613,9 @@ struct MigrateFromDevice: View {
}
// Hide settings anyway if chatDbStatus is not ok, probably passphrase needs to be entered
if dismiss || m.chatDbStatus != .ok {
dismissAllSheets(animated: true)
await MainActor.run {
showSettings = false
}
}
}
@@ -777,6 +767,6 @@ private class MigrationChatReceiver {
struct MigrateFromDevice_Previews: PreviewProvider {
static var previews: some View {
MigrateFromDevice(showProgressOnSettings: Binding.constant(false))
MigrateFromDevice(showSettings: Binding.constant(true), showProgressOnSettings: Binding.constant(false))
}
}
@@ -93,6 +93,7 @@ struct MigrateToDevice: View {
@EnvironmentObject var m: ChatModel
@EnvironmentObject var theme: AppTheme
@Environment(\.dismiss) var dismiss: DismissAction
@AppStorage(DEFAULT_DEVELOPER_TOOLS) private var developerTools = false
@Binding var migrationState: MigrationToState?
@State private var useKeychain = storeDBPassphraseGroupDefault.get()
@State private var alert: MigrateToDeviceViewAlert?
@@ -101,7 +102,6 @@ struct MigrateToDevice: View {
// Prevent from hiding the view until migration is finished or app deleted
@State private var backDisabled: Bool = false
@State private var showQRCodeScanner: Bool = true
@State private var pasteboardHasStrings = UIPasteboard.general.hasStrings
var body: some View {
VStack {
@@ -197,8 +197,10 @@ struct MigrateToDevice: View {
}
}
}
Section(header: Text("Or paste archive link").foregroundColor(theme.colors.secondary)) {
pasteLinkView()
if developerTools {
Section(header: Text("Or paste archive link").foregroundColor(theme.colors.secondary)) {
pasteLinkView()
}
}
}
}
@@ -216,7 +218,7 @@ struct MigrateToDevice: View {
} label: {
Text("Tap to paste link")
}
.disabled(!pasteboardHasStrings)
.disabled(!ChatModel.shared.pasteboardHasStrings)
.frame(maxWidth: .infinity, alignment: .center)
}
@@ -485,9 +487,6 @@ struct MigrateToDevice: View {
do {
if !hasChatCtrl() {
chatInitControllerRemovingDatabases()
} else if ChatModel.shared.chatRunning == true {
// cannot delete storage if chat is running
try await apiStopChat()
}
try await apiDeleteStorage()
try? FileManager.default.createDirectory(at: getWallpaperDirectory(), withIntermediateDirectories: true)
@@ -557,22 +556,11 @@ struct MigrateToDevice: View {
do {
try? FileManager.default.removeItem(at: getMigrationTempFilesDirectory())
MigrationToDeviceState.save(nil)
try ObjC.catchException {
appSettings.importIntoApp()
}
do {
try SimpleX.startChat(refreshInvitations: true)
AlertManager.shared.showAlertMsg(title: "Chat migrated!", message: "Finalize migration on another device.")
} catch let error {
AlertManager.shared.showAlert(Alert(title: Text("Error starting chat"), message: Text(responseError(error))))
}
appSettings.importIntoApp()
try SimpleX.startChat(refreshInvitations: true)
AlertManager.shared.showAlertMsg(title: "Chat migrated!", message: "Finalize migration on another device.")
} catch let error {
logger.error("Error importing settings: \(error.localizedDescription)")
AlertManager.shared.showAlert(
Alert(
title: Text("Error migrating settings"),
message: Text ("Some app settings were not migrated.") + Text("\n") + Text(responseError(error)))
)
AlertManager.shared.showAlert(Alert(title: Text("Error starting chat"), message: Text(responseError(error))))
}
hideView()
}
@@ -196,7 +196,7 @@ func chatContactType(chat: Chat) -> ContactType {
case .contactRequest:
return .request
case let .direct(contact):
if contact.activeConn == nil && contact.profile.contactLink != nil && contact.active {
if contact.activeConn == nil && contact.profile.contactLink != nil {
return .card
} else if contact.chatDeleted {
return .chatDeleted
@@ -585,7 +585,6 @@ private struct ConnectView: View {
@Binding var pastedLink: String
@Binding var alert: NewChatViewAlert?
@State private var sheet: PlanAndConnectActionSheet?
@State private var pasteboardHasStrings = UIPasteboard.general.hasStrings
var body: some View {
List {
@@ -622,7 +621,7 @@ private struct ConnectView: View {
} label: {
Text("Tap to paste link")
}
.disabled(!pasteboardHasStrings)
.disabled(!ChatModel.shared.pasteboardHasStrings)
.frame(maxWidth: .infinity, alignment: .center)
} else {
linkTextView(pastedLink)
@@ -59,6 +59,13 @@ struct ConnectDesktopView: View {
var body: some View {
if viaSettings {
viewBody
.modifier(BackButton(label: "Back", disabled: Binding.constant(false)) {
if m.activeRemoteCtrl {
alert = .disconnectDesktop(action: .back)
} else {
dismiss()
}
})
} else {
NavigationView {
viewBody
@@ -36,10 +36,6 @@ struct AdvancedNetworkSettings: View {
@State private var showSettingsAlert: NetworkSettingsAlert?
@State private var onionHosts: OnionHosts = .no
@State private var showSaveDialog = false
@State private var netProxy = networkProxyDefault.get()
@State private var currentNetProxy = networkProxyDefault.get()
@State private var useNetProxy = false
@State private var netProxyAuth = false
var body: some View {
VStack {
@@ -106,76 +102,6 @@ struct AdvancedNetworkSettings: View {
.foregroundColor(theme.colors.secondary)
}
Section {
Toggle("Use SOCKS proxy", isOn: $useNetProxy)
Group {
TextField("IP address", text: $netProxy.host)
TextField(
"Port",
text: Binding(
get: { netProxy.port > 0 ? "\(netProxy.port)" : "" },
set: { s in
netProxy.port = if let port = Int(s), port > 0 {
port
} else {
0
}
}
)
)
Toggle("Proxy requires password", isOn: $netProxyAuth)
if netProxyAuth {
TextField("Username", text: $netProxy.username)
PassphraseField(
key: $netProxy.password,
placeholder: "Password",
valid: NetworkProxy.validCredential(netProxy.password)
)
}
}
.if(!useNetProxy) { $0.foregroundColor(theme.colors.secondary) }
.disabled(!useNetProxy)
} header: {
HStack {
Text("SOCKS proxy").foregroundColor(theme.colors.secondary)
if useNetProxy && !netProxy.valid {
Spacer()
Image(systemName: "exclamationmark.circle.fill").foregroundColor(.red)
}
}
} footer: {
if netProxyAuth {
Text("Your credentials may be sent unencrypted.")
.foregroundColor(theme.colors.secondary)
} else {
Text("Do not use credentials with proxy.")
.foregroundColor(theme.colors.secondary)
}
}
.onChange(of: useNetProxy) { useNetProxy in
netCfg.socksProxy = useNetProxy && currentNetProxy.valid
? currentNetProxy.toProxyString()
: nil
netProxy = currentNetProxy
netProxyAuth = netProxy.username != "" || netProxy.password != ""
}
.onChange(of: netProxyAuth) { netProxyAuth in
if netProxyAuth {
netProxy.auth = currentNetProxy.auth
netProxy.username = currentNetProxy.username
netProxy.password = currentNetProxy.password
} else {
netProxy.auth = .username
netProxy.username = ""
netProxy.password = ""
}
}
.onChange(of: netProxy) { netProxy in
netCfg.socksProxy = useNetProxy && netProxy.valid
? netProxy.toProxyString()
: nil
}
Section {
Picker("Use .onion hosts", selection: $onionHosts) {
ForEach(OnionHosts.values, id: \.self) { Text($0.text) }
@@ -230,19 +156,19 @@ struct AdvancedNetworkSettings: View {
Section {
Button("Reset to defaults") {
updateNetCfgView(NetCfg.defaults, NetworkProxy.def)
updateNetCfgView(NetCfg.defaults)
}
.disabled(netCfg == NetCfg.defaults)
Button("Set timeouts for proxy/VPN") {
updateNetCfgView(netCfg.withProxyTimeouts, netProxy)
updateNetCfgView(netCfg.withProxyTimeouts)
}
.disabled(netCfg.hasProxyTimeouts)
Button("Save and reconnect") {
showSettingsAlert = .update
}
.disabled(netCfg == currentNetCfg || (useNetProxy && !netProxy.valid))
.disabled(netCfg == currentNetCfg)
}
}
}
@@ -256,8 +182,7 @@ struct AdvancedNetworkSettings: View {
if cfgLoaded { return }
cfgLoaded = true
currentNetCfg = getNetCfg()
currentNetProxy = networkProxyDefault.get()
updateNetCfgView(currentNetCfg, currentNetProxy)
updateNetCfgView(currentNetCfg)
}
.alert(item: $showSettingsAlert) { a in
switch a {
@@ -281,7 +206,7 @@ struct AdvancedNetworkSettings: View {
if netCfg == currentNetCfg {
dismiss()
cfgLoaded = false
} else if !useNetProxy || netProxy.valid {
} else {
showSaveDialog = true
}
})
@@ -296,26 +221,18 @@ struct AdvancedNetworkSettings: View {
}
}
private func updateNetCfgView(_ cfg: NetCfg, _ proxy: NetworkProxy) {
private func updateNetCfgView(_ cfg: NetCfg) {
netCfg = cfg
netProxy = proxy
onionHosts = OnionHosts(netCfg: netCfg)
enableKeepAlive = netCfg.enableKeepAlive
keepAliveOpts = netCfg.tcpKeepAlive ?? KeepAliveOpts.defaults
useNetProxy = netCfg.socksProxy != nil
netProxyAuth = switch netProxy.auth {
case .username: netProxy.username != "" || netProxy.password != ""
case .isolate: false
}
}
private func saveNetCfg() -> Bool {
do {
try setNetworkConfig(netCfg)
currentNetCfg = netCfg
setNetCfg(netCfg, networkProxy: useNetProxy ? netProxy : nil)
currentNetProxy = netProxy
networkProxyDefault.set(netProxy)
setNetCfg(netCfg)
return true
} catch let error {
let err = responseError(error)
@@ -19,15 +19,9 @@ extension AppSettings {
val.hostMode = .publicHost
val.requiredHostMode = true
}
if val.socksProxy != nil {
val.socksProxy = networkProxy?.toProxyString()
setNetCfg(val, networkProxy: networkProxy)
} else {
val.socksProxy = nil
setNetCfg(val, networkProxy: nil)
}
val.socksProxy = nil
setNetCfg(val)
}
if let val = networkProxy { networkProxyDefault.set(val) }
if let val = privacyEncryptLocalFiles { privacyEncryptLocalFilesGroupDefault.set(val) }
if let val = privacyAskToApproveRelays { privacyAskToApproveRelaysGroupDefault.set(val) }
if let val = privacyAcceptImages {
@@ -58,10 +52,10 @@ extension AppSettings {
profileImageCornerRadiusGroupDefault.set(val)
def.setValue(val, forKey: DEFAULT_PROFILE_IMAGE_CORNER_RADIUS)
}
if let val = uiColorScheme { currentThemeDefault.set(val) }
if let val = uiDarkColorScheme { systemDarkThemeDefault.set(val) }
if let val = uiCurrentThemeIds { currentThemeIdsDefault.set(val) }
if let val = uiThemes { themeOverridesDefault.set(val.skipDuplicates()) }
if let val = uiColorScheme { def.setValue(val, forKey: DEFAULT_CURRENT_THEME) }
if let val = uiDarkColorScheme { def.setValue(val, forKey: DEFAULT_SYSTEM_DARK_THEME) }
if let val = uiCurrentThemeIds { def.setValue(val, forKey: DEFAULT_CURRENT_THEME_IDS) }
if let val = uiThemes { def.setValue(val.skipDuplicates(), forKey: DEFAULT_THEME_OVERRIDES) }
if let val = oneHandUI { groupDefaults.setValue(val, forKey: GROUP_DEFAULT_ONE_HAND_UI) }
}
@@ -69,7 +63,6 @@ extension AppSettings {
let def = UserDefaults.standard
var c = AppSettings.defaults
c.networkConfig = getNetCfg()
c.networkProxy = networkProxyDefault.get()
c.privacyEncryptLocalFiles = privacyEncryptLocalFilesGroupDefault.get()
c.privacyAskToApproveRelays = privacyAskToApproveRelaysGroupDefault.get()
c.privacyAcceptImages = privacyAcceptImagesGroupDefault.get()
@@ -32,17 +32,6 @@ struct PreferencesView: View {
.disabled(currentPreferences == preferences)
}
}
.onDisappear {
if currentPreferences != preferences {
showAlert(
title: NSLocalizedString("Your chat preferences", comment: "alert title"),
message: NSLocalizedString("Chat preferences were changed.", comment: "alert message"),
buttonTitle: NSLocalizedString("Save", comment: "alert button"),
buttonAction: savePreferences,
cancelButton: true
)
}
}
}
private func featureSection(_ feature: ChatFeature, _ allowFeature: Binding<FeatureAllowed>) -> some View {
@@ -75,8 +75,6 @@ let DEFAULT_SYSTEM_DARK_THEME = "systemDarkTheme"
let DEFAULT_CURRENT_THEME_IDS = "currentThemeIds"
let DEFAULT_THEME_OVERRIDES = "themeOverrides"
let DEFAULT_NETWORK_PROXY = "networkProxy"
let ANDROID_DEFAULT_CALL_ON_LOCK_SCREEN = "androidCallOnLockScreen"
let defaultChatItemRoundness: Double = 0.75
@@ -253,7 +251,6 @@ public class CodableDefault<T: Codable> {
}
}
let networkProxyDefault: CodableDefault<NetworkProxy> = CodableDefault(defaults: UserDefaults.standard, forKey: DEFAULT_NETWORK_PROXY, withDefault: NetworkProxy.def)
struct SettingsView: View {
@Environment(\.colorScheme) var colorScheme
@@ -265,9 +262,7 @@ struct SettingsView: View {
var body: some View {
ZStack {
NavigationView {
settingsView()
}
settingsView()
if showProgress {
progressView()
}
@@ -279,7 +274,63 @@ struct SettingsView: View {
@ViewBuilder func settingsView() -> some View {
let user = chatModel.currentUser
NavigationView {
List {
Section(header: Text("You").foregroundColor(theme.colors.secondary)) {
if let user = user {
NavigationLink {
UserProfile()
.navigationTitle("Your current profile")
.modifier(ThemedBackground())
} label: {
ProfilePreview(profileOf: user)
.padding(.leading, -8)
}
}
NavigationLink {
UserProfilesView(showSettings: $showSettings)
} label: {
settingsRow("person.crop.rectangle.stack", color: theme.colors.secondary) { Text("Your chat profiles") }
}
if let user = user {
NavigationLink {
UserAddressView(shareViaProfile: user.addressShared)
.navigationTitle("SimpleX address")
.modifier(ThemedBackground(grouped: true))
.navigationBarTitleDisplayMode(.large)
} label: {
settingsRow("qrcode", color: theme.colors.secondary) { Text("Your SimpleX address") }
}
NavigationLink {
PreferencesView(profile: user.profile, preferences: user.fullPreferences, currentPreferences: user.fullPreferences)
.navigationTitle("Your preferences")
.modifier(ThemedBackground(grouped: true))
} label: {
settingsRow("switch.2", color: theme.colors.secondary) { Text("Chat preferences") }
}
}
NavigationLink {
ConnectDesktopView(viaSettings: true)
} label: {
settingsRow("desktopcomputer", color: theme.colors.secondary) { Text("Use from desktop") }
}
NavigationLink {
MigrateFromDevice(showSettings: $showSettings, showProgressOnSettings: $showProgress)
.navigationTitle("Migrate device")
.modifier(ThemedBackground(grouped: true))
.navigationBarTitleDisplayMode(.large)
} label: {
settingsRow("tray.and.arrow.up", color: theme.colors.secondary) { Text("Migrate to another device") }
}
}
.disabled(chatModel.chatRunning != true)
Section(header: Text("Settings").foregroundColor(theme.colors.secondary)) {
NavigationLink {
NotificationsView()
@@ -330,20 +381,10 @@ struct SettingsView: View {
}
.disabled(chatModel.chatRunning != true)
}
chatDatabaseRow()
}
Section(header: Text("Chat database").foregroundColor(theme.colors.secondary)) {
chatDatabaseRow()
NavigationLink {
MigrateFromDevice(showProgressOnSettings: $showProgress)
.navigationTitle("Migrate device")
.modifier(ThemedBackground(grouped: true))
.navigationBarTitleDisplayMode(.large)
} label: {
settingsRow("tray.and.arrow.up", color: theme.colors.secondary) { Text("Migrate to another device") }
}
}
Section(header: Text("Help").foregroundColor(theme.colors.secondary)) {
if let user = user {
NavigationLink {
@@ -421,10 +462,11 @@ struct SettingsView: View {
}
.navigationTitle("Your settings")
.modifier(ThemedBackground(grouped: true))
.onDisappear {
chatModel.showingTerminal = false
chatModel.terminalItems = []
}
}
.onDisappear {
chatModel.showingTerminal = false
chatModel.terminalItems = []
}
}
private func chatDatabaseRow() -> some View {
@@ -507,17 +549,16 @@ struct ProfilePreview: View {
HStack {
ProfileImage(imageStr: profileOf.image, size: 44, color: color)
.padding(.trailing, 6)
profileName().lineLimit(1)
}
}
private func profileName() -> Text {
var t = Text(profileOf.displayName).fontWeight(.semibold).font(.title2)
if profileOf.fullName != "" && profileOf.fullName != profileOf.displayName {
t = t + Text(" (" + profileOf.fullName + ")")
// .font(.callout)
.padding(.vertical, 6)
VStack(alignment: .leading) {
Text(profileOf.displayName)
.fontWeight(.bold)
.font(.title2)
if profileOf.fullName != "" && profileOf.fullName != profileOf.displayName {
Text(profileOf.fullName)
}
}
return t
}
}
}
@@ -14,6 +14,7 @@ struct UserAddressView: View {
@Environment(\.dismiss) var dismiss: DismissAction
@EnvironmentObject private var chatModel: ChatModel
@EnvironmentObject var theme: AppTheme
@State var viaCreateLinkView = false
@State var shareViaProfile = false
@State private var aas = AutoAcceptState()
@State private var savedAAS = AutoAcceptState()
@@ -21,6 +22,7 @@ struct UserAddressView: View {
@State private var showMailView = false
@State private var mailViewResult: Result<MFMailComposeResult, Error>? = nil
@State private var alert: UserAddressAlert?
@State private var showSaveDialogue = false
@State private var progressIndicator = false
@FocusState private var keyboardVisible: Bool
@@ -42,19 +44,26 @@ struct UserAddressView: View {
var body: some View {
ZStack {
userAddressScrollView()
.onDisappear {
if savedAAS != aas {
showAlert(
title: NSLocalizedString("Auto-accept settings", comment: "alert title"),
message: NSLocalizedString("Settings were changed.", comment: "alert message"),
buttonTitle: NSLocalizedString("Save", comment: "alert button"),
buttonAction: saveAAS,
cancelButton: true
)
if viaCreateLinkView {
userAddressScrollView()
} else {
userAddressScrollView()
.modifier(BackButton(disabled: Binding.constant(false)) {
if savedAAS == aas {
dismiss()
} else {
keyboardVisible = false
showSaveDialogue = true
}
})
.confirmationDialog("Save settings?", isPresented: $showSaveDialogue) {
Button("Save auto-accept settings") {
saveAAS()
dismiss()
}
Button("Exit without saving") { dismiss() }
}
}
}
if progressIndicator {
ZStack {
if chatModel.userAddress != nil {
@@ -333,7 +342,7 @@ struct UserAddressView: View {
}
}
}
private struct AutoAcceptState: Equatable {
var enable = false
var incognito = false
@@ -438,8 +447,6 @@ struct UserAddressView_Previews: PreviewProvider {
static var previews: some View {
let chatModel = ChatModel()
chatModel.userAddress = UserContactLink(connReqContact: "https://simplex.chat/contact#/?v=1&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FK1rslx-m5bpXVIdMZg9NLUZ_8JBm8xTt%23MCowBQYDK2VuAyEALDeVe-sG8mRY22LsXlPgiwTNs9dbiLrNuA7f3ZMAJ2w%3D")
return Group {
UserAddressView()
.environmentObject(chatModel)
File diff suppressed because one or more lines are too long
@@ -9,6 +9,7 @@ import SimpleXChat
struct UserProfilesView: View {
@EnvironmentObject private var m: ChatModel
@EnvironmentObject private var theme: AppTheme
@Binding var showSettings: Bool
@Environment(\.editMode) private var editMode
@AppStorage(DEFAULT_SHOW_HIDDEN_PROFILES_NOTICE) private var showHiddenProfilesNotice = true
@AppStorage(DEFAULT_SHOW_MUTE_PROFILE_ALERT) private var showMuteProfileAlert = true
@@ -95,7 +96,8 @@ struct UserProfilesView: View {
} label: {
Label("Add profile", systemImage: "plus")
}
.frame(height: 38)
.frame(height: 44)
.padding(.vertical, 4)
}
} footer: {
Text("Tap to activate profile.")
@@ -283,7 +285,7 @@ struct UserProfilesView: View {
await MainActor.run {
onboardingStageDefault.set(.step1_SimpleXInfo)
m.onboardingStage = .step1_SimpleXInfo
dismissAllSheets()
showSettings = false
}
}
} else {
@@ -306,14 +308,14 @@ struct UserProfilesView: View {
Task {
do {
try await changeActiveUserAsync_(user.userId, viewPwd: userViewPassword(user))
dismissAllSheets()
} catch {
await MainActor.run { alert = .activateUserError(error: responseError(error)) }
}
}
} label: {
HStack {
ProfileImage(imageStr: user.image, size: 38)
ProfileImage(imageStr: user.image, size: 44)
.padding(.vertical, 4)
.padding(.trailing, 12)
Text(user.chatViewName)
Spacer()
@@ -413,6 +415,6 @@ public func correctPassword(_ user: User, _ pwd: String) -> Bool {
struct UserProfilesView_Previews: PreviewProvider {
static var previews: some View {
UserProfilesView()
UserProfilesView(showSettings: Binding.constant(true))
}
}
@@ -1007,10 +1007,6 @@
<target>Автоматично приемане на изображения</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Auto-accept settings" xml:space="preserve">
<source>Auto-accept settings</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Back" xml:space="preserve">
<source>Back</source>
<target>Назад</target>
@@ -1175,7 +1171,7 @@
<trans-unit id="Cancel" xml:space="preserve">
<source>Cancel</source>
<target>Отказ</target>
<note>alert button</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Cancel migration" xml:space="preserve">
<source>Cancel migration</source>
@@ -1318,10 +1314,6 @@
<target>Чат настройки</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Chat preferences were changed." xml:space="preserve">
<source>Chat preferences were changed.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Chat theme" xml:space="preserve">
<source>Chat theme</source>
<note>No comment provided by engineer.</note>
@@ -2797,10 +2789,6 @@ This is your own one-time link!</source>
<target>Грешка при зареждане на %@ сървъри</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error migrating settings" xml:space="preserve">
<source>Error migrating settings</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error opening chat" xml:space="preserve">
<source>Error opening chat</source>
<target>Грешка при отваряне на чата</target>
@@ -3222,6 +3210,11 @@ Error: %2$@</source>
<target>Пълно име (незадължително)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Full name:" xml:space="preserve">
<source>Full name:</source>
<target>Пълно име:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Fully decentralized visible only to members." xml:space="preserve">
<source>Fully decentralized visible only to members.</source>
<target>Напълно децентрализирана – видима е само за членовете.</target>
@@ -4914,6 +4907,16 @@ Error: %@</source>
<target>Профилни изображения</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile name" xml:space="preserve">
<source>Profile name</source>
<target>Име на профила</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile name:" xml:space="preserve">
<source>Profile name:</source>
<target>Име на профила:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile password" xml:space="preserve">
<source>Profile password</source>
<target>Профилна парола</target>
@@ -5221,10 +5224,6 @@ Enable in *Network &amp; servers* settings.</source>
<target>Премахване</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Remove archive?" xml:space="preserve">
<source>Remove archive?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Remove image" xml:space="preserve">
<source>Remove image</source>
<note>No comment provided by engineer.</note>
@@ -5410,13 +5409,12 @@ Enable in *Network &amp; servers* settings.</source>
<trans-unit id="Save" xml:space="preserve">
<source>Save</source>
<target>Запази</target>
<note>alert button
chat item action</note>
<note>chat item action</note>
</trans-unit>
<trans-unit id="Save (and notify contacts)" xml:space="preserve">
<source>Save (and notify contacts)</source>
<target>Запази (и уведоми контактите)</target>
<note>alert button</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save and notify contact" xml:space="preserve">
<source>Save and notify contact</source>
@@ -5442,6 +5440,11 @@ Enable in *Network &amp; servers* settings.</source>
<target>Запази архив</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save auto-accept settings" xml:space="preserve">
<source>Save auto-accept settings</source>
<target>Запази настройките за автоматично приемане</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save group profile" xml:space="preserve">
<source>Save group profile</source>
<target>Запази профила на групата</target>
@@ -5477,15 +5480,16 @@ Enable in *Network &amp; servers* settings.</source>
<target>Запази сървърите?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save settings?" xml:space="preserve">
<source>Save settings?</source>
<target>Запази настройките?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save welcome message?" xml:space="preserve">
<source>Save welcome message?</source>
<target>Запази съобщението при посрещане?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save your profile?" xml:space="preserve">
<source>Save your profile?</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Saved" xml:space="preserve">
<source>Saved</source>
<target>Запазено</target>
@@ -5901,10 +5905,6 @@ Enable in *Network &amp; servers* settings.</source>
<target>Настройки</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Settings were changed." xml:space="preserve">
<source>Settings were changed.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Shape profile images" xml:space="preserve">
<source>Shape profile images</source>
<target>Променете формата на профилните изображения</target>
@@ -6101,10 +6101,6 @@ Enable in *Network &amp; servers* settings.</source>
<source>Soft</source>
<note>blur media</note>
</trans-unit>
<trans-unit id="Some app settings were not migrated." xml:space="preserve">
<source>Some app settings were not migrated.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Some file(s) were not exported:" xml:space="preserve">
<source>Some file(s) were not exported:</source>
<note>No comment provided by engineer.</note>
@@ -6463,10 +6459,6 @@ It can happen because of some bug or when the connection is compromised.</source
<target>Текстът, който поставихте, не е SimpleX линк за връзка.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The uploaded database archive will be permanently removed from the servers." xml:space="preserve">
<source>The uploaded database archive will be permanently removed from the servers.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Themes" xml:space="preserve">
<source>Themes</source>
<note>No comment provided by engineer.</note>
@@ -7519,10 +7511,6 @@ Repeat connection request?</source>
<target>Вашата чат база данни не е криптирана - задайте парола, за да я криптирате.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your chat preferences" xml:space="preserve">
<source>Your chat preferences</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Your chat profiles" xml:space="preserve">
<source>Your chat profiles</source>
<target>Вашите чат профили</target>
@@ -7577,15 +7565,13 @@ Repeat connection request?</source>
<target>Вашият профил **%@** ще бъде споделен.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source>
<target>Вашият профил се съхранява на вашето устройство и се споделя само с вашите контакти. SimpleX сървърите не могат да видят вашия профил.</target>
<trans-unit id="Your profile is stored on your device and shared only with your contacts.&#10;SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts.
SimpleX servers cannot see your profile.</source>
<target>Вашият профил се съхранява на вашето устройство и се споделя само с вашите контакти.
SimpleX сървърите не могат да видят вашия профил.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile was changed. If you save it, the updated profile will be sent to all your contacts." xml:space="preserve">
<source>Your profile was changed. If you save it, the updated profile will be sent to all your contacts.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>Вашият профил, контакти и доставени съобщения се съхраняват на вашето устройство.</target>
@@ -977,10 +977,6 @@
<target>Automaticky přijímat obrázky</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Auto-accept settings" xml:space="preserve">
<source>Auto-accept settings</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Back" xml:space="preserve">
<source>Back</source>
<target>Zpět</target>
@@ -1135,7 +1131,7 @@
<trans-unit id="Cancel" xml:space="preserve">
<source>Cancel</source>
<target>Zrušit</target>
<note>alert button</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Cancel migration" xml:space="preserve">
<source>Cancel migration</source>
@@ -1274,10 +1270,6 @@
<target>Předvolby chatu</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Chat preferences were changed." xml:space="preserve">
<source>Chat preferences were changed.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Chat theme" xml:space="preserve">
<source>Chat theme</source>
<note>No comment provided by engineer.</note>
@@ -2702,10 +2694,6 @@ This is your own one-time link!</source>
<target>Chyba načítání %@ serverů</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error migrating settings" xml:space="preserve">
<source>Error migrating settings</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error opening chat" xml:space="preserve">
<source>Error opening chat</source>
<note>No comment provided by engineer.</note>
@@ -3111,6 +3099,11 @@ Error: %2$@</source>
<target>Celé jméno (volitelně)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Full name:" xml:space="preserve">
<source>Full name:</source>
<target>Celé jméno:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Fully decentralized visible only to members." xml:space="preserve">
<source>Fully decentralized visible only to members.</source>
<note>No comment provided by engineer.</note>
@@ -4736,6 +4729,14 @@ Error: %@</source>
<source>Profile images</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile name" xml:space="preserve">
<source>Profile name</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile name:" xml:space="preserve">
<source>Profile name:</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile password" xml:space="preserve">
<source>Profile password</source>
<target>Heslo profilu</target>
@@ -5037,10 +5038,6 @@ Enable in *Network &amp; servers* settings.</source>
<target>Odstranit</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Remove archive?" xml:space="preserve">
<source>Remove archive?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Remove image" xml:space="preserve">
<source>Remove image</source>
<note>No comment provided by engineer.</note>
@@ -5219,13 +5216,12 @@ Enable in *Network &amp; servers* settings.</source>
<trans-unit id="Save" xml:space="preserve">
<source>Save</source>
<target>Uložit</target>
<note>alert button
chat item action</note>
<note>chat item action</note>
</trans-unit>
<trans-unit id="Save (and notify contacts)" xml:space="preserve">
<source>Save (and notify contacts)</source>
<target>Uložit (a informovat kontakty)</target>
<note>alert button</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save and notify contact" xml:space="preserve">
<source>Save and notify contact</source>
@@ -5251,6 +5247,11 @@ Enable in *Network &amp; servers* settings.</source>
<target>Uložit archiv</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save auto-accept settings" xml:space="preserve">
<source>Save auto-accept settings</source>
<target>Uložit nastavení automatického přijímání</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save group profile" xml:space="preserve">
<source>Save group profile</source>
<target>Uložení profilu skupiny</target>
@@ -5286,15 +5287,16 @@ Enable in *Network &amp; servers* settings.</source>
<target>Uložit servery?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save settings?" xml:space="preserve">
<source>Save settings?</source>
<target>Uložit nastavení?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save welcome message?" xml:space="preserve">
<source>Save welcome message?</source>
<target>Uložit uvítací zprávu?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save your profile?" xml:space="preserve">
<source>Save your profile?</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Saved" xml:space="preserve">
<source>Saved</source>
<note>No comment provided by engineer.</note>
@@ -5701,10 +5703,6 @@ Enable in *Network &amp; servers* settings.</source>
<target>Nastavení</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Settings were changed." xml:space="preserve">
<source>Settings were changed.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Shape profile images" xml:space="preserve">
<source>Shape profile images</source>
<note>No comment provided by engineer.</note>
@@ -5896,10 +5894,6 @@ Enable in *Network &amp; servers* settings.</source>
<source>Soft</source>
<note>blur media</note>
</trans-unit>
<trans-unit id="Some app settings were not migrated." xml:space="preserve">
<source>Some app settings were not migrated.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Some file(s) were not exported:" xml:space="preserve">
<source>Some file(s) were not exported:</source>
<note>No comment provided by engineer.</note>
@@ -6249,10 +6243,6 @@ Může se to stát kvůli nějaké chybě, nebo pokud je spojení kompromitován
<source>The text you pasted is not a SimpleX link.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The uploaded database archive will be permanently removed from the servers." xml:space="preserve">
<source>The uploaded database archive will be permanently removed from the servers.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Themes" xml:space="preserve">
<source>Themes</source>
<note>No comment provided by engineer.</note>
@@ -7250,10 +7240,6 @@ Repeat connection request?</source>
<target>Vaše chat databáze není šifrována nastavte přístupovou frázi pro její šifrování.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your chat preferences" xml:space="preserve">
<source>Your chat preferences</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Your chat profiles" xml:space="preserve">
<source>Your chat profiles</source>
<target>Vaše chat profily</target>
@@ -7307,15 +7293,13 @@ Repeat connection request?</source>
<target>Váš profil **%@** bude sdílen.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source>
<target>Váš profil je uložen ve vašem zařízení a sdílen pouze s vašimi kontakty. Servery SimpleX nevidí váš profil.</target>
<trans-unit id="Your profile is stored on your device and shared only with your contacts.&#10;SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts.
SimpleX servers cannot see your profile.</source>
<target>Váš profil je uložen ve vašem zařízení a sdílen pouze s vašimi kontakty.
Servery SimpleX nevidí váš profil.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile was changed. If you save it, the updated profile will be sent to all your contacts." xml:space="preserve">
<source>Your profile was changed. If you save it, the updated profile will be sent to all your contacts.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>Váš profil, kontakty a doručené zprávy jsou uloženy ve vašem zařízení.</target>
@@ -1024,10 +1024,6 @@
<target>Bilder automatisch akzeptieren</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Auto-accept settings" xml:space="preserve">
<source>Auto-accept settings</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Back" xml:space="preserve">
<source>Back</source>
<target>Zurück</target>
@@ -1201,7 +1197,7 @@
<trans-unit id="Cancel" xml:space="preserve">
<source>Cancel</source>
<target>Abbrechen</target>
<note>alert button</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Cancel migration" xml:space="preserve">
<source>Cancel migration</source>
@@ -1349,10 +1345,6 @@
<target>Chat-Präferenzen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Chat preferences were changed." xml:space="preserve">
<source>Chat preferences were changed.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Chat theme" xml:space="preserve">
<source>Chat theme</source>
<target>Chat-Design</target>
@@ -1405,22 +1397,22 @@
</trans-unit>
<trans-unit id="Clear" xml:space="preserve">
<source>Clear</source>
<target>Entfernen</target>
<target>Löschen</target>
<note>swipe action</note>
</trans-unit>
<trans-unit id="Clear conversation" xml:space="preserve">
<source>Clear conversation</source>
<target>Chat-Inhalte entfernen</target>
<target>Chatinhalte löschen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Clear conversation?" xml:space="preserve">
<source>Clear conversation?</source>
<target>Chat-Inhalte entfernen?</target>
<target>Unterhaltung löschen?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Clear private notes?" xml:space="preserve">
<source>Clear private notes?</source>
<target>Private Notizen entfernen?</target>
<target>Private Notizen löschen?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Clear verification" xml:space="preserve">
@@ -1734,7 +1726,7 @@ Das ist Ihr eigener Einmal-Link!</target>
</trans-unit>
<trans-unit id="Conversation deleted!" xml:space="preserve">
<source>Conversation deleted!</source>
<target>Chat-Inhalte entfernt!</target>
<target>Unterhaltung gelöscht!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Copy" xml:space="preserve">
@@ -2878,10 +2870,6 @@ Das ist Ihr eigener Einmal-Link!</target>
<target>Fehler beim Laden von %@ Servern</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error migrating settings" xml:space="preserve">
<source>Error migrating settings</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error opening chat" xml:space="preserve">
<source>Error opening chat</source>
<target>Fehler beim Öffnen des Chats</target>
@@ -3321,6 +3309,11 @@ Fehler: %2$@</target>
<target>Vollständiger Name (optional)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Full name:" xml:space="preserve">
<source>Full name:</source>
<target>Vollständiger Name:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Fully decentralized visible only to members." xml:space="preserve">
<source>Fully decentralized visible only to members.</source>
<target>Vollständig dezentralisiert nur für Mitglieder sichtbar.</target>
@@ -3478,7 +3471,7 @@ Fehler: %2$@</target>
</trans-unit>
<trans-unit id="Group will be deleted for you - this cannot be undone!" xml:space="preserve">
<source>Group will be deleted for you - this cannot be undone!</source>
<target>Die Gruppe wird nur bei Ihnen gelöscht. Dies kann nicht rückgängig gemacht werden!</target>
<target>Die Gruppe wird für Sie gelöscht. Dies kann nicht rückgängig gemacht werden!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Help" xml:space="preserve">
@@ -3933,7 +3926,7 @@ Das ist Ihr Link für die Gruppe %@!</target>
</trans-unit>
<trans-unit id="Keep conversation" xml:space="preserve">
<source>Keep conversation</source>
<target>Chat-Inhalte beibehalten</target>
<target>Unterhaltung behalten</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Keep the app open to use it from desktop" xml:space="preserve">
@@ -4635,7 +4628,7 @@ Dies erfordert die Aktivierung eines VPNs.</target>
</trans-unit>
<trans-unit id="Only delete conversation" xml:space="preserve">
<source>Only delete conversation</source>
<target>Nur die Chat-Inhalte löschen</target>
<target>Nur die Unterhaltung löschen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Only group owners can change group preferences." xml:space="preserve">
@@ -5052,6 +5045,16 @@ Fehler: %@</target>
<target>Profil-Bilder</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile name" xml:space="preserve">
<source>Profile name</source>
<target>Profilname</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile name:" xml:space="preserve">
<source>Profile name:</source>
<target>Profilname:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile password" xml:space="preserve">
<source>Profile password</source>
<target>Passwort für Profil</target>
@@ -5176,7 +5179,7 @@ Aktivieren Sie es in den *Netzwerk &amp; Server* Einstellungen.</target>
</trans-unit>
<trans-unit id="Reachable chat toolbar" xml:space="preserve">
<source>Reachable chat toolbar</source>
<target>Chat-Symbolleiste unten</target>
<target>Erreichbare Chat-Symbolleiste</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="React…" xml:space="preserve">
@@ -5375,10 +5378,6 @@ Aktivieren Sie es in den *Netzwerk &amp; Server* Einstellungen.</target>
<target>Entfernen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Remove archive?" xml:space="preserve">
<source>Remove archive?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Remove image" xml:space="preserve">
<source>Remove image</source>
<target>Bild entfernen</target>
@@ -5572,13 +5571,12 @@ Aktivieren Sie es in den *Netzwerk &amp; Server* Einstellungen.</target>
<trans-unit id="Save" xml:space="preserve">
<source>Save</source>
<target>Speichern</target>
<note>alert button
chat item action</note>
<note>chat item action</note>
</trans-unit>
<trans-unit id="Save (and notify contacts)" xml:space="preserve">
<source>Save (and notify contacts)</source>
<target>Speichern (und Kontakte benachrichtigen)</target>
<note>alert button</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save and notify contact" xml:space="preserve">
<source>Save and notify contact</source>
@@ -5605,6 +5603,11 @@ Aktivieren Sie es in den *Netzwerk &amp; Server* Einstellungen.</target>
<target>Archiv speichern</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save auto-accept settings" xml:space="preserve">
<source>Save auto-accept settings</source>
<target>Einstellungen von "Automatisch akzeptieren" speichern</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save group profile" xml:space="preserve">
<source>Save group profile</source>
<target>Gruppenprofil speichern</target>
@@ -5640,15 +5643,16 @@ Aktivieren Sie es in den *Netzwerk &amp; Server* Einstellungen.</target>
<target>Alle Server speichern?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save settings?" xml:space="preserve">
<source>Save settings?</source>
<target>Einstellungen speichern?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save welcome message?" xml:space="preserve">
<source>Save welcome message?</source>
<target>Begrüßungsmeldung speichern?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save your profile?" xml:space="preserve">
<source>Save your profile?</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Saved" xml:space="preserve">
<source>Saved</source>
<target>Abgespeichert</target>
@@ -5716,7 +5720,7 @@ Aktivieren Sie es in den *Netzwerk &amp; Server* Einstellungen.</target>
</trans-unit>
<trans-unit id="Search or paste SimpleX link" xml:space="preserve">
<source>Search or paste SimpleX link</source>
<target>Suchen oder SimpleX-Link einfügen</target>
<target>Suchen oder fügen Sie den SimpleX-Link ein</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Secondary" xml:space="preserve">
@@ -6088,10 +6092,6 @@ Aktivieren Sie es in den *Netzwerk &amp; Server* Einstellungen.</target>
<target>Einstellungen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Settings were changed." xml:space="preserve">
<source>Settings were changed.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Shape profile images" xml:space="preserve">
<source>Shape profile images</source>
<target>Form der Profil-Bilder</target>
@@ -6296,10 +6296,6 @@ Aktivieren Sie es in den *Netzwerk &amp; Server* Einstellungen.</target>
<target>Weich</target>
<note>blur media</note>
</trans-unit>
<trans-unit id="Some app settings were not migrated." xml:space="preserve">
<source>Some app settings were not migrated.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Some file(s) were not exported:" xml:space="preserve">
<source>Some file(s) were not exported:</source>
<target>Einzelne Datei(en) wurde(n) nicht exportiert:</target>
@@ -6628,7 +6624,7 @@ Dies kann passieren, wenn es einen Fehler gegeben hat oder die Verbindung kompro
</trans-unit>
<trans-unit id="The messages will be deleted for all members." xml:space="preserve">
<source>The messages will be deleted for all members.</source>
<target>Die Nachrichten werden für alle Gruppenmitglieder gelöscht.</target>
<target>Die Nachrichten werden für alle Mitglieder gelöscht werden.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The messages will be marked as moderated for all members." xml:space="preserve">
@@ -6671,10 +6667,6 @@ Dies kann passieren, wenn es einen Fehler gegeben hat oder die Verbindung kompro
<target>Der von Ihnen eingefügte Text ist kein SimpleX-Link.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The uploaded database archive will be permanently removed from the servers." xml:space="preserve">
<source>The uploaded database archive will be permanently removed from the servers.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Themes" xml:space="preserve">
<source>Themes</source>
<target>Design</target>
@@ -7131,7 +7123,7 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
</trans-unit>
<trans-unit id="Use the app with one hand." xml:space="preserve">
<source>Use the app with one hand.</source>
<target>Die App mit einer Hand bedienen.</target>
<target>Die App mit einer Hand nutzen.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="User profile" xml:space="preserve">
@@ -7563,7 +7555,7 @@ Verbindungsanfrage wiederholen?</target>
</trans-unit>
<trans-unit id="You can still view conversation with %@ in the list of chats." xml:space="preserve">
<source>You can still view conversation with %@ in the list of chats.</source>
<target>Sie können in der Chat-Liste weiterhin die Unterhaltung mit %@ einsehen.</target>
<target>Sie können in der Chatliste weiterhin die Unterhaltung mit %@ einsehen.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can turn on SimpleX Lock via Settings." xml:space="preserve">
@@ -7758,10 +7750,6 @@ Verbindungsanfrage wiederholen?</target>
<target>Ihre Chat-Datenbank ist nicht verschlüsselt. Bitte legen Sie ein Passwort fest, um sie zu schützen.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your chat preferences" xml:space="preserve">
<source>Your chat preferences</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Your chat profiles" xml:space="preserve">
<source>Your chat profiles</source>
<target>Ihre Chat-Profile</target>
@@ -7816,15 +7804,13 @@ Verbindungsanfrage wiederholen?</target>
<target>Ihr Profil **%@** wird geteilt.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source>
<target>Ihr Profil wird auf Ihrem Gerät gespeichert und nur mit Ihren Kontakten geteilt. SimpleX-Server können Ihr Profil nicht einsehen.</target>
<trans-unit id="Your profile is stored on your device and shared only with your contacts.&#10;SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts.
SimpleX servers cannot see your profile.</source>
<target>Ihr Profil wird auf Ihrem Gerät gespeichert und nur mit Ihren Kontakten geteilt.
SimpleX-Server können Ihr Profil nicht einsehen.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile was changed. If you save it, the updated profile will be sent to all your contacts." xml:space="preserve">
<source>Your profile was changed. If you save it, the updated profile will be sent to all your contacts.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>Ihr Profil, Ihre Kontakte und zugestellten Nachrichten werden auf Ihrem Gerät gespeichert.</target>
@@ -1025,11 +1025,6 @@
<target>Auto-accept images</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Auto-accept settings" xml:space="preserve">
<source>Auto-accept settings</source>
<target>Auto-accept settings</target>
<note>alert title</note>
</trans-unit>
<trans-unit id="Back" xml:space="preserve">
<source>Back</source>
<target>Back</target>
@@ -1203,7 +1198,7 @@
<trans-unit id="Cancel" xml:space="preserve">
<source>Cancel</source>
<target>Cancel</target>
<note>alert button</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Cancel migration" xml:space="preserve">
<source>Cancel migration</source>
@@ -1351,11 +1346,6 @@
<target>Chat preferences</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Chat preferences were changed." xml:space="preserve">
<source>Chat preferences were changed.</source>
<target>Chat preferences were changed.</target>
<note>alert message</note>
</trans-unit>
<trans-unit id="Chat theme" xml:space="preserve">
<source>Chat theme</source>
<target>Chat theme</target>
@@ -2884,11 +2874,6 @@ This is your own one-time link!</target>
<target>Error loading %@ servers</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error migrating settings" xml:space="preserve">
<source>Error migrating settings</source>
<target>Error migrating settings</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error opening chat" xml:space="preserve">
<source>Error opening chat</source>
<target>Error opening chat</target>
@@ -3329,6 +3314,11 @@ Error: %2$@</target>
<target>Full name (optional)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Full name:" xml:space="preserve">
<source>Full name:</source>
<target>Full name:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Fully decentralized visible only to members." xml:space="preserve">
<source>Fully decentralized visible only to members.</source>
<target>Fully decentralized visible only to members.</target>
@@ -5061,6 +5051,16 @@ Error: %@</target>
<target>Profile images</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile name" xml:space="preserve">
<source>Profile name</source>
<target>Profile name</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile name:" xml:space="preserve">
<source>Profile name:</source>
<target>Profile name:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile password" xml:space="preserve">
<source>Profile password</source>
<target>Profile password</target>
@@ -5384,11 +5384,6 @@ Enable in *Network &amp; servers* settings.</target>
<target>Remove</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Remove archive?" xml:space="preserve">
<source>Remove archive?</source>
<target>Remove archive?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Remove image" xml:space="preserve">
<source>Remove image</source>
<target>Remove image</target>
@@ -5582,13 +5577,12 @@ Enable in *Network &amp; servers* settings.</target>
<trans-unit id="Save" xml:space="preserve">
<source>Save</source>
<target>Save</target>
<note>alert button
chat item action</note>
<note>chat item action</note>
</trans-unit>
<trans-unit id="Save (and notify contacts)" xml:space="preserve">
<source>Save (and notify contacts)</source>
<target>Save (and notify contacts)</target>
<note>alert button</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save and notify contact" xml:space="preserve">
<source>Save and notify contact</source>
@@ -5615,6 +5609,11 @@ Enable in *Network &amp; servers* settings.</target>
<target>Save archive</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save auto-accept settings" xml:space="preserve">
<source>Save auto-accept settings</source>
<target>Save auto-accept settings</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save group profile" xml:space="preserve">
<source>Save group profile</source>
<target>Save group profile</target>
@@ -5650,16 +5649,16 @@ Enable in *Network &amp; servers* settings.</target>
<target>Save servers?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save settings?" xml:space="preserve">
<source>Save settings?</source>
<target>Save settings?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save welcome message?" xml:space="preserve">
<source>Save welcome message?</source>
<target>Save welcome message?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save your profile?" xml:space="preserve">
<source>Save your profile?</source>
<target>Save your profile?</target>
<note>alert title</note>
</trans-unit>
<trans-unit id="Saved" xml:space="preserve">
<source>Saved</source>
<target>Saved</target>
@@ -6100,11 +6099,6 @@ Enable in *Network &amp; servers* settings.</target>
<target>Settings</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Settings were changed." xml:space="preserve">
<source>Settings were changed.</source>
<target>Settings were changed.</target>
<note>alert message</note>
</trans-unit>
<trans-unit id="Shape profile images" xml:space="preserve">
<source>Shape profile images</source>
<target>Shape profile images</target>
@@ -6310,11 +6304,6 @@ Enable in *Network &amp; servers* settings.</target>
<target>Soft</target>
<note>blur media</note>
</trans-unit>
<trans-unit id="Some app settings were not migrated." xml:space="preserve">
<source>Some app settings were not migrated.</source>
<target>Some app settings were not migrated.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Some file(s) were not exported:" xml:space="preserve">
<source>Some file(s) were not exported:</source>
<target>Some file(s) were not exported:</target>
@@ -6687,11 +6676,6 @@ It can happen because of some bug or when the connection is compromised.</target
<target>The text you pasted is not a SimpleX link.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The uploaded database archive will be permanently removed from the servers." xml:space="preserve">
<source>The uploaded database archive will be permanently removed from the servers.</source>
<target>The uploaded database archive will be permanently removed from the servers.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Themes" xml:space="preserve">
<source>Themes</source>
<target>Themes</target>
@@ -7775,11 +7759,6 @@ Repeat connection request?</target>
<target>Your chat database is not encrypted - set passphrase to encrypt it.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your chat preferences" xml:space="preserve">
<source>Your chat preferences</source>
<target>Your chat preferences</target>
<note>alert title</note>
</trans-unit>
<trans-unit id="Your chat profiles" xml:space="preserve">
<source>Your chat profiles</source>
<target>Your chat profiles</target>
@@ -7835,16 +7814,13 @@ Repeat connection request?</target>
<target>Your profile **%@** will be shared.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source>
<target>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</target>
<trans-unit id="Your profile is stored on your device and shared only with your contacts.&#10;SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts.
SimpleX servers cannot see your profile.</source>
<target>Your profile is stored on your device and shared only with your contacts.
SimpleX servers cannot see your profile.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile was changed. If you save it, the updated profile will be sent to all your contacts." xml:space="preserve">
<source>Your profile was changed. If you save it, the updated profile will be sent to all your contacts.</source>
<target>Your profile was changed. If you save it, the updated profile will be sent to all your contacts.</target>
<note>alert message</note>
</trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>Your profile, contacts and delivered messages are stored on your device.</target>
@@ -1024,10 +1024,6 @@
<target>Aceptar imágenes automáticamente</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Auto-accept settings" xml:space="preserve">
<source>Auto-accept settings</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Back" xml:space="preserve">
<source>Back</source>
<target>Volver</target>
@@ -1201,7 +1197,7 @@
<trans-unit id="Cancel" xml:space="preserve">
<source>Cancel</source>
<target>Cancelar</target>
<note>alert button</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Cancel migration" xml:space="preserve">
<source>Cancel migration</source>
@@ -1349,10 +1345,6 @@
<target>Preferencias de Chat</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Chat preferences were changed." xml:space="preserve">
<source>Chat preferences were changed.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Chat theme" xml:space="preserve">
<source>Chat theme</source>
<target>Tema de chat</target>
@@ -2878,10 +2870,6 @@ This is your own one-time link!</source>
<target>Error al cargar servidores %@</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error migrating settings" xml:space="preserve">
<source>Error migrating settings</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error opening chat" xml:space="preserve">
<source>Error opening chat</source>
<target>Error al abrir chat</target>
@@ -3321,6 +3309,11 @@ Error: %2$@</target>
<target>Nombre completo (opcional)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Full name:" xml:space="preserve">
<source>Full name:</source>
<target>Nombre completo:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Fully decentralized visible only to members." xml:space="preserve">
<source>Fully decentralized visible only to members.</source>
<target>Completamente descentralizado y sólo visible para los miembros.</target>
@@ -5052,6 +5045,16 @@ Error: %@</target>
<target>Forma de los perfiles</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile name" xml:space="preserve">
<source>Profile name</source>
<target>Nombre del perfil</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile name:" xml:space="preserve">
<source>Profile name:</source>
<target>Nombre del perfil:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile password" xml:space="preserve">
<source>Profile password</source>
<target>Contraseña del perfil</target>
@@ -5375,10 +5378,6 @@ Actívalo en ajustes de *Servidores y Redes*.</target>
<target>Eliminar</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Remove archive?" xml:space="preserve">
<source>Remove archive?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Remove image" xml:space="preserve">
<source>Remove image</source>
<target>Eliminar imagen</target>
@@ -5572,13 +5571,12 @@ Actívalo en ajustes de *Servidores y Redes*.</target>
<trans-unit id="Save" xml:space="preserve">
<source>Save</source>
<target>Guardar</target>
<note>alert button
chat item action</note>
<note>chat item action</note>
</trans-unit>
<trans-unit id="Save (and notify contacts)" xml:space="preserve">
<source>Save (and notify contacts)</source>
<target>Guardar (y notificar contactos)</target>
<note>alert button</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save and notify contact" xml:space="preserve">
<source>Save and notify contact</source>
@@ -5605,6 +5603,11 @@ Actívalo en ajustes de *Servidores y Redes*.</target>
<target>Guardar archivo</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save auto-accept settings" xml:space="preserve">
<source>Save auto-accept settings</source>
<target>Guardar configuración de auto aceptar</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save group profile" xml:space="preserve">
<source>Save group profile</source>
<target>Guardar perfil de grupo</target>
@@ -5640,15 +5643,16 @@ Actívalo en ajustes de *Servidores y Redes*.</target>
<target>¿Guardar servidores?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save settings?" xml:space="preserve">
<source>Save settings?</source>
<target>¿Guardar configuración?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save welcome message?" xml:space="preserve">
<source>Save welcome message?</source>
<target>¿Guardar mensaje de bienvenida?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save your profile?" xml:space="preserve">
<source>Save your profile?</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Saved" xml:space="preserve">
<source>Saved</source>
<target>Guardado</target>
@@ -6088,10 +6092,6 @@ Actívalo en ajustes de *Servidores y Redes*.</target>
<target>Configuración</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Settings were changed." xml:space="preserve">
<source>Settings were changed.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Shape profile images" xml:space="preserve">
<source>Shape profile images</source>
<target>Dar forma a las imágenes de perfil</target>
@@ -6296,10 +6296,6 @@ Actívalo en ajustes de *Servidores y Redes*.</target>
<target>Suave</target>
<note>blur media</note>
</trans-unit>
<trans-unit id="Some app settings were not migrated." xml:space="preserve">
<source>Some app settings were not migrated.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Some file(s) were not exported:" xml:space="preserve">
<source>Some file(s) were not exported:</source>
<target>Algunos archivos no han sido exportados:</target>
@@ -6671,10 +6667,6 @@ Puede ocurrir por algún bug o cuando la conexión está comprometida.</target>
<target>El texto pegado no es un enlace SimpleX.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The uploaded database archive will be permanently removed from the servers." xml:space="preserve">
<source>The uploaded database archive will be permanently removed from the servers.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Themes" xml:space="preserve">
<source>Themes</source>
<target>Temas</target>
@@ -7758,10 +7750,6 @@ Repeat connection request?</source>
<target>La base de datos no está cifrada - establece una contraseña para cifrarla.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your chat preferences" xml:space="preserve">
<source>Your chat preferences</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Your chat profiles" xml:space="preserve">
<source>Your chat profiles</source>
<target>Mis perfiles</target>
@@ -7816,15 +7804,13 @@ Repeat connection request?</source>
<target>El perfil **%@** será compartido.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source>
<target>Tu perfil es almacenado en tu dispositivo y solamente se comparte con tus contactos. Los servidores SimpleX no pueden ver tu perfil.</target>
<trans-unit id="Your profile is stored on your device and shared only with your contacts.&#10;SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts.
SimpleX servers cannot see your profile.</source>
<target>Tu perfil es almacenado en tu dispositivo y solamente se comparte con tus contactos.
Los servidores SimpleX no pueden ver tu perfil.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile was changed. If you save it, the updated profile will be sent to all your contacts." xml:space="preserve">
<source>Your profile was changed. If you save it, the updated profile will be sent to all your contacts.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>Tu perfil, contactos y mensajes se almacenan en tu dispositivo.</target>
@@ -971,10 +971,6 @@
<target>Hyväksy kuvat automaattisesti</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Auto-accept settings" xml:space="preserve">
<source>Auto-accept settings</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Back" xml:space="preserve">
<source>Back</source>
<target>Takaisin</target>
@@ -1128,7 +1124,7 @@
<trans-unit id="Cancel" xml:space="preserve">
<source>Cancel</source>
<target>Peruuta</target>
<note>alert button</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Cancel migration" xml:space="preserve">
<source>Cancel migration</source>
@@ -1267,10 +1263,6 @@
<target>Chat-asetukset</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Chat preferences were changed." xml:space="preserve">
<source>Chat preferences were changed.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Chat theme" xml:space="preserve">
<source>Chat theme</source>
<note>No comment provided by engineer.</note>
@@ -2693,10 +2685,6 @@ This is your own one-time link!</source>
<target>Virhe %@-palvelimien lataamisessa</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error migrating settings" xml:space="preserve">
<source>Error migrating settings</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error opening chat" xml:space="preserve">
<source>Error opening chat</source>
<note>No comment provided by engineer.</note>
@@ -3101,6 +3089,11 @@ Error: %2$@</source>
<target>Koko nimi (valinnainen)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Full name:" xml:space="preserve">
<source>Full name:</source>
<target>Koko nimi:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Fully decentralized visible only to members." xml:space="preserve">
<source>Fully decentralized visible only to members.</source>
<note>No comment provided by engineer.</note>
@@ -4724,6 +4717,14 @@ Error: %@</source>
<source>Profile images</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile name" xml:space="preserve">
<source>Profile name</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile name:" xml:space="preserve">
<source>Profile name:</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile password" xml:space="preserve">
<source>Profile password</source>
<target>Profiilin salasana</target>
@@ -5025,10 +5026,6 @@ Enable in *Network &amp; servers* settings.</source>
<target>Poista</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Remove archive?" xml:space="preserve">
<source>Remove archive?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Remove image" xml:space="preserve">
<source>Remove image</source>
<note>No comment provided by engineer.</note>
@@ -5207,13 +5204,12 @@ Enable in *Network &amp; servers* settings.</source>
<trans-unit id="Save" xml:space="preserve">
<source>Save</source>
<target>Tallenna</target>
<note>alert button
chat item action</note>
<note>chat item action</note>
</trans-unit>
<trans-unit id="Save (and notify contacts)" xml:space="preserve">
<source>Save (and notify contacts)</source>
<target>Tallenna (ja ilmoita kontakteille)</target>
<note>alert button</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save and notify contact" xml:space="preserve">
<source>Save and notify contact</source>
@@ -5239,6 +5235,11 @@ Enable in *Network &amp; servers* settings.</source>
<target>Tallenna arkisto</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save auto-accept settings" xml:space="preserve">
<source>Save auto-accept settings</source>
<target>Tallenna automaattisen hyväksynnän asetukset</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save group profile" xml:space="preserve">
<source>Save group profile</source>
<target>Tallenna ryhmäprofiili</target>
@@ -5274,15 +5275,16 @@ Enable in *Network &amp; servers* settings.</source>
<target>Tallenna palvelimet?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save settings?" xml:space="preserve">
<source>Save settings?</source>
<target>Tallenna asetukset?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save welcome message?" xml:space="preserve">
<source>Save welcome message?</source>
<target>Tallenna tervetuloviesti?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save your profile?" xml:space="preserve">
<source>Save your profile?</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Saved" xml:space="preserve">
<source>Saved</source>
<note>No comment provided by engineer.</note>
@@ -5688,10 +5690,6 @@ Enable in *Network &amp; servers* settings.</source>
<target>Asetukset</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Settings were changed." xml:space="preserve">
<source>Settings were changed.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Shape profile images" xml:space="preserve">
<source>Shape profile images</source>
<note>No comment provided by engineer.</note>
@@ -5882,10 +5880,6 @@ Enable in *Network &amp; servers* settings.</source>
<source>Soft</source>
<note>blur media</note>
</trans-unit>
<trans-unit id="Some app settings were not migrated." xml:space="preserve">
<source>Some app settings were not migrated.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Some file(s) were not exported:" xml:space="preserve">
<source>Some file(s) were not exported:</source>
<note>No comment provided by engineer.</note>
@@ -6235,10 +6229,6 @@ Tämä voi johtua jostain virheestä tai siitä, että yhteys on vaarantunut.</t
<source>The text you pasted is not a SimpleX link.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The uploaded database archive will be permanently removed from the servers." xml:space="preserve">
<source>The uploaded database archive will be permanently removed from the servers.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Themes" xml:space="preserve">
<source>Themes</source>
<note>No comment provided by engineer.</note>
@@ -7235,10 +7225,6 @@ Repeat connection request?</source>
<target>Keskustelut-tietokantasi ei ole salattu - aseta tunnuslause sen salaamiseksi.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your chat preferences" xml:space="preserve">
<source>Your chat preferences</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Your chat profiles" xml:space="preserve">
<source>Your chat profiles</source>
<target>Keskusteluprofiilisi</target>
@@ -7292,15 +7278,13 @@ Repeat connection request?</source>
<target>Profiilisi **%@** jaetaan.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source>
<target>Profiilisi tallennetaan laitteeseesi ja jaetaan vain yhteystietojesi kanssa. SimpleX-palvelimet eivät näe profiiliasi.</target>
<trans-unit id="Your profile is stored on your device and shared only with your contacts.&#10;SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts.
SimpleX servers cannot see your profile.</source>
<target>Profiilisi tallennetaan laitteeseesi ja jaetaan vain yhteystietojesi kanssa.
SimpleX-palvelimet eivät näe profiiliasi.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile was changed. If you save it, the updated profile will be sent to all your contacts." xml:space="preserve">
<source>Your profile was changed. If you save it, the updated profile will be sent to all your contacts.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>Profiilisi, kontaktisi ja toimitetut viestit tallennetaan laitteellesi.</target>
@@ -1024,10 +1024,6 @@
<target>Images auto-acceptées</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Auto-accept settings" xml:space="preserve">
<source>Auto-accept settings</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Back" xml:space="preserve">
<source>Back</source>
<target>Retour</target>
@@ -1201,7 +1197,7 @@
<trans-unit id="Cancel" xml:space="preserve">
<source>Cancel</source>
<target>Annuler</target>
<note>alert button</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Cancel migration" xml:space="preserve">
<source>Cancel migration</source>
@@ -1349,10 +1345,6 @@
<target>Préférences de chat</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Chat preferences were changed." xml:space="preserve">
<source>Chat preferences were changed.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Chat theme" xml:space="preserve">
<source>Chat theme</source>
<target>Thème de chat</target>
@@ -2878,10 +2870,6 @@ Il s'agit de votre propre lien unique !</target>
<target>Erreur lors du chargement des serveurs %@</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error migrating settings" xml:space="preserve">
<source>Error migrating settings</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error opening chat" xml:space="preserve">
<source>Error opening chat</source>
<target>Erreur lors de l'ouverture du chat</target>
@@ -3321,6 +3309,11 @@ Erreur: %2$@</target>
<target>Nom complet (optionnel)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Full name:" xml:space="preserve">
<source>Full name:</source>
<target>Nom complet :</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Fully decentralized visible only to members." xml:space="preserve">
<source>Fully decentralized visible only to members.</source>
<target>Entièrement décentralisé visible que par ses membres.</target>
@@ -5052,6 +5045,16 @@ Erreur: %@</target>
<target>Images de profil</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile name" xml:space="preserve">
<source>Profile name</source>
<target>Nom du profil</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile name:" xml:space="preserve">
<source>Profile name:</source>
<target>Nom du profil :</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile password" xml:space="preserve">
<source>Profile password</source>
<target>Mot de passe de profil</target>
@@ -5375,10 +5378,6 @@ Activez-le dans les paramètres *Réseau et serveurs*.</target>
<target>Supprimer</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Remove archive?" xml:space="preserve">
<source>Remove archive?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Remove image" xml:space="preserve">
<source>Remove image</source>
<target>Enlever l'image</target>
@@ -5572,13 +5571,12 @@ Activez-le dans les paramètres *Réseau et serveurs*.</target>
<trans-unit id="Save" xml:space="preserve">
<source>Save</source>
<target>Enregistrer</target>
<note>alert button
chat item action</note>
<note>chat item action</note>
</trans-unit>
<trans-unit id="Save (and notify contacts)" xml:space="preserve">
<source>Save (and notify contacts)</source>
<target>Enregistrer (et en informer les contacts)</target>
<note>alert button</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save and notify contact" xml:space="preserve">
<source>Save and notify contact</source>
@@ -5605,6 +5603,11 @@ Activez-le dans les paramètres *Réseau et serveurs*.</target>
<target>Enregistrer l'archive</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save auto-accept settings" xml:space="preserve">
<source>Save auto-accept settings</source>
<target>Enregistrer les paramètres de validation automatique</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save group profile" xml:space="preserve">
<source>Save group profile</source>
<target>Enregistrer le profil du groupe</target>
@@ -5640,15 +5643,16 @@ Activez-le dans les paramètres *Réseau et serveurs*.</target>
<target>Enregistrer les serveurs?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save settings?" xml:space="preserve">
<source>Save settings?</source>
<target>Enregistrer les paramètres?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save welcome message?" xml:space="preserve">
<source>Save welcome message?</source>
<target>Enregistrer le message d'accueil?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save your profile?" xml:space="preserve">
<source>Save your profile?</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Saved" xml:space="preserve">
<source>Saved</source>
<target>Enregistré</target>
@@ -6088,10 +6092,6 @@ Activez-le dans les paramètres *Réseau et serveurs*.</target>
<target>Paramètres</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Settings were changed." xml:space="preserve">
<source>Settings were changed.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Shape profile images" xml:space="preserve">
<source>Shape profile images</source>
<target>Images de profil modelable</target>
@@ -6296,10 +6296,6 @@ Activez-le dans les paramètres *Réseau et serveurs*.</target>
<target>Léger</target>
<note>blur media</note>
</trans-unit>
<trans-unit id="Some app settings were not migrated." xml:space="preserve">
<source>Some app settings were not migrated.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Some file(s) were not exported:" xml:space="preserve">
<source>Some file(s) were not exported:</source>
<target>Certains fichiers n'ont pas été exportés:</target>
@@ -6671,10 +6667,6 @@ Cela peut se produire en raison d'un bug ou lorsque la connexion est compromise.
<target>Le texte collé n'est pas un lien SimpleX.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The uploaded database archive will be permanently removed from the servers." xml:space="preserve">
<source>The uploaded database archive will be permanently removed from the servers.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Themes" xml:space="preserve">
<source>Themes</source>
<target>Thèmes</target>
@@ -7758,10 +7750,6 @@ Répéter la demande de connexion ?</target>
<target>Votre base de données de chat n'est pas chiffrée - définisez une phrase secrète.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your chat preferences" xml:space="preserve">
<source>Your chat preferences</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Your chat profiles" xml:space="preserve">
<source>Your chat profiles</source>
<target>Vos profils de chat</target>
@@ -7816,15 +7804,13 @@ Répéter la demande de connexion ?</target>
<target>Votre profil **%@** sera partagé.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source>
<target>Votre profil est stocké sur votre appareil et est seulement partagé avec vos contacts. Les serveurs SimpleX ne peuvent pas voir votre profil.</target>
<trans-unit id="Your profile is stored on your device and shared only with your contacts.&#10;SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts.
SimpleX servers cannot see your profile.</source>
<target>Votre profil est stocké sur votre appareil et est seulement partagé avec vos contacts.
Les serveurs SimpleX ne peuvent pas voir votre profil.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile was changed. If you save it, the updated profile will be sent to all your contacts." xml:space="preserve">
<source>Your profile was changed. If you save it, the updated profile will be sent to all your contacts.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>Votre profil, vos contacts et les messages reçus sont stockés sur votre appareil.</target>
@@ -427,8 +427,8 @@
<source>- voice messages up to 5 minutes.
- custom time to disappear.
- editing history.</source>
<target>- 5 perc hosszúságú hangüzenetek.
- egyedi üzenet-eltűnési időkorlát.
<target>- hangüzenetek legfeljebb 5 perces időtartamig.
- egyedi eltűnési időhatár megadása.
- előzmények szerkesztése.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -496,7 +496,7 @@
<source>&lt;p&gt;Hi!&lt;/p&gt;
&lt;p&gt;&lt;a href="%@"&gt;Connect to me via SimpleX Chat&lt;/a&gt;&lt;/p&gt;</source>
<target>&lt;p&gt;Üdvözlöm!&lt;/p&gt;
&lt;p&gt;&lt;a href=„%@”&gt;Csatlakozzon hozzám a SimpleX Chaten keresztül&lt;/a&gt;&lt;/p&gt;</target>
&lt;p&gt;&lt;a href=„%@”&gt;Csatlakozzon hozzám a SimpleX Chaten&lt;/a&gt;&lt;/p&gt;</target>
<note>email text</note>
</trans-unit>
<trans-unit id="A few more things" xml:space="preserve">
@@ -570,7 +570,7 @@
</trans-unit>
<trans-unit id="Accept connection request?" xml:space="preserve">
<source>Accept connection request?</source>
<target>Ismerőskérelem elfogadása?</target>
<target>Kapcsolódási kérelem elfogadása?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Accept contact request from %@?" xml:space="preserve">
@@ -1024,10 +1024,6 @@
<target>Képek automatikus elfogadása</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Auto-accept settings" xml:space="preserve">
<source>Auto-accept settings</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Back" xml:space="preserve">
<source>Back</source>
<target>Vissza</target>
@@ -1050,7 +1046,7 @@
</trans-unit>
<trans-unit id="Bad message hash" xml:space="preserve">
<source>Bad message hash</source>
<target>Hibás az üzenet hasító értéke</target>
<target>Hibás az üzenet ellenőrzőösszege</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Better groups" xml:space="preserve">
@@ -1201,7 +1197,7 @@
<trans-unit id="Cancel" xml:space="preserve">
<source>Cancel</source>
<target>Mégse</target>
<note>alert button</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Cancel migration" xml:space="preserve">
<source>Cancel migration</source>
@@ -1349,10 +1345,6 @@
<target>Csevegési beállítások</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Chat preferences were changed." xml:space="preserve">
<source>Chat preferences were changed.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Chat theme" xml:space="preserve">
<source>Chat theme</source>
<target>Csevegés témája</target>
@@ -1530,7 +1522,7 @@
</trans-unit>
<trans-unit id="Connect to desktop" xml:space="preserve">
<source>Connect to desktop</source>
<target>Társítás számítógéppel</target>
<target>Kapcsolódás számítógéphez</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect to your friends faster." xml:space="preserve">
@@ -1554,7 +1546,7 @@ Ez az ön SimpleX címe!</target>
<source>Connect to yourself?
This is your own one-time link!</source>
<target>Kapcsolódás saját magához?
Ez az ön egyszer használatos hivatkozása!</target>
Ez az egyszer használatos hivatkozása!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via contact address" xml:space="preserve">
@@ -1584,7 +1576,7 @@ Ez az ön egyszer használatos hivatkozása!</target>
</trans-unit>
<trans-unit id="Connected desktop" xml:space="preserve">
<source>Connected desktop</source>
<target>Társított számítógép</target>
<target>Csatlakoztatott számítógép</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connected servers" xml:space="preserve">
@@ -1679,7 +1671,7 @@ Ez az ön egyszer használatos hivatkozása!</target>
</trans-unit>
<trans-unit id="Contact already exists" xml:space="preserve">
<source>Contact already exists</source>
<target>Az ismerős már létezik</target>
<target>Létező ismerős</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contact deleted!" xml:space="preserve">
@@ -1793,7 +1785,7 @@ Ez az ön egyszer használatos hivatkozása!</target>
</trans-unit>
<trans-unit id="Create group link" xml:space="preserve">
<source>Create group link</source>
<target>Csoporthivatkozás létrehozása</target>
<target>Csoportos hivatkozás létrehozása</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create link" xml:space="preserve">
@@ -1848,7 +1840,7 @@ Ez az ön egyszer használatos hivatkozása!</target>
</trans-unit>
<trans-unit id="Creating archive link" xml:space="preserve">
<source>Creating archive link</source>
<target>Archívum hivatkozás létrehozása</target>
<target>Archív hivatkozás létrehozása</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Creating link…" xml:space="preserve">
@@ -2177,7 +2169,7 @@ Ez az ön egyszer használatos hivatkozása!</target>
</trans-unit>
<trans-unit id="Delete pending connection?" xml:space="preserve">
<source>Delete pending connection?</source>
<target>Függőben lévő ismerőskérelem törlése?</target>
<target>Függő kapcsolatfelvételi kérések törlése?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delete profile" xml:space="preserve">
@@ -2487,7 +2479,7 @@ Ez az ön egyszer használatos hivatkozása!</target>
</trans-unit>
<trans-unit id="Duplicate display name!" xml:space="preserve">
<source>Duplicate display name!</source>
<target>Duplikált megjelenített név!</target>
<target>Duplikált megjelenítési név!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Duration" xml:space="preserve">
@@ -2732,7 +2724,7 @@ Ez az ön egyszer használatos hivatkozása!</target>
</trans-unit>
<trans-unit id="Error adding member(s)" xml:space="preserve">
<source>Error adding member(s)</source>
<target>Hiba a tag(ok) hozzáadásakor</target>
<target>Hiba a tag(-ok) hozzáadásakor</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error changing address" xml:space="preserve">
@@ -2775,7 +2767,7 @@ Ez az ön egyszer használatos hivatkozása!</target>
</trans-unit>
<trans-unit id="Error creating group link" xml:space="preserve">
<source>Error creating group link</source>
<target>Hiba a csoporthivatkozás létrehozásakor</target>
<target>Hiba a csoport hivatkozásának létrehozásakor</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error creating member contact" xml:space="preserve">
@@ -2878,10 +2870,6 @@ Ez az ön egyszer használatos hivatkozása!</target>
<target>Hiba a %@ kiszolgálók betöltésekor</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error migrating settings" xml:space="preserve">
<source>Error migrating settings</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error opening chat" xml:space="preserve">
<source>Error opening chat</source>
<target>Hiba a csevegés megnyitásakor</target>
@@ -2998,7 +2986,7 @@ Ez az ön egyszer használatos hivatkozása!</target>
</trans-unit>
<trans-unit id="Error updating group link" xml:space="preserve">
<source>Error updating group link</source>
<target>Hiba a csoporthivatkozás frissítésekor</target>
<target>Hiba a csoport hivatkozás frissítésekor</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error updating message" xml:space="preserve">
@@ -3321,6 +3309,11 @@ Hiba: %2$@</target>
<target>Teljes név (opcionális)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Full name:" xml:space="preserve">
<source>Full name:</source>
<target>Teljes név:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Fully decentralized visible only to members." xml:space="preserve">
<source>Fully decentralized visible only to members.</source>
<target>Teljesen decentralizált - kizárólag tagok számára látható.</target>
@@ -3398,12 +3391,12 @@ Hiba: %2$@</target>
</trans-unit>
<trans-unit id="Group link" xml:space="preserve">
<source>Group link</source>
<target>Csoporthivatkozás</target>
<target>Csoport hivatkozás</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group links" xml:space="preserve">
<source>Group links</source>
<target>Csoporthivatkozások</target>
<target>Csoport hivatkozások</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group members can add message reactions." xml:space="preserve">
@@ -3473,7 +3466,7 @@ Hiba: %2$@</target>
</trans-unit>
<trans-unit id="Group will be deleted for all members - this cannot be undone!" xml:space="preserve">
<source>Group will be deleted for all members - this cannot be undone!</source>
<target>A csoport törlésre kerül minden tag számára - ez a művelet nem vonható vissza!</target>
<target>Csoport törlésre kerül minden tag számára - ez a művelet nem vonható vissza!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group will be deleted for you - this cannot be undone!" xml:space="preserve">
@@ -3770,12 +3763,12 @@ Hiba: %2$@</target>
</trans-unit>
<trans-unit id="Invalid connection link" xml:space="preserve">
<source>Invalid connection link</source>
<target>Érvénytelen kapcsolattartási hivatkozás</target>
<target>Érvénytelen kapcsolati hivatkozás</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid display name!" xml:space="preserve">
<source>Invalid display name!</source>
<target>Érvénytelen megjelenítendő név!</target>
<target>Érvénytelen megjelenítendő felhaszálónév!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid link" xml:space="preserve">
@@ -3993,7 +3986,7 @@ Ez az ön hivatkozása a(z) %@ csoporthoz!</target>
</trans-unit>
<trans-unit id="Let's talk in SimpleX Chat" xml:space="preserve">
<source>Let's talk in SimpleX Chat</source>
<target>Beszélgessünk a SimpleX Chatben</target>
<target>Beszélgessünk a SimpleX Chat-ben</target>
<note>email subject</note>
</trans-unit>
<trans-unit id="Light" xml:space="preserve">
@@ -4008,17 +4001,17 @@ Ez az ön hivatkozása a(z) %@ csoporthoz!</target>
</trans-unit>
<trans-unit id="Link mobile and desktop apps! 🔗" xml:space="preserve">
<source>Link mobile and desktop apps! 🔗</source>
<target>Társítsa össze a mobil és asztali alkalmazásokat! 🔗</target>
<target>Társítsa össze a mobil és az asztali alkalmazásokat! 🔗</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Linked desktop options" xml:space="preserve">
<source>Linked desktop options</source>
<target>Társított számítógép beállítások</target>
<target>Összekapcsolt számítógép beállítások</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Linked desktops" xml:space="preserve">
<source>Linked desktops</source>
<target>Társított számítógépek</target>
<target>Összekapcsolt számítógépek</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Live message!" xml:space="preserve">
@@ -4083,7 +4076,7 @@ Ez az ön hivatkozása a(z) %@ csoporthoz!</target>
</trans-unit>
<trans-unit id="Many people asked: *if SimpleX has no user identifiers, how can it deliver messages?*" xml:space="preserve">
<source>Many people asked: *if SimpleX has no user identifiers, how can it deliver messages?*</source>
<target>Sokan kérdezték: *ha a SimpleX Chatnek nincsenek felhasználói azonosítói, akkor hogyan tud üzeneteket kézbesíteni?*</target>
<target>Sokan kérdezték: *ha a SimpleX-nek nincsenek felhasználói azonosítói, akkor hogyan tud üzeneteket kézbesíteni?*</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Mark deleted for everyone" xml:space="preserve">
@@ -4342,12 +4335,12 @@ Ez az ön hivatkozása a(z) %@ csoporthoz!</target>
</trans-unit>
<trans-unit id="Moderated at" xml:space="preserve">
<source>Moderated at</source>
<target>Moderálva ekkor:</target>
<target>Moderálva lett ekkor:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Moderated at: %@" xml:space="preserve">
<source>Moderated at: %@</source>
<target>Moderálva ekkor: %@</target>
<target>Moderálva lett ekkor: %@</target>
<note>copied message info</note>
</trans-unit>
<trans-unit id="More improvements are coming soon!" xml:space="preserve">
@@ -4432,7 +4425,7 @@ Ez az ön hivatkozása a(z) %@ csoporthoz!</target>
</trans-unit>
<trans-unit id="New contact request" xml:space="preserve">
<source>New contact request</source>
<target>Új ismerőskérelem</target>
<target>Új kapcsolattartási kérelem</target>
<note>notification</note>
</trans-unit>
<trans-unit id="New contact:" xml:space="preserve">
@@ -4492,7 +4485,7 @@ Ez az ön hivatkozása a(z) %@ csoporthoz!</target>
</trans-unit>
<trans-unit id="No contacts selected" xml:space="preserve">
<source>No contacts selected</source>
<target>Nincs kiválasztva ismerős</target>
<target>Nem kerültek ismerősök kiválasztásra</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="No contacts to add" xml:space="preserve">
@@ -4557,7 +4550,7 @@ Ez az ön hivatkozása a(z) %@ csoporthoz!</target>
</trans-unit>
<trans-unit id="Nothing selected" xml:space="preserve">
<source>Nothing selected</source>
<target>Nincs kiválasztva semmi</target>
<target>Semmi sincs kiválasztva</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Notifications" xml:space="preserve">
@@ -4601,7 +4594,7 @@ Ez az ön hivatkozása a(z) %@ csoporthoz!</target>
</trans-unit>
<trans-unit id="Old database archive" xml:space="preserve">
<source>Old database archive</source>
<target>Régi adatbázis-archívum</target>
<target>Régi adatbázis archívum</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="One-time invitation link" xml:space="preserve">
@@ -4630,7 +4623,7 @@ VPN engedélyezése szükséges.</target>
</trans-unit>
<trans-unit id="Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**." xml:space="preserve">
<source>Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**.</source>
<target>Csak a klienseszközök tárolják a felhasználói profilokat, névjegyeket, csoportokat és a **2 rétegű végpontok közötti titkosítással** küldött üzeneteket.</target>
<target>Csak a klienseszközök tárolják a felhasználói profilokat, névjegyeket, csoportokat és a **2 rétegű végponttól-végpontig titkosítással** küldött üzeneteket.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Only delete conversation" xml:space="preserve">
@@ -4765,7 +4758,7 @@ VPN engedélyezése szükséges.</target>
</trans-unit>
<trans-unit id="Or securely share this file link" xml:space="preserve">
<source>Or securely share this file link</source>
<target>Vagy ossza meg biztonságosan ezt a fájlhivatkozást</target>
<target>Vagy a fájl hivítkozásának biztonságos megosztása</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Or show this code" xml:space="preserve">
@@ -4825,7 +4818,7 @@ VPN engedélyezése szükséges.</target>
</trans-unit>
<trans-unit id="Past member %@" xml:space="preserve">
<source>Past member %@</source>
<target>%@ (már nem tag)</target>
<target>Már nem tag - %@</target>
<note>past/unknown group member</note>
</trans-unit>
<trans-unit id="Paste desktop address" xml:space="preserve">
@@ -4845,12 +4838,12 @@ VPN engedélyezése szükséges.</target>
</trans-unit>
<trans-unit id="Paste the link you received" xml:space="preserve">
<source>Paste the link you received</source>
<target>Kapott hivatkozás beillesztése</target>
<target>Fogadott hivatkozás beillesztése</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Pending" xml:space="preserve">
<source>Pending</source>
<target>Függőben</target>
<target>Függő</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="People can connect to you only via the links you share." xml:space="preserve">
@@ -4897,7 +4890,7 @@ Minden további problémát osszon meg a fejlesztőkkel.</target>
</trans-unit>
<trans-unit id="Please check that you used the correct link or ask your contact to send you another one." xml:space="preserve">
<source>Please check that you used the correct link or ask your contact to send you another one.</source>
<target>Ellenőrizze, hogy a megfelelő hivatkozást használta-e, vagy kérje meg az ismerősét, hogy küldjön egy másikat.</target>
<target>Ellenőrizze, hogy a megfelelő hivatkozást használta-e, vagy kérje meg ismerősét, hogy küldjön egy másikat.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Please check your network connection with %@ and try again." xml:space="preserve">
@@ -5052,6 +5045,16 @@ Hiba: %@</target>
<target>Profilképek</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile name" xml:space="preserve">
<source>Profile name</source>
<target>Profilnév</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile name:" xml:space="preserve">
<source>Profile name:</source>
<target>Profil neve:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile password" xml:space="preserve">
<source>Profile password</source>
<target>Profiljelszó</target>
@@ -5375,10 +5378,6 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben.</target>
<target>Eltávolítás</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Remove archive?" xml:space="preserve">
<source>Remove archive?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Remove image" xml:space="preserve">
<source>Remove image</source>
<target>Kép eltávolítása</target>
@@ -5451,7 +5450,7 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben.</target>
</trans-unit>
<trans-unit id="Reset" xml:space="preserve">
<source>Reset</source>
<target>Visszaállítás</target>
<target>Alaphelyzetbe állítás</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Reset all hints" xml:space="preserve">
@@ -5471,7 +5470,7 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben.</target>
</trans-unit>
<trans-unit id="Reset colors" xml:space="preserve">
<source>Reset colors</source>
<target>Színek visszaállítása</target>
<target>Színek alaphelyzetbe állítása</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Reset to app theme" xml:space="preserve">
@@ -5481,7 +5480,7 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben.</target>
</trans-unit>
<trans-unit id="Reset to defaults" xml:space="preserve">
<source>Reset to defaults</source>
<target>Visszaállítás alaphelyzetbe</target>
<target>Alaphelyzetbe állítás</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Reset to user theme" xml:space="preserve">
@@ -5572,13 +5571,12 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben.</target>
<trans-unit id="Save" xml:space="preserve">
<source>Save</source>
<target>Mentés</target>
<note>alert button
chat item action</note>
<note>chat item action</note>
</trans-unit>
<trans-unit id="Save (and notify contacts)" xml:space="preserve">
<source>Save (and notify contacts)</source>
<target>Mentés (és az ismerősök értesítése)</target>
<note>alert button</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save and notify contact" xml:space="preserve">
<source>Save and notify contact</source>
@@ -5605,6 +5603,11 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben.</target>
<target>Archívum mentése</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save auto-accept settings" xml:space="preserve">
<source>Save auto-accept settings</source>
<target>Automatikus elfogadási beállítások mentése</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save group profile" xml:space="preserve">
<source>Save group profile</source>
<target>Csoportprofil elmentése</target>
@@ -5640,15 +5643,16 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben.</target>
<target>Kiszolgálók mentése?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save settings?" xml:space="preserve">
<source>Save settings?</source>
<target>Beállítások mentése?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save welcome message?" xml:space="preserve">
<source>Save welcome message?</source>
<target>Üdvözlőszöveg mentése?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save your profile?" xml:space="preserve">
<source>Save your profile?</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Saved" xml:space="preserve">
<source>Saved</source>
<target>Mentett</target>
@@ -6020,12 +6024,12 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben.</target>
</trans-unit>
<trans-unit id="Servers info" xml:space="preserve">
<source>Servers info</source>
<target>Információk a kiszolgálókról</target>
<target>információk a kiszolgálókról</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Servers statistics will be reset - this cannot be undone!" xml:space="preserve">
<source>Servers statistics will be reset - this cannot be undone!</source>
<target>A kiszolgálók statisztikái visszaállnak - ez a művelet nem vonható vissza!</target>
<target>A kiszolgálók statisztikái visszaállnak - ez nem vonható vissza!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Session code" xml:space="preserve">
@@ -6088,10 +6092,6 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben.</target>
<target>Beállítások</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Settings were changed." xml:space="preserve">
<source>Settings were changed.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Shape profile images" xml:space="preserve">
<source>Shape profile images</source>
<target>Profilkép alakzat</target>
@@ -6243,7 +6243,7 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben.</target>
</trans-unit>
<trans-unit id="SimpleX group link" xml:space="preserve">
<source>SimpleX group link</source>
<target>SimpleX csoporthivatkozás</target>
<target>SimpleX csoport hivatkozás</target>
<note>simplex link type</note>
</trans-unit>
<trans-unit id="SimpleX links" xml:space="preserve">
@@ -6296,10 +6296,6 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben.</target>
<target>Enyhe</target>
<note>blur media</note>
</trans-unit>
<trans-unit id="Some app settings were not migrated." xml:space="preserve">
<source>Some app settings were not migrated.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Some file(s) were not exported:" xml:space="preserve">
<source>Some file(s) were not exported:</source>
<target>Néhány fájl nem került exportálásra:</target>
@@ -6437,7 +6433,7 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben.</target>
</trans-unit>
<trans-unit id="Support SimpleX Chat" xml:space="preserve">
<source>Support SimpleX Chat</source>
<target>SimpleX Chat támogatása</target>
<target>Támogassa a SimpleX Chatet</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="System" xml:space="preserve">
@@ -6556,7 +6552,7 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben.</target>
</trans-unit>
<trans-unit id="Thanks to the users contribute via Weblate!" xml:space="preserve">
<source>Thanks to the users contribute via Weblate!</source>
<target>Köszönet a felhasználóknak - hozzájárulás a Weblate-en!</target>
<target>Köszönet a felhasználóknak - hozzájárulás a Weblaten!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The 1st platform without any user identifiers private by design." xml:space="preserve">
@@ -6588,12 +6584,12 @@ Ez valamilyen hiba, vagy sérült kapcsolat esetén fordulhat elő.</target>
</trans-unit>
<trans-unit id="The code you scanned is not a SimpleX link QR code." xml:space="preserve">
<source>The code you scanned is not a SimpleX link QR code.</source>
<target>A beolvasott QR-kód nem egy SimpleX QR-kód hivatkozás.</target>
<target>A beolvasott kód nem egy SimpleX hivatkozás QR-kód.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve">
<source>The connection you accepted will be cancelled!</source>
<target>Az ön által elfogadott kérelem vissza lesz vonva!</target>
<target>Az ön által elfogadott kapcsolat vissza lesz vonva!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The contact you shared this link with will NOT be able to connect!" xml:space="preserve">
@@ -6613,7 +6609,7 @@ Ez valamilyen hiba, vagy sérült kapcsolat esetén fordulhat elő.</target>
</trans-unit>
<trans-unit id="The hash of the previous message is different." xml:space="preserve">
<source>The hash of the previous message is different.</source>
<target>Az előző üzenet hasító értéke különbözik.</target>
<target>Az előző üzenet ellenőrzőösszege különbözik.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The message will be deleted for all members." xml:space="preserve">
@@ -6671,10 +6667,6 @@ Ez valamilyen hiba, vagy sérült kapcsolat esetén fordulhat elő.</target>
<target>A beillesztett szöveg nem egy SimpleX hivatkozás.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The uploaded database archive will be permanently removed from the servers." xml:space="preserve">
<source>The uploaded database archive will be permanently removed from the servers.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Themes" xml:space="preserve">
<source>Themes</source>
<target>Témák</target>
@@ -6722,7 +6714,7 @@ Ez valamilyen hiba, vagy sérült kapcsolat esetén fordulhat elő.</target>
</trans-unit>
<trans-unit id="This display name is invalid. Please choose another name." xml:space="preserve">
<source>This display name is invalid. Please choose another name.</source>
<target>Ez a megjelenített név érvénytelen. Válasszon egy másik nevet.</target>
<target>Ez a megjelenített felhasználónév érvénytelen. Válasszon egy másik nevet.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve">
@@ -6742,12 +6734,12 @@ Ez valamilyen hiba, vagy sérült kapcsolat esetén fordulhat elő.</target>
</trans-unit>
<trans-unit id="This is your own one-time link!" xml:space="preserve">
<source>This is your own one-time link!</source>
<target>Ez az ön egyszer használatos hivatkozása!</target>
<target>Ez az egyszer használatos hivatkozása!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This link was used with another mobile device, please create a new link on the desktop." xml:space="preserve">
<source>This link was used with another mobile device, please create a new link on the desktop.</source>
<target>Ezt a hivatkozást egy másik mobileszközön már használták, hozzon létre egy új hivatkozást az asztali számítógépén.</target>
<target>Ezt a hivatkozást egy másik mobilleszközön már használták, hozzon létre egy új hivatkozást az asztali számítógépén.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This setting applies to messages in your current chat profile **%@**." xml:space="preserve">
@@ -6854,12 +6846,12 @@ A funkció bekapcsolása előtt a rendszer felszólítja a képernyőzár beáll
</trans-unit>
<trans-unit id="Trying to connect to the server used to receive messages from this contact (error: %@)." xml:space="preserve">
<source>Trying to connect to the server used to receive messages from this contact (error: %@).</source>
<target>Kapcsolódási kísérlet ahhoz a kiszolgálóhoz, amely az adott ismerősétől érkező üzenetek fogadására szolgál (hiba: %@).</target>
<target>Kapcsolódási kísérlet ahhoz a kiszolgálóhoz, amely az adott ismerőstől érkező üzenetek fogadására szolgál (hiba: %@).</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Trying to connect to the server used to receive messages from this contact." xml:space="preserve">
<source>Trying to connect to the server used to receive messages from this contact.</source>
<target>Kapcsolódási kísérlet ahhoz a kiszolgálóhoz, amely az adott ismerősétől érkező üzenetek fogadására szolgál.</target>
<target>Kapcsolódási kísérlet ahhoz a kiszolgálóhoz, amely az adott ismerőstől érkező üzenetek fogadására szolgál.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Turkish interface" xml:space="preserve">
@@ -6965,8 +6957,8 @@ A funkció bekapcsolása előtt a rendszer felszólítja a képernyőzár beáll
<trans-unit id="Unless your contact deleted the connection or this link was already used, it might be a bug - please report it.&#10;To connect, please ask your contact to create another connection link and check that you have a stable network connection." xml:space="preserve">
<source>Unless your contact deleted the connection or this link was already used, it might be a bug - please report it.
To connect, please ask your contact to create another connection link and check that you have a stable network connection.</source>
<target>Hacsak az ismerőse nem törölte a kapcsolatot, vagy ez a hivatkozás már használatban volt egyszer, lehet hogy ez egy hiba jelentse a problémát.
A kapcsolódáshoz kérje meg az ismerősét, hogy hozzon létre egy másik kapcsolattartási hivatkozást, és ellenőrizze, hogy a hálózati kapcsolat stabil-e.</target>
<target>Hacsak az ismerőse nem törölte a kapcsolatot, vagy ez a hivatkozás már használatban volt, lehet hogy ez egy hiba jelentse a problémát.
A kapcsolódáshoz kérje meg ismerősét, hogy hozzon létre egy másik kapcsolati hivatkozást, és ellenőrizze, hogy a hálózati kapcsolat stabil-e.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unlink" xml:space="preserve">
@@ -7091,7 +7083,7 @@ A kapcsolódáshoz kérje meg az ismerősét, hogy hozzon létre egy másik kapc
</trans-unit>
<trans-unit id="Use from desktop" xml:space="preserve">
<source>Use from desktop</source>
<target>Társítás számítógéppel</target>
<target>Használat számítógépl</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use iOS call interface" xml:space="preserve">
@@ -7431,7 +7423,7 @@ A kapcsolódáshoz kérje meg az ismerősét, hogy hozzon létre egy másik kapc
</trans-unit>
<trans-unit id="You are already connected to %@." xml:space="preserve">
<source>You are already connected to %@.</source>
<target>Ön már kapcsolódva van ehhez: %@.</target>
<target>Már kapcsolódva van hozzá: %@.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are already connecting to %@." xml:space="preserve">
@@ -7473,7 +7465,7 @@ Csatlakozási kérés megismétlése?</target>
</trans-unit>
<trans-unit id="You are connected to the server used to receive messages from this contact." xml:space="preserve">
<source>You are connected to the server used to receive messages from this contact.</source>
<target>Már kapcsolódott ahhoz a kiszolgálóhoz, amely az adott ismerősétől érkező üzenetek fogadására szolgál.</target>
<target>Már kapcsolódott ahhoz a kiszolgálóhoz, amely az adott ismerőstől érkező üzenetek fogadására szolgál.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are invited to group" xml:space="preserve">
@@ -7523,7 +7515,7 @@ Csatlakozási kérés megismétlése?</target>
</trans-unit>
<trans-unit id="You can make it visible to your SimpleX contacts via Settings." xml:space="preserve">
<source>You can make it visible to your SimpleX contacts via Settings.</source>
<target>Láthatóvá teheti a SimpleXbeli ismerősei számára a Beállításokban.</target>
<target>Láthatóvá teheti SimpleX ismerősök számára a Beállításokban.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can now chat with %@" xml:space="preserve">
@@ -7670,7 +7662,7 @@ Kapcsolódási kérés megismétlése?</target>
</trans-unit>
<trans-unit id="You will be connected when group link host's device is online, please wait or check later!" xml:space="preserve">
<source>You will be connected when group link host's device is online, please wait or check later!</source>
<target>Akkor lesz kapcsolódva, amikor a csoporthivatkozás tulajdonosának eszköze online lesz, várjon, vagy ellenőrizze később!</target>
<target>Akkor lesz kapcsolódva, amikor a csoportos hivatkozás tulajdonosának eszköze online lesz, várjon, vagy ellenőrizze később!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You will be connected when your connection request is accepted, please wait or check later!" xml:space="preserve">
@@ -7735,7 +7727,7 @@ Kapcsolódási kérés megismétlése?</target>
</trans-unit>
<trans-unit id="Your SimpleX address" xml:space="preserve">
<source>Your SimpleX address</source>
<target>Profil SimpleX címe</target>
<target>Az ön SimpleX címe</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your XFTP servers" xml:space="preserve">
@@ -7758,10 +7750,6 @@ Kapcsolódási kérés megismétlése?</target>
<target>A csevegési adatbázis nincs titkosítva adjon meg egy jelmondatot a titkosításhoz.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your chat preferences" xml:space="preserve">
<source>Your chat preferences</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Your chat profiles" xml:space="preserve">
<source>Your chat profiles</source>
<target>Csevegési profilok</target>
@@ -7816,15 +7804,13 @@ Kapcsolódási kérés megismétlése?</target>
<target>A(z) **%@** nevű profilja megosztásra fog kerülni.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source>
<target>Profilja az eszközön van tárolva, és csak az ismerősökkel kerül megosztásra. A SimpleX kiszolgálók nem látjhatják profilját.</target>
<trans-unit id="Your profile is stored on your device and shared only with your contacts.&#10;SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts.
SimpleX servers cannot see your profile.</source>
<target>Profilja az eszközön van tárolva, és csak az ismerősökkel kerül megosztásra.
A SimpleX kiszolgálók nem látjhatják profilját.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile was changed. If you save it, the updated profile will be sent to all your contacts." xml:space="preserve">
<source>Your profile was changed. If you save it, the updated profile will be sent to all your contacts.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>Profilja, ismerősei és az elküldött üzenetei az eszközön kerülnek tárolásra.</target>
@@ -7862,7 +7848,7 @@ Kapcsolódási kérés megismétlése?</target>
</trans-unit>
<trans-unit id="[Star on GitHub](https://github.com/simplex-chat/simplex-chat)" xml:space="preserve">
<source>[Star on GitHub](https://github.com/simplex-chat/simplex-chat)</source>
<target>[Csillagozás a GitHubon](https://github.com/simplex-chat/simplex-chat)</target>
<target>[Csillag a GitHubon](https://github.com/simplex-chat/simplex-chat)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="_italic_" xml:space="preserve">
@@ -7942,7 +7928,7 @@ Kapcsolódási kérés megismétlése?</target>
</trans-unit>
<trans-unit id="bad message hash" xml:space="preserve">
<source>bad message hash</source>
<target>hibás az üzenet hasító értéke</target>
<target>hibás az üzenet ellenőrzőösszege</target>
<note>integrity error chat item</note>
</trans-unit>
<trans-unit id="blocked" xml:space="preserve">
@@ -7972,7 +7958,7 @@ Kapcsolódási kérés megismétlése?</target>
</trans-unit>
<trans-unit id="call error" xml:space="preserve">
<source>call error</source>
<target>híváshiba</target>
<target>hiba a hívásban</target>
<note>call status</note>
</trans-unit>
<trans-unit id="call in progress" xml:space="preserve">
@@ -8067,7 +8053,7 @@ Kapcsolódási kérés megismétlése?</target>
</trans-unit>
<trans-unit id="connecting call" xml:space="preserve">
<source>connecting call…</source>
<target>kapcsolódási hívás…</target>
<target>hívás kapcsolódik…</target>
<note>call status</note>
</trans-unit>
<trans-unit id="connecting…" xml:space="preserve">
@@ -8307,12 +8293,12 @@ Kapcsolódási kérés megismétlése?</target>
</trans-unit>
<trans-unit id="incognito via group link" xml:space="preserve">
<source>incognito via group link</source>
<target>inkognitó a csoporthivatkozáson keresztül</target>
<target>inkognitó a csoportos hivatkozáson keresztül</target>
<note>chat list item description</note>
</trans-unit>
<trans-unit id="incognito via one-time link" xml:space="preserve">
<source>incognito via one-time link</source>
<target>inkognitó egy egyszer használatos hivatkozáson keresztül</target>
<target>inkognitó az egyszer használatos hivatkozáson keresztül</target>
<note>chat list item description</note>
</trans-unit>
<trans-unit id="indirect (%d)" xml:space="preserve">
@@ -8362,7 +8348,7 @@ Kapcsolódási kérés megismétlése?</target>
</trans-unit>
<trans-unit id="invited via your group link" xml:space="preserve">
<source>invited via your group link</source>
<target>meghíva az ön csoporthivatkozásán keresztül</target>
<target>meghíva az ön csoport hivatkozásán keresztül</target>
<note>rcv group event chat item</note>
</trans-unit>
<trans-unit id="italic" xml:space="preserve">
@@ -8382,7 +8368,7 @@ Kapcsolódási kérés megismétlése?</target>
</trans-unit>
<trans-unit id="marked deleted" xml:space="preserve">
<source>marked deleted</source>
<target>törlésre jelölve</target>
<target>töröltnek jelölve</target>
<note>marked deleted chat item preview text</note>
</trans-unit>
<trans-unit id="member" xml:space="preserve">
@@ -8524,7 +8510,7 @@ Kapcsolódási kérés megismétlése?</target>
</trans-unit>
<trans-unit id="received answer…" xml:space="preserve">
<source>received answer…</source>
<target>válasz fogadása…</target>
<target>fogadott válasz…</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="received confirmation…" xml:space="preserve">
@@ -8698,12 +8684,12 @@ utoljára fogadott üzenet: %2$@</target>
</trans-unit>
<trans-unit id="via group link" xml:space="preserve">
<source>via group link</source>
<target>a csoporthivatkozáson keresztül</target>
<target>csoport hivatkozáson keresztül</target>
<note>chat list item description</note>
</trans-unit>
<trans-unit id="via one-time link" xml:space="preserve">
<source>via one-time link</source>
<target>egy egyszer használatos hivatkozáson keresztül</target>
<target>egyszer használatos hivatkozáson keresztül</target>
<note>chat list item description</note>
</trans-unit>
<trans-unit id="via relay" xml:space="preserve">
@@ -8768,7 +8754,7 @@ utoljára fogadott üzenet: %2$@</target>
</trans-unit>
<trans-unit id="you blocked %@" xml:space="preserve">
<source>you blocked %@</source>
<target>ön letiltotta őt: %@</target>
<target>ön letiltotta %@-t</target>
<note>snd group event chat item</note>
</trans-unit>
<trans-unit id="you changed address" xml:space="preserve">
@@ -1024,10 +1024,6 @@
<target>Auto-accetta immagini</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Auto-accept settings" xml:space="preserve">
<source>Auto-accept settings</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Back" xml:space="preserve">
<source>Back</source>
<target>Indietro</target>
@@ -1201,7 +1197,7 @@
<trans-unit id="Cancel" xml:space="preserve">
<source>Cancel</source>
<target>Annulla</target>
<note>alert button</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Cancel migration" xml:space="preserve">
<source>Cancel migration</source>
@@ -1349,10 +1345,6 @@
<target>Preferenze della chat</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Chat preferences were changed." xml:space="preserve">
<source>Chat preferences were changed.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Chat theme" xml:space="preserve">
<source>Chat theme</source>
<target>Tema della chat</target>
@@ -2878,10 +2870,6 @@ Questo è il tuo link una tantum!</target>
<target>Errore nel caricamento dei server %@</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error migrating settings" xml:space="preserve">
<source>Error migrating settings</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error opening chat" xml:space="preserve">
<source>Error opening chat</source>
<target>Errore di apertura della chat</target>
@@ -3321,6 +3309,11 @@ Errore: %2$@</target>
<target>Nome completo (facoltativo)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Full name:" xml:space="preserve">
<source>Full name:</source>
<target>Nome completo:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Fully decentralized visible only to members." xml:space="preserve">
<source>Fully decentralized visible only to members.</source>
<target>Completamente decentralizzato: visibile solo ai membri.</target>
@@ -5052,6 +5045,16 @@ Errore: %@</target>
<target>Immagini del profilo</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile name" xml:space="preserve">
<source>Profile name</source>
<target>Nome del profilo</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile name:" xml:space="preserve">
<source>Profile name:</source>
<target>Nome del profilo:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile password" xml:space="preserve">
<source>Profile password</source>
<target>Password del profilo</target>
@@ -5375,10 +5378,6 @@ Attivalo nelle impostazioni *Rete e server*.</target>
<target>Rimuovi</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Remove archive?" xml:space="preserve">
<source>Remove archive?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Remove image" xml:space="preserve">
<source>Remove image</source>
<target>Rimuovi immagine</target>
@@ -5572,13 +5571,12 @@ Attivalo nelle impostazioni *Rete e server*.</target>
<trans-unit id="Save" xml:space="preserve">
<source>Save</source>
<target>Salva</target>
<note>alert button
chat item action</note>
<note>chat item action</note>
</trans-unit>
<trans-unit id="Save (and notify contacts)" xml:space="preserve">
<source>Save (and notify contacts)</source>
<target>Salva (e avvisa i contatti)</target>
<note>alert button</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save and notify contact" xml:space="preserve">
<source>Save and notify contact</source>
@@ -5605,6 +5603,11 @@ Attivalo nelle impostazioni *Rete e server*.</target>
<target>Salva archivio</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save auto-accept settings" xml:space="preserve">
<source>Save auto-accept settings</source>
<target>Salva le impostazioni di accettazione automatica</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save group profile" xml:space="preserve">
<source>Save group profile</source>
<target>Salva il profilo del gruppo</target>
@@ -5640,15 +5643,16 @@ Attivalo nelle impostazioni *Rete e server*.</target>
<target>Salvare i server?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save settings?" xml:space="preserve">
<source>Save settings?</source>
<target>Salvare le impostazioni?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save welcome message?" xml:space="preserve">
<source>Save welcome message?</source>
<target>Salvare il messaggio di benvenuto?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save your profile?" xml:space="preserve">
<source>Save your profile?</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Saved" xml:space="preserve">
<source>Saved</source>
<target>Salvato</target>
@@ -6088,10 +6092,6 @@ Attivalo nelle impostazioni *Rete e server*.</target>
<target>Impostazioni</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Settings were changed." xml:space="preserve">
<source>Settings were changed.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Shape profile images" xml:space="preserve">
<source>Shape profile images</source>
<target>Forma delle immagini del profilo</target>
@@ -6296,10 +6296,6 @@ Attivalo nelle impostazioni *Rete e server*.</target>
<target>Leggera</target>
<note>blur media</note>
</trans-unit>
<trans-unit id="Some app settings were not migrated." xml:space="preserve">
<source>Some app settings were not migrated.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Some file(s) were not exported:" xml:space="preserve">
<source>Some file(s) were not exported:</source>
<target>Alcuni file non sono stati esportati:</target>
@@ -6671,10 +6667,6 @@ Può accadere a causa di qualche bug o quando la connessione è compromessa.</ta
<target>Il testo che hai incollato non è un link SimpleX.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The uploaded database archive will be permanently removed from the servers." xml:space="preserve">
<source>The uploaded database archive will be permanently removed from the servers.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Themes" xml:space="preserve">
<source>Themes</source>
<target>Temi</target>
@@ -7758,10 +7750,6 @@ Ripetere la richiesta di connessione?</target>
<target>Il tuo database della chat non è crittografato: imposta la password per crittografarlo.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your chat preferences" xml:space="preserve">
<source>Your chat preferences</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Your chat profiles" xml:space="preserve">
<source>Your chat profiles</source>
<target>I tuoi profili di chat</target>
@@ -7816,15 +7804,13 @@ Ripetere la richiesta di connessione?</target>
<target>Verrà condiviso il tuo profilo **%@**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source>
<target>Il tuo profilo è memorizzato sul tuo dispositivo e condiviso solo con i tuoi contatti. I server di SimpleX non possono vedere il tuo profilo.</target>
<trans-unit id="Your profile is stored on your device and shared only with your contacts.&#10;SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts.
SimpleX servers cannot see your profile.</source>
<target>Il tuo profilo è memorizzato sul tuo dispositivo e condiviso solo con i tuoi contatti.
I server di SimpleX non possono vedere il tuo profilo.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile was changed. If you save it, the updated profile will be sent to all your contacts." xml:space="preserve">
<source>Your profile was changed. If you save it, the updated profile will be sent to all your contacts.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>Il tuo profilo, i contatti e i messaggi recapitati sono memorizzati sul tuo dispositivo.</target>
@@ -994,10 +994,6 @@
<target>画像を自動的に受信</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Auto-accept settings" xml:space="preserve">
<source>Auto-accept settings</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Back" xml:space="preserve">
<source>Back</source>
<target>戻る</target>
@@ -1152,7 +1148,7 @@
<trans-unit id="Cancel" xml:space="preserve">
<source>Cancel</source>
<target>中止</target>
<note>alert button</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Cancel migration" xml:space="preserve">
<source>Cancel migration</source>
@@ -1291,10 +1287,6 @@
<target>チャット設定</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Chat preferences were changed." xml:space="preserve">
<source>Chat preferences were changed.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Chat theme" xml:space="preserve">
<source>Chat theme</source>
<note>No comment provided by engineer.</note>
@@ -2718,10 +2710,6 @@ This is your own one-time link!</source>
<target>%@ サーバーのロード中にエラーが発生</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error migrating settings" xml:space="preserve">
<source>Error migrating settings</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error opening chat" xml:space="preserve">
<source>Error opening chat</source>
<note>No comment provided by engineer.</note>
@@ -3126,6 +3114,11 @@ Error: %2$@</source>
<target>フルネーム (任意)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Full name:" xml:space="preserve">
<source>Full name:</source>
<target>フルネーム:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Fully decentralized visible only to members." xml:space="preserve">
<source>Fully decentralized visible only to members.</source>
<note>No comment provided by engineer.</note>
@@ -4750,6 +4743,14 @@ Error: %@</source>
<source>Profile images</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile name" xml:space="preserve">
<source>Profile name</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile name:" xml:space="preserve">
<source>Profile name:</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile password" xml:space="preserve">
<source>Profile password</source>
<target>プロフィールのパスワード</target>
@@ -5050,10 +5051,6 @@ Enable in *Network &amp; servers* settings.</source>
<target>削除</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Remove archive?" xml:space="preserve">
<source>Remove archive?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Remove image" xml:space="preserve">
<source>Remove image</source>
<note>No comment provided by engineer.</note>
@@ -5232,13 +5229,12 @@ Enable in *Network &amp; servers* settings.</source>
<trans-unit id="Save" xml:space="preserve">
<source>Save</source>
<target>保存</target>
<note>alert button
chat item action</note>
<note>chat item action</note>
</trans-unit>
<trans-unit id="Save (and notify contacts)" xml:space="preserve">
<source>Save (and notify contacts)</source>
<target>保存(連絡先に通知)</target>
<note>alert button</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save and notify contact" xml:space="preserve">
<source>Save and notify contact</source>
@@ -5264,6 +5260,11 @@ Enable in *Network &amp; servers* settings.</source>
<target>アーカイブを保存</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save auto-accept settings" xml:space="preserve">
<source>Save auto-accept settings</source>
<target>自動受け入れ設定を保存する</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save group profile" xml:space="preserve">
<source>Save group profile</source>
<target>グループプロフィールの保存</target>
@@ -5299,15 +5300,16 @@ Enable in *Network &amp; servers* settings.</source>
<target>サーバを保存しますか?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save settings?" xml:space="preserve">
<source>Save settings?</source>
<target>設定を保存しますか?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save welcome message?" xml:space="preserve">
<source>Save welcome message?</source>
<target>ウェルカムメッセージを保存しますか?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save your profile?" xml:space="preserve">
<source>Save your profile?</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Saved" xml:space="preserve">
<source>Saved</source>
<note>No comment provided by engineer.</note>
@@ -5706,10 +5708,6 @@ Enable in *Network &amp; servers* settings.</source>
<target>設定</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Settings were changed." xml:space="preserve">
<source>Settings were changed.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Shape profile images" xml:space="preserve">
<source>Shape profile images</source>
<note>No comment provided by engineer.</note>
@@ -5901,10 +5899,6 @@ Enable in *Network &amp; servers* settings.</source>
<source>Soft</source>
<note>blur media</note>
</trans-unit>
<trans-unit id="Some app settings were not migrated." xml:space="preserve">
<source>Some app settings were not migrated.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Some file(s) were not exported:" xml:space="preserve">
<source>Some file(s) were not exported:</source>
<note>No comment provided by engineer.</note>
@@ -6254,10 +6248,6 @@ It can happen because of some bug or when the connection is compromised.</source
<source>The text you pasted is not a SimpleX link.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The uploaded database archive will be permanently removed from the servers." xml:space="preserve">
<source>The uploaded database archive will be permanently removed from the servers.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Themes" xml:space="preserve">
<source>Themes</source>
<note>No comment provided by engineer.</note>
@@ -7253,10 +7243,6 @@ Repeat connection request?</source>
<target>チャット データベースは暗号化されていません - 暗号化するにはパスフレーズを設定してください。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your chat preferences" xml:space="preserve">
<source>Your chat preferences</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Your chat profiles" xml:space="preserve">
<source>Your chat profiles</source>
<target>あなたのチャットプロフィール</target>
@@ -7310,15 +7296,13 @@ Repeat connection request?</source>
<target>あなたのプロファイル **%@** が共有されます。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source>
<target>プロフィールはデバイスに保存され、連絡先とのみ共有されます。 SimpleX サーバーはあなたのプロファイルを参照できません。</target>
<trans-unit id="Your profile is stored on your device and shared only with your contacts.&#10;SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts.
SimpleX servers cannot see your profile.</source>
<target>プロフィールはデバイスに保存され、連絡先とのみ共有されます。
SimpleX サーバーはあなたのプロファイルを参照できません。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile was changed. If you save it, the updated profile will be sent to all your contacts." xml:space="preserve">
<source>Your profile was changed. If you save it, the updated profile will be sent to all your contacts.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>あなたのプロフィール、連絡先、送信したメッセージがご自分の端末に保存されます。</target>
@@ -1024,10 +1024,6 @@
<target>Afbeeldingen automatisch accepteren</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Auto-accept settings" xml:space="preserve">
<source>Auto-accept settings</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Back" xml:space="preserve">
<source>Back</source>
<target>Terug</target>
@@ -1201,7 +1197,7 @@
<trans-unit id="Cancel" xml:space="preserve">
<source>Cancel</source>
<target>Annuleren</target>
<note>alert button</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Cancel migration" xml:space="preserve">
<source>Cancel migration</source>
@@ -1349,10 +1345,6 @@
<target>Gesprek voorkeuren</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Chat preferences were changed." xml:space="preserve">
<source>Chat preferences were changed.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Chat theme" xml:space="preserve">
<source>Chat theme</source>
<target>Chat thema</target>
@@ -2878,10 +2870,6 @@ Dit is uw eigen eenmalige link!</target>
<target>Fout bij het laden van %@ servers</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error migrating settings" xml:space="preserve">
<source>Error migrating settings</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error opening chat" xml:space="preserve">
<source>Error opening chat</source>
<target>Fout bij het openen van de chat</target>
@@ -3321,6 +3309,11 @@ Fout: %2$@</target>
<target>Volledige naam (optioneel)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Full name:" xml:space="preserve">
<source>Full name:</source>
<target>Volledige naam:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Fully decentralized visible only to members." xml:space="preserve">
<source>Fully decentralized visible only to members.</source>
<target>Volledig gedecentraliseerd alleen zichtbaar voor leden.</target>
@@ -5052,6 +5045,16 @@ Fout: %@</target>
<target>Profiel afbeeldingen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile name" xml:space="preserve">
<source>Profile name</source>
<target>Profielnaam</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile name:" xml:space="preserve">
<source>Profile name:</source>
<target>Profielnaam:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile password" xml:space="preserve">
<source>Profile password</source>
<target>Profiel wachtwoord</target>
@@ -5375,10 +5378,6 @@ Schakel dit in in *Netwerk en servers*-instellingen.</target>
<target>Verwijderen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Remove archive?" xml:space="preserve">
<source>Remove archive?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Remove image" xml:space="preserve">
<source>Remove image</source>
<target>Verwijder afbeelding</target>
@@ -5572,13 +5571,12 @@ Schakel dit in in *Netwerk en servers*-instellingen.</target>
<trans-unit id="Save" xml:space="preserve">
<source>Save</source>
<target>Opslaan</target>
<note>alert button
chat item action</note>
<note>chat item action</note>
</trans-unit>
<trans-unit id="Save (and notify contacts)" xml:space="preserve">
<source>Save (and notify contacts)</source>
<target>Bewaar (en informeer contacten)</target>
<note>alert button</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save and notify contact" xml:space="preserve">
<source>Save and notify contact</source>
@@ -5605,6 +5603,11 @@ Schakel dit in in *Netwerk en servers*-instellingen.</target>
<target>Bewaar archief</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save auto-accept settings" xml:space="preserve">
<source>Save auto-accept settings</source>
<target>Sla instellingen voor automatisch accepteren op</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save group profile" xml:space="preserve">
<source>Save group profile</source>
<target>Groep profiel opslaan</target>
@@ -5640,15 +5643,16 @@ Schakel dit in in *Netwerk en servers*-instellingen.</target>
<target>Servers opslaan?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save settings?" xml:space="preserve">
<source>Save settings?</source>
<target>Instellingen opslaan?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save welcome message?" xml:space="preserve">
<source>Save welcome message?</source>
<target>Welkom bericht opslaan?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save your profile?" xml:space="preserve">
<source>Save your profile?</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Saved" xml:space="preserve">
<source>Saved</source>
<target>Opgeslagen</target>
@@ -6088,10 +6092,6 @@ Schakel dit in in *Netwerk en servers*-instellingen.</target>
<target>Instellingen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Settings were changed." xml:space="preserve">
<source>Settings were changed.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Shape profile images" xml:space="preserve">
<source>Shape profile images</source>
<target>Vorm profiel afbeeldingen</target>
@@ -6296,10 +6296,6 @@ Schakel dit in in *Netwerk en servers*-instellingen.</target>
<target>Soft</target>
<note>blur media</note>
</trans-unit>
<trans-unit id="Some app settings were not migrated." xml:space="preserve">
<source>Some app settings were not migrated.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Some file(s) were not exported:" xml:space="preserve">
<source>Some file(s) were not exported:</source>
<target>Sommige bestanden zijn niet geëxporteerd:</target>
@@ -6671,10 +6667,6 @@ Het kan gebeuren vanwege een bug of wanneer de verbinding is aangetast.</target>
<target>De tekst die u hebt geplakt is geen SimpleX link.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The uploaded database archive will be permanently removed from the servers." xml:space="preserve">
<source>The uploaded database archive will be permanently removed from the servers.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Themes" xml:space="preserve">
<source>Themes</source>
<target>Thema's</target>
@@ -7758,10 +7750,6 @@ Verbindingsverzoek herhalen?</target>
<target>Uw chat database is niet versleuteld, stel een wachtwoord in om deze te versleutelen.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your chat preferences" xml:space="preserve">
<source>Your chat preferences</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Your chat profiles" xml:space="preserve">
<source>Your chat profiles</source>
<target>Uw chat profielen</target>
@@ -7816,15 +7804,13 @@ Verbindingsverzoek herhalen?</target>
<target>Uw profiel **%@** wordt gedeeld.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source>
<target>Uw profiel wordt op uw apparaat opgeslagen en alleen gedeeld met uw contacten. SimpleX servers kunnen uw profiel niet zien.</target>
<trans-unit id="Your profile is stored on your device and shared only with your contacts.&#10;SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts.
SimpleX servers cannot see your profile.</source>
<target>Uw profiel wordt op uw apparaat opgeslagen en alleen gedeeld met uw contacten.
SimpleX servers kunnen uw profiel niet zien.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile was changed. If you save it, the updated profile will be sent to all your contacts." xml:space="preserve">
<source>Your profile was changed. If you save it, the updated profile will be sent to all your contacts.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>Uw profiel, contacten en afgeleverde berichten worden op uw apparaat opgeslagen.</target>
@@ -1024,10 +1024,6 @@
<target>Automatyczne akceptowanie obrazów</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Auto-accept settings" xml:space="preserve">
<source>Auto-accept settings</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Back" xml:space="preserve">
<source>Back</source>
<target>Wstecz</target>
@@ -1201,7 +1197,7 @@
<trans-unit id="Cancel" xml:space="preserve">
<source>Cancel</source>
<target>Anuluj</target>
<note>alert button</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Cancel migration" xml:space="preserve">
<source>Cancel migration</source>
@@ -1349,10 +1345,6 @@
<target>Preferencje czatu</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Chat preferences were changed." xml:space="preserve">
<source>Chat preferences were changed.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Chat theme" xml:space="preserve">
<source>Chat theme</source>
<target>Motyw czatu</target>
@@ -2878,10 +2870,6 @@ To jest twój jednorazowy link!</target>
<target>Błąd ładowania %@ serwerów</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error migrating settings" xml:space="preserve">
<source>Error migrating settings</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error opening chat" xml:space="preserve">
<source>Error opening chat</source>
<target>Błąd otwierania czatu</target>
@@ -3321,6 +3309,11 @@ Błąd: %2$@</target>
<target>Pełna nazwa (opcjonalna)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Full name:" xml:space="preserve">
<source>Full name:</source>
<target>Pełna nazwa:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Fully decentralized visible only to members." xml:space="preserve">
<source>Fully decentralized visible only to members.</source>
<target>W pełni zdecentralizowana widoczna tylko dla członków.</target>
@@ -5052,6 +5045,16 @@ Błąd: %@</target>
<target>Zdjęcia profilowe</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile name" xml:space="preserve">
<source>Profile name</source>
<target>Nazwa profilu</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile name:" xml:space="preserve">
<source>Profile name:</source>
<target>Nazwa profilu:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile password" xml:space="preserve">
<source>Profile password</source>
<target>Hasło profilu</target>
@@ -5375,10 +5378,6 @@ Włącz w ustawianiach *Sieć i serwery* .</target>
<target>Usuń</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Remove archive?" xml:space="preserve">
<source>Remove archive?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Remove image" xml:space="preserve">
<source>Remove image</source>
<target>Usuń obraz</target>
@@ -5572,13 +5571,12 @@ Włącz w ustawianiach *Sieć i serwery* .</target>
<trans-unit id="Save" xml:space="preserve">
<source>Save</source>
<target>Zapisz</target>
<note>alert button
chat item action</note>
<note>chat item action</note>
</trans-unit>
<trans-unit id="Save (and notify contacts)" xml:space="preserve">
<source>Save (and notify contacts)</source>
<target>Zapisz (i powiadom kontakty)</target>
<note>alert button</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save and notify contact" xml:space="preserve">
<source>Save and notify contact</source>
@@ -5605,6 +5603,11 @@ Włącz w ustawianiach *Sieć i serwery* .</target>
<target>Zapisz archiwum</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save auto-accept settings" xml:space="preserve">
<source>Save auto-accept settings</source>
<target>Zapisz ustawienia automatycznej akceptacji</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save group profile" xml:space="preserve">
<source>Save group profile</source>
<target>Zapisz profil grupy</target>
@@ -5640,15 +5643,16 @@ Włącz w ustawianiach *Sieć i serwery* .</target>
<target>Zapisać serwery?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save settings?" xml:space="preserve">
<source>Save settings?</source>
<target>Zapisać ustawienia?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save welcome message?" xml:space="preserve">
<source>Save welcome message?</source>
<target>Zapisać wiadomość powitalną?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save your profile?" xml:space="preserve">
<source>Save your profile?</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Saved" xml:space="preserve">
<source>Saved</source>
<target>Zapisane</target>
@@ -6088,10 +6092,6 @@ Włącz w ustawianiach *Sieć i serwery* .</target>
<target>Ustawienia</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Settings were changed." xml:space="preserve">
<source>Settings were changed.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Shape profile images" xml:space="preserve">
<source>Shape profile images</source>
<target>Kształtuj obrazy profilowe</target>
@@ -6296,10 +6296,6 @@ Włącz w ustawianiach *Sieć i serwery* .</target>
<target>Łagodny</target>
<note>blur media</note>
</trans-unit>
<trans-unit id="Some app settings were not migrated." xml:space="preserve">
<source>Some app settings were not migrated.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Some file(s) were not exported:" xml:space="preserve">
<source>Some file(s) were not exported:</source>
<target>Niektóre plik(i) nie zostały wyeksportowane:</target>
@@ -6671,10 +6667,6 @@ Może się to zdarzyć z powodu jakiegoś błędu lub gdy połączenie jest skom
<target>Tekst, który wkleiłeś nie jest linkiem SimpleX.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The uploaded database archive will be permanently removed from the servers." xml:space="preserve">
<source>The uploaded database archive will be permanently removed from the servers.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Themes" xml:space="preserve">
<source>Themes</source>
<target>Motywy</target>
@@ -7758,10 +7750,6 @@ Powtórzyć prośbę połączenia?</target>
<target>Baza danych czatu nie jest szyfrowana - ustaw hasło, aby ją zaszyfrować.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your chat preferences" xml:space="preserve">
<source>Your chat preferences</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Your chat profiles" xml:space="preserve">
<source>Your chat profiles</source>
<target>Twoje profile czatu</target>
@@ -7816,15 +7804,13 @@ Powtórzyć prośbę połączenia?</target>
<target>Twój profil **%@** zostanie udostępniony.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source>
<target>Twój profil jest przechowywany na urządzeniu i udostępniany tylko Twoim kontaktom. Serwery SimpleX nie mogą zobaczyć Twojego profilu.</target>
<trans-unit id="Your profile is stored on your device and shared only with your contacts.&#10;SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts.
SimpleX servers cannot see your profile.</source>
<target>Twój profil jest przechowywany na urządzeniu i udostępniany tylko Twoim kontaktom.
Serwery SimpleX nie mogą zobaczyć Twojego profilu.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile was changed. If you save it, the updated profile will be sent to all your contacts." xml:space="preserve">
<source>Your profile was changed. If you save it, the updated profile will be sent to all your contacts.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>Twój profil, kontakty i dostarczone wiadomości są przechowywane na Twoim urządzeniu.</target>
@@ -1024,10 +1024,6 @@
<target>Автоприем изображений</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Auto-accept settings" xml:space="preserve">
<source>Auto-accept settings</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Back" xml:space="preserve">
<source>Back</source>
<target>Назад</target>
@@ -1201,7 +1197,7 @@
<trans-unit id="Cancel" xml:space="preserve">
<source>Cancel</source>
<target>Отменить</target>
<note>alert button</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Cancel migration" xml:space="preserve">
<source>Cancel migration</source>
@@ -1349,10 +1345,6 @@
<target>Предпочтения</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Chat preferences were changed." xml:space="preserve">
<source>Chat preferences were changed.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Chat theme" xml:space="preserve">
<source>Chat theme</source>
<target>Тема чата</target>
@@ -2878,10 +2870,6 @@ This is your own one-time link!</source>
<target>Ошибка загрузки %@ серверов</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error migrating settings" xml:space="preserve">
<source>Error migrating settings</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error opening chat" xml:space="preserve">
<source>Error opening chat</source>
<target>Ошибка доступа к чату</target>
@@ -3321,6 +3309,11 @@ Error: %2$@</source>
<target>Полное имя (не обязательно)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Full name:" xml:space="preserve">
<source>Full name:</source>
<target>Полное имя:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Fully decentralized visible only to members." xml:space="preserve">
<source>Fully decentralized visible only to members.</source>
<target>Группа полностью децентрализована – она видна только членам.</target>
@@ -5052,6 +5045,16 @@ Error: %@</source>
<target>Картинки профилей</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile name" xml:space="preserve">
<source>Profile name</source>
<target>Имя профиля</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile name:" xml:space="preserve">
<source>Profile name:</source>
<target>Имя профиля:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile password" xml:space="preserve">
<source>Profile password</source>
<target>Пароль профиля</target>
@@ -5375,10 +5378,6 @@ Enable in *Network &amp; servers* settings.</source>
<target>Удалить</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Remove archive?" xml:space="preserve">
<source>Remove archive?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Remove image" xml:space="preserve">
<source>Remove image</source>
<target>Удалить изображение</target>
@@ -5572,13 +5571,12 @@ Enable in *Network &amp; servers* settings.</source>
<trans-unit id="Save" xml:space="preserve">
<source>Save</source>
<target>Сохранить</target>
<note>alert button
chat item action</note>
<note>chat item action</note>
</trans-unit>
<trans-unit id="Save (and notify contacts)" xml:space="preserve">
<source>Save (and notify contacts)</source>
<target>Сохранить (и уведомить контакты)</target>
<note>alert button</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save and notify contact" xml:space="preserve">
<source>Save and notify contact</source>
@@ -5605,6 +5603,11 @@ Enable in *Network &amp; servers* settings.</source>
<target>Сохранить архив</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save auto-accept settings" xml:space="preserve">
<source>Save auto-accept settings</source>
<target>Сохранить настройки автоприема</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save group profile" xml:space="preserve">
<source>Save group profile</source>
<target>Сохранить профиль группы</target>
@@ -5640,15 +5643,16 @@ Enable in *Network &amp; servers* settings.</source>
<target>Сохранить серверы?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save settings?" xml:space="preserve">
<source>Save settings?</source>
<target>Сохранить настройки?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save welcome message?" xml:space="preserve">
<source>Save welcome message?</source>
<target>Сохранить приветственное сообщение?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save your profile?" xml:space="preserve">
<source>Save your profile?</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Saved" xml:space="preserve">
<source>Saved</source>
<target>Сохранено</target>
@@ -6088,10 +6092,6 @@ Enable in *Network &amp; servers* settings.</source>
<target>Настройки</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Settings were changed." xml:space="preserve">
<source>Settings were changed.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Shape profile images" xml:space="preserve">
<source>Shape profile images</source>
<target>Форма картинок профилей</target>
@@ -6296,10 +6296,6 @@ Enable in *Network &amp; servers* settings.</source>
<target>Слабое</target>
<note>blur media</note>
</trans-unit>
<trans-unit id="Some app settings were not migrated." xml:space="preserve">
<source>Some app settings were not migrated.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Some file(s) were not exported:" xml:space="preserve">
<source>Some file(s) were not exported:</source>
<target>Некоторые файл(ы) не были экспортированы:</target>
@@ -6671,10 +6667,6 @@ It can happen because of some bug or when the connection is compromised.</source
<target>Вставленный текст не является SimpleX-ссылкой.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The uploaded database archive will be permanently removed from the servers." xml:space="preserve">
<source>The uploaded database archive will be permanently removed from the servers.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Themes" xml:space="preserve">
<source>Themes</source>
<target>Темы</target>
@@ -7758,10 +7750,6 @@ Repeat connection request?</source>
<target>База данных НЕ зашифрована. Установите пароль, чтобы защитить Ваши данные.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your chat preferences" xml:space="preserve">
<source>Your chat preferences</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Your chat profiles" xml:space="preserve">
<source>Your chat profiles</source>
<target>Ваши профили чата</target>
@@ -7816,15 +7804,13 @@ Repeat connection request?</source>
<target>Будет отправлен Ваш профиль **%@**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source>
<target>Ваш профиль хранится на Вашем устройстве и отправляется только Вашим контактам. SimpleX серверы не могут получить доступ к Вашему профилю.</target>
<trans-unit id="Your profile is stored on your device and shared only with your contacts.&#10;SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts.
SimpleX servers cannot see your profile.</source>
<target>Ваш профиль хранится на Вашем устройстве и отправляется только Вашим контактам.
SimpleX серверы не могут получить доступ к Вашему профилю.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile was changed. If you save it, the updated profile will be sent to all your contacts." xml:space="preserve">
<source>Your profile was changed. If you save it, the updated profile will be sent to all your contacts.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>Ваш профиль, контакты и доставленные сообщения хранятся на Вашем устройстве.</target>
@@ -963,10 +963,6 @@
<target>ยอมรับภาพอัตโนมัติ</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Auto-accept settings" xml:space="preserve">
<source>Auto-accept settings</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Back" xml:space="preserve">
<source>Back</source>
<target>กลับ</target>
@@ -1120,7 +1116,7 @@
<trans-unit id="Cancel" xml:space="preserve">
<source>Cancel</source>
<target>ยกเลิก</target>
<note>alert button</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Cancel migration" xml:space="preserve">
<source>Cancel migration</source>
@@ -1259,10 +1255,6 @@
<target>ค่ากําหนดในการแชท</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Chat preferences were changed." xml:space="preserve">
<source>Chat preferences were changed.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Chat theme" xml:space="preserve">
<source>Chat theme</source>
<note>No comment provided by engineer.</note>
@@ -2678,10 +2670,6 @@ This is your own one-time link!</source>
<target>โหลดเซิร์ฟเวอร์ %@ ผิดพลาด</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error migrating settings" xml:space="preserve">
<source>Error migrating settings</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error opening chat" xml:space="preserve">
<source>Error opening chat</source>
<note>No comment provided by engineer.</note>
@@ -3086,6 +3074,11 @@ Error: %2$@</source>
<target>ชื่อเต็ม (ไม่บังคับ)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Full name:" xml:space="preserve">
<source>Full name:</source>
<target>ชื่อเต็ม:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Fully decentralized visible only to members." xml:space="preserve">
<source>Fully decentralized visible only to members.</source>
<note>No comment provided by engineer.</note>
@@ -4703,6 +4696,14 @@ Error: %@</source>
<source>Profile images</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile name" xml:space="preserve">
<source>Profile name</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile name:" xml:space="preserve">
<source>Profile name:</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile password" xml:space="preserve">
<source>Profile password</source>
<target>รหัสผ่านโปรไฟล์</target>
@@ -5002,10 +5003,6 @@ Enable in *Network &amp; servers* settings.</source>
<target>ลบ</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Remove archive?" xml:space="preserve">
<source>Remove archive?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Remove image" xml:space="preserve">
<source>Remove image</source>
<note>No comment provided by engineer.</note>
@@ -5184,13 +5181,12 @@ Enable in *Network &amp; servers* settings.</source>
<trans-unit id="Save" xml:space="preserve">
<source>Save</source>
<target>บันทึก</target>
<note>alert button
chat item action</note>
<note>chat item action</note>
</trans-unit>
<trans-unit id="Save (and notify contacts)" xml:space="preserve">
<source>Save (and notify contacts)</source>
<target>บันทึก (และแจ้งผู้ติดต่อ)</target>
<note>alert button</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save and notify contact" xml:space="preserve">
<source>Save and notify contact</source>
@@ -5216,6 +5212,11 @@ Enable in *Network &amp; servers* settings.</source>
<target>บันทึกไฟล์เก็บถาวร</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save auto-accept settings" xml:space="preserve">
<source>Save auto-accept settings</source>
<target>บันทึกการตั้งค่าการยอมรับอัตโนมัติ</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save group profile" xml:space="preserve">
<source>Save group profile</source>
<target>บันทึกโปรไฟล์กลุ่ม</target>
@@ -5251,15 +5252,16 @@ Enable in *Network &amp; servers* settings.</source>
<target>บันทึกเซิร์ฟเวอร์?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save settings?" xml:space="preserve">
<source>Save settings?</source>
<target>บันทึกการตั้งค่า?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save welcome message?" xml:space="preserve">
<source>Save welcome message?</source>
<target>บันทึกข้อความต้อนรับ?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save your profile?" xml:space="preserve">
<source>Save your profile?</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Saved" xml:space="preserve">
<source>Saved</source>
<note>No comment provided by engineer.</note>
@@ -5663,10 +5665,6 @@ Enable in *Network &amp; servers* settings.</source>
<target>การตั้งค่า</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Settings were changed." xml:space="preserve">
<source>Settings were changed.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Shape profile images" xml:space="preserve">
<source>Shape profile images</source>
<note>No comment provided by engineer.</note>
@@ -5855,10 +5853,6 @@ Enable in *Network &amp; servers* settings.</source>
<source>Soft</source>
<note>blur media</note>
</trans-unit>
<trans-unit id="Some app settings were not migrated." xml:space="preserve">
<source>Some app settings were not migrated.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Some file(s) were not exported:" xml:space="preserve">
<source>Some file(s) were not exported:</source>
<note>No comment provided by engineer.</note>
@@ -6209,10 +6203,6 @@ It can happen because of some bug or when the connection is compromised.</source
<source>The text you pasted is not a SimpleX link.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The uploaded database archive will be permanently removed from the servers." xml:space="preserve">
<source>The uploaded database archive will be permanently removed from the servers.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Themes" xml:space="preserve">
<source>Themes</source>
<note>No comment provided by engineer.</note>
@@ -7204,10 +7194,6 @@ Repeat connection request?</source>
<target>ฐานข้อมูลการแชทของคุณไม่ได้ถูก encrypt - ตั้งรหัสผ่านเพื่อ encrypt</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your chat preferences" xml:space="preserve">
<source>Your chat preferences</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Your chat profiles" xml:space="preserve">
<source>Your chat profiles</source>
<target>โปรไฟล์แชทของคุณ</target>
@@ -7260,15 +7246,13 @@ Repeat connection request?</source>
<source>Your profile **%@** will be shared.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source>
<target>โปรไฟล์ของคุณจะถูกจัดเก็บไว้ในอุปกรณ์ของคุณและแชร์กับผู้ติดต่อของคุณเท่านั้น เซิร์ฟเวอร์ SimpleX ไม่สามารถดูโปรไฟล์ของคุณได้</target>
<trans-unit id="Your profile is stored on your device and shared only with your contacts.&#10;SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts.
SimpleX servers cannot see your profile.</source>
<target>โปรไฟล์ของคุณจะถูกจัดเก็บไว้ในอุปกรณ์ของคุณและแชร์กับผู้ติดต่อของคุณเท่านั้น
เซิร์ฟเวอร์ SimpleX ไม่สามารถดูโปรไฟล์ของคุณได้</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile was changed. If you save it, the updated profile will be sent to all your contacts." xml:space="preserve">
<source>Your profile was changed. If you save it, the updated profile will be sent to all your contacts.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>โปรไฟล์ รายชื่อผู้ติดต่อ และข้อความที่ส่งของคุณจะถูกจัดเก็บไว้ในอุปกรณ์ของคุณ</target>
@@ -1009,10 +1009,6 @@
<target>Fotoğrafları otomatik kabul et</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Auto-accept settings" xml:space="preserve">
<source>Auto-accept settings</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Back" xml:space="preserve">
<source>Back</source>
<target>Geri</target>
@@ -1177,7 +1173,7 @@
<trans-unit id="Cancel" xml:space="preserve">
<source>Cancel</source>
<target>İptal et</target>
<note>alert button</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Cancel migration" xml:space="preserve">
<source>Cancel migration</source>
@@ -1321,10 +1317,6 @@
<target>Sohbet tercihleri</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Chat preferences were changed." xml:space="preserve">
<source>Chat preferences were changed.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Chat theme" xml:space="preserve">
<source>Chat theme</source>
<note>No comment provided by engineer.</note>
@@ -2805,10 +2797,6 @@ Bu senin kendi tek kullanımlık bağlantın!</target>
<target>%@ sunucuları yüklenirken hata oluştu</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error migrating settings" xml:space="preserve">
<source>Error migrating settings</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error opening chat" xml:space="preserve">
<source>Error opening chat</source>
<target>Sohbeti açarken sorun oluştu</target>
@@ -3235,6 +3223,11 @@ Hata: %2$@</target>
<target>Bütün isim (opsiyonel)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Full name:" xml:space="preserve">
<source>Full name:</source>
<target>Bütün isim:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Fully decentralized visible only to members." xml:space="preserve">
<source>Fully decentralized visible only to members.</source>
<target>Tamamiyle merkezi olmayan - sadece kişilere görünür.</target>
@@ -4933,6 +4926,16 @@ Hata: %@</target>
<target>Profil resimleri</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile name" xml:space="preserve">
<source>Profile name</source>
<target>Profil ismi</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile name:" xml:space="preserve">
<source>Profile name:</source>
<target>Profil ismi:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile password" xml:space="preserve">
<source>Profile password</source>
<target>Profil parolası</target>
@@ -5243,10 +5246,6 @@ Enable in *Network &amp; servers* settings.</source>
<target>Sil</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Remove archive?" xml:space="preserve">
<source>Remove archive?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Remove image" xml:space="preserve">
<source>Remove image</source>
<note>No comment provided by engineer.</note>
@@ -5433,13 +5432,12 @@ Enable in *Network &amp; servers* settings.</source>
<trans-unit id="Save" xml:space="preserve">
<source>Save</source>
<target>Kaydet</target>
<note>alert button
chat item action</note>
<note>chat item action</note>
</trans-unit>
<trans-unit id="Save (and notify contacts)" xml:space="preserve">
<source>Save (and notify contacts)</source>
<target>Kaydet (ve kişilere bildir)</target>
<note>alert button</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save and notify contact" xml:space="preserve">
<source>Save and notify contact</source>
@@ -5465,6 +5463,11 @@ Enable in *Network &amp; servers* settings.</source>
<target>Arşivi kaydet</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save auto-accept settings" xml:space="preserve">
<source>Save auto-accept settings</source>
<target>Otomatik kabul et ayarlarını kaydet</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save group profile" xml:space="preserve">
<source>Save group profile</source>
<target>Grup profilini kaydet</target>
@@ -5500,15 +5503,16 @@ Enable in *Network &amp; servers* settings.</source>
<target>Sunucular kaydedilsin mi?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save settings?" xml:space="preserve">
<source>Save settings?</source>
<target>Ayarlar kaydedilsin mi?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save welcome message?" xml:space="preserve">
<source>Save welcome message?</source>
<target>Hoşgeldin mesajı kaydedilsin mi?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save your profile?" xml:space="preserve">
<source>Save your profile?</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Saved" xml:space="preserve">
<source>Saved</source>
<target>Kaydedildi</target>
@@ -5928,10 +5932,6 @@ Enable in *Network &amp; servers* settings.</source>
<target>Ayarlar</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Settings were changed." xml:space="preserve">
<source>Settings were changed.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Shape profile images" xml:space="preserve">
<source>Shape profile images</source>
<target>Profil resimlerini şekillendir</target>
@@ -6130,10 +6130,6 @@ Enable in *Network &amp; servers* settings.</source>
<source>Soft</source>
<note>blur media</note>
</trans-unit>
<trans-unit id="Some app settings were not migrated." xml:space="preserve">
<source>Some app settings were not migrated.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Some file(s) were not exported:" xml:space="preserve">
<source>Some file(s) were not exported:</source>
<note>No comment provided by engineer.</note>
@@ -6493,10 +6489,6 @@ Bazı hatalar nedeniyle veya bağlantı tehlikeye girdiğinde meydana gelebilir.
<target>Yapıştırdığın metin bir SimpleX bağlantısı değildir.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The uploaded database archive will be permanently removed from the servers." xml:space="preserve">
<source>The uploaded database archive will be permanently removed from the servers.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Themes" xml:space="preserve">
<source>Themes</source>
<note>No comment provided by engineer.</note>
@@ -7556,10 +7548,6 @@ Bağlantı isteği tekrarlansın mı?</target>
<target>Sohbet veritabanınız şifrelenmemiş - şifrelemek için parola ayarlayın.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your chat preferences" xml:space="preserve">
<source>Your chat preferences</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Your chat profiles" xml:space="preserve">
<source>Your chat profiles</source>
<target>Sohbet profillerin</target>
@@ -7614,15 +7602,13 @@ Bağlantı isteği tekrarlansın mı?</target>
<target>Profiliniz **%@** paylaşılacaktır.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source>
<target>Profiliniz cihazınızda saklanır ve sadece kişilerinizle paylaşılır. SimpleX sunucuları profilinizi göremez.</target>
<trans-unit id="Your profile is stored on your device and shared only with your contacts.&#10;SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts.
SimpleX servers cannot see your profile.</source>
<target>Profiliniz cihazınızda saklanır ve sadece kişilerinizle paylaşılır.
SimpleX sunucuları profilinizi göremez.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile was changed. If you save it, the updated profile will be sent to all your contacts." xml:space="preserve">
<source>Your profile was changed. If you save it, the updated profile will be sent to all your contacts.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>Profiliniz, kişileriniz ve gönderilmiş mesajlar cihazınızda saklanır.</target>
@@ -1024,10 +1024,6 @@
<target>Автоматичне прийняття зображень</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Auto-accept settings" xml:space="preserve">
<source>Auto-accept settings</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Back" xml:space="preserve">
<source>Back</source>
<target>Назад</target>
@@ -1201,7 +1197,7 @@
<trans-unit id="Cancel" xml:space="preserve">
<source>Cancel</source>
<target>Скасувати</target>
<note>alert button</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Cancel migration" xml:space="preserve">
<source>Cancel migration</source>
@@ -1349,10 +1345,6 @@
<target>Налаштування чату</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Chat preferences were changed." xml:space="preserve">
<source>Chat preferences were changed.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Chat theme" xml:space="preserve">
<source>Chat theme</source>
<target>Тема чату</target>
@@ -2878,10 +2870,6 @@ This is your own one-time link!</source>
<target>Помилка завантаження %@ серверів</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error migrating settings" xml:space="preserve">
<source>Error migrating settings</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error opening chat" xml:space="preserve">
<source>Error opening chat</source>
<target>Помилка відкриття чату</target>
@@ -3321,6 +3309,11 @@ Error: %2$@</source>
<target>Повне ім'я (необов'язково)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Full name:" xml:space="preserve">
<source>Full name:</source>
<target>Повне ім'я:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Fully decentralized visible only to members." xml:space="preserve">
<source>Fully decentralized visible only to members.</source>
<target>Повністю децентралізована - видима лише для учасників.</target>
@@ -5052,6 +5045,16 @@ Error: %@</source>
<target>Зображення профілю</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile name" xml:space="preserve">
<source>Profile name</source>
<target>Назва профілю</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile name:" xml:space="preserve">
<source>Profile name:</source>
<target>Ім'я профілю:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile password" xml:space="preserve">
<source>Profile password</source>
<target>Пароль до профілю</target>
@@ -5375,10 +5378,6 @@ Enable in *Network &amp; servers* settings.</source>
<target>Видалити</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Remove archive?" xml:space="preserve">
<source>Remove archive?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Remove image" xml:space="preserve">
<source>Remove image</source>
<target>Видалити зображення</target>
@@ -5572,13 +5571,12 @@ Enable in *Network &amp; servers* settings.</source>
<trans-unit id="Save" xml:space="preserve">
<source>Save</source>
<target>Зберегти</target>
<note>alert button
chat item action</note>
<note>chat item action</note>
</trans-unit>
<trans-unit id="Save (and notify contacts)" xml:space="preserve">
<source>Save (and notify contacts)</source>
<target>Зберегти (і повідомити контактам)</target>
<note>alert button</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save and notify contact" xml:space="preserve">
<source>Save and notify contact</source>
@@ -5605,6 +5603,11 @@ Enable in *Network &amp; servers* settings.</source>
<target>Зберегти архів</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save auto-accept settings" xml:space="preserve">
<source>Save auto-accept settings</source>
<target>Зберегти налаштування автоприйому</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save group profile" xml:space="preserve">
<source>Save group profile</source>
<target>Зберегти профіль групи</target>
@@ -5640,15 +5643,16 @@ Enable in *Network &amp; servers* settings.</source>
<target>Зберегти сервери?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save settings?" xml:space="preserve">
<source>Save settings?</source>
<target>Зберегти налаштування?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save welcome message?" xml:space="preserve">
<source>Save welcome message?</source>
<target>Зберегти вітальне повідомлення?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save your profile?" xml:space="preserve">
<source>Save your profile?</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Saved" xml:space="preserve">
<source>Saved</source>
<target>Збережено</target>
@@ -6088,10 +6092,6 @@ Enable in *Network &amp; servers* settings.</source>
<target>Налаштування</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Settings were changed." xml:space="preserve">
<source>Settings were changed.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Shape profile images" xml:space="preserve">
<source>Shape profile images</source>
<target>Сформуйте зображення профілю</target>
@@ -6296,10 +6296,6 @@ Enable in *Network &amp; servers* settings.</source>
<target>М'який</target>
<note>blur media</note>
</trans-unit>
<trans-unit id="Some app settings were not migrated." xml:space="preserve">
<source>Some app settings were not migrated.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Some file(s) were not exported:" xml:space="preserve">
<source>Some file(s) were not exported:</source>
<target>Деякі файли не було експортовано:</target>
@@ -6671,10 +6667,6 @@ It can happen because of some bug or when the connection is compromised.</source
<target>Текст, який ви вставили, не є посиланням SimpleX.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The uploaded database archive will be permanently removed from the servers." xml:space="preserve">
<source>The uploaded database archive will be permanently removed from the servers.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Themes" xml:space="preserve">
<source>Themes</source>
<target>Теми</target>
@@ -7758,10 +7750,6 @@ Repeat connection request?</source>
<target>Ваша база даних чату не зашифрована - встановіть ключову фразу, щоб зашифрувати її.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your chat preferences" xml:space="preserve">
<source>Your chat preferences</source>
<note>alert title</note>
</trans-unit>
<trans-unit id="Your chat profiles" xml:space="preserve">
<source>Your chat profiles</source>
<target>Ваші профілі чату</target>
@@ -7816,15 +7804,13 @@ Repeat connection request?</source>
<target>Ваш профіль **%@** буде опублікований.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source>
<target>Ваш профіль зберігається на вашому пристрої і доступний лише вашим контактам. Сервери SimpleX не бачать ваш профіль.</target>
<trans-unit id="Your profile is stored on your device and shared only with your contacts.&#10;SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts.
SimpleX servers cannot see your profile.</source>
<target>Ваш профіль зберігається на вашому пристрої і доступний лише вашим контактам.
Сервери SimpleX не бачать ваш профіль.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile was changed. If you save it, the updated profile will be sent to all your contacts." xml:space="preserve">
<source>Your profile was changed. If you save it, the updated profile will be sent to all your contacts.</source>
<note>alert message</note>
</trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>Ваш профіль, контакти та доставлені повідомлення зберігаються на вашому пристрої.</target>
File diff suppressed because it is too large Load Diff
+2 -3
View File
@@ -104,7 +104,7 @@ class ShareModel: ObservableObject {
// Decode base64 images on background thread
let profileImages = chats.reduce(into: Dictionary<ChatInfo.ID, UIImage>()) { dict, chatData in
if let profileImage = chatData.chatInfo.image,
let uiImage = imageFromBase64(profileImage) {
let uiImage = UIImage(base64Encoded: profileImage) {
dict[chatData.id] = uiImage
}
}
@@ -320,8 +320,7 @@ class ShareModel: ObservableObject {
}
await ch.completeFile()
if await !ch.isRunning { break }
case let .chatItemsStatusesUpdated(_, chatItems):
guard let ci = chatItems.last else { continue }
case let .chatItemStatusUpdated(_, ci):
guard isMessage(for: ci) else { continue }
if let (title, message) = ci.chatItem.meta.itemStatus.statusInfo {
// `title` and `message` already localized and interpolated
+3 -3
View File
@@ -147,8 +147,8 @@ struct ShareView: View {
}
}
@ViewBuilder private func imagePreview(_ imgStr: String) -> some View {
if let img = imageFromBase64(imgStr) {
@ViewBuilder private func imagePreview(_ img: String) -> some View {
if let img = UIImage(base64Encoded: img) {
previewArea {
Image(uiImage: img)
.resizable()
@@ -163,7 +163,7 @@ struct ShareView: View {
@ViewBuilder private func linkPreview(_ linkPreview: LinkPreview) -> some View {
previewArea {
HStack(alignment: .center, spacing: 8) {
if let uiImage = imageFromBase64(linkPreview.image) {
if let uiImage = UIImage(base64Encoded: linkPreview.image) {
Image(uiImage: uiImage)
.resizable()
.aspectRatio(contentMode: .fit)
@@ -1,9 +1,7 @@
/* Bundle display name */
"CFBundleDisplayName" = "SimpleX SE";
/* Bundle name */
"CFBundleName" = "SimpleX SE";
/* Copyright (human-readable) */
"NSHumanReadableCopyright" = "版权所有 © 2024 SimpleX Chat。保留所有权利。";
/*
InfoPlist.strings
SimpleX
Created by EP on 30/07/2024.
Copyright © 2024 SimpleX Chat. All rights reserved.
*/
@@ -1,111 +1,7 @@
/* No comment provided by engineer. */
"%@" = "%@";
/* No comment provided by engineer. */
"App is locked!" = "应用程序已锁定!";
/* No comment provided by engineer. */
"Cancel" = "取消";
/* No comment provided by engineer. */
"Cannot access keychain to save database password" = "无法访问钥匙串以保存数据库密码";
/* No comment provided by engineer. */
"Cannot forward message" = "无法转发消息";
/* No comment provided by engineer. */
"Comment" = "评论";
/* No comment provided by engineer. */
"Currently maximum supported file size is %@." = "当前支持的最大文件大小为 %@。";
/* No comment provided by engineer. */
"Database downgrade required" = "需要数据库降级";
/* No comment provided by engineer. */
"Database encrypted!" = "数据库已加密!";
/* No comment provided by engineer. */
"Database error" = "数据库错误";
/* No comment provided by engineer. */
"Database passphrase is different from saved in the keychain." = "数据库密码与保存在钥匙串中的密码不同。";
/* No comment provided by engineer. */
"Database passphrase is required to open chat." = "需要数据库密码才能打开聊天。";
/* No comment provided by engineer. */
"Database upgrade required" = "需要升级数据库";
/* No comment provided by engineer. */
"Error preparing file" = "准备文件时出错";
/* No comment provided by engineer. */
"Error preparing message" = "准备消息时出错";
/* No comment provided by engineer. */
"Error: %@" = "错误:%@";
/* No comment provided by engineer. */
"File error" = "文件错误";
/* No comment provided by engineer. */
"Incompatible database version" = "不兼容的数据库版本";
/* No comment provided by engineer. */
"Invalid migration confirmation" = "无效的迁移确认";
/* No comment provided by engineer. */
"Keychain error" = "钥匙串错误";
/* No comment provided by engineer. */
"Large file!" = "大文件!";
/* No comment provided by engineer. */
"No active profile" = "无活动配置文件";
/* No comment provided by engineer. */
"Ok" = "好的";
/* No comment provided by engineer. */
"Open the app to downgrade the database." = "打开应用程序以降级数据库。";
/* No comment provided by engineer. */
"Open the app to upgrade the database." = "打开应用程序以升级数据库。";
/* No comment provided by engineer. */
"Passphrase" = "密码";
/* No comment provided by engineer. */
"Please create a profile in the SimpleX app" = "请在 SimpleX 应用程序中创建配置文件";
/* No comment provided by engineer. */
"Selected chat preferences prohibit this message." = "选定的聊天首选项禁止此消息。";
/* No comment provided by engineer. */
"Sending a message takes longer than expected." = "发送消息所需的时间比预期的要长。";
/* No comment provided by engineer. */
"Sending message…" = "正在发送消息…";
/* No comment provided by engineer. */
"Share" = "共享";
/* No comment provided by engineer. */
"Slow network?" = "网络速度慢?";
/* No comment provided by engineer. */
"Unknown database error: %@" = "未知数据库错误: %@";
/* No comment provided by engineer. */
"Unsupported format" = "不支持的格式";
/* No comment provided by engineer. */
"Wait" = "等待";
/* No comment provided by engineer. */
"Wrong database passphrase" = "数据库密码错误";
/* No comment provided by engineer. */
"You can allow sharing in Privacy & Security / SimpleX Lock settings." = "您可以在 \"隐私与安全\"/\"SimpleX Lock \"设置中允许共享。";
/*
Localizable.strings
SimpleX
Created by EP on 30/07/2024.
Copyright © 2024 SimpleX Chat. All rights reserved.
*/
+40 -56
View File
@@ -177,8 +177,6 @@
64E972072881BB22008DBC02 /* CIGroupInvitationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64E972062881BB22008DBC02 /* CIGroupInvitationView.swift */; };
64EEB0F72C353F1C00972D62 /* ServersSummaryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64EEB0F62C353F1C00972D62 /* ServersSummaryView.swift */; };
64F1CC3B28B39D8600CD1FB1 /* IncognitoHelp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64F1CC3A28B39D8600CD1FB1 /* IncognitoHelp.swift */; };
8C01E9C12C8EFC33008A4B0A /* objc.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C01E9C02C8EFC33008A4B0A /* objc.m */; };
8C01E9C22C8EFF8F008A4B0A /* objc.h in Headers */ = {isa = PBXBuildFile; fileRef = 8C01E9BF2C8EFBB6008A4B0A /* objc.h */; };
8C69FE7D2B8C7D2700267E38 /* AppSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C69FE7C2B8C7D2700267E38 /* AppSettings.swift */; };
8C74C3E52C1B900600039E77 /* ThemeTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C7E3CE32C0DEAC400BFF63A /* ThemeTypes.swift */; };
8C74C3E72C1B901900039E77 /* Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C852B072C1086D100BA61E8 /* Color.swift */; };
@@ -196,7 +194,6 @@
8CC956EE2BC0041000412A11 /* NetworkObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CC956ED2BC0041000412A11 /* NetworkObserver.swift */; };
8CE848A32C5A0FA000D5C7C8 /* SelectableChatItemToolbars.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CE848A22C5A0FA000D5C7C8 /* SelectableChatItemToolbars.swift */; };
B76E6C312C5C41D900EC11AA /* ContactListNavLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = B76E6C302C5C41D900EC11AA /* ContactListNavLink.swift */; };
CE176F202C87014C00145DBC /* InvertedForegroundStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE176F1F2C87014C00145DBC /* InvertedForegroundStyle.swift */; };
CE1EB0E42C459A660099D896 /* ShareAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE1EB0E32C459A660099D896 /* ShareAPI.swift */; };
CE2AD9CE2C452A4D00E844E3 /* ChatUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE2AD9CD2C452A4D00E844E3 /* ChatUtils.swift */; };
CE3097FB2C4C0C9F00180898 /* ErrorAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE3097FA2C4C0C9F00180898 /* ErrorAlert.swift */; };
@@ -204,7 +201,6 @@
CE38A29C2C3FCD72005ED185 /* SwiftyGif in Frameworks */ = {isa = PBXBuildFile; productRef = CE38A29B2C3FCD72005ED185 /* SwiftyGif */; };
CE75480A2C622630009579B7 /* SwipeLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE7548092C622630009579B7 /* SwipeLabel.swift */; };
CE984D4B2C36C5D500E3AEFF /* ChatItemClipShape.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE984D4A2C36C5D500E3AEFF /* ChatItemClipShape.swift */; };
CEA034032C9C0F1800B587E7 /* TranslateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEA034022C9C0F1800B587E7 /* TranslateView.swift */; };
CEDE70222C48FD9500233B1F /* SEChatState.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEDE70212C48FD9500233B1F /* SEChatState.swift */; };
CEE723AA2C3BD3D70009AE93 /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEE723A92C3BD3D70009AE93 /* ShareViewController.swift */; };
CEE723B12C3BD3D70009AE93 /* SimpleX SE.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = CEE723A72C3BD3D70009AE93 /* SimpleX SE.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
@@ -218,11 +214,11 @@
D77B92DC2952372200A5A1CC /* SwiftyGif in Frameworks */ = {isa = PBXBuildFile; productRef = D77B92DB2952372200A5A1CC /* SwiftyGif */; };
D7F0E33929964E7E0068AF69 /* LZString in Frameworks */ = {isa = PBXBuildFile; productRef = D7F0E33829964E7E0068AF69 /* LZString */; };
E51CC1E62C62085600DB91FE /* OneHandUICard.swift in Sources */ = {isa = PBXBuildFile; fileRef = E51CC1E52C62085600DB91FE /* OneHandUICard.swift */; };
E55128E72C9AD063001D165C /* libHSsimplex-chat-6.1.0.2-ItgztLmvKyzFsOmChHMkFt.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E55128E22C9AD063001D165C /* libHSsimplex-chat-6.1.0.2-ItgztLmvKyzFsOmChHMkFt.a */; };
E55128E82C9AD063001D165C /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E55128E32C9AD063001D165C /* libgmp.a */; };
E55128E92C9AD063001D165C /* libHSsimplex-chat-6.1.0.2-ItgztLmvKyzFsOmChHMkFt-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E55128E42C9AD063001D165C /* libHSsimplex-chat-6.1.0.2-ItgztLmvKyzFsOmChHMkFt-ghc9.6.3.a */; };
E55128EA2C9AD063001D165C /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E55128E52C9AD063001D165C /* libgmpxx.a */; };
E55128EB2C9AD063001D165C /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E55128E62C9AD063001D165C /* libffi.a */; };
E5BD84572C832BF9008C24D1 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E5BD84522C832BF9008C24D1 /* libgmpxx.a */; };
E5BD84582C832BF9008C24D1 /* libHSsimplex-chat-6.1.0.0-1tXK6wuT4H71iMwoWdPa4N.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E5BD84532C832BF9008C24D1 /* libHSsimplex-chat-6.1.0.0-1tXK6wuT4H71iMwoWdPa4N.a */; };
E5BD84592C832BF9008C24D1 /* libHSsimplex-chat-6.1.0.0-1tXK6wuT4H71iMwoWdPa4N-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E5BD84542C832BF9008C24D1 /* libHSsimplex-chat-6.1.0.0-1tXK6wuT4H71iMwoWdPa4N-ghc9.6.3.a */; };
E5BD845A2C832BF9008C24D1 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E5BD84552C832BF9008C24D1 /* libgmp.a */; };
E5BD845B2C832BF9008C24D1 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E5BD84562C832BF9008C24D1 /* libffi.a */; };
E5DCF8DB2C56FAC1007928CC /* SimpleXChat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE2BA682845308900EC33A6 /* SimpleXChat.framework */; };
E5DCF9712C590272007928CC /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = E5DCF96F2C590272007928CC /* Localizable.strings */; };
E5DCF9842C5902CE007928CC /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = E5DCF9822C5902CE007928CC /* Localizable.strings */; };
@@ -520,8 +516,6 @@
64E972062881BB22008DBC02 /* CIGroupInvitationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIGroupInvitationView.swift; sourceTree = "<group>"; };
64EEB0F62C353F1C00972D62 /* ServersSummaryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServersSummaryView.swift; sourceTree = "<group>"; };
64F1CC3A28B39D8600CD1FB1 /* IncognitoHelp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IncognitoHelp.swift; sourceTree = "<group>"; };
8C01E9BF2C8EFBB6008A4B0A /* objc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = objc.h; sourceTree = "<group>"; };
8C01E9C02C8EFC33008A4B0A /* objc.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = objc.m; sourceTree = "<group>"; };
8C69FE7C2B8C7D2700267E38 /* AppSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppSettings.swift; sourceTree = "<group>"; };
8C74C3EB2C1B92A900039E77 /* Theme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = "<group>"; };
8C74C3ED2C1B942300039E77 /* ChatWallpaper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatWallpaper.swift; sourceTree = "<group>"; };
@@ -538,13 +532,11 @@
8CC956ED2BC0041000412A11 /* NetworkObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkObserver.swift; sourceTree = "<group>"; };
8CE848A22C5A0FA000D5C7C8 /* SelectableChatItemToolbars.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectableChatItemToolbars.swift; sourceTree = "<group>"; };
B76E6C302C5C41D900EC11AA /* ContactListNavLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactListNavLink.swift; sourceTree = "<group>"; };
CE176F1F2C87014C00145DBC /* InvertedForegroundStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InvertedForegroundStyle.swift; sourceTree = "<group>"; };
CE1EB0E32C459A660099D896 /* ShareAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareAPI.swift; sourceTree = "<group>"; };
CE2AD9CD2C452A4D00E844E3 /* ChatUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatUtils.swift; sourceTree = "<group>"; };
CE3097FA2C4C0C9F00180898 /* ErrorAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorAlert.swift; sourceTree = "<group>"; };
CE7548092C622630009579B7 /* SwipeLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwipeLabel.swift; sourceTree = "<group>"; };
CE984D4A2C36C5D500E3AEFF /* ChatItemClipShape.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatItemClipShape.swift; sourceTree = "<group>"; };
CEA034022C9C0F1800B587E7 /* TranslateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TranslateView.swift; sourceTree = "<group>"; };
CEDE70212C48FD9500233B1F /* SEChatState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SEChatState.swift; sourceTree = "<group>"; };
CEE723A72C3BD3D70009AE93 /* SimpleX SE.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "SimpleX SE.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
CEE723A92C3BD3D70009AE93 /* ShareViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareViewController.swift; sourceTree = "<group>"; };
@@ -558,11 +550,11 @@
D741547929AF90B00022400A /* PushKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PushKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS16.1.sdk/System/Library/Frameworks/PushKit.framework; sourceTree = DEVELOPER_DIR; };
D7AA2C3429A936B400737B40 /* MediaEncryption.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; name = MediaEncryption.playground; path = Shared/MediaEncryption.playground; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
E51CC1E52C62085600DB91FE /* OneHandUICard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OneHandUICard.swift; sourceTree = "<group>"; };
E55128E22C9AD063001D165C /* libHSsimplex-chat-6.1.0.2-ItgztLmvKyzFsOmChHMkFt.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.1.0.2-ItgztLmvKyzFsOmChHMkFt.a"; sourceTree = "<group>"; };
E55128E32C9AD063001D165C /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = "<group>"; };
E55128E42C9AD063001D165C /* libHSsimplex-chat-6.1.0.2-ItgztLmvKyzFsOmChHMkFt-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.1.0.2-ItgztLmvKyzFsOmChHMkFt-ghc9.6.3.a"; sourceTree = "<group>"; };
E55128E52C9AD063001D165C /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = "<group>"; };
E55128E62C9AD063001D165C /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = "<group>"; };
E5BD84522C832BF9008C24D1 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = "<group>"; };
E5BD84532C832BF9008C24D1 /* libHSsimplex-chat-6.1.0.0-1tXK6wuT4H71iMwoWdPa4N.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.1.0.0-1tXK6wuT4H71iMwoWdPa4N.a"; sourceTree = "<group>"; };
E5BD84542C832BF9008C24D1 /* libHSsimplex-chat-6.1.0.0-1tXK6wuT4H71iMwoWdPa4N-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.1.0.0-1tXK6wuT4H71iMwoWdPa4N-ghc9.6.3.a"; sourceTree = "<group>"; };
E5BD84552C832BF9008C24D1 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = "<group>"; };
E5BD84562C832BF9008C24D1 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = "<group>"; };
E5DCF9702C590272007928CC /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
E5DCF9722C590274007928CC /* bg */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bg; path = bg.lproj/Localizable.strings; sourceTree = "<group>"; };
E5DCF9732C590275007928CC /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
@@ -653,14 +645,14 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
E55128E72C9AD063001D165C /* libHSsimplex-chat-6.1.0.2-ItgztLmvKyzFsOmChHMkFt.a in Frameworks */,
E55128E82C9AD063001D165C /* libgmp.a in Frameworks */,
E5BD84572C832BF9008C24D1 /* libgmpxx.a in Frameworks */,
E5BD845A2C832BF9008C24D1 /* libgmp.a in Frameworks */,
5CE2BA93284534B000EC33A6 /* libiconv.tbd in Frameworks */,
E55128EB2C9AD063001D165C /* libffi.a in Frameworks */,
E5BD845B2C832BF9008C24D1 /* libffi.a in Frameworks */,
E5BD84582C832BF9008C24D1 /* libHSsimplex-chat-6.1.0.0-1tXK6wuT4H71iMwoWdPa4N.a in Frameworks */,
E5BD84592C832BF9008C24D1 /* libHSsimplex-chat-6.1.0.0-1tXK6wuT4H71iMwoWdPa4N-ghc9.6.3.a in Frameworks */,
5CE2BA94284534BB00EC33A6 /* libz.tbd in Frameworks */,
E55128E92C9AD063001D165C /* libHSsimplex-chat-6.1.0.2-ItgztLmvKyzFsOmChHMkFt-ghc9.6.3.a in Frameworks */,
CE38A29C2C3FCD72005ED185 /* SwiftyGif in Frameworks */,
E55128EA2C9AD063001D165C /* libgmpxx.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -729,7 +721,6 @@
5CBE6C132944CC12002D9531 /* ScanCodeView.swift */,
64C06EB42A0A4A7C00792D4D /* ChatItemInfoView.swift */,
648679AA2BC96A74006456E7 /* ChatItemForwardingView.swift */,
CEA034022C9C0F1800B587E7 /* TranslateView.swift */,
8CE848A22C5A0FA000D5C7C8 /* SelectableChatItemToolbars.swift */,
);
path = Chat;
@@ -738,11 +729,11 @@
5C764E5C279C70B7000C6508 /* Libraries */ = {
isa = PBXGroup;
children = (
E55128E62C9AD063001D165C /* libffi.a */,
E55128E32C9AD063001D165C /* libgmp.a */,
E55128E52C9AD063001D165C /* libgmpxx.a */,
E55128E42C9AD063001D165C /* libHSsimplex-chat-6.1.0.2-ItgztLmvKyzFsOmChHMkFt-ghc9.6.3.a */,
E55128E22C9AD063001D165C /* libHSsimplex-chat-6.1.0.2-ItgztLmvKyzFsOmChHMkFt.a */,
E5BD84562C832BF9008C24D1 /* libffi.a */,
E5BD84552C832BF9008C24D1 /* libgmp.a */,
E5BD84522C832BF9008C24D1 /* libgmpxx.a */,
E5BD84542C832BF9008C24D1 /* libHSsimplex-chat-6.1.0.0-1tXK6wuT4H71iMwoWdPa4N-ghc9.6.3.a */,
E5BD84532C832BF9008C24D1 /* libHSsimplex-chat-6.1.0.0-1tXK6wuT4H71iMwoWdPa4N.a */,
);
path = Libraries;
sourceTree = "<group>";
@@ -798,7 +789,6 @@
8C9BC2642C240D5100875A27 /* ThemeModeEditor.swift */,
CE984D4A2C36C5D500E3AEFF /* ChatItemClipShape.swift */,
CE7548092C622630009579B7 /* SwipeLabel.swift */,
CE176F1F2C87014C00145DBC /* InvertedForegroundStyle.swift */,
);
path = Helpers;
sourceTree = "<group>";
@@ -986,8 +976,6 @@
5CE2BA96284537A800EC33A6 /* dummy.m */,
5CD67B8D2B0E858A00C510B1 /* hs_init.h */,
5CD67B8E2B0E858A00C510B1 /* hs_init.c */,
8C01E9BF2C8EFBB6008A4B0A /* objc.h */,
8C01E9C02C8EFC33008A4B0A /* objc.m */,
);
path = SimpleXChat;
sourceTree = "<group>";
@@ -1125,7 +1113,6 @@
files = (
5CE2BA77284530BF00EC33A6 /* SimpleXChat.h in Headers */,
5CD67B8F2B0E858A00C510B1 /* hs_init.h in Headers */,
8C01E9C22C8EFF8F008A4B0A /* objc.h in Headers */,
5CE2BA952845354B00EC33A6 /* SimpleX.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -1396,7 +1383,6 @@
5CB634A829E437960066AD6B /* PasscodeEntry.swift in Sources */,
5CFA59C42860BC6200863A68 /* MigrateToAppGroupView.swift in Sources */,
648010AB281ADD15009009B9 /* CIFileView.swift in Sources */,
CEA034032C9C0F1800B587E7 /* TranslateView.swift in Sources */,
644EFFE2292D089800525D5B /* FramedCIVoiceView.swift in Sources */,
5C4B3B0A285FB130003915F2 /* DatabaseView.swift in Sources */,
5CB2084F28DA4B4800D024EC /* RTCServers.swift in Sources */,
@@ -1503,7 +1489,6 @@
5C9CC7A928C532AB00BEF955 /* DatabaseErrorView.swift in Sources */,
5C1A4C1E27A715B700EAD5AD /* ChatItemView.swift in Sources */,
64AA1C6927EE10C800AC7277 /* ContextItemView.swift in Sources */,
CE176F202C87014C00145DBC /* InvertedForegroundStyle.swift in Sources */,
5CEBD7482A5F115D00665FE2 /* SetDeliveryReceiptsView.swift in Sources */,
5C9C2DA7289957AE00CC63B1 /* AdvancedNetworkSettings.swift in Sources */,
5CADE79A29211BB900072E13 /* PreferencesView.swift in Sources */,
@@ -1554,7 +1539,6 @@
8C74C3E72C1B901900039E77 /* Color.swift in Sources */,
5CD67B902B0E858A00C510B1 /* hs_init.c in Sources */,
5CE2BA91284533A300EC33A6 /* Notifications.swift in Sources */,
8C01E9C12C8EFC33008A4B0A /* objc.m in Sources */,
5CE2BA79284530CC00EC33A6 /* SimpleXChat.docc in Sources */,
5CE2BA90284533A300EC33A6 /* JSON.swift in Sources */,
5CE2BA8B284533A300EC33A6 /* ChatTypes.swift in Sources */,
@@ -1895,7 +1879,7 @@
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 237;
CURRENT_PROJECT_VERSION = 236;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
@@ -1920,7 +1904,7 @@
"@executable_path/Frameworks",
);
LLVM_LTO = YES_THIN;
MARKETING_VERSION = 6.1;
MARKETING_VERSION = 6.0.4;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app;
PRODUCT_NAME = SimpleX;
SDKROOT = iphoneos;
@@ -1944,7 +1928,7 @@
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 237;
CURRENT_PROJECT_VERSION = 236;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
@@ -1969,7 +1953,7 @@
"@executable_path/Frameworks",
);
LLVM_LTO = YES;
MARKETING_VERSION = 6.1;
MARKETING_VERSION = 6.0.4;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app;
PRODUCT_NAME = SimpleX;
SDKROOT = iphoneos;
@@ -1985,11 +1969,11 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 237;
CURRENT_PROJECT_VERSION = 236;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
MARKETING_VERSION = 6.1;
MARKETING_VERSION = 6.0.4;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.Tests-iOS";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
@@ -2005,11 +1989,11 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 237;
CURRENT_PROJECT_VERSION = 236;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
MARKETING_VERSION = 6.1;
MARKETING_VERSION = 6.0.4;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.Tests-iOS";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
@@ -2030,7 +2014,7 @@
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 237;
CURRENT_PROJECT_VERSION = 236;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
GCC_OPTIMIZATION_LEVEL = s;
@@ -2045,7 +2029,7 @@
"@executable_path/../../Frameworks",
);
LLVM_LTO = YES;
MARKETING_VERSION = 6.1;
MARKETING_VERSION = 6.0.4;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -2067,7 +2051,7 @@
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 237;
CURRENT_PROJECT_VERSION = 236;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
ENABLE_CODE_COVERAGE = NO;
@@ -2082,7 +2066,7 @@
"@executable_path/../../Frameworks",
);
LLVM_LTO = YES;
MARKETING_VERSION = 6.1;
MARKETING_VERSION = 6.0.4;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -2104,7 +2088,7 @@
CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES;
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 237;
CURRENT_PROJECT_VERSION = 236;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
DYLIB_COMPATIBILITY_VERSION = 1;
@@ -2130,7 +2114,7 @@
"$(PROJECT_DIR)/Libraries/sim",
);
LLVM_LTO = YES;
MARKETING_VERSION = 6.1;
MARKETING_VERSION = 6.0.4;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SDKROOT = iphoneos;
@@ -2155,7 +2139,7 @@
CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES;
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 237;
CURRENT_PROJECT_VERSION = 236;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
DYLIB_COMPATIBILITY_VERSION = 1;
@@ -2181,7 +2165,7 @@
"$(PROJECT_DIR)/Libraries/sim",
);
LLVM_LTO = YES;
MARKETING_VERSION = 6.1;
MARKETING_VERSION = 6.0.4;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SDKROOT = iphoneos;
@@ -2206,7 +2190,7 @@
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CODE_SIGN_ENTITLEMENTS = "SimpleX SE/SimpleX SE.entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 237;
CURRENT_PROJECT_VERSION = 236;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
@@ -2221,7 +2205,7 @@
"@executable_path/../../Frameworks",
);
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MARKETING_VERSION = 6.1;
MARKETING_VERSION = 6.0.4;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-SE";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
@@ -2240,7 +2224,7 @@
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CODE_SIGN_ENTITLEMENTS = "SimpleX SE/SimpleX SE.entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 237;
CURRENT_PROJECT_VERSION = 236;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
@@ -2255,7 +2239,7 @@
"@executable_path/../../Frameworks",
);
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MARKETING_VERSION = 6.1;
MARKETING_VERSION = 6.0.4;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-SE";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
+2 -54
View File
@@ -177,66 +177,14 @@ public func fromCString(_ c: UnsafeMutablePointer<CChar>) -> String {
return s
}
// TODO: Remove after XCode 16 crash has been resolved/merged
class ThreadExecutor<ResultType> {
private var stackSize: Int
private var qos: QualityOfService
/// Initialize by specifying the stack size
init(stackSize: Int, qos: QualityOfService) {
self.stackSize = stackSize
self.qos = qos
}
/// Execute a closure synchronously on a separate thread and return the result
func executeSync(_ task: @escaping () throws -> ResultType) throws -> ResultType {
// Initialize the semaphore (initially locked)
let semaphore = DispatchSemaphore(value: 0)
var result: Result<ResultType, Error>?
// Initialize the thread
let thread = Thread {
do {
let taskResult = try task()
result = .success(taskResult)
} catch {
result = .failure(error)
}
// Release the semaphore when the task is completed
semaphore.signal()
}
thread.stackSize = stackSize
thread.qualityOfService = qos
thread.start()
// Wait until the thread completes
semaphore.wait()
// Return the result
switch result! {
case .success(let result):
return result
case .failure(let error):
throw error
}
}
}
public func chatResponse(_ s: String) -> ChatResponse {
let d = s.data(using: .utf8)!
// TODO is there a way to do it without copying the data? e.g:
// let p = UnsafeMutableRawPointer.init(mutating: UnsafeRawPointer(cjson))
// let d = Data.init(bytesNoCopy: p, count: strlen(cjson), deallocator: .free)
do {
let executor = ThreadExecutor<APIResponse>(
stackSize: 2*1024*1024, // 2MiB
qos: Thread.current.qualityOfService // inherit priority
)
return try executor.executeSync {
try jsonDecoder.decode(APIResponse.self, from: d)
}.resp
let r = try jsonDecoder.decode(APIResponse.self, from: d)
return r.resp
} catch {
logger.error("chatResponse jsonDecoder.decode error: \(error.localizedDescription)")
}
+5 -91
View File
@@ -8,7 +8,6 @@
import Foundation
import SwiftUI
import Network
public let jsonDecoder = getJSONDecoder()
public let jsonEncoder = getJSONEncoder()
@@ -49,7 +48,6 @@ public enum ChatCommand {
case apiDeleteChatItem(type: ChatType, id: Int64, itemIds: [Int64], mode: CIDeleteMode)
case apiDeleteMemberChatItem(groupId: Int64, itemIds: [Int64])
case apiChatItemReaction(type: ChatType, id: Int64, itemId: Int64, add: Bool, reaction: MsgReaction)
case apiPlanForwardChatItems(toChatType: ChatType, toChatId: Int64, itemIds: [Int64])
case apiForwardChatItems(toChatType: ChatType, toChatId: Int64, fromChatType: ChatType, fromChatId: Int64, itemIds: [Int64], ttl: Int?)
case apiGetNtfToken
case apiRegisterToken(token: DeviceToken, notificationMode: NotificationsMode)
@@ -131,7 +129,6 @@ public enum ChatCommand {
// WebRTC calls /
case apiGetNetworkStatuses
case apiChatRead(type: ChatType, id: Int64, itemRange: (Int64, Int64))
case apiChatItemsRead(type: ChatType, id: Int64, itemIds: [Int64])
case apiChatUnread(type: ChatType, id: Int64, unreadChat: Bool)
case receiveFile(fileId: Int64, userApprovedRelays: Bool, encrypted: Bool?, inline: Bool?)
case setFileToReceive(fileId: Int64, userApprovedRelays: Bool, encrypted: Bool?)
@@ -205,7 +202,6 @@ public enum ChatCommand {
case let .apiDeleteChatItem(type, id, itemIds, mode): return "/_delete item \(ref(type, id)) \(itemIds.map({ "\($0)" }).joined(separator: ",")) \(mode.rawValue)"
case let .apiDeleteMemberChatItem(groupId, itemIds): return "/_delete member item #\(groupId) \(itemIds.map({ "\($0)" }).joined(separator: ","))"
case let .apiChatItemReaction(type, id, itemId, add, reaction): return "/_reaction \(ref(type, id)) \(itemId) \(onOff(add)) \(encodeJSON(reaction))"
case let .apiPlanForwardChatItems(type, id, itemIds): return "/_forward plan \(ref(type, id)) \(itemIds.map({ "\($0)" }).joined(separator: ","))"
case let .apiForwardChatItems(toChatType, toChatId, fromChatType, fromChatId, itemIds, ttl):
let ttlStr = ttl != nil ? "\(ttl!)" : "default"
return "/_forward \(ref(toChatType, toChatId)) \(ref(fromChatType, fromChatId)) \(itemIds.map({ "\($0)" }).joined(separator: ",")) ttl=\(ttlStr)"
@@ -297,7 +293,6 @@ public enum ChatCommand {
case let .apiCallStatus(contact, callStatus): return "/_call status @\(contact.apiId) \(callStatus.rawValue)"
case .apiGetNetworkStatuses: return "/_network_statuses"
case let .apiChatRead(type, id, itemRange: (from, to)): return "/_read chat \(ref(type, id)) from=\(from) to=\(to)"
case let .apiChatItemsRead(type, id, itemIds): return "/_read chat items \(ref(type, id)) \(joinedIds(itemIds))"
case let .apiChatUnread(type, id, unreadChat): return "/_unread chat \(ref(type, id)) \(onOff(unreadChat))"
case let .receiveFile(fileId, userApprovedRelays, encrypt, inline): return "/freceive \(fileId)\(onOffParam("approved_relays", userApprovedRelays))\(onOffParam("encrypt", encrypt))\(onOffParam("inline", inline))"
case let .setFileToReceive(fileId, userApprovedRelays, encrypt): return "/_set_file_to_receive \(fileId)\(onOffParam("approved_relays", userApprovedRelays))\(onOffParam("encrypt", encrypt))"
@@ -361,7 +356,6 @@ public enum ChatCommand {
case .apiConnectContactViaAddress: return "apiConnectContactViaAddress"
case .apiDeleteMemberChatItem: return "apiDeleteMemberChatItem"
case .apiChatItemReaction: return "apiChatItemReaction"
case .apiPlanForwardChatItems: return "apiPlanForwardChatItems"
case .apiForwardChatItems: return "apiForwardChatItems"
case .apiGetNtfToken: return "apiGetNtfToken"
case .apiRegisterToken: return "apiRegisterToken"
@@ -440,7 +434,6 @@ public enum ChatCommand {
case .apiCallStatus: return "apiCallStatus"
case .apiGetNetworkStatuses: return "apiGetNetworkStatuses"
case .apiChatRead: return "apiChatRead"
case .apiChatItemsRead: return "apiChatItemsRead"
case .apiChatUnread: return "apiChatUnread"
case .receiveFile: return "receiveFile"
case .setFileToReceive: return "setFileToReceive"
@@ -469,10 +462,6 @@ public enum ChatCommand {
"\(type.rawValue)\(id)"
}
func joinedIds(_ ids: [Int64]) -> String {
ids.map { "\($0)" }.joined(separator: ",")
}
func protoServersStr(_ servers: [ServerCfg]) -> String {
encodeJSON(ProtoServersConfig(servers: servers))
}
@@ -604,8 +593,7 @@ public enum ChatResponse: Decodable, Error {
case groupEmpty(user: UserRef, groupInfo: GroupInfo)
case userContactLinkSubscribed
case newChatItems(user: UserRef, chatItems: [AChatItem])
case forwardPlan(user: UserRef, chatItemIds: [Int64], forwardConfirmation: ForwardConfirmation?)
case chatItemsStatusesUpdated(user: UserRef, chatItems: [AChatItem])
case chatItemStatusUpdated(user: UserRef, chatItem: AChatItem)
case chatItemUpdated(user: UserRef, chatItem: AChatItem)
case chatItemNotChanged(user: UserRef, chatItem: AChatItem)
case chatItemReaction(user: UserRef, added: Bool, reaction: ACIReaction)
@@ -776,8 +764,7 @@ public enum ChatResponse: Decodable, Error {
case .groupEmpty: return "groupEmpty"
case .userContactLinkSubscribed: return "userContactLinkSubscribed"
case .newChatItems: return "newChatItems"
case .forwardPlan: return "forwardPlan"
case .chatItemsStatusesUpdated: return "chatItemsStatusesUpdated"
case .chatItemStatusUpdated: return "chatItemStatusUpdated"
case .chatItemUpdated: return "chatItemUpdated"
case .chatItemNotChanged: return "chatItemNotChanged"
case .chatItemReaction: return "chatItemReaction"
@@ -948,10 +935,7 @@ public enum ChatResponse: Decodable, Error {
case let .newChatItems(u, chatItems):
let itemsString = chatItems.map { chatItem in String(describing: chatItem) }.joined(separator: "\n")
return withUser(u, itemsString)
case let .forwardPlan(u, chatItemIds, forwardConfirmation): return withUser(u, "items: \(chatItemIds) forwardConfirmation: \(String(describing: forwardConfirmation))")
case let .chatItemsStatusesUpdated(u, chatItems):
let itemsString = chatItems.map { chatItem in String(describing: chatItem) }.joined(separator: "\n")
return withUser(u, itemsString)
case let .chatItemStatusUpdated(u, chatItem): return withUser(u, String(describing: chatItem))
case let .chatItemUpdated(u, chatItem): return withUser(u, String(describing: chatItem))
case let .chatItemNotChanged(u, chatItem): return withUser(u, String(describing: chatItem))
case let .chatItemReaction(u, added, reaction): return withUser(u, "added: \(added)\n\(String(describing: reaction))")
@@ -1140,7 +1124,7 @@ public enum ChatPagination {
public struct ComposedMessage: Encodable {
public var fileSource: CryptoFile?
var quotedItemId: Int64?
public var msgContent: MsgContent
var msgContent: MsgContent
public init(fileSource: CryptoFile? = nil, quotedItemId: Int64? = nil, msgContent: MsgContent) {
self.fileSource = fileSource
@@ -1506,63 +1490,6 @@ public struct KeepAliveOpts: Codable, Equatable {
public static let defaults: KeepAliveOpts = KeepAliveOpts(keepIdle: 30, keepIntvl: 15, keepCnt: 4)
}
public struct NetworkProxy: Equatable, Codable {
public var host: String = ""
public var port: Int = 0
public var auth: NetworkProxyAuth = .username
public var username: String = ""
public var password: String = ""
public static var def: NetworkProxy {
NetworkProxy()
}
public var valid: Bool {
let hostOk = switch NWEndpoint.Host(host) {
case .ipv4: true
case .ipv6: true
default: false
}
return hostOk &&
port > 0 && port <= 65535 &&
NetworkProxy.validCredential(username) && NetworkProxy.validCredential(password)
}
public static func validCredential(_ s: String) -> Bool {
!s.contains(":") && !s.contains("@")
}
public func toProxyString() -> String? {
if !valid { return nil }
var res = ""
switch auth {
case .username:
let usernameTrimmed = username.trimmingCharacters(in: .whitespaces)
let passwordTrimmed = password.trimmingCharacters(in: .whitespaces)
if usernameTrimmed != "" || passwordTrimmed != "" {
res += usernameTrimmed + ":" + passwordTrimmed + "@"
} else {
res += "@"
}
case .isolate: ()
}
if host != "" {
if host.contains(":") {
res += "[\(host.trimmingCharacters(in: [" ", "[", "]"]))]"
} else {
res += host.trimmingCharacters(in: .whitespaces)
}
}
res += ":\(port)"
return res
}
}
public enum NetworkProxyAuth: String, Codable {
case username
case isolate
}
public enum NetworkStatus: Decodable, Equatable {
case unknown
case connected
@@ -1601,13 +1528,6 @@ public enum NetworkStatus: Decodable, Equatable {
}
}
public enum ForwardConfirmation: Decodable, Hashable {
case filesNotAccepted(fileIds: [Int64])
case filesInProgress(filesCount: Int)
case filesMissing(filesCount: Int)
case filesFailed(filesCount: Int)
}
public struct ConnNetworkStatus: Decodable {
public var agentConnId: String
public var networkStatus: NetworkStatus
@@ -2193,13 +2113,11 @@ public struct MigrationFileLinkData: Codable {
public struct NetworkConfig: Codable {
let socksProxy: String?
let networkProxy: NetworkProxy?
let hostMode: HostMode?
let requiredHostMode: Bool?
public init(socksProxy: String?, networkProxy: NetworkProxy?, hostMode: HostMode?, requiredHostMode: Bool?) {
public init(socksProxy: String?, hostMode: HostMode?, requiredHostMode: Bool?) {
self.socksProxy = socksProxy
self.networkProxy = networkProxy
self.hostMode = hostMode
self.requiredHostMode = requiredHostMode
}
@@ -2208,7 +2126,6 @@ public struct MigrationFileLinkData: Codable {
return if let hostMode, let requiredHostMode {
NetworkConfig(
socksProxy: nil,
networkProxy: nil,
hostMode: hostMode == .onionViaSocks ? .onionHost : hostMode,
requiredHostMode: requiredHostMode
)
@@ -2228,7 +2145,6 @@ public struct MigrationFileLinkData: Codable {
public struct AppSettings: Codable, Equatable {
public var networkConfig: NetCfg? = nil
public var networkProxy: NetworkProxy? = nil
public var privacyEncryptLocalFiles: Bool? = nil
public var privacyAskToApproveRelays: Bool? = nil
public var privacyAcceptImages: Bool? = nil
@@ -2260,7 +2176,6 @@ public struct AppSettings: Codable, Equatable {
var empty = AppSettings()
let def = AppSettings.defaults
if networkConfig != def.networkConfig { empty.networkConfig = networkConfig }
if networkProxy != def.networkProxy { empty.networkProxy = networkProxy }
if privacyEncryptLocalFiles != def.privacyEncryptLocalFiles { empty.privacyEncryptLocalFiles = privacyEncryptLocalFiles }
if privacyAskToApproveRelays != def.privacyAskToApproveRelays { empty.privacyAskToApproveRelays = privacyAskToApproveRelays }
if privacyAcceptImages != def.privacyAcceptImages { empty.privacyAcceptImages = privacyAcceptImages }
@@ -2293,7 +2208,6 @@ public struct AppSettings: Codable, Equatable {
public static var defaults: AppSettings {
AppSettings (
networkConfig: NetCfg.defaults,
networkProxy: NetworkProxy.def,
privacyEncryptLocalFiles: true,
privacyAskToApproveRelays: true,
privacyAcceptImages: true,
+1 -6
View File
@@ -35,7 +35,6 @@ public let GROUP_DEFAULT_PRIVACY_ASK_TO_APPROVE_RELAYS = "privacyAskToApproveRel
// replaces DEFAULT_PROFILE_IMAGE_CORNER_RADIUS
public let GROUP_DEFAULT_PROFILE_IMAGE_CORNER_RADIUS = "profileImageCornerRadius"
let GROUP_DEFAULT_NTF_BADGE_COUNT = "ntgBadgeCount"
public let GROUP_DEFAULT_NETWORK_SOCKS_PROXY = "networkSocksProxy"
let GROUP_DEFAULT_NETWORK_USE_ONION_HOSTS = "networkUseOnionHosts"
let GROUP_DEFAULT_NETWORK_SESSION_MODE = "networkSessionMode"
let GROUP_DEFAULT_NETWORK_SMP_PROXY_MODE = "networkSMPProxyMode"
@@ -328,7 +327,6 @@ public class Default<T> {
}
public func getNetCfg() -> NetCfg {
let socksProxy = groupDefaults.string(forKey: GROUP_DEFAULT_NETWORK_SOCKS_PROXY)
let onionHosts = networkUseOnionHostsGroupDefault.get()
let (hostMode, requiredHostMode) = onionHosts.hostMode
let sessionMode = networkSessionModeGroupDefault.get()
@@ -351,7 +349,6 @@ public func getNetCfg() -> NetCfg {
tcpKeepAlive = nil
}
return NetCfg(
socksProxy: socksProxy,
hostMode: hostMode,
requiredHostMode: requiredHostMode,
sessionMode: sessionMode,
@@ -368,13 +365,11 @@ public func getNetCfg() -> NetCfg {
)
}
public func setNetCfg(_ cfg: NetCfg, networkProxy: NetworkProxy?) {
public func setNetCfg(_ cfg: NetCfg) {
networkUseOnionHostsGroupDefault.set(OnionHosts(netCfg: cfg))
networkSessionModeGroupDefault.set(cfg.sessionMode)
networkSMPProxyModeGroupDefault.set(cfg.smpProxyMode)
networkSMPProxyFallbackGroupDefault.set(cfg.smpProxyFallback)
let socksProxy = networkProxy?.toProxyString()
groupDefaults.set(socksProxy, forKey: GROUP_DEFAULT_NETWORK_SOCKS_PROXY)
groupDefaults.set(cfg.tcpConnectTimeout, forKey: GROUP_DEFAULT_NETWORK_TCP_CONNECT_TIMEOUT)
groupDefaults.set(cfg.tcpTimeout, forKey: GROUP_DEFAULT_NETWORK_TCP_TIMEOUT)
groupDefaults.set(cfg.tcpTimeoutPerKb, forKey: GROUP_DEFAULT_NETWORK_TCP_TIMEOUT_PER_KB)
+14 -43
View File
@@ -2713,7 +2713,7 @@ public struct CIMeta: Decodable, Hashable {
public var deletable: Bool
public var editable: Bool
public var timestampText: Text { Text(formatTimestampMeta(itemTs)) }
public var timestampText: Text { get { formatTimestampText(itemTs) } }
public var recent: Bool { updatedAt + 10 > .now }
public var isLive: Bool { itemLive == true }
public var disappearing: Bool { !isRcvNew && itemTimed?.deleteAt != nil }
@@ -2761,30 +2761,8 @@ public struct CITimed: Decodable, Hashable {
public var deleteAt: Date?
}
let msgTimeFormat = Date.FormatStyle.dateTime.hour().minute()
let msgDateFormat = Date.FormatStyle.dateTime.day(.twoDigits).month(.twoDigits)
public func formatTimestampText(_ date: Date) -> Text {
Text(verbatim: date.formatted(recent(date) ? msgTimeFormat : msgDateFormat))
}
public func formatTimestampMeta(_ date: Date) -> String {
date.formatted(date: .omitted, time: .shortened)
}
private func recent(_ date: Date) -> Bool {
let now = Date()
let calendar = Calendar.current
guard let previousDay = calendar.date(byAdding: DateComponents(day: -1), to: now),
let previousDay18 = calendar.date(bySettingHour: 18, minute: 0, second: 0, of: previousDay),
let currentDay00 = calendar.date(bySettingHour: 0, minute: 0, second: 0, of: now),
let currentDay12 = calendar.date(bySettingHour: 12, minute: 0, second: 0, of: now) else {
return false
}
let isSameDay = calendar.isDate(date, inSameDayAs: now)
return isSameDay || (now < currentDay12 && date >= previousDay18 && date < currentDay00)
Text(verbatim: date.formatted(date: .omitted, time: .shortened))
}
public enum CIStatus: Decodable, Hashable {
@@ -2812,14 +2790,13 @@ public enum CIStatus: Decodable, Hashable {
}
}
public func statusIcon(_ metaColor: Color, _ paleMetaColor: Color, _ primaryColor: Color = .accentColor) -> (Image, Color)? {
public func statusIcon(_ metaColor: Color, _ primaryColor: Color = .accentColor) -> (Image, Color)? {
switch self {
case .sndNew: nil
case let .sndSent(sndProgress):
(Image("checkmark.wide"), sndProgress == .partial ? paleMetaColor : metaColor)
case let .sndRcvd(msgRcptStatus, sndProgress):
case .sndSent: (Image("checkmark.wide"), metaColor)
case let .sndRcvd(msgRcptStatus, _):
switch msgRcptStatus {
case .ok: (Image("checkmark.2"), sndProgress == .partial ? paleMetaColor : metaColor)
case .ok: (Image("checkmark.2"), metaColor)
case .badMsgHash: (Image("checkmark.2"), .red)
}
case .sndErrorAuth: (Image(systemName: "multiply"), .red)
@@ -2831,6 +2808,14 @@ public enum CIStatus: Decodable, Hashable {
}
}
public var sndProgress: SndCIStatusProgress? {
switch self {
case let .sndSent(sndProgress): sndProgress
case let .sndRcvd(_ , sndProgress): sndProgress
default: nil
}
}
public var statusInfo: (String, String)? {
switch self {
case .sndNew: return nil
@@ -2856,13 +2841,6 @@ public enum CIStatus: Decodable, Hashable {
)
}
}
public var isSndRcvd: Bool {
switch self {
case .sndRcvd: return true
default: return false
}
}
}
public enum SndError: Decodable, Hashable {
@@ -3159,13 +3137,6 @@ public enum CIContent: Decodable, ItemContent, Hashable {
default: return false
}
}
public var isSndCall: Bool {
switch self {
case .sndCall: return true
default: return false
}
}
}
public enum MsgDecryptError: String, Decodable, Hashable {
+3 -21
View File
@@ -383,34 +383,16 @@ extension UIImage {
}
return self
}
}
public func imageFromBase64(_ base64Encoded: String?) -> UIImage? {
if let base64Encoded {
if let img = imageCache.object(forKey: base64Encoded as NSString) {
return img
} else if let data = Data(base64Encoded: dropImagePrefix(base64Encoded)),
let img = UIImage(data: data) {
imageCacheQueue.async {
imageCache.setObject(img, forKey: base64Encoded as NSString)
}
return img
public convenience init?(base64Encoded: String?) {
if let base64Encoded, let data = Data(base64Encoded: dropImagePrefix(base64Encoded)) {
self.init(data: data)
} else {
return nil
}
} else {
return nil
}
}
private let imageCacheQueue = DispatchQueue.global(qos: .background)
private var imageCache: NSCache<NSString, UIImage> = {
var cache = NSCache<NSString, UIImage>()
cache.countLimit = 1000
return cache
}()
public func getLinkPreview(url: URL, cb: @escaping (LinkPreview?) -> Void) {
logger.debug("getLinkMetadata: fetching URL preview")
LPMetadataProvider().startFetchingMetadata(for: url){ metadata, error in
-1
View File
@@ -10,7 +10,6 @@
#define SimpleX_h
#include "hs_init.h"
#include "objc.h"
extern void hs_init(int argc, char **argv[]);
-20
View File
@@ -1,20 +0,0 @@
//
// objc.h
// SimpleX (iOS)
//
// Created by Stanislav Dmitrenko on 09.09.2024.
// Copyright © 2024 SimpleX Chat. All rights reserved.
//
#ifndef objc_h
#define objc_h
#import <Foundation/Foundation.h>
@interface ObjC : NSObject
+ (BOOL)catchException:(void(^)(void))tryBlock error:(__autoreleasing NSError **)error;
@end
#endif /* objc_h */
-25
View File
@@ -1,25 +0,0 @@
//
// objc.m
// SimpleXChat
//
// Created by Stanislav Dmitrenko on 09.09.2024.
// Copyright © 2024 SimpleX Chat. All rights reserved.
//
#import "objc.h"
@implementation ObjC
// https://stackoverflow.com/a/36454808
+ (BOOL)catchException:(void(^)(void))tryBlock error:(__autoreleasing NSError **)error {
@try {
tryBlock();
return YES;
}
@catch (NSException *exception) {
*error = [[NSError alloc] initWithDomain: exception.name code: 0 userInfo: exception.userInfo];
return NO;
}
}
@end
+19 -5
View File
@@ -697,7 +697,7 @@
/* No comment provided by engineer. */
"Can't invite contacts!" = "Не може да поканят контактите!";
/* alert button */
/* No comment provided by engineer. */
"Cancel" = "Отказ";
/* No comment provided by engineer. */
@@ -1897,6 +1897,9 @@
/* No comment provided by engineer. */
"Full name (optional)" = "Пълно име (незадължително)";
/* No comment provided by engineer. */
"Full name:" = "Пълно име:";
/* No comment provided by engineer. */
"Fully decentralized visible only to members." = "Напълно децентрализирана – видима е само за членовете.";
@@ -2937,6 +2940,12 @@
/* No comment provided by engineer. */
"Profile images" = "Профилни изображения";
/* No comment provided by engineer. */
"Profile name" = "Име на профила";
/* No comment provided by engineer. */
"Profile name:" = "Име на профила:";
/* No comment provided by engineer. */
"Profile password" = "Профилна парола";
@@ -3202,11 +3211,10 @@
/* No comment provided by engineer. */
"Safer groups" = "По-безопасни групи";
/* alert button
chat item action */
/* chat item action */
"Save" = "Запази";
/* alert button */
/* No comment provided by engineer. */
"Save (and notify contacts)" = "Запази (и уведоми контактите)";
/* No comment provided by engineer. */
@@ -3221,6 +3229,9 @@
/* No comment provided by engineer. */
"Save archive" = "Запази архив";
/* No comment provided by engineer. */
"Save auto-accept settings" = "Запази настройките за автоматично приемане";
/* No comment provided by engineer. */
"Save group profile" = "Запази профила на групата";
@@ -3242,6 +3253,9 @@
/* No comment provided by engineer. */
"Save servers?" = "Запази сървърите?";
/* No comment provided by engineer. */
"Save settings?" = "Запази настройките?";
/* No comment provided by engineer. */
"Save welcome message?" = "Запази съобщението при посрещане?";
@@ -4416,7 +4430,7 @@
"Your profile **%@** will be shared." = "Вашият профил **%@** ще бъде споделен.";
/* No comment provided by engineer. */
"Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." = "Вашият профил се съхранява на вашето устройство и се споделя само с вашите контакти. SimpleX сървърите не могат да видят вашия профил.";
"Your profile is stored on your device and shared only with your contacts.\nSimpleX servers cannot see your profile." = "Вашият профил се съхранява на вашето устройство и се споделя само с вашите контакти.\nSimpleX сървърите не могат да видят вашия профил.";
/* No comment provided by engineer. */
"Your profile, contacts and delivered messages are stored on your device." = "Вашият профил, контакти и доставени съобщения се съхраняват на вашето устройство.";
+13 -5
View File
@@ -562,7 +562,7 @@
/* No comment provided by engineer. */
"Can't invite contacts!" = "Nelze pozvat kontakty!";
/* alert button */
/* No comment provided by engineer. */
"Cancel" = "Zrušit";
/* feature offered item */
@@ -1543,6 +1543,9 @@
/* No comment provided by engineer. */
"Full name (optional)" = "Celé jméno (volitelně)";
/* No comment provided by engineer. */
"Full name:" = "Celé jméno:";
/* No comment provided by engineer. */
"Fully re-implemented - work in background!" = "Plně přepracováno, prácuje na pozadí!";
@@ -2599,11 +2602,10 @@
/* No comment provided by engineer. */
"Run chat" = "Spustit chat";
/* alert button
chat item action */
/* chat item action */
"Save" = "Uložit";
/* alert button */
/* No comment provided by engineer. */
"Save (and notify contacts)" = "Uložit (a informovat kontakty)";
/* No comment provided by engineer. */
@@ -2618,6 +2620,9 @@
/* No comment provided by engineer. */
"Save archive" = "Uložit archiv";
/* No comment provided by engineer. */
"Save auto-accept settings" = "Uložit nastavení automatického přijímání";
/* No comment provided by engineer. */
"Save group profile" = "Uložení profilu skupiny";
@@ -2639,6 +2644,9 @@
/* No comment provided by engineer. */
"Save servers?" = "Uložit servery?";
/* No comment provided by engineer. */
"Save settings?" = "Uložit nastavení?";
/* No comment provided by engineer. */
"Save welcome message?" = "Uložit uvítací zprávu?";
@@ -3546,7 +3554,7 @@
"Your profile **%@** will be shared." = "Váš profil **%@** bude sdílen.";
/* No comment provided by engineer. */
"Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." = "Váš profil je uložen ve vašem zařízení a sdílen pouze s vašimi kontakty. Servery SimpleX nevidí váš profil.";
"Your profile is stored on your device and shared only with your contacts.\nSimpleX servers cannot see your profile." = "Váš profil je uložen ve vašem zařízení a sdílen pouze s vašimi kontakty.\nServery SimpleX nevidí váš profil.";
/* No comment provided by engineer. */
"Your profile, contacts and delivered messages are stored on your device." = "Váš profil, kontakty a doručené zprávy jsou uloženy ve vašem zařízení.";
+32 -18
View File
@@ -781,7 +781,7 @@
/* No comment provided by engineer. */
"Can't message member" = "Mitglied kann nicht benachrichtigt werden";
/* alert button */
/* No comment provided by engineer. */
"Cancel" = "Abbrechen";
/* No comment provided by engineer. */
@@ -921,16 +921,16 @@
"Chunks uploaded" = "Daten-Pakete hochgeladen";
/* swipe action */
"Clear" = "Entfernen";
"Clear" = "Löschen";
/* No comment provided by engineer. */
"Clear conversation" = "Chat-Inhalte entfernen";
"Clear conversation" = "Chatinhalte löschen";
/* No comment provided by engineer. */
"Clear conversation?" = "Chat-Inhalte entfernen?";
"Clear conversation?" = "Unterhaltung löschen?";
/* No comment provided by engineer. */
"Clear private notes?" = "Private Notizen entfernen?";
"Clear private notes?" = "Private Notizen löschen?";
/* No comment provided by engineer. */
"Clear verification" = "Überprüfung zurücknehmen";
@@ -1167,7 +1167,7 @@
"Continue" = "Weiter";
/* No comment provided by engineer. */
"Conversation deleted!" = "Chat-Inhalte entfernt!";
"Conversation deleted!" = "Unterhaltung gelöscht!";
/* No comment provided by engineer. */
"Copy" = "Kopieren";
@@ -2203,6 +2203,9 @@
/* No comment provided by engineer. */
"Full name (optional)" = "Vollständiger Name (optional)";
/* No comment provided by engineer. */
"Full name:" = "Vollständiger Name:";
/* No comment provided by engineer. */
"Fully decentralized visible only to members." = "Vollständig dezentralisiert nur für Mitglieder sichtbar.";
@@ -2303,7 +2306,7 @@
"Group will be deleted for all members - this cannot be undone!" = "Die Gruppe wird für alle Mitglieder gelöscht. Dies kann nicht rückgängig gemacht werden!";
/* No comment provided by engineer. */
"Group will be deleted for you - this cannot be undone!" = "Die Gruppe wird nur bei Ihnen gelöscht. Dies kann nicht rückgängig gemacht werden!";
"Group will be deleted for you - this cannot be undone!" = "Die Gruppe wird für Sie gelöscht. Dies kann nicht rückgängig gemacht werden!";
/* No comment provided by engineer. */
"Help" = "Hilfe";
@@ -2627,7 +2630,7 @@
"Keep" = "Behalten";
/* No comment provided by engineer. */
"Keep conversation" = "Chat-Inhalte beibehalten";
"Keep conversation" = "Unterhaltung behalten";
/* No comment provided by engineer. */
"Keep the app open to use it from desktop" = "Die App muss geöffnet bleiben, um sie vom Desktop aus nutzen zu können";
@@ -3112,7 +3115,7 @@
"Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**." = "Nur die Endgeräte speichern die Benutzerprofile, Kontakte, Gruppen und Nachrichten, welche über eine **2-Schichten Ende-zu-Ende-Verschlüsselung** gesendet werden.";
/* No comment provided by engineer. */
"Only delete conversation" = "Nur die Chat-Inhalte löschen";
"Only delete conversation" = "Nur die Unterhaltung löschen";
/* No comment provided by engineer. */
"Only group owners can change group preferences." = "Gruppen-Präferenzen können nur von Gruppen-Eigentümern geändert werden.";
@@ -3375,6 +3378,12 @@
/* No comment provided by engineer. */
"Profile images" = "Profil-Bilder";
/* No comment provided by engineer. */
"Profile name" = "Profilname";
/* No comment provided by engineer. */
"Profile name:" = "Profilname:";
/* No comment provided by engineer. */
"Profile password" = "Passwort für Profil";
@@ -3451,7 +3460,7 @@
"Rate the app" = "Bewerten Sie die App";
/* No comment provided by engineer. */
"Reachable chat toolbar" = "Chat-Symbolleiste unten";
"Reachable chat toolbar" = "Erreichbare Chat-Symbolleiste";
/* chat item menu */
"React…" = "Reagiere…";
@@ -3706,11 +3715,10 @@
/* No comment provided by engineer. */
"Safer groups" = "Sicherere Gruppen";
/* alert button
chat item action */
/* chat item action */
"Save" = "Speichern";
/* alert button */
/* No comment provided by engineer. */
"Save (and notify contacts)" = "Speichern (und Kontakte benachrichtigen)";
/* No comment provided by engineer. */
@@ -3728,6 +3736,9 @@
/* No comment provided by engineer. */
"Save archive" = "Archiv speichern";
/* No comment provided by engineer. */
"Save auto-accept settings" = "Einstellungen von \"Automatisch akzeptieren\" speichern";
/* No comment provided by engineer. */
"Save group profile" = "Gruppenprofil speichern";
@@ -3749,6 +3760,9 @@
/* No comment provided by engineer. */
"Save servers?" = "Alle Server speichern?";
/* No comment provided by engineer. */
"Save settings?" = "Einstellungen speichern?";
/* No comment provided by engineer. */
"Save welcome message?" = "Begrüßungsmeldung speichern?";
@@ -3801,7 +3815,7 @@
"Search bar accepts invitation links." = "In der Suchleiste werden nun auch Einladungslinks akzeptiert.";
/* No comment provided by engineer. */
"Search or paste SimpleX link" = "Suchen oder SimpleX-Link einfügen";
"Search or paste SimpleX link" = "Suchen oder fügen Sie den SimpleX-Link ein";
/* network option */
"sec" = "sek";
@@ -4371,7 +4385,7 @@
"The message will be marked as moderated for all members." = "Diese Nachricht wird für alle Mitglieder als moderiert gekennzeichnet.";
/* No comment provided by engineer. */
"The messages will be deleted for all members." = "Die Nachrichten werden für alle Gruppenmitglieder gelöscht.";
"The messages will be deleted for all members." = "Die Nachrichten werden für alle Mitglieder gelöscht werden.";
/* No comment provided by engineer. */
"The messages will be marked as moderated for all members." = "Die Nachrichten werden für alle Mitglieder als moderiert gekennzeichnet werden.";
@@ -4695,7 +4709,7 @@
"Use the app while in the call." = "Die App kann während eines Anrufs genutzt werden.";
/* No comment provided by engineer. */
"Use the app with one hand." = "Die App mit einer Hand bedienen.";
"Use the app with one hand." = "Die App mit einer Hand nutzen.";
/* No comment provided by engineer. */
"User profile" = "Benutzerprofil";
@@ -5007,7 +5021,7 @@
"You can start chat via app Settings / Database or by restarting the app" = "Sie können den Chat über die App-Einstellungen / Datenbank oder durch Neustart der App starten";
/* No comment provided by engineer. */
"You can still view conversation with %@ in the list of chats." = "Sie können in der Chat-Liste weiterhin die Unterhaltung mit %@ einsehen.";
"You can still view conversation with %@ in the list of chats." = "Sie können in der Chatliste weiterhin die Unterhaltung mit %@ einsehen.";
/* No comment provided by engineer. */
"You can turn on SimpleX Lock via Settings." = "Sie können die SimpleX-Sperre über die Einstellungen aktivieren.";
@@ -5175,7 +5189,7 @@
"Your profile **%@** will be shared." = "Ihr Profil **%@** wird geteilt.";
/* No comment provided by engineer. */
"Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." = "Ihr Profil wird auf Ihrem Gerät gespeichert und nur mit Ihren Kontakten geteilt. SimpleX-Server können Ihr Profil nicht einsehen.";
"Your profile is stored on your device and shared only with your contacts.\nSimpleX servers cannot see your profile." = "Ihr Profil wird auf Ihrem Gerät gespeichert und nur mit Ihren Kontakten geteilt.\nSimpleX-Server können Ihr Profil nicht einsehen.";
/* No comment provided by engineer. */
"Your profile, contacts and delivered messages are stored on your device." = "Ihr Profil, Ihre Kontakte und zugestellten Nachrichten werden auf Ihrem Gerät gespeichert.";
+19 -5
View File
@@ -781,7 +781,7 @@
/* No comment provided by engineer. */
"Can't message member" = "No se pueden enviar mensajes al miembro";
/* alert button */
/* No comment provided by engineer. */
"Cancel" = "Cancelar";
/* No comment provided by engineer. */
@@ -2203,6 +2203,9 @@
/* No comment provided by engineer. */
"Full name (optional)" = "Nombre completo (opcional)";
/* No comment provided by engineer. */
"Full name:" = "Nombre completo:";
/* No comment provided by engineer. */
"Fully decentralized visible only to members." = "Completamente descentralizado y sólo visible para los miembros.";
@@ -3375,6 +3378,12 @@
/* No comment provided by engineer. */
"Profile images" = "Forma de los perfiles";
/* No comment provided by engineer. */
"Profile name" = "Nombre del perfil";
/* No comment provided by engineer. */
"Profile name:" = "Nombre del perfil:";
/* No comment provided by engineer. */
"Profile password" = "Contraseña del perfil";
@@ -3706,11 +3715,10 @@
/* No comment provided by engineer. */
"Safer groups" = "Grupos más seguros";
/* alert button
chat item action */
/* chat item action */
"Save" = "Guardar";
/* alert button */
/* No comment provided by engineer. */
"Save (and notify contacts)" = "Guardar (y notificar contactos)";
/* No comment provided by engineer. */
@@ -3728,6 +3736,9 @@
/* No comment provided by engineer. */
"Save archive" = "Guardar archivo";
/* No comment provided by engineer. */
"Save auto-accept settings" = "Guardar configuración de auto aceptar";
/* No comment provided by engineer. */
"Save group profile" = "Guardar perfil de grupo";
@@ -3749,6 +3760,9 @@
/* No comment provided by engineer. */
"Save servers?" = "¿Guardar servidores?";
/* No comment provided by engineer. */
"Save settings?" = "¿Guardar configuración?";
/* No comment provided by engineer. */
"Save welcome message?" = "¿Guardar mensaje de bienvenida?";
@@ -5175,7 +5189,7 @@
"Your profile **%@** will be shared." = "El perfil **%@** será compartido.";
/* No comment provided by engineer. */
"Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." = "Tu perfil es almacenado en tu dispositivo y solamente se comparte con tus contactos. Los servidores SimpleX no pueden ver tu perfil.";
"Your profile is stored on your device and shared only with your contacts.\nSimpleX servers cannot see your profile." = "Tu perfil es almacenado en tu dispositivo y solamente se comparte con tus contactos.\nLos servidores SimpleX no pueden ver tu perfil.";
/* No comment provided by engineer. */
"Your profile, contacts and delivered messages are stored on your device." = "Tu perfil, contactos y mensajes se almacenan en tu dispositivo.";
+13 -5
View File
@@ -547,7 +547,7 @@
/* No comment provided by engineer. */
"Can't invite contacts!" = "Kontakteja ei voi kutsua!";
/* alert button */
/* No comment provided by engineer. */
"Cancel" = "Peruuta";
/* feature offered item */
@@ -1519,6 +1519,9 @@
/* No comment provided by engineer. */
"Full name (optional)" = "Koko nimi (valinnainen)";
/* No comment provided by engineer. */
"Full name:" = "Koko nimi:";
/* No comment provided by engineer. */
"Fully re-implemented - work in background!" = "Täysin uudistettu - toimii taustalla!";
@@ -2569,11 +2572,10 @@
/* No comment provided by engineer. */
"Run chat" = "Käynnistä chat";
/* alert button
chat item action */
/* chat item action */
"Save" = "Tallenna";
/* alert button */
/* No comment provided by engineer. */
"Save (and notify contacts)" = "Tallenna (ja ilmoita kontakteille)";
/* No comment provided by engineer. */
@@ -2588,6 +2590,9 @@
/* No comment provided by engineer. */
"Save archive" = "Tallenna arkisto";
/* No comment provided by engineer. */
"Save auto-accept settings" = "Tallenna automaattisen hyväksynnän asetukset";
/* No comment provided by engineer. */
"Save group profile" = "Tallenna ryhmäprofiili";
@@ -2609,6 +2614,9 @@
/* No comment provided by engineer. */
"Save servers?" = "Tallenna palvelimet?";
/* No comment provided by engineer. */
"Save settings?" = "Tallenna asetukset?";
/* No comment provided by engineer. */
"Save welcome message?" = "Tallenna tervetuloviesti?";
@@ -3504,7 +3512,7 @@
"Your profile **%@** will be shared." = "Profiilisi **%@** jaetaan.";
/* No comment provided by engineer. */
"Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." = "Profiilisi tallennetaan laitteeseesi ja jaetaan vain yhteystietojesi kanssa. SimpleX-palvelimet eivät näe profiiliasi.";
"Your profile is stored on your device and shared only with your contacts.\nSimpleX servers cannot see your profile." = "Profiilisi tallennetaan laitteeseesi ja jaetaan vain yhteystietojesi kanssa.\nSimpleX-palvelimet eivät näe profiiliasi.";
/* No comment provided by engineer. */
"Your profile, contacts and delivered messages are stored on your device." = "Profiilisi, kontaktisi ja toimitetut viestit tallennetaan laitteellesi.";
+19 -5
View File
@@ -781,7 +781,7 @@
/* No comment provided by engineer. */
"Can't message member" = "Impossible d'envoyer un message à ce membre";
/* alert button */
/* No comment provided by engineer. */
"Cancel" = "Annuler";
/* No comment provided by engineer. */
@@ -2203,6 +2203,9 @@
/* No comment provided by engineer. */
"Full name (optional)" = "Nom complet (optionnel)";
/* No comment provided by engineer. */
"Full name:" = "Nom complet :";
/* No comment provided by engineer. */
"Fully decentralized visible only to members." = "Entièrement décentralisé visible que par ses membres.";
@@ -3375,6 +3378,12 @@
/* No comment provided by engineer. */
"Profile images" = "Images de profil";
/* No comment provided by engineer. */
"Profile name" = "Nom du profil";
/* No comment provided by engineer. */
"Profile name:" = "Nom du profil :";
/* No comment provided by engineer. */
"Profile password" = "Mot de passe de profil";
@@ -3706,11 +3715,10 @@
/* No comment provided by engineer. */
"Safer groups" = "Groupes plus sûrs";
/* alert button
chat item action */
/* chat item action */
"Save" = "Enregistrer";
/* alert button */
/* No comment provided by engineer. */
"Save (and notify contacts)" = "Enregistrer (et en informer les contacts)";
/* No comment provided by engineer. */
@@ -3728,6 +3736,9 @@
/* No comment provided by engineer. */
"Save archive" = "Enregistrer l'archive";
/* No comment provided by engineer. */
"Save auto-accept settings" = "Enregistrer les paramètres de validation automatique";
/* No comment provided by engineer. */
"Save group profile" = "Enregistrer le profil du groupe";
@@ -3749,6 +3760,9 @@
/* No comment provided by engineer. */
"Save servers?" = "Enregistrer les serveurs?";
/* No comment provided by engineer. */
"Save settings?" = "Enregistrer les paramètres?";
/* No comment provided by engineer. */
"Save welcome message?" = "Enregistrer le message d'accueil?";
@@ -5175,7 +5189,7 @@
"Your profile **%@** will be shared." = "Votre profil **%@** sera partagé.";
/* No comment provided by engineer. */
"Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." = "Votre profil est stocké sur votre appareil et est seulement partagé avec vos contacts. Les serveurs SimpleX ne peuvent pas voir votre profil.";
"Your profile is stored on your device and shared only with your contacts.\nSimpleX servers cannot see your profile." = "Votre profil est stocké sur votre appareil et est seulement partagé avec vos contacts.\nLes serveurs SimpleX ne peuvent pas voir votre profil.";
/* No comment provided by engineer. */
"Your profile, contacts and delivered messages are stored on your device." = "Votre profil, vos contacts et les messages reçus sont stockés sur votre appareil.";
+91 -77
View File
@@ -29,7 +29,7 @@
"- optionally notify deleted contacts.\n- profile names with spaces.\n- and more!" = "- opcionális értesítés a törölt kapcsolatokról.\n- profilnevek szóközökkel.\n- és még sok más!";
/* No comment provided by engineer. */
"- voice messages up to 5 minutes.\n- custom time to disappear.\n- editing history." = "- 5 perc hosszúságú hangüzenetek.\n- egyedi üzenet-eltűnési időkorlát.\n- előzmények szerkesztése.";
"- voice messages up to 5 minutes.\n- custom time to disappear.\n- editing history." = "- hangüzenetek legfeljebb 5 perces időtartamig.\n- egyedi eltűnési időhatár megadása.\n- előzmények szerkesztése.";
/* No comment provided by engineer. */
", " = ", ";
@@ -62,7 +62,7 @@
"[Send us email](mailto:chat@simplex.chat)" = "[Küldjön nekünk e-mailt](mailto:chat@simplex.chat)";
/* No comment provided by engineer. */
"[Star on GitHub](https://github.com/simplex-chat/simplex-chat)" = "[Csillagozás a GitHubon](https://github.com/simplex-chat/simplex-chat)";
"[Star on GitHub](https://github.com/simplex-chat/simplex-chat)" = "[Csillag a GitHubon](https://github.com/simplex-chat/simplex-chat)";
/* No comment provided by engineer. */
"**Add contact**: to create a new invitation link, or connect via a link you received." = "**Ismerős hozzáadása**: új meghívó hivatkozás létrehozásához, vagy egy kapott hivatkozáson keresztül történő kapcsolódáshoz.";
@@ -263,7 +263,7 @@
"`a + b`" = "a + b";
/* email text */
"<p>Hi!</p>\n<p><a href=\"%@\">Connect to me via SimpleX Chat</a></p>" = "<p>Üdvözlöm!</p>\n<p><a href=„%@”>Csatlakozzon hozzám a SimpleX Chaten keresztül</a></p>";
"<p>Hi!</p>\n<p><a href=\"%@\">Connect to me via SimpleX Chat</a></p>" = "<p>Üdvözlöm!</p>\n<p><a href=„%@”>Csatlakozzon hozzám a SimpleX Chaten</a></p>";
/* No comment provided by engineer. */
"~strike~" = "\\~áthúzott~";
@@ -343,7 +343,7 @@
"Accept" = "Elfogadás";
/* No comment provided by engineer. */
"Accept connection request?" = "Ismerőskérelem elfogadása?";
"Accept connection request?" = "Kapcsolódási kérelem elfogadása?";
/* notification body */
"Accept contact request from %@?" = "Elfogadja %@ kapcsolat kérését?";
@@ -659,10 +659,10 @@
"Bad desktop address" = "Hibás számítógép cím";
/* integrity error chat item */
"bad message hash" = "hibás az üzenet hasító értéke";
"bad message hash" = "hibás az üzenet ellenőrzőösszege";
/* No comment provided by engineer. */
"Bad message hash" = "Hibás az üzenet hasító értéke";
"Bad message hash" = "Hibás az üzenet ellenőrzőösszege";
/* integrity error chat item */
"bad message ID" = "téves üzenet ID";
@@ -749,7 +749,7 @@
"Call already ended!" = "A hívás már befejeződött!";
/* call status */
"call error" = "híváshiba";
"call error" = "hiba a hívásban";
/* call status */
"call in progress" = "hívás folyamatban";
@@ -781,7 +781,7 @@
/* No comment provided by engineer. */
"Can't message member" = "Nem lehet üzenetet küldeni a tagnak";
/* alert button */
/* No comment provided by engineer. */
"Cancel" = "Mégse";
/* No comment provided by engineer. */
@@ -1002,7 +1002,7 @@
"Connect incognito" = "Kapcsolódás inkognitóban";
/* No comment provided by engineer. */
"Connect to desktop" = "Társítás számítógéppel";
"Connect to desktop" = "Kapcsolódás számítógéphez";
/* No comment provided by engineer. */
"connect to SimpleX Chat developers." = "Kapcsolódás a SimpleX Chat fejlesztőkhöz.";
@@ -1014,7 +1014,7 @@
"Connect to yourself?" = "Kapcsolódás saját magához?";
/* No comment provided by engineer. */
"Connect to yourself?\nThis is your own one-time link!" = "Kapcsolódás saját magához?\nEz az ön egyszer használatos hivatkozása!";
"Connect to yourself?\nThis is your own one-time link!" = "Kapcsolódás saját magához?\nEz az egyszer használatos hivatkozása!";
/* No comment provided by engineer. */
"Connect to yourself?\nThis is your own SimpleX address!" = "Kapcsolódás saját magához?\nEz az ön SimpleX címe!";
@@ -1038,7 +1038,7 @@
"Connected" = "Kapcsolódva";
/* No comment provided by engineer. */
"Connected desktop" = "Társított számítógép";
"Connected desktop" = "Csatlakoztatott számítógép";
/* rcv group event chat item */
"connected directly" = "közvetlenül kapcsolódva";
@@ -1068,7 +1068,7 @@
"connecting (introduction invitation)" = "kapcsolódás (bemutatkozó meghívó)";
/* call status */
"connecting call" = "kapcsolódási hívás…";
"connecting call" = "hívás kapcsolódik…";
/* No comment provided by engineer. */
"Connecting server…" = "Kapcsolódás a kiszolgálóhoz…";
@@ -1128,7 +1128,7 @@
"Contact allows" = "Ismerős engedélyezi";
/* No comment provided by engineer. */
"Contact already exists" = "Az ismerős már létezik";
"Contact already exists" = "Létező ismerős";
/* No comment provided by engineer. */
"Contact deleted!" = "Ismerős törölve!";
@@ -1197,7 +1197,7 @@
"Create group" = "Csoport létrehozása";
/* No comment provided by engineer. */
"Create group link" = "Csoporthivatkozás létrehozása";
"Create group link" = "Csoportos hivatkozás létrehozása";
/* No comment provided by engineer. */
"Create link" = "Hivatkozás létrehozása";
@@ -1233,7 +1233,7 @@
"Created on %@" = "Létrehozva %@";
/* No comment provided by engineer. */
"Creating archive link" = "Archívum hivatkozás létrehozása";
"Creating archive link" = "Archív hivatkozás létrehozása";
/* No comment provided by engineer. */
"Creating link…" = "Hivatkozás létrehozása…";
@@ -1450,7 +1450,7 @@
"Delete old database?" = "Régi adatbázis törlése?";
/* No comment provided by engineer. */
"Delete pending connection?" = "Függőben lévő ismerőskérelem törlése?";
"Delete pending connection?" = "Függő kapcsolatfelvételi kérések törlése?";
/* No comment provided by engineer. */
"Delete profile" = "Profil törlése";
@@ -1654,7 +1654,7 @@
"Downloading link details" = "Letöltési hivatkozás részletei";
/* No comment provided by engineer. */
"Duplicate display name!" = "Duplikált megjelenített név!";
"Duplicate display name!" = "Duplikált megjelenítési név!";
/* integrity error chat item */
"duplicate message" = "duplikált üzenet";
@@ -1852,7 +1852,7 @@
"Error accessing database file" = "Hiba az adatbázisfájl elérésekor";
/* No comment provided by engineer. */
"Error adding member(s)" = "Hiba a tag(ok) hozzáadásakor";
"Error adding member(s)" = "Hiba a tag(-ok) hozzáadásakor";
/* No comment provided by engineer. */
"Error changing address" = "Hiba a cím megváltoztatásakor";
@@ -1873,7 +1873,7 @@
"Error creating group" = "Hiba a csoport létrehozásakor";
/* No comment provided by engineer. */
"Error creating group link" = "Hiba a csoporthivatkozás létrehozásakor";
"Error creating group link" = "Hiba a csoport hivatkozásának létrehozásakor";
/* No comment provided by engineer. */
"Error creating member contact" = "Hiba az ismerőssel történő kapcsolat létrehozásában";
@@ -2002,7 +2002,7 @@
"Error synchronizing connection" = "Hiba a kapcsolat szinkronizálása közben";
/* No comment provided by engineer. */
"Error updating group link" = "Hiba a csoporthivatkozás frissítésekor";
"Error updating group link" = "Hiba a csoport hivatkozás frissítésekor";
/* No comment provided by engineer. */
"Error updating message" = "Hiba az üzenet frissítésekor";
@@ -2203,6 +2203,9 @@
/* No comment provided by engineer. */
"Full name (optional)" = "Teljes név (opcionális)";
/* No comment provided by engineer. */
"Full name:" = "Teljes név:";
/* No comment provided by engineer. */
"Fully decentralized visible only to members." = "Teljesen decentralizált - kizárólag tagok számára látható.";
@@ -2252,10 +2255,10 @@
"Group invitation is no longer valid, it was removed by sender." = "A csoport meghívó már nem érvényes, a küldője törölte.";
/* No comment provided by engineer. */
"Group link" = "Csoporthivatkozás";
"Group link" = "Csoport hivatkozás";
/* No comment provided by engineer. */
"Group links" = "Csoporthivatkozások";
"Group links" = "Csoport hivatkozások";
/* No comment provided by engineer. */
"Group members can add message reactions." = "Csoporttagok üzenetreakciókat adhatnak hozzá.";
@@ -2300,7 +2303,7 @@
"Group welcome message" = "Csoport üdvözlő üzenete";
/* No comment provided by engineer. */
"Group will be deleted for all members - this cannot be undone!" = "A csoport törlésre kerül minden tag számára - ez a művelet nem vonható vissza!";
"Group will be deleted for all members - this cannot be undone!" = "Csoport törlésre kerül minden tag számára - ez a művelet nem vonható vissza!";
/* No comment provided by engineer. */
"Group will be deleted for you - this cannot be undone!" = "A csoport törlésre kerül az ön számára - ez a művelet nem vonható vissza!";
@@ -2441,10 +2444,10 @@
"incognito via contact address link" = "inkognitó a kapcsolattartási hivatkozáson keresztül";
/* chat list item description */
"incognito via group link" = "inkognitó a csoporthivatkozáson keresztül";
"incognito via group link" = "inkognitó a csoportos hivatkozáson keresztül";
/* chat list item description */
"incognito via one-time link" = "inkognitó egy egyszer használatos hivatkozáson keresztül";
"incognito via one-time link" = "inkognitó az egyszer használatos hivatkozáson keresztül";
/* notification */
"Incoming audio call" = "Bejövő hanghívás";
@@ -2498,13 +2501,13 @@
"invalid chat data" = "érvénytelen csevegés adat";
/* No comment provided by engineer. */
"Invalid connection link" = "Érvénytelen kapcsolattartási hivatkozás";
"Invalid connection link" = "Érvénytelen kapcsolati hivatkozás";
/* invalid chat item */
"invalid data" = "érvénytelen adat";
/* No comment provided by engineer. */
"Invalid display name!" = "Érvénytelen megjelenítendő név!";
"Invalid display name!" = "Érvénytelen megjelenítendő felhaszálónév!";
/* No comment provided by engineer. */
"Invalid link" = "Érvénytelen hivatkozás";
@@ -2555,7 +2558,7 @@
"invited to connect" = "meghívta, hogy csatlakozzon";
/* rcv group event chat item */
"invited via your group link" = "meghíva az ön csoporthivatkozásán keresztül";
"invited via your group link" = "meghíva az ön csoport hivatkozásán keresztül";
/* No comment provided by engineer. */
"iOS Keychain is used to securely store passphrase - it allows receiving push notifications." = "Az iOS kulcstartó a jelmondat biztonságos tárolására szolgál - lehetővé teszi a push-értesítések fogadását.";
@@ -2663,7 +2666,7 @@
"left" = "elhagyta a csoportot";
/* email subject */
"Let's talk in SimpleX Chat" = "Beszélgessünk a SimpleX Chatben";
"Let's talk in SimpleX Chat" = "Beszélgessünk a SimpleX Chat-ben";
/* No comment provided by engineer. */
"Light" = "Világos";
@@ -2672,13 +2675,13 @@
"Limitations" = "Korlátozások";
/* No comment provided by engineer. */
"Link mobile and desktop apps! 🔗" = "Társítsa össze a mobil és asztali alkalmazásokat! 🔗";
"Link mobile and desktop apps! 🔗" = "Társítsa össze a mobil és az asztali alkalmazásokat! 🔗";
/* No comment provided by engineer. */
"Linked desktop options" = "Társított számítógép beállítások";
"Linked desktop options" = "Összekapcsolt számítógép beállítások";
/* No comment provided by engineer. */
"Linked desktops" = "Társított számítógépek";
"Linked desktops" = "Összekapcsolt számítógépek";
/* No comment provided by engineer. */
"LIVE" = "ÉLŐ";
@@ -2720,7 +2723,7 @@
"Make sure WebRTC ICE server addresses are in correct format, line separated and are not duplicated." = "Győződjön meg arról, hogy a WebRTC ICE-kiszolgáló címei megfelelő formátumúak, sorszeparáltak és nincsenek duplikálva.";
/* No comment provided by engineer. */
"Many people asked: *if SimpleX has no user identifiers, how can it deliver messages?*" = "Sokan kérdezték: *ha a SimpleX Chatnek nincsenek felhasználói azonosítói, akkor hogyan tud üzeneteket kézbesíteni?*";
"Many people asked: *if SimpleX has no user identifiers, how can it deliver messages?*" = "Sokan kérdezték: *ha a SimpleX-nek nincsenek felhasználói azonosítói, akkor hogyan tud üzeneteket kézbesíteni?*";
/* No comment provided by engineer. */
"Mark deleted for everyone" = "Jelölje meg mindenki számára töröltként";
@@ -2735,7 +2738,7 @@
"Markdown in messages" = "Markdown az üzenetekben";
/* marked deleted chat item preview text */
"marked deleted" = "törlésre jelölve";
"marked deleted" = "töröltnek jelölve";
/* No comment provided by engineer. */
"Max 30 seconds, received instantly." = "Max. 30 másodperc, azonnal érkezett.";
@@ -2900,10 +2903,10 @@
"moderated" = "moderált";
/* No comment provided by engineer. */
"Moderated at" = "Moderálva ekkor:";
"Moderated at" = "Moderálva lett ekkor:";
/* copied message info */
"Moderated at: %@" = "Moderálva ekkor: %@";
"Moderated at: %@" = "Moderálva lett ekkor: %@";
/* marked deleted chat item preview text */
"moderated by %@" = "moderálva lett %@ által";
@@ -2963,7 +2966,7 @@
"New chat experience 🎉" = "Új csevegési élmény 🎉";
/* notification */
"New contact request" = "Új ismerőskérelem";
"New contact request" = "Új kapcsolattartási kérelem";
/* notification */
"New contact:" = "Új kapcsolat:";
@@ -3008,7 +3011,7 @@
"No app password" = "Nincs alkalmazás jelszó";
/* No comment provided by engineer. */
"No contacts selected" = "Nincs kiválasztva ismerős";
"No contacts selected" = "Nem kerültek ismerősök kiválasztásra";
/* No comment provided by engineer. */
"No contacts to add" = "Nincs hozzáadandó ismerős";
@@ -3053,7 +3056,7 @@
"Not compatible!" = "Nem kompatibilis!";
/* No comment provided by engineer. */
"Nothing selected" = "Nincs kiválasztva semmi";
"Nothing selected" = "Semmi sincs kiválasztva";
/* No comment provided by engineer. */
"Notifications" = "Értesítések";
@@ -3091,7 +3094,7 @@
"Old database" = "Régi adatbázis";
/* No comment provided by engineer. */
"Old database archive" = "Régi adatbázis-archívum";
"Old database archive" = "Régi adatbázis archívum";
/* group pref value */
"on" = "bekapcsolva";
@@ -3109,7 +3112,7 @@
"Onion hosts will not be used." = "Onion kiszolgálók nem lesznek használva.";
/* No comment provided by engineer. */
"Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**." = "Csak a klienseszközök tárolják a felhasználói profilokat, névjegyeket, csoportokat és a **2 rétegű végpontok közötti titkosítással** küldött üzeneteket.";
"Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**." = "Csak a klienseszközök tárolják a felhasználói profilokat, névjegyeket, csoportokat és a **2 rétegű végponttól-végpontig titkosítással** küldött üzeneteket.";
/* No comment provided by engineer. */
"Only delete conversation" = "Csak a beszélgetés törlése";
@@ -3190,7 +3193,7 @@
"Or scan QR code" = "Vagy QR-kód beolvasása";
/* No comment provided by engineer. */
"Or securely share this file link" = "Vagy ossza meg biztonságosan ezt a fájlhivatkozást";
"Or securely share this file link" = "Vagy a fájl hivítkozásának biztonságos megosztása";
/* No comment provided by engineer. */
"Or show this code" = "Vagy mutassa meg ezt a kódot";
@@ -3232,7 +3235,7 @@
"Password to show" = "Jelszó megjelenítése";
/* past/unknown group member */
"Past member %@" = "%@ (már nem tag)";
"Past member %@" = "Már nem tag - %@";
/* No comment provided by engineer. */
"Paste desktop address" = "Számítógép címének beillesztése";
@@ -3244,13 +3247,13 @@
"Paste link to connect!" = "Hivatkozás beillesztése a kapcsolódáshoz!";
/* No comment provided by engineer. */
"Paste the link you received" = "Kapott hivatkozás beillesztése";
"Paste the link you received" = "Fogadott hivatkozás beillesztése";
/* No comment provided by engineer. */
"peer-to-peer" = "ponttól-pontig";
/* No comment provided by engineer. */
"Pending" = "Függőben";
"Pending" = "Függő";
/* No comment provided by engineer. */
"People can connect to you only via the links you share." = "Az emberek csak az ön által megosztott hivatkozáson keresztül kapcsolódhatnak.";
@@ -3283,7 +3286,7 @@
"Please check that mobile and desktop are connected to the same local network, and that desktop firewall allows the connection.\nPlease share any other issues with the developers." = "Ellenőrizze, hogy a mobil és az asztali számítógép ugyanahhoz a helyi hálózathoz csatlakozik-e, valamint az asztali számítógép tűzfalában engedélyezve van-e a kapcsolat.\nMinden további problémát osszon meg a fejlesztőkkel.";
/* No comment provided by engineer. */
"Please check that you used the correct link or ask your contact to send you another one." = "Ellenőrizze, hogy a megfelelő hivatkozást használta-e, vagy kérje meg az ismerősét, hogy küldjön egy másikat.";
"Please check that you used the correct link or ask your contact to send you another one." = "Ellenőrizze, hogy a megfelelő hivatkozást használta-e, vagy kérje meg ismerősét, hogy küldjön egy másikat.";
/* No comment provided by engineer. */
"Please check your network connection with %@ and try again." = "Ellenőrizze hálózati kapcsolatát a(z) %@ segítségével, és próbálja újra.";
@@ -3375,6 +3378,12 @@
/* No comment provided by engineer. */
"Profile images" = "Profilképek";
/* No comment provided by engineer. */
"Profile name" = "Profilnév";
/* No comment provided by engineer. */
"Profile name:" = "Profil neve:";
/* No comment provided by engineer. */
"Profile password" = "Profiljelszó";
@@ -3484,7 +3493,7 @@
"Receive errors" = "Üzenetfogadási hibák";
/* No comment provided by engineer. */
"received answer…" = "válasz fogadása…";
"received answer…" = "fogadott válasz…";
/* No comment provided by engineer. */
"Received at" = "Fogadva ekkor:";
@@ -3638,7 +3647,7 @@
"Required" = "Szükséges";
/* No comment provided by engineer. */
"Reset" = "Visszaállítás";
"Reset" = "Alaphelyzetbe állítás";
/* No comment provided by engineer. */
"Reset all hints" = "Tippek visszaállítása";
@@ -3650,13 +3659,13 @@
"Reset all statistics?" = "Minden statisztika visszaállítása?";
/* No comment provided by engineer. */
"Reset colors" = "Színek visszaállítása";
"Reset colors" = "Színek alaphelyzetbe állítása";
/* No comment provided by engineer. */
"Reset to app theme" = "Alkalmazás témájának visszaállítása";
/* No comment provided by engineer. */
"Reset to defaults" = "Visszaállítás alaphelyzetbe";
"Reset to defaults" = "Alaphelyzetbe állítás";
/* No comment provided by engineer. */
"Reset to user theme" = "Felhasználó által létrehozott téma visszaállítása";
@@ -3706,11 +3715,10 @@
/* No comment provided by engineer. */
"Safer groups" = "Biztonságosabb csoportok";
/* alert button
chat item action */
/* chat item action */
"Save" = "Mentés";
/* alert button */
/* No comment provided by engineer. */
"Save (and notify contacts)" = "Mentés (és az ismerősök értesítése)";
/* No comment provided by engineer. */
@@ -3728,6 +3736,9 @@
/* No comment provided by engineer. */
"Save archive" = "Archívum mentése";
/* No comment provided by engineer. */
"Save auto-accept settings" = "Automatikus elfogadási beállítások mentése";
/* No comment provided by engineer. */
"Save group profile" = "Csoportprofil elmentése";
@@ -3749,6 +3760,9 @@
/* No comment provided by engineer. */
"Save servers?" = "Kiszolgálók mentése?";
/* No comment provided by engineer. */
"Save settings?" = "Beállítások mentése?";
/* No comment provided by engineer. */
"Save welcome message?" = "Üdvözlőszöveg mentése?";
@@ -3999,10 +4013,10 @@
"Servers" = "Kiszolgálók";
/* No comment provided by engineer. */
"Servers info" = "Információk a kiszolgálókról";
"Servers info" = "információk a kiszolgálókról";
/* No comment provided by engineer. */
"Servers statistics will be reset - this cannot be undone!" = "A kiszolgálók statisztikái visszaállnak - ez a művelet nem vonható vissza!";
"Servers statistics will be reset - this cannot be undone!" = "A kiszolgálók statisztikái visszaállnak - ez nem vonható vissza!";
/* No comment provided by engineer. */
"Session code" = "Munkamenet kód";
@@ -4122,7 +4136,7 @@
"SimpleX encrypted message or connection event" = "SimpleX titkosított üzenet vagy kapcsolati esemény";
/* simplex link type */
"SimpleX group link" = "SimpleX csoporthivatkozás";
"SimpleX group link" = "SimpleX csoport hivatkozás";
/* chat feature */
"SimpleX links" = "SimpleX hivatkozások";
@@ -4260,7 +4274,7 @@
"Subscriptions ignored" = "Elutasított feliratkozások";
/* No comment provided by engineer. */
"Support SimpleX Chat" = "SimpleX Chat támogatása";
"Support SimpleX Chat" = "Támogassa a SimpleX Chatet";
/* No comment provided by engineer. */
"System" = "Rendszer";
@@ -4329,7 +4343,7 @@
"Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" = "Köszönet a felhasználóknak [hozzájárulás a Weblate-en keresztül](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!";
/* No comment provided by engineer. */
"Thanks to the users contribute via Weblate!" = "Köszönet a felhasználóknak - hozzájárulás a Weblate-en!";
"Thanks to the users contribute via Weblate!" = "Köszönet a felhasználóknak - hozzájárulás a Weblaten!";
/* No comment provided by engineer. */
"The 1st platform without any user identifiers private by design." = "Az első csevegési rendszer bármiféle felhasználó azonosító nélkül - privátra lett tervezre.";
@@ -4344,10 +4358,10 @@
"The attempt to change database passphrase was not completed." = "Az adatbázis jelmondatának megváltoztatására tett kísérlet nem fejeződött be.";
/* No comment provided by engineer. */
"The code you scanned is not a SimpleX link QR code." = "A beolvasott QR-kód nem egy SimpleX QR-kód hivatkozás.";
"The code you scanned is not a SimpleX link QR code." = "A beolvasott kód nem egy SimpleX hivatkozás QR-kód.";
/* No comment provided by engineer. */
"The connection you accepted will be cancelled!" = "Az ön által elfogadott kérelem vissza lesz vonva!";
"The connection you accepted will be cancelled!" = "Az ön által elfogadott kapcsolat vissza lesz vonva!";
/* No comment provided by engineer. */
"The contact you shared this link with will NOT be able to connect!" = "Ismerőse, akivel megosztotta ezt a hivatkozást, NEM fog tudni kapcsolódni!";
@@ -4359,7 +4373,7 @@
"The encryption is working and the new encryption agreement is not required. It may result in connection errors!" = "A titkosítás működik, és új titkosítási egyezményre nincs szükség. Ez kapcsolati hibákat eredményezhet!";
/* No comment provided by engineer. */
"The hash of the previous message is different." = "Az előző üzenet hasító értéke különbözik.";
"The hash of the previous message is different." = "Az előző üzenet ellenőrzőösszege különbözik.";
/* No comment provided by engineer. */
"The ID of the next message is incorrect (less or equal to the previous).\nIt can happen because of some bug or when the connection is compromised." = "A következő üzenet azonosítója hibás (kisebb vagy egyenlő az előzővel).\nEz valamilyen hiba, vagy sérült kapcsolat esetén fordulhat elő.";
@@ -4428,7 +4442,7 @@
"This device name" = "Ennek az eszköznek a neve";
/* No comment provided by engineer. */
"This display name is invalid. Please choose another name." = "Ez a megjelenített név érvénytelen. Válasszon egy másik nevet.";
"This display name is invalid. Please choose another name." = "Ez a megjelenített felhasználónév érvénytelen. Válasszon egy másik nevet.";
/* No comment provided by engineer. */
"This group has over %lld members, delivery receipts are not sent." = "Ennek a csoportnak több mint %lld tagja van, a kézbesítési jelentések nem kerülnek elküldésre.";
@@ -4437,13 +4451,13 @@
"This group no longer exists." = "Ez a csoport már nem létezik.";
/* No comment provided by engineer. */
"This is your own one-time link!" = "Ez az ön egyszer használatos hivatkozása!";
"This is your own one-time link!" = "Ez az egyszer használatos hivatkozása!";
/* No comment provided by engineer. */
"This is your own SimpleX address!" = "Ez az ön SimpleX címe!";
/* No comment provided by engineer. */
"This link was used with another mobile device, please create a new link on the desktop." = "Ezt a hivatkozást egy másik mobileszközön már használták, hozzon létre egy új hivatkozást az asztali számítógépén.";
"This link was used with another mobile device, please create a new link on the desktop." = "Ezt a hivatkozást egy másik mobilleszközön már használták, hozzon létre egy új hivatkozást az asztali számítógépén.";
/* No comment provided by engineer. */
"This setting applies to messages in your current chat profile **%@**." = "Ez a beállítás a jelenlegi **%@** profiljában lévő üzenetekre érvényes.";
@@ -4506,10 +4520,10 @@
"Transport sessions" = "Munkamenetek átvitele";
/* No comment provided by engineer. */
"Trying to connect to the server used to receive messages from this contact (error: %@)." = "Kapcsolódási kísérlet ahhoz a kiszolgálóhoz, amely az adott ismerősétől érkező üzenetek fogadására szolgál (hiba: %@).";
"Trying to connect to the server used to receive messages from this contact (error: %@)." = "Kapcsolódási kísérlet ahhoz a kiszolgálóhoz, amely az adott ismerőstől érkező üzenetek fogadására szolgál (hiba: %@).";
/* No comment provided by engineer. */
"Trying to connect to the server used to receive messages from this contact." = "Kapcsolódási kísérlet ahhoz a kiszolgálóhoz, amely az adott ismerősétől érkező üzenetek fogadására szolgál.";
"Trying to connect to the server used to receive messages from this contact." = "Kapcsolódási kísérlet ahhoz a kiszolgálóhoz, amely az adott ismerőstől érkező üzenetek fogadására szolgál.";
/* No comment provided by engineer. */
"Turkish interface" = "Török kezelőfelület";
@@ -4584,7 +4598,7 @@
"Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions." = "Hacsak nem az iOS hívási felületét használja, engedélyezze a Ne zavarjanak módot a megszakítások elkerülése érdekében.";
/* No comment provided by engineer. */
"Unless your contact deleted the connection or this link was already used, it might be a bug - please report it.\nTo connect, please ask your contact to create another connection link and check that you have a stable network connection." = "Hacsak az ismerőse nem törölte a kapcsolatot, vagy ez a hivatkozás már használatban volt egyszer, lehet hogy ez egy hiba jelentse a problémát.\nA kapcsolódáshoz kérje meg az ismerősét, hogy hozzon létre egy másik kapcsolattartási hivatkozást, és ellenőrizze, hogy a hálózati kapcsolat stabil-e.";
"Unless your contact deleted the connection or this link was already used, it might be a bug - please report it.\nTo connect, please ask your contact to create another connection link and check that you have a stable network connection." = "Hacsak az ismerőse nem törölte a kapcsolatot, vagy ez a hivatkozás már használatban volt, lehet hogy ez egy hiba jelentse a problémát.\nA kapcsolódáshoz kérje meg ismerősét, hogy hozzon létre egy másik kapcsolati hivatkozást, és ellenőrizze, hogy a hálózati kapcsolat stabil-e.";
/* No comment provided by engineer. */
"Unlink" = "Szétkapcsolás";
@@ -4668,7 +4682,7 @@
"Use for new connections" = "Alkalmazás új kapcsolatokhoz";
/* No comment provided by engineer. */
"Use from desktop" = "Társítás számítógéppel";
"Use from desktop" = "Használat számítógépl";
/* No comment provided by engineer. */
"Use iOS call interface" = "Az iOS hívófelület használata";
@@ -4740,10 +4754,10 @@
"via contact address link" = "kapcsolattartási cím-hivatkozáson keresztül";
/* chat list item description */
"via group link" = "a csoporthivatkozáson keresztül";
"via group link" = "csoport hivatkozáson keresztül";
/* chat list item description */
"via one-time link" = "egy egyszer használatos hivatkozáson keresztül";
"via one-time link" = "egyszer használatos hivatkozáson keresztül";
/* No comment provided by engineer. */
"via relay" = "átjátszón keresztül";
@@ -4920,7 +4934,7 @@
"You already have a chat profile with the same display name. Please choose another name." = "Már van egy csevegési profil ugyanezzel a megjelenített névvel. Válasszon egy másik nevet.";
/* No comment provided by engineer. */
"You are already connected to %@." = "Ön már kapcsolódva van ehhez: %@.";
"You are already connected to %@." = "Már kapcsolódva van hozzá: %@.";
/* No comment provided by engineer. */
"You are already connecting to %@." = "Már folyamatban van a kapcsolódás ehhez: %@.";
@@ -4944,7 +4958,7 @@
"You are already joining the group!\nRepeat join request?" = "Csatlakozás folyamatban!\nCsatlakozási kérés megismétlése?";
/* No comment provided by engineer. */
"You are connected to the server used to receive messages from this contact." = "Már kapcsolódott ahhoz a kiszolgálóhoz, amely az adott ismerősétől érkező üzenetek fogadására szolgál.";
"You are connected to the server used to receive messages from this contact." = "Már kapcsolódott ahhoz a kiszolgálóhoz, amely az adott ismerőstől érkező üzenetek fogadására szolgál.";
/* No comment provided by engineer. */
"you are invited to group" = "meghívást kapott a csoportba";
@@ -4959,7 +4973,7 @@
"you are observer" = "megfigyelő szerep";
/* snd group event chat item */
"you blocked %@" = "ön letiltotta őt: %@";
"you blocked %@" = "ön letiltotta %@-t";
/* No comment provided by engineer. */
"You can accept calls from lock screen, without device and app authentication." = "Hívásokat fogadhat a lezárási képernyőről, eszköz- és alkalmazáshitelesítés nélkül.";
@@ -4983,7 +4997,7 @@
"You can hide or mute a user profile - swipe it to the right." = "Elrejtheti vagy lenémíthatja a felhasználó profiljait - csúsztassa jobbra a profilt.";
/* No comment provided by engineer. */
"You can make it visible to your SimpleX contacts via Settings." = "Láthatóvá teheti a SimpleXbeli ismerősei számára a Beállításokban.";
"You can make it visible to your SimpleX contacts via Settings." = "Láthatóvá teheti SimpleX ismerősök számára a Beállításokban.";
/* notification body */
"You can now chat with %@" = "Mostantól küldhet üzeneteket %@ számára";
@@ -5097,7 +5111,7 @@
"You will be connected to group when the group host's device is online, please wait or check later!" = "Akkor lesz kapcsolódva a csoporthoz, amikor a csoport tulajdonosának eszköze online lesz, várjon, vagy ellenőrizze később!";
/* No comment provided by engineer. */
"You will be connected when group link host's device is online, please wait or check later!" = "Akkor lesz kapcsolódva, amikor a csoporthivatkozás tulajdonosának eszköze online lesz, várjon, vagy ellenőrizze később!";
"You will be connected when group link host's device is online, please wait or check later!" = "Akkor lesz kapcsolódva, amikor a csoportos hivatkozás tulajdonosának eszköze online lesz, várjon, vagy ellenőrizze később!";
/* No comment provided by engineer. */
"You will be connected when your connection request is accepted, please wait or check later!" = "Akkor lesz kapcsolódva, ha a kapcsolódási kérelme elfogadásra kerül, várjon, vagy ellenőrizze később!";
@@ -5175,7 +5189,7 @@
"Your profile **%@** will be shared." = "A(z) **%@** nevű profilja megosztásra fog kerülni.";
/* No comment provided by engineer. */
"Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." = "Profilja az eszközön van tárolva, és csak az ismerősökkel kerül megosztásra. A SimpleX kiszolgálók nem látjhatják profilját.";
"Your profile is stored on your device and shared only with your contacts.\nSimpleX servers cannot see your profile." = "Profilja az eszközön van tárolva, és csak az ismerősökkel kerül megosztásra.\nA SimpleX kiszolgálók nem látjhatják profilját.";
/* No comment provided by engineer. */
"Your profile, contacts and delivered messages are stored on your device." = "Profilja, ismerősei és az elküldött üzenetei az eszközön kerülnek tárolásra.";
@@ -5193,7 +5207,7 @@
"Your settings" = "Beállítások";
/* No comment provided by engineer. */
"Your SimpleX address" = "Profil SimpleX címe";
"Your SimpleX address" = "Az ön SimpleX címe";
/* No comment provided by engineer. */
"Your SMP servers" = "SMP kiszolgálók";
+19 -5
View File
@@ -781,7 +781,7 @@
/* No comment provided by engineer. */
"Can't message member" = "Impossibile inviare un messaggio al membro";
/* alert button */
/* No comment provided by engineer. */
"Cancel" = "Annulla";
/* No comment provided by engineer. */
@@ -2203,6 +2203,9 @@
/* No comment provided by engineer. */
"Full name (optional)" = "Nome completo (facoltativo)";
/* No comment provided by engineer. */
"Full name:" = "Nome completo:";
/* No comment provided by engineer. */
"Fully decentralized visible only to members." = "Completamente decentralizzato: visibile solo ai membri.";
@@ -3375,6 +3378,12 @@
/* No comment provided by engineer. */
"Profile images" = "Immagini del profilo";
/* No comment provided by engineer. */
"Profile name" = "Nome del profilo";
/* No comment provided by engineer. */
"Profile name:" = "Nome del profilo:";
/* No comment provided by engineer. */
"Profile password" = "Password del profilo";
@@ -3706,11 +3715,10 @@
/* No comment provided by engineer. */
"Safer groups" = "Gruppi più sicuri";
/* alert button
chat item action */
/* chat item action */
"Save" = "Salva";
/* alert button */
/* No comment provided by engineer. */
"Save (and notify contacts)" = "Salva (e avvisa i contatti)";
/* No comment provided by engineer. */
@@ -3728,6 +3736,9 @@
/* No comment provided by engineer. */
"Save archive" = "Salva archivio";
/* No comment provided by engineer. */
"Save auto-accept settings" = "Salva le impostazioni di accettazione automatica";
/* No comment provided by engineer. */
"Save group profile" = "Salva il profilo del gruppo";
@@ -3749,6 +3760,9 @@
/* No comment provided by engineer. */
"Save servers?" = "Salvare i server?";
/* No comment provided by engineer. */
"Save settings?" = "Salvare le impostazioni?";
/* No comment provided by engineer. */
"Save welcome message?" = "Salvare il messaggio di benvenuto?";
@@ -5175,7 +5189,7 @@
"Your profile **%@** will be shared." = "Verrà condiviso il tuo profilo **%@**.";
/* No comment provided by engineer. */
"Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." = "Il tuo profilo è memorizzato sul tuo dispositivo e condiviso solo con i tuoi contatti. I server di SimpleX non possono vedere il tuo profilo.";
"Your profile is stored on your device and shared only with your contacts.\nSimpleX servers cannot see your profile." = "Il tuo profilo è memorizzato sul tuo dispositivo e condiviso solo con i tuoi contatti.\nI server di SimpleX non possono vedere il tuo profilo.";
/* No comment provided by engineer. */
"Your profile, contacts and delivered messages are stored on your device." = "Il tuo profilo, i contatti e i messaggi recapitati sono memorizzati sul tuo dispositivo.";
+13 -5
View File
@@ -619,7 +619,7 @@
/* No comment provided by engineer. */
"Can't invite contacts!" = "連絡先を招待できません!";
/* alert button */
/* No comment provided by engineer. */
"Cancel" = "中止";
/* feature offered item */
@@ -1594,6 +1594,9 @@
/* No comment provided by engineer. */
"Full name (optional)" = "フルネーム (任意)";
/* No comment provided by engineer. */
"Full name:" = "フルネーム:";
/* No comment provided by engineer. */
"Fully re-implemented - work in background!" = "完全に再実装されました - バックグラウンドで動作します!";
@@ -2644,11 +2647,10 @@
/* No comment provided by engineer. */
"Run chat" = "チャット起動";
/* alert button
chat item action */
/* chat item action */
"Save" = "保存";
/* alert button */
/* No comment provided by engineer. */
"Save (and notify contacts)" = "保存(連絡先に通知)";
/* No comment provided by engineer. */
@@ -2663,6 +2665,9 @@
/* No comment provided by engineer. */
"Save archive" = "アーカイブを保存";
/* No comment provided by engineer. */
"Save auto-accept settings" = "自動受け入れ設定を保存する";
/* No comment provided by engineer. */
"Save group profile" = "グループプロフィールの保存";
@@ -2684,6 +2689,9 @@
/* No comment provided by engineer. */
"Save servers?" = "サーバを保存しますか?";
/* No comment provided by engineer. */
"Save settings?" = "設定を保存しますか?";
/* No comment provided by engineer. */
"Save welcome message?" = "ウェルカムメッセージを保存しますか?";
@@ -3558,7 +3566,7 @@
"Your profile **%@** will be shared." = "あなたのプロファイル **%@** が共有されます。";
/* No comment provided by engineer. */
"Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." = "プロフィールはデバイスに保存され、連絡先とのみ共有されます。 SimpleX サーバーはあなたのプロファイルを参照できません。";
"Your profile is stored on your device and shared only with your contacts.\nSimpleX servers cannot see your profile." = "プロフィールはデバイスに保存され、連絡先とのみ共有されます。\nSimpleX サーバーはあなたのプロファイルを参照できません。";
/* No comment provided by engineer. */
"Your profile, contacts and delivered messages are stored on your device." = "あなたのプロフィール、連絡先、送信したメッセージがご自分の端末に保存されます。";
+19 -5
View File
@@ -781,7 +781,7 @@
/* No comment provided by engineer. */
"Can't message member" = "Kan geen bericht sturen naar lid";
/* alert button */
/* No comment provided by engineer. */
"Cancel" = "Annuleren";
/* No comment provided by engineer. */
@@ -2203,6 +2203,9 @@
/* No comment provided by engineer. */
"Full name (optional)" = "Volledige naam (optioneel)";
/* No comment provided by engineer. */
"Full name:" = "Volledige naam:";
/* No comment provided by engineer. */
"Fully decentralized visible only to members." = "Volledig gedecentraliseerd alleen zichtbaar voor leden.";
@@ -3375,6 +3378,12 @@
/* No comment provided by engineer. */
"Profile images" = "Profiel afbeeldingen";
/* No comment provided by engineer. */
"Profile name" = "Profielnaam";
/* No comment provided by engineer. */
"Profile name:" = "Profielnaam:";
/* No comment provided by engineer. */
"Profile password" = "Profiel wachtwoord";
@@ -3706,11 +3715,10 @@
/* No comment provided by engineer. */
"Safer groups" = "Veiligere groepen";
/* alert button
chat item action */
/* chat item action */
"Save" = "Opslaan";
/* alert button */
/* No comment provided by engineer. */
"Save (and notify contacts)" = "Bewaar (en informeer contacten)";
/* No comment provided by engineer. */
@@ -3728,6 +3736,9 @@
/* No comment provided by engineer. */
"Save archive" = "Bewaar archief";
/* No comment provided by engineer. */
"Save auto-accept settings" = "Sla instellingen voor automatisch accepteren op";
/* No comment provided by engineer. */
"Save group profile" = "Groep profiel opslaan";
@@ -3749,6 +3760,9 @@
/* No comment provided by engineer. */
"Save servers?" = "Servers opslaan?";
/* No comment provided by engineer. */
"Save settings?" = "Instellingen opslaan?";
/* No comment provided by engineer. */
"Save welcome message?" = "Welkom bericht opslaan?";
@@ -5175,7 +5189,7 @@
"Your profile **%@** will be shared." = "Uw profiel **%@** wordt gedeeld.";
/* No comment provided by engineer. */
"Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." = "Uw profiel wordt op uw apparaat opgeslagen en alleen gedeeld met uw contacten. SimpleX servers kunnen uw profiel niet zien.";
"Your profile is stored on your device and shared only with your contacts.\nSimpleX servers cannot see your profile." = "Uw profiel wordt op uw apparaat opgeslagen en alleen gedeeld met uw contacten.\nSimpleX servers kunnen uw profiel niet zien.";
/* No comment provided by engineer. */
"Your profile, contacts and delivered messages are stored on your device." = "Uw profiel, contacten en afgeleverde berichten worden op uw apparaat opgeslagen.";
+19 -5
View File
@@ -781,7 +781,7 @@
/* No comment provided by engineer. */
"Can't message member" = "Nie można wysłać wiadomości do członka";
/* alert button */
/* No comment provided by engineer. */
"Cancel" = "Anuluj";
/* No comment provided by engineer. */
@@ -2203,6 +2203,9 @@
/* No comment provided by engineer. */
"Full name (optional)" = "Pełna nazwa (opcjonalna)";
/* No comment provided by engineer. */
"Full name:" = "Pełna nazwa:";
/* No comment provided by engineer. */
"Fully decentralized visible only to members." = "W pełni zdecentralizowana widoczna tylko dla członków.";
@@ -3375,6 +3378,12 @@
/* No comment provided by engineer. */
"Profile images" = "Zdjęcia profilowe";
/* No comment provided by engineer. */
"Profile name" = "Nazwa profilu";
/* No comment provided by engineer. */
"Profile name:" = "Nazwa profilu:";
/* No comment provided by engineer. */
"Profile password" = "Hasło profilu";
@@ -3706,11 +3715,10 @@
/* No comment provided by engineer. */
"Safer groups" = "Bezpieczniejsze grupy";
/* alert button
chat item action */
/* chat item action */
"Save" = "Zapisz";
/* alert button */
/* No comment provided by engineer. */
"Save (and notify contacts)" = "Zapisz (i powiadom kontakty)";
/* No comment provided by engineer. */
@@ -3728,6 +3736,9 @@
/* No comment provided by engineer. */
"Save archive" = "Zapisz archiwum";
/* No comment provided by engineer. */
"Save auto-accept settings" = "Zapisz ustawienia automatycznej akceptacji";
/* No comment provided by engineer. */
"Save group profile" = "Zapisz profil grupy";
@@ -3749,6 +3760,9 @@
/* No comment provided by engineer. */
"Save servers?" = "Zapisać serwery?";
/* No comment provided by engineer. */
"Save settings?" = "Zapisać ustawienia?";
/* No comment provided by engineer. */
"Save welcome message?" = "Zapisać wiadomość powitalną?";
@@ -5175,7 +5189,7 @@
"Your profile **%@** will be shared." = "Twój profil **%@** zostanie udostępniony.";
/* No comment provided by engineer. */
"Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." = "Twój profil jest przechowywany na urządzeniu i udostępniany tylko Twoim kontaktom. Serwery SimpleX nie mogą zobaczyć Twojego profilu.";
"Your profile is stored on your device and shared only with your contacts.\nSimpleX servers cannot see your profile." = "Twój profil jest przechowywany na urządzeniu i udostępniany tylko Twoim kontaktom.\nSerwery SimpleX nie mogą zobaczyć Twojego profilu.";
/* No comment provided by engineer. */
"Your profile, contacts and delivered messages are stored on your device." = "Twój profil, kontakty i dostarczone wiadomości są przechowywane na Twoim urządzeniu.";
+19 -5
View File
@@ -781,7 +781,7 @@
/* No comment provided by engineer. */
"Can't message member" = "Не удается написать члену группы";
/* alert button */
/* No comment provided by engineer. */
"Cancel" = "Отменить";
/* No comment provided by engineer. */
@@ -2203,6 +2203,9 @@
/* No comment provided by engineer. */
"Full name (optional)" = "Полное имя (не обязательно)";
/* No comment provided by engineer. */
"Full name:" = "Полное имя:";
/* No comment provided by engineer. */
"Fully decentralized visible only to members." = "Группа полностью децентрализована – она видна только членам.";
@@ -3375,6 +3378,12 @@
/* No comment provided by engineer. */
"Profile images" = "Картинки профилей";
/* No comment provided by engineer. */
"Profile name" = "Имя профиля";
/* No comment provided by engineer. */
"Profile name:" = "Имя профиля:";
/* No comment provided by engineer. */
"Profile password" = "Пароль профиля";
@@ -3706,11 +3715,10 @@
/* No comment provided by engineer. */
"Safer groups" = "Более безопасные группы";
/* alert button
chat item action */
/* chat item action */
"Save" = "Сохранить";
/* alert button */
/* No comment provided by engineer. */
"Save (and notify contacts)" = "Сохранить (и уведомить контакты)";
/* No comment provided by engineer. */
@@ -3728,6 +3736,9 @@
/* No comment provided by engineer. */
"Save archive" = "Сохранить архив";
/* No comment provided by engineer. */
"Save auto-accept settings" = "Сохранить настройки автоприема";
/* No comment provided by engineer. */
"Save group profile" = "Сохранить профиль группы";
@@ -3749,6 +3760,9 @@
/* No comment provided by engineer. */
"Save servers?" = "Сохранить серверы?";
/* No comment provided by engineer. */
"Save settings?" = "Сохранить настройки?";
/* No comment provided by engineer. */
"Save welcome message?" = "Сохранить приветственное сообщение?";
@@ -5175,7 +5189,7 @@
"Your profile **%@** will be shared." = "Будет отправлен Ваш профиль **%@**.";
/* No comment provided by engineer. */
"Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." = "Ваш профиль хранится на Вашем устройстве и отправляется только Вашим контактам. SimpleX серверы не могут получить доступ к Вашему профилю.";
"Your profile is stored on your device and shared only with your contacts.\nSimpleX servers cannot see your profile." = "Ваш профиль хранится на Вашем устройстве и отправляется только Вашим контактам.\nSimpleX серверы не могут получить доступ к Вашему профилю.";
/* No comment provided by engineer. */
"Your profile, contacts and delivered messages are stored on your device." = "Ваш профиль, контакты и доставленные сообщения хранятся на Вашем устройстве.";
+13 -5
View File
@@ -523,7 +523,7 @@
/* No comment provided by engineer. */
"Can't invite contacts!" = "ไม่สามารถเชิญผู้ติดต่อได้!";
/* alert button */
/* No comment provided by engineer. */
"Cancel" = "ยกเลิก";
/* feature offered item */
@@ -1468,6 +1468,9 @@
/* No comment provided by engineer. */
"Full name (optional)" = "ชื่อเต็ม (ไม่บังคับ)";
/* No comment provided by engineer. */
"Full name:" = "ชื่อเต็ม:";
/* No comment provided by engineer. */
"Fully re-implemented - work in background!" = "ดำเนินการใหม่อย่างสมบูรณ์ - ทำงานในพื้นหลัง!";
@@ -2500,11 +2503,10 @@
/* No comment provided by engineer. */
"Run chat" = "เรียกใช้แชท";
/* alert button
chat item action */
/* chat item action */
"Save" = "บันทึก";
/* alert button */
/* No comment provided by engineer. */
"Save (and notify contacts)" = "บันทึก (และแจ้งผู้ติดต่อ)";
/* No comment provided by engineer. */
@@ -2519,6 +2521,9 @@
/* No comment provided by engineer. */
"Save archive" = "บันทึกไฟล์เก็บถาวร";
/* No comment provided by engineer. */
"Save auto-accept settings" = "บันทึกการตั้งค่าการยอมรับอัตโนมัติ";
/* No comment provided by engineer. */
"Save group profile" = "บันทึกโปรไฟล์กลุ่ม";
@@ -2540,6 +2545,9 @@
/* No comment provided by engineer. */
"Save servers?" = "บันทึกเซิร์ฟเวอร์?";
/* No comment provided by engineer. */
"Save settings?" = "บันทึกการตั้งค่า?";
/* No comment provided by engineer. */
"Save welcome message?" = "บันทึกข้อความต้อนรับ?";
@@ -3405,7 +3413,7 @@
"Your privacy" = "ความเป็นส่วนตัวของคุณ";
/* No comment provided by engineer. */
"Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." = "โปรไฟล์ของคุณจะถูกจัดเก็บไว้ในอุปกรณ์ของคุณและแชร์กับผู้ติดต่อของคุณเท่านั้น เซิร์ฟเวอร์ SimpleX ไม่สามารถดูโปรไฟล์ของคุณได้";
"Your profile is stored on your device and shared only with your contacts.\nSimpleX servers cannot see your profile." = "โปรไฟล์ของคุณจะถูกจัดเก็บไว้ในอุปกรณ์ของคุณและแชร์กับผู้ติดต่อของคุณเท่านั้น\nเซิร์ฟเวอร์ SimpleX ไม่สามารถดูโปรไฟล์ของคุณได้";
/* No comment provided by engineer. */
"Your profile, contacts and delivered messages are stored on your device." = "โปรไฟล์ รายชื่อผู้ติดต่อ และข้อความที่ส่งของคุณจะถูกจัดเก็บไว้ในอุปกรณ์ของคุณ";
+19 -5
View File
@@ -703,7 +703,7 @@
/* No comment provided by engineer. */
"Can't invite contacts!" = "Kişiler davet edilemiyor!";
/* alert button */
/* No comment provided by engineer. */
"Cancel" = "İptal et";
/* No comment provided by engineer. */
@@ -1930,6 +1930,9 @@
/* No comment provided by engineer. */
"Full name (optional)" = "Bütün isim (opsiyonel)";
/* No comment provided by engineer. */
"Full name:" = "Bütün isim:";
/* No comment provided by engineer. */
"Fully decentralized visible only to members." = "Tamamiyle merkezi olmayan - sadece kişilere görünür.";
@@ -2988,6 +2991,12 @@
/* No comment provided by engineer. */
"Profile images" = "Profil resimleri";
/* No comment provided by engineer. */
"Profile name" = "Profil ismi";
/* No comment provided by engineer. */
"Profile name:" = "Profil ismi:";
/* No comment provided by engineer. */
"Profile password" = "Profil parolası";
@@ -3262,11 +3271,10 @@
/* No comment provided by engineer. */
"Safer groups" = "Daha güvenli gruplar";
/* alert button
chat item action */
/* chat item action */
"Save" = "Kaydet";
/* alert button */
/* No comment provided by engineer. */
"Save (and notify contacts)" = "Kaydet (ve kişilere bildir)";
/* No comment provided by engineer. */
@@ -3281,6 +3289,9 @@
/* No comment provided by engineer. */
"Save archive" = "Arşivi kaydet";
/* No comment provided by engineer. */
"Save auto-accept settings" = "Otomatik kabul et ayarlarını kaydet";
/* No comment provided by engineer. */
"Save group profile" = "Grup profilini kaydet";
@@ -3302,6 +3313,9 @@
/* No comment provided by engineer. */
"Save servers?" = "Sunucular kaydedilsin mi?";
/* No comment provided by engineer. */
"Save settings?" = "Ayarlar kaydedilsin mi?";
/* No comment provided by engineer. */
"Save welcome message?" = "Hoşgeldin mesajı kaydedilsin mi?";
@@ -4530,7 +4544,7 @@
"Your profile **%@** will be shared." = "Profiliniz **%@** paylaşılacaktır.";
/* No comment provided by engineer. */
"Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." = "Profiliniz cihazınızda saklanır ve sadece kişilerinizle paylaşılır. SimpleX sunucuları profilinizi göremez.";
"Your profile is stored on your device and shared only with your contacts.\nSimpleX servers cannot see your profile." = "Profiliniz cihazınızda saklanır ve sadece kişilerinizle paylaşılır.\nSimpleX sunucuları profilinizi göremez.";
/* No comment provided by engineer. */
"Your profile, contacts and delivered messages are stored on your device." = "Profiliniz, kişileriniz ve gönderilmiş mesajlar cihazınızda saklanır.";
+19 -5
View File
@@ -781,7 +781,7 @@
/* No comment provided by engineer. */
"Can't message member" = "Не можу надіслати повідомлення користувачеві";
/* alert button */
/* No comment provided by engineer. */
"Cancel" = "Скасувати";
/* No comment provided by engineer. */
@@ -2203,6 +2203,9 @@
/* No comment provided by engineer. */
"Full name (optional)" = "Повне ім'я (необов'язково)";
/* No comment provided by engineer. */
"Full name:" = "Повне ім'я:";
/* No comment provided by engineer. */
"Fully decentralized visible only to members." = "Повністю децентралізована - видима лише для учасників.";
@@ -3375,6 +3378,12 @@
/* No comment provided by engineer. */
"Profile images" = "Зображення профілю";
/* No comment provided by engineer. */
"Profile name" = "Назва профілю";
/* No comment provided by engineer. */
"Profile name:" = "Ім'я профілю:";
/* No comment provided by engineer. */
"Profile password" = "Пароль до профілю";
@@ -3706,11 +3715,10 @@
/* No comment provided by engineer. */
"Safer groups" = "Безпечніші групи";
/* alert button
chat item action */
/* chat item action */
"Save" = "Зберегти";
/* alert button */
/* No comment provided by engineer. */
"Save (and notify contacts)" = "Зберегти (і повідомити контактам)";
/* No comment provided by engineer. */
@@ -3728,6 +3736,9 @@
/* No comment provided by engineer. */
"Save archive" = "Зберегти архів";
/* No comment provided by engineer. */
"Save auto-accept settings" = "Зберегти налаштування автоприйому";
/* No comment provided by engineer. */
"Save group profile" = "Зберегти профіль групи";
@@ -3749,6 +3760,9 @@
/* No comment provided by engineer. */
"Save servers?" = "Зберегти сервери?";
/* No comment provided by engineer. */
"Save settings?" = "Зберегти налаштування?";
/* No comment provided by engineer. */
"Save welcome message?" = "Зберегти вітальне повідомлення?";
@@ -5175,7 +5189,7 @@
"Your profile **%@** will be shared." = "Ваш профіль **%@** буде опублікований.";
/* No comment provided by engineer. */
"Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." = "Ваш профіль зберігається на вашому пристрої і доступний лише вашим контактам. Сервери SimpleX не бачать ваш профіль.";
"Your profile is stored on your device and shared only with your contacts.\nSimpleX servers cannot see your profile." = "Ваш профіль зберігається на вашому пристрої і доступний лише вашим контактам.\nСервери SimpleX не бачать ваш профіль.";
/* No comment provided by engineer. */
"Your profile, contacts and delivered messages are stored on your device." = "Ваш профіль, контакти та доставлені повідомлення зберігаються на вашому пристрої.";
File diff suppressed because it is too large Load Diff
@@ -7,9 +7,6 @@
/* Privacy - Face ID Usage Description */
"NSFaceIDUsageDescription" = "SimpleX 使用Face ID进行本地身份验证";
/* Privacy - Local Network Usage Description */
"NSLocalNetworkUsageDescription" = "SimpleX 使用本地网络访问,允许通过同一网络上的桌面应用程序使用用户聊天配置文件。";
/* Privacy - Microphone Usage Description */
"NSMicrophoneUsageDescription" = "SimpleX 需要麦克风访问权限才能进行音频和视频通话,以及录制语音消息。";
@@ -5,8 +5,9 @@ import android.util.Log
import androidx.work.*
import chat.simplex.app.SimplexService.Companion.showPassphraseNotification
import chat.simplex.common.model.ChatController
import chat.simplex.common.platform.*
import chat.simplex.common.views.helpers.DBMigrationResult
import chat.simplex.common.platform.chatModel
import chat.simplex.common.platform.initChatControllerOnStart
import chat.simplex.common.views.helpers.DatabaseUtils
import kotlinx.coroutines.*
import java.util.Date
@@ -29,12 +30,12 @@ object MessagesFetcherWorker {
.setConstraints(Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build())
.build()
SimplexApp.context.getWorkManagerInstance().enqueueUniqueWork(UNIQUE_WORK_TAG, ExistingWorkPolicy.REPLACE, periodicWorkRequest)
WorkManager.getInstance(SimplexApp.context).enqueueUniqueWork(UNIQUE_WORK_TAG, ExistingWorkPolicy.REPLACE, periodicWorkRequest)
}
fun cancelAll() {
Log.d(TAG, "Worker: canceled all tasks")
SimplexApp.context.getWorkManagerInstance().cancelUniqueWork(UNIQUE_WORK_TAG)
WorkManager.getInstance(SimplexApp.context).cancelUniqueWork(UNIQUE_WORK_TAG)
}
}
@@ -1,5 +1,7 @@
package chat.simplex.app
import android.animation.ArgbEvaluator
import android.animation.ObjectAnimator
import android.annotation.SuppressLint
import android.app.*
import android.content.Context
@@ -7,7 +9,9 @@ import chat.simplex.common.platform.Log
import android.content.Intent
import android.content.pm.ActivityInfo
import android.os.*
import android.view.View
import androidx.compose.animation.core.*
import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.ui.graphics.Color
@@ -66,7 +70,7 @@ class SimplexApp: Application(), LifecycleEventObserver {
}
}
context = this
initHaskell(packageName)
initHaskell()
initMultiplatform()
runMigrations()
tmpDir.deleteRecursively()
@@ -164,7 +168,7 @@ class SimplexApp: Application(), LifecycleEventObserver {
.addTag(SimplexService.SERVICE_START_WORKER_WORK_NAME_PERIODIC)
.build()
Log.d(TAG, "ServiceStartWorker: Scheduling period work every ${SimplexService.SERVICE_START_WORKER_INTERVAL_MINUTES} minutes")
getWorkManagerInstance().enqueueUniquePeriodicWork(SimplexService.SERVICE_START_WORKER_WORK_NAME_PERIODIC, workPolicy, work)
WorkManager.getInstance(context)?.enqueueUniquePeriodicWork(SimplexService.SERVICE_START_WORKER_WORK_NAME_PERIODIC, workPolicy, work)
}
fun schedulePeriodicWakeUp() = CoroutineScope(Dispatchers.Default).launch {
@@ -276,7 +280,7 @@ class SimplexApp: Application(), LifecycleEventObserver {
override fun androidSetDrawerStatusAndNavBarColor(
isLight: Boolean,
drawerShadingColor: Color,
drawerShadingColor: Animatable<Color, AnimationVector4D>,
toolbarOnTop: Boolean,
navBarColor: Color,
) {
@@ -287,7 +291,7 @@ class SimplexApp: Application(), LifecycleEventObserver {
// Blend status bar color to the animated color
val colors = CurrentColors.value.colors
val baseBackgroundColor = if (toolbarOnTop) colors.background.mixWith(colors.onBackground, 0.97f) else colors.background
window.statusBarColor = baseBackgroundColor.mixWith(drawerShadingColor.copy(1f), 1 - drawerShadingColor.alpha).toArgb()
window.statusBarColor = baseBackgroundColor.mixWith(drawerShadingColor.value.copy(1f), 1 - drawerShadingColor.value.alpha).toArgb()
val navBar = navBarColor.toArgb()
if (window.navigationBarColor != navBar) {
@@ -292,7 +292,7 @@ class SimplexService: Service() {
fun scheduleStart(context: Context) {
Log.d(TAG, "Enqueuing work to start subscriber service")
val workManager = context.getWorkManagerInstance()
val workManager = WorkManager.getInstance(context)
val startServiceRequest = OneTimeWorkRequest.Builder(ServiceStartWorker::class.java).build()
workManager.enqueueUniqueWork(WORK_NAME_ONCE, ExistingWorkPolicy.KEEP, startServiceRequest) // Unique avoids races!
}
+2 -7
View File
@@ -99,15 +99,10 @@ kotlin {
val desktopMain by getting {
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-swing:1.8.0")
implementation("com.github.Dansoftowner:jSystemThemeDetector:3.8") {
exclude("net.java.dev.jna")
}
// For jSystemThemeDetector only
implementation("net.java.dev.jna:jna-platform:5.14.0")
implementation("com.github.Dansoftowner:jSystemThemeDetector:3.8")
implementation("com.sshtools:two-slices:0.9.0-SNAPSHOT")
implementation("org.slf4j:slf4j-simple:2.0.12")
implementation("uk.co.caprica:vlcj:4.8.3")
implementation("net.java.dev.jna:jna:5.14.0")
implementation("uk.co.caprica:vlcj:4.8.2")
implementation("com.github.NanoHttpd.nanohttpd:nanohttpd:efb2ebf85a")
implementation("com.github.NanoHttpd.nanohttpd:nanohttpd-websocket:efb2ebf85a")
implementation("com.squareup.okhttp3:okhttp:4.12.0")
@@ -6,8 +6,6 @@ import android.net.LocalServerSocket
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.fragment.app.FragmentActivity
import androidx.work.Configuration
import androidx.work.WorkManager
import java.io.*
import java.lang.ref.WeakReference
import java.util.*
@@ -31,19 +29,22 @@ lateinit var androidAppContext: Context
var mainActivity: WeakReference<FragmentActivity> = WeakReference(null)
var callActivity: WeakReference<ComponentActivity> = WeakReference(null)
fun initHaskell(packageName: String) {
fun initHaskell() {
val socketName = "chat.simplex.app.local.socket.address.listen.native.cmd2" + Random.nextLong(100000)
val s = Semaphore(0)
thread(name="stdout/stderr pipe") {
Log.d(TAG, "starting server")
val server: LocalServerSocket
try {
server = LocalServerSocket(packageName)
} catch (e: IOException) {
Log.e(TAG, e.stackTraceToString())
Log.e(TAG, "Unable to setup local server socket. Contact developers")
s.release()
// Will not have logs from backend
return@thread
var server: LocalServerSocket? = null
for (i in 0..100) {
try {
server = LocalServerSocket(socketName + i)
break
} catch (e: IOException) {
Log.e(TAG, e.stackTraceToString())
}
}
if (server == null) {
throw Error("Unable to setup local server socket. Contact developers")
}
Log.d(TAG, "started server")
s.release()
@@ -57,7 +58,7 @@ fun initHaskell(packageName: String) {
Log.d(TAG, "starting receiver loop")
while (true) {
val line = input.readLine() ?: break
Log.w(TAG, "(stdout/stderr) $line")
Log.w("$TAG (stdout/stderr)", line)
logbuffer.add(line)
}
Log.w(TAG, "exited receiver loop")
@@ -67,20 +68,7 @@ fun initHaskell(packageName: String) {
System.loadLibrary("app-lib")
s.acquire()
pipeStdOutToSocket(packageName)
pipeStdOutToSocket(socketName)
initHS()
}
fun Context.getWorkManagerInstance(): WorkManager {
// https://github.com/OneSignal/OneSignal-Android-SDK/pull/2052/files
// https://github.com/OneSignal/OneSignal-Android-SDK/issues/1672
if (!WorkManager.isInitialized()) {
try {
WorkManager.initialize(this, Configuration.Builder().build())
} catch (e: IllegalStateException) {
Log.e(TAG, "Error initializing WorkManager: ${e.stackTraceToString()}")
}
}
return WorkManager.getInstance(this)
}
@@ -1,9 +1,8 @@
package chat.simplex.common.views.chatlist
import SectionItemView
import androidx.compose.animation.*
import androidx.compose.foundation.*
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.material.DrawerDefaults.ScrimOpacity
@@ -11,22 +10,23 @@ import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.graphics.*
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.unit.*
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import chat.simplex.common.model.ChatController.appPrefs
import chat.simplex.common.model.User
import chat.simplex.common.model.UserInfo
import chat.simplex.common.platform.*
import chat.simplex.common.platform.appPlatform
import chat.simplex.common.platform.platform
import chat.simplex.common.ui.theme.*
import chat.simplex.common.views.helpers.*
import chat.simplex.common.views.onboarding.OnboardingStage
import chat.simplex.res.MR
import dev.icerock.moko.resources.compose.painterResource
import dev.icerock.moko.resources.compose.stringResource
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.launch
@Composable
actual fun UserPickerInactiveUsersSection(
@@ -38,13 +38,7 @@ actual fun UserPickerInactiveUsersSection(
val scrollState = rememberScrollState()
if (users.isNotEmpty()) {
SectionItemView(
padding = PaddingValues(
start = 16.dp,
top = if (windowOrientation() == WindowOrientation.PORTRAIT) DEFAULT_MIN_SECTION_ITEM_PADDING_VERTICAL else DEFAULT_PADDING_HALF,
bottom = DEFAULT_PADDING_HALF),
disabled = stopped
) {
SectionItemView(padding = PaddingValues(start = 16.dp, top = DEFAULT_MIN_SECTION_ITEM_PADDING_VERTICAL, bottom = DEFAULT_PADDING_HALF), disabled = stopped) {
Box {
Row(
modifier = Modifier.padding(end = DEFAULT_PADDING + 30.dp).horizontalScroll(scrollState)
@@ -52,10 +46,6 @@ actual fun UserPickerInactiveUsersSection(
users.forEach { u ->
UserPickerInactiveUserBadge(u, stopped) {
onUserClicked(it)
withBGApi {
delay(500)
scrollState.scrollTo(0)
}
}
Spacer(Modifier.width(20.dp))
}
@@ -110,113 +100,88 @@ actual fun UserPickerInactiveUsersSection(
}
}
private fun calculateFraction(pos: Float) =
(pos / 1f).coerceIn(0f, 1f)
@Composable
actual fun PlatformUserPicker(modifier: Modifier, pickerState: MutableStateFlow<AnimatedViewState>, content: @Composable () -> Unit) {
val pickerIsVisible = pickerState.collectAsState().value.isVisible()
val dismissState = rememberDismissState(initialValue = if (pickerIsVisible) DismissValue.Default else DismissValue.DismissedToEnd) {
if (it == DismissValue.DismissedToEnd && pickerState.value.isVisible()) {
pickerState.value = AnimatedViewState.HIDING
actual fun UserPickerScaffold(pickerState: MutableStateFlow<AnimatedViewState>, content: @Composable () -> Unit) {
val currentTheme by CurrentColors.collectAsState()
val resultingColor by remember {
derivedStateOf {
if (currentTheme.colors.isLight) currentTheme.colors.onSurface.copy(alpha = ScrimOpacity) else Color.Black.copy(0.64f)
}
true
}
val height = remember { mutableIntStateOf(0) }
val heightValue = height.intValue
val clickableModifier = if (pickerIsVisible) {
Modifier.clickable(interactionSource = remember { MutableInteractionSource() }, indication = null, onClick = { pickerState.value = AnimatedViewState.HIDING })
} else {
Modifier
val animatedColor = remember {
androidx.compose.animation.core.Animatable(
if (pickerState.value.isVisible()) Color.Transparent else resultingColor,
Color.VectorConverter(resultingColor.colorSpace)
)
}
Box(
Modifier
.fillMaxSize()
.then(clickableModifier)
.drawBehind {
val pos = when {
dismissState.progress.from == DismissValue.Default && dismissState.progress.to == DismissValue.Default -> 1f
dismissState.progress.from == DismissValue.DismissedToEnd && dismissState.progress.to == DismissValue.DismissedToEnd -> 0f
dismissState.progress.to == DismissValue.Default -> dismissState.progress.fraction
else -> 1 - dismissState.progress.fraction
}
val colors = CurrentColors.value.colors
val resultingColor = if (colors.isLight) colors.onSurface.copy(alpha = ScrimOpacity) else Color.Black.copy(0.64f)
val adjustedAlpha = resultingColor.alpha * calculateFraction(pos = pos)
val shadingColor = resultingColor.copy(alpha = adjustedAlpha)
if (pickerState.value.isVisible()) {
platform.androidSetDrawerStatusAndNavBarColor(
isLight = colors.isLight,
drawerShadingColor = shadingColor,
toolbarOnTop = !appPrefs.oneHandUI.get(),
navBarColor = colors.surface
)
} else if (ModalManager.start.modalCount.value == 0) {
platform.androidSetDrawerStatusAndNavBarColor(
isLight = colors.isLight,
drawerShadingColor = shadingColor,
toolbarOnTop = !appPrefs.oneHandUI.get(),
navBarColor = (if (appPrefs.oneHandUI.get() && appPrefs.onboardingStage.get() == OnboardingStage.OnboardingComplete) {
colors.background.mixWith(CurrentColors.value.colors.onBackground, 0.97f)
} else {
colors.background
})
)
LaunchedEffect(Unit) {
launch {
snapshotFlow { ModalManager.start.modalCount.value }
.collect { modalCount ->
val colors = CurrentColors.value.colors
if (modalCount == 0 && pickerState.value.isVisible()) {
platform.androidSetDrawerStatusAndNavBarColor(
isLight = colors.isLight,
drawerShadingColor = animatedColor,
toolbarOnTop = !appPrefs.oneHandUI.get(),
navBarColor = colors.surface
)
}
}
}
}
LaunchedEffect(Unit) {
snapshotFlow { currentTheme }
.distinctUntilChanged()
.collect {
launch {
pickerState.collect {
val newState = it
val colors = CurrentColors.value.colors
val toColor = if (colors.isLight) colors.onSurface.copy(alpha = ScrimOpacity) else Color.Black.copy(0.64f)
animatedColor.animateTo(if (newState.isVisible()) toColor else Color.Transparent, newChatSheetAnimSpec()) {
if (newState.isVisible()) {
platform.androidSetDrawerStatusAndNavBarColor(
isLight = colors.isLight,
drawerShadingColor = animatedColor,
toolbarOnTop = !appPrefs.oneHandUI.get(),
navBarColor = colors.surface
)
} else if (newState.isHiding()) {
platform.androidSetDrawerStatusAndNavBarColor(
isLight = colors.isLight,
drawerShadingColor = animatedColor,
toolbarOnTop = !appPrefs.oneHandUI.get(),
navBarColor = (if (appPrefs.oneHandUI.get() && appPrefs.onboardingStage.get() == OnboardingStage.OnboardingComplete) {
colors.background.mixWith(CurrentColors.value.colors.onBackground, 0.97f)
} else {
colors.background
})
)
}
}
}
}
drawRect(
if (pos != 0f) resultingColor else Color.Transparent,
alpha = calculateFraction(pos = pos)
)
}
.graphicsLayer {
if (heightValue == 0) {
alpha = 0f
}
translationY = dismissState.offset.value
},
contentAlignment = Alignment.BottomCenter
) {
Box(
Modifier.onSizeChanged { height.intValue = it.height }
}
Box(Modifier.drawBehind { drawRect(animatedColor.value) }) {
AnimatedVisibility(
visible = pickerState.run { value.isVisible() },
enter = slideInVertically(
initialOffsetY = { it },
animationSpec = userPickerAnimSpec()
) + fadeIn(animationSpec = userPickerAnimSpec()),
exit = slideOutVertically(
targetOffsetY = { it },
animationSpec = userPickerAnimSpec()
) + fadeOut(animationSpec = userPickerAnimSpec())
) {
KeyChangeEffect(pickerIsVisible) {
if (pickerState.value.isVisible()) {
try {
dismissState.animateTo(DismissValue.Default, userPickerAnimSpec())
} catch (e: CancellationException) {
Log.e(TAG, "Cancelled animateTo: ${e.stackTraceToString()}")
pickerState.value = AnimatedViewState.GONE
}
} else {
try {
dismissState.animateTo(DismissValue.DismissedToEnd, userPickerAnimSpec())
} catch (e: CancellationException) {
Log.e(TAG, "Cancelled animateTo2: ${e.stackTraceToString()}")
pickerState.value = AnimatedViewState.VISIBLE
}
}
}
val draggableModifier = if (height.intValue != 0)
Modifier.draggableBottomDrawerModifier(
state = dismissState,
swipeDistance = height.intValue.toFloat(),
)
else Modifier
Box(draggableModifier.then(modifier)) {
content()
}
content()
}
}
}
private fun Modifier.draggableBottomDrawerModifier(
state: DismissState,
swipeDistance: Float,
): Modifier = this.swipeable(
state = state,
anchors = mapOf(0f to DismissValue.Default, swipeDistance to DismissValue.DismissedToEnd),
thresholds = { _, _ -> FractionalThreshold(0.3f) },
orientation = Orientation.Vertical,
resistance = null
)
}
@@ -2,6 +2,7 @@ package chat.simplex.common.views.usersettings
import SectionView
import androidx.compose.runtime.Composable
import androidx.work.WorkManager
import chat.simplex.common.model.ChatModel
import chat.simplex.common.platform.*
import chat.simplex.common.views.helpers.*
@@ -32,7 +33,7 @@ fun restartApp() {
}
private fun shutdownApp() {
androidAppContext.getWorkManagerInstance().cancelAllWork()
WorkManager.getInstance(androidAppContext).cancelAllWork()
platform.androidServiceSafeStop()
Runtime.getRuntime().exit(0)
}

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