Files
omnivore/apple/OmnivoreKit/Sources/Views/TextChip.swift
2023-02-20 12:15:29 -07:00

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() }
}
}