mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2024-12-17 17:20:21 +01:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 43c356b9c2 | |||
| 9b29afef3e | |||
| 6eab3aeb62 | |||
| 2209a467bb | |||
| df1a471c56 | |||
| 7d43a43e82 | |||
| ae8ad5c639 | |||
| 1408d75eb3 | |||
| f408988035 | |||
| 945c5015d8 | |||
| 2e431c5afa | |||
| 924273191e | |||
| 9b82cc3303 | |||
| 19e2cebd68 |
@@ -519,7 +519,14 @@ func testProtoServer(server: String) async throws -> Result<(), ProtocolTestFail
|
||||
throw r
|
||||
}
|
||||
|
||||
func getServerOperators() throws -> ServerOperatorConditions {
|
||||
func getServerOperators() async throws -> ServerOperatorConditions {
|
||||
let r = await chatSendCmd(.apiGetServerOperators)
|
||||
if case let .serverOperatorConditions(conditions) = r { return conditions }
|
||||
logger.error("getServerOperators error: \(String(describing: r))")
|
||||
throw r
|
||||
}
|
||||
|
||||
func getServerOperatorsSync() throws -> ServerOperatorConditions {
|
||||
let r = chatSendCmdSync(.apiGetServerOperators)
|
||||
if case let .serverOperatorConditions(conditions) = r { return conditions }
|
||||
logger.error("getServerOperators error: \(String(describing: r))")
|
||||
@@ -1599,7 +1606,7 @@ func initializeChat(start: Bool, confirmStart: Bool = false, dbKey: String? = ni
|
||||
try apiSetEncryptLocalFiles(privacyEncryptLocalFilesGroupDefault.get())
|
||||
m.chatInitialized = true
|
||||
m.currentUser = try apiGetActiveUser()
|
||||
m.conditions = try getServerOperators()
|
||||
m.conditions = try getServerOperatorsSync()
|
||||
if shouldImportAppSettingsDefault.get() {
|
||||
do {
|
||||
let appSettings = try apiGetAppSettings(settings: AppSettings.current.prepareForExport())
|
||||
|
||||
@@ -96,6 +96,8 @@ struct ChatInfoView: View {
|
||||
@ObservedObject var chat: Chat
|
||||
@State var contact: Contact
|
||||
@State var localAlias: String
|
||||
@State var featuresAllowed: ContactFeaturesAllowed
|
||||
@State var currentFeaturesAllowed: ContactFeaturesAllowed
|
||||
var onSearch: () -> Void
|
||||
@State private var connectionStats: ConnectionStats? = nil
|
||||
@State private var customUserProfile: Profile? = nil
|
||||
@@ -327,6 +329,16 @@ struct ChatInfoView: View {
|
||||
$0.content
|
||||
}
|
||||
}
|
||||
.onDisappear {
|
||||
if currentFeaturesAllowed != featuresAllowed {
|
||||
showAlert(
|
||||
title: NSLocalizedString("Save preferences?", comment: "alert title"),
|
||||
buttonTitle: NSLocalizedString("Save and notify contact", comment: "alert button"),
|
||||
buttonAction: { savePreferences() },
|
||||
cancelButton: true
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func contactInfoHeader() -> some View {
|
||||
@@ -447,8 +459,9 @@ struct ChatInfoView: View {
|
||||
NavigationLink {
|
||||
ContactPreferencesView(
|
||||
contact: $contact,
|
||||
featuresAllowed: contactUserPrefsToFeaturesAllowed(contact.mergedPreferences),
|
||||
currentFeaturesAllowed: contactUserPrefsToFeaturesAllowed(contact.mergedPreferences)
|
||||
featuresAllowed: $featuresAllowed,
|
||||
currentFeaturesAllowed: $currentFeaturesAllowed,
|
||||
savePreferences: savePreferences
|
||||
)
|
||||
.navigationBarTitle("Contact preferences")
|
||||
.modifier(ThemedBackground(grouped: true))
|
||||
@@ -617,6 +630,23 @@ struct ChatInfoView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func savePreferences() {
|
||||
Task {
|
||||
do {
|
||||
let prefs = contactFeaturesAllowedToPrefs(featuresAllowed)
|
||||
if let toContact = try await apiSetContactPrefs(contactId: contact.contactId, preferences: prefs) {
|
||||
await MainActor.run {
|
||||
contact = toContact
|
||||
chatModel.updateContact(toContact)
|
||||
currentFeaturesAllowed = featuresAllowed
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
logger.error("ContactPreferencesView apiSetContactPrefs error: \(responseError(error))")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct AudioCallButton: View {
|
||||
@@ -1173,6 +1203,8 @@ struct ChatInfoView_Previews: PreviewProvider {
|
||||
chat: Chat(chatInfo: ChatInfo.sampleData.direct, chatItems: []),
|
||||
contact: Contact.sampleData,
|
||||
localAlias: "",
|
||||
featuresAllowed: contactUserPrefsToFeaturesAllowed(Contact.sampleData.mergedPreferences),
|
||||
currentFeaturesAllowed: contactUserPrefsToFeaturesAllowed(Contact.sampleData.mergedPreferences),
|
||||
onSearch: {}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -133,7 +133,12 @@ struct ChatView: View {
|
||||
.appSheet(item: $selectedMember) { member in
|
||||
Group {
|
||||
if case let .group(groupInfo) = chat.chatInfo {
|
||||
GroupMemberInfoView(groupInfo: groupInfo, groupMember: member, navigation: true)
|
||||
GroupMemberInfoView(
|
||||
groupInfo: groupInfo,
|
||||
chat: chat,
|
||||
groupMember: member,
|
||||
navigation: true
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -226,6 +231,8 @@ struct ChatView: View {
|
||||
chat: chat,
|
||||
contact: contact,
|
||||
localAlias: chat.chatInfo.localAlias,
|
||||
featuresAllowed: contactUserPrefsToFeaturesAllowed(contact.mergedPreferences),
|
||||
currentFeaturesAllowed: contactUserPrefsToFeaturesAllowed(contact.mergedPreferences),
|
||||
onSearch: { focusSearch() }
|
||||
)
|
||||
}
|
||||
@@ -1122,6 +1129,7 @@ struct ChatView: View {
|
||||
} else {
|
||||
let mem = GMember.init(member)
|
||||
m.groupMembers.append(mem)
|
||||
m.groupMembersIndexes[member.groupMemberId] = m.groupMembers.count - 1
|
||||
selectedMember = mem
|
||||
}
|
||||
}
|
||||
@@ -1877,6 +1885,7 @@ struct ReactionContextMenu: View {
|
||||
} else {
|
||||
let member = GMember.init(mem)
|
||||
m.groupMembers.append(member)
|
||||
m.groupMembersIndexes[member.groupMemberId] = m.groupMembers.count - 1
|
||||
selectedMember = member
|
||||
}
|
||||
} label: {
|
||||
|
||||
@@ -14,9 +14,10 @@ struct ContactPreferencesView: View {
|
||||
@EnvironmentObject var chatModel: ChatModel
|
||||
@EnvironmentObject var theme: AppTheme
|
||||
@Binding var contact: Contact
|
||||
@State var featuresAllowed: ContactFeaturesAllowed
|
||||
@State var currentFeaturesAllowed: ContactFeaturesAllowed
|
||||
@Binding var featuresAllowed: ContactFeaturesAllowed
|
||||
@Binding var currentFeaturesAllowed: ContactFeaturesAllowed
|
||||
@State private var showSaveDialogue = false
|
||||
let savePreferences: () -> Void
|
||||
|
||||
var body: some View {
|
||||
let user: User = chatModel.currentUser!
|
||||
@@ -48,7 +49,10 @@ struct ContactPreferencesView: View {
|
||||
savePreferences()
|
||||
dismiss()
|
||||
}
|
||||
Button("Exit without saving") { dismiss() }
|
||||
Button("Exit without saving") {
|
||||
featuresAllowed = currentFeaturesAllowed
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,31 +122,15 @@ struct ContactPreferencesView: View {
|
||||
private func featureFooter(_ feature: ChatFeature, _ enabled: FeatureEnabled) -> some View {
|
||||
Text(feature.enabledDescription(enabled))
|
||||
}
|
||||
|
||||
private func savePreferences() {
|
||||
Task {
|
||||
do {
|
||||
let prefs = contactFeaturesAllowedToPrefs(featuresAllowed)
|
||||
if let toContact = try await apiSetContactPrefs(contactId: contact.contactId, preferences: prefs) {
|
||||
await MainActor.run {
|
||||
contact = toContact
|
||||
chatModel.updateContact(toContact)
|
||||
currentFeaturesAllowed = featuresAllowed
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
logger.error("ContactPreferencesView apiSetContactPrefs error: \(responseError(error))")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ContactPreferencesView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
ContactPreferencesView(
|
||||
contact: Binding.constant(Contact.sampleData),
|
||||
featuresAllowed: ContactFeaturesAllowed.sampleData,
|
||||
currentFeaturesAllowed: ContactFeaturesAllowed.sampleData
|
||||
featuresAllowed: Binding.constant(ContactFeaturesAllowed.sampleData),
|
||||
currentFeaturesAllowed: Binding.constant(ContactFeaturesAllowed.sampleData),
|
||||
savePreferences: {}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,7 +78,12 @@ struct AddGroupMembersViewCommon: View {
|
||||
let count = selectedContacts.count
|
||||
Section {
|
||||
if creatingGroup {
|
||||
groupPreferencesButton($groupInfo, true)
|
||||
GroupPreferencesButton(
|
||||
groupInfo: $groupInfo,
|
||||
preferences: groupInfo.fullGroupPreferences,
|
||||
currentPreferences: groupInfo.fullGroupPreferences,
|
||||
creatingGroup: true
|
||||
)
|
||||
}
|
||||
rolePicker()
|
||||
inviteMembersButton()
|
||||
|
||||
@@ -87,7 +87,7 @@ struct GroupChatInfoView: View {
|
||||
if groupInfo.groupProfile.description != nil || (groupInfo.isOwner && groupInfo.businessChat == nil) {
|
||||
addOrEditWelcomeMessage()
|
||||
}
|
||||
groupPreferencesButton($groupInfo)
|
||||
GroupPreferencesButton(groupInfo: $groupInfo, preferences: groupInfo.fullGroupPreferences, currentPreferences: groupInfo.fullGroupPreferences)
|
||||
if members.filter({ $0.wrapped.memberCurrent }).count <= SMALL_GROUPS_RCPS_MEM_LIMIT {
|
||||
sendReceiptsOption()
|
||||
} else {
|
||||
@@ -439,7 +439,7 @@ struct GroupChatInfoView: View {
|
||||
}
|
||||
|
||||
private func memberInfoView(_ groupMember: GMember) -> some View {
|
||||
GroupMemberInfoView(groupInfo: groupInfo, groupMember: groupMember)
|
||||
GroupMemberInfoView(groupInfo: groupInfo, chat: chat, groupMember: groupMember)
|
||||
.navigationBarHidden(false)
|
||||
}
|
||||
|
||||
@@ -654,27 +654,72 @@ func deleteGroupAlertMessage(_ groupInfo: GroupInfo) -> Text {
|
||||
)
|
||||
}
|
||||
|
||||
func groupPreferencesButton(_ groupInfo: Binding<GroupInfo>, _ creatingGroup: Bool = false) -> some View {
|
||||
let label: LocalizedStringKey = groupInfo.wrappedValue.businessChat == nil ? "Group preferences" : "Chat preferences"
|
||||
return NavigationLink {
|
||||
GroupPreferencesView(
|
||||
groupInfo: groupInfo,
|
||||
preferences: groupInfo.wrappedValue.fullGroupPreferences,
|
||||
currentPreferences: groupInfo.wrappedValue.fullGroupPreferences,
|
||||
creatingGroup: creatingGroup
|
||||
)
|
||||
.navigationBarTitle(label)
|
||||
.modifier(ThemedBackground(grouped: true))
|
||||
.navigationBarTitleDisplayMode(.large)
|
||||
} label: {
|
||||
if creatingGroup {
|
||||
Text("Set group preferences")
|
||||
} else {
|
||||
Label(label, systemImage: "switch.2")
|
||||
struct GroupPreferencesButton: View {
|
||||
@Binding var groupInfo: GroupInfo
|
||||
@State var preferences: FullGroupPreferences
|
||||
@State var currentPreferences: FullGroupPreferences
|
||||
var creatingGroup: Bool = false
|
||||
|
||||
private var label: LocalizedStringKey {
|
||||
groupInfo.businessChat == nil ? "Group preferences" : "Chat preferences"
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
NavigationLink {
|
||||
GroupPreferencesView(
|
||||
groupInfo: $groupInfo,
|
||||
preferences: $preferences,
|
||||
currentPreferences: currentPreferences,
|
||||
creatingGroup: creatingGroup,
|
||||
savePreferences: savePreferences
|
||||
)
|
||||
.navigationBarTitle(label)
|
||||
.modifier(ThemedBackground(grouped: true))
|
||||
.navigationBarTitleDisplayMode(.large)
|
||||
.onDisappear {
|
||||
let saveText = NSLocalizedString(
|
||||
creatingGroup ? "Save" : "Save and notify group members",
|
||||
comment: "alert button"
|
||||
)
|
||||
|
||||
if groupInfo.fullGroupPreferences != preferences {
|
||||
showAlert(
|
||||
title: NSLocalizedString("Save preferences?", comment: "alert title"),
|
||||
buttonTitle: saveText,
|
||||
buttonAction: { savePreferences() },
|
||||
cancelButton: true
|
||||
)
|
||||
}
|
||||
}
|
||||
} label: {
|
||||
if creatingGroup {
|
||||
Text("Set group preferences")
|
||||
} else {
|
||||
Label(label, systemImage: "switch.2")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func savePreferences() {
|
||||
Task {
|
||||
do {
|
||||
var gp = groupInfo.groupProfile
|
||||
gp.groupPreferences = toGroupPreferences(preferences)
|
||||
let gInfo = try await apiUpdateGroup(groupInfo.groupId, gp)
|
||||
await MainActor.run {
|
||||
groupInfo = gInfo
|
||||
ChatModel.shared.updateGroup(gInfo)
|
||||
currentPreferences = preferences
|
||||
}
|
||||
} catch {
|
||||
logger.error("GroupPreferencesView apiUpdateGroup error: \(responseError(error))")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
func cantInviteIncognitoAlert() -> Alert {
|
||||
Alert(
|
||||
title: Text("Can't invite contacts!"),
|
||||
|
||||
@@ -14,6 +14,7 @@ struct GroupMemberInfoView: View {
|
||||
@EnvironmentObject var theme: AppTheme
|
||||
@Environment(\.dismiss) var dismiss: DismissAction
|
||||
@State var groupInfo: GroupInfo
|
||||
@ObservedObject var chat: Chat
|
||||
@ObservedObject var groupMember: GMember
|
||||
var navigation: Bool = false
|
||||
@State private var connectionStats: ConnectionStats? = nil
|
||||
@@ -261,6 +262,11 @@ struct GroupMemberInfoView: View {
|
||||
ProgressView().scaleEffect(2)
|
||||
}
|
||||
}
|
||||
.onChange(of: chat.chatInfo) { c in
|
||||
if case let .group(gI) = chat.chatInfo {
|
||||
groupInfo = gI
|
||||
}
|
||||
}
|
||||
.modifier(ThemedBackground(grouped: true))
|
||||
}
|
||||
|
||||
@@ -758,6 +764,7 @@ struct GroupMemberInfoView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
GroupMemberInfoView(
|
||||
groupInfo: GroupInfo.sampleData,
|
||||
chat: Chat.sampleData,
|
||||
groupMember: GMember.sampleData
|
||||
)
|
||||
}
|
||||
|
||||
@@ -20,9 +20,10 @@ struct GroupPreferencesView: View {
|
||||
@EnvironmentObject var chatModel: ChatModel
|
||||
@EnvironmentObject var theme: AppTheme
|
||||
@Binding var groupInfo: GroupInfo
|
||||
@State var preferences: FullGroupPreferences
|
||||
@State var currentPreferences: FullGroupPreferences
|
||||
@Binding var preferences: FullGroupPreferences
|
||||
var currentPreferences: FullGroupPreferences
|
||||
let creatingGroup: Bool
|
||||
let savePreferences: () -> Void
|
||||
@State private var showSaveDialogue = false
|
||||
|
||||
var body: some View {
|
||||
@@ -68,7 +69,10 @@ struct GroupPreferencesView: View {
|
||||
savePreferences()
|
||||
dismiss()
|
||||
}
|
||||
Button("Exit without saving") { dismiss() }
|
||||
Button("Exit without saving") {
|
||||
preferences = currentPreferences
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,32 +136,16 @@ struct GroupPreferencesView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func savePreferences() {
|
||||
Task {
|
||||
do {
|
||||
var gp = groupInfo.groupProfile
|
||||
gp.groupPreferences = toGroupPreferences(preferences)
|
||||
let gInfo = try await apiUpdateGroup(groupInfo.groupId, gp)
|
||||
await MainActor.run {
|
||||
groupInfo = gInfo
|
||||
chatModel.updateGroup(gInfo)
|
||||
currentPreferences = preferences
|
||||
}
|
||||
} catch {
|
||||
logger.error("GroupPreferencesView apiUpdateGroup error: \(responseError(error))")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct GroupPreferencesView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
GroupPreferencesView(
|
||||
groupInfo: Binding.constant(GroupInfo.sampleData),
|
||||
preferences: FullGroupPreferences.sampleData,
|
||||
preferences: Binding.constant(FullGroupPreferences.sampleData),
|
||||
currentPreferences: FullGroupPreferences.sampleData,
|
||||
creatingGroup: false
|
||||
creatingGroup: false,
|
||||
savePreferences: {}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,29 @@ enum UserPickerSheet: Identifiable {
|
||||
|
||||
class SaveableSettings: ObservableObject {
|
||||
@Published var servers: ServerSettings = ServerSettings(currUserServers: [], userServers: [], serverErrors: [])
|
||||
@Published var networkSettings: NetworkSettings = NetworkSettings.defaults
|
||||
|
||||
public func saveNetCfg() -> Bool {
|
||||
do {
|
||||
let netCfg = networkSettings.netCfg
|
||||
let netProxy = networkSettings.netProxy
|
||||
try setNetworkConfig(netCfg)
|
||||
networkSettings.currentNetCfg = netCfg
|
||||
setNetCfg(netCfg, networkProxy: netCfg.socksProxy != nil ? netProxy : nil)
|
||||
networkSettings.currentNetProxy = netProxy
|
||||
networkProxyDefault.set(netProxy)
|
||||
return true
|
||||
} catch let error {
|
||||
let err = responseError(error)
|
||||
showAlert(
|
||||
NSLocalizedString("Error updating settings", comment: "alert title"),
|
||||
message: responseError(error)
|
||||
)
|
||||
|
||||
logger.error("\(err)")
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ServerSettings {
|
||||
@@ -41,6 +64,20 @@ struct ServerSettings {
|
||||
public var serverErrors: [UserServersError]
|
||||
}
|
||||
|
||||
struct NetworkSettings {
|
||||
public var currentNetCfg: NetCfg
|
||||
public var netCfg: NetCfg
|
||||
public var currentNetProxy: NetworkProxy
|
||||
public var netProxy: NetworkProxy
|
||||
|
||||
static let defaults = NetworkSettings(
|
||||
currentNetCfg: NetCfg.defaults,
|
||||
netCfg: NetCfg.defaults,
|
||||
currentNetProxy: networkProxyDefault.get(),
|
||||
netProxy: networkProxyDefault.get()
|
||||
)
|
||||
}
|
||||
|
||||
struct UserPickerSheetView: View {
|
||||
let sheet: UserPickerSheet
|
||||
@EnvironmentObject var chatModel: ChatModel
|
||||
@@ -89,15 +126,30 @@ struct UserPickerSheetView: View {
|
||||
)
|
||||
}
|
||||
.onDisappear {
|
||||
let advancedNetworkCanBeSaved = advancedNetworkSettingsCanBeSaved(ss.networkSettings)
|
||||
let advancedNetworkSaveText = NSLocalizedString("Save and reconnect", comment: "alert button")
|
||||
|
||||
if serversCanBeSaved(
|
||||
ss.servers.currUserServers,
|
||||
ss.servers.userServers,
|
||||
ss.servers.serverErrors
|
||||
) {
|
||||
showAlert(
|
||||
title: NSLocalizedString("Save servers?", comment: "alert title"),
|
||||
buttonTitle: NSLocalizedString("Save", comment: "alert button"),
|
||||
buttonAction: { saveServers($ss.servers.currUserServers, $ss.servers.userServers) },
|
||||
title: NSLocalizedString(advancedNetworkCanBeSaved ? "Save servers and network settings?" : "Save servers?", comment: "alert title"),
|
||||
buttonTitle: advancedNetworkCanBeSaved ? NSLocalizedString("Save", comment: "alert button"): advancedNetworkSaveText,
|
||||
buttonAction: {
|
||||
saveServers($ss.servers.currUserServers, $ss.servers.userServers)
|
||||
if advancedNetworkCanBeSaved {
|
||||
_ = ss.saveNetCfg()
|
||||
}
|
||||
},
|
||||
cancelButton: true
|
||||
)
|
||||
} else if (advancedNetworkCanBeSaved) {
|
||||
showAlert(
|
||||
title: NSLocalizedString("Update network settings?", comment: "alert title"),
|
||||
buttonTitle: advancedNetworkSaveText,
|
||||
buttonAction: { _ = ss.saveNetCfg() },
|
||||
cancelButton: true
|
||||
)
|
||||
}
|
||||
|
||||
@@ -409,26 +409,54 @@ struct ChooseServerOperators: View {
|
||||
let operatorsPostLink = URL(string: "https://simplex.chat/blog/20241125-servers-operated-by-flux-true-privacy-and-decentralization-for-all-users.html")!
|
||||
|
||||
struct ChooseServerOperatorsInfoView: View {
|
||||
@Environment(\.colorScheme) var colorScheme: ColorScheme
|
||||
@EnvironmentObject var theme: AppTheme
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading) {
|
||||
Text("Server operators")
|
||||
.font(.largeTitle)
|
||||
.bold()
|
||||
.padding(.vertical)
|
||||
ScrollView {
|
||||
NavigationView {
|
||||
List {
|
||||
VStack(alignment: .leading) {
|
||||
Group {
|
||||
Text("The app protects your privacy by using different operators in each conversation.")
|
||||
Text("When more than one operator is enabled, none of them has metadata to learn who communicates with whom.")
|
||||
Text("For example, if your contact receives messages via a SimpleX Chat server, your app will deliver them via a Flux server.")
|
||||
Text("The app protects your privacy by using different operators in each conversation.")
|
||||
.padding(.bottom)
|
||||
Text("When more than one operator is enabled, none of them has metadata to learn who communicates with whom.")
|
||||
.padding(.bottom)
|
||||
Text("For example, if your contact receives messages via a SimpleX Chat server, your app will deliver them via a Flux server.")
|
||||
}
|
||||
.listRowBackground(Color.clear)
|
||||
.listRowSeparator(.hidden)
|
||||
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
|
||||
.padding(.top)
|
||||
|
||||
Section {
|
||||
ForEach(ChatModel.shared.conditions.serverOperators) { op in
|
||||
operatorInfoNavLinkView(op)
|
||||
}
|
||||
.padding(.bottom)
|
||||
} header: {
|
||||
Text("About operators")
|
||||
.foregroundColor(theme.colors.secondary)
|
||||
}
|
||||
}
|
||||
.navigationTitle("Server operators")
|
||||
.navigationBarTitleDisplayMode(.large)
|
||||
.modifier(ThemedBackground(grouped: true))
|
||||
}
|
||||
}
|
||||
|
||||
private func operatorInfoNavLinkView(_ op: ServerOperator) -> some View {
|
||||
NavigationLink() {
|
||||
OperatorInfoView(serverOperator: op)
|
||||
.navigationBarTitle("Network operator")
|
||||
.modifier(ThemedBackground(grouped: true))
|
||||
.navigationBarTitleDisplayMode(.large)
|
||||
} label: {
|
||||
HStack {
|
||||
Image(op.logo(colorScheme))
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 24, height: 24)
|
||||
Text(op.tradeName)
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top)
|
||||
.modifier(ThemedBackground())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+14
-22
@@ -28,19 +28,20 @@ struct AdvancedNetworkSettings: View {
|
||||
@EnvironmentObject var theme: AppTheme
|
||||
@AppStorage(DEFAULT_DEVELOPER_TOOLS) private var developerTools = false
|
||||
@AppStorage(DEFAULT_SHOW_SENT_VIA_RPOXY) private var showSentViaProxy = false
|
||||
@State private var netCfg = NetCfg.defaults
|
||||
@State private var currentNetCfg = NetCfg.defaults
|
||||
@State private var cfgLoaded = false
|
||||
@State private var enableKeepAlive = true
|
||||
@State private var keepAliveOpts = KeepAliveOpts.defaults
|
||||
@State private var showSettingsAlert: NetworkSettingsAlert?
|
||||
@State private var onionHosts: OnionHosts = .no
|
||||
@State private var showSaveDialog = false
|
||||
@State private var netProxy = networkProxyDefault.get()
|
||||
@State private var currentNetProxy = networkProxyDefault.get()
|
||||
@State private var useNetProxy = false
|
||||
@State private var netProxyAuth = false
|
||||
|
||||
@Binding public var currentNetCfg: NetCfg
|
||||
@Binding public var netCfg: NetCfg
|
||||
@Binding public var currentNetProxy: NetworkProxy
|
||||
@Binding public var netProxy: NetworkProxy
|
||||
let saveNetCfg: () -> Bool
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
List {
|
||||
@@ -312,22 +313,6 @@ struct AdvancedNetworkSettings: View {
|
||||
}
|
||||
}
|
||||
|
||||
private func saveNetCfg() -> Bool {
|
||||
do {
|
||||
try setNetworkConfig(netCfg)
|
||||
currentNetCfg = netCfg
|
||||
setNetCfg(netCfg, networkProxy: useNetProxy ? netProxy : nil)
|
||||
currentNetProxy = netProxy
|
||||
networkProxyDefault.set(netProxy)
|
||||
return true
|
||||
} catch let error {
|
||||
let err = responseError(error)
|
||||
showSettingsAlert = .error(err: err)
|
||||
logger.error("\(err)")
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
private func intSettingPicker(_ title: LocalizedStringKey, selection: Binding<Int>, values: [Int], label: String) -> some View {
|
||||
Picker(title, selection: selection) {
|
||||
ForEach(values, id: \.self) { value in
|
||||
@@ -386,6 +371,13 @@ struct AdvancedNetworkSettings: View {
|
||||
|
||||
struct AdvancedNetworkSettings_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
AdvancedNetworkSettings()
|
||||
let defaultSettings = NetworkSettings.defaults
|
||||
AdvancedNetworkSettings(
|
||||
currentNetCfg: Binding.constant(defaultSettings.currentNetCfg),
|
||||
netCfg: Binding.constant(defaultSettings.netCfg),
|
||||
currentNetProxy: Binding.constant(defaultSettings.currentNetProxy),
|
||||
netProxy: Binding.constant(defaultSettings.netProxy),
|
||||
saveNetCfg: { true }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,9 +94,15 @@ struct NetworkAndServers: View {
|
||||
}
|
||||
|
||||
NavigationLink {
|
||||
AdvancedNetworkSettings()
|
||||
.navigationTitle("Advanced settings")
|
||||
.modifier(ThemedBackground(grouped: true))
|
||||
AdvancedNetworkSettings(
|
||||
currentNetCfg: $ss.networkSettings.currentNetCfg,
|
||||
netCfg: $ss.networkSettings.netCfg,
|
||||
currentNetProxy: $ss.networkSettings.currentNetProxy,
|
||||
netProxy: $ss.networkSettings.netProxy,
|
||||
saveNetCfg: ss.saveNetCfg
|
||||
)
|
||||
.navigationTitle("Advanced settings")
|
||||
.modifier(ThemedBackground(grouped: true))
|
||||
} label: {
|
||||
Text("Advanced network settings")
|
||||
}
|
||||
@@ -336,6 +342,13 @@ func serversCanBeSaved(
|
||||
return userServers != currUserServers && serverErrors.isEmpty
|
||||
}
|
||||
|
||||
func advancedNetworkSettingsCanBeSaved(
|
||||
_ config: NetworkSettings
|
||||
) -> Bool {
|
||||
let useNetProxy = config.netCfg.socksProxy != nil
|
||||
return (config.currentNetCfg != config.netCfg || config.currentNetProxy != config.netProxy) && (useNetProxy ? config.netProxy.valid : true)
|
||||
}
|
||||
|
||||
struct ServersErrorView: View {
|
||||
@EnvironmentObject var theme: AppTheme
|
||||
var errStr: String
|
||||
|
||||
@@ -2725,7 +2725,7 @@ public struct AppSettings: Codable, Equatable {
|
||||
uiDarkColorScheme: DefaultTheme.SIMPLEX.themeName,
|
||||
uiCurrentThemeIds: nil as [String: String]?,
|
||||
uiThemes: nil as [ThemeOverrides]?,
|
||||
oneHandUI: false,
|
||||
oneHandUI: true,
|
||||
chatBottomBar: true
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1782,9 +1782,11 @@ public struct PendingContactConnection: Decodable, NamedChat, Hashable {
|
||||
public var displayName: String {
|
||||
get {
|
||||
if let initiated = pccConnStatus.initiated {
|
||||
return initiated && !viaContactUri
|
||||
return viaContactUri
|
||||
? NSLocalizedString("requested to connect", comment: "chat list item title")
|
||||
: initiated
|
||||
? NSLocalizedString("invited to connect", comment: "chat list item title")
|
||||
: NSLocalizedString("connecting…", comment: "chat list item title")
|
||||
: NSLocalizedString("accepted invitation", comment: "chat list item title")
|
||||
} else {
|
||||
// this should not be in the list
|
||||
return NSLocalizedString("connection established", comment: "chat list item title (it should not be shown")
|
||||
|
||||
+3
-2
@@ -1895,8 +1895,9 @@ class PendingContactConnection(
|
||||
generalGetString(MR.strings.display_name_connection_established)
|
||||
} else {
|
||||
generalGetString(
|
||||
if (initiated && !viaContactUri) MR.strings.display_name_invited_to_connect
|
||||
else MR.strings.display_name_connecting
|
||||
if (viaContactUri) MR.strings.display_name_requested_to_connect
|
||||
else if (initiated) MR.strings.display_name_invited_to_connect
|
||||
else MR.strings.display_name_accepted_invitation
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-7
@@ -192,13 +192,7 @@ fun DatabaseLayout(
|
||||
}
|
||||
RunChatSetting(stopped, toggleEnabled && !progressIndicator, startChat, stopChatAlert)
|
||||
}
|
||||
SectionTextFooter(
|
||||
if (stopped) {
|
||||
stringResource(MR.strings.you_must_use_the_most_recent_version_of_database)
|
||||
} else {
|
||||
stringResource(MR.strings.stop_chat_to_enable_database_actions)
|
||||
}
|
||||
)
|
||||
if (stopped) SectionTextFooter(stringResource(MR.strings.you_must_use_the_most_recent_version_of_database))
|
||||
SectionDividerSpaced(maxTopPadding = true)
|
||||
}
|
||||
|
||||
|
||||
@@ -1049,7 +1049,6 @@
|
||||
<string name="stop_sharing_address">إيقاف مشاركة العنوان؟</string>
|
||||
<string name="stop_sharing">إيقاف المشاركة</string>
|
||||
<string name="stop_chat_to_export_import_or_delete_chat_database">أوقف الدردشة لتصدير أو استيراد أو حذف قاعدة بيانات الدردشة. لن تتمكّن من استلام الرسائل وإرسالها أثناء إيقاف الدردشة.</string>
|
||||
<string name="stop_chat_to_enable_database_actions">أوقف الدردشة لتمكين إجراءات قاعدة البيانات.</string>
|
||||
<string name="chat_item_ttl_seconds">%s ثانية/ثواني</string>
|
||||
<string name="callstate_starting">يبدأ…</string>
|
||||
<string name="auth_simplex_lock_turned_on">تم تشغيل القفل SimpleX</string>
|
||||
|
||||
@@ -71,6 +71,8 @@
|
||||
<string name="connection_local_display_name">connection %1$d</string>
|
||||
<string name="display_name_connection_established">connection established</string>
|
||||
<string name="display_name_invited_to_connect">invited to connect</string>
|
||||
<string name="display_name_requested_to_connect">requested to connect</string>
|
||||
<string name="display_name_accepted_invitation">accepted invitation</string>
|
||||
<string name="display_name_connecting">connecting…</string>
|
||||
<string name="description_you_shared_one_time_link">you shared one-time link</string>
|
||||
<string name="description_you_shared_one_time_link_incognito">you shared one-time link incognito</string>
|
||||
@@ -1306,7 +1308,6 @@
|
||||
<string name="chat_database_deleted">Chat database deleted</string>
|
||||
<string name="restart_the_app_to_create_a_new_chat_profile">Restart the app to create a new chat profile.</string>
|
||||
<string name="you_must_use_the_most_recent_version_of_database">You must use the most recent version of your chat database on one device ONLY, otherwise you may stop receiving the messages from some contacts.</string>
|
||||
<string name="stop_chat_to_enable_database_actions">Stop chat to enable database actions.</string>
|
||||
<string name="files_and_media_section">Files & media</string>
|
||||
<string name="delete_files_and_media_for_all_users">Delete files for all chat profiles</string>
|
||||
<string name="delete_files_and_media_all">Delete all files</string>
|
||||
|
||||
@@ -1133,7 +1133,6 @@
|
||||
<string name="save_preferences_question">Запази настройките\?</string>
|
||||
<string name="icon_descr_speaker_on">Високоговорителят е включен</string>
|
||||
<string name="icon_descr_speaker_off">Високоговорителят е изключен</string>
|
||||
<string name="stop_chat_to_enable_database_actions">Спрете чата, за да активирате действията с базата данни.</string>
|
||||
<string name="role_in_group">Роля</string>
|
||||
<string name="network_options_save">Запази</string>
|
||||
<string name="reset_color">Нулирай цветовете</string>
|
||||
|
||||
@@ -280,7 +280,6 @@
|
||||
<string name="delete_chat_profile_action_cannot_be_undone_warning">Tuto akci nelze vzít zpět! Váš profil, kontakty, zprávy a soubory budou nenávratně ztraceny.</string>
|
||||
<string name="restart_the_app_to_create_a_new_chat_profile">Restartujte aplikaci a vytvořte nový chat profil.</string>
|
||||
<string name="you_must_use_the_most_recent_version_of_database">Nejnovější verzi databáze chatu musíte používat POUZE v jednom zařízení, jinak se může stát, že přestanete přijímat zprávy od některých kontaktů.</string>
|
||||
<string name="stop_chat_to_enable_database_actions">Zastavte chat a povolte akce s databází.</string>
|
||||
<string name="files_and_media_section">Soubory a média</string>
|
||||
<string name="delete_files_and_media_question">Smazat soubory a média\?</string>
|
||||
<string name="delete_messages">Odstranit zprávy</string>
|
||||
|
||||
@@ -597,7 +597,6 @@
|
||||
<string name="chat_database_deleted">Chat-Datenbank gelöscht</string>
|
||||
<string name="restart_the_app_to_create_a_new_chat_profile">Starten Sie die App neu, um ein neues Chat-Profil zu erstellen.</string>
|
||||
<string name="you_must_use_the_most_recent_version_of_database">Sie dürfen die neueste Version Ihrer Chat-Datenbank NUR auf einem Gerät verwenden, andernfalls erhalten Sie möglicherweise keine Nachrichten mehr von einigen Ihrer Kontakte.</string>
|
||||
<string name="stop_chat_to_enable_database_actions">Chat beenden, um Datenbankaktionen zu erlauben.</string>
|
||||
<string name="delete_files_and_media_question">Dateien und Medien löschen?</string>
|
||||
<string name="delete_files_and_media_desc">Diese Aktion kann nicht rückgängig gemacht werden! Es werden alle empfangenen und gesendeten Dateien und Medien gelöscht. Bilder mit niedriger Auflösung bleiben erhalten.</string>
|
||||
<string name="no_received_app_files">Keine empfangenen oder gesendeten Dateien</string>
|
||||
|
||||
@@ -733,7 +733,6 @@
|
||||
<string name="share_invitation_link">Compartir enlace de un uso</string>
|
||||
<string name="update_network_session_mode_question">¿Actualizar el modo de aislamiento de transporte\?</string>
|
||||
<string name="icon_descr_speaker_on">Altavoz activado</string>
|
||||
<string name="stop_chat_to_enable_database_actions">Para habilitar las acciones sobre la base de datos, debes parar SimpleX</string>
|
||||
<string name="connection_you_accepted_will_be_cancelled">¡La conexión que has aceptado se cancelará!</string>
|
||||
<string name="database_initialization_error_desc">La base de datos no funciona correctamente. Pulsa para conocer más</string>
|
||||
<string name="moderate_message_will_be_marked_warning">El mensaje será marcado como moderado para todos los miembros.</string>
|
||||
|
||||
@@ -942,7 +942,6 @@
|
||||
<string name="delete_files_and_media_desc">این عمل قابل برگشت نیست - تمام پروندهها و رسانه دریافتی حذف خواهند شد. عکسهای با کیفیت پایین باقی خواهند ماند.</string>
|
||||
<string name="you_must_use_the_most_recent_version_of_database">شما باید از تازهترین نسخه پایگاه داده گپ خود روی فقط یک دستگاه استفاده کنید، در غیر این صورت ممکن است از بعضی از مخاطبها دیگر پیامی دریافت نکنید.</string>
|
||||
<string name="messages_section_title">پیامها</string>
|
||||
<string name="stop_chat_to_enable_database_actions">به منظور فعالسازی اقدامات پایگاه داده، گپ را متوقف کنید.</string>
|
||||
<string name="enable_automatic_deletion_message">این عمل قابل برگشت نیست - پیامهای ارسالی و دریافتی قدیمیتر از زمان انتخابی حذف خواهند شد. این کار ممکن است چندین دقیقه زمان ببرد.</string>
|
||||
<string name="error_changing_message_deletion">خطا در تغییر تنظیمات</string>
|
||||
<string name="save_passphrase_in_settings">ذخیره عبارت عبور در تنظیمات</string>
|
||||
|
||||
@@ -666,7 +666,6 @@
|
||||
<string name="self_destruct_passcode">Itsetuhoutuva pääsykoodi</string>
|
||||
<string name="restart_the_app_to_use_imported_chat_database">Käynnistä sovellus uudelleen käyttääksesi tuotua keskustelutietokantaa.</string>
|
||||
<string name="old_database_archive">Vanha tietokanta-arkisto</string>
|
||||
<string name="stop_chat_to_enable_database_actions">Pysäytä keskustelu, jotta tietokantatoiminnot voidaan ottaa käyttöön.</string>
|
||||
<string name="restart_the_app_to_create_a_new_chat_profile">Luo uusi keskusteluprofiili käynnistämällä sovellus uudelleen.</string>
|
||||
<string name="messages_section_title">Viestit</string>
|
||||
<string name="chat_item_ttl_none">ei koskaan</string>
|
||||
|
||||
@@ -617,7 +617,6 @@
|
||||
<string name="error_importing_database">Erreur lors de l\'importation de la base de données du chat</string>
|
||||
<string name="chat_database_imported">Base de données du chat importée</string>
|
||||
<string name="delete_chat_profile_question">Supprimer le profil du chat \?</string>
|
||||
<string name="stop_chat_to_enable_database_actions">Arrêter le chat pour agir sur la base de données.</string>
|
||||
<string name="delete_files_and_media_question">Supprimer les fichiers et médias \?</string>
|
||||
<string name="delete_files_and_media_desc">Cette action ne peut être annulée - tous les fichiers et médias reçus et envoyés seront supprimés. Les photos à faible résolution seront conservées.</string>
|
||||
<string name="no_received_app_files">Aucun fichier reçu ou envoyé</string>
|
||||
|
||||
@@ -922,7 +922,6 @@
|
||||
<string name="only_your_contact_can_make_calls">Csak az ismerőse tud hívást indítani.</string>
|
||||
<string name="settings_section_title_themes">TÉMÁK</string>
|
||||
<string name="videos_limit_title">Túl sok videó!</string>
|
||||
<string name="stop_chat_to_enable_database_actions">Csevegési szolgáltatás megállítása az adatbázis műveletek elvégzéséhez.</string>
|
||||
<string name="welcome">Üdvözöljük!</string>
|
||||
<string name="v5_1_self_destruct_passcode">Önmegsemmisítési jelkód</string>
|
||||
<string name="connect_via_link_or_qr_from_clipboard_or_in_person">(beolvasás, vagy beillesztés a vágólapról)</string>
|
||||
|
||||
@@ -874,7 +874,6 @@
|
||||
<string name="remove_passphrase_from_keychain">Rimuovere la password dal Keystore\?</string>
|
||||
<string name="save_passphrase_in_keychain">Salva la password nel Keystore</string>
|
||||
<string name="chat_item_ttl_seconds">%s secondo/i</string>
|
||||
<string name="stop_chat_to_enable_database_actions">Ferma la chat per attivare le azioni del database.</string>
|
||||
<string name="delete_files_and_media_desc">Questa azione non può essere annullata: tutti i file e i media ricevuti e inviati verranno eliminati. Rimarranno le immagini a bassa risoluzione.</string>
|
||||
<string name="enable_automatic_deletion_message">Questa azione non può essere annullata: i messaggi inviati e ricevuti prima di quanto selezionato verranno eliminati. Potrebbe richiedere diversi minuti.</string>
|
||||
<string name="update_database">Aggiorna</string>
|
||||
|
||||
@@ -981,7 +981,6 @@
|
||||
<string name="stop_chat_question">לעצור צ׳אט\?</string>
|
||||
<string name="stop_chat_to_export_import_or_delete_chat_database">עיצרו את הצ׳אט כדי לייצא, לייבא או למחוק את מסד הנתונים. לא תוכלו לקבל ולשלוח הודעות בזמן שהצ׳אט מופסק.</string>
|
||||
<string name="stop_chat_confirmation">עצור</string>
|
||||
<string name="stop_chat_to_enable_database_actions">עיצרו את הצ׳אט כדי לאפשר פעולות מסד נתונים.</string>
|
||||
<string name="skip_inviting_button">דלג על הזמנת חברים</string>
|
||||
<string name="share_address">שתף כתובת</string>
|
||||
<string name="theme_simplex">SimpleX</string>
|
||||
|
||||
@@ -662,7 +662,6 @@
|
||||
<string name="icon_descr_speaker_off">スピーカーオフ</string>
|
||||
<string name="your_chat_database">あなたのチャットデータベース</string>
|
||||
<string name="stop_chat_confirmation">停止</string>
|
||||
<string name="stop_chat_to_enable_database_actions">データベース操作をするにはチャットを停止する必要があります。</string>
|
||||
<string name="simplex_link_contact">SimpleX連絡先アドレス</string>
|
||||
<string name="simplex_link_invitation">SimpleX使い捨て招待リンク</string>
|
||||
<string name="description_via_contact_address_link">連絡先アドレスリンク経由</string>
|
||||
|
||||
@@ -851,7 +851,6 @@
|
||||
<string name="submit_passcode">제출하기</string>
|
||||
<string name="store_passphrase_securely_without_recover">암호를 모르면 채팅에 액세스할 수 없으니 암호를 안전하게 보관해 주세요.</string>
|
||||
<string name="stop_chat_question">채팅 기능을 중지할까요\?</string>
|
||||
<string name="stop_chat_to_enable_database_actions">데이터베이스 작업을 할 수 있도록 채팅 기능을 중지하기</string>
|
||||
<string name="switch_receiving_address">수신 주소 바꾸기</string>
|
||||
<string name="decryption_error">복호화 오류</string>
|
||||
<string name="confirm_passcode">패스코드 확인</string>
|
||||
|
||||
@@ -1219,7 +1219,6 @@
|
||||
<string name="set_database_passphrase">Nustatyti duomenų slaptafrazę</string>
|
||||
<string name="set_passphrase">Nustatyti slaptafrazę</string>
|
||||
<string name="privacy_show_last_messages">Rodyti paskutines žinutes</string>
|
||||
<string name="stop_chat_to_enable_database_actions">Sustabdykite pokalbius, kad įgalinti duomenų bazės veiksmus.</string>
|
||||
<string name="settings_section_title_support">PALAIKYKITE SIMPLEX CHAT</string>
|
||||
<string name="receipts_section_description_1">Jų galima nepaisyti kontaktų ir grupių nustatymuose.</string>
|
||||
<string name="enable_automatic_deletion_message">Šis veiksmas negali būti atšauktas - žinutės išsiųstos ir gautos anksčiau nei pasirinkta bus ištrintos. Tai gali užtrukti kelias minutes.</string>
|
||||
|
||||
@@ -740,7 +740,6 @@
|
||||
<string name="restart_the_app_to_create_a_new_chat_profile">Start de app opnieuw om een nieuw chatprofiel aan te maken.</string>
|
||||
<string name="you_must_use_the_most_recent_version_of_database">U mag ALLEEN de meest recente versie van uw chat-database op één apparaat gebruiken, anders ontvangt u mogelijk geen berichten meer van sommige contacten.</string>
|
||||
<string name="restart_the_app_to_use_imported_chat_database">Start de app opnieuw om de geïmporteerde chat database te gebruiken.</string>
|
||||
<string name="stop_chat_to_enable_database_actions">Stop de chat om database acties mogelijk te maken.</string>
|
||||
<string name="delete_files_and_media_desc">Deze actie kan niet ongedaan worden gemaakt, alle ontvangen en verzonden bestanden en media worden verwijderd. Foto\'s met een lage resolutie blijven behouden.</string>
|
||||
<string name="remove_passphrase_from_keychain">Wachtwoord verwijderen uit Keychain\?</string>
|
||||
<string name="remove_passphrase">Verwijderen</string>
|
||||
|
||||
@@ -562,7 +562,6 @@
|
||||
<string name="restart_the_app_to_create_a_new_chat_profile">Uruchom ponownie aplikację, aby utworzyć nowy profil czatu.</string>
|
||||
<string name="save_passphrase_in_keychain">Zapisz hasło w Keystore</string>
|
||||
<string name="chat_item_ttl_seconds">%s sekund(y)</string>
|
||||
<string name="stop_chat_to_enable_database_actions">Zatrzymaj czat, aby umożliwić działania na bazie danych.</string>
|
||||
<string name="enable_automatic_deletion_message">Tego działania nie można cofnąć - wiadomości wysłane i odebrane wcześniej niż wybrane zostaną usunięte. Może to potrwać kilka minut.</string>
|
||||
<string name="delete_chat_profile_action_cannot_be_undone_warning">Tego działania nie można cofnąć - Twój profil, kontakty, wiadomości i pliki zostaną nieodwracalnie utracone.</string>
|
||||
<string name="messages_section_description">To ustawienie dotyczy wiadomości Twojego bieżącego profilu czatu</string>
|
||||
|
||||
@@ -853,7 +853,6 @@
|
||||
<string name="settings_section_title_socks">PROXY SOCKS</string>
|
||||
<string name="database_backup_can_be_restored">A tentativa de alterar a senha do banco de dados não foi concluída.</string>
|
||||
<string name="stop_chat_to_export_import_or_delete_chat_database">Pare o bate-papo para exportar, importar ou excluir o banco de dados do chat. Você não poderá receber e enviar mensagens enquanto o chat estiver interrompido.</string>
|
||||
<string name="stop_chat_to_enable_database_actions">Pare o bate-papo para ativar ações no banco de dados.</string>
|
||||
<string name="chat_item_ttl_seconds">%s segundo(s)</string>
|
||||
<string name="unknown_database_error_with_info">Erro de banco de dados desconhecido: %s</string>
|
||||
<string name="unknown_error">Erro desconhecido</string>
|
||||
|
||||
@@ -760,7 +760,6 @@
|
||||
<string name="group_members_n">%s, %s e %d membros</string>
|
||||
<string name="add_contact_or_create_group">Iniciar nova conversa</string>
|
||||
<string name="la_mode_system">Sistema</string>
|
||||
<string name="stop_chat_to_enable_database_actions">Parar conversa para habilitar ações do banco de dados</string>
|
||||
<string name="group_invitation_tap_to_join">Toque para participar</string>
|
||||
<string name="rcv_group_event_3_members_connected">%s, %s e %s conectado</string>
|
||||
<string name="network_option_tcp_connection_timeout">Tempo esgotado da conexão TCP</string>
|
||||
|
||||
@@ -600,7 +600,6 @@
|
||||
<string name="chat_database_deleted">Данные чата удалены</string>
|
||||
<string name="restart_the_app_to_create_a_new_chat_profile">Перезапустите приложение, чтобы создать новый профиль.</string>
|
||||
<string name="you_must_use_the_most_recent_version_of_database">Используйте самую последнюю версию архива чата и ТОЛЬКО на одном устройстве, иначе Вы можете перестать получать сообщения от некоторых контактов.</string>
|
||||
<string name="stop_chat_to_enable_database_actions">Остановите чат, чтобы разблокировать операции с архивом чата.</string>
|
||||
<string name="delete_files_and_media_for_all_users">Удалить файлы во всех профилях чата</string>
|
||||
<string name="delete_files_and_media_all">Удалить все файлы</string>
|
||||
<string name="delete_files_and_media_question">Удалить файлы и медиа?</string>
|
||||
|
||||
@@ -937,7 +937,6 @@
|
||||
<string name="star_on_github">ติดดาวบน GitHub</string>
|
||||
<string name="switch_verb">เปลี่ยน</string>
|
||||
<string name="callstate_starting">กำลังเริ่มต้น…</string>
|
||||
<string name="stop_chat_to_enable_database_actions">หยุดการแชทเพื่อเปิดใช้งานการดำเนินการกับฐานข้อมูล</string>
|
||||
<string name="stop_chat_to_export_import_or_delete_chat_database">หยุดแชทเพื่อส่งออก นำเข้า หรือลบฐานข้อมูลแชท คุณจะไม่สามารถรับและส่งข้อความได้ในขณะที่การแชทหยุดลง</string>
|
||||
<string name="v4_6_audio_video_calls_descr">รองรับบลูทูธและการปรับปรุงอื่นๆ</string>
|
||||
<string name="stop_sharing_address">หยุดแชร์ที่อยู่ไหม\?</string>
|
||||
|
||||
@@ -1034,7 +1034,6 @@
|
||||
<string name="stop_file__action">Dosyayı durdur</string>
|
||||
<string name="error_alert_title">Hata</string>
|
||||
<string name="create_another_profile_button">ProfilProfil oluştur</string>
|
||||
<string name="stop_chat_to_enable_database_actions">Veri tabanı eylemlerini etkinleştirmek için sohbeti durdur.</string>
|
||||
<string name="stop_snd_file__title">Dosya göndermeyi durdur?</string>
|
||||
<string name="auth_stop_chat">Sohbeti durdur</string>
|
||||
<string name="connect_use_current_profile">Mevcut profili kullan</string>
|
||||
|
||||
@@ -899,7 +899,6 @@
|
||||
<string name="enable_lock">Увімкнути блокування</string>
|
||||
<string name="passcode_not_changed">Пароль не змінено!</string>
|
||||
<string name="change_lock_mode">Змінити режим блокування</string>
|
||||
<string name="stop_chat_to_enable_database_actions">Зупиніть чат, щоб увімкнути дії з базою даних.</string>
|
||||
<string name="restart_the_app_to_create_a_new_chat_profile">Перезапустіть додаток, щоб створити новий профіль чату.</string>
|
||||
<string name="delete_files_and_media_for_all_users">Видалити файли для всіх профілів чату</string>
|
||||
<string name="delete_files_and_media_question">Видалити файли та медіа?</string>
|
||||
|
||||
@@ -799,7 +799,6 @@
|
||||
<string name="prohibit_direct_messages">禁止向成员发送私信。</string>
|
||||
<string name="protect_app_screen">保护应用程序屏幕</string>
|
||||
<string name="settings_section_title_themes">主题</string>
|
||||
<string name="stop_chat_to_enable_database_actions">停止聊天以启用数据库操作。</string>
|
||||
<string name="chat_item_ttl_seconds">%s 秒</string>
|
||||
<string name="alert_message_no_group">该群已不存在。</string>
|
||||
<string name="group_invitation_tap_to_join">点击加入</string>
|
||||
|
||||
@@ -119,7 +119,6 @@
|
||||
<string name="chat_is_stopped">聊天室已停止運作</string>
|
||||
<string name="stop_chat_confirmation">停止</string>
|
||||
<string name="chat_database_deleted">已刪除數據庫的對話內容</string>
|
||||
<string name="stop_chat_to_enable_database_actions">停止聊天室以啟用數據庫功能。</string>
|
||||
<string name="change_database_passphrase_question">修改數據庫密碼?</string>
|
||||
<string name="leave_group_question">確定要退出群組?</string>
|
||||
<string name="leave_group_button">退出</string>
|
||||
|
||||
@@ -1472,7 +1472,7 @@ updateGroupPreferences db User {userId} g@GroupInfo {groupId, groupProfile = p}
|
||||
)
|
||||
|]
|
||||
(ps, currentTs, userId, groupId)
|
||||
pure (g :: GroupInfo) {groupProfile = p {groupPreferences = Just ps}}
|
||||
pure (g :: GroupInfo) {groupProfile = p {groupPreferences = Just ps}, fullGroupPreferences = mergeGroupPreferences $ Just ps}
|
||||
|
||||
updateGroupProfileFromMember :: DB.Connection -> User -> GroupInfo -> Profile -> ExceptT StoreError IO GroupInfo
|
||||
updateGroupProfileFromMember db user g@GroupInfo {groupId} Profile {displayName = n, fullName = fn, image = img} = do
|
||||
|
||||
@@ -857,6 +857,10 @@ testBusinessUpdateProfiles = testChat4 businessProfile aliceProfile bobProfile c
|
||||
cath <## "updated group preferences:"
|
||||
cath <## "Voice messages: on"
|
||||
]
|
||||
biz #$> ("/_get chat #1 count=1", chat, [(1, "Voice messages: on")])
|
||||
alice #$> ("/_get chat #1 count=1", chat, [(0, "Voice messages: on")])
|
||||
bob #$> ("/_get chat #1 count=1", chat, [(0, "Voice messages: on")])
|
||||
cath #$> ("/_get chat #1 count=1", chat, [(0, "Voice messages: on")])
|
||||
|
||||
testPlanAddressOkKnown :: HasCallStack => FilePath -> IO ()
|
||||
testPlanAddressOkKnown =
|
||||
|
||||
Reference in New Issue
Block a user