Skip to content

Commit 7c01c65

Browse files
authored
Merge pull request #20 from ResistanceTo/main
Add a configurable countdown option
2 parents 49e7767 + e56093e commit 7c01c65

File tree

6 files changed

+119
-25
lines changed

6 files changed

+119
-25
lines changed

Azayaka.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
17DBD7C5295B0973005C0690 /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17DBD7C4295B0973005C0690 /* Preferences.swift */; };
1919
18B09AB72BCB6D74005CDC4E /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 18B09AB92BCB6D74005CDC4E /* Localizable.strings */; };
2020
18B09ABC2BCBA40B005CDC4E /* MenuBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18B09ABB2BCBA40B005CDC4E /* MenuBar.swift */; };
21+
7B2603882C0850CD00C47D89 /* Countdown.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B2603872C0850CD00C47D89 /* Countdown.swift */; };
2122
/* End PBXBuildFile section */
2223

2324
/* Begin PBXFileReference section */
@@ -35,6 +36,7 @@
3536
18B09AB82BCB6D74005CDC4E /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
3637
18B09ABA2BCB6D8D005CDC4E /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
3738
18B09ABB2BCBA40B005CDC4E /* MenuBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuBar.swift; sourceTree = "<group>"; };
39+
7B2603872C0850CD00C47D89 /* Countdown.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Countdown.swift; sourceTree = "<group>"; };
3840
/* End PBXFileReference section */
3941

4042
/* Begin PBXFrameworksBuildPhase section */
@@ -76,6 +78,7 @@
7678
18B09ABB2BCBA40B005CDC4E /* MenuBar.swift */,
7779
17322D592959286100185BB6 /* Processing.swift */,
7880
170297D52BCD586A0035EB26 /* Updates.swift */,
81+
7B2603872C0850CD00C47D89 /* Countdown.swift */,
7982
18B09AB92BCB6D74005CDC4E /* Localizable.strings */,
8083
17322D4E2958D08000185BB6 /* Assets.xcassets */,
8184
17322D532958D08000185BB6 /* Azayaka.entitlements */,
@@ -166,6 +169,7 @@
166169
17BCDC80295BAC9400448A97 /* Types.swift in Sources */,
167170
17322D4B2958D07E00185BB6 /* AppDelegate.swift in Sources */,
168171
17322D5C295928BE00185BB6 /* Recording.swift in Sources */,
172+
7B2603882C0850CD00C47D89 /* Countdown.swift in Sources */,
169173
18B09ABC2BCBA40B005CDC4E /* MenuBar.swift in Sources */,
170174
170297D62BCD586A0035EB26 /* Updates.swift in Sources */,
171175
17322D5E295929A000185BB6 /* Menu.swift in Sources */,

Azayaka/AppDelegate.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ class AppDelegate: NSObject, NSApplicationDelegate, SCStreamDelegate, SCStreamOu
7575
"recordMic": false,
7676
"highRes": true,
7777
Preferences.updateCheck: true,
78-
Preferences.fileName: "Recording at %t".local
78+
Preferences.fileName: "Recording at %t".local,
79+
"countDown": 0
7980
]
8081
)
8182
// create a menu bar item

Azayaka/Countdown.swift

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//
2+
// Countdown.swift
3+
// Azayaka
4+
//
5+
// Created by resistanceto on 2024/5/30.
6+
//
7+
8+
import SwiftUI
9+
10+
class CountdownManager: ObservableObject {
11+
@Published var countdown: Int = 0
12+
static let shared = CountdownManager()
13+
private var countdownWindow: NSWindow?
14+
15+
@MainActor
16+
func showCountdown(_ countdown: Int) async {
17+
if countdown == 0 { return }
18+
await withCheckedContinuation { continuation in
19+
self.countdown = countdown
20+
countdownWindow = NSWindow(
21+
contentRect: NSRect(x: 0, y: 0, width: 100, height: 100),
22+
styleMask: [.borderless],
23+
backing: .buffered, defer: false)
24+
countdownWindow?.isReleasedWhenClosed = false
25+
countdownWindow?.level = .floating
26+
countdownWindow?.center()
27+
countdownWindow?.backgroundColor = .clear
28+
countdownWindow?.isOpaque = false
29+
countdownWindow?.hasShadow = true
30+
let countdownView = NSHostingView(rootView: CountdownView().environmentObject(self))
31+
countdownWindow?.contentView = countdownView
32+
if let countdownWindow = countdownWindow { countdownWindow.makeKeyAndOrderFront(nil) }
33+
let timer = DispatchSource.makeTimerSource()
34+
timer.schedule(deadline: .now() + 1, repeating: 1.0)
35+
timer.setEventHandler {
36+
Task { @MainActor in
37+
self.countdown -= 1
38+
if self.countdown < 1 {
39+
timer.cancel()
40+
self.countdownWindow?.close()
41+
self.countdownWindow = nil
42+
continuation.resume()
43+
}
44+
}
45+
}
46+
timer.resume()
47+
}
48+
}
49+
}
50+
51+
struct CountdownView: View {
52+
@EnvironmentObject var countdownManager: CountdownManager
53+
54+
var body: some View {
55+
Text("\(countdownManager.countdown)")
56+
.font(.largeTitle)
57+
.foregroundColor(.white)
58+
.frame(width: 100, height: 100)
59+
.background(Color.black.opacity(0.7))
60+
.cornerRadius(10)
61+
.shadow(radius: 10)
62+
}
63+
}

Azayaka/Preferences.swift

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -176,17 +176,19 @@ struct Preferences: View {
176176
VStack() {
177177
GroupBox() {
178178
VStack() {
179-
TextField("File name", text: $_fileName).frame(maxWidth: 250)
180-
.onChange(of: _fileName) { newText in
181-
fileNameLength = getFileNameLength(newText)
182-
}
183-
.onAppear() {
184-
dateFormatter.dateFormat = "y-MM-dd HH.mm.ss"
185-
fileNameLength = getFileNameLength(_fileName)
186-
}
187-
.foregroundStyle(fileNameLength > NAME_MAX ? .red : .primary)
188-
Text("\"%t\" will be replaced with the recording's start time.")
189-
.font(.subheadline).foregroundColor(Color.gray)
179+
Form() {
180+
TextField("File name", text: $_fileName).frame(maxWidth: 250)
181+
.onChange(of: _fileName) { newText in
182+
fileNameLength = getFileNameLength(newText)
183+
}
184+
.onAppear() {
185+
dateFormatter.dateFormat = "y-MM-dd HH.mm.ss"
186+
fileNameLength = getFileNameLength(_fileName)
187+
}
188+
.foregroundStyle(fileNameLength > NAME_MAX ? .red : .primary)
189+
Text("\"%t\" will be replaced with the recording's start time.")
190+
.font(.subheadline).foregroundColor(Color.gray)
191+
}
190192
}.padding(10).frame(maxWidth: .infinity)
191193
}.padding([.top, .leading, .trailing], 10)
192194
GroupBox() {
@@ -240,8 +242,17 @@ struct Preferences: View {
240242

241243
struct OtherSettings: View {
242244
@AppStorage(updateCheck) private var _updateCheck: Bool = true
245+
@AppStorage("countDown") private var countDown: Int = 0
243246
@State private var launchAtLogin = SMAppService.mainApp.status == .enabled
244247

248+
private var numberFormatter: NumberFormatter {
249+
let formatter = NumberFormatter()
250+
formatter.numberStyle = .decimal
251+
formatter.minimum = 0
252+
formatter.maximum = 99
253+
return formatter
254+
}
255+
245256
var body: some View {
246257
VStack {
247258
GroupBox() {
@@ -266,6 +277,17 @@ struct Preferences: View {
266277
Text("Azayaka will check [GitHub](https://github.com/Mnpn/Azayaka/releases) for new updates.")
267278
.font(.footnote).foregroundColor(Color.gray).frame(maxWidth: .infinity).padding([.bottom, .leading, .trailing], 10)
268279
}.padding([.top, .leading, .trailing], 10)
280+
GroupBox() {
281+
VStack() {
282+
Form() {
283+
TextField("Countdown", value: $countDown, formatter: numberFormatter)
284+
.textFieldStyle(RoundedBorderTextFieldStyle())
285+
.padding([.leading, .trailing], 10)
286+
Text("Countdown to start recording, in seconds.")
287+
.font(.subheadline).foregroundColor(Color.gray)
288+
}.frame(maxWidth: 200).padding(10)
289+
}.padding(10).frame(maxWidth: .infinity)
290+
}.padding([.bottom, .leading, .trailing], 10)
269291
HStack {
270292
Text("Azayaka \(getVersion()) (\(getBuild()))").foregroundColor(Color.secondary)
271293
Spacer()
@@ -290,7 +312,7 @@ struct Preferences: View {
290312
}
291313

292314
#Preview {
293-
Preferences()
315+
Preferences()
294316
}
295317

296318
extension AppDelegate {

Azayaka/Recording.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,10 @@ extension AppDelegate {
3434
if streamType == .systemaudio {
3535
prepareAudioRecording()
3636
}
37-
Task { await record(audioOnly: streamType == .systemaudio, filter: filter!) }
38-
37+
Task {
38+
await CountdownManager.shared.showCountdown(ud.integer(forKey: "countDown"))
39+
await record(audioOnly: streamType == .systemaudio, filter: filter!)
40+
}
3941
// while recording, keep a timer which updates the menu's stats
4042
updateTimer?.invalidate()
4143
updateTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in

Azayaka/zh-Hans.lproj/Localizable.strings

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -66,18 +66,20 @@
6666
"Recording Completed" = "录制结束";
6767
"File saved to: %@" = "文件已保存至: %@";
6868
"File saved to folder: %@" = "文件已保存到: %@ 目录中";
69-
"Destination" = "Destination";
70-
"File name" = "File name";
71-
"\"%t\" will be replaced with the recording's start time." = "\"%t\" will be replaced with the recording's start time.";
72-
"Shortcuts" = "Shortcuts";
73-
"Record system audio" = "Record system audio";
74-
"Record current display" = "Record current display";
75-
"Record focused window" = "Record focused window";
76-
"Recordings can be stopped with the same shortcut." = "Recordings can be stopped with the same shortcut.";
69+
"Destination" = "保存文件";
70+
"File name" = "文件名";
71+
"\"%t\" will be replaced with the recording's start time." = "\"%t\"会被替换为录音的开始时间.";
72+
"Shortcuts" = "快捷键";
73+
"Record system audio" = "录制系统声音";
74+
"Record current display" = "录制当前显示器";
75+
"Record focused window" = "录制焦点窗口";
76+
"Recordings can be stopped with the same shortcut." = "可以用同样的快捷键停止录制";
7777
"Other" = "其他";
7878
"Launch at login" = "登录时启动";
79-
"Check for updates at launch" = "Check for updates at launch";
80-
"Azayaka will check [GitHub](https://github.com/Mnpn/Azayaka/releases) for new updates." = "Azayaka will check [GitHub](https://github.com/Mnpn/Azayaka/releases) for new updates.";
79+
"Check for updates at launch" = "启动时检查更新";
80+
"Countdown" = "倒计时";
81+
"Countdown to start recording, in seconds." = "开始录制倒计时,单位:秒";
82+
"Azayaka will check [GitHub](https://github.com/Mnpn/Azayaka/releases) for new updates." = "Azayaka会从 [GitHub](https://github.com/Mnpn/Azayaka/releases) 检查更新";
8183
"Update to %@…" = "更新至 %@…";
8284

8385
// Warning text

0 commit comments

Comments
 (0)