Bubble/Threaded/Components/NotificationRow.swift

152 lines
5.4 KiB
Swift

//Made by Lumaa
import SwiftUI
struct NotificationRow: View {
@EnvironmentObject private var navigator: Navigator
var notif: Notification = .placeholder()
var showIcon: Bool = true
var body: some View {
VStack {
HStack(spacing: 5) {
ProfilePicture(url: notif.account.avatar, size: 60)
.padding(.trailing)
.overlay(alignment: .bottomTrailing) {
if showIcon {
notifIcon()
.offset(x: -5, y: 5)
}
}
.padding(.horizontal, 10)
.onTapGesture {
navigator.navigate(to: .account(acc: notif.account))
}
VStack(alignment: .leading) {
Text(localizedString())
.multilineTextAlignment(.leading)
.font(.subheadline)
.lineLimit(2)
if notif.status != nil {
TextEmoji(notif.status!.content, emojis: notif.status!.emojis)
.multilineTextAlignment(.leading)
.font(.caption)
.foregroundStyle(Color.gray)
.lineLimit(3, reservesSpace: true)
if notif.status!.mediaAttachments.count > 0 {
Label("activity.status.attachments-\(notif.status!.mediaAttachments.count)", systemImage: "photo.on.rectangle.angled")
.multilineTextAlignment(.leading)
.font(.caption)
.foregroundStyle(Color.gray)
.lineLimit(1, reservesSpace: false)
}
} else {
TextEmoji(notif.account.note, emojis: notif.account.emojis)
.multilineTextAlignment(.leading)
.font(.caption)
.foregroundStyle(Color.gray)
.lineLimit(3, reservesSpace: true)
}
}
.contentShape(Rectangle())
.onTapGesture {
navigator.navigate(to: notif.status == nil ? .account(acc: notif.account) : .post(status: notif.status!))
}
}
.padding(.horizontal)
}
}
private func localizedString() -> LocalizedStringKey {
let nameStr = "@\(notif.account.username)"
switch (notif.supportedType) {
case .favourite:
return "activity.favorite.\(nameStr)"
case .follow:
return "activity.followed.\(nameStr)"
case .mention:
return "activity.mentionned.\(nameStr)"
case .reblog:
return "activity.reblogged.\(nameStr)"
case .status:
return "activity.status.\(nameStr)"
default:
return "activity.unknown" // follow requests & polls
}
}
private func notifColor() -> Color {
switch (notif.supportedType) {
case .favourite:
return Color.red
case .follow:
return Color.purple
case .mention:
return Color.blue
case .reblog:
return Color.orange
case .status:
return Color.yellow
default:
return Color.gray
}
}
@ViewBuilder
private func notifIcon() -> some View {
let size: CGFloat = 60.0 / 4.0
ZStack {
switch (notif.supportedType) {
case .favourite:
Image(systemName: "heart.fill")
.resizable()
.scaledToFit()
.frame(width: size, height: size)
case .follow:
Image(systemName: "person.fill.badge.plus")
.resizable()
.scaledToFit()
.frame(width: size, height: size)
case .mention:
Image(systemName: "tag.fill")
.resizable()
.scaledToFit()
.frame(width: size, height: size)
case .reblog:
Image(systemName: "bolt.horizontal.fill")
.resizable()
.scaledToFit()
.frame(width: size, height: size)
case .status:
Image(systemName: "text.badge.plus")
.resizable()
.scaledToFit()
.frame(width: size, height: size)
default:
Image(systemName: "questionmark")
.resizable()
.scaledToFit()
.frame(width: size, height: size)
}
}
.frame(minWidth: 30)
.padding(7)
.background(notifColor())
.clipShape(.circle)
.overlay {
Circle()
.stroke(Color.appBackground, lineWidth: 3)
}
.fixedSize()
}
}
#Preview {
NotificationRow()
}