diff --git a/Giffy/App/Router/Routing.swift b/Giffy/App/Router/Routing.swift index a76c3b8..4fea866 100644 --- a/Giffy/App/Router/Routing.swift +++ b/Giffy/App/Router/Routing.swift @@ -37,12 +37,14 @@ public final class Routing { public func push(_ route: T, animated: Bool = true, needValidate: Bool = false) { guard !(needValidate && routes.last?.key == route.key) else { return } routes.append(route) + print("Routing pushed: \(route)") onPush?(route, animated) } public func present(_ route: T, animated: Bool = true, needValidate: Bool = false) { guard !(needValidate && routes.last?.key == route.key) else { return } routes.append(route) + print("Routing presented: \(route)") onPresent?(route, animated) } @@ -131,7 +133,7 @@ struct NavigationControllerHost: UIViewCont router.onPresent = { route, animated in let viewController = UIHostingController(rootView: routeMap(route)) viewController.modalPresentationStyle = .overFullScreen - navigation.present(viewController, animated: animated) + rootViewController?.present(viewController, animated: animated) } router.onPopLast = { numToPop, animated in @@ -154,6 +156,25 @@ struct NavigationControllerHost: UIViewCont } } } + + private var rootViewController: UIViewController? { + UIApplication.shared.connectedScenes + .compactMap { $0 as? UIWindowScene } + .compactMap { $0.windows.first { $0.isKeyWindow } } + .first?.rootViewController.flatMap(getTopViewController) + } + + private func getTopViewController(from viewController: UIViewController) -> UIViewController { + if let presented = viewController.presentedViewController { + return getTopViewController(from: presented) + } else if let navigation = viewController as? UINavigationController { + return getTopViewController(from: navigation.visibleViewController ?? viewController) + } else if let tabBar = viewController as? UITabBarController { + return getTopViewController(from: tabBar.selectedViewController ?? viewController) + } else { + return viewController + } + } private func setupInitialRoutes(in navigation: PopAwareUINavigationController) { for path in router.currentRoutes { diff --git a/Giffy/Features/Favorite/FavoriteView.swift b/Giffy/Features/Favorite/FavoriteView.swift index 913e933..d4a190b 100644 --- a/Giffy/Features/Favorite/FavoriteView.swift +++ b/Giffy/Features/Favorite/FavoriteView.swift @@ -13,18 +13,20 @@ import CommonUI import ComposableArchitecture struct FavoriteView: View { + @Environment(\.dismiss) var pop let store: StoreOf var body: some View { WithViewStore(store, observe: { $0 }) { viewStore in - NavigationView { + ZStack { ScrollView(.vertical, showsIndicators: false) { SearchField { query in viewStore.send(.fetch(request: query)) } .padding(.horizontal, 16) .padding(.vertical, 20) - + .padding(.top, 62) + if viewStore.state.list.isEmpty { FavoriteEmptyView() .padding(.top, 50) @@ -54,42 +56,60 @@ struct FavoriteView: View { .animation(.easeInOut(duration: 0.2), value: viewStore.list.count) .navigationBarBackButtonHidden(false) .navigationBarTitleDisplayMode(.inline) - .toolbar { - ToolbarItem(placement: .topBarLeading) { - IconButton( - iconName: "chevron.left", - tint: .blue, - onClick: { - viewStore.send(.didBackPressed) - } - ) - } - - ToolbarItem(placement: .principal) { - Text(key: .titleFavorite) - .font(.bold, size: 16) + .showDialog( + shouldDismissOnTapOutside: true, + isShowing: viewStore.binding( + get: { $0.shareImage != nil }, + send: .showShare(nil) + ) + ) { + ShareView(store: viewStore.share) + } + .onAppear { + viewStore.send(.fetch()) + } + .onReceive(viewStore.state.detailDisappear) { _ in + viewStore.send(.fetch()) + } + + VStack { + FavoriteToolbar(title: Localizable.titleFavorite.tr()) { + pop() } + Spacer() } } - .showDialog( - shouldDismissOnTapOutside: true, - isShowing: viewStore.binding( - get: { $0.shareImage != nil }, - send: .showShare(nil) - ) - ) { - ShareView(store: viewStore.share) - } - .onAppear { - viewStore.send(.fetch()) - } - .onReceive(viewStore.state.detailDisappear) { _ in - viewStore.send(.fetch()) - } } } } +struct FavoriteToolbar: View { + var title: String + var onBackPressed: () -> Void + + var body: some View { + HStack { + IconButton( + iconName: "chevron.left", + tint: .Theme.red, + size: 26, + onClick: onBackPressed + ) + + Spacer() + + Text(title) + .font(.system(size: 16, weight: .bold)) + + Spacer() + + Spacer().frame(width: 32) + } + .padding(8) + .background(Blur(style: .prominent).edgesIgnoringSafeArea(.top)) + } +} + #Preview { FavoriteView(store: Injection.resolve()) } diff --git a/Giffy/Features/Home/Button.swift b/Giffy/Features/Home/Button.swift index 8499e2e..74f7be0 100644 --- a/Giffy/Features/Home/Button.swift +++ b/Giffy/Features/Home/Button.swift @@ -36,10 +36,8 @@ struct RedirectButton: View { .foregroundColor(.Theme.yellow) .frame(width: 17, height: 17) .padding(.all, 17) - .background(Color.Theme.background) - .clipShape(.circle) - .contentShape(.circle) - }.buttonStyle(.plain) + .background(Circle().fill(Color.Theme.background)) + } } } @@ -51,18 +49,17 @@ struct FavoriteButton: View { var onClick: () -> Void var body: some View { - Image(systemName: isFavorite ? "heart.fill" : "heart") - .resizable() - .foregroundColor(!isInverted ? Color.Theme.red : Color.white) - .frame(width: size.width - margin, height: size.height - margin - 4) - .background( - (!isInverted ? Color.Theme.background : Color.Theme.red) - .clipShape(Circle()) - .frame(width: size.width, height: size.height) - ) - .onTapGesture { - onClick() - } + Button(action: onClick) { + Image(systemName: isFavorite ? "heart.fill" : "heart") + .resizable() + .foregroundColor(!isInverted ? Color.Theme.red : Color.white) + .frame(width: size.width - margin, height: size.height - margin - 4) + .background( + (!isInverted ? Color.Theme.background : Color.Theme.red) + .clipShape(.circle) + .frame(width: size.width, height: size.height) + ) + } } func frame(width: CGFloat, height: CGFloat) -> Self { diff --git a/Giffy/Features/Home/GiffyRow.swift b/Giffy/Features/Home/GiffyRow.swift index bb8bfd0..902cda0 100644 --- a/Giffy/Features/Home/GiffyRow.swift +++ b/Giffy/Features/Home/GiffyRow.swift @@ -49,7 +49,6 @@ struct GiffyRow: View { FavoriteButton(isFavorite: $isFavorite, size: .init(width: 40, height: 40)) { onFavorite(giphy) } - .tapScaleEffect() .padding(.trailing, 10) } @@ -64,6 +63,7 @@ struct GiffyRow: View { .animation(.linear(duration: 0.2), value: isSelected) } + @ViewBuilder var footer: some View { HStack { if !giphy.title.isEmpty { @@ -84,7 +84,6 @@ struct GiffyRow: View { RedirectButton(onClick: { onTapRow?(giphy) }) - .tapScaleEffect() .showGiffyMenu( URL(string: giphy.url), data: downloadedImage, diff --git a/Giffy/Features/Home/HomeView.swift b/Giffy/Features/Home/HomeView.swift index 517b953..26d662e 100644 --- a/Giffy/Features/Home/HomeView.swift +++ b/Giffy/Features/Home/HomeView.swift @@ -78,7 +78,7 @@ struct HomeView: View { ) { ShareView(store: viewStore.share) } - .onChange(of: viewStore.shareImage) { image, _ in + .onChange(of: viewStore.shareImage) { _, image in tabState.isShowShare = image != nil } .onAppear { diff --git a/Giffy/Features/Search/SearchView.swift b/Giffy/Features/Search/SearchView.swift index 34c30f2..27a8f11 100644 --- a/Giffy/Features/Search/SearchView.swift +++ b/Giffy/Features/Search/SearchView.swift @@ -84,7 +84,7 @@ struct SearchView: View { ) { ShareView(store: viewStore.share) } - .onChange(of: viewStore.shareImage) { image, _ in + .onChange(of: viewStore.shareImage) { _, image in tabState.isShowShare = image != nil } .onAppear { diff --git a/Giffy/Features/Sticker/StickerView.swift b/Giffy/Features/Sticker/StickerView.swift index 7e703b5..a7732b7 100644 --- a/Giffy/Features/Sticker/StickerView.swift +++ b/Giffy/Features/Sticker/StickerView.swift @@ -69,8 +69,8 @@ struct StickerView: View { ) { ShareView(store: viewStore.state.share) } - .onChange(of: viewStore.isCopied) { _, _ in - tabState.isShowShare = viewStore.isCopied + .onChange(of: viewStore.isCopied) { _, state in + tabState.isShowShare = state } .navigationBarTitleDisplayMode(.inline) .toolbar { diff --git a/Modules/CommonUI/CommonUI/Sources/CommonUI/Assets/en.lproj/Localizable.strings b/Modules/CommonUI/CommonUI/Sources/CommonUI/Assets/en.lproj/Localizable.strings index a6f5a00..144e3c5 100644 --- a/Modules/CommonUI/CommonUI/Sources/CommonUI/Assets/en.lproj/Localizable.strings +++ b/Modules/CommonUI/CommonUI/Sources/CommonUI/Assets/en.lproj/Localizable.strings @@ -7,7 +7,7 @@ */ "profile" = "Profile"; "search" = "Discover GIFs!"; -"favorite" = "Favorite"; +"favorite" = "Favorites"; "trending" = "Trending"; "detail" = "Detail"; "today_popular" = "Today's Trending";