editor: route file taps to in-app editor; add gated IME commit logging
- ui.OpenFile now calls the in-app editor OpenFile(path) instead of the external openfunc (Android Termux bridge). The old wiring sent every browser-row tap through the Termux bridge, which crashed on Android 7+ with FileUriExposedException (file:// Intent URI) and bypassed the editor. - OpenFile no longer invokes TheState.open; it is retained as a dormant external hook for a future 'open externally' action. - Add imeDebugLog (off by default) verbose per-commit IME logging in HandleReplaceRange, plus currentEditorText helper, to aid on-device IME commit/cursor-sync debugging.
This commit is contained in:
parent
92d8a6b7f0
commit
c9c0d47f2a
|
|
@ -74,8 +74,13 @@ type Logic struct {
|
||||||
func NewLogic(mfs pool.FileSystem, path string, openfunc func(string)) *Logic {
|
func NewLogic(mfs pool.FileSystem, path string, openfunc func(string)) *Logic {
|
||||||
state := NewState()
|
state := NewState()
|
||||||
TheState = state
|
TheState = state
|
||||||
|
// The openfunc (e.g. the Android Termux bridge) is kept on TheState.open
|
||||||
|
// as an optional external hook, but it is NOT the tap path: tapping a file
|
||||||
|
// must open it in the in-app editor (doc/spec.md). The previous wiring set
|
||||||
|
// ui.OpenFile = openfunc, which routed every tap through the external
|
||||||
|
// bridge and bypassed the editor entirely.
|
||||||
TheState.open = openfunc
|
TheState.open = openfunc
|
||||||
ui.OpenFile = openfunc
|
ui.OpenFile = func(path string) { OpenFile(path) }
|
||||||
|
|
||||||
// Initialize mock filesystem if nil
|
// Initialize mock filesystem if nil
|
||||||
mockFS := mfs
|
mockFS := mfs
|
||||||
|
|
|
||||||
|
|
@ -254,7 +254,10 @@ func GoToEditor(data any) {
|
||||||
// data is the filename string from the browser list.
|
// data is the filename string from the browser list.
|
||||||
func OpenFile(data any) {
|
func OpenFile(data any) {
|
||||||
filename := data.(string)
|
filename := data.(string)
|
||||||
TheState.open(filename)
|
// NOTE: the external open hook (TheState.open, e.g. the Android Termux
|
||||||
|
// bridge) is intentionally NOT called here. Opening a file is an in-app
|
||||||
|
// action; the external bridge was the old tap path and it crashes on
|
||||||
|
// Android 7+ (FileUriExposedException from a file:// Intent URI).
|
||||||
|
|
||||||
// Dispatch a request to load the file
|
// Dispatch a request to load the file
|
||||||
go func() {
|
go func() {
|
||||||
|
|
@ -654,6 +657,10 @@ func HandleReplaceRange(startRune, endRune int, text string) {
|
||||||
}
|
}
|
||||||
absStart := windowStart + runeIndexToByteStr(windowText, startRune)
|
absStart := windowStart + runeIndexToByteStr(windowText, startRune)
|
||||||
absEnd := windowStart + runeIndexToByteStr(windowText, endRune)
|
absEnd := windowStart + runeIndexToByteStr(windowText, endRune)
|
||||||
|
if imeDebugLog {
|
||||||
|
fmt.Printf("IME DEBUG HandleReplaceRange: startRune=%d endRune=%d text=%q windowStart=%d windowLen=%d -> absStart=%d absEnd=%d\n",
|
||||||
|
startRune, endRune, text, windowStart, len(windowText), absStart, absEnd)
|
||||||
|
}
|
||||||
|
|
||||||
var newCursor int
|
var newCursor int
|
||||||
if buf := TheState.Editor.ChunkedBuffer; buf != nil {
|
if buf := TheState.Editor.ChunkedBuffer; buf != nil {
|
||||||
|
|
@ -672,9 +679,30 @@ func HandleReplaceRange(startRune, endRune int, text string) {
|
||||||
newCursor = absStart + len(text)
|
newCursor = absStart + len(text)
|
||||||
}
|
}
|
||||||
TheState.Editor.CursorPosition = newCursor
|
TheState.Editor.CursorPosition = newCursor
|
||||||
|
if imeDebugLog {
|
||||||
|
dbgBuf := currentEditorText()
|
||||||
|
if len(dbgBuf) > 40 {
|
||||||
|
dbgBuf = dbgBuf[:40]
|
||||||
|
}
|
||||||
|
fmt.Printf("IME DEBUG -> newCursor=%d buffer=%q\n", newCursor, dbgBuf)
|
||||||
|
}
|
||||||
markDirty()
|
markDirty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// imeDebugLog enables verbose per-commit IME logging. Keep false in normal
|
||||||
|
// use; enable when debugging IME commit/cursor sync on device.
|
||||||
|
const imeDebugLog = false
|
||||||
|
|
||||||
|
// currentEditorText returns the current editor buffer contents (full for
|
||||||
|
// chunked files). Used only for debug logging.
|
||||||
|
func currentEditorText() string {
|
||||||
|
if cb := TheState.Editor.ChunkedBuffer; cb != nil {
|
||||||
|
s, _ := cb.FullContent()
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
return TheState.Editor.Buffer
|
||||||
|
}
|
||||||
|
|
||||||
func markDirty() {
|
func markDirty() {
|
||||||
// TheLogic is nil in pure unit tests (no logic goroutine). Editing the
|
// TheLogic is nil in pure unit tests (no logic goroutine). Editing the
|
||||||
// buffer is still valid there; only the autosave side-effect is skipped.
|
// buffer is still valid there; only the autosave side-effect is skipped.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user