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
5 changes: 4 additions & 1 deletion .claude/settings.local.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@
"Bash(dotnet build:*)",
"Bash(taskkill:*)",
"Bash(powershell:*)",
"Bash(terminal-notifier:*)"
"Bash(terminal-notifier:*)",
"Bash(ls:*)",
"Bash(gh pr list:*)",
"Bash(git show:*)"
]
}
}
65 changes: 45 additions & 20 deletions KeyStats.Windows/KeyStats/Services/StatsManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -334,20 +334,26 @@ private void SaveStats()
{
var json = JsonSerializer.Serialize(CurrentStats, new JsonSerializerOptions { WriteIndented = true });
var tempPath = _statsFilePath + ".tmp";
var backupPath = _statsFilePath + ".bak";
File.WriteAllText(tempPath, json);
// .NET Framework 4.8 兼容:File.Move 没有 3 参数重载,需要先删除

if (File.Exists(_statsFilePath))
{
File.Delete(_statsFilePath);
// 原子替换:临时文件 → 目标文件,原文件 → 备份文件
File.Replace(tempPath, _statsFilePath, backupPath);
}
else
{
File.Move(tempPath, _statsFilePath);
}
File.Move(tempPath, _statsFilePath);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"Error saving stats: {ex.Message}");
}

RecordCurrentStatsToHistory();
SaveHistory();
}
}

Expand Down Expand Up @@ -382,7 +388,6 @@ private void RecordCurrentStatsToHistory()
KeyPressCounts = new Dictionary<string, int>(CurrentStats.KeyPressCounts)
};
History[key] = statsCopy;
// SaveHistory is called by the timer callback, no need to call it here
}

private void SaveHistory()
Expand All @@ -391,13 +396,17 @@ private void SaveHistory()
{
var json = JsonSerializer.Serialize(History, new JsonSerializerOptions { WriteIndented = true });
var tempPath = _historyFilePath + ".tmp";
var backupPath = _historyFilePath + ".bak";
File.WriteAllText(tempPath, json);
// .NET Framework 4.8 兼容:File.Move 没有 3 参数重载,需要先删除
if (File.Exists(_historyFilePath))
{
File.Delete(_historyFilePath);
}

if (File.Exists(_historyFilePath))
{
File.Replace(tempPath, _historyFilePath, backupPath);
}
else
{
File.Move(tempPath, _historyFilePath);
}
}
catch (Exception ex)
{
Expand Down Expand Up @@ -449,13 +458,17 @@ public void SaveSettings()
{
var json = JsonSerializer.Serialize(Settings, new JsonSerializerOptions { WriteIndented = true });
var tempPath = _settingsFilePath + ".tmp";
var backupPath = _settingsFilePath + ".bak";
File.WriteAllText(tempPath, json);
// .NET Framework 4.8 兼容:File.Move 没有 3 参数重载,需要先删除
if (File.Exists(_settingsFilePath))
{
File.Delete(_settingsFilePath);
}

if (File.Exists(_settingsFilePath))
{
File.Replace(tempPath, _settingsFilePath, backupPath);
}
else
{
File.Move(tempPath, _settingsFilePath);
}
}
catch (Exception ex)
{
Expand Down Expand Up @@ -512,7 +525,11 @@ private void PerformMidnightReset()
ResetStats(now);
}
// Also prune old history entries during midnight reset
PruneOldHistory(History);
lock (_lock)
{
PruneOldHistory(History);
SaveHistory();
}
ScheduleNextMidnightReset();
}

Expand All @@ -525,6 +542,11 @@ private void ResetStats(DateTime date)
{
lock (_lock)
{
// 先保存旧数据到 History,避免丢失最后一次保存后的增量
RecordCurrentStatsToHistory();
SaveHistory();

// 然后创建新的统计对象
CurrentStats = new DailyStats(date);
}

Expand Down Expand Up @@ -642,12 +664,15 @@ public enum HistoryMetric { KeyPresses, Clicks, MouseDistance, ScrollDistance }
public List<(DateTime Date, double Value)> GetHistorySeries(HistoryRange range, HistoryMetric metric)
{
var dates = GetDatesInRange(range);
return dates.Select(date =>
lock (_lock)
{
var key = date.ToString("yyyy-MM-dd");
var stats = History.TryGetValue(key, out var s) ? s : new DailyStats(date);
return (date, GetMetricValue(metric, stats));
}).ToList();
return dates.Select(date =>
{
var key = date.ToString("yyyy-MM-dd");
var stats = History.TryGetValue(key, out var s) ? s : new DailyStats(date);
return (date, GetMetricValue(metric, stats));
}).ToList();
}
}

public string FormatHistoryValue(HistoryMetric metric, double value)
Expand Down