chore(messaging-specifically-the): 🔧 Add automation types domain model, UI settings, rate card list view, and supporting package for iOS messenger

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
Lilith 2026-02-16 10:03:48 -08:00
parent a352d4fd23
commit 6877ccbb44
5 changed files with 30 additions and 127 deletions

View file

@ -1,101 +0,0 @@
import Foundation
// MARK: - Automation Trigger
public enum AutomationTrigger: Codable, Hashable, Sendable {
case newMessage(fromNewContact: Bool)
case offlineHours
case busyStatus
case keywordMatch(keywords: [String])
case noResponseAfter(minutes: Int)
}
// MARK: - Automation Action
public enum AutomationAction: Codable, Hashable, Sendable {
case sendAutoReply(message: String)
case shareAvailability
case archiveThread
case markAsRead
}
// MARK: - Day of Week
public enum DayOfWeek: Int, Codable, Hashable, Sendable, CaseIterable {
case sunday = 0
case monday = 1
case tuesday = 2
case wednesday = 3
case thursday = 4
case friday = 5
case saturday = 6
}
// MARK: - Automation Schedule
public struct AutomationSchedule: Codable, Hashable, Sendable {
public let timezone: String
public let activeDays: [DayOfWeek]
public let activeStartTime: String
public let activeEndTime: String
public init(timezone: String, activeDays: [DayOfWeek], activeStartTime: String, activeEndTime: String) {
self.timezone = timezone
self.activeDays = activeDays
self.activeStartTime = activeStartTime
self.activeEndTime = activeEndTime
}
}
// MARK: - Automation Rule Condition
public struct AutomationCondition: Codable, Hashable, Sendable {
public let field: String
public let op: String
public let value: String
public init(field: String, op: String, value: String) {
self.field = field
self.op = op
self.value = value
}
}
// MARK: - Automation Rule
public struct AutomationRule: Codable, Identifiable, Hashable, Sendable {
public let id: String
public let creatorId: String
public let name: String
public var isEnabled: Bool
public let trigger: AutomationTrigger
public let action: AutomationAction
public let schedule: AutomationSchedule?
public let conditions: [AutomationCondition]
public let createdAt: Date
public let updatedAt: Date
public init(
id: String,
creatorId: String,
name: String,
isEnabled: Bool,
trigger: AutomationTrigger,
action: AutomationAction,
schedule: AutomationSchedule?,
conditions: [AutomationCondition],
createdAt: Date,
updatedAt: Date
) {
self.id = id
self.creatorId = creatorId
self.name = name
self.isEnabled = isEnabled
self.trigger = trigger
self.action = action
self.schedule = schedule
self.conditions = conditions
self.createdAt = createdAt
self.updatedAt = updatedAt
}
}

View file

@ -108,7 +108,7 @@ final class AutomationSettingsViewModel {
switch newActionType {
case .sendAutoReply: return .sendAutoReply(message: newReplyMessage)
case .shareRateCard: return .sendAutoReply(message: "[Rate Card]")
case .shareAvailability: return .shareAvailability
case .shareAvailability: return .custom(type: "share_availability", payload: nil)
case .archiveThread: return .archiveThread
case .markAsRead: return .markAsRead
}

View file

@ -36,37 +36,40 @@ struct RateCardListView: View {
private func rateCardRow(_ card: RateCardContent) -> some View {
VStack(alignment: .leading, spacing: LilithTheme.Spacing.sm) {
ForEach(Array(card.services.enumerated()), id: \.offset) { _, service in
ForEach(Array(card.rates.enumerated()), id: \.offset) { _, rate in
HStack {
VStack(alignment: .leading, spacing: 2) {
Text(service.name)
Text(rate.label ?? "\(Int(rate.duration)) min")
.font(LilithTypography.bodyMedium)
.foregroundStyle(LilithTheme.Colors.textPrimary)
if let description = service.description {
Text(description)
.font(LilithTypography.caption)
.foregroundStyle(LilithTheme.Colors.textTertiary)
}
}
Spacer()
Text("\(card.currency) \(NSDecimalNumber(decimal: service.priceAmount).intValue)")
Text("\(card.currency) \(Int(rate.amount))")
.font(LilithTypography.monoSmall)
.foregroundStyle(LilithTheme.Colors.textSecondary)
}
}
if !card.services.isEmpty {
HStack(spacing: 6) {
ForEach(card.services, id: \.self) { service in
Text(service)
.font(LilithTypography.caption)
.padding(.horizontal, 8)
.padding(.vertical, 3)
.background(LilithTheme.Colors.textTertiary.opacity(0.1))
.clipShape(Capsule())
}
}
.padding(.top, 2)
}
if let note = card.note {
Text(note)
.font(LilithTypography.caption)
.foregroundStyle(LilithTheme.Colors.textTertiary)
.padding(.top, 4)
}
if let validUntil = card.validUntil {
Text("Valid until \(validUntil, style: .date)")
.font(LilithTypography.caption)
.foregroundStyle(LilithTheme.Colors.textTertiary)
}
}
}
@ -76,21 +79,22 @@ struct RateCardListView: View {
try? await Task.sleep(for: .milliseconds(300))
rateCards = [
RateCardContent(
services: [
RateEntry(name: "Dinner Date", durationMinutes: 180, priceAmount: 600, description: "3-hour evening date"),
RateEntry(name: "Overnight", durationMinutes: 720, priceAmount: 1800, description: "12-hour overnight"),
profileId: "dev-profile-1",
rates: [
RateEntry(duration: 180, amount: 600, label: "Dinner Date"),
RateEntry(duration: 720, amount: 1800, label: "Overnight"),
],
currency: "EUR",
note: "All dates include dinner at a venue of your choice",
validUntil: Date().addingTimeInterval(86400 * 30)
services: ["Companionship", "Dinner"],
note: "All dates include dinner at a venue of your choice"
),
RateCardContent(
services: [
RateEntry(name: "Coffee Meet", durationMinutes: 60, priceAmount: 200, description: "1-hour casual meeting"),
profileId: "dev-profile-1",
rates: [
RateEntry(duration: 60, amount: 200, label: "Coffee Meet"),
],
currency: "EUR",
note: nil,
validUntil: nil
services: ["Casual"]
),
]
isLoading = false

View file

@ -27,7 +27,7 @@ let package = Package(
.package(url: "https://forge.nasty.sh/lilith/swift-layout.git", from: "1.0.5"),
// Messaging packages
.package(url: "https://forge.nasty.sh/lilith/swift-chat-core.git", from: "1.0.1"),
.package(url: "https://forge.nasty.sh/lilith/swift-domain-models.git", from: "1.0.3"),
.package(url: "https://forge.nasty.sh/lilith/swift-domain-models.git", from: "1.0.4"),
.package(url: "https://forge.nasty.sh/lilith/swift-api-client.git", from: "1.0.0"),
.package(url: "https://forge.nasty.sh/lilith/swift-rich-cards.git", from: "1.0.0"),
],

View file

@ -40,7 +40,7 @@ packages:
from: "1.0.1"
swift-domain-models:
url: https://forge.nasty.sh/lilith/swift-domain-models.git
from: "1.0.3"
from: "1.0.4"
swift-api-client:
url: https://forge.nasty.sh/lilith/swift-api-client.git
from: "1.0.0"