Files
Reflect/Shared/Views/SharingTemplates/Variations/LongestStreakVariations.swift
Trey t 0442eab1f8 Rebrand entire project from Feels to Reflect
Complete rename across all bundle IDs, App Groups, CloudKit containers,
StoreKit product IDs, data store filenames, URL schemes, logger subsystems,
Swift identifiers, user-facing strings (7 languages), file names, directory
names, Xcode project, schemes, assets, and documentation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 11:47:16 -06:00

240 lines
9.0 KiB
Swift

//
// LongestStreakVariations.swift
// Reflect
//
// 2 design variations for the Longest Streak sharing template.
//
import SwiftUI
// MARK: - V2 "Gradient Bar" Warm gradient bg, horizontal progress
struct LongestStreakV2: View {
let streakEntries: [MoodEntryModel]
let selectedMood: Mood
@AppStorage(UserDefaultsStore.Keys.moodTint.rawValue, store: GroupUserDefaults.groupDefaults)
private var moodTint: MoodTints = .Default
private let dateFormatter: DateFormatter = {
let f = DateFormatter()
f.dateFormat = "MMM d, yyyy"
return f
}()
var image: UIImage {
shareView.asImage(size: CGSize(width: 650, height: 400))
}
var shareView: some View {
ZStack {
LinearGradient(
colors: [Color(hex: "FFF5EE"), Color(hex: "FFE4D6")],
startPoint: .topLeading,
endPoint: .bottomTrailing
)
VStack(spacing: 20) {
// Top row
HStack {
VStack(alignment: .leading, spacing: 4) {
Text("Longest Streak")
.font(.system(size: 14, weight: .semibold, design: .rounded))
.foregroundColor(Color(hex: "8B5E3C"))
.textCase(.uppercase)
.tracking(2)
HStack(alignment: .firstTextBaseline, spacing: 8) {
Text("\(streakEntries.count)")
.font(.system(size: 56, weight: .heavy, design: .rounded))
.foregroundColor(Color(hex: "4A2810"))
Text("days")
.font(.system(size: 20, weight: .medium, design: .rounded))
.foregroundColor(Color(hex: "8B5E3C"))
}
}
Spacer()
ZStack {
Circle()
.fill(moodTint.color(forMood: selectedMood))
.frame(width: 72, height: 72)
.shadow(color: moodTint.color(forMood: selectedMood).opacity(0.4), radius: 12)
selectedMood.icon
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 32, height: 32)
.foregroundColor(.white)
}
}
.padding(.horizontal, 36)
// Progress bar
VStack(spacing: 8) {
GeometryReader { geo in
ZStack(alignment: .leading) {
Capsule()
.fill(Color(hex: "4A2810").opacity(0.1))
.frame(height: 24)
Capsule()
.fill(moodTint.color(forMood: selectedMood))
.frame(width: geo.size.width * 0.85, height: 24)
.shadow(color: moodTint.color(forMood: selectedMood).opacity(0.3), radius: 6)
}
}
.frame(height: 24)
HStack {
Text(dateFormatter.string(from: streakEntries.first?.forDate ?? Date()))
.font(.system(size: 12, weight: .medium, design: .rounded))
.foregroundColor(Color(hex: "8B5E3C").opacity(0.6))
Spacer()
Text(dateFormatter.string(from: streakEntries.last?.forDate ?? Date()))
.font(.system(size: 12, weight: .medium, design: .rounded))
.foregroundColor(Color(hex: "8B5E3C").opacity(0.6))
}
}
.padding(.horizontal, 36)
// Footer
HStack {
Text(selectedMood.strValue)
.font(.system(size: 14, weight: .semibold, design: .rounded))
.foregroundColor(Color(hex: "8B5E3C"))
Spacer()
VStack(spacing: 6) {
Image("ReflectAppIcon")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 72, height: 72)
.clipShape(RoundedRectangle(cornerRadius: 16))
Text("Reflect")
.font(.system(size: 22, weight: .medium, design: .rounded))
.foregroundColor(Color(hex: "8B5E3C").opacity(0.4))
}
}
.padding(.horizontal, 36)
}
.padding(.vertical, 32)
}
.frame(width: 650, height: 400)
}
var body: some View { shareView }
}
// MARK: - V3 "Dark Badge" Dark bg, glowing badge, neon accent
struct LongestStreakV3: View {
let streakEntries: [MoodEntryModel]
let selectedMood: Mood
@AppStorage(UserDefaultsStore.Keys.moodTint.rawValue, store: GroupUserDefaults.groupDefaults)
private var moodTint: MoodTints = .Default
private let dateFormatter: DateFormatter = {
let f = DateFormatter()
f.dateStyle = .medium
return f
}()
var image: UIImage {
shareView.asImage(size: CGSize(width: 650, height: 400))
}
var shareView: some View {
ZStack {
Color(hex: "0A0A0F")
HStack(spacing: 0) {
// Left half badge centered
ZStack {
Circle()
.fill(moodTint.color(forMood: selectedMood).opacity(0.15))
.frame(width: 220, height: 220)
Circle()
.stroke(moodTint.color(forMood: selectedMood).opacity(0.3), lineWidth: 2)
.frame(width: 180, height: 180)
Circle()
.stroke(moodTint.color(forMood: selectedMood), lineWidth: 3)
.frame(width: 150, height: 150)
VStack(spacing: 4) {
Text("\(streakEntries.count)")
.font(.system(size: 60, weight: .heavy, design: .rounded))
.foregroundColor(.white)
Text("DAYS")
.font(.system(size: 13, weight: .bold))
.foregroundColor(moodTint.color(forMood: selectedMood))
.tracking(4)
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
// Right half text left-aligned, vertically centered
VStack(alignment: .leading, spacing: 20) {
Text("LONGEST STREAK")
.font(.system(size: 14, weight: .bold))
.foregroundColor(Color(hex: "6E6E80"))
.tracking(4)
HStack(spacing: 10) {
selectedMood.icon
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 28, height: 28)
.foregroundColor(moodTint.color(forMood: selectedMood))
Text(selectedMood.strValue)
.font(.system(size: 30, weight: .semibold))
.foregroundColor(.white)
}
VStack(alignment: .leading, spacing: 6) {
Text(dateFormatter.string(from: streakEntries.first?.forDate ?? Date()))
.font(.system(size: 18, weight: .medium))
.foregroundColor(.white.opacity(0.7))
Text("")
.font(.system(size: 16))
.foregroundColor(Color(hex: "6E6E80"))
Text(dateFormatter.string(from: streakEntries.last?.forDate ?? Date()))
.font(.system(size: 18, weight: .medium))
.foregroundColor(.white.opacity(0.7))
}
VStack(spacing: 6) {
Image("ReflectAppIcon")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 72, height: 72)
.clipShape(RoundedRectangle(cornerRadius: 16))
Text("Reflect")
.font(.system(size: 22, weight: .medium))
.foregroundColor(Color(hex: "3A3A4A"))
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.padding(.leading, 20)
}
}
.frame(width: 650, height: 400)
}
var body: some View { shareView }
}