Fix mentions

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel
2021-05-02 19:27:23 +02:00
parent e3753c041e
commit 3afc7c7feb
7 changed files with 291 additions and 374 deletions

View File

@@ -5,23 +5,34 @@ import MentionList from "./MentionList.vue";
import ApolloClient from "apollo-client";
import { NormalizedCacheObject } from "apollo-cache-inmemory";
import apolloProvider from "@/vue-apollo";
import { IPerson } from "@/types/actor";
import pDebounce from "p-debounce";
const client = apolloProvider.defaultClient as ApolloClient<NormalizedCacheObject>;
const fetchItems = async (query: string): Promise<IPerson[]> => {
const result = await client.query({
query: SEARCH_PERSONS,
variables: {
searchText: query,
},
});
// TipTap doesn't handle async for onFilter, hence the following line.
return result.data.searchPersons.elements;
};
const debouncedFetchItems = pDebounce(fetchItems, 200);
const mentionOptions: Partial<any> = {
HTMLAttributes: {
class: "mention",
},
suggestion: {
items: async (query: string) => {
const result = await client.query({
query: SEARCH_PERSONS,
variables: {
searchText: query,
},
});
// TipTap doesn't handle async for onFilter, hence the following line.
return result.data.searchPersons.elements;
items: async (query: string): Promise<IPerson[]> => {
if (query === "") {
return [];
}
return await debouncedFetchItems(query);
},
render: () => {
let component: VueRenderer;
@@ -51,9 +62,10 @@ const mentionOptions: Partial<any> = {
getReferenceClientRect: props.clientRect,
});
},
// onKeyDown(props: any) {
// return component.ref?.onKeyDown(props);
// },
onKeyDown(props: any) {
const ref = component.ref as typeof MentionList;
return ref?.onKeyDown(props);
},
onExit() {
popup[0].destroy();
component.destroy();

View File

@@ -7,21 +7,30 @@
:key="index"
@click="selectItem(index)"
>
{{ item }}
<actor-card :actor="item" />
</button>
</div>
</template>
<script lang="ts">
import { Vue, Component, Prop, Watch } from "vue-property-decorator";
import { displayName, usernameWithDomain } from "@/types/actor/actor.model";
import { IPerson } from "@/types/actor";
import ActorCard from "../../components/Account/ActorCard.vue";
@Component
@Component({
components: {
ActorCard,
},
})
export default class MentionList extends Vue {
@Prop({ type: Array, required: true }) items!: Array<any>;
@Prop({ type: Array, required: true }) items!: Array<IPerson>;
@Prop({ type: Function, required: true }) command!: any;
selectedIndex = 0;
displayName = displayName;
@Watch("items")
watchItems(): void {
this.selectedIndex = 0;
@@ -63,7 +72,7 @@ export default class MentionList extends Vue {
const item = this.items[index];
if (item) {
this.command({ id: item });
this.command({ id: usernameWithDomain(item) });
}
}
}
@@ -86,12 +95,12 @@ export default class MentionList extends Vue {
text-align: left;
background: transparent;
border: none;
padding: 0.2rem 0.5rem;
padding: 0.5rem 0.75rem;
&.is-selected,
&:hover {
color: #a975ff;
background: rgba(#a975ff, 0.1);
color: $background-color;
background: rgba($background-color, 0.1);
}
}
</style>

View File

@@ -0,0 +1,58 @@
/**
* From https://www.tiptap.dev/api/editor/#inject-css
* https://github.com/ueberdosis/tiptap/blob/main/packages/core/src/style.ts
*/
.ProseMirror {
position: relative;
word-wrap: break-word;
white-space: pre-wrap;
-webkit-font-variant-ligatures: none;
font-variant-ligatures: none;
& [contenteditable="false"] {
white-space: normal;
}
& [contenteditable="false"] [contenteditable="true"] {
white-space: pre-wrap;
}
pre {
white-space: pre-wrap;
}
}
.ProseMirror-gapcursor {
display: none;
pointer-events: none;
position: absolute;
&:after {
content: "";
display: block;
position: absolute;
top: -2px;
width: 20px;
border-top: 1px solid black;
animation: ProseMirror-cursor-blink 1.1s steps(2, start) infinite;
}
}
@keyframes ProseMirror-cursor-blink {
to {
visibility: hidden;
}
}
.ProseMirror-hideselection * {
&::selection {
background: transparent;
}
&::-moz-selection {
background: transparent;
}
caret-color: transparent;
}
.ProseMirror-focused .ProseMirror-gapcursor {
display: block;
}
.tippy-box[data-animation="fade"][data-state="hidden"] {
opacity: 0;
}