feat(diary): make the mood area a large square tile

'오늘 기분'을 카드의 주인공인 200pt 정사각형 타일로 재배치 — 사진은 꽉
채우고(이모지는 우하단 배지), 이모지만 있으면 크게 가운데, 비어 있으면
'탭해서 남기기' 플레이스홀더. 오른쪽에 이모지/사진/지우기 캡슐 버튼 열.
새 문자열 en/ja 번역 추가.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yKDMhuF39GVYy3FMcGHh7
This commit is contained in:
songyc macbook 2026-07-13 15:08:08 +09:00
parent daf4fc3157
commit 8d4d20fc76
2 changed files with 159 additions and 56 deletions

View File

@ -4049,6 +4049,22 @@
} }
} }
}, },
"사진 선택": {
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Choose Photo"
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "写真を選択"
}
}
}
},
"사진 앨범에 저장했어요.": { "사진 앨범에 저장했어요.": {
"localizations": { "localizations": {
"en": { "en": {
@ -5604,7 +5620,40 @@
} }
} }
}, },
"이모지 선택": {
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Choose Emoji"
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "絵文字を選択"
}
}
}
},
"이모지나 사진으로\n오늘의 기분을 남겨 보세요": {
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Capture todays mood\nwith an emoji or a photo"
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "絵文字や写真で\n今日の気分を残しましょう"
}
}
}
},
"이모지나 사진으로 오늘의 기분을 남겨 보세요": { "이모지나 사진으로 오늘의 기분을 남겨 보세요": {
"extractionState": "stale",
"localizations": { "localizations": {
"en": { "en": {
"stringUnit": { "stringUnit": {
@ -6597,6 +6646,22 @@
} }
} }
}, },
"지우기": {
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Clear"
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "消去"
}
}
}
},
"지정된 꼬리표 없음": { "지정된 꼬리표 없음": {
"localizations": { "localizations": {
"en": { "en": {
@ -7029,6 +7094,22 @@
} }
} }
}, },
"탭해서 남기기": {
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Tap to add"
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "タップして記録"
}
}
}
},
"테마": { "테마": {
"localizations": { "localizations": {
"en": { "en": {

View File

@ -992,75 +992,54 @@ private struct DiaryMoodCard: View {
@State private var showingEmojiPicker = false @State private var showingEmojiPicker = false
@State private var photoSelection: PhotosPickerItem? @State private var photoSelection: PhotosPickerItem?
///
private let tileSize: CGFloat = 200
static let emojiChoices = [ static let emojiChoices = [
"😀", "🙂", "😌", "🥰", "🥳", "🤗", "😴", "😐", "😀", "🙂", "😌", "🥰", "🥳", "🤗", "😴", "😐",
"😔", "😢", "😡", "😤", "🤒", "🤯", "😱", "🙃", "😔", "😢", "😡", "😤", "🤒", "🤯", "😱", "🙃",
] ]
var body: some View { var body: some View {
HStack(spacing: 14) { HStack(alignment: .top, spacing: 16) {
VStack(alignment: .leading, spacing: 3) { moodTile
VStack(alignment: .leading, spacing: 6) {
Text("오늘 기분") Text("오늘 기분")
.font(.subheadline.weight(.semibold)) .font(.headline)
Text("이모지나 사진으로 오늘의 기분을 남겨 보세요") Text("이모지나 사진으로\n오늘의 기분을 남겨 보세요")
.font(.caption2) .font(.caption)
.foregroundStyle(.secondary) .foregroundStyle(.secondary)
} .fixedSize(horizontal: false, vertical: true)
Spacer() Spacer(minLength: 8)
VStack(alignment: .leading, spacing: 8) {
// Button {
Button { showingEmojiPicker = true
showingEmojiPicker = true } label: {
} label: { Label("이모지 선택", systemImage: "face.smiling")
Group {
if entry.moodEmoji.isEmpty {
Image(systemName: "face.smiling")
.font(.system(size: 26))
.foregroundStyle(.secondary)
} else {
Text(entry.moodEmoji)
.font(.system(size: 34))
} }
} .popover(isPresented: $showingEmojiPicker) {
.frame(width: 60, height: 60) emojiPicker
.background(AppTheme.background, in: RoundedRectangle(cornerRadius: 14, style: .continuous))
}
.buttonStyle(.plain)
.popover(isPresented: $showingEmojiPicker) {
emojiPicker
}
//
PhotosPicker(selection: $photoSelection, matching: .images) {
Group {
if let data = entry.moodImageData, let image = UIImage(data: data) {
Image(uiImage: image)
.resizable()
.scaledToFill()
} else {
Image(systemName: "photo.badge.plus")
.font(.system(size: 24))
.foregroundStyle(.secondary)
} }
} PhotosPicker(selection: $photoSelection, matching: .images) {
.frame(width: 60, height: 60) Label("사진 선택", systemImage: "photo.badge.plus")
.background(AppTheme.background) }
.clipShape(RoundedRectangle(cornerRadius: 14, style: .continuous)) if !entry.moodEmoji.isEmpty || entry.moodImageData != nil {
} Button {
.buttonStyle(.plain) entry.moodEmoji = ""
entry.moodImageData = nil
if !entry.moodEmoji.isEmpty || entry.moodImageData != nil { touch()
Button { } label: {
entry.moodEmoji = "" Label("지우기", systemImage: "xmark.circle")
entry.moodImageData = nil }
touch()
} label: {
Image(systemName: "xmark.circle.fill")
.font(.title3)
.foregroundStyle(.secondary) .foregroundStyle(.secondary)
}
} }
.buttonStyle(.plain) .font(.footnote)
.buttonStyle(.bordered)
.buttonBorderShape(.capsule)
.tint(AppTheme.green)
} }
.frame(maxWidth: .infinity, minHeight: tileSize, alignment: .leading)
} }
.padding(14) .padding(14)
.background(AppTheme.surface, in: RoundedRectangle(cornerRadius: 16, style: .continuous)) .background(AppTheme.surface, in: RoundedRectangle(cornerRadius: 16, style: .continuous))
@ -1078,6 +1057,49 @@ private struct DiaryMoodCard: View {
} }
} }
/// : ( ),
/// , .
private var moodTile: some View {
Button {
showingEmojiPicker = true
} label: {
ZStack {
RoundedRectangle(cornerRadius: 20, style: .continuous)
.fill(AppTheme.background)
if let data = entry.moodImageData, let image = UIImage(data: data) {
Image(uiImage: image)
.resizable()
.scaledToFill()
.frame(width: tileSize, height: tileSize)
.clipShape(RoundedRectangle(cornerRadius: 20, style: .continuous))
if !entry.moodEmoji.isEmpty {
Text(entry.moodEmoji)
.font(.system(size: 40))
.padding(7)
.background(.thinMaterial, in: Circle())
.frame(maxWidth: .infinity, maxHeight: .infinity,
alignment: .bottomTrailing)
.padding(10)
}
} else if !entry.moodEmoji.isEmpty {
Text(entry.moodEmoji)
.font(.system(size: 110))
} else {
VStack(spacing: 10) {
Image(systemName: "face.smiling")
.font(.system(size: 44))
Text("탭해서 남기기")
.font(.caption)
}
.foregroundStyle(.tertiary)
}
}
.frame(width: tileSize, height: tileSize)
.contentShape(RoundedRectangle(cornerRadius: 20, style: .continuous))
}
.buttonStyle(.plain)
}
private var emojiPicker: some View { private var emojiPicker: some View {
LazyVGrid(columns: Array(repeating: GridItem(.fixed(46)), count: 4), spacing: 8) { LazyVGrid(columns: Array(repeating: GridItem(.fixed(46)), count: 4), spacing: 8) {
ForEach(Self.emojiChoices, id: \.self) { emoji in ForEach(Self.emojiChoices, id: \.self) { emoji in