fix: badge shows active count, floating widget shows priorities, record URL deep link
1. Menu bar badge and floating widget now show total active bugs count (was showing unseen-only count). Unseen dot still works independently in the bug list rows. 2. Floating widget now shows priority breakdown: 🐜 12 🔴3 🟡4 🔵2 ⚪3 Each priority gets a colored dot + count. Only non-zero priorities shown. 3. Fixed Feishu record URL format: now uses query-parameter deep link /base/{appToken}?table={tableId}&record={recordId} instead of path segments, which opens the specific record row directly in Feishu. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
723c50fc9d
commit
ec410f2bab
|
|
@ -38,7 +38,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
|
||||||
button.action = #selector(togglePopover)
|
button.action = #selector(togglePopover)
|
||||||
button.target = self
|
button.target = self
|
||||||
}
|
}
|
||||||
updateBadge(count: bugStore.unseenActiveCount)
|
updateBadge(count: bugStore.activeBugs.count)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func setupPopover() {
|
private func setupPopover() {
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ final class PollerService {
|
||||||
await MainActor.run {
|
await MainActor.run {
|
||||||
bugStore.update(with: bugs)
|
bugStore.update(with: bugs)
|
||||||
bugStore.setLoading(false)
|
bugStore.setLoading(false)
|
||||||
AppDelegate.shared?.updateBadge(count: bugStore.unseenActiveCount)
|
AppDelegate.shared?.updateBadge(count: bugStore.activeBugs.count)
|
||||||
}
|
}
|
||||||
} catch FeishuError.unauthorized {
|
} catch FeishuError.unauthorized {
|
||||||
await MainActor.run {
|
await MainActor.run {
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,8 @@ enum FeishuURLBuilder {
|
||||||
tableId: String,
|
tableId: String,
|
||||||
recordId: String
|
recordId: String
|
||||||
) -> URL {
|
) -> URL {
|
||||||
URL(string: "https://\(baseDomain)/base/\(appToken)/table/\(tableId)/record/\(recordId)")!
|
// Feishu Bitable record deep link: uses query parameters
|
||||||
|
URL(string: "https://\(baseDomain)/base/\(appToken)?table=\(tableId)&record=\(recordId)")!
|
||||||
}
|
}
|
||||||
|
|
||||||
static func tableURL(baseDomain: String, appToken: String) -> URL {
|
static func tableURL(baseDomain: String, appToken: String) -> URL {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import SwiftUI
|
||||||
final class FloatingWidgetWindow: NSPanel {
|
final class FloatingWidgetWindow: NSPanel {
|
||||||
init() {
|
init() {
|
||||||
super.init(
|
super.init(
|
||||||
contentRect: NSRect(x: 0, y: 0, width: 80, height: 60),
|
contentRect: NSRect(x: 0, y: 0, width: 140, height: 70),
|
||||||
styleMask: [.borderless, .nonactivatingPanel],
|
styleMask: [.borderless, .nonactivatingPanel],
|
||||||
backing: .buffered,
|
backing: .buffered,
|
||||||
defer: false
|
defer: false
|
||||||
|
|
@ -35,22 +35,47 @@ final class FloatingWidgetWindow: NSPanel {
|
||||||
struct FloatingWidgetView: View {
|
struct FloatingWidgetView: View {
|
||||||
@State private var bugStore = BugStore.shared
|
@State private var bugStore = BugStore.shared
|
||||||
|
|
||||||
|
private var priorityCounts: [(BugPriority, Int)] {
|
||||||
|
let active = bugStore.activeBugs
|
||||||
|
return BugPriority.allCases
|
||||||
|
.filter { $0 != .unknown }
|
||||||
|
.map { priority in
|
||||||
|
(priority, active.filter { $0.priority == priority }.count)
|
||||||
|
}
|
||||||
|
.filter { $0.1 > 0 }
|
||||||
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Button {
|
Button {
|
||||||
AppDelegate.shared?.togglePopover()
|
AppDelegate.shared?.togglePopover()
|
||||||
} label: {
|
} label: {
|
||||||
HStack(spacing: 6) {
|
VStack(spacing: 4) {
|
||||||
|
HStack(spacing: 4) {
|
||||||
Image(systemName: "ant.fill")
|
Image(systemName: "ant.fill")
|
||||||
|
.font(.caption)
|
||||||
|
Text("\(bugStore.activeBugs.count)")
|
||||||
.font(.title3)
|
.font(.title3)
|
||||||
Text("\(bugStore.unseenActiveCount)")
|
|
||||||
.font(.title2)
|
|
||||||
.fontWeight(.bold)
|
.fontWeight(.bold)
|
||||||
.contentTransition(.numericText())
|
|
||||||
}
|
}
|
||||||
.padding(.horizontal, 12)
|
if !priorityCounts.isEmpty {
|
||||||
.padding(.vertical, 8)
|
HStack(spacing: 6) {
|
||||||
|
ForEach(priorityCounts, id: \.0) { priority, count in
|
||||||
|
HStack(spacing: 2) {
|
||||||
|
Circle()
|
||||||
|
.fill(priority.color)
|
||||||
|
.frame(width: 6, height: 6)
|
||||||
|
Text("\(count)")
|
||||||
|
.font(.caption2)
|
||||||
|
.fontWeight(.medium)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding(.horizontal, 14)
|
||||||
|
.padding(.vertical, 10)
|
||||||
.background(
|
.background(
|
||||||
RoundedRectangle(cornerRadius: 12)
|
RoundedRectangle(cornerRadius: 14)
|
||||||
.fill(.ultraThinMaterial)
|
.fill(.ultraThinMaterial)
|
||||||
.shadow(color: .black.opacity(0.15), radius: 8, x: 0, y: 4)
|
.shadow(color: .black.opacity(0.15), radius: 8, x: 0, y: 4)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ struct BugListPopover: View {
|
||||||
}
|
}
|
||||||
Button("Mark all seen") {
|
Button("Mark all seen") {
|
||||||
bugStore.markAllSeen()
|
bugStore.markAllSeen()
|
||||||
AppDelegate.shared?.updateBadge(count: bugStore.unseenActiveCount)
|
AppDelegate.shared?.updateBadge(count: bugStore.activeBugs.count)
|
||||||
}
|
}
|
||||||
.font(.caption)
|
.font(.caption)
|
||||||
}
|
}
|
||||||
|
|
@ -62,7 +62,7 @@ struct BugListPopover: View {
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
openInFeishu(bug)
|
openInFeishu(bug)
|
||||||
bugStore.markSeen(bug.id)
|
bugStore.markSeen(bug.id)
|
||||||
AppDelegate.shared?.updateBadge(count: bugStore.unseenActiveCount)
|
AppDelegate.shared?.updateBadge(count: bugStore.activeBugs.count)
|
||||||
}
|
}
|
||||||
Divider().padding(.leading, 44)
|
Divider().padding(.leading, 44)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue