mirror of
https://github.com/m1k1o/neko.git
synced 2024-07-24 14:40:50 +12:00
Add mobile keyboard API (#21)
* fix page for mobile - minor changes. * fix textarea overlay to hide caret and avodi zooming on mobiles. * fix typo. * show keyboard btn if is touch device. * lint fix. * add to API. * mobile keybaord fix andorid blur. * add mobile keybaord toggle. * fix overlay. * mobile keybaord, skip if not a touch device.
This commit is contained in:
@ -20,6 +20,7 @@
|
||||
:cursorDraw="inactiveCursorDrawFunction"
|
||||
/>
|
||||
<neko-overlay
|
||||
ref="overlay"
|
||||
v-show="!private_mode_enabled && state.connection.status != 'disconnected'"
|
||||
:style="{ pointerEvents: state.control.locked ? 'none' : 'auto' }"
|
||||
:wsControl="control"
|
||||
@ -35,6 +36,7 @@
|
||||
:inactiveCursors="state.settings.inactive_cursors && session.profile.sends_inactive_cursor"
|
||||
@updateKeyboardModifiers="updateKeyboardModifiers($event)"
|
||||
@uploadDrop="uploadDrop($event)"
|
||||
@mobileKeyboardOpen="state.mobile_keyboard_open = $event"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -102,6 +104,7 @@
|
||||
@Ref('component') readonly _component!: HTMLElement
|
||||
@Ref('container') readonly _container!: HTMLElement
|
||||
@Ref('video') readonly _video!: HTMLVideoElement
|
||||
@Ref('overlay') readonly _overlay!: Overlay
|
||||
|
||||
// fallback image for webrtc reconnections:
|
||||
// chrome shows black screen when closing webrtc connection, that's why
|
||||
@ -196,6 +199,7 @@
|
||||
merciful_reconnect: false,
|
||||
},
|
||||
cursors: [],
|
||||
mobile_keyboard_open: false,
|
||||
} as NekoState
|
||||
|
||||
/////////////////////////////
|
||||
@ -405,6 +409,22 @@
|
||||
Vue.set(this.state.control, 'keyboard', { layout, variant })
|
||||
}
|
||||
|
||||
public mobileKeyboardShow() {
|
||||
this._overlay.mobileKeyboardShow()
|
||||
}
|
||||
|
||||
public mobileKeyboardHide() {
|
||||
this._overlay.mobileKeyboardHide()
|
||||
}
|
||||
|
||||
public mobileKeyboardToggle() {
|
||||
if (this.state.mobile_keyboard_open) {
|
||||
this.mobileKeyboardHide()
|
||||
} else {
|
||||
this.mobileKeyboardShow()
|
||||
}
|
||||
}
|
||||
|
||||
public setCursorDrawFunction(fn?: CursorDrawFunction) {
|
||||
Vue.set(this, 'cursorDrawFunction', fn)
|
||||
}
|
||||
|
@ -33,8 +33,9 @@
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-size: 1px; /* chrome would not paste text if 0px */
|
||||
font-size: 16px; /* at least 16px to avoid zooming on mobile */
|
||||
resize: none; /* hide textarea resize corner */
|
||||
caret-color: transparent; /* hide caret */
|
||||
outline: 0;
|
||||
border: 0;
|
||||
color: transparent;
|
||||
@ -116,6 +117,10 @@
|
||||
return 'url(' + uri + ') ' + x + ' ' + y + ', default'
|
||||
}
|
||||
|
||||
get isTouchDevice(): boolean {
|
||||
return 'ontouchstart' in window || navigator.maxTouchPoints > 0
|
||||
}
|
||||
|
||||
mounted() {
|
||||
// register mouseup globally as user can release mouse button outside of overlay
|
||||
window.addEventListener('mouseup', this.onMouseUp, true)
|
||||
@ -373,7 +378,11 @@
|
||||
}
|
||||
|
||||
onMouseEnter(e: MouseEvent) {
|
||||
this._textarea.focus()
|
||||
// focus opens the keyboard on mobile (only for android)
|
||||
if (!this.isTouchDevice) {
|
||||
this._textarea.focus()
|
||||
}
|
||||
|
||||
this.focused = true
|
||||
|
||||
if (this.isControling) {
|
||||
@ -629,5 +638,48 @@
|
||||
this.wsControl.release()
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// mobile keyboard
|
||||
//
|
||||
|
||||
public kbdShow = false
|
||||
public kbdOpen = false
|
||||
|
||||
public mobileKeyboardShow() {
|
||||
// skip if not a touch device
|
||||
if (!this.isTouchDevice) return
|
||||
|
||||
this.kbdShow = true
|
||||
this.kbdOpen = false
|
||||
|
||||
this._textarea.focus()
|
||||
window.visualViewport.addEventListener('resize', this.onVisualViewportResize)
|
||||
this.$emit('mobileKeyboardOpen', true)
|
||||
}
|
||||
|
||||
public mobileKeyboardHide() {
|
||||
// skip if not a touch device
|
||||
if (!this.isTouchDevice) return
|
||||
|
||||
this.kbdShow = false
|
||||
this.kbdOpen = false
|
||||
|
||||
this.$emit('mobileKeyboardOpen', false)
|
||||
window.visualViewport.removeEventListener('resize', this.onVisualViewportResize)
|
||||
this._textarea.blur()
|
||||
}
|
||||
|
||||
// visual viewport resize event is fired when keyboard is opened or closed
|
||||
// android does not blur textarea when keyboard is closed, so we need to do it manually
|
||||
onVisualViewportResize() {
|
||||
if (!this.kbdShow) return
|
||||
|
||||
if (!this.kbdOpen) {
|
||||
this.kbdOpen = true
|
||||
} else {
|
||||
this.mobileKeyboardHide()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -11,6 +11,7 @@ export default interface State {
|
||||
sessions: Record<string, Session>
|
||||
settings: Settings
|
||||
cursors: Cursors
|
||||
mobile_keyboard_open: boolean
|
||||
}
|
||||
|
||||
/////////////////////////////
|
||||
|
Reference in New Issue
Block a user