mirror of
https://gitee.com/farsunset/cim.git
synced 2025-07-22 07:46:43 +08:00
300 lines
10 KiB
Swift
300 lines
10 KiB
Swift
//
|
|
// DetailView.swift
|
|
// CIMApp (macOS)
|
|
//
|
|
// Created by FeiYu on 2021/10/16.
|
|
//
|
|
|
|
import SwiftUI
|
|
import CIMClient
|
|
|
|
struct DetailView: View {
|
|
@EnvironmentObject var homeData: HomeViewModel
|
|
var session: Session
|
|
var body: some View {
|
|
HStack{
|
|
VStack{
|
|
HStack{
|
|
Text(session.userName)
|
|
.font(.title2)
|
|
Spacer()
|
|
Button(action: {}, label: {
|
|
Image(systemName: "magnifyingglass")
|
|
.font(.title2)
|
|
})
|
|
.buttonStyle(PlainButtonStyle())
|
|
|
|
Button(action: {withAnimation{homeData.isExpanded.toggle()}}, label: {
|
|
Image(systemName: "sidebar.right")
|
|
.font(.title2)
|
|
.foregroundColor(homeData.isExpanded ? .blue : .primary)
|
|
})
|
|
.buttonStyle(PlainButtonStyle())
|
|
}
|
|
.padding()
|
|
|
|
MessageView(session: session)
|
|
|
|
HStack(spacing:15){
|
|
Button(action: {
|
|
print(homeData.message)
|
|
}, label: {
|
|
Image(systemName: "paperplane")
|
|
.font(.title2)
|
|
})
|
|
.buttonStyle(PlainButtonStyle())
|
|
|
|
TextField("Enter Message", text: $homeData.message, onCommit: {
|
|
homeData.sendMessage(session: session)
|
|
})
|
|
.textFieldStyle(PlainTextFieldStyle())
|
|
.padding(.vertical,8)
|
|
.padding(.horizontal)
|
|
.clipShape(Capsule())
|
|
.background(Capsule().strokeBorder(Color.white))
|
|
|
|
Button(action: { }, label: {
|
|
Image(systemName: "face.smiling.fill")
|
|
.font(.title2)
|
|
})
|
|
.buttonStyle(PlainButtonStyle())
|
|
|
|
Button(action: {}, label: {
|
|
Image(systemName: "mic")
|
|
.font(.title2)
|
|
})
|
|
.buttonStyle(PlainButtonStyle())
|
|
}
|
|
.padding([.horizontal,.bottom])
|
|
}
|
|
|
|
ExpandedView(session: session)
|
|
.background(BlurView())
|
|
.frame(width: homeData.isExpanded ? nil : 0)
|
|
.opacity(homeData.isExpanded ? 1 : 0)
|
|
}
|
|
.ignoresSafeArea(.all, edges: .all)
|
|
.onAppear(perform: {
|
|
homeData.clearUnReadMessage(session: session)
|
|
})
|
|
}
|
|
}
|
|
|
|
struct DetailView_Previews: PreviewProvider {
|
|
static var previews: some View {
|
|
Home()
|
|
}
|
|
}
|
|
|
|
struct MessageView: View {
|
|
|
|
@EnvironmentObject var homeData: HomeViewModel
|
|
var session: Session
|
|
var body: some View {
|
|
|
|
GeometryReader {render in
|
|
ScrollView{
|
|
|
|
ScrollViewReader{proxy in
|
|
VStack{
|
|
ForEach(session.allMsgs){message in
|
|
|
|
MessageCardView(message: message, session: session, width: render.frame(in: .global).width)
|
|
.padding(.bottom,20)
|
|
.tag(message.id)
|
|
}
|
|
}
|
|
.padding(.leading,10)
|
|
.onAppear(perform: {
|
|
let lastID = session.allMsgs.last!.id
|
|
proxy.scrollTo(lastID, anchor: .bottom)
|
|
})
|
|
.onChange(of: session.allMsgs, perform: { value in
|
|
withAnimation{
|
|
let lastID = value.last!.id
|
|
proxy.scrollTo(lastID, anchor: .bottom)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
struct MessageCardView: View {
|
|
|
|
@EnvironmentObject var homeData: HomeViewModel
|
|
|
|
var message: Message
|
|
var session: Session
|
|
var width: CGFloat
|
|
|
|
var body: some View {
|
|
|
|
HStack(spacing: 10) {
|
|
let myMessage = (message.sender == "\(homeData.account.id)")
|
|
if myMessage {
|
|
|
|
Spacer()
|
|
|
|
Text(message.content)
|
|
.foregroundColor(.white)
|
|
.padding(10)
|
|
.background(Color.blue)
|
|
.clipShape(MessageBubble(myMessage: myMessage))
|
|
.frame(minWidth: 0, maxWidth: width / 2, alignment: .trailing)
|
|
|
|
Image(session.userImage)
|
|
.resizable()
|
|
.aspectRatio(contentMode: .fill)
|
|
.frame(width: 35, height: 35)
|
|
.clipShape(Circle())
|
|
.offset(y: 20)
|
|
|
|
} else {
|
|
|
|
Image(session.userImage)
|
|
.resizable()
|
|
.aspectRatio(contentMode: .fill)
|
|
.frame(width: 35, height: 35)
|
|
.clipShape(Circle())
|
|
.offset(y: 20)
|
|
|
|
Text(message.content)
|
|
.foregroundColor(.white)
|
|
.padding(10)
|
|
.background(Color.primary.opacity(0.2))
|
|
.clipShape(MessageBubble(myMessage: myMessage))
|
|
.frame(minWidth: 0, maxWidth: width / 2, alignment: .leading)
|
|
|
|
Spacer()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
struct MessageBubble: Shape {
|
|
|
|
var myMessage: Bool
|
|
|
|
func path(in rect: CGRect) -> Path {
|
|
return Path{ path in
|
|
let pt1 = CGPoint(x: 0, y: 0)
|
|
let pt2 = CGPoint(x: rect.width, y: 0)
|
|
let pt3 = CGPoint(x: rect.width, y: rect.height)
|
|
let pt4 = CGPoint(x: 0, y: rect.height)
|
|
|
|
if myMessage {
|
|
path.move(to: pt3)
|
|
path.addArc(tangent1End: pt3, tangent2End: pt4, radius: 15)
|
|
path.addArc(tangent1End: pt4, tangent2End: pt1, radius: 15)
|
|
path.addArc(tangent1End: pt1, tangent2End: pt2, radius: 15)
|
|
path.addArc(tangent1End: pt2, tangent2End: pt3, radius: 15)
|
|
} else {
|
|
path.move(to: pt4)
|
|
path.addArc(tangent1End: pt4, tangent2End: pt1, radius: 15)
|
|
path.addArc(tangent1End: pt1, tangent2End: pt2, radius: 15)
|
|
path.addArc(tangent1End: pt2, tangent2End: pt3, radius: 15)
|
|
path.addArc(tangent1End: pt3, tangent2End: pt4, radius: 15)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
struct ExpandedView: View {
|
|
@EnvironmentObject var homeData: HomeViewModel
|
|
var session: Session
|
|
var body: some View {
|
|
HStack(spacing: 0) {
|
|
Divider()
|
|
|
|
VStack(spacing: 25) {
|
|
|
|
Image(session.userImage)
|
|
.resizable()
|
|
.aspectRatio(contentMode: .fill)
|
|
.frame(width: 90, height: 90)
|
|
.clipShape(Circle())
|
|
.padding(.top,35)
|
|
|
|
Text(session.userName)
|
|
.font(.title)
|
|
.fontWeight(.bold)
|
|
|
|
HStack{
|
|
|
|
Button(action: {}, label: {
|
|
VStack{
|
|
Image(systemName: "bell.slash")
|
|
.font(.title2)
|
|
Text("Mute")
|
|
}
|
|
.contentShape(Rectangle())
|
|
})
|
|
.buttonStyle(PlainButtonStyle())
|
|
|
|
Spacer()
|
|
|
|
Button(action: {}, label: {
|
|
VStack{
|
|
Image(systemName: "hand.raised.fill")
|
|
.font(.title2)
|
|
Text("Block")
|
|
}
|
|
.contentShape(Rectangle())
|
|
})
|
|
.buttonStyle(PlainButtonStyle())
|
|
|
|
Spacer()
|
|
|
|
Button(action: {}, label: {
|
|
VStack{
|
|
Image(systemName: "exclamationmark.triangle")
|
|
.font(.title2)
|
|
Text("Report")
|
|
}
|
|
.contentShape(Rectangle())
|
|
})
|
|
.buttonStyle(PlainButtonStyle())
|
|
}
|
|
.foregroundColor(.gray)
|
|
|
|
Picker(selection: $homeData.pickedTab, label: Text("Picker"), content: {
|
|
Text("Media").tag("Media")
|
|
Text("Links").tag("Links")
|
|
Text("Audio").tag("Audio")
|
|
Text("Files").tag("Files")
|
|
})
|
|
.labelsHidden()
|
|
.padding(.vertical)
|
|
.pickerStyle(SegmentedPickerStyle())
|
|
|
|
ScrollView{
|
|
if homeData.pickedTab == "Media" {
|
|
|
|
LazyVGrid(columns: Array(repeating: GridItem(.flexible(), spacing: 10), count: 3), spacing: 10, content: {
|
|
|
|
ForEach(1...8, id: \.self) {
|
|
index in
|
|
Image("avatar")
|
|
.resizable()
|
|
.aspectRatio(contentMode: .fill)
|
|
.frame(width: 80, height: 80)
|
|
.cornerRadius(3)
|
|
}
|
|
})
|
|
} else {
|
|
Text("No \(homeData.pickedTab)")
|
|
}
|
|
}
|
|
|
|
}
|
|
.padding(.horizontal)
|
|
.frame(maxWidth: 300)
|
|
}
|
|
}
|
|
}
|