Skip to content

[release] 1.0.18 업데이트#45

Merged
mark77234 merged 1 commit intomainfrom
dev
Mar 5, 2026
Merged

[release] 1.0.18 업데이트#45
mark77234 merged 1 commit intomainfrom
dev

Conversation

@mark77234
Copy link
Collaborator

업데이트 내용

  • 프로필 팬덤, PICKS 비활성화
  • 태그 수정, 프로필 이미지 삭제, 수정 API 연동
  • 프로필 수정 페이지 UI/UX 업데이트

* refactor(MyCollectionProfileSettings): 프로필 설정 페이지 분리작업

* feat(ProfileCard): 팬덤, PICKS 비활성화

* feat(ProfileSetting): 프로필 이미지 변경, 삭제, 태그 수정 API 연동

* feat(ProfileSetting): 프로필 설정 페이지 UI/UX 업데이트

* feat(ProfileSetting): UI 디테일 수정

* feat(ProfileSetting): 태그 수정 시 도움말 추가

* refactor(ProfileSetting): 리팩토링

* feat(ProfileSetting): 여백 설정

* feat(1.0.18): 버전 업데이트
Copilot AI review requested due to automatic review settings March 5, 2026 12:07
@mark77234 mark77234 merged commit 712afb7 into main Mar 5, 2026
1 check passed
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the “My Collection” profile settings flow for release 1.0.18, including disabling 일부 프로필 통계(팬덤/PICKS), adding tag/profile-image edit capabilities wired to backend APIs, and refreshing the profile settings UI/UX.

Changes:

  • Introduces a dedicated ProfileSettingViewModel and a new profile settings section UI with tag editing + profile image pick/reset.
  • Extends UserService with profile image delete/upload/update and tag update APIs (including presigned URL upload).
  • Disables 팬덤/PICKS stats display and bumps app version/build numbers to 1.0.18 (18).

Reviewed changes

Copilot reviewed 15 out of 18 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
KillingPart/Views/Screens/Main/My/MyCollection/ProfileSetting/components/MyCollectionProfileTagSectionView.swift New tag display/edit UI block with helper message support
KillingPart/Views/Screens/Main/My/MyCollection/ProfileSetting/components/MyCollectionProfileTagEditActionRowView.swift New cancel/submit row for tag editing (with progress state)
KillingPart/Views/Screens/Main/My/MyCollection/ProfileSetting/components/MyCollectionProfileSettingsInfoRowView.swift New info row view for profile settings card
KillingPart/Views/Screens/Main/My/MyCollection/ProfileSetting/components/MyCollectionProfileSettingsInfoCardView.swift New info card layout (image + name/tag rows)
KillingPart/Views/Screens/Main/My/MyCollection/ProfileSetting/components/MyCollectionProfileSettingsHeaderView.swift New header UI for profile settings (back button)
KillingPart/Views/Screens/Main/My/MyCollection/ProfileSetting/components/MyCollectionProfileSettingPageContainerView.swift New container card styling/layout wrapper
KillingPart/Views/Screens/Main/My/MyCollection/ProfileSetting/components/MyCollectionProfileImageColumnView.swift New profile image picker + reset UI column
KillingPart/Views/Screens/Main/My/MyCollection/ProfileSetting/components/MyCollectionAccountActionButton.swift New logout/withdraw entry button
KillingPart/Views/Screens/Main/My/MyCollection/ProfileSetting/ProfileSettingSection.swift New full profile settings section (keyboard handling, tag validation UX, image picking)
KillingPart/Views/Screens/Main/My/MyCollection/MyCollectionView.swift Integrates ProfileSettingViewModel and wires updated-user sync between screens
KillingPart/Views/Screens/Main/My/MyCollection/Components/ProfileSettingSection/MyCollectionProfileSettingsSection.swift Removes legacy profile settings section
KillingPart/Views/Screens/Main/My/MyCollection/Components/ProfileSettingSection/MyCollectionProfileSettingsHeaderView.swift Removes legacy profile settings header
KillingPart/Views/Screens/Main/My/MyCollection/Components/ProfileCard/MyCollectionProfileCard.swift Comments out 팬덤/PICKS stat items (feature disabled)
KillingPart/ViewModels/My/MyCollection/ProfileSetting/ProfileSettingViewModel.swift New view model handling tag/image update flows + validation + messaging
KillingPart/ViewModels/My/MyCollection/MyCollectionViewModel.swift Adds helper to apply updated user model locally
KillingPart/Services/UserService.swift Adds profile image/tag endpoints + presigned upload + richer error parsing
KillingPart/Models/UserModel.swift Adds models for presigned URL + update requests
KillingPart.xcodeproj/project.pbxproj Bumps marketing/build versions to 1.0.18 / 18

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


