krz/orgstar

A native macOS editor for org-mode files. editor org-mode swift

Sources/OrgstarMobile/FoldersScreen.swift

c1295824f55c7bba681fca8338bf08167e110105
orgstar/Sources/OrgstarMobile/FoldersScreen.swift history · blame · raw

64 lines · 2622 bytes

 1#if os(iOS)
 2import OrgApp
 3import SwiftUI
 4import UniformTypeIdentifiers
 5
 6/// The folders of org files the agenda reads, and their files.
 7struct FoldersScreen: View {
 8    let workspace: WorkspaceModel
 9    @State private var importing = false
10
11    var body: some View {
12        List {
13            ForEach(workspace.rootPaths, id: \.self) { root in
14                Section((root as NSString).lastPathComponent) {
15                    let files = workspace.files.filter { $0.root == root && $0.kind == .org }
16                    ForEach(files) { file in
17                        NavigationLink(value: ReaderRoute.file(file.path)) {
18                            Label(file.relativePath, systemImage: "doc.text")
19                        }
20                    }
21                    let pending = workspace.downloading.filter { $0.hasPrefix(root + "/") }.sorted()
22                    ForEach(pending, id: \.self) { path in
23                        Label(String(path.dropFirst(root.count + 1)), systemImage: "icloud.and.arrow.down")
24                            .foregroundStyle(.secondary)
25                    }
26                    Button("Remove Folder", role: .destructive) { try? workspace.removeRoot(path: root) }
27                }
28            }
29            if let error = workspace.lastError {
30                Text(error).foregroundStyle(.red)
31            }
32        }
33        .navigationTitle("Folders")
34        .overlay {
35            if workspace.rootPaths.isEmpty {
36                ContentUnavailableView {
37                    Label("No folders", systemImage: "folder")
38                } description: {
39                    Text("Add the folder your org files are in, from iCloud Drive or another app's storage.")
40                } actions: {
41                    Button("Add Folder") { importing = true }
42                }
43            }
44        }
45        .toolbar {
46            ToolbarItem(placement: .topBarLeading) {
47                Button("Add Folder", systemImage: "folder.badge.plus") { importing = true }
48            }
49        }
50        .fileImporter(isPresented: $importing, allowedContentTypes: [.folder]) { result in
51            guard case .success(let url) = result else { return }
52            // Kept for the bookmark; WorkspaceRoot resolves it with access again at launch.
53            _ = url.startAccessingSecurityScopedResource()
54            Task {
55                do {
56                    try await workspace.addRoot(url)
57                } catch {
58                    workspace.lastError = "Can't add \(url.lastPathComponent): \(error.localizedDescription)"
59                }
60            }
61        }
62    }
63}
64#endif