import WidgetKit import SwiftUI // V1:写死文案的小组件(Small/Medium/Large + 点击跳转 Home) struct EmotionProvider: TimelineProvider { func placeholder(in context: Context) -> EmotionEntry { EmotionEntry(date: Date()) } func getSnapshot(in context: Context, completion: @escaping (EmotionEntry) -> ()) { completion(EmotionEntry(date: Date())) } func getTimeline(in context: Context, completion: @escaping (Timeline) -> ()) { // V1:内容写死,不做数据更新;给一个较长的刷新间隔(系统仍可能自行调度) let entry = EmotionEntry(date: Date()) let nextUpdate = Calendar.current.date(byAdding: .day, value: 7, to: Date()) ?? Date().addingTimeInterval(60 * 60 * 24 * 7) completion(Timeline(entries: [entry], policy: .after(nextUpdate))) } } struct EmotionEntry: TimelineEntry { let date: Date } struct EmotionWidgetView: View { var entry: EmotionProvider.Entry @Environment(\.widgetFamily) var family private let title = "正念" private let text = "你已经很努力了,今天也值得被温柔对待。" private let deepLink = URL(string: "client:///(app)/home") var body: some View { switch family { case .systemSmall: smallView() case .systemMedium: mediumView() case .systemLarge: largeView() default: smallView() } } // 统一的“卡片背景”风格(iOS 15 兼容) private func cardBackground(colors: [Color]) -> some View { ZStack { LinearGradient( colors: colors, startPoint: .topLeading, endPoint: .bottomTrailing ) // 轻微光斑,增加层次 RadialGradient( gradient: Gradient(colors: [Color.white.opacity(0.16), Color.white.opacity(0.0)]), center: .topTrailing, startRadius: 10, endRadius: 180 ) } .overlay( RoundedRectangle(cornerRadius: 18, style: .continuous) .stroke(Color.white.opacity(0.14), lineWidth: 1) ) .cornerRadius(18) } private func chip(_ text: String) -> some View { Text(text) .font(.system(size: 12, weight: .semibold)) .foregroundColor(Color.white.opacity(0.9)) .padding(.horizontal, 10) .padding(.vertical, 6) .background(Color.white.opacity(0.14)) .cornerRadius(999) } private func smallView() -> some View { ZStack { cardBackground(colors: [ Color(red: 0.06, green: 0.08, blue: 0.12), Color(red: 0.13, green: 0.16, blue: 0.22), ]) VStack(alignment: .leading, spacing: 10) { HStack { chip(title) Spacer(minLength: 0) } Text(text) .font(.system(size: 15, weight: .semibold)) .foregroundColor(Color.white.opacity(0.92)) .lineSpacing(2) .lineLimit(4) Spacer(minLength: 0) Text("点我回到 App") .font(.system(size: 11, weight: .medium)) .foregroundColor(Color.white.opacity(0.65)) } .padding(14) } .widgetURL(deepLink) } private func mediumView() -> some View { ZStack { cardBackground(colors: [ Color(red: 0.06, green: 0.08, blue: 0.12), Color(red: 0.09, green: 0.11, blue: 0.17), ]) HStack(alignment: .top, spacing: 14) { VStack(alignment: .leading, spacing: 10) { chip(title) Text(text) .font(.system(size: 17, weight: .semibold)) .foregroundColor(Color.white.opacity(0.92)) .lineSpacing(3) .lineLimit(5) Spacer(minLength: 0) Text("轻轻呼吸,回到当下") .font(.system(size: 12, weight: .medium)) .foregroundColor(Color.white.opacity(0.7)) } // 右侧装饰区:让版面更饱满 VStack(alignment: .trailing, spacing: 8) { Text(entry.date, style: .time) .font(.system(size: 12, weight: .semibold)) .foregroundColor(Color.white.opacity(0.8)) Spacer(minLength: 0) Text("今日") .font(.system(size: 28, weight: .bold)) .foregroundColor(Color.white.opacity(0.12)) } } .padding(16) } .widgetURL(deepLink) } private func largeView() -> some View { ZStack { cardBackground(colors: [ Color(red: 0.06, green: 0.08, blue: 0.12), Color(red: 0.14, green: 0.18, blue: 0.28), ]) VStack(alignment: .leading, spacing: 14) { HStack { chip(title) Spacer(minLength: 0) Text(entry.date, style: .time) .font(.system(size: 12, weight: .semibold)) .foregroundColor(Color.white.opacity(0.78)) } Text(text) .font(.system(size: 20, weight: .semibold)) .foregroundColor(Color.white.opacity(0.92)) .lineSpacing(4) .lineLimit(8) Spacer(minLength: 0) HStack { Text("点我回到 Home") .font(.system(size: 12, weight: .medium)) .foregroundColor(Color.white.opacity(0.7)) Spacer(minLength: 0) Text("🌿") .font(.system(size: 18)) .opacity(0.9) } } .padding(18) } .widgetURL(deepLink) } } @main struct EmotionWidget: Widget { let kind: String = "EmotionWidget" var body: some WidgetConfiguration { StaticConfiguration(kind: kind, provider: EmotionProvider()) { entry in EmotionWidgetView(entry: entry) } .configurationDisplayName("情绪小组件") .description("一段温柔提醒,陪你回到当下。") .supportedFamilies([.systemSmall, .systemMedium, .systemLarge]) } }