Files
ClaudeDo/src/ClaudeDo.Ui/Views/Modals/SettingsModalView.axaml
T
Mika Kuns fde9615b34 feat(settings): per-model effort and turn presets
ClaudeDo never passed --effort, so every session inherited whatever effortLevel
the user's Claude Code config happened to carry. Settings -> General now holds one
row per model alias (haiku medium/20, sonnet high/30, opus high/40, fable high/25)
supplying the global effort and turn defaults; list- and task-level max-turns
overrides still win, and the agent editor's inherited badge follows the model.

--effort is applied to autonomous runs and to every ConPTY spec (task session,
planning start/resume, ad-hoc, list handler). The model itself is deliberately not
forced on interactive sessions. The single global 'Max turns' field is replaced by
the table, and 'fable' joins ModelRegistry.Aliases.

The migration also adds the is_manual columns used by the next commit.
2026-07-27 15:02:51 +02:00

453 lines
29 KiB
XML

<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: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="580" Height="760" MinWidth="480" 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: tabs + 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>
<TabControl Padding="20,16" TabStripPlacement="Top">
<TabItem Header="{loc:Tr settings.tabGeneral}">
<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.defaultInstructions}"/>
<TextBox AcceptsReturn="True" TextWrapping="Wrap" Height="110"
PlaceholderText="{loc:Tr settings.general.defaultInstructionsPlaceholder}"
Text="{Binding General.DefaultClaudeInstructions, Mode=TwoWay}"/>
</StackPanel>
<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">
<Grid ColumnDefinitions="90,12,*,12,110" Margin="0,0,0,6">
<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}"
Minimum="1" Maximum="200" Increment="1" FormatString="0"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
<StackPanel Spacing="4">
<TextBlock Classes="field-label" Text="{loc:Tr settings.general.maxParallelExecutions}"/>
<NumericUpDown Value="{Binding General.MaxParallelExecutions, Mode=TwoWay}"
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.reportExcludedPaths}"/>
<TextBox AcceptsReturn="True" MinHeight="60" Text="{Binding General.ReportExcludedPaths, Mode=TwoWay}"/>
</StackPanel>
<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.sessionSkills}"/>
<TextBlock Classes="meta" Opacity="0.6" TextWrapping="Wrap"
Text="{loc:Tr settings.general.sessionSkillsHint}"/>
<ItemsControl ItemsSource="{Binding General.SessionSkills}">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="agent:SelectableSkillViewModel">
<CheckBox IsChecked="{Binding IsSelected, Mode=TwoWay}" Content="{Binding Name}"
ToolTip.Tip="{Binding Description}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</StackPanel>
</ScrollViewer>
</TabItem>
<TabItem Header="{loc:Tr settings.tabWorktrees}">
<ScrollViewer>
<StackPanel Spacing="12" Margin="0,8,0,0">
<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}"
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>
<Button Content="{loc:Tr settings.worktrees.forceRemoveAll}" Classes="danger"
Command="{Binding Worktrees.RequestResetConfirmCommand}"
HorizontalAlignment="Left"
IsVisible="{Binding !Worktrees.ShowResetConfirm}"/>
<Border Classes="danger-box"
IsVisible="{Binding Worktrees.ShowResetConfirm}">
<StackPanel Spacing="8">
<TextBlock Text="{loc:Tr settings.worktrees.confirmRemoveAll}"
Foreground="{DynamicResource TextBrush}" TextWrapping="Wrap"/>
<StackPanel Orientation="Horizontal" Spacing="8">
<Button Classes="btn" Content="{loc:Tr settings.cancel}" Command="{Binding Worktrees.CancelResetConfirmCommand}"/>
<Button Content="{loc:Tr settings.worktrees.removeAll}" Classes="danger"
Command="{Binding Worktrees.ConfirmResetAllCommand}"/>
</StackPanel>
</StackPanel>
</Border>
</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.tabFiles}">
<ScrollViewer>
<StackPanel Spacing="12" Margin="0,8,0,0">
<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}"
IsEnabled="{Binding !Files.IsBusy}"
HorizontalAlignment="Left"/>
</StackPanel>
<StackPanel Spacing="6">
<TextBlock Classes="section-label" Text="{loc:Tr settings.files.promptsSection}"/>
<Grid RowDefinitions="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.openInEditor}"
Command="{Binding Files.OpenPromptCommand}" 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.openInEditor}"
Command="{Binding Files.OpenPromptCommand}" 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.openInEditor}"
Command="{Binding Files.OpenPromptCommand}" 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.openInEditor}"
Command="{Binding Files.OpenPromptCommand}" 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.openInEditor}"
Command="{Binding Files.OpenPromptCommand}" 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.openInEditor}"
Command="{Binding Files.OpenPromptCommand}" CommandParameter="WeeklyReport"/>
</Grid>
</StackPanel>
<TextBlock Classes="meta" Text="{Binding Files.StatusMessage}"
IsVisible="{Binding Files.StatusMessage, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
</StackPanel>
</ScrollViewer>
</TabItem>
<TabItem Header="{loc:Tr settings.tabPrime}">
<ScrollViewer>
<StackPanel Spacing="12" Margin="0,8,0,0">
<TextBlock Classes="meta" TextWrapping="Wrap"
Text="{loc:Tr settings.prime.description}"/>
<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}">
<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"
MinWidth="80"/>
<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>
</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"
Value="{Binding Prime.DailyPrepMaxTasks, Mode=TwoWay}"/>
</StackPanel>
</StackPanel>
</ScrollViewer>
</TabItem>
<TabItem Header="{loc:Tr settings.onlineInbox.tabHeader}">
<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}"
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>
<TabItem Header="{loc:Tr settings.tabSkills}">
<ScrollViewer>
<StackPanel Spacing="12" Margin="0,8,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}"
IsEnabled="{Binding !SessionSkills.IsBusy}"/>
</Grid>
</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.installedSection}"/>
<ItemsControl ItemsSource="{Binding SessionSkills.Skills}">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="services:SessionSkillDto">
<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">
<TextBlock Grid.Column="0" Classes="title" Text="{Binding Name}"/>
<Button Grid.Column="1" 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="2" 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>
<TextBlock Classes="meta" Text="{Binding SessionSkills.StatusMessage}"
IsVisible="{Binding SessionSkills.StatusMessage, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
</StackPanel>
</ScrollViewer>
</TabItem>
</TabControl>
</DockPanel>
</ctl:ModalShell>
</Window>