|
|
@@ -334,8 +334,10 @@ final class ViewController: NSViewController {
|
|
334
|
334
|
private var aiCompanionNotesMeetingIdByView = [ObjectIdentifier: String]()
|
|
335
|
335
|
private var aiCompanionNotesStatusLabelByView = [ObjectIdentifier: NSTextField]()
|
|
336
|
336
|
private var aiCompanionNotesCurrentRequestId: UUID?
|
|
337
|
|
- private var aiCompanionNotesWindow: NSWindow?
|
|
|
337
|
+ private var aiCompanionNotesPanel: NSPanel?
|
|
338
|
338
|
private weak var aiCompanionNotesTextView: NSTextView?
|
|
|
339
|
+ private weak var aiCompanionNotesCopyButton: NSButton?
|
|
|
340
|
+ private weak var aiCompanionNotesCloseButton: NSButton?
|
|
339
|
341
|
private var aiCompanionNotesTaskByMeetingId = [String: Task<Void, Never>]()
|
|
340
|
342
|
private var aiCompanionAudioPlayer: AVPlayer?
|
|
341
|
343
|
private var aiCompanionLocalAudioPlayer: AVAudioPlayer?
|
|
|
@@ -3522,58 +3524,148 @@ private extension ViewController {
|
|
3522
|
3524
|
|
|
3523
|
3525
|
@MainActor
|
|
3524
|
3526
|
private func aiCompanionPresentNotesWindow(meetingTitle: String, initialText: String) {
|
|
3525
|
|
- if let window = aiCompanionNotesWindow, let textView = aiCompanionNotesTextView {
|
|
3526
|
|
- window.title = "Notes - \(meetingTitle)"
|
|
|
3527
|
+ guard let hostWindow = view.window else { return }
|
|
|
3528
|
+ let hostIsDarkMode = hostWindow.effectiveAppearance.bestMatch(from: [.darkAqua, .aqua]) == .darkAqua
|
|
|
3529
|
+ let panelAppearanceName: NSAppearance.Name = hostIsDarkMode ? .darkAqua : .aqua
|
|
|
3530
|
+ let outerBackgroundColor: NSColor = hostIsDarkMode ? .windowBackgroundColor : NSColor(calibratedWhite: 0.96, alpha: 1.0)
|
|
|
3531
|
+ let headerBackgroundColor: NSColor = hostIsDarkMode ? .controlBackgroundColor : NSColor(calibratedWhite: 0.93, alpha: 1.0)
|
|
|
3532
|
+
|
|
|
3533
|
+ if let panel = aiCompanionNotesPanel, let textView = aiCompanionNotesTextView {
|
|
|
3534
|
+ panel.title = "Notes - \(meetingTitle)"
|
|
|
3535
|
+ panel.appearance = NSAppearance(named: panelAppearanceName)
|
|
|
3536
|
+ panel.backgroundColor = outerBackgroundColor
|
|
3527
|
3537
|
textView.string = initialText
|
|
3528
|
|
- window.makeKeyAndOrderFront(nil)
|
|
|
3538
|
+ if hostWindow.attachedSheet !== panel {
|
|
|
3539
|
+ hostWindow.beginSheet(panel, completionHandler: nil)
|
|
|
3540
|
+ }
|
|
|
3541
|
+ panel.makeKeyAndOrderFront(nil)
|
|
3529
|
3542
|
NSApp.activate(ignoringOtherApps: true)
|
|
3530
|
3543
|
return
|
|
3531
|
3544
|
}
|
|
3532
|
3545
|
|
|
3533
|
|
- let windowWidth: CGFloat = 640
|
|
3534
|
|
- let windowHeight: CGFloat = 560
|
|
3535
|
|
- let window = NSWindow(
|
|
3536
|
|
- contentRect: NSRect(x: 0, y: 0, width: windowWidth, height: windowHeight),
|
|
3537
|
|
- styleMask: [.titled, .closable, .resizable],
|
|
|
3546
|
+ let panelWidth: CGFloat = 720
|
|
|
3547
|
+ let panelHeight: CGFloat = 540
|
|
|
3548
|
+ let panel = NSPanel(
|
|
|
3549
|
+ contentRect: NSRect(x: 0, y: 0, width: panelWidth, height: panelHeight),
|
|
|
3550
|
+ styleMask: [.titled, .closable],
|
|
3538
|
3551
|
backing: .buffered,
|
|
3539
|
3552
|
defer: false
|
|
3540
|
3553
|
)
|
|
3541
|
|
- window.isReleasedWhenClosed = false
|
|
3542
|
|
- window.title = "Notes - \(meetingTitle)"
|
|
3543
|
|
- window.center()
|
|
|
3554
|
+ panel.isReleasedWhenClosed = false
|
|
|
3555
|
+ panel.title = "Notes - \(meetingTitle)"
|
|
|
3556
|
+ panel.isFloatingPanel = false
|
|
|
3557
|
+ panel.hidesOnDeactivate = false
|
|
|
3558
|
+ panel.delegate = self
|
|
|
3559
|
+ panel.appearance = NSAppearance(named: panelAppearanceName)
|
|
|
3560
|
+ panel.backgroundColor = outerBackgroundColor
|
|
|
3561
|
+ panel.standardWindowButton(.zoomButton)?.isHidden = true
|
|
|
3562
|
+ panel.standardWindowButton(.miniaturizeButton)?.isHidden = true
|
|
3544
|
3563
|
|
|
3545
|
3564
|
let root = NSView()
|
|
3546
|
3565
|
root.translatesAutoresizingMaskIntoConstraints = false
|
|
|
3566
|
+ root.wantsLayer = true
|
|
|
3567
|
+ root.layer?.backgroundColor = outerBackgroundColor.cgColor
|
|
|
3568
|
+
|
|
|
3569
|
+ let header = NSView()
|
|
|
3570
|
+ header.translatesAutoresizingMaskIntoConstraints = false
|
|
|
3571
|
+ header.wantsLayer = true
|
|
|
3572
|
+ header.layer?.backgroundColor = headerBackgroundColor.cgColor
|
|
|
3573
|
+ header.layer?.cornerRadius = 10
|
|
|
3574
|
+
|
|
|
3575
|
+ let titleLabel = textLabel("Meeting Notes", font: NSFont.systemFont(ofSize: 15, weight: .semibold), color: .labelColor)
|
|
|
3576
|
+ titleLabel.translatesAutoresizingMaskIntoConstraints = false
|
|
|
3577
|
+ let subtitleLabel = textLabel(meetingTitle, font: NSFont.systemFont(ofSize: 12, weight: .regular), color: .secondaryLabelColor)
|
|
|
3578
|
+ subtitleLabel.translatesAutoresizingMaskIntoConstraints = false
|
|
|
3579
|
+ subtitleLabel.lineBreakMode = .byTruncatingTail
|
|
3547
|
3580
|
|
|
3548
|
3581
|
let scroll = NSScrollView()
|
|
3549
|
3582
|
scroll.translatesAutoresizingMaskIntoConstraints = false
|
|
3550
|
|
- scroll.drawsBackground = false
|
|
|
3583
|
+ scroll.drawsBackground = true
|
|
|
3584
|
+ scroll.backgroundColor = NSColor.textBackgroundColor
|
|
3551
|
3585
|
scroll.hasVerticalScroller = true
|
|
|
3586
|
+ scroll.hasHorizontalScroller = false
|
|
|
3587
|
+ scroll.borderType = .bezelBorder
|
|
3552
|
3588
|
|
|
3553
|
3589
|
let textView = NSTextView()
|
|
3554
|
3590
|
textView.isEditable = false
|
|
3555
|
3591
|
textView.isSelectable = true
|
|
3556
|
|
- textView.backgroundColor = .clear
|
|
|
3592
|
+ textView.backgroundColor = NSColor.textBackgroundColor
|
|
|
3593
|
+ textView.textColor = NSColor.labelColor
|
|
3557
|
3594
|
textView.font = NSFont.systemFont(ofSize: 13, weight: .regular)
|
|
3558
|
3595
|
textView.string = initialText
|
|
3559
|
3596
|
textView.textContainer?.widthTracksTextView = true
|
|
|
3597
|
+ textView.textContainerInset = NSSize(width: 10, height: 10)
|
|
|
3598
|
+
|
|
|
3599
|
+ let copyButton = NSButton(title: "Copy", target: self, action: #selector(aiCompanionCopyNotesTapped(_:)))
|
|
|
3600
|
+ copyButton.translatesAutoresizingMaskIntoConstraints = false
|
|
|
3601
|
+ copyButton.bezelStyle = .rounded
|
|
|
3602
|
+
|
|
|
3603
|
+ let closeButton = NSButton(title: "Close", target: self, action: #selector(aiCompanionCloseNotesTapped(_:)))
|
|
|
3604
|
+ closeButton.translatesAutoresizingMaskIntoConstraints = false
|
|
|
3605
|
+ closeButton.bezelStyle = .rounded
|
|
3560
|
3606
|
|
|
3561
|
3607
|
scroll.documentView = textView
|
|
|
3608
|
+ header.addSubview(titleLabel)
|
|
|
3609
|
+ header.addSubview(subtitleLabel)
|
|
|
3610
|
+ header.addSubview(copyButton)
|
|
|
3611
|
+ header.addSubview(closeButton)
|
|
|
3612
|
+ root.addSubview(header)
|
|
3562
|
3613
|
root.addSubview(scroll)
|
|
3563
|
3614
|
|
|
3564
|
3615
|
NSLayoutConstraint.activate([
|
|
3565
|
|
- scroll.leadingAnchor.constraint(equalTo: root.leadingAnchor),
|
|
3566
|
|
- scroll.trailingAnchor.constraint(equalTo: root.trailingAnchor),
|
|
3567
|
|
- scroll.topAnchor.constraint(equalTo: root.topAnchor),
|
|
3568
|
|
- scroll.bottomAnchor.constraint(equalTo: root.bottomAnchor)
|
|
|
3616
|
+ header.topAnchor.constraint(equalTo: root.topAnchor, constant: 12),
|
|
|
3617
|
+ header.leadingAnchor.constraint(equalTo: root.leadingAnchor, constant: 16),
|
|
|
3618
|
+ header.trailingAnchor.constraint(equalTo: root.trailingAnchor, constant: -16),
|
|
|
3619
|
+
|
|
|
3620
|
+ titleLabel.topAnchor.constraint(equalTo: header.topAnchor, constant: 12),
|
|
|
3621
|
+ titleLabel.leadingAnchor.constraint(equalTo: header.leadingAnchor, constant: 12),
|
|
|
3622
|
+ titleLabel.trailingAnchor.constraint(lessThanOrEqualTo: copyButton.leadingAnchor, constant: -12),
|
|
|
3623
|
+
|
|
|
3624
|
+ subtitleLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 4),
|
|
|
3625
|
+ subtitleLabel.leadingAnchor.constraint(equalTo: header.leadingAnchor, constant: 12),
|
|
|
3626
|
+ subtitleLabel.trailingAnchor.constraint(lessThanOrEqualTo: copyButton.leadingAnchor, constant: -12),
|
|
|
3627
|
+ subtitleLabel.bottomAnchor.constraint(equalTo: header.bottomAnchor, constant: -12),
|
|
|
3628
|
+
|
|
|
3629
|
+ copyButton.centerYAnchor.constraint(equalTo: header.centerYAnchor),
|
|
|
3630
|
+ copyButton.trailingAnchor.constraint(equalTo: closeButton.leadingAnchor, constant: -8),
|
|
|
3631
|
+
|
|
|
3632
|
+ closeButton.centerYAnchor.constraint(equalTo: header.centerYAnchor),
|
|
|
3633
|
+ closeButton.trailingAnchor.constraint(equalTo: header.trailingAnchor, constant: -12),
|
|
|
3634
|
+
|
|
|
3635
|
+ scroll.topAnchor.constraint(equalTo: header.bottomAnchor, constant: 12),
|
|
|
3636
|
+ scroll.leadingAnchor.constraint(equalTo: root.leadingAnchor, constant: 16),
|
|
|
3637
|
+ scroll.trailingAnchor.constraint(equalTo: root.trailingAnchor, constant: -16),
|
|
|
3638
|
+ scroll.bottomAnchor.constraint(equalTo: root.bottomAnchor, constant: -16)
|
|
3569
|
3639
|
])
|
|
3570
|
3640
|
|
|
3571
|
|
- window.contentView = root
|
|
3572
|
|
- window.makeKeyAndOrderFront(nil)
|
|
|
3641
|
+ panel.contentView = root
|
|
|
3642
|
+ hostWindow.beginSheet(panel, completionHandler: nil)
|
|
|
3643
|
+ panel.makeKeyAndOrderFront(nil)
|
|
3573
|
3644
|
NSApp.activate(ignoringOtherApps: true)
|
|
3574
|
3645
|
|
|
3575
|
|
- aiCompanionNotesWindow = window
|
|
|
3646
|
+ aiCompanionNotesPanel = panel
|
|
3576
|
3647
|
aiCompanionNotesTextView = textView
|
|
|
3648
|
+ aiCompanionNotesCopyButton = copyButton
|
|
|
3649
|
+ aiCompanionNotesCloseButton = closeButton
|
|
|
3650
|
+ }
|
|
|
3651
|
+
|
|
|
3652
|
+ @objc private func aiCompanionCopyNotesTapped(_ sender: NSButton) {
|
|
|
3653
|
+ guard let notes = aiCompanionNotesTextView?.string, notes.isEmpty == false else { return }
|
|
|
3654
|
+ NSPasteboard.general.clearContents()
|
|
|
3655
|
+ NSPasteboard.general.setString(notes, forType: .string)
|
|
|
3656
|
+ sender.title = "Copied"
|
|
|
3657
|
+ DispatchQueue.main.asyncAfter(deadline: .now() + 1.2) { [weak self] in
|
|
|
3658
|
+ guard self?.aiCompanionNotesCopyButton === sender else { return }
|
|
|
3659
|
+ sender.title = "Copy"
|
|
|
3660
|
+ }
|
|
|
3661
|
+ }
|
|
|
3662
|
+
|
|
|
3663
|
+ @objc private func aiCompanionCloseNotesTapped(_ sender: NSButton) {
|
|
|
3664
|
+ guard let panel = aiCompanionNotesPanel else { return }
|
|
|
3665
|
+ if let hostWindow = view.window, hostWindow.attachedSheet === panel {
|
|
|
3666
|
+ hostWindow.endSheet(panel)
|
|
|
3667
|
+ }
|
|
|
3668
|
+ panel.orderOut(nil)
|
|
3577
|
3669
|
}
|
|
3578
|
3670
|
|
|
3579
|
3671
|
private func aiCompanionMeetMeetingCode(from meetURL: URL) -> String? {
|
|
|
@@ -6513,6 +6605,13 @@ extension ViewController: AVAudioPlayerDelegate {
|
|
6513
|
6605
|
extension ViewController: NSWindowDelegate {
|
|
6514
|
6606
|
func windowWillClose(_ notification: Notification) {
|
|
6515
|
6607
|
guard let closingWindow = notification.object as? NSWindow else { return }
|
|
|
6608
|
+ if closingWindow === aiCompanionNotesPanel {
|
|
|
6609
|
+ aiCompanionNotesPanel = nil
|
|
|
6610
|
+ aiCompanionNotesTextView = nil
|
|
|
6611
|
+ aiCompanionNotesCopyButton = nil
|
|
|
6612
|
+ aiCompanionNotesCloseButton = nil
|
|
|
6613
|
+ return
|
|
|
6614
|
+ }
|
|
6516
|
6615
|
if closingWindow === paywallWindow {
|
|
6517
|
6616
|
paywallWindow = nil
|
|
6518
|
6617
|
paywallUpgradeFlowEnabled = false
|