Skip to content

Commit ff53aef

Browse files
committed
[ADD]: Pinned mode
1 parent 2db6e5a commit ff53aef

2 files changed

Lines changed: 33 additions & 7 deletions

File tree

Notty.app/Contents/Info.plist

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313
<key>CFBundlePackageType</key>
1414
<string>APPL</string>
1515
<key>CFBundleShortVersionString</key>
16-
<string>1.1.2</string>
16+
<string>1.1.3</string>
1717
<key>CFBundleVersion</key>
18-
<string>1.1.2</string>
18+
<string>1.1.3</string>
1919
<key>LSUIElement</key>
2020
<true/>
2121
<key>NSHighResolutionCapable</key>

Notty.swift

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,10 @@ class AppDelegate: NSObject, NSApplicationDelegate {
9595
let saveURL = FileManager.default.homeDirectoryForCurrentUser
9696
.appendingPathComponent(".notty.txt")
9797

98+
// Pinned mode: panel stays open even when clicking outside
99+
var isPinned: Bool = false
100+
var titleButton: NSButton!
101+
98102
var hotKeyRef: EventHotKeyRef?
99103

100104
func applicationDidFinishLaunching(_ notification: Notification) {
@@ -143,15 +147,26 @@ class AppDelegate: NSObject, NSApplicationDelegate {
143147
container.layer?.borderColor = NSColor(white: 1.0, alpha: 0.08).cgColor
144148
container.autoresizingMask = [.width, .height] // adapts when panel is resized
145149

146-
// --- 4. Title "Notty" at the top ---
150+
// --- 4. Title "Notty" ---
147151
let title = NSTextField(labelWithString: "Notty")
148152
title.frame = NSRect(x: 16, y: 365, width: 200, height: 24)
149153
title.font = NSFont(name: "Space Mono", size: 14)
150154
?? NSFont.monospacedSystemFont(ofSize: 14, weight: .bold)
151155
title.textColor = NSColor(white: 1.0, alpha: 0.5)
152-
title.autoresizingMask = [.minYMargin] // stays pinned to the top
156+
title.autoresizingMask = [.minYMargin]
153157
container.addSubview(title)
154158

159+
// --- 4b. Pin button (top-right) ---
160+
titleButton = NSButton(frame: NSRect(x: 288, y: 364, width: 22, height: 22))
161+
titleButton.bezelStyle = .inline
162+
titleButton.isBordered = false
163+
titleButton.image = NSImage(systemSymbolName: "pin", accessibilityDescription: "Pin")
164+
titleButton.contentTintColor = NSColor(white: 1.0, alpha: 0.2)
165+
titleButton.autoresizingMask = [.minXMargin, .minYMargin]
166+
titleButton.target = self
167+
titleButton.action = #selector(togglePinned)
168+
container.addSubview(titleButton)
169+
155170
// --- 5. Text editor with scroll ---
156171
let scrollView = NSScrollView(frame: NSRect(x: 12, y: 12, width: 296, height: 345))
157172
scrollView.autoresizingMask = [.width, .height] // adapts on resize
@@ -218,10 +233,20 @@ class AppDelegate: NSObject, NSApplicationDelegate {
218233
}, 1, &eventType, Unmanaged.passUnretained(self).toOpaque(), nil)
219234
}
220235

236+
// --- Toggle pinned mode ---
237+
@objc func togglePinned() {
238+
isPinned.toggle()
239+
let icon = isPinned ? "pin.fill" : "pin"
240+
titleButton.image = NSImage(systemSymbolName: icon, accessibilityDescription: "Pin")
241+
titleButton.contentTintColor = isPinned
242+
? NSColor(white: 1.0, alpha: 0.8)
243+
: NSColor(white: 1.0, alpha: 0.2)
244+
}
245+
221246
// --- Toggle: open or close ---
222247
@objc func togglePanel() {
223248
if panel.isVisible {
224-
closePanel()
249+
closePanel(force: true)
225250
} else {
226251
// If the panel was just closed by the global monitor (clicking the icon
227252
// counts as a global click), don't reopen it immediately
@@ -280,8 +305,9 @@ class AppDelegate: NSObject, NSApplicationDelegate {
280305
}
281306
}
282307

283-
// --- Close the panel ---
284-
func closePanel() {
308+
// --- Close the panel (force: bypasses pinned mode, used by icon toggle) ---
309+
func closePanel(force: Bool = false) {
310+
if isPinned && !force { return }
285311
// Switch icon back to "folder" (closed)
286312
statusItem.button?.image = NSImage(
287313
systemSymbolName: "folder",

0 commit comments

Comments
 (0)