ios: add group members when group is created (#857)

* ios: add group members when group is created

* refactor

* more refactor
This commit is contained in:
Evgeny Poberezkin
2022-07-30 18:46:10 +01:00
committed by GitHub
parent 4f4935256c
commit 1b8c55a0a3
11 changed files with 86 additions and 57 deletions

View File

@@ -73,9 +73,7 @@ struct ChatView: View {
}
}
}
.onTapGesture {
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
.onTapGesture { hideKeyboard() }
}
}

View File

@@ -14,13 +14,15 @@ struct AddGroupMembersView: View {
@Environment(\.dismiss) var dismiss: DismissAction
var chat: Chat
var groupInfo: GroupInfo
@State var membersToAdd: [Contact]
var membersToAdd: [Contact]
var showSkip: Bool = false
var addedMembersCb: ((Set<Int64>) -> Void)? = nil
@State private var selectedContacts = Set<Int64>()
@State private var selectedRole: GroupMemberRole = .admin
var body: some View {
NavigationView {
List {
let v = List {
ChatInfoToolbar(chat: chat, imageSize: 48)
.frame(maxWidth: .infinity, alignment: .center)
.listRowBackground(Color.clear)
@@ -58,7 +60,20 @@ struct AddGroupMembersView: View {
}
}
}
.navigationBarHidden(true)
if (showSkip) {
v.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
if showSkip {
Button ("Skip") {
if let cb = addedMembersCb { cb(selectedContacts) }
}
}
}
}
} else {
v.navigationBarHidden(true)
}
}
.frame(maxHeight: .infinity, alignment: .top)
}
@@ -70,6 +85,7 @@ struct AddGroupMembersView: View {
await addMember(groupId: chat.chatInfo.apiId, contactId: contactId, memberRole: selectedRole)
}
await MainActor.run { dismiss() }
if let cb = addedMembersCb { cb(selectedContacts) }
}
} label: {
HStack {

View File

@@ -35,19 +35,6 @@ struct GroupChatInfoView: View {
groupInfoHeader()
.listRowBackground(Color.clear)
if groupInfo.canEdit {
Section {
Button {
showGroupProfile = true
} label: {
Label("Edit group profile", systemImage: "pencil")
}
}
.sheet(isPresented: $showGroupProfile) {
GroupProfileView(groupId: groupInfo.apiId, groupProfile: groupInfo.groupProfile)
}
}
Section("\(members.count + 1) members") {
if groupInfo.canAddMembers {
addMembersButton()
@@ -63,8 +50,14 @@ struct GroupChatInfoView: View {
.sheet(item: $selectedMember) { member in
GroupMemberInfoView(groupInfo: groupInfo, member: member)
}
.sheet(isPresented: $showGroupProfile) {
GroupProfileView(groupId: groupInfo.apiId, groupProfile: groupInfo.groupProfile)
}
Section {
if groupInfo.canEdit {
editGroupButton()
}
clearChatButton()
if groupInfo.canDelete {
deleteGroupButton()
@@ -156,6 +149,14 @@ struct GroupChatInfoView: View {
}
}
func editGroupButton() -> some View {
Button {
showGroupProfile = true
} label: {
Label("Edit group profile", systemImage: "pencil")
}
}
func deleteGroupButton() -> some View {
Button(role: .destructive) {
alert = .deleteGroupAlert

View File

@@ -24,7 +24,7 @@ struct GroupProfileView: View {
var body: some View {
return VStack(alignment: .leading) {
Text("Group profile is stored on members devices.\nSimpleX servers cannot see group profile.")
Text("Group profile is stored on members' devices, not on the servers.")
.padding(.bottom)
ZStack(alignment: .center) {
@@ -59,7 +59,7 @@ struct GroupProfileView: View {
profileNameTextEdit("Group full name (optional)", $groupProfile.fullName)
HStack(spacing: 20) {
Button("Cancel") { dismiss() }
Button("Save") { saveProfile() }
Button("Save group profile") { saveProfile() }
.disabled(groupProfile.displayName == "" || !validDisplayName(groupProfile.displayName))
}
}
@@ -105,6 +105,8 @@ struct GroupProfileView: View {
message: Text("\(saveGroupError ?? "Unexpected error")")
)
}
.contentShape(Rectangle())
.onTapGesture { hideKeyboard() }
}
func profileNameTextEdit(_ label: String, _ name: Binding<String>) -> some View {

View File

@@ -73,8 +73,8 @@ struct ChatPreviewView: View {
}
@ViewBuilder private func groupInactiveIcon() -> some View {
Image(systemName: "minus.circle.fill")
.foregroundColor(.red)
Image(systemName: "multiply.circle.fill")
.foregroundColor(.secondary)
.background(Circle().foregroundColor(Color(uiColor: .systemBackground)))
}

View File

@@ -10,8 +10,10 @@ import SwiftUI
import SimpleXChat
struct AddGroupView: View {
@Binding var openedSheet: NewChatAction?
@EnvironmentObject var m: ChatModel
@Environment(\.dismiss) var dismiss: DismissAction
@State private var chat: Chat?
@State private var groupInfo: GroupInfo?
@State private var profile = GroupProfile(displayName: "", fullName: "")
@FocusState private var focusDisplayName
@FocusState private var focusFullName
@@ -21,6 +23,22 @@ struct AddGroupView: View {
@State private var chosenImage: UIImage? = nil
var body: some View {
if let chat = chat, let groupInfo = groupInfo {
AddGroupMembersView(chat: chat,
groupInfo: groupInfo,
membersToAdd: filterMembersToAdd([]),
showSkip: true) { _ in
dismiss()
DispatchQueue.main.async {
m.chatId = groupInfo.id
}
}
} else {
createGroupView()
}
}
func createGroupView() -> some View {
VStack(alignment: .leading) {
Text("Create secret group")
.font(.largeTitle)
@@ -129,14 +147,15 @@ struct AddGroupView: View {
func createGroup() {
hideKeyboard()
do {
let groupInfo = try apiNewGroup(profile)
m.addChat(Chat(chatInfo: .group(groupInfo: groupInfo), chatItems: []))
openedSheet = nil
DispatchQueue.main.async {
m.chatId = groupInfo.id
let gInfo = try apiNewGroup(profile)
let c = Chat(chatInfo: .group(groupInfo: gInfo), chatItems: [])
m.addChat(c)
withAnimation {
groupInfo = gInfo
chat = c
}
} catch {
openedSheet = nil
dismiss()
AlertManager.shared.showAlert(
Alert(
title: Text("Error creating group"),
@@ -146,18 +165,17 @@ struct AddGroupView: View {
}
}
func hideKeyboard() {
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
func canCreateProfile() -> Bool {
profile.displayName != "" && validDisplayName(profile.displayName)
}
}
func hideKeyboard() {
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
struct AddGroupView_Previews: PreviewProvider {
static var previews: some View {
@State var openedSheet: NewChatAction? = nil
return AddGroupView(openedSheet: $openedSheet)
AddGroupView()
}
}

View File

@@ -39,9 +39,9 @@ struct NewChatButton: View {
.sheet(item: $actionSheet) { sheet in
switch sheet {
case .createLink: AddContactView(connReqInvitation: connReq)
case .pasteLink: PasteToConnectView(openedSheet: $actionSheet)
case .scanQRCode: ScanToConnectView(openedSheet: $actionSheet)
case .createGroup: AddGroupView(openedSheet: $actionSheet)
case .pasteLink: PasteToConnectView()
case .scanQRCode: ScanToConnectView()
case .createGroup: AddGroupView()
}
}
}
@@ -64,12 +64,12 @@ enum ConnReqType: Equatable {
case invitation
}
func connectViaLink(_ connectionLink: String, _ openedSheet: Binding<NewChatAction?>? = nil) {
func connectViaLink(_ connectionLink: String, _ dismiss: DismissAction? = nil) {
Task {
do {
let res = try await apiConnect(connReq: connectionLink)
DispatchQueue.main.async {
openedSheet?.wrappedValue = nil
dismiss?()
if let connReqType = res {
connectionReqSentAlert(connReqType)
}
@@ -77,7 +77,7 @@ func connectViaLink(_ connectionLink: String, _ openedSheet: Binding<NewChatActi
} catch {
logger.error("connectViaLink apiConnect error: \(responseError(error))")
DispatchQueue.main.async {
openedSheet?.wrappedValue = nil
dismiss?()
connectionErrorAlert(error)
}
}

View File

@@ -9,7 +9,7 @@
import SwiftUI
struct PasteToConnectView: View {
@Binding var openedSheet: NewChatAction?
@Environment(\.dismiss) var dismiss: DismissAction
@State private var connectionLink: String = ""
var body: some View {
@@ -62,13 +62,12 @@ struct PasteToConnectView: View {
}
private func connect() {
connectViaLink(connectionLink.trimmingCharacters(in: .whitespaces), $openedSheet)
connectViaLink(connectionLink.trimmingCharacters(in: .whitespaces), dismiss)
}
}
struct PasteToConnectView_Previews: PreviewProvider {
static var previews: some View {
@State var openedSheet: NewChatAction? = nil
return PasteToConnectView(openedSheet: $openedSheet)
PasteToConnectView()
}
}

View File

@@ -10,7 +10,7 @@ import SwiftUI
import CodeScanner
struct ScanToConnectView: View {
@Binding var openedSheet: NewChatAction?
@Environment(\.dismiss) var dismiss: DismissAction
var body: some View {
VStack(alignment: .leading) {
@@ -35,17 +35,16 @@ struct ScanToConnectView: View {
func processQRCode(_ resp: Result<ScanResult, ScanError>) {
switch resp {
case let .success(r):
Task { connectViaLink(r.string, $openedSheet) }
Task { connectViaLink(r.string, dismiss) }
case let .failure(e):
logger.error("ConnectContactView.processQRCode QR code error: \(e.localizedDescription)")
openedSheet = nil
dismiss()
}
}
}
struct ConnectContactView_Previews: PreviewProvider {
static var previews: some View {
@State var openedSheet: NewChatAction? = nil
return ScanToConnectView(openedSheet: $openedSheet)
ScanToConnectView()
}
}

View File

@@ -103,10 +103,6 @@ struct CreateProfile: View {
}
}
func hideKeyboard() {
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
func canCreateProfile() -> Bool {
displayName != "" && validDisplayName(displayName)
}

View File

@@ -92,8 +92,8 @@ struct MakeConnection: View {
.sheet(item: $actionSheet) { sheet in
switch sheet {
case .createLink: AddContactView(connReqInvitation: connReq)
case .pasteLink: PasteToConnectView(openedSheet: $actionSheet)
case .scanQRCode: ScanToConnectView(openedSheet: $actionSheet)
case .pasteLink: PasteToConnectView()
case .scanQRCode: ScanToConnectView()
case .createGroup: EmptyView() // TODO refactor / show during onboarding?
}
}