Switch toolbar items to viewbuilders

This commit is contained in:
Max Goedjen 2022-12-22 17:20:03 -05:00
parent acdf0baf3a
commit d429d090cf
No known key found for this signature in database

View File

@ -9,6 +9,8 @@ struct ContentView<UpdaterType: UpdaterProtocol, AgentStatusCheckerType: AgentSt
@Binding var showingCreation: Bool @Binding var showingCreation: Bool
@Binding var runningSetup: Bool @Binding var runningSetup: Bool
@Binding var hasRunSetup: Bool @Binding var hasRunSetup: Bool
@State var showingAgentInfo = false
@Environment(\.colorScheme) var colorScheme
@EnvironmentObject private var storeList: SecretStoreList @EnvironmentObject private var storeList: SecretStoreList
@EnvironmentObject private var updater: UpdaterType @EnvironmentObject private var updater: UpdaterType
@ -27,10 +29,10 @@ struct ContentView<UpdaterType: UpdaterProtocol, AgentStatusCheckerType: AgentSt
} }
.frame(minWidth: 640, minHeight: 320) .frame(minWidth: 640, minHeight: 320)
.toolbar { .toolbar {
updateNotice toolbarItem(updateNoticeView, id: "update")
setupNotice toolbarItem(runningOrRunSetupView, id: "setup")
appPathNotice toolbarItem(appPathNoticeView, id: "appPath")
newItem toolbarItem(newItemView, id: "new")
} }
.sheet(isPresented: $runningSetup) { .sheet(isPresented: $runningSetup) {
SetupView(visible: $runningSetup, setupComplete: $hasRunSetup) SetupView(visible: $runningSetup, setupComplete: $hasRunSetup)
@ -41,26 +43,42 @@ struct ContentView<UpdaterType: UpdaterProtocol, AgentStatusCheckerType: AgentSt
extension ContentView { extension ContentView {
var updateNotice: ToolbarItem<Void, AnyView> {
guard let update = updater.update else { func toolbarItem(_ view: some View, id: String) -> ToolbarItem<String, some View> {
return ToolbarItem { AnyView(EmptyView()) } ToolbarItem(id: id) { view }
} }
let color: Color
let text: String var needsSetup: Bool {
(runningSetup || !hasRunSetup || !agentStatusChecker.running) && !agentStatusChecker.developmentBuild
}
/// Item either showing a "everything's good, here's more info" or "something's wrong, re-run setup" message
/// These two are mutually exclusive
@ViewBuilder
var runningOrRunSetupView: some View {
if needsSetup {
setupNoticeView
} else {
runningNoticeView
}
}
var updateNoticeContent: (String, Color)? {
guard let update = updater.update else { return nil }
if update.critical { if update.critical {
text = "Critical Security Update Required" return ("Critical Security Update Required", .red)
color = .red
} else { } else {
if updater.testBuild { if updater.testBuild {
text = "Test Build" return ("Test Build", .blue)
color = .blue
} else { } else {
text = "Update Available" return ("Update Available", .orange)
color = .orange
} }
} }
return ToolbarItem { }
AnyView(
@ViewBuilder
var updateNoticeView: some View {
if let update = updater.update, let (text, color) = updateNoticeContent {
Button(action: { Button(action: {
selectedUpdate = update selectedUpdate = update
}, label: { }, label: {
@ -73,16 +91,12 @@ extension ContentView {
.popover(item: $selectedUpdate, attachmentAnchor: .point(.bottom), arrowEdge: .bottom) { update in .popover(item: $selectedUpdate, attachmentAnchor: .point(.bottom), arrowEdge: .bottom) { update in
UpdateDetailView(update: update) UpdateDetailView(update: update)
} }
)
} }
} }
var newItem: ToolbarItem<Void, AnyView> { @ViewBuilder
guard storeList.modifiableStore?.isAvailable ?? false else { var newItemView: some View {
return ToolbarItem { AnyView(EmptyView()) } if storeList.modifiableStore?.isAvailable ?? false {
}
return ToolbarItem {
AnyView(
Button(action: { Button(action: {
showingCreation = true showingCreation = true
}, label: { }, label: {
@ -93,16 +107,11 @@ extension ContentView {
CreateSecretView(store: modifiable, showing: $showingCreation) CreateSecretView(store: modifiable, showing: $showingCreation)
} }
} }
)
} }
} }
var setupNotice: ToolbarItem<Void, AnyView> { @ViewBuilder
return ToolbarItem { var setupNoticeView: some View {
AnyView(
Group {
if (runningSetup || !hasRunSetup || !agentStatusChecker.running) && !agentStatusChecker.developmentBuild {
Button(action: { Button(action: {
runningSetup = true runningSetup = true
}, label: { }, label: {
@ -118,21 +127,38 @@ extension ContentView {
}) })
.background(Color.orange) .background(Color.orange)
.cornerRadius(5) .cornerRadius(5)
} else {
EmptyView()
} }
@ViewBuilder
var runningNoticeView: some View {
Button(action: {
showingAgentInfo = true
}, label: {
HStack {
Text("Agent is Running")
.font(.headline)
Circle()
.frame(width: 10, height: 10)
.foregroundColor(Color.green)
} }
) })
.background((colorScheme == .dark ? Color.white : Color.black).opacity(0.05))
.cornerRadius(5)
.popover(isPresented: $showingAgentInfo, attachmentAnchor: .point(.bottom), arrowEdge: .bottom) {
VStack {
Text("SecretAgent is Running")
.font(.title)
.padding(5)
Text("SecretAgent is a process that runs in the background to sign requests, so you don't need to keep Secretive open all the time.\n\n**You can close Secretive, and everything will still keep working.**")
.frame(width: 300)
}
.padding()
} }
} }
var appPathNotice: ToolbarItem<Void, AnyView> { @ViewBuilder
let controller = ApplicationDirectoryController() var appPathNoticeView: some View {
guard !controller.isInApplicationsDirectory else { if !ApplicationDirectoryController().isInApplicationsDirectory {
return ToolbarItem { AnyView(EmptyView()) }
}
return ToolbarItem {
AnyView(
Button(action: { Button(action: {
showingAppPathNotice = true showingAppPathNotice = true
}, label: { }, label: {
@ -155,7 +181,6 @@ extension ContentView {
} }
.padding() .padding()
} }
)
} }
} }
@ -198,3 +223,28 @@ struct ContentView_Previews: PreviewProvider {
} }
#endif #endif
struct ToolbarButton: ButtonStyle {
private let lightColor: Color
private let darkColor: Color
@Environment(\.colorScheme) var colorScheme
init(color: Color) {
self.lightColor = color
self.darkColor = color
}
init(lightColor: Color, darkColor: Color) {
self.lightColor = lightColor
self.darkColor = darkColor
}
func makeBody(configuration: Configuration) -> some View {
configuration.label
// .buttonStyle(.bordered)
.padding()
.background(colorScheme == .light ? lightColor : darkColor)
.foregroundColor(.white)
}
}