private func applyUpdatedUser(_ user: UserModel) {
self.user = user
tagDraft = user.tag
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

applyUpdatedUser(_:) sets tagDraft = user.tag without normalization, reintroducing a leading "@" if the backend returns it. This can re-create the "@@" display issue and also affects canSubmitTagUpdate comparisons. Consider applying the same normalization used for tag updates when writing back to tagDraft.

Suggested change
tagDraft = user.tag
tagDraft = normalizedTag(from: user.tag)

Copilot uses AI. Check for mistakes.
switch tagValidationFeedback {
case .invalidFormat:
return TagHelperMessage(
text: "30자 이내의 영문과 숫자, 특수문자([.],[_])로 조합해주세요.",
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In tagHelperMessage, the .invalidFormat helper text says "30자 이내" but omits the minimum length (4자 이상) that the UI validates elsewhere and that the ViewModel enforces. This can mislead users when a tag is too short. Align this helper text with the actual validation rules (e.g., 4~30자).

Suggested change
text: "30자 이내의 영문과 숫자, 특수문자([.],[_])로 조합해주세요.",
text: "4자 이상 30자 이내의 영문과 숫자, 특수문자([.],[_])로 조합해주세요.",

Copilot uses AI. Check for mistakes.
Comment on lines +218 to +230
let trimmed = rawTag.trimmingCharacters(in: .whitespacesAndNewlines)
if trimmed.hasPrefix("@") {
return String(trimmed.dropFirst())
}
return trimmed
}

private func isTagFormatValid(_ tag: String) -> Bool {
guard (4...30).contains(tag.count) else { return false }
let allowedCharacters = CharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyz0123456789_.")
guard tag.rangeOfCharacter(from: allowedCharacters.inverted) == nil else { return false }
guard !tag.hasPrefix("."), !tag.hasSuffix("."), !tag.contains("..") else { return false }
return true
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tag normalization/validation logic is duplicated in this view (normalizedTag, isTagFormatValid) and also exists in ProfileSettingViewModel (normalizedTag, validateTag). Keeping rules in two places risks subtle drift (e.g., allowed characters/length) and inconsistent UX. Consider exposing a single validation API from the ViewModel (or a shared helper) and using it for both canSubmitTagUpdate and the helper message.

Suggested change
let trimmed = rawTag.trimmingCharacters(in: .whitespacesAndNewlines)
if trimmed.hasPrefix("@") {
return String(trimmed.dropFirst())
}
return trimmed
}
private func isTagFormatValid(_ tag: String) -> Bool {
guard (4...30).contains(tag.count) else { return false }
let allowedCharacters = CharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyz0123456789_.")
guard tag.rangeOfCharacter(from: allowedCharacters.inverted) == nil else { return false }
guard !tag.hasPrefix("."), !tag.hasSuffix("."), !tag.contains("..") else { return false }
return true
// Delegate normalization to the ViewModel to ensure a single source of truth.
return viewModel.normalizedTag(from: rawTag)
}
private func isTagFormatValid(_ tag: String) -> Bool {
// Delegate validation to the ViewModel to avoid duplicating tag rules here.
return viewModel.validateTag(tag)

Copilot uses AI. Check for mistakes.
}
.foregroundStyle(Color.kpPrimary)
}
.buttonStyle(.plain)
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The back button is icon-only and currently has no accessibility label/hint, which will be read as an unlabeled button by VoiceOver. Add an .accessibilityLabel (and optionally .accessibilityHint) describing the action (e.g., "뒤로가기").

Suggested change
.buttonStyle(.plain)
.buttonStyle(.plain)
.accessibilityLabel("뒤로가기")

Copilot uses AI. Check for mistakes.
Comment on lines +38 to +39
// MyCollectionProfileStatItemView(value: fanStatText, title: "팬덤")
// MyCollectionProfileStatItemView(value: pickStatText, title: "PICKS")
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leaving feature-disabled UI as commented-out code makes the layout harder to maintain and easy to forget. Prefer removing these views entirely, or guard them behind an explicit feature flag/config so the intent is clear without commented code.

Suggested change
// MyCollectionProfileStatItemView(value: fanStatText, title: "팬덤")
// MyCollectionProfileStatItemView(value: pickStatText, title: "PICKS")

Copilot uses AI. Check for mistakes.

func syncUser(_ user: UserModel?) {
self.user = user
tagDraft = user?.tag ?? ""
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

syncUser(_:) assigns tagDraft = user?.tag ?? "" which can include a leading "@". Since the editing UI renders a separate "@" prefix, users can end up seeing "@@..." in the TextField. Consider storing a normalized value (strip leading "@" and trim) in tagDraft when syncing the user.

Suggested change
tagDraft = user?.tag ?? ""
let rawTag = user?.tag ?? ""
tagDraft = normalizedTag(from: rawTag)

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants