|
|
@@ -82,7 +82,9 @@ final class DashboardView: NSView, NSTextFieldDelegate {
|
|
82
|
82
|
private let findJobsCTAChrome = HoverableView()
|
|
83
|
83
|
private var findJobsCTAGradientLayer: CAGradientLayer?
|
|
84
|
84
|
private let chatStatusStack = NSStackView()
|
|
|
85
|
+ private let chatStatusSymbolContainer = NSView()
|
|
85
|
86
|
private let chatStatusIcon = NSImageView()
|
|
|
87
|
+ private let chatStatusLoadingIndicator = NSProgressIndicator()
|
|
86
|
88
|
private let chatStatusLabel = NSTextField(labelWithString: "Opening the vault...")
|
|
87
|
89
|
private let chatScrollView = NSScrollView()
|
|
88
|
90
|
private let chatDocumentView = JobListingsDocumentView()
|
|
|
@@ -282,20 +284,47 @@ final class DashboardView: NSView, NSTextFieldDelegate {
|
|
282
|
284
|
chatStatusStack.alignment = .centerX
|
|
283
|
285
|
chatStatusStack.translatesAutoresizingMaskIntoConstraints = false
|
|
284
|
286
|
|
|
|
287
|
+ chatStatusSymbolContainer.translatesAutoresizingMaskIntoConstraints = false
|
|
|
288
|
+
|
|
285
|
289
|
chatStatusIcon.translatesAutoresizingMaskIntoConstraints = false
|
|
286
|
290
|
chatStatusIcon.wantsLayer = true
|
|
287
|
291
|
chatStatusIcon.symbolConfiguration = NSImage.SymbolConfiguration(pointSize: 36, weight: .regular)
|
|
288
|
292
|
chatStatusIcon.image = NSImage(systemSymbolName: "sparkles", accessibilityDescription: "Assistant status")
|
|
289
|
293
|
chatStatusIcon.contentTintColor = Theme.brandBlue
|
|
290
|
294
|
|
|
|
295
|
+ chatStatusLoadingIndicator.translatesAutoresizingMaskIntoConstraints = false
|
|
|
296
|
+ chatStatusLoadingIndicator.style = .spinning
|
|
|
297
|
+ chatStatusLoadingIndicator.isIndeterminate = true
|
|
|
298
|
+ chatStatusLoadingIndicator.isDisplayedWhenStopped = false
|
|
|
299
|
+ chatStatusLoadingIndicator.controlSize = .regular
|
|
|
300
|
+ chatStatusLoadingIndicator.isHidden = true
|
|
|
301
|
+ chatStatusLoadingIndicator.setAccessibilityRole(.progressIndicator)
|
|
|
302
|
+ chatStatusLoadingIndicator.setAccessibilityLabel("Searching for jobs")
|
|
|
303
|
+
|
|
|
304
|
+ chatStatusSymbolContainer.addSubview(chatStatusIcon)
|
|
|
305
|
+ chatStatusSymbolContainer.addSubview(chatStatusLoadingIndicator)
|
|
|
306
|
+
|
|
|
307
|
+ NSLayoutConstraint.activate([
|
|
|
308
|
+ chatStatusSymbolContainer.widthAnchor.constraint(equalToConstant: 40),
|
|
|
309
|
+ chatStatusSymbolContainer.heightAnchor.constraint(equalToConstant: 40),
|
|
|
310
|
+ chatStatusIcon.centerXAnchor.constraint(equalTo: chatStatusSymbolContainer.centerXAnchor),
|
|
|
311
|
+ chatStatusIcon.centerYAnchor.constraint(equalTo: chatStatusSymbolContainer.centerYAnchor),
|
|
|
312
|
+ chatStatusLoadingIndicator.centerXAnchor.constraint(equalTo: chatStatusSymbolContainer.centerXAnchor),
|
|
|
313
|
+ chatStatusLoadingIndicator.centerYAnchor.constraint(equalTo: chatStatusSymbolContainer.centerYAnchor),
|
|
|
314
|
+ chatStatusLoadingIndicator.widthAnchor.constraint(equalToConstant: 32),
|
|
|
315
|
+ chatStatusLoadingIndicator.heightAnchor.constraint(equalToConstant: 32)
|
|
|
316
|
+ ])
|
|
|
317
|
+
|
|
291
|
318
|
chatStatusLabel.font = .systemFont(ofSize: 20, weight: .semibold)
|
|
292
|
319
|
chatStatusLabel.textColor = Theme.primaryText
|
|
293
|
320
|
chatStatusLabel.alignment = .center
|
|
294
|
321
|
chatStatusLabel.maximumNumberOfLines = 1
|
|
295
|
322
|
|
|
296
|
|
- chatStatusStack.addArrangedSubview(chatStatusIcon)
|
|
|
323
|
+ chatStatusStack.addArrangedSubview(chatStatusSymbolContainer)
|
|
297
|
324
|
chatStatusStack.addArrangedSubview(chatStatusLabel)
|
|
298
|
325
|
|
|
|
326
|
+ syncChatStatusLoadingIndicator(forStatusText: chatStatusLabel.stringValue)
|
|
|
327
|
+
|
|
299
|
328
|
chatDocumentView.translatesAutoresizingMaskIntoConstraints = false
|
|
300
|
329
|
chatStack.orientation = .vertical
|
|
301
|
330
|
chatStack.spacing = 18
|
|
|
@@ -332,9 +361,22 @@ final class DashboardView: NSView, NSTextFieldDelegate {
|
|
332
|
361
|
|
|
333
|
362
|
private func setChatStatusLabel(_ text: String) {
|
|
334
|
363
|
chatStatusLabel.stringValue = text
|
|
|
364
|
+ syncChatStatusLoadingIndicator(forStatusText: text)
|
|
335
|
365
|
syncChatStatusSparkleAnimation()
|
|
336
|
366
|
}
|
|
337
|
367
|
|
|
|
368
|
+ private func syncChatStatusLoadingIndicator(forStatusText text: String) {
|
|
|
369
|
+ let loading = (text == "Thinking...")
|
|
|
370
|
+ if loading {
|
|
|
371
|
+ chatStatusIcon.isHidden = true
|
|
|
372
|
+ chatStatusLoadingIndicator.isHidden = false
|
|
|
373
|
+ chatStatusLoadingIndicator.startAnimation(nil)
|
|
|
374
|
+ } else {
|
|
|
375
|
+ chatStatusLoadingIndicator.stopAnimation(nil)
|
|
|
376
|
+ chatStatusIcon.isHidden = false
|
|
|
377
|
+ }
|
|
|
378
|
+ }
|
|
|
379
|
+
|
|
338
|
380
|
private func isWelcomeHeroVisible() -> Bool {
|
|
339
|
381
|
!mainOverlay.isHidden
|
|
340
|
382
|
}
|