Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4cc29292f1 |
+56
-32
@@ -15,7 +15,6 @@ public partial class PopupWindow : Window
|
|||||||
private static readonly UpdateManager Updater = App.Updater;
|
private static readonly UpdateManager Updater = App.Updater;
|
||||||
private readonly DispatcherTimer _clockTimer;
|
private readonly DispatcherTimer _clockTimer;
|
||||||
|
|
||||||
|
|
||||||
[DllImport("dwmapi.dll")]
|
[DllImport("dwmapi.dll")]
|
||||||
private static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int value, int size);
|
private static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int value, int size);
|
||||||
|
|
||||||
@@ -71,10 +70,8 @@ public partial class PopupWindow : Window
|
|||||||
var secondary = (SolidColorBrush)Application.Current.Resources["SecondaryBrush"];
|
var secondary = (SolidColorBrush)Application.Current.Resources["SecondaryBrush"];
|
||||||
var border = (SolidColorBrush)Application.Current.Resources["BorderBrush"];
|
var border = (SolidColorBrush)Application.Current.Resources["BorderBrush"];
|
||||||
|
|
||||||
// Gauge
|
|
||||||
var gauge = new GaugeControl { Width = 76, Height = 76, Percent = limit.UsedPercent, Accent = accent };
|
var gauge = new GaugeControl { Width = 76, Height = 76, Percent = limit.UsedPercent, Accent = accent };
|
||||||
|
|
||||||
// Live badge
|
|
||||||
var liveBadge = new Border
|
var liveBadge = new Border
|
||||||
{
|
{
|
||||||
Background = new SolidColorBrush(Color.FromArgb(30, 0, 160, 0)),
|
Background = new SolidColorBrush(Color.FromArgb(30, 0, 160, 0)),
|
||||||
@@ -86,7 +83,6 @@ public partial class PopupWindow : Window
|
|||||||
Foreground = new SolidColorBrush(Color.FromRgb(0, 120, 0)) }
|
Foreground = new SolidColorBrush(Color.FromRgb(0, 120, 0)) }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Usage badge
|
|
||||||
var usageBadge = new Border
|
var usageBadge = new Border
|
||||||
{
|
{
|
||||||
Background = new SolidColorBrush(Color.FromArgb(18, 0, 0, 0)),
|
Background = new SolidColorBrush(Color.FromArgb(18, 0, 0, 0)),
|
||||||
@@ -124,7 +120,7 @@ public partial class PopupWindow : Window
|
|||||||
BorderThickness = new Thickness(0),
|
BorderThickness = new Thickness(0),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Left side of time row: "⏱ Xh Ym Resets D MMM YYYY at HH:mm"
|
// Left: time remaining + reset date inline
|
||||||
var timeLeft = new StackPanel { Orientation = Orientation.Horizontal, VerticalAlignment = VerticalAlignment.Center };
|
var timeLeft = new StackPanel { Orientation = Orientation.Horizontal, VerticalAlignment = VerticalAlignment.Center };
|
||||||
timeLeft.Children.Add(new TextBlock { Text = "⏱ ", FontSize = 10, Foreground = secondary, VerticalAlignment = VerticalAlignment.Center });
|
timeLeft.Children.Add(new TextBlock { Text = "⏱ ", FontSize = 10, Foreground = secondary, VerticalAlignment = VerticalAlignment.Center });
|
||||||
timeLeft.Children.Add(new TextBlock { Text = limit.TimeRemaining, FontSize = 12,
|
timeLeft.Children.Add(new TextBlock { Text = limit.TimeRemaining, FontSize = 12,
|
||||||
@@ -135,7 +131,7 @@ public partial class PopupWindow : Window
|
|||||||
FontSize = 10, Foreground = secondary, VerticalAlignment = VerticalAlignment.Center
|
FontSize = 10, Foreground = secondary, VerticalAlignment = VerticalAlignment.Center
|
||||||
});
|
});
|
||||||
|
|
||||||
// Right side: "after reset" when 0%, "today HH:MM" when refreshed today
|
// Right: "after reset" when 0%, "today HH:MM" when refreshed today
|
||||||
string? refreshLabel = limit.UsedPercent == 0
|
string? refreshLabel = limit.UsedPercent == 0
|
||||||
? "after reset"
|
? "after reset"
|
||||||
: VM.LastUpdated?.Date == DateTime.Today
|
: VM.LastUpdated?.Date == DateTime.Today
|
||||||
@@ -159,7 +155,7 @@ public partial class PopupWindow : Window
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
timeRight = new TextBlock(); // empty placeholder
|
timeRight = new TextBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
var timeRow = new Grid();
|
var timeRow = new Grid();
|
||||||
@@ -216,29 +212,40 @@ public partial class PopupWindow : Window
|
|||||||
|
|
||||||
private static UIElement BuildDiarySection(AgentLimit limit)
|
private static UIElement BuildDiarySection(AgentLimit limit)
|
||||||
{
|
{
|
||||||
var text = (SolidColorBrush)Application.Current.Resources["TextBrush"];
|
|
||||||
var secondary = (SolidColorBrush)Application.Current.Resources["SecondaryBrush"];
|
var secondary = (SolidColorBrush)Application.Current.Resources["SecondaryBrush"];
|
||||||
var border = (SolidColorBrush)Application.Current.Resources["BorderBrush"];
|
var border = (SolidColorBrush)Application.Current.Resources["BorderBrush"];
|
||||||
|
|
||||||
var samples = limit.BurnHistory.Count;
|
// Stats row inside the card (mirrors macOS layout without the Claude icon/header)
|
||||||
var avgBurn = limit.BurnRate;
|
var statsRow = new Grid { Margin = new Thickness(12, 10, 12, 6) };
|
||||||
|
statsRow.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
|
||||||
var subtitle = new TextBlock
|
statsRow.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
|
||||||
|
var samplesText = new TextBlock
|
||||||
{
|
{
|
||||||
Text = $"{samples} samples · {avgBurn:F1}%/h avg burn rate",
|
Text = $"{limit.BurnHistory.Count} samples",
|
||||||
FontSize = 11,
|
FontSize = 11, Foreground = secondary, VerticalAlignment = VerticalAlignment.Center
|
||||||
Foreground = secondary,
|
|
||||||
Margin = new Thickness(16, 0, 16, 6),
|
|
||||||
};
|
};
|
||||||
|
var burnText = new TextBlock
|
||||||
|
{
|
||||||
|
Text = $"Avg burn rate: {limit.BurnRate:F1}%/h",
|
||||||
|
FontSize = 11, Foreground = secondary, VerticalAlignment = VerticalAlignment.Center
|
||||||
|
};
|
||||||
|
Grid.SetColumn(samplesText, 0);
|
||||||
|
Grid.SetColumn(burnText, 1);
|
||||||
|
statsRow.Children.Add(samplesText);
|
||||||
|
statsRow.Children.Add(burnText);
|
||||||
|
|
||||||
var sparkline = new SparklineControl
|
var sparkline = new SparklineControl
|
||||||
{
|
{
|
||||||
Height = 32,
|
Height = 40,
|
||||||
Margin = new Thickness(8, 8, 8, 8),
|
Margin = new Thickness(8, 0, 8, 8),
|
||||||
LineColor = Color.FromRgb(0xF9, 0x73, 0x16),
|
LineColor = Color.FromRgb(0xF9, 0x73, 0x16),
|
||||||
Data = limit.BurnHistory,
|
Data = limit.BurnHistory,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var cardContent = new StackPanel();
|
||||||
|
cardContent.Children.Add(statsRow);
|
||||||
|
cardContent.Children.Add(sparkline);
|
||||||
|
|
||||||
var card = new Border
|
var card = new Border
|
||||||
{
|
{
|
||||||
Background = (SolidColorBrush)Application.Current.Resources["CardBrush"],
|
Background = (SolidColorBrush)Application.Current.Resources["CardBrush"],
|
||||||
@@ -246,7 +253,7 @@ public partial class PopupWindow : Window
|
|||||||
BorderBrush = border,
|
BorderBrush = border,
|
||||||
BorderThickness = new Thickness(1),
|
BorderThickness = new Thickness(1),
|
||||||
Margin = new Thickness(12, 0, 12, 0),
|
Margin = new Thickness(12, 0, 12, 0),
|
||||||
Child = sparkline,
|
Child = cardContent,
|
||||||
};
|
};
|
||||||
|
|
||||||
var sectionLabel = new TextBlock
|
var sectionLabel = new TextBlock
|
||||||
@@ -258,7 +265,6 @@ public partial class PopupWindow : Window
|
|||||||
|
|
||||||
var section = new StackPanel();
|
var section = new StackPanel();
|
||||||
section.Children.Add(sectionLabel);
|
section.Children.Add(sectionLabel);
|
||||||
section.Children.Add(subtitle);
|
|
||||||
section.Children.Add(card);
|
section.Children.Add(card);
|
||||||
return section;
|
return section;
|
||||||
}
|
}
|
||||||
@@ -409,18 +415,35 @@ public partial class PopupWindow : Window
|
|||||||
|
|
||||||
// ── Settings ─────────────────────────────────────────────────────
|
// ── Settings ─────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
private static readonly (string Label, int Seconds)[] RefreshIntervals =
|
||||||
|
[
|
||||||
|
("1 min", 60),
|
||||||
|
("2 min", 120),
|
||||||
|
("3 min", 180),
|
||||||
|
("4 min", 240),
|
||||||
|
("5 min", 300),
|
||||||
|
("10 min", 600),
|
||||||
|
];
|
||||||
|
|
||||||
private void InitSettings()
|
private void InitSettings()
|
||||||
{
|
{
|
||||||
VersionLabel.Text = $"v{Updater.CurrentVersion}";
|
VersionLabel.Text = $"v{Updater.CurrentVersion}";
|
||||||
BetaToggle.IsChecked = Updater.BetaChannel;
|
BetaToggle.IsChecked = Updater.BetaChannel;
|
||||||
UpdateAboutSection();
|
UpdateAboutSection();
|
||||||
|
|
||||||
var intervals = new[] { ("1 min", 60), ("2 min", 120), ("3 min", 180),
|
// Populate ComboBox with ComboBoxItem — DisplayMemberPath doesn't bind reliably
|
||||||
("4 min", 240), ("5 min", 300), ("10 min", 600) };
|
// on ValueTuple at runtime so we build items explicitly.
|
||||||
RefreshPicker.ItemsSource = intervals;
|
RefreshPicker.SelectionChanged -= RefreshPicker_Changed;
|
||||||
RefreshPicker.DisplayMemberPath = "Item1";
|
RefreshPicker.Items.Clear();
|
||||||
var idx = Array.FindIndex(intervals, x => x.Item2 == VM.RefreshInterval);
|
int selectIdx = 1; // default: 2 min
|
||||||
RefreshPicker.SelectedIndex = idx < 0 ? 1 : idx;
|
for (int i = 0; i < RefreshIntervals.Length; i++)
|
||||||
|
{
|
||||||
|
var (label, seconds) = RefreshIntervals[i];
|
||||||
|
RefreshPicker.Items.Add(new ComboBoxItem { Content = label, Tag = seconds });
|
||||||
|
if (seconds == VM.RefreshInterval) selectIdx = i;
|
||||||
|
}
|
||||||
|
RefreshPicker.SelectedIndex = selectIdx;
|
||||||
|
RefreshPicker.SelectionChanged += RefreshPicker_Changed;
|
||||||
|
|
||||||
AuthPanel.Children.Clear();
|
AuthPanel.Children.Clear();
|
||||||
var dot = new System.Windows.Shapes.Ellipse
|
var dot = new System.Windows.Shapes.Ellipse
|
||||||
@@ -429,15 +452,16 @@ public partial class PopupWindow : Window
|
|||||||
Fill = VM.IsSignedIn ? Brushes.LimeGreen : Brushes.Orange,
|
Fill = VM.IsSignedIn ? Brushes.LimeGreen : Brushes.Orange,
|
||||||
VerticalAlignment = VerticalAlignment.Center,
|
VerticalAlignment = VerticalAlignment.Center,
|
||||||
};
|
};
|
||||||
var label = new TextBlock
|
var label2 = new TextBlock
|
||||||
{
|
{
|
||||||
Text = VM.IsSignedIn ? $"Signed in — {VM.UserEmail}" : "Not signed in",
|
Text = VM.IsSignedIn ? $"Signed in — {VM.UserEmail}" : "Not signed in",
|
||||||
FontSize = 13, FontWeight = FontWeights.SemiBold, Foreground = (SolidColorBrush)Application.Current.Resources["TextBrush"],
|
FontSize = 13, FontWeight = FontWeights.SemiBold,
|
||||||
|
Foreground = (SolidColorBrush)Application.Current.Resources["TextBrush"],
|
||||||
VerticalAlignment = VerticalAlignment.Center,
|
VerticalAlignment = VerticalAlignment.Center,
|
||||||
};
|
};
|
||||||
var authRow = new StackPanel { Orientation = Orientation.Horizontal };
|
var authRow = new StackPanel { Orientation = Orientation.Horizontal };
|
||||||
authRow.Children.Add(dot);
|
authRow.Children.Add(dot);
|
||||||
authRow.Children.Add(label);
|
authRow.Children.Add(label2);
|
||||||
AuthPanel.Children.Add(authRow);
|
AuthPanel.Children.Add(authRow);
|
||||||
|
|
||||||
SignOutButton.Visibility = VM.IsSignedIn ? Visibility.Visible : Visibility.Collapsed;
|
SignOutButton.Visibility = VM.IsSignedIn ? Visibility.Visible : Visibility.Collapsed;
|
||||||
@@ -521,10 +545,10 @@ public partial class PopupWindow : Window
|
|||||||
|
|
||||||
private void RefreshPicker_Changed(object s, SelectionChangedEventArgs e)
|
private void RefreshPicker_Changed(object s, SelectionChangedEventArgs e)
|
||||||
{
|
{
|
||||||
if (RefreshPicker.SelectedItem is ValueTuple<string, int> selected)
|
if (RefreshPicker.SelectedItem is ComboBoxItem item && item.Tag is int seconds)
|
||||||
{
|
{
|
||||||
VM.RefreshInterval = selected.Item2;
|
VM.RefreshInterval = seconds;
|
||||||
((App)Application.Current).ScheduleTimer(selected.Item2);
|
((App)Application.Current).ScheduleTimer(seconds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user