forked from AkkomaGang/akkoma-fe
Merge branch 'develop' into 'brendenbice1222/pleroma-fe-issues/pleroma-fe-202-show-boosted-users'
# Conflicts: # src/services/api/api.service.js
This commit is contained in:
commit
b1bd5bd08e
22 changed files with 373 additions and 281 deletions
|
@ -44,14 +44,15 @@
|
||||||
width: 16px;
|
width: 16px;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&-value {
|
&-user-name-value,
|
||||||
display: inline-block;
|
&-screen-name {
|
||||||
max-width: 100%;
|
display: inline-block;
|
||||||
overflow: hidden;
|
max-width: 100%;
|
||||||
white-space: nowrap;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
white-space: nowrap;
|
||||||
}
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-expanded-content {
|
&-expanded-content {
|
||||||
|
|
48
src/components/exporter/exporter.js
Normal file
48
src/components/exporter/exporter.js
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
const Exporter = {
|
||||||
|
props: {
|
||||||
|
getContent: {
|
||||||
|
type: Function,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
filename: {
|
||||||
|
type: String,
|
||||||
|
default: 'export.csv'
|
||||||
|
},
|
||||||
|
exportButtonLabel: {
|
||||||
|
type: String,
|
||||||
|
default () {
|
||||||
|
return this.$t('exporter.export')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
processingMessage: {
|
||||||
|
type: String,
|
||||||
|
default () {
|
||||||
|
return this.$t('exporter.processing')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
processing: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
process () {
|
||||||
|
this.processing = true
|
||||||
|
this.getContent()
|
||||||
|
.then((content) => {
|
||||||
|
const fileToDownload = document.createElement('a')
|
||||||
|
fileToDownload.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(content))
|
||||||
|
fileToDownload.setAttribute('download', this.filename)
|
||||||
|
fileToDownload.style.display = 'none'
|
||||||
|
document.body.appendChild(fileToDownload)
|
||||||
|
fileToDownload.click()
|
||||||
|
document.body.removeChild(fileToDownload)
|
||||||
|
// Add delay before hiding processing state since browser takes some time to handle file download
|
||||||
|
setTimeout(() => { this.processing = false }, 2000)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Exporter
|
20
src/components/exporter/exporter.vue
Normal file
20
src/components/exporter/exporter.vue
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<template>
|
||||||
|
<div class="exporter">
|
||||||
|
<div v-if="processing">
|
||||||
|
<i class="icon-spin4 animate-spin exporter-processing"></i>
|
||||||
|
<span>{{processingMessage}}</span>
|
||||||
|
</div>
|
||||||
|
<button class="btn btn-default" @click="process" v-else>{{exportButtonLabel}}</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./exporter.js"></script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.exporter {
|
||||||
|
&-processing {
|
||||||
|
font-size: 1.5em;
|
||||||
|
margin: 0.25em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -10,8 +10,7 @@ const FollowCard = {
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
inProgress: false,
|
inProgress: false,
|
||||||
requestSent: false,
|
requestSent: false
|
||||||
updated: false
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
@ -19,10 +18,8 @@ const FollowCard = {
|
||||||
RemoteFollow
|
RemoteFollow
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
isMe () { return this.$store.state.users.currentUser.id === this.user.id },
|
isMe () {
|
||||||
following () { return this.updated ? this.updated.following : this.user.following },
|
return this.$store.state.users.currentUser.id === this.user.id
|
||||||
showFollow () {
|
|
||||||
return !this.following || this.updated && !this.updated.following
|
|
||||||
},
|
},
|
||||||
loggedIn () {
|
loggedIn () {
|
||||||
return this.$store.state.users.currentUser
|
return this.$store.state.users.currentUser
|
||||||
|
@ -31,17 +28,15 @@ const FollowCard = {
|
||||||
methods: {
|
methods: {
|
||||||
followUser () {
|
followUser () {
|
||||||
this.inProgress = true
|
this.inProgress = true
|
||||||
requestFollow(this.user, this.$store).then(({ sent, updated }) => {
|
requestFollow(this.user, this.$store).then(({ sent }) => {
|
||||||
this.inProgress = false
|
this.inProgress = false
|
||||||
this.requestSent = sent
|
this.requestSent = sent
|
||||||
this.updated = updated
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
unfollowUser () {
|
unfollowUser () {
|
||||||
this.inProgress = true
|
this.inProgress = true
|
||||||
requestUnfollow(this.user, this.$store).then(({ updated }) => {
|
requestUnfollow(this.user, this.$store).then(() => {
|
||||||
this.inProgress = false
|
this.inProgress = false
|
||||||
this.updated = updated
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,34 +4,38 @@
|
||||||
<span class="faint" v-if="!noFollowsYou && user.follows_you">
|
<span class="faint" v-if="!noFollowsYou && user.follows_you">
|
||||||
{{ isMe ? $t('user_card.its_you') : $t('user_card.follows_you') }}
|
{{ isMe ? $t('user_card.its_you') : $t('user_card.follows_you') }}
|
||||||
</span>
|
</span>
|
||||||
<div class="follow-card-follow-button" v-if="showFollow && !loggedIn">
|
<template v-if="!loggedIn">
|
||||||
<RemoteFollow :user="user" />
|
<div class="follow-card-follow-button" v-if="!user.following">
|
||||||
</div>
|
<RemoteFollow :user="user" />
|
||||||
<button
|
</div>
|
||||||
v-if="showFollow && loggedIn"
|
</template>
|
||||||
class="btn btn-default follow-card-follow-button"
|
<template v-else>
|
||||||
@click="followUser"
|
<button
|
||||||
:disabled="inProgress"
|
v-if="!user.following"
|
||||||
:title="requestSent ? $t('user_card.follow_again') : ''"
|
class="btn btn-default follow-card-follow-button"
|
||||||
>
|
@click="followUser"
|
||||||
<template v-if="inProgress">
|
:disabled="inProgress"
|
||||||
{{ $t('user_card.follow_progress') }}
|
:title="requestSent ? $t('user_card.follow_again') : ''"
|
||||||
</template>
|
>
|
||||||
<template v-else-if="requestSent">
|
<template v-if="inProgress">
|
||||||
{{ $t('user_card.follow_sent') }}
|
{{ $t('user_card.follow_progress') }}
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else-if="requestSent">
|
||||||
{{ $t('user_card.follow') }}
|
{{ $t('user_card.follow_sent') }}
|
||||||
</template>
|
</template>
|
||||||
</button>
|
<template v-else>
|
||||||
<button v-if="following" class="btn btn-default follow-card-follow-button pressed" @click="unfollowUser" :disabled="inProgress">
|
{{ $t('user_card.follow') }}
|
||||||
<template v-if="inProgress">
|
</template>
|
||||||
{{ $t('user_card.follow_progress') }}
|
</button>
|
||||||
</template>
|
<button v-else class="btn btn-default follow-card-follow-button pressed" @click="unfollowUser" :disabled="inProgress">
|
||||||
<template v-else>
|
<template v-if="inProgress">
|
||||||
{{ $t('user_card.follow_unfollow') }}
|
{{ $t('user_card.follow_progress') }}
|
||||||
</template>
|
</template>
|
||||||
</button>
|
<template v-else>
|
||||||
|
{{ $t('user_card.follow_unfollow') }}
|
||||||
|
</template>
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</basic-user-card>
|
</basic-user-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -70,22 +70,10 @@ const ImageCropper = {
|
||||||
this.dataUrl = undefined
|
this.dataUrl = undefined
|
||||||
this.$emit('close')
|
this.$emit('close')
|
||||||
},
|
},
|
||||||
submit () {
|
submit (cropping = true) {
|
||||||
this.submitting = true
|
this.submitting = true
|
||||||
this.avatarUploadError = null
|
this.avatarUploadError = null
|
||||||
this.submitHandler(this.cropper, this.file)
|
this.submitHandler(cropping && this.cropper, this.file)
|
||||||
.then(() => this.destroy())
|
|
||||||
.catch((err) => {
|
|
||||||
this.submitError = err
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
this.submitting = false
|
|
||||||
})
|
|
||||||
},
|
|
||||||
submitWithoutCropping () {
|
|
||||||
this.submitting = true
|
|
||||||
this.avatarUploadError = null
|
|
||||||
this.submitHandler(false, this.dataUrl)
|
|
||||||
.then(() => this.destroy())
|
.then(() => this.destroy())
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
this.submitError = err
|
this.submitError = err
|
||||||
|
|
|
@ -5,9 +5,9 @@
|
||||||
<img ref="img" :src="dataUrl" alt="" @load.stop="createCropper" />
|
<img ref="img" :src="dataUrl" alt="" @load.stop="createCropper" />
|
||||||
</div>
|
</div>
|
||||||
<div class="image-cropper-buttons-wrapper">
|
<div class="image-cropper-buttons-wrapper">
|
||||||
<button class="btn" type="button" :disabled="submitting" @click="submit" v-text="saveText"></button>
|
<button class="btn" type="button" :disabled="submitting" @click="submit()" v-text="saveText"></button>
|
||||||
<button class="btn" type="button" :disabled="submitting" @click="destroy" v-text="cancelText"></button>
|
<button class="btn" type="button" :disabled="submitting" @click="destroy" v-text="cancelText"></button>
|
||||||
<button class="btn" type="button" :disabled="submitting" @click="submitWithoutCropping" v-text="saveWithoutCroppingText"></button>
|
<button class="btn" type="button" :disabled="submitting" @click="submit(false)" v-text="saveWithoutCroppingText"></button>
|
||||||
<i class="icon-spin4 animate-spin" v-if="submitting"></i>
|
<i class="icon-spin4 animate-spin" v-if="submitting"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="alert error" v-if="submitError">
|
<div class="alert error" v-if="submitError">
|
||||||
|
|
53
src/components/importer/importer.js
Normal file
53
src/components/importer/importer.js
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
const Importer = {
|
||||||
|
props: {
|
||||||
|
submitHandler: {
|
||||||
|
type: Function,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
submitButtonLabel: {
|
||||||
|
type: String,
|
||||||
|
default () {
|
||||||
|
return this.$t('importer.submit')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
successMessage: {
|
||||||
|
type: String,
|
||||||
|
default () {
|
||||||
|
return this.$t('importer.success')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
errorMessage: {
|
||||||
|
type: String,
|
||||||
|
default () {
|
||||||
|
return this.$t('importer.error')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
file: null,
|
||||||
|
error: false,
|
||||||
|
success: false,
|
||||||
|
submitting: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
change () {
|
||||||
|
this.file = this.$refs.input.files[0]
|
||||||
|
},
|
||||||
|
submit () {
|
||||||
|
this.dismiss()
|
||||||
|
this.submitting = true
|
||||||
|
this.submitHandler(this.file)
|
||||||
|
.then(() => { this.success = true })
|
||||||
|
.catch(() => { this.error = true })
|
||||||
|
.finally(() => { this.submitting = false })
|
||||||
|
},
|
||||||
|
dismiss () {
|
||||||
|
this.success = false
|
||||||
|
this.error = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Importer
|
28
src/components/importer/importer.vue
Normal file
28
src/components/importer/importer.vue
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
<template>
|
||||||
|
<div class="importer">
|
||||||
|
<form>
|
||||||
|
<input type="file" ref="input" v-on:change="change" />
|
||||||
|
</form>
|
||||||
|
<i class="icon-spin4 animate-spin importer-uploading" v-if="submitting"></i>
|
||||||
|
<button class="btn btn-default" v-else @click="submit">{{submitButtonLabel}}</button>
|
||||||
|
<div v-if="success">
|
||||||
|
<i class="icon-cross" @click="dismiss"></i>
|
||||||
|
<p>{{successMessage}}</p>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="error">
|
||||||
|
<i class="icon-cross" @click="dismiss"></i>
|
||||||
|
<p>{{errorMessage}}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./importer.js"></script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.importer {
|
||||||
|
&-uploading {
|
||||||
|
font-size: 1.5em;
|
||||||
|
margin: 0.25em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -31,6 +31,10 @@
|
||||||
&-item-inner {
|
&-item-inner {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
|
> * {
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-item-selected-inner {
|
&-item-selected-inner {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import FollowCard from '../follow_card/follow_card.vue'
|
import FollowCard from '../follow_card/follow_card.vue'
|
||||||
import userSearchApi from '../../services/new_api/user_search.js'
|
import map from 'lodash/map'
|
||||||
|
|
||||||
const userSearch = {
|
const userSearch = {
|
||||||
components: {
|
components: {
|
||||||
FollowCard
|
FollowCard
|
||||||
|
@ -10,10 +11,15 @@ const userSearch = {
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
username: '',
|
username: '',
|
||||||
users: [],
|
userIds: [],
|
||||||
loading: false
|
loading: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
users () {
|
||||||
|
return this.userIds.map(userId => this.$store.getters.findUser(userId))
|
||||||
|
}
|
||||||
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
this.search(this.query)
|
this.search(this.query)
|
||||||
},
|
},
|
||||||
|
@ -33,10 +39,10 @@ const userSearch = {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.loading = true
|
this.loading = true
|
||||||
userSearchApi.search({query, store: this.$store})
|
this.$store.dispatch('searchUsers', query)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
this.users = res
|
this.userIds = map(res, 'id')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,8 @@ import SelectableList from '../selectable_list/selectable_list.vue'
|
||||||
import ProgressButton from '../progress_button/progress_button.vue'
|
import ProgressButton from '../progress_button/progress_button.vue'
|
||||||
import EmojiInput from '../emoji-input/emoji-input.vue'
|
import EmojiInput from '../emoji-input/emoji-input.vue'
|
||||||
import Autosuggest from '../autosuggest/autosuggest.vue'
|
import Autosuggest from '../autosuggest/autosuggest.vue'
|
||||||
|
import Importer from '../importer/importer.vue'
|
||||||
|
import Exporter from '../exporter/exporter.vue'
|
||||||
import withSubscription from '../../hocs/with_subscription/with_subscription'
|
import withSubscription from '../../hocs/with_subscription/with_subscription'
|
||||||
import userSearchApi from '../../services/new_api/user_search.js'
|
import userSearchApi from '../../services/new_api/user_search.js'
|
||||||
|
|
||||||
|
@ -40,14 +42,9 @@ const UserSettings = {
|
||||||
hideFollowers: this.$store.state.users.currentUser.hide_followers,
|
hideFollowers: this.$store.state.users.currentUser.hide_followers,
|
||||||
showRole: this.$store.state.users.currentUser.show_role,
|
showRole: this.$store.state.users.currentUser.show_role,
|
||||||
role: this.$store.state.users.currentUser.role,
|
role: this.$store.state.users.currentUser.role,
|
||||||
followList: null,
|
|
||||||
followImportError: false,
|
|
||||||
followsImported: false,
|
|
||||||
enableFollowsExport: true,
|
|
||||||
pickAvatarBtnVisible: true,
|
pickAvatarBtnVisible: true,
|
||||||
bannerUploading: false,
|
bannerUploading: false,
|
||||||
backgroundUploading: false,
|
backgroundUploading: false,
|
||||||
followListUploading: false,
|
|
||||||
bannerPreview: null,
|
bannerPreview: null,
|
||||||
backgroundPreview: null,
|
backgroundPreview: null,
|
||||||
bannerUploadError: null,
|
bannerUploadError: null,
|
||||||
|
@ -75,7 +72,9 @@ const UserSettings = {
|
||||||
Autosuggest,
|
Autosuggest,
|
||||||
BlockCard,
|
BlockCard,
|
||||||
MuteCard,
|
MuteCard,
|
||||||
ProgressButton
|
ProgressButton,
|
||||||
|
Importer,
|
||||||
|
Exporter
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
user () {
|
user () {
|
||||||
|
@ -110,37 +109,23 @@ const UserSettings = {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
updateProfile () {
|
updateProfile () {
|
||||||
const name = this.newName
|
|
||||||
const description = this.newBio
|
|
||||||
const locked = this.newLocked
|
|
||||||
// Backend notation.
|
|
||||||
/* eslint-disable camelcase */
|
|
||||||
const default_scope = this.newDefaultScope
|
|
||||||
const no_rich_text = this.newNoRichText
|
|
||||||
const hide_follows = this.hideFollows
|
|
||||||
const hide_followers = this.hideFollowers
|
|
||||||
const show_role = this.showRole
|
|
||||||
|
|
||||||
/* eslint-enable camelcase */
|
|
||||||
this.$store.state.api.backendInteractor
|
this.$store.state.api.backendInteractor
|
||||||
.updateProfile({
|
.updateProfile({
|
||||||
params: {
|
params: {
|
||||||
name,
|
note: this.newBio,
|
||||||
description,
|
locked: this.newLocked,
|
||||||
locked,
|
|
||||||
// Backend notation.
|
// Backend notation.
|
||||||
/* eslint-disable camelcase */
|
/* eslint-disable camelcase */
|
||||||
default_scope,
|
display_name: this.newName,
|
||||||
no_rich_text,
|
default_scope: this.newDefaultScope,
|
||||||
hide_follows,
|
no_rich_text: this.newNoRichText,
|
||||||
hide_followers,
|
hide_follows: this.hideFollows,
|
||||||
show_role
|
hide_followers: this.hideFollowers,
|
||||||
|
show_role: this.showRole
|
||||||
/* eslint-enable camelcase */
|
/* eslint-enable camelcase */
|
||||||
}}).then((user) => {
|
}}).then((user) => {
|
||||||
if (!user.error) {
|
this.$store.commit('addNewUsers', [user])
|
||||||
this.$store.commit('addNewUsers', [user])
|
this.$store.commit('setCurrentUser', user)
|
||||||
this.$store.commit('setCurrentUser', user)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
changeVis (visibility) {
|
changeVis (visibility) {
|
||||||
|
@ -160,23 +145,29 @@ const UserSettings = {
|
||||||
reader.onload = ({target}) => {
|
reader.onload = ({target}) => {
|
||||||
const img = target.result
|
const img = target.result
|
||||||
this[slot + 'Preview'] = img
|
this[slot + 'Preview'] = img
|
||||||
|
this[slot] = file
|
||||||
}
|
}
|
||||||
reader.readAsDataURL(file)
|
reader.readAsDataURL(file)
|
||||||
},
|
},
|
||||||
submitAvatar (cropper, file) {
|
submitAvatar (cropper, file) {
|
||||||
let img
|
const that = this
|
||||||
if (cropper) {
|
return new Promise((resolve, reject) => {
|
||||||
img = cropper.getCroppedCanvas().toDataURL(file.type)
|
function updateAvatar (avatar) {
|
||||||
} else {
|
that.$store.state.api.backendInteractor.updateAvatar({ avatar })
|
||||||
img = file
|
.then((user) => {
|
||||||
}
|
that.$store.commit('addNewUsers', [user])
|
||||||
|
that.$store.commit('setCurrentUser', user)
|
||||||
|
resolve()
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
reject(new Error(that.$t('upload.error.base') + ' ' + err.message))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return this.$store.state.api.backendInteractor.updateAvatar({ params: { img } }).then((user) => {
|
if (cropper) {
|
||||||
if (!user.error) {
|
cropper.getCroppedCanvas().toBlob(updateAvatar, file.type)
|
||||||
this.$store.commit('addNewUsers', [user])
|
|
||||||
this.$store.commit('setCurrentUser', user)
|
|
||||||
} else {
|
} else {
|
||||||
throw new Error(this.$t('upload.error.base') + user.error)
|
updateAvatar(file)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
@ -186,30 +177,17 @@ const UserSettings = {
|
||||||
submitBanner () {
|
submitBanner () {
|
||||||
if (!this.bannerPreview) { return }
|
if (!this.bannerPreview) { return }
|
||||||
|
|
||||||
let banner = this.bannerPreview
|
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
let imginfo = new Image()
|
|
||||||
/* eslint-disable camelcase */
|
|
||||||
let offset_top, offset_left, width, height
|
|
||||||
imginfo.src = banner
|
|
||||||
width = imginfo.width
|
|
||||||
height = imginfo.height
|
|
||||||
offset_top = 0
|
|
||||||
offset_left = 0
|
|
||||||
this.bannerUploading = true
|
this.bannerUploading = true
|
||||||
this.$store.state.api.backendInteractor.updateBanner({params: {banner, offset_top, offset_left, width, height}}).then((data) => {
|
this.$store.state.api.backendInteractor.updateBanner({banner: this.banner})
|
||||||
if (!data.error) {
|
.then((user) => {
|
||||||
let clone = JSON.parse(JSON.stringify(this.$store.state.users.currentUser))
|
this.$store.commit('addNewUsers', [user])
|
||||||
clone.cover_photo = data.url
|
this.$store.commit('setCurrentUser', user)
|
||||||
this.$store.commit('addNewUsers', [clone])
|
|
||||||
this.$store.commit('setCurrentUser', clone)
|
|
||||||
this.bannerPreview = null
|
this.bannerPreview = null
|
||||||
} else {
|
})
|
||||||
this.bannerUploadError = this.$t('upload.error.base') + data.error
|
.catch((err) => {
|
||||||
}
|
this.bannerUploadError = this.$t('upload.error.base') + ' ' + err.message
|
||||||
this.bannerUploading = false
|
})
|
||||||
})
|
.then(() => { this.bannerUploading = false })
|
||||||
/* eslint-enable camelcase */
|
|
||||||
},
|
},
|
||||||
submitBg () {
|
submitBg () {
|
||||||
if (!this.backgroundPreview) { return }
|
if (!this.backgroundPreview) { return }
|
||||||
|
@ -236,62 +214,41 @@ const UserSettings = {
|
||||||
this.backgroundUploading = false
|
this.backgroundUploading = false
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
importFollows () {
|
importFollows (file) {
|
||||||
this.followListUploading = true
|
return this.$store.state.api.backendInteractor.importFollows(file)
|
||||||
const followList = this.followList
|
|
||||||
this.$store.state.api.backendInteractor.followImport({params: followList})
|
|
||||||
.then((status) => {
|
.then((status) => {
|
||||||
if (status) {
|
if (!status) {
|
||||||
this.followsImported = true
|
throw new Error('failed')
|
||||||
} else {
|
|
||||||
this.followImportError = true
|
|
||||||
}
|
}
|
||||||
this.followListUploading = false
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
/* This function takes an Array of Users
|
importBlocks (file) {
|
||||||
* and outputs a file with all the addresses for the user to download
|
return this.$store.state.api.backendInteractor.importBlocks(file)
|
||||||
*/
|
.then((status) => {
|
||||||
exportPeople (users, filename) {
|
if (!status) {
|
||||||
// Get all the friends addresses
|
throw new Error('failed')
|
||||||
var UserAddresses = users.map(function (user) {
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
generateExportableUsersContent (users) {
|
||||||
|
// Get addresses
|
||||||
|
return users.map((user) => {
|
||||||
// check is it's a local user
|
// check is it's a local user
|
||||||
if (user && user.is_local) {
|
if (user && user.is_local) {
|
||||||
// append the instance address
|
// append the instance address
|
||||||
// eslint-disable-next-line no-undef
|
// eslint-disable-next-line no-undef
|
||||||
user.screen_name += '@' + location.hostname
|
return user.screen_name + '@' + location.hostname
|
||||||
}
|
}
|
||||||
return user.screen_name
|
return user.screen_name
|
||||||
}).join('\n')
|
}).join('\n')
|
||||||
// Make the user download the file
|
|
||||||
var fileToDownload = document.createElement('a')
|
|
||||||
fileToDownload.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(UserAddresses))
|
|
||||||
fileToDownload.setAttribute('download', filename)
|
|
||||||
fileToDownload.style.display = 'none'
|
|
||||||
document.body.appendChild(fileToDownload)
|
|
||||||
fileToDownload.click()
|
|
||||||
document.body.removeChild(fileToDownload)
|
|
||||||
},
|
},
|
||||||
exportFollows () {
|
getFollowsContent () {
|
||||||
this.enableFollowsExport = false
|
return this.$store.state.api.backendInteractor.exportFriends({ id: this.$store.state.users.currentUser.id })
|
||||||
this.$store.state.api.backendInteractor
|
.then(this.generateExportableUsersContent)
|
||||||
.exportFriends({
|
|
||||||
id: this.$store.state.users.currentUser.id
|
|
||||||
})
|
|
||||||
.then((friendList) => {
|
|
||||||
this.exportPeople(friendList, 'friends.csv')
|
|
||||||
setTimeout(() => { this.enableFollowsExport = true }, 2000)
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
followListChange () {
|
getBlocksContent () {
|
||||||
// eslint-disable-next-line no-undef
|
return this.$store.state.api.backendInteractor.fetchBlocks()
|
||||||
let formData = new FormData()
|
.then(this.generateExportableUsersContent)
|
||||||
formData.append('list', this.$refs.followlist.files[0])
|
|
||||||
this.followList = formData
|
|
||||||
},
|
|
||||||
dismissImported () {
|
|
||||||
this.followsImported = false
|
|
||||||
this.followImportError = false
|
|
||||||
},
|
},
|
||||||
confirmDelete () {
|
confirmDelete () {
|
||||||
this.deletingAccount = true
|
this.deletingAccount = true
|
||||||
|
|
|
@ -171,26 +171,20 @@
|
||||||
<div class="setting-item">
|
<div class="setting-item">
|
||||||
<h2>{{$t('settings.follow_import')}}</h2>
|
<h2>{{$t('settings.follow_import')}}</h2>
|
||||||
<p>{{$t('settings.import_followers_from_a_csv_file')}}</p>
|
<p>{{$t('settings.import_followers_from_a_csv_file')}}</p>
|
||||||
<form>
|
<Importer :submitHandler="importFollows" :successMessage="$t('settings.follows_imported')" :errorMessage="$t('settings.follow_import_error')" />
|
||||||
<input type="file" ref="followlist" v-on:change="followListChange" />
|
|
||||||
</form>
|
|
||||||
<i class=" icon-spin4 animate-spin uploading" v-if="followListUploading"></i>
|
|
||||||
<button class="btn btn-default" v-else @click="importFollows">{{$t('general.submit')}}</button>
|
|
||||||
<div v-if="followsImported">
|
|
||||||
<i class="icon-cross" @click="dismissImported"></i>
|
|
||||||
<p>{{$t('settings.follows_imported')}}</p>
|
|
||||||
</div>
|
|
||||||
<div v-else-if="followImportError">
|
|
||||||
<i class="icon-cross" @click="dismissImported"></i>
|
|
||||||
<p>{{$t('settings.follow_import_error')}}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-item" v-if="enableFollowsExport">
|
<div class="setting-item">
|
||||||
<h2>{{$t('settings.follow_export')}}</h2>
|
<h2>{{$t('settings.follow_export')}}</h2>
|
||||||
<button class="btn btn-default" @click="exportFollows">{{$t('settings.follow_export_button')}}</button>
|
<Exporter :getContent="getFollowsContent" filename="friends.csv" :exportButtonLabel="$t('settings.follow_export_button')" />
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-item" v-else>
|
<div class="setting-item">
|
||||||
<h2>{{$t('settings.follow_export_processing')}}</h2>
|
<h2>{{$t('settings.block_import')}}</h2>
|
||||||
|
<p>{{$t('settings.import_blocks_from_a_csv_file')}}</p>
|
||||||
|
<Importer :submitHandler="importBlocks" :successMessage="$t('settings.blocks_imported')" :errorMessage="$t('settings.block_import_error')" />
|
||||||
|
</div>
|
||||||
|
<div class="setting-item">
|
||||||
|
<h2>{{$t('settings.block_export')}}</h2>
|
||||||
|
<Exporter :getContent="getBlocksContent" filename="blocks.csv" :exportButtonLabel="$t('settings.block_export_button')" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,8 @@
|
||||||
"content_type": {
|
"content_type": {
|
||||||
"text/plain": "Prostý text",
|
"text/plain": "Prostý text",
|
||||||
"text/html": "HTML",
|
"text/html": "HTML",
|
||||||
"text/markdown": "Markdown"
|
"text/markdown": "Markdown",
|
||||||
|
"text/bbcode": "BBCode"
|
||||||
},
|
},
|
||||||
"content_warning": "Předmět (volitelný)",
|
"content_warning": "Předmět (volitelný)",
|
||||||
"default": "Právě jsem přistál v L.A.",
|
"default": "Právě jsem přistál v L.A.",
|
||||||
|
|
|
@ -2,6 +2,10 @@
|
||||||
"chat": {
|
"chat": {
|
||||||
"title": "Chat"
|
"title": "Chat"
|
||||||
},
|
},
|
||||||
|
"exporter": {
|
||||||
|
"export": "Export",
|
||||||
|
"processing": "Processing, you'll soon be asked to download your file"
|
||||||
|
},
|
||||||
"features_panel": {
|
"features_panel": {
|
||||||
"chat": "Chat",
|
"chat": "Chat",
|
||||||
"gopher": "Gopher",
|
"gopher": "Gopher",
|
||||||
|
@ -31,6 +35,11 @@
|
||||||
"save_without_cropping": "Save without cropping",
|
"save_without_cropping": "Save without cropping",
|
||||||
"cancel": "Cancel"
|
"cancel": "Cancel"
|
||||||
},
|
},
|
||||||
|
"importer": {
|
||||||
|
"submit": "Submit",
|
||||||
|
"success": "Imported successfully.",
|
||||||
|
"error": "An error occured while importing this file."
|
||||||
|
},
|
||||||
"login": {
|
"login": {
|
||||||
"login": "Log in",
|
"login": "Log in",
|
||||||
"description": "Log in with OAuth",
|
"description": "Log in with OAuth",
|
||||||
|
@ -77,7 +86,8 @@
|
||||||
"content_type": {
|
"content_type": {
|
||||||
"text/plain": "Plain text",
|
"text/plain": "Plain text",
|
||||||
"text/html": "HTML",
|
"text/html": "HTML",
|
||||||
"text/markdown": "Markdown"
|
"text/markdown": "Markdown",
|
||||||
|
"text/bbcode": "BBCode"
|
||||||
},
|
},
|
||||||
"content_warning": "Subject (optional)",
|
"content_warning": "Subject (optional)",
|
||||||
"default": "Just landed in L.A.",
|
"default": "Just landed in L.A.",
|
||||||
|
@ -125,6 +135,11 @@
|
||||||
"avatarRadius": "Avatars",
|
"avatarRadius": "Avatars",
|
||||||
"background": "Background",
|
"background": "Background",
|
||||||
"bio": "Bio",
|
"bio": "Bio",
|
||||||
|
"block_export": "Block export",
|
||||||
|
"block_export_button": "Export your blocks to a csv file",
|
||||||
|
"block_import": "Block import",
|
||||||
|
"block_import_error": "Error importing blocks",
|
||||||
|
"blocks_imported": "Blocks imported! Processing them will take a while.",
|
||||||
"blocks_tab": "Blocks",
|
"blocks_tab": "Blocks",
|
||||||
"btnRadius": "Buttons",
|
"btnRadius": "Buttons",
|
||||||
"cBlue": "Blue (Reply, follow)",
|
"cBlue": "Blue (Reply, follow)",
|
||||||
|
@ -152,7 +167,6 @@
|
||||||
"filtering_explanation": "All statuses containing these words will be muted, one per line",
|
"filtering_explanation": "All statuses containing these words will be muted, one per line",
|
||||||
"follow_export": "Follow export",
|
"follow_export": "Follow export",
|
||||||
"follow_export_button": "Export your follows to a csv file",
|
"follow_export_button": "Export your follows to a csv file",
|
||||||
"follow_export_processing": "Processing, you'll soon be asked to download your file",
|
|
||||||
"follow_import": "Follow import",
|
"follow_import": "Follow import",
|
||||||
"follow_import_error": "Error importing followers",
|
"follow_import_error": "Error importing followers",
|
||||||
"follows_imported": "Follows imported! Processing them will take a while.",
|
"follows_imported": "Follows imported! Processing them will take a while.",
|
||||||
|
@ -168,6 +182,7 @@
|
||||||
"hide_post_stats": "Hide post statistics (e.g. the number of favorites)",
|
"hide_post_stats": "Hide post statistics (e.g. the number of favorites)",
|
||||||
"hide_user_stats": "Hide user statistics (e.g. the number of followers)",
|
"hide_user_stats": "Hide user statistics (e.g. the number of followers)",
|
||||||
"hide_filtered_statuses": "Hide filtered statuses",
|
"hide_filtered_statuses": "Hide filtered statuses",
|
||||||
|
"import_blocks_from_a_csv_file": "Import blocks from a csv file",
|
||||||
"import_followers_from_a_csv_file": "Import follows from a csv file",
|
"import_followers_from_a_csv_file": "Import follows from a csv file",
|
||||||
"import_theme": "Load preset",
|
"import_theme": "Load preset",
|
||||||
"inputRadius": "Input fields",
|
"inputRadius": "Input fields",
|
||||||
|
|
|
@ -77,7 +77,8 @@
|
||||||
"content_type": {
|
"content_type": {
|
||||||
"text/plain": "Tèxte brut",
|
"text/plain": "Tèxte brut",
|
||||||
"text/html": "HTML",
|
"text/html": "HTML",
|
||||||
"text/markdown": "Markdown"
|
"text/markdown": "Markdown",
|
||||||
|
"text/bbcode": "BBCode"
|
||||||
},
|
},
|
||||||
"content_warning": "Avís de contengut (opcional)",
|
"content_warning": "Avís de contengut (opcional)",
|
||||||
"default": "Escrivètz aquí vòstre estatut.",
|
"default": "Escrivètz aquí vòstre estatut.",
|
||||||
|
|
|
@ -74,7 +74,8 @@
|
||||||
"content_type": {
|
"content_type": {
|
||||||
"text/plain": "Czysty tekst",
|
"text/plain": "Czysty tekst",
|
||||||
"text/html": "HTML",
|
"text/html": "HTML",
|
||||||
"text/markdown": "Markdown"
|
"text/markdown": "Markdown",
|
||||||
|
"text/bbcode": "BBCode"
|
||||||
},
|
},
|
||||||
"content_warning": "Temat (nieobowiązkowy)",
|
"content_warning": "Temat (nieobowiązkowy)",
|
||||||
"default": "Właśnie wróciłem z kościoła",
|
"default": "Właśnie wróciłem z kościoła",
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import backendInteractorService from '../services/backend_interactor_service/backend_interactor_service.js'
|
import backendInteractorService from '../services/backend_interactor_service/backend_interactor_service.js'
|
||||||
|
import userSearchApi from '../services/new_api/user_search.js'
|
||||||
import { compact, map, each, merge, last, concat, uniq } from 'lodash'
|
import { compact, map, each, merge, last, concat, uniq } from 'lodash'
|
||||||
import { set } from 'vue'
|
import { set } from 'vue'
|
||||||
import { registerPushNotifications, unregisterPushNotifications } from '../services/push/push.js'
|
import { registerPushNotifications, unregisterPushNotifications } from '../services/push/push.js'
|
||||||
|
@ -341,6 +342,14 @@ const users = {
|
||||||
store.commit('setUserForNotification', notification)
|
store.commit('setUserForNotification', notification)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
searchUsers (store, query) {
|
||||||
|
// TODO: Move userSearch api into api.service
|
||||||
|
return userSearchApi.search({query, store: { state: store.rootState }})
|
||||||
|
.then((users) => {
|
||||||
|
store.commit('addNewUsers', users)
|
||||||
|
return users
|
||||||
|
})
|
||||||
|
},
|
||||||
async signUp (store, userInfo) {
|
async signUp (store, userInfo) {
|
||||||
store.commit('signUpPending')
|
store.commit('signUpPending')
|
||||||
|
|
||||||
|
|
|
@ -3,12 +3,10 @@ const LOGIN_URL = '/api/account/verify_credentials.json'
|
||||||
const ALL_FOLLOWING_URL = '/api/qvitter/allfollowing'
|
const ALL_FOLLOWING_URL = '/api/qvitter/allfollowing'
|
||||||
const MENTIONS_URL = '/api/statuses/mentions.json'
|
const MENTIONS_URL = '/api/statuses/mentions.json'
|
||||||
const REGISTRATION_URL = '/api/account/register.json'
|
const REGISTRATION_URL = '/api/account/register.json'
|
||||||
const AVATAR_UPDATE_URL = '/api/qvitter/update_avatar.json'
|
|
||||||
const BG_UPDATE_URL = '/api/qvitter/update_background_image.json'
|
const BG_UPDATE_URL = '/api/qvitter/update_background_image.json'
|
||||||
const BANNER_UPDATE_URL = '/api/account/update_profile_banner.json'
|
|
||||||
const PROFILE_UPDATE_URL = '/api/account/update_profile.json'
|
|
||||||
const EXTERNAL_PROFILE_URL = '/api/externalprofile/show.json'
|
const EXTERNAL_PROFILE_URL = '/api/externalprofile/show.json'
|
||||||
const QVITTER_USER_NOTIFICATIONS_READ_URL = '/api/qvitter/statuses/notifications/read.json'
|
const QVITTER_USER_NOTIFICATIONS_READ_URL = '/api/qvitter/statuses/notifications/read.json'
|
||||||
|
const BLOCKS_IMPORT_URL = '/api/pleroma/blocks_import'
|
||||||
const FOLLOW_IMPORT_URL = '/api/pleroma/follow_import'
|
const FOLLOW_IMPORT_URL = '/api/pleroma/follow_import'
|
||||||
const DELETE_ACCOUNT_URL = '/api/pleroma/delete_account'
|
const DELETE_ACCOUNT_URL = '/api/pleroma/delete_account'
|
||||||
const CHANGE_PASSWORD_URL = '/api/pleroma/change_password'
|
const CHANGE_PASSWORD_URL = '/api/pleroma/change_password'
|
||||||
|
@ -51,6 +49,7 @@ const MASTODON_POST_STATUS_URL = '/api/v1/statuses'
|
||||||
const MASTODON_MEDIA_UPLOAD_URL = '/api/v1/media'
|
const MASTODON_MEDIA_UPLOAD_URL = '/api/v1/media'
|
||||||
const MASTODON_STATUS_FAVORITEDBY_URL = id => `/api/v1/statuses/${id}/favourited_by`
|
const MASTODON_STATUS_FAVORITEDBY_URL = id => `/api/v1/statuses/${id}/favourited_by`
|
||||||
const MASTODON_STATUS_REBLOGGEDBY_URL = id => `/api/v1/statuses/${id}/reblogged_by`
|
const MASTODON_STATUS_REBLOGGEDBY_URL = id => `/api/v1/statuses/${id}/reblogged_by`
|
||||||
|
const MASTODON_PROFILE_UPDATE_URL = '/api/v1/accounts/update_credentials'
|
||||||
|
|
||||||
import { each, map, concat, last } from 'lodash'
|
import { each, map, concat, last } from 'lodash'
|
||||||
import { parseStatus, parseUser, parseNotification, parseAttachment } from '../entity_normalizer/entity_normalizer.service.js'
|
import { parseStatus, parseUser, parseNotification, parseAttachment } from '../entity_normalizer/entity_normalizer.service.js'
|
||||||
|
@ -80,28 +79,16 @@ const promisedRequest = (url, options) => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Params
|
const updateAvatar = ({credentials, avatar}) => {
|
||||||
// cropH
|
|
||||||
// cropW
|
|
||||||
// cropX
|
|
||||||
// cropY
|
|
||||||
// img (base 64 encodend data url)
|
|
||||||
const updateAvatar = ({credentials, params}) => {
|
|
||||||
let url = AVATAR_UPDATE_URL
|
|
||||||
|
|
||||||
const form = new FormData()
|
const form = new FormData()
|
||||||
|
form.append('avatar', avatar)
|
||||||
each(params, (value, key) => {
|
return fetch(MASTODON_PROFILE_UPDATE_URL, {
|
||||||
if (value) {
|
|
||||||
form.append(key, value)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return fetch(url, {
|
|
||||||
headers: authHeaders(credentials),
|
headers: authHeaders(credentials),
|
||||||
method: 'POST',
|
method: 'PATCH',
|
||||||
body: form
|
body: form
|
||||||
}).then((data) => data.json())
|
})
|
||||||
|
.then((data) => data.json())
|
||||||
|
.then((data) => parseUser(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateBg = ({credentials, params}) => {
|
const updateBg = ({credentials, params}) => {
|
||||||
|
@ -122,52 +109,29 @@ const updateBg = ({credentials, params}) => {
|
||||||
}).then((data) => data.json())
|
}).then((data) => data.json())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Params
|
const updateBanner = ({credentials, banner}) => {
|
||||||
// height
|
|
||||||
// width
|
|
||||||
// offset_left
|
|
||||||
// offset_top
|
|
||||||
// banner (base 64 encodend data url)
|
|
||||||
const updateBanner = ({credentials, params}) => {
|
|
||||||
let url = BANNER_UPDATE_URL
|
|
||||||
|
|
||||||
const form = new FormData()
|
const form = new FormData()
|
||||||
|
form.append('header', banner)
|
||||||
each(params, (value, key) => {
|
return fetch(MASTODON_PROFILE_UPDATE_URL, {
|
||||||
if (value) {
|
|
||||||
form.append(key, value)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return fetch(url, {
|
|
||||||
headers: authHeaders(credentials),
|
headers: authHeaders(credentials),
|
||||||
method: 'POST',
|
method: 'PATCH',
|
||||||
body: form
|
body: form
|
||||||
}).then((data) => data.json())
|
})
|
||||||
|
.then((data) => data.json())
|
||||||
|
.then((data) => parseUser(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Params
|
|
||||||
// name
|
|
||||||
// url
|
|
||||||
// location
|
|
||||||
// description
|
|
||||||
const updateProfile = ({credentials, params}) => {
|
const updateProfile = ({credentials, params}) => {
|
||||||
// Always include these fields, because they might be empty or false
|
return promisedRequest(MASTODON_PROFILE_UPDATE_URL, {
|
||||||
const fields = ['description', 'locked', 'no_rich_text', 'hide_follows', 'hide_followers', 'show_role']
|
headers: {
|
||||||
let url = PROFILE_UPDATE_URL
|
'Accept': 'application/json',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
const form = new FormData()
|
...authHeaders(credentials)
|
||||||
|
},
|
||||||
each(params, (value, key) => {
|
method: 'PATCH',
|
||||||
if (fields.includes(key) || value) {
|
body: JSON.stringify(params)
|
||||||
form.append(key, value)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
return fetch(url, {
|
.then((data) => parseUser(data))
|
||||||
headers: authHeaders(credentials),
|
|
||||||
method: 'POST',
|
|
||||||
body: form
|
|
||||||
}).then((data) => data.json())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Params needed:
|
// Params needed:
|
||||||
|
@ -636,9 +600,22 @@ const uploadMedia = ({formData, credentials}) => {
|
||||||
.then((data) => parseAttachment(data))
|
.then((data) => parseAttachment(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
const followImport = ({params, credentials}) => {
|
const importBlocks = ({file, credentials}) => {
|
||||||
|
const formData = new FormData()
|
||||||
|
formData.append('list', file)
|
||||||
|
return fetch(BLOCKS_IMPORT_URL, {
|
||||||
|
body: formData,
|
||||||
|
method: 'POST',
|
||||||
|
headers: authHeaders(credentials)
|
||||||
|
})
|
||||||
|
.then((response) => response.ok)
|
||||||
|
}
|
||||||
|
|
||||||
|
const importFollows = ({file, credentials}) => {
|
||||||
|
const formData = new FormData()
|
||||||
|
formData.append('list', file)
|
||||||
return fetch(FOLLOW_IMPORT_URL, {
|
return fetch(FOLLOW_IMPORT_URL, {
|
||||||
body: params,
|
body: formData,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: authHeaders(credentials)
|
headers: authHeaders(credentials)
|
||||||
})
|
})
|
||||||
|
@ -786,7 +763,8 @@ const apiService = {
|
||||||
updateProfile,
|
updateProfile,
|
||||||
updateBanner,
|
updateBanner,
|
||||||
externalProfile,
|
externalProfile,
|
||||||
followImport,
|
importBlocks,
|
||||||
|
importFollows,
|
||||||
deleteAccount,
|
deleteAccount,
|
||||||
changePassword,
|
changePassword,
|
||||||
fetchFollowRequests,
|
fetchFollowRequests,
|
||||||
|
|
|
@ -101,13 +101,14 @@ const backendInteractorService = (credentials) => {
|
||||||
|
|
||||||
const getCaptcha = () => apiService.getCaptcha()
|
const getCaptcha = () => apiService.getCaptcha()
|
||||||
const register = (params) => apiService.register(params)
|
const register = (params) => apiService.register(params)
|
||||||
const updateAvatar = ({params}) => apiService.updateAvatar({credentials, params})
|
const updateAvatar = ({avatar}) => apiService.updateAvatar({credentials, avatar})
|
||||||
const updateBg = ({params}) => apiService.updateBg({credentials, params})
|
const updateBg = ({params}) => apiService.updateBg({credentials, params})
|
||||||
const updateBanner = ({params}) => apiService.updateBanner({credentials, params})
|
const updateBanner = ({banner}) => apiService.updateBanner({credentials, banner})
|
||||||
const updateProfile = ({params}) => apiService.updateProfile({credentials, params})
|
const updateProfile = ({params}) => apiService.updateProfile({credentials, params})
|
||||||
|
|
||||||
const externalProfile = (profileUrl) => apiService.externalProfile({profileUrl, credentials})
|
const externalProfile = (profileUrl) => apiService.externalProfile({profileUrl, credentials})
|
||||||
const followImport = ({params}) => apiService.followImport({params, credentials})
|
const importBlocks = (file) => apiService.importBlocks({file, credentials})
|
||||||
|
const importFollows = (file) => apiService.importFollows({file, credentials})
|
||||||
|
|
||||||
const deleteAccount = ({password}) => apiService.deleteAccount({credentials, password})
|
const deleteAccount = ({password}) => apiService.deleteAccount({credentials, password})
|
||||||
const changePassword = ({password, newPassword, newPasswordConfirmation}) => apiService.changePassword({credentials, password, newPassword, newPasswordConfirmation})
|
const changePassword = ({password, newPassword, newPasswordConfirmation}) => apiService.changePassword({credentials, password, newPassword, newPasswordConfirmation})
|
||||||
|
@ -150,7 +151,8 @@ const backendInteractorService = (credentials) => {
|
||||||
updateBanner,
|
updateBanner,
|
||||||
updateProfile,
|
updateProfile,
|
||||||
externalProfile,
|
externalProfile,
|
||||||
followImport,
|
importBlocks,
|
||||||
|
importFollows,
|
||||||
deleteAccount,
|
deleteAccount,
|
||||||
changePassword,
|
changePassword,
|
||||||
fetchFollowRequests,
|
fetchFollowRequests,
|
||||||
|
|
|
@ -195,6 +195,7 @@ export const parseStatus = (data) => {
|
||||||
output.summary = pleroma.spoiler_text ? data.pleroma.spoiler_text['text/plain'] : data.spoiler_text
|
output.summary = pleroma.spoiler_text ? data.pleroma.spoiler_text['text/plain'] : data.spoiler_text
|
||||||
output.statusnet_conversation_id = data.pleroma.conversation_id
|
output.statusnet_conversation_id = data.pleroma.conversation_id
|
||||||
output.is_local = pleroma.local
|
output.is_local = pleroma.local
|
||||||
|
output.in_reply_to_screen_name = data.pleroma.in_reply_to_account_acct
|
||||||
} else {
|
} else {
|
||||||
output.text = data.content
|
output.text = data.content
|
||||||
output.summary = data.spoiler_text
|
output.summary = data.spoiler_text
|
||||||
|
@ -204,8 +205,6 @@ export const parseStatus = (data) => {
|
||||||
output.in_reply_to_user_id = data.in_reply_to_account_id
|
output.in_reply_to_user_id = data.in_reply_to_account_id
|
||||||
output.replies_count = data.replies_count
|
output.replies_count = data.replies_count
|
||||||
|
|
||||||
// Missing!! fix in UI?
|
|
||||||
// output.in_reply_to_screen_name = ???
|
|
||||||
if (output.type === 'retweet') {
|
if (output.type === 'retweet') {
|
||||||
output.retweeted_status = parseStatus(data.reblog)
|
output.retweeted_status = parseStatus(data.reblog)
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,18 +23,12 @@ export const requestFollow = (user, store) => new Promise((resolve, reject) => {
|
||||||
|
|
||||||
// For locked users we just mark it that we sent the follow request
|
// For locked users we just mark it that we sent the follow request
|
||||||
if (updated.locked) {
|
if (updated.locked) {
|
||||||
resolve({
|
resolve({ sent: true })
|
||||||
sent: true,
|
|
||||||
updated
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updated.following) {
|
if (updated.following) {
|
||||||
// If we get result immediately, just stop.
|
// If we get result immediately, just stop.
|
||||||
resolve({
|
resolve({ sent: false })
|
||||||
sent: false,
|
|
||||||
updated
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// But usually we don't get result immediately, so we ask server
|
// But usually we don't get result immediately, so we ask server
|
||||||
|
@ -48,16 +42,10 @@ export const requestFollow = (user, store) => new Promise((resolve, reject) => {
|
||||||
.then((following) => {
|
.then((following) => {
|
||||||
if (following) {
|
if (following) {
|
||||||
// We confirmed and everything's good.
|
// We confirmed and everything's good.
|
||||||
resolve({
|
resolve({ sent: false })
|
||||||
sent: false,
|
|
||||||
updated
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
// If after all the tries, just treat it as if user is locked
|
// If after all the tries, just treat it as if user is locked
|
||||||
resolve({
|
resolve({ sent: false })
|
||||||
sent: false,
|
|
||||||
updated
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in a new issue