mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2025-03-14 09:45:42 +00:00
Compare commits
102 commits
v6.3.0-bet
...
stable
Author | SHA1 | Date | |
---|---|---|---|
![]() |
16cf91902c | ||
![]() |
ed625347bd | ||
![]() |
4bd95c8e4e | ||
![]() |
9dfa68bf57 | ||
![]() |
3188d9f087 | ||
![]() |
89dddab060 | ||
![]() |
f31372a771 | ||
![]() |
3412ceba01 | ||
![]() |
27f63dafaa | ||
![]() |
e2d488266c | ||
![]() |
430e212a9e | ||
![]() |
47adbe2813 | ||
![]() |
cc2a45bdaf | ||
![]() |
ad4adf66ec | ||
![]() |
f53b21f8c6 | ||
![]() |
2d203c1a18 | ||
![]() |
a6631ce629 | ||
![]() |
5bef7349d8 | ||
![]() |
37050a99c9 | ||
![]() |
ca31c9a5e9 | ||
![]() |
a0560a5ad0 | ||
![]() |
a3a27b250c | ||
![]() |
7a3663f1e0 | ||
![]() |
9dac472191 | ||
![]() |
8c7df76c24 | ||
![]() |
3425bd0826 | ||
![]() |
257208a99b | ||
![]() |
8140710660 | ||
![]() |
518ab2cd3e | ||
![]() |
d2e60503f9 | ||
![]() |
7c2153762f | ||
![]() |
0a97218440 | ||
![]() |
2788a1dbb3 | ||
![]() |
1ddf7a62ad | ||
![]() |
8b030075d7 | ||
![]() |
b2de37a9fb | ||
![]() |
27bf19c2b1 | ||
![]() |
3d076a89e7 | ||
![]() |
7471fd2af5 | ||
![]() |
50232fd179 | ||
![]() |
1b757911fa | ||
![]() |
dcea008fb9 | ||
![]() |
dce8502165 | ||
![]() |
fefddb3b5a | ||
![]() |
b482d4d812 | ||
![]() |
1fcb352db4 | ||
![]() |
f701ffa4e0 | ||
![]() |
511ff1d35c | ||
![]() |
981901d587 | ||
![]() |
a5334b36f8 | ||
![]() |
b494c43706 | ||
![]() |
c972298dd2 | ||
![]() |
b96b6c70d2 | ||
![]() |
4f00f9efa0 | ||
![]() |
c81fa7e6b0 | ||
![]() |
41ccb14bfa | ||
![]() |
bf37c0762e | ||
![]() |
bc9885675d | ||
![]() |
dd13450443 | ||
![]() |
e59967b0d6 | ||
![]() |
b27e964d0c | ||
![]() |
ca3687488f | ||
![]() |
676583d3c3 | ||
![]() |
dc980ae88f | ||
![]() |
ec519afb3f | ||
![]() |
9d1329498b | ||
![]() |
704bab171d | ||
![]() |
f2430cc57f | ||
![]() |
5a0821f9fc | ||
![]() |
85409db1cc | ||
![]() |
cb3ace5f71 | ||
![]() |
88bb387b1b | ||
![]() |
7c5966df70 | ||
![]() |
1f8755f941 | ||
![]() |
e9893989df | ||
![]() |
87569e379a | ||
![]() |
dfe5a4464b | ||
![]() |
a90f255df5 | ||
![]() |
8dbebbe3d6 | ||
![]() |
47997fd90b | ||
![]() |
0e40d4b5ff | ||
![]() |
d39b4863b4 | ||
![]() |
e06741c936 | ||
![]() |
e7361cf025 | ||
![]() |
c5bb2c4ca2 | ||
![]() |
3267eb2b27 | ||
![]() |
9533772aa2 | ||
![]() |
205ced1c1d | ||
![]() |
ff35643533 | ||
![]() |
9c28a51fee | ||
![]() |
75388b997e | ||
![]() |
75685df2e8 | ||
![]() |
38c5c19b17 | ||
![]() |
a91599543e | ||
![]() |
83984e482c | ||
![]() |
e4d6a8822c | ||
![]() |
dac8389263 | ||
![]() |
6b7c4509fe | ||
![]() |
e6ddbc1172 | ||
![]() |
5b947b3130 | ||
![]() |
a622cb91f9 | ||
![]() |
844b24be9d |
238 changed files with 21469 additions and 6399 deletions
31
PRIVACY.md
31
PRIVACY.md
|
@ -123,6 +123,16 @@ This section applies only to the experimental group directory operated by Simple
|
|||
|
||||
[SimpleX Directory](/docs/DIRECTORY.md) stores: your search requests, the messages and the members profiles in the registered groups. You can connect to SimpleX Directory via [this address](https://simplex.chat/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion).
|
||||
|
||||
#### Public groups and content channels
|
||||
|
||||
You may participate in a public group and receive content from a public channel (Group). In case you send messages or comments to the Group, you grant a license:
|
||||
- to all recipients:
|
||||
- to share your messages with the new Group members and outside of the group, e.g. via quoting (replying), forwarding and copy-pasting your message. When your message is deleted or marked as deleted, the copies of your message will not be deleted.
|
||||
- to retain a copy of your messages according to the Group settings (e.g., the Group may allow irreversible message deletion from the recipient devices for a limited period of time, or it may only allow to edit and mark messages as deleted on recipient devices). Deleting message from the recipient devices or marking message as deleted revokes the license to share the message.
|
||||
- to Group owners: to share your messages with the new Group members as history of the Group. Currently, the Group history shared with the new members is limited to 100 messages.
|
||||
|
||||
Group owners may use chat relays or automated bots (Chat Relays) to re-broadcast member messages to all members, for efficiency. The Chat Relays may be operated by the group owners, by preset operators or by 3rd parties. The Chat Relays have access to and will retain messages in line with Group settings, for technical functioning of the Group. Neither you nor group owners grant any content license to Chat Relay operators.
|
||||
|
||||
#### User Support
|
||||
|
||||
The app includes support contact operated by SimpleX Chat Ltd. If you contact support, any personal data you share is kept only for the purposes of researching the issue and contacting you about your case. We recommend contacting support [via chat](https://simplex.chat/contact#/?v=1&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FK1rslx-m5bpXVIdMZg9NLUZ_8JBm8xTt%23%2F%3Fv%3D1%26dh%3DMCowBQYDK2VuAyEALDeVe-sG8mRY22LsXlPgiwTNs9dbiLrNuA7f3ZMAJ2w%253D%26srv%3Dbylepyau3ty4czmn77q4fglvperknl4bi2eb2fdy2bh4jxtf32kf73yd.onion) when it is possible, and avoid sharing any personal information.
|
||||
|
@ -131,9 +141,9 @@ The app includes support contact operated by SimpleX Chat Ltd. If you contact su
|
|||
|
||||
Preset server operators will not share the information on their servers with each other, other than aggregate usage statistics.
|
||||
|
||||
Preset server operators will not provide general access to their servers or the data on their servers to each other.
|
||||
Preset server operators must not provide general access to their servers or the data on their servers to each other.
|
||||
|
||||
Preset server operators will provide non-administrative access to control port of preset servers to SimpleX Chat Ltd, for the purposes of removing identified illegal content. This control port access only allows deleting known links and files, and access to aggregate statistics, but does NOT allow enumerating any information on the servers.
|
||||
Preset server operators will provide non-administrative access to control port of preset servers to SimpleX Chat Ltd, for the purposes of removing illegal content identified in publicly accessible resources (contact and group addresses, and downloadable files). This control port access only allows deleting known links and files, and accessing aggregate server-wide statistics, but does NOT allow enumerating any information on the servers or accessing statistics related to specific users.
|
||||
|
||||
### Information Preset Server Operators May Share
|
||||
|
||||
|
@ -148,7 +158,7 @@ The cases when the preset server operators may share the data temporarily stored
|
|||
- To detect, prevent, or otherwise address fraud, security, or technical issues.
|
||||
- To protect against harm to the rights, property, or safety of software users, operators of preset servers, or the public as required or permitted by law.
|
||||
|
||||
At the time of updating this document, the preset server operators have never provided or have been requested the access to the preset relay servers or any information from the servers by any third parties. If the preset server operators are ever requested to provide such access or information, they will follow the due legal process to limit any information shared with the third parties to the minimally required by law.
|
||||
By the time of updating this document, the preset server operators were not served with any enforceable requests and did not provide any information from the servers to any third parties. If the preset server operators are ever requested to provide such access or information, they will follow the due legal process to limit any information shared with the third parties to the minimally required by law.
|
||||
|
||||
Preset server operators will publish information they are legally allowed to share about such requests in the [Transparency reports](./docs/TRANSPARENCY.md).
|
||||
|
||||
|
@ -190,7 +200,18 @@ You accept the Conditions of Use of Software and Infrastructure ("Conditions") b
|
|||
|
||||
**Legal usage**. You agree to use SimpleX Chat Applications only for legal purposes. You will not use (or assist others in using) the Applications in ways that: 1) violate or infringe the rights of Software users, SimpleX Chat Ltd, other preset server operators, or others, including privacy, publicity, intellectual property, or other proprietary rights; 2) involve sending illegal communications, e.g. spam. While server operators cannot access content or identify messages or groups, in some cases the links to the illegal communications can be shared publicly on social media or websites. Preset server operators reserve the right to remove such links from the preset servers and disrupt the conversations that send illegal content via their servers, whether they were reported by the users or discovered by the operators themselves.
|
||||
|
||||
**Damage to SimpleX Chat Ltd and Preset Server Operators**. You must not (or assist others to) access, use, modify, distribute, transfer, or exploit SimpleX Chat Applications in unauthorized manners, or in ways that harm Software users, SimpleX Chat Ltd, other preset server operators, their Infrastructure, or any other systems. For example, you must not 1) access preset operators' Infrastructure or systems without authorization, in any way other than by using the Software; 2) disrupt the integrity or performance of preset operators' Infrastructure; 3) collect information about the users in any manner; or 4) sell, rent, or charge for preset operators' Infrastructure. This does not prohibit you from providing your own Infrastructure to others, whether free or for a fee, as long as you do not violate these Conditions and AGPLv3 license, including the requirement to publish any modifications of the relay server software.
|
||||
**Damage to SimpleX Chat Ltd and Preset Server Operators**. You must not (or assist others to) access, use, modify, distribute, transfer, or exploit SimpleX Chat Applications in unauthorized manners, or in ways that harm Software users, SimpleX Chat Ltd, other preset server operators, their Infrastructure, or any other systems. For example, you must not 1) access preset operators' Infrastructure or systems without authorization, in any way other than by using the Software or by using a 3rd party client applications that satisfies the requirements of the Conditions of use (see the next section); 2) disrupt the integrity or performance of preset operators' Infrastructure; 3) collect information about the users in any manner; or 4) sell, rent, or charge for preset operators' Infrastructure. This does not prohibit you from providing your own Infrastructure to others, whether free or for a fee, as long as you do not violate these Conditions and AGPLv3 license, including the requirement to publish any modifications of the relay server software.
|
||||
|
||||
**3rd party client applications**. You may use a 3rd party application (App) to access preset operators' Infrastructure or systems, provided that this App:
|
||||
- is compatible with the protocol specifications not older than 1 year,
|
||||
- provides user-to-user messaging only or enables automated chat bots sending messages requested by users (in case of bots, it must be made clear to the users that these are automated bots),
|
||||
- implements the same limits, rules and restrictions as Software,
|
||||
- requires that the users accept the same Conditions of use of preset operators' Infrastructure as in Software prior to providing access to this Infrastructure,
|
||||
- displays the notice that it is the App for using SimpleX network,
|
||||
- provides its source code under open-source license accessible to the users via the App interface. In case the App uses the source code of Software, the App's source code must be provided under AGPLv3 license, and in case it is developed without using Software code its source code must be provided under any widely recognized free open-source license,
|
||||
- does NOT use the branding of SimpleX Chat Ltd without the permission,
|
||||
- does NOT pretend to be Software,
|
||||
- complies with these Conditions of use.
|
||||
|
||||
**Keeping your data secure**. SimpleX Chat is the first communication software that aims to be 100% private by design - server software neither has the ability to access your messages, nor it has information about who you communicate with. That means that you are solely responsible for keeping your device, your user profile and any data safe and secure. If you lose your phone or remove the Software from the device, you will not be able to recover the lost data, unless you made a back up. To protect the data you need to make regular backups, as using old backups may disrupt your communication with some of the contacts. SimpleX Chat Ltd and other preset server operators are not responsible for any data loss.
|
||||
|
||||
|
@ -222,4 +243,4 @@ You accept the Conditions of Use of Software and Infrastructure ("Conditions") b
|
|||
|
||||
**Ending these conditions**. You may end these Conditions with SimpleX Chat Ltd and preset server operators at any time by deleting the Applications from your devices and discontinuing use of the Infrastructure of SimpleX Chat Ltd and preset server operators. The provisions related to Licenses, Disclaimers, Limitation of Liability, Resolving dispute, Availability, Changes to the conditions, Enforcing the conditions, and Ending these conditions will survive termination of your relationship with SimpleX Chat Ltd and/or preset server operators.
|
||||
|
||||
Updated November 14, 2024
|
||||
Updated March 3, 2025
|
||||
|
|
|
@ -234,6 +234,10 @@ You can use SimpleX with your own servers and still communicate with people usin
|
|||
|
||||
Recent and important updates:
|
||||
|
||||
[Mar 8, 2025. SimpleX Chat v6.3: new user experience and safety in public groups](./blog/20250308-simplex-chat-v6-3-new-user-experience-safety-in-public-groups.md)
|
||||
|
||||
[Jan 14, 2025. SimpleX network: large groups and privacy-preserving content moderation](./blog/20250114-simplex-network-large-groups-privacy-preserving-content-moderation.md)
|
||||
|
||||
[Dec 10, 2024. SimpleX network: preset servers operated by Flux, business chats and more with v6.2 of the apps](./20241210-simplex-network-v6-2-servers-by-flux-business-chats.md)
|
||||
|
||||
[Oct 14, 2024. SimpleX network: security review of protocols design by Trail of Bits, v6.1 released with better calls and user experience.](./blog/20241014-simplex-network-v6-1-security-review-better-calls-user-experience.md)
|
||||
|
@ -305,12 +309,13 @@ What is already implemented:
|
|||
15. Manual messaging queue rotations to move conversation to another SMP relay.
|
||||
16. Sending end-to-end encrypted files using [XFTP protocol](https://simplex.chat/blog/20230301-simplex-file-transfer-protocol.html).
|
||||
17. Local files encryption.
|
||||
18. [Reproducible server builds](./docs/SERVER.md#reproduce-builds).
|
||||
|
||||
We plan to add:
|
||||
|
||||
1. Automatic message queue rotation and redundancy. Currently the queues created between two users are used until the queue is manually changed by the user or contact is deleted. We are planning to add automatic queue rotation to make these identifiers temporary and rotate based on some schedule TBC (e.g., every X messages, or every X hours/days).
|
||||
2. Message "mixing" - adding latency to message delivery, to protect against traffic correlation by message time.
|
||||
3. Reproducible builds – this is the limitation of the development stack, but we will be investing into solving this problem. Users can still build all applications and services from the source code.
|
||||
3. Reproducible clients builds – this is a complex problem, but we are aiming to have it in 2025 at least partially.
|
||||
4. Recipients' XFTP relays to reduce traffic and conceal IP addresses from the relays chosen, and potentially controlled, by another party.
|
||||
|
||||
## For developers
|
||||
|
|
|
@ -288,8 +288,10 @@ struct ContentView: View {
|
|||
}
|
||||
prefShowLANotice = true
|
||||
connectViaUrl()
|
||||
showReRegisterTokenAlert()
|
||||
}
|
||||
.onChange(of: chatModel.appOpenUrl) { _ in connectViaUrl() }
|
||||
.onChange(of: chatModel.reRegisterTknStatus) { _ in showReRegisterTokenAlert() }
|
||||
.sheet(item: $noticesSheetItem) { item in
|
||||
switch item {
|
||||
case let .whatsNew(updatedConditions):
|
||||
|
@ -315,6 +317,12 @@ struct ContentView: View {
|
|||
.onContinueUserActivity("INStartCallIntent", perform: processUserActivity)
|
||||
.onContinueUserActivity("INStartAudioCallIntent", perform: processUserActivity)
|
||||
.onContinueUserActivity("INStartVideoCallIntent", perform: processUserActivity)
|
||||
.onContinueUserActivity(NSUserActivityTypeBrowsingWeb) { userActivity in
|
||||
if let url = userActivity.webpageURL {
|
||||
logger.debug("onContinueUserActivity.NSUserActivityTypeBrowsingWeb: \(url)")
|
||||
chatModel.appOpenUrl = url
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func setConditionsNotified_() async {
|
||||
|
@ -468,6 +476,21 @@ struct ContentView: View {
|
|||
}
|
||||
}
|
||||
|
||||
func showReRegisterTokenAlert() {
|
||||
dismissAllSheets() {
|
||||
let m = ChatModel.shared
|
||||
if let errorTknStatus = m.reRegisterTknStatus, let token = chatModel.deviceToken {
|
||||
chatModel.reRegisterTknStatus = nil
|
||||
AlertManager.shared.showAlert(Alert(
|
||||
title: Text("Notifications error"),
|
||||
message: Text(tokenStatusInfo(errorTknStatus, register: true)),
|
||||
primaryButton: .default(Text("Register")) { reRegisterToken(token: token) },
|
||||
secondaryButton: .cancel()
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func showPlanAndConnectAlert(_ alert: PlanAndConnectAlert) {
|
||||
AlertManager.shared.showAlert(planAndConnectAlert(alert, dismiss: false))
|
||||
}
|
||||
|
|
|
@ -53,11 +53,18 @@ class ItemsModel: ObservableObject {
|
|||
var itemAdded = false {
|
||||
willSet { publisher.send() }
|
||||
}
|
||||
|
||||
|
||||
// set listener here that will be notified on every add/delete of a chat item
|
||||
let chatState = ActiveChatState()
|
||||
var chatItemsChangesListener: RecalculatePositions = RecalculatePositions()
|
||||
|
||||
// Publishes directly to `objectWillChange` publisher,
|
||||
// this will cause reversedChatItems to be rendered without throttling
|
||||
@Published var isLoading = false
|
||||
@Published var showLoadingProgress = false
|
||||
@Published var showLoadingProgress: ChatId? = nil
|
||||
|
||||
private var navigationTimeoutTask: Task<Void, Never>? = nil
|
||||
private var loadChatTask: Task<Void, Never>? = nil
|
||||
|
||||
init() {
|
||||
publisher
|
||||
|
@ -67,33 +74,41 @@ class ItemsModel: ObservableObject {
|
|||
}
|
||||
|
||||
func loadOpenChat(_ chatId: ChatId, willNavigate: @escaping () -> Void = {}) {
|
||||
let navigationTimeout = Task {
|
||||
navigationTimeoutTask?.cancel()
|
||||
loadChatTask?.cancel()
|
||||
navigationTimeoutTask = Task {
|
||||
do {
|
||||
try await Task.sleep(nanoseconds: 250_000000)
|
||||
await MainActor.run {
|
||||
willNavigate()
|
||||
ChatModel.shared.chatId = chatId
|
||||
willNavigate()
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
let progressTimeout = Task {
|
||||
do {
|
||||
try await Task.sleep(nanoseconds: 1500_000000)
|
||||
await MainActor.run { showLoadingProgress = true }
|
||||
} catch {}
|
||||
}
|
||||
Task {
|
||||
if let chat = ChatModel.shared.getChat(chatId) {
|
||||
await MainActor.run { self.isLoading = true }
|
||||
// try? await Task.sleep(nanoseconds: 5000_000000)
|
||||
await loadChat(chat: chat)
|
||||
navigationTimeout.cancel()
|
||||
progressTimeout.cancel()
|
||||
loadChatTask = Task {
|
||||
await MainActor.run { self.isLoading = true }
|
||||
// try? await Task.sleep(nanoseconds: 1000_000000)
|
||||
await loadChat(chatId: chatId)
|
||||
if !Task.isCancelled {
|
||||
await MainActor.run {
|
||||
self.isLoading = false
|
||||
self.showLoadingProgress = false
|
||||
willNavigate()
|
||||
ChatModel.shared.chatId = chatId
|
||||
self.showLoadingProgress = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func loadOpenChatNoWait(_ chatId: ChatId, _ openAroundItemId: ChatItem.ID? = nil) {
|
||||
navigationTimeoutTask?.cancel()
|
||||
loadChatTask?.cancel()
|
||||
loadChatTask = Task {
|
||||
// try? await Task.sleep(nanoseconds: 1000_000000)
|
||||
await loadChat(chatId: chatId, openAroundItemId: openAroundItemId, clearItems: openAroundItemId == nil)
|
||||
if !Task.isCancelled {
|
||||
await MainActor.run {
|
||||
if openAroundItemId == nil {
|
||||
ChatModel.shared.chatId = chatId
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -124,11 +139,9 @@ class ChatTagsModel: ObservableObject {
|
|||
}
|
||||
}
|
||||
}
|
||||
if case let .presetTag(tag) = tm.activeFilter, (newPresetTags[tag] ?? 0) == 0 {
|
||||
activeFilter = nil
|
||||
}
|
||||
presetTags = newPresetTags
|
||||
unreadTags = newUnreadTags
|
||||
clearActiveChatFilterIfNeeded()
|
||||
}
|
||||
|
||||
func updateChatFavorite(favorite: Bool, wasFavorite: Bool) {
|
||||
|
@ -137,9 +150,7 @@ class ChatTagsModel: ObservableObject {
|
|||
presetTags[.favorites] = (count ?? 0) + 1
|
||||
} else if !favorite && wasFavorite, let count {
|
||||
presetTags[.favorites] = max(0, count - 1)
|
||||
if case .presetTag(.favorites) = activeFilter, (presetTags[.favorites] ?? 0) == 0 {
|
||||
activeFilter = nil
|
||||
}
|
||||
clearActiveChatFilterIfNeeded()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -163,6 +174,7 @@ class ChatTagsModel: ObservableObject {
|
|||
}
|
||||
}
|
||||
}
|
||||
clearActiveChatFilterIfNeeded()
|
||||
}
|
||||
|
||||
func markChatTagRead(_ chat: Chat) -> Void {
|
||||
|
@ -193,7 +205,17 @@ class ChatTagsModel: ObservableObject {
|
|||
|
||||
func changeGroupReportsTag(_ by: Int = 0) {
|
||||
if by == 0 { return }
|
||||
presetTags[.groupReports] = (presetTags[.groupReports] ?? 0) + by
|
||||
presetTags[.groupReports] = max(0, (presetTags[.groupReports] ?? 0) + by)
|
||||
clearActiveChatFilterIfNeeded()
|
||||
}
|
||||
|
||||
func clearActiveChatFilterIfNeeded() {
|
||||
let clear = switch activeFilter {
|
||||
case let .presetTag(tag): (presetTags[tag] ?? 0) == 0
|
||||
case let .userTag(tag): !userTags.contains(tag)
|
||||
case .unread, nil: false
|
||||
}
|
||||
if clear { activeFilter = nil }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -253,6 +275,7 @@ final class ChatModel: ObservableObject {
|
|||
@Published var deletedChats: Set<String> = []
|
||||
// current chat
|
||||
@Published var chatId: String?
|
||||
@Published var openAroundItemId: ChatItem.ID? = nil
|
||||
var chatItemStatuses: Dictionary<Int64, CIStatus> = [:]
|
||||
@Published var chatToTop: String?
|
||||
@Published var groupMembers: [GMember] = []
|
||||
|
@ -267,6 +290,7 @@ final class ChatModel: ObservableObject {
|
|||
@Published var deviceToken: DeviceToken?
|
||||
@Published var savedToken: DeviceToken?
|
||||
@Published var tokenRegistered = false
|
||||
@Published var reRegisterTknStatus: NtfTknStatus? = nil
|
||||
@Published var tokenStatus: NtfTknStatus?
|
||||
@Published var notificationMode = NotificationsMode.off
|
||||
@Published var notificationServer: String?
|
||||
|
@ -545,6 +569,7 @@ final class ChatModel: ObservableObject {
|
|||
ci.meta.itemStatus = status
|
||||
}
|
||||
im.reversedChatItems.insert(ci, at: hasLiveDummy ? 1 : 0)
|
||||
im.chatItemsChangesListener.added((ci.id, ci.isRcvNew), hasLiveDummy ? 1 : 0)
|
||||
im.itemAdded = true
|
||||
ChatItemDummyModel.shared.sendUpdate()
|
||||
return true
|
||||
|
@ -590,14 +615,54 @@ final class ChatModel: ObservableObject {
|
|||
// remove from current chat
|
||||
if chatId == cInfo.id {
|
||||
if let i = getChatItemIndex(cItem) {
|
||||
_ = withAnimation {
|
||||
im.reversedChatItems.remove(at: i)
|
||||
withAnimation {
|
||||
let item = im.reversedChatItems.remove(at: i)
|
||||
im.chatItemsChangesListener.removed([(item.id, i, item.isRcvNew)], im.reversedChatItems.reversed())
|
||||
}
|
||||
}
|
||||
}
|
||||
VoiceItemState.stopVoiceInChatView(cInfo, cItem)
|
||||
}
|
||||
|
||||
func removeMemberItems(_ removedMember: GroupMember, byMember: GroupMember, _ groupInfo: GroupInfo) {
|
||||
// this should not happen, only another member can "remove" user, user can only "leave" (another event).
|
||||
if byMember.groupMemberId == groupInfo.membership.groupMemberId {
|
||||
logger.debug("exiting removeMemberItems")
|
||||
return
|
||||
}
|
||||
if chatId == groupInfo.id {
|
||||
for i in 0..<im.reversedChatItems.count {
|
||||
if let updatedItem = removedUpdatedItem(im.reversedChatItems[i]) {
|
||||
_updateChatItem(at: i, with: updatedItem)
|
||||
}
|
||||
}
|
||||
} else if let chat = getChat(groupInfo.id),
|
||||
chat.chatItems.count > 0,
|
||||
let updatedItem = removedUpdatedItem(chat.chatItems[0]) {
|
||||
chat.chatItems = [updatedItem]
|
||||
}
|
||||
|
||||
func removedUpdatedItem(_ item: ChatItem) -> ChatItem? {
|
||||
let newContent: CIContent
|
||||
if case .groupSnd = item.chatDir, removedMember.groupMemberId == groupInfo.membership.groupMemberId {
|
||||
newContent = .sndModerated
|
||||
} else if case let .groupRcv(groupMember) = item.chatDir, groupMember.groupMemberId == removedMember.groupMemberId {
|
||||
newContent = .rcvModerated
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
var updatedItem = item
|
||||
updatedItem.meta.itemDeleted = .moderated(deletedTs: Date.now, byGroupMember: byMember)
|
||||
if groupInfo.fullGroupPreferences.fullDelete.on {
|
||||
updatedItem.content = newContent
|
||||
}
|
||||
if item.isActiveReport {
|
||||
decreaseGroupReportsCounter(groupInfo.id)
|
||||
}
|
||||
return updatedItem
|
||||
}
|
||||
}
|
||||
|
||||
func nextChatItemData<T>(_ chatItemId: Int64, previous: Bool, map: @escaping (ChatItem) -> T?) -> T? {
|
||||
guard var i = im.reversedChatItems.firstIndex(where: { $0.id == chatItemId }) else { return nil }
|
||||
if previous {
|
||||
|
@ -640,6 +705,7 @@ final class ChatModel: ObservableObject {
|
|||
let cItem = ChatItem.liveDummy(chatInfo.chatType)
|
||||
withAnimation {
|
||||
im.reversedChatItems.insert(cItem, at: 0)
|
||||
im.chatItemsChangesListener.added((cItem.id, cItem.isRcvNew), 0)
|
||||
im.itemAdded = true
|
||||
}
|
||||
return cItem
|
||||
|
@ -659,71 +725,23 @@ final class ChatModel: ObservableObject {
|
|||
im.reversedChatItems.first?.isLiveDummy == true
|
||||
}
|
||||
|
||||
func markChatItemsRead(_ cInfo: ChatInfo) {
|
||||
func markAllChatItemsRead(_ cInfo: ChatInfo) {
|
||||
// update preview
|
||||
_updateChat(cInfo.id) { chat in
|
||||
self.decreaseUnreadCounter(user: self.currentUser!, chat: chat)
|
||||
self.updateFloatingButtons(unreadCount: 0)
|
||||
ChatTagsModel.shared.markChatTagRead(chat)
|
||||
chat.chatStats = ChatStats()
|
||||
}
|
||||
// update current chat
|
||||
if chatId == cInfo.id {
|
||||
markCurrentChatRead()
|
||||
}
|
||||
}
|
||||
|
||||
private func markCurrentChatRead(fromIndex i: Int = 0) {
|
||||
var j = i
|
||||
while j < im.reversedChatItems.count {
|
||||
markChatItemRead_(j)
|
||||
j += 1
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
markCurrentChatRead(fromIndex: i)
|
||||
_updateChat(cInfo.id) { chat in
|
||||
var unreadBelow = 0
|
||||
var unreadMentionsBelow = 0
|
||||
var j = i - 1
|
||||
while j >= 0 {
|
||||
let meta = self.im.reversedChatItems[j].meta
|
||||
if case .rcvNew = meta.itemStatus {
|
||||
unreadBelow += 1
|
||||
if meta.userMention {
|
||||
unreadMentionsBelow += 1
|
||||
}
|
||||
}
|
||||
j -= 1
|
||||
}
|
||||
// update preview
|
||||
let markedCount = chat.chatStats.unreadCount - unreadBelow
|
||||
let markedMentionsCount = chat.chatStats.unreadMentions - unreadMentionsBelow
|
||||
if markedCount > 0 || markedMentionsCount > 0 {
|
||||
let wasUnread = chat.unreadTag
|
||||
chat.chatStats.unreadCount -= markedCount
|
||||
chat.chatStats.unreadMentions -= markedMentionsCount
|
||||
ChatTagsModel.shared.updateChatTagRead(chat, wasUnread: wasUnread)
|
||||
let by = chat.chatInfo.chatSettings?.enableNtfs == .mentions ? markedMentionsCount : markedCount
|
||||
self.decreaseUnreadCounter(user: self.currentUser!, by: by)
|
||||
self.updateFloatingButtons(unreadCount: chat.chatStats.unreadCount)
|
||||
}
|
||||
}
|
||||
var i = 0
|
||||
while i < im.reversedChatItems.count {
|
||||
markChatItemRead_(i)
|
||||
i += 1
|
||||
}
|
||||
} else {
|
||||
markChatItemsRead(cInfo)
|
||||
im.chatItemsChangesListener.read(nil, im.reversedChatItems.reversed())
|
||||
}
|
||||
}
|
||||
|
||||
func markChatUnread(_ cInfo: ChatInfo, unreadChat: Bool = true) {
|
||||
_updateChat(cInfo.id) { chat in
|
||||
let wasUnread = chat.unreadTag
|
||||
|
@ -745,16 +763,25 @@ final class ChatModel: ObservableObject {
|
|||
if chatId == cInfo.id {
|
||||
chatItemStatuses = [:]
|
||||
im.reversedChatItems = []
|
||||
im.chatItemsChangesListener.cleared()
|
||||
}
|
||||
}
|
||||
|
||||
func markChatItemsRead(_ cInfo: ChatInfo, _ itemIds: [ChatItem.ID], _ mentionsRead: Int) {
|
||||
if self.chatId == cInfo.id {
|
||||
for itemId in itemIds {
|
||||
if let i = im.reversedChatItems.firstIndex(where: { $0.id == itemId }) {
|
||||
var unreadItemIds: Set<ChatItem.ID> = []
|
||||
var i = 0
|
||||
var ids = Set(itemIds)
|
||||
while i < im.reversedChatItems.count && !ids.isEmpty {
|
||||
let item = im.reversedChatItems[i]
|
||||
if ids.contains(item.id) && item.isRcvNew {
|
||||
markChatItemRead_(i)
|
||||
unreadItemIds.insert(item.id)
|
||||
ids.remove(item.id)
|
||||
}
|
||||
i += 1
|
||||
}
|
||||
im.chatItemsChangesListener.read(unreadItemIds, im.reversedChatItems.reversed())
|
||||
}
|
||||
self.unreadCollector.changeUnreadCounter(cInfo.id, by: -itemIds.count, unreadMentions: -mentionsRead)
|
||||
}
|
||||
|
@ -782,9 +809,6 @@ final class ChatModel: ObservableObject {
|
|||
}
|
||||
|
||||
func changeUnreadCounter(_ chatId: ChatId, by count: Int, unreadMentions: Int) {
|
||||
if chatId == ChatModel.shared.chatId {
|
||||
ChatView.FloatingButtonModel.shared.totalUnread += count
|
||||
}
|
||||
let (unread, mentions) = self.unreadCounts[chatId] ?? (0, 0)
|
||||
self.unreadCounts[chatId] = (unread + count, mentions + unreadMentions)
|
||||
subject.send()
|
||||
|
@ -917,7 +941,7 @@ final class ChatModel: ObservableObject {
|
|||
}
|
||||
|
||||
func decreaseGroupReportsCounter(_ chatId: ChatId, by: Int = 1) {
|
||||
changeGroupReportsCounter(chatId, -1)
|
||||
changeGroupReportsCounter(chatId, -by)
|
||||
}
|
||||
|
||||
private func changeGroupReportsCounter(_ chatId: ChatId, _ by: Int = 0) {
|
||||
|
@ -978,12 +1002,17 @@ final class ChatModel: ObservableObject {
|
|||
|
||||
// returns the previous member in the same merge group and the count of members in this group
|
||||
func getPrevHiddenMember(_ member: GroupMember, _ range: ClosedRange<Int>) -> (GroupMember?, Int) {
|
||||
let items = im.reversedChatItems
|
||||
var prevMember: GroupMember? = nil
|
||||
var memberIds: Set<Int64> = []
|
||||
for i in range {
|
||||
if case let .groupRcv(m) = im.reversedChatItems[i].chatDir {
|
||||
if prevMember == nil && m.groupMemberId != member.groupMemberId { prevMember = m }
|
||||
memberIds.insert(m.groupMemberId)
|
||||
if i < items.count {
|
||||
if case let .groupRcv(m) = items[i].chatDir {
|
||||
if prevMember == nil && m.groupMemberId != member.groupMemberId { prevMember = m }
|
||||
memberIds.insert(m.groupMemberId)
|
||||
}
|
||||
} else {
|
||||
logger.error("getPrevHiddenMember: index >= count of reversed items: \(i) vs \(items.count), range: \(String(describing: range))")
|
||||
}
|
||||
}
|
||||
return (prevMember, memberIds.count)
|
||||
|
|
|
@ -328,38 +328,27 @@ func apiGetChatTagsAsync() async throws -> [ChatTag] {
|
|||
|
||||
let loadItemsPerPage = 50
|
||||
|
||||
func apiGetChat(type: ChatType, id: Int64, search: String = "") async throws -> Chat {
|
||||
let r = await chatSendCmd(.apiGetChat(type: type, id: id, pagination: .last(count: loadItemsPerPage), search: search))
|
||||
if case let .apiChat(_, chat) = r { return Chat.init(chat) }
|
||||
func apiGetChat(chatId: ChatId, pagination: ChatPagination, search: String = "") async throws -> (Chat, NavigationInfo) {
|
||||
let r = await chatSendCmd(.apiGetChat(chatId: chatId, pagination: pagination, search: search))
|
||||
if case let .apiChat(_, chat, navInfo) = r { return (Chat.init(chat), navInfo ?? NavigationInfo()) }
|
||||
throw r
|
||||
}
|
||||
|
||||
func apiGetChatItems(type: ChatType, id: Int64, pagination: ChatPagination, search: String = "") async throws -> [ChatItem] {
|
||||
let r = await chatSendCmd(.apiGetChat(type: type, id: id, pagination: pagination, search: search))
|
||||
if case let .apiChat(_, chat) = r { return chat.chatItems }
|
||||
throw r
|
||||
func loadChat(chat: Chat, search: String = "", clearItems: Bool = true) async {
|
||||
await loadChat(chatId: chat.chatInfo.id, search: search, clearItems: clearItems)
|
||||
}
|
||||
|
||||
func loadChat(chat: Chat, search: String = "", clearItems: Bool = true, replaceChat: Bool = false) async {
|
||||
do {
|
||||
let cInfo = chat.chatInfo
|
||||
let m = ChatModel.shared
|
||||
let im = ItemsModel.shared
|
||||
func loadChat(chatId: ChatId, search: String = "", openAroundItemId: ChatItem.ID? = nil, clearItems: Bool = true) async {
|
||||
let m = ChatModel.shared
|
||||
let im = ItemsModel.shared
|
||||
await MainActor.run {
|
||||
m.chatItemStatuses = [:]
|
||||
if clearItems {
|
||||
await MainActor.run { im.reversedChatItems = [] }
|
||||
im.reversedChatItems = []
|
||||
ItemsModel.shared.chatItemsChangesListener.cleared()
|
||||
}
|
||||
let chat = try await apiGetChat(type: cInfo.chatType, id: cInfo.apiId, search: search)
|
||||
await MainActor.run {
|
||||
im.reversedChatItems = chat.chatItems.reversed()
|
||||
m.updateChatInfo(chat.chatInfo)
|
||||
if (replaceChat) {
|
||||
m.replaceChat(chat.chatInfo.id, chat)
|
||||
}
|
||||
}
|
||||
} catch let error {
|
||||
logger.error("loadChat error: \(responseError(error))")
|
||||
}
|
||||
await apiLoadMessages(chatId, openAroundItemId != nil ? .around(chatItemId: openAroundItemId!, count: loadItemsPerPage) : (search == "" ? .initial(count: loadItemsPerPage) : .last(count: loadItemsPerPage)), im.chatState, search, openAroundItemId, { 0...0 })
|
||||
}
|
||||
|
||||
func apiGetChatItemInfo(type: ChatType, id: Int64, itemId: Int64) async throws -> ChatItemInfo {
|
||||
|
@ -516,6 +505,18 @@ func apiDeleteMemberChatItems(groupId: Int64, itemIds: [Int64]) async throws ->
|
|||
throw r
|
||||
}
|
||||
|
||||
func apiArchiveReceivedReports(groupId: Int64) async throws -> ChatResponse {
|
||||
let r = await chatSendCmd(.apiArchiveReceivedReports(groupId: groupId), bgDelay: msgDelay)
|
||||
if case .groupChatItemsDeleted = r { return r }
|
||||
throw r
|
||||
}
|
||||
|
||||
func apiDeleteReceivedReports(groupId: Int64, itemIds: [Int64], mode: CIDeleteMode) async throws -> [ChatItemDeletion] {
|
||||
let r = await chatSendCmd(.apiDeleteReceivedReports(groupId: groupId, itemIds: itemIds, mode: mode), bgDelay: msgDelay)
|
||||
if case let .chatItemsDeleted(_, chatItemDeletions, _) = r { return chatItemDeletions }
|
||||
throw r
|
||||
}
|
||||
|
||||
func apiGetNtfToken() -> (DeviceToken?, NtfTknStatus?, NotificationsMode, String?) {
|
||||
let r = chatSendCmdSync(.apiGetNtfToken)
|
||||
switch r {
|
||||
|
@ -542,7 +543,12 @@ func registerToken(token: DeviceToken) {
|
|||
Task {
|
||||
do {
|
||||
let status = try await apiRegisterToken(token: token, notificationMode: mode)
|
||||
await MainActor.run { m.tokenStatus = status }
|
||||
await MainActor.run {
|
||||
m.tokenStatus = status
|
||||
if !status.workingToken {
|
||||
m.reRegisterTknStatus = status
|
||||
}
|
||||
}
|
||||
} catch let error {
|
||||
logger.error("registerToken apiRegisterToken error: \(responseError(error))")
|
||||
}
|
||||
|
@ -550,10 +556,49 @@ func registerToken(token: DeviceToken) {
|
|||
}
|
||||
}
|
||||
|
||||
func tokenStatusInfo(_ status: NtfTknStatus, register: Bool) -> String {
|
||||
String.localizedStringWithFormat(NSLocalizedString("Token status: %@.", comment: "token status"), status.text)
|
||||
+ "\n" + status.info(register: register)
|
||||
}
|
||||
|
||||
func reRegisterToken(token: DeviceToken) {
|
||||
let m = ChatModel.shared
|
||||
let mode = m.notificationMode
|
||||
logger.debug("reRegisterToken \(mode.rawValue)")
|
||||
Task {
|
||||
do {
|
||||
let status = try await apiRegisterToken(token: token, notificationMode: mode)
|
||||
await MainActor.run {
|
||||
m.tokenStatus = status
|
||||
showAlert(
|
||||
status.workingToken
|
||||
? NSLocalizedString("Notifications status", comment: "alert title")
|
||||
: NSLocalizedString("Notifications error", comment: "alert title"),
|
||||
message: tokenStatusInfo(status, register: false)
|
||||
)
|
||||
}
|
||||
} catch let error {
|
||||
logger.error("reRegisterToken apiRegisterToken error: \(responseError(error))")
|
||||
await MainActor.run {
|
||||
showAlert(
|
||||
NSLocalizedString("Error registering for notifications", comment: "alert title"),
|
||||
message: responseError(error)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func apiVerifyToken(token: DeviceToken, nonce: String, code: String) async throws {
|
||||
try await sendCommandOkResp(.apiVerifyToken(token: token, nonce: nonce, code: code))
|
||||
}
|
||||
|
||||
func apiCheckToken(token: DeviceToken) async throws -> NtfTknStatus {
|
||||
let r = await chatSendCmd(.apiCheckToken(token: token))
|
||||
if case let .ntfTokenStatus(status) = r { return status }
|
||||
throw r
|
||||
}
|
||||
|
||||
func apiDeleteToken(token: DeviceToken) async throws {
|
||||
try await sendCommandOkResp(.apiDeleteToken(token: token))
|
||||
}
|
||||
|
@ -813,7 +858,7 @@ func apiSetConnectionIncognito(connId: Int64, incognito: Bool) async throws -> P
|
|||
|
||||
func apiChangeConnectionUser(connId: Int64, userId: Int64) async throws -> PendingContactConnection? {
|
||||
let r = await chatSendCmd(.apiChangeConnectionUser(connId: connId, userId: userId))
|
||||
|
||||
|
||||
if case let .connectionUserChanged(_, _, toConnection, _) = r {return toConnection}
|
||||
throw r
|
||||
}
|
||||
|
@ -1468,7 +1513,7 @@ func markChatRead(_ chat: Chat) async {
|
|||
let cInfo = chat.chatInfo
|
||||
try await apiChatRead(type: cInfo.chatType, id: cInfo.apiId)
|
||||
await MainActor.run {
|
||||
withAnimation { ChatModel.shared.markChatItemsRead(cInfo) }
|
||||
withAnimation { ChatModel.shared.markAllChatItemsRead(cInfo) }
|
||||
}
|
||||
}
|
||||
if chat.chatStats.unreadChat {
|
||||
|
@ -1543,21 +1588,21 @@ func apiJoinGroup(_ groupId: Int64) async throws -> JoinGroupResult {
|
|||
}
|
||||
}
|
||||
|
||||
func apiRemoveMember(_ groupId: Int64, _ memberId: Int64) async throws -> GroupMember {
|
||||
let r = await chatSendCmd(.apiRemoveMember(groupId: groupId, memberId: memberId), bgTask: false)
|
||||
if case let .userDeletedMember(_, _, member) = r { return member }
|
||||
func apiRemoveMembers(_ groupId: Int64, _ memberIds: [Int64], _ withMessages: Bool = false) async throws -> [GroupMember] {
|
||||
let r = await chatSendCmd(.apiRemoveMembers(groupId: groupId, memberIds: memberIds, withMessages: withMessages), bgTask: false)
|
||||
if case let .userDeletedMembers(_, _, members, withMessages) = r { return members }
|
||||
throw r
|
||||
}
|
||||
|
||||
func apiMemberRole(_ groupId: Int64, _ memberId: Int64, _ memberRole: GroupMemberRole) async throws -> GroupMember {
|
||||
let r = await chatSendCmd(.apiMemberRole(groupId: groupId, memberId: memberId, memberRole: memberRole), bgTask: false)
|
||||
if case let .memberRoleUser(_, _, member, _, _) = r { return member }
|
||||
func apiMembersRole(_ groupId: Int64, _ memberIds: [Int64], _ memberRole: GroupMemberRole) async throws -> [GroupMember] {
|
||||
let r = await chatSendCmd(.apiMembersRole(groupId: groupId, memberIds: memberIds, memberRole: memberRole), bgTask: false)
|
||||
if case let .membersRoleUser(_, _, members, _) = r { return members }
|
||||
throw r
|
||||
}
|
||||
|
||||
func apiBlockMemberForAll(_ groupId: Int64, _ memberId: Int64, _ blocked: Bool) async throws -> GroupMember {
|
||||
let r = await chatSendCmd(.apiBlockMemberForAll(groupId: groupId, memberId: memberId, blocked: blocked), bgTask: false)
|
||||
if case let .memberBlockedForAllUser(_, _, member, _) = r { return member }
|
||||
func apiBlockMembersForAll(_ groupId: Int64, _ memberIds: [Int64], _ blocked: Bool) async throws -> [GroupMember] {
|
||||
let r = await chatSendCmd(.apiBlockMembersForAll(groupId: groupId, memberIds: memberIds, blocked: blocked), bgTask: false)
|
||||
if case let .membersBlockedForAllUser(_, _, members, _) = r { return members }
|
||||
throw r
|
||||
}
|
||||
|
||||
|
@ -2090,42 +2135,13 @@ func processReceivedMsg(_ res: ChatResponse) async {
|
|||
} else {
|
||||
m.removeChatItem(item.deletedChatItem.chatInfo, item.deletedChatItem.chatItem)
|
||||
}
|
||||
if item.deletedChatItem.chatItem.isActiveReport {
|
||||
m.decreaseGroupReportsCounter(item.deletedChatItem.chatInfo.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
case let .groupChatItemsDeleted(user, groupInfo, chatItemIDs, _, member_):
|
||||
if !active(user) {
|
||||
do {
|
||||
let users = try listUsers()
|
||||
await MainActor.run {
|
||||
m.users = users
|
||||
}
|
||||
} catch {
|
||||
logger.error("Error loading users: \(error)")
|
||||
}
|
||||
return
|
||||
}
|
||||
let im = ItemsModel.shared
|
||||
let cInfo = ChatInfo.group(groupInfo: groupInfo)
|
||||
await MainActor.run {
|
||||
m.decreaseGroupReportsCounter(cInfo.id, by: chatItemIDs.count)
|
||||
}
|
||||
var notFound = chatItemIDs.count
|
||||
for ci in im.reversedChatItems {
|
||||
if chatItemIDs.contains(ci.id) {
|
||||
let deleted = if case let .groupRcv(groupMember) = ci.chatDir, let member_, groupMember.groupMemberId != member_.groupMemberId {
|
||||
CIDeleted.moderated(deletedTs: Date.now, byGroupMember: member_)
|
||||
} else {
|
||||
CIDeleted.deleted(deletedTs: Date.now)
|
||||
}
|
||||
await MainActor.run {
|
||||
var newItem = ci
|
||||
newItem.meta.itemDeleted = deleted
|
||||
_ = m.upsertChatItem(cInfo, newItem)
|
||||
}
|
||||
notFound -= 1
|
||||
if notFound == 0 { break }
|
||||
}
|
||||
}
|
||||
await groupChatItemsDeleted(user, groupInfo, chatItemIDs, member_)
|
||||
case let .receivedGroupInvitation(user, groupInfo, _, _):
|
||||
if active(user) {
|
||||
await MainActor.run {
|
||||
|
@ -2145,7 +2161,7 @@ func processReceivedMsg(_ res: ChatResponse) async {
|
|||
}
|
||||
case let .groupLinkConnecting(user, groupInfo, hostMember):
|
||||
if !active(user) { return }
|
||||
|
||||
|
||||
await MainActor.run {
|
||||
m.updateGroup(groupInfo)
|
||||
if let hostConn = hostMember.activeConn {
|
||||
|
@ -2171,16 +2187,22 @@ func processReceivedMsg(_ res: ChatResponse) async {
|
|||
_ = m.upsertGroupMember(groupInfo, member)
|
||||
}
|
||||
}
|
||||
case let .deletedMemberUser(user, groupInfo, _): // TODO update user member
|
||||
case let .deletedMemberUser(user, groupInfo, member, withMessages): // TODO update user member
|
||||
if active(user) {
|
||||
await MainActor.run {
|
||||
m.updateGroup(groupInfo)
|
||||
if withMessages {
|
||||
m.removeMemberItems(groupInfo.membership, byMember: member, groupInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
case let .deletedMember(user, groupInfo, _, deletedMember):
|
||||
case let .deletedMember(user, groupInfo, byMember, deletedMember, withMessages):
|
||||
if active(user) {
|
||||
await MainActor.run {
|
||||
_ = m.upsertGroupMember(groupInfo, deletedMember)
|
||||
if withMessages {
|
||||
m.removeMemberItems(deletedMember, byMember: byMember, groupInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
case let .leftMember(user, groupInfo, member):
|
||||
|
@ -2468,6 +2490,43 @@ func chatItemSimpleUpdate(_ user: any UserLike, _ aChatItem: AChatItem) async {
|
|||
}
|
||||
}
|
||||
|
||||
func groupChatItemsDeleted(_ user: UserRef, _ groupInfo: GroupInfo, _ chatItemIDs: Set<Int64>, _ member_: GroupMember?) async {
|
||||
let m = ChatModel.shared
|
||||
if !active(user) {
|
||||
do {
|
||||
let users = try listUsers()
|
||||
await MainActor.run {
|
||||
m.users = users
|
||||
}
|
||||
} catch {
|
||||
logger.error("Error loading users: \(error)")
|
||||
}
|
||||
return
|
||||
}
|
||||
let im = ItemsModel.shared
|
||||
let cInfo = ChatInfo.group(groupInfo: groupInfo)
|
||||
await MainActor.run {
|
||||
m.decreaseGroupReportsCounter(cInfo.id, by: chatItemIDs.count)
|
||||
}
|
||||
var notFound = chatItemIDs.count
|
||||
for ci in im.reversedChatItems {
|
||||
if chatItemIDs.contains(ci.id) {
|
||||
let deleted = if case let .groupRcv(groupMember) = ci.chatDir, let member_, groupMember.groupMemberId != member_.groupMemberId {
|
||||
CIDeleted.moderated(deletedTs: Date.now, byGroupMember: member_)
|
||||
} else {
|
||||
CIDeleted.deleted(deletedTs: Date.now)
|
||||
}
|
||||
await MainActor.run {
|
||||
var newItem = ci
|
||||
newItem.meta.itemDeleted = deleted
|
||||
_ = m.upsertChatItem(cInfo, newItem)
|
||||
}
|
||||
notFound -= 1
|
||||
if notFound == 0 { break }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func refreshCallInvitations() async throws {
|
||||
let m = ChatModel.shared
|
||||
let callInvitations = try await apiGetCallInvitations()
|
||||
|
|
|
@ -361,7 +361,7 @@ struct ActiveCallOverlay: View {
|
|||
HStack {
|
||||
Text(call.encryptionStatus)
|
||||
if let connInfo = call.connectionInfo {
|
||||
Text("(") + Text(connInfo.text) + Text(")")
|
||||
Text(verbatim: "(") + Text(connInfo.text) + Text(verbatim: ")")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -390,7 +390,7 @@ struct ActiveCallOverlay: View {
|
|||
HStack {
|
||||
Text(call.encryptionStatus)
|
||||
if let connInfo = call.connectionInfo {
|
||||
Text("(") + Text(connInfo.text) + Text(")")
|
||||
Text(verbatim: "(") + Text(connInfo.text) + Text(verbatim: ")")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -684,17 +684,23 @@ struct ChatTTLOption: View {
|
|||
) {
|
||||
progressIndicator = true
|
||||
Task {
|
||||
let m = ChatModel.shared
|
||||
do {
|
||||
try await setChatTTL(chatType: chat.chatInfo.chatType, id: chat.chatInfo.apiId, ttl)
|
||||
await loadChat(chat: chat, clearItems: true, replaceChat: true)
|
||||
await loadChat(chat: chat, clearItems: true)
|
||||
await MainActor.run {
|
||||
progressIndicator = false
|
||||
currentChatItemTTL = chatItemTTL
|
||||
if ItemsModel.shared.reversedChatItems.isEmpty && m.chatId == chat.id,
|
||||
let chat = m.getChat(chat.id) {
|
||||
chat.chatItems = []
|
||||
m.replaceChat(chat.id, chat)
|
||||
}
|
||||
}
|
||||
}
|
||||
catch let error {
|
||||
logger.error("setChatTTL error \(responseError(error))")
|
||||
await loadChat(chat: chat, clearItems: true, replaceChat: true)
|
||||
await loadChat(chat: chat, clearItems: true)
|
||||
await MainActor.run {
|
||||
chatItemTTL = currentChatItemTTL
|
||||
progressIndicator = false
|
||||
|
|
|
@ -293,16 +293,16 @@ struct CIFileView_Previews: PreviewProvider {
|
|||
file: nil
|
||||
)
|
||||
Group {
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: sentFile)
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample())
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(fileName: "some_long_file_name_here", fileStatus: .rcvInvitation))
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(fileStatus: .rcvAccepted))
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(fileStatus: .rcvTransfer(rcvProgress: 7, rcvTotal: 10)))
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(fileStatus: .rcvCancelled))
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(fileSize: 1_000_000_000, fileStatus: .rcvInvitation))
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(text: "Hello there", fileStatus: .rcvInvitation))
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", fileStatus: .rcvInvitation))
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: fileChatItemWtFile)
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: sentFile, scrollToItemId: { _ in })
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(), scrollToItemId: { _ in })
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(fileName: "some_long_file_name_here", fileStatus: .rcvInvitation), scrollToItemId: { _ in })
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(fileStatus: .rcvAccepted), scrollToItemId: { _ in })
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(fileStatus: .rcvTransfer(rcvProgress: 7, rcvTotal: 10)), scrollToItemId: { _ in })
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(fileStatus: .rcvCancelled), scrollToItemId: { _ in })
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(fileSize: 1_000_000_000, fileStatus: .rcvInvitation), scrollToItemId: { _ in })
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(text: "Hello there", fileStatus: .rcvInvitation), scrollToItemId: { _ in })
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", fileStatus: .rcvInvitation), scrollToItemId: { _ in })
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: fileChatItemWtFile, scrollToItemId: { _ in })
|
||||
}
|
||||
.environment(\.revealed, false)
|
||||
.previewLayout(.fixed(width: 360, height: 360))
|
||||
|
|
|
@ -12,6 +12,7 @@ import SimpleXChat
|
|||
struct CIImageView: View {
|
||||
@EnvironmentObject var m: ChatModel
|
||||
let chatItem: ChatItem
|
||||
var scrollToItemId: ((ChatItem.ID) -> Void)? = nil
|
||||
var preview: UIImage?
|
||||
let maxWidth: CGFloat
|
||||
var imgWidth: CGFloat?
|
||||
|
@ -25,7 +26,7 @@ struct CIImageView: View {
|
|||
if let uiImage = getLoadedImage(file) {
|
||||
Group { if smallView { smallViewImageView(uiImage) } else { imageView(uiImage) } }
|
||||
.fullScreenCover(isPresented: $showFullScreenImage) {
|
||||
FullScreenMediaView(chatItem: chatItem, image: uiImage, showView: $showFullScreenImage)
|
||||
FullScreenMediaView(chatItem: chatItem, scrollToItemId: scrollToItemId, image: uiImage, showView: $showFullScreenImage)
|
||||
}
|
||||
.if(!smallView) { view in
|
||||
view.modifier(PrivacyBlur(blurred: $blurred))
|
||||
|
|
|
@ -21,9 +21,8 @@ struct CIMemberCreatedContactView: View {
|
|||
if let contactId = groupMember.memberContactId {
|
||||
memberCreatedContactView(openText: "Open")
|
||||
.onTapGesture {
|
||||
dismissAllSheets(animated: true)
|
||||
DispatchQueue.main.async {
|
||||
ItemsModel.shared.loadOpenChat("@\(contactId)")
|
||||
ItemsModel.shared.loadOpenChat("@\(contactId)") {
|
||||
dismissAllSheets(animated: true)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -161,13 +161,13 @@ struct CIRcvDecryptionError: View {
|
|||
let why = Text(decryptErrorReason)
|
||||
switch msgDecryptError {
|
||||
case .ratchetHeader:
|
||||
message = Text("\(msgCount) messages failed to decrypt.") + Text("\n") + why
|
||||
message = Text("\(msgCount) messages failed to decrypt.") + textNewLine + why
|
||||
case .tooManySkipped:
|
||||
message = Text("\(msgCount) messages skipped.") + Text("\n") + why
|
||||
message = Text("\(msgCount) messages skipped.") + textNewLine + why
|
||||
case .ratchetEarlier:
|
||||
message = Text("\(msgCount) messages failed to decrypt.") + Text("\n") + why
|
||||
message = Text("\(msgCount) messages failed to decrypt.") + textNewLine + why
|
||||
case .other:
|
||||
message = Text("\(msgCount) messages failed to decrypt.") + Text("\n") + why
|
||||
message = Text("\(msgCount) messages failed to decrypt.") + textNewLine + why
|
||||
case .ratchetSync:
|
||||
message = Text("Encryption re-negotiation failed.")
|
||||
}
|
||||
|
|
|
@ -498,10 +498,10 @@ struct CIVoiceView_Previews: PreviewProvider {
|
|||
duration: 30,
|
||||
allowMenu: Binding.constant(true)
|
||||
)
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: sentVoiceMessage, allowMenu: .constant(true))
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getVoiceMsgContentSample(), allowMenu: .constant(true))
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getVoiceMsgContentSample(fileStatus: .rcvTransfer(rcvProgress: 7, rcvTotal: 10)), allowMenu: .constant(true))
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: voiceMessageWtFile, allowMenu: .constant(true))
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: sentVoiceMessage, scrollToItemId: { _ in }, allowMenu: .constant(true))
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getVoiceMsgContentSample(), scrollToItemId: { _ in }, allowMenu: .constant(true))
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getVoiceMsgContentSample(fileStatus: .rcvTransfer(rcvProgress: 7, rcvTotal: 10)), scrollToItemId: { _ in }, allowMenu: .constant(true))
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: voiceMessageWtFile, scrollToItemId: { _ in }, allowMenu: .constant(true))
|
||||
}
|
||||
.previewLayout(.fixed(width: 360, height: 360))
|
||||
}
|
||||
|
|
|
@ -92,11 +92,11 @@ struct FramedCIVoiceView_Previews: PreviewProvider {
|
|||
file: CIFile.getSample(fileStatus: .sndComplete)
|
||||
)
|
||||
Group {
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: sentVoiceMessage)
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getVoiceMsgContentSample(text: "Hello there"))
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getVoiceMsgContentSample(text: "Hello there", fileStatus: .rcvTransfer(rcvProgress: 7, rcvTotal: 10)))
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getVoiceMsgContentSample(text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."))
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: voiceMessageWithQuote)
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: sentVoiceMessage, scrollToItemId: { _ in })
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getVoiceMsgContentSample(text: "Hello there"), scrollToItemId: { _ in })
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getVoiceMsgContentSample(text: "Hello there", fileStatus: .rcvTransfer(rcvProgress: 7, rcvTotal: 10)), scrollToItemId: { _ in })
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getVoiceMsgContentSample(text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."), scrollToItemId: { _ in })
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: voiceMessageWithQuote, scrollToItemId: { _ in })
|
||||
}
|
||||
.environment(\.revealed, false)
|
||||
.previewLayout(.fixed(width: 360, height: 360))
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -13,8 +13,8 @@ import AVKit
|
|||
|
||||
struct FullScreenMediaView: View {
|
||||
@EnvironmentObject var m: ChatModel
|
||||
@EnvironmentObject var scrollModel: ReverseListScrollModel
|
||||
@State var chatItem: ChatItem
|
||||
var scrollToItemId: ((ChatItem.ID) -> Void)?
|
||||
@State var image: UIImage?
|
||||
@State var player: AVPlayer? = nil
|
||||
@State var url: URL? = nil
|
||||
|
@ -71,7 +71,7 @@ struct FullScreenMediaView: View {
|
|||
let w = abs(t.width)
|
||||
if t.height > 60 && t.height > w * 2 {
|
||||
showView = false
|
||||
scrollModel.scrollToItem(id: chatItem.id)
|
||||
scrollToItemId?(chatItem.id)
|
||||
} else if w > 60 && w > abs(t.height) * 2 && !scrolling {
|
||||
let previous = t.width > 0
|
||||
scrolling = true
|
||||
|
|
|
@ -31,8 +31,8 @@ struct IntegrityErrorItemView: View {
|
|||
case .msgBadHash:
|
||||
AlertManager.shared.showAlert(Alert(
|
||||
title: Text("Bad message hash"),
|
||||
message: Text("The hash of the previous message is different.") + Text("\n") +
|
||||
Text(decryptErrorReason) + Text("\n") +
|
||||
message: Text("The hash of the previous message is different.") + textNewLine +
|
||||
Text(decryptErrorReason) + textNewLine +
|
||||
Text("Please report it to the developers.")
|
||||
))
|
||||
case .msgBadId: msgBadIdAlert()
|
||||
|
@ -47,7 +47,7 @@ struct IntegrityErrorItemView: View {
|
|||
message: Text("""
|
||||
The ID of the next message is incorrect (less or equal to the previous).
|
||||
It can happen because of some bug or when the connection is compromised.
|
||||
""") + Text("\n") +
|
||||
""") + textNewLine +
|
||||
Text("Please report it to the developers.")
|
||||
))
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ private let typingIndicators: [Text] = [
|
|||
]
|
||||
|
||||
private func typing(_ w: Font.Weight = .light) -> Text {
|
||||
Text(".").fontWeight(w)
|
||||
Text(verbatim: ".").fontWeight(w)
|
||||
}
|
||||
|
||||
struct MsgContentView: View {
|
||||
|
@ -88,7 +88,7 @@ struct MsgContentView: View {
|
|||
}
|
||||
|
||||
private func reserveSpaceForMeta(_ mt: CIMeta) -> Text {
|
||||
(rightToLeft ? Text("\n") : Text(verbatim: " ")) + ciMetaText(mt, chatTTL: chat.chatInfo.timedMessagesTTL, encrypted: nil, colorMode: .transparent, showViaProxy: showSentViaProxy, showTimesamp: showTimestamp)
|
||||
(rightToLeft ? textNewLine : Text(verbatim: " ")) + ciMetaText(mt, chatTTL: chat.chatInfo.timedMessagesTTL, encrypted: nil, colorMode: .transparent, showViaProxy: showSentViaProxy, showTimesamp: showTimestamp)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,7 +117,7 @@ func messageText(_ text: String, _ formattedText: [FormattedText]?, _ sender: St
|
|||
|
||||
if let s = sender {
|
||||
let t = Text(s)
|
||||
return (preview ? t : t.fontWeight(.medium)) + Text(": ") + res
|
||||
return (preview ? t : t.fontWeight(.medium)) + Text(verbatim: ": ") + res
|
||||
} else {
|
||||
return res
|
||||
}
|
||||
|
@ -170,7 +170,7 @@ private func formatText(_ ft: FormattedText, _ preview: Bool, showSecret: Bool,
|
|||
}
|
||||
|
||||
private func mentionText(_ name: String) -> Text {
|
||||
Text(name.contains(" @") ? "@'\(name)'" : "@\(name)").fontWeight(.semibold)
|
||||
Text(verbatim: name.contains(" @") ? "@'\(name)'" : "@\(name)").fontWeight(.semibold)
|
||||
}
|
||||
|
||||
private func linkText(_ s: String, _ link: String, _ preview: Bool, prefix: String, color: Color = Color(uiColor: uiLinkColor), uiColor: UIColor = uiLinkColor) -> Text {
|
||||
|
|
|
@ -354,8 +354,9 @@ struct ChatItemInfoView: View {
|
|||
Button {
|
||||
Task {
|
||||
await MainActor.run {
|
||||
ItemsModel.shared.loadOpenChat(forwardedFromItem.chatInfo.id)
|
||||
dismiss()
|
||||
ItemsModel.shared.loadOpenChat(forwardedFromItem.chatInfo.id) {
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
} label: {
|
||||
|
|
|
@ -35,18 +35,21 @@ struct ChatItemView: View {
|
|||
@Environment(\.showTimestamp) var showTimestamp: Bool
|
||||
@Environment(\.revealed) var revealed: Bool
|
||||
var chatItem: ChatItem
|
||||
var scrollToItemId: (ChatItem.ID) -> Void
|
||||
var maxWidth: CGFloat = .infinity
|
||||
@Binding var allowMenu: Bool
|
||||
|
||||
init(
|
||||
chat: Chat,
|
||||
chatItem: ChatItem,
|
||||
scrollToItemId: @escaping (ChatItem.ID) -> Void,
|
||||
showMember: Bool = false,
|
||||
maxWidth: CGFloat = .infinity,
|
||||
allowMenu: Binding<Bool> = .constant(false)
|
||||
) {
|
||||
self.chat = chat
|
||||
self.chatItem = chatItem
|
||||
self.scrollToItemId = scrollToItemId
|
||||
self.maxWidth = maxWidth
|
||||
_allowMenu = allowMenu
|
||||
}
|
||||
|
@ -90,6 +93,7 @@ struct ChatItemView: View {
|
|||
return FramedItemView(
|
||||
chat: chat,
|
||||
chatItem: chatItem,
|
||||
scrollToItemId: scrollToItemId,
|
||||
preview: preview,
|
||||
maxWidth: maxWidth,
|
||||
imgWidth: adjustedMaxWidth,
|
||||
|
@ -244,15 +248,15 @@ func chatEventText(_ ci: ChatItem, _ secondaryColor: Color) -> Text {
|
|||
struct ChatItemView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
Group{
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .directSnd, .now, "hello"))
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "hello there too"))
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .directSnd, .now, "🙂"))
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "🙂🙂🙂🙂🙂"))
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "🙂🙂🙂🙂🙂🙂"))
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getDeletedContentSample())
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent(sndProgress: .complete), itemDeleted: .deleted(deletedTs: .now)))
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .directSnd, .now, "🙂", .sndSent(sndProgress: .complete), itemLive: true)).environment(\.revealed, true)
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent(sndProgress: .complete), itemLive: true)).environment(\.revealed, true)
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .directSnd, .now, "hello"), scrollToItemId: { _ in })
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "hello there too"), scrollToItemId: { _ in })
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .directSnd, .now, "🙂"), scrollToItemId: { _ in })
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "🙂🙂🙂🙂🙂"), scrollToItemId: { _ in })
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "🙂🙂🙂🙂🙂🙂"), scrollToItemId: { _ in })
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getDeletedContentSample(), scrollToItemId: { _ in })
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent(sndProgress: .complete), itemDeleted: .deleted(deletedTs: .now)), scrollToItemId: { _ in })
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .directSnd, .now, "🙂", .sndSent(sndProgress: .complete), itemLive: true), scrollToItemId: { _ in }).environment(\.revealed, true)
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent(sndProgress: .complete), itemLive: true), scrollToItemId: { _ in }).environment(\.revealed, true)
|
||||
}
|
||||
.environment(\.revealed, false)
|
||||
.previewLayout(.fixed(width: 360, height: 70))
|
||||
|
@ -272,7 +276,8 @@ struct ChatItemView_NonMsgContentDeleted_Previews: PreviewProvider {
|
|||
content: .rcvIntegrityError(msgError: .msgSkipped(fromMsgId: 1, toMsgId: 2)),
|
||||
quotedItem: nil,
|
||||
file: nil
|
||||
)
|
||||
),
|
||||
scrollToItemId: { _ in }
|
||||
)
|
||||
ChatItemView(
|
||||
chat: Chat.sampleData,
|
||||
|
@ -282,7 +287,8 @@ struct ChatItemView_NonMsgContentDeleted_Previews: PreviewProvider {
|
|||
content: .rcvDecryptionError(msgDecryptError: .ratchetHeader, msgCount: 2),
|
||||
quotedItem: nil,
|
||||
file: nil
|
||||
)
|
||||
),
|
||||
scrollToItemId: { _ in }
|
||||
)
|
||||
ChatItemView(
|
||||
chat: Chat.sampleData,
|
||||
|
@ -292,7 +298,8 @@ struct ChatItemView_NonMsgContentDeleted_Previews: PreviewProvider {
|
|||
content: .rcvGroupInvitation(groupInvitation: CIGroupInvitation.getSample(status: .pending), memberRole: .admin),
|
||||
quotedItem: nil,
|
||||
file: nil
|
||||
)
|
||||
),
|
||||
scrollToItemId: { _ in }
|
||||
)
|
||||
ChatItemView(
|
||||
chat: Chat.sampleData,
|
||||
|
@ -302,7 +309,8 @@ struct ChatItemView_NonMsgContentDeleted_Previews: PreviewProvider {
|
|||
content: .rcvGroupEvent(rcvGroupEvent: .memberAdded(groupMemberId: 1, profile: Profile.sampleData)),
|
||||
quotedItem: nil,
|
||||
file: nil
|
||||
)
|
||||
),
|
||||
scrollToItemId: { _ in }
|
||||
)
|
||||
ChatItemView(
|
||||
chat: Chat.sampleData,
|
||||
|
@ -312,7 +320,8 @@ struct ChatItemView_NonMsgContentDeleted_Previews: PreviewProvider {
|
|||
content: ciFeatureContent,
|
||||
quotedItem: nil,
|
||||
file: nil
|
||||
)
|
||||
),
|
||||
scrollToItemId: { _ in }
|
||||
)
|
||||
}
|
||||
.environment(\.revealed, true)
|
||||
|
|
342
apps/ios/Shared/Views/Chat/ChatItemsLoader.swift
Normal file
342
apps/ios/Shared/Views/Chat/ChatItemsLoader.swift
Normal file
|
@ -0,0 +1,342 @@
|
|||
//
|
||||
// ChatItemsLoader.swift
|
||||
// SimpleX (iOS)
|
||||
//
|
||||
// Created by Stanislav Dmitrenko on 17.12.2024.
|
||||
// Copyright © 2024 SimpleX Chat. All rights reserved.
|
||||
//
|
||||
|
||||
import SimpleXChat
|
||||
import SwiftUI
|
||||
|
||||
let TRIM_KEEP_COUNT = 200
|
||||
|
||||
func apiLoadMessages(
|
||||
_ chatId: ChatId,
|
||||
_ pagination: ChatPagination,
|
||||
_ chatState: ActiveChatState,
|
||||
_ search: String = "",
|
||||
_ openAroundItemId: ChatItem.ID? = nil,
|
||||
_ visibleItemIndexesNonReversed: @MainActor () -> ClosedRange<Int> = { 0 ... 0 }
|
||||
) async {
|
||||
let chat: Chat
|
||||
let navInfo: NavigationInfo
|
||||
do {
|
||||
(chat, navInfo) = try await apiGetChat(chatId: chatId, pagination: pagination, search: search)
|
||||
} catch let error {
|
||||
logger.error("apiLoadMessages error: \(responseError(error))")
|
||||
return
|
||||
}
|
||||
|
||||
let chatModel = ChatModel.shared
|
||||
|
||||
// For .initial allow the chatItems to be empty as well as chatModel.chatId to not match this chat because these values become set after .initial finishes
|
||||
let paginationIsInitial = switch pagination { case .initial: true; default: false }
|
||||
let paginationIsLast = switch pagination { case .last: true; default: false }
|
||||
// When openAroundItemId is provided, chatId can be different too
|
||||
if ((chatModel.chatId != chat.id || chat.chatItems.isEmpty) && !paginationIsInitial && !paginationIsLast && openAroundItemId == nil) || Task.isCancelled {
|
||||
return
|
||||
}
|
||||
|
||||
let unreadAfterItemId = chatState.unreadAfterItemId
|
||||
|
||||
let oldItems = Array(ItemsModel.shared.reversedChatItems.reversed())
|
||||
var newItems: [ChatItem] = []
|
||||
switch pagination {
|
||||
case .initial:
|
||||
let newSplits: [Int64] = if !chat.chatItems.isEmpty && navInfo.afterTotal > 0 { [chat.chatItems.last!.id] } else { [] }
|
||||
if chatModel.getChat(chat.id) == nil {
|
||||
chatModel.addChat(chat)
|
||||
}
|
||||
await MainActor.run {
|
||||
chatModel.chatItemStatuses.removeAll()
|
||||
ItemsModel.shared.reversedChatItems = chat.chatItems.reversed()
|
||||
chatModel.updateChatInfo(chat.chatInfo)
|
||||
chatState.splits = newSplits
|
||||
if !chat.chatItems.isEmpty {
|
||||
chatState.unreadAfterItemId = chat.chatItems.last!.id
|
||||
}
|
||||
chatState.totalAfter = navInfo.afterTotal
|
||||
chatState.unreadTotal = chat.chatStats.unreadCount
|
||||
chatState.unreadAfter = navInfo.afterUnread
|
||||
chatState.unreadAfterNewestLoaded = navInfo.afterUnread
|
||||
}
|
||||
case let .before(paginationChatItemId, _):
|
||||
newItems.append(contentsOf: oldItems)
|
||||
let indexInCurrentItems = oldItems.firstIndex(where: { $0.id == paginationChatItemId })
|
||||
guard let indexInCurrentItems else { return }
|
||||
let (newIds, _) = mapItemsToIds(chat.chatItems)
|
||||
let wasSize = newItems.count
|
||||
let visibleItemIndexes = await MainActor.run { visibleItemIndexesNonReversed() }
|
||||
let modifiedSplits = removeDuplicatesAndModifySplitsOnBeforePagination(
|
||||
unreadAfterItemId, &newItems, newIds, chatState.splits, visibleItemIndexes
|
||||
)
|
||||
let insertAt = max((indexInCurrentItems - (wasSize - newItems.count) + modifiedSplits.trimmedIds.count), 0)
|
||||
newItems.insert(contentsOf: chat.chatItems, at: insertAt)
|
||||
let newReversed: [ChatItem] = newItems.reversed()
|
||||
await MainActor.run {
|
||||
ItemsModel.shared.reversedChatItems = newReversed
|
||||
chatState.splits = modifiedSplits.newSplits
|
||||
chatState.moveUnreadAfterItem(modifiedSplits.oldUnreadSplitIndex, modifiedSplits.newUnreadSplitIndex, oldItems)
|
||||
}
|
||||
case let .after(paginationChatItemId, _):
|
||||
newItems.append(contentsOf: oldItems)
|
||||
let indexInCurrentItems = oldItems.firstIndex(where: { $0.id == paginationChatItemId })
|
||||
guard let indexInCurrentItems else { return }
|
||||
|
||||
let mappedItems = mapItemsToIds(chat.chatItems)
|
||||
let newIds = mappedItems.0
|
||||
let (newSplits, unreadInLoaded) = removeDuplicatesAndModifySplitsOnAfterPagination(
|
||||
mappedItems.1, paginationChatItemId, &newItems, newIds, chat, chatState.splits
|
||||
)
|
||||
let indexToAdd = min(indexInCurrentItems + 1, newItems.count)
|
||||
let indexToAddIsLast = indexToAdd == newItems.count
|
||||
newItems.insert(contentsOf: chat.chatItems, at: indexToAdd)
|
||||
let new: [ChatItem] = newItems
|
||||
let newReversed: [ChatItem] = newItems.reversed()
|
||||
await MainActor.run {
|
||||
ItemsModel.shared.reversedChatItems = newReversed
|
||||
chatState.splits = newSplits
|
||||
chatState.moveUnreadAfterItem(chatState.splits.first ?? new.last!.id, new)
|
||||
// loading clear bottom area, updating number of unread items after the newest loaded item
|
||||
if indexToAddIsLast {
|
||||
chatState.unreadAfterNewestLoaded -= unreadInLoaded
|
||||
}
|
||||
}
|
||||
case .around:
|
||||
let newSplits: [Int64]
|
||||
if openAroundItemId == nil {
|
||||
newItems.append(contentsOf: oldItems)
|
||||
newSplits = await removeDuplicatesAndUpperSplits(&newItems, chat, chatState.splits, visibleItemIndexesNonReversed)
|
||||
} else {
|
||||
newSplits = []
|
||||
}
|
||||
// currently, items will always be added on top, which is index 0
|
||||
newItems.insert(contentsOf: chat.chatItems, at: 0)
|
||||
let newReversed: [ChatItem] = newItems.reversed()
|
||||
await MainActor.run {
|
||||
ItemsModel.shared.reversedChatItems = newReversed
|
||||
chatState.splits = [chat.chatItems.last!.id] + newSplits
|
||||
chatState.unreadAfterItemId = chat.chatItems.last!.id
|
||||
chatState.totalAfter = navInfo.afterTotal
|
||||
chatState.unreadTotal = chat.chatStats.unreadCount
|
||||
chatState.unreadAfter = navInfo.afterUnread
|
||||
|
||||
if let openAroundItemId {
|
||||
chatState.unreadAfterNewestLoaded = navInfo.afterUnread
|
||||
ChatModel.shared.openAroundItemId = openAroundItemId
|
||||
ChatModel.shared.chatId = chatId
|
||||
} else {
|
||||
// no need to set it, count will be wrong
|
||||
// chatState.unreadAfterNewestLoaded = navInfo.afterUnread
|
||||
}
|
||||
}
|
||||
case .last:
|
||||
newItems.append(contentsOf: oldItems)
|
||||
removeDuplicates(&newItems, chat)
|
||||
newItems.append(contentsOf: chat.chatItems)
|
||||
let items = newItems
|
||||
await MainActor.run {
|
||||
ItemsModel.shared.reversedChatItems = items.reversed()
|
||||
chatModel.updateChatInfo(chat.chatInfo)
|
||||
chatState.unreadAfterNewestLoaded = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class ModifiedSplits {
|
||||
let oldUnreadSplitIndex: Int
|
||||
let newUnreadSplitIndex: Int
|
||||
let trimmedIds: Set<Int64>
|
||||
let newSplits: [Int64]
|
||||
|
||||
init(oldUnreadSplitIndex: Int, newUnreadSplitIndex: Int, trimmedIds: Set<Int64>, newSplits: [Int64]) {
|
||||
self.oldUnreadSplitIndex = oldUnreadSplitIndex
|
||||
self.newUnreadSplitIndex = newUnreadSplitIndex
|
||||
self.trimmedIds = trimmedIds
|
||||
self.newSplits = newSplits
|
||||
}
|
||||
}
|
||||
|
||||
private func removeDuplicatesAndModifySplitsOnBeforePagination(
|
||||
_ unreadAfterItemId: Int64,
|
||||
_ newItems: inout [ChatItem],
|
||||
_ newIds: Set<Int64>,
|
||||
_ splits: [Int64],
|
||||
_ visibleItemIndexes: ClosedRange<Int>
|
||||
) -> ModifiedSplits {
|
||||
var oldUnreadSplitIndex: Int = -1
|
||||
var newUnreadSplitIndex: Int = -1
|
||||
var lastSplitIndexTrimmed: Int? = nil
|
||||
var allowedTrimming = true
|
||||
var index = 0
|
||||
/** keep the newest [TRIM_KEEP_COUNT] items (bottom area) and oldest [TRIM_KEEP_COUNT] items, trim others */
|
||||
let trimLowerBound = visibleItemIndexes.upperBound + TRIM_KEEP_COUNT
|
||||
let trimUpperBound = newItems.count - TRIM_KEEP_COUNT
|
||||
let trimRange = trimUpperBound >= trimLowerBound ? trimLowerBound ... trimUpperBound : -1 ... -1
|
||||
var trimmedIds = Set<Int64>()
|
||||
let prevTrimLowerBound = visibleItemIndexes.upperBound + TRIM_KEEP_COUNT + 1
|
||||
let prevTrimUpperBound = newItems.count - TRIM_KEEP_COUNT
|
||||
let prevItemTrimRange = prevTrimUpperBound >= prevTrimLowerBound ? prevTrimLowerBound ... prevTrimUpperBound : -1 ... -1
|
||||
var newSplits = splits
|
||||
|
||||
newItems.removeAll(where: {
|
||||
let invisibleItemToTrim = trimRange.contains(index) && allowedTrimming
|
||||
let prevItemWasTrimmed = prevItemTrimRange.contains(index) && allowedTrimming
|
||||
// may disable it after clearing the whole split range
|
||||
if !splits.isEmpty && $0.id == splits.first {
|
||||
// trim only in one split range
|
||||
allowedTrimming = false
|
||||
}
|
||||
let indexInSplits = splits.firstIndex(of: $0.id)
|
||||
if let indexInSplits {
|
||||
lastSplitIndexTrimmed = indexInSplits
|
||||
}
|
||||
if invisibleItemToTrim {
|
||||
if prevItemWasTrimmed {
|
||||
trimmedIds.insert($0.id)
|
||||
} else {
|
||||
newUnreadSplitIndex = index
|
||||
// prev item is not supposed to be trimmed, so exclude current one from trimming and set a split here instead.
|
||||
// this allows to define splitRange of the oldest items and to start loading trimmed items when user scrolls in the opposite direction
|
||||
if let lastSplitIndexTrimmed {
|
||||
var new = newSplits
|
||||
new[lastSplitIndexTrimmed] = $0.id
|
||||
newSplits = new
|
||||
} else {
|
||||
newSplits = [$0.id] + newSplits
|
||||
}
|
||||
}
|
||||
}
|
||||
if unreadAfterItemId == $0.id {
|
||||
oldUnreadSplitIndex = index
|
||||
}
|
||||
index += 1
|
||||
return (invisibleItemToTrim && prevItemWasTrimmed) || newIds.contains($0.id)
|
||||
})
|
||||
// will remove any splits that now becomes obsolete because items were merged
|
||||
newSplits = newSplits.filter { split in !newIds.contains(split) && !trimmedIds.contains(split) }
|
||||
return ModifiedSplits(oldUnreadSplitIndex: oldUnreadSplitIndex, newUnreadSplitIndex: newUnreadSplitIndex, trimmedIds: trimmedIds, newSplits: newSplits)
|
||||
}
|
||||
|
||||
private func removeDuplicatesAndModifySplitsOnAfterPagination(
|
||||
_ unreadInLoaded: Int,
|
||||
_ paginationChatItemId: Int64,
|
||||
_ newItems: inout [ChatItem],
|
||||
_ newIds: Set<Int64>,
|
||||
_ chat: Chat,
|
||||
_ splits: [Int64]
|
||||
) -> ([Int64], Int) {
|
||||
var unreadInLoaded = unreadInLoaded
|
||||
var firstItemIdBelowAllSplits: Int64? = nil
|
||||
var splitsToRemove: Set<Int64> = []
|
||||
let indexInSplitRanges = splits.firstIndex(of: paginationChatItemId)
|
||||
// Currently, it should always load from split range
|
||||
let loadingFromSplitRange = indexInSplitRanges != nil
|
||||
var splitsToMerge: [Int64] = if let indexInSplitRanges, loadingFromSplitRange && indexInSplitRanges + 1 <= splits.count {
|
||||
Array(splits[indexInSplitRanges + 1 ..< splits.count])
|
||||
} else {
|
||||
[]
|
||||
}
|
||||
newItems.removeAll(where: { new in
|
||||
let duplicate = newIds.contains(new.id)
|
||||
if loadingFromSplitRange && duplicate {
|
||||
if splitsToMerge.contains(new.id) {
|
||||
splitsToMerge.removeAll(where: { $0 == new.id })
|
||||
splitsToRemove.insert(new.id)
|
||||
} else if firstItemIdBelowAllSplits == nil && splitsToMerge.isEmpty {
|
||||
// we passed all splits and found duplicated item below all of them, which means no splits anymore below the loaded items
|
||||
firstItemIdBelowAllSplits = new.id
|
||||
}
|
||||
}
|
||||
if duplicate && new.isRcvNew {
|
||||
unreadInLoaded -= 1
|
||||
}
|
||||
return duplicate
|
||||
})
|
||||
var newSplits: [Int64] = []
|
||||
if firstItemIdBelowAllSplits != nil {
|
||||
// no splits anymore, all were merged with bottom items
|
||||
newSplits = []
|
||||
} else {
|
||||
if !splitsToRemove.isEmpty {
|
||||
var new = splits
|
||||
new.removeAll(where: { splitsToRemove.contains($0) })
|
||||
newSplits = new
|
||||
}
|
||||
let enlargedSplit = splits.firstIndex(of: paginationChatItemId)
|
||||
if let enlargedSplit {
|
||||
// move the split to the end of loaded items
|
||||
var new = splits
|
||||
new[enlargedSplit] = chat.chatItems.last!.id
|
||||
newSplits = new
|
||||
}
|
||||
}
|
||||
return (newSplits, unreadInLoaded)
|
||||
}
|
||||
|
||||
private func removeDuplicatesAndUpperSplits(
|
||||
_ newItems: inout [ChatItem],
|
||||
_ chat: Chat,
|
||||
_ splits: [Int64],
|
||||
_ visibleItemIndexesNonReversed: @MainActor () -> ClosedRange<Int>
|
||||
) async -> [Int64] {
|
||||
if splits.isEmpty {
|
||||
removeDuplicates(&newItems, chat)
|
||||
return splits
|
||||
}
|
||||
|
||||
var newSplits = splits
|
||||
let visibleItemIndexes = await MainActor.run { visibleItemIndexesNonReversed() }
|
||||
let (newIds, _) = mapItemsToIds(chat.chatItems)
|
||||
var idsToTrim: [BoxedValue<Set<Int64>>] = []
|
||||
idsToTrim.append(BoxedValue(Set()))
|
||||
var index = 0
|
||||
newItems.removeAll(where: {
|
||||
let duplicate = newIds.contains($0.id)
|
||||
if (!duplicate && visibleItemIndexes.lowerBound > index) {
|
||||
idsToTrim.last?.boxedValue.insert($0.id)
|
||||
}
|
||||
if visibleItemIndexes.lowerBound > index, let firstIndex = newSplits.firstIndex(of: $0.id) {
|
||||
newSplits.remove(at: firstIndex)
|
||||
// closing previous range. All items in idsToTrim that ends with empty set should be deleted.
|
||||
// Otherwise, the last set should be excluded from trimming because it is in currently visible split range
|
||||
idsToTrim.append(BoxedValue(Set()))
|
||||
}
|
||||
|
||||
index += 1
|
||||
return duplicate
|
||||
})
|
||||
if !idsToTrim.last!.boxedValue.isEmpty {
|
||||
// it has some elements to trim from currently visible range which means the items shouldn't be trimmed
|
||||
// Otherwise, the last set would be empty
|
||||
idsToTrim.removeLast()
|
||||
}
|
||||
let allItemsToDelete = idsToTrim.compactMap { set in set.boxedValue }.joined()
|
||||
if !allItemsToDelete.isEmpty {
|
||||
newItems.removeAll(where: { allItemsToDelete.contains($0.id) })
|
||||
}
|
||||
return newSplits
|
||||
}
|
||||
|
||||
// ids, number of unread items
|
||||
private func mapItemsToIds(_ items: [ChatItem]) -> (Set<Int64>, Int) {
|
||||
var unreadInLoaded = 0
|
||||
var ids: Set<Int64> = Set()
|
||||
var i = 0
|
||||
while i < items.count {
|
||||
let item = items[i]
|
||||
ids.insert(item.id)
|
||||
if item.isRcvNew {
|
||||
unreadInLoaded += 1
|
||||
}
|
||||
i += 1
|
||||
}
|
||||
return (ids, unreadInLoaded)
|
||||
}
|
||||
|
||||
private func removeDuplicates(_ newItems: inout [ChatItem], _ chat: Chat) {
|
||||
let (newIds, _) = mapItemsToIds(chat.chatItems)
|
||||
newItems.removeAll { newIds.contains($0.id) }
|
||||
}
|
459
apps/ios/Shared/Views/Chat/ChatItemsMerger.swift
Normal file
459
apps/ios/Shared/Views/Chat/ChatItemsMerger.swift
Normal file
|
@ -0,0 +1,459 @@
|
|||
//
|
||||
// ChatItemsMerger.swift
|
||||
// SimpleX (iOS)
|
||||
//
|
||||
// Created by Stanislav Dmitrenko on 02.12.2024.
|
||||
// Copyright © 2024 SimpleX Chat. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import SimpleXChat
|
||||
|
||||
struct MergedItems: Hashable, Equatable {
|
||||
let items: [MergedItem]
|
||||
let splits: [SplitRange]
|
||||
// chat item id, index in list
|
||||
let indexInParentItems: Dictionary<Int64, Int>
|
||||
|
||||
static func == (lhs: Self, rhs: Self) -> Bool {
|
||||
lhs.hashValue == rhs.hashValue
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
hasher.combine("\(items.hashValue)")
|
||||
}
|
||||
|
||||
static func create(_ items: [ChatItem], _ revealedItems: Set<Int64>, _ chatState: ActiveChatState) -> MergedItems {
|
||||
if items.isEmpty {
|
||||
return MergedItems(items: [], splits: [], indexInParentItems: [:])
|
||||
}
|
||||
|
||||
let unreadCount = chatState.unreadTotal
|
||||
|
||||
let unreadAfterItemId = chatState.unreadAfterItemId
|
||||
let itemSplits = chatState.splits
|
||||
var mergedItems: [MergedItem] = []
|
||||
// Indexes of splits here will be related to reversedChatItems, not chatModel.chatItems
|
||||
var splitRanges: [SplitRange] = []
|
||||
var indexInParentItems = Dictionary<Int64, Int>()
|
||||
var index = 0
|
||||
var unclosedSplitIndex: Int? = nil
|
||||
var unclosedSplitIndexInParent: Int? = nil
|
||||
var visibleItemIndexInParent = -1
|
||||
var unreadBefore = unreadCount - chatState.unreadAfterNewestLoaded
|
||||
var lastRevealedIdsInMergedItems: BoxedValue<[Int64]>? = nil
|
||||
var lastRangeInReversedForMergedItems: BoxedValue<ClosedRange<Int>>? = nil
|
||||
var recent: MergedItem? = nil
|
||||
while index < items.count {
|
||||
let item = items[index]
|
||||
let prev = index >= 1 ? items[index - 1] : nil
|
||||
let next = index + 1 < items.count ? items[index + 1] : nil
|
||||
let category = item.mergeCategory
|
||||
let itemIsSplit = itemSplits.contains(item.id)
|
||||
|
||||
if item.id == unreadAfterItemId {
|
||||
unreadBefore = unreadCount - chatState.unreadAfter
|
||||
}
|
||||
if item.isRcvNew {
|
||||
unreadBefore -= 1
|
||||
}
|
||||
|
||||
let revealed = item.mergeCategory == nil || revealedItems.contains(item.id)
|
||||
if recent != nil, case let .grouped(items, _, _, _, mergeCategory, unreadIds, _, _) = recent, mergeCategory == category, let first = items.boxedValue.first, !revealedItems.contains(first.item.id) && !itemIsSplit {
|
||||
let listItem = ListItem(item: item, prevItem: prev, nextItem: next, unreadBefore: unreadBefore)
|
||||
items.boxedValue.append(listItem)
|
||||
|
||||
if item.isRcvNew {
|
||||
unreadIds.boxedValue.insert(item.id)
|
||||
}
|
||||
if let lastRevealedIdsInMergedItems, let lastRangeInReversedForMergedItems {
|
||||
if revealed {
|
||||
lastRevealedIdsInMergedItems.boxedValue.append(item.id)
|
||||
}
|
||||
lastRangeInReversedForMergedItems.boxedValue = lastRangeInReversedForMergedItems.boxedValue.lowerBound ... index
|
||||
}
|
||||
} else {
|
||||
visibleItemIndexInParent += 1
|
||||
let listItem = ListItem(item: item, prevItem: prev, nextItem: next, unreadBefore: unreadBefore)
|
||||
if item.mergeCategory != nil {
|
||||
if item.mergeCategory != prev?.mergeCategory || lastRevealedIdsInMergedItems == nil {
|
||||
lastRevealedIdsInMergedItems = BoxedValue(revealedItems.contains(item.id) ? [item.id] : [])
|
||||
} else if revealed, let lastRevealedIdsInMergedItems {
|
||||
lastRevealedIdsInMergedItems.boxedValue.append(item.id)
|
||||
}
|
||||
lastRangeInReversedForMergedItems = BoxedValue(index ... index)
|
||||
recent = MergedItem.grouped(
|
||||
items: BoxedValue([listItem]),
|
||||
revealed: revealed,
|
||||
revealedIdsWithinGroup: lastRevealedIdsInMergedItems!,
|
||||
rangeInReversed: lastRangeInReversedForMergedItems!,
|
||||
mergeCategory: item.mergeCategory,
|
||||
unreadIds: BoxedValue(item.isRcvNew ? Set(arrayLiteral: item.id) : Set()),
|
||||
startIndexInReversedItems: index,
|
||||
hash: listItem.genHash(revealedItems.contains(prev?.id ?? -1), revealedItems.contains(next?.id ?? -1))
|
||||
)
|
||||
} else {
|
||||
lastRangeInReversedForMergedItems = nil
|
||||
recent = MergedItem.single(
|
||||
item: listItem,
|
||||
startIndexInReversedItems: index,
|
||||
hash: listItem.genHash(revealedItems.contains(prev?.id ?? -1), revealedItems.contains(next?.id ?? -1))
|
||||
)
|
||||
}
|
||||
mergedItems.append(recent!)
|
||||
}
|
||||
if itemIsSplit {
|
||||
// found item that is considered as a split
|
||||
if let unclosedSplitIndex, let unclosedSplitIndexInParent {
|
||||
// it was at least second split in the list
|
||||
splitRanges.append(SplitRange(itemId: items[unclosedSplitIndex].id, indexRangeInReversed: unclosedSplitIndex ... index - 1, indexRangeInParentItems: unclosedSplitIndexInParent ... visibleItemIndexInParent - 1))
|
||||
}
|
||||
unclosedSplitIndex = index
|
||||
unclosedSplitIndexInParent = visibleItemIndexInParent
|
||||
} else if index + 1 == items.count, let unclosedSplitIndex, let unclosedSplitIndexInParent {
|
||||
// just one split for the whole list, there will be no more, it's the end
|
||||
splitRanges.append(SplitRange(itemId: items[unclosedSplitIndex].id, indexRangeInReversed: unclosedSplitIndex ... index, indexRangeInParentItems: unclosedSplitIndexInParent ... visibleItemIndexInParent))
|
||||
}
|
||||
indexInParentItems[item.id] = visibleItemIndexInParent
|
||||
index += 1
|
||||
}
|
||||
return MergedItems(
|
||||
items: mergedItems,
|
||||
splits: splitRanges,
|
||||
indexInParentItems: indexInParentItems
|
||||
)
|
||||
}
|
||||
|
||||
// Use this check to ensure that mergedItems state based on currently actual state of global
|
||||
// splits and reversedChatItems
|
||||
func isActualState() -> Bool {
|
||||
let im = ItemsModel.shared
|
||||
// do not load anything if global splits state is different than in merged items because it
|
||||
// will produce undefined results in terms of loading and placement of items.
|
||||
// Same applies to reversedChatItems
|
||||
return indexInParentItems.count == im.reversedChatItems.count &&
|
||||
splits.count == im.chatState.splits.count &&
|
||||
// that's just an optimization because most of the time only 1 split exists
|
||||
((splits.count == 1 && splits[0].itemId == im.chatState.splits[0]) || splits.map({ split in split.itemId }).sorted() == im.chatState.splits.sorted())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
enum MergedItem: Identifiable, Hashable, Equatable {
|
||||
// equatable and hashable implementations allows to see the difference and correctly scroll to items we want
|
||||
static func == (lhs: Self, rhs: Self) -> Bool {
|
||||
lhs.hash == rhs.hash
|
||||
}
|
||||
|
||||
var id: Int64 { newest().item.id }
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
hasher.combine(hash)
|
||||
}
|
||||
|
||||
var hash: String {
|
||||
switch self {
|
||||
case .single(_, _, let hash): hash + " 1"
|
||||
case .grouped(let items, _, _, _, _, _, _, let hash): hash + " \(items.boxedValue.count)"
|
||||
}
|
||||
}
|
||||
|
||||
// the item that is always single, cannot be grouped and always revealed
|
||||
case single(
|
||||
item: ListItem,
|
||||
startIndexInReversedItems: Int,
|
||||
hash: String
|
||||
)
|
||||
|
||||
/** The item that can contain multiple items or just one depending on revealed state. When the whole group of merged items is revealed,
|
||||
* there will be multiple [Grouped] items with revealed flag set to true. When the whole group is collapsed, it will be just one instance
|
||||
* of [Grouped] item with all grouped items inside [items]. In other words, number of [MergedItem] will always be equal to number of
|
||||
* visible items in ChatView's EndlessScrollView */
|
||||
case grouped (
|
||||
items: BoxedValue<[ListItem]>,
|
||||
revealed: Bool,
|
||||
// it stores ids for all consecutive revealed items from the same group in order to hide them all on user's action
|
||||
// it's the same list instance for all Grouped items within revealed group
|
||||
/** @see reveal */
|
||||
revealedIdsWithinGroup: BoxedValue<[Int64]>,
|
||||
rangeInReversed: BoxedValue<ClosedRange<Int>>,
|
||||
mergeCategory: CIMergeCategory?,
|
||||
unreadIds: BoxedValue<Set<Int64>>,
|
||||
startIndexInReversedItems: Int,
|
||||
hash: String
|
||||
)
|
||||
|
||||
func revealItems(_ reveal: Bool, _ revealedItems: Binding<Set<Int64>>) {
|
||||
if case .grouped(let items, _, let revealedIdsWithinGroup, _, _, _, _, _) = self {
|
||||
var newRevealed = revealedItems.wrappedValue
|
||||
var i = 0
|
||||
if reveal {
|
||||
while i < items.boxedValue.count {
|
||||
newRevealed.insert(items.boxedValue[i].item.id)
|
||||
i += 1
|
||||
}
|
||||
} else {
|
||||
while i < revealedIdsWithinGroup.boxedValue.count {
|
||||
newRevealed.remove(revealedIdsWithinGroup.boxedValue[i])
|
||||
i += 1
|
||||
}
|
||||
revealedIdsWithinGroup.boxedValue.removeAll()
|
||||
}
|
||||
revealedItems.wrappedValue = newRevealed
|
||||
}
|
||||
}
|
||||
|
||||
var startIndexInReversedItems: Int {
|
||||
get {
|
||||
switch self {
|
||||
case let .single(_, startIndexInReversedItems, _): startIndexInReversedItems
|
||||
case let .grouped(_, _, _, _, _, _, startIndexInReversedItems, _): startIndexInReversedItems
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func hasUnread() -> Bool {
|
||||
switch self {
|
||||
case let .single(item, _, _): item.item.isRcvNew
|
||||
case let .grouped(_, _, _, _, _, unreadIds, _, _): !unreadIds.boxedValue.isEmpty
|
||||
}
|
||||
}
|
||||
|
||||
func newest() -> ListItem {
|
||||
switch self {
|
||||
case let .single(item, _, _): item
|
||||
case let .grouped(items, _, _, _, _, _, _, _): items.boxedValue[0]
|
||||
}
|
||||
}
|
||||
|
||||
func oldest() -> ListItem {
|
||||
switch self {
|
||||
case let .single(item, _, _): item
|
||||
case let .grouped(items, _, _, _, _, _, _, _): items.boxedValue[items.boxedValue.count - 1]
|
||||
}
|
||||
}
|
||||
|
||||
func lastIndexInReversed() -> Int {
|
||||
switch self {
|
||||
case .single: startIndexInReversedItems
|
||||
case let .grouped(items, _, _, _, _, _, _, _): startIndexInReversedItems + items.boxedValue.count - 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct SplitRange {
|
||||
let itemId: Int64
|
||||
/** range of indexes inside reversedChatItems where the first element is the split (it's index is [indexRangeInReversed.first])
|
||||
* so [0, 1, 2, -100-, 101] if the 3 is a split, SplitRange(indexRange = 3 .. 4) will be this SplitRange instance
|
||||
* (3, 4 indexes of the splitRange with the split itself at index 3)
|
||||
* */
|
||||
let indexRangeInReversed: ClosedRange<Int>
|
||||
/** range of indexes inside LazyColumn where the first element is the split (it's index is [indexRangeInParentItems.first]) */
|
||||
let indexRangeInParentItems: ClosedRange<Int>
|
||||
}
|
||||
|
||||
struct ListItem: Hashable {
|
||||
let item: ChatItem
|
||||
let prevItem: ChatItem?
|
||||
let nextItem: ChatItem?
|
||||
// how many unread items before (older than) this one (excluding this one)
|
||||
let unreadBefore: Int
|
||||
|
||||
private func chatDirHash(_ chatDir: CIDirection?) -> Int {
|
||||
guard let chatDir else { return 0 }
|
||||
return switch chatDir {
|
||||
case .directSnd: 0
|
||||
case .directRcv: 1
|
||||
case .groupSnd: 2
|
||||
case let .groupRcv(mem): "\(mem.groupMemberId) \(mem.displayName) \(mem.memberStatus.rawValue) \(mem.memberRole.rawValue) \(mem.image?.hash ?? 0)".hash
|
||||
case .localSnd: 4
|
||||
case .localRcv: 5
|
||||
}
|
||||
}
|
||||
|
||||
// using meta.hashValue instead of parts takes much more time so better to use partial meta here
|
||||
func genHash(_ prevRevealed: Bool, _ nextRevealed: Bool) -> String {
|
||||
"\(item.meta.itemId) \(item.meta.updatedAt.hashValue) \(item.meta.itemEdited) \(item.meta.itemDeleted?.hashValue ?? 0) \(item.meta.itemTimed?.hashValue ?? 0) \(item.meta.itemStatus.hashValue) \(item.meta.sentViaProxy ?? false) \(item.mergeCategory?.hashValue ?? 0) \(chatDirHash(item.chatDir)) \(item.reactions.hashValue) \(item.meta.isRcvNew) \(item.text.hash) \(item.file?.hashValue ?? 0) \(item.quotedItem?.itemId ?? 0) \(unreadBefore) \(prevItem?.id ?? 0) \(chatDirHash(prevItem?.chatDir)) \(prevItem?.mergeCategory?.hashValue ?? 0) \(prevRevealed) \(nextItem?.id ?? 0) \(chatDirHash(nextItem?.chatDir)) \(nextItem?.mergeCategory?.hashValue ?? 0) \(nextRevealed)"
|
||||
}
|
||||
}
|
||||
|
||||
class ActiveChatState {
|
||||
var splits: [Int64] = []
|
||||
var unreadAfterItemId: Int64 = -1
|
||||
// total items after unread after item (exclusive)
|
||||
var totalAfter: Int = 0
|
||||
var unreadTotal: Int = 0
|
||||
// exclusive
|
||||
var unreadAfter: Int = 0
|
||||
// exclusive
|
||||
var unreadAfterNewestLoaded: Int = 0
|
||||
|
||||
func moveUnreadAfterItem(_ toItemId: Int64?, _ nonReversedItems: [ChatItem]) {
|
||||
guard let toItemId else { return }
|
||||
let currentIndex = nonReversedItems.firstIndex(where: { $0.id == unreadAfterItemId })
|
||||
let newIndex = nonReversedItems.firstIndex(where: { $0.id == toItemId })
|
||||
guard let currentIndex, let newIndex else {
|
||||
return
|
||||
}
|
||||
unreadAfterItemId = toItemId
|
||||
let unreadDiff = newIndex > currentIndex
|
||||
? -nonReversedItems[currentIndex + 1..<newIndex + 1].filter { $0.isRcvNew }.count
|
||||
: nonReversedItems[newIndex + 1..<currentIndex + 1].filter { $0.isRcvNew }.count
|
||||
unreadAfter += unreadDiff
|
||||
}
|
||||
|
||||
func moveUnreadAfterItem(_ fromIndex: Int, _ toIndex: Int, _ nonReversedItems: [ChatItem]) {
|
||||
if fromIndex == -1 || toIndex == -1 {
|
||||
return
|
||||
}
|
||||
unreadAfterItemId = nonReversedItems[toIndex].id
|
||||
let unreadDiff = toIndex > fromIndex
|
||||
? -nonReversedItems[fromIndex + 1..<toIndex + 1].filter { $0.isRcvNew }.count
|
||||
: nonReversedItems[toIndex + 1..<fromIndex + 1].filter { $0.isRcvNew }.count
|
||||
unreadAfter += unreadDiff
|
||||
}
|
||||
|
||||
func clear() {
|
||||
splits = []
|
||||
unreadAfterItemId = -1
|
||||
totalAfter = 0
|
||||
unreadTotal = 0
|
||||
unreadAfter = 0
|
||||
unreadAfterNewestLoaded = 0
|
||||
}
|
||||
}
|
||||
|
||||
class BoxedValue<T: Hashable>: Equatable, Hashable {
|
||||
static func == (lhs: BoxedValue<T>, rhs: BoxedValue<T>) -> Bool {
|
||||
lhs.boxedValue == rhs.boxedValue
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
hasher.combine("\(self)")
|
||||
}
|
||||
|
||||
var boxedValue : T
|
||||
init(_ value: T) {
|
||||
self.boxedValue = value
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
func visibleItemIndexesNonReversed(_ listState: EndlessScrollView<MergedItem>.ListState, _ mergedItems: MergedItems) -> ClosedRange<Int> {
|
||||
let zero = 0 ... 0
|
||||
let items = mergedItems.items
|
||||
if items.isEmpty {
|
||||
return zero
|
||||
}
|
||||
let newest = items.count > listState.firstVisibleItemIndex ? items[listState.firstVisibleItemIndex].startIndexInReversedItems : nil
|
||||
let oldest = items.count > listState.lastVisibleItemIndex ? items[listState.lastVisibleItemIndex].lastIndexInReversed() : nil
|
||||
guard let newest, let oldest else {
|
||||
return zero
|
||||
}
|
||||
let size = ItemsModel.shared.reversedChatItems.count
|
||||
let range = size - oldest ... size - newest
|
||||
if range.lowerBound < 0 || range.upperBound < 0 {
|
||||
return zero
|
||||
}
|
||||
|
||||
// visible items mapped to their underlying data structure which is ItemsModel.shared.reversedChatItems.reversed()
|
||||
return range
|
||||
}
|
||||
|
||||
class RecalculatePositions {
|
||||
private var chatState: ActiveChatState { get { ItemsModel.shared.chatState } }
|
||||
|
||||
func read(_ itemIds: Set<Int64>?, _ newItems: [ChatItem]) {
|
||||
guard let itemIds else {
|
||||
// special case when the whole chat became read
|
||||
chatState.unreadTotal = 0
|
||||
chatState.unreadAfter = 0
|
||||
return
|
||||
}
|
||||
var unreadAfterItemIndex: Int = -1
|
||||
// since it's more often that the newest items become read, it's logical to loop from the end of the list to finish it faster
|
||||
var i = newItems.count - 1
|
||||
var ids = itemIds
|
||||
// intermediate variables to prevent re-setting state value a lot of times without reason
|
||||
var newUnreadTotal = chatState.unreadTotal
|
||||
var newUnreadAfter = chatState.unreadAfter
|
||||
while i >= 0 {
|
||||
let item = newItems[i]
|
||||
if item.id == chatState.unreadAfterItemId {
|
||||
unreadAfterItemIndex = i
|
||||
}
|
||||
if ids.contains(item.id) {
|
||||
// was unread, now this item is read
|
||||
if (unreadAfterItemIndex == -1) {
|
||||
newUnreadAfter -= 1
|
||||
}
|
||||
newUnreadTotal -= 1
|
||||
ids.remove(item.id)
|
||||
if ids.isEmpty {
|
||||
break
|
||||
}
|
||||
}
|
||||
i -= 1
|
||||
}
|
||||
chatState.unreadTotal = newUnreadTotal
|
||||
chatState.unreadAfter = newUnreadAfter
|
||||
}
|
||||
func added(_ item: (Int64, Bool), _ index: Int) {
|
||||
if item.1 {
|
||||
chatState.unreadAfter += 1
|
||||
chatState.unreadTotal += 1
|
||||
}
|
||||
}
|
||||
func removed(_ itemIds: [(Int64, Int, Bool)], _ newItems: [ChatItem]) {
|
||||
var newSplits: [Int64] = []
|
||||
for split in chatState.splits {
|
||||
let index = itemIds.firstIndex(where: { (delId, _, _) in delId == split })
|
||||
// deleted the item that was right before the split between items, find newer item so it will act like the split
|
||||
if let index {
|
||||
let idx = itemIds[index].1 - itemIds.filter { (_, delIndex, _) in delIndex <= index }.count
|
||||
let newSplit = newItems.count > idx && idx >= 0 ? newItems[idx].id : nil
|
||||
// it the whole section is gone and splits overlap, don't add it at all
|
||||
if let newSplit, !newSplits.contains(newSplit) {
|
||||
newSplits.append(newSplit)
|
||||
}
|
||||
} else {
|
||||
newSplits.append(split)
|
||||
}
|
||||
}
|
||||
chatState.splits = newSplits
|
||||
|
||||
let index = itemIds.firstIndex(where: { (delId, _, _) in delId == chatState.unreadAfterItemId })
|
||||
// unread after item was removed
|
||||
if let index {
|
||||
let idx = itemIds[index].1 - itemIds.filter { (_, delIndex, _) in delIndex <= index }.count
|
||||
var newUnreadAfterItemId = newItems.count > idx && idx >= 0 ? newItems[idx].id : nil
|
||||
let newUnreadAfterItemWasNull = newUnreadAfterItemId == nil
|
||||
if newUnreadAfterItemId == nil {
|
||||
// everything on top (including unread after item) were deleted, take top item as unread after id
|
||||
newUnreadAfterItemId = newItems.first?.id
|
||||
}
|
||||
if let newUnreadAfterItemId {
|
||||
chatState.unreadAfterItemId = newUnreadAfterItemId
|
||||
chatState.totalAfter -= itemIds.filter { (_, delIndex, _) in delIndex > index }.count
|
||||
chatState.unreadTotal -= itemIds.filter { (_, delIndex, isRcvNew) in delIndex <= index && isRcvNew }.count
|
||||
chatState.unreadAfter -= itemIds.filter { (_, delIndex, isRcvNew) in delIndex > index && isRcvNew }.count
|
||||
if newUnreadAfterItemWasNull {
|
||||
// since the unread after item was moved one item after initial position, adjust counters accordingly
|
||||
if newItems.first?.isRcvNew == true {
|
||||
chatState.unreadTotal += 1
|
||||
chatState.unreadAfter -= 1
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// all items were deleted, 0 items in chatItems
|
||||
chatState.unreadAfterItemId = -1
|
||||
chatState.totalAfter = 0
|
||||
chatState.unreadTotal = 0
|
||||
chatState.unreadAfter = 0
|
||||
}
|
||||
} else {
|
||||
chatState.totalAfter -= itemIds.count
|
||||
}
|
||||
}
|
||||
func cleared() { chatState.clear() }
|
||||
}
|
165
apps/ios/Shared/Views/Chat/ChatScrollHelpers.swift
Normal file
165
apps/ios/Shared/Views/Chat/ChatScrollHelpers.swift
Normal file
|
@ -0,0 +1,165 @@
|
|||
//
|
||||
// ChatScrollHelpers.swift
|
||||
// SimpleX (iOS)
|
||||
//
|
||||
// Created by Stanislav Dmitrenko on 20.12.2024.
|
||||
// Copyright © 2024 SimpleX Chat. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import SimpleXChat
|
||||
|
||||
func loadLastItems(_ loadingMoreItems: Binding<Bool>, loadingBottomItems: Binding<Bool>, _ chat: Chat) {
|
||||
if ItemsModel.shared.chatState.totalAfter == 0 {
|
||||
return
|
||||
}
|
||||
loadingMoreItems.wrappedValue = true
|
||||
loadingBottomItems.wrappedValue = true
|
||||
Task {
|
||||
try? await Task.sleep(nanoseconds: 500_000000)
|
||||
if ChatModel.shared.chatId != chat.chatInfo.id {
|
||||
await MainActor.run {
|
||||
loadingMoreItems.wrappedValue = false
|
||||
}
|
||||
return
|
||||
}
|
||||
await apiLoadMessages(chat.chatInfo.id, ChatPagination.last(count: 50), ItemsModel.shared.chatState)
|
||||
await MainActor.run {
|
||||
loadingMoreItems.wrappedValue = false
|
||||
loadingBottomItems.wrappedValue = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class PreloadState {
|
||||
static let shared = PreloadState()
|
||||
var prevFirstVisible: Int64 = Int64.min
|
||||
var prevItemsCount: Int = 0
|
||||
var preloading: Bool = false
|
||||
}
|
||||
|
||||
func preloadIfNeeded(
|
||||
_ allowLoadMoreItems: Binding<Bool>,
|
||||
_ ignoreLoadingRequests: Binding<Int64?>,
|
||||
_ listState: EndlessScrollView<MergedItem>.ListState,
|
||||
_ mergedItems: BoxedValue<MergedItems>,
|
||||
loadItems: @escaping (Bool, ChatPagination) async -> Bool
|
||||
) {
|
||||
let state = PreloadState.shared
|
||||
guard !listState.isScrolling && !listState.isAnimatedScrolling,
|
||||
state.prevFirstVisible != listState.firstVisibleItemIndex || state.prevItemsCount != mergedItems.boxedValue.indexInParentItems.count,
|
||||
!state.preloading,
|
||||
listState.totalItemsCount > 0
|
||||
else {
|
||||
return
|
||||
}
|
||||
state.prevFirstVisible = listState.firstVisibleItemId as! Int64
|
||||
state.prevItemsCount = mergedItems.boxedValue.indexInParentItems.count
|
||||
state.preloading = true
|
||||
let allowLoadMore = allowLoadMoreItems.wrappedValue
|
||||
Task {
|
||||
defer {
|
||||
state.preloading = false
|
||||
}
|
||||
await preloadItems(mergedItems.boxedValue, allowLoadMore, listState, ignoreLoadingRequests) { pagination in
|
||||
await loadItems(false, pagination)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func preloadItems(
|
||||
_ mergedItems: MergedItems,
|
||||
_ allowLoadMoreItems: Bool,
|
||||
_ listState: EndlessScrollView<MergedItem>.ListState,
|
||||
_ ignoreLoadingRequests: Binding<Int64?>,
|
||||
_ loadItems: @escaping (ChatPagination) async -> Bool)
|
||||
async {
|
||||
let allowLoad = allowLoadMoreItems || mergedItems.items.count == listState.lastVisibleItemIndex + 1
|
||||
let remaining = ChatPagination.UNTIL_PRELOAD_COUNT
|
||||
let firstVisibleIndex = listState.firstVisibleItemIndex
|
||||
|
||||
if !(await preloadItemsBefore()) {
|
||||
await preloadItemsAfter()
|
||||
}
|
||||
|
||||
func preloadItemsBefore() async -> Bool {
|
||||
let splits = mergedItems.splits
|
||||
let lastVisibleIndex = listState.lastVisibleItemIndex
|
||||
var lastIndexToLoadFrom: Int? = findLastIndexToLoadFromInSplits(firstVisibleIndex, lastVisibleIndex, remaining, splits)
|
||||
let items: [ChatItem] = ItemsModel.shared.reversedChatItems.reversed()
|
||||
if splits.isEmpty && !items.isEmpty && lastVisibleIndex > mergedItems.items.count - remaining {
|
||||
lastIndexToLoadFrom = items.count - 1
|
||||
}
|
||||
let loadFromItemId: Int64?
|
||||
if allowLoad, let lastIndexToLoadFrom {
|
||||
let index = items.count - 1 - lastIndexToLoadFrom
|
||||
loadFromItemId = index >= 0 ? items[index].id : nil
|
||||
} else {
|
||||
loadFromItemId = nil
|
||||
}
|
||||
guard let loadFromItemId, ignoreLoadingRequests.wrappedValue != loadFromItemId else {
|
||||
return false
|
||||
}
|
||||
let sizeWas = items.count
|
||||
let firstItemIdWas = items.first?.id
|
||||
let triedToLoad = await loadItems(ChatPagination.before(chatItemId: loadFromItemId, count: ChatPagination.PRELOAD_COUNT))
|
||||
if triedToLoad && sizeWas == ItemsModel.shared.reversedChatItems.count && firstItemIdWas == ItemsModel.shared.reversedChatItems.last?.id {
|
||||
ignoreLoadingRequests.wrappedValue = loadFromItemId
|
||||
}
|
||||
return triedToLoad
|
||||
}
|
||||
|
||||
func preloadItemsAfter() async {
|
||||
let splits = mergedItems.splits
|
||||
let split = splits.last(where: { $0.indexRangeInParentItems.contains(firstVisibleIndex) })
|
||||
// we're inside a splitRange (top --- [end of the splitRange --- we're here --- start of the splitRange] --- bottom)
|
||||
let reversedItems: [ChatItem] = ItemsModel.shared.reversedChatItems
|
||||
if let split, split.indexRangeInParentItems.lowerBound + remaining > firstVisibleIndex {
|
||||
let index = split.indexRangeInReversed.lowerBound
|
||||
if index >= 0 {
|
||||
let loadFromItemId = reversedItems[index].id
|
||||
_ = await loadItems(ChatPagination.after(chatItemId: loadFromItemId, count: ChatPagination.PRELOAD_COUNT))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func oldestPartiallyVisibleListItemInListStateOrNull(_ listState: EndlessScrollView<MergedItem>.ListState) -> ListItem? {
|
||||
if listState.lastVisibleItemIndex < listState.items.count {
|
||||
return listState.items[listState.lastVisibleItemIndex].oldest()
|
||||
} else {
|
||||
return listState.items.last?.oldest()
|
||||
}
|
||||
}
|
||||
|
||||
private func findLastIndexToLoadFromInSplits(_ firstVisibleIndex: Int, _ lastVisibleIndex: Int, _ remaining: Int, _ splits: [SplitRange]) -> Int? {
|
||||
for split in splits {
|
||||
// before any split
|
||||
if split.indexRangeInParentItems.lowerBound > firstVisibleIndex {
|
||||
if lastVisibleIndex > (split.indexRangeInParentItems.lowerBound - remaining) {
|
||||
return split.indexRangeInReversed.lowerBound - 1
|
||||
}
|
||||
break
|
||||
}
|
||||
let containsInRange = split.indexRangeInParentItems.contains(firstVisibleIndex)
|
||||
if containsInRange {
|
||||
if lastVisibleIndex > (split.indexRangeInParentItems.upperBound - remaining) {
|
||||
return split.indexRangeInReversed.upperBound
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
/// Disable animation on iOS 15
|
||||
func withConditionalAnimation<Result>(
|
||||
_ animation: Animation? = .default,
|
||||
_ body: () throws -> Result
|
||||
) rethrows -> Result {
|
||||
if #available(iOS 16.0, *) {
|
||||
try withAnimation(animation, body)
|
||||
} else {
|
||||
try body()
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -325,6 +325,7 @@ struct ComposeView: View {
|
|||
@ObservedObject var chat: Chat
|
||||
@Binding var composeState: ComposeState
|
||||
@Binding var keyboardVisible: Bool
|
||||
@Binding var keyboardHiddenDate: Date
|
||||
@Binding var selectedRange: NSRange
|
||||
|
||||
@State var linkUrl: URL? = nil
|
||||
|
@ -392,7 +393,7 @@ struct ComposeView: View {
|
|||
}
|
||||
.disabled(composeState.attachmentDisabled || !chat.userCanSend || (chat.chatInfo.contact?.nextSendGrpInv ?? false))
|
||||
.frame(width: 25, height: 25)
|
||||
.padding(.bottom, 12)
|
||||
.padding(.bottom, 16)
|
||||
.padding(.leading, 12)
|
||||
.tint(theme.colors.primary)
|
||||
if case let .group(g) = chat.chatInfo,
|
||||
|
@ -434,6 +435,7 @@ struct ComposeView: View {
|
|||
timedMessageAllowed: chat.chatInfo.featureEnabled(.timedMessages),
|
||||
onMediaAdded: { media in if !media.isEmpty { chosenMedia = media }},
|
||||
keyboardVisible: $keyboardVisible,
|
||||
keyboardHiddenDate: $keyboardHiddenDate,
|
||||
sendButtonColor: chat.chatInfo.incognito
|
||||
? .indigo.opacity(colorScheme == .dark ? 1 : 0.7)
|
||||
: theme.colors.primary
|
||||
|
@ -1280,6 +1282,7 @@ struct ComposeView_Previews: PreviewProvider {
|
|||
chat: chat,
|
||||
composeState: $composeState,
|
||||
keyboardVisible: Binding.constant(true),
|
||||
keyboardHiddenDate: Binding.constant(Date.now),
|
||||
selectedRange: $selectedRange
|
||||
)
|
||||
.environmentObject(ChatModel())
|
||||
|
@ -1287,6 +1290,7 @@ struct ComposeView_Previews: PreviewProvider {
|
|||
chat: chat,
|
||||
composeState: $composeState,
|
||||
keyboardVisible: Binding.constant(true),
|
||||
keyboardHiddenDate: Binding.constant(Date.now),
|
||||
selectedRange: $selectedRange
|
||||
)
|
||||
.environmentObject(ChatModel())
|
||||
|
|
|
@ -16,19 +16,14 @@ struct NativeTextEditor: UIViewRepresentable {
|
|||
@Binding var disableEditing: Bool
|
||||
@Binding var height: CGFloat
|
||||
@Binding var focused: Bool
|
||||
@Binding var lastUnfocusedDate: Date
|
||||
@Binding var placeholder: String?
|
||||
@Binding var selectedRange: NSRange
|
||||
let onImagesAdded: ([UploadContent]) -> Void
|
||||
|
||||
private let minHeight: CGFloat = 37
|
||||
static let minHeight: CGFloat = 39
|
||||
|
||||
private let defaultHeight: CGFloat = {
|
||||
let field = CustomUITextField(parent: nil, height: Binding.constant(0))
|
||||
field.textContainerInset = UIEdgeInsets(top: 8, left: 5, bottom: 6, right: 4)
|
||||
return min(max(field.sizeThatFits(CGSizeMake(field.frame.size.width, CGFloat.greatestFiniteMagnitude)).height, 37), 360).rounded(.down)
|
||||
}()
|
||||
|
||||
func makeUIView(context: Context) -> UITextView {
|
||||
func makeUIView(context: Context) -> CustomUITextField {
|
||||
let field = CustomUITextField(parent: self, height: _height)
|
||||
field.backgroundColor = .clear
|
||||
field.text = text
|
||||
|
@ -38,10 +33,9 @@ struct NativeTextEditor: UIViewRepresentable {
|
|||
if !disableEditing {
|
||||
text = newText
|
||||
field.textAlignment = alignment(text)
|
||||
updateFont(field)
|
||||
field.updateFont()
|
||||
// Speed up the process of updating layout, reduce jumping content on screen
|
||||
updateHeight(field)
|
||||
self.height = field.frame.size.height
|
||||
field.updateHeight()
|
||||
} else {
|
||||
field.text = text
|
||||
}
|
||||
|
@ -49,67 +43,47 @@ struct NativeTextEditor: UIViewRepresentable {
|
|||
onImagesAdded(images)
|
||||
}
|
||||
}
|
||||
field.setOnFocusChangedListener { focused = $0 }
|
||||
field.setOnFocusChangedListener {
|
||||
focused = $0
|
||||
if !focused {
|
||||
lastUnfocusedDate = .now
|
||||
}
|
||||
}
|
||||
field.delegate = field
|
||||
field.textContainerInset = UIEdgeInsets(top: 8, left: 5, bottom: 6, right: 4)
|
||||
field.setPlaceholderView()
|
||||
updateFont(field)
|
||||
updateHeight(field)
|
||||
field.updateFont()
|
||||
field.updateHeight(updateBindingNow: false)
|
||||
return field
|
||||
}
|
||||
|
||||
func updateUIView(_ field: UITextView, context: Context) {
|
||||
func updateUIView(_ field: CustomUITextField, context: Context) {
|
||||
if field.markedTextRange == nil && field.text != text {
|
||||
field.text = text
|
||||
field.textAlignment = alignment(text)
|
||||
updateFont(field)
|
||||
updateHeight(field)
|
||||
field.updateFont()
|
||||
field.updateHeight(updateBindingNow: false)
|
||||
}
|
||||
|
||||
let castedField = field as! CustomUITextField
|
||||
if castedField.placeholder != placeholder {
|
||||
castedField.placeholder = placeholder
|
||||
if field.placeholder != placeholder {
|
||||
field.placeholder = placeholder
|
||||
}
|
||||
|
||||
if field.selectedRange != selectedRange {
|
||||
field.selectedRange = selectedRange
|
||||
}
|
||||
}
|
||||
|
||||
private func updateHeight(_ field: UITextView) {
|
||||
let maxHeight = min(360, field.font!.lineHeight * 12)
|
||||
// When having emoji in text view and then removing it, sizeThatFits shows previous size (too big for empty text view), so using work around with default size
|
||||
let newHeight = field.text == ""
|
||||
? defaultHeight
|
||||
: min(max(field.sizeThatFits(CGSizeMake(field.frame.size.width, CGFloat.greatestFiniteMagnitude)).height, minHeight), maxHeight).rounded(.down)
|
||||
|
||||
if field.frame.size.height != newHeight {
|
||||
field.frame.size = CGSizeMake(field.frame.size.width, newHeight)
|
||||
(field as! CustomUITextField).invalidateIntrinsicContentHeight(newHeight)
|
||||
}
|
||||
}
|
||||
|
||||
private func updateFont(_ field: UITextView) {
|
||||
let newFont = isShortEmoji(field.text)
|
||||
? (field.text.count < 4 ? largeEmojiUIFont : mediumEmojiUIFont)
|
||||
: UIFont.preferredFont(forTextStyle: .body)
|
||||
if field.font != newFont {
|
||||
field.font = newFont
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func alignment(_ text: String) -> NSTextAlignment {
|
||||
isRightToLeft(text) ? .right : .left
|
||||
}
|
||||
|
||||
private class CustomUITextField: UITextView, UITextViewDelegate {
|
||||
class CustomUITextField: UITextView, UITextViewDelegate {
|
||||
var parent: NativeTextEditor?
|
||||
var height: Binding<CGFloat>
|
||||
var newHeight: CGFloat = 0
|
||||
var onTextChanged: (String, [UploadContent]) -> Void = { newText, image in }
|
||||
var onFocusChanged: (Bool) -> Void = { focused in }
|
||||
|
||||
|
||||
private let placeholderLabel: UILabel = UILabel()
|
||||
|
||||
init(parent: NativeTextEditor?, height: Binding<CGFloat>) {
|
||||
|
@ -135,11 +109,44 @@ private class CustomUITextField: UITextView, UITextViewDelegate {
|
|||
invalidateIntrinsicContentSize()
|
||||
}
|
||||
|
||||
override var intrinsicContentSize: CGSize {
|
||||
if height.wrappedValue != newHeight {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now(), execute: { self.height.wrappedValue = self.newHeight })
|
||||
func updateHeight(updateBindingNow: Bool = true) {
|
||||
let maxHeight = min(360, font!.lineHeight * 12)
|
||||
let newHeight = min(max(sizeThatFits(CGSizeMake(frame.size.width, CGFloat.greatestFiniteMagnitude)).height, NativeTextEditor.minHeight), maxHeight).rounded(.down)
|
||||
|
||||
if self.newHeight != newHeight {
|
||||
frame.size = CGSizeMake(frame.size.width, newHeight)
|
||||
invalidateIntrinsicContentHeight(newHeight)
|
||||
if updateBindingNow {
|
||||
self.height.wrappedValue = newHeight
|
||||
} else {
|
||||
DispatchQueue.main.async {
|
||||
self.height.wrappedValue = newHeight
|
||||
}
|
||||
}
|
||||
}
|
||||
return CGSizeMake(0, newHeight)
|
||||
}
|
||||
|
||||
func updateFont() {
|
||||
let newFont = isShortEmoji(text)
|
||||
? (text.count < 4 ? largeEmojiUIFont : mediumEmojiUIFont)
|
||||
: UIFont.preferredFont(forTextStyle: .body)
|
||||
if font != newFont {
|
||||
font = newFont
|
||||
// force apply new font because it has problem with doing it when the field had two emojis
|
||||
if text.count == 0 {
|
||||
text = " "
|
||||
text = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
updateHeight()
|
||||
}
|
||||
|
||||
override var intrinsicContentSize: CGSize {
|
||||
CGSizeMake(0, newHeight)
|
||||
}
|
||||
|
||||
func setOnTextChangedListener(onTextChanged: @escaping (String, [UploadContent]) -> Void) {
|
||||
|
@ -265,6 +272,7 @@ struct NativeTextEditor_Previews: PreviewProvider{
|
|||
disableEditing: Binding.constant(false),
|
||||
height: Binding.constant(100),
|
||||
focused: Binding.constant(false),
|
||||
lastUnfocusedDate: Binding.constant(.now),
|
||||
placeholder: Binding.constant("Placeholder"),
|
||||
selectedRange: Binding.constant(NSRange(location: 0, length: 0)),
|
||||
onImagesAdded: { _ in }
|
||||
|
|
|
@ -32,8 +32,9 @@ struct SendMessageView: View {
|
|||
@State private var holdingVMR = false
|
||||
@Namespace var namespace
|
||||
@Binding var keyboardVisible: Bool
|
||||
@Binding var keyboardHiddenDate: Date
|
||||
var sendButtonColor = Color.accentColor
|
||||
@State private var teHeight: CGFloat = 42
|
||||
@State private var teHeight: CGFloat = NativeTextEditor.minHeight
|
||||
@State private var teFont: Font = .body
|
||||
@State private var sendButtonSize: CGFloat = 29
|
||||
@State private var sendButtonOpacity: CGFloat = 1
|
||||
|
@ -44,53 +45,54 @@ struct SendMessageView: View {
|
|||
@UserDefault(DEFAULT_LIVE_MESSAGE_ALERT_SHOWN) private var liveMessageAlertShown = false
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
let composeShape = RoundedRectangle(cornerSize: CGSize(width: 20, height: 20))
|
||||
HStack(alignment: .bottom) {
|
||||
ZStack(alignment: .leading) {
|
||||
if case .voicePreview = composeState.preview {
|
||||
Text("Voice message…")
|
||||
.font(teFont.italic())
|
||||
.multilineTextAlignment(.leading)
|
||||
.foregroundColor(theme.colors.secondary)
|
||||
.padding(.horizontal, 10)
|
||||
.padding(.vertical, 8)
|
||||
.frame(maxWidth: .infinity)
|
||||
} else {
|
||||
NativeTextEditor(
|
||||
text: $composeState.message,
|
||||
disableEditing: $composeState.inProgress,
|
||||
height: $teHeight,
|
||||
focused: $keyboardVisible,
|
||||
placeholder: Binding(get: { composeState.placeholder }, set: { _ in }),
|
||||
selectedRange: $selectedRange,
|
||||
onImagesAdded: onMediaAdded
|
||||
)
|
||||
.allowsTightening(false)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
}
|
||||
}
|
||||
if progressByTimeout {
|
||||
ProgressView()
|
||||
.scaleEffect(1.4)
|
||||
.frame(width: 31, height: 31, alignment: .center)
|
||||
.padding([.bottom, .trailing], 3)
|
||||
} else {
|
||||
VStack(alignment: .trailing) {
|
||||
if teHeight > 100 && !composeState.inProgress {
|
||||
deleteTextButton()
|
||||
Spacer()
|
||||
}
|
||||
composeActionButtons()
|
||||
}
|
||||
.frame(height: teHeight, alignment: .bottom)
|
||||
}
|
||||
let composeShape = RoundedRectangle(cornerSize: CGSize(width: 20, height: 20))
|
||||
ZStack(alignment: .leading) {
|
||||
if case .voicePreview = composeState.preview {
|
||||
Text("Voice message…")
|
||||
.font(teFont.italic())
|
||||
.multilineTextAlignment(.leading)
|
||||
.foregroundColor(theme.colors.secondary)
|
||||
.padding(.horizontal, 10)
|
||||
.padding(.vertical, 8)
|
||||
.padding(.trailing, 32)
|
||||
.frame(maxWidth: .infinity)
|
||||
} else {
|
||||
NativeTextEditor(
|
||||
text: $composeState.message,
|
||||
disableEditing: $composeState.inProgress,
|
||||
height: $teHeight,
|
||||
focused: $keyboardVisible,
|
||||
lastUnfocusedDate: $keyboardHiddenDate,
|
||||
placeholder: Binding(get: { composeState.placeholder }, set: { _ in }),
|
||||
selectedRange: $selectedRange,
|
||||
onImagesAdded: onMediaAdded
|
||||
)
|
||||
.padding(.trailing, 32)
|
||||
.allowsTightening(false)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
}
|
||||
.padding(.vertical, 1)
|
||||
.background(theme.colors.background)
|
||||
.clipShape(composeShape)
|
||||
.overlay(composeShape.strokeBorder(.secondary, lineWidth: 0.5).opacity(0.7))
|
||||
}
|
||||
.overlay(alignment: .topTrailing, content: {
|
||||
if !progressByTimeout && teHeight > 100 && !composeState.inProgress {
|
||||
deleteTextButton()
|
||||
}
|
||||
})
|
||||
.overlay(alignment: .bottomTrailing, content: {
|
||||
if progressByTimeout {
|
||||
ProgressView()
|
||||
.scaleEffect(1.4)
|
||||
.frame(width: 31, height: 31, alignment: .center)
|
||||
.padding([.bottom, .trailing], 4)
|
||||
} else {
|
||||
composeActionButtons()
|
||||
// required for intercepting clicks
|
||||
.background(.white.opacity(0.000001))
|
||||
}
|
||||
})
|
||||
.padding(.vertical, 1)
|
||||
.background(theme.colors.background)
|
||||
.clipShape(composeShape)
|
||||
.overlay(composeShape.strokeBorder(.secondary, lineWidth: 0.5).opacity(0.7))
|
||||
.onChange(of: composeState.message, perform: { text in updateFont(text) })
|
||||
.onChange(of: composeState.inProgress) { inProgress in
|
||||
if inProgress {
|
||||
|
@ -169,7 +171,7 @@ struct SendMessageView: View {
|
|||
!composeState.sendEnabled ||
|
||||
composeState.inProgress
|
||||
)
|
||||
.frame(width: 29, height: 29)
|
||||
.frame(width: 31, height: 31)
|
||||
.padding([.bottom, .trailing], 4)
|
||||
}
|
||||
|
||||
|
@ -192,7 +194,7 @@ struct SendMessageView: View {
|
|||
composeState.endLiveDisabled ||
|
||||
disableSendButton
|
||||
)
|
||||
.frame(width: 29, height: 29)
|
||||
.frame(width: 31, height: 31)
|
||||
.contextMenu{
|
||||
sendButtonContextMenuItems()
|
||||
}
|
||||
|
@ -269,7 +271,7 @@ struct SendMessageView: View {
|
|||
.foregroundColor(theme.colors.primary)
|
||||
}
|
||||
.disabled(disabled)
|
||||
.frame(width: 29, height: 29)
|
||||
.frame(width: 31, height: 31)
|
||||
.padding([.bottom, .trailing], 4)
|
||||
._onButtonGesture { down in
|
||||
if down {
|
||||
|
@ -325,7 +327,7 @@ struct SendMessageView: View {
|
|||
.foregroundColor(theme.colors.secondary)
|
||||
}
|
||||
.disabled(composeState.inProgress)
|
||||
.frame(width: 29, height: 29)
|
||||
.frame(width: 31, height: 31)
|
||||
.padding([.bottom, .trailing], 4)
|
||||
}
|
||||
|
||||
|
@ -410,7 +412,7 @@ struct SendMessageView: View {
|
|||
.foregroundColor(theme.colors.primary)
|
||||
}
|
||||
.disabled(composeState.inProgress)
|
||||
.frame(width: 29, height: 29)
|
||||
.frame(width: 31, height: 31)
|
||||
.padding([.bottom, .trailing], 4)
|
||||
}
|
||||
|
||||
|
@ -441,7 +443,8 @@ struct SendMessageView_Previews: PreviewProvider {
|
|||
selectedRange: $selectedRange,
|
||||
sendMessage: { _ in },
|
||||
onMediaAdded: { _ in },
|
||||
keyboardVisible: Binding.constant(true)
|
||||
keyboardVisible: Binding.constant(true),
|
||||
keyboardHiddenDate: Binding.constant(Date.now)
|
||||
)
|
||||
}
|
||||
VStack {
|
||||
|
@ -452,7 +455,8 @@ struct SendMessageView_Previews: PreviewProvider {
|
|||
selectedRange: $selectedRangeEditing,
|
||||
sendMessage: { _ in },
|
||||
onMediaAdded: { _ in },
|
||||
keyboardVisible: Binding.constant(true)
|
||||
keyboardVisible: Binding.constant(true),
|
||||
keyboardHiddenDate: Binding.constant(Date.now)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
698
apps/ios/Shared/Views/Chat/EndlessScrollView.swift
Normal file
698
apps/ios/Shared/Views/Chat/EndlessScrollView.swift
Normal file
|
@ -0,0 +1,698 @@
|
|||
//
|
||||
// EndlessScrollView.swift
|
||||
// SimpleX (iOS)
|
||||
//
|
||||
// Created by Stanislav Dmitrenko on 25.01.2025.
|
||||
// Copyright © 2024 SimpleX Chat. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct ScrollRepresentable<Content: View, ScrollItem>: UIViewControllerRepresentable where ScrollItem : Identifiable, ScrollItem: Hashable {
|
||||
|
||||
let scrollView: EndlessScrollView<ScrollItem>
|
||||
let content: (Int, ScrollItem) -> Content
|
||||
|
||||
func makeUIViewController(context: Context) -> ScrollController {
|
||||
ScrollController.init(scrollView: scrollView, content: content)
|
||||
}
|
||||
|
||||
func updateUIViewController(_ controller: ScrollController, context: Context) {}
|
||||
|
||||
class ScrollController: UIViewController {
|
||||
let scrollView: EndlessScrollView<ScrollItem>
|
||||
fileprivate var items: [ScrollItem] = []
|
||||
fileprivate var content: ((Int, ScrollItem) -> Content)!
|
||||
|
||||
fileprivate init(scrollView: EndlessScrollView<ScrollItem>, content: @escaping (Int, ScrollItem) -> Content) {
|
||||
self.scrollView = scrollView
|
||||
self.content = content
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
self.view = scrollView
|
||||
scrollView.createCell = createCell
|
||||
scrollView.updateCell = updateCell
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) { fatalError() }
|
||||
|
||||
private func createCell(_ index: Int, _ items: [ScrollItem], _ cellsToReuse: inout [UIView]) -> UIView {
|
||||
let item: ScrollItem? = index >= 0 && index < items.count ? items[index] : nil
|
||||
let cell: UIView
|
||||
if #available(iOS 16.0, *), false {
|
||||
let c: UITableViewCell = cellsToReuse.isEmpty ? UITableViewCell() : cellsToReuse.removeLast() as! UITableViewCell
|
||||
if let item {
|
||||
c.contentConfiguration = UIHostingConfiguration { self.content(index, item) }
|
||||
.margins(.all, 0)
|
||||
.minSize(height: 1) // Passing zero will result in system default of 44 points being used
|
||||
}
|
||||
cell = c
|
||||
} else {
|
||||
let c = cellsToReuse.isEmpty ? HostingCell<Content>() : cellsToReuse.removeLast() as! HostingCell<Content>
|
||||
if let item {
|
||||
c.set(content: self.content(index, item), parent: self)
|
||||
}
|
||||
cell = c
|
||||
}
|
||||
cell.isHidden = false
|
||||
cell.backgroundColor = .clear
|
||||
let size = cell.systemLayoutSizeFitting(CGSizeMake(scrollView.bounds.width, CGFloat.greatestFiniteMagnitude))
|
||||
cell.frame.size.width = scrollView.bounds.width
|
||||
cell.frame.size.height = size.height
|
||||
return cell
|
||||
}
|
||||
|
||||
private func updateCell(cell: UIView, _ index: Int, _ items: [ScrollItem]) {
|
||||
let item = items[index]
|
||||
if #available(iOS 16.0, *), false {
|
||||
(cell as! UITableViewCell).contentConfiguration = UIHostingConfiguration { self.content(index, item) }
|
||||
.margins(.all, 0)
|
||||
.minSize(height: 1) // Passing zero will result in system default of 44 points being used
|
||||
} else {
|
||||
if let cell = cell as? HostingCell<Content> {
|
||||
cell.set(content: self.content(index, item), parent: self)
|
||||
} else {
|
||||
fatalError("Unexpected Cell Type for: \(item)")
|
||||
}
|
||||
}
|
||||
let size = cell.systemLayoutSizeFitting(CGSizeMake(scrollView.bounds.width, CGFloat.greatestFiniteMagnitude))
|
||||
cell.frame.size.width = scrollView.bounds.width
|
||||
cell.frame.size.height = size.height
|
||||
cell.setNeedsLayout()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class EndlessScrollView<ScrollItem>: UIScrollView, UIScrollViewDelegate, UIGestureRecognizerDelegate where ScrollItem : Identifiable, ScrollItem: Hashable {
|
||||
|
||||
/// Stores actual state of the scroll view and all elements drawn on the screen
|
||||
let listState: ListState = ListState()
|
||||
|
||||
/// Just some random big number that will probably be enough to scrolling down and up without reaching the end
|
||||
var initialOffset: CGFloat = 100000000
|
||||
|
||||
/// Default item id when no items in the visible items list. Something that will never be in real data
|
||||
fileprivate static var DEFAULT_ITEM_ID: any Hashable { get { Int64.min } }
|
||||
|
||||
/// Storing an offset that was already used for laying down content to be able to see the difference
|
||||
var prevProcessedOffset: CGFloat = 0
|
||||
|
||||
/// When screen is being rotated, it's important to track the view size and adjust scroll offset accordingly because the view doesn't know that the content
|
||||
/// starts from bottom and ends at top, not vice versa as usual
|
||||
var oldScreenHeight: CGFloat = 0
|
||||
|
||||
/// Not 100% correct height of the content since the items loaded lazily and their dimensions are unkown until they are on screen
|
||||
var estimatedContentHeight: ContentHeight = ContentHeight()
|
||||
|
||||
/// Specify here the value that is small enough to NOT see any weird animation when you scroll to items. Minimum expected item size is ok. Scroll speed depends on it too
|
||||
var averageItemHeight: CGFloat = 30
|
||||
|
||||
/// This is used as a multiplier for difference between current index and scrollTo index using [averageItemHeight] as well. Increase it to get faster speed
|
||||
var scrollStepMultiplier: CGFloat = 0.37
|
||||
|
||||
/// Adds content padding to top
|
||||
var insetTop: CGFloat = 100
|
||||
|
||||
/// Adds content padding to bottom
|
||||
var insetBottom: CGFloat = 100
|
||||
|
||||
var scrollToItemIndexDelayed: Int? = nil
|
||||
|
||||
/// The second scroll view that is used only for purpose of displaying scroll bar with made-up content size and scroll offset that is gathered from main scroll view, see [estimatedContentHeight]
|
||||
let scrollBarView: UIScrollView = UIScrollView(frame: .zero)
|
||||
|
||||
/// Stores views that can be used to hold new content so it will be faster to replace something than to create the whole view from scratch
|
||||
var cellsToReuse: [UIView] = []
|
||||
|
||||
/// Enable debug to see hundreds of logs
|
||||
var debug: Bool = false
|
||||
|
||||
var createCell: (Int, [ScrollItem], inout [UIView]) -> UIView? = { _, _, _ in nil }
|
||||
var updateCell: (UIView, Int, [ScrollItem]) -> Void = { cell, _, _ in }
|
||||
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
self.delegate = self
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) { fatalError() }
|
||||
|
||||
class ListState: NSObject {
|
||||
|
||||
/// Will be called on every change of the items array, visible items, and scroll position
|
||||
var onUpdateListener: () -> Void = {}
|
||||
|
||||
/// Items that were used to lay out the screen
|
||||
var items: [ScrollItem] = [] {
|
||||
didSet {
|
||||
onUpdateListener()
|
||||
}
|
||||
}
|
||||
|
||||
/// It is equai to the number of [items]
|
||||
var totalItemsCount: Int {
|
||||
items.count
|
||||
}
|
||||
|
||||
/// The items with their positions and other useful information. Only those that are visible on screen
|
||||
var visibleItems: [EndlessScrollView<ScrollItem>.VisibleItem] = []
|
||||
|
||||
/// Index in [items] of the first item on screen. This is intentiallty not derived from visible items because it's is used as a starting point for laying out the screen
|
||||
var firstVisibleItemIndex: Int = 0
|
||||
|
||||
/// Unique item id of the first visible item on screen
|
||||
var firstVisibleItemId: any Hashable = EndlessScrollView<ScrollItem>.DEFAULT_ITEM_ID
|
||||
|
||||
/// Item offset of the first item on screen. Most of the time it's non-positive but it can be positive as well when a user produce overscroll effect on top/bottom of the scroll view
|
||||
var firstVisibleItemOffset: CGFloat = -100
|
||||
|
||||
/// Index of the last visible item on screen
|
||||
var lastVisibleItemIndex: Int {
|
||||
visibleItems.last?.index ?? 0
|
||||
}
|
||||
|
||||
/// Whether there is a non-animated scroll to item in progress or not
|
||||
var isScrolling: Bool = false
|
||||
/// Whether there is an animated scroll to item in progress or not
|
||||
var isAnimatedScrolling: Bool = false
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
}
|
||||
}
|
||||
|
||||
class VisibleItem {
|
||||
let index: Int
|
||||
let item: ScrollItem
|
||||
let view: UIView
|
||||
var offset: CGFloat
|
||||
|
||||
init(index: Int, item: ScrollItem, view: UIView, offset: CGFloat) {
|
||||
self.index = index
|
||||
self.item = item
|
||||
self.view = view
|
||||
self.offset = offset
|
||||
}
|
||||
}
|
||||
|
||||
class ContentHeight {
|
||||
/// After that you should see overscroll effect. When scroll positon is far from
|
||||
/// top/bottom items, these values are estimated based on items count multiplied by averageItemHeight or real item height (from visible items). Example:
|
||||
/// [ 10, 9, 8, 7, (6, 5, 4, 3), 2, 1, 0] - 6, 5, 4, 3 are visible and have know heights but others have unknown height and for them averageItemHeight will be used to calculate the whole content height
|
||||
var topOffsetY: CGFloat = 0
|
||||
var bottomOffsetY: CGFloat = 0
|
||||
|
||||
var virtualScrollOffsetY: CGFloat = 0
|
||||
|
||||
/// How much distance were overscolled on top which often means to show sticky scrolling that should scroll back to real position after a users finishes dragging the scrollView
|
||||
var overscrolledTop: CGFloat = 0
|
||||
|
||||
/// Adds content padding to bottom and top
|
||||
var inset: CGFloat = 100
|
||||
|
||||
/// Estimated height of the contents of scroll view
|
||||
var height: CGFloat {
|
||||
get { bottomOffsetY - topOffsetY }
|
||||
}
|
||||
|
||||
/// Estimated height of the contents of scroll view + distance of overscrolled effect. It's only updated when number of item changes to prevent jumping of scroll bar
|
||||
var virtualOverscrolledHeight: CGFloat {
|
||||
get {
|
||||
bottomOffsetY - topOffsetY + overscrolledTop - inset * 2
|
||||
}
|
||||
}
|
||||
|
||||
func update(
|
||||
_ contentOffset: CGPoint,
|
||||
_ listState: ListState,
|
||||
_ averageItemHeight: CGFloat,
|
||||
_ updateStaleHeight: Bool
|
||||
) {
|
||||
let lastVisible = listState.visibleItems.last
|
||||
let firstVisible = listState.visibleItems.first
|
||||
guard let last = lastVisible, let first = firstVisible else {
|
||||
topOffsetY = contentOffset.y
|
||||
bottomOffsetY = contentOffset.y
|
||||
virtualScrollOffsetY = 0
|
||||
overscrolledTop = 0
|
||||
return
|
||||
}
|
||||
topOffsetY = last.view.frame.origin.y - CGFloat(listState.totalItemsCount - last.index - 1) * averageItemHeight - self.inset
|
||||
bottomOffsetY = first.view.frame.origin.y + first.view.bounds.height + CGFloat(first.index) * averageItemHeight + self.inset
|
||||
virtualScrollOffsetY = contentOffset.y - topOffsetY
|
||||
overscrolledTop = max(0, last.index == listState.totalItemsCount - 1 ? last.view.frame.origin.y - contentOffset.y : 0)
|
||||
}
|
||||
}
|
||||
|
||||
var topY: CGFloat {
|
||||
get { contentOffset.y }
|
||||
}
|
||||
|
||||
var bottomY: CGFloat {
|
||||
get { contentOffset.y + bounds.height }
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
if contentSize.height == 0 {
|
||||
setup()
|
||||
}
|
||||
let newScreenHeight = bounds.height
|
||||
if newScreenHeight != oldScreenHeight && oldScreenHeight != 0 {
|
||||
contentOffset.y += oldScreenHeight - newScreenHeight
|
||||
scrollBarView.frame = CGRectMake(frame.width - 10, self.insetTop, 10, frame.height - self.insetTop - self.insetBottom)
|
||||
}
|
||||
oldScreenHeight = newScreenHeight
|
||||
adaptItems(listState.items, false)
|
||||
if let index = scrollToItemIndexDelayed {
|
||||
scrollToItem(index)
|
||||
scrollToItemIndexDelayed = nil
|
||||
}
|
||||
}
|
||||
|
||||
private func setup() {
|
||||
contentSize = CGSizeMake(frame.size.width, initialOffset * 2)
|
||||
prevProcessedOffset = initialOffset
|
||||
contentOffset = CGPointMake(0, initialOffset)
|
||||
|
||||
showsVerticalScrollIndicator = false
|
||||
scrollBarView.showsHorizontalScrollIndicator = false
|
||||
panGestureRecognizer.delegate = self
|
||||
addGestureRecognizer(scrollBarView.panGestureRecognizer)
|
||||
superview!.addSubview(scrollBarView)
|
||||
}
|
||||
|
||||
func updateItems(_ items: [ScrollItem], _ forceReloadVisible: Bool = false) {
|
||||
if !Thread.isMainThread {
|
||||
fatalError("Use main thread to update items")
|
||||
}
|
||||
if bounds.height == 0 {
|
||||
self.listState.items = items
|
||||
// this function requires to have valid bounds and it will be called again once it has them
|
||||
return
|
||||
}
|
||||
adaptItems(items, forceReloadVisible)
|
||||
snapToContent(animated: false)
|
||||
}
|
||||
|
||||
/// [forceReloadVisible]: reloads every item that was visible regardless of hashValue changes
|
||||
private func adaptItems(_ items: [ScrollItem], _ forceReloadVisible: Bool, overridenOffset: CGFloat? = nil) {
|
||||
let start = Date.now
|
||||
// special case when everything was removed
|
||||
if items.isEmpty {
|
||||
listState.visibleItems.forEach { item in item.view.removeFromSuperview() }
|
||||
listState.visibleItems = []
|
||||
listState.firstVisibleItemId = EndlessScrollView<ScrollItem>.DEFAULT_ITEM_ID
|
||||
listState.firstVisibleItemIndex = 0
|
||||
listState.firstVisibleItemOffset = -insetTop
|
||||
|
||||
estimatedContentHeight.update(contentOffset, listState, averageItemHeight, true)
|
||||
scrollBarView.contentSize = .zero
|
||||
scrollBarView.contentOffset = .zero
|
||||
|
||||
prevProcessedOffset = contentOffset.y
|
||||
// this check is just to prevent didSet listener from firing on the same empty array, no use for this
|
||||
if !self.listState.items.isEmpty {
|
||||
self.listState.items = items
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
let contentOffsetY = overridenOffset ?? contentOffset.y
|
||||
|
||||
var oldVisible = listState.visibleItems
|
||||
var newVisible: [VisibleItem] = []
|
||||
let offsetsDiff = contentOffsetY - prevProcessedOffset
|
||||
|
||||
var shouldBeFirstVisible = items.firstIndex(where: { item in item.id == listState.firstVisibleItemId as! ScrollItem.ID }) ?? 0
|
||||
|
||||
var wasFirstVisibleItemOffset = listState.firstVisibleItemOffset
|
||||
var alreadyChangedIndexWhileScrolling = false
|
||||
var allowOneMore = false
|
||||
var nextOffsetY: CGFloat = 0
|
||||
var i = shouldBeFirstVisible
|
||||
// building list of visible items starting from the first one that should be visible
|
||||
while i >= 0 && i < items.count {
|
||||
let item = items[i]
|
||||
let visibleIndex = oldVisible.firstIndex(where: { vis in vis.item.id == item.id })
|
||||
let visible: VisibleItem?
|
||||
if let visibleIndex {
|
||||
let v = oldVisible.remove(at: visibleIndex)
|
||||
if forceReloadVisible || v.view.bounds.width != bounds.width || v.item.hashValue != item.hashValue {
|
||||
updateCell(v.view, i, items)
|
||||
}
|
||||
visible = v
|
||||
} else {
|
||||
visible = nil
|
||||
}
|
||||
if shouldBeFirstVisible == i {
|
||||
if let vis = visible {
|
||||
|
||||
if // there is auto scroll in progress and the first item has a higher offset than bottom part
|
||||
// of the screen. In order to make scrolling down & up equal in time, we treat this as a sign to
|
||||
// re-make the first visible item
|
||||
(listState.isAnimatedScrolling && vis.view.frame.origin.y + vis.view.bounds.height < contentOffsetY + bounds.height) ||
|
||||
// the fist visible item previously is hidden now, remove it and move on
|
||||
!isVisible(vis.view) {
|
||||
let newIndex: Int
|
||||
if listState.isAnimatedScrolling {
|
||||
// skip many items to make the scrolling take less time
|
||||
var indexDiff = !alreadyChangedIndexWhileScrolling ? Int(ceil(abs(offsetsDiff / averageItemHeight))) : 0
|
||||
// if index was already changed, no need to change it again. Otherwise, the scroll will overscoll and return back animated. Because it means the whole screen was scrolled
|
||||
alreadyChangedIndexWhileScrolling = true
|
||||
|
||||
indexDiff = offsetsDiff <= 0 ? indexDiff : -indexDiff
|
||||
newIndex = max(0, min(items.count - 1, i + indexDiff))
|
||||
// offset for the first visible item can now be 0 because the previous first visible item doesn't exist anymore
|
||||
wasFirstVisibleItemOffset = 0
|
||||
} else {
|
||||
// don't skip multiple items if it's manual scrolling gesture
|
||||
newIndex = i + (offsetsDiff <= 0 ? 1 : -1)
|
||||
}
|
||||
shouldBeFirstVisible = newIndex
|
||||
i = newIndex
|
||||
|
||||
cellsToReuse.append(vis.view)
|
||||
hideAndRemoveFromSuperviewIfNeeded(vis.view)
|
||||
continue
|
||||
}
|
||||
}
|
||||
let vis: VisibleItem
|
||||
if let visible {
|
||||
vis = VisibleItem(index: i, item: item, view: visible.view, offset: offsetToBottom(visible.view))
|
||||
} else {
|
||||
let cell = createCell(i, items, &cellsToReuse)!
|
||||
cell.frame.origin.y = bottomY + wasFirstVisibleItemOffset - cell.frame.height
|
||||
vis = VisibleItem(index: i, item: item, view: cell, offset: offsetToBottom(cell))
|
||||
}
|
||||
if vis.view.superview == nil {
|
||||
addSubview(vis.view)
|
||||
}
|
||||
newVisible.append(vis)
|
||||
nextOffsetY = vis.view.frame.origin.y
|
||||
} else {
|
||||
let vis: VisibleItem
|
||||
if let visible {
|
||||
vis = VisibleItem(index: i, item: item, view: visible.view, offset: offsetToBottom(visible.view))
|
||||
nextOffsetY -= vis.view.frame.height
|
||||
vis.view.frame.origin.y = nextOffsetY
|
||||
} else {
|
||||
let cell = createCell(i, items, &cellsToReuse)!
|
||||
nextOffsetY -= cell.frame.height
|
||||
cell.frame.origin.y = nextOffsetY
|
||||
vis = VisibleItem(index: i, item: item, view: cell, offset: offsetToBottom(cell))
|
||||
}
|
||||
if vis.view.superview == nil {
|
||||
addSubview(vis.view)
|
||||
}
|
||||
newVisible.append(vis)
|
||||
}
|
||||
if abs(nextOffsetY) < contentOffsetY && !allowOneMore {
|
||||
break
|
||||
} else if abs(nextOffsetY) < contentOffsetY {
|
||||
allowOneMore = false
|
||||
}
|
||||
i += 1
|
||||
}
|
||||
if let firstVisible = newVisible.first, firstVisible.view.frame.origin.y + firstVisible.view.frame.height < contentOffsetY + bounds.height, firstVisible.index > 0 {
|
||||
var offset: CGFloat = firstVisible.view.frame.origin.y + firstVisible.view.frame.height
|
||||
let index = firstVisible.index
|
||||
for i in stride(from: index - 1, through: 0, by: -1) {
|
||||
let item = items[i]
|
||||
let visibleIndex = oldVisible.firstIndex(where: { vis in vis.item.id == item.id })
|
||||
let vis: VisibleItem
|
||||
if let visibleIndex {
|
||||
let visible = oldVisible.remove(at: visibleIndex)
|
||||
visible.view.frame.origin.y = offset
|
||||
vis = VisibleItem(index: i, item: item, view: visible.view, offset: offsetToBottom(visible.view))
|
||||
} else {
|
||||
let cell = createCell(i, items, &cellsToReuse)!
|
||||
cell.frame.origin.y = offset
|
||||
vis = VisibleItem(index: i, item: item, view: cell, offset: offsetToBottom(cell))
|
||||
}
|
||||
if vis.view.superview == nil {
|
||||
addSubview(vis.view)
|
||||
}
|
||||
offset += vis.view.frame.height
|
||||
newVisible.insert(vis, at: 0)
|
||||
if offset >= contentOffsetY + bounds.height {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// removing already unneeded visible items
|
||||
oldVisible.forEach { vis in
|
||||
cellsToReuse.append(vis.view)
|
||||
hideAndRemoveFromSuperviewIfNeeded(vis.view)
|
||||
}
|
||||
let itemsCountChanged = listState.items.count != items.count
|
||||
prevProcessedOffset = contentOffsetY
|
||||
|
||||
listState.visibleItems = newVisible
|
||||
listState.items = items
|
||||
|
||||
listState.firstVisibleItemId = listState.visibleItems.first?.item.id ?? EndlessScrollView<ScrollItem>.DEFAULT_ITEM_ID
|
||||
listState.firstVisibleItemIndex = listState.visibleItems.first?.index ?? 0
|
||||
listState.firstVisibleItemOffset = listState.visibleItems.first?.offset ?? -insetTop
|
||||
|
||||
estimatedContentHeight.update(contentOffset, listState, averageItemHeight, itemsCountChanged)
|
||||
scrollBarView.contentSize = CGSizeMake(bounds.width, estimatedContentHeight.virtualOverscrolledHeight)
|
||||
scrollBarView.contentOffset = CGPointMake(0, estimatedContentHeight.virtualScrollOffsetY)
|
||||
scrollBarView.isHidden = listState.visibleItems.count == listState.items.count && (listState.visibleItems.isEmpty || -listState.firstVisibleItemOffset + (listState.visibleItems.last?.offset ?? 0) + insetTop < bounds.height)
|
||||
|
||||
if debug {
|
||||
println("time spent \((-start.timeIntervalSinceNow).description.prefix(5).replacingOccurrences(of: "0.000", with: "<0").replacingOccurrences(of: "0.", with: ""))")
|
||||
}
|
||||
}
|
||||
|
||||
func setScrollPosition(_ index: Int, _ id: Int64, _ offset: CGFloat = 0) {
|
||||
listState.firstVisibleItemIndex = index
|
||||
listState.firstVisibleItemId = id
|
||||
listState.firstVisibleItemOffset = offset == 0 ? -bounds.height + insetTop + insetBottom : offset
|
||||
}
|
||||
|
||||
func scrollToItem(_ index: Int, top: Bool = true) {
|
||||
if index >= listState.items.count || listState.isScrolling || listState.isAnimatedScrolling {
|
||||
return
|
||||
}
|
||||
if bounds.height == 0 || contentSize.height == 0 {
|
||||
scrollToItemIndexDelayed = index
|
||||
return
|
||||
}
|
||||
listState.isScrolling = true
|
||||
defer {
|
||||
listState.isScrolling = false
|
||||
}
|
||||
|
||||
// just a faster way to set top item as requested index
|
||||
listState.firstVisibleItemIndex = index
|
||||
listState.firstVisibleItemId = listState.items[index].id
|
||||
listState.firstVisibleItemOffset = -bounds.height + insetTop + insetBottom
|
||||
scrollBarView.flashScrollIndicators()
|
||||
adaptItems(listState.items, false)
|
||||
|
||||
var adjustedOffset = self.contentOffset.y
|
||||
var i = 0
|
||||
|
||||
var upPrev = index > listState.firstVisibleItemIndex
|
||||
//let firstOrLastIndex = upPrev ? listState.visibleItems.last?.index ?? 0 : listState.firstVisibleItemIndex
|
||||
//let step: CGFloat = max(0.1, CGFloat(abs(index - firstOrLastIndex)) * scrollStepMultiplier)
|
||||
|
||||
var stepSlowdownMultiplier: CGFloat = 1
|
||||
while i < 200 {
|
||||
let up = index > listState.firstVisibleItemIndex
|
||||
if upPrev != up {
|
||||
stepSlowdownMultiplier = stepSlowdownMultiplier * 0.5
|
||||
upPrev = up
|
||||
}
|
||||
|
||||
// these two lines makes scrolling's finish non-linear and NOT overscroll visually when reach target index
|
||||
let firstOrLastIndex = up ? listState.visibleItems.last?.index ?? 0 : listState.firstVisibleItemIndex
|
||||
let step: CGFloat = max(0.1, CGFloat(abs(index - firstOrLastIndex)) * scrollStepMultiplier) * stepSlowdownMultiplier
|
||||
|
||||
let offsetToScroll = (up ? -averageItemHeight : averageItemHeight) * step
|
||||
adjustedOffset += offsetToScroll
|
||||
if let item = listState.visibleItems.first(where: { $0.index == index }) {
|
||||
let y = if top {
|
||||
min(estimatedContentHeight.bottomOffsetY - bounds.height, item.view.frame.origin.y - insetTop)
|
||||
} else {
|
||||
max(estimatedContentHeight.topOffsetY - insetTop - insetBottom, item.view.frame.origin.y + item.view.bounds.height - bounds.height + insetBottom)
|
||||
}
|
||||
setContentOffset(CGPointMake(contentOffset.x, y), animated: false)
|
||||
scrollBarView.flashScrollIndicators()
|
||||
break
|
||||
}
|
||||
contentOffset = CGPointMake(contentOffset.x, adjustedOffset)
|
||||
adaptItems(listState.items, false)
|
||||
snapToContent(animated: false)
|
||||
i += 1
|
||||
}
|
||||
adaptItems(listState.items, false)
|
||||
snapToContent(animated: false)
|
||||
estimatedContentHeight.update(contentOffset, listState, averageItemHeight, true)
|
||||
}
|
||||
|
||||
func scrollToItemAnimated(_ index: Int, top: Bool = true) async {
|
||||
if index >= listState.items.count || listState.isScrolling || listState.isAnimatedScrolling {
|
||||
return
|
||||
}
|
||||
listState.isAnimatedScrolling = true
|
||||
defer {
|
||||
listState.isAnimatedScrolling = false
|
||||
}
|
||||
var adjustedOffset = self.contentOffset.y
|
||||
var i = 0
|
||||
|
||||
var upPrev = index > listState.firstVisibleItemIndex
|
||||
//let firstOrLastIndex = upPrev ? listState.visibleItems.last?.index ?? 0 : listState.firstVisibleItemIndex
|
||||
//let step: CGFloat = max(0.1, CGFloat(abs(index - firstOrLastIndex)) * scrollStepMultiplier)
|
||||
|
||||
var stepSlowdownMultiplier: CGFloat = 1
|
||||
while i < 200 {
|
||||
let up = index > listState.firstVisibleItemIndex
|
||||
if upPrev != up {
|
||||
stepSlowdownMultiplier = stepSlowdownMultiplier * 0.5
|
||||
upPrev = up
|
||||
}
|
||||
|
||||
// these two lines makes scrolling's finish non-linear and NOT overscroll visually when reach target index
|
||||
let firstOrLastIndex = up ? listState.visibleItems.last?.index ?? 0 : listState.firstVisibleItemIndex
|
||||
let step: CGFloat = max(0.1, CGFloat(abs(index - firstOrLastIndex)) * scrollStepMultiplier) * stepSlowdownMultiplier
|
||||
|
||||
//println("Scrolling step \(step) \(stepSlowdownMultiplier) index \(index) \(firstOrLastIndex) \(index - firstOrLastIndex) \(adjustedOffset), up \(up), i \(i)")
|
||||
|
||||
let offsetToScroll = (up ? -averageItemHeight : averageItemHeight) * step
|
||||
adjustedOffset += offsetToScroll
|
||||
if let item = listState.visibleItems.first(where: { $0.index == index }) {
|
||||
let y = if top {
|
||||
min(estimatedContentHeight.bottomOffsetY - bounds.height, item.view.frame.origin.y - insetTop)
|
||||
} else {
|
||||
max(estimatedContentHeight.topOffsetY - insetTop - insetBottom, item.view.frame.origin.y + item.view.bounds.height - bounds.height + insetBottom)
|
||||
}
|
||||
setContentOffset(CGPointMake(contentOffset.x, y), animated: true)
|
||||
scrollBarView.flashScrollIndicators()
|
||||
break
|
||||
}
|
||||
contentOffset = CGPointMake(contentOffset.x, adjustedOffset)
|
||||
|
||||
// skipping unneded relayout if this offset is already processed
|
||||
if prevProcessedOffset - contentOffset.y != 0 {
|
||||
adaptItems(listState.items, false)
|
||||
snapToContent(animated: false)
|
||||
}
|
||||
// let UI time to update to see the animated position change
|
||||
await MainActor.run {}
|
||||
|
||||
i += 1
|
||||
}
|
||||
estimatedContentHeight.update(contentOffset, listState, averageItemHeight, true)
|
||||
}
|
||||
|
||||
func scrollToBottom() {
|
||||
scrollToItem(0, top: false)
|
||||
}
|
||||
|
||||
func scrollToBottomAnimated() {
|
||||
Task {
|
||||
await scrollToItemAnimated(0, top: false)
|
||||
}
|
||||
}
|
||||
|
||||
func scroll(by: CGFloat, animated: Bool = true) {
|
||||
setContentOffset(CGPointMake(contentOffset.x, contentOffset.y + by), animated: animated)
|
||||
}
|
||||
|
||||
func scrollViewShouldScrollToTop(_ scrollView: UIScrollView) -> Bool {
|
||||
if !listState.items.isEmpty {
|
||||
scrollToBottomAnimated()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private func snapToContent(animated: Bool) {
|
||||
let topBlankSpace = estimatedContentHeight.height < bounds.height ? bounds.height - estimatedContentHeight.height : 0
|
||||
if topY < estimatedContentHeight.topOffsetY - topBlankSpace {
|
||||
setContentOffset(CGPointMake(0, estimatedContentHeight.topOffsetY - topBlankSpace), animated: animated)
|
||||
} else if bottomY > estimatedContentHeight.bottomOffsetY {
|
||||
setContentOffset(CGPointMake(0, estimatedContentHeight.bottomOffsetY - bounds.height), animated: animated)
|
||||
}
|
||||
}
|
||||
|
||||
func offsetToBottom(_ view: UIView) -> CGFloat {
|
||||
bottomY - (view.frame.origin.y + view.frame.height)
|
||||
}
|
||||
|
||||
/// If I try to .removeFromSuperview() right when I need to remove the view, it is possible to crash the app when the view was hidden in result of
|
||||
/// pressing Hide in menu on top of the revealed item within the group. So at that point the item should still be attached to the view
|
||||
func hideAndRemoveFromSuperviewIfNeeded(_ view: UIView) {
|
||||
if view.isHidden {
|
||||
// already passed this function
|
||||
return
|
||||
}
|
||||
(view as? ReusableView)?.prepareForReuse()
|
||||
view.isHidden = true
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
|
||||
if view.isHidden { view.removeFromSuperview() }
|
||||
}
|
||||
}
|
||||
|
||||
/// Synchronizing both scrollViews
|
||||
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
|
||||
true
|
||||
}
|
||||
|
||||
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
|
||||
if !decelerate {
|
||||
snapToContent(animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
override var contentOffset: CGPoint {
|
||||
get { super.contentOffset }
|
||||
set {
|
||||
var newOffset = newValue
|
||||
let topBlankSpace = estimatedContentHeight.height < bounds.height ? bounds.height - estimatedContentHeight.height : 0
|
||||
if contentOffset.y > 0 && newOffset.y < estimatedContentHeight.topOffsetY - topBlankSpace && contentOffset.y > newOffset.y {
|
||||
if !isDecelerating {
|
||||
newOffset.y = min(contentOffset.y, newOffset.y + abs(newOffset.y - estimatedContentHeight.topOffsetY + topBlankSpace) / 1.8)
|
||||
} else {
|
||||
DispatchQueue.main.async {
|
||||
self.setContentOffset(newValue, animated: false)
|
||||
self.snapToContent(animated: true)
|
||||
}
|
||||
}
|
||||
} else if contentOffset.y > 0 && newOffset.y + bounds.height > estimatedContentHeight.bottomOffsetY && contentOffset.y < newOffset.y {
|
||||
if !isDecelerating {
|
||||
newOffset.y = max(contentOffset.y, newOffset.y - abs(newOffset.y + bounds.height - estimatedContentHeight.bottomOffsetY) / 1.8)
|
||||
} else {
|
||||
DispatchQueue.main.async {
|
||||
self.setContentOffset(newValue, animated: false)
|
||||
self.snapToContent(animated: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
super.contentOffset = newOffset
|
||||
}
|
||||
}
|
||||
|
||||
private func stopScrolling() {
|
||||
let offsetYToStopAt = if abs(contentOffset.y - estimatedContentHeight.topOffsetY) < abs(bottomY - estimatedContentHeight.bottomOffsetY) {
|
||||
estimatedContentHeight.topOffsetY
|
||||
} else {
|
||||
estimatedContentHeight.bottomOffsetY - bounds.height
|
||||
}
|
||||
setContentOffset(CGPointMake(contentOffset.x, offsetYToStopAt), animated: false)
|
||||
}
|
||||
|
||||
func isVisible(_ view: UIView) -> Bool {
|
||||
if view.superview == nil {
|
||||
return false
|
||||
}
|
||||
return view.frame.intersects(CGRectMake(0, contentOffset.y, bounds.width, bounds.height))
|
||||
}
|
||||
}
|
||||
|
||||
private func println(_ text: String) {
|
||||
print("\(Date.now.timeIntervalSince1970): \(text)")
|
||||
}
|
|
@ -681,12 +681,14 @@ struct GroupChatInfoView: View {
|
|||
primaryButton: .destructive(Text("Remove")) {
|
||||
Task {
|
||||
do {
|
||||
let updatedMember = try await apiRemoveMember(groupInfo.groupId, mem.groupMemberId)
|
||||
let updatedMembers = try await apiRemoveMembers(groupInfo.groupId, [mem.groupMemberId])
|
||||
await MainActor.run {
|
||||
_ = chatModel.upsertGroupMember(groupInfo, updatedMember)
|
||||
updatedMembers.forEach { updatedMember in
|
||||
_ = chatModel.upsertGroupMember(groupInfo, updatedMember)
|
||||
}
|
||||
}
|
||||
} catch let error {
|
||||
logger.error("apiRemoveMember error: \(responseError(error))")
|
||||
logger.error("apiRemoveMembers error: \(responseError(error))")
|
||||
let a = getErrorAlert(error, "Error removing member")
|
||||
alert = .error(title: a.title, error: a.message)
|
||||
}
|
||||
|
|
|
@ -366,14 +366,8 @@ struct GroupMemberInfoView: View {
|
|||
func newDirectChatButton(_ contactId: Int64, width: CGFloat) -> some View {
|
||||
InfoViewButton(image: "message.fill", title: "message", width: width) {
|
||||
Task {
|
||||
do {
|
||||
let chat = try await apiGetChat(type: .direct, id: contactId)
|
||||
chatModel.addChat(chat)
|
||||
ItemsModel.shared.loadOpenChat(chat.id) {
|
||||
dismissAllSheets(animated: true)
|
||||
}
|
||||
} catch let error {
|
||||
logger.error("openDirectChatButton apiGetChat error: \(responseError(error))")
|
||||
ItemsModel.shared.loadOpenChat("@\(contactId)") {
|
||||
dismissAllSheets(animated: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -616,13 +610,15 @@ struct GroupMemberInfoView: View {
|
|||
primaryButton: .destructive(Text("Remove")) {
|
||||
Task {
|
||||
do {
|
||||
let updatedMember = try await apiRemoveMember(groupInfo.groupId, mem.groupMemberId)
|
||||
let updatedMembers = try await apiRemoveMembers(groupInfo.groupId, [mem.groupMemberId])
|
||||
await MainActor.run {
|
||||
_ = chatModel.upsertGroupMember(groupInfo, updatedMember)
|
||||
updatedMembers.forEach { updatedMember in
|
||||
_ = chatModel.upsertGroupMember(groupInfo, updatedMember)
|
||||
}
|
||||
dismiss()
|
||||
}
|
||||
} catch let error {
|
||||
logger.error("apiRemoveMember error: \(responseError(error))")
|
||||
logger.error("apiRemoveMembers error: \(responseError(error))")
|
||||
let a = getErrorAlert(error, "Error removing member")
|
||||
alert = .error(title: a.title, error: a.message)
|
||||
}
|
||||
|
@ -647,14 +643,16 @@ struct GroupMemberInfoView: View {
|
|||
primaryButton: .default(Text("Change")) {
|
||||
Task {
|
||||
do {
|
||||
let updatedMember = try await apiMemberRole(groupInfo.groupId, mem.groupMemberId, newRole)
|
||||
let updatedMembers = try await apiMembersRole(groupInfo.groupId, [mem.groupMemberId], newRole)
|
||||
await MainActor.run {
|
||||
_ = chatModel.upsertGroupMember(groupInfo, updatedMember)
|
||||
updatedMembers.forEach { updatedMember in
|
||||
_ = chatModel.upsertGroupMember(groupInfo, updatedMember)
|
||||
}
|
||||
}
|
||||
|
||||
} catch let error {
|
||||
newRole = mem.memberRole
|
||||
logger.error("apiMemberRole error: \(responseError(error))")
|
||||
logger.error("apiMembersRole error: \(responseError(error))")
|
||||
let a = getErrorAlert(error, "Error changing role")
|
||||
alert = .error(title: a.title, error: a.message)
|
||||
}
|
||||
|
@ -806,12 +804,14 @@ func unblockForAllAlert(_ gInfo: GroupInfo, _ mem: GroupMember) -> Alert {
|
|||
func blockMemberForAll(_ gInfo: GroupInfo, _ member: GroupMember, _ blocked: Bool) {
|
||||
Task {
|
||||
do {
|
||||
let updatedMember = try await apiBlockMemberForAll(gInfo.groupId, member.groupMemberId, blocked)
|
||||
let updatedMembers = try await apiBlockMembersForAll(gInfo.groupId, [member.groupMemberId], blocked)
|
||||
await MainActor.run {
|
||||
_ = ChatModel.shared.upsertGroupMember(gInfo, updatedMember)
|
||||
updatedMembers.forEach { updatedMember in
|
||||
_ = ChatModel.shared.upsertGroupMember(gInfo, updatedMember)
|
||||
}
|
||||
}
|
||||
} catch let error {
|
||||
logger.error("apiBlockMemberForAll error: \(responseError(error))")
|
||||
logger.error("apiBlockMembersForAll error: \(responseError(error))")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,79 +27,78 @@ struct GroupMentionsView: View {
|
|||
@State private var mentionName: String = ""
|
||||
@State private var mentionRange: NSRange?
|
||||
@State private var mentionMemberId: String?
|
||||
@State private var sortedMembers: [GMember] = []
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
ZStack(alignment: .bottom) {
|
||||
if isVisible {
|
||||
Color.white.opacity(0.01)
|
||||
.edgesIgnoringSafeArea(.all)
|
||||
.onTapGesture {
|
||||
isVisible = false
|
||||
}
|
||||
}
|
||||
VStack {
|
||||
Spacer()
|
||||
VStack {
|
||||
Spacer()
|
||||
VStack {
|
||||
let filtered = filteredMembers()
|
||||
if filtered.count > 0 {
|
||||
Color.white.opacity(0.01)
|
||||
.edgesIgnoringSafeArea(.all)
|
||||
.onTapGesture {
|
||||
isVisible = false
|
||||
}
|
||||
VStack(spacing: 0) {
|
||||
Spacer()
|
||||
Divider()
|
||||
let list = List {
|
||||
ForEach(filteredMembers, id: \.wrapped.groupMemberId) { member in
|
||||
let mentioned = mentionMemberId == member.wrapped.memberId
|
||||
let disabled = composeState.mentions.count >= MAX_NUMBER_OF_MENTIONS && !mentioned
|
||||
memberRowView(member.wrapped, mentioned)
|
||||
.contentShape(Rectangle())
|
||||
.disabled(disabled)
|
||||
.opacity(disabled ? 0.6 : 1)
|
||||
.onTapGesture {
|
||||
memberSelected(member)
|
||||
let scroll = ScrollView {
|
||||
LazyVStack(spacing: 0) {
|
||||
ForEach(Array(filtered.enumerated()), id: \.element.wrapped.groupMemberId) { index, member in
|
||||
let mentioned = mentionMemberId == member.wrapped.memberId
|
||||
let disabled = composeState.mentions.count >= MAX_NUMBER_OF_MENTIONS && !mentioned
|
||||
ZStack(alignment: .bottom) {
|
||||
memberRowView(member.wrapped, mentioned)
|
||||
.contentShape(Rectangle())
|
||||
.disabled(disabled)
|
||||
.opacity(disabled ? 0.6 : 1)
|
||||
.onTapGesture {
|
||||
memberSelected(member)
|
||||
}
|
||||
.padding(.horizontal)
|
||||
.frame(height: MEMBER_ROW_SIZE)
|
||||
|
||||
Divider()
|
||||
.padding(.leading)
|
||||
.padding(.leading, 48)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.listStyle(PlainListStyle())
|
||||
.frame(height: MEMBER_ROW_SIZE * min(MAX_VISIBLE_MEMBER_ROWS, CGFloat(filteredMembers.count)))
|
||||
|
||||
.frame(maxHeight: MEMBER_ROW_SIZE * min(MAX_VISIBLE_MEMBER_ROWS, CGFloat(filtered.count)))
|
||||
.background(Color(UIColor.systemBackground))
|
||||
|
||||
if #available(iOS 16.0, *) {
|
||||
list.scrollDismissesKeyboard(.never)
|
||||
scroll.scrollDismissesKeyboard(.never)
|
||||
} else {
|
||||
list
|
||||
scroll
|
||||
}
|
||||
}
|
||||
.background(Color(UIColor.systemBackground))
|
||||
}
|
||||
.frame(maxWidth: .infinity, maxHeight: MEMBER_ROW_SIZE * MAX_VISIBLE_MEMBER_ROWS)
|
||||
}
|
||||
.offset(y: isVisible ? 0 : 300)
|
||||
.animation(.spring(), value: isVisible)
|
||||
.onChange(of: composeState.parsedMessage) { parsedMsg in
|
||||
currentMessage = composeState.message
|
||||
messageChanged(currentMessage, parsedMsg, selectedRange)
|
||||
}
|
||||
.onChange(of: selectedRange) { r in
|
||||
// This condition is needed to prevent messageChanged called twice,
|
||||
// because composeState.formattedText triggers later when message changes.
|
||||
// The condition is only true if position changed without text change
|
||||
if currentMessage == composeState.message {
|
||||
messageChanged(currentMessage, composeState.parsedMessage, r)
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
currentMessage = composeState.message
|
||||
}
|
||||
.onChange(of: composeState.parsedMessage) { parsedMsg in
|
||||
currentMessage = composeState.message
|
||||
messageChanged(currentMessage, parsedMsg, selectedRange)
|
||||
}
|
||||
.onChange(of: selectedRange) { r in
|
||||
// This condition is needed to prevent messageChanged called twice,
|
||||
// because composeState.formattedText triggers later when message changes.
|
||||
// The condition is only true if position changed without text change
|
||||
if currentMessage == composeState.message {
|
||||
messageChanged(currentMessage, composeState.parsedMessage, r)
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
currentMessage = composeState.message
|
||||
}
|
||||
}
|
||||
|
||||
private var filteredMembers: [GMember] {
|
||||
let members = m.groupMembers
|
||||
.filter { m in
|
||||
let status = m.wrapped.memberStatus
|
||||
return status != .memLeft && status != .memRemoved && status != .memInvited
|
||||
}
|
||||
.sorted { $0.wrapped.memberRole > $1.wrapped.memberRole }
|
||||
private func filteredMembers() -> [GMember] {
|
||||
let s = mentionName.lowercased()
|
||||
return s.isEmpty
|
||||
? members
|
||||
: members.filter { $0.wrapped.localAliasAndFullName.localizedLowercase.contains(s) }
|
||||
? sortedMembers
|
||||
: sortedMembers.filter { $0.wrapped.localAliasAndFullName.localizedLowercase.contains(s) }
|
||||
}
|
||||
|
||||
private func messageChanged(_ msg: String, _ parsedMsg: [FormattedText], _ range: NSRange) {
|
||||
|
@ -112,7 +111,10 @@ struct GroupMentionsView: View {
|
|||
mentionRange = r
|
||||
mentionMemberId = composeState.mentions[name]?.memberId
|
||||
if !m.membersLoaded {
|
||||
Task { await m.loadGroupMembers(groupInfo) }
|
||||
Task {
|
||||
await m.loadGroupMembers(groupInfo)
|
||||
sortMembers()
|
||||
}
|
||||
}
|
||||
return
|
||||
case .none: () //
|
||||
|
@ -124,7 +126,10 @@ struct GroupMentionsView: View {
|
|||
mentionName = ""
|
||||
mentionRange = atRange
|
||||
mentionMemberId = nil
|
||||
Task { await m.loadGroupMembers(groupInfo) }
|
||||
Task {
|
||||
await m.loadGroupMembers(groupInfo)
|
||||
sortMembers()
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -134,6 +139,14 @@ struct GroupMentionsView: View {
|
|||
closeMemberList()
|
||||
}
|
||||
|
||||
private func sortMembers() {
|
||||
sortedMembers = m.groupMembers.filter({ m in
|
||||
let status = m.wrapped.memberStatus
|
||||
return status != .memLeft && status != .memRemoved && status != .memInvited
|
||||
})
|
||||
.sorted { $0.wrapped.memberRole > $1.wrapped.memberRole }
|
||||
}
|
||||
|
||||
private func removeUnusedMentions(_ parsedMsg: [FormattedText]) {
|
||||
let usedMentions: Set<String> = Set(parsedMsg.compactMap { ft in
|
||||
if case let .mention(name) = ft.format { name } else { nil }
|
||||
|
|
|
@ -37,6 +37,7 @@ struct GroupPreferencesView: View {
|
|||
featureSection(.voice, $preferences.voice.enable, $preferences.voice.role)
|
||||
featureSection(.files, $preferences.files.enable, $preferences.files.role)
|
||||
featureSection(.simplexLinks, $preferences.simplexLinks.enable, $preferences.simplexLinks.role)
|
||||
featureSection(.reports, $preferences.reports.enable)
|
||||
featureSection(.history, $preferences.history.enable)
|
||||
|
||||
if groupInfo.isOwner {
|
||||
|
@ -89,6 +90,7 @@ struct GroupPreferencesView: View {
|
|||
settingsRow(icon, color: color) {
|
||||
Toggle(feature.text, isOn: enable)
|
||||
}
|
||||
.disabled(feature == .reports) // remove in 6.4
|
||||
if timedOn {
|
||||
DropdownCustomTimePicker(
|
||||
selection: $preferences.timedMessages.ttl,
|
||||
|
|
|
@ -1,371 +0,0 @@
|
|||
//
|
||||
// ReverseList.swift
|
||||
// SimpleX (iOS)
|
||||
//
|
||||
// Created by Levitating Pineapple on 11/06/2024.
|
||||
// Copyright © 2024 SimpleX Chat. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import Combine
|
||||
import SimpleXChat
|
||||
|
||||
/// A List, which displays it's items in reverse order - from bottom to top
|
||||
struct ReverseList<Content: View>: UIViewControllerRepresentable {
|
||||
let items: Array<ChatItem>
|
||||
|
||||
@Binding var scrollState: ReverseListScrollModel.State
|
||||
|
||||
/// Closure, that returns user interface for a given item
|
||||
let content: (ChatItem) -> Content
|
||||
|
||||
let loadPage: () -> Void
|
||||
|
||||
func makeUIViewController(context: Context) -> Controller {
|
||||
Controller(representer: self)
|
||||
}
|
||||
|
||||
func updateUIViewController(_ controller: Controller, context: Context) {
|
||||
controller.representer = self
|
||||
if case let .scrollingTo(destination) = scrollState, !items.isEmpty {
|
||||
controller.view.layer.removeAllAnimations()
|
||||
switch destination {
|
||||
case .nextPage:
|
||||
controller.scrollToNextPage()
|
||||
case let .item(id):
|
||||
controller.scroll(to: items.firstIndex(where: { $0.id == id }), position: .bottom)
|
||||
case .bottom:
|
||||
controller.scroll(to: 0, position: .top)
|
||||
}
|
||||
} else {
|
||||
controller.update(items: items)
|
||||
}
|
||||
}
|
||||
|
||||
/// Controller, which hosts SwiftUI cells
|
||||
class Controller: UITableViewController {
|
||||
private enum Section { case main }
|
||||
var representer: ReverseList
|
||||
private var dataSource: UITableViewDiffableDataSource<Section, ChatItem>!
|
||||
private var itemCount: Int = 0
|
||||
private let updateFloatingButtons = PassthroughSubject<Void, Never>()
|
||||
private var bag = Set<AnyCancellable>()
|
||||
|
||||
init(representer: ReverseList) {
|
||||
self.representer = representer
|
||||
super.init(style: .plain)
|
||||
|
||||
// 1. Style
|
||||
tableView = InvertedTableView()
|
||||
tableView.separatorStyle = .none
|
||||
tableView.transform = .verticalFlip
|
||||
tableView.backgroundColor = .clear
|
||||
|
||||
// 2. Register cells
|
||||
if #available(iOS 16.0, *) {
|
||||
tableView.register(
|
||||
UITableViewCell.self,
|
||||
forCellReuseIdentifier: cellReuseId
|
||||
)
|
||||
} else {
|
||||
tableView.register(
|
||||
HostingCell<Content>.self,
|
||||
forCellReuseIdentifier: cellReuseId
|
||||
)
|
||||
}
|
||||
|
||||
// 3. Configure data source
|
||||
self.dataSource = UITableViewDiffableDataSource<Section, ChatItem>(
|
||||
tableView: tableView
|
||||
) { (tableView, indexPath, item) -> UITableViewCell? in
|
||||
if indexPath.item > self.itemCount - 8 {
|
||||
self.representer.loadPage()
|
||||
}
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseId, for: indexPath)
|
||||
if #available(iOS 16.0, *) {
|
||||
cell.contentConfiguration = UIHostingConfiguration { self.representer.content(item) }
|
||||
.margins(.all, 0)
|
||||
.minSize(height: 1) // Passing zero will result in system default of 44 points being used
|
||||
} else {
|
||||
if let cell = cell as? HostingCell<Content> {
|
||||
cell.set(content: self.representer.content(item), parent: self)
|
||||
} else {
|
||||
fatalError("Unexpected Cell Type for: \(item)")
|
||||
}
|
||||
}
|
||||
cell.transform = .verticalFlip
|
||||
cell.selectionStyle = .none
|
||||
cell.backgroundColor = .clear
|
||||
return cell
|
||||
}
|
||||
|
||||
// 4. External state changes will require manual layout updates
|
||||
NotificationCenter.default
|
||||
.addObserver(
|
||||
self,
|
||||
selector: #selector(updateLayout),
|
||||
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)
|
||||
}
|
||||
}
|
||||
.store(in: &bag)
|
||||
}
|
||||
|
||||
@available(*, unavailable)
|
||||
required init?(coder: NSCoder) { fatalError() }
|
||||
|
||||
deinit { NotificationCenter.default.removeObserver(self) }
|
||||
|
||||
@objc private func updateLayout() {
|
||||
if #available(iOS 16.0, *) {
|
||||
tableView.setNeedsLayout()
|
||||
tableView.layoutIfNeeded()
|
||||
} else {
|
||||
tableView.reloadData()
|
||||
}
|
||||
}
|
||||
|
||||
/// Hides keyboard, when user begins to scroll.
|
||||
/// Equivalent to `.scrollDismissesKeyboard(.immediately)`
|
||||
override func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
|
||||
UIApplication.shared
|
||||
.sendAction(
|
||||
#selector(UIResponder.resignFirstResponder),
|
||||
to: nil,
|
||||
from: nil,
|
||||
for: nil
|
||||
)
|
||||
NotificationCenter.default.post(name: .chatViewWillBeginScrolling, object: nil)
|
||||
}
|
||||
|
||||
override func viewDidAppear(_ animated: Bool) {
|
||||
tableView.clipsToBounds = false
|
||||
parent?.viewIfLoaded?.clipsToBounds = false
|
||||
}
|
||||
|
||||
/// Scrolls up
|
||||
func scrollToNextPage() {
|
||||
tableView.setContentOffset(
|
||||
CGPoint(
|
||||
x: tableView.contentOffset.x,
|
||||
y: tableView.contentOffset.y + tableView.bounds.height
|
||||
),
|
||||
animated: true
|
||||
)
|
||||
Task { representer.scrollState = .atDestination }
|
||||
}
|
||||
|
||||
/// Scrolls to Item at index path
|
||||
/// - Parameter indexPath: Item to scroll to - will scroll to beginning of the list, if `nil`
|
||||
func scroll(to index: Int?, position: UITableView.ScrollPosition) {
|
||||
var animated = false
|
||||
if #available(iOS 16.0, *) {
|
||||
animated = true
|
||||
}
|
||||
if let index, tableView.numberOfRows(inSection: 0) != 0 {
|
||||
tableView.scrollToRow(
|
||||
at: IndexPath(row: index, section: 0),
|
||||
at: position,
|
||||
animated: animated
|
||||
)
|
||||
} else {
|
||||
tableView.setContentOffset(
|
||||
CGPoint(x: .zero, y: -InvertedTableView.inset),
|
||||
animated: animated
|
||||
)
|
||||
}
|
||||
Task { representer.scrollState = .atDestination }
|
||||
}
|
||||
|
||||
func update(items: [ChatItem]) {
|
||||
var snapshot = NSDiffableDataSourceSnapshot<Section, ChatItem>()
|
||||
snapshot.appendSections([.main])
|
||||
snapshot.appendItems(items)
|
||||
dataSource.defaultRowAnimation = .none
|
||||
dataSource.apply(
|
||||
snapshot,
|
||||
animatingDifferences: itemCount != 0 && abs(items.count - itemCount) == 1
|
||||
)
|
||||
// Sets content offset on initial load
|
||||
if itemCount == 0 {
|
||||
tableView.setContentOffset(
|
||||
CGPoint(x: 0, y: -InvertedTableView.inset),
|
||||
animated: false
|
||||
)
|
||||
}
|
||||
itemCount = items.count
|
||||
updateFloatingButtons.send()
|
||||
}
|
||||
|
||||
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||
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
|
||||
}
|
||||
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 }
|
||||
}
|
||||
}
|
||||
|
||||
/// `UIHostingConfiguration` back-port for iOS14 and iOS15
|
||||
/// Implemented as a `UITableViewCell` that wraps and manages a generic `UIHostingController`
|
||||
private final class HostingCell<Hosted: View>: UITableViewCell {
|
||||
private let hostingController = UIHostingController<Hosted?>(rootView: nil)
|
||||
|
||||
/// Updates content of the cell
|
||||
/// For reference: https://noahgilmore.com/blog/swiftui-self-sizing-cells/
|
||||
func set(content: Hosted, parent: UIViewController) {
|
||||
hostingController.view.backgroundColor = .clear
|
||||
hostingController.rootView = content
|
||||
if let hostingView = hostingController.view {
|
||||
hostingView.invalidateIntrinsicContentSize()
|
||||
if hostingController.parent != parent { parent.addChild(hostingController) }
|
||||
if !contentView.subviews.contains(hostingController.view) {
|
||||
contentView.addSubview(hostingController.view)
|
||||
hostingView.translatesAutoresizingMaskIntoConstraints = false
|
||||
NSLayoutConstraint.activate([
|
||||
hostingView.leadingAnchor
|
||||
.constraint(equalTo: contentView.leadingAnchor),
|
||||
hostingView.trailingAnchor
|
||||
.constraint(equalTo: contentView.trailingAnchor),
|
||||
hostingView.topAnchor
|
||||
.constraint(equalTo: contentView.topAnchor),
|
||||
hostingView.bottomAnchor
|
||||
.constraint(equalTo: contentView.bottomAnchor)
|
||||
])
|
||||
}
|
||||
if hostingController.parent != parent { hostingController.didMove(toParent: parent) }
|
||||
} else {
|
||||
fatalError("Hosting View not loaded \(hostingController)")
|
||||
}
|
||||
}
|
||||
|
||||
override func prepareForReuse() {
|
||||
super.prepareForReuse()
|
||||
hostingController.rootView = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typealias ListState = (
|
||||
scrollOffset: Double,
|
||||
topItemDate: Date?,
|
||||
bottomItemId: ChatItem.ID?
|
||||
)
|
||||
|
||||
/// Manages ``ReverseList`` scrolling
|
||||
class ReverseListScrollModel: ObservableObject {
|
||||
/// Represents Scroll State of ``ReverseList``
|
||||
enum State: Equatable {
|
||||
enum Destination: Equatable {
|
||||
case nextPage
|
||||
case item(ChatItem.ID)
|
||||
case bottom
|
||||
}
|
||||
|
||||
case scrollingTo(Destination)
|
||||
case atDestination
|
||||
}
|
||||
|
||||
@Published var state: State = .atDestination
|
||||
|
||||
func scrollToNextPage() {
|
||||
state = .scrollingTo(.nextPage)
|
||||
}
|
||||
|
||||
func scrollToBottom() {
|
||||
state = .scrollingTo(.bottom)
|
||||
}
|
||||
|
||||
func scrollToItem(id: ChatItem.ID) {
|
||||
state = .scrollingTo(.item(id))
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate let cellReuseId = "hostingCell"
|
||||
|
||||
fileprivate let notificationName = NSNotification.Name(rawValue: "reverseListNeedsLayout")
|
||||
|
||||
fileprivate extension CGAffineTransform {
|
||||
/// Transform that vertically flips the view, preserving it's location
|
||||
static let verticalFlip = CGAffineTransform(scaleX: 1, y: -1)
|
||||
}
|
||||
|
||||
extension NotificationCenter {
|
||||
static func postReverseListNeedsLayout() {
|
||||
NotificationCenter.default.post(
|
||||
name: notificationName,
|
||||
object: nil
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Disable animation on iOS 15
|
||||
func withConditionalAnimation<Result>(
|
||||
_ animation: Animation? = .default,
|
||||
_ body: () throws -> Result
|
||||
) rethrows -> Result {
|
||||
if #available(iOS 16.0, *) {
|
||||
try withAnimation(animation, body)
|
||||
} else {
|
||||
try body()
|
||||
}
|
||||
}
|
||||
|
||||
class InvertedTableView: UITableView {
|
||||
static let inset = CGFloat(100)
|
||||
|
||||
static let insets = UIEdgeInsets(
|
||||
top: inset,
|
||||
left: .zero,
|
||||
bottom: inset,
|
||||
right: .zero
|
||||
)
|
||||
|
||||
override var contentInsetAdjustmentBehavior: UIScrollView.ContentInsetAdjustmentBehavior {
|
||||
get { .never }
|
||||
set { }
|
||||
}
|
||||
|
||||
override var contentInset: UIEdgeInsets {
|
||||
get { Self.insets }
|
||||
set { }
|
||||
}
|
||||
|
||||
override var adjustedContentInset: UIEdgeInsets {
|
||||
Self.insets
|
||||
}
|
||||
}
|
52
apps/ios/Shared/Views/Chat/ScrollViewCells.swift
Normal file
52
apps/ios/Shared/Views/Chat/ScrollViewCells.swift
Normal file
|
@ -0,0 +1,52 @@
|
|||
//
|
||||
// ScrollViewCells.swift
|
||||
// SimpleX (iOS)
|
||||
//
|
||||
// Created by Stanislav Dmitrenko on 27.01.2025.
|
||||
// Copyright © 2024 SimpleX Chat. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
protocol ReusableView {
|
||||
func prepareForReuse()
|
||||
}
|
||||
|
||||
/// `UIHostingConfiguration` back-port for iOS14 and iOS15
|
||||
/// Implemented as a `UIView` that wraps and manages a generic `UIHostingController`
|
||||
final class HostingCell<Hosted: View>: UIView, ReusableView {
|
||||
private let hostingController = UIHostingController<Hosted?>(rootView: nil)
|
||||
|
||||
/// Updates content of the cell
|
||||
/// For reference: https://noahgilmore.com/blog/swiftui-self-sizing-cells/
|
||||
func set(content: Hosted, parent: UIViewController) {
|
||||
hostingController.view.backgroundColor = .clear
|
||||
hostingController.rootView = content
|
||||
if let hostingView = hostingController.view {
|
||||
hostingView.invalidateIntrinsicContentSize()
|
||||
if hostingController.parent != parent { parent.addChild(hostingController) }
|
||||
if !subviews.contains(hostingController.view) {
|
||||
addSubview(hostingController.view)
|
||||
hostingView.translatesAutoresizingMaskIntoConstraints = false
|
||||
NSLayoutConstraint.activate([
|
||||
hostingView.leadingAnchor
|
||||
.constraint(equalTo: leadingAnchor),
|
||||
hostingView.trailingAnchor
|
||||
.constraint(equalTo: trailingAnchor),
|
||||
hostingView.topAnchor
|
||||
.constraint(equalTo: topAnchor),
|
||||
hostingView.bottomAnchor
|
||||
.constraint(equalTo: bottomAnchor)
|
||||
])
|
||||
}
|
||||
if hostingController.parent != parent { hostingController.didMove(toParent: parent) }
|
||||
} else {
|
||||
fatalError("Hosting View not loaded \(hostingController)")
|
||||
}
|
||||
}
|
||||
|
||||
func prepareForReuse() {
|
||||
//super.prepareForReuse()
|
||||
hostingController.rootView = nil
|
||||
}
|
||||
}
|
|
@ -30,12 +30,15 @@ struct SelectedItemsBottomToolbar: View {
|
|||
var chatInfo: ChatInfo
|
||||
// Bool - delete for everyone is possible
|
||||
var deleteItems: (Bool) -> Void
|
||||
var archiveItems: () -> Void
|
||||
var moderateItems: () -> Void
|
||||
//var shareItems: () -> Void
|
||||
var forwardItems: () -> Void
|
||||
@State var deleteEnabled: Bool = false
|
||||
@State var deleteForEveryoneEnabled: Bool = false
|
||||
|
||||
@State var canArchiveReports: Bool = false
|
||||
|
||||
@State var canModerate: Bool = false
|
||||
@State var moderateEnabled: Bool = false
|
||||
|
||||
|
@ -50,7 +53,11 @@ struct SelectedItemsBottomToolbar: View {
|
|||
|
||||
HStack(alignment: .center) {
|
||||
Button {
|
||||
deleteItems(deleteForEveryoneEnabled)
|
||||
if canArchiveReports {
|
||||
archiveItems()
|
||||
} else {
|
||||
deleteItems(deleteForEveryoneEnabled)
|
||||
}
|
||||
} label: {
|
||||
Image(systemName: "trash")
|
||||
.resizable()
|
||||
|
@ -109,19 +116,25 @@ struct SelectedItemsBottomToolbar: View {
|
|||
deleteCountProhibited = count == 0 || count > 200
|
||||
forwardCountProhibited = count == 0 || count > 20
|
||||
canModerate = possibleToModerate(chatInfo)
|
||||
let groupInfo: GroupInfo? = if case let ChatInfo.group(groupInfo: info) = chatInfo {
|
||||
info
|
||||
} else {
|
||||
nil
|
||||
}
|
||||
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, canArchiveReports, me, onlyOwnGroupItems, forwardEnabled, selectedChatItems) = chatItems.reduce((true, true, true, true, true, true, [])) { (r, ci) in
|
||||
if selected.contains(ci.id) {
|
||||
var (de, dee, me, onlyOwnGroupItems, fe, sel) = r
|
||||
var (de, dee, ar, me, onlyOwnGroupItems, fe, sel) = r
|
||||
de = de && ci.canBeDeletedForSelf
|
||||
dee = dee && ci.meta.deletable && !ci.localNote && !ci.isReport
|
||||
ar = ar && ci.isActiveReport && ci.chatDir != .groupSnd && groupInfo != nil && groupInfo!.membership.memberRole >= .moderator
|
||||
onlyOwnGroupItems = onlyOwnGroupItems && ci.chatDir == .groupSnd && !ci.isReport
|
||||
me = me && ci.content.msgContent != nil && ci.memberToModerate(chatInfo) != nil && !ci.isReport
|
||||
fe = fe && ci.content.msgContent != nil && ci.meta.itemDeleted == nil && !ci.isLiveDummy && !ci.isReport
|
||||
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, ar, me, onlyOwnGroupItems, fe, sel)
|
||||
} else {
|
||||
return r
|
||||
}
|
||||
|
|
|
@ -211,23 +211,32 @@ struct ChatListNavLink: View {
|
|||
}
|
||||
.swipeActions(edge: .trailing, allowsFullSwipe: true) {
|
||||
tagChatButton(chat)
|
||||
let showReportsButton = chat.chatStats.reportsCount > 0 && groupInfo.membership.memberRole >= .moderator
|
||||
let showClearButton = !chat.chatItems.isEmpty
|
||||
let showDeleteGroup = groupInfo.canDelete
|
||||
let showLeaveGroup = groupInfo.membership.memberCurrent
|
||||
let totalNumberOfButtons = 1 + (showClearButton ? 1 : 0) + (showDeleteGroup ? 1 : 0) + (showLeaveGroup ? 1 : 0)
|
||||
let totalNumberOfButtons = 1 + (showReportsButton ? 1 : 0) + (showClearButton ? 1 : 0) + (showDeleteGroup ? 1 : 0) + (showLeaveGroup ? 1 : 0)
|
||||
|
||||
if showClearButton, totalNumberOfButtons <= 3 {
|
||||
if showClearButton && totalNumberOfButtons <= 3 {
|
||||
clearChatButton()
|
||||
}
|
||||
if (showLeaveGroup) {
|
||||
|
||||
if showReportsButton && totalNumberOfButtons <= 3 {
|
||||
archiveAllReportsButton()
|
||||
}
|
||||
|
||||
if showLeaveGroup {
|
||||
leaveGroupChatButton(groupInfo)
|
||||
}
|
||||
|
||||
if showDeleteGroup {
|
||||
if totalNumberOfButtons <= 3 {
|
||||
|
||||
if showDeleteGroup && totalNumberOfButtons <= 3 {
|
||||
deleteGroupChatButton(groupInfo)
|
||||
} else if totalNumberOfButtons > 3 {
|
||||
if showDeleteGroup && !groupInfo.membership.memberActive {
|
||||
deleteGroupChatButton(groupInfo)
|
||||
moreOptionsButton(false, chat, groupInfo)
|
||||
} else {
|
||||
moreOptionsButton(chat, groupInfo)
|
||||
moreOptionsButton(true, chat, groupInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -313,6 +322,14 @@ struct ChatListNavLink: View {
|
|||
}
|
||||
}
|
||||
|
||||
private func archiveAllReportsButton() -> some View {
|
||||
Button {
|
||||
AlertManager.shared.showAlert(archiveAllReportsAlert())
|
||||
} label: {
|
||||
SwipeLabel(NSLocalizedString("Archive reports", comment: "swipe action"), systemImage: "archivebox", inverted: oneHandUI)
|
||||
}
|
||||
}
|
||||
|
||||
private func clearChatButton() -> some View {
|
||||
Button {
|
||||
AlertManager.shared.showAlert(clearChatAlert())
|
||||
|
@ -354,15 +371,20 @@ struct ChatListNavLink: View {
|
|||
)
|
||||
}
|
||||
|
||||
private func moreOptionsButton(_ chat: Chat, _ groupInfo: GroupInfo?) -> some View {
|
||||
private func moreOptionsButton(_ canShowGroupDelete: Bool, _ chat: Chat, _ groupInfo: GroupInfo?) -> some View {
|
||||
Button {
|
||||
var buttons: [Alert.Button] = [
|
||||
.default(Text("Clear")) {
|
||||
AlertManager.shared.showAlert(clearChatAlert())
|
||||
}
|
||||
]
|
||||
|
||||
if let gi = groupInfo, gi.canDelete {
|
||||
var buttons: [Alert.Button] = []
|
||||
buttons.append(.default(Text("Clear")) {
|
||||
AlertManager.shared.showAlert(clearChatAlert())
|
||||
})
|
||||
|
||||
if let groupInfo, chat.chatStats.reportsCount > 0 && groupInfo.membership.memberRole >= .moderator && groupInfo.ready {
|
||||
buttons.append(.default(Text("Archive reports")) {
|
||||
AlertManager.shared.showAlert(archiveAllReportsAlert())
|
||||
})
|
||||
}
|
||||
|
||||
if canShowGroupDelete, let gi = groupInfo, gi.canDelete {
|
||||
buttons.append(.destructive(Text("Delete")) {
|
||||
AlertManager.shared.showAlert(deleteGroupAlert(gi))
|
||||
})
|
||||
|
@ -372,7 +394,7 @@ struct ChatListNavLink: View {
|
|||
|
||||
actionSheet = SomeActionSheet(
|
||||
actionSheet: ActionSheet(
|
||||
title: Text("Clear or delete group?"),
|
||||
title: canShowGroupDelete ? Text("Clear or delete group?") : Text("Clear group?"),
|
||||
buttons: buttons
|
||||
),
|
||||
id: "other options"
|
||||
|
@ -490,6 +512,27 @@ struct ChatListNavLink: View {
|
|||
)
|
||||
}
|
||||
|
||||
private func archiveAllReportsAlert() -> Alert {
|
||||
Alert(
|
||||
title: Text("Archive all reports?"),
|
||||
message: Text("All reports will be archived for you."),
|
||||
primaryButton: .destructive(Text("Archive")) {
|
||||
Task { await archiveAllReportsForMe(chat.chatInfo.apiId) }
|
||||
},
|
||||
secondaryButton: .cancel()
|
||||
)
|
||||
}
|
||||
|
||||
private func archiveAllReportsForMe(_ apiId: Int64) async {
|
||||
do {
|
||||
if case let .groupChatItemsDeleted(user, groupInfo, chatItemIDs, _, member) = try await apiArchiveReceivedReports(groupId: apiId) {
|
||||
await groupChatItemsDeleted(user, groupInfo, chatItemIDs, member)
|
||||
}
|
||||
} catch {
|
||||
logger.error("archiveAllReportsForMe error: \(responseError(error))")
|
||||
}
|
||||
}
|
||||
|
||||
private func clearChatAlert() -> Alert {
|
||||
Alert(
|
||||
title: Text("Clear conversation?"),
|
||||
|
@ -552,8 +595,9 @@ struct ChatListNavLink: View {
|
|||
Task {
|
||||
let ok = await connectContactViaAddress(contact.contactId, incognito, showAlert: { AlertManager.shared.showAlert($0) })
|
||||
if ok {
|
||||
ItemsModel.shared.loadOpenChat(contact.id)
|
||||
AlertManager.shared.showAlert(connReqSentAlert(.contact))
|
||||
ItemsModel.shared.loadOpenChat(contact.id) {
|
||||
AlertManager.shared.showAlert(connReqSentAlert(.contact))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -148,7 +148,10 @@ struct ChatListView: View {
|
|||
@State private var userPickerShown: Bool = false
|
||||
@State private var sheet: SomeSheet<AnyView>? = nil
|
||||
@StateObject private var chatTagsModel = ChatTagsModel.shared
|
||||
|
||||
|
||||
// iOS 15 is required it to show/hide toolbar while chat is hidden/visible
|
||||
@State private var viewOnScreen = true
|
||||
|
||||
@AppStorage(GROUP_DEFAULT_ONE_HAND_UI, store: groupDefaults) private var oneHandUI = true
|
||||
@AppStorage(DEFAULT_ONE_HAND_UI_CARD_SHOWN) private var oneHandUICardShown = false
|
||||
@AppStorage(DEFAULT_ADDRESS_CREATION_CARD_SHOWN) private var addressCreationCardShown = false
|
||||
|
@ -203,7 +206,17 @@ struct ChatListView: View {
|
|||
.navigationBarHidden(searchMode || oneHandUI)
|
||||
}
|
||||
.scaleEffect(x: 1, y: oneHandUI ? -1 : 1, anchor: .center)
|
||||
.onDisappear() { activeUserPickerSheet = nil }
|
||||
.onAppear {
|
||||
if #unavailable(iOS 16.0), !viewOnScreen {
|
||||
viewOnScreen = true
|
||||
}
|
||||
}
|
||||
.onDisappear {
|
||||
activeUserPickerSheet = nil
|
||||
if #unavailable(iOS 16.0) {
|
||||
viewOnScreen = false
|
||||
}
|
||||
}
|
||||
.refreshable {
|
||||
AlertManager.shared.showAlert(Alert(
|
||||
title: Text("Reconnect servers?"),
|
||||
|
@ -258,7 +271,7 @@ struct ChatListView: View {
|
|||
}
|
||||
} else {
|
||||
if oneHandUI {
|
||||
content().toolbar { bottomToolbarGroup }
|
||||
content().toolbar { bottomToolbarGroup() }
|
||||
} else {
|
||||
content().toolbar { topToolbar }
|
||||
}
|
||||
|
@ -286,9 +299,9 @@ struct ChatListView: View {
|
|||
}
|
||||
}
|
||||
|
||||
@ToolbarContentBuilder var bottomToolbarGroup: some ToolbarContent {
|
||||
@ToolbarContentBuilder func bottomToolbarGroup() -> some ToolbarContent {
|
||||
let padding: Double = Self.hasHomeIndicator ? 0 : 14
|
||||
ToolbarItemGroup(placement: .bottomBar) {
|
||||
ToolbarItemGroup(placement: viewOnScreen ? .bottomBar : .principal) {
|
||||
leadingToolbarItem.padding(.bottom, padding)
|
||||
Spacer()
|
||||
SubsStatusIndicator().padding(.bottom, padding)
|
||||
|
|
|
@ -143,6 +143,7 @@ struct ChatPreviewView: View {
|
|||
}
|
||||
case let .group(groupInfo):
|
||||
switch (groupInfo.membership.memberStatus) {
|
||||
case .memRejected: inactiveIcon()
|
||||
case .memLeft: inactiveIcon()
|
||||
case .memRemoved: inactiveIcon()
|
||||
case .memGroupDeleted: inactiveIcon()
|
||||
|
@ -153,7 +154,7 @@ struct ChatPreviewView: View {
|
|||
}
|
||||
}
|
||||
|
||||
@ViewBuilder private func inactiveIcon() -> some View {
|
||||
private func inactiveIcon() -> some View {
|
||||
Image(systemName: "multiply.circle.fill")
|
||||
.foregroundColor(.secondary.opacity(0.65))
|
||||
.background(Circle().foregroundColor(Color(uiColor: .systemBackground)))
|
||||
|
@ -168,7 +169,7 @@ struct ChatPreviewView: View {
|
|||
let v = previewTitle(t)
|
||||
switch (groupInfo.membership.memberStatus) {
|
||||
case .memInvited: v.foregroundColor(deleting ? theme.colors.secondary : chat.chatInfo.incognito ? .indigo : theme.colors.primary)
|
||||
case .memAccepted: v.foregroundColor(theme.colors.secondary)
|
||||
case .memAccepted, .memRejected: v.foregroundColor(theme.colors.secondary)
|
||||
default: if deleting { v.foregroundColor(theme.colors.secondary) } else { v }
|
||||
}
|
||||
default: previewTitle(t)
|
||||
|
@ -336,6 +337,7 @@ struct ChatPreviewView: View {
|
|||
}
|
||||
case let .group(groupInfo):
|
||||
switch (groupInfo.membership.memberStatus) {
|
||||
case .memRejected: chatPreviewInfoText("rejected")
|
||||
case .memInvited: groupInvitationPreviewText(groupInfo)
|
||||
case .memAccepted: chatPreviewInfoText("connecting…")
|
||||
default: EmptyView()
|
||||
|
@ -384,12 +386,10 @@ struct ChatPreviewView: View {
|
|||
case let .image(_, image):
|
||||
smallContentPreview(size: dynamicMediaSize) {
|
||||
CIImageView(chatItem: ci, preview: imageFromBase64(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)
|
||||
.environmentObject(ReverseListScrollModel())
|
||||
}
|
||||
case let .voice(_, duration):
|
||||
smallContentPreviewVoice(size: dynamicMediaSize) {
|
||||
|
|
|
@ -587,7 +587,7 @@ struct SMPStatsView: View {
|
|||
} header: {
|
||||
Text("Statistics")
|
||||
} footer: {
|
||||
Text("Starting from \(localTimestamp(statsStartedAt)).") + Text("\n") + Text("All data is kept private on your device.")
|
||||
Text("Starting from \(localTimestamp(statsStartedAt)).") + textNewLine + Text("All data is kept private on your device.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -703,7 +703,7 @@ struct XFTPStatsView: View {
|
|||
} header: {
|
||||
Text("Statistics")
|
||||
} footer: {
|
||||
Text("Starting from \(localTimestamp(statsStartedAt)).") + Text("\n") + Text("All data is kept private on your device.")
|
||||
Text("Starting from \(localTimestamp(statsStartedAt)).") + textNewLine + Text("All data is kept private on your device.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ struct TagListView: View {
|
|||
Button {
|
||||
showAlert(
|
||||
NSLocalizedString("Delete list?", comment: "alert title"),
|
||||
message: NSLocalizedString("All chats will be removed from the list \(text), and the list deleted.", comment: "alert message"),
|
||||
message: String.localizedStringWithFormat(NSLocalizedString("All chats will be removed from the list %@, and the list deleted.", comment: "alert message"), text),
|
||||
actions: {[
|
||||
UIAlertAction(
|
||||
title: NSLocalizedString("Cancel", comment: "alert action"),
|
||||
|
|
|
@ -188,8 +188,7 @@ struct ContactListNavLink: View {
|
|||
Task {
|
||||
let ok = await connectContactViaAddress(contact.contactId, incognito, showAlert: { alert = SomeAlert(alert: $0, id: "ContactListNavLink connectContactViaAddress") })
|
||||
if ok {
|
||||
ItemsModel.shared.loadOpenChat(contact.id)
|
||||
DispatchQueue.main.async {
|
||||
ItemsModel.shared.loadOpenChat(contact.id) {
|
||||
dismissAllSheets(animated: true) {
|
||||
AlertManager.shared.showAlert(connReqSentAlert(.contact))
|
||||
}
|
||||
|
|
|
@ -141,7 +141,7 @@ struct DatabaseErrorView: View {
|
|||
}
|
||||
|
||||
private func migrationsText(_ ms: [String]) -> some View {
|
||||
(Text("Migrations:").font(.subheadline) + Text(verbatim: "\n") + Text(ms.joined(separator: "\n")).font(.caption))
|
||||
(Text("Migrations:").font(.subheadline) + textNewLine + Text(ms.joined(separator: "\n")).font(.caption))
|
||||
.multilineTextAlignment(.center)
|
||||
.padding(.horizontal, 25)
|
||||
}
|
||||
|
|
|
@ -279,7 +279,7 @@ struct DatabaseView: View {
|
|||
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:") + Text(archiveErrorsText(errs)),
|
||||
message: Text("You may save the exported archive.") + textNewLine + Text("Some file(s) were not exported:") + Text(archiveErrorsText(errs)),
|
||||
dismissButton: .default(Text("Continue")) {
|
||||
showShareSheet(items: [archivePath])
|
||||
}
|
||||
|
|
|
@ -65,6 +65,7 @@ struct LocalAuthView: View {
|
|||
// Clear sensitive data on screen just in case app fails to hide its views while new database is created
|
||||
m.chatId = nil
|
||||
ItemsModel.shared.reversedChatItems = []
|
||||
ItemsModel.shared.chatItemsChangesListener.cleared()
|
||||
m.updateChats([])
|
||||
m.users = []
|
||||
_ = kcAppPassword.set(password)
|
||||
|
|
|
@ -177,7 +177,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:") + Text(archiveErrorsText(errs)),
|
||||
message: Text("You may migrate the exported database.") + textNewLine + Text("Some file(s) were not exported:") + Text(archiveErrorsText(errs)),
|
||||
dismissButton: .default(Text("Continue")) {
|
||||
Task { await uploadArchive(path: archivePath) }
|
||||
}
|
||||
|
|
|
@ -539,7 +539,7 @@ struct MigrateToDevice: View {
|
|||
chatInitControllerRemovingDatabases()
|
||||
} else if ChatModel.shared.chatRunning == true {
|
||||
// cannot delete storage if chat is running
|
||||
try await apiStopChat()
|
||||
try await stopChatAsync()
|
||||
}
|
||||
try await apiDeleteStorage()
|
||||
try? FileManager.default.createDirectory(at: getWallpaperDirectory(), withIntermediateDirectories: true)
|
||||
|
@ -623,7 +623,7 @@ struct MigrateToDevice: View {
|
|||
AlertManager.shared.showAlert(
|
||||
Alert(
|
||||
title: Text("Error migrating settings"),
|
||||
message: Text ("Some app settings were not migrated.") + Text("\n") + Text(responseError(error)))
|
||||
message: Text ("Some app settings were not migrated.") + textNewLine + Text(responseError(error)))
|
||||
)
|
||||
}
|
||||
hideView()
|
||||
|
@ -632,6 +632,8 @@ struct MigrateToDevice: View {
|
|||
private func hideView() {
|
||||
onboardingStageDefault.set(.onboardingComplete)
|
||||
m.onboardingStage = .onboardingComplete
|
||||
m.migrationState = nil
|
||||
MigrationToDeviceState.save(nil)
|
||||
dismiss()
|
||||
}
|
||||
|
||||
|
|
|
@ -1205,12 +1205,14 @@ func openKnownContact(_ contact: Contact, dismiss: Bool, showAlreadyExistsAlert:
|
|||
DispatchQueue.main.async {
|
||||
if dismiss {
|
||||
dismissAllSheets(animated: true) {
|
||||
ItemsModel.shared.loadOpenChat(c.id)
|
||||
showAlreadyExistsAlert?()
|
||||
ItemsModel.shared.loadOpenChat(c.id) {
|
||||
showAlreadyExistsAlert?()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ItemsModel.shared.loadOpenChat(c.id)
|
||||
showAlreadyExistsAlert?()
|
||||
ItemsModel.shared.loadOpenChat(c.id) {
|
||||
showAlreadyExistsAlert?()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1224,12 +1226,14 @@ func openKnownGroup(_ groupInfo: GroupInfo, dismiss: Bool, showAlreadyExistsAler
|
|||
DispatchQueue.main.async {
|
||||
if dismiss {
|
||||
dismissAllSheets(animated: true) {
|
||||
ItemsModel.shared.loadOpenChat(g.id)
|
||||
showAlreadyExistsAlert?()
|
||||
ItemsModel.shared.loadOpenChat(g.id) {
|
||||
showAlreadyExistsAlert?()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ItemsModel.shared.loadOpenChat(g.id)
|
||||
showAlreadyExistsAlert?()
|
||||
ItemsModel.shared.loadOpenChat(g.id) {
|
||||
showAlreadyExistsAlert?()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -161,11 +161,8 @@ struct ChooseServerOperators: View {
|
|||
case .showInfo:
|
||||
ChooseServerOperatorsInfoView()
|
||||
case .showConditions:
|
||||
UsageConditionsView(
|
||||
currUserServers: Binding.constant([]),
|
||||
userServers: Binding.constant([])
|
||||
)
|
||||
.modifier(ThemedBackground(grouped: true))
|
||||
SimpleConditionsView()
|
||||
.modifier(ThemedBackground(grouped: true))
|
||||
}
|
||||
}
|
||||
.frame(maxHeight: .infinity, alignment: .top)
|
||||
|
|
|
@ -145,6 +145,7 @@ struct CreateFirstProfile: View {
|
|||
TextField("Enter your name…", text: $displayName)
|
||||
.focused($focusDisplayName)
|
||||
.padding(.horizontal)
|
||||
.padding(.trailing, 20)
|
||||
.padding(.vertical, 10)
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 10, style: .continuous)
|
||||
|
|
|
@ -140,6 +140,8 @@ struct SimpleXInfo: View {
|
|||
|
||||
let textSpace = Text(verbatim: " ")
|
||||
|
||||
let textNewLine = Text(verbatim: "\n")
|
||||
|
||||
struct SimpleXInfo_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
SimpleXInfo(onboarding: true)
|
||||
|
|
|
@ -539,7 +539,46 @@ private let versionDescriptions: [VersionDescription] = [
|
|||
description: "Delivered even when Apple drops them."
|
||||
)),
|
||||
]
|
||||
)
|
||||
),
|
||||
VersionDescription(
|
||||
version: "v6.3",
|
||||
post: URL(string: "https://simplex.chat/blog/20250308-simplex-chat-v6-3-new-user-experience-safety-in-public-groups.html"),
|
||||
features: [
|
||||
.feature(Description(
|
||||
icon: "at",
|
||||
title: "Mention members 👋",
|
||||
description: "Get notified when mentioned."
|
||||
)),
|
||||
.feature(Description(
|
||||
icon: "flag",
|
||||
title: "Send private reports",
|
||||
description: "Help admins moderating their groups."
|
||||
)),
|
||||
.feature(Description(
|
||||
icon: "list.bullet",
|
||||
title: "Organize chats into lists",
|
||||
description: "Don't miss important messages."
|
||||
)),
|
||||
.feature(Description(
|
||||
icon: nil,
|
||||
title: "Better privacy and security",
|
||||
description: nil,
|
||||
subfeatures: [
|
||||
("eye.slash", "Private media file names."),
|
||||
("trash", "Set message expiration in chats.")
|
||||
]
|
||||
)),
|
||||
.feature(Description(
|
||||
icon: nil,
|
||||
title: "Better groups performance",
|
||||
description: nil,
|
||||
subfeatures: [
|
||||
("bolt", "Faster sending messages."),
|
||||
("person.2.slash", "Faster deletion of groups.")
|
||||
]
|
||||
)),
|
||||
]
|
||||
),
|
||||
]
|
||||
|
||||
private let lastVersion = versionDescriptions.last!.version
|
||||
|
|
|
@ -20,6 +20,7 @@ struct TerminalView: View {
|
|||
@State var composeState: ComposeState = ComposeState()
|
||||
@State var selectedRange = NSRange()
|
||||
@State private var keyboardVisible = false
|
||||
@State private var keyboardHiddenDate = Date.now
|
||||
@State var authorized = !UserDefaults.standard.bool(forKey: DEFAULT_PERFORM_LA)
|
||||
@State private var terminalItem: TerminalItem?
|
||||
@State private var scrolled = false
|
||||
|
@ -101,7 +102,8 @@ struct TerminalView: View {
|
|||
sendMessage: { _ in consoleSendMessage() },
|
||||
showVoiceMessageButton: false,
|
||||
onMediaAdded: { _ in },
|
||||
keyboardVisible: $keyboardVisible
|
||||
keyboardVisible: $keyboardVisible,
|
||||
keyboardHiddenDate: $keyboardHiddenDate
|
||||
)
|
||||
.padding(.horizontal, 12)
|
||||
}
|
||||
|
|
|
@ -367,13 +367,13 @@ struct ChatThemePreview: View {
|
|||
let alice = ChatItem.getSample(1, CIDirection.directRcv, Date.now, NSLocalizedString("Good afternoon!", comment: "message preview"))
|
||||
let bob = ChatItem.getSample(2, CIDirection.directSnd, Date.now, NSLocalizedString("Good morning!", comment: "message preview"), quotedItem: CIQuote.getSample(alice.id, alice.meta.itemTs, alice.content.text, chatDir: alice.chatDir))
|
||||
HStack {
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: alice)
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: alice, scrollToItemId: { _ in })
|
||||
.modifier(ChatItemClipped(alice, tailVisible: true))
|
||||
Spacer()
|
||||
}
|
||||
HStack {
|
||||
Spacer()
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: bob)
|
||||
ChatItemView(chat: Chat.sampleData, chatItem: bob, scrollToItemId: { _ in })
|
||||
.modifier(ChatItemClipped(bob, tailVisible: true))
|
||||
.frame(alignment: .trailing)
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ struct MarkdownHelp: View {
|
|||
mdFormat("_italic_", Text("italic").italic())
|
||||
mdFormat("~strike~", Text("strike").strikethrough())
|
||||
mdFormat("`a + b`", Text("`a + b`").font(.body.monospaced()))
|
||||
mdFormat("!1 colored!", Text("colored").foregroundColor(.red) + Text(" (") + color("1", .red) + color("2", .green) + color("3", .blue) + color("4", .yellow) + color("5", .cyan) + Text("6").foregroundColor(.purple) + Text(")"))
|
||||
mdFormat("!1 colored!", Text("colored").foregroundColor(.red) + Text(verbatim: " (") + color("1", .red) + color("2", .green) + color("3", .blue) + color("4", .yellow) + color("5", .cyan) + Text("6").foregroundColor(.purple) + Text(verbatim: ")"))
|
||||
(
|
||||
mdFormat("#secret#", Text("secret")
|
||||
.foregroundColor(.clear)
|
||||
|
@ -39,7 +39,7 @@ private func mdFormat(_ format: LocalizedStringKey, _ example: Text) -> some Vie
|
|||
}
|
||||
|
||||
private func color(_ s: String, _ c: Color) -> Text {
|
||||
Text(s).foregroundColor(c) + Text(", ")
|
||||
Text(s).foregroundColor(c) + Text(verbatim: ", ")
|
||||
}
|
||||
|
||||
struct MarkdownHelp_Previews: PreviewProvider {
|
||||
|
|
|
@ -368,8 +368,8 @@ struct AdvancedNetworkSettings: View {
|
|||
let userMode = Text("A separate TCP connection will be used **for each chat profile you have in the app**.")
|
||||
return switch mode {
|
||||
case .user: userMode
|
||||
case .session: userMode + Text("\n") + Text("New SOCKS credentials will be used every time you start the app.")
|
||||
case .server: userMode + Text("\n") + Text("New SOCKS credentials will be used for each server.")
|
||||
case .session: userMode + textNewLine + Text("New SOCKS credentials will be used every time you start the app.")
|
||||
case .server: userMode + textNewLine + Text("New SOCKS credentials will be used for each server.")
|
||||
case .entity: Text("A separate TCP connection will be used **for each contact and group member**.\n**Please note**: if you have many connections, your battery and traffic consumption can be substantially higher and some connections may fail.")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -238,22 +238,23 @@ struct UsageConditionsView: View {
|
|||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: 20) {
|
||||
HStack {
|
||||
Text("Conditions of use").font(.largeTitle).bold()
|
||||
Spacer()
|
||||
conditionsLinkButton()
|
||||
}
|
||||
.padding(.top)
|
||||
.padding(.top)
|
||||
|
||||
switch ChatModel.shared.conditions.conditionsAction {
|
||||
|
||||
case .none:
|
||||
regularConditionsHeader()
|
||||
.padding(.top)
|
||||
.padding(.top)
|
||||
ConditionsTextView()
|
||||
.padding(.bottom)
|
||||
.padding(.bottom)
|
||||
|
||||
case let .review(operators, deadline, _):
|
||||
HStack {
|
||||
Text("Updated conditions").font(.largeTitle).bold()
|
||||
}
|
||||
.padding(.top)
|
||||
.padding(.top)
|
||||
|
||||
Text("Conditions will be accepted for the operator(s): **\(operators.map { $0.legalName_ }.joined(separator: ", "))**.")
|
||||
ConditionsTextView()
|
||||
VStack(spacing: 8) {
|
||||
|
@ -265,6 +266,10 @@ struct UsageConditionsView: View {
|
|||
.multilineTextAlignment(.center)
|
||||
.frame(maxWidth: .infinity, alignment: .center)
|
||||
.padding(.horizontal, 32)
|
||||
conditionsDiffButton(.footnote)
|
||||
} else {
|
||||
conditionsDiffButton()
|
||||
.padding(.top)
|
||||
}
|
||||
}
|
||||
.padding(.bottom)
|
||||
|
@ -272,6 +277,9 @@ struct UsageConditionsView: View {
|
|||
|
||||
|
||||
case let .accepted(operators):
|
||||
regularConditionsHeader()
|
||||
.padding(.top)
|
||||
.padding(.top)
|
||||
Text("Conditions are accepted for the operator(s): **\(operators.map { $0.legalName_ }.joined(separator: ", "))**.")
|
||||
ConditionsTextView()
|
||||
.padding(.bottom)
|
||||
|
@ -312,6 +320,43 @@ struct UsageConditionsView: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder private func conditionsDiffButton(_ font: Font? = nil) -> some View {
|
||||
let commit = ChatModel.shared.conditions.currentConditions.conditionsCommit
|
||||
if let commitUrl = URL(string: "https://github.com/simplex-chat/simplex-chat/commit/\(commit)") {
|
||||
Link(destination: commitUrl) {
|
||||
HStack {
|
||||
Text("Open changes")
|
||||
Image(systemName: "arrow.up.right.circle")
|
||||
}
|
||||
.font(font)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func regularConditionsHeader() -> some View {
|
||||
HStack {
|
||||
Text("Conditions of use").font(.largeTitle).bold()
|
||||
Spacer()
|
||||
conditionsLinkButton()
|
||||
}
|
||||
}
|
||||
|
||||
struct SimpleConditionsView: View {
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: 20) {
|
||||
regularConditionsHeader()
|
||||
.padding(.top)
|
||||
.padding(.top)
|
||||
ConditionsTextView()
|
||||
.padding(.bottom)
|
||||
.padding(.bottom)
|
||||
}
|
||||
.padding(.horizontal, 25)
|
||||
.frame(maxHeight: .infinity)
|
||||
}
|
||||
}
|
||||
|
||||
func validateServers_(_ userServers: Binding<[UserOperatorServers]>, _ serverErrors: Binding<[UserServersError]>) {
|
||||
|
|
|
@ -13,7 +13,7 @@ struct NotificationsView: View {
|
|||
@EnvironmentObject var m: ChatModel
|
||||
@EnvironmentObject var theme: AppTheme
|
||||
@State private var notificationMode: NotificationsMode = ChatModel.shared.notificationMode
|
||||
@State private var showAlert: NotificationAlert?
|
||||
@State private var ntfAlert: NotificationAlert?
|
||||
@State private var legacyDatabase = dbContainerGroupDefault.get() == .documents
|
||||
@State private var testing = false
|
||||
@State private var testedSuccess: Bool? = nil
|
||||
|
@ -25,7 +25,7 @@ struct NotificationsView: View {
|
|||
ProgressView().scaleEffect(2)
|
||||
}
|
||||
}
|
||||
.alert(item: $showAlert) { alert in
|
||||
.alert(item: $ntfAlert) { alert in
|
||||
if let token = m.deviceToken {
|
||||
return notificationAlert(alert, token)
|
||||
} else {
|
||||
|
@ -41,7 +41,7 @@ struct NotificationsView: View {
|
|||
List {
|
||||
Section {
|
||||
SelectionListView(list: NotificationsMode.values, selection: $notificationMode) { mode in
|
||||
showAlert = .setMode(mode: mode)
|
||||
ntfAlert = .setMode(mode: mode)
|
||||
}
|
||||
} footer: {
|
||||
VStack(alignment: .leading) {
|
||||
|
@ -95,7 +95,7 @@ struct NotificationsView: View {
|
|||
|
||||
if let server = m.notificationServer {
|
||||
smpServers("Push server", [server], theme.colors.secondary)
|
||||
testServerButton(server)
|
||||
testTokenButton(server)
|
||||
}
|
||||
} header: {
|
||||
Text("Push notifications")
|
||||
|
@ -163,7 +163,7 @@ struct NotificationsView: View {
|
|||
await MainActor.run {
|
||||
let err = responseError(error)
|
||||
logger.error("apiDeleteToken error: \(err)")
|
||||
showAlert = .error(title: "Error deleting token", error: err)
|
||||
ntfAlert = .error(title: "Error deleting token", error: err)
|
||||
}
|
||||
}
|
||||
default:
|
||||
|
@ -181,19 +181,19 @@ struct NotificationsView: View {
|
|||
await MainActor.run {
|
||||
let err = responseError(error)
|
||||
logger.error("apiRegisterToken error: \(err)")
|
||||
showAlert = .error(title: "Error enabling notifications", error: err)
|
||||
ntfAlert = .error(title: "Error enabling notifications", error: err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func testServerButton(_ server: String) -> some View {
|
||||
private func testTokenButton(_ server: String) -> some View {
|
||||
HStack {
|
||||
Button("Test server") {
|
||||
Button("Test notifications") {
|
||||
testing = true
|
||||
Task {
|
||||
await testServer(server)
|
||||
await testServerAndToken(server)
|
||||
await MainActor.run { testing = false }
|
||||
}
|
||||
}
|
||||
|
@ -215,22 +215,61 @@ struct NotificationsView: View {
|
|||
}
|
||||
}
|
||||
|
||||
private func testServer(_ server: String) async {
|
||||
private func testServerAndToken(_ server: String) async {
|
||||
do {
|
||||
let r = try await testProtoServer(server: server)
|
||||
switch r {
|
||||
case .success:
|
||||
await MainActor.run {
|
||||
testedSuccess = true
|
||||
if let token = m.deviceToken {
|
||||
do {
|
||||
let status = try await apiCheckToken(token: token)
|
||||
await MainActor.run {
|
||||
m.tokenStatus = status
|
||||
testedSuccess = status.workingToken
|
||||
if status.workingToken {
|
||||
showAlert(
|
||||
NSLocalizedString("Notifications status", comment: "alert title"),
|
||||
message: tokenStatusInfo(status, register: false)
|
||||
)
|
||||
} else {
|
||||
showAlert(
|
||||
title: NSLocalizedString("Notifications error", comment: "alert title"),
|
||||
message: tokenStatusInfo(status, register: true),
|
||||
buttonTitle: "Register",
|
||||
buttonAction: {
|
||||
reRegisterToken(token: token)
|
||||
testedSuccess = nil
|
||||
},
|
||||
cancelButton: true
|
||||
)
|
||||
}
|
||||
}
|
||||
} catch let error {
|
||||
await MainActor.run {
|
||||
let err = responseError(error)
|
||||
logger.error("apiCheckToken \(err)")
|
||||
ntfAlert = .error(title: "Error checking token status", error: err)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
await MainActor.run {
|
||||
showAlert(
|
||||
NSLocalizedString("No token!", comment: "alert title")
|
||||
)
|
||||
}
|
||||
}
|
||||
case let .failure(f):
|
||||
await MainActor.run {
|
||||
showAlert = .testFailure(testFailure: f)
|
||||
ntfAlert = .testFailure(testFailure: f)
|
||||
testedSuccess = false
|
||||
}
|
||||
}
|
||||
} catch let error {
|
||||
logger.error("testServerConnection \(responseError(error))")
|
||||
await MainActor.run {
|
||||
let err = responseError(error)
|
||||
logger.error("testServerConnection \(err)")
|
||||
ntfAlert = .error(title: "Error testing server connection", error: err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -477,7 +477,11 @@ struct SettingsView: View {
|
|||
case .registered:
|
||||
icon = "bolt.fill"
|
||||
color = theme.colors.secondary
|
||||
case .invalid:
|
||||
case .invalid: fallthrough
|
||||
case .invalidBad: fallthrough
|
||||
case .invalidTopic: fallthrough
|
||||
case .invalidExpired: fallthrough
|
||||
case .invalidUnregistered:
|
||||
icon = "bolt.slash"
|
||||
color = theme.colors.secondary
|
||||
case .confirmed:
|
||||
|
@ -524,7 +528,7 @@ struct ProfilePreview: View {
|
|||
func profileName(_ profileOf: NamedChat) -> Text {
|
||||
var t = Text(profileOf.displayName).fontWeight(.semibold).font(.title2)
|
||||
if profileOf.fullName != "" && profileOf.fullName != profileOf.displayName {
|
||||
t = t + Text(" (" + profileOf.fullName + ")")
|
||||
t = t + Text(verbatim: " (" + profileOf.fullName + ")")
|
||||
// .font(.callout)
|
||||
}
|
||||
return t
|
||||
|
|
|
@ -33,7 +33,7 @@ struct StorageView: View {
|
|||
private func directoryView(_ name: LocalizedStringKey, _ contents: [String: Int64]) -> some View {
|
||||
Text(name).font(.headline)
|
||||
ForEach(Array(contents), id: \.key) { (key, value) in
|
||||
Text(key).bold() + Text(" ") + Text("\(ByteCountFormatter.string(fromByteCount: value, countStyle: .binary))")
|
||||
Text(key).bold() + Text(verbatim: " ") + Text((ByteCountFormatter.string(fromByteCount: value, countStyle: .binary)))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -5,22 +5,6 @@
|
|||
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.4" build-num="15F31d"/>
|
||||
</header>
|
||||
<body>
|
||||
<trans-unit id=" " xml:space="preserve">
|
||||
<source>
|
||||
</source>
|
||||
<target>
|
||||
</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=" " xml:space="preserve">
|
||||
<source> </source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=" (" xml:space="preserve">
|
||||
<source> (</source>
|
||||
<target> (</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=" (can be copied)" xml:space="preserve">
|
||||
<source> (can be copied)</source>
|
||||
<target> (може да се копира)</target>
|
||||
|
@ -323,11 +307,6 @@
|
|||
<target>%u пропуснати съобщения.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="(" xml:space="preserve">
|
||||
<source>(</source>
|
||||
<target>(</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="(new)" xml:space="preserve">
|
||||
<source>(new)</source>
|
||||
<target>(ново)</target>
|
||||
|
@ -338,11 +317,6 @@
|
|||
<target>(това устройство v%@)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=")" xml:space="preserve">
|
||||
<source>)</source>
|
||||
<target>)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="**Create 1-time link**: to create and share a new invitation link." xml:space="preserve">
|
||||
<source>**Create 1-time link**: to create and share a new invitation link.</source>
|
||||
<target>**Добави контакт**: за създаване на нов линк.</target>
|
||||
|
@ -407,11 +381,6 @@
|
|||
<target>\*удебелен*</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=", " xml:space="preserve">
|
||||
<source>, </source>
|
||||
<target>, </target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="- connect to [directory service](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (BETA)! - delivery receipts (up to 20 members). - faster and more stable." xml:space="preserve">
|
||||
<source>- connect to [directory service](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (BETA)!
|
||||
- delivery receipts (up to 20 members).
|
||||
|
@ -448,11 +417,6 @@
|
|||
- история на редактиране.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="." xml:space="preserve">
|
||||
<source>.</source>
|
||||
<target>.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="0 sec" xml:space="preserve">
|
||||
<source>0 sec</source>
|
||||
<target>0 сек</target>
|
||||
|
@ -519,11 +483,6 @@
|
|||
<target>30 секунди</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=": " xml:space="preserve">
|
||||
<source>: </source>
|
||||
<target>: </target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="<p>Hi!</p> <p><a href="%@">Connect to me via SimpleX Chat</a></p>" xml:space="preserve">
|
||||
<source><p>Hi!</p>
|
||||
<p><a href="%@">Connect to me via SimpleX Chat</a></p></source>
|
||||
|
@ -631,6 +590,10 @@
|
|||
<target>Грешки при потвърждението</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Active" xml:space="preserve">
|
||||
<source>Active</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Active connections" xml:space="preserve">
|
||||
<source>Active connections</source>
|
||||
<target>Активни връзки</target>
|
||||
|
@ -768,8 +731,8 @@
|
|||
<target>Всички чатове и съобщения ще бъдат изтрити - това не може да бъде отменено!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All chats will be removed from the list (text), and the list deleted." xml:space="preserve">
|
||||
<source>All chats will be removed from the list (text), and the list deleted.</source>
|
||||
<trans-unit id="All chats will be removed from the list %@, and the list deleted." xml:space="preserve">
|
||||
<source>All chats will be removed from the list %@, and the list deleted.</source>
|
||||
<note>alert message</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All data is erased when it is entered." xml:space="preserve">
|
||||
|
@ -811,6 +774,10 @@
|
|||
<target>Всички профили</target>
|
||||
<note>profile dropdown</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All reports will be archived for you." xml:space="preserve">
|
||||
<source>All reports will be archived for you.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
||||
<source>All your contacts will remain connected.</source>
|
||||
<target>Всички ваши контакти ще останат свързани.</target>
|
||||
|
@ -886,6 +853,10 @@
|
|||
<target>Позволи необратимо изтриване на изпратените съобщения. (24 часа)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Allow to report messsages to moderators." xml:space="preserve">
|
||||
<source>Allow to report messsages to moderators.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Allow to send SimpleX links." xml:space="preserve">
|
||||
<source>Allow to send SimpleX links.</source>
|
||||
<target>Разрешаване на изпращане на SimpleX линкове.</target>
|
||||
|
@ -1048,6 +1019,14 @@
|
|||
<source>Archive</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive %lld reports?" xml:space="preserve">
|
||||
<source>Archive %lld reports?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive all reports?" xml:space="preserve">
|
||||
<source>Archive all reports?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive and upload" xml:space="preserve">
|
||||
<source>Archive and upload</source>
|
||||
<target>Архивиране и качване</target>
|
||||
|
@ -1066,6 +1045,10 @@
|
|||
<source>Archive report?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive reports" xml:space="preserve">
|
||||
<source>Archive reports</source>
|
||||
<note>swipe action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archived contacts" xml:space="preserve">
|
||||
<source>Archived contacts</source>
|
||||
<target>Архивирани контакти</target>
|
||||
|
@ -1180,6 +1163,10 @@
|
|||
<target>По-добри групи</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better groups performance" xml:space="preserve">
|
||||
<source>Better groups performance</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better message dates." xml:space="preserve">
|
||||
<source>Better message dates.</source>
|
||||
<target>По-добри дати на съобщението.</target>
|
||||
|
@ -1200,6 +1187,10 @@
|
|||
<target>Подобрени известия</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better privacy and security" xml:space="preserve">
|
||||
<source>Better privacy and security</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better security ✅" xml:space="preserve">
|
||||
<source>Better security ✅</source>
|
||||
<target>По-добра сигурност ✅</target>
|
||||
|
@ -1603,6 +1594,10 @@
|
|||
<target>Изчисти разговора?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Clear group?" xml:space="preserve">
|
||||
<source>Clear group?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Clear or delete group?" xml:space="preserve">
|
||||
<source>Clear or delete group?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -1732,6 +1727,10 @@
|
|||
<target>Потвърди качването</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Confirmed" xml:space="preserve">
|
||||
<source>Confirmed</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Connect" xml:space="preserve">
|
||||
<source>Connect</source>
|
||||
<target>Свързване</target>
|
||||
|
@ -1993,31 +1992,32 @@ This is your own one-time link!</source>
|
|||
</trans-unit>
|
||||
<trans-unit id="Create" xml:space="preserve">
|
||||
<source>Create</source>
|
||||
<target>Създай</target>
|
||||
<target>Създаване</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Create 1-time link" xml:space="preserve">
|
||||
<source>Create 1-time link</source>
|
||||
<target>Създаване на еднократна препратка</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Create SimpleX address" xml:space="preserve">
|
||||
<source>Create SimpleX address</source>
|
||||
<target>Създай SimpleX адрес</target>
|
||||
<target>Създаване на адрес в SimpleX</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Create a group using a random profile." xml:space="preserve">
|
||||
<source>Create a group using a random profile.</source>
|
||||
<target>Създай група с автоматично генериран профилл.</target>
|
||||
<target>Създаване група с автоматично създаден профил.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Create file" xml:space="preserve">
|
||||
<source>Create file</source>
|
||||
<target>Създай файл</target>
|
||||
<target>Създаване на файл</target>
|
||||
<note>server test step</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Create group" xml:space="preserve">
|
||||
<source>Create group</source>
|
||||
<target>Създай група</target>
|
||||
<target>Създаване на група</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Create group link" xml:space="preserve">
|
||||
|
@ -2689,6 +2689,10 @@ This is your own one-time link!</source>
|
|||
<target>Не активирай</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Don't miss important messages." xml:space="preserve">
|
||||
<source>Don't miss important messages.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Don't show again" xml:space="preserve">
|
||||
<source>Don't show again</source>
|
||||
<target>Не показвай отново</target>
|
||||
|
@ -3032,6 +3036,10 @@ This is your own one-time link!</source>
|
|||
<source>Error changing to incognito!</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error checking token status" xml:space="preserve">
|
||||
<source>Error checking token status</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error connecting to forwarding server %@. Please try later." xml:space="preserve">
|
||||
<source>Error connecting to forwarding server %@. Please try later.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -3179,6 +3187,10 @@ This is your own one-time link!</source>
|
|||
<source>Error reconnecting servers</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error registering for notifications" xml:space="preserve">
|
||||
<source>Error registering for notifications</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error removing member" xml:space="preserve">
|
||||
<source>Error removing member</source>
|
||||
<target>Грешка при отстраняване на член</target>
|
||||
|
@ -3279,6 +3291,10 @@ This is your own one-time link!</source>
|
|||
<target>Грешка при синхронизиране на връзката</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error testing server connection" xml:space="preserve">
|
||||
<source>Error testing server connection</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error updating group link" xml:space="preserve">
|
||||
<source>Error updating group link</source>
|
||||
<target>Грешка при актуализиране на груповия линк</target>
|
||||
|
@ -3356,6 +3372,10 @@ This is your own one-time link!</source>
|
|||
<target>Разшири</target>
|
||||
<note>chat item action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Expired" xml:space="preserve">
|
||||
<source>Expired</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Export database" xml:space="preserve">
|
||||
<source>Export database</source>
|
||||
<target>Експортирай база данни</target>
|
||||
|
@ -3395,11 +3415,19 @@ This is your own one-time link!</source>
|
|||
<target>Бързо и без чакане, докато подателят е онлайн!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Faster deletion of groups." xml:space="preserve">
|
||||
<source>Faster deletion of groups.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Faster joining and more reliable messages." xml:space="preserve">
|
||||
<source>Faster joining and more reliable messages.</source>
|
||||
<target>По-бързо присъединяване и по-надеждни съобщения.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Faster sending messages." xml:space="preserve">
|
||||
<source>Faster sending messages.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Favorite" xml:space="preserve">
|
||||
<source>Favorite</source>
|
||||
<target>Любим</target>
|
||||
|
@ -3418,9 +3446,9 @@ This is your own one-time link!</source>
|
|||
%@</source>
|
||||
<note>alert message</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="File is blocked by server operator: (info.reason.text)." xml:space="preserve">
|
||||
<trans-unit id="File is blocked by server operator: %@." xml:space="preserve">
|
||||
<source>File is blocked by server operator:
|
||||
(info.reason.text).</source>
|
||||
%@.</source>
|
||||
<note>file error text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="File not found - most likely file was deleted or cancelled." xml:space="preserve">
|
||||
|
@ -3543,6 +3571,10 @@ This is your own one-time link!</source>
|
|||
<target>Поправката не се поддържа от члена на групата</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For all moderators" xml:space="preserve">
|
||||
<source>For all moderators</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For chat profile %@:" xml:space="preserve">
|
||||
<source>For chat profile %@:</source>
|
||||
<note>servers error</note>
|
||||
|
@ -3556,6 +3588,10 @@ This is your own one-time link!</source>
|
|||
<source>For example, if your contact receives messages via a SimpleX Chat server, your app will deliver them via a Flux server.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For me" xml:space="preserve">
|
||||
<source>For me</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For private routing" xml:space="preserve">
|
||||
<source>For private routing</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -3666,6 +3702,10 @@ Error: %2$@</source>
|
|||
<target>GIF файлове и стикери</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Get notified when mentioned." xml:space="preserve">
|
||||
<source>Get notified when mentioned.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Good afternoon!" xml:space="preserve">
|
||||
<source>Good afternoon!</source>
|
||||
<note>message preview</note>
|
||||
|
@ -3778,6 +3818,10 @@ Error: %2$@</source>
|
|||
<target>Помощ</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Help admins moderating their groups." xml:space="preserve">
|
||||
<source>Help admins moderating their groups.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Hidden" xml:space="preserve">
|
||||
<source>Hidden</source>
|
||||
<target>Скрит</target>
|
||||
|
@ -4077,6 +4121,26 @@ More improvements are coming soon!</source>
|
|||
<source>Interface colors</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid" xml:space="preserve">
|
||||
<source>Invalid</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (bad token)" xml:space="preserve">
|
||||
<source>Invalid (bad token)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (expired)" xml:space="preserve">
|
||||
<source>Invalid (expired)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (unregistered)" xml:space="preserve">
|
||||
<source>Invalid (unregistered)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (wrong topic)" xml:space="preserve">
|
||||
<source>Invalid (wrong topic)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid QR code" xml:space="preserve">
|
||||
<source>Invalid QR code</source>
|
||||
<target>Невалиден QR код</target>
|
||||
|
@ -4444,6 +4508,10 @@ This is your link for group %@!</source>
|
|||
<source>Member inactive</source>
|
||||
<note>item status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Member reports" xml:space="preserve">
|
||||
<source>Member reports</source>
|
||||
<note>chat feature</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Member role will be changed to "%@". All chat members will be notified." xml:space="preserve">
|
||||
<source>Member role will be changed to "%@". All chat members will be notified.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -4477,6 +4545,10 @@ This is your link for group %@!</source>
|
|||
<target>Членовете на групата могат необратимо да изтриват изпратените съобщения. (24 часа)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Members can report messsages to moderators." xml:space="preserve">
|
||||
<source>Members can report messsages to moderators.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Members can send SimpleX links." xml:space="preserve">
|
||||
<source>Members can send SimpleX links.</source>
|
||||
<target>Членовете на групата могат да изпращат SimpleX линкове.</target>
|
||||
|
@ -4502,6 +4574,10 @@ This is your link for group %@!</source>
|
|||
<target>Членовете на групата могат да изпращат гласови съобщения.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Mention members 👋" xml:space="preserve">
|
||||
<source>Mention members 👋</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Menus" xml:space="preserve">
|
||||
<source>Menus</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -4734,7 +4810,11 @@ This is your link for group %@!</source>
|
|||
<trans-unit id="Mute" xml:space="preserve">
|
||||
<source>Mute</source>
|
||||
<target>Без звук</target>
|
||||
<note>swipe action</note>
|
||||
<note>notification label action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Mute all" xml:space="preserve">
|
||||
<source>Mute all</source>
|
||||
<note>notification label action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Muted when inactive!" xml:space="preserve">
|
||||
<source>Muted when inactive!</source>
|
||||
|
@ -4783,6 +4863,10 @@ This is your link for group %@!</source>
|
|||
<target>Състояние на мрежата</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="New" xml:space="preserve">
|
||||
<source>New</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="New Passcode" xml:space="preserve">
|
||||
<source>New Passcode</source>
|
||||
<target>Нов kод за достъп</target>
|
||||
|
@ -4926,6 +5010,10 @@ This is your link for group %@!</source>
|
|||
<source>No media & file servers.</source>
|
||||
<note>servers error</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No message" xml:space="preserve">
|
||||
<source>No message</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No message servers." xml:space="preserve">
|
||||
<source>No message servers.</source>
|
||||
<note>servers error</note>
|
||||
|
@ -4974,6 +5062,10 @@ This is your link for group %@!</source>
|
|||
<source>No servers to send files.</source>
|
||||
<note>servers error</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No token!" xml:space="preserve">
|
||||
<source>No token!</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No unread chats" xml:space="preserve">
|
||||
<source>No unread chats</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -5010,10 +5102,18 @@ This is your link for group %@!</source>
|
|||
<target>Известията са деактивирани!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Notifications error" xml:space="preserve">
|
||||
<source>Notifications error</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Notifications privacy" xml:space="preserve">
|
||||
<source>Notifications privacy</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Notifications status" xml:space="preserve">
|
||||
<source>Notifications status</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Now admins can: - delete members' messages. - disable members ("observer" role)" xml:space="preserve">
|
||||
<source>Now admins can:
|
||||
- delete members' messages.
|
||||
|
@ -5244,6 +5344,10 @@ Requires compatible VPN.</source>
|
|||
<source>Or to share privately</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Organize chats into lists" xml:space="preserve">
|
||||
<source>Organize chats into lists</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Other" xml:space="preserve">
|
||||
<source>Other</source>
|
||||
<target>Други</target>
|
||||
|
@ -5427,6 +5531,18 @@ Error: %@</source>
|
|||
<target>Моля, съхранявайте паролата на сигурно място, НЯМА да можете да я промените, ако я загубите.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please try to disable and re-enable notfications." xml:space="preserve">
|
||||
<source>Please try to disable and re-enable notfications.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please wait for token activation to complete." xml:space="preserve">
|
||||
<source>Please wait for token activation to complete.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please wait for token to be registered." xml:space="preserve">
|
||||
<source>Please wait for token to be registered.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Polish interface" xml:space="preserve">
|
||||
<source>Polish interface</source>
|
||||
<target>Полски интерфейс</target>
|
||||
|
@ -5483,6 +5599,10 @@ Error: %@</source>
|
|||
<target>Поверителни имена на файлове</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Private media file names." xml:space="preserve">
|
||||
<source>Private media file names.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Private message routing" xml:space="preserve">
|
||||
<source>Private message routing</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -5553,6 +5673,10 @@ Error: %@</source>
|
|||
<target>Забрани реакциите на съобщенията.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Prohibit reporting messages to moderators." xml:space="preserve">
|
||||
<source>Prohibit reporting messages to moderators.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Prohibit sending SimpleX links." xml:space="preserve">
|
||||
<source>Prohibit sending SimpleX links.</source>
|
||||
<target>Забранете изпращането на SimpleX линкове.</target>
|
||||
|
@ -5794,6 +5918,18 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>Намалена консумация на батерията</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Register" xml:space="preserve">
|
||||
<source>Register</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Register notification token?" xml:space="preserve">
|
||||
<source>Register notification token?</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Registered" xml:space="preserve">
|
||||
<source>Registered</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Reject" xml:space="preserve">
|
||||
<source>Reject</source>
|
||||
<target>Отхвърляне</target>
|
||||
|
@ -5921,6 +6057,14 @@ Enable in *Network & servers* settings.</source>
|
|||
<source>Report violation: only group moderators will see it.</source>
|
||||
<note>report reason</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Report: %@" xml:space="preserve">
|
||||
<source>Report: %@</source>
|
||||
<note>report in notification</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Reporting messages to moderators is prohibited." xml:space="preserve">
|
||||
<source>Reporting messages to moderators is prohibited.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Reports" xml:space="preserve">
|
||||
<source>Reports</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -6321,6 +6465,10 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>Изпращай известия</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Send private reports" xml:space="preserve">
|
||||
<source>Send private reports</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Send questions and ideas" xml:space="preserve">
|
||||
<source>Send questions and ideas</source>
|
||||
<target>Изпращайте въпроси и идеи</target>
|
||||
|
@ -6541,6 +6689,10 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>Задайте го вместо системната идентификация.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Set message expiration in chats." xml:space="preserve">
|
||||
<source>Set message expiration in chats.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Set passcode" xml:space="preserve">
|
||||
<source>Set passcode</source>
|
||||
<target>Задай kод за достъп</target>
|
||||
|
@ -6972,6 +7124,10 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>Времето на изчакване за установяване на TCP връзка</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="TCP port for messaging" xml:space="preserve">
|
||||
<source>TCP port for messaging</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="TCP_KEEPCNT" xml:space="preserve">
|
||||
<source>TCP_KEEPCNT</source>
|
||||
<target>TCP_KEEPCNT</target>
|
||||
|
@ -7044,6 +7200,10 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>Тестът е неуспешен на стъпка %@.</target>
|
||||
<note>server test failure</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Test notifications" xml:space="preserve">
|
||||
<source>Test notifications</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Test server" xml:space="preserve">
|
||||
<source>Test server</source>
|
||||
<target>Тествай сървър</target>
|
||||
|
@ -7166,10 +7326,6 @@ It can happen because of some bug or when the connection is compromised.</source
|
|||
<target>Профилът се споделя само с вашите контакти.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="The report will be archived for you." xml:space="preserve">
|
||||
<source>The report will be archived for you.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve">
|
||||
<source>The same conditions will apply to operator **%@**.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -7291,6 +7447,10 @@ It can happen because of some bug or when the connection is compromised.</source
|
|||
<source>This link was used with another mobile device, please create a new link on the desktop.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="This message was deleted or not received yet." xml:space="preserve">
|
||||
<source>This message was deleted or not received yet.</source>
|
||||
<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">
|
||||
<source>This setting applies to messages in your current chat profile **%@**.</source>
|
||||
<target>Тази настройка се прилага за съобщения в текущия ви профил **%@**.</target>
|
||||
|
@ -7394,6 +7554,10 @@ You will be prompted to complete authentication before this feature is enabled.<
|
|||
<target>Избор на инкогнито при свързване.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Token status: %@." xml:space="preserve">
|
||||
<source>Token status: %@.</source>
|
||||
<note>token status</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Toolbar opacity" xml:space="preserve">
|
||||
<source>Toolbar opacity</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -7554,7 +7718,7 @@ To connect, please ask your contact to create another connection link and check
|
|||
<trans-unit id="Unmute" xml:space="preserve">
|
||||
<source>Unmute</source>
|
||||
<target>Уведомявай</target>
|
||||
<note>swipe action</note>
|
||||
<note>notification label action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Unread" xml:space="preserve">
|
||||
<source>Unread</source>
|
||||
|
@ -7585,6 +7749,10 @@ To connect, please ask your contact to create another connection link and check
|
|||
<source>Update settings?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Updated conditions" xml:space="preserve">
|
||||
<source>Updated conditions</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Updating settings will re-connect the client to all servers." xml:space="preserve">
|
||||
<source>Updating settings will re-connect the client to all servers.</source>
|
||||
<target>Актуализирането на настройките ще свърже отново клиента към всички сървъри.</target>
|
||||
|
@ -7640,6 +7808,10 @@ To connect, please ask your contact to create another connection link and check
|
|||
<target>Използвай сървърите на SimpleX Chat?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use TCP port %@ when no port is specified." xml:space="preserve">
|
||||
<source>Use TCP port %@ when no port is specified.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use chat" xml:space="preserve">
|
||||
<source>Use chat</source>
|
||||
<target>Използвай чата</target>
|
||||
|
@ -7709,6 +7881,10 @@ To connect, please ask your contact to create another connection link and check
|
|||
<source>Use the app with one hand.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use web port" xml:space="preserve">
|
||||
<source>Use web port</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="User selection" xml:space="preserve">
|
||||
<source>User selection</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -8239,6 +8415,10 @@ Repeat connection request?</source>
|
|||
<target>Изпратихте покана за групата</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="You should receive notifications." xml:space="preserve">
|
||||
<source>You should receive notifications.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="You will be connected to group when the group host's device is online, please wait or check later!" xml:space="preserve">
|
||||
<source>You will be connected to group when the group host's device is online, please wait or check later!</source>
|
||||
<target>Ще бъдете свързани с групата, когато устройството на домакина на групата е онлайн, моля, изчакайте или проверете по-късно!</target>
|
||||
|
@ -8310,7 +8490,7 @@ Repeat connection request?</source>
|
|||
</trans-unit>
|
||||
<trans-unit id="Your SimpleX address" xml:space="preserve">
|
||||
<source>Your SimpleX address</source>
|
||||
<target>Вашият SimpleX адрес</target>
|
||||
<target>Вашият адрес в SimpleX</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Your calls" xml:space="preserve">
|
||||
|
@ -9017,10 +9197,6 @@ Repeat connection request?</source>
|
|||
<target>месеци</target>
|
||||
<note>time unit</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="mute" xml:space="preserve">
|
||||
<source>mute</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="never" xml:space="preserve">
|
||||
<source>never</source>
|
||||
<target>никога</target>
|
||||
|
@ -9096,6 +9272,14 @@ Repeat connection request?</source>
|
|||
<target>peer-to-peer</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="pending" xml:space="preserve">
|
||||
<source>pending</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="pending approval" xml:space="preserve">
|
||||
<source>pending approval</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="quantum resistant e2e encryption" xml:space="preserve">
|
||||
<source>quantum resistant e2e encryption</source>
|
||||
<target>квантово устойчиво e2e криптиране</target>
|
||||
|
@ -9111,6 +9295,10 @@ Repeat connection request?</source>
|
|||
<target>получено потвърждение…</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="rejected" xml:space="preserve">
|
||||
<source>rejected</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="rejected call" xml:space="preserve">
|
||||
<source>rejected call</source>
|
||||
<target>отхвърлено повикване</target>
|
||||
|
@ -9239,10 +9427,6 @@ last received msg: %2$@</source>
|
|||
<target>неизвестен статус</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="unmute" xml:space="preserve">
|
||||
<source>unmute</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="unprotected" xml:space="preserve">
|
||||
<source>unprotected</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
|
|
@ -5,22 +5,6 @@
|
|||
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.4" build-num="15F31d"/>
|
||||
</header>
|
||||
<body>
|
||||
<trans-unit id=" " xml:space="preserve">
|
||||
<source>
|
||||
</source>
|
||||
<target>
|
||||
</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=" " xml:space="preserve">
|
||||
<source> </source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=" (" xml:space="preserve">
|
||||
<source> (</source>
|
||||
<target> (</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=" (can be copied)" xml:space="preserve">
|
||||
<source> (can be copied)</source>
|
||||
<target> (lze kopírovat)</target>
|
||||
|
@ -321,11 +305,6 @@
|
|||
<target>%u zpráv přeskočeno.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="(" xml:space="preserve">
|
||||
<source>(</source>
|
||||
<target>(</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="(new)" xml:space="preserve">
|
||||
<source>(new)</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -335,11 +314,6 @@
|
|||
<target>(toto zařízení v%@)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=")" xml:space="preserve">
|
||||
<source>)</source>
|
||||
<target>)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="**Create 1-time link**: to create and share a new invitation link." xml:space="preserve">
|
||||
<source>**Create 1-time link**: to create and share a new invitation link.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -400,11 +374,6 @@
|
|||
<target>\*tučně*</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=", " xml:space="preserve">
|
||||
<source>, </source>
|
||||
<target>, </target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="- connect to [directory service](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (BETA)! - delivery receipts (up to 20 members). - faster and more stable." xml:space="preserve">
|
||||
<source>- connect to [directory service](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (BETA)!
|
||||
- delivery receipts (up to 20 members).
|
||||
|
@ -438,11 +407,6 @@
|
|||
- historie úprav.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="." xml:space="preserve">
|
||||
<source>.</source>
|
||||
<target>.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="0 sec" xml:space="preserve">
|
||||
<source>0 sec</source>
|
||||
<note>time to disappear</note>
|
||||
|
@ -507,11 +471,6 @@
|
|||
<target>30 vteřin</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=": " xml:space="preserve">
|
||||
<source>: </source>
|
||||
<target>: </target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="<p>Hi!</p> <p><a href="%@">Connect to me via SimpleX Chat</a></p>" xml:space="preserve">
|
||||
<source><p>Hi!</p>
|
||||
<p><a href="%@">Connect to me via SimpleX Chat</a></p></source>
|
||||
|
@ -613,6 +572,10 @@
|
|||
<source>Acknowledgement errors</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Active" xml:space="preserve">
|
||||
<source>Active</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Active connections" xml:space="preserve">
|
||||
<source>Active connections</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -737,8 +700,8 @@
|
|||
<target>Všechny chaty a zprávy budou smazány – tuto akci nelze vrátit zpět!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All chats will be removed from the list (text), and the list deleted." xml:space="preserve">
|
||||
<source>All chats will be removed from the list (text), and the list deleted.</source>
|
||||
<trans-unit id="All chats will be removed from the list %@, and the list deleted." xml:space="preserve">
|
||||
<source>All chats will be removed from the list %@, and the list deleted.</source>
|
||||
<note>alert message</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All data is erased when it is entered." xml:space="preserve">
|
||||
|
@ -776,6 +739,10 @@
|
|||
<source>All profiles</source>
|
||||
<note>profile dropdown</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All reports will be archived for you." xml:space="preserve">
|
||||
<source>All reports will be archived for you.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
||||
<source>All your contacts will remain connected.</source>
|
||||
<target>Všechny vaše kontakty zůstanou připojeny.</target>
|
||||
|
@ -847,6 +814,10 @@
|
|||
<target>Povolit nevratné smazání odeslaných zpráv. (24 hodin)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Allow to report messsages to moderators." xml:space="preserve">
|
||||
<source>Allow to report messsages to moderators.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Allow to send SimpleX links." xml:space="preserve">
|
||||
<source>Allow to send SimpleX links.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -1001,6 +972,14 @@
|
|||
<source>Archive</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive %lld reports?" xml:space="preserve">
|
||||
<source>Archive %lld reports?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive all reports?" xml:space="preserve">
|
||||
<source>Archive all reports?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive and upload" xml:space="preserve">
|
||||
<source>Archive and upload</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -1017,6 +996,10 @@
|
|||
<source>Archive report?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive reports" xml:space="preserve">
|
||||
<source>Archive reports</source>
|
||||
<note>swipe action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archived contacts" xml:space="preserve">
|
||||
<source>Archived contacts</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -1124,6 +1107,10 @@
|
|||
<source>Better groups</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better groups performance" xml:space="preserve">
|
||||
<source>Better groups performance</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better message dates." xml:space="preserve">
|
||||
<source>Better message dates.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -1141,6 +1128,10 @@
|
|||
<source>Better notifications</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better privacy and security" xml:space="preserve">
|
||||
<source>Better privacy and security</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better security ✅" xml:space="preserve">
|
||||
<source>Better security ✅</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -1519,6 +1510,10 @@
|
|||
<target>Vyčistit konverzaci?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Clear group?" xml:space="preserve">
|
||||
<source>Clear group?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Clear or delete group?" xml:space="preserve">
|
||||
<source>Clear or delete group?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -1644,6 +1639,10 @@
|
|||
<source>Confirm upload</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Confirmed" xml:space="preserve">
|
||||
<source>Confirmed</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Connect" xml:space="preserve">
|
||||
<source>Connect</source>
|
||||
<target>Připojit</target>
|
||||
|
@ -2571,6 +2570,10 @@ This is your own one-time link!</source>
|
|||
<target>Nepovolovat</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Don't miss important messages." xml:space="preserve">
|
||||
<source>Don't miss important messages.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Don't show again" xml:space="preserve">
|
||||
<source>Don't show again</source>
|
||||
<target>Znovu neukazuj</target>
|
||||
|
@ -2900,6 +2903,10 @@ This is your own one-time link!</source>
|
|||
<source>Error changing to incognito!</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error checking token status" xml:space="preserve">
|
||||
<source>Error checking token status</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error connecting to forwarding server %@. Please try later." xml:space="preserve">
|
||||
<source>Error connecting to forwarding server %@. Please try later.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -3044,6 +3051,10 @@ This is your own one-time link!</source>
|
|||
<source>Error reconnecting servers</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error registering for notifications" xml:space="preserve">
|
||||
<source>Error registering for notifications</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error removing member" xml:space="preserve">
|
||||
<source>Error removing member</source>
|
||||
<target>Chyba při odebrání člena</target>
|
||||
|
@ -3142,6 +3153,10 @@ This is your own one-time link!</source>
|
|||
<target>Chyba synchronizace připojení</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error testing server connection" xml:space="preserve">
|
||||
<source>Error testing server connection</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error updating group link" xml:space="preserve">
|
||||
<source>Error updating group link</source>
|
||||
<target>Chyba aktualizace odkazu skupiny</target>
|
||||
|
@ -3216,6 +3231,10 @@ This is your own one-time link!</source>
|
|||
<source>Expand</source>
|
||||
<note>chat item action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Expired" xml:space="preserve">
|
||||
<source>Expired</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Export database" xml:space="preserve">
|
||||
<source>Export database</source>
|
||||
<target>Export databáze</target>
|
||||
|
@ -3254,10 +3273,18 @@ This is your own one-time link!</source>
|
|||
<target>Rychle a bez čekání, než bude odesílatel online!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Faster deletion of groups." xml:space="preserve">
|
||||
<source>Faster deletion of groups.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Faster joining and more reliable messages." xml:space="preserve">
|
||||
<source>Faster joining and more reliable messages.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Faster sending messages." xml:space="preserve">
|
||||
<source>Faster sending messages.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Favorite" xml:space="preserve">
|
||||
<source>Favorite</source>
|
||||
<target>Oblíbené</target>
|
||||
|
@ -3276,9 +3303,9 @@ This is your own one-time link!</source>
|
|||
%@</source>
|
||||
<note>alert message</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="File is blocked by server operator: (info.reason.text)." xml:space="preserve">
|
||||
<trans-unit id="File is blocked by server operator: %@." xml:space="preserve">
|
||||
<source>File is blocked by server operator:
|
||||
(info.reason.text).</source>
|
||||
%@.</source>
|
||||
<note>file error text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="File not found - most likely file was deleted or cancelled." xml:space="preserve">
|
||||
|
@ -3398,6 +3425,10 @@ This is your own one-time link!</source>
|
|||
<target>Opravit nepodporované členem skupiny</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For all moderators" xml:space="preserve">
|
||||
<source>For all moderators</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For chat profile %@:" xml:space="preserve">
|
||||
<source>For chat profile %@:</source>
|
||||
<note>servers error</note>
|
||||
|
@ -3411,6 +3442,10 @@ This is your own one-time link!</source>
|
|||
<source>For example, if your contact receives messages via a SimpleX Chat server, your app will deliver them via a Flux server.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For me" xml:space="preserve">
|
||||
<source>For me</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For private routing" xml:space="preserve">
|
||||
<source>For private routing</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -3515,6 +3550,10 @@ Error: %2$@</source>
|
|||
<target>GIFy a nálepky</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Get notified when mentioned." xml:space="preserve">
|
||||
<source>Get notified when mentioned.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Good afternoon!" xml:space="preserve">
|
||||
<source>Good afternoon!</source>
|
||||
<note>message preview</note>
|
||||
|
@ -3625,6 +3664,10 @@ Error: %2$@</source>
|
|||
<target>Pomoc</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Help admins moderating their groups." xml:space="preserve">
|
||||
<source>Help admins moderating their groups.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Hidden" xml:space="preserve">
|
||||
<source>Hidden</source>
|
||||
<target>Skryté</target>
|
||||
|
@ -3915,6 +3958,26 @@ More improvements are coming soon!</source>
|
|||
<source>Interface colors</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid" xml:space="preserve">
|
||||
<source>Invalid</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (bad token)" xml:space="preserve">
|
||||
<source>Invalid (bad token)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (expired)" xml:space="preserve">
|
||||
<source>Invalid (expired)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (unregistered)" xml:space="preserve">
|
||||
<source>Invalid (unregistered)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (wrong topic)" xml:space="preserve">
|
||||
<source>Invalid (wrong topic)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid QR code" xml:space="preserve">
|
||||
<source>Invalid QR code</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -4265,6 +4328,10 @@ This is your link for group %@!</source>
|
|||
<source>Member inactive</source>
|
||||
<note>item status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Member reports" xml:space="preserve">
|
||||
<source>Member reports</source>
|
||||
<note>chat feature</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Member role will be changed to "%@". All chat members will be notified." xml:space="preserve">
|
||||
<source>Member role will be changed to "%@". All chat members will be notified.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -4298,6 +4365,10 @@ This is your link for group %@!</source>
|
|||
<target>Členové skupiny mohou nevratně mazat odeslané zprávy. (24 hodin)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Members can report messsages to moderators." xml:space="preserve">
|
||||
<source>Members can report messsages to moderators.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Members can send SimpleX links." xml:space="preserve">
|
||||
<source>Members can send SimpleX links.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -4322,6 +4393,10 @@ This is your link for group %@!</source>
|
|||
<target>Členové skupiny mohou posílat hlasové zprávy.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Mention members 👋" xml:space="preserve">
|
||||
<source>Mention members 👋</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Menus" xml:space="preserve">
|
||||
<source>Menus</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -4541,7 +4616,11 @@ This is your link for group %@!</source>
|
|||
<trans-unit id="Mute" xml:space="preserve">
|
||||
<source>Mute</source>
|
||||
<target>Ztlumit</target>
|
||||
<note>swipe action</note>
|
||||
<note>notification label action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Mute all" xml:space="preserve">
|
||||
<source>Mute all</source>
|
||||
<note>notification label action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Muted when inactive!" xml:space="preserve">
|
||||
<source>Muted when inactive!</source>
|
||||
|
@ -4588,6 +4667,10 @@ This is your link for group %@!</source>
|
|||
<target>Stav sítě</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="New" xml:space="preserve">
|
||||
<source>New</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="New Passcode" xml:space="preserve">
|
||||
<source>New Passcode</source>
|
||||
<target>Nové heslo</target>
|
||||
|
@ -4730,6 +4813,10 @@ This is your link for group %@!</source>
|
|||
<source>No media & file servers.</source>
|
||||
<note>servers error</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No message" xml:space="preserve">
|
||||
<source>No message</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No message servers." xml:space="preserve">
|
||||
<source>No message servers.</source>
|
||||
<note>servers error</note>
|
||||
|
@ -4777,6 +4864,10 @@ This is your link for group %@!</source>
|
|||
<source>No servers to send files.</source>
|
||||
<note>servers error</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No token!" xml:space="preserve">
|
||||
<source>No token!</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No unread chats" xml:space="preserve">
|
||||
<source>No unread chats</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -4812,10 +4903,18 @@ This is your link for group %@!</source>
|
|||
<target>Oznámení jsou zakázána!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Notifications error" xml:space="preserve">
|
||||
<source>Notifications error</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Notifications privacy" xml:space="preserve">
|
||||
<source>Notifications privacy</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Notifications status" xml:space="preserve">
|
||||
<source>Notifications status</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Now admins can: - delete members' messages. - disable members ("observer" role)" xml:space="preserve">
|
||||
<source>Now admins can:
|
||||
- delete members' messages.
|
||||
|
@ -5038,6 +5137,10 @@ Vyžaduje povolení sítě VPN.</target>
|
|||
<source>Or to share privately</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Organize chats into lists" xml:space="preserve">
|
||||
<source>Organize chats into lists</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Other" xml:space="preserve">
|
||||
<source>Other</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -5212,6 +5315,18 @@ Error: %@</source>
|
|||
<target>Heslo uložte bezpečně, v případě jeho ztráty jej NEBUDE možné změnit.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please try to disable and re-enable notfications." xml:space="preserve">
|
||||
<source>Please try to disable and re-enable notfications.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please wait for token activation to complete." xml:space="preserve">
|
||||
<source>Please wait for token activation to complete.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please wait for token to be registered." xml:space="preserve">
|
||||
<source>Please wait for token to be registered.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Polish interface" xml:space="preserve">
|
||||
<source>Polish interface</source>
|
||||
<target>Polské rozhraní</target>
|
||||
|
@ -5268,6 +5383,10 @@ Error: %@</source>
|
|||
<target>Soukromé názvy souborů</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Private media file names." xml:space="preserve">
|
||||
<source>Private media file names.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Private message routing" xml:space="preserve">
|
||||
<source>Private message routing</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -5336,6 +5455,10 @@ Error: %@</source>
|
|||
<target>Zakázat reakce na zprávy.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Prohibit reporting messages to moderators." xml:space="preserve">
|
||||
<source>Prohibit reporting messages to moderators.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Prohibit sending SimpleX links." xml:space="preserve">
|
||||
<source>Prohibit sending SimpleX links.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -5571,6 +5694,18 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>Snížení spotřeby baterie</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Register" xml:space="preserve">
|
||||
<source>Register</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Register notification token?" xml:space="preserve">
|
||||
<source>Register notification token?</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Registered" xml:space="preserve">
|
||||
<source>Registered</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Reject" xml:space="preserve">
|
||||
<source>Reject</source>
|
||||
<target>Odmítnout</target>
|
||||
|
@ -5693,6 +5828,14 @@ Enable in *Network & servers* settings.</source>
|
|||
<source>Report violation: only group moderators will see it.</source>
|
||||
<note>report reason</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Report: %@" xml:space="preserve">
|
||||
<source>Report: %@</source>
|
||||
<note>report in notification</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Reporting messages to moderators is prohibited." xml:space="preserve">
|
||||
<source>Reporting messages to moderators is prohibited.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Reports" xml:space="preserve">
|
||||
<source>Reports</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -6085,6 +6228,10 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>Odeslat oznámení</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Send private reports" xml:space="preserve">
|
||||
<source>Send private reports</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Send questions and ideas" xml:space="preserve">
|
||||
<source>Send questions and ideas</source>
|
||||
<target>Zasílání otázek a nápadů</target>
|
||||
|
@ -6303,6 +6450,10 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>Nastavte jej namísto ověřování systému.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Set message expiration in chats." xml:space="preserve">
|
||||
<source>Set message expiration in chats.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Set passcode" xml:space="preserve">
|
||||
<source>Set passcode</source>
|
||||
<target>Nastavit heslo</target>
|
||||
|
@ -6724,6 +6875,10 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>Časový limit připojení TCP</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="TCP port for messaging" xml:space="preserve">
|
||||
<source>TCP port for messaging</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="TCP_KEEPCNT" xml:space="preserve">
|
||||
<source>TCP_KEEPCNT</source>
|
||||
<target>TCP_KEEPCNT</target>
|
||||
|
@ -6793,6 +6948,10 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>Test selhal v kroku %@.</target>
|
||||
<note>server test failure</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Test notifications" xml:space="preserve">
|
||||
<source>Test notifications</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Test server" xml:space="preserve">
|
||||
<source>Test server</source>
|
||||
<target>Testovací server</target>
|
||||
|
@ -6914,10 +7073,6 @@ Může se to stát kvůli nějaké chybě, nebo pokud je spojení kompromitován
|
|||
<target>Profil je sdílen pouze s vašimi kontakty.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="The report will be archived for you." xml:space="preserve">
|
||||
<source>The report will be archived for you.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve">
|
||||
<source>The same conditions will apply to operator **%@**.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -7032,6 +7187,10 @@ Může se to stát kvůli nějaké chybě, nebo pokud je spojení kompromitován
|
|||
<source>This link was used with another mobile device, please create a new link on the desktop.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="This message was deleted or not received yet." xml:space="preserve">
|
||||
<source>This message was deleted or not received yet.</source>
|
||||
<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">
|
||||
<source>This setting applies to messages in your current chat profile **%@**.</source>
|
||||
<target>Toto nastavení platí pro zprávy ve vašem aktuálním chat profilu **%@**.</target>
|
||||
|
@ -7134,6 +7293,10 @@ Před zapnutím této funkce budete vyzváni k dokončení ověření.</target>
|
|||
<target>Změnit inkognito režim při připojení.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Token status: %@." xml:space="preserve">
|
||||
<source>Token status: %@.</source>
|
||||
<note>token status</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Toolbar opacity" xml:space="preserve">
|
||||
<source>Toolbar opacity</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -7286,7 +7449,7 @@ Chcete-li se připojit, požádejte svůj kontakt o vytvoření dalšího odkazu
|
|||
<trans-unit id="Unmute" xml:space="preserve">
|
||||
<source>Unmute</source>
|
||||
<target>Zrušit ztlumení</target>
|
||||
<note>swipe action</note>
|
||||
<note>notification label action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Unread" xml:space="preserve">
|
||||
<source>Unread</source>
|
||||
|
@ -7316,6 +7479,10 @@ Chcete-li se připojit, požádejte svůj kontakt o vytvoření dalšího odkazu
|
|||
<source>Update settings?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Updated conditions" xml:space="preserve">
|
||||
<source>Updated conditions</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Updating settings will re-connect the client to all servers." xml:space="preserve">
|
||||
<source>Updating settings will re-connect the client to all servers.</source>
|
||||
<target>Aktualizací nastavení se klient znovu připojí ke všem serverům.</target>
|
||||
|
@ -7369,6 +7536,10 @@ Chcete-li se připojit, požádejte svůj kontakt o vytvoření dalšího odkazu
|
|||
<target>Používat servery SimpleX Chat?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use TCP port %@ when no port is specified." xml:space="preserve">
|
||||
<source>Use TCP port %@ when no port is specified.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use chat" xml:space="preserve">
|
||||
<source>Use chat</source>
|
||||
<target>Použijte chat</target>
|
||||
|
@ -7435,6 +7606,10 @@ Chcete-li se připojit, požádejte svůj kontakt o vytvoření dalšího odkazu
|
|||
<source>Use the app with one hand.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use web port" xml:space="preserve">
|
||||
<source>Use web port</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="User selection" xml:space="preserve">
|
||||
<source>User selection</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -7933,6 +8108,10 @@ Repeat connection request?</source>
|
|||
<target>Odeslali jste pozvánku do skupiny</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="You should receive notifications." xml:space="preserve">
|
||||
<source>You should receive notifications.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="You will be connected to group when the group host's device is online, please wait or check later!" xml:space="preserve">
|
||||
<source>You will be connected to group when the group host's device is online, please wait or check later!</source>
|
||||
<target>Ke skupině budete připojeni, až bude zařízení hostitele skupiny online, vyčkejte prosím nebo se podívejte později!</target>
|
||||
|
@ -8696,10 +8875,6 @@ Repeat connection request?</source>
|
|||
<target>měsíců</target>
|
||||
<note>time unit</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="mute" xml:space="preserve">
|
||||
<source>mute</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="never" xml:space="preserve">
|
||||
<source>never</source>
|
||||
<target>nikdy</target>
|
||||
|
@ -8774,6 +8949,14 @@ Repeat connection request?</source>
|
|||
<target>peer-to-peer</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="pending" xml:space="preserve">
|
||||
<source>pending</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="pending approval" xml:space="preserve">
|
||||
<source>pending approval</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="quantum resistant e2e encryption" xml:space="preserve">
|
||||
<source>quantum resistant e2e encryption</source>
|
||||
<note>chat item text</note>
|
||||
|
@ -8788,6 +8971,10 @@ Repeat connection request?</source>
|
|||
<target>obdržel potvrzení…</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="rejected" xml:space="preserve">
|
||||
<source>rejected</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="rejected call" xml:space="preserve">
|
||||
<source>rejected call</source>
|
||||
<target>odmítnutý hovor</target>
|
||||
|
@ -8907,10 +9094,6 @@ last received msg: %2$@</source>
|
|||
<source>unknown status</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="unmute" xml:space="preserve">
|
||||
<source>unmute</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="unprotected" xml:space="preserve">
|
||||
<source>unprotected</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -5,23 +5,6 @@
|
|||
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.4" build-num="15F31d"/>
|
||||
</header>
|
||||
<body>
|
||||
<trans-unit id=" " xml:space="preserve">
|
||||
<source>
|
||||
</source>
|
||||
<target>
|
||||
</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=" " xml:space="preserve">
|
||||
<source> </source>
|
||||
<target> </target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=" (" xml:space="preserve">
|
||||
<source> (</source>
|
||||
<target> (</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=" (can be copied)" xml:space="preserve">
|
||||
<source> (can be copied)</source>
|
||||
<target> (can be copied)</target>
|
||||
|
@ -332,11 +315,6 @@
|
|||
<target>%u messages skipped.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="(" xml:space="preserve">
|
||||
<source>(</source>
|
||||
<target>(</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="(new)" xml:space="preserve">
|
||||
<source>(new)</source>
|
||||
<target>(new)</target>
|
||||
|
@ -347,11 +325,6 @@
|
|||
<target>(this device v%@)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=")" xml:space="preserve">
|
||||
<source>)</source>
|
||||
<target>)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="**Create 1-time link**: to create and share a new invitation link." xml:space="preserve">
|
||||
<source>**Create 1-time link**: to create and share a new invitation link.</source>
|
||||
<target>**Create 1-time link**: to create and share a new invitation link.</target>
|
||||
|
@ -417,11 +390,6 @@
|
|||
<target>\*bold*</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=", " xml:space="preserve">
|
||||
<source>, </source>
|
||||
<target>, </target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="- connect to [directory service](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (BETA)! - delivery receipts (up to 20 members). - faster and more stable." xml:space="preserve">
|
||||
<source>- connect to [directory service](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (BETA)!
|
||||
- delivery receipts (up to 20 members).
|
||||
|
@ -458,11 +426,6 @@
|
|||
- editing history.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="." xml:space="preserve">
|
||||
<source>.</source>
|
||||
<target>.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="0 sec" xml:space="preserve">
|
||||
<source>0 sec</source>
|
||||
<target>0 sec</target>
|
||||
|
@ -531,11 +494,6 @@
|
|||
<target>30 seconds</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=": " xml:space="preserve">
|
||||
<source>: </source>
|
||||
<target>: </target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="<p>Hi!</p> <p><a href="%@">Connect to me via SimpleX Chat</a></p>" xml:space="preserve">
|
||||
<source><p>Hi!</p>
|
||||
<p><a href="%@">Connect to me via SimpleX Chat</a></p></source>
|
||||
|
@ -643,6 +601,11 @@
|
|||
<target>Acknowledgement errors</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Active" xml:space="preserve">
|
||||
<source>Active</source>
|
||||
<target>Active</target>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Active connections" xml:space="preserve">
|
||||
<source>Active connections</source>
|
||||
<target>Active connections</target>
|
||||
|
@ -783,9 +746,9 @@
|
|||
<target>All chats and messages will be deleted - this cannot be undone!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All chats will be removed from the list (text), and the list deleted." xml:space="preserve">
|
||||
<source>All chats will be removed from the list (text), and the list deleted.</source>
|
||||
<target>All chats will be removed from the list (text), and the list deleted.</target>
|
||||
<trans-unit id="All chats will be removed from the list %@, and the list deleted." xml:space="preserve">
|
||||
<source>All chats will be removed from the list %@, and the list deleted.</source>
|
||||
<target>All chats will be removed from the list %@, and the list deleted.</target>
|
||||
<note>alert message</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All data is erased when it is entered." xml:space="preserve">
|
||||
|
@ -828,6 +791,11 @@
|
|||
<target>All profiles</target>
|
||||
<note>profile dropdown</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All reports will be archived for you." xml:space="preserve">
|
||||
<source>All reports will be archived for you.</source>
|
||||
<target>All reports will be archived for you.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
||||
<source>All your contacts will remain connected.</source>
|
||||
<target>All your contacts will remain connected.</target>
|
||||
|
@ -903,6 +871,11 @@
|
|||
<target>Allow to irreversibly delete sent messages. (24 hours)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Allow to report messsages to moderators." xml:space="preserve">
|
||||
<source>Allow to report messsages to moderators.</source>
|
||||
<target>Allow to report messsages to moderators.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Allow to send SimpleX links." xml:space="preserve">
|
||||
<source>Allow to send SimpleX links.</source>
|
||||
<target>Allow to send SimpleX links.</target>
|
||||
|
@ -1068,6 +1041,16 @@
|
|||
<target>Archive</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive %lld reports?" xml:space="preserve">
|
||||
<source>Archive %lld reports?</source>
|
||||
<target>Archive %lld reports?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive all reports?" xml:space="preserve">
|
||||
<source>Archive all reports?</source>
|
||||
<target>Archive all reports?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive and upload" xml:space="preserve">
|
||||
<source>Archive and upload</source>
|
||||
<target>Archive and upload</target>
|
||||
|
@ -1088,6 +1071,11 @@
|
|||
<target>Archive report?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive reports" xml:space="preserve">
|
||||
<source>Archive reports</source>
|
||||
<target>Archive reports</target>
|
||||
<note>swipe action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archived contacts" xml:space="preserve">
|
||||
<source>Archived contacts</source>
|
||||
<target>Archived contacts</target>
|
||||
|
@ -1203,6 +1191,11 @@
|
|||
<target>Better groups</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better groups performance" xml:space="preserve">
|
||||
<source>Better groups performance</source>
|
||||
<target>Better groups performance</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better message dates." xml:space="preserve">
|
||||
<source>Better message dates.</source>
|
||||
<target>Better message dates.</target>
|
||||
|
@ -1223,6 +1216,11 @@
|
|||
<target>Better notifications</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better privacy and security" xml:space="preserve">
|
||||
<source>Better privacy and security</source>
|
||||
<target>Better privacy and security</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better security ✅" xml:space="preserve">
|
||||
<source>Better security ✅</source>
|
||||
<target>Better security ✅</target>
|
||||
|
@ -1645,6 +1643,11 @@
|
|||
<target>Clear conversation?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Clear group?" xml:space="preserve">
|
||||
<source>Clear group?</source>
|
||||
<target>Clear group?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Clear or delete group?" xml:space="preserve">
|
||||
<source>Clear or delete group?</source>
|
||||
<target>Clear or delete group?</target>
|
||||
|
@ -1790,6 +1793,11 @@
|
|||
<target>Confirm upload</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Confirmed" xml:space="preserve">
|
||||
<source>Confirmed</source>
|
||||
<target>Confirmed</target>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Connect" xml:space="preserve">
|
||||
<source>Connect</source>
|
||||
<target>Connect</target>
|
||||
|
@ -2805,6 +2813,11 @@ This is your own one-time link!</target>
|
|||
<target>Don't enable</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Don't miss important messages." xml:space="preserve">
|
||||
<source>Don't miss important messages.</source>
|
||||
<target>Don't miss important messages.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Don't show again" xml:space="preserve">
|
||||
<source>Don't show again</source>
|
||||
<target>Don't show again</target>
|
||||
|
@ -3161,6 +3174,11 @@ This is your own one-time link!</target>
|
|||
<target>Error changing to incognito!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error checking token status" xml:space="preserve">
|
||||
<source>Error checking token status</source>
|
||||
<target>Error checking token status</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error connecting to forwarding server %@. Please try later." xml:space="preserve">
|
||||
<source>Error connecting to forwarding server %@. Please try later.</source>
|
||||
<target>Error connecting to forwarding server %@. Please try later.</target>
|
||||
|
@ -3316,6 +3334,11 @@ This is your own one-time link!</target>
|
|||
<target>Error reconnecting servers</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error registering for notifications" xml:space="preserve">
|
||||
<source>Error registering for notifications</source>
|
||||
<target>Error registering for notifications</target>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error removing member" xml:space="preserve">
|
||||
<source>Error removing member</source>
|
||||
<target>Error removing member</target>
|
||||
|
@ -3421,6 +3444,11 @@ This is your own one-time link!</target>
|
|||
<target>Error synchronizing connection</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error testing server connection" xml:space="preserve">
|
||||
<source>Error testing server connection</source>
|
||||
<target>Error testing server connection</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error updating group link" xml:space="preserve">
|
||||
<source>Error updating group link</source>
|
||||
<target>Error updating group link</target>
|
||||
|
@ -3501,6 +3529,11 @@ This is your own one-time link!</target>
|
|||
<target>Expand</target>
|
||||
<note>chat item action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Expired" xml:space="preserve">
|
||||
<source>Expired</source>
|
||||
<target>Expired</target>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Export database" xml:space="preserve">
|
||||
<source>Export database</source>
|
||||
<target>Export database</target>
|
||||
|
@ -3541,11 +3574,21 @@ This is your own one-time link!</target>
|
|||
<target>Fast and no wait until the sender is online!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Faster deletion of groups." xml:space="preserve">
|
||||
<source>Faster deletion of groups.</source>
|
||||
<target>Faster deletion of groups.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Faster joining and more reliable messages." xml:space="preserve">
|
||||
<source>Faster joining and more reliable messages.</source>
|
||||
<target>Faster joining and more reliable messages.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Faster sending messages." xml:space="preserve">
|
||||
<source>Faster sending messages.</source>
|
||||
<target>Faster sending messages.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Favorite" xml:space="preserve">
|
||||
<source>Favorite</source>
|
||||
<target>Favorite</target>
|
||||
|
@ -3568,11 +3611,11 @@ This is your own one-time link!</target>
|
|||
%@</target>
|
||||
<note>alert message</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="File is blocked by server operator: (info.reason.text)." xml:space="preserve">
|
||||
<trans-unit id="File is blocked by server operator: %@." xml:space="preserve">
|
||||
<source>File is blocked by server operator:
|
||||
(info.reason.text).</source>
|
||||
%@.</source>
|
||||
<target>File is blocked by server operator:
|
||||
(info.reason.text).</target>
|
||||
%@.</target>
|
||||
<note>file error text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="File not found - most likely file was deleted or cancelled." xml:space="preserve">
|
||||
|
@ -3700,6 +3743,11 @@ This is your own one-time link!</target>
|
|||
<target>Fix not supported by group member</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For all moderators" xml:space="preserve">
|
||||
<source>For all moderators</source>
|
||||
<target>For all moderators</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For chat profile %@:" xml:space="preserve">
|
||||
<source>For chat profile %@:</source>
|
||||
<target>For chat profile %@:</target>
|
||||
|
@ -3715,6 +3763,11 @@ This is your own one-time link!</target>
|
|||
<target>For example, if your contact receives messages via a SimpleX Chat server, your app will deliver them via a Flux server.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For me" xml:space="preserve">
|
||||
<source>For me</source>
|
||||
<target>For me</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For private routing" xml:space="preserve">
|
||||
<source>For private routing</source>
|
||||
<target>For private routing</target>
|
||||
|
@ -3839,6 +3892,11 @@ Error: %2$@</target>
|
|||
<target>GIFs and stickers</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Get notified when mentioned." xml:space="preserve">
|
||||
<source>Get notified when mentioned.</source>
|
||||
<target>Get notified when mentioned.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Good afternoon!" xml:space="preserve">
|
||||
<source>Good afternoon!</source>
|
||||
<target>Good afternoon!</target>
|
||||
|
@ -3954,6 +4012,11 @@ Error: %2$@</target>
|
|||
<target>Help</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Help admins moderating their groups." xml:space="preserve">
|
||||
<source>Help admins moderating their groups.</source>
|
||||
<target>Help admins moderating their groups.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Hidden" xml:space="preserve">
|
||||
<source>Hidden</source>
|
||||
<target>Hidden</target>
|
||||
|
@ -4263,6 +4326,31 @@ More improvements are coming soon!</target>
|
|||
<target>Interface colors</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid" xml:space="preserve">
|
||||
<source>Invalid</source>
|
||||
<target>Invalid</target>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (bad token)" xml:space="preserve">
|
||||
<source>Invalid (bad token)</source>
|
||||
<target>Invalid (bad token)</target>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (expired)" xml:space="preserve">
|
||||
<source>Invalid (expired)</source>
|
||||
<target>Invalid (expired)</target>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (unregistered)" xml:space="preserve">
|
||||
<source>Invalid (unregistered)</source>
|
||||
<target>Invalid (unregistered)</target>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (wrong topic)" xml:space="preserve">
|
||||
<source>Invalid (wrong topic)</source>
|
||||
<target>Invalid (wrong topic)</target>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid QR code" xml:space="preserve">
|
||||
<source>Invalid QR code</source>
|
||||
<target>Invalid QR code</target>
|
||||
|
@ -4641,6 +4729,11 @@ This is your link for group %@!</target>
|
|||
<target>Member inactive</target>
|
||||
<note>item status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Member reports" xml:space="preserve">
|
||||
<source>Member reports</source>
|
||||
<target>Member reports</target>
|
||||
<note>chat feature</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Member role will be changed to "%@". All chat members will be notified." xml:space="preserve">
|
||||
<source>Member role will be changed to "%@". All chat members will be notified.</source>
|
||||
<target>Member role will be changed to "%@". All chat members will be notified.</target>
|
||||
|
@ -4676,6 +4769,11 @@ This is your link for group %@!</target>
|
|||
<target>Members can irreversibly delete sent messages. (24 hours)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Members can report messsages to moderators." xml:space="preserve">
|
||||
<source>Members can report messsages to moderators.</source>
|
||||
<target>Members can report messsages to moderators.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Members can send SimpleX links." xml:space="preserve">
|
||||
<source>Members can send SimpleX links.</source>
|
||||
<target>Members can send SimpleX links.</target>
|
||||
|
@ -4701,6 +4799,11 @@ This is your link for group %@!</target>
|
|||
<target>Members can send voice messages.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Mention members 👋" xml:space="preserve">
|
||||
<source>Mention members 👋</source>
|
||||
<target>Mention members 👋</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Menus" xml:space="preserve">
|
||||
<source>Menus</source>
|
||||
<target>Menus</target>
|
||||
|
@ -4949,7 +5052,12 @@ This is your link for group %@!</target>
|
|||
<trans-unit id="Mute" xml:space="preserve">
|
||||
<source>Mute</source>
|
||||
<target>Mute</target>
|
||||
<note>swipe action</note>
|
||||
<note>notification label action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Mute all" xml:space="preserve">
|
||||
<source>Mute all</source>
|
||||
<target>Mute all</target>
|
||||
<note>notification label action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Muted when inactive!" xml:space="preserve">
|
||||
<source>Muted when inactive!</source>
|
||||
|
@ -5001,6 +5109,11 @@ This is your link for group %@!</target>
|
|||
<target>Network status</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="New" xml:space="preserve">
|
||||
<source>New</source>
|
||||
<target>New</target>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="New Passcode" xml:space="preserve">
|
||||
<source>New Passcode</source>
|
||||
<target>New Passcode</target>
|
||||
|
@ -5156,6 +5269,11 @@ This is your link for group %@!</target>
|
|||
<target>No media & file servers.</target>
|
||||
<note>servers error</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No message" xml:space="preserve">
|
||||
<source>No message</source>
|
||||
<target>No message</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No message servers." xml:space="preserve">
|
||||
<source>No message servers.</source>
|
||||
<target>No message servers.</target>
|
||||
|
@ -5211,6 +5329,11 @@ This is your link for group %@!</target>
|
|||
<target>No servers to send files.</target>
|
||||
<note>servers error</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No token!" xml:space="preserve">
|
||||
<source>No token!</source>
|
||||
<target>No token!</target>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No unread chats" xml:space="preserve">
|
||||
<source>No unread chats</source>
|
||||
<target>No unread chats</target>
|
||||
|
@ -5251,11 +5374,21 @@ This is your link for group %@!</target>
|
|||
<target>Notifications are disabled!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Notifications error" xml:space="preserve">
|
||||
<source>Notifications error</source>
|
||||
<target>Notifications error</target>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Notifications privacy" xml:space="preserve">
|
||||
<source>Notifications privacy</source>
|
||||
<target>Notifications privacy</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Notifications status" xml:space="preserve">
|
||||
<source>Notifications status</source>
|
||||
<target>Notifications status</target>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Now admins can: - delete members' messages. - disable members ("observer" role)" xml:space="preserve">
|
||||
<source>Now admins can:
|
||||
- delete members' messages.
|
||||
|
@ -5499,6 +5632,11 @@ Requires compatible VPN.</target>
|
|||
<target>Or to share privately</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Organize chats into lists" xml:space="preserve">
|
||||
<source>Organize chats into lists</source>
|
||||
<target>Organize chats into lists</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Other" xml:space="preserve">
|
||||
<source>Other</source>
|
||||
<target>Other</target>
|
||||
|
@ -5690,6 +5828,21 @@ Error: %@</target>
|
|||
<target>Please store passphrase securely, you will NOT be able to change it if you lose it.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please try to disable and re-enable notfications." xml:space="preserve">
|
||||
<source>Please try to disable and re-enable notfications.</source>
|
||||
<target>Please try to disable and re-enable notfications.</target>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please wait for token activation to complete." xml:space="preserve">
|
||||
<source>Please wait for token activation to complete.</source>
|
||||
<target>Please wait for token activation to complete.</target>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please wait for token to be registered." xml:space="preserve">
|
||||
<source>Please wait for token to be registered.</source>
|
||||
<target>Please wait for token to be registered.</target>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Polish interface" xml:space="preserve">
|
||||
<source>Polish interface</source>
|
||||
<target>Polish interface</target>
|
||||
|
@ -5750,6 +5903,11 @@ Error: %@</target>
|
|||
<target>Private filenames</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Private media file names." xml:space="preserve">
|
||||
<source>Private media file names.</source>
|
||||
<target>Private media file names.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Private message routing" xml:space="preserve">
|
||||
<source>Private message routing</source>
|
||||
<target>Private message routing</target>
|
||||
|
@ -5825,6 +5983,11 @@ Error: %@</target>
|
|||
<target>Prohibit messages reactions.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Prohibit reporting messages to moderators." xml:space="preserve">
|
||||
<source>Prohibit reporting messages to moderators.</source>
|
||||
<target>Prohibit reporting messages to moderators.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Prohibit sending SimpleX links." xml:space="preserve">
|
||||
<source>Prohibit sending SimpleX links.</source>
|
||||
<target>Prohibit sending SimpleX links.</target>
|
||||
|
@ -6082,6 +6245,21 @@ Enable in *Network & servers* settings.</target>
|
|||
<target>Reduced battery usage</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Register" xml:space="preserve">
|
||||
<source>Register</source>
|
||||
<target>Register</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Register notification token?" xml:space="preserve">
|
||||
<source>Register notification token?</source>
|
||||
<target>Register notification token?</target>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Registered" xml:space="preserve">
|
||||
<source>Registered</source>
|
||||
<target>Registered</target>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Reject" xml:space="preserve">
|
||||
<source>Reject</source>
|
||||
<target>Reject</target>
|
||||
|
@ -6218,6 +6396,16 @@ Enable in *Network & servers* settings.</target>
|
|||
<target>Report violation: only group moderators will see it.</target>
|
||||
<note>report reason</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Report: %@" xml:space="preserve">
|
||||
<source>Report: %@</source>
|
||||
<target>Report: %@</target>
|
||||
<note>report in notification</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Reporting messages to moderators is prohibited." xml:space="preserve">
|
||||
<source>Reporting messages to moderators is prohibited.</source>
|
||||
<target>Reporting messages to moderators is prohibited.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Reports" xml:space="preserve">
|
||||
<source>Reports</source>
|
||||
<target>Reports</target>
|
||||
|
@ -6644,6 +6832,11 @@ Enable in *Network & servers* settings.</target>
|
|||
<target>Send notifications</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Send private reports" xml:space="preserve">
|
||||
<source>Send private reports</source>
|
||||
<target>Send private reports</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Send questions and ideas" xml:space="preserve">
|
||||
<source>Send questions and ideas</source>
|
||||
<target>Send questions and ideas</target>
|
||||
|
@ -6884,6 +7077,11 @@ Enable in *Network & servers* settings.</target>
|
|||
<target>Set it instead of system authentication.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Set message expiration in chats." xml:space="preserve">
|
||||
<source>Set message expiration in chats.</source>
|
||||
<target>Set message expiration in chats.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Set passcode" xml:space="preserve">
|
||||
<source>Set passcode</source>
|
||||
<target>Set passcode</target>
|
||||
|
@ -7348,6 +7546,11 @@ Enable in *Network & servers* settings.</target>
|
|||
<target>TCP connection timeout</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="TCP port for messaging" xml:space="preserve">
|
||||
<source>TCP port for messaging</source>
|
||||
<target>TCP port for messaging</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="TCP_KEEPCNT" xml:space="preserve">
|
||||
<source>TCP_KEEPCNT</source>
|
||||
<target>TCP_KEEPCNT</target>
|
||||
|
@ -7423,6 +7626,11 @@ Enable in *Network & servers* settings.</target>
|
|||
<target>Test failed at step %@.</target>
|
||||
<note>server test failure</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Test notifications" xml:space="preserve">
|
||||
<source>Test notifications</source>
|
||||
<target>Test notifications</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Test server" xml:space="preserve">
|
||||
<source>Test server</source>
|
||||
<target>Test server</target>
|
||||
|
@ -7550,11 +7758,6 @@ It can happen because of some bug or when the connection is compromised.</target
|
|||
<target>The profile is only shared with your contacts.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="The report will be archived for you." xml:space="preserve">
|
||||
<source>The report will be archived for you.</source>
|
||||
<target>The report will be archived for you.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve">
|
||||
<source>The same conditions will apply to operator **%@**.</source>
|
||||
<target>The same conditions will apply to operator **%@**.</target>
|
||||
|
@ -7685,6 +7888,11 @@ It can happen because of some bug or when the connection is compromised.</target
|
|||
<target>This link was used with another mobile device, please create a new link on the desktop.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="This message was deleted or not received yet." xml:space="preserve">
|
||||
<source>This message was deleted or not received yet.</source>
|
||||
<target>This message was deleted or not received yet.</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">
|
||||
<source>This setting applies to messages in your current chat profile **%@**.</source>
|
||||
<target>This setting applies to messages in your current chat profile **%@**.</target>
|
||||
|
@ -7797,6 +8005,11 @@ You will be prompted to complete authentication before this feature is enabled.<
|
|||
<target>Toggle incognito when connecting.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Token status: %@." xml:space="preserve">
|
||||
<source>Token status: %@.</source>
|
||||
<target>Token status: %@.</target>
|
||||
<note>token status</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Toolbar opacity" xml:space="preserve">
|
||||
<source>Toolbar opacity</source>
|
||||
<target>Toolbar opacity</target>
|
||||
|
@ -7962,7 +8175,7 @@ To connect, please ask your contact to create another connection link and check
|
|||
<trans-unit id="Unmute" xml:space="preserve">
|
||||
<source>Unmute</source>
|
||||
<target>Unmute</target>
|
||||
<note>swipe action</note>
|
||||
<note>notification label action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Unread" xml:space="preserve">
|
||||
<source>Unread</source>
|
||||
|
@ -7994,6 +8207,11 @@ To connect, please ask your contact to create another connection link and check
|
|||
<target>Update settings?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Updated conditions" xml:space="preserve">
|
||||
<source>Updated conditions</source>
|
||||
<target>Updated conditions</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Updating settings will re-connect the client to all servers." xml:space="preserve">
|
||||
<source>Updating settings will re-connect the client to all servers.</source>
|
||||
<target>Updating settings will re-connect the client to all servers.</target>
|
||||
|
@ -8054,6 +8272,11 @@ To connect, please ask your contact to create another connection link and check
|
|||
<target>Use SimpleX Chat servers?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use TCP port %@ when no port is specified." xml:space="preserve">
|
||||
<source>Use TCP port %@ when no port is specified.</source>
|
||||
<target>Use TCP port %@ when no port is specified.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use chat" xml:space="preserve">
|
||||
<source>Use chat</source>
|
||||
<target>Use chat</target>
|
||||
|
@ -8129,6 +8352,11 @@ To connect, please ask your contact to create another connection link and check
|
|||
<target>Use the app with one hand.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use web port" xml:space="preserve">
|
||||
<source>Use web port</source>
|
||||
<target>Use web port</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="User selection" xml:space="preserve">
|
||||
<source>User selection</source>
|
||||
<target>User selection</target>
|
||||
|
@ -8683,6 +8911,11 @@ Repeat connection request?</target>
|
|||
<target>You sent group invitation</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="You should receive notifications." xml:space="preserve">
|
||||
<source>You should receive notifications.</source>
|
||||
<target>You should receive notifications.</target>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="You will be connected to group when the group host's device is online, please wait or check later!" xml:space="preserve">
|
||||
<source>You will be connected to group when the group host's device is online, please wait or check later!</source>
|
||||
<target>You will be connected to group when the group host's device is online, please wait or check later!</target>
|
||||
|
@ -9479,11 +9712,6 @@ Repeat connection request?</target>
|
|||
<target>months</target>
|
||||
<note>time unit</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="mute" xml:space="preserve">
|
||||
<source>mute</source>
|
||||
<target>mute</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="never" xml:space="preserve">
|
||||
<source>never</source>
|
||||
<target>never</target>
|
||||
|
@ -9561,6 +9789,16 @@ Repeat connection request?</target>
|
|||
<target>peer-to-peer</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="pending" xml:space="preserve">
|
||||
<source>pending</source>
|
||||
<target>pending</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="pending approval" xml:space="preserve">
|
||||
<source>pending approval</source>
|
||||
<target>pending approval</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="quantum resistant e2e encryption" xml:space="preserve">
|
||||
<source>quantum resistant e2e encryption</source>
|
||||
<target>quantum resistant e2e encryption</target>
|
||||
|
@ -9576,6 +9814,11 @@ Repeat connection request?</target>
|
|||
<target>received confirmation…</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="rejected" xml:space="preserve">
|
||||
<source>rejected</source>
|
||||
<target>rejected</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="rejected call" xml:space="preserve">
|
||||
<source>rejected call</source>
|
||||
<target>rejected call</target>
|
||||
|
@ -9710,11 +9953,6 @@ last received msg: %2$@</target>
|
|||
<target>unknown status</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="unmute" xml:space="preserve">
|
||||
<source>unmute</source>
|
||||
<target>unmute</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="unprotected" xml:space="preserve">
|
||||
<source>unprotected</source>
|
||||
<target>unprotected</target>
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -5,22 +5,6 @@
|
|||
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.4" build-num="15F31d"/>
|
||||
</header>
|
||||
<body>
|
||||
<trans-unit id=" " xml:space="preserve">
|
||||
<source>
|
||||
</source>
|
||||
<target>
|
||||
</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=" " xml:space="preserve">
|
||||
<source> </source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=" (" xml:space="preserve">
|
||||
<source> (</source>
|
||||
<target> (</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=" (can be copied)" xml:space="preserve">
|
||||
<source> (can be copied)</source>
|
||||
<target> (voidaan kopioida)</target>
|
||||
|
@ -312,11 +296,6 @@
|
|||
<target>%u viestit ohitettu.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="(" xml:space="preserve">
|
||||
<source>(</source>
|
||||
<target>(</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="(new)" xml:space="preserve">
|
||||
<source>(new)</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -325,11 +304,6 @@
|
|||
<source>(this device v%@)</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=")" xml:space="preserve">
|
||||
<source>)</source>
|
||||
<target>)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="**Create 1-time link**: to create and share a new invitation link." xml:space="preserve">
|
||||
<source>**Create 1-time link**: to create and share a new invitation link.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -390,11 +364,6 @@
|
|||
<target>\*bold*</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=", " xml:space="preserve">
|
||||
<source>, </source>
|
||||
<target>, </target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="- connect to [directory service](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (BETA)! - delivery receipts (up to 20 members). - faster and more stable." xml:space="preserve">
|
||||
<source>- connect to [directory service](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (BETA)!
|
||||
- delivery receipts (up to 20 members).
|
||||
|
@ -425,11 +394,6 @@
|
|||
- historian muokkaaminen.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="." xml:space="preserve">
|
||||
<source>.</source>
|
||||
<target>.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="0 sec" xml:space="preserve">
|
||||
<source>0 sec</source>
|
||||
<note>time to disappear</note>
|
||||
|
@ -494,11 +458,6 @@
|
|||
<target>30 sekuntia</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=": " xml:space="preserve">
|
||||
<source>: </source>
|
||||
<target>: </target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="<p>Hi!</p> <p><a href="%@">Connect to me via SimpleX Chat</a></p>" xml:space="preserve">
|
||||
<source><p>Hi!</p>
|
||||
<p><a href="%@">Connect to me via SimpleX Chat</a></p></source>
|
||||
|
@ -600,6 +559,10 @@
|
|||
<source>Acknowledgement errors</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Active" xml:space="preserve">
|
||||
<source>Active</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Active connections" xml:space="preserve">
|
||||
<source>Active connections</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -724,8 +687,8 @@
|
|||
<target>Kaikki keskustelut ja viestit poistetaan - tätä ei voi kumota!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All chats will be removed from the list (text), and the list deleted." xml:space="preserve">
|
||||
<source>All chats will be removed from the list (text), and the list deleted.</source>
|
||||
<trans-unit id="All chats will be removed from the list %@, and the list deleted." xml:space="preserve">
|
||||
<source>All chats will be removed from the list %@, and the list deleted.</source>
|
||||
<note>alert message</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All data is erased when it is entered." xml:space="preserve">
|
||||
|
@ -763,6 +726,10 @@
|
|||
<source>All profiles</source>
|
||||
<note>profile dropdown</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All reports will be archived for you." xml:space="preserve">
|
||||
<source>All reports will be archived for you.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
||||
<source>All your contacts will remain connected.</source>
|
||||
<target>Kaikki kontaktisi pysyvät yhteydessä.</target>
|
||||
|
@ -834,6 +801,10 @@
|
|||
<target>Salli lähetettyjen viestien peruuttamaton poistaminen. (24 tuntia)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Allow to report messsages to moderators." xml:space="preserve">
|
||||
<source>Allow to report messsages to moderators.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Allow to send SimpleX links." xml:space="preserve">
|
||||
<source>Allow to send SimpleX links.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -987,6 +958,14 @@
|
|||
<source>Archive</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive %lld reports?" xml:space="preserve">
|
||||
<source>Archive %lld reports?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive all reports?" xml:space="preserve">
|
||||
<source>Archive all reports?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive and upload" xml:space="preserve">
|
||||
<source>Archive and upload</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -1003,6 +982,10 @@
|
|||
<source>Archive report?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive reports" xml:space="preserve">
|
||||
<source>Archive reports</source>
|
||||
<note>swipe action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archived contacts" xml:space="preserve">
|
||||
<source>Archived contacts</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -1110,6 +1093,10 @@
|
|||
<source>Better groups</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better groups performance" xml:space="preserve">
|
||||
<source>Better groups performance</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better message dates." xml:space="preserve">
|
||||
<source>Better message dates.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -1127,6 +1114,10 @@
|
|||
<source>Better notifications</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better privacy and security" xml:space="preserve">
|
||||
<source>Better privacy and security</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better security ✅" xml:space="preserve">
|
||||
<source>Better security ✅</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -1504,6 +1495,10 @@
|
|||
<target>Tyhjennä keskustelu?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Clear group?" xml:space="preserve">
|
||||
<source>Clear group?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Clear or delete group?" xml:space="preserve">
|
||||
<source>Clear or delete group?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -1629,6 +1624,10 @@
|
|||
<source>Confirm upload</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Confirmed" xml:space="preserve">
|
||||
<source>Confirmed</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Connect" xml:space="preserve">
|
||||
<source>Connect</source>
|
||||
<target>Yhdistä</target>
|
||||
|
@ -2556,6 +2555,10 @@ This is your own one-time link!</source>
|
|||
<target>Älä salli</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Don't miss important messages." xml:space="preserve">
|
||||
<source>Don't miss important messages.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Don't show again" xml:space="preserve">
|
||||
<source>Don't show again</source>
|
||||
<target>Älä näytä uudelleen</target>
|
||||
|
@ -2884,6 +2887,10 @@ This is your own one-time link!</source>
|
|||
<source>Error changing to incognito!</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error checking token status" xml:space="preserve">
|
||||
<source>Error checking token status</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error connecting to forwarding server %@. Please try later." xml:space="preserve">
|
||||
<source>Error connecting to forwarding server %@. Please try later.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -3027,6 +3034,10 @@ This is your own one-time link!</source>
|
|||
<source>Error reconnecting servers</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error registering for notifications" xml:space="preserve">
|
||||
<source>Error registering for notifications</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error removing member" xml:space="preserve">
|
||||
<source>Error removing member</source>
|
||||
<target>Virhe poistettaessa jäsentä</target>
|
||||
|
@ -3124,6 +3135,10 @@ This is your own one-time link!</source>
|
|||
<target>Virhe yhteyden synkronoinnissa</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error testing server connection" xml:space="preserve">
|
||||
<source>Error testing server connection</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error updating group link" xml:space="preserve">
|
||||
<source>Error updating group link</source>
|
||||
<target>Virhe ryhmälinkin päivittämisessä</target>
|
||||
|
@ -3198,6 +3213,10 @@ This is your own one-time link!</source>
|
|||
<source>Expand</source>
|
||||
<note>chat item action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Expired" xml:space="preserve">
|
||||
<source>Expired</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Export database" xml:space="preserve">
|
||||
<source>Export database</source>
|
||||
<target>Vie tietokanta</target>
|
||||
|
@ -3236,10 +3255,18 @@ This is your own one-time link!</source>
|
|||
<target>Nopea ja ei odotusta, kunnes lähettäjä on online-tilassa!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Faster deletion of groups." xml:space="preserve">
|
||||
<source>Faster deletion of groups.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Faster joining and more reliable messages." xml:space="preserve">
|
||||
<source>Faster joining and more reliable messages.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Faster sending messages." xml:space="preserve">
|
||||
<source>Faster sending messages.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Favorite" xml:space="preserve">
|
||||
<source>Favorite</source>
|
||||
<target>Suosikki</target>
|
||||
|
@ -3258,9 +3285,9 @@ This is your own one-time link!</source>
|
|||
%@</source>
|
||||
<note>alert message</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="File is blocked by server operator: (info.reason.text)." xml:space="preserve">
|
||||
<trans-unit id="File is blocked by server operator: %@." xml:space="preserve">
|
||||
<source>File is blocked by server operator:
|
||||
(info.reason.text).</source>
|
||||
%@.</source>
|
||||
<note>file error text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="File not found - most likely file was deleted or cancelled." xml:space="preserve">
|
||||
|
@ -3380,6 +3407,10 @@ This is your own one-time link!</source>
|
|||
<target>Ryhmän jäsen ei tue korjausta</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For all moderators" xml:space="preserve">
|
||||
<source>For all moderators</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For chat profile %@:" xml:space="preserve">
|
||||
<source>For chat profile %@:</source>
|
||||
<note>servers error</note>
|
||||
|
@ -3393,6 +3424,10 @@ This is your own one-time link!</source>
|
|||
<source>For example, if your contact receives messages via a SimpleX Chat server, your app will deliver them via a Flux server.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For me" xml:space="preserve">
|
||||
<source>For me</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For private routing" xml:space="preserve">
|
||||
<source>For private routing</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -3497,6 +3532,10 @@ Error: %2$@</source>
|
|||
<target>GIFit ja tarrat</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Get notified when mentioned." xml:space="preserve">
|
||||
<source>Get notified when mentioned.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Good afternoon!" xml:space="preserve">
|
||||
<source>Good afternoon!</source>
|
||||
<note>message preview</note>
|
||||
|
@ -3607,6 +3646,10 @@ Error: %2$@</source>
|
|||
<target>Apua</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Help admins moderating their groups." xml:space="preserve">
|
||||
<source>Help admins moderating their groups.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Hidden" xml:space="preserve">
|
||||
<source>Hidden</source>
|
||||
<target>Piilotettu</target>
|
||||
|
@ -3897,6 +3940,26 @@ More improvements are coming soon!</source>
|
|||
<source>Interface colors</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid" xml:space="preserve">
|
||||
<source>Invalid</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (bad token)" xml:space="preserve">
|
||||
<source>Invalid (bad token)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (expired)" xml:space="preserve">
|
||||
<source>Invalid (expired)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (unregistered)" xml:space="preserve">
|
||||
<source>Invalid (unregistered)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (wrong topic)" xml:space="preserve">
|
||||
<source>Invalid (wrong topic)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid QR code" xml:space="preserve">
|
||||
<source>Invalid QR code</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -4247,6 +4310,10 @@ This is your link for group %@!</source>
|
|||
<source>Member inactive</source>
|
||||
<note>item status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Member reports" xml:space="preserve">
|
||||
<source>Member reports</source>
|
||||
<note>chat feature</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Member role will be changed to "%@". All chat members will be notified." xml:space="preserve">
|
||||
<source>Member role will be changed to "%@". All chat members will be notified.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -4280,6 +4347,10 @@ This is your link for group %@!</source>
|
|||
<target>Ryhmän jäsenet voivat poistaa lähetetyt viestit peruuttamattomasti. (24 tuntia)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Members can report messsages to moderators." xml:space="preserve">
|
||||
<source>Members can report messsages to moderators.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Members can send SimpleX links." xml:space="preserve">
|
||||
<source>Members can send SimpleX links.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -4304,6 +4375,10 @@ This is your link for group %@!</source>
|
|||
<target>Ryhmän jäsenet voivat lähettää ääniviestejä.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Mention members 👋" xml:space="preserve">
|
||||
<source>Mention members 👋</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Menus" xml:space="preserve">
|
||||
<source>Menus</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -4523,7 +4598,11 @@ This is your link for group %@!</source>
|
|||
<trans-unit id="Mute" xml:space="preserve">
|
||||
<source>Mute</source>
|
||||
<target>Mykistä</target>
|
||||
<note>swipe action</note>
|
||||
<note>notification label action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Mute all" xml:space="preserve">
|
||||
<source>Mute all</source>
|
||||
<note>notification label action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Muted when inactive!" xml:space="preserve">
|
||||
<source>Muted when inactive!</source>
|
||||
|
@ -4570,6 +4649,10 @@ This is your link for group %@!</source>
|
|||
<target>Verkon tila</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="New" xml:space="preserve">
|
||||
<source>New</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="New Passcode" xml:space="preserve">
|
||||
<source>New Passcode</source>
|
||||
<target>Uusi pääsykoodi</target>
|
||||
|
@ -4711,6 +4794,10 @@ This is your link for group %@!</source>
|
|||
<source>No media & file servers.</source>
|
||||
<note>servers error</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No message" xml:space="preserve">
|
||||
<source>No message</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No message servers." xml:space="preserve">
|
||||
<source>No message servers.</source>
|
||||
<note>servers error</note>
|
||||
|
@ -4758,6 +4845,10 @@ This is your link for group %@!</source>
|
|||
<source>No servers to send files.</source>
|
||||
<note>servers error</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No token!" xml:space="preserve">
|
||||
<source>No token!</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No unread chats" xml:space="preserve">
|
||||
<source>No unread chats</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -4793,10 +4884,18 @@ This is your link for group %@!</source>
|
|||
<target>Ilmoitukset on poistettu käytöstä!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Notifications error" xml:space="preserve">
|
||||
<source>Notifications error</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Notifications privacy" xml:space="preserve">
|
||||
<source>Notifications privacy</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Notifications status" xml:space="preserve">
|
||||
<source>Notifications status</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Now admins can: - delete members' messages. - disable members ("observer" role)" xml:space="preserve">
|
||||
<source>Now admins can:
|
||||
- delete members' messages.
|
||||
|
@ -5018,6 +5117,10 @@ Edellyttää VPN:n sallimista.</target>
|
|||
<source>Or to share privately</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Organize chats into lists" xml:space="preserve">
|
||||
<source>Organize chats into lists</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Other" xml:space="preserve">
|
||||
<source>Other</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -5192,6 +5295,18 @@ Error: %@</source>
|
|||
<target>Säilytä tunnuslause turvallisesti, ET voi muuttaa sitä, jos kadotat sen.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please try to disable and re-enable notfications." xml:space="preserve">
|
||||
<source>Please try to disable and re-enable notfications.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please wait for token activation to complete." xml:space="preserve">
|
||||
<source>Please wait for token activation to complete.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please wait for token to be registered." xml:space="preserve">
|
||||
<source>Please wait for token to be registered.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Polish interface" xml:space="preserve">
|
||||
<source>Polish interface</source>
|
||||
<target>Puolalainen käyttöliittymä</target>
|
||||
|
@ -5248,6 +5363,10 @@ Error: %@</source>
|
|||
<target>Yksityiset tiedostonimet</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Private media file names." xml:space="preserve">
|
||||
<source>Private media file names.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Private message routing" xml:space="preserve">
|
||||
<source>Private message routing</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -5316,6 +5435,10 @@ Error: %@</source>
|
|||
<target>Estä viestireaktiot.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Prohibit reporting messages to moderators." xml:space="preserve">
|
||||
<source>Prohibit reporting messages to moderators.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Prohibit sending SimpleX links." xml:space="preserve">
|
||||
<source>Prohibit sending SimpleX links.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -5551,6 +5674,18 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>Pienempi akun käyttö</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Register" xml:space="preserve">
|
||||
<source>Register</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Register notification token?" xml:space="preserve">
|
||||
<source>Register notification token?</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Registered" xml:space="preserve">
|
||||
<source>Registered</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Reject" xml:space="preserve">
|
||||
<source>Reject</source>
|
||||
<target>Hylkää</target>
|
||||
|
@ -5673,6 +5808,14 @@ Enable in *Network & servers* settings.</source>
|
|||
<source>Report violation: only group moderators will see it.</source>
|
||||
<note>report reason</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Report: %@" xml:space="preserve">
|
||||
<source>Report: %@</source>
|
||||
<note>report in notification</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Reporting messages to moderators is prohibited." xml:space="preserve">
|
||||
<source>Reporting messages to moderators is prohibited.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Reports" xml:space="preserve">
|
||||
<source>Reports</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -6064,6 +6207,10 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>Lähetys ilmoitukset</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Send private reports" xml:space="preserve">
|
||||
<source>Send private reports</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Send questions and ideas" xml:space="preserve">
|
||||
<source>Send questions and ideas</source>
|
||||
<target>Lähetä kysymyksiä ja ideoita</target>
|
||||
|
@ -6282,6 +6429,10 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>Aseta se järjestelmän todennuksen sijaan.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Set message expiration in chats." xml:space="preserve">
|
||||
<source>Set message expiration in chats.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Set passcode" xml:space="preserve">
|
||||
<source>Set passcode</source>
|
||||
<target>Aseta pääsykoodi</target>
|
||||
|
@ -6702,6 +6853,10 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>TCP-yhteyden aikakatkaisu</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="TCP port for messaging" xml:space="preserve">
|
||||
<source>TCP port for messaging</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="TCP_KEEPCNT" xml:space="preserve">
|
||||
<source>TCP_KEEPCNT</source>
|
||||
<target>TCP_KEEPCNT</target>
|
||||
|
@ -6771,6 +6926,10 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>Testi epäonnistui vaiheessa %@.</target>
|
||||
<note>server test failure</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Test notifications" xml:space="preserve">
|
||||
<source>Test notifications</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Test server" xml:space="preserve">
|
||||
<source>Test server</source>
|
||||
<target>Testipalvelin</target>
|
||||
|
@ -6892,10 +7051,6 @@ Tämä voi johtua jostain virheestä tai siitä, että yhteys on vaarantunut.</t
|
|||
<target>Profiili jaetaan vain kontaktiesi kanssa.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="The report will be archived for you." xml:space="preserve">
|
||||
<source>The report will be archived for you.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve">
|
||||
<source>The same conditions will apply to operator **%@**.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -7010,6 +7165,10 @@ Tämä voi johtua jostain virheestä tai siitä, että yhteys on vaarantunut.</t
|
|||
<source>This link was used with another mobile device, please create a new link on the desktop.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="This message was deleted or not received yet." xml:space="preserve">
|
||||
<source>This message was deleted or not received yet.</source>
|
||||
<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">
|
||||
<source>This setting applies to messages in your current chat profile **%@**.</source>
|
||||
<target>Tämä asetus koskee nykyisen keskusteluprofiilisi viestejä *%@**.</target>
|
||||
|
@ -7111,6 +7270,10 @@ Sinua kehotetaan suorittamaan todennus loppuun, ennen kuin tämä ominaisuus ote
|
|||
<source>Toggle incognito when connecting.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Token status: %@." xml:space="preserve">
|
||||
<source>Token status: %@.</source>
|
||||
<note>token status</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Toolbar opacity" xml:space="preserve">
|
||||
<source>Toolbar opacity</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -7263,7 +7426,7 @@ Jos haluat muodostaa yhteyden, pyydä kontaktiasi luomaan toinen yhteyslinkki ja
|
|||
<trans-unit id="Unmute" xml:space="preserve">
|
||||
<source>Unmute</source>
|
||||
<target>Poista mykistys</target>
|
||||
<note>swipe action</note>
|
||||
<note>notification label action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Unread" xml:space="preserve">
|
||||
<source>Unread</source>
|
||||
|
@ -7293,6 +7456,10 @@ Jos haluat muodostaa yhteyden, pyydä kontaktiasi luomaan toinen yhteyslinkki ja
|
|||
<source>Update settings?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Updated conditions" xml:space="preserve">
|
||||
<source>Updated conditions</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Updating settings will re-connect the client to all servers." xml:space="preserve">
|
||||
<source>Updating settings will re-connect the client to all servers.</source>
|
||||
<target>Asetusten päivittäminen yhdistää asiakkaan uudelleen kaikkiin palvelimiin.</target>
|
||||
|
@ -7346,6 +7513,10 @@ Jos haluat muodostaa yhteyden, pyydä kontaktiasi luomaan toinen yhteyslinkki ja
|
|||
<target>Käytä SimpleX Chat palvelimia?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use TCP port %@ when no port is specified." xml:space="preserve">
|
||||
<source>Use TCP port %@ when no port is specified.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use chat" xml:space="preserve">
|
||||
<source>Use chat</source>
|
||||
<target>Käytä chattia</target>
|
||||
|
@ -7412,6 +7583,10 @@ Jos haluat muodostaa yhteyden, pyydä kontaktiasi luomaan toinen yhteyslinkki ja
|
|||
<source>Use the app with one hand.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use web port" xml:space="preserve">
|
||||
<source>Use web port</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="User selection" xml:space="preserve">
|
||||
<source>User selection</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -7910,6 +8085,10 @@ Repeat connection request?</source>
|
|||
<target>Lähetit ryhmäkutsun</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="You should receive notifications." xml:space="preserve">
|
||||
<source>You should receive notifications.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="You will be connected to group when the group host's device is online, please wait or check later!" xml:space="preserve">
|
||||
<source>You will be connected to group when the group host's device is online, please wait or check later!</source>
|
||||
<target>Sinut yhdistetään ryhmään, kun ryhmän isännän laite on online-tilassa, odota tai tarkista myöhemmin!</target>
|
||||
|
@ -8673,10 +8852,6 @@ Repeat connection request?</source>
|
|||
<target>kuukautta</target>
|
||||
<note>time unit</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="mute" xml:space="preserve">
|
||||
<source>mute</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="never" xml:space="preserve">
|
||||
<source>never</source>
|
||||
<target>ei koskaan</target>
|
||||
|
@ -8751,6 +8926,14 @@ Repeat connection request?</source>
|
|||
<target>vertais</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="pending" xml:space="preserve">
|
||||
<source>pending</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="pending approval" xml:space="preserve">
|
||||
<source>pending approval</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="quantum resistant e2e encryption" xml:space="preserve">
|
||||
<source>quantum resistant e2e encryption</source>
|
||||
<note>chat item text</note>
|
||||
|
@ -8765,6 +8948,10 @@ Repeat connection request?</source>
|
|||
<target>vahvistus saatu…</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="rejected" xml:space="preserve">
|
||||
<source>rejected</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="rejected call" xml:space="preserve">
|
||||
<source>rejected call</source>
|
||||
<target>hylätty puhelu</target>
|
||||
|
@ -8883,10 +9070,6 @@ last received msg: %2$@</source>
|
|||
<source>unknown status</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="unmute" xml:space="preserve">
|
||||
<source>unmute</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="unprotected" xml:space="preserve">
|
||||
<source>unprotected</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
|
|
@ -5,22 +5,6 @@
|
|||
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.4" build-num="15F31d"/>
|
||||
</header>
|
||||
<body>
|
||||
<trans-unit id=" " xml:space="preserve">
|
||||
<source>
|
||||
</source>
|
||||
<target>
|
||||
</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=" " xml:space="preserve">
|
||||
<source> </source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=" (" xml:space="preserve">
|
||||
<source> (</source>
|
||||
<target> (</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=" (can be copied)" xml:space="preserve">
|
||||
<source> (can be copied)</source>
|
||||
<target> (peut être copié)</target>
|
||||
|
@ -330,11 +314,6 @@
|
|||
<target>%u messages sautés.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="(" xml:space="preserve">
|
||||
<source>(</source>
|
||||
<target>(</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="(new)" xml:space="preserve">
|
||||
<source>(new)</source>
|
||||
<target>(nouveau)</target>
|
||||
|
@ -345,11 +324,6 @@
|
|||
<target>(cet appareil v%@)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=")" xml:space="preserve">
|
||||
<source>)</source>
|
||||
<target>)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="**Create 1-time link**: to create and share a new invitation link." xml:space="preserve">
|
||||
<source>**Create 1-time link**: to create and share a new invitation link.</source>
|
||||
<target>**Ajouter un contact** : pour créer un nouveau lien d'invitation.</target>
|
||||
|
@ -415,11 +389,6 @@
|
|||
<target>\*gras*</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=", " xml:space="preserve">
|
||||
<source>, </source>
|
||||
<target>, </target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="- connect to [directory service](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (BETA)! - delivery receipts (up to 20 members). - faster and more stable." xml:space="preserve">
|
||||
<source>- connect to [directory service](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (BETA)!
|
||||
- delivery receipts (up to 20 members).
|
||||
|
@ -456,11 +425,6 @@
|
|||
- l'historique de modification.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="." xml:space="preserve">
|
||||
<source>.</source>
|
||||
<target>.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="0 sec" xml:space="preserve">
|
||||
<source>0 sec</source>
|
||||
<target>0 sec</target>
|
||||
|
@ -528,11 +492,6 @@
|
|||
<target>30 secondes</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=": " xml:space="preserve">
|
||||
<source>: </source>
|
||||
<target>: </target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="<p>Hi!</p> <p><a href="%@">Connect to me via SimpleX Chat</a></p>" xml:space="preserve">
|
||||
<source><p>Hi!</p>
|
||||
<p><a href="%@">Connect to me via SimpleX Chat</a></p></source>
|
||||
|
@ -640,6 +599,10 @@
|
|||
<target>Erreur d'accusé de réception</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Active" xml:space="preserve">
|
||||
<source>Active</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Active connections" xml:space="preserve">
|
||||
<source>Active connections</source>
|
||||
<target>Connections actives</target>
|
||||
|
@ -777,8 +740,8 @@
|
|||
<target>Toutes les discussions et tous les messages seront supprimés - il est impossible de revenir en arrière !</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All chats will be removed from the list (text), and the list deleted." xml:space="preserve">
|
||||
<source>All chats will be removed from the list (text), and the list deleted.</source>
|
||||
<trans-unit id="All chats will be removed from the list %@, and the list deleted." xml:space="preserve">
|
||||
<source>All chats will be removed from the list %@, and the list deleted.</source>
|
||||
<note>alert message</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All data is erased when it is entered." xml:space="preserve">
|
||||
|
@ -821,6 +784,10 @@
|
|||
<target>Tous les profiles</target>
|
||||
<note>profile dropdown</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All reports will be archived for you." xml:space="preserve">
|
||||
<source>All reports will be archived for you.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
||||
<source>All your contacts will remain connected.</source>
|
||||
<target>Tous vos contacts resteront connectés.</target>
|
||||
|
@ -896,6 +863,10 @@
|
|||
<target>Autoriser la suppression irréversible de messages envoyés. (24 heures)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Allow to report messsages to moderators." xml:space="preserve">
|
||||
<source>Allow to report messsages to moderators.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Allow to send SimpleX links." xml:space="preserve">
|
||||
<source>Allow to send SimpleX links.</source>
|
||||
<target>Autorise l'envoi de liens SimpleX.</target>
|
||||
|
@ -1058,6 +1029,14 @@
|
|||
<source>Archive</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive %lld reports?" xml:space="preserve">
|
||||
<source>Archive %lld reports?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive all reports?" xml:space="preserve">
|
||||
<source>Archive all reports?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive and upload" xml:space="preserve">
|
||||
<source>Archive and upload</source>
|
||||
<target>Archiver et téléverser</target>
|
||||
|
@ -1076,6 +1055,10 @@
|
|||
<source>Archive report?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive reports" xml:space="preserve">
|
||||
<source>Archive reports</source>
|
||||
<note>swipe action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archived contacts" xml:space="preserve">
|
||||
<source>Archived contacts</source>
|
||||
<target>Contacts archivés</target>
|
||||
|
@ -1190,6 +1173,10 @@
|
|||
<target>Des groupes plus performants</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better groups performance" xml:space="preserve">
|
||||
<source>Better groups performance</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better message dates." xml:space="preserve">
|
||||
<source>Better message dates.</source>
|
||||
<target>Meilleures dates de messages.</target>
|
||||
|
@ -1210,6 +1197,10 @@
|
|||
<target>Notifications améliorées</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better privacy and security" xml:space="preserve">
|
||||
<source>Better privacy and security</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better security ✅" xml:space="preserve">
|
||||
<source>Better security ✅</source>
|
||||
<target>Sécurité accrue ✅</target>
|
||||
|
@ -1630,6 +1621,10 @@
|
|||
<target>Effacer la conversation ?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Clear group?" xml:space="preserve">
|
||||
<source>Clear group?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Clear or delete group?" xml:space="preserve">
|
||||
<source>Clear or delete group?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -1773,6 +1768,10 @@
|
|||
<target>Confirmer la transmission</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Confirmed" xml:space="preserve">
|
||||
<source>Confirmed</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Connect" xml:space="preserve">
|
||||
<source>Connect</source>
|
||||
<target>Se connecter</target>
|
||||
|
@ -2775,6 +2774,10 @@ Il s'agit de votre propre lien unique !</target>
|
|||
<target>Ne pas activer</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Don't miss important messages." xml:space="preserve">
|
||||
<source>Don't miss important messages.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Don't show again" xml:space="preserve">
|
||||
<source>Don't show again</source>
|
||||
<target>Ne plus afficher</target>
|
||||
|
@ -3129,6 +3132,10 @@ Il s'agit de votre propre lien unique !</target>
|
|||
<target>Erreur lors du passage en mode incognito !</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error checking token status" xml:space="preserve">
|
||||
<source>Error checking token status</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error connecting to forwarding server %@. Please try later." xml:space="preserve">
|
||||
<source>Error connecting to forwarding server %@. Please try later.</source>
|
||||
<target>Erreur de connexion au serveur de redirection %@. Veuillez réessayer plus tard.</target>
|
||||
|
@ -3282,6 +3289,10 @@ Il s'agit de votre propre lien unique !</target>
|
|||
<target>Erreur de reconnexion des serveurs</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error registering for notifications" xml:space="preserve">
|
||||
<source>Error registering for notifications</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error removing member" xml:space="preserve">
|
||||
<source>Error removing member</source>
|
||||
<target>Erreur lors de la suppression d'un membre</target>
|
||||
|
@ -3385,6 +3396,10 @@ Il s'agit de votre propre lien unique !</target>
|
|||
<target>Erreur de synchronisation de connexion</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error testing server connection" xml:space="preserve">
|
||||
<source>Error testing server connection</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error updating group link" xml:space="preserve">
|
||||
<source>Error updating group link</source>
|
||||
<target>Erreur lors de la mise à jour du lien de groupe</target>
|
||||
|
@ -3465,6 +3480,10 @@ Il s'agit de votre propre lien unique !</target>
|
|||
<target>Étendre</target>
|
||||
<note>chat item action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Expired" xml:space="preserve">
|
||||
<source>Expired</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Export database" xml:space="preserve">
|
||||
<source>Export database</source>
|
||||
<target>Exporter la base de données</target>
|
||||
|
@ -3505,11 +3524,19 @@ Il s'agit de votre propre lien unique !</target>
|
|||
<target>Rapide et ne nécessitant pas d'attendre que l'expéditeur soit en ligne !</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Faster deletion of groups." xml:space="preserve">
|
||||
<source>Faster deletion of groups.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Faster joining and more reliable messages." xml:space="preserve">
|
||||
<source>Faster joining and more reliable messages.</source>
|
||||
<target>Connexion plus rapide et messages plus fiables.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Faster sending messages." xml:space="preserve">
|
||||
<source>Faster sending messages.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Favorite" xml:space="preserve">
|
||||
<source>Favorite</source>
|
||||
<target>Favoris</target>
|
||||
|
@ -3531,9 +3558,9 @@ Il s'agit de votre propre lien unique !</target>
|
|||
%@</target>
|
||||
<note>alert message</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="File is blocked by server operator: (info.reason.text)." xml:space="preserve">
|
||||
<trans-unit id="File is blocked by server operator: %@." xml:space="preserve">
|
||||
<source>File is blocked by server operator:
|
||||
(info.reason.text).</source>
|
||||
%@.</source>
|
||||
<note>file error text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="File not found - most likely file was deleted or cancelled." xml:space="preserve">
|
||||
|
@ -3661,6 +3688,10 @@ Il s'agit de votre propre lien unique !</target>
|
|||
<target>Correction non prise en charge par un membre du groupe</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For all moderators" xml:space="preserve">
|
||||
<source>For all moderators</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For chat profile %@:" xml:space="preserve">
|
||||
<source>For chat profile %@:</source>
|
||||
<target>Pour le profil de discussion %@ :</target>
|
||||
|
@ -3676,6 +3707,10 @@ Il s'agit de votre propre lien unique !</target>
|
|||
<target>Par exemple, si votre contact reçoit des messages via un serveur SimpleX Chat, votre application les transmettra via un serveur Flux.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For me" xml:space="preserve">
|
||||
<source>For me</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For private routing" xml:space="preserve">
|
||||
<source>For private routing</source>
|
||||
<target>Pour le routage privé</target>
|
||||
|
@ -3800,6 +3835,10 @@ Erreur : %2$@</target>
|
|||
<target>GIFs et stickers</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Get notified when mentioned." xml:space="preserve">
|
||||
<source>Get notified when mentioned.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Good afternoon!" xml:space="preserve">
|
||||
<source>Good afternoon!</source>
|
||||
<target>Bonjour !</target>
|
||||
|
@ -3914,6 +3953,10 @@ Erreur : %2$@</target>
|
|||
<target>Aide</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Help admins moderating their groups." xml:space="preserve">
|
||||
<source>Help admins moderating their groups.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Hidden" xml:space="preserve">
|
||||
<source>Hidden</source>
|
||||
<target>Caché</target>
|
||||
|
@ -4220,6 +4263,26 @@ D'autres améliorations sont à venir !</target>
|
|||
<target>Couleurs d'interface</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid" xml:space="preserve">
|
||||
<source>Invalid</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (bad token)" xml:space="preserve">
|
||||
<source>Invalid (bad token)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (expired)" xml:space="preserve">
|
||||
<source>Invalid (expired)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (unregistered)" xml:space="preserve">
|
||||
<source>Invalid (unregistered)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (wrong topic)" xml:space="preserve">
|
||||
<source>Invalid (wrong topic)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid QR code" xml:space="preserve">
|
||||
<source>Invalid QR code</source>
|
||||
<target>Code QR invalide</target>
|
||||
|
@ -4595,6 +4658,10 @@ Voici votre lien pour le groupe %@ !</target>
|
|||
<target>Membre inactif</target>
|
||||
<note>item status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Member reports" xml:space="preserve">
|
||||
<source>Member reports</source>
|
||||
<note>chat feature</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Member role will be changed to "%@". All chat members will be notified." xml:space="preserve">
|
||||
<source>Member role will be changed to "%@". All chat members will be notified.</source>
|
||||
<target>Le rôle du membre sera modifié pour « %@ ». Tous les membres du chat seront notifiés.</target>
|
||||
|
@ -4630,6 +4697,10 @@ Voici votre lien pour le groupe %@ !</target>
|
|||
<target>Les membres du groupe peuvent supprimer de manière irréversible les messages envoyés. (24 heures)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Members can report messsages to moderators." xml:space="preserve">
|
||||
<source>Members can report messsages to moderators.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Members can send SimpleX links." xml:space="preserve">
|
||||
<source>Members can send SimpleX links.</source>
|
||||
<target>Les membres du groupe peuvent envoyer des liens SimpleX.</target>
|
||||
|
@ -4655,6 +4726,10 @@ Voici votre lien pour le groupe %@ !</target>
|
|||
<target>Les membres du groupe peuvent envoyer des messages vocaux.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Mention members 👋" xml:space="preserve">
|
||||
<source>Mention members 👋</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Menus" xml:space="preserve">
|
||||
<source>Menus</source>
|
||||
<target>Menus</target>
|
||||
|
@ -4901,7 +4976,11 @@ Voici votre lien pour le groupe %@ !</target>
|
|||
<trans-unit id="Mute" xml:space="preserve">
|
||||
<source>Mute</source>
|
||||
<target>Muet</target>
|
||||
<note>swipe action</note>
|
||||
<note>notification label action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Mute all" xml:space="preserve">
|
||||
<source>Mute all</source>
|
||||
<note>notification label action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Muted when inactive!" xml:space="preserve">
|
||||
<source>Muted when inactive!</source>
|
||||
|
@ -4953,6 +5032,10 @@ Voici votre lien pour le groupe %@ !</target>
|
|||
<target>État du réseau</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="New" xml:space="preserve">
|
||||
<source>New</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="New Passcode" xml:space="preserve">
|
||||
<source>New Passcode</source>
|
||||
<target>Nouveau code d'accès</target>
|
||||
|
@ -5105,6 +5188,10 @@ Voici votre lien pour le groupe %@ !</target>
|
|||
<target>Pas de serveurs de médias et de fichiers.</target>
|
||||
<note>servers error</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No message" xml:space="preserve">
|
||||
<source>No message</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No message servers." xml:space="preserve">
|
||||
<source>No message servers.</source>
|
||||
<target>Pas de serveurs de messages.</target>
|
||||
|
@ -5160,6 +5247,10 @@ Voici votre lien pour le groupe %@ !</target>
|
|||
<target>Pas de serveurs pour envoyer des fichiers.</target>
|
||||
<note>servers error</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No token!" xml:space="preserve">
|
||||
<source>No token!</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No unread chats" xml:space="preserve">
|
||||
<source>No unread chats</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -5198,11 +5289,19 @@ Voici votre lien pour le groupe %@ !</target>
|
|||
<target>Les notifications sont désactivées !</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Notifications error" xml:space="preserve">
|
||||
<source>Notifications error</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Notifications privacy" xml:space="preserve">
|
||||
<source>Notifications privacy</source>
|
||||
<target>Notifications sécurisées</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Notifications status" xml:space="preserve">
|
||||
<source>Notifications status</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Now admins can: - delete members' messages. - disable members ("observer" role)" xml:space="preserve">
|
||||
<source>Now admins can:
|
||||
- delete members' messages.
|
||||
|
@ -5441,6 +5540,10 @@ Nécessite l'activation d'un VPN.</target>
|
|||
<target>Ou à partager en privé</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Organize chats into lists" xml:space="preserve">
|
||||
<source>Organize chats into lists</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Other" xml:space="preserve">
|
||||
<source>Other</source>
|
||||
<target>Autres</target>
|
||||
|
@ -5632,6 +5735,18 @@ Erreur : %@</target>
|
|||
<target>Veuillez conserver votre phrase secrète en lieu sûr, vous NE pourrez PAS la changer si vous la perdez.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please try to disable and re-enable notfications." xml:space="preserve">
|
||||
<source>Please try to disable and re-enable notfications.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please wait for token activation to complete." xml:space="preserve">
|
||||
<source>Please wait for token activation to complete.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please wait for token to be registered." xml:space="preserve">
|
||||
<source>Please wait for token to be registered.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Polish interface" xml:space="preserve">
|
||||
<source>Polish interface</source>
|
||||
<target>Interface en polonais</target>
|
||||
|
@ -5692,6 +5807,10 @@ Erreur : %@</target>
|
|||
<target>Noms de fichiers privés</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Private media file names." xml:space="preserve">
|
||||
<source>Private media file names.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Private message routing" xml:space="preserve">
|
||||
<source>Private message routing</source>
|
||||
<target>Routage privé des messages</target>
|
||||
|
@ -5767,6 +5886,10 @@ Erreur : %@</target>
|
|||
<target>Interdire les réactions aux messages.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Prohibit reporting messages to moderators." xml:space="preserve">
|
||||
<source>Prohibit reporting messages to moderators.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Prohibit sending SimpleX links." xml:space="preserve">
|
||||
<source>Prohibit sending SimpleX links.</source>
|
||||
<target>Interdire l'envoi de liens SimpleX.</target>
|
||||
|
@ -6024,6 +6147,18 @@ Activez-le dans les paramètres *Réseau et serveurs*.</target>
|
|||
<target>Réduction de la consommation de batterie</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Register" xml:space="preserve">
|
||||
<source>Register</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Register notification token?" xml:space="preserve">
|
||||
<source>Register notification token?</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Registered" xml:space="preserve">
|
||||
<source>Registered</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Reject" xml:space="preserve">
|
||||
<source>Reject</source>
|
||||
<target>Rejeter</target>
|
||||
|
@ -6153,6 +6288,14 @@ Activez-le dans les paramètres *Réseau et serveurs*.</target>
|
|||
<source>Report violation: only group moderators will see it.</source>
|
||||
<note>report reason</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Report: %@" xml:space="preserve">
|
||||
<source>Report: %@</source>
|
||||
<note>report in notification</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Reporting messages to moderators is prohibited." xml:space="preserve">
|
||||
<source>Reporting messages to moderators is prohibited.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Reports" xml:space="preserve">
|
||||
<source>Reports</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -6577,6 +6720,10 @@ Activez-le dans les paramètres *Réseau et serveurs*.</target>
|
|||
<target>Envoi de notifications</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Send private reports" xml:space="preserve">
|
||||
<source>Send private reports</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Send questions and ideas" xml:space="preserve">
|
||||
<source>Send questions and ideas</source>
|
||||
<target>Envoyez vos questions et idées</target>
|
||||
|
@ -6816,6 +6963,10 @@ Activez-le dans les paramètres *Réseau et serveurs*.</target>
|
|||
<target>Il permet de remplacer l'authentification du système.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Set message expiration in chats." xml:space="preserve">
|
||||
<source>Set message expiration in chats.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Set passcode" xml:space="preserve">
|
||||
<source>Set passcode</source>
|
||||
<target>Définir le code d'accès</target>
|
||||
|
@ -7278,6 +7429,10 @@ Activez-le dans les paramètres *Réseau et serveurs*.</target>
|
|||
<target>Délai de connexion TCP</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="TCP port for messaging" xml:space="preserve">
|
||||
<source>TCP port for messaging</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="TCP_KEEPCNT" xml:space="preserve">
|
||||
<source>TCP_KEEPCNT</source>
|
||||
<target>TCP_KEEPCNT</target>
|
||||
|
@ -7353,6 +7508,10 @@ Activez-le dans les paramètres *Réseau et serveurs*.</target>
|
|||
<target>Échec du test à l'étape %@.</target>
|
||||
<note>server test failure</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Test notifications" xml:space="preserve">
|
||||
<source>Test notifications</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Test server" xml:space="preserve">
|
||||
<source>Test server</source>
|
||||
<target>Tester le serveur</target>
|
||||
|
@ -7480,10 +7639,6 @@ Cela peut se produire en raison d'un bug ou lorsque la connexion est compromise.
|
|||
<target>Le profil n'est partagé qu'avec vos contacts.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="The report will be archived for you." xml:space="preserve">
|
||||
<source>The report will be archived for you.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve">
|
||||
<source>The same conditions will apply to operator **%@**.</source>
|
||||
<target>Les mêmes conditions s'appliquent à l'opérateur **%@**.</target>
|
||||
|
@ -7613,6 +7768,10 @@ Cela peut se produire en raison d'un bug ou lorsque la connexion est compromise.
|
|||
<target>Ce lien a été utilisé avec un autre appareil mobile, veuillez créer un nouveau lien sur le bureau.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="This message was deleted or not received yet." xml:space="preserve">
|
||||
<source>This message was deleted or not received yet.</source>
|
||||
<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">
|
||||
<source>This setting applies to messages in your current chat profile **%@**.</source>
|
||||
<target>Ce paramètre s'applique aux messages de votre profil de chat actuel **%@**.</target>
|
||||
|
@ -7725,6 +7884,10 @@ Vous serez invité à confirmer l'authentification avant que cette fonction ne s
|
|||
<target>Basculer en mode incognito lors de la connexion.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Token status: %@." xml:space="preserve">
|
||||
<source>Token status: %@.</source>
|
||||
<note>token status</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Toolbar opacity" xml:space="preserve">
|
||||
<source>Toolbar opacity</source>
|
||||
<target>Opacité de la barre d'outils</target>
|
||||
|
@ -7890,7 +8053,7 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien
|
|||
<trans-unit id="Unmute" xml:space="preserve">
|
||||
<source>Unmute</source>
|
||||
<target>Démute</target>
|
||||
<note>swipe action</note>
|
||||
<note>notification label action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Unread" xml:space="preserve">
|
||||
<source>Unread</source>
|
||||
|
@ -7922,6 +8085,10 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien
|
|||
<target>Mettre à jour les paramètres ?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Updated conditions" xml:space="preserve">
|
||||
<source>Updated conditions</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Updating settings will re-connect the client to all servers." xml:space="preserve">
|
||||
<source>Updating settings will re-connect the client to all servers.</source>
|
||||
<target>La mise à jour des ces paramètres reconnectera le client à tous les serveurs.</target>
|
||||
|
@ -7982,6 +8149,10 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien
|
|||
<target>Utiliser les serveurs SimpleX Chat ?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use TCP port %@ when no port is specified." xml:space="preserve">
|
||||
<source>Use TCP port %@ when no port is specified.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use chat" xml:space="preserve">
|
||||
<source>Use chat</source>
|
||||
<target>Utiliser le chat</target>
|
||||
|
@ -8057,6 +8228,10 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien
|
|||
<target>Utiliser l'application d'une main.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use web port" xml:space="preserve">
|
||||
<source>Use web port</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="User selection" xml:space="preserve">
|
||||
<source>User selection</source>
|
||||
<target>Sélection de l'utilisateur</target>
|
||||
|
@ -8610,6 +8785,10 @@ Répéter la demande de connexion ?</target>
|
|||
<target>Vous avez envoyé une invitation de groupe</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="You should receive notifications." xml:space="preserve">
|
||||
<source>You should receive notifications.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="You will be connected to group when the group host's device is online, please wait or check later!" xml:space="preserve">
|
||||
<source>You will be connected to group when the group host's device is online, please wait or check later!</source>
|
||||
<target>Vous serez connecté·e au groupe lorsque l'appareil de l'hôte sera en ligne, veuillez attendre ou vérifier plus tard !</target>
|
||||
|
@ -9404,11 +9583,6 @@ Répéter la demande de connexion ?</target>
|
|||
<target>mois</target>
|
||||
<note>time unit</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="mute" xml:space="preserve">
|
||||
<source>mute</source>
|
||||
<target>muet</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="never" xml:space="preserve">
|
||||
<source>never</source>
|
||||
<target>jamais</target>
|
||||
|
@ -9486,6 +9660,14 @@ Répéter la demande de connexion ?</target>
|
|||
<target>pair-à-pair</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="pending" xml:space="preserve">
|
||||
<source>pending</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="pending approval" xml:space="preserve">
|
||||
<source>pending approval</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="quantum resistant e2e encryption" xml:space="preserve">
|
||||
<source>quantum resistant e2e encryption</source>
|
||||
<target>chiffrement e2e résistant post-quantique</target>
|
||||
|
@ -9501,6 +9683,10 @@ Répéter la demande de connexion ?</target>
|
|||
<target>confimation reçu…</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="rejected" xml:space="preserve">
|
||||
<source>rejected</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="rejected call" xml:space="preserve">
|
||||
<source>rejected call</source>
|
||||
<target>appel rejeté</target>
|
||||
|
@ -9635,11 +9821,6 @@ dernier message reçu : %2$@</target>
|
|||
<target>statut inconnu</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="unmute" xml:space="preserve">
|
||||
<source>unmute</source>
|
||||
<target>démuter</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="unprotected" xml:space="preserve">
|
||||
<source>unprotected</source>
|
||||
<target>non protégé</target>
|
||||
|
|
|
@ -1693,12 +1693,14 @@ We will be adding server redundancy to prevent lost messages.</source>
|
|||
<source>Live message!</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Live messages" xml:space="preserve">
|
||||
<trans-unit id="Live messages" xml:space="preserve" approved="no">
|
||||
<source>Live messages</source>
|
||||
<target state="translated">Žive poruke</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Local name" xml:space="preserve">
|
||||
<trans-unit id="Local name" xml:space="preserve" approved="no">
|
||||
<source>Local name</source>
|
||||
<target state="translated">Lokalno ime</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Local profile data only" xml:space="preserve">
|
||||
|
@ -3715,6 +3717,14 @@ SimpleX servers cannot see your profile.</source>
|
|||
<source>Immediately</source>
|
||||
<target state="translated">Odmah</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="Address settings" xml:space="preserve" approved="no">
|
||||
<source>Address settings</source>
|
||||
<target state="translated">Podešavanje adrese</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="Admins can block a member for all." xml:space="preserve" approved="no">
|
||||
<source>Admins can block a member for all.</source>
|
||||
<target state="needs-translation">Administratori mogu da blokiraju</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
<file original="en.lproj/SimpleX--iOS--InfoPlist.strings" source-language="en" target-language="hr" datatype="plaintext">
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -5,22 +5,6 @@
|
|||
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.4" build-num="15F31d"/>
|
||||
</header>
|
||||
<body>
|
||||
<trans-unit id=" " xml:space="preserve">
|
||||
<source>
|
||||
</source>
|
||||
<target>
|
||||
</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=" " xml:space="preserve">
|
||||
<source> </source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=" (" xml:space="preserve">
|
||||
<source> (</source>
|
||||
<target> (</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=" (can be copied)" xml:space="preserve">
|
||||
<source> (can be copied)</source>
|
||||
<target> (コピー可能)</target>
|
||||
|
@ -330,11 +314,6 @@
|
|||
<target>%u 件のメッセージがスキップされました。</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="(" xml:space="preserve">
|
||||
<source>(</source>
|
||||
<target>(</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="(new)" xml:space="preserve">
|
||||
<source>(new)</source>
|
||||
<target>(新規)</target>
|
||||
|
@ -345,11 +324,6 @@
|
|||
<target>(このデバイス v%@)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=")" xml:space="preserve">
|
||||
<source>)</source>
|
||||
<target>)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="**Create 1-time link**: to create and share a new invitation link." xml:space="preserve">
|
||||
<source>**Create 1-time link**: to create and share a new invitation link.</source>
|
||||
<target>**コンタクトの追加**: 新しい招待リンクを作成するか、受け取ったリンクから接続します。</target>
|
||||
|
@ -415,11 +389,6 @@
|
|||
<target>\*太字*</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=", " xml:space="preserve">
|
||||
<source>, </source>
|
||||
<target>, </target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="- connect to [directory service](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (BETA)! - delivery receipts (up to 20 members). - faster and more stable." xml:space="preserve">
|
||||
<source>- connect to [directory service](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (BETA)!
|
||||
- delivery receipts (up to 20 members).
|
||||
|
@ -456,11 +425,6 @@
|
|||
- 編集履歴。</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="." xml:space="preserve">
|
||||
<source>.</source>
|
||||
<target>.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="0 sec" xml:space="preserve">
|
||||
<source>0 sec</source>
|
||||
<target>0 秒</target>
|
||||
|
@ -528,11 +492,6 @@
|
|||
<target>30秒</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=": " xml:space="preserve">
|
||||
<source>: </source>
|
||||
<target>: </target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="<p>Hi!</p> <p><a href="%@">Connect to me via SimpleX Chat</a></p>" xml:space="preserve">
|
||||
<source><p>Hi!</p>
|
||||
<p><a href="%@">Connect to me via SimpleX Chat</a></p></source>
|
||||
|
@ -634,6 +593,10 @@
|
|||
<source>Acknowledgement errors</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Active" xml:space="preserve">
|
||||
<source>Active</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Active connections" xml:space="preserve">
|
||||
<source>Active connections</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -761,8 +724,8 @@
|
|||
<target>全チャットとメッセージが削除されます(※元に戻せません※)!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All chats will be removed from the list (text), and the list deleted." xml:space="preserve">
|
||||
<source>All chats will be removed from the list (text), and the list deleted.</source>
|
||||
<trans-unit id="All chats will be removed from the list %@, and the list deleted." xml:space="preserve">
|
||||
<source>All chats will be removed from the list %@, and the list deleted.</source>
|
||||
<note>alert message</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All data is erased when it is entered." xml:space="preserve">
|
||||
|
@ -801,6 +764,10 @@
|
|||
<target>すべてのプロフィール</target>
|
||||
<note>profile dropdown</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All reports will be archived for you." xml:space="preserve">
|
||||
<source>All reports will be archived for you.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
||||
<source>All your contacts will remain connected.</source>
|
||||
<target>あなたの連絡先が繋がったまま継続します。</target>
|
||||
|
@ -874,6 +841,10 @@
|
|||
<target>送信済みメッセージの永久削除を許可する。(24時間)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Allow to report messsages to moderators." xml:space="preserve">
|
||||
<source>Allow to report messsages to moderators.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Allow to send SimpleX links." xml:space="preserve">
|
||||
<source>Allow to send SimpleX links.</source>
|
||||
<target>SimpleXリンクの送信を許可。</target>
|
||||
|
@ -1035,6 +1006,14 @@
|
|||
<source>Archive</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive %lld reports?" xml:space="preserve">
|
||||
<source>Archive %lld reports?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive all reports?" xml:space="preserve">
|
||||
<source>Archive all reports?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive and upload" xml:space="preserve">
|
||||
<source>Archive and upload</source>
|
||||
<target>アーカイブとアップロード</target>
|
||||
|
@ -1052,6 +1031,10 @@
|
|||
<source>Archive report?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive reports" xml:space="preserve">
|
||||
<source>Archive reports</source>
|
||||
<note>swipe action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archived contacts" xml:space="preserve">
|
||||
<source>Archived contacts</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -1159,6 +1142,10 @@
|
|||
<source>Better groups</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better groups performance" xml:space="preserve">
|
||||
<source>Better groups performance</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better message dates." xml:space="preserve">
|
||||
<source>Better message dates.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -1176,6 +1163,10 @@
|
|||
<source>Better notifications</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better privacy and security" xml:space="preserve">
|
||||
<source>Better privacy and security</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better security ✅" xml:space="preserve">
|
||||
<source>Better security ✅</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -1557,6 +1548,10 @@
|
|||
<target>ダイアログのクリアしますか?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Clear group?" xml:space="preserve">
|
||||
<source>Clear group?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Clear or delete group?" xml:space="preserve">
|
||||
<source>Clear or delete group?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -1685,6 +1680,10 @@
|
|||
<source>Confirm upload</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Confirmed" xml:space="preserve">
|
||||
<source>Confirmed</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Connect" xml:space="preserve">
|
||||
<source>Connect</source>
|
||||
<target>接続</target>
|
||||
|
@ -2628,6 +2627,10 @@ This is your own one-time link!</source>
|
|||
<target>有効にしない</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Don't miss important messages." xml:space="preserve">
|
||||
<source>Don't miss important messages.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Don't show again" xml:space="preserve">
|
||||
<source>Don't show again</source>
|
||||
<target>次から表示しない</target>
|
||||
|
@ -2957,6 +2960,10 @@ This is your own one-time link!</source>
|
|||
<source>Error changing to incognito!</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error checking token status" xml:space="preserve">
|
||||
<source>Error checking token status</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error connecting to forwarding server %@. Please try later." xml:space="preserve">
|
||||
<source>Error connecting to forwarding server %@. Please try later.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -3100,6 +3107,10 @@ This is your own one-time link!</source>
|
|||
<source>Error reconnecting servers</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error registering for notifications" xml:space="preserve">
|
||||
<source>Error registering for notifications</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error removing member" xml:space="preserve">
|
||||
<source>Error removing member</source>
|
||||
<target>メンバー除名にエラー発生</target>
|
||||
|
@ -3197,6 +3208,10 @@ This is your own one-time link!</source>
|
|||
<target>接続の同期エラー</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error testing server connection" xml:space="preserve">
|
||||
<source>Error testing server connection</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error updating group link" xml:space="preserve">
|
||||
<source>Error updating group link</source>
|
||||
<target>グループのリンクのアップデートにエラー発生</target>
|
||||
|
@ -3271,6 +3286,10 @@ This is your own one-time link!</source>
|
|||
<source>Expand</source>
|
||||
<note>chat item action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Expired" xml:space="preserve">
|
||||
<source>Expired</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Export database" xml:space="preserve">
|
||||
<source>Export database</source>
|
||||
<target>データベースをエキスポート</target>
|
||||
|
@ -3309,10 +3328,18 @@ This is your own one-time link!</source>
|
|||
<target>送信者がオンラインになるまでの待ち時間がなく、速い!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Faster deletion of groups." xml:space="preserve">
|
||||
<source>Faster deletion of groups.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Faster joining and more reliable messages." xml:space="preserve">
|
||||
<source>Faster joining and more reliable messages.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Faster sending messages." xml:space="preserve">
|
||||
<source>Faster sending messages.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Favorite" xml:space="preserve">
|
||||
<source>Favorite</source>
|
||||
<target>お気に入り</target>
|
||||
|
@ -3331,9 +3358,9 @@ This is your own one-time link!</source>
|
|||
%@</source>
|
||||
<note>alert message</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="File is blocked by server operator: (info.reason.text)." xml:space="preserve">
|
||||
<trans-unit id="File is blocked by server operator: %@." xml:space="preserve">
|
||||
<source>File is blocked by server operator:
|
||||
(info.reason.text).</source>
|
||||
%@.</source>
|
||||
<note>file error text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="File not found - most likely file was deleted or cancelled." xml:space="preserve">
|
||||
|
@ -3453,6 +3480,10 @@ This is your own one-time link!</source>
|
|||
<target>グループメンバーによる修正はサポートされていません</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For all moderators" xml:space="preserve">
|
||||
<source>For all moderators</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For chat profile %@:" xml:space="preserve">
|
||||
<source>For chat profile %@:</source>
|
||||
<note>servers error</note>
|
||||
|
@ -3466,6 +3497,10 @@ This is your own one-time link!</source>
|
|||
<source>For example, if your contact receives messages via a SimpleX Chat server, your app will deliver them via a Flux server.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For me" xml:space="preserve">
|
||||
<source>For me</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For private routing" xml:space="preserve">
|
||||
<source>For private routing</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -3570,6 +3605,10 @@ Error: %2$@</source>
|
|||
<target>GIFとステッカー</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Get notified when mentioned." xml:space="preserve">
|
||||
<source>Get notified when mentioned.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Good afternoon!" xml:space="preserve">
|
||||
<source>Good afternoon!</source>
|
||||
<note>message preview</note>
|
||||
|
@ -3680,6 +3719,10 @@ Error: %2$@</source>
|
|||
<target>ヘルプ</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Help admins moderating their groups." xml:space="preserve">
|
||||
<source>Help admins moderating their groups.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Hidden" xml:space="preserve">
|
||||
<source>Hidden</source>
|
||||
<target>プライベート</target>
|
||||
|
@ -3970,6 +4013,26 @@ More improvements are coming soon!</source>
|
|||
<source>Interface colors</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid" xml:space="preserve">
|
||||
<source>Invalid</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (bad token)" xml:space="preserve">
|
||||
<source>Invalid (bad token)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (expired)" xml:space="preserve">
|
||||
<source>Invalid (expired)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (unregistered)" xml:space="preserve">
|
||||
<source>Invalid (unregistered)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (wrong topic)" xml:space="preserve">
|
||||
<source>Invalid (wrong topic)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid QR code" xml:space="preserve">
|
||||
<source>Invalid QR code</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -4320,6 +4383,10 @@ This is your link for group %@!</source>
|
|||
<source>Member inactive</source>
|
||||
<note>item status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Member reports" xml:space="preserve">
|
||||
<source>Member reports</source>
|
||||
<note>chat feature</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Member role will be changed to "%@". All chat members will be notified." xml:space="preserve">
|
||||
<source>Member role will be changed to "%@". All chat members will be notified.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -4353,6 +4420,10 @@ This is your link for group %@!</source>
|
|||
<target>グループのメンバーがメッセージを完全削除することができます。(24時間)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Members can report messsages to moderators." xml:space="preserve">
|
||||
<source>Members can report messsages to moderators.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Members can send SimpleX links." xml:space="preserve">
|
||||
<source>Members can send SimpleX links.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -4377,6 +4448,10 @@ This is your link for group %@!</source>
|
|||
<target>グループのメンバーが音声メッセージを送信できます。</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Mention members 👋" xml:space="preserve">
|
||||
<source>Mention members 👋</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Menus" xml:space="preserve">
|
||||
<source>Menus</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -4598,7 +4673,11 @@ This is your link for group %@!</source>
|
|||
<trans-unit id="Mute" xml:space="preserve">
|
||||
<source>Mute</source>
|
||||
<target>ミュート</target>
|
||||
<note>swipe action</note>
|
||||
<note>notification label action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Mute all" xml:space="preserve">
|
||||
<source>Mute all</source>
|
||||
<note>notification label action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Muted when inactive!" xml:space="preserve">
|
||||
<source>Muted when inactive!</source>
|
||||
|
@ -4645,6 +4724,10 @@ This is your link for group %@!</source>
|
|||
<target>ネットワーク状況</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="New" xml:space="preserve">
|
||||
<source>New</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="New Passcode" xml:space="preserve">
|
||||
<source>New Passcode</source>
|
||||
<target>新しいパスコード</target>
|
||||
|
@ -4787,6 +4870,10 @@ This is your link for group %@!</source>
|
|||
<source>No media & file servers.</source>
|
||||
<note>servers error</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No message" xml:space="preserve">
|
||||
<source>No message</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No message servers." xml:space="preserve">
|
||||
<source>No message servers.</source>
|
||||
<note>servers error</note>
|
||||
|
@ -4834,6 +4921,10 @@ This is your link for group %@!</source>
|
|||
<source>No servers to send files.</source>
|
||||
<note>servers error</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No token!" xml:space="preserve">
|
||||
<source>No token!</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No unread chats" xml:space="preserve">
|
||||
<source>No unread chats</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -4869,10 +4960,18 @@ This is your link for group %@!</source>
|
|||
<target>通知が無効になっています!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Notifications error" xml:space="preserve">
|
||||
<source>Notifications error</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Notifications privacy" xml:space="preserve">
|
||||
<source>Notifications privacy</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Notifications status" xml:space="preserve">
|
||||
<source>Notifications status</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Now admins can: - delete members' messages. - disable members ("observer" role)" xml:space="preserve">
|
||||
<source>Now admins can:
|
||||
- delete members' messages.
|
||||
|
@ -5095,6 +5194,10 @@ VPN を有効にする必要があります。</target>
|
|||
<source>Or to share privately</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Organize chats into lists" xml:space="preserve">
|
||||
<source>Organize chats into lists</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Other" xml:space="preserve">
|
||||
<source>Other</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -5269,6 +5372,18 @@ Error: %@</source>
|
|||
<target>パスフレーズを失くさないように保管してください。失くすと変更できなくなります。</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please try to disable and re-enable notfications." xml:space="preserve">
|
||||
<source>Please try to disable and re-enable notfications.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please wait for token activation to complete." xml:space="preserve">
|
||||
<source>Please wait for token activation to complete.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please wait for token to be registered." xml:space="preserve">
|
||||
<source>Please wait for token to be registered.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Polish interface" xml:space="preserve">
|
||||
<source>Polish interface</source>
|
||||
<target>ポーランド語UI</target>
|
||||
|
@ -5325,6 +5440,10 @@ Error: %@</source>
|
|||
<target>プライベートなファイル名</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Private media file names." xml:space="preserve">
|
||||
<source>Private media file names.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Private message routing" xml:space="preserve">
|
||||
<source>Private message routing</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -5394,6 +5513,10 @@ Error: %@</source>
|
|||
<target>メッセージへのリアクションは禁止されています。</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Prohibit reporting messages to moderators." xml:space="preserve">
|
||||
<source>Prohibit reporting messages to moderators.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Prohibit sending SimpleX links." xml:space="preserve">
|
||||
<source>Prohibit sending SimpleX links.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -5628,6 +5751,18 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>電池使用量低減</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Register" xml:space="preserve">
|
||||
<source>Register</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Register notification token?" xml:space="preserve">
|
||||
<source>Register notification token?</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Registered" xml:space="preserve">
|
||||
<source>Registered</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Reject" xml:space="preserve">
|
||||
<source>Reject</source>
|
||||
<target>拒否</target>
|
||||
|
@ -5750,6 +5885,14 @@ Enable in *Network & servers* settings.</source>
|
|||
<source>Report violation: only group moderators will see it.</source>
|
||||
<note>report reason</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Report: %@" xml:space="preserve">
|
||||
<source>Report: %@</source>
|
||||
<note>report in notification</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Reporting messages to moderators is prohibited." xml:space="preserve">
|
||||
<source>Reporting messages to moderators is prohibited.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Reports" xml:space="preserve">
|
||||
<source>Reports</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -6141,6 +6284,10 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>通知を送信する</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Send private reports" xml:space="preserve">
|
||||
<source>Send private reports</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Send questions and ideas" xml:space="preserve">
|
||||
<source>Send questions and ideas</source>
|
||||
<target>質問やアイデアを送る</target>
|
||||
|
@ -6352,6 +6499,10 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>システム認証の代わりに設定します。</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Set message expiration in chats." xml:space="preserve">
|
||||
<source>Set message expiration in chats.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Set passcode" xml:space="preserve">
|
||||
<source>Set passcode</source>
|
||||
<target>パスコードを設定する</target>
|
||||
|
@ -6773,6 +6924,10 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>TCP接続タイムアウト</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="TCP port for messaging" xml:space="preserve">
|
||||
<source>TCP port for messaging</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="TCP_KEEPCNT" xml:space="preserve">
|
||||
<source>TCP_KEEPCNT</source>
|
||||
<target>TCP_KEEPCNT</target>
|
||||
|
@ -6842,6 +6997,10 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>テストはステップ %@ で失敗しました。</target>
|
||||
<note>server test failure</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Test notifications" xml:space="preserve">
|
||||
<source>Test notifications</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Test server" xml:space="preserve">
|
||||
<source>Test server</source>
|
||||
<target>テストサーバ</target>
|
||||
|
@ -6963,10 +7122,6 @@ It can happen because of some bug or when the connection is compromised.</source
|
|||
<target>プロフィールは連絡先にしか共有されません。</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="The report will be archived for you." xml:space="preserve">
|
||||
<source>The report will be archived for you.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve">
|
||||
<source>The same conditions will apply to operator **%@**.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -7080,6 +7235,10 @@ It can happen because of some bug or when the connection is compromised.</source
|
|||
<source>This link was used with another mobile device, please create a new link on the desktop.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="This message was deleted or not received yet." xml:space="preserve">
|
||||
<source>This message was deleted or not received yet.</source>
|
||||
<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">
|
||||
<source>This setting applies to messages in your current chat profile **%@**.</source>
|
||||
<target>この設定は現在のチャットプロフィール **%@** のメッセージに適用されます。</target>
|
||||
|
@ -7181,6 +7340,10 @@ You will be prompted to complete authentication before this feature is enabled.<
|
|||
<source>Toggle incognito when connecting.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Token status: %@." xml:space="preserve">
|
||||
<source>Token status: %@.</source>
|
||||
<note>token status</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Toolbar opacity" xml:space="preserve">
|
||||
<source>Toolbar opacity</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -7333,7 +7496,7 @@ To connect, please ask your contact to create another connection link and check
|
|||
<trans-unit id="Unmute" xml:space="preserve">
|
||||
<source>Unmute</source>
|
||||
<target>ミュート解除</target>
|
||||
<note>swipe action</note>
|
||||
<note>notification label action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Unread" xml:space="preserve">
|
||||
<source>Unread</source>
|
||||
|
@ -7363,6 +7526,10 @@ To connect, please ask your contact to create another connection link and check
|
|||
<source>Update settings?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Updated conditions" xml:space="preserve">
|
||||
<source>Updated conditions</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Updating settings will re-connect the client to all servers." xml:space="preserve">
|
||||
<source>Updating settings will re-connect the client to all servers.</source>
|
||||
<target>設定を更新すると、全サーバにクライントの再接続が行われます。</target>
|
||||
|
@ -7416,6 +7583,10 @@ To connect, please ask your contact to create another connection link and check
|
|||
<target>SimpleX チャット サーバーを使用しますか?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use TCP port %@ when no port is specified." xml:space="preserve">
|
||||
<source>Use TCP port %@ when no port is specified.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use chat" xml:space="preserve">
|
||||
<source>Use chat</source>
|
||||
<target>チャット</target>
|
||||
|
@ -7482,6 +7653,10 @@ To connect, please ask your contact to create another connection link and check
|
|||
<source>Use the app with one hand.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use web port" xml:space="preserve">
|
||||
<source>Use web port</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="User selection" xml:space="preserve">
|
||||
<source>User selection</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -7981,6 +8156,10 @@ Repeat connection request?</source>
|
|||
<target>グループの招待を送りました</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="You should receive notifications." xml:space="preserve">
|
||||
<source>You should receive notifications.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="You will be connected to group when the group host's device is online, please wait or check later!" xml:space="preserve">
|
||||
<source>You will be connected to group when the group host's device is online, please wait or check later!</source>
|
||||
<target>グループのホスト端末がオンラインになったら、接続されます。後でチェックするか、しばらくお待ちください!</target>
|
||||
|
@ -8744,10 +8923,6 @@ Repeat connection request?</source>
|
|||
<target>月</target>
|
||||
<note>time unit</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="mute" xml:space="preserve">
|
||||
<source>mute</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="never" xml:space="preserve">
|
||||
<source>never</source>
|
||||
<target>一度も</target>
|
||||
|
@ -8822,6 +8997,14 @@ Repeat connection request?</source>
|
|||
<target>P2P</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="pending" xml:space="preserve">
|
||||
<source>pending</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="pending approval" xml:space="preserve">
|
||||
<source>pending approval</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="quantum resistant e2e encryption" xml:space="preserve">
|
||||
<source>quantum resistant e2e encryption</source>
|
||||
<note>chat item text</note>
|
||||
|
@ -8836,6 +9019,10 @@ Repeat connection request?</source>
|
|||
<target>確認を受け取りました…</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="rejected" xml:space="preserve">
|
||||
<source>rejected</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="rejected call" xml:space="preserve">
|
||||
<source>rejected call</source>
|
||||
<target>拒否した通話</target>
|
||||
|
@ -8954,10 +9141,6 @@ last received msg: %2$@</source>
|
|||
<source>unknown status</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="unmute" xml:space="preserve">
|
||||
<source>unmute</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="unprotected" xml:space="preserve">
|
||||
<source>unprotected</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -5,22 +5,6 @@
|
|||
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.4" build-num="15F31d"/>
|
||||
</header>
|
||||
<body>
|
||||
<trans-unit id=" " xml:space="preserve">
|
||||
<source>
|
||||
</source>
|
||||
<target>
|
||||
</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=" " xml:space="preserve">
|
||||
<source> </source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=" (" xml:space="preserve">
|
||||
<source> (</source>
|
||||
<target> (</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=" (can be copied)" xml:space="preserve">
|
||||
<source> (can be copied)</source>
|
||||
<target> (można skopiować)</target>
|
||||
|
@ -208,6 +192,7 @@
|
|||
</trans-unit>
|
||||
<trans-unit id="%d seconds(s)" xml:space="preserve">
|
||||
<source>%d seconds(s)</source>
|
||||
<target>%d sekundach</target>
|
||||
<note>delete after time</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="%d skipped message(s)" xml:space="preserve">
|
||||
|
@ -330,11 +315,6 @@
|
|||
<target>%u pominiętych wiadomości.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="(" xml:space="preserve">
|
||||
<source>(</source>
|
||||
<target>(</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="(new)" xml:space="preserve">
|
||||
<source>(new)</source>
|
||||
<target>(nowy)</target>
|
||||
|
@ -345,11 +325,6 @@
|
|||
<target>(to urządzenie v%@)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=")" xml:space="preserve">
|
||||
<source>)</source>
|
||||
<target>)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="**Create 1-time link**: to create and share a new invitation link." xml:space="preserve">
|
||||
<source>**Create 1-time link**: to create and share a new invitation link.</source>
|
||||
<target>**Dodaj kontakt**: aby utworzyć nowy link z zaproszeniem lub połączyć się za pomocą otrzymanego linku.</target>
|
||||
|
@ -415,11 +390,6 @@
|
|||
<target>\*pogrubiony*</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=", " xml:space="preserve">
|
||||
<source>, </source>
|
||||
<target>, </target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="- connect to [directory service](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (BETA)! - delivery receipts (up to 20 members). - faster and more stable." xml:space="preserve">
|
||||
<source>- connect to [directory service](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (BETA)!
|
||||
- delivery receipts (up to 20 members).
|
||||
|
@ -456,11 +426,6 @@
|
|||
- historia edycji.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="." xml:space="preserve">
|
||||
<source>.</source>
|
||||
<target>.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="0 sec" xml:space="preserve">
|
||||
<source>0 sec</source>
|
||||
<target>0 sek</target>
|
||||
|
@ -501,6 +466,7 @@
|
|||
</trans-unit>
|
||||
<trans-unit id="1 year" xml:space="preserve">
|
||||
<source>1 year</source>
|
||||
<target>1 roku</target>
|
||||
<note>delete after time</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="1-time link" xml:space="preserve">
|
||||
|
@ -528,11 +494,6 @@
|
|||
<target>30 sekund</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=": " xml:space="preserve">
|
||||
<source>: </source>
|
||||
<target>: </target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="<p>Hi!</p> <p><a href="%@">Connect to me via SimpleX Chat</a></p>" xml:space="preserve">
|
||||
<source><p>Hi!</p>
|
||||
<p><a href="%@">Connect to me via SimpleX Chat</a></p></source>
|
||||
|
@ -640,6 +601,11 @@
|
|||
<target>Błędy potwierdzenia</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Active" xml:space="preserve">
|
||||
<source>Active</source>
|
||||
<target>Aktywne</target>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Active connections" xml:space="preserve">
|
||||
<source>Active connections</source>
|
||||
<target>Aktywne połączenia</target>
|
||||
|
@ -657,6 +623,7 @@
|
|||
</trans-unit>
|
||||
<trans-unit id="Add list" xml:space="preserve">
|
||||
<source>Add list</source>
|
||||
<target>Dodaj listę</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Add profile" xml:space="preserve">
|
||||
|
@ -686,6 +653,7 @@
|
|||
</trans-unit>
|
||||
<trans-unit id="Add to list" xml:space="preserve">
|
||||
<source>Add to list</source>
|
||||
<target>Dodaj do listy</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Add welcome message" xml:space="preserve">
|
||||
|
@ -765,6 +733,7 @@
|
|||
</trans-unit>
|
||||
<trans-unit id="All" xml:space="preserve">
|
||||
<source>All</source>
|
||||
<target>Wszystko</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All app data is deleted." xml:space="preserve">
|
||||
|
@ -777,8 +746,9 @@
|
|||
<target>Wszystkie czaty i wiadomości zostaną usunięte - nie można tego cofnąć!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All chats will be removed from the list (text), and the list deleted." xml:space="preserve">
|
||||
<source>All chats will be removed from the list (text), and the list deleted.</source>
|
||||
<trans-unit id="All chats will be removed from the list %@, and the list deleted." xml:space="preserve">
|
||||
<source>All chats will be removed from the list %@, and the list deleted.</source>
|
||||
<target>Wszystkie rozmowy zostaną usunięte z listy %@, a lista usunięta.</target>
|
||||
<note>alert message</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All data is erased when it is entered." xml:space="preserve">
|
||||
|
@ -798,6 +768,7 @@
|
|||
</trans-unit>
|
||||
<trans-unit id="All messages and files are sent **end-to-end encrypted**, with post-quantum security in direct messages." xml:space="preserve">
|
||||
<source>All messages and files are sent **end-to-end encrypted**, with post-quantum security in direct messages.</source>
|
||||
<target>Wszystkie wiadomości i pliki są wysyłane **z szyfrowaniem end-to-end**, z bezpieczeństwem postkwantowym w wiadomościach bezpośrednich.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All messages will be deleted - this cannot be undone!" xml:space="preserve">
|
||||
|
@ -820,6 +791,11 @@
|
|||
<target>Wszystkie profile</target>
|
||||
<note>profile dropdown</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All reports will be archived for you." xml:space="preserve">
|
||||
<source>All reports will be archived for you.</source>
|
||||
<target>Wszystkie raporty zostaną dla Ciebie zarchiwizowane.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
||||
<source>All your contacts will remain connected.</source>
|
||||
<target>Wszystkie Twoje kontakty pozostaną połączone.</target>
|
||||
|
@ -895,6 +871,11 @@
|
|||
<target>Zezwól na nieodwracalne usunięcie wysłanych wiadomości. (24 godziny)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Allow to report messsages to moderators." xml:space="preserve">
|
||||
<source>Allow to report messsages to moderators.</source>
|
||||
<target>Zezwól na zgłaszanie wiadomości moderatorom.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Allow to send SimpleX links." xml:space="preserve">
|
||||
<source>Allow to send SimpleX links.</source>
|
||||
<target>Zezwól na wysyłanie linków SimpleX.</target>
|
||||
|
@ -977,6 +958,7 @@
|
|||
</trans-unit>
|
||||
<trans-unit id="Another reason" xml:space="preserve">
|
||||
<source>Another reason</source>
|
||||
<target>Inny powód</target>
|
||||
<note>report reason</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Answer call" xml:space="preserve">
|
||||
|
@ -1006,6 +988,7 @@
|
|||
</trans-unit>
|
||||
<trans-unit id="App group:" xml:space="preserve">
|
||||
<source>App group:</source>
|
||||
<target>Grupa aplikacji:</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="App icon" xml:space="preserve">
|
||||
|
@ -1055,6 +1038,17 @@
|
|||
</trans-unit>
|
||||
<trans-unit id="Archive" xml:space="preserve">
|
||||
<source>Archive</source>
|
||||
<target>Archiwizuj</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive %lld reports?" xml:space="preserve">
|
||||
<source>Archive %lld reports?</source>
|
||||
<target>Archiwizować %lld reports?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive all reports?" xml:space="preserve">
|
||||
<source>Archive all reports?</source>
|
||||
<target>Archiwizować wszystkie zgłoszenia?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive and upload" xml:space="preserve">
|
||||
|
@ -1069,12 +1063,19 @@
|
|||
</trans-unit>
|
||||
<trans-unit id="Archive report" xml:space="preserve">
|
||||
<source>Archive report</source>
|
||||
<target>Archiwizuj zgłoszenie</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive report?" xml:space="preserve">
|
||||
<source>Archive report?</source>
|
||||
<target>Archiwizować zgłoszenie?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive reports" xml:space="preserve">
|
||||
<source>Archive reports</source>
|
||||
<target>Archiwizuj zgłoszenia</target>
|
||||
<note>swipe action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archived contacts" xml:space="preserve">
|
||||
<source>Archived contacts</source>
|
||||
<target>Zarchiwizowane kontakty</target>
|
||||
|
@ -1087,6 +1088,7 @@
|
|||
</trans-unit>
|
||||
<trans-unit id="Ask" xml:space="preserve">
|
||||
<source>Ask</source>
|
||||
<target>Zapytaj</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Attach" xml:space="preserve">
|
||||
|
@ -1189,6 +1191,10 @@
|
|||
<target>Lepsze grupy</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better groups performance" xml:space="preserve">
|
||||
<source>Better groups performance</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better message dates." xml:space="preserve">
|
||||
<source>Better message dates.</source>
|
||||
<target>Lepsze daty wiadomości.</target>
|
||||
|
@ -1209,6 +1215,10 @@
|
|||
<target>Lepsze powiadomienia</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better privacy and security" xml:space="preserve">
|
||||
<source>Better privacy and security</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better security ✅" xml:space="preserve">
|
||||
<source>Better security ✅</source>
|
||||
<target>Lepsze zabezpieczenia ✅</target>
|
||||
|
@ -1311,6 +1321,7 @@
|
|||
</trans-unit>
|
||||
<trans-unit id="Businesses" xml:space="preserve">
|
||||
<source>Businesses</source>
|
||||
<target>Firmy</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="By chat profile (default) or [by connection](https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation) (BETA)." xml:space="preserve">
|
||||
|
@ -1629,6 +1640,10 @@
|
|||
<target>Wyczyścić rozmowę?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Clear group?" xml:space="preserve">
|
||||
<source>Clear group?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Clear or delete group?" xml:space="preserve">
|
||||
<source>Clear or delete group?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -1768,6 +1783,10 @@
|
|||
<target>Potwierdź wgranie</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Confirmed" xml:space="preserve">
|
||||
<source>Confirmed</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Connect" xml:space="preserve">
|
||||
<source>Connect</source>
|
||||
<target>Połącz</target>
|
||||
|
@ -2761,6 +2780,10 @@ To jest twój jednorazowy link!</target>
|
|||
<target>Nie włączaj</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Don't miss important messages." xml:space="preserve">
|
||||
<source>Don't miss important messages.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Don't show again" xml:space="preserve">
|
||||
<source>Don't show again</source>
|
||||
<target>Nie pokazuj ponownie</target>
|
||||
|
@ -3111,6 +3134,10 @@ To jest twój jednorazowy link!</target>
|
|||
<target>Błąd zmiany na incognito!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error checking token status" xml:space="preserve">
|
||||
<source>Error checking token status</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error connecting to forwarding server %@. Please try later." xml:space="preserve">
|
||||
<source>Error connecting to forwarding server %@. Please try later.</source>
|
||||
<target>Błąd połączenia z serwerem przekierowania %@. Spróbuj ponownie później.</target>
|
||||
|
@ -3263,6 +3290,10 @@ To jest twój jednorazowy link!</target>
|
|||
<target>Błąd ponownego łączenia serwerów</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error registering for notifications" xml:space="preserve">
|
||||
<source>Error registering for notifications</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error removing member" xml:space="preserve">
|
||||
<source>Error removing member</source>
|
||||
<target>Błąd usuwania członka</target>
|
||||
|
@ -3365,6 +3396,10 @@ To jest twój jednorazowy link!</target>
|
|||
<target>Błąd synchronizacji połączenia</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error testing server connection" xml:space="preserve">
|
||||
<source>Error testing server connection</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error updating group link" xml:space="preserve">
|
||||
<source>Error updating group link</source>
|
||||
<target>Błąd aktualizacji linku grupy</target>
|
||||
|
@ -3443,6 +3478,10 @@ To jest twój jednorazowy link!</target>
|
|||
<target>Rozszerz</target>
|
||||
<note>chat item action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Expired" xml:space="preserve">
|
||||
<source>Expired</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Export database" xml:space="preserve">
|
||||
<source>Export database</source>
|
||||
<target>Eksportuj bazę danych</target>
|
||||
|
@ -3483,11 +3522,19 @@ To jest twój jednorazowy link!</target>
|
|||
<target>Szybko i bez czekania aż nadawca będzie online!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Faster deletion of groups." xml:space="preserve">
|
||||
<source>Faster deletion of groups.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Faster joining and more reliable messages." xml:space="preserve">
|
||||
<source>Faster joining and more reliable messages.</source>
|
||||
<target>Szybsze dołączenie i bardziej niezawodne wiadomości.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Faster sending messages." xml:space="preserve">
|
||||
<source>Faster sending messages.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Favorite" xml:space="preserve">
|
||||
<source>Favorite</source>
|
||||
<target>Ulubione</target>
|
||||
|
@ -3509,9 +3556,9 @@ To jest twój jednorazowy link!</target>
|
|||
%@</target>
|
||||
<note>alert message</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="File is blocked by server operator: (info.reason.text)." xml:space="preserve">
|
||||
<trans-unit id="File is blocked by server operator: %@." xml:space="preserve">
|
||||
<source>File is blocked by server operator:
|
||||
(info.reason.text).</source>
|
||||
%@.</source>
|
||||
<note>file error text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="File not found - most likely file was deleted or cancelled." xml:space="preserve">
|
||||
|
@ -3639,6 +3686,10 @@ To jest twój jednorazowy link!</target>
|
|||
<target>Naprawa nie jest obsługiwana przez członka grupy</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For all moderators" xml:space="preserve">
|
||||
<source>For all moderators</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For chat profile %@:" xml:space="preserve">
|
||||
<source>For chat profile %@:</source>
|
||||
<note>servers error</note>
|
||||
|
@ -3652,6 +3703,10 @@ To jest twój jednorazowy link!</target>
|
|||
<source>For example, if your contact receives messages via a SimpleX Chat server, your app will deliver them via a Flux server.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For me" xml:space="preserve">
|
||||
<source>For me</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For private routing" xml:space="preserve">
|
||||
<source>For private routing</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -3773,6 +3828,10 @@ Błąd: %2$@</target>
|
|||
<target>GIF-y i naklejki</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Get notified when mentioned." xml:space="preserve">
|
||||
<source>Get notified when mentioned.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Good afternoon!" xml:space="preserve">
|
||||
<source>Good afternoon!</source>
|
||||
<target>Dzień dobry!</target>
|
||||
|
@ -3887,6 +3946,10 @@ Błąd: %2$@</target>
|
|||
<target>Pomoc</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Help admins moderating their groups." xml:space="preserve">
|
||||
<source>Help admins moderating their groups.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Hidden" xml:space="preserve">
|
||||
<source>Hidden</source>
|
||||
<target>Ukryte</target>
|
||||
|
@ -4189,6 +4252,26 @@ More improvements are coming soon!</source>
|
|||
<target>Kolory interfejsu</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid" xml:space="preserve">
|
||||
<source>Invalid</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (bad token)" xml:space="preserve">
|
||||
<source>Invalid (bad token)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (expired)" xml:space="preserve">
|
||||
<source>Invalid (expired)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (unregistered)" xml:space="preserve">
|
||||
<source>Invalid (unregistered)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (wrong topic)" xml:space="preserve">
|
||||
<source>Invalid (wrong topic)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid QR code" xml:space="preserve">
|
||||
<source>Invalid QR code</source>
|
||||
<target>Nieprawidłowy kod QR</target>
|
||||
|
@ -4561,6 +4644,10 @@ To jest twój link do grupy %@!</target>
|
|||
<target>Członek nieaktywny</target>
|
||||
<note>item status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Member reports" xml:space="preserve">
|
||||
<source>Member reports</source>
|
||||
<note>chat feature</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Member role will be changed to "%@". All chat members will be notified." xml:space="preserve">
|
||||
<source>Member role will be changed to "%@". All chat members will be notified.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -4594,6 +4681,10 @@ To jest twój link do grupy %@!</target>
|
|||
<target>Członkowie grupy mogą nieodwracalnie usuwać wysłane wiadomości. (24 godziny)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Members can report messsages to moderators." xml:space="preserve">
|
||||
<source>Members can report messsages to moderators.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Members can send SimpleX links." xml:space="preserve">
|
||||
<source>Members can send SimpleX links.</source>
|
||||
<target>Członkowie grupy mogą wysyłać linki SimpleX.</target>
|
||||
|
@ -4619,6 +4710,10 @@ To jest twój link do grupy %@!</target>
|
|||
<target>Członkowie grupy mogą wysyłać wiadomości głosowe.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Mention members 👋" xml:space="preserve">
|
||||
<source>Mention members 👋</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Menus" xml:space="preserve">
|
||||
<source>Menus</source>
|
||||
<target>Menu</target>
|
||||
|
@ -4864,7 +4959,11 @@ To jest twój link do grupy %@!</target>
|
|||
<trans-unit id="Mute" xml:space="preserve">
|
||||
<source>Mute</source>
|
||||
<target>Wycisz</target>
|
||||
<note>swipe action</note>
|
||||
<note>notification label action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Mute all" xml:space="preserve">
|
||||
<source>Mute all</source>
|
||||
<note>notification label action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Muted when inactive!" xml:space="preserve">
|
||||
<source>Muted when inactive!</source>
|
||||
|
@ -4914,6 +5013,10 @@ To jest twój link do grupy %@!</target>
|
|||
<target>Status sieci</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="New" xml:space="preserve">
|
||||
<source>New</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="New Passcode" xml:space="preserve">
|
||||
<source>New Passcode</source>
|
||||
<target>Nowy Pin</target>
|
||||
|
@ -5063,6 +5166,10 @@ To jest twój link do grupy %@!</target>
|
|||
<source>No media & file servers.</source>
|
||||
<note>servers error</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No message" xml:space="preserve">
|
||||
<source>No message</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No message servers." xml:space="preserve">
|
||||
<source>No message servers.</source>
|
||||
<note>servers error</note>
|
||||
|
@ -5113,6 +5220,10 @@ To jest twój link do grupy %@!</target>
|
|||
<source>No servers to send files.</source>
|
||||
<note>servers error</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No token!" xml:space="preserve">
|
||||
<source>No token!</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No unread chats" xml:space="preserve">
|
||||
<source>No unread chats</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -5151,10 +5262,18 @@ To jest twój link do grupy %@!</target>
|
|||
<target>Powiadomienia są wyłączone!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Notifications error" xml:space="preserve">
|
||||
<source>Notifications error</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Notifications privacy" xml:space="preserve">
|
||||
<source>Notifications privacy</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Notifications status" xml:space="preserve">
|
||||
<source>Notifications status</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Now admins can: - delete members' messages. - disable members ("observer" role)" xml:space="preserve">
|
||||
<source>Now admins can:
|
||||
- delete members' messages.
|
||||
|
@ -5386,6 +5505,10 @@ Wymaga włączenia VPN.</target>
|
|||
<source>Or to share privately</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Organize chats into lists" xml:space="preserve">
|
||||
<source>Organize chats into lists</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Other" xml:space="preserve">
|
||||
<source>Other</source>
|
||||
<target>Inne</target>
|
||||
|
@ -5577,6 +5700,18 @@ Błąd: %@</target>
|
|||
<target>Przechowuj kod dostępu w bezpieczny sposób, w przypadku jego utraty NIE będzie można go zmienić.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please try to disable and re-enable notfications." xml:space="preserve">
|
||||
<source>Please try to disable and re-enable notfications.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please wait for token activation to complete." xml:space="preserve">
|
||||
<source>Please wait for token activation to complete.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please wait for token to be registered." xml:space="preserve">
|
||||
<source>Please wait for token to be registered.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Polish interface" xml:space="preserve">
|
||||
<source>Polish interface</source>
|
||||
<target>Polski interfejs</target>
|
||||
|
@ -5635,6 +5770,10 @@ Błąd: %@</target>
|
|||
<target>Prywatne nazwy plików</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Private media file names." xml:space="preserve">
|
||||
<source>Private media file names.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Private message routing" xml:space="preserve">
|
||||
<source>Private message routing</source>
|
||||
<target>Trasowanie prywatnych wiadomości</target>
|
||||
|
@ -5710,6 +5849,10 @@ Błąd: %@</target>
|
|||
<target>Zabroń reakcje wiadomości.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Prohibit reporting messages to moderators." xml:space="preserve">
|
||||
<source>Prohibit reporting messages to moderators.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Prohibit sending SimpleX links." xml:space="preserve">
|
||||
<source>Prohibit sending SimpleX links.</source>
|
||||
<target>Zabroń wysyłania linków SimpleX.</target>
|
||||
|
@ -5967,6 +6110,18 @@ Włącz w ustawianiach *Sieć i serwery* .</target>
|
|||
<target>Zmniejszone zużycie baterii</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Register" xml:space="preserve">
|
||||
<source>Register</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Register notification token?" xml:space="preserve">
|
||||
<source>Register notification token?</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Registered" xml:space="preserve">
|
||||
<source>Registered</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Reject" xml:space="preserve">
|
||||
<source>Reject</source>
|
||||
<target>Odrzuć</target>
|
||||
|
@ -6096,6 +6251,14 @@ Włącz w ustawianiach *Sieć i serwery* .</target>
|
|||
<source>Report violation: only group moderators will see it.</source>
|
||||
<note>report reason</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Report: %@" xml:space="preserve">
|
||||
<source>Report: %@</source>
|
||||
<note>report in notification</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Reporting messages to moderators is prohibited." xml:space="preserve">
|
||||
<source>Reporting messages to moderators is prohibited.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Reports" xml:space="preserve">
|
||||
<source>Reports</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -6518,6 +6681,10 @@ Włącz w ustawianiach *Sieć i serwery* .</target>
|
|||
<target>Wyślij powiadomienia</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Send private reports" xml:space="preserve">
|
||||
<source>Send private reports</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Send questions and ideas" xml:space="preserve">
|
||||
<source>Send questions and ideas</source>
|
||||
<target>Wyślij pytania i pomysły</target>
|
||||
|
@ -6753,6 +6920,10 @@ Włącz w ustawianiach *Sieć i serwery* .</target>
|
|||
<target>Ustaw go zamiast uwierzytelniania systemowego.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Set message expiration in chats." xml:space="preserve">
|
||||
<source>Set message expiration in chats.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Set passcode" xml:space="preserve">
|
||||
<source>Set passcode</source>
|
||||
<target>Ustaw pin</target>
|
||||
|
@ -7204,6 +7375,10 @@ Włącz w ustawianiach *Sieć i serwery* .</target>
|
|||
<target>Limit czasu połączenia TCP</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="TCP port for messaging" xml:space="preserve">
|
||||
<source>TCP port for messaging</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="TCP_KEEPCNT" xml:space="preserve">
|
||||
<source>TCP_KEEPCNT</source>
|
||||
<target>TCP_KEEPCNT</target>
|
||||
|
@ -7278,6 +7453,10 @@ Włącz w ustawianiach *Sieć i serwery* .</target>
|
|||
<target>Test nie powiódł się na etapie %@.</target>
|
||||
<note>server test failure</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Test notifications" xml:space="preserve">
|
||||
<source>Test notifications</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Test server" xml:space="preserve">
|
||||
<source>Test server</source>
|
||||
<target>Przetestuj serwer</target>
|
||||
|
@ -7403,10 +7582,6 @@ Może się to zdarzyć z powodu jakiegoś błędu lub gdy połączenie jest skom
|
|||
<target>Profil jest udostępniany tylko Twoim kontaktom.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="The report will be archived for you." xml:space="preserve">
|
||||
<source>The report will be archived for you.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve">
|
||||
<source>The same conditions will apply to operator **%@**.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -7531,6 +7706,10 @@ Może się to zdarzyć z powodu jakiegoś błędu lub gdy połączenie jest skom
|
|||
<target>Ten link dostał użyty z innym urządzeniem mobilnym, proszę stworzyć nowy link na komputerze.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="This message was deleted or not received yet." xml:space="preserve">
|
||||
<source>This message was deleted or not received yet.</source>
|
||||
<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">
|
||||
<source>This setting applies to messages in your current chat profile **%@**.</source>
|
||||
<target>To ustawienie dotyczy wiadomości Twojego bieżącego profilu czatu **%@**.</target>
|
||||
|
@ -7639,6 +7818,10 @@ Przed włączeniem tej funkcji zostanie wyświetlony monit uwierzytelniania.</ta
|
|||
<target>Przełącz incognito przy połączeniu.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Token status: %@." xml:space="preserve">
|
||||
<source>Token status: %@.</source>
|
||||
<note>token status</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Toolbar opacity" xml:space="preserve">
|
||||
<source>Toolbar opacity</source>
|
||||
<target>Nieprzezroczystość paska narzędzi</target>
|
||||
|
@ -7803,7 +7986,7 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc
|
|||
<trans-unit id="Unmute" xml:space="preserve">
|
||||
<source>Unmute</source>
|
||||
<target>Wyłącz wyciszenie</target>
|
||||
<note>swipe action</note>
|
||||
<note>notification label action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Unread" xml:space="preserve">
|
||||
<source>Unread</source>
|
||||
|
@ -7835,6 +8018,10 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc
|
|||
<target>Zaktualizować ustawienia?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Updated conditions" xml:space="preserve">
|
||||
<source>Updated conditions</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Updating settings will re-connect the client to all servers." xml:space="preserve">
|
||||
<source>Updating settings will re-connect the client to all servers.</source>
|
||||
<target>Aktualizacja ustawień spowoduje ponowne połączenie klienta ze wszystkimi serwerami.</target>
|
||||
|
@ -7894,6 +8081,10 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc
|
|||
<target>Użyć serwerów SimpleX Chat?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use TCP port %@ when no port is specified." xml:space="preserve">
|
||||
<source>Use TCP port %@ when no port is specified.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use chat" xml:space="preserve">
|
||||
<source>Use chat</source>
|
||||
<target>Użyj czatu</target>
|
||||
|
@ -7966,6 +8157,10 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc
|
|||
<target>Korzystaj z aplikacji jedną ręką.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use web port" xml:space="preserve">
|
||||
<source>Use web port</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="User selection" xml:space="preserve">
|
||||
<source>User selection</source>
|
||||
<target>Wybór użytkownika</target>
|
||||
|
@ -8512,6 +8707,10 @@ Powtórzyć prośbę połączenia?</target>
|
|||
<target>Wysłałeś zaproszenie do grupy</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="You should receive notifications." xml:space="preserve">
|
||||
<source>You should receive notifications.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="You will be connected to group when the group host's device is online, please wait or check later!" xml:space="preserve">
|
||||
<source>You will be connected to group when the group host's device is online, please wait or check later!</source>
|
||||
<target>Zostaniesz połączony do grupy, gdy urządzenie gospodarza grupy będzie online, proszę czekać lub sprawdzić później!</target>
|
||||
|
@ -8693,6 +8892,7 @@ Powtórzyć prośbę połączenia?</target>
|
|||
</trans-unit>
|
||||
<trans-unit id="Your servers" xml:space="preserve">
|
||||
<source>Your servers</source>
|
||||
<target>Twoje serwery</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Your settings" xml:space="preserve">
|
||||
|
@ -9302,11 +9502,6 @@ Powtórzyć prośbę połączenia?</target>
|
|||
<target>miesiące</target>
|
||||
<note>time unit</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="mute" xml:space="preserve">
|
||||
<source>mute</source>
|
||||
<target>wycisz</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="never" xml:space="preserve">
|
||||
<source>never</source>
|
||||
<target>nigdy</target>
|
||||
|
@ -9384,6 +9579,14 @@ Powtórzyć prośbę połączenia?</target>
|
|||
<target>peer-to-peer</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="pending" xml:space="preserve">
|
||||
<source>pending</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="pending approval" xml:space="preserve">
|
||||
<source>pending approval</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="quantum resistant e2e encryption" xml:space="preserve">
|
||||
<source>quantum resistant e2e encryption</source>
|
||||
<target>kwantowo odporne szyfrowanie e2e</target>
|
||||
|
@ -9399,6 +9602,10 @@ Powtórzyć prośbę połączenia?</target>
|
|||
<target>otrzymano potwierdzenie…</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="rejected" xml:space="preserve">
|
||||
<source>rejected</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="rejected call" xml:space="preserve">
|
||||
<source>rejected call</source>
|
||||
<target>odrzucone połączenie</target>
|
||||
|
@ -9532,11 +9739,6 @@ ostatnia otrzymana wiadomość: %2$@</target>
|
|||
<target>nieznany status</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="unmute" xml:space="preserve">
|
||||
<source>unmute</source>
|
||||
<target>wyłącz wyciszenie</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="unprotected" xml:space="preserve">
|
||||
<source>unprotected</source>
|
||||
<target>niezabezpieczony</target>
|
||||
|
@ -9781,6 +9983,7 @@ ostatnia otrzymana wiadomość: %2$@</target>
|
|||
</trans-unit>
|
||||
<trans-unit id="New messages in %d chats" xml:space="preserve">
|
||||
<source>New messages in %d chats</source>
|
||||
<target>Nowe wiadomości w %d czatach</target>
|
||||
<note>notification body</note>
|
||||
</trans-unit>
|
||||
</body>
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -5,22 +5,6 @@
|
|||
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.4" build-num="15F31d"/>
|
||||
</header>
|
||||
<body>
|
||||
<trans-unit id=" " xml:space="preserve">
|
||||
<source>
|
||||
</source>
|
||||
<target>
|
||||
</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=" " xml:space="preserve">
|
||||
<source> </source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=" (" xml:space="preserve">
|
||||
<source> (</source>
|
||||
<target> (</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=" (can be copied)" xml:space="preserve">
|
||||
<source> (can be copied)</source>
|
||||
<target> (สามารถคัดลอกได้)</target>
|
||||
|
@ -306,11 +290,6 @@
|
|||
<target>%u ข้อความที่ถูกข้าม</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="(" xml:space="preserve">
|
||||
<source>(</source>
|
||||
<target>(</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="(new)" xml:space="preserve">
|
||||
<source>(new)</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -319,11 +298,6 @@
|
|||
<source>(this device v%@)</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=")" xml:space="preserve">
|
||||
<source>)</source>
|
||||
<target>)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="**Create 1-time link**: to create and share a new invitation link." xml:space="preserve">
|
||||
<source>**Create 1-time link**: to create and share a new invitation link.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -384,11 +358,6 @@
|
|||
<target>\*ตัวหนา*</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=", " xml:space="preserve">
|
||||
<source>, </source>
|
||||
<target>, </target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="- connect to [directory service](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (BETA)! - delivery receipts (up to 20 members). - faster and more stable." xml:space="preserve">
|
||||
<source>- connect to [directory service](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (BETA)!
|
||||
- delivery receipts (up to 20 members).
|
||||
|
@ -419,11 +388,6 @@
|
|||
- ประวัติการแก้ไข</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="." xml:space="preserve">
|
||||
<source>.</source>
|
||||
<target>.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="0 sec" xml:space="preserve">
|
||||
<source>0 sec</source>
|
||||
<note>time to disappear</note>
|
||||
|
@ -488,11 +452,6 @@
|
|||
<target>30 วินาที</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=": " xml:space="preserve">
|
||||
<source>: </source>
|
||||
<target>: </target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="<p>Hi!</p> <p><a href="%@">Connect to me via SimpleX Chat</a></p>" xml:space="preserve">
|
||||
<source><p>Hi!</p>
|
||||
<p><a href="%@">Connect to me via SimpleX Chat</a></p></source>
|
||||
|
@ -592,6 +551,10 @@
|
|||
<source>Acknowledgement errors</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Active" xml:space="preserve">
|
||||
<source>Active</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Active connections" xml:space="preserve">
|
||||
<source>Active connections</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -716,8 +679,8 @@
|
|||
<target>แชทและข้อความทั้งหมดจะถูกลบ - การดำเนินการนี้ไม่สามารถยกเลิกได้!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All chats will be removed from the list (text), and the list deleted." xml:space="preserve">
|
||||
<source>All chats will be removed from the list (text), and the list deleted.</source>
|
||||
<trans-unit id="All chats will be removed from the list %@, and the list deleted." xml:space="preserve">
|
||||
<source>All chats will be removed from the list %@, and the list deleted.</source>
|
||||
<note>alert message</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All data is erased when it is entered." xml:space="preserve">
|
||||
|
@ -755,6 +718,10 @@
|
|||
<source>All profiles</source>
|
||||
<note>profile dropdown</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All reports will be archived for you." xml:space="preserve">
|
||||
<source>All reports will be archived for you.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
||||
<source>All your contacts will remain connected.</source>
|
||||
<target>ผู้ติดต่อทั้งหมดของคุณจะยังคงเชื่อมต่ออยู่.</target>
|
||||
|
@ -826,6 +793,10 @@
|
|||
<target>อนุญาตให้ลบข้อความที่ส่งไปแล้วอย่างถาวร</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Allow to report messsages to moderators." xml:space="preserve">
|
||||
<source>Allow to report messsages to moderators.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Allow to send SimpleX links." xml:space="preserve">
|
||||
<source>Allow to send SimpleX links.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -979,6 +950,14 @@
|
|||
<source>Archive</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive %lld reports?" xml:space="preserve">
|
||||
<source>Archive %lld reports?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive all reports?" xml:space="preserve">
|
||||
<source>Archive all reports?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive and upload" xml:space="preserve">
|
||||
<source>Archive and upload</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -995,6 +974,10 @@
|
|||
<source>Archive report?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive reports" xml:space="preserve">
|
||||
<source>Archive reports</source>
|
||||
<note>swipe action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archived contacts" xml:space="preserve">
|
||||
<source>Archived contacts</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -1102,6 +1085,10 @@
|
|||
<source>Better groups</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better groups performance" xml:space="preserve">
|
||||
<source>Better groups performance</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better message dates." xml:space="preserve">
|
||||
<source>Better message dates.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -1119,6 +1106,10 @@
|
|||
<source>Better notifications</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better privacy and security" xml:space="preserve">
|
||||
<source>Better privacy and security</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better security ✅" xml:space="preserve">
|
||||
<source>Better security ✅</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -1496,6 +1487,10 @@
|
|||
<target>ลบการสนทนา?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Clear group?" xml:space="preserve">
|
||||
<source>Clear group?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Clear or delete group?" xml:space="preserve">
|
||||
<source>Clear or delete group?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -1621,6 +1616,10 @@
|
|||
<source>Confirm upload</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Confirmed" xml:space="preserve">
|
||||
<source>Confirmed</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Connect" xml:space="preserve">
|
||||
<source>Connect</source>
|
||||
<target>เชื่อมต่อ</target>
|
||||
|
@ -2543,6 +2542,10 @@ This is your own one-time link!</source>
|
|||
<target>อย่าเปิดใช้งาน</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Don't miss important messages." xml:space="preserve">
|
||||
<source>Don't miss important messages.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Don't show again" xml:space="preserve">
|
||||
<source>Don't show again</source>
|
||||
<target>ไม่ต้องแสดงอีก</target>
|
||||
|
@ -2870,6 +2873,10 @@ This is your own one-time link!</source>
|
|||
<source>Error changing to incognito!</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error checking token status" xml:space="preserve">
|
||||
<source>Error checking token status</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error connecting to forwarding server %@. Please try later." xml:space="preserve">
|
||||
<source>Error connecting to forwarding server %@. Please try later.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -3012,6 +3019,10 @@ This is your own one-time link!</source>
|
|||
<source>Error reconnecting servers</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error registering for notifications" xml:space="preserve">
|
||||
<source>Error registering for notifications</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error removing member" xml:space="preserve">
|
||||
<source>Error removing member</source>
|
||||
<target>เกิดข้อผิดพลาดในการลบสมาชิก</target>
|
||||
|
@ -3109,6 +3120,10 @@ This is your own one-time link!</source>
|
|||
<target>เกิดข้อผิดพลาดในการซิงโครไนซ์การเชื่อมต่อ</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error testing server connection" xml:space="preserve">
|
||||
<source>Error testing server connection</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error updating group link" xml:space="preserve">
|
||||
<source>Error updating group link</source>
|
||||
<target>เกิดข้อผิดพลาดในการอัปเดตลิงก์กลุ่ม</target>
|
||||
|
@ -3183,6 +3198,10 @@ This is your own one-time link!</source>
|
|||
<source>Expand</source>
|
||||
<note>chat item action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Expired" xml:space="preserve">
|
||||
<source>Expired</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Export database" xml:space="preserve">
|
||||
<source>Export database</source>
|
||||
<target>ส่งออกฐานข้อมูล</target>
|
||||
|
@ -3221,10 +3240,18 @@ This is your own one-time link!</source>
|
|||
<target>รวดเร็วและไม่ต้องรอจนกว่าผู้ส่งจะออนไลน์!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Faster deletion of groups." xml:space="preserve">
|
||||
<source>Faster deletion of groups.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Faster joining and more reliable messages." xml:space="preserve">
|
||||
<source>Faster joining and more reliable messages.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Faster sending messages." xml:space="preserve">
|
||||
<source>Faster sending messages.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Favorite" xml:space="preserve">
|
||||
<source>Favorite</source>
|
||||
<target>ที่ชอบ</target>
|
||||
|
@ -3243,9 +3270,9 @@ This is your own one-time link!</source>
|
|||
%@</source>
|
||||
<note>alert message</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="File is blocked by server operator: (info.reason.text)." xml:space="preserve">
|
||||
<trans-unit id="File is blocked by server operator: %@." xml:space="preserve">
|
||||
<source>File is blocked by server operator:
|
||||
(info.reason.text).</source>
|
||||
%@.</source>
|
||||
<note>file error text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="File not found - most likely file was deleted or cancelled." xml:space="preserve">
|
||||
|
@ -3365,6 +3392,10 @@ This is your own one-time link!</source>
|
|||
<target>การแก้ไขไม่สนับสนุนโดยสมาชิกกลุ่ม</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For all moderators" xml:space="preserve">
|
||||
<source>For all moderators</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For chat profile %@:" xml:space="preserve">
|
||||
<source>For chat profile %@:</source>
|
||||
<note>servers error</note>
|
||||
|
@ -3378,6 +3409,10 @@ This is your own one-time link!</source>
|
|||
<source>For example, if your contact receives messages via a SimpleX Chat server, your app will deliver them via a Flux server.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For me" xml:space="preserve">
|
||||
<source>For me</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For private routing" xml:space="preserve">
|
||||
<source>For private routing</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -3482,6 +3517,10 @@ Error: %2$@</source>
|
|||
<target>GIFs และสติกเกอร์</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Get notified when mentioned." xml:space="preserve">
|
||||
<source>Get notified when mentioned.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Good afternoon!" xml:space="preserve">
|
||||
<source>Good afternoon!</source>
|
||||
<note>message preview</note>
|
||||
|
@ -3592,6 +3631,10 @@ Error: %2$@</source>
|
|||
<target>ความช่วยเหลือ</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Help admins moderating their groups." xml:space="preserve">
|
||||
<source>Help admins moderating their groups.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Hidden" xml:space="preserve">
|
||||
<source>Hidden</source>
|
||||
<target>ซ่อนอยู่</target>
|
||||
|
@ -3881,6 +3924,26 @@ More improvements are coming soon!</source>
|
|||
<source>Interface colors</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid" xml:space="preserve">
|
||||
<source>Invalid</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (bad token)" xml:space="preserve">
|
||||
<source>Invalid (bad token)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (expired)" xml:space="preserve">
|
||||
<source>Invalid (expired)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (unregistered)" xml:space="preserve">
|
||||
<source>Invalid (unregistered)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (wrong topic)" xml:space="preserve">
|
||||
<source>Invalid (wrong topic)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid QR code" xml:space="preserve">
|
||||
<source>Invalid QR code</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -4230,6 +4293,10 @@ This is your link for group %@!</source>
|
|||
<source>Member inactive</source>
|
||||
<note>item status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Member reports" xml:space="preserve">
|
||||
<source>Member reports</source>
|
||||
<note>chat feature</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Member role will be changed to "%@". All chat members will be notified." xml:space="preserve">
|
||||
<source>Member role will be changed to "%@". All chat members will be notified.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -4263,6 +4330,10 @@ This is your link for group %@!</source>
|
|||
<target>สมาชิกกลุ่มสามารถลบข้อความที่ส่งแล้วอย่างถาวร</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Members can report messsages to moderators." xml:space="preserve">
|
||||
<source>Members can report messsages to moderators.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Members can send SimpleX links." xml:space="preserve">
|
||||
<source>Members can send SimpleX links.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -4287,6 +4358,10 @@ This is your link for group %@!</source>
|
|||
<target>สมาชิกกลุ่มสามารถส่งข้อความเสียง</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Mention members 👋" xml:space="preserve">
|
||||
<source>Mention members 👋</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Menus" xml:space="preserve">
|
||||
<source>Menus</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -4505,7 +4580,11 @@ This is your link for group %@!</source>
|
|||
<trans-unit id="Mute" xml:space="preserve">
|
||||
<source>Mute</source>
|
||||
<target>ปิดเสียง</target>
|
||||
<note>swipe action</note>
|
||||
<note>notification label action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Mute all" xml:space="preserve">
|
||||
<source>Mute all</source>
|
||||
<note>notification label action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Muted when inactive!" xml:space="preserve">
|
||||
<source>Muted when inactive!</source>
|
||||
|
@ -4552,6 +4631,10 @@ This is your link for group %@!</source>
|
|||
<target>สถานะเครือข่าย</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="New" xml:space="preserve">
|
||||
<source>New</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="New Passcode" xml:space="preserve">
|
||||
<source>New Passcode</source>
|
||||
<target>รหัสผ่านใหม่</target>
|
||||
|
@ -4692,6 +4775,10 @@ This is your link for group %@!</source>
|
|||
<source>No media & file servers.</source>
|
||||
<note>servers error</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No message" xml:space="preserve">
|
||||
<source>No message</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No message servers." xml:space="preserve">
|
||||
<source>No message servers.</source>
|
||||
<note>servers error</note>
|
||||
|
@ -4739,6 +4826,10 @@ This is your link for group %@!</source>
|
|||
<source>No servers to send files.</source>
|
||||
<note>servers error</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No token!" xml:space="preserve">
|
||||
<source>No token!</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No unread chats" xml:space="preserve">
|
||||
<source>No unread chats</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -4774,10 +4865,18 @@ This is your link for group %@!</source>
|
|||
<target>ปิดการแจ้งเตือน!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Notifications error" xml:space="preserve">
|
||||
<source>Notifications error</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Notifications privacy" xml:space="preserve">
|
||||
<source>Notifications privacy</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Notifications status" xml:space="preserve">
|
||||
<source>Notifications status</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Now admins can: - delete members' messages. - disable members ("observer" role)" xml:space="preserve">
|
||||
<source>Now admins can:
|
||||
- delete members' messages.
|
||||
|
@ -4997,6 +5096,10 @@ Requires compatible VPN.</source>
|
|||
<source>Or to share privately</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Organize chats into lists" xml:space="preserve">
|
||||
<source>Organize chats into lists</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Other" xml:space="preserve">
|
||||
<source>Other</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -5171,6 +5274,18 @@ Error: %@</source>
|
|||
<target>โปรดจัดเก็บรหัสผ่านอย่างปลอดภัย คุณจะไม่สามารถเปลี่ยนรหัสผ่านได้หากคุณทำรหัสผ่านหาย</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please try to disable and re-enable notfications." xml:space="preserve">
|
||||
<source>Please try to disable and re-enable notfications.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please wait for token activation to complete." xml:space="preserve">
|
||||
<source>Please wait for token activation to complete.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please wait for token to be registered." xml:space="preserve">
|
||||
<source>Please wait for token to be registered.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Polish interface" xml:space="preserve">
|
||||
<source>Polish interface</source>
|
||||
<target>อินเตอร์เฟซภาษาโปแลนด์</target>
|
||||
|
@ -5227,6 +5342,10 @@ Error: %@</source>
|
|||
<target>ชื่อไฟล์ส่วนตัว</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Private media file names." xml:space="preserve">
|
||||
<source>Private media file names.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Private message routing" xml:space="preserve">
|
||||
<source>Private message routing</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -5295,6 +5414,10 @@ Error: %@</source>
|
|||
<target>ห้ามแสดงปฏิกิริยาต่อข้อความ</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Prohibit reporting messages to moderators." xml:space="preserve">
|
||||
<source>Prohibit reporting messages to moderators.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Prohibit sending SimpleX links." xml:space="preserve">
|
||||
<source>Prohibit sending SimpleX links.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -5529,6 +5652,18 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>ลดการใช้แบตเตอรี่</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Register" xml:space="preserve">
|
||||
<source>Register</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Register notification token?" xml:space="preserve">
|
||||
<source>Register notification token?</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Registered" xml:space="preserve">
|
||||
<source>Registered</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Reject" xml:space="preserve">
|
||||
<source>Reject</source>
|
||||
<target>ปฏิเสธ</target>
|
||||
|
@ -5650,6 +5785,14 @@ Enable in *Network & servers* settings.</source>
|
|||
<source>Report violation: only group moderators will see it.</source>
|
||||
<note>report reason</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Report: %@" xml:space="preserve">
|
||||
<source>Report: %@</source>
|
||||
<note>report in notification</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Reporting messages to moderators is prohibited." xml:space="preserve">
|
||||
<source>Reporting messages to moderators is prohibited.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Reports" xml:space="preserve">
|
||||
<source>Reports</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -6041,6 +6184,10 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>ส่งการแจ้งเตือน</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Send private reports" xml:space="preserve">
|
||||
<source>Send private reports</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Send questions and ideas" xml:space="preserve">
|
||||
<source>Send questions and ideas</source>
|
||||
<target>ส่งคําถามและความคิด</target>
|
||||
|
@ -6257,6 +6404,10 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>ตั้งแทนการรับรองความถูกต้องของระบบ</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Set message expiration in chats." xml:space="preserve">
|
||||
<source>Set message expiration in chats.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Set passcode" xml:space="preserve">
|
||||
<source>Set passcode</source>
|
||||
<target>ตั้งรหัสผ่าน</target>
|
||||
|
@ -6675,6 +6826,10 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>หมดเวลาการเชื่อมต่อ TCP</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="TCP port for messaging" xml:space="preserve">
|
||||
<source>TCP port for messaging</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="TCP_KEEPCNT" xml:space="preserve">
|
||||
<source>TCP_KEEPCNT</source>
|
||||
<target>TCP_KEEPCNT</target>
|
||||
|
@ -6744,6 +6899,10 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>การทดสอบล้มเหลวในขั้นตอน %@</target>
|
||||
<note>server test failure</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Test notifications" xml:space="preserve">
|
||||
<source>Test notifications</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Test server" xml:space="preserve">
|
||||
<source>Test server</source>
|
||||
<target>เซิร์ฟเวอร์ทดสอบ</target>
|
||||
|
@ -6866,10 +7025,6 @@ It can happen because of some bug or when the connection is compromised.</source
|
|||
<target>โปรไฟล์นี้แชร์กับผู้ติดต่อของคุณเท่านั้น</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="The report will be archived for you." xml:space="preserve">
|
||||
<source>The report will be archived for you.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve">
|
||||
<source>The same conditions will apply to operator **%@**.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -6982,6 +7137,10 @@ It can happen because of some bug or when the connection is compromised.</source
|
|||
<source>This link was used with another mobile device, please create a new link on the desktop.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="This message was deleted or not received yet." xml:space="preserve">
|
||||
<source>This message was deleted or not received yet.</source>
|
||||
<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">
|
||||
<source>This setting applies to messages in your current chat profile **%@**.</source>
|
||||
<target>การตั้งค่านี้ใช้กับข้อความในโปรไฟล์แชทปัจจุบันของคุณ **%@**</target>
|
||||
|
@ -7083,6 +7242,10 @@ You will be prompted to complete authentication before this feature is enabled.<
|
|||
<source>Toggle incognito when connecting.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Token status: %@." xml:space="preserve">
|
||||
<source>Token status: %@.</source>
|
||||
<note>token status</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Toolbar opacity" xml:space="preserve">
|
||||
<source>Toolbar opacity</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -7235,7 +7398,7 @@ To connect, please ask your contact to create another connection link and check
|
|||
<trans-unit id="Unmute" xml:space="preserve">
|
||||
<source>Unmute</source>
|
||||
<target>เปิดเสียง</target>
|
||||
<note>swipe action</note>
|
||||
<note>notification label action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Unread" xml:space="preserve">
|
||||
<source>Unread</source>
|
||||
|
@ -7265,6 +7428,10 @@ To connect, please ask your contact to create another connection link and check
|
|||
<source>Update settings?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Updated conditions" xml:space="preserve">
|
||||
<source>Updated conditions</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Updating settings will re-connect the client to all servers." xml:space="preserve">
|
||||
<source>Updating settings will re-connect the client to all servers.</source>
|
||||
<target>การอัปเดตการตั้งค่าจะเชื่อมต่อไคลเอนต์กับเซิร์ฟเวอร์ทั้งหมดอีกครั้ง</target>
|
||||
|
@ -7318,6 +7485,10 @@ To connect, please ask your contact to create another connection link and check
|
|||
<target>ใช้เซิร์ฟเวอร์ SimpleX Chat ไหม?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use TCP port %@ when no port is specified." xml:space="preserve">
|
||||
<source>Use TCP port %@ when no port is specified.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use chat" xml:space="preserve">
|
||||
<source>Use chat</source>
|
||||
<target>ใช้แชท</target>
|
||||
|
@ -7382,6 +7553,10 @@ To connect, please ask your contact to create another connection link and check
|
|||
<source>Use the app with one hand.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use web port" xml:space="preserve">
|
||||
<source>Use web port</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="User selection" xml:space="preserve">
|
||||
<source>User selection</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -7879,6 +8054,10 @@ Repeat connection request?</source>
|
|||
<target>คุณส่งคำเชิญเข้าร่วมกลุ่มแล้ว</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="You should receive notifications." xml:space="preserve">
|
||||
<source>You should receive notifications.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="You will be connected to group when the group host's device is online, please wait or check later!" xml:space="preserve">
|
||||
<source>You will be connected to group when the group host's device is online, please wait or check later!</source>
|
||||
<target>คุณจะเชื่อมต่อกับกลุ่มเมื่ออุปกรณ์โฮสต์ของกลุ่มออนไลน์อยู่ โปรดรอหรือตรวจสอบภายหลัง!</target>
|
||||
|
@ -8639,10 +8818,6 @@ Repeat connection request?</source>
|
|||
<target>เดือน</target>
|
||||
<note>time unit</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="mute" xml:space="preserve">
|
||||
<source>mute</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="never" xml:space="preserve">
|
||||
<source>never</source>
|
||||
<target>ไม่เคย</target>
|
||||
|
@ -8717,6 +8892,14 @@ Repeat connection request?</source>
|
|||
<target>เพื่อนต่อเพื่อน</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="pending" xml:space="preserve">
|
||||
<source>pending</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="pending approval" xml:space="preserve">
|
||||
<source>pending approval</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="quantum resistant e2e encryption" xml:space="preserve">
|
||||
<source>quantum resistant e2e encryption</source>
|
||||
<note>chat item text</note>
|
||||
|
@ -8731,6 +8914,10 @@ Repeat connection request?</source>
|
|||
<target>ได้รับการยืนยัน…</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="rejected" xml:space="preserve">
|
||||
<source>rejected</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="rejected call" xml:space="preserve">
|
||||
<source>rejected call</source>
|
||||
<target>สายถูกปฏิเสธ</target>
|
||||
|
@ -8849,10 +9036,6 @@ last received msg: %2$@</source>
|
|||
<source>unknown status</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="unmute" xml:space="preserve">
|
||||
<source>unmute</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="unprotected" xml:space="preserve">
|
||||
<source>unprotected</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
|
|
@ -5,22 +5,6 @@
|
|||
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.4" build-num="15F31d"/>
|
||||
</header>
|
||||
<body>
|
||||
<trans-unit id=" " xml:space="preserve">
|
||||
<source>
|
||||
</source>
|
||||
<target>
|
||||
</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=" " xml:space="preserve">
|
||||
<source> </source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=" (" xml:space="preserve">
|
||||
<source> (</source>
|
||||
<target> (</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=" (can be copied)" xml:space="preserve">
|
||||
<source> (can be copied)</source>
|
||||
<target> (kopyalanabilir)</target>
|
||||
|
@ -330,11 +314,6 @@
|
|||
<target>%u mesajlar atlandı.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="(" xml:space="preserve">
|
||||
<source>(</source>
|
||||
<target>(</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="(new)" xml:space="preserve">
|
||||
<source>(new)</source>
|
||||
<target>(yeni)</target>
|
||||
|
@ -345,11 +324,6 @@
|
|||
<target>(bu cihaz v%@)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=")" xml:space="preserve">
|
||||
<source>)</source>
|
||||
<target>)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="**Create 1-time link**: to create and share a new invitation link." xml:space="preserve">
|
||||
<source>**Create 1-time link**: to create and share a new invitation link.</source>
|
||||
<target>**Kişi ekle**: yeni bir davet bağlantısı oluşturmak için, ya da aldığın bağlantıyla bağlan.</target>
|
||||
|
@ -415,11 +389,6 @@
|
|||
<target>\*kalın*</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=", " xml:space="preserve">
|
||||
<source>, </source>
|
||||
<target>, </target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="- connect to [directory service](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (BETA)! - delivery receipts (up to 20 members). - faster and more stable." xml:space="preserve">
|
||||
<source>- connect to [directory service](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (BETA)!
|
||||
- delivery receipts (up to 20 members).
|
||||
|
@ -456,11 +425,6 @@
|
|||
- düzenleme geçmişi.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="." xml:space="preserve">
|
||||
<source>.</source>
|
||||
<target>.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="0 sec" xml:space="preserve">
|
||||
<source>0 sec</source>
|
||||
<target>0 saniye</target>
|
||||
|
@ -528,11 +492,6 @@
|
|||
<target>30 saniye</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=": " xml:space="preserve">
|
||||
<source>: </source>
|
||||
<target>: </target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="<p>Hi!</p> <p><a href="%@">Connect to me via SimpleX Chat</a></p>" xml:space="preserve">
|
||||
<source><p>Hi!</p>
|
||||
<p><a href="%@">Connect to me via SimpleX Chat</a></p></source>
|
||||
|
@ -640,6 +599,10 @@
|
|||
<target>Onay hataları</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Active" xml:space="preserve">
|
||||
<source>Active</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Active connections" xml:space="preserve">
|
||||
<source>Active connections</source>
|
||||
<target>Aktif bağlantılar</target>
|
||||
|
@ -777,8 +740,8 @@
|
|||
<target>Tüm konuşmalar ve mesajlar silinecektir. Bu, geri alınamaz!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All chats will be removed from the list (text), and the list deleted." xml:space="preserve">
|
||||
<source>All chats will be removed from the list (text), and the list deleted.</source>
|
||||
<trans-unit id="All chats will be removed from the list %@, and the list deleted." xml:space="preserve">
|
||||
<source>All chats will be removed from the list %@, and the list deleted.</source>
|
||||
<note>alert message</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All data is erased when it is entered." xml:space="preserve">
|
||||
|
@ -821,6 +784,10 @@
|
|||
<target>Tüm Profiller</target>
|
||||
<note>profile dropdown</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All reports will be archived for you." xml:space="preserve">
|
||||
<source>All reports will be archived for you.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
||||
<source>All your contacts will remain connected.</source>
|
||||
<target>Konuştuğun kişilerin tümü bağlı kalacaktır.</target>
|
||||
|
@ -896,6 +863,10 @@
|
|||
<target>Gönderilen mesajların kalıcı olarak silinmesine izin ver. (24 saat içinde)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Allow to report messsages to moderators." xml:space="preserve">
|
||||
<source>Allow to report messsages to moderators.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Allow to send SimpleX links." xml:space="preserve">
|
||||
<source>Allow to send SimpleX links.</source>
|
||||
<target>SimpleX bağlantıları göndilmesine izin ver.</target>
|
||||
|
@ -1058,6 +1029,14 @@
|
|||
<source>Archive</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive %lld reports?" xml:space="preserve">
|
||||
<source>Archive %lld reports?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive all reports?" xml:space="preserve">
|
||||
<source>Archive all reports?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive and upload" xml:space="preserve">
|
||||
<source>Archive and upload</source>
|
||||
<target>Arşivle ve yükle</target>
|
||||
|
@ -1076,6 +1055,10 @@
|
|||
<source>Archive report?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive reports" xml:space="preserve">
|
||||
<source>Archive reports</source>
|
||||
<note>swipe action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archived contacts" xml:space="preserve">
|
||||
<source>Archived contacts</source>
|
||||
<target>Arşivli kişiler</target>
|
||||
|
@ -1190,6 +1173,10 @@
|
|||
<target>Daha iyi gruplar</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better groups performance" xml:space="preserve">
|
||||
<source>Better groups performance</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better message dates." xml:space="preserve">
|
||||
<source>Better message dates.</source>
|
||||
<target>Daha iyi mesaj tarihleri.</target>
|
||||
|
@ -1210,6 +1197,10 @@
|
|||
<target>Daha iyi bildirimler</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better privacy and security" xml:space="preserve">
|
||||
<source>Better privacy and security</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better security ✅" xml:space="preserve">
|
||||
<source>Better security ✅</source>
|
||||
<target>Daha iyi güvenlik ✅</target>
|
||||
|
@ -1630,6 +1621,10 @@
|
|||
<target>Sohbet temizlensin mi?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Clear group?" xml:space="preserve">
|
||||
<source>Clear group?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Clear or delete group?" xml:space="preserve">
|
||||
<source>Clear or delete group?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -1773,6 +1768,10 @@
|
|||
<target>Yüklemeyi onayla</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Confirmed" xml:space="preserve">
|
||||
<source>Confirmed</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Connect" xml:space="preserve">
|
||||
<source>Connect</source>
|
||||
<target>Bağlan</target>
|
||||
|
@ -2774,6 +2773,10 @@ Bu senin kendi tek kullanımlık bağlantın!</target>
|
|||
<target>Etkinleştirme</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Don't miss important messages." xml:space="preserve">
|
||||
<source>Don't miss important messages.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Don't show again" xml:space="preserve">
|
||||
<source>Don't show again</source>
|
||||
<target>Yeniden gösterme</target>
|
||||
|
@ -3128,6 +3131,10 @@ Bu senin kendi tek kullanımlık bağlantın!</target>
|
|||
<target>Gizli moduna geçerken hata oluştu!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error checking token status" xml:space="preserve">
|
||||
<source>Error checking token status</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error connecting to forwarding server %@. Please try later." xml:space="preserve">
|
||||
<source>Error connecting to forwarding server %@. Please try later.</source>
|
||||
<target>Yönlendirme sunucusu %@'ya bağlanırken hata oluştu. Lütfen daha sonra deneyin.</target>
|
||||
|
@ -3281,6 +3288,10 @@ Bu senin kendi tek kullanımlık bağlantın!</target>
|
|||
<target>Hata sunuculara yeniden bağlanılıyor</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error registering for notifications" xml:space="preserve">
|
||||
<source>Error registering for notifications</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error removing member" xml:space="preserve">
|
||||
<source>Error removing member</source>
|
||||
<target>Kişiyi silerken sorun oluştu</target>
|
||||
|
@ -3384,6 +3395,10 @@ Bu senin kendi tek kullanımlık bağlantın!</target>
|
|||
<target>Bağlantı senkronizasyonunda hata oluştu</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error testing server connection" xml:space="preserve">
|
||||
<source>Error testing server connection</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error updating group link" xml:space="preserve">
|
||||
<source>Error updating group link</source>
|
||||
<target>Grup bağlantısı güncellenirken hata oluştu</target>
|
||||
|
@ -3464,6 +3479,10 @@ Bu senin kendi tek kullanımlık bağlantın!</target>
|
|||
<target>Genişlet</target>
|
||||
<note>chat item action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Expired" xml:space="preserve">
|
||||
<source>Expired</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Export database" xml:space="preserve">
|
||||
<source>Export database</source>
|
||||
<target>Veritabanını dışarı aktar</target>
|
||||
|
@ -3504,11 +3523,19 @@ Bu senin kendi tek kullanımlık bağlantın!</target>
|
|||
<target>Hızlı ve gönderici çevrimiçi olana kadar beklemek yok!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Faster deletion of groups." xml:space="preserve">
|
||||
<source>Faster deletion of groups.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Faster joining and more reliable messages." xml:space="preserve">
|
||||
<source>Faster joining and more reliable messages.</source>
|
||||
<target>Daha hızlı katılma ve daha güvenilir mesajlar.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Faster sending messages." xml:space="preserve">
|
||||
<source>Faster sending messages.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Favorite" xml:space="preserve">
|
||||
<source>Favorite</source>
|
||||
<target>Favori</target>
|
||||
|
@ -3530,9 +3557,9 @@ Bu senin kendi tek kullanımlık bağlantın!</target>
|
|||
%@</target>
|
||||
<note>alert message</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="File is blocked by server operator: (info.reason.text)." xml:space="preserve">
|
||||
<trans-unit id="File is blocked by server operator: %@." xml:space="preserve">
|
||||
<source>File is blocked by server operator:
|
||||
(info.reason.text).</source>
|
||||
%@.</source>
|
||||
<note>file error text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="File not found - most likely file was deleted or cancelled." xml:space="preserve">
|
||||
|
@ -3660,6 +3687,10 @@ Bu senin kendi tek kullanımlık bağlantın!</target>
|
|||
<target>Düzeltme grup üyesi tarafından desteklenmiyor</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For all moderators" xml:space="preserve">
|
||||
<source>For all moderators</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For chat profile %@:" xml:space="preserve">
|
||||
<source>For chat profile %@:</source>
|
||||
<target>Sohbet profili için %@:</target>
|
||||
|
@ -3675,6 +3706,10 @@ Bu senin kendi tek kullanımlık bağlantın!</target>
|
|||
<target>Örneğin, eğer kişiniz SimpleX Sohbet sunucusundan mesajları alıyorsa, uygulamanız bu mesajları Flux sunucusundan iletecektir.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For me" xml:space="preserve">
|
||||
<source>For me</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For private routing" xml:space="preserve">
|
||||
<source>For private routing</source>
|
||||
<target>Gizli yönlendirme için</target>
|
||||
|
@ -3799,6 +3834,10 @@ Hata: %2$@</target>
|
|||
<target>GİFler ve çıkartmalar</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Get notified when mentioned." xml:space="preserve">
|
||||
<source>Get notified when mentioned.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Good afternoon!" xml:space="preserve">
|
||||
<source>Good afternoon!</source>
|
||||
<target>İyi öğlenler!</target>
|
||||
|
@ -3913,6 +3952,10 @@ Hata: %2$@</target>
|
|||
<target>Yardım</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Help admins moderating their groups." xml:space="preserve">
|
||||
<source>Help admins moderating their groups.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Hidden" xml:space="preserve">
|
||||
<source>Hidden</source>
|
||||
<target>Gizlenmiş</target>
|
||||
|
@ -4219,6 +4262,26 @@ Daha fazla iyileştirme yakında geliyor!</target>
|
|||
<target>Arayüz renkleri</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid" xml:space="preserve">
|
||||
<source>Invalid</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (bad token)" xml:space="preserve">
|
||||
<source>Invalid (bad token)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (expired)" xml:space="preserve">
|
||||
<source>Invalid (expired)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (unregistered)" xml:space="preserve">
|
||||
<source>Invalid (unregistered)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (wrong topic)" xml:space="preserve">
|
||||
<source>Invalid (wrong topic)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid QR code" xml:space="preserve">
|
||||
<source>Invalid QR code</source>
|
||||
<target>Geçersiz QR kodu</target>
|
||||
|
@ -4594,6 +4657,10 @@ Bu senin grup için bağlantın %@!</target>
|
|||
<target>Üye inaktif</target>
|
||||
<note>item status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Member reports" xml:space="preserve">
|
||||
<source>Member reports</source>
|
||||
<note>chat feature</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Member role will be changed to "%@". All chat members will be notified." xml:space="preserve">
|
||||
<source>Member role will be changed to "%@". All chat members will be notified.</source>
|
||||
<target>Üye rolü "%@" olarak değiştirilecektir. Tüm sohbet üyeleri bilgilendirilecektir.</target>
|
||||
|
@ -4628,6 +4695,10 @@ Bu senin grup için bağlantın %@!</target>
|
|||
<target>Grup üyeleri, gönderilen mesajları kalıcı olarak silebilir. (24 saat içinde)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Members can report messsages to moderators." xml:space="preserve">
|
||||
<source>Members can report messsages to moderators.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Members can send SimpleX links." xml:space="preserve">
|
||||
<source>Members can send SimpleX links.</source>
|
||||
<target>Grup üyeleri SimpleX bağlantıları gönderebilir.</target>
|
||||
|
@ -4653,6 +4724,10 @@ Bu senin grup için bağlantın %@!</target>
|
|||
<target>Grup üyeleri sesli mesajlar gönderebilir.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Mention members 👋" xml:space="preserve">
|
||||
<source>Mention members 👋</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Menus" xml:space="preserve">
|
||||
<source>Menus</source>
|
||||
<target>Menüler</target>
|
||||
|
@ -4898,7 +4973,11 @@ Bu senin grup için bağlantın %@!</target>
|
|||
<trans-unit id="Mute" xml:space="preserve">
|
||||
<source>Mute</source>
|
||||
<target>Sustur</target>
|
||||
<note>swipe action</note>
|
||||
<note>notification label action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Mute all" xml:space="preserve">
|
||||
<source>Mute all</source>
|
||||
<note>notification label action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Muted when inactive!" xml:space="preserve">
|
||||
<source>Muted when inactive!</source>
|
||||
|
@ -4948,6 +5027,10 @@ Bu senin grup için bağlantın %@!</target>
|
|||
<target>Ağ durumu</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="New" xml:space="preserve">
|
||||
<source>New</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="New Passcode" xml:space="preserve">
|
||||
<source>New Passcode</source>
|
||||
<target>Yeni şifre</target>
|
||||
|
@ -5097,6 +5180,10 @@ Bu senin grup için bağlantın %@!</target>
|
|||
<source>No media & file servers.</source>
|
||||
<note>servers error</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No message" xml:space="preserve">
|
||||
<source>No message</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No message servers." xml:space="preserve">
|
||||
<source>No message servers.</source>
|
||||
<note>servers error</note>
|
||||
|
@ -5147,6 +5234,10 @@ Bu senin grup için bağlantın %@!</target>
|
|||
<source>No servers to send files.</source>
|
||||
<note>servers error</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No token!" xml:space="preserve">
|
||||
<source>No token!</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No unread chats" xml:space="preserve">
|
||||
<source>No unread chats</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -5185,10 +5276,18 @@ Bu senin grup için bağlantın %@!</target>
|
|||
<target>Bildirimler devre dışı!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Notifications error" xml:space="preserve">
|
||||
<source>Notifications error</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Notifications privacy" xml:space="preserve">
|
||||
<source>Notifications privacy</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Notifications status" xml:space="preserve">
|
||||
<source>Notifications status</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Now admins can: - delete members' messages. - disable members ("observer" role)" xml:space="preserve">
|
||||
<source>Now admins can:
|
||||
- delete members' messages.
|
||||
|
@ -5420,6 +5519,10 @@ VPN'nin etkinleştirilmesi gerekir.</target>
|
|||
<source>Or to share privately</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Organize chats into lists" xml:space="preserve">
|
||||
<source>Organize chats into lists</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Other" xml:space="preserve">
|
||||
<source>Other</source>
|
||||
<target>Diğer</target>
|
||||
|
@ -5611,6 +5714,18 @@ Hata: %@</target>
|
|||
<target>Lütfen parolayı güvenli bir şekilde saklayın, kaybederseniz parolayı DEĞİŞTİREMEZSİNİZ.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please try to disable and re-enable notfications." xml:space="preserve">
|
||||
<source>Please try to disable and re-enable notfications.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please wait for token activation to complete." xml:space="preserve">
|
||||
<source>Please wait for token activation to complete.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please wait for token to be registered." xml:space="preserve">
|
||||
<source>Please wait for token to be registered.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Polish interface" xml:space="preserve">
|
||||
<source>Polish interface</source>
|
||||
<target>Lehçe arayüz</target>
|
||||
|
@ -5669,6 +5784,10 @@ Hata: %@</target>
|
|||
<target>Gizli dosya adları</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Private media file names." xml:space="preserve">
|
||||
<source>Private media file names.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Private message routing" xml:space="preserve">
|
||||
<source>Private message routing</source>
|
||||
<target>Gizli mesaj yönlendirme</target>
|
||||
|
@ -5744,6 +5863,10 @@ Hata: %@</target>
|
|||
<target>Mesajlarda tepkileri yasakla.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Prohibit reporting messages to moderators." xml:space="preserve">
|
||||
<source>Prohibit reporting messages to moderators.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Prohibit sending SimpleX links." xml:space="preserve">
|
||||
<source>Prohibit sending SimpleX links.</source>
|
||||
<target>SimpleX bağlantısı gönderimini yasakla.</target>
|
||||
|
@ -6001,6 +6124,18 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>Azaltılmış pil kullanımı</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Register" xml:space="preserve">
|
||||
<source>Register</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Register notification token?" xml:space="preserve">
|
||||
<source>Register notification token?</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Registered" xml:space="preserve">
|
||||
<source>Registered</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Reject" xml:space="preserve">
|
||||
<source>Reject</source>
|
||||
<target>Reddet</target>
|
||||
|
@ -6130,6 +6265,14 @@ Enable in *Network & servers* settings.</source>
|
|||
<source>Report violation: only group moderators will see it.</source>
|
||||
<note>report reason</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Report: %@" xml:space="preserve">
|
||||
<source>Report: %@</source>
|
||||
<note>report in notification</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Reporting messages to moderators is prohibited." xml:space="preserve">
|
||||
<source>Reporting messages to moderators is prohibited.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Reports" xml:space="preserve">
|
||||
<source>Reports</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -6552,6 +6695,10 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>Bildirimler gönder</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Send private reports" xml:space="preserve">
|
||||
<source>Send private reports</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Send questions and ideas" xml:space="preserve">
|
||||
<source>Send questions and ideas</source>
|
||||
<target>Fikirler ve sorular gönderin</target>
|
||||
|
@ -6787,6 +6934,10 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>Sistem kimlik doğrulaması yerine ayarla.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Set message expiration in chats." xml:space="preserve">
|
||||
<source>Set message expiration in chats.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Set passcode" xml:space="preserve">
|
||||
<source>Set passcode</source>
|
||||
<target>Şifre ayarla</target>
|
||||
|
@ -7241,6 +7392,10 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>TCP bağlantı zaman aşımı</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="TCP port for messaging" xml:space="preserve">
|
||||
<source>TCP port for messaging</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="TCP_KEEPCNT" xml:space="preserve">
|
||||
<source>TCP_KEEPCNT</source>
|
||||
<target>TCP_KEEPCNT</target>
|
||||
|
@ -7315,6 +7470,10 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>Test %@ adımında başarısız oldu.</target>
|
||||
<note>server test failure</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Test notifications" xml:space="preserve">
|
||||
<source>Test notifications</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Test server" xml:space="preserve">
|
||||
<source>Test server</source>
|
||||
<target>Sunucuyu test et</target>
|
||||
|
@ -7440,10 +7599,6 @@ Bazı hatalar nedeniyle veya bağlantı tehlikeye girdiğinde meydana gelebilir.
|
|||
<target>Profil sadece kişilerinle paylaşılacak.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="The report will be archived for you." xml:space="preserve">
|
||||
<source>The report will be archived for you.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve">
|
||||
<source>The same conditions will apply to operator **%@**.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -7568,6 +7723,10 @@ Bazı hatalar nedeniyle veya bağlantı tehlikeye girdiğinde meydana gelebilir.
|
|||
<target>Bu bağlantı başka bir mobil cihazda kullanıldı, lütfen masaüstünde yeni bir bağlantı oluşturun.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="This message was deleted or not received yet." xml:space="preserve">
|
||||
<source>This message was deleted or not received yet.</source>
|
||||
<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">
|
||||
<source>This setting applies to messages in your current chat profile **%@**.</source>
|
||||
<target>Bu ayar, geçerli sohbet profiliniz **%@** deki mesajlara uygulanır.</target>
|
||||
|
@ -7676,6 +7835,10 @@ Bu özellik etkinleştirilmeden önce kimlik doğrulamayı tamamlamanız istenec
|
|||
<target>Bağlanırken gizli moda geçiş yap.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Token status: %@." xml:space="preserve">
|
||||
<source>Token status: %@.</source>
|
||||
<note>token status</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Toolbar opacity" xml:space="preserve">
|
||||
<source>Toolbar opacity</source>
|
||||
<target>Araç çubuğu opaklığı</target>
|
||||
|
@ -7840,7 +8003,7 @@ Bağlanmak için lütfen kişinizden başka bir bağlantı oluşturmasını iste
|
|||
<trans-unit id="Unmute" xml:space="preserve">
|
||||
<source>Unmute</source>
|
||||
<target>Susturmayı kaldır</target>
|
||||
<note>swipe action</note>
|
||||
<note>notification label action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Unread" xml:space="preserve">
|
||||
<source>Unread</source>
|
||||
|
@ -7872,6 +8035,10 @@ Bağlanmak için lütfen kişinizden başka bir bağlantı oluşturmasını iste
|
|||
<target>Ayarları güncelleyelim mi?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Updated conditions" xml:space="preserve">
|
||||
<source>Updated conditions</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Updating settings will re-connect the client to all servers." xml:space="preserve">
|
||||
<source>Updating settings will re-connect the client to all servers.</source>
|
||||
<target>Ayarların güncellenmesi, istemciyi tüm sunuculara yeniden bağlayacaktır.</target>
|
||||
|
@ -7931,6 +8098,10 @@ Bağlanmak için lütfen kişinizden başka bir bağlantı oluşturmasını iste
|
|||
<target>SimpleX Chat sunucuları kullanılsın mı?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use TCP port %@ when no port is specified." xml:space="preserve">
|
||||
<source>Use TCP port %@ when no port is specified.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use chat" xml:space="preserve">
|
||||
<source>Use chat</source>
|
||||
<target>Sohbeti kullan</target>
|
||||
|
@ -8003,6 +8174,10 @@ Bağlanmak için lütfen kişinizden başka bir bağlantı oluşturmasını iste
|
|||
<target>Uygulamayı tek elle kullan.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use web port" xml:space="preserve">
|
||||
<source>Use web port</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="User selection" xml:space="preserve">
|
||||
<source>User selection</source>
|
||||
<target>Kullanıcı seçimi</target>
|
||||
|
@ -8549,6 +8724,10 @@ Bağlantı isteği tekrarlansın mı?</target>
|
|||
<target>Grup daveti gönderdiniz</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="You should receive notifications." xml:space="preserve">
|
||||
<source>You should receive notifications.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="You will be connected to group when the group host's device is online, please wait or check later!" xml:space="preserve">
|
||||
<source>You will be connected to group when the group host's device is online, please wait or check later!</source>
|
||||
<target>Grup sahibinin cihazı çevrimiçi olduğunda gruba bağlanacaksınız, lütfen bekleyin veya daha sonra kontrol edin!</target>
|
||||
|
@ -9339,11 +9518,6 @@ Bağlantı isteği tekrarlansın mı?</target>
|
|||
<target>aylar</target>
|
||||
<note>time unit</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="mute" xml:space="preserve">
|
||||
<source>mute</source>
|
||||
<target>Sessiz</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="never" xml:space="preserve">
|
||||
<source>never</source>
|
||||
<target>asla</target>
|
||||
|
@ -9421,6 +9595,14 @@ Bağlantı isteği tekrarlansın mı?</target>
|
|||
<target>eşler arası</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="pending" xml:space="preserve">
|
||||
<source>pending</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="pending approval" xml:space="preserve">
|
||||
<source>pending approval</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="quantum resistant e2e encryption" xml:space="preserve">
|
||||
<source>quantum resistant e2e encryption</source>
|
||||
<target>kuantuma dayanıklı e2e şifreleme</target>
|
||||
|
@ -9436,6 +9618,10 @@ Bağlantı isteği tekrarlansın mı?</target>
|
|||
<target>onaylama alındı…</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="rejected" xml:space="preserve">
|
||||
<source>rejected</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="rejected call" xml:space="preserve">
|
||||
<source>rejected call</source>
|
||||
<target>geri çevrilmiş çağrı</target>
|
||||
|
@ -9569,11 +9755,6 @@ son alınan msj: %2$@</target>
|
|||
<target>bilinmeyen durum</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="unmute" xml:space="preserve">
|
||||
<source>unmute</source>
|
||||
<target>susturmayı kaldır</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="unprotected" xml:space="preserve">
|
||||
<source>unprotected</source>
|
||||
<target>korumasız</target>
|
||||
|
|
|
@ -5,22 +5,6 @@
|
|||
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.4" build-num="15F31d"/>
|
||||
</header>
|
||||
<body>
|
||||
<trans-unit id=" " xml:space="preserve">
|
||||
<source>
|
||||
</source>
|
||||
<target>
|
||||
</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=" " xml:space="preserve">
|
||||
<source> </source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=" (" xml:space="preserve">
|
||||
<source> (</source>
|
||||
<target> (</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=" (can be copied)" xml:space="preserve">
|
||||
<source> (can be copied)</source>
|
||||
<target> (можна скопіювати)</target>
|
||||
|
@ -330,11 +314,6 @@
|
|||
<target>%u повідомлень пропущено.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="(" xml:space="preserve">
|
||||
<source>(</source>
|
||||
<target>(</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="(new)" xml:space="preserve">
|
||||
<source>(new)</source>
|
||||
<target>(новий)</target>
|
||||
|
@ -345,11 +324,6 @@
|
|||
<target>(цей пристрій v%@)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=")" xml:space="preserve">
|
||||
<source>)</source>
|
||||
<target>)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="**Create 1-time link**: to create and share a new invitation link." xml:space="preserve">
|
||||
<source>**Create 1-time link**: to create and share a new invitation link.</source>
|
||||
<target>**Додати контакт**: створити нове посилання-запрошення.</target>
|
||||
|
@ -415,11 +389,6 @@
|
|||
<target>\*жирний*</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=", " xml:space="preserve">
|
||||
<source>, </source>
|
||||
<target>, </target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="- connect to [directory service](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (BETA)! - delivery receipts (up to 20 members). - faster and more stable." xml:space="preserve">
|
||||
<source>- connect to [directory service](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (BETA)!
|
||||
- delivery receipts (up to 20 members).
|
||||
|
@ -456,11 +425,6 @@
|
|||
- історія редагування.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="." xml:space="preserve">
|
||||
<source>.</source>
|
||||
<target>.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="0 sec" xml:space="preserve">
|
||||
<source>0 sec</source>
|
||||
<target>0 сек</target>
|
||||
|
@ -528,11 +492,6 @@
|
|||
<target>30 секунд</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=": " xml:space="preserve">
|
||||
<source>: </source>
|
||||
<target>: </target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="<p>Hi!</p> <p><a href="%@">Connect to me via SimpleX Chat</a></p>" xml:space="preserve">
|
||||
<source><p>Hi!</p>
|
||||
<p><a href="%@">Connect to me via SimpleX Chat</a></p></source>
|
||||
|
@ -640,6 +599,10 @@
|
|||
<target>Помилки підтвердження</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Active" xml:space="preserve">
|
||||
<source>Active</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Active connections" xml:space="preserve">
|
||||
<source>Active connections</source>
|
||||
<target>Активні з'єднання</target>
|
||||
|
@ -777,8 +740,8 @@
|
|||
<target>Всі чати та повідомлення будуть видалені - це неможливо скасувати!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All chats will be removed from the list (text), and the list deleted." xml:space="preserve">
|
||||
<source>All chats will be removed from the list (text), and the list deleted.</source>
|
||||
<trans-unit id="All chats will be removed from the list %@, and the list deleted." xml:space="preserve">
|
||||
<source>All chats will be removed from the list %@, and the list deleted.</source>
|
||||
<note>alert message</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All data is erased when it is entered." xml:space="preserve">
|
||||
|
@ -821,6 +784,10 @@
|
|||
<target>Всі профілі</target>
|
||||
<note>profile dropdown</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All reports will be archived for you." xml:space="preserve">
|
||||
<source>All reports will be archived for you.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
||||
<source>All your contacts will remain connected.</source>
|
||||
<target>Всі ваші контакти залишаться на зв'язку.</target>
|
||||
|
@ -896,6 +863,10 @@
|
|||
<target>Дозволяє безповоротно видаляти надіслані повідомлення. (24 години)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Allow to report messsages to moderators." xml:space="preserve">
|
||||
<source>Allow to report messsages to moderators.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Allow to send SimpleX links." xml:space="preserve">
|
||||
<source>Allow to send SimpleX links.</source>
|
||||
<target>Дозволити надсилати посилання SimpleX.</target>
|
||||
|
@ -1058,6 +1029,14 @@
|
|||
<source>Archive</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive %lld reports?" xml:space="preserve">
|
||||
<source>Archive %lld reports?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive all reports?" xml:space="preserve">
|
||||
<source>Archive all reports?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive and upload" xml:space="preserve">
|
||||
<source>Archive and upload</source>
|
||||
<target>Архівування та завантаження</target>
|
||||
|
@ -1076,6 +1055,10 @@
|
|||
<source>Archive report?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive reports" xml:space="preserve">
|
||||
<source>Archive reports</source>
|
||||
<note>swipe action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archived contacts" xml:space="preserve">
|
||||
<source>Archived contacts</source>
|
||||
<target>Архівні контакти</target>
|
||||
|
@ -1190,6 +1173,10 @@
|
|||
<target>Кращі групи</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better groups performance" xml:space="preserve">
|
||||
<source>Better groups performance</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better message dates." xml:space="preserve">
|
||||
<source>Better message dates.</source>
|
||||
<target>Кращі дати повідомлень.</target>
|
||||
|
@ -1210,6 +1197,10 @@
|
|||
<target>Кращі сповіщення</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better privacy and security" xml:space="preserve">
|
||||
<source>Better privacy and security</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better security ✅" xml:space="preserve">
|
||||
<source>Better security ✅</source>
|
||||
<target>Краща безпека ✅</target>
|
||||
|
@ -1630,6 +1621,10 @@
|
|||
<target>Відверта розмова?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Clear group?" xml:space="preserve">
|
||||
<source>Clear group?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Clear or delete group?" xml:space="preserve">
|
||||
<source>Clear or delete group?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -1773,6 +1768,10 @@
|
|||
<target>Підтвердити завантаження</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Confirmed" xml:space="preserve">
|
||||
<source>Confirmed</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Connect" xml:space="preserve">
|
||||
<source>Connect</source>
|
||||
<target>Підключіться</target>
|
||||
|
@ -2775,6 +2774,10 @@ This is your own one-time link!</source>
|
|||
<target>Не вмикати</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Don't miss important messages." xml:space="preserve">
|
||||
<source>Don't miss important messages.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Don't show again" xml:space="preserve">
|
||||
<source>Don't show again</source>
|
||||
<target>Більше не показувати</target>
|
||||
|
@ -3129,6 +3132,10 @@ This is your own one-time link!</source>
|
|||
<target>Помилка переходу на інкогніто!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error checking token status" xml:space="preserve">
|
||||
<source>Error checking token status</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error connecting to forwarding server %@. Please try later." xml:space="preserve">
|
||||
<source>Error connecting to forwarding server %@. Please try later.</source>
|
||||
<target>Помилка підключення до сервера переадресації %@. Спробуйте пізніше.</target>
|
||||
|
@ -3282,6 +3289,10 @@ This is your own one-time link!</source>
|
|||
<target>Помилка перепідключення серверів</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error registering for notifications" xml:space="preserve">
|
||||
<source>Error registering for notifications</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error removing member" xml:space="preserve">
|
||||
<source>Error removing member</source>
|
||||
<target>Помилка видалення учасника</target>
|
||||
|
@ -3385,6 +3396,10 @@ This is your own one-time link!</source>
|
|||
<target>Помилка синхронізації з'єднання</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error testing server connection" xml:space="preserve">
|
||||
<source>Error testing server connection</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error updating group link" xml:space="preserve">
|
||||
<source>Error updating group link</source>
|
||||
<target>Помилка оновлення посилання на групу</target>
|
||||
|
@ -3465,6 +3480,10 @@ This is your own one-time link!</source>
|
|||
<target>Розгорнути</target>
|
||||
<note>chat item action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Expired" xml:space="preserve">
|
||||
<source>Expired</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Export database" xml:space="preserve">
|
||||
<source>Export database</source>
|
||||
<target>Експорт бази даних</target>
|
||||
|
@ -3505,11 +3524,19 @@ This is your own one-time link!</source>
|
|||
<target>Швидко і без очікування, поки відправник буде онлайн!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Faster deletion of groups." xml:space="preserve">
|
||||
<source>Faster deletion of groups.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Faster joining and more reliable messages." xml:space="preserve">
|
||||
<source>Faster joining and more reliable messages.</source>
|
||||
<target>Швидше приєднання та надійніші повідомлення.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Faster sending messages." xml:space="preserve">
|
||||
<source>Faster sending messages.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Favorite" xml:space="preserve">
|
||||
<source>Favorite</source>
|
||||
<target>Улюблений</target>
|
||||
|
@ -3531,9 +3558,9 @@ This is your own one-time link!</source>
|
|||
%@</target>
|
||||
<note>alert message</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="File is blocked by server operator: (info.reason.text)." xml:space="preserve">
|
||||
<trans-unit id="File is blocked by server operator: %@." xml:space="preserve">
|
||||
<source>File is blocked by server operator:
|
||||
(info.reason.text).</source>
|
||||
%@.</source>
|
||||
<note>file error text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="File not found - most likely file was deleted or cancelled." xml:space="preserve">
|
||||
|
@ -3661,6 +3688,10 @@ This is your own one-time link!</source>
|
|||
<target>Виправлення не підтримується учасником групи</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For all moderators" xml:space="preserve">
|
||||
<source>For all moderators</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For chat profile %@:" xml:space="preserve">
|
||||
<source>For chat profile %@:</source>
|
||||
<target>Для профілю чату %@:</target>
|
||||
|
@ -3676,6 +3707,10 @@ This is your own one-time link!</source>
|
|||
<target>Наприклад, якщо ваш контакт отримує повідомлення через сервер SimpleX Chat, ваш додаток доставлятиме їх через сервер Flux.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For me" xml:space="preserve">
|
||||
<source>For me</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For private routing" xml:space="preserve">
|
||||
<source>For private routing</source>
|
||||
<target>Для приватної маршрутизації</target>
|
||||
|
@ -3800,6 +3835,10 @@ Error: %2$@</source>
|
|||
<target>GIF-файли та наклейки</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Get notified when mentioned." xml:space="preserve">
|
||||
<source>Get notified when mentioned.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Good afternoon!" xml:space="preserve">
|
||||
<source>Good afternoon!</source>
|
||||
<target>Доброго дня!</target>
|
||||
|
@ -3914,6 +3953,10 @@ Error: %2$@</source>
|
|||
<target>Довідка</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Help admins moderating their groups." xml:space="preserve">
|
||||
<source>Help admins moderating their groups.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Hidden" xml:space="preserve">
|
||||
<source>Hidden</source>
|
||||
<target>Приховано</target>
|
||||
|
@ -4220,6 +4263,26 @@ More improvements are coming soon!</source>
|
|||
<target>Кольори інтерфейсу</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid" xml:space="preserve">
|
||||
<source>Invalid</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (bad token)" xml:space="preserve">
|
||||
<source>Invalid (bad token)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (expired)" xml:space="preserve">
|
||||
<source>Invalid (expired)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (unregistered)" xml:space="preserve">
|
||||
<source>Invalid (unregistered)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (wrong topic)" xml:space="preserve">
|
||||
<source>Invalid (wrong topic)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid QR code" xml:space="preserve">
|
||||
<source>Invalid QR code</source>
|
||||
<target>Неправильний QR-код</target>
|
||||
|
@ -4595,6 +4658,10 @@ This is your link for group %@!</source>
|
|||
<target>Користувач неактивний</target>
|
||||
<note>item status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Member reports" xml:space="preserve">
|
||||
<source>Member reports</source>
|
||||
<note>chat feature</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Member role will be changed to "%@". All chat members will be notified." xml:space="preserve">
|
||||
<source>Member role will be changed to "%@". All chat members will be notified.</source>
|
||||
<target>Роль учасника буде змінено на "%@". Усі учасники чату отримають сповіщення.</target>
|
||||
|
@ -4630,6 +4697,10 @@ This is your link for group %@!</source>
|
|||
<target>Учасники групи можуть безповоротно видаляти надіслані повідомлення. (24 години)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Members can report messsages to moderators." xml:space="preserve">
|
||||
<source>Members can report messsages to moderators.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Members can send SimpleX links." xml:space="preserve">
|
||||
<source>Members can send SimpleX links.</source>
|
||||
<target>Учасники групи можуть надсилати посилання SimpleX.</target>
|
||||
|
@ -4655,6 +4726,10 @@ This is your link for group %@!</source>
|
|||
<target>Учасники групи можуть надсилати голосові повідомлення.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Mention members 👋" xml:space="preserve">
|
||||
<source>Mention members 👋</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Menus" xml:space="preserve">
|
||||
<source>Menus</source>
|
||||
<target>Меню</target>
|
||||
|
@ -4901,7 +4976,11 @@ This is your link for group %@!</source>
|
|||
<trans-unit id="Mute" xml:space="preserve">
|
||||
<source>Mute</source>
|
||||
<target>Вимкнути звук</target>
|
||||
<note>swipe action</note>
|
||||
<note>notification label action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Mute all" xml:space="preserve">
|
||||
<source>Mute all</source>
|
||||
<note>notification label action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Muted when inactive!" xml:space="preserve">
|
||||
<source>Muted when inactive!</source>
|
||||
|
@ -4953,6 +5032,10 @@ This is your link for group %@!</source>
|
|||
<target>Стан мережі</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="New" xml:space="preserve">
|
||||
<source>New</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="New Passcode" xml:space="preserve">
|
||||
<source>New Passcode</source>
|
||||
<target>Новий пароль</target>
|
||||
|
@ -5105,6 +5188,10 @@ This is your link for group %@!</source>
|
|||
<target>Ніяких медіа та файлових серверів.</target>
|
||||
<note>servers error</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No message" xml:space="preserve">
|
||||
<source>No message</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No message servers." xml:space="preserve">
|
||||
<source>No message servers.</source>
|
||||
<target>Ніяких серверів повідомлень.</target>
|
||||
|
@ -5160,6 +5247,10 @@ This is your link for group %@!</source>
|
|||
<target>Немає серверів для надсилання файлів.</target>
|
||||
<note>servers error</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No token!" xml:space="preserve">
|
||||
<source>No token!</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No unread chats" xml:space="preserve">
|
||||
<source>No unread chats</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -5198,11 +5289,19 @@ This is your link for group %@!</source>
|
|||
<target>Сповіщення вимкнено!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Notifications error" xml:space="preserve">
|
||||
<source>Notifications error</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Notifications privacy" xml:space="preserve">
|
||||
<source>Notifications privacy</source>
|
||||
<target>Сповіщення про приватність</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Notifications status" xml:space="preserve">
|
||||
<source>Notifications status</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Now admins can: - delete members' messages. - disable members ("observer" role)" xml:space="preserve">
|
||||
<source>Now admins can:
|
||||
- delete members' messages.
|
||||
|
@ -5441,6 +5540,10 @@ Requires compatible VPN.</source>
|
|||
<target>Або поділитися приватно</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Organize chats into lists" xml:space="preserve">
|
||||
<source>Organize chats into lists</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Other" xml:space="preserve">
|
||||
<source>Other</source>
|
||||
<target>Інше</target>
|
||||
|
@ -5632,6 +5735,18 @@ Error: %@</source>
|
|||
<target>Будь ласка, зберігайте пароль надійно, ви НЕ зможете змінити його, якщо втратите.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please try to disable and re-enable notfications." xml:space="preserve">
|
||||
<source>Please try to disable and re-enable notfications.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please wait for token activation to complete." xml:space="preserve">
|
||||
<source>Please wait for token activation to complete.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please wait for token to be registered." xml:space="preserve">
|
||||
<source>Please wait for token to be registered.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Polish interface" xml:space="preserve">
|
||||
<source>Polish interface</source>
|
||||
<target>Польський інтерфейс</target>
|
||||
|
@ -5692,6 +5807,10 @@ Error: %@</source>
|
|||
<target>Приватні імена файлів</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Private media file names." xml:space="preserve">
|
||||
<source>Private media file names.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Private message routing" xml:space="preserve">
|
||||
<source>Private message routing</source>
|
||||
<target>Маршрутизація приватних повідомлень</target>
|
||||
|
@ -5767,6 +5886,10 @@ Error: %@</source>
|
|||
<target>Заборонити реакції на повідомлення.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Prohibit reporting messages to moderators." xml:space="preserve">
|
||||
<source>Prohibit reporting messages to moderators.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Prohibit sending SimpleX links." xml:space="preserve">
|
||||
<source>Prohibit sending SimpleX links.</source>
|
||||
<target>Заборонити надсилання посилань SimpleX.</target>
|
||||
|
@ -6024,6 +6147,18 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>Зменшення використання акумулятора</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Register" xml:space="preserve">
|
||||
<source>Register</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Register notification token?" xml:space="preserve">
|
||||
<source>Register notification token?</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Registered" xml:space="preserve">
|
||||
<source>Registered</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Reject" xml:space="preserve">
|
||||
<source>Reject</source>
|
||||
<target>Відхилити</target>
|
||||
|
@ -6153,6 +6288,14 @@ Enable in *Network & servers* settings.</source>
|
|||
<source>Report violation: only group moderators will see it.</source>
|
||||
<note>report reason</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Report: %@" xml:space="preserve">
|
||||
<source>Report: %@</source>
|
||||
<note>report in notification</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Reporting messages to moderators is prohibited." xml:space="preserve">
|
||||
<source>Reporting messages to moderators is prohibited.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Reports" xml:space="preserve">
|
||||
<source>Reports</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -6577,6 +6720,10 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>Надсилати сповіщення</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Send private reports" xml:space="preserve">
|
||||
<source>Send private reports</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Send questions and ideas" xml:space="preserve">
|
||||
<source>Send questions and ideas</source>
|
||||
<target>Надсилайте запитання та ідеї</target>
|
||||
|
@ -6816,6 +6963,10 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>Встановіть його замість аутентифікації системи.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Set message expiration in chats." xml:space="preserve">
|
||||
<source>Set message expiration in chats.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Set passcode" xml:space="preserve">
|
||||
<source>Set passcode</source>
|
||||
<target>Встановити пароль</target>
|
||||
|
@ -7278,6 +7429,10 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>Тайм-аут TCP-з'єднання</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="TCP port for messaging" xml:space="preserve">
|
||||
<source>TCP port for messaging</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="TCP_KEEPCNT" xml:space="preserve">
|
||||
<source>TCP_KEEPCNT</source>
|
||||
<target>TCP_KEEPCNT</target>
|
||||
|
@ -7353,6 +7508,10 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>Тест завершився невдало на кроці %@.</target>
|
||||
<note>server test failure</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Test notifications" xml:space="preserve">
|
||||
<source>Test notifications</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Test server" xml:space="preserve">
|
||||
<source>Test server</source>
|
||||
<target>Тестовий сервер</target>
|
||||
|
@ -7480,10 +7639,6 @@ It can happen because of some bug or when the connection is compromised.</source
|
|||
<target>Профіль доступний лише вашим контактам.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="The report will be archived for you." xml:space="preserve">
|
||||
<source>The report will be archived for you.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve">
|
||||
<source>The same conditions will apply to operator **%@**.</source>
|
||||
<target>Такі ж умови діятимуть і для оператора **%@**.</target>
|
||||
|
@ -7613,6 +7768,10 @@ It can happen because of some bug or when the connection is compromised.</source
|
|||
<target>Це посилання було використано з іншого мобільного пристрою, будь ласка, створіть нове посилання на робочому столі.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="This message was deleted or not received yet." xml:space="preserve">
|
||||
<source>This message was deleted or not received yet.</source>
|
||||
<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">
|
||||
<source>This setting applies to messages in your current chat profile **%@**.</source>
|
||||
<target>Це налаштування застосовується до повідомлень у вашому поточному профілі чату **%@**.</target>
|
||||
|
@ -7725,6 +7884,10 @@ You will be prompted to complete authentication before this feature is enabled.<
|
|||
<target>Увімкніть інкогніто при підключенні.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Token status: %@." xml:space="preserve">
|
||||
<source>Token status: %@.</source>
|
||||
<note>token status</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Toolbar opacity" xml:space="preserve">
|
||||
<source>Toolbar opacity</source>
|
||||
<target>Непрозорість панелі інструментів</target>
|
||||
|
@ -7890,7 +8053,7 @@ To connect, please ask your contact to create another connection link and check
|
|||
<trans-unit id="Unmute" xml:space="preserve">
|
||||
<source>Unmute</source>
|
||||
<target>Увімкнути звук</target>
|
||||
<note>swipe action</note>
|
||||
<note>notification label action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Unread" xml:space="preserve">
|
||||
<source>Unread</source>
|
||||
|
@ -7922,6 +8085,10 @@ To connect, please ask your contact to create another connection link and check
|
|||
<target>Оновити налаштування?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Updated conditions" xml:space="preserve">
|
||||
<source>Updated conditions</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Updating settings will re-connect the client to all servers." xml:space="preserve">
|
||||
<source>Updating settings will re-connect the client to all servers.</source>
|
||||
<target>Оновлення налаштувань призведе до перепідключення клієнта до всіх серверів.</target>
|
||||
|
@ -7982,6 +8149,10 @@ To connect, please ask your contact to create another connection link and check
|
|||
<target>Використовувати сервери SimpleX Chat?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use TCP port %@ when no port is specified." xml:space="preserve">
|
||||
<source>Use TCP port %@ when no port is specified.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use chat" xml:space="preserve">
|
||||
<source>Use chat</source>
|
||||
<target>Використовуйте чат</target>
|
||||
|
@ -8057,6 +8228,10 @@ To connect, please ask your contact to create another connection link and check
|
|||
<target>Використовуйте додаток однією рукою.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use web port" xml:space="preserve">
|
||||
<source>Use web port</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="User selection" xml:space="preserve">
|
||||
<source>User selection</source>
|
||||
<target>Вибір користувача</target>
|
||||
|
@ -8610,6 +8785,10 @@ Repeat connection request?</source>
|
|||
<target>Ви надіслали запрошення до групи</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="You should receive notifications." xml:space="preserve">
|
||||
<source>You should receive notifications.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="You will be connected to group when the group host's device is online, please wait or check later!" xml:space="preserve">
|
||||
<source>You will be connected to group when the group host's device is online, please wait or check later!</source>
|
||||
<target>Ви будете підключені до групи, коли пристрій господаря групи буде в мережі, будь ласка, зачекайте або перевірте пізніше!</target>
|
||||
|
@ -9404,11 +9583,6 @@ Repeat connection request?</source>
|
|||
<target>місяців</target>
|
||||
<note>time unit</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="mute" xml:space="preserve">
|
||||
<source>mute</source>
|
||||
<target>приглушити</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="never" xml:space="preserve">
|
||||
<source>never</source>
|
||||
<target>ніколи</target>
|
||||
|
@ -9486,6 +9660,14 @@ Repeat connection request?</source>
|
|||
<target>одноранговий</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="pending" xml:space="preserve">
|
||||
<source>pending</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="pending approval" xml:space="preserve">
|
||||
<source>pending approval</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="quantum resistant e2e encryption" xml:space="preserve">
|
||||
<source>quantum resistant e2e encryption</source>
|
||||
<target>квантово-стійке шифрування e2e</target>
|
||||
|
@ -9501,6 +9683,10 @@ Repeat connection request?</source>
|
|||
<target>отримали підтвердження…</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="rejected" xml:space="preserve">
|
||||
<source>rejected</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="rejected call" xml:space="preserve">
|
||||
<source>rejected call</source>
|
||||
<target>відхилений виклик</target>
|
||||
|
@ -9635,11 +9821,6 @@ last received msg: %2$@</source>
|
|||
<target>невідомий статус</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="unmute" xml:space="preserve">
|
||||
<source>unmute</source>
|
||||
<target>увімкнути звук</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="unprotected" xml:space="preserve">
|
||||
<source>unprotected</source>
|
||||
<target>незахищені</target>
|
||||
|
|
|
@ -5,22 +5,6 @@
|
|||
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.4" build-num="15F31d"/>
|
||||
</header>
|
||||
<body>
|
||||
<trans-unit id=" " xml:space="preserve">
|
||||
<source>
|
||||
</source>
|
||||
<target>
|
||||
</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=" " xml:space="preserve">
|
||||
<source> </source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=" (" xml:space="preserve">
|
||||
<source> (</source>
|
||||
<target> (</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=" (can be copied)" xml:space="preserve">
|
||||
<source> (can be copied)</source>
|
||||
<target> (可复制)</target>
|
||||
|
@ -322,11 +306,6 @@
|
|||
<target>已跳过 %u 条消息。</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="(" xml:space="preserve">
|
||||
<source>(</source>
|
||||
<target>(</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="(new)" xml:space="preserve">
|
||||
<source>(new)</source>
|
||||
<target>(新)</target>
|
||||
|
@ -337,11 +316,6 @@
|
|||
<target>(此设备 v%@)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=")" xml:space="preserve">
|
||||
<source>)</source>
|
||||
<target>)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="**Create 1-time link**: to create and share a new invitation link." xml:space="preserve">
|
||||
<source>**Create 1-time link**: to create and share a new invitation link.</source>
|
||||
<target>**添加联系人**: 创建新的邀请链接,或通过您收到的链接进行连接.</target>
|
||||
|
@ -406,11 +380,6 @@
|
|||
<target>\*加粗*</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=", " xml:space="preserve">
|
||||
<source>, </source>
|
||||
<target>, </target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="- connect to [directory service](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (BETA)! - delivery receipts (up to 20 members). - faster and more stable." xml:space="preserve">
|
||||
<source>- connect to [directory service](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) (BETA)!
|
||||
- delivery receipts (up to 20 members).
|
||||
|
@ -447,11 +416,6 @@
|
|||
- 编辑消息历史。</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="." xml:space="preserve">
|
||||
<source>.</source>
|
||||
<target>.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="0 sec" xml:space="preserve">
|
||||
<source>0 sec</source>
|
||||
<target>0 秒</target>
|
||||
|
@ -517,11 +481,6 @@
|
|||
<target>30秒</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id=": " xml:space="preserve">
|
||||
<source>: </source>
|
||||
<target>: </target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="<p>Hi!</p> <p><a href="%@">Connect to me via SimpleX Chat</a></p>" xml:space="preserve">
|
||||
<source><p>Hi!</p>
|
||||
<p><a href="%@">Connect to me via SimpleX Chat</a></p></source>
|
||||
|
@ -626,6 +585,10 @@
|
|||
<target>确认错误</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Active" xml:space="preserve">
|
||||
<source>Active</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Active connections" xml:space="preserve">
|
||||
<source>Active connections</source>
|
||||
<target>活动连接</target>
|
||||
|
@ -756,8 +719,8 @@
|
|||
<target>所有聊天记录和消息将被删除——这一行为无法撤销!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All chats will be removed from the list (text), and the list deleted." xml:space="preserve">
|
||||
<source>All chats will be removed from the list (text), and the list deleted.</source>
|
||||
<trans-unit id="All chats will be removed from the list %@, and the list deleted." xml:space="preserve">
|
||||
<source>All chats will be removed from the list %@, and the list deleted.</source>
|
||||
<note>alert message</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All data is erased when it is entered." xml:space="preserve">
|
||||
|
@ -799,6 +762,10 @@
|
|||
<target>所有配置文件</target>
|
||||
<note>profile dropdown</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All reports will be archived for you." xml:space="preserve">
|
||||
<source>All reports will be archived for you.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
||||
<source>All your contacts will remain connected.</source>
|
||||
<target>所有联系人会保持连接。</target>
|
||||
|
@ -874,6 +841,10 @@
|
|||
<target>允许不可撤回地删除已发送消息</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Allow to report messsages to moderators." xml:space="preserve">
|
||||
<source>Allow to report messsages to moderators.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Allow to send SimpleX links." xml:space="preserve">
|
||||
<source>Allow to send SimpleX links.</source>
|
||||
<target>允许发送 SimpleX 链接。</target>
|
||||
|
@ -1035,6 +1006,14 @@
|
|||
<source>Archive</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive %lld reports?" xml:space="preserve">
|
||||
<source>Archive %lld reports?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive all reports?" xml:space="preserve">
|
||||
<source>Archive all reports?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive and upload" xml:space="preserve">
|
||||
<source>Archive and upload</source>
|
||||
<target>存档和上传</target>
|
||||
|
@ -1053,6 +1032,10 @@
|
|||
<source>Archive report?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archive reports" xml:space="preserve">
|
||||
<source>Archive reports</source>
|
||||
<note>swipe action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Archived contacts" xml:space="preserve">
|
||||
<source>Archived contacts</source>
|
||||
<target>已存档的联系人</target>
|
||||
|
@ -1165,6 +1148,10 @@
|
|||
<target>更佳的群组</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better groups performance" xml:space="preserve">
|
||||
<source>Better groups performance</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better message dates." xml:space="preserve">
|
||||
<source>Better message dates.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -1183,6 +1170,10 @@
|
|||
<source>Better notifications</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better privacy and security" xml:space="preserve">
|
||||
<source>Better privacy and security</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Better security ✅" xml:space="preserve">
|
||||
<source>Better security ✅</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -1590,6 +1581,10 @@
|
|||
<target>清除对话吗?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Clear group?" xml:space="preserve">
|
||||
<source>Clear group?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Clear or delete group?" xml:space="preserve">
|
||||
<source>Clear or delete group?</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -1724,6 +1719,10 @@
|
|||
<target>确认上传</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Confirmed" xml:space="preserve">
|
||||
<source>Confirmed</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Connect" xml:space="preserve">
|
||||
<source>Connect</source>
|
||||
<target>连接</target>
|
||||
|
@ -2715,6 +2714,10 @@ This is your own one-time link!</source>
|
|||
<target>不要启用</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Don't miss important messages." xml:space="preserve">
|
||||
<source>Don't miss important messages.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Don't show again" xml:space="preserve">
|
||||
<source>Don't show again</source>
|
||||
<target>不再显示</target>
|
||||
|
@ -3062,6 +3065,10 @@ This is your own one-time link!</source>
|
|||
<source>Error changing to incognito!</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error checking token status" xml:space="preserve">
|
||||
<source>Error checking token status</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error connecting to forwarding server %@. Please try later." xml:space="preserve">
|
||||
<source>Error connecting to forwarding server %@. Please try later.</source>
|
||||
<target>连接到转发服务器 %@ 时出错。请稍后尝试。</target>
|
||||
|
@ -3213,6 +3220,10 @@ This is your own one-time link!</source>
|
|||
<target>重新连接服务器时出错</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error registering for notifications" xml:space="preserve">
|
||||
<source>Error registering for notifications</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error removing member" xml:space="preserve">
|
||||
<source>Error removing member</source>
|
||||
<target>删除成员错误</target>
|
||||
|
@ -3314,6 +3325,10 @@ This is your own one-time link!</source>
|
|||
<target>同步连接错误</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error testing server connection" xml:space="preserve">
|
||||
<source>Error testing server connection</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error updating group link" xml:space="preserve">
|
||||
<source>Error updating group link</source>
|
||||
<target>更新群组链接错误</target>
|
||||
|
@ -3392,6 +3407,10 @@ This is your own one-time link!</source>
|
|||
<target>展开</target>
|
||||
<note>chat item action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Expired" xml:space="preserve">
|
||||
<source>Expired</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Export database" xml:space="preserve">
|
||||
<source>Export database</source>
|
||||
<target>导出数据库</target>
|
||||
|
@ -3432,11 +3451,19 @@ This is your own one-time link!</source>
|
|||
<target>快速且无需等待发件人在线!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Faster deletion of groups." xml:space="preserve">
|
||||
<source>Faster deletion of groups.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Faster joining and more reliable messages." xml:space="preserve">
|
||||
<source>Faster joining and more reliable messages.</source>
|
||||
<target>加入速度更快、信息更可靠。</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Faster sending messages." xml:space="preserve">
|
||||
<source>Faster sending messages.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Favorite" xml:space="preserve">
|
||||
<source>Favorite</source>
|
||||
<target>最喜欢</target>
|
||||
|
@ -3456,9 +3483,9 @@ This is your own one-time link!</source>
|
|||
%@</source>
|
||||
<note>alert message</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="File is blocked by server operator: (info.reason.text)." xml:space="preserve">
|
||||
<trans-unit id="File is blocked by server operator: %@." xml:space="preserve">
|
||||
<source>File is blocked by server operator:
|
||||
(info.reason.text).</source>
|
||||
%@.</source>
|
||||
<note>file error text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="File not found - most likely file was deleted or cancelled." xml:space="preserve">
|
||||
|
@ -3586,6 +3613,10 @@ This is your own one-time link!</source>
|
|||
<target>修复群组成员不支持的问题</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For all moderators" xml:space="preserve">
|
||||
<source>For all moderators</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For chat profile %@:" xml:space="preserve">
|
||||
<source>For chat profile %@:</source>
|
||||
<note>servers error</note>
|
||||
|
@ -3599,6 +3630,10 @@ This is your own one-time link!</source>
|
|||
<source>For example, if your contact receives messages via a SimpleX Chat server, your app will deliver them via a Flux server.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For me" xml:space="preserve">
|
||||
<source>For me</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For private routing" xml:space="preserve">
|
||||
<source>For private routing</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -3716,6 +3751,10 @@ Error: %2$@</source>
|
|||
<target>GIF 和贴纸</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Get notified when mentioned." xml:space="preserve">
|
||||
<source>Get notified when mentioned.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Good afternoon!" xml:space="preserve">
|
||||
<source>Good afternoon!</source>
|
||||
<target>下午好!</target>
|
||||
|
@ -3830,6 +3869,10 @@ Error: %2$@</source>
|
|||
<target>帮助</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Help admins moderating their groups." xml:space="preserve">
|
||||
<source>Help admins moderating their groups.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Hidden" xml:space="preserve">
|
||||
<source>Hidden</source>
|
||||
<target>隐藏</target>
|
||||
|
@ -4131,6 +4174,26 @@ More improvements are coming soon!</source>
|
|||
<target>界面颜色</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid" xml:space="preserve">
|
||||
<source>Invalid</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (bad token)" xml:space="preserve">
|
||||
<source>Invalid (bad token)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (expired)" xml:space="preserve">
|
||||
<source>Invalid (expired)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (unregistered)" xml:space="preserve">
|
||||
<source>Invalid (unregistered)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid (wrong topic)" xml:space="preserve">
|
||||
<source>Invalid (wrong topic)</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid QR code" xml:space="preserve">
|
||||
<source>Invalid QR code</source>
|
||||
<target>无效的二维码</target>
|
||||
|
@ -4503,6 +4566,10 @@ This is your link for group %@!</source>
|
|||
<target>成员不活跃</target>
|
||||
<note>item status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Member reports" xml:space="preserve">
|
||||
<source>Member reports</source>
|
||||
<note>chat feature</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Member role will be changed to "%@". All chat members will be notified." xml:space="preserve">
|
||||
<source>Member role will be changed to "%@". All chat members will be notified.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -4536,6 +4603,10 @@ This is your link for group %@!</source>
|
|||
<target>群组成员可以不可撤回地删除已发送的消息</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Members can report messsages to moderators." xml:space="preserve">
|
||||
<source>Members can report messsages to moderators.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Members can send SimpleX links." xml:space="preserve">
|
||||
<source>Members can send SimpleX links.</source>
|
||||
<target>群成员可发送 SimpleX 链接。</target>
|
||||
|
@ -4561,6 +4632,10 @@ This is your link for group %@!</source>
|
|||
<target>群组成员可以发送语音消息。</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Mention members 👋" xml:space="preserve">
|
||||
<source>Mention members 👋</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Menus" xml:space="preserve">
|
||||
<source>Menus</source>
|
||||
<target>菜单</target>
|
||||
|
@ -4804,7 +4879,11 @@ This is your link for group %@!</source>
|
|||
<trans-unit id="Mute" xml:space="preserve">
|
||||
<source>Mute</source>
|
||||
<target>静音</target>
|
||||
<note>swipe action</note>
|
||||
<note>notification label action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Mute all" xml:space="preserve">
|
||||
<source>Mute all</source>
|
||||
<note>notification label action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Muted when inactive!" xml:space="preserve">
|
||||
<source>Muted when inactive!</source>
|
||||
|
@ -4854,6 +4933,10 @@ This is your link for group %@!</source>
|
|||
<target>网络状态</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="New" xml:space="preserve">
|
||||
<source>New</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="New Passcode" xml:space="preserve">
|
||||
<source>New Passcode</source>
|
||||
<target>新密码</target>
|
||||
|
@ -5001,6 +5084,10 @@ This is your link for group %@!</source>
|
|||
<source>No media & file servers.</source>
|
||||
<note>servers error</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No message" xml:space="preserve">
|
||||
<source>No message</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No message servers." xml:space="preserve">
|
||||
<source>No message servers.</source>
|
||||
<note>servers error</note>
|
||||
|
@ -5049,6 +5136,10 @@ This is your link for group %@!</source>
|
|||
<source>No servers to send files.</source>
|
||||
<note>servers error</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No token!" xml:space="preserve">
|
||||
<source>No token!</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No unread chats" xml:space="preserve">
|
||||
<source>No unread chats</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -5086,10 +5177,18 @@ This is your link for group %@!</source>
|
|||
<target>通知被禁用!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Notifications error" xml:space="preserve">
|
||||
<source>Notifications error</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Notifications privacy" xml:space="preserve">
|
||||
<source>Notifications privacy</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Notifications status" xml:space="preserve">
|
||||
<source>Notifications status</source>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Now admins can: - delete members' messages. - disable members ("observer" role)" xml:space="preserve">
|
||||
<source>Now admins can:
|
||||
- delete members' messages.
|
||||
|
@ -5321,6 +5420,10 @@ Requires compatible VPN.</source>
|
|||
<source>Or to share privately</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Organize chats into lists" xml:space="preserve">
|
||||
<source>Organize chats into lists</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Other" xml:space="preserve">
|
||||
<source>Other</source>
|
||||
<target>其他</target>
|
||||
|
@ -5509,6 +5612,18 @@ Error: %@</source>
|
|||
<target>请安全地保存密码,如果您丢失了密码,您将无法更改它。</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please try to disable and re-enable notfications." xml:space="preserve">
|
||||
<source>Please try to disable and re-enable notfications.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please wait for token activation to complete." xml:space="preserve">
|
||||
<source>Please wait for token activation to complete.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please wait for token to be registered." xml:space="preserve">
|
||||
<source>Please wait for token to be registered.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Polish interface" xml:space="preserve">
|
||||
<source>Polish interface</source>
|
||||
<target>波兰语界面</target>
|
||||
|
@ -5566,6 +5681,10 @@ Error: %@</source>
|
|||
<target>私密文件名</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Private media file names." xml:space="preserve">
|
||||
<source>Private media file names.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Private message routing" xml:space="preserve">
|
||||
<source>Private message routing</source>
|
||||
<target>私有消息路由</target>
|
||||
|
@ -5641,6 +5760,10 @@ Error: %@</source>
|
|||
<target>禁止消息回应。</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Prohibit reporting messages to moderators." xml:space="preserve">
|
||||
<source>Prohibit reporting messages to moderators.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Prohibit sending SimpleX links." xml:space="preserve">
|
||||
<source>Prohibit sending SimpleX links.</source>
|
||||
<target>禁止发送 SimpleX 链接。</target>
|
||||
|
@ -5897,6 +6020,18 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>减少电池使用量</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Register" xml:space="preserve">
|
||||
<source>Register</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Register notification token?" xml:space="preserve">
|
||||
<source>Register notification token?</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Registered" xml:space="preserve">
|
||||
<source>Registered</source>
|
||||
<note>token status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Reject" xml:space="preserve">
|
||||
<source>Reject</source>
|
||||
<target>拒绝</target>
|
||||
|
@ -6025,6 +6160,14 @@ Enable in *Network & servers* settings.</source>
|
|||
<source>Report violation: only group moderators will see it.</source>
|
||||
<note>report reason</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Report: %@" xml:space="preserve">
|
||||
<source>Report: %@</source>
|
||||
<note>report in notification</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Reporting messages to moderators is prohibited." xml:space="preserve">
|
||||
<source>Reporting messages to moderators is prohibited.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Reports" xml:space="preserve">
|
||||
<source>Reports</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -6443,6 +6586,10 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>发送通知</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Send private reports" xml:space="preserve">
|
||||
<source>Send private reports</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Send questions and ideas" xml:space="preserve">
|
||||
<source>Send questions and ideas</source>
|
||||
<target>发送问题和想法</target>
|
||||
|
@ -6677,6 +6824,10 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>设置它以代替系统身份验证。</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Set message expiration in chats." xml:space="preserve">
|
||||
<source>Set message expiration in chats.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Set passcode" xml:space="preserve">
|
||||
<source>Set passcode</source>
|
||||
<target>设置密码</target>
|
||||
|
@ -7125,6 +7276,10 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>TCP 连接超时</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="TCP port for messaging" xml:space="preserve">
|
||||
<source>TCP port for messaging</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="TCP_KEEPCNT" xml:space="preserve">
|
||||
<source>TCP_KEEPCNT</source>
|
||||
<target>TCP_KEEPCNT</target>
|
||||
|
@ -7198,6 +7353,10 @@ Enable in *Network & servers* settings.</source>
|
|||
<target>在步骤 %@ 上测试失败。</target>
|
||||
<note>server test failure</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Test notifications" xml:space="preserve">
|
||||
<source>Test notifications</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Test server" xml:space="preserve">
|
||||
<source>Test server</source>
|
||||
<target>测试服务器</target>
|
||||
|
@ -7323,10 +7482,6 @@ It can happen because of some bug or when the connection is compromised.</source
|
|||
<target>该资料仅与您的联系人共享。</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="The report will be archived for you." xml:space="preserve">
|
||||
<source>The report will be archived for you.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve">
|
||||
<source>The same conditions will apply to operator **%@**.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
|
@ -7450,6 +7605,10 @@ It can happen because of some bug or when the connection is compromised.</source
|
|||
<target>此链接已在其他移动设备上使用,请在桌面上创建新链接。</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="This message was deleted or not received yet." xml:space="preserve">
|
||||
<source>This message was deleted or not received yet.</source>
|
||||
<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">
|
||||
<source>This setting applies to messages in your current chat profile **%@**.</source>
|
||||
<target>此设置适用于您当前聊天资料 **%@** 中的消息。</target>
|
||||
|
@ -7556,6 +7715,10 @@ You will be prompted to complete authentication before this feature is enabled.<
|
|||
<target>在连接时切换隐身模式。</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Token status: %@." xml:space="preserve">
|
||||
<source>Token status: %@.</source>
|
||||
<note>token status</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Toolbar opacity" xml:space="preserve">
|
||||
<source>Toolbar opacity</source>
|
||||
<target>工具栏不透明度</target>
|
||||
|
@ -7720,7 +7883,7 @@ To connect, please ask your contact to create another connection link and check
|
|||
<trans-unit id="Unmute" xml:space="preserve">
|
||||
<source>Unmute</source>
|
||||
<target>取消静音</target>
|
||||
<note>swipe action</note>
|
||||
<note>notification label action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Unread" xml:space="preserve">
|
||||
<source>Unread</source>
|
||||
|
@ -7752,6 +7915,10 @@ To connect, please ask your contact to create another connection link and check
|
|||
<target>更新设置?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Updated conditions" xml:space="preserve">
|
||||
<source>Updated conditions</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Updating settings will re-connect the client to all servers." xml:space="preserve">
|
||||
<source>Updating settings will re-connect the client to all servers.</source>
|
||||
<target>更新设置会将客户端重新连接到所有服务器。</target>
|
||||
|
@ -7810,6 +7977,10 @@ To connect, please ask your contact to create another connection link and check
|
|||
<target>使用 SimpleX Chat 服务器?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use TCP port %@ when no port is specified." xml:space="preserve">
|
||||
<source>Use TCP port %@ when no port is specified.</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use chat" xml:space="preserve">
|
||||
<source>Use chat</source>
|
||||
<target>使用聊天</target>
|
||||
|
@ -7882,6 +8053,10 @@ To connect, please ask your contact to create another connection link and check
|
|||
<target>用一只手使用应用程序。</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use web port" xml:space="preserve">
|
||||
<source>Use web port</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="User selection" xml:space="preserve">
|
||||
<source>User selection</source>
|
||||
<target>用户选择</target>
|
||||
|
@ -8427,6 +8602,10 @@ Repeat connection request?</source>
|
|||
<target>您发送了群组邀请</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="You should receive notifications." xml:space="preserve">
|
||||
<source>You should receive notifications.</source>
|
||||
<note>token info</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="You will be connected to group when the group host's device is online, please wait or check later!" xml:space="preserve">
|
||||
<source>You will be connected to group when the group host's device is online, please wait or check later!</source>
|
||||
<target>您将在组主设备上线时连接到该群组,请稍等或稍后再检查!</target>
|
||||
|
@ -9213,11 +9392,6 @@ Repeat connection request?</source>
|
|||
<target>月</target>
|
||||
<note>time unit</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="mute" xml:space="preserve">
|
||||
<source>mute</source>
|
||||
<target>静音</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="never" xml:space="preserve">
|
||||
<source>never</source>
|
||||
<target>从不</target>
|
||||
|
@ -9295,6 +9469,14 @@ Repeat connection request?</source>
|
|||
<target>点对点</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="pending" xml:space="preserve">
|
||||
<source>pending</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="pending approval" xml:space="preserve">
|
||||
<source>pending approval</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="quantum resistant e2e encryption" xml:space="preserve">
|
||||
<source>quantum resistant e2e encryption</source>
|
||||
<target>抗量子端到端加密</target>
|
||||
|
@ -9310,6 +9492,10 @@ Repeat connection request?</source>
|
|||
<target>已受到确认……</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="rejected" xml:space="preserve">
|
||||
<source>rejected</source>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="rejected call" xml:space="preserve">
|
||||
<source>rejected call</source>
|
||||
<target>拒接来电</target>
|
||||
|
@ -9443,11 +9629,6 @@ last received msg: %2$@</source>
|
|||
<target>未知状态</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="unmute" xml:space="preserve">
|
||||
<source>unmute</source>
|
||||
<target>取消静音</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="unprotected" xml:space="preserve">
|
||||
<source>unprotected</source>
|
||||
<target>未受保护</target>
|
||||
|
|
|
@ -790,7 +790,12 @@ func receivedMsgNtf(_ res: ChatResponse) async -> (String, NSENotificationData)?
|
|||
cItem = autoReceiveFile(file) ?? cItem
|
||||
}
|
||||
let ntf: NSENotificationData = (cInfo.ntfsEnabled(chatItem: cItem) && cItem.showNotification) ? .messageReceived(user, cInfo, cItem) : .noNtf
|
||||
return (chatItem.chatId, ntf)
|
||||
let chatIdOrMemberId = if case let .groupRcv(groupMember) = chatItem.chatItem.chatDir {
|
||||
groupMember.id
|
||||
} else {
|
||||
chatItem.chatInfo.id
|
||||
}
|
||||
return (chatIdOrMemberId, ntf)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,7 +1,3 @@
|
|||
/*
|
||||
Localizable.strings
|
||||
SimpleX
|
||||
/* notification body */
|
||||
"New messages in %d chats" = "Nowe wiadomości w %d czatach";
|
||||
|
||||
Created by EP on 30/07/2024.
|
||||
Copyright © 2024 SimpleX Chat. All rights reserved.
|
||||
*/
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
"Comment" = "Hozzászólás";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Currently maximum supported file size is %@." = "Jelenleg a maximálisan támogatott fájlméret: %@.";
|
||||
"Currently maximum supported file size is %@." = "Jelenleg támogatott legnagyobb fájl méret: %@.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Database downgrade required" = "Adatbázis visszafejlesztése szükséges";
|
||||
|
@ -92,7 +92,7 @@
|
|||
"Share" = "Megosztás";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Slow network?" = "Lassú internetkapcsolat?";
|
||||
"Slow network?" = "Lassú a hálózata?";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Unknown database error: %@" = "Ismeretlen adatbázishiba: %@";
|
||||
|
|
|
@ -166,17 +166,17 @@
|
|||
647F090E288EA27B00644C40 /* GroupMemberInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 647F090D288EA27B00644C40 /* GroupMemberInfoView.swift */; };
|
||||
648010AB281ADD15009009B9 /* CIFileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 648010AA281ADD15009009B9 /* CIFileView.swift */; };
|
||||
648679AB2BC96A74006456E7 /* ChatItemForwardingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 648679AA2BC96A74006456E7 /* ChatItemForwardingView.swift */; };
|
||||
649B28DD2CFE07CF00536B68 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 649B28D82CFE07CF00536B68 /* libffi.a */; };
|
||||
649B28DE2CFE07CF00536B68 /* libHSsimplex-chat-6.3.0.2-Dof9ekfAaNQ8X3suD73WcH-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 649B28D92CFE07CF00536B68 /* libHSsimplex-chat-6.3.0.2-Dof9ekfAaNQ8X3suD73WcH-ghc9.6.3.a */; };
|
||||
649B28DF2CFE07CF00536B68 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 649B28DA2CFE07CF00536B68 /* libgmpxx.a */; };
|
||||
649B28E02CFE07CF00536B68 /* libHSsimplex-chat-6.3.0.2-Dof9ekfAaNQ8X3suD73WcH.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 649B28DB2CFE07CF00536B68 /* libHSsimplex-chat-6.3.0.2-Dof9ekfAaNQ8X3suD73WcH.a */; };
|
||||
649B28E12CFE07CF00536B68 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 649B28DC2CFE07CF00536B68 /* libgmp.a */; };
|
||||
649BCDA0280460FD00C3A862 /* ComposeImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 649BCD9F280460FD00C3A862 /* ComposeImageView.swift */; };
|
||||
649BCDA22805D6EF00C3A862 /* CIImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 649BCDA12805D6EF00C3A862 /* CIImageView.swift */; };
|
||||
64AA1C6927EE10C800AC7277 /* ContextItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64AA1C6827EE10C800AC7277 /* ContextItemView.swift */; };
|
||||
64AA1C6C27F3537400AC7277 /* DeletedItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64AA1C6B27F3537400AC7277 /* DeletedItemView.swift */; };
|
||||
64C06EB52A0A4A7C00792D4D /* ChatItemInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64C06EB42A0A4A7C00792D4D /* ChatItemInfoView.swift */; };
|
||||
64C3B0212A0D359700E19930 /* CustomTimePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64C3B0202A0D359700E19930 /* CustomTimePicker.swift */; };
|
||||
64C8299D2D54AEEE006B9E89 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C829982D54AEED006B9E89 /* libgmp.a */; };
|
||||
64C8299E2D54AEEE006B9E89 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C829992D54AEEE006B9E89 /* libffi.a */; };
|
||||
64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.0.8-3RDt4h0Fq4hJV00CU7V8H-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.0.8-3RDt4h0Fq4hJV00CU7V8H-ghc9.6.3.a */; };
|
||||
64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-6.3.0.8-3RDt4h0Fq4hJV00CU7V8H.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.0.8-3RDt4h0Fq4hJV00CU7V8H.a */; };
|
||||
64C829A12D54AEEE006B9E89 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299C2D54AEEE006B9E89 /* libgmpxx.a */; };
|
||||
64D0C2C029F9688300B38D5F /* UserAddressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64D0C2BF29F9688300B38D5F /* UserAddressView.swift */; };
|
||||
64D0C2C229FA57AB00B38D5F /* UserAddressLearnMore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64D0C2C129FA57AB00B38D5F /* UserAddressLearnMore.swift */; };
|
||||
64D0C2C629FAC1EC00B38D5F /* AddContactLearnMore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64D0C2C529FAC1EC00B38D5F /* AddContactLearnMore.swift */; };
|
||||
|
@ -198,9 +198,14 @@
|
|||
8C8118722C220B5B00E6FC94 /* Yams in Frameworks */ = {isa = PBXBuildFile; productRef = 8C8118712C220B5B00E6FC94 /* Yams */; };
|
||||
8C81482C2BD91CD4002CBEC3 /* AudioDevicePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C81482B2BD91CD4002CBEC3 /* AudioDevicePicker.swift */; };
|
||||
8C9BC2652C240D5200875A27 /* ThemeModeEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C9BC2642C240D5100875A27 /* ThemeModeEditor.swift */; };
|
||||
8CAD466F2D15A8100078D18F /* ChatScrollHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CAD466E2D15A8100078D18F /* ChatScrollHelpers.swift */; };
|
||||
8CAEF1502D11A6A000240F00 /* ChatItemsLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CAEF14F2D11A6A000240F00 /* ChatItemsLoader.swift */; };
|
||||
8CB15EA02CFDA30600C28209 /* ChatItemsMerger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CB15E9F2CFDA30600C28209 /* ChatItemsMerger.swift */; };
|
||||
8CB3476C2CF5CFFA006787A5 /* Ink in Frameworks */ = {isa = PBXBuildFile; productRef = 8CB3476B2CF5CFFA006787A5 /* Ink */; };
|
||||
8CB3476E2CF5F58B006787A5 /* ConditionsWebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CB3476D2CF5F58B006787A5 /* ConditionsWebView.swift */; };
|
||||
8CBC14862D357CDB00BBD901 /* StorageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CBC14852D357CDB00BBD901 /* StorageView.swift */; };
|
||||
8CC317442D4FEB9B00292A20 /* EndlessScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CC317432D4FEB9B00292A20 /* EndlessScrollView.swift */; };
|
||||
8CC317462D4FEBA800292A20 /* ScrollViewCells.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CC317452D4FEBA800292A20 /* ScrollViewCells.swift */; };
|
||||
8CC4ED902BD7B8530078AEE8 /* CallAudioDeviceManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CC4ED8F2BD7B8530078AEE8 /* CallAudioDeviceManager.swift */; };
|
||||
8CC956EE2BC0041000412A11 /* NetworkObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CC956ED2BC0041000412A11 /* NetworkObserver.swift */; };
|
||||
8CE848A32C5A0FA000D5C7C8 /* SelectableChatItemToolbars.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CE848A22C5A0FA000D5C7C8 /* SelectableChatItemToolbars.swift */; };
|
||||
|
@ -225,7 +230,6 @@
|
|||
CEE723B12C3BD3D70009AE93 /* SimpleX SE.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = CEE723A72C3BD3D70009AE93 /* SimpleX SE.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
CEE723F02C3D25C70009AE93 /* ShareView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEE723EF2C3D25C70009AE93 /* ShareView.swift */; };
|
||||
CEE723F22C3D25ED0009AE93 /* ShareModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEE723F12C3D25ED0009AE93 /* ShareModel.swift */; };
|
||||
CEEA861D2C2ABCB50084E1EA /* ReverseList.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEEA861C2C2ABCB50084E1EA /* ReverseList.swift */; };
|
||||
CEFB2EDF2CA1BCC7004B1ECE /* SheetRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEFB2EDE2CA1BCC7004B1ECE /* SheetRepresentable.swift */; };
|
||||
D7197A1829AE89660055C05A /* WebRTC in Frameworks */ = {isa = PBXBuildFile; productRef = D7197A1729AE89660055C05A /* WebRTC */; };
|
||||
D72A9088294BD7A70047C86D /* NativeTextEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = D72A9087294BD7A70047C86D /* NativeTextEditor.swift */; };
|
||||
|
@ -519,17 +523,17 @@
|
|||
648010AA281ADD15009009B9 /* CIFileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIFileView.swift; sourceTree = "<group>"; };
|
||||
648679AA2BC96A74006456E7 /* ChatItemForwardingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatItemForwardingView.swift; sourceTree = "<group>"; };
|
||||
6493D667280ED77F007A76FB /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
649B28D82CFE07CF00536B68 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = "<group>"; };
|
||||
649B28D92CFE07CF00536B68 /* libHSsimplex-chat-6.3.0.2-Dof9ekfAaNQ8X3suD73WcH-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.3.0.2-Dof9ekfAaNQ8X3suD73WcH-ghc9.6.3.a"; sourceTree = "<group>"; };
|
||||
649B28DA2CFE07CF00536B68 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = "<group>"; };
|
||||
649B28DB2CFE07CF00536B68 /* libHSsimplex-chat-6.3.0.2-Dof9ekfAaNQ8X3suD73WcH.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.3.0.2-Dof9ekfAaNQ8X3suD73WcH.a"; sourceTree = "<group>"; };
|
||||
649B28DC2CFE07CF00536B68 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = "<group>"; };
|
||||
649BCD9F280460FD00C3A862 /* ComposeImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeImageView.swift; sourceTree = "<group>"; };
|
||||
649BCDA12805D6EF00C3A862 /* CIImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIImageView.swift; sourceTree = "<group>"; };
|
||||
64AA1C6827EE10C800AC7277 /* ContextItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextItemView.swift; sourceTree = "<group>"; };
|
||||
64AA1C6B27F3537400AC7277 /* DeletedItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeletedItemView.swift; sourceTree = "<group>"; };
|
||||
64C06EB42A0A4A7C00792D4D /* ChatItemInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatItemInfoView.swift; sourceTree = "<group>"; };
|
||||
64C3B0202A0D359700E19930 /* CustomTimePicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomTimePicker.swift; sourceTree = "<group>"; };
|
||||
64C829982D54AEED006B9E89 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = "<group>"; };
|
||||
64C829992D54AEEE006B9E89 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = "<group>"; };
|
||||
64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.0.8-3RDt4h0Fq4hJV00CU7V8H-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.3.0.8-3RDt4h0Fq4hJV00CU7V8H-ghc9.6.3.a"; sourceTree = "<group>"; };
|
||||
64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.0.8-3RDt4h0Fq4hJV00CU7V8H.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.3.0.8-3RDt4h0Fq4hJV00CU7V8H.a"; sourceTree = "<group>"; };
|
||||
64C8299C2D54AEEE006B9E89 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = "<group>"; };
|
||||
64D0C2BF29F9688300B38D5F /* UserAddressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAddressView.swift; sourceTree = "<group>"; };
|
||||
64D0C2C129FA57AB00B38D5F /* UserAddressLearnMore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAddressLearnMore.swift; sourceTree = "<group>"; };
|
||||
64D0C2C529FAC1EC00B38D5F /* AddContactLearnMore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddContactLearnMore.swift; sourceTree = "<group>"; };
|
||||
|
@ -551,8 +555,13 @@
|
|||
8C852B072C1086D100BA61E8 /* Color.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Color.swift; sourceTree = "<group>"; };
|
||||
8C86EBE42C0DAE4F00E12243 /* ThemeManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemeManager.swift; sourceTree = "<group>"; };
|
||||
8C9BC2642C240D5100875A27 /* ThemeModeEditor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemeModeEditor.swift; sourceTree = "<group>"; };
|
||||
8CAD466E2D15A8100078D18F /* ChatScrollHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatScrollHelpers.swift; sourceTree = "<group>"; };
|
||||
8CAEF14F2D11A6A000240F00 /* ChatItemsLoader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatItemsLoader.swift; sourceTree = "<group>"; };
|
||||
8CB15E9F2CFDA30600C28209 /* ChatItemsMerger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatItemsMerger.swift; sourceTree = "<group>"; };
|
||||
8CB3476D2CF5F58B006787A5 /* ConditionsWebView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConditionsWebView.swift; sourceTree = "<group>"; };
|
||||
8CBC14852D357CDB00BBD901 /* StorageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorageView.swift; sourceTree = "<group>"; };
|
||||
8CC317432D4FEB9B00292A20 /* EndlessScrollView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EndlessScrollView.swift; sourceTree = "<group>"; };
|
||||
8CC317452D4FEBA800292A20 /* ScrollViewCells.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScrollViewCells.swift; sourceTree = "<group>"; };
|
||||
8CC4ED8F2BD7B8530078AEE8 /* CallAudioDeviceManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallAudioDeviceManager.swift; sourceTree = "<group>"; };
|
||||
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>"; };
|
||||
|
@ -576,7 +585,6 @@
|
|||
CEE723D42C3C21F50009AE93 /* SimpleX SE.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "SimpleX SE.entitlements"; sourceTree = "<group>"; };
|
||||
CEE723EF2C3D25C70009AE93 /* ShareView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareView.swift; sourceTree = "<group>"; };
|
||||
CEE723F12C3D25ED0009AE93 /* ShareModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareModel.swift; sourceTree = "<group>"; };
|
||||
CEEA861C2C2ABCB50084E1EA /* ReverseList.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReverseList.swift; sourceTree = "<group>"; };
|
||||
CEFB2EDE2CA1BCC7004B1ECE /* SheetRepresentable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SheetRepresentable.swift; sourceTree = "<group>"; };
|
||||
D72A9087294BD7A70047C86D /* NativeTextEditor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NativeTextEditor.swift; sourceTree = "<group>"; };
|
||||
D741547729AF89AF0022400A /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS16.1.sdk/System/Library/Frameworks/StoreKit.framework; sourceTree = DEVELOPER_DIR; };
|
||||
|
@ -675,14 +683,14 @@
|
|||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
649B28DF2CFE07CF00536B68 /* libgmpxx.a in Frameworks */,
|
||||
5CE2BA93284534B000EC33A6 /* libiconv.tbd in Frameworks */,
|
||||
649B28E12CFE07CF00536B68 /* libgmp.a in Frameworks */,
|
||||
5CE2BA94284534BB00EC33A6 /* libz.tbd in Frameworks */,
|
||||
649B28E02CFE07CF00536B68 /* libHSsimplex-chat-6.3.0.2-Dof9ekfAaNQ8X3suD73WcH.a in Frameworks */,
|
||||
64C8299D2D54AEEE006B9E89 /* libgmp.a in Frameworks */,
|
||||
64C8299E2D54AEEE006B9E89 /* libffi.a in Frameworks */,
|
||||
64C829A12D54AEEE006B9E89 /* libgmpxx.a in Frameworks */,
|
||||
64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.0.8-3RDt4h0Fq4hJV00CU7V8H-ghc9.6.3.a in Frameworks */,
|
||||
64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-6.3.0.8-3RDt4h0Fq4hJV00CU7V8H.a in Frameworks */,
|
||||
CE38A29C2C3FCD72005ED185 /* SwiftyGif in Frameworks */,
|
||||
649B28DE2CFE07CF00536B68 /* libHSsimplex-chat-6.3.0.2-Dof9ekfAaNQ8X3suD73WcH-ghc9.6.3.a in Frameworks */,
|
||||
649B28DD2CFE07CF00536B68 /* libffi.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -737,6 +745,8 @@
|
|||
5C5F4AC227A5E9AF00B51EF1 /* Chat */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8CC317452D4FEBA800292A20 /* ScrollViewCells.swift */,
|
||||
8CC317432D4FEB9B00292A20 /* EndlessScrollView.swift */,
|
||||
6440CA01288AEC770062C672 /* Group */,
|
||||
5CE4407427ADB657007B033A /* ChatItem */,
|
||||
5CEACCE527DE977C000BD591 /* ComposeMessage */,
|
||||
|
@ -747,11 +757,13 @@
|
|||
5CE4407127ADB1D0007B033A /* Emoji.swift */,
|
||||
5CADE79B292131E900072E13 /* ContactPreferencesView.swift */,
|
||||
5CBE6C11294487F7002D9531 /* VerifyCodeView.swift */,
|
||||
CEEA861C2C2ABCB50084E1EA /* ReverseList.swift */,
|
||||
5CBE6C132944CC12002D9531 /* ScanCodeView.swift */,
|
||||
64C06EB42A0A4A7C00792D4D /* ChatItemInfoView.swift */,
|
||||
648679AA2BC96A74006456E7 /* ChatItemForwardingView.swift */,
|
||||
8CE848A22C5A0FA000D5C7C8 /* SelectableChatItemToolbars.swift */,
|
||||
8CB15E9F2CFDA30600C28209 /* ChatItemsMerger.swift */,
|
||||
8CAEF14F2D11A6A000240F00 /* ChatItemsLoader.swift */,
|
||||
8CAD466E2D15A8100078D18F /* ChatScrollHelpers.swift */,
|
||||
);
|
||||
path = Chat;
|
||||
sourceTree = "<group>";
|
||||
|
@ -759,11 +771,11 @@
|
|||
5C764E5C279C70B7000C6508 /* Libraries */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
649B28D82CFE07CF00536B68 /* libffi.a */,
|
||||
649B28DC2CFE07CF00536B68 /* libgmp.a */,
|
||||
649B28DA2CFE07CF00536B68 /* libgmpxx.a */,
|
||||
649B28D92CFE07CF00536B68 /* libHSsimplex-chat-6.3.0.2-Dof9ekfAaNQ8X3suD73WcH-ghc9.6.3.a */,
|
||||
649B28DB2CFE07CF00536B68 /* libHSsimplex-chat-6.3.0.2-Dof9ekfAaNQ8X3suD73WcH.a */,
|
||||
64C829992D54AEEE006B9E89 /* libffi.a */,
|
||||
64C829982D54AEED006B9E89 /* libgmp.a */,
|
||||
64C8299C2D54AEEE006B9E89 /* libgmpxx.a */,
|
||||
64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.0.8-3RDt4h0Fq4hJV00CU7V8H-ghc9.6.3.a */,
|
||||
64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.0.8-3RDt4h0Fq4hJV00CU7V8H.a */,
|
||||
);
|
||||
path = Libraries;
|
||||
sourceTree = "<group>";
|
||||
|
@ -1408,8 +1420,8 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
CEEA861D2C2ABCB50084E1EA /* ReverseList.swift in Sources */,
|
||||
64C06EB52A0A4A7C00792D4D /* ChatItemInfoView.swift in Sources */,
|
||||
8CC317442D4FEB9B00292A20 /* EndlessScrollView.swift in Sources */,
|
||||
640417CE2B29B8C200CCB412 /* NewChatView.swift in Sources */,
|
||||
6440CA03288AECA70062C672 /* AddGroupMembersView.swift in Sources */,
|
||||
640743612CD360E600158442 /* ChooseServerOperators.swift in Sources */,
|
||||
|
@ -1427,6 +1439,7 @@
|
|||
5C13730B28156D2700F43030 /* ContactConnectionView.swift in Sources */,
|
||||
644EFFE0292CFD7F00525D5B /* CIVoiceView.swift in Sources */,
|
||||
6432857C2925443C00FBE5C8 /* GroupPreferencesView.swift in Sources */,
|
||||
8CC317462D4FEBA800292A20 /* ScrollViewCells.swift in Sources */,
|
||||
5C93293129239BED0090FFF9 /* ProtocolServerView.swift in Sources */,
|
||||
5C9CC7AD28C55D7800BEF955 /* DatabaseEncryptionView.swift in Sources */,
|
||||
8C74C3EC2C1B92A900039E77 /* Theme.swift in Sources */,
|
||||
|
@ -1516,6 +1529,7 @@
|
|||
5C6BA667289BD954009B8ECC /* DismissSheets.swift in Sources */,
|
||||
5C577F7D27C83AA10006112D /* MarkdownHelp.swift in Sources */,
|
||||
6407BA83295DA85D0082BA18 /* CIInvalidJSONView.swift in Sources */,
|
||||
8CAD466F2D15A8100078D18F /* ChatScrollHelpers.swift in Sources */,
|
||||
644EFFDE292BCD9D00525D5B /* ComposeVoiceView.swift in Sources */,
|
||||
5CA059EB279559F40002BEB4 /* SimpleXApp.swift in Sources */,
|
||||
64D0C2C029F9688300B38D5F /* UserAddressView.swift in Sources */,
|
||||
|
@ -1527,6 +1541,7 @@
|
|||
5CADE79C292131E900072E13 /* ContactPreferencesView.swift in Sources */,
|
||||
CEA6E91C2CBD21B0002B5DB4 /* UserDefault.swift in Sources */,
|
||||
5CB346E52868AA7F001FD2EF /* SuspendChat.swift in Sources */,
|
||||
8CAEF1502D11A6A000240F00 /* ChatItemsLoader.swift in Sources */,
|
||||
5C9C2DA52894777E00CC63B1 /* GroupProfileView.swift in Sources */,
|
||||
5CEACCED27DEA495000BD591 /* MsgContentView.swift in Sources */,
|
||||
8C81482C2BD91CD4002CBEC3 /* AudioDevicePicker.swift in Sources */,
|
||||
|
@ -1566,6 +1581,7 @@
|
|||
64C3B0212A0D359700E19930 /* CustomTimePicker.swift in Sources */,
|
||||
8CC4ED902BD7B8530078AEE8 /* CallAudioDeviceManager.swift in Sources */,
|
||||
18415C6C56DBCEC2CBBD2F11 /* WebRTCClient.swift in Sources */,
|
||||
8CB15EA02CFDA30600C28209 /* ChatItemsMerger.swift in Sources */,
|
||||
184152CEF68D2336FC2EBCB0 /* CallViewRenderers.swift in Sources */,
|
||||
5CB634AD29E46CF70066AD6B /* LocalAuthView.swift in Sources */,
|
||||
18415FEFE153C5920BFB7828 /* GroupWelcomeView.swift in Sources */,
|
||||
|
@ -1947,7 +1963,7 @@
|
|||
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 261;
|
||||
CURRENT_PROJECT_VERSION = 269;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
||||
ENABLE_BITCODE = NO;
|
||||
|
@ -1973,6 +1989,7 @@
|
|||
);
|
||||
LLVM_LTO = YES_THIN;
|
||||
MARKETING_VERSION = 6.3;
|
||||
OTHER_LDFLAGS = "-Wl,-stack_size,0x1000000";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app;
|
||||
PRODUCT_NAME = SimpleX;
|
||||
SDKROOT = iphoneos;
|
||||
|
@ -1996,7 +2013,7 @@
|
|||
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 261;
|
||||
CURRENT_PROJECT_VERSION = 269;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
||||
ENABLE_BITCODE = NO;
|
||||
|
@ -2022,6 +2039,7 @@
|
|||
);
|
||||
LLVM_LTO = YES;
|
||||
MARKETING_VERSION = 6.3;
|
||||
OTHER_LDFLAGS = "-Wl,-stack_size,0x1000000";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app;
|
||||
PRODUCT_NAME = SimpleX;
|
||||
SDKROOT = iphoneos;
|
||||
|
@ -2037,7 +2055,7 @@
|
|||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 261;
|
||||
CURRENT_PROJECT_VERSION = 269;
|
||||
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
|
@ -2057,7 +2075,7 @@
|
|||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 261;
|
||||
CURRENT_PROJECT_VERSION = 269;
|
||||
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
|
@ -2082,7 +2100,7 @@
|
|||
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 261;
|
||||
CURRENT_PROJECT_VERSION = 269;
|
||||
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
||||
ENABLE_BITCODE = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = s;
|
||||
|
@ -2119,7 +2137,7 @@
|
|||
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 261;
|
||||
CURRENT_PROJECT_VERSION = 269;
|
||||
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
||||
ENABLE_BITCODE = NO;
|
||||
ENABLE_CODE_COVERAGE = NO;
|
||||
|
@ -2156,7 +2174,7 @@
|
|||
CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES;
|
||||
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 261;
|
||||
CURRENT_PROJECT_VERSION = 269;
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
|
@ -2207,7 +2225,7 @@
|
|||
CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES;
|
||||
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 261;
|
||||
CURRENT_PROJECT_VERSION = 269;
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
|
@ -2258,7 +2276,7 @@
|
|||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||
CODE_SIGN_ENTITLEMENTS = "SimpleX SE/SimpleX SE.entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 261;
|
||||
CURRENT_PROJECT_VERSION = 269;
|
||||
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||
|
@ -2292,7 +2310,7 @@
|
|||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||
CODE_SIGN_ENTITLEMENTS = "SimpleX SE/SimpleX SE.entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 261;
|
||||
CURRENT_PROJECT_VERSION = 269;
|
||||
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||
|
|
|
@ -203,7 +203,7 @@ public func chatResponse(_ s: String) -> ChatResponse {
|
|||
let jChats = jApiChats["chats"] as? NSArray {
|
||||
let chats = jChats.map { jChat in
|
||||
if let chatData = try? parseChatData(jChat) {
|
||||
return chatData
|
||||
return chatData.0
|
||||
}
|
||||
return ChatData.invalidJSON(serializeJSON(jChat, options: .prettyPrinted) ?? "")
|
||||
}
|
||||
|
@ -213,8 +213,8 @@ public func chatResponse(_ s: String) -> ChatResponse {
|
|||
if let jApiChat = jResp["apiChat"] as? NSDictionary,
|
||||
let user: UserRef = try? decodeObject(jApiChat["user"] as Any),
|
||||
let jChat = jApiChat["chat"] as? NSDictionary,
|
||||
let chat = try? parseChatData(jChat) {
|
||||
return .apiChat(user: user, chat: chat)
|
||||
let (chat, navInfo) = try? parseChatData(jChat, jApiChat["navInfo"] as? NSDictionary) {
|
||||
return .apiChat(user: user, chat: chat, navInfo: navInfo)
|
||||
}
|
||||
} else if type == "chatCmdError" {
|
||||
if let jError = jResp["chatCmdError"] as? NSDictionary {
|
||||
|
@ -247,10 +247,11 @@ private func errorJson(_ jDict: NSDictionary) -> String? {
|
|||
}
|
||||
}
|
||||
|
||||
func parseChatData(_ jChat: Any) throws -> ChatData {
|
||||
func parseChatData(_ jChat: Any, _ jNavInfo: Any? = nil) throws -> (ChatData, NavigationInfo) {
|
||||
let jChatDict = jChat as! NSDictionary
|
||||
let chatInfo: ChatInfo = try decodeObject(jChatDict["chatInfo"]!)
|
||||
let chatStats: ChatStats = try decodeObject(jChatDict["chatStats"]!)
|
||||
let navInfo: NavigationInfo = jNavInfo == nil ? NavigationInfo() : try decodeObject((jNavInfo as! NSDictionary)["navInfo"]!)
|
||||
let jChatItems = jChatDict["chatItems"] as! NSArray
|
||||
let chatItems = jChatItems.map { jCI in
|
||||
if let ci: ChatItem = try? decodeObject(jCI) {
|
||||
|
@ -262,7 +263,7 @@ func parseChatData(_ jChat: Any) throws -> ChatData {
|
|||
json: serializeJSON(jCI, options: .prettyPrinted) ?? ""
|
||||
)
|
||||
}
|
||||
return ChatData(chatInfo: chatInfo, chatItems: chatItems, chatStats: chatStats)
|
||||
return (ChatData(chatInfo: chatInfo, chatItems: chatItems, chatStats: chatStats), navInfo)
|
||||
}
|
||||
|
||||
func decodeObject<T: Decodable>(_ obj: Any) throws -> T {
|
||||
|
|
|
@ -42,7 +42,7 @@ public enum ChatCommand {
|
|||
case apiGetSettings(settings: AppSettings)
|
||||
case apiGetChatTags(userId: Int64)
|
||||
case apiGetChats(userId: Int64)
|
||||
case apiGetChat(type: ChatType, id: Int64, pagination: ChatPagination, search: String)
|
||||
case apiGetChat(chatId: ChatId, pagination: ChatPagination, search: String)
|
||||
case apiGetChatItemInfo(type: ChatType, id: Int64, itemId: Int64)
|
||||
case apiSendMessages(type: ChatType, id: Int64, live: Bool, ttl: Int?, composedMessages: [ComposedMessage])
|
||||
case apiCreateChatTag(tag: ChatTagData)
|
||||
|
@ -55,6 +55,8 @@ public enum ChatCommand {
|
|||
case apiUpdateChatItem(type: ChatType, id: Int64, itemId: Int64, updatedMessage: UpdatedMessage, live: Bool)
|
||||
case apiDeleteChatItem(type: ChatType, id: Int64, itemIds: [Int64], mode: CIDeleteMode)
|
||||
case apiDeleteMemberChatItem(groupId: Int64, itemIds: [Int64])
|
||||
case apiArchiveReceivedReports(groupId: Int64)
|
||||
case apiDeleteReceivedReports(groupId: Int64, itemIds: [Int64], mode: CIDeleteMode)
|
||||
case apiChatItemReaction(type: ChatType, id: Int64, itemId: Int64, add: Bool, reaction: MsgReaction)
|
||||
case apiGetReactionMembers(userId: Int64, groupId: Int64, itemId: Int64, reaction: MsgReaction)
|
||||
case apiPlanForwardChatItems(toChatType: ChatType, toChatId: Int64, itemIds: [Int64])
|
||||
|
@ -62,15 +64,16 @@ public enum ChatCommand {
|
|||
case apiGetNtfToken
|
||||
case apiRegisterToken(token: DeviceToken, notificationMode: NotificationsMode)
|
||||
case apiVerifyToken(token: DeviceToken, nonce: String, code: String)
|
||||
case apiCheckToken(token: DeviceToken)
|
||||
case apiDeleteToken(token: DeviceToken)
|
||||
case apiGetNtfConns(nonce: String, encNtfInfo: String)
|
||||
case apiGetConnNtfMessages(connIds: [String])
|
||||
case apiNewGroup(userId: Int64, incognito: Bool, groupProfile: GroupProfile)
|
||||
case apiAddMember(groupId: Int64, contactId: Int64, memberRole: GroupMemberRole)
|
||||
case apiJoinGroup(groupId: Int64)
|
||||
case apiMemberRole(groupId: Int64, memberId: Int64, memberRole: GroupMemberRole)
|
||||
case apiBlockMemberForAll(groupId: Int64, memberId: Int64, blocked: Bool)
|
||||
case apiRemoveMember(groupId: Int64, memberId: Int64)
|
||||
case apiMembersRole(groupId: Int64, memberIds: [Int64], memberRole: GroupMemberRole)
|
||||
case apiBlockMembersForAll(groupId: Int64, memberIds: [Int64], blocked: Bool)
|
||||
case apiRemoveMembers(groupId: Int64, memberIds: [Int64], withMessages: Bool)
|
||||
case apiLeaveGroup(groupId: Int64)
|
||||
case apiListMembers(groupId: Int64)
|
||||
case apiUpdateGroupProfile(groupId: Int64, groupProfile: GroupProfile)
|
||||
|
@ -209,7 +212,7 @@ public enum ChatCommand {
|
|||
case let .apiGetSettings(settings): return "/_get app settings \(encodeJSON(settings))"
|
||||
case let .apiGetChatTags(userId): return "/_get tags \(userId)"
|
||||
case let .apiGetChats(userId): return "/_get chats \(userId) pcc=on"
|
||||
case let .apiGetChat(type, id, pagination, search): return "/_get chat \(ref(type, id)) \(pagination.cmdString)" +
|
||||
case let .apiGetChat(chatId, pagination, search): return "/_get chat \(chatId) \(pagination.cmdString)" +
|
||||
(search == "" ? "" : " search=\(search)")
|
||||
case let .apiGetChatItemInfo(type, id, itemId): return "/_get item info \(ref(type, id)) \(itemId)"
|
||||
case let .apiSendMessages(type, id, live, ttl, composedMessages):
|
||||
|
@ -229,6 +232,8 @@ public enum ChatCommand {
|
|||
case let .apiUpdateChatItem(type, id, itemId, um, live): return "/_update item \(ref(type, id)) \(itemId) live=\(onOff(live)) \(um.cmdString)"
|
||||
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 .apiArchiveReceivedReports(groupId): return "/_archive reports #\(groupId)"
|
||||
case let .apiDeleteReceivedReports(groupId, itemIds, mode): return "/_delete reports #\(groupId) \(itemIds.map({ "\($0)" }).joined(separator: ",")) \(mode.rawValue)"
|
||||
case let .apiChatItemReaction(type, id, itemId, add, reaction): return "/_reaction \(ref(type, id)) \(itemId) \(onOff(add)) \(encodeJSON(reaction))"
|
||||
case let .apiGetReactionMembers(userId, groupId, itemId, reaction): return "/_reaction members \(userId) #\(groupId) \(itemId) \(encodeJSON(reaction))"
|
||||
case let .apiPlanForwardChatItems(type, id, itemIds): return "/_forward plan \(ref(type, id)) \(itemIds.map({ "\($0)" }).joined(separator: ","))"
|
||||
|
@ -238,15 +243,16 @@ public enum ChatCommand {
|
|||
case .apiGetNtfToken: return "/_ntf get "
|
||||
case let .apiRegisterToken(token, notificationMode): return "/_ntf register \(token.cmdString) \(notificationMode.rawValue)"
|
||||
case let .apiVerifyToken(token, nonce, code): return "/_ntf verify \(token.cmdString) \(nonce) \(code)"
|
||||
case let .apiCheckToken(token): return "/_ntf check \(token.cmdString)"
|
||||
case let .apiDeleteToken(token): return "/_ntf delete \(token.cmdString)"
|
||||
case let .apiGetNtfConns(nonce, encNtfInfo): return "/_ntf conns \(nonce) \(encNtfInfo)"
|
||||
case let .apiGetConnNtfMessages(connIds): return "/_ntf conn messages \(connIds.joined(separator: ","))"
|
||||
case let .apiNewGroup(userId, incognito, groupProfile): return "/_group \(userId) incognito=\(onOff(incognito)) \(encodeJSON(groupProfile))"
|
||||
case let .apiAddMember(groupId, contactId, memberRole): return "/_add #\(groupId) \(contactId) \(memberRole)"
|
||||
case let .apiJoinGroup(groupId): return "/_join #\(groupId)"
|
||||
case let .apiMemberRole(groupId, memberId, memberRole): return "/_member role #\(groupId) \(memberId) \(memberRole.rawValue)"
|
||||
case let .apiBlockMemberForAll(groupId, memberId, blocked): return "/_block #\(groupId) \(memberId) blocked=\(onOff(blocked))"
|
||||
case let .apiRemoveMember(groupId, memberId): return "/_remove #\(groupId) \(memberId)"
|
||||
case let .apiMembersRole(groupId, memberIds, memberRole): return "/_member role #\(groupId) \(memberIds.map({ "\($0)" }).joined(separator: ",")) \(memberRole.rawValue)"
|
||||
case let .apiBlockMembersForAll(groupId, memberIds, blocked): return "/_block #\(groupId) \(memberIds.map({ "\($0)" }).joined(separator: ",")) blocked=\(onOff(blocked))"
|
||||
case let .apiRemoveMembers(groupId, memberIds, withMessages): return "/_remove #\(groupId) \(memberIds.map({ "\($0)" }).joined(separator: ",")) messages=\(onOff(withMessages))"
|
||||
case let .apiLeaveGroup(groupId): return "/_leave #\(groupId)"
|
||||
case let .apiListMembers(groupId): return "/_members #\(groupId)"
|
||||
case let .apiUpdateGroupProfile(groupId, groupProfile): return "/_group_profile #\(groupId) \(encodeJSON(groupProfile))"
|
||||
|
@ -402,6 +408,8 @@ public enum ChatCommand {
|
|||
case .apiDeleteChatItem: return "apiDeleteChatItem"
|
||||
case .apiConnectContactViaAddress: return "apiConnectContactViaAddress"
|
||||
case .apiDeleteMemberChatItem: return "apiDeleteMemberChatItem"
|
||||
case .apiArchiveReceivedReports: return "apiArchiveReceivedReports"
|
||||
case .apiDeleteReceivedReports: return "apiDeleteReceivedReports"
|
||||
case .apiChatItemReaction: return "apiChatItemReaction"
|
||||
case .apiGetReactionMembers: return "apiGetReactionMembers"
|
||||
case .apiPlanForwardChatItems: return "apiPlanForwardChatItems"
|
||||
|
@ -409,15 +417,16 @@ public enum ChatCommand {
|
|||
case .apiGetNtfToken: return "apiGetNtfToken"
|
||||
case .apiRegisterToken: return "apiRegisterToken"
|
||||
case .apiVerifyToken: return "apiVerifyToken"
|
||||
case .apiCheckToken: return "apiCheckToken"
|
||||
case .apiDeleteToken: return "apiDeleteToken"
|
||||
case .apiGetNtfConns: return "apiGetNtfConns"
|
||||
case .apiGetConnNtfMessages: return "apiGetConnNtfMessages"
|
||||
case .apiNewGroup: return "apiNewGroup"
|
||||
case .apiAddMember: return "apiAddMember"
|
||||
case .apiJoinGroup: return "apiJoinGroup"
|
||||
case .apiMemberRole: return "apiMemberRole"
|
||||
case .apiBlockMemberForAll: return "apiBlockMemberForAll"
|
||||
case .apiRemoveMember: return "apiRemoveMember"
|
||||
case .apiMembersRole: return "apiMembersRole"
|
||||
case .apiBlockMembersForAll: return "apiBlockMembersForAll"
|
||||
case .apiRemoveMembers: return "apiRemoveMembers"
|
||||
case .apiLeaveGroup: return "apiLeaveGroup"
|
||||
case .apiListMembers: return "apiListMembers"
|
||||
case .apiUpdateGroupProfile: return "apiUpdateGroupProfile"
|
||||
|
@ -591,7 +600,7 @@ public enum ChatResponse: Decodable, Error {
|
|||
case chatStopped
|
||||
case chatSuspended
|
||||
case apiChats(user: UserRef, chats: [ChatData])
|
||||
case apiChat(user: UserRef, chat: ChatData)
|
||||
case apiChat(user: UserRef, chat: ChatData, navInfo: NavigationInfo?)
|
||||
case chatTags(user: UserRef, userTags: [ChatTag])
|
||||
case chatItemInfo(user: UserRef, chatItem: AChatItem, chatItemInfo: ChatItemInfo)
|
||||
case serverTestResult(user: UserRef, testServer: String, testFailure: ProtocolTestFailure?)
|
||||
|
@ -672,18 +681,18 @@ public enum ChatResponse: Decodable, Error {
|
|||
case userAcceptedGroupSent(user: UserRef, groupInfo: GroupInfo, hostContact: Contact?)
|
||||
case groupLinkConnecting(user: UserRef, groupInfo: GroupInfo, hostMember: GroupMember)
|
||||
case businessLinkConnecting(user: UserRef, groupInfo: GroupInfo, hostMember: GroupMember, fromContact: Contact)
|
||||
case userDeletedMember(user: UserRef, groupInfo: GroupInfo, member: GroupMember)
|
||||
case userDeletedMembers(user: UserRef, groupInfo: GroupInfo, members: [GroupMember], withMessages: Bool)
|
||||
case leftMemberUser(user: UserRef, groupInfo: GroupInfo)
|
||||
case groupMembers(user: UserRef, group: Group)
|
||||
case receivedGroupInvitation(user: UserRef, groupInfo: GroupInfo, contact: Contact, memberRole: GroupMemberRole)
|
||||
case groupDeletedUser(user: UserRef, groupInfo: GroupInfo)
|
||||
case joinedGroupMemberConnecting(user: UserRef, groupInfo: GroupInfo, hostMember: GroupMember, member: GroupMember)
|
||||
case memberRole(user: UserRef, groupInfo: GroupInfo, byMember: GroupMember, member: GroupMember, fromRole: GroupMemberRole, toRole: GroupMemberRole)
|
||||
case memberRoleUser(user: UserRef, groupInfo: GroupInfo, member: GroupMember, fromRole: GroupMemberRole, toRole: GroupMemberRole)
|
||||
case membersRoleUser(user: UserRef, groupInfo: GroupInfo, members: [GroupMember], toRole: GroupMemberRole)
|
||||
case memberBlockedForAll(user: UserRef, groupInfo: GroupInfo, byMember: GroupMember, member: GroupMember, blocked: Bool)
|
||||
case memberBlockedForAllUser(user: UserRef, groupInfo: GroupInfo, member: GroupMember, blocked: Bool)
|
||||
case deletedMemberUser(user: UserRef, groupInfo: GroupInfo, member: GroupMember)
|
||||
case deletedMember(user: UserRef, groupInfo: GroupInfo, byMember: GroupMember, deletedMember: GroupMember)
|
||||
case membersBlockedForAllUser(user: UserRef, groupInfo: GroupInfo, members: [GroupMember], blocked: Bool)
|
||||
case deletedMemberUser(user: UserRef, groupInfo: GroupInfo, member: GroupMember, withMessages: Bool)
|
||||
case deletedMember(user: UserRef, groupInfo: GroupInfo, byMember: GroupMember, deletedMember: GroupMember, withMessages: Bool)
|
||||
case leftMember(user: UserRef, groupInfo: GroupInfo, member: GroupMember)
|
||||
case groupDeleted(user: UserRef, groupInfo: GroupInfo, member: GroupMember)
|
||||
case contactsMerged(user: UserRef, intoContact: Contact, mergedContact: Contact)
|
||||
|
@ -852,16 +861,16 @@ public enum ChatResponse: Decodable, Error {
|
|||
case .userAcceptedGroupSent: return "userAcceptedGroupSent"
|
||||
case .groupLinkConnecting: return "groupLinkConnecting"
|
||||
case .businessLinkConnecting: return "businessLinkConnecting"
|
||||
case .userDeletedMember: return "userDeletedMember"
|
||||
case .userDeletedMembers: return "userDeletedMembers"
|
||||
case .leftMemberUser: return "leftMemberUser"
|
||||
case .groupMembers: return "groupMembers"
|
||||
case .receivedGroupInvitation: return "receivedGroupInvitation"
|
||||
case .groupDeletedUser: return "groupDeletedUser"
|
||||
case .joinedGroupMemberConnecting: return "joinedGroupMemberConnecting"
|
||||
case .memberRole: return "memberRole"
|
||||
case .memberRoleUser: return "memberRoleUser"
|
||||
case .membersRoleUser: return "membersRoleUser"
|
||||
case .memberBlockedForAll: return "memberBlockedForAll"
|
||||
case .memberBlockedForAllUser: return "memberBlockedForAllUser"
|
||||
case .membersBlockedForAllUser: return "membersBlockedForAllUser"
|
||||
case .deletedMemberUser: return "deletedMemberUser"
|
||||
case .deletedMember: return "deletedMember"
|
||||
case .leftMember: return "leftMember"
|
||||
|
@ -949,7 +958,7 @@ public enum ChatResponse: Decodable, Error {
|
|||
case .chatStopped: return noDetails
|
||||
case .chatSuspended: return noDetails
|
||||
case let .apiChats(u, chats): return withUser(u, String(describing: chats))
|
||||
case let .apiChat(u, chat): return withUser(u, String(describing: chat))
|
||||
case let .apiChat(u, chat, navInfo): return withUser(u, "chat: \(String(describing: chat))\nnavInfo: \(String(describing: navInfo))")
|
||||
case let .chatTags(u, userTags): return withUser(u, "userTags: \(String(describing: userTags))")
|
||||
case let .chatItemInfo(u, chatItem, chatItemInfo): return withUser(u, "chatItem: \(String(describing: chatItem))\nchatItemInfo: \(String(describing: chatItemInfo))")
|
||||
case let .serverTestResult(u, server, testFailure): return withUser(u, "server: \(server)\nresult: \(String(describing: testFailure))")
|
||||
|
@ -1039,18 +1048,18 @@ public enum ChatResponse: Decodable, Error {
|
|||
case let .userAcceptedGroupSent(u, groupInfo, hostContact): return withUser(u, "groupInfo: \(groupInfo)\nhostContact: \(String(describing: hostContact))")
|
||||
case let .groupLinkConnecting(u, groupInfo, hostMember): return withUser(u, "groupInfo: \(groupInfo)\nhostMember: \(String(describing: hostMember))")
|
||||
case let .businessLinkConnecting(u, groupInfo, hostMember, fromContact): return withUser(u, "groupInfo: \(groupInfo)\nhostMember: \(String(describing: hostMember))\nfromContact: \(String(describing: fromContact))")
|
||||
case let .userDeletedMember(u, groupInfo, member): return withUser(u, "groupInfo: \(groupInfo)\nmember: \(member)")
|
||||
case let .userDeletedMembers(u, groupInfo, members, withMessages): return withUser(u, "groupInfo: \(groupInfo)\nmembers: \(members)\nwithMessages: \(withMessages)")
|
||||
case let .leftMemberUser(u, groupInfo): return withUser(u, String(describing: groupInfo))
|
||||
case let .groupMembers(u, group): return withUser(u, String(describing: group))
|
||||
case let .receivedGroupInvitation(u, groupInfo, contact, memberRole): return withUser(u, "groupInfo: \(groupInfo)\ncontact: \(contact)\nmemberRole: \(memberRole)")
|
||||
case let .groupDeletedUser(u, groupInfo): return withUser(u, String(describing: groupInfo))
|
||||
case let .joinedGroupMemberConnecting(u, groupInfo, hostMember, member): return withUser(u, "groupInfo: \(groupInfo)\nhostMember: \(hostMember)\nmember: \(member)")
|
||||
case let .memberRole(u, groupInfo, byMember, member, fromRole, toRole): return withUser(u, "groupInfo: \(groupInfo)\nbyMember: \(byMember)\nmember: \(member)\nfromRole: \(fromRole)\ntoRole: \(toRole)")
|
||||
case let .memberRoleUser(u, groupInfo, member, fromRole, toRole): return withUser(u, "groupInfo: \(groupInfo)\nmember: \(member)\nfromRole: \(fromRole)\ntoRole: \(toRole)")
|
||||
case let .membersRoleUser(u, groupInfo, members, toRole): return withUser(u, "groupInfo: \(groupInfo)\nmembers: \(members)\ntoRole: \(toRole)")
|
||||
case let .memberBlockedForAll(u, groupInfo, byMember, member, blocked): return withUser(u, "groupInfo: \(groupInfo)\nbyMember: \(byMember)\nmember: \(member)\nblocked: \(blocked)")
|
||||
case let .memberBlockedForAllUser(u, groupInfo, member, blocked): return withUser(u, "groupInfo: \(groupInfo)\nmember: \(member)\nblocked: \(blocked)")
|
||||
case let .deletedMemberUser(u, groupInfo, member): return withUser(u, "groupInfo: \(groupInfo)\nmember: \(member)")
|
||||
case let .deletedMember(u, groupInfo, byMember, deletedMember): return withUser(u, "groupInfo: \(groupInfo)\nbyMember: \(byMember)\ndeletedMember: \(deletedMember)")
|
||||
case let .membersBlockedForAllUser(u, groupInfo, members, blocked): return withUser(u, "groupInfo: \(groupInfo)\nmember: \(members)\nblocked: \(blocked)")
|
||||
case let .deletedMemberUser(u, groupInfo, member, withMessages): return withUser(u, "groupInfo: \(groupInfo)\nmember: \(member)\nwithMessages: \(withMessages)")
|
||||
case let .deletedMember(u, groupInfo, byMember, deletedMember, withMessages): return withUser(u, "groupInfo: \(groupInfo)\nbyMember: \(byMember)\ndeletedMember: \(deletedMember)\nwithMessages: \(withMessages)")
|
||||
case let .leftMember(u, groupInfo, member): return withUser(u, "groupInfo: \(groupInfo)\nmember: \(member)")
|
||||
case let .groupDeleted(u, groupInfo, member): return withUser(u, "groupInfo: \(groupInfo)\nmember: \(member)")
|
||||
case let .contactsMerged(u, intoContact, mergedContact): return withUser(u, "intoContact: \(intoContact)\nmergedContact: \(mergedContact)")
|
||||
|
@ -1200,10 +1209,15 @@ struct NewUser: Encodable {
|
|||
}
|
||||
|
||||
public enum ChatPagination {
|
||||
public static let INITIAL_COUNT = 75
|
||||
public static let PRELOAD_COUNT = 100
|
||||
public static let UNTIL_PRELOAD_COUNT = 50
|
||||
|
||||
case last(count: Int)
|
||||
case after(chatItemId: Int64, count: Int)
|
||||
case before(chatItemId: Int64, count: Int)
|
||||
case around(chatItemId: Int64, count: Int)
|
||||
case initial(count: Int)
|
||||
|
||||
var cmdString: String {
|
||||
switch self {
|
||||
|
@ -1211,6 +1225,7 @@ public enum ChatPagination {
|
|||
case let .after(chatItemId, count): return "after=\(chatItemId) count=\(count)"
|
||||
case let .before(chatItemId, count): return "before=\(chatItemId) count=\(count)"
|
||||
case let .around(chatItemId, count): return "around=\(chatItemId) count=\(count)"
|
||||
case let .initial(count): return "initial=\(count)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1218,7 +1233,7 @@ public enum ChatPagination {
|
|||
public struct ChatTagData: Encodable {
|
||||
public var emoji: String?
|
||||
public var text: String
|
||||
|
||||
|
||||
public init(emoji: String?, text: String) {
|
||||
self.emoji = emoji
|
||||
self.text = text
|
||||
|
@ -1474,7 +1489,7 @@ public struct UserOperatorServers: Identifiable, Equatable, Codable {
|
|||
}
|
||||
set { `operator` = newValue }
|
||||
}
|
||||
|
||||
|
||||
public static var sampleData1 = UserOperatorServers(
|
||||
operator: ServerOperator.sampleData1,
|
||||
smpServers: [UserServer.sampleData.preset],
|
||||
|
@ -1785,7 +1800,7 @@ public struct NetCfg: Codable, Equatable {
|
|||
rcvConcurrency: 8,
|
||||
smpPingInterval: 1200_000_000
|
||||
)
|
||||
|
||||
|
||||
public var withProxyTimeouts: NetCfg {
|
||||
var cfg = self
|
||||
cfg.tcpConnectTimeout = NetCfg.proxyDefaults.tcpConnectTimeout
|
||||
|
@ -1795,7 +1810,7 @@ public struct NetCfg: Codable, Equatable {
|
|||
cfg.smpPingInterval = NetCfg.proxyDefaults.smpPingInterval
|
||||
return cfg
|
||||
}
|
||||
|
||||
|
||||
public var hasProxyTimeouts: Bool {
|
||||
tcpConnectTimeout == NetCfg.proxyDefaults.tcpConnectTimeout &&
|
||||
tcpTimeout == NetCfg.proxyDefaults.tcpTimeout &&
|
||||
|
@ -1928,7 +1943,7 @@ public struct NetworkProxy: Equatable, Codable {
|
|||
public static var def: NetworkProxy {
|
||||
NetworkProxy()
|
||||
}
|
||||
|
||||
|
||||
public var valid: Bool {
|
||||
let hostOk = switch NWEndpoint.Host(host) {
|
||||
case .ipv4: true
|
||||
|
@ -1939,7 +1954,7 @@ public struct NetworkProxy: Equatable, Codable {
|
|||
port > 0 && port <= 65535 &&
|
||||
NetworkProxy.validCredential(username) && NetworkProxy.validCredential(password)
|
||||
}
|
||||
|
||||
|
||||
public static func validCredential(_ s: String) -> Bool {
|
||||
!s.contains(":") && !s.contains("@")
|
||||
}
|
||||
|
@ -2039,6 +2054,16 @@ public struct ChatSettings: Codable, Hashable {
|
|||
public static let defaults: ChatSettings = ChatSettings(enableNtfs: .all, sendRcpts: nil, favorite: false)
|
||||
}
|
||||
|
||||
public struct NavigationInfo: Decodable {
|
||||
public var afterUnread: Int = 0
|
||||
public var afterTotal: Int = 0
|
||||
|
||||
public init(afterUnread: Int = 0, afterTotal: Int = 0) {
|
||||
self.afterUnread = afterUnread
|
||||
self.afterTotal = afterTotal
|
||||
}
|
||||
}
|
||||
|
||||
public enum MsgFilter: String, Codable, Hashable {
|
||||
case none
|
||||
case all
|
||||
|
@ -2245,7 +2270,7 @@ public enum NotificationsMode: String, Decodable, SelectableItem {
|
|||
case .instant: "Instant"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public var icon: String {
|
||||
switch self {
|
||||
case .off: return "arrow.clockwise"
|
||||
|
@ -2760,7 +2785,7 @@ public struct AppSettings: Codable, Equatable {
|
|||
public var uiThemes: [ThemeOverrides]? = nil
|
||||
public var oneHandUI: Bool? = nil
|
||||
public var chatBottomBar: Bool? = nil
|
||||
|
||||
|
||||
public func prepareForExport() -> AppSettings {
|
||||
var empty = AppSettings()
|
||||
let def = AppSettings.defaults
|
||||
|
|
|
@ -711,6 +711,7 @@ public enum GroupFeature: String, Decodable, Feature, Hashable {
|
|||
case voice
|
||||
case files
|
||||
case simplexLinks
|
||||
case reports
|
||||
case history
|
||||
|
||||
public var id: Self { self }
|
||||
|
@ -731,6 +732,7 @@ public enum GroupFeature: String, Decodable, Feature, Hashable {
|
|||
case .voice: true
|
||||
case .files: true
|
||||
case .simplexLinks: true
|
||||
case .reports: false
|
||||
case .history: false
|
||||
}
|
||||
}
|
||||
|
@ -744,6 +746,7 @@ public enum GroupFeature: String, Decodable, Feature, Hashable {
|
|||
case .voice: return NSLocalizedString("Voice messages", comment: "chat feature")
|
||||
case .files: return NSLocalizedString("Files and media", comment: "chat feature")
|
||||
case .simplexLinks: return NSLocalizedString("SimpleX links", comment: "chat feature")
|
||||
case .reports: return NSLocalizedString("Member reports", comment: "chat feature")
|
||||
case .history: return NSLocalizedString("Visible history", comment: "chat feature")
|
||||
}
|
||||
}
|
||||
|
@ -757,6 +760,7 @@ public enum GroupFeature: String, Decodable, Feature, Hashable {
|
|||
case .voice: return "mic"
|
||||
case .files: return "doc"
|
||||
case .simplexLinks: return "link.circle"
|
||||
case .reports: return "flag"
|
||||
case .history: return "clock"
|
||||
}
|
||||
}
|
||||
|
@ -770,6 +774,7 @@ public enum GroupFeature: String, Decodable, Feature, Hashable {
|
|||
case .voice: return "mic.fill"
|
||||
case .files: return "doc.fill"
|
||||
case .simplexLinks: return "link.circle.fill"
|
||||
case .reports: return "flag.fill"
|
||||
case .history: return "clock.fill"
|
||||
}
|
||||
}
|
||||
|
@ -819,6 +824,11 @@ public enum GroupFeature: String, Decodable, Feature, Hashable {
|
|||
case .on: return "Allow to send SimpleX links."
|
||||
case .off: return "Prohibit sending SimpleX links."
|
||||
}
|
||||
case .reports:
|
||||
switch enabled {
|
||||
case .on: return "Allow to report messsages to moderators."
|
||||
case .off: return "Prohibit reporting messages to moderators."
|
||||
}
|
||||
case .history:
|
||||
switch enabled {
|
||||
case .on: return "Send up to 100 last messages to new members."
|
||||
|
@ -862,6 +872,11 @@ public enum GroupFeature: String, Decodable, Feature, Hashable {
|
|||
case .on: return "Members can send SimpleX links."
|
||||
case .off: return "SimpleX links are prohibited."
|
||||
}
|
||||
case .reports:
|
||||
switch enabled {
|
||||
case .on: return "Members can report messsages to moderators."
|
||||
case .off: return "Reporting messages to moderators is prohibited."
|
||||
}
|
||||
case .history:
|
||||
switch enabled {
|
||||
case .on: return "Up to 100 last messages are sent to new members."
|
||||
|
@ -1007,6 +1022,7 @@ public struct FullGroupPreferences: Decodable, Equatable, Hashable {
|
|||
public var voice: RoleGroupPreference
|
||||
public var files: RoleGroupPreference
|
||||
public var simplexLinks: RoleGroupPreference
|
||||
public var reports: GroupPreference
|
||||
public var history: GroupPreference
|
||||
|
||||
public init(
|
||||
|
@ -1017,6 +1033,7 @@ public struct FullGroupPreferences: Decodable, Equatable, Hashable {
|
|||
voice: RoleGroupPreference,
|
||||
files: RoleGroupPreference,
|
||||
simplexLinks: RoleGroupPreference,
|
||||
reports: GroupPreference,
|
||||
history: GroupPreference
|
||||
) {
|
||||
self.timedMessages = timedMessages
|
||||
|
@ -1026,6 +1043,7 @@ public struct FullGroupPreferences: Decodable, Equatable, Hashable {
|
|||
self.voice = voice
|
||||
self.files = files
|
||||
self.simplexLinks = simplexLinks
|
||||
self.reports = reports
|
||||
self.history = history
|
||||
}
|
||||
|
||||
|
@ -1037,6 +1055,7 @@ public struct FullGroupPreferences: Decodable, Equatable, Hashable {
|
|||
voice: RoleGroupPreference(enable: .on, role: nil),
|
||||
files: RoleGroupPreference(enable: .on, role: nil),
|
||||
simplexLinks: RoleGroupPreference(enable: .on, role: nil),
|
||||
reports: GroupPreference(enable: .on),
|
||||
history: GroupPreference(enable: .on)
|
||||
)
|
||||
}
|
||||
|
@ -1049,6 +1068,7 @@ public struct GroupPreferences: Codable, Hashable {
|
|||
public var voice: RoleGroupPreference?
|
||||
public var files: RoleGroupPreference?
|
||||
public var simplexLinks: RoleGroupPreference?
|
||||
public var reports: GroupPreference?
|
||||
public var history: GroupPreference?
|
||||
|
||||
public init(
|
||||
|
@ -1059,6 +1079,7 @@ public struct GroupPreferences: Codable, Hashable {
|
|||
voice: RoleGroupPreference? = nil,
|
||||
files: RoleGroupPreference? = nil,
|
||||
simplexLinks: RoleGroupPreference? = nil,
|
||||
reports: GroupPreference? = nil,
|
||||
history: GroupPreference? = nil
|
||||
) {
|
||||
self.timedMessages = timedMessages
|
||||
|
@ -1068,6 +1089,7 @@ public struct GroupPreferences: Codable, Hashable {
|
|||
self.voice = voice
|
||||
self.files = files
|
||||
self.simplexLinks = simplexLinks
|
||||
self.reports = reports
|
||||
self.history = history
|
||||
}
|
||||
|
||||
|
@ -1079,6 +1101,7 @@ public struct GroupPreferences: Codable, Hashable {
|
|||
voice: RoleGroupPreference(enable: .on, role: nil),
|
||||
files: RoleGroupPreference(enable: .on, role: nil),
|
||||
simplexLinks: RoleGroupPreference(enable: .on, role: nil),
|
||||
reports: GroupPreference(enable: .on),
|
||||
history: GroupPreference(enable: .on)
|
||||
)
|
||||
}
|
||||
|
@ -1092,6 +1115,7 @@ public func toGroupPreferences(_ fullPreferences: FullGroupPreferences) -> Group
|
|||
voice: fullPreferences.voice,
|
||||
files: fullPreferences.files,
|
||||
simplexLinks: fullPreferences.simplexLinks,
|
||||
reports: fullPreferences.reports,
|
||||
history: fullPreferences.history
|
||||
)
|
||||
}
|
||||
|
@ -1588,6 +1612,7 @@ public struct ChatStats: Decodable, Hashable {
|
|||
// actual only via getChats() and getChat(.initial), otherwise, zero
|
||||
public var reportsCount: Int = 0
|
||||
public var minUnreadItemId: Int64 = 0
|
||||
// actual only via getChats(), otherwise, false
|
||||
public var unreadChat: Bool = false
|
||||
}
|
||||
|
||||
|
@ -2116,11 +2141,13 @@ public struct GroupMember: Identifiable, Decodable, Hashable {
|
|||
|
||||
public var memberActive: Bool {
|
||||
switch memberStatus {
|
||||
case .memRejected: return false
|
||||
case .memRemoved: return false
|
||||
case .memLeft: return false
|
||||
case .memGroupDeleted: return false
|
||||
case .memUnknown: return false
|
||||
case .memInvited: return false
|
||||
case .memPendingApproval: return true
|
||||
case .memIntroduced: return false
|
||||
case .memIntroInvited: return false
|
||||
case .memAccepted: return false
|
||||
|
@ -2133,11 +2160,13 @@ public struct GroupMember: Identifiable, Decodable, Hashable {
|
|||
|
||||
public var memberCurrent: Bool {
|
||||
switch memberStatus {
|
||||
case .memRejected: return false
|
||||
case .memRemoved: return false
|
||||
case .memLeft: return false
|
||||
case .memGroupDeleted: return false
|
||||
case .memUnknown: return false
|
||||
case .memInvited: return false
|
||||
case .memPendingApproval: return false
|
||||
case .memIntroduced: return true
|
||||
case .memIntroInvited: return true
|
||||
case .memAccepted: return true
|
||||
|
@ -2263,11 +2292,13 @@ public enum GroupMemberCategory: String, Decodable, Hashable {
|
|||
}
|
||||
|
||||
public enum GroupMemberStatus: String, Decodable, Hashable {
|
||||
case memRejected = "rejected"
|
||||
case memRemoved = "removed"
|
||||
case memLeft = "left"
|
||||
case memGroupDeleted = "deleted"
|
||||
case memUnknown = "unknown"
|
||||
case memInvited = "invited"
|
||||
case memPendingApproval = "pending_approval"
|
||||
case memIntroduced = "introduced"
|
||||
case memIntroInvited = "intro-inv"
|
||||
case memAccepted = "accepted"
|
||||
|
@ -2278,11 +2309,13 @@ public enum GroupMemberStatus: String, Decodable, Hashable {
|
|||
|
||||
public var text: LocalizedStringKey {
|
||||
switch self {
|
||||
case .memRejected: return "rejected"
|
||||
case .memRemoved: return "removed"
|
||||
case .memLeft: return "left"
|
||||
case .memGroupDeleted: return "group deleted"
|
||||
case .memUnknown: return "unknown status"
|
||||
case .memInvited: return "invited"
|
||||
case .memPendingApproval: return "pending approval"
|
||||
case .memIntroduced: return "connecting (introduced)"
|
||||
case .memIntroInvited: return "connecting (introduction invitation)"
|
||||
case .memAccepted: return "connecting (accepted)"
|
||||
|
@ -2295,11 +2328,13 @@ public enum GroupMemberStatus: String, Decodable, Hashable {
|
|||
|
||||
public var shortText: LocalizedStringKey {
|
||||
switch self {
|
||||
case .memRejected: return "rejected"
|
||||
case .memRemoved: return "removed"
|
||||
case .memLeft: return "left"
|
||||
case .memGroupDeleted: return "group deleted"
|
||||
case .memUnknown: return "unknown"
|
||||
case .memInvited: return "invited"
|
||||
case .memPendingApproval: return "pending"
|
||||
case .memIntroduced: return "connecting"
|
||||
case .memIntroInvited: return "connecting"
|
||||
case .memAccepted: return "connecting"
|
||||
|
@ -2411,13 +2446,6 @@ public struct ChatItemDeletion: Decodable, Hashable {
|
|||
public struct AChatItem: Decodable, Hashable {
|
||||
public var chatInfo: ChatInfo
|
||||
public var chatItem: ChatItem
|
||||
|
||||
public var chatId: String {
|
||||
if case let .groupRcv(groupMember) = chatItem.chatDir {
|
||||
return groupMember.id
|
||||
}
|
||||
return chatInfo.id
|
||||
}
|
||||
}
|
||||
|
||||
public struct CIMentionMember: Decodable, Hashable {
|
||||
|
@ -3238,6 +3266,20 @@ public enum CIForwardedFrom: Decodable, Hashable {
|
|||
}
|
||||
}
|
||||
|
||||
public var chatTypeApiIdMsgId: (ChatType, Int64, ChatItem.ID?)? {
|
||||
switch self {
|
||||
case .unknown: nil
|
||||
case let .contact(_, _, contactId, msgId):
|
||||
if let contactId {
|
||||
(ChatType.direct, contactId, msgId)
|
||||
} else { nil }
|
||||
case let .group(_, _, groupId, msgId):
|
||||
if let groupId {
|
||||
(ChatType.group, groupId, msgId)
|
||||
} else { nil }
|
||||
}
|
||||
}
|
||||
|
||||
public func text(_ chatType: ChatType) -> LocalizedStringKey {
|
||||
chatType == .local
|
||||
? (chatName == "" ? "saved" : "saved from \(chatName)")
|
||||
|
@ -3506,8 +3548,12 @@ extension MsgReaction: Decodable {
|
|||
let type = try container.decode(String.self, forKey: CodingKeys.type)
|
||||
switch type {
|
||||
case "emoji":
|
||||
let emoji = try container.decode(MREmojiChar.self, forKey: CodingKeys.emoji)
|
||||
self = .emoji(emoji: emoji)
|
||||
do {
|
||||
let emoji = try container.decode(MREmojiChar.self, forKey: CodingKeys.emoji)
|
||||
self = .emoji(emoji: emoji)
|
||||
} catch {
|
||||
self = .unknown(type: "emoji")
|
||||
}
|
||||
default:
|
||||
self = .unknown(type: type)
|
||||
}
|
||||
|
@ -3781,7 +3827,7 @@ public enum FileError: Decodable, Equatable, Hashable {
|
|||
public var errorInfo: String {
|
||||
switch self {
|
||||
case .auth: NSLocalizedString("Wrong key or unknown file chunk address - most likely file is deleted.", comment: "file error text")
|
||||
case let .blocked(_, info): NSLocalizedString("File is blocked by server operator:\n\(info.reason.text).", comment: "file error text")
|
||||
case let .blocked(_, info): String.localizedStringWithFormat(NSLocalizedString("File is blocked by server operator:\n%@.", comment: "file error text"), info.reason.text)
|
||||
case .noFile: NSLocalizedString("File not found - most likely file was deleted or cancelled.", comment: "file error text")
|
||||
case let .relay(srvError): String.localizedStringWithFormat(NSLocalizedString("File server error: %@", comment: "file error text"), srvError.errorInfo)
|
||||
case let .other(fileError): String.localizedStringWithFormat(NSLocalizedString("Error: %@", comment: "file error text"), fileError)
|
||||
|
@ -4124,9 +4170,61 @@ public enum NtfTknStatus: String, Decodable, Hashable {
|
|||
case new = "NEW"
|
||||
case registered = "REGISTERED"
|
||||
case invalid = "INVALID"
|
||||
case invalidBad = "INVALID,BAD"
|
||||
case invalidTopic = "INVALID,TOPIC"
|
||||
case invalidExpired = "INVALID,EXPIRED"
|
||||
case invalidUnregistered = "INVALID,UNREGISTERED"
|
||||
case confirmed = "CONFIRMED"
|
||||
case active = "ACTIVE"
|
||||
case expired = "EXPIRED"
|
||||
|
||||
public var workingToken: Bool {
|
||||
switch self {
|
||||
case .new: true
|
||||
case .registered: true
|
||||
case .invalid: false
|
||||
case .invalidBad: false
|
||||
case .invalidTopic: false
|
||||
case .invalidExpired: false
|
||||
case .invalidUnregistered: false
|
||||
case .confirmed: true
|
||||
case .active: true
|
||||
case .expired: false
|
||||
}
|
||||
}
|
||||
|
||||
public var text: String {
|
||||
switch self {
|
||||
case .new: NSLocalizedString("New", comment: "token status text")
|
||||
case .registered: NSLocalizedString("Registered", comment: "token status text")
|
||||
case .invalid: NSLocalizedString("Invalid", comment: "token status text")
|
||||
case .invalidBad: NSLocalizedString("Invalid (bad token)", comment: "token status text")
|
||||
case .invalidTopic: NSLocalizedString("Invalid (wrong topic)", comment: "token status text")
|
||||
case .invalidExpired: NSLocalizedString("Invalid (expired)", comment: "token status text")
|
||||
case .invalidUnregistered: NSLocalizedString("Invalid (unregistered)", comment: "token status text")
|
||||
case .confirmed: NSLocalizedString("Confirmed", comment: "token status text")
|
||||
case .active: NSLocalizedString("Active", comment: "token status text")
|
||||
case .expired: NSLocalizedString("Expired", comment: "token status text")
|
||||
}
|
||||
}
|
||||
|
||||
public func info(register: Bool) -> String {
|
||||
switch self {
|
||||
case .new: return NSLocalizedString("Please wait for token to be registered.", comment: "token info")
|
||||
case .registered: fallthrough
|
||||
case .confirmed: return NSLocalizedString("Please wait for token activation to complete.", comment: "token info")
|
||||
case .active: return NSLocalizedString("You should receive notifications.", comment: "token info")
|
||||
case .invalid: fallthrough
|
||||
case .invalidBad: fallthrough
|
||||
case .invalidTopic: fallthrough
|
||||
case .invalidExpired: fallthrough
|
||||
case .invalidUnregistered: fallthrough
|
||||
case .expired:
|
||||
return register
|
||||
? NSLocalizedString("Register notification token?", comment: "token info")
|
||||
: NSLocalizedString("Please try to disable and re-enable notfications.", comment: "token info")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public struct SndFileTransfer: Decodable, Hashable {
|
||||
|
|
|
@ -27,6 +27,7 @@ extension ChatLike {
|
|||
case .files: p.files.on(for: groupInfo.membership)
|
||||
case .simplexLinks: p.simplexLinks.on(for: groupInfo.membership)
|
||||
case .history: p.history.on
|
||||
case .reports: p.reports.on
|
||||
}
|
||||
} else {
|
||||
return true
|
||||
|
|
|
@ -203,6 +203,11 @@ func hideSecrets(_ cItem: ChatItem) -> String {
|
|||
}
|
||||
return res
|
||||
} else {
|
||||
return cItem.text
|
||||
let mc = cItem.content.msgContent
|
||||
if case let .report(text, reason) = mc {
|
||||
return String.localizedStringWithFormat(NSLocalizedString("Report: %@", comment: "report in notification"), text.isEmpty ? reason.text : text)
|
||||
} else {
|
||||
return cItem.text
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,4 +21,13 @@ DIR *opendir$INODE64(const char *name) {
|
|||
return opendir(name);
|
||||
}
|
||||
|
||||
int readdir$INODE64(DIR *restrict dirp, struct dirent *restrict entry,
|
||||
struct dirent **restrict result) {
|
||||
return readdir_r(dirp, entry, result);
|
||||
}
|
||||
|
||||
DIR *fdopendir$INODE64(const char *name) {
|
||||
return opendir(name);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,9 +1,3 @@
|
|||
/* No comment provided by engineer. */
|
||||
"\n" = "\n";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
" (" = " (";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
" (can be copied)" = " (може да се копира)";
|
||||
|
||||
|
@ -22,30 +16,15 @@
|
|||
/* No comment provided by engineer. */
|
||||
"- voice messages up to 5 minutes.\n- custom time to disappear.\n- editing history." = "- гласови съобщения до 5 минути.\n- персонализирано време за изчезване.\n- история на редактиране.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
", " = ", ";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
": " = ": ";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"!1 colored!" = "!1 цветно!";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"." = ".";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"(" = "(";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"(new)" = "(ново)";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"(this device v%@)" = "(това устройство v%@)";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
")" = ")";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"[Contribute](https://github.com/simplex-chat/simplex-chat#contribute)" = "[Допринеси](https://github.com/simplex-chat/simplex-chat#contribute)";
|
||||
|
||||
|
@ -1135,16 +1114,19 @@
|
|||
"Correct name to %@?" = "Поправи име на %@?";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Create" = "Създай";
|
||||
"Create" = "Създаване";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Create a group using a random profile." = "Създай група с автоматично генериран профилл.";
|
||||
"Create 1-time link" = "Създаване на еднократна препратка";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Create a group using a random profile." = "Създаване група с автоматично създаден профил.";
|
||||
|
||||
/* server test step */
|
||||
"Create file" = "Създай файл";
|
||||
"Create file" = "Създаване на файл";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Create group" = "Създай група";
|
||||
"Create group" = "Създаване на група";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Create group link" = "Създай групов линк";
|
||||
|
@ -1165,7 +1147,7 @@
|
|||
"Create secret group" = "Създай тайна група";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Create SimpleX address" = "Създай SimpleX адрес";
|
||||
"Create SimpleX address" = "Създаване на адрес в SimpleX";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Create your profile" = "Създай своя профил";
|
||||
|
@ -2637,7 +2619,7 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Multiple chat profiles" = "Множество профили за чат";
|
||||
|
||||
/* swipe action */
|
||||
/* notification label action */
|
||||
"Mute" = "Без звук";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
|
@ -3980,7 +3962,7 @@
|
|||
/* authentication reason */
|
||||
"Unlock app" = "Отключи приложението";
|
||||
|
||||
/* swipe action */
|
||||
/* notification label action */
|
||||
"Unmute" = "Уведомявай";
|
||||
|
||||
/* swipe action */
|
||||
|
@ -4479,7 +4461,7 @@
|
|||
"Your settings" = "Вашите настройки";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Your SimpleX address" = "Вашият SimpleX адрес";
|
||||
"Your SimpleX address" = "Вашият адрес в SimpleX";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Your SMP servers" = "Вашите SMP сървъри";
|
||||
|
|
|
@ -1,9 +1,3 @@
|
|||
/* No comment provided by engineer. */
|
||||
"\n" = "\n";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
" (" = " (";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
" (can be copied)" = " (lze kopírovat)";
|
||||
|
||||
|
@ -19,27 +13,12 @@
|
|||
/* No comment provided by engineer. */
|
||||
"- voice messages up to 5 minutes.\n- custom time to disappear.\n- editing history." = "- 5 minutové hlasové zprávy.\n- vlastní čas mizení.\n- historie úprav.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
", " = ", ";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
": " = ": ";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"!1 colored!" = "!1 barevný!";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"." = ".";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"(" = "(";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"(this device v%@)" = "(toto zařízení v%@)";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
")" = ")";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"[Contribute](https://github.com/simplex-chat/simplex-chat#contribute)" = "[Přispějte](https://github.com/simplex-chat/simplex-chat#contribute)";
|
||||
|
||||
|
@ -2036,7 +2015,7 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Multiple chat profiles" = "Více chatovacích profilů";
|
||||
|
||||
/* swipe action */
|
||||
/* notification label action */
|
||||
"Mute" = "Ztlumit";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
|
@ -3124,7 +3103,7 @@
|
|||
/* authentication reason */
|
||||
"Unlock app" = "Odemknout aplikaci";
|
||||
|
||||
/* swipe action */
|
||||
/* notification label action */
|
||||
"Unmute" = "Zrušit ztlumení";
|
||||
|
||||
/* swipe action */
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,9 +1,3 @@
|
|||
/* No comment provided by engineer. */
|
||||
"\n" = "\n";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
" (" = " (";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
" (can be copied)" = " (voidaan kopioida)";
|
||||
|
||||
|
@ -16,24 +10,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"- voice messages up to 5 minutes.\n- custom time to disappear.\n- editing history." = "- ääniviestit enintään 5 minuuttia.\n- mukautettu katoamisaika.\n- historian muokkaaminen.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
", " = ", ";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
": " = ": ";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"!1 colored!" = "!1 värillinen!";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"." = ".";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"(" = "(";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
")" = ")";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"[Contribute](https://github.com/simplex-chat/simplex-chat#contribute)" = "[Osallistu](https://github.com/simplex-chat/simplex-chat#contribute)";
|
||||
|
||||
|
@ -1988,7 +1967,7 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Multiple chat profiles" = "Useita keskusteluprofiileja";
|
||||
|
||||
/* swipe action */
|
||||
/* notification label action */
|
||||
"Mute" = "Mykistä";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
|
@ -3058,7 +3037,7 @@
|
|||
/* authentication reason */
|
||||
"Unlock app" = "Avaa sovellus";
|
||||
|
||||
/* swipe action */
|
||||
/* notification label action */
|
||||
"Unmute" = "Poista mykistys";
|
||||
|
||||
/* swipe action */
|
||||
|
|
|
@ -1,9 +1,3 @@
|
|||
/* No comment provided by engineer. */
|
||||
"\n" = "\n";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
" (" = " (";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
" (can be copied)" = " (peut être copié)";
|
||||
|
||||
|
@ -22,30 +16,15 @@
|
|||
/* No comment provided by engineer. */
|
||||
"- voice messages up to 5 minutes.\n- custom time to disappear.\n- editing history." = "- messages vocaux pouvant durer jusqu'à 5 minutes.\n- délai personnalisé de disparition.\n- l'historique de modification.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
", " = ", ";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
": " = ": ";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"!1 colored!" = "!1 coloré!";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"." = ".";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"(" = "(";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"(new)" = "(nouveau)";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"(this device v%@)" = "(cet appareil v%@)";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
")" = ")";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"[Contribute](https://github.com/simplex-chat/simplex-chat#contribute)" = "[Contribuer](https://github.com/simplex-chat/simplex-chat#contribute)";
|
||||
|
||||
|
@ -3156,10 +3135,7 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Multiple chat profiles" = "Différents profils de chat";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"mute" = "muet";
|
||||
|
||||
/* swipe action */
|
||||
/* notification label action */
|
||||
"Mute" = "Muet";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
|
@ -5015,10 +4991,7 @@
|
|||
/* authentication reason */
|
||||
"Unlock app" = "Déverrouiller l'app";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"unmute" = "démuter";
|
||||
|
||||
/* swipe action */
|
||||
/* notification label action */
|
||||
"Unmute" = "Démute";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -8,7 +8,7 @@
|
|||
"NSFaceIDUsageDescription" = "A SimpleX Face ID-t használ a helyi hitelesítéshez";
|
||||
|
||||
/* Privacy - Local Network Usage Description */
|
||||
"NSLocalNetworkUsageDescription" = "A SimpleX helyi hálózati hozzáférést használ, hogy lehetővé tegye a felhasználói csevegőprofil használatát számítógépen keresztül ugyanazon a hálózaton.";
|
||||
"NSLocalNetworkUsageDescription" = "A SimpleX helyi hálózati hozzáférést használ, hogy lehetővé tegye a felhasználói csevegési profil használatát számítógépen keresztül ugyanazon a hálózaton.";
|
||||
|
||||
/* Privacy - Microphone Usage Description */
|
||||
"NSMicrophoneUsageDescription" = "A SimpleXnek mikrofon-hozzáférésre van szüksége hang- és videohívásokhoz, valamint hangüzenetek rögzítéséhez.";
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,9 +1,3 @@
|
|||
/* No comment provided by engineer. */
|
||||
"\n" = "\n";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
" (" = " (";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
" (can be copied)" = " (コピー可能)";
|
||||
|
||||
|
@ -22,30 +16,15 @@
|
|||
/* No comment provided by engineer. */
|
||||
"- voice messages up to 5 minutes.\n- custom time to disappear.\n- editing history." = "- 最長 5 分間の音声メッセージ。\n- 消えるまでのカスタム時間。\n- 編集履歴。";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
", " = ", ";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
": " = ": ";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"!1 colored!" = "!1 色付き!";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"." = ".";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"(" = "(";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"(new)" = "(新規)";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"(this device v%@)" = "(このデバイス v%@)";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
")" = ")";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"[Contribute](https://github.com/simplex-chat/simplex-chat#contribute)" = "[貢献する](https://github.com/simplex-chat/simplex-chat#contribute)";
|
||||
|
||||
|
@ -2201,7 +2180,7 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Multiple chat profiles" = "複数チャットのプロフィール";
|
||||
|
||||
/* swipe action */
|
||||
/* notification label action */
|
||||
"Mute" = "ミュート";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
|
@ -3256,7 +3235,7 @@
|
|||
/* authentication reason */
|
||||
"Unlock app" = "アプリのロック解除";
|
||||
|
||||
/* swipe action */
|
||||
/* notification label action */
|
||||
"Unmute" = "ミュート解除";
|
||||
|
||||
/* swipe action */
|
||||
|
|
|
@ -1,9 +1,3 @@
|
|||
/* No comment provided by engineer. */
|
||||
"\n" = "\n";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
" (" = " (";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
" (can be copied)" = " (kan gekopieerd worden)";
|
||||
|
||||
|
@ -22,30 +16,15 @@
|
|||
/* No comment provided by engineer. */
|
||||
"- voice messages up to 5 minutes.\n- custom time to disappear.\n- editing history." = "- spraakberichten tot 5 minuten.\n- aangepaste tijd om te verdwijnen.\n- bewerkingsgeschiedenis.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
", " = ", ";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
": " = ": ";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"!1 colored!" = "!1 gekleurd!";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"." = ".";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"(" = "(";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"(new)" = "(nieuw)";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"(this device v%@)" = "(dit apparaat v%@)";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
")" = ")";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"[Contribute](https://github.com/simplex-chat/simplex-chat#contribute)" = "[Bijdragen](https://github.com/simplex-chat/simplex-chat#contribute)";
|
||||
|
||||
|
@ -199,6 +178,9 @@
|
|||
/* time interval */
|
||||
"%d sec" = "%d sec";
|
||||
|
||||
/* delete after time */
|
||||
"%d seconds(s)" = "%d seconden";
|
||||
|
||||
/* integrity error chat item */
|
||||
"%d skipped message(s)" = "%d overgeslagen bericht(en)";
|
||||
|
||||
|
@ -304,6 +286,9 @@
|
|||
time interval */
|
||||
"1 week" = "1 week";
|
||||
|
||||
/* delete after time */
|
||||
"1 year" = "1 jaar";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"1-time link" = "Eenmalige link";
|
||||
|
||||
|
@ -388,6 +373,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Acknowledgement errors" = "Bevestigingsfouten";
|
||||
|
||||
/* token status text */
|
||||
"Active" = "actief";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Active connections" = "Actieve verbindingen";
|
||||
|
||||
|
@ -397,6 +385,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Add friends" = "Vrienden toevoegen";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Add list" = "Lijst toevoegen";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Add profile" = "Profiel toevoegen";
|
||||
|
||||
|
@ -412,6 +403,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Add to another device" = "Toevoegen aan een ander apparaat";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Add to list" = "Toevoegen aan lijst";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Add welcome message" = "Welkom bericht toevoegen";
|
||||
|
||||
|
@ -469,12 +463,18 @@
|
|||
/* chat item text */
|
||||
"agreeing encryption…" = "versleuteling overeenkomen…";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"All" = "alle";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"All app data is deleted." = "Alle app-gegevens worden verwijderd.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"All chats and messages will be deleted - this cannot be undone!" = "Alle chats en berichten worden verwijderd, dit kan niet ongedaan worden gemaakt!";
|
||||
|
||||
/* alert message */
|
||||
"All chats will be removed from the list %@, and the list deleted." = "Alle chats worden uit de lijst %@ verwijderd en de lijst wordt verwijderd.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"All data is erased when it is entered." = "Alle gegevens worden bij het invoeren gewist.";
|
||||
|
||||
|
@ -502,6 +502,9 @@
|
|||
/* profile dropdown */
|
||||
"All profiles" = "Alle profielen";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"All reports will be archived for you." = "Alle rapporten worden voor u gearchiveerd.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"All your contacts will remain connected." = "Al uw contacten blijven verbonden.";
|
||||
|
||||
|
@ -547,6 +550,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Allow to irreversibly delete sent messages. (24 hours)" = "Sta toe om verzonden berichten definitief te verwijderen. (24 uur)";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Allow to report messsages to moderators." = "Hiermee kunt u berichten rapporteren aan moderators.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Allow to send files and media." = "Sta toe om bestanden en media te verzenden.";
|
||||
|
||||
|
@ -601,6 +607,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"and %lld other events" = "en %lld andere gebeurtenissen";
|
||||
|
||||
/* report reason */
|
||||
"Another reason" = "Een andere reden";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Answer call" = "Beantwoord oproep";
|
||||
|
||||
|
@ -616,6 +625,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"App encrypts new local files (except videos)." = "App versleutelt nieuwe lokale bestanden (behalve video's).";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"App group:" = "App-groep:";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"App icon" = "App icon";
|
||||
|
||||
|
@ -643,18 +655,42 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Apply to" = "Toepassen op";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Archive" = "Archief";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Archive %lld reports?" = "%lld rapporten archiveren?";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Archive all reports?" = "Alle rapporten archiveren?";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Archive and upload" = "Archiveren en uploaden";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Archive contacts to chat later." = "Archiveer contacten om later te chatten.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Archive report" = "Rapport archiveren";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Archive report?" = "Rapport archiveren?";
|
||||
|
||||
/* swipe action */
|
||||
"Archive reports" = "Rapporten archiveren";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Archived contacts" = "Gearchiveerde contacten";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"archived report" = "gearchiveerd rapport";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Archiving database" = "Database archiveren";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Ask" = "Vragen";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Attach" = "Bijvoegen";
|
||||
|
||||
|
@ -730,6 +766,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Better groups" = "Betere groepen";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Better groups performance" = "Betere prestaties van groepen";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Better message dates." = "Betere datums voor berichten.";
|
||||
|
||||
|
@ -742,6 +781,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Better notifications" = "Betere meldingen";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Better privacy and security" = "Betere privacy en veiligheid";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Better security ✅" = "Betere beveiliging ✅";
|
||||
|
||||
|
@ -814,6 +856,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Business chats" = "Zakelijke chats";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Businesses" = "bedrijven";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"By chat profile (default) or [by connection](https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation) (BETA)." = "Via chatprofiel (standaard) of [via verbinding](https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation) (BETA).";
|
||||
|
||||
|
@ -884,6 +929,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Change" = "Veranderen";
|
||||
|
||||
/* alert title */
|
||||
"Change automatic message deletion?" = "Automatisch verwijderen van berichten wijzigen?";
|
||||
|
||||
/* authentication reason */
|
||||
"Change chat profiles" = "Gebruikersprofielen wijzigen";
|
||||
|
||||
|
@ -1032,6 +1080,12 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Clear conversation?" = "Gesprek wissen?";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Clear group?" = "Groep wissen?";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Clear or delete group?" = "Groep wissen of verwijderen?";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Clear private notes?" = "Privénotities verwijderen?";
|
||||
|
||||
|
@ -1047,6 +1101,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"colored" = "gekleurd";
|
||||
|
||||
/* report reason */
|
||||
"Community guidelines violation" = "Schending van de communityrichtlijnen";
|
||||
|
||||
/* server test step */
|
||||
"Compare file" = "Bestand vergelijken";
|
||||
|
||||
|
@ -1119,6 +1176,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Confirm upload" = "Bevestig het uploaden";
|
||||
|
||||
/* token status text */
|
||||
"Confirmed" = "Bevestigd";
|
||||
|
||||
/* server test step */
|
||||
"Connect" = "Verbind";
|
||||
|
||||
|
@ -1218,6 +1278,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Connection and servers status." = "Verbindings- en serverstatus.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Connection blocked" = "Verbinding geblokkeerd";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Connection error" = "Verbindingsfout";
|
||||
|
||||
|
@ -1227,12 +1290,21 @@
|
|||
/* chat list item title (it should not be shown */
|
||||
"connection established" = "verbinding gemaakt";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Connection is blocked by server operator:\n%@" = "Verbinding is geblokkeerd door serveroperator:\n%@";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Connection not ready." = "Verbinding nog niet klaar.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Connection notifications" = "Verbindingsmeldingen";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Connection request sent!" = "Verbindingsverzoek verzonden!";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Connection requires encryption renegotiation." = "Verbinding vereist heronderhandeling over encryptie.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Connection security" = "Beveiliging van de verbinding";
|
||||
|
||||
|
@ -1293,6 +1365,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Contacts can mark messages for deletion; you will be able to view them." = "Contact personen kunnen berichten markeren voor verwijdering; u kunt ze wel bekijken.";
|
||||
|
||||
/* blocking reason */
|
||||
"Content violates conditions of use" = "Inhoud schendt de gebruiksvoorwaarden";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Continue" = "Doorgaan";
|
||||
|
||||
|
@ -1335,6 +1410,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Create link" = "Maak link";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Create list" = "Maak een lijst";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Create new profile in [desktop app](https://simplex.chat/downloads/). 💻" = "Maak een nieuw profiel aan in [desktop-app](https://simplex.chat/downloads/). 💻";
|
||||
|
||||
|
@ -1514,6 +1592,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Delete chat" = "Chat verwijderen";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Delete chat messages from your device." = "Verwijder chatberichten van uw apparaat.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Delete chat profile" = "Chatprofiel verwijderen";
|
||||
|
||||
|
@ -1568,6 +1649,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Delete link?" = "Link verwijderen?";
|
||||
|
||||
/* alert title */
|
||||
"Delete list?" = "Lijst verwijderen?";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Delete member message?" = "Bericht van lid verwijderen?";
|
||||
|
||||
|
@ -1598,6 +1682,9 @@
|
|||
/* server test step */
|
||||
"Delete queue" = "Wachtrij verwijderen";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Delete report" = "Rapport verwijderen";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Delete up to 20 messages at once." = "Verwijder maximaal 20 berichten tegelijk.";
|
||||
|
||||
|
@ -1706,6 +1793,12 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Disable (keep overrides)" = "Uitschakelen (overschrijvingen behouden)";
|
||||
|
||||
/* alert title */
|
||||
"Disable automatic message deletion?" = "Automatisch verwijderen van berichten uitschakelen?";
|
||||
|
||||
/* alert button */
|
||||
"Disable delete messages" = "Berichten verwijderen uitschakelen";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Disable for all" = "Uitschakelen voor iedereen";
|
||||
|
||||
|
@ -1766,15 +1859,24 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Do NOT use SimpleX for emergency calls." = "Gebruik SimpleX NIET voor noodoproepen.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Documents:" = "Documenten:";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Don't create address" = "Maak geen adres aan";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Don't enable" = "Niet inschakelen";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Don't miss important messages." = "‐Mis geen belangrijke berichten.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Don't show again" = "Niet meer weergeven";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Done" = "Klaar";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Downgrade and open chat" = "Downgraden en chat openen";
|
||||
|
||||
|
@ -1956,6 +2058,9 @@
|
|||
/* chat item text */
|
||||
"encryption re-negotiation required for %@" = "heronderhandeling van versleuteling vereist voor % @";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Encryption renegotiation in progress." = "Er wordt opnieuw onderhandeld over de encryptie.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"ended" = "geëindigd";
|
||||
|
||||
|
@ -2031,6 +2136,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Error changing to incognito!" = "Fout bij het overschakelen naar incognito!";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Error checking token status" = "Fout bij het controleren van de tokenstatus";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Error connecting to forwarding server %@. Please try later." = "Fout bij het verbinden met doorstuurserver %@. Probeer het later opnieuw.";
|
||||
|
||||
|
@ -2043,6 +2151,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Error creating group link" = "Fout bij maken van groep link";
|
||||
|
||||
/* alert title */
|
||||
"Error creating list" = "Fout bij het aanmaken van de lijst";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Error creating member contact" = "Fout bij aanmaken contact";
|
||||
|
||||
|
@ -2052,6 +2163,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Error creating profile!" = "Fout bij aanmaken van profiel!";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Error creating report" = "Fout bij maken van rapport";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Error decrypting file" = "Fout bij het ontsleutelen van bestand";
|
||||
|
||||
|
@ -2118,12 +2232,21 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Error reconnecting servers" = "Fout bij opnieuw verbinden van servers";
|
||||
|
||||
/* alert title */
|
||||
"Error registering for notifications" = "Fout bij registreren voor meldingen";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Error removing member" = "Fout bij verwijderen van lid";
|
||||
|
||||
/* alert title */
|
||||
"Error reordering lists" = "Fout bij het opnieuw ordenen van lijsten";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Error resetting statistics" = "Fout bij het resetten van statistieken";
|
||||
|
||||
/* alert title */
|
||||
"Error saving chat list" = "Fout bij het opslaan van chatlijst";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Error saving group profile" = "Fout bij opslaan van groep profiel";
|
||||
|
||||
|
@ -2175,6 +2298,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Error synchronizing connection" = "Fout bij het synchroniseren van de verbinding";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Error testing server connection" = "Fout bij het testen van de serververbinding";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Error updating group link" = "Fout bij bijwerken van groep link";
|
||||
|
||||
|
@ -2229,6 +2355,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"expired" = "verlopen";
|
||||
|
||||
/* token status text */
|
||||
"Expired" = "Verlopen";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Export database" = "Database exporteren";
|
||||
|
||||
|
@ -2253,18 +2382,30 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Fast and no wait until the sender is online!" = "Snel en niet wachten tot de afzender online is!";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Faster deletion of groups." = "Sneller verwijderen van groepen.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Faster joining and more reliable messages." = "Snellere deelname en betrouwbaardere berichten.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Faster sending messages." = "Sneller verzenden van berichten.";
|
||||
|
||||
/* swipe action */
|
||||
"Favorite" = "Favoriet";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Favorites" = "Favorieten";
|
||||
|
||||
/* file error alert title */
|
||||
"File error" = "Bestandsfout";
|
||||
|
||||
/* alert message */
|
||||
"File errors:\n%@" = "Bestandsfouten:\n%@";
|
||||
|
||||
/* file error text */
|
||||
"File is blocked by server operator:\n%@." = "Bestand is geblokkeerd door serveroperator:\n%@.";
|
||||
|
||||
/* file error text */
|
||||
"File not found - most likely file was deleted or cancelled." = "Bestand niet gevonden - hoogstwaarschijnlijk is het bestand verwijderd of geannuleerd.";
|
||||
|
||||
|
@ -2340,6 +2481,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Fix not supported by group member" = "Herstel wordt niet ondersteund door groepslid";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"For all moderators" = "Voor alle moderators";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"for better metadata privacy." = "voor betere privacy van metagegevens.";
|
||||
|
||||
|
@ -2352,6 +2496,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"For example, if your contact receives messages via a SimpleX Chat server, your app will deliver them via a Flux server." = "Als uw contactpersoon bijvoorbeeld berichten ontvangt via een SimpleX Chat-server, worden deze door uw app via een Flux-server verzonden.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"For me" = "Voor mij";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"For private routing" = "Voor privé-routering";
|
||||
|
||||
|
@ -2424,6 +2571,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Further reduced battery usage" = "Verder verminderd batterij verbruik";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Get notified when mentioned." = "Ontvang een melding als u vermeld wordt.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"GIFs and stickers" = "GIF's en stickers";
|
||||
|
||||
|
@ -2496,9 +2646,15 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Group will be deleted for you - this cannot be undone!" = "De groep wordt voor u verwijderd, dit kan niet ongedaan worden gemaakt!";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Groups" = "Groepen";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Help" = "Help";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Help admins moderating their groups." = "Help beheerders bij het modereren van hun groepen.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Hidden" = "Verborgen";
|
||||
|
||||
|
@ -2535,6 +2691,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"How it helps privacy" = "Hoe het de privacy helpt";
|
||||
|
||||
/* alert button */
|
||||
"How it works" = "Hoe het werkt";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"How SimpleX works" = "Hoe SimpleX werkt";
|
||||
|
||||
|
@ -2622,6 +2781,12 @@
|
|||
/* No comment provided by engineer. */
|
||||
"inactive" = "inactief";
|
||||
|
||||
/* report reason */
|
||||
"Inappropriate content" = "Ongepaste inhoud";
|
||||
|
||||
/* report reason */
|
||||
"Inappropriate profile" = "Ongepast profiel";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Incognito" = "Incognito";
|
||||
|
||||
|
@ -2688,6 +2853,21 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Interface colors" = "Interface kleuren";
|
||||
|
||||
/* token status text */
|
||||
"Invalid" = "Ongeldig";
|
||||
|
||||
/* token status text */
|
||||
"Invalid (bad token)" = "Ongeldig (ongeldig token)";
|
||||
|
||||
/* token status text */
|
||||
"Invalid (expired)" = "Ongeldig (verlopen)";
|
||||
|
||||
/* token status text */
|
||||
"Invalid (unregistered)" = "Ongeldig (niet geregistreerd)";
|
||||
|
||||
/* token status text */
|
||||
"Invalid (wrong topic)" = "Ongeldig (verkeerd onderwerp)";
|
||||
|
||||
/* invalid chat data */
|
||||
"invalid chat" = "ongeldige gesprek";
|
||||
|
||||
|
@ -2889,6 +3069,15 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Linked desktops" = "Gelinkte desktops";
|
||||
|
||||
/* swipe action */
|
||||
"List" = "Lijst";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"List name and emoji should be different for all lists." = "De naam en emoji van de lijst moeten voor alle lijsten verschillend zijn.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"List name..." = "Naam van lijst...";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"LIVE" = "LIVE";
|
||||
|
||||
|
@ -2958,6 +3147,9 @@
|
|||
/* item status text */
|
||||
"Member inactive" = "Lid inactief";
|
||||
|
||||
/* chat feature */
|
||||
"Member reports" = "Ledenrapporten";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Member role will be changed to \"%@\". All chat members will be notified." = "De rol van het lid wordt gewijzigd naar \"%@\". Alle chatleden worden op de hoogte gebracht.";
|
||||
|
||||
|
@ -2979,6 +3171,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Members can irreversibly delete sent messages. (24 hours)" = "Groepsleden kunnen verzonden berichten onherroepelijk verwijderen. (24 uur)";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Members can report messsages to moderators." = "Leden kunnen berichten melden bij moderators.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Members can send direct messages." = "Groepsleden kunnen directe berichten sturen.";
|
||||
|
||||
|
@ -2994,6 +3189,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Members can send voice messages." = "Groepsleden kunnen spraak berichten verzenden.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Mention members 👋" = "Vermeld leden 👋";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Menus" = "Menu's";
|
||||
|
||||
|
@ -3066,6 +3264,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Messages from %@ will be shown!" = "Berichten van %@ worden getoond!";
|
||||
|
||||
/* alert message */
|
||||
"Messages in this chat will never be deleted." = "Berichten in deze chat zullen nooit worden verwijderd.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Messages received" = "Berichten ontvangen";
|
||||
|
||||
|
@ -3138,9 +3339,15 @@
|
|||
/* marked deleted chat item preview text */
|
||||
"moderated by %@" = "gemodereerd door %@";
|
||||
|
||||
/* member role */
|
||||
"moderator" = "moderator";
|
||||
|
||||
/* time unit */
|
||||
"months" = "maanden";
|
||||
|
||||
/* swipe action */
|
||||
"More" = "Meer";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"More improvements are coming soon!" = "Meer verbeteringen volgen snel!";
|
||||
|
||||
|
@ -3156,12 +3363,12 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Multiple chat profiles" = "Meerdere chatprofielen";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"mute" = "dempen";
|
||||
|
||||
/* swipe action */
|
||||
/* notification label action */
|
||||
"Mute" = "Dempen";
|
||||
|
||||
/* notification label action */
|
||||
"Mute all" = "Alles dempen";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Muted when inactive!" = "Gedempt wanneer inactief!";
|
||||
|
||||
|
@ -3195,6 +3402,9 @@
|
|||
/* delete after time */
|
||||
"never" = "nooit";
|
||||
|
||||
/* token status text */
|
||||
"New" = "Nieuw";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"New chat" = "Nieuw gesprek";
|
||||
|
||||
|
@ -3255,6 +3465,15 @@
|
|||
/* Authentication unavailable */
|
||||
"No app password" = "Geen app wachtwoord";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"No chats" = "Geen chats";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"No chats found" = "Geen chats gevonden";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"No chats in list %@" = "Geen chats in lijst %@";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"No contacts selected" = "Geen contacten geselecteerd";
|
||||
|
||||
|
@ -3288,6 +3507,9 @@
|
|||
/* servers error */
|
||||
"No media & file servers." = "Geen media- en bestandsservers.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"No message" = "Geen bericht";
|
||||
|
||||
/* servers error */
|
||||
"No message servers." = "Geen berichtenservers.";
|
||||
|
||||
|
@ -3324,12 +3546,21 @@
|
|||
/* copied message info in history */
|
||||
"no text" = "geen tekst";
|
||||
|
||||
/* alert title */
|
||||
"No token!" = "Geen token!";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"No unread chats" = "Geen ongelezen chats";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"No user identifiers." = "Geen gebruikers-ID's.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Not compatible!" = "Niet compatibel!";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Notes" = "Notities";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Nothing selected" = "Niets geselecteerd";
|
||||
|
||||
|
@ -3342,9 +3573,15 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Notifications are disabled!" = "Meldingen zijn uitgeschakeld!";
|
||||
|
||||
/* alert title */
|
||||
"Notifications error" = "Meldingsfout";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Notifications privacy" = "Privacy van meldingen";
|
||||
|
||||
/* alert title */
|
||||
"Notifications status" = "Meldingsstatus";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Now admins can:\n- delete members' messages.\n- disable members (\"observer\" role)" = "Nu kunnen beheerders: \n- berichten van leden verwijderen.\n- schakel leden uit (\"waarnemer\" rol)";
|
||||
|
||||
|
@ -3407,6 +3644,12 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Only group owners can enable voice messages." = "Alleen groep eigenaren kunnen spraak berichten inschakelen.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Only sender and moderators see it" = "Alleen de verzender en moderators zien het";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Only you and moderators see it" = "Alleen jij en moderators zien het";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Only you can add message reactions." = "Alleen jij kunt bericht reacties toevoegen.";
|
||||
|
||||
|
@ -3455,12 +3698,21 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Open group" = "Open groep";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Open link" = "Link openen";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Open links from chat list" = "Open links van chatlijst";
|
||||
|
||||
/* authentication reason */
|
||||
"Open migration to another device" = "Open de migratie naar een ander apparaat";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Open Settings" = "Open instellingen";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Open web link?" = "Weblink openen?";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Opening app…" = "App openen…";
|
||||
|
||||
|
@ -3488,6 +3740,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Or to share privately" = "Of om privé te delen";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Organize chats into lists" = "Organiseer chats in lijsten";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"other" = "overig";
|
||||
|
||||
|
@ -3614,6 +3869,15 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Please store passphrase securely, you will NOT be able to change it if you lose it." = "Bewaar het wachtwoord veilig, u kunt deze NIET wijzigen als u het kwijtraakt.";
|
||||
|
||||
/* token info */
|
||||
"Please try to disable and re-enable notfications." = "Probeer meldingen uit en weer in te schakelen.";
|
||||
|
||||
/* token info */
|
||||
"Please wait for token activation to complete." = "Wacht tot de tokenactivering voltooid is.";
|
||||
|
||||
/* token info */
|
||||
"Please wait for token to be registered." = "Wacht tot het token is geregistreerd.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Polish interface" = "Poolse interface";
|
||||
|
||||
|
@ -3650,6 +3914,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Private filenames" = "Privé bestandsnamen";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Private media file names." = "Namen van persoonlijke mediabestanden.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Private message routing" = "Routering van privéberichten";
|
||||
|
||||
|
@ -3695,6 +3962,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Prohibit messages reactions." = "Berichten reacties verbieden.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Prohibit reporting messages to moderators." = "Het melden van berichten aan moderators is niet toegestaan.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Prohibit sending direct messages to members." = "Verbied het sturen van directe berichten naar leden.";
|
||||
|
||||
|
@ -3857,6 +4127,15 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Reduced battery usage" = "Verminderd batterijgebruik";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Register" = "Register";
|
||||
|
||||
/* token info */
|
||||
"Register notification token?" = "Meldingstoken registreren?";
|
||||
|
||||
/* token status text */
|
||||
"Registered" = "Geregistreerd";
|
||||
|
||||
/* reject incoming call via notification
|
||||
swipe action */
|
||||
"Reject" = "Afwijzen";
|
||||
|
@ -3936,6 +4215,36 @@
|
|||
/* chat item action */
|
||||
"Reply" = "Antwoord";
|
||||
|
||||
/* chat item action */
|
||||
"Report" = "Rapport";
|
||||
|
||||
/* report reason */
|
||||
"Report content: only group moderators will see it." = "Inhoud melden: alleen groepsmoderators kunnen dit zien.";
|
||||
|
||||
/* report reason */
|
||||
"Report member profile: only group moderators will see it." = "Rapporteer ledenprofiel: alleen groepsmoderators kunnen dit zien.";
|
||||
|
||||
/* report reason */
|
||||
"Report other: only group moderators will see it." = "Anders melden: alleen groepsmoderators kunnen het zien.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Report reason?" = "Reden melding?";
|
||||
|
||||
/* report reason */
|
||||
"Report spam: only group moderators will see it." = "Spam melden: alleen groepsmoderators kunnen het zien.";
|
||||
|
||||
/* report reason */
|
||||
"Report violation: only group moderators will see it." = "Rapporteer overtreding: alleen groepsmoderators kunnen dit zien.";
|
||||
|
||||
/* report in notification */
|
||||
"Report: %@" = "Rapport: %@";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Reporting messages to moderators is prohibited." = "Het is niet toegestaan om berichten aan moderators te melden.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Reports" = "Rapporten";
|
||||
|
||||
/* chat list item title */
|
||||
"requested to connect" = "verzocht om verbinding te maken";
|
||||
|
||||
|
@ -4039,6 +4348,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Save group profile" = "Groep profiel opslaan";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Save list" = "Lijst opslaan";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Save passphrase and open chat" = "Wachtwoord opslaan en open je chats";
|
||||
|
||||
|
@ -4207,6 +4519,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Send notifications" = "Meldingen verzenden";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Send private reports" = "Verstuur rapporten privé";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Send questions and ideas" = "Stuur vragen en ideeën";
|
||||
|
||||
|
@ -4339,6 +4654,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Set 1 day" = "Stel 1 dag in";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Set chat name…" = "Stel chatnaam in…";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Set contact name…" = "Contactnaam instellen…";
|
||||
|
||||
|
@ -4351,11 +4669,14 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Set it instead of system authentication." = "Stel het in in plaats van systeemverificatie.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Set message expiration in chats." = "Stel de berichtvervaldatum in chats in.";
|
||||
|
||||
/* profile update event chat item */
|
||||
"set new contact address" = "nieuw contactadres instellen";
|
||||
|
||||
/* profile update event chat item */
|
||||
"set new profile picture" = "nieuwe profielfoto instellen";
|
||||
"set new profile picture" = "nieuwe profielfoto";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Set passcode" = "Toegangscode instellen";
|
||||
|
@ -4547,6 +4868,10 @@
|
|||
/* notification title */
|
||||
"Somebody" = "Iemand";
|
||||
|
||||
/* blocking reason
|
||||
report reason */
|
||||
"Spam" = "Spam";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Square, circle, or anything in between." = "Vierkant, cirkel of iets daartussenin.";
|
||||
|
||||
|
@ -4604,6 +4929,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Stopping chat" = "Chat stoppen";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Storage" = "Opslag";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"strike" = "staking";
|
||||
|
||||
|
@ -4673,6 +5001,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"TCP connection timeout" = "Timeout van TCP-verbinding";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"TCP port for messaging" = "TCP-poort voor berichtenuitwisseling";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"TCP_KEEPCNT" = "TCP_KEEPCNT";
|
||||
|
||||
|
@ -4688,6 +5019,9 @@
|
|||
/* server test failure */
|
||||
"Test failed at step %@." = "Test mislukt bij stap %@.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Test notifications" = "Testmeldingen";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Test server" = "Server test";
|
||||
|
||||
|
@ -4808,6 +5142,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"This action cannot be undone - the messages sent and received earlier than selected will be deleted. It may take several minutes." = "Deze actie kan niet ongedaan worden gemaakt, de berichten die eerder zijn verzonden en ontvangen dan geselecteerd, worden verwijderd. Het kan enkele minuten duren.";
|
||||
|
||||
/* alert message */
|
||||
"This action cannot be undone - the messages sent and received in this chat earlier than selected will be deleted." = "Deze actie kan niet ongedaan worden gemaakt. De berichten die eerder in deze chat zijn verzonden en ontvangen dan geselecteerd, worden verwijderd.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"This action cannot be undone - your profile, contacts, messages and files will be irreversibly lost." = "Deze actie kan niet ongedaan worden gemaakt. Uw profiel, contacten, berichten en bestanden gaan definitief verloren.";
|
||||
|
||||
|
@ -4841,6 +5178,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"This link was used with another mobile device, please create a new link on the desktop." = "Deze link is gebruikt met een ander mobiel apparaat. Maak een nieuwe link op de desktop.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"This message was deleted or not received yet." = "Dit bericht is verwijderd of nog niet ontvangen.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"This setting applies to messages in your current chat profile **%@**." = "Deze instelling is van toepassing op berichten in je huidige chatprofiel **%@**.";
|
||||
|
||||
|
@ -4907,6 +5247,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Toggle incognito when connecting." = "Schakel incognito in tijdens het verbinden.";
|
||||
|
||||
/* token status */
|
||||
"Token status: %@." = "Tokenstatus: %@.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Toolbar opacity" = "De transparantie van de werkbalk";
|
||||
|
||||
|
@ -5015,10 +5358,7 @@
|
|||
/* authentication reason */
|
||||
"Unlock app" = "Ontgrendel app";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"unmute" = "dempen opheffen";
|
||||
|
||||
/* swipe action */
|
||||
/* notification label action */
|
||||
"Unmute" = "Dempen opheffen";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
|
@ -5123,12 +5463,18 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Use SOCKS proxy" = "Gebruik SOCKS proxy";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Use TCP port %@ when no port is specified." = "Gebruik TCP-poort %@ als er geen poort is opgegeven.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Use the app while in the call." = "Gebruik de app tijdens het gesprek.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Use the app with one hand." = "Gebruik de app met één hand.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Use web port" = "Gebruik een webpoort";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"User selection" = "Gebruikersselectie";
|
||||
|
||||
|
@ -5339,6 +5685,9 @@
|
|||
/* pref value */
|
||||
"yes" = "Ja";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Yes" = "Ja";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"you" = "jij";
|
||||
|
||||
|
@ -5534,6 +5883,9 @@
|
|||
/* chat list item description */
|
||||
"you shared one-time link incognito" = "je hebt een eenmalige link incognito gedeeld";
|
||||
|
||||
/* token info */
|
||||
"You should receive notifications." = "U zou meldingen moeten ontvangen.";
|
||||
|
||||
/* snd group event chat item */
|
||||
"you unblocked %@" = "je hebt %@ gedeblokkeerd";
|
||||
|
||||
|
|
|
@ -1,9 +1,3 @@
|
|||
/* No comment provided by engineer. */
|
||||
"\n" = "\n";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
" (" = " (";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
" (can be copied)" = " (można skopiować)";
|
||||
|
||||
|
@ -22,30 +16,15 @@
|
|||
/* No comment provided by engineer. */
|
||||
"- voice messages up to 5 minutes.\n- custom time to disappear.\n- editing history." = "- wiadomości głosowe do 5 minut.\n- niestandardowy czas zniknięcia.\n- historia edycji.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
", " = ", ";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
": " = ": ";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"!1 colored!" = "!1 pokolorowany!";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"." = ".";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"(" = "(";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"(new)" = "(nowy)";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"(this device v%@)" = "(to urządzenie v%@)";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
")" = ")";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"[Contribute](https://github.com/simplex-chat/simplex-chat#contribute)" = "[Przyczyń się](https://github.com/simplex-chat/simplex-chat#contribute)";
|
||||
|
||||
|
@ -199,6 +178,9 @@
|
|||
/* time interval */
|
||||
"%d sec" = "%d sek";
|
||||
|
||||
/* delete after time */
|
||||
"%d seconds(s)" = "%d sekundach";
|
||||
|
||||
/* integrity error chat item */
|
||||
"%d skipped message(s)" = "%d pominięte wiadomość(i)";
|
||||
|
||||
|
@ -304,6 +286,9 @@
|
|||
time interval */
|
||||
"1 week" = "1 tydzień";
|
||||
|
||||
/* delete after time */
|
||||
"1 year" = "1 roku";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"1-time link" = "link jednorazowy";
|
||||
|
||||
|
@ -385,6 +370,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Acknowledgement errors" = "Błędy potwierdzenia";
|
||||
|
||||
/* token status text */
|
||||
"Active" = "Aktywne";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Active connections" = "Aktywne połączenia";
|
||||
|
||||
|
@ -394,6 +382,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Add friends" = "Dodaj znajomych";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Add list" = "Dodaj listę";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Add profile" = "Dodaj profil";
|
||||
|
||||
|
@ -409,6 +400,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Add to another device" = "Dodaj do innego urządzenia";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Add to list" = "Dodaj do listy";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Add welcome message" = "Dodaj wiadomość powitalną";
|
||||
|
||||
|
@ -466,12 +460,18 @@
|
|||
/* chat item text */
|
||||
"agreeing encryption…" = "uzgadnianie szyfrowania…";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"All" = "Wszystko";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"All app data is deleted." = "Wszystkie dane aplikacji są usunięte.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"All chats and messages will be deleted - this cannot be undone!" = "Wszystkie czaty i wiadomości zostaną usunięte - nie można tego cofnąć!";
|
||||
|
||||
/* alert message */
|
||||
"All chats will be removed from the list %@, and the list deleted." = "Wszystkie rozmowy zostaną usunięte z listy %@, a lista usunięta.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"All data is erased when it is entered." = "Wszystkie dane są usuwane po jego wprowadzeniu.";
|
||||
|
||||
|
@ -484,6 +484,9 @@
|
|||
/* feature role */
|
||||
"all members" = "wszyscy członkowie";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"All messages and files are sent **end-to-end encrypted**, with post-quantum security in direct messages." = "Wszystkie wiadomości i pliki są wysyłane **z szyfrowaniem end-to-end**, z bezpieczeństwem postkwantowym w wiadomościach bezpośrednich.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"All messages will be deleted - this cannot be undone!" = "Wszystkie wiadomości zostaną usunięte – nie można tego cofnąć!";
|
||||
|
||||
|
@ -496,6 +499,9 @@
|
|||
/* profile dropdown */
|
||||
"All profiles" = "Wszystkie profile";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"All reports will be archived for you." = "Wszystkie raporty zostaną dla Ciebie zarchiwizowane.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"All your contacts will remain connected." = "Wszystkie Twoje kontakty pozostaną połączone.";
|
||||
|
||||
|
@ -541,6 +547,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Allow to irreversibly delete sent messages. (24 hours)" = "Zezwól na nieodwracalne usunięcie wysłanych wiadomości. (24 godziny)";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Allow to report messsages to moderators." = "Zezwól na zgłaszanie wiadomości moderatorom.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Allow to send files and media." = "Pozwól na wysyłanie plików i mediów.";
|
||||
|
||||
|
@ -595,6 +604,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"and %lld other events" = "i %lld innych wydarzeń";
|
||||
|
||||
/* report reason */
|
||||
"Another reason" = "Inny powód";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Answer call" = "Odbierz połączenie";
|
||||
|
||||
|
@ -610,6 +622,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"App encrypts new local files (except videos)." = "Aplikacja szyfruje nowe lokalne pliki (bez filmów).";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"App group:" = "Grupa aplikacji:";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"App icon" = "Ikona aplikacji";
|
||||
|
||||
|
@ -637,18 +652,39 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Apply to" = "Zastosuj dla";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Archive" = "Archiwizuj";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Archive %lld reports?" = "Archiwizować %lld reports?";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Archive all reports?" = "Archiwizować wszystkie zgłoszenia?";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Archive and upload" = "Archiwizuj i prześlij";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Archive contacts to chat later." = "Archiwizuj kontakty aby porozmawiać później.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Archive report" = "Archiwizuj zgłoszenie";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Archive report?" = "Archiwizować zgłoszenie?";
|
||||
|
||||
/* swipe action */
|
||||
"Archive reports" = "Archiwizuj zgłoszenia";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Archived contacts" = "Zarchiwizowane kontakty";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Archiving database" = "Archiwizowanie bazy danych";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Ask" = "Zapytaj";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Attach" = "Dołącz";
|
||||
|
||||
|
@ -808,6 +844,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Business chats" = "Czaty biznesowe";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Businesses" = "Firmy";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"By chat profile (default) or [by connection](https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation) (BETA)." = "Według profilu czatu (domyślnie) lub [według połączenia](https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation) (BETA).";
|
||||
|
||||
|
@ -3042,10 +3081,7 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Multiple chat profiles" = "Wiele profili czatu";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"mute" = "wycisz";
|
||||
|
||||
/* swipe action */
|
||||
/* notification label action */
|
||||
"Mute" = "Wycisz";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
|
@ -4751,10 +4787,7 @@
|
|||
/* authentication reason */
|
||||
"Unlock app" = "Odblokuj aplikację";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"unmute" = "wyłącz wyciszenie";
|
||||
|
||||
/* swipe action */
|
||||
/* notification label action */
|
||||
"Unmute" = "Wyłącz wyciszenie";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
|
@ -5342,6 +5375,9 @@
|
|||
/* No comment provided by engineer. */
|
||||
"Your server address" = "Twój adres serwera";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Your servers" = "Twoje serwery";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Your settings" = "Twoje ustawienia";
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue