Hey my cards are sticking to the left for some reason. How can I fix this?
![Example of issue](https://user-images.githubusercontent.com/81453549/157522562-05b884dd-35d2-4739-9498-bea0c3fd3d17.png)
struct RestCardView: View {
let restaurants: Restaurants
@Environment(\.colorScheme) var colorScheme
var body: some View {
GeometryReader { geo in
let card = (
VStack {
if #available(iOS 15, *) {
AsyncImage(url: restaurants.imageUrl) { image in
imag
![Simulator Screen Shot - iPhone 13 - 2022-03-09 at 11 48 24](https://user-images.githubusercontent.com/81453549/157522210-0892cbd6-6cc7-4d9f-9889-9a3ffdfe2ffe.png)
e
.resizable()
.frame(idealWidth: geo.size.width, idealHeight: geo.size.height)//, maxHeight: 10)
.aspectRatio(contentMode: .fit)
} placeholder: {
Image(systemName: "photo")
.res
![Simulator Screen Shot - iPhone 13 - 2022-03-09 at 11 48 24](https://user-images.githubusercontent.com/81453549/157522269-6dee8139-720b-4384-9424-9105e3c5accb.png)
izable()
// .frame(height: geo.size.width)
.aspectRatio(contentMode: .fit)
.imageScale(.large)
.foregroundColor(.gray)
}
.ignoresSafeArea()
// switch image {
// case .empty:
// Image(named: "No Image")
// .resizable()
// .aspectRatio(contentMode: .fit)
// .frame(height: geo.size.width)
// .clipped()
// case .success(let image):
// image
// .resizable()
// .aspectRatio(contentMode: .fit)
// .frame(height: geo.size.width)
// .clipped()
// case .failure:
// Image(named: "No Image")
// .resizable()
// .aspectRatio(contentMode: .fit)
// .frame(height: geo.size.width)
// .clipped()
// @unknown default:
// // Since the AsyncImagePhase enum isn't frozen,
// // we need to add this currently unused fallback
// // to handle any new cases that might be added
// // in the future:
// Image(named: "No Image")
// .resizable()
// .aspectRatio(contentMode: .fit)
// .frame(height: geo.size.width)
// .clipped()
// }
// }
}else {
URLImage(restaurants.imageUrl) { image in
image
.resizable()
.aspectRatio(contentMode: .fit)
.frame(idealHeight: geo.size.width)//, maxHeight: 50)
.clipped()
}
}
HStack{
Text(restaurants.name)
if restaurants.price != "Unknown" {
Text(restaurants.price)
}
}
.padding(.bottom)
if restaurants.category != [] {
Text("\(restaurants.category.joined(separator: ", "))")
.padding(.horizontal)
}
// if !restaurants.isClosed {
// Text("Open")
// .foregroundColor(Color.green)
// }else {
// Text("Closed")
// .foregroundColor(Color.red)
// }
Button(action: {
print("opening site pressed")
if let url = URL(string: restaurants.url) {
UIApplication.shared.open(url)
}
}) {
HStack {
RestaurantReviews(reviews: restaurants.rating, forgroundColor: .yelpDefault, yelpIconSelectedSize: .large)
Text("\(restaurants.reviewCount)")
.foregroundColor(.primary)
.padding(.trailing)
Text("More Info")
Image("yelp logo")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(maxWidth: 30)
}
}
.padding(.horizontal)
Button(action: {
print("opening location pressed")
Utilities.encodeForGoogleMaps(url: restaurants.name) { loc in
print("loc = \(loc)")
if let url = URL(string: "https://www.google.com/maps/search/?api=1&query=\(loc)") {
UIApplication.shared.open(url)
}
}
}, label: {
Text(restaurants.location)
})
.padding(.bottom)
})
if colorScheme == .dark {
card
// .opacity(0.2)
.background(Color(red: 0.15, green: 0.15, blue: 0.15))
.cornerRadius(12)
.shadow(radius: 4)
}else {//if colorScheme == .light {
card
.background(Color.white)
.cornerRadius(12)
.shadow(radius: 4)
}
}
}
}
struct MediaCardView: View {
let media: Media
@Environment(\.colorScheme) var colorScheme
var body: some View {
GeometryReader { geo in
let card = (
VStack {
if #available(iOS 15, *) {
AsyncImage(url: media.imageUrl) { image in
image
.resizable()
.frame(idealWidth: geo.size.width, idealHeight: geo.size.height)//, maxHeight: 10)
.aspectRatio(contentMode: .fit)
} placeholder: {
Image(systemName: "photo")
.resizable()
// .frame(height: geo.size.width)
.aspectRatio(contentMode: .fit)
.imageScale(.large)
.foregroundColor(.gray)
}
.ignoresSafeArea()
// switch image {
// case .empty:
// Image(named: "No Image")
// .resizable()
// .aspectRatio(contentMode: .fit)
// .frame(height: geo.size.width)
// .clipped()
// case .success(let image):
// image
// .resizable()
// .aspectRatio(contentMode: .fit)
// .frame(height: geo.size.width)
// .clipped()
// case .failure:
// Image(named: "No Image")
// .resizable()
// .aspectRatio(contentMode: .fit)
// .frame(height: geo.size.width)
// .clipped()
// @unknown default:
// // Since the AsyncImagePhase enum isn't frozen,
// // we need to add this currently unused fallback
// // to handle any new cases that might be added
// // in the future:
// Image(named: "No Image")
// .resizable()
// .aspectRatio(contentMode: .fit)
// .frame(height: geo.size.width)
// .clipped()
// }
// }
}else {
URLImage(media.imageUrl) { image in
image
.resizable()
.aspectRatio(contentMode: .fit)
.frame(idealHeight: geo.size.width)//, maxHeight: 50)
.clipped()
}
}
HStack{
Text(media.name)
}
// .padding(.bottom)
let rating = "Avg. Rating: \(media.rating.rounded())/10 from \(media.ratingCount) reviews"
Text(rating)
.padding(.bottom)
Text(media.description)
.padding(.horizontal)
}
.padding(.bottom))
.onAppear {
print("Avg. Rating: \(media.rating)/10 from \(media.ratingCount) reviews")
}
if colorScheme == .dark {
card
// .opacity(0.2)
.background(Color(red: 0.15, green: 0.15, blue: 0.15))
.cornerRadius(12)
.shadow(radius: 4)
}else {//if colorScheme == .light {
card
.background(Color.white)
.cornerRadius(12)
.shadow(radius: 4)
}
}
}
}
struct CardViewWithThumbs: View {
let restaurants: Restaurants
let media: Media
let direction: LeftRight?
static var yes = Array<Any>()
var body: some View {
ZStack(alignment: .topTrailing) {
ZStack(alignment: .topLeading) {
if Utilities.picktType == .media {
MediaCardView(media: media)
.accessibilityIdentifier("Card")
}else {
RestCardView(restaurants: restaurants)
.accessibilityIdentifier("Card")
}
Image(systemName: "hand.thumbsup.fill")
.resizable()
.foregroundColor(Color.green)
.opacity(direction == .right ? 1 : 0)
.frame(width: 100, height: 100)
.padding()
}
Image(systemName: "hand.thumbsdown.fill")
.resizable()
.foregroundColor(Color.red)
.opacity(direction == .left ? 1 : 0)
.frame(width: 100, height: 100)
.padding()
}
.animation(.default)
}
}
struct Thumbs: View {
...
func showFinalRestView() {
db.collection("parties").document(Utilities.code).addSnapshotListener { doc, error in
print("Start data fetch...")
if error == nil {
print("error = nil")
if doc != nil && doc!.exists {
print("Doc Exists")
if let num = doc!.get("devicesNum") as? Int {
devicesNum = num
if let dev = doc!.get("devices") as? Array<String> {
devices = dev
print("devices = \(dev)")
for name in dev {
print("DeviceList = \(Devices.list)")
if !Devices.list.contains(Devices(id: name, name: name)) {
print("DeviceList Contains = \(name)")
Devices.list.append(Devices(id: name, name: name))
}
}
if let done = doc!.get("devicesDone") as? Array<String> {
print("devicesDone = \(done), devices = \(devices)")
devicesDone = done
if done.sorted() == dev.sorted() && done.count == num {
if var topController = UIApplication.shared.windows.first!.rootViewController {
while let presentedViewController = topController.presentedViewController {
topController = presentedViewController
}
self.fullScreenAd.showAd(root: topController, then: {
// print("fetch data")
// viewModels.fetchData {
// viewModels.fetchData { //yesRestaurant, AllRestaurants, yesMedia, allMedia, devices, devicesDone in
// vmRestAll = AllRestaurants
// vmRestYes = yesRestaurant
// vmDevices = devices
// vmMediaAll = allMedia
// vmMediaYes = yesMedia
print("show final view")
// fullScreenAd.showAd {
Utilities.showFinal = true
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) {
self.presentation.wrappedValue.dismiss()
results = false
topPick = false
}
print("yesRestaurants from restPicker = \(viewModels.yesRestaurants), allRestaurants = \(viewModels.allRestaurants)")
print("done from completion handler")
// }
// }
})
}
}
}else {
print("error: \(error)")
}
}else {
print("error: \(error)")
}
}else {
print("error: \(error)")
}
}
}
}
}
func showfinalview() {
print("show final view, yes.restlist = \(yes.restList), yes.medialist = \(yes.mediaList)")
results = true
topPick = true
}
func addRestData(card: Restaurants, direction: LeftRight) {
if NetworkMonitor.shared.isConnected {
if direction == .right {
itemCount += 1
print("Code = \(Utilities.code)")
print("Name = \(Utilities.name)")
yes.restList.append(Restaurants(name: card.name, imageUrl: card.imageUrl, id: card.id, rating: card.rating, url: card.url, location: card.location, category: card.category, tag: [], isClosed: card.isClosed, price: card.price, reviewCount: card.reviewCount))
print("yes, list = \(yes.restList)")
}else {
print("no")
itemNo += 1
no.restList.append(Restaurants(name: card.name, imageUrl: card.imageUrl, id: card.id, rating: card.rating, url: card.url, location: card.location, category: card.category, tag: [], isClosed: card.isClosed, price: card.price, reviewCount: card.reviewCount))
}
if card.name == restData.last?.name {
showfinalview()
// showFinal = true
}
}else {
disabledAlert = true
}
}
...
var body: some View {
GeometryReader { geo in
// NavigationView {
VStack(alignment: .center) {
Text(" ")
.padding(.bottom)
HStack {
Text("Party Code: \(Utilities.code)")
.padding(.trailing)
if Utilities.joinDisabled == false {
Button(action: {
copy = true
switch Utilities.shareMode {
case .sheet:
// shareSheet.toggle()
Utilities.presentShareSheet(activityItems: ["pickt://join/\(Utilities.code)"])
// let activityVC = UIActivityViewController(activityItems: ["pickt://join/\(Utilities.code)"], applicationActivities: nil)
// UIApplication.shared.windows.first?.rootViewController?.present(activityVC, animated: true, completion: nil)
case .clipboard:
let pasteboard = UIPasteboard.general
pasteboard.string = "pickt://join/\(Utilities.code)"
}
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
copy = false
}
}, label: {
if !copy {
Group {
switch Utilities.shareMode {
case .sheet:
Image(systemName: "square.and.arrow.up")
case .clipboard:
Image(systemName: "doc.on.clipboard")
}
}
}else {
Image(systemName: "checkmark")
}
})
.foregroundColor(.primary)
.frame(width: 35, height: 35)
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(Color.primary, lineWidth: 1)
)
}
}
.padding(.top)
// Button("Stop Searching") {
// if yes.list.count > 0 {
// showfinalview()
// }
// }
if restData == [] && Utilities.picktType == .restaurants {
Text("No Results Found For Query Terms:\n\nLocation: \(Utilities.location),\nRestaurant Filter: \(Utilities.restFilter),\nCuisine: \(Utilities.cuisine)")
.multilineTextAlignment(.center)
.padding(.top)
}else {
Group {
if Utilities.picktType == .media {
if Utilities.mediaType == .TVShows {
Text("Searching for TV Shows")
// Text("Everyone is seeing the same tv cards, please swipe right for yes and left for no.")
}else if Utilities.mediaType == .Movies {
Text("Searching for Movies")
// Text("Everyone is seeing the same movie cards, please swipe right for yes and left for no.")
}
}else {
Text("Searching \(Utilities.location) with \(Utilities.restFilter), \(Utilities.cuisine)")
// .padding(.horizontal)
// Text("Everyone is seeing the same restaurant cards, please swipe right for yes and left for no.")
}
}
.padding()
.accessibility(identifier: "Searching")
.onTapGesture {
if UserDefaults.standard.bool(forKey: "FASTLANE_SNAPSHOT") {
for item in Restaurants.viewModels {
yes.restList.append(item)
}
self.showfinalview()
}
}
HStack {
Button(action: {
var mediaList = Array<Media>()
var restList = Array<Restaurants>()
for item in no.mediaList {
if !mediaList.contains(item) {
mediaList.append(item)
}
}
for item in no.restList {
if !restList.contains(item) {
restList.append(item)
}
}
no.mediaList = mediaList
no.restList = restList
noList = true
}, label: {
Image(systemName: "hand.thumbsdown")
Text("\(itemNo)")
})
.accessibility(identifier: "No List")
.foregroundColor(.red)
Spacer()
.frame(width: 40)
Button(action: {
var mediaList = Array<Media>()
var restList = Array<Restaurants>()
for item in yes.mediaList {
if !mediaList.contains(item) {
mediaList.append(item)
}
}
for item in yes.restList {
if !restList.contains(item) {
restList.append(item)
}
}
yes.mediaList = mediaList
yes.restList = restList
yesList = true
}, label: {
Image(systemName: "hand.thumbsup")
Text("\(itemCount)")
})
.accessibility(identifier: "Yes List")
.foregroundColor(.green)
}
.padding()
}
if results {
Group {
Text("\(waitingPhrases.randomElement()!)")
// VStack {
// Text("People Who Have Finished:\n")
// ForEach(devicesDone.indices) {
// Text(self.devicesDone[$0])
// }
// }
// .padding()
Button("Override, Show Results") {
overrideResults = true
}
Button {
topPick = true
} label: {
HStack {
Image(systemName: "filemenu.and.selection")
if pick != "None" {
Text("Change your top pick")
}else {
Text("Choose your top pick")
}
}
}
}
.padding()
}
if !results && restData != [] && restData != [Restaurants(name: "nil", imageUrl: URL(string: Utilities.noImage)!, id: "abcdef", rating: 0, url: "https://google.com", location: "nil", category: ["nil"], tag: [], isClosed: false, price: "Unknown", reviewCount: 0)] && Utilities.picktType == .restaurants {
ZStack(alignment: Alignment(horizontal: .center, vertical: .center), content: {
CardStack(
direction: LeftRight.direction,
data: restData,
onSwipe: { card, direction in
print("Swiped \(card.name) to \(direction)")
addRestData(card: card, direction: direction)
},
content: { restaurants, direction, _ in
CardViewWithThumbs(restaurants: restaurants, media: Media(name: "nil", imageUrl: URL(string: Utilities.noImage)!, id: "abcde", description: "abcde", ratingCount: 1, rating: 8, tag: []), direction: direction)
}
)
.padding()
.scaledToFit()
.frame(alignment: .center)
// .frame(maxWidth: screen.width)
.environment(\.cardStackConfiguration, CardStackConfiguration(
maxVisibleCards: 3
// swipeThreshold: 0.1,
// cardOffset: 10,
// cardScale: 0.2,
// animation: .linear
))
})
}else if Utilities.picktType == .media && mediaData != [] {
ZStack(alignment: Alignment(horizontal: .center, vertical: .center), content: {
CardStack(
direction: LeftRight.direction,
data: mediaData,
onSwipe: { card, direction in
print("Swiped \(card.name) to \(direction)")
addMediaData(card: card, direction: direction)
if card.name == mediaData.last?.name {
showfinalview()
// showFinal = true
}
},
content: { media, direction, _ in
CardViewWithThumbs(restaurants: Restaurants(name: "nil", imageUrl: URL(string: Utilities.noImage)!, id: "abcdef", rating: 0, url: "https://google.com", location: "nil", category: ["nil"], tag: [], isClosed: false, price: "Unknown", reviewCount: 0), media: media, direction: direction)
}
)
.padding(.all)
// .frame(height: screen.height)
// .frame(minHeight: 0, idealHeight: screen.height, maxHeight: 450, alignment: .center)
.scaledToFit()
.frame(maxWidth: 700, maxHeight: 800)
// .frame(maxWidth: screen.width)
.environment(\.cardStackConfiguration, CardStackConfiguration(
maxVisibleCards: 3
// swipeThreshold: 0.1,
// cardOffset: 10,
// cardScale: 0.2,
// animation: .linear
))
})
}
}
...
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
}