Search code examples
swiftmacosswiftuimenubar

SwiftUI macOS Menu Bar app copy and paste into text field


*EDIT: So I figured it out. It might not be the swiftUI way about doing it but it works for my app. I found this post that answered most my questions. I created a new file used the mainMenu view template and that was it. *

I'm creating a menu bar app with a text field that I want users to be able to paste their clipboards into. I think the issue is because it doesn't have a menu since copy and paste works on a black project in a text field in a normal window. I have read a few other post about using a swift package called hotkey but I don't think that will work since I want it to use the systems clipboards not a custom one to the app.

Can this be done in a menu bar only app?

Thank you for the help as I learn.

Here is the test code I'm using.

ContentView

import SwiftUI

struct ContentView: View {
   @State var jobName = String()

var body: some View {
    Text("Testing copy and paste")
        .padding()
    
    TextField(/*@START_MENU_TOKEN@*/"Placeholder"/*@END_MENU_TOKEN@*/, text: $jobName)
   
    
    Button("print text") {
        print(jobName)
    }
}
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
    }

AppDelegate

import Cocoa
import SwiftUI

class AppDelegate: NSObject, NSApplicationDelegate {

    var popover: NSPopover!
    var statusBarItem: NSStatusItem!
    
    func applicationDidFinishLaunching(_ aNotification: Notification) {
        // Create the SwiftUI view that provides the window contents.
        let contentView = ContentView()

        // Create the popover
        let popover = NSPopover()
        popover.contentSize = NSSize(width: 400, height: 500)
        popover.behavior = .transient
        popover.contentViewController = NSHostingController(rootView: contentView)
        self.popover = popover
        
        // Create the status item
        self.statusBarItem = NSStatusBar.system.statusItem(withLength: CGFloat(NSStatusItem.variableLength))
        
        if let button = self.statusBarItem.button {
            button.image = NSImage(named: "Icon")
            button.action = #selector(togglePopover(_:))
        }
    }
    
    @objc func togglePopover(_ sender: AnyObject?) {
        if let button = self.statusBarItem.button {
            if self.popover.isShown {
                self.popover.performClose(sender)
            } else {
                self.popover.show(relativeTo: button.bounds, of: button, preferredEdge: NSRectEdge.minY)
            }
        }
    }
        
    

    func applicationWillTerminate(_ aNotification: Notification) {
        // Insert code here to tear down your application
    }

    func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool {
        return true
    }



}

Main

import Foundation
import Cocoa



// 1
let app = NSApplication.shared
let delegate = AppDelegate()
app.delegate = delegate

// 2
_ = NSApplicationMain(CommandLine.argc, CommandLine.unsafeArgv)

Solution

  • So I figured it out. It might not be the swiftUI way about doing it but it works for my app. I found this post that answered most my questions. I created a new file used the mainMenu view template and that was it.