Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions NotchIA.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1277,15 +1277,15 @@
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 20806;
CURRENT_PROJECT_VERSION = 20807;
DEVELOPMENT_TEAM = "";
ENABLE_HARDENED_RUNTIME = NO;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = NotchIAXPCHelper/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = NotchIAXPCHelper;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
MACOSX_DEPLOYMENT_TARGET = 15.0;
MARKETING_VERSION = 2.8.6;
MARKETING_VERSION = 2.8.7;
PRODUCT_BUNDLE_IDENTIFIER = com.coaxel2.notchia.NotchIAXPCHelper;
PRODUCT_NAME = "$(TARGET_NAME)";
REGISTER_APP_GROUPS = YES;
Expand All @@ -1303,15 +1303,15 @@
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 20806;
CURRENT_PROJECT_VERSION = 20807;
DEVELOPMENT_TEAM = "";
ENABLE_HARDENED_RUNTIME = NO;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = NotchIAXPCHelper/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = NotchIAXPCHelper;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
MACOSX_DEPLOYMENT_TARGET = 15.0;
MARKETING_VERSION = 2.8.6;
MARKETING_VERSION = 2.8.7;
PRODUCT_BUNDLE_IDENTIFIER = com.coaxel2.notchia.NotchIAXPCHelper;
PRODUCT_NAME = "$(TARGET_NAME)";
REGISTER_APP_GROUPS = YES;
Expand Down Expand Up @@ -1462,7 +1462,7 @@
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 20806;
CURRENT_PROJECT_VERSION = 20807;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "\"NotchIA/Preview Content\"";
DEVELOPMENT_TEAM = "";
Expand Down Expand Up @@ -1490,7 +1490,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 15.0;
MARKETING_VERSION = 2.8.6;
MARKETING_VERSION = 2.8.7;
PRODUCT_BUNDLE_IDENTIFIER = com.coaxel2.notchia;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
Expand Down Expand Up @@ -1518,7 +1518,7 @@
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = YES;
CURRENT_PROJECT_VERSION = 20806;
CURRENT_PROJECT_VERSION = 20807;
DEAD_CODE_STRIPPING = YES;
DEPLOYMENT_POSTPROCESSING = YES;
DEVELOPMENT_ASSET_PATHS = "\"NotchIA/Preview Content\"";
Expand Down Expand Up @@ -1546,7 +1546,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 15.0;
MARKETING_VERSION = 2.8.6;
MARKETING_VERSION = 2.8.7;
PRODUCT_BUNDLE_IDENTIFIER = com.coaxel2.notchia;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
Expand Down
4 changes: 4 additions & 0 deletions NotchIA/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,10 @@ struct ContentView: View {
}

private var shouldShowCodeAssistantCompactActivity: Bool {
// Pro lockdown : la live-activity "AI session active" est une feature
// Pro (onglet `.claudeCode` est requiresPro). Free users ne la voient
// jamais, peu importe leurs Defaults — pas de fuite d'existence.
guard LicenseManager.shared.state.isPro else { return false }
guard !coordinator.expandingView.show,
!vm.hideOnClosed,
Defaults[.enableClaudeCode],
Expand Down
7 changes: 6 additions & 1 deletion NotchIA/NotchIAApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -280,8 +280,13 @@ class AppDelegate: NSObject, NSApplicationDelegate {
}

private func setupDragDetectorForScreen(_ screen: NSScreen) {
// Pro lockdown : le drag-detector existe pour ouvrir l'onglet Shelf
// au drag-and-drop d'un fichier sur l'encoche. Shelf est requiresPro,
// donc on n'installe pas le détecteur pour les users free — pas de
// fuite d'existence de la feature.
guard LicenseManager.shared.state.isPro else { return }
guard let uuid = screen.displayUUID else { return }

let screenFrame = screen.frame
let notchHeight = openNotchSize.height
let notchWidth = openNotchSize.width
Expand Down
3 changes: 3 additions & 0 deletions NotchIA/components/Notch/NotchIAHeader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ struct NotchIAHeader: View {
@EnvironmentObject var vm: NotchIAViewModel
@ObservedObject var coordinator = NotchIAViewCoordinator.shared
@ObservedObject var screenLockManager = ScreenLockManager.shared
// Observé pour que le filtre `.requiresPro` de la barre d'onglets
// re-rende quand la licence change (activation/révocation à la volée).
@ObservedObject private var license = LicenseManager.shared
@Default(.appGradientTheme) private var gradientTheme
@Namespace var animation

Expand Down
4 changes: 4 additions & 0 deletions NotchIA/components/Tabs/TabSelectionView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ import SwiftUI

struct TabSelectionView: View {
@ObservedObject var coordinator = NotchIAViewCoordinator.shared
// Observé pour que le filtre `.requiresPro` re-rende quand la licence
// change (activation/révocation à la volée → onglets Pro apparaissent
// ou disparaissent immédiatement).
@ObservedObject private var license = LicenseManager.shared
@Default(.appGradientTheme) private var theme
@Namespace var animation

Expand Down
18 changes: 18 additions & 0 deletions NotchIA/enums/generic.swift
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,25 @@ extension NotchViews {
}
}

/// Onglets gated derrière la licence Pro. Cachés ENTIÈREMENT de la barre
/// d'onglets pour les users free — pas seulement de paywall au clic, mais
/// pas de fuite d'existence non plus. La détection associée en background
/// (ClaudeCode JSONL, Clipboard pasteboard, drag-and-drop Shelf) est aussi
/// désactivée pour les users free dans leurs managers respectifs.
var requiresPro: Bool {
switch self {
case .shelf, .claudeCode, .clipboard: return true
case .media, .calendar, .digest, .pomodoro: return false
}
}

@MainActor
var isVisibleInExpandedNotch: Bool {
// Pro lockdown : si l'onglet est Pro et l'utilisateur n'a pas de
// licence active, on le masque entièrement de la barre.
if requiresPro && !LicenseManager.shared.state.isPro {
return false
}
switch self {
case .media:
return Defaults[.showMediaTab]
Expand Down
8 changes: 8 additions & 0 deletions NotchIA/managers/ClaudeCodeManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,14 @@ final class ClaudeCodeManager: ObservableObject {
/// scan timer doesn't stall the main actor for 5-50ms (or much more
/// when the system is under load).
func scanForSessions() async {
// Pro lockdown : pas de scan des sessions Claude Code pour les users
// sans licence Pro. L'onglet IA Code (`.claudeCode`) est requiresPro
// et la live-activity compact dans l'encoche aussi — pas de scan,
// pas de session trackée, pas de fuite d'existence de la feature.
guard LicenseManager.shared.state.isPro else {
await MainActor.run { self.availableSessions = [] }
return
}
let fm = FileManager.default

var sessions: [ClaudeSession] = []
Expand Down
6 changes: 5 additions & 1 deletion NotchIA/managers/ClipboardManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,11 @@ final class ClipboardManager: ObservableObject {
}

private func checkPasteboard() {
guard Defaults[.enableClipboardHistory] else { return }
// Pro lockdown : aucune entrée du presse-papiers n'est enregistrée
// pour les users sans licence Pro. L'historique est une feature Pro
// (l'onglet `.clipboard` est requiresPro) — `items` reste vide tant
// que l'utilisateur n'a pas activé sa licence.
guard Defaults[.enableClipboardHistory], LicenseManager.shared.state.isPro else { return }
let pb = NSPasteboard.general
guard pb.changeCount != lastChangeCount else { return }
lastChangeCount = pb.changeCount
Expand Down
4 changes: 4 additions & 0 deletions NotchIA/managers/CodexManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ final class CodexManager: ObservableObject {
}

func scanForSessions() {
// Pro lockdown : pas de scan des sessions Codex pour les users free.
// L'onglet IA Code (`.claudeCode`) est requiresPro et son provider
// Codex aussi. Pas de fuite d'existence.
guard LicenseManager.shared.state.isPro else { return }
// Snapshot caches (value types) so the background task has its own copy.
let scanner = CodexSessionScanner(
indexFile: indexFile,
Expand Down
6 changes: 6 additions & 0 deletions NotchIA/managers/CopilotManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,12 @@ final class CopilotManager: ObservableObject {
}

private func checkCopilotStatus() {
// Pro lockdown : pas de scan des logs Copilot pour les users free.
// Provider Copilot affilié à l'onglet IA Code requiresPro.
guard LicenseManager.shared.state.isPro else {
if isActive { isActive = false }
return
}
statusTicket &+= 1
let ticket = statusTicket
let reader = logReader
Expand Down
20 changes: 10 additions & 10 deletions updater/appcast.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,16 @@
-->
<rss xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle" version="2.0">
<channel>
<item>
<title>2.8.7</title>
<pubDate>Mon, 25 May 2026 23:52:28 +0000</pubDate>
<link>https://github.com/coaxel2/NotchIA/releases</link>
<sparkle:version>20807</sparkle:version>
<sparkle:shortVersionString>2.8.7</sparkle:shortVersionString>
<sparkle:minimumSystemVersion>15.0</sparkle:minimumSystemVersion>
<description><![CDATA[5 layers of Pro gating : hidden tabs, hidden compact AI activity, no clipboard recording, no AI session scanning, no drag detector for free users.]]></description>
<enclosure url="https://github.com/coaxel2/NotchIA/releases/download/v2.8.7/NotchIA.dmg" length="13554233" type="application/octet-stream" sparkle:edSignature="05ezNoKl/jMBSYOfS9/MTWJNfWJE8MA8poho/Lt59shOca5A0wsE1lA8UC1rZgnrQMIrZKD6FHcT453oykUJCQ=="/>
</item>
<item>
<title>2.8.6</title>
<pubDate>Mon, 25 May 2026 23:37:23 +0000</pubDate>
Expand All @@ -52,16 +62,6 @@
<description><![CDATA[Fix bug where v2.8.4 DMG was compiled without FoundationModels SDK because CI used Xcode 16.4. Now picks latest Xcode dynamically.]]></description>
<enclosure url="https://github.com/coaxel2/NotchIA/releases/download/v2.8.5/NotchIA.dmg" length="13193353" type="application/octet-stream" sparkle:edSignature="Vo9w+zOTLI1t99u90Ff2wvavVHkFoMMDu8FBckEQyePCEcO7uvEKetPfkVvKkHzaS0klwwH8uPIMpHZKXWeWBg=="/>
</item>
<item>
<title>2.8.4</title>
<pubDate>Mon, 25 May 2026 23:13:24 +0000</pubDate>
<link>https://github.com/coaxel2/NotchIA/releases</link>
<sparkle:version>20804</sparkle:version>
<sparkle:shortVersionString>2.8.4</sparkle:shortVersionString>
<sparkle:minimumSystemVersion>15.0</sparkle:minimumSystemVersion>
<description><![CDATA[Fix Digest summary always in French + Shelf 'Apple Intelligence indisponible' string not localized.]]></description>
<enclosure url="https://github.com/coaxel2/NotchIA/releases/download/v2.8.4/NotchIA.dmg" length="13193339" type="application/octet-stream" sparkle:edSignature="o46kgThZAGJIjJgmJZ3p3erzWa5Ft8nlb4qkRqGi5lcAxsXiqDq9FSeORHiPtRr9D5RVcLV/2NbvNn+ZVaKdBg=="/>
</item>
<item>
<title>2.7.3</title>
<pubDate>Mon, 24 Nov 2025 08:07:37 +0000</pubDate>
Expand Down
Loading