summaryrefslogtreecommitdiff
path: root/src/server/web/app/common/views/components/messaging.vue
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/web/app/common/views/components/messaging.vue')
-rw-r--r--src/server/web/app/common/views/components/messaging.vue463
1 files changed, 0 insertions, 463 deletions
diff --git a/src/server/web/app/common/views/components/messaging.vue b/src/server/web/app/common/views/components/messaging.vue
deleted file mode 100644
index 8317c3738a..0000000000
--- a/src/server/web/app/common/views/components/messaging.vue
+++ /dev/null
@@ -1,463 +0,0 @@
-<template>
-<div class="mk-messaging" :data-compact="compact">
- <div class="search" v-if="!compact" :style="{ top: headerTop + 'px' }">
- <div class="form">
- <label for="search-input">%fa:search%</label>
- <input v-model="q" type="search" @input="search" @keydown="onSearchKeydown" placeholder="%i18n:common.tags.mk-messaging.search-user%"/>
- </div>
- <div class="result">
- <ol class="users" v-if="result.length > 0" ref="searchResult">
- <li v-for="(user, i) in result"
- @keydown.enter="navigate(user)"
- @keydown="onSearchResultKeydown(i)"
- @click="navigate(user)"
- tabindex="-1"
- >
- <img class="avatar" :src="`${user.avatarUrl}?thumbnail&size=32`" alt=""/>
- <span class="name">{{ user.name }}</span>
- <span class="username">@{{ getAcct(user) }}</span>
- </li>
- </ol>
- </div>
- </div>
- <div class="history" v-if="messages.length > 0">
- <template>
- <a v-for="message in messages"
- class="user"
- :href="`/i/messaging/${getAcct(isMe(message) ? message.recipient : message.user)}`"
- :data-is-me="isMe(message)"
- :data-is-read="message.isRead"
- @click.prevent="navigate(isMe(message) ? message.recipient : message.user)"
- :key="message.id"
- >
- <div>
- <img class="avatar" :src="`${isMe(message) ? message.recipient.avatarUrl : message.user.avatarUrl}?thumbnail&size=64`" alt=""/>
- <header>
- <span class="name">{{ isMe(message) ? message.recipient.name : message.user.name }}</span>
- <span class="username">@{{ getAcct(isMe(message) ? message.recipient : message.user) }}</span>
- <mk-time :time="message.createdAt"/>
- </header>
- <div class="body">
- <p class="text"><span class="me" v-if="isMe(message)">%i18n:common.tags.mk-messaging.you%:</span>{{ message.text }}</p>
- </div>
- </div>
- </a>
- </template>
- </div>
- <p class="no-history" v-if="!fetching && messages.length == 0">%i18n:common.tags.mk-messaging.no-history%</p>
- <p class="fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
-</div>
-</template>
-
-<script lang="ts">
-import Vue from 'vue';
-import getAcct from '../../../../../common/user/get-acct';
-
-export default Vue.extend({
- props: {
- compact: {
- type: Boolean,
- default: false
- },
- headerTop: {
- type: Number,
- default: 0
- }
- },
- data() {
- return {
- fetching: true,
- moreFetching: false,
- messages: [],
- q: null,
- result: [],
- connection: null,
- connectionId: null
- };
- },
- mounted() {
- this.connection = (this as any).os.streams.messagingIndexStream.getConnection();
- this.connectionId = (this as any).os.streams.messagingIndexStream.use();
-
- this.connection.on('message', this.onMessage);
- this.connection.on('read', this.onRead);
-
- (this as any).api('messaging/history').then(messages => {
- this.messages = messages;
- this.fetching = false;
- });
- },
- beforeDestroy() {
- this.connection.off('message', this.onMessage);
- this.connection.off('read', this.onRead);
- (this as any).os.streams.messagingIndexStream.dispose(this.connectionId);
- },
- methods: {
- getAcct,
- isMe(message) {
- return message.userId == (this as any).os.i.id;
- },
- onMessage(message) {
- this.messages = this.messages.filter(m => !(
- (m.recipientId == message.recipientId && m.userId == message.userId) ||
- (m.recipientId == message.userId && m.userId == message.recipientId)));
-
- this.messages.unshift(message);
- },
- onRead(ids) {
- ids.forEach(id => {
- const found = this.messages.find(m => m.id == id);
- if (found) found.isRead = true;
- });
- },
- search() {
- if (this.q == '') {
- this.result = [];
- return;
- }
- (this as any).api('users/search', {
- query: this.q,
- max: 5
- }).then(users => {
- this.result = users;
- });
- },
- navigate(user) {
- this.$emit('navigate', user);
- },
- onSearchKeydown(e) {
- switch (e.which) {
- case 9: // [TAB]
- case 40: // [↓]
- e.preventDefault();
- e.stopPropagation();
- (this.$refs.searchResult as any).childNodes[0].focus();
- break;
- }
- },
- onSearchResultKeydown(i, e) {
- const list = this.$refs.searchResult as any;
-
- const cancel = () => {
- e.preventDefault();
- e.stopPropagation();
- };
-
- switch (true) {
- case e.which == 27: // [ESC]
- cancel();
- (this.$refs.search as any).focus();
- break;
-
- case e.which == 9 && e.shiftKey: // [TAB] + [Shift]
- case e.which == 38: // [↑]
- cancel();
- (list.childNodes[i].previousElementSibling || list.childNodes[this.result.length - 1]).focus();
- break;
-
- case e.which == 9: // [TAB]
- case e.which == 40: // [↓]
- cancel();
- (list.childNodes[i].nextElementSibling || list.childNodes[0]).focus();
- break;
- }
- }
- }
-});
-</script>
-
-<style lang="stylus" scoped>
-@import '~const.styl'
-
-.mk-messaging
-
- &[data-compact]
- font-size 0.8em
-
- > .history
- > a
- &:last-child
- border-bottom none
-
- &:not([data-is-me]):not([data-is-read])
- > div
- background-image none
- border-left solid 4px #3aa2dc
-
- > div
- padding 16px
-
- > header
- > .mk-time
- font-size 1em
-
- > .avatar
- width 42px
- height 42px
- margin 0 12px 0 0
-
- > .search
- display block
- position -webkit-sticky
- position sticky
- top 0
- left 0
- z-index 1
- width 100%
- background #fff
- box-shadow 0 0px 2px rgba(0, 0, 0, 0.2)
-
- > .form
- padding 8px
- background #f7f7f7
-
- > label
- display block
- position absolute
- top 0
- left 8px
- z-index 1
- height 100%
- width 38px
- pointer-events none
-
- > [data-fa]
- display block
- position absolute
- top 0
- right 0
- bottom 0
- left 0
- width 1em
- line-height 56px
- margin auto
- color #555
-
- > input
- margin 0
- padding 0 0 0 32px
- width 100%
- font-size 1em
- line-height 38px
- color #000
- outline none
- border solid 1px #eee
- border-radius 5px
- box-shadow none
- transition color 0.5s ease, border 0.5s ease
-
- &:hover
- border solid 1px #ddd
- transition border 0.2s ease
-
- &:focus
- color darken($theme-color, 20%)
- border solid 1px $theme-color
- transition color 0, border 0
-
- > .result
- display block
- top 0
- left 0
- z-index 2
- width 100%
- margin 0
- padding 0
- background #fff
-
- > .users
- margin 0
- padding 0
- list-style none
-
- > li
- display inline-block
- z-index 1
- width 100%
- padding 8px 32px
- vertical-align top
- white-space nowrap
- overflow hidden
- color rgba(0, 0, 0, 0.8)
- text-decoration none
- transition none
- cursor pointer
-
- &:hover
- &:focus
- color #fff
- background $theme-color
-
- .name
- color #fff
-
- .username
- color #fff
-
- &:active
- color #fff
- background darken($theme-color, 10%)
-
- .name
- color #fff
-
- .username
- color #fff
-
- .avatar
- vertical-align middle
- min-width 32px
- min-height 32px
- max-width 32px
- max-height 32px
- margin 0 8px 0 0
- border-radius 6px
-
- .name
- margin 0 8px 0 0
- /*font-weight bold*/
- font-weight normal
- color rgba(0, 0, 0, 0.8)
-
- .username
- font-weight normal
- color rgba(0, 0, 0, 0.3)
-
- > .history
-
- > a
- display block
- text-decoration none
- background #fff
- border-bottom solid 1px #eee
-
- *
- pointer-events none
- user-select none
-
- &:hover
- background #fafafa
-
- > .avatar
- filter saturate(200%)
-
- &:active
- background #eee
-
- &[data-is-read]
- &[data-is-me]
- opacity 0.8
-
- &:not([data-is-me]):not([data-is-read])
- > div
- background-image url("/assets/unread.svg")
- background-repeat no-repeat
- background-position 0 center
-
- &:after
- content ""
- display block
- clear both
-
- > div
- max-width 500px
- margin 0 auto
- padding 20px 30px
-
- &:after
- content ""
- display block
- clear both
-
- > header
- display flex
- align-items center
- margin-bottom 2px
- white-space nowrap
- overflow hidden
-
- > .name
- margin 0
- padding 0
- overflow hidden
- text-overflow ellipsis
- font-size 1em
- color rgba(0, 0, 0, 0.9)
- font-weight bold
- transition all 0.1s ease
-
- > .username
- margin 0 8px
- color rgba(0, 0, 0, 0.5)
-
- > .mk-time
- margin 0 0 0 auto
- color rgba(0, 0, 0, 0.5)
- font-size 80%
-
- > .avatar
- float left
- width 54px
- height 54px
- margin 0 16px 0 0
- border-radius 8px
- transition all 0.1s ease
-
- > .body
-
- > .text
- display block
- margin 0 0 0 0
- padding 0
- overflow hidden
- overflow-wrap break-word
- font-size 1.1em
- color rgba(0, 0, 0, 0.8)
-
- .me
- color rgba(0, 0, 0, 0.4)
-
- > .image
- display block
- max-width 100%
- max-height 512px
-
- > .no-history
- margin 0
- padding 2em 1em
- text-align center
- color #999
- font-weight 500
-
- > .fetching
- margin 0
- padding 16px
- text-align center
- color #aaa
-
- > [data-fa]
- margin-right 4px
-
- // TODO: element base media query
- @media (max-width 400px)
- > .search
- > .result
- > .users
- > li
- padding 8px 16px
-
- > .history
- > a
- &:not([data-is-me]):not([data-is-read])
- > div
- background-image none
- border-left solid 4px #3aa2dc
-
- > div
- padding 16px
- font-size 14px
-
- > .avatar
- margin 0 12px 0 0
-
-</style>