Merge branch 'develop' into delete-gitlab-ci
All checks were successful
ci/woodpecker/pr/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/pr/woodpecker Pipeline was successful
This commit is contained in:
commit
ad8be6b199
80 changed files with 2152 additions and 200 deletions
|
@ -10,3 +10,5 @@ Contributors of this project.
|
||||||
- shpuld (shpuld@shitposter.club): CSS and styling
|
- shpuld (shpuld@shitposter.club): CSS and styling
|
||||||
- Vincent Guth (https://unsplash.com/photos/XrwVIFy6rTw): Background images.
|
- Vincent Guth (https://unsplash.com/photos/XrwVIFy6rTw): Background images.
|
||||||
- hj (hj@shigusegubu.club): Code
|
- hj (hj@shigusegubu.club): Code
|
||||||
|
- Sean King (seanking@freespeechextremist.com): Code
|
||||||
|
- Tusooa Zhu (tusooa@kazv.moe): Code
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
# Pleroma-FE
|
# Pleroma-FE
|
||||||
|
|
||||||
|
![English OK](https://img.shields.io/badge/English-OK-blueviolet) ![日本語OK](https://img.shields.io/badge/%E6%97%A5%E6%9C%AC%E8%AA%9E-OK-blueviolet)
|
||||||
|
|
||||||
This is a fork of Pleroma-FE from the Pleroma project, with support for new Akkoma features such as:
|
This is a fork of Pleroma-FE from the Pleroma project, with support for new Akkoma features such as:
|
||||||
- MFM support via [marked-mfm](https://akkoma.dev/sfr/marked-mfm)
|
- MFM support via [marked-mfm](https://akkoma.dev/sfr/marked-mfm)
|
||||||
- Custom emoji reactions
|
- Custom emoji reactions
|
||||||
|
|
4
config/ihba.json
Normal file
4
config/ihba.json
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"target": "https://ihatebeinga.live",
|
||||||
|
"staticConfigPreference": false
|
||||||
|
}
|
|
@ -15,6 +15,7 @@
|
||||||
<body class="hidden">
|
<body class="hidden">
|
||||||
<noscript>To use Pleroma, please enable JavaScript.</noscript>
|
<noscript>To use Pleroma, please enable JavaScript.</noscript>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
<div id="modal"></div>
|
||||||
<!-- built files will be auto injected -->
|
<!-- built files will be auto injected -->
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
"@babel/runtime": "7.17.8",
|
"@babel/runtime": "7.17.8",
|
||||||
"@chenfengyuan/vue-qrcode": "2.0.0",
|
"@chenfengyuan/vue-qrcode": "2.0.0",
|
||||||
"@fortawesome/fontawesome-svg-core": "1.3.0",
|
"@fortawesome/fontawesome-svg-core": "1.3.0",
|
||||||
"@fortawesome/free-regular-svg-icons": "5.15.4",
|
"@fortawesome/free-regular-svg-icons": "^6.1.2",
|
||||||
"@fortawesome/free-solid-svg-icons": "5.15.4",
|
"@fortawesome/free-solid-svg-icons": "5.15.4",
|
||||||
"@fortawesome/vue-fontawesome": "3.0.1",
|
"@fortawesome/vue-fontawesome": "3.0.1",
|
||||||
"@kazvmoe-infra/pinch-zoom-element": "1.2.0",
|
"@kazvmoe-infra/pinch-zoom-element": "1.2.0",
|
||||||
|
|
|
@ -10,7 +10,9 @@ import MobilePostStatusButton from './components/mobile_post_status_button/mobil
|
||||||
import MobileNav from './components/mobile_nav/mobile_nav.vue'
|
import MobileNav from './components/mobile_nav/mobile_nav.vue'
|
||||||
import DesktopNav from './components/desktop_nav/desktop_nav.vue'
|
import DesktopNav from './components/desktop_nav/desktop_nav.vue'
|
||||||
import UserReportingModal from './components/user_reporting_modal/user_reporting_modal.vue'
|
import UserReportingModal from './components/user_reporting_modal/user_reporting_modal.vue'
|
||||||
|
import EditStatusModal from './components/edit_status_modal/edit_status_modal.vue'
|
||||||
import PostStatusModal from './components/post_status_modal/post_status_modal.vue'
|
import PostStatusModal from './components/post_status_modal/post_status_modal.vue'
|
||||||
|
import StatusHistoryModal from './components/status_history_modal/status_history_modal.vue'
|
||||||
import GlobalNoticeList from './components/global_notice_list/global_notice_list.vue'
|
import GlobalNoticeList from './components/global_notice_list/global_notice_list.vue'
|
||||||
import { windowWidth, windowHeight } from './services/window_utils/window_utils'
|
import { windowWidth, windowHeight } from './services/window_utils/window_utils'
|
||||||
import { mapGetters } from 'vuex'
|
import { mapGetters } from 'vuex'
|
||||||
|
@ -33,6 +35,8 @@ export default {
|
||||||
SettingsModal,
|
SettingsModal,
|
||||||
UserReportingModal,
|
UserReportingModal,
|
||||||
PostStatusModal,
|
PostStatusModal,
|
||||||
|
EditStatusModal,
|
||||||
|
StatusHistoryModal,
|
||||||
GlobalNoticeList
|
GlobalNoticeList
|
||||||
},
|
},
|
||||||
data: () => ({
|
data: () => ({
|
||||||
|
@ -83,6 +87,7 @@ export default {
|
||||||
return this.$store.getters.mergedConfig.alwaysShowNewPostButton || this.layoutType === 'mobile'
|
return this.$store.getters.mergedConfig.alwaysShowNewPostButton || this.layoutType === 'mobile'
|
||||||
},
|
},
|
||||||
showFeaturesPanel () { return this.$store.state.instance.showFeaturesPanel },
|
showFeaturesPanel () { return this.$store.state.instance.showFeaturesPanel },
|
||||||
|
editingAvailable () { return this.$store.state.instance.editingAvailable },
|
||||||
layoutType () { return this.$store.state.interface.layoutType },
|
layoutType () { return this.$store.state.interface.layoutType },
|
||||||
privateMode () { return this.$store.state.instance.private },
|
privateMode () { return this.$store.state.instance.private },
|
||||||
reverseLayout () {
|
reverseLayout () {
|
||||||
|
|
|
@ -58,8 +58,10 @@
|
||||||
<MobilePostStatusButton />
|
<MobilePostStatusButton />
|
||||||
<UserReportingModal />
|
<UserReportingModal />
|
||||||
<PostStatusModal />
|
<PostStatusModal />
|
||||||
|
<EditStatusModal v-if="editingAvailable" />
|
||||||
|
<StatusHistoryModal v-if="editingAvailable" />
|
||||||
<SettingsModal />
|
<SettingsModal />
|
||||||
<div id="modal" />
|
<UpdateNotification />
|
||||||
<GlobalNoticeList />
|
<GlobalNoticeList />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import Cookies from 'js-cookie'
|
||||||
import { createApp } from 'vue'
|
import { createApp } from 'vue'
|
||||||
import { createRouter, createWebHistory } from 'vue-router'
|
import { createRouter, createWebHistory } from 'vue-router'
|
||||||
import vClickOutside from 'click-outside-vue3'
|
import vClickOutside from 'click-outside-vue3'
|
||||||
|
@ -48,6 +49,20 @@ const preloadFetch = async (request) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const resolveLanguage = (instanceLanguages) => {
|
||||||
|
// First language in navigator.languages that is listed as an instance language
|
||||||
|
// falls back to first instance language
|
||||||
|
const navigatorLanguages = navigator.languages.map((x) => x.split('-')[0])
|
||||||
|
|
||||||
|
for (const navLanguage of navigatorLanguages) {
|
||||||
|
if (instanceLanguages.includes(navLanguage)) {
|
||||||
|
return navLanguage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return instanceLanguages[0]
|
||||||
|
}
|
||||||
|
|
||||||
const getInstanceConfig = async ({ store }) => {
|
const getInstanceConfig = async ({ store }) => {
|
||||||
try {
|
try {
|
||||||
const res = await preloadFetch('/api/v1/instance')
|
const res = await preloadFetch('/api/v1/instance')
|
||||||
|
@ -58,6 +73,10 @@ const getInstanceConfig = async ({ store }) => {
|
||||||
|
|
||||||
store.dispatch('setInstanceOption', { name: 'textlimit', value: textlimit })
|
store.dispatch('setInstanceOption', { name: 'textlimit', value: textlimit })
|
||||||
store.dispatch('setInstanceOption', { name: 'accountApprovalRequired', value: data.approval_required })
|
store.dispatch('setInstanceOption', { name: 'accountApprovalRequired', value: data.approval_required })
|
||||||
|
// don't override cookie if set
|
||||||
|
if (!Cookies.get('userLanguage')) {
|
||||||
|
store.dispatch('setOption', { name: 'interfaceLanguage', value: resolveLanguage(data.languages) })
|
||||||
|
}
|
||||||
|
|
||||||
if (vapidPublicKey) {
|
if (vapidPublicKey) {
|
||||||
store.dispatch('setInstanceOption', { name: 'vapidPublicKey', value: vapidPublicKey })
|
store.dispatch('setInstanceOption', { name: 'vapidPublicKey', value: vapidPublicKey })
|
||||||
|
@ -124,6 +143,11 @@ const setSettings = async ({ apiConfig, staticConfig, store }) => {
|
||||||
copyInstanceOption('hideBotIndication')
|
copyInstanceOption('hideBotIndication')
|
||||||
copyInstanceOption('hideUserStats')
|
copyInstanceOption('hideUserStats')
|
||||||
copyInstanceOption('hideFilteredStatuses')
|
copyInstanceOption('hideFilteredStatuses')
|
||||||
|
copyInstanceOption('hideSiteName')
|
||||||
|
copyInstanceOption('hideSiteFavicon')
|
||||||
|
copyInstanceOption('showWiderShortcuts')
|
||||||
|
copyInstanceOption('showNavShortcuts')
|
||||||
|
copyInstanceOption('showPanelNavShortcuts')
|
||||||
copyInstanceOption('logo')
|
copyInstanceOption('logo')
|
||||||
|
|
||||||
store.dispatch('setInstanceOption', {
|
store.dispatch('setInstanceOption', {
|
||||||
|
@ -154,6 +178,7 @@ const setSettings = async ({ apiConfig, staticConfig, store }) => {
|
||||||
copyInstanceOption('alwaysShowSubjectInput')
|
copyInstanceOption('alwaysShowSubjectInput')
|
||||||
copyInstanceOption('showFeaturesPanel')
|
copyInstanceOption('showFeaturesPanel')
|
||||||
copyInstanceOption('hideSitename')
|
copyInstanceOption('hideSitename')
|
||||||
|
copyInstanceOption('renderMisskeyMarkdown')
|
||||||
copyInstanceOption('sidebarRight')
|
copyInstanceOption('sidebarRight')
|
||||||
|
|
||||||
return store.dispatch('setTheme', config['theme'])
|
return store.dispatch('setTheme', config['theme'])
|
||||||
|
@ -248,8 +273,10 @@ const getNodeInfo = async ({ store }) => {
|
||||||
store.dispatch('setInstanceOption', { name: 'mediaProxyAvailable', value: features.includes('media_proxy') })
|
store.dispatch('setInstanceOption', { name: 'mediaProxyAvailable', value: features.includes('media_proxy') })
|
||||||
store.dispatch('setInstanceOption', { name: 'safeDM', value: features.includes('safe_dm_mentions') })
|
store.dispatch('setInstanceOption', { name: 'safeDM', value: features.includes('safe_dm_mentions') })
|
||||||
store.dispatch('setInstanceOption', { name: 'pollsAvailable', value: features.includes('polls') })
|
store.dispatch('setInstanceOption', { name: 'pollsAvailable', value: features.includes('polls') })
|
||||||
|
store.dispatch('setInstanceOption', { name: 'editingAvailable', value: features.includes('editing') })
|
||||||
store.dispatch('setInstanceOption', { name: 'pollLimits', value: metadata.pollLimits })
|
store.dispatch('setInstanceOption', { name: 'pollLimits', value: metadata.pollLimits })
|
||||||
store.dispatch('setInstanceOption', { name: 'mailerEnabled', value: metadata.mailerEnabled })
|
store.dispatch('setInstanceOption', { name: 'mailerEnabled', value: metadata.mailerEnabled })
|
||||||
|
store.dispatch('setInstanceOption', { name: 'translationEnabled', value: features.includes('akkoma:machine_translation') })
|
||||||
|
|
||||||
const uploadLimits = metadata.uploadLimits
|
const uploadLimits = metadata.uploadLimits
|
||||||
store.dispatch('setInstanceOption', { name: 'uploadlimit', value: parseInt(uploadLimits.general) })
|
store.dispatch('setInstanceOption', { name: 'uploadlimit', value: parseInt(uploadLimits.general) })
|
||||||
|
@ -371,6 +398,7 @@ const afterStoreSetup = async ({ store, i18n }) => {
|
||||||
store.dispatch('startFetchingAnnouncements')
|
store.dispatch('startFetchingAnnouncements')
|
||||||
getTOS({ store })
|
getTOS({ store })
|
||||||
getStickers({ store })
|
getStickers({ store })
|
||||||
|
store.dispatch('getSupportedTranslationlanguages')
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(),
|
history: createWebHistory(),
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import ProgressButton from '../progress_button/progress_button.vue'
|
import ProgressButton from '../progress_button/progress_button.vue'
|
||||||
import Popover from '../popover/popover.vue'
|
import Popover from '../popover/popover.vue'
|
||||||
|
import ConfirmModal from '../confirm_modal/confirm_modal.vue'
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
|
import { mapState } from 'vuex'
|
||||||
import {
|
import {
|
||||||
faEllipsisV
|
faEllipsisV
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
@ -14,13 +16,22 @@ const AccountActions = {
|
||||||
'user', 'relationship'
|
'user', 'relationship'
|
||||||
],
|
],
|
||||||
data () {
|
data () {
|
||||||
return { }
|
return {
|
||||||
|
showingConfirmBlock: false
|
||||||
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
ProgressButton,
|
ProgressButton,
|
||||||
Popover
|
Popover,
|
||||||
|
ConfirmModal
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
showConfirmBlock () {
|
||||||
|
this.showingConfirmBlock = true
|
||||||
|
},
|
||||||
|
hideConfirmBlock () {
|
||||||
|
this.showingConfirmBlock = false
|
||||||
|
},
|
||||||
showRepeats () {
|
showRepeats () {
|
||||||
this.$store.dispatch('showReblogs', this.user.id)
|
this.$store.dispatch('showReblogs', this.user.id)
|
||||||
},
|
},
|
||||||
|
@ -28,7 +39,15 @@ const AccountActions = {
|
||||||
this.$store.dispatch('hideReblogs', this.user.id)
|
this.$store.dispatch('hideReblogs', this.user.id)
|
||||||
},
|
},
|
||||||
blockUser () {
|
blockUser () {
|
||||||
|
if (!this.shouldConfirmBlock) {
|
||||||
|
this.doBlockUser()
|
||||||
|
} else {
|
||||||
|
this.showConfirmBlock()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
doBlockUser () {
|
||||||
this.$store.dispatch('blockUser', this.user.id)
|
this.$store.dispatch('blockUser', this.user.id)
|
||||||
|
this.hideConfirmBlock()
|
||||||
},
|
},
|
||||||
unblockUser () {
|
unblockUser () {
|
||||||
this.$store.dispatch('unblockUser', this.user.id)
|
this.$store.dispatch('unblockUser', this.user.id)
|
||||||
|
@ -36,6 +55,14 @@ const AccountActions = {
|
||||||
reportUser () {
|
reportUser () {
|
||||||
this.$store.dispatch('openUserReportingModal', { userId: this.user.id })
|
this.$store.dispatch('openUserReportingModal', { userId: this.user.id })
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
shouldConfirmBlock () {
|
||||||
|
return this.$store.getters.mergedConfig.modalOnBlock
|
||||||
|
},
|
||||||
|
...mapState({
|
||||||
|
pleromaChatMessagesAvailable: state => state.instance.pleromaChatMessagesAvailable
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,27 @@
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
</Popover>
|
</Popover>
|
||||||
|
<teleport to="#modal">
|
||||||
|
<confirm-modal
|
||||||
|
v-if="showingConfirmBlock"
|
||||||
|
:title="$t('user_card.block_confirm_title')"
|
||||||
|
:confirm-text="$t('user_card.block_confirm_accept_button')"
|
||||||
|
:cancel-text="$t('user_card.block_confirm_cancel_button')"
|
||||||
|
@accepted="doBlockUser"
|
||||||
|
@cancelled="hideConfirmBlock"
|
||||||
|
>
|
||||||
|
<i18n-t
|
||||||
|
keypath="user_card.block_confirm"
|
||||||
|
tag="span"
|
||||||
|
>
|
||||||
|
<template v-slot:user>
|
||||||
|
<span
|
||||||
|
v-text="user.screen_name_ui"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</i18n-t>
|
||||||
|
</confirm-modal>
|
||||||
|
</teleport>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="panel panel-default announcements-page">
|
<div class="panel panel-default announcements-page">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<span>
|
<div class="title">
|
||||||
{{ $t('announcements.page_header') }}
|
{{ $t('announcements.page_header') }}
|
||||||
</span>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<section
|
<section
|
||||||
|
|
|
@ -132,6 +132,9 @@ const Attachment = {
|
||||||
...mapGetters(['mergedConfig'])
|
...mapGetters(['mergedConfig'])
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
'attachment.description' (newVal) {
|
||||||
|
this.localDescription = newVal
|
||||||
|
},
|
||||||
localDescription (newVal) {
|
localDescription (newVal) {
|
||||||
this.onEdit(newVal)
|
this.onEdit(newVal)
|
||||||
}
|
}
|
||||||
|
|
37
src/components/confirm_modal/confirm_modal.js
Normal file
37
src/components/confirm_modal/confirm_modal.js
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
import DialogModal from '../dialog_modal/dialog_modal.vue'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This component emits the following events:
|
||||||
|
* cancelled, emitted when the action should not be performed;
|
||||||
|
* accepted, emitted when the action should be performed;
|
||||||
|
*
|
||||||
|
* The caller should close this dialog after receiving any of the two events.
|
||||||
|
*/
|
||||||
|
const ConfirmModal = {
|
||||||
|
components: {
|
||||||
|
DialogModal
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
title: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
cancelText: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
confirmText: {
|
||||||
|
type: String
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onCancel () {
|
||||||
|
this.$emit('cancelled')
|
||||||
|
},
|
||||||
|
onAccept () {
|
||||||
|
this.$emit('accepted')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ConfirmModal
|
39
src/components/confirm_modal/confirm_modal.vue
Normal file
39
src/components/confirm_modal/confirm_modal.vue
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
<template>
|
||||||
|
<dialog-modal
|
||||||
|
v-body-scroll-lock="true"
|
||||||
|
class="confirm-modal"
|
||||||
|
:on-cancel="onCancel"
|
||||||
|
>
|
||||||
|
<template #header>
|
||||||
|
<span v-text="title" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<slot />
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<button
|
||||||
|
class="btn button-default"
|
||||||
|
@click.prevent="onCancel"
|
||||||
|
v-text="cancelText"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
class="btn button-default button-positive"
|
||||||
|
@click.prevent="onAccept"
|
||||||
|
v-text="confirmText"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</dialog-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import '../../_variables';
|
||||||
|
|
||||||
|
.confirm-modal {
|
||||||
|
.button-positive {
|
||||||
|
border: 3px solid var(--accent, $fallback--link);
|
||||||
|
border-radius: var(--btnRadius, $fallback--btnRadius);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script src="./confirm_modal.js"></script>
|
|
@ -1,6 +1,8 @@
|
||||||
import { reduce, filter, findIndex, clone, get } from 'lodash'
|
import { reduce, filter, findIndex, clone, get } from 'lodash'
|
||||||
import Status from '../status/status.vue'
|
import Status from '../status/status.vue'
|
||||||
import ThreadTree from '../thread_tree/thread_tree.vue'
|
import ThreadTree from '../thread_tree/thread_tree.vue'
|
||||||
|
import { WSConnectionStatus } from '../../services/api/api.service.js'
|
||||||
|
import { mapGetters, mapState } from 'vuex'
|
||||||
|
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import {
|
import {
|
||||||
|
@ -77,6 +79,9 @@ const conversation = {
|
||||||
const maxDepth = this.$store.getters.mergedConfig.maxDepthInThread - 2
|
const maxDepth = this.$store.getters.mergedConfig.maxDepthInThread - 2
|
||||||
return maxDepth >= 1 ? maxDepth : 1
|
return maxDepth >= 1 ? maxDepth : 1
|
||||||
},
|
},
|
||||||
|
streamingEnabled () {
|
||||||
|
return this.mergedConfig.useStreamingApi && this.mastoUserSocketStatus === WSConnectionStatus.JOINED
|
||||||
|
},
|
||||||
displayStyle () {
|
displayStyle () {
|
||||||
return this.$store.getters.mergedConfig.conversationDisplay
|
return this.$store.getters.mergedConfig.conversationDisplay
|
||||||
},
|
},
|
||||||
|
@ -339,7 +344,11 @@ const conversation = {
|
||||||
},
|
},
|
||||||
maybeHighlight () {
|
maybeHighlight () {
|
||||||
return this.isExpanded ? this.highlight : null
|
return this.isExpanded ? this.highlight : null
|
||||||
}
|
},
|
||||||
|
...mapGetters(['mergedConfig']),
|
||||||
|
...mapState({
|
||||||
|
mastoUserSocketStatus: state => state.api.mastoUserSocketStatus
|
||||||
|
})
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
Status,
|
Status,
|
||||||
|
@ -395,6 +404,11 @@ const conversation = {
|
||||||
setHighlight (id) {
|
setHighlight (id) {
|
||||||
if (!id) return
|
if (!id) return
|
||||||
this.highlight = id
|
this.highlight = id
|
||||||
|
|
||||||
|
if (!this.streamingEnabled) {
|
||||||
|
this.$store.dispatch('fetchStatus', id)
|
||||||
|
}
|
||||||
|
|
||||||
this.$store.dispatch('fetchFavsAndRepeats', id)
|
this.$store.dispatch('fetchFavsAndRepeats', id)
|
||||||
this.$store.dispatch('fetchEmojiReactionsBy', id)
|
this.$store.dispatch('fetchEmojiReactionsBy', id)
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import SearchBar from 'components/search_bar/search_bar.vue'
|
import SearchBar from 'components/search_bar/search_bar.vue'
|
||||||
|
import ConfirmModal from '../confirm_modal/confirm_modal.vue'
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import {
|
import {
|
||||||
faSignInAlt,
|
faSignInAlt,
|
||||||
|
@ -38,7 +39,8 @@ library.add(
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
SearchBar
|
SearchBar,
|
||||||
|
ConfirmModal
|
||||||
},
|
},
|
||||||
data: () => ({
|
data: () => ({
|
||||||
searchBarHidden: true,
|
searchBarHidden: true,
|
||||||
|
@ -48,7 +50,8 @@ export default {
|
||||||
window.CSS.supports('-moz-mask-size', 'contain') ||
|
window.CSS.supports('-moz-mask-size', 'contain') ||
|
||||||
window.CSS.supports('-ms-mask-size', 'contain') ||
|
window.CSS.supports('-ms-mask-size', 'contain') ||
|
||||||
window.CSS.supports('-o-mask-size', 'contain')
|
window.CSS.supports('-o-mask-size', 'contain')
|
||||||
)
|
),
|
||||||
|
showingConfirmLogout: false
|
||||||
}),
|
}),
|
||||||
computed: {
|
computed: {
|
||||||
enableMask () { return this.supportsMask && this.$store.state.instance.logoMask },
|
enableMask () { return this.supportsMask && this.$store.state.instance.logoMask },
|
||||||
|
@ -92,7 +95,10 @@ export default {
|
||||||
hideSitename () { return this.$store.state.instance.hideSitename },
|
hideSitename () { return this.$store.state.instance.hideSitename },
|
||||||
logoLeft () { return this.$store.state.instance.logoLeft },
|
logoLeft () { return this.$store.state.instance.logoLeft },
|
||||||
currentUser () { return this.$store.state.users.currentUser },
|
currentUser () { return this.$store.state.users.currentUser },
|
||||||
privateMode () { return this.$store.state.instance.private }
|
privateMode () { return this.$store.state.instance.private },
|
||||||
|
shouldConfirmLogout () {
|
||||||
|
return this.$store.getters.mergedConfig.modalOnLogout
|
||||||
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
scrollToTop () {
|
scrollToTop () {
|
||||||
|
|
|
@ -54,17 +54,6 @@
|
||||||
:title="$t('nav.public_tl')"
|
:title="$t('nav.public_tl')"
|
||||||
/>
|
/>
|
||||||
</router-link>
|
</router-link>
|
||||||
<router-link
|
|
||||||
:to="{ name: 'public-external-timeline' }"
|
|
||||||
class="nav-icon"
|
|
||||||
>
|
|
||||||
<FAIcon
|
|
||||||
fixed-width
|
|
||||||
class="fa-scale-110 fa-old-padding"
|
|
||||||
icon="globe"
|
|
||||||
:title="$t('nav.twkn')"
|
|
||||||
/>
|
|
||||||
</router-link>
|
|
||||||
<router-link
|
<router-link
|
||||||
v-if="currentUser"
|
v-if="currentUser"
|
||||||
:to="{ name: 'bubble-timeline' }"
|
:to="{ name: 'bubble-timeline' }"
|
||||||
|
@ -77,6 +66,17 @@
|
||||||
:title="$t('nav.bubble_timeline')"
|
:title="$t('nav.bubble_timeline')"
|
||||||
/>
|
/>
|
||||||
</router-link>
|
</router-link>
|
||||||
|
<router-link
|
||||||
|
:to="{ name: 'public-external-timeline' }"
|
||||||
|
class="nav-icon"
|
||||||
|
>
|
||||||
|
<FAIcon
|
||||||
|
fixed-width
|
||||||
|
class="fa-scale-110 fa-old-padding"
|
||||||
|
icon="globe"
|
||||||
|
:title="$t('nav.twkn')"
|
||||||
|
/>
|
||||||
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<router-link
|
<router-link
|
||||||
|
@ -104,6 +104,7 @@
|
||||||
class="nav-items right"
|
class="nav-items right"
|
||||||
>
|
>
|
||||||
<router-link
|
<router-link
|
||||||
|
v-if="currentUser"
|
||||||
class="nav-icon"
|
class="nav-icon"
|
||||||
:to="{ name: 'interactions', params: { username: currentUser.screen_name } }"
|
:to="{ name: 'interactions', params: { username: currentUser.screen_name } }"
|
||||||
>
|
>
|
||||||
|
@ -166,6 +167,18 @@
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<teleport to="#modal">
|
||||||
|
<confirm-modal
|
||||||
|
v-if="showingConfirmLogout"
|
||||||
|
:title="$t('login.logout_confirm_title')"
|
||||||
|
:confirm-text="$t('login.logout_confirm_accept_button')"
|
||||||
|
:cancel-text="$t('login.logout_confirm_cancel_button')"
|
||||||
|
@accepted="doLogout"
|
||||||
|
@cancelled="hideConfirmLogout"
|
||||||
|
>
|
||||||
|
{{ $t('login.logout_confirm') }}
|
||||||
|
</confirm-modal>
|
||||||
|
</teleport>
|
||||||
</nav>
|
</nav>
|
||||||
</template>
|
</template>
|
||||||
<script src="./desktop_nav.js"></script>
|
<script src="./desktop_nav.js"></script>
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
right: 0;
|
right: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
background: rgba(27,31,35,.5);
|
background: rgba(27,31,35,.5);
|
||||||
z-index: 99;
|
z-index: 2000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,9 +51,10 @@
|
||||||
margin: 15vh auto;
|
margin: 15vh auto;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
z-index: 999;
|
z-index: 2001;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
display: block;
|
display: block;
|
||||||
|
width: max-content;
|
||||||
background-color: $fallback--bg;
|
background-color: $fallback--bg;
|
||||||
background-color: var(--bg, $fallback--bg);
|
background-color: var(--bg, $fallback--bg);
|
||||||
|
|
||||||
|
|
75
src/components/edit_status_modal/edit_status_modal.js
Normal file
75
src/components/edit_status_modal/edit_status_modal.js
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
import PostStatusForm from '../post_status_form/post_status_form.vue'
|
||||||
|
import Modal from '../modal/modal.vue'
|
||||||
|
import statusPosterService from '../../services/status_poster/status_poster.service.js'
|
||||||
|
import get from 'lodash/get'
|
||||||
|
|
||||||
|
const EditStatusModal = {
|
||||||
|
components: {
|
||||||
|
PostStatusForm,
|
||||||
|
Modal
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
resettingForm: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
isLoggedIn () {
|
||||||
|
return !!this.$store.state.users.currentUser
|
||||||
|
},
|
||||||
|
modalActivated () {
|
||||||
|
return this.$store.state.editStatus.modalActivated
|
||||||
|
},
|
||||||
|
isFormVisible () {
|
||||||
|
return this.isLoggedIn && !this.resettingForm && this.modalActivated
|
||||||
|
},
|
||||||
|
params () {
|
||||||
|
return this.$store.state.editStatus.params || {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
params (newVal, oldVal) {
|
||||||
|
if (get(newVal, 'statusId') !== get(oldVal, 'statusId')) {
|
||||||
|
this.resettingForm = true
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.resettingForm = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isFormVisible (val) {
|
||||||
|
if (val) {
|
||||||
|
this.$nextTick(() => this.$el && this.$el.querySelector('textarea').focus())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
doEditStatus ({ status, spoilerText, sensitive, media, contentType, poll }) {
|
||||||
|
const params = {
|
||||||
|
store: this.$store,
|
||||||
|
statusId: this.$store.state.editStatus.params.statusId,
|
||||||
|
status,
|
||||||
|
spoilerText,
|
||||||
|
sensitive,
|
||||||
|
poll,
|
||||||
|
media,
|
||||||
|
contentType
|
||||||
|
}
|
||||||
|
|
||||||
|
return statusPosterService.editStatus(params)
|
||||||
|
.then((data) => {
|
||||||
|
return data
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error('Error editing status', err)
|
||||||
|
return {
|
||||||
|
error: err.message
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
closeModal () {
|
||||||
|
this.$store.dispatch('closeEditStatusModal')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EditStatusModal
|
48
src/components/edit_status_modal/edit_status_modal.vue
Normal file
48
src/components/edit_status_modal/edit_status_modal.vue
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
<template>
|
||||||
|
<Modal
|
||||||
|
v-if="isFormVisible"
|
||||||
|
class="edit-form-modal-view"
|
||||||
|
@backdropClicked="closeModal"
|
||||||
|
>
|
||||||
|
<div class="edit-form-modal-panel panel">
|
||||||
|
<div class="panel-heading">
|
||||||
|
{{ $t('post_status.edit_status') }}
|
||||||
|
</div>
|
||||||
|
<PostStatusForm
|
||||||
|
class="panel-body"
|
||||||
|
v-bind="params"
|
||||||
|
@posted="closeModal"
|
||||||
|
:disablePolls="true"
|
||||||
|
:disableVisibilitySelector="true"
|
||||||
|
:post-handler="doEditStatus"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./edit_status_modal.js"></script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.modal-view.edit-form-modal-view {
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
.edit-form-modal-panel {
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-top: 25%;
|
||||||
|
margin-bottom: 2em;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 700px;
|
||||||
|
|
||||||
|
@media (orientation: landscape) {
|
||||||
|
margin-top: 8%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-bottom-left {
|
||||||
|
max-width: 6.5em;
|
||||||
|
|
||||||
|
.emoji-icon {
|
||||||
|
justify-content: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -46,14 +46,6 @@ const EmojiReactions = {
|
||||||
reactedWith (emoji) {
|
reactedWith (emoji) {
|
||||||
return this.status.emoji_reactions.find(r => r.name === emoji).me
|
return this.status.emoji_reactions.find(r => r.name === emoji).me
|
||||||
},
|
},
|
||||||
isLocalReaction (emojiUrl) {
|
|
||||||
if (!emojiUrl) return true
|
|
||||||
const reacted = this.accountsForEmoji[emojiUrl]
|
|
||||||
if (reacted.length === 0) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return reacted[0].is_local
|
|
||||||
},
|
|
||||||
fetchEmojiReactionsByIfMissing () {
|
fetchEmojiReactionsByIfMissing () {
|
||||||
const hasNoAccounts = this.status.emoji_reactions.find(r => !r.accounts)
|
const hasNoAccounts = this.status.emoji_reactions.find(r => !r.accounts)
|
||||||
if (hasNoAccounts) {
|
if (hasNoAccounts) {
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
<button
|
<button
|
||||||
class="emoji-reaction btn button-default"
|
class="emoji-reaction btn button-default"
|
||||||
:class="{ 'picked-reaction': reactedWith(reaction.name), 'not-clickable': !loggedIn }"
|
:class="{ 'picked-reaction': reactedWith(reaction.name), 'not-clickable': !loggedIn }"
|
||||||
:disabled="!isLocalReaction(reaction.url)"
|
|
||||||
@click="emojiOnClick(reaction.name, $event)"
|
@click="emojiOnClick(reaction.name, $event)"
|
||||||
@mouseenter="fetchEmojiReactionsByIfMissing()"
|
@mouseenter="fetchEmojiReactionsByIfMissing()"
|
||||||
>
|
>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import Popover from '../popover/popover.vue'
|
import Popover from '../popover/popover.vue'
|
||||||
|
import ConfirmModal from '../confirm_modal/confirm_modal.vue'
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import {
|
import {
|
||||||
faEllipsisH,
|
faEllipsisH,
|
||||||
|
@ -6,7 +7,8 @@ import {
|
||||||
faEyeSlash,
|
faEyeSlash,
|
||||||
faThumbtack,
|
faThumbtack,
|
||||||
faShareAlt,
|
faShareAlt,
|
||||||
faExternalLinkAlt
|
faExternalLinkAlt,
|
||||||
|
faHistory
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
import {
|
import {
|
||||||
faBookmark as faBookmarkReg,
|
faBookmark as faBookmarkReg,
|
||||||
|
@ -21,19 +23,49 @@ library.add(
|
||||||
faThumbtack,
|
faThumbtack,
|
||||||
faShareAlt,
|
faShareAlt,
|
||||||
faExternalLinkAlt,
|
faExternalLinkAlt,
|
||||||
faFlag
|
faFlag,
|
||||||
|
faHistory
|
||||||
)
|
)
|
||||||
|
|
||||||
const ExtraButtons = {
|
const ExtraButtons = {
|
||||||
props: ['status'],
|
props: ['status'],
|
||||||
components: { Popover },
|
components: {
|
||||||
|
Popover,
|
||||||
|
ConfirmModal
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
expanded: false,
|
||||||
|
showingDeleteDialog: false
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
deleteStatus () {
|
deleteStatus () {
|
||||||
const confirmed = window.confirm(this.$t('status.delete_confirm'))
|
if (this.shouldConfirmDelete) {
|
||||||
if (confirmed) {
|
this.showDeleteStatusConfirmDialog()
|
||||||
this.$store.dispatch('deleteStatus', { id: this.status.id })
|
} else {
|
||||||
|
this.doDeleteStatus()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
doDeleteStatus () {
|
||||||
|
this.$store.dispatch('deleteStatus', { id: this.status.id })
|
||||||
|
this.hideDeleteStatusConfirmDialog()
|
||||||
|
},
|
||||||
|
showDeleteStatusConfirmDialog () {
|
||||||
|
this.showingDeleteDialog = true
|
||||||
|
},
|
||||||
|
hideDeleteStatusConfirmDialog () {
|
||||||
|
this.showingDeleteDialog = false
|
||||||
|
},
|
||||||
|
translateStatus () {
|
||||||
|
if (this.noTranslationTargetSet) {
|
||||||
|
this.$store.dispatch('pushGlobalNotice', { messageKey: 'toast.no_translation_target_set', level: 'info' })
|
||||||
|
}
|
||||||
|
const translateTo = this.$store.getters.mergedConfig.translationLanguage || this.$store.state.instance.interfaceLanguage
|
||||||
|
this.$store.dispatch('translateStatus', { id: this.status.id, language: translateTo })
|
||||||
|
.then(() => this.$emit('onSuccess'))
|
||||||
|
.catch(err => this.$emit('onError', err.error.error))
|
||||||
|
},
|
||||||
pinStatus () {
|
pinStatus () {
|
||||||
this.$store.dispatch('pinStatus', this.status.id)
|
this.$store.dispatch('pinStatus', this.status.id)
|
||||||
.then(() => this.$emit('onSuccess'))
|
.then(() => this.$emit('onSuccess'))
|
||||||
|
@ -71,6 +103,25 @@ const ExtraButtons = {
|
||||||
},
|
},
|
||||||
reportStatus () {
|
reportStatus () {
|
||||||
this.$store.dispatch('openUserReportingModal', { userId: this.status.user.id, statusIds: [this.status.id] })
|
this.$store.dispatch('openUserReportingModal', { userId: this.status.user.id, statusIds: [this.status.id] })
|
||||||
|
},
|
||||||
|
editStatus () {
|
||||||
|
this.$store.dispatch('fetchStatusSource', { id: this.status.id })
|
||||||
|
.then(data => this.$store.dispatch('openEditStatusModal', {
|
||||||
|
statusId: this.status.id,
|
||||||
|
subject: data.spoiler_text,
|
||||||
|
statusText: data.text,
|
||||||
|
statusIsSensitive: this.status.nsfw,
|
||||||
|
statusPoll: this.status.poll,
|
||||||
|
statusFiles: [...this.status.attachments],
|
||||||
|
visibility: this.status.visibility,
|
||||||
|
statusContentType: data.content_type
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
showStatusHistory () {
|
||||||
|
const originalStatus = { ...this.status }
|
||||||
|
const stripFieldsList = ['attachments', 'created_at', 'emojis', 'text', 'raw_html', 'nsfw', 'poll', 'summary', 'summary_raw_html']
|
||||||
|
stripFieldsList.forEach(p => delete originalStatus[p])
|
||||||
|
this.$store.dispatch('openStatusHistoryModal', originalStatus)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -89,9 +140,26 @@ const ExtraButtons = {
|
||||||
canMute () {
|
canMute () {
|
||||||
return !!this.currentUser
|
return !!this.currentUser
|
||||||
},
|
},
|
||||||
|
canTranslate () {
|
||||||
|
return this.$store.state.instance.translationEnabled === true
|
||||||
|
},
|
||||||
|
noTranslationTargetSet () {
|
||||||
|
return this.$store.getters.mergedConfig.translationLanguage === undefined
|
||||||
|
},
|
||||||
statusLink () {
|
statusLink () {
|
||||||
|
if (this.status.is_local) {
|
||||||
return `${this.$store.state.instance.server}${this.$router.resolve({ name: 'conversation', params: { id: this.status.id } }).href}`
|
return `${this.$store.state.instance.server}${this.$router.resolve({ name: 'conversation', params: { id: this.status.id } }).href}`
|
||||||
|
} else {
|
||||||
|
return this.status.external_url
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
shouldConfirmDelete () {
|
||||||
|
return this.$store.getters.mergedConfig.modalOnDelete
|
||||||
|
},
|
||||||
|
isEdited () {
|
||||||
|
return this.status.edited_at !== null
|
||||||
|
},
|
||||||
|
editingAvailable () { return this.$store.state.instance.editingAvailable }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,6 +73,28 @@
|
||||||
icon="bookmark"
|
icon="bookmark"
|
||||||
/><span>{{ $t("status.unbookmark") }}</span>
|
/><span>{{ $t("status.unbookmark") }}</span>
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
v-if="ownStatus && editingAvailable"
|
||||||
|
class="button-default dropdown-item dropdown-item-icon"
|
||||||
|
@click.prevent="editStatus"
|
||||||
|
@click="close"
|
||||||
|
>
|
||||||
|
<FAIcon
|
||||||
|
fixed-width
|
||||||
|
icon="pen"
|
||||||
|
/><span>{{ $t("status.edit") }}</span>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
v-if="isEdited && editingAvailable"
|
||||||
|
class="button-default dropdown-item dropdown-item-icon"
|
||||||
|
@click.prevent="showStatusHistory"
|
||||||
|
@click="close"
|
||||||
|
>
|
||||||
|
<FAIcon
|
||||||
|
fixed-width
|
||||||
|
icon="history"
|
||||||
|
/><span>{{ $t("status.edit_history") }}</span>
|
||||||
|
</button>
|
||||||
<button
|
<button
|
||||||
v-if="canDelete"
|
v-if="canDelete"
|
||||||
class="button-default dropdown-item dropdown-item-icon"
|
class="button-default dropdown-item dropdown-item-icon"
|
||||||
|
@ -116,6 +138,27 @@
|
||||||
:icon="['far', 'flag']"
|
:icon="['far', 'flag']"
|
||||||
/><span>{{ $t("user_card.report") }}</span>
|
/><span>{{ $t("user_card.report") }}</span>
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
v-if="canTranslate"
|
||||||
|
class="button-default dropdown-item dropdown-item-icon"
|
||||||
|
@click.prevent="translateStatus"
|
||||||
|
@click="close"
|
||||||
|
>
|
||||||
|
<FAIcon
|
||||||
|
fixed-width
|
||||||
|
icon="globe"
|
||||||
|
/><span>{{ $t("status.translate") }}</span>
|
||||||
|
|
||||||
|
<template v-if="noTranslationTargetSet">
|
||||||
|
<span class="dropdown-item-icon__badge warning">
|
||||||
|
<FAIcon
|
||||||
|
fixed-width
|
||||||
|
icon="exclamation-triangle"
|
||||||
|
name="test"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:trigger>
|
<template v-slot:trigger>
|
||||||
|
@ -125,6 +168,18 @@
|
||||||
icon="ellipsis-h"
|
icon="ellipsis-h"
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
|
<teleport to="#modal">
|
||||||
|
<ConfirmModal
|
||||||
|
v-if="showingDeleteDialog"
|
||||||
|
:title="$t('status.delete_confirm_title')"
|
||||||
|
:cancel-text="$t('status.delete_confirm_cancel_button')"
|
||||||
|
:confirm-text="$t('status.delete_confirm_accept_button')"
|
||||||
|
@cancelled="hideDeleteStatusConfirmDialog"
|
||||||
|
@accepted="doDeleteStatus"
|
||||||
|
>
|
||||||
|
{{ $t('status.delete_confirm') }}
|
||||||
|
</ConfirmModal>
|
||||||
|
</teleport>
|
||||||
</template>
|
</template>
|
||||||
</Popover>
|
</Popover>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,12 +1,20 @@
|
||||||
|
import ConfirmModal from '../confirm_modal/confirm_modal.vue'
|
||||||
import { requestFollow, requestUnfollow } from '../../services/follow_manipulate/follow_manipulate'
|
import { requestFollow, requestUnfollow } from '../../services/follow_manipulate/follow_manipulate'
|
||||||
export default {
|
export default {
|
||||||
props: ['relationship', 'user', 'labelFollowing', 'buttonClass'],
|
props: ['relationship', 'user', 'labelFollowing', 'buttonClass'],
|
||||||
|
components: {
|
||||||
|
ConfirmModal
|
||||||
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
inProgress: false
|
inProgress: false,
|
||||||
|
showingConfirmUnfollow: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
shouldConfirmUnfollow () {
|
||||||
|
return this.$store.getters.mergedConfig.modalOnUnfollow
|
||||||
|
},
|
||||||
isPressed () {
|
isPressed () {
|
||||||
return this.inProgress || this.relationship.following
|
return this.inProgress || this.relationship.following
|
||||||
},
|
},
|
||||||
|
@ -35,6 +43,12 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
showConfirmUnfollow () {
|
||||||
|
this.showingConfirmUnfollow = true
|
||||||
|
},
|
||||||
|
hideConfirmUnfollow () {
|
||||||
|
this.showingConfirmUnfollow = false
|
||||||
|
},
|
||||||
onClick () {
|
onClick () {
|
||||||
this.relationship.following || this.relationship.requested ? this.unfollow() : this.follow()
|
this.relationship.following || this.relationship.requested ? this.unfollow() : this.follow()
|
||||||
},
|
},
|
||||||
|
@ -45,12 +59,21 @@ export default {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
unfollow () {
|
unfollow () {
|
||||||
|
if (this.shouldConfirmUnfollow) {
|
||||||
|
this.showConfirmUnfollow()
|
||||||
|
} else {
|
||||||
|
this.doUnfollow()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
doUnfollow () {
|
||||||
const store = this.$store
|
const store = this.$store
|
||||||
this.inProgress = true
|
this.inProgress = true
|
||||||
requestUnfollow(this.relationship.id, store).then(() => {
|
requestUnfollow(this.relationship.id, store).then(() => {
|
||||||
this.inProgress = false
|
this.inProgress = false
|
||||||
store.commit('removeStatus', { timeline: 'friends', userId: this.relationship.id })
|
store.commit('removeStatus', { timeline: 'friends', userId: this.relationship.id })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
this.hideConfirmUnfollow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,27 @@
|
||||||
@click="onClick"
|
@click="onClick"
|
||||||
>
|
>
|
||||||
{{ label }}
|
{{ label }}
|
||||||
|
<teleport to="#modal">
|
||||||
|
<confirm-modal
|
||||||
|
v-if="showingConfirmUnfollow"
|
||||||
|
:title="$t('user_card.unfollow_confirm_title')"
|
||||||
|
:confirm-text="$t('user_card.unfollow_confirm_accept_button')"
|
||||||
|
:cancel-text="$t('user_card.unfollow_confirm_cancel_button')"
|
||||||
|
@accepted="doUnfollow"
|
||||||
|
@cancelled="hideConfirmUnfollow"
|
||||||
|
>
|
||||||
|
<i18n-t
|
||||||
|
keypath="user_card.unfollow_confirm"
|
||||||
|
tag="span"
|
||||||
|
>
|
||||||
|
<template #user>
|
||||||
|
<span
|
||||||
|
v-text="user.screen_name_ui"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</i18n-t>
|
||||||
|
</confirm-modal>
|
||||||
|
</teleport>
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,18 @@
|
||||||
import BasicUserCard from '../basic_user_card/basic_user_card.vue'
|
import BasicUserCard from '../basic_user_card/basic_user_card.vue'
|
||||||
|
import ConfirmModal from '../confirm_modal/confirm_modal.vue'
|
||||||
import { notificationsFromStore } from '../../services/notification_utils/notification_utils.js'
|
import { notificationsFromStore } from '../../services/notification_utils/notification_utils.js'
|
||||||
|
|
||||||
const FollowRequestCard = {
|
const FollowRequestCard = {
|
||||||
props: ['user'],
|
props: ['user'],
|
||||||
components: {
|
components: {
|
||||||
BasicUserCard
|
BasicUserCard,
|
||||||
|
ConfirmModal
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
showingApproveConfirmDialog: false,
|
||||||
|
showingDenyConfirmDialog: false
|
||||||
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
findFollowRequestNotificationId () {
|
findFollowRequestNotificationId () {
|
||||||
|
@ -13,7 +21,26 @@ const FollowRequestCard = {
|
||||||
)
|
)
|
||||||
return notif && notif.id
|
return notif && notif.id
|
||||||
},
|
},
|
||||||
|
showApproveConfirmDialog () {
|
||||||
|
this.showingApproveConfirmDialog = true
|
||||||
|
},
|
||||||
|
hideApproveConfirmDialog () {
|
||||||
|
this.showingApproveConfirmDialog = false
|
||||||
|
},
|
||||||
|
showDenyConfirmDialog () {
|
||||||
|
this.showingDenyConfirmDialog = true
|
||||||
|
},
|
||||||
|
hideDenyConfirmDialog () {
|
||||||
|
this.showingDenyConfirmDialog = false
|
||||||
|
},
|
||||||
approveUser () {
|
approveUser () {
|
||||||
|
if (this.shouldConfirmApprove) {
|
||||||
|
this.showApproveConfirmDialog()
|
||||||
|
} else {
|
||||||
|
this.doApprove()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
doApprove () {
|
||||||
this.$store.state.api.backendInteractor.approveUser({ id: this.user.id })
|
this.$store.state.api.backendInteractor.approveUser({ id: this.user.id })
|
||||||
this.$store.dispatch('removeFollowRequest', this.user)
|
this.$store.dispatch('removeFollowRequest', this.user)
|
||||||
|
|
||||||
|
@ -25,14 +52,34 @@ const FollowRequestCard = {
|
||||||
notification.type = 'follow'
|
notification.type = 'follow'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
this.hideApproveConfirmDialog()
|
||||||
},
|
},
|
||||||
denyUser () {
|
denyUser () {
|
||||||
|
if (this.shouldConfirmDeny) {
|
||||||
|
this.showDenyConfirmDialog()
|
||||||
|
} else {
|
||||||
|
this.doDeny()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
doDeny () {
|
||||||
const notifId = this.findFollowRequestNotificationId()
|
const notifId = this.findFollowRequestNotificationId()
|
||||||
this.$store.state.api.backendInteractor.denyUser({ id: this.user.id })
|
this.$store.state.api.backendInteractor.denyUser({ id: this.user.id })
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.$store.dispatch('dismissNotificationLocal', { id: notifId })
|
this.$store.dispatch('dismissNotificationLocal', { id: notifId })
|
||||||
this.$store.dispatch('removeFollowRequest', this.user)
|
this.$store.dispatch('removeFollowRequest', this.user)
|
||||||
})
|
})
|
||||||
|
this.hideDenyConfirmDialog()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
mergedConfig () {
|
||||||
|
return this.$store.getters.mergedConfig
|
||||||
|
},
|
||||||
|
shouldConfirmApprove () {
|
||||||
|
return this.mergedConfig.modalOnApproveFollow
|
||||||
|
},
|
||||||
|
shouldConfirmDeny () {
|
||||||
|
return this.mergedConfig.modalOnDenyFollow
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,28 @@
|
||||||
{{ $t('user_card.deny') }}
|
{{ $t('user_card.deny') }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
<teleport to="#modal">
|
||||||
|
<confirm-modal
|
||||||
|
v-if="showingApproveConfirmDialog"
|
||||||
|
:title="$t('user_card.approve_confirm_title')"
|
||||||
|
:confirm-text="$t('user_card.approve_confirm_accept_button')"
|
||||||
|
:cancel-text="$t('user_card.approve_confirm_cancel_button')"
|
||||||
|
@accepted="doApprove"
|
||||||
|
@cancelled="hideApproveConfirmDialog"
|
||||||
|
>
|
||||||
|
{{ $t('user_card.approve_confirm', { user: user.screen_name_ui }) }}
|
||||||
|
</confirm-modal>
|
||||||
|
<confirm-modal
|
||||||
|
v-if="showingDenyConfirmDialog"
|
||||||
|
:title="$t('user_card.deny_confirm_title')"
|
||||||
|
:confirm-text="$t('user_card.deny_confirm_accept_button')"
|
||||||
|
:cancel-text="$t('user_card.deny_confirm_cancel_button')"
|
||||||
|
@accepted="doDeny"
|
||||||
|
@cancelled="hideDenyConfirmDialog"
|
||||||
|
>
|
||||||
|
{{ $t('user_card.deny_confirm', { user: user.screen_name_ui }) }}
|
||||||
|
</confirm-modal>
|
||||||
|
</teleport>
|
||||||
</basic-user-card>
|
</basic-user-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
|
<FAIcon
|
||||||
|
v-if="globeIcon"
|
||||||
|
icon="globe"
|
||||||
|
/>
|
||||||
|
{{ ' ' }}
|
||||||
<label for="interface-language-switcher">
|
<label for="interface-language-switcher">
|
||||||
{{ promptText }}
|
{{ promptText }}
|
||||||
</label>
|
</label>
|
||||||
|
@ -39,6 +44,10 @@ export default {
|
||||||
setLanguage: {
|
setLanguage: {
|
||||||
type: Function,
|
type: Function,
|
||||||
required: true
|
required: true
|
||||||
|
},
|
||||||
|
globeIcon: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
import SideDrawer from '../side_drawer/side_drawer.vue'
|
import SideDrawer from '../side_drawer/side_drawer.vue'
|
||||||
import Notifications from '../notifications/notifications.vue'
|
import Notifications from '../notifications/notifications.vue'
|
||||||
|
import ConfirmModal from '../confirm_modal/confirm_modal.vue'
|
||||||
import { unseenNotificationsFromStore } from '../../services/notification_utils/notification_utils'
|
import { unseenNotificationsFromStore } from '../../services/notification_utils/notification_utils'
|
||||||
import GestureService from '../../services/gesture_service/gesture_service'
|
import GestureService from '../../services/gesture_service/gesture_service'
|
||||||
|
import { mapGetters } from 'vuex'
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import {
|
import {
|
||||||
faTimes,
|
faTimes,
|
||||||
|
@ -18,11 +20,13 @@ library.add(
|
||||||
const MobileNav = {
|
const MobileNav = {
|
||||||
components: {
|
components: {
|
||||||
SideDrawer,
|
SideDrawer,
|
||||||
Notifications
|
Notifications,
|
||||||
|
ConfirmModal
|
||||||
},
|
},
|
||||||
data: () => ({
|
data: () => ({
|
||||||
notificationsCloseGesture: undefined,
|
notificationsCloseGesture: undefined,
|
||||||
notificationsOpen: false
|
notificationsOpen: false,
|
||||||
|
showingConfirmLogout: false
|
||||||
}),
|
}),
|
||||||
created () {
|
created () {
|
||||||
this.notificationsCloseGesture = GestureService.swipeGesture(
|
this.notificationsCloseGesture = GestureService.swipeGesture(
|
||||||
|
@ -47,7 +51,11 @@ const MobileNav = {
|
||||||
hideSiteName () {
|
hideSiteName () {
|
||||||
return this.mergedConfig.hideSiteName
|
return this.mergedConfig.hideSiteName
|
||||||
},
|
},
|
||||||
sitename () { return this.$store.state.instance.name }
|
sitename () { return this.$store.state.instance.name },
|
||||||
|
shouldConfirmLogout () {
|
||||||
|
return this.$store.getters.mergedConfig.modalOnLogout
|
||||||
|
},
|
||||||
|
...mapGetters(['unreadChatCount'])
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
toggleMobileSidebar () {
|
toggleMobileSidebar () {
|
||||||
|
@ -73,9 +81,23 @@ const MobileNav = {
|
||||||
scrollToTop () {
|
scrollToTop () {
|
||||||
window.scrollTo(0, 0)
|
window.scrollTo(0, 0)
|
||||||
},
|
},
|
||||||
|
showConfirmLogout () {
|
||||||
|
this.showingConfirmLogout = true
|
||||||
|
},
|
||||||
|
hideConfirmLogout () {
|
||||||
|
this.showingConfirmLogout = false
|
||||||
|
},
|
||||||
logout () {
|
logout () {
|
||||||
|
if (!this.shouldConfirmLogout) {
|
||||||
|
this.doLogout()
|
||||||
|
} else {
|
||||||
|
this.showConfirmLogout()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
doLogout () {
|
||||||
this.$router.replace('/main/public')
|
this.$router.replace('/main/public')
|
||||||
this.$store.dispatch('logout')
|
this.$store.dispatch('logout')
|
||||||
|
this.hideConfirmLogout()
|
||||||
},
|
},
|
||||||
markNotificationsAsSeen () {
|
markNotificationsAsSeen () {
|
||||||
// this.$refs.notifications.markAsSeen()
|
// this.$refs.notifications.markAsSeen()
|
||||||
|
|
|
@ -76,6 +76,18 @@
|
||||||
ref="sideDrawer"
|
ref="sideDrawer"
|
||||||
:logout="logout"
|
:logout="logout"
|
||||||
/>
|
/>
|
||||||
|
<teleport to="#modal">
|
||||||
|
<confirm-modal
|
||||||
|
v-if="showingConfirmLogout"
|
||||||
|
:title="$t('login.logout_confirm_title')"
|
||||||
|
:confirm-text="$t('login.logout_confirm_accept_button')"
|
||||||
|
:cancel-text="$t('login.logout_confirm_cancel_button')"
|
||||||
|
@accepted="doLogout"
|
||||||
|
@cancelled="hideConfirmLogout"
|
||||||
|
>
|
||||||
|
{{ $t('login.logout_confirm') }}
|
||||||
|
</confirm-modal>
|
||||||
|
</teleport>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -206,6 +218,14 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.confirm-modal.dark-overlay {
|
||||||
|
&::before {
|
||||||
|
z-index: 3000;
|
||||||
|
}
|
||||||
|
.dialog-modal.panel {
|
||||||
|
z-index: 3001;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -13,13 +13,13 @@
|
||||||
<span v-if="user.is_local">
|
<span v-if="user.is_local">
|
||||||
<button
|
<button
|
||||||
class="button-default dropdown-item"
|
class="button-default dropdown-item"
|
||||||
@click="toggleRight("admin")"
|
@click="toggleRight('admin')"
|
||||||
>
|
>
|
||||||
{{ $t(!!user.rights.admin ? 'user_card.admin_menu.revoke_admin' : 'user_card.admin_menu.grant_admin') }}
|
{{ $t(!!user.rights.admin ? 'user_card.admin_menu.revoke_admin' : 'user_card.admin_menu.grant_admin') }}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="button-default dropdown-item"
|
class="button-default dropdown-item"
|
||||||
@click="toggleRight("moderator")"
|
@click="toggleRight('moderator')"
|
||||||
>
|
>
|
||||||
{{ $t(!!user.rights.moderator ? 'user_card.admin_menu.revoke_moderator' : 'user_card.admin_menu.grant_moderator') }}
|
{{ $t(!!user.rights.moderator ? 'user_card.admin_menu.revoke_moderator' : 'user_card.admin_menu.grant_moderator') }}
|
||||||
</button>
|
</button>
|
||||||
|
@ -167,6 +167,7 @@
|
||||||
|
|
||||||
.moderation-tools-popover {
|
.moderation-tools-popover {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
z-index: 999;
|
||||||
.trigger {
|
.trigger {
|
||||||
display: flex !important;
|
display: flex !important;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
v-if="federationPolicy"
|
v-if="hasInstanceSpecificPolicies"
|
||||||
class="mrf-transparency-panel"
|
class="mrf-transparency-panel"
|
||||||
>
|
>
|
||||||
<div class="panel panel-default base01-background">
|
<div class="panel panel-default base01-background">
|
||||||
|
|
|
@ -5,6 +5,7 @@ import UserAvatar from '../user_avatar/user_avatar.vue'
|
||||||
import UserCard from '../user_card/user_card.vue'
|
import UserCard from '../user_card/user_card.vue'
|
||||||
import Timeago from '../timeago/timeago.vue'
|
import Timeago from '../timeago/timeago.vue'
|
||||||
import RichContent from 'src/components/rich_content/rich_content.jsx'
|
import RichContent from 'src/components/rich_content/rich_content.jsx'
|
||||||
|
import ConfirmModal from '../confirm_modal/confirm_modal.vue'
|
||||||
import { isStatusNotification } from '../../services/notification_utils/notification_utils.js'
|
import { isStatusNotification } from '../../services/notification_utils/notification_utils.js'
|
||||||
import { highlightClass, highlightStyle } from '../../services/user_highlighter/user_highlighter.js'
|
import { highlightClass, highlightStyle } from '../../services/user_highlighter/user_highlighter.js'
|
||||||
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'
|
||||||
|
@ -36,7 +37,9 @@ const Notification = {
|
||||||
return {
|
return {
|
||||||
userExpanded: false,
|
userExpanded: false,
|
||||||
betterShadow: this.$store.state.interface.browserSupport.cssFilter,
|
betterShadow: this.$store.state.interface.browserSupport.cssFilter,
|
||||||
unmuted: false
|
unmuted: false,
|
||||||
|
showingApproveConfirmDialog: false,
|
||||||
|
showingDenyConfirmDialog: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
props: [ 'notification' ],
|
props: [ 'notification' ],
|
||||||
|
@ -46,7 +49,8 @@ const Notification = {
|
||||||
UserCard,
|
UserCard,
|
||||||
Timeago,
|
Timeago,
|
||||||
Status,
|
Status,
|
||||||
RichContent
|
RichContent,
|
||||||
|
ConfirmModal
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
toggleUserExpanded () {
|
toggleUserExpanded () {
|
||||||
|
@ -61,7 +65,26 @@ const Notification = {
|
||||||
toggleMute () {
|
toggleMute () {
|
||||||
this.unmuted = !this.unmuted
|
this.unmuted = !this.unmuted
|
||||||
},
|
},
|
||||||
|
showApproveConfirmDialog () {
|
||||||
|
this.showingApproveConfirmDialog = true
|
||||||
|
},
|
||||||
|
hideApproveConfirmDialog () {
|
||||||
|
this.showingApproveConfirmDialog = false
|
||||||
|
},
|
||||||
|
showDenyConfirmDialog () {
|
||||||
|
this.showingDenyConfirmDialog = true
|
||||||
|
},
|
||||||
|
hideDenyConfirmDialog () {
|
||||||
|
this.showingDenyConfirmDialog = false
|
||||||
|
},
|
||||||
approveUser () {
|
approveUser () {
|
||||||
|
if (this.shouldConfirmApprove) {
|
||||||
|
this.showApproveConfirmDialog()
|
||||||
|
} else {
|
||||||
|
this.doApprove()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
doApprove () {
|
||||||
this.$store.state.api.backendInteractor.approveUser({ id: this.user.id })
|
this.$store.state.api.backendInteractor.approveUser({ id: this.user.id })
|
||||||
this.$store.dispatch('removeFollowRequest', this.user)
|
this.$store.dispatch('removeFollowRequest', this.user)
|
||||||
this.$store.dispatch('markSingleNotificationAsSeen', { id: this.notification.id })
|
this.$store.dispatch('markSingleNotificationAsSeen', { id: this.notification.id })
|
||||||
|
@ -71,13 +94,22 @@ const Notification = {
|
||||||
notification.type = 'follow'
|
notification.type = 'follow'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
this.hideApproveConfirmDialog()
|
||||||
},
|
},
|
||||||
denyUser () {
|
denyUser () {
|
||||||
|
if (this.shouldConfirmDeny) {
|
||||||
|
this.showDenyConfirmDialog()
|
||||||
|
} else {
|
||||||
|
this.doDeny()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
doDeny () {
|
||||||
this.$store.state.api.backendInteractor.denyUser({ id: this.user.id })
|
this.$store.state.api.backendInteractor.denyUser({ id: this.user.id })
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.$store.dispatch('dismissNotificationLocal', { id: this.notification.id })
|
this.$store.dispatch('dismissNotificationLocal', { id: this.notification.id })
|
||||||
this.$store.dispatch('removeFollowRequest', this.user)
|
this.$store.dispatch('removeFollowRequest', this.user)
|
||||||
})
|
})
|
||||||
|
this.hideDenyConfirmDialog()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -107,6 +139,15 @@ const Notification = {
|
||||||
isStatusNotification () {
|
isStatusNotification () {
|
||||||
return isStatusNotification(this.notification.type)
|
return isStatusNotification(this.notification.type)
|
||||||
},
|
},
|
||||||
|
mergedConfig () {
|
||||||
|
return this.$store.getters.mergedConfig
|
||||||
|
},
|
||||||
|
shouldConfirmApprove () {
|
||||||
|
return this.mergedConfig.modalOnApproveFollow
|
||||||
|
},
|
||||||
|
shouldConfirmDeny () {
|
||||||
|
return this.mergedConfig.modalOnDenyFollow
|
||||||
|
},
|
||||||
...mapState({
|
...mapState({
|
||||||
currentUser: state => state.users.currentUser
|
currentUser: state => state.users.currentUser
|
||||||
})
|
})
|
||||||
|
|
|
@ -231,6 +231,28 @@
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<teleport to="#modal">
|
||||||
|
<confirm-modal
|
||||||
|
v-if="showingApproveConfirmDialog"
|
||||||
|
:title="$t('user_card.approve_confirm_title')"
|
||||||
|
:confirm-text="$t('user_card.approve_confirm_accept_button')"
|
||||||
|
:cancel-text="$t('user_card.approve_confirm_cancel_button')"
|
||||||
|
@accepted="doApprove"
|
||||||
|
@cancelled="hideApproveConfirmDialog"
|
||||||
|
>
|
||||||
|
{{ $t('user_card.approve_confirm', { user: user.screen_name_ui }) }}
|
||||||
|
</confirm-modal>
|
||||||
|
<confirm-modal
|
||||||
|
v-if="showingDenyConfirmDialog"
|
||||||
|
:title="$t('user_card.deny_confirm_title')"
|
||||||
|
:confirm-text="$t('user_card.deny_confirm_accept_button')"
|
||||||
|
:cancel-text="$t('user_card.deny_confirm_cancel_button')"
|
||||||
|
@accepted="doDeny"
|
||||||
|
@cancelled="hideDenyConfirmDialog"
|
||||||
|
>
|
||||||
|
{{ $t('user_card.deny_confirm', { user: user.screen_name_ui }) }}
|
||||||
|
</confirm-modal>
|
||||||
|
</teleport>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,14 @@ const pxStringToNumber = (str) => {
|
||||||
|
|
||||||
const PostStatusForm = {
|
const PostStatusForm = {
|
||||||
props: [
|
props: [
|
||||||
|
'statusId',
|
||||||
|
'statusText',
|
||||||
|
'statusIsSensitive',
|
||||||
|
'statusPoll',
|
||||||
|
'statusFiles',
|
||||||
|
'statusMediaDescriptions',
|
||||||
|
'statusScope',
|
||||||
|
'statusContentType',
|
||||||
'replyTo',
|
'replyTo',
|
||||||
'quoteId',
|
'quoteId',
|
||||||
'repliedUser',
|
'repliedUser',
|
||||||
|
@ -63,6 +71,7 @@ const PostStatusForm = {
|
||||||
'subject',
|
'subject',
|
||||||
'disableSubject',
|
'disableSubject',
|
||||||
'disableScopeSelector',
|
'disableScopeSelector',
|
||||||
|
'disableVisibilitySelector',
|
||||||
'disableNotice',
|
'disableNotice',
|
||||||
'disableLockWarning',
|
'disableLockWarning',
|
||||||
'disablePolls',
|
'disablePolls',
|
||||||
|
@ -120,23 +129,40 @@ const PostStatusForm = {
|
||||||
|
|
||||||
const { postContentType: contentType, sensitiveByDefault, sensitiveIfSubject } = this.$store.getters.mergedConfig
|
const { postContentType: contentType, sensitiveByDefault, sensitiveIfSubject } = this.$store.getters.mergedConfig
|
||||||
|
|
||||||
return {
|
let statusParams = {
|
||||||
dropFiles: [],
|
|
||||||
uploadingFiles: false,
|
|
||||||
error: null,
|
|
||||||
posting: false,
|
|
||||||
highlighted: 0,
|
|
||||||
newStatus: {
|
|
||||||
spoilerText: this.subject || '',
|
spoilerText: this.subject || '',
|
||||||
status: statusText,
|
status: statusText,
|
||||||
sensitiveIfSubject,
|
sensitiveByDefault,
|
||||||
nsfw: !!sensitiveByDefault,
|
nsfw: !!sensitiveByDefault,
|
||||||
files: [],
|
files: [],
|
||||||
poll: {},
|
poll: {},
|
||||||
mediaDescriptions: {},
|
mediaDescriptions: {},
|
||||||
visibility: this.suggestedVisibility(),
|
visibility: this.suggestedVisibility(),
|
||||||
contentType
|
contentType
|
||||||
},
|
}
|
||||||
|
|
||||||
|
if (this.statusId) {
|
||||||
|
const statusContentType = this.statusContentType || contentType
|
||||||
|
statusParams = {
|
||||||
|
spoilerText: this.subject || '',
|
||||||
|
status: this.statusText || '',
|
||||||
|
sensitiveIfSubject,
|
||||||
|
nsfw: this.statusIsSensitive || !!sensitiveByDefault,
|
||||||
|
files: this.statusFiles || [],
|
||||||
|
poll: this.statusPoll || {},
|
||||||
|
mediaDescriptions: this.statusMediaDescriptions || {},
|
||||||
|
visibility: this.statusScope || this.suggestedVisibility(),
|
||||||
|
contentType: statusContentType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
dropFiles: [],
|
||||||
|
uploadingFiles: false,
|
||||||
|
error: null,
|
||||||
|
posting: false,
|
||||||
|
highlighted: 0,
|
||||||
|
newStatus: statusParams,
|
||||||
caret: 0,
|
caret: 0,
|
||||||
pollFormVisible: false,
|
pollFormVisible: false,
|
||||||
showDropIcon: 'hide',
|
showDropIcon: 'hide',
|
||||||
|
@ -232,6 +258,9 @@ const PostStatusForm = {
|
||||||
uploadFileLimitReached () {
|
uploadFileLimitReached () {
|
||||||
return this.newStatus.files.length >= this.fileLimit
|
return this.newStatus.files.length >= this.fileLimit
|
||||||
},
|
},
|
||||||
|
isEdit () {
|
||||||
|
return typeof this.statusId !== 'undefined' && this.statusId.trim() !== ''
|
||||||
|
},
|
||||||
...mapGetters(['mergedConfig']),
|
...mapGetters(['mergedConfig']),
|
||||||
...mapState({
|
...mapState({
|
||||||
mobileLayout: state => state.interface.mobileLayout
|
mobileLayout: state => state.interface.mobileLayout
|
||||||
|
|
|
@ -66,6 +66,13 @@
|
||||||
<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
|
||||||
|
v-if="isEdit"
|
||||||
|
class="visibility-notice edit-warning"
|
||||||
|
>
|
||||||
|
<p>{{ $t('post_status.edit_remote_warning') }}</p>
|
||||||
|
<p>{{ $t('post_status.edit_unsupported_warning') }}</p>
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="!disablePreview"
|
v-if="!disablePreview"
|
||||||
class="preview-heading faint"
|
class="preview-heading faint"
|
||||||
|
@ -180,6 +187,7 @@
|
||||||
class="visibility-tray"
|
class="visibility-tray"
|
||||||
>
|
>
|
||||||
<scope-selector
|
<scope-selector
|
||||||
|
v-if="!disableVisibilitySelector"
|
||||||
:show-all="showAllScopes"
|
:show-all="showAllScopes"
|
||||||
:user-default="userDefaultScope"
|
:user-default="userDefaultScope"
|
||||||
:original-scope="copyMessageScope"
|
:original-scope="copyMessageScope"
|
||||||
|
@ -420,6 +428,16 @@
|
||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.visibility-notice.edit-warning {
|
||||||
|
> :first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
> :last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.media-upload-icon, .poll-icon, .emoji-icon {
|
.media-upload-icon, .poll-icon, .emoji-icon {
|
||||||
font-size: 1.85em;
|
font-size: 1.85em;
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import ConfirmModal from '../confirm_modal/confirm_modal.vue'
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import { faRetweet } from '@fortawesome/free-solid-svg-icons'
|
import { faRetweet } from '@fortawesome/free-solid-svg-icons'
|
||||||
|
|
||||||
|
@ -5,13 +6,24 @@ library.add(faRetweet)
|
||||||
|
|
||||||
const RetweetButton = {
|
const RetweetButton = {
|
||||||
props: ['status', 'loggedIn', 'visibility'],
|
props: ['status', 'loggedIn', 'visibility'],
|
||||||
|
components: {
|
||||||
|
ConfirmModal
|
||||||
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
animated: false
|
animated: false,
|
||||||
|
showingConfirmDialog: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
retweet () {
|
retweet () {
|
||||||
|
if (!this.status.repeated && this.shouldConfirmRepeat) {
|
||||||
|
this.showConfirmDialog()
|
||||||
|
} else {
|
||||||
|
this.doRetweet()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
doRetweet () {
|
||||||
if (!this.status.repeated) {
|
if (!this.status.repeated) {
|
||||||
this.$store.dispatch('retweet', { id: this.status.id })
|
this.$store.dispatch('retweet', { id: this.status.id })
|
||||||
} else {
|
} else {
|
||||||
|
@ -21,6 +33,13 @@ const RetweetButton = {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.animated = false
|
this.animated = false
|
||||||
}, 500)
|
}, 500)
|
||||||
|
this.hideConfirmDialog()
|
||||||
|
},
|
||||||
|
showConfirmDialog () {
|
||||||
|
this.showingConfirmDialog = true
|
||||||
|
},
|
||||||
|
hideConfirmDialog () {
|
||||||
|
this.showingConfirmDialog = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -29,6 +48,9 @@ const RetweetButton = {
|
||||||
},
|
},
|
||||||
mergedConfig () {
|
mergedConfig () {
|
||||||
return this.$store.getters.mergedConfig
|
return this.$store.getters.mergedConfig
|
||||||
|
},
|
||||||
|
shouldConfirmRepeat () {
|
||||||
|
return this.mergedConfig.modalOnRepeat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,18 @@
|
||||||
>
|
>
|
||||||
{{ status.repeat_num }}
|
{{ status.repeat_num }}
|
||||||
</span>
|
</span>
|
||||||
|
<teleport to="#modal">
|
||||||
|
<confirm-modal
|
||||||
|
v-if="showingConfirmDialog"
|
||||||
|
:title="$t('status.repeat_confirm_title')"
|
||||||
|
:confirm-text="$t('status.repeat_confirm_accept_button')"
|
||||||
|
:cancel-text="$t('status.repeat_confirm_cancel_button')"
|
||||||
|
@accepted="doRetweet"
|
||||||
|
@cancelled="hideConfirmDialog"
|
||||||
|
>
|
||||||
|
{{ $t('status.repeat_confirm') }}
|
||||||
|
</confirm-modal>
|
||||||
|
</teleport>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,11 @@ const GeneralTab = {
|
||||||
value: mode,
|
value: mode,
|
||||||
label: this.$t(`settings.third_column_mode_${mode}`)
|
label: this.$t(`settings.third_column_mode_${mode}`)
|
||||||
})),
|
})),
|
||||||
|
userProfileDefaultTabOptions: ['statuses', 'replies'].map(tab => ({
|
||||||
|
key: tab,
|
||||||
|
value: tab,
|
||||||
|
label: this.$t(`user_card.${tab}`)
|
||||||
|
})),
|
||||||
loopSilentAvailable:
|
loopSilentAvailable:
|
||||||
// Firefox
|
// Firefox
|
||||||
Object.getOwnPropertyDescriptor(HTMLVideoElement.prototype, 'mozHasAudio') ||
|
Object.getOwnPropertyDescriptor(HTMLVideoElement.prototype, 'mozHasAudio') ||
|
||||||
|
@ -50,6 +55,7 @@ const GeneralTab = {
|
||||||
Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'webkitAudioDecodedByteCount') ||
|
Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'webkitAudioDecodedByteCount') ||
|
||||||
// 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')
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
@ -82,11 +88,23 @@ const GeneralTab = {
|
||||||
this.$store.dispatch('setOption', { name: 'interfaceLanguage', value: val })
|
this.$store.dispatch('setOption', { name: 'interfaceLanguage', value: val })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
translationLanguages () {
|
||||||
|
return (this.$store.getters.mergedConfig.supportedTranslationLanguages.target || []).map(lang => ({ key: lang.code, value: lang.code, label: lang.name }))
|
||||||
|
},
|
||||||
|
translationLanguage: {
|
||||||
|
get: function () { return this.$store.getters.mergedConfig.translationLanguage },
|
||||||
|
set: function (val) {
|
||||||
|
this.$store.dispatch('setOption', { name: 'translationLanguage', value: val })
|
||||||
|
}
|
||||||
|
},
|
||||||
...SharedComputedObject()
|
...SharedComputedObject()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
changeDefaultScope (value) {
|
changeDefaultScope (value) {
|
||||||
this.$store.dispatch('setServerSideOption', { name: 'defaultScope', value })
|
this.$store.dispatch('setServerSideOption', { name: 'defaultScope', value })
|
||||||
|
},
|
||||||
|
setTranslationLanguage (value) {
|
||||||
|
this.$store.dispatch('setOption', { name: 'translationLanguage', value })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,11 +15,6 @@
|
||||||
{{ $t('settings.hide_isp') }}
|
{{ $t('settings.hide_isp') }}
|
||||||
</BooleanSetting>
|
</BooleanSetting>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
|
||||||
<BooleanSetting path="sidebarRight">
|
|
||||||
{{ $t('settings.right_sidebar') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<li v-if="instanceWallpaperUsed">
|
<li v-if="instanceWallpaperUsed">
|
||||||
<BooleanSetting path="hideInstanceWallpaper">
|
<BooleanSetting path="hideInstanceWallpaper">
|
||||||
{{ $t('settings.hide_wallpaper') }}
|
{{ $t('settings.hide_wallpaper') }}
|
||||||
|
@ -49,6 +44,14 @@
|
||||||
{{ $t('settings.show_nav_shortcuts') }}
|
{{ $t('settings.show_nav_shortcuts') }}
|
||||||
</BooleanSetting>
|
</BooleanSetting>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting
|
||||||
|
path="showPanelNavShortcuts"
|
||||||
|
expert="1"
|
||||||
|
>
|
||||||
|
{{ $t('settings.show_panel_nav_shortcuts') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<BooleanSetting
|
<BooleanSetting
|
||||||
path="showWiderShortcuts"
|
path="showWiderShortcuts"
|
||||||
|
@ -96,41 +99,7 @@
|
||||||
{{ $t('settings.virtual_scrolling') }}
|
{{ $t('settings.virtual_scrolling') }}
|
||||||
</BooleanSetting>
|
</BooleanSetting>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
|
||||||
<BooleanSetting path="disableStickyHeaders">
|
|
||||||
{{ $t('settings.disable_sticky_headers') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<BooleanSetting path="showScrollbars">
|
|
||||||
{{ $t('settings.show_scrollbars') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<ChoiceSetting
|
|
||||||
v-if="user"
|
|
||||||
id="thirdColumnMode"
|
|
||||||
path="thirdColumnMode"
|
|
||||||
:options="thirdColumnModeOptions"
|
|
||||||
>
|
|
||||||
{{ $t('settings.third_column_mode') }}
|
|
||||||
</ChoiceSetting>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<BooleanSetting path="minimalScopesMode">
|
|
||||||
{{ $t('settings.minimal_scopes_mode') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<BooleanSetting path="sensitiveByDefault">
|
|
||||||
{{ $t('settings.sensitive_by_default') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<BooleanSetting path="sensitiveIfSubject">
|
|
||||||
{{ $t('settings.sensitive_if_subject') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<li>
|
<li>
|
||||||
<BooleanSetting path="renderMisskeyMarkdown">
|
<BooleanSetting path="renderMisskeyMarkdown">
|
||||||
{{ $t('settings.render_mfm') }}
|
{{ $t('settings.render_mfm') }}
|
||||||
|
@ -148,6 +117,25 @@
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<ChoiceSetting
|
||||||
|
id="userProfileDefaultTab"
|
||||||
|
path="userProfileDefaultTab"
|
||||||
|
:options="userProfileDefaultTabOptions"
|
||||||
|
>
|
||||||
|
{{ $t('settings.user_profile_default_tab') }}
|
||||||
|
</ChoiceSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<ChoiceSetting
|
||||||
|
v-if="user && (translationLanguages.length > 0)"
|
||||||
|
id="translationLanguage"
|
||||||
|
path="translationLanguage"
|
||||||
|
:options="translationLanguages"
|
||||||
|
>
|
||||||
|
{{ $t('settings.translation_language') }}
|
||||||
|
</ChoiceSetting>
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<BooleanSetting
|
<BooleanSetting
|
||||||
path="alwaysShowNewPostButton"
|
path="alwaysShowNewPostButton"
|
||||||
|
@ -164,6 +152,77 @@
|
||||||
{{ $t('settings.autohide_floating_post_button') }}
|
{{ $t('settings.autohide_floating_post_button') }}
|
||||||
</BooleanSetting>
|
</BooleanSetting>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<h3>{{ $t('settings.columns') }}</h3>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting path="disableStickyHeaders">
|
||||||
|
{{ $t('settings.disable_sticky_headers') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting path="showScrollbars">
|
||||||
|
{{ $t('settings.show_scrollbars') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting path="sidebarRight">
|
||||||
|
{{ $t('settings.right_sidebar') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<ChoiceSetting
|
||||||
|
v-if="user"
|
||||||
|
id="thirdColumnMode"
|
||||||
|
path="thirdColumnMode"
|
||||||
|
:options="thirdColumnModeOptions"
|
||||||
|
>
|
||||||
|
{{ $t('settings.third_column_mode') }}
|
||||||
|
</ChoiceSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<h3>{{ $t('settings.confirmation_dialogs') }}</h3>
|
||||||
|
</li>
|
||||||
|
<li class="select-multiple">
|
||||||
|
<span class="label">{{ $t('settings.confirm_dialogs') }}</span>
|
||||||
|
<ul class="option-list">
|
||||||
|
<li>
|
||||||
|
<BooleanSetting path="modalOnRepeat">
|
||||||
|
{{ $t('settings.confirm_dialogs_repeat') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting path="modalOnUnfollow">
|
||||||
|
{{ $t('settings.confirm_dialogs_unfollow') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting path="modalOnBlock">
|
||||||
|
{{ $t('settings.confirm_dialogs_block') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting path="modalOnMute">
|
||||||
|
{{ $t('settings.confirm_dialogs_mute') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting path="modalOnDelete">
|
||||||
|
{{ $t('settings.confirm_dialogs_delete') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting path="modalOnApproveFollow">
|
||||||
|
{{ $t('settings.confirm_dialogs_approve_follow') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting path="modalOnDenyFollow">
|
||||||
|
{{ $t('settings.confirm_dialogs_deny_follow') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-item">
|
<div class="setting-item">
|
||||||
|
@ -398,12 +457,22 @@
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting path="minimalScopesMode">
|
||||||
|
{{ $t('settings.minimal_scopes_mode') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<!-- <BooleanSetting path="serverSide_defaultNSFW"> -->
|
<!-- <BooleanSetting path="serverSide_defaultNSFW"> -->
|
||||||
<BooleanSetting path="sensitiveByDefault">
|
<BooleanSetting path="sensitiveByDefault">
|
||||||
{{ $t('settings.sensitive_by_default') }}
|
{{ $t('settings.sensitive_by_default') }}
|
||||||
</BooleanSetting>
|
</BooleanSetting>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting path="sensitiveIfSubject">
|
||||||
|
{{ $t('settings.sensitive_if_subject') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<BooleanSetting
|
<BooleanSetting
|
||||||
path="scopeCopy"
|
path="scopeCopy"
|
||||||
|
|
|
@ -437,6 +437,12 @@ const Status = {
|
||||||
},
|
},
|
||||||
visibilityLocalized () {
|
visibilityLocalized () {
|
||||||
return this.$i18n.t('general.scope_in_timeline.' + this.status.visibility)
|
return this.$i18n.t('general.scope_in_timeline.' + this.status.visibility)
|
||||||
|
},
|
||||||
|
isEdited () {
|
||||||
|
return this.status.edited_at !== null
|
||||||
|
},
|
||||||
|
editingAvailable () {
|
||||||
|
return this.$store.state.instance.editingAvailable
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
|
@ -160,7 +160,8 @@
|
||||||
margin-right: 0.2em;
|
margin-right: 0.2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
& .heading-reply-row {
|
& .heading-reply-row,
|
||||||
|
& .heading-edited-row {
|
||||||
position: relative;
|
position: relative;
|
||||||
align-content: baseline;
|
align-content: baseline;
|
||||||
font-size: 0.85em;
|
font-size: 0.85em;
|
||||||
|
|
|
@ -329,6 +329,24 @@
|
||||||
class="mentions-line"
|
class="mentions-line"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="isEdited && editingAvailable && !isPreview"
|
||||||
|
class="heading-edited-row"
|
||||||
|
>
|
||||||
|
<i18n-t
|
||||||
|
keypath="status.edited_at"
|
||||||
|
tag="span"
|
||||||
|
>
|
||||||
|
<template #time>
|
||||||
|
<Timeago
|
||||||
|
:time="status.edited_at"
|
||||||
|
:auto-update="60"
|
||||||
|
:long-format="true"
|
||||||
|
:with-direction="true"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</i18n-t>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<StatusContent
|
<StatusContent
|
||||||
|
|
|
@ -9,6 +9,7 @@ import {
|
||||||
faLink,
|
faLink,
|
||||||
faPollH
|
faPollH
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
import Select from 'src/components/select/select.vue'
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
faFile,
|
faFile,
|
||||||
|
@ -39,7 +40,8 @@ const StatusContent = {
|
||||||
return {
|
return {
|
||||||
postLength: this.status.text.length,
|
postLength: this.status.text.length,
|
||||||
parseReadyDone: false,
|
parseReadyDone: false,
|
||||||
renderMisskeyMarkdown
|
renderMisskeyMarkdown,
|
||||||
|
translateFrom: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -80,10 +82,14 @@ const StatusContent = {
|
||||||
attachmentTypes () {
|
attachmentTypes () {
|
||||||
return this.status.attachments.map(file => fileType.fileType(file.mimetype))
|
return this.status.attachments.map(file => fileType.fileType(file.mimetype))
|
||||||
},
|
},
|
||||||
|
translationLanguages () {
|
||||||
|
return (this.$store.getters.mergedConfig.supportedTranslationLanguages.source || []).map(lang => ({ key: lang.code, value: lang.code, label: lang.name }))
|
||||||
|
},
|
||||||
...mapGetters(['mergedConfig'])
|
...mapGetters(['mergedConfig'])
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
RichContent
|
RichContent,
|
||||||
|
Select
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
this.status.attentions && this.status.attentions.forEach(attn => {
|
this.status.attentions && this.status.attentions.forEach(attn => {
|
||||||
|
@ -126,6 +132,10 @@ const StatusContent = {
|
||||||
},
|
},
|
||||||
generateTagLink (tag) {
|
generateTagLink (tag) {
|
||||||
return `/tag/${tag}`
|
return `/tag/${tag}`
|
||||||
|
},
|
||||||
|
translateStatus () {
|
||||||
|
const translateTo = this.$store.getters.mergedConfig.translationLanguage || this.$store.state.instance.interfaceLanguage
|
||||||
|
this.$store.dispatch('translateStatus', { id: this.status.id, language: translateTo, from: this.translateFrom })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,12 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
|
.translation {
|
||||||
|
border: 1px solid var(--accent, $fallback--link);
|
||||||
|
border-radius: var(--panelRadius, $fallback--panelRadius);
|
||||||
|
margin-top: 1em;
|
||||||
|
padding: 0.5em;
|
||||||
|
}
|
||||||
.emoji {
|
.emoji {
|
||||||
--_still_image-label-scale: 0.5;
|
--_still_image-label-scale: 0.5;
|
||||||
--emoji-size: 38px;
|
--emoji-size: 38px;
|
||||||
|
|
|
@ -56,6 +56,44 @@
|
||||||
:attentions="status.attentions"
|
:attentions="status.attentions"
|
||||||
@parseReady="onParseReady"
|
@parseReady="onParseReady"
|
||||||
/>
|
/>
|
||||||
|
<div
|
||||||
|
v-if="status.translation"
|
||||||
|
class="translation"
|
||||||
|
>
|
||||||
|
<h4>{{ $t('status.translated_from', { language: status.translation.detected_language }) }}</h4>
|
||||||
|
<RichContent
|
||||||
|
:class="{ '-single-line': singleLine }"
|
||||||
|
class="text media-body"
|
||||||
|
:html="status.translation.text"
|
||||||
|
:emoji="status.emojis"
|
||||||
|
:handle-links="true"
|
||||||
|
:mfm="renderMisskeyMarkdown && (status.media_type === 'text/x.misskeymarkdown')"
|
||||||
|
:greentext="mergedConfig.greentext"
|
||||||
|
:attentions="status.attentions"
|
||||||
|
@parseReady="onParseReady"
|
||||||
|
/>
|
||||||
|
<div>
|
||||||
|
<label class="label">{{ $t('status.override_translation_source_language') }}</label>
|
||||||
|
{{ ' ' }}
|
||||||
|
<Select
|
||||||
|
id="source-language-switcher"
|
||||||
|
v-model="translateFrom"
|
||||||
|
class="preset-switcher"
|
||||||
|
>
|
||||||
|
<option
|
||||||
|
v-for="language in translationLanguages"
|
||||||
|
:key="language.key"
|
||||||
|
:value="language.value"
|
||||||
|
>
|
||||||
|
{{ language.label }}
|
||||||
|
</option>
|
||||||
|
</Select>
|
||||||
|
{{ ' ' }}
|
||||||
|
<button @click="translateStatus" class="btn button-default">
|
||||||
|
{{ $t('status.translate') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
v-show="hideSubjectStatus"
|
v-show="hideSubjectStatus"
|
||||||
|
|
|
@ -103,6 +103,9 @@ const StatusContent = {
|
||||||
renderMfmOnHover () {
|
renderMfmOnHover () {
|
||||||
return this.mergedConfig.renderMfmOnHover
|
return this.mergedConfig.renderMfmOnHover
|
||||||
},
|
},
|
||||||
|
renderMisskeyMarkdown () {
|
||||||
|
return this.mergedConfig.renderMisskeyMarkdown
|
||||||
|
},
|
||||||
...mapGetters(['mergedConfig']),
|
...mapGetters(['mergedConfig']),
|
||||||
...mapState({
|
...mapState({
|
||||||
currentUser: state => state.users.currentUser
|
currentUser: state => state.users.currentUser
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="StatusContent"
|
class="StatusContent"
|
||||||
:class="{ '-compact': compact, 'mfm-hover': renderMfmOnHover }"
|
:class="{ '-compact': compact, 'mfm-hover': renderMfmOnHover, 'mfm-disabled': !renderMisskeyMarkdown }"
|
||||||
>
|
>
|
||||||
<slot name="header" />
|
<slot name="header" />
|
||||||
<StatusBody
|
<StatusBody
|
||||||
|
@ -78,7 +78,12 @@
|
||||||
|
|
||||||
&.mfm-hover:not(:hover) {
|
&.mfm-hover:not(:hover) {
|
||||||
.mfm {
|
.mfm {
|
||||||
animation: none;
|
animation: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.mfm-disabled {
|
||||||
|
.mfm {
|
||||||
|
animation: none !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
60
src/components/status_history_modal/status_history_modal.js
Normal file
60
src/components/status_history_modal/status_history_modal.js
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
import { get } from 'lodash'
|
||||||
|
import Modal from '../modal/modal.vue'
|
||||||
|
import Status from '../status/status.vue'
|
||||||
|
|
||||||
|
const StatusHistoryModal = {
|
||||||
|
components: {
|
||||||
|
Modal,
|
||||||
|
Status
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
statuses: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
modalActivated () {
|
||||||
|
return this.$store.state.statusHistory.modalActivated
|
||||||
|
},
|
||||||
|
params () {
|
||||||
|
return this.$store.state.statusHistory.params
|
||||||
|
},
|
||||||
|
statusId () {
|
||||||
|
return this.params.id
|
||||||
|
},
|
||||||
|
historyCount () {
|
||||||
|
return this.statuses.length
|
||||||
|
},
|
||||||
|
history () {
|
||||||
|
return this.statuses
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
params (newVal, oldVal) {
|
||||||
|
const newStatusId = get(newVal, 'id') !== get(oldVal, 'id')
|
||||||
|
if (newStatusId) {
|
||||||
|
this.resetHistory()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newStatusId || get(newVal, 'edited_at') !== get(oldVal, 'edited_at')) {
|
||||||
|
this.fetchStatusHistory()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
resetHistory () {
|
||||||
|
this.statuses = []
|
||||||
|
},
|
||||||
|
fetchStatusHistory () {
|
||||||
|
this.$store.dispatch('fetchStatusHistory', this.params)
|
||||||
|
.then(data => {
|
||||||
|
this.statuses = data
|
||||||
|
})
|
||||||
|
},
|
||||||
|
closeModal () {
|
||||||
|
this.$store.dispatch('closeStatusHistoryModal')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default StatusHistoryModal
|
46
src/components/status_history_modal/status_history_modal.vue
Normal file
46
src/components/status_history_modal/status_history_modal.vue
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
<template>
|
||||||
|
<Modal
|
||||||
|
v-if="modalActivated"
|
||||||
|
class="status-history-modal-view"
|
||||||
|
@backdropClicked="closeModal"
|
||||||
|
>
|
||||||
|
<div class="status-history-modal-panel panel">
|
||||||
|
<div class="panel-heading">
|
||||||
|
{{ $tc('status.edit_history_modal_title', historyCount - 1, { historyCount: historyCount - 1 }) }}
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<div
|
||||||
|
v-if="historyCount > 0"
|
||||||
|
class="history-body"
|
||||||
|
>
|
||||||
|
<status
|
||||||
|
v-for="status in history"
|
||||||
|
:key="status.id"
|
||||||
|
:statusoid="status"
|
||||||
|
:isPreview="true"
|
||||||
|
class="conversation-status status-fadein panel-body"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./status_history_modal.js"></script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.modal-view.status-history-modal-view {
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
.status-history-modal-panel {
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-top: 25%;
|
||||||
|
margin-bottom: 2em;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 700px;
|
||||||
|
|
||||||
|
@media (orientation: landscape) {
|
||||||
|
margin-top: 8%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -2,6 +2,7 @@ import Status from '../status/status.vue'
|
||||||
import timelineFetcher from '../../services/timeline_fetcher/timeline_fetcher.service.js'
|
import timelineFetcher from '../../services/timeline_fetcher/timeline_fetcher.service.js'
|
||||||
import Conversation from '../conversation/conversation.vue'
|
import Conversation from '../conversation/conversation.vue'
|
||||||
import TimelineMenu from '../timeline_menu/timeline_menu.vue'
|
import TimelineMenu from '../timeline_menu/timeline_menu.vue'
|
||||||
|
import TimelineMenuTabs from '../timeline_menu_tabs/timeline_menu_tabs.vue'
|
||||||
import TimelineQuickSettings from './timeline_quick_settings.vue'
|
import TimelineQuickSettings from './timeline_quick_settings.vue'
|
||||||
import { debounce, throttle, keyBy } from 'lodash'
|
import { debounce, throttle, keyBy } from 'lodash'
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
|
@ -39,6 +40,7 @@ const Timeline = {
|
||||||
Status,
|
Status,
|
||||||
Conversation,
|
Conversation,
|
||||||
TimelineMenu,
|
TimelineMenu,
|
||||||
|
TimelineMenuTabs,
|
||||||
TimelineQuickSettings
|
TimelineQuickSettings
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -85,6 +87,9 @@ const Timeline = {
|
||||||
},
|
},
|
||||||
virtualScrollingEnabled () {
|
virtualScrollingEnabled () {
|
||||||
return this.$store.getters.mergedConfig.virtualScrolling
|
return this.$store.getters.mergedConfig.virtualScrolling
|
||||||
|
},
|
||||||
|
showPanelNavShortcuts () {
|
||||||
|
return this.$store.getters.mergedConfig.showPanelNavShortcuts
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created () {
|
created () {
|
||||||
|
@ -145,7 +150,9 @@ const Timeline = {
|
||||||
this.$store.commit('showNewStatuses', { timeline: this.timelineName })
|
this.$store.commit('showNewStatuses', { timeline: this.timelineName })
|
||||||
this.paused = false
|
this.paused = false
|
||||||
}
|
}
|
||||||
|
if (!this.inProfile) {
|
||||||
window.scrollTo({ top: 0 })
|
window.scrollTo({ top: 0 })
|
||||||
|
}
|
||||||
},
|
},
|
||||||
fetchOlderStatuses: throttle(function () {
|
fetchOlderStatuses: throttle(function () {
|
||||||
const store = this.$store
|
const store = this.$store
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
<template>
|
<template>
|
||||||
<div :class="['Timeline', classes.root]">
|
<div :class="['Timeline', classes.root]">
|
||||||
<div :class="classes.header">
|
<div :class="classes.header">
|
||||||
<TimelineMenu v-if="!embedded" />
|
<template v-if="!embedded">
|
||||||
|
<TimelineMenuTabs v-if="showPanelNavShortcuts" />
|
||||||
|
<TimelineMenu v-else />
|
||||||
|
</template>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
v-if="showLoadButton"
|
v-if="showLoadButton"
|
||||||
class="button-default loadmore-button"
|
class="button-default loadmore-button"
|
||||||
|
|
30
src/components/timeline_menu_tabs/timeline_menu_content.js
Normal file
30
src/components/timeline_menu_tabs/timeline_menu_content.js
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import { mapState } from 'vuex'
|
||||||
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
|
import {
|
||||||
|
faUsers,
|
||||||
|
faGlobe,
|
||||||
|
faBookmark,
|
||||||
|
faEnvelope,
|
||||||
|
faHome
|
||||||
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
import { faCircle } from '@fortawesome/free-regular-svg-icons'
|
||||||
|
library.add(
|
||||||
|
faUsers,
|
||||||
|
faGlobe,
|
||||||
|
faBookmark,
|
||||||
|
faEnvelope,
|
||||||
|
faHome,
|
||||||
|
faCircle
|
||||||
|
)
|
||||||
|
|
||||||
|
const TimelineMenuContent = {
|
||||||
|
computed: {
|
||||||
|
...mapState({
|
||||||
|
currentUser: state => state.users.currentUser,
|
||||||
|
privateMode: state => state.instance.private,
|
||||||
|
federating: state => state.instance.federating
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TimelineMenuContent
|
114
src/components/timeline_menu_tabs/timeline_menu_content.vue
Normal file
114
src/components/timeline_menu_tabs/timeline_menu_content.vue
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
<template>
|
||||||
|
<ul>
|
||||||
|
<li v-if="currentUser">
|
||||||
|
<router-link
|
||||||
|
class="menu-item"
|
||||||
|
:to="{ name: 'friends' }"
|
||||||
|
>
|
||||||
|
<FAIcon
|
||||||
|
fixed-width
|
||||||
|
class="fa-scale-110 fa-old-padding "
|
||||||
|
icon="home"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
:title="$t('nav.home_timeline_description')"
|
||||||
|
:aria-label="$t('nav.home_timeline_description')"
|
||||||
|
>{{ $t("nav.home_timeline") }}</span>
|
||||||
|
</router-link>
|
||||||
|
</li>
|
||||||
|
<li v-if="currentUser">
|
||||||
|
<router-link
|
||||||
|
class="menu-item"
|
||||||
|
:to="{ name: 'bubble-timeline' }"
|
||||||
|
>
|
||||||
|
<FAIcon
|
||||||
|
fixed-width
|
||||||
|
class="fa-scale-110 fa-old-padding "
|
||||||
|
:icon="['far', 'circle']"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
:title="$t('nav.bubble_timeline_description')"
|
||||||
|
:aria-label="$t('nav.bubble_timeline_description')"
|
||||||
|
>{{ $t("nav.bubble_timeline") }}</span>
|
||||||
|
</router-link>
|
||||||
|
</li>
|
||||||
|
<li v-if="currentUser || !privateMode">
|
||||||
|
<router-link
|
||||||
|
class="menu-item"
|
||||||
|
:to="{ name: 'public-timeline' }"
|
||||||
|
>
|
||||||
|
<FAIcon
|
||||||
|
fixed-width
|
||||||
|
class="fa-scale-110 fa-old-padding "
|
||||||
|
icon="users"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
:title="$t('nav.public_timeline_description')"
|
||||||
|
:aria-label="$t('nav.public_timeline_description')"
|
||||||
|
>{{ $t("nav.public_tl") }}</span>
|
||||||
|
</router-link>
|
||||||
|
</li>
|
||||||
|
<li v-if="federating && (currentUser || !privateMode)">
|
||||||
|
<router-link
|
||||||
|
class="menu-item"
|
||||||
|
:to="{ name: 'public-external-timeline' }"
|
||||||
|
>
|
||||||
|
<FAIcon
|
||||||
|
fixed-width
|
||||||
|
class="fa-scale-110 fa-old-padding "
|
||||||
|
icon="globe"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
:title="$t('nav.twkn_timeline_description')"
|
||||||
|
:aria-label="$t('nav.twkn_timeline_description')"
|
||||||
|
>{{ $t("nav.twkn") }}</span>
|
||||||
|
</router-link>
|
||||||
|
</li>
|
||||||
|
<li v-if="currentUser">
|
||||||
|
<router-link
|
||||||
|
class="menu-item"
|
||||||
|
:to="{ name: 'bookmarks'}"
|
||||||
|
>
|
||||||
|
<FAIcon
|
||||||
|
fixed-width
|
||||||
|
class="fa-scale-110 fa-old-padding "
|
||||||
|
icon="bookmark"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
:title="$t('nav.bookmarks')"
|
||||||
|
:aria-label="$t('nav.bookmarks')"
|
||||||
|
>{{ $t("nav.bookmarks") }}</span>
|
||||||
|
</router-link>
|
||||||
|
</li>
|
||||||
|
<li v-if="currentUser">
|
||||||
|
<router-link
|
||||||
|
class="menu-item"
|
||||||
|
:to="{ name: 'dms', params: { username: currentUser.screen_name } }"
|
||||||
|
>
|
||||||
|
<FAIcon
|
||||||
|
fixed-width
|
||||||
|
class="fa-scale-110 fa-old-padding "
|
||||||
|
icon="envelope"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
:title="$t('nav.dms')"
|
||||||
|
:aria-label="$t('nav.dms')"
|
||||||
|
>{{ $t("nav.dms") }}</span>
|
||||||
|
</router-link>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./timeline_menu_content.js" ></script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@import "../../_variables.scss";
|
||||||
|
.timeline-desc {
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--text, $fallback--text);
|
||||||
|
padding-left: 1em;
|
||||||
|
display: block;
|
||||||
|
background-color: scale(var(--bg, $fallback--bg), 0.1);
|
||||||
|
padding-bottom: 0.4em;
|
||||||
|
}
|
||||||
|
</style>
|
61
src/components/timeline_menu_tabs/timeline_menu_tabs.js
Normal file
61
src/components/timeline_menu_tabs/timeline_menu_tabs.js
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
import Popover from '../popover/popover.vue'
|
||||||
|
import TimelineMenuContent from './timeline_menu_content.vue'
|
||||||
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
|
import {
|
||||||
|
faChevronDown
|
||||||
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
|
||||||
|
library.add(faChevronDown)
|
||||||
|
|
||||||
|
// Route -> i18n key mapping, exported and not in the computed
|
||||||
|
// because nav panel benefits from the same information.
|
||||||
|
export const timelineNames = () => {
|
||||||
|
return {
|
||||||
|
'friends': 'nav.home_timeline',
|
||||||
|
'bookmarks': 'nav.bookmarks',
|
||||||
|
'dms': 'nav.dms',
|
||||||
|
'public-timeline': 'nav.public_tl',
|
||||||
|
'public-external-timeline': 'nav.twkn',
|
||||||
|
'bubble-timeline': 'nav.bubble_timeline'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const TimelineMenuTabs = {
|
||||||
|
components: {
|
||||||
|
Popover,
|
||||||
|
TimelineMenuContent
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
isOpen: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created () {
|
||||||
|
if (timelineNames()[this.$route.name]) {
|
||||||
|
this.$store.dispatch('setLastTimeline', this.$route.name)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
currentUser () {
|
||||||
|
return this.$store.state.users.currentUser
|
||||||
|
},
|
||||||
|
privateMode () {
|
||||||
|
return this.$store.state.instance.private
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
timelineName () {
|
||||||
|
const route = this.$route.name
|
||||||
|
if (route === 'tag-timeline') {
|
||||||
|
return '#' + this.$route.params.tag
|
||||||
|
}
|
||||||
|
if (route === 'list-timeline') {
|
||||||
|
return this.$store.getters.findListTitle(this.$route.params.id)
|
||||||
|
}
|
||||||
|
const i18nkey = timelineNames()[this.$route.name]
|
||||||
|
return i18nkey ? this.$t(i18nkey) : route
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TimelineMenuTabs
|
96
src/components/timeline_menu_tabs/timeline_menu_tabs.vue
Normal file
96
src/components/timeline_menu_tabs/timeline_menu_tabs.vue
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
v-if="currentUser || !privateMode"
|
||||||
|
class="nav-items timeline-menu-tabs"
|
||||||
|
>
|
||||||
|
<router-link
|
||||||
|
v-if="currentUser"
|
||||||
|
:to="{ name: 'friends' }"
|
||||||
|
class="nav-icon"
|
||||||
|
>
|
||||||
|
<FAIcon
|
||||||
|
fixed-width
|
||||||
|
class="fa-scale-110 fa-old-padding"
|
||||||
|
icon="home"
|
||||||
|
:title="$t('nav.home_timeline_description')"
|
||||||
|
/>
|
||||||
|
</router-link>
|
||||||
|
<router-link
|
||||||
|
:to="{ name: 'public-timeline' }"
|
||||||
|
class="nav-icon"
|
||||||
|
>
|
||||||
|
<FAIcon
|
||||||
|
fixed-width
|
||||||
|
class="fa-scale-110 fa-old-padding"
|
||||||
|
icon="users"
|
||||||
|
:title="$t('nav.public_timeline_description')"
|
||||||
|
/>
|
||||||
|
</router-link>
|
||||||
|
<router-link
|
||||||
|
v-if="currentUser"
|
||||||
|
:to="{ name: 'bubble-timeline' }"
|
||||||
|
class="nav-icon"
|
||||||
|
>
|
||||||
|
<FAIcon
|
||||||
|
fixed-width
|
||||||
|
class="fa-scale-110 fa-old-padding"
|
||||||
|
:icon="['far', 'circle']"
|
||||||
|
:title="$t('nav.bubble_timeline_description')"
|
||||||
|
/>
|
||||||
|
</router-link>
|
||||||
|
<router-link
|
||||||
|
:to="{ name: 'public-external-timeline' }"
|
||||||
|
class="nav-icon"
|
||||||
|
>
|
||||||
|
<FAIcon
|
||||||
|
fixed-width
|
||||||
|
class="fa-scale-110 fa-old-padding"
|
||||||
|
icon="globe"
|
||||||
|
:title="$t('nav.twkn_timeline_description')"
|
||||||
|
/>
|
||||||
|
</router-link>
|
||||||
|
<span class="timeline-title">{{ timelineName() }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./timeline_menu_tabs.js" ></script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@import '../../_variables.scss';
|
||||||
|
|
||||||
|
.timeline-menu-tabs {
|
||||||
|
.nav-icon {
|
||||||
|
margin-left: 0.7em;
|
||||||
|
width: 2em;
|
||||||
|
height: 100%;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
&.router-link-active {
|
||||||
|
border-bottom: 2px solid var(--selectedMenuText, $fallback--text);
|
||||||
|
padding-bottom: 0.8em;
|
||||||
|
|
||||||
|
.svg-inline--fa {
|
||||||
|
font-weight: bolder;
|
||||||
|
color: $fallback--text;
|
||||||
|
color: var(--selectedMenuText, $fallback--text);
|
||||||
|
--lightText: var(--selectedMenuLightText, $fallback--lightText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-title {
|
||||||
|
margin-left: 1em;
|
||||||
|
font-size: 1.2em;
|
||||||
|
font-weight: bold;
|
||||||
|
color: var(--selectedMenuText, $fallback--text);
|
||||||
|
color: var(--selectedMenuText, $fallback--text);
|
||||||
|
--lightText: var(--selectedMenuLightText, $fallback--lightText);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media all and (max-width: 900px) {
|
||||||
|
.timeline-title {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -6,6 +6,7 @@ import ModerationTools from '../moderation_tools/moderation_tools.vue'
|
||||||
import AccountActions from '../account_actions/account_actions.vue'
|
import AccountActions from '../account_actions/account_actions.vue'
|
||||||
import Select from '../select/select.vue'
|
import Select from '../select/select.vue'
|
||||||
import RichContent from 'src/components/rich_content/rich_content.jsx'
|
import RichContent from 'src/components/rich_content/rich_content.jsx'
|
||||||
|
import ConfirmModal from '../confirm_modal/confirm_modal.vue'
|
||||||
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'
|
||||||
import { mapGetters } from 'vuex'
|
import { mapGetters } from 'vuex'
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
|
@ -32,7 +33,8 @@ export default {
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
followRequestInProgress: false,
|
followRequestInProgress: false,
|
||||||
betterShadow: this.$store.state.interface.browserSupport.cssFilter
|
betterShadow: this.$store.state.interface.browserSupport.cssFilter,
|
||||||
|
showingConfirmMute: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created () {
|
created () {
|
||||||
|
@ -69,6 +71,7 @@ export default {
|
||||||
return `${serverUrl.protocol}//${serverUrl.host}/main/ostatus`
|
return `${serverUrl.protocol}//${serverUrl.host}/main/ostatus`
|
||||||
},
|
},
|
||||||
loggedIn () {
|
loggedIn () {
|
||||||
|
console.log({ ...this.$store.state.users.currentUser })
|
||||||
return this.$store.state.users.currentUser
|
return this.$store.state.users.currentUser
|
||||||
},
|
},
|
||||||
dailyAvg () {
|
dailyAvg () {
|
||||||
|
@ -112,6 +115,9 @@ export default {
|
||||||
hideFollowersCount () {
|
hideFollowersCount () {
|
||||||
return this.isOtherUser && this.user.hide_followers_count
|
return this.isOtherUser && this.user.hide_followers_count
|
||||||
},
|
},
|
||||||
|
shouldConfirmMute () {
|
||||||
|
return this.mergedConfig.modalOnMute
|
||||||
|
},
|
||||||
...mapGetters(['mergedConfig'])
|
...mapGetters(['mergedConfig'])
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
@ -122,14 +128,29 @@ export default {
|
||||||
ProgressButton,
|
ProgressButton,
|
||||||
FollowButton,
|
FollowButton,
|
||||||
Select,
|
Select,
|
||||||
RichContent
|
RichContent,
|
||||||
|
ConfirmModal
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
refetchRelationship () {
|
refetchRelationship () {
|
||||||
return this.$store.dispatch('fetchUserRelationship', this.user.id)
|
return this.$store.dispatch('fetchUserRelationship', this.user.id)
|
||||||
},
|
},
|
||||||
|
showConfirmMute () {
|
||||||
|
this.showingConfirmMute = true
|
||||||
|
},
|
||||||
|
hideConfirmMute () {
|
||||||
|
this.showingConfirmMute = false
|
||||||
|
},
|
||||||
muteUser () {
|
muteUser () {
|
||||||
|
if (!this.shouldConfirmMute) {
|
||||||
|
this.doMuteUser()
|
||||||
|
} else {
|
||||||
|
this.showConfirmMute()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
doMuteUser () {
|
||||||
this.$store.dispatch('muteUser', this.user.id)
|
this.$store.dispatch('muteUser', this.user.id)
|
||||||
|
this.hideConfirmMute()
|
||||||
},
|
},
|
||||||
unmuteUser () {
|
unmuteUser () {
|
||||||
this.$store.dispatch('unmuteUser', this.user.id)
|
this.$store.dispatch('unmuteUser', this.user.id)
|
||||||
|
|
|
@ -245,7 +245,7 @@
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<ModerationTools
|
<ModerationTools
|
||||||
v-if="loggedIn.role === "admin""
|
v-if="loggedIn.role === 'admin'"
|
||||||
:user="user"
|
:user="user"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -295,6 +295,27 @@
|
||||||
:handle-links="true"
|
:handle-links="true"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<teleport to="#modal">
|
||||||
|
<confirm-modal
|
||||||
|
v-if="showingConfirmMute"
|
||||||
|
:title="$t('user_card.mute_confirm_title')"
|
||||||
|
:confirm-text="$t('user_card.mute_confirm_accept_button')"
|
||||||
|
:cancel-text="$t('user_card.mute_confirm_cancel_button')"
|
||||||
|
@accepted="doMuteUser"
|
||||||
|
@cancelled="hideConfirmMute"
|
||||||
|
>
|
||||||
|
<i18n-t
|
||||||
|
keypath="user_card.mute_confirm"
|
||||||
|
tag="span"
|
||||||
|
>
|
||||||
|
<template #user>
|
||||||
|
<span
|
||||||
|
v-text="user.screen_name_ui"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</i18n-t>
|
||||||
|
</confirm-modal>
|
||||||
|
</teleport>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -33,23 +33,23 @@ const FriendList = withLoadMore({
|
||||||
additionalPropNames: ['userId']
|
additionalPropNames: ['userId']
|
||||||
})(List)
|
})(List)
|
||||||
|
|
||||||
const defaultTabKey = 'statuses'
|
|
||||||
|
|
||||||
const UserProfile = {
|
const UserProfile = {
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
error: false,
|
error: false,
|
||||||
userId: null,
|
userId: null,
|
||||||
tab: defaultTabKey,
|
tab: 'statuses',
|
||||||
footerRef: null,
|
footerRef: null,
|
||||||
note: null,
|
note: null,
|
||||||
noteLoading: false
|
noteLoading: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created () {
|
created () {
|
||||||
|
const defaultTabKey = this.defaultTabKey
|
||||||
const routeParams = this.$route.params
|
const routeParams = this.$route.params
|
||||||
|
const hash = (get(this.$route, 'hash') || defaultTabKey).replace(/^#/, '')
|
||||||
|
if (hash !== '') this.tab = hash
|
||||||
this.load(routeParams.name || routeParams.id)
|
this.load(routeParams.name || routeParams.id)
|
||||||
this.tab = get(this.$route, 'query.hash', defaultTabKey).replace(/^#/, '')
|
|
||||||
},
|
},
|
||||||
unmounted () {
|
unmounted () {
|
||||||
this.stopFetching()
|
this.stopFetching()
|
||||||
|
@ -58,6 +58,9 @@ const UserProfile = {
|
||||||
timeline () {
|
timeline () {
|
||||||
return this.$store.state.statuses.timelines.user
|
return this.$store.state.statuses.timelines.user
|
||||||
},
|
},
|
||||||
|
replies () {
|
||||||
|
return this.$store.state.statuses.timelines.replies
|
||||||
|
},
|
||||||
favorites () {
|
favorites () {
|
||||||
return this.$store.state.statuses.timelines.favorites
|
return this.$store.state.statuses.timelines.favorites
|
||||||
},
|
},
|
||||||
|
@ -82,28 +85,39 @@ const UserProfile = {
|
||||||
},
|
},
|
||||||
currentUser () {
|
currentUser () {
|
||||||
return this.$store.state.users.currentUser
|
return this.$store.state.users.currentUser
|
||||||
|
},
|
||||||
|
defaultTabKey () {
|
||||||
|
return this.$store.getters.mergedConfig.userProfileDefaultTab || 'statuses'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
setFooterRef (el) {
|
setFooterRef (el) {
|
||||||
this.footerRef = el
|
this.footerRef = el
|
||||||
},
|
},
|
||||||
load (userNameOrId) {
|
onRouteChange (previousTab, nextTab) {
|
||||||
const startFetchingTimeline = (timeline, userId) => {
|
const timelineTabMap = {
|
||||||
// Clear timeline only if load another user's profile
|
statuses: 'user',
|
||||||
if (userId !== this.$store.state.statuses.timelines[timeline].userId) {
|
replies: 'replies',
|
||||||
this.$store.commit('clearTimeline', { timeline })
|
media: 'media'
|
||||||
}
|
|
||||||
this.$store.dispatch('startFetchingTimeline', { timeline, userId })
|
|
||||||
}
|
}
|
||||||
|
// only we can see our own favourites
|
||||||
|
if (this.isUs) timelineTabMap['favorites'] = 'favorites'
|
||||||
|
|
||||||
|
const timeline = timelineTabMap[nextTab]
|
||||||
|
|
||||||
|
if (timeline) {
|
||||||
|
this.stopFetching()
|
||||||
|
this.$store.dispatch('startFetchingTimeline', { timeline: timeline, userId: this.userId })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
load (userNameOrId) {
|
||||||
const loadById = (userId) => {
|
const loadById = (userId) => {
|
||||||
this.userId = userId
|
this.userId = userId
|
||||||
startFetchingTimeline('user', userId)
|
const timelines = ['user', 'favorites', 'replies', 'media']
|
||||||
startFetchingTimeline('media', userId)
|
timelines.forEach((timeline) => {
|
||||||
if (this.isUs) {
|
this.$store.commit('clearTimeline', { timeline: timeline })
|
||||||
startFetchingTimeline('favorites', userId)
|
})
|
||||||
}
|
this.onRouteChange(null, this.tab)
|
||||||
// Fetch all pinned statuses immediately
|
// Fetch all pinned statuses immediately
|
||||||
this.$store.dispatch('fetchPinnedStatuses', userId)
|
this.$store.dispatch('fetchPinnedStatuses', userId)
|
||||||
}
|
}
|
||||||
|
@ -137,6 +151,7 @@ const UserProfile = {
|
||||||
},
|
},
|
||||||
stopFetching () {
|
stopFetching () {
|
||||||
this.$store.dispatch('stopFetchingTimeline', 'user')
|
this.$store.dispatch('stopFetchingTimeline', 'user')
|
||||||
|
this.$store.dispatch('stopFetchingTimeline', 'replies')
|
||||||
this.$store.dispatch('stopFetchingTimeline', 'favorites')
|
this.$store.dispatch('stopFetchingTimeline', 'favorites')
|
||||||
this.$store.dispatch('stopFetchingTimeline', 'media')
|
this.$store.dispatch('stopFetchingTimeline', 'media')
|
||||||
},
|
},
|
||||||
|
@ -177,7 +192,9 @@ const UserProfile = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'$route.hash': function (newVal) {
|
'$route.hash': function (newVal) {
|
||||||
this.tab = newVal.replace(/^#/, '') || defaultTabKey
|
const oldTab = this.tab
|
||||||
|
this.tab = newVal.replace(/^#/, '') || this.defaultTabKey
|
||||||
|
this.onRouteChange(oldTab, this.tab)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
|
|
@ -79,6 +79,18 @@
|
||||||
:in-profile="true"
|
:in-profile="true"
|
||||||
:footer-slipgate="footerRef"
|
:footer-slipgate="footerRef"
|
||||||
/>
|
/>
|
||||||
|
<Timeline
|
||||||
|
key="replies"
|
||||||
|
:label="$t('user_card.replies')"
|
||||||
|
:count="user.statuses_count"
|
||||||
|
:embedded="true"
|
||||||
|
:title="$t('user_card.replies')"
|
||||||
|
:timeline="replies"
|
||||||
|
timeline-name="replies"
|
||||||
|
:user-id="userId"
|
||||||
|
:in-profile="true"
|
||||||
|
:footer-slipgate="footerRef"
|
||||||
|
/>
|
||||||
<div
|
<div
|
||||||
v-if="followsTabVisible"
|
v-if="followsTabVisible"
|
||||||
key="followees"
|
key="followees"
|
||||||
|
@ -109,7 +121,6 @@
|
||||||
<Timeline
|
<Timeline
|
||||||
key="media"
|
key="media"
|
||||||
:label="$t('user_card.media')"
|
:label="$t('user_card.media')"
|
||||||
:disabled="!media.visibleStatuses.length"
|
|
||||||
:embedded="true"
|
:embedded="true"
|
||||||
:title="$t('user_card.media')"
|
:title="$t('user_card.media')"
|
||||||
timeline-name="media"
|
timeline-name="media"
|
||||||
|
@ -122,7 +133,7 @@
|
||||||
v-if="isUs"
|
v-if="isUs"
|
||||||
key="favorites"
|
key="favorites"
|
||||||
:label="$t('user_card.favorites')"
|
:label="$t('user_card.favorites')"
|
||||||
:disabled="!favorites.visibleStatuses.length"
|
:disabled="!isUs"
|
||||||
:embedded="true"
|
:embedded="true"
|
||||||
:title="$t('user_card.favorites')"
|
:title="$t('user_card.favorites')"
|
||||||
timeline-name="favorites"
|
timeline-name="favorites"
|
||||||
|
|
|
@ -98,7 +98,6 @@
|
||||||
"features_panel": {
|
"features_panel": {
|
||||||
"media_proxy": "Proxy per multimèdia",
|
"media_proxy": "Proxy per multimèdia",
|
||||||
"scope_options": "Opcions d'abast",
|
"scope_options": "Opcions d'abast",
|
||||||
"shout": "Altaveu",
|
|
||||||
"text_limit": "Límit de text",
|
"text_limit": "Límit de text",
|
||||||
"title": "Funcionalitats",
|
"title": "Funcionalitats",
|
||||||
"upload_limit": "Límit de càrrega",
|
"upload_limit": "Límit de càrrega",
|
||||||
|
@ -400,7 +399,7 @@
|
||||||
"conversation_display_linear": "Estil linear",
|
"conversation_display_linear": "Estil linear",
|
||||||
"conversation_display_tree": "Estil d'arbre",
|
"conversation_display_tree": "Estil d'arbre",
|
||||||
"conversation_other_replies_button": "Mostra el botó \"altres respostes\"",
|
"conversation_other_replies_button": "Mostra el botó \"altres respostes\"",
|
||||||
"conversation_other_replies_button_below": "Apunts a sota",
|
"conversation_other_replies_button_below": "Apunts de sota",
|
||||||
"conversation_other_replies_button_inside": "Apunts interiors",
|
"conversation_other_replies_button_inside": "Apunts interiors",
|
||||||
"current_avatar": "El teu avatar actual",
|
"current_avatar": "El teu avatar actual",
|
||||||
"current_mascot": "La teva mascota actual",
|
"current_mascot": "La teva mascota actual",
|
||||||
|
@ -461,6 +460,8 @@
|
||||||
"hide_muted_threads": "Amaga fils silenciats",
|
"hide_muted_threads": "Amaga fils silenciats",
|
||||||
"hide_post_stats": "Amaga les estadístiques dels apunts (p. ex. el número de favorits)",
|
"hide_post_stats": "Amaga les estadístiques dels apunts (p. ex. el número de favorits)",
|
||||||
"hide_shoutbox": "Amaga la casella de gàbia de grills",
|
"hide_shoutbox": "Amaga la casella de gàbia de grills",
|
||||||
|
"hide_site_favicon": "Amaga el favicon de l'instància en el panell superior",
|
||||||
|
"hide_site_name": "Amaga el nom de l'instància en el panell superior",
|
||||||
"hide_threads_with_blocked_users": "Amaga els fils mencionant usuaris bloquejats",
|
"hide_threads_with_blocked_users": "Amaga els fils mencionant usuaris bloquejats",
|
||||||
"hide_user_stats": "Amaga les estadístiques de l'usuari (p. ex. el número de seguidors)",
|
"hide_user_stats": "Amaga les estadístiques de l'usuari (p. ex. el número de seguidors)",
|
||||||
"hide_wallpaper": "Amagar el fons de l'instància",
|
"hide_wallpaper": "Amagar el fons de l'instància",
|
||||||
|
@ -546,13 +547,13 @@
|
||||||
"notification_setting_hide_notification_contents": "Amagar el remitent i els continguts de les notificacions push",
|
"notification_setting_hide_notification_contents": "Amagar el remitent i els continguts de les notificacions push",
|
||||||
"notification_setting_privacy": "Privacitat",
|
"notification_setting_privacy": "Privacitat",
|
||||||
"notification_visibility": "Tipus de notificacions a mostrar",
|
"notification_visibility": "Tipus de notificacions a mostrar",
|
||||||
"notification_visibility_emoji_reactions": "reacciona",
|
"notification_visibility_emoji_reactions": "reaccionen",
|
||||||
"notification_visibility_follows": "em segueix",
|
"notification_visibility_follows": "em segueixen",
|
||||||
"notification_visibility_likes": "m'afavoreix",
|
"notification_visibility_likes": "m'afavoreixen",
|
||||||
"notification_visibility_mentions": "em menciona",
|
"notification_visibility_mentions": "em mencionen",
|
||||||
"notification_visibility_moves": "es mou",
|
"notification_visibility_moves": "usuari es mou",
|
||||||
"notification_visibility_polls": "finalitza una enquesta que he votat",
|
"notification_visibility_polls": "finalitza una enquesta que he votat",
|
||||||
"notification_visibility_repeats": "em repeteix",
|
"notification_visibility_repeats": "em repeteixen",
|
||||||
"notifications": "Notificacions",
|
"notifications": "Notificacions",
|
||||||
"nsfw_clickthrough": "Amaga els Mèdia sensibles/NSFW",
|
"nsfw_clickthrough": "Amaga els Mèdia sensibles/NSFW",
|
||||||
"oauth_tokens": "Codis OAuth",
|
"oauth_tokens": "Codis OAuth",
|
||||||
|
@ -613,7 +614,10 @@
|
||||||
"settings": "Configuració",
|
"settings": "Configuració",
|
||||||
"show_admin_badge": "Mostra l'insígnia \"Administrador\" en el meu perfil",
|
"show_admin_badge": "Mostra l'insígnia \"Administrador\" en el meu perfil",
|
||||||
"show_moderator_badge": "Mostra l'insígnia \"Moderador\" en el meu perfil",
|
"show_moderator_badge": "Mostra l'insígnia \"Moderador\" en el meu perfil",
|
||||||
|
"show_nav_shortcuts": "Mostra els accessos directes addicionals en el panell superior",
|
||||||
|
"show_panel_nav_shortcuts": "Mostra els accessos directes de navegació de la línia de temps en el panell superior",
|
||||||
"show_scrollbars": "Mostra les barres de desplaçament de la columna lateral",
|
"show_scrollbars": "Mostra les barres de desplaçament de la columna lateral",
|
||||||
|
"show_wider_shortcuts": "Mostra més separats els accessos directes del panell superior",
|
||||||
"show_yous": "Mostra (Tu)s",
|
"show_yous": "Mostra (Tu)s",
|
||||||
"stop_gifs": "Pausa les imatges animades fins que hi passis el cursor per sobre",
|
"stop_gifs": "Pausa les imatges animades fins que hi passis el cursor per sobre",
|
||||||
"streaming": "Mostra automàticament els nous apunts quan et desplacis a la part superior",
|
"streaming": "Mostra automàticament els nous apunts quan et desplacis a la part superior",
|
||||||
|
|
|
@ -98,7 +98,6 @@
|
||||||
"features_panel": {
|
"features_panel": {
|
||||||
"media_proxy": "Media proxy",
|
"media_proxy": "Media proxy",
|
||||||
"scope_options": "Scope options",
|
"scope_options": "Scope options",
|
||||||
"shout": "Shoutbox",
|
|
||||||
"text_limit": "Text limit",
|
"text_limit": "Text limit",
|
||||||
"title": "Features",
|
"title": "Features",
|
||||||
"upload_limit": "Upload limit",
|
"upload_limit": "Upload limit",
|
||||||
|
@ -280,11 +279,14 @@
|
||||||
"text/plain": "Plain text",
|
"text/plain": "Plain text",
|
||||||
"text/x.misskeymarkdown": "MFM"
|
"text/x.misskeymarkdown": "MFM"
|
||||||
},
|
},
|
||||||
"content_warning": "Subject (optional)",
|
"content_warning": "Content Warning (optional)",
|
||||||
"default": "Just arrived at Luna Nova Academy",
|
"default": "Just arrived at Luna Nova Academy",
|
||||||
"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.",
|
||||||
"empty_status_error": "Can't send a post with no content and no files",
|
"empty_status_error": "Can't send a post with no content and no files",
|
||||||
|
"edit_status": "Edit Status",
|
||||||
|
"edit_remote_warning": "Other instances may not support edits!",
|
||||||
|
"edit_unsupported_warning": "Polls and mentions will not be changed by editing.",
|
||||||
"media_description": "Media description",
|
"media_description": "Media description",
|
||||||
"media_description_error": "Failed to update media, try again",
|
"media_description_error": "Failed to update media, try again",
|
||||||
"media_not_sensitive_warning": "You have a Content Warning, but the attachments are not marked as sensitive!",
|
"media_not_sensitive_warning": "You have a Content Warning, but the attachments are not marked as sensitive!",
|
||||||
|
@ -314,7 +316,7 @@
|
||||||
"email": "Email",
|
"email": "Email",
|
||||||
"email_language": "In which language do you want to receive emails from the server?",
|
"email_language": "In which language do you want to receive emails from the server?",
|
||||||
"fullname": "Display name",
|
"fullname": "Display name",
|
||||||
"fullname_placeholder": "e.g. Lain Iwakura",
|
"fullname_placeholder": "e.g. Atsuko Kagari",
|
||||||
"new_captcha": "Click the image to get a new captcha",
|
"new_captcha": "Click the image to get a new captcha",
|
||||||
"password_confirm": "Password confirmation",
|
"password_confirm": "Password confirmation",
|
||||||
"reason": "Reason to register",
|
"reason": "Reason to register",
|
||||||
|
@ -322,7 +324,7 @@
|
||||||
"register": "Register",
|
"register": "Register",
|
||||||
"registration": "Registration",
|
"registration": "Registration",
|
||||||
"token": "Invite token",
|
"token": "Invite token",
|
||||||
"username_placeholder": "e.g. lain",
|
"username_placeholder": "e.g. akko",
|
||||||
"validations": {
|
"validations": {
|
||||||
"email_required": "cannot be left blank",
|
"email_required": "cannot be left blank",
|
||||||
"fullname_required": "cannot be left blank",
|
"fullname_required": "cannot be left blank",
|
||||||
|
@ -393,9 +395,19 @@
|
||||||
"changed_password": "Password changed successfully!",
|
"changed_password": "Password changed successfully!",
|
||||||
"chatMessageRadius": "Chat message",
|
"chatMessageRadius": "Chat message",
|
||||||
"checkboxRadius": "Checkboxes",
|
"checkboxRadius": "Checkboxes",
|
||||||
"collapse_subject": "Collapse posts with subjects",
|
"collapse_subject": "Collapse posts with content warnings",
|
||||||
|
"columns": "Columns",
|
||||||
"composing": "Composing",
|
"composing": "Composing",
|
||||||
|
"confirm_dialogs": "Require confirmation for:",
|
||||||
|
"confirm_dialogs_approve_follow": "Accepting a follow request",
|
||||||
|
"confirm_dialogs_block": "Blocking someone",
|
||||||
|
"confirm_dialogs_delete": "Deleting a post",
|
||||||
|
"confirm_dialogs_deny_follow": "Rejecting a follow request",
|
||||||
|
"confirm_dialogs_mute": "Muting someone",
|
||||||
|
"confirm_dialogs_repeat": "Repeating a post",
|
||||||
|
"confirm_dialogs_unfollow": "Unfollowing someone",
|
||||||
"confirm_new_password": "Confirm new password",
|
"confirm_new_password": "Confirm new password",
|
||||||
|
"confirmation_dialogs": "Confirmation options",
|
||||||
"conversation_display": "Conversation display style",
|
"conversation_display": "Conversation display style",
|
||||||
"conversation_display_linear": "Linear-style",
|
"conversation_display_linear": "Linear-style",
|
||||||
"conversation_display_tree": "Tree-style",
|
"conversation_display_tree": "Tree-style",
|
||||||
|
@ -427,8 +439,8 @@
|
||||||
"backup_settings_theme": "Backup settings and theme to file",
|
"backup_settings_theme": "Backup settings and theme to file",
|
||||||
"errors": {
|
"errors": {
|
||||||
"file_slightly_new": "File minor version is different, some settings might not load",
|
"file_slightly_new": "File minor version is different, some settings might not load",
|
||||||
"file_too_new": "Incompatile major version: {fileMajor}, this PleromaFE (settings ver {feMajor}) is too old to handle it",
|
"file_too_new": "Incompatible major version: {fileMajor}, this PleromaFE (settings ver {feMajor}) is too old to handle it",
|
||||||
"file_too_old": "Incompatile major version: {fileMajor}, file version is too old and not supported (min. set. ver. {feMajor})",
|
"file_too_old": "Incompatible major version: {fileMajor}, file version is too old and not supported (min. set. ver. {feMajor})",
|
||||||
"invalid_file": "The selected file is not a supported Pleroma settings backup. No changes were made."
|
"invalid_file": "The selected file is not a supported Pleroma settings backup. No changes were made."
|
||||||
},
|
},
|
||||||
"restore_settings": "Restore settings from file"
|
"restore_settings": "Restore settings from file"
|
||||||
|
@ -521,7 +533,7 @@
|
||||||
"more_settings": "More settings",
|
"more_settings": "More settings",
|
||||||
"move_account": "Move account",
|
"move_account": "Move account",
|
||||||
"move_account_error": "Error moving account: {error}",
|
"move_account_error": "Error moving account: {error}",
|
||||||
"move_account_notes": "If you want to move the account somewhere else, you must go to your target account and add an alias pointing here.",
|
"move_account_notes": "If you want to move this account somewhere else, you must go to your target account and add an alias pointing here.",
|
||||||
"move_account_target": "Target account (e.g. {example})",
|
"move_account_target": "Target account (e.g. {example})",
|
||||||
"moved_account": "Account is moved.",
|
"moved_account": "Account is moved.",
|
||||||
"mute_bot_posts": "Mute bot posts",
|
"mute_bot_posts": "Mute bot posts",
|
||||||
|
@ -605,7 +617,7 @@
|
||||||
"security": "Security",
|
"security": "Security",
|
||||||
"security_tab": "Security",
|
"security_tab": "Security",
|
||||||
"sensitive_by_default": "Mark posts as sensitive by default",
|
"sensitive_by_default": "Mark posts as sensitive by default",
|
||||||
"sensitive_if_subject": "Automatically mark images as sensitive if a subject line is specified",
|
"sensitive_if_subject": "Automatically mark images as sensitive if a content warning is specified",
|
||||||
"set_new_avatar": "Set new avatar",
|
"set_new_avatar": "Set new avatar",
|
||||||
"set_new_mascot": "Set new mascot",
|
"set_new_mascot": "Set new mascot",
|
||||||
"set_new_profile_background": "Set new profile background",
|
"set_new_profile_background": "Set new profile background",
|
||||||
|
@ -616,6 +628,7 @@
|
||||||
"show_admin_badge": "Show \"Admin\" badge in my profile",
|
"show_admin_badge": "Show \"Admin\" badge in my profile",
|
||||||
"show_moderator_badge": "Show \"Moderator\" badge in my profile",
|
"show_moderator_badge": "Show \"Moderator\" badge in my profile",
|
||||||
"show_nav_shortcuts": "Show extra navigation shortcuts in top panel",
|
"show_nav_shortcuts": "Show extra navigation shortcuts in top panel",
|
||||||
|
"show_panel_nav_shortcuts": "Show timeline navigation shortcuts at the top of the panel",
|
||||||
"show_scrollbars": "Show side column's scrollbars",
|
"show_scrollbars": "Show side column's scrollbars",
|
||||||
"show_wider_shortcuts": "Show wider gap between top panel shortcuts",
|
"show_wider_shortcuts": "Show wider gap between top panel shortcuts",
|
||||||
"show_yous": "Show (You)s",
|
"show_yous": "Show (You)s",
|
||||||
|
@ -767,9 +780,9 @@
|
||||||
"use_source": "New version"
|
"use_source": "New version"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"subject_input_always_show": "Always show subject field",
|
"subject_input_always_show": "Always show content warning field",
|
||||||
"subject_line_behavior": "Copy subject when replying",
|
"subject_line_behavior": "Copy content warning when replying",
|
||||||
"subject_line_email": "Like email: \"re: subject\"",
|
"subject_line_email": "Like email: \"re: warning\"",
|
||||||
"subject_line_mastodon": "Like mastodon: copy as is",
|
"subject_line_mastodon": "Like mastodon: copy as is",
|
||||||
"subject_line_noop": "Do not copy",
|
"subject_line_noop": "Do not copy",
|
||||||
"text": "Text",
|
"text": "Text",
|
||||||
|
@ -783,7 +796,8 @@
|
||||||
"third_column_mode_postform": "Main post form and navigation",
|
"third_column_mode_postform": "Main post form and navigation",
|
||||||
"token": "Token",
|
"token": "Token",
|
||||||
"tooltipRadius": "Tooltips/alerts",
|
"tooltipRadius": "Tooltips/alerts",
|
||||||
"tree_advanced": "Allow more flexible navigation in tree view",
|
"translation_language": "Automatic Translation Language",
|
||||||
|
"tree_advanced": "Display extra buttons to open and close reply chains in threads",
|
||||||
"tree_fade_ancestors": "Display ancestors of the current post in faint text",
|
"tree_fade_ancestors": "Display ancestors of the current post in faint text",
|
||||||
"type_domains_to_mute": "Search domains to mute",
|
"type_domains_to_mute": "Search domains to mute",
|
||||||
"upload_a_photo": "Upload a photo",
|
"upload_a_photo": "Upload a photo",
|
||||||
|
@ -793,6 +807,7 @@
|
||||||
"use_contain_fit": "Don't crop the attachment in thumbnails",
|
"use_contain_fit": "Don't crop the attachment in thumbnails",
|
||||||
"use_one_click_nsfw": "Open NSFW attachments with just one click",
|
"use_one_click_nsfw": "Open NSFW attachments with just one click",
|
||||||
"user_mutes": "Users",
|
"user_mutes": "Users",
|
||||||
|
"user_profile_default_tab": "Default Tab on User Profile",
|
||||||
"user_profiles": "User Profiles",
|
"user_profiles": "User Profiles",
|
||||||
"user_settings": "User Settings",
|
"user_settings": "User Settings",
|
||||||
"valid_until": "Valid until",
|
"valid_until": "Valid until",
|
||||||
|
@ -818,12 +833,19 @@
|
||||||
"copy_link": "Copy link to post",
|
"copy_link": "Copy link to post",
|
||||||
"delete": "Delete post",
|
"delete": "Delete post",
|
||||||
"delete_confirm": "Do you really want to delete this post?",
|
"delete_confirm": "Do you really want to delete this post?",
|
||||||
|
"delete_confirm_accept_button": "Yes, delete it",
|
||||||
|
"delete_confirm_cancel_button": "No, keep it",
|
||||||
|
"delete_confirm_title": "Confirm deletion",
|
||||||
|
"edit": "Edit",
|
||||||
|
"edited_at": "Edited {time}",
|
||||||
|
"edit_history": "Edit History",
|
||||||
|
"edit_history_modal_title": "Edited {historyCount} time | Edited {historyCount} times",
|
||||||
"expand": "Expand",
|
"expand": "Expand",
|
||||||
"external_source": "External source",
|
"external_source": "External source",
|
||||||
"favorites": "Favorites",
|
"favorites": "Favorites",
|
||||||
"hide_attachment": "Hide attachment",
|
"hide_attachment": "Hide attachment",
|
||||||
"hide_content": "Hide content",
|
"hide_content": "Hide content",
|
||||||
"hide_full_subject": "Hide full subject",
|
"hide_full_subject": "Hide full content warning",
|
||||||
"many_attachments": "Post has {number} attachment | Post has {number} attachments",
|
"many_attachments": "Post has {number} attachment | Post has {number} attachments",
|
||||||
"mentions": "Mentions",
|
"mentions": "Mentions",
|
||||||
"move_down": "Shift attachment right",
|
"move_down": "Shift attachment right",
|
||||||
|
@ -831,32 +853,39 @@
|
||||||
"mute_conversation": "Mute conversation",
|
"mute_conversation": "Mute conversation",
|
||||||
"nsfw": "NSFW",
|
"nsfw": "NSFW",
|
||||||
"open_gallery": "Open gallery",
|
"open_gallery": "Open gallery",
|
||||||
|
"override_translation_source_language": "Override source language",
|
||||||
"pin": "Pin on profile",
|
"pin": "Pin on profile",
|
||||||
"pinned": "Pinned",
|
"pinned": "Pinned",
|
||||||
"plus_more": "+{number} more",
|
"plus_more": "+{number} more",
|
||||||
"remove_attachment": "Remove attachment",
|
"remove_attachment": "Remove attachment",
|
||||||
|
"repeat_confirm": "Do you really want to repeat this post?",
|
||||||
|
"repeat_confirm_accept_button": "Yes, repeat it",
|
||||||
|
"repeat_confirm_cancel_button": "No, don't repeat",
|
||||||
|
"repeat_confirm_title": "Confirm repeat",
|
||||||
"repeats": "Repeats",
|
"repeats": "Repeats",
|
||||||
"replies_list": "Replies:",
|
"replies_list": "Replies:",
|
||||||
"replies_list_with_others": "Replies (+{numReplies} other): | Replies (+{numReplies} others):",
|
"replies_list_with_others": "View {numReplies} more reply | View {numReplies} more replies",
|
||||||
"reply_to": "Reply to",
|
"reply_to": "Reply to",
|
||||||
"show_all_attachments": "Show all attachments",
|
"show_all_attachments": "Show all attachments",
|
||||||
"show_all_conversation": "Show full conversation ({numStatus} other post) | Show full conversation ({numStatus} other posts)",
|
"show_all_conversation": "Show full conversation ({numStatus} other post) | Show full conversation ({numStatus} other posts)",
|
||||||
"show_all_conversation_with_icon": "{icon} {text}",
|
"show_all_conversation_with_icon": "{icon} {text}",
|
||||||
"show_attachment_description": "Preview description (open attachment for full description)",
|
"show_attachment_description": "Preview description (open attachment for full description)",
|
||||||
"show_attachment_in_modal": "Show in media modal",
|
"show_attachment_in_modal": "Show attachment in a window",
|
||||||
"show_content": "Show content",
|
"show_content": "Show content",
|
||||||
"show_full_subject": "Show full subject",
|
"show_full_subject": "Show full content warning",
|
||||||
"show_only_conversation_under_this": "Only show replies to this post",
|
"show_only_conversation_under_this": "Only show replies to this post",
|
||||||
"status_deleted": "This post was deleted",
|
"status_deleted": "This post was deleted",
|
||||||
"status_unavailable": "Post unavailable",
|
"status_unavailable": "Post unavailable",
|
||||||
"thread_follow": "See the remaining part of this thread ({numStatus} post in total) | See the remaining part of this thread ({numStatus} posts in total)",
|
"thread_follow": "View {numStatus} more reply | View {numStatus} more replies",
|
||||||
"thread_follow_with_icon": "{icon} {text}",
|
"thread_follow_with_icon": "{icon} {text}",
|
||||||
"thread_hide": "Hide this thread",
|
"thread_hide": "Hide this thread",
|
||||||
"thread_muted": "Thread muted",
|
"thread_muted": "Thread muted",
|
||||||
"thread_muted_and_words": ", has words:",
|
"thread_muted_and_words": ", has words:",
|
||||||
"thread_show": "Show this thread",
|
"thread_show": "Show this thread",
|
||||||
"thread_show_full": "Show everything under this thread ({numStatus} post in total, max depth {depth}) | Show everything under this thread ({numStatus} posts in total, max depth {depth})",
|
"thread_show_full": "Show {numStatus} reply | Show all {numStatus} replies",
|
||||||
"thread_show_full_with_icon": "{icon} {text}",
|
"thread_show_full_with_icon": "{icon} {text}",
|
||||||
|
"translate": "Translate",
|
||||||
|
"translated_from": "Translated from {language}",
|
||||||
"unbookmark": "Unbookmark",
|
"unbookmark": "Unbookmark",
|
||||||
"unmute_conversation": "Unmute conversation",
|
"unmute_conversation": "Unmute conversation",
|
||||||
"unpin": "Unpin from profile",
|
"unpin": "Unpin from profile",
|
||||||
|
@ -899,6 +928,9 @@
|
||||||
"socket_reconnected": "Realtime connection established",
|
"socket_reconnected": "Realtime connection established",
|
||||||
"up_to_date": "Up-to-date"
|
"up_to_date": "Up-to-date"
|
||||||
},
|
},
|
||||||
|
"toast": {
|
||||||
|
"no_translation_target_set": "No translation target language set - this may fail. Please set a target language in your settings."
|
||||||
|
},
|
||||||
"tool_tip": {
|
"tool_tip": {
|
||||||
"accept_follow_request": "Accept follow request",
|
"accept_follow_request": "Accept follow request",
|
||||||
"add_reaction": "Add Reaction",
|
"add_reaction": "Add Reaction",
|
||||||
|
@ -947,12 +979,24 @@
|
||||||
"strip_media": "Remove media from posts"
|
"strip_media": "Remove media from posts"
|
||||||
},
|
},
|
||||||
"approve": "Approve",
|
"approve": "Approve",
|
||||||
|
"approve_confirm": "Are you sure you want to let this user follow you?",
|
||||||
|
"approve_confirm_accept_button": "Yes, accept",
|
||||||
|
"approve_confirm_cancel_button": "No, cancel",
|
||||||
|
"approve_confirm_title": "Approve follow request",
|
||||||
"block": "Block",
|
"block": "Block",
|
||||||
|
"block_confirm": "Are you sure you want to block {user}?",
|
||||||
|
"block_confirm_accept_button": "Yes, block",
|
||||||
|
"block_confirm_cancel_button": "No, don't block",
|
||||||
|
"block_confirm_title": "Block user",
|
||||||
"block_progress": "Blocking…",
|
"block_progress": "Blocking…",
|
||||||
"blocked": "Blocked!",
|
"blocked": "Blocked!",
|
||||||
"bot": "Bot",
|
"bot": "Bot",
|
||||||
"deactivated": "Deactivated",
|
"deactivated": "Deactivated",
|
||||||
"deny": "Deny",
|
"deny": "Deny",
|
||||||
|
"deny_confirm": "Are you sure you want to deny this user's follow request?",
|
||||||
|
"deny_confirm_accept_button": "Yes, deny",
|
||||||
|
"deny_confirm_cancel_button": "No, cancel",
|
||||||
|
"deny_confirm_title": "Deny follow request",
|
||||||
"domain_muted": "Unblock domain",
|
"domain_muted": "Unblock domain",
|
||||||
"edit_profile": "Edit profile",
|
"edit_profile": "Edit profile",
|
||||||
"favorites": "Favorites",
|
"favorites": "Favorites",
|
||||||
|
@ -978,18 +1022,27 @@
|
||||||
"mention": "Mention",
|
"mention": "Mention",
|
||||||
"message": "Message",
|
"message": "Message",
|
||||||
"mute": "Mute",
|
"mute": "Mute",
|
||||||
|
"mute_confirm": "Are you sure you want to mute {user}?",
|
||||||
|
"mute_confirm_accept_button": "Yes, mute",
|
||||||
|
"mute_confirm_cancel_button": "No, don't mute",
|
||||||
|
"mute_confirm_title": "Mute user",
|
||||||
"mute_domain": "Block domain",
|
"mute_domain": "Block domain",
|
||||||
"mute_progress": "Muting…",
|
"mute_progress": "Muting…",
|
||||||
"muted": "Muted",
|
"muted": "Muted",
|
||||||
"note": "Private note",
|
"note": "Private note",
|
||||||
"per_day": "per day",
|
"per_day": "per day",
|
||||||
"remote_follow": "Remote follow",
|
"remote_follow": "Remote follow",
|
||||||
|
"replies": "With Replies",
|
||||||
"report": "Report",
|
"report": "Report",
|
||||||
"show_repeats": "Show repeats",
|
"show_repeats": "Show repeats",
|
||||||
"statuses": "Posts",
|
"statuses": "Posts",
|
||||||
"subscribe": "Subscribe",
|
"subscribe": "Subscribe",
|
||||||
"unblock": "Unblock",
|
"unblock": "Unblock",
|
||||||
"unblock_progress": "Unblocking…",
|
"unblock_progress": "Unblocking…",
|
||||||
|
"unfollow_confirm": "Are you sure you want to unfollow {user}?",
|
||||||
|
"unfollow_confirm_accept_button": "Yes, unfollow",
|
||||||
|
"unfollow_confirm_cancel_button": "No, don't unfollow",
|
||||||
|
"unfollow_confirm_title": "Unfollow user",
|
||||||
"unmute": "Unmute",
|
"unmute": "Unmute",
|
||||||
"unmute_progress": "Unmuting…",
|
"unmute_progress": "Unmuting…",
|
||||||
"unsubscribe": "Unsubscribe"
|
"unsubscribe": "Unsubscribe"
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
{
|
{
|
||||||
"about": {
|
"about": {
|
||||||
|
"bubble_instances": "Instancias de burbuja local",
|
||||||
|
"bubble_instances_description": "Instancias elegidas por los/las adminstradores/as para representar el área local de esta instancia",
|
||||||
"mrf": {
|
"mrf": {
|
||||||
"federation": "Federación",
|
"federation": "Federación",
|
||||||
"keyword": {
|
"keyword": {
|
||||||
|
@ -137,7 +139,8 @@
|
||||||
"direct": "Directo",
|
"direct": "Directo",
|
||||||
"local": "Local - sólo tu instancia puede ver esta publicación",
|
"local": "Local - sólo tu instancia puede ver esta publicación",
|
||||||
"private": "Sólo para seguidores",
|
"private": "Sólo para seguidores",
|
||||||
"public": "Público"
|
"public": "Público",
|
||||||
|
"unlisted": "No listado"
|
||||||
},
|
},
|
||||||
"show_less": "Mostrar menos",
|
"show_less": "Mostrar menos",
|
||||||
"show_more": "Mostrar más",
|
"show_more": "Mostrar más",
|
||||||
|
@ -164,6 +167,8 @@
|
||||||
"lists": {
|
"lists": {
|
||||||
"create": "Crear",
|
"create": "Crear",
|
||||||
"delete": "Eliminar lista",
|
"delete": "Eliminar lista",
|
||||||
|
"lists": "Listas",
|
||||||
|
"new": "Nueva Lista",
|
||||||
"save": "Guardar cambios",
|
"save": "Guardar cambios",
|
||||||
"search": "Buscar cuentas",
|
"search": "Buscar cuentas",
|
||||||
"title": "Título de la lista"
|
"title": "Título de la lista"
|
||||||
|
@ -193,6 +198,7 @@
|
||||||
"nav": {
|
"nav": {
|
||||||
"about": "Acerca de",
|
"about": "Acerca de",
|
||||||
"administration": "Administración",
|
"administration": "Administración",
|
||||||
|
"announcements": "Anuncios",
|
||||||
"back": "Volver",
|
"back": "Volver",
|
||||||
"bookmarks": "Marcadores",
|
"bookmarks": "Marcadores",
|
||||||
"chats": "Chats",
|
"chats": "Chats",
|
||||||
|
@ -200,13 +206,16 @@
|
||||||
"friend_requests": "Solicitudes de seguimiento",
|
"friend_requests": "Solicitudes de seguimiento",
|
||||||
"home_timeline": "Línea temporal personal",
|
"home_timeline": "Línea temporal personal",
|
||||||
"interactions": "Interacciones",
|
"interactions": "Interacciones",
|
||||||
|
"lists": "Listas",
|
||||||
"mentions": "Menciones",
|
"mentions": "Menciones",
|
||||||
"preferences": "Preferencias",
|
"preferences": "Preferencias",
|
||||||
|
"public_timeline_description": "Publicaciones públicas de esta instancia",
|
||||||
"public_tl": "Línea temporal pública",
|
"public_tl": "Línea temporal pública",
|
||||||
"search": "Buscar",
|
"search": "Buscar",
|
||||||
"timeline": "Línea Temporal",
|
"timeline": "Línea Temporal",
|
||||||
"timelines": "Líneas de Tiempo",
|
"timelines": "Líneas de Tiempo",
|
||||||
"twkn": "Red Conocida",
|
"twkn": "Red Conocida",
|
||||||
|
"twkn_timeline_description": "Publicaciones de la red conocida",
|
||||||
"user_search": "Búsqueda de Usuarios",
|
"user_search": "Búsqueda de Usuarios",
|
||||||
"who_to_follow": "A quién seguir"
|
"who_to_follow": "A quién seguir"
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
{
|
{
|
||||||
"about": {
|
"about": {
|
||||||
|
"bubble_instances": "Les instances de la bulle locale",
|
||||||
|
"bubble_instances_description": "Des instances choisies par l'administration pour representer la région de cette instance",
|
||||||
"mrf": {
|
"mrf": {
|
||||||
"federation": "Fédération",
|
"federation": "Fédération",
|
||||||
"keyword": {
|
"keyword": {
|
||||||
|
@ -96,7 +98,6 @@
|
||||||
"features_panel": {
|
"features_panel": {
|
||||||
"media_proxy": "Proxy pièce-jointes",
|
"media_proxy": "Proxy pièce-jointes",
|
||||||
"scope_options": "Options de visibilité",
|
"scope_options": "Options de visibilité",
|
||||||
"shout": "Shoutbox",
|
|
||||||
"text_limit": "Limite du texte",
|
"text_limit": "Limite du texte",
|
||||||
"title": "Fonctionnalités",
|
"title": "Fonctionnalités",
|
||||||
"upload_limit": "Limite de téléversement",
|
"upload_limit": "Limite de téléversement",
|
||||||
|
@ -136,6 +137,7 @@
|
||||||
},
|
},
|
||||||
"scope_in_timeline": {
|
"scope_in_timeline": {
|
||||||
"direct": "Direct",
|
"direct": "Direct",
|
||||||
|
"local": "Local - visible seulement sur cette instance",
|
||||||
"private": "Abonné·e·s uniquement",
|
"private": "Abonné·e·s uniquement",
|
||||||
"public": "Public",
|
"public": "Public",
|
||||||
"unlisted": "Non-listé"
|
"unlisted": "Non-listé"
|
||||||
|
@ -281,11 +283,11 @@
|
||||||
"default": "Je viens d'arriver au QG de la NERV",
|
"default": "Je viens d'arriver au QG de la NERV",
|
||||||
"direct_warning_to_all": "Ce message sera visible pour toutes les personnes mentionnées.",
|
"direct_warning_to_all": "Ce message sera visible pour toutes les personnes mentionnées.",
|
||||||
"direct_warning_to_first_only": "Ce message sera visible uniquement pour personnes mentionnées au début du message.",
|
"direct_warning_to_first_only": "Ce message sera visible uniquement pour personnes mentionnées au début du message.",
|
||||||
"empty_status_error": "Impossible de poster un statut vide sans pièces-jointes",
|
"empty_status_error": "Impossible de publier un statut vide sans pièces-jointes",
|
||||||
"media_description": "Description de la pièce-jointe",
|
"media_description": "Description de la pièce-jointe",
|
||||||
"media_description_error": "Échec de téléversement du media, essayez encore",
|
"media_description_error": "Échec de téléversement du media, essayez encore",
|
||||||
"media_not_sensitive_warning": "Il y a un avertissment, mais les pièces jointes ne sont pas marquées comme sensibles !",
|
"media_not_sensitive_warning": "Il y a un avertissment, mais les pièces jointes ne sont pas marquées comme sensibles !",
|
||||||
"new_status": "Poster un nouveau statut",
|
"new_status": "Nouveau statut",
|
||||||
"post": "Post",
|
"post": "Post",
|
||||||
"posting": "Envoi en cours",
|
"posting": "Envoi en cours",
|
||||||
"preview": "Prévisualisation",
|
"preview": "Prévisualisation",
|
||||||
|
@ -306,7 +308,7 @@
|
||||||
},
|
},
|
||||||
"registration": {
|
"registration": {
|
||||||
"bio": "Biographie",
|
"bio": "Biographie",
|
||||||
"bio_placeholder": "ex.\nSalut, je suis Lain\nJe suis une héroïne d'animation qui vit dans une banlieue japonaise. Vous me connaissez peut-être du Wired.",
|
"bio_placeholder": "ex :\nSalut, je me présente ici !\nJ’adore les animés et les jeux vidéos. J’espère qu'on peut être amis⋅ies !",
|
||||||
"captcha": "CAPTCHA",
|
"captcha": "CAPTCHA",
|
||||||
"email": "Courriel",
|
"email": "Courriel",
|
||||||
"email_language": "Dans quelle langue souhaitez-vous recevoir des courriels ?",
|
"email_language": "Dans quelle langue souhaitez-vous recevoir des courriels ?",
|
||||||
|
@ -458,6 +460,8 @@
|
||||||
"hide_muted_threads": "Masquer les fils de discussion silenciés",
|
"hide_muted_threads": "Masquer les fils de discussion silenciés",
|
||||||
"hide_post_stats": "Masquer les statistiques des messages (ex. le nombre de favoris)",
|
"hide_post_stats": "Masquer les statistiques des messages (ex. le nombre de favoris)",
|
||||||
"hide_shoutbox": "Cacher la shoutbox de l'instance",
|
"hide_shoutbox": "Cacher la shoutbox de l'instance",
|
||||||
|
"hide_site_favicon": "Ne pas afficher le favicon de l’instance dans le panneau supérieur",
|
||||||
|
"hide_site_name": "Ne pas afficher le nom de l'instance dans le panneau supérieur",
|
||||||
"hide_threads_with_blocked_users": "Masquer les fils qui mentionnent les personnes bloquées",
|
"hide_threads_with_blocked_users": "Masquer les fils qui mentionnent les personnes bloquées",
|
||||||
"hide_user_stats": "Masquer les statistiques de compte (ex. le nombre de suivis)",
|
"hide_user_stats": "Masquer les statistiques de compte (ex. le nombre de suivis)",
|
||||||
"hide_wallpaper": "Cacher le fond d'écran",
|
"hide_wallpaper": "Cacher le fond d'écran",
|
||||||
|
@ -576,6 +580,7 @@
|
||||||
"remove_alias": "Supprimer ce pseudo",
|
"remove_alias": "Supprimer ce pseudo",
|
||||||
"remove_backup": "Supprimer",
|
"remove_backup": "Supprimer",
|
||||||
"render_mfm": "Afficher le contenu Misskey Markdown",
|
"render_mfm": "Afficher le contenu Misskey Markdown",
|
||||||
|
"render_mfm_on_hover": "Rester sur du contenu MFM pour déclencher les animations",
|
||||||
"replies_in_timeline": "Réponses dans le flux",
|
"replies_in_timeline": "Réponses dans le flux",
|
||||||
"reply_visibility_all": "Montrer toutes les réponses",
|
"reply_visibility_all": "Montrer toutes les réponses",
|
||||||
"reply_visibility_following": "Afficher uniquement les réponses adressées à moi ou aux personnes que je suis",
|
"reply_visibility_following": "Afficher uniquement les réponses adressées à moi ou aux personnes que je suis",
|
||||||
|
@ -609,7 +614,10 @@
|
||||||
"settings": "Paramètres",
|
"settings": "Paramètres",
|
||||||
"show_admin_badge": "Afficher le badge d'Admin sur mon profil",
|
"show_admin_badge": "Afficher le badge d'Admin sur mon profil",
|
||||||
"show_moderator_badge": "Afficher le badge de Modo' sur mon profil",
|
"show_moderator_badge": "Afficher le badge de Modo' sur mon profil",
|
||||||
|
"show_nav_shortcuts": "Afficher plus de raccourcis de navigations dans le panneau supérieur",
|
||||||
|
"show_panel_nav_shortcuts": "Afficher les raccourcis de navigation du flux dans le panneau supérieur",
|
||||||
"show_scrollbars": "Afficher la barre de défilement",
|
"show_scrollbars": "Afficher la barre de défilement",
|
||||||
|
"show_wider_shortcuts": "Plus d'espace entre les raccourcis dans le panneau supérieur",
|
||||||
"show_yous": "Afficher « Vous : »",
|
"show_yous": "Afficher « Vous : »",
|
||||||
"stop_gifs": "N'animer les GIFS que lors du survol du curseur de la souris",
|
"stop_gifs": "N'animer les GIFS que lors du survol du curseur de la souris",
|
||||||
"streaming": "Charger automatiquement les nouveaux statuts lorsque vous êtes au haut de la page",
|
"streaming": "Charger automatiquement les nouveaux statuts lorsque vous êtes au haut de la page",
|
||||||
|
|
|
@ -23,8 +23,10 @@
|
||||||
"media_nsfw_desc": "このインスタンスでは、以下のインスタンスからの投稿に対して、メディアを閲覧注意に設定します:",
|
"media_nsfw_desc": "このインスタンスでは、以下のインスタンスからの投稿に対して、メディアを閲覧注意に設定します:",
|
||||||
"media_removal": "メディア除去",
|
"media_removal": "メディア除去",
|
||||||
"media_removal_desc": "このインスタンスでは、以下のインスタンスからの投稿に対して、メディアを除去します:",
|
"media_removal_desc": "このインスタンスでは、以下のインスタンスからの投稿に対して、メディアを除去します:",
|
||||||
|
"not_applicable": "なし",
|
||||||
"quarantine": "検疫",
|
"quarantine": "検疫",
|
||||||
"quarantine_desc": "このインスタンスでは、以下のインスタンスに対して公開投稿のみを送信します:",
|
"quarantine_desc": "このインスタンスでは、以下のインスタンスに投稿を送信しません",
|
||||||
|
"reason": "理由",
|
||||||
"reject": "拒否",
|
"reject": "拒否",
|
||||||
"reject_desc": "このインスタンスでは、以下のインスタンスからのメッセージを受け付けません:",
|
"reject_desc": "このインスタンスでは、以下のインスタンスからのメッセージを受け付けません:",
|
||||||
"simple_policies": "インスタンス固有のポリシー"
|
"simple_policies": "インスタンス固有のポリシー"
|
||||||
|
@ -33,7 +35,25 @@
|
||||||
"staff": "スタッフ"
|
"staff": "スタッフ"
|
||||||
},
|
},
|
||||||
"announcements": {
|
"announcements": {
|
||||||
"page_header": "お知らせ"
|
"all_day_prompt": "一日中",
|
||||||
|
"cancel_edit_action": "キャンセル",
|
||||||
|
"close_error": "閉じる",
|
||||||
|
"delete_action": "削除",
|
||||||
|
"edit_action": "更新",
|
||||||
|
"end_time_display": "{time}に終わる",
|
||||||
|
"end_time_prompt": "終了時間 ",
|
||||||
|
"inactive_message": "無効",
|
||||||
|
"mark_as_read_action": "読んだ",
|
||||||
|
"page_header": "お知らせ",
|
||||||
|
"post_action": "投稿",
|
||||||
|
"post_error": "エラーが発生しました: {error}",
|
||||||
|
"post_form_header": "お知らせ作成",
|
||||||
|
"post_placeholder": "コンテンツ",
|
||||||
|
"published_time_display": "{time}に告知されました",
|
||||||
|
"start_time_display": "{time}で始まる",
|
||||||
|
"start_time_prompt": "開始時間 ",
|
||||||
|
"submit_edit_action": "OK",
|
||||||
|
"title": "お知らせ"
|
||||||
},
|
},
|
||||||
"chats": {
|
"chats": {
|
||||||
"chats": "チャット一覧",
|
"chats": "チャット一覧",
|
||||||
|
@ -115,6 +135,13 @@
|
||||||
"admin": "管理者",
|
"admin": "管理者",
|
||||||
"moderator": "モデレーター"
|
"moderator": "モデレーター"
|
||||||
},
|
},
|
||||||
|
"scope_in_timeline": {
|
||||||
|
"direct": "ダイレクト",
|
||||||
|
"local": "ローカル:このインスタンスのユーザーしか見えません",
|
||||||
|
"private": "フォロワー限定",
|
||||||
|
"public": "公開",
|
||||||
|
"unlisted": "アンリステッド"
|
||||||
|
},
|
||||||
"show_less": "たたむ",
|
"show_less": "たたむ",
|
||||||
"show_more": "もっと見る",
|
"show_more": "もっと見る",
|
||||||
"submit": "送信",
|
"submit": "送信",
|
||||||
|
@ -137,6 +164,16 @@
|
||||||
"load_older": "古いインタラクションを見る",
|
"load_older": "古いインタラクションを見る",
|
||||||
"moves": "ユーザーの引っ越し"
|
"moves": "ユーザーの引っ越し"
|
||||||
},
|
},
|
||||||
|
"lists": {
|
||||||
|
"create": "作成",
|
||||||
|
"delete": "削除",
|
||||||
|
"following_only": "フォローしているユーザーのみ",
|
||||||
|
"lists": "リスト",
|
||||||
|
"new": "リスト作成",
|
||||||
|
"save": "OK",
|
||||||
|
"search": "ユーザー探索",
|
||||||
|
"title": "リスト名"
|
||||||
|
},
|
||||||
"login": {
|
"login": {
|
||||||
"authentication_code": "認証コード",
|
"authentication_code": "認証コード",
|
||||||
"description": "OAuthでログイン",
|
"description": "OAuthでログイン",
|
||||||
|
@ -150,12 +187,14 @@
|
||||||
"login": "ログイン",
|
"login": "ログイン",
|
||||||
"logout": "ログアウト",
|
"logout": "ログアウト",
|
||||||
"password": "パスワード",
|
"password": "パスワード",
|
||||||
"placeholder": "例: lain",
|
"placeholder": "例: user",
|
||||||
"recovery_code": "リカバリーコード",
|
"recovery_code": "リカバリーコード",
|
||||||
"register": "登録",
|
"register": "登録",
|
||||||
"username": "ユーザー名"
|
"username": "ユーザー名"
|
||||||
},
|
},
|
||||||
"media_modal": {
|
"media_modal": {
|
||||||
|
"counter": "{current} / {total}",
|
||||||
|
"hide": "閉じる",
|
||||||
"next": "次",
|
"next": "次",
|
||||||
"previous": "前"
|
"previous": "前"
|
||||||
},
|
},
|
||||||
|
@ -187,18 +226,19 @@
|
||||||
"who_to_follow": "おすすめユーザー"
|
"who_to_follow": "おすすめユーザー"
|
||||||
},
|
},
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"broken_favorite": "ステータスが見つかりません。探しています…",
|
"broken_favorite": "投稿が見つかりません。探しています…",
|
||||||
"error": "通知の取得に失敗しました: {0}",
|
"error": "通知の取得に失敗しました: {0}",
|
||||||
"favorited_you": "あなたのステータスがお気に入りされました",
|
"favorited_you": "投稿がお気に入りに登録されました",
|
||||||
"follow_request": "あなたをフォローしたいです",
|
"follow_request": "あなたをフォローしたいです",
|
||||||
"followed_you": "フォローされました",
|
"followed_you": "フォローされました",
|
||||||
"load_older": "古い通知をみる",
|
"load_older": "古い通知をみる",
|
||||||
"migrated_to": "インスタンスを引っ越しました",
|
"migrated_to": "インスタンスを引っ越しました",
|
||||||
"no_more_notifications": "通知はありません",
|
"no_more_notifications": "通知はありません",
|
||||||
"notifications": "通知",
|
"notifications": "通知",
|
||||||
|
"poll_ended": "投票終了",
|
||||||
"reacted_with": "{0} でリアクションしました",
|
"reacted_with": "{0} でリアクションしました",
|
||||||
"read": "読んだ!",
|
"read": "読んだ!",
|
||||||
"repeated_you": "あなたのステータスがリピートされました"
|
"repeated_you": "投稿がリピートされました"
|
||||||
},
|
},
|
||||||
"password_reset": {
|
"password_reset": {
|
||||||
"check_email": "パスワードをリセットするためのリンクが記載されたメールが届いているか確認してください。",
|
"check_email": "パスワードをリセットするためのリンクが記載されたメールが届いているか確認してください。",
|
||||||
|
@ -221,7 +261,7 @@
|
||||||
"multiple_choices": "複数選択式",
|
"multiple_choices": "複数選択式",
|
||||||
"not_enough_options": "相異なる選択肢が不足しています",
|
"not_enough_options": "相異なる選択肢が不足しています",
|
||||||
"option": "選択肢",
|
"option": "選択肢",
|
||||||
"people_voted_count": "{count} 人投票 | {count} 人投票",
|
"people_voted_count": "{count} 人投票",
|
||||||
"single_choice": "択一式",
|
"single_choice": "択一式",
|
||||||
"type": "投票の形式",
|
"type": "投票の形式",
|
||||||
"vote": "投票",
|
"vote": "投票",
|
||||||
|
@ -229,14 +269,15 @@
|
||||||
"votes_count": "{count} 票 | {count} 票"
|
"votes_count": "{count} 票 | {count} 票"
|
||||||
},
|
},
|
||||||
"post_status": {
|
"post_status": {
|
||||||
"account_not_locked_warning": "あなたのアカウントは {0} ではありません。あなたをフォローすれば、誰でも、フォロワー限定のステータスを読むことができます。",
|
"account_not_locked_warning": "あなたのアカウントは {0} ではありません。あなたをフォローすれば、誰でも、フォロワー限定の投稿を読むことができます。",
|
||||||
"account_not_locked_warning_link": "ロックされたアカウント",
|
"account_not_locked_warning_link": "ロックされたアカウント",
|
||||||
"attachments_sensitive": "ファイルをNSFWにする",
|
"attachments_sensitive": "ファイルをNSFWにする",
|
||||||
"content_type": {
|
"content_type": {
|
||||||
"text/bbcode": "BBCode",
|
"text/bbcode": "BBCode",
|
||||||
"text/html": "HTML",
|
"text/html": "HTML",
|
||||||
"text/markdown": "Markdown",
|
"text/markdown": "Markdown",
|
||||||
"text/plain": "プレーンテキスト"
|
"text/plain": "プレーンテキスト",
|
||||||
|
"text/x.misskeymarkdown": "MFM"
|
||||||
},
|
},
|
||||||
"content_warning": "説明 (省略可)",
|
"content_warning": "説明 (省略可)",
|
||||||
"default": "羽田空港に着きました。",
|
"default": "羽田空港に着きました。",
|
||||||
|
@ -245,6 +286,7 @@
|
||||||
"empty_status_error": "投稿内容を入力してください",
|
"empty_status_error": "投稿内容を入力してください",
|
||||||
"media_description": "メディアの説明",
|
"media_description": "メディアの説明",
|
||||||
"media_description_error": "メディアのアップロードに失敗しました。もう一度お試しください",
|
"media_description_error": "メディアのアップロードに失敗しました。もう一度お試しください",
|
||||||
|
"media_not_sensitive_warning": "注意: 説明が付けていますがNSFW警告が付けていません",
|
||||||
"new_status": "投稿する",
|
"new_status": "投稿する",
|
||||||
"post": "投稿",
|
"post": "投稿",
|
||||||
"posting": "投稿",
|
"posting": "投稿",
|
||||||
|
@ -258,6 +300,7 @@
|
||||||
"unlisted": "アンリステッド: 公開タイムラインに届きません"
|
"unlisted": "アンリステッド: 公開タイムラインに届きません"
|
||||||
},
|
},
|
||||||
"scope_notice": {
|
"scope_notice": {
|
||||||
|
"local": "このインスタンスのユーザーしか見えません",
|
||||||
"private": "この投稿は、あなたのフォロワーだけが、見ることができます",
|
"private": "この投稿は、あなたのフォロワーだけが、見ることができます",
|
||||||
"public": "この投稿は、誰でも見ることができます",
|
"public": "この投稿は、誰でも見ることができます",
|
||||||
"unlisted": "この投稿は、パブリックタイムラインと、接続しているすべてのネットワークには、表示されません"
|
"unlisted": "この投稿は、パブリックタイムラインと、接続しているすべてのネットワークには、表示されません"
|
||||||
|
@ -268,6 +311,7 @@
|
||||||
"bio_placeholder": "例:\nこんにちは。私は玲音。\n私はアニメのキャラクターで、日本の郊外に住んでいます。私をWiredで見たことがあるかもしれません。",
|
"bio_placeholder": "例:\nこんにちは。私は玲音。\n私はアニメのキャラクターで、日本の郊外に住んでいます。私をWiredで見たことがあるかもしれません。",
|
||||||
"captcha": "CAPTCHA",
|
"captcha": "CAPTCHA",
|
||||||
"email": "Eメール",
|
"email": "Eメール",
|
||||||
|
"email_language": "サーバーからのメールの言語",
|
||||||
"fullname": "スクリーンネーム",
|
"fullname": "スクリーンネーム",
|
||||||
"fullname_placeholder": "例: 岩倉玲音",
|
"fullname_placeholder": "例: 岩倉玲音",
|
||||||
"new_captcha": "文字が読めないときは、画像をクリックすると、新しい画像になります",
|
"new_captcha": "文字が読めないときは、画像をクリックすると、新しい画像になります",
|
||||||
|
@ -304,6 +348,17 @@
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"accent": "アクセント",
|
"accent": "アクセント",
|
||||||
|
"account_alias": "アカウントのエイリアス名",
|
||||||
|
"account_alias_table_head": "エイリアス名",
|
||||||
|
"account_backup": "アカウントのバックアップ",
|
||||||
|
"account_backup_description": "投稿やアカウント情報をダウンロードできますが、インポートすることがまだできません",
|
||||||
|
"account_backup_table_head": "バックアップ",
|
||||||
|
"account_privacy": "プライバシー",
|
||||||
|
"add_alias_error": "エイリアス名を参加できませんでした:{error}",
|
||||||
|
"add_backup": "バックアップ作成",
|
||||||
|
"add_backup_error": "バックアップを作成できませんでした:{error}",
|
||||||
|
"added_alias": "エイリアス名を参加しました",
|
||||||
|
"added_backup": "バックアップを作成しました",
|
||||||
"allow_following_move": "フォロー中のアカウントが引っ越したとき、自動フォローを許可する",
|
"allow_following_move": "フォロー中のアカウントが引っ越したとき、自動フォローを許可する",
|
||||||
"always_show_post_button": "投稿ボタンを常に表示",
|
"always_show_post_button": "投稿ボタンを常に表示",
|
||||||
"app_name": "アプリの名称",
|
"app_name": "アプリの名称",
|
||||||
|
@ -315,6 +370,7 @@
|
||||||
"avatarRadius": "アバター",
|
"avatarRadius": "アバター",
|
||||||
"avatar_size_instruction": "アバターの大きさは、150×150ピクセルか、それよりも大きくするといいです。",
|
"avatar_size_instruction": "アバターの大きさは、150×150ピクセルか、それよりも大きくするといいです。",
|
||||||
"background": "バックグラウンド",
|
"background": "バックグラウンド",
|
||||||
|
"backup_not_ready": "バックアップはまだ完成していません",
|
||||||
"bio": "プロフィール",
|
"bio": "プロフィール",
|
||||||
"block_export": "ブロックのエクスポート",
|
"block_export": "ブロックのエクスポート",
|
||||||
"block_export_button": "ブロックをCSVファイルにエクスポートする",
|
"block_export_button": "ブロックをCSVファイルにエクスポートする",
|
||||||
|
@ -337,9 +393,26 @@
|
||||||
"chatMessageRadius": "チャットメッセージ",
|
"chatMessageRadius": "チャットメッセージ",
|
||||||
"checkboxRadius": "チェックボックス",
|
"checkboxRadius": "チェックボックス",
|
||||||
"collapse_subject": "説明のある投稿をたたむ",
|
"collapse_subject": "説明のある投稿をたたむ",
|
||||||
|
"columns": "カラム",
|
||||||
"composing": "投稿",
|
"composing": "投稿",
|
||||||
|
"confirm_dialogs": "選択しているアクションは確認必要があります",
|
||||||
|
"confirm_dialogs_approve_follow": "フォローリクエストを受け入れること",
|
||||||
|
"confirm_dialogs_block": "ユーザーをブロックすること",
|
||||||
|
"confirm_dialogs_delete": "投稿を削除すること",
|
||||||
|
"confirm_dialogs_deny_follow": "フォローリクエストを断ること",
|
||||||
|
"confirm_dialogs_mute": "ユーザーをミュートすること",
|
||||||
|
"confirm_dialogs_repeat": "投稿をリピートすること",
|
||||||
|
"confirm_dialogs_unfollow": "フォローをやめること",
|
||||||
"confirm_new_password": "新しいパスワードの確認",
|
"confirm_new_password": "新しいパスワードの確認",
|
||||||
|
"confirmation_dialogs": "確認設定",
|
||||||
|
"conversation_display": "スレッドの表示モード",
|
||||||
|
"conversation_display_linear": "リニアー",
|
||||||
|
"conversation_display_tree": "ツリー",
|
||||||
|
"conversation_other_replies_button": "「別の返信」のボタンは",
|
||||||
|
"conversation_other_replies_button_below": "投稿の下",
|
||||||
|
"conversation_other_replies_button_inside": "投稿の中",
|
||||||
"current_avatar": "現在のアバター",
|
"current_avatar": "現在のアバター",
|
||||||
|
"current_mascot": "現在のマスコット",
|
||||||
"current_password": "現在のパスワード",
|
"current_password": "現在のパスワード",
|
||||||
"data_import_export_tab": "インポートとエクスポート",
|
"data_import_export_tab": "インポートとエクスポート",
|
||||||
"default_vis": "デフォルトの公開範囲",
|
"default_vis": "デフォルトの公開範囲",
|
||||||
|
@ -350,6 +423,8 @@
|
||||||
"disable_sticky_headers": "ヘッダーを追従させない",
|
"disable_sticky_headers": "ヘッダーを追従させない",
|
||||||
"discoverable": "検索などのサービスでこのアカウントを見つけることを許可する",
|
"discoverable": "検索などのサービスでこのアカウントを見つけることを許可する",
|
||||||
"domain_mutes": "ドメイン",
|
"domain_mutes": "ドメイン",
|
||||||
|
"download_backup": "ダウンロード",
|
||||||
|
"email_language": "メールの表示言語",
|
||||||
"emoji_reactions_on_timeline": "絵文字リアクションをタイムラインに表示",
|
"emoji_reactions_on_timeline": "絵文字リアクションをタイムラインに表示",
|
||||||
"enable_web_push_notifications": "ウェブプッシュ通知を許可する",
|
"enable_web_push_notifications": "ウェブプッシュ通知を許可する",
|
||||||
"enter_current_password_to_confirm": "あなたのアイデンティティを証明するため、現在のパスワードを入力してください",
|
"enter_current_password_to_confirm": "あなたのアイデンティティを証明するため、現在のパスワードを入力してください",
|
||||||
|
@ -361,6 +436,8 @@
|
||||||
"backup_settings_theme": "テーマを含む設定をファイルにバックアップする",
|
"backup_settings_theme": "テーマを含む設定をファイルにバックアップする",
|
||||||
"errors": {
|
"errors": {
|
||||||
"file_slightly_new": "ファイルのマイナーバージョンが異なり、一部の設定が読み込まれないことがあります",
|
"file_slightly_new": "ファイルのマイナーバージョンが異なり、一部の設定が読み込まれないことがあります",
|
||||||
|
"file_too_new": "非対応:Pleroma-FE v{feMajor}は古すぎて、v{fileMajor}の設定を読み込めません",
|
||||||
|
"file_too_old": "非対応:設定ファイル v{fileMajor}は古すぎて、Pleroma-FE v{feMajor}が読み込めません",
|
||||||
"invalid_file": "これはPleromaの設定をバックアップしたファイルではありません。"
|
"invalid_file": "これはPleromaの設定をバックアップしたファイルではありません。"
|
||||||
},
|
},
|
||||||
"restore_settings": "設定をファイルから復元する"
|
"restore_settings": "設定をファイルから復元する"
|
||||||
|
@ -379,17 +456,23 @@
|
||||||
"hide_all_muted_posts": "ミュートした投稿を隠す",
|
"hide_all_muted_posts": "ミュートした投稿を隠す",
|
||||||
"hide_attachments_in_convo": "スレッドのファイルを隠す",
|
"hide_attachments_in_convo": "スレッドのファイルを隠す",
|
||||||
"hide_attachments_in_tl": "タイムラインのファイルを隠す",
|
"hide_attachments_in_tl": "タイムラインのファイルを隠す",
|
||||||
|
"hide_bot_indication": "botマークを隠す",
|
||||||
|
"hide_favorites_description": "お気に入りリストを隠す",
|
||||||
"hide_filtered_statuses": "フィルターされた投稿を隠す",
|
"hide_filtered_statuses": "フィルターされた投稿を隠す",
|
||||||
"hide_followers_count_description": "フォロワーの数を見せない",
|
"hide_followers_count_description": "フォロワーの数を見せない",
|
||||||
"hide_followers_description": "フォロワーを見せない",
|
"hide_followers_description": "フォロワーを見せない",
|
||||||
"hide_follows_count_description": "フォローしている人の数を見せない",
|
"hide_follows_count_description": "フォローしている人の数を見せない",
|
||||||
"hide_follows_description": "フォローしている人を見せない",
|
"hide_follows_description": "フォローしている人を見せない",
|
||||||
"hide_isp": "インスタンス固有パネルを隠す",
|
"hide_isp": "インスタンス固有パネルを隠す",
|
||||||
|
"hide_list_aliases_error_action": "閉じる",
|
||||||
"hide_media_previews": "メディアのプレビューを隠す",
|
"hide_media_previews": "メディアのプレビューを隠す",
|
||||||
"hide_muted_posts": "ミュートしているユーザーの投稿を隠す",
|
"hide_muted_posts": "ミュートしているユーザーの投稿を隠す",
|
||||||
"hide_muted_threads": "ミュートしているスレを隠す",
|
"hide_muted_threads": "ミュートしているスレを隠す",
|
||||||
"hide_post_stats": "投稿の統計を隠す (例: お気に入りの数)",
|
"hide_post_stats": "投稿の統計を隠す (例: お気に入りの数)",
|
||||||
"hide_shoutbox": "Shoutboxを表示しない",
|
"hide_shoutbox": "Shoutboxを表示しない",
|
||||||
|
"hide_site_favicon": "ページ上にアイコンを隠す",
|
||||||
|
"hide_site_name": "インスタンス名を隠す",
|
||||||
|
"hide_threads_with_blocked_users": "ブロックしているユーザーをメンションする投稿を隠す",
|
||||||
"hide_user_stats": "ユーザーの統計を隠す (例: フォロワーの数)",
|
"hide_user_stats": "ユーザーの統計を隠す (例: フォロワーの数)",
|
||||||
"hide_wallpaper": "インスタンスのバックグラウンドを隠す",
|
"hide_wallpaper": "インスタンスのバックグラウンドを隠す",
|
||||||
"hide_wordfiltered_statuses": "単語フィルタに一致する投稿を隠す",
|
"hide_wordfiltered_statuses": "単語フィルタに一致する投稿を隠す",
|
||||||
|
@ -401,18 +484,26 @@
|
||||||
"instance_default": "(デフォルト: {value})",
|
"instance_default": "(デフォルト: {value})",
|
||||||
"instance_default_simple": "(デフォルト)",
|
"instance_default_simple": "(デフォルト)",
|
||||||
"interface": "インターフェース",
|
"interface": "インターフェース",
|
||||||
"interfaceLanguage": "インターフェースの言語",
|
"interfaceLanguage": "表示言語",
|
||||||
"invalid_theme_imported": "このファイルはPleromaのテーマではありません。テーマは変更されませんでした。",
|
"invalid_theme_imported": "このファイルはPleromaのテーマではありません。テーマは変更されませんでした。",
|
||||||
"limited_availability": "あなたのブラウザではできません",
|
"limited_availability": "あなたのブラウザではできません",
|
||||||
"links": "リンク",
|
"links": "リンク",
|
||||||
|
"list_aliases_error": "エイリアス を読み込めませんでした:{error}",
|
||||||
|
"list_backups_error": "バクアップを読み込めませんでした:{error}",
|
||||||
"lock_account_description": "あなたが認めた人だけ、あなたのアカウントをフォローできる",
|
"lock_account_description": "あなたが認めた人だけ、あなたのアカウントをフォローできる",
|
||||||
"loop_video": "ビデオを繰り返す",
|
"loop_video": "ビデオを繰り返す",
|
||||||
"loop_video_silent_only": "音のないビデオだけ繰り返す",
|
"loop_video_silent_only": "音のないビデオだけ繰り返す",
|
||||||
|
"mascot": "マストドンFEのマスコット",
|
||||||
|
"max_depth_in_thread": "スレッドの初期の最大レベル数",
|
||||||
"max_thumbnails": "投稿に含まれるサムネイルの最大数",
|
"max_thumbnails": "投稿に含まれるサムネイルの最大数",
|
||||||
|
"mention_link_bolden_you": "メンションされたら、強調にする",
|
||||||
"mention_link_display": "メンションリンクの表示モード",
|
"mention_link_display": "メンションリンクの表示モード",
|
||||||
"mention_link_display_full": "名前とドメイン、例: {'@'}foo{'@'}example.org",
|
"mention_link_display_full": "名前とドメイン、例: {'@'}foo{'@'}example.org",
|
||||||
"mention_link_display_full_for_remote": "ローカルユーザー: 名前のみ、リモートユーザー: 名前とドメイン",
|
"mention_link_display_full_for_remote": "ローカルユーザー: 名前のみ、リモートユーザー: 名前とドメイン",
|
||||||
"mention_link_display_short": "名前のみ、例:{'@'}foo",
|
"mention_link_display_short": "名前のみ、例:{'@'}foo",
|
||||||
|
"mention_link_fade_domain": "ドメインを色あせる",
|
||||||
|
"mention_link_show_avatar": "メンションの側にアバターを表示",
|
||||||
|
"mention_link_show_tooltip": "リモートユーザに名前とドメインのツールチップを付ける",
|
||||||
"mention_links": "メンションリンク",
|
"mention_links": "メンションリンク",
|
||||||
"mfa": {
|
"mfa": {
|
||||||
"authentication_methods": "認証方法",
|
"authentication_methods": "認証方法",
|
||||||
|
@ -437,6 +528,12 @@
|
||||||
},
|
},
|
||||||
"minimal_scopes_mode": "公開範囲選択オプションを最小にする",
|
"minimal_scopes_mode": "公開範囲選択オプションを最小にする",
|
||||||
"more_settings": "その他の設定",
|
"more_settings": "その他の設定",
|
||||||
|
"move_account": "アカウントの引っ越し",
|
||||||
|
"move_account_error": "引っ越しできませんでした:{error}",
|
||||||
|
"move_account_notes": "アカウントを引っ越ししたいなら、先のアカウントでアカウントエイリアスを作成してください",
|
||||||
|
"move_account_target": "引っ越し先",
|
||||||
|
"moved_account": "引っ越ししました",
|
||||||
|
"mute_bot_posts": "botの投稿をミュート",
|
||||||
"mute_export": "ミュートのエクスポート",
|
"mute_export": "ミュートのエクスポート",
|
||||||
"mute_export_button": "ミュートをCSVファイルにエクスポートする",
|
"mute_export_button": "ミュートをCSVファイルにエクスポートする",
|
||||||
"mute_import": "ミュートのインポート",
|
"mute_import": "ミュートのインポート",
|
||||||
|
@ -446,6 +543,7 @@
|
||||||
"mutes_tab": "ミュート",
|
"mutes_tab": "ミュート",
|
||||||
"name": "名前",
|
"name": "名前",
|
||||||
"name_bio": "名前とプロフィール",
|
"name_bio": "名前とプロフィール",
|
||||||
|
"new_alias_target": "アカウントエイリアスを作成",
|
||||||
"new_email": "新しいメールアドレス",
|
"new_email": "新しいメールアドレス",
|
||||||
"new_password": "新しいパスワード",
|
"new_password": "新しいパスワード",
|
||||||
"no_blocks": "ブロックはありません",
|
"no_blocks": "ブロックはありません",
|
||||||
|
@ -455,6 +553,7 @@
|
||||||
"notification_mutes": "特定のユーザーからの通知を止めるには、ミュートしてください。",
|
"notification_mutes": "特定のユーザーからの通知を止めるには、ミュートしてください。",
|
||||||
"notification_setting_block_from_strangers": "フォローしていないユーザーからの通知を拒否する",
|
"notification_setting_block_from_strangers": "フォローしていないユーザーからの通知を拒否する",
|
||||||
"notification_setting_filters": "フィルター",
|
"notification_setting_filters": "フィルター",
|
||||||
|
"notification_setting_hide_if_cw": "説明がつけたら、プッシュ通知で投稿を隠す",
|
||||||
"notification_setting_hide_notification_contents": "送った人と内容を、プッシュ通知に表示しない",
|
"notification_setting_hide_notification_contents": "送った人と内容を、プッシュ通知に表示しない",
|
||||||
"notification_setting_privacy": "プライバシー",
|
"notification_setting_privacy": "プライバシー",
|
||||||
"notification_visibility": "表示する通知",
|
"notification_visibility": "表示する通知",
|
||||||
|
@ -463,6 +562,7 @@
|
||||||
"notification_visibility_likes": "お気に入り",
|
"notification_visibility_likes": "お気に入り",
|
||||||
"notification_visibility_mentions": "メンション",
|
"notification_visibility_mentions": "メンション",
|
||||||
"notification_visibility_moves": "ユーザーの引っ越し",
|
"notification_visibility_moves": "ユーザーの引っ越し",
|
||||||
|
"notification_visibility_polls": "参加した投票の結果",
|
||||||
"notification_visibility_repeats": "リピート",
|
"notification_visibility_repeats": "リピート",
|
||||||
"notifications": "通知",
|
"notifications": "通知",
|
||||||
"nsfw_clickthrough": "NSFWなファイルを隠す",
|
"nsfw_clickthrough": "NSFWなファイルを隠す",
|
||||||
|
@ -473,6 +573,7 @@
|
||||||
"play_videos_in_modal": "ビデオをメディアビューアーで見る",
|
"play_videos_in_modal": "ビデオをメディアビューアーで見る",
|
||||||
"post_look_feel": "投稿の見た目",
|
"post_look_feel": "投稿の見た目",
|
||||||
"post_status_content_type": "投稿のコンテントタイプ",
|
"post_status_content_type": "投稿のコンテントタイプ",
|
||||||
|
"posts": "投稿",
|
||||||
"preload_images": "画像を先読みする",
|
"preload_images": "画像を先読みする",
|
||||||
"presets": "プリセット",
|
"presets": "プリセット",
|
||||||
"profile_background": "プロフィールの背景",
|
"profile_background": "プロフィールの背景",
|
||||||
|
@ -486,7 +587,10 @@
|
||||||
"profile_tab": "プロフィール",
|
"profile_tab": "プロフィール",
|
||||||
"radii_help": "インターフェースの丸さを設定する",
|
"radii_help": "インターフェースの丸さを設定する",
|
||||||
"refresh_token": "トークンを更新",
|
"refresh_token": "トークンを更新",
|
||||||
|
"remove_alias": "削除",
|
||||||
|
"remove_backup": "削除",
|
||||||
"render_mfm": "Misskey Markdownを表示",
|
"render_mfm": "Misskey Markdownを表示",
|
||||||
|
"render_mfm_on_hover": "マウスポインタを置いていないMFMアニメーションを停止",
|
||||||
"replies_in_timeline": "タイムラインのリプライ",
|
"replies_in_timeline": "タイムラインのリプライ",
|
||||||
"reply_visibility_all": "すべてのリプライを見る",
|
"reply_visibility_all": "すべてのリプライを見る",
|
||||||
"reply_visibility_following": "私に宛てられたリプライと、フォローしている人からのリプライを見る",
|
"reply_visibility_following": "私に宛てられたリプライと、フォローしている人からのリプライを見る",
|
||||||
|
@ -510,15 +614,21 @@
|
||||||
"security": "セキュリティ",
|
"security": "セキュリティ",
|
||||||
"security_tab": "セキュリティ",
|
"security_tab": "セキュリティ",
|
||||||
"sensitive_by_default": "はじめから投稿をセンシティブとして設定",
|
"sensitive_by_default": "はじめから投稿をセンシティブとして設定",
|
||||||
"sensitive_if_subject": "ステータスにサブジェクトをついたらNSFWにする",
|
"sensitive_if_subject": "投稿にサブジェクトをついたらNSFWにする",
|
||||||
"set_new_avatar": "新しいアバターを設定する",
|
"set_new_avatar": "新しいアバターを設定する",
|
||||||
|
"set_new_mascot": "マスコットを更新",
|
||||||
"set_new_profile_background": "新しいプロフィールのバックグラウンドを設定する",
|
"set_new_profile_background": "新しいプロフィールのバックグラウンドを設定する",
|
||||||
"set_new_profile_banner": "新しいプロフィールバナーを設定する",
|
"set_new_profile_banner": "新しいプロフィールバナーを設定する",
|
||||||
"setting_changed": "規定の設定と異なっています",
|
"setting_changed": "規定の設定と異なっています",
|
||||||
|
"setting_server_side": "この設定は、全クライエントに適用します",
|
||||||
"settings": "設定",
|
"settings": "設定",
|
||||||
"show_admin_badge": "\"管理者\"のバッジを見せる",
|
"show_admin_badge": "\"管理者\"のバッジを見せる",
|
||||||
"show_moderator_badge": "\"モデレーター\"のバッジを見せる",
|
"show_moderator_badge": "\"モデレーター\"のバッジを見せる",
|
||||||
|
"show_nav_shortcuts": "ページ上にショートカットを追加",
|
||||||
|
"show_panel_nav_shortcuts": "ページ上にタイムラインショートカットを追加",
|
||||||
"show_scrollbars": "カラムのスクロールバーを表示",
|
"show_scrollbars": "カラムのスクロールバーを表示",
|
||||||
|
"show_wider_shortcuts": "ページ上にショートカット間のスペースを増大",
|
||||||
|
"show_yous": "メンション側に「(あなた)」を表示",
|
||||||
"stop_gifs": "カーソルを重ねたとき、GIFを動かす",
|
"stop_gifs": "カーソルを重ねたとき、GIFを動かす",
|
||||||
"streaming": "上までスクロールしたとき、自動的にストリーミングする",
|
"streaming": "上までスクロールしたとき、自動的にストリーミングする",
|
||||||
"style": {
|
"style": {
|
||||||
|
@ -683,13 +793,19 @@
|
||||||
"third_column_mode_postform": "で投稿フォームを表示",
|
"third_column_mode_postform": "で投稿フォームを表示",
|
||||||
"token": "トークン",
|
"token": "トークン",
|
||||||
"tooltipRadius": "ツールチップとアラート",
|
"tooltipRadius": "ツールチップとアラート",
|
||||||
|
"translation_language": "翻訳先言語",
|
||||||
|
"tree_advanced": "スレッドで「返信を見る」、「閉じる」ボタンを表示",
|
||||||
|
"tree_fade_ancestors": "見ている投稿の親投稿を色あせる",
|
||||||
"type_domains_to_mute": "ミュートしたいドメインを検索",
|
"type_domains_to_mute": "ミュートしたいドメインを検索",
|
||||||
"upload_a_photo": "画像をアップロード",
|
"upload_a_photo": "画像をアップロード",
|
||||||
"useStreamingApi": "投稿と通知を、すぐに受け取る",
|
"useStreamingApi": "投稿と通知を、すぐに受け取る",
|
||||||
"useStreamingApiWarning": "(実験中で、投稿を取りこぼすかもしれないので、おすすめしません)",
|
"useStreamingApiWarning": "(実験中で、投稿を取りこぼすかもしれないので、おすすめしません)",
|
||||||
|
"use_at_icon": "{'@'}マークをアイコンにする",
|
||||||
"use_contain_fit": "画像のサムネイルを、切り抜かない",
|
"use_contain_fit": "画像のサムネイルを、切り抜かない",
|
||||||
"use_one_click_nsfw": "NSFWなファイルを1クリックで開く",
|
"use_one_click_nsfw": "NSFWなファイルを1クリックで開く",
|
||||||
"user_mutes": "ユーザー",
|
"user_mutes": "ユーザー",
|
||||||
|
"user_profile_default_tab": "ユーザープロファイルの初期タブ",
|
||||||
|
"user_profiles": "ユーザーのプロファイル",
|
||||||
"user_settings": "ユーザー設定",
|
"user_settings": "ユーザー設定",
|
||||||
"valid_until": "まで有効",
|
"valid_until": "まで有効",
|
||||||
"values": {
|
"values": {
|
||||||
|
@ -702,33 +818,67 @@
|
||||||
"title": "バージョン"
|
"title": "バージョン"
|
||||||
},
|
},
|
||||||
"virtual_scrolling": "タイムラインの描画を最適化する",
|
"virtual_scrolling": "タイムラインの描画を最適化する",
|
||||||
"word_filter": "単語フィルタ"
|
"word_filter": "単語フィルタ",
|
||||||
|
"wordfilter": "単語フィルター"
|
||||||
},
|
},
|
||||||
"status": {
|
"status": {
|
||||||
|
"ancestor_follow": "{numReplies}件の返信を見る",
|
||||||
|
"ancestor_follow_with_icon": "{icon} {text}",
|
||||||
|
"attachment_stop_flash": "フラッシュを停止",
|
||||||
"bookmark": "ブックマーク",
|
"bookmark": "ブックマーク",
|
||||||
|
"collapse_attachments": "ファイルを隠す",
|
||||||
"copy_link": "リンクをコピー",
|
"copy_link": "リンクをコピー",
|
||||||
"delete": "ステータスを削除",
|
"delete": "投稿を削除",
|
||||||
"delete_confirm": "本当にこのステータスを削除してもよろしいですか?",
|
"delete_confirm": "投稿を削除しますか?",
|
||||||
|
"delete_confirm_accept_button": "削除",
|
||||||
|
"delete_confirm_cancel_button": "キャンセル",
|
||||||
|
"delete_confirm_title": "削除を確認してください",
|
||||||
"expand": "広げる",
|
"expand": "広げる",
|
||||||
"external_source": "外部ソース",
|
"external_source": "外部ソース",
|
||||||
"favorites": "お気に入り",
|
"favorites": "お気に入り",
|
||||||
|
"hide_attachment": "ファイルを隠す",
|
||||||
"hide_content": "隠す",
|
"hide_content": "隠す",
|
||||||
"hide_full_subject": "隠す",
|
"hide_full_subject": "隠す",
|
||||||
|
"many_attachments": "ファイルは{number}件があります",
|
||||||
"mentions": "メンション",
|
"mentions": "メンション",
|
||||||
|
"move_down": "右に移動",
|
||||||
|
"move_up": "左に移動",
|
||||||
"mute_conversation": "スレッドをミュート",
|
"mute_conversation": "スレッドをミュート",
|
||||||
"nsfw": "閲覧注意",
|
"nsfw": "閲覧注意",
|
||||||
|
"open_gallery": "ギャラリーを見る",
|
||||||
|
"override_translation_source_language": "翻訳元言語",
|
||||||
"pin": "プロフィールにピン留め",
|
"pin": "プロフィールにピン留め",
|
||||||
"pinned": "ピン留め",
|
"pinned": "ピン留め",
|
||||||
"plus_more": "ほか{number}件",
|
"plus_more": "ほか{number}件",
|
||||||
|
"remove_attachment": "削除",
|
||||||
|
"repeat_confirm": "リピートしますか?",
|
||||||
|
"repeat_confirm_accept_button": "リピート",
|
||||||
|
"repeat_confirm_cancel_button": "キャンセル",
|
||||||
|
"repeat_confirm_title": "リピートを確認してください",
|
||||||
"repeats": "リピート",
|
"repeats": "リピート",
|
||||||
"replies_list": "返信:",
|
"replies_list": "返信:",
|
||||||
|
"replies_list_with_others": "{numReplies}件の返信を見る",
|
||||||
"reply_to": "返信",
|
"reply_to": "返信",
|
||||||
|
"show_all_attachments": "全ファイルを表示",
|
||||||
|
"show_all_conversation": "スレッドの全部を見る",
|
||||||
|
"show_all_conversation_with_icon": "{icon} {text}",
|
||||||
|
"show_attachment_description": "説明の略を見る",
|
||||||
|
"show_attachment_in_modal": "ファイルをウインドウで見る",
|
||||||
"show_content": "見る",
|
"show_content": "見る",
|
||||||
"show_full_subject": "全部見る",
|
"show_full_subject": "全部見る",
|
||||||
|
"show_only_conversation_under_this": "この投稿を返信する投稿のみ",
|
||||||
"status_deleted": "この投稿は削除されました",
|
"status_deleted": "この投稿は削除されました",
|
||||||
"status_unavailable": "利用できません",
|
"status_unavailable": "利用できません",
|
||||||
|
"thread_follow": "{numStatus}件の返信を見る",
|
||||||
|
"thread_follow_with_icon": "{icon} {text}",
|
||||||
|
"thread_hide": "スレッドを隠す",
|
||||||
"thread_muted": "ミュートされたスレッド",
|
"thread_muted": "ミュートされたスレッド",
|
||||||
"thread_muted_and_words": "以下の単語を含むため:",
|
"thread_muted_and_words": "以下の単語を含むため:",
|
||||||
|
"thread_show": "スレッドを表示",
|
||||||
|
"thread_show_full": "{numStatus}件の返信を見る",
|
||||||
|
"thread_show_full_with_icon": "{icon} {text}",
|
||||||
|
"translate": "翻訳",
|
||||||
|
"translated_from": "{language}から翻訳されました",
|
||||||
"unbookmark": "ブックマーク解除",
|
"unbookmark": "ブックマーク解除",
|
||||||
"unmute_conversation": "スレッドのミュートを解除",
|
"unmute_conversation": "スレッドのミュートを解除",
|
||||||
"unpin": "プロフィールのピン留めを外す",
|
"unpin": "プロフィールのピン留めを外す",
|
||||||
|
@ -760,10 +910,10 @@
|
||||||
"collapse": "たたむ",
|
"collapse": "たたむ",
|
||||||
"conversation": "スレッド",
|
"conversation": "スレッド",
|
||||||
"error": "タイムラインの読み込みに失敗しました: {0}",
|
"error": "タイムラインの読み込みに失敗しました: {0}",
|
||||||
"load_older": "古いステータス",
|
"load_older": "古い投稿",
|
||||||
"no_more_statuses": "これで終わりです",
|
"no_more_statuses": "これで終わりです",
|
||||||
"no_retweet_hint": "投稿を「フォロワーのみ」または「ダイレクト」にすると、リピートできなくなります",
|
"no_retweet_hint": "投稿を「フォロワーのみ」または「ダイレクト」にすると、リピートできなくなります",
|
||||||
"no_statuses": "ステータスはありません",
|
"no_statuses": "投稿はありません",
|
||||||
"reload": "再読み込み",
|
"reload": "再読み込み",
|
||||||
"repeated": "リピート",
|
"repeated": "リピート",
|
||||||
"show_new": "読み込み",
|
"show_new": "読み込み",
|
||||||
|
@ -771,12 +921,16 @@
|
||||||
"socket_reconnected": "リアルタイム接続が確立されました",
|
"socket_reconnected": "リアルタイム接続が確立されました",
|
||||||
"up_to_date": "最新"
|
"up_to_date": "最新"
|
||||||
},
|
},
|
||||||
|
"toast": {
|
||||||
|
"no_translation_target_set": "翻訳先言語の設定していません、設定をしてください"
|
||||||
|
},
|
||||||
"tool_tip": {
|
"tool_tip": {
|
||||||
"accept_follow_request": "フォローリクエストを許可",
|
"accept_follow_request": "フォローリクエストを許可",
|
||||||
"add_reaction": "リアクションを追加",
|
"add_reaction": "リアクションを追加",
|
||||||
"bookmark": "ブックマーク",
|
"bookmark": "ブックマーク",
|
||||||
"favorite": "お気に入り",
|
"favorite": "お気に入り",
|
||||||
"media_upload": "メディアをアップロード",
|
"media_upload": "メディアをアップロード",
|
||||||
|
"quote": "参照",
|
||||||
"reject_follow_request": "フォローリクエストを拒否",
|
"reject_follow_request": "フォローリクエストを拒否",
|
||||||
"repeat": "リピート",
|
"repeat": "リピート",
|
||||||
"reply": "返信",
|
"reply": "返信",
|
||||||
|
@ -803,6 +957,7 @@
|
||||||
"deactivate_account": "アカウントをアクティブでなくする",
|
"deactivate_account": "アカウントをアクティブでなくする",
|
||||||
"delete_account": "アカウントを削除",
|
"delete_account": "アカウントを削除",
|
||||||
"delete_user": "ユーザーを削除",
|
"delete_user": "ユーザーを削除",
|
||||||
|
"delete_user_data_and_deactivate_confirmation": "本当に削除しますか?削除したら、絶対に取り返せません",
|
||||||
"disable_any_subscription": "フォローされないようにする",
|
"disable_any_subscription": "フォローされないようにする",
|
||||||
"disable_remote_subscription": "他のインスタンスからフォローされないようにする",
|
"disable_remote_subscription": "他のインスタンスからフォローされないようにする",
|
||||||
"force_nsfw": "すべての投稿をNSFWにする",
|
"force_nsfw": "すべての投稿をNSFWにする",
|
||||||
|
@ -817,14 +972,29 @@
|
||||||
"strip_media": "投稿からメディアを除去する"
|
"strip_media": "投稿からメディアを除去する"
|
||||||
},
|
},
|
||||||
"approve": "受け入れ",
|
"approve": "受け入れ",
|
||||||
|
"approve_confirm": "フォローリクエストを受け入れますか?",
|
||||||
|
"approve_confirm_accept_button": "受け入れる",
|
||||||
|
"approve_confirm_cancel_button": "キャンセル",
|
||||||
|
"approve_confirm_title": "受け入れを確認してください",
|
||||||
"block": "ブロック",
|
"block": "ブロック",
|
||||||
|
"block_confirm": "{user}をブロックしますか?",
|
||||||
|
"block_confirm_accept_button": "ブロック",
|
||||||
|
"block_confirm_cancel_button": "キャンセル",
|
||||||
|
"block_confirm_title": "ブロックを確認してください",
|
||||||
"block_progress": "ブロックしています…",
|
"block_progress": "ブロックしています…",
|
||||||
"blocked": "ブロックしています!",
|
"blocked": "ブロックしています!",
|
||||||
"bot": "bot",
|
"bot": "bot",
|
||||||
|
"deactivated": "無効",
|
||||||
"deny": "お断り",
|
"deny": "お断り",
|
||||||
|
"deny_confirm": "フォローリクエストを断りますか?",
|
||||||
|
"deny_confirm_accept_button": "お断り",
|
||||||
|
"deny_confirm_cancel_button": "キャンセル",
|
||||||
|
"deny_confirm_title": "お断りを確認してください",
|
||||||
|
"domain_muted": "ドメインブロックをやめる",
|
||||||
"edit_profile": "プロフィールを編集",
|
"edit_profile": "プロフィールを編集",
|
||||||
"favorites": "お気に入り",
|
"favorites": "お気に入り",
|
||||||
"follow": "フォロー",
|
"follow": "フォロー",
|
||||||
|
"follow_cancel": "フォローリクエストを取り消す",
|
||||||
"follow_progress": "リクエストしています…",
|
"follow_progress": "リクエストしています…",
|
||||||
"follow_sent": "リクエストを送りました!",
|
"follow_sent": "リクエストを送りました!",
|
||||||
"follow_unfollow": "フォローをやめる",
|
"follow_unfollow": "フォローをやめる",
|
||||||
|
@ -845,17 +1015,27 @@
|
||||||
"mention": "メンション",
|
"mention": "メンション",
|
||||||
"message": "メッセージ",
|
"message": "メッセージ",
|
||||||
"mute": "ミュート",
|
"mute": "ミュート",
|
||||||
|
"mute_confirm": "{user}をミュートしますか?",
|
||||||
|
"mute_confirm_accept_button": "ミュート",
|
||||||
|
"mute_confirm_cancel_button": "キャンセル",
|
||||||
|
"mute_confirm_title": "ユーザーをミュート",
|
||||||
|
"mute_domain": "ドメインをブロック",
|
||||||
"mute_progress": "ミュートしています…",
|
"mute_progress": "ミュートしています…",
|
||||||
"muted": "ミュートしています",
|
"muted": "ミュートしています",
|
||||||
"note": "私的なメモ",
|
"note": "私的なメモ",
|
||||||
"per_day": "/日",
|
"per_day": "/日",
|
||||||
"remote_follow": "リモートフォロー",
|
"remote_follow": "リモートフォロー",
|
||||||
|
"replies": "投稿と返信",
|
||||||
"report": "通報",
|
"report": "通報",
|
||||||
"show_repeats": "リピートを見る",
|
"show_repeats": "リピートを見る",
|
||||||
"statuses": "ステータス",
|
"statuses": "投稿",
|
||||||
"subscribe": "購読",
|
"subscribe": "購読",
|
||||||
"unblock": "ブロック解除",
|
"unblock": "ブロック解除",
|
||||||
"unblock_progress": "ブロックを解除しています…",
|
"unblock_progress": "ブロックを解除しています…",
|
||||||
|
"unfollow_confirm": "{user}のフォローをやめますか?",
|
||||||
|
"unfollow_confirm_accept_button": "やめる",
|
||||||
|
"unfollow_confirm_cancel_button": "キャンセル",
|
||||||
|
"unfollow_confirm_title": "フォローをやめる",
|
||||||
"unmute": "ミュート解除",
|
"unmute": "ミュート解除",
|
||||||
"unmute_progress": "ミュートを解除しています…",
|
"unmute_progress": "ミュートを解除しています…",
|
||||||
"unsubscribe": "購読を解除"
|
"unsubscribe": "購読を解除"
|
||||||
|
|
|
@ -98,7 +98,6 @@
|
||||||
"features_panel": {
|
"features_panel": {
|
||||||
"media_proxy": "Mediaproxy",
|
"media_proxy": "Mediaproxy",
|
||||||
"scope_options": "Zichtbaarheidsopties",
|
"scope_options": "Zichtbaarheidsopties",
|
||||||
"shout": "Shoutbox",
|
|
||||||
"text_limit": "Tekstlimiet",
|
"text_limit": "Tekstlimiet",
|
||||||
"title": "Functies",
|
"title": "Functies",
|
||||||
"upload_limit": "Upload limiet",
|
"upload_limit": "Upload limiet",
|
||||||
|
@ -394,8 +393,16 @@
|
||||||
"chatMessageRadius": "Chatbericht",
|
"chatMessageRadius": "Chatbericht",
|
||||||
"checkboxRadius": "Checkboxen",
|
"checkboxRadius": "Checkboxen",
|
||||||
"collapse_subject": "Berichten met een onderwerp inklappen",
|
"collapse_subject": "Berichten met een onderwerp inklappen",
|
||||||
|
"columns": "Kolommen",
|
||||||
"composing": "Opstellen",
|
"composing": "Opstellen",
|
||||||
|
"confirm_dialogs": "Bevestiging vereisen voor:",
|
||||||
|
"confirm_dialogs_block": "Iemand blokkeren",
|
||||||
|
"confirm_dialogs_delete": "Een bericht verwijderen",
|
||||||
|
"confirm_dialogs_mute": "Iemand negeren",
|
||||||
|
"confirm_dialogs_repeat": "Herhalen van een bericht",
|
||||||
|
"confirm_dialogs_unfollow": "Iemand ontvolgen",
|
||||||
"confirm_new_password": "Nieuw wachtwoord bevestigen",
|
"confirm_new_password": "Nieuw wachtwoord bevestigen",
|
||||||
|
"confirmation_dialogs": "Bevestigingsopties",
|
||||||
"conversation_display": "Gespreksweergave stijl",
|
"conversation_display": "Gespreksweergave stijl",
|
||||||
"conversation_display_linear": "Lineaire weergave",
|
"conversation_display_linear": "Lineaire weergave",
|
||||||
"conversation_display_tree": "Boom weergave",
|
"conversation_display_tree": "Boom weergave",
|
||||||
|
@ -461,6 +468,8 @@
|
||||||
"hide_muted_threads": "Genegeerde gesprekken verbergen",
|
"hide_muted_threads": "Genegeerde gesprekken verbergen",
|
||||||
"hide_post_stats": "Bericht-statistieken verbergen (bijv. het aantal favorieten)",
|
"hide_post_stats": "Bericht-statistieken verbergen (bijv. het aantal favorieten)",
|
||||||
"hide_shoutbox": "Shoutbox verbergen",
|
"hide_shoutbox": "Shoutbox verbergen",
|
||||||
|
"hide_site_favicon": "Favicon verbergen in top-paneel",
|
||||||
|
"hide_site_name": "Instantienaam verbergen in top paneel",
|
||||||
"hide_threads_with_blocked_users": "Gesprekken met geblokkeerde gebruikers verbergen",
|
"hide_threads_with_blocked_users": "Gesprekken met geblokkeerde gebruikers verbergen",
|
||||||
"hide_user_stats": "Gebruikers-statistieken verbergen (bijv. het aantal volgers)",
|
"hide_user_stats": "Gebruikers-statistieken verbergen (bijv. het aantal volgers)",
|
||||||
"hide_wallpaper": "Achtergrond-afbeelding verbergen",
|
"hide_wallpaper": "Achtergrond-afbeelding verbergen",
|
||||||
|
@ -613,7 +622,10 @@
|
||||||
"settings": "Instellingen",
|
"settings": "Instellingen",
|
||||||
"show_admin_badge": "\"Beheerder\" badge in mijn profiel tonen",
|
"show_admin_badge": "\"Beheerder\" badge in mijn profiel tonen",
|
||||||
"show_moderator_badge": "\"Moderator\" badge in mijn profiel tonen",
|
"show_moderator_badge": "\"Moderator\" badge in mijn profiel tonen",
|
||||||
|
"show_nav_shortcuts": "Extra navigatie snelkoppelingen tonen in top paneel",
|
||||||
|
"show_panel_nav_shortcuts": "Tijdlijn navigatie-snelkoppelingen tonen bovenop het paneel",
|
||||||
"show_scrollbars": "Scrollbalk tonen in zijkolommen",
|
"show_scrollbars": "Scrollbalk tonen in zijkolommen",
|
||||||
|
"show_wider_shortcuts": "Extra ruimte tonen tussen snelkoppelingen in top paneel",
|
||||||
"show_yous": "(Jij)'s tonen",
|
"show_yous": "(Jij)'s tonen",
|
||||||
"stop_gifs": "Geanimeerde afbeeldingen afspelen bij zweven",
|
"stop_gifs": "Geanimeerde afbeeldingen afspelen bij zweven",
|
||||||
"streaming": "Automatisch streamen van nieuwe berichten inschakelen wanneer tot boven gescrold is",
|
"streaming": "Automatisch streamen van nieuwe berichten inschakelen wanneer tot boven gescrold is",
|
||||||
|
|
|
@ -75,7 +75,6 @@
|
||||||
"features_panel": {
|
"features_panel": {
|
||||||
"media_proxy": "Proxy pre médiá",
|
"media_proxy": "Proxy pre médiá",
|
||||||
"scope_options": "Nastavenia rámca",
|
"scope_options": "Nastavenia rámca",
|
||||||
"shout": "Verejné fórum",
|
|
||||||
"text_limit": "Limit počtu znakov",
|
"text_limit": "Limit počtu znakov",
|
||||||
"title": "Vlastnosti",
|
"title": "Vlastnosti",
|
||||||
"upload_limit": "Limit nahrávania",
|
"upload_limit": "Limit nahrávania",
|
||||||
|
|
|
@ -19,6 +19,8 @@ import reportsModule from './modules/reports.js'
|
||||||
import pollsModule from './modules/polls.js'
|
import pollsModule from './modules/polls.js'
|
||||||
import postStatusModule from './modules/postStatus.js'
|
import postStatusModule from './modules/postStatus.js'
|
||||||
import announcementsModule from './modules/announcements.js'
|
import announcementsModule from './modules/announcements.js'
|
||||||
|
import editStatusModule from './modules/editStatus.js'
|
||||||
|
import statusHistoryModule from './modules/statusHistory.js'
|
||||||
|
|
||||||
import { createI18n } from 'vue-i18n'
|
import { createI18n } from 'vue-i18n'
|
||||||
|
|
||||||
|
@ -81,7 +83,9 @@ const persistedStateOptions = {
|
||||||
reports: reportsModule,
|
reports: reportsModule,
|
||||||
polls: pollsModule,
|
polls: pollsModule,
|
||||||
postStatus: postStatusModule,
|
postStatus: postStatusModule,
|
||||||
announcements: announcementsModule
|
announcements: announcementsModule,
|
||||||
|
editStatus: editStatusModule,
|
||||||
|
statusHistory: statusHistoryModule
|
||||||
},
|
},
|
||||||
plugins,
|
plugins,
|
||||||
strict: false // Socket modifies itself, let's ignore this for now.
|
strict: false // Socket modifies itself, let's ignore this for now.
|
||||||
|
|
|
@ -98,6 +98,13 @@ const api = {
|
||||||
showImmediately: timelineData.visibleStatuses.length === 0,
|
showImmediately: timelineData.visibleStatuses.length === 0,
|
||||||
timeline: 'friends'
|
timeline: 'friends'
|
||||||
})
|
})
|
||||||
|
} else if (message.event === 'status.update') {
|
||||||
|
dispatch('addNewStatuses', {
|
||||||
|
statuses: [message.status],
|
||||||
|
userId: false,
|
||||||
|
showImmediately: message.status.id in timelineData.visibleStatusesObject,
|
||||||
|
timeline: 'friends'
|
||||||
|
})
|
||||||
} else if (message.event === 'delete') {
|
} else if (message.event === 'delete') {
|
||||||
dispatch('deleteStatusById', message.id)
|
dispatch('deleteStatusById', message.id)
|
||||||
}
|
}
|
||||||
|
@ -252,6 +259,12 @@ const api = {
|
||||||
if (!fetcher) return
|
if (!fetcher) return
|
||||||
store.commit('removeFetcher', { fetcherName: 'announcements', fetcher })
|
store.commit('removeFetcher', { fetcherName: 'announcements', fetcher })
|
||||||
},
|
},
|
||||||
|
getSupportedTranslationlanguages (store) {
|
||||||
|
store.state.backendInteractor.getSupportedTranslationlanguages({ store })
|
||||||
|
.then((data) => {
|
||||||
|
store.dispatch('setOption', { name: 'supportedTranslationLanguages', value: data })
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
// Pleroma websocket
|
// Pleroma websocket
|
||||||
setWsToken (store, token) {
|
setWsToken (store, token) {
|
||||||
|
|
|
@ -34,9 +34,10 @@ export const defaultState = {
|
||||||
hideThreadsWithBlockedUsers: undefined, // instance default
|
hideThreadsWithBlockedUsers: undefined, // instance default
|
||||||
hideWordFilteredPosts: undefined, // instance default
|
hideWordFilteredPosts: undefined, // instance default
|
||||||
muteBotStatuses: undefined, // instance default
|
muteBotStatuses: undefined, // instance default
|
||||||
collapseMessageWithSubject: undefined, // instance default
|
collapseMessageWithSubject: true, // instance default
|
||||||
padEmoji: true,
|
padEmoji: true,
|
||||||
showNavShortcuts: undefined, // instance default
|
showNavShortcuts: undefined, // instance default
|
||||||
|
showPanelNavShortcuts: undefined, // instance default
|
||||||
showWiderShortcuts: undefined, // instance default
|
showWiderShortcuts: undefined, // instance default
|
||||||
hideSiteFavicon: undefined, // instance default
|
hideSiteFavicon: undefined, // instance default
|
||||||
hideSiteName: undefined, // instance default
|
hideSiteName: undefined, // instance default
|
||||||
|
@ -80,6 +81,14 @@ export const defaultState = {
|
||||||
minimalScopesMode: undefined, // instance default
|
minimalScopesMode: undefined, // instance default
|
||||||
// This hides statuses filtered via a word filter
|
// This hides statuses filtered via a word filter
|
||||||
hideFilteredStatuses: undefined, // instance default
|
hideFilteredStatuses: undefined, // instance default
|
||||||
|
modalOnRepeat: undefined, // instance default
|
||||||
|
modalOnUnfollow: undefined, // instance default
|
||||||
|
modalOnBlock: undefined, // instance default
|
||||||
|
modalOnMute: undefined, // instance default
|
||||||
|
modalOnDelete: undefined, // instance default
|
||||||
|
modalOnLogout: undefined, // instance default
|
||||||
|
modalOnApproveFollow: undefined, // instance default
|
||||||
|
modalOnDenyFollow: undefined, // instance default
|
||||||
playVideosInModal: false,
|
playVideosInModal: false,
|
||||||
useOneClickNsfw: false,
|
useOneClickNsfw: false,
|
||||||
useContainFit: true,
|
useContainFit: true,
|
||||||
|
@ -105,7 +114,10 @@ export const defaultState = {
|
||||||
conversationTreeAdvanced: undefined, // instance default
|
conversationTreeAdvanced: undefined, // instance default
|
||||||
conversationOtherRepliesButton: undefined, // instance default
|
conversationOtherRepliesButton: undefined, // instance default
|
||||||
conversationTreeFadeAncestors: undefined, // instance default
|
conversationTreeFadeAncestors: undefined, // instance default
|
||||||
maxDepthInThread: undefined // instance default
|
maxDepthInThread: undefined, // instance default
|
||||||
|
translationLanguage: undefined, // instance default,
|
||||||
|
supportedTranslationLanguages: {}, // instance default
|
||||||
|
userProfileDefaultTab: 'statuses'
|
||||||
}
|
}
|
||||||
|
|
||||||
// caching the instance default properties
|
// caching the instance default properties
|
||||||
|
@ -178,6 +190,7 @@ const config = {
|
||||||
case 'interfaceLanguage':
|
case 'interfaceLanguage':
|
||||||
messages.setLanguage(this.getters.i18n, value)
|
messages.setLanguage(this.getters.i18n, value)
|
||||||
Cookies.set(BACKEND_LANGUAGE_COOKIE_NAME, localeService.internalToBackendLocale(value))
|
Cookies.set(BACKEND_LANGUAGE_COOKIE_NAME, localeService.internalToBackendLocale(value))
|
||||||
|
dispatch('setInstanceOption', { name: 'interfaceLanguage', value })
|
||||||
break
|
break
|
||||||
case 'thirdColumnMode':
|
case 'thirdColumnMode':
|
||||||
dispatch('setLayoutWidth', undefined)
|
dispatch('setLayoutWidth', undefined)
|
||||||
|
|
25
src/modules/editStatus.js
Normal file
25
src/modules/editStatus.js
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
const editStatus = {
|
||||||
|
state: {
|
||||||
|
params: null,
|
||||||
|
modalActivated: false
|
||||||
|
},
|
||||||
|
mutations: {
|
||||||
|
openEditStatusModal (state, params) {
|
||||||
|
state.params = params
|
||||||
|
state.modalActivated = true
|
||||||
|
},
|
||||||
|
closeEditStatusModal (state) {
|
||||||
|
state.modalActivated = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
openEditStatusModal ({ commit }, params) {
|
||||||
|
commit('openEditStatusModal', params)
|
||||||
|
},
|
||||||
|
closeEditStatusModal ({ commit }) {
|
||||||
|
commit('closeEditStatusModal')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default editStatus
|
|
@ -17,7 +17,7 @@ const defaultState = {
|
||||||
defaultAvatar: '/images/avi.png',
|
defaultAvatar: '/images/avi.png',
|
||||||
defaultBanner: '/images/banner.png',
|
defaultBanner: '/images/banner.png',
|
||||||
background: '/static/aurora_borealis.jpg',
|
background: '/static/aurora_borealis.jpg',
|
||||||
collapseMessageWithSubject: false,
|
collapseMessageWithSubject: true,
|
||||||
greentext: false,
|
greentext: false,
|
||||||
useAtIcon: false,
|
useAtIcon: false,
|
||||||
mentionLinkDisplay: 'short',
|
mentionLinkDisplay: 'short',
|
||||||
|
@ -38,6 +38,14 @@ const defaultState = {
|
||||||
hideSiteName: false,
|
hideSiteName: false,
|
||||||
hideUserStats: false,
|
hideUserStats: false,
|
||||||
muteBotStatuses: false,
|
muteBotStatuses: false,
|
||||||
|
modalOnRepeat: false,
|
||||||
|
modalOnUnfollow: false,
|
||||||
|
modalOnBlock: true,
|
||||||
|
modalOnMute: false,
|
||||||
|
modalOnDelete: true,
|
||||||
|
modalOnLogout: true,
|
||||||
|
modalOnApproveFollow: false,
|
||||||
|
modalOnDenyFollow: false,
|
||||||
loginMethod: 'password',
|
loginMethod: 'password',
|
||||||
logo: '/static/logo.svg',
|
logo: '/static/logo.svg',
|
||||||
logoMargin: '.2em',
|
logoMargin: '.2em',
|
||||||
|
|
25
src/modules/statusHistory.js
Normal file
25
src/modules/statusHistory.js
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
const statusHistory = {
|
||||||
|
state: {
|
||||||
|
params: {},
|
||||||
|
modalActivated: false
|
||||||
|
},
|
||||||
|
mutations: {
|
||||||
|
openStatusHistoryModal (state, params) {
|
||||||
|
state.params = params
|
||||||
|
state.modalActivated = true
|
||||||
|
},
|
||||||
|
closeStatusHistoryModal (state) {
|
||||||
|
state.modalActivated = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
openStatusHistoryModal ({ commit }, params) {
|
||||||
|
commit('openStatusHistoryModal', params)
|
||||||
|
},
|
||||||
|
closeStatusHistoryModal ({ commit }) {
|
||||||
|
commit('closeStatusHistoryModal')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default statusHistory
|
|
@ -64,7 +64,8 @@ export const defaultState = () => ({
|
||||||
dms: emptyTl(),
|
dms: emptyTl(),
|
||||||
bookmarks: emptyTl(),
|
bookmarks: emptyTl(),
|
||||||
list: emptyTl(),
|
list: emptyTl(),
|
||||||
bubble: emptyTl()
|
bubble: emptyTl(),
|
||||||
|
replies: emptyTl()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -183,7 +184,7 @@ const addNewStatuses = (state, { statuses, showImmediately = false, timeline, us
|
||||||
// This makes sure that user timeline won't get data meant for other
|
// This makes sure that user timeline won't get data meant for other
|
||||||
// user. I.e. opening different user profiles makes request which could
|
// user. I.e. opening different user profiles makes request which could
|
||||||
// return data late after user already viewing different user profile
|
// return data late after user already viewing different user profile
|
||||||
if ((timeline === 'user' || timeline === 'media') && timelineObject.userId !== userId) {
|
if ((timeline === 'user' || timeline === 'media' || timeline === 'replies') && timelineObject.userId !== userId) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,6 +251,9 @@ const addNewStatuses = (state, { statuses, showImmediately = false, timeline, us
|
||||||
'status': (status) => {
|
'status': (status) => {
|
||||||
addStatus(status, showImmediately)
|
addStatus(status, showImmediately)
|
||||||
},
|
},
|
||||||
|
'edit': (status) => {
|
||||||
|
addStatus(status, showImmediately)
|
||||||
|
},
|
||||||
'retweet': (status) => {
|
'retweet': (status) => {
|
||||||
// RetweetedStatuses are never shown immediately
|
// RetweetedStatuses are never shown immediately
|
||||||
const retweetedStatus = addStatus(status.retweeted_status, false, false)
|
const retweetedStatus = addStatus(status.retweeted_status, false, false)
|
||||||
|
@ -425,6 +429,10 @@ export const mutations = {
|
||||||
state.conversationsObject[newStatus.statusnet_conversation_id].forEach(status => { status.thread_muted = newStatus.thread_muted })
|
state.conversationsObject[newStatus.statusnet_conversation_id].forEach(status => { status.thread_muted = newStatus.thread_muted })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
setTranslatedStatus (state, { id, translation }) {
|
||||||
|
const newStatus = state.allStatusesObject[id]
|
||||||
|
newStatus.translation = translation
|
||||||
|
},
|
||||||
setRetweeted (state, { status, value }) {
|
setRetweeted (state, { status, value }) {
|
||||||
const newStatus = state.allStatusesObject[status.id]
|
const newStatus = state.allStatusesObject[status.id]
|
||||||
|
|
||||||
|
@ -602,6 +610,12 @@ const statuses = {
|
||||||
return rootState.api.backendInteractor.fetchStatus({ id })
|
return rootState.api.backendInteractor.fetchStatus({ id })
|
||||||
.then((status) => dispatch('addNewStatuses', { statuses: [status] }))
|
.then((status) => dispatch('addNewStatuses', { statuses: [status] }))
|
||||||
},
|
},
|
||||||
|
fetchStatusSource ({ rootState, dispatch }, status) {
|
||||||
|
return apiService.fetchStatusSource({ id: status.id, credentials: rootState.users.currentUser.credentials })
|
||||||
|
},
|
||||||
|
fetchStatusHistory ({ rootState, dispatch }, status) {
|
||||||
|
return apiService.fetchStatusHistory({ status })
|
||||||
|
},
|
||||||
deleteStatus ({ rootState, commit }, status) {
|
deleteStatus ({ rootState, commit }, status) {
|
||||||
commit('setDeleted', { status })
|
commit('setDeleted', { status })
|
||||||
apiService.deleteStatus({ id: status.id, credentials: rootState.users.currentUser.credentials })
|
apiService.deleteStatus({ id: status.id, credentials: rootState.users.currentUser.credentials })
|
||||||
|
@ -637,6 +651,10 @@ const statuses = {
|
||||||
rootState.api.backendInteractor.unpinOwnStatus({ id: statusId })
|
rootState.api.backendInteractor.unpinOwnStatus({ id: statusId })
|
||||||
.then((status) => dispatch('addNewStatuses', { statuses: [status] }))
|
.then((status) => dispatch('addNewStatuses', { statuses: [status] }))
|
||||||
},
|
},
|
||||||
|
translateStatus ({ rootState, commit }, { id, translation, language, from }) {
|
||||||
|
return rootState.api.backendInteractor.translateStatus({ id: id, translation, language, from })
|
||||||
|
.then((translation) => commit('setTranslatedStatus', { id, translation }))
|
||||||
|
},
|
||||||
muteConversation ({ rootState, commit }, statusId) {
|
muteConversation ({ rootState, commit }, statusId) {
|
||||||
return rootState.api.backendInteractor.muteConversation({ id: statusId })
|
return rootState.api.backendInteractor.muteConversation({ id: statusId })
|
||||||
.then((status) => commit('setMutedStatus', status))
|
.then((status) => commit('setMutedStatus', status))
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { each, map, concat, last, get } from 'lodash'
|
import { each, map, concat, last, get } from 'lodash'
|
||||||
import { parseStatus, parseUser, parseNotification, parseAttachment, parseLinkHeaderPagination } from '../entity_normalizer/entity_normalizer.service.js'
|
import { parseStatus, parseSource, parseUser, parseNotification, parseAttachment, parseLinkHeaderPagination } from '../entity_normalizer/entity_normalizer.service.js'
|
||||||
import { RegistrationError, StatusCodeError } from '../errors/errors'
|
import { RegistrationError, StatusCodeError } from '../errors/errors'
|
||||||
|
|
||||||
/* eslint-env browser */
|
/* eslint-env browser */
|
||||||
|
@ -31,6 +31,8 @@ const MASTODON_LOGIN_URL = '/api/v1/accounts/verify_credentials'
|
||||||
const MASTODON_REGISTRATION_URL = '/api/v1/accounts'
|
const MASTODON_REGISTRATION_URL = '/api/v1/accounts'
|
||||||
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 AKKOMA_LANGUAGES_URL = '/api/v1/akkoma/translation/languages'
|
||||||
|
const AKKOMA_TRANSLATE_URL = (id, lang) => `/api/v1/statuses/${id}/translations/${lang}`
|
||||||
const MASTODON_DISMISS_NOTIFICATION_URL = id => `/api/v1/notifications/${id}/dismiss`
|
const MASTODON_DISMISS_NOTIFICATION_URL = id => `/api/v1/notifications/${id}/dismiss`
|
||||||
const MASTODON_FAVORITE_URL = id => `/api/v1/statuses/${id}/favourite`
|
const MASTODON_FAVORITE_URL = id => `/api/v1/statuses/${id}/favourite`
|
||||||
const MASTODON_UNFAVORITE_URL = id => `/api/v1/statuses/${id}/unfavourite`
|
const MASTODON_UNFAVORITE_URL = id => `/api/v1/statuses/${id}/unfavourite`
|
||||||
|
@ -50,6 +52,8 @@ const MASTODON_USER_HOME_TIMELINE_URL = '/api/v1/timelines/home'
|
||||||
const AKKOMA_BUBBLE_TIMELINE_URL = '/api/v1/timelines/bubble'
|
const AKKOMA_BUBBLE_TIMELINE_URL = '/api/v1/timelines/bubble'
|
||||||
const MASTODON_STATUS_URL = id => `/api/v1/statuses/${id}`
|
const MASTODON_STATUS_URL = id => `/api/v1/statuses/${id}`
|
||||||
const MASTODON_STATUS_CONTEXT_URL = id => `/api/v1/statuses/${id}/context`
|
const MASTODON_STATUS_CONTEXT_URL = id => `/api/v1/statuses/${id}/context`
|
||||||
|
const MASTODON_STATUS_SOURCE_URL = id => `/api/v1/statuses/${id}/source`
|
||||||
|
const MASTODON_STATUS_HISTORY_URL = id => `/api/v1/statuses/${id}/history`
|
||||||
const MASTODON_USER_URL = id => `/api/v1/accounts/${id}?with_relationships=true`
|
const MASTODON_USER_URL = id => `/api/v1/accounts/${id}?with_relationships=true`
|
||||||
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`
|
||||||
|
@ -510,6 +514,31 @@ const fetchStatus = ({ id, credentials }) => {
|
||||||
.then((data) => parseStatus(data))
|
.then((data) => parseStatus(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fetchStatusSource = ({ id, credentials }) => {
|
||||||
|
let url = MASTODON_STATUS_SOURCE_URL(id)
|
||||||
|
return fetch(url, { headers: authHeaders(credentials) })
|
||||||
|
.then((data) => {
|
||||||
|
if (data.ok) {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
throw new Error('Error fetching source', data)
|
||||||
|
})
|
||||||
|
.then((data) => data.json())
|
||||||
|
.then((data) => parseSource(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchStatusHistory = ({ status, credentials }) => {
|
||||||
|
let url = MASTODON_STATUS_HISTORY_URL(status.id)
|
||||||
|
return promisedRequest({ url, credentials })
|
||||||
|
.then((data) => {
|
||||||
|
data.reverse()
|
||||||
|
return data.map((item) => {
|
||||||
|
item.originalStatus = status
|
||||||
|
return parseStatus(item)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const tagUser = ({ tag, credentials, user }) => {
|
const tagUser = ({ tag, credentials, user }) => {
|
||||||
const screenName = user.screen_name
|
const screenName = user.screen_name
|
||||||
const form = {
|
const form = {
|
||||||
|
@ -615,6 +644,7 @@ const fetchTimeline = ({
|
||||||
notifications: MASTODON_USER_NOTIFICATIONS_URL,
|
notifications: MASTODON_USER_NOTIFICATIONS_URL,
|
||||||
'publicAndExternal': MASTODON_PUBLIC_TIMELINE,
|
'publicAndExternal': MASTODON_PUBLIC_TIMELINE,
|
||||||
user: MASTODON_USER_TIMELINE_URL,
|
user: MASTODON_USER_TIMELINE_URL,
|
||||||
|
replies: MASTODON_USER_TIMELINE_URL,
|
||||||
media: MASTODON_USER_TIMELINE_URL,
|
media: MASTODON_USER_TIMELINE_URL,
|
||||||
list: MASTODON_LIST_TIMELINE_URL,
|
list: MASTODON_LIST_TIMELINE_URL,
|
||||||
favorites: MASTODON_USER_FAVORITES_TIMELINE_URL,
|
favorites: MASTODON_USER_FAVORITES_TIMELINE_URL,
|
||||||
|
@ -626,7 +656,7 @@ const fetchTimeline = ({
|
||||||
|
|
||||||
let url = timelineUrls[timeline]
|
let url = timelineUrls[timeline]
|
||||||
|
|
||||||
if (timeline === 'user' || timeline === 'media') {
|
if (timeline === 'user' || timeline === 'media' || timeline === 'replies') {
|
||||||
url = url(userId)
|
url = url(userId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -658,6 +688,9 @@ const fetchTimeline = ({
|
||||||
if (replyVisibility !== 'all') {
|
if (replyVisibility !== 'all') {
|
||||||
params.push(['reply_visibility', replyVisibility])
|
params.push(['reply_visibility', replyVisibility])
|
||||||
}
|
}
|
||||||
|
if (timeline === 'user') {
|
||||||
|
params.push(['exclude_replies', 1])
|
||||||
|
}
|
||||||
|
|
||||||
params.push(['limit', 20])
|
params.push(['limit', 20])
|
||||||
|
|
||||||
|
@ -738,6 +771,18 @@ const unretweet = ({ id, credentials }) => {
|
||||||
.then((data) => parseStatus(data))
|
.then((data) => parseStatus(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getSupportedTranslationlanguages = ({ credentials }) => {
|
||||||
|
return promisedRequest({ url: AKKOMA_LANGUAGES_URL, credentials })
|
||||||
|
}
|
||||||
|
|
||||||
|
const translateStatus = ({ id, credentials, language, from }) => {
|
||||||
|
const queryString = from ? `?from=${from}` : ''
|
||||||
|
return promisedRequest({ url: AKKOMA_TRANSLATE_URL(id, language) + queryString, method: 'GET', credentials })
|
||||||
|
.then((data) => {
|
||||||
|
return data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const bookmarkStatus = ({ id, credentials }) => {
|
const bookmarkStatus = ({ id, credentials }) => {
|
||||||
return promisedRequest({
|
return promisedRequest({
|
||||||
url: MASTODON_BOOKMARK_STATUS_URL(id),
|
url: MASTODON_BOOKMARK_STATUS_URL(id),
|
||||||
|
@ -819,6 +864,54 @@ const postStatus = ({
|
||||||
.then((data) => data.error ? data : parseStatus(data))
|
.then((data) => data.error ? data : parseStatus(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const editStatus = ({
|
||||||
|
id,
|
||||||
|
credentials,
|
||||||
|
status,
|
||||||
|
spoilerText,
|
||||||
|
sensitive,
|
||||||
|
poll,
|
||||||
|
mediaIds = [],
|
||||||
|
contentType
|
||||||
|
}) => {
|
||||||
|
const form = new FormData()
|
||||||
|
const pollOptions = poll.options || []
|
||||||
|
|
||||||
|
form.append('status', status)
|
||||||
|
if (spoilerText) form.append('spoiler_text', spoilerText)
|
||||||
|
if (sensitive) form.append('sensitive', sensitive)
|
||||||
|
if (contentType) form.append('content_type', contentType)
|
||||||
|
mediaIds.forEach(val => {
|
||||||
|
form.append('media_ids[]', val)
|
||||||
|
})
|
||||||
|
|
||||||
|
if (pollOptions.some(option => option !== '')) {
|
||||||
|
const normalizedPoll = {
|
||||||
|
expires_in: poll.expiresIn,
|
||||||
|
multiple: poll.multiple
|
||||||
|
}
|
||||||
|
Object.keys(normalizedPoll).forEach(key => {
|
||||||
|
form.append(`poll[${key}]`, normalizedPoll[key])
|
||||||
|
})
|
||||||
|
|
||||||
|
pollOptions.forEach(option => {
|
||||||
|
form.append('poll[options][]', option)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
let putHeaders = authHeaders(credentials)
|
||||||
|
|
||||||
|
return fetch(MASTODON_STATUS_URL(id), {
|
||||||
|
body: form,
|
||||||
|
method: 'PUT',
|
||||||
|
headers: putHeaders
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
return response.json()
|
||||||
|
})
|
||||||
|
.then((data) => data.error ? data : parseStatus(data))
|
||||||
|
}
|
||||||
|
|
||||||
const deleteStatus = ({ id, credentials }) => {
|
const deleteStatus = ({ id, credentials }) => {
|
||||||
return fetch(MASTODON_DELETE_URL(id), {
|
return fetch(MASTODON_DELETE_URL(id), {
|
||||||
headers: authHeaders(credentials),
|
headers: authHeaders(credentials),
|
||||||
|
@ -1375,7 +1468,8 @@ const MASTODON_STREAMING_EVENTS = new Set([
|
||||||
'update',
|
'update',
|
||||||
'notification',
|
'notification',
|
||||||
'delete',
|
'delete',
|
||||||
'filters_changed'
|
'filters_changed',
|
||||||
|
'status.update'
|
||||||
])
|
])
|
||||||
|
|
||||||
const PLEROMA_STREAMING_EVENTS = new Set([
|
const PLEROMA_STREAMING_EVENTS = new Set([
|
||||||
|
@ -1456,6 +1550,8 @@ export const handleMastoWS = (wsEvent) => {
|
||||||
const data = payload ? JSON.parse(payload) : null
|
const data = payload ? JSON.parse(payload) : null
|
||||||
if (event === 'update') {
|
if (event === 'update') {
|
||||||
return { event, status: parseStatus(data) }
|
return { event, status: parseStatus(data) }
|
||||||
|
} else if (event === 'status.update') {
|
||||||
|
return { event, status: parseStatus(data) }
|
||||||
} else if (event === 'notification') {
|
} else if (event === 'notification') {
|
||||||
return { event, notification: parseNotification(data) }
|
return { event, notification: parseNotification(data) }
|
||||||
}
|
}
|
||||||
|
@ -1480,6 +1576,8 @@ const apiService = {
|
||||||
fetchPinnedStatuses,
|
fetchPinnedStatuses,
|
||||||
fetchConversation,
|
fetchConversation,
|
||||||
fetchStatus,
|
fetchStatus,
|
||||||
|
fetchStatusSource,
|
||||||
|
fetchStatusHistory,
|
||||||
fetchFriends,
|
fetchFriends,
|
||||||
exportFriends,
|
exportFriends,
|
||||||
fetchFollowers,
|
fetchFollowers,
|
||||||
|
@ -1500,6 +1598,7 @@ const apiService = {
|
||||||
bookmarkStatus,
|
bookmarkStatus,
|
||||||
unbookmarkStatus,
|
unbookmarkStatus,
|
||||||
postStatus,
|
postStatus,
|
||||||
|
editStatus,
|
||||||
deleteStatus,
|
deleteStatus,
|
||||||
uploadMedia,
|
uploadMedia,
|
||||||
setMediaDescription,
|
setMediaDescription,
|
||||||
|
@ -1576,7 +1675,9 @@ const apiService = {
|
||||||
postAnnouncement,
|
postAnnouncement,
|
||||||
editAnnouncement,
|
editAnnouncement,
|
||||||
deleteAnnouncement,
|
deleteAnnouncement,
|
||||||
adminFetchAnnouncements
|
adminFetchAnnouncements,
|
||||||
|
translateStatus,
|
||||||
|
getSupportedTranslationlanguages
|
||||||
}
|
}
|
||||||
|
|
||||||
export default apiService
|
export default apiService
|
||||||
|
|
|
@ -40,6 +40,10 @@ const backendInteractorService = credentials => ({
|
||||||
return ProcessedWS({ url, id: 'User' })
|
return ProcessedWS({ url, id: 'User' })
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getSupportedTranslationlanguages ({ store }) {
|
||||||
|
return apiService.getSupportedTranslationlanguages({ store, credentials })
|
||||||
|
},
|
||||||
|
|
||||||
...Object.entries(apiService).reduce((acc, [key, func]) => {
|
...Object.entries(apiService).reduce((acc, [key, func]) => {
|
||||||
return {
|
return {
|
||||||
...acc,
|
...acc,
|
||||||
|
|
|
@ -242,6 +242,16 @@ export const parseAttachment = (data) => {
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const parseSource = (data) => {
|
||||||
|
const output = {}
|
||||||
|
|
||||||
|
output.text = data.text
|
||||||
|
output.spoiler_text = data.spoiler_text
|
||||||
|
output.content_type = data.content_type
|
||||||
|
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
export const parseStatus = (data) => {
|
export const parseStatus = (data) => {
|
||||||
const output = {}
|
const output = {}
|
||||||
const masto = data.hasOwnProperty('account')
|
const masto = data.hasOwnProperty('account')
|
||||||
|
@ -263,6 +273,8 @@ export const parseStatus = (data) => {
|
||||||
|
|
||||||
output.tags = data.tags
|
output.tags = data.tags
|
||||||
|
|
||||||
|
output.edited_at = data.edited_at
|
||||||
|
|
||||||
if (data.pleroma) {
|
if (data.pleroma) {
|
||||||
const { pleroma } = data
|
const { pleroma } = data
|
||||||
output.text = pleroma.content ? data.pleroma.content['text/plain'] : data.content
|
output.text = pleroma.content ? data.pleroma.content['text/plain'] : data.content
|
||||||
|
@ -374,6 +386,10 @@ export const parseStatus = (data) => {
|
||||||
output.favoritedBy = []
|
output.favoritedBy = []
|
||||||
output.rebloggedBy = []
|
output.rebloggedBy = []
|
||||||
|
|
||||||
|
if (data.hasOwnProperty('originalStatus')) {
|
||||||
|
Object.assign(output, data.originalStatus)
|
||||||
|
}
|
||||||
|
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,47 @@ const postStatus = ({
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const editStatus = ({
|
||||||
|
store,
|
||||||
|
statusId,
|
||||||
|
status,
|
||||||
|
spoilerText,
|
||||||
|
sensitive,
|
||||||
|
poll,
|
||||||
|
media = [],
|
||||||
|
contentType = 'text/plain'
|
||||||
|
}) => {
|
||||||
|
const mediaIds = map(media, 'id')
|
||||||
|
|
||||||
|
return apiService.editStatus({
|
||||||
|
id: statusId,
|
||||||
|
credentials: store.state.users.currentUser.credentials,
|
||||||
|
status,
|
||||||
|
spoilerText,
|
||||||
|
sensitive,
|
||||||
|
poll,
|
||||||
|
mediaIds,
|
||||||
|
contentType
|
||||||
|
})
|
||||||
|
.then((data) => {
|
||||||
|
if (!data.error) {
|
||||||
|
store.dispatch('addNewStatuses', {
|
||||||
|
statuses: [data],
|
||||||
|
timeline: 'friends',
|
||||||
|
showImmediately: true,
|
||||||
|
noIdUpdate: true // To prevent missing notices on next pull.
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error('Error editing status', err)
|
||||||
|
return {
|
||||||
|
error: err.message
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
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 })
|
||||||
|
@ -61,6 +102,7 @@ const setMediaDescription = ({ store, id, description }) => {
|
||||||
|
|
||||||
const statusPosterService = {
|
const statusPosterService = {
|
||||||
postStatus,
|
postStatus,
|
||||||
|
editStatus,
|
||||||
uploadMedia,
|
uploadMedia,
|
||||||
setMediaDescription
|
setMediaDescription
|
||||||
}
|
}
|
||||||
|
|
15
yarn.lock
15
yarn.lock
|
@ -1085,6 +1085,11 @@
|
||||||
minimatch "^3.1.2"
|
minimatch "^3.1.2"
|
||||||
strip-json-comments "^3.1.1"
|
strip-json-comments "^3.1.1"
|
||||||
|
|
||||||
|
"@fortawesome/fontawesome-common-types@6.1.2":
|
||||||
|
version "6.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.1.2.tgz#c1095b1bbabf19f37f9ff0719db38d92a410bcfe"
|
||||||
|
integrity sha512-wBaAPGz1Awxg05e0PBRkDRuTsy4B3dpBm+zreTTyd9TH4uUM27cAL4xWyWR0rLJCrRwzVsQ4hF3FvM6rqydKPA==
|
||||||
|
|
||||||
"@fortawesome/fontawesome-common-types@^0.2.36":
|
"@fortawesome/fontawesome-common-types@^0.2.36":
|
||||||
version "0.2.36"
|
version "0.2.36"
|
||||||
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.36.tgz#b44e52db3b6b20523e0c57ef8c42d315532cb903"
|
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.36.tgz#b44e52db3b6b20523e0c57ef8c42d315532cb903"
|
||||||
|
@ -1102,12 +1107,12 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@fortawesome/fontawesome-common-types" "^0.3.0"
|
"@fortawesome/fontawesome-common-types" "^0.3.0"
|
||||||
|
|
||||||
"@fortawesome/free-regular-svg-icons@5.15.4":
|
"@fortawesome/free-regular-svg-icons@^6.1.2":
|
||||||
version "5.15.4"
|
version "6.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-5.15.4.tgz#b97edab436954333bbeac09cfc40c6a951081a02"
|
resolved "https://registry.yarnpkg.com/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.1.2.tgz#9f04009098addcc11d0d185126f058ed042c3099"
|
||||||
integrity sha512-9VNNnU3CXHy9XednJ3wzQp6SwNwT3XaM26oS4Rp391GsxVYA+0oDR2J194YCIWf7jNRCYKjUCOduxdceLrx+xw==
|
integrity sha512-xR4hA+tAwsaTHGfb+25H1gVU/aJ0Rzu+xIUfnyrhaL13yNQ7TWiI2RvzniAaB+VGHDU2a+Pk96Ve+pkN3/+TTQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@fortawesome/fontawesome-common-types" "^0.2.36"
|
"@fortawesome/fontawesome-common-types" "6.1.2"
|
||||||
|
|
||||||
"@fortawesome/free-solid-svg-icons@5.15.4":
|
"@fortawesome/free-solid-svg-icons@5.15.4":
|
||||||
version "5.15.4"
|
version "5.15.4"
|
||||||
|
|
Loading…
Reference in a new issue