refactor: Break EventView into 3 separate views

SelectedEventView
EmbeddedEventView
EventView
This commit is contained in:
William Casarin
2023-01-23 12:13:58 -08:00
parent 7e1daf7816
commit 8df5bf04ae
13 changed files with 298 additions and 138 deletions

View File

@@ -49,7 +49,7 @@ struct DirectMessagesView: View {
func MaybeEvent(_ tup: (String, DirectMessageModel)) -> some View {
Group {
if let ev = tup.1.events.last {
EventView(damus: damus_state, event: ev, pubkey: tup.0, show_friend_icon: true)
EventView(damus: damus_state, event: ev, pubkey: tup.0)
.onTapGesture {
pubkey = tup.0
active_model = tup.1

View File

@@ -72,7 +72,7 @@ struct EventDetailView: View {
toggle_thread_view()
}
case .event(let ev, let highlight):
EventView(event: ev, highlight: highlight, has_action_bar: true, damus: damus, show_friend_icon: true)
EventView(event: ev, has_action_bar: true, damus: damus)
.onTapGesture {
if thread.initial_event.id == ev.id {
toggle_thread_view()

View File

@@ -11,7 +11,6 @@ import SwiftUI
enum EventViewKind {
case small
case normal
case big
case selected
}
@@ -21,56 +20,40 @@ func eventviewsize_to_font(_ size: EventViewKind) -> Font {
return .body
case .normal:
return .body
case .big:
return .headline
case .selected:
return .custom("selected", size: 21.0)
}
}
struct EventView: View {
let event: NostrEvent
let highlight: Highlight
let has_action_bar: Bool
let damus: DamusState
let pubkey: String
let show_friend_icon: Bool
let size: EventViewKind
let embedded: Bool
@EnvironmentObject var action_bar: ActionBarModel
init(event: NostrEvent, highlight: Highlight, has_action_bar: Bool, damus: DamusState, show_friend_icon: Bool, size: EventViewKind = .normal, embedded: Bool = false) {
init(event: NostrEvent, has_action_bar: Bool, damus: DamusState) {
self.event = event
self.highlight = highlight
self.has_action_bar = has_action_bar
self.damus = damus
self.pubkey = event.pubkey
self.show_friend_icon = show_friend_icon
self.size = size
self.embedded = embedded
}
init(damus: DamusState, event: NostrEvent, show_friend_icon: Bool, size: EventViewKind = .normal, embedded: Bool = false) {
init(damus: DamusState, event: NostrEvent) {
self.event = event
self.highlight = .none
self.has_action_bar = false
self.damus = damus
self.pubkey = event.pubkey
self.show_friend_icon = show_friend_icon
self.size = size
self.embedded = embedded
}
init(damus: DamusState, event: NostrEvent, pubkey: String, show_friend_icon: Bool, size: EventViewKind = .normal, embedded: Bool = false) {
init(damus: DamusState, event: NostrEvent, pubkey: String) {
self.event = event
self.highlight = .none
self.has_action_bar = false
self.damus = damus
self.pubkey = pubkey
self.show_friend_icon = show_friend_icon
self.size = size
self.embedded = embedded
}
var body: some View {
@@ -101,88 +84,43 @@ struct EventView: View {
return HStack(alignment: .top) {
let profile = damus.profiles.lookup(id: pubkey)
if size != .selected {
VStack {
let pmodel = ProfileModel(pubkey: pubkey, damus: damus)
let pv = ProfileView(damus_state: damus, profile: pmodel, followers: FollowersModel(damus_state: damus, target: pubkey))
if !embedded {
NavigationLink(destination: pv) {
ProfilePicView(pubkey: pubkey, size: PFP_SIZE, highlight: highlight, profiles: damus.profiles)
}
}
Spacer()
VStack {
let pmodel = ProfileModel(pubkey: pubkey, damus: damus)
let pv = ProfileView(damus_state: damus, profile: pmodel, followers: FollowersModel(damus_state: damus, target: pubkey))
NavigationLink(destination: pv) {
ProfilePicView(pubkey: pubkey, size: PFP_SIZE, highlight: .none, profiles: damus.profiles)
}
Spacer()
}
VStack(alignment: .leading) {
HStack(alignment: .center) {
if size == .selected {
VStack {
let pmodel = ProfileModel(pubkey: pubkey, damus: damus)
let pv = ProfileView(damus_state: damus, profile: pmodel, followers: FollowersModel(damus_state: damus, target: pubkey))
NavigationLink(destination: pv) {
ProfilePicView(pubkey: pubkey, size: PFP_SIZE, highlight: highlight, profiles: damus.profiles)
}
}
}
EventProfileName(pubkey: pubkey, profile: profile, damus: damus, show_friend_confirmed: true, size: .normal)
EventProfileName(pubkey: pubkey, profile: profile, damus: damus, show_friend_confirmed: show_friend_icon, size: size)
if size != .selected {
Text("\(format_relative_time(event.created_at))")
.font(eventviewsize_to_font(size))
.foregroundColor(.gray)
}
}
if event.is_reply(damus.keypair.privkey) {
Text("\(reply_desc(profiles: damus.profiles, event: event))")
.font(.footnote)
Text("\(format_relative_time(event.created_at))")
.foregroundColor(.gray)
.frame(maxWidth: .infinity, alignment: .leading)
}
let should_show_img = should_show_images(contacts: damus.contacts, ev: event, our_pubkey: damus.pubkey, booster_pubkey: booster_pubkey)
NoteContentView(privkey: damus.keypair.privkey, event: event, profiles: damus.profiles, previews: damus.previews, show_images: should_show_img, artifacts: .just_content(content), size: self.size)
.frame(maxWidth: .infinity, alignment: .leading)
.allowsHitTesting(!embedded)
EventBody(damus_state: damus, event: event, size: .normal)
if !embedded {
if let mention = first_eref_mention(ev: event, privkey: damus.keypair.privkey) {
BuilderEventView(damus: damus, event_id: mention.ref.id)
}
if let mention = first_eref_mention(ev: event, privkey: damus.keypair.privkey) {
BuilderEventView(damus: damus, event_id: mention.ref.id)
}
if has_action_bar {
Rectangle().frame(height: 2).opacity(0)
if has_action_bar {
if size == .selected {
Text("\(format_date(event.created_at))")
.padding(.top, 10)
.font(.footnote)
.foregroundColor(.gray)
Divider()
.padding([.bottom], 4)
} else {
Rectangle().frame(height: 2).opacity(0)
}
let bar = make_actionbar_model(ev: event, damus: damus)
if size == .selected && !bar.is_empty {
EventDetailBar(state: damus, target: event.id, bar: bar)
Divider()
}
EventActionBar(damus_state: damus, event: event, bar: bar)
.padding([.top], 4)
}
Divider()
let bar = make_actionbar_model(ev: event, damus: damus)
EventActionBar(damus_state: damus, event: event, bar: bar)
.padding([.top], 4)
}
Divider()
.padding([.top], 4)
}
.padding([.leading], 2)
}
@@ -339,31 +277,18 @@ struct EventView_Previews: PreviewProvider {
*/
EventView(
event: NostrEvent(
content: "hello there https://jb55.com/s/Oct12-150217.png https://jb55.com/red-me.jpg cool",
pubkey: "pk",
createdAt: Int64(Date().timeIntervalSince1970 - 100)
),
highlight: .none,
event: test_event,
has_action_bar: true,
damus: test_damus_state(),
show_friend_icon: true,
size: .selected
)
EventView(
event: NostrEvent(
content: "hello there https://jb55.com/s/Oct12-150217.png https://jb55.com/red-me.jpg cool",
pubkey: "pk",
createdAt: Int64(Date().timeIntervalSince1970 - 100)
),
highlight: .none,
has_action_bar: true,
damus: test_damus_state(),
show_friend_icon: true,
size: .normal
damus: test_damus_state()
)
}
.padding()
}
}
let test_event =
NostrEvent(
content: "hello there https://jb55.com/s/Oct12-150217.png https://jb55.com/red-me.jpg cool",
pubkey: "pk",
createdAt: Int64(Date().timeIntervalSince1970 - 100)
)

View File

@@ -0,0 +1,81 @@
//
// BuilderEventView.swift
// damus
//
// Created by William Casarin on 2023-01-23.
//
import SwiftUI
struct BuilderEventView: View {
let damus: DamusState
let event_id: String
@State var event: NostrEvent?
@State var subscription_uuid: String = UUID().description
func unsubscribe() {
damus.pool.unsubscribe(sub_id: subscription_uuid)
}
func subscribe(filters: [NostrFilter]) {
damus.pool.register_handler(sub_id: subscription_uuid, handler: handle_event)
damus.pool.send(.subscribe(.init(filters: filters, sub_id: subscription_uuid)))
}
func handle_event(relay_id: String, ev: NostrConnectionEvent) {
guard case .nostr_event(let nostr_response) = ev else {
return
}
guard case .event(let id, let nostr_event) = nostr_response else {
return
}
// Is current event
if id == subscription_uuid {
if event != nil {
return
}
event = nostr_event
unsubscribe()
}
}
func load() {
subscribe(filters: [
NostrFilter(
ids: [self.event_id],
limit: 1
)
])
}
var body: some View {
VStack {
if let event = event {
let ev = event.inner_event ?? event
NavigationLink(destination: BuildThreadV2View(damus: damus, event_id: ev.id)) {
EmbeddedEventView(damus_state: damus, event: event)
.padding(8)
}.buttonStyle(.plain)
} else {
ProgressView().padding()
}
}
.frame(minWidth: 0, maxWidth: .infinity)
.cornerRadius(8)
.border(Color.gray.opacity(0.2), width: 1)
.onAppear {
self.load()
}
}
}
struct BuilderEventView_Previews: PreviewProvider {
static var previews: some View {
BuilderEventView(damus: test_damus_state(), event_id: "536bee9e83c818e3b82c101935128ae27a0d4290039aaf253efe5f09232c1962")
}
}

View File

@@ -0,0 +1,34 @@
//
// EmbeddedEventView.swift
// damus
//
// Created by William Casarin on 2023-01-23.
//
import SwiftUI
struct EmbeddedEventView: View {
let damus_state: DamusState
let event: NostrEvent
var pubkey: String {
event.pubkey
}
var body: some View {
VStack(alignment: .leading) {
let profile = damus_state.profiles.lookup(id: pubkey)
EventProfile(damus_state: damus_state, pubkey: pubkey, profile: profile, size: .small)
EventBody(damus_state: damus_state, event: event, size: .small)
}
}
}
struct EmbeddedEventView_Previews: PreviewProvider {
static var previews: some View {
EmbeddedEventView(damus_state: test_damus_state(), event: test_event)
.padding()
}
}

View File

@@ -0,0 +1,35 @@
//
// EventBody.swift
// damus
//
// Created by William Casarin on 2023-01-23.
//
import SwiftUI
struct EventBody: View {
let damus_state: DamusState
let event: NostrEvent
let size: EventViewKind
var content: String {
event.get_content(damus_state.keypair.privkey)
}
var body: some View {
if event_is_reply(event, privkey: damus_state.keypair.privkey) {
ReplyDescription(event: event, profiles: damus_state.profiles)
}
let should_show_img = should_show_images(contacts: damus_state.contacts, ev: event, our_pubkey: damus_state.pubkey, booster_pubkey: nil)
NoteContentView(privkey: damus_state.keypair.privkey, event: event, profiles: damus_state.profiles, previews: damus_state.previews, show_images: should_show_img, artifacts: .just_content(content), size: size)
.frame(maxWidth: .infinity, alignment: .leading)
}
}
struct EventBody_Previews: PreviewProvider {
static var previews: some View {
EventBody(damus_state: test_damus_state(), event: test_event, size: .normal)
}
}

View File

@@ -0,0 +1,51 @@
//
// EventProfile.swift
// damus
//
// Created by William Casarin on 2023-01-23.
//
import SwiftUI
func eventview_pfp_size(_ size: EventViewKind) -> CGFloat {
switch size {
case .small:
return PFP_SIZE * 0.5
case .normal:
return PFP_SIZE
case .selected:
return PFP_SIZE
}
}
struct EventProfile: View {
let damus_state: DamusState
let pubkey: String
let profile: Profile?
let size: EventViewKind
var pfp_size: CGFloat {
eventview_pfp_size(size)
}
var body: some View {
HStack(alignment: .center) {
VStack {
let pmodel = ProfileModel(pubkey: pubkey, damus: damus_state)
let pv = ProfileView(damus_state: damus_state, profile: pmodel, followers: FollowersModel(damus_state: damus_state, target: pubkey))
NavigationLink(destination: pv) {
ProfilePicView(pubkey: pubkey, size: pfp_size, highlight: .none, profiles: damus_state.profiles)
}
}
EventProfileName(pubkey: pubkey, profile: profile, damus: damus_state, show_friend_confirmed: true, size: size)
}
}
}
struct EventProfile_Previews: PreviewProvider {
static var previews: some View {
EventProfile(damus_state: test_damus_state(), pubkey: "pk", profile: nil, size: .normal)
}
}

View File

@@ -0,0 +1,27 @@
//
// ReplyDescription.swift
// damus
//
// Created by William Casarin on 2023-01-23.
//
import SwiftUI
// jb55 - TODO: this could be a lot better
struct ReplyDescription: View {
let event: NostrEvent
let profiles: Profiles
var body: some View {
Text("\(reply_desc(profiles: profiles, event: event))")
.font(.footnote)
.foregroundColor(.gray)
.frame(maxWidth: .infinity, alignment: .leading)
}
}
struct ReplyDescription_Previews: PreviewProvider {
static var previews: some View {
ReplyDescription(event: test_event, profiles: test_damus_state().profiles)
}
}

View File

@@ -0,0 +1,73 @@
//
// SelectedEventView.swift
// damus
//
// Created by William Casarin on 2023-01-23.
//
import SwiftUI
struct SelectedEventView: View {
let damus: DamusState
let event: NostrEvent
var pubkey: String {
event.pubkey
}
var body: some View {
HStack(alignment: .top) {
let profile = damus.profiles.lookup(id: pubkey)
VStack(alignment: .leading) {
HStack(alignment: .center) {
VStack {
let pmodel = ProfileModel(pubkey: pubkey, damus: damus)
let pv = ProfileView(damus_state: damus, profile: pmodel, followers: FollowersModel(damus_state: damus, target: pubkey))
NavigationLink(destination: pv) {
ProfilePicView(pubkey: pubkey, size: PFP_SIZE, highlight: .none, profiles: damus.profiles)
}
}
EventProfileName(pubkey: pubkey, profile: profile, damus: damus, show_friend_confirmed: true, size: .selected)
}
EventBody(damus_state: damus, event: event, size: .selected)
if let mention = first_eref_mention(ev: event, privkey: damus.keypair.privkey) {
BuilderEventView(damus: damus, event_id: mention.ref.id)
}
Text("\(format_date(event.created_at))")
.padding(.top, 10)
.font(.footnote)
.foregroundColor(.gray)
Divider()
.padding([.bottom], 4)
let bar = make_actionbar_model(ev: event, damus: damus)
if !bar.is_empty {
EventDetailBar(state: damus, target: event.id, bar: bar)
Divider()
}
EventActionBar(damus_state: damus, event: event, bar: bar)
.padding([.top], 4)
Divider()
.padding([.top], 4)
}
.padding([.leading], 2)
}
}
}
struct SelectedEventView_Previews: PreviewProvider {
static var previews: some View {
SelectedEventView(damus: test_damus_state(), event: test_event)
.padding()
}
}

View File

@@ -45,7 +45,7 @@ struct ReplyView: View {
ParticipantsView(damus_state: damus, references: $references, originalReferences: $originalReferences)
}
ScrollView {
EventView(event: replying_to, highlight: .none, has_action_bar: false, damus: damus, show_friend_icon: true)
EventView(event: replying_to, has_action_bar: false, damus: damus)
}
PostView(replying_to: replying_to, references: references)
}

View File

@@ -255,14 +255,7 @@ struct ThreadV2View: View {
// MARK: - Parents events view
VStack {
ForEach(thread.parentEvents, id: \.id) { event in
EventView(
event: event,
highlight: .none,
has_action_bar: true,
damus: damus,
show_friend_icon: true, // TODO: change it
size: .small
)
EventView(event: event, has_action_bar: true, damus: damus)
.onTapGesture {
nav_target = event.id
navigating = true
@@ -285,24 +278,17 @@ struct ThreadV2View: View {
})
// MARK: - Actual event view
EventView(
event: thread.current,
highlight: .none,
has_action_bar: true,
SelectedEventView(
damus: damus,
show_friend_icon: true, // TODO: change it
size: .selected
event: thread.current
).id("main")
// MARK: - Responses of the actual event view
ForEach(thread.childEvents, id: \.id) { event in
EventView(
event: event,
highlight: .none,
has_action_bar: true,
damus: damus,
show_friend_icon: true, // TODO: change it
size: .small
damus: damus
)
.onTapGesture {
nav_target = event.id

View File

@@ -43,7 +43,7 @@ struct InnerTimelineView: View {
//let is_chatroom = should_show_chatroom(ev)
//let tv = ThreadView(thread: tm, damus: damus, is_chatroom: is_chatroom)
EventView(event: ev, highlight: .none, has_action_bar: true, damus: damus, show_friend_icon: show_friend_icon)
EventView(event: ev, has_action_bar: true, damus: damus)
.onTapGesture {
nav_target = ev
navigating = true