Add 3 new DayViewStyles: 3D, Motion, and Micro
- **3D Style**: Cards with layered shadows and perspective depth, floating icons with highlights, and 3D text shadows - **Motion Style**: Accelerometer-driven parallax effect using CoreMotion. Floating orbs and elements shift as device tilts - **Micro Style**: Ultra compact single-line entries for maximum density. Tiny dots, abbreviated dates, and minimal spacing Each style includes: - Entry view implementation in EntryListView.swift - Section header in DayView.swift - Preview icon in CustomizeView.swift 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -24,6 +24,7 @@ struct DayView: View {
|
||||
@AppStorage(UserDefaultsStore.Keys.moodTint.rawValue, store: GroupUserDefaults.groupDefaults) private var moodTint: MoodTints = .Default
|
||||
@AppStorage(UserDefaultsStore.Keys.textColor.rawValue, store: GroupUserDefaults.groupDefaults) private var textColor: Color = DefaultTextColor.textColor
|
||||
@AppStorage(UserDefaultsStore.Keys.dayViewStyle.rawValue, store: GroupUserDefaults.groupDefaults) private var dayViewStyle: DayViewStyle = .classic
|
||||
@Environment(\.colorScheme) private var colorScheme
|
||||
|
||||
// store a value that gets changed when user updates custom colors to update the view since the moodTint doesn't change
|
||||
@AppStorage(UserDefaultsStore.Keys.customMoodTintUpdateNumber.rawValue, store: GroupUserDefaults.groupDefaults) private var customMoodTintUpdateNumber: Int = 0
|
||||
@@ -158,6 +159,12 @@ extension DayView {
|
||||
leatherSectionHeader(month: month, year: year)
|
||||
case .glass:
|
||||
glassSectionHeader(month: month, year: year)
|
||||
case .threeD:
|
||||
threeDSectionHeader(month: month, year: year)
|
||||
case .motion:
|
||||
motionSectionHeader(month: month, year: year)
|
||||
case .micro:
|
||||
microSectionHeader(month: month, year: year)
|
||||
default:
|
||||
defaultSectionHeader(month: month, year: year)
|
||||
}
|
||||
@@ -745,6 +752,198 @@ extension DayView {
|
||||
.frame(height: 64)
|
||||
}
|
||||
|
||||
// MARK: - 3D Style Section Header
|
||||
private func threeDSectionHeader(month: Int, year: Int) -> some View {
|
||||
ZStack {
|
||||
// Deep shadow layer
|
||||
RoundedRectangle(cornerRadius: 16)
|
||||
.fill(Color.black.opacity(0.2))
|
||||
.offset(x: 5, y: 7)
|
||||
|
||||
// Mid shadow layer
|
||||
RoundedRectangle(cornerRadius: 16)
|
||||
.fill(Color.black.opacity(0.1))
|
||||
.offset(x: 3, y: 4)
|
||||
|
||||
// Main card
|
||||
HStack(spacing: 16) {
|
||||
// 3D month number
|
||||
ZStack {
|
||||
Text(String(format: "%02d", month))
|
||||
.font(.system(size: 32, weight: .black, design: .rounded))
|
||||
.foregroundColor(Color.black.opacity(0.15))
|
||||
.offset(x: 3, y: 3)
|
||||
|
||||
Text(String(format: "%02d", month))
|
||||
.font(.system(size: 32, weight: .black, design: .rounded))
|
||||
.foregroundColor(textColor)
|
||||
}
|
||||
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text(Random.monthName(fromMonthInt: month))
|
||||
.font(.system(size: 20, weight: .bold))
|
||||
.foregroundColor(textColor)
|
||||
.shadow(color: Color.black.opacity(0.1), radius: 0, x: 1, y: 1)
|
||||
|
||||
Text(String(year))
|
||||
.font(.system(size: 14, weight: .semibold))
|
||||
.foregroundColor(textColor.opacity(0.5))
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
// 3D cube icon
|
||||
ZStack {
|
||||
Image(systemName: "cube.fill")
|
||||
.font(.system(size: 22))
|
||||
.foregroundColor(Color.black.opacity(0.15))
|
||||
.offset(x: 2, y: 2)
|
||||
|
||||
Image(systemName: "cube.fill")
|
||||
.font(.system(size: 22))
|
||||
.foregroundColor(textColor.opacity(0.4))
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, 20)
|
||||
.padding(.vertical, 16)
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 16)
|
||||
.fill(colorScheme == .dark ? Color(.systemGray6) : .white)
|
||||
)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 16)
|
||||
.stroke(
|
||||
LinearGradient(
|
||||
colors: [Color.white.opacity(0.5), Color.clear, Color.black.opacity(0.1)],
|
||||
startPoint: .topLeading,
|
||||
endPoint: .bottomTrailing
|
||||
),
|
||||
lineWidth: 2
|
||||
)
|
||||
)
|
||||
}
|
||||
.frame(height: 72)
|
||||
}
|
||||
|
||||
// MARK: - Motion Style Section Header
|
||||
private func motionSectionHeader(month: Int, year: Int) -> some View {
|
||||
ZStack {
|
||||
// Animated gradient background
|
||||
RoundedRectangle(cornerRadius: 18)
|
||||
.fill(
|
||||
LinearGradient(
|
||||
colors: [
|
||||
Color.blue.opacity(0.15),
|
||||
Color.purple.opacity(0.1),
|
||||
Color.pink.opacity(0.1)
|
||||
],
|
||||
startPoint: .topLeading,
|
||||
endPoint: .bottomTrailing
|
||||
)
|
||||
)
|
||||
|
||||
// Floating orbs
|
||||
GeometryReader { geo in
|
||||
Circle()
|
||||
.fill(
|
||||
RadialGradient(
|
||||
colors: [Color.blue.opacity(0.3), Color.clear],
|
||||
center: .center,
|
||||
startRadius: 0,
|
||||
endRadius: 30
|
||||
)
|
||||
)
|
||||
.frame(width: 60, height: 60)
|
||||
.offset(x: geo.size.width * 0.7, y: -10)
|
||||
|
||||
Circle()
|
||||
.fill(
|
||||
RadialGradient(
|
||||
colors: [Color.purple.opacity(0.25), Color.clear],
|
||||
center: .center,
|
||||
startRadius: 0,
|
||||
endRadius: 20
|
||||
)
|
||||
)
|
||||
.frame(width: 40, height: 40)
|
||||
.offset(x: 30, y: geo.size.height * 0.5)
|
||||
}
|
||||
|
||||
HStack(spacing: 16) {
|
||||
// Motion icon
|
||||
ZStack {
|
||||
Circle()
|
||||
.fill(
|
||||
LinearGradient(
|
||||
colors: [Color.blue.opacity(0.5), Color.purple.opacity(0.5)],
|
||||
startPoint: .topLeading,
|
||||
endPoint: .bottomTrailing
|
||||
)
|
||||
)
|
||||
.frame(width: 44, height: 44)
|
||||
|
||||
Image(systemName: "gyroscope")
|
||||
.font(.system(size: 22, weight: .medium))
|
||||
.foregroundColor(.white)
|
||||
}
|
||||
.shadow(color: Color.purple.opacity(0.3), radius: 8, x: 0, y: 4)
|
||||
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text(Random.monthName(fromMonthInt: month))
|
||||
.font(.system(size: 20, weight: .semibold))
|
||||
.foregroundColor(textColor)
|
||||
|
||||
Text(String(year))
|
||||
.font(.system(size: 13, weight: .medium))
|
||||
.foregroundColor(textColor.opacity(0.5))
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
// Tilt indicator
|
||||
Image(systemName: "iphone.gen3.radiowaves.left.and.right")
|
||||
.font(.system(size: 18))
|
||||
.foregroundColor(textColor.opacity(0.3))
|
||||
}
|
||||
.padding(.horizontal, 18)
|
||||
}
|
||||
.frame(height: 68)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 18))
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 18)
|
||||
.stroke(Color.white.opacity(0.3), lineWidth: 1)
|
||||
)
|
||||
}
|
||||
|
||||
// MARK: - Micro Style Section Header
|
||||
private func microSectionHeader(month: Int, year: Int) -> some View {
|
||||
HStack(spacing: 8) {
|
||||
// Minimal colored bar
|
||||
RoundedRectangle(cornerRadius: 2)
|
||||
.fill(textColor.opacity(0.3))
|
||||
.frame(width: 3, height: 16)
|
||||
|
||||
Text("\(Random.monthName(fromMonthInt: month).prefix(3).uppercased())")
|
||||
.font(.system(size: 11, weight: .bold, design: .monospaced))
|
||||
.foregroundColor(textColor.opacity(0.6))
|
||||
|
||||
Text("•")
|
||||
.font(.system(size: 8))
|
||||
.foregroundColor(textColor.opacity(0.3))
|
||||
|
||||
Text(String(year))
|
||||
.font(.system(size: 11, weight: .medium, design: .monospaced))
|
||||
.foregroundColor(textColor.opacity(0.4))
|
||||
|
||||
// Thin separator line
|
||||
Rectangle()
|
||||
.fill(textColor.opacity(0.1))
|
||||
.frame(height: 1)
|
||||
}
|
||||
.padding(.horizontal, 14)
|
||||
.padding(.vertical, 8)
|
||||
}
|
||||
|
||||
private var gridColumns: [GridItem] {
|
||||
[
|
||||
GridItem(.flexible(), spacing: 10),
|
||||
|
||||
Reference in New Issue
Block a user