select html file

This commit is contained in:
Dmitry Vasilev
2022-11-28 20:53:35 +08:00
parent cbfde4eafd
commit ffec3e3cc2
5 changed files with 81 additions and 17 deletions

View File

@@ -177,6 +177,7 @@
.entrypoint_title {
margin-right: 0.5em;
margin-left: 1.5em;
}
.callnode {

View File

@@ -506,6 +506,10 @@ const change_entrypoint = (state, entrypoint, index) => {
)
}
const change_html_file = (state, html_file) => {
return {...state, html_file}
}
const goto_definition = (state, index) => {
if(!state.parse_result.ok){
return {state, effects: {type: 'set_status', args: ['unresolved syntax errors']}}
@@ -766,7 +770,6 @@ const load_dir = (state, dir) => {
parse_result: null,
project_dir: dir,
files: {...files, ...state.files},
})
}
@@ -815,6 +818,7 @@ export const COMMANDS = {
step_into,
change_current_module,
change_entrypoint,
change_html_file,
goto_definition,
goto_problem,
move_cursor,

View File

@@ -1,4 +1,4 @@
import {exec, get_state, open_run_window} from '../index.js'
import {exec, get_state, open_run_window, reload_run_window} from '../index.js'
import {Editor} from './editor.js'
import {Files} from './files.js'
import {CallTree} from './calltree.js'
@@ -10,6 +10,8 @@ import {FLAGS} from '../feature_flags.js'
export class UI {
constructor(container, state){
this.change_entrypoint = this.change_entrypoint.bind(this)
this.change_html_file = this.change_html_file.bind(this)
this.open_run_window = this.open_run_window.bind(this)
this.files = new Files(this)
@@ -71,7 +73,7 @@ export class UI {
el('a', {
'class': 'open_run_window',
href: 'javascript: void(0)',
click: open_run_window,
click: this.open_run_window,
},
'(Re)open run window (F6)'
),
@@ -137,7 +139,7 @@ export class UI {
}
if(e.key == 'F6'){
open_run_window()
this.open_run_window()
}
})
@@ -190,7 +192,7 @@ export class UI {
render_entrypoint_select(state) {
this.entrypoint_select.replaceChildren(
el('span', 'entrypoint_title', 'entrypoint'),
el('span', 'entrypoint_title', 'js entrypoint'),
el('select', {
click: e => e.stopPropagation(),
change: this.change_entrypoint,
@@ -207,10 +209,35 @@ export class UI {
f == '' ? "*scratch*" : f
)
)
)
),
el('span', 'entrypoint_title', 'html page'),
el('select', {
click: e => e.stopPropagation(),
change: this.change_html_file,
},
['']
.concat(
Object
.keys(state.files)
.sort()
.filter(f => f.endsWith('.htm') || f.endsWith('.html'))
)
.map(f =>
el('option',
state.html_file == f
? { value: f, selected: true }
: { value: f},
f == '' ? 'abount:blank' : f
)
)
),
)
}
open_run_window() {
open_run_window(get_state())
}
change_entrypoint(e) {
const file = e.target.value
const index = this.editor.get_caret_position(file)
@@ -221,6 +248,12 @@ export class UI {
this.editor.focus()
}
change_html_file(e) {
const html_file = e.target.value
exec('change_html_file', html_file)
reload_run_window(get_state())
}
render_debugger(state) {
this.debugger_container.style = ''
this.problems_container.style = 'display: none'

15
src/effects.js vendored
View File

@@ -136,10 +136,19 @@ export const render_common_side_effects = (prev, next, command, ui) => {
||
prev.current_module != next.current_module
) {
ui.render_entrypoint_select(next)
ui.files.render(next)
}
if(
prev.project_dir != next.project_dir
||
prev.entrypoint != next.entrypoint
||
prev.html_file != next.html_file
) {
ui.render_entrypoint_select(next)
}
if(prev.current_module != next.current_module) {
localStorage.current_module = next.current_module
ui.render_current_module(next.current_module)
@@ -149,6 +158,10 @@ export const render_common_side_effects = (prev, next, command, ui) => {
localStorage.entrypoint = next.entrypoint
}
if(prev.html_file != next.html_file) {
localStorage.html_file = next.html_file
}
if(prev.current_module != next.current_module) {
ensure_session(ui, next)
ui.editor.unembed_value_explorer()

View File

@@ -18,25 +18,29 @@ const set_error_handler = w => {
})
}
const get_html_url = state => {
return state.html_file == ''
? 'about:blank'
: window.location.origin + '/' + state.html_file + '?leporello'
}
// By default run code in hidden iframe, until user explicitly opens visible
// window
globalThis.run_window = (() => {
const open_run_iframe = state => {
const iframe = document.createElement('iframe')
//iframe.src = 'about:blank'
iframe.src = '/index.html?leporello'
iframe.src = get_html_url(state)
iframe.setAttribute('hidden', '')
document.body.appendChild(iframe)
set_error_handler(iframe.contentWindow)
return iframe.contentWindow
})()
globalThis.run_window = iframe.contentWindow
}
// Open another browser window so user can interact with application
// TODO test in another browsers
export const open_run_window = () => {
export const open_run_window = state => {
globalThis.run_window.close()
//const next_window = open('about:blank')
const next_window = globalThis.run_window = open('/index.html?leporello')
const next_window = globalThis.run_window = open(get_html_url(state))
const is_loaded = () => {
const nav = next_window.performance.getEntriesByType("navigation")[0]
@@ -85,9 +89,7 @@ export const open_run_window = () => {
// If by that time next_window.closed was set to true, then page was
// closed
// TODO get back to iframe?
console.log("CLOSED")
} else {
console.log("REFRESHED")
add_load_handler()
}
}, 100)
@@ -97,12 +99,20 @@ export const open_run_window = () => {
add_load_handler()
}
export const reload_run_window = state => {
// TODO after window location reload, open_run_window command will be fired.
// Maybe we should have separate commands for open_run_window and
// reload_run_window?
globalThis.run_window.location = get_html_url(state)
}
const read_modules = async () => {
const default_module = {'': localStorage.code || EXAMPLE}
const current = {
// TODO fix when there are no such modules anymore
current_module: localStorage.current_module ?? '',
entrypoint: localStorage.entrypoint ?? '',
html_file: localStorage.html_file ?? '',
}
const project_dir = await load_dir(false)
if(project_dir == null) {
@@ -130,6 +140,9 @@ export const init = (container, _COMMANDS) => {
set_error_handler(window)
read_modules().then(initial_state => {
open_run_iframe(initial_state)
state = COMMANDS.get_initial_state({
...initial_state,
on_async_call: (...args) => exec('on_async_call', ...args)