mirror of
https://github.com/Dimillian/IceCubesApp.git
synced 2024-12-23 07:36:48 +00:00
Better notifications UX
This commit is contained in:
parent
8de2a8192b
commit
2c39af280e
2 changed files with 95 additions and 35 deletions
|
@ -13,46 +13,85 @@ struct NotificationRowView: View {
|
||||||
var body: some View {
|
var body: some View {
|
||||||
if let type = notification.supportedType {
|
if let type = notification.supportedType {
|
||||||
HStack(alignment: .top, spacing: 8) {
|
HStack(alignment: .top, spacing: 8) {
|
||||||
AvatarView(url: notification.account.avatar)
|
makeAvatarView(type: type)
|
||||||
.onTapGesture {
|
|
||||||
routeurPath.navigate(to: .accountDetailWithAccount(account: notification.account))
|
|
||||||
}
|
|
||||||
VStack(alignment: .leading, spacing: 0) {
|
VStack(alignment: .leading, spacing: 0) {
|
||||||
HStack(spacing: 0) {
|
makeMainLabel(type: type)
|
||||||
Text(notification.account.displayName)
|
makeContent(type: type)
|
||||||
.font(.subheadline)
|
|
||||||
.fontWeight(.semibold) +
|
|
||||||
Text(" ") +
|
|
||||||
Text(type.label())
|
|
||||||
.font(.subheadline) +
|
|
||||||
Text(" ⸱ ")
|
|
||||||
.font(.footnote)
|
|
||||||
.foregroundColor(.gray) +
|
|
||||||
Text(notification.createdAt.formatted)
|
|
||||||
.font(.footnote)
|
|
||||||
.foregroundColor(.gray)
|
|
||||||
Spacer()
|
|
||||||
}
|
|
||||||
if let status = notification.status {
|
|
||||||
StatusRowView(viewModel: .init(status: status, isEmbed: true))
|
|
||||||
.padding(8)
|
|
||||||
.background(Color.gray.opacity(0.10))
|
|
||||||
.overlay(
|
|
||||||
RoundedRectangle(cornerRadius: 4)
|
|
||||||
.stroke(.gray.opacity(0.35), lineWidth: 1)
|
|
||||||
)
|
|
||||||
.padding(.top, 8)
|
|
||||||
} else {
|
|
||||||
Text(notification.account.acct)
|
|
||||||
.font(.callout)
|
|
||||||
.foregroundColor(.gray)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
EmptyView()
|
EmptyView()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
.background(Circle().foregroundColor(Color.brand))
|
||||||
|
.frame(width: 24, height: 24)
|
||||||
|
|
||||||
|
Image(systemName: type.iconName())
|
||||||
|
.resizable()
|
||||||
|
.frame(width: 12, height: 12)
|
||||||
|
.foregroundColor(.white)
|
||||||
|
}
|
||||||
|
.offset(x: -14, y: -4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func makeMainLabel(type: Models.Notification.NotificationType) -> some View {
|
||||||
|
VStack(alignment: .leading, spacing: 0) {
|
||||||
|
HStack(spacing: 0) {
|
||||||
|
Text(notification.account.displayName)
|
||||||
|
.font(.subheadline)
|
||||||
|
.fontWeight(.semibold) +
|
||||||
|
Text(" ") +
|
||||||
|
Text(type.label())
|
||||||
|
.font(.subheadline) +
|
||||||
|
Text(" ⸱ ")
|
||||||
|
.font(.footnote)
|
||||||
|
.foregroundColor(.gray) +
|
||||||
|
Text(notification.createdAt.formatted)
|
||||||
|
.font(.footnote)
|
||||||
|
.foregroundColor(.gray)
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ViewBuilder
|
||||||
|
private func makeContent(type: Models.Notification.NotificationType) -> some View {
|
||||||
|
if let status = notification.status {
|
||||||
|
StatusRowView(viewModel: .init(status: status, isEmbed: true))
|
||||||
|
.padding(8)
|
||||||
|
.background(Color.gray.opacity(0.10))
|
||||||
|
.overlay(
|
||||||
|
RoundedRectangle(cornerRadius: 4)
|
||||||
|
.stroke(.gray.opacity(0.35), lineWidth: 1)
|
||||||
|
)
|
||||||
|
.padding(.top, 8)
|
||||||
|
} else {
|
||||||
|
Text(notification.account.acct)
|
||||||
|
.font(.callout)
|
||||||
|
.foregroundColor(.gray)
|
||||||
|
|
||||||
|
if type == .follow {
|
||||||
|
Text(notification.account.note.asSafeAttributedString)
|
||||||
|
.lineLimit(3)
|
||||||
|
.font(.body)
|
||||||
|
.foregroundColor(.gray)
|
||||||
|
.environment(\.openURL, OpenURLAction { url in
|
||||||
|
routeurPath.handle(url: url)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Models.Notification.NotificationType {
|
extension Models.Notification.NotificationType {
|
||||||
|
@ -76,6 +115,25 @@ extension Models.Notification.NotificationType {
|
||||||
return "has been edited"
|
return "has been edited"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func iconName() -> String {
|
||||||
|
switch self {
|
||||||
|
case .status:
|
||||||
|
return "pencil"
|
||||||
|
case .mention:
|
||||||
|
return "at"
|
||||||
|
case .reblog:
|
||||||
|
return "arrow.left.arrow.right.circle.fill"
|
||||||
|
case .follow, .follow_request:
|
||||||
|
return "person.fill.badge.plus"
|
||||||
|
case .favourite:
|
||||||
|
return "star.fill"
|
||||||
|
case .poll:
|
||||||
|
return "chart.bar.fill"
|
||||||
|
case .update:
|
||||||
|
return "pencil.line"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct NotificationRowView_Previews: PreviewProvider {
|
struct NotificationRowView_Previews: PreviewProvider {
|
||||||
|
|
|
@ -16,8 +16,10 @@ public struct StatusRowView: View {
|
||||||
|
|
||||||
public var body: some View {
|
public var body: some View {
|
||||||
VStack(alignment: .leading) {
|
VStack(alignment: .leading) {
|
||||||
reblogView
|
if !viewModel.isEmbed {
|
||||||
replyView
|
reblogView
|
||||||
|
replyView
|
||||||
|
}
|
||||||
statusView
|
statusView
|
||||||
if !viewModel.isEmbed {
|
if !viewModel.isEmbed {
|
||||||
StatusActionsView(viewModel: viewModel)
|
StatusActionsView(viewModel: viewModel)
|
||||||
|
|
Loading…
Reference in a new issue