177 lines
5.6 KiB
Swift
177 lines
5.6 KiB
Swift
import Libbox
|
|
import Library
|
|
import SwiftUI
|
|
|
|
@MainActor
|
|
public struct GroupView: View {
|
|
@State private var group: OutboundGroup
|
|
@State private var geometryWidth: CGFloat = 300
|
|
@State private var alert: Alert?
|
|
|
|
|
|
public init(_ group: OutboundGroup) {
|
|
_group = State(initialValue: group)
|
|
}
|
|
|
|
private var title: some View {
|
|
HStack {
|
|
// Text(group.tag)
|
|
// .font(.headline)
|
|
//Text()
|
|
Text(group.tag)
|
|
.font(.subheadline)
|
|
.foregroundColor(.secondary)
|
|
Text("\(group.items.count)")
|
|
.font(.subheadline)
|
|
.padding(EdgeInsets(top: 2, leading: 4, bottom: 2, trailing: 4))
|
|
.background(Color.gray.opacity(0.5))
|
|
.cornerRadius(4)
|
|
Button {
|
|
group.isExpand = !group.isExpand
|
|
Task {
|
|
await setGroupExpand()
|
|
}
|
|
} label: {
|
|
HStack{
|
|
|
|
if group.isExpand {
|
|
Image(systemName: "arrow.down.to.line")
|
|
Text("收起").font(.subheadline)
|
|
} else {
|
|
Image(systemName: "arrow.up.to.line")
|
|
Text("展开").font(.subheadline)
|
|
}
|
|
|
|
}
|
|
}
|
|
#if os(macOS) || os(tvOS)
|
|
.buttonStyle(.plain)
|
|
#endif
|
|
Button {
|
|
Task {
|
|
await doURLTest()
|
|
}
|
|
} label: {
|
|
Image(systemName: "bolt.fill")
|
|
Text("测速").font(.subheadline)
|
|
}
|
|
#if os(macOS) || os(tvOS)
|
|
.buttonStyle(.plain)
|
|
#endif
|
|
}
|
|
.alertBinding($alert)
|
|
.padding([.top, .bottom], 10)
|
|
}
|
|
|
|
public var body: some View {
|
|
Section {
|
|
if group.isExpand {
|
|
LazyVGrid(columns: Array(repeating: GridItem(.flexible()),
|
|
count: explandColumnCount()))
|
|
{
|
|
ForEach(group.items, id: \.tag) { it in
|
|
GroupItemView($group, it)
|
|
}
|
|
}
|
|
} else {
|
|
VStack(spacing: 5) {
|
|
ForEach(Array(itemGroups.enumerated()), id: \.offset) { items in
|
|
HStack(spacing: 5) {
|
|
ForEach(items.element, id: \.tag) { it in
|
|
ZStack {
|
|
Rectangle()
|
|
.fill(it.delayColor)
|
|
if it.tag == group.selected {
|
|
Rectangle()
|
|
.fill(Color.white)
|
|
#if !os(tvOS)
|
|
.frame(width: 5, height: 5)
|
|
#else
|
|
.frame(width: 15, height: 15)
|
|
#endif
|
|
}
|
|
}
|
|
#if !os(tvOS)
|
|
.frame(width: 10, height: 10)
|
|
#else
|
|
.frame(width: 30, height: 30)
|
|
#endif
|
|
}
|
|
}.frame(maxWidth: .infinity, alignment: .topLeading)
|
|
}
|
|
}
|
|
}
|
|
} header: {
|
|
//title .frame(maxWidth: .infinity, alignment: .topLeading)
|
|
}
|
|
.background {
|
|
/* GeometryReader { geometry in
|
|
Rectangle()
|
|
.fill(.clear)
|
|
.frame(height: 1)
|
|
.onChangeCompat(of: geometry.size.width) { newValue in
|
|
geometryWidth = newValue
|
|
}
|
|
.onAppear {
|
|
geometryWidth = geometry.size.width
|
|
}
|
|
}.padding() */
|
|
}.padding(.leading,-18.0)
|
|
}
|
|
|
|
private var itemGroups: [[OutboundGroupItem]] {
|
|
let count: Int
|
|
#if os(tvOS)
|
|
count = Int(Int(geometryWidth) / 40)
|
|
#else
|
|
count = Int(Int(geometryWidth) / 20)
|
|
#endif
|
|
if count == 0 {
|
|
return [group.items]
|
|
} else {
|
|
return group.items.chunked(
|
|
into: count
|
|
)
|
|
}
|
|
}
|
|
|
|
private func explandColumnCount() -> Int {
|
|
let standardCount = Int(Int(geometryWidth) / 180)
|
|
#if os(iOS)
|
|
return standardCount < 2 ? 1 : standardCount
|
|
#elseif os(tvOS)
|
|
return 4
|
|
#else
|
|
return standardCount < 1 ? 1 : standardCount
|
|
#endif
|
|
}
|
|
|
|
private nonisolated func doURLTest() async {
|
|
do {
|
|
try await LibboxNewStandaloneCommandClient()!.urlTest(group.tag)
|
|
} catch {
|
|
await MainActor.run {
|
|
alert = Alert(error)
|
|
}
|
|
}
|
|
}
|
|
|
|
private nonisolated func setGroupExpand() async {
|
|
do {
|
|
try await LibboxNewStandaloneCommandClient()!.setGroupExpand(group.tag, isExpand: group.isExpand)
|
|
} catch {
|
|
await MainActor.run {
|
|
alert = Alert(error)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private extension Array {
|
|
func chunked(into size: Int) -> [[Element]] {
|
|
stride(from: 0, to: count, by: size).map {
|
|
Array(self[$0 ..< Swift.min($0 + size, count)])
|
|
}
|
|
}
|
|
}
|