Skip to content

Commit 0a84a1a

Browse files
CaptainSharkydanast2
authored andcommitted
#40: переход на Деталку из Избранного (#68)
1 parent 11394b9 commit 0a84a1a

File tree

10 files changed

+104
-32
lines changed

10 files changed

+104
-32
lines changed

EatHub/EatHub/Application/AppDependencies.swift

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,16 @@ struct AppDependencies {
1212
let mealsService: MealsService
1313
let detailsViewModelBuilder: (DetailsViewModuleInput) -> DetailsViewModel
1414
let launchScreenStateManager: LaunchScreenStateManager
15+
let favoritesManager: FavoritesManagerInterface
1516

1617
init() {
1718
let apiRequester = APIRequester()
1819
let mealsService = MealsService(requester: apiRequester)
1920
self.mealsService = mealsService
2021

22+
let favoritesManager = FavoritesManager()
23+
self.favoritesManager = favoritesManager
24+
2125
let detailsViewModelBuilder: ((DetailsViewModuleInput) -> DetailsViewModel) = { input in
2226
DetailsViewModel(
2327
id: input.id,
@@ -39,6 +43,10 @@ struct AppDependencies {
3943
}
4044

4145
func makeFavoriteViewModel() -> FavoriteViewModel {
42-
FavoriteViewModel(favoritesManager: FavoritesManager(), mealsService: mealsService)
46+
FavoriteViewModel(
47+
favoritesManager: favoritesManager,
48+
mealsService: mealsService,
49+
detailsViewModelBuilder: detailsViewModelBuilder
50+
)
4351
}
4452
}

EatHub/EatHub/Design/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"images" : [
33
{
4+
"filename" : "icon.png",
45
"idiom" : "universal",
56
"platform" : "ios",
67
"size" : "1024x1024"
@@ -12,6 +13,7 @@
1213
"value" : "dark"
1314
}
1415
],
16+
"filename" : "icon 1.png",
1517
"idiom" : "universal",
1618
"platform" : "ios",
1719
"size" : "1024x1024"
@@ -23,6 +25,7 @@
2325
"value" : "tinted"
2426
}
2527
],
28+
"filename" : "icon 2.png",
2629
"idiom" : "universal",
2730
"platform" : "ios",
2831
"size" : "1024x1024"
366 KB
Loading
366 KB
Loading
366 KB
Loading

EatHub/EatHub/Mappers/MealMapper/MealMapper.swift

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,3 @@ extension MealItemResponseModel {
3838
)
3939
}
4040
}
41-
42-
extension Meal {
43-
func mapToRecipe() -> RecipeViewModel {
44-
RecipeViewModel(id: id, name: name, imageName: thumbnail ?? "MealTemplate")
45-
}
46-
}

EatHub/EatHub/Modules/Favorite/FavoriteView.swift

Lines changed: 61 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,38 @@ import SwiftUI
22

