Handle soft keyboard better

This commit is contained in:
N-Pex 2020-12-04 10:44:46 +01:00
parent bf0f2af59e
commit 70d015e5ce
4 changed files with 93 additions and 30 deletions

15
package-lock.json generated
View file

@ -20,6 +20,7 @@
"roboto-fontface": "*",
"v-emoji-picker": "^2.3.1",
"vue": "^2.6.11",
"vue-resize": "^0.5.0",
"vue-router": "^3.2.0",
"vuetify": "^2.2.11",
"vuex": "^3.5.1"
@ -13499,6 +13500,14 @@
"vue-class-component": "*"
}
},
"node_modules/vue-resize": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/vue-resize/-/vue-resize-0.5.0.tgz",
"integrity": "sha512-k5gOOwTIGSoWZb133Gx3IfSeiiAmve5GyWI7+pU8CvbNntpSAlrCYwZ26GB63NpxcLPK94+m0BDl5TxuZUI+Hw==",
"peerDependencies": {
"vue": "^2.6.11"
}
},
"node_modules/vue-router": {
"version": "3.4.9",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.4.9.tgz",
@ -25652,6 +25661,12 @@
"integrity": "sha512-xYA8MkZynPBGd/w5QFJ2d/NM0z/YeegMqYTphy7NJQXbZcuU6FC6AOdUAcy4SXP+YnkerC6AfH+ldg7PDk9ESQ==",
"requires": {}
},
"vue-resize": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/vue-resize/-/vue-resize-0.5.0.tgz",
"integrity": "sha512-k5gOOwTIGSoWZb133Gx3IfSeiiAmve5GyWI7+pU8CvbNntpSAlrCYwZ26GB63NpxcLPK94+m0BDl5TxuZUI+Hw==",
"requires": {}
},
"vue-router": {
"version": "3.4.9",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.4.9.tgz",

View file

@ -21,6 +21,7 @@
"roboto-fontface": "*",
"v-emoji-picker": "^2.3.1",
"vue": "^2.6.11",
"vue-resize": "^0.5.0",
"vue-router": "^3.2.0",
"vuetify": "^2.2.11",
"vuex": "^3.5.1"

View file

@ -7,12 +7,21 @@
v-on:sscroll="onScroll"
>
<div v-for="event in events" :key="event.getId()">
<div v-if="!event.isRelation() && !event.isRedacted() && !event.isRedaction()">
<div style="position:relative;user-select:none"
v-on:touchstart="(e) => { touchStart(e, event) }"
v-on:touchend="touchEnd"
v-on:touchcancel="touchCancel"
v-on:touchmove="touchMove"
<div
v-if="
!event.isRelation() && !event.isRedacted() && !event.isRedaction()
"
>
<div
style="position: relative; user-select: none"
v-on:touchstart="
(e) => {
touchStart(e, event);
}
"
v-on:touchend="touchEnd"
v-on:touchcancel="touchCancel"
v-on:touchmove="touchMove"
>
<component
:is="componentForEvent(event)"
@ -37,6 +46,12 @@
</div>
</div>
</div>
<!-- Handle resizes, e.g. when soft keyboard is shown/hidden -->
<resize-observer
ref="chatContainerResizer"
@notify="handleChatContainerResize"
/>
</div>
<!-- Input area -->
@ -196,7 +211,13 @@ export default {
currentSendError: null,
showEmojiPicker: false,
selectedEvent: null,
showContextMenu: false
showContextMenu: false,
/**
* Current chat container size. We need to keep track of this so that if and when
* a soft keyboard is shown/hidden we can restore the scroll position correctly.
* If we don't, the keyboard will simply overflow the message we are answering to etc.
*/
chatContainerSize: 0,
};
},
@ -205,6 +226,8 @@ export default {
this.scrollPosition = new ScrollPosition(container);
this.$matrix.on("Room.timeline", this.onEvent);
this.$matrix.on("RoomMember.typing", this.onUserTyping);
this.chatContainerSize = this.$refs.chatContainerResizer.$el.clientHeight;
console.log("resize initial height: ", this.chatContainerSize);
},
destroyed() {
@ -258,13 +281,13 @@ export default {
methods: {
touchX(event) {
if(event.type.indexOf('mouse') !== -1){
if (event.type.indexOf("mouse") !== -1) {
return event.clientX;
}
return event.touches[0].clientX;
},
touchY(event) {
if(event.type.indexOf('mouse') !== -1){
if (event.type.indexOf("mouse") !== -1) {
return event.clientY;
}
return event.touches[0].clientY;
@ -291,17 +314,38 @@ export default {
this.touchCurrentX = this.touchX(e);
this.touchCurrentY = this.touchY(e);
var tapTolerance = 4;
var touchMoved = Math.abs(this.touchStartX - this.touchCurrentX) > tapTolerance ||
Math.abs(this.touchStartY - this.touchCurrentY) > tapTolerance;
if(touchMoved){
var touchMoved =
Math.abs(this.touchStartX - this.touchCurrentX) > tapTolerance ||
Math.abs(this.touchStartY - this.touchCurrentY) > tapTolerance;
if (touchMoved) {
this.touchTimer && clearTimeout(this.touchTimer);
}
},
/**
* Triggered when out "long tap" timer hits.
*/
touchTimerElapsed() {
console.log('timer');
this.showContextMenu = true;
},
/**
* If chat container is shrunk (probably because soft keyboard is shown) adjust
* the scroll position so that e.g. if we were looking at the last message when
* moving focus to the input field, we would still see the last message. Otherwise
* if would be hidden behind the keyboard.
*/
handleChatContainerResize({ width, height }) {
console.log("resized", width, height);
const delta = height - this.chatContainerSize;
this.chatContainerSize = height;
console.log("resized delta " + delta);
const container = this.$refs.chatContainer;
if (delta < 0) {
container.scrollTop -= delta;
}
},
componentForEvent(event) {
switch (event.getType()) {
case "m.room.member":
@ -312,7 +356,7 @@ export default {
} else if (event.getContent().membership == "invite") {
return ContactInvited;
}
break;
break;
case "m.room.message":
if (event.getSender() != this.$matrix.currentUserId) {
@ -372,7 +416,7 @@ export default {
// If we are at bottom, scroll to see new events...
const container = this.$refs.chatContainer;
var scrollToSeeNew = (event.getSender() == this.$matrix.currentUserId); // When we sent, scroll
var scrollToSeeNew = event.getSender() == this.$matrix.currentUserId; // When we sent, scroll
if (
container.scrollHeight - container.scrollTop.toFixed(0) ==
container.clientHeight
@ -542,25 +586,25 @@ export default {
if (this.selectedEvent) {
const event = this.selectedEvent;
this.selectedEvent = null;
this.sendQuickReaction({reaction:e.data, event: event});
this.sendQuickReaction({ reaction: e.data, event: event });
}
},
sendQuickReaction(e) {
util
.sendQuickReaction(
this.$matrix.matrixClient,
this.roomId,
e.reaction,
e.event
)
.then(() => {
console.log("Quick reaction message");
})
.catch((err) => {
console.log("Failed to send quick reaction:", err);
});
}
.sendQuickReaction(
this.$matrix.matrixClient,
this.roomId,
e.reaction,
e.event
)
.then(() => {
console.log("Quick reaction message");
})
.catch((err) => {
console.log("Failed to send quick reaction:", err);
});
},
},
};
</script>

View file

@ -7,9 +7,12 @@ import matrix from './services/matrix.service'
import 'roboto-fontface/css/roboto/roboto-fontface.css'
import 'material-design-icons-iconfont/dist/material-design-icons.css'
import VEmojiPicker from 'v-emoji-picker';
import VueResize from 'vue-resize';
import 'vue-resize/dist/vue-resize.css';
Vue.config.productionTip = false
Vue.use(VueResize);
Vue.use(VEmojiPicker);
Vue.use(matrix, {store: store});