Tap area improvements + live status in profile tab

This commit is contained in:
Thomas Ricouard 2022-12-26 08:47:41 +01:00
parent bda77571b6
commit 48ed60b095
7 changed files with 78 additions and 29 deletions

View file

@ -8,6 +8,8 @@ import Env
public struct AccountDetailView: View {
@Environment(\.redactionReasons) private var reasons
@EnvironmentObject private var watcher: StreamWatcher
@EnvironmentObject private var currentAccount: CurrentAccount
@EnvironmentObject private var theme: Theme
@EnvironmentObject private var client: Client
@EnvironmentObject private var routeurPath: RouterPath
@ -77,6 +79,12 @@ public struct AccountDetailView: View {
await viewModel.fetchStatuses()
}
}
.onChange(of: watcher.latestEvent?.id) { id in
if let latestEvent = watcher.latestEvent,
viewModel.accountId == currentAccount.account?.id {
viewModel.handleEvent(event: latestEvent, currentAccount: currentAccount)
}
}
.edgesIgnoringSafeArea(.top)
.navigationTitle(Text(scrollOffset < -200 ? viewModel.title : ""))
}

View file

@ -2,6 +2,7 @@ import SwiftUI
import Network
import Models
import Status
import Env
@MainActor
class AccountDetailViewModel: ObservableObject, StatusesFetcher {
@ -170,4 +171,21 @@ class AccountDetailViewModel: ObservableObject, StatusesFetcher {
tabState = .followedTags(tags: followedTags)
}
}
func handleEvent(event: any StreamEvent, currentAccount: CurrentAccount) {
if let event = event as? StreamEventUpdate {
if event.status.account.id == currentAccount.account?.id {
statuses.insert(event.status, at: 0)
statusesState = .display(statuses: statuses, nextPageState: .hasNextPage)
}
} else if let event = event as? StreamEventDelete {
statuses.removeAll(where: { $0.id == event.status })
statusesState = .display(statuses: statuses, nextPageState: .hasNextPage)
} else if let event = event as? StreamEventStatusUpdate {
if let originalIndex = statuses.firstIndex(where: { $0.id == event.status.id }) {
statuses[originalIndex] = event.status
statusesState = .display(statuses: statuses, nextPageState: .hasNextPage)
}
}
}
}

View file

@ -51,6 +51,7 @@ public struct AccountsListRow: View {
.onAppear {
viewModel.client = client
}
.contentShape(Rectangle())
.onTapGesture {
routeurPath.navigate(to: .accountDetailWithAccount(account: viewModel.account))
}

View file

@ -22,6 +22,7 @@ public struct TagRowView: View {
}
Spacer()
}
.contentShape(Rectangle())
.onTapGesture {
routeurPath.navigate(to: .hashTag(tag: tag.name, account: nil))
}

View file

@ -28,9 +28,6 @@ struct NotificationRowView: View {
private func makeAvatarView(type: Models.Notification.NotificationType) -> some View {
ZStack(alignment: .topLeading) {
AvatarView(url: notification.account.avatar)
.onTapGesture {
routeurPath.navigate(to: .accountDetailWithAccount(account: notification.account))
}
ZStack(alignment: .center) {
Circle()
.strokeBorder(Color.white, lineWidth: 1)
@ -44,6 +41,10 @@ struct NotificationRowView: View {
}
.offset(x: -14, y: -4)
}
.contentShape(Rectangle())
.onTapGesture {
routeurPath.navigate(to: .accountDetailWithAccount(account: notification.account))
}
}
private func makeMainLabel(type: Models.Notification.NotificationType) -> some View {
@ -64,6 +65,10 @@ struct NotificationRowView: View {
Spacer()
}
}
.contentShape(Rectangle())
.onTapGesture {
routeurPath.navigate(to: .accountDetailWithAccount(account: notification.account))
}
}
@ViewBuilder
@ -78,18 +83,24 @@ struct NotificationRowView: View {
)
.padding(.top, 8)
} else {
Text("@\(notification.account.acct)")
.font(.callout)
.foregroundColor(.gray)
if type == .follow {
Text(notification.account.note.asSafeAttributedString)
.lineLimit(3)
Group {
Text("@\(notification.account.acct)")
.font(.callout)
.foregroundColor(.gray)
.environment(\.openURL, OpenURLAction { url in
routeurPath.handle(url: url)
})
if type == .follow {
Text(notification.account.note.asSafeAttributedString)
.lineLimit(3)
.font(.callout)
.foregroundColor(.gray)
.environment(\.openURL, OpenURLAction { url in
routeurPath.handle(url: url)
})
}
}
.contentShape(Rectangle())
.onTapGesture {
routeurPath.navigate(to: .accountDetailWithAccount(account: notification.account))
}
}
}

View file

@ -55,6 +55,7 @@ public struct StatusDetailView: View {
}
}
.padding(.horizontal, DS.Constants.layoutPadding)
.padding(.top, DS.Constants.layoutPadding)
}
.task {
guard !isLoaded else { return }

View file

@ -27,6 +27,10 @@ public struct StatusRowView: View {
StatusActionsView(viewModel: viewModel)
.padding(.vertical, 8)
.tint(viewModel.isFocused ? theme.tintColor : .gray)
.contentShape(Rectangle())
.onTapGesture {
routeurPath.navigate(to: .statusDetail(id: viewModel.status.reblog?.id ?? viewModel.status.id))
}
}
}
.onAppear {
@ -84,25 +88,28 @@ public struct StatusRowView: View {
}
}
Text(status.content.asSafeAttributedString)
.font(.body)
.onTapGesture {
routeurPath.navigate(to: .statusDetail(id: status.id))
Group {
Text(status.content.asSafeAttributedString)
.font(.body)
.environment(\.openURL, OpenURLAction { url in
routeurPath.handleStatus(status: status, url: url)
})
if !status.mediaAttachments.isEmpty {
if viewModel.isEmbed {
Image(systemName: "paperclip")
} else {
StatusMediaPreviewView(attachements: status.mediaAttachments)
.padding(.vertical, 4)
}
}
.environment(\.openURL, OpenURLAction { url in
routeurPath.handleStatus(status: status, url: url)
})
if !status.mediaAttachments.isEmpty {
if viewModel.isEmbed {
Image(systemName: "paperclip")
} else {
StatusMediaPreviewView(attachements: status.mediaAttachments)
.padding(.vertical, 4)
if let card = status.card, !viewModel.isEmbed {
StatusCardView(card: card)
}
}
if let card = status.card, !viewModel.isEmbed {
StatusCardView(card: card)
.contentShape(Rectangle())
.onTapGesture {
routeurPath.navigate(to: .statusDetail(id: viewModel.status.reblog?.id ?? viewModel.status.id))
}
}
}
@ -130,8 +137,10 @@ public struct StatusRowView: View {
contextMenu
} label: {
Image(systemName: "ellipsis")
.frame(width: 30, height: 30)
}
.foregroundColor(.gray)
.contentShape(Rectangle())
}
@ViewBuilder