Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

All notable changes to DotoryCount are recorded in this file.

## [0.4.2] - 2026-09-24

- Keep the photographed glass floor behind the acorns while retaining the
front rim and side reflections. A softly feathered oval removes only the
foreground floor overlay that made acorns appear behind the base.
- Add a contact shadow along the inner floor to ground sparse and full piles.
- Bumped the app to version 0.4.2 (build 10).

## [0.4.1] - 2026-09-24

- Keep the iPhone experience in portrait, where the photographic jar and date
Expand Down
24 changes: 12 additions & 12 deletions DotoryCount.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 9;
CURRENT_PROJECT_VERSION = 10;
DEVELOPMENT_TEAM = W395S42ZJ9;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
Expand All @@ -409,7 +409,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 0.4.1;
MARKETING_VERSION = 0.4.2;
PRODUCT_BUNDLE_IDENTIFIER = com.dotoryman.dotorycount;
PRODUCT_NAME = "$(TARGET_NAME)";
STRING_CATALOG_GENERATE_SYMBOLS = YES;
Expand All @@ -428,7 +428,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 9;
CURRENT_PROJECT_VERSION = 10;
DEVELOPMENT_TEAM = W395S42ZJ9;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
Expand All @@ -441,7 +441,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 0.4.1;
MARKETING_VERSION = 0.4.2;
PRODUCT_BUNDLE_IDENTIFIER = com.dotoryman.dotorycount;
PRODUCT_NAME = "$(TARGET_NAME)";
STRING_CATALOG_GENERATE_SYMBOLS = YES;
Expand All @@ -459,10 +459,10 @@
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 9;
CURRENT_PROJECT_VERSION = 10;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
MARKETING_VERSION = 0.4.1;
MARKETING_VERSION = 0.4.2;
PRODUCT_BUNDLE_IDENTIFIER = com.dotoryman.dotorycount.tests;
PRODUCT_NAME = "$(TARGET_NAME)";
STRING_CATALOG_GENERATE_SYMBOLS = NO;
Expand All @@ -480,10 +480,10 @@
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 9;
CURRENT_PROJECT_VERSION = 10;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
MARKETING_VERSION = 0.4.1;
MARKETING_VERSION = 0.4.2;
PRODUCT_BUNDLE_IDENTIFIER = com.dotoryman.dotorycount.tests;
PRODUCT_NAME = "$(TARGET_NAME)";
STRING_CATALOG_GENERATE_SYMBOLS = NO;
Expand All @@ -500,9 +500,9 @@
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 9;
CURRENT_PROJECT_VERSION = 10;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 0.4.1;
MARKETING_VERSION = 0.4.2;
PRODUCT_BUNDLE_IDENTIFIER = com.dotoryman.dotorycount.uitests;
PRODUCT_NAME = "$(TARGET_NAME)";
STRING_CATALOG_GENERATE_SYMBOLS = NO;
Expand All @@ -519,9 +519,9 @@
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 9;
CURRENT_PROJECT_VERSION = 10;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 0.4.1;
MARKETING_VERSION = 0.4.2;
PRODUCT_BUNDLE_IDENTIFIER = com.dotoryman.dotorycount.uitests;
PRODUCT_NAME = "$(TARGET_NAME)";
STRING_CATALOG_GENERATE_SYMBOLS = NO;
Expand Down
63 changes: 45 additions & 18 deletions DotoryCount/Features/Home/PhotographicJarScene.swift
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,9 @@ struct PhotographicJarScene: View {
.frame(width: width, height: height)

Ellipse()
.fill(.black.opacity(0.20))
.frame(width: 510 * scale, height: 108 * scale)
.blur(radius: 31 * scale)
.fill(.black.opacity(0.32))
.frame(width: 510 * scale, height: 82 * scale)
.blur(radius: 18 * scale)
.position(x: 470 * scale, y: 1282 * scale)

Ellipse()
Expand All @@ -155,28 +155,37 @@ struct PhotographicJarScene: View {
.blur(radius: 54 * scale)
.position(x: 470 * scale, y: 1130 * scale)

ForEach(settledIndices, id: \.self) { index in
acorn(at: PhotographicJarStages.placements[index],
golden: isGolden(index: index), scale: scale)
}
ZStack(alignment: .topLeading) {
ForEach(settledIndices, id: \.self) { index in
acorn(at: PhotographicJarStages.placements[index],
golden: isGolden(index: index), scale: scale)
}

if stage > 0 {
let placement = PhotographicJarStages.placements[stage - 1]
TimelineView(.animation(minimumInterval: 1.0 / 60, paused: !isAnimating)) { timeline in
let elapsed = timeline.date.timeIntervalSince(dropStartedAt)
let motion = isAnimating ? min(max(elapsed / JarDropTiming.duration, 0), 1) : 1
let offset = fallingOffset(placement, progress: motion)
acorn(at: placement,
golden: isGolden(index: stage - 1),
scale: scale,
offset: offset,
extraRotation: fallingRotation(progress: motion))
if stage > 0 {
let placement = PhotographicJarStages.placements[stage - 1]
TimelineView(.animation(minimumInterval: 1.0 / 60, paused: !isAnimating)) { timeline in
let elapsed = timeline.date.timeIntervalSince(dropStartedAt)
let motion = isAnimating ? min(max(elapsed / JarDropTiming.duration, 0), 1) : 1
let offset = fallingOffset(placement, progress: motion)
acorn(at: placement,
golden: isGolden(index: stage - 1),
scale: scale,
offset: offset,
extraRotation: fallingRotation(progress: motion))
}
}
}
.frame(width: width, height: height)

Image("JarGlassFront")
.resizable()
.frame(width: width, height: height)
.mask(
JarForegroundGlassMask()
.fill(style: FillStyle(eoFill: true))
.blur(radius: 14 * scale)
.frame(width: width, height: height)
)
.allowsHitTesting(false)

LinearGradient(
Expand Down Expand Up @@ -293,3 +302,21 @@ struct PhotographicJarScene: View {
}
}
}

/// The photographed bottom is already in JarEmptyBase behind the acorns. Keep
/// the front rim and side refractions, but leave the central inner floor clear
/// so the nuts sit visibly *on* that surface instead of behind another copy.
private struct JarForegroundGlassMask: Shape {
func path(in rect: CGRect) -> Path {
let scale = rect.width / 941
var path = Path()
path.addRect(rect)
path.addEllipse(in: CGRect(
x: 165 * scale,
y: 1215 * scale,
width: 610 * scale,
height: 170 * scale
))
return path
}
}
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ An iOS app that records meaningful time by adding one acorn to a jar each day.

**언어 및 기술 · Languages & Technologies:** Swift · SwiftUI · SwiftData

v0.4.1: 사실적인 36단계 도토리 병, 낙하 애니메이션, 편리해진 기준일 선택. 아이폰은 세로 화면에 맞춰 표시됩니다.
v0.4.2: 사실적인 36단계 도토리 병, 자연스러운 유리 바닥 깊이, 낙하 애니메이션, 편리해진 기준일 선택. 아이폰은 세로 화면에 맞춰 표시됩니다.

v0.4.1: A 36-stage photographic jar, animated acorn drops, easier date selection, and a portrait iPhone layout.
v0.4.2: A 36-stage photographic jar with grounded acorns, animated drops, easier date selection, and a portrait iPhone layout.

[변경 이력 · Changelog](CHANGELOG.md) · [개발 계획 · Roadmap](ROADMAP.md)