mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2024-12-17 17:20:21 +01:00
updates to sheet
This commit is contained in:
@@ -46,6 +46,7 @@ struct ChatListNavLink: View {
|
||||
@Environment(\.dynamicTypeSize) private var userFont: DynamicTypeSize
|
||||
@AppStorage(GROUP_DEFAULT_ONE_HAND_UI, store: groupDefaults) private var oneHandUI = false
|
||||
@ObservedObject var chat: Chat
|
||||
@Binding var parentSheet: SomeSheet<AnyView>?
|
||||
@State private var showContactRequestDialog = false
|
||||
@State private var showJoinGroupDialog = false
|
||||
@State private var showContactConnectionInfo = false
|
||||
@@ -122,7 +123,6 @@ struct ChatListNavLink: View {
|
||||
markReadButton()
|
||||
toggleFavoriteButton()
|
||||
toggleNtfsButton(chat: chat)
|
||||
tagChatButton(chat)
|
||||
}
|
||||
.swipeActions(edge: .trailing, allowsFullSwipe: true) {
|
||||
if !chat.chatItems.isEmpty {
|
||||
@@ -141,7 +141,7 @@ struct ChatListNavLink: View {
|
||||
deleteLabel
|
||||
}
|
||||
.tint(.red)
|
||||
untagChatButton(chat)
|
||||
tagChatButton(chat)
|
||||
}
|
||||
.frame(height: dynamicRowHeight)
|
||||
}
|
||||
@@ -193,6 +193,7 @@ struct ChatListNavLink: View {
|
||||
if groupInfo.canDelete {
|
||||
deleteGroupChatButton(groupInfo)
|
||||
}
|
||||
tagChatButton(chat)
|
||||
}
|
||||
default:
|
||||
NavLinkPlain(
|
||||
@@ -215,7 +216,14 @@ struct ChatListNavLink: View {
|
||||
leaveGroupChatButton(groupInfo)
|
||||
}
|
||||
if groupInfo.canDelete {
|
||||
deleteGroupChatButton(groupInfo)
|
||||
if !groupInfo.membership.memberCurrent {
|
||||
deleteGroupChatButton(groupInfo)
|
||||
tagChatButton(chat)
|
||||
} else {
|
||||
// TODO: Show ...
|
||||
}
|
||||
} else {
|
||||
tagChatButton(chat)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -311,37 +319,22 @@ struct ChatListNavLink: View {
|
||||
|
||||
private func tagChatButton(_ chat: Chat) -> some View {
|
||||
Button {
|
||||
sheet = SomeSheet(
|
||||
parentSheet = SomeSheet(
|
||||
content: {
|
||||
AnyView(
|
||||
ChatListTag(chat: chat)
|
||||
NavigationView {
|
||||
ChatListTag(chat: chat)
|
||||
}
|
||||
)
|
||||
},
|
||||
id: "tag sheet",
|
||||
id: "lists sheet",
|
||||
fraction: 0.7
|
||||
)
|
||||
} label: {
|
||||
SwipeLabel(NSLocalizedString("Tag", comment: "swipe action"), systemImage: "tag.fill", inverted: oneHandUI)
|
||||
SwipeLabel(NSLocalizedString("Lists", comment: "swipe action"), systemImage: "tag.fill", inverted: oneHandUI)
|
||||
}
|
||||
.tint(Color.indigo)
|
||||
}
|
||||
|
||||
private func untagChatButton(_ chat: Chat) -> some View {
|
||||
Button {
|
||||
sheet = SomeSheet(
|
||||
content: {
|
||||
AnyView(
|
||||
ChatListTag(chat: chat, untag: true)
|
||||
)
|
||||
},
|
||||
id: "tag sheet",
|
||||
fraction: 0.7
|
||||
)
|
||||
} label: {
|
||||
SwipeLabel(NSLocalizedString("Untag", comment: "swipe action"), systemImage: "tag.fill", inverted: oneHandUI)
|
||||
}
|
||||
.tint(Color.yellow.opacity(0.8))
|
||||
}
|
||||
|
||||
private func clearNoteFolderButton() -> some View {
|
||||
Button {
|
||||
@@ -522,99 +515,50 @@ struct ChatListNavLink: View {
|
||||
|
||||
struct ChatListTag: View {
|
||||
var chat: Chat
|
||||
var untag: Bool = false
|
||||
@EnvironmentObject var chatTagsModel: ChatTagsModel
|
||||
@EnvironmentObject var m: ChatModel
|
||||
@State private var emoji: String = ""
|
||||
@State private var name: String = ""
|
||||
|
||||
var chatTagsIds: [Int64] { chat.chatInfo.contact?.chatTags ?? chat.chatInfo.groupInfo?.chatTags ?? [] }
|
||||
|
||||
var body: some View {
|
||||
List {
|
||||
if untag {
|
||||
untagView()
|
||||
} else {
|
||||
tagView()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder private func tagView() -> some View {
|
||||
Section {
|
||||
TextField("Emoji..", text: $emoji)
|
||||
TextField("Tag name...", text: $name)
|
||||
Button {
|
||||
createChatTag()
|
||||
NavigationLink {
|
||||
CreateChatListTag(chat: chat)
|
||||
} label: {
|
||||
Text("Create tag")
|
||||
Label("Create list", systemImage: "plus")
|
||||
}
|
||||
}
|
||||
|
||||
let tagsToPick = chatTagsModel.tags.compactMap { tag in
|
||||
if case let .chatTag(emoji, text, tagId) = tag, !chatTagsIds.contains(tagId) {
|
||||
return (emoji, text, tagId)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if !tagsToPick.isEmpty {
|
||||
Section {
|
||||
ForEach(tagsToPick, id: \.0) { tag in
|
||||
let (emoji, text, tagId) = tag
|
||||
Button {
|
||||
tagChat(tagId)
|
||||
} label: {
|
||||
Text("\(emoji) \(text)")
|
||||
|
||||
if !chatTagsModel.tags.isEmpty {
|
||||
ForEach(chatTagsModel.tags) { tag in
|
||||
if case let .chatTag(emoji, text, tagId) = tag {
|
||||
let selected = chatTagsIds.contains(tagId)
|
||||
|
||||
HStack {
|
||||
Text(emoji)
|
||||
Text(text)
|
||||
.padding(.leading, 12)
|
||||
Spacer()
|
||||
radioButton(selected: selected)
|
||||
}
|
||||
.onTapGesture {
|
||||
if selected {
|
||||
untagChat(tagId)
|
||||
} else {
|
||||
tagChat(tagId)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
EmptyView()
|
||||
}
|
||||
}
|
||||
} header: {
|
||||
Text("Choose existing")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder private func untagView() -> some View {
|
||||
Section {
|
||||
ForEach(chatTagsModel.tags) { tag in
|
||||
if case let .chatTag(emoji, text, tagId) = tag, chatTagsIds.contains(tagId) {
|
||||
Button {
|
||||
untagChat(tagId)
|
||||
} label: {
|
||||
Text("\(emoji) \(text)")
|
||||
}
|
||||
} else {
|
||||
EmptyView()
|
||||
}
|
||||
}
|
||||
} header: {
|
||||
Text("Choose existing")
|
||||
}
|
||||
}
|
||||
|
||||
private func createChatTag() {
|
||||
Task {
|
||||
do {
|
||||
let (userTags, chatTags) = try await apiCreateChatTag(
|
||||
type: chat.chatInfo.chatType,
|
||||
id: chat.chatInfo.apiId,
|
||||
tag: ChatTagData(emoji: emoji, text: name)
|
||||
)
|
||||
|
||||
await MainActor.run {
|
||||
chatTagsModel.tags = userTags.map {
|
||||
.chatTag(emoji: $0.chatTagEmoji, text: $0.chatTagText, tagId: $0.chatTagId)
|
||||
}
|
||||
updateChatTags(chat: chat, chatTags: chatTags)
|
||||
}
|
||||
} catch let error {
|
||||
showAlert(
|
||||
NSLocalizedString("Error creating tag", comment: "alert title"),
|
||||
message: responseError(error)
|
||||
)
|
||||
}
|
||||
}
|
||||
@ViewBuilder private func radioButton(selected: Bool) -> some View {
|
||||
Image(systemName: selected ? "checkmark.circle.fill" : "circle")
|
||||
.imageScale(.large)
|
||||
.foregroundStyle(selected ? Color.accentColor : Color(.tertiaryLabel))
|
||||
}
|
||||
|
||||
private func tagChat(_ tagId: Int64) {
|
||||
@@ -634,7 +578,7 @@ struct ChatListTag: View {
|
||||
}
|
||||
} catch let error {
|
||||
showAlert(
|
||||
NSLocalizedString("Error tagging chat", comment: "alert title"),
|
||||
NSLocalizedString("Error adding chat to list", comment: "alert title"),
|
||||
message: responseError(error)
|
||||
)
|
||||
}
|
||||
@@ -658,7 +602,7 @@ struct ChatListTag: View {
|
||||
}
|
||||
} catch let error {
|
||||
showAlert(
|
||||
NSLocalizedString("Error untagging chat", comment: "alert title"),
|
||||
NSLocalizedString("Error removing chat from list", comment: "alert title"),
|
||||
message: responseError(error)
|
||||
)
|
||||
}
|
||||
@@ -677,6 +621,58 @@ struct ChatListTag: View {
|
||||
}
|
||||
}
|
||||
|
||||
struct CreateChatListTag: View {
|
||||
var chat: Chat
|
||||
@Environment(\.presentationMode) var presentationMode
|
||||
@EnvironmentObject var chatTagsModel: ChatTagsModel
|
||||
@EnvironmentObject var m: ChatModel
|
||||
@State private var emoji: String = ""
|
||||
@State private var name: String = ""
|
||||
|
||||
var body: some View {
|
||||
List {
|
||||
TextField("Emoji..", text: $emoji)
|
||||
TextField("List name...", text: $name)
|
||||
Button {
|
||||
createChatTag()
|
||||
} label: {
|
||||
Text("Create list")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func createChatTag() {
|
||||
Task {
|
||||
do {
|
||||
let (userTags, chatTags) = try await apiCreateChatTag(
|
||||
type: chat.chatInfo.chatType,
|
||||
id: chat.chatInfo.apiId,
|
||||
tag: ChatTagData(emoji: emoji, text: name)
|
||||
)
|
||||
|
||||
await MainActor.run {
|
||||
chatTagsModel.tags = userTags.map {
|
||||
.chatTag(emoji: $0.chatTagEmoji, text: $0.chatTagText, tagId: $0.chatTagId)
|
||||
}
|
||||
if var contact = chat.chatInfo.contact {
|
||||
contact.chatTags = chatTags
|
||||
m.updateContact(contact)
|
||||
} else if var group = chat.chatInfo.groupInfo {
|
||||
group.chatTags = chatTags
|
||||
m.updateGroup(group)
|
||||
}
|
||||
presentationMode.wrappedValue.dismiss()
|
||||
}
|
||||
} catch let error {
|
||||
showAlert(
|
||||
NSLocalizedString("Error creating list", comment: "alert title"),
|
||||
message: responseError(error)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func rejectContactRequestAlert(_ contactRequest: UserContactRequest) -> Alert {
|
||||
Alert(
|
||||
title: Text("Reject contact request"),
|
||||
@@ -778,15 +774,15 @@ struct ChatListNavLink_Previews: PreviewProvider {
|
||||
ChatListNavLink(chat: Chat(
|
||||
chatInfo: ChatInfo.sampleData.direct,
|
||||
chatItems: [ChatItem.getSample(1, .directSnd, .now, "hello")]
|
||||
))
|
||||
), parentSheet: .constant(nil))
|
||||
ChatListNavLink(chat: Chat(
|
||||
chatInfo: ChatInfo.sampleData.direct,
|
||||
chatItems: [ChatItem.getSample(1, .directSnd, .now, "hello")]
|
||||
))
|
||||
), parentSheet: .constant(nil))
|
||||
ChatListNavLink(chat: Chat(
|
||||
chatInfo: ChatInfo.sampleData.contactRequest,
|
||||
chatItems: []
|
||||
))
|
||||
), parentSheet: .constant(nil))
|
||||
}
|
||||
.previewLayout(.fixed(width: 360, height: 82))
|
||||
}
|
||||
|
||||
@@ -117,6 +117,7 @@ struct ChatListView: View {
|
||||
@State private var searchChatFilteredBySimplexLink: String? = nil
|
||||
@State private var scrollToSearchBar = false
|
||||
@State private var userPickerShown: Bool = false
|
||||
@State private var sheet: SomeSheet<AnyView>? = nil
|
||||
@StateObject private var chatTagsModel = ChatTagsModel.shared
|
||||
|
||||
@AppStorage(DEFAULT_SHOW_UNREAD_AND_FAVORITES) private var showUnreadAndFavorites = false
|
||||
@@ -163,6 +164,17 @@ struct ChatListView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
.sheet(item: $sheet) {
|
||||
if #available(iOS 16.0, *) {
|
||||
$0.content
|
||||
.presentationDetents([.fraction($0.fraction)])
|
||||
.environmentObject(chatTagsModel)
|
||||
} else {
|
||||
$0.content
|
||||
.environmentObject(chatTagsModel)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var chatListView: some View {
|
||||
@@ -308,7 +320,7 @@ struct ChatListView: View {
|
||||
}
|
||||
if #available(iOS 16.0, *) {
|
||||
ForEach(cs, id: \.viewId) { chat in
|
||||
ChatListNavLink(chat: chat)
|
||||
ChatListNavLink(chat: chat, parentSheet: $sheet)
|
||||
.scaleEffect(x: 1, y: oneHandUI ? -1 : 1, anchor: .center)
|
||||
.padding(.trailing, -16)
|
||||
.disabled(chatModel.chatRunning != true || chatModel.deletedChats.contains(chat.chatInfo.id))
|
||||
@@ -320,7 +332,7 @@ struct ChatListView: View {
|
||||
VStack(spacing: .zero) {
|
||||
Divider()
|
||||
.padding(.leading, 16)
|
||||
ChatListNavLink(chat: chat)
|
||||
ChatListNavLink(chat: chat, parentSheet: $sheet)
|
||||
.padding(.horizontal, 8)
|
||||
.padding(.vertical, 6)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user