- KFImage 공통 옵션(다운샘플링, scaleFactor, backgroundDecode, cancelOnDisappear, retry) 캡슐화한 DownsampledKFImage 추가 - 채팅-캐릭터 탭 Character/Recent/배너 뷰에서 인라인 KFImage 제거 → 공통 뷰 적용 - 수평 리스트 HStack → LazyHStack으로 교체해 프리로딩/메모리 개선 Why: 대형 원본 디코딩으로 인한 메모리 스파이크 완화 및 일관된 이미지 로딩 정책 적용. 유지보수성 및 성능 향상.
		
			
				
	
	
		
			65 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			Swift
		
	
	
	
	
	
			
		
		
	
	
			65 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			Swift
		
	
	
	
	
	
//
 | 
						|
//  CharacterItemView.swift
 | 
						|
//  SodaLive
 | 
						|
//
 | 
						|
//  Created by klaus on 8/29/25.
 | 
						|
//
 | 
						|
 | 
						|
import SwiftUI
 | 
						|
import Kingfisher
 | 
						|
 | 
						|
struct CharacterItemView: View {
 | 
						|
    
 | 
						|
    let character: Character
 | 
						|
    let size: CGFloat
 | 
						|
    let rank: Int
 | 
						|
    let isShowRank: Bool
 | 
						|
    
 | 
						|
    private var capHeight: CGFloat {
 | 
						|
        UIFont(name: Font.preBold.rawValue, size: 72)?.capHeight ?? 72
 | 
						|
    }
 | 
						|
    
 | 
						|
    var body: some View {
 | 
						|
        VStack(alignment: .leading, spacing: 4) {
 | 
						|
            ZStack(alignment: .bottomLeading) {
 | 
						|
                DownsampledKFImage(
 | 
						|
                    url: URL(string: character.imageUrl),
 | 
						|
                    size: CGSize(width: size, height: size)
 | 
						|
                )
 | 
						|
                .cornerRadius(12)
 | 
						|
                
 | 
						|
                if isShowRank {
 | 
						|
                    Text("\(rank)")
 | 
						|
                        .font(.custom(Font.preBold.rawValue, size: 72))
 | 
						|
                        .foregroundColor(.white)
 | 
						|
                        .lineLimit(1)
 | 
						|
                        .frame(height: capHeight)
 | 
						|
                }
 | 
						|
            }
 | 
						|
            
 | 
						|
            Text(character.name)
 | 
						|
                .font(.custom(Font.preRegular.rawValue, size: 18))
 | 
						|
                .foregroundColor(.white)
 | 
						|
                .lineLimit(1)
 | 
						|
                .truncationMode(.tail)
 | 
						|
            
 | 
						|
            if let desc = character.description, !desc.isEmpty {
 | 
						|
                Text(desc)
 | 
						|
                    .font(.custom(Font.preRegular.rawValue, size: 14))
 | 
						|
                    .foregroundColor(Color(hex: "78909C"))
 | 
						|
                    .lineLimit(1)
 | 
						|
            }
 | 
						|
        }
 | 
						|
        .frame(width: size, alignment: .leading)
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
#Preview {
 | 
						|
    CharacterItemView(
 | 
						|
        character: Character(characterId: 1, name: "찰리", description: "새로운 친구", imageUrl: "https://picsum.photos/300"),
 | 
						|
        size: 168,
 | 
						|
        rank: 20,
 | 
						|
        isShowRank: true
 | 
						|
    )
 | 
						|
}
 |