user_settings.js (13695B)
1 import unescape from 'lodash/unescape'
2 import get from 'lodash/get'
3 import map from 'lodash/map'
4 import reject from 'lodash/reject'
5 import TabSwitcher from '../tab_switcher/tab_switcher.js'
6 import ImageCropper from '../image_cropper/image_cropper.vue'
7 import StyleSwitcher from '../style_switcher/style_switcher.vue'
8 import ScopeSelector from '../scope_selector/scope_selector.vue'
9 import fileSizeFormatService from '../../services/file_size_format/file_size_format.js'
10 import BlockCard from '../block_card/block_card.vue'
11 import MuteCard from '../mute_card/mute_card.vue'
12 import DomainMuteCard from '../domain_mute_card/domain_mute_card.vue'
13 import SelectableList from '../selectable_list/selectable_list.vue'
14 import ProgressButton from '../progress_button/progress_button.vue'
15 import EmojiInput from '../emoji_input/emoji_input.vue'
16 import suggestor from '../emoji_input/suggestor.js'
17 import Autosuggest from '../autosuggest/autosuggest.vue'
18 import Importer from '../importer/importer.vue'
19 import Exporter from '../exporter/exporter.vue'
20 import withSubscription from '../../hocs/with_subscription/with_subscription'
21 import Checkbox from '../checkbox/checkbox.vue'
22 import Mfa from './mfa.vue'
23
24 const BlockList = withSubscription({
25 fetch: (props, $store) => $store.dispatch('fetchBlocks'),
26 select: (props, $store) => get($store.state.users.currentUser, 'blockIds', []),
27 childPropName: 'items'
28 })(SelectableList)
29
30 const MuteList = withSubscription({
31 fetch: (props, $store) => $store.dispatch('fetchMutes'),
32 select: (props, $store) => get($store.state.users.currentUser, 'muteIds', []),
33 childPropName: 'items'
34 })(SelectableList)
35
36 const DomainMuteList = withSubscription({
37 fetch: (props, $store) => $store.dispatch('fetchDomainMutes'),
38 select: (props, $store) => get($store.state.users.currentUser, 'domainMutes', []),
39 childPropName: 'items'
40 })(SelectableList)
41
42 const UserSettings = {
43 data () {
44 return {
45 newEmail: '',
46 newName: this.$store.state.users.currentUser.name,
47 newBio: unescape(this.$store.state.users.currentUser.description),
48 newLocked: this.$store.state.users.currentUser.locked,
49 newNoRichText: this.$store.state.users.currentUser.no_rich_text,
50 newDefaultScope: this.$store.state.users.currentUser.default_scope,
51 hideFollows: this.$store.state.users.currentUser.hide_follows,
52 hideFollowers: this.$store.state.users.currentUser.hide_followers,
53 hideFollowsCount: this.$store.state.users.currentUser.hide_follows_count,
54 hideFollowersCount: this.$store.state.users.currentUser.hide_followers_count,
55 showRole: this.$store.state.users.currentUser.show_role,
56 role: this.$store.state.users.currentUser.role,
57 discoverable: this.$store.state.users.currentUser.discoverable,
58 allowFollowingMove: this.$store.state.users.currentUser.allow_following_move,
59 pickAvatarBtnVisible: true,
60 bannerUploading: false,
61 backgroundUploading: false,
62 banner: null,
63 bannerPreview: null,
64 background: null,
65 backgroundPreview: null,
66 bannerUploadError: null,
67 backgroundUploadError: null,
68 changeEmailError: false,
69 changeEmailPassword: '',
70 changedEmail: false,
71 deletingAccount: false,
72 deleteAccountConfirmPasswordInput: '',
73 deleteAccountError: false,
74 changePasswordInputs: [ '', '', '' ],
75 changedPassword: false,
76 changePasswordError: false,
77 activeTab: 'profile',
78 notificationSettings: this.$store.state.users.currentUser.notification_settings,
79 newDomainToMute: ''
80 }
81 },
82 created () {
83 this.$store.dispatch('fetchTokens')
84 },
85 components: {
86 StyleSwitcher,
87 ScopeSelector,
88 TabSwitcher,
89 ImageCropper,
90 BlockList,
91 MuteList,
92 DomainMuteList,
93 EmojiInput,
94 Autosuggest,
95 BlockCard,
96 MuteCard,
97 DomainMuteCard,
98 ProgressButton,
99 Importer,
100 Exporter,
101 Mfa,
102 Checkbox
103 },
104 computed: {
105 user () {
106 return this.$store.state.users.currentUser
107 },
108 emojiUserSuggestor () {
109 return suggestor({
110 emoji: [
111 ...this.$store.state.instance.emoji,
112 ...this.$store.state.instance.customEmoji
113 ],
114 users: this.$store.state.users.users,
115 updateUsersList: (input) => this.$store.dispatch('searchUsers', input)
116 })
117 },
118 emojiSuggestor () {
119 return suggestor({ emoji: [
120 ...this.$store.state.instance.emoji,
121 ...this.$store.state.instance.customEmoji
122 ] })
123 },
124 pleromaBackend () {
125 return this.$store.state.instance.pleromaBackend
126 },
127 minimalScopesMode () {
128 return this.$store.state.instance.minimalScopesMode
129 },
130 vis () {
131 return {
132 public: { selected: this.newDefaultScope === 'public' },
133 unlisted: { selected: this.newDefaultScope === 'unlisted' },
134 private: { selected: this.newDefaultScope === 'private' },
135 direct: { selected: this.newDefaultScope === 'direct' }
136 }
137 },
138 currentSaveStateNotice () {
139 return this.$store.state.interface.settings.currentSaveStateNotice
140 },
141 oauthTokens () {
142 return this.$store.state.oauthTokens.tokens.map(oauthToken => {
143 return {
144 id: oauthToken.id,
145 appName: oauthToken.app_name,
146 validUntil: new Date(oauthToken.valid_until).toLocaleDateString()
147 }
148 })
149 }
150 },
151 methods: {
152 updateProfile () {
153 this.$store.state.api.backendInteractor
154 .updateProfile({
155 params: {
156 note: this.newBio,
157 locked: this.newLocked,
158 // Backend notation.
159 /* eslint-disable camelcase */
160 display_name: this.newName,
161 default_scope: this.newDefaultScope,
162 no_rich_text: this.newNoRichText,
163 hide_follows: this.hideFollows,
164 hide_followers: this.hideFollowers,
165 discoverable: this.discoverable,
166 allow_following_move: this.allowFollowingMove,
167 hide_follows_count: this.hideFollowsCount,
168 hide_followers_count: this.hideFollowersCount,
169 show_role: this.showRole
170 /* eslint-enable camelcase */
171 } }).then((user) => {
172 this.$store.commit('addNewUsers', [user])
173 this.$store.commit('setCurrentUser', user)
174 })
175 },
176 updateNotificationSettings () {
177 this.$store.state.api.backendInteractor
178 .updateNotificationSettings({ settings: this.notificationSettings })
179 },
180 changeVis (visibility) {
181 this.newDefaultScope = visibility
182 },
183 uploadFile (slot, e) {
184 const file = e.target.files[0]
185 if (!file) { return }
186 if (file.size > this.$store.state.instance[slot + 'limit']) {
187 const filesize = fileSizeFormatService.fileSizeFormat(file.size)
188 const allowedsize = fileSizeFormatService.fileSizeFormat(this.$store.state.instance[slot + 'limit'])
189 this[slot + 'UploadError'] = this.$t('upload.error.base') + ' ' + this.$t('upload.error.file_too_big', { filesize: filesize.num, filesizeunit: filesize.unit, allowedsize: allowedsize.num, allowedsizeunit: allowedsize.unit })
190 return
191 }
192 // eslint-disable-next-line no-undef
193 const reader = new FileReader()
194 reader.onload = ({ target }) => {
195 const img = target.result
196 this[slot + 'Preview'] = img
197 this[slot] = file
198 }
199 reader.readAsDataURL(file)
200 },
201 submitAvatar (cropper, file) {
202 const that = this
203 return new Promise((resolve, reject) => {
204 function updateAvatar (avatar) {
205 that.$store.state.api.backendInteractor.updateAvatar({ avatar })
206 .then((user) => {
207 that.$store.commit('addNewUsers', [user])
208 that.$store.commit('setCurrentUser', user)
209 resolve()
210 })
211 .catch((err) => {
212 reject(new Error(that.$t('upload.error.base') + ' ' + err.message))
213 })
214 }
215
216 if (cropper) {
217 cropper.getCroppedCanvas().toBlob(updateAvatar, file.type)
218 } else {
219 updateAvatar(file)
220 }
221 })
222 },
223 clearUploadError (slot) {
224 this[slot + 'UploadError'] = null
225 },
226 submitBanner () {
227 if (!this.bannerPreview) { return }
228
229 this.bannerUploading = true
230 this.$store.state.api.backendInteractor.updateBanner({ banner: this.banner })
231 .then((user) => {
232 this.$store.commit('addNewUsers', [user])
233 this.$store.commit('setCurrentUser', user)
234 this.bannerPreview = null
235 })
236 .catch((err) => {
237 this.bannerUploadError = this.$t('upload.error.base') + ' ' + err.message
238 })
239 .then(() => { this.bannerUploading = false })
240 },
241 submitBg () {
242 if (!this.backgroundPreview) { return }
243 let background = this.background
244 this.backgroundUploading = true
245 this.$store.state.api.backendInteractor.updateBg({ background }).then((data) => {
246 if (!data.error) {
247 this.$store.commit('addNewUsers', [data])
248 this.$store.commit('setCurrentUser', data)
249 this.backgroundPreview = null
250 } else {
251 this.backgroundUploadError = this.$t('upload.error.base') + data.error
252 }
253 this.backgroundUploading = false
254 })
255 },
256 importFollows (file) {
257 return this.$store.state.api.backendInteractor.importFollows({ file })
258 .then((status) => {
259 if (!status) {
260 throw new Error('failed')
261 }
262 })
263 },
264 importBlocks (file) {
265 return this.$store.state.api.backendInteractor.importBlocks({ file })
266 .then((status) => {
267 if (!status) {
268 throw new Error('failed')
269 }
270 })
271 },
272 generateExportableUsersContent (users) {
273 // Get addresses
274 return users.map((user) => {
275 // check is it's a local user
276 if (user && user.is_local) {
277 // append the instance address
278 // eslint-disable-next-line no-undef
279 return user.screen_name + '@' + location.hostname
280 }
281 return user.screen_name
282 }).join('\n')
283 },
284 getFollowsContent () {
285 return this.$store.state.api.backendInteractor.exportFriends({ id: this.$store.state.users.currentUser.id })
286 .then(this.generateExportableUsersContent)
287 },
288 getBlocksContent () {
289 return this.$store.state.api.backendInteractor.fetchBlocks()
290 .then(this.generateExportableUsersContent)
291 },
292 confirmDelete () {
293 this.deletingAccount = true
294 },
295 deleteAccount () {
296 this.$store.state.api.backendInteractor.deleteAccount({ password: this.deleteAccountConfirmPasswordInput })
297 .then((res) => {
298 if (res.status === 'success') {
299 this.$store.dispatch('logout')
300 this.$router.push({ name: 'root' })
301 } else {
302 this.deleteAccountError = res.error
303 }
304 })
305 },
306 changePassword () {
307 const params = {
308 password: this.changePasswordInputs[0],
309 newPassword: this.changePasswordInputs[1],
310 newPasswordConfirmation: this.changePasswordInputs[2]
311 }
312 this.$store.state.api.backendInteractor.changePassword(params)
313 .then((res) => {
314 if (res.status === 'success') {
315 this.changedPassword = true
316 this.changePasswordError = false
317 this.logout()
318 } else {
319 this.changedPassword = false
320 this.changePasswordError = res.error
321 }
322 })
323 },
324 changeEmail () {
325 const params = {
326 email: this.newEmail,
327 password: this.changeEmailPassword
328 }
329 this.$store.state.api.backendInteractor.changeEmail(params)
330 .then((res) => {
331 if (res.status === 'success') {
332 this.changedEmail = true
333 this.changeEmailError = false
334 } else {
335 this.changedEmail = false
336 this.changeEmailError = res.error
337 }
338 })
339 },
340 activateTab (tabName) {
341 this.activeTab = tabName
342 },
343 logout () {
344 this.$store.dispatch('logout')
345 this.$router.replace('/')
346 },
347 revokeToken (id) {
348 if (window.confirm(`${this.$i18n.t('settings.revoke_token')}?`)) {
349 this.$store.dispatch('revokeToken', id)
350 }
351 },
352 filterUnblockedUsers (userIds) {
353 return reject(userIds, (userId) => {
354 const relationship = this.$store.getters.relationship(this.userId)
355 return relationship.blocking || userId === this.$store.state.users.currentUser.id
356 })
357 },
358 filterUnMutedUsers (userIds) {
359 return reject(userIds, (userId) => {
360 const relationship = this.$store.getters.relationship(this.userId)
361 return relationship.muting || userId === this.$store.state.users.currentUser.id
362 })
363 },
364 queryUserIds (query) {
365 return this.$store.dispatch('searchUsers', query)
366 .then((users) => map(users, 'id'))
367 },
368 blockUsers (ids) {
369 return this.$store.dispatch('blockUsers', ids)
370 },
371 unblockUsers (ids) {
372 return this.$store.dispatch('unblockUsers', ids)
373 },
374 muteUsers (ids) {
375 return this.$store.dispatch('muteUsers', ids)
376 },
377 unmuteUsers (ids) {
378 return this.$store.dispatch('unmuteUsers', ids)
379 },
380 unmuteDomains (domains) {
381 return this.$store.dispatch('unmuteDomains', domains)
382 },
383 muteDomain () {
384 return this.$store.dispatch('muteDomain', this.newDomainToMute)
385 .then(() => { this.newDomainToMute = '' })
386 },
387 identity (value) {
388 return value
389 }
390 }
391 }
392
393 export default UserSettings