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