Improve display of results
This commit is contained in:
@ -5,10 +5,14 @@ struct ListPopup: View {
|
||||
@Environment(\.dismiss)
|
||||
var dismiss
|
||||
|
||||
let title: LocalizedStringKey
|
||||
|
||||
let items: [String]
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
Text(title)
|
||||
.font(.title)
|
||||
List {
|
||||
ForEach(items, id: \.self) { page in
|
||||
Text(page)
|
||||
|
@ -5,12 +5,14 @@ struct TextWithPopup: View {
|
||||
|
||||
let symbol: SFSymbol
|
||||
|
||||
let title: LocalizedStringKey
|
||||
|
||||
let text: LocalizedStringKey
|
||||
|
||||
let items: [String]
|
||||
|
||||
@State
|
||||
private var isHovering = false
|
||||
private var showSheet = false
|
||||
|
||||
var body: some View {
|
||||
HStack {
|
||||
@ -23,14 +25,69 @@ struct TextWithPopup: View {
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
if items.count > 0 {
|
||||
isHovering.toggle()
|
||||
showSheet.toggle()
|
||||
}
|
||||
}
|
||||
.sheet(isPresented: $isHovering) {
|
||||
ListPopup(items: items)
|
||||
.sheet(isPresented: $showSheet) {
|
||||
ListPopup(title: title, items: items)
|
||||
.onTapGesture {
|
||||
isHovering.toggle()
|
||||
showSheet.toggle()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct PopupWithList<ListContent>: View where ListContent: View {
|
||||
|
||||
let symbol: SFSymbol
|
||||
|
||||
let text: LocalizedStringKey
|
||||
|
||||
let canShowPopup: Bool
|
||||
|
||||
let content: ListContent
|
||||
|
||||
init(symbol: SFSymbol, text: LocalizedStringKey, canShowPopup: Bool, @ViewBuilder content: () -> ListContent) {
|
||||
self.symbol = symbol
|
||||
self.text = text
|
||||
self.canShowPopup = canShowPopup
|
||||
self.content = content()
|
||||
}
|
||||
|
||||
@State
|
||||
private var showSheet = false
|
||||
|
||||
var body: some View {
|
||||
HStack {
|
||||
Image(systemSymbol: symbol)
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(width: 16, height: 16)
|
||||
Text(text)
|
||||
}
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
if canShowPopup {
|
||||
showSheet.toggle()
|
||||
}
|
||||
}
|
||||
.sheet(isPresented: $showSheet) {
|
||||
Popup(content: content)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private struct Popup<Content>: View where Content: View {
|
||||
|
||||
@Environment(\.dismiss)
|
||||
var dismiss
|
||||
|
||||
let content: Content
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
content
|
||||
Button("Dismiss") { dismiss() }
|
||||
}.padding()
|
||||
}
|
||||
}
|
||||
|
@ -69,6 +69,7 @@ struct LocalizedPageContentView: View {
|
||||
let linkingPosts = content.posts.filter { $0.linkedPage == page }
|
||||
TextWithPopup(
|
||||
symbol: .ipadAndArrowForward,
|
||||
title: "Post linking to page",
|
||||
text: "\(linkingPosts.count) linking posts",
|
||||
items: linkingPosts.map { $0.title(in: language) })
|
||||
}.foregroundStyle(.secondary)
|
||||
|
@ -1,6 +1,23 @@
|
||||
import SwiftUI
|
||||
import SFSafeSymbols
|
||||
|
||||
private struct TextWithSymbol: Comparable, Identifiable {
|
||||
|
||||
let symbol: SFSymbol
|
||||
|
||||
let color: Color
|
||||
|
||||
let text: String
|
||||
|
||||
static func < (lhs: TextWithSymbol, rhs: TextWithSymbol) -> Bool {
|
||||
lhs.text < rhs.text
|
||||
}
|
||||
|
||||
var id: String {
|
||||
text
|
||||
}
|
||||
}
|
||||
|
||||
struct PageContentResultsView: View {
|
||||
|
||||
@Environment(\.language)
|
||||
@ -9,48 +26,100 @@ struct PageContentResultsView: View {
|
||||
@ObservedObject
|
||||
var results: PageGenerationResults
|
||||
|
||||
#warning("Rework to only show a single popup with all files, and indicate missing ones")
|
||||
private var totalFileCount: Int {
|
||||
results.usedFiles.count + results.missingFiles.count + results.missingLinkedFiles.count
|
||||
}
|
||||
|
||||
private var allFiles: [TextWithSymbol] {
|
||||
results.usedFiles.map {
|
||||
TextWithSymbol(
|
||||
symbol: $0.type.category.symbol,
|
||||
color: .blue,
|
||||
text: $0.id)
|
||||
}
|
||||
+ results.missingFiles.keys.map {
|
||||
TextWithSymbol(
|
||||
symbol: .questionmarkCircleFill,
|
||||
color: .red,
|
||||
text: $0)
|
||||
}
|
||||
+ results.missingLinkedFiles.keys.map {
|
||||
TextWithSymbol(
|
||||
symbol: .questionmarkCircleFill,
|
||||
color: .red,
|
||||
text: $0)
|
||||
}
|
||||
}
|
||||
|
||||
private var totalLinkCount: Int {
|
||||
results.externalLinks.count +
|
||||
results.missingLinkedPages.count +
|
||||
results.linkedPages.count
|
||||
}
|
||||
|
||||
private var allLinks: [TextWithSymbol] {
|
||||
results.externalLinks.map {
|
||||
TextWithSymbol(
|
||||
symbol: .network,
|
||||
color: .blue,
|
||||
text: $0)
|
||||
}
|
||||
+ results.missingLinkedPages.keys.map {
|
||||
TextWithSymbol(
|
||||
symbol: .questionmarkCircleFill,
|
||||
color: .red,
|
||||
text: $0)
|
||||
}
|
||||
+ results.linkedPages.map {
|
||||
TextWithSymbol(
|
||||
symbol: .docBadgePlus,
|
||||
color: .blue,
|
||||
text: $0.title(in: language))
|
||||
}
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
HStack {
|
||||
TextWithPopup(
|
||||
PopupWithList(
|
||||
symbol: .photoOnRectangleAngled,
|
||||
text: "\(totalFileCount) images and files",
|
||||
items: results.usedFiles.sorted().map { $0.id })
|
||||
.foregroundStyle(.secondary)
|
||||
text: "\(totalFileCount) files", canShowPopup: totalFileCount > 0) {
|
||||
Text("Files")
|
||||
.font(.title)
|
||||
List {
|
||||
ForEach(allFiles.sorted()) { file in
|
||||
HStack {
|
||||
Image(systemSymbol: file.symbol)
|
||||
.frame(width: 18)
|
||||
.foregroundStyle(file.color)
|
||||
Text(file.text)
|
||||
}
|
||||
}
|
||||
}
|
||||
.frame(minHeight: 400)
|
||||
}
|
||||
|
||||
TextWithPopup(
|
||||
symbol: .docBadgePlus,
|
||||
text: "\(results.linkedPages.count + results.missingLinkedPages.count) page links",
|
||||
items: results.linkedPages.sorted().map { $0.localized(in: language).title })
|
||||
.foregroundStyle(.secondary)
|
||||
PopupWithList(
|
||||
symbol: .photoOnRectangleAngled,
|
||||
text: "\(totalLinkCount) links", canShowPopup: totalLinkCount > 0) {
|
||||
Text("Links")
|
||||
.font(.title)
|
||||
List {
|
||||
ForEach(allLinks.sorted()) { file in
|
||||
HStack {
|
||||
Image(systemSymbol: file.symbol)
|
||||
.frame(width: 18)
|
||||
.foregroundStyle(file.color)
|
||||
Text(file.text)
|
||||
}
|
||||
}
|
||||
}
|
||||
.frame(minHeight: 400)
|
||||
}
|
||||
|
||||
TextWithPopup(
|
||||
symbol: .globe,
|
||||
text: "\(results.externalLinks.count) external links",
|
||||
items: results.externalLinks.sorted())
|
||||
.foregroundStyle(.secondary)
|
||||
|
||||
if !results.missingLinkedPages.isEmpty {
|
||||
TextWithPopup(
|
||||
symbol: .exclamationmarkTriangleFill,
|
||||
text: "\(results.missingLinkedPages.count) missing pages",
|
||||
items: results.missingLinkedPages.keys.sorted())
|
||||
.foregroundStyle(.red)
|
||||
}
|
||||
if !results.missingFiles.isEmpty {
|
||||
TextWithPopup(
|
||||
symbol: .exclamationmarkTriangleFill,
|
||||
text: "\(results.missingFiles.count) missing files",
|
||||
items: results.missingFiles.keys.sorted())
|
||||
.foregroundStyle(.red)
|
||||
}
|
||||
if !results.invalidCommands.isEmpty {
|
||||
TextWithPopup(
|
||||
symbol: .exclamationmarkTriangleFill,
|
||||
title: "Invalid commands",
|
||||
text: "\(results.invalidCommands.count) invalid commands",
|
||||
items: results.invalidCommands.map { $0.markdown }.sorted())
|
||||
.foregroundStyle(.red)
|
||||
|
Reference in New Issue
Block a user