remoteview
Version:
Remote isolated browser platform by Dosyago
266 lines (251 loc) • 8.27 kB
JavaScript
import keys from '../../../kbd.js';
import {DEBUG, logitKeyInputEvent} from '../common.js';
import {d as R} from '../../node_modules/dumbass/r.js';
import {OmniBox} from './omniBox.js';
import {PluginsMenuButton} from './pluginsMenuButton.js';
export function Controls(state) {
const {H,retargetTab} = state;
return R`
<nav class="controls history aux" stylist="styleNavControl">
<!--History-->
<form submit=${e => H({ synthetic: true,
type: 'history',
event: e
})} click=${saveClick} stylist="styleHistoryForm">
<button ${state.tabs.length?'':'disabled'} name=history_action title=Back value=back class=back><</button>
<button ${state.tabs.length?'':'disabled'} name=history_action title=Forward value=forward class=forward>></button>
</form>
</nav>
<nav class="controls keyinput aux" stylist="styleNavControl">
<!--Text-->
<form class=kbd-input submit=${e => e.preventDefault()}>
<input tabindex=-1 class=control name=key_input size=5
autocomplete=off
bond=${el => state.viewState.keyinput = el}
keydown=${[logitKeyInputEvent,e => state.openKey = e.key, H,limitCursor,retargetTab]}
keyup=${[logitKeyInputEvent,() => state.openKey = '', H,retargetTab]}
focusin=${[() => clearWord(state), () => state.openKey = '']}
compositionstart=${[logitKeyInputEvent, startComposition]}
compositionupdate=${[logitKeyInputEvent,updateComposition]}
compositionend=${[logitKeyInputEvent,endComposition]}
input=${[logitKeyInputEvent,inputText]}
keypress=${[logitKeyInputEvent, pressKey]}
paste=${e => {
inputText({type:'paste',data:e.clipboardData.getData('Text')});
}}
>
<textarea tabindex=-1 class=control name=textarea_input cols=5 rows=1
autocomplete=off
bond=${el => state.viewState.textarea = el}
keydown=${[logitKeyInputEvent,e => state.openKey = e.key, H,limitCursor,retargetTab]}
keyup=${[logitKeyInputEvent,() => state.openKey = '', H,retargetTab]}
focusin=${[() => clearWord(state), () => state.openKey = '']}
compositionstart=${[logitKeyInputEvent,startComposition]}
compositionupdate=${[logitKeyInputEvent,updateComposition]}
compositionend=${[logitKeyInputEvent,endComposition]}
input=${[logitKeyInputEvent,inputText]}
keypress=${[logitKeyInputEvent, pressKey]}
paste=${e => {
inputText({type:'paste',data:e.clipboardData.getData('Text')});
}}
></textarea>
</form>
</nav>
${OmniBox(state)}
${DEBUG.pluginsMenu ? PluginsMenuButton(state) : ''}
`;
function startComposition(/*e*/) {
state.isComposing = true;
state.latestData = "";
}
function updateComposition(e) {
state.isComposing = true;
if ( state.hasCommitted ) {
state.latestData = e.data || state.latestData || "";
}
}
function endComposition(e) {
if ( ! state.isComposing ) return;
state.isComposing = false;
if ( e.data == state.latestCommitData ) return;
let data = e.data || "";
if ( commitChange(e, state) ) {
H({
synthetic: true,
type: 'typing',
event: e,
data: data
});
state.latestCommitData = data;
state.hasCommitted = true;
state.latestData = "";
} else {
state.latestData = "";
}
}
function inputText(e) {
let data = e.data || "";
if ( state.convertTypingEventsToSyncValueEvents ) {
H({
synthetic: true,
type: 'typing',
event: e,
data: data
});
} else {
if ( state.openKey == data ) return;
if ( commitChange(e, state) ) {
state.isComposing = false;
H({
synthetic: true,
type: 'typing',
event: e,
data: data
});
state.latestCommitData = data;
state.hasCommitted = true;
state.latestData = "";
} else if ( e.inputType == 'deleteContentBackward' ) {
if ( ! state.backspaceFiring ) {
H({
type: "keydown",
key: "Backspace"
});
H({
type: "keyup",
key: "Backspace"
});
if ( state.viewState.shouldHaveFocus ) {
state.viewState.shouldHaveFocus.value = "";
}
/**
H({
synthetic: true,
type: 'typing-deleteContentBackward',
event: e,
contextId: state.contextIdOfFocusedInput,
valueToDelete: state.latestCommitData,
});
**/
}
state.latestData = "";
} else if ( e.inputType == 'insertReplacementText' ) {
if ( ! state.backspaceFiring ) {
H({
type: "keydown",
key: "Backspace"
});
H({
type: "keyup",
key: "Backspace"
});
if ( state.viewState.shouldHaveFocus ) {
state.viewState.shouldHaveFocus.value = "";
}
/**
H({
synthetic: true,
type: 'typing-deleteContentBackward',
event: e,
contextId: state.contextIdOfFocusedInput,
valueToDelete: state.latestCommitData,
});
**/
}
state.latestData = "";
H({
synthetic: true,
type: 'typing-deleteContentBackward',
event: e,
contextId: state.contextIdOfFocusedInput,
valueToDelete: state.currentWord,
});
H({
synthetic: true,
type: 'typing',
event: e,
data: e.data
});
state.latestData = "";
clearWord(state);
state.latestCommitData = e.data;
state.hasCommitted = true;
} else if ( e.type == 'paste' ) {
H({
synthetic: true,
type: 'typing',
event: e,
data: data
});
state.latestData = "";
clearWord(state);
state.latestCommitData = data;
state.hasCommitted = true;
state.latestData = "";
}
}
}
function pressKey(e) {
updateWord(e, state);
if ( e.key && e.key.length == 1 ) {
state.lastKeypressKey = e.key;
H({
synthetic: true,
type: 'typing',
event: e,
data: e.key
});
} else H(e);
retargetTab(e);
}
}
// Helper functions
// save the target of a form submission
export function saveClick(event) {
if ( event.target.matches('button') ) {
event.currentTarget.clickedButton = event.target;
}
}
// keep track of sequences of keypresses (words basically)
// because some IMEs (iOS / Safari) issue a insertReplacementText if we select a
// suggested word, which requires we delete the word already entered.
function clearWord(state) {
state.hasCommitted = false;
state.currentWord = "";
}
function updateWord(keypress, state) {
const key = keys[keypress.key];
if ( !! key && (key.code == 'Space' || key.code == 'Enter') ) {
clearWord(state);
} else {
state.currentWord += keypress.key;
}
}
/**
* Limit cursor prevents the cursor to be moved
* Inside textarea.
* The reason we do this is to greatly simplify (for now)
* The type of input events that we need to handle and transmit
* to the remote browser.
* This limits us to only consider appending or deleting at the END
* of the textarea.
**/
function limitCursor(/*event*/) {
/*
const target = event.target;
target.selectionStart = target.selectionEnd = target.value.length;
*/
return;
}
// text
// determines if it's time to commit a text input change from an IME
function commitChange(e, state) {
const canCommit = (
(e.type == "input" && e.inputType == "insertText") ||
(e.type == "compositionend" && !! (e.data || state.latestData) )
);
if ( DEBUG.val >= DEBUG.high ) {
logitKeyInputEvent(e);
}
return canCommit;
}