TheAcharya / MarkerData

The avant-garde Marker extraction application crafted for Final Cut Pro
https://markerdata.theacharya.co
MIT License
22 stars 1 forks source link

Show Update Badge in Menu Bar #94

Closed IAmVigneswaran closed 2 weeks ago

IAmVigneswaran commented 2 months ago

@milanvarady Would it be possible to show a New Version Available badge beside Check for Updates... in the application menu bar, if there is a an update available?

In an event user cancels an update, at least the user knows it is available?

update-menu



update-badge
milanvarady commented 1 month ago

After a bit of looking around, I didn't find a way to do this. When an update is available sparkle brings up a window showing it. If automatic checking is disabled it is not checked. I haven't seen an app using Sparkle that has this either.

IAmVigneswaran commented 1 month ago

CommandPost has somewhat of this feature. When a new update is available a Update found: XXX text appears in the menu bar.

The code is written in Lua. I wonder if we can take ideas from it?

https://github.com/CommandPost/CommandPost-App/blob/039f03e8132121f5da92e97ec33130a68cf9ab95/Hammerspoon/MJAppDelegate.m#L373

#pragma mark - Sparkle delegate methods
- (void)updater:(id)updater didFindValidUpdate:(id)update {
    NSLog(@"Update found: %@ (Build: %@)", [update valueForKey:@"displayVersionString"], [update valueForKey:@"versionString"]);
    self.updateAvailable = [update valueForKey:@"versionString"];
    self.updateAvailableDisplayVersion = [update valueForKey:@"displayVersionString"];
}

https://github.com/CommandPost/CommandPost/blob/b62c62cbc56ebba4fb956e92f6d8c2fab6306de8/src/plugins/core/preferences/updates.lua#L75

    --------------------------------------------------------------------------------
    -- Add update info to menubar:
    --------------------------------------------------------------------------------
    local top = deps.menu.top
    top
        :addItem(0.00000000000000000000000000001, function()
            if hs.updateAvailable() then
                local version, build = hs.updateAvailable()
                return {
                    title   = i18n("updateAvailable") .. ": " .. version .. " (" .. build .. ")",
                    fn      = function() hs.focus(); checkForUpdates() end
                }
            end
        end)
        :addSeparator(2)

If we can't have a badge, we can have a menu item above About Marker Data. If there is a new update. When the didFindValidUpdate delegate method is triggered.

update-menu-item

Chris shared some code snippet ideas.

@main
class AppDelegate: NSObject, NSApplicationDelegate, SPUUpdaterDelegate {
    var updaterController: SPUStandardUpdaterController!

    func applicationDidFinishLaunching(_ aNotification: Notification) {
        updaterController = SPUStandardUpdaterController(startingUpdater: true, updaterDelegate: self, userDriverDelegate: nil)
    }

    func updater(_ updater: SPUUpdater, didFindValidUpdate item: SUAppcastItem) {
        // Notify SwiftUI view about the update:
        NotificationCenter.default.post(name: .updateAvailable, object: nil)
    }    
}

extension Notification.Name {
    static let updateAvailable = Notification.Name("updateAvailable")
}
struct ContentView: View {
    @State private var isUpdateAvailable = false

    var body: some View {
        VStack {
            if isUpdateAvailable {
                Button(action: {
                    // Trigger Sparkle update process:
                    if let appDelegate = NSApplication.shared.delegate as? AppDelegate {
                        appDelegate.updaterController.checkForUpdates(nil)
                    }
                }) {
                    Text("Update Available")
                }
                .padding()
            }
        }
        .onAppear {
            NotificationCenter.default.addObserver(forName: .updateAvailable, object: nil, queue: .main) { _ in
                self.isUpdateAvailable = true
            }
        }
    }
}

@main
struct MyApp: App {
    @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}
milanvarady commented 1 month ago

Chris shared some code snippet ideas.

I used the code example. I'm not sure if it actually works, because I can't test it as of yet obviously, but if it does work it will look like this:

CleanShot 2024-05-26 at 23 12 08

IAmVigneswaran commented 3 weeks ago

@milanvarady I notice a minor bug.

For some reason, the update badge does not show up again after the app is restarted. It only show up once.

milanvarady commented 2 weeks ago

The checking wasn't consistent, so I used a different method. It should work now every time.

IAmVigneswaran commented 2 weeks ago

The checking wasn't consistent, so I used a different method. It should work now every time.

Thanks for the fix! It is working now.