Skip to content
Snippets Groups Projects
Unverified Commit 6abb234e authored by Greta's avatar Greta Committed by GitHub
Browse files

Merge pull request #3641 from nextcloud/fix/inline_avatars

Show inline avatars for all participants in a threading
parents 12be98fa 49cc5013
No related branches found
No related tags found
No related merge requests found
......@@ -60,6 +60,6 @@ class AddressbookSource implements IAvatarSource {
return null;
}
return $factory->createInternal($url, null);
return $factory->createInternal($url);
}
}
<template>
<router-link v-if="email !== label"
v-tooltip.bottom="email"
:to="newMessageRoute"
exact>
{{ label }}
</router-link>
<router-link v-else :to="newMessageRoute" exact>
{{ label }}
</router-link>
</template>
<script>
export default {
name: 'Address',
props: {
email: {
type: String,
required: true,
},
label: {
type: String,
required: true,
},
},
computed: {
newMessageRoute() {
return {
name: 'message',
params: {
mailboxId: this.$route.params.mailboxId,
threadId: 'new',
},
query: {
to: this.email,
},
}
},
},
}
</script>
<template>
<span>
<template v-for="(entry, idx) in entries">
<Address :key="entry.email" :email="entry.email" :label="entry.label" />
<span v-if="idx === entries.length - 2" :key="'split' + entry.email">{{ t('mail', 'and') }}</span>
<span v-else-if="idx + 1 < entries.length" :key="'split' + entry.email">, </span>
</template>
</span>
</template>
<script>
import Address from './Address'
export default {
name: 'AddressList',
components: {
Address,
},
props: {
entries: {
type: Array,
required: true,
},
},
}
</script>
<!--
- @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
-
- @author 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
-
- @license GNU AGPL version 3 or any later version
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<template>
<UserBubble :display-name="label"
:avatar-image="avatarUrlAbsolute"
@click="onClick">
<span class="user-bubble-email">{{ email }}</span>
</UserBubble>
</template>
<script>
import { generateUrl } from '@nextcloud/router'
import UserBubble from '@nextcloud/vue/dist/Components/UserBubble'
import { fetchAvatarUrlMemoized } from '../service/AvatarService'
export default {
name: 'RecipientBubble',
components: {
UserBubble,
},
props: {
email: {
type: String,
required: true,
},
label: {
type: String,
required: true,
},
},
data() {
return {
avatarUrl: undefined,
}
},
computed: {
avatarUrlAbsolute() {
if (!this.avatarUrl) {
return
}
if (this.avatarUrl.startsWith('http')) {
return this.avatarUrl
}
// Make it an absolute URL because the user bubble component doesn't work with relative URLs
return window.location.protocol + '//' + window.location.host + generateUrl(this.avatarUrl)
},
},
async mounted() {
try {
this.avatarUrl = await fetchAvatarUrlMemoized(this.email)
} catch (error) {
console.debug('no avatar for ' + this.email, {
error,
})
}
},
methods: {
onClick() {
this.$router.push({
name: 'message',
params: {
mailboxId: 'priority', // TODO: figure out current mailbox
threadId: 'new',
},
query: {
to: this.email,
},
})
},
},
}
</script>
<style lang="scss" scoped>
.user-bubble-email {
margin: 10px;
}
</style>
......@@ -7,9 +7,12 @@
<h2 :title="threadSubject">
{{ threadSubject }}
</h2>
<p class="transparency">
<AddressList :entries="threadParticipants" />
</p>
<div class="avatar-header">
<RecipientBubble v-for="participant in threadParticipants"
:key="participant.email"
:email="participant.email"
:label="participant.label" />
</div>
</div>
</div>
<ThreadEnvelope v-for="env in thread"
......@@ -26,20 +29,21 @@
import AppContentDetails from '@nextcloud/vue/dist/Components/AppContentDetails'
import { prop, uniqBy } from 'ramda'
import AddressList from './AddressList'
import { getRandomMessageErrorMessage } from '../util/ErrorMessageFactory'
import Loading from './Loading'
import logger from '../logger'
import RecipientBubble from './RecipientBubble'
import ThreadEnvelope from './ThreadEnvelope'
export default {
name: 'Thread',
components: {
AddressList,
RecipientBubble,
AppContentDetails,
Loading,
ThreadEnvelope,
},
data() {
return {
loading: true,
......@@ -282,4 +286,10 @@ export default {
.app-content-list-item-star.icon-starred {
display: none;
}
.user-bubble__wrapper {
margin-right: 4px;
}
.user-bubble__title {
cursor: pointer;
}
</style>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment