diff --git a/Balance/Distraction/Drawing/DrawView.swift b/Balance/Distraction/Drawing/DrawView.swift index 2392f04..963695b 100644 --- a/Balance/Distraction/Drawing/DrawView.swift +++ b/Balance/Distraction/Drawing/DrawView.swift @@ -15,7 +15,8 @@ struct DrawingView: UIViewRepresentable { @Binding var isdraw: Bool @Binding var type: PKInkingTool.InkType @Binding var color: Color - + @Binding var isColoring: Bool + // Updating inktype var ink: PKInkingTool { PKInkingTool(type, color: UIColor(color)) @@ -26,8 +27,16 @@ struct DrawingView: UIViewRepresentable { func makeUIView(context: Context) -> PKCanvasView { canvas.drawingPolicy = .anyInput canvas.tool = isdraw ? ink : eraser - canvas.minimumZoomScale = 1 - canvas.maximumZoomScale = 1 + if isColoring == false { + canvas.minimumZoomScale = 0.2 + canvas.maximumZoomScale = 4 + canvas.contentSize = CGSize(width: 1000, height: 1000) + canvas.contentInset = UIEdgeInsets(top: 500, left: 500, bottom: 500, right: 500) + } else { + canvas.minimumZoomScale = 1 + canvas.maximumZoomScale = 1 + } + return canvas } @@ -54,7 +63,6 @@ struct DrawView: View { @State private var title = "" @State private var showingAlert = false @State var drawingSize = CGSize(width: 350, height: 350) -// @State var backgroundImage = "" @State var isNewDraw = false @State var isColoring = false @@ -67,7 +75,7 @@ struct DrawView: View { Spacer().frame(height: 20) toolkitView Spacer() - DrawingView(canvas: $canvas, isdraw: $isdraw, type: $type, color: $color) + DrawingView(canvas: $canvas, isdraw: $isdraw, type: $type, color: $color, isColoring: $isColoring) .frame(width: drawingSize.width, height: drawingSize.height) .border(Color.gray, width: 5) Spacer() diff --git a/Balance/Distraction/Gallery/LookImages/GalleryView.swift b/Balance/Distraction/Gallery/LookImages/GalleryView.swift index e52dd0b..0e578c4 100644 --- a/Balance/Distraction/Gallery/LookImages/GalleryView.swift +++ b/Balance/Distraction/Gallery/LookImages/GalleryView.swift @@ -11,6 +11,7 @@ struct ImageTagView: View { var selectedCategory: Category @Binding var selectedBtn: Int @Binding var filteredCat: [Photo] + @Binding var selectedCat: Category @Binding var isUpload: Bool @Binding var profile: ProfileUser @@ -19,6 +20,7 @@ struct ImageTagView: View { self.isUpload = false self.selectedBtn = self.selectedCategory.id filteredCat.removeAll() + self.selectedCat = self.selectedCategory if self.selectedCategory.name == "Favorites" { filteredCat = UserImageCache.load(key: self.profile.id.appending("FavoritesArray")) } else if self.selectedCategory.name == "Removed" { @@ -27,9 +29,20 @@ struct ImageTagView: View { filteredCat = UserImageCache.load(key: self.profile.id.appending("UploadedArray")) self.isUpload = true } else { + if self.selectedCategory.name == "All" { + filteredCat = UserImageCache.load(key: self.profile.id.appending("UploadedArray")) + } + let removedElements = UserImageCache.load(key: self.profile.id.appending("RemovedArray")) + var isRemoved = false for photo in photoArray { for category in photo.category where category.name == self.selectedCategory.name { - filteredCat.append(photo) + for removedPhoto in removedElements where removedPhoto.name == photo.name { + isRemoved = true + } + if !isRemoved { + filteredCat.append(photo) + } + isRemoved = false } } } @@ -50,12 +63,12 @@ struct ImageTagView: View { struct GalleryView: View { @State var index = 0 @State var selectedCategory = imageCategoryArray[0] - @State var filtered = photoArray + @State var filtered = [Photo]() @State var selected = 0 @State var isUpload = false @State var profile = ProfileUser() let highlightArray = photoArray.filter { $0.highlight == true } - + var body: some View { ActivityLogContainer { ZStack { @@ -79,6 +92,7 @@ struct GalleryView: View { } }.onAppear { loadUser() + loadData() } } } @@ -95,7 +109,12 @@ struct GalleryView: View { viewName: "Image Highlight Selected: " + img.name, isDirectChildToContainer: true, content: { - ImageView(imagesArray: highlightArray, currentIndex: index, selected: highlightArray[index]) + ImageView( + imagesArray: highlightArray, + currentIndex: index, + selected: highlightArray[index], + selectedCategory: selectedCategory + ) } ) ) { @@ -135,13 +154,14 @@ struct GalleryView: View { selectedCategory: cat, selectedBtn: self.$selected, filteredCat: self.$filtered, + selectedCat: self.$selectedCategory, isUpload: self.$isUpload, profile: self.$profile ) } } } - ImageCollectionView(imageArray: filtered).padding(.horizontal, 10.0) + ImageCollectionView(imageArray: filtered, category: selectedCategory).padding(.horizontal, 10.0) } } @@ -155,6 +175,35 @@ struct GalleryView: View { } } } + + func loadData() { + filtered.removeAll() + if selectedCategory.name == "All" { + filtered = UserImageCache.load(key: self.profile.id.appending("UploadedArray")) + } + if self.selectedCategory.name == "Favorites" { + filtered = UserImageCache.load(key: self.profile.id.appending("FavoritesArray")) + } else if self.selectedCategory.name == "Removed" { + filtered = UserImageCache.load(key: self.profile.id.appending("RemovedArray")) + } else if self.selectedCategory.name == "Uploaded" { + filtered = UserImageCache.load(key: self.profile.id.appending("UploadedArray")) + } else { + let removedElements = UserImageCache.load(key: self.profile.id.appending("RemovedArray")) + var isRemoved = false + for photo in photoArray { + for category in photo.category where category.name == self.selectedCategory.name { + for removedPhoto in removedElements where removedPhoto.name == photo.name { + isRemoved = true + } + if !isRemoved { + filtered.append(photo) + } + isRemoved = false + } + } +// filtered.append(contentsOf: photoArray) + } + } } #if DEBUG diff --git a/Balance/Distraction/Gallery/LookImages/ImageCollectionView.swift b/Balance/Distraction/Gallery/LookImages/ImageCollectionView.swift index 600bd50..951d941 100644 --- a/Balance/Distraction/Gallery/LookImages/ImageCollectionView.swift +++ b/Balance/Distraction/Gallery/LookImages/ImageCollectionView.swift @@ -9,6 +9,7 @@ import SwiftUI struct ImageCollectionView: View { var images = [Photo]() + var category: Category var gridItemLayout = [GridItem(.fixed(110)), GridItem(.fixed(110)), GridItem(.fixed(110))] var body: some View { @@ -20,7 +21,7 @@ struct ImageCollectionView: View { viewName: "Image Selected: " + images[index].name, isDirectChildToContainer: true, content: { - ImageView(imagesArray: images, currentIndex: index, selected: images[index]) + ImageView(imagesArray: images, currentIndex: index, selected: images[index], selectedCategory: category) } ) ) { @@ -51,13 +52,14 @@ struct ImageCollectionView: View { } } - init(imageArray: [Photo]) { + init(imageArray: [Photo], category: Category) { self.images = imageArray + self.category = category } } struct ImageCollectionView_Previews: PreviewProvider { static var previews: some View { - ImageCollectionView(imageArray: (1...8).map { Photo(category: [Category(id: 5, name: "Landscape")], name: "img\($0)") }) + ImageCollectionView(imageArray: (1...8).map { Photo(category: [Category(id: 5, name: "Landscape")], name: "img\($0)") }, category: Category(id: 0, name: "Removed")) } } diff --git a/Balance/Distraction/Gallery/LookImages/ImageView.swift b/Balance/Distraction/Gallery/LookImages/ImageView.swift index 969c0a6..1ee877c 100644 --- a/Balance/Distraction/Gallery/LookImages/ImageView.swift +++ b/Balance/Distraction/Gallery/LookImages/ImageView.swift @@ -7,6 +7,28 @@ import SwiftUI +struct HUD: View { + @ViewBuilder let content: Content + + var body: some View { + content + .padding(.horizontal, 12) + .padding(16) + .background( + Capsule() + .foregroundColor(Color.white) + .shadow(color: Color(.black).opacity(0.16), radius: 12, x: 0, y: 5) + ) + } +} + +struct ScaleButtonStyle: ButtonStyle { + func makeBody(configuration: Self.Configuration) -> some View { + configuration.label + .scaleEffect(configuration.isPressed ? 1.4 : 1) + } +} + struct ImageView: View { @Environment(\.dismiss) var dismiss var imagesArray: [Photo] @@ -14,7 +36,12 @@ struct ImageView: View { @State var selected: Photo @State var profile = ProfileUser() @State var savedArray = [Photo]() - + @State private var scaleValue = CGFloat(1) + @State private var showingHUD = false + @State private var strMsg = "" + @State private var imgMsg = "" + @State var selectedCategory: Category + var body: some View { ActivityLogContainer { ZStack { @@ -22,38 +49,94 @@ struct ImageView: View { VStack { HeaderMenu(title: "Distraction") Spacer() - TabView(selection: $selected) { - ForEach(self.imagesArray) { img in - CardImageView(image: img.name, imageData: img.imageData) - .tag(img) - } - } - .tabViewStyle(.page(indexDisplayMode: .never)) - .onAppear(perform: { - self.selected = self.imagesArray[currentIndex] - }) + tabImages + .tabViewStyle(.page(indexDisplayMode: .never)) + .onAppear(perform: { + self.selected = self.imagesArray[currentIndex] + }) Spacer() actionsButtons Spacer() } + if showingHUD { + HUD { + Label(strMsg, systemImage: imgMsg) + } + .transition(AnyTransition.move(edge: .top).combined(with: .opacity)) + .onAppear { + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + withAnimation { + showingHUD = false + } + } + } + .zIndex(1) + } }.onAppear { loadUser() } } } + var tabImages: some View { + TabView(selection: $selected) { + ForEach(self.imagesArray) { img in + CardImageView(image: img.name, imageData: img.imageData) + .tag(img) + } + } + } + var actionsButtons: some View { HStack(spacing: 50) { - dislikeAction - likeAction + if selectedCategory.name == "Removed" { + returnAction + } else if selectedCategory.name == "Favorites" { + unLikeAction + } else if selectedCategory.name == "Uploaded" { + deleteAction + likeAction + } else { + dislikeAction + likeAction + } } } + var deleteAction: some View { + Button(action: { + print("DELETE tab = \(selected.name)") + showingHUD.toggle() + self.strMsg = "Deleted!" + self.imgMsg = "trash.fill" + savedArray = UserImageCache.load(key: self.profile.id.appending("UploadedArray")) + let result = savedArray.filter { $0.name != selected.name } + UserImageCache.save(result, key: self.profile.id.appending("UploadedArray")) + }) { + Image(systemName: "trash.fill") + .resizable() + .frame(width: 30, height: 30) + .foregroundColor(primaryColor) + .padding(10) + .background(Color.white) + .clipShape(Circle()) + .shadow(color: Color.black.opacity(0.50), radius: 3, x: 0, y: 2) + .accessibilityLabel("trash.fill") + .scaleEffect(scaleValue) + .tint(primaryColor) + } + .buttonStyle(ScaleButtonStyle()) + .buttonStyle(ActivityLogButtonStyle(activityDescription: "IMAGE REVIEW: " + selected.name + " status: DELETE")) + } + var dislikeAction: some View { Button(action: { print("DISLIKE tab = \(selected.name)") + showingHUD.toggle() + self.strMsg = "Removed!" + self.imgMsg = "xmark.circle.fill" savedArray = UserImageCache.load(key: self.profile.id.appending("RemovedArray")) - let result = savedArray.filter { $0.id == selected.id } + let result = savedArray.filter { $0.name == selected.name } if result.isEmpty { savedArray.append(selected) UserImageCache.save(savedArray, key: self.profile.id.appending("RemovedArray")) @@ -68,14 +151,20 @@ struct ImageView: View { .clipShape(Circle()) .shadow(color: Color.black.opacity(0.50), radius: 3, x: 0, y: 2) .accessibilityLabel("crossImage") - }.buttonStyle(ActivityLogButtonStyle(activityDescription: "IMAGE REVIEW: " + selected.id + "status: REMOVED")) + .scaleEffect(scaleValue) + } + .buttonStyle(ScaleButtonStyle()) + .buttonStyle(ActivityLogButtonStyle(activityDescription: "IMAGE REVIEW: " + selected.id + "status: REMOVED")) } var likeAction: some View { Button(action: { print("LIKE tab = \(selected.name)") + showingHUD.toggle() + self.strMsg = "Added!" + self.imgMsg = "heart.fill" savedArray = UserImageCache.load(key: self.profile.id.appending("FavoritesArray")) - let result = savedArray.filter { $0.id == selected.id } + let result = savedArray.filter { $0.name == selected.name } if result.isEmpty { savedArray.append(selected) UserImageCache.save(savedArray, key: self.profile.id.appending("FavoritesArray")) @@ -90,7 +179,64 @@ struct ImageView: View { .clipShape(Circle()) .shadow(color: Color.black.opacity(0.50), radius: 3, x: 0, y: 2) .accessibilityLabel("heartImage") - }.buttonStyle(ActivityLogButtonStyle(activityDescription: "IMAGE REVIEW: " + selected.name + " status: FAVORITE")) + .scaleEffect(scaleValue) + } + .buttonStyle(ScaleButtonStyle()) + .buttonStyle(ActivityLogButtonStyle(activityDescription: "IMAGE REVIEW: " + selected.name + " status: FAVORITE")) + } + + var unLikeAction: some View { + Button(action: { + print("UNLIKE tab = \(selected.name)") + showingHUD.toggle() + self.strMsg = "Removed from favorites!" + self.imgMsg = "heart.slash.fill" + savedArray = UserImageCache.load(key: self.profile.id.appending("FavoritesArray")) + let result = savedArray.filter { $0.name != selected.name } + UserImageCache.save(result, key: self.profile.id.appending("FavoritesArray")) + }) { + Image(systemName: "heart.slash.fill") + .resizable() + .frame(width: 30, height: 30) + .foregroundColor(primaryColor) + .padding(10) + .background(Color.white) + .clipShape(Circle()) + .shadow(color: Color.black.opacity(0.50), radius: 3, x: 0, y: 2) + .accessibilityLabel("heart.slash.fill") + .scaleEffect(scaleValue) + .tint(primaryColor) + } + .buttonStyle(ScaleButtonStyle()) + .buttonStyle(ActivityLogButtonStyle(activityDescription: "IMAGE REVIEW: " + selected.name + " status: UNLIKE")) + } + + var returnAction: some View { + Button(action: { + print("RETURN tab = \(selected.name)") + showingHUD.toggle() + self.strMsg = "Return to list!" + self.imgMsg = "arrowshape.turn.up.backward.circle.fill" + let removedArray = UserImageCache.load(key: self.profile.id.appending("RemovedArray")) + let result = removedArray.filter { $0.name != selected.name } + if !result.isEmpty { + UserImageCache.save(result, key: self.profile.id.appending("RemovedArray")) + } + }) { + Image(systemName: "arrowshape.turn.up.backward.circle.fill") + .resizable() + .frame(width: 30, height: 30) + .foregroundColor(primaryColor) + .padding(10) + .background(Color.white) + .clipShape(Circle()) + .shadow(color: Color.black.opacity(0.50), radius: 3, x: 0, y: 2) + .accessibilityLabel("backImage") + .scaleEffect(scaleValue) + .tint(primaryColor) + } + .buttonStyle(ScaleButtonStyle()) + .buttonStyle(ActivityLogButtonStyle(activityDescription: "IMAGE REVIEW: " + selected.name + " status: RETURN")) } func loadUser() { diff --git a/Balance/Distraction/Music/iOS_SDK/SpotifyViewController.swift b/Balance/Distraction/Music/iOS_SDK/SpotifyViewController.swift index 343703b..0f1273e 100644 --- a/Balance/Distraction/Music/iOS_SDK/SpotifyViewController.swift +++ b/Balance/Distraction/Music/iOS_SDK/SpotifyViewController.swift @@ -277,10 +277,13 @@ extension SpotifyViewController: UITableViewDelegate, UITableViewDataSource { } @objc func pressed(sender : UIButton) { - guard let url = URL(string: "spotify://") else { - return + if UIApplication.shared.canOpenURL(URL(string: "spotify:")!) { + // spotify is installed. + UIApplication.shared.open(URL(string: "spotify:")!) + } else { + // spotify is not installed. Launch AppStore to install spotify app + UIApplication.shared.open(URL(string: spotifyURL)!) } - UIApplication.shared.open(url) } func player() { diff --git a/Balance/Fealing/Guess/BoxView.swift b/Balance/Fealing/Guess/BoxView.swift index b627a4e..abfccba 100644 --- a/Balance/Fealing/Guess/BoxView.swift +++ b/Balance/Fealing/Guess/BoxView.swift @@ -8,11 +8,13 @@ import SwiftUI struct BoxView: View { - @Environment(\.dismiss) var dismiss @Binding var selectedBtn: Int @Binding var questionIndex: Int @Binding var questions: [Question] @Binding var stopUserInteraction: Bool + @Binding var showingAlert: Bool + @Binding var correctAnswers: Int + @Binding var firstTry: Bool var box: Box var body: some View { @@ -22,16 +24,29 @@ struct BoxView: View { if self.questionIndex < (questions.count - 1) { if !self.box.correct { stopUserInteraction = false + firstTry = false return } + if firstTry == true { + correctAnswers += 1 + } DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { self.questionIndex += 1 self.selectedBtn = -1 stopUserInteraction = false + firstTry = true } } else { + if !self.box.correct { + stopUserInteraction = false + firstTry = false + return + } + if firstTry == true { + correctAnswers += 1 + } DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { - dismiss() + showingAlert = true } } }) { diff --git a/Balance/Fealing/Guess/GuessView.swift b/Balance/Fealing/Guess/GuessView.swift index 8f7ef0b..253df24 100644 --- a/Balance/Fealing/Guess/GuessView.swift +++ b/Balance/Fealing/Guess/GuessView.swift @@ -20,10 +20,14 @@ struct Question: Identifiable { } struct GuessView: View { + @Environment(\.dismiss) var dismiss @State var selected = 10 @State var questionIndex = 0 @State var stopUserInteraction = false - @State var questions = questionArray.prefix(10).shuffled() + @State var questions = [Question]() + @State var showingAlert = false + @State var firstTry = true + @State var correctAnswer = 0 var gridItemLayout = [GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible())] var body: some View { @@ -43,7 +47,19 @@ struct GuessView: View { optionsButtons } } + .onAppear(perform: { + questions = questionArray.prefix(cantAnswer).shuffled() + }) .disabled(stopUserInteraction) + .alert("You got \(correctAnswer)/\(cantAnswer) right on the first try!", isPresented: $showingAlert) { + Button("Close", role: .cancel) { + correctAnswer = 0 + firstTry = true + DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { + dismiss() + } + } + } } } @@ -86,27 +102,34 @@ struct GuessView: View { .cornerRadius(100, corners: .bottomLeft) .padding(40) .zIndex(0) - Image(questions[questionIndex].image) - .resizable() - .scaledToFit() - .frame(width: 220, height: 220, alignment: .center) - .accessibilityLabel(questions[questionIndex].image) - .frame(alignment: .center) - .zIndex(1) - .animation(.easeInOut(duration: 0.5), value: UUID()) + if !questions.isEmpty { + Image(questions[questionIndex].image) + .resizable() + .scaledToFit() + .frame(width: 220, height: 220, alignment: .center) + .accessibilityLabel(questions[questionIndex].image) + .frame(alignment: .center) + .zIndex(1) + .animation(.easeInOut(duration: 0.5), value: UUID()) + } } } var optionsButtons: some View { LazyVGrid(columns: gridItemLayout, spacing: 20) { - ForEach(questions[questionIndex].options, id: \.id) { box in - BoxView( - selectedBtn: self.$selected, - questionIndex: self.$questionIndex, - questions: $questions, - stopUserInteraction: $stopUserInteraction, - box: box - ).animation(.easeInOut(duration: 0.5), value: UUID()) + if !questions.isEmpty { + ForEach(questions[questionIndex].options, id: \.id) { box in + BoxView( + selectedBtn: self.$selected, + questionIndex: self.$questionIndex, + questions: $questions, + stopUserInteraction: $stopUserInteraction, + showingAlert: $showingAlert, + correctAnswers: $correctAnswer, + firstTry: $firstTry, + box: box + ).animation(.easeInOut(duration: 0.5), value: UUID()) + } } }.padding() } diff --git a/Balance/Utils/Constant.swift b/Balance/Utils/Constant.swift index 1dff826..5bd068a 100644 --- a/Balance/Utils/Constant.swift +++ b/Balance/Utils/Constant.swift @@ -71,3 +71,6 @@ let correctOption = Color(#colorLiteral(red: 0.6474730372, green: 1, blue: 0.811 let wrongOption = Color(#colorLiteral(red: 0.9673425555, green: 0.1463843882, blue: 0.5197440386, alpha: 1)) let silentTrack = "spotify:track:7p5bQJB4XsZJEEn6Tb7EaL" +let cantAnswer = 10 + +let spotifyURL = "https://itunes.com/apps/spotifyltd"