mirror of
https://github.com/Dimillian/IceCubesApp.git
synced 2025-01-03 12:58:50 +00:00
Tap area improvements + live status in profile tab
This commit is contained in:
parent
bda77571b6
commit
48ed60b095
7 changed files with 78 additions and 29 deletions
|
@ -8,6 +8,8 @@ import Env
|
||||||
|
|
||||||
public struct AccountDetailView: View {
|
public struct AccountDetailView: View {
|
||||||
@Environment(\.redactionReasons) private var reasons
|
@Environment(\.redactionReasons) private var reasons
|
||||||
|
@EnvironmentObject private var watcher: StreamWatcher
|
||||||
|
@EnvironmentObject private var currentAccount: CurrentAccount
|
||||||
@EnvironmentObject private var theme: Theme
|
@EnvironmentObject private var theme: Theme
|
||||||
@EnvironmentObject private var client: Client
|
@EnvironmentObject private var client: Client
|
||||||
@EnvironmentObject private var routeurPath: RouterPath
|
@EnvironmentObject private var routeurPath: RouterPath
|
||||||
|
@ -77,6 +79,12 @@ public struct AccountDetailView: View {
|
||||||
await viewModel.fetchStatuses()
|
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)
|
.edgesIgnoringSafeArea(.top)
|
||||||
.navigationTitle(Text(scrollOffset < -200 ? viewModel.title : ""))
|
.navigationTitle(Text(scrollOffset < -200 ? viewModel.title : ""))
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ import SwiftUI
|
||||||
import Network
|
import Network
|
||||||
import Models
|
import Models
|
||||||
import Status
|
import Status
|
||||||
|
import Env
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
class AccountDetailViewModel: ObservableObject, StatusesFetcher {
|
class AccountDetailViewModel: ObservableObject, StatusesFetcher {
|
||||||
|
@ -170,4 +171,21 @@ class AccountDetailViewModel: ObservableObject, StatusesFetcher {
|
||||||
tabState = .followedTags(tags: followedTags)
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,7 @@ public struct AccountsListRow: View {
|
||||||
.onAppear {
|
.onAppear {
|
||||||
viewModel.client = client
|
viewModel.client = client
|
||||||
}
|
}
|
||||||
|
.contentShape(Rectangle())
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
routeurPath.navigate(to: .accountDetailWithAccount(account: viewModel.account))
|
routeurPath.navigate(to: .accountDetailWithAccount(account: viewModel.account))
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ public struct TagRowView: View {
|
||||||
}
|
}
|
||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
|
.contentShape(Rectangle())
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
routeurPath.navigate(to: .hashTag(tag: tag.name, account: nil))
|
routeurPath.navigate(to: .hashTag(tag: tag.name, account: nil))
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,9 +28,6 @@ struct NotificationRowView: View {
|
||||||
private func makeAvatarView(type: Models.Notification.NotificationType) -> some View {
|
private func makeAvatarView(type: Models.Notification.NotificationType) -> some View {
|
||||||
ZStack(alignment: .topLeading) {
|
ZStack(alignment: .topLeading) {
|
||||||
AvatarView(url: notification.account.avatar)
|
AvatarView(url: notification.account.avatar)
|
||||||
.onTapGesture {
|
|
||||||
routeurPath.navigate(to: .accountDetailWithAccount(account: notification.account))
|
|
||||||
}
|
|
||||||
ZStack(alignment: .center) {
|
ZStack(alignment: .center) {
|
||||||
Circle()
|
Circle()
|
||||||
.strokeBorder(Color.white, lineWidth: 1)
|
.strokeBorder(Color.white, lineWidth: 1)
|
||||||
|
@ -44,6 +41,10 @@ struct NotificationRowView: View {
|
||||||
}
|
}
|
||||||
.offset(x: -14, y: -4)
|
.offset(x: -14, y: -4)
|
||||||
}
|
}
|
||||||
|
.contentShape(Rectangle())
|
||||||
|
.onTapGesture {
|
||||||
|
routeurPath.navigate(to: .accountDetailWithAccount(account: notification.account))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func makeMainLabel(type: Models.Notification.NotificationType) -> some View {
|
private func makeMainLabel(type: Models.Notification.NotificationType) -> some View {
|
||||||
|
@ -64,6 +65,10 @@ struct NotificationRowView: View {
|
||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.contentShape(Rectangle())
|
||||||
|
.onTapGesture {
|
||||||
|
routeurPath.navigate(to: .accountDetailWithAccount(account: notification.account))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
|
@ -78,18 +83,24 @@ struct NotificationRowView: View {
|
||||||
)
|
)
|
||||||
.padding(.top, 8)
|
.padding(.top, 8)
|
||||||
} else {
|
} else {
|
||||||
Text("@\(notification.account.acct)")
|
Group {
|
||||||
.font(.callout)
|
Text("@\(notification.account.acct)")
|
||||||
.foregroundColor(.gray)
|
|
||||||
|
|
||||||
if type == .follow {
|
|
||||||
Text(notification.account.note.asSafeAttributedString)
|
|
||||||
.lineLimit(3)
|
|
||||||
.font(.callout)
|
.font(.callout)
|
||||||
.foregroundColor(.gray)
|
.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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,7 @@ public struct StatusDetailView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(.horizontal, DS.Constants.layoutPadding)
|
.padding(.horizontal, DS.Constants.layoutPadding)
|
||||||
|
.padding(.top, DS.Constants.layoutPadding)
|
||||||
}
|
}
|
||||||
.task {
|
.task {
|
||||||
guard !isLoaded else { return }
|
guard !isLoaded else { return }
|
||||||
|
|
|
@ -27,6 +27,10 @@ public struct StatusRowView: View {
|
||||||
StatusActionsView(viewModel: viewModel)
|
StatusActionsView(viewModel: viewModel)
|
||||||
.padding(.vertical, 8)
|
.padding(.vertical, 8)
|
||||||
.tint(viewModel.isFocused ? theme.tintColor : .gray)
|
.tint(viewModel.isFocused ? theme.tintColor : .gray)
|
||||||
|
.contentShape(Rectangle())
|
||||||
|
.onTapGesture {
|
||||||
|
routeurPath.navigate(to: .statusDetail(id: viewModel.status.reblog?.id ?? viewModel.status.id))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.onAppear {
|
.onAppear {
|
||||||
|
@ -84,25 +88,28 @@ public struct StatusRowView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Text(status.content.asSafeAttributedString)
|
Group {
|
||||||
.font(.body)
|
Text(status.content.asSafeAttributedString)
|
||||||
.onTapGesture {
|
.font(.body)
|
||||||
routeurPath.navigate(to: .statusDetail(id: status.id))
|
.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
|
if let card = status.card, !viewModel.isEmbed {
|
||||||
routeurPath.handleStatus(status: status, url: url)
|
StatusCardView(card: card)
|
||||||
})
|
|
||||||
|
|
||||||
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 {
|
.contentShape(Rectangle())
|
||||||
StatusCardView(card: card)
|
.onTapGesture {
|
||||||
|
routeurPath.navigate(to: .statusDetail(id: viewModel.status.reblog?.id ?? viewModel.status.id))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -130,8 +137,10 @@ public struct StatusRowView: View {
|
||||||
contextMenu
|
contextMenu
|
||||||
} label: {
|
} label: {
|
||||||
Image(systemName: "ellipsis")
|
Image(systemName: "ellipsis")
|
||||||
|
.frame(width: 30, height: 30)
|
||||||
}
|
}
|
||||||
.foregroundColor(.gray)
|
.foregroundColor(.gray)
|
||||||
|
.contentShape(Rectangle())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
|
|
Loading…
Reference in a new issue