189 lines
4.9 KiB
Swift
189 lines
4.9 KiB
Swift
import Models
|
|
import SwiftUI
|
|
import Utils
|
|
|
|
public struct TextChip: View {
|
|
@Environment(\.colorScheme) var colorScheme
|
|
|
|
let checked: Bool
|
|
let padded: Bool
|
|
var onTap: ((TextChip) -> Void)?
|
|
|
|
public init(text: String, color: Color, negated: Bool = false) {
|
|
self.text = text
|
|
self.color = color
|
|
self.negated = negated
|
|
self.checked = false
|
|
self.padded = false
|
|
}
|
|
|
|
public init?(feedItemLabel: LinkedItemLabel, negated: Bool = false) {
|
|
guard let color = Color(hex: feedItemLabel.color ?? "") else { return nil }
|
|
|
|
self.text = feedItemLabel.name ?? ""
|
|
self.color = color
|
|
self.negated = negated
|
|
self.checked = false
|
|
self.padded = false
|
|
}
|
|
|
|
// swiftlint:disable:next line_length
|
|
public init?(feedItemLabel: LinkedItemLabel, negated: Bool = false, checked: Bool = false, padded: Bool = false, onTap: ((TextChip) -> Void)?) {
|
|
guard let color = Color(hex: feedItemLabel.color ?? "") else {
|
|
return nil
|
|
}
|
|
|
|
self.text = feedItemLabel.name ?? ""
|
|
self.color = color
|
|
self.negated = negated
|
|
self.onTap = onTap
|
|
self.checked = checked
|
|
self.padded = padded
|
|
}
|
|
|
|
public let text: String
|
|
let color: Color
|
|
let negated: Bool
|
|
|
|
var textColor: Color {
|
|
guard let luminance = color.luminance else {
|
|
return .white
|
|
}
|
|
|
|
return luminance > 0.35 ? .black : .white
|
|
}
|
|
|
|
var backgroundColor: Color {
|
|
color.opacity(0.9)
|
|
}
|
|
|
|
var checkedBorderColor: Color {
|
|
colorScheme == .dark ? Color.white : Color.black
|
|
}
|
|
|
|
var borderColor: Color {
|
|
checked ? checkedBorderColor : Color.clear
|
|
}
|
|
|
|
public var body: some View {
|
|
ZStack(alignment: .topTrailing) {
|
|
Text(text)
|
|
.strikethrough(color: negated ? textColor : .clear)
|
|
.padding(.horizontal, padded ? 10 : 8)
|
|
.padding(.vertical, padded ? 8 : 5)
|
|
.font(.appCaptionMedium)
|
|
.foregroundColor(textColor)
|
|
.lineLimit(1)
|
|
.background(
|
|
RoundedRectangle(cornerRadius: 4)
|
|
.fill(backgroundColor)
|
|
)
|
|
.overlay(
|
|
RoundedRectangle(cornerRadius: 4)
|
|
.stroke(borderColor, lineWidth: 2)
|
|
)
|
|
.padding(1)
|
|
}.onTapGesture {
|
|
if let onTap = onTap {
|
|
onTap(self)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public struct TextChipButton: View {
|
|
public static func makeAddLabelButton(onTap: @escaping () -> Void) -> TextChipButton {
|
|
TextChipButton(title: LocalText.labelsGeneric, color: .systemGray6, actionType: .show, negated: false, onTap: onTap)
|
|
}
|
|
|
|
public static func makeMenuButton(title: String) -> TextChipButton {
|
|
TextChipButton(title: title, color: .systemGray6, actionType: .show, negated: false, onTap: {})
|
|
}
|
|
|
|
public static func makeSearchFilterButton(title: String, onTap: @escaping () -> Void) -> TextChipButton {
|
|
TextChipButton(title: title, color: .appCtaYellow, actionType: .filter, negated: false, onTap: onTap)
|
|
}
|
|
|
|
public static func makeShowOptionsButton(title: String, onTap: @escaping () -> Void) -> TextChipButton {
|
|
TextChipButton(title: title, color: .appButtonBackground, actionType: .add, negated: false, onTap: onTap)
|
|
}
|
|
|
|
public static func makeRemovableLabelButton(
|
|
feedItemLabel: LinkedItemLabel,
|
|
negated: Bool,
|
|
onTap: @escaping () -> Void
|
|
) -> TextChipButton {
|
|
TextChipButton(
|
|
title: feedItemLabel.name ?? "",
|
|
color: Color(hex: feedItemLabel.color ?? "") ?? .appButtonBackground,
|
|
actionType: .remove,
|
|
negated: negated,
|
|
onTap: onTap
|
|
)
|
|
}
|
|
|
|
public enum ActionType {
|
|
case remove
|
|
case add
|
|
case show
|
|
case filter
|
|
|
|
var systemIconName: String {
|
|
switch self {
|
|
case .filter, .remove:
|
|
return "xmark"
|
|
case .add:
|
|
return "plus"
|
|
case .show:
|
|
return "chevron.down"
|
|
}
|
|
}
|
|
}
|
|
|
|
public init(title: String, color: Color, actionType: ActionType, negated: Bool, onTap: @escaping () -> Void) {
|
|
self.text = title
|
|
self.color = color
|
|
self.onTap = onTap
|
|
self.actionType = actionType
|
|
self.foregroundColor = {
|
|
if actionType == .show {
|
|
return .appGrayText
|
|
}
|
|
return color.isDark ? .white : .black
|
|
}()
|
|
self.negated = negated
|
|
}
|
|
|
|
let text: String
|
|
let negated: Bool
|
|
let color: Color
|
|
let onTap: () -> Void
|
|
let actionType: ActionType
|
|
let foregroundColor: Color
|
|
|
|
public var body: some View {
|
|
VStack(spacing: 0) {
|
|
HStack {
|
|
if actionType == .filter {
|
|
Image(systemName: "line.3.horizontal.decrease")
|
|
}
|
|
|
|
Text(text)
|
|
.strikethrough(color: negated ? foregroundColor : .clear)
|
|
.padding(.leading, 3)
|
|
Image(systemName: actionType.systemIconName)
|
|
}
|
|
.padding(.horizontal, 10)
|
|
.padding(.vertical, 8)
|
|
.font(.appFootnote)
|
|
.foregroundColor(foregroundColor)
|
|
.lineLimit(1)
|
|
.background(Rectangle().fill(color))
|
|
.cornerRadius(8)
|
|
}
|
|
.padding(.vertical, 0)
|
|
.contentShape(Rectangle())
|
|
.onTapGesture { onTap() }
|
|
}
|
|
}
|