Merge branch 'master' into master-android

This commit is contained in:
Evgeny Poberezkin
2024-10-07 23:32:07 +01:00
97 changed files with 2755 additions and 1121 deletions
+3 -6
View File
@@ -29,12 +29,12 @@ struct ContentView: View {
@AppStorage(DEFAULT_PERFORM_LA) private var prefPerformLA = false
@AppStorage(DEFAULT_PRIVACY_PROTECT_SCREEN) private var protectScreen = false
@AppStorage(DEFAULT_NOTIFICATION_ALERT_SHOWN) private var notificationAlertShown = false
@State private var showSettings = false
@State private var showWhatsNew = false
@State private var showChooseLAMode = false
@State private var showSetPasscode = false
@State private var waitingForOrPassedAuth = true
@State private var chatListActionSheet: ChatListActionSheet? = nil
@State private var chatListUserPickerSheet: UserPickerSheet? = nil
private let callTopPadding: CGFloat = 40
@@ -86,7 +86,7 @@ struct ContentView: View {
callView(call)
}
if !showSettings, let la = chatModel.laRequest {
if chatListUserPickerSheet == nil, let la = chatModel.laRequest {
LocalAuthView(authRequest: la)
.onDisappear {
// this flag is separate from accessAuthenticated to show initializationView while we wait for authentication
@@ -109,9 +109,6 @@ struct ContentView: View {
}
}
.alert(isPresented: $alertManager.presentAlert) { alertManager.alertView! }
.sheet(isPresented: $showSettings) {
SettingsView(showSettings: $showSettings)
}
.confirmationDialog("SimpleX Lock mode", isPresented: $showChooseLAMode, titleVisibility: .visible) {
Button("System authentication") { initialEnableLA() }
Button("Passcode entry") { showSetPasscode = true }
@@ -253,7 +250,7 @@ struct ContentView: View {
private func mainView() -> some View {
ZStack(alignment: .top) {
ChatListView(showSettings: $showSettings).privacySensitive(protectScreen)
ChatListView(activeUserPickerSheet: $chatListUserPickerSheet).privacySensitive(protectScreen)
.onAppear {
requestNtfAuthorization()
// Local Authentication notice is to be shown on next start after onboarding is complete
+1 -1
View File
@@ -526,7 +526,7 @@ final class ChatModel: ObservableObject {
}
func updateCurrentUserUiThemes(uiThemes: ThemeModeOverrides?) {
guard var current = currentUser else { return }
guard var current = currentUser, current.uiThemes != uiThemes else { return }
current.uiThemes = uiThemes
let i = users.firstIndex(where: { $0.user.userId == current.userId })
if let i {
+1 -1
View File
@@ -122,7 +122,7 @@ extension ThemeWallpaper {
let preset: String? = if case let WallpaperType.preset(filename, _) = type { filename } else { nil }
let scale: Float? = if case let WallpaperType.preset(_, scale) = type { scale } else { if case let WallpaperType.image(_, scale, _) = type { scale } else { 1.0 } }
let scaleType: WallpaperScaleType? = if case let WallpaperType.image(_, _, scaleType) = type { scaleType } else { nil }
let image: String? = if case WallpaperType.image = type, let image = type.uiImage { resizeImageToStrSize(image, maxDataSize: 5_000_000) } else { nil }
let image: String? = if case WallpaperType.image = type, let image = type.uiImage { resizeImageToStrSizeSync(image, maxDataSize: 5_000_000) } else { nil }
return ThemeWallpaper (
preset: preset,
scale: scale,
@@ -459,7 +459,7 @@ struct ComposeView: View {
Task {
var media: [(String, UploadContent)] = []
for content in selected {
if let img = resizeImageToStrSize(content.uiImage, maxDataSize: 14000) {
if let img = await resizeImageToStrSize(content.uiImage, maxDataSize: 14000) {
media.append((img, content))
await MainActor.run {
composeState = composeState.copy(preview: .mediaPreviews(mediaPreviews: media))
@@ -551,7 +551,7 @@ struct ComposeView: View {
}
private func addMediaContent(_ content: UploadContent) async {
if let img = resizeImageToStrSize(content.uiImage, maxDataSize: 14000) {
if let img = await resizeImageToStrSize(content.uiImage, maxDataSize: 14000) {
var newMedia: [(String, UploadContent?)] = []
if case var .mediaPreviews(media) = composeState.preview {
media.append((img, content))
@@ -110,10 +110,13 @@ struct GroupProfileView: View {
}
}
.onChange(of: chosenImage) { image in
if let image = image {
groupProfile.image = resizeImageToStrSize(cropToSquare(image), maxDataSize: 12500)
} else {
groupProfile.image = nil
Task {
let resized: String? = if let image {
await resizeImageToStrSize(cropToSquare(image), maxDataSize: 12500)
} else {
nil
}
await MainActor.run { groupProfile.image = resized }
}
}
.onAppear {
@@ -10,7 +10,7 @@ import SwiftUI
struct ChatHelp: View {
@EnvironmentObject var chatModel: ChatModel
@Binding var showSettings: Bool
let dismissSettingsSheet: DismissAction
var body: some View {
ScrollView { chatHelp() }
@@ -23,7 +23,7 @@ struct ChatHelp: View {
VStack(alignment: .leading, spacing: 0) {
Text("To ask any questions and to receive updates:")
Button("connect to SimpleX Chat developers.") {
showSettings = false
dismissSettingsSheet()
DispatchQueue.main.async {
UIApplication.shared.open(simplexTeamURL)
}
@@ -61,8 +61,9 @@ struct ChatHelp: View {
}
struct ChatHelp_Previews: PreviewProvider {
@Environment(\.dismiss) static var mockDismiss
static var previews: some View {
@State var showSettings = false
return ChatHelp(showSettings: $showSettings)
ChatHelp(dismissSettingsSheet: mockDismiss)
}
}
@@ -18,19 +18,77 @@ enum UserPickerSheet: Identifiable {
case settings
var id: Self { self }
var navigationTitle: LocalizedStringKey {
switch self {
case .address: "SimpleX address"
case .chatPreferences: "Your preferences"
case .chatProfiles: "Your chat profiles"
case .currentProfile: "Your current profile"
case .useFromDesktop: "Connect to desktop"
case .settings: "Your settings"
}
}
}
struct UserPickerSheetView: View {
let sheet: UserPickerSheet
@EnvironmentObject var chatModel: ChatModel
@State private var loaded = false
var body: some View {
NavigationView {
ZStack {
if loaded, let currentUser = chatModel.currentUser {
switch sheet {
case .address:
UserAddressView(shareViaProfile: currentUser.addressShared)
case .chatPreferences:
PreferencesView(
profile: currentUser.profile,
preferences: currentUser.fullPreferences,
currentPreferences: currentUser.fullPreferences
)
case .chatProfiles:
UserProfilesView()
case .currentProfile:
UserProfile()
case .useFromDesktop:
ConnectDesktopView()
case .settings:
SettingsView()
}
}
Color.clear // Required for list background to be rendered during loading
}
.navigationTitle(sheet.navigationTitle)
.navigationBarTitleDisplayMode(.large)
.modifier(ThemedBackground(grouped: true))
}
.overlay {
if let la = chatModel.laRequest {
LocalAuthView(authRequest: la)
}
}
.task {
withAnimation(
.easeOut(duration: 0.1),
{ loaded = true }
)
}
}
}
struct ChatListView: View {
@EnvironmentObject var chatModel: ChatModel
@EnvironmentObject var theme: AppTheme
@Binding var showSettings: Bool
@Binding var activeUserPickerSheet: UserPickerSheet?
@State private var searchMode = false
@FocusState private var searchFocussed
@State private var searchText = ""
@State private var searchShowingSimplexLink = false
@State private var searchChatFilteredBySimplexLink: String? = nil
@State private var scrollToSearchBar = false
@State private var activeUserPickerSheet: UserPickerSheet? = nil
@State private var userPickerShown: Bool = false
@AppStorage(DEFAULT_SHOW_UNREAD_AND_FAVORITES) private var showUnreadAndFavorites = false
@@ -58,43 +116,20 @@ struct ChatListView: View {
destination: chatView
) { chatListView }
}
.sheet(isPresented: $userPickerShown) {
UserPicker(activeSheet: $activeUserPickerSheet)
.sheet(item: $activeUserPickerSheet) { sheet in
if let currentUser = chatModel.currentUser {
switch sheet {
case .address:
NavigationView {
UserAddressView(shareViaProfile: currentUser.addressShared)
.navigationTitle("SimpleX address")
.navigationBarTitleDisplayMode(.large)
.modifier(ThemedBackground(grouped: true))
}
case .chatProfiles:
NavigationView {
UserProfilesView()
}
case .currentProfile:
NavigationView {
UserProfile()
.navigationTitle("Your current profile")
.modifier(ThemedBackground(grouped: true))
}
case .chatPreferences:
NavigationView {
PreferencesView(profile: currentUser.profile, preferences: currentUser.fullPreferences, currentPreferences: currentUser.fullPreferences)
.navigationTitle("Your preferences")
.navigationBarTitleDisplayMode(.large)
.modifier(ThemedBackground(grouped: true))
}
case .useFromDesktop:
ConnectDesktopView(viaSettings: false)
case .settings:
SettingsView(showSettings: $showSettings)
.navigationBarTitleDisplayMode(.large)
}
}
.modifier(
Sheet(isPresented: $userPickerShown) {
UserPicker(userPickerShown: $userPickerShown, activeSheet: $activeUserPickerSheet)
}
)
.sheet(item: $activeUserPickerSheet) {
UserPickerSheetView(sheet: $0)
}
.onChange(of: activeUserPickerSheet) {
if $0 != nil {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
userPickerShown = false
}
}
}
}
@@ -544,6 +579,8 @@ func chatStoppedIcon() -> some View {
}
struct ChatListView_Previews: PreviewProvider {
@State static var userPickerSheet: UserPickerSheet? = .none
static var previews: some View {
let chatModel = ChatModel()
chatModel.updateChats([
@@ -562,9 +599,9 @@ struct ChatListView_Previews: PreviewProvider {
])
return Group {
ChatListView(showSettings: Binding.constant(false))
ChatListView(activeUserPickerSheet: $userPickerSheet)
.environmentObject(chatModel)
ChatListView(showSettings: Binding.constant(false))
ChatListView(activeUserPickerSheet: $userPickerSheet)
.environmentObject(ChatModel())
}
}
+128 -44
View File
@@ -12,42 +12,30 @@ struct UserPicker: View {
@Environment(\.dynamicTypeSize) private var userFont: DynamicTypeSize
@Environment(\.scenePhase) private var scenePhase: ScenePhase
@Environment(\.colorScheme) private var colorScheme: ColorScheme
@Environment(\.dismiss) private var dismiss: DismissAction
@Binding var userPickerShown: Bool
@Binding var activeSheet: UserPickerSheet?
@State private var currentUser: Int64?
@State private var switchingProfile = false
@State private var frameWidth: CGFloat = 0
@State private var resetScroll = ResetScrollAction()
// Inset grouped list dimensions
private let imageSize: CGFloat = 44
private let rowPadding: CGFloat = 16
private let rowVerticalPadding: CGFloat = 11
private let sectionSpacing: CGFloat = 35
private var sectionHorizontalPadding: CGFloat { frameWidth > 375 ? 20 : 16 }
private let sectionShape = RoundedRectangle(cornerRadius: 10, style: .continuous)
var body: some View {
if #available(iOS 16.0, *) {
let v = viewBody.presentationDetents([.height(400)])
if #available(iOS 16.4, *) {
v.scrollBounceBehavior(.basedOnSize)
} else {
v
}
} else {
viewBody
}
}
@ViewBuilder
private var viewBody: some View {
let otherUsers: [UserInfo] = m.users
.filter { u in !u.user.hidden && u.user.userId != m.currentUser?.userId }
.sorted(using: KeyPathComparator<UserInfo>(\.user.activeOrder, order: .reverse))
let sectionWidth = max(frameWidth - sectionHorizontalPadding * 2, 0)
let currentUserWidth = max(frameWidth - sectionHorizontalPadding - rowPadding * 2 - 14 - imageSize, 0)
VStack(spacing: 0) {
VStack(spacing: sectionSpacing) {
if let user = m.currentUser {
StickyScrollView {
StickyScrollView(resetScroll: $resetScroll) {
HStack(spacing: rowPadding) {
HStack {
ProfileImage(imageStr: user.image, size: imageSize, color: Color(uiColor: .tertiarySystemGroupedBackground))
@@ -56,9 +44,8 @@ struct UserPicker: View {
}
.padding(rowPadding)
.frame(width: otherUsers.isEmpty ? sectionWidth : currentUserWidth, alignment: .leading)
.background(Color(.secondarySystemGroupedBackground))
.modifier(ListRow { activeSheet = .currentProfile })
.clipShape(sectionShape)
.onTapGesture { activeSheet = .currentProfile }
ForEach(otherUsers) { u in
userView(u, size: imageSize)
.frame(maxWidth: sectionWidth * 0.618)
@@ -72,20 +59,21 @@ struct UserPicker: View {
.overlay(DetermineWidth())
.onPreferenceChange(DetermineWidth.Key.self) { frameWidth = $0 }
}
List {
Section {
openSheetOnTap("qrcode", title: m.userAddress == nil ? "Create SimpleX address" : "Your SimpleX address", sheet: .address)
openSheetOnTap("switch.2", title: "Chat preferences", sheet: .chatPreferences)
openSheetOnTap("person.crop.rectangle.stack", title: "Your chat profiles", sheet: .chatProfiles)
openSheetOnTap("desktopcomputer", title: "Use from desktop", sheet: .useFromDesktop)
ZStack(alignment: .trailing) {
openSheetOnTap("gearshape", title: "Settings", sheet: .settings)
Image(systemName: colorScheme == .light ? "sun.max" : "moon.fill")
VStack(spacing: 0) {
openSheetOnTap("qrcode", title: m.userAddress == nil ? "Create SimpleX address" : "Your SimpleX address", sheet: .address)
openSheetOnTap("switch.2", title: "Chat preferences", sheet: .chatPreferences)
openSheetOnTap("person.crop.rectangle.stack", title: "Your chat profiles", sheet: .chatProfiles)
openSheetOnTap("desktopcomputer", title: "Use from desktop", sheet: .useFromDesktop)
ZStack(alignment: .trailing) {
openSheetOnTap("gearshape", title: "Settings", sheet: .settings, showDivider: false)
Image(systemName: colorScheme == .light ? "sun.max" : "moon.fill")
.resizable()
.scaledToFit()
.symbolRenderingMode(.monochrome)
.foregroundColor(theme.colors.secondary)
.frame(maxWidth: 20, maxHeight: 20)
.frame(maxWidth: 20, maxHeight: .infinity)
.padding(.horizontal, rowPadding)
.background(Color(.systemBackground).opacity(0.01))
.onTapGesture {
if (colorScheme == .light) {
ThemeManager.applyTheme(systemDarkThemeDefault.get())
@@ -96,9 +84,11 @@ struct UserPicker: View {
.onLongPressGesture {
ThemeManager.applyTheme(DefaultTheme.SYSTEM_THEME_NAME)
}
}
}
}
.clipShape(sectionShape)
.padding(.horizontal, sectionHorizontalPadding)
.padding(.bottom, sectionSpacing)
}
.onAppear {
// This check prevents the call of listUsers after the app is suspended, and the database is closed.
@@ -117,6 +107,9 @@ struct UserPicker: View {
}
}
}
.onChange(of: userPickerShown) {
if !$0 { resetScroll() }
}
.modifier(ThemedBackground(grouped: true))
.disabled(switchingProfile)
}
@@ -133,15 +126,15 @@ struct UserPicker: View {
Text(u.user.displayName).font(.title2).lineLimit(1)
}
.padding(rowPadding)
.background(Color(.secondarySystemGroupedBackground))
.clipShape(sectionShape)
.onTapGesture {
.modifier(ListRow {
switchingProfile = true
dismiss()
Task {
do {
try await changeActiveUserAsync_(u.user.userId, viewPwd: nil)
await MainActor.run { switchingProfile = false }
await MainActor.run {
switchingProfile = false
userPickerShown = false
}
} catch {
await MainActor.run {
switchingProfile = false
@@ -152,19 +145,23 @@ struct UserPicker: View {
}
}
}
}
})
.clipShape(sectionShape)
}
private func openSheetOnTap(_ icon: String, title: LocalizedStringKey, sheet: UserPickerSheet) -> some View {
Button {
activeSheet = sheet
} label: {
private func openSheetOnTap(_ icon: String, title: LocalizedStringKey, sheet: UserPickerSheet, showDivider: Bool = true) -> some View {
ZStack(alignment: .bottom) {
settingsRow(icon, color: theme.colors.secondary) {
Text(title).foregroundColor(.primary)
}
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.horizontal, rowPadding)
.padding(.vertical, rowVerticalPadding)
.modifier(ListRow { activeSheet = sheet })
if showDivider {
Divider().padding(.leading, 52)
}
}
.frame(maxWidth: .infinity, alignment: .leading)
.contentShape(Rectangle())
}
private func unreadBadge(_ u: UserInfo) -> some View {
@@ -179,6 +176,92 @@ struct UserPicker: View {
}
}
struct ListRow: ViewModifier {
@Environment(\.colorScheme) private var colorScheme: ColorScheme
@State private var touchDown = false
let action: () -> Void
func body(content: Content) -> some View {
ZStack {
elevatedSecondarySystemGroupedBackground
Color(.systemGray4).opacity(touchDown ? 1 : 0)
content
TouchOverlay(touchDown: $touchDown, action: action)
}
}
var elevatedSecondarySystemGroupedBackground: Color {
switch colorScheme {
case .dark: Color(0xFF2C2C2E)
default: Color(0xFFFFFFFF)
}
}
struct TouchOverlay: UIViewRepresentable {
@Binding var touchDown: Bool
let action: () -> Void
func makeUIView(context: Context) -> TouchView {
let touchView = TouchView()
let gesture = UILongPressGestureRecognizer(
target: touchView,
action: #selector(touchView.longPress(gesture:))
)
gesture.delegate = touchView
gesture.minimumPressDuration = 0
touchView.addGestureRecognizer(gesture)
return touchView
}
func updateUIView(_ touchView: TouchView, context: Context) {
touchView.representer = self
}
class TouchView: UIView, UIGestureRecognizerDelegate {
var representer: TouchOverlay?
private var startLocation: CGPoint?
private var task: Task<Void, Never>?
@objc
func longPress(gesture: UILongPressGestureRecognizer) {
switch gesture.state {
case .began:
startLocation = gesture.location(in: nil)
task = Task {
do {
try await Task.sleep(nanoseconds: 200_000000)
await MainActor.run { representer?.touchDown = true }
} catch { }
}
case .ended:
if hitTest(gesture.location(in: self), with: nil) == self {
representer?.action()
}
task?.cancel()
representer?.touchDown = false
case .changed:
if let startLocation {
let location = gesture.location(in: nil)
let dx = location.x - startLocation.x
let dy = location.y - startLocation.y
if sqrt(pow(dx, 2) + pow(dy, 2)) > 10 { gesture.state = .failed }
}
case .cancelled, .failed:
task?.cancel()
representer?.touchDown = false
default: break
}
}
func gestureRecognizer(
_: UIGestureRecognizer,
shouldRecognizeSimultaneouslyWith: UIGestureRecognizer
) -> Bool { true }
}
}
}
struct UserPicker_Previews: PreviewProvider {
static var previews: some View {
@State var activeSheet: UserPickerSheet?
@@ -186,6 +269,7 @@ struct UserPicker_Previews: PreviewProvider {
let m = ChatModel()
m.users = [UserInfo.sampleData, UserInfo.sampleData]
return UserPicker(
userPickerShown: .constant(true),
activeSheet: $activeSheet
)
.environmentObject(m)
@@ -44,7 +44,7 @@ enum DatabaseAlert: Identifiable {
struct DatabaseView: View {
@EnvironmentObject var m: ChatModel
@EnvironmentObject var theme: AppTheme
@Binding var showSettings: Bool
let dismissSettingsSheet: DismissAction
@State private var runChat = false
@State private var alert: DatabaseAlert? = nil
@State private var showFileImporter = false
@@ -439,7 +439,7 @@ struct DatabaseView: View {
private func startChat() {
if m.chatDbChanged {
showSettings = false
dismissSettingsSheet()
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
resetChatCtrl()
do {
@@ -533,7 +533,9 @@ func deleteChatAsync() async throws {
}
struct DatabaseView_Previews: PreviewProvider {
@Environment(\.dismiss) static var mockDismiss
static var previews: some View {
DatabaseView(showSettings: Binding.constant(false), chatItemTTL: .none)
DatabaseView(dismissSettingsSheet: mockDismiss, chatItemTTL: .none)
}
}
@@ -0,0 +1,188 @@
//
// SwiftUISheet.swift
// SimpleX (iOS)
//
// Created by user on 23/09/2024.
// Copyright © 2024 SimpleX Chat. All rights reserved.
//
import SwiftUI
private let sheetAnimationDuration: Double = 0.35
// Refrence: https://easings.net/
private let easeOutCubic = UICubicTimingParameters(
controlPoint1: CGPoint(x: 0.215, y: 0.61),
controlPoint2: CGPoint(x: 0.355, y: 1)
)
struct Sheet<SheetContent: View>: ViewModifier {
@Binding var isPresented: Bool
@ViewBuilder let sheetContent: () -> SheetContent
func body(content: Content) -> some View {
ZStack {
content
SheetRepresentable(isPresented: $isPresented, content: sheetContent())
.allowsHitTesting(isPresented)
.ignoresSafeArea()
}
}
}
struct SheetRepresentable<Content: View>: UIViewControllerRepresentable {
@Binding var isPresented: Bool
let content: Content
func makeUIViewController(context: Context) -> Controller<Content> {
Controller(content: content, representer: self)
}
func updateUIViewController(_ sheetController: Controller<Content>, context: Context) {
sheetController.animate(isPresented: isPresented)
}
class Controller<C: View>: UIViewController {
let hostingController: UIHostingController<C>
private let animator = UIViewPropertyAnimator(
duration: sheetAnimationDuration,
timingParameters: easeOutCubic
)
private let representer: SheetRepresentable<C>
private var retainedFraction: CGFloat = 0
private var sheetHeight: Double { hostingController.view.frame.height }
private var task: Task<Void, Never>?
init(content: C, representer: SheetRepresentable<C>) {
self.representer = representer
self.hostingController = UIHostingController(rootView: content)
super.init(nibName: nil, bundle: nil)
}
@available(*, unavailable)
required init?(coder: NSCoder) { fatalError("init(coder:) missing") }
deinit {
animator.stopAnimation(true)
animator.finishAnimation(at: .current)
}
func animate(isPresented: Bool) {
let alreadyAnimating = animator.isRunning && isPresented != animator.isReversed
let sheetFullyDismissed = animator.fractionComplete == (animator.isReversed ? 1 : 0)
let sheetFullyPresented = animator.fractionComplete == (animator.isReversed ? 0 : 1)
if !isPresented && sheetFullyDismissed ||
isPresented && sheetFullyPresented ||
alreadyAnimating {
return
}
animator.pauseAnimation()
animator.isReversed = !isPresented
animator.continueAnimation(
withTimingParameters: isPresented
? easeOutCubic
: UICubicTimingParameters(animationCurve: .easeIn),
durationFactor: 1 - animator.fractionComplete
)
handleVisibility()
}
func handleVisibility() {
if animator.isReversed {
task = Task {
do {
let sleepDuration = UInt64(sheetAnimationDuration * Double(NSEC_PER_SEC))
try await Task.sleep(nanoseconds: sleepDuration)
view.isHidden = true
} catch { }
}
} else {
task?.cancel()
task = nil
view.isHidden = false
}
}
override func viewDidLoad() {
view.isHidden = true
view.backgroundColor = .clear
view.addGestureRecognizer(
UITapGestureRecognizer(target: self, action: #selector(tap(gesture:)))
)
addChild(hostingController)
hostingController.didMove(toParent: self)
if let sheet = hostingController.view {
sheet.isHidden = true
sheet.clipsToBounds = true
sheet.layer.cornerRadius = 10
sheet.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMinXMinYCorner]
sheet.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(pan(gesture:))))
sheet.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(sheet)
NSLayoutConstraint.activate([
hostingController.view.leadingAnchor.constraint(equalTo: view.leadingAnchor),
hostingController.view.trailingAnchor.constraint(equalTo: view.trailingAnchor),
hostingController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor),
])
}
}
override func viewDidAppear(_ animated: Bool) {
// Ensures animations are only setup once
// on some iOS version `viewDidAppear` can get called on each state change.
if hostingController.view.isHidden {
hostingController.view.transform = CGAffineTransform(translationX: 0, y: self.sheetHeight)
hostingController.view.isHidden = false
animator.pausesOnCompletion = true
animator.addAnimations {
self.hostingController.view.transform = .identity
self.view.backgroundColor = UIColor {
switch $0.userInterfaceStyle {
case .dark: .black.withAlphaComponent(0.290)
default: .black.withAlphaComponent(0.121)
}
}
}
animator.startAnimation()
animator.pauseAnimation()
}
}
@objc
func pan(gesture: UIPanGestureRecognizer) {
switch gesture.state {
case .began:
animator.isReversed = false
animator.pauseAnimation()
retainedFraction = animator.fractionComplete
case .changed:
animator.fractionComplete = retainedFraction - gesture.translation(in: view).y / sheetHeight
case .ended, .cancelled:
let velocity = gesture.velocity(in: view).y
animator.isReversed = (velocity - (animator.fractionComplete - 0.5) * 100).sign == .plus
let defaultVelocity = sheetHeight / sheetAnimationDuration
let fractionRemaining = 1 - animator.fractionComplete
let durationFactor = min(max(fractionRemaining / (abs(velocity) / defaultVelocity), 0.5), 1)
animator.continueAnimation(withTimingParameters: nil, durationFactor: durationFactor * fractionRemaining)
handleVisibility()
DispatchQueue.main.asyncAfter(deadline: .now() + sheetAnimationDuration) {
self.representer.isPresented = !self.animator.isReversed
}
default: break
}
}
@objc
func tap(gesture: UITapGestureRecognizer) {
switch gesture.state {
case .ended:
if gesture.location(in: view).y < view.frame.height - sheetHeight {
representer.isPresented = false
}
default: break
}
}
}
}
@@ -9,6 +9,7 @@
import SwiftUI
struct StickyScrollView<Content: View>: UIViewRepresentable {
@Binding var resetScroll: ResetScrollAction
@ViewBuilder let content: () -> Content
func makeUIView(context: Context) -> UIScrollView {
@@ -18,6 +19,9 @@ struct StickyScrollView<Content: View>: UIViewRepresentable {
sv.showsHorizontalScrollIndicator = false
sv.addSubview(hc.view)
sv.delegate = context.coordinator
DispatchQueue.main.async {
resetScroll = ResetScrollAction { sv.setContentOffset(.zero, animated: false) }
}
return sv
}
@@ -50,3 +54,8 @@ struct StickyScrollView<Content: View>: UIViewRepresentable {
}
}
}
struct ResetScrollAction {
var action = { }
func callAsFunction() { action() }
}
@@ -137,10 +137,13 @@ struct AddGroupView: View {
createInvalidNameAlert(mkValidName(profile.displayName), $profile.displayName)
}
.onChange(of: chosenImage) { image in
if let image = image {
profile.image = resizeImageToStrSize(cropToSquare(image), maxDataSize: 12500)
} else {
profile.image = nil
Task {
let resized: String? = if let image {
await resizeImageToStrSize(cropToSquare(image), maxDataSize: 12500)
} else {
nil
}
await MainActor.run { profile.image = resized }
}
}
.modifier(ThemedBackground(grouped: true))
@@ -241,7 +241,6 @@ private struct InviteView: View {
@Binding var choosingProfile: Bool
@AppStorage(GROUP_DEFAULT_INCOGNITO, store: groupDefaults) private var incognitoDefault = false
@State private var showSettings: Bool = false
var body: some View {
List {
@@ -693,6 +692,7 @@ struct ScannerInView: View {
.frame(maxWidth: .infinity, maxHeight: .infinity)
.foregroundColor(Color.clear)
switch cameraAuthorizationStatus {
case .authorized, nil: EmptyView()
case .restricted: Text("Camera not available")
case .denied: Label("Enable camera access", systemImage: "camera")
default: Label("Tap to scan", systemImage: "qrcode")
@@ -712,21 +712,26 @@ struct ScannerInView: View {
.disabled(cameraAuthorizationStatus == .restricted)
}
}
.onAppear {
.task {
let status = AVCaptureDevice.authorizationStatus(for: .video)
cameraAuthorizationStatus = status
if showQRCodeScanner {
switch status {
case .notDetermined: askCameraAuthorization()
case .notDetermined: await askCameraAuthorizationAsync()
case .restricted: showQRCodeScanner = false
case .denied: showQRCodeScanner = false
case .authorized: ()
@unknown default: askCameraAuthorization()
@unknown default: await askCameraAuthorizationAsync()
}
}
}
}
func askCameraAuthorizationAsync() async {
await AVCaptureDevice.requestAccess(for: .video)
cameraAuthorizationStatus = AVCaptureDevice.authorizationStatus(for: .video)
}
func askCameraAuthorization(_ cb: (() -> Void)? = nil) {
AVCaptureDevice.requestAccess(for: .video) { allowed in
cameraAuthorizationStatus = AVCaptureDevice.authorizationStatus(for: .video)
+23 -23
View File
@@ -49,34 +49,34 @@ struct QRCode: View {
ZStack {
if let image = image {
qrCodeImage(image)
}
GeometryReader { geo in
ZStack {
if withLogo {
let w = geo.size.width
Image("icon-light")
.resizable()
.scaledToFit()
.frame(width: w * 0.16, height: w * 0.16)
.frame(width: w * 0.165, height: w * 0.165)
.background(.white)
.clipShape(Circle())
GeometryReader { geo in
ZStack {
if withLogo {
let w = geo.size.width
Image("icon-light")
.resizable()
.scaledToFit()
.frame(width: w * 0.16, height: w * 0.16)
.frame(width: w * 0.165, height: w * 0.165)
.background(.white)
.clipShape(Circle())
}
}
}
.onAppear {
makeScreenshotFunc = {
let size = CGSizeMake(1024 / UIScreen.main.scale, 1024 / UIScreen.main.scale)
showShareSheet(items: [makeScreenshot(geo.frame(in: .local).origin, size)])
onShare?()
.onAppear {
makeScreenshotFunc = {
let size = CGSizeMake(1024 / UIScreen.main.scale, 1024 / UIScreen.main.scale)
showShareSheet(items: [makeScreenshot(geo.frame(in: .local).origin, size)])
onShare?()
}
}
.frame(width: geo.size.width, height: geo.size.height)
}
.frame(width: geo.size.width, height: geo.size.height)
} else {
Color.clear.aspectRatio(1, contentMode: .fit)
}
}
.onTapGesture(perform: makeScreenshotFunc)
.onAppear {
image = image ?? generateImage(uri, tintColor: tintColor)
}
.task { image = await generateImage(uri, tintColor: tintColor) }
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
@@ -89,7 +89,7 @@ private func qrCodeImage(_ image: UIImage) -> some View {
.textSelection(.enabled)
}
private func generateImage(_ uri: String, tintColor: UIColor) -> UIImage? {
private func generateImage(_ uri: String, tintColor: UIColor) async -> UIImage? {
let context = CIContext()
let filter = CIFilter.qrCodeGenerator()
filter.message = Data(uri.utf8)
@@ -14,7 +14,6 @@ struct ConnectDesktopView: View {
@EnvironmentObject var m: ChatModel
@EnvironmentObject var theme: AppTheme
@Environment(\.dismiss) var dismiss: DismissAction
var viaSettings = false
@AppStorage(DEFAULT_DEVICE_NAME_FOR_REMOTE_ACCESS) private var deviceName = UIDevice.current.name
@AppStorage(DEFAULT_CONFIRM_REMOTE_SESSIONS) private var confirmRemoteSessions = false
@AppStorage(DEFAULT_CONNECT_REMOTE_VIA_MULTICAST) private var connectRemoteViaMulticast = true
@@ -57,16 +56,6 @@ struct ConnectDesktopView: View {
}
var body: some View {
if viaSettings {
viewBody
} else {
NavigationView {
viewBody
}
}
}
var viewBody: some View {
Group {
let discovery = m.remoteCtrlSession?.discovery
if discovery == true || (discovery == nil && !showConnectScreen) {
@@ -58,6 +58,8 @@ extension AppSettings {
profileImageCornerRadiusGroupDefault.set(val)
def.setValue(val, forKey: DEFAULT_PROFILE_IMAGE_CORNER_RADIUS)
}
if let val = uiChatItemRoundness { def.setValue(val, forKey: DEFAULT_CHAT_ITEM_ROUNDNESS)}
if let val = uiChatItemTail { def.setValue(val, forKey: DEFAULT_CHAT_ITEM_TAIL)}
if let val = uiColorScheme { currentThemeDefault.set(val) }
if let val = uiDarkColorScheme { systemDarkThemeDefault.set(val) }
if let val = uiCurrentThemeIds { currentThemeIdsDefault.set(val) }
@@ -91,6 +93,8 @@ extension AppSettings {
c.iosCallKitEnabled = callKitEnabledGroupDefault.get()
c.iosCallKitCallsInRecents = def.bool(forKey: DEFAULT_CALL_KIT_CALLS_IN_RECENTS)
c.uiProfileImageCornerRadius = def.double(forKey: DEFAULT_PROFILE_IMAGE_CORNER_RADIUS)
c.uiChatItemRoundness = def.double(forKey: DEFAULT_CHAT_ITEM_ROUNDNESS)
c.uiChatItemTail = def.bool(forKey: DEFAULT_CHAT_ITEM_TAIL)
c.uiColorScheme = currentThemeDefault.get()
c.uiDarkColorScheme = systemDarkThemeDefault.get()
c.uiCurrentThemeIds = currentThemeIdsDefault.get()
@@ -257,23 +257,18 @@ let networkProxyDefault: CodableDefault<NetworkProxy> = CodableDefault(defaults:
struct SettingsView: View {
@Environment(\.colorScheme) var colorScheme
@Environment(\.dismiss) var dismiss
@EnvironmentObject var chatModel: ChatModel
@EnvironmentObject var sceneDelegate: SceneDelegate
@EnvironmentObject var theme: AppTheme
@Binding var showSettings: Bool
@State private var showProgress: Bool = false
var body: some View {
ZStack {
NavigationView {
settingsView()
}
settingsView()
if showProgress {
progressView()
}
if let la = chatModel.laRequest {
LocalAuthView(authRequest: la)
}
}
}
@@ -347,7 +342,7 @@ struct SettingsView: View {
Section(header: Text("Help").foregroundColor(theme.colors.secondary)) {
if let user = user {
NavigationLink {
ChatHelp(showSettings: $showSettings)
ChatHelp(dismissSettingsSheet: dismiss)
.navigationTitle("Welcome \(user.displayName)!")
.modifier(ThemedBackground())
.frame(maxHeight: .infinity, alignment: .top)
@@ -372,7 +367,7 @@ struct SettingsView: View {
}
settingsRow("number", color: theme.colors.secondary) {
Button("Send questions and ideas") {
showSettings = false
dismiss()
DispatchQueue.main.async {
UIApplication.shared.open(simplexTeamURL)
}
@@ -429,7 +424,7 @@ struct SettingsView: View {
private func chatDatabaseRow() -> some View {
NavigationLink {
DatabaseView(showSettings: $showSettings, chatItemTTL: chatModel.chatItemTTL)
DatabaseView(dismissSettingsSheet: dismiss, chatItemTTL: chatModel.chatItemTTL)
.navigationTitle("Your chat database")
.modifier(ThemedBackground(grouped: true))
} label: {
@@ -525,9 +520,7 @@ struct SettingsView_Previews: PreviewProvider {
static var previews: some View {
let chatModel = ChatModel()
chatModel.currentUser = User.sampleData
@State var showSettings = false
return SettingsView(showSettings: $showSettings)
return SettingsView()
.environmentObject(chatModel)
}
}
@@ -94,10 +94,13 @@ struct UserProfile: View {
}
}
.onChange(of: chosenImage) { image in
if let image {
profile.image = resizeImageToStrSize(cropToSquare(image), maxDataSize: 12500)
} else {
profile.image = nil
Task {
let resized: String? = if let image {
await resizeImageToStrSize(cropToSquare(image), maxDataSize: 12500)
} else {
nil
}
await MainActor.run { profile.image = resized }
}
}
// Modals
@@ -737,7 +737,7 @@
</trans-unit>
<trans-unit id="All profiles" xml:space="preserve">
<source>All profiles</source>
<note>No comment provided by engineer.</note>
<note>profile dropdown</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source>
@@ -2934,7 +2934,7 @@ This is your own one-time link!</source>
<trans-unit id="Error switching profile!" xml:space="preserve">
<source>Error switching profile!</source>
<target>Грешка при смяна на профил!</target>
<note>No comment provided by engineer.</note>
<note>alertTitle</note>
</trans-unit>
<trans-unit id="Error synchronizing connection" xml:space="preserve">
<source>Error synchronizing connection</source>
@@ -2979,8 +2979,7 @@ This is your own one-time link!</source>
<trans-unit id="Error: %@" xml:space="preserve">
<source>Error: %@</source>
<target>Грешка: %@</target>
<note>file error text
snd error text</note>
<note>alert message</note>
</trans-unit>
<trans-unit id="Error: URL is invalid" xml:space="preserve">
<source>Error: URL is invalid</source>
@@ -7267,11 +7266,6 @@ To connect, please ask your contact to create another connection link and check
<source>XFTP server</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You" xml:space="preserve">
<source>You</source>
<target>Вие</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You **must not** use the same database on two devices." xml:space="preserve">
<source>You **must not** use the same database on two devices.</source>
<target>**Не трябва** да използвате една и съща база данни на две устройства.</target>
@@ -715,7 +715,7 @@
</trans-unit>
<trans-unit id="All profiles" xml:space="preserve">
<source>All profiles</source>
<note>No comment provided by engineer.</note>
<note>profile dropdown</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source>
@@ -2836,7 +2836,7 @@ This is your own one-time link!</source>
<trans-unit id="Error switching profile!" xml:space="preserve">
<source>Error switching profile!</source>
<target>Chyba při přepínání profilu!</target>
<note>No comment provided by engineer.</note>
<note>alertTitle</note>
</trans-unit>
<trans-unit id="Error synchronizing connection" xml:space="preserve">
<source>Error synchronizing connection</source>
@@ -2879,8 +2879,7 @@ This is your own one-time link!</source>
<trans-unit id="Error: %@" xml:space="preserve">
<source>Error: %@</source>
<target>Chyba: %@</target>
<note>file error text
snd error text</note>
<note>alert message</note>
</trans-unit>
<trans-unit id="Error: URL is invalid" xml:space="preserve">
<source>Error: URL is invalid</source>
@@ -7015,11 +7014,6 @@ Chcete-li se připojit, požádejte svůj kontakt o vytvoření dalšího odkazu
<source>XFTP server</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You" xml:space="preserve">
<source>You</source>
<target>Vy</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You **must not** use the same database on two devices." xml:space="preserve">
<source>You **must not** use the same database on two devices.</source>
<note>No comment provided by engineer.</note>
@@ -164,18 +164,22 @@
</trans-unit>
<trans-unit id="%d file(s) are still being downloaded." xml:space="preserve">
<source>%d file(s) are still being downloaded.</source>
<target>%d Datei(en) wird/werden immer noch heruntergeladen.</target>
<note>forward confirmation reason</note>
</trans-unit>
<trans-unit id="%d file(s) failed to download." xml:space="preserve">
<source>%d file(s) failed to download.</source>
<target>Bei %d Datei(en) ist das Herunterladen fehlgeschlagen.</target>
<note>forward confirmation reason</note>
</trans-unit>
<trans-unit id="%d file(s) were deleted." xml:space="preserve">
<source>%d file(s) were deleted.</source>
<target>%d Datei(en) wurde(n) gelöscht.</target>
<note>forward confirmation reason</note>
</trans-unit>
<trans-unit id="%d file(s) were not downloaded." xml:space="preserve">
<source>%d file(s) were not downloaded.</source>
<target>%d Datei(en) wurde(n) nicht heruntergeladen.</target>
<note>forward confirmation reason</note>
</trans-unit>
<trans-unit id="%d hours" xml:space="preserve">
@@ -185,6 +189,7 @@
</trans-unit>
<trans-unit id="%d messages not forwarded" xml:space="preserve">
<source>%d messages not forwarded</source>
<target>%d Nachrichten wurden nicht weitergeleitet</target>
<note>alert title</note>
</trans-unit>
<trans-unit id="%d min" xml:space="preserve">
@@ -748,7 +753,7 @@
<trans-unit id="All profiles" xml:space="preserve">
<source>All profiles</source>
<target>Alle Profile</target>
<note>No comment provided by engineer.</note>
<note>profile dropdown</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source>
@@ -1777,7 +1782,7 @@ Das ist Ihr eigener Einmal-Link!</target>
</trans-unit>
<trans-unit id="Corner" xml:space="preserve">
<source>Corner</source>
<target>Ecke</target>
<target>Ecken-Abrundung</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Correct name to %@?" xml:space="preserve">
@@ -2451,6 +2456,7 @@ Das ist Ihr eigener Einmal-Link!</target>
</trans-unit>
<trans-unit id="Do not use credentials with proxy." xml:space="preserve">
<source>Do not use credentials with proxy.</source>
<target>Verwenden Sie keine Anmeldeinformationen mit einem Proxy.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Don't create address" xml:space="preserve">
@@ -2496,6 +2502,7 @@ Das ist Ihr eigener Einmal-Link!</target>
</trans-unit>
<trans-unit id="Download files" xml:space="preserve">
<source>Download files</source>
<target>Dateien herunterladen</target>
<note>alert action</note>
</trans-unit>
<trans-unit id="Downloaded" xml:space="preserve">
@@ -3026,7 +3033,7 @@ Das ist Ihr eigener Einmal-Link!</target>
<trans-unit id="Error switching profile!" xml:space="preserve">
<source>Error switching profile!</source>
<target>Fehler beim Umschalten des Profils!</target>
<note>No comment provided by engineer.</note>
<note>alertTitle</note>
</trans-unit>
<trans-unit id="Error synchronizing connection" xml:space="preserve">
<source>Error synchronizing connection</source>
@@ -3071,8 +3078,7 @@ Das ist Ihr eigener Einmal-Link!</target>
<trans-unit id="Error: %@" xml:space="preserve">
<source>Error: %@</source>
<target>Fehler: %@</target>
<note>file error text
snd error text</note>
<note>alert message</note>
</trans-unit>
<trans-unit id="Error: URL is invalid" xml:space="preserve">
<source>Error: URL is invalid</source>
@@ -3162,6 +3168,8 @@ Das ist Ihr eigener Einmal-Link!</target>
<trans-unit id="File errors:&#10;%@" xml:space="preserve">
<source>File errors:
%@</source>
<target>Datei-Fehler:
%@</target>
<note>alert message</note>
</trans-unit>
<trans-unit id="File not found - most likely file was deleted or cancelled." xml:space="preserve">
@@ -3301,6 +3309,7 @@ Das ist Ihr eigener Einmal-Link!</target>
</trans-unit>
<trans-unit id="Forward %d message(s)?" xml:space="preserve">
<source>Forward %d message(s)?</source>
<target>%d Nachricht(en) weiterleiten?</target>
<note>alert title</note>
</trans-unit>
<trans-unit id="Forward and save messages" xml:space="preserve">
@@ -3310,10 +3319,12 @@ Das ist Ihr eigener Einmal-Link!</target>
</trans-unit>
<trans-unit id="Forward messages" xml:space="preserve">
<source>Forward messages</source>
<target>Nachrichten weiterleiten</target>
<note>alert action</note>
</trans-unit>
<trans-unit id="Forward messages without files?" xml:space="preserve">
<source>Forward messages without files?</source>
<target>Nachrichten ohne Dateien weiterleiten?</target>
<note>alert message</note>
</trans-unit>
<trans-unit id="Forwarded" xml:space="preserve">
@@ -3328,6 +3339,7 @@ Das ist Ihr eigener Einmal-Link!</target>
</trans-unit>
<trans-unit id="Forwarding %lld messages" xml:space="preserve">
<source>Forwarding %lld messages</source>
<target>%lld Nachricht(en) wird/werden weitergeleitet</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Forwarding server %@ failed to connect to destination server %@. Please try later." xml:space="preserve">
@@ -3626,6 +3638,7 @@ Fehler: %2$@</target>
</trans-unit>
<trans-unit id="IP address" xml:space="preserve">
<source>IP address</source>
<target>IP-Adresse</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="If you can't meet in person, show QR code in a video call, or share the link." xml:space="preserve">
@@ -4330,6 +4343,7 @@ Das ist Ihr Link für die Gruppe %@!</target>
</trans-unit>
<trans-unit id="Messages were deleted after you selected them." xml:space="preserve">
<source>Messages were deleted after you selected them.</source>
<target>Die Nachrichten wurden gelöscht, nachdem Sie sie ausgewählt hatten.</target>
<note>alert message</note>
</trans-unit>
<trans-unit id="Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery." xml:space="preserve">
@@ -4629,6 +4643,7 @@ Das ist Ihr Link für die Gruppe %@!</target>
</trans-unit>
<trans-unit id="Nothing to forward!" xml:space="preserve">
<source>Nothing to forward!</source>
<target>Es gibt nichts zum Weiterleiten!</target>
<note>alert title</note>
</trans-unit>
<trans-unit id="Notifications" xml:space="preserve">
@@ -4857,6 +4872,8 @@ Dies erfordert die Aktivierung eines VPNs.</target>
<trans-unit id="Other file errors:&#10;%@" xml:space="preserve">
<source>Other file errors:
%@</source>
<target>Andere(r) Datei-Fehler:
%@</target>
<note>alert message</note>
</trans-unit>
<trans-unit id="PING count" xml:space="preserve">
@@ -4896,6 +4913,7 @@ Dies erfordert die Aktivierung eines VPNs.</target>
</trans-unit>
<trans-unit id="Password" xml:space="preserve">
<source>Password</source>
<target>Passwort</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Password to show" xml:space="preserve">
@@ -5049,6 +5067,7 @@ Fehler: %@</target>
</trans-unit>
<trans-unit id="Port" xml:space="preserve">
<source>Port</source>
<target>Port</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Possibly, certificate fingerprint in server address is incorrect" xml:space="preserve">
@@ -5240,6 +5259,7 @@ Aktivieren Sie es in den *Netzwerk &amp; Server* Einstellungen.</target>
</trans-unit>
<trans-unit id="Proxy requires password" xml:space="preserve">
<source>Proxy requires password</source>
<target>Der Proxy benötigt ein Passwort</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Push notifications" xml:space="preserve">
@@ -5650,6 +5670,7 @@ Aktivieren Sie es in den *Netzwerk &amp; Server* Einstellungen.</target>
</trans-unit>
<trans-unit id="SOCKS proxy" xml:space="preserve">
<source>SOCKS proxy</source>
<target>SOCKS-Proxy</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Safely receive files" xml:space="preserve">
@@ -5765,6 +5786,7 @@ Aktivieren Sie es in den *Netzwerk &amp; Server* Einstellungen.</target>
</trans-unit>
<trans-unit id="Saving %lld messages" xml:space="preserve">
<source>Saving %lld messages</source>
<target>Es wird/werden %lld Nachricht(en) gesichert</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Scale" xml:space="preserve">
@@ -6579,7 +6601,7 @@ Aktivieren Sie es in den *Netzwerk &amp; Server* Einstellungen.</target>
</trans-unit>
<trans-unit id="Tail" xml:space="preserve">
<source>Tail</source>
<target>Sprechblase</target>
<target>Sprechblasen-Format</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Take picture" xml:space="preserve">
@@ -7175,6 +7197,7 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
</trans-unit>
<trans-unit id="Use SOCKS proxy" xml:space="preserve">
<source>Use SOCKS proxy</source>
<target>SOCKS-Proxy nutzen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use SimpleX Chat servers?" xml:space="preserve">
@@ -7254,6 +7277,7 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
</trans-unit>
<trans-unit id="Username" xml:space="preserve">
<source>Username</source>
<target>Benutzername</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Using SimpleX Chat servers." xml:space="preserve">
@@ -7516,11 +7540,6 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
<target>XFTP-Server</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You" xml:space="preserve">
<source>You</source>
<target>Profil</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You **must not** use the same database on two devices." xml:space="preserve">
<source>You **must not** use the same database on two devices.</source>
<target>Sie dürfen die selbe Datenbank **nicht** auf zwei Geräten nutzen.</target>
@@ -7902,6 +7921,7 @@ Verbindungsanfrage wiederholen?</target>
</trans-unit>
<trans-unit id="Your credentials may be sent unencrypted." xml:space="preserve">
<source>Your credentials may be sent unencrypted.</source>
<target>Ihre Anmeldeinformationen können unverschlüsselt versendet werden.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your current chat database will be DELETED and REPLACED with the imported one." xml:space="preserve">
@@ -753,7 +753,7 @@
<trans-unit id="All profiles" xml:space="preserve">
<source>All profiles</source>
<target>All profiles</target>
<note>No comment provided by engineer.</note>
<note>profile dropdown</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source>
@@ -3033,7 +3033,7 @@ This is your own one-time link!</target>
<trans-unit id="Error switching profile!" xml:space="preserve">
<source>Error switching profile!</source>
<target>Error switching profile!</target>
<note>No comment provided by engineer.</note>
<note>alertTitle</note>
</trans-unit>
<trans-unit id="Error synchronizing connection" xml:space="preserve">
<source>Error synchronizing connection</source>
@@ -3078,8 +3078,7 @@ This is your own one-time link!</target>
<trans-unit id="Error: %@" xml:space="preserve">
<source>Error: %@</source>
<target>Error: %@</target>
<note>file error text
snd error text</note>
<note>alert message</note>
</trans-unit>
<trans-unit id="Error: URL is invalid" xml:space="preserve">
<source>Error: URL is invalid</source>
@@ -7541,11 +7540,6 @@ To connect, please ask your contact to create another connection link and check
<target>XFTP server</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You" xml:space="preserve">
<source>You</source>
<target>You</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You **must not** use the same database on two devices." xml:space="preserve">
<source>You **must not** use the same database on two devices.</source>
<target>You **must not** use the same database on two devices.</target>
@@ -139,6 +139,7 @@
</trans-unit>
<trans-unit id="%@, %@" xml:space="preserve">
<source>%1$@, %2$@</source>
<target>%1$@, %2$@</target>
<note>format for date separator in chat</note>
</trans-unit>
<trans-unit id="%@, %@ and %lld members" xml:space="preserve">
@@ -163,18 +164,22 @@
</trans-unit>
<trans-unit id="%d file(s) are still being downloaded." xml:space="preserve">
<source>%d file(s) are still being downloaded.</source>
<target>%d archivo(s) se está(n) descargando todavía.</target>
<note>forward confirmation reason</note>
</trans-unit>
<trans-unit id="%d file(s) failed to download." xml:space="preserve">
<source>%d file(s) failed to download.</source>
<target>La descarga ha fallado para %d archivo(s).</target>
<note>forward confirmation reason</note>
</trans-unit>
<trans-unit id="%d file(s) were deleted." xml:space="preserve">
<source>%d file(s) were deleted.</source>
<target>%d archivo(s) ha(n) sido eliminado(s).</target>
<note>forward confirmation reason</note>
</trans-unit>
<trans-unit id="%d file(s) were not downloaded." xml:space="preserve">
<source>%d file(s) were not downloaded.</source>
<target>%d archivo(s) no se ha(n) descargado.</target>
<note>forward confirmation reason</note>
</trans-unit>
<trans-unit id="%d hours" xml:space="preserve">
@@ -184,6 +189,7 @@
</trans-unit>
<trans-unit id="%d messages not forwarded" xml:space="preserve">
<source>%d messages not forwarded</source>
<target>%d mensajes no enviados</target>
<note>alert title</note>
</trans-unit>
<trans-unit id="%d min" xml:space="preserve">
@@ -531,7 +537,7 @@
</trans-unit>
<trans-unit id="A new random profile will be shared." xml:space="preserve">
<source>A new random profile will be shared.</source>
<target>Se compartirá un perfil nuevo aleatorio.</target>
<target>Compartirás un perfil nuevo aleatorio.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="A separate TCP connection will be used **for each chat profile you have in the app**." xml:space="preserve">
@@ -747,7 +753,7 @@
<trans-unit id="All profiles" xml:space="preserve">
<source>All profiles</source>
<target>Todos los perfiles</target>
<note>No comment provided by engineer.</note>
<note>profile dropdown</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source>
@@ -1046,6 +1052,7 @@
</trans-unit>
<trans-unit id="Auto-accept settings" xml:space="preserve">
<source>Auto-accept settings</source>
<target>Auto aceptar configuración</target>
<note>alert title</note>
</trans-unit>
<trans-unit id="Back" xml:space="preserve">
@@ -1371,6 +1378,7 @@
</trans-unit>
<trans-unit id="Chat preferences were changed." xml:space="preserve">
<source>Chat preferences were changed.</source>
<target>Las preferencias del chat han sido modificadas.</target>
<note>alert message</note>
</trans-unit>
<trans-unit id="Chat theme" xml:space="preserve">
@@ -1774,6 +1782,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Corner" xml:space="preserve">
<source>Corner</source>
<target>Esquina</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Correct name to %@?" xml:space="preserve">
@@ -1982,7 +1991,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Database passphrase is different from saved in the keychain." xml:space="preserve">
<source>Database passphrase is different from saved in the keychain.</source>
<target>La contraseña es distinta a la almacenada en Keychain.</target>
<target>La contraseña es diferente a la almacenada en Keychain.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Database passphrase is required to open chat." xml:space="preserve">
@@ -2407,7 +2416,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Disconnect desktop?" xml:space="preserve">
<source>Disconnect desktop?</source>
<target>¿Desconectar ordenador?</target>
<target>¿Desconectar del ordenador?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Discover and join groups" xml:space="preserve">
@@ -2447,6 +2456,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Do not use credentials with proxy." xml:space="preserve">
<source>Do not use credentials with proxy.</source>
<target>No uses credenciales con proxy.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Don't create address" xml:space="preserve">
@@ -2461,7 +2471,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Don't show again" xml:space="preserve">
<source>Don't show again</source>
<target>No mostrar de nuevo</target>
<target>No volver a mostrar</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Downgrade and open chat" xml:space="preserve">
@@ -2492,6 +2502,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Download files" xml:space="preserve">
<source>Download files</source>
<target>Descargar archivos</target>
<note>alert action</note>
</trans-unit>
<trans-unit id="Downloaded" xml:space="preserve">
@@ -2771,6 +2782,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Error changing connection profile" xml:space="preserve">
<source>Error changing connection profile</source>
<target>Error al cambiar el perfil de conexión</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error changing role" xml:space="preserve">
@@ -2785,6 +2797,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Error changing to incognito!" xml:space="preserve">
<source>Error changing to incognito!</source>
<target>¡Error al cambiar a incógnito!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error connecting to forwarding server %@. Please try later." xml:space="preserve">
@@ -2909,6 +2922,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Error migrating settings" xml:space="preserve">
<source>Error migrating settings</source>
<target>Error al migrar la configuración</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error opening chat" xml:space="preserve">
@@ -3013,12 +3027,13 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Error switching profile" xml:space="preserve">
<source>Error switching profile</source>
<target>Error al cambiar perfil</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error switching profile!" xml:space="preserve">
<source>Error switching profile!</source>
<target>¡Error al cambiar perfil!</target>
<note>No comment provided by engineer.</note>
<note>alertTitle</note>
</trans-unit>
<trans-unit id="Error synchronizing connection" xml:space="preserve">
<source>Error synchronizing connection</source>
@@ -3063,8 +3078,7 @@ This is your own one-time link!</source>
<trans-unit id="Error: %@" xml:space="preserve">
<source>Error: %@</source>
<target>Error: %@</target>
<note>file error text
snd error text</note>
<note>alert message</note>
</trans-unit>
<trans-unit id="Error: URL is invalid" xml:space="preserve">
<source>Error: URL is invalid</source>
@@ -3154,6 +3168,8 @@ This is your own one-time link!</source>
<trans-unit id="File errors:&#10;%@" xml:space="preserve">
<source>File errors:
%@</source>
<target>Error(es) de archivo
%@</target>
<note>alert message</note>
</trans-unit>
<trans-unit id="File not found - most likely file was deleted or cancelled." xml:space="preserve">
@@ -3293,6 +3309,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Forward %d message(s)?" xml:space="preserve">
<source>Forward %d message(s)?</source>
<target>¿Reenviar %d mensaje(s)?</target>
<note>alert title</note>
</trans-unit>
<trans-unit id="Forward and save messages" xml:space="preserve">
@@ -3302,10 +3319,12 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Forward messages" xml:space="preserve">
<source>Forward messages</source>
<target>Reenviar mensajes</target>
<note>alert action</note>
</trans-unit>
<trans-unit id="Forward messages without files?" xml:space="preserve">
<source>Forward messages without files?</source>
<target>¿Reenviar mensajes sin los archivos?</target>
<note>alert message</note>
</trans-unit>
<trans-unit id="Forwarded" xml:space="preserve">
@@ -3320,6 +3339,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Forwarding %lld messages" xml:space="preserve">
<source>Forwarding %lld messages</source>
<target>Reenviando %lld mensajes</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Forwarding server %@ failed to connect to destination server %@. Please try later." xml:space="preserve">
@@ -3373,12 +3393,12 @@ Error: %2$@</target>
</trans-unit>
<trans-unit id="Fully decentralized – visible only to members." xml:space="preserve">
<source>Fully decentralized – visible only to members.</source>
<target>Completamente descentralizado y sólo visible para los miembros.</target>
<target>Totalmente descentralizado. Visible sólo para los miembros.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Fully re-implemented - work in background!" xml:space="preserve">
<source>Fully re-implemented - work in background!</source>
<target>Completamente reimplementado: ¡funciona en segundo plano!</target>
<target>Totalmente revisado. ¡Funciona en segundo plano!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Further reduced battery usage" xml:space="preserve">
@@ -3618,6 +3638,7 @@ Error: %2$@</target>
</trans-unit>
<trans-unit id="IP address" xml:space="preserve">
<source>IP address</source>
<target>Dirección IP</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="If you can't meet in person, show QR code in a video call, or share the link." xml:space="preserve">
@@ -4267,6 +4288,7 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Message shape" xml:space="preserve">
<source>Message shape</source>
<target>Forma del mensaje</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Message source remains private." xml:space="preserve">
@@ -4321,6 +4343,7 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Messages were deleted after you selected them." xml:space="preserve">
<source>Messages were deleted after you selected them.</source>
<target>Los mensajes han sido borrados después de seleccionarlos.</target>
<note>alert message</note>
</trans-unit>
<trans-unit id="Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery." xml:space="preserve">
@@ -4620,6 +4643,7 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Nothing to forward!" xml:space="preserve">
<source>Nothing to forward!</source>
<target>¡Nada para reenviar!</target>
<note>alert title</note>
</trans-unit>
<trans-unit id="Notifications" xml:space="preserve">
@@ -4848,6 +4872,8 @@ Requiere activación de la VPN.</target>
<trans-unit id="Other file errors:&#10;%@" xml:space="preserve">
<source>Other file errors:
%@</source>
<target>Otro(s) error(es) de archivo.
%@</target>
<note>alert message</note>
</trans-unit>
<trans-unit id="PING count" xml:space="preserve">
@@ -4887,6 +4913,7 @@ Requiere activación de la VPN.</target>
</trans-unit>
<trans-unit id="Password" xml:space="preserve">
<source>Password</source>
<target>Contraseña</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Password to show" xml:space="preserve">
@@ -5040,6 +5067,7 @@ Error: %@</target>
</trans-unit>
<trans-unit id="Port" xml:space="preserve">
<source>Port</source>
<target>Puerto</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Possibly, certificate fingerprint in server address is incorrect" xml:space="preserve">
@@ -5231,6 +5259,7 @@ Actívalo en ajustes de *Servidores y Redes*.</target>
</trans-unit>
<trans-unit id="Proxy requires password" xml:space="preserve">
<source>Proxy requires password</source>
<target>El proxy requiere contraseña</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Push notifications" xml:space="preserve">
@@ -5456,6 +5485,7 @@ Actívalo en ajustes de *Servidores y Redes*.</target>
</trans-unit>
<trans-unit id="Remove archive?" xml:space="preserve">
<source>Remove archive?</source>
<target>¿Eliminar archivo?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Remove image" xml:space="preserve">
@@ -5640,6 +5670,7 @@ Actívalo en ajustes de *Servidores y Redes*.</target>
</trans-unit>
<trans-unit id="SOCKS proxy" xml:space="preserve">
<source>SOCKS proxy</source>
<target>Proxy SOCKS</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Safely receive files" xml:space="preserve">
@@ -5730,6 +5761,7 @@ Actívalo en ajustes de *Servidores y Redes*.</target>
</trans-unit>
<trans-unit id="Save your profile?" xml:space="preserve">
<source>Save your profile?</source>
<target>¿Guardar tu perfil?</target>
<note>alert title</note>
</trans-unit>
<trans-unit id="Saved" xml:space="preserve">
@@ -5754,6 +5786,7 @@ Actívalo en ajustes de *Servidores y Redes*.</target>
</trans-unit>
<trans-unit id="Saving %lld messages" xml:space="preserve">
<source>Saving %lld messages</source>
<target>Guardando %lld mensajes</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Scale" xml:space="preserve">
@@ -5838,6 +5871,7 @@ Actívalo en ajustes de *Servidores y Redes*.</target>
</trans-unit>
<trans-unit id="Select chat profile" xml:space="preserve">
<source>Select chat profile</source>
<target>Selecciona perfil de chat</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Selected %lld" xml:space="preserve">
@@ -5887,7 +5921,7 @@ Actívalo en ajustes de *Servidores y Redes*.</target>
</trans-unit>
<trans-unit id="Send direct message to connect" xml:space="preserve">
<source>Send direct message to connect</source>
<target>Envia un mensaje para conectar</target>
<target>Envía un mensaje para conectar</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Send disappearing message" xml:space="preserve">
@@ -6177,6 +6211,7 @@ Actívalo en ajustes de *Servidores y Redes*.</target>
</trans-unit>
<trans-unit id="Settings were changed." xml:space="preserve">
<source>Settings were changed.</source>
<target>La configuración ha sido modificada.</target>
<note>alert message</note>
</trans-unit>
<trans-unit id="Shape profile images" xml:space="preserve">
@@ -6216,6 +6251,7 @@ Actívalo en ajustes de *Servidores y Redes*.</target>
</trans-unit>
<trans-unit id="Share profile" xml:space="preserve">
<source>Share profile</source>
<target>Comparte perfil</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Share this 1-time invite link" xml:space="preserve">
@@ -6385,6 +6421,7 @@ Actívalo en ajustes de *Servidores y Redes*.</target>
</trans-unit>
<trans-unit id="Some app settings were not migrated." xml:space="preserve">
<source>Some app settings were not migrated.</source>
<target>Algunas configuraciones de la app no han sido migradas.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Some file(s) were not exported:" xml:space="preserve">
@@ -6564,6 +6601,7 @@ Actívalo en ajustes de *Servidores y Redes*.</target>
</trans-unit>
<trans-unit id="Tail" xml:space="preserve">
<source>Tail</source>
<target>Cola</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Take picture" xml:space="preserve">
@@ -6760,6 +6798,7 @@ Puede ocurrir por algún bug o cuando la conexión está comprometida.</target>
</trans-unit>
<trans-unit id="The uploaded database archive will be permanently removed from the servers." xml:space="preserve">
<source>The uploaded database archive will be permanently removed from the servers.</source>
<target>El archivo de bases de datos subido será eliminado permanentemente de los servidores.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Themes" xml:space="preserve">
@@ -7158,6 +7197,7 @@ Para conectarte pide a tu contacto que cree otro enlace y comprueba la conexión
</trans-unit>
<trans-unit id="Use SOCKS proxy" xml:space="preserve">
<source>Use SOCKS proxy</source>
<target>Usar proxy SOCKS</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use SimpleX Chat servers?" xml:space="preserve">
@@ -7237,6 +7277,7 @@ Para conectarte pide a tu contacto que cree otro enlace y comprueba la conexión
</trans-unit>
<trans-unit id="Username" xml:space="preserve">
<source>Username</source>
<target>Nombre de usuario</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Using SimpleX Chat servers." xml:space="preserve">
@@ -7499,11 +7540,6 @@ Para conectarte pide a tu contacto que cree otro enlace y comprueba la conexión
<target>Servidor XFTP</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You" xml:space="preserve">
<source>You</source>
<target>Tú</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You **must not** use the same database on two devices." xml:space="preserve">
<source>You **must not** use the same database on two devices.</source>
<target>**No debes** usar la misma base de datos en dos dispositivos.</target>
@@ -7855,6 +7891,7 @@ Repeat connection request?</source>
</trans-unit>
<trans-unit id="Your chat preferences" xml:space="preserve">
<source>Your chat preferences</source>
<target>Tus preferencias de chat</target>
<note>alert title</note>
</trans-unit>
<trans-unit id="Your chat profiles" xml:space="preserve">
@@ -7864,6 +7901,7 @@ Repeat connection request?</source>
</trans-unit>
<trans-unit id="Your connection was moved to %@ but an unexpected error occurred while redirecting you to the profile." xml:space="preserve">
<source>Your connection was moved to %@ but an unexpected error occurred while redirecting you to the profile.</source>
<target>Tu conexión ha sido trasladada a %@ pero ha ocurrido un error inesperado al redirigirte al perfil.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your contact sent a file that is larger than currently supported maximum size (%@)." xml:space="preserve">
@@ -7883,6 +7921,7 @@ Repeat connection request?</source>
</trans-unit>
<trans-unit id="Your credentials may be sent unencrypted." xml:space="preserve">
<source>Your credentials may be sent unencrypted.</source>
<target>Tus credenciales podrían ser enviadas sin cifrar.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your current chat database will be DELETED and REPLACED with the imported one." xml:space="preserve">
@@ -7922,6 +7961,7 @@ Repeat connection request?</source>
</trans-unit>
<trans-unit id="Your profile was changed. If you save it, the updated profile will be sent to all your contacts." xml:space="preserve">
<source>Your profile was changed. If you save it, the updated profile will be sent to all your contacts.</source>
<target>Tu perfil ha sido modificado. Si lo guardas la actualización será enviada a todos tus contactos.</target>
<note>alert message</note>
</trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
@@ -7941,7 +7981,7 @@ Repeat connection request?</source>
</trans-unit>
<trans-unit id="Your server address" xml:space="preserve">
<source>Your server address</source>
<target>Dirección de tu servidor</target>
<target>Dirección del servidor</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your settings" xml:space="preserve">
@@ -9065,7 +9105,7 @@ last received msg: %2$@</source>
</trans-unit>
<trans-unit id="Database passphrase is different from saved in the keychain." xml:space="preserve">
<source>Database passphrase is different from saved in the keychain.</source>
<target>La contraseña de la base de datos es distinta a la almacenada en keychain.</target>
<target>La contraseña de la base de datos es diferente a la almacenada en keychain.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Database passphrase is required to open chat." xml:space="preserve">
@@ -710,7 +710,7 @@
</trans-unit>
<trans-unit id="All profiles" xml:space="preserve">
<source>All profiles</source>
<note>No comment provided by engineer.</note>
<note>profile dropdown</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source>
@@ -2826,7 +2826,7 @@ This is your own one-time link!</source>
<trans-unit id="Error switching profile!" xml:space="preserve">
<source>Error switching profile!</source>
<target>Virhe profiilin vaihdossa!</target>
<note>No comment provided by engineer.</note>
<note>alertTitle</note>
</trans-unit>
<trans-unit id="Error synchronizing connection" xml:space="preserve">
<source>Error synchronizing connection</source>
@@ -2869,8 +2869,7 @@ This is your own one-time link!</source>
<trans-unit id="Error: %@" xml:space="preserve">
<source>Error: %@</source>
<target>Virhe: %@</target>
<note>file error text
snd error text</note>
<note>alert message</note>
</trans-unit>
<trans-unit id="Error: URL is invalid" xml:space="preserve">
<source>Error: URL is invalid</source>
@@ -7000,11 +6999,6 @@ Jos haluat muodostaa yhteyden, pyydä kontaktiasi luomaan toinen yhteyslinkki ja
<source>XFTP server</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You" xml:space="preserve">
<source>You</source>
<target>Sinä</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You **must not** use the same database on two devices." xml:space="preserve">
<source>You **must not** use the same database on two devices.</source>
<note>No comment provided by engineer.</note>
@@ -747,7 +747,7 @@
<trans-unit id="All profiles" xml:space="preserve">
<source>All profiles</source>
<target>Tous les profiles</target>
<note>No comment provided by engineer.</note>
<note>profile dropdown</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source>
@@ -3018,7 +3018,7 @@ Il s'agit de votre propre lien unique !</target>
<trans-unit id="Error switching profile!" xml:space="preserve">
<source>Error switching profile!</source>
<target>Erreur lors du changement de profil !</target>
<note>No comment provided by engineer.</note>
<note>alertTitle</note>
</trans-unit>
<trans-unit id="Error synchronizing connection" xml:space="preserve">
<source>Error synchronizing connection</source>
@@ -3063,8 +3063,7 @@ Il s'agit de votre propre lien unique !</target>
<trans-unit id="Error: %@" xml:space="preserve">
<source>Error: %@</source>
<target>Erreur : %@</target>
<note>file error text
snd error text</note>
<note>alert message</note>
</trans-unit>
<trans-unit id="Error: URL is invalid" xml:space="preserve">
<source>Error: URL is invalid</source>
@@ -7499,11 +7498,6 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien
<target>Serveur XFTP</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You" xml:space="preserve">
<source>You</source>
<target>Vous</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You **must not** use the same database on two devices." xml:space="preserve">
<source>You **must not** use the same database on two devices.</source>
<target>Vous **ne devez pas** utiliser la même base de données sur deux appareils.</target>
File diff suppressed because it is too large Load Diff
@@ -164,18 +164,22 @@
</trans-unit>
<trans-unit id="%d file(s) are still being downloaded." xml:space="preserve">
<source>%d file(s) are still being downloaded.</source>
<target>%d file è/sono ancora in scaricamento.</target>
<note>forward confirmation reason</note>
</trans-unit>
<trans-unit id="%d file(s) failed to download." xml:space="preserve">
<source>%d file(s) failed to download.</source>
<target>%d file ha/hanno fallito lo scaricamento.</target>
<note>forward confirmation reason</note>
</trans-unit>
<trans-unit id="%d file(s) were deleted." xml:space="preserve">
<source>%d file(s) were deleted.</source>
<target>%d file è/sono stato/i eliminato/i.</target>
<note>forward confirmation reason</note>
</trans-unit>
<trans-unit id="%d file(s) were not downloaded." xml:space="preserve">
<source>%d file(s) were not downloaded.</source>
<target>%d file non è/sono stato/i scaricato/i.</target>
<note>forward confirmation reason</note>
</trans-unit>
<trans-unit id="%d hours" xml:space="preserve">
@@ -185,6 +189,7 @@
</trans-unit>
<trans-unit id="%d messages not forwarded" xml:space="preserve">
<source>%d messages not forwarded</source>
<target>%d messaggi non inoltrati</target>
<note>alert title</note>
</trans-unit>
<trans-unit id="%d min" xml:space="preserve">
@@ -748,7 +753,7 @@
<trans-unit id="All profiles" xml:space="preserve">
<source>All profiles</source>
<target>Tutti gli profili</target>
<note>No comment provided by engineer.</note>
<note>profile dropdown</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source>
@@ -2451,6 +2456,7 @@ Questo è il tuo link una tantum!</target>
</trans-unit>
<trans-unit id="Do not use credentials with proxy." xml:space="preserve">
<source>Do not use credentials with proxy.</source>
<target>Non usare credenziali con proxy.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Don't create address" xml:space="preserve">
@@ -2496,6 +2502,7 @@ Questo è il tuo link una tantum!</target>
</trans-unit>
<trans-unit id="Download files" xml:space="preserve">
<source>Download files</source>
<target>Scarica i file</target>
<note>alert action</note>
</trans-unit>
<trans-unit id="Downloaded" xml:space="preserve">
@@ -3026,7 +3033,7 @@ Questo è il tuo link una tantum!</target>
<trans-unit id="Error switching profile!" xml:space="preserve">
<source>Error switching profile!</source>
<target>Errore nel cambio di profilo!</target>
<note>No comment provided by engineer.</note>
<note>alertTitle</note>
</trans-unit>
<trans-unit id="Error synchronizing connection" xml:space="preserve">
<source>Error synchronizing connection</source>
@@ -3071,8 +3078,7 @@ Questo è il tuo link una tantum!</target>
<trans-unit id="Error: %@" xml:space="preserve">
<source>Error: %@</source>
<target>Errore: %@</target>
<note>file error text
snd error text</note>
<note>alert message</note>
</trans-unit>
<trans-unit id="Error: URL is invalid" xml:space="preserve">
<source>Error: URL is invalid</source>
@@ -3162,6 +3168,8 @@ Questo è il tuo link una tantum!</target>
<trans-unit id="File errors:&#10;%@" xml:space="preserve">
<source>File errors:
%@</source>
<target>Errori di file:
%@</target>
<note>alert message</note>
</trans-unit>
<trans-unit id="File not found - most likely file was deleted or cancelled." xml:space="preserve">
@@ -3301,6 +3309,7 @@ Questo è il tuo link una tantum!</target>
</trans-unit>
<trans-unit id="Forward %d message(s)?" xml:space="preserve">
<source>Forward %d message(s)?</source>
<target>Inoltrare %d messaggio/i?</target>
<note>alert title</note>
</trans-unit>
<trans-unit id="Forward and save messages" xml:space="preserve">
@@ -3310,10 +3319,12 @@ Questo è il tuo link una tantum!</target>
</trans-unit>
<trans-unit id="Forward messages" xml:space="preserve">
<source>Forward messages</source>
<target>Inoltra i messaggi</target>
<note>alert action</note>
</trans-unit>
<trans-unit id="Forward messages without files?" xml:space="preserve">
<source>Forward messages without files?</source>
<target>Inoltrare i messaggi senza file?</target>
<note>alert message</note>
</trans-unit>
<trans-unit id="Forwarded" xml:space="preserve">
@@ -3328,6 +3339,7 @@ Questo è il tuo link una tantum!</target>
</trans-unit>
<trans-unit id="Forwarding %lld messages" xml:space="preserve">
<source>Forwarding %lld messages</source>
<target>Inoltro di %lld messaggi</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Forwarding server %@ failed to connect to destination server %@. Please try later." xml:space="preserve">
@@ -3626,6 +3638,7 @@ Errore: %2$@</target>
</trans-unit>
<trans-unit id="IP address" xml:space="preserve">
<source>IP address</source>
<target>Indirizzo IP</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="If you can't meet in person, show QR code in a video call, or share the link." xml:space="preserve">
@@ -4330,6 +4343,7 @@ Questo è il tuo link per il gruppo %@!</target>
</trans-unit>
<trans-unit id="Messages were deleted after you selected them." xml:space="preserve">
<source>Messages were deleted after you selected them.</source>
<target>I messaggi sono stati eliminati dopo che li hai selezionati.</target>
<note>alert message</note>
</trans-unit>
<trans-unit id="Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery." xml:space="preserve">
@@ -4629,6 +4643,7 @@ Questo è il tuo link per il gruppo %@!</target>
</trans-unit>
<trans-unit id="Nothing to forward!" xml:space="preserve">
<source>Nothing to forward!</source>
<target>Niente da inoltrare!</target>
<note>alert title</note>
</trans-unit>
<trans-unit id="Notifications" xml:space="preserve">
@@ -4857,6 +4872,8 @@ Richiede l'attivazione della VPN.</target>
<trans-unit id="Other file errors:&#10;%@" xml:space="preserve">
<source>Other file errors:
%@</source>
<target>Altri errori di file:
%@</target>
<note>alert message</note>
</trans-unit>
<trans-unit id="PING count" xml:space="preserve">
@@ -4896,6 +4913,7 @@ Richiede l'attivazione della VPN.</target>
</trans-unit>
<trans-unit id="Password" xml:space="preserve">
<source>Password</source>
<target>Password</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Password to show" xml:space="preserve">
@@ -5049,6 +5067,7 @@ Errore: %@</target>
</trans-unit>
<trans-unit id="Port" xml:space="preserve">
<source>Port</source>
<target>Porta</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Possibly, certificate fingerprint in server address is incorrect" xml:space="preserve">
@@ -5240,6 +5259,7 @@ Attivalo nelle impostazioni *Rete e server*.</target>
</trans-unit>
<trans-unit id="Proxy requires password" xml:space="preserve">
<source>Proxy requires password</source>
<target>Il proxy richiede una password</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Push notifications" xml:space="preserve">
@@ -5650,6 +5670,7 @@ Attivalo nelle impostazioni *Rete e server*.</target>
</trans-unit>
<trans-unit id="SOCKS proxy" xml:space="preserve">
<source>SOCKS proxy</source>
<target>Proxy SOCKS</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Safely receive files" xml:space="preserve">
@@ -5765,6 +5786,7 @@ Attivalo nelle impostazioni *Rete e server*.</target>
</trans-unit>
<trans-unit id="Saving %lld messages" xml:space="preserve">
<source>Saving %lld messages</source>
<target>Salvataggio di %lld messaggi</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Scale" xml:space="preserve">
@@ -7175,6 +7197,7 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e
</trans-unit>
<trans-unit id="Use SOCKS proxy" xml:space="preserve">
<source>Use SOCKS proxy</source>
<target>Usa proxy SOCKS</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use SimpleX Chat servers?" xml:space="preserve">
@@ -7254,6 +7277,7 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e
</trans-unit>
<trans-unit id="Username" xml:space="preserve">
<source>Username</source>
<target>Nome utente</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Using SimpleX Chat servers." xml:space="preserve">
@@ -7516,11 +7540,6 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e
<target>Server XFTP</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You" xml:space="preserve">
<source>You</source>
<target>Tu</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You **must not** use the same database on two devices." xml:space="preserve">
<source>You **must not** use the same database on two devices.</source>
<target>**Non devi** usare lo stesso database su due dispositivi.</target>
@@ -7902,6 +7921,7 @@ Ripetere la richiesta di connessione?</target>
</trans-unit>
<trans-unit id="Your credentials may be sent unencrypted." xml:space="preserve">
<source>Your credentials may be sent unencrypted.</source>
<target>Le credenziali potrebbero essere inviate in chiaro.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your current chat database will be DELETED and REPLACED with the imported one." xml:space="preserve">
@@ -8121,7 +8141,7 @@ Ripetere la richiesta di connessione?</target>
</trans-unit>
<trans-unit id="changed your role to %@" xml:space="preserve">
<source>changed your role to %@</source>
<target>cambiato il tuo ruolo in %@</target>
<target>ha cambiato il tuo ruolo in %@</target>
<note>rcv group event chat item</note>
</trans-unit>
<trans-unit id="changing address for %@…" xml:space="preserve">
@@ -727,7 +727,7 @@
</trans-unit>
<trans-unit id="All profiles" xml:space="preserve">
<source>All profiles</source>
<note>No comment provided by engineer.</note>
<note>profile dropdown</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source>
@@ -2851,7 +2851,7 @@ This is your own one-time link!</source>
<trans-unit id="Error switching profile!" xml:space="preserve">
<source>Error switching profile!</source>
<target>プロフィール切り替えにエラー発生!</target>
<note>No comment provided by engineer.</note>
<note>alertTitle</note>
</trans-unit>
<trans-unit id="Error synchronizing connection" xml:space="preserve">
<source>Error synchronizing connection</source>
@@ -2894,8 +2894,7 @@ This is your own one-time link!</source>
<trans-unit id="Error: %@" xml:space="preserve">
<source>Error: %@</source>
<target>エラー : %@</target>
<note>file error text
snd error text</note>
<note>alert message</note>
</trans-unit>
<trans-unit id="Error: URL is invalid" xml:space="preserve">
<source>Error: URL is invalid</source>
@@ -7018,11 +7017,6 @@ To connect, please ask your contact to create another connection link and check
<source>XFTP server</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You" xml:space="preserve">
<source>You</source>
<target>あなた</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You **must not** use the same database on two devices." xml:space="preserve">
<source>You **must not** use the same database on two devices.</source>
<note>No comment provided by engineer.</note>
@@ -164,18 +164,22 @@
</trans-unit>
<trans-unit id="%d file(s) are still being downloaded." xml:space="preserve">
<source>%d file(s) are still being downloaded.</source>
<target>%d bestand(en) worden nog gedownload.</target>
<note>forward confirmation reason</note>
</trans-unit>
<trans-unit id="%d file(s) failed to download." xml:space="preserve">
<source>%d file(s) failed to download.</source>
<target>%d bestand(en) konden niet worden gedownload.</target>
<note>forward confirmation reason</note>
</trans-unit>
<trans-unit id="%d file(s) were deleted." xml:space="preserve">
<source>%d file(s) were deleted.</source>
<target>%d bestand(en) zijn verwijderd.</target>
<note>forward confirmation reason</note>
</trans-unit>
<trans-unit id="%d file(s) were not downloaded." xml:space="preserve">
<source>%d file(s) were not downloaded.</source>
<target>%d bestand(en) zijn niet gedownload.</target>
<note>forward confirmation reason</note>
</trans-unit>
<trans-unit id="%d hours" xml:space="preserve">
@@ -185,6 +189,7 @@
</trans-unit>
<trans-unit id="%d messages not forwarded" xml:space="preserve">
<source>%d messages not forwarded</source>
<target>%d berichten niet doorgestuurd</target>
<note>alert title</note>
</trans-unit>
<trans-unit id="%d min" xml:space="preserve">
@@ -748,7 +753,7 @@
<trans-unit id="All profiles" xml:space="preserve">
<source>All profiles</source>
<target>Alle profielen</target>
<note>No comment provided by engineer.</note>
<note>profile dropdown</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source>
@@ -1473,7 +1478,7 @@
</trans-unit>
<trans-unit id="Completed" xml:space="preserve">
<source>Completed</source>
<target>voltooid</target>
<target>Voltooid</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Configure ICE servers" xml:space="preserve">
@@ -2451,6 +2456,7 @@ Dit is uw eigen eenmalige link!</target>
</trans-unit>
<trans-unit id="Do not use credentials with proxy." xml:space="preserve">
<source>Do not use credentials with proxy.</source>
<target>Gebruik geen inloggegevens met proxy.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Don't create address" xml:space="preserve">
@@ -2496,6 +2502,7 @@ Dit is uw eigen eenmalige link!</target>
</trans-unit>
<trans-unit id="Download files" xml:space="preserve">
<source>Download files</source>
<target>‐Bestanden downloaden</target>
<note>alert action</note>
</trans-unit>
<trans-unit id="Downloaded" xml:space="preserve">
@@ -3026,7 +3033,7 @@ Dit is uw eigen eenmalige link!</target>
<trans-unit id="Error switching profile!" xml:space="preserve">
<source>Error switching profile!</source>
<target>Fout bij wisselen van profiel!</target>
<note>No comment provided by engineer.</note>
<note>alertTitle</note>
</trans-unit>
<trans-unit id="Error synchronizing connection" xml:space="preserve">
<source>Error synchronizing connection</source>
@@ -3071,8 +3078,7 @@ Dit is uw eigen eenmalige link!</target>
<trans-unit id="Error: %@" xml:space="preserve">
<source>Error: %@</source>
<target>Fout: %@</target>
<note>file error text
snd error text</note>
<note>alert message</note>
</trans-unit>
<trans-unit id="Error: URL is invalid" xml:space="preserve">
<source>Error: URL is invalid</source>
@@ -3162,6 +3168,8 @@ Dit is uw eigen eenmalige link!</target>
<trans-unit id="File errors:&#10;%@" xml:space="preserve">
<source>File errors:
%@</source>
<target>Bestandsfouten:
%@</target>
<note>alert message</note>
</trans-unit>
<trans-unit id="File not found - most likely file was deleted or cancelled." xml:space="preserve">
@@ -3301,6 +3309,7 @@ Dit is uw eigen eenmalige link!</target>
</trans-unit>
<trans-unit id="Forward %d message(s)?" xml:space="preserve">
<source>Forward %d message(s)?</source>
<target>%d bericht(en) doorsturen?</target>
<note>alert title</note>
</trans-unit>
<trans-unit id="Forward and save messages" xml:space="preserve">
@@ -3310,10 +3319,12 @@ Dit is uw eigen eenmalige link!</target>
</trans-unit>
<trans-unit id="Forward messages" xml:space="preserve">
<source>Forward messages</source>
<target>Berichten doorsturen</target>
<note>alert action</note>
</trans-unit>
<trans-unit id="Forward messages without files?" xml:space="preserve">
<source>Forward messages without files?</source>
<target>Berichten doorsturen zonder bestanden?</target>
<note>alert message</note>
</trans-unit>
<trans-unit id="Forwarded" xml:space="preserve">
@@ -3328,6 +3339,7 @@ Dit is uw eigen eenmalige link!</target>
</trans-unit>
<trans-unit id="Forwarding %lld messages" xml:space="preserve">
<source>Forwarding %lld messages</source>
<target>%lld berichten doorsturen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Forwarding server %@ failed to connect to destination server %@. Please try later." xml:space="preserve">
@@ -3626,6 +3638,7 @@ Fout: %2$@</target>
</trans-unit>
<trans-unit id="IP address" xml:space="preserve">
<source>IP address</source>
<target>IP-adres</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="If you can't meet in person, show QR code in a video call, or share the link." xml:space="preserve">
@@ -4330,6 +4343,7 @@ Dit is jouw link voor groep %@!</target>
</trans-unit>
<trans-unit id="Messages were deleted after you selected them." xml:space="preserve">
<source>Messages were deleted after you selected them.</source>
<target>Berichten zijn verwijderd nadat u ze had geselecteerd.</target>
<note>alert message</note>
</trans-unit>
<trans-unit id="Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery." xml:space="preserve">
@@ -4629,6 +4643,7 @@ Dit is jouw link voor groep %@!</target>
</trans-unit>
<trans-unit id="Nothing to forward!" xml:space="preserve">
<source>Nothing to forward!</source>
<target>Niets om door te sturen!</target>
<note>alert title</note>
</trans-unit>
<trans-unit id="Notifications" xml:space="preserve">
@@ -4857,6 +4872,8 @@ Vereist het inschakelen van VPN.</target>
<trans-unit id="Other file errors:&#10;%@" xml:space="preserve">
<source>Other file errors:
%@</source>
<target>Andere bestandsfouten:
%@</target>
<note>alert message</note>
</trans-unit>
<trans-unit id="PING count" xml:space="preserve">
@@ -4896,6 +4913,7 @@ Vereist het inschakelen van VPN.</target>
</trans-unit>
<trans-unit id="Password" xml:space="preserve">
<source>Password</source>
<target>Wachtwoord</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Password to show" xml:space="preserve">
@@ -5049,6 +5067,7 @@ Fout: %@</target>
</trans-unit>
<trans-unit id="Port" xml:space="preserve">
<source>Port</source>
<target>Poort</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Possibly, certificate fingerprint in server address is incorrect" xml:space="preserve">
@@ -5240,6 +5259,7 @@ Schakel dit in in *Netwerk en servers*-instellingen.</target>
</trans-unit>
<trans-unit id="Proxy requires password" xml:space="preserve">
<source>Proxy requires password</source>
<target>Proxy vereist wachtwoord</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Push notifications" xml:space="preserve">
@@ -5650,6 +5670,7 @@ Schakel dit in in *Netwerk en servers*-instellingen.</target>
</trans-unit>
<trans-unit id="SOCKS proxy" xml:space="preserve">
<source>SOCKS proxy</source>
<target>SOCKS proxy</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Safely receive files" xml:space="preserve">
@@ -5765,6 +5786,7 @@ Schakel dit in in *Netwerk en servers*-instellingen.</target>
</trans-unit>
<trans-unit id="Saving %lld messages" xml:space="preserve">
<source>Saving %lld messages</source>
<target>%lld berichten opslaan</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Scale" xml:space="preserve">
@@ -6524,17 +6546,17 @@ Schakel dit in in *Netwerk en servers*-instellingen.</target>
</trans-unit>
<trans-unit id="Subscribed" xml:space="preserve">
<source>Subscribed</source>
<target>Ingeschreven</target>
<target>Subscribed</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Subscription errors" xml:space="preserve">
<source>Subscription errors</source>
<target>Inschrijving fouten</target>
<target>Subscription fouten</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Subscriptions ignored" xml:space="preserve">
<source>Subscriptions ignored</source>
<target>Inschrijvingen genegeerd</target>
<target>Subscriptions genegeerd</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Support SimpleX Chat" xml:space="preserve">
@@ -7174,6 +7196,7 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak
</trans-unit>
<trans-unit id="Use SOCKS proxy" xml:space="preserve">
<source>Use SOCKS proxy</source>
<target>Gebruik SOCKS proxy</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use SimpleX Chat servers?" xml:space="preserve">
@@ -7253,6 +7276,7 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak
</trans-unit>
<trans-unit id="Username" xml:space="preserve">
<source>Username</source>
<target>Gebruikersnaam</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Using SimpleX Chat servers." xml:space="preserve">
@@ -7515,11 +7539,6 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak
<target>XFTP server</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You" xml:space="preserve">
<source>You</source>
<target>Jij</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You **must not** use the same database on two devices." xml:space="preserve">
<source>You **must not** use the same database on two devices.</source>
<target>U **mag** niet dezelfde database op twee apparaten gebruiken.</target>
@@ -7901,6 +7920,7 @@ Verbindingsverzoek herhalen?</target>
</trans-unit>
<trans-unit id="Your credentials may be sent unencrypted." xml:space="preserve">
<source>Your credentials may be sent unencrypted.</source>
<target>Uw inloggegevens worden mogelijk niet-versleuteld verzonden.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your current chat database will be DELETED and REPLACED with the imported one." xml:space="preserve">
@@ -747,7 +747,7 @@
<trans-unit id="All profiles" xml:space="preserve">
<source>All profiles</source>
<target>Wszystkie profile</target>
<note>No comment provided by engineer.</note>
<note>profile dropdown</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source>
@@ -3018,7 +3018,7 @@ To jest twój jednorazowy link!</target>
<trans-unit id="Error switching profile!" xml:space="preserve">
<source>Error switching profile!</source>
<target>Błąd przełączania profilu!</target>
<note>No comment provided by engineer.</note>
<note>alertTitle</note>
</trans-unit>
<trans-unit id="Error synchronizing connection" xml:space="preserve">
<source>Error synchronizing connection</source>
@@ -3063,8 +3063,7 @@ To jest twój jednorazowy link!</target>
<trans-unit id="Error: %@" xml:space="preserve">
<source>Error: %@</source>
<target>Błąd: %@</target>
<note>file error text
snd error text</note>
<note>alert message</note>
</trans-unit>
<trans-unit id="Error: URL is invalid" xml:space="preserve">
<source>Error: URL is invalid</source>
@@ -7499,11 +7498,6 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc
<target>Serwer XFTP</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You" xml:space="preserve">
<source>You</source>
<target>Ty</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You **must not** use the same database on two devices." xml:space="preserve">
<source>You **must not** use the same database on two devices.</source>
<target>**Nie możesz** używać tej samej bazy na dwóch urządzeniach.</target>
@@ -5502,6 +5502,74 @@ Isso pode acontecer por causa de algum bug ou quando a conexão está comprometi
<source>Archived contacts</source>
<target state="translated">Contatos arquivados</target>
</trans-unit>
<trans-unit id="Cellular" xml:space="preserve" approved="no">
<source>Cellular</source>
<target state="translated">Rede móvel</target>
</trans-unit>
<trans-unit id="%d file(s) failed to download." xml:space="preserve" approved="no">
<source>%d file(s) failed to download.</source>
<target state="translated">%d arquivo(s) falharam ao ser baixados.</target>
</trans-unit>
<trans-unit id="%d file(s) were deleted." xml:space="preserve" approved="no">
<source>%d file(s) were deleted.</source>
<target state="translated">%d arquivo(s) foram apagados.</target>
</trans-unit>
<trans-unit id="%d messages not forwarded" xml:space="preserve" approved="no">
<source>%d messages not forwarded</source>
<target state="translated">%d mensagens não encaminhadas</target>
</trans-unit>
<trans-unit id="Bad desktop address" xml:space="preserve" approved="no">
<source>Bad desktop address</source>
<target state="translated">Endereço de desktop incorreto</target>
</trans-unit>
<trans-unit id="Blur for better privacy." xml:space="preserve" approved="no">
<source>Blur for better privacy.</source>
<target state="translated">Borrar para melhor privacidade.</target>
</trans-unit>
<trans-unit id="%d file(s) are still being downloaded." xml:space="preserve" approved="no">
<source>%d file(s) are still being downloaded.</source>
<target state="translated">%d arquivo(s) ainda estão sendo baixados.</target>
</trans-unit>
<trans-unit id="%d file(s) were not downloaded." xml:space="preserve" approved="no">
<source>%d file(s) were not downloaded.</source>
<target state="translated">%d arquivo(s) não foram baixados.</target>
</trans-unit>
<trans-unit id="Chat colors" xml:space="preserve" approved="no">
<source>Chat colors</source>
<target state="translated">Cores do chat</target>
</trans-unit>
<trans-unit id="%lld group events" xml:space="preserve" approved="no">
<source>%lld group events</source>
<target state="translated">%lld eventos do grupo</target>
</trans-unit>
<trans-unit id="%lld messages moderated by %@" xml:space="preserve" approved="no">
<source>%lld messages moderated by %@</source>
<target state="translated">%lld mensagens moderadas por %@</target>
</trans-unit>
<trans-unit id="%@, %@" xml:space="preserve" approved="no">
<source>%1$@, %2$@</source>
<target state="translated">%1$@, %2$@</target>
</trans-unit>
<trans-unit id="%lld new interface languages" xml:space="preserve" approved="no">
<source>%lld new interface languages</source>
<target state="translated">%lld novos idiomas de interface</target>
</trans-unit>
<trans-unit id="Better networking" xml:space="preserve" approved="no">
<source>Better networking</source>
<target state="translated">Melhores redes</target>
</trans-unit>
<trans-unit id="Bulgarian, Finnish, Thai and Ukrainian - thanks to the users and [Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" xml:space="preserve" approved="no">
<source>Bulgarian, Finnish, Thai and Ukrainian - thanks to the users and [Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!</source>
<target state="translated">Búlgaro, Finlandês, Tailandês e Ucraniano - obrigado aos usuários e [Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!</target>
</trans-unit>
<trans-unit id="Better groups" xml:space="preserve" approved="no">
<source>Better groups</source>
<target state="translated">Melhores grupos</target>
</trans-unit>
<trans-unit id="Capacity exceeded - recipient did not receive previously sent messages." xml:space="preserve" approved="no">
<source>Capacity exceeded - recipient did not receive previously sent messages.</source>
<target state="translated">Capacidade excedida - o destinatário não recebeu as mensagens enviadas anteriormente.</target>
</trans-unit>
</body>
</file>
<file original="en.lproj/SimpleX--iOS--InfoPlist.strings" source-language="en" target-language="pt-BR" datatype="plaintext">
@@ -747,7 +747,7 @@
<trans-unit id="All profiles" xml:space="preserve">
<source>All profiles</source>
<target>Все профили</target>
<note>No comment provided by engineer.</note>
<note>profile dropdown</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source>
@@ -3018,7 +3018,7 @@ This is your own one-time link!</source>
<trans-unit id="Error switching profile!" xml:space="preserve">
<source>Error switching profile!</source>
<target>Ошибка выбора профиля!</target>
<note>No comment provided by engineer.</note>
<note>alertTitle</note>
</trans-unit>
<trans-unit id="Error synchronizing connection" xml:space="preserve">
<source>Error synchronizing connection</source>
@@ -3063,8 +3063,7 @@ This is your own one-time link!</source>
<trans-unit id="Error: %@" xml:space="preserve">
<source>Error: %@</source>
<target>Ошибка: %@</target>
<note>file error text
snd error text</note>
<note>alert message</note>
</trans-unit>
<trans-unit id="Error: URL is invalid" xml:space="preserve">
<source>Error: URL is invalid</source>
@@ -7499,11 +7498,6 @@ To connect, please ask your contact to create another connection link and check
<target>XFTP сервер</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You" xml:space="preserve">
<source>You</source>
<target>Вы</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You **must not** use the same database on two devices." xml:space="preserve">
<source>You **must not** use the same database on two devices.</source>
<target>Вы **не должны** использовать одну и ту же базу данных на двух устройствах.</target>
@@ -702,7 +702,7 @@
</trans-unit>
<trans-unit id="All profiles" xml:space="preserve">
<source>All profiles</source>
<note>No comment provided by engineer.</note>
<note>profile dropdown</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source>
@@ -2811,7 +2811,7 @@ This is your own one-time link!</source>
<trans-unit id="Error switching profile!" xml:space="preserve">
<source>Error switching profile!</source>
<target>เกิดข้อผิดพลาดในการเปลี่ยนโปรไฟล์!</target>
<note>No comment provided by engineer.</note>
<note>alertTitle</note>
</trans-unit>
<trans-unit id="Error synchronizing connection" xml:space="preserve">
<source>Error synchronizing connection</source>
@@ -2854,8 +2854,7 @@ This is your own one-time link!</source>
<trans-unit id="Error: %@" xml:space="preserve">
<source>Error: %@</source>
<target>ข้อผิดพลาด: % @</target>
<note>file error text
snd error text</note>
<note>alert message</note>
</trans-unit>
<trans-unit id="Error: URL is invalid" xml:space="preserve">
<source>Error: URL is invalid</source>
@@ -6970,11 +6969,6 @@ To connect, please ask your contact to create another connection link and check
<source>XFTP server</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You" xml:space="preserve">
<source>You</source>
<target>คุณ</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You **must not** use the same database on two devices." xml:space="preserve">
<source>You **must not** use the same database on two devices.</source>
<note>No comment provided by engineer.</note>
@@ -737,7 +737,7 @@
</trans-unit>
<trans-unit id="All profiles" xml:space="preserve">
<source>All profiles</source>
<note>No comment provided by engineer.</note>
<note>profile dropdown</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source>
@@ -2942,7 +2942,7 @@ Bu senin kendi tek kullanımlık bağlantın!</target>
<trans-unit id="Error switching profile!" xml:space="preserve">
<source>Error switching profile!</source>
<target>Profil değiştirilirken hata oluştu!</target>
<note>No comment provided by engineer.</note>
<note>alertTitle</note>
</trans-unit>
<trans-unit id="Error synchronizing connection" xml:space="preserve">
<source>Error synchronizing connection</source>
@@ -2987,8 +2987,7 @@ Bu senin kendi tek kullanımlık bağlantın!</target>
<trans-unit id="Error: %@" xml:space="preserve">
<source>Error: %@</source>
<target>Hata: %@</target>
<note>file error text
snd error text</note>
<note>alert message</note>
</trans-unit>
<trans-unit id="Error: URL is invalid" xml:space="preserve">
<source>Error: URL is invalid</source>
@@ -7304,11 +7303,6 @@ Bağlanmak için lütfen kişinizden başka bir bağlantı oluşturmasını iste
<source>XFTP server</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You" xml:space="preserve">
<source>You</source>
<target>Sen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You **must not** use the same database on two devices." xml:space="preserve">
<source>You **must not** use the same database on two devices.</source>
<target>Aynı veritabanını iki cihazda **kullanmamalısınız**.</target>
@@ -747,7 +747,7 @@
<trans-unit id="All profiles" xml:space="preserve">
<source>All profiles</source>
<target>Всі профілі</target>
<note>No comment provided by engineer.</note>
<note>profile dropdown</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source>
@@ -3018,7 +3018,7 @@ This is your own one-time link!</source>
<trans-unit id="Error switching profile!" xml:space="preserve">
<source>Error switching profile!</source>
<target>Помилка перемикання профілю!</target>
<note>No comment provided by engineer.</note>
<note>alertTitle</note>
</trans-unit>
<trans-unit id="Error synchronizing connection" xml:space="preserve">
<source>Error synchronizing connection</source>
@@ -3063,8 +3063,7 @@ This is your own one-time link!</source>
<trans-unit id="Error: %@" xml:space="preserve">
<source>Error: %@</source>
<target>Помилка: %@</target>
<note>file error text
snd error text</note>
<note>alert message</note>
</trans-unit>
<trans-unit id="Error: URL is invalid" xml:space="preserve">
<source>Error: URL is invalid</source>
@@ -7499,11 +7498,6 @@ To connect, please ask your contact to create another connection link and check
<target>XFTP-сервер</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You" xml:space="preserve">
<source>You</source>
<target>Ти</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You **must not** use the same database on two devices." xml:space="preserve">
<source>You **must not** use the same database on two devices.</source>
<target>Ви **не повинні використовувати** одну і ту ж базу даних на двох пристроях.</target>
@@ -747,7 +747,7 @@
<trans-unit id="All profiles" xml:space="preserve">
<source>All profiles</source>
<target>所有配置文件</target>
<note>No comment provided by engineer.</note>
<note>profile dropdown</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source>
@@ -3018,7 +3018,7 @@ This is your own one-time link!</source>
<trans-unit id="Error switching profile!" xml:space="preserve">
<source>Error switching profile!</source>
<target>切换资料错误!</target>
<note>No comment provided by engineer.</note>
<note>alertTitle</note>
</trans-unit>
<trans-unit id="Error synchronizing connection" xml:space="preserve">
<source>Error synchronizing connection</source>
@@ -3063,8 +3063,7 @@ This is your own one-time link!</source>
<trans-unit id="Error: %@" xml:space="preserve">
<source>Error: %@</source>
<target>错误: %@</target>
<note>file error text
snd error text</note>
<note>alert message</note>
</trans-unit>
<trans-unit id="Error: URL is invalid" xml:space="preserve">
<source>Error: URL is invalid</source>
@@ -7499,11 +7498,6 @@ To connect, please ask your contact to create another connection link and check
<target>XFTP 服务器</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You" xml:space="preserve">
<source>You</source>
<target>您</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You **must not** use the same database on two devices." xml:space="preserve">
<source>You **must not** use the same database on two devices.</source>
<target>您 **不得** 在两台设备上使用相同的数据库。</target>
+46 -14
View File
@@ -26,7 +26,7 @@ enum NSENotification {
case nse(UNMutableNotificationContent)
case callkit(RcvCallInvitation)
case empty
case msgInfo(NtfMsgInfo)
case msgInfo(NtfMsgAckInfo)
var isCallInvitation: Bool {
switch self {
@@ -119,7 +119,9 @@ class NotificationService: UNNotificationServiceExtension {
var threadId: UUID? = NSEThreads.shared.newThread()
var notificationInfo: NtfMessages?
var receiveEntityId: String?
var receiveConnId: String?
var expectedMessage: String?
var allowedGetNextAttempts: Int = 3
// return true if the message is taken - it prevents sending it to another NotificationService instance for processing
var shouldProcessNtf = false
var appSubscriber: AppSubscriber?
@@ -191,17 +193,21 @@ class NotificationService: UNNotificationServiceExtension {
let dbStatus = startChat()
if case .ok = dbStatus,
let ntfInfo = apiGetNtfMessage(nonce: nonce, encNtfInfo: encNtfInfo) {
logger.debug("NotificationService: receiveNtfMessages: apiGetNtfMessage \(String(describing: ntfInfo.ntfMessage_ == nil ? 0 : 1))")
logger.debug("NotificationService: receiveNtfMessages: apiGetNtfMessage \(String(describing: ntfInfo.receivedMsg_ == nil ? 0 : 1))")
if let connEntity = ntfInfo.connEntity_ {
setBestAttemptNtf(
ntfInfo.ntfsEnabled
? .nse(createConnectionEventNtf(ntfInfo.user, connEntity))
: .empty
)
if let id = connEntity.id, ntfInfo.msgTs != nil {
if let id = connEntity.id, ntfInfo.expectedMsg_ != nil {
notificationInfo = ntfInfo
receiveEntityId = id
expectedMessage = ntfInfo.ntfMessage_.flatMap { $0.msgId }
receiveConnId = connEntity.conn.agentConnId
let expectedMsgId = ntfInfo.expectedMsg_?.msgId
let receivedMsgId = ntfInfo.receivedMsg_?.msgId
logger.debug("NotificationService: receiveNtfMessages: expectedMsgId = \(expectedMsgId ?? "nil", privacy: .private), receivedMsgId = \(receivedMsgId ?? "nil", privacy: .private)")
expectedMessage = expectedMsgId
shouldProcessNtf = true
return
}
@@ -219,22 +225,34 @@ class NotificationService: UNNotificationServiceExtension {
}
func processReceivedNtf(_ ntf: NSENotification) -> Bool {
guard let ntfInfo = notificationInfo, let msgTs = ntfInfo.msgTs else { return false }
guard let ntfInfo = notificationInfo, let expectedMsgTs = ntfInfo.expectedMsg_?.msgTs else { return false }
if !ntfInfo.user.showNotifications {
self.setBestAttemptNtf(.empty)
}
if case let .msgInfo(info) = ntf {
if info.msgId == expectedMessage {
expectedMessage = nil
logger.debug("NotificationService processNtf: msgInfo")
logger.debug("NotificationService processNtf: msgInfo msgId = \(info.msgId, privacy: .private): expected")
self.deliverBestAttemptNtf()
return true
} else if info.msgTs > msgTs {
logger.debug("NotificationService processNtf: unexpected msgInfo, let other instance to process it, stopping this one")
} else if let msgTs = info.msgTs_, msgTs > expectedMsgTs {
logger.debug("NotificationService processNtf: msgInfo msgId = \(info.msgId, privacy: .private): unexpected msgInfo, let other instance to process it, stopping this one")
self.deliverBestAttemptNtf()
return false
} else if allowedGetNextAttempts > 0, let receiveConnId = receiveConnId {
logger.debug("NotificationService processNtf: msgInfo msgId = \(info.msgId, privacy: .private): unexpected msgInfo, get next message")
allowedGetNextAttempts -= 1
if let receivedMsg = apiGetConnNtfMessage(connId: receiveConnId) {
logger.debug("NotificationService processNtf, on apiGetConnNtfMessage: msgInfo msgId = \(info.msgId, privacy: .private), receivedMsg msgId = \(receivedMsg.msgId, privacy: .private)")
return true
} else {
logger.debug("NotificationService processNtf, on apiGetConnNtfMessage: msgInfo msgId = \(info.msgId, privacy: .private): no next message, deliver best attempt")
self.deliverBestAttemptNtf()
return false
}
} else {
logger.debug("NotificationService processNtf: unknown message, let other instance to process it")
logger.debug("NotificationService processNtf: msgInfo msgId = \(info.msgId, privacy: .private): unknown message, let other instance to process it")
self.deliverBestAttemptNtf()
return false
}
} else if ntfInfo.user.showNotifications {
@@ -692,9 +710,9 @@ func apiGetNtfMessage(nonce: String, encNtfInfo: String) -> NtfMessages? {
return nil
}
let r = sendSimpleXCmd(.apiGetNtfMessage(nonce: nonce, encNtfInfo: encNtfInfo))
if case let .ntfMessages(user, connEntity_, msgTs, ntfMessage_) = r, let user = user {
logger.debug("apiGetNtfMessage response ntfMessages: \(ntfMessage_ == nil ? 0 : 1)")
return NtfMessages(user: user, connEntity_: connEntity_, msgTs: msgTs, ntfMessage_: ntfMessage_)
if case let .ntfMessages(user, connEntity_, expectedMsg_, receivedMsg_) = r, let user = user {
logger.debug("apiGetNtfMessage response ntfMessages: \(receivedMsg_ == nil ? 0 : 1)")
return NtfMessages(user: user, connEntity_: connEntity_, expectedMsg_: expectedMsg_, receivedMsg_: receivedMsg_)
} else if case let .chatCmdError(_, error) = r {
logger.debug("apiGetNtfMessage error response: \(String.init(describing: error))")
} else {
@@ -703,6 +721,20 @@ func apiGetNtfMessage(nonce: String, encNtfInfo: String) -> NtfMessages? {
return nil
}
func apiGetConnNtfMessage(connId: String) -> NtfMsgInfo? {
guard apiGetActiveUser() != nil else {
logger.debug("no active user")
return nil
}
let r = sendSimpleXCmd(.apiGetConnNtfMessage(connId: connId))
if case let .connNtfMessage(receivedMsg_) = r {
logger.debug("apiGetConnNtfMessage response receivedMsg_: \(receivedMsg_ == nil ? 0 : 1)")
return receivedMsg_
}
logger.debug("apiGetConnNtfMessage error: \(responseError(r))")
return nil
}
func apiReceiveFile(fileId: Int64, encrypted: Bool, inline: Bool? = nil) -> AChatItem? {
let userApprovedRelays = !privacyAskToApproveRelaysGroupDefault.get()
let r = sendSimpleXCmd(.receiveFile(fileId: fileId, userApprovedRelays: userApprovedRelays, encrypted: encrypted, inline: inline))
@@ -740,8 +772,8 @@ func setNetworkConfig(_ cfg: NetCfg) throws {
struct NtfMessages {
var user: User
var connEntity_: ConnectionEntity?
var msgTs: Date?
var ntfMessage_: NtfMsgInfo?
var expectedMsg_: NtfMsgInfo?
var receivedMsg_: NtfMsgInfo?
var ntfsEnabled: Bool {
user.showNotifications && (connEntity_?.ntfsEnabled ?? false)
+3 -3
View File
@@ -417,7 +417,7 @@ fileprivate func getSharedContent(_ ip: NSItemProvider) async -> Result<SharedCo
let data = try? Data(contentsOf: url),
let image = UIImage(data: data),
let cryptoFile = saveFile(data, generateNewFileName("IMG", "gif"), encrypted: privacyEncryptLocalFilesGroupDefault.get()),
let preview = resizeImageToStrSize(image, maxDataSize: MAX_DATA_SIZE) {
let preview = await resizeImageToStrSize(image, maxDataSize: MAX_DATA_SIZE) {
.success(.image(preview: preview, cryptoFile: cryptoFile))
} else { .failure(ErrorAlert("Error preparing message")) }
@@ -425,7 +425,7 @@ fileprivate func getSharedContent(_ ip: NSItemProvider) async -> Result<SharedCo
} else {
if let image = await staticImage(),
let cryptoFile = saveImage(image),
let preview = resizeImageToStrSize(image, maxDataSize: MAX_DATA_SIZE) {
let preview = await resizeImageToStrSize(image, maxDataSize: MAX_DATA_SIZE) {
.success(.image(preview: preview, cryptoFile: cryptoFile))
} else { .failure(ErrorAlert("Error preparing message")) }
}
@@ -435,7 +435,7 @@ fileprivate func getSharedContent(_ ip: NSItemProvider) async -> Result<SharedCo
if let url = try? await inPlaceUrl(type: type),
let trancodedUrl = await transcodeVideo(from: url),
let (image, duration) = AVAsset(url: trancodedUrl).generatePreview(),
let preview = resizeImageToStrSize(image, maxDataSize: MAX_DATA_SIZE),
let preview = await resizeImageToStrSize(image, maxDataSize: MAX_DATA_SIZE),
let cryptoFile = moveTempFileFromURL(trancodedUrl) {
try? FileManager.default.removeItem(at: trancodedUrl)
return .success(.movie(preview: preview, duration: duration, cryptoFile: cryptoFile))
@@ -29,7 +29,7 @@
"Database error" = "Error en base de datos";
/* No comment provided by engineer. */
"Database passphrase is different from saved in the keychain." = "La contraseña de la base de datos es distinta a la almacenada en keychain.";
"Database passphrase is different from saved in the keychain." = "La contraseña de la base de datos es diferente a la almacenada en keychain.";
/* No comment provided by engineer. */
"Database passphrase is required to open chat." = "Se requiere la contraseña de la base de datos para abrir la aplicación.";
@@ -26,13 +26,13 @@
"Database encrypted!" = "Adatbázis titkosítva!";
/* No comment provided by engineer. */
"Database error" = "Adatbázis hiba";
"Database error" = "Adatbázishiba";
/* No comment provided by engineer. */
"Database passphrase is different from saved in the keychain." = "Az adatbázis jelmondata eltér a kulcstartóban lévőtől.";
/* No comment provided by engineer. */
"Database passphrase is required to open chat." = "Adatbázis jelmondat szükséges a csevegés megnyitásához.";
"Database passphrase is required to open chat." = "Adatbázis-jelmondat szükséges a csevegés megnyitásához.";
/* No comment provided by engineer. */
"Database upgrade required" = "Adatbázis fejlesztése szükséges";
@@ -50,7 +50,7 @@
"File error" = "Fájlhiba";
/* No comment provided by engineer. */
"Incompatible database version" = "Nem kompatibilis adatbázis verzió";
"Incompatible database version" = "Nem kompatibilis adatbázis-verzió";
/* No comment provided by engineer. */
"Invalid migration confirmation" = "Érvénytelen átköltöztetési visszaigazolás";
@@ -95,7 +95,7 @@
"Slow network?" = "Lassú internetkapcsolat?";
/* No comment provided by engineer. */
"Unknown database error: %@" = "Ismeretlen adatbázis hiba: %@";
"Unknown database error: %@" = "Ismeretlen adatbázishiba: %@";
/* No comment provided by engineer. */
"Unsupported format" = "Nem támogatott formátum";
@@ -104,7 +104,7 @@
"Wait" = "Várjon";
/* No comment provided by engineer. */
"Wrong database passphrase" = "Hibás adatbázis jelmondat";
"Wrong database passphrase" = "Hibás adatbázis-jelmondat";
/* No comment provided by engineer. */
"You can allow sharing in Privacy & Security / SimpleX Lock settings." = "A megosztást az Adatvédelem és biztonság / SimpleX-zár menüben engedélyezheti.";
+34 -30
View File
@@ -147,11 +147,6 @@
6407BA83295DA85D0082BA18 /* CIInvalidJSONView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6407BA82295DA85D0082BA18 /* CIInvalidJSONView.swift */; };
6419EC562AB8BC8B004A607A /* ContextInvitingContactMemberView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6419EC552AB8BC8B004A607A /* ContextInvitingContactMemberView.swift */; };
6419EC582AB97507004A607A /* CIMemberCreatedContactView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6419EC572AB97507004A607A /* CIMemberCreatedContactView.swift */; };
64227CFA2CAAA7C200E910A3 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64227CF52CAAA7C200E910A3 /* libgmpxx.a */; };
64227CFB2CAAA7C200E910A3 /* libHSsimplex-chat-6.1.0.4-8Sjoh2YTHoMJcEgF7NicnN.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64227CF62CAAA7C200E910A3 /* libHSsimplex-chat-6.1.0.4-8Sjoh2YTHoMJcEgF7NicnN.a */; };
64227CFC2CAAA7C200E910A3 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64227CF72CAAA7C200E910A3 /* libgmp.a */; };
64227CFD2CAAA7C200E910A3 /* libHSsimplex-chat-6.1.0.4-8Sjoh2YTHoMJcEgF7NicnN-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64227CF82CAAA7C200E910A3 /* libHSsimplex-chat-6.1.0.4-8Sjoh2YTHoMJcEgF7NicnN-ghc9.6.3.a */; };
64227CFE2CAAA7C200E910A3 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64227CF92CAAA7C200E910A3 /* libffi.a */; };
6432857C2925443C00FBE5C8 /* GroupPreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6432857B2925443C00FBE5C8 /* GroupPreferencesView.swift */; };
6440CA00288857A10062C672 /* CIEventView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6440C9FF288857A10062C672 /* CIEventView.swift */; };
6440CA03288AECA70062C672 /* AddGroupMembersView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6440CA02288AECA70062C672 /* AddGroupMembersView.swift */; };
@@ -179,6 +174,11 @@
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 */; };
64BAB0852CB417A500D7D8FD /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64BAB0802CB417A500D7D8FD /* libgmp.a */; };
64BAB0862CB417A500D7D8FD /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64BAB0812CB417A500D7D8FD /* libgmpxx.a */; };
64BAB0872CB417A500D7D8FD /* libHSsimplex-chat-6.1.0.5-KYQ48Wt5wtN69vfbmNbu15-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64BAB0822CB417A500D7D8FD /* libHSsimplex-chat-6.1.0.5-KYQ48Wt5wtN69vfbmNbu15-ghc9.6.3.a */; };
64BAB0882CB417A500D7D8FD /* libHSsimplex-chat-6.1.0.5-KYQ48Wt5wtN69vfbmNbu15.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64BAB0832CB417A500D7D8FD /* libHSsimplex-chat-6.1.0.5-KYQ48Wt5wtN69vfbmNbu15.a */; };
64BAB0892CB417A500D7D8FD /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64BAB0842CB417A500D7D8FD /* libffi.a */; };
64C06EB52A0A4A7C00792D4D /* ChatItemInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64C06EB42A0A4A7C00792D4D /* ChatItemInfoView.swift */; };
64C3B0212A0D359700E19930 /* CustomTimePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64C3B0202A0D359700E19930 /* CustomTimePicker.swift */; };
64D0C2C029F9688300B38D5F /* UserAddressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64D0C2BF29F9688300B38D5F /* UserAddressView.swift */; };
@@ -221,6 +221,7 @@
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 */; };
D741547829AF89AF0022400A /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D741547729AF89AF0022400A /* StoreKit.framework */; };
@@ -493,11 +494,6 @@
6407BA82295DA85D0082BA18 /* CIInvalidJSONView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIInvalidJSONView.swift; sourceTree = "<group>"; };
6419EC552AB8BC8B004A607A /* ContextInvitingContactMemberView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextInvitingContactMemberView.swift; sourceTree = "<group>"; };
6419EC572AB97507004A607A /* CIMemberCreatedContactView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIMemberCreatedContactView.swift; sourceTree = "<group>"; };
64227CF52CAAA7C200E910A3 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = "<group>"; };
64227CF62CAAA7C200E910A3 /* libHSsimplex-chat-6.1.0.4-8Sjoh2YTHoMJcEgF7NicnN.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.1.0.4-8Sjoh2YTHoMJcEgF7NicnN.a"; sourceTree = "<group>"; };
64227CF72CAAA7C200E910A3 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = "<group>"; };
64227CF82CAAA7C200E910A3 /* libHSsimplex-chat-6.1.0.4-8Sjoh2YTHoMJcEgF7NicnN-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.1.0.4-8Sjoh2YTHoMJcEgF7NicnN-ghc9.6.3.a"; sourceTree = "<group>"; };
64227CF92CAAA7C200E910A3 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = "<group>"; };
6432857B2925443C00FBE5C8 /* GroupPreferencesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupPreferencesView.swift; sourceTree = "<group>"; };
6440C9FF288857A10062C672 /* CIEventView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIEventView.swift; sourceTree = "<group>"; };
6440CA02288AECA70062C672 /* AddGroupMembersView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddGroupMembersView.swift; sourceTree = "<group>"; };
@@ -526,6 +522,11 @@
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>"; };
64BAB0802CB417A500D7D8FD /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = "<group>"; };
64BAB0812CB417A500D7D8FD /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = "<group>"; };
64BAB0822CB417A500D7D8FD /* libHSsimplex-chat-6.1.0.5-KYQ48Wt5wtN69vfbmNbu15-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.1.0.5-KYQ48Wt5wtN69vfbmNbu15-ghc9.6.3.a"; sourceTree = "<group>"; };
64BAB0832CB417A500D7D8FD /* libHSsimplex-chat-6.1.0.5-KYQ48Wt5wtN69vfbmNbu15.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.1.0.5-KYQ48Wt5wtN69vfbmNbu15.a"; sourceTree = "<group>"; };
64BAB0842CB417A500D7D8FD /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; 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>"; };
64D0C2BF29F9688300B38D5F /* UserAddressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAddressView.swift; sourceTree = "<group>"; };
@@ -568,6 +569,7 @@
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; };
D741547929AF90B00022400A /* PushKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PushKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS16.1.sdk/System/Library/Frameworks/PushKit.framework; sourceTree = DEVELOPER_DIR; };
@@ -663,14 +665,14 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
64227CFA2CAAA7C200E910A3 /* libgmpxx.a in Frameworks */,
64BAB0882CB417A500D7D8FD /* libHSsimplex-chat-6.1.0.5-KYQ48Wt5wtN69vfbmNbu15.a in Frameworks */,
5CE2BA93284534B000EC33A6 /* libiconv.tbd in Frameworks */,
64227CFD2CAAA7C200E910A3 /* libHSsimplex-chat-6.1.0.4-8Sjoh2YTHoMJcEgF7NicnN-ghc9.6.3.a in Frameworks */,
64227CFE2CAAA7C200E910A3 /* libffi.a in Frameworks */,
64BAB0862CB417A500D7D8FD /* libgmpxx.a in Frameworks */,
64BAB0892CB417A500D7D8FD /* libffi.a in Frameworks */,
5CE2BA94284534BB00EC33A6 /* libz.tbd in Frameworks */,
64227CFB2CAAA7C200E910A3 /* libHSsimplex-chat-6.1.0.4-8Sjoh2YTHoMJcEgF7NicnN.a in Frameworks */,
64227CFC2CAAA7C200E910A3 /* libgmp.a in Frameworks */,
64BAB0852CB417A500D7D8FD /* libgmp.a in Frameworks */,
CE38A29C2C3FCD72005ED185 /* SwiftyGif in Frameworks */,
64BAB0872CB417A500D7D8FD /* libHSsimplex-chat-6.1.0.5-KYQ48Wt5wtN69vfbmNbu15-ghc9.6.3.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -747,11 +749,11 @@
5C764E5C279C70B7000C6508 /* Libraries */ = {
isa = PBXGroup;
children = (
64227CF92CAAA7C200E910A3 /* libffi.a */,
64227CF72CAAA7C200E910A3 /* libgmp.a */,
64227CF52CAAA7C200E910A3 /* libgmpxx.a */,
64227CF82CAAA7C200E910A3 /* libHSsimplex-chat-6.1.0.4-8Sjoh2YTHoMJcEgF7NicnN-ghc9.6.3.a */,
64227CF62CAAA7C200E910A3 /* libHSsimplex-chat-6.1.0.4-8Sjoh2YTHoMJcEgF7NicnN.a */,
64BAB0842CB417A500D7D8FD /* libffi.a */,
64BAB0802CB417A500D7D8FD /* libgmp.a */,
64BAB0812CB417A500D7D8FD /* libgmpxx.a */,
64BAB0822CB417A500D7D8FD /* libHSsimplex-chat-6.1.0.5-KYQ48Wt5wtN69vfbmNbu15-ghc9.6.3.a */,
64BAB0832CB417A500D7D8FD /* libHSsimplex-chat-6.1.0.5-KYQ48Wt5wtN69vfbmNbu15.a */,
);
path = Libraries;
sourceTree = "<group>";
@@ -809,6 +811,7 @@
CE7548092C622630009579B7 /* SwipeLabel.swift */,
CE176F1F2C87014C00145DBC /* InvertedForegroundStyle.swift */,
CEDB245A2C9CD71800FBC5F6 /* StickyScrollView.swift */,
CEFB2EDE2CA1BCC7004B1ECE /* SheetRepresentable.swift */,
);
path = Helpers;
sourceTree = "<group>";
@@ -1459,6 +1462,7 @@
5CB634B129E5EFEA0066AD6B /* PasscodeView.swift in Sources */,
8C69FE7D2B8C7D2700267E38 /* AppSettings.swift in Sources */,
5C2E260F27A30FDC00F70299 /* ChatView.swift in Sources */,
CEFB2EDF2CA1BCC7004B1ECE /* SheetRepresentable.swift in Sources */,
5C2E260B27A30CFA00F70299 /* ChatListView.swift in Sources */,
6442E0BA287F169300CEC0F9 /* AddGroupView.swift in Sources */,
5CF937232B2503D000E1D781 /* NSESubscriber.swift in Sources */,
@@ -1905,7 +1909,7 @@
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 240;
CURRENT_PROJECT_VERSION = 241;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
@@ -1954,7 +1958,7 @@
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 240;
CURRENT_PROJECT_VERSION = 241;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
@@ -1995,7 +1999,7 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 240;
CURRENT_PROJECT_VERSION = 241;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
@@ -2015,7 +2019,7 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 240;
CURRENT_PROJECT_VERSION = 241;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
@@ -2040,7 +2044,7 @@
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 240;
CURRENT_PROJECT_VERSION = 241;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
GCC_OPTIMIZATION_LEVEL = s;
@@ -2077,7 +2081,7 @@
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 240;
CURRENT_PROJECT_VERSION = 241;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
ENABLE_CODE_COVERAGE = NO;
@@ -2114,7 +2118,7 @@
CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES;
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 240;
CURRENT_PROJECT_VERSION = 241;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
DYLIB_COMPATIBILITY_VERSION = 1;
@@ -2165,7 +2169,7 @@
CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES;
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 240;
CURRENT_PROJECT_VERSION = 241;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
DYLIB_COMPATIBILITY_VERSION = 1;
@@ -2216,7 +2220,7 @@
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CODE_SIGN_ENTITLEMENTS = "SimpleX SE/SimpleX SE.entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 240;
CURRENT_PROJECT_VERSION = 241;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
@@ -2250,7 +2254,7 @@
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CODE_SIGN_ENTITLEMENTS = "SimpleX SE/SimpleX SE.entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 240;
CURRENT_PROJECT_VERSION = 241;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
+16 -4
View File
@@ -56,6 +56,7 @@ public enum ChatCommand {
case apiVerifyToken(token: DeviceToken, nonce: String, code: String)
case apiDeleteToken(token: DeviceToken)
case apiGetNtfMessage(nonce: String, encNtfInfo: String)
case apiGetConnNtfMessage(connId: String)
case apiNewGroup(userId: Int64, incognito: Bool, groupProfile: GroupProfile)
case apiAddMember(groupId: Int64, contactId: Int64, memberRole: GroupMemberRole)
case apiJoinGroup(groupId: Int64)
@@ -214,6 +215,7 @@ public enum ChatCommand {
case let .apiVerifyToken(token, nonce, code): return "/_ntf verify \(token.cmdString) \(nonce) \(code)"
case let .apiDeleteToken(token): return "/_ntf delete \(token.cmdString)"
case let .apiGetNtfMessage(nonce, encNtfInfo): return "/_ntf message \(nonce) \(encNtfInfo)"
case let .apiGetConnNtfMessage(connId): return "/_ntf conn message \(connId)"
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)"
@@ -368,6 +370,7 @@ public enum ChatCommand {
case .apiVerifyToken: return "apiVerifyToken"
case .apiDeleteToken: return "apiDeleteToken"
case .apiGetNtfMessage: return "apiGetNtfMessage"
case .apiGetConnNtfMessage: return "apiGetConnNtfMessage"
case .apiNewGroup: return "apiNewGroup"
case .apiAddMember: return "apiAddMember"
case .apiJoinGroup: return "apiJoinGroup"
@@ -679,8 +682,9 @@ public enum ChatResponse: Decodable, Error {
case callInvitations(callInvitations: [RcvCallInvitation])
case ntfTokenStatus(status: NtfTknStatus)
case ntfToken(token: DeviceToken, status: NtfTknStatus, ntfMode: NotificationsMode, ntfServer: String)
case ntfMessages(user_: User?, connEntity_: ConnectionEntity?, msgTs: Date?, ntfMessage_: NtfMsgInfo?)
case ntfMessage(user: UserRef, connEntity: ConnectionEntity, ntfMessage: NtfMsgInfo)
case ntfMessages(user_: User?, connEntity_: ConnectionEntity?, expectedMsg_: NtfMsgInfo?, receivedMsg_: NtfMsgInfo?)
case connNtfMessage(receivedMsg_: NtfMsgInfo?)
case ntfMessage(user: UserRef, connEntity: ConnectionEntity, ntfMessage: NtfMsgAckInfo)
case contactConnectionDeleted(user: UserRef, connection: PendingContactConnection)
case contactDisabled(user: UserRef, contact: Contact)
// remote desktop responses/events
@@ -848,6 +852,7 @@ public enum ChatResponse: Decodable, Error {
case .ntfTokenStatus: return "ntfTokenStatus"
case .ntfToken: return "ntfToken"
case .ntfMessages: return "ntfMessages"
case .connNtfMessage: return "connNtfMessage"
case .ntfMessage: return "ntfMessage"
case .contactConnectionDeleted: return "contactConnectionDeleted"
case .contactDisabled: return "contactDisabled"
@@ -1024,7 +1029,8 @@ public enum ChatResponse: Decodable, Error {
case let .callInvitations(invs): return String(describing: invs)
case let .ntfTokenStatus(status): return String(describing: status)
case let .ntfToken(token, status, ntfMode, ntfServer): return "token: \(token)\nstatus: \(status.rawValue)\nntfMode: \(ntfMode.rawValue)\nntfServer: \(ntfServer)"
case let .ntfMessages(u, connEntity, msgTs, ntfMessages): return withUser(u, "connEntity: \(String(describing: connEntity))\nmsgTs: \(String(describing: msgTs))\nntfMessages: \(String(describing: ntfMessages))")
case let .ntfMessages(u, connEntity, expectedMsg_, receivedMsg_): return withUser(u, "connEntity: \(String(describing: connEntity))\nexpectedMsg_: \(String(describing: expectedMsg_))\nreceivedMsg_: \(String(describing: receivedMsg_))")
case let .connNtfMessage(receivedMsg_): return "receivedMsg_: \(String(describing: receivedMsg_))"
case let .ntfMessage(u, connEntity, ntfMessage): return withUser(u, "connEntity: \(String(describing: connEntity))\nntfMessage: \(String(describing: ntfMessage))")
case let .contactConnectionDeleted(u, connection): return withUser(u, String(describing: connection))
case let .contactDisabled(u, contact): return withUser(u, String(describing: contact))
@@ -1353,7 +1359,7 @@ public struct NetCfg: Codable, Equatable {
public var sessionMode = TransportSessionMode.user
public var smpProxyMode: SMPProxyMode = .unknown
public var smpProxyFallback: SMPProxyFallback = .allowProtected
var smpWebPort = false
public var smpWebPort = false
public var tcpConnectTimeout: Int // microseconds
public var tcpTimeout: Int // microseconds
public var tcpTimeoutPerKb: Int // microseconds
@@ -2251,6 +2257,8 @@ public struct AppSettings: Codable, Equatable {
public var iosCallKitEnabled: Bool? = nil
public var iosCallKitCallsInRecents: Bool? = nil
public var uiProfileImageCornerRadius: Double? = nil
public var uiChatItemRoundness: Double? = nil
public var uiChatItemTail: Bool? = nil
public var uiColorScheme: String? = nil
public var uiDarkColorScheme: String? = nil
public var uiCurrentThemeIds: [String: String]? = nil
@@ -2283,6 +2291,8 @@ public struct AppSettings: Codable, Equatable {
if iosCallKitEnabled != def.iosCallKitEnabled { empty.iosCallKitEnabled = iosCallKitEnabled }
if iosCallKitCallsInRecents != def.iosCallKitCallsInRecents { empty.iosCallKitCallsInRecents = iosCallKitCallsInRecents }
if uiProfileImageCornerRadius != def.uiProfileImageCornerRadius { empty.uiProfileImageCornerRadius = uiProfileImageCornerRadius }
if uiChatItemRoundness != def.uiChatItemRoundness { empty.uiChatItemRoundness = uiChatItemRoundness }
if uiChatItemTail != def.uiChatItemTail { empty.uiChatItemTail = uiChatItemTail }
if uiColorScheme != def.uiColorScheme { empty.uiColorScheme = uiColorScheme }
if uiDarkColorScheme != def.uiDarkColorScheme { empty.uiDarkColorScheme = uiDarkColorScheme }
if uiCurrentThemeIds != def.uiCurrentThemeIds { empty.uiCurrentThemeIds = uiCurrentThemeIds }
@@ -2316,6 +2326,8 @@ public struct AppSettings: Codable, Equatable {
iosCallKitEnabled: true,
iosCallKitCallsInRecents: false,
uiProfileImageCornerRadius: 22.5,
uiChatItemRoundness: 0.75,
uiChatItemTail: true,
uiColorScheme: DefaultTheme.SYSTEM_THEME_NAME,
uiDarkColorScheme: DefaultTheme.SIMPLEX.themeName,
uiCurrentThemeIds: nil as [String: String]?,
+1
View File
@@ -357,6 +357,7 @@ public func getNetCfg() -> NetCfg {
sessionMode: sessionMode,
smpProxyMode: smpProxyMode,
smpProxyFallback: smpProxyFallback,
smpWebPort: false,
tcpConnectTimeout: tcpConnectTimeout,
tcpTimeout: tcpTimeout,
tcpTimeoutPerKb: tcpTimeoutPerKb,
+26 -11
View File
@@ -2240,32 +2240,42 @@ public struct MemberSubError: Decodable, Hashable {
}
public enum ConnectionEntity: Decodable, Hashable {
case rcvDirectMsgConnection(contact: Contact?)
case rcvGroupMsgConnection(groupInfo: GroupInfo, groupMember: GroupMember)
case sndFileConnection(sndFileTransfer: SndFileTransfer)
case rcvFileConnection(rcvFileTransfer: RcvFileTransfer)
case userContactConnection(userContact: UserContact)
case rcvDirectMsgConnection(entityConnection: Connection, contact: Contact?)
case rcvGroupMsgConnection(entityConnection: Connection, groupInfo: GroupInfo, groupMember: GroupMember)
case sndFileConnection(entityConnection: Connection, sndFileTransfer: SndFileTransfer)
case rcvFileConnection(entityConnection: Connection, rcvFileTransfer: RcvFileTransfer)
case userContactConnection(entityConnection: Connection, userContact: UserContact)
public var id: String? {
switch self {
case let .rcvDirectMsgConnection(contact):
case let .rcvDirectMsgConnection(_, contact):
return contact?.id
case let .rcvGroupMsgConnection(_, groupMember):
case let .rcvGroupMsgConnection(_, _, groupMember):
return groupMember.id
case let .userContactConnection(userContact):
case let .userContactConnection(_, userContact):
return userContact.id
default:
return nil
}
}
public var conn: Connection {
switch self {
case let .rcvDirectMsgConnection(entityConnection, _): entityConnection
case let .rcvGroupMsgConnection(entityConnection, _, _): entityConnection
case let .sndFileConnection(entityConnection, _): entityConnection
case let .rcvFileConnection(entityConnection, _): entityConnection
case let .userContactConnection(entityConnection, _): entityConnection
}
}
public var ntfsEnabled: Bool {
switch self {
case let .rcvDirectMsgConnection(contact): return contact?.chatSettings.enableNtfs == .all
case let .rcvGroupMsgConnection(groupInfo, _): return groupInfo.chatSettings.enableNtfs == .all
case let .rcvDirectMsgConnection(_, contact): return contact?.chatSettings.enableNtfs == .all
case let .rcvGroupMsgConnection(_, groupInfo, _): return groupInfo.chatSettings.enableNtfs == .all
case .sndFileConnection: return false
case .rcvFileConnection: return false
case let .userContactConnection(userContact): return userContact.groupId == nil
case let .userContactConnection(_, userContact): return userContact.groupId == nil
}
}
}
@@ -2275,6 +2285,11 @@ public struct NtfMsgInfo: Decodable, Hashable {
public var msgTs: Date
}
public struct NtfMsgAckInfo: Decodable, Hashable {
public var msgId: String
public var msgTs_: Date?
}
public struct ChatItemDeletion: Decodable, Hashable {
public var deletedChatItem: AChatItem
public var toChatItem: AChatItem? = nil
+10 -2
View File
@@ -100,7 +100,7 @@ public func resizeImageToDataSize(_ image: UIImage, maxDataSize: Int64, hasAlpha
return data
}
public func resizeImageToStrSize(_ image: UIImage, maxDataSize: Int64) -> String? {
public func resizeImageToStrSizeSync(_ image: UIImage, maxDataSize: Int64) -> String? {
var img = image
let hasAlpha = imageHasAlpha(image)
var str = compressImageStr(img, hasAlpha: hasAlpha)
@@ -116,7 +116,15 @@ public func resizeImageToStrSize(_ image: UIImage, maxDataSize: Int64) -> String
return str
}
public func resizeImageToStrSize(_ image: UIImage, maxDataSize: Int64) async -> String? {
resizeImageToStrSizeSync(image, maxDataSize: maxDataSize)
}
public func compressImageStr(_ image: UIImage, _ compressionQuality: CGFloat = 0.85, hasAlpha: Bool) -> String? {
// // Heavy workload to verify if UI gets blocked by the call
// for i in 0..<100 {
// print(image.jpegData(compressionQuality: Double(i) / 100)?.count ?? 0, terminator: ", ")
// }
let ext = hasAlpha ? "png" : "jpg"
if let data = hasAlpha ? image.pngData() : image.jpegData(compressionQuality: compressionQuality) {
return "data:image/\(ext);base64,\(data.base64EncodedString())"
@@ -426,7 +434,7 @@ public func getLinkPreview(url: URL, cb: @escaping (LinkPreview?) -> Void) {
logger.error("Couldn't load image preview from link metadata with error: \(error.localizedDescription)")
} else {
if let image = object as? UIImage,
let resized = resizeImageToStrSize(image, maxDataSize: 14000),
let resized = resizeImageToStrSizeSync(image, maxDataSize: 14000),
let title = metadata.title,
let uri = metadata.originalURL {
linkPreview = LinkPreview(uri: uri, title: title, image: resized)
+2 -2
View File
@@ -94,7 +94,7 @@ public func createConnectionEventNtf(_ user: User, _ connEntity: ConnectionEntit
var body: String? = nil
var targetContentIdentifier: String? = nil
switch connEntity {
case let .rcvDirectMsgConnection(contact):
case let .rcvDirectMsgConnection(_, contact):
if let contact = contact {
title = hideContent ? contactHidden : "\(contact.chatViewName):"
targetContentIdentifier = contact.id
@@ -102,7 +102,7 @@ public func createConnectionEventNtf(_ user: User, _ connEntity: ConnectionEntit
title = NSLocalizedString("New contact:", comment: "notification")
}
body = NSLocalizedString("message received", comment: "notification")
case let .rcvGroupMsgConnection(groupInfo, groupMember):
case let .rcvGroupMsgConnection(_, groupInfo, groupMember):
title = groupMsgNtfTitle(groupInfo, groupMember, hideContent: hideContent)
body = NSLocalizedString("message received", comment: "notification")
targetContentIdentifier = groupInfo.id
+2 -6
View File
@@ -1732,7 +1732,7 @@
/* No comment provided by engineer. */
"Error stopping chat" = "Грешка при спиране на чата";
/* No comment provided by engineer. */
/* alertTitle */
"Error switching profile!" = "Грешка при смяна на профил!";
/* No comment provided by engineer. */
@@ -1759,8 +1759,7 @@
/* No comment provided by engineer. */
"Error: " = "Грешка: ";
/* file error text
snd error text */
/* alert message */
"Error: %@" = "Грешка: %@";
/* No comment provided by engineer. */
@@ -4167,9 +4166,6 @@
/* No comment provided by engineer. */
"you" = "вие";
/* No comment provided by engineer. */
"You" = "Вие";
/* No comment provided by engineer. */
"You **must not** use the same database on two devices." = "**Не трябва** да използвате една и съща база данни на две устройства.";
+2 -6
View File
@@ -1422,7 +1422,7 @@
/* No comment provided by engineer. */
"Error stopping chat" = "Chyba při zastavení chatu";
/* No comment provided by engineer. */
/* alertTitle */
"Error switching profile!" = "Chyba při přepínání profilu!";
/* No comment provided by engineer. */
@@ -1443,8 +1443,7 @@
/* No comment provided by engineer. */
"Error: " = "Chyba: ";
/* file error text
snd error text */
/* alert message */
"Error: %@" = "Chyba: %@";
/* No comment provided by engineer. */
@@ -3350,9 +3349,6 @@
/* pref value */
"yes" = "ano";
/* No comment provided by engineer. */
"You" = "Vy";
/* No comment provided by engineer. */
"You accepted connection" = "Přijali jste spojení";
+77 -9
View File
@@ -175,9 +175,24 @@
/* time interval */
"%d days" = "%d Tage";
/* forward confirmation reason */
"%d file(s) are still being downloaded." = "%d Datei(en) wird/werden immer noch heruntergeladen.";
/* forward confirmation reason */
"%d file(s) failed to download." = "Bei %d Datei(en) ist das Herunterladen fehlgeschlagen.";
/* forward confirmation reason */
"%d file(s) were deleted." = "%d Datei(en) wurde(n) gelöscht.";
/* forward confirmation reason */
"%d file(s) were not downloaded." = "%d Datei(en) wurde(n) nicht heruntergeladen.";
/* time interval */
"%d hours" = "%d Stunden";
/* alert title */
"%d messages not forwarded" = "%d Nachrichten wurden nicht weitergeleitet";
/* time interval */
"%d min" = "%d min";
@@ -457,7 +472,7 @@
/* No comment provided by engineer. */
"All new messages from %@ will be hidden!" = "Von %@ werden alle neuen Nachrichten ausgeblendet!";
/* No comment provided by engineer. */
/* profile dropdown */
"All profiles" = "Alle Profile";
/* No comment provided by engineer. */
@@ -1188,7 +1203,7 @@
"Core version: v%@" = "Core Version: v%@";
/* No comment provided by engineer. */
"Corner" = "Ecke";
"Corner" = "Ecken-Abrundung";
/* No comment provided by engineer. */
"Correct name to %@?" = "Richtiger Name für %@?";
@@ -1623,6 +1638,9 @@
/* No comment provided by engineer. */
"Do NOT send messages directly, even if your or destination server does not support private routing." = "Nachrichten werden nicht direkt versendet, selbst wenn Ihr oder der Zielserver kein privates Routing unterstützt.";
/* No comment provided by engineer. */
"Do not use credentials with proxy." = "Verwenden Sie keine Anmeldeinformationen mit einem Proxy.";
/* No comment provided by engineer. */
"Do NOT use private routing." = "Sie nutzen KEIN privates Routing.";
@@ -1654,6 +1672,9 @@
/* server test step */
"Download file" = "Datei herunterladen";
/* alert action */
"Download files" = "Dateien herunterladen";
/* No comment provided by engineer. */
"Downloaded" = "Heruntergeladen";
@@ -2020,7 +2041,7 @@
/* No comment provided by engineer. */
"Error switching profile" = "Fehler beim Wechseln des Profils";
/* No comment provided by engineer. */
/* alertTitle */
"Error switching profile!" = "Fehler beim Umschalten des Profils!";
/* No comment provided by engineer. */
@@ -2047,8 +2068,7 @@
/* No comment provided by engineer. */
"Error: " = "Fehler: ";
/* file error text
snd error text */
/* alert message */
"Error: %@" = "Fehler: %@";
/* No comment provided by engineer. */
@@ -2108,6 +2128,9 @@
/* No comment provided by engineer. */
"File error" = "Datei-Fehler";
/* alert message */
"File errors:\n%@" = "Datei-Fehler:\n%@";
/* file error text */
"File not found - most likely file was deleted or cancelled." = "Datei nicht gefunden - höchstwahrscheinlich wurde die Datei gelöscht oder der Transfer abgebrochen.";
@@ -2189,9 +2212,18 @@
/* chat item action */
"Forward" = "Weiterleiten";
/* alert title */
"Forward %d message(s)?" = "%d Nachricht(en) weiterleiten?";
/* No comment provided by engineer. */
"Forward and save messages" = "Nachrichten weiterleiten und speichern";
/* alert action */
"Forward messages" = "Nachrichten weiterleiten";
/* alert message */
"Forward messages without files?" = "Nachrichten ohne Dateien weiterleiten?";
/* No comment provided by engineer. */
"forwarded" = "weitergeleitet";
@@ -2201,6 +2233,9 @@
/* No comment provided by engineer. */
"Forwarded from" = "Weitergeleitet aus";
/* No comment provided by engineer. */
"Forwarding %lld messages" = "%lld Nachricht(en) wird/werden weitergeleitet";
/* No comment provided by engineer. */
"Forwarding server %@ failed to connect to destination server %@. Please try later." = "Weiterleitungsserver %@ konnte sich nicht mit dem Zielserver %@ verbinden. Bitte versuchen Sie es später erneut.";
@@ -2588,6 +2623,9 @@
/* No comment provided by engineer. */
"iOS Keychain will be used to securely store passphrase after you restart the app or change passphrase - it will allow receiving push notifications." = "Für die sichere Speicherung des Passworts nach dem Neustart der App und dem Wechsel des Passworts wird der iOS Schlüsselbund verwendet - dies erlaubt den Empfang von Push-Benachrichtigungen.";
/* No comment provided by engineer. */
"IP address" = "IP-Adresse";
/* No comment provided by engineer. */
"Irreversible message deletion" = "Unwiederbringliches löschen einer Nachricht";
@@ -2873,6 +2911,9 @@
/* No comment provided by engineer. */
"Messages sent" = "Gesendete Nachrichten";
/* alert message */
"Messages were deleted after you selected them." = "Die Nachrichten wurden gelöscht, nachdem Sie sie ausgewählt hatten.";
/* No comment provided by engineer. */
"Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery." = "Nachrichten, Dateien und Anrufe sind durch **Ende-zu-Ende-Verschlüsselung** mit Perfect Forward Secrecy, Ablehnung und Einbruchs-Wiederherstellung geschützt.";
@@ -3083,6 +3124,9 @@
/* No comment provided by engineer. */
"Nothing selected" = "Nichts ausgewählt";
/* alert title */
"Nothing to forward!" = "Es gibt nichts zum Weiterleiten!";
/* No comment provided by engineer. */
"Notifications" = "Benachrichtigungen";
@@ -3235,6 +3279,9 @@
/* No comment provided by engineer. */
"other errors" = "Andere Fehler";
/* alert message */
"Other file errors:\n%@" = "Andere(r) Datei-Fehler:\n%@";
/* member role */
"owner" = "Eigentümer";
@@ -3256,6 +3303,9 @@
/* No comment provided by engineer. */
"Passcode set!" = "Zugangscode eingestellt!";
/* No comment provided by engineer. */
"Password" = "Passwort";
/* No comment provided by engineer. */
"Password to show" = "Passwort anzeigen";
@@ -3352,6 +3402,9 @@
/* No comment provided by engineer. */
"Polish interface" = "Polnische Bedienoberfläche";
/* No comment provided by engineer. */
"Port" = "Port";
/* server test error */
"Possibly, certificate fingerprint in server address is incorrect" = "Der Fingerabdruck des Zertifikats in der Serveradresse ist wahrscheinlich ungültig";
@@ -3463,6 +3516,9 @@
/* No comment provided by engineer. */
"Proxied servers" = "Proxy-Server";
/* No comment provided by engineer. */
"Proxy requires password" = "Der Proxy benötigt ein Passwort";
/* No comment provided by engineer. */
"Push notifications" = "Push-Benachrichtigungen";
@@ -3804,6 +3860,9 @@
/* No comment provided by engineer. */
"Saved WebRTC ICE servers will be removed" = "Gespeicherte WebRTC ICE-Server werden entfernt";
/* No comment provided by engineer. */
"Saving %lld messages" = "Es wird/werden %lld Nachricht(en) gesichert";
/* No comment provided by engineer. */
"Scale" = "Skalieren";
@@ -4209,6 +4268,9 @@
/* No comment provided by engineer. */
"SMP server" = "SMP-Server";
/* No comment provided by engineer. */
"SOCKS proxy" = "SOCKS-Proxy";
/* blur media */
"Soft" = "Weich";
@@ -4315,7 +4377,7 @@
"System authentication" = "System-Authentifizierung";
/* No comment provided by engineer. */
"Tail" = "Sprechblase";
"Tail" = "Sprechblasen-Format";
/* No comment provided by engineer. */
"Take picture" = "Machen Sie ein Foto";
@@ -4743,6 +4805,9 @@
/* No comment provided by engineer. */
"Use SimpleX Chat servers?" = "Verwenden Sie SimpleX-Chat-Server?";
/* No comment provided by engineer. */
"Use SOCKS proxy" = "SOCKS-Proxy nutzen";
/* No comment provided by engineer. */
"Use the app while in the call." = "Die App kann während eines Anrufs genutzt werden.";
@@ -4755,6 +4820,9 @@
/* No comment provided by engineer. */
"User selection" = "Benutzer-Auswahl";
/* No comment provided by engineer. */
"Username" = "Benutzername";
/* No comment provided by engineer. */
"Using SimpleX Chat servers." = "Verwendung von SimpleX-Chat-Servern.";
@@ -4956,9 +5024,6 @@
/* No comment provided by engineer. */
"you" = "Profil";
/* No comment provided by engineer. */
"You" = "Profil";
/* No comment provided by engineer. */
"You **must not** use the same database on two devices." = "Sie dürfen die selbe Datenbank **nicht** auf zwei Geräten nutzen.";
@@ -5211,6 +5276,9 @@
/* No comment provided by engineer. */
"Your contacts will remain connected." = "Ihre Kontakte bleiben weiterhin verbunden.";
/* No comment provided by engineer. */
"Your credentials may be sent unencrypted." = "Ihre Anmeldeinformationen können unverschlüsselt versendet werden.";
/* No comment provided by engineer. */
"Your current chat database will be DELETED and REPLACED with the imported one." = "Ihre aktuelle Chat-Datenbank wird GELÖSCHT und durch die Importierte ERSETZT.";
+142 -14
View File
@@ -160,6 +160,9 @@
/* notification title */
"%@ wants to connect!" = "¡ %@ quiere contactar!";
/* format for date separator in chat */
"%@, %@" = "%1$@, %2$@";
/* No comment provided by engineer. */
"%@, %@ and %lld members" = "%@, %@ y %lld miembro(s) más";
@@ -172,9 +175,24 @@
/* time interval */
"%d days" = "%d días";
/* forward confirmation reason */
"%d file(s) are still being downloaded." = "%d archivo(s) se está(n) descargando todavía.";
/* forward confirmation reason */
"%d file(s) failed to download." = "La descarga ha fallado para %d archivo(s).";
/* forward confirmation reason */
"%d file(s) were deleted." = "%d archivo(s) ha(n) sido eliminado(s).";
/* forward confirmation reason */
"%d file(s) were not downloaded." = "%d archivo(s) no se ha(n) descargado.";
/* time interval */
"%d hours" = "%d horas";
/* alert title */
"%d messages not forwarded" = "%d mensajes no enviados";
/* time interval */
"%d min" = "%d minutos";
@@ -305,7 +323,7 @@
"A new contact" = "Contacto nuevo";
/* No comment provided by engineer. */
"A new random profile will be shared." = "Se compartirá un perfil nuevo aleatorio.";
"A new random profile will be shared." = "Compartirás un perfil nuevo aleatorio.";
/* No comment provided by engineer. */
"A separate TCP connection will be used **for each chat profile you have in the app**." = "Se usará una conexión TCP independiente **por cada perfil que tengas en la aplicación**.";
@@ -454,7 +472,7 @@
/* No comment provided by engineer. */
"All new messages from %@ will be hidden!" = "¡Los mensajes nuevos de %@ estarán ocultos!";
/* No comment provided by engineer. */
/* profile dropdown */
"All profiles" = "Todos los perfiles";
/* No comment provided by engineer. */
@@ -649,6 +667,9 @@
/* No comment provided by engineer. */
"Auto-accept images" = "Aceptar imágenes automáticamente";
/* alert title */
"Auto-accept settings" = "Auto aceptar configuración";
/* No comment provided by engineer. */
"Back" = "Volver";
@@ -890,6 +911,9 @@
/* No comment provided by engineer. */
"Chat preferences" = "Preferencias de Chat";
/* alert message */
"Chat preferences were changed." = "Las preferencias del chat han sido modificadas.";
/* No comment provided by engineer. */
"Chat theme" = "Tema de chat";
@@ -1178,6 +1202,9 @@
/* No comment provided by engineer. */
"Core version: v%@" = "Versión Core: v%@";
/* No comment provided by engineer. */
"Corner" = "Esquina";
/* No comment provided by engineer. */
"Correct name to %@?" = "¿Corregir el nombre a %@?";
@@ -1305,7 +1332,7 @@
"Database passphrase & export" = "Base de datos y contraseña";
/* No comment provided by engineer. */
"Database passphrase is different from saved in the keychain." = "La contraseña es distinta a la almacenada en Keychain.";
"Database passphrase is different from saved in the keychain." = "La contraseña es diferente a la almacenada en Keychain.";
/* No comment provided by engineer. */
"Database passphrase is required to open chat." = "Para abrir la aplicación se requiere la contraseña de la base de datos.";
@@ -1594,7 +1621,7 @@
"Disconnect" = "Desconectar";
/* No comment provided by engineer. */
"Disconnect desktop?" = "¿Desconectar ordenador?";
"Disconnect desktop?" = "¿Desconectar del ordenador?";
/* No comment provided by engineer. */
"Discover and join groups" = "Descubre y únete a grupos";
@@ -1611,6 +1638,9 @@
/* No comment provided by engineer. */
"Do NOT send messages directly, even if your or destination server does not support private routing." = "NO enviar mensajes directamente incluso si tu servidor o el de destino no soportan enrutamiento privado.";
/* No comment provided by engineer. */
"Do not use credentials with proxy." = "No uses credenciales con proxy.";
/* No comment provided by engineer. */
"Do NOT use private routing." = "NO usar enrutamiento privado.";
@@ -1624,7 +1654,7 @@
"Don't enable" = "No activar";
/* No comment provided by engineer. */
"Don't show again" = "No mostrar de nuevo";
"Don't show again" = "No volver a mostrar";
/* No comment provided by engineer. */
"Downgrade and open chat" = "Degradar y abrir Chat";
@@ -1642,6 +1672,9 @@
/* server test step */
"Download file" = "Descargar archivo";
/* alert action */
"Download files" = "Descargar archivos";
/* No comment provided by engineer. */
"Downloaded" = "Descargado";
@@ -1858,12 +1891,18 @@
/* No comment provided by engineer. */
"Error changing address" = "Error al cambiar servidor";
/* No comment provided by engineer. */
"Error changing connection profile" = "Error al cambiar el perfil de conexión";
/* No comment provided by engineer. */
"Error changing role" = "Error al cambiar rol";
/* No comment provided by engineer. */
"Error changing setting" = "Error cambiando configuración";
/* No comment provided by engineer. */
"Error changing to incognito!" = "¡Error al cambiar a incógnito!";
/* No comment provided by engineer. */
"Error connecting to forwarding server %@. Please try later." = "Error al conectar con el servidor de reenvío %@. Por favor, inténtalo más tarde.";
@@ -1936,6 +1975,9 @@
/* No comment provided by engineer. */
"Error loading %@ servers" = "Error al cargar servidores %@";
/* No comment provided by engineer. */
"Error migrating settings" = "Error al migrar la configuración";
/* No comment provided by engineer. */
"Error opening chat" = "Error al abrir chat";
@@ -1997,6 +2039,9 @@
"Error stopping chat" = "Error al parar SimpleX";
/* No comment provided by engineer. */
"Error switching profile" = "Error al cambiar perfil";
/* alertTitle */
"Error switching profile!" = "¡Error al cambiar perfil!";
/* No comment provided by engineer. */
@@ -2023,8 +2068,7 @@
/* No comment provided by engineer. */
"Error: " = "Error: ";
/* file error text
snd error text */
/* alert message */
"Error: %@" = "Error: %@";
/* No comment provided by engineer. */
@@ -2084,6 +2128,9 @@
/* No comment provided by engineer. */
"File error" = "Error de archivo";
/* alert message */
"File errors:\n%@" = "Error(es) de archivo\n%@";
/* file error text */
"File not found - most likely file was deleted or cancelled." = "Archivo no encontrado, probablemente haya sido borrado o cancelado.";
@@ -2165,9 +2212,18 @@
/* chat item action */
"Forward" = "Reenviar";
/* alert title */
"Forward %d message(s)?" = "¿Reenviar %d mensaje(s)?";
/* No comment provided by engineer. */
"Forward and save messages" = "Reenviar y guardar mensajes";
/* alert action */
"Forward messages" = "Reenviar mensajes";
/* alert message */
"Forward messages without files?" = "¿Reenviar mensajes sin los archivos?";
/* No comment provided by engineer. */
"forwarded" = "reenviado";
@@ -2177,6 +2233,9 @@
/* No comment provided by engineer. */
"Forwarded from" = "Reenviado por";
/* No comment provided by engineer. */
"Forwarding %lld messages" = "Reenviando %lld mensajes";
/* No comment provided by engineer. */
"Forwarding server %@ failed to connect to destination server %@. Please try later." = "El servidor de reenvío %@ no ha podido conectarse al servidor de destino %@. Por favor, intentalo más tarde.";
@@ -2205,10 +2264,10 @@
"Full name (optional)" = "Nombre completo (opcional)";
/* No comment provided by engineer. */
"Fully decentralized – visible only to members." = "Completamente descentralizado y sólo visible para los miembros.";
"Fully decentralized – visible only to members." = "Totalmente descentralizado. Visible sólo para los miembros.";
/* No comment provided by engineer. */
"Fully re-implemented - work in background!" = "Completamente reimplementado: ¡funciona en segundo plano!";
"Fully re-implemented - work in background!" = "Totalmente revisado. ¡Funciona en segundo plano!";
/* No comment provided by engineer. */
"Further reduced battery usage" = "Reducción consumo de batería";
@@ -2564,6 +2623,9 @@
/* No comment provided by engineer. */
"iOS Keychain will be used to securely store passphrase after you restart the app or change passphrase - it will allow receiving push notifications." = "iOS Keychain se usará para almacenar la contraseña de forma segura después de reiniciar la aplicación o cambiar la contraseña. Esto permitirá recibir notificaciones automáticas.";
/* No comment provided by engineer. */
"IP address" = "Dirección IP";
/* No comment provided by engineer. */
"Irreversible message deletion" = "Eliminación irreversible del mensaje";
@@ -2816,6 +2878,9 @@
/* No comment provided by engineer. */
"Message servers" = "Servidores de mensajes";
/* No comment provided by engineer. */
"Message shape" = "Forma del mensaje";
/* No comment provided by engineer. */
"Message source remains private." = "El autor del mensaje se mantiene privado.";
@@ -2846,6 +2911,9 @@
/* No comment provided by engineer. */
"Messages sent" = "Mensajes enviados";
/* alert message */
"Messages were deleted after you selected them." = "Los mensajes han sido borrados después de seleccionarlos.";
/* No comment provided by engineer. */
"Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery." = "Los mensajes, archivos y llamadas están protegidos mediante **cifrado de extremo a extremo** con secreto perfecto hacía adelante, repudio y recuperación tras ataque.";
@@ -3056,6 +3124,9 @@
/* No comment provided by engineer. */
"Nothing selected" = "Nada seleccionado";
/* alert title */
"Nothing to forward!" = "¡Nada para reenviar!";
/* No comment provided by engineer. */
"Notifications" = "Notificaciones";
@@ -3208,6 +3279,9 @@
/* No comment provided by engineer. */
"other errors" = "otros errores";
/* alert message */
"Other file errors:\n%@" = "Otro(s) error(es) de archivo.\n%@";
/* member role */
"owner" = "propietario";
@@ -3229,6 +3303,9 @@
/* No comment provided by engineer. */
"Passcode set!" = "¡Código de acceso guardado!";
/* No comment provided by engineer. */
"Password" = "Contraseña";
/* No comment provided by engineer. */
"Password to show" = "Contraseña para hacerlo visible";
@@ -3325,6 +3402,9 @@
/* No comment provided by engineer. */
"Polish interface" = "Interfaz en polaco";
/* No comment provided by engineer. */
"Port" = "Puerto";
/* server test error */
"Possibly, certificate fingerprint in server address is incorrect" = "Posiblemente la huella digital del certificado en la dirección del servidor es incorrecta";
@@ -3436,6 +3516,9 @@
/* No comment provided by engineer. */
"Proxied servers" = "Servidores con proxy";
/* No comment provided by engineer. */
"Proxy requires password" = "El proxy requiere contraseña";
/* No comment provided by engineer. */
"Push notifications" = "Notificaciones automáticas";
@@ -3581,6 +3664,9 @@
/* No comment provided by engineer. */
"Remove" = "Eliminar";
/* No comment provided by engineer. */
"Remove archive?" = "¿Eliminar archivo?";
/* No comment provided by engineer. */
"Remove image" = "Eliminar imagen";
@@ -3753,6 +3839,9 @@
/* No comment provided by engineer. */
"Save welcome message?" = "¿Guardar mensaje de bienvenida?";
/* alert title */
"Save your profile?" = "¿Guardar tu perfil?";
/* No comment provided by engineer. */
"saved" = "guardado";
@@ -3771,6 +3860,9 @@
/* No comment provided by engineer. */
"Saved WebRTC ICE servers will be removed" = "Los servidores WebRTC ICE guardados serán eliminados";
/* No comment provided by engineer. */
"Saving %lld messages" = "Guardando %lld mensajes";
/* No comment provided by engineer. */
"Scale" = "Escala";
@@ -3834,6 +3926,9 @@
/* chat item action */
"Select" = "Seleccionar";
/* No comment provided by engineer. */
"Select chat profile" = "Selecciona perfil de chat";
/* No comment provided by engineer. */
"Selected %lld" = "Seleccionados %lld";
@@ -3865,7 +3960,7 @@
"send direct message" = "Enviar mensaje directo";
/* No comment provided by engineer. */
"Send direct message to connect" = "Envia un mensaje para conectar";
"Send direct message to connect" = "Envía un mensaje para conectar";
/* No comment provided by engineer. */
"Send disappearing message" = "Enviar mensaje temporal";
@@ -4047,6 +4142,9 @@
/* No comment provided by engineer. */
"Settings" = "Configuración";
/* alert message */
"Settings were changed." = "La configuración ha sido modificada.";
/* No comment provided by engineer. */
"Shape profile images" = "Dar forma a las imágenes de perfil";
@@ -4068,6 +4166,9 @@
/* No comment provided by engineer. */
"Share link" = "Compartir enlace";
/* No comment provided by engineer. */
"Share profile" = "Comparte perfil";
/* No comment provided by engineer. */
"Share this 1-time invite link" = "Comparte este enlace de un solo uso";
@@ -4167,9 +4268,15 @@
/* No comment provided by engineer. */
"SMP server" = "Servidor SMP";
/* No comment provided by engineer. */
"SOCKS proxy" = "Proxy SOCKS";
/* blur media */
"Soft" = "Suave";
/* No comment provided by engineer. */
"Some app settings were not migrated." = "Algunas configuraciones de la app no han sido migradas.";
/* No comment provided by engineer. */
"Some file(s) were not exported:" = "Algunos archivos no han sido exportados:";
@@ -4269,6 +4376,9 @@
/* No comment provided by engineer. */
"System authentication" = "Autenticación del sistema";
/* No comment provided by engineer. */
"Tail" = "Cola";
/* No comment provided by engineer. */
"Take picture" = "Tomar foto";
@@ -4398,6 +4508,9 @@
/* No comment provided by engineer. */
"The text you pasted is not a SimpleX link." = "El texto pegado no es un enlace SimpleX.";
/* No comment provided by engineer. */
"The uploaded database archive will be permanently removed from the servers." = "El archivo de bases de datos subido será eliminado permanentemente de los servidores.";
/* No comment provided by engineer. */
"Themes" = "Temas";
@@ -4692,6 +4805,9 @@
/* No comment provided by engineer. */
"Use SimpleX Chat servers?" = "¿Usar servidores SimpleX Chat?";
/* No comment provided by engineer. */
"Use SOCKS proxy" = "Usar proxy SOCKS";
/* No comment provided by engineer. */
"Use the app while in the call." = "Usar la aplicación durante la llamada.";
@@ -4704,6 +4820,9 @@
/* No comment provided by engineer. */
"User selection" = "Selección de usuarios";
/* No comment provided by engineer. */
"Username" = "Nombre de usuario";
/* No comment provided by engineer. */
"Using SimpleX Chat servers." = "Usar servidores SimpleX Chat.";
@@ -4905,9 +5024,6 @@
/* No comment provided by engineer. */
"you" = "tu";
/* No comment provided by engineer. */
"You" = "Tú";
/* No comment provided by engineer. */
"You **must not** use the same database on two devices." = "**No debes** usar la misma base de datos en dos dispositivos.";
@@ -5142,9 +5258,15 @@
/* No comment provided by engineer. */
"Your chat database is not encrypted - set passphrase to encrypt it." = "La base de datos no está cifrada - establece una contraseña para cifrarla.";
/* alert title */
"Your chat preferences" = "Tus preferencias de chat";
/* No comment provided by engineer. */
"Your chat profiles" = "Mis perfiles";
/* No comment provided by engineer. */
"Your connection was moved to %@ but an unexpected error occurred while redirecting you to the profile." = "Tu conexión ha sido trasladada a %@ pero ha ocurrido un error inesperado al redirigirte al perfil.";
/* No comment provided by engineer. */
"Your contact sent a file that is larger than currently supported maximum size (%@)." = "El contacto ha enviado un archivo mayor al máximo admitido (%@).";
@@ -5154,6 +5276,9 @@
/* No comment provided by engineer. */
"Your contacts will remain connected." = "Tus contactos permanecerán conectados.";
/* No comment provided by engineer. */
"Your credentials may be sent unencrypted." = "Tus credenciales podrían ser enviadas sin cifrar.";
/* No comment provided by engineer. */
"Your current chat database will be DELETED and REPLACED with the imported one." = "La base de datos actual será ELIMINADA y SUSTITUIDA por la importada.";
@@ -5178,6 +5303,9 @@
/* No comment provided by engineer. */
"Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." = "Tu perfil es almacenado en tu dispositivo y solamente se comparte con tus contactos. Los servidores SimpleX no pueden ver tu perfil.";
/* alert message */
"Your profile was changed. If you save it, the updated profile will be sent to all your contacts." = "Tu perfil ha sido modificado. Si lo guardas la actualización será enviada a todos tus contactos.";
/* No comment provided by engineer. */
"Your profile, contacts and delivered messages are stored on your device." = "Tu perfil, contactos y mensajes se almacenan en tu dispositivo.";
@@ -5188,7 +5316,7 @@
"Your server" = "Tu servidor";
/* No comment provided by engineer. */
"Your server address" = "Dirección de tu servidor";
"Your server address" = "Dirección del servidor";
/* No comment provided by engineer. */
"Your settings" = "Configuración";
+2 -6
View File
@@ -1395,7 +1395,7 @@
/* No comment provided by engineer. */
"Error stopping chat" = "Virhe keskustelun lopettamisessa";
/* No comment provided by engineer. */
/* alertTitle */
"Error switching profile!" = "Virhe profiilin vaihdossa!";
/* No comment provided by engineer. */
@@ -1416,8 +1416,7 @@
/* No comment provided by engineer. */
"Error: " = "Virhe: ";
/* file error text
snd error text */
/* alert message */
"Error: %@" = "Virhe: %@";
/* No comment provided by engineer. */
@@ -3308,9 +3307,6 @@
/* pref value */
"yes" = "kyllä";
/* No comment provided by engineer. */
"You" = "Sinä";
/* No comment provided by engineer. */
"You accepted connection" = "Hyväksyit yhteyden";
+3 -7
View File
@@ -454,7 +454,7 @@
/* No comment provided by engineer. */
"All new messages from %@ will be hidden!" = "Tous les nouveaux messages de %@ seront cachés !";
/* No comment provided by engineer. */
/* profile dropdown */
"All profiles" = "Tous les profiles";
/* No comment provided by engineer. */
@@ -1996,7 +1996,7 @@
/* No comment provided by engineer. */
"Error stopping chat" = "Erreur lors de l'arrêt du chat";
/* No comment provided by engineer. */
/* alertTitle */
"Error switching profile!" = "Erreur lors du changement de profil !";
/* No comment provided by engineer. */
@@ -2023,8 +2023,7 @@
/* No comment provided by engineer. */
"Error: " = "Erreur : ";
/* file error text
snd error text */
/* alert message */
"Error: %@" = "Erreur : %@";
/* No comment provided by engineer. */
@@ -4905,9 +4904,6 @@
/* No comment provided by engineer. */
"you" = "vous";
/* No comment provided by engineer. */
"You" = "Vous";
/* No comment provided by engineer. */
"You **must not** use the same database on two devices." = "Vous **ne devez pas** utiliser la même base de données sur deux appareils.";
File diff suppressed because it is too large Load Diff
+76 -8
View File
@@ -175,9 +175,24 @@
/* time interval */
"%d days" = "%d giorni";
/* forward confirmation reason */
"%d file(s) are still being downloaded." = "%d file è/sono ancora in scaricamento.";
/* forward confirmation reason */
"%d file(s) failed to download." = "%d file ha/hanno fallito lo scaricamento.";
/* forward confirmation reason */
"%d file(s) were deleted." = "%d file è/sono stato/i eliminato/i.";
/* forward confirmation reason */
"%d file(s) were not downloaded." = "%d file non è/sono stato/i scaricato/i.";
/* time interval */
"%d hours" = "%d ore";
/* alert title */
"%d messages not forwarded" = "%d messaggi non inoltrati";
/* time interval */
"%d min" = "%d min";
@@ -457,7 +472,7 @@
/* No comment provided by engineer. */
"All new messages from %@ will be hidden!" = "Tutti i nuovi messaggi da %@ verrranno nascosti!";
/* No comment provided by engineer. */
/* profile dropdown */
"All profiles" = "Tutti gli profili";
/* No comment provided by engineer. */
@@ -849,7 +864,7 @@
"changed role of %@ to %@" = "ha cambiato il ruolo di %1$@ in %2$@";
/* rcv group event chat item */
"changed your role to %@" = "cambiato il tuo ruolo in %@";
"changed your role to %@" = "ha cambiato il tuo ruolo in %@";
/* chat item text */
"changing address for %@…" = "cambio indirizzo per %@…";
@@ -1623,6 +1638,9 @@
/* No comment provided by engineer. */
"Do NOT send messages directly, even if your or destination server does not support private routing." = "NON inviare messaggi direttamente, anche se il tuo server o quello di destinazione non supporta l'instradamento privato.";
/* No comment provided by engineer. */
"Do not use credentials with proxy." = "Non usare credenziali con proxy.";
/* No comment provided by engineer. */
"Do NOT use private routing." = "NON usare l'instradamento privato.";
@@ -1654,6 +1672,9 @@
/* server test step */
"Download file" = "Scarica file";
/* alert action */
"Download files" = "Scarica i file";
/* No comment provided by engineer. */
"Downloaded" = "Scaricato";
@@ -2020,7 +2041,7 @@
/* No comment provided by engineer. */
"Error switching profile" = "Errore nel cambio di profilo";
/* No comment provided by engineer. */
/* alertTitle */
"Error switching profile!" = "Errore nel cambio di profilo!";
/* No comment provided by engineer. */
@@ -2047,8 +2068,7 @@
/* No comment provided by engineer. */
"Error: " = "Errore: ";
/* file error text
snd error text */
/* alert message */
"Error: %@" = "Errore: %@";
/* No comment provided by engineer. */
@@ -2108,6 +2128,9 @@
/* No comment provided by engineer. */
"File error" = "Errore del file";
/* alert message */
"File errors:\n%@" = "Errori di file:\n%@";
/* file error text */
"File not found - most likely file was deleted or cancelled." = "File non trovato - probabilmente è stato eliminato o annullato.";
@@ -2189,9 +2212,18 @@
/* chat item action */
"Forward" = "Inoltra";
/* alert title */
"Forward %d message(s)?" = "Inoltrare %d messaggio/i?";
/* No comment provided by engineer. */
"Forward and save messages" = "Inoltra e salva i messaggi";
/* alert action */
"Forward messages" = "Inoltra i messaggi";
/* alert message */
"Forward messages without files?" = "Inoltrare i messaggi senza file?";
/* No comment provided by engineer. */
"forwarded" = "inoltrato";
@@ -2201,6 +2233,9 @@
/* No comment provided by engineer. */
"Forwarded from" = "Inoltrato da";
/* No comment provided by engineer. */
"Forwarding %lld messages" = "Inoltro di %lld messaggi";
/* No comment provided by engineer. */
"Forwarding server %@ failed to connect to destination server %@. Please try later." = "Il server di inoltro %@ non è riuscito a connettersi al server di destinazione %@. Riprova più tardi.";
@@ -2588,6 +2623,9 @@
/* No comment provided by engineer. */
"iOS Keychain will be used to securely store passphrase after you restart the app or change passphrase - it will allow receiving push notifications." = "Il portachiavi di iOS verrà usato per archiviare in modo sicuro la password dopo il riavvio dell'app o la modifica della password; consentirà di ricevere notifiche push.";
/* No comment provided by engineer. */
"IP address" = "Indirizzo IP";
/* No comment provided by engineer. */
"Irreversible message deletion" = "Eliminazione irreversibile del messaggio";
@@ -2873,6 +2911,9 @@
/* No comment provided by engineer. */
"Messages sent" = "Messaggi inviati";
/* alert message */
"Messages were deleted after you selected them." = "I messaggi sono stati eliminati dopo che li hai selezionati.";
/* No comment provided by engineer. */
"Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery." = "I messaggi, i file e le chiamate sono protetti da **crittografia end-to-end** con perfect forward secrecy, ripudio e recupero da intrusione.";
@@ -3083,6 +3124,9 @@
/* No comment provided by engineer. */
"Nothing selected" = "Nessuna selezione";
/* alert title */
"Nothing to forward!" = "Niente da inoltrare!";
/* No comment provided by engineer. */
"Notifications" = "Notifiche";
@@ -3235,6 +3279,9 @@
/* No comment provided by engineer. */
"other errors" = "altri errori";
/* alert message */
"Other file errors:\n%@" = "Altri errori di file:\n%@";
/* member role */
"owner" = "proprietario";
@@ -3256,6 +3303,9 @@
/* No comment provided by engineer. */
"Passcode set!" = "Codice di accesso impostato!";
/* No comment provided by engineer. */
"Password" = "Password";
/* No comment provided by engineer. */
"Password to show" = "Password per mostrare";
@@ -3352,6 +3402,9 @@
/* No comment provided by engineer. */
"Polish interface" = "Interfaccia polacca";
/* No comment provided by engineer. */
"Port" = "Porta";
/* server test error */
"Possibly, certificate fingerprint in server address is incorrect" = "Probabilmente l'impronta del certificato nell'indirizzo del server è sbagliata";
@@ -3463,6 +3516,9 @@
/* No comment provided by engineer. */
"Proxied servers" = "Server via proxy";
/* No comment provided by engineer. */
"Proxy requires password" = "Il proxy richiede una password";
/* No comment provided by engineer. */
"Push notifications" = "Notifiche push";
@@ -3804,6 +3860,9 @@
/* No comment provided by engineer. */
"Saved WebRTC ICE servers will be removed" = "I server WebRTC ICE salvati verranno rimossi";
/* No comment provided by engineer. */
"Saving %lld messages" = "Salvataggio di %lld messaggi";
/* No comment provided by engineer. */
"Scale" = "Scala";
@@ -4209,6 +4268,9 @@
/* No comment provided by engineer. */
"SMP server" = "Server SMP";
/* No comment provided by engineer. */
"SOCKS proxy" = "Proxy SOCKS";
/* blur media */
"Soft" = "Leggera";
@@ -4743,6 +4805,9 @@
/* No comment provided by engineer. */
"Use SimpleX Chat servers?" = "Usare i server di SimpleX Chat?";
/* No comment provided by engineer. */
"Use SOCKS proxy" = "Usa proxy SOCKS";
/* No comment provided by engineer. */
"Use the app while in the call." = "Usa l'app mentre sei in chiamata.";
@@ -4755,6 +4820,9 @@
/* No comment provided by engineer. */
"User selection" = "Selezione utente";
/* No comment provided by engineer. */
"Username" = "Nome utente";
/* No comment provided by engineer. */
"Using SimpleX Chat servers." = "Utilizzo dei server SimpleX Chat.";
@@ -4956,9 +5024,6 @@
/* No comment provided by engineer. */
"you" = "tu";
/* No comment provided by engineer. */
"You" = "Tu";
/* No comment provided by engineer. */
"You **must not** use the same database on two devices." = "**Non devi** usare lo stesso database su due dispositivi.";
@@ -5211,6 +5276,9 @@
/* No comment provided by engineer. */
"Your contacts will remain connected." = "I tuoi contatti resteranno connessi.";
/* No comment provided by engineer. */
"Your credentials may be sent unencrypted." = "Le credenziali potrebbero essere inviate in chiaro.";
/* No comment provided by engineer. */
"Your current chat database will be DELETED and REPLACED with the imported one." = "Il tuo attuale database della chat verrà ELIMINATO e SOSTITUITO con quello importato.";
+2 -6
View File
@@ -1470,7 +1470,7 @@
/* No comment provided by engineer. */
"Error stopping chat" = "チャット停止にエラー発生";
/* No comment provided by engineer. */
/* alertTitle */
"Error switching profile!" = "プロフィール切り替えにエラー発生!";
/* No comment provided by engineer. */
@@ -1491,8 +1491,7 @@
/* No comment provided by engineer. */
"Error: " = "エラー : ";
/* file error text
snd error text */
/* alert message */
"Error: %@" = "エラー : %@";
/* No comment provided by engineer. */
@@ -3362,9 +3361,6 @@
/* pref value */
"yes" = "はい";
/* No comment provided by engineer. */
"You" = "あなた";
/* No comment provided by engineer. */
"You accepted connection" = "接続を承認しました";
+79 -11
View File
@@ -175,9 +175,24 @@
/* time interval */
"%d days" = "%d dagen";
/* forward confirmation reason */
"%d file(s) are still being downloaded." = "%d bestand(en) worden nog gedownload.";
/* forward confirmation reason */
"%d file(s) failed to download." = "%d bestand(en) konden niet worden gedownload.";
/* forward confirmation reason */
"%d file(s) were deleted." = "%d bestand(en) zijn verwijderd.";
/* forward confirmation reason */
"%d file(s) were not downloaded." = "%d bestand(en) zijn niet gedownload.";
/* time interval */
"%d hours" = "%d uren";
/* alert title */
"%d messages not forwarded" = "%d berichten niet doorgestuurd";
/* time interval */
"%d min" = "%d min";
@@ -457,7 +472,7 @@
/* No comment provided by engineer. */
"All new messages from %@ will be hidden!" = "Alle nieuwe berichten van %@ worden verborgen!";
/* No comment provided by engineer. */
/* profile dropdown */
"All profiles" = "Alle profielen";
/* No comment provided by engineer. */
@@ -963,7 +978,7 @@
"complete" = "compleet";
/* No comment provided by engineer. */
"Completed" = "voltooid";
"Completed" = "Voltooid";
/* No comment provided by engineer. */
"Configure ICE servers" = "ICE servers configureren";
@@ -1623,6 +1638,9 @@
/* No comment provided by engineer. */
"Do NOT send messages directly, even if your or destination server does not support private routing." = "Stuur GEEN berichten rechtstreeks, zelfs als uw of de bestemmingsserver geen privéroutering ondersteunt.";
/* No comment provided by engineer. */
"Do not use credentials with proxy." = "Gebruik geen inloggegevens met proxy.";
/* No comment provided by engineer. */
"Do NOT use private routing." = "Gebruik GEEN privéroutering.";
@@ -1654,6 +1672,9 @@
/* server test step */
"Download file" = "Download bestand";
/* alert action */
"Download files" = "‐Bestanden downloaden";
/* No comment provided by engineer. */
"Downloaded" = "Gedownload";
@@ -2020,7 +2041,7 @@
/* No comment provided by engineer. */
"Error switching profile" = "Fout bij wisselen van profiel";
/* No comment provided by engineer. */
/* alertTitle */
"Error switching profile!" = "Fout bij wisselen van profiel!";
/* No comment provided by engineer. */
@@ -2047,8 +2068,7 @@
/* No comment provided by engineer. */
"Error: " = "Fout: ";
/* file error text
snd error text */
/* alert message */
"Error: %@" = "Fout: %@";
/* No comment provided by engineer. */
@@ -2108,6 +2128,9 @@
/* No comment provided by engineer. */
"File error" = "Bestandsfout";
/* alert message */
"File errors:\n%@" = "Bestandsfouten:\n%@";
/* file error text */
"File not found - most likely file was deleted or cancelled." = "Bestand niet gevonden - hoogstwaarschijnlijk is het bestand verwijderd of geannuleerd.";
@@ -2189,9 +2212,18 @@
/* chat item action */
"Forward" = "Doorsturen";
/* alert title */
"Forward %d message(s)?" = "%d bericht(en) doorsturen?";
/* No comment provided by engineer. */
"Forward and save messages" = "Berichten doorsturen en opslaan";
/* alert action */
"Forward messages" = "Berichten doorsturen";
/* alert message */
"Forward messages without files?" = "Berichten doorsturen zonder bestanden?";
/* No comment provided by engineer. */
"forwarded" = "doorgestuurd";
@@ -2201,6 +2233,9 @@
/* No comment provided by engineer. */
"Forwarded from" = "Doorgestuurd vanuit";
/* No comment provided by engineer. */
"Forwarding %lld messages" = "%lld berichten doorsturen";
/* No comment provided by engineer. */
"Forwarding server %@ failed to connect to destination server %@. Please try later." = "De doorstuurserver %@ kon geen verbinding maken met de bestemmingsserver %@. Probeer het later opnieuw.";
@@ -2588,6 +2623,9 @@
/* No comment provided by engineer. */
"iOS Keychain will be used to securely store passphrase after you restart the app or change passphrase - it will allow receiving push notifications." = "iOS-keychain wordt gebruikt om het wachtwoord veilig op te slaan nadat u de app opnieuw hebt opgestart of het wachtwoord hebt gewijzigd, hiermee kunt u push meldingen ontvangen.";
/* No comment provided by engineer. */
"IP address" = "IP-adres";
/* No comment provided by engineer. */
"Irreversible message deletion" = "Onomkeerbare berichtverwijdering";
@@ -2873,6 +2911,9 @@
/* No comment provided by engineer. */
"Messages sent" = "Berichten verzonden";
/* alert message */
"Messages were deleted after you selected them." = "Berichten zijn verwijderd nadat u ze had geselecteerd.";
/* No comment provided by engineer. */
"Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery." = "Berichten, bestanden en oproepen worden beschermd door **end-to-end codering** met perfecte voorwaartse geheimhouding, afwijzing en inbraakherstel.";
@@ -3083,6 +3124,9 @@
/* No comment provided by engineer. */
"Nothing selected" = "Niets geselecteerd";
/* alert title */
"Nothing to forward!" = "Niets om door te sturen!";
/* No comment provided by engineer. */
"Notifications" = "Meldingen";
@@ -3235,6 +3279,9 @@
/* No comment provided by engineer. */
"other errors" = "overige fouten";
/* alert message */
"Other file errors:\n%@" = "Andere bestandsfouten:\n%@";
/* member role */
"owner" = "Eigenaar";
@@ -3256,6 +3303,9 @@
/* No comment provided by engineer. */
"Passcode set!" = "Toegangscode ingesteld!";
/* No comment provided by engineer. */
"Password" = "Wachtwoord";
/* No comment provided by engineer. */
"Password to show" = "Wachtwoord om weer te geven";
@@ -3352,6 +3402,9 @@
/* No comment provided by engineer. */
"Polish interface" = "Poolse interface";
/* No comment provided by engineer. */
"Port" = "Poort";
/* server test error */
"Possibly, certificate fingerprint in server address is incorrect" = "Mogelijk is de certificaat vingerafdruk in het server adres onjuist";
@@ -3463,6 +3516,9 @@
/* No comment provided by engineer. */
"Proxied servers" = "Proxied servers";
/* No comment provided by engineer. */
"Proxy requires password" = "Proxy vereist wachtwoord";
/* No comment provided by engineer. */
"Push notifications" = "Push meldingen";
@@ -3804,6 +3860,9 @@
/* No comment provided by engineer. */
"Saved WebRTC ICE servers will be removed" = "Opgeslagen WebRTC ICE servers worden verwijderd";
/* No comment provided by engineer. */
"Saving %lld messages" = "%lld berichten opslaan";
/* No comment provided by engineer. */
"Scale" = "Schaal";
@@ -4209,6 +4268,9 @@
/* No comment provided by engineer. */
"SMP server" = "SMP server";
/* No comment provided by engineer. */
"SOCKS proxy" = "SOCKS proxy";
/* blur media */
"Soft" = "Soft";
@@ -4297,13 +4359,13 @@
"Submit" = "Indienen";
/* No comment provided by engineer. */
"Subscribed" = "Ingeschreven";
"Subscribed" = "Subscribed";
/* No comment provided by engineer. */
"Subscription errors" = "Inschrijving fouten";
"Subscription errors" = "Subscription fouten";
/* No comment provided by engineer. */
"Subscriptions ignored" = "Inschrijvingen genegeerd";
"Subscriptions ignored" = "Subscriptions genegeerd";
/* No comment provided by engineer. */
"Support SimpleX Chat" = "Ondersteuning van SimpleX Chat";
@@ -4740,6 +4802,9 @@
/* No comment provided by engineer. */
"Use SimpleX Chat servers?" = "SimpleX Chat servers gebruiken?";
/* No comment provided by engineer. */
"Use SOCKS proxy" = "Gebruik SOCKS proxy";
/* No comment provided by engineer. */
"Use the app while in the call." = "Gebruik de app tijdens het gesprek.";
@@ -4752,6 +4817,9 @@
/* No comment provided by engineer. */
"User selection" = "Gebruikersselectie";
/* No comment provided by engineer. */
"Username" = "Gebruikersnaam";
/* No comment provided by engineer. */
"Using SimpleX Chat servers." = "SimpleX Chat servers gebruiken.";
@@ -4953,9 +5021,6 @@
/* No comment provided by engineer. */
"you" = "jij";
/* No comment provided by engineer. */
"You" = "Jij";
/* No comment provided by engineer. */
"You **must not** use the same database on two devices." = "U **mag** niet dezelfde database op twee apparaten gebruiken.";
@@ -5208,6 +5273,9 @@
/* No comment provided by engineer. */
"Your contacts will remain connected." = "Uw contacten blijven verbonden.";
/* No comment provided by engineer. */
"Your credentials may be sent unencrypted." = "Uw inloggegevens worden mogelijk niet-versleuteld verzonden.";
/* No comment provided by engineer. */
"Your current chat database will be DELETED and REPLACED with the imported one." = "Uw huidige chat database wordt VERWIJDERD en VERVANGEN door de geïmporteerde.";
+3 -7
View File
@@ -454,7 +454,7 @@
/* No comment provided by engineer. */
"All new messages from %@ will be hidden!" = "Wszystkie nowe wiadomości z %@ zostaną ukryte!";
/* No comment provided by engineer. */
/* profile dropdown */
"All profiles" = "Wszystkie profile";
/* No comment provided by engineer. */
@@ -1996,7 +1996,7 @@
/* No comment provided by engineer. */
"Error stopping chat" = "Błąd zatrzymania czatu";
/* No comment provided by engineer. */
/* alertTitle */
"Error switching profile!" = "Błąd przełączania profilu!";
/* No comment provided by engineer. */
@@ -2023,8 +2023,7 @@
/* No comment provided by engineer. */
"Error: " = "Błąd: ";
/* file error text
snd error text */
/* alert message */
"Error: %@" = "Błąd: %@";
/* No comment provided by engineer. */
@@ -4905,9 +4904,6 @@
/* No comment provided by engineer. */
"you" = "Ty";
/* No comment provided by engineer. */
"You" = "Ty";
/* No comment provided by engineer. */
"You **must not** use the same database on two devices." = "**Nie możesz** używać tej samej bazy na dwóch urządzeniach.";
+3 -7
View File
@@ -454,7 +454,7 @@
/* No comment provided by engineer. */
"All new messages from %@ will be hidden!" = "Все новые сообщения от %@ будут скрыты!";
/* No comment provided by engineer. */
/* profile dropdown */
"All profiles" = "Все профили";
/* No comment provided by engineer. */
@@ -1996,7 +1996,7 @@
/* No comment provided by engineer. */
"Error stopping chat" = "Ошибка при остановке чата";
/* No comment provided by engineer. */
/* alertTitle */
"Error switching profile!" = "Ошибка выбора профиля!";
/* No comment provided by engineer. */
@@ -2023,8 +2023,7 @@
/* No comment provided by engineer. */
"Error: " = "Ошибка: ";
/* file error text
snd error text */
/* alert message */
"Error: %@" = "Ошибка: %@";
/* No comment provided by engineer. */
@@ -4905,9 +4904,6 @@
/* No comment provided by engineer. */
"you" = "Вы";
/* No comment provided by engineer. */
"You" = "Вы";
/* No comment provided by engineer. */
"You **must not** use the same database on two devices." = "Вы **не должны** использовать одну и ту же базу данных на двух устройствах.";
+2 -6
View File
@@ -1347,7 +1347,7 @@
/* No comment provided by engineer. */
"Error stopping chat" = "เกิดข้อผิดพลาดในการหยุดแชท";
/* No comment provided by engineer. */
/* alertTitle */
"Error switching profile!" = "เกิดข้อผิดพลาดในการเปลี่ยนโปรไฟล์!";
/* No comment provided by engineer. */
@@ -1368,8 +1368,7 @@
/* No comment provided by engineer. */
"Error: " = "ผิดพลาด: ";
/* file error text
snd error text */
/* alert message */
"Error: %@" = "ข้อผิดพลาด: % @";
/* No comment provided by engineer. */
@@ -3215,9 +3214,6 @@
/* pref value */
"yes" = "ใช่";
/* No comment provided by engineer. */
"You" = "คุณ";
/* No comment provided by engineer. */
"You accepted connection" = "คุณยอมรับการเชื่อมต่อ";
+2 -6
View File
@@ -1756,7 +1756,7 @@
/* No comment provided by engineer. */
"Error stopping chat" = "Sohbet durdurulurken hata oluştu";
/* No comment provided by engineer. */
/* alertTitle */
"Error switching profile!" = "Profil değiştirilirken hata oluştu!";
/* No comment provided by engineer. */
@@ -1783,8 +1783,7 @@
/* No comment provided by engineer. */
"Error: " = "Hata: ";
/* file error text
snd error text */
/* alert message */
"Error: %@" = "Hata: %@";
/* No comment provided by engineer. */
@@ -4281,9 +4280,6 @@
/* No comment provided by engineer. */
"you" = "sen";
/* No comment provided by engineer. */
"You" = "Sen";
/* No comment provided by engineer. */
"You **must not** use the same database on two devices." = "Aynı veritabanını iki cihazda **kullanmamalısınız**.";
+3 -7
View File
@@ -454,7 +454,7 @@
/* No comment provided by engineer. */
"All new messages from %@ will be hidden!" = "Всі нові повідомлення від %@ будуть приховані!";
/* No comment provided by engineer. */
/* profile dropdown */
"All profiles" = "Всі профілі";
/* No comment provided by engineer. */
@@ -1996,7 +1996,7 @@
/* No comment provided by engineer. */
"Error stopping chat" = "Помилка зупинки чату";
/* No comment provided by engineer. */
/* alertTitle */
"Error switching profile!" = "Помилка перемикання профілю!";
/* No comment provided by engineer. */
@@ -2023,8 +2023,7 @@
/* No comment provided by engineer. */
"Error: " = "Помилка: ";
/* file error text
snd error text */
/* alert message */
"Error: %@" = "Помилка: %@";
/* No comment provided by engineer. */
@@ -4905,9 +4904,6 @@
/* No comment provided by engineer. */
"you" = "ти";
/* No comment provided by engineer. */
"You" = "Ти";
/* No comment provided by engineer. */
"You **must not** use the same database on two devices." = "Ви **не повинні використовувати** одну і ту ж базу даних на двох пристроях.";
+3 -7
View File
@@ -454,7 +454,7 @@
/* No comment provided by engineer. */
"All new messages from %@ will be hidden!" = "来自 %@ 的所有新消息都将被隐藏!";
/* No comment provided by engineer. */
/* profile dropdown */
"All profiles" = "所有配置文件";
/* No comment provided by engineer. */
@@ -1996,7 +1996,7 @@
/* No comment provided by engineer. */
"Error stopping chat" = "停止聊天错误";
/* No comment provided by engineer. */
/* alertTitle */
"Error switching profile!" = "切换资料错误!";
/* No comment provided by engineer. */
@@ -2023,8 +2023,7 @@
/* No comment provided by engineer. */
"Error: " = "错误: ";
/* file error text
snd error text */
/* alert message */
"Error: %@" = "错误: %@";
/* No comment provided by engineer. */
@@ -4905,9 +4904,6 @@
/* No comment provided by engineer. */
"you" = "您";
/* No comment provided by engineer. */
"You" = "您";
/* No comment provided by engineer. */
"You **must not** use the same database on two devices." = "您 **不得** 在两台设备上使用相同的数据库。";
@@ -115,6 +115,9 @@ fun AppearanceScope.AppearanceLayout(
SectionDividerSpaced()
ThemesSection(systemDarkTheme)
SectionDividerSpaced()
MessageShapeSection()
SectionDividerSpaced()
ProfileImageSection()
@@ -219,6 +219,8 @@ class AppPreferences {
}, settingsThemes)
val themeOverrides = mkThemeOverridesPreference()
val profileImageCornerRadius = mkFloatPreference(SHARED_PREFS_PROFILE_IMAGE_CORNER_RADIUS, 22.5f)
val chatItemRoundness = mkFloatPreference(SHARED_PREFS_CHAT_ITEM_ROUNDNESS, 0.75f)
val chatItemTail = mkBoolPreference(SHARED_PREFS_CHAT_ITEM_TAIL, true)
val fontScale = mkFloatPreference(SHARED_PREFS_FONT_SCALE, 1f)
val densityScale = mkFloatPreference(SHARED_PREFS_DENSITY_SCALE, 1f)
@@ -422,6 +424,8 @@ class AppPreferences {
private const val SHARED_PREFS_THEMES_OLD = "Themes"
private const val SHARED_PREFS_THEME_OVERRIDES = "ThemeOverrides"
private const val SHARED_PREFS_PROFILE_IMAGE_CORNER_RADIUS = "ProfileImageCornerRadius"
private const val SHARED_PREFS_CHAT_ITEM_ROUNDNESS = "ChatItemRoundness"
private const val SHARED_PREFS_CHAT_ITEM_TAIL = "ChatItemTail"
private const val SHARED_PREFS_FONT_SCALE = "FontScale"
private const val SHARED_PREFS_DENSITY_SCALE = "DensityScale"
private const val SHARED_PREFS_WHATS_NEW_VERSION = "WhatsNewVersion"
@@ -6334,6 +6338,8 @@ data class AppSettings(
var iosCallKitEnabled: Boolean? = null,
var iosCallKitCallsInRecents: Boolean? = null,
var uiProfileImageCornerRadius: Float? = null,
var uiChatItemRoundness: Float? = null,
var uiChatItemTail: Boolean? = null,
var uiColorScheme: String? = null,
var uiDarkColorScheme: String? = null,
var uiCurrentThemeIds: Map<String, String>? = null,
@@ -6366,6 +6372,8 @@ data class AppSettings(
if (iosCallKitEnabled != def.iosCallKitEnabled) { empty.iosCallKitEnabled = iosCallKitEnabled }
if (iosCallKitCallsInRecents != def.iosCallKitCallsInRecents) { empty.iosCallKitCallsInRecents = iosCallKitCallsInRecents }
if (uiProfileImageCornerRadius != def.uiProfileImageCornerRadius) { empty.uiProfileImageCornerRadius = uiProfileImageCornerRadius }
if (uiChatItemRoundness != def.uiChatItemRoundness) { empty.uiChatItemRoundness = uiChatItemRoundness }
if (uiChatItemTail != def.uiChatItemTail) { empty.uiChatItemTail = uiChatItemTail }
if (uiColorScheme != def.uiColorScheme) { empty.uiColorScheme = uiColorScheme }
if (uiDarkColorScheme != def.uiDarkColorScheme) { empty.uiDarkColorScheme = uiDarkColorScheme }
if (uiCurrentThemeIds != def.uiCurrentThemeIds) { empty.uiCurrentThemeIds = uiCurrentThemeIds }
@@ -6409,6 +6417,8 @@ data class AppSettings(
iosCallKitEnabled?.let { def.iosCallKitEnabled.set(it) }
iosCallKitCallsInRecents?.let { def.iosCallKitCallsInRecents.set(it) }
uiProfileImageCornerRadius?.let { def.profileImageCornerRadius.set(it) }
uiChatItemRoundness?.let { def.chatItemRoundness.set(it) }
uiChatItemTail?.let { def.chatItemTail.set(it) }
uiColorScheme?.let { def.currentTheme.set(it) }
uiDarkColorScheme?.let { def.systemDarkTheme.set(it) }
uiCurrentThemeIds?.let { def.currentThemeIds.set(it) }
@@ -6442,6 +6452,8 @@ data class AppSettings(
iosCallKitEnabled = true,
iosCallKitCallsInRecents = false,
uiProfileImageCornerRadius = 22.5f,
uiChatItemRoundness = 0.75f,
uiChatItemTail = true,
uiColorScheme = DefaultTheme.SYSTEM_THEME_NAME,
uiDarkColorScheme = DefaultTheme.SIMPLEX.themeName,
uiCurrentThemeIds = null,
@@ -6476,6 +6488,8 @@ data class AppSettings(
iosCallKitEnabled = def.iosCallKitEnabled.get(),
iosCallKitCallsInRecents = def.iosCallKitCallsInRecents.get(),
uiProfileImageCornerRadius = def.profileImageCornerRadius.get(),
uiChatItemRoundness = def.chatItemRoundness.get(),
uiChatItemTail = def.chatItemTail.get(),
uiColorScheme = def.currentTheme.get() ?: DefaultTheme.SYSTEM_THEME_NAME,
uiDarkColorScheme = def.systemDarkTheme.get() ?: DefaultTheme.SIMPLEX.themeName,
uiCurrentThemeIds = def.currentThemeIds.get(),
@@ -24,11 +24,10 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import chat.simplex.common.model.*
import chat.simplex.common.platform.*
import chat.simplex.common.views.chat.item.ItemAction
import chat.simplex.common.views.chat.item.MarkdownText
import chat.simplex.common.views.helpers.*
import chat.simplex.common.ui.theme.*
import chat.simplex.common.views.chat.group.MemberProfileImage
import chat.simplex.common.views.chat.item.*
import chat.simplex.common.views.chatlist.*
import chat.simplex.res.MR
import dev.icerock.moko.resources.ImageResource
@@ -75,7 +74,7 @@ fun ChatItemInfoView(chatRh: Long?, ci: ChatItem, ciInfo: ChatItemInfo, devTools
Column {
Box(
Modifier.clip(RoundedCornerShape(18.dp)).background(itemColor).padding(bottom = 3.dp)
Modifier.clipChatItem().background(itemColor).padding(bottom = 3.dp)
.combinedClickable(onLongClick = { showMenu.value = true }, onClick = {})
.onRightClick { showMenu.value = true }
) {
@@ -122,7 +121,7 @@ fun ChatItemInfoView(chatRh: Long?, ci: ChatItem, ciInfo: ChatItemInfo, devTools
Column {
Box(
Modifier.clip(RoundedCornerShape(18.dp)).background(quoteColor).padding(bottom = 3.dp)
Modifier.clipChatItem().background(quoteColor).padding(bottom = 3.dp)
.combinedClickable(onLongClick = { showMenu.value = true }, onClick = {})
.onRightClick { showMenu.value = true }
) {
@@ -1036,7 +1036,7 @@ fun BoxWithConstraintsScope.ChatItemsList(
tryOrShowError("${cItem.id}ChatItem", error = {
CIBrokenComposableView(if (cItem.chatDir.sent) Alignment.CenterEnd else Alignment.CenterStart)
}) {
ChatItemView(remoteHostId, chatInfo, cItem, composeState, provider, useLinkPreviews = useLinkPreviews, linkMode = linkMode, revealed = revealed, range = range, fillMaxWidth = fillMaxWidth, selectedChatItems = selectedChatItems, selectChatItem = { selectUnselectChatItem(true, cItem, revealed, selectedChatItems) }, deleteMessage = deleteMessage, deleteMessages = deleteMessages, receiveFile = receiveFile, cancelFile = cancelFile, joinGroup = joinGroup, acceptCall = acceptCall, acceptFeature = acceptFeature, openDirectChat = openDirectChat, forwardItem = forwardItem, updateContactStats = updateContactStats, updateMemberStats = updateMemberStats, syncContactConnection = syncContactConnection, syncMemberConnection = syncMemberConnection, findModelChat = findModelChat, findModelMember = findModelMember, scrollToItem = scrollToItem, setReaction = setReaction, showItemDetails = showItemDetails, developerTools = developerTools, showViaProxy = showViaProxy, showTimestamp = itemSeparation.timestamp)
ChatItemView(remoteHostId, chatInfo, cItem, composeState, provider, useLinkPreviews = useLinkPreviews, linkMode = linkMode, revealed = revealed, range = range, fillMaxWidth = fillMaxWidth, selectedChatItems = selectedChatItems, selectChatItem = { selectUnselectChatItem(true, cItem, revealed, selectedChatItems) }, deleteMessage = deleteMessage, deleteMessages = deleteMessages, receiveFile = receiveFile, cancelFile = cancelFile, joinGroup = joinGroup, acceptCall = acceptCall, acceptFeature = acceptFeature, openDirectChat = openDirectChat, forwardItem = forwardItem, updateContactStats = updateContactStats, updateMemberStats = updateMemberStats, syncContactConnection = syncContactConnection, syncMemberConnection = syncMemberConnection, findModelChat = findModelChat, findModelMember = findModelMember, scrollToItem = scrollToItem, setReaction = setReaction, showItemDetails = showItemDetails, developerTools = developerTools, showViaProxy = showViaProxy, itemSeparation = itemSeparation, showTimestamp = itemSeparation.timestamp)
}
}
@@ -1081,6 +1081,15 @@ fun BoxWithConstraintsScope.ChatItemsList(
}
}
@Composable
fun adjustTailPaddingOffset(originalPadding: Dp, start: Boolean): Dp {
val chatItemTail = remember { appPreferences.chatItemTail.state }
val style = shapeStyle(cItem, chatItemTail.value, itemSeparation.largeGap, true)
val tailRendered = style is ShapeStyle.Bubble && style.tailVisible
return originalPadding + (if (tailRendered) 0.dp else if (start) msgTailWidthDp * 2 else msgTailWidthDp)
}
Box {
val voiceWithTransparentBack = cItem.content.msgContent is MsgContent.MCVoice && cItem.content.text.isEmpty() && cItem.quotedItem == null && cItem.meta.itemForwarded == null
val selectionVisible = selectedChatItems.value != null && cItem.canBeDeletedForSelf
@@ -1099,7 +1108,7 @@ fun BoxWithConstraintsScope.ChatItemsList(
Column(
Modifier
.padding(top = 8.dp)
.padding(start = 8.dp, end = if (voiceWithTransparentBack) 12.dp else 66.dp)
.padding(start = 8.dp, end = if (voiceWithTransparentBack) 12.dp else adjustTailPaddingOffset(66.dp, start = false))
.fillMaxWidth()
.then(swipeableModifier),
verticalArrangement = Arrangement.spacedBy(4.dp),
@@ -1111,7 +1120,7 @@ fun BoxWithConstraintsScope.ChatItemsList(
Text(
memberNames(member, prevMember, memCount),
Modifier
.padding(start = MEMBER_IMAGE_SIZE + DEFAULT_PADDING_HALF)
.padding(start = (MEMBER_IMAGE_SIZE * fontSizeSqrtMultiplier) + DEFAULT_PADDING_HALF)
.weight(1f, false),
fontSize = 13.5.sp,
color = MaterialTheme.colors.secondary,
@@ -1119,9 +1128,13 @@ fun BoxWithConstraintsScope.ChatItemsList(
maxLines = 1
)
if (memCount == 1 && member.memberRole > GroupMemberRole.Member) {
val chatItemTail = remember { appPreferences.chatItemTail.state }
val style = shapeStyle(cItem, chatItemTail.value, itemSeparation.largeGap, true)
val tailRendered = style is ShapeStyle.Bubble && style.tailVisible
Text(
member.memberRole.text,
Modifier.padding(start = DEFAULT_PADDING_HALF * 1.5f, end = DEFAULT_PADDING_HALF),
Modifier.padding(start = DEFAULT_PADDING_HALF * 1.5f, end = DEFAULT_PADDING_HALF + if (tailRendered) msgTailWidthDp else 0.dp),
fontSize = 13.5.sp,
fontWeight = FontWeight.Medium,
color = MaterialTheme.colors.secondary,
@@ -1137,12 +1150,11 @@ fun BoxWithConstraintsScope.ChatItemsList(
androidx.compose.animation.AnimatedVisibility(selectionVisible, enter = fadeIn(), exit = fadeOut()) {
SelectedChatItem(Modifier, cItem.id, selectedChatItems)
}
Row(Modifier.graphicsLayer { translationX = selectionOffset.toPx() },
horizontalArrangement = Arrangement.spacedBy(4.dp)) {
Row(Modifier.graphicsLayer { translationX = selectionOffset.toPx() }) {
Box(Modifier.clickable { showMemberInfo(chatInfo.groupInfo, member) }) {
MemberImage(member)
}
Box(modifier = Modifier.padding(top = 2.dp)) {
Box(modifier = Modifier.padding(top = 2.dp, start = 4.dp).chatItemOffset(cItem, itemSeparation.largeGap, revealed = revealed.value)) {
ChatItemViewShortHand(cItem, itemSeparation, range, false)
}
}
@@ -1164,7 +1176,8 @@ fun BoxWithConstraintsScope.ChatItemsList(
}
Row(
Modifier
.padding(start = 8.dp + MEMBER_IMAGE_SIZE + 4.dp, end = if (voiceWithTransparentBack) 12.dp else 66.dp)
.padding(start = 8.dp + (MEMBER_IMAGE_SIZE * fontSizeSqrtMultiplier) + 4.dp, end = if (voiceWithTransparentBack) 12.dp else adjustTailPaddingOffset(66.dp, start = false))
.chatItemOffset(cItem, itemSeparation.largeGap, revealed = revealed.value)
.then(swipeableOrSelectionModifier)
) {
ChatItemViewShortHand(cItem, itemSeparation, range)
@@ -1178,7 +1191,8 @@ fun BoxWithConstraintsScope.ChatItemsList(
}
Box(
Modifier
.padding(start = if (voiceWithTransparentBack) 12.dp else 104.dp, end = 12.dp)
.padding(start = if (voiceWithTransparentBack) 12.dp else adjustTailPaddingOffset(104.dp, start = true), end = 12.dp)
.chatItemOffset(cItem, itemSeparation.largeGap, revealed = revealed.value)
.then(if (selectionVisible) Modifier else swipeableModifier)
) {
ChatItemViewShortHand(cItem, itemSeparation, range)
@@ -1190,11 +1204,14 @@ fun BoxWithConstraintsScope.ChatItemsList(
AnimatedVisibility (selectionVisible, enter = fadeIn(), exit = fadeOut()) {
SelectedChatItem(Modifier.padding(start = 8.dp), cItem.id, selectedChatItems)
}
Box(
Modifier.padding(
start = if (sent && !voiceWithTransparentBack) 76.dp else 12.dp,
end = if (sent || voiceWithTransparentBack) 12.dp else 76.dp,
).then(if (!selectionVisible || !sent) swipeableOrSelectionModifier else Modifier)
start = if (sent && !voiceWithTransparentBack) adjustTailPaddingOffset(76.dp, start = true) else 12.dp,
end = if (sent || voiceWithTransparentBack) 12.dp else adjustTailPaddingOffset(76.dp, start = false),
)
.chatItemOffset(cItem, itemSeparation.largeGap, revealed = revealed.value)
.then(if (!selectionVisible || !sent) swipeableOrSelectionModifier else Modifier)
) {
ChatItemViewShortHand(cItem, itemSeparation, range)
}
@@ -3,13 +3,14 @@ package chat.simplex.common.views.chat.item
import androidx.compose.desktop.ui.tooling.preview.Preview
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.shape.*
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.geometry.*
import androidx.compose.ui.graphics.*
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.*
@@ -26,9 +27,16 @@ import chat.simplex.common.views.chat.*
import chat.simplex.common.views.helpers.*
import chat.simplex.res.MR
import kotlinx.datetime.Clock
import kotlin.math.*
// TODO refactor so that FramedItemView can show all CIContent items if they're deleted (see Swift code)
private val msgRectMaxRadius = 18.dp
private val msgBubbleMaxRadius = msgRectMaxRadius * 1.2f
val msgTailWidthDp = 9.dp
private val msgTailMinHeightDp = msgTailWidthDp * 1.254f // ~56deg
private val msgTailMaxHeightDp = msgTailWidthDp * 1.732f // 60deg
val chatEventStyle = SpanStyle(fontSize = 12.sp, fontWeight = FontWeight.Light, color = CurrentColors.value.colors.secondary)
fun chatEventText(ci: ChatItem): AnnotatedString =
@@ -74,6 +82,7 @@ fun ChatItemView(
developerTools: Boolean,
showViaProxy: Boolean,
showTimestamp: Boolean,
itemSeparation: ItemSeparation,
preview: Boolean = false,
) {
val uriHandler = LocalUriHandler.current
@@ -100,7 +109,7 @@ fun ChatItemView(
@Composable
fun ChatItemReactions() {
Row(verticalAlignment = Alignment.CenterVertically) {
Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.chatItemOffset(cItem, itemSeparation.largeGap, inverted = true, revealed = true)) {
cItem.reactions.forEach { r ->
var modifier = Modifier.padding(horizontal = 5.dp, vertical = 2.dp).clip(RoundedCornerShape(8.dp))
if (cInfo.featureEnabled(ChatFeature.Reactions) && (cItem.allowAddReaction || r.userReacted)) {
@@ -127,13 +136,13 @@ fun ChatItemView(
Column(horizontalAlignment = if (cItem.chatDir.sent) Alignment.End else Alignment.Start) {
Column(
Modifier
.clip(RoundedCornerShape(18.dp))
.clipChatItem(cItem, itemSeparation.largeGap, revealed.value)
.combinedClickable(onLongClick = { showMenu.value = true }, onClick = onClick)
.onRightClick { showMenu.value = true },
) {
@Composable
fun framedItemView() {
FramedItemView(cInfo, cItem, uriHandler, imageProvider, linkMode = linkMode, showViaProxy = showViaProxy, showMenu, showTimestamp = showTimestamp, receiveFile, onLinkLongClick, scrollToItem)
FramedItemView(cInfo, cItem, uriHandler, imageProvider, linkMode = linkMode, showViaProxy = showViaProxy, showMenu, showTimestamp = showTimestamp, tailVisible = itemSeparation.largeGap, receiveFile, onLinkLongClick, scrollToItem)
}
fun deleteMessageQuestionText(): String {
@@ -795,6 +804,154 @@ fun ItemAction(text: String, color: Color = Color.Unspecified, onClick: () -> Un
}
}
@Composable
fun Modifier.chatItemOffset(cItem: ChatItem, tailVisible: Boolean, inverted: Boolean = false, revealed: Boolean): Modifier {
val chatItemTail = remember { appPreferences.chatItemTail.state }
val style = shapeStyle(cItem, chatItemTail.value, tailVisible, revealed)
val offset = if (style is ShapeStyle.Bubble) {
if (style.tailVisible) {
if (cItem.chatDir.sent) msgTailWidthDp else -msgTailWidthDp
} else {
0.dp
}
} else 0.dp
return this.offset(x = if (inverted) (-1f * offset) else offset)
}
@Composable
fun Modifier.clipChatItem(chatItem: ChatItem? = null, tailVisible: Boolean = false, revealed: Boolean = false): Modifier {
val chatItemRoundness = remember { appPreferences.chatItemRoundness.state }
val chatItemTail = remember { appPreferences.chatItemTail.state }
val style = shapeStyle(chatItem, chatItemTail.value, tailVisible, revealed)
val cornerRoundness = chatItemRoundness.value.coerceIn(0f, 1f)
val shape = when (style) {
is ShapeStyle.Bubble -> chatItemShape(cornerRoundness, LocalDensity.current, style.tailVisible, chatItem?.chatDir?.sent == true)
is ShapeStyle.RoundRect -> RoundedCornerShape(style.radius * cornerRoundness)
}
return this.clip(shape)
}
private fun chatItemShape(roundness: Float, density: Density, tailVisible: Boolean, sent: Boolean = false): GenericShape = GenericShape { size, _ ->
val (msgTailWidth, msgBubbleMaxRadius) = with(density) { Pair(msgTailWidthDp.toPx(), msgBubbleMaxRadius.toPx()) }
val width = if (sent && tailVisible) size.width - msgTailWidth else size.width
val height = size.height
val rxMax = min(msgBubbleMaxRadius, width / 2)
val ryMax = min(msgBubbleMaxRadius, height / 2)
val rx = roundness * rxMax
val ry = roundness * ryMax
val tailHeight = with(density) {
min(
msgTailMinHeightDp.toPx() + roundness * (msgTailMaxHeightDp.toPx() - msgTailMinHeightDp.toPx()),
height / 2
)
}
moveTo(rx, 0f)
lineTo(width - rx, 0f) // Top Line
if (roundness > 0) {
quadraticBezierTo(width, 0f, width, ry) // Top-right corner
}
if (height > 2 * ry) {
lineTo(width, height - ry) // Right side
}
if (roundness > 0) {
quadraticBezierTo(width, height, width - rx, height) // Bottom-right corner
}
if (tailVisible) {
lineTo(0f, height) // Bottom line
if (roundness > 0) {
val d = tailHeight - msgTailWidth * msgTailWidth / tailHeight
val controlPoint = Offset(msgTailWidth, height - tailHeight + d * sqrt(roundness))
quadraticBezierTo(controlPoint.x, controlPoint.y, msgTailWidth, height - tailHeight)
} else {
lineTo(msgTailWidth, height - tailHeight)
}
if (height > ry + tailHeight) {
lineTo(msgTailWidth, ry)
}
} else {
lineTo(rx, height) // Bottom line
if (roundness > 0) {
quadraticBezierTo(0f, height, 0f, height - ry) // Bottom-left corner
}
if (height > 2 * ry) {
lineTo(0f, ry) // Left side
}
}
if (roundness > 0) {
val bubbleInitialX = if (tailVisible) msgTailWidth else 0f
quadraticBezierTo(bubbleInitialX, 0f, bubbleInitialX + rx, 0f) // Top-left corner
}
if (sent) {
val matrix = Matrix()
matrix.scale(-1f, 1f)
this.transform(matrix)
this.translate(Offset(size.width, 0f))
}
}
sealed class ShapeStyle {
data class Bubble(val tailVisible: Boolean, val startPadding: Boolean) : ShapeStyle()
data class RoundRect(val radius: Dp) : ShapeStyle()
}
fun shapeStyle(chatItem: ChatItem? = null, tailEnabled: Boolean, tailVisible: Boolean, revealed: Boolean): ShapeStyle {
if (chatItem == null) {
return ShapeStyle.RoundRect(msgRectMaxRadius)
}
when (chatItem.content) {
is CIContent.SndMsgContent,
is CIContent.RcvMsgContent,
is CIContent.RcvDecryptionError,
is CIContent.SndDeleted,
is CIContent.RcvDeleted,
is CIContent.RcvIntegrityError,
is CIContent.SndModerated,
is CIContent.RcvModerated,
is CIContent.RcvBlocked,
is CIContent.InvalidJSON -> {
if (chatItem.meta.itemDeleted != null && (!revealed || chatItem.isDeletedContent)) {
return ShapeStyle.RoundRect(msgRectMaxRadius)
}
val tail = when (val content = chatItem.content.msgContent) {
is MsgContent.MCImage,
is MsgContent.MCVideo,
is MsgContent.MCVoice -> {
if (content.text.isEmpty()) {
false
} else {
tailVisible
}
}
is MsgContent.MCText -> {
if (isShortEmoji(content.text)) {
false
} else {
tailVisible
}
}
else -> tailVisible
}
return if (tailEnabled) {
ShapeStyle.Bubble(tail, !chatItem.chatDir.sent)
} else {
ShapeStyle.RoundRect(msgRectMaxRadius)
}
}
is CIContent.RcvGroupInvitation,
is CIContent.SndGroupInvitation -> return ShapeStyle.RoundRect(msgRectMaxRadius)
else -> return ShapeStyle.RoundRect(8.dp)
}
}
fun cancelFileAlertDialog(fileId: Long, cancelFile: (Long) -> Unit, cancelAction: CancelAction) {
AlertManager.shared.showAlertDialog(
title = generalGetString(cancelAction.alert.titleId),
@@ -931,6 +1088,7 @@ fun PreviewChatItemView(
showViaProxy = false,
showTimestamp = true,
preview = true,
itemSeparation = ItemSeparation(timestamp = true, largeGap = true, null)
)
}
@@ -970,7 +1128,8 @@ fun PreviewChatItemViewDeletedContent() {
developerTools = false,
showViaProxy = false,
preview = true,
showTimestamp = true
showTimestamp = true,
itemSeparation = ItemSeparation(timestamp = true, largeGap = true, null)
)
}
}
@@ -2,12 +2,10 @@ package chat.simplex.common.views.chat.item
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.clipToBounds
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.painter.Painter
@@ -36,6 +34,7 @@ fun FramedItemView(
showViaProxy: Boolean,
showMenu: MutableState<Boolean>,
showTimestamp: Boolean,
tailVisible: Boolean = false,
receiveFile: (Long) -> Unit,
onLinkLongClick: (link: String) -> Unit = {},
scrollToItem: (Long) -> Unit = {},
@@ -190,7 +189,7 @@ fun FramedItemView(
val sentColor = MaterialTheme.appColors.sentMessage
val receivedColor = MaterialTheme.appColors.receivedMessage
Box(Modifier
.clip(RoundedCornerShape(18.dp))
.clipChatItem(ci, tailVisible, revealed = true)
.background(
when {
transparentBackground -> Color.Transparent
@@ -200,7 +199,14 @@ fun FramedItemView(
)) {
var metaColor = MaterialTheme.colors.secondary
Box(contentAlignment = Alignment.BottomEnd) {
Column(Modifier.width(IntrinsicSize.Max)) {
val chatItemTail = remember { appPreferences.chatItemTail.state }
val style = shapeStyle(ci, chatItemTail.value, tailVisible, revealed = true)
val tailRendered = style is ShapeStyle.Bubble && style.tailVisible
Column(
Modifier
.width(IntrinsicSize.Max)
.padding(start = if (tailRendered) msgTailWidthDp else 0.dp, end = if (sent && tailRendered) msgTailWidthDp else 0.dp)
) {
PriorityLayout(Modifier, CHAT_IMAGE_LAYOUT_ID) {
if (ci.meta.itemDeleted != null) {
when (ci.meta.itemDeleted) {
@@ -279,7 +285,13 @@ fun FramedItemView(
}
}
}
Box(Modifier.padding(bottom = 6.dp, end = 12.dp)) {
Box(
Modifier
.padding(
bottom = 6.dp,
end = 12.dp + if (tailRendered && sent) msgTailWidthDp else 0.dp,
)
) {
CIMetaView(ci, chatTTL, metaColor, showViaProxy = showViaProxy, showTimestamp = showTimestamp)
}
}
@@ -35,6 +35,7 @@ import chat.simplex.common.platform.*
import chat.simplex.common.ui.theme.ThemeManager.colorFromReadableHex
import chat.simplex.common.ui.theme.ThemeManager.toReadableHex
import chat.simplex.common.views.chat.item.PreviewChatItemView
import chat.simplex.common.views.chat.item.msgTailWidthDp
import chat.simplex.res.MR
import com.godaddy.android.colorpicker.ClassicColorPicker
import com.godaddy.android.colorpicker.HsvColor
@@ -84,6 +85,31 @@ object AppearanceScope {
}
}
@Composable
fun MessageShapeSection() {
SectionView(stringResource(MR.strings.settings_section_title_message_shape).uppercase(), contentPadding = PaddingValues()) {
Row(modifier = Modifier.padding(start = DEFAULT_PADDING, end = DEFAULT_PADDING + 4.dp ) ,verticalAlignment = Alignment.CenterVertically) {
Text(stringResource(MR.strings.settings_message_shape_corner), color = colors.onBackground)
Spacer(Modifier.width(10.dp))
Slider(
remember { appPreferences.chatItemRoundness.state }.value,
valueRange = 0f..1f,
steps = 20,
onValueChange = {
val diff = it % 0.05f
appPreferences.chatItemRoundness.set(it + (if (diff >= 0.025f) -diff + 0.05f else -diff))
saveThemeToDatabase(null)
},
colors = SliderDefaults.colors(
activeTickColor = Color.Transparent,
inactiveTickColor = Color.Transparent,
)
)
}
SettingsPreferenceItem(icon = null, stringResource(MR.strings.settings_message_shape_tail), appPreferences.chatItemTail)
}
}
@Composable
fun FontScaleSection() {
val localFontScale = remember { mutableStateOf(appPrefs.fontScale.get()) }
@@ -169,13 +195,17 @@ object AppearanceScope {
.padding(DEFAULT_PADDING_HALF)
) {
if (withMessages) {
val alice = remember { ChatItem.getSampleData(1, CIDirection.DirectRcv(), Clock.System.now(), generalGetString(MR.strings.wallpaper_preview_hello_bob)) }
PreviewChatItemView(alice)
PreviewChatItemView(
ChatItem.getSampleData(2, CIDirection.DirectSnd(), Clock.System.now(), stringResource(MR.strings.wallpaper_preview_hello_alice),
quotedItem = CIQuote(alice.chatDir, alice.id, sentAt = alice.meta.itemTs, formattedText = alice.formattedText, content = MsgContent.MCText(alice.content.text))
)
)
val chatItemTail = remember { appPreferences.chatItemTail.state }
Column(verticalArrangement = Arrangement.spacedBy(4.dp), modifier = if (chatItemTail.value) Modifier else Modifier.padding(horizontal = msgTailWidthDp)) {
val alice = remember { ChatItem.getSampleData(1, CIDirection.DirectRcv(), Clock.System.now(), generalGetString(MR.strings.wallpaper_preview_hello_bob)) }
PreviewChatItemView(alice)
PreviewChatItemView(
ChatItem.getSampleData(2, CIDirection.DirectSnd(), Clock.System.now(), stringResource(MR.strings.wallpaper_preview_hello_alice),
quotedItem = CIQuote(alice.chatDir, alice.id, sentAt = alice.meta.itemTs, formattedText = alice.formattedText, content = MsgContent.MCText(alice.content.text))
)
)
}
} else {
Box(Modifier.fillMaxSize())
}
@@ -1265,8 +1265,8 @@
<string name="you_can_share_your_address">يمكنك مشاركة عنوانك كرابط أو رمز QR - يمكن لأي شخص الاتصال بك.</string>
<string name="you_can_create_it_later">يمكنك إنشاؤه لاحقًا</string>
<string name="invite_prohibited_description">أنت تحاول دعوة جهة اتصال قمت بمشاركة ملف تعريف متخفي معها إلى المجموعة التي تستخدم فيها ملفك الشخصي الرئيسي</string>
<string name="user_unmute">إلغاء الكتم</string>
<string name="unmute_chat">إلغاء الكتم</string>
<string name="user_unmute">ألغِ الكتم</string>
<string name="unmute_chat">ألغِ الكتم</string>
<string name="you_accepted_connection">لقد قبلت الاتصال</string>
<string name="unhide_profile">إلغاء إخفاء ملف تعريف</string>
<string name="alert_text_connection_pending_they_need_to_be_online_can_delete_and_retry">يجب أن تكون جهة الاتصال متصلة بالإنترنت حتى يكتمل الاتصال.
@@ -2090,4 +2090,18 @@
<string name="switching_profile_error_title">خطأ في تبديل الملف الشخصي</string>
<string name="select_chat_profile">حدد ملف تعريف الدردشة</string>
<string name="switching_profile_error_message">لقد تم نقل اتصالك إلى %s ولكن حدث خطأ غير متوقع أثناء إعادة توجيهك إلى الملف الشخصي.</string>
<string name="forward_alert_title_messages_to_forward">تحويل %1$s رسالة؟</string>
<string name="forward_files_messages_deleted_after_selection_title">لم يحوّل %1$s من الرسائل</string>
<string name="compose_forward_messages_n">جارِ تحويل %1$s رسالة</string>
<string name="forward_multiple">حوّل الرسائل…</string>
<string name="forward_alert_forward_messages_without_files">تحويل الرسائل بدون ملفات؟</string>
<string name="compose_save_messages_n">جارِ حفظ %1$s رسالة</string>
<string name="network_proxy_incorrect_config_desc">تأكد من صحة تضبيط الوكيل.</string>
<string name="n_other_file_errors">%1$d خطأ في ملف آخر.</string>
<string name="forward_files_messages_deleted_after_selection_desc">حُذفت الرسائل بعد تحديدها.</string>
<string name="forward_alert_title_nothing_to_forward">لا يوجد شيء لتحويله!</string>
<string name="network_proxy_password">كلمة المرور</string>
<string name="network_proxy_auth">استيثاق الوكيل</string>
<string name="delete_messages_cannot_be_undone_warning">سيتم حذف الرسائل - لا يمكن التراجع عن هذا!</string>
<string name="icon_descr_sound_muted">الصوت مكتوم</string>
</resources>
@@ -1196,6 +1196,9 @@
<string name="settings_section_title_icon">APP ICON</string>
<string name="settings_section_title_themes">THEMES</string>
<string name="settings_section_title_profile_images">Profile images</string>
<string name="settings_section_title_message_shape">Message shape</string>
<string name="settings_message_shape_corner">Corner</string>
<string name="settings_message_shape_tail">Tail</string>
<string name="settings_section_title_chat_theme">Chat theme</string>
<string name="settings_section_title_user_theme">Profile theme</string>
<string name="settings_section_title_chat_colors">Chat colors</string>
@@ -2170,4 +2170,22 @@
<string name="network_proxy_auth_mode_isolate_by_auth_user">Verwenden Sie für jedes Profil unterschiedliche Proxy-Anmeldeinformationen.</string>
<string name="network_proxy_random_credentials">Verwenden Sie zufällige Anmeldeinformationen</string>
<string name="network_proxy_username">Benutzername</string>
<string name="n_file_errors">%1$d Datei-Fehler:
\n%2$s</string>
<string name="forward_files_in_progress_desc">%1$d Datei(en) wird/werden immer noch heruntergeladen.</string>
<string name="forward_files_failed_to_receive_desc">Bei %1$d Datei(en) ist das Herunterladen fehlgeschlagen.</string>
<string name="error_forwarding_messages">Fehler beim Weiterleiten der Nachrichten</string>
<string name="forward_files_messages_deleted_after_selection_desc">Die Nachrichten wurden gelöscht, nachdem Sie sie ausgewählt hatten.</string>
<string name="forward_alert_title_nothing_to_forward">Es gibt nichts zum Weiterleiten!</string>
<string name="n_other_file_errors">%1$d andere(r) Datei-Fehler.</string>
<string name="forward_alert_title_messages_to_forward">%1$s Nachricht(en) weiterleiten?</string>
<string name="forward_files_missing_desc">%1$d Datei(en) wurde(n) gelöscht.</string>
<string name="forward_files_not_accepted_desc">%1$d Datei(en) wurde(n) nicht heruntergeladen.</string>
<string name="forward_alert_forward_messages_without_files">Nachrichten ohne Dateien weiterleiten?</string>
<string name="forward_files_messages_deleted_after_selection_title">%1$s Nachrichten wurden nicht weitergeleitet</string>
<string name="forward_files_not_accepted_receive_files">Herunterladen</string>
<string name="compose_forward_messages_n">Es wird/werden %1$s Nachricht(en) weitergeleitet</string>
<string name="forward_multiple">Nachrichten werden weitergeleitet…</string>
<string name="compose_save_messages_n">Es wird/werden %1$s Nachricht(en) gesichert</string>
<string name="icon_descr_sound_muted">Ton stummgeschaltet</string>
</resources>
@@ -83,7 +83,7 @@
<string name="database_passphrase_will_be_updated">La contraseña de cifrado de la base de datos será actualizada.</string>
<string name="info_row_database_id">ID base de datos</string>
<string name="direct_messages_are_prohibited_in_chat">Los mensajes directos entre miembros del grupo no están permitidos.</string>
<string name="passphrase_is_different">La contraseña de la base de datos es distinta a la almacenada en Keystore.</string>
<string name="passphrase_is_different">La contraseña de la base de datos es diferente a la almacenada en Keystore.</string>
<string name="database_will_be_encrypted_and_passphrase_stored">La base de datos será cifrada y la contraseña se guardará en Keystore.</string>
<string name="delete_contact_question">¿Eliminar contacto\?</string>
<string name="delete_message__question">¿Eliminar mensaje\?</string>
@@ -830,7 +830,7 @@
<string name="chat_help_tap_button">Pulsa el botón</string>
<string name="to_start_a_new_chat_help_header">Para iniciar un chat nuevo</string>
<string name="switch_receiving_address">Cambiar servidor de recepción</string>
<string name="group_is_decentralized">Completamente descentralizado y sólo visible para los miembros.</string>
<string name="group_is_decentralized">Totalmente descentralizado. Visible sólo para los miembros.</string>
<string name="to_connect_via_link_title">Para conectarte mediante enlace</string>
<string name="smp_servers_test_failed">¡Error en prueba del servidor!</string>
<string name="smp_servers_test_some_failed">Algunos servidores no superaron la prueba:</string>
@@ -949,7 +949,7 @@
<string name="your_chat_profiles">Mis perfiles</string>
<string name="your_simplex_contact_address">Mi dirección SimpleX</string>
<string name="smp_servers_your_server">Tu servidor</string>
<string name="smp_servers_your_server_address">Dirección de tu servidor</string>
<string name="smp_servers_your_server_address">Dirección del servidor</string>
<string name="your_current_profile">Tu perfil actual</string>
<string name="your_profile_is_stored_on_device_and_shared_only_with_contacts_simplex_cannot_see_it">Tu perfil es almacenado en tu dispositivo y solamente se comparte con tus contactos. Los servidores SimpleX no pueden ver tu perfil.</string>
<string name="language_system">Sistema</string>
@@ -971,7 +971,7 @@
<string name="button_welcome_message">Mensaje de bienvenida</string>
<string name="group_welcome_title">Mensaje de bienvenida</string>
<string name="make_profile_private">¡Hacer perfil privado!</string>
<string name="dont_show_again">No mostrar de nuevo</string>
<string name="dont_show_again">No volver a mostrar</string>
<string name="muted_when_inactive">¡Silenciado cuando está inactivo!</string>
<string name="v4_6_group_moderation">Moderación de grupos</string>
<string name="v4_6_hidden_chat_profiles">Perfiles ocultos</string>
@@ -1347,7 +1347,7 @@
<string name="connect_via_link_incognito">Conectar en incógnito</string>
<string name="turn_off_battery_optimization_button">Permitir</string>
<string name="turn_off_system_restriction_button">Abrir configuración</string>
<string name="connect__a_new_random_profile_will_be_shared">Se compartirá un perfil nuevo aleatorio.</string>
<string name="connect__a_new_random_profile_will_be_shared">Compartirás un perfil nuevo aleatorio.</string>
<string name="paste_the_link_you_received_to_connect_with_your_contact">Pega el enlace recibido para conectar con tu contacto…</string>
<string name="connect__your_profile_will_be_shared">El perfil %1$s será compartido.</string>
<string name="disable_notifications_button">Desactivar notificaciones</string>
@@ -1383,7 +1383,7 @@
<string name="v5_3_new_desktop_app">Nueva aplicación para ordenador!</string>
<string name="v5_3_new_interface_languages">6 idiomas nuevos para el interfaz</string>
<string name="v5_3_encrypt_local_files_descr">Cifrado de los nuevos archivos locales (excepto vídeos).</string>
<string name="compose_send_direct_message_to_connect">Enviar mensaje directo para conectar</string>
<string name="compose_send_direct_message_to_connect">Envía un mensaje para conectar</string>
<string name="v5_3_discover_join_groups">Descubre y únete a grupos</string>
<string name="v5_3_simpler_incognito_mode">Modo incógnito simplificado</string>
<string name="v5_3_new_interface_languages_descr">Árabe, Búlgaro, Finlandés, Hebreo, Tailandés y Ucraniano - gracias a los usuarios y Weblate.</string>
@@ -1450,7 +1450,7 @@
<string name="bad_desktop_address">Dirección ordenador incorrecta</string>
<string name="devices">Dispositivo</string>
<string name="non_content_uri_alert_title">Ruta archivo no valida.</string>
<string name="disconnect_desktop_question">¿Desconectar ordenador?</string>
<string name="disconnect_desktop_question">¿Desconectar del ordenador?</string>
<string name="block_member_desc">¡Los mensajes nuevos de %s estarán ocultos!</string>
<string name="desktop_app_version_is_incompatible">La versión de aplicación del ordenador %s no es compatible con esta aplicación.</string>
<string name="blocked_item_description">bloqueado</string>
@@ -2070,4 +2070,41 @@
<string name="new_message">Nuevo mensaje</string>
<string name="error_parsing_uri_title">Enlace no válido</string>
<string name="error_parsing_uri_desc">Por favor, comprueba que el enlace SimpleX es correcto.</string>
<string name="forward_files_in_progress_desc">%1$d archivo(s) se está(n) descargando todavía.</string>
<string name="n_other_file_errors">%1$d otro(s) error(es) de archivo.</string>
<string name="settings_section_title_chat_database">BASE DE DATOS</string>
<string name="error_forwarding_messages">Error en reenvío de mensajes</string>
<string name="forward_alert_title_messages_to_forward">¿Reenviar %1$s mensaje(s)?</string>
<string name="forward_multiple">Reenviar mensajes…</string>
<string name="system_mode_toast">Modo de sistema</string>
<string name="forward_alert_forward_messages_without_files">¿Reenviar mensajes sin los archivos?</string>
<string name="network_proxy_incorrect_config_desc">Asegúrate de que la configuración del proxy es correcta.</string>
<string name="forward_files_missing_desc">%1$d archivo(s) ha(n) sido eliminado(s).</string>
<string name="n_file_errors">%1$d error(es) de archivo
\n%2$s</string>
<string name="forward_files_failed_to_receive_desc">La descarga ha fallado para %1$d archivo(s).</string>
<string name="forward_files_not_accepted_desc">%1$d archivo(s) no se ha(n) descargado.</string>
<string name="forward_files_messages_deleted_after_selection_title">%1$s mensajes no enviados</string>
<string name="forward_files_not_accepted_receive_files">Descargar</string>
<string name="compose_forward_messages_n">Reenviando %1$s mensajes</string>
<string name="forward_files_messages_deleted_after_selection_desc">Los mensajes han sido borrados después de seleccionarlos.</string>
<string name="forward_alert_title_nothing_to_forward">¡Nada para reenviar!</string>
<string name="compose_save_messages_n">Guardando %1$s mensajes</string>
<string name="network_proxy_auth_mode_no_auth">No uses credenciales con proxy.</string>
<string name="network_proxy_incorrect_config_title">Error guardando proxy</string>
<string name="network_proxy_password">Contraseña</string>
<string name="network_proxy_auth">Autenticación proxy</string>
<string name="network_proxy_auth_mode_isolate_by_auth_entity">Credenciales proxy diferentes para cada conexión.</string>
<string name="network_proxy_auth_mode_isolate_by_auth_user">Credenciales proxy diferentes para cada perfil.</string>
<string name="network_proxy_random_credentials">Credenciales aleatorias</string>
<string name="network_proxy_username">Nombre de usuario</string>
<string name="network_proxy_auth_mode_username_password">Tus credenciales podrían ser enviadas sin cifrar.</string>
<string name="migrate_from_device_remove_archive_question">¿Eliminar archivo?</string>
<string name="migrate_from_device_uploaded_archive_will_be_removed">El archivo de bases de datos subido será eliminado permanentemente de los servidores.</string>
<string name="delete_messages_cannot_be_undone_warning">Los mensajes serán eliminados. ¡No podrá deshacerse!</string>
<string name="switching_profile_error_title">Error al cambiar perfil</string>
<string name="select_chat_profile">Selecciona perfil de chat</string>
<string name="new_chat_share_profile">Comparte perfil</string>
<string name="switching_profile_error_message">Tu conexión ha sido trasladada a %s pero ha ocurrido un error inesperado al redirigirte al perfil.</string>
<string name="icon_descr_sound_muted">Sonido silenciado</string>
</resources>
File diff suppressed because it is too large Load Diff
@@ -413,7 +413,7 @@
<string name="icon_descr_group_inactive">Gruppo inattivo</string>
<string name="rcv_conn_event_switch_queue_phase_completed">indirizzo cambiato per te</string>
<string name="rcv_group_event_changed_member_role">ha cambiato il ruolo di %s in %s</string>
<string name="rcv_group_event_changed_your_role">cambiato il tuo ruolo in %s</string>
<string name="rcv_group_event_changed_your_role">ha cambiato il tuo ruolo in %s</string>
<string name="rcv_conn_event_switch_queue_phase_changing">cambio indirizzo…</string>
<string name="snd_conn_event_switch_queue_phase_changing_for_member">cambio indirizzo per %s…</string>
<string name="rcv_group_event_member_connected">si è connesso/a</string>
@@ -2105,4 +2105,7 @@
<string name="compose_forward_messages_n">Inoltro di %1$s messaggi</string>
<string name="forward_multiple">Inoltra messaggi…</string>
<string name="compose_save_messages_n">Salvataggio di %1$s messaggi</string>
<string name="icon_descr_sound_muted">Audio silenziato</string>
<string name="error_initializing_web_view_wrong_arch">Errore di inizializzazione di WebView. Assicurati di avere WebView installato e che la sua architettura supportata sia arm64.
\nErrore: %s</string>
</resources>
@@ -1886,4 +1886,9 @@
<string name="cannot_share_message_alert_title">メッセージを送信することができません</string>
<string name="cant_call_contact_alert_title">連絡先と通話することができません</string>
<string name="servers_info_sessions_connecting">接続待ち</string>
<string name="privacy_media_blur_radius_off">無し</string>
<string name="privacy_media_blur_radius_soft">控え目</string>
<string name="network_options_save_and_reconnect">保存して再接続</string>
<string name="privacy_media_blur_radius_strong">強め</string>
<string name="privacy_media_blur_radius_medium">普通</string>
</resources>
@@ -1888,7 +1888,7 @@
<string name="servers_info_private_data_disclaimer">Beginnend vanaf %s.
\nAlle gegevens zijn privé op uw apparaat.</string>
<string name="servers_info_connected_servers_section_header">Verbonden servers</string>
<string name="servers_info_subscriptions_connections_pending">in behandeling</string>
<string name="servers_info_subscriptions_connections_pending">In behandeling</string>
<string name="servers_info_previously_connected_servers_section_header">Eerder verbonden servers</string>
<string name="servers_info_proxied_servers_section_header">Proxied servers</string>
<string name="servers_info_subscriptions_total">Totaal</string>
@@ -1929,7 +1929,7 @@
<string name="downloaded_files">Gedownloade bestanden</string>
<string name="secured">Beveiligd</string>
<string name="size">Maat</string>
<string name="subscribed">Ingeschreven</string>
<string name="subscribed">Subscribed</string>
<string name="uploaded_files">Geüploade bestanden</string>
<string name="upload_errors">Upload fouten</string>
<string name="download_errors">Downloadfouten</string>
@@ -1938,7 +1938,7 @@
<string name="all_users">Alle profielen</string>
<string name="attempts_label">pogingen</string>
<string name="chunks_deleted">Stukken verwijderd</string>
<string name="completed">voltooid</string>
<string name="completed">Voltooid</string>
<string name="servers_info_sessions_connected">Verbonden</string>
<string name="servers_info_sessions_connecting">Verbinden</string>
<string name="servers_info_reconnect_server_error">Fout bij opnieuw verbinding maken met de server</string>
@@ -1977,8 +1977,8 @@
<string name="app_check_for_updates">Controleer op updates</string>
<string name="app_check_for_updates_notice_title">Controleer op updates</string>
<string name="app_check_for_updates_notice_disable">Uitschakelen</string>
<string name="subscription_errors">Inschrijving fouten</string>
<string name="subscription_results_ignored">Inschrijvingen genegeerd</string>
<string name="subscription_errors">Subscription fouten</string>
<string name="subscription_results_ignored">Subscriptions genegeerd</string>
<string name="app_check_for_updates_stable">Stabiel</string>
<string name="app_check_for_updates_update_available">Update beschikbaar: %s</string>
<string name="app_check_for_updates_canceled">Downloaden van update geannuleerd</string>
@@ -2076,4 +2076,32 @@
<string name="migrate_from_device_remove_archive_question">Archief verwijderen?</string>
<string name="delete_messages_cannot_be_undone_warning">Berichten worden verwijderd. Dit kan niet ongedaan worden gemaakt!</string>
<string name="migrate_from_device_uploaded_archive_will_be_removed">Het geüploade databasearchief wordt permanent van de servers verwijderd.</string>
<string name="n_file_errors">%1$d bestandsfout(en):
\n%2$s</string>
<string name="forward_files_messages_deleted_after_selection_title">%1$s berichten niet doorgestuurd</string>
<string name="forward_alert_title_messages_to_forward">%1$s bericht(en) doorsturen?</string>
<string name="network_proxy_auth">Proxy-authenticatie</string>
<string name="forward_files_messages_deleted_after_selection_desc">Berichten zijn verwijderd nadat u ze had geselecteerd.</string>
<string name="network_proxy_username">Gebruikersnaam</string>
<string name="n_other_file_errors">%1$d overige bestandsfout(en).</string>
<string name="error_forwarding_messages">Fout bij het doorsturen van berichten</string>
<string name="forward_alert_title_nothing_to_forward">Niets om door te sturen!</string>
<string name="forward_files_in_progress_desc">%1$d bestand(en) worden nog gedownload.</string>
<string name="forward_files_not_accepted_desc">%1$d bestand(en) zijn niet gedownload.</string>
<string name="forward_alert_forward_messages_without_files">Berichten doorsturen zonder bestanden?</string>
<string name="forward_files_failed_to_receive_desc">%1$d bestand(en) konden niet worden gedownload.</string>
<string name="forward_files_missing_desc">%1$d bestand(en) zijn verwijderd.</string>
<string name="forward_files_not_accepted_receive_files">Download</string>
<string name="compose_forward_messages_n">%1$s berichten doorsturen</string>
<string name="forward_multiple">Berichten doorsturen…</string>
<string name="compose_save_messages_n">%1$s berichten opslaan</string>
<string name="network_proxy_auth_mode_no_auth">Gebruik geen inloggegevens met proxy.</string>
<string name="network_proxy_auth_mode_isolate_by_auth_entity">Gebruik voor elke verbinding verschillende proxy-inloggegevens.</string>
<string name="network_proxy_auth_mode_isolate_by_auth_user">Gebruik voor elk profiel verschillende proxy-inloggegevens.</string>
<string name="network_proxy_random_credentials">Gebruik willekeurige inloggegevens</string>
<string name="network_proxy_auth_mode_username_password">Uw inloggegevens worden mogelijk niet-versleuteld verzonden.</string>
<string name="network_proxy_incorrect_config_title">Fout bij opslaan proxy</string>
<string name="network_proxy_incorrect_config_desc">Zorg ervoor dat de proxyconfiguratie correct is.</string>
<string name="network_proxy_password">Wachtwoord</string>
<string name="icon_descr_sound_muted">Geluid gedempt</string>
</resources>
@@ -2069,4 +2069,19 @@
<string name="v6_0_connect_faster_descr">Szybciej łącz się ze znajomymi.</string>
<string name="v6_0_connection_servers_status">Kontroluj swoją sieć</string>
<string name="v6_0_delete_many_messages_descr">Usuń do 20 wiadomości na raz.</string>
<string name="error_forwarding_messages">Błąd przekazywania wiadomości</string>
<string name="forward_files_not_accepted_desc">%1$d plik(ów/i) nie zostały pobrane.</string>
<string name="forward_alert_title_messages_to_forward">Czy przekazać %1$s wiadomoś(ć/ci)?</string>
<string name="forward_alert_forward_messages_without_files">Przekazać wiadomości bez plików?</string>
<string name="forward_files_missing_desc">%1$d plik(ów/i) zostały usunięte.</string>
<string name="forward_files_messages_deleted_after_selection_title">%1$s wiadomoś(ć/ci) nie przekazane</string>
<string name="compose_forward_messages_n">Przekazywanie %1$s wiadomoś(ć/ci)</string>
<string name="forward_multiple">Przekazywanie wiadomości…</string>
<string name="network_proxy_auth_mode_no_auth">Nie używaj danych logowania do proxy.</string>
<string name="network_proxy_incorrect_config_title">Błąd zapisywania ustawień proxy</string>
<string name="network_proxy_incorrect_config_desc">Sprawdź czy konfiguracja serwera proxy jest poprawna.</string>
<string name="forward_files_in_progress_desc">%1$d plik(ów/i) dalej są pobierane.</string>
<string name="forward_files_failed_to_receive_desc">%1$d plik(ów/i) nie udało się pobrać.</string>
<string name="switching_profile_error_title">Błąd zmiany profilu</string>
<string name="settings_section_title_chat_database">BAZA CZATU</string>
</resources>
@@ -2068,4 +2068,40 @@
<string name="app_check_for_updates_button_remind_later">Me lembre mais tarde</string>
<string name="app_check_for_updates_notice_desc">Para ser notificado sobre os novos lançamentos, habilite a checagem periódica de versões Estáveis e Beta.</string>
<string name="one_hand_ui">Barra de ferramentas de conversa acessível</string>
<string name="forward_files_failed_to_receive_desc">Falha no baixar de %1$d arquivo(s).</string>
<string name="forward_files_messages_deleted_after_selection_title">%1$s mensagens não encaminhadas.</string>
<string name="settings_section_title_chat_database">DADOS DO BATE-PAPO</string>
<string name="network_proxy_random_credentials">Utilize credenciais aleatórias</string>
<string name="migrate_from_device_uploaded_archive_will_be_removed">O arquivo de banco de dados enviado será removido permanentemente dos servidores.</string>
<string name="network_proxy_auth_mode_isolate_by_auth_entity">Use credenciais diferentes de proxy para cada conexão.</string>
<string name="switching_profile_error_message">Sua conexão foi movida para %s, mas um erro inesperado ocorreu ao redirecioná-lo para o seu perfil.</string>
<string name="n_file_errors">%1$d erro(s) de arquivo(s):
\n%2$s</string>
<string name="n_other_file_errors">%1$d outro erro de arquivo.</string>
<string name="error_forwarding_messages">Erro ao encaminhar mensagens.</string>
<string name="forward_alert_title_messages_to_forward">Encaminhar %1$s mensagens?</string>
<string name="forward_alert_forward_messages_without_files">Encaminhar mensagens sem arquivos?</string>
<string name="forward_files_messages_deleted_after_selection_desc">As mensagens foram excluidas após vocês selecioná-las.</string>
<string name="forward_alert_title_nothing_to_forward">Nada para encaminhar!</string>
<string name="forward_files_in_progress_desc">%1$d arquivo(s) ainda estão sendo baixados.</string>
<string name="forward_files_missing_desc">%1$d arquivos foram excluidos.</string>
<string name="forward_files_not_accepted_desc">%1$d arquivos não foram baixados.</string>
<string name="forward_files_not_accepted_receive_files">Baixar</string>
<string name="forward_multiple">Emcaminhar mensagens…</string>
<string name="compose_forward_messages_n">Encaminhando %1$s mensagens.</string>
<string name="compose_save_messages_n">Salvando %1$s mensagens</string>
<string name="network_proxy_auth">Autenticação de proxy</string>
<string name="network_proxy_auth_mode_no_auth">Não utilize credenciais com proxy.</string>
<string name="network_proxy_incorrect_config_desc">Certifique-se de que configuração do proxy está correta.</string>
<string name="network_proxy_auth_mode_isolate_by_auth_user">Use diferentes credenciais de proxy para cada perfil.</string>
<string name="network_proxy_auth_mode_username_password">Suas credenciais podem ser enviadas sem criptografia.</string>
<string name="migrate_from_device_remove_archive_question">Remover arquivo?</string>
<string name="delete_messages_cannot_be_undone_warning">As mensagens serão excluídas - isso não pode ser desfeito!</string>
<string name="switching_profile_error_title">Erro ao alternar perfil</string>
<string name="select_chat_profile">Selecionar perfil de bate-papo</string>
<string name="new_chat_share_profile">Compartilhar perfil</string>
<string name="system_mode_toast">Modo sistema</string>
<string name="network_proxy_incorrect_config_title">Erro ao salvar proxy</string>
<string name="network_proxy_password">Senha</string>
<string name="network_proxy_username">Nome de usuário</string>
</resources>
@@ -674,4 +674,57 @@
<string name="migrate_from_device_delete_database_from_device">Șterge baza de date de pe acest dispozitiv</string>
<string name="delete_chat_profile">Șterge profil de conversație</string>
<string name="delete_files_and_media_for_all_users">Șterge fișiere pentru toate profilurile de conversație</string>
<string name="opensource_protocol_and_code_anybody_can_run_servers">Oricine poate găzdui servere.</string>
<string name="deleted_chats">Contacte arhivate</string>
<string name="app_check_for_updates_beta">Beta</string>
<string name="calls_prohibited_alert_title">Apeluri interzise!</string>
<string name="cant_call_member_alert_title">Nu se poate apela membrul grupului</string>
<string name="chat_database_exported_title">Bază de date conversație exportată</string>
<string name="app_check_for_updates">Verifică pentru actualizări</string>
<string name="profile_update_event_contact_name_changed">Contactul %1$s a schimbat la %2$s</string>
<string name="cant_call_contact_deleted_alert_text">Contactul este șters.</string>
<string name="v6_0_connection_servers_status">Controlează-ți rețeaua</string>
<string name="database_encryption_will_be_updated">Fraza de acces pentru criptarea bazei de date va fi actualizată și stocată în Keystore.</string>
<string name="database_passphrase">Fraza de acces a bazei de date</string>
<string name="xftp_servers_configured">Servere XFTP configurate</string>
<string name="set_password_to_export_desc">Baza de date este criptată folosind o expresie de acces aleatorie. Schimbați-o înainte de a exporta.</string>
<string name="info_view_call_button">apel</string>
<string name="info_view_connect_button">conectare</string>
<string name="contact_deleted">Contact șters!</string>
<string name="conversation_deleted">Conversație ștearsă!</string>
<string name="app_check_for_updates_download_completed_title">Actualizarea aplicației este descărcată</string>
<string name="app_check_for_updates_notice_title">Verifică pentru actualizări</string>
<string name="create_address_button">Creează</string>
<string name="privacy_media_blur_radius">Estompează media</string>
<string name="settings_section_title_chat_database">BAZĂ DE DATE CHAT</string>
<string name="v6_0_connect_faster_descr">Conectează-te cu prietenii mai ușor.</string>
<string name="attempts_label">încercări</string>
<string name="completed">Completat</string>
<string name="developer_options">ID-urile bazei de date și opțiunea de izolare a transportului.</string>
<string name="info_row_database_id">ID bază de date</string>
<string name="share_text_database_id">ID bază de date: %d</string>
<string name="connections">Conexiuni</string>
<string name="created">Creat</string>
<string name="v6_0_privacy_blur">Estompează pentru intimitate mai bună.</string>
<string name="v6_0_connection_servers_status_descr">Stare conexiune și servere</string>
<string name="database_error">Eroare bază de date</string>
<string name="contacts_can_mark_messages_for_deletion">Contactele pot marca mesajele pentru ștergere; tu le vei putea vedea.</string>
<string name="database_downgrade">Downgrade al bazei de date</string>
<string name="database_migration_in_progress">Migrarea bazei de date este în proces.
\nPoate dura câteva minute.</string>
<string name="database_passphrase_and_export">Fraza de acces a bazei de date și export</string>
<string name="all_users">Toate profilurile</string>
<string name="current_user">Profil actual</string>
<string name="confirm_delete_contact_question">Confirmi ștergerea contactului?</string>
<string name="delete_contact_cannot_undo_warning">Contactul va fi șters - acest lucru nu poate fi anulat!</string>
<string name="smp_servers_configured">Servere SMP configurate</string>
<string name="servers_info_sessions_connected">Conectat</string>
<string name="correct_name_to">Corectează numele la %s?</string>
<string name="chat_database_exported_continue">Continuă</string>
<string name="encrypted_with_random_passphrase">Baza de date este criptată folosind o expresie de acces aleatorie, o poți schimba</string>
<string name="cant_send_message_to_member_alert_title">Nu se pot trimite mesaje membrului grupului</string>
<string name="servers_info_sessions_connecting">Se conectează</string>
<string name="servers_info_connected_servers_section_header">Servere conectate</string>
<string name="cant_call_contact_alert_title">Nu se poate apela contactul</string>
<string name="cant_call_contact_connecting_wait_alert_text">Se conectează la contact, te rog așteaptă sau verifică mai târziu!</string>
</resources>
@@ -592,7 +592,7 @@
<string name="hidden_profile_password">Gizli profil parolası</string>
<string name="how_to_use_markdown">Markdown nasıl kullanılır</string>
<string name="how_it_works">Nasıl çalışıyor</string>
<string name="immune_to_spam_and_abuse">Kötüye kullanmaya ve istenmeyen mesajlara duyarlı</string>
<string name="immune_to_spam_and_abuse">Spamdan etkilenmez</string>
<string name="icon_descr_hang_up">Çağırıyı bitir.</string>
<string name="icon_descr_flip_camera">Kameranın karşı yüzüne geç</string>
<string name="import_database_question">Konuşma veri tabanı içe aktarılsın mı?</string>
@@ -825,7 +825,7 @@
<string name="mark_read">Okundu olarak işaretle</string>
<string name="mark_unread">Okunmadı olarak işaretle</string>
<string name="chat_console">Sohbet konsolu</string>
<string name="onboarding_notifications_mode_periodic_desc"><![CDATA[<b>Pil için iyi</b>. Arka plan hizmeti mesajları 10 dakikada bir kontrol eder. Aramaları veya acil mesajları kaçırabilirsiniz.]]></string>
<string name="onboarding_notifications_mode_periodic_desc"><![CDATA[<b>Pil ömrü için iyi</b>. Uygulama mesajları 10 dakikada bir kontrol eder. Aramaları veya acil mesajları kaçırabilirsiniz.]]></string>
<string name="v4_4_verify_connection_security_desc">Güvenlik kodlarını kişilerinizle karşılaştırın.</string>
<string name="notifications_mode_service_desc">Arka plan hizmeti her zaman çalışır - mesajlar gelir gelmez bildirim gönderilir.</string>
<string name="onboarding_notifications_mode_off_desc"><![CDATA[<b>Pil için en iyisi</b>. Sadece uygulama çalışırken bildirim alırsınız (arka plan hizmeti YOK).]]></string>
@@ -1188,7 +1188,7 @@
<string name="la_lock_mode">SimpleX Kilit modu</string>
<string name="share_file">Dosya paylaş…</string>
<string name="periodic_notifications_desc">Uygulama yeni mesajları periyodik olarak alır - günde pilin yüzde birkaçını kullanır. Uygulama anlık bildirimleri kullanmaz - cihazınızdan gelen veriler sunuculara gönderilmez.</string>
<string name="first_platform_without_user_ids">Herhangi bir kullanıcı tanımlayıcısı olmayan ilk platform - tasarım gereği gizli.</string>
<string name="first_platform_without_user_ids">Herhangi bir kullanıcı tanımlayıcısı yok.</string>
<string name="icon_descr_speaker_off">Hoparlör kapalı</string>
<string name="sync_connection_force_desc">Şifreleme çalışıyor ve yeni bir şifreleme anlaşması gerekli değil. Yoksa bağlantı hataları ortaya çıkabilir!</string>
<string name="show_call_on_lock_screen">Göster</string>
@@ -1854,4 +1854,170 @@
<string name="message_queue_info_server_info">sunucu kuyruk bilgisi: %1$s
\n
\nson alınan msj: %2$s</string>
<string name="smp_proxy_error_connecting">Yönlendirme sunucusuna (%1$s) bağlantı sırasında hata oluştu. Lütfen daha sonra tekrar deneyin.</string>
<string name="file_error_relay">Dosya sunucusu hatası. %1$s</string>
<string name="scan_paste_link">Tara / Bağlantı yapıştır</string>
<string name="app_check_for_updates">Güncellemeleri kontrol et</string>
<string name="app_check_for_updates_disabled">Devre dışı</string>
<string name="app_check_for_updates_download_completed_title">Uygulama Güncellemesi indirildi</string>
<string name="app_check_for_updates_button_remind_later">Daha sonra hatırlat</string>
<string name="app_check_for_updates_notice_title">Güncellemeleri kontrol et</string>
<string name="servers_info_reconnect_server_message">Mesajı göndermeye zorlamak için sunucuya yeniden bağlan. Bu ekstra internet kullanır.</string>
<string name="servers_info_modal_error_title">Hata</string>
<string name="error_forwarding_messages">Mesajların yönlendirilmesi sırasında hata oluştu.</string>
<string name="file_error_no_file">Dosya bulunamadı - muhtemelen dosya silindi veya göderim iptal edildi.</string>
<string name="forward_alert_title_messages_to_forward">%1$s Mesaj yönlendirilsin mi ?</string>
<string name="selected_chat_items_nothing_selected">Hiçbir şey seçilmedi.</string>
<string name="forward_alert_title_nothing_to_forward">Yönlendirilecek bir şey yok!</string>
<string name="selected_chat_items_selected_n">%d seçildi.</string>
<string name="forward_alert_forward_messages_without_files">Mesajlar dosyalar olmadan iletilsin mi ?</string>
<string name="forward_files_messages_deleted_after_selection_desc">Mesajlar siz seçtikten sonra silindi.</string>
<string name="cannot_share_message_alert_title">Mesaj gönderilemedi</string>
<string name="forward_files_not_accepted_receive_files">İndir</string>
<string name="forward_multiple">Mesajları ilet..</string>
<string name="compose_forward_messages_n">%1$s mesaj iletiliyor</string>
<string name="compose_save_messages_n">%1$s Mesaj kayıt ediliyor.</string>
<string name="info_view_connect_button">bağlan</string>
<string name="info_view_call_button">Ara</string>
<string name="info_view_message_button">mesaj</string>
<string name="only_delete_conversation">Sadece sohbeti sil</string>
<string name="info_view_open_button">açık</string>
<string name="info_view_search_button">ara</string>
<string name="switching_profile_error_title">Profil değiştirme sırasında hata oluştu.</string>
<string name="select_chat_profile">Sohbet profili seç</string>
<string name="xftp_servers_configured">XFTP sunucuları yapılandırıldı</string>
<string name="media_and_file_servers">Medya ve dosya sunucuları</string>
<string name="network_proxy_auth_mode_no_auth">Proxy ile bilgeleri kullanma</string>
<string name="network_proxy_incorrect_config_title">Proxy kayıt edilirken hata oluştu.</string>
<string name="network_proxy_incorrect_config_desc">Proxy konfigürasyonunun doğru olduğundan emin olun.</string>
<string name="network_proxy_password">Şifre</string>
<string name="app_check_for_updates_beta">Beta</string>
<string name="app_check_for_updates_download_started">Uygulama güncellemesi indiriliyor, uygulamayı kapatmayın</string>
<string name="app_check_for_updates_installed_successfully_title">Kurulum başarılı</string>
<string name="app_check_for_updates_button_install">Güncellemeyi Kur</string>
<string name="app_check_for_updates_button_open">Dosya konumunu aç</string>
<string name="app_check_for_updates_notice_disable">Devre dışı bırak</string>
<string name="app_check_for_updates_installed_successfully_desc">Lütfen uygulamayı yeniden başlatın.</string>
<string name="invite_friends_short">Davet</string>
<string name="create_address_button">Yarat</string>
<string name="privacy_media_blur_radius_off">Kapalı</string>
<string name="settings_section_title_chat_database">Mesajlaşma Veritabanı</string>
<string name="chat_database_exported_continue">Devam et</string>
<string name="share_text_message_status">Mesaj durumu: %s</string>
<string name="appearance_font_size">Yazı tipi boyutu</string>
<string name="v6_0_new_chat_experience">Yeni bir sohbet deneyimi 🎉</string>
<string name="v6_0_connection_servers_status">Ağınızı kontrol edin</string>
<string name="v6_0_connection_servers_status_descr">Bağlantı ve sunucuların durumu</string>
<string name="v6_0_increase_font_size">Yazı boyutunu arttır</string>
<string name="remote_ctrl_connection_stopped_desc">Lütfen telefonun ve bilgisayarın aynı lokal ağa bağlı olduğundan ve bilgisayar güvenlik duvarının bağlantıya izin verdiğinden emin olun. Lütfen diğer herhangi bir sorunu geliştiricilerle paylaşın.</string>
<string name="servers_info_reset_stats_alert_title">Tüm istatistikler sıfırlansın mı ?</string>
<string name="servers_info_reconnect_server_error">Hata, sunucuya yeniden bağlanılıyor</string>
<string name="servers_info_reconnect_all_servers_button">Tüm sunuculara yeniden bağlan</string>
<string name="duplicates_label">Kopyalar</string>
<string name="chunks_uploaded">Parçalar yüklendi</string>
<string name="downloaded_files">Dosyalar İndirildi</string>
<string name="download_errors">İndirme hataları</string>
<string name="info_row_message_status">Mesaj durumu</string>
<string name="error_parsing_uri_title">Geçersiz link</string>
<string name="error_parsing_uri_desc">Lütfen SimpleX linki doğru mu kontrol edin.</string>
<string name="proxy_destination_error_broker_host">Varış sunucusu ardesi (%1$s) yönlendirme sunucusu (%2$s) ile uyumsuz.</string>
<string name="proxy_destination_error_broker_version">Varış sunucusu sürümü (%1$s) yönlendirme sunucusu (%2$s) ile uyumsuz.</string>
<string name="message_forwarded_title">Mesaj iletildi</string>
<string name="member_inactive_desc">Kullanıcı aktif olursa mesaj iletilebilir.</string>
<string name="compose_message_placeholder">Mesaj</string>
<string name="deleted_chats">Arşivli kişiler</string>
<string name="no_filtered_contacts">Filtrelenmiş kişiler yok</string>
<string name="paste_link">Bağlantıyı yapıştır</string>
<string name="action_button_add_members">Davet et</string>
<string name="member_info_member_disabled">Devre dışı</string>
<string name="member_info_member_inactive">inaktif</string>
<string name="allow_calls_question">Aramalara izin verilsin mi ?</string>
<string name="calls_prohibited_alert_title">Aramalara izin verilmiyor</string>
<string name="cant_call_contact_deleted_alert_text">Kişi silindi.</string>
<string name="cant_send_message_to_member_alert_title">Grup üyesine mesaj gönderilemiyor</string>
<string name="cant_call_member_send_message_alert_text">Çağrıları aktif etmek için mesaj gönder.</string>
<string name="v6_0_your_contacts_descr">Daha sonra görüşmek için kişileri arşivleyin</string>
<string name="v6_0_private_routing_descr">IP adresinizi ve bağlantılarınızı korur.</string>
<string name="v6_0_new_media_options">Yeni medya seçenekleri</string>
<string name="v6_0_privacy_blur">Daha iyi gizlilik için bulanıklaştır.</string>
<string name="v6_0_connect_faster_descr">Arkadaşlarınıza daha hızlı bağlanın</string>
<string name="v6_0_delete_many_messages_descr">Aynı anda yirmiye kadar mesaj silin.</string>
<string name="v6_0_chat_list_media">Sohbet listesinden oynat.</string>
<string name="migrate_from_device_remove_archive_question">Arşiv kaldırılsın mı ?</string>
<string name="servers_info_sessions_connected">Bağlandı</string>
<string name="current_user">Aktif profil</string>
<string name="servers_info_files_tab">Dosyalar</string>
<string name="servers_info_missing">Bilgi yok, yenilemeyi deneyin</string>
<string name="servers_info_sessions_connecting">Bağlanıyor</string>
<string name="servers_info_sessions_errors">Hatalar</string>
<string name="servers_info_messages_received">Mesajlar alındı</string>
<string name="servers_info_messages_sent">Mesajlar gönderildi</string>
<string name="servers_info_reconnect_servers_message">Mesaj iletimine zorlamak için tüm sunuculara yeniden bağlan. Bu ekstra internet kullanılır.</string>
<string name="servers_info_reconnect_server_title">Sunucuya yeniden bağlansın mı ?</string>
<string name="servers_info_reconnect_servers_title">Sunuculara yeniden bağlanılsın mı ?</string>
<string name="servers_info_reconnect_servers_error">Hata sunuculara yeniden bağlanılıyor</string>
<string name="servers_info_reset_stats_alert_confirm">Sıfırla</string>
<string name="connections">Bağlantılar</string>
<string name="created">Yaratıldı</string>
<string name="decryption_errors">Şifre çözme hataları</string>
<string name="other_errors">diğer hatalar</string>
<string name="completed">Tamamlandı</string>
<string name="deleted">Silindi</string>
<string name="deletion_errors">Silme hatası</string>
<string name="open_server_settings_button">Sunucu ayarlarını aç</string>
<string name="share_text_file_status">Dosya durumu: %s</string>
<string name="new_message">Yeni mesaj</string>
<string name="smp_servers_other">Diğer SMP sunucuları</string>
<string name="reconnect">Yeniden bağlan</string>
<string name="sent_directly">Direkt gönderildi.</string>
<string name="all_users">Tüm Profiller</string>
<string name="cant_call_member_alert_title">Grup üyesi aranamıyor</string>
<string name="chat_database_exported_title">Veritabanı dışa aktarıldı</string>
<string name="chunks_deleted">Parçalar silindi</string>
<string name="chunks_downloaded">Parçalar indirildi</string>
<string name="servers_info_connected_servers_section_header">Sunucuayı bağlandı</string>
<string name="cant_call_contact_connecting_wait_alert_text">Kişiye bağlanılıyor, lütfen bekleyin ya da daha sonra kontrol edin.</string>
<string name="copy_error">Kopyalama hatası</string>
<string name="delete_without_notification">Bildirim göndermeden sil</string>
<string name="v6_0_upgrade_app_descr">Yeni versiyonları GitHub\'dan indirin</string>
<string name="servers_info_reset_stats_alert_error_title">Hata istatistikler sıfırlanıyor</string>
<string name="smp_proxy_error_broker_host">Yönlendirme sunucu adresi (%1$s) ağ ayarlarıyla uyumsuz.</string>
<string name="info_row_file_status">Dosya durumu</string>
<string name="proxy_destination_error_failed_to_connect">Yönlendirme sunucusu (%1$s) varış sunucusuna (%2$s) bağlanamadı. Lütfen daha sonra tekrar deneyin.</string>
<string name="smp_proxy_error_broker_version">Yönlendirme suncusu sürümü ağ ayarlarıyla uyumsuz. %1$s</string>
<string name="servers_info_subscriptions_connections_pending">Bekliyor</string>
<string name="calls_prohibited_ask_to_enable_calls_alert_text">Lütfen kişinizden çağrılara izin vermesini isteyin.</string>
<string name="servers_info_previously_connected_servers_section_header">Önceden bağlanılmış sunucular</string>
<string name="cant_call_contact_alert_title">Kişi aranamıyor</string>
<string name="network_options_save_and_reconnect">Kayıt et ve yeniden bağlan</string>
<string name="delete_messages_cannot_be_undone_warning">Mesajlar silinecek - bu geri alınamaz!</string>
<string name="delete_messages_mark_deleted_warning">Mesajlar silinmek üzere işaretlendi. Alıcılar bu mesajları görebilecek.</string>
<string name="delete_members_messages__question">Üylerin %d mesajı silinsin mi ?</string>
<string name="member_inactive_title">Üye inaktif</string>
<string name="message_forwarded_desc">Henüz direkt bağlantı yok mesaj admin tarafından yönlendirildi.</string>
<string name="message_servers">Mesaj sunucuları</string>
<string name="smp_servers_configured">SMP sunucları yapılandırıldı</string>
<string name="xftp_servers_other">Diğer XFTP sunucuları</string>
<string name="privacy_media_blur_radius">Medyayı bulanıklaştır.</string>
<string name="delete_contact_cannot_undo_warning">Kişiler silinecek - bu geri alınamaz !</string>
<string name="keep_conversation">Sohbeti sakla.</string>
<string name="confirm_delete_contact_question">Kişiyi silmek istediğinizden emin misiniz ?</string>
<string name="conversation_deleted">Sohbet silindi!</string>
<string name="contact_deleted">Kişiler silindi!</string>
<string name="please_try_later">Lütfen sonra tekrar deneyin</string>
<string name="private_routing_error">Gizli yönlendirme hatası</string>
<string name="file_error">Dosya hatası</string>
<string name="servers_info_details">Detaylar</string>
<string name="expired_label">Süresi dolmuş</string>
<string name="send_errors">Gönderme hataları</string>
<string name="attempts_label">denemeler</string>
<string name="servers_info_detailed_statistics">Detaylı istatistikler</string>
<string name="servers_info_downloaded">İndirildi</string>
<string name="other_label">diğer</string>
<string name="servers_info_detailed_statistics_received_messages_header">Alınan mesajlar</string>
<string name="servers_info_detailed_statistics_received_total">Toplam alınan</string>
<string name="select_verb">Seç</string>
<string name="cannot_share_message_alert_text">Seçilen sohbet tercihleri bu mesajı yasakladı.</string>
<string name="servers_info_reset_stats">Tüm istatistikleri sıfırla</string>
<string name="reset_all_hints">Tüm ip uçlarını sıfırla</string>
</resources>
@@ -2086,4 +2086,22 @@
<string name="network_proxy_password">Пароль</string>
<string name="network_proxy_username">Ім\'я користувача</string>
<string name="network_proxy_auth_mode_isolate_by_auth_user">Використовуйте різні облікові дані проксі для кожного профілю.</string>
<string name="n_other_file_errors">%1$d інша(і) помилка(и) файлу.</string>
<string name="forward_files_failed_to_receive_desc">%1$d файл(и) не вдалося завантажити.</string>
<string name="forward_files_messages_deleted_after_selection_title">%1$s повідомлень не було переслано.</string>
<string name="forward_files_not_accepted_receive_files">Завантажити</string>
<string name="forward_alert_title_messages_to_forward">Переслати %1$s повідомлень?</string>
<string name="forward_multiple">Пересилаю повідомлення…</string>
<string name="forward_alert_forward_messages_without_files">Переслати повідомлення без файлів?</string>
<string name="forward_alert_title_nothing_to_forward">Немає нічого для пересилання!</string>
<string name="compose_save_messages_n">Зберігаю %1$s повідомлень.</string>
<string name="n_file_errors">%1$d помилка(и) файлу:
\n%2$s</string>
<string name="forward_files_not_accepted_desc">%1$d файл(и) не були завантажені.</string>
<string name="forward_files_in_progress_desc">%1$d файл(и) ще завантажуються.</string>
<string name="forward_files_missing_desc">%1$d файл(и) були видалені.</string>
<string name="compose_forward_messages_n">Пересилаю %1$s повідомлень</string>
<string name="forward_files_messages_deleted_after_selection_desc">Повідомлення були видалені після того, як ви їх вибрали.</string>
<string name="error_forwarding_messages">Помилка при пересиланні повідомлень</string>
<string name="icon_descr_sound_muted">Звук вимкнено</string>
</resources>
@@ -829,4 +829,59 @@
<string name="smp_proxy_error_broker_version">Phiên bản máy chủ chuyển tiếp không tương thích với cài đặt mạng: %1$s.</string>
<string name="section_title_for_console">CHO CONSOLE</string>
<string name="forward_message">Chuyển tiếp tin nhắn…</string>
<string name="v4_6_reduced_battery_usage">Giảm thiểu sử dụng pin hơn nữa</string>
<string name="forward_alert_forward_messages_without_files">Chuyển tiếp tin nhắn mà không có tệp?</string>
<string name="wallpaper_preview_hello_alice">Chào buổi chiều!</string>
<string name="v4_4_french_interface">Giao diện tiếng Pháp</string>
<string name="found_desktop">Đã tìm thấy máy tính</string>
<string name="simplex_link_mode_full">Liên kết đầy đủ</string>
<string name="from_gallery_button">Từ Thư viện</string>
<string name="full_name__field">Tên đầy đủ:</string>
<string name="group_is_decentralized">Tuyệt đối phi tập trung - chỉ hiển thị cho thành viên.</string>
<string name="wallpaper_preview_hello_bob">Chào buổi sáng!</string>
<string name="group_member_status_group_deleted">nhóm đã bị xóa</string>
<string name="group_members_can_add_message_reactions">Các thành viên nhóm có thể thả cảm xúc tin nhắn.</string>
<string name="group_members_can_delete">Các thành viên nhóm có thể xóa theo cách không thể hồi phục các tin nhắn đã gửi. (24 giờ)</string>
<string name="group_members_can_send_voice">Các thành viên trong nhóm có thể gửi tin nhắn thoại.</string>
<string name="permissions_required">Cấp quyền</string>
<string name="group_link">Liên kết nhóm</string>
<string name="info_row_group">Nhóm</string>
<string name="group_full_name_field">Tên đầy đủ nhóm:</string>
<string name="group_members_can_send_disappearing">Các thành viên trong nhóm có thể gửi tin nhắn tự xóa.</string>
<string name="group_members_can_send_files">Các thành viên trong nhóm có thể gửi tệp và phương tiện truyền thông.</string>
<string name="group_members_can_send_simplex_links">Các thành viên trong nhóm có thể gửi liên kết SimpleX.</string>
<string name="icon_descr_group_inactive">Nhóm không hoạt động</string>
<string name="connect_plan_group_already_exists">Nhóm đã tồn tại rồi!</string>
<string name="group_members_can_send_dms">Các thành viên trong nhóm có thể gửi tin nhắn trực tiếp.</string>
<string name="v4_2_group_links">Liên kết nhóm</string>
<string name="group_invitation_expired">Lời mời nhóm đã hết hạn</string>
<string name="alert_message_group_invitation_expired">Lời mới nhóm không còn có hiệu lực, nó đã bị xóa bởi người gửi.</string>
<string name="permissions_grant">Cho phép thực hiện cuộc gọi</string>
<string name="permissions_grant_in_settings">Cấp quyền trong cài đặt</string>
<string name="hide_notification">Ẩn</string>
<string name="icon_descr_hang_up">Ngắt kết nối</string>
<string name="notification_preview_mode_hidden">Ẩn</string>
<string name="hidden_profile_password">Mật khẩu hồ sơ ẩn</string>
<string name="group_profile_is_stored_on_members_devices">Hồ sơ nhóm được lưu trữ tại thiết bị của thành viên, không lưu trữ trên máy chủ.</string>
<string name="snd_group_event_group_profile_updated">hồ sơ nhóm đã được cập nhật</string>
<string name="icon_descr_help">trợ giúp</string>
<string name="hide_dev_options">Ẩn:</string>
<string name="email_invite_body">Xin chào!
\nKết nối với tôi qua SimpleX Chat: %s</string>
<string name="hide_profile">Ẩn hồ sơ</string>
<string name="settings_section_title_help">TRỢ GIÚP</string>
<string name="delete_group_for_all_members_cannot_undo_warning">Nhóm sẽ bị xóa cho tất cả các thành viên - điều này không thể hoàn tác!</string>
<string name="delete_group_for_self_cannot_undo_warning">Nhóm sẽ bị xóa cho bạn - điều này không thể hoàn tác!</string>
<string name="group_preferences">Tùy chọn nhóm</string>
<string name="recent_history_is_not_sent_to_new_members">Lịch sử không được gửi đến các thành viên mới.</string>
<string name="v4_3_improved_privacy_and_security_desc">Ẩn màn hình ứng dụng trong danh sách các ứng dụng gần đây.</string>
<string name="v4_6_group_moderation">Quản trị nhóm</string>
<string name="v4_6_group_welcome_message">Lời chào nhóm</string>
<string name="audio_device_wired_headphones">Tai nghe</string>
<string name="notification_display_mode_hidden_desc">Ẩn liên hệ và tin nhắn</string>
<string name="hide_verb">Ẩn</string>
<string name="user_hide">Ẩn</string>
<string name="edit_history">Lịch sử</string>
<string name="alert_title_no_group">Không tìm thấy nhóm!</string>
<string name="v4_6_hidden_chat_profiles">Hồ sơ trò chuyện ẩn</string>
</resources>
@@ -2087,4 +2087,22 @@
<string name="network_proxy_random_credentials">使用随机凭据</string>
<string name="network_proxy_username">用户名</string>
<string name="new_chat_share_profile">分享配置文件</string>
<string name="error_forwarding_messages">转发消息出错</string>
<string name="forward_files_messages_deleted_after_selection_desc">在你选中消息后这些消息被删除。</string>
<string name="n_file_errors">%1$d 个文件错误:
\n%2$s</string>
<string name="n_other_file_errors">其他 %1$d 个文件错误。</string>
<string name="forward_files_not_accepted_desc">%1$d 个文件未被下载。</string>
<string name="forward_alert_title_messages_to_forward">转发 %1$s 条消息?</string>
<string name="forward_alert_forward_messages_without_files">仅转发消息不转发文件?</string>
<string name="forward_alert_title_nothing_to_forward">没什么可转发的!</string>
<string name="forward_files_in_progress_desc">仍有 %1$d 个文件在下载中。</string>
<string name="forward_files_failed_to_receive_desc">%1$d 个文件下载失败。</string>
<string name="forward_files_missing_desc">%1$d 个文件被删除了。</string>
<string name="forward_files_not_accepted_receive_files">下载</string>
<string name="forward_files_messages_deleted_after_selection_title">%1$s 条消息未被转发</string>
<string name="forward_multiple">转发消息…</string>
<string name="compose_forward_messages_n">转发 %1$s 条消息</string>
<string name="compose_save_messages_n">保存 %1$s 条消息</string>
<string name="icon_descr_sound_muted">已静音</string>
</resources>
@@ -62,6 +62,9 @@ fun AppearanceScope.AppearanceLayout(
SectionDividerSpaced()
ThemesSection(systemDarkTheme)
SectionDividerSpaced()
MessageShapeSection()
SectionDividerSpaced()
ProfileImageSection()
+4 -4
View File
@@ -26,11 +26,11 @@ android.enableJetifier=true
kotlin.mpp.androidSourceSetLayoutVersion=2
kotlin.jvm.target=11
android.version_name=6.1-beta.2
android.version_code=243
android.version_name=6.1-beta.3
android.version_code=244
desktop.version_name=6.1-beta.2
desktop.version_code=69
desktop.version_name=6.1-beta.3
desktop.version_code=70
kotlin.version=1.9.23
gradle.plugin.version=8.2.0
+1 -1
View File
@@ -12,7 +12,7 @@ constraints: zip +disable-bzip2 +disable-zstd
source-repository-package
type: git
location: https://github.com/simplex-chat/simplexmq.git
tag: da79d544cf990fb0638ae5434407d6a30724fb87
tag: b8971a31bcb82fffabcb792c9afd6bc4a96ec649
source-repository-package
type: git
+1 -1
View File
@@ -1,5 +1,5 @@
name: simplex-chat
version: 6.1.0.5
version: 6.1.0.6
#synopsis:
#description:
homepage: https://github.com/simplex-chat/simplex-chat#readme
+1 -1
View File
@@ -1,5 +1,5 @@
{
"https://github.com/simplex-chat/simplexmq.git"."da79d544cf990fb0638ae5434407d6a30724fb87" = "11rxpcg2g781rbr5d20fw6zpv81q06w3c9bh6qh5cpnza230yvl3";
"https://github.com/simplex-chat/simplexmq.git"."b8971a31bcb82fffabcb792c9afd6bc4a96ec649" = "1p6m390ngcsp7i7vy0m0zxh167gkbciavva9a00l6pxwzaz9qmpi";
"https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38";
"https://github.com/simplex-chat/direct-sqlcipher.git"."f814ee68b16a9447fbb467ccc8f29bdd3546bfd9" = "1ql13f4kfwkbaq7nygkxgw84213i0zm7c1a8hwvramayxl38dq5d";
"https://github.com/simplex-chat/sqlcipher-simple.git"."a46bd361a19376c5211f1058908fc0ae6bf42446" = "1z0r78d8f0812kxbgsm735qf6xx8lvaz27k1a0b4a2m0sshpd5gl";
+1 -1
View File
@@ -5,7 +5,7 @@ cabal-version: 1.12
-- see: https://github.com/sol/hpack
name: simplex-chat
version: 6.1.0.5
version: 6.1.0.6
category: Web, System, Services, Cryptography
homepage: https://github.com/simplex-chat/simplex-chat#readme
author: simplex.chat
+22 -10
View File
@@ -54,7 +54,6 @@ import qualified Data.Text as T
import Data.Text.Encoding (decodeLatin1, encodeUtf8)
import Data.Time (NominalDiffTime, addUTCTime, defaultTimeLocale, formatTime)
import Data.Time.Clock (UTCTime, diffUTCTime, getCurrentTime, nominalDay, nominalDiffTimeToSeconds)
import Data.Time.Clock.System (systemToUTCTime)
import qualified Data.UUID as UUID
import qualified Data.UUID.V4 as V4
import Data.Word (Word32)
@@ -342,11 +341,11 @@ newChatController
userServers user' = useServers config protocol <$> withTransaction chatStore (`getProtocolServers` user')
updateNetworkConfig :: NetworkConfig -> SimpleNetCfg -> NetworkConfig
updateNetworkConfig cfg SimpleNetCfg {socksProxy, socksMode, hostMode, requiredHostMode, smpProxyMode_, smpProxyFallback_, tcpTimeout_, logTLSErrors} =
updateNetworkConfig cfg SimpleNetCfg {socksProxy, socksMode, hostMode, requiredHostMode, smpProxyMode_, smpProxyFallback_, smpWebPort, tcpTimeout_, logTLSErrors} =
let cfg1 = maybe cfg (\smpProxyMode -> cfg {smpProxyMode}) smpProxyMode_
cfg2 = maybe cfg1 (\smpProxyFallback -> cfg1 {smpProxyFallback}) smpProxyFallback_
cfg3 = maybe cfg2 (\tcpTimeout -> cfg2 {tcpTimeout, tcpConnectTimeout = (tcpTimeout * 3) `div` 2}) tcpTimeout_
in cfg3 {socksProxy, socksMode, hostMode, requiredHostMode, logTLSErrors}
in cfg3 {socksProxy, socksMode, hostMode, requiredHostMode, smpWebPort, logTLSErrors}
withChatLock :: String -> CM a -> CM a
withChatLock name action = asks chatLock >>= \l -> withLock l name action
@@ -1452,14 +1451,25 @@ processChatCommand' vr = \case
APIVerifyToken token nonce code -> withUser $ \_ -> withAgent (\a -> verifyNtfToken a token nonce code) >> ok_
APIDeleteToken token -> withUser $ \_ -> withAgent (`deleteNtfToken` token) >> ok_
APIGetNtfMessage nonce encNtfInfo -> withUser $ \_ -> do
(NotificationInfo {ntfConnId, ntfMsgMeta}, msg) <- withAgent $ \a -> getNotificationMessage a nonce encNtfInfo
let msgTs' = systemToUTCTime . (\SMP.NMsgMeta {msgTs} -> msgTs) <$> ntfMsgMeta
agentConnId = AgentConnId ntfConnId
(NotificationInfo {ntfConnId, ntfMsgMeta = nMsgMeta}, msg) <- withAgent $ \a -> getNotificationMessage a nonce encNtfInfo
let agentConnId = AgentConnId ntfConnId
user_ <- withStore' (`getUserByAConnId` agentConnId)
connEntity_ <-
pure user_ $>>= \user ->
withStore (\db -> Just <$> getConnectionEntity db vr user agentConnId) `catchChatError` (\e -> toView (CRChatError (Just user) e) $> Nothing)
pure CRNtfMessages {user_, connEntity_, msgTs = msgTs', ntfMessage_ = ntfMsgInfo <$> msg}
pure
CRNtfMessages
{ user_,
connEntity_,
-- Decrypted ntf meta of the expected message (the one notification was sent for)
expectedMsg_ = expectedMsgInfo <$> nMsgMeta,
-- Info of the first message retrieved by agent using GET
-- (may differ from the expected message due to, for example, coalescing or loss of notifications)
receivedMsg_ = receivedMsgInfo <$> msg
}
ApiGetConnNtfMessage (AgentConnId connId) -> withUser $ \_ -> do
msg <- withAgent $ \a -> getConnectionMessage a connId
pure $ CRConnNtfMessage (receivedMsgInfo <$> msg)
APIGetUserProtoServers userId (AProtocolType p) -> withUserId userId $ \user -> withServerProtocol p $ do
cfg@ChatConfig {defaultServers} <- asks config
servers <- withFastStore' (`getProtocolServers` user)
@@ -4343,7 +4353,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
END -> case entity of
RcvDirectMsgConnection _ (Just ct) -> toView $ CRContactAnotherClient user ct
_ -> toView $ CRSubscriptionEnd user entity
MSGNTF smpMsgInfo -> toView $ CRNtfMessage user entity $ ntfMsgInfo smpMsgInfo
MSGNTF msgId msgTs_ -> toView $ CRNtfMessage user entity $ ntfMsgAckInfo msgId msgTs_
_ -> case entity of
RcvDirectMsgConnection conn contact_ ->
processDirectMessage agentMessage entity conn contact_
@@ -8012,6 +8022,7 @@ chatCommandP =
"/_ntf verify " *> (APIVerifyToken <$> strP <* A.space <*> strP <* A.space <*> strP),
"/_ntf delete " *> (APIDeleteToken <$> strP),
"/_ntf message " *> (APIGetNtfMessage <$> strP <* A.space <*> strP),
"/_ntf conn message " *> (ApiGetConnNtfMessage <$> strP),
"/_add #" *> (APIAddMember <$> A.decimal <* A.space <*> A.decimal <*> memberRole),
"/_join #" *> (APIJoinGroup <$> A.decimal),
"/_member role #" *> (APIMemberRole <$> A.decimal <* A.space <*> A.decimal <*> memberRole),
@@ -8356,13 +8367,14 @@ chatCommandP =
socksProxy <- "socks=" *> ("off" $> Nothing <|> "on" $> Just defaultSocksProxyWithAuth <|> Just <$> strP)
socksMode <- " socks-mode=" *> strP <|> pure SMAlways
hostMode <- " host-mode=" *> (textToHostMode . safeDecodeUtf8 <$?> A.takeTill (== ' ')) <|> pure (defaultHostMode socksProxy)
requiredHostMode <- " required-host-mode" *> onOffP <|> pure False
requiredHostMode <- (" required-host-mode" $> True) <|> pure False
smpProxyMode_ <- optional $ " smp-proxy=" *> strP
smpProxyFallback_ <- optional $ " smp-proxy-fallback=" *> strP
smpWebPort <- (" smp-web-port" $> True) <|> pure False
t_ <- optional $ " timeout=" *> A.decimal
logTLSErrors <- " log=" *> onOffP <|> pure False
let tcpTimeout_ = (1000000 *) <$> t_
pure $ SimpleNetCfg {socksProxy, socksMode, hostMode, requiredHostMode, smpProxyMode_, smpProxyFallback_, tcpTimeout_, logTLSErrors}
pure $ SimpleNetCfg {socksProxy, socksMode, hostMode, requiredHostMode, smpProxyMode_, smpProxyFallback_, smpWebPort, tcpTimeout_, logTLSErrors}
dbKeyP = nonEmptyKey <$?> strP
nonEmptyKey k@(DBEncryptionKey s) = if BA.null s then Left "empty key" else Right k
dbEncryptionConfig currentKey newKey = DBEncryptionConfig {currentKey, newKey, keepKey = Just False}
+12
View File
@@ -50,6 +50,8 @@ data AppSettings = AppSettings
iosCallKitEnabled :: Maybe Bool,
iosCallKitCallsInRecents :: Maybe Bool,
uiProfileImageCornerRadius :: Maybe Double,
uiChatItemRoundness :: Maybe Double,
uiChatItemTail :: Maybe Bool,
uiColorScheme :: Maybe UIColorScheme,
uiDarkColorScheme :: Maybe DarkColorScheme,
uiCurrentThemeIds :: Maybe (Map ThemeColorScheme Text),
@@ -97,6 +99,8 @@ defaultAppSettings =
iosCallKitEnabled = Just True,
iosCallKitCallsInRecents = Just False,
uiProfileImageCornerRadius = Just 22.5,
uiChatItemRoundness = Just 0.75,
uiChatItemTail = Just True,
uiColorScheme = Just UCSSystem,
uiDarkColorScheme = Just DCSSimplex,
uiCurrentThemeIds = Nothing,
@@ -131,6 +135,8 @@ defaultParseAppSettings =
iosCallKitEnabled = Nothing,
iosCallKitCallsInRecents = Nothing,
uiProfileImageCornerRadius = Nothing,
uiChatItemRoundness = Nothing,
uiChatItemTail = Nothing,
uiColorScheme = Nothing,
uiDarkColorScheme = Nothing,
uiCurrentThemeIds = Nothing,
@@ -165,6 +171,8 @@ combineAppSettings platformDefaults storedSettings =
iosCallKitCallsInRecents = p iosCallKitCallsInRecents,
androidCallOnLockScreen = p androidCallOnLockScreen,
uiProfileImageCornerRadius = p uiProfileImageCornerRadius,
uiChatItemRoundness = p uiChatItemRoundness,
uiChatItemTail = p uiChatItemTail,
uiColorScheme = p uiColorScheme,
uiDarkColorScheme = p uiDarkColorScheme,
uiCurrentThemeIds = p uiCurrentThemeIds,
@@ -215,6 +223,8 @@ instance FromJSON AppSettings where
iosCallKitCallsInRecents <- p "iosCallKitCallsInRecents"
androidCallOnLockScreen <- p "androidCallOnLockScreen"
uiProfileImageCornerRadius <- p "uiProfileImageCornerRadius"
uiChatItemRoundness <- p "uiChatItemRoundness"
uiChatItemTail <- p "uiChatItemTail"
uiColorScheme <- p "uiColorScheme"
uiDarkColorScheme <- p "uiDarkColorScheme"
uiCurrentThemeIds <- p "uiCurrentThemeIds"
@@ -246,6 +256,8 @@ instance FromJSON AppSettings where
iosCallKitCallsInRecents,
androidCallOnLockScreen,
uiProfileImageCornerRadius,
uiChatItemRoundness,
uiChatItemTail,
uiColorScheme,
uiDarkColorScheme,
uiCurrentThemeIds,
+36 -7
View File
@@ -44,7 +44,7 @@ import Data.String
import Data.Text (Text)
import Data.Text.Encoding (decodeLatin1)
import Data.Time (NominalDiffTime, UTCTime)
import Data.Time.Clock.System (systemToUTCTime)
import Data.Time.Clock.System (SystemTime (..), systemToUTCTime)
import Data.Version (showVersion)
import Data.Word (Word16)
import Database.SQLite.Simple (SQLError)
@@ -84,7 +84,7 @@ import Simplex.Messaging.Crypto.Ratchet (PQEncryption)
import Simplex.Messaging.Encoding.String
import Simplex.Messaging.Notifications.Protocol (DeviceToken (..), NtfTknStatus)
import Simplex.Messaging.Parsers (defaultJSON, dropPrefix, enumJSON, parseAll, parseString, sumTypeJSON)
import Simplex.Messaging.Protocol (AProtoServerWithAuth, AProtocolType (..), CorrId, NtfServer, ProtocolType (..), ProtocolTypeI, QueueId, SMPMsgMeta (..), SProtocolType, SubscriptionMode (..), UserProtocol, XFTPServer, userProtocol)
import Simplex.Messaging.Protocol (AProtoServerWithAuth, AProtocolType (..), CorrId, MsgId, NMsgMeta (..), NtfServer, ProtocolType (..), ProtocolTypeI, QueueId, SMPMsgMeta (..), SProtocolType, SubscriptionMode (..), UserProtocol, XFTPServer, userProtocol)
import Simplex.Messaging.TMap (TMap)
import Simplex.Messaging.Transport (TLS, simplexMQVersion)
import Simplex.Messaging.Transport.Client (SocksProxyWithAuth, TransportHost)
@@ -331,6 +331,7 @@ data ChatCommand
| APIVerifyToken DeviceToken C.CbNonce ByteString
| APIDeleteToken DeviceToken
| APIGetNtfMessage {nonce :: C.CbNonce, encNtfInfo :: ByteString}
| ApiGetConnNtfMessage {connId :: AgentConnId}
| APIAddMember GroupId ContactId GroupMemberRole
| APIJoinGroup GroupId
| APIMemberRole GroupId GroupMemberId GroupMemberRole
@@ -744,8 +745,9 @@ data ChatResponse
| CRUserContactLinkSubError {chatError :: ChatError} -- TODO delete
| CRNtfTokenStatus {status :: NtfTknStatus}
| CRNtfToken {token :: DeviceToken, status :: NtfTknStatus, ntfMode :: NotificationsMode, ntfServer :: NtfServer}
| CRNtfMessages {user_ :: Maybe User, connEntity_ :: Maybe ConnectionEntity, msgTs :: Maybe UTCTime, ntfMessage_ :: Maybe NtfMsgInfo}
| CRNtfMessage {user :: User, connEntity :: ConnectionEntity, ntfMessage :: NtfMsgInfo}
| CRNtfMessages {user_ :: Maybe User, connEntity_ :: Maybe ConnectionEntity, expectedMsg_ :: Maybe NtfMsgInfo, receivedMsg_ :: Maybe NtfMsgInfo}
| CRConnNtfMessage {receivedMsg_ :: Maybe NtfMsgInfo}
| CRNtfMessage {user :: User, connEntity :: ConnectionEntity, ntfMessage :: NtfMsgAckInfo}
| CRContactConnectionDeleted {user :: User, connection :: PendingContactConnection}
| CRRemoteHostList {remoteHosts :: [RemoteHostInfo]}
| CRCurrentRemoteHost {remoteHost_ :: Maybe RemoteHostInfo}
@@ -990,13 +992,25 @@ data SimpleNetCfg = SimpleNetCfg
requiredHostMode :: Bool,
smpProxyMode_ :: Maybe SMPProxyMode,
smpProxyFallback_ :: Maybe SMPProxyFallback,
smpWebPort :: Bool,
tcpTimeout_ :: Maybe Int,
logTLSErrors :: Bool
}
deriving (Show)
defaultSimpleNetCfg :: SimpleNetCfg
defaultSimpleNetCfg = SimpleNetCfg Nothing SMAlways HMOnionViaSocks True Nothing Nothing Nothing False
defaultSimpleNetCfg =
SimpleNetCfg
{ socksProxy = Nothing,
socksMode = SMAlways,
hostMode = HMOnionViaSocks,
requiredHostMode = False,
smpProxyMode_ = Nothing,
smpProxyFallback_ = Nothing,
smpWebPort = False,
tcpTimeout_ = Nothing,
logTLSErrors = False
}
data ContactSubStatus = ContactSubStatus
{ contact :: Contact,
@@ -1052,8 +1066,21 @@ instance FromJSON ComposedMessage where
data NtfMsgInfo = NtfMsgInfo {msgId :: Text, msgTs :: UTCTime}
deriving (Show)
ntfMsgInfo :: SMPMsgMeta -> NtfMsgInfo
ntfMsgInfo SMPMsgMeta {msgId, msgTs} = NtfMsgInfo {msgId = decodeLatin1 $ strEncode msgId, msgTs = systemToUTCTime msgTs}
receivedMsgInfo :: SMPMsgMeta -> NtfMsgInfo
receivedMsgInfo SMPMsgMeta {msgId, msgTs} = ntfMsgInfo_ msgId msgTs
expectedMsgInfo :: NMsgMeta -> NtfMsgInfo
expectedMsgInfo NMsgMeta {msgId, msgTs} = ntfMsgInfo_ msgId msgTs
ntfMsgInfo_ :: MsgId -> SystemTime -> NtfMsgInfo
ntfMsgInfo_ msgId msgTs = NtfMsgInfo {msgId = decodeLatin1 $ strEncode msgId, msgTs = systemToUTCTime msgTs}
-- Acknowledged message info - used to correlate with expected message
data NtfMsgAckInfo = NtfMsgAckInfo {msgId :: Text, msgTs_ :: Maybe UTCTime}
deriving (Show)
ntfMsgAckInfo :: MsgId -> Maybe UTCTime -> NtfMsgAckInfo
ntfMsgAckInfo msgId msgTs_ = NtfMsgAckInfo {msgId = decodeLatin1 $ strEncode msgId, msgTs_}
crNtfToken :: (DeviceToken, NtfTknStatus, NotificationsMode, NtfServer) -> ChatResponse
crNtfToken (token, status, ntfMode, ntfServer) = CRNtfToken {token, status, ntfMode, ntfServer}
@@ -1504,6 +1531,8 @@ $(JQ.deriveJSON defaultJSON ''UserProfileUpdateSummary)
$(JQ.deriveJSON defaultJSON ''NtfMsgInfo)
$(JQ.deriveJSON defaultJSON ''NtfMsgAckInfo)
$(JQ.deriveJSON defaultJSON ''SwitchProgress)
$(JQ.deriveJSON defaultJSON ''RatchetSyncProgress)
+6
View File
@@ -170,6 +170,11 @@ coreChatOptsP appDir defaultDbFileName = do
<> metavar "SMP_PROXY_FALLBACK_MODE"
<> help "Allow downgrade and connect directly: no, [when IP address is] protected (default), yes"
)
smpWebPort <-
switch
( long "smp-web-port"
<> help "Use port 443 with SMP servers when not specified"
)
t <-
option
auto
@@ -249,6 +254,7 @@ coreChatOptsP appDir defaultDbFileName = do
requiredHostMode,
smpProxyMode_,
smpProxyFallback_,
smpWebPort,
tcpTimeout_ = Just $ useTcpTimeout socksProxy t,
logTLSErrors
},
+1
View File
@@ -326,6 +326,7 @@ responseToView hu@(currentRH, user_) ChatConfig {logLevel, showReactions, showRe
CRNtfTokenStatus status -> ["device token status: " <> plain (smpEncode status)]
CRNtfToken _ status mode srv -> ["device token status: " <> plain (smpEncode status) <> ", notifications mode: " <> plain (strEncode mode) <> ", server: " <> sShow srv]
CRNtfMessages {} -> []
CRConnNtfMessage {} -> []
CRNtfMessage {} -> []
CRCurrentRemoteHost rhi_ ->
[ maybe
+2 -2
View File
@@ -36,7 +36,7 @@ import Simplex.Chat.Terminal.Output (newChatTerminal)
import Simplex.Chat.Types
import Simplex.FileTransfer.Description (kb, mb)
import Simplex.FileTransfer.Server (runXFTPServerBlocking)
import Simplex.FileTransfer.Server.Env (XFTPServerConfig (..), defaultFileExpiration, supportedXFTPhandshakes)
import Simplex.FileTransfer.Server.Env (XFTPServerConfig (..), defaultFileExpiration)
import Simplex.FileTransfer.Transport (supportedFileServerVRange)
import Simplex.Messaging.Agent (disposeAgentClient)
import Simplex.Messaging.Agent.Env.SQLite
@@ -52,7 +52,7 @@ import Simplex.Messaging.Protocol (srvHostnamesSMPClientVersion)
import Simplex.Messaging.Server (runSMPServerBlocking)
import Simplex.Messaging.Server.Env.STM
import Simplex.Messaging.Transport
import Simplex.Messaging.Transport.Server (ServerCredentials (..), TransportServerConfig (..), defaultTransportServerConfig)
import Simplex.Messaging.Transport.Server (ServerCredentials (..), defaultTransportServerConfig)
import Simplex.Messaging.Version
import Simplex.Messaging.Version.Internal
import System.Directory (createDirectoryIfMissing, removeDirectoryRecursive)
+4 -1
View File
@@ -252,5 +252,8 @@
"please-enable-javascript": "Por favor habilite o JavaScript para ver o QR code.",
"jobs": "Junte-se à equipe",
"docs-dropdown-8": "Serviço de Diretório SimpleX",
"docs-dropdown-9": "Baixar"
"docs-dropdown-9": "Baixar",
"docs-dropdown-11": "FAQ",
"docs-dropdown-10": "Transparência",
"docs-dropdown-12": "Segurança"
}