summaryrefslogtreecommitdiff
path: root/src/client/app/common/views/components/follow-button.vue
blob: 71d3a63e4ccc9d4062dbc96f4e30ad9a547bf591 (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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
<template>
<button class="wfliddvnhxvyusikowhxozkyxyenqxqr"
	:class="{ wait, block, inline, mini, active: isFollowing || hasPendingFollowRequestFromYou }"
	@click="onClick"
	:disabled="wait"
	:inline="inline"
>
	<template v-if="!wait">
		<fa :icon="iconAndText[0]"/> <template v-if="!mini">{{ iconAndText[1] }}</template>
	</template>
	<template v-else><fa icon="spinner" pulse fixed-width/></template>
</button>
</template>

<script lang="ts">
import Vue from 'vue';
import i18n from '../../../i18n';

export default Vue.extend({
	i18n: i18n('common/views/components/follow-button.vue'),

	props: {
		user: {
			type: Object,
			required: true
		},
		block: {
			type: Boolean,
			required: false,
			default: false
		},
		inline: {
			type: Boolean,
			required: false,
			default: false
		},
		mini: {
			type: Boolean,
			required: false,
			default: false
		}
	},

	data() {
		return {
			isFollowing: this.user.isFollowing,
			hasPendingFollowRequestFromYou: this.user.hasPendingFollowRequestFromYou,
			wait: false,
			connection: null
		};
	},

	computed: {
		iconAndText(): any[] {
			return (
				(this.hasPendingFollowRequestFromYou && this.user.isLocked) ? ['hourglass-half', this.$t('request-pending')] :
				(this.hasPendingFollowRequestFromYou && !this.user.isLocked) ? ['spinner', this.$t('follow-processing')] :
				(this.isFollowing) ? ['minus', this.$t('following')] :
				(!this.isFollowing && this.user.isLocked) ? ['plus', this.$t('follow-request')] :
				(!this.isFollowing && !this.user.isLocked) ? ['plus', this.$t('follow')] :
				[]
			);
		}
	},

	mounted() {
		this.connection = this.$root.stream.useSharedConnection('main');

		this.connection.on('follow', this.onFollowChange);
		this.connection.on('unfollow', this.onFollowChange);
	},

	beforeDestroy() {
		this.connection.dispose();
	},

	methods: {
		onFollowChange(user) {
			if (user.id == this.user.id) {
				this.isFollowing = user.isFollowing;
				this.hasPendingFollowRequestFromYou = user.hasPendingFollowRequestFromYou;
			}
		},

		async onClick() {
			this.wait = true;

			try {
				if (this.isFollowing) {
					await this.$root.api('following/delete', {
						userId: this.user.id
					});
				} else {
					if (this.hasPendingFollowRequestFromYou) {
						await this.$root.api('following/requests/cancel', {
							userId: this.user.id
						});
					} else if (this.user.isLocked) {
						await this.$root.api('following/create', {
							userId: this.user.id
						});
						this.hasPendingFollowRequestFromYou = true;
					} else {
						await this.$root.api('following/create', {
							userId: this.user.id
						});
						this.hasPendingFollowRequestFromYou = true;
					}
				}
			} catch (e) {
				console.error(e);
			} finally {
				this.wait = false;
			}
		}
	}
});
</script>

<style lang="stylus" scoped>
.wfliddvnhxvyusikowhxozkyxyenqxqr
	display block
	user-select none
	cursor pointer
	padding 0 16px
	margin 0
	min-width 100px
	line-height 36px
	font-size 14px
	font-weight bold
	color var(--primary)
	background transparent
	outline none
	border solid 1px var(--primary)
	border-radius 36px

	&.inline
		display inline-block

	&.mini
		padding 0
		min-width 0
		width 32px
		height 32px
		font-size 16px
		border-radius 4px
		line-height 32px

		&:focus
			&:after
				border-radius 8px

	&.block
		width 100%

	&:focus
		&:after
			content ""
			pointer-events none
			position absolute
			top -5px
			right -5px
			bottom -5px
			left -5px
			border 2px solid var(--primaryAlpha03)
			border-radius 36px

	&:hover
		background var(--primaryAlpha01)

	&:active
		background var(--primaryAlpha02)

	&.active
		color var(--primaryForeground)
		background var(--primary)

		&:hover
			background var(--primaryLighten10)
			border-color var(--primaryLighten10)

		&:active
			background var(--primaryDarken10)
			border-color var(--primaryDarken10)

	&.wait
		cursor wait !important
		opacity 0.7

	*
		pointer-events none

</style>