diff --git a/Clipy/Sources/Managers/MenuManager.swift b/Clipy/Sources/Managers/MenuManager.swift index 04bf68c..bb73b4c 100644 --- a/Clipy/Sources/Managers/MenuManager.swift +++ b/Clipy/Sources/Managers/MenuManager.swift @@ -2486,20 +2486,22 @@ class BoardManPanel: NSPanel { licenseLimitsLabel = limitsLabel let licenseKey = NSTextField(frame: .zero) - licenseKey.placeholderString = "XXXX-XXXX-XXXX-XXXX" + licenseKey.placeholderString = "License activation is not connected yet" licenseKey.font = NSFont.monospacedSystemFont(ofSize: 11, weight: .regular) - licenseKey.toolTip = "Founder codes activate locally. Production licenses still require signed tokens." + licenseKey.isEnabled = false + licenseKey.toolTip = "License activation is a disabled preview in this build." contentView.addSubview(licenseKey) licenseKeyField = licenseKey let activate = NSButton(title: "Activate", target: self, action: #selector(activateLicenseRequested(_:))) activate.font = NSFont.systemFont(ofSize: 11, weight: .medium) activate.bezelStyle = .rounded - activate.toolTip = "Activates an internal founder code locally when it matches." + activate.isEnabled = false + activate.toolTip = "Activation is not connected yet." contentView.addSubview(activate) licenseActivateButton = activate - let activationStatus = NSTextField(labelWithString: "Internal dogfood: founder codes activate locally. Unknown codes stay locked.") + let activationStatus = NSTextField(labelWithString: "Activation is not connected yet. Free remains the default runtime entitlement.") activationStatus.font = NSFont.systemFont(ofSize: 11) activationStatus.textColor = .secondaryLabelColor activationStatus.lineBreakMode = .byWordWrapping @@ -2528,7 +2530,7 @@ class BoardManPanel: NSPanel { contentView.addSubview(lockedProControl) licenseProLockedControlView = lockedProControl - let licenseNote = NSTextField(labelWithString: "Internal dogfood only. Production licensing still requires signed token activation.") + let licenseNote = NSTextField(labelWithString: "Static preview only. 1 license = 1 PC. No backend activation, device binding, or license storage is connected.") licenseNote.font = NSFont.systemFont(ofSize: 11) licenseNote.textColor = .secondaryLabelColor licenseNote.lineBreakMode = .byWordWrapping @@ -4045,12 +4047,8 @@ class BoardManPanel: NSPanel { } @objc private func activateLicenseRequested(_ sender: NSButton) { - let request = LicenseActivationRequest( - licenseKey: licenseKeyField?.stringValue ?? "" - ) - let response = StubLicenseActivationClient().activate(request) - licenseActivationStatusLabel?.stringValue = "\(licenseActivationStatusTitle(response.status)): \(response.message)" - licenseActivationStatusLabel?.textColor = response.status == .activated ? .systemGreen : (response.status == .invalidInput || response.status == .unsupported ? .systemRed : .secondaryLabelColor) + licenseActivationStatusLabel?.stringValue = "Activation is not connected yet. Free remains the default runtime entitlement." + licenseActivationStatusLabel?.textColor = .secondaryLabelColor refreshLicenseSummary() } diff --git a/Clipy/Sources/Preferences/Panels/CPYBetaPreferenceViewController.swift b/Clipy/Sources/Preferences/Panels/CPYBetaPreferenceViewController.swift index 7370ef2..69d0466 100644 --- a/Clipy/Sources/Preferences/Panels/CPYBetaPreferenceViewController.swift +++ b/Clipy/Sources/Preferences/Panels/CPYBetaPreferenceViewController.swift @@ -8,9 +8,12 @@ import Cocoa final class CPYBetaPreferenceViewController: NSViewController { private let licenseField = NSSecureTextField(string: "") - private let validationLabel = BoardManPreferenceUI.label("Awaiting activation", size: 12, color: BoardManPreferenceUI.secondaryText) + private let validationLabel = BoardManPreferenceUI.label("Not connected yet", size: 12, color: BoardManPreferenceUI.secondaryText) private let planLabel = BoardManPreferenceUI.label("Free Plan", size: 28, weight: .bold) private let statusPill = BoardManPreferenceUI.label("Free", size: 12, weight: .semibold) + private let currentPlanValue = BoardManPreferenceUI.label("Free Plan", size: 12, weight: .semibold) + private let statusValue = BoardManPreferenceUI.label("Free", size: 12, weight: .semibold) + private let lastVerifiedValue = BoardManPreferenceUI.label("Not verified / Offline", size: 12, weight: .semibold, color: BoardManPreferenceUI.red) private let deviceStatus = BoardManPreferenceUI.label("Not activated", size: 12, color: BoardManPreferenceUI.secondaryText) override func loadView() { @@ -29,38 +32,45 @@ final class CPYBetaPreferenceViewController: NSViewController { statusPill.frame = NSRect(x: 20, y: 118, width: 70, height: 24) BoardManPreferenceUI.prepare(statusPill, color: BoardManPreferenceUI.card, radius: 12, border: BoardManPreferenceUI.borderSubtle) currentPlan.addSubview(statusPill) - currentPlan.addSubview(infoRow("clock", "Last verified:", "Offline", accent: true, y: 78)) - currentPlan.addSubview(infoRow("laptopcomputer", "Device activated:", "Not activated", y: 44)) + currentPlan.addSubview(statusRow("tag", "Current Plan:", currentPlanValue, y: 92)) + currentPlan.addSubview(statusRow("checkmark.seal", "Status:", statusValue, y: 66)) + currentPlan.addSubview(statusRow("clock", "Last verified:", lastVerifiedValue, y: 40)) + currentPlan.addSubview(statusRow("laptopcomputer", "Device activated:", deviceStatus, y: 14)) let upgrade = BoardManPreferenceUI.secondaryButton("Upgrade to Pro ›") upgrade.target = self upgrade.action = #selector(openBuyPro) upgrade.frame = NSRect(x: 200, y: 150, width: 130, height: 38) upgrade.layer?.borderColor = BoardManPreferenceUI.red.withAlphaComponent(0.8).cgColor currentPlan.addSubview(upgrade) - currentPlan.addSubview(BoardManPreferenceUI.label("ā“˜ Pro unlocks advanced customization and unlimited usage.", size: 11, color: BoardManPreferenceUI.secondaryText).positioned(x: 20, y: 18, w: 310, h: 18)) view.addSubview(currentPlan) let activation = card(x: 395, y: 320, w: 405, h: 250, title: "2. License Key Activation", icon: "key") - licenseField.placeholderString = "Enter your license key" + licenseField.placeholderString = "License activation is not connected yet" licenseField.font = NSFont.systemFont(ofSize: 14) licenseField.textColor = BoardManPreferenceUI.primaryText licenseField.backgroundColor = BoardManPreferenceUI.field + licenseField.isEnabled = false + licenseField.toolTip = "License activation is a disabled preview in this build." licenseField.frame = NSRect(x: 20, y: 165, width: 365, height: 38) activation.addSubview(licenseField) let activate = BoardManPreferenceUI.primaryButton("Activate License") activate.target = self activate.action = #selector(activateLicense) + activate.isEnabled = false + activate.toolTip = "Activation is not connected yet." activate.frame = NSRect(x: 20, y: 115, width: 165, height: 38) activation.addSubview(activate) let paste = BoardManPreferenceUI.secondaryButton("Paste from Clipboard") paste.target = self paste.action = #selector(pasteLicense) + paste.isEnabled = false + paste.toolTip = "License input is disabled until activation is implemented." paste.frame = NSRect(x: 195, y: 115, width: 190, height: 38) activation.addSubview(paste) activation.addSubview(BoardManPreferenceUI.label("Validation status:", size: 13, color: BoardManPreferenceUI.secondaryText).positioned(x: 20, y: 78, w: 130, h: 20)) validationLabel.frame = NSRect(x: 150, y: 78, width: 220, height: 20) activation.addSubview(validationLabel) - let empty = BoardManPreferenceUI.label("ā“˜ No license has been activated on this Mac.", size: 13, color: BoardManPreferenceUI.secondaryText) + let empty = BoardManPreferenceUI.label("No license has been activated. Activation is not connected in this build.", size: 13, color: BoardManPreferenceUI.secondaryText) empty.alignment = .center empty.frame = NSRect(x: 20, y: 18, width: 365, height: 44) BoardManPreferenceUI.prepare(empty, color: BoardManPreferenceUI.field, radius: BoardManPreferenceUI.Radius.control, border: BoardManPreferenceUI.borderSubtle) @@ -69,10 +79,10 @@ final class CPYBetaPreferenceViewController: NSViewController { let device = card(x: 820, y: 320, w: 330, h: 250, title: "3. Device Binding", icon: "laptopcomputer") device.addSubview(row("Device name:", Host.current().localizedName ?? "This Mac", y: 165)) - device.addSubview(row("Masked Device ID:", maskedDeviceID(), y: 132)) + device.addSubview(row("Masked Device ID:", "Not activated", y: 132)) device.addSubview(row("Activated at:", "—", y: 99)) - device.addSubview(BoardManPreferenceUI.label("Each Pro license can be activated on one Mac at a time.", size: 13, color: BoardManPreferenceUI.secondaryText).positioned(x: 20, y: 58, w: 285, h: 38)) - let deactivate = BoardManPreferenceUI.secondaryButton("šŸ”’ Deactivate this device") + device.addSubview(BoardManPreferenceUI.label("1 license = 1 PC. Device binding is not connected in this build.", size: 13, color: BoardManPreferenceUI.secondaryText).positioned(x: 20, y: 58, w: 285, h: 38)) + let deactivate = BoardManPreferenceUI.secondaryButton("Deactivate this device") deactivate.isEnabled = false deactivate.frame = NSRect(x: 20, y: 20, width: 290, height: 30) device.addSubview(deactivate) @@ -91,7 +101,7 @@ final class CPYBetaPreferenceViewController: NSViewController { cta.layer?.borderColor = BoardManPreferenceUI.red.withAlphaComponent(0.9).cgColor cta.addSubview(BoardManPreferenceUI.icon("diamond.fill", size: 34).positioned(x: 143, y: 190, w: 44, h: 36)) cta.addSubview(BoardManPreferenceUI.label("Unlock the full power of Board-Man", size: 17, weight: .bold).positioned(x: 45, y: 150, w: 250, h: 26)) - cta.addSubview(BoardManPreferenceUI.label("āœ“ 1 license = 1 PC\nāœ“ Lifetime access for one Mac", size: 14, color: BoardManPreferenceUI.primaryText).positioned(x: 60, y: 95, w: 220, h: 46)) + cta.addSubview(BoardManPreferenceUI.label("1 license = 1 PC\nPro unlocks advanced controls", size: 14, color: BoardManPreferenceUI.primaryText).positioned(x: 60, y: 95, w: 220, h: 46)) let buy = BoardManPreferenceUI.primaryButton("Buy Board-Man Pro ›") buy.target = self buy.action = #selector(openBuyPro) @@ -111,8 +121,13 @@ final class CPYBetaPreferenceViewController: NSViewController { planLabel.stringValue = active ? "Board-Man Pro" : "Free Plan" statusPill.stringValue = active ? "Active" : "Free" statusPill.layer?.backgroundColor = (active ? BoardManPreferenceUI.redSoft : BoardManPreferenceUI.card).cgColor + currentPlanValue.stringValue = active ? "Board-Man Pro" : "Free Plan" + statusValue.stringValue = active ? "Active" : "Free" + lastVerifiedValue.stringValue = active ? "Verified" : "Not verified / Offline" + lastVerifiedValue.textColor = active ? .systemGreen : BoardManPreferenceUI.red deviceStatus.stringValue = active ? "Activated" : "Not activated" - validationLabel.stringValue = active ? "Activated" : "Awaiting activation" + deviceStatus.textColor = active ? .systemGreen : BoardManPreferenceUI.secondaryText + validationLabel.stringValue = active ? "Activated" : "Not connected yet" validationLabel.textColor = active ? .systemGreen : BoardManPreferenceUI.secondaryText } @@ -133,11 +148,12 @@ final class CPYBetaPreferenceViewController: NSViewController { return row } - private func infoRow(_ symbol: String, _ left: String, _ right: String, accent: Bool = false, y: CGFloat) -> NSView { + private func statusRow(_ symbol: String, _ left: String, _ value: NSTextField, y: CGFloat) -> NSView { let row = NSView(frame: NSRect(x: 20, y: y, width: 310, height: 20)) row.addSubview(BoardManPreferenceUI.icon(symbol, size: 13, color: BoardManPreferenceUI.secondaryText).positioned(x: 0, y: 0, w: 18, h: 18)) - row.addSubview(BoardManPreferenceUI.label(left, size: 12, color: BoardManPreferenceUI.secondaryText).positioned(x: 28, y: 0, w: 120, h: 20)) - row.addSubview(BoardManPreferenceUI.label(right, size: 12, weight: .semibold, color: accent ? BoardManPreferenceUI.red : BoardManPreferenceUI.secondaryText).positioned(x: 155, y: 0, w: 140, h: 20)) + row.addSubview(BoardManPreferenceUI.label(left, size: 12, color: BoardManPreferenceUI.secondaryText).positioned(x: 28, y: 0, w: 115, h: 20)) + value.frame = NSRect(x: 145, y: 0, width: 160, height: 20) + row.addSubview(value) return row } @@ -156,23 +172,14 @@ final class CPYBetaPreferenceViewController: NSViewController { view.addSubview(BoardManPreferenceUI.label("Free is useful. Pro removes daily limits and unlocks advanced customization.", size: 13, color: BoardManPreferenceUI.secondaryText).positioned(x: 30, y: 562, w: 520, h: 18)) } - private func maskedDeviceID() -> String { - let id = LocalDeviceIdentityService.shared.deviceID().replacingOccurrences(of: "-", with: "") - guard id.count > 8 else { return "••••" } - return "BMN-••••-" + String(id.suffix(4)).uppercased() - } - @objc private func pasteLicense() { - if let copied = NSPasteboard.general.string(forType: .string) { - licenseField.stringValue = copied.trimmingCharacters(in: .whitespacesAndNewlines) - } + validationLabel.stringValue = "Activation is not connected yet." + validationLabel.textColor = BoardManPreferenceUI.secondaryText } @objc private func activateLicense() { - let response = StubLicenseActivationClient().activate(LicenseActivationRequest(licenseKey: licenseField.stringValue, localDeviceID: LocalDeviceIdentityService.shared.deviceID())) - validationLabel.stringValue = response.message - validationLabel.textColor = response.status == .activated ? .systemGreen : BoardManPreferenceUI.red - refreshPlanState() + validationLabel.stringValue = "Activation is not connected yet." + validationLabel.textColor = BoardManPreferenceUI.secondaryText } @objc private func openBuyPro() {