Skip to content

Instantly share code, notes, and snippets.

@saroar
Created January 26, 2024 15:52
Show Gist options
  • Save saroar/b8fc3a41d09b51e716ffabe0e796990c to your computer and use it in GitHub Desktop.
Save saroar/b8fc3a41d09b51e716ffabe0e796990c to your computer and use it in GitHub Desktop.
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