Files
ClaudeDo/src/ClaudeDo.Ui/Views/Modals/SettingsModalView.axaml
T
mika kuns 7c7c33d677 feat(ui): PowerUse-Einstellungen nach Settings -> Ausfuehrung verschieben
Schalter, Zeitfenster und Handoff-Prozent lagen im Usage-Monitor und mussten
in SettingsModalViewModel nur load->save durchgeschleift werden, damit ein
Settings-Speichern sie nicht zurueckwirft. Jetzt gehoeren sie dem General-Tab,
der Monitor ist wieder nur Anzeige + Threshold-Drag, und "Jetzt aktualisieren"
sitzt als Icon in der Titelleiste (neuer ModalShell.HeaderActions-Slot).
2026-09-07 08:17:37 +02:00

781 lines
51 KiB
XML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:ClaudeDo.Ui.ViewModels.Modals"
xmlns:settings="using:ClaudeDo.Ui.ViewModels.Modals.Settings"
xmlns:ui="using:ClaudeDo.Ui"
xmlns:agent="using:ClaudeDo.Ui.ViewModels.Agent"
xmlns:services="using:ClaudeDo.Ui.Services"
xmlns:ctl="using:ClaudeDo.Ui.Views.Controls"
xmlns:loc="using:ClaudeDo.Ui.Localization"
xmlns:locm="using:ClaudeDo.Localization"
x:Class="ClaudeDo.Ui.Views.Modals.SettingsModalView"
x:DataType="vm:SettingsModalViewModel"
Title="{loc:Tr settings.title}"
Width="700" Height="760" MinWidth="600" MinHeight="520"
CanResize="True"
WindowDecorations="BorderOnly"
ExtendClientAreaToDecorationsHint="True"
ExtendClientAreaTitleBarHeightHint="-1"
WindowStartupLocation="CenterOwner"
Background="{DynamicResource SurfaceBrush}">
<Window.KeyBindings>
<KeyBinding Gesture="Escape" Command="{Binding CancelCommand}"/>
</Window.KeyBindings>
<ctl:ModalShell Title="{loc:Tr settings.title}" CloseCommand="{Binding CancelCommand}">
<ctl:ModalShell.Footer>
<StackPanel Orientation="Horizontal" Spacing="8"
HorizontalAlignment="Right" VerticalAlignment="Center">
<Button Classes="btn" Content="{loc:Tr settings.cancel}" Command="{Binding CancelCommand}" MinWidth="90"/>
<Button Content="{loc:Tr settings.save}" Classes="primary"
Command="{Binding SaveCommand}"
IsEnabled="{Binding !IsBusy}" MinWidth="90"/>
</StackPanel>
</ctl:ModalShell.Footer>
<!-- Body: sidebar + tab-content host + bottom validation/status strip -->
<DockPanel>
<StackPanel DockPanel.Dock="Bottom" Margin="20,0,20,8" Spacing="2">
<TextBlock Classes="meta" Text="{Binding ValidationError}"
Foreground="{DynamicResource BloodBrush}"
IsVisible="{Binding ValidationError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
<TextBlock Classes="meta" Text="{Binding StatusMessage}"
IsVisible="{Binding StatusMessage, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
</StackPanel>
<Grid ColumnDefinitions="170,1,*">
<!-- Sidebar: two independently-scrolled groups sharing one SelectedCategory. -->
<StackPanel Grid.Column="0" Spacing="16" Margin="12,16,8,8">
<StackPanel Spacing="2">
<TextBlock Classes="eyebrow" Opacity="0.6" Margin="10,0,0,4"
Text="{loc:Tr settings.sidebar.groupBasis}"/>
<ListBox ItemsSource="{Binding BasisCategories}"
SelectedItem="{Binding SelectedCategory, Mode=TwoWay}"
Background="Transparent">
<ListBox.ItemTemplate>
<DataTemplate x:DataType="vm:SettingsCategory">
<TextBlock Text="{Binding Label.Value}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
<StackPanel Spacing="2">
<TextBlock Classes="eyebrow" Opacity="0.6" Margin="10,0,0,4"
Text="{loc:Tr settings.sidebar.groupAdvanced}"/>
<ListBox ItemsSource="{Binding ErweitertCategories}"
SelectedItem="{Binding SelectedCategory, Mode=TwoWay}"
Background="Transparent">
<ListBox.Styles>
<Style Selector="ListBoxItem" x:DataType="vm:SettingsCategory">
<Setter Property="IsVisible" Value="{Binding IsVisible}"/>
</Style>
</ListBox.Styles>
<ListBox.ItemTemplate>
<DataTemplate x:DataType="vm:SettingsCategory">
<TextBlock Text="{Binding Label.Value}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</StackPanel>
<Border Grid.Column="1" Background="{DynamicResource LineBrush}" Width="1" Margin="0,8"/>
<!-- TabControl stays the content host (SelectedIndex driven by the sidebar); its own
header strip is re-templated away so only PART_SelectedContentHost renders.
The PART_ItemsPresenter must stay in the template even though it is collapsed:
TabControl.SelectedContent is resolved via ContainerFromIndex, and without a
presenter the TabItem containers are never realized -> SelectedContent is null
and the modal body renders empty. -->
<TabControl Grid.Column="2" Padding="20,16" SelectedIndex="{Binding SelectedIndex, Mode=OneWay}">
<TabControl.Template>
<ControlTemplate TargetType="TabControl">
<Panel>
<ItemsPresenter Name="PART_ItemsPresenter"
ItemsPanel="{TemplateBinding ItemsPanel}"
IsVisible="False"/>
<ContentPresenter Name="PART_SelectedContentHost"
Padding="{TemplateBinding Padding}"
Content="{TemplateBinding SelectedContent}"
ContentTemplate="{TemplateBinding SelectedContentTemplate}"/>
</Panel>
</ControlTemplate>
</TabControl.Template>
<!-- Allgemein: language, accent, default instructions. -->
<TabItem Header="{loc:Tr settings.sidebar.categoryGeneral}">
<ScrollViewer>
<StackPanel Spacing="12" Margin="0,8,0,0">
<StackPanel Spacing="4">
<TextBlock Classes="field-label" Text="{loc:Tr settings.language}"/>
<ComboBox ItemsSource="{Binding General.Languages}"
SelectedItem="{Binding General.SelectedLanguage, Mode=TwoWay}"
HorizontalAlignment="Left" Width="220">
<ComboBox.ItemTemplate>
<DataTemplate x:DataType="locm:LanguageOption">
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
<StackPanel Spacing="4">
<TextBlock Classes="field-label" Text="{loc:Tr settings.general.accentPreset}"/>
<ItemsControl ItemsSource="{Binding General.AccentPresetSwatches}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" Spacing="8"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="ui:AccentPresetSwatchViewModel">
<Button Padding="6,4"
Command="{Binding $parent[ItemsControl].((vm:SettingsModalViewModel)DataContext).General.SelectAccentPresetCommand}"
CommandParameter="{Binding Preset}">
<StackPanel Spacing="4">
<Grid Width="32" Height="32">
<Border Width="32" Height="32" CornerRadius="16"
BorderBrush="{DynamicResource AccentBrush}" BorderThickness="2"
IsVisible="{Binding IsSelected}"/>
<Ellipse Width="22" Height="22"
HorizontalAlignment="Center" VerticalAlignment="Center">
<Ellipse.Fill>
<SolidColorBrush Color="{Binding DisplayColor}"/>
</Ellipse.Fill>
</Ellipse>
</Grid>
<TextBlock Text="{Binding DisplayName}"
HorizontalAlignment="Center" FontSize="11"/>
</StackPanel>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
<StackPanel Spacing="4">
<TextBlock Classes="field-label" Text="{loc:Tr settings.general.defaultInstructions}"/>
<TextBox AcceptsReturn="True" TextWrapping="Wrap" Height="110"
PlaceholderText="{loc:Tr settings.general.defaultInstructionsPlaceholder}"
Text="{Binding General.DefaultClaudeInstructions, Mode=TwoWay}"/>
</StackPanel>
</StackPanel>
</ScrollViewer>
</TabItem>
<!-- Ausführung: model/permission, per-model presets, parallelism, usage gate. -->
<TabItem Header="{loc:Tr settings.sidebar.categoryExecution}">
<ScrollViewer>
<StackPanel Spacing="12" Margin="0,8,0,0">
<Grid ColumnDefinitions="*,12,*">
<StackPanel Grid.Column="0" Spacing="4">
<TextBlock Classes="field-label" Text="{loc:Tr settings.general.model}"/>
<ComboBox ItemsSource="{Binding General.Models}"
SelectedItem="{Binding General.DefaultModel, Mode=TwoWay}"
HorizontalAlignment="Stretch"/>
</StackPanel>
<StackPanel Grid.Column="2" Spacing="4">
<TextBlock Classes="field-label" Text="{loc:Tr settings.general.permission}"/>
<ComboBox ItemsSource="{Binding General.PermissionModes}"
SelectedItem="{Binding General.DefaultPermissionMode, Mode=TwoWay}"
HorizontalAlignment="Stretch"/>
</StackPanel>
</Grid>
<!-- Per-model run defaults: replaces the single global "max turns" field. -->
<StackPanel Spacing="4">
<TextBlock Classes="field-label" Text="{loc:Tr settings.general.modelPresets}"/>
<TextBlock Text="{loc:Tr settings.general.modelPresetsHint}"
Opacity="0.6" FontSize="12" TextWrapping="Wrap"/>
<Grid ColumnDefinitions="90,12,*,12,110" Margin="0,4,0,0">
<TextBlock Grid.Column="0" Classes="eyebrow" Text="{loc:Tr settings.general.model}"/>
<TextBlock Grid.Column="2" Classes="eyebrow" Text="{loc:Tr settings.general.effort}"/>
<TextBlock Grid.Column="4" Classes="eyebrow" Text="{loc:Tr settings.general.maxTurns}"/>
</Grid>
<ItemsControl ItemsSource="{Binding General.ModelPresets}">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="settings:ModelPresetRowViewModel">
<StackPanel Spacing="2" Margin="0,0,0,6">
<Grid ColumnDefinitions="90,12,*,12,110">
<TextBlock Grid.Column="0" Text="{Binding Model}" VerticalAlignment="Center"/>
<ComboBox Grid.Column="2" ItemsSource="{Binding EffortLevels}"
SelectedItem="{Binding Effort, Mode=TwoWay}"
HorizontalAlignment="Stretch"/>
<NumericUpDown Grid.Column="4" Value="{Binding MaxTurns, Mode=TwoWay, Converter={StaticResource KeepLastNumber}}"
Minimum="1" Maximum="200" Increment="1" FormatString="0"/>
</Grid>
<TextBlock Classes="meta" Opacity="0.6" TextWrapping="Wrap"
Text="{Binding ClampHint}"
IsVisible="{Binding ClampHint, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<StackPanel Spacing="4" Margin="0,4,0,0">
<TextBlock Classes="eyebrow" Text="{loc:Tr settings.general.maxTurnsCeiling}"/>
<NumericUpDown Value="{Binding General.MaxTurnsCeiling, Mode=TwoWay, Converter={StaticResource KeepLastNumber}}"
Minimum="1" Maximum="200" Increment="10" FormatString="0"
HorizontalAlignment="Left" Width="140"/>
<TextBlock Text="{loc:Tr settings.general.maxTurnsCeilingHint}"
Opacity="0.6" FontSize="12" TextWrapping="Wrap"/>
</StackPanel>
</StackPanel>
<StackPanel Spacing="4">
<TextBlock Classes="field-label" Text="{loc:Tr settings.general.maxParallelExecutions}"/>
<NumericUpDown Value="{Binding General.MaxParallelExecutions, Mode=TwoWay, Converter={StaticResource KeepLastNumber}}"
Minimum="1" Maximum="20" Increment="1" FormatString="0"
HorizontalAlignment="Left" Width="140"/>
<TextBlock Text="{loc:Tr settings.general.maxParallelExecutionsHint}"
Opacity="0.6" FontSize="12"/>
</StackPanel>
<StackPanel Spacing="4">
<TextBlock Classes="field-label" Text="{loc:Tr settings.general.usageGateHeading}"/>
<TextBlock Text="{loc:Tr settings.general.usageGateHint}"
Opacity="0.6" FontSize="12" TextWrapping="Wrap"/>
<StackPanel Orientation="Horizontal" Spacing="16">
<StackPanel Spacing="4">
<TextBlock Classes="eyebrow" Text="{loc:Tr settings.general.usageGateFiveHourPct}"/>
<NumericUpDown Value="{Binding General.UsageGateFiveHourPct, Mode=TwoWay, Converter={StaticResource KeepLastNumber}}"
Minimum="0" Maximum="100" Increment="5" FormatString="0"
HorizontalAlignment="Left" Width="140"/>
</StackPanel>
<StackPanel Spacing="4">
<TextBlock Classes="eyebrow" Text="{loc:Tr settings.general.usageGateSevenDayPct}"/>
<NumericUpDown Value="{Binding General.UsageGateSevenDayPct, Mode=TwoWay, Converter={StaticResource KeepLastNumber}}"
Minimum="0" Maximum="100" Increment="5" FormatString="0"
HorizontalAlignment="Left" Width="140"/>
</StackPanel>
</StackPanel>
<CheckBox IsChecked="{Binding General.AutoContinueOnUsageLimit, Mode=TwoWay}"
Content="{loc:Tr settings.general.autoContinueOnUsageLimit}"/>
<TextBlock Text="{loc:Tr settings.general.autoContinueOnUsageLimitHint}"
Opacity="0.6" FontSize="12" TextWrapping="Wrap"/>
<!-- Outside the PowerUse section below on purpose: the handoff budget also bounds
a normal (interactive) handler run. -->
<StackPanel Spacing="4">
<TextBlock Classes="eyebrow" Text="{loc:Tr settings.general.listHandlerMaxHandoffs}"/>
<NumericUpDown Value="{Binding General.ListHandlerMaxHandoffs, Mode=TwoWay, Converter={StaticResource KeepLastNumber}}"
Minimum="1" Maximum="200" Increment="2" FormatString="0"
HorizontalAlignment="Left" Width="140"/>
<TextBlock Text="{loc:Tr settings.general.listHandlerMaxHandoffsHint}"
Opacity="0.6" FontSize="12" TextWrapping="Wrap"/>
</StackPanel>
</StackPanel>
<!-- PowerUse: a master switch plus its time window. Never sufficient on its own —
the run's list must also allow PowerUse in its list settings. -->
<StackPanel Spacing="4">
<TextBlock Classes="field-label" Text="{loc:Tr settings.general.powerUseHeading}"/>
<CheckBox IsChecked="{Binding General.PowerUseEnabled, Mode=TwoWay}"
Content="{loc:Tr settings.general.powerUse}"/>
<TextBlock Text="{loc:Tr settings.general.powerUseHint}"
Opacity="0.6" FontSize="12" TextWrapping="Wrap"/>
<StackPanel Orientation="Horizontal" Spacing="8" Margin="0,6,0,0">
<TextBlock Classes="eyebrow" VerticalAlignment="Center"
Text="{loc:Tr settings.general.powerUseWindow}"/>
<TextBox Width="70" FontSize="12" Padding="6,2"
Watermark="{loc:Tr settings.general.powerUseWindowPlaceholder}"
Text="{Binding General.PowerUseWindowStart, Mode=TwoWay}"/>
<TextBlock Classes="meta" VerticalAlignment="Center" Text="–"/>
<TextBox Width="70" FontSize="12" Padding="6,2"
Watermark="{loc:Tr settings.general.powerUseWindowPlaceholder}"
Text="{Binding General.PowerUseWindowEnd, Mode=TwoWay}"/>
<TextBlock Classes="eyebrow" VerticalAlignment="Center" Margin="12,0,0,0"
Text="{loc:Tr settings.general.powerUseHandoffPct}"/>
<NumericUpDown Width="80" FontSize="12" Padding="6,2" ShowButtonSpinner="False"
Minimum="50" Maximum="99" Increment="1" FormatString="0"
Value="{Binding General.PowerUseHandoffPct, Mode=TwoWay, Converter={StaticResource KeepLastNumber}}"/>
</StackPanel>
<TextBlock Text="{loc:Tr settings.general.powerUseWindowHint}"
Opacity="0.6" FontSize="12" TextWrapping="Wrap"/>
</StackPanel>
<!-- Throttle stages live on the usage-monitor gauges (drag + spinner per stage);
echoed read-only here so they aren't invisible on the tab that owns the gate. -->
<StackPanel Spacing="4">
<TextBlock Classes="field-label" Text="{loc:Tr settings.general.throttleStagesHeading}"/>
<TextBlock Text="{Binding ThrottleSummary}" Classes="meta"/>
<TextBlock Text="{loc:Tr settings.general.throttleStagesHint}"
Opacity="0.6" FontSize="12" TextWrapping="Wrap"/>
<Button Classes="btn" HorizontalAlignment="Left"
Content="{loc:Tr settings.general.openUsageMonitor}"
Command="{Binding OpenUsageMonitorCommand}"/>
</StackPanel>
</StackPanel>
</ScrollViewer>
</TabItem>
<TabItem Header="{loc:Tr settings.sidebar.categoryPrime}">
<ScrollViewer>
<StackPanel Spacing="12" Margin="0,8,0,0">
<Border IsVisible="{Binding !HasLinkedRepo}"
Background="{DynamicResource DeepBrush}" BorderBrush="{DynamicResource LineBrush}"
BorderThickness="1" CornerRadius="6" Padding="10,8">
<StackPanel Orientation="Horizontal" Spacing="8" VerticalAlignment="Center">
<TextBlock Classes="meta" Text="{loc:Tr settings.repoHint.text}" VerticalAlignment="Center"/>
<Button Classes="btn" Content="{loc:Tr settings.repoHint.link}" Command="{Binding OpenRepoImportCommand}"/>
</StackPanel>
</Border>
<TextBlock Classes="meta" TextWrapping="Wrap"
Text="{loc:Tr settings.prime.description}"/>
<TextBlock Classes="meta" TextWrapping="Wrap"
Text="{loc:Tr settings.prime.actionHint}"/>
<ItemsControl ItemsSource="{Binding Prime.Rows}">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="settings:PrimeScheduleRowViewModel">
<Border BorderBrush="{DynamicResource LineBrush}" BorderThickness="1"
CornerRadius="6" Padding="10,8" Margin="0,0,0,8"
Background="{DynamicResource DeepBrush}">
<StackPanel Spacing="6">
<Grid ColumnDefinitions="Auto,Auto,Auto,*,Auto" ColumnSpacing="8">
<CheckBox Grid.Column="0" IsChecked="{Binding Enabled, Mode=TwoWay}" VerticalAlignment="Center"/>
<StackPanel Grid.Column="1" Orientation="Horizontal" Spacing="4" VerticalAlignment="Center">
<ToggleButton Classes="day-toggle" Content="{loc:Tr settings.prime.dayMo}" IsChecked="{Binding Monday, Mode=TwoWay}"/>
<ToggleButton Classes="day-toggle" Content="{loc:Tr settings.prime.dayTu}" IsChecked="{Binding Tuesday, Mode=TwoWay}"/>
<ToggleButton Classes="day-toggle" Content="{loc:Tr settings.prime.dayWe}" IsChecked="{Binding Wednesday, Mode=TwoWay}"/>
<ToggleButton Classes="day-toggle" Content="{loc:Tr settings.prime.dayTh}" IsChecked="{Binding Thursday, Mode=TwoWay}"/>
<ToggleButton Classes="day-toggle" Content="{loc:Tr settings.prime.dayFr}" IsChecked="{Binding Friday, Mode=TwoWay}"/>
<ToggleButton Classes="day-toggle" Content="{loc:Tr settings.prime.daySa}" IsChecked="{Binding Saturday, Mode=TwoWay}"/>
<ToggleButton Classes="day-toggle" Content="{loc:Tr settings.prime.daySu}" IsChecked="{Binding Sunday, Mode=TwoWay}"/>
</StackPanel>
<TextBox Grid.Column="2"
Text="{Binding TimeText, Mode=TwoWay}"
PlaceholderText="HH:mm" MaxLength="5"
Width="68" VerticalAlignment="Center"/>
<TextBlock Classes="meta" Grid.Column="3" Text="{Binding LastRunLabel}" VerticalAlignment="Center"
TextTrimming="CharacterEllipsis"
ToolTip.Tip="{Binding LastRunLabel}"/>
<Button Classes="icon-btn" Grid.Column="4" Content="✕"
ToolTip.Tip="{loc:Tr settings.prime.removeScheduleTip}"
Command="{Binding $parent[ItemsControl].((vm:SettingsModalViewModel)DataContext).Prime.RemoveScheduleCommand}"
CommandParameter="{Binding}"/>
</Grid>
<TextBlock Classes="field-label" Text="{loc:Tr settings.prime.actionLabel}"/>
<StackPanel Orientation="Horizontal" Spacing="16">
<RadioButton GroupName="{Binding RadioGroup}"
Content="{loc:Tr settings.prime.actionPing}"
IsChecked="{Binding IsPing, Mode=TwoWay}"/>
<RadioButton GroupName="{Binding RadioGroup}"
Content="{loc:Tr settings.prime.actionFillMyDay}"
IsChecked="{Binding IsFillMyDay, Mode=TwoWay}"/>
<RadioButton GroupName="{Binding RadioGroup}"
Content="{loc:Tr settings.prime.actionCustom}"
IsChecked="{Binding IsCustom, Mode=TwoWay}"/>
</StackPanel>
<TextBlock Classes="field-label" Text="{Binding PromptLabel}"
IsVisible="{Binding ShowPrompt}"/>
<TextBox Text="{Binding PromptOverride, Mode=TwoWay}"
PlaceholderText="{Binding PromptPlaceholder}"
IsVisible="{Binding ShowPrompt}"
AcceptsReturn="True" TextWrapping="Wrap"
MinHeight="48" MaxHeight="120"/>
</StackPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Button Classes="btn" Content="{loc:Tr settings.prime.addSchedule}" Command="{Binding Prime.AddScheduleCommand}" HorizontalAlignment="Left"/>
<StackPanel Orientation="Horizontal" Spacing="8" VerticalAlignment="Center">
<TextBlock Classes="field-label" Text="{loc:Tr settings.prime.dailyPrepMaxTasks}" VerticalAlignment="Center"/>
<NumericUpDown Minimum="1" Maximum="50" Increment="1" Width="100" FormatString="0"
IsEnabled="{Binding Prime.AnyFillMyDay}"
Value="{Binding Prime.DailyPrepMaxTasks, Mode=TwoWay, Converter={StaticResource KeepLastNumber}}"/>
<TextBlock Classes="meta" VerticalAlignment="Center"
Text="{loc:Tr settings.prime.maxTasksDisabledHint}"
IsVisible="{Binding !Prime.AnyFillMyDay}"/>
</StackPanel>
</StackPanel>
</ScrollViewer>
</TabItem>
<TabItem Header="{loc:Tr settings.sidebar.categoryWorktrees}">
<ScrollViewer>
<StackPanel Spacing="12" Margin="0,8,0,0">
<Border IsVisible="{Binding !HasLinkedRepo}"
Background="{DynamicResource DeepBrush}" BorderBrush="{DynamicResource LineBrush}"
BorderThickness="1" CornerRadius="6" Padding="10,8">
<StackPanel Orientation="Horizontal" Spacing="8" VerticalAlignment="Center">
<TextBlock Classes="meta" Text="{loc:Tr settings.repoHint.text}" VerticalAlignment="Center"/>
<Button Classes="btn" Content="{loc:Tr settings.repoHint.link}" Command="{Binding OpenRepoImportCommand}"/>
</StackPanel>
</Border>
<Grid ColumnDefinitions="*,12,2*">
<StackPanel Grid.Column="0" Spacing="4">
<TextBlock Classes="field-label" Text="{loc:Tr settings.worktrees.strategy}"/>
<ComboBox ItemsSource="{Binding Worktrees.WorktreeStrategies}"
SelectedItem="{Binding Worktrees.WorktreeStrategy, Mode=TwoWay}"
HorizontalAlignment="Stretch"/>
</StackPanel>
<StackPanel Grid.Column="2" Spacing="4">
<TextBlock Classes="field-label" Text="{loc:Tr settings.worktrees.centralWorktreeRoot}"/>
<TextBox Text="{Binding Worktrees.CentralWorktreeRoot, Mode=TwoWay}"
PlaceholderText="e.g. C:\worktrees"/>
</StackPanel>
</Grid>
<StackPanel Orientation="Horizontal" Spacing="8">
<CheckBox IsChecked="{Binding Worktrees.WorktreeAutoCleanupEnabled, Mode=TwoWay}"
Content="{loc:Tr settings.worktrees.autoCleanup}"
VerticalAlignment="Center"/>
<NumericUpDown Value="{Binding Worktrees.WorktreeAutoCleanupDays, Mode=TwoWay, Converter={StaticResource KeepLastNumber}}"
Width="130" Minimum="1" Maximum="365" Increment="1" FormatString="0"
IsEnabled="{Binding Worktrees.WorktreeAutoCleanupEnabled}"/>
<TextBlock Classes="body" Text="{loc:Tr settings.worktrees.days}" VerticalAlignment="Center"/>
</StackPanel>
<Border BorderBrush="{DynamicResource LineBrush}" BorderThickness="0,1,0,0" Margin="0,4,0,0"/>
<StackPanel Spacing="8">
<Button Classes="btn" Content="{loc:Tr settings.worktrees.cleanupFinished}"
Command="{Binding Worktrees.CleanupWorktreesCommand}"
HorizontalAlignment="Left"/>
<StackPanel Orientation="Horizontal" Spacing="8">
<Button Content="{loc:Tr settings.worktrees.forceRemoveAll}" Classes="danger"
Command="{Binding Worktrees.ConfirmResetAllCommand}"
HorizontalAlignment="Left"
IsEnabled="{Binding !Worktrees.ResetStatus.IsRunning}"/>
<ctl:OperationIndicator Status="{Binding Worktrees.ResetStatus}"/>
</StackPanel>
</StackPanel>
<TextBlock Classes="meta" Text="{Binding Worktrees.StatusMessage}"
IsVisible="{Binding Worktrees.StatusMessage, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
</StackPanel>
</ScrollViewer>
</TabItem>
<TabItem Header="{loc:Tr settings.sidebar.categoryFiles}">
<ScrollViewer>
<StackPanel Spacing="12" Margin="0,8,0,0">
<!-- claude_bin from worker.config.json — saved on its own button, not the modal's
Save, because the worker owns that file rather than app_settings. -->
<StackPanel Spacing="6">
<TextBlock Classes="section-label" Text="{loc:Tr settings.files.cliSection}"/>
<TextBlock Classes="meta" Text="{loc:Tr settings.files.claudeBinHint}" TextWrapping="Wrap"/>
<Grid ColumnDefinitions="*,Auto" ColumnSpacing="8">
<TextBox Grid.Column="0" Text="{Binding Files.ClaudeBin, Mode=TwoWay}"
PlaceholderText="claude"/>
<Button Grid.Column="1" Classes="btn" Content="{loc:Tr settings.save}"
Command="{Binding Files.SaveClaudeBinCommand}"/>
</Grid>
<ctl:OperationIndicator Status="{Binding Files.ClaudeBinOp}"/>
<TextBlock Classes="path-mono" TextWrapping="Wrap"
Text="{Binding Files.ClaudeBinResolvedHint}"
IsVisible="{Binding Files.ClaudeBinResolvedHint, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
</StackPanel>
<StackPanel Spacing="6">
<TextBlock Classes="section-label" Text="{loc:Tr settings.files.agentsSection}"/>
<TextBlock Classes="meta" Text="{loc:Tr settings.files.agentsHint}"
TextWrapping="Wrap"/>
<Button Classes="btn" Content="{loc:Tr settings.files.restoreDefaultAgents}"
Command="{Binding Files.RestoreDefaultAgentsCommand}"
HorizontalAlignment="Left"/>
<ctl:OperationIndicator Status="{Binding Files.RestoreOp}"/>
</StackPanel>
<StackPanel Spacing="6">
<TextBlock Classes="section-label" Text="{loc:Tr settings.files.promptsSection}"/>
<Grid RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto" ColumnDefinitions="120,*,Auto" RowSpacing="8">
<TextBlock Grid.Row="0" Grid.Column="0" Classes="field-label" Text="{loc:Tr settings.files.systemPrompt}" VerticalAlignment="Center"/>
<TextBlock Grid.Row="0" Grid.Column="1" Classes="path-mono" Text="{Binding Files.SystemPromptPath}" VerticalAlignment="Center"/>
<Button Classes="btn" Grid.Row="0" Grid.Column="2" Content="{loc:Tr settings.files.viewPrompt}"
Command="{Binding Files.ViewPromptCommand}" CommandParameter="System"/>
<TextBlock Grid.Row="1" Grid.Column="0" Classes="field-label" Text="{loc:Tr settings.files.planningPrompt}" VerticalAlignment="Center"/>
<TextBlock Grid.Row="1" Grid.Column="1" Classes="path-mono" Text="{Binding Files.PlanningPromptPath}" VerticalAlignment="Center"/>
<Button Classes="btn" Grid.Row="1" Grid.Column="2" Content="{loc:Tr settings.files.viewPrompt}"
Command="{Binding Files.ViewPromptCommand}" CommandParameter="Planning"/>
<TextBlock Grid.Row="2" Grid.Column="0" Classes="field-label" Text="{loc:Tr settings.files.planningInitialPrompt}" VerticalAlignment="Center"/>
<TextBlock Grid.Row="2" Grid.Column="1" Classes="path-mono" Text="{Binding Files.PlanningInitialPromptPath}" VerticalAlignment="Center"/>
<Button Classes="btn" Grid.Row="2" Grid.Column="2" Content="{loc:Tr settings.files.viewPrompt}"
Command="{Binding Files.ViewPromptCommand}" CommandParameter="PlanningInitial"/>
<TextBlock Grid.Row="3" Grid.Column="0" Classes="field-label" Text="{loc:Tr settings.files.retryPrompt}" VerticalAlignment="Center"/>
<TextBlock Grid.Row="3" Grid.Column="1" Classes="path-mono" Text="{Binding Files.RetryPromptPath}" VerticalAlignment="Center"/>
<Button Classes="btn" Grid.Row="3" Grid.Column="2" Content="{loc:Tr settings.files.viewPrompt}"
Command="{Binding Files.ViewPromptCommand}" CommandParameter="Retry"/>
<TextBlock Grid.Row="4" Grid.Column="0" Classes="field-label" Text="{loc:Tr settings.files.dailyPrepPrompt}" VerticalAlignment="Center"/>
<TextBlock Grid.Row="4" Grid.Column="1" Classes="path-mono" Text="{Binding Files.DailyPrepPromptPath}" VerticalAlignment="Center"/>
<Button Classes="btn" Grid.Row="4" Grid.Column="2" Content="{loc:Tr settings.files.viewPrompt}"
Command="{Binding Files.ViewPromptCommand}" CommandParameter="DailyPrep"/>
<TextBlock Grid.Row="5" Grid.Column="0" Classes="field-label" Text="{loc:Tr settings.files.weeklyReportPrompt}" VerticalAlignment="Center"/>
<TextBlock Grid.Row="5" Grid.Column="1" Classes="path-mono" Text="{Binding Files.WeeklyReportPromptPath}" VerticalAlignment="Center"/>
<Button Classes="btn" Grid.Row="5" Grid.Column="2" Content="{loc:Tr settings.files.viewPrompt}"
Command="{Binding Files.ViewPromptCommand}" CommandParameter="WeeklyReport"/>
<TextBlock Grid.Row="6" Grid.Column="0" Classes="field-label" Text="{loc:Tr settings.files.powerUsePrompt}" VerticalAlignment="Center"/>
<TextBlock Grid.Row="6" Grid.Column="1" Classes="path-mono" Text="{Binding Files.PowerUsePromptPath}" VerticalAlignment="Center"/>
<Button Classes="btn" Grid.Row="6" Grid.Column="2" Content="{loc:Tr settings.files.viewPrompt}"
Command="{Binding Files.ViewPromptCommand}" CommandParameter="PowerUseAddendum"/>
</Grid>
</StackPanel>
<StackPanel Spacing="6" IsVisible="{Binding Files.ViewedKindName, Converter={x:Static StringConverters.IsNotNullOrEmpty}}">
<TextBlock Classes="section-label" Text="{Binding Files.ViewedKindName}"/>
<Border BorderBrush="{DynamicResource LineBrush}" BorderThickness="1" CornerRadius="6" Padding="10"
Background="{DynamicResource DeepBrush}">
<ScrollViewer MaxHeight="260">
<ctl:MarkdownView Markdown="{Binding Files.ViewedContent}"/>
</ScrollViewer>
</Border>
</StackPanel>
<StackPanel Spacing="6" IsVisible="{Binding Files.HasCustomizedPrompts}">
<TextBlock Classes="section-label" Text="{loc:Tr settings.files.customizedSection}"/>
<TextBlock Classes="meta" Text="{loc:Tr settings.files.customizedHint}" TextWrapping="Wrap"/>
<ItemsControl ItemsSource="{Binding Files.CustomizedPrompts}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Spacing="4" Margin="0,0,0,10">
<Grid ColumnDefinitions="*,Auto">
<TextBlock Grid.Column="0" Classes="field-label" Text="{Binding KindName}" VerticalAlignment="Center"/>
<Button Grid.Column="1" Classes="btn" Content="{loc:Tr settings.files.resetToDefault}"
Command="{Binding ResetCommand}"/>
</Grid>
<TextBlock Classes="path-mono" Text="{Binding DiffPreview}" TextWrapping="Wrap"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
<TextBlock Classes="meta" Text="{Binding Files.StatusMessage}"
IsVisible="{Binding Files.StatusMessage, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
</StackPanel>
</ScrollViewer>
</TabItem>
<!-- Session Skills: merged install/manage list (was the "Skills" tab) plus the global
active-selection checkbox that used to be a separate list on the General tab. -->
<TabItem Header="{loc:Tr settings.sidebar.categorySkills}">
<ScrollViewer>
<StackPanel Spacing="12" Margin="0,8,0,0">
<Border IsVisible="{Binding !HasLinkedRepo}"
Background="{DynamicResource DeepBrush}" BorderBrush="{DynamicResource LineBrush}"
BorderThickness="1" CornerRadius="6" Padding="10,8">
<StackPanel Orientation="Horizontal" Spacing="8" VerticalAlignment="Center">
<TextBlock Classes="meta" Text="{loc:Tr settings.repoHint.text}" VerticalAlignment="Center"/>
<Button Classes="btn" Content="{loc:Tr settings.repoHint.link}" Command="{Binding OpenRepoImportCommand}"/>
</StackPanel>
</Border>
<StackPanel Spacing="6">
<TextBlock Classes="section-label" Text="{loc:Tr settings.skills.installedSection}"/>
<TextBlock Classes="meta" Opacity="0.6" TextWrapping="Wrap"
Text="{loc:Tr settings.general.sessionSkillsHint}"/>
<ctl:OperationIndicator Status="{Binding SessionSkills.UpdateOp}"/>
<ItemsControl ItemsSource="{Binding SessionSkills.Skills}">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="settings:SessionSkillRowViewModel">
<Border BorderBrush="{DynamicResource LineBrush}" BorderThickness="1"
CornerRadius="6" Padding="10,8" Margin="0,0,0,8"
Background="{DynamicResource DeepBrush}">
<StackPanel Spacing="4">
<Grid ColumnDefinitions="Auto,*,Auto,Auto">
<CheckBox Grid.Column="0" IsChecked="{Binding IsSelected, Mode=TwoWay}"
VerticalAlignment="Center" Margin="0,0,6,0"/>
<TextBlock Grid.Column="1" Classes="title" Text="{Binding Name}" VerticalAlignment="Center"/>
<Button Grid.Column="2" Classes="btn" Content="{loc:Tr settings.skills.updateButton}"
Margin="0,0,6,0"
Command="{Binding $parent[ItemsControl].((vm:SettingsModalViewModel)DataContext).SessionSkills.UpdateCommand}"
CommandParameter="{Binding SourceUrl}"/>
<Button Grid.Column="3" Classes="btn danger" Content="{loc:Tr settings.skills.removeButton}"
Command="{Binding $parent[ItemsControl].((vm:SettingsModalViewModel)DataContext).SessionSkills.RemoveCommand}"
CommandParameter="{Binding SourceUrl}"/>
</Grid>
<TextBlock Classes="meta" Text="{Binding Description}" TextWrapping="Wrap"
IsVisible="{Binding Description, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
<TextBlock Classes="meta" Opacity="0.6" Text="{Binding PinnedRef}"/>
<TextBlock Classes="path-mono" Text="{Binding SourceUrl}" TextTrimming="PrefixCharacterEllipsis"/>
</StackPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<TextBlock Classes="meta" Opacity="0.6" TextWrapping="Wrap"
Text="{loc:Tr settings.skills.emptyState}"
IsVisible="{Binding SessionSkills.IsEmpty}"/>
</StackPanel>
<Border BorderBrush="{DynamicResource LineBrush}" BorderThickness="0,1,0,0" Margin="0,2,0,0"/>
<StackPanel Spacing="6">
<TextBlock Classes="section-label" Text="{loc:Tr settings.skills.installSection}"/>
<Grid ColumnDefinitions="*,Auto" ColumnSpacing="8">
<TextBox Grid.Column="0" Text="{Binding SessionSkills.InstallUrl, Mode=TwoWay}"
PlaceholderText="{loc:Tr settings.skills.installUrlPlaceholder}"/>
<Button Grid.Column="1" Classes="btn" Content="{loc:Tr settings.skills.installButton}"
Command="{Binding SessionSkills.InstallCommand}"/>
</Grid>
<ctl:OperationIndicator Status="{Binding SessionSkills.InstallOp}"/>
</StackPanel>
<TextBlock Classes="meta" Text="{Binding SessionSkills.StatusMessage}"
IsVisible="{Binding SessionSkills.StatusMessage, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
</StackPanel>
</ScrollViewer>
</TabItem>
<!-- Berichte: standup weekday + weekly-report excluded paths (split out of General). -->
<TabItem Header="{loc:Tr settings.sidebar.categoryReports}">
<ScrollViewer>
<StackPanel Spacing="12" Margin="0,8,0,0">
<Border IsVisible="{Binding !HasLinkedRepo}"
Background="{DynamicResource DeepBrush}" BorderBrush="{DynamicResource LineBrush}"
BorderThickness="1" CornerRadius="6" Padding="10,8">
<StackPanel Orientation="Horizontal" Spacing="8" VerticalAlignment="Center">
<TextBlock Classes="meta" Text="{loc:Tr settings.repoHint.text}" VerticalAlignment="Center"/>
<Button Classes="btn" Content="{loc:Tr settings.repoHint.link}" Command="{Binding OpenRepoImportCommand}"/>
</StackPanel>
</Border>
<StackPanel Spacing="4">
<TextBlock Classes="field-label" Text="{loc:Tr settings.general.standupWeekday}"/>
<ComboBox SelectedIndex="{Binding General.StandupWeekday, Mode=TwoWay}" HorizontalAlignment="Left">
<ComboBoxItem Content="{loc:Tr settings.general.weekdaySunday}"/>
<ComboBoxItem Content="{loc:Tr settings.general.weekdayMonday}"/>
<ComboBoxItem Content="{loc:Tr settings.general.weekdayTuesday}"/>
<ComboBoxItem Content="{loc:Tr settings.general.weekdayWednesday}"/>
<ComboBoxItem Content="{loc:Tr settings.general.weekdayThursday}"/>
<ComboBoxItem Content="{loc:Tr settings.general.weekdayFriday}"/>
<ComboBoxItem Content="{loc:Tr settings.general.weekdaySaturday}"/>
</ComboBox>
</StackPanel>
<StackPanel Spacing="4">
<TextBlock Classes="field-label" Text="{loc:Tr settings.general.reportExcludedPaths}"/>
<TextBox AcceptsReturn="True" MinHeight="60" Text="{Binding General.ReportExcludedPaths, Mode=TwoWay}"/>
</StackPanel>
</StackPanel>
</ScrollViewer>
</TabItem>
<TabItem Header="{loc:Tr settings.onlineInbox.tabHeader}"
IsVisible="{Binding ShowOnlineInbox}">
<ScrollViewer>
<StackPanel Spacing="14" Margin="0,8,0,0">
<!-- Enable toggle + restart hint -->
<StackPanel Spacing="4">
<CheckBox IsChecked="{Binding OnlineInbox.Enabled, Mode=TwoWay}"
Content="{loc:Tr settings.onlineInbox.enabledLabel}"/>
<TextBlock Classes="meta" Text="{loc:Tr settings.onlineInbox.restartHint}"
TextWrapping="Wrap" Opacity="0.6"/>
</StackPanel>
<Border BorderBrush="{DynamicResource LineBrush}" BorderThickness="0,1,0,0" Margin="0,2,0,0"/>
<!-- Auth status section -->
<StackPanel Spacing="8">
<TextBlock Classes="section-label" Text="{loc:Tr settings.onlineInbox.statusSection}"/>
<StackPanel Orientation="Horizontal" Spacing="10" VerticalAlignment="Center"
IsVisible="{Binding OnlineInbox.SignedIn}">
<Border Width="8" Height="8" CornerRadius="4"
Background="{DynamicResource StatusRunningBrush}"/>
<TextBlock Classes="body" VerticalAlignment="Center"
Text="{loc:Tr settings.onlineInbox.signedInStatus}"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Spacing="10" VerticalAlignment="Center"
IsVisible="{Binding !OnlineInbox.SignedIn}">
<Border Width="8" Height="8" CornerRadius="4"
Background="{DynamicResource StatusIdleBrush}"/>
<TextBlock Classes="body" VerticalAlignment="Center"
Text="{loc:Tr settings.onlineInbox.signedOutStatus}"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Spacing="8">
<Button Classes="btn"
Content="{loc:Tr settings.onlineInbox.signInButton}"
Command="{Binding OnlineInbox.SignInCommand}"
IsEnabled="{Binding !OnlineInbox.IsBusy}"
IsVisible="{Binding !OnlineInbox.SignedIn}"/>
<Button Classes="btn danger"
Content="{loc:Tr settings.onlineInbox.signOutButton}"
Command="{Binding OnlineInbox.SignOutCommand}"
IsEnabled="{Binding !OnlineInbox.IsBusy}"
IsVisible="{Binding OnlineInbox.SignedIn}"/>
</StackPanel>
</StackPanel>
<Border BorderBrush="{DynamicResource LineBrush}" BorderThickness="0,1,0,0" Margin="0,2,0,0"/>
<!-- Config fields -->
<StackPanel Spacing="10">
<TextBlock Classes="section-label" Text="{loc:Tr settings.onlineInbox.configSection}"/>
<StackPanel Spacing="4">
<TextBlock Classes="field-label" Text="{loc:Tr settings.onlineInbox.apiBaseUrlLabel}"/>
<TextBox Text="{Binding OnlineInbox.ApiBaseUrl, Mode=TwoWay}"
PlaceholderText="{loc:Tr settings.onlineInbox.apiBaseUrlPlaceholder}"/>
</StackPanel>
<StackPanel Spacing="4">
<TextBlock Classes="field-label" Text="{loc:Tr settings.onlineInbox.authorityLabel}"/>
<TextBox Text="{Binding OnlineInbox.Authority, Mode=TwoWay}"
PlaceholderText="{loc:Tr settings.onlineInbox.authorityPlaceholder}"/>
</StackPanel>
<Grid ColumnDefinitions="*,12,*">
<StackPanel Grid.Column="0" Spacing="4">
<TextBlock Classes="field-label" Text="{loc:Tr settings.onlineInbox.clientIdLabel}"/>
<TextBox Text="{Binding OnlineInbox.ClientId, Mode=TwoWay}"/>
</StackPanel>
<StackPanel Grid.Column="2" Spacing="4">
<TextBlock Classes="field-label" Text="{loc:Tr settings.onlineInbox.scopesLabel}"/>
<TextBox Text="{Binding OnlineInbox.Scopes, Mode=TwoWay}"/>
</StackPanel>
</Grid>
<StackPanel Spacing="4">
<TextBlock Classes="field-label" Text="{loc:Tr settings.onlineInbox.redirectUriLabel}"/>
<TextBox Text="{Binding OnlineInbox.RedirectUri, Mode=TwoWay}"/>
</StackPanel>
<StackPanel Spacing="4">
<TextBlock Classes="field-label" Text="{loc:Tr settings.onlineInbox.pollIntervalLabel}"/>
<NumericUpDown Value="{Binding OnlineInbox.PollIntervalSeconds, Mode=TwoWay, Converter={StaticResource KeepLastNumber}}"
Minimum="10" Maximum="3600" Increment="10" FormatString="0"
HorizontalAlignment="Left" Width="140"/>
</StackPanel>
<Button Classes="btn"
Content="{loc:Tr settings.onlineInbox.saveButton}"
Command="{Binding OnlineInbox.SaveCommand}"
IsEnabled="{Binding !OnlineInbox.IsBusy}"
HorizontalAlignment="Left"/>
</StackPanel>
<TextBlock Classes="meta" Text="{Binding OnlineInbox.StatusMessage}"
IsVisible="{Binding OnlineInbox.StatusMessage, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
</StackPanel>
</ScrollViewer>
</TabItem>
<!-- Ticketsystem: Base-URL + PAT for the Bandel ticket integration. Empty base URL
disables the feature entirely, so this tab intentionally never forces a value. -->
<TabItem Header="{loc:Tr settings.sidebar.categoryTickets}">
<ScrollViewer>
<StackPanel Spacing="14" Margin="0,8,0,0">
<StackPanel Spacing="4">
<TextBlock Classes="field-label" Text="{loc:Tr settings.tickets.baseUrl}"/>
<TextBox Text="{Binding Tickets.ApiBaseUrl, Mode=TwoWay}"/>
<TextBlock Classes="meta" Text="{loc:Tr settings.tickets.baseUrlHint}"
TextWrapping="Wrap" Opacity="0.6"/>
</StackPanel>
<Border BorderBrush="{DynamicResource LineBrush}" BorderThickness="0,1,0,0" Margin="0,2,0,0"/>
<StackPanel Spacing="4">
<TextBlock Classes="field-label" Text="{loc:Tr settings.tickets.token}"/>
<TextBox Text="{Binding Tickets.Token, Mode=TwoWay}"
PasswordChar="•"
PlaceholderText="{Binding Tickets.TokenPlaceholder}"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Spacing="8">
<Button Classes="btn"
Content="{loc:Tr settings.tickets.testConnection}"
Command="{Binding Tickets.TestConnectionCommand}"
IsEnabled="{Binding !Tickets.IsBusy}"/>
<Button Classes="btn danger"
Content="{loc:Tr settings.tickets.clearToken}"
Command="{Binding Tickets.ClearTokenCommand}"
IsEnabled="{Binding !Tickets.IsBusy}"/>
</StackPanel>
<TextBlock Classes="meta" Text="{Binding Tickets.StatusMessage}"
IsVisible="{Binding Tickets.StatusMessage, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
</StackPanel>
</ScrollViewer>
</TabItem>
</TabControl>
</Grid>
</DockPanel>
</ctl:ModalShell>
</Window>