@@ -95,6 +95,8 @@ final class NWUpdateChecker {
9595
9696 if nwIsRemote ( remoteTag, newerThan: current) {
9797 lastAlertedVersion = remoteTag
98+ // Signal the status bar to show an “update available” badge
99+ NotificationCenter . default. post ( name: . showUpdateBadge, object: nil )
98100 let notes = remote. body? . trimmingCharacters ( in: . whitespacesAndNewlines)
99101
100102 // Prefer a .zip asset if available
@@ -114,6 +116,7 @@ final class NWUpdateChecker {
114116 )
115117 } else if userInitiated {
116118 nwShowInfoAlert ( title: " You’re Up To Date " , text: " You have the latest version ( \( current) ). " )
119+ NotificationCenter . default. post ( name: . hideUpdateBadge, object: nil )
117120 }
118121 }
119122
@@ -179,16 +182,33 @@ final class NWUpdateChecker {
179182 return formatter. string ( fromByteCount: bytes)
180183 }
181184
185+ @objc private func progressNextClicked( _ sender: Any ? ) {
186+ // When the user clicks Next, show the final instructions and turn the button into "Finish (Go to Finder)"
187+ if let label = progressLabel {
188+ label. stringValue = " File has been downloaded. Open the zip and launch the new app. "
189+ }
190+ if let button = finderButton {
191+ button. title = " Finish (Go to Finder) "
192+ button. target = self
193+ button. action = #selector( progressGoToFinderClicked ( _: ) )
194+ }
195+ }
196+
182197 @objc private func progressGoToFinderClicked( _ sender: Any ? ) {
183198 if let url = downloadedFileURL {
184199 NSWorkspace . shared. activateFileViewerSelecting ( [ url] )
185200 }
201+
202+ // Clean up the progress window UI
186203 progressWindow? . close ( )
187204 progressWindow = nil
188205 progressBar = nil
189206 progressLabel = nil
190207 finderButton = nil
191208 downloadedFileURL = nil
209+
210+ // Quit the app so the user can open the new app without conflicts
211+ NSApp . terminate ( nil )
192212 }
193213
194214 // MARK: - Alerts
@@ -332,17 +352,20 @@ final class NWUpdateChecker {
332352 label. alignment = . center
333353 content. addSubview ( label)
334354
335- // “Go to Finder” button centered under the label, initially hidden until download completes
336- // “Go to Finder” button centered under the label, initially hidden until download completes
337- let finderWidth : CGFloat = 120
338- let finderX = ( windowWidth - finderWidth) / 2
339- let finder = NSButton ( title: " Go to Finder " , target: self , action: #selector( progressGoToFinderClicked ( _: ) ) )
340- // Slightly lower Y to increase spacing between label and button
341- finder. frame = NSRect ( x: finderX, y: 14 , width: finderWidth, height: 30 )
355+ // “Next” button near the bottom-right, initially hidden until download completes.
356+ // After the user clicks it, it will turn into “Finish (Go to Finder)”.
357+ let finderWidth : CGFloat = 150 // about one-quarter wider than the original button
358+ let finderHeight : CGFloat = 32
359+ let finderPadding : CGFloat = 16
360+ let finderX = windowWidth - finderPadding - finderWidth
361+ let finderY : CGFloat = 8
362+ let finder = NSButton ( title: " Next " , target: self , action: #selector( progressNextClicked ( _: ) ) )
363+ finder. frame = NSRect ( x: finderX, y: finderY, width: finderWidth, height: finderHeight)
342364 finder. isHidden = true
343365 finder. alphaValue = 0 // start hidden for fade-in
344366 finder. bezelStyle = . rounded
345- finder. contentTintColor = . systemBlue // blue button
367+ finder. bezelColor = . systemBlue
368+ finder. contentTintColor = . white // white text on blue background
346369 content. addSubview ( finder)
347370
348371 window. contentView = content
@@ -408,28 +431,14 @@ final class NWUpdateChecker {
408431 context. duration = 0.25
409432 bar. animator ( ) . doubleValue = 1.0
410433 } , completionHandler: {
411- // 2) Fade in the completion text
412- if let label = self . progressLabel {
413- label. stringValue = " File has been downloaded. Open the zip and launch the new app. "
414- label. alphaValue = 0.0
415- NSAnimationContext . runAnimationGroup ( { context in
416- context. duration = 0.25
417- label. animator ( ) . alphaValue = 1.0
418- } , completionHandler: {
419- // 3) Fade in the “Go to Finder” button
420- if let button = self . finderButton {
421- button. isHidden = false
422- button. alphaValue = 0.0
423- NSAnimationContext . runAnimationGroup { context in
424- context. duration = 0.25
425- button. animator ( ) . alphaValue = 1.0
426- }
427- }
428- } )
429- } else if let button = self . finderButton {
430- // No label; just show the button if label is missing
434+ // After the bar is full, fade in the "Next" button.
435+ if let button = self . finderButton {
431436 button. isHidden = false
432- button. alphaValue = 1.0
437+ button. alphaValue = 0.0
438+ NSAnimationContext . runAnimationGroup { context in
439+ context. duration = 0.25
440+ button. animator ( ) . alphaValue = 1.0
441+ }
433442 }
434443 } )
435444 }
@@ -450,7 +459,6 @@ final class NWUpdateChecker {
450459 DockProgress . style = . squircle( color: . blue)
451460 DockProgress . progressInstance = task. progress
452461
453- // Observe progress to update the small window's bar
454462 // Observe progress to update the small window's bar
455463 activeDownloadObservation = task. progress. observe ( \. fractionCompleted, options: [ . initial, . new] ) { [ weak self] progressObj, _ in
456464 guard let self else { return }
@@ -468,7 +476,11 @@ final class NWUpdateChecker {
468476 if let label = self . progressLabel {
469477 let clamped = max ( 0 , min ( 1 , fraction) )
470478 let percent = Int ( ( clamped * 100 ) . rounded ( ) )
471- label. stringValue = " Downloading… \( percent) % "
479+ if clamped >= 1.0 {
480+ label. stringValue = " Finished downloading ( \( percent) %) "
481+ } else {
482+ label. stringValue = " Downloading… \( percent) % "
483+ }
472484 }
473485 }
474486 }
0 commit comments