EventMenu.swift (7993B)
1 // 2 // EventMenu.swift 3 // damus 4 // 5 // Created by William Casarin on 2023-01-23. 6 // 7 8 import SwiftUI 9 10 struct EventMenuContext: View { 11 let damus_state: DamusState 12 let event: NostrEvent 13 let target_pubkey: Pubkey 14 let profileModel : ProfileModel 15 16 init(damus: DamusState, event: NostrEvent) { 17 self.damus_state = damus 18 self.event = event 19 self.target_pubkey = event.pubkey 20 self.profileModel = ProfileModel(pubkey: target_pubkey, damus: damus) 21 } 22 23 var body: some View { 24 HStack { 25 Label("", systemImage: "ellipsis") 26 .foregroundColor(Color.gray) 27 .contentShape(Circle()) 28 // Add our Menu button inside an overlay modifier to avoid affecting the rest of the layout around us. 29 .overlay( 30 Menu { 31 MenuItems(damus_state: damus_state, event: event, target_pubkey: target_pubkey, profileModel: profileModel) 32 } label: { 33 Color.clear 34 } 35 // Hitbox frame size 36 .frame(width: 50, height: 35) 37 ) 38 } 39 .padding([.bottom], 4) 40 .contentShape(Rectangle()) 41 .onTapGesture {} 42 } 43 } 44 45 struct MenuItems: View { 46 let damus_state: DamusState 47 let event: NostrEvent 48 let target_pubkey: Pubkey 49 let profileModel: ProfileModel 50 51 @State private var isBookmarked: Bool = false 52 @State private var isMutedThread: Bool = false 53 54 init(damus_state: DamusState, event: NostrEvent, target_pubkey: Pubkey, profileModel: ProfileModel) { 55 let bookmarked = damus_state.bookmarks.isBookmarked(event) 56 self._isBookmarked = State(initialValue: bookmarked) 57 58 let muted_thread = damus_state.mutelist_manager.is_event_muted(event) 59 self._isMutedThread = State(initialValue: muted_thread) 60 61 self.damus_state = damus_state 62 self.event = event 63 self.target_pubkey = target_pubkey 64 self.profileModel = profileModel 65 } 66 67 var body: some View { 68 Group { 69 Button { 70 UIPasteboard.general.string = event.get_content(damus_state.keypair) 71 } label: { 72 Label(NSLocalizedString("Copy text", comment: "Context menu option for copying the text from an note."), image: "copy2") 73 } 74 75 Button { 76 UIPasteboard.general.string = Bech32Object.encode(.nprofile(NProfile(author: target_pubkey, relays: profileModel.getCappedRelayStrings()))) 77 } label: { 78 Label(NSLocalizedString("Copy user public key", comment: "Context menu option for copying the ID of the user who created the note."), image: "user") 79 } 80 81 Button { 82 UIPasteboard.general.string = event.id.bech32 83 } label: { 84 Label(NSLocalizedString("Copy note ID", comment: "Context menu option for copying the ID of the note."), image: "note-book") 85 } 86 87 if damus_state.settings.developer_mode { 88 Button { 89 UIPasteboard.general.string = event_to_json(ev: event) 90 } label: { 91 Label(NSLocalizedString("Copy note JSON", comment: "Context menu option for copying the JSON text from the note."), image: "code.on.square") 92 } 93 } 94 95 Button { 96 self.damus_state.bookmarks.updateBookmark(event) 97 isBookmarked = self.damus_state.bookmarks.isBookmarked(event) 98 } label: { 99 let imageName = isBookmarked ? "bookmark.fill" : "bookmark" 100 let removeBookmarkString = NSLocalizedString("Remove bookmark", comment: "Context menu option for removing a note bookmark.") 101 let addBookmarkString = NSLocalizedString("Add bookmark", comment: "Context menu option for adding a note bookmark.") 102 Label(isBookmarked ? removeBookmarkString : addBookmarkString, image: imageName) 103 } 104 105 Button { 106 notify(.broadcast(event)) 107 } label: { 108 Label(NSLocalizedString("Broadcast", comment: "Context menu option for broadcasting the user's note to all of the user's connected relay servers."), image: "globe") 109 } 110 // Mute thread - relocated to below Broadcast, as to move further away from Add Bookmark to prevent accidental muted threads 111 if event.known_kind != .dm { 112 MuteDurationMenu { duration in 113 if let full_keypair = self.damus_state.keypair.to_full(), 114 let new_mutelist_ev = toggle_from_mutelist(keypair: full_keypair, prev: damus_state.mutelist_manager.event, to_toggle: .thread(event.thread_id(keypair: damus_state.keypair), duration?.date_from_now)) { 115 damus_state.mutelist_manager.set_mutelist(new_mutelist_ev) 116 damus_state.postbox.send(new_mutelist_ev) 117 } 118 let muted = damus_state.mutelist_manager.is_event_muted(event) 119 isMutedThread = muted 120 } label: { 121 let imageName = isMutedThread ? "mute" : "mute" 122 let unmuteThreadString = NSLocalizedString("Unmute conversation", comment: "Context menu option for unmuting a conversation.") 123 let muteThreadString = NSLocalizedString("Mute conversation", comment: "Context menu option for muting a conversation.") 124 Label(isMutedThread ? unmuteThreadString : muteThreadString, image: imageName) 125 } 126 } 127 // Only allow reporting if logged in with private key and the currently viewed profile is not the logged in profile. 128 if damus_state.keypair.pubkey != target_pubkey && damus_state.keypair.privkey != nil { 129 Button(role: .destructive) { 130 notify(.report(.note(ReportNoteTarget(pubkey: target_pubkey, note_id: event.id)))) 131 } label: { 132 Label(NSLocalizedString("Report", comment: "Context menu option for reporting content."), image: "raising-hand") 133 } 134 135 MuteDurationMenu { duration in 136 notify(.mute(.user(target_pubkey, duration?.date_from_now))) 137 } label: { 138 Label(NSLocalizedString("Mute user", comment: "Context menu option for muting users."), image: "mute") 139 } 140 } 141 } 142 .onAppear() { 143 profileModel.subscribeToFindRelays() 144 } 145 .onDisappear() { 146 profileModel.unsubscribeFindRelays() 147 } 148 } 149 } 150 151 /* 152 struct EventMenu: UIViewRepresentable { 153 154 typealias UIViewType = UIButton 155 156 let saveAction = UIAction(title: "") { action in } 157 let saveMenu = UIMenu(title: "", children: [ 158 UIAction(title: "First Menu Item", image: UIImage(systemName: "nameOfSFSymbol")) { action in 159 //code action for menu item 160 }, 161 UIAction(title: "First Menu Item", image: UIImage(systemName: "nameOfSFSymbol")) { action in 162 //code action for menu item 163 }, 164 UIAction(title: "First Menu Item", image: UIImage(systemName: "nameOfSFSymbol")) { action in 165 //code action for menu item 166 }, 167 ]) 168 169 func makeUIView(context: Context) -> UIButton { 170 let button = UIButton(frame: CGRect(x: 0, y: 0, width: 20, height: 20)) 171 button.showsMenuAsPrimaryAction = true 172 button.menu = saveMenu 173 174 return button 175 } 176 177 func updateUIView(_ uiView: UIButton, context: Context) { 178 uiView.setImage(UIImage(systemName: "plus"), for: .normal) 179 } 180 } 181 182 struct EventMenu_Previews: PreviewProvider { 183 static var previews: some View { 184 EventMenu(event: test_event, privkey: nil, pubkey: test_event.pubkey) 185 } 186 } 187 188 */