| 1 | <UserControl xmlns="https://github.com/avaloniaui" |
| 2 | xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
| 3 | xmlns:vm="using:CascadeIDE.ViewModels" |
| 4 | xmlns:views="using:CascadeIDE.Views" |
| 5 | xmlns:awv="clr-namespace:Avalonia.Controls;assembly=Avalonia.Controls.WebView" |
| 6 | x:Class="CascadeIDE.Views.WebAiPortalMfdPageView" |
| 7 | x:DataType="vm:MainWindowViewModel"> |
| 8 | <DockPanel Margin="0,4,0,0"> |
| 9 | <views:PanelChromeHeader DockPanel.Dock="Top" |
| 10 | Title="WEB AI · portal / bridge (ADR 0108)" |
| 11 | UppercaseTitle="True"/> |
| 12 | |
| 13 | <!-- По умолчанию свёрнуто: под WebView уходит почти вся высота MFD (ADR 0108). --> |
| 14 | <Grid RowDefinitions="Auto,*" |
| 15 | RowSpacing="6" |
| 16 | Margin="0,8,0,0"> |
| 17 | |
| 18 | <Expander Grid.Row="0" |
| 19 | IsExpanded="False" |
| 20 | ExpandDirection="Down" |
| 21 | HorizontalAlignment="Stretch"> |
| 22 | <Expander.Header> |
| 23 | <DockPanel LastChildFill="True" Margin="0,2,0,0"> |
| 24 | <Button DockPanel.Dock="Right" |
| 25 | Content="Отозвать" |
| 26 | MinWidth="84" |
| 27 | Margin="8,0,0,0" |
| 28 | Click="OnRevokeBridgeClick" |
| 29 | ToolTip.Tip="Сбросить согласие и выключить мост."/> |
| 30 | <Button DockPanel.Dock="Right" |
| 31 | Content="Запуск" |
| 32 | MinWidth="88" |
| 33 | Margin="8,0,0,0" |
| 34 | Click="OnExecuteJsonCascadeFromClipboardClick" |
| 35 | ToolTip.Tip="Выполнить команду из буфера или последнюю json-cascade на странице."/> |
| 36 | <Button DockPanel.Dock="Right" |
| 37 | AutomationProperties.Name="Перейти" |
| 38 | Margin="8,0,0,0" |
| 39 | MinWidth="36" |
| 40 | Padding="8,4" |
| 41 | Click="OnNavigateClick" |
| 42 | ToolTip.Tip="Перейти (Enter)"> |
| 43 | <TextBlock Text="⇨" |
| 44 | FontSize="16" |
| 45 | VerticalAlignment="Center" |
| 46 | HorizontalAlignment="Center"/> |
| 47 | </Button> |
| 48 | <TextBox MinHeight="28" |
| 49 | PlaceholderText="example.com или https://…" |
| 50 | ToolTip.Tip="Без схемы подставится https:// (для localhost и 127.0.0.1 — http://). Enter — перейти." |
| 51 | KeyDown="OnWebAiPortalUrlKeyDown" |
| 52 | Text="{Binding WebAiPortalUrlText, Mode=TwoWay}"/> |
| 53 | </DockPanel> |
| 54 | </Expander.Header> |
| 55 | <Border Padding="8" |
| 56 | Background="#22000000" |
| 57 | CornerRadius="4"> |
| 58 | <Grid ColumnDefinitions="Auto,*,Auto,Auto" |
| 59 | ColumnSpacing="10" |
| 60 | RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto" |
| 61 | RowSpacing="6"> |
| 62 | <CheckBox Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" |
| 63 | Content="Принял политику моста" |
| 64 | IsChecked="{Binding WebAiPortalBridge.BridgeConsented, Mode=TwoWay}"/> |
| 65 | <CheckBox Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" |
| 66 | Content="Мост включён (invokeCSharpAction)" |
| 67 | IsChecked="{Binding WebAiPortalBridge.BridgeArmed, Mode=TwoWay}"/> |
| 68 | <CheckBox Grid.Row="1" Grid.Column="2" Grid.ColumnSpan="2" |
| 69 | Content="Все write на сессию" |
| 70 | IsChecked="{Binding WebAiPortalBridge.AllowWritesForSession, Mode=TwoWay}"/> |
| 71 | |
| 72 | <CheckBox Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" |
| 73 | Content="Ответ IDE → буфер" |
| 74 | IsChecked="{Binding WebAiPortalCopyFullBridgeResultToClipboard, Mode=TwoWay}" |
| 75 | ToolTip.Tip="После моста текст в системный буфер. Если включён «Под лимит чата» и ответ длинный — вместо сырого JSON кладётся компакт с HCI." /> |
| 76 | <CheckBox Grid.Row="2" Grid.Column="2" Grid.ColumnSpan="2" |
| 77 | Content="Подмешать в композитор (фокус на странице)" |
| 78 | IsChecked="{Binding WebAiPortalTryInjectResultIntoFocusedComposer, Mode=TwoWay}" |
| 79 | ToolTip.Tip="Курсор в поле ввода чата на странице; после ответа моста текст добавляется как эвристика (может не сработать на каждой вёрстке)."/> |
| 80 | |
| 81 | <CheckBox Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="4" |
| 82 | Content="Под лимит чата (~1200): компакт + HCI вместо сырого JSON" |
| 83 | IsChecked="{Binding WebAiPortalPreferCompactComposerForChat, Mode=TwoWay}" |
| 84 | ToolTip.Tip="Ответы типа get_editor_state с большим превью ломают веб-чат. В буфер/композитор — короткая сводка и готовые json-cascade (codebase_index_search, codebase_index_status, explain, узкий read)." /> |
| 85 | |
| 86 | <CheckBox Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="4" |
| 87 | Content="Авто: последняя json-cascade на странице → мост (poll, без кнопки)" |
| 88 | IsChecked="{Binding WebAiPortalAutoDomBridgePolling, Mode=TwoWay}" |
| 89 | ToolTip.Tip="Раз в ~1 с IDE находит последний блок ```json-cascade с command_id в DOM и выполняет его (буфер/копипаст не нужны). Повтор того же payload не запускает мост заново до смены страницы. Отправить результат в поле чата сайта пользователь делает там (или «Подмешать в композитор»)." /> |
| 90 | |
| 91 | <Button Grid.Row="5" |
| 92 | Grid.Column="0" |
| 93 | Grid.ColumnSpan="4" |
| 94 | HorizontalAlignment="Stretch" |
| 95 | HorizontalContentAlignment="Center" |
| 96 | Content="Выполнить команду: буфер → последняя на странице" |
| 97 | Click="OnExecuteJsonCascadeFromClipboardClick" |
| 98 | ToolTip.Tip="Ручной вариант ADR 0108: 1) fenced json-cascade или голый JSON с command_id в буфере; 2) иначе последний такой блок в pre/code на открытой странице (снизу в DOM)." /> |
| 99 | </Grid> |
| 100 | </Border> |
| 101 | </Expander> |
| 102 | |
| 103 | <Grid Grid.Row="1" MinHeight="180"> |
| 104 | <awv:NativeWebView x:Name="WebView" |
| 105 | NavigationCompleted="OnNavigationCompletedWeb" |
| 106 | WebMessageReceived="OnWebMessageReceived"/> |
| 107 | <!-- Не резервируем отдельную строку под статус; не перехватываем клики по странице. --> |
| 108 | <Border VerticalAlignment="Bottom" |
| 109 | HorizontalAlignment="Stretch" |
| 110 | Margin="0,0,0,4" |
| 111 | Padding="8,4" |
| 112 | Background="#D9000000" |
| 113 | CornerRadius="4" |
| 114 | IsHitTestVisible="False"> |
| 115 | <TextBlock Text="{Binding WebAiPortalLastBridgeResult}" |
| 116 | TextWrapping="Wrap" |
| 117 | MaxHeight="48" |
| 118 | FontSize="11" |
| 119 | Opacity="0.95"/> |
| 120 | </Border> |
| 121 | </Grid> |
| 122 | </Grid> |
| 123 | </DockPanel> |
| 124 | </UserControl> |
| 125 | |