From 8d4d20fc76713fb59d74bfdf03428067336c65d8 Mon Sep 17 00:00:00 2001 From: songyc macbook Date: Mon, 13 Jul 2026 15:08:08 +0900 Subject: [PATCH] feat(diary): make the mood area a large square tile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit '오늘 기분'을 카드의 주인공인 200pt 정사각형 타일로 재배치 — 사진은 꽉 채우고(이모지는 우하단 배지), 이모지만 있으면 크게 가운데, 비어 있으면 '탭해서 남기기' 플레이스홀더. 오른쪽에 이모지/사진/지우기 캡슐 버튼 열. 새 문자열 en/ja 번역 추가. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_013yKDMhuF39GVYy3FMcGHh7 --- myApp/HaruDanim/IOS/Localizable.xcstrings | 81 +++++++++++++ myApp/HaruDanim/IOS/Views/DiaryView.swift | 134 +++++++++++++--------- 2 files changed, 159 insertions(+), 56 deletions(-) diff --git a/myApp/HaruDanim/IOS/Localizable.xcstrings b/myApp/HaruDanim/IOS/Localizable.xcstrings index 8884e88..1847de6 100644 --- a/myApp/HaruDanim/IOS/Localizable.xcstrings +++ b/myApp/HaruDanim/IOS/Localizable.xcstrings @@ -4049,6 +4049,22 @@ } } }, + "사진 선택": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Choose Photo" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "写真を選択" + } + } + } + }, "사진 앨범에 저장했어요.": { "localizations": { "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": { "en": { "stringUnit": { @@ -6597,6 +6646,22 @@ } } }, + "지우기": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Clear" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "消去" + } + } + } + }, "지정된 꼬리표 없음": { "localizations": { "en": { @@ -7029,6 +7094,22 @@ } } }, + "탭해서 남기기": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Tap to add" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "タップして記録" + } + } + } + }, "테마": { "localizations": { "en": { diff --git a/myApp/HaruDanim/IOS/Views/DiaryView.swift b/myApp/HaruDanim/IOS/Views/DiaryView.swift index 7e166cd..a677c78 100644 --- a/myApp/HaruDanim/IOS/Views/DiaryView.swift +++ b/myApp/HaruDanim/IOS/Views/DiaryView.swift @@ -992,75 +992,54 @@ private struct DiaryMoodCard: View { @State private var showingEmojiPicker = false @State private var photoSelection: PhotosPickerItem? + /// 기분 타일 크기 — 카드의 주인공이 되도록 큼직한 정사각형 + private let tileSize: CGFloat = 200 + static let emojiChoices = [ "😀", "🙂", "😌", "🥰", "🥳", "🤗", "😴", "😐", "😔", "😢", "😡", "😤", "🤒", "🤯", "😱", "🙃", ] var body: some View { - HStack(spacing: 14) { - VStack(alignment: .leading, spacing: 3) { + HStack(alignment: .top, spacing: 16) { + moodTile + VStack(alignment: .leading, spacing: 6) { Text("오늘 기분") - .font(.subheadline.weight(.semibold)) - Text("이모지나 사진으로 오늘의 기분을 남겨 보세요") - .font(.caption2) + .font(.headline) + Text("이모지나 사진으로\n오늘의 기분을 남겨 보세요") + .font(.caption) .foregroundStyle(.secondary) - } - Spacer() - - // 이모지 선택 - Button { - showingEmojiPicker = true - } label: { - Group { - if entry.moodEmoji.isEmpty { - Image(systemName: "face.smiling") - .font(.system(size: 26)) - .foregroundStyle(.secondary) - } else { - Text(entry.moodEmoji) - .font(.system(size: 34)) + .fixedSize(horizontal: false, vertical: true) + Spacer(minLength: 8) + VStack(alignment: .leading, spacing: 8) { + Button { + showingEmojiPicker = true + } label: { + Label("이모지 선택", systemImage: "face.smiling") } - } - .frame(width: 60, height: 60) - .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) + .popover(isPresented: $showingEmojiPicker) { + emojiPicker } - } - .frame(width: 60, height: 60) - .background(AppTheme.background) - .clipShape(RoundedRectangle(cornerRadius: 14, style: .continuous)) - } - .buttonStyle(.plain) - - if !entry.moodEmoji.isEmpty || entry.moodImageData != nil { - Button { - entry.moodEmoji = "" - entry.moodImageData = nil - touch() - } label: { - Image(systemName: "xmark.circle.fill") - .font(.title3) + PhotosPicker(selection: $photoSelection, matching: .images) { + Label("사진 선택", systemImage: "photo.badge.plus") + } + if !entry.moodEmoji.isEmpty || entry.moodImageData != nil { + Button { + entry.moodEmoji = "" + entry.moodImageData = nil + touch() + } label: { + Label("지우기", systemImage: "xmark.circle") + } .foregroundStyle(.secondary) + } } - .buttonStyle(.plain) + .font(.footnote) + .buttonStyle(.bordered) + .buttonBorderShape(.capsule) + .tint(AppTheme.green) } + .frame(maxWidth: .infinity, minHeight: tileSize, alignment: .leading) } .padding(14) .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 { LazyVGrid(columns: Array(repeating: GridItem(.fixed(46)), count: 4), spacing: 8) { ForEach(Self.emojiChoices, id: \.self) { emoji in