forked from AkkomaGang/akkoma-fe
merge develop & resolve conflict
This commit is contained in:
commit
5fd589d5e7
38 changed files with 528 additions and 227 deletions
|
@ -154,7 +154,7 @@ input, textarea, .select {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border: none;
|
border: none;
|
||||||
color: $fallback--text;
|
color: $fallback--text;
|
||||||
color: var(--text, $fallback--text);
|
color: var(--inputText, --text, $fallback--text);
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0 2em 0 .2em;
|
padding: 0 2em 0 .2em;
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
|
|
|
@ -97,6 +97,7 @@ const setSettings = async ({ apiConfig, staticConfig, store }) => {
|
||||||
copyInstanceOption('showInstanceSpecificPanel')
|
copyInstanceOption('showInstanceSpecificPanel')
|
||||||
copyInstanceOption('scopeOptionsEnabled')
|
copyInstanceOption('scopeOptionsEnabled')
|
||||||
copyInstanceOption('formattingOptionsEnabled')
|
copyInstanceOption('formattingOptionsEnabled')
|
||||||
|
copyInstanceOption('hideMutedPosts')
|
||||||
copyInstanceOption('collapseMessageWithSubject')
|
copyInstanceOption('collapseMessageWithSubject')
|
||||||
copyInstanceOption('loginMethod')
|
copyInstanceOption('loginMethod')
|
||||||
copyInstanceOption('scopeCopy')
|
copyInstanceOption('scopeCopy')
|
||||||
|
@ -203,6 +204,12 @@ const getNodeInfo = async ({ store }) => {
|
||||||
const suggestions = metadata.suggestions
|
const suggestions = metadata.suggestions
|
||||||
store.dispatch('setInstanceOption', { name: 'suggestionsEnabled', value: suggestions.enabled })
|
store.dispatch('setInstanceOption', { name: 'suggestionsEnabled', value: suggestions.enabled })
|
||||||
store.dispatch('setInstanceOption', { name: 'suggestionsWeb', value: suggestions.web })
|
store.dispatch('setInstanceOption', { name: 'suggestionsWeb', value: suggestions.web })
|
||||||
|
|
||||||
|
const software = data.software
|
||||||
|
store.dispatch('setInstanceOption', { name: 'backendVersion', value: software.version })
|
||||||
|
|
||||||
|
const frontendVersion = window.___pleromafe_commit_hash
|
||||||
|
store.dispatch('setInstanceOption', { name: 'frontendVersion', value: frontendVersion })
|
||||||
} else {
|
} else {
|
||||||
throw (res)
|
throw (res)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="basic-user-card-collapsed-content" v-else>
|
<div class="basic-user-card-collapsed-content" v-else>
|
||||||
<div :title="user.name" class="basic-user-card-user-name">
|
<div :title="user.name" class="basic-user-card-user-name">
|
||||||
<span v-if="user.name_html" v-html="user.name_html"></span>
|
<span v-if="user.name_html" class="basic-user-card-user-name-value" v-html="user.name_html"></span>
|
||||||
<span v-else>{{ user.name }}</span>
|
<span v-else class="basic-user-card-user-name-value">{{ user.name }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<router-link class="basic-user-card-screen-name" :to="userProfileLink(user)">
|
<router-link class="basic-user-card-screen-name" :to="userProfileLink(user)">
|
||||||
|
@ -52,6 +52,14 @@
|
||||||
width: 16px;
|
width: 16px;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&-value {
|
||||||
|
display: inline-block;
|
||||||
|
max-width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-expanded-content {
|
&-expanded-content {
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import Conversation from '../conversation/conversation.vue'
|
import Conversation from '../conversation/conversation.vue'
|
||||||
import { find } from 'lodash'
|
|
||||||
|
|
||||||
const conversationPage = {
|
const conversationPage = {
|
||||||
components: {
|
components: {
|
||||||
|
@ -8,8 +7,8 @@ const conversationPage = {
|
||||||
computed: {
|
computed: {
|
||||||
statusoid () {
|
statusoid () {
|
||||||
const id = this.$route.params.id
|
const id = this.$route.params.id
|
||||||
const statuses = this.$store.state.statuses.allStatuses
|
const statuses = this.$store.state.statuses.allStatusesObject
|
||||||
const status = find(statuses, {id})
|
const status = statuses[id]
|
||||||
|
|
||||||
return status
|
return status
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { reduce, filter } from 'lodash'
|
import { reduce, filter } from 'lodash'
|
||||||
|
import { set } from 'vue'
|
||||||
import Status from '../status/status.vue'
|
import Status from '../status/status.vue'
|
||||||
|
|
||||||
const sortById = (a, b) => {
|
const sortById = (a, b) => {
|
||||||
|
@ -25,7 +26,8 @@ const sortAndFilterConversation = (conversation) => {
|
||||||
const conversation = {
|
const conversation = {
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
highlight: null
|
highlight: null,
|
||||||
|
converationStatusIds: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
props: [
|
props: [
|
||||||
|
@ -36,6 +38,15 @@ const conversation = {
|
||||||
status () {
|
status () {
|
||||||
return this.statusoid
|
return this.statusoid
|
||||||
},
|
},
|
||||||
|
idsToShow () {
|
||||||
|
if (this.converationStatusIds.length > 0) {
|
||||||
|
return this.converationStatusIds
|
||||||
|
} else if (this.statusId) {
|
||||||
|
return [this.statusId]
|
||||||
|
} else {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
},
|
||||||
statusId () {
|
statusId () {
|
||||||
if (this.statusoid.retweeted_status) {
|
if (this.statusoid.retweeted_status) {
|
||||||
return this.statusoid.retweeted_status.id
|
return this.statusoid.retweeted_status.id
|
||||||
|
@ -48,9 +59,11 @@ const conversation = {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
const conversationId = this.status.statusnet_conversation_id
|
const statusesObject = this.$store.state.statuses.allStatusesObject
|
||||||
const statuses = this.$store.state.statuses.allStatuses
|
const conversation = this.idsToShow.reduce((acc, id) => {
|
||||||
const conversation = filter(statuses, { statusnet_conversation_id: conversationId })
|
acc.push(statusesObject[id])
|
||||||
|
return acc
|
||||||
|
}, [])
|
||||||
return sortAndFilterConversation(conversation)
|
return sortAndFilterConversation(conversation)
|
||||||
},
|
},
|
||||||
replies () {
|
replies () {
|
||||||
|
@ -83,9 +96,15 @@ const conversation = {
|
||||||
methods: {
|
methods: {
|
||||||
fetchConversation () {
|
fetchConversation () {
|
||||||
if (this.status) {
|
if (this.status) {
|
||||||
const conversationId = this.status.statusnet_conversation_id
|
this.$store.state.api.backendInteractor.fetchConversation({id: this.status.id})
|
||||||
this.$store.state.api.backendInteractor.fetchConversation({id: conversationId})
|
.then(({ancestors, descendants}) => {
|
||||||
.then((statuses) => this.$store.dispatch('addNewStatuses', { statuses }))
|
this.$store.dispatch('addNewStatuses', { statuses: ancestors })
|
||||||
|
this.$store.dispatch('addNewStatuses', { statuses: descendants })
|
||||||
|
set(this, 'converationStatusIds', [].concat(
|
||||||
|
ancestors.map(_ => _.id),
|
||||||
|
this.statusId,
|
||||||
|
descendants.map(_ => _.id)))
|
||||||
|
})
|
||||||
.then(() => this.setHighlight(this.statusId))
|
.then(() => this.setHighlight(this.statusId))
|
||||||
} else {
|
} else {
|
||||||
const id = this.$route.params.id
|
const id = this.$route.params.id
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import BasicUserCard from '../basic_user_card/basic_user_card.vue'
|
import BasicUserCard from '../basic_user_card/basic_user_card.vue'
|
||||||
|
import RemoteFollow from '../remote_follow/remote_follow.vue'
|
||||||
import { requestFollow, requestUnfollow } from '../../services/follow_manipulate/follow_manipulate'
|
import { requestFollow, requestUnfollow } from '../../services/follow_manipulate/follow_manipulate'
|
||||||
|
|
||||||
const FollowCard = {
|
const FollowCard = {
|
||||||
|
@ -14,13 +15,17 @@ const FollowCard = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
BasicUserCard
|
BasicUserCard,
|
||||||
|
RemoteFollow
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
isMe () { return this.$store.state.users.currentUser.id === this.user.id },
|
isMe () { return this.$store.state.users.currentUser.id === this.user.id },
|
||||||
following () { return this.updated ? this.updated.following : this.user.following },
|
following () { return this.updated ? this.updated.following : this.user.following },
|
||||||
showFollow () {
|
showFollow () {
|
||||||
return !this.following || this.updated && !this.updated.following
|
return !this.following || this.updated && !this.updated.following
|
||||||
|
},
|
||||||
|
loggedIn () {
|
||||||
|
return this.$store.state.users.currentUser
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
|
@ -4,9 +4,12 @@
|
||||||
<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">
|
||||||
|
<RemoteFollow :user="user" />
|
||||||
|
</div>
|
||||||
<button
|
<button
|
||||||
v-if="showFollow"
|
v-if="showFollow && loggedIn"
|
||||||
class="btn btn-default"
|
class="btn btn-default follow-card-follow-button"
|
||||||
@click="followUser"
|
@click="followUser"
|
||||||
:disabled="inProgress"
|
:disabled="inProgress"
|
||||||
:title="requestSent ? $t('user_card.follow_again') : ''"
|
:title="requestSent ? $t('user_card.follow_again') : ''"
|
||||||
|
@ -21,7 +24,7 @@
|
||||||
{{ $t('user_card.follow') }}
|
{{ $t('user_card.follow') }}
|
||||||
</template>
|
</template>
|
||||||
</button>
|
</button>
|
||||||
<button v-if="following" class="btn btn-default pressed" @click="unfollowUser" :disabled="inProgress">
|
<button v-if="following" class="btn btn-default follow-card-follow-button pressed" @click="unfollowUser" :disabled="inProgress">
|
||||||
<template v-if="inProgress">
|
<template v-if="inProgress">
|
||||||
{{ $t('user_card.follow_progress') }}
|
{{ $t('user_card.follow_progress') }}
|
||||||
</template>
|
</template>
|
||||||
|
@ -36,15 +39,17 @@
|
||||||
<script src="./follow_card.js"></script>
|
<script src="./follow_card.js"></script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.follow-card-content-container {
|
.follow-card {
|
||||||
flex-shrink: 0;
|
&-content-container {
|
||||||
display: flex;
|
flex-shrink: 0;
|
||||||
flex-direction: row;
|
display: flex;
|
||||||
justify-content: space-between;
|
flex-direction: row;
|
||||||
flex-wrap: wrap;
|
justify-content: space-between;
|
||||||
line-height: 1.5em;
|
flex-wrap: wrap;
|
||||||
|
line-height: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
.btn {
|
&-follow-button {
|
||||||
margin-top: 0.5em;
|
margin-top: 0.5em;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
width: 10em;
|
width: 10em;
|
||||||
|
|
|
@ -31,6 +31,9 @@ const ImageCropper = {
|
||||||
saveButtonLabel: {
|
saveButtonLabel: {
|
||||||
type: String
|
type: String
|
||||||
},
|
},
|
||||||
|
saveWithoutCroppingButtonlabel: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
cancelButtonLabel: {
|
cancelButtonLabel: {
|
||||||
type: String
|
type: String
|
||||||
}
|
}
|
||||||
|
@ -48,6 +51,9 @@ const ImageCropper = {
|
||||||
saveText () {
|
saveText () {
|
||||||
return this.saveButtonLabel || this.$t('image_cropper.save')
|
return this.saveButtonLabel || this.$t('image_cropper.save')
|
||||||
},
|
},
|
||||||
|
saveWithoutCroppingText () {
|
||||||
|
return this.saveWithoutCroppingButtonlabel || this.$t('image_cropper.save_without_cropping')
|
||||||
|
},
|
||||||
cancelText () {
|
cancelText () {
|
||||||
return this.cancelButtonLabel || this.$t('image_cropper.cancel')
|
return this.cancelButtonLabel || this.$t('image_cropper.cancel')
|
||||||
},
|
},
|
||||||
|
@ -76,6 +82,18 @@ const ImageCropper = {
|
||||||
this.submitting = false
|
this.submitting = false
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
submitWithoutCropping () {
|
||||||
|
this.submitting = true
|
||||||
|
this.avatarUploadError = null
|
||||||
|
this.submitHandler(false, this.dataUrl)
|
||||||
|
.then(() => this.destroy())
|
||||||
|
.catch((err) => {
|
||||||
|
this.submitError = err
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.submitting = false
|
||||||
|
})
|
||||||
|
},
|
||||||
pickImage () {
|
pickImage () {
|
||||||
this.$refs.input.click()
|
this.$refs.input.click()
|
||||||
},
|
},
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
<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>
|
||||||
<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">
|
||||||
|
@ -36,7 +37,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&-buttons-wrapper {
|
&-buttons-wrapper {
|
||||||
margin-top: 15px;
|
margin-top: 10px;
|
||||||
|
|
||||||
|
button {
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -20,7 +20,7 @@ const mediaUpload = {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const formData = new FormData()
|
const formData = new FormData()
|
||||||
formData.append('media', file)
|
formData.append('file', file)
|
||||||
|
|
||||||
self.$emit('uploading')
|
self.$emit('uploading')
|
||||||
self.uploading = true
|
self.uploading = true
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<basic-user-card :user="user">
|
<basic-user-card :user="user">
|
||||||
<template slot="secondary-area">
|
<div class="mute-card-content-container">
|
||||||
<button class="btn btn-default" @click="unmuteUser" :disabled="progress" v-if="muted">
|
<button class="btn btn-default" @click="unmuteUser" :disabled="progress" v-if="muted">
|
||||||
<template v-if="progress">
|
<template v-if="progress">
|
||||||
{{ $t('user_card.unmute_progress') }}
|
{{ $t('user_card.unmute_progress') }}
|
||||||
|
@ -17,8 +17,18 @@
|
||||||
{{ $t('user_card.mute') }}
|
{{ $t('user_card.mute') }}
|
||||||
</template>
|
</template>
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</div>
|
||||||
</basic-user-card>
|
</basic-user-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./mute_card.js"></script>
|
<script src="./mute_card.js"></script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.mute-card-content-container {
|
||||||
|
margin-top: 0.5em;
|
||||||
|
text-align: right;
|
||||||
|
button {
|
||||||
|
width: 10em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -296,6 +296,8 @@ const PostStatusForm = {
|
||||||
},
|
},
|
||||||
paste (e) {
|
paste (e) {
|
||||||
if (e.clipboardData.files.length > 0) {
|
if (e.clipboardData.files.length > 0) {
|
||||||
|
// prevent pasting of file as text
|
||||||
|
e.preventDefault()
|
||||||
// Strangely, files property gets emptied after event propagation
|
// Strangely, files property gets emptied after event propagation
|
||||||
// Trying to wrap it in array doesn't work. Plus I doubt it's possible
|
// Trying to wrap it in array doesn't work. Plus I doubt it's possible
|
||||||
// to hold more than one file in clipboard.
|
// to hold more than one file in clipboard.
|
||||||
|
|
|
@ -84,10 +84,10 @@
|
||||||
<div class="media-upload-wrapper" v-for="file in newStatus.files">
|
<div class="media-upload-wrapper" v-for="file in newStatus.files">
|
||||||
<i class="fa button-icon icon-cancel" @click="removeMediaFile(file)"></i>
|
<i class="fa button-icon icon-cancel" @click="removeMediaFile(file)"></i>
|
||||||
<div class="media-upload-container attachment">
|
<div class="media-upload-container attachment">
|
||||||
<img class="thumbnail media-upload" :src="file.image" v-if="type(file) === 'image'"></img>
|
<img class="thumbnail media-upload" :src="file.url" v-if="type(file) === 'image'"></img>
|
||||||
<video v-if="type(file) === 'video'" :src="file.image" controls></video>
|
<video v-if="type(file) === 'video'" :src="file.url" controls></video>
|
||||||
<audio v-if="type(file) === 'audio'" :src="file.image" controls></audio>
|
<audio v-if="type(file) === 'audio'" :src="file.url" controls></audio>
|
||||||
<a v-if="type(file) === 'unknown'" :href="file.image">{{file.url}}</a>
|
<a v-if="type(file) === 'unknown'" :href="file.url">{{file.url}}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -287,8 +287,6 @@
|
||||||
img {
|
img {
|
||||||
width: 24px;
|
width: 24px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
border-radius: $fallback--avatarRadius;
|
|
||||||
border-radius: var(--avatarRadius, $fallback--avatarRadius);
|
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,9 @@ const registration = {
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
token () { return this.$route.params.token },
|
token () { return this.$route.params.token },
|
||||||
|
bioPlaceholder () {
|
||||||
|
return this.$t('registration.bio_placeholder').replace(/\s*\n\s*/g, ' \n')
|
||||||
|
},
|
||||||
...mapState({
|
...mapState({
|
||||||
registrationOpen: (state) => state.instance.registrationOpen,
|
registrationOpen: (state) => state.instance.registrationOpen,
|
||||||
signedIn: (state) => !!state.users.currentUser,
|
signedIn: (state) => !!state.users.currentUser,
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
|
|
||||||
<div class='form-group'>
|
<div class='form-group'>
|
||||||
<label class='form--label' for='bio'>{{$t('registration.bio')}} ({{$t('general.optional')}})</label>
|
<label class='form--label' for='bio'>{{$t('registration.bio')}} ({{$t('general.optional')}})</label>
|
||||||
<textarea :disabled="isPending" v-model='user.bio' class='form-control' id='bio' :placeholder="$t('registration.bio_placeholder')"></textarea>
|
<textarea :disabled="isPending" v-model='user.bio' class='form-control' id='bio' :placeholder="bioPlaceholder"></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class='form-group' :class="{ 'form-group--error': $v.user.password.$error }">
|
<div class='form-group' :class="{ 'form-group--error': $v.user.password.$error }">
|
||||||
|
|
10
src/components/remote_follow/remote_follow.js
Normal file
10
src/components/remote_follow/remote_follow.js
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
export default {
|
||||||
|
props: [ 'user' ],
|
||||||
|
computed: {
|
||||||
|
subscribeUrl () {
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
|
const serverUrl = new URL(this.user.statusnet_profile_url)
|
||||||
|
return `${serverUrl.protocol}//${serverUrl.host}/main/ostatus`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
24
src/components/remote_follow/remote_follow.vue
Normal file
24
src/components/remote_follow/remote_follow.vue
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<template>
|
||||||
|
<div class="remote-follow">
|
||||||
|
<form method="POST" :action='subscribeUrl'>
|
||||||
|
<input type="hidden" name="nickname" :value="user.screen_name">
|
||||||
|
<input type="hidden" name="profile" value="">
|
||||||
|
<button click="submit" class="remote-button">
|
||||||
|
{{ $t('user_card.remote_follow') }}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./remote_follow.js"></script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.remote-follow {
|
||||||
|
max-width: 220px;
|
||||||
|
|
||||||
|
.remote-button {
|
||||||
|
width: 100%;
|
||||||
|
min-height: 28px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,8 +1,13 @@
|
||||||
/* eslint-env browser */
|
/* eslint-env browser */
|
||||||
|
import { filter, trim } from 'lodash'
|
||||||
|
|
||||||
import TabSwitcher from '../tab_switcher/tab_switcher.js'
|
import TabSwitcher from '../tab_switcher/tab_switcher.js'
|
||||||
import StyleSwitcher from '../style_switcher/style_switcher.vue'
|
import StyleSwitcher from '../style_switcher/style_switcher.vue'
|
||||||
import InterfaceLanguageSwitcher from '../interface_language_switcher/interface_language_switcher.vue'
|
import InterfaceLanguageSwitcher from '../interface_language_switcher/interface_language_switcher.vue'
|
||||||
import { filter, trim } from 'lodash'
|
import { extractCommit } from '../../services/version/version.service'
|
||||||
|
|
||||||
|
const pleromaFeCommitUrl = 'https://git.pleroma.social/pleroma/pleroma-fe/commit/'
|
||||||
|
const pleromaBeCommitUrl = 'https://git.pleroma.social/pleroma/pleroma/commit/'
|
||||||
|
|
||||||
const settings = {
|
const settings = {
|
||||||
data () {
|
data () {
|
||||||
|
@ -42,6 +47,11 @@ const settings = {
|
||||||
pauseOnUnfocusedLocal: user.pauseOnUnfocused,
|
pauseOnUnfocusedLocal: user.pauseOnUnfocused,
|
||||||
hoverPreviewLocal: user.hoverPreview,
|
hoverPreviewLocal: user.hoverPreview,
|
||||||
|
|
||||||
|
hideMutedPostsLocal: typeof user.hideMutedPosts === 'undefined'
|
||||||
|
? instance.hideMutedPosts
|
||||||
|
: user.hideMutedPosts,
|
||||||
|
hideMutedPostsDefault: this.$t('settings.values.' + instance.hideMutedPosts),
|
||||||
|
|
||||||
collapseMessageWithSubjectLocal: typeof user.collapseMessageWithSubject === 'undefined'
|
collapseMessageWithSubjectLocal: typeof user.collapseMessageWithSubject === 'undefined'
|
||||||
? instance.collapseMessageWithSubject
|
? instance.collapseMessageWithSubject
|
||||||
: user.collapseMessageWithSubject,
|
: user.collapseMessageWithSubject,
|
||||||
|
@ -78,7 +88,10 @@ const settings = {
|
||||||
// Future spec, still not supported in Nightly 63 as of 08/2018
|
// Future spec, still not supported in Nightly 63 as of 08/2018
|
||||||
Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'audioTracks'),
|
Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'audioTracks'),
|
||||||
playVideosInModal: user.playVideosInModal,
|
playVideosInModal: user.playVideosInModal,
|
||||||
useContainFit: user.useContainFit
|
useContainFit: user.useContainFit,
|
||||||
|
|
||||||
|
backendVersion: instance.backendVersion,
|
||||||
|
frontendVersion: instance.frontendVersion
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
@ -96,7 +109,13 @@ const settings = {
|
||||||
postFormats () {
|
postFormats () {
|
||||||
return this.$store.state.instance.postFormats || []
|
return this.$store.state.instance.postFormats || []
|
||||||
},
|
},
|
||||||
instanceSpecificPanelPresent () { return this.$store.state.instance.showInstanceSpecificPanel }
|
instanceSpecificPanelPresent () { return this.$store.state.instance.showInstanceSpecificPanel },
|
||||||
|
frontendVersionLink () {
|
||||||
|
return pleromaFeCommitUrl + this.frontendVersion
|
||||||
|
},
|
||||||
|
backendVersionLink () {
|
||||||
|
return pleromaBeCommitUrl + extractCommit(this.backendVersion)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
hideAttachmentsLocal (value) {
|
hideAttachmentsLocal (value) {
|
||||||
|
@ -163,6 +182,9 @@ const settings = {
|
||||||
value = filter(value.split('\n'), (word) => trim(word).length > 0)
|
value = filter(value.split('\n'), (word) => trim(word).length > 0)
|
||||||
this.$store.dispatch('setOption', { name: 'muteWords', value })
|
this.$store.dispatch('setOption', { name: 'muteWords', value })
|
||||||
},
|
},
|
||||||
|
hideMutedPostsLocal (value) {
|
||||||
|
this.$store.dispatch('setOption', { name: 'hideMutedPosts', value })
|
||||||
|
},
|
||||||
collapseMessageWithSubjectLocal (value) {
|
collapseMessageWithSubjectLocal (value) {
|
||||||
this.$store.dispatch('setOption', { name: 'collapseMessageWithSubject', value })
|
this.$store.dispatch('setOption', { name: 'collapseMessageWithSubject', value })
|
||||||
},
|
},
|
||||||
|
|
|
@ -36,6 +36,10 @@
|
||||||
<div class="setting-item">
|
<div class="setting-item">
|
||||||
<h2>{{$t('nav.timeline')}}</h2>
|
<h2>{{$t('nav.timeline')}}</h2>
|
||||||
<ul class="setting-list">
|
<ul class="setting-list">
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="hideMutedPosts" v-model="hideMutedPostsLocal">
|
||||||
|
<label for="hideMutedPosts">{{$t('settings.hide_muted_posts')}} {{$t('settings.instance_default', { value: hideMutedPostsDefault })}}</label>
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<input type="checkbox" id="collapseMessageWithSubject" v-model="collapseMessageWithSubjectLocal">
|
<input type="checkbox" id="collapseMessageWithSubject" v-model="collapseMessageWithSubjectLocal">
|
||||||
<label for="collapseMessageWithSubject">
|
<label for="collapseMessageWithSubject">
|
||||||
|
@ -261,6 +265,28 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div :label="$t('settings.version.title')" >
|
||||||
|
<div class="setting-item">
|
||||||
|
<ul class="setting-list">
|
||||||
|
<li>
|
||||||
|
<p>{{$t('settings.version.backend_version')}}</p>
|
||||||
|
<ul class="option-list">
|
||||||
|
<li>
|
||||||
|
<a :href="backendVersionLink" target="_blank">{{backendVersion}}</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>{{$t('settings.version.frontend_version')}}</p>
|
||||||
|
<ul class="option-list">
|
||||||
|
<li>
|
||||||
|
<a :href="frontendVersionLink" target="_blank">{{frontendVersion}}</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</tab-switcher>
|
</tab-switcher>
|
||||||
</keep-alive>
|
</keep-alive>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import UserAvatar from '../user_avatar/user_avatar.vue'
|
import UserAvatar from '../user_avatar/user_avatar.vue'
|
||||||
|
import RemoteFollow from '../remote_follow/remote_follow.vue'
|
||||||
import { hex2rgb } from '../../services/color_convert/color_convert.js'
|
import { hex2rgb } from '../../services/color_convert/color_convert.js'
|
||||||
import { requestFollow, requestUnfollow } from '../../services/follow_manipulate/follow_manipulate'
|
import { requestFollow, requestUnfollow } from '../../services/follow_manipulate/follow_manipulate'
|
||||||
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
|
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
|
||||||
|
@ -99,7 +100,8 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
UserAvatar
|
UserAvatar,
|
||||||
|
RemoteFollow
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
followUser () {
|
followUser () {
|
||||||
|
@ -119,24 +121,16 @@ export default {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
blockUser () {
|
blockUser () {
|
||||||
const store = this.$store
|
this.$store.dispatch('blockUser', this.user.id)
|
||||||
store.state.api.backendInteractor.blockUser(this.user.id)
|
|
||||||
.then((blockedUser) => {
|
|
||||||
store.commit('addNewUsers', [blockedUser])
|
|
||||||
store.commit('removeStatus', { timeline: 'friends', userId: this.user.id })
|
|
||||||
store.commit('removeStatus', { timeline: 'public', userId: this.user.id })
|
|
||||||
store.commit('removeStatus', { timeline: 'publicAndExternal', userId: this.user.id })
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
unblockUser () {
|
unblockUser () {
|
||||||
const store = this.$store
|
this.$store.dispatch('unblockUser', this.user.id)
|
||||||
store.state.api.backendInteractor.unblockUser(this.user.id)
|
|
||||||
.then((unblockedUser) => store.commit('addNewUsers', [unblockedUser]))
|
|
||||||
},
|
},
|
||||||
toggleMute () {
|
muteUser () {
|
||||||
const store = this.$store
|
this.$store.dispatch('muteUser', this.user.id)
|
||||||
store.commit('setMuted', {user: this.user, muted: !this.user.muted})
|
},
|
||||||
store.state.api.backendInteractor.setUserMute(this.user)
|
unmuteUser () {
|
||||||
|
this.$store.dispatch('unmuteUser', this.user.id)
|
||||||
},
|
},
|
||||||
setProfileView (v) {
|
setProfileView (v) {
|
||||||
if (this.switcher) {
|
if (this.switcher) {
|
||||||
|
|
|
@ -74,24 +74,18 @@
|
||||||
</div>
|
</div>
|
||||||
<div class='mute' v-if='isOtherUser && loggedIn'>
|
<div class='mute' v-if='isOtherUser && loggedIn'>
|
||||||
<span v-if='user.muted'>
|
<span v-if='user.muted'>
|
||||||
<button @click="toggleMute" class="pressed">
|
<button @click="unmuteUser" class="pressed">
|
||||||
{{ $t('user_card.muted') }}
|
{{ $t('user_card.muted') }}
|
||||||
</button>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
<span v-if='!user.muted'>
|
<span v-if='!user.muted'>
|
||||||
<button @click="toggleMute">
|
<button @click="muteUser">
|
||||||
{{ $t('user_card.mute') }}
|
{{ $t('user_card.mute') }}
|
||||||
</button>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="remote-follow" v-if='!loggedIn && user.is_local'>
|
<div v-if='!loggedIn && user.is_local'>
|
||||||
<form method="POST" :action='subscribeUrl'>
|
<RemoteFollow :user="user" />
|
||||||
<input type="hidden" name="nickname" :value="user.screen_name">
|
|
||||||
<input type="hidden" name="profile" value="">
|
|
||||||
<button click="submit" class="remote-button">
|
|
||||||
{{ $t('user_card.remote_follow') }}
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
<div class='block' v-if='isOtherUser && loggedIn'>
|
<div class='block' v-if='isOtherUser && loggedIn'>
|
||||||
<span v-if='user.statusnet_blocking'>
|
<span v-if='user.statusnet_blocking'>
|
||||||
|
@ -375,11 +369,6 @@
|
||||||
min-height: 28px;
|
min-height: 28px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.remote-follow {
|
|
||||||
max-width: 220px;
|
|
||||||
min-height: 28px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.follow {
|
.follow {
|
||||||
max-width: 220px;
|
max-width: 220px;
|
||||||
min-height: 28px;
|
min-height: 28px;
|
||||||
|
|
|
@ -158,7 +158,13 @@ const UserSettings = {
|
||||||
reader.readAsDataURL(file)
|
reader.readAsDataURL(file)
|
||||||
},
|
},
|
||||||
submitAvatar (cropper, file) {
|
submitAvatar (cropper, file) {
|
||||||
const img = cropper.getCroppedCanvas().toDataURL(file.type)
|
let img
|
||||||
|
if (cropper) {
|
||||||
|
img = cropper.getCroppedCanvas().toDataURL(file.type)
|
||||||
|
} else {
|
||||||
|
img = file
|
||||||
|
}
|
||||||
|
|
||||||
return this.$store.state.api.backendInteractor.updateAvatar({ params: { img } }).then((user) => {
|
return this.$store.state.api.backendInteractor.updateAvatar({ params: { img } }).then((user) => {
|
||||||
if (!user.error) {
|
if (!user.error) {
|
||||||
this.$store.commit('addNewUsers', [user])
|
this.$store.commit('addNewUsers', [user])
|
||||||
|
|
|
@ -192,6 +192,12 @@
|
||||||
<template slot="empty">{{$t('settings.no_blocks')}}</template>
|
<template slot="empty">{{$t('settings.no_blocks')}}</template>
|
||||||
</block-list>
|
</block-list>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div :label="$t('settings.mutes_tab')">
|
||||||
|
<mute-list :refresh="true">
|
||||||
|
<template slot="empty">{{$t('settings.no_mutes')}}</template>
|
||||||
|
</mute-list>
|
||||||
|
</div>
|
||||||
</tab-switcher>
|
</tab-switcher>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
"image_cropper": {
|
"image_cropper": {
|
||||||
"crop_picture": "Crop picture",
|
"crop_picture": "Crop picture",
|
||||||
"save": "Save",
|
"save": "Save",
|
||||||
|
"save_without_cropping": "Save without cropping",
|
||||||
"cancel": "Cancel"
|
"cancel": "Cancel"
|
||||||
},
|
},
|
||||||
"login": {
|
"login": {
|
||||||
|
@ -97,7 +98,7 @@
|
||||||
"new_captcha": "Click the image to get a new captcha",
|
"new_captcha": "Click the image to get a new captcha",
|
||||||
"username_placeholder": "e.g. lain",
|
"username_placeholder": "e.g. lain",
|
||||||
"fullname_placeholder": "e.g. Lain Iwakura",
|
"fullname_placeholder": "e.g. Lain Iwakura",
|
||||||
"bio_placeholder": "e.g.\nHi, I'm Lain\nI’m an anime girl living in suburban Japan. You may know me from the Wired.",
|
"bio_placeholder": "e.g.\nHi, I'm Lain.\nI’m an anime girl living in suburban Japan. You may know me from the Wired.",
|
||||||
"validations": {
|
"validations": {
|
||||||
"username_required": "cannot be left blank",
|
"username_required": "cannot be left blank",
|
||||||
"fullname_required": "cannot be left blank",
|
"fullname_required": "cannot be left blank",
|
||||||
|
@ -152,6 +153,7 @@
|
||||||
"general": "General",
|
"general": "General",
|
||||||
"hide_attachments_in_convo": "Hide attachments in conversations",
|
"hide_attachments_in_convo": "Hide attachments in conversations",
|
||||||
"hide_attachments_in_tl": "Hide attachments in timeline",
|
"hide_attachments_in_tl": "Hide attachments in timeline",
|
||||||
|
"hide_muted_posts": "Hide posts of muted users",
|
||||||
"max_thumbnails": "Maximum amount of thumbnails per post",
|
"max_thumbnails": "Maximum amount of thumbnails per post",
|
||||||
"hide_isp": "Hide instance-specific panel",
|
"hide_isp": "Hide instance-specific panel",
|
||||||
"preload_images": "Preload images",
|
"preload_images": "Preload images",
|
||||||
|
@ -347,6 +349,11 @@
|
||||||
"checkbox": "I have skimmed over terms and conditions",
|
"checkbox": "I have skimmed over terms and conditions",
|
||||||
"link": "a nice lil' link"
|
"link": "a nice lil' link"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"title": "Version",
|
||||||
|
"backend_version": "Backend Version",
|
||||||
|
"frontend_version": "Frontend Version"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeline": {
|
"timeline": {
|
||||||
|
|
147
src/i18n/oc.json
147
src/i18n/oc.json
|
@ -59,19 +59,21 @@
|
||||||
"broken_favorite": "Estatut desconegut, sèm a lo cercar...",
|
"broken_favorite": "Estatut desconegut, sèm a lo cercar...",
|
||||||
"favorited_you": "a aimat vòstre estatut",
|
"favorited_you": "a aimat vòstre estatut",
|
||||||
"followed_you": "vos a seguit",
|
"followed_you": "vos a seguit",
|
||||||
"load_older": "Cargar las notificaciones mai ancianas",
|
"load_older": "Cargar las notificacions mai ancianas",
|
||||||
"notifications": "Notficacions",
|
"notifications": "Notficacions",
|
||||||
"read": "Legit !",
|
"read": "Legit !",
|
||||||
"repeated_you": "a repetit vòstre estatut",
|
"repeated_you": "a repetit vòstre estatut",
|
||||||
"no_more_notifications": "Pas mai de notificacions"
|
"no_more_notifications": "Pas mai de notificacions"
|
||||||
},
|
},
|
||||||
"post_status": {
|
"post_status": {
|
||||||
"new_status": "Publicar d’estatuts novèls",
|
"new_status": "Publicar d’estatuts novèls",
|
||||||
"account_not_locked_warning": "Vòstre compte es pas {0}. Qual que siá pòt vos seguir per veire vòstras publicacions destinadas pas qu'a vòstres seguidors.",
|
"account_not_locked_warning": "Vòstre compte es pas {0}. Qual que siá pòt vos seguir per veire vòstras publicacions destinadas pas qu’a vòstres seguidors.",
|
||||||
"account_not_locked_warning_link": "clavat",
|
"account_not_locked_warning_link": "clavat",
|
||||||
"attachments_sensitive": "Marcar las pèças juntas coma sensiblas",
|
"attachments_sensitive": "Marcar las pèças juntas coma sensiblas",
|
||||||
"content_type": {
|
"content_type": {
|
||||||
"text/plain": "Tèxte brut"
|
"text/plain": "Tèxte brut",
|
||||||
|
"text/html": "HTML",
|
||||||
|
"text/markdown": "Markdown"
|
||||||
},
|
},
|
||||||
"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.",
|
||||||
|
@ -118,12 +120,12 @@
|
||||||
"blocks_tab": "Blocatges",
|
"blocks_tab": "Blocatges",
|
||||||
"btnRadius": "Botons",
|
"btnRadius": "Botons",
|
||||||
"cBlue": "Blau (Respondre, seguir)",
|
"cBlue": "Blau (Respondre, seguir)",
|
||||||
"cGreen": "Verd (Repartajar)",
|
"cGreen": "Verd (Repertir)",
|
||||||
"cOrange": "Irange (Aimar)",
|
"cOrange": "Irange (Aimar)",
|
||||||
"cRed": "Roge (Anullar)",
|
"cRed": "Roge (Anullar)",
|
||||||
"change_password": "Cambiar lo senhal",
|
"change_password": "Cambiar lo senhal",
|
||||||
"change_password_error": "Una error s’es producha en cambiant lo senhal.",
|
"change_password_error": "Una error s’es producha en cambiant lo senhal.",
|
||||||
"changed_password": "Senhal corrèctament cambiat !",
|
"changed_password": "Senhal corrèctament cambiat !",
|
||||||
"collapse_subject": "Replegar las publicacions amb de subjèctes",
|
"collapse_subject": "Replegar las publicacions amb de subjèctes",
|
||||||
"composing": "Escritura",
|
"composing": "Escritura",
|
||||||
"confirm_new_password": "Confirmatz lo nòu senhal",
|
"confirm_new_password": "Confirmatz lo nòu senhal",
|
||||||
|
@ -134,7 +136,7 @@
|
||||||
"default_vis": "Nivèl de visibilitat per defaut",
|
"default_vis": "Nivèl de visibilitat per defaut",
|
||||||
"delete_account": "Suprimir lo compte",
|
"delete_account": "Suprimir lo compte",
|
||||||
"delete_account_description": "Suprimir vòstre compte e los messatges per sempre.",
|
"delete_account_description": "Suprimir vòstre compte e los messatges per sempre.",
|
||||||
"delete_account_error": "Una error s’es producha en suprimir lo compte. S’aquò ten d’arribar mercés de contactar vòstre administrador d’instància.",
|
"delete_account_error": "Una error s’es producha en suprimir lo compte. S’aquò ten d’arribar mercés de contactar vòstre administrator d’instància.",
|
||||||
"delete_account_instructions": "Picatz vòstre senhal dins lo camp tèxte çai-jos per confirmar la supression del compte.",
|
"delete_account_instructions": "Picatz vòstre senhal dins lo camp tèxte çai-jos per confirmar la supression del compte.",
|
||||||
"avatar_size_instruction": "La talha minimum recomandada pels imatges d’avatar es 150x150 pixèls.",
|
"avatar_size_instruction": "La talha minimum recomandada pels imatges d’avatar es 150x150 pixèls.",
|
||||||
"export_theme": "Enregistrar la preconfiguracion",
|
"export_theme": "Enregistrar la preconfiguracion",
|
||||||
|
@ -154,14 +156,14 @@
|
||||||
"hide_isp": "Amagar lo panèl especial instància",
|
"hide_isp": "Amagar lo panèl especial instància",
|
||||||
"preload_images": "Precargar los imatges",
|
"preload_images": "Precargar los imatges",
|
||||||
"use_one_click_nsfw": "Dobrir las pèças juntas NSFW amb un clic",
|
"use_one_click_nsfw": "Dobrir las pèças juntas NSFW amb un clic",
|
||||||
"hide_post_stats": "Amagar los estatistics de publicacion (ex. lo ombre de favorits)",
|
"hide_post_stats": "Amagar las estatisticas de publicacion (ex. lo nombre de favorits)",
|
||||||
"hide_user_stats": "Amagar las estatisticas de l’utilizaire (ex. lo nombre de seguidors)",
|
"hide_user_stats": "Amagar las estatisticas de l’utilizaire (ex. lo nombre de seguidors)",
|
||||||
"hide_filtered_statuses": "Amagar los estatuts filtrats",
|
"hide_filtered_statuses": "Amagar los estatuts filtrats",
|
||||||
"import_followers_from_a_csv_file": "Importar los seguidors d’un fichièr csv",
|
"import_followers_from_a_csv_file": "Importar los seguidors d’un fichièr csv",
|
||||||
"import_theme": "Cargar un tèma",
|
"import_theme": "Cargar un tèma",
|
||||||
"inputRadius": "Camps tèxte",
|
"inputRadius": "Camps tèxte",
|
||||||
"checkboxRadius": "Casas de marcar",
|
"checkboxRadius": "Casas de marcar",
|
||||||
"instance_default": "(defaut : {value})",
|
"instance_default": "(defaut : {value})",
|
||||||
"instance_default_simple": "(defaut)",
|
"instance_default_simple": "(defaut)",
|
||||||
"interface": "Interfàcia",
|
"interface": "Interfàcia",
|
||||||
"interfaceLanguage": "Lenga de l’interfàcia",
|
"interfaceLanguage": "Lenga de l’interfàcia",
|
||||||
|
@ -172,7 +174,7 @@
|
||||||
"loop_video": "Bocla vidèo",
|
"loop_video": "Bocla vidèo",
|
||||||
"loop_video_silent_only": "Legir en bocla solament las vidèos sens son (coma los « Gifs » de Mastodon)",
|
"loop_video_silent_only": "Legir en bocla solament las vidèos sens son (coma los « Gifs » de Mastodon)",
|
||||||
"mutes_tab": "Agamats",
|
"mutes_tab": "Agamats",
|
||||||
"play_videos_in_modal": "Legir las vidèoas dirèctament dins la visualizaira mèdia",
|
"play_videos_in_modal": "Legir las vidèos dirèctament dins la visualizaira mèdia",
|
||||||
"use_contain_fit": "Talhar pas las pèças juntas per las vinhetas",
|
"use_contain_fit": "Talhar pas las pèças juntas per las vinhetas",
|
||||||
"name": "Nom",
|
"name": "Nom",
|
||||||
"name_bio": "Nom & Bio",
|
"name_bio": "Nom & Bio",
|
||||||
|
@ -223,7 +225,7 @@
|
||||||
"post_status_content_type": "Publicar lo tipe de contengut dels estatuts",
|
"post_status_content_type": "Publicar lo tipe de contengut dels estatuts",
|
||||||
"stop_gifs": "Lançar los GIFs al subrevòl",
|
"stop_gifs": "Lançar los GIFs al subrevòl",
|
||||||
"streaming": "Activar lo cargament automatic dels novèls estatus en anar amont",
|
"streaming": "Activar lo cargament automatic dels novèls estatus en anar amont",
|
||||||
"text": "Tèxt",
|
"text": "Tèxte",
|
||||||
"theme": "Tèma",
|
"theme": "Tèma",
|
||||||
"theme_help_v2_1": "You can also override certain component's colors and opacity by toggling the checkbox, use \"Clear all\" button to clear all overrides.",
|
"theme_help_v2_1": "You can also override certain component's colors and opacity by toggling the checkbox, use \"Clear all\" button to clear all overrides.",
|
||||||
"theme_help_v2_2": "Icons underneath some entries are background/text contrast indicators, hover over for detailed info. Please keep in mind that when using transparency contrast indicators show the worst possible case.",
|
"theme_help_v2_2": "Icons underneath some entries are background/text contrast indicators, hover over for detailed info. Please keep in mind that when using transparency contrast indicators show the worst possible case.",
|
||||||
|
@ -234,6 +236,117 @@
|
||||||
"values": {
|
"values": {
|
||||||
"false": "non",
|
"false": "non",
|
||||||
"true": "òc"
|
"true": "òc"
|
||||||
|
},
|
||||||
|
"notifications": "Notificacions",
|
||||||
|
"enable_web_push_notifications": "Activar las notificacions web push",
|
||||||
|
"style": {
|
||||||
|
"switcher": {
|
||||||
|
"keep_color": "Gardar las colors",
|
||||||
|
"keep_shadows": "Gardar las ombras",
|
||||||
|
"keep_opacity": "Gardar l’opacitat",
|
||||||
|
"keep_roundness": "Gardar la redondetat",
|
||||||
|
"keep_fonts": "Gardar las polissas",
|
||||||
|
"save_load_hint": "Las opcions « Gardar » permeton de servar las opcions configuradas actualament quand seleccionatz o cargatz un tèma, permeton tanben d’enregistrar aquelas opcions quand exportatz un tèma. Quand totas las casas son pas marcadas, l’exportacion de tèma o enregistrarà tot.",
|
||||||
|
"reset": "Restablir",
|
||||||
|
"clear_all": "O escafar tot",
|
||||||
|
"clear_opacity": "Escafar l’opacitat"
|
||||||
|
},
|
||||||
|
"common": {
|
||||||
|
"color": "Color",
|
||||||
|
"opacity": "Opacitat",
|
||||||
|
"contrast": {
|
||||||
|
"hint": "Lo coeficient de contraste es de {ratio}. Dòna {level} {context}",
|
||||||
|
"level": {
|
||||||
|
"aa": "un nivèl AA minimum recomandat",
|
||||||
|
"aaa": "un nivèl AAA recomandat",
|
||||||
|
"bad": "pas un nivèl d’accessibilitat recomandat"
|
||||||
|
},
|
||||||
|
"context": {
|
||||||
|
"18pt": "pel tèxte grand (18pt+)",
|
||||||
|
"text": "pel tèxte"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"common_colors": {
|
||||||
|
"_tab_label": "Comun",
|
||||||
|
"main": "Colors comunas",
|
||||||
|
"foreground_hint": "Vejatz « Avançat » per mai de paramètres detalhats",
|
||||||
|
"rgbo": "Icònas, accents, badges"
|
||||||
|
},
|
||||||
|
"advanced_colors": {
|
||||||
|
"_tab_label": "Avançat",
|
||||||
|
"alert": "Rèire plan d’alèrtas",
|
||||||
|
"alert_error": "Error",
|
||||||
|
"badge": "Rèire plan dels badges",
|
||||||
|
"badge_notification": "Notificacion",
|
||||||
|
"panel_header": "Bandièra del tablèu de bòrd",
|
||||||
|
"top_bar": "Barra amont",
|
||||||
|
"borders": "Caires",
|
||||||
|
"buttons": "Botons",
|
||||||
|
"inputs": "Camps tèxte",
|
||||||
|
"faint_text": "Tèxte descolorit"
|
||||||
|
},
|
||||||
|
"radii": {
|
||||||
|
"_tab_label": "Redondetat"
|
||||||
|
},
|
||||||
|
"shadows": {
|
||||||
|
"_tab_label": "Ombra e luminositat",
|
||||||
|
"component": "Compausant",
|
||||||
|
"override": "Subrecargar",
|
||||||
|
"shadow_id": "Ombra #{value}",
|
||||||
|
"blur": "Fosc",
|
||||||
|
"spread": "Espandiment",
|
||||||
|
"inset": "Incrustacion",
|
||||||
|
"hint": "Per las ombras podètz tanben utilizar --variable coma valor de color per emplegar una variable CSS3. Notatz que lo paramètre d’opacitat foncionarà pas dins aquel cas.",
|
||||||
|
"filter_hint": {
|
||||||
|
"always_drop_shadow": "Avertiment, aquel ombra utiliza totjorn {0} quand lo navigator es compatible.",
|
||||||
|
"drop_shadow_syntax": "{0} es pas compatible amb lo paramètre {1} e lo mot clau {2}.",
|
||||||
|
"avatar_inset": "Notatz que combinar d’ombras incrustadas e pas incrustadas pòt donar de resultats inesperats amb los avatars transparents.",
|
||||||
|
"spread_zero": "L’ombra amb un espandiment de > 0 apareisserà coma reglat a zèro",
|
||||||
|
"inset_classic": "L’ombra d’incrustacion utilizarà {0}"
|
||||||
|
},
|
||||||
|
"components": {
|
||||||
|
"panel": "Tablèu",
|
||||||
|
"panelHeader": "Bandièra del tablèu",
|
||||||
|
"topBar": "Barra amont",
|
||||||
|
"avatar": "Utilizar l’avatar (vista perfil)",
|
||||||
|
"avatarStatus": "Avatar de l’utilizaire (afichatge publicacion)",
|
||||||
|
"popup": "Fenèstras sorgissentas e astúcias",
|
||||||
|
"button": "Boton",
|
||||||
|
"buttonHover": "Boton (en passar la mirga)",
|
||||||
|
"buttonPressed": "Boton (en quichar)",
|
||||||
|
"buttonPressedHover": "Boton (en quichar e passar)",
|
||||||
|
"input": "Camp tèxte"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fonts": {
|
||||||
|
"_tab_label": "Polissas",
|
||||||
|
"help": "Selecionatz la polissa d’utilizar pels elements de l’UI. Per « Personalizada » vos cal picar lo nom exacte tal coma apareis sul sistèma.",
|
||||||
|
"components": {
|
||||||
|
"interface": "Interfàcia",
|
||||||
|
"input": "Camps tèxte",
|
||||||
|
"post": "Tèxte de publicacion",
|
||||||
|
"postCode": "Tèxte Monospaced dins las publicacion (tèxte formatat)"
|
||||||
|
},
|
||||||
|
"family": "Nom de la polissa",
|
||||||
|
"size": "Talha (en px)",
|
||||||
|
"weight": "Largor (gras)",
|
||||||
|
"custom": "Personalizada"
|
||||||
|
},
|
||||||
|
"preview": {
|
||||||
|
"header": "Apercebut",
|
||||||
|
"content": "Contengut",
|
||||||
|
"error": "Error d’exemple",
|
||||||
|
"button": "Boton",
|
||||||
|
"text": "A tròç de mai de {0} e {1}",
|
||||||
|
"mono": "contengut",
|
||||||
|
"input": "arribada al país.",
|
||||||
|
"faint_link": "manual d’ajuda",
|
||||||
|
"fine_print": "Legissètz nòstre {0} per legir pas res d’util !",
|
||||||
|
"header_faint": "Va plan",
|
||||||
|
"checkbox": "Ai legit los tèrmes e condicions d’utilizacion",
|
||||||
|
"link": "un pichon ligam simpatic"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeline": {
|
"timeline": {
|
||||||
|
@ -241,19 +354,21 @@
|
||||||
"conversation": "Conversacion",
|
"conversation": "Conversacion",
|
||||||
"error_fetching": "Error en cercant de mesas a jorn",
|
"error_fetching": "Error en cercant de mesas a jorn",
|
||||||
"load_older": "Ne veire mai",
|
"load_older": "Ne veire mai",
|
||||||
|
"no_retweet_hint": "Las publicacions marcadas pels seguidors solament o dirèctas se pòdon pas repetir",
|
||||||
"repeated": "repetit",
|
"repeated": "repetit",
|
||||||
"show_new": "Ne veire mai",
|
"show_new": "Ne veire mai",
|
||||||
"up_to_date": "A jorn",
|
"up_to_date": "A jorn",
|
||||||
"no_retweet_hint": "La publicacion marcada coma pels seguidors solament o dirècte pòt pas èsser repetida"
|
"no_more_statuses": "Pas mai d’estatuts",
|
||||||
|
"no_statuses": "Cap d’estatuts"
|
||||||
},
|
},
|
||||||
"status": {
|
"status": {
|
||||||
"reply_to": "Respondre à",
|
"reply_to": "Respond a",
|
||||||
"replies_list": "Responsas :"
|
"replies_list": "Responsas :"
|
||||||
},
|
},
|
||||||
"user_card": {
|
"user_card": {
|
||||||
"approve": "Validar",
|
"approve": "Validar",
|
||||||
"block": "Blocar",
|
"block": "Blocar",
|
||||||
"blocked": "Blocat !",
|
"blocked": "Blocat !",
|
||||||
"deny": "Refusar",
|
"deny": "Refusar",
|
||||||
"favorites": "Favorits",
|
"favorites": "Favorits",
|
||||||
"follow": "Seguir",
|
"follow": "Seguir",
|
||||||
|
@ -263,8 +378,8 @@
|
||||||
"follow_unfollow": "Quitar de seguir",
|
"follow_unfollow": "Quitar de seguir",
|
||||||
"followees": "Abonaments",
|
"followees": "Abonaments",
|
||||||
"followers": "Seguidors",
|
"followers": "Seguidors",
|
||||||
"following": "Seguit !",
|
"following": "Seguit !",
|
||||||
"follows_you": "Vos sèc !",
|
"follows_you": "Vos sèc !",
|
||||||
"its_you": "Sètz vos !",
|
"its_you": "Sètz vos !",
|
||||||
"media": "Mèdia",
|
"media": "Mèdia",
|
||||||
"mute": "Amagar",
|
"mute": "Amagar",
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
"public_tl": "Linha do tempo pública",
|
"public_tl": "Linha do tempo pública",
|
||||||
"timeline": "Linha do tempo",
|
"timeline": "Linha do tempo",
|
||||||
"twkn": "Toda a rede conhecida",
|
"twkn": "Toda a rede conhecida",
|
||||||
"user_search": "Busca de usuário",
|
"user_search": "Buscar usuários",
|
||||||
"who_to_follow": "Quem seguir",
|
"who_to_follow": "Quem seguir",
|
||||||
"preferences": "Preferências"
|
"preferences": "Preferências"
|
||||||
},
|
},
|
||||||
|
@ -67,8 +67,8 @@
|
||||||
},
|
},
|
||||||
"post_status": {
|
"post_status": {
|
||||||
"new_status": "Postar novo status",
|
"new_status": "Postar novo status",
|
||||||
"account_not_locked_warning": "Sua conta não está {0}. Qualquer pessoa pode te seguir para ver seus posts restritos.",
|
"account_not_locked_warning": "Sua conta não é {0}. Qualquer pessoa pode te seguir e ver seus posts privados (só para seguidores).",
|
||||||
"account_not_locked_warning_link": "fechada",
|
"account_not_locked_warning_link": "restrita",
|
||||||
"attachments_sensitive": "Marcar anexos como sensíveis",
|
"attachments_sensitive": "Marcar anexos como sensíveis",
|
||||||
"content_type": {
|
"content_type": {
|
||||||
"text/plain": "Texto puro"
|
"text/plain": "Texto puro"
|
||||||
|
@ -115,7 +115,7 @@
|
||||||
"avatarRadius": "Avatares",
|
"avatarRadius": "Avatares",
|
||||||
"background": "Pano de Fundo",
|
"background": "Pano de Fundo",
|
||||||
"bio": "Biografia",
|
"bio": "Biografia",
|
||||||
"blocks_tab": "Blocos",
|
"blocks_tab": "Bloqueios",
|
||||||
"btnRadius": "Botões",
|
"btnRadius": "Botões",
|
||||||
"cBlue": "Azul (Responder, seguir)",
|
"cBlue": "Azul (Responder, seguir)",
|
||||||
"cGreen": "Verde (Repetir)",
|
"cGreen": "Verde (Repetir)",
|
||||||
|
@ -125,7 +125,7 @@
|
||||||
"change_password_error": "Houve um erro ao modificar sua senha.",
|
"change_password_error": "Houve um erro ao modificar sua senha.",
|
||||||
"changed_password": "Senha modificada com sucesso!",
|
"changed_password": "Senha modificada com sucesso!",
|
||||||
"collapse_subject": "Esconder posts com assunto",
|
"collapse_subject": "Esconder posts com assunto",
|
||||||
"composing": "Escrevendo",
|
"composing": "Escrita",
|
||||||
"confirm_new_password": "Confirmar nova senha",
|
"confirm_new_password": "Confirmar nova senha",
|
||||||
"current_avatar": "Seu avatar atual",
|
"current_avatar": "Seu avatar atual",
|
||||||
"current_password": "Sua senha atual",
|
"current_password": "Sua senha atual",
|
||||||
|
@ -139,7 +139,7 @@
|
||||||
"avatar_size_instruction": "O tamanho mínimo recomendado para imagens de avatar é 150x150 pixels.",
|
"avatar_size_instruction": "O tamanho mínimo recomendado para imagens de avatar é 150x150 pixels.",
|
||||||
"export_theme": "Salvar predefinições",
|
"export_theme": "Salvar predefinições",
|
||||||
"filtering": "Filtragem",
|
"filtering": "Filtragem",
|
||||||
"filtering_explanation": "Todas as postagens contendo estas palavras serão silenciadas, uma por linha.",
|
"filtering_explanation": "Todas as postagens contendo estas palavras serão silenciadas; uma palavra por linha.",
|
||||||
"follow_export": "Exportar quem você segue",
|
"follow_export": "Exportar quem você segue",
|
||||||
"follow_export_button": "Exportar quem você segue para um arquivo CSV",
|
"follow_export_button": "Exportar quem você segue para um arquivo CSV",
|
||||||
"follow_export_processing": "Processando. Em breve você receberá a solicitação de download do arquivo",
|
"follow_export_processing": "Processando. Em breve você receberá a solicitação de download do arquivo",
|
||||||
|
@ -178,7 +178,7 @@
|
||||||
"name_bio": "Nome & Biografia",
|
"name_bio": "Nome & Biografia",
|
||||||
"new_password": "Nova senha",
|
"new_password": "Nova senha",
|
||||||
"notification_visibility": "Tipos de notificação para mostrar",
|
"notification_visibility": "Tipos de notificação para mostrar",
|
||||||
"notification_visibility_follows": "Seguidos",
|
"notification_visibility_follows": "Seguidas",
|
||||||
"notification_visibility_likes": "Favoritos",
|
"notification_visibility_likes": "Favoritos",
|
||||||
"notification_visibility_mentions": "Menções",
|
"notification_visibility_mentions": "Menções",
|
||||||
"notification_visibility_repeats": "Repetições",
|
"notification_visibility_repeats": "Repetições",
|
||||||
|
@ -187,7 +187,7 @@
|
||||||
"no_mutes": "Sem silenciados",
|
"no_mutes": "Sem silenciados",
|
||||||
"hide_follows_description": "Não mostrar quem estou seguindo",
|
"hide_follows_description": "Não mostrar quem estou seguindo",
|
||||||
"hide_followers_description": "Não mostrar quem me segue",
|
"hide_followers_description": "Não mostrar quem me segue",
|
||||||
"show_admin_badge": "Mostrar distintivo de Administrador em meu perfil",
|
"show_admin_badge": "Mostrar título de Administrador em meu perfil",
|
||||||
"show_moderator_badge": "Mostrar título de Moderador em meu perfil",
|
"show_moderator_badge": "Mostrar título de Moderador em meu perfil",
|
||||||
"nsfw_clickthrough": "Habilitar clique para ocultar anexos sensíveis",
|
"nsfw_clickthrough": "Habilitar clique para ocultar anexos sensíveis",
|
||||||
"oauth_tokens": "Token OAuth",
|
"oauth_tokens": "Token OAuth",
|
||||||
|
@ -201,9 +201,9 @@
|
||||||
"profile_background": "Pano de fundo de perfil",
|
"profile_background": "Pano de fundo de perfil",
|
||||||
"profile_banner": "Capa de perfil",
|
"profile_banner": "Capa de perfil",
|
||||||
"profile_tab": "Perfil",
|
"profile_tab": "Perfil",
|
||||||
"radii_help": "Arredondar arestas da interface (em píxeis)",
|
"radii_help": "Arredondar arestas da interface (em pixel)",
|
||||||
"replies_in_timeline": "Respostas na linha do tempo",
|
"replies_in_timeline": "Respostas na linha do tempo",
|
||||||
"reply_link_preview": "Habilitar a pré-visualização de link de respostas ao passar o mouse.",
|
"reply_link_preview": "Habilitar a pré-visualização de de respostas ao passar o mouse.",
|
||||||
"reply_visibility_all": "Mostrar todas as respostas",
|
"reply_visibility_all": "Mostrar todas as respostas",
|
||||||
"reply_visibility_following": "Só mostrar respostas direcionadas a mim ou a usuários que sigo",
|
"reply_visibility_following": "Só mostrar respostas direcionadas a mim ou a usuários que sigo",
|
||||||
"reply_visibility_self": "Só mostrar respostas direcionadas a mim",
|
"reply_visibility_self": "Só mostrar respostas direcionadas a mim",
|
||||||
|
@ -212,7 +212,7 @@
|
||||||
"security_tab": "Segurança",
|
"security_tab": "Segurança",
|
||||||
"scope_copy": "Copiar opções de privacidade ao responder (Mensagens diretas sempre copiam)",
|
"scope_copy": "Copiar opções de privacidade ao responder (Mensagens diretas sempre copiam)",
|
||||||
"set_new_avatar": "Alterar avatar",
|
"set_new_avatar": "Alterar avatar",
|
||||||
"set_new_profile_background": "Alterar o plano de fundo de perfil",
|
"set_new_profile_background": "Alterar o pano de fundo de perfil",
|
||||||
"set_new_profile_banner": "Alterar capa de perfil",
|
"set_new_profile_banner": "Alterar capa de perfil",
|
||||||
"settings": "Configurações",
|
"settings": "Configurações",
|
||||||
"subject_input_always_show": "Sempre mostrar campo de assunto",
|
"subject_input_always_show": "Sempre mostrar campo de assunto",
|
||||||
|
@ -220,9 +220,9 @@
|
||||||
"subject_line_email": "Como em email: \"re: assunto\"",
|
"subject_line_email": "Como em email: \"re: assunto\"",
|
||||||
"subject_line_mastodon": "Como o Mastodon: copiar como está",
|
"subject_line_mastodon": "Como o Mastodon: copiar como está",
|
||||||
"subject_line_noop": "Não copiar",
|
"subject_line_noop": "Não copiar",
|
||||||
"post_status_content_type": "Postar tipo de conteúdo do status",
|
"post_status_content_type": "Tipo de conteúdo do status",
|
||||||
"stop_gifs": "Reproduzir GIFs ao passar o cursor em cima",
|
"stop_gifs": "Reproduzir GIFs ao passar o cursor",
|
||||||
"streaming": "Habilitar o fluxo automático de postagens quando ao topo da página",
|
"streaming": "Habilitar o fluxo automático de postagens no topo da página",
|
||||||
"text": "Texto",
|
"text": "Texto",
|
||||||
"theme": "Tema",
|
"theme": "Tema",
|
||||||
"theme_help": "Use cores em código hexadecimal (#rrggbb) para personalizar seu esquema de cores.",
|
"theme_help": "Use cores em código hexadecimal (#rrggbb) para personalizar seu esquema de cores.",
|
||||||
|
@ -235,7 +235,7 @@
|
||||||
"false": "não",
|
"false": "não",
|
||||||
"true": "sim"
|
"true": "sim"
|
||||||
},
|
},
|
||||||
"notifications": "Notifications",
|
"notifications": "Notificações",
|
||||||
"enable_web_push_notifications": "Habilitar notificações web push",
|
"enable_web_push_notifications": "Habilitar notificações web push",
|
||||||
"style": {
|
"style": {
|
||||||
"switcher": {
|
"switcher": {
|
||||||
|
@ -245,7 +245,7 @@
|
||||||
"keep_roundness": "Manter arredondado",
|
"keep_roundness": "Manter arredondado",
|
||||||
"keep_fonts": "Manter fontes",
|
"keep_fonts": "Manter fontes",
|
||||||
"save_load_hint": "Manter as opções preserva as opções atuais ao selecionar ou carregar temas; também salva as opções ao exportar um tempo. Quanto todos os campos estiverem desmarcados, tudo será salvo ao exportar o tema.",
|
"save_load_hint": "Manter as opções preserva as opções atuais ao selecionar ou carregar temas; também salva as opções ao exportar um tempo. Quanto todos os campos estiverem desmarcados, tudo será salvo ao exportar o tema.",
|
||||||
"reset": "Voltar ao padrão",
|
"reset": "Restaurar o padrão",
|
||||||
"clear_all": "Limpar tudo",
|
"clear_all": "Limpar tudo",
|
||||||
"clear_opacity": "Limpar opacidade"
|
"clear_opacity": "Limpar opacidade"
|
||||||
},
|
},
|
||||||
|
@ -319,7 +319,7 @@
|
||||||
},
|
},
|
||||||
"fonts": {
|
"fonts": {
|
||||||
"_tab_label": "Fontes",
|
"_tab_label": "Fontes",
|
||||||
"help": "Selecionar fonte dos elementos da interface. Para fonte \"personalizada\" você deve entrar exatamente o nome da fonte no sistema.",
|
"help": "Selecione as fontes dos elementos da interface. Para fonte \"personalizada\" você deve inserir o mesmo nome da fonte no sistema.",
|
||||||
"components": {
|
"components": {
|
||||||
"interface": "Interface",
|
"interface": "Interface",
|
||||||
"input": "Campo de entrada",
|
"input": "Campo de entrada",
|
||||||
|
@ -383,7 +383,7 @@
|
||||||
"mute": "Silenciar",
|
"mute": "Silenciar",
|
||||||
"muted": "Silenciado",
|
"muted": "Silenciado",
|
||||||
"per_day": "por dia",
|
"per_day": "por dia",
|
||||||
"remote_follow": "Seguidor Remoto",
|
"remote_follow": "Seguir remotamente",
|
||||||
"statuses": "Postagens",
|
"statuses": "Postagens",
|
||||||
"unblock": "Desbloquear",
|
"unblock": "Desbloquear",
|
||||||
"unblock_progress": "Desbloqueando...",
|
"unblock_progress": "Desbloqueando...",
|
||||||
|
|
|
@ -60,6 +60,9 @@ export default function createPersistedState ({
|
||||||
merge({}, store.state, savedState)
|
merge({}, store.state, savedState)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
if (store.state.oauth.token) {
|
||||||
|
store.dispatch('loginUser', store.state.oauth.token)
|
||||||
|
}
|
||||||
loaded = true
|
loaded = true
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("Couldn't load state")
|
console.log("Couldn't load state")
|
||||||
|
|
|
@ -5,6 +5,7 @@ const browserLocale = (window.navigator.language || 'en').split('-')[0]
|
||||||
|
|
||||||
const defaultState = {
|
const defaultState = {
|
||||||
colors: {},
|
colors: {},
|
||||||
|
hideMutedPosts: undefined, // instance default
|
||||||
collapseMessageWithSubject: undefined, // instance default
|
collapseMessageWithSubject: undefined, // instance default
|
||||||
hideAttachments: false,
|
hideAttachments: false,
|
||||||
hideAttachmentsInConv: false,
|
hideAttachmentsInConv: false,
|
||||||
|
|
|
@ -18,6 +18,7 @@ const defaultState = {
|
||||||
scopeOptionsEnabled: true,
|
scopeOptionsEnabled: true,
|
||||||
formattingOptionsEnabled: false,
|
formattingOptionsEnabled: false,
|
||||||
alwaysShowSubjectInput: true,
|
alwaysShowSubjectInput: true,
|
||||||
|
hideMutedPosts: false,
|
||||||
collapseMessageWithSubject: false,
|
collapseMessageWithSubject: false,
|
||||||
hidePostStats: false,
|
hidePostStats: false,
|
||||||
hideUserStats: false,
|
hideUserStats: false,
|
||||||
|
@ -48,7 +49,11 @@ const defaultState = {
|
||||||
|
|
||||||
// Html stuff
|
// Html stuff
|
||||||
instanceSpecificPanelContent: '',
|
instanceSpecificPanelContent: '',
|
||||||
tos: ''
|
tos: '',
|
||||||
|
|
||||||
|
// Version Information
|
||||||
|
backendVersion: '',
|
||||||
|
frontendVersion: ''
|
||||||
}
|
}
|
||||||
|
|
||||||
const instance = {
|
const instance = {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { remove, slice, each, find, maxBy, minBy, merge, first, last, isArray, omitBy } from 'lodash'
|
import { remove, slice, each, find, maxBy, minBy, merge, first, last, isArray, omitBy } from 'lodash'
|
||||||
|
import { set } from 'vue'
|
||||||
import apiService from '../services/api/api.service.js'
|
import apiService from '../services/api/api.service.js'
|
||||||
// import parse from '../services/status_parser/status_parser.js'
|
// import parse from '../services/status_parser/status_parser.js'
|
||||||
|
|
||||||
|
@ -82,7 +83,7 @@ const mergeOrAdd = (arr, obj, item) => {
|
||||||
// This is a new item, prepare it
|
// This is a new item, prepare it
|
||||||
prepareStatus(item)
|
prepareStatus(item)
|
||||||
arr.push(item)
|
arr.push(item)
|
||||||
obj[item.id] = item
|
set(obj, item.id, item)
|
||||||
return {item, new: true}
|
return {item, new: true}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,9 +16,9 @@ export const mergeOrAdd = (arr, obj, item) => {
|
||||||
} else {
|
} else {
|
||||||
// This is a new item, prepare it
|
// This is a new item, prepare it
|
||||||
arr.push(item)
|
arr.push(item)
|
||||||
obj[item.id] = item
|
set(obj, item.id, item)
|
||||||
if (item.screen_name && !item.screen_name.includes('@')) {
|
if (item.screen_name && !item.screen_name.includes('@')) {
|
||||||
obj[item.screen_name.toLowerCase()] = item
|
set(obj, item.screen_name.toLowerCase(), item)
|
||||||
}
|
}
|
||||||
return { item, new: true }
|
return { item, new: true }
|
||||||
}
|
}
|
||||||
|
@ -102,10 +102,20 @@ export const mutations = {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
saveBlocks (state, blockIds) {
|
updateBlocks (state, blockedUsers) {
|
||||||
|
// Reset statusnet_blocking of all fetched users
|
||||||
|
each(state.users, (user) => { user.statusnet_blocking = false })
|
||||||
|
each(blockedUsers, (user) => mergeOrAdd(state.users, state.usersObject, user))
|
||||||
|
},
|
||||||
|
saveBlockIds (state, blockIds) {
|
||||||
state.currentUser.blockIds = blockIds
|
state.currentUser.blockIds = blockIds
|
||||||
},
|
},
|
||||||
saveMutes (state, muteIds) {
|
updateMutes (state, mutedUsers) {
|
||||||
|
// Reset muted of all fetched users
|
||||||
|
each(state.users, (user) => { user.muted = false })
|
||||||
|
each(mutedUsers, (user) => mergeOrAdd(state.users, state.usersObject, user))
|
||||||
|
},
|
||||||
|
saveMuteIds (state, muteIds) {
|
||||||
state.currentUser.muteIds = muteIds
|
state.currentUser.muteIds = muteIds
|
||||||
},
|
},
|
||||||
setUserForStatus (state, status) {
|
setUserForStatus (state, status) {
|
||||||
|
@ -172,34 +182,39 @@ const users = {
|
||||||
fetchBlocks (store) {
|
fetchBlocks (store) {
|
||||||
return store.rootState.api.backendInteractor.fetchBlocks()
|
return store.rootState.api.backendInteractor.fetchBlocks()
|
||||||
.then((blocks) => {
|
.then((blocks) => {
|
||||||
store.commit('saveBlocks', map(blocks, 'id'))
|
store.commit('saveBlockIds', map(blocks, 'id'))
|
||||||
store.commit('addNewUsers', blocks)
|
store.commit('updateBlocks', blocks)
|
||||||
return blocks
|
return blocks
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
blockUser (store, id) {
|
blockUser (store, userId) {
|
||||||
return store.rootState.api.backendInteractor.blockUser(id)
|
return store.rootState.api.backendInteractor.blockUser(userId)
|
||||||
.then((user) => store.commit('addNewUsers', [user]))
|
.then((relationship) => {
|
||||||
|
store.commit('updateUserRelationship', [relationship])
|
||||||
|
store.commit('removeStatus', { timeline: 'friends', userId })
|
||||||
|
store.commit('removeStatus', { timeline: 'public', userId })
|
||||||
|
store.commit('removeStatus', { timeline: 'publicAndExternal', userId })
|
||||||
|
})
|
||||||
},
|
},
|
||||||
unblockUser (store, id) {
|
unblockUser (store, id) {
|
||||||
return store.rootState.api.backendInteractor.unblockUser(id)
|
return store.rootState.api.backendInteractor.unblockUser(id)
|
||||||
.then((user) => store.commit('addNewUsers', [user]))
|
.then((relationship) => store.commit('updateUserRelationship', [relationship]))
|
||||||
},
|
},
|
||||||
fetchMutes (store) {
|
fetchMutes (store) {
|
||||||
return store.rootState.api.backendInteractor.fetchMutes()
|
return store.rootState.api.backendInteractor.fetchMutes()
|
||||||
.then((mutedUsers) => {
|
.then((mutes) => {
|
||||||
each(mutedUsers, (user) => { user.muted = true })
|
store.commit('updateMutes', mutes)
|
||||||
store.commit('addNewUsers', mutedUsers)
|
store.commit('saveMuteIds', map(mutes, 'id'))
|
||||||
store.commit('saveMutes', map(mutedUsers, 'id'))
|
return mutes
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
muteUser (store, id) {
|
muteUser (store, id) {
|
||||||
return store.state.api.backendInteractor.setUserMute({ id, muted: true })
|
return store.rootState.api.backendInteractor.muteUser(id)
|
||||||
.then((user) => store.commit('addNewUsers', [user]))
|
.then((relationship) => store.commit('updateUserRelationship', [relationship]))
|
||||||
},
|
},
|
||||||
unmuteUser (store, id) {
|
unmuteUser (store, id) {
|
||||||
return store.state.api.backendInteractor.setUserMute({ id, muted: false })
|
return store.rootState.api.backendInteractor.unmuteUser(id)
|
||||||
.then((user) => store.commit('addNewUsers', [user]))
|
.then((relationship) => store.commit('updateUserRelationship', [relationship]))
|
||||||
},
|
},
|
||||||
addFriends ({ rootState, commit }, fetchBy) {
|
addFriends ({ rootState, commit }, fetchBy) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
|
|
@ -9,19 +9,13 @@ const FAVORITE_URL = '/api/favorites/create'
|
||||||
const UNFAVORITE_URL = '/api/favorites/destroy'
|
const UNFAVORITE_URL = '/api/favorites/destroy'
|
||||||
const RETWEET_URL = '/api/statuses/retweet'
|
const RETWEET_URL = '/api/statuses/retweet'
|
||||||
const UNRETWEET_URL = '/api/statuses/unretweet'
|
const UNRETWEET_URL = '/api/statuses/unretweet'
|
||||||
const STATUS_UPDATE_URL = '/api/statuses/update.json'
|
|
||||||
const STATUS_DELETE_URL = '/api/statuses/destroy'
|
const STATUS_DELETE_URL = '/api/statuses/destroy'
|
||||||
const STATUS_URL = '/api/statuses/show'
|
|
||||||
const MEDIA_UPLOAD_URL = '/api/statusnet/media/upload'
|
|
||||||
const CONVERSATION_URL = '/api/statusnet/conversation'
|
|
||||||
const MENTIONS_URL = '/api/statuses/mentions.json'
|
const MENTIONS_URL = '/api/statuses/mentions.json'
|
||||||
const DM_TIMELINE_URL = '/api/statuses/dm_timeline.json'
|
const DM_TIMELINE_URL = '/api/statuses/dm_timeline.json'
|
||||||
const FOLLOWERS_URL = '/api/statuses/followers.json'
|
const FOLLOWERS_URL = '/api/statuses/followers.json'
|
||||||
const FRIENDS_URL = '/api/statuses/friends.json'
|
const FRIENDS_URL = '/api/statuses/friends.json'
|
||||||
const BLOCKS_URL = '/api/statuses/blocks.json'
|
|
||||||
const FOLLOWING_URL = '/api/friendships/create.json'
|
const FOLLOWING_URL = '/api/friendships/create.json'
|
||||||
const UNFOLLOWING_URL = '/api/friendships/destroy.json'
|
const UNFOLLOWING_URL = '/api/friendships/destroy.json'
|
||||||
const QVITTER_USER_PREF_URL = '/api/qvitter/set_profile_pref.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 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'
|
||||||
|
@ -29,8 +23,6 @@ const BANNER_UPDATE_URL = '/api/account/update_profile_banner.json'
|
||||||
const PROFILE_UPDATE_URL = '/api/account/update_profile.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 BLOCKING_URL = '/api/blocks/create.json'
|
|
||||||
const UNBLOCKING_URL = '/api/blocks/destroy.json'
|
|
||||||
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'
|
||||||
|
@ -41,12 +33,22 @@ const SUGGESTIONS_URL = '/api/v1/suggestions'
|
||||||
|
|
||||||
const MASTODON_USER_FAVORITES_TIMELINE_URL = '/api/v1/favourites'
|
const MASTODON_USER_FAVORITES_TIMELINE_URL = '/api/v1/favourites'
|
||||||
const MASTODON_USER_NOTIFICATIONS_URL = '/api/v1/notifications'
|
const MASTODON_USER_NOTIFICATIONS_URL = '/api/v1/notifications'
|
||||||
|
const MASTODON_STATUS_URL = id => `/api/v1/statuses/${id}`
|
||||||
|
const MASTODON_STATUS_CONTEXT_URL = id => `/api/v1/statuses/${id}/context`
|
||||||
const MASTODON_USER_URL = '/api/v1/accounts'
|
const MASTODON_USER_URL = '/api/v1/accounts'
|
||||||
const MASTODON_USER_RELATIONSHIPS_URL = '/api/v1/accounts/relationships'
|
const MASTODON_USER_RELATIONSHIPS_URL = '/api/v1/accounts/relationships'
|
||||||
const MASTODON_USER_TIMELINE_URL = id => `/api/v1/accounts/${id}/statuses`
|
const MASTODON_USER_TIMELINE_URL = id => `/api/v1/accounts/${id}/statuses`
|
||||||
|
const MASTODON_USER_BLOCKS_URL = '/api/v1/blocks/'
|
||||||
|
const MASTODON_USER_MUTES_URL = '/api/v1/mutes/'
|
||||||
|
const MASTODON_BLOCK_USER_URL = id => `/api/v1/accounts/${id}/block`
|
||||||
|
const MASTODON_UNBLOCK_USER_URL = id => `/api/v1/accounts/${id}/unblock`
|
||||||
|
const MASTODON_MUTE_USER_URL = id => `/api/v1/accounts/${id}/mute`
|
||||||
|
const MASTODON_UNMUTE_USER_URL = id => `/api/v1/accounts/${id}/unmute`
|
||||||
|
const MASTODON_POST_STATUS_URL = '/api/v1/statuses'
|
||||||
|
const MASTODON_MEDIA_UPLOAD_URL = '/api/v1/media'
|
||||||
|
|
||||||
import { each, map } from 'lodash'
|
import { each, map } from 'lodash'
|
||||||
import { parseStatus, parseUser, parseNotification } from '../entity_normalizer/entity_normalizer.service.js'
|
import { parseStatus, parseUser, parseNotification, parseAttachment } from '../entity_normalizer/entity_normalizer.service.js'
|
||||||
import 'whatwg-fetch'
|
import 'whatwg-fetch'
|
||||||
import { StatusCodeError } from '../errors/errors'
|
import { StatusCodeError } from '../errors/errors'
|
||||||
|
|
||||||
|
@ -60,6 +62,19 @@ let fetch = (url, options) => {
|
||||||
return oldfetch(fullUrl, options)
|
return oldfetch(fullUrl, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const promisedRequest = (url, options) => {
|
||||||
|
return fetch(url, options)
|
||||||
|
.then((response) => {
|
||||||
|
return new Promise((resolve, reject) => response.json()
|
||||||
|
.then((json) => {
|
||||||
|
if (!response.ok) {
|
||||||
|
return reject(new StatusCodeError(response.status, json, { url, options }, response))
|
||||||
|
}
|
||||||
|
return resolve(json)
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Params
|
// Params
|
||||||
// cropH
|
// cropH
|
||||||
// cropW
|
// cropW
|
||||||
|
@ -212,16 +227,14 @@ const unfollowUser = ({id, credentials}) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const blockUser = ({id, credentials}) => {
|
const blockUser = ({id, credentials}) => {
|
||||||
let url = `${BLOCKING_URL}?user_id=${id}`
|
return fetch(MASTODON_BLOCK_USER_URL(id), {
|
||||||
return fetch(url, {
|
|
||||||
headers: authHeaders(credentials),
|
headers: authHeaders(credentials),
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
}).then((data) => data.json())
|
}).then((data) => data.json())
|
||||||
}
|
}
|
||||||
|
|
||||||
const unblockUser = ({id, credentials}) => {
|
const unblockUser = ({id, credentials}) => {
|
||||||
let url = `${UNBLOCKING_URL}?user_id=${id}`
|
return fetch(MASTODON_UNBLOCK_USER_URL(id), {
|
||||||
return fetch(url, {
|
|
||||||
headers: authHeaders(credentials),
|
headers: authHeaders(credentials),
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
}).then((data) => data.json())
|
}).then((data) => data.json())
|
||||||
|
@ -245,16 +258,7 @@ const denyUser = ({id, credentials}) => {
|
||||||
|
|
||||||
const fetchUser = ({id, credentials}) => {
|
const fetchUser = ({id, credentials}) => {
|
||||||
let url = `${MASTODON_USER_URL}/${id}`
|
let url = `${MASTODON_USER_URL}/${id}`
|
||||||
return fetch(url, { headers: authHeaders(credentials) })
|
return promisedRequest(url, { headers: authHeaders(credentials) })
|
||||||
.then((response) => {
|
|
||||||
return new Promise((resolve, reject) => response.json()
|
|
||||||
.then((json) => {
|
|
||||||
if (!response.ok) {
|
|
||||||
return reject(new StatusCodeError(response.status, json, { url }, response))
|
|
||||||
}
|
|
||||||
return resolve(json)
|
|
||||||
}))
|
|
||||||
})
|
|
||||||
.then((data) => parseUser(data))
|
.then((data) => parseUser(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -313,8 +317,8 @@ const fetchFollowRequests = ({credentials}) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const fetchConversation = ({id, credentials}) => {
|
const fetchConversation = ({id, credentials}) => {
|
||||||
let url = `${CONVERSATION_URL}/${id}.json?count=100`
|
let urlContext = MASTODON_STATUS_CONTEXT_URL(id)
|
||||||
return fetch(url, { headers: authHeaders(credentials) })
|
return fetch(urlContext, { headers: authHeaders(credentials) })
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (data.ok) {
|
if (data.ok) {
|
||||||
return data
|
return data
|
||||||
|
@ -322,11 +326,14 @@ const fetchConversation = ({id, credentials}) => {
|
||||||
throw new Error('Error fetching timeline', data)
|
throw new Error('Error fetching timeline', data)
|
||||||
})
|
})
|
||||||
.then((data) => data.json())
|
.then((data) => data.json())
|
||||||
.then((data) => data.map(parseStatus))
|
.then(({ancestors, descendants}) => ({
|
||||||
|
ancestors: ancestors.map(parseStatus),
|
||||||
|
descendants: descendants.map(parseStatus)
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
const fetchStatus = ({id, credentials}) => {
|
const fetchStatus = ({id, credentials}) => {
|
||||||
let url = `${STATUS_URL}/${id}.json`
|
let url = MASTODON_STATUS_URL(id)
|
||||||
return fetch(url, { headers: authHeaders(credentials) })
|
return fetch(url, { headers: authHeaders(credentials) })
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (data.ok) {
|
if (data.ok) {
|
||||||
|
@ -338,23 +345,7 @@ const fetchStatus = ({id, credentials}) => {
|
||||||
.then((data) => parseStatus(data))
|
.then((data) => parseStatus(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
const setUserMute = ({id, credentials, muted = true}) => {
|
const fetchTimeline = ({timeline, credentials, since = false, until = false, userId = false, tag = false, withMuted = false}) => {
|
||||||
const form = new FormData()
|
|
||||||
|
|
||||||
const muteInteger = muted ? 1 : 0
|
|
||||||
|
|
||||||
form.append('namespace', 'qvitter')
|
|
||||||
form.append('data', muteInteger)
|
|
||||||
form.append('topic', `mute:${id}`)
|
|
||||||
|
|
||||||
return fetch(QVITTER_USER_PREF_URL, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: authHeaders(credentials),
|
|
||||||
body: form
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const fetchTimeline = ({timeline, credentials, since = false, until = false, userId = false, tag = false}) => {
|
|
||||||
const timelineUrls = {
|
const timelineUrls = {
|
||||||
public: PUBLIC_TIMELINE_URL,
|
public: PUBLIC_TIMELINE_URL,
|
||||||
friends: FRIENDS_TIMELINE_URL,
|
friends: FRIENDS_TIMELINE_URL,
|
||||||
|
@ -390,6 +381,7 @@ const fetchTimeline = ({timeline, credentials, since = false, until = false, use
|
||||||
}
|
}
|
||||||
|
|
||||||
params.push(['count', 20])
|
params.push(['count', 20])
|
||||||
|
params.push(['with_muted', withMuted])
|
||||||
|
|
||||||
const queryString = map(params, (param) => `${param[0]}=${param[1]}`).join('&')
|
const queryString = map(params, (param) => `${param[0]}=${param[1]}`).join('&')
|
||||||
url += `?${queryString}`
|
url += `?${queryString}`
|
||||||
|
@ -450,23 +442,23 @@ const unretweet = ({ id, credentials }) => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const postStatus = ({credentials, status, spoilerText, visibility, sensitive, mediaIds, inReplyToStatusId, contentType, noAttachmentLinks}) => {
|
const postStatus = ({credentials, status, spoilerText, visibility, sensitive, mediaIds = [], inReplyToStatusId, contentType}) => {
|
||||||
const idsText = mediaIds.join(',')
|
|
||||||
const form = new FormData()
|
const form = new FormData()
|
||||||
|
|
||||||
form.append('status', status)
|
form.append('status', status)
|
||||||
form.append('source', 'Pleroma FE')
|
form.append('source', 'Pleroma FE')
|
||||||
if (noAttachmentLinks) form.append('no_attachment_links', noAttachmentLinks)
|
|
||||||
if (spoilerText) form.append('spoiler_text', spoilerText)
|
if (spoilerText) form.append('spoiler_text', spoilerText)
|
||||||
if (visibility) form.append('visibility', visibility)
|
if (visibility) form.append('visibility', visibility)
|
||||||
if (sensitive) form.append('sensitive', sensitive)
|
if (sensitive) form.append('sensitive', sensitive)
|
||||||
if (contentType) form.append('content_type', contentType)
|
if (contentType) form.append('content_type', contentType)
|
||||||
form.append('media_ids', idsText)
|
mediaIds.forEach(val => {
|
||||||
|
form.append('media_ids[]', val)
|
||||||
|
})
|
||||||
if (inReplyToStatusId) {
|
if (inReplyToStatusId) {
|
||||||
form.append('in_reply_to_status_id', inReplyToStatusId)
|
form.append('in_reply_to_id', inReplyToStatusId)
|
||||||
}
|
}
|
||||||
|
|
||||||
return fetch(STATUS_UPDATE_URL, {
|
return fetch(MASTODON_POST_STATUS_URL, {
|
||||||
body: form,
|
body: form,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: authHeaders(credentials)
|
headers: authHeaders(credentials)
|
||||||
|
@ -491,13 +483,13 @@ const deleteStatus = ({ id, credentials }) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const uploadMedia = ({formData, credentials}) => {
|
const uploadMedia = ({formData, credentials}) => {
|
||||||
return fetch(MEDIA_UPLOAD_URL, {
|
return fetch(MASTODON_MEDIA_UPLOAD_URL, {
|
||||||
body: formData,
|
body: formData,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: authHeaders(credentials)
|
headers: authHeaders(credentials)
|
||||||
})
|
})
|
||||||
.then((response) => response.text())
|
.then((data) => data.json())
|
||||||
.then((text) => (new DOMParser()).parseFromString(text, 'application/xml'))
|
.then((data) => parseAttachment(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
const followImport = ({params, credentials}) => {
|
const followImport = ({params, credentials}) => {
|
||||||
|
@ -538,30 +530,40 @@ const changePassword = ({credentials, password, newPassword, newPasswordConfirma
|
||||||
}
|
}
|
||||||
|
|
||||||
const fetchMutes = ({credentials}) => {
|
const fetchMutes = ({credentials}) => {
|
||||||
const url = '/api/qvitter/mutes.json'
|
return promisedRequest(MASTODON_USER_MUTES_URL, { headers: authHeaders(credentials) })
|
||||||
|
.then((users) => users.map(parseUser))
|
||||||
return fetch(url, {
|
|
||||||
headers: authHeaders(credentials)
|
|
||||||
}).then((data) => data.json())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const fetchBlocks = ({page, credentials}) => {
|
const muteUser = ({id, credentials}) => {
|
||||||
return fetch(BLOCKS_URL, {
|
return promisedRequest(MASTODON_MUTE_USER_URL(id), {
|
||||||
headers: authHeaders(credentials)
|
headers: authHeaders(credentials),
|
||||||
}).then((data) => {
|
method: 'POST'
|
||||||
if (data.ok) {
|
|
||||||
return data.json()
|
|
||||||
}
|
|
||||||
throw new Error('Error fetching blocks', data)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const unmuteUser = ({id, credentials}) => {
|
||||||
|
return promisedRequest(MASTODON_UNMUTE_USER_URL(id), {
|
||||||
|
headers: authHeaders(credentials),
|
||||||
|
method: 'POST'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchBlocks = ({credentials}) => {
|
||||||
|
return promisedRequest(MASTODON_USER_BLOCKS_URL, { headers: authHeaders(credentials) })
|
||||||
|
.then((users) => users.map(parseUser))
|
||||||
|
}
|
||||||
|
|
||||||
const fetchOAuthTokens = ({credentials}) => {
|
const fetchOAuthTokens = ({credentials}) => {
|
||||||
const url = '/api/oauth_tokens.json'
|
const url = '/api/oauth_tokens.json'
|
||||||
|
|
||||||
return fetch(url, {
|
return fetch(url, {
|
||||||
headers: authHeaders(credentials)
|
headers: authHeaders(credentials)
|
||||||
}).then((data) => data.json())
|
}).then((data) => {
|
||||||
|
if (data.ok) {
|
||||||
|
return data.json()
|
||||||
|
}
|
||||||
|
throw new Error('Error fetching auth tokens', data)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const revokeOAuthToken = ({id, credentials}) => {
|
const revokeOAuthToken = ({id, credentials}) => {
|
||||||
|
@ -613,8 +615,9 @@ const apiService = {
|
||||||
deleteStatus,
|
deleteStatus,
|
||||||
uploadMedia,
|
uploadMedia,
|
||||||
fetchAllFollowing,
|
fetchAllFollowing,
|
||||||
setUserMute,
|
|
||||||
fetchMutes,
|
fetchMutes,
|
||||||
|
muteUser,
|
||||||
|
unmuteUser,
|
||||||
fetchBlocks,
|
fetchBlocks,
|
||||||
fetchOAuthTokens,
|
fetchOAuthTokens,
|
||||||
revokeOAuthToken,
|
revokeOAuthToken,
|
||||||
|
|
|
@ -62,12 +62,10 @@ const backendInteractorService = (credentials) => {
|
||||||
return timelineFetcherService.startFetching({timeline, store, credentials, userId, tag})
|
return timelineFetcherService.startFetching({timeline, store, credentials, userId, tag})
|
||||||
}
|
}
|
||||||
|
|
||||||
const setUserMute = ({id, muted = true}) => {
|
|
||||||
return apiService.setUserMute({id, muted, credentials})
|
|
||||||
}
|
|
||||||
|
|
||||||
const fetchMutes = () => apiService.fetchMutes({credentials})
|
const fetchMutes = () => apiService.fetchMutes({credentials})
|
||||||
const fetchBlocks = (params) => apiService.fetchBlocks({credentials, ...params})
|
const muteUser = (id) => apiService.muteUser({credentials, id})
|
||||||
|
const unmuteUser = (id) => apiService.unmuteUser({credentials, id})
|
||||||
|
const fetchBlocks = () => apiService.fetchBlocks({credentials})
|
||||||
const fetchFollowRequests = () => apiService.fetchFollowRequests({credentials})
|
const fetchFollowRequests = () => apiService.fetchFollowRequests({credentials})
|
||||||
const fetchOAuthTokens = () => apiService.fetchOAuthTokens({credentials})
|
const fetchOAuthTokens = () => apiService.fetchOAuthTokens({credentials})
|
||||||
const revokeOAuthToken = (id) => apiService.revokeOAuthToken({id, credentials})
|
const revokeOAuthToken = (id) => apiService.revokeOAuthToken({id, credentials})
|
||||||
|
@ -100,8 +98,9 @@ const backendInteractorService = (credentials) => {
|
||||||
fetchAllFollowing,
|
fetchAllFollowing,
|
||||||
verifyCredentials: apiService.verifyCredentials,
|
verifyCredentials: apiService.verifyCredentials,
|
||||||
startFetching,
|
startFetching,
|
||||||
setUserMute,
|
|
||||||
fetchMutes,
|
fetchMutes,
|
||||||
|
muteUser,
|
||||||
|
unmuteUser,
|
||||||
fetchBlocks,
|
fetchBlocks,
|
||||||
fetchOAuthTokens,
|
fetchOAuthTokens,
|
||||||
revokeOAuthToken,
|
revokeOAuthToken,
|
||||||
|
|
|
@ -128,14 +128,15 @@ export const parseUser = (data) => {
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
const parseAttachment = (data) => {
|
export const parseAttachment = (data) => {
|
||||||
const output = {}
|
const output = {}
|
||||||
const masto = !data.hasOwnProperty('oembed')
|
const masto = !data.hasOwnProperty('oembed')
|
||||||
|
|
||||||
if (masto) {
|
if (masto) {
|
||||||
// Not exactly same...
|
// Not exactly same...
|
||||||
output.mimetype = data.type
|
output.mimetype = data.pleroma ? data.pleroma.mime_type : data.type
|
||||||
output.meta = data.meta // not present in BE yet
|
output.meta = data.meta // not present in BE yet
|
||||||
|
output.id = data.id
|
||||||
} else {
|
} else {
|
||||||
output.mimetype = data.mimetype
|
output.mimetype = data.mimetype
|
||||||
// output.meta = ??? missing
|
// output.meta = ??? missing
|
||||||
|
@ -311,5 +312,5 @@ export const parseNotification = (data) => {
|
||||||
|
|
||||||
const isNsfw = (status) => {
|
const isNsfw = (status) => {
|
||||||
const nsfwRegex = /#nsfw/i
|
const nsfwRegex = /#nsfw/i
|
||||||
return (status.tags || []).includes('nsfw') || !!status.text.match(nsfwRegex)
|
return (status.tags || []).includes('nsfw') || !!(status.text || '').match(nsfwRegex)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
import utils from './utils.js'
|
import utils from './utils.js'
|
||||||
|
import { parseUser } from '../entity_normalizer/entity_normalizer.service.js'
|
||||||
|
|
||||||
const search = ({query, store}) => {
|
const search = ({query, store}) => {
|
||||||
return utils.request({
|
return utils.request({
|
||||||
store,
|
store,
|
||||||
url: '/api/pleroma/search_user',
|
url: '/api/v1/accounts/search',
|
||||||
params: {
|
params: {
|
||||||
query
|
q: query
|
||||||
}
|
}
|
||||||
}).then((data) => data.json())
|
})
|
||||||
|
.then((data) => data.json())
|
||||||
|
.then((data) => data.map(parseUser))
|
||||||
}
|
}
|
||||||
const UserSearch = {
|
const UserSearch = {
|
||||||
search
|
search
|
||||||
|
|
|
@ -4,7 +4,7 @@ import apiService from '../api/api.service.js'
|
||||||
const postStatus = ({ store, status, spoilerText, visibility, sensitive, media = [], inReplyToStatusId = undefined, contentType = 'text/plain' }) => {
|
const postStatus = ({ store, status, spoilerText, visibility, sensitive, media = [], inReplyToStatusId = undefined, contentType = 'text/plain' }) => {
|
||||||
const mediaIds = map(media, 'id')
|
const mediaIds = map(media, 'id')
|
||||||
|
|
||||||
return apiService.postStatus({credentials: store.state.users.currentUser.credentials, status, spoilerText, visibility, sensitive, mediaIds, inReplyToStatusId, contentType, noAttachmentLinks: store.state.instance.noAttachmentLinks})
|
return apiService.postStatus({credentials: store.state.users.currentUser.credentials, status, spoilerText, visibility, sensitive, mediaIds, inReplyToStatusId, contentType})
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (!data.error) {
|
if (!data.error) {
|
||||||
store.dispatch('addNewStatuses', {
|
store.dispatch('addNewStatuses', {
|
||||||
|
@ -26,25 +26,7 @@ const postStatus = ({ store, status, spoilerText, visibility, sensitive, media =
|
||||||
const uploadMedia = ({ store, formData }) => {
|
const uploadMedia = ({ store, formData }) => {
|
||||||
const credentials = store.state.users.currentUser.credentials
|
const credentials = store.state.users.currentUser.credentials
|
||||||
|
|
||||||
return apiService.uploadMedia({ credentials, formData }).then((xml) => {
|
return apiService.uploadMedia({ credentials, formData })
|
||||||
// Firefox and Chrome treat method differently...
|
|
||||||
let link = xml.getElementsByTagName('link')
|
|
||||||
|
|
||||||
if (link.length === 0) {
|
|
||||||
link = xml.getElementsByTagName('atom:link')
|
|
||||||
}
|
|
||||||
|
|
||||||
link = link[0]
|
|
||||||
|
|
||||||
const mediaData = {
|
|
||||||
id: xml.getElementsByTagName('media_id')[0].textContent,
|
|
||||||
url: xml.getElementsByTagName('media_url')[0].textContent,
|
|
||||||
image: link.getAttribute('href'),
|
|
||||||
mimetype: link.getAttribute('type')
|
|
||||||
}
|
|
||||||
|
|
||||||
return mediaData
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const statusPosterService = {
|
const statusPosterService = {
|
||||||
|
|
|
@ -19,6 +19,9 @@ const fetchAndUpdate = ({store, credentials, timeline = 'friends', older = false
|
||||||
const args = { timeline, credentials }
|
const args = { timeline, credentials }
|
||||||
const rootState = store.rootState || store.state
|
const rootState = store.rootState || store.state
|
||||||
const timelineData = rootState.statuses.timelines[camelCase(timeline)]
|
const timelineData = rootState.statuses.timelines[camelCase(timeline)]
|
||||||
|
const hideMutedPosts = typeof rootState.config.hideMutedPosts === 'undefined'
|
||||||
|
? rootState.instance.hideMutedPosts
|
||||||
|
: rootState.config.hideMutedPosts
|
||||||
|
|
||||||
if (older) {
|
if (older) {
|
||||||
args['until'] = until || timelineData.minId
|
args['until'] = until || timelineData.minId
|
||||||
|
@ -28,6 +31,7 @@ const fetchAndUpdate = ({store, credentials, timeline = 'friends', older = false
|
||||||
|
|
||||||
args['userId'] = userId
|
args['userId'] = userId
|
||||||
args['tag'] = tag
|
args['tag'] = tag
|
||||||
|
args['withMuted'] = !hideMutedPosts
|
||||||
|
|
||||||
const numStatusesBeforeFetch = timelineData.statuses.length
|
const numStatusesBeforeFetch = timelineData.statuses.length
|
||||||
|
|
||||||
|
|
6
src/services/version/version.service.js
Normal file
6
src/services/version/version.service.js
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
|
||||||
|
export const extractCommit = versionString => {
|
||||||
|
const regex = /-g(\w+)$/i
|
||||||
|
const matches = versionString.match(regex)
|
||||||
|
return matches ? matches[1] : ''
|
||||||
|
}
|
Loading…
Reference in a new issue