Skip to content

Commit

Permalink
layout tweaks
Browse files Browse the repository at this point in the history
  • Loading branch information
hiroshihorie committed Feb 15, 2022
1 parent a72104d commit 5c5993e
Show file tree
Hide file tree
Showing 2 changed files with 188 additions and 34 deletions.
8 changes: 4 additions & 4 deletions LiveKitExample.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -678,7 +678,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 5;
CURRENT_PROJECT_VERSION = 6;
DEVELOPMENT_TEAM = J48VV6BZV9;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_PREVIEWS = YES;
Expand All @@ -691,7 +691,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 11.0;
MARKETING_VERSION = 1.0.2;
MARKETING_VERSION = 1.0.3;
PRODUCT_BUNDLE_IDENTIFIER = "io.livekit.example.Multiplatform-SwiftUI";
PRODUCT_NAME = LiveKitExample;
SDKROOT = macosx;
Expand All @@ -708,7 +708,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 5;
CURRENT_PROJECT_VERSION = 6;
DEVELOPMENT_TEAM = J48VV6BZV9;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_PREVIEWS = YES;
Expand All @@ -721,7 +721,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 11.0;
MARKETING_VERSION = 1.0.2;
MARKETING_VERSION = 1.0.3;
PRODUCT_BUNDLE_IDENTIFIER = "io.livekit.example.Multiplatform-SwiftUI";
PRODUCT_NAME = LiveKitExample;
SDKROOT = macosx;
Expand Down
214 changes: 184 additions & 30 deletions Shared/RoomView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ struct RoomView: View {
@State private var pinned: Bool = false
#endif

@State private var columns = 0.0
// @State private var itemCount = 0.0

func messageView(_ message: ExampleRoomMessage) -> some View {

Expand Down Expand Up @@ -146,7 +146,6 @@ struct RoomView: View {
func content(geometry: GeometryProxy) -> some View {

VStack {

if case .connecting(let connectMode) = roomCtx.connectionState,
case .reconnect(let reconnectMode) = connectMode {
Text("Re-connecting(\(String(describing: reconnectMode)))...")
Expand All @@ -155,42 +154,50 @@ struct RoomView: View {
.padding()
}

HorVStack(axis: geometry.isWide ? .horizontal : .vertical) {
HorVStack(axis: geometry.isTall ? .vertical : .horizontal, spacing: 5) {

Group {
if let focusParticipant = room.focusParticipant {
ParticipantView(participant: focusParticipant,
videoViewMode: appCtx.videoViewMode, onTap: ({ _ in
room.focusParticipant = nil
})).frame(maxWidth: .infinity, maxHeight: .infinity)
ZStack(alignment: .topTrailing) {
ParticipantView(participant: focusParticipant,
videoViewMode: appCtx.videoViewMode) { _ in
room.focusParticipant = nil
}
.overlay(RoundedRectangle(cornerRadius: 8)
.stroke(Color.orange.opacity(0.3), lineWidth: 5.0))
Text("FOCUSED")
.font(.system(size: 10))
.fontWeight(.bold)
.foregroundColor(Color.white)
.padding(.horizontal, 5)
.padding(.vertical, 2)
.background(Color.orange.opacity(0.3))
.cornerRadius(8)
.padding()
}
} else {
ScrollView(.vertical, showsIndicators: true) {
LazyVGrid(columns: (0...Int(max(0, columns))).map { _ in GridItem(.flexible()) },
alignment: .center,
spacing: 10) {
ForEach(room.allParticipants.values) { participant in
ParticipantView(participant: participant,
videoViewMode: appCtx.videoViewMode, onTap: ({ participant in
room.focusParticipant = participant
})).aspectRatio(1, contentMode: .fit)
}
}.padding()
ParticipantLayout(room.allParticipants.values, spacing: 5) { participant in
ParticipantView(participant: participant,
videoViewMode: appCtx.videoViewMode) { participant in
room.focusParticipant = participant

}
}
}
}
.frame(
minWidth: 0,
maxWidth: .infinity,
minHeight: 0,
maxHeight: .infinity,
alignment: .topLeading
maxHeight: .infinity
)
// Show messages view if enabled
if room.showMessagesView {
messagesView(geometry: geometry)
}
}
}
.padding(5)
}

var body: some View {
Expand All @@ -207,16 +214,6 @@ struct RoomView: View {
}
.pickerStyle(SegmentedPickerStyle())

if room.allParticipants.count > 1 {
Slider(
value: $columns,
in: 0...Double(room.allParticipants.count - 1),
step: 1
)
.frame(idealWidth: 100)
Text("\(Int(columns) + 1)")
}

Spacer()

Group {
Expand Down Expand Up @@ -390,6 +387,135 @@ struct RoomView: View {
}
}

struct ParticipantLayout<Content: View>: View {

let views: [AnyView]
let spacing: CGFloat?

init<Data: RandomAccessCollection>(
_ data: Data,
id: KeyPath<Data.Element, Data.Element> = \.self,
spacing: CGFloat? = nil,
@ViewBuilder content: @escaping (Data.Element) -> Content) {
self.spacing = spacing
self.views = data.map { AnyView(content($0[keyPath: id])) }
}

func computeColumn(with geometry: GeometryProxy) -> (x: Int, y: Int) {
let sqr = Double(views.count).squareRoot()
let r: [Int] = [Int(sqr.rounded()), Int(sqr.rounded(.up))]
let c = geometry.isTall ? r : r.reversed()
return (x: c[0], y: c[1])
}

func grid(axis: Axis) -> some View {
ScrollView([ axis == .vertical ? .vertical : .horizontal ]) {
HorVGrid(axis: axis, columns: [GridItem(.flexible())], spacing: spacing) {
ForEach(0..<views.count, id: \.self) { i in
views[i]
.aspectRatio(1, contentMode: .fill)
}
}
}
}

var body: some View {
GeometryReader { geometry in
if views.isEmpty {
EmptyView()
} else if geometry.size.width <= 300 {
grid(axis: .vertical)
} else if geometry.size.height <= 300 {
grid(axis: .horizontal)
} else {

let verticalWhenTall: Axis = geometry.isTall ? .vertical : .horizontal
let horizontalWhenTall: Axis = geometry.isTall ? .horizontal : .vertical

switch views.count {
// simply return first view
case 1: views[0]
case 3: HorVStack(axis: verticalWhenTall, spacing: spacing) {
views[0]
HorVStack(axis: horizontalWhenTall, spacing: spacing) {
views[1]
views[2]
}
}
case 5: HorVStack(axis: verticalWhenTall, spacing: spacing) {
views[0]
if geometry.isTall {
HStack(spacing: spacing) {
views[1]
views[2]
}
HStack(spacing: spacing) {
views[3]
views[4]

}
} else {
VStack(spacing: spacing) {
views[1]
views[3]
}
VStack(spacing: spacing) {
views[2]
views[4]
}
}
}
// case 6:
// if geometry.isTall {
// VStack {
// HStack {
// views[0]
// views[1]
// }
// HStack {
// views[2]
// views[3]
// }
// HStack {
// views[4]
// views[5]
// }
// }
// } else {
// VStack {
// HStack {
// views[0]
// views[1]
// views[2]
// }
// HStack {
// views[3]
// views[4]
// views[5]
// }
// }
// }
default:
let c = computeColumn(with: geometry)
VStack(spacing: spacing) {
ForEach(0...(c.y - 1), id: \.self) { y in
HStack(spacing: spacing) {
ForEach(0...(c.x - 1), id: \.self) { x in
let index = (y * c.x) + x
if index < views.count {
views[index]
}
}
}
}
}

}
}
}
}
}

struct HorVStack<Content: View>: View {
let axis: Axis
let horizontalAlignment: HorizontalAlignment
Expand Down Expand Up @@ -421,6 +547,34 @@ struct HorVStack<Content: View>: View {
}
}

struct HorVGrid<Content: View>: View {
let axis: Axis
let spacing: CGFloat?
let content: () -> Content
let columns: [GridItem]

init(axis: Axis = .horizontal,
columns: [GridItem],
spacing: CGFloat? = nil,
@ViewBuilder content: @escaping () -> Content) {

self.axis = axis
self.spacing = spacing
self.columns = columns
self.content = content
}

var body: some View {
Group {
if axis == .vertical {
LazyVGrid(columns: columns, spacing: spacing, content: content)
} else {
LazyHGrid(rows: columns, spacing: spacing, content: content)
}
}
}
}

extension GeometryProxy {

public var isTall: Bool {
Expand Down

0 comments on commit 5c5993e

Please sign in to comment.