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:
parent
daf4fc3157
commit
8d4d20fc76
@ -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 today’s 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": {
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user