Quick prompting for stuff on debug/test builds

This commit is contained in:
Max Goedjen 2021-12-31 14:52:40 -08:00
parent 6eee29e1fa
commit b8411008ae
No known key found for this signature in database
GPG Key ID: E58C21DD77B9B8E8
6 changed files with 64 additions and 47 deletions

View File

@ -4,12 +4,14 @@ import Combine
public protocol UpdaterProtocol: ObservableObject {
var update: Release? { get }
var testBuild: Bool { get }
}
public class Updater: ObservableObject, UpdaterProtocol {
@Published public var update: Release?
public let testBuild: Bool
private let osVersion: SemVer
private let currentVersion: SemVer
@ -17,6 +19,7 @@ public class Updater: ObservableObject, UpdaterProtocol {
public init(checkOnLaunch: Bool, osVersion: SemVer = SemVer(ProcessInfo.processInfo.operatingSystemVersion), currentVersion: SemVer = SemVer(Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "0.0.0")) {
self.osVersion = osVersion
self.currentVersion = currentVersion
testBuild = currentVersion == SemVer("0.0.0")
if checkOnLaunch {
// Don't do a launch check if the user hasn't seen the setup prompt explaining updater yet.
checkForUpdates()

View File

@ -36,7 +36,7 @@ struct Secretive: App {
if agentStatusChecker.running && justUpdatedChecker.justUpdated {
// Relaunch the agent, since it'll be running from earlier update still
reinstallAgent()
} else if !agentStatusChecker.running {
} else if !agentStatusChecker.running && !agentStatusChecker.developmentBuild {
forceLaunchAgent()
}
}

View File

@ -5,6 +5,7 @@ import SecretKit
protocol AgentStatusCheckerProtocol: ObservableObject {
var running: Bool { get }
var developmentBuild: Bool { get }
}
class AgentStatusChecker: ObservableObject, AgentStatusCheckerProtocol {
@ -36,6 +37,12 @@ class AgentStatusChecker: ObservableObject, AgentStatusCheckerProtocol {
return nil
}
// Whether Secretive is being run in an Xcode environment.
var developmentBuild: Bool {
Bundle.main.bundleURL.absoluteString.contains("/Library/Developer/Xcode")
}
}

View File

@ -4,6 +4,7 @@ import Combine
class PreviewAgentStatusChecker: AgentStatusCheckerProtocol {
let running: Bool
let developmentBuild = false
init(running: Bool = true) {
self.running = running

View File

@ -5,6 +5,7 @@ import Brief
class PreviewUpdater: UpdaterProtocol {
let update: Release?
let testBuild = false
init(update: Update = .none) {
switch update {

View File

@ -3,18 +3,18 @@ import SecretKit
import Brief
struct ContentView<UpdaterType: UpdaterProtocol, AgentStatusCheckerType: AgentStatusCheckerProtocol>: View {
@Binding var showingCreation: Bool
@Binding var runningSetup: Bool
@Binding var hasRunSetup: Bool
@EnvironmentObject private var storeList: SecretStoreList
@EnvironmentObject private var updater: UpdaterType
@EnvironmentObject private var agentStatusChecker: AgentStatusCheckerType
@State private var selectedUpdate: Release?
@State private var showingAppPathNotice = false
var body: some View {
VStack {
if storeList.anyAvailable {
@ -31,11 +31,11 @@ struct ContentView<UpdaterType: UpdaterProtocol, AgentStatusCheckerType: AgentSt
newItem
}
}
}
extension ContentView {
var updateNotice: ToolbarItem<Void, AnyView> {
guard let update = updater.update else {
return ToolbarItem { AnyView(EmptyView()) }
@ -46,8 +46,13 @@ extension ContentView {
text = "Critical Security Update Required"
color = .red
} else {
text = "Update Available"
color = .orange
if updater.testBuild {
text = "Test Build"
color = .blue
} else {
text = "Update Available"
color = .orange
}
}
return ToolbarItem {
AnyView(
@ -58,15 +63,15 @@ extension ContentView {
.font(.headline)
.foregroundColor(.white)
})
.background(color)
.cornerRadius(5)
.popover(item: $selectedUpdate, attachmentAnchor: .point(.bottom), arrowEdge: .bottom) { update in
UpdateDetailView(update: update)
}
.background(color)
.cornerRadius(5)
.popover(item: $selectedUpdate, attachmentAnchor: .point(.bottom), arrowEdge: .bottom) { update in
UpdateDetailView(update: update)
}
)
}
}
var newItem: ToolbarItem<Void, AnyView> {
guard storeList.modifiableStore?.isAvailable ?? false else {
return ToolbarItem { AnyView(EmptyView()) }
@ -78,21 +83,21 @@ extension ContentView {
}, label: {
Image(systemName: "plus")
})
.popover(isPresented: $showingCreation, attachmentAnchor: .point(.bottom), arrowEdge: .bottom) {
if let modifiable = storeList.modifiableStore {
CreateSecretView(store: modifiable, showing: $showingCreation)
.popover(isPresented: $showingCreation, attachmentAnchor: .point(.bottom), arrowEdge: .bottom) {
if let modifiable = storeList.modifiableStore {
CreateSecretView(store: modifiable, showing: $showingCreation)
}
}
}
)
}
}
var setupNotice: ToolbarItem<Void, AnyView> {
return ToolbarItem {
AnyView(
Group {
if runningSetup || !hasRunSetup || !agentStatusChecker.running {
if (runningSetup || !hasRunSetup || !agentStatusChecker.running) && !agentStatusChecker.developmentBuild {
Button(action: {
runningSetup = true
}, label: {
@ -106,19 +111,19 @@ extension ContentView {
.font(.headline)
.foregroundColor(.white)
})
.background(Color.orange)
.cornerRadius(5)
.background(Color.orange)
.cornerRadius(5)
} else {
EmptyView()
}
}
.sheet(isPresented: $runningSetup) {
SetupView(visible: $runningSetup, setupComplete: $hasRunSetup)
}
.sheet(isPresented: $runningSetup) {
SetupView(visible: $runningSetup, setupComplete: $hasRunSetup)
}
)
}
}
var appPathNotice: ToolbarItem<Void, AnyView> {
let controller = ApplicationDirectoryController()
guard !controller.isInApplicationsDirectory else {
@ -135,29 +140,29 @@ extension ContentView {
.font(.headline)
.foregroundColor(.white)
})
.background(Color.orange)
.cornerRadius(5)
.popover(isPresented: $showingAppPathNotice, attachmentAnchor: .point(.bottom), arrowEdge: .bottom) {
VStack {
Image(systemName: "exclamationmark.triangle")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 64)
Text("Secretive needs to be in your Applications folder to work properly. Please move it and relaunch.")
.frame(maxWidth: 300)
.background(Color.orange)
.cornerRadius(5)
.popover(isPresented: $showingAppPathNotice, attachmentAnchor: .point(.bottom), arrowEdge: .bottom) {
VStack {
Image(systemName: "exclamationmark.triangle")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 64)
Text("Secretive needs to be in your Applications folder to work properly. Please move it and relaunch.")
.frame(maxWidth: 300)
}
.padding()
}
.padding()
}
)
}
}
}
#if DEBUG
struct ContentView_Previews: PreviewProvider {
private static let storeList: SecretStoreList = {
let list = SecretStoreList()
list.add(store: SecureEnclave.Store())
@ -166,11 +171,11 @@ struct ContentView_Previews: PreviewProvider {
}()
private static let agentStatusChecker = AgentStatusChecker()
private static let justUpdatedChecker = JustUpdatedChecker()
@State var hasRunSetup = false
@State private var showingSetup = false
@State private var showingCreation = false
static var previews: some View {
Group {
// Empty on modifiable and nonmodifiable
@ -178,7 +183,7 @@ struct ContentView_Previews: PreviewProvider {
.environmentObject(Preview.storeList(stores: [Preview.Store(numberOfRandomSecrets: 0)], modifiableStores: [Preview.StoreModifiable(numberOfRandomSecrets: 0)]))
.environmentObject(PreviewUpdater())
.environmentObject(agentStatusChecker)
// 5 items on modifiable and nonmodifiable
ContentView<PreviewUpdater, AgentStatusChecker>(showingCreation: .constant(false), runningSetup: .constant(false), hasRunSetup: .constant(true))
.environmentObject(Preview.storeList(stores: [Preview.Store()], modifiableStores: [Preview.StoreModifiable()]))
@ -186,7 +191,7 @@ struct ContentView_Previews: PreviewProvider {
.environmentObject(agentStatusChecker)
}
.environmentObject(agentStatusChecker)
}
}