diff --git a/Packages/Notifications/Sources/Notifications/NotificationRowView.swift b/Packages/Notifications/Sources/Notifications/NotificationRowView.swift index 737ab154..b5f08bfb 100644 --- a/Packages/Notifications/Sources/Notifications/NotificationRowView.swift +++ b/Packages/Notifications/Sources/Notifications/NotificationRowView.swift @@ -13,46 +13,85 @@ struct NotificationRowView: View { var body: some View { if let type = notification.supportedType { HStack(alignment: .top, spacing: 8) { - AvatarView(url: notification.account.avatar) - .onTapGesture { - routeurPath.navigate(to: .accountDetailWithAccount(account: notification.account)) - } + makeAvatarView(type: type) 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() - } - 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) - } + makeMainLabel(type: type) + makeContent(type: type) } } } else { 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 { @@ -76,6 +115,25 @@ extension Models.Notification.NotificationType { 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 { diff --git a/Packages/Status/Sources/Status/Row/StatusRowView.swift b/Packages/Status/Sources/Status/Row/StatusRowView.swift index bb3afb0d..150871c3 100644 --- a/Packages/Status/Sources/Status/Row/StatusRowView.swift +++ b/Packages/Status/Sources/Status/Row/StatusRowView.swift @@ -16,8 +16,10 @@ public struct StatusRowView: View { public var body: some View { VStack(alignment: .leading) { - reblogView - replyView + if !viewModel.isEmbed { + reblogView + replyView + } statusView if !viewModel.isEmbed { StatusActionsView(viewModel: viewModel)