iceshrimp/src/web/app/desktop/views/components/ui.header.notifications.vue

159 lines
3.3 KiB
Vue
Raw Normal View History

2018-02-12 21:10:16 +09:00
<template>
2018-02-20 22:53:34 +09:00
<div class="notifications">
2018-02-12 21:10:16 +09:00
<button :data-active="isOpen" @click="toggle" title="%i18n:desktop.tags.mk-ui-header-notifications.title%">
%fa:R bell%<template v-if="hasUnreadNotifications">%fa:circle%</template>
</button>
2018-02-20 22:53:34 +09:00
<div class="pop" v-if="isOpen">
2018-02-12 21:10:16 +09:00
<mk-notifications/>
</div>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import contains from '../../../common/scripts/contains';
export default Vue.extend({
data() {
return {
isOpen: false,
hasUnreadNotifications: false,
connection: null,
connectionId: null
};
},
mounted() {
2018-02-18 12:35:18 +09:00
if ((this as any).os.isSignedIn) {
this.connection = (this as any).os.stream.getConnection();
this.connectionId = (this as any).os.stream.use();
2018-02-12 21:10:16 +09:00
this.connection.on('read_all_notifications', this.onReadAllNotifications);
this.connection.on('unread_notification', this.onUnreadNotification);
// Fetch count of unread notifications
2018-02-18 12:35:18 +09:00
(this as any).api('notifications/get_unread_count').then(res => {
2018-02-12 21:10:16 +09:00
if (res.count > 0) {
this.hasUnreadNotifications = true;
}
});
}
},
beforeDestroy() {
2018-02-18 12:35:18 +09:00
if ((this as any).os.isSignedIn) {
2018-02-12 21:10:16 +09:00
this.connection.off('read_all_notifications', this.onReadAllNotifications);
this.connection.off('unread_notification', this.onUnreadNotification);
2018-02-18 12:35:18 +09:00
(this as any).os.stream.dispose(this.connectionId);
2018-02-12 21:10:16 +09:00
}
},
methods: {
onReadAllNotifications() {
this.hasUnreadNotifications = false;
},
onUnreadNotification() {
this.hasUnreadNotifications = true;
},
toggle() {
this.isOpen ? this.close() : this.open();
},
open() {
this.isOpen = true;
Array.from(document.querySelectorAll('body *')).forEach(el => {
el.addEventListener('mousedown', this.onMousedown);
});
},
close() {
this.isOpen = false;
Array.from(document.querySelectorAll('body *')).forEach(el => {
el.removeEventListener('mousedown', this.onMousedown);
});
},
onMousedown(e) {
e.preventDefault();
if (!contains(this.$el, e.target) && this.$el != e.target) this.close();
return false;
}
}
});
</script>
<style lang="stylus" scoped>
2018-03-03 13:47:55 +09:00
@import '~const.styl'
2018-02-20 22:53:34 +09:00
.notifications
2018-02-12 21:10:16 +09:00
> button
display block
margin 0
padding 0
width 32px
color #9eaba8
border none
background transparent
cursor pointer
*
pointer-events none
&:hover
&[data-active='true']
color darken(#9eaba8, 20%)
&:active
color darken(#9eaba8, 30%)
> [data-fa].bell
font-size 1.2em
line-height 48px
> [data-fa].circle
margin-left -5px
vertical-align super
font-size 10px
color $theme-color
2018-02-20 22:53:34 +09:00
> .pop
2018-02-12 21:10:16 +09:00
display block
position absolute
top 56px
right -72px
width 300px
background #fff
border-radius 4px
box-shadow 0 1px 4px rgba(0, 0, 0, 0.25)
&:before
content ""
pointer-events none
display block
position absolute
top -28px
right 74px
border-top solid 14px transparent
border-right solid 14px transparent
border-bottom solid 14px rgba(0, 0, 0, 0.1)
border-left solid 14px transparent
&:after
content ""
pointer-events none
display block
position absolute
top -27px
right 74px
border-top solid 14px transparent
border-right solid 14px transparent
border-bottom solid 14px #fff
border-left solid 14px transparent
2018-02-17 03:01:00 +09:00
> .mk-notifications
2018-02-12 21:10:16 +09:00
max-height 350px
font-size 1rem
overflow auto
</style>