/
NavigationProperty.swift
113 lines (103 loc) · 3.95 KB
/
NavigationProperty.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
//
// Created by Jeffrey Bergier on 2022/06/17.
//
// MIT License
//
// Copyright (c) 2021 Jeffrey Bergier
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
import SwiftUI
import Umbrella
import V3Model
@propertyWrapper
internal struct Navigation: DynamicProperty {
@JSBSceneStorage("com.hipstapaper.nav") private var storage = Value()
internal var wrappedValue: Value {
get { self.storage }
nonmutating set { self.storage = newValue }
}
internal var projectedValue: Binding<Value> {
self.$storage
}
}
extension Navigation {
internal struct Value: Hashable, Codable {
internal var sidebar: Sidebar = .init()
internal var detail: Detail = .init()
internal var isWebsitesEdit: Website.Selection = []
internal var isError: ErrorStorage.Identifier?
}
internal struct Sidebar: Hashable, Codable {
internal var isTagsEdit: TagsEdit = .init()
}
internal struct Detail: Hashable, Codable {
internal var isTagApply: Website.Selection = []
internal var isTagApplyPopover: Website.Selection = []
internal var isShare: Website.Selection = []
internal var isSharePopover: Website.Selection = []
internal var isBrowse: Website.Selection.Element? = nil
}
internal struct TagsEdit: Hashable, Codable {
internal var isError: ErrorStorage.Identifier?
internal var isPresented: Tag.Selection = []
}
internal struct Basic: Hashable, Codable {
internal var isPresented: Bool = false
}
}
// MARK: isPresenting Hack
/*
`IsPresenting` is used when presenting programmatically, like Errors.
If this returns yes, nothing new should be presented unless dismissing
everything else.
This is a pretty broken system as I can't detect when the system
is presenting (like menus). Also, the error in the console for trying
to present multiple items is not catcable or detectable.
Modal presentation in SwiftUI is fundamentally broken because there is no
Environment variable to check `isPresenting`. Also there is no way to force
the system to dismiss all presented views.
*/
extension Navigation.Value {
internal var isPresenting: Bool {
self.detail.isPresenting
|| self.sidebar.isPresenting
|| self.isWebsitesEdit.isEmpty == false
|| self.isError != nil
}
}
extension Navigation.Sidebar {
internal var isPresenting: Bool {
self.isTagsEdit.isPresented.isEmpty == false
}
}
extension Navigation.Detail {
internal var isPresenting: Bool {
self.isTagApply.isEmpty == false
|| self.isTagApplyPopover.isEmpty == false
|| self.isShare.isEmpty == false
|| self.isSharePopover.isEmpty == false
|| self.isBrowse != nil
}
}
extension Navigation.TagsEdit {
internal var isPresenting: Bool {
self.isError != nil
}
}