aboutsummaryrefslogtreecommitdiffstats
path: root/core/src/components/ContactsMenu/Contact.vue
diff options
context:
space:
mode:
Diffstat (limited to 'core/src/components/ContactsMenu/Contact.vue')
-rw-r--r--core/src/components/ContactsMenu/Contact.vue193
1 files changed, 193 insertions, 0 deletions
diff --git a/core/src/components/ContactsMenu/Contact.vue b/core/src/components/ContactsMenu/Contact.vue
new file mode 100644
index 00000000000..322f53647b1
--- /dev/null
+++ b/core/src/components/ContactsMenu/Contact.vue
@@ -0,0 +1,193 @@
+<!--
+ - SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ - SPDX-License-Identifier: AGPL-3.0-or-later
+-->
+
+<template>
+ <li class="contact">
+ <NcAvatar class="contact__avatar"
+ :size="44"
+ :user="contact.isUser ? contact.uid : undefined"
+ :is-no-user="!contact.isUser"
+ :disable-menu="true"
+ :display-name="contact.avatarLabel"
+ :preloaded-user-status="preloadedUserStatus" />
+ <a class="contact__body"
+ :href="contact.profileUrl || contact.topAction?.hyperlink">
+ <div class="contact__body__full-name">{{ contact.fullName }}</div>
+ <div v-if="contact.lastMessage" class="contact__body__last-message">{{ contact.lastMessage }}</div>
+ <div v-if="contact.statusMessage" class="contact__body__status-message">{{ contact.statusMessage }}</div>
+ <div v-else class="contact__body__email-address">{{ contact.emailAddresses[0] }}</div>
+ </a>
+ <NcActions v-if="actions.length"
+ :inline="contact.topAction ? 1 : 0">
+ <template v-for="(action, idx) in actions">
+ <NcActionLink v-if="action.hyperlink !== '#'"
+ :key="`${idx}-link`"
+ :href="action.hyperlink"
+ class="other-actions">
+ <template #icon>
+ <img aria-hidden="true" class="contact__action__icon" :src="action.icon">
+ </template>
+ {{ action.title }}
+ </NcActionLink>
+ <NcActionText v-else :key="`${idx}-text`" class="other-actions">
+ <template #icon>
+ <img aria-hidden="true" class="contact__action__icon" :src="action.icon">
+ </template>
+ {{ action.title }}
+ </NcActionText>
+ </template>
+ <NcActionButton v-for="action in jsActions"
+ :key="action.id"
+ :close-after-click="true"
+ class="other-actions"
+ @click="action.callback(contact)">
+ <template #icon>
+ <NcIconSvgWrapper class="contact__action__icon-svg"
+ :svg="action.iconSvg(contact)" />
+ </template>
+ {{ action.displayName(contact) }}
+ </NcActionButton>
+ </NcActions>
+ </li>
+</template>
+
+<script>
+import NcActionLink from '@nextcloud/vue/components/NcActionLink'
+import NcActionText from '@nextcloud/vue/components/NcActionText'
+import NcActionButton from '@nextcloud/vue/components/NcActionButton'
+import NcActions from '@nextcloud/vue/components/NcActions'
+import NcAvatar from '@nextcloud/vue/components/NcAvatar'
+import NcIconSvgWrapper from '@nextcloud/vue/components/NcIconSvgWrapper'
+import { getEnabledContactsMenuActions } from '@nextcloud/vue/functions/contactsMenu'
+
+export default {
+ name: 'Contact',
+ components: {
+ NcActionLink,
+ NcActionText,
+ NcActionButton,
+ NcActions,
+ NcAvatar,
+ NcIconSvgWrapper,
+ },
+ props: {
+ contact: {
+ required: true,
+ type: Object,
+ },
+ },
+ computed: {
+ actions() {
+ if (this.contact.topAction) {
+ return [this.contact.topAction, ...this.contact.actions]
+ }
+ return this.contact.actions
+ },
+ jsActions() {
+ return getEnabledContactsMenuActions(this.contact)
+ },
+ preloadedUserStatus() {
+ if (this.contact.status) {
+ return {
+ status: this.contact.status,
+ message: this.contact.statusMessage,
+ icon: this.contact.statusIcon,
+ }
+ }
+ return undefined
+ },
+ },
+}
+</script>
+
+<style scoped lang="scss">
+.contact {
+ display: flex;
+ position: relative;
+ align-items: center;
+ padding: 3px;
+ padding-inline-start: 10px;
+
+ &__action {
+ &__icon {
+ width: 20px;
+ height: 20px;
+ padding: 12px;
+ filter: var(--background-invert-if-dark);
+ }
+
+ &__icon-svg {
+ padding: 5px;
+ }
+ }
+
+ &__avatar {
+ display: inherit;
+ }
+
+ &__body {
+ flex-grow: 1;
+ padding-inline-start: 10px;
+ margin-inline-start: 10px;
+ min-width: 0;
+
+ div {
+ position: relative;
+ width: 100%;
+ overflow-x: hidden;
+ text-overflow: ellipsis;
+ margin: -1px 0;
+ }
+ div:first-of-type {
+ margin-top: 0;
+ }
+ div:last-of-type {
+ margin-bottom: 0;
+ }
+
+ &__last-message, &__status-message, &__email-address {
+ color: var(--color-text-maxcontrast);
+ }
+
+ &:focus-visible {
+ box-shadow: 0 0 0 4px var(--color-main-background) !important;
+ outline: 2px solid var(--color-main-text) !important;
+ }
+ }
+
+ .other-actions {
+ width: 16px;
+ height: 16px;
+ cursor: pointer;
+
+ img {
+ filter: var(--background-invert-if-dark);
+ }
+ }
+
+ button.other-actions {
+ width: 44px;
+
+ &:focus {
+ border-color: transparent;
+ box-shadow: 0 0 0 2px var(--color-main-text);
+ }
+
+ &:focus-visible {
+ border-radius: var(--border-radius-pill);
+ }
+ }
+
+ /* actions menu */
+ .menu {
+ top: 47px;
+ margin-inline-end: 13px;
+ }
+
+ .popovermenu::after {
+ inset-inline-end: 2px;
+ }
+}
+</style>