Merge remote-tracking branch 'origin/develop' into shigusegubu
* origin/develop: (38 commits) give notification timeago a min width streamline profile image api, update reset ui for all profile images to match avatar, remove unnecessary stuff corrected tos.html location Translated using Weblate (Italian) Translated using Weblate (Chinese (Simplified)) Translated using Weblate (Italian) Translated using Weblate (Finnish) Apply suggestion to src/components/staff_panel/staff_panel.js StaffPanel: Move staff loading to panel creation. Apply suggestion to src/boot/after_store.js fix preview opening automatically After Store: Correctly handle preloaded HTML remove console log fix issue on posting another status remove unnecessary code add more ways to set description fix edge case of videos and unknown files together fix modal types check being broken don't close preview on post, move visibility notices above the preview where they belong remove contenttype check from content type watcher ...
This commit is contained in:
commit
4e8499abad
33 changed files with 684 additions and 241 deletions
|
@ -19,6 +19,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Autocomplete domains from list of known instances
|
- Autocomplete domains from list of known instances
|
||||||
- 'Bot' settings option and badge
|
- 'Bot' settings option and badge
|
||||||
- Added profile meta data fields that can be set in profile settings
|
- Added profile meta data fields that can be set in profile settings
|
||||||
|
- Added option to reset avatar/banner in profile settings
|
||||||
|
- Descriptions can be set on uploaded files before posting
|
||||||
|
- Added status preview option to preview your statuses before posting
|
||||||
- When a post is a reply to an unavailable post, the 'Reply to'-text has a strike-through style
|
- When a post is a reply to an unavailable post, the 'Reply to'-text has a strike-through style
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
@ -27,6 +30,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Close the media modal on navigation events
|
- Close the media modal on navigation events
|
||||||
- Add colons to the emoji alt text, to make them copyable
|
- Add colons to the emoji alt text, to make them copyable
|
||||||
- Add better visual indication for drag-and-drop for files
|
- Add better visual indication for drag-and-drop for files
|
||||||
|
- When disabling attachments, the placeholder links now show an icon and the description instead of just IMAGE or VIDEO etc
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Custom Emoji will display in poll options now.
|
- Custom Emoji will display in poll options now.
|
||||||
|
@ -38,6 +42,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Subject field now appears disabled when posting
|
- Subject field now appears disabled when posting
|
||||||
- Fix status ellipsis menu being cut off in notifications column
|
- Fix status ellipsis menu being cut off in notifications column
|
||||||
- Fixed autocomplete sometimes not returning the right user when there's already some results
|
- Fixed autocomplete sometimes not returning the right user when there's already some results
|
||||||
|
- Videos and audio and misc files show description as alt/title properly now
|
||||||
|
- Clicking on non-image/video files no longer opens an empty modal
|
||||||
|
- Audio files can now be played back in the frontend with hidden attachments
|
||||||
|
- Videos are not cropped awkwardly in the uploads section anymore
|
||||||
- Reply filtering options in Settings -> Filtering now work again using filtering on server
|
- Reply filtering options in Settings -> Filtering now work again using filtering on server
|
||||||
- Don't show just blank-screen when cookies are disabled
|
- Don't show just blank-screen when cookies are disabled
|
||||||
|
|
||||||
|
|
|
@ -25,10 +25,10 @@ const preloadFetch = async (request) => {
|
||||||
if (!data || !data[request]) {
|
if (!data || !data[request]) {
|
||||||
return window.fetch(request)
|
return window.fetch(request)
|
||||||
}
|
}
|
||||||
const requestData = atob(data[request])
|
const requestData = JSON.parse(atob(data[request]))
|
||||||
return {
|
return {
|
||||||
ok: true,
|
ok: true,
|
||||||
json: () => JSON.parse(requestData),
|
json: () => requestData,
|
||||||
text: () => requestData
|
text: () => requestData
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -215,7 +215,6 @@ const getAppSecret = async ({ store }) => {
|
||||||
|
|
||||||
const resolveStaffAccounts = ({ store, accounts }) => {
|
const resolveStaffAccounts = ({ store, accounts }) => {
|
||||||
const nicknames = accounts.map(uri => uri.split('/').pop())
|
const nicknames = accounts.map(uri => uri.split('/').pop())
|
||||||
nicknames.map(nickname => store.dispatch('fetchUser', nickname))
|
|
||||||
store.dispatch('setInstanceOption', { name: 'staffAccounts', value: nicknames })
|
store.dispatch('setInstanceOption', { name: 'staffAccounts', value: nicknames })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@ const Attachment = {
|
||||||
props: [
|
props: [
|
||||||
'attachment',
|
'attachment',
|
||||||
'nsfw',
|
'nsfw',
|
||||||
'statusId',
|
|
||||||
'size',
|
'size',
|
||||||
'allowPlay',
|
'allowPlay',
|
||||||
'setMedia',
|
'setMedia',
|
||||||
|
@ -30,9 +29,21 @@ const Attachment = {
|
||||||
VideoAttachment
|
VideoAttachment
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
usePlaceHolder () {
|
usePlaceholder () {
|
||||||
return this.size === 'hide' || this.type === 'unknown'
|
return this.size === 'hide' || this.type === 'unknown'
|
||||||
},
|
},
|
||||||
|
placeholderName () {
|
||||||
|
if (this.attachment.description === '' || !this.attachment.description) {
|
||||||
|
return this.type.toUpperCase()
|
||||||
|
}
|
||||||
|
return this.attachment.description
|
||||||
|
},
|
||||||
|
placeholderIconClass () {
|
||||||
|
if (this.type === 'image') return 'icon-picture'
|
||||||
|
if (this.type === 'video') return 'icon-video'
|
||||||
|
if (this.type === 'audio') return 'icon-music'
|
||||||
|
return 'icon-doc'
|
||||||
|
},
|
||||||
referrerpolicy () {
|
referrerpolicy () {
|
||||||
return this.$store.state.instance.mediaProxyAvailable ? '' : 'no-referrer'
|
return this.$store.state.instance.mediaProxyAvailable ? '' : 'no-referrer'
|
||||||
},
|
},
|
||||||
|
@ -49,7 +60,15 @@ const Attachment = {
|
||||||
return this.size === 'small'
|
return this.size === 'small'
|
||||||
},
|
},
|
||||||
fullwidth () {
|
fullwidth () {
|
||||||
return this.type === 'html' || this.type === 'audio'
|
if (this.size === 'hide') return false
|
||||||
|
return this.type === 'html' || this.type === 'audio' || this.type === 'unknown'
|
||||||
|
},
|
||||||
|
useModal () {
|
||||||
|
const modalTypes = this.size === 'hide' ? ['image', 'video', 'audio']
|
||||||
|
: this.mergedConfig.playVideosInModal
|
||||||
|
? ['image', 'video']
|
||||||
|
: ['image']
|
||||||
|
return modalTypes.includes(this.type)
|
||||||
},
|
},
|
||||||
...mapGetters(['mergedConfig'])
|
...mapGetters(['mergedConfig'])
|
||||||
},
|
},
|
||||||
|
@ -60,12 +79,7 @@ const Attachment = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
openModal (event) {
|
openModal (event) {
|
||||||
const modalTypes = this.mergedConfig.playVideosInModal
|
if (this.useModal) {
|
||||||
? ['image', 'video']
|
|
||||||
: ['image']
|
|
||||||
if (fileTypeService.fileMatchesSomeType(modalTypes, this.attachment) ||
|
|
||||||
this.usePlaceHolder
|
|
||||||
) {
|
|
||||||
event.stopPropagation()
|
event.stopPropagation()
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
this.setMedia()
|
this.setMedia()
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
v-if="usePlaceHolder"
|
v-if="usePlaceholder"
|
||||||
|
:class="{ 'fullwidth': fullwidth }"
|
||||||
@click="openModal"
|
@click="openModal"
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
|
@ -8,8 +9,11 @@
|
||||||
class="placeholder"
|
class="placeholder"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
:href="attachment.url"
|
:href="attachment.url"
|
||||||
|
:alt="attachment.description"
|
||||||
|
:title="attachment.description"
|
||||||
>
|
>
|
||||||
[{{ nsfw ? "NSFW/" : "" }}{{ type.toUpperCase() }}]
|
<span :class="placeholderIconClass" />
|
||||||
|
<b>{{ nsfw ? "NSFW / " : "" }}</b>{{ placeholderName }}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
@ -22,6 +26,8 @@
|
||||||
v-if="hidden"
|
v-if="hidden"
|
||||||
class="image-attachment"
|
class="image-attachment"
|
||||||
:href="attachment.url"
|
:href="attachment.url"
|
||||||
|
:alt="attachment.description"
|
||||||
|
:title="attachment.description"
|
||||||
@click.prevent="toggleHidden"
|
@click.prevent="toggleHidden"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
|
@ -51,7 +57,6 @@
|
||||||
:class="{'hidden': hidden && preloadImage }"
|
:class="{'hidden': hidden && preloadImage }"
|
||||||
:href="attachment.url"
|
:href="attachment.url"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
:title="attachment.description"
|
|
||||||
@click="openModal"
|
@click="openModal"
|
||||||
>
|
>
|
||||||
<StillImage
|
<StillImage
|
||||||
|
@ -59,6 +64,7 @@
|
||||||
:mimetype="attachment.mimetype"
|
:mimetype="attachment.mimetype"
|
||||||
:src="attachment.large_thumb_url || attachment.url"
|
:src="attachment.large_thumb_url || attachment.url"
|
||||||
:image-load-handler="onImageLoad"
|
:image-load-handler="onImageLoad"
|
||||||
|
:alt="attachment.description"
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
@ -83,6 +89,8 @@
|
||||||
<audio
|
<audio
|
||||||
v-if="type === 'audio'"
|
v-if="type === 'audio'"
|
||||||
:src="attachment.url"
|
:src="attachment.url"
|
||||||
|
:alt="attachment.description"
|
||||||
|
:title="attachment.description"
|
||||||
controls
|
controls
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
@ -116,22 +124,19 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|
||||||
.attachment.media-upload-container {
|
.non-gallery {
|
||||||
flex: 0 0 auto;
|
|
||||||
max-height: 200px;
|
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
video {
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.placeholder {
|
.placeholder {
|
||||||
margin-right: 8px;
|
display: inline-block;
|
||||||
margin-bottom: 4px;
|
padding: 0.3em 1em 0.3em 0;
|
||||||
color: $fallback--link;
|
color: $fallback--link;
|
||||||
color: var(--postLink, $fallback--link);
|
color: var(--postLink, $fallback--link);
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nsfw-placeholder {
|
.nsfw-placeholder {
|
||||||
|
|
|
@ -50,9 +50,7 @@
|
||||||
align-content: stretch;
|
align-content: stretch;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: specificity problem with this and .attachments.attachment
|
.gallery-row-inner .attachment {
|
||||||
// we shouldn't have the need for .image here
|
|
||||||
.attachment.image {
|
|
||||||
margin: 0 0.5em 0 0;
|
margin: 0 0.5em 0 0;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
v-if="type === 'image'"
|
v-if="type === 'image'"
|
||||||
class="modal-image"
|
class="modal-image"
|
||||||
:src="currentMedia.url"
|
:src="currentMedia.url"
|
||||||
|
:alt="currentMedia.description"
|
||||||
|
:title="currentMedia.description"
|
||||||
@touchstart.stop="mediaTouchStart"
|
@touchstart.stop="mediaTouchStart"
|
||||||
@touchmove.stop="mediaTouchMove"
|
@touchmove.stop="mediaTouchMove"
|
||||||
@click="hide"
|
@click="hide"
|
||||||
|
@ -18,6 +20,14 @@
|
||||||
:attachment="currentMedia"
|
:attachment="currentMedia"
|
||||||
:controls="true"
|
:controls="true"
|
||||||
/>
|
/>
|
||||||
|
<audio
|
||||||
|
v-if="type === 'audio'"
|
||||||
|
class="modal-image"
|
||||||
|
:src="currentMedia.url"
|
||||||
|
:alt="currentMedia.description"
|
||||||
|
:title="currentMedia.description"
|
||||||
|
controls
|
||||||
|
/>
|
||||||
<button
|
<button
|
||||||
v-if="canNavigate"
|
v-if="canNavigate"
|
||||||
:title="$t('media_modal.previous')"
|
:title="$t('media_modal.previous')"
|
||||||
|
|
|
@ -118,6 +118,11 @@
|
||||||
flex: 1;
|
flex: 1;
|
||||||
padding-left: 0.8em;
|
padding-left: 0.8em;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
|
||||||
|
.timeago {
|
||||||
|
min-width: 3em;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.emoji-reaction-emoji {
|
.emoji-reaction-emoji {
|
||||||
|
|
|
@ -3,9 +3,11 @@ import MediaUpload from '../media_upload/media_upload.vue'
|
||||||
import ScopeSelector from '../scope_selector/scope_selector.vue'
|
import ScopeSelector from '../scope_selector/scope_selector.vue'
|
||||||
import EmojiInput from '../emoji_input/emoji_input.vue'
|
import EmojiInput from '../emoji_input/emoji_input.vue'
|
||||||
import PollForm from '../poll/poll_form.vue'
|
import PollForm from '../poll/poll_form.vue'
|
||||||
|
import Attachment from '../attachment/attachment.vue'
|
||||||
|
import StatusContent from '../status_content/status_content.vue'
|
||||||
import fileTypeService from '../../services/file_type/file_type.service.js'
|
import fileTypeService from '../../services/file_type/file_type.service.js'
|
||||||
import { findOffset } from '../../services/offset_finder/offset_finder.service.js'
|
import { findOffset } from '../../services/offset_finder/offset_finder.service.js'
|
||||||
import { reject, map, uniqBy } from 'lodash'
|
import { reject, map, uniqBy, debounce } from 'lodash'
|
||||||
import suggestor from '../emoji_input/suggestor.js'
|
import suggestor from '../emoji_input/suggestor.js'
|
||||||
import { mapGetters } from 'vuex'
|
import { mapGetters } from 'vuex'
|
||||||
import Checkbox from '../checkbox/checkbox.vue'
|
import Checkbox from '../checkbox/checkbox.vue'
|
||||||
|
@ -38,7 +40,9 @@ const PostStatusForm = {
|
||||||
EmojiInput,
|
EmojiInput,
|
||||||
PollForm,
|
PollForm,
|
||||||
ScopeSelector,
|
ScopeSelector,
|
||||||
Checkbox
|
Checkbox,
|
||||||
|
Attachment,
|
||||||
|
StatusContent
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
this.resize(this.$refs.textarea)
|
this.resize(this.$refs.textarea)
|
||||||
|
@ -78,13 +82,16 @@ const PostStatusForm = {
|
||||||
nsfw: false,
|
nsfw: false,
|
||||||
files: [],
|
files: [],
|
||||||
poll: {},
|
poll: {},
|
||||||
|
mediaDescriptions: {},
|
||||||
visibility: scope,
|
visibility: scope,
|
||||||
contentType
|
contentType
|
||||||
},
|
},
|
||||||
caret: 0,
|
caret: 0,
|
||||||
pollFormVisible: false,
|
pollFormVisible: false,
|
||||||
showDropIcon: 'hide',
|
showDropIcon: 'hide',
|
||||||
dropStopTimeout: null
|
dropStopTimeout: null,
|
||||||
|
preview: null,
|
||||||
|
previewLoading: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -163,19 +170,30 @@ const PostStatusForm = {
|
||||||
this.newStatus.poll &&
|
this.newStatus.poll &&
|
||||||
this.newStatus.poll.error
|
this.newStatus.poll.error
|
||||||
},
|
},
|
||||||
|
showPreview () {
|
||||||
|
return !!this.preview || this.previewLoading
|
||||||
|
},
|
||||||
|
emptyStatus () {
|
||||||
|
return this.newStatus.status.trim() === '' && this.newStatus.files.length === 0
|
||||||
|
},
|
||||||
...mapGetters(['mergedConfig'])
|
...mapGetters(['mergedConfig'])
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
'newStatus.contentType': function () {
|
||||||
|
this.autoPreview()
|
||||||
|
},
|
||||||
|
'newStatus.spoilerText': function () {
|
||||||
|
this.autoPreview()
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
postStatus (newStatus) {
|
async postStatus (newStatus) {
|
||||||
if (this.posting) { return }
|
if (this.posting) { return }
|
||||||
if (this.submitDisabled) { return }
|
if (this.submitDisabled) { return }
|
||||||
|
if (this.emptyStatus) {
|
||||||
if (this.newStatus.status === '') {
|
this.error = this.$t('post_status.empty_status_error')
|
||||||
if (this.newStatus.files.length === 0) {
|
|
||||||
this.error = 'Cannot post an empty status with no files'
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const poll = this.pollFormVisible ? this.newStatus.poll : {}
|
const poll = this.pollFormVisible ? this.newStatus.poll : {}
|
||||||
if (this.pollContentError) {
|
if (this.pollContentError) {
|
||||||
|
@ -184,7 +202,16 @@ const PostStatusForm = {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.posting = true
|
this.posting = true
|
||||||
statusPoster.postStatus({
|
|
||||||
|
try {
|
||||||
|
await this.setAllMediaDescriptions()
|
||||||
|
} catch (e) {
|
||||||
|
this.error = this.$t('post_status.media_description_error')
|
||||||
|
this.posting = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await statusPoster.postStatus({
|
||||||
status: newStatus.status,
|
status: newStatus.status,
|
||||||
spoilerText: newStatus.spoilerText || null,
|
spoilerText: newStatus.spoilerText || null,
|
||||||
visibility: newStatus.visibility,
|
visibility: newStatus.visibility,
|
||||||
|
@ -194,7 +221,8 @@ const PostStatusForm = {
|
||||||
inReplyToStatusId: this.replyTo,
|
inReplyToStatusId: this.replyTo,
|
||||||
contentType: newStatus.contentType,
|
contentType: newStatus.contentType,
|
||||||
poll
|
poll
|
||||||
}).then((data) => {
|
})
|
||||||
|
|
||||||
if (!data.error) {
|
if (!data.error) {
|
||||||
this.newStatus = {
|
this.newStatus = {
|
||||||
status: '',
|
status: '',
|
||||||
|
@ -202,7 +230,8 @@ const PostStatusForm = {
|
||||||
files: [],
|
files: [],
|
||||||
visibility: newStatus.visibility,
|
visibility: newStatus.visibility,
|
||||||
contentType: newStatus.contentType,
|
contentType: newStatus.contentType,
|
||||||
poll: {}
|
poll: {},
|
||||||
|
mediaDescriptions: {}
|
||||||
}
|
}
|
||||||
this.pollFormVisible = false
|
this.pollFormVisible = false
|
||||||
this.$refs.mediaUpload.clearFile()
|
this.$refs.mediaUpload.clearFile()
|
||||||
|
@ -212,12 +241,64 @@ const PostStatusForm = {
|
||||||
el.style.height = 'auto'
|
el.style.height = 'auto'
|
||||||
el.style.height = undefined
|
el.style.height = undefined
|
||||||
this.error = null
|
this.error = null
|
||||||
|
if (this.preview) this.previewStatus()
|
||||||
} else {
|
} else {
|
||||||
this.error = data.error
|
this.error = data.error
|
||||||
}
|
}
|
||||||
|
|
||||||
this.posting = false
|
this.posting = false
|
||||||
|
},
|
||||||
|
previewStatus () {
|
||||||
|
if (this.emptyStatus && this.newStatus.spoilerText.trim() === '') {
|
||||||
|
this.preview = { error: this.$t('post_status.preview_empty') }
|
||||||
|
this.previewLoading = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const newStatus = this.newStatus
|
||||||
|
this.previewLoading = true
|
||||||
|
statusPoster.postStatus({
|
||||||
|
status: newStatus.status,
|
||||||
|
spoilerText: newStatus.spoilerText || null,
|
||||||
|
visibility: newStatus.visibility,
|
||||||
|
sensitive: newStatus.nsfw,
|
||||||
|
media: [],
|
||||||
|
store: this.$store,
|
||||||
|
inReplyToStatusId: this.replyTo,
|
||||||
|
contentType: newStatus.contentType,
|
||||||
|
poll: {},
|
||||||
|
preview: true
|
||||||
|
}).then((data) => {
|
||||||
|
// Don't apply preview if not loading, because it means
|
||||||
|
// user has closed the preview manually.
|
||||||
|
if (!this.previewLoading) return
|
||||||
|
if (!data.error) {
|
||||||
|
this.preview = data
|
||||||
|
} else {
|
||||||
|
this.preview = { error: data.error }
|
||||||
|
}
|
||||||
|
}).catch((error) => {
|
||||||
|
this.preview = { error }
|
||||||
|
}).finally(() => {
|
||||||
|
this.previewLoading = false
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
debouncePreviewStatus: debounce(function () { this.previewStatus() }, 500),
|
||||||
|
autoPreview () {
|
||||||
|
if (!this.preview) return
|
||||||
|
this.previewLoading = true
|
||||||
|
this.debouncePreviewStatus()
|
||||||
|
},
|
||||||
|
closePreview () {
|
||||||
|
this.preview = null
|
||||||
|
this.previewLoading = false
|
||||||
|
},
|
||||||
|
togglePreview () {
|
||||||
|
if (this.showPreview) {
|
||||||
|
this.closePreview()
|
||||||
|
} else {
|
||||||
|
this.previewStatus()
|
||||||
|
}
|
||||||
|
},
|
||||||
addMediaFile (fileInfo) {
|
addMediaFile (fileInfo) {
|
||||||
this.newStatus.files.push(fileInfo)
|
this.newStatus.files.push(fileInfo)
|
||||||
},
|
},
|
||||||
|
@ -239,6 +320,7 @@ const PostStatusForm = {
|
||||||
return fileTypeService.fileType(fileInfo.mimetype)
|
return fileTypeService.fileType(fileInfo.mimetype)
|
||||||
},
|
},
|
||||||
paste (e) {
|
paste (e) {
|
||||||
|
this.autoPreview()
|
||||||
this.resize(e)
|
this.resize(e)
|
||||||
if (e.clipboardData.files.length > 0) {
|
if (e.clipboardData.files.length > 0) {
|
||||||
// prevent pasting of file as text
|
// prevent pasting of file as text
|
||||||
|
@ -273,6 +355,7 @@ const PostStatusForm = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onEmojiInputInput (e) {
|
onEmojiInputInput (e) {
|
||||||
|
this.autoPreview()
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.resize(this.$refs['textarea'])
|
this.resize(this.$refs['textarea'])
|
||||||
})
|
})
|
||||||
|
@ -388,6 +471,15 @@ const PostStatusForm = {
|
||||||
},
|
},
|
||||||
dismissScopeNotice () {
|
dismissScopeNotice () {
|
||||||
this.$store.dispatch('setOption', { name: 'hideScopeNotice', value: true })
|
this.$store.dispatch('setOption', { name: 'hideScopeNotice', value: true })
|
||||||
|
},
|
||||||
|
setMediaDescription (id) {
|
||||||
|
const description = this.newStatus.mediaDescriptions[id]
|
||||||
|
if (!description || description.trim() === '') return
|
||||||
|
return statusPoster.setMediaDescription({ store: this.$store, id, description })
|
||||||
|
},
|
||||||
|
setAllMediaDescriptions () {
|
||||||
|
const ids = this.newStatus.files.map(file => file.id)
|
||||||
|
return Promise.all(ids.map(id => this.setMediaDescription(id)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,6 +69,44 @@
|
||||||
<span v-if="safeDMEnabled">{{ $t('post_status.direct_warning_to_first_only') }}</span>
|
<span v-if="safeDMEnabled">{{ $t('post_status.direct_warning_to_first_only') }}</span>
|
||||||
<span v-else>{{ $t('post_status.direct_warning_to_all') }}</span>
|
<span v-else>{{ $t('post_status.direct_warning_to_all') }}</span>
|
||||||
</p>
|
</p>
|
||||||
|
<div class="preview-heading faint">
|
||||||
|
<a
|
||||||
|
class="preview-toggle faint"
|
||||||
|
@click.stop.prevent="togglePreview"
|
||||||
|
>
|
||||||
|
{{ $t('post_status.preview') }}
|
||||||
|
<i
|
||||||
|
class="icon-down-open"
|
||||||
|
:style="{ transform: showPreview ? 'rotate(0deg)' : 'rotate(-90deg)' }"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
<i
|
||||||
|
v-show="previewLoading"
|
||||||
|
class="icon-spin3 animate-spin"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="showPreview"
|
||||||
|
class="preview-container"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-if="!preview"
|
||||||
|
class="preview-status"
|
||||||
|
>
|
||||||
|
{{ $t('general.loading') }}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-else-if="preview.error"
|
||||||
|
class="preview-status preview-error"
|
||||||
|
>
|
||||||
|
{{ preview.error }}
|
||||||
|
</div>
|
||||||
|
<StatusContent
|
||||||
|
v-else
|
||||||
|
:status="preview"
|
||||||
|
class="preview-status"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<EmojiInput
|
<EmojiInput
|
||||||
v-if="newStatus.spoilerText || alwaysShowSubject"
|
v-if="newStatus.spoilerText || alwaysShowSubject"
|
||||||
v-model="newStatus.spoilerText"
|
v-model="newStatus.spoilerText"
|
||||||
|
@ -77,7 +115,6 @@
|
||||||
class="form-control"
|
class="form-control"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
|
|
||||||
v-model="newStatus.spoilerText"
|
v-model="newStatus.spoilerText"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('post_status.content_warning')"
|
:placeholder="$t('post_status.content_warning')"
|
||||||
|
@ -245,27 +282,18 @@
|
||||||
class="fa button-icon icon-cancel"
|
class="fa button-icon icon-cancel"
|
||||||
@click="removeMediaFile(file)"
|
@click="removeMediaFile(file)"
|
||||||
/>
|
/>
|
||||||
<div class="media-upload-container attachment">
|
<attachment
|
||||||
<img
|
:attachment="file"
|
||||||
v-if="type(file) === 'image'"
|
:set-media="() => $store.dispatch('setMedia', newStatus.files)"
|
||||||
class="thumbnail media-upload"
|
size="small"
|
||||||
:src="file.url"
|
allow-play="false"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
v-model="newStatus.mediaDescriptions[file.id]"
|
||||||
|
type="text"
|
||||||
|
:placeholder="$t('post_status.media_description')"
|
||||||
|
@keydown.enter.prevent=""
|
||||||
>
|
>
|
||||||
<video
|
|
||||||
v-if="type(file) === 'video'"
|
|
||||||
:src="file.url"
|
|
||||||
controls
|
|
||||||
/>
|
|
||||||
<audio
|
|
||||||
v-if="type(file) === 'audio'"
|
|
||||||
:src="file.url"
|
|
||||||
controls
|
|
||||||
/>
|
|
||||||
<a
|
|
||||||
v-if="type(file) === 'unknown'"
|
|
||||||
:href="file.url"
|
|
||||||
>{{ file.url }}</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
@ -302,14 +330,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.post-status-form {
|
|
||||||
.visibility-tray {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
padding-top: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.post-status-form {
|
.post-status-form {
|
||||||
.form-bottom {
|
.form-bottom {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -336,6 +356,48 @@
|
||||||
max-width: 10em;
|
max-width: 10em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.preview-heading {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.icon-spin3 {
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-toggle {
|
||||||
|
display: flex;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-down-open {
|
||||||
|
transition: transform 0.1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-container {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-error {
|
||||||
|
font-style: italic;
|
||||||
|
color: $fallback--faint;
|
||||||
|
color: var(--faint, $fallback--faint);
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-status {
|
||||||
|
border: 1px solid $fallback--border;
|
||||||
|
border: 1px solid var(--border, $fallback--border);
|
||||||
|
border-radius: $fallback--tooltipRadius;
|
||||||
|
border-radius: var(--tooltipRadius, $fallback--tooltipRadius);
|
||||||
|
padding: 0.5em;
|
||||||
|
margin: 0;
|
||||||
|
line-height: 1.4em;
|
||||||
|
}
|
||||||
|
|
||||||
.text-format {
|
.text-format {
|
||||||
.only-format {
|
.only-format {
|
||||||
color: $fallback--faint;
|
color: $fallback--faint;
|
||||||
|
@ -343,6 +405,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.visibility-tray {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
.media-upload-icon, .poll-icon, .emoji-icon {
|
.media-upload-icon, .poll-icon, .emoji-icon {
|
||||||
font-size: 26px;
|
font-size: 26px;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
@ -395,11 +463,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.media-upload-wrapper {
|
.media-upload-wrapper {
|
||||||
flex: 0 0 auto;
|
|
||||||
max-width: 100%;
|
|
||||||
min-width: 50px;
|
|
||||||
margin-right: .2em;
|
margin-right: .2em;
|
||||||
margin-bottom: .5em;
|
margin-bottom: .5em;
|
||||||
|
width: 18em;
|
||||||
|
|
||||||
.icon-cancel {
|
.icon-cancel {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
@ -413,6 +479,20 @@
|
||||||
border-bottom-left-radius: 0;
|
border-bottom-left-radius: 0;
|
||||||
border-bottom-right-radius: 0;
|
border-bottom-right-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
img, video {
|
||||||
|
object-fit: contain;
|
||||||
|
max-height: 10em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video {
|
||||||
|
max-height: 10em;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
flex: 1;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-input-wrapper {
|
.status-input-wrapper {
|
||||||
|
@ -422,28 +502,13 @@
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.attachments {
|
.media-upload-wrapper .attachments {
|
||||||
padding: 0 0.5em;
|
padding: 0 0.5em;
|
||||||
|
|
||||||
.attachment {
|
.attachment {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
flex: 0 0 auto;
|
|
||||||
border: 1px solid $fallback--border;
|
|
||||||
border: 1px solid var(--border, $fallback--border);
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
audio {
|
|
||||||
min-width: 300px;
|
|
||||||
flex: 1 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
display: block;
|
|
||||||
text-align: left;
|
|
||||||
line-height: 1.2;
|
|
||||||
padding: .5em;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
i {
|
i {
|
||||||
|
|
|
@ -77,6 +77,33 @@ const ProfileTab = {
|
||||||
},
|
},
|
||||||
maxFields () {
|
maxFields () {
|
||||||
return this.fieldsLimits ? this.fieldsLimits.maxFields : 0
|
return this.fieldsLimits ? this.fieldsLimits.maxFields : 0
|
||||||
|
},
|
||||||
|
defaultAvatar () {
|
||||||
|
return this.$store.state.instance.server + this.$store.state.instance.defaultAvatar
|
||||||
|
},
|
||||||
|
defaultBanner () {
|
||||||
|
return this.$store.state.instance.server + this.$store.state.instance.defaultBanner
|
||||||
|
},
|
||||||
|
isDefaultAvatar () {
|
||||||
|
const baseAvatar = this.$store.state.instance.defaultAvatar
|
||||||
|
return !(this.$store.state.users.currentUser.profile_image_url) ||
|
||||||
|
this.$store.state.users.currentUser.profile_image_url.includes(baseAvatar)
|
||||||
|
},
|
||||||
|
isDefaultBanner () {
|
||||||
|
const baseBanner = this.$store.state.instance.defaultBanner
|
||||||
|
return !(this.$store.state.users.currentUser.cover_photo) ||
|
||||||
|
this.$store.state.users.currentUser.cover_photo.includes(baseBanner)
|
||||||
|
},
|
||||||
|
isDefaultBackground () {
|
||||||
|
return !(this.$store.state.users.currentUser.background_image)
|
||||||
|
},
|
||||||
|
avatarImgSrc () {
|
||||||
|
const src = this.$store.state.users.currentUser.profile_image_url_original
|
||||||
|
return (!src) ? this.defaultAvatar : src
|
||||||
|
},
|
||||||
|
bannerImgSrc () {
|
||||||
|
const src = this.$store.state.users.currentUser.cover_photo
|
||||||
|
return (!src) ? this.defaultBanner : src
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -150,11 +177,29 @@ const ProfileTab = {
|
||||||
}
|
}
|
||||||
reader.readAsDataURL(file)
|
reader.readAsDataURL(file)
|
||||||
},
|
},
|
||||||
|
resetAvatar () {
|
||||||
|
const confirmed = window.confirm(this.$t('settings.reset_avatar_confirm'))
|
||||||
|
if (confirmed) {
|
||||||
|
this.submitAvatar(undefined, '')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
resetBanner () {
|
||||||
|
const confirmed = window.confirm(this.$t('settings.reset_banner_confirm'))
|
||||||
|
if (confirmed) {
|
||||||
|
this.submitBanner('')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
resetBackground () {
|
||||||
|
const confirmed = window.confirm(this.$t('settings.reset_background_confirm'))
|
||||||
|
if (confirmed) {
|
||||||
|
this.submitBackground('')
|
||||||
|
}
|
||||||
|
},
|
||||||
submitAvatar (cropper, file) {
|
submitAvatar (cropper, file) {
|
||||||
const that = this
|
const that = this
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
function updateAvatar (avatar) {
|
function updateAvatar (avatar) {
|
||||||
that.$store.state.api.backendInteractor.updateAvatar({ avatar })
|
that.$store.state.api.backendInteractor.updateProfileImages({ avatar })
|
||||||
.then((user) => {
|
.then((user) => {
|
||||||
that.$store.commit('addNewUsers', [user])
|
that.$store.commit('addNewUsers', [user])
|
||||||
that.$store.commit('setCurrentUser', user)
|
that.$store.commit('setCurrentUser', user)
|
||||||
|
@ -172,11 +217,11 @@ const ProfileTab = {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
submitBanner () {
|
submitBanner (banner) {
|
||||||
if (!this.bannerPreview) { return }
|
if (!this.bannerPreview && banner !== '') { return }
|
||||||
|
|
||||||
this.bannerUploading = true
|
this.bannerUploading = true
|
||||||
this.$store.state.api.backendInteractor.updateBanner({ banner: this.banner })
|
this.$store.state.api.backendInteractor.updateProfileImages({ banner })
|
||||||
.then((user) => {
|
.then((user) => {
|
||||||
this.$store.commit('addNewUsers', [user])
|
this.$store.commit('addNewUsers', [user])
|
||||||
this.$store.commit('setCurrentUser', user)
|
this.$store.commit('setCurrentUser', user)
|
||||||
|
@ -187,11 +232,11 @@ const ProfileTab = {
|
||||||
})
|
})
|
||||||
.then(() => { this.bannerUploading = false })
|
.then(() => { this.bannerUploading = false })
|
||||||
},
|
},
|
||||||
submitBg () {
|
submitBackground (background) {
|
||||||
if (!this.backgroundPreview) { return }
|
if (!this.backgroundPreview && background !== '') { return }
|
||||||
let background = this.background
|
|
||||||
this.backgroundUploading = true
|
this.backgroundUploading = true
|
||||||
this.$store.state.api.backendInteractor.updateBg({ background }).then((data) => {
|
this.$store.state.api.backendInteractor.updateProfileImages({ background }).then((data) => {
|
||||||
if (!data.error) {
|
if (!data.error) {
|
||||||
this.$store.commit('addNewUsers', [data])
|
this.$store.commit('addNewUsers', [data])
|
||||||
this.$store.commit('setCurrentUser', data)
|
this.$store.commit('setCurrentUser', data)
|
||||||
|
|
|
@ -13,8 +13,14 @@
|
||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.banner {
|
.banner-background-preview {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
width: 300px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.uploading {
|
.uploading {
|
||||||
|
@ -26,18 +32,40 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bg {
|
.current-avatar-container {
|
||||||
max-width: 100%;
|
position: relative;
|
||||||
|
width: 150px;
|
||||||
|
height: 150px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.current-avatar {
|
.current-avatar {
|
||||||
display: block;
|
display: block;
|
||||||
width: 150px;
|
width: 100%;
|
||||||
height: 150px;
|
height: 100%;
|
||||||
border-radius: $fallback--avatarRadius;
|
border-radius: $fallback--avatarRadius;
|
||||||
border-radius: var(--avatarRadius, $fallback--avatarRadius);
|
border-radius: var(--avatarRadius, $fallback--avatarRadius);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.reset-button {
|
||||||
|
position: absolute;
|
||||||
|
top: 0.2em;
|
||||||
|
right: 0.2em;
|
||||||
|
border-radius: $fallback--tooltipRadius;
|
||||||
|
border-radius: var(--tooltipRadius, $fallback--tooltipRadius);
|
||||||
|
background-color: rgba(0, 0, 0, 0.6);
|
||||||
|
opacity: 0.7;
|
||||||
|
color: white;
|
||||||
|
width: 1.5em;
|
||||||
|
height: 1.5em;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 1.5em;
|
||||||
|
font-size: 1.5em;
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.oauth-tokens {
|
.oauth-tokens {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
|
@ -86,6 +114,7 @@
|
||||||
&>.emoji-input {
|
&>.emoji-input {
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
margin: 0 .2em .5em;
|
margin: 0 .2em .5em;
|
||||||
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&>.icon-container {
|
&>.icon-container {
|
||||||
|
|
|
@ -161,11 +161,19 @@
|
||||||
<p class="visibility-notice">
|
<p class="visibility-notice">
|
||||||
{{ $t('settings.avatar_size_instruction') }}
|
{{ $t('settings.avatar_size_instruction') }}
|
||||||
</p>
|
</p>
|
||||||
<p>{{ $t('settings.current_avatar') }}</p>
|
<div class="current-avatar-container">
|
||||||
<img
|
<img
|
||||||
:src="user.profile_image_url_original"
|
:src="user.profile_image_url_original"
|
||||||
class="current-avatar"
|
class="current-avatar"
|
||||||
>
|
>
|
||||||
|
<i
|
||||||
|
v-if="!isDefaultAvatar && pickAvatarBtnVisible"
|
||||||
|
:title="$t('settings.reset_avatar')"
|
||||||
|
class="reset-button icon-cancel"
|
||||||
|
type="button"
|
||||||
|
@click="resetAvatar"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<p>{{ $t('settings.set_new_avatar') }}</p>
|
<p>{{ $t('settings.set_new_avatar') }}</p>
|
||||||
<button
|
<button
|
||||||
v-show="pickAvatarBtnVisible"
|
v-show="pickAvatarBtnVisible"
|
||||||
|
@ -184,15 +192,20 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-item">
|
<div class="setting-item">
|
||||||
<h2>{{ $t('settings.profile_banner') }}</h2>
|
<h2>{{ $t('settings.profile_banner') }}</h2>
|
||||||
<p>{{ $t('settings.current_profile_banner') }}</p>
|
<div class="banner-background-preview">
|
||||||
<img
|
<img :src="user.cover_photo">
|
||||||
:src="user.cover_photo"
|
<i
|
||||||
class="banner"
|
v-if="!isDefaultBanner"
|
||||||
>
|
:title="$t('settings.reset_profile_banner')"
|
||||||
|
class="reset-button icon-cancel"
|
||||||
|
type="button"
|
||||||
|
@click="resetBanner"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<p>{{ $t('settings.set_new_profile_banner') }}</p>
|
<p>{{ $t('settings.set_new_profile_banner') }}</p>
|
||||||
<img
|
<img
|
||||||
v-if="bannerPreview"
|
v-if="bannerPreview"
|
||||||
class="banner"
|
class="banner-background-preview"
|
||||||
:src="bannerPreview"
|
:src="bannerPreview"
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
|
@ -208,7 +221,7 @@
|
||||||
<button
|
<button
|
||||||
v-else-if="bannerPreview"
|
v-else-if="bannerPreview"
|
||||||
class="btn btn-default"
|
class="btn btn-default"
|
||||||
@click="submitBanner"
|
@click="submitBanner(banner)"
|
||||||
>
|
>
|
||||||
{{ $t('general.submit') }}
|
{{ $t('general.submit') }}
|
||||||
</button>
|
</button>
|
||||||
|
@ -225,10 +238,20 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-item">
|
<div class="setting-item">
|
||||||
<h2>{{ $t('settings.profile_background') }}</h2>
|
<h2>{{ $t('settings.profile_background') }}</h2>
|
||||||
|
<div class="banner-background-preview">
|
||||||
|
<img :src="user.background_image">
|
||||||
|
<i
|
||||||
|
v-if="!isDefaultBackground"
|
||||||
|
:title="$t('settings.reset_profile_background')"
|
||||||
|
class="reset-button icon-cancel"
|
||||||
|
type="button"
|
||||||
|
@click="resetBackground"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<p>{{ $t('settings.set_new_profile_background') }}</p>
|
<p>{{ $t('settings.set_new_profile_background') }}</p>
|
||||||
<img
|
<img
|
||||||
v-if="backgroundPreview"
|
v-if="backgroundPreview"
|
||||||
class="bg"
|
class="banner-background-preview"
|
||||||
:src="backgroundPreview"
|
:src="backgroundPreview"
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
|
@ -244,7 +267,7 @@
|
||||||
<button
|
<button
|
||||||
v-else-if="backgroundPreview"
|
v-else-if="backgroundPreview"
|
||||||
class="btn btn-default"
|
class="btn btn-default"
|
||||||
@click="submitBg"
|
@click="submitBackground(background)"
|
||||||
>
|
>
|
||||||
{{ $t('general.submit') }}
|
{{ $t('general.submit') }}
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -2,6 +2,10 @@ import map from 'lodash/map'
|
||||||
import BasicUserCard from '../basic_user_card/basic_user_card.vue'
|
import BasicUserCard from '../basic_user_card/basic_user_card.vue'
|
||||||
|
|
||||||
const StaffPanel = {
|
const StaffPanel = {
|
||||||
|
created () {
|
||||||
|
const nicknames = this.$store.state.instance.staffAccounts
|
||||||
|
nicknames.forEach(nickname => this.$store.dispatch('fetchUserIfMissing', nickname))
|
||||||
|
},
|
||||||
components: {
|
components: {
|
||||||
BasicUserCard
|
BasicUserCard
|
||||||
},
|
},
|
||||||
|
|
|
@ -377,9 +377,6 @@ $status-margin: 0.75em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-el {
|
.status-el {
|
||||||
overflow-wrap: break-word;
|
|
||||||
word-wrap: break-word;
|
|
||||||
word-break: break-word;
|
|
||||||
border-left-width: 0px;
|
border-left-width: 0px;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
border-color: $fallback--border;
|
border-color: $fallback--border;
|
||||||
|
|
|
@ -99,15 +99,8 @@ const StatusContent = {
|
||||||
file => !fileType.fileMatchesSomeType(this.galleryTypes, file)
|
file => !fileType.fileMatchesSomeType(this.galleryTypes, file)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
hasImageAttachments () {
|
attachmentTypes () {
|
||||||
return this.status.attachments.some(
|
return this.status.attachments.map(file => fileType.fileType(file.mimetype))
|
||||||
file => fileType.fileType(file.mimetype) === 'image'
|
|
||||||
)
|
|
||||||
},
|
|
||||||
hasVideoAttachments () {
|
|
||||||
return this.status.attachments.some(
|
|
||||||
file => fileType.fileType(file.mimetype) === 'video'
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
maxThumbnails () {
|
maxThumbnails () {
|
||||||
return this.mergedConfig.maxThumbnails
|
return this.mergedConfig.maxThumbnails
|
||||||
|
|
|
@ -55,13 +55,21 @@
|
||||||
>
|
>
|
||||||
{{ $t("status.show_content") }}
|
{{ $t("status.show_content") }}
|
||||||
<span
|
<span
|
||||||
v-if="hasImageAttachments"
|
v-if="attachmentTypes.includes('image')"
|
||||||
class="icon-picture"
|
class="icon-picture"
|
||||||
/>
|
/>
|
||||||
<span
|
<span
|
||||||
v-if="hasVideoAttachments"
|
v-if="attachmentTypes.includes('video')"
|
||||||
class="icon-video"
|
class="icon-video"
|
||||||
/>
|
/>
|
||||||
|
<span
|
||||||
|
v-if="attachmentTypes.includes('audio')"
|
||||||
|
class="icon-music"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
v-if="attachmentTypes.includes('unknown')"
|
||||||
|
class="icon-doc"
|
||||||
|
/>
|
||||||
<span
|
<span
|
||||||
v-if="status.card"
|
v-if="status.card"
|
||||||
class="icon-link"
|
class="icon-link"
|
||||||
|
@ -217,6 +225,9 @@ $status-margin: 0.75em;
|
||||||
font-family: var(--postFont, sans-serif);
|
font-family: var(--postFont, sans-serif);
|
||||||
line-height: 1.4em;
|
line-height: 1.4em;
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
word-wrap: break-word;
|
||||||
|
word-break: break-word;
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
margin: 0.2em 0 0.2em 2em;
|
margin: 0.2em 0 0.2em 2em;
|
||||||
|
|
|
@ -4,7 +4,8 @@ const StillImage = {
|
||||||
'referrerpolicy',
|
'referrerpolicy',
|
||||||
'mimetype',
|
'mimetype',
|
||||||
'imageLoadError',
|
'imageLoadError',
|
||||||
'imageLoadHandler'
|
'imageLoadHandler',
|
||||||
|
'alt'
|
||||||
],
|
],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
<img
|
<img
|
||||||
ref="src"
|
ref="src"
|
||||||
:key="src"
|
:key="src"
|
||||||
|
:alt="alt"
|
||||||
|
:title="alt"
|
||||||
:src="src"
|
:src="src"
|
||||||
:referrerpolicy="referrerpolicy"
|
:referrerpolicy="referrerpolicy"
|
||||||
@load="onLoad"
|
@load="onLoad"
|
||||||
|
|
|
@ -8,26 +8,20 @@ const UserAvatar = {
|
||||||
],
|
],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
showPlaceholder: false
|
showPlaceholder: false,
|
||||||
|
defaultAvatar: `${this.$store.state.instance.server + this.$store.state.instance.defaultAvatar}`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
StillImage
|
StillImage
|
||||||
},
|
},
|
||||||
computed: {
|
|
||||||
imgSrc () {
|
|
||||||
return this.showPlaceholder ? '/images/avi.png' : this.user.profile_image_url_original
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
|
imgSrc (src) {
|
||||||
|
return (!src || this.showPlaceholder) ? this.defaultAvatar : src
|
||||||
|
},
|
||||||
imageLoadError () {
|
imageLoadError () {
|
||||||
this.showPlaceholder = true
|
this.showPlaceholder = true
|
||||||
}
|
}
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
src () {
|
|
||||||
this.showPlaceholder = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
class="avatar"
|
class="avatar"
|
||||||
:alt="user.screen_name"
|
:alt="user.screen_name"
|
||||||
:title="user.screen_name"
|
:title="user.screen_name"
|
||||||
:src="imgSrc"
|
:src="imgSrc(user.profile_image_url_original)"
|
||||||
:class="{ 'avatar-compact': compact, 'better-shadow': betterShadow }"
|
:class="{ 'avatar-compact': compact, 'better-shadow': betterShadow }"
|
||||||
:image-load-error="imageLoadError"
|
:image-load-error="imageLoadError"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -10,10 +10,8 @@
|
||||||
:hide-bio="true"
|
:hide-bio="true"
|
||||||
rounded="top"
|
rounded="top"
|
||||||
/>
|
/>
|
||||||
<div class="panel-footer">
|
|
||||||
<PostStatusForm />
|
<PostStatusForm />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<auth-form
|
<auth-form
|
||||||
v-else
|
v-else
|
||||||
key="user-panel"
|
key="user-panel"
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
:src="attachment.url"
|
:src="attachment.url"
|
||||||
:loop="loopVideo"
|
:loop="loopVideo"
|
||||||
:controls="controls"
|
:controls="controls"
|
||||||
|
:alt="attachment.description"
|
||||||
|
:title="attachment.description"
|
||||||
playsinline
|
playsinline
|
||||||
@loadeddata="onVideoDataLoad"
|
@loadeddata="onVideoDataLoad"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -7,7 +7,7 @@ function showWhoToFollow (panel, reply) {
|
||||||
|
|
||||||
panel.usersToFollow.forEach((toFollow, index) => {
|
panel.usersToFollow.forEach((toFollow, index) => {
|
||||||
let user = shuffled[index]
|
let user = shuffled[index]
|
||||||
let img = user.avatar || '/images/avi.png'
|
let img = user.avatar || this.$store.state.instance.defaultAvatar
|
||||||
let name = user.acct
|
let name = user.acct
|
||||||
|
|
||||||
toFollow.img = img
|
toFollow.img = img
|
||||||
|
@ -38,13 +38,7 @@ function getWhoToFollow (panel) {
|
||||||
|
|
||||||
const WhoToFollowPanel = {
|
const WhoToFollowPanel = {
|
||||||
data: () => ({
|
data: () => ({
|
||||||
usersToFollow: new Array(3).fill().map(x => (
|
usersToFollow: []
|
||||||
{
|
|
||||||
img: '/images/avi.png',
|
|
||||||
name: '',
|
|
||||||
id: 0
|
|
||||||
}
|
|
||||||
))
|
|
||||||
}),
|
}),
|
||||||
computed: {
|
computed: {
|
||||||
user: function () {
|
user: function () {
|
||||||
|
@ -68,6 +62,13 @@ const WhoToFollowPanel = {
|
||||||
},
|
},
|
||||||
mounted:
|
mounted:
|
||||||
function () {
|
function () {
|
||||||
|
this.usersToFollow = new Array(3).fill().map(x => (
|
||||||
|
{
|
||||||
|
img: this.$store.state.instance.defaultAvatar,
|
||||||
|
name: '',
|
||||||
|
id: 0
|
||||||
|
}
|
||||||
|
))
|
||||||
if (this.suggestionsEnabled) {
|
if (this.suggestionsEnabled) {
|
||||||
getWhoToFollow(this)
|
getWhoToFollow(this)
|
||||||
}
|
}
|
||||||
|
|
|
@ -178,6 +178,7 @@
|
||||||
"account_not_locked_warning": "Your account is not {0}. Anyone can follow you to view your follower-only posts.",
|
"account_not_locked_warning": "Your account is not {0}. Anyone can follow you to view your follower-only posts.",
|
||||||
"account_not_locked_warning_link": "locked",
|
"account_not_locked_warning_link": "locked",
|
||||||
"attachments_sensitive": "Mark attachments as sensitive",
|
"attachments_sensitive": "Mark attachments as sensitive",
|
||||||
|
"media_description": "Media description",
|
||||||
"content_type": {
|
"content_type": {
|
||||||
"text/plain": "Plain text",
|
"text/plain": "Plain text",
|
||||||
"text/html": "HTML",
|
"text/html": "HTML",
|
||||||
|
@ -189,6 +190,10 @@
|
||||||
"direct_warning_to_all": "This post will be visible to all the mentioned users.",
|
"direct_warning_to_all": "This post will be visible to all the mentioned users.",
|
||||||
"direct_warning_to_first_only": "This post will only be visible to the mentioned users at the beginning of the message.",
|
"direct_warning_to_first_only": "This post will only be visible to the mentioned users at the beginning of the message.",
|
||||||
"posting": "Posting",
|
"posting": "Posting",
|
||||||
|
"preview": "Preview",
|
||||||
|
"preview_empty": "Empty",
|
||||||
|
"empty_status_error": "Can't post an empty status with no files",
|
||||||
|
"media_description_error": "Failed to update media, try again",
|
||||||
"scope_notice": {
|
"scope_notice": {
|
||||||
"public": "This post will be visible to everyone",
|
"public": "This post will be visible to everyone",
|
||||||
"private": "This post will be visible to your followers only",
|
"private": "This post will be visible to your followers only",
|
||||||
|
@ -285,9 +290,7 @@
|
||||||
"collapse_subject": "Collapse posts with subjects",
|
"collapse_subject": "Collapse posts with subjects",
|
||||||
"composing": "Composing",
|
"composing": "Composing",
|
||||||
"confirm_new_password": "Confirm new password",
|
"confirm_new_password": "Confirm new password",
|
||||||
"current_avatar": "Your current avatar",
|
|
||||||
"current_password": "Current password",
|
"current_password": "Current password",
|
||||||
"current_profile_banner": "Your current profile banner",
|
|
||||||
"mutes_and_blocks": "Mutes and Blocks",
|
"mutes_and_blocks": "Mutes and Blocks",
|
||||||
"data_import_export_tab": "Data Import / Export",
|
"data_import_export_tab": "Data Import / Export",
|
||||||
"default_vis": "Default visibility scope",
|
"default_vis": "Default visibility scope",
|
||||||
|
@ -394,6 +397,12 @@
|
||||||
"set_new_avatar": "Set new avatar",
|
"set_new_avatar": "Set new avatar",
|
||||||
"set_new_profile_background": "Set new profile background",
|
"set_new_profile_background": "Set new profile background",
|
||||||
"set_new_profile_banner": "Set new profile banner",
|
"set_new_profile_banner": "Set new profile banner",
|
||||||
|
"reset_avatar": "Reset avatar",
|
||||||
|
"reset_profile_background": "Reset profile background",
|
||||||
|
"reset_profile_banner": "Reset profile banner",
|
||||||
|
"reset_avatar_confirm": "Do you really want to reset the avatar?",
|
||||||
|
"reset_banner_confirm": "Do you really want to reset the banner?",
|
||||||
|
"reset_background_confirm": "Do you really want to reset the background?",
|
||||||
"settings": "Settings",
|
"settings": "Settings",
|
||||||
"subject_input_always_show": "Always show subject field",
|
"subject_input_always_show": "Always show subject field",
|
||||||
"subject_line_behavior": "Copy subject when replying",
|
"subject_line_behavior": "Copy subject when replying",
|
||||||
|
|
|
@ -66,7 +66,7 @@
|
||||||
"search": "Haku"
|
"search": "Haku"
|
||||||
},
|
},
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"broken_favorite": "Viestiä ei löydetty...",
|
"broken_favorite": "Viestiä ei löydetty…",
|
||||||
"favorited_you": "tykkäsi viestistäsi",
|
"favorited_you": "tykkäsi viestistäsi",
|
||||||
"followed_you": "seuraa sinua",
|
"followed_you": "seuraa sinua",
|
||||||
"load_older": "Lataa vanhempia ilmoituksia",
|
"load_older": "Lataa vanhempia ilmoituksia",
|
||||||
|
@ -101,7 +101,7 @@
|
||||||
},
|
},
|
||||||
"post_status": {
|
"post_status": {
|
||||||
"new_status": "Uusi viesti",
|
"new_status": "Uusi viesti",
|
||||||
"account_not_locked_warning": "Tilisi ei ole {0}. Kuka vain voi seurata sinua nähdäksesi 'vain-seuraajille' -viestisi",
|
"account_not_locked_warning": "Tilisi ei ole {0}. Kuka vain voi seurata sinua nähdäksesi 'vain-seuraajille' -viestisi.",
|
||||||
"account_not_locked_warning_link": "lukittu",
|
"account_not_locked_warning_link": "lukittu",
|
||||||
"attachments_sensitive": "Merkkaa liitteet arkaluonteisiksi",
|
"attachments_sensitive": "Merkkaa liitteet arkaluonteisiksi",
|
||||||
"content_type": {
|
"content_type": {
|
||||||
|
@ -288,7 +288,7 @@
|
||||||
"authentication_methods": "Todennus",
|
"authentication_methods": "Todennus",
|
||||||
"warning_of_generate_new_codes": "Luodessasi uudet palautuskoodit, vanhat koodisi lakkaavat toimimasta.",
|
"warning_of_generate_new_codes": "Luodessasi uudet palautuskoodit, vanhat koodisi lakkaavat toimimasta.",
|
||||||
"recovery_codes": "Palautuskoodit.",
|
"recovery_codes": "Palautuskoodit.",
|
||||||
"waiting_a_recovery_codes": "Odotetaan palautuskoodeja...",
|
"waiting_a_recovery_codes": "Odotetaan palautuskoodeja…",
|
||||||
"recovery_codes_warning": "Kirjoita koodit ylös tai tallenna ne turvallisesti, muuten et näe niitä uudestaan. Jos et voi käyttää monivaihetodennusta ja sinulla ei ole palautuskoodeja, et voi enää kirjautua sisään tilillesi.",
|
"recovery_codes_warning": "Kirjoita koodit ylös tai tallenna ne turvallisesti, muuten et näe niitä uudestaan. Jos et voi käyttää monivaihetodennusta ja sinulla ei ole palautuskoodeja, et voi enää kirjautua sisään tilillesi.",
|
||||||
"scan": {
|
"scan": {
|
||||||
"title": "Skannaa",
|
"title": "Skannaa",
|
||||||
|
@ -575,7 +575,7 @@
|
||||||
"statuses": "Viestit",
|
"statuses": "Viestit",
|
||||||
"hidden": "Piilotettu",
|
"hidden": "Piilotettu",
|
||||||
"media": "Media",
|
"media": "Media",
|
||||||
"block_progress": "Estetään...",
|
"block_progress": "Estetään…",
|
||||||
"admin_menu": {
|
"admin_menu": {
|
||||||
"grant_admin": "Anna Ylläpitöoikeudet",
|
"grant_admin": "Anna Ylläpitöoikeudet",
|
||||||
"force_nsfw": "Merkitse kaikki viestit NSFW:nä",
|
"force_nsfw": "Merkitse kaikki viestit NSFW:nä",
|
||||||
|
@ -601,10 +601,10 @@
|
||||||
"subscribe": "Tilaa",
|
"subscribe": "Tilaa",
|
||||||
"unsubscribe": "Poista tilaus",
|
"unsubscribe": "Poista tilaus",
|
||||||
"unblock": "Poista esto",
|
"unblock": "Poista esto",
|
||||||
"unblock_progress": "Postetaan estoa...",
|
"unblock_progress": "Postetaan estoa…",
|
||||||
"unmute": "Poista mykistys",
|
"unmute": "Poista mykistys",
|
||||||
"unmute_progress": "Poistetaan mykistystä...",
|
"unmute_progress": "Poistetaan mykistystä…",
|
||||||
"mute_progress": "Mykistetään...",
|
"mute_progress": "Mykistetään…",
|
||||||
"hide_repeats": "Piilota toistot",
|
"hide_repeats": "Piilota toistot",
|
||||||
"show_repeats": "Näytä toistot"
|
"show_repeats": "Näytä toistot"
|
||||||
},
|
},
|
||||||
|
@ -674,8 +674,8 @@
|
||||||
"domain_mute_card": {
|
"domain_mute_card": {
|
||||||
"mute": "Mykistä",
|
"mute": "Mykistä",
|
||||||
"unmute": "Poista mykistys",
|
"unmute": "Poista mykistys",
|
||||||
"mute_progress": "Mykistetään...",
|
"mute_progress": "Mykistetään…",
|
||||||
"unmute_progress": "Poistetaan mykistyst..."
|
"unmute_progress": "Poistetaan mykistyst…"
|
||||||
},
|
},
|
||||||
"exporter": {
|
"exporter": {
|
||||||
"export": "Vie",
|
"export": "Vie",
|
||||||
|
|
123
src/i18n/it.json
123
src/i18n/it.json
|
@ -34,7 +34,8 @@
|
||||||
"user_search": "Ricerca utenti",
|
"user_search": "Ricerca utenti",
|
||||||
"search": "Ricerca",
|
"search": "Ricerca",
|
||||||
"who_to_follow": "Chi seguire",
|
"who_to_follow": "Chi seguire",
|
||||||
"preferences": "Preferenze"
|
"preferences": "Preferenze",
|
||||||
|
"bookmarks": "Segnalibri"
|
||||||
},
|
},
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"followed_you": "ti segue",
|
"followed_you": "ti segue",
|
||||||
|
@ -271,10 +272,59 @@
|
||||||
"shadow_id": "Ombra numero {value}",
|
"shadow_id": "Ombra numero {value}",
|
||||||
"override": "Sostituisci",
|
"override": "Sostituisci",
|
||||||
"component": "Componente",
|
"component": "Componente",
|
||||||
"_tab_label": "Luci ed ombre"
|
"_tab_label": "Luci ed ombre",
|
||||||
|
"components": {
|
||||||
|
"avatarStatus": "Icona utente (vista messaggio)",
|
||||||
|
"avatar": "Icona utente (vista profilo)",
|
||||||
|
"topBar": "Barra superiore",
|
||||||
|
"panelHeader": "Intestazione pannello",
|
||||||
|
"panel": "Pannello",
|
||||||
|
"input": "Campo d'immissione",
|
||||||
|
"buttonPressedHover": "Pulsante (puntato e premuto)",
|
||||||
|
"buttonPressed": "Pulsante (premuto)",
|
||||||
|
"buttonHover": "Pulsante (puntato)",
|
||||||
|
"button": "Pulsante",
|
||||||
|
"popup": "Sbalzi e suggerimenti"
|
||||||
|
},
|
||||||
|
"filter_hint": {
|
||||||
|
"inset_classic": "Le ombre incluse usano {0}",
|
||||||
|
"spread_zero": "Lo spandimento maggiore di zero si azzera sulle ombre",
|
||||||
|
"avatar_inset": "Tieni presente che combinare ombre (sia incluse che non) sulle icone utente potrebbe dare risultati strani con quelle trasparenti.",
|
||||||
|
"drop_shadow_syntax": "{0} non supporta il parametro {1} né la keyword {2}.",
|
||||||
|
"always_drop_shadow": "Attenzione: quest'ombra usa sempre {0} se il tuo browser lo supporta."
|
||||||
|
},
|
||||||
|
"hintV3": "Per le ombre puoi anche usare la sintassi {0} per sfruttare il secondo colore."
|
||||||
},
|
},
|
||||||
"radii": {
|
"radii": {
|
||||||
"_tab_label": "Raggio"
|
"_tab_label": "Raggio"
|
||||||
|
},
|
||||||
|
"fonts": {
|
||||||
|
"_tab_label": "Font",
|
||||||
|
"custom": "Personalizzato",
|
||||||
|
"weight": "Peso (grassettatura)",
|
||||||
|
"size": "Dimensione (in pixel)",
|
||||||
|
"family": "Nome font",
|
||||||
|
"components": {
|
||||||
|
"postCode": "Font a spaziatura fissa incluso in un messaggio",
|
||||||
|
"post": "Testo del messaggio",
|
||||||
|
"input": "Campi d'immissione",
|
||||||
|
"interface": "Interfaccia"
|
||||||
|
},
|
||||||
|
"help": "Seleziona il font da usare per gli elementi dell'interfaccia. Se scegli \"personalizzato\" devi inserire il suo nome di sistema."
|
||||||
|
},
|
||||||
|
"preview": {
|
||||||
|
"link": "un bel collegamentino",
|
||||||
|
"checkbox": "Ho dato uno sguardo a termini e condizioni",
|
||||||
|
"header_faint": "Tutto bene",
|
||||||
|
"fine_print": "Leggi il nostro {0} per imparare un bel niente!",
|
||||||
|
"faint_link": "utilissimo manuale",
|
||||||
|
"input": "Sono appena atterrato a Fiumicino.",
|
||||||
|
"mono": "contenuto",
|
||||||
|
"text": "Altro {0} e {1}",
|
||||||
|
"content": "Contenuto",
|
||||||
|
"button": "Pulsante",
|
||||||
|
"error": "Errore d'esempio",
|
||||||
|
"header": "Anteprima"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"enable_web_push_notifications": "Abilita notifiche web push",
|
"enable_web_push_notifications": "Abilita notifiche web push",
|
||||||
|
@ -336,7 +386,19 @@
|
||||||
"emoji_reactions_on_timeline": "Mostra emoji di reazione sulle sequenze",
|
"emoji_reactions_on_timeline": "Mostra emoji di reazione sulle sequenze",
|
||||||
"pad_emoji": "Affianca spazi agli emoji inseriti tramite selettore",
|
"pad_emoji": "Affianca spazi agli emoji inseriti tramite selettore",
|
||||||
"notification_blocks": "Bloccando un utente non riceverai più le sue notifiche né lo seguirai più.",
|
"notification_blocks": "Bloccando un utente non riceverai più le sue notifiche né lo seguirai più.",
|
||||||
"mutes_and_blocks": "Zittiti e bloccati"
|
"mutes_and_blocks": "Zittiti e bloccati",
|
||||||
|
"profile_fields": {
|
||||||
|
"value": "Contenuto",
|
||||||
|
"name": "Etichetta",
|
||||||
|
"add_field": "Aggiungi campo",
|
||||||
|
"label": "Metadati profilo"
|
||||||
|
},
|
||||||
|
"bot": "Questo profilo è di un robot",
|
||||||
|
"version": {
|
||||||
|
"frontend_version": "Versione interfaccia",
|
||||||
|
"backend_version": "Versione backend",
|
||||||
|
"title": "Versione"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"timeline": {
|
"timeline": {
|
||||||
"error_fetching": "Errore nell'aggiornamento",
|
"error_fetching": "Errore nell'aggiornamento",
|
||||||
|
@ -346,7 +408,10 @@
|
||||||
"collapse": "Riduci",
|
"collapse": "Riduci",
|
||||||
"conversation": "Conversazione",
|
"conversation": "Conversazione",
|
||||||
"no_retweet_hint": "Il messaggio è diretto o solo per seguaci e non può essere condiviso",
|
"no_retweet_hint": "Il messaggio è diretto o solo per seguaci e non può essere condiviso",
|
||||||
"repeated": "condiviso"
|
"repeated": "condiviso",
|
||||||
|
"no_statuses": "Nessun messaggio",
|
||||||
|
"no_more_statuses": "Fine dei messaggi",
|
||||||
|
"reload": "Ricarica"
|
||||||
},
|
},
|
||||||
"user_card": {
|
"user_card": {
|
||||||
"follow": "Segui",
|
"follow": "Segui",
|
||||||
|
@ -425,7 +490,10 @@
|
||||||
},
|
},
|
||||||
"direct_warning_to_first_only": "Questo messaggio sarà visibile solo agli utenti menzionati all'inizio.",
|
"direct_warning_to_first_only": "Questo messaggio sarà visibile solo agli utenti menzionati all'inizio.",
|
||||||
"direct_warning_to_all": "Questo messaggio sarà visibile a tutti i menzionati.",
|
"direct_warning_to_all": "Questo messaggio sarà visibile a tutti i menzionati.",
|
||||||
"new_status": "Nuovo messaggio"
|
"new_status": "Nuovo messaggio",
|
||||||
|
"empty_status_error": "Non puoi pubblicare messaggi vuoti senza allegati",
|
||||||
|
"preview_empty": "Vuoto",
|
||||||
|
"preview": "Anteprima"
|
||||||
},
|
},
|
||||||
"registration": {
|
"registration": {
|
||||||
"bio": "Introduzione",
|
"bio": "Introduzione",
|
||||||
|
@ -548,5 +616,50 @@
|
||||||
"error": "Non trovato.",
|
"error": "Non trovato.",
|
||||||
"searching_for": "Cerco",
|
"searching_for": "Cerco",
|
||||||
"remote_user_resolver": "Cerca utenti remoti"
|
"remote_user_resolver": "Cerca utenti remoti"
|
||||||
|
},
|
||||||
|
"errors": {
|
||||||
|
"storage_unavailable": "Pleroma non ha potuto accedere ai dati del tuo browser. Le tue credenziali o le tue impostazioni locali non potranno essere salvate e potresti incontrare strani errori. Prova ad abilitare i cookie."
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"pinned": "Intestato",
|
||||||
|
"unpin": "De-intesta",
|
||||||
|
"pin": "Intesta al profilo",
|
||||||
|
"delete": "Elimina messaggio",
|
||||||
|
"repeats": "Condivisi",
|
||||||
|
"favorites": "Preferiti"
|
||||||
|
},
|
||||||
|
"time": {
|
||||||
|
"years_short": "{0}a",
|
||||||
|
"year_short": "{0}a",
|
||||||
|
"years": "{0} anni",
|
||||||
|
"year": "{0} anno",
|
||||||
|
"weeks_short": "{0}set",
|
||||||
|
"week_short": "{0}set",
|
||||||
|
"seconds_short": "{0}sec",
|
||||||
|
"second_short": "{0}sec",
|
||||||
|
"weeks": "{0} settimane",
|
||||||
|
"week": "{0} settimana",
|
||||||
|
"seconds": "{0} secondi",
|
||||||
|
"second": "{0} secondo",
|
||||||
|
"now_short": "ora",
|
||||||
|
"now": "adesso",
|
||||||
|
"months_short": "{0}me",
|
||||||
|
"month_short": "{0}me",
|
||||||
|
"months": "{0} mesi",
|
||||||
|
"month": "{0} mese",
|
||||||
|
"minutes_short": "{0}min",
|
||||||
|
"minute_short": "{0}min",
|
||||||
|
"minutes": "{0} minuti",
|
||||||
|
"minute": "{0} minuto",
|
||||||
|
"in_past": "{0} fa",
|
||||||
|
"in_future": "fra {0}",
|
||||||
|
"hours_short": "{0}h",
|
||||||
|
"days_short": "{0}g",
|
||||||
|
"hour_short": "{0}h",
|
||||||
|
"hours": "{0} ore",
|
||||||
|
"hour": "{0} ora",
|
||||||
|
"day_short": "{0}g",
|
||||||
|
"days": "{0} giorni",
|
||||||
|
"day": "{0} giorno"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,7 @@
|
||||||
"administration": "管理员"
|
"administration": "管理员"
|
||||||
},
|
},
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"broken_favorite": "未知的状态,正在搜索中...",
|
"broken_favorite": "未知的状态,正在搜索中…",
|
||||||
"favorited_you": "收藏了你的状态",
|
"favorited_you": "收藏了你的状态",
|
||||||
"followed_you": "关注了你",
|
"followed_you": "关注了你",
|
||||||
"load_older": "加载更早的通知",
|
"load_older": "加载更早的通知",
|
||||||
|
@ -185,7 +185,7 @@
|
||||||
"generate_new_recovery_codes": "生成新的恢复码",
|
"generate_new_recovery_codes": "生成新的恢复码",
|
||||||
"warning_of_generate_new_codes": "当你生成新的恢复码时,你的旧恢复码就失效了。",
|
"warning_of_generate_new_codes": "当你生成新的恢复码时,你的旧恢复码就失效了。",
|
||||||
"recovery_codes": "恢复码。",
|
"recovery_codes": "恢复码。",
|
||||||
"waiting_a_recovery_codes": "正在接收备份码……",
|
"waiting_a_recovery_codes": "正在接收备份码…",
|
||||||
"recovery_codes_warning": "抄写这些号码,或者保存在安全的地方。这些号码不会再次显示。如果你无法访问你的 2FA app,也丢失了你的恢复码,你的账号就再也无法登录了。",
|
"recovery_codes_warning": "抄写这些号码,或者保存在安全的地方。这些号码不会再次显示。如果你无法访问你的 2FA app,也丢失了你的恢复码,你的账号就再也无法登录了。",
|
||||||
"authentication_methods": "身份验证方法",
|
"authentication_methods": "身份验证方法",
|
||||||
"scan": {
|
"scan": {
|
||||||
|
@ -564,11 +564,11 @@
|
||||||
"subscribe": "订阅",
|
"subscribe": "订阅",
|
||||||
"unsubscribe": "退订",
|
"unsubscribe": "退订",
|
||||||
"unblock": "取消拉黑",
|
"unblock": "取消拉黑",
|
||||||
"unblock_progress": "取消拉黑中...",
|
"unblock_progress": "取消拉黑中…",
|
||||||
"block_progress": "拉黑中...",
|
"block_progress": "拉黑中…",
|
||||||
"unmute": "取消隐藏",
|
"unmute": "取消隐藏",
|
||||||
"unmute_progress": "取消隐藏中...",
|
"unmute_progress": "取消隐藏中…",
|
||||||
"mute_progress": "隐藏中...",
|
"mute_progress": "隐藏中…",
|
||||||
"admin_menu": {
|
"admin_menu": {
|
||||||
"moderation": "权限",
|
"moderation": "权限",
|
||||||
"grant_admin": "赋予管理权限",
|
"grant_admin": "赋予管理权限",
|
||||||
|
@ -690,9 +690,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"domain_mute_card": {
|
"domain_mute_card": {
|
||||||
"unmute_progress": "正在取消隐藏……",
|
"unmute_progress": "正在取消隐藏…",
|
||||||
"unmute": "取消隐藏",
|
"unmute": "取消隐藏",
|
||||||
"mute_progress": "隐藏中……",
|
"mute_progress": "隐藏中…",
|
||||||
"mute": "隐藏"
|
"mute": "隐藏"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,8 @@ const defaultState = {
|
||||||
|
|
||||||
// Stuff from static/config.json
|
// Stuff from static/config.json
|
||||||
alwaysShowSubjectInput: true,
|
alwaysShowSubjectInput: true,
|
||||||
|
defaultAvatar: '/images/avi.png',
|
||||||
|
defaultBanner: '/images/banner.png',
|
||||||
background: '/static/aurora_borealis.jpg',
|
background: '/static/aurora_borealis.jpg',
|
||||||
collapseMessageWithSubject: false,
|
collapseMessageWithSubject: false,
|
||||||
disableChat: false,
|
disableChat: false,
|
||||||
|
|
|
@ -22,7 +22,7 @@ const mediaViewer = {
|
||||||
setMedia ({ commit }, attachments) {
|
setMedia ({ commit }, attachments) {
|
||||||
const media = attachments.filter(attachment => {
|
const media = attachments.filter(attachment => {
|
||||||
const type = fileTypeService.fileType(attachment.mimetype)
|
const type = fileTypeService.fileType(attachment.mimetype)
|
||||||
return type === 'image' || type === 'video'
|
return type === 'image' || type === 'video' || type === 'audio'
|
||||||
})
|
})
|
||||||
commit('setMedia', media)
|
commit('setMedia', media)
|
||||||
},
|
},
|
||||||
|
|
|
@ -266,6 +266,11 @@ const users = {
|
||||||
mutations,
|
mutations,
|
||||||
getters,
|
getters,
|
||||||
actions: {
|
actions: {
|
||||||
|
fetchUserIfMissing (store, id) {
|
||||||
|
if (!store.getters.findUser(id)) {
|
||||||
|
store.dispatch('fetchUser', id)
|
||||||
|
}
|
||||||
|
},
|
||||||
fetchUser (store, id) {
|
fetchUser (store, id) {
|
||||||
return store.rootState.api.backendInteractor.fetchUser({ id })
|
return store.rootState.api.backendInteractor.fetchUser({ id })
|
||||||
.then((user) => {
|
.then((user) => {
|
||||||
|
|
|
@ -141,20 +141,11 @@ const updateNotificationSettings = ({ credentials, settings }) => {
|
||||||
}).then((data) => data.json())
|
}).then((data) => data.json())
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateAvatar = ({ credentials, avatar }) => {
|
const updateProfileImages = ({ credentials, avatar = null, banner = null, background = null }) => {
|
||||||
const form = new FormData()
|
const form = new FormData()
|
||||||
form.append('avatar', avatar)
|
if (avatar !== null) form.append('avatar', avatar)
|
||||||
return fetch(MASTODON_PROFILE_UPDATE_URL, {
|
if (banner !== null) form.append('header', banner)
|
||||||
headers: authHeaders(credentials),
|
if (background !== null) form.append('pleroma_background_image', background)
|
||||||
method: 'PATCH',
|
|
||||||
body: form
|
|
||||||
}).then((data) => data.json())
|
|
||||||
.then((data) => parseUser(data))
|
|
||||||
}
|
|
||||||
|
|
||||||
const updateBg = ({ credentials, background }) => {
|
|
||||||
const form = new FormData()
|
|
||||||
form.append('pleroma_background_image', background)
|
|
||||||
return fetch(MASTODON_PROFILE_UPDATE_URL, {
|
return fetch(MASTODON_PROFILE_UPDATE_URL, {
|
||||||
headers: authHeaders(credentials),
|
headers: authHeaders(credentials),
|
||||||
method: 'PATCH',
|
method: 'PATCH',
|
||||||
|
@ -164,17 +155,6 @@ const updateBg = ({ credentials, background }) => {
|
||||||
.then((data) => parseUser(data))
|
.then((data) => parseUser(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateBanner = ({ credentials, banner }) => {
|
|
||||||
const form = new FormData()
|
|
||||||
form.append('header', banner)
|
|
||||||
return fetch(MASTODON_PROFILE_UPDATE_URL, {
|
|
||||||
headers: authHeaders(credentials),
|
|
||||||
method: 'PATCH',
|
|
||||||
body: form
|
|
||||||
}).then((data) => data.json())
|
|
||||||
.then((data) => parseUser(data))
|
|
||||||
}
|
|
||||||
|
|
||||||
const updateProfile = ({ credentials, params }) => {
|
const updateProfile = ({ credentials, params }) => {
|
||||||
return promisedRequest({
|
return promisedRequest({
|
||||||
url: MASTODON_PROFILE_UPDATE_URL,
|
url: MASTODON_PROFILE_UPDATE_URL,
|
||||||
|
@ -645,7 +625,8 @@ const postStatus = ({
|
||||||
poll,
|
poll,
|
||||||
mediaIds = [],
|
mediaIds = [],
|
||||||
inReplyToStatusId,
|
inReplyToStatusId,
|
||||||
contentType
|
contentType,
|
||||||
|
preview
|
||||||
}) => {
|
}) => {
|
||||||
const form = new FormData()
|
const form = new FormData()
|
||||||
const pollOptions = poll.options || []
|
const pollOptions = poll.options || []
|
||||||
|
@ -675,6 +656,9 @@ const postStatus = ({
|
||||||
if (inReplyToStatusId) {
|
if (inReplyToStatusId) {
|
||||||
form.append('in_reply_to_id', inReplyToStatusId)
|
form.append('in_reply_to_id', inReplyToStatusId)
|
||||||
}
|
}
|
||||||
|
if (preview) {
|
||||||
|
form.append('preview', 'true')
|
||||||
|
}
|
||||||
|
|
||||||
return fetch(MASTODON_POST_STATUS_URL, {
|
return fetch(MASTODON_POST_STATUS_URL, {
|
||||||
body: form,
|
body: form,
|
||||||
|
@ -682,13 +666,7 @@ const postStatus = ({
|
||||||
headers: authHeaders(credentials)
|
headers: authHeaders(credentials)
|
||||||
})
|
})
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
if (response.ok) {
|
|
||||||
return response.json()
|
return response.json()
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
error: response
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.then((data) => data.error ? data : parseStatus(data))
|
.then((data) => data.error ? data : parseStatus(data))
|
||||||
}
|
}
|
||||||
|
@ -710,6 +688,17 @@ const uploadMedia = ({ formData, credentials }) => {
|
||||||
.then((data) => parseAttachment(data))
|
.then((data) => parseAttachment(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const setMediaDescription = ({ id, description, credentials }) => {
|
||||||
|
return promisedRequest({
|
||||||
|
url: `${MASTODON_MEDIA_UPLOAD_URL}/${id}`,
|
||||||
|
method: 'PUT',
|
||||||
|
headers: authHeaders(credentials),
|
||||||
|
payload: {
|
||||||
|
description
|
||||||
|
}
|
||||||
|
}).then((data) => parseAttachment(data))
|
||||||
|
}
|
||||||
|
|
||||||
const importBlocks = ({ file, credentials }) => {
|
const importBlocks = ({ file, credentials }) => {
|
||||||
const formData = new FormData()
|
const formData = new FormData()
|
||||||
formData.append('list', file)
|
formData.append('list', file)
|
||||||
|
@ -1179,6 +1168,7 @@ const apiService = {
|
||||||
postStatus,
|
postStatus,
|
||||||
deleteStatus,
|
deleteStatus,
|
||||||
uploadMedia,
|
uploadMedia,
|
||||||
|
setMediaDescription,
|
||||||
fetchMutes,
|
fetchMutes,
|
||||||
muteUser,
|
muteUser,
|
||||||
unmuteUser,
|
unmuteUser,
|
||||||
|
@ -1196,10 +1186,8 @@ const apiService = {
|
||||||
deactivateUser,
|
deactivateUser,
|
||||||
register,
|
register,
|
||||||
getCaptcha,
|
getCaptcha,
|
||||||
updateAvatar,
|
updateProfileImages,
|
||||||
updateBg,
|
|
||||||
updateProfile,
|
updateProfile,
|
||||||
updateBanner,
|
|
||||||
importBlocks,
|
importBlocks,
|
||||||
importFollows,
|
importFollows,
|
||||||
deleteAccount,
|
deleteAccount,
|
||||||
|
|
|
@ -1,7 +1,18 @@
|
||||||
import { map } from 'lodash'
|
import { map } from 'lodash'
|
||||||
import apiService from '../api/api.service.js'
|
import apiService from '../api/api.service.js'
|
||||||
|
|
||||||
const postStatus = ({ store, status, spoilerText, visibility, sensitive, poll, media = [], inReplyToStatusId = undefined, contentType = 'text/plain' }) => {
|
const postStatus = ({
|
||||||
|
store,
|
||||||
|
status,
|
||||||
|
spoilerText,
|
||||||
|
visibility,
|
||||||
|
sensitive,
|
||||||
|
poll,
|
||||||
|
media = [],
|
||||||
|
inReplyToStatusId = undefined,
|
||||||
|
contentType = 'text/plain',
|
||||||
|
preview = false
|
||||||
|
}) => {
|
||||||
const mediaIds = map(media, 'id')
|
const mediaIds = map(media, 'id')
|
||||||
|
|
||||||
return apiService.postStatus({
|
return apiService.postStatus({
|
||||||
|
@ -13,9 +24,11 @@ const postStatus = ({ store, status, spoilerText, visibility, sensitive, poll, m
|
||||||
mediaIds,
|
mediaIds,
|
||||||
inReplyToStatusId,
|
inReplyToStatusId,
|
||||||
contentType,
|
contentType,
|
||||||
poll })
|
poll,
|
||||||
|
preview
|
||||||
|
})
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (!data.error) {
|
if (!data.error && !preview) {
|
||||||
store.dispatch('addNewStatuses', {
|
store.dispatch('addNewStatuses', {
|
||||||
statuses: [data],
|
statuses: [data],
|
||||||
timeline: 'friends',
|
timeline: 'friends',
|
||||||
|
@ -34,13 +47,18 @@ const postStatus = ({ store, status, spoilerText, visibility, sensitive, poll, m
|
||||||
|
|
||||||
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 })
|
return apiService.uploadMedia({ credentials, formData })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const setMediaDescription = ({ store, id, description }) => {
|
||||||
|
const credentials = store.state.users.currentUser.credentials
|
||||||
|
return apiService.setMediaDescription({ credentials, id, description })
|
||||||
|
}
|
||||||
|
|
||||||
const statusPosterService = {
|
const statusPosterService = {
|
||||||
postStatus,
|
postStatus,
|
||||||
uploadMedia
|
uploadMedia,
|
||||||
|
setMediaDescription
|
||||||
}
|
}
|
||||||
|
|
||||||
export default statusPosterService
|
export default statusPosterService
|
||||||
|
|
|
@ -387,6 +387,18 @@
|
||||||
"css": "bookmark-empty",
|
"css": "bookmark-empty",
|
||||||
"code": 61591,
|
"code": 61591,
|
||||||
"src": "fontawesome"
|
"src": "fontawesome"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uid": "9ea0a737ccc45d6c510dcbae56058849",
|
||||||
|
"css": "music",
|
||||||
|
"code": 59432,
|
||||||
|
"src": "fontawesome"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uid": "1b5a5d7b7e3c71437f5a26befdd045ed",
|
||||||
|
"css": "doc",
|
||||||
|
"code": 59433,
|
||||||
|
"src": "fontawesome"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
Loading…
Add table
Reference in a new issue