From 48ed60b09566e311f6cef95855f2b78e454dfb37 Mon Sep 17 00:00:00 2001 From: Thomas Ricouard Date: Mon, 26 Dec 2022 08:47:41 +0100 Subject: [PATCH] Tap area improvements + live status in profile tab --- .../Sources/Account/AccountDetailView.swift | 8 ++++ .../Account/AccountDetailViewModel.swift | 18 ++++++++ .../AccountsLIst/AccountsListRow.swift | 1 + .../DesignSystem/Views/TagRowView.swift | 1 + .../Notifications/NotificationRowView.swift | 37 +++++++++++------ .../Status/Detail/StatusDetailVIew.swift | 1 + .../Sources/Status/Row/StatusRowView.swift | 41 +++++++++++-------- 7 files changed, 78 insertions(+), 29 deletions(-) diff --git a/Packages/Account/Sources/Account/AccountDetailView.swift b/Packages/Account/Sources/Account/AccountDetailView.swift index f00b2262..5d221865 100644 --- a/Packages/Account/Sources/Account/AccountDetailView.swift +++ b/Packages/Account/Sources/Account/AccountDetailView.swift @@ -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 : "")) } diff --git a/Packages/Account/Sources/Account/AccountDetailViewModel.swift b/Packages/Account/Sources/Account/AccountDetailViewModel.swift index 437f6fc7..a6ef3f15 100644 --- a/Packages/Account/Sources/Account/AccountDetailViewModel.swift +++ b/Packages/Account/Sources/Account/AccountDetailViewModel.swift @@ -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) + } + } + } } diff --git a/Packages/Account/Sources/Account/AccountsLIst/AccountsListRow.swift b/Packages/Account/Sources/Account/AccountsLIst/AccountsListRow.swift index 6e21d8e7..cb321350 100644 --- a/Packages/Account/Sources/Account/AccountsLIst/AccountsListRow.swift +++ b/Packages/Account/Sources/Account/AccountsLIst/AccountsListRow.swift @@ -51,6 +51,7 @@ public struct AccountsListRow: View { .onAppear { viewModel.client = client } + .contentShape(Rectangle()) .onTapGesture { routeurPath.navigate(to: .accountDetailWithAccount(account: viewModel.account)) } diff --git a/Packages/DesignSystem/Sources/DesignSystem/Views/TagRowView.swift b/Packages/DesignSystem/Sources/DesignSystem/Views/TagRowView.swift index 97f30353..65161fdc 100644 --- a/Packages/DesignSystem/Sources/DesignSystem/Views/TagRowView.swift +++ b/Packages/DesignSystem/Sources/DesignSystem/Views/TagRowView.swift @@ -22,6 +22,7 @@ public struct TagRowView: View { } Spacer() } + .contentShape(Rectangle()) .onTapGesture { routeurPath.navigate(to: .hashTag(tag: tag.name, account: nil)) } diff --git a/Packages/Notifications/Sources/Notifications/NotificationRowView.swift b/Packages/Notifications/Sources/Notifications/NotificationRowView.swift index 03da8ae0..42aa7411 100644 --- a/Packages/Notifications/Sources/Notifications/NotificationRowView.swift +++ b/Packages/Notifications/Sources/Notifications/NotificationRowView.swift @@ -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)) } } } diff --git a/Packages/Status/Sources/Status/Detail/StatusDetailVIew.swift b/Packages/Status/Sources/Status/Detail/StatusDetailVIew.swift index 38d1b566..f8bbd90b 100644 --- a/Packages/Status/Sources/Status/Detail/StatusDetailVIew.swift +++ b/Packages/Status/Sources/Status/Detail/StatusDetailVIew.swift @@ -55,6 +55,7 @@ public struct StatusDetailView: View { } } .padding(.horizontal, DS.Constants.layoutPadding) + .padding(.top, DS.Constants.layoutPadding) } .task { guard !isLoaded else { return } diff --git a/Packages/Status/Sources/Status/Row/StatusRowView.swift b/Packages/Status/Sources/Status/Row/StatusRowView.swift index b453024a..73429f5d 100644 --- a/Packages/Status/Sources/Status/Row/StatusRowView.swift +++ b/Packages/Status/Sources/Status/Row/StatusRowView.swift @@ -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