From 8929d15df0680b08da856d68085f798dfbd58b44 Mon Sep 17 00:00:00 2001 From: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com> Date: Tue, 21 Mar 2023 18:15:48 +0300 Subject: [PATCH] ios: ability to specify welcome message in a group (#2041) * ios: ability to specify welcome message in a group * update state in model --- .../Views/Chat/Group/GroupChatInfoView.swift | 13 +++ .../Views/Chat/Group/GroupWelcomeView.swift | 84 +++++++++++++++++++ .../Views/UserSettings/SMPServersView.swift | 16 ++++ apps/ios/SimpleX.xcodeproj/project.pbxproj | 4 + 4 files changed, 117 insertions(+) create mode 100644 apps/ios/Shared/Views/Chat/Group/GroupWelcomeView.swift diff --git a/apps/ios/Shared/Views/Chat/Group/GroupChatInfoView.swift b/apps/ios/Shared/Views/Chat/Group/GroupChatInfoView.swift index 569be904ab..b13e9d7ce5 100644 --- a/apps/ios/Shared/Views/Chat/Group/GroupChatInfoView.swift +++ b/apps/ios/Shared/Views/Chat/Group/GroupChatInfoView.swift @@ -45,6 +45,7 @@ struct GroupChatInfoView: View { Section { if groupInfo.canEdit { editGroupButton() + addOrEditWelcomeMessage() } groupPreferencesButton($groupInfo) } header: { @@ -215,6 +216,18 @@ struct GroupChatInfoView: View { } } + private func addOrEditWelcomeMessage() -> some View { + NavigationLink { + GroupWelcomeView(groupId: groupInfo.groupId, groupInfo: $groupInfo) + .navigationTitle("Welcome message") + .navigationBarTitleDisplayMode(.large) + } label: { + groupInfo.groupProfile.description == nil + ? Label("Add welcome message", systemImage: "plus.bubble.fill") + : Label("Welcome message", systemImage: "plus.bubble.fill") + } + } + private func deleteGroupButton() -> some View { Button(role: .destructive) { alert = .deleteGroupAlert diff --git a/apps/ios/Shared/Views/Chat/Group/GroupWelcomeView.swift b/apps/ios/Shared/Views/Chat/Group/GroupWelcomeView.swift new file mode 100644 index 0000000000..7aa372d5dc --- /dev/null +++ b/apps/ios/Shared/Views/Chat/Group/GroupWelcomeView.swift @@ -0,0 +1,84 @@ +// +// GroupWelcomeView.swift +// SimpleX (iOS) +// +// Created by Avently on 21/03/2022. +// Copyright © 2023 SimpleX Chat. All rights reserved. +// + +import SwiftUI +import SimpleXChat + +struct GroupWelcomeView: View { + @Environment(\.dismiss) var dismiss: DismissAction + @EnvironmentObject private var m: ChatModel + var groupId: Int64 + @Binding var groupInfo: GroupInfo + @State private var welcomeText: String = "" + @FocusState private var keyboardVisible: Bool + @State private var showSaveDialog = false + + var body: some View { + List { + Section { + TextEditor(text: $welcomeText) + .focused($keyboardVisible) + .padding(.horizontal, -5) + .padding(.top, -8) + .frame(height: 90, alignment: .topLeading) + .frame(maxWidth: .infinity, alignment: .leading) + } + Section { + saveButton() + } + } + .onAppear { + welcomeText = groupInfo.groupProfile.description ?? "" + } + .modifier(BackButton { + if welcomeText == groupInfo.groupProfile.description || (welcomeText == "" && groupInfo.groupProfile.description == nil) { + dismiss() + } else { + showSaveDialog = true + } + }) + .confirmationDialog("Save welcome message?", isPresented: $showSaveDialog) { + Button("Save and update group profile") { + save() + dismiss() + } + Button("Exit without saving") { dismiss() } + } + } + + @ViewBuilder private func saveButton() -> some View { + Button("Save and update group profile") { + save() + } + .disabled(welcomeText == groupInfo.groupProfile.description || (welcomeText == "" && groupInfo.groupProfile.description == nil)) + } + + private func save() { + Task { + do { + var welcome: String? = welcomeText.trimmingCharacters(in: .whitespacesAndNewlines) + if welcome?.count == 0 { + welcome = nil + } + var groupProfileUpdated = groupInfo.groupProfile + groupProfileUpdated.description = welcome + groupInfo = try await apiUpdateGroup(groupId, groupProfileUpdated) + m.updateGroup(groupInfo) + welcomeText = welcome ?? "" + } catch let error { + logger.error("apiUpdateGroup error: \(responseError(error))") + } + } + } +} + +struct GroupWelcomeView_Previews: PreviewProvider { + static var previews: some View { + GroupWelcomeView(groupId: 1, groupInfo: Binding.constant(GroupInfo.sampleData)) + } +} diff --git a/apps/ios/Shared/Views/UserSettings/SMPServersView.swift b/apps/ios/Shared/Views/UserSettings/SMPServersView.swift index 7cea87cb6a..ab6b954779 100644 --- a/apps/ios/Shared/Views/UserSettings/SMPServersView.swift +++ b/apps/ios/Shared/Views/UserSettings/SMPServersView.swift @@ -12,6 +12,7 @@ import SimpleXChat private let howToUrl = URL(string: "https://github.com/simplex-chat/simplex-chat/blob/stable/docs/SERVER.md")! struct SMPServersView: View { + @Environment(\.dismiss) var dismiss: DismissAction @EnvironmentObject private var m: ChatModel @Environment(\.editMode) private var editMode @State private var servers = ChatModel.shared.userSMPServers ?? [] @@ -20,6 +21,7 @@ struct SMPServersView: View { @State private var showScanSMPServer = false @State private var testing = false @State private var alert: SMPServerAlert? = nil + @State private var showSaveDialog = false var body: some View { ZStack { @@ -87,6 +89,20 @@ struct SMPServersView: View { .sheet(isPresented: $showScanSMPServer) { ScanSMPServer(servers: $servers) } + .modifier(BackButton { + if saveDisabled { + dismiss() + } else { + showSaveDialog = true + } + }) + .confirmationDialog("Save servers?", isPresented: $showSaveDialog) { + Button("Save") { + saveSMPServers() + dismiss() + } + Button("Exit without saving") { dismiss() } + } .alert(item: $alert) { a in switch a { case let .testsFailed(fs): diff --git a/apps/ios/SimpleX.xcodeproj/project.pbxproj b/apps/ios/SimpleX.xcodeproj/project.pbxproj index d0e3e65615..0c8ba46dfb 100644 --- a/apps/ios/SimpleX.xcodeproj/project.pbxproj +++ b/apps/ios/SimpleX.xcodeproj/project.pbxproj @@ -13,6 +13,7 @@ 1841594C978674A7B42EF0C0 /* AnimatedImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1841511920742C6E152E469F /* AnimatedImageView.swift */; }; 18415B0585EB5A9A0A7CA8CD /* PressedButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18415A7F0F189D87DEFEABCA /* PressedButtonStyle.swift */; }; 18415C6C56DBCEC2CBBD2F11 /* WebRTCClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18415323A4082FC92887F906 /* WebRTCClient.swift */; }; + 18415FEFE153C5920BFB7828 /* GroupWelcomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1841516F0CE5992B0EDFB377 /* GroupWelcomeView.swift */; }; 3C71477A281C0F6800CB4D4B /* www in Resources */ = {isa = PBXBuildFile; fileRef = 3C714779281C0F6800CB4D4B /* www */; }; 3C8C548928133C84000A3EC7 /* PasteToConnectView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C8C548828133C84000A3EC7 /* PasteToConnectView.swift */; }; 3CDBCF4227FAE51000354CDD /* ComposeLinkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CDBCF4127FAE51000354CDD /* ComposeLinkView.swift */; }; @@ -231,6 +232,7 @@ /* Begin PBXFileReference section */ 1841511920742C6E152E469F /* AnimatedImageView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnimatedImageView.swift; sourceTree = ""; }; + 1841516F0CE5992B0EDFB377 /* GroupWelcomeView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupWelcomeView.swift; sourceTree = ""; }; 18415323A4082FC92887F906 /* WebRTCClient.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebRTCClient.swift; sourceTree = ""; }; 18415835CBD939A9ABDC108A /* UserPicker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserPicker.swift; sourceTree = ""; }; 18415845648CA4F5A8BCA272 /* UserProfilesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserProfilesView.swift; sourceTree = ""; }; @@ -796,6 +798,7 @@ 647F090D288EA27B00644C40 /* GroupMemberInfoView.swift */, 5C9C2DA42894777E00CC63B1 /* GroupProfileView.swift */, 6448BBB528FA9D56000D2AB9 /* GroupLinkView.swift */, + 1841516F0CE5992B0EDFB377 /* GroupWelcomeView.swift */, ); path = Group; sourceTree = ""; @@ -1126,6 +1129,7 @@ 1841560FD1CD447955474C1D /* UserProfilesView.swift in Sources */, 18415C6C56DBCEC2CBBD2F11 /* WebRTCClient.swift in Sources */, 184152CEF68D2336FC2EBCB0 /* CallViewRenderers.swift in Sources */, + 18415FEFE153C5920BFB7828 /* GroupWelcomeView.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; };