ios, android: show progress indicator on joining group (#3281)
This commit is contained in:
parent
4a8da196ad
commit
4a5fdd3e0e
@ -17,34 +17,45 @@ struct CIGroupInvitationView: View {
|
|||||||
var memberRole: GroupMemberRole
|
var memberRole: GroupMemberRole
|
||||||
var chatIncognito: Bool = false
|
var chatIncognito: Bool = false
|
||||||
@State private var frameWidth: CGFloat = 0
|
@State private var frameWidth: CGFloat = 0
|
||||||
|
@State private var inProgress = false
|
||||||
|
@State private var progressByTimeout = false
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
let action = !chatItem.chatDir.sent && groupInvitation.status == .pending
|
let action = !chatItem.chatDir.sent && groupInvitation.status == .pending
|
||||||
let v = ZStack(alignment: .bottomTrailing) {
|
let v = ZStack(alignment: .bottomTrailing) {
|
||||||
VStack(alignment: .leading) {
|
ZStack {
|
||||||
groupInfoView(action)
|
VStack(alignment: .leading) {
|
||||||
.padding(.horizontal, 2)
|
groupInfoView(action)
|
||||||
.padding(.top, 8)
|
.padding(.horizontal, 2)
|
||||||
.padding(.bottom, 6)
|
.padding(.top, 8)
|
||||||
.overlay(DetermineWidth())
|
.padding(.bottom, 6)
|
||||||
|
.overlay(DetermineWidth())
|
||||||
|
|
||||||
Divider().frame(width: frameWidth)
|
Divider().frame(width: frameWidth)
|
||||||
|
|
||||||
if action {
|
if action {
|
||||||
groupInvitationText()
|
VStack(alignment: .leading, spacing: 2) {
|
||||||
.overlay(DetermineWidth())
|
groupInvitationText()
|
||||||
Text(chatIncognito ? "Tap to join incognito" : "Tap to join")
|
.overlay(DetermineWidth())
|
||||||
.foregroundColor(chatIncognito ? .indigo : .accentColor)
|
Text(chatIncognito ? "Tap to join incognito" : "Tap to join")
|
||||||
.font(.callout)
|
.foregroundColor(inProgress ? .secondary : chatIncognito ? .indigo : .accentColor)
|
||||||
.padding(.trailing, 60)
|
.font(.callout)
|
||||||
.overlay(DetermineWidth())
|
.padding(.trailing, 60)
|
||||||
} else {
|
.overlay(DetermineWidth())
|
||||||
groupInvitationText()
|
}
|
||||||
.padding(.trailing, 60)
|
} else {
|
||||||
.overlay(DetermineWidth())
|
groupInvitationText()
|
||||||
|
.padding(.trailing, 60)
|
||||||
|
.overlay(DetermineWidth())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding(.bottom, 2)
|
||||||
|
|
||||||
|
if progressByTimeout {
|
||||||
|
ProgressView().scaleEffect(2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(.bottom, 2)
|
|
||||||
chatItem.timestampText
|
chatItem.timestampText
|
||||||
.font(.caption)
|
.font(.caption)
|
||||||
.foregroundColor(.secondary)
|
.foregroundColor(.secondary)
|
||||||
@ -55,11 +66,24 @@ struct CIGroupInvitationView: View {
|
|||||||
.cornerRadius(18)
|
.cornerRadius(18)
|
||||||
.textSelection(.disabled)
|
.textSelection(.disabled)
|
||||||
.onPreferenceChange(DetermineWidth.Key.self) { frameWidth = $0 }
|
.onPreferenceChange(DetermineWidth.Key.self) { frameWidth = $0 }
|
||||||
|
.onChange(of: inProgress) { inProgress in
|
||||||
|
if inProgress {
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
||||||
|
progressByTimeout = inProgress
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
progressByTimeout = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if action {
|
if action {
|
||||||
v.onTapGesture {
|
v.onTapGesture {
|
||||||
joinGroup(groupInvitation.groupId)
|
inProgress = true
|
||||||
|
joinGroup(groupInvitation.groupId) {
|
||||||
|
await MainActor.run { inProgress = false }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
.disabled(inProgress)
|
||||||
} else {
|
} else {
|
||||||
v
|
v
|
||||||
}
|
}
|
||||||
@ -67,7 +91,7 @@ struct CIGroupInvitationView: View {
|
|||||||
|
|
||||||
private func groupInfoView(_ action: Bool) -> some View {
|
private func groupInfoView(_ action: Bool) -> some View {
|
||||||
var color: Color
|
var color: Color
|
||||||
if action {
|
if action && !inProgress {
|
||||||
color = chatIncognito ? .indigo : .accentColor
|
color = chatIncognito ? .indigo : .accentColor
|
||||||
} else {
|
} else {
|
||||||
color = Color(uiColor: .tertiaryLabel)
|
color = Color(uiColor: .tertiaryLabel)
|
||||||
|
@ -33,19 +33,32 @@ struct ChatListNavLink: View {
|
|||||||
@State private var showContactConnectionInfo = false
|
@State private var showContactConnectionInfo = false
|
||||||
@State private var showInvalidJSON = false
|
@State private var showInvalidJSON = false
|
||||||
@State private var showDeleteContactActionSheet = false
|
@State private var showDeleteContactActionSheet = false
|
||||||
|
@State private var inProgress = false
|
||||||
|
@State private var progressByTimeout = false
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
switch chat.chatInfo {
|
Group {
|
||||||
case let .direct(contact):
|
switch chat.chatInfo {
|
||||||
contactNavLink(contact)
|
case let .direct(contact):
|
||||||
case let .group(groupInfo):
|
contactNavLink(contact)
|
||||||
groupNavLink(groupInfo)
|
case let .group(groupInfo):
|
||||||
case let .contactRequest(cReq):
|
groupNavLink(groupInfo)
|
||||||
contactRequestNavLink(cReq)
|
case let .contactRequest(cReq):
|
||||||
case let .contactConnection(cConn):
|
contactRequestNavLink(cReq)
|
||||||
contactConnectionNavLink(cConn)
|
case let .contactConnection(cConn):
|
||||||
case let .invalidJSON(json):
|
contactConnectionNavLink(cConn)
|
||||||
invalidJSONPreview(json)
|
case let .invalidJSON(json):
|
||||||
|
invalidJSONPreview(json)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.onChange(of: inProgress) { inProgress in
|
||||||
|
if inProgress {
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
||||||
|
progressByTimeout = inProgress
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
progressByTimeout = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,7 +66,7 @@ struct ChatListNavLink: View {
|
|||||||
NavLinkPlain(
|
NavLinkPlain(
|
||||||
tag: chat.chatInfo.id,
|
tag: chat.chatInfo.id,
|
||||||
selection: $chatModel.chatId,
|
selection: $chatModel.chatId,
|
||||||
label: { ChatPreviewView(chat: chat) }
|
label: { ChatPreviewView(chat: chat, progressByTimeout: Binding.constant(false)) }
|
||||||
)
|
)
|
||||||
.swipeActions(edge: .leading, allowsFullSwipe: true) {
|
.swipeActions(edge: .leading, allowsFullSwipe: true) {
|
||||||
markReadButton()
|
markReadButton()
|
||||||
@ -101,7 +114,7 @@ struct ChatListNavLink: View {
|
|||||||
@ViewBuilder private func groupNavLink(_ groupInfo: GroupInfo) -> some View {
|
@ViewBuilder private func groupNavLink(_ groupInfo: GroupInfo) -> some View {
|
||||||
switch (groupInfo.membership.memberStatus) {
|
switch (groupInfo.membership.memberStatus) {
|
||||||
case .memInvited:
|
case .memInvited:
|
||||||
ChatPreviewView(chat: chat)
|
ChatPreviewView(chat: chat, progressByTimeout: $progressByTimeout)
|
||||||
.frame(height: rowHeights[dynamicTypeSize])
|
.frame(height: rowHeights[dynamicTypeSize])
|
||||||
.swipeActions(edge: .trailing, allowsFullSwipe: true) {
|
.swipeActions(edge: .trailing, allowsFullSwipe: true) {
|
||||||
joinGroupButton()
|
joinGroupButton()
|
||||||
@ -112,12 +125,16 @@ struct ChatListNavLink: View {
|
|||||||
.onTapGesture { showJoinGroupDialog = true }
|
.onTapGesture { showJoinGroupDialog = true }
|
||||||
.confirmationDialog("Group invitation", isPresented: $showJoinGroupDialog, titleVisibility: .visible) {
|
.confirmationDialog("Group invitation", isPresented: $showJoinGroupDialog, titleVisibility: .visible) {
|
||||||
Button(chat.chatInfo.incognito ? "Join incognito" : "Join group") {
|
Button(chat.chatInfo.incognito ? "Join incognito" : "Join group") {
|
||||||
joinGroup(groupInfo.groupId)
|
inProgress = true
|
||||||
|
joinGroup(groupInfo.groupId) {
|
||||||
|
await MainActor.run { inProgress = false }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Button("Delete invitation", role: .destructive) { Task { await deleteChat(chat) } }
|
Button("Delete invitation", role: .destructive) { Task { await deleteChat(chat) } }
|
||||||
}
|
}
|
||||||
|
.disabled(inProgress)
|
||||||
case .memAccepted:
|
case .memAccepted:
|
||||||
ChatPreviewView(chat: chat)
|
ChatPreviewView(chat: chat, progressByTimeout: Binding.constant(false))
|
||||||
.frame(height: rowHeights[dynamicTypeSize])
|
.frame(height: rowHeights[dynamicTypeSize])
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
AlertManager.shared.showAlert(groupInvitationAcceptedAlert())
|
AlertManager.shared.showAlert(groupInvitationAcceptedAlert())
|
||||||
@ -134,7 +151,7 @@ struct ChatListNavLink: View {
|
|||||||
NavLinkPlain(
|
NavLinkPlain(
|
||||||
tag: chat.chatInfo.id,
|
tag: chat.chatInfo.id,
|
||||||
selection: $chatModel.chatId,
|
selection: $chatModel.chatId,
|
||||||
label: { ChatPreviewView(chat: chat) },
|
label: { ChatPreviewView(chat: chat, progressByTimeout: Binding.constant(false)) },
|
||||||
disabled: !groupInfo.ready
|
disabled: !groupInfo.ready
|
||||||
)
|
)
|
||||||
.frame(height: rowHeights[dynamicTypeSize])
|
.frame(height: rowHeights[dynamicTypeSize])
|
||||||
@ -159,7 +176,10 @@ struct ChatListNavLink: View {
|
|||||||
|
|
||||||
private func joinGroupButton() -> some View {
|
private func joinGroupButton() -> some View {
|
||||||
Button {
|
Button {
|
||||||
joinGroup(chat.chatInfo.apiId)
|
inProgress = true
|
||||||
|
joinGroup(chat.chatInfo.apiId) {
|
||||||
|
await MainActor.run { inProgress = false }
|
||||||
|
}
|
||||||
} label: {
|
} label: {
|
||||||
Label("Join", systemImage: chat.chatInfo.incognito ? "theatermasks" : "ipad.and.arrow.forward")
|
Label("Join", systemImage: chat.chatInfo.incognito ? "theatermasks" : "ipad.and.arrow.forward")
|
||||||
}
|
}
|
||||||
@ -419,7 +439,7 @@ func deleteContactConnectionAlert(_ contactConnection: PendingContactConnection,
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func joinGroup(_ groupId: Int64) {
|
func joinGroup(_ groupId: Int64, _ onComplete: @escaping () async -> Void) {
|
||||||
Task {
|
Task {
|
||||||
logger.debug("joinGroup")
|
logger.debug("joinGroup")
|
||||||
do {
|
do {
|
||||||
@ -434,7 +454,9 @@ func joinGroup(_ groupId: Int64) {
|
|||||||
AlertManager.shared.showAlertMsg(title: "No group!", message: "This group no longer exists.")
|
AlertManager.shared.showAlertMsg(title: "No group!", message: "This group no longer exists.")
|
||||||
await deleteGroup()
|
await deleteGroup()
|
||||||
}
|
}
|
||||||
|
await onComplete()
|
||||||
} catch let error {
|
} catch let error {
|
||||||
|
await onComplete()
|
||||||
let a = getErrorAlert(error, "Error joining group")
|
let a = getErrorAlert(error, "Error joining group")
|
||||||
AlertManager.shared.showAlertMsg(title: a.title, message: a.message)
|
AlertManager.shared.showAlertMsg(title: a.title, message: a.message)
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ import SimpleXChat
|
|||||||
struct ChatPreviewView: View {
|
struct ChatPreviewView: View {
|
||||||
@EnvironmentObject var chatModel: ChatModel
|
@EnvironmentObject var chatModel: ChatModel
|
||||||
@ObservedObject var chat: Chat
|
@ObservedObject var chat: Chat
|
||||||
|
@Binding var progressByTimeout: Bool
|
||||||
@Environment(\.colorScheme) var colorScheme
|
@Environment(\.colorScheme) var colorScheme
|
||||||
var darkGreen = Color(red: 0, green: 0.5, blue: 0)
|
var darkGreen = Color(red: 0, green: 0.5, blue: 0)
|
||||||
|
|
||||||
@ -252,6 +253,12 @@ struct ChatPreviewView: View {
|
|||||||
} else {
|
} else {
|
||||||
incognitoIcon(chat.chatInfo.incognito)
|
incognitoIcon(chat.chatInfo.incognito)
|
||||||
}
|
}
|
||||||
|
case .group:
|
||||||
|
if progressByTimeout {
|
||||||
|
ProgressView()
|
||||||
|
} else {
|
||||||
|
incognitoIcon(chat.chatInfo.incognito)
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
incognitoIcon(chat.chatInfo.incognito)
|
incognitoIcon(chat.chatInfo.incognito)
|
||||||
}
|
}
|
||||||
@ -280,30 +287,30 @@ struct ChatPreviewView_Previews: PreviewProvider {
|
|||||||
ChatPreviewView(chat: Chat(
|
ChatPreviewView(chat: Chat(
|
||||||
chatInfo: ChatInfo.sampleData.direct,
|
chatInfo: ChatInfo.sampleData.direct,
|
||||||
chatItems: []
|
chatItems: []
|
||||||
))
|
), progressByTimeout: Binding.constant(false))
|
||||||
ChatPreviewView(chat: Chat(
|
ChatPreviewView(chat: Chat(
|
||||||
chatInfo: ChatInfo.sampleData.direct,
|
chatInfo: ChatInfo.sampleData.direct,
|
||||||
chatItems: [ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent(sndProgress: .complete))]
|
chatItems: [ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent(sndProgress: .complete))]
|
||||||
))
|
), progressByTimeout: Binding.constant(false))
|
||||||
ChatPreviewView(chat: Chat(
|
ChatPreviewView(chat: Chat(
|
||||||
chatInfo: ChatInfo.sampleData.direct,
|
chatInfo: ChatInfo.sampleData.direct,
|
||||||
chatItems: [ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent(sndProgress: .complete))],
|
chatItems: [ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent(sndProgress: .complete))],
|
||||||
chatStats: ChatStats(unreadCount: 11, minUnreadItemId: 0)
|
chatStats: ChatStats(unreadCount: 11, minUnreadItemId: 0)
|
||||||
))
|
), progressByTimeout: Binding.constant(false))
|
||||||
ChatPreviewView(chat: Chat(
|
ChatPreviewView(chat: Chat(
|
||||||
chatInfo: ChatInfo.sampleData.direct,
|
chatInfo: ChatInfo.sampleData.direct,
|
||||||
chatItems: [ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent(sndProgress: .complete), itemDeleted: .deleted(deletedTs: .now))]
|
chatItems: [ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent(sndProgress: .complete), itemDeleted: .deleted(deletedTs: .now))]
|
||||||
))
|
), progressByTimeout: Binding.constant(false))
|
||||||
ChatPreviewView(chat: Chat(
|
ChatPreviewView(chat: Chat(
|
||||||
chatInfo: ChatInfo.sampleData.direct,
|
chatInfo: ChatInfo.sampleData.direct,
|
||||||
chatItems: [ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent(sndProgress: .complete))],
|
chatItems: [ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent(sndProgress: .complete))],
|
||||||
chatStats: ChatStats(unreadCount: 3, minUnreadItemId: 0)
|
chatStats: ChatStats(unreadCount: 3, minUnreadItemId: 0)
|
||||||
))
|
), progressByTimeout: Binding.constant(false))
|
||||||
ChatPreviewView(chat: Chat(
|
ChatPreviewView(chat: Chat(
|
||||||
chatInfo: ChatInfo.sampleData.group,
|
chatInfo: ChatInfo.sampleData.group,
|
||||||
chatItems: [ChatItem.getSample(1, .directSnd, .now, "Lorem ipsum dolor sit amet, d. consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")],
|
chatItems: [ChatItem.getSample(1, .directSnd, .now, "Lorem ipsum dolor sit amet, d. consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")],
|
||||||
chatStats: ChatStats(unreadCount: 11, minUnreadItemId: 0)
|
chatStats: ChatStats(unreadCount: 11, minUnreadItemId: 0)
|
||||||
))
|
), progressByTimeout: Binding.constant(false))
|
||||||
}
|
}
|
||||||
.previewLayout(.fixed(width: 360, height: 78))
|
.previewLayout(.fixed(width: 360, height: 78))
|
||||||
}
|
}
|
||||||
|
@ -269,8 +269,11 @@ fun ChatView(chatId: String, chatModel: ChatModel, onComposed: suspend (chatId:
|
|||||||
cancelFile = { fileId ->
|
cancelFile = { fileId ->
|
||||||
withApi { chatModel.controller.cancelFile(user, fileId) }
|
withApi { chatModel.controller.cancelFile(user, fileId) }
|
||||||
},
|
},
|
||||||
joinGroup = { groupId ->
|
joinGroup = { groupId, onComplete ->
|
||||||
withApi { chatModel.controller.apiJoinGroup(groupId) }
|
withApi {
|
||||||
|
chatModel.controller.apiJoinGroup(groupId)
|
||||||
|
onComplete.invoke()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
startCall = out@ { media ->
|
startCall = out@ { media ->
|
||||||
withBGApi {
|
withBGApi {
|
||||||
@ -431,7 +434,7 @@ fun ChatLayout(
|
|||||||
deleteMessage: (Long, CIDeleteMode) -> Unit,
|
deleteMessage: (Long, CIDeleteMode) -> Unit,
|
||||||
receiveFile: (Long, Boolean) -> Unit,
|
receiveFile: (Long, Boolean) -> Unit,
|
||||||
cancelFile: (Long) -> Unit,
|
cancelFile: (Long) -> Unit,
|
||||||
joinGroup: (Long) -> Unit,
|
joinGroup: (Long, () -> Unit) -> Unit,
|
||||||
startCall: (CallMediaType) -> Unit,
|
startCall: (CallMediaType) -> Unit,
|
||||||
endCall: () -> Unit,
|
endCall: () -> Unit,
|
||||||
acceptCall: (Contact) -> Unit,
|
acceptCall: (Contact) -> Unit,
|
||||||
@ -720,7 +723,7 @@ fun BoxWithConstraintsScope.ChatItemsList(
|
|||||||
deleteMessage: (Long, CIDeleteMode) -> Unit,
|
deleteMessage: (Long, CIDeleteMode) -> Unit,
|
||||||
receiveFile: (Long, Boolean) -> Unit,
|
receiveFile: (Long, Boolean) -> Unit,
|
||||||
cancelFile: (Long) -> Unit,
|
cancelFile: (Long) -> Unit,
|
||||||
joinGroup: (Long) -> Unit,
|
joinGroup: (Long, () -> Unit) -> Unit,
|
||||||
acceptCall: (Contact) -> Unit,
|
acceptCall: (Contact) -> Unit,
|
||||||
acceptFeature: (Contact, ChatFeature, Int?) -> Unit,
|
acceptFeature: (Contact, ChatFeature, Int?) -> Unit,
|
||||||
openDirectChat: (Long) -> Unit,
|
openDirectChat: (Long) -> Unit,
|
||||||
@ -872,7 +875,7 @@ fun BoxWithConstraintsScope.ChatItemsList(
|
|||||||
) {
|
) {
|
||||||
MemberImage(member)
|
MemberImage(member)
|
||||||
}
|
}
|
||||||
ChatItemView(chat.chatInfo, cItem, composeState, provider, useLinkPreviews = useLinkPreviews, linkMode = linkMode, deleteMessage = deleteMessage, receiveFile = receiveFile, cancelFile = cancelFile, joinGroup = {}, acceptCall = acceptCall, acceptFeature = acceptFeature, openDirectChat = openDirectChat, updateContactStats = updateContactStats, updateMemberStats = updateMemberStats, syncContactConnection = syncContactConnection, syncMemberConnection = syncMemberConnection, findModelChat = findModelChat, findModelMember = findModelMember, scrollToItem = scrollToItem, setReaction = setReaction, showItemDetails = showItemDetails, getConnectedMemberNames = ::getConnectedMemberNames, developerTools = developerTools)
|
ChatItemView(chat.chatInfo, cItem, composeState, provider, useLinkPreviews = useLinkPreviews, linkMode = linkMode, deleteMessage = deleteMessage, receiveFile = receiveFile, cancelFile = cancelFile, joinGroup = { _, _ -> }, acceptCall = acceptCall, acceptFeature = acceptFeature, openDirectChat = openDirectChat, updateContactStats = updateContactStats, updateMemberStats = updateMemberStats, syncContactConnection = syncContactConnection, syncMemberConnection = syncMemberConnection, findModelChat = findModelChat, findModelMember = findModelMember, scrollToItem = scrollToItem, setReaction = setReaction, showItemDetails = showItemDetails, getConnectedMemberNames = ::getConnectedMemberNames, developerTools = developerTools)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -881,7 +884,7 @@ fun BoxWithConstraintsScope.ChatItemsList(
|
|||||||
.padding(start = 8.dp + MEMBER_IMAGE_SIZE + 4.dp, end = if (voiceWithTransparentBack) 12.dp else 66.dp)
|
.padding(start = 8.dp + MEMBER_IMAGE_SIZE + 4.dp, end = if (voiceWithTransparentBack) 12.dp else 66.dp)
|
||||||
.then(swipeableModifier)
|
.then(swipeableModifier)
|
||||||
) {
|
) {
|
||||||
ChatItemView(chat.chatInfo, cItem, composeState, provider, useLinkPreviews = useLinkPreviews, linkMode = linkMode, deleteMessage = deleteMessage, receiveFile = receiveFile, cancelFile = cancelFile, joinGroup = {}, acceptCall = acceptCall, acceptFeature = acceptFeature, openDirectChat = openDirectChat, updateContactStats = updateContactStats, updateMemberStats = updateMemberStats, syncContactConnection = syncContactConnection, syncMemberConnection = syncMemberConnection, findModelChat = findModelChat, findModelMember = findModelMember, scrollToItem = scrollToItem, setReaction = setReaction, showItemDetails = showItemDetails, getConnectedMemberNames = ::getConnectedMemberNames, developerTools = developerTools)
|
ChatItemView(chat.chatInfo, cItem, composeState, provider, useLinkPreviews = useLinkPreviews, linkMode = linkMode, deleteMessage = deleteMessage, receiveFile = receiveFile, cancelFile = cancelFile, joinGroup = { _, _ -> }, acceptCall = acceptCall, acceptFeature = acceptFeature, openDirectChat = openDirectChat, updateContactStats = updateContactStats, updateMemberStats = updateMemberStats, syncContactConnection = syncContactConnection, syncMemberConnection = syncMemberConnection, findModelChat = findModelChat, findModelMember = findModelMember, scrollToItem = scrollToItem, setReaction = setReaction, showItemDetails = showItemDetails, getConnectedMemberNames = ::getConnectedMemberNames, developerTools = developerTools)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -891,7 +894,7 @@ fun BoxWithConstraintsScope.ChatItemsList(
|
|||||||
.padding(start = if (voiceWithTransparentBack) 12.dp else 104.dp, end = 12.dp)
|
.padding(start = if (voiceWithTransparentBack) 12.dp else 104.dp, end = 12.dp)
|
||||||
.then(swipeableModifier)
|
.then(swipeableModifier)
|
||||||
) {
|
) {
|
||||||
ChatItemView(chat.chatInfo, cItem, composeState, provider, useLinkPreviews = useLinkPreviews, linkMode = linkMode, deleteMessage = deleteMessage, receiveFile = receiveFile, cancelFile = cancelFile, joinGroup = {}, acceptCall = acceptCall, acceptFeature = acceptFeature, openDirectChat = openDirectChat, updateContactStats = updateContactStats, updateMemberStats = updateMemberStats, syncContactConnection = syncContactConnection, syncMemberConnection = syncMemberConnection, findModelChat = findModelChat, findModelMember = findModelMember, scrollToItem = scrollToItem, setReaction = setReaction, showItemDetails = showItemDetails, developerTools = developerTools)
|
ChatItemView(chat.chatInfo, cItem, composeState, provider, useLinkPreviews = useLinkPreviews, linkMode = linkMode, deleteMessage = deleteMessage, receiveFile = receiveFile, cancelFile = cancelFile, joinGroup = { _, _ -> }, acceptCall = acceptCall, acceptFeature = acceptFeature, openDirectChat = openDirectChat, updateContactStats = updateContactStats, updateMemberStats = updateMemberStats, syncContactConnection = syncContactConnection, syncMemberConnection = syncMemberConnection, findModelChat = findModelChat, findModelMember = findModelMember, scrollToItem = scrollToItem, setReaction = setReaction, showItemDetails = showItemDetails, developerTools = developerTools)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else { // direct message
|
} else { // direct message
|
||||||
@ -1323,7 +1326,7 @@ fun PreviewChatLayout() {
|
|||||||
deleteMessage = { _, _ -> },
|
deleteMessage = { _, _ -> },
|
||||||
receiveFile = { _, _ -> },
|
receiveFile = { _, _ -> },
|
||||||
cancelFile = {},
|
cancelFile = {},
|
||||||
joinGroup = {},
|
joinGroup = { _, _ -> },
|
||||||
startCall = {},
|
startCall = {},
|
||||||
endCall = {},
|
endCall = {},
|
||||||
acceptCall = { _ -> },
|
acceptCall = { _ -> },
|
||||||
@ -1393,7 +1396,7 @@ fun PreviewGroupChatLayout() {
|
|||||||
deleteMessage = { _, _ -> },
|
deleteMessage = { _, _ -> },
|
||||||
receiveFile = { _, _ -> },
|
receiveFile = { _, _ -> },
|
||||||
cancelFile = {},
|
cancelFile = {},
|
||||||
joinGroup = {},
|
joinGroup = { _, _ -> },
|
||||||
startCall = {},
|
startCall = {},
|
||||||
endCall = {},
|
endCall = {},
|
||||||
acceptCall = { _ -> },
|
acceptCall = { _ -> },
|
||||||
|
@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.*
|
|||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.*
|
import androidx.compose.material.*
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import dev.icerock.moko.resources.compose.stringResource
|
import dev.icerock.moko.resources.compose.stringResource
|
||||||
@ -17,6 +18,7 @@ import chat.simplex.common.ui.theme.*
|
|||||||
import chat.simplex.common.views.helpers.*
|
import chat.simplex.common.views.helpers.*
|
||||||
import chat.simplex.common.model.*
|
import chat.simplex.common.model.*
|
||||||
import chat.simplex.res.MR
|
import chat.simplex.res.MR
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CIGroupInvitationView(
|
fun CIGroupInvitationView(
|
||||||
@ -24,16 +26,26 @@ fun CIGroupInvitationView(
|
|||||||
groupInvitation: CIGroupInvitation,
|
groupInvitation: CIGroupInvitation,
|
||||||
memberRole: GroupMemberRole,
|
memberRole: GroupMemberRole,
|
||||||
chatIncognito: Boolean = false,
|
chatIncognito: Boolean = false,
|
||||||
joinGroup: (Long) -> Unit
|
joinGroup: (Long, () -> Unit) -> Unit
|
||||||
) {
|
) {
|
||||||
val sent = ci.chatDir.sent
|
val sent = ci.chatDir.sent
|
||||||
val action = !sent && groupInvitation.status == CIGroupInvitationStatus.Pending
|
val action = !sent && groupInvitation.status == CIGroupInvitationStatus.Pending
|
||||||
|
val inProgress = remember { mutableStateOf(false) }
|
||||||
|
var progressByTimeout by rememberSaveable { mutableStateOf(false) }
|
||||||
|
LaunchedEffect(inProgress.value) {
|
||||||
|
progressByTimeout = if (inProgress.value) {
|
||||||
|
delay(1000)
|
||||||
|
inProgress.value
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun groupInfoView() {
|
fun groupInfoView() {
|
||||||
val p = groupInvitation.groupProfile
|
val p = groupInvitation.groupProfile
|
||||||
val iconColor =
|
val iconColor =
|
||||||
if (action) if (chatIncognito) Indigo else MaterialTheme.colors.primary
|
if (action && !inProgress.value) if (chatIncognito) Indigo else MaterialTheme.colors.primary
|
||||||
else if (isInDarkTheme()) FileDark else FileLight
|
else if (isInDarkTheme()) FileDark else FileLight
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
@ -70,8 +82,9 @@ fun CIGroupInvitationView(
|
|||||||
val sentColor = CurrentColors.collectAsState().value.appColors.sentMessage
|
val sentColor = CurrentColors.collectAsState().value.appColors.sentMessage
|
||||||
val receivedColor = CurrentColors.collectAsState().value.appColors.receivedMessage
|
val receivedColor = CurrentColors.collectAsState().value.appColors.receivedMessage
|
||||||
Surface(
|
Surface(
|
||||||
modifier = if (action) Modifier.clickable(onClick = {
|
modifier = if (action && !inProgress.value) Modifier.clickable(onClick = {
|
||||||
joinGroup(groupInvitation.groupId)
|
inProgress.value = true
|
||||||
|
joinGroup(groupInvitation.groupId) { inProgress.value = false }
|
||||||
}) else Modifier,
|
}) else Modifier,
|
||||||
shape = RoundedCornerShape(18.dp),
|
shape = RoundedCornerShape(18.dp),
|
||||||
color = if (sent) sentColor else receivedColor,
|
color = if (sent) sentColor else receivedColor,
|
||||||
@ -83,26 +96,45 @@ fun CIGroupInvitationView(
|
|||||||
.padding(start = 8.dp, end = 12.dp),
|
.padding(start = 8.dp, end = 12.dp),
|
||||||
contentAlignment = Alignment.BottomEnd
|
contentAlignment = Alignment.BottomEnd
|
||||||
) {
|
) {
|
||||||
Column(
|
Box(
|
||||||
Modifier
|
contentAlignment = Alignment.Center
|
||||||
.defaultMinSize(minWidth = 220.dp)
|
|
||||||
.padding(bottom = 4.dp),
|
|
||||||
) {
|
) {
|
||||||
groupInfoView()
|
Column(
|
||||||
Column(Modifier.padding(top = 2.dp, start = 5.dp)) {
|
Modifier
|
||||||
Divider(Modifier.fillMaxWidth().padding(bottom = 4.dp))
|
.defaultMinSize(minWidth = 220.dp)
|
||||||
if (action) {
|
.padding(bottom = 4.dp),
|
||||||
groupInvitationText()
|
) {
|
||||||
Text(stringResource(
|
groupInfoView()
|
||||||
if (chatIncognito) MR.strings.group_invitation_tap_to_join_incognito else MR.strings.group_invitation_tap_to_join),
|
Column(Modifier.padding(top = 2.dp, start = 5.dp)) {
|
||||||
color = if (chatIncognito) Indigo else MaterialTheme.colors.primary)
|
Divider(Modifier.fillMaxWidth().padding(bottom = 4.dp))
|
||||||
} else {
|
if (action) {
|
||||||
Box(Modifier.padding(end = 48.dp)) {
|
|
||||||
groupInvitationText()
|
groupInvitationText()
|
||||||
|
Text(
|
||||||
|
stringResource(
|
||||||
|
if (chatIncognito) MR.strings.group_invitation_tap_to_join_incognito else MR.strings.group_invitation_tap_to_join
|
||||||
|
),
|
||||||
|
color = if (inProgress.value)
|
||||||
|
MaterialTheme.colors.secondary
|
||||||
|
else
|
||||||
|
if (chatIncognito) Indigo else MaterialTheme.colors.primary
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Box(Modifier.padding(end = 48.dp)) {
|
||||||
|
groupInvitationText()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (progressByTimeout) {
|
||||||
|
CircularProgressIndicator(
|
||||||
|
Modifier.size(32.dp),
|
||||||
|
color = if (isInDarkTheme()) FileDark else FileLight,
|
||||||
|
strokeWidth = 3.dp
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
ci.timestampText,
|
ci.timestampText,
|
||||||
color = MaterialTheme.colors.secondary,
|
color = MaterialTheme.colors.secondary,
|
||||||
@ -124,7 +156,7 @@ fun PendingCIGroupInvitationViewPreview() {
|
|||||||
ci = ChatItem.getGroupInvitationSample(),
|
ci = ChatItem.getGroupInvitationSample(),
|
||||||
groupInvitation = CIGroupInvitation.getSample(),
|
groupInvitation = CIGroupInvitation.getSample(),
|
||||||
memberRole = GroupMemberRole.Admin,
|
memberRole = GroupMemberRole.Admin,
|
||||||
joinGroup = {}
|
joinGroup = { _, _ -> }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -140,7 +172,7 @@ fun CIGroupInvitationViewAcceptedPreview() {
|
|||||||
ci = ChatItem.getGroupInvitationSample(),
|
ci = ChatItem.getGroupInvitationSample(),
|
||||||
groupInvitation = CIGroupInvitation.getSample(status = CIGroupInvitationStatus.Accepted),
|
groupInvitation = CIGroupInvitation.getSample(status = CIGroupInvitationStatus.Accepted),
|
||||||
memberRole = GroupMemberRole.Admin,
|
memberRole = GroupMemberRole.Admin,
|
||||||
joinGroup = {}
|
joinGroup = { _, _ -> }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -156,7 +188,7 @@ fun CIGroupInvitationViewLongNamePreview() {
|
|||||||
status = CIGroupInvitationStatus.Accepted
|
status = CIGroupInvitationStatus.Accepted
|
||||||
),
|
),
|
||||||
memberRole = GroupMemberRole.Admin,
|
memberRole = GroupMemberRole.Admin,
|
||||||
joinGroup = {}
|
joinGroup = { _, _ -> }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ fun ChatItemView(
|
|||||||
deleteMessage: (Long, CIDeleteMode) -> Unit,
|
deleteMessage: (Long, CIDeleteMode) -> Unit,
|
||||||
receiveFile: (Long, Boolean) -> Unit,
|
receiveFile: (Long, Boolean) -> Unit,
|
||||||
cancelFile: (Long) -> Unit,
|
cancelFile: (Long) -> Unit,
|
||||||
joinGroup: (Long) -> Unit,
|
joinGroup: (Long, () -> Unit) -> Unit,
|
||||||
acceptCall: (Contact) -> Unit,
|
acceptCall: (Contact) -> Unit,
|
||||||
scrollToItem: (Long) -> Unit,
|
scrollToItem: (Long) -> Unit,
|
||||||
acceptFeature: (Contact, ChatFeature, Int?) -> Unit,
|
acceptFeature: (Contact, ChatFeature, Int?) -> Unit,
|
||||||
@ -578,7 +578,7 @@ fun PreviewChatItemView() {
|
|||||||
deleteMessage = { _, _ -> },
|
deleteMessage = { _, _ -> },
|
||||||
receiveFile = { _, _ -> },
|
receiveFile = { _, _ -> },
|
||||||
cancelFile = {},
|
cancelFile = {},
|
||||||
joinGroup = {},
|
joinGroup = { _, _ -> },
|
||||||
acceptCall = { _ -> },
|
acceptCall = { _ -> },
|
||||||
scrollToItem = {},
|
scrollToItem = {},
|
||||||
acceptFeature = { _, _, _ -> },
|
acceptFeature = { _, _, _ -> },
|
||||||
@ -609,7 +609,7 @@ fun PreviewChatItemViewDeletedContent() {
|
|||||||
deleteMessage = { _, _ -> },
|
deleteMessage = { _, _ -> },
|
||||||
receiveFile = { _, _ -> },
|
receiveFile = { _, _ -> },
|
||||||
cancelFile = {},
|
cancelFile = {},
|
||||||
joinGroup = {},
|
joinGroup = { _, _ -> },
|
||||||
acceptCall = { _ -> },
|
acceptCall = { _ -> },
|
||||||
scrollToItem = {},
|
scrollToItem = {},
|
||||||
acceptFeature = { _, _, _ -> },
|
acceptFeature = { _, _, _ -> },
|
||||||
|
@ -12,6 +12,7 @@ import dev.icerock.moko.resources.compose.stringResource
|
|||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.desktop.ui.tooling.preview.Preview
|
import androidx.compose.desktop.ui.tooling.preview.Preview
|
||||||
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.ui.text.AnnotatedString
|
import androidx.compose.ui.text.AnnotatedString
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
@ -44,11 +45,22 @@ fun ChatListNavLinkView(chat: Chat, chatModel: ChatModel) {
|
|||||||
}
|
}
|
||||||
val selectedChat = remember(chat.id) { derivedStateOf { chat.id == ChatModel.chatId.value } }
|
val selectedChat = remember(chat.id) { derivedStateOf { chat.id == ChatModel.chatId.value } }
|
||||||
val showChatPreviews = chatModel.showChatPreviews.value
|
val showChatPreviews = chatModel.showChatPreviews.value
|
||||||
|
val inProgress = remember { mutableStateOf(false) }
|
||||||
|
var progressByTimeout by rememberSaveable { mutableStateOf(false) }
|
||||||
|
LaunchedEffect(inProgress.value) {
|
||||||
|
progressByTimeout = if (inProgress.value) {
|
||||||
|
delay(1000)
|
||||||
|
inProgress.value
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
when (chat.chatInfo) {
|
when (chat.chatInfo) {
|
||||||
is ChatInfo.Direct -> {
|
is ChatInfo.Direct -> {
|
||||||
val contactNetworkStatus = chatModel.contactNetworkStatus(chat.chatInfo.contact)
|
val contactNetworkStatus = chatModel.contactNetworkStatus(chat.chatInfo.contact)
|
||||||
ChatListNavLinkLayout(
|
ChatListNavLinkLayout(
|
||||||
chatLinkPreview = { ChatPreviewView(chat, showChatPreviews, chatModel.draft.value, chatModel.draftChatId.value, chatModel.currentUser.value?.profile?.displayName, contactNetworkStatus, stopped, linkMode) },
|
chatLinkPreview = { ChatPreviewView(chat, showChatPreviews, chatModel.draft.value, chatModel.draftChatId.value, chatModel.currentUser.value?.profile?.displayName, contactNetworkStatus, stopped, linkMode, inProgress = false, progressByTimeout = false) },
|
||||||
click = { directChatAction(chat.chatInfo, chatModel) },
|
click = { directChatAction(chat.chatInfo, chatModel) },
|
||||||
dropdownMenuItems = { ContactMenuItems(chat, chatModel, showMenu, showMarkRead) },
|
dropdownMenuItems = { ContactMenuItems(chat, chatModel, showMenu, showMarkRead) },
|
||||||
showMenu,
|
showMenu,
|
||||||
@ -58,9 +70,9 @@ fun ChatListNavLinkView(chat: Chat, chatModel: ChatModel) {
|
|||||||
}
|
}
|
||||||
is ChatInfo.Group ->
|
is ChatInfo.Group ->
|
||||||
ChatListNavLinkLayout(
|
ChatListNavLinkLayout(
|
||||||
chatLinkPreview = { ChatPreviewView(chat, showChatPreviews, chatModel.draft.value, chatModel.draftChatId.value, chatModel.currentUser.value?.profile?.displayName, null, stopped, linkMode) },
|
chatLinkPreview = { ChatPreviewView(chat, showChatPreviews, chatModel.draft.value, chatModel.draftChatId.value, chatModel.currentUser.value?.profile?.displayName, null, stopped, linkMode, inProgress.value, progressByTimeout) },
|
||||||
click = { groupChatAction(chat.chatInfo.groupInfo, chatModel) },
|
click = { if (!inProgress.value) groupChatAction(chat.chatInfo.groupInfo, chatModel, inProgress) },
|
||||||
dropdownMenuItems = { GroupMenuItems(chat, chat.chatInfo.groupInfo, chatModel, showMenu, showMarkRead) },
|
dropdownMenuItems = { GroupMenuItems(chat, chat.chatInfo.groupInfo, chatModel, showMenu, inProgress, showMarkRead) },
|
||||||
showMenu,
|
showMenu,
|
||||||
stopped,
|
stopped,
|
||||||
selectedChat
|
selectedChat
|
||||||
@ -110,9 +122,9 @@ fun directChatAction(chatInfo: ChatInfo, chatModel: ChatModel) {
|
|||||||
withBGApi { openChat(chatInfo, chatModel) }
|
withBGApi { openChat(chatInfo, chatModel) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun groupChatAction(groupInfo: GroupInfo, chatModel: ChatModel) {
|
fun groupChatAction(groupInfo: GroupInfo, chatModel: ChatModel, inProgress: MutableState<Boolean>? = null) {
|
||||||
when (groupInfo.membership.memberStatus) {
|
when (groupInfo.membership.memberStatus) {
|
||||||
GroupMemberStatus.MemInvited -> acceptGroupInvitationAlertDialog(groupInfo, chatModel)
|
GroupMemberStatus.MemInvited -> acceptGroupInvitationAlertDialog(groupInfo, chatModel, inProgress)
|
||||||
GroupMemberStatus.MemAccepted -> groupInvitationAcceptedAlert()
|
GroupMemberStatus.MemAccepted -> groupInvitationAcceptedAlert()
|
||||||
else -> withBGApi { openChat(ChatInfo.Group(groupInfo), chatModel) }
|
else -> withBGApi { openChat(ChatInfo.Group(groupInfo), chatModel) }
|
||||||
}
|
}
|
||||||
@ -193,10 +205,19 @@ fun ContactMenuItems(chat: Chat, chatModel: ChatModel, showMenu: MutableState<Bo
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun GroupMenuItems(chat: Chat, groupInfo: GroupInfo, chatModel: ChatModel, showMenu: MutableState<Boolean>, showMarkRead: Boolean) {
|
fun GroupMenuItems(
|
||||||
|
chat: Chat,
|
||||||
|
groupInfo: GroupInfo,
|
||||||
|
chatModel: ChatModel,
|
||||||
|
showMenu: MutableState<Boolean>,
|
||||||
|
inProgress: MutableState<Boolean>,
|
||||||
|
showMarkRead: Boolean
|
||||||
|
) {
|
||||||
when (groupInfo.membership.memberStatus) {
|
when (groupInfo.membership.memberStatus) {
|
||||||
GroupMemberStatus.MemInvited -> {
|
GroupMemberStatus.MemInvited -> {
|
||||||
JoinGroupAction(chat, groupInfo, chatModel, showMenu)
|
if (!inProgress.value) {
|
||||||
|
JoinGroupAction(chat, groupInfo, chatModel, showMenu, inProgress)
|
||||||
|
}
|
||||||
if (groupInfo.canDelete) {
|
if (groupInfo.canDelete) {
|
||||||
DeleteGroupAction(chat, groupInfo, chatModel, showMenu)
|
DeleteGroupAction(chat, groupInfo, chatModel, showMenu)
|
||||||
}
|
}
|
||||||
@ -317,8 +338,20 @@ fun DeleteGroupAction(chat: Chat, groupInfo: GroupInfo, chatModel: ChatModel, sh
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun JoinGroupAction(chat: Chat, groupInfo: GroupInfo, chatModel: ChatModel, showMenu: MutableState<Boolean>) {
|
fun JoinGroupAction(
|
||||||
val joinGroup: () -> Unit = { withApi { chatModel.controller.apiJoinGroup(groupInfo.groupId) } }
|
chat: Chat,
|
||||||
|
groupInfo: GroupInfo,
|
||||||
|
chatModel: ChatModel,
|
||||||
|
showMenu: MutableState<Boolean>,
|
||||||
|
inProgress: MutableState<Boolean>
|
||||||
|
) {
|
||||||
|
val joinGroup: () -> Unit = {
|
||||||
|
withApi {
|
||||||
|
inProgress.value = true
|
||||||
|
chatModel.controller.apiJoinGroup(groupInfo.groupId)
|
||||||
|
inProgress.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
ItemAction(
|
ItemAction(
|
||||||
if (chat.chatInfo.incognito) stringResource(MR.strings.join_group_incognito_button) else stringResource(MR.strings.join_group_button),
|
if (chat.chatInfo.incognito) stringResource(MR.strings.join_group_incognito_button) else stringResource(MR.strings.join_group_button),
|
||||||
if (chat.chatInfo.incognito) painterResource(MR.images.ic_theater_comedy_filled) else painterResource(MR.images.ic_login),
|
if (chat.chatInfo.incognito) painterResource(MR.images.ic_theater_comedy_filled) else painterResource(MR.images.ic_login),
|
||||||
@ -558,12 +591,18 @@ fun pendingContactAlertDialog(chatInfo: ChatInfo, chatModel: ChatModel) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun acceptGroupInvitationAlertDialog(groupInfo: GroupInfo, chatModel: ChatModel) {
|
fun acceptGroupInvitationAlertDialog(groupInfo: GroupInfo, chatModel: ChatModel, inProgress: MutableState<Boolean>? = null) {
|
||||||
AlertManager.shared.showAlertDialog(
|
AlertManager.shared.showAlertDialog(
|
||||||
title = generalGetString(MR.strings.join_group_question),
|
title = generalGetString(MR.strings.join_group_question),
|
||||||
text = generalGetString(MR.strings.you_are_invited_to_group_join_to_connect_with_group_members),
|
text = generalGetString(MR.strings.you_are_invited_to_group_join_to_connect_with_group_members),
|
||||||
confirmText = if (groupInfo.membership.memberIncognito) generalGetString(MR.strings.join_group_incognito_button) else generalGetString(MR.strings.join_group_button),
|
confirmText = if (groupInfo.membership.memberIncognito) generalGetString(MR.strings.join_group_incognito_button) else generalGetString(MR.strings.join_group_button),
|
||||||
onConfirm = { withApi { chatModel.controller.apiJoinGroup(groupInfo.groupId) } },
|
onConfirm = {
|
||||||
|
withApi {
|
||||||
|
inProgress?.value = true
|
||||||
|
chatModel.controller.apiJoinGroup(groupInfo.groupId)
|
||||||
|
inProgress?.value = false
|
||||||
|
}
|
||||||
|
},
|
||||||
dismissText = generalGetString(MR.strings.delete_verb),
|
dismissText = generalGetString(MR.strings.delete_verb),
|
||||||
onDismiss = { deleteGroup(groupInfo, chatModel) }
|
onDismiss = { deleteGroup(groupInfo, chatModel) }
|
||||||
)
|
)
|
||||||
@ -680,7 +719,9 @@ fun PreviewChatListNavLinkDirect() {
|
|||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
stopped = false,
|
stopped = false,
|
||||||
linkMode = SimplexLinkMode.DESCRIPTION
|
linkMode = SimplexLinkMode.DESCRIPTION,
|
||||||
|
inProgress = false,
|
||||||
|
progressByTimeout = false
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
click = {},
|
click = {},
|
||||||
@ -721,7 +762,9 @@ fun PreviewChatListNavLinkGroup() {
|
|||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
stopped = false,
|
stopped = false,
|
||||||
linkMode = SimplexLinkMode.DESCRIPTION
|
linkMode = SimplexLinkMode.DESCRIPTION,
|
||||||
|
inProgress = false,
|
||||||
|
progressByTimeout = false
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
click = {},
|
click = {},
|
||||||
|
@ -37,7 +37,9 @@ fun ChatPreviewView(
|
|||||||
currentUserProfileDisplayName: String?,
|
currentUserProfileDisplayName: String?,
|
||||||
contactNetworkStatus: NetworkStatus?,
|
contactNetworkStatus: NetworkStatus?,
|
||||||
stopped: Boolean,
|
stopped: Boolean,
|
||||||
linkMode: SimplexLinkMode
|
linkMode: SimplexLinkMode,
|
||||||
|
inProgress: Boolean,
|
||||||
|
progressByTimeout: Boolean
|
||||||
) {
|
) {
|
||||||
val cInfo = chat.chatInfo
|
val cInfo = chat.chatInfo
|
||||||
|
|
||||||
@ -135,7 +137,12 @@ fun ChatPreviewView(
|
|||||||
}
|
}
|
||||||
is ChatInfo.Group ->
|
is ChatInfo.Group ->
|
||||||
when (cInfo.groupInfo.membership.memberStatus) {
|
when (cInfo.groupInfo.membership.memberStatus) {
|
||||||
GroupMemberStatus.MemInvited -> chatPreviewTitleText(if (chat.chatInfo.incognito) Indigo else MaterialTheme.colors.primary)
|
GroupMemberStatus.MemInvited -> chatPreviewTitleText(
|
||||||
|
if (inProgress)
|
||||||
|
MaterialTheme.colors.secondary
|
||||||
|
else
|
||||||
|
if (chat.chatInfo.incognito) Indigo else MaterialTheme.colors.primary
|
||||||
|
)
|
||||||
GroupMemberStatus.MemAccepted -> chatPreviewTitleText(MaterialTheme.colors.secondary)
|
GroupMemberStatus.MemAccepted -> chatPreviewTitleText(MaterialTheme.colors.secondary)
|
||||||
else -> chatPreviewTitleText()
|
else -> chatPreviewTitleText()
|
||||||
}
|
}
|
||||||
@ -194,6 +201,17 @@ fun ChatPreviewView(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun progressView() {
|
||||||
|
CircularProgressIndicator(
|
||||||
|
Modifier
|
||||||
|
.padding(horizontal = 2.dp)
|
||||||
|
.size(15.dp),
|
||||||
|
color = MaterialTheme.colors.secondary,
|
||||||
|
strokeWidth = 1.5.dp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun chatStatusImage() {
|
fun chatStatusImage() {
|
||||||
if (cInfo is ChatInfo.Direct) {
|
if (cInfo is ChatInfo.Direct) {
|
||||||
@ -213,17 +231,17 @@ fun ChatPreviewView(
|
|||||||
)
|
)
|
||||||
|
|
||||||
else ->
|
else ->
|
||||||
CircularProgressIndicator(
|
progressView()
|
||||||
Modifier
|
|
||||||
.padding(horizontal = 2.dp)
|
|
||||||
.size(15.dp),
|
|
||||||
color = MaterialTheme.colors.secondary,
|
|
||||||
strokeWidth = 1.5.dp
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
IncognitoIcon(chat.chatInfo.incognito)
|
IncognitoIcon(chat.chatInfo.incognito)
|
||||||
}
|
}
|
||||||
|
} else if (cInfo is ChatInfo.Group) {
|
||||||
|
if (progressByTimeout) {
|
||||||
|
progressView()
|
||||||
|
} else {
|
||||||
|
IncognitoIcon(chat.chatInfo.incognito)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
IncognitoIcon(chat.chatInfo.incognito)
|
IncognitoIcon(chat.chatInfo.incognito)
|
||||||
}
|
}
|
||||||
@ -351,6 +369,6 @@ fun unreadCountStr(n: Int): String {
|
|||||||
@Composable
|
@Composable
|
||||||
fun PreviewChatPreviewView() {
|
fun PreviewChatPreviewView() {
|
||||||
SimpleXTheme {
|
SimpleXTheme {
|
||||||
ChatPreviewView(Chat.sampleData, true, null, null, "", contactNetworkStatus = NetworkStatus.Connected(), stopped = false, linkMode = SimplexLinkMode.DESCRIPTION)
|
ChatPreviewView(Chat.sampleData, true, null, null, "", contactNetworkStatus = NetworkStatus.Connected(), stopped = false, linkMode = SimplexLinkMode.DESCRIPTION, inProgress = false, progressByTimeout = false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user