Skip to content

Commit 740c76d

Browse files
authored
Merge pull request #3 from yeapea/claude/setup-docs-planning-Im7eV
Claude/setup docs planning im7e v
2 parents deef541 + 16bd37a commit 740c76d

4 files changed

Lines changed: 90 additions & 81 deletions

File tree

Spaceman.xcodeproj/project.pbxproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,7 @@
545545
PRODUCT_BUNDLE_IDENTIFIER = dev.jaysce.Spaceman;
546546
PRODUCT_NAME = "$(TARGET_NAME)";
547547
SWIFT_OBJC_BRIDGING_HEADER = "Spaceman/Spaceman-Bridging-Header.h";
548-
SWIFT_VERSION = 5.0;
548+
SWIFT_VERSION = 5.10;
549549
};
550550
name = Debug;
551551
};
@@ -576,7 +576,7 @@
576576
PRODUCT_BUNDLE_IDENTIFIER = dev.jaysce.Spaceman;
577577
PRODUCT_NAME = "$(TARGET_NAME)";
578578
SWIFT_OBJC_BRIDGING_HEADER = "Spaceman/Spaceman-Bridging-Header.h";
579-
SWIFT_VERSION = 5.0;
579+
SWIFT_VERSION = 5.10;
580580
};
581581
name = Release;
582582
};
@@ -597,7 +597,7 @@
597597
PRODUCT_NAME = "$(TARGET_NAME)";
598598
SDKROOT = macosx;
599599
SWIFT_EMIT_LOC_STRINGS = NO;
600-
SWIFT_VERSION = 5.0;
600+
SWIFT_VERSION = 5.10;
601601
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Spaceman.app/Contents/MacOS/Spaceman";
602602
};
603603
name = Debug;
@@ -619,7 +619,7 @@
619619
PRODUCT_NAME = "$(TARGET_NAME)";
620620
SDKROOT = macosx;
621621
SWIFT_EMIT_LOC_STRINGS = NO;
622-
SWIFT_VERSION = 5.0;
622+
SWIFT_VERSION = 5.10;
623623
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Spaceman.app/Contents/MacOS/Spaceman";
624624
};
625625
name = Release;

Spaceman/Helpers/IconCreator.swift

