summaryrefslogtreecommitdiff
path: root/src/web/app/desktop/views/components/ui.header.notifications.vue
blob: e829418d18b5e38b59905b7f2a2f9131240d9f3c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
<template>
<div class="notifications">
	<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>
	<div class="pop" v-if="isOpen">
		<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() {
		if ((this as any).os.isSignedIn) {
			this.connection = (this as any).os.stream.getConnection();
			this.connectionId = (this as any).os.stream.use();

			this.connection.on('read_all_notifications', this.onReadAllNotifications);
			this.connection.on('unread_notification', this.onUnreadNotification);

			// Fetch count of unread notifications
			(this as any).api('notifications/get_unread_count').then(res => {
				if (res.count > 0) {
					this.hasUnreadNotifications = true;
				}
			});
		}
	},
	beforeDestroy() {
		if ((this as any).os.isSignedIn) {
			this.connection.off('read_all_notifications', this.onReadAllNotifications);
			this.connection.off('unread_notification', this.onUnreadNotification);
			(this as any).os.stream.dispose(this.connectionId);
		}
	},
	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>
@import '~const.styl'

.notifications

	> 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

	> .pop
		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

		> .mk-notifications
			max-height 350px
			font-size 1rem
			overflow auto

</style>