Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion Sources/ConfigureSheetController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ final class ConfigureSheetController: NSObject {

let window: NSWindow

private var settings = NecoSaverSettings.load()
private var settings = NecoSaverSettings.standard
private let onDismiss: (_ saved: Bool) -> Void
private var rows: [Row] = []
private let pictureCheckbox = NSButton(checkboxWithTitle: "Picture:", target: nil, action: nil)
Expand All @@ -38,10 +38,29 @@ final class ConfigureSheetController: NSObject {
)
super.init()
window.title = "NecoSaver"
// ARC owns this window through `window`; leaving the default on would let a
// host that closes the sheet release it a second time.
window.isReleasedWhenClosed = false
buildInterface()
reload()
}

/// Re-reads the stored settings into the controls. The same sheet is handed to
/// the host every time it asks, so this is what makes the second opening show
/// what is stored rather than where the first one was left.
func reload() {
settings = Self.stored()
refresh()
}

/// The saved settings, with the picture seeded the same way the saver seeds it,
/// so the field shows the path the cats are actually walking on.
private static func stored() -> NecoSaverSettings {
var settings = NecoSaverSettings.load()
settings.seedPicturePath(with: Wallpaper.desktopPicturePath(for: nil) ?? "")
return settings
}

// MARK: - Interface

private func buildInterface() {
Expand Down
27 changes: 17 additions & 10 deletions Sources/NecoSaverView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import ScreenSaver
@objc(NecoSaverView)
final class NecoSaverView: ScreenSaverView {
private let engine: NecoSaverEngine
/// Held strongly: the host releases its reference once the sheet is up, and a
/// deallocated controller takes the sheet's targets with it.
/// Built once and kept: the host releases its reference once the sheet is up,
/// and a deallocated controller takes the sheet's window and targets with it.
private var sheetController: ConfigureSheetController?

override init?(frame: NSRect, isPreview: Bool) {
Expand Down Expand Up @@ -62,19 +62,26 @@ final class NecoSaverView: ScreenSaverView {
true
}

/// Hosts read this more than once, and can replace the view between reading it
/// and presenting it. Building a controller per read would hand back a window
/// whose only owner was dropped by the very next read — and the sheet then
/// simply never appears. One controller, kept, re-reading the settings each
/// time it is handed over.
override var configureSheet: NSWindow? {
let controller = ConfigureSheetController { [weak self] saved in
guard let self else { return }
if saved {
engine.apply(settings())
loadWallpaper()
}
sheetController = nil
}
let controller = sheetController ?? makeSheetController()
sheetController = controller
controller.reload()
return controller.window
}

private func makeSheetController() -> ConfigureSheetController {
ConfigureSheetController { [weak self] saved in
guard let self, saved else { return }
engine.apply(settings())
loadWallpaper()
}
}

/// Reads a picture only when one is going to be drawn — decoding one costs
/// several megabytes that a grey backdrop has no use for.
private func loadWallpaper() {
Expand Down
Loading