chore: improve reaction picker behaviour

This commit is contained in:
syuilo 2021-02-28 02:22:53 +09:00
parent 764a158cd7
commit 7674a62d40
2 changed files with 63 additions and 61 deletions

View file

@ -69,71 +69,78 @@ export default defineComponent({
mounted() { mounted() {
this.$watch('src', () => { this.$watch('src', () => {
this.fixed = getFixedContainer(this.src) != null; this.fixed = getFixedContainer(this.src) != null;
this.$nextTick(() => {
this.align();
});
}, { immediate: true }); }, { immediate: true });
this.$nextTick(() => { this.$nextTick(() => {
const popover = this.$refs.content as any; const popover = this.$refs.content as any;
// TODO: ResizeObserver
new ResizeObserver((entries, observer) => { new ResizeObserver((entries, observer) => {
if (!this.popup) return; this.align();
const rect = this.src.getBoundingClientRect();
const width = popover.offsetWidth;
const height = popover.offsetHeight;
let left;
let top;
if (this.srcCenter) {
const x = rect.left + (this.fixed ? 0 : window.pageXOffset) + (this.src.offsetWidth / 2);
const y = rect.top + (this.fixed ? 0 : window.pageYOffset) + (this.src.offsetHeight / 2);
left = (x - (width / 2));
top = (y - (height / 2));
} else {
const x = rect.left + (this.fixed ? 0 : window.pageXOffset) + (this.src.offsetWidth / 2);
const y = rect.top + (this.fixed ? 0 : window.pageYOffset) + this.src.offsetHeight;
left = (x - (width / 2));
top = y;
}
if (this.fixed) {
if (left + width > window.innerWidth) {
left = window.innerWidth - width;
}
if (top + height > window.innerHeight) {
top = window.innerHeight - height;
}
} else {
if (left + width - window.pageXOffset > window.innerWidth) {
left = window.innerWidth - width + window.pageXOffset - 1;
}
if (top + height - window.pageYOffset > window.innerHeight) {
top = window.innerHeight - height + window.pageYOffset - 1;
}
}
if (top < 0) {
top = 0;
}
if (left < 0) {
left = 0;
}
if (top > rect.top + (this.fixed ? 0 : window.pageYOffset)) {
this.transformOrigin = 'center top';
}
popover.style.left = left + 'px';
popover.style.top = top + 'px';
}).observe(popover); }).observe(popover);
}); });
}, },
methods: { methods: {
align() {
if (!this.popup) return;
const popover = this.$refs.content as any;
const rect = this.src.getBoundingClientRect();
const width = popover.offsetWidth;
const height = popover.offsetHeight;
let left;
let top;
if (this.srcCenter) {
const x = rect.left + (this.fixed ? 0 : window.pageXOffset) + (this.src.offsetWidth / 2);
const y = rect.top + (this.fixed ? 0 : window.pageYOffset) + (this.src.offsetHeight / 2);
left = (x - (width / 2));
top = (y - (height / 2));
} else {
const x = rect.left + (this.fixed ? 0 : window.pageXOffset) + (this.src.offsetWidth / 2);
const y = rect.top + (this.fixed ? 0 : window.pageYOffset) + this.src.offsetHeight;
left = (x - (width / 2));
top = y;
}
if (this.fixed) {
if (left + width > window.innerWidth) {
left = window.innerWidth - width;
}
if (top + height > window.innerHeight) {
top = window.innerHeight - height;
}
} else {
if (left + width - window.pageXOffset > window.innerWidth) {
left = window.innerWidth - width + window.pageXOffset - 1;
}
if (top + height - window.pageYOffset > window.innerHeight) {
top = window.innerHeight - height + window.pageYOffset - 1;
}
}
if (top < 0) {
top = 0;
}
if (left < 0) {
left = 0;
}
if (top > rect.top + (this.fixed ? 0 : window.pageYOffset)) {
this.transformOrigin = 'center top';
}
popover.style.left = left + 'px';
popover.style.top = top + 'px';
},
childRendered() { childRendered() {
// //
const content = this.$refs.content.children[0]; const content = this.$refs.content.children[0];

View file

@ -360,16 +360,12 @@ export async function openEmojiPicker(src?: HTMLElement, opts, initialTextarea:
let reactionPicker = null; let reactionPicker = null;
export async function pickReaction(src: HTMLElement, chosen, closed) { export async function pickReaction(src: HTMLElement, chosen, closed) {
if (reactionPicker) { if (reactionPicker) {
if (reactionPicker.opening) return;
reactionPicker.opening = true;
reactionPicker.src.value = src; reactionPicker.src.value = src;
reactionPicker.manualShowing.value = true; reactionPicker.manualShowing.value = true;
reactionPicker.chosen = chosen; reactionPicker.chosen = chosen;
reactionPicker.closed = closed; reactionPicker.closed = closed;
} else { } else {
reactionPicker = { reactionPicker = {
opening: true,
src: ref(src), src: ref(src),
manualShowing: ref(true), manualShowing: ref(true),
chosen, closed chosen, closed
@ -388,7 +384,6 @@ export async function pickReaction(src: HTMLElement, chosen, closed) {
closed: () => { closed: () => {
reactionPicker.src.value = null; reactionPicker.src.value = null;
reactionPicker.closed(); reactionPicker.closed();
reactionPicker.opening = false;
} }
}); });
} }