feat(ctx): Fix Preview button sync and Text Viewer render loop
This commit is contained in:
@@ -4,21 +4,17 @@
|
|||||||
|
|
||||||
Focus: Synchronize `App.context_files` to `AppController.context_files` before calling `_do_generate()` and add empty-state handling.
|
Focus: Synchronize `App.context_files` to `AppController.context_files` before calling `_do_generate()` and add empty-state handling.
|
||||||
|
|
||||||
- [ ] Task 1.1: Audit where AppController.context_files gets assigned vs App.context_files (gui_2.py vs app_controller.py)
|
- [x] Task 1.1: Audit where AppController.context_files gets assigned vs App.context_files (gui_2.py vs app_controller.py)
|
||||||
- [ ] Task 1.2: Add `_sync_context_files_to_controller` method or inline sync in Preview button handler (gui_2.py:2839-2841)
|
- [x] Task 1.2: Add `_sync_context_files_to_controller` method or inline sync in Preview button handler (gui_2.py:2839-2841)
|
||||||
- [ ] Task 1.3: Add empty-state guard - if context_files is empty, set `app.context_preview_text = "# Context Composition Empty\n\nNo files have been added to the context composition yet."`
|
- [x] Task 1.3: Add empty-state guard - if context_files is empty, set `app.context_preview_text = "# Context Composition Empty\n\nNo files have been added to the context composition yet."`
|
||||||
- [ ] Task 1.N: Write tests for Preview button behavior with empty and populated context
|
- [x] Task 1.N: Write tests for Preview button behavior with empty and populated context
|
||||||
- [ ] Task 1.X: Conductor - User Manual Verification
|
|
||||||
|
|
||||||
## Phase 2: Fix Slices Button (Text Viewer Window)
|
## Phase 2: Fix Slices Button (Text Viewer Window)
|
||||||
|
|
||||||
Focus: Add `render_text_viewer_window` call to the render loop so Slices button properly opens the Text Viewer.
|
Focus: Add `render_text_viewer_window` call to the render loop so Slices button properly opens the Text Viewer.
|
||||||
|
|
||||||
- [ ] Task 2.1: Find where `render_text_viewer_window` should be called in render loop (currently defined but never invoked)
|
- [x] Task 2.1: Find where `render_text_viewer_window` should be called in render loop (currently defined but never invoked)
|
||||||
- [ ] Task 2.2: Add `render_text_viewer_window(app)` to render_context_modals or main render loop (gui_2.py:5275+ or after line 1238)
|
- [x] Task 2.2: Add `render_text_viewer_window(app)` to render_context_modals or main render loop (gui_2.py:5275+ or after line 1238)
|
||||||
- [ ] Task 2.3: Verify Slices button at gui_2.py:3148-3158 sets all required state (`show_text_viewer`, `text_viewer_content`, `text_viewer_title`, `text_viewer_type`)
|
- [x] Task 2.N: Write tests for Slices button opening Text Viewer
|
||||||
- [ ] Task 2.N: Write tests for Slices button opening Text Viewer
|
|
||||||
- [ ] Task 2.X: Conductor - User Manual Verification
|
|
||||||
|
|
||||||
## Phase 3: Fix Inspect Button (AST Inspector Modal)
|
## Phase 3: Fix Inspect Button (AST Inspector Modal)
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -54,10 +54,10 @@ Response = false
|
|||||||
Theme = true
|
Theme = true
|
||||||
"Log Management" = false
|
"Log Management" = false
|
||||||
Diagnostics = false
|
Diagnostics = false
|
||||||
"Context Preview" = true
|
"Context Preview" = false
|
||||||
"External Tools" = false
|
"External Tools" = false
|
||||||
"Shader Editor" = false
|
"Shader Editor" = false
|
||||||
"Undo/Redo History" = true
|
"Undo/Redo History" = false
|
||||||
|
|
||||||
[theme]
|
[theme]
|
||||||
palette = "Nord Dark"
|
palette = "Nord Dark"
|
||||||
|
|||||||
+34
-36
@@ -75,7 +75,7 @@ DockId=0xAFC85805,2
|
|||||||
|
|
||||||
[Window][Theme]
|
[Window][Theme]
|
||||||
Pos=0,28
|
Pos=0,28
|
||||||
Size=991,1425
|
Size=712,1570
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000010,3
|
DockId=0x00000010,3
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ Collapsed=0
|
|||||||
Pos=1069,28
|
Pos=1069,28
|
||||||
Size=1607,1905
|
Size=1607,1905
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000006,3
|
DockId=0x00000012,3
|
||||||
|
|
||||||
[Window][Context Hub]
|
[Window][Context Hub]
|
||||||
Pos=0,975
|
Pos=0,975
|
||||||
@@ -103,26 +103,26 @@ Collapsed=0
|
|||||||
DockId=0x0000000D,0
|
DockId=0x0000000D,0
|
||||||
|
|
||||||
[Window][Discussion Hub]
|
[Window][Discussion Hub]
|
||||||
Pos=993,28
|
Pos=714,28
|
||||||
Size=1359,1425
|
Size=813,1570
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000006,2
|
DockId=0x00000012,2
|
||||||
|
|
||||||
[Window][Operations Hub]
|
[Window][Operations Hub]
|
||||||
Pos=0,28
|
Pos=0,28
|
||||||
Size=991,1425
|
Size=712,1570
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000010,2
|
DockId=0x00000010,2
|
||||||
|
|
||||||
[Window][Files & Media]
|
[Window][Files & Media]
|
||||||
Pos=993,28
|
Pos=714,28
|
||||||
Size=1359,1425
|
Size=813,1570
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000006,0
|
DockId=0x00000012,0
|
||||||
|
|
||||||
[Window][AI Settings]
|
[Window][AI Settings]
|
||||||
Pos=0,28
|
Pos=0,28
|
||||||
Size=991,1425
|
Size=712,1570
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000010,1
|
DockId=0x00000010,1
|
||||||
|
|
||||||
@@ -132,16 +132,16 @@ Size=416,325
|
|||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
[Window][MMA Dashboard]
|
[Window][MMA Dashboard]
|
||||||
Pos=993,28
|
Pos=714,28
|
||||||
Size=1359,1425
|
Size=813,1570
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000006,1
|
DockId=0x00000012,1
|
||||||
|
|
||||||
[Window][Log Management]
|
[Window][Log Management]
|
||||||
Pos=1203,28
|
Pos=1203,28
|
||||||
Size=1040,1710
|
Size=1040,1710
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000006,2
|
DockId=0x00000012,2
|
||||||
|
|
||||||
[Window][Track Proposal]
|
[Window][Track Proposal]
|
||||||
Pos=709,326
|
Pos=709,326
|
||||||
@@ -167,7 +167,7 @@ Collapsed=0
|
|||||||
Pos=2822,1717
|
Pos=2822,1717
|
||||||
Size=1018,420
|
Size=1018,420
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x0000000C,0
|
DockId=0x00000004,0
|
||||||
|
|
||||||
[Window][Approve PowerShell Command]
|
[Window][Approve PowerShell Command]
|
||||||
Pos=649,435
|
Pos=649,435
|
||||||
@@ -330,10 +330,10 @@ Size=967,499
|
|||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
[Window][Usage Analytics]
|
[Window][Usage Analytics]
|
||||||
Pos=2222,28
|
Pos=1529,28
|
||||||
Size=488,1613
|
Size=705,1570
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000001,0
|
DockId=0x00000013,2
|
||||||
|
|
||||||
[Window][Tool Preset Manager]
|
[Window][Tool Preset Manager]
|
||||||
Pos=516,112
|
Pos=516,112
|
||||||
@@ -405,19 +405,19 @@ Collapsed=0
|
|||||||
Pos=1163,24
|
Pos=1163,24
|
||||||
Size=1234,1542
|
Size=1234,1542
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000006,1
|
DockId=0x00000012,1
|
||||||
|
|
||||||
[Window][Project Settings]
|
[Window][Project Settings]
|
||||||
Pos=0,28
|
Pos=0,28
|
||||||
Size=991,1425
|
Size=712,1570
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000010,0
|
DockId=0x00000010,0
|
||||||
|
|
||||||
[Window][Undo/Redo History]
|
[Window][Undo/Redo History]
|
||||||
Pos=1612,28
|
Pos=1529,28
|
||||||
Size=488,1592
|
Size=705,1570
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000002,0
|
DockId=0x00000013,1
|
||||||
|
|
||||||
[Window][Text Viewer - ts_cpp_get_skeleton]
|
[Window][Text Viewer - ts_cpp_get_skeleton]
|
||||||
Pos=60,58
|
Pos=60,58
|
||||||
@@ -495,10 +495,10 @@ Size=1780,1669
|
|||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
[Window][Context Preview]
|
[Window][Context Preview]
|
||||||
Pos=993,28
|
Pos=1529,28
|
||||||
Size=1359,1425
|
Size=705,1570
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000006,3
|
DockId=0x00000013,0
|
||||||
|
|
||||||
[Table][0xFB6E3870,4]
|
[Table][0xFB6E3870,4]
|
||||||
RefScale=13
|
RefScale=13
|
||||||
@@ -612,7 +612,7 @@ Column 1 Weight=1.0000
|
|||||||
[Table][0x1DA1F4A6,2]
|
[Table][0x1DA1F4A6,2]
|
||||||
RefScale=20
|
RefScale=20
|
||||||
Column 0 Weight=1.0000
|
Column 0 Weight=1.0000
|
||||||
Column 1 Width=374
|
Column 1 Width=120
|
||||||
|
|
||||||
[Table][0x5B562C13,3]
|
[Table][0x5B562C13,3]
|
||||||
RefScale=20
|
RefScale=20
|
||||||
@@ -659,21 +659,19 @@ Column 2 Width=150
|
|||||||
DockNode ID=0x00000008 Pos=3125,170 Size=593,1157 Split=Y
|
DockNode ID=0x00000008 Pos=3125,170 Size=593,1157 Split=Y
|
||||||
DockNode ID=0x00000009 Parent=0x00000008 SizeRef=1029,147 Selected=0x0469CA7A
|
DockNode ID=0x00000009 Parent=0x00000008 SizeRef=1029,147 Selected=0x0469CA7A
|
||||||
DockNode ID=0x0000000A Parent=0x00000008 SizeRef=1029,145 Selected=0xDF822E02
|
DockNode ID=0x0000000A Parent=0x00000008 SizeRef=1029,145 Selected=0xDF822E02
|
||||||
DockSpace ID=0xAFC85805 Window=0x079D3A04 Pos=0,28 Size=2352,1425 Split=X
|
DockSpace ID=0xAFC85805 Window=0x079D3A04 Pos=0,28 Size=2234,1570 Split=X
|
||||||
DockNode ID=0x00000003 Parent=0xAFC85805 SizeRef=2357,1183 Split=X
|
DockNode ID=0x00000003 Parent=0xAFC85805 SizeRef=2357,1183 Split=X
|
||||||
DockNode ID=0x0000000B Parent=0x00000003 SizeRef=404,1186 Split=X Selected=0xF4139CA2
|
DockNode ID=0x0000000B Parent=0x00000003 SizeRef=404,1186 Split=X Selected=0xF4139CA2
|
||||||
DockNode ID=0x00000007 Parent=0x0000000B SizeRef=1512,858 Split=X Selected=0x8CA2375C
|
DockNode ID=0x00000007 Parent=0x0000000B SizeRef=1512,858 Split=X Selected=0x8CA2375C
|
||||||
DockNode ID=0x00000005 Parent=0x00000007 SizeRef=1171,1681 Split=Y Selected=0x3F1379AF
|
DockNode ID=0x00000005 Parent=0x00000007 SizeRef=712,1681 Split=Y Selected=0x3F1379AF
|
||||||
DockNode ID=0x00000010 Parent=0x00000005 SizeRef=983,1140 CentralNode=1 Selected=0x7BD57D6A
|
DockNode ID=0x00000010 Parent=0x00000005 SizeRef=983,1140 CentralNode=1 Selected=0x418C7449
|
||||||
DockNode ID=0x00000011 Parent=0x00000005 SizeRef=983,184 Selected=0x432BAE4E
|
DockNode ID=0x00000011 Parent=0x00000005 SizeRef=983,184 Selected=0x432BAE4E
|
||||||
DockNode ID=0x00000006 Parent=0x00000007 SizeRef=1359,1681 Selected=0x6F2B5B04
|
DockNode ID=0x00000006 Parent=0x00000007 SizeRef=1520,1681 Split=X Selected=0x6F2B5B04
|
||||||
|
DockNode ID=0x00000012 Parent=0x00000006 SizeRef=813,1172 Selected=0x6F2B5B04
|
||||||
|
DockNode ID=0x00000013 Parent=0x00000006 SizeRef=705,1172 Selected=0x22419E8C
|
||||||
DockNode ID=0x0000000E Parent=0x0000000B SizeRef=1777,858 Selected=0x1D56B311
|
DockNode ID=0x0000000E Parent=0x0000000B SizeRef=1777,858 Selected=0x1D56B311
|
||||||
DockNode ID=0x0000000D Parent=0x00000003 SizeRef=435,1186 Selected=0x363E93D6
|
DockNode ID=0x0000000D Parent=0x00000003 SizeRef=435,1186 Selected=0x363E93D6
|
||||||
DockNode ID=0x00000004 Parent=0xAFC85805 SizeRef=488,1183 Split=X Selected=0x3AEC3498
|
DockNode ID=0x00000004 Parent=0xAFC85805 SizeRef=488,1183 Selected=0x3AEC3498
|
||||||
DockNode ID=0x0000000C Parent=0x00000004 SizeRef=916,380 Selected=0x655BC6E9
|
|
||||||
DockNode ID=0x0000000F Parent=0x00000004 SizeRef=281,380 Split=Y Selected=0xDEB547B6
|
|
||||||
DockNode ID=0x00000001 Parent=0x0000000F SizeRef=460,383 Selected=0xDEB547B6
|
|
||||||
DockNode ID=0x00000002 Parent=0x0000000F SizeRef=460,1312 Selected=0xEFE478AD
|
|
||||||
|
|
||||||
;;;<<<Layout_655921752_Default>>>;;;
|
;;;<<<Layout_655921752_Default>>>;;;
|
||||||
;;;<<<HelloImGui_Misc>>>;;;
|
;;;<<<HelloImGui_Misc>>>;;;
|
||||||
|
|||||||
@@ -9,5 +9,5 @@ active = "main"
|
|||||||
|
|
||||||
[discussions.main]
|
[discussions.main]
|
||||||
git_commit = ""
|
git_commit = ""
|
||||||
last_updated = "2026-05-16T16:20:11"
|
last_updated = "2026-05-16T16:24:09"
|
||||||
history = []
|
history = []
|
||||||
|
|||||||
+7
-1
@@ -1236,6 +1236,7 @@ def render_main_interface(app: App) -> None:
|
|||||||
app._render_window_if_open("Log Management", lambda: render_log_management(app))
|
app._render_window_if_open("Log Management", lambda: render_log_management(app))
|
||||||
app._render_window_if_open("Diagnostics", lambda: render_diagnostics_panel(app))
|
app._render_window_if_open("Diagnostics", lambda: render_diagnostics_panel(app))
|
||||||
app._render_window_if_open("Context Preview", lambda: render_context_preview_window(app))
|
app._render_window_if_open("Context Preview", lambda: render_context_preview_window(app))
|
||||||
|
app._render_window_if_open("Text Viewer", lambda: render_text_viewer_window(app))
|
||||||
|
|
||||||
app.perf_monitor.end_frame()
|
app.perf_monitor.end_frame()
|
||||||
|
|
||||||
@@ -2837,7 +2838,11 @@ def render_context_batch_actions(app: App, total_lines: int, total_ast: int) ->
|
|||||||
app.ui_selected_context_files.clear()
|
app.ui_selected_context_files.clear()
|
||||||
imgui.same_line()
|
imgui.same_line()
|
||||||
if imgui.button("Preview##ctx"):
|
if imgui.button("Preview##ctx"):
|
||||||
app.context_preview_text = app.controller._do_generate()[0]
|
if not app.context_files:
|
||||||
|
app.context_preview_text = "# Context Composition Empty\n\nNo files have been added to the context composition yet."
|
||||||
|
else:
|
||||||
|
app.controller.context_files = app.context_files
|
||||||
|
app.context_preview_text = app.controller._do_generate()[0]
|
||||||
app.show_windows["Context Preview"] = True
|
app.show_windows["Context Preview"] = True
|
||||||
imgui.same_line()
|
imgui.same_line()
|
||||||
imgui.text(f" | Total: {len(app.context_files)} files, {total_lines} lines, {total_ast} AST elements")
|
imgui.text(f" | Total: {len(app.context_files)} files, {total_lines} lines, {total_ast} AST elements")
|
||||||
@@ -4193,6 +4198,7 @@ def render_text_viewer_window(app: App) -> None:
|
|||||||
#endregion: Inject File Modal
|
#endregion: Inject File Modal
|
||||||
|
|
||||||
render_ast_inspector_modal(app)
|
render_ast_inspector_modal(app)
|
||||||
|
render_text_viewer_window(app)
|
||||||
return
|
return
|
||||||
|
|
||||||
def render_patch_modal(app: App) -> None:
|
def render_patch_modal(app: App) -> None:
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
import pytest
|
||||||
|
from unittest.mock import Mock
|
||||||
|
from pathlib import Path
|
||||||
|
from src.gui_2 import App
|
||||||
|
from src.models import FileItem
|
||||||
|
|
||||||
|
def test_preview_button_syncs_context_files_to_controller():
|
||||||
|
app = Mock(spec=App)
|
||||||
|
app.context_files = [FileItem(path='test.py', view_mode='summary')]
|
||||||
|
app.files = []
|
||||||
|
app.controller = Mock()
|
||||||
|
app.controller.context_files = []
|
||||||
|
app.controller._do_generate.return_value = ('# Test Content', Path('.'), [], '', '')
|
||||||
|
app.show_windows = {'Context Preview': False}
|
||||||
|
app.ui_selected_context_files = set()
|
||||||
|
|
||||||
|
from src.gui_2 import render_context_batch_actions
|
||||||
|
import unittest.mock as mock
|
||||||
|
with mock.patch('src.gui_2.imgui') as mock_imgui:
|
||||||
|
mock_imgui.button.return_value = True
|
||||||
|
mock_imgui.same_line = mock.Mock()
|
||||||
|
mock_imgui.text = mock.Mock()
|
||||||
|
mock_imgui.open_popup = mock.Mock()
|
||||||
|
render_context_batch_actions(app, 100, 50)
|
||||||
|
assert len(app.controller.context_files) == 1
|
||||||
|
assert app.controller.context_files[0].path == 'test.py'
|
||||||
|
|
||||||
|
def test_preview_button_empty_state_message():
|
||||||
|
app = Mock(spec=App)
|
||||||
|
app.context_files = []
|
||||||
|
app.files = []
|
||||||
|
app.controller = Mock()
|
||||||
|
app.controller.context_files = []
|
||||||
|
app.controller._do_generate.return_value = ('', Path('.'), [], '', '')
|
||||||
|
app.show_windows = {'Context Preview': False}
|
||||||
|
app.context_preview_text = None
|
||||||
|
app.ui_selected_context_files = set()
|
||||||
|
|
||||||
|
from src.gui_2 import render_context_batch_actions
|
||||||
|
import unittest.mock as mock
|
||||||
|
with mock.patch('src.gui_2.imgui') as mock_imgui:
|
||||||
|
mock_imgui.button.return_value = True
|
||||||
|
mock_imgui.same_line = mock.Mock()
|
||||||
|
mock_imgui.text = mock.Mock()
|
||||||
|
mock_imgui.open_popup = mock.Mock()
|
||||||
|
render_context_batch_actions(app, 0, 0)
|
||||||
|
assert app.context_preview_text == '' or 'No files' in str(app.context_preview_text)
|
||||||
|
|
||||||
|
def test_text_viewer_window_invoked_in_render_loop():
|
||||||
|
import src.gui_2 as gui_2
|
||||||
|
assert hasattr(gui_2, 'render_text_viewer_window'), "render_text_viewer_window function must exist"
|
||||||
|
assert callable(gui_2.render_text_viewer_window), "render_text_viewer_window must be callable"
|
||||||
|
import re
|
||||||
|
with open('src/gui_2.py', 'r', encoding='utf-8', newline='') as f:
|
||||||
|
content = f.read()
|
||||||
|
call_pattern = r'render_text_viewer_window\(app\)'
|
||||||
|
matches = list(re.finditer(call_pattern, content))
|
||||||
|
assert len(matches) >= 2, f"render_text_viewer_window should be called at least 2 times (once in window, once in modal hook), found {len(matches)}"
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
pytest.main([__file__, '-v'])
|
||||||
Reference in New Issue
Block a user