mirror of
https://github.com/FBukovina/Atoll.git
synced 2026-10-27 15:14:33 +00:00
Update alert UI and button changes
This commit is contained in:
parent
adc28fcf2f
commit
24009f7b81
7 changed files with 96 additions and 9 deletions
|
|
@ -851,7 +851,7 @@ struct ContentView: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func shouldPreventAutoClose() -> Bool {
|
private func shouldPreventAutoClose() -> Bool {
|
||||||
hasAnyActivePopovers() || SharingStateManager.shared.preventNotchClose
|
hasAnyActivePopovers() || vm.isAutoCloseSuppressed || SharingStateManager.shared.preventNotchClose
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper to prevent rapid haptic feedback
|
// Helper to prevent rapid haptic feedback
|
||||||
|
|
|
||||||
|
|
@ -5295,6 +5295,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Clear Clipboard History?" : {
|
||||||
|
"comment" : "An alert title that asks the user to confirm clearing their clipboard history.",
|
||||||
|
"isCommentAutoGenerated" : true
|
||||||
|
},
|
||||||
"Clear Color History" : {
|
"Clear Color History" : {
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"fr" : {
|
"fr" : {
|
||||||
|
|
@ -5331,6 +5335,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Clear History" : {
|
||||||
|
"comment" : "The text on a button that clears the clipboard history.",
|
||||||
|
"isCommentAutoGenerated" : true
|
||||||
|
},
|
||||||
"Clear Pinned Items" : {
|
"Clear Pinned Items" : {
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"fr" : {
|
"fr" : {
|
||||||
|
|
@ -6716,6 +6724,9 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Delete All Notes?" : {
|
||||||
|
|
||||||
},
|
},
|
||||||
"Delete Animation" : {
|
"Delete Animation" : {
|
||||||
"comment" : "The title of an alert that appears when trying to delete a custom animation.",
|
"comment" : "The title of an alert that appears when trying to delete a custom animation.",
|
||||||
|
|
@ -18822,6 +18833,13 @@
|
||||||
"comment" : "A footer description for the custom timer settings, explaining their purpose.",
|
"comment" : "A footer description for the custom timer settings, explaining their purpose.",
|
||||||
"isCommentAutoGenerated" : true
|
"isCommentAutoGenerated" : true
|
||||||
},
|
},
|
||||||
|
"This permanently removes every saved note and its attachments." : {
|
||||||
|
|
||||||
|
},
|
||||||
|
"This removes every saved clipboard item from the notch tab." : {
|
||||||
|
"comment" : "A message displayed when they clear their clipboard history.",
|
||||||
|
"isCommentAutoGenerated" : true
|
||||||
|
},
|
||||||
"Time Range" : {
|
"Time Range" : {
|
||||||
"extractionState" : "stale",
|
"extractionState" : "stale",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,8 @@ struct DynamicIslandHeader: View {
|
||||||
@State private var showTimerPopover = false
|
@State private var showTimerPopover = false
|
||||||
@Default(.enableTimerFeature) var enableTimerFeature
|
@Default(.enableTimerFeature) var enableTimerFeature
|
||||||
@Default(.timerDisplayMode) var timerDisplayMode
|
@Default(.timerDisplayMode) var timerDisplayMode
|
||||||
|
@Default(.showClipboardIcon) var showClipboardIcon
|
||||||
|
@Default(.clipboardDisplayMode) var clipboardDisplayMode
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
HStack(spacing: 0) {
|
HStack(spacing: 0) {
|
||||||
|
|
@ -68,10 +70,12 @@ struct DynamicIslandHeader: View {
|
||||||
.buttonStyle(PlainButtonStyle())
|
.buttonStyle(PlainButtonStyle())
|
||||||
}
|
}
|
||||||
|
|
||||||
if Defaults[.enableClipboardManager] && Defaults[.showClipboardIcon] {
|
if Defaults[.enableClipboardManager]
|
||||||
|
&& showClipboardIcon
|
||||||
|
&& clipboardDisplayMode != .separateTab {
|
||||||
Button(action: {
|
Button(action: {
|
||||||
// Switch behavior based on display mode
|
// Switch behavior based on display mode
|
||||||
switch Defaults[.clipboardDisplayMode] {
|
switch clipboardDisplayMode {
|
||||||
case .panel:
|
case .panel:
|
||||||
ClipboardPanelManager.shared.toggleClipboardPanel()
|
ClipboardPanelManager.shared.toggleClipboardPanel()
|
||||||
case .popover:
|
case .popover:
|
||||||
|
|
@ -237,7 +241,7 @@ struct DynamicIslandHeader: View {
|
||||||
.onChange(of: coordinator.shouldToggleClipboardPopover) { _ in
|
.onChange(of: coordinator.shouldToggleClipboardPopover) { _ in
|
||||||
// Only toggle if clipboard is enabled
|
// Only toggle if clipboard is enabled
|
||||||
if Defaults[.enableClipboardManager] {
|
if Defaults[.enableClipboardManager] {
|
||||||
switch Defaults[.clipboardDisplayMode] {
|
switch clipboardDisplayMode {
|
||||||
case .panel:
|
case .panel:
|
||||||
ClipboardPanelManager.shared.toggleClipboardPanel()
|
ClipboardPanelManager.shared.toggleClipboardPanel()
|
||||||
case .popover:
|
case .popover:
|
||||||
|
|
@ -253,7 +257,7 @@ struct DynamicIslandHeader: View {
|
||||||
}
|
}
|
||||||
.onReceive(NotificationCenter.default.publisher(for: NSNotification.Name("ToggleClipboardPopover"))) { _ in
|
.onReceive(NotificationCenter.default.publisher(for: NSNotification.Name("ToggleClipboardPopover"))) { _ in
|
||||||
// Handle keyboard shortcut for popover mode
|
// Handle keyboard shortcut for popover mode
|
||||||
if Defaults[.enableClipboardManager] && Defaults[.clipboardDisplayMode] == .popover {
|
if Defaults[.enableClipboardManager] && clipboardDisplayMode == .popover {
|
||||||
showClipboardPopover.toggle()
|
showClipboardPopover.toggle()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -351,6 +351,8 @@ struct NotchClipboardList: View {
|
||||||
@State private var justCopiedId: UUID?
|
@State private var justCopiedId: UUID?
|
||||||
@State private var suppressionToken = UUID()
|
@State private var suppressionToken = UUID()
|
||||||
@State private var isSuppressing = false
|
@State private var isSuppressing = false
|
||||||
|
@State private var showClearHistoryAlert = false
|
||||||
|
@State private var autoCloseToken = UUID()
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(spacing: 0) {
|
VStack(spacing: 0) {
|
||||||
|
|
@ -363,10 +365,10 @@ struct NotchClipboardList: View {
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
if !clipboardManager.clipboardHistory.isEmpty {
|
if !clipboardManager.clipboardHistory.isEmpty {
|
||||||
Button(action: { clipboardManager.clearHistory() }) {
|
Button(action: { showClearHistoryAlert = true }) {
|
||||||
Image(systemName: "trash")
|
Image(systemName: "trash")
|
||||||
.font(.system(size: 14))
|
.font(.system(size: 14))
|
||||||
.foregroundStyle(.white.opacity(0.6))
|
.foregroundStyle(.red)
|
||||||
.padding(6)
|
.padding(6)
|
||||||
.background(Color.white.opacity(0.1))
|
.background(Color.white.opacity(0.1))
|
||||||
.clipShape(Circle())
|
.clipShape(Circle())
|
||||||
|
|
@ -432,6 +434,17 @@ struct NotchClipboardList: View {
|
||||||
.onDisappear {
|
.onDisappear {
|
||||||
updateSuppression(for: false)
|
updateSuppression(for: false)
|
||||||
}
|
}
|
||||||
|
.alert("Clear Clipboard History?", isPresented: $showClearHistoryAlert) {
|
||||||
|
Button("Clear History", role: .destructive) {
|
||||||
|
clipboardManager.clearHistory()
|
||||||
|
}
|
||||||
|
Button("Cancel", role: .cancel) {}
|
||||||
|
} message: {
|
||||||
|
Text("This removes every saved clipboard item from the notch tab.")
|
||||||
|
}
|
||||||
|
.onChange(of: showClearHistoryAlert) { _, isShowing in
|
||||||
|
vm.setAutoCloseSuppression(isShowing, token: autoCloseToken)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateSuppression(for hovering: Bool) {
|
private func updateSuppression(for hovering: Bool) {
|
||||||
|
|
@ -513,6 +526,8 @@ struct NoteListView: View {
|
||||||
@State private var isSearchExpanded = false
|
@State private var isSearchExpanded = false
|
||||||
@State private var suppressionToken = UUID()
|
@State private var suppressionToken = UUID()
|
||||||
@State private var isSuppressing = false
|
@State private var isSuppressing = false
|
||||||
|
@State private var showClearNotesAlert = false
|
||||||
|
@State private var autoCloseToken = UUID()
|
||||||
|
|
||||||
var sortedNotes: [NoteItem] {
|
var sortedNotes: [NoteItem] {
|
||||||
var filtered = searchText.isEmpty ? notes : notes.filter {
|
var filtered = searchText.isEmpty ? notes : notes.filter {
|
||||||
|
|
@ -575,11 +590,11 @@ struct NoteListView: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !notes.isEmpty {
|
if !notes.isEmpty {
|
||||||
Button(action: onClearAll) {
|
Button(action: { showClearNotesAlert = true }) {
|
||||||
Image(systemName: "trash")
|
Image(systemName: "trash")
|
||||||
.font(.system(size: 14))
|
.font(.system(size: 14))
|
||||||
.frame(width: 16, height: 16)
|
.frame(width: 16, height: 16)
|
||||||
.foregroundStyle(.white.opacity(0.6))
|
.foregroundStyle(.red)
|
||||||
.padding(5)
|
.padding(5)
|
||||||
.background(Color.white.opacity(0.1))
|
.background(Color.white.opacity(0.1))
|
||||||
.clipShape(Circle())
|
.clipShape(Circle())
|
||||||
|
|
@ -710,6 +725,17 @@ struct NoteListView: View {
|
||||||
.onDisappear {
|
.onDisappear {
|
||||||
updateSuppression(for: false)
|
updateSuppression(for: false)
|
||||||
}
|
}
|
||||||
|
.alert("Delete All Notes?", isPresented: $showClearNotesAlert) {
|
||||||
|
Button("Delete", role: .destructive) {
|
||||||
|
onClearAll()
|
||||||
|
}
|
||||||
|
Button("Cancel", role: .cancel) {}
|
||||||
|
} message: {
|
||||||
|
Text("This permanently removes every saved note and its attachments.")
|
||||||
|
}
|
||||||
|
.onChange(of: showClearNotesAlert) { _, isShowing in
|
||||||
|
vm.setAutoCloseSuppression(isShowing, token: autoCloseToken)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateSuppression(for hovering: Bool) {
|
private func updateSuppression(for hovering: Bool) {
|
||||||
|
|
|
||||||
|
|
@ -727,6 +727,9 @@ struct SettingsView: View {
|
||||||
|
|
||||||
private func isTabVisible(_ tab: SettingsTab) -> Bool {
|
private func isTabVisible(_ tab: SettingsTab) -> Bool {
|
||||||
switch tab {
|
switch tab {
|
||||||
|
case .notes:
|
||||||
|
// Keep notes configuration visible even when other tabs are hidden in minimalistic mode
|
||||||
|
return true
|
||||||
case .timer, .stats, .clipboard, .screenAssistant, .colorPicker, .shelf:
|
case .timer, .stats, .clipboard, .screenAssistant, .colorPicker, .shelf:
|
||||||
return !enableMinimalisticUI
|
return !enableMinimalisticUI
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -160,6 +160,7 @@ class ClipboardManager: ObservableObject {
|
||||||
@Published var clipboardHistory: [ClipboardItem] = []
|
@Published var clipboardHistory: [ClipboardItem] = []
|
||||||
@Published var pinnedItems: [ClipboardItem] = []
|
@Published var pinnedItems: [ClipboardItem] = []
|
||||||
@Published var isMonitoring: Bool = false
|
@Published var isMonitoring: Bool = false
|
||||||
|
@Published private(set) var lastCopiedItemDate: Date?
|
||||||
|
|
||||||
private var timer: Timer?
|
private var timer: Timer?
|
||||||
private var lastChangeCount: Int = 0
|
private var lastChangeCount: Int = 0
|
||||||
|
|
@ -450,6 +451,7 @@ class ClipboardManager: ObservableObject {
|
||||||
|
|
||||||
// Add to beginning of array
|
// Add to beginning of array
|
||||||
self.clipboardHistory.insert(item, at: 0)
|
self.clipboardHistory.insert(item, at: 0)
|
||||||
|
self.lastCopiedItemDate = item.timestamp
|
||||||
|
|
||||||
// Keep only the most recent items and clean up old files
|
// Keep only the most recent items and clean up old files
|
||||||
let itemsToDelete = Array(self.clipboardHistory.dropFirst(self.maxHistoryItems))
|
let itemsToDelete = Array(self.clipboardHistory.dropFirst(self.maxHistoryItems))
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,9 @@ class DynamicIslandViewModel: NSObject, ObservableObject {
|
||||||
@Published var shouldRecheckHover: Bool = false
|
@Published var shouldRecheckHover: Bool = false
|
||||||
@Published var isScrollGestureActive: Bool = false
|
@Published var isScrollGestureActive: Bool = false
|
||||||
private var scrollGestureSuppressionTokens: Set<UUID> = []
|
private var scrollGestureSuppressionTokens: Set<UUID> = []
|
||||||
|
@Published private(set) var isAutoCloseSuppressed: Bool = false
|
||||||
|
private var autoCloseSuppressionTokens: Set<UUID> = []
|
||||||
|
private let clipboardFocusWindow: TimeInterval = 10
|
||||||
|
|
||||||
func setScrollGestureSuppression(_ active: Bool, token: UUID) {
|
func setScrollGestureSuppression(_ active: Bool, token: UUID) {
|
||||||
if active {
|
if active {
|
||||||
|
|
@ -57,6 +60,34 @@ class DynamicIslandViewModel: NSObject, ObservableObject {
|
||||||
isScrollGestureActive = false
|
isScrollGestureActive = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setAutoCloseSuppression(_ active: Bool, token: UUID) {
|
||||||
|
if active {
|
||||||
|
let inserted = autoCloseSuppressionTokens.insert(token).inserted
|
||||||
|
if inserted {
|
||||||
|
isAutoCloseSuppressed = true
|
||||||
|
}
|
||||||
|
} else if autoCloseSuppressionTokens.remove(token) != nil {
|
||||||
|
isAutoCloseSuppressed = !autoCloseSuppressionTokens.isEmpty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func resetAutoCloseSuppression() {
|
||||||
|
autoCloseSuppressionTokens.removeAll()
|
||||||
|
isAutoCloseSuppressed = false
|
||||||
|
}
|
||||||
|
|
||||||
|
private func focusClipboardTabIfNeeded() {
|
||||||
|
guard !Defaults[.enableMinimalisticUI] else { return }
|
||||||
|
guard Defaults[.enableClipboardManager] else { return }
|
||||||
|
guard Defaults[.clipboardDisplayMode] == .separateTab else { return }
|
||||||
|
guard let lastCopyDate = ClipboardManager.shared.lastCopiedItemDate else { return }
|
||||||
|
guard Date().timeIntervalSince(lastCopyDate) <= clipboardFocusWindow else { return }
|
||||||
|
guard coordinator.currentView != .notes else { return }
|
||||||
|
withAnimation(.smooth) {
|
||||||
|
coordinator.currentView = .notes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let webcamManager = WebcamManager.shared
|
let webcamManager = WebcamManager.shared
|
||||||
@Published var isCameraExpanded: Bool = false
|
@Published var isCameraExpanded: Bool = false
|
||||||
@Published var isRequestingAuthorization: Bool = false
|
@Published var isRequestingAuthorization: Bool = false
|
||||||
|
|
@ -305,6 +336,7 @@ class DynamicIslandViewModel: NSObject, ObservableObject {
|
||||||
|
|
||||||
// Force music information update when notch is opened
|
// Force music information update when notch is opened
|
||||||
MusicManager.shared.forceUpdate()
|
MusicManager.shared.forceUpdate()
|
||||||
|
focusClipboardTabIfNeeded()
|
||||||
}
|
}
|
||||||
|
|
||||||
private func calculateDynamicNotchSize() -> CGSize {
|
private func calculateDynamicNotchSize() -> CGSize {
|
||||||
|
|
@ -330,6 +362,7 @@ class DynamicIslandViewModel: NSObject, ObservableObject {
|
||||||
closedNotchSize = targetSize
|
closedNotchSize = targetSize
|
||||||
notchState = .closed
|
notchState = .closed
|
||||||
resetScrollGestureSuppression()
|
resetScrollGestureSuppression()
|
||||||
|
resetAutoCloseSuppression()
|
||||||
|
|
||||||
// Set the current view to shelf if it contains files and the user enables openShelfByDefault
|
// Set the current view to shelf if it contains files and the user enables openShelfByDefault
|
||||||
// Otherwise, if the user has not enabled openLastShelfByDefault, set the view to home
|
// Otherwise, if the user has not enabled openLastShelfByDefault, set the view to home
|
||||||
|
|
@ -347,6 +380,7 @@ class DynamicIslandViewModel: NSObject, ObservableObject {
|
||||||
closedNotchSize = targetSize
|
closedNotchSize = targetSize
|
||||||
notchState = .closed
|
notchState = .closed
|
||||||
resetScrollGestureSuppression()
|
resetScrollGestureSuppression()
|
||||||
|
resetAutoCloseSuppression()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue