mirror of
https://github.com/nimbold/Firelink.git
synced 2026-08-25 10:07:44 +00:00
fix: align download table columns
This commit is contained in:
@@ -214,6 +214,7 @@ private struct DownloadTable: View {
|
|||||||
@State private var sortColumn: DownloadColumn = .dateAdded
|
@State private var sortColumn: DownloadColumn = .dateAdded
|
||||||
@State private var sortDirection: SortDirection = .descending
|
@State private var sortDirection: SortDirection = .descending
|
||||||
@State private var pendingDeleteItem: DownloadItem?
|
@State private var pendingDeleteItem: DownloadItem?
|
||||||
|
@State private var resizeBaseWidths: [DownloadColumn: CGFloat] = [:]
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(spacing: 0) {
|
VStack(spacing: 0) {
|
||||||
@@ -304,42 +305,62 @@ private struct DownloadTable: View {
|
|||||||
HStack(spacing: 0) {
|
HStack(spacing: 0) {
|
||||||
ForEach(orderedVisibleColumns) { column in
|
ForEach(orderedVisibleColumns) { column in
|
||||||
HStack(spacing: 0) {
|
HStack(spacing: 0) {
|
||||||
Button {
|
ZStack(alignment: .trailing) {
|
||||||
if sortColumn == column {
|
Button {
|
||||||
sortDirection.toggle()
|
|
||||||
} else {
|
|
||||||
sortColumn = column
|
|
||||||
sortDirection = .ascending
|
|
||||||
}
|
|
||||||
} label: {
|
|
||||||
HStack(spacing: 4) {
|
|
||||||
Text(column.rawValue)
|
|
||||||
.font(.caption.weight(.semibold))
|
|
||||||
.lineLimit(1)
|
|
||||||
if sortColumn == column {
|
if sortColumn == column {
|
||||||
Image(systemName: sortDirection == .ascending ? "chevron.up" : "chevron.down")
|
sortDirection.toggle()
|
||||||
.font(.caption2)
|
} else {
|
||||||
|
sortColumn = column
|
||||||
|
sortDirection = .ascending
|
||||||
}
|
}
|
||||||
Spacer(minLength: 0)
|
} label: {
|
||||||
}
|
HStack(spacing: 4) {
|
||||||
.padding(.horizontal, 8)
|
Spacer(minLength: 0)
|
||||||
.frame(width: max(44, width(for: column) - 8), height: 34, alignment: .leading)
|
Text(column.rawValue)
|
||||||
}
|
.font(.caption.weight(.semibold))
|
||||||
.buttonStyle(.plain)
|
.lineLimit(1)
|
||||||
|
.truncationMode(.tail)
|
||||||
Rectangle()
|
.multilineTextAlignment(.center)
|
||||||
.fill(.secondary.opacity(0.18))
|
.layoutPriority(1)
|
||||||
.frame(width: 1, height: 20)
|
if sortColumn == column {
|
||||||
.padding(.horizontal, 3)
|
Image(systemName: sortDirection == .ascending ? "chevron.up" : "chevron.down")
|
||||||
.contentShape(Rectangle())
|
.font(.caption2)
|
||||||
.gesture(
|
|
||||||
DragGesture(minimumDistance: 1)
|
|
||||||
.onChanged { value in
|
|
||||||
columnWidths[column] = max(70, column.width + value.translation.width)
|
|
||||||
}
|
}
|
||||||
)
|
Spacer(minLength: 0)
|
||||||
|
}
|
||||||
|
.padding(.horizontal, 8)
|
||||||
|
.frame(width: width(for: column), height: 34, alignment: .center)
|
||||||
|
.clipped()
|
||||||
|
}
|
||||||
|
.buttonStyle(.plain)
|
||||||
|
|
||||||
|
Rectangle()
|
||||||
|
.fill(.secondary.opacity(0.18))
|
||||||
|
.frame(width: 1, height: 20)
|
||||||
|
.frame(width: 8, height: 34)
|
||||||
|
.contentShape(Rectangle())
|
||||||
|
.onHover { isHovering in
|
||||||
|
if isHovering {
|
||||||
|
NSCursor.resizeLeftRight.push()
|
||||||
|
} else {
|
||||||
|
NSCursor.pop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.gesture(
|
||||||
|
DragGesture(minimumDistance: 1)
|
||||||
|
.onChanged { value in
|
||||||
|
let baseWidth = resizeBaseWidths[column] ?? width(for: column)
|
||||||
|
resizeBaseWidths[column] = baseWidth
|
||||||
|
columnWidths[column] = max(70, baseWidth + value.translation.width)
|
||||||
|
}
|
||||||
|
.onEnded { _ in
|
||||||
|
resizeBaseWidths[column] = nil
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.frame(width: width(for: column), height: 34)
|
||||||
|
.clipped()
|
||||||
}
|
}
|
||||||
.frame(width: width(for: column), height: 34)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.frame(minWidth: totalWidth, alignment: .leading)
|
.frame(minWidth: totalWidth, alignment: .leading)
|
||||||
@@ -493,9 +514,10 @@ private struct DownloadRow: View {
|
|||||||
HStack(alignment: .top, spacing: 0) {
|
HStack(alignment: .top, spacing: 0) {
|
||||||
ForEach(visibleColumns) { column in
|
ForEach(visibleColumns) { column in
|
||||||
cell(for: column)
|
cell(for: column)
|
||||||
.frame(width: columnWidth(column), alignment: .leading)
|
|
||||||
.padding(.horizontal, 8)
|
.padding(.horizontal, 8)
|
||||||
.padding(.vertical, 8)
|
.padding(.vertical, 8)
|
||||||
|
.frame(width: columnWidth(column), alignment: alignment(for: column))
|
||||||
|
.clipped()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -510,57 +532,83 @@ private struct DownloadRow: View {
|
|||||||
.foregroundStyle(categoryColor)
|
.foregroundStyle(categoryColor)
|
||||||
.frame(width: 22)
|
.frame(width: 22)
|
||||||
VStack(alignment: .leading, spacing: 6) {
|
VStack(alignment: .leading, spacing: 6) {
|
||||||
HStack {
|
Text(item.fileName)
|
||||||
Text(item.fileName)
|
.font(.headline)
|
||||||
.font(.headline)
|
.lineLimit(1)
|
||||||
.lineLimit(1)
|
.truncationMode(.tail)
|
||||||
}
|
|
||||||
Text(item.url.absoluteString)
|
Text(item.url.absoluteString)
|
||||||
.font(.caption)
|
.font(.caption)
|
||||||
.foregroundStyle(.secondary)
|
.foregroundStyle(.secondary)
|
||||||
.lineLimit(1)
|
.lineLimit(1)
|
||||||
|
.truncationMode(.tail)
|
||||||
}
|
}
|
||||||
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
}
|
}
|
||||||
case .size:
|
case .size:
|
||||||
Text(ByteFormatter.string(item.sizeBytes))
|
Text(ByteFormatter.string(item.sizeBytes))
|
||||||
.monospacedDigit()
|
.monospacedDigit()
|
||||||
|
.lineLimit(1)
|
||||||
|
.truncationMode(.tail)
|
||||||
case .status:
|
case .status:
|
||||||
Text(item.status.rawValue)
|
Text(item.status.rawValue)
|
||||||
|
.lineLimit(1)
|
||||||
|
.truncationMode(.tail)
|
||||||
case .progress:
|
case .progress:
|
||||||
Text(progressStatusText)
|
Text(progressStatusText)
|
||||||
.monospacedDigit()
|
.monospacedDigit()
|
||||||
.foregroundStyle(statusColor)
|
.foregroundStyle(statusColor)
|
||||||
|
.lineLimit(1)
|
||||||
|
.truncationMode(.tail)
|
||||||
case .lastTry:
|
case .lastTry:
|
||||||
Text(formatted(item.lastTryAt))
|
Text(formatted(item.lastTryAt))
|
||||||
|
.lineLimit(1)
|
||||||
|
.truncationMode(.tail)
|
||||||
case .dateAdded:
|
case .dateAdded:
|
||||||
Text(formatted(item.createdAt))
|
Text(formatted(item.createdAt))
|
||||||
|
.lineLimit(1)
|
||||||
|
.truncationMode(.tail)
|
||||||
case .category:
|
case .category:
|
||||||
Text(item.category.rawValue)
|
Text(item.category.rawValue)
|
||||||
|
.lineLimit(1)
|
||||||
|
.truncationMode(.tail)
|
||||||
case .connections:
|
case .connections:
|
||||||
Text("\(item.connectionsPerServer)")
|
Text("\(item.connectionsPerServer)")
|
||||||
.monospacedDigit()
|
.monospacedDigit()
|
||||||
|
.lineLimit(1)
|
||||||
case .liveConnections:
|
case .liveConnections:
|
||||||
Text("\(item.connectionCount)")
|
Text("\(item.connectionCount)")
|
||||||
.monospacedDigit()
|
.monospacedDigit()
|
||||||
|
.lineLimit(1)
|
||||||
case .speed:
|
case .speed:
|
||||||
Text(item.speedText)
|
Text(item.speedText)
|
||||||
|
.lineLimit(1)
|
||||||
|
.truncationMode(.tail)
|
||||||
case .eta:
|
case .eta:
|
||||||
Text(item.etaText)
|
Text(item.etaText)
|
||||||
|
.lineLimit(1)
|
||||||
|
.truncationMode(.tail)
|
||||||
case .destination:
|
case .destination:
|
||||||
Text(item.destinationPath)
|
Text(item.destinationPath)
|
||||||
.font(.system(.caption, design: .monospaced))
|
.font(.system(.caption, design: .monospaced))
|
||||||
.lineLimit(2)
|
.lineLimit(1)
|
||||||
|
.truncationMode(.tail)
|
||||||
case .url:
|
case .url:
|
||||||
Text(item.url.absoluteString)
|
Text(item.url.absoluteString)
|
||||||
.font(.system(.caption, design: .monospaced))
|
.font(.system(.caption, design: .monospaced))
|
||||||
.lineLimit(2)
|
.lineLimit(1)
|
||||||
|
.truncationMode(.tail)
|
||||||
case .message:
|
case .message:
|
||||||
Text(item.message)
|
Text(item.message)
|
||||||
.foregroundStyle(.secondary)
|
.foregroundStyle(.secondary)
|
||||||
.lineLimit(2)
|
.lineLimit(1)
|
||||||
|
.truncationMode(.tail)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func alignment(for column: DownloadColumn) -> Alignment {
|
||||||
|
column == .fileName ? .leading : .center
|
||||||
|
}
|
||||||
|
|
||||||
private var categoryColor: Color {
|
private var categoryColor: Color {
|
||||||
switch item.category {
|
switch item.category {
|
||||||
case .musics: .pink
|
case .musics: .pink
|
||||||
|
|||||||
Reference in New Issue
Block a user