137 lines
4.1 KiB
Swift
137 lines
4.1 KiB
Swift
import SwiftUI
|
|
import Kingfisher
|
|
|
|
struct ChannelDonationItemView: View {
|
|
let item: GetChannelDonationListItem
|
|
let previewLimit: Int?
|
|
let isShowFullMessageOnTap: Bool
|
|
|
|
@State private var isExpanded = false
|
|
|
|
init(
|
|
item: GetChannelDonationListItem,
|
|
previewLimit: Int? = nil,
|
|
isShowFullMessageOnTap: Bool = false
|
|
) {
|
|
self.item = item
|
|
self.previewLimit = previewLimit
|
|
self.isShowFullMessageOnTap = isShowFullMessageOnTap
|
|
}
|
|
|
|
private var donationBackgroundColor: Color {
|
|
if item.isSecret {
|
|
return Color(hex: "59548f").opacity(0.8)
|
|
}
|
|
|
|
if item.can >= 10000 {
|
|
return Color(hex: "c25264").opacity(0.8)
|
|
}
|
|
|
|
if item.can >= 5000 {
|
|
return Color(hex: "d85e37").opacity(0.8)
|
|
}
|
|
|
|
if item.can >= 1000 {
|
|
return Color(hex: "d38c38").opacity(0.8)
|
|
}
|
|
|
|
if item.can >= 500 {
|
|
return Color(hex: "c25264").opacity(0.8)
|
|
}
|
|
|
|
if item.can >= 100 {
|
|
return Color(hex: "4d6aa4").opacity(0.8)
|
|
}
|
|
|
|
if item.can >= 50 {
|
|
return Color(hex: "2d7390").opacity(0.8)
|
|
}
|
|
|
|
return Color(hex: "548f7d").opacity(0.8)
|
|
}
|
|
|
|
var body: some View {
|
|
VStack(alignment: .leading, spacing: 10) {
|
|
HStack(spacing: 11) {
|
|
KFImage(URL(string: item.profileUrl))
|
|
.cancelOnDisappear(true)
|
|
.downsampling(size: CGSize(width: 40, height: 40))
|
|
.resizable()
|
|
.scaledToFill()
|
|
.frame(width: 40, height: 40)
|
|
.clipShape(Circle())
|
|
|
|
VStack(alignment: .leading, spacing: 2) {
|
|
Text(item.nickname)
|
|
.appFont(size: 18, weight: .bold)
|
|
.foregroundColor(.white)
|
|
.lineLimit(1)
|
|
|
|
Text(item.relativeTimeText())
|
|
.appFont(size: 14, weight: .regular)
|
|
.foregroundColor(Color(hex: "78909C"))
|
|
}
|
|
|
|
Spacer()
|
|
}
|
|
|
|
highlightedMessageText(displayMessage)
|
|
.appFont(size: 16, weight: .regular)
|
|
.lineLimit(isExpanded ? nil : 2)
|
|
.multilineTextAlignment(.leading)
|
|
.frame(maxWidth: .infinity, alignment: .leading)
|
|
}
|
|
.padding(16)
|
|
.frame(maxWidth: .infinity, alignment: .leading)
|
|
.background(donationBackgroundColor)
|
|
.cornerRadius(16)
|
|
.onTapGesture {
|
|
guard isShowFullMessageOnTap else { return }
|
|
guard isTruncated else { return }
|
|
isExpanded = true
|
|
}
|
|
}
|
|
}
|
|
|
|
private extension ChannelDonationItemView {
|
|
var normalizedMessage: String {
|
|
item.message.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
}
|
|
|
|
var displayMessage: String {
|
|
guard !isExpanded else { return normalizedMessage }
|
|
guard let previewLimit else { return normalizedMessage }
|
|
|
|
if normalizedMessage.count > previewLimit {
|
|
return String(normalizedMessage.prefix(previewLimit)) + "..."
|
|
}
|
|
|
|
return normalizedMessage
|
|
}
|
|
|
|
var isTruncated: Bool {
|
|
guard let previewLimit else { return false }
|
|
return normalizedMessage.count > previewLimit
|
|
}
|
|
|
|
func highlightedMessageText(_ message: String) -> Text {
|
|
let plainCanToken = "\(item.can)캔"
|
|
let commaCanToken = "\(item.can.comma())캔"
|
|
|
|
let range = message.range(of: commaCanToken)
|
|
?? message.range(of: plainCanToken)
|
|
|
|
guard let range else {
|
|
return Text(message).foregroundColor(Color(hex: "CFD8DC"))
|
|
}
|
|
|
|
let prefixText = String(message[..<range.lowerBound])
|
|
let canText = String(message[range])
|
|
let suffixText = String(message[range.upperBound...])
|
|
|
|
return Text(prefixText).foregroundColor(Color(hex: "CFD8DC"))
|
|
+ Text(canText).foregroundColor(Color(hex: "FDCA2F"))
|
|
+ Text(suffixText).foregroundColor(Color(hex: "CFD8DC"))
|
|
}
|
|
}
|