mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-10-31 16:24:11 +00:00
d51a9b3a2b
* Correctly tear down the user session on signing out * Fix session verification <-> user session retain cycle, visible range debouncer leak * Manually clean up coordinators retained within SwiftUI's NavigationStacks * Slightly refactor the timeline content menu builder and prevent it from retaining the view model. Cleanup now unnecessarily optional RoomScreenCoordinator instance vars * Move coordinator dismissal logic to the navigation modules
112 lines
3.6 KiB
Swift
112 lines
3.6 KiB
Swift
//
|
|
// Copyright 2022 New Vector Ltd
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
|
|
import SwiftUI
|
|
|
|
struct TimelineItemContextMenuActions {
|
|
let actions: [TimelineItemContextMenuAction]
|
|
let debugActions: [TimelineItemContextMenuAction]
|
|
|
|
init?(actions: [TimelineItemContextMenuAction], debugActions: [TimelineItemContextMenuAction]) {
|
|
if actions.isEmpty, debugActions.isEmpty {
|
|
return nil
|
|
}
|
|
|
|
self.actions = actions
|
|
self.debugActions = debugActions
|
|
}
|
|
}
|
|
|
|
enum TimelineItemContextMenuAction: Identifiable, Hashable {
|
|
case react
|
|
case copy
|
|
case edit
|
|
case quote
|
|
case copyPermalink
|
|
case redact
|
|
case reply
|
|
case viewSource
|
|
case retryDecryption(sessionId: String)
|
|
|
|
var id: Self { self }
|
|
|
|
var switchToDefaultComposer: Bool {
|
|
switch self {
|
|
case .reply, .edit:
|
|
return false
|
|
default:
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
|
|
public struct TimelineItemContextMenu: View {
|
|
let contextMenuActions: TimelineItemContextMenuActions
|
|
let callback: (TimelineItemContextMenuAction) -> Void
|
|
|
|
public var body: some View {
|
|
viewsForActions(contextMenuActions.actions)
|
|
Menu {
|
|
viewsForActions(contextMenuActions.debugActions)
|
|
} label: {
|
|
Label("Developer", systemImage: "hammer")
|
|
}
|
|
}
|
|
|
|
private func viewsForActions(_ actions: [TimelineItemContextMenuAction]) -> some View {
|
|
ForEach(actions, id: \.self) { item in
|
|
switch item {
|
|
case .react:
|
|
Button { callback(item) } label: {
|
|
Label(ElementL10n.reactions, systemImage: "face.smiling")
|
|
}
|
|
case .copy:
|
|
Button { callback(item) } label: {
|
|
Label(ElementL10n.actionCopy, systemImage: "doc.on.doc")
|
|
}
|
|
case .edit:
|
|
Button { callback(item) } label: {
|
|
Label(ElementL10n.edit, systemImage: "pencil")
|
|
}
|
|
case .quote:
|
|
Button { callback(item) } label: {
|
|
Label(ElementL10n.actionQuote, systemImage: "quote.bubble")
|
|
}
|
|
case .copyPermalink:
|
|
Button { callback(item) } label: {
|
|
Label(ElementL10n.permalink, systemImage: "link")
|
|
}
|
|
case .reply:
|
|
Button { callback(item) } label: {
|
|
Label(ElementL10n.reply, systemImage: "arrow.uturn.left")
|
|
}
|
|
case .redact:
|
|
Button(role: .destructive) { callback(item) } label: {
|
|
Label(ElementL10n.messageActionItemRedact, systemImage: "trash")
|
|
}
|
|
case .viewSource:
|
|
Button { callback(item) } label: {
|
|
Label(ElementL10n.viewSource, systemImage: "doc.text.below.ecg")
|
|
}
|
|
case .retryDecryption:
|
|
Button { callback(item) } label: {
|
|
Label(ElementL10n.roomTimelineContextMenuRetryDecryption, systemImage: "arrow.down.message")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|