diff --git "a/\353\251\244\353\262\204-\352\260\234\353\260\234-\355\217\264\353\215\224/\354\234\240\354\240\225\354\243\274/BoostPillyze/BoostPillyze.xcodeproj/project.pbxproj" "b/\353\251\244\353\262\204-\352\260\234\353\260\234-\355\217\264\353\215\224/\354\234\240\354\240\225\354\243\274/BoostPillyze/BoostPillyze.xcodeproj/project.pbxproj" index 91e5ac8..cb8d31a 100644 --- "a/\353\251\244\353\262\204-\352\260\234\353\260\234-\355\217\264\353\215\224/\354\234\240\354\240\225\354\243\274/BoostPillyze/BoostPillyze.xcodeproj/project.pbxproj" +++ "b/\353\251\244\353\262\204-\352\260\234\353\260\234-\355\217\264\353\215\224/\354\234\240\354\240\225\354\243\274/BoostPillyze/BoostPillyze.xcodeproj/project.pbxproj" @@ -29,6 +29,8 @@ 9B5AE8462C452BA300BC1ED7 /* JSONLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B5AE8452C452BA300BC1ED7 /* JSONLoader.swift */; }; 9B5AE8492C452D8000BC1ED7 /* food_list_with_rank.json in Resources */ = {isa = PBXBuildFile; fileRef = 9B5AE8482C452D8000BC1ED7 /* food_list_with_rank.json */; }; 9B5AE84D2C46860800BC1ED7 /* AddDietTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B5AE84C2C46860800BC1ED7 /* AddDietTab.swift */; }; + 9B5AE8A12C53B6AD00BC1ED7 /* add-list.lottie in Resources */ = {isa = PBXBuildFile; fileRef = 9B5AE8A02C53B6AD00BC1ED7 /* add-list.lottie */; }; + 9B5AE8A72C53BAF400BC1ED7 /* Lottie in Frameworks */ = {isa = PBXBuildFile; productRef = 9B5AE8A62C53BAF400BC1ED7 /* Lottie */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -66,6 +68,7 @@ 9B5AE8452C452BA300BC1ED7 /* JSONLoader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSONLoader.swift; sourceTree = ""; }; 9B5AE8482C452D8000BC1ED7 /* food_list_with_rank.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = food_list_with_rank.json; sourceTree = ""; }; 9B5AE84C2C46860800BC1ED7 /* AddDietTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddDietTab.swift; sourceTree = ""; }; + 9B5AE8A02C53B6AD00BC1ED7 /* add-list.lottie */ = {isa = PBXFileReference; lastKnownFileType = file; path = "add-list.lottie"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -73,6 +76,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 9B5AE8A72C53BAF400BC1ED7 /* Lottie in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -149,6 +153,7 @@ 9B0470212C41752800ADAFF3 /* Resource */ = { isa = PBXGroup; children = ( + 9B5AE89F2C53B69400BC1ED7 /* Lottie */, 9B5AE8472C452D6F00BC1ED7 /* JSON */, 9B046FFA2C41735C00ADAFF3 /* Assets.xcassets */, ); @@ -244,6 +249,14 @@ path = ViewModel; sourceTree = ""; }; + 9B5AE89F2C53B69400BC1ED7 /* Lottie */ = { + isa = PBXGroup; + children = ( + 9B5AE8A02C53B6AD00BC1ED7 /* add-list.lottie */, + ); + path = Lottie; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -260,6 +273,9 @@ dependencies = ( ); name = BoostPillyze; + packageProductDependencies = ( + 9B5AE8A62C53BAF400BC1ED7 /* Lottie */, + ); productName = BoostPillyze; productReference = 9B046FF32C41735B00ADAFF3 /* BoostPillyze.app */; productType = "com.apple.product-type.application"; @@ -310,6 +326,9 @@ Base, ); mainGroup = 9B046FEA2C41735B00ADAFF3; + packageReferences = ( + 9B5AE8A52C53BAF400BC1ED7 /* XCRemoteSwiftPackageReference "lottie-ios" */, + ); productRefGroup = 9B046FF42C41735B00ADAFF3 /* Products */; projectDirPath = ""; projectRoot = ""; @@ -328,6 +347,7 @@ 9B046FFE2C41735C00ADAFF3 /* Preview Assets.xcassets in Resources */, 9B046FFB2C41735C00ADAFF3 /* Assets.xcassets in Resources */, 9B5AE8492C452D8000BC1ED7 /* food_list_with_rank.json in Resources */, + 9B5AE8A12C53B6AD00BC1ED7 /* add-list.lottie in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -641,6 +661,25 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ + +/* Begin XCRemoteSwiftPackageReference section */ + 9B5AE8A52C53BAF400BC1ED7 /* XCRemoteSwiftPackageReference "lottie-ios" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/airbnb/lottie-ios"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 4.5.0; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 9B5AE8A62C53BAF400BC1ED7 /* Lottie */ = { + isa = XCSwiftPackageProductDependency; + package = 9B5AE8A52C53BAF400BC1ED7 /* XCRemoteSwiftPackageReference "lottie-ios" */; + productName = Lottie; + }; +/* End XCSwiftPackageProductDependency section */ }; rootObject = 9B046FEB2C41735B00ADAFF3 /* Project object */; } diff --git "a/\353\251\244\353\262\204-\352\260\234\353\260\234-\355\217\264\353\215\224/\354\234\240\354\240\225\354\243\274/BoostPillyze/BoostPillyze/AddDiet/View/AddDietView.swift" "b/\353\251\244\353\262\204-\352\260\234\353\260\234-\355\217\264\353\215\224/\354\234\240\354\240\225\354\243\274/BoostPillyze/BoostPillyze/AddDiet/View/AddDietView.swift" index 73455e9..f0a1560 100644 --- "a/\353\251\244\353\262\204-\352\260\234\353\260\234-\355\217\264\353\215\224/\354\234\240\354\240\225\354\243\274/BoostPillyze/BoostPillyze/AddDiet/View/AddDietView.swift" +++ "b/\353\251\244\353\262\204-\352\260\234\353\260\234-\355\217\264\353\215\224/\354\234\240\354\240\225\354\243\274/BoostPillyze/BoostPillyze/AddDiet/View/AddDietView.swift" @@ -7,6 +7,7 @@ import SwiftUI import Combine +import Lottie struct AddDietView: View { @@ -23,42 +24,60 @@ struct AddDietView: View { @State private var currentTab: AddDietTab = .most @State private var categories: [String] = ["전체", "음식", "세트", "인기"] @State private var currentCategory: String = "인기" + @State private var playbackMode: LottiePlaybackMode = LottiePlaybackMode.paused + @State private var animationCount = 0 var body: some View { - SearchHeaderView( - didTapCancelButton: didTapCancelButton, - searchKeyword: $searchKeyword - ) - .padding(.horizontal) - - ZStack(alignment: .bottom) { - TopTabBar(currentTab: $currentTab) - Rectangle() - .frame(height: 1) - .foregroundStyle(.disabled) + VStack { + SearchHeaderView( + didTapCancelButton: didTapCancelButton, + searchKeyword: $searchKeyword + ) + .padding(.horizontal) + + ZStack(alignment: .bottom) { + TopTabBar(currentTab: $currentTab) + Rectangle() + .frame(height: 1) + .foregroundStyle(.disabled) + } + + ScrollView(.horizontal) { + HStack { + ForEach(categories, id: \.self) { category in + CategoryChipButton(currentCategory: $currentCategory, title: category) + } + } + .padding(.vertical, 11) + .padding(.horizontal, 20) + } + + switch currentTab { + case .most: + ZStack { + FoodList( + didTapFoodListItem: didTapFoodListItem, + foods: $output.foods, + selectedFoods: $output.selectedFoods + ) + } + case .favorites: + PlaceholderView() + case .custom: + Spacer() + } } - - ScrollView(.horizontal) { - HStack { - ForEach(categories, id: \.self) { category in - CategoryChipButton(currentCategory: $currentCategory, title: category) + .overlay { + if animationCount > 0 { + LottieView { + try await DotLottieFile.named("add-list") } + .playing(.fromProgress(0, toProgress: 1, loopMode: .playOnce)) + .id(animationCount) } - .padding(.vertical, 11) - .padding(.horizontal, 20) } - - switch currentTab { - case .most: - FoodList( - didTapFoodListItem: didTapFoodListItem, - foods: $output.foods, - selectedFoods: $output.selectedFoods - ) - case .favorites: - PlaceholderView() - case .custom: - Spacer() + .onReceive(output.playAddListLottie) { + animationCount += 1 } } } diff --git "a/\353\251\244\353\262\204-\352\260\234\353\260\234-\355\217\264\353\215\224/\354\234\240\354\240\225\354\243\274/BoostPillyze/BoostPillyze/AddDiet/ViewModel/AddDietViewModel.swift" "b/\353\251\244\353\262\204-\352\260\234\353\260\234-\355\217\264\353\215\224/\354\234\240\354\240\225\354\243\274/BoostPillyze/BoostPillyze/AddDiet/ViewModel/AddDietViewModel.swift" index d0d804d..54e2058 100644 --- "a/\353\251\244\353\262\204-\352\260\234\353\260\234-\355\217\264\353\215\224/\354\234\240\354\240\225\354\243\274/BoostPillyze/BoostPillyze/AddDiet/ViewModel/AddDietViewModel.swift" +++ "b/\353\251\244\353\262\204-\352\260\234\353\260\234-\355\217\264\353\215\224/\354\234\240\354\240\225\354\243\274/BoostPillyze/BoostPillyze/AddDiet/ViewModel/AddDietViewModel.swift" @@ -53,6 +53,7 @@ private extension AddDietViewModel { output.selectedFoods.remove(food) } else { output.selectedFoods.insert(food) + output.playAddListLottie.send() } } } diff --git "a/\353\251\244\353\262\204-\352\260\234\353\260\234-\355\217\264\353\215\224/\354\234\240\354\240\225\354\243\274/BoostPillyze/BoostPillyze/AddDiet/ViewModel/AddDietViewModelInputOutput.swift" "b/\353\251\244\353\262\204-\352\260\234\353\260\234-\355\217\264\353\215\224/\354\234\240\354\240\225\354\243\274/BoostPillyze/BoostPillyze/AddDiet/ViewModel/AddDietViewModelInputOutput.swift" index 3b1d40e..a293e8f 100644 --- "a/\353\251\244\353\262\204-\352\260\234\353\260\234-\355\217\264\353\215\224/\354\234\240\354\240\225\354\243\274/BoostPillyze/BoostPillyze/AddDiet/ViewModel/AddDietViewModelInputOutput.swift" +++ "b/\353\251\244\353\262\204-\352\260\234\353\260\234-\355\217\264\353\215\224/\354\234\240\354\240\225\354\243\274/BoostPillyze/BoostPillyze/AddDiet/ViewModel/AddDietViewModelInputOutput.swift" @@ -24,5 +24,6 @@ extension AddDietViewModel { @Published var foods: [Food] = [] @Published var selectedFoods: Set = [] + let playAddListLottie: PassthroughSubject = .init() } } diff --git "a/\353\251\244\353\262\204-\352\260\234\353\260\234-\355\217\264\353\215\224/\354\234\240\354\240\225\354\243\274/BoostPillyze/BoostPillyze/Resource/Lottie/add-list.lottie" "b/\353\251\244\353\262\204-\352\260\234\353\260\234-\355\217\264\353\215\224/\354\234\240\354\240\225\354\243\274/BoostPillyze/BoostPillyze/Resource/Lottie/add-list.lottie" new file mode 100644 index 0000000..bbb43d2 Binary files /dev/null and "b/\353\251\244\353\262\204-\352\260\234\353\260\234-\355\217\264\353\215\224/\354\234\240\354\240\225\354\243\274/BoostPillyze/BoostPillyze/Resource/Lottie/add-list.lottie" differ