[Phase L2-7] 퀵 액션 바 — 최근 실행 항목 칩 표시
Models/QuickActionChip.cs (신규 12줄): - Title, Symbol, Path, Background 레코드 Services/UsageRankingService.cs: - GetTopItems(int n) 메서드 추가: 실행 횟수 상위 N개 (경로, 횟수) 반환 ViewModels/LauncherViewModel.cs: - QuickActionItems (ObservableCollection<QuickActionChip>) 프로퍼티 추가 - ShowQuickActions: 입력 비었을 때 칩 표시 조건 - LoadQuickActions(): 상위 8개 경로 → 파일 존재 확인 → 타입별 아이콘/색상 칩 생성 - OnShown()에서 LoadQuickActions() 호출 - InputText 변경 시 ShowQuickActions 알림 Views/LauncherWindow.xaml: - 입력 Grid를 2행 구조로 변환 (RowDefinitions 추가) - Row 1: ItemsControl + WrapPanel + DataTemplate 칩 UI - CornerRadius=10 Border, 아이콘+제목 StackPanel - 호버 시 AccentColor 테두리, 최대 너비 100px 말줄임 Views/LauncherWindow.Shell.cs: - QuickActionChip_Click 핸들러: 창 숨김 → 경로 실행 → 사용 통계 기록 빌드: 경고 0, 오류 0 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -48,6 +48,15 @@ public partial class LauncherViewModel : INotifyPropertyChanged
|
||||
/// </summary>
|
||||
public ICollectionView GroupedResults { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 퀵 액션 바 — 가장 많이 실행한 항목을 입력창 아래 칩으로 표시합니다.
|
||||
/// 입력창이 비어 있을 때만 표시됩니다.
|
||||
/// </summary>
|
||||
public ObservableCollection<QuickActionChip> QuickActionItems { get; } = new();
|
||||
|
||||
/// <summary>퀵 액션 칩 표시 조건: 입력이 없고 칩이 하나 이상 있을 때</summary>
|
||||
public bool ShowQuickActions => string.IsNullOrEmpty(_inputText) && QuickActionItems.Count > 0;
|
||||
|
||||
// ─── 기본 프로퍼티 ────────────────────────────────────────────────────────
|
||||
|
||||
public string InputText
|
||||
@@ -66,6 +75,8 @@ public partial class LauncherViewModel : INotifyPropertyChanged
|
||||
OnPropertyChanged(nameof(ShowMergeHint));
|
||||
OnPropertyChanged(nameof(MergeHintText));
|
||||
|
||||
OnPropertyChanged(nameof(ShowQuickActions));
|
||||
|
||||
// 연속 입력 시 이전 검색 즉시 취소 + 50ms 디바운스 후 실제 검색 시작
|
||||
_searchCts?.Cancel();
|
||||
_debounceTimer?.Dispose();
|
||||
@@ -266,6 +277,47 @@ public partial class LauncherViewModel : INotifyPropertyChanged
|
||||
Results.Clear();
|
||||
_lastSearchQuery = "";
|
||||
ClearMerge();
|
||||
LoadQuickActions();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// UsageRankingService 상위 항목에서 퀵 액션 칩을 생성합니다.
|
||||
/// 실제로 존재하는 파일/폴더만 표시하며 최대 8개로 제한합니다.
|
||||
/// </summary>
|
||||
public void LoadQuickActions()
|
||||
{
|
||||
QuickActionItems.Clear();
|
||||
var topItems = UsageRankingService.GetTopItems(16); // 여유분 확보 (일부 경로가 없을 수 있음)
|
||||
var added = 0;
|
||||
foreach (var (path, _) in topItems)
|
||||
{
|
||||
if (added >= 8) break;
|
||||
var expanded = Environment.ExpandEnvironmentVariables(path);
|
||||
var isFolder = Directory.Exists(expanded);
|
||||
var isFile = !isFolder && File.Exists(expanded);
|
||||
if (!isFolder && !isFile) continue; // 삭제된 항목 건너뜀
|
||||
|
||||
var ext = Path.GetExtension(expanded).ToLowerInvariant();
|
||||
var title = Path.GetFileNameWithoutExtension(expanded);
|
||||
if (string.IsNullOrEmpty(title)) title = Path.GetFileName(expanded);
|
||||
|
||||
var symbol = isFolder ? Symbols.Folder
|
||||
: ext == ".exe" ? Symbols.App
|
||||
: ext is ".lnk"
|
||||
or ".url" ? Symbols.App
|
||||
: Symbols.File;
|
||||
|
||||
var color = isFolder ? Color.FromRgb(0x10, 0x7C, 0x10)
|
||||
: ext == ".exe" ? Color.FromRgb(0x4B, 0x5E, 0xFC)
|
||||
: ext is ".lnk"
|
||||
or ".url" ? Color.FromRgb(0x4B, 0x5E, 0xFC)
|
||||
: Color.FromRgb(0x5B, 0x4E, 0x7E);
|
||||
|
||||
var bg = new SolidColorBrush(Color.FromArgb(0x26, color.R, color.G, color.B));
|
||||
QuickActionItems.Add(new QuickActionChip(title, symbol, path, bg));
|
||||
added++;
|
||||
}
|
||||
OnPropertyChanged(nameof(ShowQuickActions));
|
||||
}
|
||||
|
||||
// ─── 검색 ────────────────────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user