2023-02-08 21:35:42 +00:00
|
|
|
<template>
|
|
|
|
<div class="container">
|
2023-03-30 18:44:18 +00:00
|
|
|
<div class="primary" ref="primary">
|
2023-02-08 21:35:42 +00:00
|
|
|
<component :is="primary" />
|
|
|
|
</div>
|
2023-03-30 18:44:18 +00:00
|
|
|
|
|
|
|
<div
|
|
|
|
class="separator"
|
|
|
|
ref="separator"
|
|
|
|
@pointerdown="sepDown"
|
|
|
|
@touchmove.passive="sepTouchMove"
|
|
|
|
@touchend.passive="pointerUp"
|
|
|
|
@touchcancel.passive="pointerUp"
|
|
|
|
></div>
|
|
|
|
|
2023-02-08 21:35:42 +00:00
|
|
|
<div class="timeline">
|
|
|
|
<Timeline />
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script lang="ts">
|
|
|
|
import { defineComponent } from "vue";
|
|
|
|
import Timeline from "./Timeline.vue";
|
2023-02-09 08:39:02 +00:00
|
|
|
const MapSplitMatter = () => import("./top-matter/MapSplitMatter.vue");
|
2023-03-30 18:44:18 +00:00
|
|
|
import { emit } from "@nextcloud/event-bus";
|
2023-02-08 21:35:42 +00:00
|
|
|
|
|
|
|
export default defineComponent({
|
|
|
|
name: "SplitTimeline",
|
|
|
|
|
|
|
|
components: {
|
|
|
|
Timeline,
|
|
|
|
},
|
|
|
|
|
2023-03-30 18:44:18 +00:00
|
|
|
data: () => ({
|
|
|
|
pointerDown: false,
|
|
|
|
primaryPos: 0,
|
|
|
|
}),
|
|
|
|
|
2023-02-08 21:35:42 +00:00
|
|
|
computed: {
|
|
|
|
primary() {
|
|
|
|
switch (this.$route.name) {
|
2023-02-08 22:13:13 +00:00
|
|
|
case "map":
|
|
|
|
return MapSplitMatter;
|
2023-02-08 21:35:42 +00:00
|
|
|
default:
|
|
|
|
return "None";
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
2023-03-30 18:44:18 +00:00
|
|
|
|
|
|
|
beforeDestroy() {
|
|
|
|
this.pointerUp();
|
|
|
|
},
|
|
|
|
|
|
|
|
methods: {
|
|
|
|
isVertical() {
|
|
|
|
return globalThis.windowInnerWidth <= 768;
|
|
|
|
},
|
|
|
|
|
|
|
|
sepDown(event: PointerEvent) {
|
|
|
|
this.pointerDown = true;
|
|
|
|
|
|
|
|
// Get position of primary element
|
|
|
|
const primary = <HTMLDivElement>this.$refs.primary;
|
|
|
|
const rect = primary.getBoundingClientRect();
|
|
|
|
this.primaryPos = this.isVertical() ? rect.top : rect.left;
|
|
|
|
|
|
|
|
// Let touch handle itself
|
|
|
|
if (event.pointerType === "touch") return;
|
|
|
|
|
|
|
|
// Otherwise, handle pointer events on document
|
|
|
|
document.addEventListener("pointermove", this.documentPointerMove);
|
|
|
|
document.addEventListener("pointerup", this.pointerUp);
|
|
|
|
|
|
|
|
// Prevent text selection
|
|
|
|
event.preventDefault();
|
|
|
|
event.stopPropagation();
|
|
|
|
},
|
|
|
|
|
|
|
|
sepTouchMove(event: TouchEvent) {
|
|
|
|
if (!this.pointerDown) return;
|
|
|
|
this.setFlexBasis(event.touches[0]);
|
|
|
|
},
|
|
|
|
|
|
|
|
documentPointerMove(event: PointerEvent) {
|
|
|
|
if (!this.pointerDown || !event.buttons) return this.pointerUp();
|
|
|
|
this.setFlexBasis(event);
|
|
|
|
},
|
|
|
|
|
|
|
|
pointerUp() {
|
|
|
|
// Get rid of listeners on document quickly
|
|
|
|
this.pointerDown = false;
|
|
|
|
document.removeEventListener("pointermove", this.documentPointerMove);
|
|
|
|
document.removeEventListener("pointerup", this.pointerUp);
|
|
|
|
emit("memories:window:resize", null);
|
|
|
|
},
|
|
|
|
|
|
|
|
setFlexBasis(pos: { clientX: number; clientY: number }) {
|
|
|
|
const ref = this.isVertical() ? pos.clientY : pos.clientX;
|
|
|
|
const newWidth = Math.max(ref - this.primaryPos, 50);
|
|
|
|
(<HTMLDivElement>this.$refs.primary).style.flexBasis = `${newWidth}px`;
|
|
|
|
},
|
|
|
|
},
|
2023-02-08 21:35:42 +00:00
|
|
|
});
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
.container {
|
|
|
|
width: 100%;
|
|
|
|
height: 100%;
|
|
|
|
display: flex;
|
|
|
|
overflow: hidden;
|
2023-03-30 18:44:18 +00:00
|
|
|
|
|
|
|
> div {
|
|
|
|
height: 100%;
|
|
|
|
max-height: 100%;
|
|
|
|
}
|
|
|
|
|
|
|
|
> .primary {
|
|
|
|
flex-basis: 60%;
|
|
|
|
flex-shrink: 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
> .timeline {
|
|
|
|
flex-basis: auto;
|
|
|
|
flex-grow: 1;
|
|
|
|
padding-left: 8px;
|
|
|
|
overflow: hidden;
|
|
|
|
}
|
|
|
|
|
|
|
|
> .separator {
|
|
|
|
flex-grow: 0;
|
|
|
|
flex-shrink: 0;
|
|
|
|
width: 5px;
|
|
|
|
background-color: gray;
|
|
|
|
opacity: 0.1;
|
|
|
|
cursor: col-resize;
|
|
|
|
margin: 0 0 0 auto;
|
|
|
|
transition: opacity 0.4s ease-out, background-color 0.4s ease-out;
|
|
|
|
}
|
|
|
|
|
|
|
|
> .separator:hover {
|
|
|
|
opacity: 0.4;
|
|
|
|
background-color: var(--color-primary);
|
|
|
|
}
|
2023-02-08 21:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@media (max-width: 768px) {
|
|
|
|
.container {
|
|
|
|
flex-direction: column;
|
2023-03-30 18:44:18 +00:00
|
|
|
|
|
|
|
> div {
|
|
|
|
width: 100%;
|
|
|
|
height: unset;
|
|
|
|
}
|
|
|
|
|
|
|
|
> .primary {
|
|
|
|
flex-basis: 40%;
|
|
|
|
}
|
|
|
|
|
|
|
|
> .timeline {
|
|
|
|
padding-left: 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
> .separator {
|
|
|
|
height: 5px;
|
|
|
|
width: 100%;
|
|
|
|
}
|
2023-02-08 21:35:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
</style>
|