From 4d2b89618cd2fc9cc254086d17d103101079c948 Mon Sep 17 00:00:00 2001 From: zendergod Date: Tue, 28 Jul 2026 21:22:46 +0530 Subject: [PATCH] Show Camera Bubble as a normal macOS app --- Info.plist | 6 ++-- README.md | 1 + Sources/CameraBubble/main.swift | 53 ++++++++++++++++++++++++++++++++- 3 files changed, 56 insertions(+), 4 deletions(-) diff --git a/Info.plist b/Info.plist index e04c10b..e59de3e 100644 --- a/Info.plist +++ b/Info.plist @@ -19,15 +19,15 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.1.0 + 1.1.1 CFBundleVersion - 1 + 2 LSMinimumSystemVersion 14.0 LSApplicationCategoryType public.app-category.video LSUIElement - + NSCameraUsageDescription Camera Bubble shows your camera in a floating window while you record your screen. NSHighResolutionCapable diff --git a/README.md b/README.md index ac8fe24..0be2907 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ want. - Manual `Start / Pause / Resume` timer - Timer reset between takes - Menu-bar controls for the bubble and timer +- A normal Dock icon, Spotlight entry, and Applications/Launchpad presence - Remembers window size, position, and mirroring - Native app icon and About panel - Works across macOS Spaces and full-screen apps diff --git a/Sources/CameraBubble/main.swift b/Sources/CameraBubble/main.swift index 3d4b29c..667c98f 100644 --- a/Sources/CameraBubble/main.swift +++ b/Sources/CameraBubble/main.swift @@ -244,6 +244,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate { func applicationDidFinishLaunching(_ notification: Notification) { configurePanel() + configureMainMenu() configureStatusItem() showBubble() } @@ -252,6 +253,52 @@ final class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate { panel.saveFrame(usingName: "CameraBubbleWindow") } + func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool { + showBubble() + return true + } + + private func configureMainMenu() { + let mainMenu = NSMenu() + + let appMenuItem = NSMenuItem() + mainMenu.addItem(appMenuItem) + let appMenu = NSMenu() + appMenuItem.submenu = appMenu + + let about = appMenu.addItem( + withTitle: "About Camera Bubble", + action: #selector(showAbout), + keyEquivalent: "" + ) + about.target = self + appMenu.addItem(.separator()) + + let show = appMenu.addItem( + withTitle: "Show Camera Bubble", + action: #selector(showBubbleFromMenu), + keyEquivalent: "b" + ) + show.target = self + + appMenu.addItem(.separator()) + appMenu.addItem( + withTitle: "Hide Camera Bubble", + action: #selector(NSApplication.hide(_:)), + keyEquivalent: "h" + ) + appMenu.addItem(.separator()) + + let quit = appMenu.addItem( + withTitle: "Quit Camera Bubble", + action: #selector(NSApplication.terminate(_:)), + keyEquivalent: "q" + ) + quit.target = NSApp + + NSApp.mainMenu = mainMenu + } + private func configurePanel() { let defaultSize = NSSize(width: 360, height: 240) previewView = CameraPreviewView(frame: NSRect(origin: .zero, size: defaultSize)) @@ -338,6 +385,10 @@ final class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate { panel.isVisible ? hideBubble() : showBubble() } + @objc private func showBubbleFromMenu() { + showBubble() + } + private func showBubble() { panel.orderFrontRegardless() updateMenuState() @@ -410,7 +461,7 @@ enum CameraBubbleApp { let app = NSApplication.shared let delegate = AppDelegate() app.delegate = delegate - app.setActivationPolicy(.accessory) + app.setActivationPolicy(.regular) app.run() } }