33
struct FavoriteView: View {
44
@ObservedObject var viewModel: FavoriteViewModel
5+
@State private var selectedItem: RecipeViewModel?
6+
@State private var showDetail: Bool = false
7+
@Namespace private var animationNamespace
8+
9+
private enum Constants {
10+
static let animationDuration: TimeInterval = 0.5
11+
static let detailZIndex: Double = 1
12+
static let detailTransition: AnyTransition = .asymmetric(
13+
insertion: .move(edge: .bottom),
14+
removal: .move(edge: .bottom)
15+
)
16+
}
517

618
var body: some View {
719
NavigationView {
8-
ScrollView {
9-
VStack(alignment: .leading, spacing: 0) {
10-
favoritesTitle
11-
favoritesList
20+
ZStack {
21+
ScrollView {
22+
VStack(alignment: .leading, spacing: 0) {
23+
favoritesTitle
24+
favoritesList
25+
}
26+
}
27+
.background(Color(.systemGroupedBackground))
28+
.onAppear {
29+
viewModel.refreshFavorites()
30+
}
31+
32+
if let selectedItem, showDetail {
33+
openDetailsView(for: selectedItem)
1234
}
1335
}
14-
.background(Color(.systemGroupedBackground))
1536
.navigationBarHidden(true)
16-
.onAppear {
17-
viewModel.refreshFavorites()
18-
}
1937
}
2038
}
2139
}
@@ -30,20 +48,48 @@ private extension FavoriteView {
3048

3149
var favoritesList: some View {
3250
LazyVStack(spacing: 8) {
33-
ForEach(viewModel.likedRecipes) { recipe in
34-
// TODO: Добавить переход
35-
// NavigationLink(destination: RecipeDetailView(recipe: recipe)) {
51+
ForEach(viewModel.likedRecipes) { recipeViewModel in
3652
RecipeRow(
37-
recipe: recipe,
53+
recipe: recipeViewModel,
3854
onToggleFavorite: {
39-
viewModel.toggleFavorite(for: recipe)
55+
viewModel.toggleFavorite(for: recipeViewModel)
4056
}
4157
)
42-
// }
43-
.buttonStyle(PlainButtonStyle())
58+
.onTapGesture {
59+
withAnimation(.easeInOut(duration: Constants.animationDuration)) {
60+
selectedItem = recipeViewModel
61+
showDetail = true
62+
}
63+
}
4464
}
4565
}
4666
.padding(.horizontal)
4767
.padding(.top, 8)
4868
}
69+
70+
@ViewBuilder
71+
func openDetailsView(for recipeViewModel: RecipeViewModel) -> some View {
72+
let viewModel = viewModel.detailsViewModelBuilder(
73+
DetailsViewModuleInput(
74+
id: recipeViewModel.id,
75+
name: recipeViewModel.name,
76+
thumbnail: recipeViewModel.thumbnail
77+
)
78+
)
79+
DetailsView(
80+
viewModel: viewModel,
81+
onClose: {
82+
withAnimation(.easeInOut(duration: Constants.animationDuration)) {
83+
showDetail = false
84+
viewModel.isCloseButtonHidden = true
85+
}
86+
DispatchQueue.main.asyncAfter(deadline: .now() + Constants.animationDuration) {
87+
selectedItem = nil
88+
}
89+
},
90+
namespace: animationNamespace
91+
)
92+
.zIndex(Constants.detailZIndex)
93+
.transition(Constants.detailTransition)
94+
}
4995
}

EatHub/EatHub/Modules/Favorite/FavoriteViewModel.swift

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,22 @@ import Combine
44
final class FavoriteViewModel: ObservableObject {
55
@Published var likedRecipes: [RecipeViewModel] = []
66
var recipesIdentifiers: [String] = []
7+
var detailsViewModelBuilder: (DetailsViewModuleInput) -> DetailsViewModel
78

89
let title = "Favourites"
910

1011
private let favoritesManager: FavoritesManagerInterface
1112
private let mealsService: MealsServiceInterface
1213
private var cancellables = Set<AnyCancellable>()
1314

14-
init(favoritesManager: FavoritesManagerInterface, mealsService: MealsServiceInterface) {
15+
init(
16+
favoritesManager: FavoritesManagerInterface,
17+
mealsService: MealsServiceInterface,
18+
detailsViewModelBuilder: @escaping ((DetailsViewModuleInput) -> DetailsViewModel)
19+
) {
1520
self.favoritesManager = favoritesManager
1621
self.mealsService = mealsService
22+
self.detailsViewModelBuilder = detailsViewModelBuilder
1723

1824
// убрать
1925
favoritesManager.populateInitialFavorites(with: ["52943", "52869", "52883", "52823"])
@@ -48,11 +54,20 @@ final class FavoriteViewModel: ObservableObject {
4854
for id in ids {
4955
mealsService.fetchMeal(id: id)
5056
.receive(on: DispatchQueue.main)
51-
.sink { _ in } receiveValue: { [weak self] meal in
52-
if let recipe = meal?.mapToRecipe() {
53-
self?.likedRecipes.append(recipe)
57+
.sink(
58+
receiveCompletion: { _ in },
59+
receiveValue: { [weak self] meal in
60+
guard let self else { return }
61+
guard let meal else { return }
62+
63+
let recipeRowViewModel = RecipeViewModel(
64+
id: meal.id,
65+
name: meal.name,
66+
thumbnail: meal.thumbnail
67+
)
68+
likedRecipes.append(recipeRowViewModel)
5469
}
55-
}
70+
)
5671
.store(in: &cancellables)
5772
}
5873
}

EatHub/EatHub/Modules/Favorite/Models/RecipeViewModel.swift

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,18 @@ import Foundation
33
class RecipeViewModel: ObservableObject, Identifiable {
44
let id: String
55
@Published var name: String
6-
@Published var imageName: String
7-
@Published var isFavorite: Bool = true
6+
@Published var thumbnail: String?
7+
@Published var isFavorite: Bool
88

9-
init(id: String, name: String, imageName: String) {
9+
init(
10+
id: String,
11+
name: String,
12+
thumbnail: String?,
13+
isFavorite: Bool = true
14+
) {
1015
self.id = id
1116
self.name = name
12-
self.imageName = imageName
17+
self.thumbnail = thumbnail
18+
self.isFavorite = isFavorite
1319
}
1420
}

EatHub/EatHub/Modules/Favorite/RecipeRow.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ struct RecipeRow: View {
1414

1515
var body: some View {
1616
HStack {
17-
if let url = URL(string: recipe.imageName) {
17+
if let url = URL(string: recipe.thumbnail ?? "") {
1818
CachedAsyncImage(url: url) { image in
1919
image
2020
.resizable()

0 commit comments

Comments
 (0)