feature/#54 - 리스트뷰 placeholder 모델 적용 - #59
Conversation
Walkthrough서비스 로고 카탈로그와 이미지 세트 메타데이터를 추가하고, Changes서비스 로고 아바타
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant SecretListView
participant DVVaultContainer
participant ServiceLogoCatalog
SecretListView->>DVVaultContainer: service와 typeIcon 전달
DVVaultContainer->>ServiceLogoCatalog: 서비스 로고 조회
ServiceLogoCatalog-->>DVVaultContainer: 로고 또는 nil 반환
DVVaultContainer-->>SecretListView: 로고, 이니셜 또는 타입 아이콘 표시
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
Projects/DVPresentation/Sources/Dependencies/SecretClient.swift (1)
75-78: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
public extension대신 선언에 직접 접근 제어를 지정하세요.
preview만 공개해야 하므로 extension은 기본 접근 수준으로 두고public static let preview를 명시하는 편이 API 범위를 분명히 합니다.수정 예시
-public extension [Secret] { +extension [Secret] { - static let preview: [Secret] = [ + public static let preview: [Secret] = [As per path instructions, "public extension 패턴 대신 각 선언에 직접 접근 제어가 명시되어 있는지 확인하세요."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@Projects/DVPresentation/Sources/Dependencies/SecretClient.swift` around lines 75 - 78, Change the [Secret] extension to use the default access level instead of public, and mark only the preview property with explicit public access. Keep the existing preview fixture contents unchanged.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@Projects/DVDesign/SampleApp/Sources/DVVaultContainerPreviewView.swift`:
- Around line 10-22: Update the sample data in the vaults array to include a
typeIcon fallback for entries whose service is nil, and update the
DVVaultContainer call site to pass that tuple value through as typeIcon.
Preserve existing service and status values while ensuring the sample exercises
the avatar fallback behavior.
In `@Projects/DVPresentation/Sources/Dependencies/SecretClient.swift`:
- Around line 31-41: Split the `.all`, `.liked`, and `.project` branches in
`fetchByQuery` so each collection applies its own preview predicate: `.all`
returns non-deleted secrets, `.liked` returns only secrets with `liked == true`,
and `.project` returns only secrets linked to the requested `projectID`; update
the corresponding preview fixtures so each collection’s list state can be
validated independently.
---
Nitpick comments:
In `@Projects/DVPresentation/Sources/Dependencies/SecretClient.swift`:
- Around line 75-78: Change the [Secret] extension to use the default access
level instead of public, and mark only the preview property with explicit public
access. Keep the existing preview fixture contents unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 691eedf6-9858-4676-9542-407e4b85613b
⛔ Files ignored due to path filters (4)
Projects/DVDesign/Resources/Assets.xcassets/ServiceLogos/github.imageset/github.svgis excluded by!**/*.svgProjects/DVDesign/Resources/Assets.xcassets/ServiceLogos/google.imageset/google.svgis excluded by!**/*.svgProjects/DVDesign/Resources/Assets.xcassets/ServiceLogos/kakaotalk.imageset/kakaotalk.svgis excluded by!**/*.svgProjects/DVDesign/Resources/Assets.xcassets/ServiceLogos/naver.imageset/naver.svgis excluded by!**/*.svg
📒 Files selected for processing (12)
Projects/DVDesign/Resources/Assets.xcassets/ServiceLogos/Contents.jsonProjects/DVDesign/Resources/Assets.xcassets/ServiceLogos/github.imageset/Contents.jsonProjects/DVDesign/Resources/Assets.xcassets/ServiceLogos/google.imageset/Contents.jsonProjects/DVDesign/Resources/Assets.xcassets/ServiceLogos/kakaotalk.imageset/Contents.jsonProjects/DVDesign/Resources/Assets.xcassets/ServiceLogos/naver.imageset/Contents.jsonProjects/DVDesign/SampleApp/Sources/DVVaultContainerPreviewView.swiftProjects/DVDesign/Sources/Components/DVVaultContainer.swiftProjects/DVDesign/Sources/Foundations/ServiceLogo/ServiceLogoCatalog.swiftProjects/DVPresentation/Sources/Dependencies/SecretClient.swiftProjects/DVPresentation/Sources/Features/CreateSecret/Model/CreatableSecretType.swiftProjects/DVPresentation/Sources/Features/SecretList/SecretListView.swiftProjects/DVPresentation/Sources/Support/SecretType+Icon.swift
DVVaultContainer.swift:71 — renderingMode(.template) + .foregroundStyle(Color.dv(.white))로 SVG 전체를 흰색 단색으로
CreatableSecretType.swift 원본은 person.badge.key.fill. 새 SecretType+Icon.swift에선 checkmark.shield.fill.
|
|
🟡 P2 · 설계/유지보수
ServiceLogoCatalog.swift:24-44 — 별칭 dict와 로고 dict를 따로 두면, 로고 추가 시 두 곳을 동기화해야 하는 실수 소지.
Dependency 정의 파일에 preview 데이터 80줄이 몰림. SecretClient+Preview.swift로 분리 권장 — Dependency 인터페이스와
프로젝트 룰이 "선언마다 접근 제어 명시"라면 (coderabbit path instructions), public extension 대신 extension [Secret]
ServiceLogoCatalog.swift에 private extension Color 정의. DVDesign에 DVColor 유틸이 이미 있으니 Color+Hex.swift로 -> 이거는 선택적으로 반영 |
-> 이거는 스타일에 따라 반영 여부 결정하면 될 듯. |
doyeonk429
left a comment
There was a problem hiding this comment.
my CC 칭찬 보내드립니다
✅ 잘한 부분
- service → 이니셜 → typeIcon 3단 폴백 우선순위 명료.
- KakaoTalk 제외한 SVG 자산에 CC0 라이선스 근거(Simple Icons) 첨부.
- Preview fixture가 폴백 3단계 × SecretType 6종을 실제로 커버 — 회귀 감지에 유용.
- SecretType+Icon.swift를 만들어 SelectSecretType/SecretList 두 곳이 같은 소스를 쓰게 만든 방향은 좋음(단, P1의 side-effect만 정리).
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
Projects/DVPresentation/Sources/Dependencies/SecretClient+Preview.swift (1)
24-24: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win프리뷰 fixture를 공개 API에서 제외하세요.
제공된 사용처는 모두
DVPresentation내부이므로, 외부 모듈 사용이 없다면public을 제거해 fixture가 모듈 API 계약에 포함되지 않게 하세요.
Projects/DVPresentation/Sources/Dependencies/SecretClient+Preview.swift#L24-L24:[Secret].preview의public을 제거하세요.Projects/DVPresentation/Sources/Dependencies/SecretClient+Preview.swift#L27-L27:preview(in:)의public을 제거하세요.Projects/DVPresentation/Sources/Dependencies/SecretClient+Preview.swift#L87-L87:[Project].preview의public을 제거하세요.As per path instructions, “접근 제어가 가능한 가장 엄격한 수준인지 확인하세요.”
수정 예시
- public static let preview: [Secret] = previewFixtures.map(\.secret) + static let preview: [Secret] = previewFixtures.map(\.secret) - public static func preview(in projectID: Project.ID) -> [Secret] { + static func preview(in projectID: Project.ID) -> [Secret] { - public static let preview: [Project] = [ + static let preview: [Project] = [🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@Projects/DVPresentation/Sources/Dependencies/SecretClient`+Preview.swift at line 24, 프리뷰 fixture가 공개 모듈 API에 노출되지 않도록 SecretClient+Preview.swift의 [Secret].preview, preview(in:), [Project].preview 선언에서 public 접근 제어자를 제거하고, 외부 접근이 불가능한 가장 엄격한 수준을 적용하세요.Source: Path instructions
Projects/DVDesign/Sources/Foundations/ServiceLogo/ServiceLogoCatalog.swift (1)
52-55: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winAlias 인덱스 생성에도 동일한 정규화를 적용하세요.
현재 조회 시에는
normalize(service)를 사용하지만 인덱스 생성 시에는alias를 그대로 키로 저장합니다. 향후"Google Workspace"같은 alias를 추가하면 저장 키와 조회 키가 달라져 매칭이 실패합니다.수정 예시
for alias in entry.aliases { - result[alias] = entry.logo + result[normalize(alias)] = entry.logo }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@Projects/DVDesign/Sources/Foundations/ServiceLogo/ServiceLogoCatalog.swift` around lines 52 - 55, Update the logosByAlias index construction to apply normalize(alias) before storing each alias key, matching the normalization used by service lookup. Keep mapping the normalized key to entry.logo and preserve the existing entries.reduce flow.Projects/DVDesign/SampleApp/Sources/DVVaultContainerPreviewView.swift (1)
13-25: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winBool 플래그 대신 명명된 샘플 모델을 사용하세요.
vaults[index].4가typeIcon사용 여부를 의미해 데이터의 의도가 호출부에 숨겨져 있습니다.VaultPreviewItem구조체의typeIcon: Image?프로퍼티로 표현하면 필드 순서 변경이나 잘못된 인덱스 전달을 예방할 수 있습니다.개선 예시
+private struct VaultPreviewItem { + let name: String + let date: String + let trailingIcon: DVVaultContainer.TrailingIcon? + let service: String? + let typeIcon: Image? +} + - private let vaults: [(String, String, DVVaultContainer.TrailingIcon?, String?, Bool)] = [ + private let vaults: [VaultPreviewItem] = [ - ("내가 설정한 이름", "2026.04.01", nil, nil, true), + .init(name: "내가 설정한 이름", date: "2026.04.01", trailingIcon: nil, service: nil, typeIcon: placeholderTypeIcon),- typeIcon: vaults[index].4 ? placeholderTypeIcon : nil, + typeIcon: vaults[index].typeIcon,Also applies to: 71-71
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@Projects/DVDesign/SampleApp/Sources/DVVaultContainerPreviewView.swift` around lines 13 - 25, Replace the positional vault tuple and its Boolean flag in DVVaultContainerPreviewView with a named VaultPreviewItem model containing a typeIcon: Image? property. Update the vaults sample data and all consumers, including the referenced later usage, to access named properties instead of tuple indices while preserving the current preview behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@Projects/DVDesign/Sources/Foundations/ServiceLogo/ServiceLogoCatalog.swift`:
- Around line 22-26: Update ServiceLogoCatalog.normalize to make its filtering
behavior match the documented and alias-supported character range: retain only
ASCII English letters and digits, or consistently revise the comment and alias
policy to support Unicode. Prefer the smallest change that preserves the
existing ASCII alias behavior.
---
Nitpick comments:
In `@Projects/DVDesign/SampleApp/Sources/DVVaultContainerPreviewView.swift`:
- Around line 13-25: Replace the positional vault tuple and its Boolean flag in
DVVaultContainerPreviewView with a named VaultPreviewItem model containing a
typeIcon: Image? property. Update the vaults sample data and all consumers,
including the referenced later usage, to access named properties instead of
tuple indices while preserving the current preview behavior.
In `@Projects/DVDesign/Sources/Foundations/ServiceLogo/ServiceLogoCatalog.swift`:
- Around line 52-55: Update the logosByAlias index construction to apply
normalize(alias) before storing each alias key, matching the normalization used
by service lookup. Keep mapping the normalized key to entry.logo and preserve
the existing entries.reduce flow.
In `@Projects/DVPresentation/Sources/Dependencies/SecretClient`+Preview.swift:
- Line 24: 프리뷰 fixture가 공개 모듈 API에 노출되지 않도록 SecretClient+Preview.swift의
[Secret].preview, preview(in:), [Project].preview 선언에서 public 접근 제어자를 제거하고, 외부
접근이 불가능한 가장 엄격한 수준을 적용하세요.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 964d0415-ff45-47e2-a674-1e23881e21d2
📒 Files selected for processing (7)
Projects/DVDesign/Resources/Assets.xcassets/ServiceLogos/kakaotalk.imageset/Contents.jsonProjects/DVDesign/SampleApp/Sources/DVVaultContainerPreviewView.swiftProjects/DVDesign/Sources/Components/DVVaultContainer.swiftProjects/DVDesign/Sources/Foundations/Color/Color+Hex.swiftProjects/DVDesign/Sources/Foundations/ServiceLogo/ServiceLogoCatalog.swiftProjects/DVPresentation/Sources/Dependencies/SecretClient+Preview.swiftProjects/DVPresentation/Sources/Dependencies/SecretClient.swift
🚧 Files skipped from review as they are similar to previous changes (2)
- Projects/DVDesign/Resources/Assets.xcassets/ServiceLogos/kakaotalk.imageset/Contents.json
- Projects/DVDesign/Sources/Components/DVVaultContainer.swift
| /// 영문/숫자만 남기고 비교한다. "Google Cloud"처럼 알려지지 않은 표기는 | ||
| /// `aliases`에 미리 추가해두지 않는 한 조용히 매칭 실패해 이니셜 폴백으로 빠진다. | ||
| private static func normalize(_ raw: String) -> String { | ||
| raw.lowercased().filter { $0.isLetter || $0.isNumber } | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Locate and inspect the target file and relevant symbol usages without executing repo code.
if [ -f Projects/DVDesign/Sources/Foundations/ServiceLogo/ServiceLogoCatalog.swift ]; then
echo "== file exists =="
wc -l Projects/DVDesign/Sources/Foundations/ServiceLogo/ServiceLogoCatalog.swift
echo "== outline =="
ast-grep outline Projects/DVDesign/Sources/Foundations/ServiceLogo/ServiceLogoCatalog.swift || true
echo "== relevant lines =="
nl -ba Projects/DVDesign/Sources/Foundations/ServiceLogo/ServiceLogoCatalog.swift | sed -n '1,140p'
else
echo "target file not found"
fd -a 'ServiceLogoCatalog.swift' .
fi
echo "== related ServiceLogo references =="
rg -n "normalize|aliases|ServiceLogo|ServiceLogoCatalog|isASCII|isLetter|isNumber" Projects/DVDesign -g '*.swift' || true
echo "== Swift/unicode properties probe =="
python3 - <<'PY'
# Read-only semantic probe: inspect how Swift Unicode scalar properties are commonly documented
# and demonstrate equivalent Python-style Unicode is_alnum split behavior, without running repo code.
samples = {
"Google Cloud": ["Google Cloud"],
"3D": ["3D"],
"Cafe": ["Cafe"],
"Zürich": ["Zürich"],
"1ø1": ["1ø1"],
"α": ["α"],
"Ω": ["Ω"],
}
print("In Swift Character.isLetter/isNumber, Unicode letters/digits are included, e.g.:")
for sample, chars in samples.items():
print(f"{sample!r}: {' '.join(f\"'{c}'={ord(c):04X}\" for c in sample)}")
PYRepository: DevaultProject/Devault-macOS
Length of output: 514
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== target file =="
cat -n Projects/DVDesign/Sources/Foundations/ServiceLogo/ServiceLogoCatalog.swift
echo "== related ServiceLogo references =="
rg -n "normalize|aliases|ServiceLogo|ServiceLogoCatalog|isASCII|isLetter|isNumber" Projects/DVDesign -g '*.swift' || true
echo "== Swift/unicode properties probe =="
python3 - <<'PY'
samples = {
"Google Cloud": ["Google Cloud"],
"3D": ["3D"],
"Cafe": ["Cafe"],
"Zürich": ["Zürich"],
"1ø1": ["1ø1"],
"α": ["α"],
"Ω": ["Ω"],
}
print("Examples of Unicode letters/digits that String.CharacterSet.letters/digits would include:")
for sample, chars in samples.items():
print(f"{sample!r}: {' '.join(f\"'{c}'={ord(c):04X}\" for c in sample)}")
PYRepository: DevaultProject/Devault-macOS
Length of output: 5826
정규화 규칙과 구현의 문자 범위를 일치시키세요.
주석은 영문/숫자만 남긴다고 설명하지만 isLetter/isNumber는 Unicode 문자와 숫자도 통과시킵니다. 현재 alias가 영문 ASCII로 정의되어 있다면 영어+숫자로 엄격히 필터링하거나, Unicode alias가 허용된다고 주석과 alias 정책을 함께 명시하세요.
수정 예시
- raw.lowercased().filter { $0.isLetter || $0.isNumber }
+ raw.lowercased().filter { $0.isASCII && ($0.isLetter || $0.isNumber) }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| /// 영문/숫자만 남기고 비교한다. "Google Cloud"처럼 알려지지 않은 표기는 | |
| /// `aliases`에 미리 추가해두지 않는 한 조용히 매칭 실패해 이니셜 폴백으로 빠진다. | |
| private static func normalize(_ raw: String) -> String { | |
| raw.lowercased().filter { $0.isLetter || $0.isNumber } | |
| } | |
| /// 영문/숫자만 남기고 비교한다. "Google Cloud"처럼 알려지지 않은 표기는 | |
| /// `aliases`에 미리 추가해두지 않는 한 조용히 매칭 실패해 이니셜 폴백으로 빠진다. | |
| private static func normalize(_ raw: String) -> String { | |
| raw.lowercased().filter { $0.isASCII && ($0.isLetter || $0.isNumber) } | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@Projects/DVDesign/Sources/Foundations/ServiceLogo/ServiceLogoCatalog.swift`
around lines 22 - 26, Update ServiceLogoCatalog.normalize to make its filtering
behavior match the documented and alias-supported character range: retain only
ASCII English letters and digits, or consistently revise the comment and alias
policy to support Unicode. Prefer the smallest change that preserves the
existing ASCII alias behavior.
|
.oauth 아이콘 : SecretType+Icon.swift:17에 여전히 checkmark.shield.fill. SelectSecretType 카드 그리드 아이콘이 원본(person.badge.key.fill)에서 바뀐 채로 유지 되는데 @yeseonglee 의도 맞나용? |
|
넹 checkmark shield 맞습니당 |
✨ What’s this PR?
📌 관련 이슈 (Related Issue)
🧶 주요 변경 내용 (Summary)
DVVaultContainer아바타에 3단계 폴백 추가: 서비스 로고 매칭 →service첫 글자 이니셜 →secretType아이콘ServiceLogoCatalog로 별칭(alias) 매핑 (Simple Icons, CC0 라이선스)📸 스크린샷 (Optional)
🧪 테스트 / 검증 내역
💬 기타 공유 사항
🙇🏻♀️ 리뷰 가이드 (선택)
Summary by CodeRabbit