adding some nicer ui for the convos

This commit is contained in:
talksik
2022-01-01 18:48:37 -08:00
parent d64267b2a1
commit f497740c75
4 changed files with 184 additions and 152 deletions
+94 -74
View File
@@ -9,89 +9,95 @@ import SwiftUI
struct ConvoFooterView: View { struct ConvoFooterView: View {
@EnvironmentObject var convoVM: ConvoViewModel @EnvironmentObject var convoVM: ConvoViewModel
@EnvironmentObject var authSessionStore: AuthSessionStore
@State private var convoRelativeTime = "started 20 minutes ago" @State private var convoRelativeTime = "started 20 minutes ago"
@State private var selectedConvo: Convo? = nil
var body: some View { var body: some View {
ZStack(alignment:.bottomTrailing) { ZStack(alignment:.bottomTrailing) {
VStack(alignment:.center) { VStack(alignment:.center) {
Spacer() Spacer()
HStack { HStack {
ProfilePicturesOverlappedView(indvAvatarWidth: CGFloat(35)) if self.selectedConvo != nil {
.padding(.leading, 20) let filteredUsers = self.authSessionStore.relevantUsersDict.filter {
.padding(.trailing, 10) return self.selectedConvo!.users.contains($0.key)
}
let convoUsers: [User] = Array(filteredUsers.values)
// meta data of convo
VStack (alignment: .leading) {
Text("kev, sarth, and 5 others")
.font(.footnote)
.foregroundColor(NirvanaColor.light)
switch self.convoVM.connectionState { ProfilePicturesOverlappedView(indvAvatarWidth: CGFloat(35), users: convoUsers)
case .connecting: .padding(.leading, 20)
Label("connecting", systemImage: "chart.bar") .padding(.trailing, 10)
.foregroundColor(Color.orange)
.font(.caption) // meta data of convo
case .connected: VStack (alignment: .leading) {
Label("connected", systemImage: "chart.bar.fill") ConvoUsernames(users: convoUsers)
.foregroundColor(Color.green)
.font(.caption) switch self.convoVM.connectionState {
case .reconnecting: case .connecting:
Label("reconnecting", systemImage: "chart.bar") Label("connecting", systemImage: "chart.bar")
.foregroundColor(Color.orange) .foregroundColor(Color.orange)
.font(.caption) .font(.caption)
case .failed: case .connected:
Label("failed", systemImage: "chart.bar") Label("connected", systemImage: "chart.bar.fill")
.foregroundColor(Color.red) .foregroundColor(Color.green)
.font(.caption) .font(.caption)
case .disconnected: case .reconnecting:
Label("disconnected", systemImage: "chart.bar") Label("reconnecting", systemImage: "chart.bar")
.foregroundColor(Color.red) .foregroundColor(Color.orange)
.font(.caption) .font(.caption)
default: case .failed:
Label("disconnected", systemImage: "chart.bar") Label("failed", systemImage: "chart.bar")
.foregroundColor(Color.red) .foregroundColor(Color.red)
.font(.caption) .font(.caption)
case .disconnected:
Label("disconnected", systemImage: "chart.bar")
.foregroundColor(Color.red)
.font(.caption)
default:
Label("disconnected", systemImage: "chart.bar")
.foregroundColor(Color.red)
.font(.caption)
}
Text(self.convoRelativeTime)
.font(.caption2)
.foregroundColor(.gray)
} }
Text(self.convoRelativeTime) Spacer()
.font(.caption2)
.foregroundColor(.gray)
}
Spacer()
// disconnect button
Button {
print("showing more info about the chat")
// show a sheet of the members in the call and add them if I want // disconnect button
Button {
print("showing more info about the chat")
// show a sheet of the members in the call and add them if I want
} label: {
Label("attendees", systemImage: "person.2.circle.fill")
.labelStyle(.iconOnly)
.foregroundColor(NirvanaColor.teal)
.font(.title2)
.padding(.trailing, 5)
}
} label: { // disconnect button
Label("attendees", systemImage: "person.2.circle.fill") Button {
.labelStyle(.iconOnly) print("disconnecting user now ")
.foregroundColor(NirvanaColor.teal)
.font(.title2) self.convoVM.leaveConvo()
.padding(.trailing, 5)
// show success or failure toast
} label: {
Label("Call", systemImage: "powerplug.fill")
.labelStyle(.iconOnly)
.foregroundColor(Color.orange)
.font(.title2)
.padding(.trailing, 5)
}
} }
// disconnect button
Button {
print("disconnecting user now ")
self.convoVM.leaveConvo()
// show success or failure toast
} label: {
Label("Call", systemImage: "powerplug.fill")
.labelStyle(.iconOnly)
.foregroundColor(Color.orange)
.font(.title2)
.padding(.trailing, 5)
}
} }
.frame(maxWidth: .infinity, maxHeight: 60) // 60 is the height of the footer control big circle .frame(maxWidth: .infinity, maxHeight: 60) // 60 is the height of the footer control big circle
.background(Color.white.opacity(0.5)) .background(Color.white.opacity(0.5))
@@ -105,17 +111,20 @@ struct ConvoFooterView: View {
x:0, x:0,
y:self.convoVM.selectedConvoId == nil ? 150 : 0 y:self.convoVM.selectedConvoId == nil ? 150 : 0
) )
.onChange(of: self.convoVM.selectedConvoId) {newConvo in .onReceive(self.convoVM.$selectedConvoId) {newConvoId in
// update meta data based on which convo was selected // update meta data based on which convo was selected
// reset the selected options to start fresh // reset the selected options to start fresh
// self.convoRelativeTime = "" self.convoRelativeTime = ""
self.selectedConvo = self.convoVM.relevantConvos.first {convo in
convo.id == newConvoId
}
// get relative start time of convo // get relative start time of convo
// let formatter = RelativeDateTimeFormatter() let formatter = RelativeDateTimeFormatter()
// formatter.unitsStyle = .full formatter.unitsStyle = .full
// self.convoRelativeTime = formatter.localizedString(for: self.selectedConvo?.startedTimestamp ?? Date(), relativeTo: Date())
// let relativeDate = formatter.localizedString(for: ?.sentTimestamp ?? Date(), relativeTo: Date())
} }
} }
} }
@@ -125,3 +134,14 @@ struct ConvoFooterView_Previews: PreviewProvider {
ConvoFooterView() ConvoFooterView()
} }
} }
struct ConvoUsernames: View {
var users: [User]
var body: some View {
let userNames = self.users.map{$0.nickname ?? ""}.joined(separator: ",")
Text(userNames)
.font(.footnote)
.foregroundColor(NirvanaColor.light)
}
}
+62 -59
View File
@@ -7,67 +7,70 @@
import SwiftUI import SwiftUI
struct ConvosView: View { /**
@EnvironmentObject var vm: ConvoViewModel deprecated...used to insert into circlegridview but can isolate later
@State var animate = false */
//struct ConvosView: View {
var body: some View { // @EnvironmentObject var vm: ConvoViewModel
ScrollView([.horizontal]) { // @State var animate = false
HStack {
ForEach(0..<self.vm.relevantConvos.count, id: \.self) {index in
let currConvo = self.vm.relevantConvos[index]
ZStack(alignment: .topTrailing) {
Circle()
.foregroundColor(self.vm.selectedConvoId == currConvo.id ? Color.green : NirvanaColor.dimTeal.opacity(0.2))
ZStack {
Color.clear
ProfilePicturesOverlappedView()
.shadow(radius: 10)
}
Text("+2")
.padding(5)
.font(.caption)
.foregroundColor(Color.white)
.background(NirvanaColor.dimTeal)
.cornerRadius(100)
// ZStack(alignment: .bottom) {
// Color.clear
// //
// Text("kev, sarth...") // var body: some View {
// .foregroundColor(NirvanaColor.teal) // ScrollView([.horizontal]) {
// .font(.caption) // HStack {
// ForEach(0..<self.vm.relevantConvos.count, id: \.self) {index in
// let currConvo = self.vm.relevantConvos[index]
// ZStack(alignment: .topTrailing) {
// Circle()
// .foregroundColor(self.vm.selectedConvoId == currConvo.id ? Color.green : NirvanaColor.dimTeal.opacity(0.2))
//
// ZStack {
// Color.clear
// ProfilePicturesOverlappedView()
// .shadow(radius: 10)
// } // }
} //
.frame(width: 100, height: 100) // Text("+2")
.scaleEffect(self.animate ? 1 : 0.85) // .padding(5)
.animation( // .font(.caption)
Animation.easeInOut(duration: self.vm.selectedConvoId == currConvo.id ? 2 : 4 // .foregroundColor(Color.white)
).repeatForever(autoreverses: true), // .background(NirvanaColor.dimTeal)
value: self.animate // .cornerRadius(100)
) //
.onTapGesture { //// ZStack(alignment: .bottom) {
// if not in a call already //// Color.clear
if !self.vm.isInCall() { ////
self.vm.selectedConvoId = self.vm.relevantConvos[index].id! //// Text("kev, sarth...")
self.vm.joinConvo(convoId: currConvo.id!) //// .foregroundColor(NirvanaColor.teal)
//// .font(.caption)
return //// }
} // }
// .frame(width: 100, height: 100)
self.vm.leaveConvo() // .scaleEffect(self.animate ? 1 : 0.85)
} // .animation(
} // Animation.easeInOut(duration: self.vm.selectedConvoId == currConvo.id ? 2 : 4
} // ).repeatForever(autoreverses: true),
.onAppear { // value: self.animate
self.animate = true // )
} // .onTapGesture {
} // // if not in a call already
.padding() // if !self.vm.isInCall() {
} // self.vm.selectedConvoId = self.vm.relevantConvos[index].id!
} // self.vm.joinConvo(convoId: currConvo.id!)
//
// return
// }
//
// self.vm.leaveConvo()
// }
// }
// }
// .onAppear {
// self.animate = true
// }
// }
// .padding()
// }
//}
//struct ConvosView_Previews: PreviewProvider { //struct ConvosView_Previews: PreviewProvider {
// static var previews: some View { // static var previews: some View {
@@ -7,31 +7,33 @@
import SwiftUI import SwiftUI
/**
@return a view that overlaps the user avatars
*/
struct ProfilePicturesOverlappedView: View { struct ProfilePicturesOverlappedView: View {
let numberAttendees:Int = 5
let offset:Int = 15 let offset:Int = 15
var indvAvatarWidth: CGFloat = 50 var indvAvatarWidth: CGFloat = 50
var users: [User]
var body: some View { var body: some View {
ZStack { ZStack {
ForEach(0..<numberAttendees, id: \.self) {attendeeIndex in ForEach(0..<users.count, id: \.self) {userIndex in
if attendeeIndex < 3 { Image(users[userIndex].avatar ?? Avatars.avatarSystemNames[1])
Image(Avatars.avatarSystemNames[attendeeIndex+1]) .resizable()
.resizable() .scaledToFit()
.scaledToFit() .background(NirvanaColor.dimTeal)
.background(NirvanaColor.dimTeal) .clipShape(Circle())
.clipShape(Circle()) .offset(x: CGFloat((-15 * userIndex)) + 15)
.offset(x: CGFloat((-15 * attendeeIndex)) + 15) .frame(width: indvAvatarWidth)
.frame(width: indvAvatarWidth)
}
} }
} }
} }
} }
struct ProfilePicturesOverlappedView_Previews: PreviewProvider { //struct ProfilePicturesOverlappedView_Previews: PreviewProvider {
static var previews: some View { // static var previews: some View {
ProfilePicturesOverlappedView() // ProfilePicturesOverlappedView()
} // }
} //}
@@ -54,6 +54,8 @@ struct CircleGridView: View {
@State var animateLiveConvos = false @State var animateLiveConvos = false
let maxNumAvatarsToShowInConvo = 3
var body: some View { var body: some View {
// main communication hub // main communication hub
// TODO: client side, sort the honeycomb from top left to bottom right // TODO: client side, sort the honeycomb from top left to bottom right
@@ -74,6 +76,10 @@ struct CircleGridView: View {
// live convos // live convos
ForEach(0..<convos.count, id: \.self) {value in ForEach(0..<convos.count, id: \.self) {value in
let currConvo = self.convoVM.relevantConvos[value] let currConvo = self.convoVM.relevantConvos[value]
let filteredUsers = self.authSessionStore.relevantUsersDict.filter {
return currConvo.users.contains($0.key)
}
let convoUsers: [User] = Array(filteredUsers.values)
GeometryReader {gridProxy in GeometryReader {gridProxy in
let scale = getScale(proxy: gridProxy, itemNumber: value, userId: nil, convoId: currConvo.id) let scale = getScale(proxy: gridProxy, itemNumber: value, userId: nil, convoId: currConvo.id)
@@ -81,20 +87,21 @@ struct CircleGridView: View {
ZStack(alignment: .topTrailing) { ZStack(alignment: .topTrailing) {
Circle() Circle()
.foregroundColor(self.getBubbleTint(convoId: currConvo.id)) .foregroundColor(self.getBubbleTint(convoId: currConvo.id))
ZStack { ZStack {
Color.clear Color.clear
ProfilePicturesOverlappedView() ProfilePicturesOverlappedView(users: Array(convoUsers.prefix(maxNumAvatarsToShowInConvo)))
.shadow(color: Color.black.opacity(0.2), radius: 10, x: 0, y: 20) .shadow(color: Color.black.opacity(0.2), radius: 10, x: 0, y: 20)
} }
Text("+2") Text("\(convoUsers.count)")
.padding(5) .padding(5)
.font(.caption) .font(.caption)
.foregroundColor(Color.white) .foregroundColor(Color.white)
.background(NirvanaColor.dimTeal) .background(NirvanaColor.dimTeal)
.cornerRadius(100) .cornerRadius(100)
// ZStack(alignment: .bottom) { // ZStack(alignment: .bottom) {
// Color.clear // Color.clear
// //