mirror of
https://github.com/carey314/mio-plugin-fund.git
synced 2026-08-10 05:44:31 +00:00
Add operation feedback across the three interactive paths in 看盘侠: - Toast: ObservableObject + view modifier, lime/red/yellow palette matching FundTheme. Auto-dismiss after 2.6s, click to dismiss. - ConfirmDialog: programmatic ask() returning async Bool via a captured CheckedContinuation. Danger flag flips the confirm button to a red palette. - HoldingsView: row remove now asks for confirmation (the trash UI is a hover-only ✕ — easy to misclick); on confirm, row slides out to the leading edge with a spring + a success toast lands. - HoldingsView: position edit Save / Clear surface the right semantic toast (success for save, info for clear). - AddView: adding a fund toasts the name; tapping an already-added row toasts an info reminder rather than silently no-op'ing. Bump version 0.2.0 → 0.3.0 (Info.plist + FundPlugin.version). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
53 lines
1.4 KiB
Swift
53 lines
1.4 KiB
Swift
//
|
|
// FundPlugin.swift
|
|
// Mio Island plugin: 盯基金
|
|
//
|
|
// Principal class. Module = FundPlugin, Class = FundPlugin →
|
|
// NSPrincipalClass = "FundPlugin.FundPlugin".
|
|
//
|
|
|
|
import AppKit
|
|
import SwiftUI
|
|
|
|
final class FundPlugin: NSObject, MioPlugin {
|
|
var id: String { "fund" }
|
|
var name: String { "看盘侠" }
|
|
var icon: String { "chart.line.uptrend.xyaxis" }
|
|
var version: String { "0.3.0" }
|
|
|
|
func activate() {
|
|
FundDebugLog.write("plugin activate")
|
|
// Kick off the refresh loops as soon as the plugin enables.
|
|
// The store is a singleton so the loops survive panel show/hide.
|
|
Task { @MainActor in
|
|
FundStore.shared.start()
|
|
await FundStore.shared.refreshNow()
|
|
}
|
|
}
|
|
|
|
func deactivate() {
|
|
FundDebugLog.write("plugin deactivate")
|
|
Task { @MainActor in
|
|
FundStore.shared.stop()
|
|
}
|
|
}
|
|
|
|
func makeView() -> NSView {
|
|
let view = NSHostingView(rootView: ExpandedView())
|
|
view.autoresizingMask = [.width, .height]
|
|
return view
|
|
}
|
|
|
|
@objc func viewForSlot(_ slot: String, context: [String: Any]) -> NSView? {
|
|
switch slot {
|
|
case "header":
|
|
let v = NSHostingView(rootView: HeaderSlotView())
|
|
v.frame = NSRect(x: 0, y: 0, width: 20, height: 20)
|
|
v.setFrameSize(NSSize(width: 20, height: 20))
|
|
return v
|
|
default:
|
|
return nil
|
|
}
|
|
}
|
|
}
|