Compare commits
2 Commits
a4710d525b
...
d779b7a42c
Author | SHA1 | Date | |
---|---|---|---|
|
d779b7a42c | ||
|
f968ccad29 |
@ -207,7 +207,8 @@
|
|||||||
E2F3B3982DC54F9400CFA712 /* ChangeObservingItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2F3B3972DC54F8600CFA712 /* ChangeObservingItem.swift */; };
|
E2F3B3982DC54F9400CFA712 /* ChangeObservingItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2F3B3972DC54F8600CFA712 /* ChangeObservingItem.swift */; };
|
||||||
E2F3B39C2DC5542E00CFA712 /* LabelEditingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2F3B39B2DC5542E00CFA712 /* LabelEditingView.swift */; };
|
E2F3B39C2DC5542E00CFA712 /* LabelEditingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2F3B39B2DC5542E00CFA712 /* LabelEditingView.swift */; };
|
||||||
E2F3B39E2DC55B1C00CFA712 /* LabelCreationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2F3B39D2DC55B1C00CFA712 /* LabelCreationView.swift */; };
|
E2F3B39E2DC55B1C00CFA712 /* LabelCreationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2F3B39D2DC55B1C00CFA712 /* LabelCreationView.swift */; };
|
||||||
E2F3B3A22DC769C300CFA712 /* DeleteButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2F3B3A12DC769BF00CFA712 /* DeleteButton.swift */; };
|
E2F3B3A22DC769C300CFA712 /* ColoredButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2F3B3A12DC769BF00CFA712 /* ColoredButton.swift */; };
|
||||||
|
E2F3B3A42DC7DC2400CFA712 /* GenerationIssuesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2F3B3A32DC7DC1F00CFA712 /* GenerationIssuesView.swift */; };
|
||||||
E2FD1D0D2D2DBBA600B48627 /* LinkPreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2FD1D0C2D2DBBA100B48627 /* LinkPreview.swift */; };
|
E2FD1D0D2D2DBBA600B48627 /* LinkPreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2FD1D0C2D2DBBA100B48627 /* LinkPreview.swift */; };
|
||||||
E2FD1D192D2DC4F500B48627 /* LoadingContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2FD1D182D2DC4F500B48627 /* LoadingContext.swift */; };
|
E2FD1D192D2DC4F500B48627 /* LoadingContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2FD1D182D2DC4F500B48627 /* LoadingContext.swift */; };
|
||||||
E2FD1D1B2D2DC63800B48627 /* LinkPreviewDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2FD1D1A2D2DC62C00B48627 /* LinkPreviewDetailView.swift */; };
|
E2FD1D1B2D2DC63800B48627 /* LinkPreviewDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2FD1D1A2D2DC62C00B48627 /* LinkPreviewDetailView.swift */; };
|
||||||
@ -491,7 +492,8 @@
|
|||||||
E2F3B3972DC54F8600CFA712 /* ChangeObservingItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChangeObservingItem.swift; sourceTree = "<group>"; };
|
E2F3B3972DC54F8600CFA712 /* ChangeObservingItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChangeObservingItem.swift; sourceTree = "<group>"; };
|
||||||
E2F3B39B2DC5542E00CFA712 /* LabelEditingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelEditingView.swift; sourceTree = "<group>"; };
|
E2F3B39B2DC5542E00CFA712 /* LabelEditingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelEditingView.swift; sourceTree = "<group>"; };
|
||||||
E2F3B39D2DC55B1C00CFA712 /* LabelCreationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelCreationView.swift; sourceTree = "<group>"; };
|
E2F3B39D2DC55B1C00CFA712 /* LabelCreationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelCreationView.swift; sourceTree = "<group>"; };
|
||||||
E2F3B3A12DC769BF00CFA712 /* DeleteButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeleteButton.swift; sourceTree = "<group>"; };
|
E2F3B3A12DC769BF00CFA712 /* ColoredButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColoredButton.swift; sourceTree = "<group>"; };
|
||||||
|
E2F3B3A32DC7DC1F00CFA712 /* GenerationIssuesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GenerationIssuesView.swift; sourceTree = "<group>"; };
|
||||||
E2FD1D0C2D2DBBA100B48627 /* LinkPreview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkPreview.swift; sourceTree = "<group>"; };
|
E2FD1D0C2D2DBBA100B48627 /* LinkPreview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkPreview.swift; sourceTree = "<group>"; };
|
||||||
E2FD1D182D2DC4F500B48627 /* LoadingContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingContext.swift; sourceTree = "<group>"; };
|
E2FD1D182D2DC4F500B48627 /* LoadingContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingContext.swift; sourceTree = "<group>"; };
|
||||||
E2FD1D1A2D2DC62C00B48627 /* LinkPreviewDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkPreviewDetailView.swift; sourceTree = "<group>"; };
|
E2FD1D1A2D2DC62C00B48627 /* LinkPreviewDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkPreviewDetailView.swift; sourceTree = "<group>"; };
|
||||||
@ -601,6 +603,7 @@
|
|||||||
E20BCCA02D53985500B8DBEB /* Generation */ = {
|
E20BCCA02D53985500B8DBEB /* Generation */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
E2F3B3A32DC7DC1F00CFA712 /* GenerationIssuesView.swift */,
|
||||||
E20BCCAE2D53F4A500B8DBEB /* GenerationStringIssuesView.swift */,
|
E20BCCAE2D53F4A500B8DBEB /* GenerationStringIssuesView.swift */,
|
||||||
E20BCCAC2D53F48100B8DBEB /* IssueStatus.swift */,
|
E20BCCAC2D53F48100B8DBEB /* IssueStatus.swift */,
|
||||||
E20BCCAA2D53B85300B8DBEB /* GenerationResultsIssueView.swift */,
|
E20BCCAA2D53B85300B8DBEB /* GenerationResultsIssueView.swift */,
|
||||||
@ -831,7 +834,7 @@
|
|||||||
E2A21C372CB9A4F10060935B /* Generic */ = {
|
E2A21C372CB9A4F10060935B /* Generic */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
E2F3B3A12DC769BF00CFA712 /* DeleteButton.swift */,
|
E2F3B3A12DC769BF00CFA712 /* ColoredButton.swift */,
|
||||||
E229902F2D0F75CF009F8D77 /* BoolPropertyView.swift */,
|
E229902F2D0F75CF009F8D77 /* BoolPropertyView.swift */,
|
||||||
E22990312D0F7678009F8D77 /* DatePropertyView.swift */,
|
E22990312D0F7678009F8D77 /* DatePropertyView.swift */,
|
||||||
E29D312F2D03A2BD0051B7F4 /* DescriptionField.swift */,
|
E29D312F2D03A2BD0051B7F4 /* DescriptionField.swift */,
|
||||||
@ -1452,7 +1455,7 @@
|
|||||||
E25DA58B2D020C9500AEF16D /* PageImage.swift in Sources */,
|
E25DA58B2D020C9500AEF16D /* PageImage.swift in Sources */,
|
||||||
E2521DFC2D5020BE00C56662 /* PostContentGenerator.swift in Sources */,
|
E2521DFC2D5020BE00C56662 /* PostContentGenerator.swift in Sources */,
|
||||||
E21850232CF10C850090B18B /* TagSelectionView.swift in Sources */,
|
E21850232CF10C850090B18B /* TagSelectionView.swift in Sources */,
|
||||||
E2F3B3A22DC769C300CFA712 /* DeleteButton.swift in Sources */,
|
E2F3B3A22DC769C300CFA712 /* ColoredButton.swift in Sources */,
|
||||||
E2A21C332CB5BCAC0060935B /* PageContentView.swift in Sources */,
|
E2A21C332CB5BCAC0060935B /* PageContentView.swift in Sources */,
|
||||||
E22990402D0F95EC009F8D77 /* FolderOnDiskPropertyView.swift in Sources */,
|
E22990402D0F95EC009F8D77 /* FolderOnDiskPropertyView.swift in Sources */,
|
||||||
E2FE0F422D2B4821002963B7 /* OtherCodeBlock.swift in Sources */,
|
E2FE0F422D2B4821002963B7 /* OtherCodeBlock.swift in Sources */,
|
||||||
@ -1560,6 +1563,7 @@
|
|||||||
E2FE0F6C2D2D335E002963B7 /* LocalizedPageSettingsView.swift in Sources */,
|
E2FE0F6C2D2D335E002963B7 /* LocalizedPageSettingsView.swift in Sources */,
|
||||||
E2B85F572C4BD0BB0047CD0C /* Binding+Extension.swift in Sources */,
|
E2B85F572C4BD0BB0047CD0C /* Binding+Extension.swift in Sources */,
|
||||||
E2B85F432C4294F60047CD0C /* FeedEntry.swift in Sources */,
|
E2B85F432C4294F60047CD0C /* FeedEntry.swift in Sources */,
|
||||||
|
E2F3B3A42DC7DC2400CFA712 /* GenerationIssuesView.swift in Sources */,
|
||||||
E25DA56D2D00EBCF00AEF16D /* NavigationBarSettingsView.swift in Sources */,
|
E25DA56D2D00EBCF00AEF16D /* NavigationBarSettingsView.swift in Sources */,
|
||||||
E25DA5272CFF745700AEF16D /* URL+Extensions.swift in Sources */,
|
E25DA5272CFF745700AEF16D /* URL+Extensions.swift in Sources */,
|
||||||
E2FE0F642D2C2F4D002963B7 /* ButtonBlock.swift in Sources */,
|
E2FE0F642D2C2F4D002963B7 /* ButtonBlock.swift in Sources */,
|
||||||
|
@ -51,20 +51,24 @@ struct FileDetailView: View {
|
|||||||
text: "A file that can be used in a post or page")
|
text: "A file that can be used in a post or page")
|
||||||
|
|
||||||
GenericPropertyView(title: "Actions") {
|
GenericPropertyView(title: "Actions") {
|
||||||
HStack(spacing: 10) {
|
ColoredButton(icon: .folder, text: "Show in folder", action: showFileInFinder)
|
||||||
ButtonIcon(.folder, action: showFileInFinder)
|
ColoredButton(icon: .arrowClockwise, text: "Mark file as changed", action: markFileAsChanged)
|
||||||
ButtonIcon(.arrowClockwise, action: markFileAsChanged)
|
if file.isExternallyStored {
|
||||||
if file.isExternallyStored {
|
ColoredButton(
|
||||||
ButtonIcon(.squareAndArrowDown, action: replaceFile)
|
icon: .squareAndArrowDown,
|
||||||
} else {
|
text: "Convert to internal file",
|
||||||
ButtonIcon(.arrowLeftArrowRight, action: replaceFile)
|
action: replaceFile)
|
||||||
ButtonIcon(.squareDashed, action: convertToExternal)
|
} else {
|
||||||
}
|
ColoredButton(
|
||||||
ButtonIcon(.trash, action: deleteFile)
|
icon: .arrowLeftArrowRight,
|
||||||
.foregroundStyle(.red)
|
text: "Replace file",
|
||||||
|
action: replaceFile)
|
||||||
|
ColoredButton(
|
||||||
|
icon: .squareDashed,
|
||||||
|
text: "Convert to external file",
|
||||||
|
action: convertToExternal)
|
||||||
}
|
}
|
||||||
.buttonStyle(.plain)
|
ColoredButton(delete: deleteFile)
|
||||||
.foregroundStyle(.blue)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IdPropertyView(
|
IdPropertyView(
|
||||||
|
@ -86,10 +86,16 @@ struct GenerationContentView: View {
|
|||||||
text: "draft posts",
|
text: "draft posts",
|
||||||
statusWhenNonEmpty: .warning,
|
statusWhenNonEmpty: .warning,
|
||||||
items: draftPosts) { $0.id }
|
items: draftPosts) { $0.id }
|
||||||
GenerationStringIssuesView(
|
GenerationIssuesView(
|
||||||
text: "additional output files",
|
text: "additional output files",
|
||||||
statusWhenNonEmpty: .warning,
|
statusWhenNonEmpty: .warning,
|
||||||
items: content.results.unusedFilesInOutput)
|
items: $content.results.unusedFilesInOutput) { filePath in
|
||||||
|
HStack {
|
||||||
|
Text(filePath)
|
||||||
|
Spacer()
|
||||||
|
Button("Delete", action: { delete(unusedFile: filePath) })
|
||||||
|
}
|
||||||
|
}
|
||||||
GenerationStringIssuesView(
|
GenerationStringIssuesView(
|
||||||
text: "inaccessible files",
|
text: "inaccessible files",
|
||||||
items: content.results.inaccessibleFiles) { $0.id }
|
items: content.results.inaccessibleFiles) { $0.id }
|
||||||
@ -134,6 +140,13 @@ struct GenerationContentView: View {
|
|||||||
}
|
}
|
||||||
}.padding()
|
}.padding()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func delete(unusedFile: String) {
|
||||||
|
guard content.storage.deleteInOutputFolder(unusedFile) else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
content.results.unusedFilesInOutput.remove(unusedFile)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#Preview {
|
#Preview {
|
||||||
|
65
CHDataManagement/Views/Generation/GenerationIssuesView.swift
Normal file
65
CHDataManagement/Views/Generation/GenerationIssuesView.swift
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct GenerationIssuesView<S, T, V>: View where S: Collection, T: Hashable & Comparable, V: View, S.Element == T {
|
||||||
|
|
||||||
|
let text: String
|
||||||
|
|
||||||
|
let statusWhenNonEmpty: IssueStatus
|
||||||
|
|
||||||
|
@Binding
|
||||||
|
var items: S
|
||||||
|
|
||||||
|
let map: (T) -> V
|
||||||
|
|
||||||
|
@State
|
||||||
|
private var showList = false
|
||||||
|
|
||||||
|
var status: IssueStatus {
|
||||||
|
items.isEmpty ? .nominal : statusWhenNonEmpty
|
||||||
|
}
|
||||||
|
|
||||||
|
init(text: String, statusWhenNonEmpty: IssueStatus = .error, items: Binding<S>, map: @escaping (T) -> V) {
|
||||||
|
self.text = text
|
||||||
|
self.statusWhenNonEmpty = statusWhenNonEmpty
|
||||||
|
self._items = items
|
||||||
|
self.map = map
|
||||||
|
}
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
HStack {
|
||||||
|
Button(action: showListIfNonEmpty) {
|
||||||
|
Image(systemSymbol: status.symbol)
|
||||||
|
.foregroundStyle(status.color)
|
||||||
|
}.buttonStyle(.plain)
|
||||||
|
Text("\(items.count) \(text)")
|
||||||
|
}
|
||||||
|
.sheet(isPresented: $showList) {
|
||||||
|
VStack {
|
||||||
|
Text("\(items.count) \(text)")
|
||||||
|
.font(.title)
|
||||||
|
List(items.sorted(), id: \.self) { item in
|
||||||
|
map(item)
|
||||||
|
}
|
||||||
|
.frame(minHeight: 400)
|
||||||
|
Button("Close") { showList = false }
|
||||||
|
}.padding()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func showListIfNonEmpty() {
|
||||||
|
guard !items.isEmpty else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
showList = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension GenerationIssuesView where S == Set<String>, V == Text {
|
||||||
|
|
||||||
|
init(text: String, statusWhenNonEmpty: IssueStatus = .error, items: Binding<Set<String>>) {
|
||||||
|
self.text = text
|
||||||
|
self.statusWhenNonEmpty = statusWhenNonEmpty
|
||||||
|
self._items = items
|
||||||
|
self.map = { Text($0) }
|
||||||
|
}
|
||||||
|
}
|
45
CHDataManagement/Views/Generic/ColoredButton.swift
Normal file
45
CHDataManagement/Views/Generic/ColoredButton.swift
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import SwiftUI
|
||||||
|
import SFSafeSymbols
|
||||||
|
|
||||||
|
struct ColoredButton: View {
|
||||||
|
|
||||||
|
let icon: SFSymbol
|
||||||
|
|
||||||
|
let text: LocalizedStringKey
|
||||||
|
|
||||||
|
let fillColor: Color
|
||||||
|
|
||||||
|
let textColor: Color
|
||||||
|
|
||||||
|
let action: () -> Void
|
||||||
|
|
||||||
|
init(icon: SFSymbol, text: LocalizedStringKey, fillColor: Color = .blue, textColor: Color = .white, action: @escaping () -> Void) {
|
||||||
|
self.icon = icon
|
||||||
|
self.text = text
|
||||||
|
self.fillColor = fillColor
|
||||||
|
self.textColor = textColor
|
||||||
|
self.action = action
|
||||||
|
}
|
||||||
|
|
||||||
|
init(delete: @escaping () -> Void) {
|
||||||
|
self.icon = .trash
|
||||||
|
self.text = "Delete"
|
||||||
|
self.fillColor = .red
|
||||||
|
self.textColor = .white
|
||||||
|
self.action = delete
|
||||||
|
}
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
Button(action: action) {
|
||||||
|
HStack {
|
||||||
|
Spacer()
|
||||||
|
Image(systemSymbol: icon)
|
||||||
|
Text(text)
|
||||||
|
.padding(.vertical, 8)
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
.foregroundStyle(textColor)
|
||||||
|
.background(RoundedRectangle(cornerRadius: 8).fill(fillColor))
|
||||||
|
}.buttonStyle(.plain)
|
||||||
|
}
|
||||||
|
}
|
@ -1,20 +0,0 @@
|
|||||||
import SwiftUI
|
|
||||||
|
|
||||||
struct DeleteButton: View {
|
|
||||||
|
|
||||||
let action: () -> Void
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
Button(action: action) {
|
|
||||||
HStack {
|
|
||||||
Spacer()
|
|
||||||
Image(systemSymbol: .trash)
|
|
||||||
Text("Delete")
|
|
||||||
.padding(.vertical, 8)
|
|
||||||
Spacer()
|
|
||||||
}
|
|
||||||
.foregroundStyle(Color.white)
|
|
||||||
.background(RoundedRectangle(cornerRadius: 8).fill(Color.red))
|
|
||||||
}.buttonStyle(.plain)
|
|
||||||
}
|
|
||||||
}
|
|
@ -76,7 +76,7 @@ struct PageDetailView: View {
|
|||||||
page: page.localized(in: language),
|
page: page.localized(in: language),
|
||||||
transferImage: transferImage)
|
transferImage: transferImage)
|
||||||
.id(page.id + language.rawValue)
|
.id(page.id + language.rawValue)
|
||||||
DeleteButton(action: deletePage)
|
ColoredButton(delete: deletePage)
|
||||||
}
|
}
|
||||||
.padding()
|
.padding()
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
import SFSafeSymbols
|
||||||
|
|
||||||
struct PostDetailView: View {
|
struct PostDetailView: View {
|
||||||
|
|
||||||
@ -33,7 +34,12 @@ struct PostDetailView: View {
|
|||||||
text: "Posts capture quick updates and can link to pages")
|
text: "Posts capture quick updates and can link to pages")
|
||||||
|
|
||||||
if post.linkedPage == nil {
|
if post.linkedPage == nil {
|
||||||
Button("Create page", action: createPageFromPost)
|
ColoredButton(
|
||||||
|
icon: .documentBadgePlus,
|
||||||
|
text: "Create page",
|
||||||
|
fillColor: .blue,
|
||||||
|
textColor: .white,
|
||||||
|
action: createPageFromPost)
|
||||||
}
|
}
|
||||||
|
|
||||||
IdPropertyView(
|
IdPropertyView(
|
||||||
@ -76,7 +82,7 @@ struct PostDetailView: View {
|
|||||||
LocalizedPostDetailView(
|
LocalizedPostDetailView(
|
||||||
post: post.localized(in: language),
|
post: post.localized(in: language),
|
||||||
transferImage: transferImage)
|
transferImage: transferImage)
|
||||||
DeleteButton(action: deletePost)
|
ColoredButton(delete: deletePost)
|
||||||
}
|
}
|
||||||
.padding()
|
.padding()
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ struct TagDetailView: View {
|
|||||||
tag: tag.localized(in: language),
|
tag: tag.localized(in: language),
|
||||||
transferImage: transferImage)
|
transferImage: transferImage)
|
||||||
.id(tag.id + language.rawValue)
|
.id(tag.id + language.rawValue)
|
||||||
DeleteButton(action: deleteTag)
|
ColoredButton(delete: deleteTag)
|
||||||
}
|
}
|
||||||
.padding()
|
.padding()
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user