adding toasts like crazy
This commit is contained in:
@@ -8,8 +8,45 @@
|
||||
import Foundation
|
||||
import Contacts
|
||||
import SwiftUI
|
||||
import AlertToast
|
||||
|
||||
class ContactsViewModel : ObservableObject {
|
||||
@Published var toast: Toast? {
|
||||
didSet {
|
||||
self.showToast = true
|
||||
}
|
||||
}
|
||||
@Published var showToast: Bool = false
|
||||
|
||||
enum Toast: Identifiable {
|
||||
var id: Self { self }
|
||||
|
||||
case maxFriendsInCircle
|
||||
case cannotFriendYourself
|
||||
case addedFriend
|
||||
case removedFriend
|
||||
case fetchingContacts
|
||||
|
||||
case generalError
|
||||
|
||||
var view: AlertToast {
|
||||
switch self {
|
||||
case .fetchingContacts:
|
||||
return AlertToast(displayMode: .hud, type: .systemImage("person.3.fill", NirvanaColor.dimTeal), title: "looking for friends")
|
||||
case .removedFriend:
|
||||
return AlertToast(displayMode: .hud, type: .complete(Color.green), title: "removed friend")
|
||||
case .addedFriend:
|
||||
return AlertToast(displayMode: .hud, type: .complete(Color.green), title: "added friend")
|
||||
case .cannotFriendYourself:
|
||||
return AlertToast(displayMode: .hud, type: .error(Color.orange), title: "silly! 🙉", subTitle: "you cannot friend yourself")
|
||||
case .maxFriendsInCircle:
|
||||
return AlertToast(displayMode: .hud, type: .systemImage("person.crop.circle.badge.exclamationmark.fill", Color.orange), title: "circle full!", subTitle: "tap on an existing friend and hold down on their icon in the bottom left to remove them to make space")
|
||||
default:
|
||||
return AlertToast(displayMode: .hud, type: .error(Color.orange), title: "Something went wrong ‼️")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Published var showPermissionAlert = false
|
||||
@Published var contacts: [String: ContactsViewModelContact] = [:]
|
||||
|
||||
@@ -48,6 +85,8 @@ class ContactsViewModel : ObservableObject {
|
||||
fetchRequest.sortOrder = .userDefault
|
||||
|
||||
do {
|
||||
self.toast = .fetchingContacts
|
||||
|
||||
try store.enumerateContacts(with: fetchRequest) {[weak self](contact, stop) in
|
||||
// only checking if american number or not for now
|
||||
var cnPhoneNumber = contact.phoneNumbers.first?.value.stringValue
|
||||
@@ -88,7 +127,6 @@ class ContactsViewModel : ObservableObject {
|
||||
}
|
||||
} catch {
|
||||
print("Unable to fetch contacts. \(error)")
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,6 +135,7 @@ class ContactsViewModel : ObservableObject {
|
||||
// make sure userId is not the same as friendId...don't want people friending themselves
|
||||
if userId == friendId {
|
||||
completion(ServiceState.error(ServiceError(description: "You cannot friend yourself, silly!")))
|
||||
self.toast = .cannotFriendYourself
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
import SwiftUI
|
||||
import Contacts
|
||||
import NavigationStack
|
||||
import AlertToast
|
||||
|
||||
struct FindFriendsView: View {
|
||||
@EnvironmentObject var navigationStack : NavigationStack
|
||||
@@ -52,6 +53,9 @@ struct FindFriendsView: View {
|
||||
.onAppear {
|
||||
self.contactsVM.fetchContacts()
|
||||
}
|
||||
.toast(isPresenting: self.$contactsVM.showToast) {
|
||||
self.contactsVM.toast?.view ?? AlertToast(displayMode: .hud, type: .error(Color.red), title: "Something went wrong")
|
||||
}
|
||||
}
|
||||
|
||||
var searchItems: [String] {
|
||||
@@ -134,24 +138,28 @@ struct ListContactRow: View {
|
||||
primaryButton: .default(Text("Cancel")),
|
||||
secondaryButton: .default(Text("Confirm")) {
|
||||
print("adding contact to circle")
|
||||
// call method in vm to get it done, then navigate to the circle
|
||||
if self.authSessionStore.friendsArr.count < 10 || self.authSessionStore.user?.phoneNumber == "+19499230445" {
|
||||
self.contactsVM.addOrActivateFriendToCircle(userId: self.authSessionStore.user!.id!, friendId: (contact.user!.id)!) {res in
|
||||
print(res)
|
||||
|
||||
switch res {
|
||||
case .error(let err):
|
||||
print(err)
|
||||
case .success(let str):
|
||||
print(str)
|
||||
}
|
||||
}
|
||||
if self.authSessionStore.friendsArr.count >= 10 {
|
||||
self.contactsVM.toast = .maxFriendsInCircle
|
||||
return
|
||||
}
|
||||
|
||||
self.contactsVM.addOrActivateFriendToCircle(userId: self.authSessionStore.user!.id!, friendId: (contact.user!.id)!) {res in
|
||||
print(res)
|
||||
|
||||
self.navigationStack.push(InnerCircleView())
|
||||
switch res {
|
||||
case .error(let err):
|
||||
print(err)
|
||||
self.contactsVM.toast = .generalError
|
||||
case .success(let str):
|
||||
print(str)
|
||||
self.contactsVM.toast = .addedFriend
|
||||
self.navigationStack.push(InnerCircleView())
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
else { // invite button to text the person
|
||||
HStack(alignment: .center, spacing: 0) {
|
||||
|
||||
@@ -43,11 +43,9 @@ struct CircleFooterView: View {
|
||||
Button(role: .destructive) {
|
||||
print("deactivating friend...removing from circle")
|
||||
if self.authSessionStore.user?.id != nil && self.selectedFriendIndex != nil {
|
||||
self.innerCircleVM.activateOrDeactiveInboxUser(activate: false, userId: self.authSessionStore.user!.id!, friendId: self.selectedFriendIndex!) {res in
|
||||
|
||||
print(res)
|
||||
self.selectedFriendIndex = nil // making this footer disappear although a view change should do this
|
||||
}
|
||||
self.innerCircleVM.activateOrDeactiveInboxUser(activate: false, userId: self.authSessionStore.user!.id!, friendId: self.selectedFriendIndex!)
|
||||
|
||||
self.selectedFriendIndex = nil
|
||||
}
|
||||
} label: {
|
||||
Label("Remove from Circle", systemImage: "person.crop.circle.fill.badge.minus")
|
||||
|
||||
@@ -131,7 +131,6 @@ struct CircleGridView: View {
|
||||
else {
|
||||
print("no convo id to join")
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
self.convoVM.toast = .alreadyInCall
|
||||
@@ -308,17 +307,17 @@ struct CircleGridView: View {
|
||||
message: Text(self.alertSubtext),
|
||||
primaryButton: .destructive(Text("Reject"), action: {
|
||||
// create user friend but a rejected one
|
||||
if self.authSessionStore.friendsArr.count < 10 || self.authSessionStore.user?.phoneNumber == "+19499230445" {
|
||||
self.innerCircleVM.activateOrDeactiveInboxUser(activate: false, userId: self.authSessionStore.user!.id!, friendId: inboxUserId) { res in
|
||||
print(res)
|
||||
}
|
||||
}
|
||||
self.innerCircleVM.activateOrDeactiveInboxUser(activate: false, userId: self.authSessionStore.user!.id!, friendId: inboxUserId)
|
||||
}),
|
||||
secondaryButton: .default(Text("Add"), action: {
|
||||
// create user friend
|
||||
self.innerCircleVM.activateOrDeactiveInboxUser(activate: true, userId: self.authSessionStore.user!.id!, friendId: inboxUserId) { res in
|
||||
print(res)
|
||||
// create user friend if have space in circle
|
||||
// TODO: view models should be able to do this validation, need some way of view models to speak to each other
|
||||
if self.authSessionStore.friendsArr.count >= 10 {
|
||||
self.innerCircleVM.toast = .maxFriendsInCircle
|
||||
return
|
||||
}
|
||||
|
||||
self.innerCircleVM.activateOrDeactiveInboxUser(activate: true, userId: self.authSessionStore.user!.id!, friendId: inboxUserId)
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
@@ -153,6 +153,9 @@ struct InnerCircleView: View {
|
||||
.toast(isPresenting: self.$convoViewModel.showToast) {
|
||||
self.convoViewModel.toast?.view ?? AlertToast(displayMode: .hud, type: .error(Color.red), title: "Something went wrong")
|
||||
}
|
||||
.toast(isPresenting: self.$innerCircleVM.showToast) {
|
||||
self.innerCircleVM.toast?.view ?? AlertToast(displayMode: .hud, type: .error(Color.red), title: "Something went wrong")
|
||||
}
|
||||
// .onDisappear {
|
||||
// print("deiniting data listeners, but current data should still be cached!")
|
||||
//
|
||||
|
||||
@@ -7,8 +7,58 @@
|
||||
|
||||
import Foundation
|
||||
import AVFoundation
|
||||
import AlertToast
|
||||
import SwiftUI
|
||||
|
||||
class InnerCircleViewModel: ObservableObject {
|
||||
@Published var toast: Toast? {
|
||||
didSet {
|
||||
self.showToast = true
|
||||
}
|
||||
}
|
||||
@Published var showToast: Bool = false
|
||||
|
||||
enum Toast: Identifiable {
|
||||
var id: Self { self }
|
||||
|
||||
case startedClip
|
||||
case problemSendingClip
|
||||
case nothingRecorded
|
||||
case clipSent
|
||||
|
||||
case maxFriendsInCircle
|
||||
case cannotFriendYourself
|
||||
case addedFriend
|
||||
case removedFriend
|
||||
|
||||
case generalError
|
||||
|
||||
|
||||
var view: AlertToast {
|
||||
switch self {
|
||||
case .removedFriend:
|
||||
return AlertToast(displayMode: .hud, type: .complete(Color.green), title: "removed friend")
|
||||
case .addedFriend:
|
||||
return AlertToast(displayMode: .hud, type: .complete(Color.green), title: "added friend")
|
||||
case .cannotFriendYourself:
|
||||
return AlertToast(displayMode: .hud, type: .error(Color.orange), title: "silly! 🙉", subTitle: "you cannot friend yourself")
|
||||
case .maxFriendsInCircle:
|
||||
return AlertToast(displayMode: .hud, type: .systemImage("person.crop.circle.badge.exclamationmark.fill", Color.orange), title: "circle full!", subTitle: "tap on an existing friend and hold down on their icon in the bottom left to remove them to make space")
|
||||
case .nothingRecorded:
|
||||
return AlertToast(displayMode: .hud, type: .systemImage("exclamationmark.triangle.fill", NirvanaColor.teal), title: "nothing recorded", subTitle: "please try again")
|
||||
case .clipSent:
|
||||
return AlertToast(displayMode: .hud, type: .systemImage("paperplane.circle.fill", NirvanaColor.teal), title: "clip sent")
|
||||
case .problemSendingClip:
|
||||
return AlertToast(displayMode: .hud, type: .error(Color.orange), title: "problem sending clip", subTitle: "please try again")
|
||||
case .startedClip:
|
||||
return AlertToast(displayMode: .hud, type: .systemImage("waveform.circle.fill", NirvanaColor.teal), title: "clip started")
|
||||
default:
|
||||
return AlertToast(displayMode: .hud, type: .error(Color.orange), title: "Something went wrong ‼️")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var audioRecorder : AVAudioRecorder!
|
||||
var audioPlayer : AVAudioPlayer!
|
||||
|
||||
@@ -21,7 +71,7 @@ class InnerCircleViewModel: ObservableObject {
|
||||
private let cloudStorageService = CloudStorageService()
|
||||
private let firestoreService = FirestoreService()
|
||||
private let pushNotificationService = PushNotificationService()
|
||||
private let agoraService = AgoraService()
|
||||
|
||||
|
||||
init() {
|
||||
// separate set up for listening vs recording
|
||||
@@ -57,6 +107,8 @@ extension InnerCircleViewModel {
|
||||
audioRecorder.record()
|
||||
isRecording = true
|
||||
|
||||
self.toast = .startedClip
|
||||
|
||||
self.audioLocalUrl = filePath // setting this for later use when recording is stopped
|
||||
|
||||
} catch {
|
||||
@@ -81,6 +133,7 @@ extension InnerCircleViewModel {
|
||||
self.cloudStorageService.uploadLocalUrl(localFileUrl: self.audioLocalUrl!) {[weak self] audioDataUrl in
|
||||
if audioDataUrl == nil {
|
||||
print("there was an error in uploading file")
|
||||
self?.toast = .problemSendingClip
|
||||
return
|
||||
}
|
||||
|
||||
@@ -90,18 +143,33 @@ extension InnerCircleViewModel {
|
||||
self?.firestoreService.createMessage(message: newMessage) {[weak self] res in
|
||||
print(res)
|
||||
|
||||
// sending push notification if there was a device token
|
||||
if receiver.deviceToken != nil && receiver.nickname != nil {
|
||||
self?.pushNotificationService.sendPushNotification(to: receiver.deviceToken!, title: "🌱Nirvana", body: "continue your conversation with \(sender.nickname ?? "your friend")")
|
||||
switch res {
|
||||
case .success:
|
||||
|
||||
self?.toast = .clipSent
|
||||
|
||||
// sending push notification if there was a device token for this friend
|
||||
if receiver.deviceToken != nil && receiver.nickname != nil {
|
||||
self?.pushNotificationService.sendPushNotification(to: receiver.deviceToken!, title: "🌱Nirvana", body: "continue your conversation with \(sender.nickname ?? "your friend")")
|
||||
}
|
||||
|
||||
// delete local audio file from user's phone so that it doesn't take crazy space
|
||||
print("stopped recording: file about to get deleted from \(self?.getTemporaryDirectory()) with filename: \(self?.audioLocalUrl)")
|
||||
|
||||
try? FileManager.default.removeItem(at: (self?.audioLocalUrl)!)
|
||||
case .error(let err):
|
||||
print(err)
|
||||
self?.toast = .problemSendingClip
|
||||
default:
|
||||
self?.toast = .problemSendingClip
|
||||
}
|
||||
|
||||
// delete local audio file from user's phone so that it doesn't get crazy
|
||||
print("stopped recording: file about to get deleted from \(self?.getTemporaryDirectory()) with filename: \(self?.audioLocalUrl)")
|
||||
|
||||
try? FileManager.default.removeItem(at: (self?.audioLocalUrl)!)
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
print("nothing recorded, can't send")
|
||||
self.toast = .problemSendingClip
|
||||
}
|
||||
}
|
||||
|
||||
func getTemporaryDirectory() -> URL {
|
||||
@@ -123,11 +191,12 @@ extension InnerCircleViewModel {
|
||||
|
||||
// handle activating or deactivating friends
|
||||
extension InnerCircleViewModel {
|
||||
func activateOrDeactiveInboxUser(activate: Bool, userId: String, friendId: String, completion: @escaping((_ state: ServiceState) -> ())) {
|
||||
func activateOrDeactiveInboxUser(activate: Bool, userId: String, friendId: String) {
|
||||
// validation
|
||||
// make sure userId is not the same as friendId...don't want people friending themselves
|
||||
if userId == friendId {
|
||||
completion(ServiceState.error(ServiceError(description: "You cannot friend yourself, silly!")))
|
||||
print("you cannot friend yourself")
|
||||
self.toast = .cannotFriendYourself
|
||||
return
|
||||
}
|
||||
|
||||
@@ -135,7 +204,20 @@ extension InnerCircleViewModel {
|
||||
var userFriend = UserFriends(userId: userId, friendId: friendId, isActive: activate, lastUpdatedTimestamp: nil)
|
||||
|
||||
self.firestoreService.createOrUpdateUserFriends(userFriend: userFriend, activateOrDeactivate: activate) {[weak self] res in
|
||||
completion(res)
|
||||
switch res {
|
||||
case .success:
|
||||
if activate {
|
||||
self?.toast = .addedFriend
|
||||
}
|
||||
else {
|
||||
self?.toast = .removedFriend
|
||||
}
|
||||
case .error(let err):
|
||||
print(err)
|
||||
self?.toast = .generalError
|
||||
default:
|
||||
self?.toast = .generalError
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -146,15 +228,3 @@ extension InnerCircleViewModel {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// everything related to calls and such
|
||||
extension InnerCircleViewModel {
|
||||
func getAgoraToken() {
|
||||
if let uid = AuthSessionStore.getCurrentUserId() {
|
||||
self.agoraService.getAgoraUserTokenServer(channelName: uid)
|
||||
}
|
||||
else {
|
||||
print("no user authenticated to get an agora token")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user