Fix built-in app grouping and bubble hover settings
| | |
| | | var onDragModeChange: ((Bool) -> Void)? = nil |
| | | var onBubbleHover: ((AppInfo, CGRect, Bool) -> Void)? = nil |
| | | var onEditNote: ((AppInfo, CGRect) -> Void)? = nil |
| | | var itemID: String |
| | | @Binding var hoveredAppItemID: String? |
| | | let onSelect: () -> Void |
| | | |
| | | @State private var isHovered = false |
| | | @State private var wiggle = false |
| | | @State private var interactionFrame: CGRect = .zero |
| | | @AppStorage("showUncommonAppBubbles") private var showUncommonAppBubbles = AppDefaults.showUncommonAppBubbles |
| | |
| | | private var iconSlotSize: CGFloat { iconSize * Self.hoverScale } |
| | | private var labelWidth: CGFloat { iconSize + 20 } |
| | | private var labelHeight: CGFloat { Self.labelHeight } |
| | | private var isHovered: Bool { hoveredAppItemID == itemID } |
| | | |
| | | var body: some View { |
| | | VStack(spacing: 6) { |
| | |
| | | .lineLimit(1) |
| | | .truncationMode(.tail) |
| | | .frame(width: labelWidth, height: labelHeight) |
| | | .opacity(showName ? 1 : (isHovered ? 0.85 : 0)) |
| | | .opacity(showName ? 1 : (shouldShowHoverName ? 0.85 : 0)) |
| | | } |
| | | .padding(.vertical, 8) |
| | | .padding(.horizontal, 4) |
| | |
| | | .background( |
| | | AppGridItemHoverTracker { hovering, frame in |
| | | interactionFrame = frame |
| | | setHoverState(hovering) |
| | | if hovering { |
| | | setHoverState(true) |
| | | guard shouldShowAppBubble else { return } |
| | | onBubbleHover?(app, frame, hovering) |
| | | } else { |
| | | } else if isHovered { |
| | | setHoverState(false) |
| | | onBubbleHover?(app, frame, hovering) |
| | | } else { |
| | | setHoverState(false) |
| | | } |
| | | } |
| | | ) |
| | |
| | | .onChange(of: dragModeActive) { _, active in |
| | | wiggle = active |
| | | } |
| | | .onDisappear { |
| | | if hoveredAppItemID == itemID { |
| | | hoveredAppItemID = nil |
| | | onBubbleHover?(app, interactionFrame, false) |
| | | } |
| | | } |
| | | } |
| | | |
| | | private var shouldShowAppBubble: Bool { |
| | | !showUncommonAppBubbles || app.isUncommon |
| | | } |
| | | |
| | | private var shouldShowHoverName: Bool { |
| | | !showName && !shouldShowAppBubble && isHovered |
| | | } |
| | | |
| | | private func setHoverState(_ hovering: Bool) { |
| | | guard isHovered != hovering else { return } |
| | | withAnimation(hovering ? Self.hoverInAnimation : Self.hoverOutAnimation) { |
| | | isHovered = hovering |
| | | if hovering { |
| | | hoveredAppItemID = itemID |
| | | } else if hoveredAppItemID == itemID { |
| | | hoveredAppItemID = nil |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | @State private var refreshInProgress = false |
| | | @State private var refreshAgainAfterCurrent = false |
| | | @State private var refreshAgainForceLayout = false |
| | | @State private var hoveredAppItemID: String? = nil |
| | | @State private var hoveredBubble: AppBubbleContext? = nil |
| | | @State private var editingBubble: AppBubbleContext? = nil |
| | | @State private var bubbleDraftNote = "" |
| | |
| | | onDragModeChange: { setAppDragMode($0) }, |
| | | onBubbleHover: handleBubbleHover, |
| | | onEditNote: beginEditingBubbleNote, |
| | | hoveredAppItemID: $hoveredAppItemID, |
| | | onDropApp: { path, source, copy in |
| | | dropApp(path: path, sourceTag: source, targetTag: group.name, copy: copy) |
| | | } |
| | |
| | | onDragModeChange: { setAppDragMode($0) }, |
| | | onBubbleHover: handleBubbleHover, |
| | | onEditNote: beginEditingBubbleNote, |
| | | itemID: "\(group.name)|\(app.path.path)", |
| | | hoveredAppItemID: $hoveredAppItemID, |
| | | onSelect: { openApp(app) } |
| | | ) |
| | | } |
| | |
| | | onDragModeChange: { setAppDragMode($0) }, |
| | | onBubbleHover: handleBubbleHover, |
| | | onEditNote: beginEditingBubbleNote, |
| | | itemID: "\(group.name)|\(app.path.path)", |
| | | hoveredAppItemID: $hoveredAppItemID, |
| | | onSelect: { openApp(app) } |
| | | ) |
| | | .frame(width: cellWidth) |
| | |
| | | var seenAppIDsByGroup: [String: Set<URL>] = [:] |
| | | |
| | | for app in apps { |
| | | if app.isAppleApp { |
| | | appendGroupedApp(app, to: macCategory, groups: &dict, seenAppIDsByGroup: &seenAppIDsByGroup) |
| | | } |
| | | |
| | | if app.tags.isEmpty { |
| | | let bucket = app.isAppleApp ? macCategory : defaultGroupName |
| | | appendGroupedApp(app, to: bucket, groups: &dict, seenAppIDsByGroup: &seenAppIDsByGroup) |
| | | if !app.isAppleApp { |
| | | appendGroupedApp(app, to: defaultGroupName, groups: &dict, seenAppIDsByGroup: &seenAppIDsByGroup) |
| | | } |
| | | } else { |
| | | for tag in uniqueOrdered(app.tags) { |
| | | let displayName = nameOverrides[tag] ?? tag |
| | | guard displayName != macCategory else { continue } |
| | | appendGroupedApp(app, to: displayName, groups: &dict, seenAppIDsByGroup: &seenAppIDsByGroup) |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | var current = store.appTags[path] ?? [] |
| | | if !copy, !sourceTag.isEmpty { |
| | | if !copy, !sourceTag.isEmpty, sourceTag != "Mac自带", sourceTag != tr("group.appleBuiltIn") { |
| | | current.removeAll { $0 == sourceTag } |
| | | } |
| | | if !current.contains(targetTag) { |
| | |
| | | <key>CFBundlePackageType</key> |
| | | <string>APPL</string> |
| | | <key>CFBundleShortVersionString</key> |
| | | <string>7.2.0</string> |
| | | <string>7.3.0</string> |
| | | <key>CFBundleVersion</key> |
| | | <string>738</string> |
| | | <string>739</string> |
| | | <key>LSMinimumSystemVersion</key> |
| | | <string>15.0</string> |
| | | <key>NSHighResolutionCapable</key> |
| | |
| | | "settings.systemSchemeAppliedMessage": "تم تطبيق %tagCount% تعيينات وسوم على %appCount% تطبيقات.", |
| | | "settings.systemSchemeApplyFailed": "ما فيه نتائج تصنيف ذكي قابلة للتطبيق.", |
| | | "scheme.local": "المخطط المحلي", |
| | | "scheme.systemSmartStart": "مخطط البداية الذكي للنظام" |
| | | "scheme.systemSmartStart": "مخطط البداية الذكي للنظام", |
| | | "settings.bubbleDisplayScope": "Bubble tips show for:", |
| | | "settings.bubbleAllApps": "All apps", |
| | | "settings.bubbleUncommonOnly": "Uncommon apps only" |
| | | } |
| | |
| | | "settings.systemSchemeAppliedMessage": "تم تطبيق %tagCount% تعيينات وسوم على %appCount% تطبيقات.", |
| | | "settings.systemSchemeApplyFailed": "لا توجد نتائج تصنيف ذكي يمكن تطبيقها.", |
| | | "scheme.local": "المخطط المحلي", |
| | | "scheme.systemSmartStart": "مخطط البداية الذكي للنظام" |
| | | "scheme.systemSmartStart": "مخطط البداية الذكي للنظام", |
| | | "settings.bubbleDisplayScope": "Bubble tips show for:", |
| | | "settings.bubbleAllApps": "All apps", |
| | | "settings.bubbleUncommonOnly": "Uncommon apps only" |
| | | } |
| | |
| | | "settings.systemSchemeAppliedMessage": "Použito %tagCount% přiřazení štítků pro %appCount% aplikací.", |
| | | "settings.systemSchemeApplyFailed": "Nejsou k dispozici žádné výsledky chytré klasifikace.", |
| | | "scheme.local": "Místní schéma", |
| | | "scheme.systemSmartStart": "Chytré počáteční schéma systému" |
| | | "scheme.systemSmartStart": "Chytré počáteční schéma systému", |
| | | "settings.bubbleDisplayScope": "Bubble tips show for:", |
| | | "settings.bubbleAllApps": "All apps", |
| | | "settings.bubbleUncommonOnly": "Uncommon apps only" |
| | | } |
| | |
| | | "settings.systemSchemeAppliedMessage": "%tagCount% tagtildelinger anvendt på %appCount% apps.", |
| | | "settings.systemSchemeApplyFailed": "Ingen smarte klassificeringsresultater kan anvendes.", |
| | | "scheme.local": "Lokalt skema", |
| | | "scheme.systemSmartStart": "Systemets smarte startskema" |
| | | "scheme.systemSmartStart": "Systemets smarte startskema", |
| | | "settings.bubbleDisplayScope": "Bubble tips show for:", |
| | | "settings.bubbleAllApps": "All apps", |
| | | "settings.bubbleUncommonOnly": "Uncommon apps only" |
| | | } |
| | |
| | | "settings.systemSchemeAppliedMessage": "%tagCount% Tag-Zuordnungen auf %appCount% Apps angewendet.", |
| | | "settings.systemSchemeApplyFailed": "Es sind keine intelligenten Klassifizierungsergebnisse verfügbar.", |
| | | "scheme.local": "Lokales Schema", |
| | | "scheme.systemSmartStart": "Intelligentes System-Startschema" |
| | | "scheme.systemSmartStart": "Intelligentes System-Startschema", |
| | | "settings.bubbleDisplayScope": "Bubble tips show for:", |
| | | "settings.bubbleAllApps": "All apps", |
| | | "settings.bubbleUncommonOnly": "Uncommon apps only" |
| | | } |
| | |
| | | "settings.systemSchemeAppliedMessage": "Applied %tagCount% tag assignments across %appCount% apps.", |
| | | "settings.systemSchemeApplyFailed": "No smart classification results were available to apply.", |
| | | "scheme.local": "Local scheme", |
| | | "scheme.systemSmartStart": "System smart initial scheme" |
| | | "scheme.systemSmartStart": "System smart initial scheme", |
| | | "settings.bubbleDisplayScope": "Bubble tips show for:", |
| | | "settings.bubbleAllApps": "All apps", |
| | | "settings.bubbleUncommonOnly": "Uncommon apps only" |
| | | } |
| | |
| | | "settings.systemSchemeAppliedMessage": "Se aplicaron %tagCount% asignaciones de etiquetas a %appCount% apps.", |
| | | "settings.systemSchemeApplyFailed": "No hay resultados de clasificación inteligente para aplicar.", |
| | | "scheme.local": "Esquema local", |
| | | "scheme.systemSmartStart": "Esquema inicial inteligente del sistema" |
| | | "scheme.systemSmartStart": "Esquema inicial inteligente del sistema", |
| | | "settings.bubbleDisplayScope": "Bubble tips show for:", |
| | | "settings.bubbleAllApps": "All apps", |
| | | "settings.bubbleUncommonOnly": "Uncommon apps only" |
| | | } |
| | |
| | | "settings.systemSchemeAppliedMessage": "%tagCount% attributions de tags appliquées à %appCount% apps.", |
| | | "settings.systemSchemeApplyFailed": "Aucun résultat de classification intelligente à appliquer.", |
| | | "scheme.local": "Schéma local", |
| | | "scheme.systemSmartStart": "Schéma initial intelligent du système" |
| | | "scheme.systemSmartStart": "Schéma initial intelligent du système", |
| | | "settings.bubbleDisplayScope": "Bubble tips show for:", |
| | | "settings.bubbleAllApps": "All apps", |
| | | "settings.bubbleUncommonOnly": "Uncommon apps only" |
| | | } |
| | |
| | | "settings.systemSchemeAppliedMessage": "Menerapkan %tagCount% penetapan tag pada %appCount% app.", |
| | | "settings.systemSchemeApplyFailed": "Tidak ada hasil klasifikasi pintar yang dapat diterapkan.", |
| | | "scheme.local": "Skema lokal", |
| | | "scheme.systemSmartStart": "Skema awal pintar sistem" |
| | | "scheme.systemSmartStart": "Skema awal pintar sistem", |
| | | "settings.bubbleDisplayScope": "Bubble tips show for:", |
| | | "settings.bubbleAllApps": "All apps", |
| | | "settings.bubbleUncommonOnly": "Uncommon apps only" |
| | | } |
| | |
| | | "settings.systemSchemeAppliedMessage": "Applicate %tagCount% assegnazioni tag a %appCount% app.", |
| | | "settings.systemSchemeApplyFailed": "Nessun risultato di classificazione intelligente disponibile.", |
| | | "scheme.local": "Schema locale", |
| | | "scheme.systemSmartStart": "Schema iniziale intelligente di sistema" |
| | | "scheme.systemSmartStart": "Schema iniziale intelligente di sistema", |
| | | "settings.bubbleDisplayScope": "Bubble tips show for:", |
| | | "settings.bubbleAllApps": "All apps", |
| | | "settings.bubbleUncommonOnly": "Uncommon apps only" |
| | | } |
| | |
| | | "settings.systemSchemeAppliedMessage": "%appCount% 個のアプリに %tagCount% 件のタグ割り当てを適用しました。", |
| | | "settings.systemSchemeApplyFailed": "適用できるスマート分類結果がありませんでした。", |
| | | "scheme.local": "ローカル分類スキーム", |
| | | "scheme.systemSmartStart": "システム初期スマート分類" |
| | | "scheme.systemSmartStart": "システム初期スマート分類", |
| | | "settings.bubbleDisplayScope": "吹き出しの表示対象:", |
| | | "settings.bubbleAllApps": "すべてのアプリ", |
| | | "settings.bubbleUncommonOnly": "あまり使わないアプリのみ" |
| | | } |
| | |
| | | "settings.systemSchemeAppliedMessage": "%appCount%개의 앱에 %tagCount%개의 태그 할당을 적용했습니다.", |
| | | "settings.systemSchemeApplyFailed": "적용할 수 있는 스마트 분류 결과가 없습니다.", |
| | | "scheme.local": "로컬 분류 방식", |
| | | "scheme.systemSmartStart": "시스템 스마트 초기 분류" |
| | | "scheme.systemSmartStart": "시스템 스마트 초기 분류", |
| | | "settings.bubbleDisplayScope": "말풍선 표시 대상:", |
| | | "settings.bubbleAllApps": "모든 앱", |
| | | "settings.bubbleUncommonOnly": "자주 쓰지 않는 앱만" |
| | | } |
| | |
| | | "settings.systemSchemeAppliedMessage": "%tagCount% tugasan tag digunakan pada %appCount% app.", |
| | | "settings.systemSchemeApplyFailed": "Tiada hasil pengelasan pintar untuk digunakan.", |
| | | "scheme.local": "Skema setempat", |
| | | "scheme.systemSmartStart": "Skema awal pintar sistem" |
| | | "scheme.systemSmartStart": "Skema awal pintar sistem", |
| | | "settings.bubbleDisplayScope": "Bubble tips show for:", |
| | | "settings.bubbleAllApps": "All apps", |
| | | "settings.bubbleUncommonOnly": "Uncommon apps only" |
| | | } |
| | |
| | | "settings.systemSchemeAppliedMessage": "Brukte %tagCount% taggtildelinger på %appCount% apper.", |
| | | "settings.systemSchemeApplyFailed": "Ingen smarte klassifiseringsresultater kan brukes.", |
| | | "scheme.local": "Lokalt skjema", |
| | | "scheme.systemSmartStart": "Systemets smarte startskjema" |
| | | "scheme.systemSmartStart": "Systemets smarte startskjema", |
| | | "settings.bubbleDisplayScope": "Bubble tips show for:", |
| | | "settings.bubbleAllApps": "All apps", |
| | | "settings.bubbleUncommonOnly": "Uncommon apps only" |
| | | } |
| | |
| | | "settings.systemSchemeAppliedMessage": "%tagCount% tagtoewijzingen toegepast op %appCount% apps.", |
| | | "settings.systemSchemeApplyFailed": "Geen slimme classificatieresultaten beschikbaar om toe te passen.", |
| | | "scheme.local": "Lokaal schema", |
| | | "scheme.systemSmartStart": "Slim beginschema van systeem" |
| | | "scheme.systemSmartStart": "Slim beginschema van systeem", |
| | | "settings.bubbleDisplayScope": "Bubble tips show for:", |
| | | "settings.bubbleAllApps": "All apps", |
| | | "settings.bubbleUncommonOnly": "Uncommon apps only" |
| | | } |
| | |
| | | "settings.systemSchemeAppliedMessage": "Brukte %tagCount% taggtildelinger på %appCount% apper.", |
| | | "settings.systemSchemeApplyFailed": "Ingen smarte klassifiseringsresultater kan brukes.", |
| | | "scheme.local": "Lokalt skjema", |
| | | "scheme.systemSmartStart": "Systemets smarte startskjema" |
| | | "scheme.systemSmartStart": "Systemets smarte startskjema", |
| | | "settings.bubbleDisplayScope": "Bubble tips show for:", |
| | | "settings.bubbleAllApps": "All apps", |
| | | "settings.bubbleUncommonOnly": "Uncommon apps only" |
| | | } |
| | |
| | | "settings.systemSchemeAppliedMessage": "Brukte %tagCount% taggtildelinger på %appCount% apper.", |
| | | "settings.systemSchemeApplyFailed": "Ingen smarte klassifiseringsresultater kan brukes.", |
| | | "scheme.local": "Lokalt skjema", |
| | | "scheme.systemSmartStart": "Systemets smarte startskjema" |
| | | "scheme.systemSmartStart": "Systemets smarte startskjema", |
| | | "settings.bubbleDisplayScope": "Bubble tips show for:", |
| | | "settings.bubbleAllApps": "All apps", |
| | | "settings.bubbleUncommonOnly": "Uncommon apps only" |
| | | } |
| | |
| | | "settings.systemSchemeAppliedMessage": "Zastosowano %tagCount% przypisań tagów dla %appCount% aplikacji.", |
| | | "settings.systemSchemeApplyFailed": "Brak wyników inteligentnej klasyfikacji do zastosowania.", |
| | | "scheme.local": "Schemat lokalny", |
| | | "scheme.systemSmartStart": "Inteligentny schemat początkowy systemu" |
| | | "scheme.systemSmartStart": "Inteligentny schemat początkowy systemu", |
| | | "settings.bubbleDisplayScope": "Bubble tips show for:", |
| | | "settings.bubbleAllApps": "All apps", |
| | | "settings.bubbleUncommonOnly": "Uncommon apps only" |
| | | } |
| | |
| | | "settings.systemSchemeAppliedMessage": "Foram aplicadas %tagCount% atribuições de tags em %appCount% apps.", |
| | | "settings.systemSchemeApplyFailed": "Não há resultados de classificação inteligente para aplicar.", |
| | | "scheme.local": "Esquema local", |
| | | "scheme.systemSmartStart": "Esquema inicial inteligente do sistema" |
| | | "scheme.systemSmartStart": "Esquema inicial inteligente do sistema", |
| | | "settings.bubbleDisplayScope": "Bubble tips show for:", |
| | | "settings.bubbleAllApps": "All apps", |
| | | "settings.bubbleUncommonOnly": "Uncommon apps only" |
| | | } |
| | |
| | | "settings.systemSchemeAppliedMessage": "Au fost aplicate %tagCount% atribuiri de etichete pentru %appCount% aplicații.", |
| | | "settings.systemSchemeApplyFailed": "Nu există rezultate de clasificare inteligentă de aplicat.", |
| | | "scheme.local": "Schema locală", |
| | | "scheme.systemSmartStart": "Schema inteligentă inițială a sistemului" |
| | | "scheme.systemSmartStart": "Schema inteligentă inițială a sistemului", |
| | | "settings.bubbleDisplayScope": "Bubble tips show for:", |
| | | "settings.bubbleAllApps": "All apps", |
| | | "settings.bubbleUncommonOnly": "Uncommon apps only" |
| | | } |
| | |
| | | "settings.systemSchemeAppliedMessage": "Применено %tagCount% назначений тегов для %appCount% приложений.", |
| | | "settings.systemSchemeApplyFailed": "Нет результатов интеллектуальной классификации для применения.", |
| | | "scheme.local": "Локальная схема", |
| | | "scheme.systemSmartStart": "Интеллектуальная начальная схема системы" |
| | | "scheme.systemSmartStart": "Интеллектуальная начальная схема системы", |
| | | "settings.bubbleDisplayScope": "Bubble tips show for:", |
| | | "settings.bubbleAllApps": "All apps", |
| | | "settings.bubbleUncommonOnly": "Uncommon apps only" |
| | | } |
| | |
| | | "settings.systemSchemeAppliedMessage": "Примењено је %tagCount% додела ознака за %appCount% апликација.", |
| | | "settings.systemSchemeApplyFailed": "Нема резултата паметне класификације за примену.", |
| | | "scheme.local": "Локална шема", |
| | | "scheme.systemSmartStart": "Паметна почетна шема система" |
| | | "scheme.systemSmartStart": "Паметна почетна шема система", |
| | | "settings.bubbleDisplayScope": "Bubble tips show for:", |
| | | "settings.bubbleAllApps": "All apps", |
| | | "settings.bubbleUncommonOnly": "Uncommon apps only" |
| | | } |
| | |
| | | "settings.systemSchemeAppliedMessage": "%tagCount% taggtilldelningar tillämpades på %appCount% appar.", |
| | | "settings.systemSchemeApplyFailed": "Inga smarta klassificeringsresultat kunde tillämpas.", |
| | | "scheme.local": "Lokalt schema", |
| | | "scheme.systemSmartStart": "Systemets smarta startschema" |
| | | "scheme.systemSmartStart": "Systemets smarta startschema", |
| | | "settings.bubbleDisplayScope": "Bubble tips show for:", |
| | | "settings.bubbleAllApps": "All apps", |
| | | "settings.bubbleUncommonOnly": "Uncommon apps only" |
| | | } |
| | |
| | | "settings.systemSchemeAppliedMessage": "นำการกำหนดแท็ก %tagCount% รายการไปใช้กับแอป %appCount% รายการแล้ว", |
| | | "settings.systemSchemeApplyFailed": "ไม่มีผลการจัดหมวดหมู่อัจฉริยะให้ใช้", |
| | | "scheme.local": "ชุดภายในเครื่อง", |
| | | "scheme.systemSmartStart": "ชุดเริ่มต้นอัจฉริยะของระบบ" |
| | | "scheme.systemSmartStart": "ชุดเริ่มต้นอัจฉริยะของระบบ", |
| | | "settings.bubbleDisplayScope": "Bubble tips show for:", |
| | | "settings.bubbleAllApps": "All apps", |
| | | "settings.bubbleUncommonOnly": "Uncommon apps only" |
| | | } |
| | |
| | | "settings.systemSchemeAppliedMessage": "%appCount% uygulamada %tagCount% etiket ataması uygulandı.", |
| | | "settings.systemSchemeApplyFailed": "Uygulanacak akıllı sınıflandırma sonucu yok.", |
| | | "scheme.local": "Yerel şema", |
| | | "scheme.systemSmartStart": "Sistem akıllı başlangıç şeması" |
| | | "scheme.systemSmartStart": "Sistem akıllı başlangıç şeması", |
| | | "settings.bubbleDisplayScope": "Bubble tips show for:", |
| | | "settings.bubbleAllApps": "All apps", |
| | | "settings.bubbleUncommonOnly": "Uncommon apps only" |
| | | } |
| | |
| | | "settings.systemSchemeAppliedMessage": "Застосовано %tagCount% призначень тегів для %appCount% програм.", |
| | | "settings.systemSchemeApplyFailed": "Немає результатів розумної класифікації для застосування.", |
| | | "scheme.local": "Локальна схема", |
| | | "scheme.systemSmartStart": "Розумна початкова схема системи" |
| | | "scheme.systemSmartStart": "Розумна початкова схема системи", |
| | | "settings.bubbleDisplayScope": "Bubble tips show for:", |
| | | "settings.bubbleAllApps": "All apps", |
| | | "settings.bubbleUncommonOnly": "Uncommon apps only" |
| | | } |
| | |
| | | "settings.systemSchemeAppliedMessage": "Đã áp dụng %tagCount% gán thẻ cho %appCount% ứng dụng.", |
| | | "settings.systemSchemeApplyFailed": "Không có kết quả phân loại thông minh để áp dụng.", |
| | | "scheme.local": "Sơ đồ cục bộ", |
| | | "scheme.systemSmartStart": "Sơ đồ khởi tạo thông minh của hệ thống" |
| | | "scheme.systemSmartStart": "Sơ đồ khởi tạo thông minh của hệ thống", |
| | | "settings.bubbleDisplayScope": "Bubble tips show for:", |
| | | "settings.bubbleAllApps": "All apps", |
| | | "settings.bubbleUncommonOnly": "Uncommon apps only" |
| | | } |
| | |
| | | "settings.systemSchemeAppliedMessage": "已为 %appCount% 个应用应用 %tagCount% 个标签分配。", |
| | | "settings.systemSchemeApplyFailed": "没有找到可应用的智能分类结果。", |
| | | "scheme.local": "本地分类方案", |
| | | "scheme.systemSmartStart": "系统智能化初始分类" |
| | | "scheme.systemSmartStart": "系统智能化初始分类", |
| | | "settings.bubbleDisplayScope": "气泡提示框显示位置:", |
| | | "settings.bubbleAllApps": "全部应用", |
| | | "settings.bubbleUncommonOnly": "仅不常用应用" |
| | | } |
| | |
| | | "settings.systemSchemeAppliedMessage": "已為 %appCount% 個 App 套用 %tagCount% 個標籤分配。", |
| | | "settings.systemSchemeApplyFailed": "沒有找到可套用的智慧分類結果。", |
| | | "scheme.local": "本機分類方案", |
| | | "scheme.systemSmartStart": "系統智慧化初始分類" |
| | | "scheme.systemSmartStart": "系統智慧化初始分類", |
| | | "settings.bubbleDisplayScope": "氣泡提示框顯示位置:", |
| | | "settings.bubbleAllApps": "全部 App", |
| | | "settings.bubbleUncommonOnly": "僅不常用 App" |
| | | } |
| | |
| | | return FileManager.default.fileExists(atPath: path) |
| | | } |
| | | |
| | | private func bubbleScopeOption( |
| | | _ title: String, |
| | | isSelected: Bool, |
| | | action: @escaping () -> Void |
| | | ) -> some View { |
| | | Button(action: action) { |
| | | HStack(spacing: 6) { |
| | | Image(systemName: isSelected ? "largecircle.fill.circle" : "circle") |
| | | .font(.system(size: 13, weight: .medium)) |
| | | .frame(width: 16, height: 16) |
| | | Text(title) |
| | | .font(.system(size: 13, weight: .medium)) |
| | | } |
| | | .foregroundStyle(isSelected ? Color.accentColor : Color.primary) |
| | | .contentShape(Rectangle()) |
| | | } |
| | | .buttonStyle(.plain) |
| | | } |
| | | |
| | | private func syncSelectedLanguage() { |
| | | let code = L10n.currentCode |
| | | guard selectedLanguage != code else { return } |
| | |
| | | |
| | | Spacer(minLength: 22) |
| | | |
| | | VStack(alignment: .leading, spacing: 5) { |
| | | Toggle(tr("settings.uncommonBubble"), isOn: $showUncommonAppBubbles) |
| | | HStack(alignment: .center, spacing: 14) { |
| | | Text(tr("settings.bubbleDisplayScope")) |
| | | .font(.system(size: 13, weight: .medium)) |
| | | Text(tr("settings.uncommonBubbleDesc")) |
| | | .font(.caption) |
| | | .foregroundStyle(.secondary) |
| | | .fixedSize(horizontal: false, vertical: true) |
| | | .frame(width: 190, alignment: .trailing) |
| | | |
| | | HStack(spacing: 20) { |
| | | bubbleScopeOption( |
| | | tr("settings.bubbleAllApps"), |
| | | isSelected: !showUncommonAppBubbles |
| | | ) { |
| | | showUncommonAppBubbles = false |
| | | } |
| | | .frame(width: 420, alignment: .leading) |
| | | bubbleScopeOption( |
| | | tr("settings.bubbleUncommonOnly"), |
| | | isSelected: showUncommonAppBubbles |
| | | ) { |
| | | showUncommonAppBubbles = true |
| | | } |
| | | } |
| | | .frame(width: 300, alignment: .leading) |
| | | } |
| | | .frame(width: 520, alignment: .center) |
| | | |
| | | Spacer(minLength: 18) |
| | | } |
| | |
| | | var onDragModeChange: ((Bool) -> Void)? = nil |
| | | var onBubbleHover: ((AppInfo, CGRect, Bool) -> Void)? = nil |
| | | var onEditNote: ((AppInfo, CGRect) -> Void)? = nil |
| | | @Binding var hoveredAppItemID: String? |
| | | var onDropApp: ((String, String, Bool) -> Void)? = nil |
| | | |
| | | /// Adaptive columns — auto-fit based on icon size and available width. |
| | |
| | | onDragModeChange: onDragModeChange, |
| | | onBubbleHover: onBubbleHover, |
| | | onEditNote: onEditNote, |
| | | itemID: "\(group.name)|\(app.path.path)", |
| | | hoveredAppItemID: $hoveredAppItemID, |
| | | onSelect: { onSelectApp(app) } |
| | | ) |
| | | } |
| | |
| | | # Apptag Changelog |
| | | |
| | | ## [7.3.0] — 2026-05-18 |
| | | |
| | | - 修复 Apple 系统自带 App 被拖入其他标签后从「Mac自带」分组消失的问题,「Mac自带」现在作为客观属性始终保留 |
| | | - 气泡提示设置改为「全部应用 / 仅不常用应用」二选一,并补齐多语言文案 |
| | | - 统一 App 图标 hover 焦点状态,降低快速滑过、视图复用或同一 App 出现在多个分组时出现小名字残影的概率 |
| | | - 当气泡提示范围选择「全部应用」时,hover 不再额外显示 App 图标下方的小名字,避免和大气泡重复 |
| | | - 版本号更新为 `7.3.0`,Build 更新为 `739` |
| | | |
| | | ## [7.2.0] — 2026-05-18 |
| | | |
| | | - 统筹优化 App hover 交互:容器、图标和气泡不再同时做大幅动画,避免快速滑过时出现慢动作和卡顿 |