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 = 20800;
CURRENT_PROJECT_VERSION = 20801;
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.0;
MARKETING_VERSION = 2.8.1;
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 = 20800;
CURRENT_PROJECT_VERSION = 20801;
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.0;
MARKETING_VERSION = 2.8.1;
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 = 20800;
CURRENT_PROJECT_VERSION = 20801;
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.0;
MARKETING_VERSION = 2.8.1;
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 = 20800;
CURRENT_PROJECT_VERSION = 20801;
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.0;
MARKETING_VERSION = 2.8.1;
PRODUCT_BUNDLE_IDENTIFIER = com.coaxel2.notchia;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
Expand Down
24 changes: 24 additions & 0 deletions NotchIA/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,30 @@ struct ContentView: View {
}
.foregroundStyle(.gray)
.padding(.bottom, 10)
} else if coordinator.sneakPeek.type == .focus {
// Peek 2.5s à l'activation/désactivation d'un Mode Focus.
// value == 1.0 → activé (icône Focus + label), value == 0 → désactivé.
HStack(spacing: 6) {
Image(systemName: coordinator.sneakPeek.icon.isEmpty ? "moon.fill" : coordinator.sneakPeek.icon)
.font(.system(size: 11, weight: .semibold))
.foregroundStyle(coordinator.sneakPeek.value > 0 ? .purple : .gray)
Text(
coordinator.sneakPeek.value > 0
? String(localized: "\(focusModeManager.focusLabel) activé")
: String(localized: "Focus désactivé")
)
.font(.system(size: 11, weight: .medium, design: .rounded))
.foregroundStyle(.white.opacity(0.9))
.lineLimit(1)
}
.padding(.horizontal, 10)
.padding(.vertical, 4)
.background(
Capsule()
.fill(Color.black)
.stroke(Color.white.opacity(0.1), lineWidth: 1)
)
.padding(.bottom, 10)
}
}
}
Expand Down
58 changes: 57 additions & 1 deletion NotchIA/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -42695,7 +42695,63 @@
}
}
},
"Σ": {}
"Σ": {},
"%@ activé": {
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "%@ on"
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value": "%@ activé"
}
},
"es": {
"stringUnit": {
"state": "translated",
"value": "%@ activado"
}
},
"de": {
"stringUnit": {
"state": "translated",
"value": "%@ aktiv"
}
}
}
},
"Focus désactivé": {
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Focus off"
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value": "Focus désactivé"
}
},
"es": {
"stringUnit": {
"state": "translated",
"value": "Focus desactivado"
}
},
"de": {
"stringUnit": {
"state": "translated",
"value": "Focus aus"
}
}
}
}
},
"version": "1.0"
}
8 changes: 7 additions & 1 deletion NotchIA/NotchIAViewCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ enum SneakContentType {
case download
case pomodoro
case clipboard
/// Focus / Ne pas déranger activé ou désactivé. Déclenché par
/// `FocusModeManager` quand `isActive` change. Durée du peek 2.5s.
case focus
}

struct sneakPeek {
Expand Down Expand Up @@ -251,7 +254,10 @@ class NotchIAViewCoordinator: ObservableObject {
icon: String = ""
) {
sneakPeekDuration = duration
if type != .music && type != .pomodoro && type != .screenRecording {
// Le peek `.focus` est une notification d'état (activation/désactivation
// d'un Mode Focus), pas un HUD de remplacement — il s'affiche peu importe
// le réglage hudReplacement, comme music/pomodoro/screenRecording.
if type != .music && type != .pomodoro && type != .screenRecording && type != .focus {
// close()
if !Defaults[.hudReplacement] {
return
Expand Down
19 changes: 19 additions & 0 deletions NotchIA/managers/FocusModeManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,25 @@ final class FocusModeManager: ObservableObject {
}
}
.store(in: &cancellables)

// Peek 2.5s quand le mode Focus change (on/off). dropFirst() évite
// de fire au boot quand l'état initial est calculé. removeDuplicates
// dédoublonne les notifications privées qui se déclenchent en rafale.
$isActive
.dropFirst()
.removeDuplicates()
.sink { [weak self] active in
guard let self else { return }
guard Defaults[.enableFocusModeDetection] else { return }
NotchIAViewCoordinator.shared.toggleSneakPeek(
status: true,
type: .focus,
duration: 2.5,
value: active ? 1.0 : 0.0,
icon: active ? self.focusIcon : "moon.slash.fill"
)
}
.store(in: &cancellables)
}

private func startMonitoring() {
Expand Down