@shaykec/app-agent 1.0.9 → 1.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agents/catalog-analyzer.md +57 -0
- package/.claude/skills/android-customizer/SKILL.md +23 -10
- package/.claude/skills/bug-fixer/SKILL.md +59 -0
- package/.claude/skills/catalog-analyzer/SKILL.md +96 -0
- package/.claude/skills/customization-planner/SKILL.md +44 -5
- package/.claude/skills/design-selector/SKILL.md +3 -1
- package/.claude/skills/design-system/SKILL.md +1 -1
- package/.claude/skills/exploratory-tester/SKILL.md +82 -0
- package/.claude/skills/ios-customizer/SKILL.md +29 -8
- package/.claude/skills/module-integrator/SKILL.md +1 -1
- package/.claude/skills/react-native-customizer/SKILL.md +22 -10
- package/.claude/skills/test-planner/SKILL.md +72 -0
- package/.cursor/agents/README.md +3 -1
- package/.cursor/agents/catalog-analyzer.md +83 -0
- package/.cursor/rules/safety-guardrails.mdc +1 -1
- package/.cursor/rules/workflow.mdc +52 -18
- package/.cursor/skills/android-customizer/SKILL.md +43 -19
- package/.cursor/skills/bug-fixer/SKILL.md +189 -0
- package/.cursor/skills/catalog-analyzer/SKILL.md +222 -0
- package/.cursor/skills/customization-planner/SKILL.md +55 -8
- package/.cursor/skills/design-selector/SKILL.md +6 -5
- package/.cursor/skills/design-system/SKILL.md +8 -7
- package/.cursor/skills/exploratory-tester/SKILL.md +223 -0
- package/.cursor/skills/ios-customizer/SKILL.md +47 -12
- package/.cursor/skills/module-integrator/SKILL.md +2 -2
- package/.cursor/skills/output-validator/SKILL.md +1 -1
- package/.cursor/skills/react-native-customizer/SKILL.md +46 -16
- package/.cursor/skills/test-planner/SKILL.md +199 -0
- package/.cursor/skills/web-analyzer/SKILL.md +310 -0
- package/.cursor/skills/web-crawler/SKILL.md +252 -0
- package/AGENTS.md +32 -11
- package/CLAUDE.md +78 -33
- package/README.md +77 -11
- package/designs/DESIGN_CATALOG.md +17 -15
- package/designs/DESIGN_PRINCIPLES.md +53 -0
- package/designs/brands/accessible-high-contrast.md +14 -0
- package/designs/brands/corporate-professional.md +14 -0
- package/designs/brands/dark-luxe.md +14 -0
- package/designs/brands/kids-playful.md +14 -0
- package/designs/brands/medical-clinical.md +14 -0
- package/designs/brands/modern-minimal.md +14 -0
- package/designs/brands/nature-organic.md +14 -0
- package/designs/brands/neo-brutalist.md +14 -0
- package/designs/brands/retro-vintage.md +14 -0
- package/designs/brands/soft-gradient.md +14 -0
- package/designs/brands/sport-athletic.md +14 -0
- package/designs/brands/tech-dynamic.md +14 -0
- package/designs/brands/vibrant-playful.md +14 -0
- package/dist/cli.d.ts +4 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +123 -11
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +8 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +6 -1
- package/dist/config.js.map +1 -1
- package/dist/engines/claude-engine.d.ts.map +1 -1
- package/dist/engines/claude-engine.js +16 -4
- package/dist/engines/claude-engine.js.map +1 -1
- package/dist/engines/types.d.ts +1 -1
- package/dist/engines/types.d.ts.map +1 -1
- package/dist/engines/types.js +31 -2
- package/dist/engines/types.js.map +1 -1
- package/dist/github.d.ts +3 -0
- package/dist/github.d.ts.map +1 -1
- package/dist/github.js +47 -4
- package/dist/github.js.map +1 -1
- package/dist/index.js +294 -16
- package/dist/index.js.map +1 -1
- package/dist/prompt-builder.d.ts +17 -1
- package/dist/prompt-builder.d.ts.map +1 -1
- package/dist/prompt-builder.js +272 -1
- package/dist/prompt-builder.js.map +1 -1
- package/dist/validator.d.ts +7 -2
- package/dist/validator.d.ts.map +1 -1
- package/dist/validator.js +61 -41
- package/dist/validator.js.map +1 -1
- package/dist/workspace.js +2 -2
- package/dist/workspace.js.map +1 -1
- package/package.json +2 -4
- package/prompts/agent-prompt.md +35 -18
- package/prompts/deep-test-agent-prompt.md +122 -0
- package/prompts/fix-agent-prompt.md +90 -0
- package/prompts/quick-agent-prompt.md +32 -2
- package/prompts/scratch-agent-prompt.md +5 -8
- package/prompts/web-clone-agent-prompt.md +179 -0
- package/templates/android/BookTemplate/app/src/main/kotlin/com/appship/book/core/animation/AnimatedTransitionsModifiers.kt +188 -0
- package/templates/android/ChatTemplate/app/src/main/kotlin/com/appship/chat/core/animation/AnimatedTransitionsModifiers.kt +188 -0
- package/templates/android/ChatTemplate/app/src/main/kotlin/com/appship/chat/features/conversations/ConversationsScreen.kt +1 -1
- package/templates/android/DashTemplate/app/src/main/kotlin/com/appship/dash/core/animation/AnimatedTransitionsModifiers.kt +188 -0
- package/templates/android/DashTemplate/app/src/main/kotlin/com/appship/dash/features/navigation/MainScreen.kt +1 -0
- package/templates/android/FamilyTemplate/app/src/main/java/com/appship/family/core/animation/AnimatedTransitionsModifiers.kt +188 -0
- package/templates/android/FamilyTemplate/app/src/main/java/com/appship/family/features/navigation/MainNavigation.kt +5 -1
- package/templates/android/FinanceTemplate/app/src/main/kotlin/com/appship/finance/core/animation/AnimatedTransitionsModifiers.kt +188 -0
- package/templates/android/GameTemplate/app/src/main/kotlin/com/appship/game/core/animation/AnimatedTransitionsModifiers.kt +188 -0
- package/templates/android/GameTemplate/app/src/main/kotlin/com/appship/game/core/animation/MotionPreferencesScreen.kt +3 -3
- package/templates/android/GameTemplate/app/src/main/kotlin/com/appship/game/features/navigation/Navigation.kt +1 -1
- package/templates/android/GameTemplate/app/src/main/kotlin/com/appship/game/features/settings/SettingsScreen.kt +1 -1
- package/templates/android/HealthTemplate/app/src/main/kotlin/com/appship/health/core/animation/AnimatedTransitionsModifiers.kt +188 -0
- package/templates/android/LearnTemplate/app/src/main/kotlin/com/appship/learn/core/animation/AnimatedTransitionsModifiers.kt +188 -0
- package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/core/animation/AnimatedTransitionsModifiers.kt +188 -0
- package/templates/android/MediaTemplate/app/src/main/kotlin/com/appship/media/core/animation/AnimatedTransitionsModifiers.kt +188 -0
- package/templates/android/MediaTemplate/app/src/main/kotlin/com/appship/media/features/settings/SettingsScreen.kt +3 -2
- package/templates/android/ReferenceTemplate/app/src/main/kotlin/com/appship/reference/core/animation/AnimatedTransitionsModifiers.kt +188 -0
- package/templates/android/ReferenceTemplate/app/src/main/kotlin/com/appship/reference/features/settings/SettingsScreen.kt +1 -1
- package/templates/android/ShopTemplate/app/src/main/kotlin/com/appship/shop/core/animation/AnimatedTransitionsModifiers.kt +188 -0
- package/templates/android/ShopTemplate/app/src/main/kotlin/com/appship/shop/features/cart/CartScreen.kt +3 -2
- package/templates/android/Skeleton/app/src/main/kotlin/com/appship/skeleton/core/animation/AnimatedTransitionsModifiers.kt +188 -0
- package/templates/android/Skeleton/tests/03_detail_screen.yaml +1 -1
- package/templates/android/Skeleton/tests/04_favorites.yaml +1 -1
- package/templates/android/Skeleton/tests/08_full_e2e.yaml +7 -1
- package/templates/android/SocialTemplate/app/src/main/kotlin/com/appship/social/core/animation/AnimatedTransitionsModifiers.kt +188 -0
- package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/core/animation/AnimatedTransitionsModifiers.kt +188 -0
- package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/features/settings/SettingsScreen.kt +3 -2
- package/templates/android/TrackTemplate/app/src/main/kotlin/com/appship/track/core/animation/AnimatedTransitionsModifiers.kt +188 -0
- package/templates/ios/BookTemplate/BookTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
- package/templates/ios/ChatTemplate/ChatTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
- package/templates/ios/DashTemplate/DashTemplate/App/AppConfig.swift +1 -0
- package/templates/ios/DashTemplate/DashTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
- package/templates/ios/DashTemplate/DashTemplate/Core/Strings.swift +13 -0
- package/templates/ios/DashTemplate/DashTemplate.xcodeproj/project.pbxproj +32 -20
- package/templates/ios/FamilyTemplate/FamilyTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
- package/templates/ios/FinanceTemplate/FinanceTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
- package/templates/ios/FinanceTemplate/FinanceTemplate/Core/Strings.swift +42 -0
- package/templates/ios/FinanceTemplate/FinanceTemplate.xcodeproj/project.pbxproj +36 -30
- package/templates/ios/GameTemplate/GameTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
- package/templates/ios/HealthTemplate/HealthTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
- package/templates/ios/LearnTemplate/LearnTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
- package/templates/ios/MapTemplate/MapTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
- package/templates/ios/MediaTemplate/MediaTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
- package/templates/ios/ReferenceTemplate/ReferenceTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
- package/templates/ios/ReferenceTemplate/ReferenceTemplate/Core/Strings.swift +12 -0
- package/templates/ios/ReferenceTemplate/ReferenceTemplate/Features/SkeletonLoading/SkeletonLoadingView.swift +2 -37
- package/templates/ios/ShopTemplate/ShopTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
- package/templates/ios/Skeleton/Skeleton/Core/Animation/AnimatedTransitionsView.swift +201 -0
- package/templates/ios/Skeleton/tests/08_full_e2e.yaml +4 -0
- package/templates/ios/SocialTemplate/SocialTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
- package/templates/ios/TaskTemplate/TaskTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
- package/templates/ios/TrackTemplate/TrackTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
- package/templates/react-native/BookTemplate/src/animation/useAnimatedList.ts +219 -2
- package/templates/react-native/BookTemplate/src/animation/useMotionPreferences.ts +23 -9
- package/templates/react-native/BookTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
- package/templates/react-native/ChatTemplate/src/animation/useAnimatedList.ts +219 -2
- package/templates/react-native/ChatTemplate/src/animation/useMotionPreferences.ts +23 -9
- package/templates/react-native/ChatTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
- package/templates/react-native/DashTemplate/src/animation/useAnimatedList.ts +219 -2
- package/templates/react-native/DashTemplate/src/animation/useMotionPreferences.ts +23 -9
- package/templates/react-native/DashTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
- package/templates/react-native/FamilyTemplate/src/animation/useAnimatedList.ts +219 -2
- package/templates/react-native/FamilyTemplate/src/animation/useMotionPreferences.ts +23 -9
- package/templates/react-native/FamilyTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
- package/templates/react-native/FinanceTemplate/src/animation/useAnimatedList.ts +219 -2
- package/templates/react-native/FinanceTemplate/src/animation/useMotionPreferences.ts +23 -9
- package/templates/react-native/FinanceTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
- package/templates/react-native/GameTemplate/src/animation/useAnimatedList.ts +219 -2
- package/templates/react-native/GameTemplate/src/animation/useMotionPreferences.ts +23 -9
- package/templates/react-native/GameTemplate/src/screens/GameDetail/GameDetailScreen.tsx +2 -1
- package/templates/react-native/GameTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
- package/templates/react-native/HealthTemplate/src/animation/useAnimatedList.ts +219 -2
- package/templates/react-native/HealthTemplate/src/animation/useMotionPreferences.ts +23 -9
- package/templates/react-native/HealthTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
- package/templates/react-native/HealthTemplate/src/screens/WorkoutDetail/WorkoutDetailScreen.tsx +1 -1
- package/templates/react-native/LearnTemplate/src/animation/useAnimatedList.ts +219 -2
- package/templates/react-native/LearnTemplate/src/animation/useMotionPreferences.ts +23 -9
- package/templates/react-native/LearnTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
- package/templates/react-native/MapTemplate/src/animation/useAnimatedList.ts +219 -2
- package/templates/react-native/MapTemplate/src/animation/useMotionPreferences.ts +23 -9
- package/templates/react-native/MapTemplate/src/screens/Map/MapScreen.tsx +14 -0
- package/templates/react-native/MapTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
- package/templates/react-native/MediaTemplate/src/animation/useAnimatedList.ts +219 -2
- package/templates/react-native/MediaTemplate/src/animation/useMotionPreferences.ts +23 -9
- package/templates/react-native/MediaTemplate/src/screens/PlaylistDetail/PlaylistDetailScreen.tsx +1 -1
- package/templates/react-native/MediaTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
- package/templates/react-native/ReferenceTemplate/src/animation/useAnimatedList.ts +219 -2
- package/templates/react-native/ReferenceTemplate/src/animation/useMotionPreferences.ts +23 -9
- package/templates/react-native/ReferenceTemplate/src/screens/Settings/SettingsScreen.tsx +1 -1
- package/templates/react-native/ShopTemplate/src/animation/useAnimatedList.ts +219 -2
- package/templates/react-native/ShopTemplate/src/animation/useMotionPreferences.ts +23 -9
- package/templates/react-native/ShopTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
- package/templates/react-native/Skeleton/TESTING_MANIFEST.md +1 -1
- package/templates/react-native/Skeleton/src/animation/useAnimatedList.ts +219 -2
- package/templates/react-native/Skeleton/src/animation/useMotionPreferences.ts +23 -9
- package/templates/react-native/Skeleton/src/screens/Profile/ProfileScreen.tsx +1 -1
- package/templates/react-native/Skeleton/tests/07_profile.yaml +3 -2
- package/templates/react-native/Skeleton/tests/08_full_e2e.yaml +12 -1
- package/templates/react-native/SocialTemplate/src/animation/useAnimatedList.ts +219 -2
- package/templates/react-native/SocialTemplate/src/animation/useMotionPreferences.ts +23 -9
- package/templates/react-native/SocialTemplate/src/screens/Feed/FeedScreen.tsx +1 -0
- package/templates/react-native/SocialTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
- package/templates/react-native/TaskTemplate/src/animation/useAnimatedList.ts +219 -2
- package/templates/react-native/TaskTemplate/src/animation/useMotionPreferences.ts +23 -9
- package/templates/react-native/TaskTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
- package/templates/react-native/TrackTemplate/src/animation/useAnimatedList.ts +219 -2
- package/templates/react-native/TrackTemplate/src/animation/useMotionPreferences.ts +23 -9
- package/templates/react-native/TrackTemplate/src/screens/Settings/SettingsScreen.tsx +1 -1
- package/templates/shared/ios/AnimatedTransitions/AnimatedTransitionsView.swift +233 -93
- package/.claude/agents/template-selector.md +0 -39
- package/.claude/skills/module-selector/SKILL.md +0 -81
- package/.claude/skills/template-selector/SKILL.md +0 -44
- package/.cursor/agents/template-selector.md +0 -52
- package/.cursor/skills/module-selector/SKILL.md +0 -135
- package/.cursor/skills/template-selector/SKILL.md +0 -123
package/templates/ios/FamilyTemplate/FamilyTemplate/Core/Animation/AnimatedTransitionsView.swift
CHANGED
|
@@ -57,6 +57,155 @@ struct BounceScaleModifier: ViewModifier {
|
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
// MARK: - Scale on Press Modifier
|
|
61
|
+
/// Applies scale-down + spring-back animation when pressed (like a button press).
|
|
62
|
+
struct ScaleOnPressModifier: ViewModifier {
|
|
63
|
+
@State private var isPressed = false
|
|
64
|
+
|
|
65
|
+
func body(content: Content) -> some View {
|
|
66
|
+
content
|
|
67
|
+
.scaleEffect(isPressed ? 0.95 : 1.0)
|
|
68
|
+
.animation(.spring(response: 0.3, dampingFraction: 0.7), value: isPressed)
|
|
69
|
+
.simultaneousGesture(
|
|
70
|
+
DragGesture(minimumDistance: 0)
|
|
71
|
+
.onChanged { _ in isPressed = true }
|
|
72
|
+
.onEnded { _ in isPressed = false }
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// MARK: - Haptic Feedback Modifier
|
|
78
|
+
/// Triggers haptic feedback on tap.
|
|
79
|
+
struct HapticFeedbackModifier: ViewModifier {
|
|
80
|
+
let style: UIImpactFeedbackGenerator.FeedbackStyle
|
|
81
|
+
|
|
82
|
+
func body(content: Content) -> some View {
|
|
83
|
+
content
|
|
84
|
+
.onTapGesture {
|
|
85
|
+
UIImpactFeedbackGenerator(style: style).impactOccurred()
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// MARK: - Slide and Fade Modifier
|
|
91
|
+
/// Applies a slide-from-side + fade-in animation on appear.
|
|
92
|
+
struct SlideAndFadeModifier: ViewModifier {
|
|
93
|
+
let delay: Double
|
|
94
|
+
@State private var isVisible = false
|
|
95
|
+
|
|
96
|
+
func body(content: Content) -> some View {
|
|
97
|
+
content
|
|
98
|
+
.opacity(isVisible ? 1 : 0)
|
|
99
|
+
.offset(x: isVisible ? 0 : 20)
|
|
100
|
+
.motionAware(animation: .spring(response: 0.5, dampingFraction: 0.8).delay(delay))
|
|
101
|
+
.onAppear {
|
|
102
|
+
isVisible = true
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// MARK: - Card Shadow Modifier
|
|
108
|
+
/// Applies a subtle colored shadow to cards and elevated surfaces.
|
|
109
|
+
struct CardShadowModifier: ViewModifier {
|
|
110
|
+
let color: Color
|
|
111
|
+
let radius: CGFloat
|
|
112
|
+
let y: CGFloat
|
|
113
|
+
|
|
114
|
+
func body(content: Content) -> some View {
|
|
115
|
+
content
|
|
116
|
+
.shadow(color: color.opacity(0.08), radius: radius, x: 0, y: y)
|
|
117
|
+
.shadow(color: Color.black.opacity(0.04), radius: radius / 2, x: 0, y: y / 2)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// MARK: - Elevated Shadow Modifier
|
|
122
|
+
/// Applies a deeper shadow for FABs and floating elements.
|
|
123
|
+
struct ElevatedShadowModifier: ViewModifier {
|
|
124
|
+
let color: Color
|
|
125
|
+
|
|
126
|
+
func body(content: Content) -> some View {
|
|
127
|
+
content
|
|
128
|
+
.shadow(color: color.opacity(0.12), radius: 16, x: 0, y: 8)
|
|
129
|
+
.shadow(color: Color.black.opacity(0.06), radius: 8, x: 0, y: 4)
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// MARK: - Shimmer Modifier
|
|
134
|
+
/// Applies a shimmer/skeleton-loading gradient overlay for loading states.
|
|
135
|
+
struct ShimmerModifier: ViewModifier {
|
|
136
|
+
@State private var isAnimating = false
|
|
137
|
+
|
|
138
|
+
func body(content: Content) -> some View {
|
|
139
|
+
content
|
|
140
|
+
.overlay(
|
|
141
|
+
GeometryReader { geometry in
|
|
142
|
+
if isAnimating {
|
|
143
|
+
LinearGradient(
|
|
144
|
+
colors: [
|
|
145
|
+
Color.clear,
|
|
146
|
+
Color.white.opacity(0.3),
|
|
147
|
+
Color.clear
|
|
148
|
+
],
|
|
149
|
+
startPoint: .leading,
|
|
150
|
+
endPoint: .trailing
|
|
151
|
+
)
|
|
152
|
+
.offset(x: isAnimating ? geometry.size.width : -geometry.size.width)
|
|
153
|
+
.animation(
|
|
154
|
+
Animation.linear(duration: 1.5)
|
|
155
|
+
.repeatForever(autoreverses: false),
|
|
156
|
+
value: isAnimating
|
|
157
|
+
)
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
)
|
|
161
|
+
.clipped()
|
|
162
|
+
.onAppear {
|
|
163
|
+
isAnimating = true
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// MARK: - Pulse Modifier
|
|
169
|
+
/// Applies a repeating scale pulse effect (e.g., for notifications, active indicators).
|
|
170
|
+
struct PulseModifier: ViewModifier {
|
|
171
|
+
let intensity: CGFloat
|
|
172
|
+
@State private var scale: CGFloat = 1.0
|
|
173
|
+
|
|
174
|
+
func body(content: Content) -> some View {
|
|
175
|
+
content
|
|
176
|
+
.scaleEffect(scale)
|
|
177
|
+
.onAppear {
|
|
178
|
+
withAnimation(
|
|
179
|
+
.easeInOut(duration: 1.0)
|
|
180
|
+
.repeatForever(autoreverses: true)
|
|
181
|
+
) {
|
|
182
|
+
scale = 1.0 + intensity
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// MARK: - Heart Bounce Modifier
|
|
189
|
+
/// Applies a scale-up bounce then return when toggled (e.g., favorite/like buttons).
|
|
190
|
+
struct HeartBounceModifier: ViewModifier {
|
|
191
|
+
let isActive: Bool
|
|
192
|
+
@State private var scale: CGFloat = 1.0
|
|
193
|
+
|
|
194
|
+
func body(content: Content) -> some View {
|
|
195
|
+
content
|
|
196
|
+
.scaleEffect(scale)
|
|
197
|
+
.motionAware(animation: .spring(response: 0.3, dampingFraction: 0.5))
|
|
198
|
+
.onChange(of: isActive) { _, newValue in
|
|
199
|
+
if newValue {
|
|
200
|
+
scale = 1.3
|
|
201
|
+
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
|
|
202
|
+
scale = 1.0
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
60
209
|
// MARK: - View Extensions
|
|
61
210
|
|
|
62
211
|
extension View {
|
|
@@ -79,4 +228,56 @@ extension View {
|
|
|
79
228
|
func bounceOnChange(isActive: Bool) -> some View {
|
|
80
229
|
modifier(BounceScaleModifier(isActive: isActive))
|
|
81
230
|
}
|
|
231
|
+
|
|
232
|
+
/// Applies scale-down press feedback to any tappable element.
|
|
233
|
+
/// Scales to 0.95 on press with spring return animation.
|
|
234
|
+
func scaleOnPress() -> some View {
|
|
235
|
+
modifier(ScaleOnPressModifier())
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/// Triggers haptic feedback on tap.
|
|
239
|
+
/// - Parameter style: Feedback intensity (.light, .medium, .heavy)
|
|
240
|
+
func hapticFeedback(_ style: UIImpactFeedbackGenerator.FeedbackStyle = .light) -> some View {
|
|
241
|
+
modifier(HapticFeedbackModifier(style: style))
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/// Applies a slide-from-side + fade-in animation on appear.
|
|
245
|
+
/// - Parameter delay: Delay before animation starts (default: 0)
|
|
246
|
+
func slideAndFade(delay: Double = 0) -> some View {
|
|
247
|
+
modifier(SlideAndFadeModifier(delay: delay))
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/// Applies subtle colored shadow to cards and elevated surfaces.
|
|
251
|
+
/// Uses dual-shadow technique: primary-tinted shadow + neutral shadow for depth.
|
|
252
|
+
/// - Parameters:
|
|
253
|
+
/// - color: Shadow tint color (default: .primary)
|
|
254
|
+
/// - radius: Shadow blur radius (default: 8)
|
|
255
|
+
/// - y: Vertical offset (default: 4)
|
|
256
|
+
func cardShadow(color: Color = .primary, radius: CGFloat = 8, y: CGFloat = 4) -> some View {
|
|
257
|
+
modifier(CardShadowModifier(color: color, radius: radius, y: y))
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/// Applies deeper shadow for floating elements (FABs, modals).
|
|
261
|
+
/// - Parameter color: Shadow tint color (default: .primary)
|
|
262
|
+
func elevatedShadow(color: Color = .primary) -> some View {
|
|
263
|
+
modifier(ElevatedShadowModifier(color: color))
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/// Applies a shimmer loading overlay (e.g., for skeleton placeholder views).
|
|
267
|
+
func shimmer() -> some View {
|
|
268
|
+
modifier(ShimmerModifier())
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/// Applies a repeating pulse animation (e.g., for notifications, live indicators).
|
|
272
|
+
/// - Parameter intensity: Scale increase per pulse (default: 0.05 = 5% bigger)
|
|
273
|
+
func pulse(intensity: CGFloat = 0.05) -> some View {
|
|
274
|
+
modifier(PulseModifier(intensity: intensity))
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/// Applies a heart/like bounce effect when toggled active.
|
|
278
|
+
/// Scales up to 1.3x then springs back. Perfect for favorite buttons.
|
|
279
|
+
/// - Parameter isActive: Boolean that triggers the bounce when it becomes true
|
|
280
|
+
func heartBounce(isActive: Bool) -> some View {
|
|
281
|
+
modifier(HeartBounceModifier(isActive: isActive))
|
|
282
|
+
}
|
|
82
283
|
}
|
package/templates/ios/FinanceTemplate/FinanceTemplate/Core/Animation/AnimatedTransitionsView.swift
CHANGED
|
@@ -57,6 +57,155 @@ struct BounceScaleModifier: ViewModifier {
|
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
// MARK: - Scale on Press Modifier
|
|
61
|
+
/// Applies scale-down + spring-back animation when pressed (like a button press).
|
|
62
|
+
struct ScaleOnPressModifier: ViewModifier {
|
|
63
|
+
@State private var isPressed = false
|
|
64
|
+
|
|
65
|
+
func body(content: Content) -> some View {
|
|
66
|
+
content
|
|
67
|
+
.scaleEffect(isPressed ? 0.95 : 1.0)
|
|
68
|
+
.animation(.spring(response: 0.3, dampingFraction: 0.7), value: isPressed)
|
|
69
|
+
.simultaneousGesture(
|
|
70
|
+
DragGesture(minimumDistance: 0)
|
|
71
|
+
.onChanged { _ in isPressed = true }
|
|
72
|
+
.onEnded { _ in isPressed = false }
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// MARK: - Haptic Feedback Modifier
|
|
78
|
+
/// Triggers haptic feedback on tap.
|
|
79
|
+
struct HapticFeedbackModifier: ViewModifier {
|
|
80
|
+
let style: UIImpactFeedbackGenerator.FeedbackStyle
|
|
81
|
+
|
|
82
|
+
func body(content: Content) -> some View {
|
|
83
|
+
content
|
|
84
|
+
.onTapGesture {
|
|
85
|
+
UIImpactFeedbackGenerator(style: style).impactOccurred()
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// MARK: - Slide and Fade Modifier
|
|
91
|
+
/// Applies a slide-from-side + fade-in animation on appear.
|
|
92
|
+
struct SlideAndFadeModifier: ViewModifier {
|
|
93
|
+
let delay: Double
|
|
94
|
+
@State private var isVisible = false
|
|
95
|
+
|
|
96
|
+
func body(content: Content) -> some View {
|
|
97
|
+
content
|
|
98
|
+
.opacity(isVisible ? 1 : 0)
|
|
99
|
+
.offset(x: isVisible ? 0 : 20)
|
|
100
|
+
.motionAware(animation: .spring(response: 0.5, dampingFraction: 0.8).delay(delay))
|
|
101
|
+
.onAppear {
|
|
102
|
+
isVisible = true
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// MARK: - Card Shadow Modifier
|
|
108
|
+
/// Applies a subtle colored shadow to cards and elevated surfaces.
|
|
109
|
+
struct CardShadowModifier: ViewModifier {
|
|
110
|
+
let color: Color
|
|
111
|
+
let radius: CGFloat
|
|
112
|
+
let y: CGFloat
|
|
113
|
+
|
|
114
|
+
func body(content: Content) -> some View {
|
|
115
|
+
content
|
|
116
|
+
.shadow(color: color.opacity(0.08), radius: radius, x: 0, y: y)
|
|
117
|
+
.shadow(color: Color.black.opacity(0.04), radius: radius / 2, x: 0, y: y / 2)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// MARK: - Elevated Shadow Modifier
|
|
122
|
+
/// Applies a deeper shadow for FABs and floating elements.
|
|
123
|
+
struct ElevatedShadowModifier: ViewModifier {
|
|
124
|
+
let color: Color
|
|
125
|
+
|
|
126
|
+
func body(content: Content) -> some View {
|
|
127
|
+
content
|
|
128
|
+
.shadow(color: color.opacity(0.12), radius: 16, x: 0, y: 8)
|
|
129
|
+
.shadow(color: Color.black.opacity(0.06), radius: 8, x: 0, y: 4)
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// MARK: - Shimmer Modifier
|
|
134
|
+
/// Applies a shimmer/skeleton-loading gradient overlay for loading states.
|
|
135
|
+
struct ShimmerModifier: ViewModifier {
|
|
136
|
+
@State private var isAnimating = false
|
|
137
|
+
|
|
138
|
+
func body(content: Content) -> some View {
|
|
139
|
+
content
|
|
140
|
+
.overlay(
|
|
141
|
+
GeometryReader { geometry in
|
|
142
|
+
if isAnimating {
|
|
143
|
+
LinearGradient(
|
|
144
|
+
colors: [
|
|
145
|
+
Color.clear,
|
|
146
|
+
Color.white.opacity(0.3),
|
|
147
|
+
Color.clear
|
|
148
|
+
],
|
|
149
|
+
startPoint: .leading,
|
|
150
|
+
endPoint: .trailing
|
|
151
|
+
)
|
|
152
|
+
.offset(x: isAnimating ? geometry.size.width : -geometry.size.width)
|
|
153
|
+
.animation(
|
|
154
|
+
Animation.linear(duration: 1.5)
|
|
155
|
+
.repeatForever(autoreverses: false),
|
|
156
|
+
value: isAnimating
|
|
157
|
+
)
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
)
|
|
161
|
+
.clipped()
|
|
162
|
+
.onAppear {
|
|
163
|
+
isAnimating = true
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// MARK: - Pulse Modifier
|
|
169
|
+
/// Applies a repeating scale pulse effect (e.g., for notifications, active indicators).
|
|
170
|
+
struct PulseModifier: ViewModifier {
|
|
171
|
+
let intensity: CGFloat
|
|
172
|
+
@State private var scale: CGFloat = 1.0
|
|
173
|
+
|
|
174
|
+
func body(content: Content) -> some View {
|
|
175
|
+
content
|
|
176
|
+
.scaleEffect(scale)
|
|
177
|
+
.onAppear {
|
|
178
|
+
withAnimation(
|
|
179
|
+
.easeInOut(duration: 1.0)
|
|
180
|
+
.repeatForever(autoreverses: true)
|
|
181
|
+
) {
|
|
182
|
+
scale = 1.0 + intensity
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// MARK: - Heart Bounce Modifier
|
|
189
|
+
/// Applies a scale-up bounce then return when toggled (e.g., favorite/like buttons).
|
|
190
|
+
struct HeartBounceModifier: ViewModifier {
|
|
191
|
+
let isActive: Bool
|
|
192
|
+
@State private var scale: CGFloat = 1.0
|
|
193
|
+
|
|
194
|
+
func body(content: Content) -> some View {
|
|
195
|
+
content
|
|
196
|
+
.scaleEffect(scale)
|
|
197
|
+
.motionAware(animation: .spring(response: 0.3, dampingFraction: 0.5))
|
|
198
|
+
.onChange(of: isActive) { _, newValue in
|
|
199
|
+
if newValue {
|
|
200
|
+
scale = 1.3
|
|
201
|
+
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
|
|
202
|
+
scale = 1.0
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
60
209
|
// MARK: - View Extensions
|
|
61
210
|
|
|
62
211
|
extension View {
|
|
@@ -79,4 +228,56 @@ extension View {
|
|
|
79
228
|
func bounceOnChange(isActive: Bool) -> some View {
|
|
80
229
|
modifier(BounceScaleModifier(isActive: isActive))
|
|
81
230
|
}
|
|
231
|
+
|
|
232
|
+
/// Applies scale-down press feedback to any tappable element.
|
|
233
|
+
/// Scales to 0.95 on press with spring return animation.
|
|
234
|
+
func scaleOnPress() -> some View {
|
|
235
|
+
modifier(ScaleOnPressModifier())
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/// Triggers haptic feedback on tap.
|
|
239
|
+
/// - Parameter style: Feedback intensity (.light, .medium, .heavy)
|
|
240
|
+
func hapticFeedback(_ style: UIImpactFeedbackGenerator.FeedbackStyle = .light) -> some View {
|
|
241
|
+
modifier(HapticFeedbackModifier(style: style))
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/// Applies a slide-from-side + fade-in animation on appear.
|
|
245
|
+
/// - Parameter delay: Delay before animation starts (default: 0)
|
|
246
|
+
func slideAndFade(delay: Double = 0) -> some View {
|
|
247
|
+
modifier(SlideAndFadeModifier(delay: delay))
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/// Applies subtle colored shadow to cards and elevated surfaces.
|
|
251
|
+
/// Uses dual-shadow technique: primary-tinted shadow + neutral shadow for depth.
|
|
252
|
+
/// - Parameters:
|
|
253
|
+
/// - color: Shadow tint color (default: .primary)
|
|
254
|
+
/// - radius: Shadow blur radius (default: 8)
|
|
255
|
+
/// - y: Vertical offset (default: 4)
|
|
256
|
+
func cardShadow(color: Color = .primary, radius: CGFloat = 8, y: CGFloat = 4) -> some View {
|
|
257
|
+
modifier(CardShadowModifier(color: color, radius: radius, y: y))
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/// Applies deeper shadow for floating elements (FABs, modals).
|
|
261
|
+
/// - Parameter color: Shadow tint color (default: .primary)
|
|
262
|
+
func elevatedShadow(color: Color = .primary) -> some View {
|
|
263
|
+
modifier(ElevatedShadowModifier(color: color))
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/// Applies a shimmer loading overlay (e.g., for skeleton placeholder views).
|
|
267
|
+
func shimmer() -> some View {
|
|
268
|
+
modifier(ShimmerModifier())
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/// Applies a repeating pulse animation (e.g., for notifications, live indicators).
|
|
272
|
+
/// - Parameter intensity: Scale increase per pulse (default: 0.05 = 5% bigger)
|
|
273
|
+
func pulse(intensity: CGFloat = 0.05) -> some View {
|
|
274
|
+
modifier(PulseModifier(intensity: intensity))
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/// Applies a heart/like bounce effect when toggled active.
|
|
278
|
+
/// Scales up to 1.3x then springs back. Perfect for favorite buttons.
|
|
279
|
+
/// - Parameter isActive: Boolean that triggers the bounce when it becomes true
|
|
280
|
+
func heartBounce(isActive: Bool) -> some View {
|
|
281
|
+
modifier(HeartBounceModifier(isActive: isActive))
|
|
282
|
+
}
|
|
82
283
|
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
// PLACEHOLDER: Replace with domain-specific strings during customization.
|
|
4
|
+
|
|
5
|
+
enum Strings {
|
|
6
|
+
// MARK: - Empty States
|
|
7
|
+
enum EmptyStates {
|
|
8
|
+
// No Results
|
|
9
|
+
static let noResultsTitle = "No Results Found"
|
|
10
|
+
static func noResultsSubtitle(_ query: String) -> String {
|
|
11
|
+
"We couldn't find anything matching \"\(query)\""
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// No Items (home/main list)
|
|
15
|
+
static let noItemsTitle = "Nothing Here Yet"
|
|
16
|
+
static let noItemsSubtitle = "Get started by adding your first item"
|
|
17
|
+
static let addItemButton = "Add Item"
|
|
18
|
+
|
|
19
|
+
// No Favorites
|
|
20
|
+
static let noFavoritesTitle = "No Favorites Yet"
|
|
21
|
+
static let noFavoritesSubtitle = "Items you favorite will appear here"
|
|
22
|
+
static let browseButton = "Browse"
|
|
23
|
+
|
|
24
|
+
// No Connection
|
|
25
|
+
static let noConnectionTitle = "No Internet Connection"
|
|
26
|
+
static let noConnectionSubtitle = "Please check your connection and try again"
|
|
27
|
+
static let retryButton = "Retry"
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// MARK: - Motion Preferences
|
|
31
|
+
enum MotionPreferences {
|
|
32
|
+
static let animationLevel = "Animations"
|
|
33
|
+
static let description = "Controls how animations and transitions appear throughout the app. System Reduce Motion setting is always respected."
|
|
34
|
+
static let reduceMotionActive = "System Reduce Motion is enabled. Animations will be simplified."
|
|
35
|
+
static let intensityFull = "Full"
|
|
36
|
+
static let intensityReduced = "Reduced"
|
|
37
|
+
static let intensityOff = "Off"
|
|
38
|
+
static let fullDescription = "All animations and transitions enabled"
|
|
39
|
+
static let reducedDescription = "Simplified cross-fade transitions only"
|
|
40
|
+
static let offDescription = "No animations — instant state changes"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -9,7 +9,10 @@
|
|
|
9
9
|
/* Begin PBXBuildFile section */
|
|
10
10
|
0030A6126AB53949A447E5A4 /* AddTransactionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D4087E872161E3965345839 /* AddTransactionView.swift */; };
|
|
11
11
|
06262F6E375D62E5C83CB6E7 /* LocalStorageProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5CB4A0AF70D48234F8E319B /* LocalStorageProvider.swift */; };
|
|
12
|
+
081B7BF598EE452C17C13248 /* MotionPreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38C603496F4A6BF6925E5478 /* MotionPreferencesView.swift */; };
|
|
13
|
+
099E5918A202176F7876BD8D /* MotionPreferencesService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 583FCC836FF458E31F3256C0 /* MotionPreferencesService.swift */; };
|
|
12
14
|
0C2A1C677B50A41C657D6D88 /* Models.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0FCDE28B386F10576BE071C /* Models.swift */; };
|
|
15
|
+
0E97036E016CA1FFFD217DD4 /* AnimatedTransitionsModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15193469E944502B83786EAD /* AnimatedTransitionsModels.swift */; };
|
|
13
16
|
13AC5FDCD39B5109826858DC /* DataRepositoryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B2A4C9064BF1A20305E2A78 /* DataRepositoryTests.swift */; };
|
|
14
17
|
2D63116A37CE16D9EACFAECF /* BudgetsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 728C18F9384ABF099DDBE598 /* BudgetsView.swift */; };
|
|
15
18
|
339B2018E800424FE60C5720 /* NetworkMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C5A7E7C81AF5E00E0A381BF /* NetworkMonitor.swift */; };
|
|
@@ -32,20 +35,17 @@
|
|
|
32
35
|
A305D126DE0BABE62D437C80 /* AccountEntity.swift in Sources */ = {isa = PBXBuildFile; fileRef = F32E86E6C71160D4E183740A /* AccountEntity.swift */; };
|
|
33
36
|
A686FF824C3467A163E8DB22 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = FBA40139BF96E8F5D0451613 /* Assets.xcassets */; };
|
|
34
37
|
A6C7FDC75029CE2B8014E9C5 /* GoalEntity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75EF7EDEC9048C32A74D39CC /* GoalEntity.swift */; };
|
|
38
|
+
B5FCA0B1591F3636F297C4AD /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93749A5DBE5A340BF09D6295 /* Strings.swift */; };
|
|
39
|
+
C603AFB1EB99F9B054DA31F2 /* AnimatedTransitionsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA4C933669D854FCE33848C8 /* AnimatedTransitionsService.swift */; };
|
|
35
40
|
C64812CB63135E8FE931EB90 /* TransactionsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AD24420E8D94F3B7B252EC1 /* TransactionsView.swift */; };
|
|
36
41
|
CFDFD5A345100A7E59E06003 /* LocalPersistence.swift in Sources */ = {isa = PBXBuildFile; fileRef = E73FB29D044A8414DC323190 /* LocalPersistence.swift */; };
|
|
37
42
|
D8454AF6FD657C0C60CEAFD7 /* CategoryEntity.swift in Sources */ = {isa = PBXBuildFile; fileRef = D545536631A59F160A2C07C0 /* CategoryEntity.swift */; };
|
|
38
43
|
D989823A63D5F0F1127638EE /* HomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 415FA5F58F95CB679BE66E24 /* HomeView.swift */; };
|
|
39
44
|
E7D118ABFBD92EAC4ACB817E /* BillEntity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA1C263945CBA4D7068C395 /* BillEntity.swift */; };
|
|
45
|
+
EE916674E2F0F9EBCC556C6D /* MotionPreferencesModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66301A39BDB01056CBD435F1 /* MotionPreferencesModels.swift */; };
|
|
40
46
|
EEF019728CCB5CF689E24E96 /* DataRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA19A16CEE9A32C13776FC44 /* DataRepository.swift */; };
|
|
47
|
+
F2BD0B1F473FDCCC9C85DEE7 /* AnimatedTransitionsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AF81BAFE40F3C3D2B1E5833 /* AnimatedTransitionsView.swift */; };
|
|
41
48
|
FB159B101849018F8A40A6F1 /* EmptyStateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 326A8F3E2250136B4EFFA138 /* EmptyStateView.swift */; };
|
|
42
|
-
0011A7CEDB5A42A4A9FCCBE0 /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC5EC469DD9D47F49EA72212 /* Strings.swift */; };
|
|
43
|
-
FA7703E8EB784C2DB6295DEA /* AnimatedTransitionsModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9536F490EBC74A558D1628AD /* AnimatedTransitionsModels.swift */; };
|
|
44
|
-
A70AF1ACCCF74265A66E111E /* AnimatedTransitionsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09D7444EA4CA4436BB1AD120 /* AnimatedTransitionsService.swift */; };
|
|
45
|
-
49D845B6FEE846FDAFC1BF08 /* AnimatedTransitionsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB844B30E17D49FDBBEF816F /* AnimatedTransitionsView.swift */; };
|
|
46
|
-
4D3826B044754313B2D61BA1 /* MotionPreferencesModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD2A62C23E2541C5944964CA /* MotionPreferencesModels.swift */; };
|
|
47
|
-
11E273AF32C6424384CF5476 /* MotionPreferencesService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B00ED63502346338D320F19 /* MotionPreferencesService.swift */; };
|
|
48
|
-
F0A979C3513F41DAB0BECFF0 /* MotionPreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9B93275A47A4B85BC823B33 /* MotionPreferencesView.swift */; };
|
|
49
49
|
/* End PBXBuildFile section */
|
|
50
50
|
|
|
51
51
|
/* Begin PBXContainerItemProxy section */
|
|
@@ -61,11 +61,13 @@
|
|
|
61
61
|
/* Begin PBXFileReference section */
|
|
62
62
|
04AED7EA6B55AADEFAE90802 /* FinanceTemplate.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = FinanceTemplate.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
63
63
|
150AF829A865D5A9EACC25BE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
|
|
64
|
+
15193469E944502B83786EAD /* AnimatedTransitionsModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnimatedTransitionsModels.swift; sourceTree = "<group>"; };
|
|
64
65
|
1C00F9B04A3A2E702DF93BEE /* CoreDataStack.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataStack.swift; sourceTree = "<group>"; };
|
|
66
|
+
2AF81BAFE40F3C3D2B1E5833 /* AnimatedTransitionsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnimatedTransitionsView.swift; sourceTree = "<group>"; };
|
|
65
67
|
2B830C1208F1D61593CB4B29 /* GoalsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GoalsView.swift; sourceTree = "<group>"; };
|
|
66
68
|
2BEF28E0E8F98C7F5D03BCBE /* BudgetEntity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BudgetEntity.swift; sourceTree = "<group>"; };
|
|
67
69
|
326A8F3E2250136B4EFFA138 /* EmptyStateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyStateView.swift; sourceTree = "<group>"; };
|
|
68
|
-
|
|
70
|
+
38C603496F4A6BF6925E5478 /* MotionPreferencesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MotionPreferencesView.swift; sourceTree = "<group>"; };
|
|
69
71
|
3A2CE72C76C692429FD8D128 /* Colors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Colors.swift; sourceTree = "<group>"; };
|
|
70
72
|
415FA5F58F95CB679BE66E24 /* HomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeView.swift; sourceTree = "<group>"; };
|
|
71
73
|
46BEE8E0E968DB2CD24E1753 /* OfflineBanner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OfflineBanner.swift; sourceTree = "<group>"; };
|
|
@@ -73,7 +75,9 @@
|
|
|
73
75
|
4DA1404BAA55F4B0201F889A /* AppConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppConfig.swift; sourceTree = "<group>"; };
|
|
74
76
|
4E1D6FE7CDDE464E6FA187C4 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
|
|
75
77
|
5454AA7EB63BDE729C41E146 /* FinanceTemplateTests.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = FinanceTemplateTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
78
|
+
583FCC836FF458E31F3256C0 /* MotionPreferencesService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MotionPreferencesService.swift; sourceTree = "<group>"; };
|
|
76
79
|
5D4087E872161E3965345839 /* AddTransactionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddTransactionView.swift; sourceTree = "<group>"; };
|
|
80
|
+
66301A39BDB01056CBD435F1 /* MotionPreferencesModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MotionPreferencesModels.swift; sourceTree = "<group>"; };
|
|
77
81
|
6AD24420E8D94F3B7B252EC1 /* TransactionsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionsView.swift; sourceTree = "<group>"; };
|
|
78
82
|
728C18F9384ABF099DDBE598 /* BudgetsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BudgetsView.swift; sourceTree = "<group>"; };
|
|
79
83
|
75EF7EDEC9048C32A74D39CC /* GoalEntity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GoalEntity.swift; sourceTree = "<group>"; };
|
|
@@ -84,9 +88,11 @@
|
|
|
84
88
|
86A2D418BE44E2AAD0CB5CBF /* MainTabView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainTabView.swift; sourceTree = "<group>"; };
|
|
85
89
|
8BA1C263945CBA4D7068C395 /* BillEntity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BillEntity.swift; sourceTree = "<group>"; };
|
|
86
90
|
8C5A7E7C81AF5E00E0A381BF /* NetworkMonitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkMonitor.swift; sourceTree = "<group>"; };
|
|
91
|
+
93749A5DBE5A340BF09D6295 /* Strings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Strings.swift; sourceTree = "<group>"; };
|
|
87
92
|
960D99E887A6CF84FFD9C135 /* MockDataProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockDataProvider.swift; sourceTree = "<group>"; };
|
|
88
93
|
AA19A16CEE9A32C13776FC44 /* DataRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataRepository.swift; sourceTree = "<group>"; };
|
|
89
94
|
C9176647AD403B9E81B2C8F7 /* FinanceTemplateApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FinanceTemplateApp.swift; sourceTree = "<group>"; };
|
|
95
|
+
CA4C933669D854FCE33848C8 /* AnimatedTransitionsService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnimatedTransitionsService.swift; sourceTree = "<group>"; };
|
|
90
96
|
D545536631A59F160A2C07C0 /* CategoryEntity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CategoryEntity.swift; sourceTree = "<group>"; };
|
|
91
97
|
E0FCDE28B386F10576BE071C /* Models.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Models.swift; sourceTree = "<group>"; };
|
|
92
98
|
E2A5DC14F392BA60D307615A /* MockDataProviderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockDataProviderTests.swift; sourceTree = "<group>"; };
|
|
@@ -95,12 +101,6 @@
|
|
|
95
101
|
F5CB4A0AF70D48234F8E319B /* LocalStorageProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalStorageProvider.swift; sourceTree = "<group>"; };
|
|
96
102
|
FBA40139BF96E8F5D0451613 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
|
97
103
|
FE0C15DF4A0311371691BD07 /* InsightEntity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InsightEntity.swift; sourceTree = "<group>"; };
|
|
98
|
-
9536F490EBC74A558D1628AD /* AnimatedTransitionsModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnimatedTransitionsModels.swift; sourceTree = "<group>"; };
|
|
99
|
-
09D7444EA4CA4436BB1AD120 /* AnimatedTransitionsService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnimatedTransitionsService.swift; sourceTree = "<group>"; };
|
|
100
|
-
CB844B30E17D49FDBBEF816F /* AnimatedTransitionsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnimatedTransitionsView.swift; sourceTree = "<group>"; };
|
|
101
|
-
CD2A62C23E2541C5944964CA /* MotionPreferencesModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MotionPreferencesModels.swift; sourceTree = "<group>"; };
|
|
102
|
-
4B00ED63502346338D320F19 /* MotionPreferencesService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MotionPreferencesService.swift; sourceTree = "<group>"; };
|
|
103
|
-
D9B93275A47A4B85BC823B33 /* MotionPreferencesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MotionPreferencesView.swift; sourceTree = "<group>"; };
|
|
104
104
|
/* End PBXFileReference section */
|
|
105
105
|
|
|
106
106
|
/* Begin PBXGroup section */
|
|
@@ -108,8 +108,8 @@
|
|
|
108
108
|
isa = PBXGroup;
|
|
109
109
|
children = (
|
|
110
110
|
326A8F3E2250136B4EFFA138 /* EmptyStateView.swift */,
|
|
111
|
-
|
|
112
|
-
|
|
111
|
+
93749A5DBE5A340BF09D6295 /* Strings.swift */,
|
|
112
|
+
C4993DBC1783F06100452CA6 /* Animation */,
|
|
113
113
|
3E1B31013348328C560DB6A6 /* Theme */,
|
|
114
114
|
);
|
|
115
115
|
path = Core;
|
|
@@ -234,6 +234,19 @@
|
|
|
234
234
|
path = Components;
|
|
235
235
|
sourceTree = "<group>";
|
|
236
236
|
};
|
|
237
|
+
C4993DBC1783F06100452CA6 /* Animation */ = {
|
|
238
|
+
isa = PBXGroup;
|
|
239
|
+
children = (
|
|
240
|
+
15193469E944502B83786EAD /* AnimatedTransitionsModels.swift */,
|
|
241
|
+
CA4C933669D854FCE33848C8 /* AnimatedTransitionsService.swift */,
|
|
242
|
+
2AF81BAFE40F3C3D2B1E5833 /* AnimatedTransitionsView.swift */,
|
|
243
|
+
66301A39BDB01056CBD435F1 /* MotionPreferencesModels.swift */,
|
|
244
|
+
583FCC836FF458E31F3256C0 /* MotionPreferencesService.swift */,
|
|
245
|
+
38C603496F4A6BF6925E5478 /* MotionPreferencesView.swift */,
|
|
246
|
+
);
|
|
247
|
+
path = Animation;
|
|
248
|
+
sourceTree = "<group>";
|
|
249
|
+
};
|
|
237
250
|
D2B443E14BBBE3F725724EA3 /* LocalStorage */ = {
|
|
238
251
|
isa = PBXGroup;
|
|
239
252
|
children = (
|
|
@@ -299,19 +312,6 @@
|
|
|
299
312
|
path = Home;
|
|
300
313
|
sourceTree = "<group>";
|
|
301
314
|
};
|
|
302
|
-
F5548A96E41143B9AE2B0475 /* Animation */ = {
|
|
303
|
-
isa = PBXGroup;
|
|
304
|
-
children = (
|
|
305
|
-
9536F490EBC74A558D1628AD /* AnimatedTransitionsModels.swift */,
|
|
306
|
-
09D7444EA4CA4436BB1AD120 /* AnimatedTransitionsService.swift */,
|
|
307
|
-
CB844B30E17D49FDBBEF816F /* AnimatedTransitionsView.swift */,
|
|
308
|
-
CD2A62C23E2541C5944964CA /* MotionPreferencesModels.swift */,
|
|
309
|
-
4B00ED63502346338D320F19 /* MotionPreferencesService.swift */,
|
|
310
|
-
D9B93275A47A4B85BC823B33 /* MotionPreferencesView.swift */,
|
|
311
|
-
);
|
|
312
|
-
path = Animation;
|
|
313
|
-
sourceTree = "<group>";
|
|
314
|
-
};
|
|
315
315
|
/* End PBXGroup section */
|
|
316
316
|
|
|
317
317
|
/* Begin PBXNativeTarget section */
|
|
@@ -398,6 +398,9 @@
|
|
|
398
398
|
files = (
|
|
399
399
|
A305D126DE0BABE62D437C80 /* AccountEntity.swift in Sources */,
|
|
400
400
|
0030A6126AB53949A447E5A4 /* AddTransactionView.swift in Sources */,
|
|
401
|
+
0E97036E016CA1FFFD217DD4 /* AnimatedTransitionsModels.swift in Sources */,
|
|
402
|
+
C603AFB1EB99F9B054DA31F2 /* AnimatedTransitionsService.swift in Sources */,
|
|
403
|
+
F2BD0B1F473FDCCC9C85DEE7 /* AnimatedTransitionsView.swift in Sources */,
|
|
401
404
|
71CD22588C17F4482E662150 /* AppConfig.swift in Sources */,
|
|
402
405
|
E7D118ABFBD92EAC4ACB817E /* BillEntity.swift in Sources */,
|
|
403
406
|
4B1231A6F5DE03FF8E0E0A8A /* BudgetEntity.swift in Sources */,
|
|
@@ -409,7 +412,6 @@
|
|
|
409
412
|
7D8CA62EA059158C74908B60 /* DataSourceResolver.swift in Sources */,
|
|
410
413
|
FB159B101849018F8A40A6F1 /* EmptyStateView.swift in Sources */,
|
|
411
414
|
58F7B061E2D219A0E8DA197B /* FinanceTemplateApp.swift in Sources */,
|
|
412
|
-
0011A7CEDB5A42A4A9FCCBE0 /* Strings.swift in Sources */,
|
|
413
415
|
A6C7FDC75029CE2B8014E9C5 /* GoalEntity.swift in Sources */,
|
|
414
416
|
37E80967377DD57E4F82DC8B /* GoalsView.swift in Sources */,
|
|
415
417
|
D989823A63D5F0F1127638EE /* HomeView.swift in Sources */,
|
|
@@ -419,9 +421,13 @@
|
|
|
419
421
|
95860BD08AF9C7391CAB2318 /* MainTabView.swift in Sources */,
|
|
420
422
|
58F60CA041D3F2047251858B /* MockDataProvider.swift in Sources */,
|
|
421
423
|
0C2A1C677B50A41C657D6D88 /* Models.swift in Sources */,
|
|
424
|
+
EE916674E2F0F9EBCC556C6D /* MotionPreferencesModels.swift in Sources */,
|
|
425
|
+
099E5918A202176F7876BD8D /* MotionPreferencesService.swift in Sources */,
|
|
426
|
+
081B7BF598EE452C17C13248 /* MotionPreferencesView.swift in Sources */,
|
|
422
427
|
339B2018E800424FE60C5720 /* NetworkMonitor.swift in Sources */,
|
|
423
428
|
3F3E5E170276B05545875BA0 /* OfflineBanner.swift in Sources */,
|
|
424
429
|
8C33D08433A0A07CF32E722D /* SettingsView.swift in Sources */,
|
|
430
|
+
B5FCA0B1591F3636F297C4AD /* Strings.swift in Sources */,
|
|
425
431
|
4179BAD8F353E1D5D1470B97 /* SyncManager.swift in Sources */,
|
|
426
432
|
717E7677B9D7CEF8B3B77687 /* TransactionEntity.swift in Sources */,
|
|
427
433
|
C64812CB63135E8FE931EB90 /* TransactionsView.swift in Sources */,
|