FollowPackView.swift (6472B)
1 // 2 // FollowPackView.swift 3 // damus 4 // 5 // Created by eric on 4/30/25. 6 // 7 8 import SwiftUI 9 import Kingfisher 10 11 struct FollowPackView: View { 12 let state: DamusState 13 let event: FollowPackEvent 14 @StateObject var model: FollowPackModel 15 @State var blur_imgs: Bool 16 17 @Environment(\.colorScheme) var colorScheme 18 19 @ObservedObject var artifacts: NoteArtifactsModel 20 21 init(state: DamusState, ev: FollowPackEvent, model: FollowPackModel, blur_imgs: Bool) { 22 self.state = state 23 self.event = ev 24 self._model = StateObject(wrappedValue: model) 25 self.blur_imgs = blur_imgs 26 27 self._artifacts = ObservedObject(wrappedValue: state.events.get_cache_data(ev.event.id).artifacts_model) 28 } 29 30 init(state: DamusState, ev: NostrEvent, model: FollowPackModel, blur_imgs: Bool) { 31 self.state = state 32 self.event = FollowPackEvent.parse(from: ev) 33 self._model = StateObject(wrappedValue: model) 34 self.blur_imgs = blur_imgs 35 36 self._artifacts = ObservedObject(wrappedValue: state.events.get_cache_data(ev.id).artifacts_model) 37 } 38 39 func content_filter(_ pubkeys: [Pubkey]) -> ((NostrEvent) -> Bool) { 40 var filters = ContentFilters.defaults(damus_state: self.state) 41 filters.append({ pubkeys.contains($0.pubkey) }) 42 return ContentFilters(filters: filters).filter 43 } 44 45 enum FollowPackTabSelection: Int { 46 case people = 0 47 case posts = 1 48 } 49 50 @State var tab_selection: FollowPackTabSelection = .people 51 52 var body: some View { 53 ZStack { 54 ScrollView { 55 FollowPackHeader 56 57 FollowPackTabs 58 } 59 } 60 .onAppear { 61 if model.events.events.isEmpty { 62 model.subscribe(follow_pack_users: event.publicKeys) 63 } 64 } 65 .onDisappear { 66 model.unsubscribe() 67 } 68 } 69 70 var tabs: [(String, FollowPackTabSelection)] { 71 let tabs = [ 72 (NSLocalizedString("People", comment: "Label for filter for seeing the people in this follow pack."), FollowPackTabSelection.people), 73 (NSLocalizedString("Posts", comment: "Label for filter for seeing the posts from the people in this follow pack."), FollowPackTabSelection.posts) 74 ] 75 return tabs 76 } 77 78 var FollowPackTabs: some View { 79 80 VStack(spacing: 0) { 81 VStack(spacing: 0) { 82 CustomPicker(tabs: tabs, selection: $tab_selection) 83 Divider() 84 .frame(height: 1) 85 } 86 .background(colorScheme == .dark ? Color.black : Color.white) 87 88 if tab_selection == FollowPackTabSelection.people { 89 LazyVStack(alignment: .leading) { 90 ForEach(event.publicKeys.reversed(), id: \.self) { pk in 91 FollowUserView(target: .pubkey(pk), damus_state: state) 92 } 93 } 94 .padding() 95 .padding(.bottom, 50) 96 .tag(FollowPackTabSelection.people) 97 .id(FollowPackTabSelection.people) 98 } 99 100 if tab_selection == FollowPackTabSelection.posts { 101 InnerTimelineView(events: model.events, damus: state, filter: content_filter(event.publicKeys)) 102 } 103 } 104 .onAppear() { 105 model.subscribe(follow_pack_users: event.publicKeys) 106 } 107 .onDisappear { 108 model.unsubscribe() 109 } 110 } 111 112 var FollowPackHeader: some View { 113 VStack(alignment: .leading, spacing: 10) { 114 115 if state.settings.media_previews { 116 FollowPackBannerImage(state: state, options: EventViewOptions(), image: event.image, preview: false, blur_imgs: blur_imgs) 117 } 118 119 Text(event.title ?? NSLocalizedString("Untitled", comment: "Title of follow list event if it is untitled.")) 120 .font(.title) 121 .padding(.horizontal, 10) 122 .padding(.top, 5) 123 124 if let description = event.description { 125 Text(description) 126 .font(.body) 127 .foregroundColor(.gray) 128 .padding(.horizontal, 10) 129 } else { 130 EmptyView() 131 } 132 133 HStack(alignment: .center) { 134 ProfilePicView(pubkey: event.event.pubkey, size: 25, highlight: .none, profiles: state.profiles, disable_animation: state.settings.disable_animation, show_zappability: true) 135 .onTapGesture { 136 state.nav.push(route: Route.ProfileByKey(pubkey: event.event.pubkey)) 137 } 138 let profile_txn = state.profiles.lookup(id: event.event.pubkey) 139 let profile = profile_txn?.unsafeUnownedValue 140 let displayName = Profile.displayName(profile: profile, pubkey: event.event.pubkey) 141 switch displayName { 142 case .one(let one): 143 Text("Created by \(one)", comment: "Lets the user know who created this follow pack.") 144 .font(.subheadline).foregroundColor(.gray) 145 146 case .both(username: let username, displayName: let displayName): 147 HStack(spacing: 6) { 148 Text("Created by \(displayName)", comment: "Lets the user know who created this follow pack.") 149 .font(.subheadline).foregroundColor(.gray) 150 151 Text(verbatim: "@\(username)") 152 .font(.subheadline).foregroundColor(.gray) 153 } 154 } 155 } 156 .padding(.horizontal, 10) 157 .padding(.bottom, 20) 158 159 HStack(alignment: .center) { 160 FollowPackUsers(state: state, publicKeys: event.publicKeys) 161 } 162 .padding(.horizontal, 10) 163 .padding(.bottom, 20) 164 } 165 } 166 } 167 168 169 struct FollowPackView_Previews: PreviewProvider { 170 static var previews: some View { 171 VStack { 172 FollowPackView(state: test_damus_state, ev: test_follow_list_event, model: FollowPackModel(damus_state: test_damus_state), blur_imgs: false) 173 } 174 .frame(height: 400) 175 } 176 }