feat(65): F10 saves a clip; the gear drawer owns the three settings
Slice 4. 607 green, 0 warnings. Clips remain **off by default** and, while off, the ring is never constructed — so no reader thread and no encoder output exist until someone asks for the feature. - **F10** (`HotkeyId.SaveClip`, default F10, remappable in the hotkey dialog) snapshots the ring, writes the file, prunes to the retention count and toasts the name. Empty ring → "nothing to clip yet" instead of a zero-byte file; clips off → says so and points at Settings. - **Settings**: Enable, length (10 or 15, default 10), keep (3/4/5, default 3). Persisted in the layout store and **coerced on load** — a bad stored value falls back to a legal one, so the ring can never be sized for a length the UI cannot show. - The ring is sized from length × tier bitrate × 1.25 and rebuilt if either changes; it is created at session start and dropped at stop, so memory is only spent while a show is running. - The drawer states the boundary in the creator's terms: "A capture, not an editor: for trimming, captions or a library, use a video editor." Still to come: the replay layer itself (play once then hide in Live, loop the kept clips elsewhere).
This commit is contained in:
@@ -16,6 +16,8 @@ public enum HotkeyId
|
||||
ToggleMicMute = 7,
|
||||
ToggleGameMute = 8,
|
||||
TraxPlayPause = 9,
|
||||
/// <summary>TASK 65: snapshot the replay ring and save it as a clip.</summary>
|
||||
SaveClip = 10,
|
||||
}
|
||||
|
||||
/// <summary>Registers/revokes the OS-level hotkeys. Seam so tests never touch
|
||||
@@ -65,6 +67,7 @@ public sealed class GlobalHotkeyManager
|
||||
[HotkeyId.ToggleMicMute] = new HotkeyChord(0, 0x76), // F7
|
||||
[HotkeyId.ToggleGameMute] = new HotkeyChord(0, 0x77), // F8
|
||||
[HotkeyId.TraxPlayPause] = new HotkeyChord(0, 0x78), // F9
|
||||
[HotkeyId.SaveClip] = new HotkeyChord(0, 0x79), // F10
|
||||
};
|
||||
|
||||
private readonly IHotkeyRegistrar _registrar;
|
||||
|
||||
@@ -63,6 +63,23 @@ public partial class LayoutStore : IDisposable
|
||||
|
||||
public void SaveShowMonetaryMetrics(bool show) => UpsertSetting("Metrics.ShowMonetary", show ? "1" : "0");
|
||||
|
||||
/// <summary>TASK 65: replay clips. Off by default — the ring costs memory and the feature is opt-in.</summary>
|
||||
public bool LoadClipsEnabled() => GetSetting("Clips.Enabled") == "1";
|
||||
|
||||
public void SaveClipsEnabled(bool enabled) => UpsertSetting("Clips.Enabled", enabled ? "1" : "0");
|
||||
|
||||
/// <summary>Clip length in seconds: 10 or 15 (default 10).</summary>
|
||||
public int LoadClipSeconds()
|
||||
=> int.TryParse(GetSetting("Clips.Seconds"), out var s) && (s == 10 || s == 15) ? s : 10;
|
||||
|
||||
public void SaveClipSeconds(int seconds) => UpsertSetting("Clips.Seconds", seconds.ToString());
|
||||
|
||||
/// <summary>How many clips survive on disk: 3, 4 or 5 (default 3).</summary>
|
||||
public int LoadClipKeep()
|
||||
=> int.TryParse(GetSetting("Clips.Keep"), out var k) && k >= 3 && k <= 5 ? k : 3;
|
||||
|
||||
public void SaveClipKeep(int keep) => UpsertSetting("Clips.Keep", keep.ToString());
|
||||
|
||||
public bool LoadAutoChromaScreen() => GetSetting("Video.AutoChromaScreen") == "1";
|
||||
|
||||
public void SaveAutoChromaScreen(bool enabled) => UpsertSetting("Video.AutoChromaScreen", enabled ? "1" : "0");
|
||||
|
||||
Reference in New Issue
Block a user