Scroll to selected items
This commit is contained in:
parent
6e2cee596d
commit
fdae71b132
1 changed files with 61 additions and 9 deletions
|
@ -1,26 +1,49 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-if="Object.keys(sourceItem.threads).length === 1 && '0' in sourceItem.threads" class="relative">
|
<div v-if="Object.keys(sourceItem.threads).length === 1 && '0' in sourceItem.threads" class="relative">
|
||||||
<div :style="style()" class="p-4 border-2 -mt-2px cursor-pointer bg-gray-200 border-gray-800 select-none relative z-20" :class="isSelected(0) ? 'selected shadow-md -mx-2' : ''" @click="select(0)" @mousedown="e => startDrag(e)" @touchstart="e => startDrag(e)">
|
<div
|
||||||
|
:style="style()"
|
||||||
|
:ref="isSelected(0) ? 'highlightedElement' : ''"
|
||||||
|
class="p-4 border-2 -mt-2px cursor-pointer bg-gray-200 border-gray-800 select-none relative z-20"
|
||||||
|
:class="isSelected(0) ? 'selected shadow-md -mx-2' : ''"
|
||||||
|
@click="select(0)"
|
||||||
|
@mousedown="e => startDrag(e)"
|
||||||
|
@touchstart="e => startDrag(e)">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<Avatar v-if="getContact(0)" v-bind="getContact(0)!" class="mr-2" />
|
<Avatar v-if="getContact(0)" v-bind="getContact(0)!" class="mr-2" />
|
||||||
<span class="bg-gray-300 px-2 py-1 rounded-2xl block overflow-hidden text-nowrap text-ellipsis">
|
<span class="bg-gray-300 px-2 py-1 rounded-2xl block overflow-hidden text-nowrap text-ellipsis">
|
||||||
<component :is="parseString(item.threads[0].preview)" />
|
<component :is="parseString(item.threads[0].preview)" />
|
||||||
</span>
|
</span>
|
||||||
<span class="grow" />
|
<span class="grow" />
|
||||||
<span v-if="item.threads[0].count > 0" class="inline-flex items-center justify-center w-3 h-3 p-3 ms-3 text-sm font-medium text-blue-800 bg-blue-100 rounded-full dark:bg-blue-900 dark:text-blue-300">{{ item.threads[0].count }}</span>
|
<span
|
||||||
|
v-if="item.threads[0].count > 0"
|
||||||
|
class="inline-flex items-center justify-center w-3 h-3 p-3 ms-3 text-sm font-medium text-blue-800 bg-blue-100 rounded-full dark:bg-blue-900 dark:text-blue-300">
|
||||||
|
{{ item.threads[0].count }}
|
||||||
|
</span>
|
||||||
<span v-else><FontAwesomeIcon class="w-6 h-6 text-lime-600" :icon="faCheck" /></span>
|
<span v-else><FontAwesomeIcon class="w-6 h-6 text-lime-600" :icon="faCheck" /></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex -mb-2 text-gray-500 text-sm font-normal">
|
<div class="flex -mb-2 text-gray-500 text-sm font-normal">
|
||||||
<span class="grow">{{ sourceItem.title }}</span>
|
<span class="grow">{{ sourceItem.title }}</span>
|
||||||
<span>{{ source.name }}</span>
|
<span>{{ source.name }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="item.threads[0].snoozedUntil != null" class="mt-4 text-sm text-yellow-600">Snoozed until {{ new Date(item.threads[0].snoozedUntil).toLocaleString() }}</div>
|
<div
|
||||||
|
v-if="item.threads[0].snoozedUntil != null"
|
||||||
|
class="mt-4 text-sm text-yellow-600">
|
||||||
|
Snoozed until {{ new Date(item.threads[0].snoozedUntil).toLocaleString() }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<component :is="actionIndicators" />
|
<component :is="actionIndicators" />
|
||||||
</div>
|
</div>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<div class="p-4 border-2 -mt-2px bg-gray-200 border-gray-800 select-none relative z-20" :style="style()" @mousemove="drag" @mousedown="e => startDrag(e)" @mouseup="endDrag" @touchmove="drag" @touchstart="e => startDrag(e)" @touchend="endDrag">
|
<div
|
||||||
|
class="p-4 border-2 -mt-2px bg-gray-200 border-gray-800 select-none relative z-20"
|
||||||
|
:style="style()"
|
||||||
|
@mousemove="drag"
|
||||||
|
@mousedown="e => startDrag(e)"
|
||||||
|
@mouseup="endDrag"
|
||||||
|
@touchmove="drag"
|
||||||
|
@touchstart="e => startDrag(e)"
|
||||||
|
@touchend="endDrag">
|
||||||
<div class="flex -mb-2 text-gray-500 text-sm font-normal">
|
<div class="flex -mb-2 text-gray-500 text-sm font-normal">
|
||||||
<span class="grow">{{ sourceItem.title }}</span>
|
<span class="grow">{{ sourceItem.title }}</span>
|
||||||
<span>{{ source.name }}</span>
|
<span>{{ source.name }}</span>
|
||||||
|
@ -29,19 +52,38 @@
|
||||||
<component :is="actionIndicators" />
|
<component :is="actionIndicators" />
|
||||||
</div>
|
</div>
|
||||||
<div v-for="(thread, id) in activeThreads" class="relative">
|
<div v-for="(thread, id) in activeThreads" class="relative">
|
||||||
<div class="p-4 border-2 -mt-2px cursor-pointer bg-slate-300 border-gray-800 select-none relative z-20" :class="isSelected(id) ? 'selected shadow-md -mx-2 thread' : ''" :style="style(parseInt(id as unknown as string))" @click="select(parseInt(id as unknown as string))" @mousemove="drag" @mousedown="e => startDrag(e, id as unknown as string)" @mouseup="endDrag" @touchmove="drag" @touchstart="e => startDrag(e, id as unknown as string)" @touchend="endDrag">
|
<div
|
||||||
|
class="p-4 border-2 -mt-2px cursor-pointer bg-slate-300 border-gray-800 select-none relative z-20"
|
||||||
|
:ref="isSelected(id) ? 'highlightedElement' : ''"
|
||||||
|
:class="isSelected(id) ? 'selected shadow-md -mx-2 thread' : ''"
|
||||||
|
:style="style(parseInt(id as unknown as string))"
|
||||||
|
@click="select(parseInt(id as unknown as string))"
|
||||||
|
@mousemove="drag"
|
||||||
|
@mousedown="e => startDrag(e, id as unknown as string)"
|
||||||
|
@mouseup="endDrag"
|
||||||
|
@touchmove="drag"
|
||||||
|
@touchstart="e => startDrag(e, id as unknown as string)"
|
||||||
|
@touchend="endDrag">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<Avatar v-if="getContact(id)" v-bind="getContact(id)!" class="mr-2" />
|
<Avatar v-if="getContact(id)" v-bind="getContact(id)!" class="mr-2" />
|
||||||
<span class="bg-gray-100 px-2 py-1 rounded-2xl block overflow-hidden text-nowrap text-ellipsis">
|
<span class="bg-gray-100 px-2 py-1 rounded-2xl block overflow-hidden text-nowrap text-ellipsis">
|
||||||
<component :is="parseString(thread.preview)" />
|
<component :is="parseString(thread.preview)" />
|
||||||
</span>
|
</span>
|
||||||
<span class="grow" />
|
<span class="grow" />
|
||||||
<span v-if="thread.count > 1" class="inline-flex items-center justify-center w-3 h-3 p-3 ms-3 text-sm font-medium text-blue-800 bg-blue-100 rounded-full dark:bg-blue-900 dark:text-blue-300">{{ thread.count }}</span>
|
<span
|
||||||
|
v-if="thread.count > 1"
|
||||||
|
class="inline-flex items-center justify-center w-3 h-3 p-3 ms-3 text-sm font-medium text-blue-800 bg-blue-100 rounded-full dark:bg-blue-900 dark:text-blue-300">
|
||||||
|
{{ thread.count }}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex -mb-2 text-gray-500 text-sm font-normal">
|
<div class="flex -mb-2 text-gray-500 text-sm font-normal">
|
||||||
<span class="grow">{{ sourceItem.threads[id].title }}</span>
|
<span class="grow">{{ sourceItem.threads[id].title }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="thread.snoozedUntil != null" class="mt-4 text-sm text-yellow-600">Snoozed until {{ new Date(thread.snoozedUntil).toLocaleString() }}</div>
|
<div
|
||||||
|
v-if="thread.snoozedUntil != null"
|
||||||
|
class="mt-4 text-sm text-yellow-600">
|
||||||
|
Snoozed until {{ new Date(thread.snoozedUntil).toLocaleString() }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<component :is="actionIndicators" />
|
<component :is="actionIndicators" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -51,7 +93,7 @@
|
||||||
<script setup lang="tsx">
|
<script setup lang="tsx">
|
||||||
import { faCheck, faClockRotateLeft } from '@fortawesome/free-solid-svg-icons';
|
import { faCheck, faClockRotateLeft } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
|
||||||
import { computed, ref } from 'vue';
|
import { computed, ref, watch } from 'vue';
|
||||||
import type { Item, ItemThread, ThreadRef } from "../state";
|
import type { Item, ItemThread, ThreadRef } from "../state";
|
||||||
import { items, sources } from '../state';
|
import { items, sources } from '../state';
|
||||||
import { parseString } from '../utils';
|
import { parseString } from '../utils';
|
||||||
|
@ -90,6 +132,16 @@ const style = (id?: number) =>
|
||||||
const source = computed(() => sources.value[props.item.source]);
|
const source = computed(() => sources.value[props.item.source]);
|
||||||
const sourceItem = computed(() => source.value.items[props.item.sourceItem]);
|
const sourceItem = computed(() => source.value.items[props.item.sourceItem]);
|
||||||
|
|
||||||
|
// Gets assigned on any thread item that should be highlighted
|
||||||
|
const highlightedElement = ref();
|
||||||
|
watch(highlightedElement, element => {
|
||||||
|
if (Array.isArray(element)) {
|
||||||
|
element.forEach(el => el?.scrollIntoView());
|
||||||
|
} else {
|
||||||
|
element?.scrollIntoView();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
function getContact(thread: number) {
|
function getContact(thread: number) {
|
||||||
const contact = props.item.threads[thread].contact;
|
const contact = props.item.threads[thread].contact;
|
||||||
return contact == null ? undefined : sources.value[props.item.source].contacts[contact];
|
return contact == null ? undefined : sources.value[props.item.source].contacts[contact];
|
||||||
|
|
Loading…
Reference in a new issue