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.
|
||||
|
||||
- [ ] 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)
|
||||
- [ ] 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
|
||||
- [ ] Task 1.X: Conductor - User Manual Verification
|
||||
|
||||
- [x] Task 1.1: Audit where AppController.context_files gets assigned vs App.context_files (gui_2.py vs app_controller.py)
|
||||
- [x] 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.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.N: Write tests for Preview button behavior with empty and populated context
|
||||
## 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.
|
||||
|
||||
- [ ] 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)
|
||||
- [ ] 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`)
|
||||
- [ ] Task 2.N: Write tests for Slices button opening Text Viewer
|
||||
- [ ] Task 2.X: Conductor - User Manual Verification
|
||||
- [x] Task 2.1: Find where `render_text_viewer_window` should be called in render loop (currently defined but never invoked)
|
||||
- [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)
|
||||
- [x] Task 2.N: Write tests for Slices button opening Text Viewer
|
||||
|
||||
## Phase 3: Fix Inspect Button (AST Inspector Modal)
|
||||
|
||||
|
||||
+2
-2
@@ -54,10 +54,10 @@ Response = false
|
||||
Theme = true
|
||||
"Log Management" = false
|
||||
Diagnostics = false
|
||||
"Context Preview" = true
|
||||
"Context Preview" = false
|
||||
"External Tools" = false
|
||||
"Shader Editor" = false
|
||||
"Undo/Redo History" = true
|
||||
"Undo/Redo History" = false
|
||||
|
||||
[theme]
|
||||
palette = "Nord Dark"
|
||||
|
||||
+34
-36
@@ -75,7 +75,7 @@ DockId=0xAFC85805,2
|
||||
|
||||
[Window][Theme]
|
||||
Pos=0,28
|
||||
Size=991,1425
|
||||
Size=712,1570
|
||||
Collapsed=0
|
||||
DockId=0x00000010,3
|
||||
|
||||
@@ -88,7 +88,7 @@ Collapsed=0
|
||||
Pos=1069,28
|
||||
Size=1607,1905
|
||||
Collapsed=0
|
||||
DockId=0x00000006,3
|
||||
DockId=0x00000012,3
|
||||
|
||||
[Window][Context Hub]
|
||||
Pos=0,975
|
||||
@@ -103,26 +103,26 @@ Collapsed=0
|
||||
DockId=0x0000000D,0
|
||||
|
||||
[Window][Discussion Hub]
|
||||
Pos=993,28
|
||||
Size=1359,1425
|
||||
Pos=714,28
|
||||
Size=813,1570
|
||||
Collapsed=0
|
||||
DockId=0x00000006,2
|
||||
DockId=0x00000012,2
|
||||
|
||||
[Window][Operations Hub]
|
||||
Pos=0,28
|
||||
Size=991,1425
|
||||
Size=712,1570
|
||||
Collapsed=0
|
||||
DockId=0x00000010,2
|
||||
|
||||
[Window][Files & Media]
|
||||
Pos=993,28
|
||||
Size=1359,1425
|
||||
Pos=714,28
|
||||
Size=813,1570
|
||||
Collapsed=0
|
||||
DockId=0x00000006,0
|
||||
DockId=0x00000012,0
|
||||
|
||||
[Window][AI Settings]
|
||||
Pos=0,28
|
||||
Size=991,1425
|
||||
Size=712,1570
|
||||
Collapsed=0
|
||||
DockId=0x00000010,1
|
||||
|
||||
@@ -132,16 +132,16 @@ Size=416,325
|
||||
Collapsed=0
|
||||
|
||||
[Window][MMA Dashboard]
|
||||
Pos=993,28
|
||||
Size=1359,1425
|
||||
Pos=714,28
|
||||
Size=813,1570
|
||||
Collapsed=0
|
||||
DockId=0x00000006,1
|
||||
DockId=0x00000012,1
|
||||
|
||||
[Window][Log Management]
|
||||
Pos=1203,28
|
||||
Size=1040,1710
|
||||
Collapsed=0
|
||||
DockId=0x00000006,2
|
||||
DockId=0x00000012,2
|
||||
|
||||
[Window][Track Proposal]
|
||||
Pos=709,326
|
||||
@@ -167,7 +167,7 @@ Collapsed=0
|
||||
Pos=2822,1717
|
||||
Size=1018,420
|
||||
Collapsed=0
|
||||
DockId=0x0000000C,0
|
||||
DockId=0x00000004,0
|
||||
|
||||
[Window][Approve PowerShell Command]
|
||||
Pos=649,435
|
||||
@@ -330,10 +330,10 @@ Size=967,499
|
||||
Collapsed=0
|
||||
|
||||
[Window][Usage Analytics]
|
||||
Pos=2222,28
|
||||
Size=488,1613
|
||||
Pos=1529,28
|
||||
Size=705,1570
|
||||
Collapsed=0
|
||||
DockId=0x00000001,0
|
||||
DockId=0x00000013,2
|
||||
|
||||
[Window][Tool Preset Manager]
|
||||
Pos=516,112
|
||||
@@ -405,19 +405,19 @@ Collapsed=0
|
||||
Pos=1163,24
|
||||
Size=1234,1542
|
||||
Collapsed=0
|
||||
DockId=0x00000006,1
|
||||
DockId=0x00000012,1
|
||||
|
||||
[Window][Project Settings]
|
||||
Pos=0,28
|
||||
Size=991,1425
|
||||
Size=712,1570
|
||||
Collapsed=0
|
||||
DockId=0x00000010,0
|
||||
|
||||
[Window][Undo/Redo History]
|
||||
Pos=1612,28
|
||||
Size=488,1592
|
||||
Pos=1529,28
|
||||
Size=705,1570
|
||||
Collapsed=0
|
||||
DockId=0x00000002,0
|
||||
DockId=0x00000013,1
|
||||
|
||||
[Window][Text Viewer - ts_cpp_get_skeleton]
|
||||
Pos=60,58
|
||||
@@ -495,10 +495,10 @@ Size=1780,1669
|
||||
Collapsed=0
|
||||
|
||||
[Window][Context Preview]
|
||||
Pos=993,28
|
||||
Size=1359,1425
|
||||
Pos=1529,28
|
||||
Size=705,1570
|
||||
Collapsed=0
|
||||
DockId=0x00000006,3
|
||||
DockId=0x00000013,0
|
||||
|
||||
[Table][0xFB6E3870,4]
|
||||
RefScale=13
|
||||
@@ -612,7 +612,7 @@ Column 1 Weight=1.0000
|
||||
[Table][0x1DA1F4A6,2]
|
||||
RefScale=20
|
||||
Column 0 Weight=1.0000
|
||||
Column 1 Width=374
|
||||
Column 1 Width=120
|
||||
|
||||
[Table][0x5B562C13,3]
|
||||
RefScale=20
|
||||
@@ -659,21 +659,19 @@ Column 2 Width=150
|
||||
DockNode ID=0x00000008 Pos=3125,170 Size=593,1157 Split=Y
|
||||
DockNode ID=0x00000009 Parent=0x00000008 SizeRef=1029,147 Selected=0x0469CA7A
|
||||
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=0x0000000B Parent=0x00000003 SizeRef=404,1186 Split=X Selected=0xF4139CA2
|
||||
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=0x00000010 Parent=0x00000005 SizeRef=983,1140 CentralNode=1 Selected=0x7BD57D6A
|
||||
DockNode ID=0x00000005 Parent=0x00000007 SizeRef=712,1681 Split=Y Selected=0x3F1379AF
|
||||
DockNode ID=0x00000010 Parent=0x00000005 SizeRef=983,1140 CentralNode=1 Selected=0x418C7449
|
||||
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=0x0000000D Parent=0x00000003 SizeRef=435,1186 Selected=0x363E93D6
|
||||
DockNode ID=0x00000004 Parent=0xAFC85805 SizeRef=488,1183 Split=X 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
|
||||
DockNode ID=0x00000004 Parent=0xAFC85805 SizeRef=488,1183 Selected=0x3AEC3498
|
||||
|
||||
;;;<<<Layout_655921752_Default>>>;;;
|
||||
;;;<<<HelloImGui_Misc>>>;;;
|
||||
|
||||
@@ -9,5 +9,5 @@ active = "main"
|
||||
|
||||
[discussions.main]
|
||||
git_commit = ""
|
||||
last_updated = "2026-05-16T16:20:11"
|
||||
last_updated = "2026-05-16T16:24:09"
|
||||
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("Diagnostics", lambda: render_diagnostics_panel(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()
|
||||
|
||||
@@ -2837,7 +2838,11 @@ def render_context_batch_actions(app: App, total_lines: int, total_ast: int) ->
|
||||
app.ui_selected_context_files.clear()
|
||||
imgui.same_line()
|
||||
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
|
||||
imgui.same_line()
|
||||
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
|
||||
|
||||
render_ast_inspector_modal(app)
|
||||
render_text_viewer_window(app)
|
||||
return
|
||||
|
||||
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