diff --git a/apps/ios/Shared/Views/ChatList/ChatListNavLink.swift b/apps/ios/Shared/Views/ChatList/ChatListNavLink.swift index 0668d64441..3de6c93101 100644 --- a/apps/ios/Shared/Views/ChatList/ChatListNavLink.swift +++ b/apps/ios/Shared/Views/ChatList/ChatListNavLink.swift @@ -44,6 +44,7 @@ struct ChatListNavLink: View { @EnvironmentObject var chatModel: ChatModel @EnvironmentObject var theme: AppTheme @Environment(\.dynamicTypeSize) private var userFont: DynamicTypeSize + @AppStorage(GROUP_DEFAULT_ONE_HAND_UI, store: groupDefaults) private var oneHandUI = false @ObservedObject var chat: Chat @State private var showContactRequestDialog = false @State private var showJoinGroupDialog = false @@ -56,7 +57,7 @@ struct ChatListNavLink: View { @State private var inProgress = false @State private var progressByTimeout = false - var dynamicRowHeight: CGFloat { dynamicSizes[userFont]?.rowHeight ?? 80 } + var dynamicRowHeight: CGFloat { dynamicSize(userFont).rowHeight } var body: some View { Group { @@ -102,7 +103,7 @@ struct ChatListNavLink: View { showSheetContent: { sheet = $0 } ) } label: { - Label("Delete", systemImage: "trash") + deleteLabel } .tint(.red) } @@ -120,7 +121,7 @@ struct ChatListNavLink: View { .swipeActions(edge: .leading, allowsFullSwipe: true) { markReadButton() toggleFavoriteButton() - ToggleNtfsButton(chat: chat) + toggleNtfsButton(chat: chat) } .swipeActions(edge: .trailing, allowsFullSwipe: true) { if !chat.chatItems.isEmpty { @@ -136,7 +137,7 @@ struct ChatListNavLink: View { showSheetContent: { sheet = $0 } ) } label: { - Label("Delete", systemImage: "trash") + deleteLabel } .tint(.red) } @@ -202,7 +203,7 @@ struct ChatListNavLink: View { .swipeActions(edge: .leading, allowsFullSwipe: true) { markReadButton() toggleFavoriteButton() - ToggleNtfsButton(chat: chat) + toggleNtfsButton(chat: chat) } .swipeActions(edge: .trailing, allowsFullSwipe: true) { if !chat.chatItems.isEmpty { @@ -243,7 +244,7 @@ struct ChatListNavLink: View { await MainActor.run { inProgress = false } } } label: { - Label("Join", systemImage: chat.chatInfo.incognito ? "theatermasks" : "ipad.and.arrow.forward") + SwipeLabel(NSLocalizedString("Join", comment: "swipe action"), systemImage: chat.chatInfo.incognito ? "theatermasks" : "ipad.and.arrow.forward", inverted: oneHandUI) } .tint(chat.chatInfo.incognito ? .indigo : theme.colors.primary) } @@ -253,14 +254,14 @@ struct ChatListNavLink: View { Button { Task { await markChatRead(chat) } } label: { - Label("Read", systemImage: "checkmark") + SwipeLabel(NSLocalizedString("Read", comment: "swipe action"), systemImage: "checkmark", inverted: oneHandUI) } .tint(theme.colors.primary) } else { Button { Task { await markChatUnread(chat) } } label: { - Label("Unread", systemImage: "circlebadge.fill") + SwipeLabel(NSLocalizedString("Unread", comment: "swipe action"), systemImage: "circlebadge.fill", inverted: oneHandUI) } .tint(theme.colors.primary) } @@ -272,24 +273,36 @@ struct ChatListNavLink: View { Button { toggleChatFavorite(chat, favorite: false) } label: { - Label("Unfav.", systemImage: "star.slash") + SwipeLabel(NSLocalizedString("Unfav.", comment: "swipe action"), systemImage: "star.slash.fill", inverted: oneHandUI) } .tint(.green) } else { Button { toggleChatFavorite(chat, favorite: true) } label: { - Label("Favorite", systemImage: "star.fill") + SwipeLabel(NSLocalizedString("Favorite", comment: "swipe action"), systemImage: "star.fill", inverted: oneHandUI) } .tint(.green) } } + @ViewBuilder private func toggleNtfsButton(chat: Chat) -> some View { + Button { + toggleNotifications(chat, enableNtfs: !chat.chatInfo.ntfsEnabled) + } label: { + if chat.chatInfo.ntfsEnabled { + SwipeLabel(NSLocalizedString("Mute", comment: "swipe action"), systemImage: "speaker.slash.fill", inverted: oneHandUI) + } else { + SwipeLabel(NSLocalizedString("Unmute", comment: "swipe action"), systemImage: "speaker.wave.2.fill", inverted: oneHandUI) + } + } + } + private func clearChatButton() -> some View { Button { AlertManager.shared.showAlert(clearChatAlert()) } label: { - Label("Clear", systemImage: "gobackward") + SwipeLabel(NSLocalizedString("Clear", comment: "swipe action"), systemImage: "gobackward", inverted: oneHandUI) } .tint(Color.orange) } @@ -298,7 +311,7 @@ struct ChatListNavLink: View { Button { AlertManager.shared.showAlert(clearNoteFolderAlert()) } label: { - Label("Clear", systemImage: "gobackward") + SwipeLabel(NSLocalizedString("Clear", comment: "swipe action"), systemImage: "gobackward", inverted: oneHandUI) } .tint(Color.orange) } @@ -307,7 +320,7 @@ struct ChatListNavLink: View { Button { AlertManager.shared.showAlert(leaveGroupAlert(groupInfo)) } label: { - Label("Leave", systemImage: "rectangle.portrait.and.arrow.right") + SwipeLabel(NSLocalizedString("Leave", comment: "swipe action"), systemImage: "rectangle.portrait.and.arrow.right.fill", inverted: oneHandUI) } .tint(Color.yellow) } @@ -316,7 +329,7 @@ struct ChatListNavLink: View { Button { AlertManager.shared.showAlert(deleteGroupAlert(groupInfo)) } label: { - Label("Delete", systemImage: "trash") + deleteLabel } .tint(.red) } @@ -326,18 +339,18 @@ struct ChatListNavLink: View { .swipeActions(edge: .trailing, allowsFullSwipe: true) { Button { Task { await acceptContactRequest(incognito: false, contactRequest: contactRequest) } - } label: { Label("Accept", systemImage: "checkmark") } + } label: { SwipeLabel(NSLocalizedString("Accept", comment: "swipe action"), systemImage: "checkmark", inverted: oneHandUI) } .tint(theme.colors.primary) Button { Task { await acceptContactRequest(incognito: true, contactRequest: contactRequest) } } label: { - Label("Accept incognito", systemImage: "theatermasks") + SwipeLabel(NSLocalizedString("Accept incognito", comment: "swipe action"), systemImage: "theatermasks.fill", inverted: oneHandUI) } .tint(.indigo) Button { AlertManager.shared.showAlert(rejectContactRequestAlert(contactRequest)) } label: { - Label("Reject", systemImage: "multiply") + SwipeLabel(NSLocalizedString("Reject", comment: "swipe action"), systemImage: "multiply.fill", inverted: oneHandUI) } .tint(.red) } @@ -358,14 +371,14 @@ struct ChatListNavLink: View { AlertManager.shared.showAlertMsg(title: a.title, message: a.message) }) } label: { - Label("Delete", systemImage: "trash") + deleteLabel } .tint(.red) Button { showContactConnectionInfo = true } label: { - Label("Name", systemImage: "pencil") + SwipeLabel(NSLocalizedString("Name", comment: "swipe action"), systemImage: "pencil", inverted: oneHandUI) } .tint(theme.colors.primary) } @@ -384,6 +397,10 @@ struct ChatListNavLink: View { } } + private var deleteLabel: some View { + SwipeLabel(NSLocalizedString("Delete", comment: "swipe action"), systemImage: "trash.fill", inverted: oneHandUI) + } + private func deleteGroupAlert(_ groupInfo: GroupInfo) -> Alert { Alert( title: Text("Delete group?"), diff --git a/apps/ios/Shared/Views/ChatList/ChatListView.swift b/apps/ios/Shared/Views/ChatList/ChatListView.swift index 7f5a36adac..efe55152e9 100644 --- a/apps/ios/Shared/Views/ChatList/ChatListView.swift +++ b/apps/ios/Shared/Views/ChatList/ChatListView.swift @@ -20,10 +20,12 @@ struct ChatListView: View { @State private var searchChatFilteredBySimplexLink: String? = nil @State private var userPickerVisible = false @State private var showConnectDesktop = false + @State private var scrollToSearchBar = false @AppStorage(DEFAULT_SHOW_UNREAD_AND_FAVORITES) private var showUnreadAndFavorites = false - @AppStorage(DEFAULT_ONE_HAND_UI) private var oneHandUI = false - + @AppStorage(GROUP_DEFAULT_ONE_HAND_UI, store: groupDefaults) private var oneHandUI = true + @AppStorage(DEFAULT_ONE_HAND_UI_CARD_SHOWN) private var oneHandUICardShown = false + var body: some View { if #available(iOS 16.0, *) { viewBody.scrollDismissesKeyboard(.immediately) @@ -33,18 +35,14 @@ struct ChatListView: View { } private var viewBody: some View { - ZStack(alignment: .topLeading) { + ZStack(alignment: oneHandUI ? .bottomLeading : .topLeading) { NavStackCompat( isActive: Binding( get: { chatModel.chatId != nil }, set: { _ in } ), destination: chatView - ) { - VStack { - chatListView - } - } + ) { chatListView } if userPickerVisible { Rectangle().fill(.white.opacity(0.001)).onTapGesture { withAnimation { @@ -64,9 +62,11 @@ struct ChatListView: View { } private var chatListView: some View { - VStack { + withToolbar { chatList - toolbar + .background(theme.colors.background) + .navigationBarTitleDisplayMode(.inline) + .navigationBarHidden(searchMode || oneHandUI) } .scaleEffect(x: 1, y: oneHandUI ? -1 : 1, anchor: .center) .onDisappear() { withAnimation { userPickerVisible = false } } @@ -86,66 +86,110 @@ struct ChatListView: View { secondaryButton: .cancel() )) } - .listStyle(.plain) - .background(theme.colors.background) - .navigationBarTitleDisplayMode(.inline) - .navigationBarHidden(searchMode) - } - - @ViewBuilder private var toolbar: some View { - let t = VStack{}.toolbar { - ToolbarItem(placement: .navigationBarLeading) { - let user = chatModel.currentUser ?? User.sampleData - ZStack(alignment: .topTrailing) { - ProfileImage(imageStr: user.image, size: 32, color: Color(uiColor: .quaternaryLabel)) - .padding(.trailing, 4) - let allRead = chatModel.users - .filter { u in !u.user.activeUser && !u.user.hidden } - .allSatisfy { u in u.unreadCount == 0 } - if !allRead { - unreadBadge(size: 12) - } - } - .onTapGesture { - if chatModel.users.filter({ u in u.user.activeUser || !u.user.hidden }).count > 1 { - withAnimation { - userPickerVisible.toggle() - } - } else { - showSettings = true - } - } - } - ToolbarItem(placement: .principal) { - HStack(spacing: 4) { - Text("Chats") - .font(.headline) - SubsStatusIndicator() - } - .frame(maxWidth: .infinity, alignment: .center) - } - ToolbarItem(placement: .navigationBarTrailing) { - switch chatModel.chatRunning { - case .some(true): NewChatMenuButton() - case .some(false): chatStoppedIcon() - case .none: EmptyView() - } + .safeAreaInset(edge: .top) { + if oneHandUI { Divider().background(Material.ultraThin) } + } + .safeAreaInset(edge: .bottom) { + if oneHandUI { + Divider().padding(.bottom, Self.hasHomeIndicator ? 0 : 8).background(Material.ultraThin) } } - - if #unavailable(iOS 16) { - t - } else if oneHandUI { - t.toolbarBackground(.visible, for: .navigationBar) + } + + static var hasHomeIndicator: Bool = { + if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, + let window = windowScene.windows.first { + window.safeAreaInsets.bottom > 0 + } else { false } + }() + + @ViewBuilder func withToolbar(content: () -> some View) -> some View { + if #available(iOS 16.0, *) { + if oneHandUI { + content() + .toolbarBackground(.hidden, for: .bottomBar) + .toolbar { bottomToolbar } + } else { + content() + .toolbarBackground(.automatic, for: .navigationBar) + .toolbar { topToolbar } + } } else { - t.toolbarBackground(.visible, for: .bottomBar) + if oneHandUI { + content().toolbar { bottomToolbarGroup } + } else { + content().toolbar { topToolbar } + } + } + } + + @ToolbarContentBuilder var topToolbar: some ToolbarContent { + ToolbarItem(placement: .topBarLeading) { leadingToolbarItem } + ToolbarItem(placement: .principal) { SubsStatusIndicator() } + ToolbarItem(placement: .topBarTrailing) { trailingToolbarItem } + } + + @ToolbarContentBuilder var bottomToolbar: some ToolbarContent { + let padding: Double = Self.hasHomeIndicator ? 0 : 14 + ToolbarItem(placement: .bottomBar) { + HStack { + leadingToolbarItem.padding(.bottom, padding) + Spacer() + SubsStatusIndicator().padding(.bottom, padding) + Spacer() + trailingToolbarItem.padding(.bottom, padding) + } + .contentShape(Rectangle()) + .onTapGesture { scrollToSearchBar = true } + } + } + + @ToolbarContentBuilder var bottomToolbarGroup: some ToolbarContent { + let padding: Double = Self.hasHomeIndicator ? 0 : 14 + ToolbarItemGroup(placement: .bottomBar) { + leadingToolbarItem.padding(.bottom, padding) + Spacer() + SubsStatusIndicator().padding(.bottom, padding) + Spacer() + trailingToolbarItem.padding(.bottom, padding) + } + } + + @ViewBuilder var leadingToolbarItem: some View { + let user = chatModel.currentUser ?? User.sampleData + ZStack(alignment: .topTrailing) { + ProfileImage(imageStr: user.image, size: 32, color: Color(uiColor: .quaternaryLabel)) + .padding(.trailing, 4) + let allRead = chatModel.users + .filter { u in !u.user.activeUser && !u.user.hidden } + .allSatisfy { u in u.unreadCount == 0 } + if !allRead { + unreadBadge(size: 12) + } + } + .onTapGesture { + if chatModel.users.filter({ u in u.user.activeUser || !u.user.hidden }).count > 1 { + withAnimation { + userPickerVisible.toggle() + } + } else { + showSettings = true + } + } + } + + @ViewBuilder var trailingToolbarItem: some View { + switch chatModel.chatRunning { + case .some(true): NewChatMenuButton() + case .some(false): chatStoppedIcon() + case .none: EmptyView() } } @ViewBuilder private var chatList: some View { let cs = filteredChats() ZStack { - VStack { + ScrollViewReader { scrollProxy in List { if !chatModel.chats.isEmpty { ChatListSearchBar( @@ -159,6 +203,14 @@ struct ChatListView: View { .listRowSeparator(.hidden) .listRowBackground(Color.clear) .frame(maxWidth: .infinity) + .padding(.top, oneHandUI ? 8 : 0) + .id("searchBar") + } + if !oneHandUICardShown { + OneHandUICard() + .scaleEffect(x: 1, y: oneHandUI ? -1 : 1, anchor: .center) + .listRowSeparator(.hidden) + .listRowBackground(Color.clear) } ForEach(cs, id: \.viewId) { chat in ChatListNavLink(chat: chat) @@ -169,16 +221,23 @@ struct ChatListView: View { } .offset(x: -8) } - } - .onChange(of: chatModel.chatId) { chId in - if chId == nil, let chatId = chatModel.chatToTop { - chatModel.chatToTop = nil - chatModel.popChat(chatId) + .listStyle(.plain) + .onChange(of: chatModel.chatId) { chId in + if chId == nil, let chatId = chatModel.chatToTop { + chatModel.chatToTop = nil + chatModel.popChat(chatId) + } + stopAudioPlayer() + } + .onChange(of: chatModel.currentUser?.userId) { _ in + stopAudioPlayer() + } + .onChange(of: scrollToSearchBar) { scrollToSearchBar in + if scrollToSearchBar { + Task { self.scrollToSearchBar = false } + withAnimation { scrollProxy.scrollTo("searchBar") } + } } - stopAudioPlayer() - } - .onChange(of: chatModel.currentUser?.userId) { _ in - stopAudioPlayer() } if cs.isEmpty && !chatModel.chats.isEmpty { Text("No filtered chats") @@ -270,6 +329,7 @@ struct SubsStatusIndicator: View { showServersSummary = true } label: { HStack(spacing: 4) { + Text("Chats").foregroundStyle(Color.primary).fixedSize().font(.headline) SubscriptionStatusIndicatorView(subs: subs, hasSess: hasSess) if showSubscriptionPercentage { SubscriptionStatusPercentageView(subs: subs, hasSess: hasSess) @@ -356,7 +416,6 @@ struct ChatListSearchBar: View { toggleFilterButton() } } - Divider() } .onChange(of: searchFocussed) { sf in withAnimation { searchMode = sf } diff --git a/apps/ios/Shared/Views/ChatList/OneHandUICard.swift b/apps/ios/Shared/Views/ChatList/OneHandUICard.swift new file mode 100644 index 0000000000..636d165114 --- /dev/null +++ b/apps/ios/Shared/Views/ChatList/OneHandUICard.swift @@ -0,0 +1,52 @@ +// +// OneHandUICard.swift +// SimpleX (iOS) +// +// Created by EP on 06/08/2024. +// Copyright © 2024 SimpleX Chat. All rights reserved. +// + +import SwiftUI +import SimpleXChat + +struct OneHandUICard: View { + @EnvironmentObject var theme: AppTheme + @Environment(\.dynamicTypeSize) private var userFont: DynamicTypeSize + @AppStorage(GROUP_DEFAULT_ONE_HAND_UI, store: groupDefaults) private var oneHandUI = true + @AppStorage(DEFAULT_ONE_HAND_UI_CARD_SHOWN) private var oneHandUICardShown = false + @State private var showOneHandUIAlert = false + + var body: some View { + ZStack(alignment: .topTrailing) { + VStack(alignment: .leading, spacing: 8) { + Text("Toggle chat list:").font(.title3) + Toggle("Reachable chat toolbar", isOn: $oneHandUI) + } + Image(systemName: "multiply") + .foregroundColor(theme.colors.secondary) + .onTapGesture { + showOneHandUIAlert = true + } + } + .padding() + .background(theme.appColors.sentMessage) + .cornerRadius(12) + .frame(height: dynamicSize(userFont).rowHeight) + .padding(.vertical, 12) + .alert(isPresented: $showOneHandUIAlert) { + Alert( + title: Text("Reachable chat toolbar"), + message: Text("You can change it in Appearance settings."), + dismissButton: .default(Text("Ok")) { + withAnimation { + oneHandUICardShown = true + } + } + ) + } + } +} + +#Preview { + OneHandUICard() +} diff --git a/apps/ios/Shared/Views/Helpers/SwipeLabel.swift b/apps/ios/Shared/Views/Helpers/SwipeLabel.swift new file mode 100644 index 0000000000..564589be6f --- /dev/null +++ b/apps/ios/Shared/Views/Helpers/SwipeLabel.swift @@ -0,0 +1,80 @@ +// +// SwipeLabel.swift +// SimpleX (iOS) +// +// Created by Levitating Pineapple on 06/08/2024. +// Copyright © 2024 SimpleX Chat. All rights reserved. +// + +import SwiftUI + +struct SwipeLabel: View { + private let text: String + private let systemImage: String + private let inverted: Bool + + init(_ text: String, systemImage: String, inverted: Bool) { + self.text = text + self.systemImage = systemImage + self.inverted = inverted + } + + var body: some View { + if inverted { + Image( + uiImage: SwipeActionView( + systemName: systemImage, + text: text + ).snapshot(inverted: inverted) + ) + } else { + Label(text, systemImage: systemImage) + } + } + + private class SwipeActionView: UIView { + private let imageView = UIImageView() + private let label = UILabel() + private let fontSize: CGFloat + + init(systemName: String, text: String) { + fontSize = UIFontDescriptor.preferredFontDescriptor(withTextStyle: .subheadline).pointSize + super.init(frame: CGRect(x: 0, y: 0, width: 64, height: 32 + fontSize)) + imageView.image = UIImage(systemName: systemName) + imageView.contentMode = .scaleAspectFit + label.text = text + label.textAlignment = .center + label.font = UIFont.systemFont(ofSize: fontSize, weight: .medium) + addSubview(imageView) + addSubview(label) + } + + override func layoutSubviews() { + imageView.frame = CGRect( + x: 20, + y: 0, + width: 24, + height: 24 + ) + label.frame = CGRect( + x: 0, + y: 32, + width: 64, + height: fontSize + ) + } + + @available(*, unavailable) + required init?(coder: NSCoder) { fatalError("not implemented") } + + func snapshot(inverted: Bool) -> UIImage { + UIGraphicsImageRenderer(bounds: bounds).image { context in + if inverted { + context.cgContext.scaleBy(x: 1, y: -1) + context.cgContext.translateBy(x: 0, y: -bounds.height) + } + layer.render(in: context.cgContext) + }.withRenderingMode(.alwaysTemplate) + } + } +} diff --git a/apps/ios/Shared/Views/NewChat/NewChatMenuButton.swift b/apps/ios/Shared/Views/NewChat/NewChatMenuButton.swift index ee447efdd9..433d2cc102 100644 --- a/apps/ios/Shared/Views/NewChat/NewChatMenuButton.swift +++ b/apps/ios/Shared/Views/NewChat/NewChatMenuButton.swift @@ -112,7 +112,7 @@ struct NewChatSheet: View { .modifier(ThemedBackground(grouped: true)) .navigationBarTitleDisplayMode(.large) } label: { - Label("Create group", systemImage: "person.2") + Label("Create group", systemImage: "person.2.circle.fill") } } @@ -142,7 +142,10 @@ struct NewChatSheet: View { func newChatActionButton(_ icon: String, color: Color/* = .secondary*/, content: @escaping () -> Content) -> some View { ZStack(alignment: .leading) { - Image(systemName: icon).frame(maxWidth: 24, maxHeight: 24, alignment: .center) + Image(systemName: icon) + .resizable() + .scaledToFit() + .frame(maxWidth: 24, maxHeight: 24, alignment: .center) .symbolRenderingMode(.monochrome) .foregroundColor(color) content().foregroundColor(theme.colors.onBackground).padding(.leading, indent) @@ -340,7 +343,7 @@ struct ContactsListSearchBar: View { } .padding(EdgeInsets(top: 7, leading: 7, bottom: 7, trailing: 7)) .foregroundColor(theme.colors.secondary) - .background(theme.colors.isLight ? theme.colors.background : theme.colors.secondaryVariant) + .background(Color(uiColor: .secondarySystemGroupedBackground)) .cornerRadius(10.0) if searchFocussed { @@ -354,6 +357,7 @@ struct ContactsListSearchBar: View { toggleFilterButton() } } + .padding(.top, 24) .onChange(of: searchFocussed) { sf in withAnimation { searchMode = sf } } @@ -447,8 +451,8 @@ struct DeletedChats: View { showDeletedChatIcon: false ) } - .navigationTitle("Deleted chats") - .navigationBarTitleDisplayMode(.inline) + .navigationTitle("Archived contacts") + .navigationBarTitleDisplayMode(.large) .navigationBarHidden(searchMode) .modifier(ThemedBackground(grouped: true)) diff --git a/apps/ios/Shared/Views/Onboarding/WhatsNewView.swift b/apps/ios/Shared/Views/Onboarding/WhatsNewView.swift index 47ac706e15..ed3adcfe7d 100644 --- a/apps/ios/Shared/Views/Onboarding/WhatsNewView.swift +++ b/apps/ios/Shared/Views/Onboarding/WhatsNewView.swift @@ -15,9 +15,10 @@ private struct VersionDescription { } private struct FeatureDescription { - var icon: String + var icon: String? var title: LocalizedStringKey - var description: LocalizedStringKey + var description: LocalizedStringKey? + var subfeatures: [(icon: String, description: LocalizedStringKey)] = [] } private let versionDescriptions: [VersionDescription] = [ @@ -432,34 +433,36 @@ private let versionDescriptions: [VersionDescription] = [ version: "v6.0", post: URL(string: "https://simplex.chat/blog/20240814-simplex-chat-vision-funding-v6-private-routing-new-user-experience.html"), features: [ + FeatureDescription( + icon: nil, + title: "New chat experience 🎉", + description: nil, + subfeatures: [ + ("link.badge.plus", "Connect to your friends faster."), + ("archivebox", "Archive contacts to chat later."), + ("trash", "Delete up to 20 messages at once."), + ("platter.filled.bottom.and.arrow.down.iphone", "Use the app with one hand."), + ("paintpalette", "Color chats with the new themes."), + ] + ), + FeatureDescription( + icon: nil, + title: "New media options", + description: nil, + subfeatures: [ + ("square.and.arrow.up", "Share from other apps."), + ("play.circle", "Play from the chat list."), + ("circle.filled.pattern.diagonalline.rectangle", "Blur for better privacy.") + ] + ), FeatureDescription( icon: "arrow.forward", title: "Private message routing 🚀", description: "It protects your IP address and connections." ), - FeatureDescription( - icon: "person.text.rectangle", - title: "Your contacts your way", - description: "- Search contacts when starting chat.\n- Archive contacts to chat later." - ), - FeatureDescription( - icon: "platter.filled.bottom.iphone", - title: "Reachable chat toolbar 👋", - description: "Use the app with one hand." - ), - FeatureDescription( - icon: "link", - title: "Connect to your friends faster", - description: "Even when they are offline." - ), - FeatureDescription( - icon: "trash", - title: "Moderate like a pro ✋", - description: "Delete up to 20 messages at once." - ), FeatureDescription( icon: "network", - title: "Control your network", + title: "Better networking", description: "Connection and servers status." ) ] @@ -489,35 +492,37 @@ struct WhatsNewView: View { VStack { TabView(selection: $currentVersion) { ForEach(Array(versionDescriptions.enumerated()), id: \.0) { (i, v) in - VStack(alignment: .leading, spacing: 16) { - Text("New in \(v.version)") - .font(.title) - .foregroundColor(theme.colors.secondary) - .frame(maxWidth: .infinity) - .padding(.vertical) - ForEach(v.features, id: \.icon) { f in - featureDescription(f.icon, f.title, f.description) - .padding(.bottom, 8) - } - if let post = v.post { - Link(destination: post) { - HStack { - Text("Read more") - Image(systemName: "arrow.up.right.circle") + ScrollView { + VStack(alignment: .leading, spacing: 16) { + Text("New in \(v.version)") + .font(.title) + .foregroundColor(theme.colors.secondary) + .frame(maxWidth: .infinity) + .padding(.vertical) + ForEach(v.features, id: \.title) { f in + featureDescription(f) + .padding(.bottom, 8) + } + if let post = v.post { + Link(destination: post) { + HStack { + Text("Read more") + Image(systemName: "arrow.up.right.circle") + } } } - } - if !viaSettings { - Spacer() - Button("Ok") { - dismiss() + if !viaSettings { + Spacer() + Button("Ok") { + dismiss() + } + .font(.title3) + .frame(maxWidth: .infinity, alignment: .center) + Spacer() } - .font(.title3) - .frame(maxWidth: .infinity, alignment: .center) - Spacer() } + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading) } - .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading) .tag(i) } } @@ -531,18 +536,37 @@ struct WhatsNewView: View { } } - private func featureDescription(_ icon: String, _ title: LocalizedStringKey, _ description: LocalizedStringKey) -> some View { + private func featureDescription(_ f: FeatureDescription) -> some View { VStack(alignment: .leading, spacing: 4) { - HStack(alignment: .center, spacing: 4) { - Image(systemName: icon) - .symbolRenderingMode(.monochrome) - .foregroundColor(theme.colors.secondary) - .frame(minWidth: 30, alignment: .center) - Text(title).font(.title3).bold() + if let icon = f.icon { + HStack(alignment: .center, spacing: 4) { + Image(systemName: icon) + .symbolRenderingMode(.monochrome) + .foregroundColor(theme.colors.secondary) + .frame(minWidth: 30, alignment: .center) + Text(f.title).font(.title3).bold() + } + } else { + Text(f.title).font(.title3).bold() + } + if let d = f.description { + Text(d) + .multilineTextAlignment(.leading) + .lineLimit(10) + } + if f.subfeatures.count > 0 { + ForEach(f.subfeatures, id: \.icon) { s in + HStack(alignment: .center, spacing: 4) { + Image(systemName: s.icon) + .symbolRenderingMode(.monochrome) + .foregroundColor(theme.colors.secondary) + .frame(minWidth: 30, alignment: .center) + Text(s.description) + .multilineTextAlignment(.leading) + .lineLimit(3) + } + } } - Text(description) - .multilineTextAlignment(.leading) - .lineLimit(10) } } diff --git a/apps/ios/Shared/Views/UserSettings/AppSettings.swift b/apps/ios/Shared/Views/UserSettings/AppSettings.swift index 66cb41a57d..6247777bf2 100644 --- a/apps/ios/Shared/Views/UserSettings/AppSettings.swift +++ b/apps/ios/Shared/Views/UserSettings/AppSettings.swift @@ -28,7 +28,10 @@ extension AppSettings { privacyAcceptImagesGroupDefault.set(val) def.setValue(val, forKey: DEFAULT_PRIVACY_ACCEPT_IMAGES) } - if let val = privacyLinkPreviews { def.setValue(val, forKey: DEFAULT_PRIVACY_LINK_PREVIEWS) } + if let val = privacyLinkPreviews { + privacyLinkPreviewsGroupDefault.set(val) + def.setValue(val, forKey: DEFAULT_PRIVACY_LINK_PREVIEWS) + } if let val = privacyShowChatPreviews { def.setValue(val, forKey: DEFAULT_PRIVACY_SHOW_CHAT_PREVIEWS) } if let val = privacySaveLastDraft { def.setValue(val, forKey: DEFAULT_PRIVACY_SAVE_LAST_DRAFT) } if let val = privacyProtectScreen { def.setValue(val, forKey: DEFAULT_PRIVACY_PROTECT_SCREEN) } @@ -45,12 +48,15 @@ extension AppSettings { if let val = androidCallOnLockScreen { def.setValue(val.rawValue, forKey: ANDROID_DEFAULT_CALL_ON_LOCK_SCREEN) } if let val = iosCallKitEnabled { callKitEnabledGroupDefault.set(val) } if let val = iosCallKitCallsInRecents { def.setValue(val, forKey: DEFAULT_CALL_KIT_CALLS_IN_RECENTS) } - if let val = uiProfileImageCornerRadius { def.setValue(val, forKey: DEFAULT_PROFILE_IMAGE_CORNER_RADIUS) } + if let val = uiProfileImageCornerRadius { + profileImageCornerRadiusGroupDefault.set(val) + def.setValue(val, forKey: DEFAULT_PROFILE_IMAGE_CORNER_RADIUS) + } if let val = uiColorScheme { def.setValue(val, forKey: DEFAULT_CURRENT_THEME) } if let val = uiDarkColorScheme { def.setValue(val, forKey: DEFAULT_SYSTEM_DARK_THEME) } if let val = uiCurrentThemeIds { def.setValue(val, forKey: DEFAULT_CURRENT_THEME_IDS) } if let val = uiThemes { def.setValue(val.skipDuplicates(), forKey: DEFAULT_THEME_OVERRIDES) } - if let val = oneHandUI { def.setValue(val, forKey: DEFAULT_ONE_HAND_UI) } + if let val = oneHandUI { groupDefaults.setValue(val, forKey: GROUP_DEFAULT_ONE_HAND_UI) } } public static var current: AppSettings { @@ -82,7 +88,7 @@ extension AppSettings { c.uiDarkColorScheme = systemDarkThemeDefault.get() c.uiCurrentThemeIds = currentThemeIdsDefault.get() c.uiThemes = themeOverridesDefault.get() - c.oneHandUI = def.bool(forKey: DEFAULT_ONE_HAND_UI) + c.oneHandUI = groupDefaults.bool(forKey: GROUP_DEFAULT_ONE_HAND_UI) return c } } diff --git a/apps/ios/Shared/Views/UserSettings/AppearanceSettings.swift b/apps/ios/Shared/Views/UserSettings/AppearanceSettings.swift index 7f18d43a5e..0087aaea1b 100644 --- a/apps/ios/Shared/Views/UserSettings/AppearanceSettings.swift +++ b/apps/ios/Shared/Views/UserSettings/AppearanceSettings.swift @@ -33,7 +33,7 @@ struct AppearanceSettings: View { }() @State private var darkModeTheme: String = UserDefaults.standard.string(forKey: DEFAULT_SYSTEM_DARK_THEME) ?? DefaultTheme.DARK.themeName @AppStorage(DEFAULT_PROFILE_IMAGE_CORNER_RADIUS) private var profileImageCornerRadius = defaultProfileImageCorner - @AppStorage(DEFAULT_ONE_HAND_UI) private var oneHandUI = false + @AppStorage(GROUP_DEFAULT_ONE_HAND_UI, store: groupDefaults) private var oneHandUI = true @State var themeUserDestination: (Int64, ThemeModeOverrides?)? = { if let currentUser = ChatModel.shared.currentUser, let uiThemes = currentUser.uiThemes, uiThemes.preferredMode(!CurrentColors.colors.isLight) != nil { @@ -63,6 +63,10 @@ struct AppearanceSettings: View { } } + Section("Chat list") { + Toggle("Reachable chat toolbar", isOn: $oneHandUI) + } + Section { ThemeDestinationPicker(themeUserDestination: $themeUserDestination, themeUserDest: themeUserDestination?.0, customizeThemeIsOpen: $customizeThemeIsOpen) diff --git a/apps/ios/Shared/Views/UserSettings/DeveloperView.swift b/apps/ios/Shared/Views/UserSettings/DeveloperView.swift index 41a580496f..4ef05bd998 100644 --- a/apps/ios/Shared/Views/UserSettings/DeveloperView.swift +++ b/apps/ios/Shared/Views/UserSettings/DeveloperView.swift @@ -13,7 +13,8 @@ struct DeveloperView: View { @EnvironmentObject var theme: AppTheme @AppStorage(DEFAULT_DEVELOPER_TOOLS) private var developerTools = false @AppStorage(GROUP_DEFAULT_CONFIRM_DB_UPGRADES, store: groupDefaults) private var confirmDatabaseUpgrades = false - @AppStorage(DEFAULT_ONE_HAND_UI) private var oneHandUI = false + @State private var hintsUnchanged = hintDefaultsUnchanged() + @Environment(\.colorScheme) var colorScheme var body: some View { @@ -34,6 +35,10 @@ struct DeveloperView: View { } label: { settingsRow("terminal", color: theme.colors.secondary) { Text("Chat console") } } + settingsRow("lightbulb.max", color: theme.colors.secondary) { + Button("Reset all hints", action: resetHintDefaults) + .disabled(hintsUnchanged) + } settingsRow("chevron.left.forwardslash.chevron.right", color: theme.colors.secondary) { Toggle("Show developer options", isOn: $developerTools) } @@ -49,9 +54,6 @@ struct DeveloperView: View { settingsRow("internaldrive", color: theme.colors.secondary) { Toggle("Confirm database upgrades", isOn: $confirmDatabaseUpgrades) } - settingsRow("hand.wave", color: theme.colors.secondary) { - Toggle("One-hand UI", isOn: $oneHandUI) - } } header: { Text("Developer options") } @@ -59,6 +61,21 @@ struct DeveloperView: View { } } } + + private func resetHintDefaults() { + for def in hintDefaults { + if let val = appDefaults[def] as? Bool { + UserDefaults.standard.set(val, forKey: def) + } + } + hintsUnchanged = true + } +} + +private func hintDefaultsUnchanged() -> Bool { + hintDefaults.allSatisfy { def in + appDefaults[def] as? Bool == UserDefaults.standard.bool(forKey: def) + } } struct DeveloperView_Previews: PreviewProvider { diff --git a/apps/ios/Shared/Views/UserSettings/PrivacySettings.swift b/apps/ios/Shared/Views/UserSettings/PrivacySettings.swift index 8bd9072f7f..338943f13a 100644 --- a/apps/ios/Shared/Views/UserSettings/PrivacySettings.swift +++ b/apps/ios/Shared/Views/UserSettings/PrivacySettings.swift @@ -117,7 +117,7 @@ struct PrivacySettings: View { privacyAcceptImagesGroupDefault.set($0) } } - settingsRow("circle.rectangle.filled.pattern.diagonalline", color: theme.colors.secondary) { + settingsRow("circle.filled.pattern.diagonalline.rectangle", color: theme.colors.secondary) { Picker("Blur media", selection: $privacyMediaBlurRadius) { let values = [0, 12, 24, 48] + ([0, 12, 24, 48].contains(privacyMediaBlurRadius) ? [] : [privacyMediaBlurRadius]) ForEach(values, id: \.self) { radius in diff --git a/apps/ios/Shared/Views/UserSettings/SettingsView.swift b/apps/ios/Shared/Views/UserSettings/SettingsView.swift index 59e4f8af35..51ce56939e 100644 --- a/apps/ios/Shared/Views/UserSettings/SettingsView.swift +++ b/apps/ios/Shared/Views/UserSettings/SettingsView.swift @@ -47,7 +47,7 @@ let DEFAULT_ACCENT_COLOR_GREEN = "accentColorGreen" // deprecated, only used for let DEFAULT_ACCENT_COLOR_BLUE = "accentColorBlue" // deprecated, only used for migration let DEFAULT_USER_INTERFACE_STYLE = "userInterfaceStyle" // deprecated, only used for migration let DEFAULT_PROFILE_IMAGE_CORNER_RADIUS = "profileImageCornerRadius" -let DEFAULT_ONE_HAND_UI = "oneHandUI" +let DEFAULT_ONE_HAND_UI_CARD_SHOWN = "oneHandUICardShown" let DEFAULT_CONNECT_VIA_LINK_TAB = "connectViaLinkTab" let DEFAULT_LIVE_MESSAGE_ALERT_SHOWN = "liveMessageAlertShown" let DEFAULT_SHOW_HIDDEN_PROFILES_NOTICE = "showHiddenProfilesNotice" @@ -97,7 +97,7 @@ let appDefaults: [String: Any] = [ DEFAULT_DEVELOPER_TOOLS: false, DEFAULT_ENCRYPTION_STARTED: false, DEFAULT_PROFILE_IMAGE_CORNER_RADIUS: defaultProfileImageCorner, - DEFAULT_ONE_HAND_UI: false, + DEFAULT_ONE_HAND_UI_CARD_SHOWN: false, DEFAULT_CONNECT_VIA_LINK_TAB: ConnectViaLinkTab.scan.rawValue, DEFAULT_LIVE_MESSAGE_ALERT_SHOWN: false, DEFAULT_SHOW_HIDDEN_PROFILES_NOTICE: true, @@ -120,6 +120,18 @@ let appDefaults: [String: Any] = [ DEFAULT_CURRENT_THEME_IDS: "{}" ] +// only Bool defaults can be used here, +// or hintDefaultsUnchanged and resetHintDefaults need to be changed +let hintDefaults = [ + DEFAULT_LA_NOTICE_SHOWN, + DEFAULT_ONE_HAND_UI_CARD_SHOWN, + DEFAULT_LIVE_MESSAGE_ALERT_SHOWN, + DEFAULT_SHOW_HIDDEN_PROFILES_NOTICE, + DEFAULT_SHOW_MUTE_PROFILE_ALERT, + DEFAULT_SHOW_DELETE_CONVERSATION_NOTICE, + DEFAULT_SHOW_DELETE_CONTACT_NOTICE +] + // not used anymore enum ConnectViaLinkTab: String { case scan diff --git a/apps/ios/SimpleX Localizations/bg.xcloc/Localized Contents/bg.xliff b/apps/ios/SimpleX Localizations/bg.xcloc/Localized Contents/bg.xliff index 51f6c9c975..aa077ed370 100644 --- a/apps/ios/SimpleX Localizations/bg.xcloc/Localized Contents/bg.xliff +++ b/apps/ios/SimpleX Localizations/bg.xcloc/Localized Contents/bg.xliff @@ -565,7 +565,8 @@ Accept Приеми accept contact request via notification - accept incoming call via notification + accept incoming call via notification + swipe action Accept connection request? @@ -580,7 +581,8 @@ Accept incognito Приеми инкогнито - accept contact request via notification + accept contact request via notification + swipe action Acknowledged @@ -1287,6 +1289,10 @@ Чатът е спрян. Ако вече сте използвали тази база данни на друго устройство, трябва да я прехвърлите обратно, преди да стартирате чата отново. No comment provided by engineer. + + Chat list + No comment provided by engineer. + Chat migrated! Чатът е мигриран! @@ -1346,7 +1352,7 @@ Clear Изчисти - No comment provided by engineer. + swipe action Clear conversation @@ -1923,7 +1929,8 @@ This is your own one-time link! Delete Изтрий - chat item action + chat item action + swipe action Delete %lld messages of members? @@ -2125,10 +2132,6 @@ This is your own one-time link! Изтрито на: %@ copied message info - - Deleted chats - No comment provided by engineer. - Deletion errors No comment provided by engineer. @@ -2991,7 +2994,7 @@ This is your own one-time link! Favorite Любим - No comment provided by engineer. + swipe action File error @@ -3750,7 +3753,7 @@ Error: %2$@ Join Присъединяване - No comment provided by engineer. + swipe action Join group @@ -3841,7 +3844,7 @@ This is your link for group %@! Leave Напусни - No comment provided by engineer. + swipe action Leave group @@ -4221,7 +4224,7 @@ This is your link for group %@! Mute Без звук - No comment provided by engineer. + swipe action Muted when inactive! @@ -4231,7 +4234,7 @@ This is your link for group %@! Name Име - No comment provided by engineer. + swipe action Network & servers @@ -4442,10 +4445,6 @@ This is your link for group %@! Стар архив на база данни No comment provided by engineer. - - One-hand UI - No comment provided by engineer. - One-time invitation link Линк за еднократна покана @@ -5003,6 +5002,10 @@ Enable in *Network & servers* settings. Оценете приложението No comment provided by engineer. + + Reachable chat toolbar + No comment provided by engineer. + Reachable chat toolbar 👋 No comment provided by engineer. @@ -5015,7 +5018,7 @@ Enable in *Network & servers* settings. Read Прочетено - No comment provided by engineer. + swipe action Read more @@ -5166,7 +5169,8 @@ Enable in *Network & servers* settings. Reject Отхвърляне - reject incoming call via notification + reject incoming call via notification + swipe action Reject (sender NOT notified) @@ -5267,6 +5271,10 @@ Enable in *Network & servers* settings. Нулиране No comment provided by engineer. + + Reset all hints + No comment provided by engineer. + Reset all statistics No comment provided by engineer. @@ -6551,6 +6559,10 @@ You will be prompted to complete authentication before this feature is enabled.< За да проверите криптирането от край до край с вашия контакт, сравнете (или сканирайте) кода на вашите устройства. No comment provided by engineer. + + Toggle chat list: + No comment provided by engineer. + Toggle incognito when connecting. Избор на инкогнито при свързване. @@ -6632,7 +6644,7 @@ You will be prompted to complete authentication before this feature is enabled.< Unfav. Премахни от любимите - No comment provided by engineer. + swipe action Unhide @@ -6708,12 +6720,12 @@ To connect, please ask your contact to create another connection link and check Unmute Уведомявай - No comment provided by engineer. + swipe action Unread Непрочетено - No comment provided by engineer. + swipe action Up to 100 last messages are sent to new members. @@ -7191,6 +7203,10 @@ Repeat join request? Можете да приемате обаждания от заключен екран, без идентификация на устройство и приложението. No comment provided by engineer. + + You can change it in Appearance settings. + No comment provided by engineer. + You can create it later Можете да го създадете по-късно diff --git a/apps/ios/SimpleX Localizations/cs.xcloc/Localized Contents/cs.xliff b/apps/ios/SimpleX Localizations/cs.xcloc/Localized Contents/cs.xliff index ef54e8786e..045c4897f6 100644 --- a/apps/ios/SimpleX Localizations/cs.xcloc/Localized Contents/cs.xliff +++ b/apps/ios/SimpleX Localizations/cs.xcloc/Localized Contents/cs.xliff @@ -547,7 +547,8 @@ Accept Přijmout accept contact request via notification - accept incoming call via notification + accept incoming call via notification + swipe action Accept connection request? @@ -562,7 +563,8 @@ Accept incognito Přijmout inkognito - accept contact request via notification + accept contact request via notification + swipe action Acknowledged @@ -1244,6 +1246,10 @@ Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat. No comment provided by engineer. + + Chat list + No comment provided by engineer. + Chat migrated! No comment provided by engineer. @@ -1301,7 +1307,7 @@ Clear Vyčistit - No comment provided by engineer. + swipe action Clear conversation @@ -1853,7 +1859,8 @@ This is your own one-time link! Delete Smazat - chat item action + chat item action + swipe action Delete %lld messages of members? @@ -2052,10 +2059,6 @@ This is your own one-time link! Smazáno v: %@ copied message info - - Deleted chats - No comment provided by engineer. - Deletion errors No comment provided by engineer. @@ -2888,7 +2891,7 @@ This is your own one-time link! Favorite Oblíbené - No comment provided by engineer. + swipe action File error @@ -3620,7 +3623,7 @@ Error: %2$@ Join Připojte se na - No comment provided by engineer. + swipe action Join group @@ -3703,7 +3706,7 @@ This is your link for group %@! Leave Opustit - No comment provided by engineer. + swipe action Leave group @@ -4067,7 +4070,7 @@ This is your link for group %@! Mute Ztlumit - No comment provided by engineer. + swipe action Muted when inactive! @@ -4077,7 +4080,7 @@ This is your link for group %@! Name Jméno - No comment provided by engineer. + swipe action Network & servers @@ -4282,10 +4285,6 @@ This is your link for group %@! Archiv staré databáze No comment provided by engineer. - - One-hand UI - No comment provided by engineer. - One-time invitation link Jednorázový zvací odkaz @@ -4820,6 +4819,10 @@ Enable in *Network & servers* settings. Ohodnoťte aplikaci No comment provided by engineer. + + Reachable chat toolbar + No comment provided by engineer. + Reachable chat toolbar 👋 No comment provided by engineer. @@ -4832,7 +4835,7 @@ Enable in *Network & servers* settings. Read Číst - No comment provided by engineer. + swipe action Read more @@ -4980,7 +4983,8 @@ Enable in *Network & servers* settings. Reject Odmítnout - reject incoming call via notification + reject incoming call via notification + swipe action Reject (sender NOT notified) @@ -5076,6 +5080,10 @@ Enable in *Network & servers* settings. Obnovit No comment provided by engineer. + + Reset all hints + No comment provided by engineer. + Reset all statistics No comment provided by engineer. @@ -6328,6 +6336,10 @@ Před zapnutím této funkce budete vyzváni k dokončení ověření. Chcete-li ověřit koncové šifrování u svého kontaktu, porovnejte (nebo naskenujte) kód na svých zařízeních. No comment provided by engineer. + + Toggle chat list: + No comment provided by engineer. + Toggle incognito when connecting. Změnit inkognito režim při připojení. @@ -6403,7 +6415,7 @@ Před zapnutím této funkce budete vyzváni k dokončení ověření. Unfav. Odobl. - No comment provided by engineer. + swipe action Unhide @@ -6477,12 +6489,12 @@ Chcete-li se připojit, požádejte svůj kontakt o vytvoření dalšího odkazu Unmute Zrušit ztlumení - No comment provided by engineer. + swipe action Unread Nepřečtený - No comment provided by engineer. + swipe action Up to 100 last messages are sent to new members. @@ -6928,6 +6940,10 @@ Repeat join request? Můžete přijímat hovory z obrazovky zámku, bez ověření zařízení a aplikace. No comment provided by engineer. + + You can change it in Appearance settings. + No comment provided by engineer. + You can create it later Můžete vytvořit později diff --git a/apps/ios/SimpleX Localizations/de.xcloc/Localized Contents/de.xliff b/apps/ios/SimpleX Localizations/de.xcloc/Localized Contents/de.xliff index 394d3b23a7..dd53c6d9ff 100644 --- a/apps/ios/SimpleX Localizations/de.xcloc/Localized Contents/de.xliff +++ b/apps/ios/SimpleX Localizations/de.xcloc/Localized Contents/de.xliff @@ -566,7 +566,8 @@ Accept Annehmen accept contact request via notification - accept incoming call via notification + accept incoming call via notification + swipe action Accept connection request? @@ -581,7 +582,8 @@ Accept incognito Inkognito akzeptieren - accept contact request via notification + accept contact request via notification + swipe action Acknowledged @@ -1308,6 +1310,10 @@ Der Chat ist angehalten. Wenn Sie diese Datenbank bereits auf einem anderen Gerät genutzt haben, sollten Sie diese vor dem Starten des Chats wieder zurückspielen. No comment provided by engineer. + + Chat list + No comment provided by engineer. + Chat migrated! Chat wurde migriert! @@ -1371,7 +1377,7 @@ Clear Löschen - No comment provided by engineer. + swipe action Clear conversation @@ -1964,7 +1970,8 @@ Das ist Ihr eigener Einmal-Link! Delete Löschen - chat item action + chat item action + swipe action Delete %lld messages of members? @@ -2168,10 +2175,6 @@ Das ist Ihr eigener Einmal-Link! Gelöscht um: %@ copied message info - - Deleted chats - No comment provided by engineer. - Deletion errors Fehler beim Löschen @@ -3054,7 +3057,7 @@ Das ist Ihr eigener Einmal-Link! Favorite Favorit - No comment provided by engineer. + swipe action File error @@ -3830,7 +3833,7 @@ Fehler: %2$@ Join Beitreten - No comment provided by engineer. + swipe action Join group @@ -3921,7 +3924,7 @@ Das ist Ihr Link für die Gruppe %@! Leave Verlassen - No comment provided by engineer. + swipe action Leave group @@ -4315,7 +4318,7 @@ Das ist Ihr Link für die Gruppe %@! Mute Stummschalten - No comment provided by engineer. + swipe action Muted when inactive! @@ -4325,7 +4328,7 @@ Das ist Ihr Link für die Gruppe %@! Name Name - No comment provided by engineer. + swipe action Network & servers @@ -4540,10 +4543,6 @@ Das ist Ihr Link für die Gruppe %@! Altes Datenbankarchiv No comment provided by engineer. - - One-hand UI - No comment provided by engineer. - One-time invitation link Einmal-Einladungslink @@ -5117,6 +5116,10 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen. Bewerten Sie die App No comment provided by engineer. + + Reachable chat toolbar + No comment provided by engineer. + Reachable chat toolbar 👋 No comment provided by engineer. @@ -5129,7 +5132,7 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen. Read Gelesen - No comment provided by engineer. + swipe action Read more @@ -5289,7 +5292,8 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen. Reject Ablehnen - reject incoming call via notification + reject incoming call via notification + swipe action Reject (sender NOT notified) @@ -5391,6 +5395,10 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen. Zurücksetzen No comment provided by engineer. + + Reset all hints + No comment provided by engineer. + Reset all statistics Alle Statistiken zurücksetzen @@ -6729,6 +6737,10 @@ Sie werden aufgefordert, die Authentifizierung abzuschließen, bevor diese Funkt Um die Ende-zu-Ende-Verschlüsselung mit Ihrem Kontakt zu überprüfen, müssen Sie den Sicherheitscode in Ihren Apps vergleichen oder scannen. No comment provided by engineer. + + Toggle chat list: + No comment provided by engineer. + Toggle incognito when connecting. Inkognito beim Verbinden einschalten. @@ -6812,7 +6824,7 @@ Sie werden aufgefordert, die Authentifizierung abzuschließen, bevor diese Funkt Unfav. Fav. entf. - No comment provided by engineer. + swipe action Unhide @@ -6889,12 +6901,12 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s Unmute Stummschaltung aufheben - No comment provided by engineer. + swipe action Unread Ungelesen - No comment provided by engineer. + swipe action Up to 100 last messages are sent to new members. @@ -7387,6 +7399,10 @@ Verbindungsanfrage wiederholen? Sie können Anrufe ohne Geräte- und App-Authentifizierung vom Sperrbildschirm aus annehmen. No comment provided by engineer. + + You can change it in Appearance settings. + No comment provided by engineer. + You can create it later Sie können dies später erstellen diff --git a/apps/ios/SimpleX Localizations/en.xcloc/Localized Contents/en.xliff b/apps/ios/SimpleX Localizations/en.xcloc/Localized Contents/en.xliff index 66f17165b5..3e684f143b 100644 --- a/apps/ios/SimpleX Localizations/en.xcloc/Localized Contents/en.xliff +++ b/apps/ios/SimpleX Localizations/en.xcloc/Localized Contents/en.xliff @@ -568,7 +568,8 @@ Accept Accept accept contact request via notification - accept incoming call via notification + accept incoming call via notification + swipe action Accept connection request? @@ -583,7 +584,8 @@ Accept incognito Accept incognito - accept contact request via notification + accept contact request via notification + swipe action Acknowledged @@ -1316,6 +1318,11 @@ Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat. No comment provided by engineer. + + Chat list + Chat list + No comment provided by engineer. + Chat migrated! Chat migrated! @@ -1379,7 +1386,7 @@ Clear Clear - No comment provided by engineer. + swipe action Clear conversation @@ -1981,7 +1988,8 @@ This is your own one-time link! Delete Delete - chat item action + chat item action + swipe action Delete %lld messages of members? @@ -2188,11 +2196,6 @@ This is your own one-time link! Deleted at: %@ copied message info - - Deleted chats - Deleted chats - No comment provided by engineer. - Deletion errors Deletion errors @@ -3077,7 +3080,7 @@ This is your own one-time link! Favorite Favorite - No comment provided by engineer. + swipe action File error @@ -3854,7 +3857,7 @@ Error: %2$@ Join Join - No comment provided by engineer. + swipe action Join group @@ -3946,7 +3949,7 @@ This is your link for group %@! Leave Leave - No comment provided by engineer. + swipe action Leave group @@ -4341,7 +4344,7 @@ This is your link for group %@! Mute Mute - No comment provided by engineer. + swipe action Muted when inactive! @@ -4351,7 +4354,7 @@ This is your link for group %@! Name Name - No comment provided by engineer. + swipe action Network & servers @@ -4567,11 +4570,6 @@ This is your link for group %@! Old database archive No comment provided by engineer. - - One-hand UI - One-hand UI - No comment provided by engineer. - One-time invitation link One-time invitation link @@ -5147,6 +5145,11 @@ Enable in *Network & servers* settings. Rate the app No comment provided by engineer. + + Reachable chat toolbar + Reachable chat toolbar + No comment provided by engineer. + Reachable chat toolbar 👋 Reachable chat toolbar 👋 @@ -5160,7 +5163,7 @@ Enable in *Network & servers* settings. Read Read - No comment provided by engineer. + swipe action Read more @@ -5320,7 +5323,8 @@ Enable in *Network & servers* settings. Reject Reject - reject incoming call via notification + reject incoming call via notification + swipe action Reject (sender NOT notified) @@ -5422,6 +5426,11 @@ Enable in *Network & servers* settings. Reset No comment provided by engineer. + + Reset all hints + Reset all hints + No comment provided by engineer. + Reset all statistics Reset all statistics @@ -6761,6 +6770,11 @@ You will be prompted to complete authentication before this feature is enabled.< To verify end-to-end encryption with your contact compare (or scan) the code on your devices. No comment provided by engineer. + + Toggle chat list: + Toggle chat list: + No comment provided by engineer. + Toggle incognito when connecting. Toggle incognito when connecting. @@ -6844,7 +6858,7 @@ You will be prompted to complete authentication before this feature is enabled.< Unfav. Unfav. - No comment provided by engineer. + swipe action Unhide @@ -6921,12 +6935,12 @@ To connect, please ask your contact to create another connection link and check Unmute Unmute - No comment provided by engineer. + swipe action Unread Unread - No comment provided by engineer. + swipe action Up to 100 last messages are sent to new members. @@ -7420,6 +7434,11 @@ Repeat join request? You can accept calls from lock screen, without device and app authentication. No comment provided by engineer. + + You can change it in Appearance settings. + You can change it in Appearance settings. + No comment provided by engineer. + You can create it later You can create it later diff --git a/apps/ios/SimpleX Localizations/es.xcloc/Localized Contents/es.xliff b/apps/ios/SimpleX Localizations/es.xcloc/Localized Contents/es.xliff index 0636082aa1..786984f3ab 100644 --- a/apps/ios/SimpleX Localizations/es.xcloc/Localized Contents/es.xliff +++ b/apps/ios/SimpleX Localizations/es.xcloc/Localized Contents/es.xliff @@ -566,7 +566,8 @@ Accept Aceptar accept contact request via notification - accept incoming call via notification + accept incoming call via notification + swipe action Accept connection request? @@ -581,7 +582,8 @@ Accept incognito Aceptar incógnito - accept contact request via notification + accept contact request via notification + swipe action Acknowledged @@ -1305,6 +1307,10 @@ Chat parado. Si has usado esta base de datos en otro dispositivo, debes transferirla de vuelta antes de iniciar Chat. No comment provided by engineer. + + Chat list + No comment provided by engineer. + Chat migrated! ¡Chat migrado! @@ -1368,7 +1374,7 @@ Clear Vaciar - No comment provided by engineer. + swipe action Clear conversation @@ -1960,7 +1966,8 @@ This is your own one-time link! Delete Eliminar - chat item action + chat item action + swipe action Delete %lld messages of members? @@ -2163,10 +2170,6 @@ This is your own one-time link! Eliminado: %@ copied message info - - Deleted chats - No comment provided by engineer. - Deletion errors Errores de borrado @@ -3044,7 +3047,7 @@ This is your own one-time link! Favorite Favoritos - No comment provided by engineer. + swipe action File error @@ -3817,7 +3820,7 @@ Error: %2$@ Join Unirte - No comment provided by engineer. + swipe action Join group @@ -3908,7 +3911,7 @@ This is your link for group %@! Leave Salir - No comment provided by engineer. + swipe action Leave group @@ -4299,7 +4302,7 @@ This is your link for group %@! Mute Silenciar - No comment provided by engineer. + swipe action Muted when inactive! @@ -4309,7 +4312,7 @@ This is your link for group %@! Name Nombre - No comment provided by engineer. + swipe action Network & servers @@ -4523,10 +4526,6 @@ This is your link for group %@! Archivo de bases de datos antiguas No comment provided by engineer. - - One-hand UI - No comment provided by engineer. - One-time invitation link Enlace de invitación de un solo uso @@ -5100,6 +5099,10 @@ Actívalo en ajustes de *Servidores y Redes*. Valora la aplicación No comment provided by engineer. + + Reachable chat toolbar + No comment provided by engineer. + Reachable chat toolbar 👋 No comment provided by engineer. @@ -5112,7 +5115,7 @@ Actívalo en ajustes de *Servidores y Redes*. Read Leer - No comment provided by engineer. + swipe action Read more @@ -5272,7 +5275,8 @@ Actívalo en ajustes de *Servidores y Redes*. Reject Rechazar - reject incoming call via notification + reject incoming call via notification + swipe action Reject (sender NOT notified) @@ -5374,6 +5378,10 @@ Actívalo en ajustes de *Servidores y Redes*. Restablecer No comment provided by engineer. + + Reset all hints + No comment provided by engineer. + Reset all statistics Restablecer estadísticas @@ -6702,6 +6710,10 @@ Se te pedirá que completes la autenticación antes de activar esta función.Para verificar el cifrado de extremo a extremo con tu contacto, compara (o escanea) el código en ambos dispositivos. No comment provided by engineer. + + Toggle chat list: + No comment provided by engineer. + Toggle incognito when connecting. Activa incógnito al conectar. @@ -6785,7 +6797,7 @@ Se te pedirá que completes la autenticación antes de activar esta función. Unfav. No fav. - No comment provided by engineer. + swipe action Unhide @@ -6862,12 +6874,12 @@ Para conectarte pide a tu contacto que cree otro enlace y comprueba la conexión Unmute Activar audio - No comment provided by engineer. + swipe action Unread No leído - No comment provided by engineer. + swipe action Up to 100 last messages are sent to new members. @@ -7359,6 +7371,10 @@ Repeat join request? Puede aceptar llamadas desde la pantalla de bloqueo, sin autenticación de dispositivos y aplicaciones. No comment provided by engineer. + + You can change it in Appearance settings. + No comment provided by engineer. + You can create it later Puedes crearla más tarde diff --git a/apps/ios/SimpleX Localizations/fi.xcloc/Localized Contents/fi.xliff b/apps/ios/SimpleX Localizations/fi.xcloc/Localized Contents/fi.xliff index a980b93a79..9f120b9808 100644 --- a/apps/ios/SimpleX Localizations/fi.xcloc/Localized Contents/fi.xliff +++ b/apps/ios/SimpleX Localizations/fi.xcloc/Localized Contents/fi.xliff @@ -542,7 +542,8 @@ Accept Hyväksy accept contact request via notification - accept incoming call via notification + accept incoming call via notification + swipe action Accept connection request? @@ -557,7 +558,8 @@ Accept incognito Hyväksy tuntematon - accept contact request via notification + accept contact request via notification + swipe action Acknowledged @@ -1237,6 +1239,10 @@ Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat. No comment provided by engineer. + + Chat list + No comment provided by engineer. + Chat migrated! No comment provided by engineer. @@ -1294,7 +1300,7 @@ Clear Tyhjennä - No comment provided by engineer. + swipe action Clear conversation @@ -1846,7 +1852,8 @@ This is your own one-time link! Delete Poista - chat item action + chat item action + swipe action Delete %lld messages of members? @@ -2045,10 +2052,6 @@ This is your own one-time link! Poistettu klo: %@ copied message info - - Deleted chats - No comment provided by engineer. - Deletion errors No comment provided by engineer. @@ -2878,7 +2881,7 @@ This is your own one-time link! Favorite Suosikki - No comment provided by engineer. + swipe action File error @@ -3610,7 +3613,7 @@ Error: %2$@ Join Liity - No comment provided by engineer. + swipe action Join group @@ -3693,7 +3696,7 @@ This is your link for group %@! Leave Poistu - No comment provided by engineer. + swipe action Leave group @@ -4057,7 +4060,7 @@ This is your link for group %@! Mute Mykistä - No comment provided by engineer. + swipe action Muted when inactive! @@ -4067,7 +4070,7 @@ This is your link for group %@! Name Nimi - No comment provided by engineer. + swipe action Network & servers @@ -4271,10 +4274,6 @@ This is your link for group %@! Vanha tietokanta-arkisto No comment provided by engineer. - - One-hand UI - No comment provided by engineer. - One-time invitation link Kertakutsulinkki @@ -4808,6 +4807,10 @@ Enable in *Network & servers* settings. Arvioi sovellus No comment provided by engineer. + + Reachable chat toolbar + No comment provided by engineer. + Reachable chat toolbar 👋 No comment provided by engineer. @@ -4820,7 +4823,7 @@ Enable in *Network & servers* settings. Read Lue - No comment provided by engineer. + swipe action Read more @@ -4968,7 +4971,8 @@ Enable in *Network & servers* settings. Reject Hylkää - reject incoming call via notification + reject incoming call via notification + swipe action Reject (sender NOT notified) @@ -5064,6 +5068,10 @@ Enable in *Network & servers* settings. Oletustilaan No comment provided by engineer. + + Reset all hints + No comment provided by engineer. + Reset all statistics No comment provided by engineer. @@ -6314,6 +6322,10 @@ Sinua kehotetaan suorittamaan todennus loppuun, ennen kuin tämä ominaisuus ote Voit tarkistaa päästä päähän -salauksen kontaktisi kanssa vertaamalla (tai skannaamalla) laitteidenne koodia. No comment provided by engineer. + + Toggle chat list: + No comment provided by engineer. + Toggle incognito when connecting. No comment provided by engineer. @@ -6388,7 +6400,7 @@ Sinua kehotetaan suorittamaan todennus loppuun, ennen kuin tämä ominaisuus ote Unfav. Epäsuotuisa. - No comment provided by engineer. + swipe action Unhide @@ -6462,12 +6474,12 @@ Jos haluat muodostaa yhteyden, pyydä kontaktiasi luomaan toinen yhteyslinkki ja Unmute Poista mykistys - No comment provided by engineer. + swipe action Unread Lukematon - No comment provided by engineer. + swipe action Up to 100 last messages are sent to new members. @@ -6913,6 +6925,10 @@ Repeat join request? Voit vastaanottaa puheluita lukitusnäytöltä ilman laitteen ja sovelluksen todennusta. No comment provided by engineer. + + You can change it in Appearance settings. + No comment provided by engineer. + You can create it later Voit luoda sen myöhemmin diff --git a/apps/ios/SimpleX Localizations/fr.xcloc/Localized Contents/fr.xliff b/apps/ios/SimpleX Localizations/fr.xcloc/Localized Contents/fr.xliff index 82eb9384e9..94017c5ece 100644 --- a/apps/ios/SimpleX Localizations/fr.xcloc/Localized Contents/fr.xliff +++ b/apps/ios/SimpleX Localizations/fr.xcloc/Localized Contents/fr.xliff @@ -566,7 +566,8 @@ Accept Accepter accept contact request via notification - accept incoming call via notification + accept incoming call via notification + swipe action Accept connection request? @@ -581,7 +582,8 @@ Accept incognito Accepter en incognito - accept contact request via notification + accept contact request via notification + swipe action Acknowledged @@ -1307,6 +1309,10 @@ Le chat est arrêté. Si vous avez déjà utilisé cette base de données sur un autre appareil, vous devez la transférer à nouveau avant de démarrer le chat. No comment provided by engineer. + + Chat list + No comment provided by engineer. + Chat migrated! Messagerie transférée ! @@ -1370,7 +1376,7 @@ Clear Effacer - No comment provided by engineer. + swipe action Clear conversation @@ -1963,7 +1969,8 @@ Il s'agit de votre propre lien unique ! Delete Supprimer - chat item action + chat item action + swipe action Delete %lld messages of members? @@ -2167,10 +2174,6 @@ Il s'agit de votre propre lien unique ! Supprimé à : %@ copied message info - - Deleted chats - No comment provided by engineer. - Deletion errors Erreurs de suppression @@ -3053,7 +3056,7 @@ Il s'agit de votre propre lien unique ! Favorite Favoris - No comment provided by engineer. + swipe action File error @@ -3829,7 +3832,7 @@ Erreur : %2$@ Join Rejoindre - No comment provided by engineer. + swipe action Join group @@ -3920,7 +3923,7 @@ Voici votre lien pour le groupe %@ ! Leave Quitter - No comment provided by engineer. + swipe action Leave group @@ -4312,7 +4315,7 @@ Voici votre lien pour le groupe %@ ! Mute Muet - No comment provided by engineer. + swipe action Muted when inactive! @@ -4322,7 +4325,7 @@ Voici votre lien pour le groupe %@ ! Name Nom - No comment provided by engineer. + swipe action Network & servers @@ -4537,10 +4540,6 @@ Voici votre lien pour le groupe %@ ! Archives de l'ancienne base de données No comment provided by engineer. - - One-hand UI - No comment provided by engineer. - One-time invitation link Lien d'invitation unique @@ -5114,6 +5113,10 @@ Activez-le dans les paramètres *Réseau et serveurs*. Évaluer l'app No comment provided by engineer. + + Reachable chat toolbar + No comment provided by engineer. + Reachable chat toolbar 👋 No comment provided by engineer. @@ -5126,7 +5129,7 @@ Activez-le dans les paramètres *Réseau et serveurs*. Read Lire - No comment provided by engineer. + swipe action Read more @@ -5286,7 +5289,8 @@ Activez-le dans les paramètres *Réseau et serveurs*. Reject Rejeter - reject incoming call via notification + reject incoming call via notification + swipe action Reject (sender NOT notified) @@ -5388,6 +5392,10 @@ Activez-le dans les paramètres *Réseau et serveurs*. Réinitialisation No comment provided by engineer. + + Reset all hints + No comment provided by engineer. + Reset all statistics Réinitialiser toutes les statistiques @@ -6722,6 +6730,10 @@ Vous serez invité à confirmer l'authentification avant que cette fonction ne s Pour vérifier le chiffrement de bout en bout avec votre contact, comparez (ou scannez) le code sur vos appareils. No comment provided by engineer. + + Toggle chat list: + No comment provided by engineer. + Toggle incognito when connecting. Basculer en mode incognito lors de la connexion. @@ -6805,7 +6817,7 @@ Vous serez invité à confirmer l'authentification avant que cette fonction ne s Unfav. Unfav. - No comment provided by engineer. + swipe action Unhide @@ -6882,12 +6894,12 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien Unmute Démute - No comment provided by engineer. + swipe action Unread Non lu - No comment provided by engineer. + swipe action Up to 100 last messages are sent to new members. @@ -7379,6 +7391,10 @@ Répéter la demande d'adhésion ? Vous pouvez accepter des appels à partir de l'écran de verrouillage, sans authentification de l'appareil ou de l'application. No comment provided by engineer. + + You can change it in Appearance settings. + No comment provided by engineer. + You can create it later Vous pouvez la créer plus tard diff --git a/apps/ios/SimpleX Localizations/hu.xcloc/Localized Contents/hu.xliff b/apps/ios/SimpleX Localizations/hu.xcloc/Localized Contents/hu.xliff index 8d932c6a01..2574511655 100644 --- a/apps/ios/SimpleX Localizations/hu.xcloc/Localized Contents/hu.xliff +++ b/apps/ios/SimpleX Localizations/hu.xcloc/Localized Contents/hu.xliff @@ -566,7 +566,8 @@ Accept Elfogadás accept contact request via notification - accept incoming call via notification + accept incoming call via notification + swipe action Accept connection request? @@ -581,7 +582,8 @@ Accept incognito Fogadás inkognítóban - accept contact request via notification + accept contact request via notification + swipe action Acknowledged @@ -1308,6 +1310,10 @@ A csevegés leállt. Ha már használta ezt az adatbázist egy másik eszközön, úgy visszaállítás szükséges a csevegés megkezdése előtt. No comment provided by engineer. + + Chat list + No comment provided by engineer. + Chat migrated! A csevegés átköltöztetve! @@ -1371,7 +1377,7 @@ Clear Kiürítés - No comment provided by engineer. + swipe action Clear conversation @@ -1964,7 +1970,8 @@ Ez az egyszer használatos hivatkozása! Delete Törlés - chat item action + chat item action + swipe action Delete %lld messages of members? @@ -2168,10 +2175,6 @@ Ez az egyszer használatos hivatkozása! Törölve ekkor: %@ copied message info - - Deleted chats - No comment provided by engineer. - Deletion errors Törlési hibák @@ -3054,7 +3057,7 @@ Ez az egyszer használatos hivatkozása! Favorite Kedvenc - No comment provided by engineer. + swipe action File error @@ -3830,7 +3833,7 @@ Hiba: %2$@ Join Csatlakozás - No comment provided by engineer. + swipe action Join group @@ -3921,7 +3924,7 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Leave Elhagyás - No comment provided by engineer. + swipe action Leave group @@ -4315,7 +4318,7 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Mute Elnémítás - No comment provided by engineer. + swipe action Muted when inactive! @@ -4325,7 +4328,7 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Name Név - No comment provided by engineer. + swipe action Network & servers @@ -4540,10 +4543,6 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Régi adatbázis archívum No comment provided by engineer. - - One-hand UI - No comment provided by engineer. - One-time invitation link Egyszer használatos meghívó hivatkozás @@ -5117,6 +5116,10 @@ Engedélyezze a beállításokban a *Hálózat és kiszolgálók* menüpontban.< Értékelje az alkalmazást No comment provided by engineer. + + Reachable chat toolbar + No comment provided by engineer. + Reachable chat toolbar 👋 No comment provided by engineer. @@ -5129,7 +5132,7 @@ Engedélyezze a beállításokban a *Hálózat és kiszolgálók* menüpontban.< Read Olvasd el - No comment provided by engineer. + swipe action Read more @@ -5289,7 +5292,8 @@ Engedélyezze a beállításokban a *Hálózat és kiszolgálók* menüpontban.< Reject Elutasítás - reject incoming call via notification + reject incoming call via notification + swipe action Reject (sender NOT notified) @@ -5391,6 +5395,10 @@ Engedélyezze a beállításokban a *Hálózat és kiszolgálók* menüpontban.< Alaphelyzetbe állítás No comment provided by engineer. + + Reset all hints + No comment provided by engineer. + Reset all statistics Minden statisztika visszaállítása @@ -6729,6 +6737,10 @@ A funkció bekapcsolása előtt a rendszer felszólítja a képernyőzár beáll A végpontok közötti titkosítás ellenőrzéséhez hasonlítsa össze (vagy olvassa be a QR-kódot) az ismerőse eszközén lévő kóddal. No comment provided by engineer. + + Toggle chat list: + No comment provided by engineer. + Toggle incognito when connecting. Inkognitó mód kapcsolódáskor. @@ -6812,7 +6824,7 @@ A funkció bekapcsolása előtt a rendszer felszólítja a képernyőzár beáll Unfav. Nem kedvelt. - No comment provided by engineer. + swipe action Unhide @@ -6889,12 +6901,12 @@ A kapcsolódáshoz kérje meg ismerősét, hogy hozzon létre egy másik kapcsol Unmute Némítás feloldása - No comment provided by engineer. + swipe action Unread Olvasatlan - No comment provided by engineer. + swipe action Up to 100 last messages are sent to new members. @@ -7387,6 +7399,10 @@ Csatlakozási kérés megismétlése? Hívásokat fogadhat a lezárási képernyőről, eszköz- és alkalmazáshitelesítés nélkül. No comment provided by engineer. + + You can change it in Appearance settings. + No comment provided by engineer. + You can create it later Létrehozás később diff --git a/apps/ios/SimpleX Localizations/it.xcloc/Localized Contents/it.xliff b/apps/ios/SimpleX Localizations/it.xcloc/Localized Contents/it.xliff index 2049816358..fedc2e2d9e 100644 --- a/apps/ios/SimpleX Localizations/it.xcloc/Localized Contents/it.xliff +++ b/apps/ios/SimpleX Localizations/it.xcloc/Localized Contents/it.xliff @@ -566,7 +566,8 @@ Accept Accetta accept contact request via notification - accept incoming call via notification + accept incoming call via notification + swipe action Accept connection request? @@ -581,7 +582,8 @@ Accept incognito Accetta in incognito - accept contact request via notification + accept contact request via notification + swipe action Acknowledged @@ -1308,6 +1310,10 @@ La chat è ferma. Se hai già usato questo database su un altro dispositivo, dovresti trasferirlo prima di avviare la chat. No comment provided by engineer. + + Chat list + No comment provided by engineer. + Chat migrated! Chat migrata! @@ -1371,7 +1377,7 @@ Clear Svuota - No comment provided by engineer. + swipe action Clear conversation @@ -1964,7 +1970,8 @@ Questo è il tuo link una tantum! Delete Elimina - chat item action + chat item action + swipe action Delete %lld messages of members? @@ -2168,10 +2175,6 @@ Questo è il tuo link una tantum! Eliminato il: %@ copied message info - - Deleted chats - No comment provided by engineer. - Deletion errors Errori di eliminazione @@ -3054,7 +3057,7 @@ Questo è il tuo link una tantum! Favorite Preferito - No comment provided by engineer. + swipe action File error @@ -3830,7 +3833,7 @@ Errore: %2$@ Join Entra - No comment provided by engineer. + swipe action Join group @@ -3921,7 +3924,7 @@ Questo è il tuo link per il gruppo %@! Leave Esci - No comment provided by engineer. + swipe action Leave group @@ -4315,7 +4318,7 @@ Questo è il tuo link per il gruppo %@! Mute Silenzia - No comment provided by engineer. + swipe action Muted when inactive! @@ -4325,7 +4328,7 @@ Questo è il tuo link per il gruppo %@! Name Nome - No comment provided by engineer. + swipe action Network & servers @@ -4540,10 +4543,6 @@ Questo è il tuo link per il gruppo %@! Vecchio archivio del database No comment provided by engineer. - - One-hand UI - No comment provided by engineer. - One-time invitation link Link di invito una tantum @@ -5117,6 +5116,10 @@ Attivalo nelle impostazioni *Rete e server*. Valuta l'app No comment provided by engineer. + + Reachable chat toolbar + No comment provided by engineer. + Reachable chat toolbar 👋 No comment provided by engineer. @@ -5129,7 +5132,7 @@ Attivalo nelle impostazioni *Rete e server*. Read Leggi - No comment provided by engineer. + swipe action Read more @@ -5289,7 +5292,8 @@ Attivalo nelle impostazioni *Rete e server*. Reject Rifiuta - reject incoming call via notification + reject incoming call via notification + swipe action Reject (sender NOT notified) @@ -5391,6 +5395,10 @@ Attivalo nelle impostazioni *Rete e server*. Ripristina No comment provided by engineer. + + Reset all hints + No comment provided by engineer. + Reset all statistics Azzera tutte le statistiche @@ -6729,6 +6737,10 @@ Ti verrà chiesto di completare l'autenticazione prima di attivare questa funzio Per verificare la crittografia end-to-end con il tuo contatto, confrontate (o scansionate) il codice sui vostri dispositivi. No comment provided by engineer. + + Toggle chat list: + No comment provided by engineer. + Toggle incognito when connecting. Attiva/disattiva l'incognito quando ti colleghi. @@ -6812,7 +6824,7 @@ Ti verrà chiesto di completare l'autenticazione prima di attivare questa funzio Unfav. Non pref. - No comment provided by engineer. + swipe action Unhide @@ -6889,12 +6901,12 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e Unmute Riattiva notifiche - No comment provided by engineer. + swipe action Unread Non letto - No comment provided by engineer. + swipe action Up to 100 last messages are sent to new members. @@ -7387,6 +7399,10 @@ Ripetere la richiesta di ingresso? Puoi accettare chiamate dalla schermata di blocco, senza l'autenticazione del dispositivo e dell'app. No comment provided by engineer. + + You can change it in Appearance settings. + No comment provided by engineer. + You can create it later Puoi crearlo più tardi diff --git a/apps/ios/SimpleX Localizations/ja.xcloc/Localized Contents/ja.xliff b/apps/ios/SimpleX Localizations/ja.xcloc/Localized Contents/ja.xliff index 9d34262316..7d05b72347 100644 --- a/apps/ios/SimpleX Localizations/ja.xcloc/Localized Contents/ja.xliff +++ b/apps/ios/SimpleX Localizations/ja.xcloc/Localized Contents/ja.xliff @@ -559,7 +559,8 @@ Accept 承諾 accept contact request via notification - accept incoming call via notification + accept incoming call via notification + swipe action Accept connection request? @@ -574,7 +575,8 @@ Accept incognito シークレットモードで承諾 - accept contact request via notification + accept contact request via notification + swipe action Acknowledged @@ -1261,6 +1263,10 @@ Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat. No comment provided by engineer. + + Chat list + No comment provided by engineer. + Chat migrated! No comment provided by engineer. @@ -1318,7 +1324,7 @@ Clear 消す - No comment provided by engineer. + swipe action Clear conversation @@ -1870,7 +1876,8 @@ This is your own one-time link! Delete 削除 - chat item action + chat item action + swipe action Delete %lld messages of members? @@ -2069,10 +2076,6 @@ This is your own one-time link! 削除完了: %@ copied message info - - Deleted chats - No comment provided by engineer. - Deletion errors No comment provided by engineer. @@ -2903,7 +2906,7 @@ This is your own one-time link! Favorite お気に入り - No comment provided by engineer. + swipe action File error @@ -3635,7 +3638,7 @@ Error: %2$@ Join 参加 - No comment provided by engineer. + swipe action Join group @@ -3718,7 +3721,7 @@ This is your link for group %@! Leave 脱退 - No comment provided by engineer. + swipe action Leave group @@ -4081,7 +4084,7 @@ This is your link for group %@! Mute ミュート - No comment provided by engineer. + swipe action Muted when inactive! @@ -4091,7 +4094,7 @@ This is your link for group %@! Name 名前 - No comment provided by engineer. + swipe action Network & servers @@ -4296,10 +4299,6 @@ This is your link for group %@! 過去のデータベースアーカイブ No comment provided by engineer. - - One-hand UI - No comment provided by engineer. - One-time invitation link 使い捨ての招待リンク @@ -4834,6 +4833,10 @@ Enable in *Network & servers* settings. アプリを評価 No comment provided by engineer. + + Reachable chat toolbar + No comment provided by engineer. + Reachable chat toolbar 👋 No comment provided by engineer. @@ -4846,7 +4849,7 @@ Enable in *Network & servers* settings. Read 読む - No comment provided by engineer. + swipe action Read more @@ -4993,7 +4996,8 @@ Enable in *Network & servers* settings. Reject 拒否 - reject incoming call via notification + reject incoming call via notification + swipe action Reject (sender NOT notified) @@ -5089,6 +5093,10 @@ Enable in *Network & servers* settings. 戻す No comment provided by engineer. + + Reset all hints + No comment provided by engineer. + Reset all statistics No comment provided by engineer. @@ -6332,6 +6340,10 @@ You will be prompted to complete authentication before this feature is enabled.< エンドツーエンド暗号化を確認するには、ご自分の端末と連絡先の端末のコードを比べます (スキャンします)。 No comment provided by engineer. + + Toggle chat list: + No comment provided by engineer. + Toggle incognito when connecting. No comment provided by engineer. @@ -6406,7 +6418,7 @@ You will be prompted to complete authentication before this feature is enabled.< Unfav. お気に入りを取り消す。 - No comment provided by engineer. + swipe action Unhide @@ -6480,12 +6492,12 @@ To connect, please ask your contact to create another connection link and check Unmute ミュート解除 - No comment provided by engineer. + swipe action Unread 未読 - No comment provided by engineer. + swipe action Up to 100 last messages are sent to new members. @@ -6931,6 +6943,10 @@ Repeat join request? デバイスやアプリの認証を行わずに、ロック画面から通話を受けることができます。 No comment provided by engineer. + + You can change it in Appearance settings. + No comment provided by engineer. + You can create it later 後からでも作成できます diff --git a/apps/ios/SimpleX Localizations/nl.xcloc/Localized Contents/nl.xliff b/apps/ios/SimpleX Localizations/nl.xcloc/Localized Contents/nl.xliff index e138a209de..c16f9f3ff4 100644 --- a/apps/ios/SimpleX Localizations/nl.xcloc/Localized Contents/nl.xliff +++ b/apps/ios/SimpleX Localizations/nl.xcloc/Localized Contents/nl.xliff @@ -566,7 +566,8 @@ Accept Accepteer accept contact request via notification - accept incoming call via notification + accept incoming call via notification + swipe action Accept connection request? @@ -581,7 +582,8 @@ Accept incognito Accepteer incognito - accept contact request via notification + accept contact request via notification + swipe action Acknowledged @@ -1308,6 +1310,10 @@ Chat is gestopt. Als je deze database al op een ander apparaat hebt gebruikt, moet je deze terugzetten voordat je met chatten begint. No comment provided by engineer. + + Chat list + No comment provided by engineer. + Chat migrated! Chat gemigreerd! @@ -1371,7 +1377,7 @@ Clear Wissen - No comment provided by engineer. + swipe action Clear conversation @@ -1964,7 +1970,8 @@ Dit is uw eigen eenmalige link! Delete Verwijderen - chat item action + chat item action + swipe action Delete %lld messages of members? @@ -2168,10 +2175,6 @@ Dit is uw eigen eenmalige link! Verwijderd om: %@ copied message info - - Deleted chats - No comment provided by engineer. - Deletion errors Verwijderingsfouten @@ -3054,7 +3057,7 @@ Dit is uw eigen eenmalige link! Favorite Favoriet - No comment provided by engineer. + swipe action File error @@ -3830,7 +3833,7 @@ Fout: %2$@ Join Word lid van - No comment provided by engineer. + swipe action Join group @@ -3921,7 +3924,7 @@ Dit is jouw link voor groep %@! Leave Verlaten - No comment provided by engineer. + swipe action Leave group @@ -4315,7 +4318,7 @@ Dit is jouw link voor groep %@! Mute Dempen - No comment provided by engineer. + swipe action Muted when inactive! @@ -4325,7 +4328,7 @@ Dit is jouw link voor groep %@! Name Naam - No comment provided by engineer. + swipe action Network & servers @@ -4540,10 +4543,6 @@ Dit is jouw link voor groep %@! Oud database archief No comment provided by engineer. - - One-hand UI - No comment provided by engineer. - One-time invitation link Eenmalige uitnodiging link @@ -5117,6 +5116,10 @@ Schakel dit in in *Netwerk en servers*-instellingen. Beoordeel de app No comment provided by engineer. + + Reachable chat toolbar + No comment provided by engineer. + Reachable chat toolbar 👋 No comment provided by engineer. @@ -5129,7 +5132,7 @@ Schakel dit in in *Netwerk en servers*-instellingen. Read Lees - No comment provided by engineer. + swipe action Read more @@ -5289,7 +5292,8 @@ Schakel dit in in *Netwerk en servers*-instellingen. Reject Afwijzen - reject incoming call via notification + reject incoming call via notification + swipe action Reject (sender NOT notified) @@ -5391,6 +5395,10 @@ Schakel dit in in *Netwerk en servers*-instellingen. Resetten No comment provided by engineer. + + Reset all hints + No comment provided by engineer. + Reset all statistics Reset alle statistieken @@ -6729,6 +6737,10 @@ U wordt gevraagd de authenticatie te voltooien voordat deze functie wordt ingesc Vergelijk (of scan) de code op uw apparaten om end-to-end-codering met uw contact te verifiëren. No comment provided by engineer. + + Toggle chat list: + No comment provided by engineer. + Toggle incognito when connecting. Schakel incognito in tijdens het verbinden. @@ -6812,7 +6824,7 @@ U wordt gevraagd de authenticatie te voltooien voordat deze functie wordt ingesc Unfav. Niet fav. - No comment provided by engineer. + swipe action Unhide @@ -6889,12 +6901,12 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak Unmute Dempen opheffen - No comment provided by engineer. + swipe action Unread Ongelezen - No comment provided by engineer. + swipe action Up to 100 last messages are sent to new members. @@ -7387,6 +7399,10 @@ Deelnameverzoek herhalen? U kunt oproepen van het vergrendelingsscherm accepteren, zonder apparaat- en app-verificatie. No comment provided by engineer. + + You can change it in Appearance settings. + No comment provided by engineer. + You can create it later U kan het later maken diff --git a/apps/ios/SimpleX Localizations/pl.xcloc/Localized Contents/pl.xliff b/apps/ios/SimpleX Localizations/pl.xcloc/Localized Contents/pl.xliff index 19bad71751..2905aa52cf 100644 --- a/apps/ios/SimpleX Localizations/pl.xcloc/Localized Contents/pl.xliff +++ b/apps/ios/SimpleX Localizations/pl.xcloc/Localized Contents/pl.xliff @@ -566,7 +566,8 @@ Accept Akceptuj accept contact request via notification - accept incoming call via notification + accept incoming call via notification + swipe action Accept connection request? @@ -581,7 +582,8 @@ Accept incognito Akceptuj incognito - accept contact request via notification + accept contact request via notification + swipe action Acknowledged @@ -1305,6 +1307,10 @@ Czat został zatrzymany. Jeśli korzystałeś już z tej bazy danych na innym urządzeniu, powinieneś przenieść ją z powrotem przed rozpoczęciem czatu. No comment provided by engineer. + + Chat list + No comment provided by engineer. + Chat migrated! Czat zmigrowany! @@ -1368,7 +1374,7 @@ Clear Wyczyść - No comment provided by engineer. + swipe action Clear conversation @@ -1960,7 +1966,8 @@ To jest twój jednorazowy link! Delete Usuń - chat item action + chat item action + swipe action Delete %lld messages of members? @@ -2163,10 +2170,6 @@ To jest twój jednorazowy link! Usunięto o: %@ copied message info - - Deleted chats - No comment provided by engineer. - Deletion errors Błędy usuwania @@ -3044,7 +3047,7 @@ To jest twój jednorazowy link! Favorite Ulubione - No comment provided by engineer. + swipe action File error @@ -3817,7 +3820,7 @@ Błąd: %2$@ Join Dołącz - No comment provided by engineer. + swipe action Join group @@ -3908,7 +3911,7 @@ To jest twój link do grupy %@! Leave Opuść - No comment provided by engineer. + swipe action Leave group @@ -4299,7 +4302,7 @@ To jest twój link do grupy %@! Mute Wycisz - No comment provided by engineer. + swipe action Muted when inactive! @@ -4309,7 +4312,7 @@ To jest twój link do grupy %@! Name Nazwa - No comment provided by engineer. + swipe action Network & servers @@ -4523,10 +4526,6 @@ To jest twój link do grupy %@! Stare archiwum bazy danych No comment provided by engineer. - - One-hand UI - No comment provided by engineer. - One-time invitation link Jednorazowy link zaproszenia @@ -5100,6 +5099,10 @@ Włącz w ustawianiach *Sieć i serwery* . Oceń aplikację No comment provided by engineer. + + Reachable chat toolbar + No comment provided by engineer. + Reachable chat toolbar 👋 No comment provided by engineer. @@ -5112,7 +5115,7 @@ Włącz w ustawianiach *Sieć i serwery* . Read Czytaj - No comment provided by engineer. + swipe action Read more @@ -5272,7 +5275,8 @@ Włącz w ustawianiach *Sieć i serwery* . Reject Odrzuć - reject incoming call via notification + reject incoming call via notification + swipe action Reject (sender NOT notified) @@ -5374,6 +5378,10 @@ Włącz w ustawianiach *Sieć i serwery* . Resetuj No comment provided by engineer. + + Reset all hints + No comment provided by engineer. + Reset all statistics Resetuj wszystkie statystyki @@ -6702,6 +6710,10 @@ Przed włączeniem tej funkcji zostanie wyświetlony monit uwierzytelniania.Aby zweryfikować szyfrowanie end-to-end z Twoim kontaktem porównaj (lub zeskanuj) kod na waszych urządzeniach. No comment provided by engineer. + + Toggle chat list: + No comment provided by engineer. + Toggle incognito when connecting. Przełącz incognito przy połączeniu. @@ -6785,7 +6797,7 @@ Przed włączeniem tej funkcji zostanie wyświetlony monit uwierzytelniania. Unfav. Nie ulub. - No comment provided by engineer. + swipe action Unhide @@ -6862,12 +6874,12 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc Unmute Wyłącz wyciszenie - No comment provided by engineer. + swipe action Unread Nieprzeczytane - No comment provided by engineer. + swipe action Up to 100 last messages are sent to new members. @@ -7359,6 +7371,10 @@ Powtórzyć prośbę dołączenia? Możesz przyjmować połączenia z ekranu blokady, bez uwierzytelniania urządzenia i aplikacji. No comment provided by engineer. + + You can change it in Appearance settings. + No comment provided by engineer. + You can create it later Możesz go utworzyć później diff --git a/apps/ios/SimpleX Localizations/ru.xcloc/Localized Contents/ru.xliff b/apps/ios/SimpleX Localizations/ru.xcloc/Localized Contents/ru.xliff index 1a7578c908..529276a7d4 100644 --- a/apps/ios/SimpleX Localizations/ru.xcloc/Localized Contents/ru.xliff +++ b/apps/ios/SimpleX Localizations/ru.xcloc/Localized Contents/ru.xliff @@ -565,7 +565,8 @@ Accept Принять accept contact request via notification - accept incoming call via notification + accept incoming call via notification + swipe action Accept connection request? @@ -580,7 +581,8 @@ Accept incognito Принять инкогнито - accept contact request via notification + accept contact request via notification + swipe action Acknowledged @@ -1290,6 +1292,10 @@ Чат остановлен. Если вы уже использовали эту базу данных на другом устройстве, перенесите ее обратно до запуска чата. No comment provided by engineer. + + Chat list + No comment provided by engineer. + Chat migrated! Чат мигрирован! @@ -1349,7 +1355,7 @@ Clear Очистить - No comment provided by engineer. + swipe action Clear conversation @@ -1927,7 +1933,8 @@ This is your own one-time link! Delete Удалить - chat item action + chat item action + swipe action Delete %lld messages of members? @@ -2129,10 +2136,6 @@ This is your own one-time link! Удалено: %@ copied message info - - Deleted chats - No comment provided by engineer. - Deletion errors No comment provided by engineer. @@ -2998,7 +3001,7 @@ This is your own one-time link! Favorite Избранный - No comment provided by engineer. + swipe action File error @@ -3762,7 +3765,7 @@ Error: %2$@ Join Вступить - No comment provided by engineer. + swipe action Join group @@ -3853,7 +3856,7 @@ This is your link for group %@! Leave Выйти - No comment provided by engineer. + swipe action Leave group @@ -4234,7 +4237,7 @@ This is your link for group %@! Mute Без звука - No comment provided by engineer. + swipe action Muted when inactive! @@ -4244,7 +4247,7 @@ This is your link for group %@! Name Имя - No comment provided by engineer. + swipe action Network & servers @@ -4456,10 +4459,6 @@ This is your link for group %@! Старый архив чата No comment provided by engineer. - - One-hand UI - No comment provided by engineer. - One-time invitation link Одноразовая ссылка @@ -5023,6 +5022,10 @@ Enable in *Network & servers* settings. Оценить приложение No comment provided by engineer. + + Reachable chat toolbar + No comment provided by engineer. + Reachable chat toolbar 👋 No comment provided by engineer. @@ -5035,7 +5038,7 @@ Enable in *Network & servers* settings. Read Прочитано - No comment provided by engineer. + swipe action Read more @@ -5186,7 +5189,8 @@ Enable in *Network & servers* settings. Reject Отклонить - reject incoming call via notification + reject incoming call via notification + swipe action Reject (sender NOT notified) @@ -5287,6 +5291,10 @@ Enable in *Network & servers* settings. Сбросить No comment provided by engineer. + + Reset all hints + No comment provided by engineer. + Reset all statistics No comment provided by engineer. @@ -6580,6 +6588,10 @@ You will be prompted to complete authentication before this feature is enabled.< Чтобы подтвердить end-to-end шифрование с Вашим контактом сравните (или сканируйте) код безопасности на Ваших устройствах. No comment provided by engineer. + + Toggle chat list: + No comment provided by engineer. + Toggle incognito when connecting. Установите режим Инкогнито при соединении. @@ -6661,7 +6673,7 @@ You will be prompted to complete authentication before this feature is enabled.< Unfav. Не избр. - No comment provided by engineer. + swipe action Unhide @@ -6738,12 +6750,12 @@ To connect, please ask your contact to create another connection link and check Unmute Уведомлять - No comment provided by engineer. + swipe action Unread Не прочитано - No comment provided by engineer. + swipe action Up to 100 last messages are sent to new members. @@ -7226,6 +7238,10 @@ Repeat join request? Вы можете принимать звонки на экране блокировки, без аутентификации. No comment provided by engineer. + + You can change it in Appearance settings. + No comment provided by engineer. + You can create it later Вы можете создать его позже diff --git a/apps/ios/SimpleX Localizations/th.xcloc/Localized Contents/th.xliff b/apps/ios/SimpleX Localizations/th.xcloc/Localized Contents/th.xliff index 6958c185e6..e078f14979 100644 --- a/apps/ios/SimpleX Localizations/th.xcloc/Localized Contents/th.xliff +++ b/apps/ios/SimpleX Localizations/th.xcloc/Localized Contents/th.xliff @@ -535,7 +535,8 @@ Accept รับ accept contact request via notification - accept incoming call via notification + accept incoming call via notification + swipe action Accept connection request? @@ -549,7 +550,8 @@ Accept incognito ยอมรับโหมดไม่ระบุตัวตน - accept contact request via notification + accept contact request via notification + swipe action Acknowledged @@ -1229,6 +1231,10 @@ Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat. No comment provided by engineer. + + Chat list + No comment provided by engineer. + Chat migrated! No comment provided by engineer. @@ -1286,7 +1292,7 @@ Clear ลบ - No comment provided by engineer. + swipe action Clear conversation @@ -1835,7 +1841,8 @@ This is your own one-time link! Delete ลบ - chat item action + chat item action + swipe action Delete %lld messages of members? @@ -2034,10 +2041,6 @@ This is your own one-time link! ลบที่: %@ copied message info - - Deleted chats - No comment provided by engineer. - Deletion errors No comment provided by engineer. @@ -2863,7 +2866,7 @@ This is your own one-time link! Favorite ที่ชอบ - No comment provided by engineer. + swipe action File error @@ -3593,7 +3596,7 @@ Error: %2$@ Join เข้าร่วม - No comment provided by engineer. + swipe action Join group @@ -3676,7 +3679,7 @@ This is your link for group %@! Leave ออกจาก - No comment provided by engineer. + swipe action Leave group @@ -4039,7 +4042,7 @@ This is your link for group %@! Mute ปิดเสียง - No comment provided by engineer. + swipe action Muted when inactive! @@ -4049,7 +4052,7 @@ This is your link for group %@! Name ชื่อ - No comment provided by engineer. + swipe action Network & servers @@ -4252,10 +4255,6 @@ This is your link for group %@! คลังฐานข้อมูลเก่า No comment provided by engineer. - - One-hand UI - No comment provided by engineer. - One-time invitation link ลิงก์คำเชิญแบบใช้ครั้งเดียว @@ -4787,6 +4786,10 @@ Enable in *Network & servers* settings. ให้คะแนนแอป No comment provided by engineer. + + Reachable chat toolbar + No comment provided by engineer. + Reachable chat toolbar 👋 No comment provided by engineer. @@ -4799,7 +4802,7 @@ Enable in *Network & servers* settings. Read อ่าน - No comment provided by engineer. + swipe action Read more @@ -4946,7 +4949,8 @@ Enable in *Network & servers* settings. Reject ปฏิเสธ - reject incoming call via notification + reject incoming call via notification + swipe action Reject (sender NOT notified) @@ -5041,6 +5045,10 @@ Enable in *Network & servers* settings. รีเซ็ต No comment provided by engineer. + + Reset all hints + No comment provided by engineer. + Reset all statistics No comment provided by engineer. @@ -6286,6 +6294,10 @@ You will be prompted to complete authentication before this feature is enabled.< ในการตรวจสอบการเข้ารหัสแบบ encrypt จากต้นจนจบ กับผู้ติดต่อของคุณ ให้เปรียบเทียบ (หรือสแกน) รหัสบนอุปกรณ์ของคุณ No comment provided by engineer. + + Toggle chat list: + No comment provided by engineer. + Toggle incognito when connecting. No comment provided by engineer. @@ -6360,7 +6372,7 @@ You will be prompted to complete authentication before this feature is enabled.< Unfav. เลิกชอบ - No comment provided by engineer. + swipe action Unhide @@ -6434,12 +6446,12 @@ To connect, please ask your contact to create another connection link and check Unmute เปิดเสียง - No comment provided by engineer. + swipe action Unread เปลี่ยนเป็นยังไม่ได้อ่าน - No comment provided by engineer. + swipe action Up to 100 last messages are sent to new members. @@ -6883,6 +6895,10 @@ Repeat join request? คุณสามารถรับสายจากหน้าจอล็อกโดยไม่ต้องมีการตรวจสอบสิทธิ์อุปกรณ์และแอป No comment provided by engineer. + + You can change it in Appearance settings. + No comment provided by engineer. + You can create it later คุณสามารถสร้างได้ในภายหลัง diff --git a/apps/ios/SimpleX Localizations/tr.xcloc/Localized Contents/tr.xliff b/apps/ios/SimpleX Localizations/tr.xcloc/Localized Contents/tr.xliff index c79f051d2c..2a3abba4d3 100644 --- a/apps/ios/SimpleX Localizations/tr.xcloc/Localized Contents/tr.xliff +++ b/apps/ios/SimpleX Localizations/tr.xcloc/Localized Contents/tr.xliff @@ -565,7 +565,8 @@ Accept Kabul et accept contact request via notification - accept incoming call via notification + accept incoming call via notification + swipe action Accept connection request? @@ -580,7 +581,8 @@ Accept incognito Takma adla kabul et - accept contact request via notification + accept contact request via notification + swipe action Acknowledged @@ -1290,6 +1292,10 @@ Sohbet durduruldu. Bu veritabanını zaten başka bir cihazda kullandıysanız, sohbete başlamadan önce onu geri aktarmalısınız. No comment provided by engineer. + + Chat list + No comment provided by engineer. + Chat migrated! Sohbet taşındı! @@ -1349,7 +1355,7 @@ Clear Temizle - No comment provided by engineer. + swipe action Clear conversation @@ -1928,7 +1934,8 @@ Bu senin kendi tek kullanımlık bağlantın! Delete Sil - chat item action + chat item action + swipe action Delete %lld messages of members? @@ -2130,10 +2137,6 @@ Bu senin kendi tek kullanımlık bağlantın! %@ de silindi copied message info - - Deleted chats - No comment provided by engineer. - Deletion errors No comment provided by engineer. @@ -2999,7 +3002,7 @@ Bu senin kendi tek kullanımlık bağlantın! Favorite Favori - No comment provided by engineer. + swipe action File error @@ -3763,7 +3766,7 @@ Hata: %2$@ Join Katıl - No comment provided by engineer. + swipe action Join group @@ -3854,7 +3857,7 @@ Bu senin grup için bağlantın %@! Leave Ayrıl - No comment provided by engineer. + swipe action Leave group @@ -4236,7 +4239,7 @@ Bu senin grup için bağlantın %@! Mute Sustur - No comment provided by engineer. + swipe action Muted when inactive! @@ -4246,7 +4249,7 @@ Bu senin grup için bağlantın %@! Name İsim - No comment provided by engineer. + swipe action Network & servers @@ -4458,10 +4461,6 @@ Bu senin grup için bağlantın %@! Eski veritabanı arşivi No comment provided by engineer. - - One-hand UI - No comment provided by engineer. - One-time invitation link Tek zamanlı bağlantı daveti @@ -5025,6 +5024,10 @@ Enable in *Network & servers* settings. Uygulamayı değerlendir No comment provided by engineer. + + Reachable chat toolbar + No comment provided by engineer. + Reachable chat toolbar 👋 No comment provided by engineer. @@ -5037,7 +5040,7 @@ Enable in *Network & servers* settings. Read Oku - No comment provided by engineer. + swipe action Read more @@ -5188,7 +5191,8 @@ Enable in *Network & servers* settings. Reject Reddet - reject incoming call via notification + reject incoming call via notification + swipe action Reject (sender NOT notified) @@ -5289,6 +5293,10 @@ Enable in *Network & servers* settings. Sıfırla No comment provided by engineer. + + Reset all hints + No comment provided by engineer. + Reset all statistics No comment provided by engineer. @@ -6582,6 +6590,10 @@ Bu özellik etkinleştirilmeden önce kimlik doğrulamayı tamamlamanız istenec Kişinizle uçtan uca şifrelemeyi doğrulamak için cihazlarınızdaki kodu karşılaştırın (veya tarayın). No comment provided by engineer. + + Toggle chat list: + No comment provided by engineer. + Toggle incognito when connecting. Bağlanırken gizli moda geçiş yap. @@ -6663,7 +6675,7 @@ Bu özellik etkinleştirilmeden önce kimlik doğrulamayı tamamlamanız istenec Unfav. Favorilerden çık. - No comment provided by engineer. + swipe action Unhide @@ -6740,12 +6752,12 @@ Bağlanmak için lütfen kişinizden başka bir bağlantı oluşturmasını iste Unmute Susturmayı kaldır - No comment provided by engineer. + swipe action Unread Okunmamış - No comment provided by engineer. + swipe action Up to 100 last messages are sent to new members. @@ -7228,6 +7240,10 @@ Katılma isteği tekrarlansın mı? Cihaz ve uygulama kimlik doğrulaması olmadan kilit ekranından çağrı kabul edebilirsiniz. No comment provided by engineer. + + You can change it in Appearance settings. + No comment provided by engineer. + You can create it later Daha sonra oluşturabilirsiniz diff --git a/apps/ios/SimpleX Localizations/uk.xcloc/Localized Contents/uk.xliff b/apps/ios/SimpleX Localizations/uk.xcloc/Localized Contents/uk.xliff index 7e505910ac..4dd083713c 100644 --- a/apps/ios/SimpleX Localizations/uk.xcloc/Localized Contents/uk.xliff +++ b/apps/ios/SimpleX Localizations/uk.xcloc/Localized Contents/uk.xliff @@ -565,7 +565,8 @@ Accept Прийняти accept contact request via notification - accept incoming call via notification + accept incoming call via notification + swipe action Accept connection request? @@ -580,7 +581,8 @@ Accept incognito Прийняти інкогніто - accept contact request via notification + accept contact request via notification + swipe action Acknowledged @@ -1290,6 +1292,10 @@ Чат зупинено. Якщо ви вже використовували цю базу даних на іншому пристрої, перенесіть її назад перед запуском чату. No comment provided by engineer. + + Chat list + No comment provided by engineer. + Chat migrated! Чат перемістився! @@ -1349,7 +1355,7 @@ Clear Чисто - No comment provided by engineer. + swipe action Clear conversation @@ -1928,7 +1934,8 @@ This is your own one-time link! Delete Видалити - chat item action + chat item action + swipe action Delete %lld messages of members? @@ -2130,10 +2137,6 @@ This is your own one-time link! Видалено за: %@ copied message info - - Deleted chats - No comment provided by engineer. - Deletion errors No comment provided by engineer. @@ -2999,7 +3002,7 @@ This is your own one-time link! Favorite Улюблений - No comment provided by engineer. + swipe action File error @@ -3763,7 +3766,7 @@ Error: %2$@ Join Приєднуйтесь - No comment provided by engineer. + swipe action Join group @@ -3854,7 +3857,7 @@ This is your link for group %@! Leave Залишити - No comment provided by engineer. + swipe action Leave group @@ -4236,7 +4239,7 @@ This is your link for group %@! Mute Вимкнути звук - No comment provided by engineer. + swipe action Muted when inactive! @@ -4246,7 +4249,7 @@ This is your link for group %@! Name Ім'я - No comment provided by engineer. + swipe action Network & servers @@ -4458,10 +4461,6 @@ This is your link for group %@! Старий архів бази даних No comment provided by engineer. - - One-hand UI - No comment provided by engineer. - One-time invitation link Посилання на одноразове запрошення @@ -5025,6 +5024,10 @@ Enable in *Network & servers* settings. Оцініть додаток No comment provided by engineer. + + Reachable chat toolbar + No comment provided by engineer. + Reachable chat toolbar 👋 No comment provided by engineer. @@ -5037,7 +5040,7 @@ Enable in *Network & servers* settings. Read Читати - No comment provided by engineer. + swipe action Read more @@ -5188,7 +5191,8 @@ Enable in *Network & servers* settings. Reject Відхилити - reject incoming call via notification + reject incoming call via notification + swipe action Reject (sender NOT notified) @@ -5289,6 +5293,10 @@ Enable in *Network & servers* settings. Перезавантаження No comment provided by engineer. + + Reset all hints + No comment provided by engineer. + Reset all statistics No comment provided by engineer. @@ -6582,6 +6590,10 @@ You will be prompted to complete authentication before this feature is enabled.< Щоб перевірити наскрізне шифрування з вашим контактом, порівняйте (або відскануйте) код на ваших пристроях. No comment provided by engineer. + + Toggle chat list: + No comment provided by engineer. + Toggle incognito when connecting. Увімкніть інкогніто при підключенні. @@ -6663,7 +6675,7 @@ You will be prompted to complete authentication before this feature is enabled.< Unfav. Нелюб. - No comment provided by engineer. + swipe action Unhide @@ -6740,12 +6752,12 @@ To connect, please ask your contact to create another connection link and check Unmute Увімкнути звук - No comment provided by engineer. + swipe action Unread Непрочитане - No comment provided by engineer. + swipe action Up to 100 last messages are sent to new members. @@ -7228,6 +7240,10 @@ Repeat join request? Ви можете приймати дзвінки з екрана блокування без автентифікації пристрою та програми. No comment provided by engineer. + + You can change it in Appearance settings. + No comment provided by engineer. + You can create it later Ви можете створити його пізніше diff --git a/apps/ios/SimpleX Localizations/zh-Hans.xcloc/Localized Contents/zh-Hans.xliff b/apps/ios/SimpleX Localizations/zh-Hans.xcloc/Localized Contents/zh-Hans.xliff index 0dd69443f8..0f428db73a 100644 --- a/apps/ios/SimpleX Localizations/zh-Hans.xcloc/Localized Contents/zh-Hans.xliff +++ b/apps/ios/SimpleX Localizations/zh-Hans.xcloc/Localized Contents/zh-Hans.xliff @@ -553,7 +553,8 @@ Accept 接受 accept contact request via notification - accept incoming call via notification + accept incoming call via notification + swipe action Accept connection request? @@ -568,7 +569,8 @@ Accept incognito 接受隐身聊天 - accept contact request via notification + accept contact request via notification + swipe action Acknowledged @@ -1274,6 +1276,10 @@ 聊天已停止。如果你已经在另一台设备商使用过此数据库,你应该在启动聊天前将数据库传输回来。 No comment provided by engineer. + + Chat list + No comment provided by engineer. + Chat migrated! 已迁移聊天! @@ -1332,7 +1338,7 @@ Clear 清除 - No comment provided by engineer. + swipe action Clear conversation @@ -1901,7 +1907,8 @@ This is your own one-time link! Delete 删除 - chat item action + chat item action + swipe action Delete %lld messages of members? @@ -2102,10 +2109,6 @@ This is your own one-time link! 已删除于:%@ copied message info - - Deleted chats - No comment provided by engineer. - Deletion errors No comment provided by engineer. @@ -2962,7 +2965,7 @@ This is your own one-time link! Favorite 最喜欢 - No comment provided by engineer. + swipe action File error @@ -3718,7 +3721,7 @@ Error: %2$@ Join 加入 - No comment provided by engineer. + swipe action Join group @@ -3805,7 +3808,7 @@ This is your link for group %@! Leave 离开 - No comment provided by engineer. + swipe action Leave group @@ -4182,7 +4185,7 @@ This is your link for group %@! Mute 静音 - No comment provided by engineer. + swipe action Muted when inactive! @@ -4192,7 +4195,7 @@ This is your link for group %@! Name 名称 - No comment provided by engineer. + swipe action Network & servers @@ -4403,10 +4406,6 @@ This is your link for group %@! 旧数据库存档 No comment provided by engineer. - - One-hand UI - No comment provided by engineer. - One-time invitation link 一次性邀请链接 @@ -4954,6 +4953,10 @@ Enable in *Network & servers* settings. 评价此应用程序 No comment provided by engineer. + + Reachable chat toolbar + No comment provided by engineer. + Reachable chat toolbar 👋 No comment provided by engineer. @@ -4966,7 +4969,7 @@ Enable in *Network & servers* settings. Read 已读 - No comment provided by engineer. + swipe action Read more @@ -5116,7 +5119,8 @@ Enable in *Network & servers* settings. Reject 拒绝 - reject incoming call via notification + reject incoming call via notification + swipe action Reject (sender NOT notified) @@ -5217,6 +5221,10 @@ Enable in *Network & servers* settings. 重置 No comment provided by engineer. + + Reset all hints + No comment provided by engineer. + Reset all statistics No comment provided by engineer. @@ -6501,6 +6509,10 @@ You will be prompted to complete authentication before this feature is enabled.< 要与您的联系人验证端到端加密,请比较(或扫描)您设备上的代码。 No comment provided by engineer. + + Toggle chat list: + No comment provided by engineer. + Toggle incognito when connecting. 在连接时切换隐身模式。 @@ -6581,7 +6593,7 @@ You will be prompted to complete authentication before this feature is enabled.< Unfav. 取消最喜欢 - No comment provided by engineer. + swipe action Unhide @@ -6657,12 +6669,12 @@ To connect, please ask your contact to create another connection link and check Unmute 取消静音 - No comment provided by engineer. + swipe action Unread 未读 - No comment provided by engineer. + swipe action Up to 100 last messages are sent to new members. @@ -7131,6 +7143,10 @@ Repeat join request? 您可以从锁屏上接听电话,无需设备和应用程序的认证。 No comment provided by engineer. + + You can change it in Appearance settings. + No comment provided by engineer. + You can create it later 您可以以后创建它 diff --git a/apps/ios/SimpleX.xcodeproj/project.pbxproj b/apps/ios/SimpleX.xcodeproj/project.pbxproj index 7a205455dd..85e2390fc1 100644 --- a/apps/ios/SimpleX.xcodeproj/project.pbxproj +++ b/apps/ios/SimpleX.xcodeproj/project.pbxproj @@ -205,6 +205,7 @@ CE3097FB2C4C0C9F00180898 /* ErrorAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE3097FA2C4C0C9F00180898 /* ErrorAlert.swift */; }; CE38A29A2C3FCA54005ED185 /* ImageUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CBD2859295711D700EC2CF4 /* ImageUtils.swift */; }; CE38A29C2C3FCD72005ED185 /* SwiftyGif in Frameworks */ = {isa = PBXBuildFile; productRef = CE38A29B2C3FCD72005ED185 /* SwiftyGif */; }; + CE75480A2C622630009579B7 /* SwipeLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE7548092C622630009579B7 /* SwipeLabel.swift */; }; CE984D4B2C36C5D500E3AEFF /* ChatItemClipShape.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE984D4A2C36C5D500E3AEFF /* ChatItemClipShape.swift */; }; CEDE70222C48FD9500233B1F /* SEChatState.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEDE70212C48FD9500233B1F /* SEChatState.swift */; }; CEE723AA2C3BD3D70009AE93 /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEE723A92C3BD3D70009AE93 /* ShareViewController.swift */; }; @@ -219,12 +220,13 @@ D77B92DC2952372200A5A1CC /* SwiftyGif in Frameworks */ = {isa = PBXBuildFile; productRef = D77B92DB2952372200A5A1CC /* SwiftyGif */; }; D7F0E33929964E7E0068AF69 /* LZString in Frameworks */ = {isa = PBXBuildFile; productRef = D7F0E33829964E7E0068AF69 /* LZString */; }; E50581062C3DDD9D009C3F71 /* Yams in Frameworks */ = {isa = PBXBuildFile; productRef = E50581052C3DDD9D009C3F71 /* Yams */; }; + E51CC1E62C62085600DB91FE /* OneHandUICard.swift in Sources */ = {isa = PBXBuildFile; fileRef = E51CC1E52C62085600DB91FE /* OneHandUICard.swift */; }; + E51CC1F62C62BAB900DB91FE /* libHSsimplex-chat-6.0.0.4-3xUPNxPQ4Yz9H0nVfm7Usu-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E51CC1F12C62BAB900DB91FE /* libHSsimplex-chat-6.0.0.4-3xUPNxPQ4Yz9H0nVfm7Usu-ghc9.6.3.a */; }; + E51CC1F72C62BAB900DB91FE /* libHSsimplex-chat-6.0.0.4-3xUPNxPQ4Yz9H0nVfm7Usu.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E51CC1F22C62BAB900DB91FE /* libHSsimplex-chat-6.0.0.4-3xUPNxPQ4Yz9H0nVfm7Usu.a */; }; + E51CC1F82C62BAB900DB91FE /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E51CC1F32C62BAB900DB91FE /* libgmp.a */; }; + E51CC1F92C62BAB900DB91FE /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E51CC1F42C62BAB900DB91FE /* libgmpxx.a */; }; + E51CC1FA2C62BAB900DB91FE /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E51CC1F52C62BAB900DB91FE /* libffi.a */; }; E5DCF8DB2C56FAC1007928CC /* SimpleXChat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE2BA682845308900EC33A6 /* SimpleXChat.framework */; }; - E5DCF8E12C5847EB007928CC /* libHSsimplex-chat-6.0.0.3-5yF58NJ20MV4vZ7jQKFAxB.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E5DCF8DC2C5847EB007928CC /* libHSsimplex-chat-6.0.0.3-5yF58NJ20MV4vZ7jQKFAxB.a */; }; - E5DCF8E22C5847EB007928CC /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E5DCF8DD2C5847EB007928CC /* libgmp.a */; }; - E5DCF8E32C5847EB007928CC /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E5DCF8DE2C5847EB007928CC /* libgmpxx.a */; }; - E5DCF8E42C5847EB007928CC /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E5DCF8DF2C5847EB007928CC /* libffi.a */; }; - E5DCF8E52C5847EB007928CC /* libHSsimplex-chat-6.0.0.3-5yF58NJ20MV4vZ7jQKFAxB-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E5DCF8E02C5847EB007928CC /* libHSsimplex-chat-6.0.0.3-5yF58NJ20MV4vZ7jQKFAxB-ghc9.6.3.a */; }; E5DCF9712C590272007928CC /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = E5DCF96F2C590272007928CC /* Localizable.strings */; }; E5DCF9842C5902CE007928CC /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = E5DCF9822C5902CE007928CC /* Localizable.strings */; }; E5DCF9982C5906FF007928CC /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = E5DCF9962C5906FF007928CC /* InfoPlist.strings */; }; @@ -546,6 +548,7 @@ CE1EB0E32C459A660099D896 /* ShareAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareAPI.swift; sourceTree = ""; }; CE2AD9CD2C452A4D00E844E3 /* ChatUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatUtils.swift; sourceTree = ""; }; CE3097FA2C4C0C9F00180898 /* ErrorAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorAlert.swift; sourceTree = ""; }; + CE7548092C622630009579B7 /* SwipeLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwipeLabel.swift; sourceTree = ""; }; CE984D4A2C36C5D500E3AEFF /* ChatItemClipShape.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatItemClipShape.swift; sourceTree = ""; }; CEDE70212C48FD9500233B1F /* SEChatState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SEChatState.swift; sourceTree = ""; }; CEE723A72C3BD3D70009AE93 /* SimpleX SE.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "SimpleX SE.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -559,11 +562,12 @@ 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; }; D7AA2C3429A936B400737B40 /* MediaEncryption.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; name = MediaEncryption.playground; path = Shared/MediaEncryption.playground; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; - E5DCF8DC2C5847EB007928CC /* libHSsimplex-chat-6.0.0.3-5yF58NJ20MV4vZ7jQKFAxB.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.0.0.3-5yF58NJ20MV4vZ7jQKFAxB.a"; sourceTree = ""; }; - E5DCF8DD2C5847EB007928CC /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = ""; }; - E5DCF8DE2C5847EB007928CC /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = ""; }; - E5DCF8DF2C5847EB007928CC /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = ""; }; - E5DCF8E02C5847EB007928CC /* libHSsimplex-chat-6.0.0.3-5yF58NJ20MV4vZ7jQKFAxB-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.0.0.3-5yF58NJ20MV4vZ7jQKFAxB-ghc9.6.3.a"; sourceTree = ""; }; + E51CC1E52C62085600DB91FE /* OneHandUICard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OneHandUICard.swift; sourceTree = ""; }; + E51CC1F12C62BAB900DB91FE /* libHSsimplex-chat-6.0.0.4-3xUPNxPQ4Yz9H0nVfm7Usu-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.0.0.4-3xUPNxPQ4Yz9H0nVfm7Usu-ghc9.6.3.a"; sourceTree = ""; }; + E51CC1F22C62BAB900DB91FE /* libHSsimplex-chat-6.0.0.4-3xUPNxPQ4Yz9H0nVfm7Usu.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.0.0.4-3xUPNxPQ4Yz9H0nVfm7Usu.a"; sourceTree = ""; }; + E51CC1F32C62BAB900DB91FE /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = ""; }; + E51CC1F42C62BAB900DB91FE /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = ""; }; + E51CC1F52C62BAB900DB91FE /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = ""; }; E5DCF9702C590272007928CC /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; E5DCF9722C590274007928CC /* bg */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bg; path = bg.lproj/Localizable.strings; sourceTree = ""; }; E5DCF9732C590275007928CC /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = ""; }; @@ -654,15 +658,15 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + E51CC1F72C62BAB900DB91FE /* libHSsimplex-chat-6.0.0.4-3xUPNxPQ4Yz9H0nVfm7Usu.a in Frameworks */, + E51CC1F82C62BAB900DB91FE /* libgmp.a in Frameworks */, 5CE2BA93284534B000EC33A6 /* libiconv.tbd in Frameworks */, 5CE2BA94284534BB00EC33A6 /* libz.tbd in Frameworks */, + E51CC1F92C62BAB900DB91FE /* libgmpxx.a in Frameworks */, E50581062C3DDD9D009C3F71 /* Yams in Frameworks */, - E5DCF8E52C5847EB007928CC /* libHSsimplex-chat-6.0.0.3-5yF58NJ20MV4vZ7jQKFAxB-ghc9.6.3.a in Frameworks */, - E5DCF8E42C5847EB007928CC /* libffi.a in Frameworks */, - E5DCF8E12C5847EB007928CC /* libHSsimplex-chat-6.0.0.3-5yF58NJ20MV4vZ7jQKFAxB.a in Frameworks */, - E5DCF8E22C5847EB007928CC /* libgmp.a in Frameworks */, CE38A29C2C3FCD72005ED185 /* SwiftyGif in Frameworks */, - E5DCF8E32C5847EB007928CC /* libgmpxx.a in Frameworks */, + E51CC1FA2C62BAB900DB91FE /* libffi.a in Frameworks */, + E51CC1F62C62BAB900DB91FE /* libHSsimplex-chat-6.0.0.4-3xUPNxPQ4Yz9H0nVfm7Usu-ghc9.6.3.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -739,11 +743,11 @@ 5C764E5C279C70B7000C6508 /* Libraries */ = { isa = PBXGroup; children = ( - E5DCF8DF2C5847EB007928CC /* libffi.a */, - E5DCF8DD2C5847EB007928CC /* libgmp.a */, - E5DCF8DE2C5847EB007928CC /* libgmpxx.a */, - E5DCF8E02C5847EB007928CC /* libHSsimplex-chat-6.0.0.3-5yF58NJ20MV4vZ7jQKFAxB-ghc9.6.3.a */, - E5DCF8DC2C5847EB007928CC /* libHSsimplex-chat-6.0.0.3-5yF58NJ20MV4vZ7jQKFAxB.a */, + E51CC1F52C62BAB900DB91FE /* libffi.a */, + E51CC1F32C62BAB900DB91FE /* libgmp.a */, + E51CC1F42C62BAB900DB91FE /* libgmpxx.a */, + E51CC1F12C62BAB900DB91FE /* libHSsimplex-chat-6.0.0.4-3xUPNxPQ4Yz9H0nVfm7Usu-ghc9.6.3.a */, + E51CC1F22C62BAB900DB91FE /* libHSsimplex-chat-6.0.0.4-3xUPNxPQ4Yz9H0nVfm7Usu.a */, ); path = Libraries; sourceTree = ""; @@ -799,6 +803,7 @@ 8C74C3ED2C1B942300039E77 /* ChatWallpaper.swift */, 8C9BC2642C240D5100875A27 /* ThemeModeEditor.swift */, CE984D4A2C36C5D500E3AEFF /* ChatItemClipShape.swift */, + CE7548092C622630009579B7 /* SwipeLabel.swift */, ); path = Helpers; sourceTree = ""; @@ -945,6 +950,7 @@ 5C10D88728EED12E00E58BF0 /* ContactConnectionInfo.swift */, 18415835CBD939A9ABDC108A /* UserPicker.swift */, 64EEB0F62C353F1C00972D62 /* ServersSummaryView.swift */, + E51CC1E52C62085600DB91FE /* OneHandUICard.swift */, ); path = ChatList; sourceTree = ""; @@ -1371,6 +1377,7 @@ 5C93292F29239A170090FFF9 /* ProtocolServersView.swift in Sources */, 5CB924D727A8563F00ACCCDD /* SettingsView.swift in Sources */, 5CEACCE327DE9246000BD591 /* ComposeView.swift in Sources */, + E51CC1E62C62085600DB91FE /* OneHandUICard.swift in Sources */, 5C65DAF929D0CC20003CEE45 /* DeveloperView.swift in Sources */, 5C36027327F47AD5009F19D9 /* AppDelegate.swift in Sources */, 5CB924E127A867BA00ACCCDD /* UserProfile.swift in Sources */, @@ -1453,6 +1460,7 @@ 64D0C2C229FA57AB00B38D5F /* UserAddressLearnMore.swift in Sources */, 8CE848A32C5A0FA000D5C7C8 /* SelectableChatItemToolbars.swift in Sources */, 64466DCC29FFE3E800E3D48D /* MailView.swift in Sources */, + CE75480A2C622630009579B7 /* SwipeLabel.swift in Sources */, 5C971E2127AEBF8300C8A3CE /* ChatInfoImage.swift in Sources */, 5C55A921283CCCB700C4E99E /* IncomingCallView.swift in Sources */, 6454036F2822A9750090DDFF /* ComposeFileView.swift in Sources */, @@ -1888,7 +1896,7 @@ CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES; CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 229; + CURRENT_PROJECT_VERSION = 230; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = 5NN7GUYB6T; ENABLE_BITCODE = NO; @@ -1937,7 +1945,7 @@ CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES; CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 229; + CURRENT_PROJECT_VERSION = 230; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = 5NN7GUYB6T; ENABLE_BITCODE = NO; @@ -1978,11 +1986,11 @@ buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 230; DEVELOPMENT_TEAM = 5NN7GUYB6T; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 15.0; - MARKETING_VERSION = 1.0; + MARKETING_VERSION = 6.0; PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.Tests-iOS"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; @@ -1998,11 +2006,11 @@ buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 230; DEVELOPMENT_TEAM = 5NN7GUYB6T; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 15.0; - MARKETING_VERSION = 1.0; + MARKETING_VERSION = 6.0; PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.Tests-iOS"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; @@ -2023,7 +2031,7 @@ CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 229; + CURRENT_PROJECT_VERSION = 230; DEVELOPMENT_TEAM = 5NN7GUYB6T; ENABLE_BITCODE = NO; GCC_OPTIMIZATION_LEVEL = s; @@ -2060,7 +2068,7 @@ CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 229; + CURRENT_PROJECT_VERSION = 230; DEVELOPMENT_TEAM = 5NN7GUYB6T; ENABLE_BITCODE = NO; ENABLE_CODE_COVERAGE = NO; @@ -2097,7 +2105,7 @@ CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES; CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 229; + CURRENT_PROJECT_VERSION = 230; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5NN7GUYB6T; DYLIB_COMPATIBILITY_VERSION = 1; @@ -2148,7 +2156,7 @@ CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES; CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 229; + CURRENT_PROJECT_VERSION = 230; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5NN7GUYB6T; DYLIB_COMPATIBILITY_VERSION = 1; @@ -2199,7 +2207,7 @@ CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CODE_SIGN_ENTITLEMENTS = "SimpleX SE/SimpleX SE.entitlements"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 230; DEVELOPMENT_TEAM = 5NN7GUYB6T; ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu17; @@ -2214,7 +2222,7 @@ "@executable_path/../../Frameworks", ); LOCALIZATION_PREFERS_STRING_CATALOGS = YES; - MARKETING_VERSION = 1.0; + MARKETING_VERSION = 6.0; PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-SE"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; @@ -2233,7 +2241,7 @@ CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CODE_SIGN_ENTITLEMENTS = "SimpleX SE/SimpleX SE.entitlements"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 230; DEVELOPMENT_TEAM = 5NN7GUYB6T; ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu17; @@ -2248,7 +2256,7 @@ "@executable_path/../../Frameworks", ); LOCALIZATION_PREFERS_STRING_CATALOGS = YES; - MARKETING_VERSION = 1.0; + MARKETING_VERSION = 6.0; PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-SE"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; diff --git a/apps/ios/SimpleXChat/APITypes.swift b/apps/ios/SimpleXChat/APITypes.swift index 7fb89be92e..fc315dabf0 100644 --- a/apps/ios/SimpleXChat/APITypes.swift +++ b/apps/ios/SimpleXChat/APITypes.swift @@ -1933,7 +1933,7 @@ public enum DatabaseError: Decodable, Hashable { public enum SQLiteError: Decodable, Hashable { case errorNotADatabase - case error(String) + case error(dbError: String) } public enum AgentErrorType: Decodable, Hashable { diff --git a/apps/ios/SimpleXChat/AppGroup.swift b/apps/ios/SimpleXChat/AppGroup.swift index 933842e0cb..40b9deaef5 100644 --- a/apps/ios/SimpleXChat/AppGroup.swift +++ b/apps/ios/SimpleXChat/AppGroup.swift @@ -55,6 +55,7 @@ public let GROUP_DEFAULT_INITIAL_RANDOM_DB_PASSPHRASE = "initialRandomDBPassphra public let GROUP_DEFAULT_CONFIRM_DB_UPGRADES = "confirmDBUpgrades" public let GROUP_DEFAULT_CALL_KIT_ENABLED = "callKitEnabled" public let GROUP_DEFAULT_PQ_EXPERIMENTAL_ENABLED = "pqExperimentalEnabled" // no longer used +public let GROUP_DEFAULT_ONE_HAND_UI = "oneHandUI" public let APP_GROUP_NAME = "group.chat.simplex.app" @@ -81,7 +82,7 @@ public func registerGroupDefaults() { GROUP_DEFAULT_INCOGNITO: false, GROUP_DEFAULT_STORE_DB_PASSPHRASE: true, GROUP_DEFAULT_INITIAL_RANDOM_DB_PASSPHRASE: false, - GROUP_DEFAULT_PERFORM_LA: true, + GROUP_DEFAULT_PERFORM_LA: false, GROUP_DEFAULT_ALLOW_SHARE_EXTENSION: false, GROUP_DEFAULT_PRIVACY_LINK_PREVIEWS: false, GROUP_DEFAULT_PRIVACY_ACCEPT_IMAGES: true, @@ -92,6 +93,7 @@ public func registerGroupDefaults() { GROUP_DEFAULT_CONFIRM_DB_UPGRADES: false, GROUP_DEFAULT_CALL_KIT_ENABLED: true, GROUP_DEFAULT_PQ_EXPERIMENTAL_ENABLED: false, + GROUP_DEFAULT_ONE_HAND_UI: true ]) } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt index 4211ebd4b7..19c8b11ca5 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt @@ -19,6 +19,8 @@ import chat.simplex.res.MR import dev.icerock.moko.resources.ImageResource import dev.icerock.moko.resources.StringResource import kotlinx.coroutines.* +import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.internal.ChannelFlow import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import kotlinx.datetime.* @@ -301,9 +303,7 @@ object ChatModel { else chat.chatStats ) - if (i > 0) { - chats.add(index = 0, chats.removeAt(i)) - } + popChatCollector.addChat(chat.remoteHostId, chat.id) } else { addChat(Chat(remoteHostId = rhId, chatInfo = cInfo, chatItems = arrayListOf(cItem))) } @@ -421,6 +421,32 @@ object ChatModel { } } + private val popChatCollector = PopChatCollector() + + class PopChatCollector { + private val subject = MutableSharedFlow() + + init { + withLongRunningApi { + subject + .throttleLatest(2000) + .collect { + withChats { + chats.replaceAll(chats.value.sortedByDescending { it.popTs }) + } + } + } + } + + suspend fun addChat(remoteHostId: Long?, chatId: ChatId) { + val index = getChatIndex(remoteHostId, chatId) + if (index >= 0) { + chats.value[index].popTs = Clock.System.now() + subject.emit(Unit) + } + } + } + fun markChatItemsRead(remoteHostId: Long?, chatInfo: ChatInfo, range: CC.ItemRange? = null, unreadCountAfter: Int? = null) { val cInfo = chatInfo val markedRead = markItemsReadInCurrentChat(chatInfo, range) @@ -671,6 +697,7 @@ object ChatModel { showingInvitation.value = null chatModel.chatItems.clear() chatModel.chatId.value = withId + ModalManager.start.closeModals() ModalManager.end.closeModals() } } @@ -681,6 +708,7 @@ object ChatModel { chatModel.chatItems.clear() chatModel.chatId.value = null // Close NewChatView + ModalManager.start.closeModals() ModalManager.center.closeModals() ModalManager.end.closeModals() } @@ -845,6 +873,9 @@ data class Chat( val chatItems: List, val chatStats: ChatStats = ChatStats() ) { + @Transient + var popTs: Instant? = null + val nextSendGrpInv: Boolean get() = when (chatInfo) { is ChatInfo.Direct -> chatInfo.contact.nextSendGrpInv diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt index 4f193bebd2..967427162b 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt @@ -159,6 +159,7 @@ class AppPreferences { val incognito = mkBoolPreference(SHARED_PREFS_INCOGNITO, false) val liveMessageAlertShown = mkBoolPreference(SHARED_PREFS_LIVE_MESSAGE_ALERT_SHOWN, false) val showHiddenProfilesNotice = mkBoolPreference(SHARED_PREFS_SHOW_HIDDEN_PROFILES_NOTICE, true) + val oneHandUICardShown = mkBoolPreference(SHARED_PREFS_ONE_HAND_UI_CARD_SHOWN, false) val showMuteProfileAlert = mkBoolPreference(SHARED_PREFS_SHOW_MUTE_PROFILE_ALERT, true) val appLanguage = mkStrPreference(SHARED_PREFS_APP_LANGUAGE, null) val appUpdateChannel = mkEnumPreference(SHARED_PREFS_APP_UPDATE_CHANNEL, AppUpdatesChannel.DISABLED) { AppUpdatesChannel.entries.firstOrNull { it.name == this } } @@ -227,6 +228,16 @@ class AppPreferences { val oneHandUI = mkBoolPreference(SHARED_PREFS_ONE_HAND_UI, appPlatform.isAndroid) + val hintPreferences: List, Boolean>> = listOf( + laNoticeShown to false, + oneHandUICardShown to false, + liveMessageAlertShown to false, + showHiddenProfilesNotice to true, + showMuteProfileAlert to true, + showDeleteConversationNotice to true, + showDeleteContactNotice to true, + ) + private fun mkIntPreference(prefName: String, default: Int) = SharedPreference( get = fun() = settings.getInt(prefName, default), @@ -372,6 +383,7 @@ class AppPreferences { private const val SHARED_PREFS_INCOGNITO = "Incognito" private const val SHARED_PREFS_LIVE_MESSAGE_ALERT_SHOWN = "LiveMessageAlertShown" private const val SHARED_PREFS_SHOW_HIDDEN_PROFILES_NOTICE = "ShowHiddenProfilesNotice" + private const val SHARED_PREFS_ONE_HAND_UI_CARD_SHOWN = "OneHandUICardShown" private const val SHARED_PREFS_SHOW_MUTE_PROFILE_ALERT = "ShowMuteProfileAlert" private const val SHARED_PREFS_STORE_DB_PASSPHRASE = "StoreDBPassphrase" private const val SHARED_PREFS_INITIAL_RANDOM_DB_PASSPHRASE = "InitialRandomDBPassphrase" @@ -519,7 +531,10 @@ object ChatController { suspend fun startChatWithTemporaryDatabase(ctrl: ChatCtrl, netCfg: NetCfg): User? { Log.d(TAG, "startChatWithTemporaryDatabase") val migrationActiveUser = apiGetActiveUser(null, ctrl) ?: apiCreateActiveUser(null, Profile(displayName = "Temp", fullName = ""), ctrl = ctrl) - apiSetNetworkConfig(netCfg, ctrl) + if (!apiSetNetworkConfig(netCfg, ctrl)) { + Log.e(TAG, "Error setting network config, stopping migration") + return null + } apiSetAppFilePaths( getMigrationTempFilesDirectory().absolutePath, getMigrationTempFilesDirectory().absolutePath, @@ -5759,7 +5774,7 @@ sealed class DatabaseError { @Serializable sealed class SQLiteError { @Serializable @SerialName("errorNotADatabase") object ErrorNotADatabase: SQLiteError() - @Serializable @SerialName("error") class Error(val error: String): SQLiteError() + @Serializable @SerialName("error") class Error(val dbError: String): SQLiteError() } @Serializable diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatInfoView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatInfoView.kt index 7c694e00b1..5d9b33d416 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatInfoView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatInfoView.kt @@ -31,8 +31,7 @@ import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.intl.Locale import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp +import androidx.compose.ui.unit.* import chat.simplex.common.model.* import chat.simplex.common.model.ChatController.appPrefs import chat.simplex.common.model.ChatModel.controller @@ -545,20 +544,22 @@ fun ChatInfoLayout( SectionSpacer() - Row( - Modifier - .fillMaxWidth() - .padding(horizontal = DEFAULT_PADDING), - horizontalArrangement = Arrangement.Center, - verticalAlignment = Alignment.CenterVertically + Box( + Modifier.fillMaxWidth(), + contentAlignment = Alignment.Center ) { - SearchButton(chat, contact, close, onSearchClicked) - Spacer(Modifier.weight(1f)) - AudioCallButton(chat, contact) - Spacer(Modifier.weight(1f)) - VideoButton(chat, contact) - Spacer(Modifier.weight(1f)) - MuteButton(chat, contact) + Row( + Modifier + .widthIn(max = 460.dp) + .padding(horizontal = DEFAULT_PADDING), + horizontalArrangement = Arrangement.SpaceEvenly, + verticalAlignment = Alignment.CenterVertically + ) { + SearchButton(modifier = Modifier.fillMaxWidth(0.25f), chat, contact, close, onSearchClicked) + AudioCallButton(modifier = Modifier.fillMaxWidth(0.33f), chat, contact) + VideoButton(modifier = Modifier.fillMaxWidth(0.5f), chat, contact) + MuteButton(modifier = Modifier.fillMaxWidth(1f), chat, contact) + } } SectionSpacer() @@ -779,9 +780,16 @@ fun LocalAliasEditor( } @Composable -fun SearchButton(chat: Chat, contact: Contact, close: () -> Unit, onSearchClicked: () -> Unit) { +fun SearchButton( + modifier: Modifier, + chat: Chat, + contact: Contact, + close: () -> Unit, + onSearchClicked: () -> Unit +) { val disabled = !contact.ready || chat.chatItems.isEmpty() InfoViewActionButton( + modifier = modifier, icon = painterResource(MR.images.ic_search), title = generalGetString(MR.strings.info_view_search_button), disabled = disabled, @@ -796,11 +804,16 @@ fun SearchButton(chat: Chat, contact: Contact, close: () -> Unit, onSearchClicke } @Composable -fun MuteButton(chat: Chat, contact: Contact) { +fun MuteButton( + modifier: Modifier, + chat: Chat, + contact: Contact +) { val ntfsEnabled = remember { mutableStateOf(chat.chatInfo.ntfsEnabled) } val disabled = !contact.ready || !contact.active InfoViewActionButton( + modifier = modifier, icon = if (ntfsEnabled.value) painterResource(MR.images.ic_notifications_off) else painterResource(MR.images.ic_notifications), title = if (ntfsEnabled.value) stringResource(MR.strings.mute_chat) else stringResource(MR.strings.unmute_chat), disabled = disabled, @@ -812,8 +825,13 @@ fun MuteButton(chat: Chat, contact: Contact) { } @Composable -fun AudioCallButton(chat: Chat, contact: Contact) { +fun AudioCallButton( + modifier: Modifier, + chat: Chat, + contact: Contact +) { CallButton( + modifier = modifier, chat, contact, icon = painterResource(MR.images.ic_call), @@ -823,8 +841,13 @@ fun AudioCallButton(chat: Chat, contact: Contact) { } @Composable -fun VideoButton(chat: Chat, contact: Contact) { +fun VideoButton( + modifier: Modifier, + chat: Chat, + contact: Contact +) { CallButton( + modifier = modifier, chat, contact, icon = painterResource(MR.images.ic_videocam), @@ -834,7 +857,14 @@ fun VideoButton(chat: Chat, contact: Contact) { } @Composable -fun CallButton(chat: Chat, contact: Contact, icon: Painter, title: String, mediaType: CallMediaType) { +fun CallButton( + modifier: Modifier, + chat: Chat, + contact: Contact, + icon: Painter, + title: String, + mediaType: CallMediaType +) { val canCall = contact.ready && contact.active && contact.mergedPreferences.calls.enabled.forUser && chatModel.activeCall.value == null val needToAllowCallsToContact = remember(chat.chatInfo) { chat.chatInfo is ChatInfo.Direct && with(chat.chatInfo.contact.mergedPreferences.calls) { @@ -845,6 +875,7 @@ fun CallButton(chat: Chat, contact: Contact, icon: Painter, title: String, media val allowedCallsByPrefs = remember(chat.chatInfo) { chat.chatInfo.featureEnabled(ChatFeature.Calls) } InfoViewActionButton( + modifier = modifier, icon = icon, title = title, disabled = chatModel.activeCall.value != null, @@ -907,42 +938,52 @@ private fun showCallsProhibitedAlert() { ) } -// for ChatInfoView (it has most buttons - 4) we use Spacer(Modifier.weight(1f)) to fit, -// for GroupChat And GroupMemberInfoViews (2 to 3 buttons) we use this as approximately equal to spacing in ChatInfoView -val INFO_VIEW_BUTTONS_PADDING = 36.dp - @Composable -fun InfoViewActionButton(icon: Painter, title: String, disabled: Boolean, disabledLook: Boolean, onClick: () -> Unit) { - Column( - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center - ) { - IconButton( - onClick = onClick, - enabled = !disabled +fun InfoViewActionButton( + modifier: Modifier, + icon: Painter, + title: String, + disabled: Boolean, + disabledLook: Boolean, + onClick: () -> Unit +) { + Box(modifier) { + Column( + Modifier + .fillMaxWidth() + .padding(8.dp), + horizontalAlignment = Alignment.CenterHorizontally ) { - Box( - modifier = Modifier - .background( - if (disabledLook) MaterialTheme.colors.secondaryVariant else MaterialTheme.colors.primary, - shape = CircleShape - ) - .padding(16.dp) + IconButton( + onClick = onClick, + enabled = !disabled ) { - Icon( - icon, - contentDescription = null, - Modifier.size(24.dp * fontSizeSqrtMultiplier), - tint = if (disabledLook) MaterialTheme.colors.secondary else MaterialTheme.colors.onPrimary - ) + Box( + Modifier + .size(56.dp) + .background( + if (disabledLook) MaterialTheme.colors.secondaryVariant else MaterialTheme.colors.primary, + shape = CircleShape + ), + contentAlignment = Alignment.Center + ) { + Icon( + icon, + contentDescription = null, + Modifier.size(24.dp * fontSizeSqrtMultiplier), + tint = if (disabledLook) MaterialTheme.colors.secondary else MaterialTheme.colors.onPrimary + ) + } } + Text( + title.capitalize(Locale.current), + Modifier.padding(top = DEFAULT_SPACE_AFTER_ICON), + style = MaterialTheme.typography.subtitle2.copy(fontWeight = FontWeight.Normal, fontSize = 12.sp), + color = MaterialTheme.colors.secondary, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) } - Text( - title.capitalize(Locale.current), - style = MaterialTheme.typography.subtitle2.copy(fontWeight = FontWeight.Normal), - color = MaterialTheme.colors.secondary, - modifier = Modifier.padding(top = DEFAULT_SPACE_AFTER_ICON) - ) } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupChatInfoView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupChatInfoView.kt index 5d69972886..97b6cb91a7 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupChatInfoView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupChatInfoView.kt @@ -23,8 +23,7 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp +import androidx.compose.ui.unit.* import chat.simplex.common.model.* import chat.simplex.common.model.ChatModel.withChats import chat.simplex.common.ui.theme.* @@ -184,10 +183,17 @@ private fun removeMemberAlert(rhId: Long?, groupInfo: GroupInfo, mem: GroupMembe } @Composable -fun SearchButton(chat: Chat, group: GroupInfo, close: () -> Unit, onSearchClicked: () -> Unit) { +fun SearchButton( + modifier: Modifier, + chat: Chat, + group: GroupInfo, + close: () -> Unit, + onSearchClicked: () -> Unit +) { val disabled = !group.ready || chat.chatItems.isEmpty() InfoViewActionButton( + modifier = modifier, icon = painterResource(MR.images.ic_search), title = generalGetString(MR.strings.info_view_search_button), disabled = disabled, @@ -202,10 +208,15 @@ fun SearchButton(chat: Chat, group: GroupInfo, close: () -> Unit, onSearchClicke } @Composable -fun MuteButton(chat: Chat, groupInfo: GroupInfo) { +fun MuteButton( + modifier: Modifier, + chat: Chat, + groupInfo: GroupInfo +) { val ntfsEnabled = remember { mutableStateOf(chat.chatInfo.ntfsEnabled) } InfoViewActionButton( + modifier = modifier, icon = if (ntfsEnabled.value) painterResource(MR.images.ic_notifications_off) else painterResource(MR.images.ic_notifications), title = if (ntfsEnabled.value) stringResource(MR.strings.mute_chat) else stringResource(MR.strings.unmute_chat), disabled = !groupInfo.ready, @@ -217,8 +228,13 @@ fun MuteButton(chat: Chat, groupInfo: GroupInfo) { } @Composable -fun AddGroupMembersButton(chat: Chat, groupInfo: GroupInfo) { +fun AddGroupMembersButton( + modifier: Modifier, + chat: Chat, + groupInfo: GroupInfo +) { InfoViewActionButton( + modifier = modifier, icon = if (groupInfo.incognito) painterResource(MR.images.ic_add_link) else painterResource(MR.images.ic_person_add_500), title = stringResource(MR.strings.action_button_add_members), disabled = !groupInfo.ready, @@ -278,20 +294,26 @@ fun GroupChatInfoLayout( } SectionSpacer() - Row( - Modifier - .fillMaxWidth() - .padding(horizontal = DEFAULT_PADDING), - horizontalArrangement = Arrangement.Center, - verticalAlignment = Alignment.CenterVertically + Box( + Modifier.fillMaxWidth(), + contentAlignment = Alignment.Center ) { - SearchButton(chat, groupInfo, close, onSearchClicked) - if (groupInfo.canAddMembers) { - Spacer(Modifier.width(INFO_VIEW_BUTTONS_PADDING)) - AddGroupMembersButton(chat, groupInfo) + Row( + Modifier + .widthIn(max = if (groupInfo.canAddMembers) 320.dp else 230.dp) + .padding(horizontal = DEFAULT_PADDING), + horizontalArrangement = Arrangement.SpaceEvenly, + verticalAlignment = Alignment.CenterVertically + ) { + if (groupInfo.canAddMembers) { + SearchButton(modifier = Modifier.fillMaxWidth(0.33f), chat, groupInfo, close, onSearchClicked) + AddGroupMembersButton(modifier = Modifier.fillMaxWidth(0.5f), chat, groupInfo) + MuteButton(modifier = Modifier.fillMaxWidth(1f), chat, groupInfo) + } else { + SearchButton(modifier = Modifier.fillMaxWidth(0.5f), chat, groupInfo, close, onSearchClicked) + MuteButton(modifier = Modifier.fillMaxWidth(1f), chat, groupInfo) + } } - Spacer(Modifier.width(INFO_VIEW_BUTTONS_PADDING)) - MuteButton(chat, groupInfo) } SectionSpacer() diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupMemberInfoView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupMemberInfoView.kt index 4e84b1b651..f814fb2eb8 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupMemberInfoView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupMemberInfoView.kt @@ -327,49 +327,49 @@ fun GroupMemberInfoLayout( val contactId = member.memberContactId - Row( - Modifier - .fillMaxWidth() - .padding(horizontal = DEFAULT_PADDING), - horizontalArrangement = Arrangement.Center, - verticalAlignment = Alignment.CenterVertically + Box( + Modifier.fillMaxWidth(), + contentAlignment = Alignment.Center ) { - val knownChat = if (contactId != null) knownDirectChat(contactId) else null - if (knownChat != null) { - val (chat, contact) = knownChat - OpenChatButton(onClick = { openDirectChat(contact.contactId) }) - Spacer(Modifier.width(INFO_VIEW_BUTTONS_PADDING)) - AudioCallButton(chat, contact) - Spacer(Modifier.width(INFO_VIEW_BUTTONS_PADDING)) - VideoButton(chat, contact) - } else if (groupInfo.fullGroupPreferences.directMessages.on(groupInfo.membership)) { - if (contactId != null) { - OpenChatButton(onClick = { openDirectChat(contactId) }) // legacy - only relevant for direct contacts created when joining group - } else { - OpenChatButton(onClick = { createMemberContact() }) + Row( + Modifier + .widthIn(max = 320.dp) + .padding(horizontal = DEFAULT_PADDING), + horizontalArrangement = Arrangement.SpaceEvenly, + verticalAlignment = Alignment.CenterVertically + ) { + val knownChat = if (contactId != null) knownDirectChat(contactId) else null + if (knownChat != null) { + val (chat, contact) = knownChat + OpenChatButton(modifier = Modifier.fillMaxWidth(0.33f), onClick = { openDirectChat(contact.contactId) }) + AudioCallButton(modifier = Modifier.fillMaxWidth(0.5f), chat, contact) + VideoButton(modifier = Modifier.fillMaxWidth(1f), chat, contact) + } else if (groupInfo.fullGroupPreferences.directMessages.on(groupInfo.membership)) { + if (contactId != null) { + OpenChatButton(modifier = Modifier.fillMaxWidth(0.33f), onClick = { openDirectChat(contactId) }) // legacy - only relevant for direct contacts created when joining group + } else { + OpenChatButton(modifier = Modifier.fillMaxWidth(0.33f), onClick = { createMemberContact() }) + } + InfoViewActionButton(modifier = Modifier.fillMaxWidth(0.5f), painterResource(MR.images.ic_call), generalGetString(MR.strings.info_view_call_button), disabled = false, disabledLook = true, onClick = { + showSendMessageToEnableCallsAlert() + }) + InfoViewActionButton(modifier = Modifier.fillMaxWidth(1f), painterResource(MR.images.ic_videocam), generalGetString(MR.strings.info_view_video_button), disabled = false, disabledLook = true, onClick = { + showSendMessageToEnableCallsAlert() + }) + } else { // no known contact chat && directMessages are off + InfoViewActionButton(modifier = Modifier.fillMaxWidth(0.33f), painterResource(MR.images.ic_chat_bubble), generalGetString(MR.strings.info_view_message_button), disabled = false, disabledLook = true, onClick = { + showDirectMessagesProhibitedAlert(generalGetString(MR.strings.cant_send_message_to_member_alert_title)) + }) + InfoViewActionButton(modifier = Modifier.fillMaxWidth(0.5f), painterResource(MR.images.ic_call), generalGetString(MR.strings.info_view_call_button), disabled = false, disabledLook = true, onClick = { + showDirectMessagesProhibitedAlert(generalGetString(MR.strings.cant_call_member_alert_title)) + }) + InfoViewActionButton(modifier = Modifier.fillMaxWidth(1f), painterResource(MR.images.ic_videocam), generalGetString(MR.strings.info_view_video_button), disabled = false, disabledLook = true, onClick = { + showDirectMessagesProhibitedAlert(generalGetString(MR.strings.cant_call_member_alert_title)) + }) } - Spacer(Modifier.width(INFO_VIEW_BUTTONS_PADDING)) - InfoViewActionButton(painterResource(MR.images.ic_call), generalGetString(MR.strings.info_view_call_button), disabled = false, disabledLook = true, onClick = { - showSendMessageToEnableCallsAlert() - }) - Spacer(Modifier.width(INFO_VIEW_BUTTONS_PADDING)) - InfoViewActionButton(painterResource(MR.images.ic_videocam), generalGetString(MR.strings.info_view_video_button), disabled = false, disabledLook = true, onClick = { - showSendMessageToEnableCallsAlert() - }) - } else { // no known contact chat && directMessages are off - InfoViewActionButton(painterResource(MR.images.ic_chat_bubble), generalGetString(MR.strings.info_view_message_button), disabled = false, disabledLook = true, onClick = { - showDirectMessagesProhibitedAlert(generalGetString(MR.strings.cant_send_message_to_member_alert_title)) - }) - Spacer(Modifier.width(INFO_VIEW_BUTTONS_PADDING)) - InfoViewActionButton(painterResource(MR.images.ic_call), generalGetString(MR.strings.info_view_call_button), disabled = false, disabledLook = true, onClick = { - showDirectMessagesProhibitedAlert(generalGetString(MR.strings.cant_call_member_alert_title)) - }) - Spacer(Modifier.width(INFO_VIEW_BUTTONS_PADDING)) - InfoViewActionButton(painterResource(MR.images.ic_videocam), generalGetString(MR.strings.info_view_video_button), disabled = false, disabledLook = true, onClick = { - showDirectMessagesProhibitedAlert(generalGetString(MR.strings.cant_call_member_alert_title)) - }) } } + SectionSpacer() if (member.memberActive) { @@ -580,8 +580,12 @@ fun RemoveMemberButton(onClick: () -> Unit) { } @Composable -fun OpenChatButton(onClick: () -> Unit) { +fun OpenChatButton( + modifier: Modifier, + onClick: () -> Unit +) { InfoViewActionButton( + modifier = modifier, icon = painterResource(MR.images.ic_chat_bubble), title = generalGetString(MR.strings.info_view_message_button), disabled = false, diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatListView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatListView.kt index 207f8a4b26..b4e11be1ed 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatListView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatListView.kt @@ -12,6 +12,7 @@ import androidx.compose.runtime.* import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip import androidx.compose.ui.focus.* import androidx.compose.ui.graphics.* import androidx.compose.ui.text.font.FontStyle @@ -30,11 +31,11 @@ import chat.simplex.common.ui.theme.* import chat.simplex.common.views.helpers.* import chat.simplex.common.views.onboarding.WhatsNewView import chat.simplex.common.views.onboarding.shouldShowWhatsNew -import chat.simplex.common.views.usersettings.SettingsView import chat.simplex.common.platform.* import chat.simplex.common.views.call.Call import chat.simplex.common.views.chat.item.CIFileViewScope import chat.simplex.common.views.newchat.* +import chat.simplex.common.views.usersettings.* import chat.simplex.res.MR import kotlinx.coroutines.* import kotlinx.coroutines.flow.MutableStateFlow @@ -70,10 +71,72 @@ private fun showNewChatSheet(oneHandUI: State) { } } +@Composable +fun ToggleChatListCard() { + Column( + modifier = Modifier + .padding(16.dp) + .clip(RoundedCornerShape(18.dp)) + ) { + Box( + modifier = Modifier + .background(MaterialTheme.appColors.sentMessage) + ) { + Box( + modifier = Modifier.fillMaxWidth().matchParentSize().padding(5.dp), + contentAlignment = Alignment.TopEnd + ) { + IconButton( + onClick = { + appPrefs.oneHandUICardShown.set(true) + AlertManager.shared.showAlertMsg( + title = generalGetString(MR.strings.one_hand_ui), + text = generalGetString(MR.strings.one_hand_ui_change_instruction), + ) + } + ) { + Icon( + painterResource(MR.images.ic_close), stringResource(MR.strings.back), tint = MaterialTheme.colors.secondary + ) + } + } + Column( + modifier = Modifier + .padding(horizontal = DEFAULT_PADDING) + .padding(top = DEFAULT_PADDING) + ) { + Row( + horizontalArrangement = Arrangement.Start, + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.fillMaxWidth() + ) { + Text(stringResource(MR.strings.one_hand_ui_card_title), style = MaterialTheme.typography.h3) + } + Row( + Modifier.fillMaxWidth().padding(top = 6.dp, bottom = 12.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Text(stringResource(MR.strings.one_hand_ui), Modifier.weight(10f), style = MaterialTheme.typography.body1) + + Spacer(Modifier.fillMaxWidth().weight(1f)) + + SharedPreferenceToggle( + appPrefs.oneHandUI, + enabled = true, + onChange = { + val c = CurrentColors.value.colors + platform.androidSetStatusAndNavBarColors(c.isLight, c.background, !appPrefs.oneHandUI.get(), appPrefs.oneHandUI.get()) + } + ) + } + } + } + } +} + @Composable fun ChatListView(chatModel: ChatModel, settingsState: SettingsViewState, setPerformLA: (Boolean) -> Unit, stopped: Boolean) { val oneHandUI = remember { appPrefs.oneHandUI.state } - LaunchedEffect(Unit) { if (shouldShowWhatsNew(chatModel)) { delay(1000L) @@ -337,7 +400,7 @@ fun SubscriptionStatusIndicator(click: (() -> Unit)) { val scope = rememberCoroutineScope() suspend fun setSubsTotal() { - if (chatModel.currentUser.value != null) { + if (chatModel.currentUser.value != null && chatModel.controller.hasChatCtrl() && chatModel.chatRunning.value == true) { val r = chatModel.controller.getAgentSubsTotal(chatModel.remoteHostId()) if (r != null) { subs = r.first @@ -547,6 +610,7 @@ private fun ChatList(chatModel: ChatModel, searchText: MutableState chat.remoteHostId to chat.id }) { index, chat -> val nextChatSelected = remember(chat.id, chats) { derivedStateOf { chatModel.chatId.value != null && chats.getOrNull(index + 1)?.id == chatModel.chatId.value diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Utils.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Utils.kt index cc4194d0c8..7512cf872e 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Utils.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Utils.kt @@ -16,6 +16,7 @@ import chat.simplex.res.MR import com.charleskorn.kaml.decodeFromStream import dev.icerock.moko.resources.StringResource import kotlinx.coroutines.* +import kotlinx.coroutines.flow.* import kotlinx.serialization.encodeToString import java.io.* import java.net.URI @@ -535,6 +536,13 @@ fun TextUnit.toDp(): Dp { return Dp(value * LocalDensity.current.fontScale) } +fun Flow.throttleLatest(delayMillis: Long): Flow = this + .conflate() + .transform { + emit(it) + delay(delayMillis) + } + @Composable fun DisposableEffectOnGone(always: () -> Unit = {}, whenDispose: () -> Unit = {}, whenGone: () -> Unit) { DisposableEffect(Unit) { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/migration/MigrateFromDevice.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/migration/MigrateFromDevice.kt index c60723ee36..152befb82d 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/migration/MigrateFromDevice.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/migration/MigrateFromDevice.kt @@ -516,8 +516,11 @@ suspend fun initTemporaryDatabase(tempDatabaseFile: File, netCfg: NetCfg): Pair< try { if (ctrl != null) { val user = startChatWithTemporaryDatabase(ctrl, netCfg) - return if (user != null) ctrl to user else null + if (user != null) return ctrl to user + chatCloseStore(ctrl) } + File(tempDatabaseFile.absolutePath + "_chat.db").delete() + File(tempDatabaseFile.absolutePath + "_agent.db").delete() } catch (e: Throwable) { Log.e(TAG, "Error while starting chat in temporary database: ${e.stackTraceToString()}") } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/migration/MigrateToDevice.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/migration/MigrateToDevice.kt index 1a1e8426d4..f8a82d010d 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/migration/MigrateToDevice.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/migration/MigrateToDevice.kt @@ -515,7 +515,9 @@ private fun MutableState.prepareDatabase( withLongRunningApi { val ctrlAndUser = initTemporaryDatabase(tempDatabaseFile, netCfg) if (ctrlAndUser == null) { - state = MigrationToState.DownloadFailed(0, link, archivePath(), netCfg) + // Probably, something wrong with network config or database initialization, let's start from scratch + state = MigrationToState.PasteOrScanLink + MigrationToDeviceState.save(null) return@withLongRunningApi } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatSheet.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatSheet.kt index a1eaf97fe7..dfe47be178 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatSheet.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatSheet.kt @@ -250,7 +250,6 @@ private fun NewChatSheetLayout( icon = it.first, text = it.second, click = it.third, - extraPadding = true, ) } } @@ -283,7 +282,7 @@ private fun NewChatSheetLayout( contentDescription = stringResource(MR.strings.deleted_chats), tint = MaterialTheme.colors.secondary, ) - TextIconSpaced(extraPadding = true) + TextIconSpaced(false) Text(text = stringResource(MR.strings.deleted_chats), color = MaterialTheme.colors.onBackground) } } @@ -330,14 +329,13 @@ private fun NewChatButton( text: String, click: () -> Unit, textColor: Color = Color.Unspecified, - iconColor: Color = MaterialTheme.colors.secondary, - disabled: Boolean = false, - extraPadding: Boolean = false, + iconColor: Color = MaterialTheme.colors.primary, + disabled: Boolean = false ) { SectionItemView(click, disabled = disabled) { Row { Icon(icon, text, tint = if (disabled) MaterialTheme.colors.secondary else iconColor) - TextIconSpaced(extraPadding) + TextIconSpaced(false) Text(text, color = if (disabled) MaterialTheme.colors.secondary else textColor) } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/WhatsNewView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/WhatsNewView.kt index 05cd9cb118..be9acedd89 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/WhatsNewView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/WhatsNewView.kt @@ -30,7 +30,7 @@ fun WhatsNewView(viaSettings: Boolean = false, close: () -> Unit) { val currentVersion = remember { mutableStateOf(versionDescriptions.lastIndex) } @Composable - fun featureDescription(icon: Painter, titleId: StringResource, descrId: StringResource, link: String?) { + fun featureDescription(icon: ImageResource?, titleId: StringResource, descrId: StringResource?, link: String?, subfeatures: List>) { @Composable fun linkButton(link: String) { val uriHandler = LocalUriHandler.current @@ -47,7 +47,7 @@ fun WhatsNewView(viaSettings: Boolean = false, close: () -> Unit) { horizontalArrangement = Arrangement.spacedBy(8.dp), modifier = Modifier.padding(bottom = 4.dp) ) { - Icon(icon, stringResource(titleId), tint = MaterialTheme.colors.secondary) + if (icon != null) Icon(painterResource(icon), stringResource(titleId), tint = MaterialTheme.colors.secondary) Text( generalGetString(titleId), maxLines = 2, @@ -59,7 +59,17 @@ fun WhatsNewView(viaSettings: Boolean = false, close: () -> Unit) { linkButton(link) } } - Text(generalGetString(descrId), fontSize = 15.sp) + if (descrId != null) Text(generalGetString(descrId), fontSize = 15.sp) + for ((si, sd) in subfeatures) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp), + modifier = Modifier.padding(bottom = 4.dp) + ) { + Icon(painterResource(si), stringResource(sd), tint = MaterialTheme.colors.secondary) + Text(generalGetString(sd), fontSize = 15.sp) + } + } } } @@ -116,7 +126,7 @@ fun WhatsNewView(viaSettings: Boolean = false, close: () -> Unit) { v.features.forEach { feature -> if (feature.show) { - featureDescription(painterResource(feature.icon), feature.titleId, feature.descrId, feature.link) + featureDescription(feature.icon, feature.titleId, feature.descrId, feature.link, feature.subfeatures) } } @@ -157,9 +167,10 @@ fun ReadMoreButton(url: String) { } private data class FeatureDescription( - val icon: ImageResource, + val icon: ImageResource?, val titleId: StringResource, - val descrId: StringResource, + val descrId: StringResource?, + var subfeatures: List> = listOf(), val link: String? = null, val show: Boolean = true ) @@ -595,14 +606,24 @@ private val versionDescriptions: List = listOf( post = "https://simplex.chat/blog/20240814-simplex-chat-vision-funding-v6-private-routing-new-user-experience.html", features = listOf( FeatureDescription( - icon = MR.images.ic_settings_ethernet, - titleId = MR.strings.v5_8_private_routing, - descrId = MR.strings.v6_0_private_routing_descr + icon = null, + titleId = MR.strings.v6_0_new_chat_experience, + descrId = null, + subfeatures = listOf( + MR.images.ic_add_link to MR.strings.v6_0_connect_faster_descr, + MR.images.ic_inventory_2 to MR.strings.v6_0_your_contacts_descr, + MR.images.ic_delete to MR.strings.v6_0_delete_many_messages_descr, + MR.images.ic_match_case to MR.strings.v6_0_increase_font_size + ) ), FeatureDescription( - icon = MR.images.ic_id_card, - titleId = MR.strings.v6_0_your_contacts, - descrId = MR.strings.v6_0_your_contacts_descr + icon = null, + titleId = MR.strings.v6_0_new_media_options, + descrId = null, + subfeatures = listOf( + MR.images.ic_play_arrow_filled to MR.strings.v6_0_chat_list_media, + MR.images.ic_blur_on to MR.strings.v6_0_privacy_blur, + ) ), FeatureDescription( icon = MR.images.ic_toast, @@ -611,20 +632,21 @@ private val versionDescriptions: List = listOf( show = appPlatform.isAndroid ), FeatureDescription( - icon = MR.images.ic_link, - titleId = MR.strings.v6_0_connect_faster, - descrId = MR.strings.v6_0_connect_faster_descr - ), - FeatureDescription( - icon = MR.images.ic_delete, - titleId = MR.strings.v6_0_delete_many_messages, - descrId = MR.strings.v6_0_delete_many_messages_descr + icon = MR.images.ic_settings_ethernet, + titleId = MR.strings.v5_8_private_routing, + descrId = MR.strings.v6_0_private_routing_descr ), FeatureDescription( icon = MR.images.ic_wifi_tethering, titleId = MR.strings.v6_0_connection_servers_status, descrId = MR.strings.v6_0_connection_servers_status_descr - ) + ), + FeatureDescription( + icon = MR.images.ic_upgrade, + titleId = MR.strings.v6_0_upgrade_app, + descrId = MR.strings.v6_0_upgrade_app_descr, + show = appPlatform.isDesktop + ), ), ) ) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/DeveloperView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/DeveloperView.kt index ef8c30b43a..8a6e4efe32 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/DeveloperView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/DeveloperView.kt @@ -9,6 +9,7 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.runtime.* +import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalUriHandler import chat.simplex.common.model.* @@ -30,9 +31,11 @@ fun DeveloperView( AppBarTitle(stringResource(MR.strings.settings_developer_tools)) val developerTools = m.controller.appPrefs.developerTools val devTools = remember { developerTools.state } + val unchangedHints = mutableStateOf(unchangedHintPreferences()) SectionView { InstallTerminalAppItem(uriHandler) ChatConsoleItem { withAuth(generalGetString(MR.strings.auth_open_chat_console), generalGetString(MR.strings.auth_log_in_using_credential), showCustomModal { it, close -> TerminalView(it, close) }) } + ResetHintsItem(unchangedHints) SettingsPreferenceItem(painterResource(MR.images.ic_code), stringResource(MR.strings.show_developer_options), developerTools) SectionTextFooter( generalGetString(if (devTools.value) MR.strings.show_dev_options else MR.strings.hide_dev_options) + " " + diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/SettingsView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/SettingsView.kt index b0aa365a21..442bced4d9 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/SettingsView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/SettingsView.kt @@ -330,6 +330,31 @@ fun ChatLockItem( } } +@Composable fun ResetHintsItem(unchangedHints: MutableState) { + SectionItemView({ + resetHintPreferences() + unchangedHints.value = true + }, disabled = unchangedHints.value) { + Icon( + painter = painterResource(MR.images.ic_lightbulb), + contentDescription = "Lightbulb", + tint = MaterialTheme.colors.secondary, + ) + TextIconSpaced() + Text(generalGetString(MR.strings.reset_all_hints), color = if (unchangedHints.value) MaterialTheme.colors.secondary else MaterialTheme.colors.primary) + } +} + +private fun resetHintPreferences() { + for ((pref, def) in appPreferences.hintPreferences) { + pref.set(def) + } +} + +fun unchangedHintPreferences(): Boolean = appPreferences.hintPreferences.all { (pref, def) -> + pref.state.value == def +} + @Composable fun AppVersionItem(showVersion: () -> Unit) { SectionItemViewWithIcon(showVersion) { AppVersionText() } diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml index bdd54811ac..db0b407d9d 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml @@ -739,6 +739,7 @@ Other XFTP servers Show percentage Install SimpleX Chat for terminal + Reset all hints Star on GitHub Contribute Rate the app @@ -1294,6 +1295,8 @@ Incompatible database version Confirm database upgrades Reachable chat toolbar + Toggle chat list: + You can change it in Appearance settings. Show console in new window Show chat list in new window Invalid migration confirmation @@ -1974,15 +1977,19 @@ Improved message delivery With reduced battery usage. Persian UI + New chat experience 🎉 + New media options It protects your IP address and connections. - Your contacts your way - - Search contacts when starting chat.\n- Archive contacts to chat later. - Reachable chat toolbar 👋 + Archive contacts to chat later. + Reachable chat toolbar Use the app with one hand. - Connect to your friends faster - Even when they are offline. - Moderate like a pro ✋ + Connect to your friends faster. Delete up to 20 messages at once. + Play from the chat list. + Blur for better privacy. + Increase font size. + Upgrade app automatically + Download new versions from GitHub. Control your network Connection and servers status. diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/images/ic_lightbulb.svg b/apps/multiplatform/common/src/commonMain/resources/MR/images/ic_lightbulb.svg new file mode 100644 index 0000000000..689e5c2d5c --- /dev/null +++ b/apps/multiplatform/common/src/commonMain/resources/MR/images/ic_lightbulb.svg @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/images/ic_match_case.svg b/apps/multiplatform/common/src/commonMain/resources/MR/images/ic_match_case.svg new file mode 100644 index 0000000000..b56c8cb590 --- /dev/null +++ b/apps/multiplatform/common/src/commonMain/resources/MR/images/ic_match_case.svg @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/images/ic_upgrade.svg b/apps/multiplatform/common/src/commonMain/resources/MR/images/ic_upgrade.svg new file mode 100644 index 0000000000..c9ecd4ad87 --- /dev/null +++ b/apps/multiplatform/common/src/commonMain/resources/MR/images/ic_upgrade.svg @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/apps/multiplatform/gradle.properties b/apps/multiplatform/gradle.properties index 10af65c5af..1c2f0b16b8 100644 --- a/apps/multiplatform/gradle.properties +++ b/apps/multiplatform/gradle.properties @@ -26,11 +26,11 @@ android.enableJetifier=true kotlin.mpp.androidSourceSetLayoutVersion=2 kotlin.jvm.target=11 -android.version_name=6.0-beta.2 -android.version_code=227 +android.version_name=6.0-beta.3 +android.version_code=228 -desktop.version_name=6.0-beta.2 -desktop.version_code=58 +desktop.version_name=6.0-beta.3 +desktop.version_code=59 kotlin.version=1.9.23 gradle.plugin.version=8.2.0 diff --git a/cabal.project b/cabal.project index c316d93305..5afb0ae821 100644 --- a/cabal.project +++ b/cabal.project @@ -12,7 +12,7 @@ constraints: zip +disable-bzip2 +disable-zstd source-repository-package type: git location: https://github.com/simplex-chat/simplexmq.git - tag: a76e15fd77d68a09bc43820c1cf6bd1c71700100 + tag: 7d8457263bb77c6d9cb1cd102c3c70177e75327f source-repository-package type: git diff --git a/package.yaml b/package.yaml index 095a36371a..3a565cc44c 100644 --- a/package.yaml +++ b/package.yaml @@ -1,5 +1,5 @@ name: simplex-chat -version: 6.0.0.4 +version: 6.0.0.5 #synopsis: #description: homepage: https://github.com/simplex-chat/simplex-chat#readme diff --git a/scripts/nix/sha256map.nix b/scripts/nix/sha256map.nix index 69eca4dd5c..1b9d0bca4a 100644 --- a/scripts/nix/sha256map.nix +++ b/scripts/nix/sha256map.nix @@ -1,5 +1,5 @@ { - "https://github.com/simplex-chat/simplexmq.git"."a76e15fd77d68a09bc43820c1cf6bd1c71700100" = "07vrjpid03w8f1himhvaaljzspwxxkln814k5kx0yw9hhmabh7zy"; + "https://github.com/simplex-chat/simplexmq.git"."7d8457263bb77c6d9cb1cd102c3c70177e75327f" = "1n95mp2qmx9nj25zzqibkgx7s23shw7c26mf42bw661aprx4v24m"; "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"; diff --git a/simplex-chat.cabal b/simplex-chat.cabal index bd17fd9d64..79e70874da 100644 --- a/simplex-chat.cabal +++ b/simplex-chat.cabal @@ -5,7 +5,7 @@ cabal-version: 1.12 -- see: https://github.com/sol/hpack name: simplex-chat -version: 6.0.0.4 +version: 6.0.0.5 category: Web, System, Services, Cryptography homepage: https://github.com/simplex-chat/simplex-chat#readme author: simplex.chat diff --git a/src/Simplex/Chat/Controller.hs b/src/Simplex/Chat/Controller.hs index 301ef690a6..dbfa361c70 100644 --- a/src/Simplex/Chat/Controller.hs +++ b/src/Simplex/Chat/Controller.hs @@ -1204,7 +1204,7 @@ data DatabaseError | DBErrorOpen {sqliteError :: SQLiteError} deriving (Show, Exception) -data SQLiteError = SQLiteErrorNotADatabase | SQLiteError String +data SQLiteError = SQLiteErrorNotADatabase | SQLiteError {dbError :: String} deriving (Show, Exception) throwDBError :: DatabaseError -> CM ()