import Foundation
import Combine
import Pyramid
import UIKit
class UserViewModel: ObservableObject {
@Published var user: CurrentUser = CurrentUser.dInit
@Published var uploading = false
let provider = Pyramid()
var cancellationToken: AnyCancellable?
init() {
self.fetchMySelf()
}
}
extension UserViewModel {
func fetchMySelf() {
guard let my: CurrentUser = KeychainService.loadCodable(for: .currentUser) else {
return
}
cancellationToken = provider.request(
with: UserAPI.me(my.id),
scheduler: RunLoop.main,
class: CurrentUser.self
)
.receive(on: RunLoop.main)
.sink(receiveCompletion: { completionResponse in
switch completionResponse {
case .failure(let error):
print(error)
case .finished:
break
}
}, receiveValue: { [weak self] res in
guard let self = self else { return }
self.user = res
KeychainService.save(codable: res, for: .currentUser)
})
}
func uploadAvatar(_ image: UIImage) {
uploading = true
guard let me: CurrentUser = KeychainService.loadCodable(for: .currentUser) else {
return
}
AWSS3Helper.uploadImage(image, conversationId: nil, userId: me.id) { [weak self] imageURLString in
DispatchQueue.main.async {
self?.uploading = false
let attachment = Attachment(type: .image, userId: me.id, imageUrlString: imageURLString)
self?.createAttachment(attachment)
}
}
}
func createAttachment(_ attachment: Attachment) {
cancellationToken = provider.request(
with: AttachmentAPI.create(attachment),
scheduler: RunLoop.main,
class: Attachment.self
).sink(receiveCompletion: { completionResponse in
switch completionResponse {
case .failure(let error):
print(error)
case .finished:
break
}
}, receiveValue: { res in
print(#line, self, res)
self.fetchMySelf()
})
}
}
struct ProfileView: View {
@State var moveToAuth: Bool = false
@StateObject private var eventViewModel = EventViewModel()
@StateObject private var me = UserViewModel()
@ObservedObject var viewModel = AuthViewModel()
@EnvironmentObject var appState: AppState
@State private var showingImagePicker = false
@State private var inputImage: UIImage?
var body: some View {
NavigationView {
ScrollView {
AsyncImage(
url: me.user.imageURL,
placeholder: { Text("Loading...").frame(width: 100, height: 100, alignment: .center) },
image: {
Image(uiImage: $0).resizable()
}
)
.aspectRatio(contentMode: .fit)
.overlay(
ProfileImageOverlay(
showingImagePicker: self.$showingImagePicker,
inputImage: self.$inputImage
).environmentObject(me) ,
alignment: .bottomTrailing
)
Divider()
VStack(alignment: .leading) {
Text("My Events:")
.font(.system(size: 23, weight: .bold, design: .rounded))
.padding(.top, 10)
.padding()
}
LazyVStack {
ForEach(eventViewModel.myEvents) { event in
EventRow(event: event)
.hideRowSeparator()
.onAppear {
eventViewModel.fetchMoreMyEventIfNeeded(currentItem: event)
}
}
if eventViewModel.isLoadingPage {
ProgressView()
}
}
HStack {
Button(action: {
AppUserDefaults.resetAuthData()
self.viewModel.isAuthorized = false
self.moveToAuth.toggle()
}) {
Text("Logout")
.font(.title)
.bold()
}.background(
NavigationLink.init(
destination: AuthView()
.onAppear(perform: {
appState.tabBarIsHidden = true
})
.navigationBarTitle(String.empty)
.navigationBarHidden(true),
isActive: $moveToAuth,
label: {}
)
)
}
}
.navigationBarTitle("Profile", displayMode: .inline)
.onAppear {
self.eventViewModel.fetchMoreMyEvents()
}
.sheet(isPresented: $showingImagePicker, onDismiss: loadImage) {
ImagePicker(image: self.$inputImage)
}
}
.navigationViewStyle(StackNavigationViewStyle())
}
func loadImage() {
guard let inputImage = inputImage else { return }
//image = Image(uiImage: inputImage)
me.uploadAvatar(inputImage)
}
}