adding some nicer ui for the convos
This commit is contained in:
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
//
|
//
|
||||||
|
|||||||
Reference in New Issue
Block a user