Created
January 26, 2024 15:52
-
-
Save saroar/b8fc3a41d09b51e716ffabe0e796990c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import ComposableArchitecture | |
import LPGSharedModels | |
import BSON | |
import ComposableCoreLocation | |
import LocationReducer | |
import UserDefaultsClient | |
import SwiftUI | |
import NukeUI | |
public struct SwapReducer: Reducer { | |
public struct State: Equatable, Identifiable { | |
public init(swap: SwapOutput) { | |
self.swap = swap | |
} | |
public var id: ObjectId { swap.id } | |
public var swap: SwapOutput | |
fileprivate var images: [URL] = [] | |
fileprivate var selectedImageUrl: URL? = nil | |
} | |
public enum Action: Equatable { | |
case onAppear | |
case updateImage(image: URL) | |
case moveToDetailsView | |
} | |
public init() {} | |
public var body: some Reducer<State, Action> { | |
Reduce(self.core) | |
} | |
func core(state: inout State, action: Action) -> Effect<Action> { | |
switch action { | |
case .onAppear: | |
guard | |
let firstAttachment = state.swap.attachments.first, | |
let imageUrl = firstAttachment.imageUrlString, | |
let url = URL(string: imageUrl) | |
else { | |
return .none | |
} | |
state.selectedImageUrl = url | |
for attachment in state.swap.attachments { | |
guard | |
let iurl = attachment.imageUrlString, | |
let url = URL(string: iurl) | |
else { continue } | |
state.images.append(url) | |
} | |
return .none | |
case .updateImage(image: let url): | |
state.selectedImageUrl = url | |
return .none | |
case .moveToDetailsView: | |
return .none | |
} | |
} | |
} | |
public struct SwapView: View { | |
private var gridLayout = [ GridItem() ] | |
private var threeColumnGrid = [GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible())] | |
let store: StoreOf<SwapReducer> | |
public init(store: StoreOf<SwapReducer>) { | |
self.store = store | |
} | |
public var body: some View { | |
WithViewStore(self.store, observe: { $0 }) { viewStore in | |
VStack { | |
HStack { | |
// Image | |
LazyImage(request: ImageRequest(url: viewStore.swap.owner.imageURL)) { state in | |
if let image = state.image { | |
image | |
.resizable() | |
.scaledToFill() | |
.frame(width: 50, height: 80) | |
.clipShape(RoundedRectangle(cornerRadius: 3.0, style: .continuous)) | |
.padding([.top, .trailing, .bottom], 5) | |
} else { | |
Color.blue | |
.scaledToFill() | |
.frame(width: 50, height: 80) | |
.clipShape(RoundedRectangle(cornerRadius: 3.0, style: .continuous)) | |
.padding([.top, .trailing, .bottom], 5) | |
} | |
} | |
// Text VStack | |
VStack(alignment: .leading) { | |
VStack(alignment: .leading) { | |
Text("\(viewStore.swap.owner.fullName!)") | |
.font(.customTitle2) | |
.fontWeight(.medium) | |
.foregroundColor(.nevyDarkLPG) | |
Text("Created by \(Date().formatted(.dateTime.day().month().hour()))") | |
.font(.customSubheadline) | |
.fontWeight(.light) | |
.foregroundColor(.nevyDarkLPG) | |
} | |
.padding(.vertical, 2) | |
Text("\(viewStore.swap.title)") | |
.lineLimit(2) | |
.font(.customTitle2) | |
.fontWeight(.semibold) | |
.foregroundColor(.nevyDarkLPG) | |
} | |
.frame(height: 80) | |
.padding(.vertical) | |
Spacer() | |
} | |
.frame(height: 80) // Set a preferred height for the entire HStack content | |
.shadow(color: Color.black.opacity(0.3), radius: 9, x: 0, y: 5) | |
.padding(.bottom, 30) | |
Button(action: { | |
viewStore.send(.moveToDetailsView) | |
}) { | |
LazyImage(request: ImageRequest(url: viewStore.selectedImageUrl)) { state in | |
if let image = state.image { | |
image | |
.resizable() | |
.scaledToFill() | |
.frame(minWidth: 0, maxWidth: .infinity) | |
.frame(maxHeight: 250) | |
.cornerRadius(10) | |
.shadow(color: Color.primary.opacity(0.3), radius: 1) | |
.shadow(color: Color.black.opacity(0.6), radius: 8, x: 0, y: 5) | |
.padding(.bottom, 5) | |
} else if state.error != nil { | |
Color.blue | |
.frame(minWidth: 0, maxWidth: .infinity) | |
.frame(minHeight: 250 ,maxHeight: 250) | |
.cornerRadius(10) | |
.shadow(color: Color.primary.opacity(0.3), radius: 1) | |
.shadow(color: Color.black.opacity(0.6), radius: 8, x: 0, y: 5) | |
.padding(.bottom, 5) | |
} else { | |
Color.blue | |
.frame(minWidth: 0, maxWidth: .infinity) | |
.frame(minHeight: 250 ,maxHeight: 250) | |
.cornerRadius(10) | |
.shadow(color: Color.primary.opacity(0.3), radius: 1) | |
.shadow(color: Color.black.opacity(0.6), radius: 8, x: 0, y: 5) | |
.padding(.bottom, 5) | |
} | |
} | |
} | |
LazyVGrid(columns: [GridItem(.adaptive(minimum: 50))]) { | |
ForEach(viewStore.images, id: \.self) { url in | |
Button(action: { | |
viewStore.send(.updateImage(image: url)) | |
}) { | |
LazyImage(request: ImageRequest(url: url)) { state in | |
if let image = state.image { | |
image | |
.resizable() | |
.scaledToFill() | |
.frame(minWidth: 0, maxWidth: .infinity) | |
.frame(height: 50) | |
.cornerRadius(10) | |
} else { | |
Color.blue | |
.scaledToFill() | |
.frame(minWidth: 0, maxWidth: .infinity) | |
.frame(height: 50) | |
.cornerRadius(10) | |
} | |
} | |
} | |
} | |
} | |
.frame(minHeight: 0, maxHeight: .infinity, alignment: .top) | |
} | |
.onAppear { | |
viewStore.send(.onAppear) | |
} | |
.padding(.horizontal) | |
} | |
} | |
} | |
#if DEBUG | |
struct SwapView_Previews: PreviewProvider { | |
static var previews: some View { | |
SwapView( | |
store: .init( | |
initialState: SwapReducer.State( | |
swap: .init( | |
id: .init(), | |
title: "Car and Dolls Car and Dolls Car and Dolls Car and DollsCar and DollsCar and Dolls", | |
details: "awesome car", | |
distance: 0.9, | |
addressName: "some address goes here", | |
geometry: .near, | |
sponsored: true, | |
overlay: false, | |
owner: .withAttachments, | |
conversationId: .init(), | |
categoryId: .init(), | |
attachments: [.image1, .image2, .image3, .image4], | |
urlString: "", | |
createdAt: .now, | |
updatedAt: .now | |
) | |
) | |
) { | |
SwapReducer() | |
} | |
) | |
} | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment