From b7e007b583ca2a949027c7011a585dd353536f0b Mon Sep 17 00:00:00 2001 From: sion Date: Wed, 15 Jan 2025 20:19:09 +0900 Subject: [PATCH 1/3] =?UTF-8?q?[Feat]=20=EC=B6=94=EC=96=B5=EC=B9=B4?= =?UTF-8?q?=EB=93=9C=20=EB=AA=A9=EB=A1=9D=EC=97=90=EC=84=9C=20=EC=B5=9C?= =?UTF-8?q?=EC=8B=A0=20=EC=B9=B4=EB=93=9C=EB=A5=BC=20=ED=81=AC=EA=B2=8C=20?= =?UTF-8?q?=EB=B3=B4=EC=97=AC=EC=A3=BC=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Views/MemoryCard/MemoryCardsView.swift | 70 +++++++++++++------ 1 file changed, 49 insertions(+), 21 deletions(-) diff --git a/Harmony/Harmony/Views/MemoryCard/MemoryCardsView.swift b/Harmony/Harmony/Views/MemoryCard/MemoryCardsView.swift index f2c9353..c7e9246 100644 --- a/Harmony/Harmony/Views/MemoryCard/MemoryCardsView.swift +++ b/Harmony/Harmony/Views/MemoryCard/MemoryCardsView.swift @@ -14,11 +14,12 @@ struct MemoryCardsView: View { @State private var isAppeared = false @State private var isContentVisible = false @State private var appearingCardIndex = 0 - + let columns = [ - GridItem(.flexible(), spacing: 20), GridItem(.flexible(), spacing: 20) + GridItem(.flexible(), spacing: 20), + GridItem(.flexible(), spacing: 20) ] - + var body: some View { NavigationStack { ZStack { @@ -28,6 +29,7 @@ struct MemoryCardsView: View { .background(Color.gray1) } else { VStack(spacing: 0) { + // MARK: - 상단 바 요소들 VStack(spacing: 0) { if isSearchBarVisible { HStack { @@ -80,7 +82,8 @@ struct MemoryCardsView: View { .background(Color.white) } } - + + // 정렬 버튼 HStack { Spacer() Button(action: { @@ -102,27 +105,55 @@ struct MemoryCardsView: View { Divider() .background(Color.gray3) - + + // 오류 메시지 if let errorMessage = viewModel.errorMessage { Text(errorMessage) .foregroundColor(.red) .padding() } else { + // MARK: - ScrollView 영역 ScrollView { - LazyVGrid(columns: columns, spacing: 30) { - ForEach(Array(viewModel.filteredMemoryCards.enumerated()), id: \.element.id) { index, card in - NavigationLink(destination: MemoryCardDetailView(memoryCardId: card.id, groupId: card.groupId ?? 1)) { - MemoryCardView(card: card, viewModel: viewModel) - .frame(maxWidth: .infinity, maxHeight: .infinity) - .padding(.horizontal, -15) - .padding(.bottom, -15) - .opacity(index <= appearingCardIndex ? 1 : 0) - .offset(y: index <= appearingCardIndex ? 0 : 100) - .animation(.spring(response: 0.4, dampingFraction: 0.7, blendDuration: 0.2).delay(Double(index) * 0.03), value: appearingCardIndex) + VStack(spacing: 0) { + if let newCard = viewModel.newMemoryCard { + NavigationLink( + destination: MemoryCardDetailView( + memoryCardId: newCard.id, + groupId: newCard.groupId ?? 1 + ) + ) { + MemoryCardView(card: newCard, viewModel: viewModel) + .padding(.top, 20) } } + + LazyVGrid(columns: columns, spacing: 30) { + ForEach(Array(viewModel.filteredMemoryCards.enumerated()), id: \.element.id) { index, card in + if card != viewModel.newMemoryCard { + NavigationLink( + destination: MemoryCardDetailView( + memoryCardId: card.id, + groupId: card.groupId ?? 1 + ) + ) { + MemoryCardView(card: card, viewModel: viewModel) + .frame(maxWidth: .infinity, maxHeight: .infinity) + .padding(.horizontal, -15) + .padding(.bottom, -15) + .opacity(index <= appearingCardIndex ? 1 : 0) + .offset(y: index <= appearingCardIndex ? 0 : 100) + .animation( + .spring(response: 0.4, dampingFraction: 0.7, blendDuration: 0.2) + .delay(Double(index) * 0.03), + value: appearingCardIndex + ) + } + } + } + } + .padding([.horizontal, .top]) + .background(Color.gray1) } - .padding([.horizontal, .top]) .background(Color.gray1) } .background(Color.gray1) @@ -143,10 +174,6 @@ struct MemoryCardsView: View { isContentVisible = true } } - - - - .onChange(of: viewModel.isLoading) { isLoading in if !isLoading { withAnimation(.easeInOut(duration: 0.3)) { @@ -155,9 +182,10 @@ struct MemoryCardsView: View { animateCards() } } - } } + + // MARK: - 카드 애니메이션 private func animateCards() { let totalCards = viewModel.filteredMemoryCards.count for index in 0.. Date: Wed, 15 Jan 2025 21:04:29 +0900 Subject: [PATCH 2/3] =?UTF-8?q?[Fix]=20MemoryCardView=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EC=83=81=ED=95=98=20=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83=20?= =?UTF-8?q?=EC=A1=B0=EC=A0=95=EC=9A=A9=20=EC=BD=94=EB=93=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EB=B0=8F=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Views/MemoryCard/MemoryCardView.swift | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/Harmony/Harmony/Views/MemoryCard/MemoryCardView.swift b/Harmony/Harmony/Views/MemoryCard/MemoryCardView.swift index 7f1859f..9bb85a4 100644 --- a/Harmony/Harmony/Views/MemoryCard/MemoryCardView.swift +++ b/Harmony/Harmony/Views/MemoryCard/MemoryCardView.swift @@ -17,24 +17,32 @@ struct MemoryCardView: View { var body: some View { GeometryReader { geometry in + + let isNew = (viewModel.newMemoryCard == card) + VStack(alignment: .leading, spacing: 10) { ZStack(alignment: .topTrailing) { if let url = URL(string: card.image), !card.image.isEmpty { KFImage(url) .resizable() .aspectRatio(contentMode: .fill) - .frame(width: geometry.size.width, height: 120) + .frame( + width: geometry.size.width, + height: isNew ? 180 : 120 + ) .clipped() .cornerRadius(10, corners: [.topLeft, .topRight]) } else { Rectangle() .fill(Color.gray.opacity(0.2)) - .frame(width: geometry.size.width, height: 120) + .frame( + width: geometry.size.width, + height: isNew ? 180 : 120 + ) .cornerRadius(10, corners: [.topLeft, .topRight]) } - // "새로운 추억" 캡슐 추가 - if viewModel.newMemoryCard == card { + if isNew { Text("새로운 추억") .font(.system(size: 14, weight: .bold)) .foregroundColor(.white) @@ -66,7 +74,7 @@ struct MemoryCardView: View { ) } .padding(.horizontal) - .frame(height: 200) + .frame(height: (viewModel.newMemoryCard == card) ? 260 : 200) .frame(maxHeight: .infinity) .transition(.opacity.combined(with: .scale)) } From 2f4ec1c6a238681e45157ff9e5e9450686f768ab Mon Sep 17 00:00:00 2001 From: sion Date: Wed, 15 Jan 2025 21:43:21 +0900 Subject: [PATCH 3/3] =?UTF-8?q?[Fix]=20Figma=20=EB=94=94=EC=9E=90=EC=9D=B8?= =?UTF-8?q?=EC=97=90=20=EB=A7=9E=EA=B2=8C=20=EA=B0=9C=20=EB=B3=84=20?= =?UTF-8?q?=EC=B6=94=EC=96=B5=EC=B9=B4=EB=93=9C=EC=99=80=20=ED=85=8C?= =?UTF-8?q?=EB=91=90=EB=A6=AC=20=EC=98=A4=EB=B2=84=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EC=9D=98=20CornerRadius=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Harmony/Harmony/Views/MemoryCard/MemoryCardView.swift | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Harmony/Harmony/Views/MemoryCard/MemoryCardView.swift b/Harmony/Harmony/Views/MemoryCard/MemoryCardView.swift index 9bb85a4..6c99e44 100644 --- a/Harmony/Harmony/Views/MemoryCard/MemoryCardView.swift +++ b/Harmony/Harmony/Views/MemoryCard/MemoryCardView.swift @@ -31,7 +31,6 @@ struct MemoryCardView: View { height: isNew ? 180 : 120 ) .clipped() - .cornerRadius(10, corners: [.topLeft, .topRight]) } else { Rectangle() .fill(Color.gray.opacity(0.2)) @@ -39,7 +38,6 @@ struct MemoryCardView: View { width: geometry.size.width, height: isNew ? 180 : 120 ) - .cornerRadius(10, corners: [.topLeft, .topRight]) } if isNew { @@ -50,7 +48,7 @@ struct MemoryCardView: View { .padding(.horizontal, 10) .background(Color.mainGreen) .cornerRadius(15) - .offset(x: -10, y: 10) // 위치 조정 + .offset(x: -10, y: 10) } } @@ -66,10 +64,9 @@ struct MemoryCardView: View { .padding([.horizontal, .bottom]) } .background(Color.white) - .cornerRadius(15) .shadow(color: Color.black.opacity(0.1), radius: 5, x: 0, y: 5) .overlay( - RoundedRectangle(cornerRadius: 15) + RoundedRectangle(cornerRadius: 0) .stroke(Color.gray3, lineWidth: 0.5) ) }