Lines changed: 70 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -59,16 +59,14 @@ final class IconCreator {
5959
for space in spaces {
6060
let textRect = NSRect(origin: CGPoint.zero, size: iconSize)
6161
let spaceNumber = NSString(string: String(space.spaceNumber))
62-
let image = NSImage(size: iconSize)
63-
64-
image.lockFocus()
65-
spaceNumber.drawVerticallyCentered(
66-
in: textRect,
67-
withAttributes: getStringAttributes(
68-
alpha: space.isCurrentSpace ? 1 : 0.4,
69-
fontSize: 12))
62+
let attributes = getStringAttributes(
63+
alpha: space.isCurrentSpace ? 1 : 0.4,
64+
fontSize: 12)
65+
let image = NSImage(size: iconSize, flipped: false) { _ in
66+
spaceNumber.drawVerticallyCentered(in: textRect, withAttributes: attributes)
67+
return true
68+
}
7069
image.isTemplate = true
71-
image.unlockFocus()
7270

7371
newIcons.append(image)
7472
}
@@ -83,31 +81,31 @@ final class IconCreator {
8381
for space in spaces {
8482
let textRect = NSRect(origin: CGPoint.zero, size: iconSize)
8583
let number = desktopsOnly ? space.desktopNumber : space.spaceNumber
86-
let iconImage = NSImage(size: iconSize)
87-
let numberImage = NSImage(size: iconSize)
84+
let numberImage = NSImage(size: iconSize, flipped: false) { _ in
85+
if let number {
86+
let spaceNumber = NSString(string: String(number))
87+
spaceNumber.drawVerticallyCentered(
88+
in: textRect,
89+
withAttributes: self.getStringAttributes(alpha: 1))
90+
}
91+
return true
92+
}
8893

89-
if let number {
90-
numberImage.lockFocus()
91-
let spaceNumber = NSString(string: String(number))
92-
spaceNumber.drawVerticallyCentered(
94+
let baseIcon = icons[index]
95+
let iconImage = NSImage(size: iconSize, flipped: false) { _ in
96+
baseIcon.draw(
9397
in: textRect,
94-
withAttributes: getStringAttributes(alpha: 1))
95-
numberImage.unlockFocus()
98+
from: NSRect.zero,
99+
operation: NSCompositingOperation.sourceOver,
100+
fraction: 1.0)
101+
numberImage.draw(
102+
in: textRect,
103+
from: NSRect.zero,
104+
operation: NSCompositingOperation.destinationOut,
105+
fraction: 1.0)
106+
return true
96107
}
97-
98-
iconImage.lockFocus()
99-
icons[index].draw(
100-
in: textRect,
101-
from: NSRect.zero,
102-
operation: NSCompositingOperation.sourceOver,
103-
fraction: 1.0)
104-
numberImage.draw(
105-
in: textRect,
106-
from: NSRect.zero,
107-
operation: NSCompositingOperation.destinationOut,
108-
fraction: 1.0)
109108
iconImage.isTemplate = true
110-
iconImage.unlockFocus()
111109

112110
newIcons.append(iconImage)
113111
index += 1
@@ -123,28 +121,28 @@ final class IconCreator {
123121
for space in spaces {
124122
let textRect = NSRect(origin: CGPoint.zero, size: iconSize)
125123
let spaceText = NSString(string: "\(space.spaceNumber): \(space.spaceName.uppercased())")
126-
let iconImage = NSImage(size: iconSize)
127-
let textImage = NSImage(size: iconSize)
128-
129-
textImage.lockFocus()
130-
spaceText.drawVerticallyCentered(
131-
in: textRect,
132-
withAttributes: getStringAttributes(alpha: 1))
133-
textImage.unlockFocus()
134-
135-
iconImage.lockFocus()
136-
icons[index].draw(
137-
in: textRect,
138-
from: NSRect.zero,
139-
operation: NSCompositingOperation.sourceOver,
140-
fraction: 1.0)
141-
textImage.draw(
142-
in: textRect,
143-
from: NSRect.zero,
144-
operation: NSCompositingOperation.destinationOut,
145-
fraction: 1.0)
124+
let textImage = NSImage(size: iconSize, flipped: false) { _ in
125+
spaceText.drawVerticallyCentered(
126+
in: textRect,
127+
withAttributes: self.getStringAttributes(alpha: 1))
128+
return true
129+
}
130+
131+
let baseIcon = icons[index]
132+
let iconImage = NSImage(size: iconSize, flipped: false) { _ in
133+
baseIcon.draw(
134+
in: textRect,
135+
from: NSRect.zero,
136+
operation: NSCompositingOperation.sourceOver,
137+
fraction: 1.0)
138+
textImage.draw(
139+
in: textRect,
140+
from: NSRect.zero,
141+
operation: NSCompositingOperation.destinationOut,
142+
fraction: 1.0)
143+
return true
144+
}
146145
iconImage.isTemplate = true
147-
iconImage.unlockFocus()
148146

149147
newIcons.append(iconImage)
150148
index += 1
@@ -185,24 +183,30 @@ final class IconCreator {
185183
let accomodatingGapWidth = CGFloat(numIcons - 1) * gapWidth
186184
let accomodatingDisplayGapWidth = CGFloat(displayCount - 1) * displayGapWidth
187185
let totalWidth = combinedIconWidth + accomodatingGapWidth + accomodatingDisplayGapWidth
188-
let image = NSImage(size: NSSize(width: totalWidth, height: iconSize.height))
189-
190-
image.lockFocus()
191-
var xOffset = CGFloat.zero
192-
for icon in iconsWithDisplayProperties {
193-
icon.image.draw(
194-
at: NSPoint(x: xOffset, y: 0),
195-
from: NSRect.zero,
196-
operation: NSCompositingOperation.sourceOver,
197-
fraction: 1.0)
198-
if icon.nextSpaceOnDifferentDisplay {
199-
xOffset += iconSize.width + displayGapWidth
200-
} else {
201-
xOffset += iconSize.width + gapWidth
186+
let iconHeight = iconSize.height
187+
let iconWidth = iconSize.width
188+
let gapWidth = self.gapWidth
189+
let displayGapWidth = self.displayGapWidth
190+
let image = NSImage(
191+
size: NSSize(width: totalWidth, height: iconHeight),
192+
flipped: false
193+
) { _ in
194+
var xOffset = CGFloat.zero
195+
for icon in iconsWithDisplayProperties {
196+
icon.image.draw(
197+
at: NSPoint(x: xOffset, y: 0),
198+
from: NSRect.zero,
199+
operation: NSCompositingOperation.sourceOver,
200+
fraction: 1.0)
201+
if icon.nextSpaceOnDifferentDisplay {
202+
xOffset += iconWidth + displayGapWidth
203+
} else {
204+
xOffset += iconWidth + gapWidth
205+
}
202206
}
207+
return true
203208
}
204209
image.isTemplate = true
205-
image.unlockFocus()
206210

207211
return image
208212
}

Spaceman/View/PreferencesView.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ struct PreferencesView: View {
1616
@AppStorage("displayStyle") private var selectedStyle = 0
1717
@AppStorage("spaceNames") private var data = Data()
1818
@AppStorage("autoRefreshSpaces") private var autoRefreshSpaces = false
19-
@StateObject private var prefsVM = PreferencesViewModel()
19+
@State private var prefsVM = PreferencesViewModel()
2020

2121
// MARK: - Main Body
2222
var body: some View {
@@ -36,7 +36,7 @@ struct PreferencesView: View {
3636
}
3737
.ignoresSafeArea()
3838
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top)
39-
.onAppear(perform: prefsVM.loadData)
39+
.onAppear { prefsVM.loadData() }
4040
.onChange(of: data) {
4141
prefsVM.loadData()
4242
}
@@ -163,7 +163,8 @@ struct PreferencesView: View {
163163

164164
// MARK: - Space Name Editor
165165
private var spaceNameEditor: some View {
166-
HStack {
166+
@Bindable var prefsVM = prefsVM
167+
return HStack {
167168
Picker(selection: $prefsVM.selectedSpace, label: Text("Space")) {
168169
ForEach(0..<prefsVM.sortedSpaceNamesDict.count, id: \.self) {
169170
Text(String(prefsVM.sortedSpaceNamesDict[$0].value.spaceNum))

Spaceman/ViewModel/PreferencesViewModel.swift

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,20 @@
66
//
77

88
import Foundation
9-
import SwiftUI
9+
import Observation
1010

11-
final class PreferencesViewModel: ObservableObject {
12-
@AppStorage("autoRefreshSpaces") private var autoRefreshSpaces = false
13-
@Published var selectedSpace = 0
14-
@Published var spaceName = ""
11+
@MainActor
12+
@Observable
13+
final class PreferencesViewModel {
14+
var selectedSpace = 0
15+
var spaceName = ""
1516
var spaceNamesDict: [String: SpaceNameInfo] = [:]
1617
var sortedSpaceNamesDict: [Dictionary<String, SpaceNameInfo>.Element] = []
17-
private var timer: Timer?
18+
19+
@ObservationIgnored private var timer: Timer?
1820

1921
init() {
20-
if autoRefreshSpaces {
22+
if UserDefaults.standard.bool(forKey: "autoRefreshSpaces") {
2123
startTimer()
2224
}
2325
}
@@ -54,7 +56,9 @@ final class PreferencesViewModel: ObservableObject {
5456
func startTimer() {
5557
timer?.invalidate()
5658
timer = Timer.scheduledTimer(withTimeInterval: 5, repeats: true) { [weak self] _ in
57-
self?.refreshSpaces()
59+
Task { @MainActor in
60+
self?.refreshSpaces()
61+
}
5862
}
5963
}
6064

0 commit comments

Comments
 (0)