using ClawdDotNet.Core.Backup; namespace ClawdDotNet; /// /// Fragt ab, wohin wiederhergestellt wird und — falls nötig — die Passphrase. /// /// Bewusst ein eigener Schritt statt stiller Vorbelegung: Eine Wiederherstellung /// überschreibt Arbeitsstände, das soll niemand versehentlich auslösen. /// public sealed class frm_RestoreBackup : Form { private readonly TextBox _txtTarget = new(); private readonly TextBox _txtPassphrase = new() { UseSystemPasswordChar = true }; private readonly CheckBox _chkOverwrite = new(); public string TargetDirectory => _txtTarget.Text.Trim(); public string? Passphrase => _txtPassphrase.Text.Length > 0 ? _txtPassphrase.Text : null; public bool Overwrite => _chkOverwrite.Checked; public frm_RestoreBackup(BackupManifest manifest, string suggestedTarget) { Text = "Sicherung wiederherstellen"; FormBorderStyle = FormBorderStyle.FixedDialog; StartPosition = FormStartPosition.CenterParent; MinimizeBox = false; MaximizeBox = false; ClientSize = new Size(680, 380); var layout = new TableLayoutPanel { ColumnCount = 3, Dock = DockStyle.Fill, Padding = new Padding(14), RowCount = 7 }; layout.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize)); layout.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F)); layout.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize)); for (var i = 0; i < 7; i++) layout.RowStyles.Add(new RowStyle(SizeType.AutoSize)); // ─── Beschreibung der Sicherung ─── var info = new Label { AutoSize = true, Margin = new Padding(0, 0, 0, 12), Text = $"Instanz: {manifest.InstanceName}\n" + $"Erstellt: {manifest.CreatedAt:g}\n" + $"Dateien: {manifest.Files.Count}\n" + $"Zugangsdaten: {DescribeSecrets(manifest)}" }; layout.Controls.Add(info, 0, 0); layout.SetColumnSpan(info, 3); // ─── Zielordner ─── layout.Controls.Add(new Label { Anchor = AnchorStyles.Left, AutoSize = true, Text = "Zielordner:" }, 0, 1); _txtTarget.Anchor = AnchorStyles.Left | AnchorStyles.Right; _txtTarget.Text = suggestedTarget; layout.Controls.Add(_txtTarget, 1, 1); var browse = new Button { AutoSize = true, Text = "…" }; browse.Click += OnBrowse; layout.Controls.Add(browse, 2, 1); var targetHint = new Label { AutoSize = true, ForeColor = SystemColors.GrayText, Margin = new Padding(0, 2, 0, 10), MaximumSize = new Size(620, 0), Text = "Vorgeschlagen ist ein neuer Ordner. Die laufende Instanz zu überschreiben " + "wird nicht empfohlen: Sie hält Dateien geöffnet und schreibt Teile davon " + "sofort wieder zurück." }; layout.Controls.Add(targetHint, 1, 2); layout.SetColumnSpan(targetHint, 2); // ─── Passphrase ─── var needsPassphrase = manifest.HasSecrets; var lblPass = new Label { Anchor = AnchorStyles.Left, AutoSize = true, Enabled = needsPassphrase, Text = "Passphrase:" }; layout.Controls.Add(lblPass, 0, 3); _txtPassphrase.Anchor = AnchorStyles.Left | AnchorStyles.Right; _txtPassphrase.Enabled = needsPassphrase; layout.Controls.Add(_txtPassphrase, 1, 3); var passHint = new Label { AutoSize = true, ForeColor = SystemColors.GrayText, Margin = new Padding(0, 2, 0, 10), MaximumSize = new Size(620, 0), Text = needsPassphrase ? "Diese Sicherung enthält geschützte Zugangsdaten." : "Diese Sicherung enthält keine Zugangsdaten — API-Schlüssel und Passwörter " + "müssen nach dem Wiederherstellen neu eingetragen werden." }; layout.Controls.Add(passHint, 1, 4); layout.SetColumnSpan(passHint, 2); // ─── Überschreiben ─── _chkOverwrite.AutoSize = true; _chkOverwrite.Margin = new Padding(0, 0, 0, 12); _chkOverwrite.Text = "Vorhandene Dateien im Zielordner überschreiben"; layout.Controls.Add(_chkOverwrite, 1, 5); layout.SetColumnSpan(_chkOverwrite, 2); // ─── Schaltflächen ─── var buttons = new FlowLayoutPanel { AutoSize = true, Dock = DockStyle.Fill, FlowDirection = FlowDirection.RightToLeft }; var cancel = new Button { AutoSize = true, DialogResult = DialogResult.Cancel, Text = "Abbrechen" }; var ok = new Button { AutoSize = true, Text = "Wiederherstellen" }; ok.Click += OnConfirm; buttons.Controls.Add(cancel); buttons.Controls.Add(ok); layout.Controls.Add(buttons, 1, 6); layout.SetColumnSpan(buttons, 2); Controls.Add(layout); AcceptButton = ok; CancelButton = cancel; } private static string DescribeSecrets(BackupManifest manifest) => manifest.HasSecrets ? $"{manifest.SecretCount}, mit Passphrase geschützt" : manifest.SecretCount > 0 ? $"{manifest.SecretCount} entfernt" : "keine"; private void OnBrowse(object? sender, EventArgs e) { using var dialog = new FolderBrowserDialog { Description = "Zielordner für die Wiederherstellung", UseDescriptionForTitle = true }; if (dialog.ShowDialog(this) == DialogResult.OK) _txtTarget.Text = dialog.SelectedPath; } private void OnConfirm(object? sender, EventArgs e) { if (string.IsNullOrWhiteSpace(TargetDirectory)) { MessageBox.Show(this, "Bitte einen Zielordner angeben.", "Wiederherstellen", MessageBoxButtons.OK, MessageBoxIcon.Information); return; } if (_txtPassphrase.Enabled && string.IsNullOrEmpty(_txtPassphrase.Text)) { MessageBox.Show(this, "Diese Sicherung enthält geschützte Zugangsdaten. Ohne Passphrase lässt sie " + "sich nicht wiederherstellen.", "Wiederherstellen", MessageBoxButtons.OK, MessageBoxIcon.Information); _txtPassphrase.Focus(); return; } DialogResult = DialogResult.OK; Close(); } }