update develop
This commit is contained in:
commit
a72a155098
103 changed files with 8606 additions and 6698 deletions
13
CHANGELOG.md
13
CHANGELOG.md
|
|
@ -6,16 +6,29 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
### Changed
|
### Changed
|
||||||
- Removed the use of with_move parameters when fetching notifications
|
- Removed the use of with_move parameters when fetching notifications
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Weird bug related to post being sent seemingly after pasting with keyboard (hopefully)
|
||||||
|
- Multiple issues with muted statuses/notifications
|
||||||
|
|
||||||
## [Unreleased patch]
|
## [Unreleased patch]
|
||||||
### Add
|
### Add
|
||||||
- Added private notifications option for push notifications
|
- Added private notifications option for push notifications
|
||||||
- 'Copy link' button for statuses (in the ellipsis menu)
|
- 'Copy link' button for statuses (in the ellipsis menu)
|
||||||
|
- Autocomplete domains from list of known instances
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Registration page no longer requires email if the server is configured not to require it
|
- Registration page no longer requires email if the server is configured not to require it
|
||||||
|
- Change heart to thumbs up in reaction picker
|
||||||
|
- Close the media modal on navigation events
|
||||||
|
- Add colons to the emoji alt text, to make them copyable
|
||||||
|
- Add better visual indication for drag-and-drop for files
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Status ellipsis menu closes properly when selecting certain options
|
- Status ellipsis menu closes properly when selecting certain options
|
||||||
|
- Cropped images look correct in Chrome
|
||||||
|
- Newlines in the muted words settings work again
|
||||||
|
- Clicking on non-latin hashtags won't open a new window
|
||||||
|
- Uploading and drag-dropping multiple files works correctly now.
|
||||||
|
|
||||||
## [2.0.3] - 2020-05-02
|
## [2.0.3] - 2020-05-02
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# pleroma_fe
|
# Pleroma-FE
|
||||||
|
|
||||||
> A single column frontend for both Pleroma and GS servers.
|
> A single column frontend designed for Pleroma.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
@ -11,7 +11,6 @@ To translate Pleroma-FE, add your language to [src/i18n/messages.js](https://git
|
||||||
# FOR ADMINS
|
# FOR ADMINS
|
||||||
|
|
||||||
You don't need to build Pleroma-FE yourself. Those using the Pleroma backend will be able to use it out of the box.
|
You don't need to build Pleroma-FE yourself. Those using the Pleroma backend will be able to use it out of the box.
|
||||||
For the GNU social backend, check out https://git.pleroma.social/pleroma/pleroma-fe/wikis/dual-boot-with-qvitter to see how to run Pleroma-FE and Qvitter at the same time.
|
|
||||||
|
|
||||||
## Build Setup
|
## Build Setup
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ will become
|
||||||
Note that you can only use emoji defined on your instance, you cannot "copy" someone else's emoji, and will have to ask your administrator to copy emoji from other instance to yours.
|
Note that you can only use emoji defined on your instance, you cannot "copy" someone else's emoji, and will have to ask your administrator to copy emoji from other instance to yours.
|
||||||
Lastly, there's two convenience options for emoji: an emoji picker (smiley face to the right of "submit" button) and autocomplete suggestions - when you start typing :shortcode: it will automatically try to suggest you emoj and complete the shortcode for you if you select one. **Note** that if emoji doesn't show up in suggestions nor in emoji picker it means there's no such emoji on your instance, if shortcode doesn't match any defined emoji it will appear as text.
|
Lastly, there's two convenience options for emoji: an emoji picker (smiley face to the right of "submit" button) and autocomplete suggestions - when you start typing :shortcode: it will automatically try to suggest you emoj and complete the shortcode for you if you select one. **Note** that if emoji doesn't show up in suggestions nor in emoji picker it means there's no such emoji on your instance, if shortcode doesn't match any defined emoji it will appear as text.
|
||||||
* **Attachments** are fairly simple - you can attach any file to a post as long as the file is within maximum size limits. If you're uploading explicit material you can mark all of your attachments as sensitive (or add `#nsfw` tag) - it will hide the images and videos behind a warning so that it won't be displayed instantly.
|
* **Attachments** are fairly simple - you can attach any file to a post as long as the file is within maximum size limits. If you're uploading explicit material you can mark all of your attachments as sensitive (or add `#nsfw` tag) - it will hide the images and videos behind a warning so that it won't be displayed instantly.
|
||||||
* **Subject line** also known as **CW** (Content Warning) could be used as a header to the post and/or to warn others about contents of the post having something that might upset somebody or something among those lines. Several applications allow to hide post content leaving only subject line visible. As a side-effect using subject line will also mark your images as sensitive (see above).
|
* **Subject line** also known as **CW** (Content Warning) could be used as a header to the post and/or to warn others about contents of the post having something that might upset somebody or something among those lines. Several applications allow to hide post content leaving only subject line visible. Using a subject line will not mark your images as sensitive, you will have to do that explicitly (see above).
|
||||||
* **Visiblity scope** controls who will be able to see your posts. There are four scopes available:
|
* **Visiblity scope** controls who will be able to see your posts. There are four scopes available:
|
||||||
|
|
||||||
1. `Public`: This is the default, and some fediverse software like GNU Social only supports this. This means that your post is accessible by anyone and will be shown in the public timelines.
|
1. `Public`: This is the default, and some fediverse software like GNU Social only supports this. This means that your post is accessible by anyone and will be shown in the public timelines.
|
||||||
|
|
|
||||||
|
|
@ -29,11 +29,11 @@
|
||||||
"portal-vue": "^2.1.4",
|
"portal-vue": "^2.1.4",
|
||||||
"sanitize-html": "^1.13.0",
|
"sanitize-html": "^1.13.0",
|
||||||
"v-click-outside": "^2.1.1",
|
"v-click-outside": "^2.1.1",
|
||||||
"vue": "^2.5.13",
|
"vue": "^2.6.11",
|
||||||
"vue-chat-scroll": "^1.2.1",
|
"vue-chat-scroll": "^1.2.1",
|
||||||
"vue-i18n": "^7.3.2",
|
"vue-i18n": "^7.3.2",
|
||||||
"vue-router": "^3.0.1",
|
"vue-router": "^3.0.1",
|
||||||
"vue-template-compiler": "^2.3.4",
|
"vue-template-compiler": "^2.6.11",
|
||||||
"vuelidate": "^0.7.4",
|
"vuelidate": "^0.7.4",
|
||||||
"vuex": "^3.0.1",
|
"vuex": "^3.0.1",
|
||||||
"whatwg-fetch": "^2.0.3"
|
"whatwg-fetch": "^2.0.3"
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import InstanceSpecificPanel from './components/instance_specific_panel/instance
|
||||||
import FeaturesPanel from './components/features_panel/features_panel.vue'
|
import FeaturesPanel from './components/features_panel/features_panel.vue'
|
||||||
import WhoToFollowPanel from './components/who_to_follow_panel/who_to_follow_panel.vue'
|
import WhoToFollowPanel from './components/who_to_follow_panel/who_to_follow_panel.vue'
|
||||||
import ChatPanel from './components/chat_panel/chat_panel.vue'
|
import ChatPanel from './components/chat_panel/chat_panel.vue'
|
||||||
|
import SettingsModal from './components/settings_modal/settings_modal.vue'
|
||||||
import MediaModal from './components/media_modal/media_modal.vue'
|
import MediaModal from './components/media_modal/media_modal.vue'
|
||||||
import SideDrawer from './components/side_drawer/side_drawer.vue'
|
import SideDrawer from './components/side_drawer/side_drawer.vue'
|
||||||
import MobilePostStatusButton from './components/mobile_post_status_button/mobile_post_status_button.vue'
|
import MobilePostStatusButton from './components/mobile_post_status_button/mobile_post_status_button.vue'
|
||||||
|
|
@ -29,6 +30,7 @@ export default {
|
||||||
SideDrawer,
|
SideDrawer,
|
||||||
MobilePostStatusButton,
|
MobilePostStatusButton,
|
||||||
MobileNav,
|
MobileNav,
|
||||||
|
SettingsModal,
|
||||||
UserReportingModal,
|
UserReportingModal,
|
||||||
PostStatusModal
|
PostStatusModal
|
||||||
},
|
},
|
||||||
|
|
@ -45,7 +47,8 @@ export default {
|
||||||
}),
|
}),
|
||||||
created () {
|
created () {
|
||||||
// Load the locale from the storage
|
// Load the locale from the storage
|
||||||
this.$i18n.locale = this.$store.getters.mergedConfig.interfaceLanguage
|
const val = this.$store.getters.mergedConfig.interfaceLanguage
|
||||||
|
this.$store.dispatch('setOption', { name: 'interfaceLanguage', value: val })
|
||||||
window.addEventListener('resize', this.updateMobileState)
|
window.addEventListener('resize', this.updateMobileState)
|
||||||
},
|
},
|
||||||
destroyed () {
|
destroyed () {
|
||||||
|
|
@ -117,6 +120,9 @@ export default {
|
||||||
onSearchBarToggled (hidden) {
|
onSearchBarToggled (hidden) {
|
||||||
this.searchBarHidden = hidden
|
this.searchBarHidden = hidden
|
||||||
},
|
},
|
||||||
|
openSettingsModal () {
|
||||||
|
this.$store.dispatch('openSettingsModal')
|
||||||
|
},
|
||||||
updateMobileState () {
|
updateMobileState () {
|
||||||
const mobileLayout = windowWidth() <= 800
|
const mobileLayout = windowWidth() <= 800
|
||||||
const changed = mobileLayout !== this.isMobileLayout
|
const changed = mobileLayout !== this.isMobileLayout
|
||||||
|
|
|
||||||
47
src/App.scss
47
src/App.scss
|
|
@ -566,7 +566,7 @@ main-router {
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
margin-left: .25em;
|
margin-left: .5em;
|
||||||
min-width: 1px;
|
min-width: 1px;
|
||||||
align-self: stretch;
|
align-self: stretch;
|
||||||
}
|
}
|
||||||
|
|
@ -860,51 +860,6 @@ nav {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.setting-item {
|
|
||||||
border-bottom: 2px solid var(--fg, $fallback--fg);
|
|
||||||
margin: 1em 1em 1.4em;
|
|
||||||
padding-bottom: 1.4em;
|
|
||||||
|
|
||||||
> div {
|
|
||||||
margin-bottom: .5em;
|
|
||||||
&:last-child {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
border-bottom: none;
|
|
||||||
padding-bottom: 0;
|
|
||||||
margin-bottom: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
select {
|
|
||||||
min-width: 10em;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
textarea {
|
|
||||||
width: 100%;
|
|
||||||
max-width: 100%;
|
|
||||||
height: 100px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.unavailable,
|
|
||||||
.unavailable i {
|
|
||||||
color: var(--cRed, $fallback--cRed);
|
|
||||||
color: $fallback--cRed;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn {
|
|
||||||
min-height: 28px;
|
|
||||||
min-width: 10em;
|
|
||||||
padding: 0 2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.number-input {
|
|
||||||
max-width: 6em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.select-multiple {
|
.select-multiple {
|
||||||
display: flex;
|
display: flex;
|
||||||
.option-list {
|
.option-list {
|
||||||
|
|
|
||||||
|
|
@ -46,15 +46,16 @@
|
||||||
@toggled="onSearchBarToggled"
|
@toggled="onSearchBarToggled"
|
||||||
@click.stop.native
|
@click.stop.native
|
||||||
/>
|
/>
|
||||||
<router-link
|
<a
|
||||||
|
href="#"
|
||||||
class="mobile-hidden"
|
class="mobile-hidden"
|
||||||
:to="{ name: 'settings'}"
|
@click.stop="openSettingsModal"
|
||||||
>
|
>
|
||||||
<i
|
<i
|
||||||
class="button-icon icon-cog nav-icon"
|
class="button-icon icon-cog nav-icon"
|
||||||
:title="$t('nav.preferences')"
|
:title="$t('nav.preferences')"
|
||||||
/>
|
/>
|
||||||
</router-link>
|
</a>
|
||||||
<a
|
<a
|
||||||
v-if="currentUser && currentUser.role === 'admin'"
|
v-if="currentUser && currentUser.role === 'admin'"
|
||||||
href="/pleroma/admin/#/login-pleroma"
|
href="/pleroma/admin/#/login-pleroma"
|
||||||
|
|
@ -125,6 +126,7 @@
|
||||||
<MobilePostStatusButton />
|
<MobilePostStatusButton />
|
||||||
<UserReportingModal />
|
<UserReportingModal />
|
||||||
<PostStatusModal />
|
<PostStatusModal />
|
||||||
|
<SettingsModal />
|
||||||
<portal-target name="modal" />
|
<portal-target name="modal" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -110,6 +110,7 @@ const setSettings = async ({ apiConfig, staticConfig, store }) => {
|
||||||
copyInstanceOption('alwaysShowSubjectInput')
|
copyInstanceOption('alwaysShowSubjectInput')
|
||||||
copyInstanceOption('showFeaturesPanel')
|
copyInstanceOption('showFeaturesPanel')
|
||||||
copyInstanceOption('hideSitename')
|
copyInstanceOption('hideSitename')
|
||||||
|
copyInstanceOption('sidebarRight')
|
||||||
|
|
||||||
return store.dispatch('setTheme', config['theme'])
|
return store.dispatch('setTheme', config['theme'])
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,8 @@ import Interactions from 'components/interactions/interactions.vue'
|
||||||
import DMs from 'components/dm_timeline/dm_timeline.vue'
|
import DMs from 'components/dm_timeline/dm_timeline.vue'
|
||||||
import UserProfile from 'components/user_profile/user_profile.vue'
|
import UserProfile from 'components/user_profile/user_profile.vue'
|
||||||
import Search from 'components/search/search.vue'
|
import Search from 'components/search/search.vue'
|
||||||
import Settings from 'components/settings/settings.vue'
|
|
||||||
import Registration from 'components/registration/registration.vue'
|
import Registration from 'components/registration/registration.vue'
|
||||||
import PasswordReset from 'components/password_reset/password_reset.vue'
|
import PasswordReset from 'components/password_reset/password_reset.vue'
|
||||||
import UserSettings from 'components/user_settings/user_settings.vue'
|
|
||||||
import FollowRequests from 'components/follow_requests/follow_requests.vue'
|
import FollowRequests from 'components/follow_requests/follow_requests.vue'
|
||||||
import OAuthCallback from 'components/oauth_callback/oauth_callback.vue'
|
import OAuthCallback from 'components/oauth_callback/oauth_callback.vue'
|
||||||
import Notifications from 'components/notifications/notifications.vue'
|
import Notifications from 'components/notifications/notifications.vue'
|
||||||
|
|
@ -56,12 +54,10 @@ export default (store) => {
|
||||||
{ name: 'external-user-profile', path: '/users/:id', component: UserProfile },
|
{ name: 'external-user-profile', path: '/users/:id', component: UserProfile },
|
||||||
{ name: 'interactions', path: '/users/:username/interactions', component: Interactions, beforeEnter: validateAuthenticatedRoute },
|
{ name: 'interactions', path: '/users/:username/interactions', component: Interactions, beforeEnter: validateAuthenticatedRoute },
|
||||||
{ name: 'dms', path: '/users/:username/dms', component: DMs, beforeEnter: validateAuthenticatedRoute },
|
{ name: 'dms', path: '/users/:username/dms', component: DMs, beforeEnter: validateAuthenticatedRoute },
|
||||||
{ name: 'settings', path: '/settings', component: Settings },
|
|
||||||
{ name: 'registration', path: '/registration', component: Registration },
|
{ name: 'registration', path: '/registration', component: Registration },
|
||||||
{ name: 'password-reset', path: '/password-reset', component: PasswordReset, props: true },
|
{ name: 'password-reset', path: '/password-reset', component: PasswordReset, props: true },
|
||||||
{ name: 'registration-token', path: '/registration/:token', component: Registration },
|
{ name: 'registration-token', path: '/registration/:token', component: Registration },
|
||||||
{ name: 'friend-requests', path: '/friend-requests', component: FollowRequests, beforeEnter: validateAuthenticatedRoute },
|
{ name: 'friend-requests', path: '/friend-requests', component: FollowRequests, beforeEnter: validateAuthenticatedRoute },
|
||||||
{ name: 'user-settings', path: '/user-settings', component: UserSettings, beforeEnter: validateAuthenticatedRoute },
|
|
||||||
{ name: 'notifications', path: '/:username/notifications', component: Notifications, beforeEnter: validateAuthenticatedRoute },
|
{ name: 'notifications', path: '/:username/notifications', component: Notifications, beforeEnter: validateAuthenticatedRoute },
|
||||||
{ name: 'login', path: '/login', component: AuthForm },
|
{ name: 'login', path: '/login', component: AuthForm },
|
||||||
{ name: 'chat', path: '/chat', component: ChatPanel, props: () => ({ floating: false }) },
|
{ name: 'chat', path: '/chat', component: ChatPanel, props: () => ({ floating: false }) },
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
<template>
|
||||||
|
<div class="async-component-error">
|
||||||
|
<div>
|
||||||
|
<h4>
|
||||||
|
{{ $t('general.generic_error') }}
|
||||||
|
</h4>
|
||||||
|
<p>
|
||||||
|
{{ $t('general.error_retry') }}
|
||||||
|
</p>
|
||||||
|
<button
|
||||||
|
class="btn"
|
||||||
|
@click="retry"
|
||||||
|
>
|
||||||
|
{{ $t('general.retry') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
methods: {
|
||||||
|
retry () {
|
||||||
|
this.$emit('resetAsyncComponent')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.async-component-error {
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
.btn {
|
||||||
|
margin: .5em;
|
||||||
|
padding: .5em 2em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -5,9 +5,20 @@ const DomainMuteCard = {
|
||||||
components: {
|
components: {
|
||||||
ProgressButton
|
ProgressButton
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
user () {
|
||||||
|
return this.$store.state.users.currentUser
|
||||||
|
},
|
||||||
|
muted () {
|
||||||
|
return this.user.domainMutes.includes(this.domain)
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
unmuteDomain () {
|
unmuteDomain () {
|
||||||
return this.$store.dispatch('unmuteDomain', this.domain)
|
return this.$store.dispatch('unmuteDomain', this.domain)
|
||||||
|
},
|
||||||
|
muteDomain () {
|
||||||
|
return this.$store.dispatch('muteDomain', this.domain)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
{{ domain }}
|
{{ domain }}
|
||||||
</div>
|
</div>
|
||||||
<ProgressButton
|
<ProgressButton
|
||||||
|
v-if="muted"
|
||||||
:click="unmuteDomain"
|
:click="unmuteDomain"
|
||||||
class="btn btn-default"
|
class="btn btn-default"
|
||||||
>
|
>
|
||||||
|
|
@ -12,6 +13,16 @@
|
||||||
{{ $t('domain_mute_card.unmute_progress') }}
|
{{ $t('domain_mute_card.unmute_progress') }}
|
||||||
</template>
|
</template>
|
||||||
</ProgressButton>
|
</ProgressButton>
|
||||||
|
<ProgressButton
|
||||||
|
v-else
|
||||||
|
:click="muteDomain"
|
||||||
|
class="btn btn-default"
|
||||||
|
>
|
||||||
|
{{ $t('domain_mute_card.mute') }}
|
||||||
|
<template slot="progress">
|
||||||
|
{{ $t('domain_mute_card.mute_progress') }}
|
||||||
|
</template>
|
||||||
|
</ProgressButton>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -34,5 +45,9 @@
|
||||||
button {
|
button {
|
||||||
width: 10em;
|
width: 10em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.autosuggest-results & {
|
||||||
|
padding-left: 1em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ import _ from 'lodash'
|
||||||
export default {
|
export default {
|
||||||
computed: {
|
computed: {
|
||||||
languageCodes () {
|
languageCodes () {
|
||||||
return Object.keys(languagesObject)
|
return languagesObject.languages
|
||||||
},
|
},
|
||||||
|
|
||||||
languageNames () {
|
languageNames () {
|
||||||
|
|
@ -43,7 +43,6 @@ export default {
|
||||||
get: function () { return this.$store.getters.mergedConfig.interfaceLanguage },
|
get: function () { return this.$store.getters.mergedConfig.interfaceLanguage },
|
||||||
set: function (val) {
|
set: function (val) {
|
||||||
this.$store.dispatch('setOption', { name: 'interfaceLanguage', value: val })
|
this.$store.dispatch('setOption', { name: 'interfaceLanguage', value: val })
|
||||||
this.$i18n.locale = val
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -84,10 +84,12 @@ const MediaModal = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
|
window.addEventListener('popstate', this.hide)
|
||||||
document.addEventListener('keyup', this.handleKeyupEvent)
|
document.addEventListener('keyup', this.handleKeyupEvent)
|
||||||
document.addEventListener('keydown', this.handleKeydownEvent)
|
document.addEventListener('keydown', this.handleKeydownEvent)
|
||||||
},
|
},
|
||||||
destroyed () {
|
destroyed () {
|
||||||
|
window.removeEventListener('popstate', this.hide)
|
||||||
document.removeEventListener('keyup', this.handleKeyupEvent)
|
document.removeEventListener('keyup', this.handleKeyupEvent)
|
||||||
document.removeEventListener('keydown', this.handleKeydownEvent)
|
document.removeEventListener('keydown', this.handleKeydownEvent)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,15 @@ import fileSizeFormatService from '../../services/file_size_format/file_size_for
|
||||||
const mediaUpload = {
|
const mediaUpload = {
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
uploading: false,
|
uploadCount: 0,
|
||||||
uploadReady: true
|
uploadReady: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
uploading () {
|
||||||
|
return this.uploadCount > 0
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
uploadFile (file) {
|
uploadFile (file) {
|
||||||
const self = this
|
const self = this
|
||||||
|
|
@ -23,29 +28,21 @@ const mediaUpload = {
|
||||||
formData.append('file', file)
|
formData.append('file', file)
|
||||||
|
|
||||||
self.$emit('uploading')
|
self.$emit('uploading')
|
||||||
self.uploading = true
|
self.uploadCount++
|
||||||
|
|
||||||
statusPosterService.uploadMedia({ store, formData })
|
statusPosterService.uploadMedia({ store, formData })
|
||||||
.then((fileData) => {
|
.then((fileData) => {
|
||||||
self.$emit('uploaded', fileData)
|
self.$emit('uploaded', fileData)
|
||||||
self.uploading = false
|
self.decreaseUploadCount()
|
||||||
}, (error) => { // eslint-disable-line handle-callback-err
|
}, (error) => { // eslint-disable-line handle-callback-err
|
||||||
self.$emit('upload-failed', 'default')
|
self.$emit('upload-failed', 'default')
|
||||||
self.uploading = false
|
self.decreaseUploadCount()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
fileDrop (e) {
|
decreaseUploadCount () {
|
||||||
if (e.dataTransfer.files.length > 0) {
|
this.uploadCount--
|
||||||
e.preventDefault() // allow dropping text like before
|
if (this.uploadCount === 0) {
|
||||||
this.uploadFile(e.dataTransfer.files[0])
|
this.$emit('all-uploaded')
|
||||||
}
|
|
||||||
},
|
|
||||||
fileDrag (e) {
|
|
||||||
let types = e.dataTransfer.types
|
|
||||||
if (types.contains('Files')) {
|
|
||||||
e.dataTransfer.dropEffect = 'copy'
|
|
||||||
} else {
|
|
||||||
e.dataTransfer.dropEffect = 'none'
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
clearFile () {
|
clearFile () {
|
||||||
|
|
@ -54,11 +51,13 @@ const mediaUpload = {
|
||||||
this.uploadReady = true
|
this.uploadReady = true
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
change ({ target }) {
|
multiUpload (files) {
|
||||||
for (var i = 0; i < target.files.length; i++) {
|
for (const file of files) {
|
||||||
let file = target.files[i]
|
|
||||||
this.uploadFile(file)
|
this.uploadFile(file)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
change ({ target }) {
|
||||||
|
this.multiUpload(target.files)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
props: [
|
props: [
|
||||||
|
|
@ -67,7 +66,7 @@ const mediaUpload = {
|
||||||
watch: {
|
watch: {
|
||||||
'dropFiles': function (fileInfos) {
|
'dropFiles': function (fileInfos) {
|
||||||
if (!this.uploading) {
|
if (!this.uploading) {
|
||||||
this.uploadFile(fileInfos[0])
|
this.multiUpload(fileInfos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div class="media-upload">
|
||||||
class="media-upload"
|
|
||||||
@drop.prevent
|
|
||||||
@dragover.prevent="fileDrag"
|
|
||||||
@drop="fileDrop"
|
|
||||||
>
|
|
||||||
<label
|
<label
|
||||||
class="label"
|
class="label"
|
||||||
:title="$t('tool_tip.media_upload')"
|
:title="$t('tool_tip.media_upload')"
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
v-show="isOpen"
|
v-show="isOpen"
|
||||||
v-body-scroll-lock="isOpen"
|
v-body-scroll-lock="isOpen && !noBackground"
|
||||||
class="modal-view"
|
class="modal-view"
|
||||||
|
:class="classes"
|
||||||
@click.self="$emit('backdropClicked')"
|
@click.self="$emit('backdropClicked')"
|
||||||
>
|
>
|
||||||
<slot />
|
<slot />
|
||||||
|
|
@ -15,6 +16,18 @@ export default {
|
||||||
isOpen: {
|
isOpen: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true
|
||||||
|
},
|
||||||
|
noBackground: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
classes () {
|
||||||
|
return {
|
||||||
|
'modal-background': !this.noBackground,
|
||||||
|
'open': this.isOpen
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -32,12 +45,22 @@ export default {
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
pointer-events: none;
|
||||||
animation-duration: 0.2s;
|
animation-duration: 0.2s;
|
||||||
background-color: rgba(0, 0, 0, 0.5);
|
|
||||||
animation-name: modal-background-fadein;
|
animation-name: modal-background-fadein;
|
||||||
|
|
||||||
body:not(.scroll-locked) & {
|
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
|
||||||
|
> * {
|
||||||
|
pointer-events: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.modal-background {
|
||||||
|
pointer-events: initial;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.open {
|
||||||
|
opacity: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import StatusContent from '../status_content/status_content.vue'
|
||||||
import Status from '../status/status.vue'
|
import Status from '../status/status.vue'
|
||||||
import UserAvatar from '../user_avatar/user_avatar.vue'
|
import UserAvatar from '../user_avatar/user_avatar.vue'
|
||||||
import UserCard from '../user_card/user_card.vue'
|
import UserCard from '../user_card/user_card.vue'
|
||||||
|
|
@ -16,10 +17,11 @@ const Notification = {
|
||||||
},
|
},
|
||||||
props: [ 'notification' ],
|
props: [ 'notification' ],
|
||||||
components: {
|
components: {
|
||||||
Status,
|
StatusContent,
|
||||||
UserAvatar,
|
UserAvatar,
|
||||||
UserCard,
|
UserCard,
|
||||||
Timeago
|
Timeago,
|
||||||
|
Status
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
toggleUserExpanded () {
|
toggleUserExpanded () {
|
||||||
|
|
|
||||||
|
|
@ -157,11 +157,9 @@
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<status
|
<status-content
|
||||||
class="faint"
|
class="faint"
|
||||||
:compact="true"
|
:status="notification.action"
|
||||||
:statusoid="notification.action"
|
|
||||||
:no-heading="true"
|
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,8 @@
|
||||||
border-bottom: 1px solid;
|
border-bottom: 1px solid;
|
||||||
border-color: $fallback--border;
|
border-color: $fallback--border;
|
||||||
border-color: var(--border, $fallback--border);
|
border-color: var(--border, $fallback--border);
|
||||||
|
word-wrap: break-word;
|
||||||
|
word-break: break-word;
|
||||||
|
|
||||||
&:hover .animated.avatar {
|
&:hover .animated.avatar {
|
||||||
canvas {
|
canvas {
|
||||||
|
|
@ -46,10 +48,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.muted {
|
|
||||||
padding: .25em .6em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.non-mention {
|
.non-mention {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
|
|
||||||
29
src/components/panel_loading/panel_loading.vue
Normal file
29
src/components/panel_loading/panel_loading.vue
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
<template>
|
||||||
|
<div class="panel-loading">
|
||||||
|
<span class="loading-text">
|
||||||
|
<i class="icon-spin4 animate-spin" />
|
||||||
|
{{ $t('general.loading') }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@import 'src/_variables.scss';
|
||||||
|
|
||||||
|
.panel-loading {
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 2em;
|
||||||
|
color: $fallback--text;
|
||||||
|
color: var(--text, $fallback--text);
|
||||||
|
.loading-text i {
|
||||||
|
font-size: 3em;
|
||||||
|
line-height: 0;
|
||||||
|
vertical-align: middle;
|
||||||
|
color: $fallback--text;
|
||||||
|
color: var(--text, $fallback--text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -82,7 +82,9 @@ const PostStatusForm = {
|
||||||
contentType
|
contentType
|
||||||
},
|
},
|
||||||
caret: 0,
|
caret: 0,
|
||||||
pollFormVisible: false
|
pollFormVisible: false,
|
||||||
|
showDropIcon: 'hide',
|
||||||
|
dropStopTimeout: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
@ -218,7 +220,6 @@ const PostStatusForm = {
|
||||||
},
|
},
|
||||||
addMediaFile (fileInfo) {
|
addMediaFile (fileInfo) {
|
||||||
this.newStatus.files.push(fileInfo)
|
this.newStatus.files.push(fileInfo)
|
||||||
this.enableSubmit()
|
|
||||||
},
|
},
|
||||||
removeMediaFile (fileInfo) {
|
removeMediaFile (fileInfo) {
|
||||||
let index = this.newStatus.files.indexOf(fileInfo)
|
let index = this.newStatus.files.indexOf(fileInfo)
|
||||||
|
|
@ -227,7 +228,6 @@ const PostStatusForm = {
|
||||||
uploadFailed (errString, templateArgs) {
|
uploadFailed (errString, templateArgs) {
|
||||||
templateArgs = templateArgs || {}
|
templateArgs = templateArgs || {}
|
||||||
this.error = this.$t('upload.error.base') + ' ' + this.$t('upload.error.' + errString, templateArgs)
|
this.error = this.$t('upload.error.base') + ' ' + this.$t('upload.error.' + errString, templateArgs)
|
||||||
this.enableSubmit()
|
|
||||||
},
|
},
|
||||||
disableSubmit () {
|
disableSubmit () {
|
||||||
this.submitDisabled = true
|
this.submitDisabled = true
|
||||||
|
|
@ -250,13 +250,27 @@ const PostStatusForm = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fileDrop (e) {
|
fileDrop (e) {
|
||||||
if (e.dataTransfer.files.length > 0) {
|
if (e.dataTransfer && e.dataTransfer.types.includes('Files')) {
|
||||||
e.preventDefault() // allow dropping text like before
|
e.preventDefault() // allow dropping text like before
|
||||||
this.dropFiles = e.dataTransfer.files
|
this.dropFiles = e.dataTransfer.files
|
||||||
|
clearTimeout(this.dropStopTimeout)
|
||||||
|
this.showDropIcon = 'hide'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
fileDragStop (e) {
|
||||||
|
// The false-setting is done with delay because just using leave-events
|
||||||
|
// directly caused unwanted flickering, this is not perfect either but
|
||||||
|
// much less noticable.
|
||||||
|
clearTimeout(this.dropStopTimeout)
|
||||||
|
this.showDropIcon = 'fade'
|
||||||
|
this.dropStopTimeout = setTimeout(() => (this.showDropIcon = 'hide'), 500)
|
||||||
|
},
|
||||||
fileDrag (e) {
|
fileDrag (e) {
|
||||||
e.dataTransfer.dropEffect = 'copy'
|
e.dataTransfer.dropEffect = 'copy'
|
||||||
|
if (e.dataTransfer && e.dataTransfer.types.includes('Files')) {
|
||||||
|
clearTimeout(this.dropStopTimeout)
|
||||||
|
this.showDropIcon = 'show'
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onEmojiInputInput (e) {
|
onEmojiInputInput (e) {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,15 @@
|
||||||
<form
|
<form
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
@submit.prevent="postStatus(newStatus)"
|
@submit.prevent="postStatus(newStatus)"
|
||||||
|
@dragover.prevent="fileDrag"
|
||||||
>
|
>
|
||||||
|
<div
|
||||||
|
v-show="showDropIcon !== 'hide'"
|
||||||
|
:style="{ animation: showDropIcon === 'show' ? 'fade-in 0.25s' : 'fade-out 0.5s' }"
|
||||||
|
class="drop-indicator icon-upload"
|
||||||
|
@dragleave="fileDragStop"
|
||||||
|
@drop.stop="fileDrop"
|
||||||
|
/>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<i18n
|
<i18n
|
||||||
v-if="!$store.state.users.currentUser.locked && newStatus.visibility == 'private'"
|
v-if="!$store.state.users.currentUser.locked && newStatus.visibility == 'private'"
|
||||||
|
|
@ -96,9 +104,7 @@
|
||||||
:disabled="posting"
|
:disabled="posting"
|
||||||
class="form-post-body"
|
class="form-post-body"
|
||||||
@keydown.meta.enter="postStatus(newStatus)"
|
@keydown.meta.enter="postStatus(newStatus)"
|
||||||
@keyup.ctrl.enter="postStatus(newStatus)"
|
@keydown.ctrl.enter="postStatus(newStatus)"
|
||||||
@drop="fileDrop"
|
|
||||||
@dragover.prevent="fileDrag"
|
|
||||||
@input="resize"
|
@input="resize"
|
||||||
@compositionupdate="resize"
|
@compositionupdate="resize"
|
||||||
@paste="paste"
|
@paste="paste"
|
||||||
|
|
@ -172,6 +178,7 @@
|
||||||
@uploading="disableSubmit"
|
@uploading="disableSubmit"
|
||||||
@uploaded="addMediaFile"
|
@uploaded="addMediaFile"
|
||||||
@upload-failed="uploadFailed"
|
@upload-failed="uploadFailed"
|
||||||
|
@all-uploaded="enableSubmit"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
class="emoji-icon"
|
class="emoji-icon"
|
||||||
|
|
@ -446,7 +453,8 @@
|
||||||
form {
|
form {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding: 0.6em;
|
margin: 0.6em;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-group {
|
.form-group {
|
||||||
|
|
@ -504,5 +512,35 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
z-index: 4;
|
z-index: 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes fade-in {
|
||||||
|
from { opacity: 0; }
|
||||||
|
to { opacity: 0.6; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fade-out {
|
||||||
|
from { opacity: 0.6; }
|
||||||
|
to { opacity: 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.drop-indicator {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
font-size: 5em;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
opacity: 0.6;
|
||||||
|
color: $fallback--text;
|
||||||
|
color: var(--text, $fallback--text);
|
||||||
|
background-color: $fallback--bg;
|
||||||
|
background-color: var(--bg, $fallback--bg);
|
||||||
|
border-radius: $fallback--tooltipRadius;
|
||||||
|
border-radius: var(--tooltipRadius, $fallback--tooltipRadius);
|
||||||
|
border: 2px dashed $fallback--text;
|
||||||
|
border: 2px dashed var(--text, $fallback--text);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -13,9 +13,6 @@ const PostStatusModal = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
isLoggedIn () {
|
|
||||||
return !!this.$store.state.users.currentUser
|
|
||||||
},
|
|
||||||
modalActivated () {
|
modalActivated () {
|
||||||
return this.$store.state.postStatus.modalActivated
|
return this.$store.state.postStatus.modalActivated
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<Modal
|
<Modal
|
||||||
v-if="isLoggedIn && !resettingForm"
|
|
||||||
:is-open="modalActivated"
|
:is-open="modalActivated"
|
||||||
class="post-form-modal-view"
|
class="post-form-modal-view"
|
||||||
@backdropClicked="closeModal"
|
@backdropClicked="closeModal"
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ const ReactButton = {
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
commonEmojis () {
|
commonEmojis () {
|
||||||
return ['❤️', '😠', '👀', '😂', '🔥']
|
return ['👍', '😠', '👀', '😂', '🔥']
|
||||||
},
|
},
|
||||||
emojis () {
|
emojis () {
|
||||||
if (this.filterWord !== '') {
|
if (this.filterWord !== '') {
|
||||||
|
|
|
||||||
|
|
@ -1,128 +0,0 @@
|
||||||
/* eslint-env browser */
|
|
||||||
import { filter, trim } from 'lodash'
|
|
||||||
|
|
||||||
import TabSwitcher from '../tab_switcher/tab_switcher.js'
|
|
||||||
import StyleSwitcher from '../style_switcher/style_switcher.vue'
|
|
||||||
import InterfaceLanguageSwitcher from '../interface_language_switcher/interface_language_switcher.vue'
|
|
||||||
import { extractCommit } from '../../services/version/version.service'
|
|
||||||
import { instanceDefaultProperties, defaultState as configDefaultState } from '../../modules/config.js'
|
|
||||||
import Checkbox from '../checkbox/checkbox.vue'
|
|
||||||
|
|
||||||
const pleromaFeCommitUrl = 'https://git.pleroma.social/pleroma/pleroma-fe/commit/'
|
|
||||||
const pleromaBeCommitUrl = 'https://git.pleroma.social/pleroma/pleroma/commit/'
|
|
||||||
|
|
||||||
const multiChoiceProperties = [
|
|
||||||
'postContentType',
|
|
||||||
'subjectLineBehavior'
|
|
||||||
]
|
|
||||||
|
|
||||||
const settings = {
|
|
||||||
data () {
|
|
||||||
const instance = this.$store.state.instance
|
|
||||||
|
|
||||||
return {
|
|
||||||
loopSilentAvailable:
|
|
||||||
// Firefox
|
|
||||||
Object.getOwnPropertyDescriptor(HTMLVideoElement.prototype, 'mozHasAudio') ||
|
|
||||||
// Chrome-likes
|
|
||||||
Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'webkitAudioDecodedByteCount') ||
|
|
||||||
// Future spec, still not supported in Nightly 63 as of 08/2018
|
|
||||||
Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'audioTracks'),
|
|
||||||
|
|
||||||
backendVersion: instance.backendVersion,
|
|
||||||
frontendVersion: instance.frontendVersion
|
|
||||||
}
|
|
||||||
},
|
|
||||||
components: {
|
|
||||||
TabSwitcher,
|
|
||||||
StyleSwitcher,
|
|
||||||
InterfaceLanguageSwitcher,
|
|
||||||
Checkbox
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
user () {
|
|
||||||
return this.$store.state.users.currentUser
|
|
||||||
},
|
|
||||||
currentSaveStateNotice () {
|
|
||||||
return this.$store.state.interface.settings.currentSaveStateNotice
|
|
||||||
},
|
|
||||||
postFormats () {
|
|
||||||
return this.$store.state.instance.postFormats || []
|
|
||||||
},
|
|
||||||
instanceSpecificPanelPresent () { return this.$store.state.instance.showInstanceSpecificPanel },
|
|
||||||
frontendVersionLink () {
|
|
||||||
return pleromaFeCommitUrl + this.frontendVersion
|
|
||||||
},
|
|
||||||
backendVersionLink () {
|
|
||||||
return pleromaBeCommitUrl + extractCommit(this.backendVersion)
|
|
||||||
},
|
|
||||||
// Getting localized values for instance-default properties
|
|
||||||
...instanceDefaultProperties
|
|
||||||
.filter(key => multiChoiceProperties.includes(key))
|
|
||||||
.map(key => [
|
|
||||||
key + 'DefaultValue',
|
|
||||||
function () {
|
|
||||||
return this.$store.getters.instanceDefaultConfig[key]
|
|
||||||
}
|
|
||||||
])
|
|
||||||
.reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}),
|
|
||||||
...instanceDefaultProperties
|
|
||||||
.filter(key => !multiChoiceProperties.includes(key))
|
|
||||||
.map(key => [
|
|
||||||
key + 'LocalizedValue',
|
|
||||||
function () {
|
|
||||||
return this.$t('settings.values.' + this.$store.getters.instanceDefaultConfig[key])
|
|
||||||
}
|
|
||||||
])
|
|
||||||
.reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}),
|
|
||||||
// Generating computed values for vuex properties
|
|
||||||
...Object.keys(configDefaultState)
|
|
||||||
.map(key => [key, {
|
|
||||||
get () { return this.$store.getters.mergedConfig[key] },
|
|
||||||
set (value) {
|
|
||||||
this.$store.dispatch('setOption', { name: key, value })
|
|
||||||
}
|
|
||||||
}])
|
|
||||||
.reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}),
|
|
||||||
// Special cases (need to transform values or perform actions first)
|
|
||||||
muteWordsString: {
|
|
||||||
get () { return this.$store.getters.mergedConfig.muteWords.join('\n') },
|
|
||||||
set (value) {
|
|
||||||
this.$store.dispatch('setOption', {
|
|
||||||
name: 'muteWords',
|
|
||||||
value: filter(value.split('\n'), (word) => trim(word).length > 0)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
useStreamingApi: {
|
|
||||||
get () { return this.$store.getters.mergedConfig.useStreamingApi },
|
|
||||||
set (value) {
|
|
||||||
const promise = value
|
|
||||||
? this.$store.dispatch('enableMastoSockets')
|
|
||||||
: this.$store.dispatch('disableMastoSockets')
|
|
||||||
|
|
||||||
promise.then(() => {
|
|
||||||
this.$store.dispatch('setOption', { name: 'useStreamingApi', value })
|
|
||||||
}).catch((e) => {
|
|
||||||
console.error('Failed starting MastoAPI Streaming socket', e)
|
|
||||||
this.$store.dispatch('disableMastoSockets')
|
|
||||||
this.$store.dispatch('setOption', { name: 'useStreamingApi', value: false })
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// Updating nested properties
|
|
||||||
watch: {
|
|
||||||
notificationVisibility: {
|
|
||||||
handler (value) {
|
|
||||||
this.$store.dispatch('setOption', {
|
|
||||||
name: 'notificationVisibility',
|
|
||||||
value: this.$store.getters.mergedConfig.notificationVisibility
|
|
||||||
})
|
|
||||||
},
|
|
||||||
deep: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default settings
|
|
||||||
|
|
@ -1,429 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="settings panel panel-default">
|
|
||||||
<div class="panel-heading">
|
|
||||||
<div class="title">
|
|
||||||
{{ $t('settings.settings') }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<transition name="fade">
|
|
||||||
<template v-if="currentSaveStateNotice">
|
|
||||||
<div
|
|
||||||
v-if="currentSaveStateNotice.error"
|
|
||||||
class="alert error"
|
|
||||||
@click.prevent
|
|
||||||
>
|
|
||||||
{{ $t('settings.saving_err') }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
v-if="!currentSaveStateNotice.error"
|
|
||||||
class="alert transparent"
|
|
||||||
@click.prevent
|
|
||||||
>
|
|
||||||
{{ $t('settings.saving_ok') }}
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</transition>
|
|
||||||
</div>
|
|
||||||
<div class="panel-body">
|
|
||||||
<keep-alive>
|
|
||||||
<tab-switcher>
|
|
||||||
<div :label="$t('settings.general')">
|
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{ $t('settings.interface') }}</h2>
|
|
||||||
<ul class="setting-list">
|
|
||||||
<li>
|
|
||||||
<interface-language-switcher />
|
|
||||||
</li>
|
|
||||||
<li v-if="instanceSpecificPanelPresent">
|
|
||||||
<Checkbox v-model="hideISP">
|
|
||||||
{{ $t('settings.hide_isp') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{ $t('nav.timeline') }}</h2>
|
|
||||||
<ul class="setting-list">
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="hideMutedPosts">
|
|
||||||
{{ $t('settings.hide_muted_posts') }} {{ $t('settings.instance_default', { value: hideMutedPostsLocalizedValue }) }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="collapseMessageWithSubject">
|
|
||||||
{{ $t('settings.collapse_subject') }} {{ $t('settings.instance_default', { value: collapseMessageWithSubjectLocalizedValue }) }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="streaming">
|
|
||||||
{{ $t('settings.streaming') }}
|
|
||||||
</Checkbox>
|
|
||||||
<ul
|
|
||||||
class="setting-list suboptions"
|
|
||||||
:class="[{disabled: !streaming}]"
|
|
||||||
>
|
|
||||||
<li>
|
|
||||||
<Checkbox
|
|
||||||
v-model="pauseOnUnfocused"
|
|
||||||
:disabled="!streaming"
|
|
||||||
>
|
|
||||||
{{ $t('settings.pause_on_unfocused') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="useStreamingApi">
|
|
||||||
{{ $t('settings.useStreamingApi') }}
|
|
||||||
<br>
|
|
||||||
<small>
|
|
||||||
{{ $t('settings.useStreamingApiWarning') }}
|
|
||||||
</small>
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="autoLoad">
|
|
||||||
{{ $t('settings.autoload') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="hoverPreview">
|
|
||||||
{{ $t('settings.reply_link_preview') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="virtualScrolling">
|
|
||||||
{{ $t('settings.virtual_scrolling') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="emojiReactionsOnTimeline">
|
|
||||||
{{ $t('settings.emoji_reactions_on_timeline') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{ $t('settings.composing') }}</h2>
|
|
||||||
<ul class="setting-list">
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="scopeCopy">
|
|
||||||
{{ $t('settings.scope_copy') }} {{ $t('settings.instance_default', { value: scopeCopyLocalizedValue }) }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="alwaysShowSubjectInput">
|
|
||||||
{{ $t('settings.subject_input_always_show') }} {{ $t('settings.instance_default', { value: alwaysShowSubjectInputLocalizedValue }) }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<div>
|
|
||||||
{{ $t('settings.subject_line_behavior') }}
|
|
||||||
<label
|
|
||||||
for="subjectLineBehavior"
|
|
||||||
class="select"
|
|
||||||
>
|
|
||||||
<select
|
|
||||||
id="subjectLineBehavior"
|
|
||||||
v-model="subjectLineBehavior"
|
|
||||||
>
|
|
||||||
<option value="email">
|
|
||||||
{{ $t('settings.subject_line_email') }}
|
|
||||||
{{ subjectLineBehaviorDefaultValue == 'email' ? $t('settings.instance_default_simple') : '' }}
|
|
||||||
</option>
|
|
||||||
<option value="masto">
|
|
||||||
{{ $t('settings.subject_line_mastodon') }}
|
|
||||||
{{ subjectLineBehaviorDefaultValue == 'mastodon' ? $t('settings.instance_default_simple') : '' }}
|
|
||||||
</option>
|
|
||||||
<option value="noop">
|
|
||||||
{{ $t('settings.subject_line_noop') }}
|
|
||||||
{{ subjectLineBehaviorDefaultValue == 'noop' ? $t('settings.instance_default_simple') : '' }}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
<i class="icon-down-open" />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<li v-if="postFormats.length > 0">
|
|
||||||
<div>
|
|
||||||
{{ $t('settings.post_status_content_type') }}
|
|
||||||
<label
|
|
||||||
for="postContentType"
|
|
||||||
class="select"
|
|
||||||
>
|
|
||||||
<select
|
|
||||||
id="postContentType"
|
|
||||||
v-model="postContentType"
|
|
||||||
>
|
|
||||||
<option
|
|
||||||
v-for="postFormat in postFormats"
|
|
||||||
:key="postFormat"
|
|
||||||
:value="postFormat"
|
|
||||||
>
|
|
||||||
{{ $t(`post_status.content_type["${postFormat}"]`) }}
|
|
||||||
{{ postContentTypeDefaultValue === postFormat ? $t('settings.instance_default_simple') : '' }}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
<i class="icon-down-open" />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="minimalScopesMode">
|
|
||||||
{{ $t('settings.minimal_scopes_mode') }} {{ $t('settings.instance_default', { value: minimalScopesModeLocalizedValue }) }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="autohideFloatingPostButton">
|
|
||||||
{{ $t('settings.autohide_floating_post_button') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="padEmoji">
|
|
||||||
{{ $t('settings.pad_emoji') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{ $t('settings.attachments') }}</h2>
|
|
||||||
<ul class="setting-list">
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="hideAttachments">
|
|
||||||
{{ $t('settings.hide_attachments_in_tl') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="hideAttachmentsInConv">
|
|
||||||
{{ $t('settings.hide_attachments_in_convo') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<label for="maxThumbnails">
|
|
||||||
{{ $t('settings.max_thumbnails') }}
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
id="maxThumbnails"
|
|
||||||
v-model.number="maxThumbnails"
|
|
||||||
class="number-input"
|
|
||||||
type="number"
|
|
||||||
min="0"
|
|
||||||
step="1"
|
|
||||||
>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="hideNsfw">
|
|
||||||
{{ $t('settings.nsfw_clickthrough') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<ul class="setting-list suboptions">
|
|
||||||
<li>
|
|
||||||
<Checkbox
|
|
||||||
v-model="preloadImage"
|
|
||||||
:disabled="!hideNsfw"
|
|
||||||
>
|
|
||||||
{{ $t('settings.preload_images') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox
|
|
||||||
v-model="useOneClickNsfw"
|
|
||||||
:disabled="!hideNsfw"
|
|
||||||
>
|
|
||||||
{{ $t('settings.use_one_click_nsfw') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="stopGifs">
|
|
||||||
{{ $t('settings.stop_gifs') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="loopVideo">
|
|
||||||
{{ $t('settings.loop_video') }}
|
|
||||||
</Checkbox>
|
|
||||||
<ul
|
|
||||||
class="setting-list suboptions"
|
|
||||||
:class="[{disabled: !streaming}]"
|
|
||||||
>
|
|
||||||
<li>
|
|
||||||
<Checkbox
|
|
||||||
v-model="loopVideoSilentOnly"
|
|
||||||
:disabled="!loopVideo || !loopSilentAvailable"
|
|
||||||
>
|
|
||||||
{{ $t('settings.loop_video_silent_only') }}
|
|
||||||
</Checkbox>
|
|
||||||
<div
|
|
||||||
v-if="!loopSilentAvailable"
|
|
||||||
class="unavailable"
|
|
||||||
>
|
|
||||||
<i class="icon-globe" />! {{ $t('settings.limited_availability') }}
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="playVideosInModal">
|
|
||||||
{{ $t('settings.play_videos_in_modal') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="useContainFit">
|
|
||||||
{{ $t('settings.use_contain_fit') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{ $t('settings.notifications') }}</h2>
|
|
||||||
<ul class="setting-list">
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="webPushNotifications">
|
|
||||||
{{ $t('settings.enable_web_push_notifications') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{ $t('settings.fun') }}</h2>
|
|
||||||
<ul class="setting-list">
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="greentext">
|
|
||||||
{{ $t('settings.greentext') }} {{ $t('settings.instance_default', { value: greentextLocalizedValue }) }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div :label="$t('settings.theme')">
|
|
||||||
<div class="setting-item">
|
|
||||||
<style-switcher />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div :label="$t('settings.filtering')">
|
|
||||||
<div class="setting-item">
|
|
||||||
<div class="select-multiple">
|
|
||||||
<span class="label">{{ $t('settings.notification_visibility') }}</span>
|
|
||||||
<ul class="option-list">
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="notificationVisibility.likes">
|
|
||||||
{{ $t('settings.notification_visibility_likes') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="notificationVisibility.repeats">
|
|
||||||
{{ $t('settings.notification_visibility_repeats') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="notificationVisibility.follows">
|
|
||||||
{{ $t('settings.notification_visibility_follows') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="notificationVisibility.mentions">
|
|
||||||
{{ $t('settings.notification_visibility_mentions') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="notificationVisibility.moves">
|
|
||||||
{{ $t('settings.notification_visibility_moves') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="notificationVisibility.emojiReactions">
|
|
||||||
{{ $t('settings.notification_visibility_emoji_reactions') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
{{ $t('settings.replies_in_timeline') }}
|
|
||||||
<label
|
|
||||||
for="replyVisibility"
|
|
||||||
class="select"
|
|
||||||
>
|
|
||||||
<select
|
|
||||||
id="replyVisibility"
|
|
||||||
v-model="replyVisibility"
|
|
||||||
>
|
|
||||||
<option
|
|
||||||
value="all"
|
|
||||||
selected
|
|
||||||
>{{ $t('settings.reply_visibility_all') }}</option>
|
|
||||||
<option value="following">{{ $t('settings.reply_visibility_following') }}</option>
|
|
||||||
<option value="self">{{ $t('settings.reply_visibility_self') }}</option>
|
|
||||||
</select>
|
|
||||||
<i class="icon-down-open" />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<Checkbox v-model="hidePostStats">
|
|
||||||
{{ $t('settings.hide_post_stats') }} {{ $t('settings.instance_default', { value: hidePostStatsLocalizedValue }) }}
|
|
||||||
</Checkbox>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<Checkbox v-model="hideUserStats">
|
|
||||||
{{ $t('settings.hide_user_stats') }} {{ $t('settings.instance_default', { value: hideUserStatsLocalizedValue }) }}
|
|
||||||
</Checkbox>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="setting-item">
|
|
||||||
<div>
|
|
||||||
<p>{{ $t('settings.filtering_explanation') }}</p>
|
|
||||||
<textarea
|
|
||||||
id="muteWords"
|
|
||||||
v-model="muteWordsString"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<Checkbox v-model="hideFilteredStatuses">
|
|
||||||
{{ $t('settings.hide_filtered_statuses') }} {{ $t('settings.instance_default', { value: hideFilteredStatusesLocalizedValue }) }}
|
|
||||||
</Checkbox>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div :label="$t('settings.version.title')">
|
|
||||||
<div class="setting-item">
|
|
||||||
<ul class="setting-list">
|
|
||||||
<li>
|
|
||||||
<p>{{ $t('settings.version.backend_version') }}</p>
|
|
||||||
<ul class="option-list">
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
:href="backendVersionLink"
|
|
||||||
target="_blank"
|
|
||||||
>{{ backendVersion }}</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>{{ $t('settings.version.frontend_version') }}</p>
|
|
||||||
<ul class="option-list">
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
:href="frontendVersionLink"
|
|
||||||
target="_blank"
|
|
||||||
>{{ frontendVersion }}</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</tab-switcher>
|
|
||||||
</keep-alive>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script src="./settings.js">
|
|
||||||
</script>
|
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
import {
|
||||||
|
instanceDefaultProperties,
|
||||||
|
multiChoiceProperties,
|
||||||
|
defaultState as configDefaultState
|
||||||
|
} from 'src/modules/config.js'
|
||||||
|
|
||||||
|
const SharedComputedObject = () => ({
|
||||||
|
user () {
|
||||||
|
return this.$store.state.users.currentUser
|
||||||
|
},
|
||||||
|
// Getting localized values for instance-default properties
|
||||||
|
...instanceDefaultProperties
|
||||||
|
.filter(key => multiChoiceProperties.includes(key))
|
||||||
|
.map(key => [
|
||||||
|
key + 'DefaultValue',
|
||||||
|
function () {
|
||||||
|
return this.$store.getters.instanceDefaultConfig[key]
|
||||||
|
}
|
||||||
|
])
|
||||||
|
.reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}),
|
||||||
|
...instanceDefaultProperties
|
||||||
|
.filter(key => !multiChoiceProperties.includes(key))
|
||||||
|
.map(key => [
|
||||||
|
key + 'LocalizedValue',
|
||||||
|
function () {
|
||||||
|
return this.$t('settings.values.' + this.$store.getters.instanceDefaultConfig[key])
|
||||||
|
}
|
||||||
|
])
|
||||||
|
.reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}),
|
||||||
|
// Generating computed values for vuex properties
|
||||||
|
...Object.keys(configDefaultState)
|
||||||
|
.map(key => [key, {
|
||||||
|
get () { return this.$store.getters.mergedConfig[key] },
|
||||||
|
set (value) {
|
||||||
|
this.$store.dispatch('setOption', { name: key, value })
|
||||||
|
}
|
||||||
|
}])
|
||||||
|
.reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}),
|
||||||
|
// Special cases (need to transform values or perform actions first)
|
||||||
|
useStreamingApi: {
|
||||||
|
get () { return this.$store.getters.mergedConfig.useStreamingApi },
|
||||||
|
set (value) {
|
||||||
|
const promise = value
|
||||||
|
? this.$store.dispatch('enableMastoSockets')
|
||||||
|
: this.$store.dispatch('disableMastoSockets')
|
||||||
|
|
||||||
|
promise.then(() => {
|
||||||
|
this.$store.dispatch('setOption', { name: 'useStreamingApi', value })
|
||||||
|
}).catch((e) => {
|
||||||
|
console.error('Failed starting MastoAPI Streaming socket', e)
|
||||||
|
this.$store.dispatch('disableMastoSockets')
|
||||||
|
this.$store.dispatch('setOption', { name: 'useStreamingApi', value: false })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
export default SharedComputedObject
|
||||||
42
src/components/settings_modal/settings_modal.js
Normal file
42
src/components/settings_modal/settings_modal.js
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
import Modal from 'src/components/modal/modal.vue'
|
||||||
|
import PanelLoading from 'src/components/panel_loading/panel_loading.vue'
|
||||||
|
import AsyncComponentError from 'src/components/async_component_error/async_component_error.vue'
|
||||||
|
import getResettableAsyncComponent from 'src/services/resettable_async_component.js'
|
||||||
|
|
||||||
|
const SettingsModal = {
|
||||||
|
components: {
|
||||||
|
Modal,
|
||||||
|
SettingsModalContent: getResettableAsyncComponent(
|
||||||
|
() => import('./settings_modal_content.vue'),
|
||||||
|
{
|
||||||
|
loading: PanelLoading,
|
||||||
|
error: AsyncComponentError,
|
||||||
|
delay: 0
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
closeModal () {
|
||||||
|
this.$store.dispatch('closeSettingsModal')
|
||||||
|
},
|
||||||
|
peekModal () {
|
||||||
|
this.$store.dispatch('togglePeekSettingsModal')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
currentSaveStateNotice () {
|
||||||
|
return this.$store.state.interface.settings.currentSaveStateNotice
|
||||||
|
},
|
||||||
|
modalActivated () {
|
||||||
|
return this.$store.state.interface.settingsModalState !== 'hidden'
|
||||||
|
},
|
||||||
|
modalOpenedOnce () {
|
||||||
|
return this.$store.state.interface.settingsModalLoaded
|
||||||
|
},
|
||||||
|
modalPeeked () {
|
||||||
|
return this.$store.state.interface.settingsModalState === 'minimized'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SettingsModal
|
||||||
44
src/components/settings_modal/settings_modal.scss
Normal file
44
src/components/settings_modal/settings_modal.scss
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
@import 'src/_variables.scss';
|
||||||
|
.settings-modal {
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&.peek {
|
||||||
|
.settings-modal-panel {
|
||||||
|
/* Explanation:
|
||||||
|
* Modal is positioned vertically centered.
|
||||||
|
* 100vh - 100% = Distance between modal's top+bottom boundaries and screen
|
||||||
|
* (100vh - 100%) / 2 = Distance between bottom (or top) boundary and screen
|
||||||
|
* + 100% - we move modal completely off-screen, it's top boundary touches
|
||||||
|
* bottom of the screen
|
||||||
|
* - 50px - leaving tiny amount of space so that titlebar + tiny amount of modal is visible
|
||||||
|
*/
|
||||||
|
transform: translateY(calc(((100vh - 100%) / 2 + 100%) - 50px));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-modal-panel {
|
||||||
|
overflow: hidden;
|
||||||
|
transition: transform;
|
||||||
|
transition-timing-function: ease-in-out;
|
||||||
|
transition-duration: 300ms;
|
||||||
|
width: 1000px;
|
||||||
|
max-width: 90vw;
|
||||||
|
height: 90vh;
|
||||||
|
|
||||||
|
@media all and (max-width: 800px) {
|
||||||
|
max-width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-body {
|
||||||
|
height: 100%;
|
||||||
|
overflow-y: hidden;
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
min-height: 28px;
|
||||||
|
min-width: 10em;
|
||||||
|
padding: 0 2em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
54
src/components/settings_modal/settings_modal.vue
Normal file
54
src/components/settings_modal/settings_modal.vue
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
<template>
|
||||||
|
<Modal
|
||||||
|
:is-open="modalActivated"
|
||||||
|
class="settings-modal"
|
||||||
|
:class="{ peek: modalPeeked }"
|
||||||
|
:no-background="modalPeeked"
|
||||||
|
>
|
||||||
|
<div class="settings-modal-panel panel">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<span class="title">
|
||||||
|
{{ $t('settings.settings') }}
|
||||||
|
</span>
|
||||||
|
<transition name="fade">
|
||||||
|
<template v-if="currentSaveStateNotice">
|
||||||
|
<div
|
||||||
|
v-if="currentSaveStateNotice.error"
|
||||||
|
class="alert error"
|
||||||
|
@click.prevent
|
||||||
|
>
|
||||||
|
{{ $t('settings.saving_err') }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="!currentSaveStateNotice.error"
|
||||||
|
class="alert transparent"
|
||||||
|
@click.prevent
|
||||||
|
>
|
||||||
|
{{ $t('settings.saving_ok') }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</transition>
|
||||||
|
<button
|
||||||
|
class="btn"
|
||||||
|
@click="peekModal"
|
||||||
|
>
|
||||||
|
{{ $t('general.peek') }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="btn"
|
||||||
|
@click="closeModal"
|
||||||
|
>
|
||||||
|
{{ $t('general.close') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<SettingsModalContent v-if="modalOpenedOnce" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./settings_modal.js"></script>
|
||||||
|
|
||||||
|
<style src="./settings_modal.scss" lang="scss"></style>
|
||||||
34
src/components/settings_modal/settings_modal_content.js
Normal file
34
src/components/settings_modal/settings_modal_content.js
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
import TabSwitcher from 'src/components/tab_switcher/tab_switcher.js'
|
||||||
|
|
||||||
|
import DataImportExportTab from './tabs/data_import_export_tab.vue'
|
||||||
|
import MutesAndBlocksTab from './tabs/mutes_and_blocks_tab.vue'
|
||||||
|
import NotificationsTab from './tabs/notifications_tab.vue'
|
||||||
|
import FilteringTab from './tabs/filtering_tab.vue'
|
||||||
|
import SecurityTab from './tabs/security_tab/security_tab.vue'
|
||||||
|
import ProfileTab from './tabs/profile_tab.vue'
|
||||||
|
import GeneralTab from './tabs/general_tab.vue'
|
||||||
|
import VersionTab from './tabs/version_tab.vue'
|
||||||
|
import ThemeTab from './tabs/theme_tab/theme_tab.vue'
|
||||||
|
|
||||||
|
const SettingsModalContent = {
|
||||||
|
components: {
|
||||||
|
TabSwitcher,
|
||||||
|
|
||||||
|
DataImportExportTab,
|
||||||
|
MutesAndBlocksTab,
|
||||||
|
NotificationsTab,
|
||||||
|
FilteringTab,
|
||||||
|
SecurityTab,
|
||||||
|
ProfileTab,
|
||||||
|
GeneralTab,
|
||||||
|
VersionTab,
|
||||||
|
ThemeTab
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
isLoggedIn () {
|
||||||
|
return !!this.$store.state.users.currentUser
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SettingsModalContent
|
||||||
43
src/components/settings_modal/settings_modal_content.scss
Normal file
43
src/components/settings_modal/settings_modal_content.scss
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
@import 'src/_variables.scss';
|
||||||
|
.settings_tab-switcher {
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
.setting-item {
|
||||||
|
border-bottom: 2px solid var(--fg, $fallback--fg);
|
||||||
|
margin: 1em 1em 1.4em;
|
||||||
|
padding-bottom: 1.4em;
|
||||||
|
|
||||||
|
> div {
|
||||||
|
margin-bottom: .5em;
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
padding-bottom: 0;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
min-width: 10em;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.unavailable,
|
||||||
|
.unavailable i {
|
||||||
|
color: var(--cRed, $fallback--cRed);
|
||||||
|
color: $fallback--cRed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.number-input {
|
||||||
|
max-width: 6em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
73
src/components/settings_modal/settings_modal_content.vue
Normal file
73
src/components/settings_modal/settings_modal_content.vue
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
<template>
|
||||||
|
<tab-switcher
|
||||||
|
ref="tabSwitcher"
|
||||||
|
class="settings_tab-switcher"
|
||||||
|
:side-tab-bar="true"
|
||||||
|
:scrollable-tabs="true"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
:label="$t('settings.general')"
|
||||||
|
icon="wrench"
|
||||||
|
>
|
||||||
|
<GeneralTab />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="isLoggedIn"
|
||||||
|
:label="$t('settings.profile_tab')"
|
||||||
|
icon="user"
|
||||||
|
>
|
||||||
|
<ProfileTab />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="isLoggedIn"
|
||||||
|
:label="$t('settings.security_tab')"
|
||||||
|
icon="lock"
|
||||||
|
>
|
||||||
|
<SecurityTab />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
:label="$t('settings.filtering')"
|
||||||
|
icon="filter"
|
||||||
|
>
|
||||||
|
<FilteringTab />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
:label="$t('settings.theme')"
|
||||||
|
icon="brush"
|
||||||
|
>
|
||||||
|
<ThemeTab />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="isLoggedIn"
|
||||||
|
:label="$t('settings.notifications')"
|
||||||
|
icon="bell-ringing-o"
|
||||||
|
>
|
||||||
|
<NotificationsTab />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="isLoggedIn"
|
||||||
|
:label="$t('settings.data_import_export_tab')"
|
||||||
|
icon="download"
|
||||||
|
>
|
||||||
|
<DataImportExportTab />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="isLoggedIn"
|
||||||
|
:label="$t('settings.mutes_and_blocks')"
|
||||||
|
:fullHeight="true"
|
||||||
|
icon="eye-off"
|
||||||
|
>
|
||||||
|
<MutesAndBlocksTab />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
:label="$t('settings.version.title')"
|
||||||
|
icon="info-circled"
|
||||||
|
>
|
||||||
|
<VersionTab />
|
||||||
|
</div>
|
||||||
|
</tab-switcher>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./settings_modal_content.js"></script>
|
||||||
|
|
||||||
|
<style src="./settings_modal_content.scss" lang="scss"></style>
|
||||||
65
src/components/settings_modal/tabs/data_import_export_tab.js
Normal file
65
src/components/settings_modal/tabs/data_import_export_tab.js
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
import Importer from 'src/components/importer/importer.vue'
|
||||||
|
import Exporter from 'src/components/exporter/exporter.vue'
|
||||||
|
import Checkbox from 'src/components/checkbox/checkbox.vue'
|
||||||
|
|
||||||
|
const DataImportExportTab = {
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
activeTab: 'profile',
|
||||||
|
newDomainToMute: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created () {
|
||||||
|
this.$store.dispatch('fetchTokens')
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
Importer,
|
||||||
|
Exporter,
|
||||||
|
Checkbox
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
user () {
|
||||||
|
return this.$store.state.users.currentUser
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getFollowsContent () {
|
||||||
|
return this.$store.state.api.backendInteractor.exportFriends({ id: this.$store.state.users.currentUser.id })
|
||||||
|
.then(this.generateExportableUsersContent)
|
||||||
|
},
|
||||||
|
getBlocksContent () {
|
||||||
|
return this.$store.state.api.backendInteractor.fetchBlocks()
|
||||||
|
.then(this.generateExportableUsersContent)
|
||||||
|
},
|
||||||
|
importFollows (file) {
|
||||||
|
return this.$store.state.api.backendInteractor.importFollows({ file })
|
||||||
|
.then((status) => {
|
||||||
|
if (!status) {
|
||||||
|
throw new Error('failed')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
importBlocks (file) {
|
||||||
|
return this.$store.state.api.backendInteractor.importBlocks({ file })
|
||||||
|
.then((status) => {
|
||||||
|
if (!status) {
|
||||||
|
throw new Error('failed')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
generateExportableUsersContent (users) {
|
||||||
|
// Get addresses
|
||||||
|
return users.map((user) => {
|
||||||
|
// check is it's a local user
|
||||||
|
if (user && user.is_local) {
|
||||||
|
// append the instance address
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
|
return user.screen_name + '@' + location.hostname
|
||||||
|
}
|
||||||
|
return user.screen_name
|
||||||
|
}).join('\n')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DataImportExportTab
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
:label="$t('settings.data_import_export_tab')"
|
||||||
|
>
|
||||||
|
<div class="setting-item">
|
||||||
|
<h2>{{ $t('settings.follow_import') }}</h2>
|
||||||
|
<p>{{ $t('settings.import_followers_from_a_csv_file') }}</p>
|
||||||
|
<Importer
|
||||||
|
:submit-handler="importFollows"
|
||||||
|
:success-message="$t('settings.follows_imported')"
|
||||||
|
:error-message="$t('settings.follow_import_error')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="setting-item">
|
||||||
|
<h2>{{ $t('settings.follow_export') }}</h2>
|
||||||
|
<Exporter
|
||||||
|
:get-content="getFollowsContent"
|
||||||
|
filename="friends.csv"
|
||||||
|
:export-button-label="$t('settings.follow_export_button')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="setting-item">
|
||||||
|
<h2>{{ $t('settings.block_import') }}</h2>
|
||||||
|
<p>{{ $t('settings.import_blocks_from_a_csv_file') }}</p>
|
||||||
|
<Importer
|
||||||
|
:submit-handler="importBlocks"
|
||||||
|
:success-message="$t('settings.blocks_imported')"
|
||||||
|
:error-message="$t('settings.block_import_error')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="setting-item">
|
||||||
|
<h2>{{ $t('settings.block_export') }}</h2>
|
||||||
|
<Exporter
|
||||||
|
:get-content="getBlocksContent"
|
||||||
|
filename="blocks.csv"
|
||||||
|
:export-button-label="$t('settings.block_export_button')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./data_import_export_tab.js"></script>
|
||||||
|
<!-- <style lang="scss" src="./profile.scss"></style> -->
|
||||||
44
src/components/settings_modal/tabs/filtering_tab.js
Normal file
44
src/components/settings_modal/tabs/filtering_tab.js
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
import { filter, trim } from 'lodash'
|
||||||
|
import Checkbox from 'src/components/checkbox/checkbox.vue'
|
||||||
|
|
||||||
|
import SharedComputedObject from '../helpers/shared_computed_object.js'
|
||||||
|
|
||||||
|
const FilteringTab = {
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
muteWordsStringLocal: this.$store.getters.mergedConfig.muteWords.join('\n')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
Checkbox
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...SharedComputedObject(),
|
||||||
|
muteWordsString: {
|
||||||
|
get () {
|
||||||
|
return this.muteWordsStringLocal
|
||||||
|
},
|
||||||
|
set (value) {
|
||||||
|
this.muteWordsStringLocal = value
|
||||||
|
this.$store.dispatch('setOption', {
|
||||||
|
name: 'muteWords',
|
||||||
|
value: filter(value.split('\n'), (word) => trim(word).length > 0)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// Updating nested properties
|
||||||
|
watch: {
|
||||||
|
notificationVisibility: {
|
||||||
|
handler (value) {
|
||||||
|
this.$store.dispatch('setOption', {
|
||||||
|
name: 'notificationVisibility',
|
||||||
|
value: this.$store.getters.mergedConfig.notificationVisibility
|
||||||
|
})
|
||||||
|
},
|
||||||
|
deep: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FilteringTab
|
||||||
86
src/components/settings_modal/tabs/filtering_tab.vue
Normal file
86
src/components/settings_modal/tabs/filtering_tab.vue
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
<template>
|
||||||
|
<div :label="$t('settings.filtering')">
|
||||||
|
<div class="setting-item">
|
||||||
|
<div class="select-multiple">
|
||||||
|
<span class="label">{{ $t('settings.notification_visibility') }}</span>
|
||||||
|
<ul class="option-list">
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="notificationVisibility.likes">
|
||||||
|
{{ $t('settings.notification_visibility_likes') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="notificationVisibility.repeats">
|
||||||
|
{{ $t('settings.notification_visibility_repeats') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="notificationVisibility.follows">
|
||||||
|
{{ $t('settings.notification_visibility_follows') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="notificationVisibility.mentions">
|
||||||
|
{{ $t('settings.notification_visibility_mentions') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="notificationVisibility.moves">
|
||||||
|
{{ $t('settings.notification_visibility_moves') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="notificationVisibility.emojiReactions">
|
||||||
|
{{ $t('settings.notification_visibility_emoji_reactions') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{{ $t('settings.replies_in_timeline') }}
|
||||||
|
<label
|
||||||
|
for="replyVisibility"
|
||||||
|
class="select"
|
||||||
|
>
|
||||||
|
<select
|
||||||
|
id="replyVisibility"
|
||||||
|
v-model="replyVisibility"
|
||||||
|
>
|
||||||
|
<option
|
||||||
|
value="all"
|
||||||
|
selected
|
||||||
|
>{{ $t('settings.reply_visibility_all') }}</option>
|
||||||
|
<option value="following">{{ $t('settings.reply_visibility_following') }}</option>
|
||||||
|
<option value="self">{{ $t('settings.reply_visibility_self') }}</option>
|
||||||
|
</select>
|
||||||
|
<i class="icon-down-open" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Checkbox v-model="hidePostStats">
|
||||||
|
{{ $t('settings.hide_post_stats') }} {{ $t('settings.instance_default', { value: hidePostStatsLocalizedValue }) }}
|
||||||
|
</Checkbox>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Checkbox v-model="hideUserStats">
|
||||||
|
{{ $t('settings.hide_user_stats') }} {{ $t('settings.instance_default', { value: hideUserStatsLocalizedValue }) }}
|
||||||
|
</Checkbox>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="setting-item">
|
||||||
|
<div>
|
||||||
|
<p>{{ $t('settings.filtering_explanation') }}</p>
|
||||||
|
<textarea
|
||||||
|
id="muteWords"
|
||||||
|
v-model="muteWordsString"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Checkbox v-model="hideFilteredStatuses">
|
||||||
|
{{ $t('settings.hide_filtered_statuses') }} {{ $t('settings.instance_default', { value: hideFilteredStatusesLocalizedValue }) }}
|
||||||
|
</Checkbox>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script src="./filtering_tab.js"></script>
|
||||||
31
src/components/settings_modal/tabs/general_tab.js
Normal file
31
src/components/settings_modal/tabs/general_tab.js
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
import Checkbox from 'src/components/checkbox/checkbox.vue'
|
||||||
|
import InterfaceLanguageSwitcher from 'src/components/interface_language_switcher/interface_language_switcher.vue'
|
||||||
|
|
||||||
|
import SharedComputedObject from '../helpers/shared_computed_object.js'
|
||||||
|
|
||||||
|
const GeneralTab = {
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
loopSilentAvailable:
|
||||||
|
// Firefox
|
||||||
|
Object.getOwnPropertyDescriptor(HTMLVideoElement.prototype, 'mozHasAudio') ||
|
||||||
|
// Chrome-likes
|
||||||
|
Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'webkitAudioDecodedByteCount') ||
|
||||||
|
// Future spec, still not supported in Nightly 63 as of 08/2018
|
||||||
|
Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'audioTracks')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
Checkbox,
|
||||||
|
InterfaceLanguageSwitcher
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
postFormats () {
|
||||||
|
return this.$store.state.instance.postFormats || []
|
||||||
|
},
|
||||||
|
instanceSpecificPanelPresent () { return this.$store.state.instance.showInstanceSpecificPanel },
|
||||||
|
...SharedComputedObject()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default GeneralTab
|
||||||
272
src/components/settings_modal/tabs/general_tab.vue
Normal file
272
src/components/settings_modal/tabs/general_tab.vue
Normal file
|
|
@ -0,0 +1,272 @@
|
||||||
|
<template>
|
||||||
|
<div :label="$t('settings.general')">
|
||||||
|
<div class="setting-item">
|
||||||
|
<h2>{{ $t('settings.interface') }}</h2>
|
||||||
|
<ul class="setting-list">
|
||||||
|
<li>
|
||||||
|
<interface-language-switcher />
|
||||||
|
</li>
|
||||||
|
<li v-if="instanceSpecificPanelPresent">
|
||||||
|
<Checkbox v-model="hideISP">
|
||||||
|
{{ $t('settings.hide_isp') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="setting-item">
|
||||||
|
<h2>{{ $t('nav.timeline') }}</h2>
|
||||||
|
<ul class="setting-list">
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="hideMutedPosts">
|
||||||
|
{{ $t('settings.hide_muted_posts') }} {{ $t('settings.instance_default', { value: hideMutedPostsLocalizedValue }) }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="collapseMessageWithSubject">
|
||||||
|
{{ $t('settings.collapse_subject') }} {{ $t('settings.instance_default', { value: collapseMessageWithSubjectLocalizedValue }) }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="streaming">
|
||||||
|
{{ $t('settings.streaming') }}
|
||||||
|
</Checkbox>
|
||||||
|
<ul
|
||||||
|
class="setting-list suboptions"
|
||||||
|
:class="[{disabled: !streaming}]"
|
||||||
|
>
|
||||||
|
<li>
|
||||||
|
<Checkbox
|
||||||
|
v-model="pauseOnUnfocused"
|
||||||
|
:disabled="!streaming"
|
||||||
|
>
|
||||||
|
{{ $t('settings.pause_on_unfocused') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="useStreamingApi">
|
||||||
|
{{ $t('settings.useStreamingApi') }}
|
||||||
|
<br>
|
||||||
|
<small>
|
||||||
|
{{ $t('settings.useStreamingApiWarning') }}
|
||||||
|
</small>
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="autoLoad">
|
||||||
|
{{ $t('settings.autoload') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="hoverPreview">
|
||||||
|
{{ $t('settings.reply_link_preview') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="emojiReactionsOnTimeline">
|
||||||
|
{{ $t('settings.emoji_reactions_on_timeline') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="setting-item">
|
||||||
|
<h2>{{ $t('settings.composing') }}</h2>
|
||||||
|
<ul class="setting-list">
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="scopeCopy">
|
||||||
|
{{ $t('settings.scope_copy') }} {{ $t('settings.instance_default', { value: scopeCopyLocalizedValue }) }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="alwaysShowSubjectInput">
|
||||||
|
{{ $t('settings.subject_input_always_show') }} {{ $t('settings.instance_default', { value: alwaysShowSubjectInputLocalizedValue }) }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div>
|
||||||
|
{{ $t('settings.subject_line_behavior') }}
|
||||||
|
<label
|
||||||
|
for="subjectLineBehavior"
|
||||||
|
class="select"
|
||||||
|
>
|
||||||
|
<select
|
||||||
|
id="subjectLineBehavior"
|
||||||
|
v-model="subjectLineBehavior"
|
||||||
|
>
|
||||||
|
<option value="email">
|
||||||
|
{{ $t('settings.subject_line_email') }}
|
||||||
|
{{ subjectLineBehaviorDefaultValue == 'email' ? $t('settings.instance_default_simple') : '' }}
|
||||||
|
</option>
|
||||||
|
<option value="masto">
|
||||||
|
{{ $t('settings.subject_line_mastodon') }}
|
||||||
|
{{ subjectLineBehaviorDefaultValue == 'mastodon' ? $t('settings.instance_default_simple') : '' }}
|
||||||
|
</option>
|
||||||
|
<option value="noop">
|
||||||
|
{{ $t('settings.subject_line_noop') }}
|
||||||
|
{{ subjectLineBehaviorDefaultValue == 'noop' ? $t('settings.instance_default_simple') : '' }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<i class="icon-down-open" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li v-if="postFormats.length > 0">
|
||||||
|
<div>
|
||||||
|
{{ $t('settings.post_status_content_type') }}
|
||||||
|
<label
|
||||||
|
for="postContentType"
|
||||||
|
class="select"
|
||||||
|
>
|
||||||
|
<select
|
||||||
|
id="postContentType"
|
||||||
|
v-model="postContentType"
|
||||||
|
>
|
||||||
|
<option
|
||||||
|
v-for="postFormat in postFormats"
|
||||||
|
:key="postFormat"
|
||||||
|
:value="postFormat"
|
||||||
|
>
|
||||||
|
{{ $t(`post_status.content_type["${postFormat}"]`) }}
|
||||||
|
{{ postContentTypeDefaultValue === postFormat ? $t('settings.instance_default_simple') : '' }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<i class="icon-down-open" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="minimalScopesMode">
|
||||||
|
{{ $t('settings.minimal_scopes_mode') }} {{ $t('settings.instance_default', { value: minimalScopesModeLocalizedValue }) }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="autohideFloatingPostButton">
|
||||||
|
{{ $t('settings.autohide_floating_post_button') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="padEmoji">
|
||||||
|
{{ $t('settings.pad_emoji') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="setting-item">
|
||||||
|
<h2>{{ $t('settings.attachments') }}</h2>
|
||||||
|
<ul class="setting-list">
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="hideAttachments">
|
||||||
|
{{ $t('settings.hide_attachments_in_tl') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="hideAttachmentsInConv">
|
||||||
|
{{ $t('settings.hide_attachments_in_convo') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<label for="maxThumbnails">
|
||||||
|
{{ $t('settings.max_thumbnails') }}
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="maxThumbnails"
|
||||||
|
v-model.number="maxThumbnails"
|
||||||
|
class="number-input"
|
||||||
|
type="number"
|
||||||
|
min="0"
|
||||||
|
step="1"
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="hideNsfw">
|
||||||
|
{{ $t('settings.nsfw_clickthrough') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<ul class="setting-list suboptions">
|
||||||
|
<li>
|
||||||
|
<Checkbox
|
||||||
|
v-model="preloadImage"
|
||||||
|
:disabled="!hideNsfw"
|
||||||
|
>
|
||||||
|
{{ $t('settings.preload_images') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox
|
||||||
|
v-model="useOneClickNsfw"
|
||||||
|
:disabled="!hideNsfw"
|
||||||
|
>
|
||||||
|
{{ $t('settings.use_one_click_nsfw') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="stopGifs">
|
||||||
|
{{ $t('settings.stop_gifs') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="loopVideo">
|
||||||
|
{{ $t('settings.loop_video') }}
|
||||||
|
</Checkbox>
|
||||||
|
<ul
|
||||||
|
class="setting-list suboptions"
|
||||||
|
:class="[{disabled: !streaming}]"
|
||||||
|
>
|
||||||
|
<li>
|
||||||
|
<Checkbox
|
||||||
|
v-model="loopVideoSilentOnly"
|
||||||
|
:disabled="!loopVideo || !loopSilentAvailable"
|
||||||
|
>
|
||||||
|
{{ $t('settings.loop_video_silent_only') }}
|
||||||
|
</Checkbox>
|
||||||
|
<div
|
||||||
|
v-if="!loopSilentAvailable"
|
||||||
|
class="unavailable"
|
||||||
|
>
|
||||||
|
<i class="icon-globe" />! {{ $t('settings.limited_availability') }}
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="playVideosInModal">
|
||||||
|
{{ $t('settings.play_videos_in_modal') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="useContainFit">
|
||||||
|
{{ $t('settings.use_contain_fit') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="setting-item">
|
||||||
|
<h2>{{ $t('settings.notifications') }}</h2>
|
||||||
|
<ul class="setting-list">
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="webPushNotifications">
|
||||||
|
{{ $t('settings.enable_web_push_notifications') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="setting-item">
|
||||||
|
<h2>{{ $t('settings.fun') }}</h2>
|
||||||
|
<ul class="setting-list">
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="greentext">
|
||||||
|
{{ $t('settings.greentext') }} {{ $t('settings.instance_default', { value: greentextLocalizedValue }) }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./general_tab.js"></script>
|
||||||
136
src/components/settings_modal/tabs/mutes_and_blocks_tab.js
Normal file
136
src/components/settings_modal/tabs/mutes_and_blocks_tab.js
Normal file
|
|
@ -0,0 +1,136 @@
|
||||||
|
import get from 'lodash/get'
|
||||||
|
import map from 'lodash/map'
|
||||||
|
import reject from 'lodash/reject'
|
||||||
|
import Autosuggest from 'src/components/autosuggest/autosuggest.vue'
|
||||||
|
import TabSwitcher from 'src/components/tab_switcher/tab_switcher.js'
|
||||||
|
import BlockCard from 'src/components/block_card/block_card.vue'
|
||||||
|
import MuteCard from 'src/components/mute_card/mute_card.vue'
|
||||||
|
import DomainMuteCard from 'src/components/domain_mute_card/domain_mute_card.vue'
|
||||||
|
import SelectableList from 'src/components/selectable_list/selectable_list.vue'
|
||||||
|
import ProgressButton from 'src/components/progress_button/progress_button.vue'
|
||||||
|
import withSubscription from 'src/components/../hocs/with_subscription/with_subscription'
|
||||||
|
import Checkbox from 'src/components/checkbox/checkbox.vue'
|
||||||
|
|
||||||
|
const BlockList = withSubscription({
|
||||||
|
fetch: (props, $store) => $store.dispatch('fetchBlocks'),
|
||||||
|
select: (props, $store) => get($store.state.users.currentUser, 'blockIds', []),
|
||||||
|
childPropName: 'items'
|
||||||
|
})(SelectableList)
|
||||||
|
|
||||||
|
const MuteList = withSubscription({
|
||||||
|
fetch: (props, $store) => $store.dispatch('fetchMutes'),
|
||||||
|
select: (props, $store) => get($store.state.users.currentUser, 'muteIds', []),
|
||||||
|
childPropName: 'items'
|
||||||
|
})(SelectableList)
|
||||||
|
|
||||||
|
const DomainMuteList = withSubscription({
|
||||||
|
fetch: (props, $store) => $store.dispatch('fetchDomainMutes'),
|
||||||
|
select: (props, $store) => get($store.state.users.currentUser, 'domainMutes', []),
|
||||||
|
childPropName: 'items'
|
||||||
|
})(SelectableList)
|
||||||
|
|
||||||
|
const MutesAndBlocks = {
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
activeTab: 'profile'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created () {
|
||||||
|
this.$store.dispatch('fetchTokens')
|
||||||
|
this.$store.dispatch('getKnownDomains')
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
TabSwitcher,
|
||||||
|
BlockList,
|
||||||
|
MuteList,
|
||||||
|
DomainMuteList,
|
||||||
|
BlockCard,
|
||||||
|
MuteCard,
|
||||||
|
DomainMuteCard,
|
||||||
|
ProgressButton,
|
||||||
|
Autosuggest,
|
||||||
|
Checkbox
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
knownDomains () {
|
||||||
|
return this.$store.state.instance.knownDomains
|
||||||
|
},
|
||||||
|
user () {
|
||||||
|
return this.$store.state.users.currentUser
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
importFollows (file) {
|
||||||
|
return this.$store.state.api.backendInteractor.importFollows({ file })
|
||||||
|
.then((status) => {
|
||||||
|
if (!status) {
|
||||||
|
throw new Error('failed')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
importBlocks (file) {
|
||||||
|
return this.$store.state.api.backendInteractor.importBlocks({ file })
|
||||||
|
.then((status) => {
|
||||||
|
if (!status) {
|
||||||
|
throw new Error('failed')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
generateExportableUsersContent (users) {
|
||||||
|
// Get addresses
|
||||||
|
return users.map((user) => {
|
||||||
|
// check is it's a local user
|
||||||
|
if (user && user.is_local) {
|
||||||
|
// append the instance address
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
|
return user.screen_name + '@' + location.hostname
|
||||||
|
}
|
||||||
|
return user.screen_name
|
||||||
|
}).join('\n')
|
||||||
|
},
|
||||||
|
activateTab (tabName) {
|
||||||
|
this.activeTab = tabName
|
||||||
|
},
|
||||||
|
filterUnblockedUsers (userIds) {
|
||||||
|
return reject(userIds, (userId) => {
|
||||||
|
const relationship = this.$store.getters.relationship(this.userId)
|
||||||
|
return relationship.blocking || userId === this.user.id
|
||||||
|
})
|
||||||
|
},
|
||||||
|
filterUnMutedUsers (userIds) {
|
||||||
|
return reject(userIds, (userId) => {
|
||||||
|
const relationship = this.$store.getters.relationship(this.userId)
|
||||||
|
return relationship.muting || userId === this.user.id
|
||||||
|
})
|
||||||
|
},
|
||||||
|
queryUserIds (query) {
|
||||||
|
return this.$store.dispatch('searchUsers', { query })
|
||||||
|
.then((users) => map(users, 'id'))
|
||||||
|
},
|
||||||
|
blockUsers (ids) {
|
||||||
|
return this.$store.dispatch('blockUsers', ids)
|
||||||
|
},
|
||||||
|
unblockUsers (ids) {
|
||||||
|
return this.$store.dispatch('unblockUsers', ids)
|
||||||
|
},
|
||||||
|
muteUsers (ids) {
|
||||||
|
return this.$store.dispatch('muteUsers', ids)
|
||||||
|
},
|
||||||
|
unmuteUsers (ids) {
|
||||||
|
return this.$store.dispatch('unmuteUsers', ids)
|
||||||
|
},
|
||||||
|
filterUnMutedDomains (urls) {
|
||||||
|
return urls.filter(url => !this.user.domainMutes.includes(url))
|
||||||
|
},
|
||||||
|
queryKnownDomains (query) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
resolve(this.knownDomains.filter(url => url.toLowerCase().includes(query)))
|
||||||
|
})
|
||||||
|
},
|
||||||
|
unmuteDomains (domains) {
|
||||||
|
return this.$store.dispatch('unmuteDomains', domains)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MutesAndBlocks
|
||||||
29
src/components/settings_modal/tabs/mutes_and_blocks_tab.scss
Normal file
29
src/components/settings_modal/tabs/mutes_and_blocks_tab.scss
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
.mutes-and-blocks-tab {
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
.usersearch-wrapper {
|
||||||
|
padding: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bulk-actions {
|
||||||
|
text-align: right;
|
||||||
|
padding: 0 1em;
|
||||||
|
min-height: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bulk-action-button {
|
||||||
|
width: 10em
|
||||||
|
}
|
||||||
|
|
||||||
|
.domain-mute-form {
|
||||||
|
padding: 1em;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column
|
||||||
|
}
|
||||||
|
|
||||||
|
.domain-mute-button {
|
||||||
|
align-self: flex-end;
|
||||||
|
margin-top: 1em;
|
||||||
|
width: 10em
|
||||||
|
}
|
||||||
|
}
|
||||||
171
src/components/settings_modal/tabs/mutes_and_blocks_tab.vue
Normal file
171
src/components/settings_modal/tabs/mutes_and_blocks_tab.vue
Normal file
|
|
@ -0,0 +1,171 @@
|
||||||
|
<template>
|
||||||
|
<tab-switcher
|
||||||
|
:scrollable-tabs="true"
|
||||||
|
class="mutes-and-blocks-tab"
|
||||||
|
>
|
||||||
|
<div :label="$t('settings.blocks_tab')">
|
||||||
|
<div class="usersearch-wrapper">
|
||||||
|
<Autosuggest
|
||||||
|
:filter="filterUnblockedUsers"
|
||||||
|
:query="queryUserIds"
|
||||||
|
:placeholder="$t('settings.search_user_to_block')"
|
||||||
|
>
|
||||||
|
<BlockCard
|
||||||
|
slot-scope="row"
|
||||||
|
:user-id="row.item"
|
||||||
|
/>
|
||||||
|
</Autosuggest>
|
||||||
|
</div>
|
||||||
|
<BlockList
|
||||||
|
:refresh="true"
|
||||||
|
:get-key="i => i"
|
||||||
|
>
|
||||||
|
<template
|
||||||
|
slot="header"
|
||||||
|
slot-scope="{selected}"
|
||||||
|
>
|
||||||
|
<div class="bulk-actions">
|
||||||
|
<ProgressButton
|
||||||
|
v-if="selected.length > 0"
|
||||||
|
class="btn btn-default bulk-action-button"
|
||||||
|
:click="() => blockUsers(selected)"
|
||||||
|
>
|
||||||
|
{{ $t('user_card.block') }}
|
||||||
|
<template slot="progress">
|
||||||
|
{{ $t('user_card.block_progress') }}
|
||||||
|
</template>
|
||||||
|
</ProgressButton>
|
||||||
|
<ProgressButton
|
||||||
|
v-if="selected.length > 0"
|
||||||
|
class="btn btn-default"
|
||||||
|
:click="() => unblockUsers(selected)"
|
||||||
|
>
|
||||||
|
{{ $t('user_card.unblock') }}
|
||||||
|
<template slot="progress">
|
||||||
|
{{ $t('user_card.unblock_progress') }}
|
||||||
|
</template>
|
||||||
|
</ProgressButton>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template
|
||||||
|
slot="item"
|
||||||
|
slot-scope="{item}"
|
||||||
|
>
|
||||||
|
<BlockCard :user-id="item" />
|
||||||
|
</template>
|
||||||
|
<template slot="empty">
|
||||||
|
{{ $t('settings.no_blocks') }}
|
||||||
|
</template>
|
||||||
|
</BlockList>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div :label="$t('settings.mutes_tab')">
|
||||||
|
<tab-switcher>
|
||||||
|
<div label="Users">
|
||||||
|
<div class="usersearch-wrapper">
|
||||||
|
<Autosuggest
|
||||||
|
:filter="filterUnMutedUsers"
|
||||||
|
:query="queryUserIds"
|
||||||
|
:placeholder="$t('settings.search_user_to_mute')"
|
||||||
|
>
|
||||||
|
<MuteCard
|
||||||
|
slot-scope="row"
|
||||||
|
:user-id="row.item"
|
||||||
|
/>
|
||||||
|
</Autosuggest>
|
||||||
|
</div>
|
||||||
|
<MuteList
|
||||||
|
:refresh="true"
|
||||||
|
:get-key="i => i"
|
||||||
|
>
|
||||||
|
<template
|
||||||
|
slot="header"
|
||||||
|
slot-scope="{selected}"
|
||||||
|
>
|
||||||
|
<div class="bulk-actions">
|
||||||
|
<ProgressButton
|
||||||
|
v-if="selected.length > 0"
|
||||||
|
class="btn btn-default"
|
||||||
|
:click="() => muteUsers(selected)"
|
||||||
|
>
|
||||||
|
{{ $t('user_card.mute') }}
|
||||||
|
<template slot="progress">
|
||||||
|
{{ $t('user_card.mute_progress') }}
|
||||||
|
</template>
|
||||||
|
</ProgressButton>
|
||||||
|
<ProgressButton
|
||||||
|
v-if="selected.length > 0"
|
||||||
|
class="btn btn-default"
|
||||||
|
:click="() => unmuteUsers(selected)"
|
||||||
|
>
|
||||||
|
{{ $t('user_card.unmute') }}
|
||||||
|
<template slot="progress">
|
||||||
|
{{ $t('user_card.unmute_progress') }}
|
||||||
|
</template>
|
||||||
|
</ProgressButton>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template
|
||||||
|
slot="item"
|
||||||
|
slot-scope="{item}"
|
||||||
|
>
|
||||||
|
<MuteCard :user-id="item" />
|
||||||
|
</template>
|
||||||
|
<template slot="empty">
|
||||||
|
{{ $t('settings.no_mutes') }}
|
||||||
|
</template>
|
||||||
|
</MuteList>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div :label="$t('settings.domain_mutes')">
|
||||||
|
<div class="domain-mute-form">
|
||||||
|
<Autosuggest
|
||||||
|
:filter="filterUnMutedDomains"
|
||||||
|
:query="queryKnownDomains"
|
||||||
|
:placeholder="$t('settings.type_domains_to_mute')"
|
||||||
|
>
|
||||||
|
<DomainMuteCard
|
||||||
|
slot-scope="row"
|
||||||
|
:domain="row.item"
|
||||||
|
/>
|
||||||
|
</Autosuggest>
|
||||||
|
</div>
|
||||||
|
<DomainMuteList
|
||||||
|
:refresh="true"
|
||||||
|
:get-key="i => i"
|
||||||
|
>
|
||||||
|
<template
|
||||||
|
slot="header"
|
||||||
|
slot-scope="{selected}"
|
||||||
|
>
|
||||||
|
<div class="bulk-actions">
|
||||||
|
<ProgressButton
|
||||||
|
v-if="selected.length > 0"
|
||||||
|
class="btn btn-default"
|
||||||
|
:click="() => unmuteDomains(selected)"
|
||||||
|
>
|
||||||
|
{{ $t('domain_mute_card.unmute') }}
|
||||||
|
<template slot="progress">
|
||||||
|
{{ $t('domain_mute_card.unmute_progress') }}
|
||||||
|
</template>
|
||||||
|
</ProgressButton>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template
|
||||||
|
slot="item"
|
||||||
|
slot-scope="{item}"
|
||||||
|
>
|
||||||
|
<DomainMuteCard :domain="item" />
|
||||||
|
</template>
|
||||||
|
<template slot="empty">
|
||||||
|
{{ $t('settings.no_mutes') }}
|
||||||
|
</template>
|
||||||
|
</DomainMuteList>
|
||||||
|
</div>
|
||||||
|
</tab-switcher>
|
||||||
|
</div>
|
||||||
|
</tab-switcher>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./mutes_and_blocks_tab.js"></script>
|
||||||
|
<style lang="scss" src="./mutes_and_blocks_tab.scss"></style>
|
||||||
27
src/components/settings_modal/tabs/notifications_tab.js
Normal file
27
src/components/settings_modal/tabs/notifications_tab.js
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
import Checkbox from 'src/components/checkbox/checkbox.vue'
|
||||||
|
|
||||||
|
const NotificationsTab = {
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
activeTab: 'profile',
|
||||||
|
notificationSettings: this.$store.state.users.currentUser.notification_settings,
|
||||||
|
newDomainToMute: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
Checkbox
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
user () {
|
||||||
|
return this.$store.state.users.currentUser
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
updateNotificationSettings () {
|
||||||
|
this.$store.state.api.backendInteractor
|
||||||
|
.updateNotificationSettings({ settings: this.notificationSettings })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NotificationsTab
|
||||||
54
src/components/settings_modal/tabs/notifications_tab.vue
Normal file
54
src/components/settings_modal/tabs/notifications_tab.vue
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
<template>
|
||||||
|
<div :label="$t('settings.notifications')">
|
||||||
|
<div class="setting-item">
|
||||||
|
<h2>{{ $t('settings.notification_setting_filters') }}</h2>
|
||||||
|
<div class="select-multiple">
|
||||||
|
<span class="label">{{ $t('settings.notification_setting') }}</span>
|
||||||
|
<ul class="option-list">
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="notificationSettings.follows">
|
||||||
|
{{ $t('settings.notification_setting_follows') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="notificationSettings.followers">
|
||||||
|
{{ $t('settings.notification_setting_followers') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="notificationSettings.non_follows">
|
||||||
|
{{ $t('settings.notification_setting_non_follows') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="notificationSettings.non_followers">
|
||||||
|
{{ $t('settings.notification_setting_non_followers') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="setting-item">
|
||||||
|
<h2>{{ $t('settings.notification_setting_privacy') }}</h2>
|
||||||
|
<p>
|
||||||
|
<Checkbox v-model="notificationSettings.privacy_option">
|
||||||
|
{{ $t('settings.notification_setting_privacy_option') }}
|
||||||
|
</Checkbox>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="setting-item">
|
||||||
|
<p>{{ $t('settings.notification_mutes') }}</p>
|
||||||
|
<p>{{ $t('settings.notification_blocks') }}</p>
|
||||||
|
<button
|
||||||
|
class="btn btn-default"
|
||||||
|
@click="updateNotificationSettings"
|
||||||
|
>
|
||||||
|
{{ $t('general.submit') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./notifications_tab.js"></script>
|
||||||
|
<!-- <style lang="scss" src="./profile.scss"></style> -->
|
||||||
179
src/components/settings_modal/tabs/profile_tab.js
Normal file
179
src/components/settings_modal/tabs/profile_tab.js
Normal file
|
|
@ -0,0 +1,179 @@
|
||||||
|
import unescape from 'lodash/unescape'
|
||||||
|
import ImageCropper from 'src/components/image_cropper/image_cropper.vue'
|
||||||
|
import ScopeSelector from 'src/components/scope_selector/scope_selector.vue'
|
||||||
|
import fileSizeFormatService from 'src/components/../services/file_size_format/file_size_format.js'
|
||||||
|
import ProgressButton from 'src/components/progress_button/progress_button.vue'
|
||||||
|
import EmojiInput from 'src/components/emoji_input/emoji_input.vue'
|
||||||
|
import suggestor from 'src/components/emoji_input/suggestor.js'
|
||||||
|
import Autosuggest from 'src/components/autosuggest/autosuggest.vue'
|
||||||
|
import Checkbox from 'src/components/checkbox/checkbox.vue'
|
||||||
|
|
||||||
|
const ProfileTab = {
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
newName: this.$store.state.users.currentUser.name,
|
||||||
|
newBio: unescape(this.$store.state.users.currentUser.description),
|
||||||
|
newLocked: this.$store.state.users.currentUser.locked,
|
||||||
|
newNoRichText: this.$store.state.users.currentUser.no_rich_text,
|
||||||
|
newDefaultScope: this.$store.state.users.currentUser.default_scope,
|
||||||
|
hideFollows: this.$store.state.users.currentUser.hide_follows,
|
||||||
|
hideFollowers: this.$store.state.users.currentUser.hide_followers,
|
||||||
|
hideFollowsCount: this.$store.state.users.currentUser.hide_follows_count,
|
||||||
|
hideFollowersCount: this.$store.state.users.currentUser.hide_followers_count,
|
||||||
|
showRole: this.$store.state.users.currentUser.show_role,
|
||||||
|
role: this.$store.state.users.currentUser.role,
|
||||||
|
discoverable: this.$store.state.users.currentUser.discoverable,
|
||||||
|
allowFollowingMove: this.$store.state.users.currentUser.allow_following_move,
|
||||||
|
pickAvatarBtnVisible: true,
|
||||||
|
bannerUploading: false,
|
||||||
|
backgroundUploading: false,
|
||||||
|
banner: null,
|
||||||
|
bannerPreview: null,
|
||||||
|
background: null,
|
||||||
|
backgroundPreview: null,
|
||||||
|
bannerUploadError: null,
|
||||||
|
backgroundUploadError: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
ScopeSelector,
|
||||||
|
ImageCropper,
|
||||||
|
EmojiInput,
|
||||||
|
Autosuggest,
|
||||||
|
ProgressButton,
|
||||||
|
Checkbox
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
user () {
|
||||||
|
return this.$store.state.users.currentUser
|
||||||
|
},
|
||||||
|
emojiUserSuggestor () {
|
||||||
|
return suggestor({
|
||||||
|
emoji: [
|
||||||
|
...this.$store.state.instance.emoji,
|
||||||
|
...this.$store.state.instance.customEmoji
|
||||||
|
],
|
||||||
|
users: this.$store.state.users.users,
|
||||||
|
updateUsersList: (query) => this.$store.dispatch('searchUsers', { query })
|
||||||
|
})
|
||||||
|
},
|
||||||
|
emojiSuggestor () {
|
||||||
|
return suggestor({ emoji: [
|
||||||
|
...this.$store.state.instance.emoji,
|
||||||
|
...this.$store.state.instance.customEmoji
|
||||||
|
] })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
updateProfile () {
|
||||||
|
this.$store.state.api.backendInteractor
|
||||||
|
.updateProfile({
|
||||||
|
params: {
|
||||||
|
note: this.newBio,
|
||||||
|
locked: this.newLocked,
|
||||||
|
// Backend notation.
|
||||||
|
/* eslint-disable camelcase */
|
||||||
|
display_name: this.newName,
|
||||||
|
default_scope: this.newDefaultScope,
|
||||||
|
no_rich_text: this.newNoRichText,
|
||||||
|
hide_follows: this.hideFollows,
|
||||||
|
hide_followers: this.hideFollowers,
|
||||||
|
discoverable: this.discoverable,
|
||||||
|
allow_following_move: this.allowFollowingMove,
|
||||||
|
hide_follows_count: this.hideFollowsCount,
|
||||||
|
hide_followers_count: this.hideFollowersCount,
|
||||||
|
show_role: this.showRole
|
||||||
|
/* eslint-enable camelcase */
|
||||||
|
} }).then((user) => {
|
||||||
|
this.$store.commit('addNewUsers', [user])
|
||||||
|
this.$store.commit('setCurrentUser', user)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
changeVis (visibility) {
|
||||||
|
this.newDefaultScope = visibility
|
||||||
|
},
|
||||||
|
uploadFile (slot, e) {
|
||||||
|
const file = e.target.files[0]
|
||||||
|
if (!file) { return }
|
||||||
|
if (file.size > this.$store.state.instance[slot + 'limit']) {
|
||||||
|
const filesize = fileSizeFormatService.fileSizeFormat(file.size)
|
||||||
|
const allowedsize = fileSizeFormatService.fileSizeFormat(this.$store.state.instance[slot + 'limit'])
|
||||||
|
this[slot + 'UploadError'] = [
|
||||||
|
this.$t('upload.error.base'),
|
||||||
|
this.$t(
|
||||||
|
'upload.error.file_too_big',
|
||||||
|
{
|
||||||
|
filesize: filesize.num,
|
||||||
|
filesizeunit: filesize.unit,
|
||||||
|
allowedsize: allowedsize.num,
|
||||||
|
allowedsizeunit: allowedsize.unit
|
||||||
|
}
|
||||||
|
)
|
||||||
|
].join(' ')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
|
const reader = new FileReader()
|
||||||
|
reader.onload = ({ target }) => {
|
||||||
|
const img = target.result
|
||||||
|
this[slot + 'Preview'] = img
|
||||||
|
this[slot] = file
|
||||||
|
}
|
||||||
|
reader.readAsDataURL(file)
|
||||||
|
},
|
||||||
|
submitAvatar (cropper, file) {
|
||||||
|
const that = this
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
function updateAvatar (avatar) {
|
||||||
|
that.$store.state.api.backendInteractor.updateAvatar({ avatar })
|
||||||
|
.then((user) => {
|
||||||
|
that.$store.commit('addNewUsers', [user])
|
||||||
|
that.$store.commit('setCurrentUser', user)
|
||||||
|
resolve()
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
reject(new Error(that.$t('upload.error.base') + ' ' + err.message))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cropper) {
|
||||||
|
cropper.getCroppedCanvas().toBlob(updateAvatar, file.type)
|
||||||
|
} else {
|
||||||
|
updateAvatar(file)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
submitBanner () {
|
||||||
|
if (!this.bannerPreview) { return }
|
||||||
|
|
||||||
|
this.bannerUploading = true
|
||||||
|
this.$store.state.api.backendInteractor.updateBanner({ banner: this.banner })
|
||||||
|
.then((user) => {
|
||||||
|
this.$store.commit('addNewUsers', [user])
|
||||||
|
this.$store.commit('setCurrentUser', user)
|
||||||
|
this.bannerPreview = null
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
this.bannerUploadError = this.$t('upload.error.base') + ' ' + err.message
|
||||||
|
})
|
||||||
|
.then(() => { this.bannerUploading = false })
|
||||||
|
},
|
||||||
|
submitBg () {
|
||||||
|
if (!this.backgroundPreview) { return }
|
||||||
|
let background = this.background
|
||||||
|
this.backgroundUploading = true
|
||||||
|
this.$store.state.api.backendInteractor.updateBg({ background }).then((data) => {
|
||||||
|
if (!data.error) {
|
||||||
|
this.$store.commit('addNewUsers', [data])
|
||||||
|
this.$store.commit('setCurrentUser', data)
|
||||||
|
this.backgroundPreview = null
|
||||||
|
} else {
|
||||||
|
this.backgroundUploadError = this.$t('upload.error.base') + data.error
|
||||||
|
}
|
||||||
|
this.backgroundUploading = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ProfileTab
|
||||||
82
src/components/settings_modal/tabs/profile_tab.scss
Normal file
82
src/components/settings_modal/tabs/profile_tab.scss
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
@import '../../../_variables.scss';
|
||||||
|
.profile-tab {
|
||||||
|
.bio {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.visibility-tray {
|
||||||
|
padding-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=file] {
|
||||||
|
padding: 5px;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uploading {
|
||||||
|
font-size: 1.5em;
|
||||||
|
margin: 0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.name-changer {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.current-avatar {
|
||||||
|
display: block;
|
||||||
|
width: 150px;
|
||||||
|
height: 150px;
|
||||||
|
border-radius: $fallback--avatarRadius;
|
||||||
|
border-radius: var(--avatarRadius, $fallback--avatarRadius);
|
||||||
|
}
|
||||||
|
|
||||||
|
.oauth-tokens {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
th {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-usersearch-wrapper {
|
||||||
|
padding: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-bulk-actions {
|
||||||
|
text-align: right;
|
||||||
|
padding: 0 1em;
|
||||||
|
min-height: 28px;
|
||||||
|
|
||||||
|
button {
|
||||||
|
width: 10em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-domain-mute-form {
|
||||||
|
padding: 1em;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
button {
|
||||||
|
align-self: flex-end;
|
||||||
|
margin-top: 1em;
|
||||||
|
width: 10em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-subitem {
|
||||||
|
margin-left: 1.75em;
|
||||||
|
}
|
||||||
|
}
|
||||||
213
src/components/settings_modal/tabs/profile_tab.vue
Normal file
213
src/components/settings_modal/tabs/profile_tab.vue
Normal file
|
|
@ -0,0 +1,213 @@
|
||||||
|
<template>
|
||||||
|
<div class="profile-tab">
|
||||||
|
<div class="setting-item">
|
||||||
|
<h2>{{ $t('settings.name_bio') }}</h2>
|
||||||
|
<p>{{ $t('settings.name') }}</p>
|
||||||
|
<EmojiInput
|
||||||
|
v-model="newName"
|
||||||
|
enable-emoji-picker
|
||||||
|
:suggest="emojiSuggestor"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
id="username"
|
||||||
|
v-model="newName"
|
||||||
|
classname="name-changer"
|
||||||
|
>
|
||||||
|
</EmojiInput>
|
||||||
|
<p>{{ $t('settings.bio') }}</p>
|
||||||
|
<EmojiInput
|
||||||
|
v-model="newBio"
|
||||||
|
enable-emoji-picker
|
||||||
|
:suggest="emojiUserSuggestor"
|
||||||
|
>
|
||||||
|
<textarea
|
||||||
|
v-model="newBio"
|
||||||
|
classname="bio"
|
||||||
|
/>
|
||||||
|
</EmojiInput>
|
||||||
|
<p>
|
||||||
|
<Checkbox v-model="newLocked">
|
||||||
|
{{ $t('settings.lock_account_description') }}
|
||||||
|
</Checkbox>
|
||||||
|
</p>
|
||||||
|
<div>
|
||||||
|
<label for="default-vis">{{ $t('settings.default_vis') }}</label>
|
||||||
|
<div
|
||||||
|
id="default-vis"
|
||||||
|
class="visibility-tray"
|
||||||
|
>
|
||||||
|
<scope-selector
|
||||||
|
:show-all="true"
|
||||||
|
:user-default="newDefaultScope"
|
||||||
|
:initial-scope="newDefaultScope"
|
||||||
|
:on-scope-change="changeVis"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<Checkbox v-model="newNoRichText">
|
||||||
|
{{ $t('settings.no_rich_text_description') }}
|
||||||
|
</Checkbox>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<Checkbox v-model="hideFollows">
|
||||||
|
{{ $t('settings.hide_follows_description') }}
|
||||||
|
</Checkbox>
|
||||||
|
</p>
|
||||||
|
<p class="setting-subitem">
|
||||||
|
<Checkbox
|
||||||
|
v-model="hideFollowsCount"
|
||||||
|
:disabled="!hideFollows"
|
||||||
|
>
|
||||||
|
{{ $t('settings.hide_follows_count_description') }}
|
||||||
|
</Checkbox>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<Checkbox v-model="hideFollowers">
|
||||||
|
{{ $t('settings.hide_followers_description') }}
|
||||||
|
</Checkbox>
|
||||||
|
</p>
|
||||||
|
<p class="setting-subitem">
|
||||||
|
<Checkbox
|
||||||
|
v-model="hideFollowersCount"
|
||||||
|
:disabled="!hideFollowers"
|
||||||
|
>
|
||||||
|
{{ $t('settings.hide_followers_count_description') }}
|
||||||
|
</Checkbox>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<Checkbox v-model="allowFollowingMove">
|
||||||
|
{{ $t('settings.allow_following_move') }}
|
||||||
|
</Checkbox>
|
||||||
|
</p>
|
||||||
|
<p v-if="role === 'admin' || role === 'moderator'">
|
||||||
|
<Checkbox v-model="showRole">
|
||||||
|
<template v-if="role === 'admin'">
|
||||||
|
{{ $t('settings.show_admin_badge') }}
|
||||||
|
</template>
|
||||||
|
<template v-if="role === 'moderator'">
|
||||||
|
{{ $t('settings.show_moderator_badge') }}
|
||||||
|
</template>
|
||||||
|
</Checkbox>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<Checkbox v-model="discoverable">
|
||||||
|
{{ $t('settings.discoverable') }}
|
||||||
|
</Checkbox>
|
||||||
|
</p>
|
||||||
|
<button
|
||||||
|
:disabled="newName && newName.length === 0"
|
||||||
|
class="btn btn-default"
|
||||||
|
@click="updateProfile"
|
||||||
|
>
|
||||||
|
{{ $t('general.submit') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="setting-item">
|
||||||
|
<h2>{{ $t('settings.avatar') }}</h2>
|
||||||
|
<p class="visibility-notice">
|
||||||
|
{{ $t('settings.avatar_size_instruction') }}
|
||||||
|
</p>
|
||||||
|
<p>{{ $t('settings.current_avatar') }}</p>
|
||||||
|
<img
|
||||||
|
:src="user.profile_image_url_original"
|
||||||
|
class="current-avatar"
|
||||||
|
>
|
||||||
|
<p>{{ $t('settings.set_new_avatar') }}</p>
|
||||||
|
<button
|
||||||
|
v-show="pickAvatarBtnVisible"
|
||||||
|
id="pick-avatar"
|
||||||
|
class="btn"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
{{ $t('settings.upload_a_photo') }}
|
||||||
|
</button>
|
||||||
|
<image-cropper
|
||||||
|
trigger="#pick-avatar"
|
||||||
|
:submit-handler="submitAvatar"
|
||||||
|
@open="pickAvatarBtnVisible=false"
|
||||||
|
@close="pickAvatarBtnVisible=true"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="setting-item">
|
||||||
|
<h2>{{ $t('settings.profile_banner') }}</h2>
|
||||||
|
<p>{{ $t('settings.current_profile_banner') }}</p>
|
||||||
|
<img
|
||||||
|
:src="user.cover_photo"
|
||||||
|
class="banner"
|
||||||
|
>
|
||||||
|
<p>{{ $t('settings.set_new_profile_banner') }}</p>
|
||||||
|
<img
|
||||||
|
v-if="bannerPreview"
|
||||||
|
class="banner"
|
||||||
|
:src="bannerPreview"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
@change="uploadFile('banner', $event)"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<i
|
||||||
|
v-if="bannerUploading"
|
||||||
|
class=" icon-spin4 animate-spin uploading"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
v-else-if="bannerPreview"
|
||||||
|
class="btn btn-default"
|
||||||
|
@click="submitBanner"
|
||||||
|
>
|
||||||
|
{{ $t('general.submit') }}
|
||||||
|
</button>
|
||||||
|
<div
|
||||||
|
v-if="bannerUploadError"
|
||||||
|
class="alert error"
|
||||||
|
>
|
||||||
|
Error: {{ bannerUploadError }}
|
||||||
|
<i
|
||||||
|
class="button-icon icon-cancel"
|
||||||
|
@click="clearUploadError('banner')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="setting-item">
|
||||||
|
<h2>{{ $t('settings.profile_background') }}</h2>
|
||||||
|
<p>{{ $t('settings.set_new_profile_background') }}</p>
|
||||||
|
<img
|
||||||
|
v-if="backgroundPreview"
|
||||||
|
class="bg"
|
||||||
|
:src="backgroundPreview"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
@change="uploadFile('background', $event)"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<i
|
||||||
|
v-if="backgroundUploading"
|
||||||
|
class=" icon-spin4 animate-spin uploading"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
v-else-if="backgroundPreview"
|
||||||
|
class="btn btn-default"
|
||||||
|
@click="submitBg"
|
||||||
|
>
|
||||||
|
{{ $t('general.submit') }}
|
||||||
|
</button>
|
||||||
|
<div
|
||||||
|
v-if="backgroundUploadError"
|
||||||
|
class="alert error"
|
||||||
|
>
|
||||||
|
Error: {{ backgroundUploadError }}
|
||||||
|
<i
|
||||||
|
class="button-icon icon-cancel"
|
||||||
|
@click="clearUploadError('background')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./profile_tab.js"></script>
|
||||||
|
<style lang="scss" src="./profile_tab.scss"></style>
|
||||||
|
|
@ -137,20 +137,20 @@
|
||||||
|
|
||||||
<script src="./mfa.js"></script>
|
<script src="./mfa.js"></script>
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@import '../../_variables.scss';
|
@import '../../../../_variables.scss';
|
||||||
.warning {
|
|
||||||
color: $fallback--cOrange;
|
|
||||||
color: var(--cOrange, $fallback--cOrange);
|
|
||||||
}
|
|
||||||
.mfa-settings {
|
.mfa-settings {
|
||||||
.mfa-heading, .method-item {
|
.mfa-heading, .method-item {
|
||||||
overflow: hidden;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.warning {
|
||||||
|
color: $fallback--cOrange;
|
||||||
|
color: var(--cOrange, $fallback--cOrange);
|
||||||
|
}
|
||||||
|
|
||||||
.setup-otp {
|
.setup-otp {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div class="mfa-backup-codes">
|
||||||
<h4 v-if="displayTitle">
|
<h4 v-if="displayTitle">
|
||||||
{{ $t('settings.mfa.recovery_codes') }}
|
{{ $t('settings.mfa.recovery_codes') }}
|
||||||
</h4>
|
</h4>
|
||||||
|
|
@ -21,8 +21,9 @@
|
||||||
</template>
|
</template>
|
||||||
<script src="./mfa_backup_codes.js"></script>
|
<script src="./mfa_backup_codes.js"></script>
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@import '../../_variables.scss';
|
@import '../../../../_variables.scss';
|
||||||
|
|
||||||
|
.mfa-backup-codes {
|
||||||
.warning {
|
.warning {
|
||||||
color: $fallback--cOrange;
|
color: $fallback--cOrange;
|
||||||
color: var(--cOrange, $fallback--cOrange);
|
color: var(--cOrange, $fallback--cOrange);
|
||||||
|
|
@ -30,4 +31,5 @@
|
||||||
.backup-codes {
|
.backup-codes {
|
||||||
font-family: var(--postCodeFont, monospace);
|
font-family: var(--postCodeFont, monospace);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
106
src/components/settings_modal/tabs/security_tab/security_tab.js
Normal file
106
src/components/settings_modal/tabs/security_tab/security_tab.js
Normal file
|
|
@ -0,0 +1,106 @@
|
||||||
|
import ProgressButton from 'src/components/progress_button/progress_button.vue'
|
||||||
|
import Checkbox from 'src/components/checkbox/checkbox.vue'
|
||||||
|
import Mfa from './mfa.vue'
|
||||||
|
|
||||||
|
const SecurityTab = {
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
newEmail: '',
|
||||||
|
changeEmailError: false,
|
||||||
|
changeEmailPassword: '',
|
||||||
|
changedEmail: false,
|
||||||
|
deletingAccount: false,
|
||||||
|
deleteAccountConfirmPasswordInput: '',
|
||||||
|
deleteAccountError: false,
|
||||||
|
changePasswordInputs: [ '', '', '' ],
|
||||||
|
changedPassword: false,
|
||||||
|
changePasswordError: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created () {
|
||||||
|
this.$store.dispatch('fetchTokens')
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
ProgressButton,
|
||||||
|
Mfa,
|
||||||
|
Checkbox
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
user () {
|
||||||
|
return this.$store.state.users.currentUser
|
||||||
|
},
|
||||||
|
pleromaBackend () {
|
||||||
|
return this.$store.state.instance.pleromaBackend
|
||||||
|
},
|
||||||
|
oauthTokens () {
|
||||||
|
return this.$store.state.oauthTokens.tokens.map(oauthToken => {
|
||||||
|
return {
|
||||||
|
id: oauthToken.id,
|
||||||
|
appName: oauthToken.app_name,
|
||||||
|
validUntil: new Date(oauthToken.valid_until).toLocaleDateString()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
confirmDelete () {
|
||||||
|
this.deletingAccount = true
|
||||||
|
},
|
||||||
|
deleteAccount () {
|
||||||
|
this.$store.state.api.backendInteractor.deleteAccount({ password: this.deleteAccountConfirmPasswordInput })
|
||||||
|
.then((res) => {
|
||||||
|
if (res.status === 'success') {
|
||||||
|
this.$store.dispatch('logout')
|
||||||
|
this.$router.push({ name: 'root' })
|
||||||
|
} else {
|
||||||
|
this.deleteAccountError = res.error
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
changePassword () {
|
||||||
|
const params = {
|
||||||
|
password: this.changePasswordInputs[0],
|
||||||
|
newPassword: this.changePasswordInputs[1],
|
||||||
|
newPasswordConfirmation: this.changePasswordInputs[2]
|
||||||
|
}
|
||||||
|
this.$store.state.api.backendInteractor.changePassword(params)
|
||||||
|
.then((res) => {
|
||||||
|
if (res.status === 'success') {
|
||||||
|
this.changedPassword = true
|
||||||
|
this.changePasswordError = false
|
||||||
|
this.logout()
|
||||||
|
} else {
|
||||||
|
this.changedPassword = false
|
||||||
|
this.changePasswordError = res.error
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
changeEmail () {
|
||||||
|
const params = {
|
||||||
|
email: this.newEmail,
|
||||||
|
password: this.changeEmailPassword
|
||||||
|
}
|
||||||
|
this.$store.state.api.backendInteractor.changeEmail(params)
|
||||||
|
.then((res) => {
|
||||||
|
if (res.status === 'success') {
|
||||||
|
this.changedEmail = true
|
||||||
|
this.changeEmailError = false
|
||||||
|
} else {
|
||||||
|
this.changedEmail = false
|
||||||
|
this.changeEmailError = res.error
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
logout () {
|
||||||
|
this.$store.dispatch('logout')
|
||||||
|
this.$router.replace('/')
|
||||||
|
},
|
||||||
|
revokeToken (id) {
|
||||||
|
if (window.confirm(`${this.$i18n.t('settings.revoke_token')}?`)) {
|
||||||
|
this.$store.dispatch('revokeToken', id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SecurityTab
|
||||||
143
src/components/settings_modal/tabs/security_tab/security_tab.vue
Normal file
143
src/components/settings_modal/tabs/security_tab/security_tab.vue
Normal file
|
|
@ -0,0 +1,143 @@
|
||||||
|
<template>
|
||||||
|
<div :label="$t('settings.security_tab')">
|
||||||
|
<div class="setting-item">
|
||||||
|
<h2>{{ $t('settings.change_email') }}</h2>
|
||||||
|
<div>
|
||||||
|
<p>{{ $t('settings.new_email') }}</p>
|
||||||
|
<input
|
||||||
|
v-model="newEmail"
|
||||||
|
type="email"
|
||||||
|
autocomplete="email"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p>{{ $t('settings.current_password') }}</p>
|
||||||
|
<input
|
||||||
|
v-model="changeEmailPassword"
|
||||||
|
type="password"
|
||||||
|
autocomplete="current-password"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
class="btn btn-default"
|
||||||
|
@click="changeEmail"
|
||||||
|
>
|
||||||
|
{{ $t('general.submit') }}
|
||||||
|
</button>
|
||||||
|
<p v-if="changedEmail">
|
||||||
|
{{ $t('settings.changed_email') }}
|
||||||
|
</p>
|
||||||
|
<template v-if="changeEmailError !== false">
|
||||||
|
<p>{{ $t('settings.change_email_error') }}</p>
|
||||||
|
<p>{{ changeEmailError }}</p>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="setting-item">
|
||||||
|
<h2>{{ $t('settings.change_password') }}</h2>
|
||||||
|
<div>
|
||||||
|
<p>{{ $t('settings.current_password') }}</p>
|
||||||
|
<input
|
||||||
|
v-model="changePasswordInputs[0]"
|
||||||
|
type="password"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p>{{ $t('settings.new_password') }}</p>
|
||||||
|
<input
|
||||||
|
v-model="changePasswordInputs[1]"
|
||||||
|
type="password"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p>{{ $t('settings.confirm_new_password') }}</p>
|
||||||
|
<input
|
||||||
|
v-model="changePasswordInputs[2]"
|
||||||
|
type="password"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
class="btn btn-default"
|
||||||
|
@click="changePassword"
|
||||||
|
>
|
||||||
|
{{ $t('general.submit') }}
|
||||||
|
</button>
|
||||||
|
<p v-if="changedPassword">
|
||||||
|
{{ $t('settings.changed_password') }}
|
||||||
|
</p>
|
||||||
|
<p v-else-if="changePasswordError !== false">
|
||||||
|
{{ $t('settings.change_password_error') }}
|
||||||
|
</p>
|
||||||
|
<p v-if="changePasswordError">
|
||||||
|
{{ changePasswordError }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="setting-item">
|
||||||
|
<h2>{{ $t('settings.oauth_tokens') }}</h2>
|
||||||
|
<table class="oauth-tokens">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{{ $t('settings.app_name') }}</th>
|
||||||
|
<th>{{ $t('settings.valid_until') }}</th>
|
||||||
|
<th />
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr
|
||||||
|
v-for="oauthToken in oauthTokens"
|
||||||
|
:key="oauthToken.id"
|
||||||
|
>
|
||||||
|
<td>{{ oauthToken.appName }}</td>
|
||||||
|
<td>{{ oauthToken.validUntil }}</td>
|
||||||
|
<td class="actions">
|
||||||
|
<button
|
||||||
|
class="btn btn-default"
|
||||||
|
@click="revokeToken(oauthToken.id)"
|
||||||
|
>
|
||||||
|
{{ $t('settings.revoke_token') }}
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<mfa />
|
||||||
|
<div class="setting-item">
|
||||||
|
<h2>{{ $t('settings.delete_account') }}</h2>
|
||||||
|
<p v-if="!deletingAccount">
|
||||||
|
{{ $t('settings.delete_account_description') }}
|
||||||
|
</p>
|
||||||
|
<div v-if="deletingAccount">
|
||||||
|
<p>{{ $t('settings.delete_account_instructions') }}</p>
|
||||||
|
<p>{{ $t('login.password') }}</p>
|
||||||
|
<input
|
||||||
|
v-model="deleteAccountConfirmPasswordInput"
|
||||||
|
type="password"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
class="btn btn-default"
|
||||||
|
@click="deleteAccount"
|
||||||
|
>
|
||||||
|
{{ $t('settings.delete_account') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<p v-if="deleteAccountError !== false">
|
||||||
|
{{ $t('settings.delete_account_error') }}
|
||||||
|
</p>
|
||||||
|
<p v-if="deleteAccountError">
|
||||||
|
{{ deleteAccountError }}
|
||||||
|
</p>
|
||||||
|
<button
|
||||||
|
v-if="!deletingAccount"
|
||||||
|
class="btn btn-default"
|
||||||
|
@click="confirmDelete"
|
||||||
|
>
|
||||||
|
{{ $t('general.submit') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./security_tab.js"></script>
|
||||||
|
<!-- <style lang="scss" src="./profile.scss"></style> -->
|
||||||
|
|
@ -3,7 +3,7 @@ import {
|
||||||
rgb2hex,
|
rgb2hex,
|
||||||
hex2rgb,
|
hex2rgb,
|
||||||
getContrastRatioLayers
|
getContrastRatioLayers
|
||||||
} from '../../services/color_convert/color_convert.js'
|
} from 'src/services/color_convert/color_convert.js'
|
||||||
import {
|
import {
|
||||||
DEFAULT_SHADOWS,
|
DEFAULT_SHADOWS,
|
||||||
generateColors,
|
generateColors,
|
||||||
|
|
@ -14,26 +14,27 @@ import {
|
||||||
getThemes,
|
getThemes,
|
||||||
shadows2to3,
|
shadows2to3,
|
||||||
colors2to3
|
colors2to3
|
||||||
} from '../../services/style_setter/style_setter.js'
|
} from 'src/services/style_setter/style_setter.js'
|
||||||
import {
|
import {
|
||||||
SLOT_INHERITANCE
|
SLOT_INHERITANCE
|
||||||
} from '../../services/theme_data/pleromafe.js'
|
} from 'src/services/theme_data/pleromafe.js'
|
||||||
import {
|
import {
|
||||||
CURRENT_VERSION,
|
CURRENT_VERSION,
|
||||||
OPACITIES,
|
OPACITIES,
|
||||||
getLayers,
|
getLayers,
|
||||||
getOpacitySlot
|
getOpacitySlot
|
||||||
} from '../../services/theme_data/theme_data.service.js'
|
} from 'src/services/theme_data/theme_data.service.js'
|
||||||
import ColorInput from '../color_input/color_input.vue'
|
import ColorInput from 'src/components/color_input/color_input.vue'
|
||||||
import RangeInput from '../range_input/range_input.vue'
|
import RangeInput from 'src/components/range_input/range_input.vue'
|
||||||
import OpacityInput from '../opacity_input/opacity_input.vue'
|
import OpacityInput from 'src/components/opacity_input/opacity_input.vue'
|
||||||
import ShadowControl from '../shadow_control/shadow_control.vue'
|
import ShadowControl from 'src/components/shadow_control/shadow_control.vue'
|
||||||
import FontControl from '../font_control/font_control.vue'
|
import FontControl from 'src/components/font_control/font_control.vue'
|
||||||
import ContrastRatio from '../contrast_ratio/contrast_ratio.vue'
|
import ContrastRatio from 'src/components/contrast_ratio/contrast_ratio.vue'
|
||||||
import TabSwitcher from '../tab_switcher/tab_switcher.js'
|
import TabSwitcher from 'src/components/tab_switcher/tab_switcher.js'
|
||||||
|
import ExportImport from 'src/components/export_import/export_import.vue'
|
||||||
|
import Checkbox from 'src/components/checkbox/checkbox.vue'
|
||||||
|
|
||||||
import Preview from './preview.vue'
|
import Preview from './preview.vue'
|
||||||
import ExportImport from '../export_import/export_import.vue'
|
|
||||||
import Checkbox from '../checkbox/checkbox.vue'
|
|
||||||
|
|
||||||
// List of color values used in v1
|
// List of color values used in v1
|
||||||
const v1OnlyNames = [
|
const v1OnlyNames = [
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
@import '../../_variables.scss';
|
@import 'src/_variables.scss';
|
||||||
.style-switcher {
|
.theme-tab {
|
||||||
|
padding-bottom: 2em;
|
||||||
.theme-warning {
|
.theme-warning {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
|
|
@ -54,10 +55,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-switcher {
|
|
||||||
margin: 0 -1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.reset-container {
|
.reset-container {
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
@ -98,20 +95,25 @@
|
||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 30px;
|
min-height: 30px;
|
||||||
|
margin-bottom: 1em;
|
||||||
.btn {
|
|
||||||
min-width: 1px;
|
|
||||||
flex: 0 auto;
|
|
||||||
padding: 0 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
p {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
margin-right: .5em;
|
margin-right: .5em;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
margin-bottom: 1em;
|
.tab-header-buttons {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
min-width: 1px;
|
||||||
|
flex: 0 auto;
|
||||||
|
padding: 0 1em;
|
||||||
|
margin-bottom: .5em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.shadow-selector {
|
.shadow-selector {
|
||||||
|
|
@ -161,7 +163,7 @@
|
||||||
border-bottom: 1px dashed;
|
border-bottom: 1px dashed;
|
||||||
border-color: $fallback--border;
|
border-color: $fallback--border;
|
||||||
border-color: var(--border, $fallback--border);
|
border-color: var(--border, $fallback--border);
|
||||||
margin: 1em -1em 0;
|
margin: 1em 0;
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
background: var(--body-background-image);
|
background: var(--body-background-image);
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
|
|
@ -328,6 +330,14 @@
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.apply-container {
|
||||||
|
.btn {
|
||||||
|
min-height: 28px;
|
||||||
|
min-width: 10em;
|
||||||
|
padding: 0 2em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
margin-left: .25em;
|
margin-left: .25em;
|
||||||
margin-right: .25em;
|
margin-right: .25em;
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="style-switcher">
|
<div class="theme-tab">
|
||||||
<div class="presets-container">
|
<div class="presets-container">
|
||||||
<div class="save-load">
|
<div class="save-load">
|
||||||
<div
|
<div
|
||||||
|
|
@ -126,6 +126,7 @@
|
||||||
>
|
>
|
||||||
<div class="tab-header">
|
<div class="tab-header">
|
||||||
<p>{{ $t('settings.theme_help') }}</p>
|
<p>{{ $t('settings.theme_help') }}</p>
|
||||||
|
<div class="tab-header-buttons">
|
||||||
<button
|
<button
|
||||||
class="btn"
|
class="btn"
|
||||||
@click="clearOpacity"
|
@click="clearOpacity"
|
||||||
|
|
@ -139,6 +140,7 @@
|
||||||
{{ $t('settings.style.switcher.clear_all') }}
|
{{ $t('settings.style.switcher.clear_all') }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<p>{{ $t('settings.theme_help_v2_1') }}</p>
|
<p>{{ $t('settings.theme_help_v2_1') }}</p>
|
||||||
<h4>{{ $t('settings.style.common_colors.main') }}</h4>
|
<h4>{{ $t('settings.style.common_colors.main') }}</h4>
|
||||||
<div class="color-item">
|
<div class="color-item">
|
||||||
|
|
@ -951,6 +953,6 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./style_switcher.js"></script>
|
<script src="./theme_tab.js"></script>
|
||||||
|
|
||||||
<style src="./style_switcher.scss" lang="scss"></style>
|
<style src="./theme_tab.scss" lang="scss"></style>
|
||||||
24
src/components/settings_modal/tabs/version_tab.js
Normal file
24
src/components/settings_modal/tabs/version_tab.js
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { extractCommit } from 'src/services/version/version.service'
|
||||||
|
|
||||||
|
const pleromaFeCommitUrl = 'https://git.pleroma.social/pleroma/pleroma-fe/commit/'
|
||||||
|
const pleromaBeCommitUrl = 'https://git.pleroma.social/pleroma/pleroma/commit/'
|
||||||
|
|
||||||
|
const VersionTab = {
|
||||||
|
data () {
|
||||||
|
const instance = this.$store.state.instance
|
||||||
|
return {
|
||||||
|
backendVersion: instance.backendVersion,
|
||||||
|
frontendVersion: instance.frontendVersion
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
frontendVersionLink () {
|
||||||
|
return pleromaFeCommitUrl + this.frontendVersion
|
||||||
|
},
|
||||||
|
backendVersionLink () {
|
||||||
|
return pleromaBeCommitUrl + extractCommit(this.backendVersion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default VersionTab
|
||||||
31
src/components/settings_modal/tabs/version_tab.vue
Normal file
31
src/components/settings_modal/tabs/version_tab.vue
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
<template>
|
||||||
|
<div :label="$t('settings.version.title')">
|
||||||
|
<div class="setting-item">
|
||||||
|
<ul class="setting-list">
|
||||||
|
<li>
|
||||||
|
<p>{{ $t('settings.version.backend_version') }}</p>
|
||||||
|
<ul class="option-list">
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
:href="backendVersionLink"
|
||||||
|
target="_blank"
|
||||||
|
>{{ backendVersion }}</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>{{ $t('settings.version.frontend_version') }}</p>
|
||||||
|
<ul class="option-list">
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
:href="frontendVersionLink"
|
||||||
|
target="_blank"
|
||||||
|
>{{ frontendVersion }}</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script src="./version_tab.js">
|
||||||
|
|
@ -62,6 +62,9 @@ const SideDrawer = {
|
||||||
},
|
},
|
||||||
touchMove (e) {
|
touchMove (e) {
|
||||||
GestureService.updateSwipe(e, this.closeGesture)
|
GestureService.updateSwipe(e, this.closeGesture)
|
||||||
|
},
|
||||||
|
openSettingsModal () {
|
||||||
|
this.$store.dispatch('openSettingsModal')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -122,9 +122,12 @@
|
||||||
</router-link>
|
</router-link>
|
||||||
</li>
|
</li>
|
||||||
<li @click="toggleDrawer">
|
<li @click="toggleDrawer">
|
||||||
<router-link :to="{ name: 'settings' }">
|
<a
|
||||||
|
href="#"
|
||||||
|
@click="openSettingsModal"
|
||||||
|
>
|
||||||
<i class="button-icon icon-cog" /> {{ $t("settings.settings") }}
|
<i class="button-icon icon-cog" /> {{ $t("settings.settings") }}
|
||||||
</router-link>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li @click="toggleDrawer">
|
<li @click="toggleDrawer">
|
||||||
<router-link :to="{ name: 'about'}">
|
<router-link :to="{ name: 'about'}">
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,9 @@ import StatusPopover from '../status_popover/status_popover.vue'
|
||||||
import EmojiReactions from '../emoji_reactions/emoji_reactions.vue'
|
import EmojiReactions from '../emoji_reactions/emoji_reactions.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 { highlightClass, highlightStyle } from '../../services/user_highlighter/user_highlighter.js'
|
import { highlightClass, highlightStyle } from '../../services/user_highlighter/user_highlighter.js'
|
||||||
import { filter, unescape, uniqBy } from 'lodash'
|
import { muteWordHits } from '../../services/status_parser/status_parser.js'
|
||||||
|
import { unescape, uniqBy } from 'lodash'
|
||||||
|
import { mapGetters, mapState } from 'vuex'
|
||||||
|
|
||||||
const Status = {
|
const Status = {
|
||||||
name: 'Status',
|
name: 'Status',
|
||||||
|
|
@ -45,6 +47,12 @@ const Status = {
|
||||||
muteWords () {
|
muteWords () {
|
||||||
return this.mergedConfig.muteWords
|
return this.mergedConfig.muteWords
|
||||||
},
|
},
|
||||||
|
showReasonMutedThread () {
|
||||||
|
return (
|
||||||
|
this.status.thread_muted ||
|
||||||
|
(this.status.reblog && this.status.reblog.thread_muted)
|
||||||
|
) && !this.inConversation
|
||||||
|
},
|
||||||
repeaterClass () {
|
repeaterClass () {
|
||||||
const user = this.statusoid.user
|
const user = this.statusoid.user
|
||||||
return highlightClass(user)
|
return highlightClass(user)
|
||||||
|
|
@ -94,20 +102,42 @@ const Status = {
|
||||||
return !!this.currentUser
|
return !!this.currentUser
|
||||||
},
|
},
|
||||||
muteWordHits () {
|
muteWordHits () {
|
||||||
const statusText = this.status.text.toLowerCase()
|
return muteWordHits(this.status, this.muteWords)
|
||||||
const statusSummary = this.status.summary.toLowerCase()
|
|
||||||
const hits = filter(this.muteWords, (muteWord) => {
|
|
||||||
return statusText.includes(muteWord.toLowerCase()) || statusSummary.includes(muteWord.toLowerCase())
|
|
||||||
})
|
|
||||||
|
|
||||||
return hits
|
|
||||||
},
|
},
|
||||||
muted () {
|
muted () {
|
||||||
const relationship = this.$store.getters.relationship(this.status.user.id)
|
const { status } = this
|
||||||
return !this.unmuted && (
|
const { reblog } = status
|
||||||
(!(this.inProfile && this.status.user.id === this.profileUserId) && relationship.muting) ||
|
const relationship = this.$store.getters.relationship(status.user.id)
|
||||||
(!this.inConversation && this.status.thread_muted) ||
|
const relationshipReblog = reblog && this.$store.getters.relationship(reblog.user.id)
|
||||||
this.muteWordHits.length > 0)
|
const reasonsToMute = (
|
||||||
|
// Post is muted according to BE
|
||||||
|
status.muted ||
|
||||||
|
// Reprööt of a muted post according to BE
|
||||||
|
(reblog && reblog.muted) ||
|
||||||
|
// Muted user
|
||||||
|
relationship.muting ||
|
||||||
|
// Muted user of a reprööt
|
||||||
|
(relationshipReblog && relationshipReblog.muting) ||
|
||||||
|
// Thread is muted
|
||||||
|
status.thread_muted ||
|
||||||
|
// Wordfiltered
|
||||||
|
this.muteWordHits.length > 0
|
||||||
|
)
|
||||||
|
const excusesNotToMute = (
|
||||||
|
(
|
||||||
|
this.inProfile && (
|
||||||
|
// Don't mute user's posts on user timeline (except reblogs)
|
||||||
|
(!reblog && status.user.id === this.profileUserId) ||
|
||||||
|
// Same as above but also allow self-reblogs
|
||||||
|
(reblog && reblog.user.id === this.profileUserId)
|
||||||
|
)
|
||||||
|
) ||
|
||||||
|
// Don't mute statuses in muted conversation when said conversation is opened
|
||||||
|
(this.inConversation && status.thread_muted)
|
||||||
|
// No excuses if post has muted words
|
||||||
|
) && !this.muteWordHits.length > 0
|
||||||
|
|
||||||
|
return !this.unmuted && !excusesNotToMute && reasonsToMute
|
||||||
},
|
},
|
||||||
hideFilteredStatuses () {
|
hideFilteredStatuses () {
|
||||||
return this.mergedConfig.hideFilteredStatuses
|
return this.mergedConfig.hideFilteredStatuses
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,33 @@
|
||||||
</div>
|
</div>
|
||||||
<template v-if="muted && !isPreview">
|
<template v-if="muted && !isPreview">
|
||||||
<div class="media status container muted">
|
<div class="media status container muted">
|
||||||
<small>
|
<small class="username">
|
||||||
|
<i
|
||||||
|
v-if="muted && retweet"
|
||||||
|
class="button-icon icon-retweet"
|
||||||
|
/>
|
||||||
<router-link :to="userProfileLink">
|
<router-link :to="userProfileLink">
|
||||||
{{ status.user.screen_name }}
|
{{ status.user.screen_name }}
|
||||||
</router-link>
|
</router-link>
|
||||||
</small>
|
</small>
|
||||||
<small class="muteWords">{{ muteWordHits.join(', ') }}</small>
|
<small
|
||||||
|
v-if="showReasonMutedThread"
|
||||||
|
class="mute-thread"
|
||||||
|
>
|
||||||
|
{{ $t('status.thread_muted') }}
|
||||||
|
</small>
|
||||||
|
<small
|
||||||
|
v-if="showReasonMutedThread && muteWordHits.length > 0"
|
||||||
|
class="mute-thread"
|
||||||
|
>
|
||||||
|
{{ $t('status.thread_muted_and_words') }}
|
||||||
|
</small>
|
||||||
|
<small
|
||||||
|
class="mute-words"
|
||||||
|
:title="muteWordHits.join(', ')"
|
||||||
|
>
|
||||||
|
{{ muteWordHits.join(', ') }}
|
||||||
|
</small>
|
||||||
<a
|
<a
|
||||||
href="#"
|
href="#"
|
||||||
class="unmute"
|
class="unmute"
|
||||||
|
|
@ -659,20 +680,49 @@ $status-margin: 0.75em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.muted {
|
.muted {
|
||||||
padding: 0.25em 0.5em;
|
padding: .25em .6em;
|
||||||
button {
|
height: 1.2em;
|
||||||
|
line-height: 1.2em;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
|
||||||
|
.username, .mute-thread, .mute-words {
|
||||||
|
word-wrap: normal;
|
||||||
|
word-break: normal;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.username, .mute-words {
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.username {
|
||||||
|
flex: 0 1 auto;
|
||||||
|
margin-right: .2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mute-thread {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mute-words {
|
||||||
|
flex: 1 0 5em;
|
||||||
|
margin-left: .2em;
|
||||||
|
&::before {
|
||||||
|
content: ' '
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.unmute {
|
||||||
|
flex: 0 0 auto;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
}
|
|
||||||
|
|
||||||
.muteWords {
|
|
||||||
margin-left: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
a.unmute {
|
|
||||||
display: block;
|
display: block;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.reply-body {
|
.reply-body {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
|
|
||||||
|
|
@ -176,8 +176,8 @@ const StatusContent = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (target.rel.match(/(?:^|\s)tag(?:$|\s)/) || target.className.match(/hashtag/)) {
|
if (target.rel.match(/(?:^|\s)tag(?:$|\s)/) || target.className.match(/hashtag/)) {
|
||||||
// Extract tag name from link url
|
// Extract tag name from dataset or link url
|
||||||
const tag = extractTagFromUrl(target.href)
|
const tag = target.dataset.tag || extractTagFromUrl(target.href)
|
||||||
if (tag) {
|
if (tag) {
|
||||||
const link = this.generateTagLink(tag)
|
const link = this.generateTagLink(tag)
|
||||||
this.$router.push(link)
|
this.$router.push(link)
|
||||||
|
|
|
||||||
|
|
@ -23,12 +23,21 @@
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@import '../../_variables.scss';
|
@import '../../_variables.scss';
|
||||||
|
.contain-fit {
|
||||||
|
.still-image {
|
||||||
|
img {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.still-image {
|
.still-image {
|
||||||
position: relative;
|
position: relative;
|
||||||
line-height: 0;
|
line-height: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
&:hover canvas {
|
&:hover canvas {
|
||||||
display: none;
|
display: none;
|
||||||
|
|
@ -36,8 +45,8 @@
|
||||||
|
|
||||||
img {
|
img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
|
align-self: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.animated {
|
&.animated {
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,11 @@ export default Vue.component('tab-switcher', {
|
||||||
required: false,
|
required: false,
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
|
},
|
||||||
|
sideTabBar: {
|
||||||
|
required: false,
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
|
|
@ -55,6 +60,9 @@ export default Vue.component('tab-switcher', {
|
||||||
this.onSwitch.call(null, this.$slots.default[index].key)
|
this.onSwitch.call(null, this.$slots.default[index].key)
|
||||||
}
|
}
|
||||||
this.active = index
|
this.active = index
|
||||||
|
if (this.scrollableTabs) {
|
||||||
|
this.$refs.contents.scrollTop = 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -64,7 +72,6 @@ export default Vue.component('tab-switcher', {
|
||||||
if (!slot.tag) return
|
if (!slot.tag) return
|
||||||
const classesTab = ['tab']
|
const classesTab = ['tab']
|
||||||
const classesWrapper = ['tab-wrapper']
|
const classesWrapper = ['tab-wrapper']
|
||||||
|
|
||||||
if (this.activeIndex === index) {
|
if (this.activeIndex === index) {
|
||||||
classesTab.push('active')
|
classesTab.push('active')
|
||||||
classesWrapper.push('active')
|
classesWrapper.push('active')
|
||||||
|
|
@ -87,8 +94,14 @@ export default Vue.component('tab-switcher', {
|
||||||
<button
|
<button
|
||||||
disabled={slot.data.attrs.disabled}
|
disabled={slot.data.attrs.disabled}
|
||||||
onClick={this.activateTab(index)}
|
onClick={this.activateTab(index)}
|
||||||
class={classesTab.join(' ')}>
|
class={classesTab.join(' ')}
|
||||||
{slot.data.attrs.label}</button>
|
type="button"
|
||||||
|
>
|
||||||
|
{!slot.data.attrs.icon ? '' : (<i class={'tab-icon icon-' + slot.data.attrs.icon}/>)}
|
||||||
|
<span class="text">
|
||||||
|
{slot.data.attrs.label}
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
@ -96,20 +109,32 @@ export default Vue.component('tab-switcher', {
|
||||||
const contents = this.$slots.default.map((slot, index) => {
|
const contents = this.$slots.default.map((slot, index) => {
|
||||||
if (!slot.tag) return
|
if (!slot.tag) return
|
||||||
const active = this.activeIndex === index
|
const active = this.activeIndex === index
|
||||||
if (this.renderOnlyFocused) {
|
const classes = [ active ? 'active' : 'hidden' ]
|
||||||
return active
|
if (slot.data.attrs.fullHeight) {
|
||||||
? <div class="active">{slot}</div>
|
classes.push('full-height')
|
||||||
: <div class="hidden"></div>
|
|
||||||
}
|
}
|
||||||
return <div class={active ? 'active' : 'hidden' }>{slot}</div>
|
const renderSlot = (!this.renderOnlyFocused || active)
|
||||||
|
? slot
|
||||||
|
: ''
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div class={classes}>
|
||||||
|
{
|
||||||
|
this.sideTabBar
|
||||||
|
? <h1 class="mobile-label">{slot.data.attrs.label}</h1>
|
||||||
|
: ''
|
||||||
|
}
|
||||||
|
{renderSlot}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="tab-switcher">
|
<div class={'tab-switcher ' + (this.sideTabBar ? 'side-tabs' : 'top-tabs')}>
|
||||||
<div class="tabs">
|
<div class="tabs">
|
||||||
{tabs}
|
{tabs}
|
||||||
</div>
|
</div>
|
||||||
<div class={'contents' + (this.scrollableTabs ? ' scrollable-tabs' : '')}>
|
<div ref="contents" class={'contents' + (this.scrollableTabs ? ' scrollable-tabs' : '')}>
|
||||||
{contents}
|
{contents}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,145 @@
|
||||||
|
|
||||||
.tab-switcher {
|
.tab-switcher {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
|
.tab-icon {
|
||||||
|
font-size: 2em;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.top-tabs {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
|
> .tabs {
|
||||||
|
width: 100%;
|
||||||
|
overflow-y: hidden;
|
||||||
|
overflow-x: auto;
|
||||||
|
padding-top: 5px;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
&::after, &::before {
|
||||||
|
content: '';
|
||||||
|
flex: 1 1 auto;
|
||||||
|
border-bottom: 1px solid;
|
||||||
|
border-bottom-color: $fallback--border;
|
||||||
|
border-bottom-color: var(--border, $fallback--border);
|
||||||
|
}
|
||||||
|
.tab-wrapper {
|
||||||
|
height: 28px;
|
||||||
|
|
||||||
|
&:not(.active)::after {
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
border-bottom: 1px solid;
|
||||||
|
border-bottom-color: $fallback--border;
|
||||||
|
border-bottom-color: var(--border, $fallback--border);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.tab {
|
||||||
|
width: 100%;
|
||||||
|
min-width: 1px;
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
padding-bottom: 99px;
|
||||||
|
margin-bottom: 6px - 99px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.contents.scrollable-tabs {
|
||||||
|
flex-basis: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.side-tabs {
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
@media all and (max-width: 800px) {
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .contents {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .tabs {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
&::after, &::before {
|
||||||
|
flex-shrink: 0;
|
||||||
|
flex-basis: .5em;
|
||||||
|
content: '';
|
||||||
|
border-right: 1px solid;
|
||||||
|
border-right-color: $fallback--border;
|
||||||
|
border-right-color: var(--border, $fallback--border);
|
||||||
|
}
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
flex-grow: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-wrapper {
|
||||||
|
min-width: 10em;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
@media all and (max-width: 800px) {
|
||||||
|
min-width: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.active)::after {
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
border-right: 1px solid;
|
||||||
|
border-right-color: $fallback--border;
|
||||||
|
border-right-color: var(--border, $fallback--border);
|
||||||
|
}
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
flex: 0 0 6px;
|
||||||
|
content: '';
|
||||||
|
border-right: 1px solid;
|
||||||
|
border-right-color: $fallback--border;
|
||||||
|
border-right-color: var(--border, $fallback--border);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child .tab {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab {
|
||||||
|
flex: 1;
|
||||||
|
box-sizing: content-box;
|
||||||
|
min-width: 10em;
|
||||||
|
min-width: 1px;
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
padding-left: 1em;
|
||||||
|
padding-right: calc(1em + 200px);
|
||||||
|
margin-right: -200px;
|
||||||
|
margin-left: 1em;
|
||||||
|
|
||||||
|
@media all and (max-width: 800px) {
|
||||||
|
padding-left: .25em;
|
||||||
|
padding-right: calc(.25em + 200px);
|
||||||
|
margin-right: calc(.25em - 200px);
|
||||||
|
margin-left: .25em;
|
||||||
|
.text {
|
||||||
|
display: none
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.contents {
|
.contents {
|
||||||
flex: 1 0 auto;
|
flex: 1 0 auto;
|
||||||
min-height: 0px;
|
min-height: 0px;
|
||||||
|
|
@ -11,52 +148,32 @@
|
||||||
.hidden {
|
.hidden {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
.full-height:not(.hidden) {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
> *:not(.mobile-label) {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&.scrollable-tabs {
|
&.scrollable-tabs {
|
||||||
flex-basis: 0;
|
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.tabs {
|
|
||||||
display: flex;
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
overflow-y: hidden;
|
|
||||||
overflow-x: auto;
|
|
||||||
padding-top: 5px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
|
|
||||||
&::after, &::before {
|
|
||||||
display: block;
|
|
||||||
content: '';
|
|
||||||
flex: 1 1 auto;
|
|
||||||
border-bottom: 1px solid;
|
|
||||||
border-bottom-color: $fallback--border;
|
|
||||||
border-bottom-color: var(--border, $fallback--border);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-wrapper {
|
|
||||||
height: 28px;
|
|
||||||
position: relative;
|
|
||||||
display: flex;
|
|
||||||
flex: 0 0 auto;
|
|
||||||
|
|
||||||
.tab {
|
.tab {
|
||||||
width: 100%;
|
|
||||||
min-width: 1px;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
border-bottom-left-radius: 0;
|
|
||||||
border-bottom-right-radius: 0;
|
|
||||||
padding: 6px 1em;
|
|
||||||
padding-bottom: 99px;
|
|
||||||
margin-bottom: 6px - 99px;
|
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
padding: 6px 1em;
|
||||||
color: $fallback--text;
|
|
||||||
color: var(--tabText, $fallback--text);
|
|
||||||
background-color: $fallback--fg;
|
background-color: $fallback--fg;
|
||||||
background-color: var(--tab, $fallback--fg);
|
background-color: var(--tab, $fallback--fg);
|
||||||
|
|
||||||
|
&, &:active .tab-icon {
|
||||||
|
color: $fallback--text;
|
||||||
|
color: var(--tabText, $fallback--text);
|
||||||
|
}
|
||||||
|
|
||||||
&:not(.active) {
|
&:not(.active) {
|
||||||
z-index: 4;
|
z-index: 4;
|
||||||
|
|
||||||
|
|
@ -79,20 +196,41 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tabs {
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
&::after, &::before {
|
||||||
|
display: block;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-wrapper {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
|
||||||
&:not(.active) {
|
&:not(.active) {
|
||||||
&::after {
|
&::after {
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
z-index: 7;
|
z-index: 7;
|
||||||
border-bottom: 1px solid;
|
|
||||||
border-bottom-color: $fallback--border;
|
|
||||||
border-bottom-color: var(--border, $fallback--border);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mobile-label {
|
||||||
|
padding-left: .3em;
|
||||||
|
padding-bottom: .25em;
|
||||||
|
margin-top: .5em;
|
||||||
|
margin-left: .2em;
|
||||||
|
margin-bottom: .25em;
|
||||||
|
border-bottom: 1px solid var(--border, $fallback--border);
|
||||||
|
|
||||||
|
@media all and (min-width: 800px) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,15 +50,6 @@
|
||||||
>
|
>
|
||||||
{{ user.name }}
|
{{ user.name }}
|
||||||
</div>
|
</div>
|
||||||
<router-link
|
|
||||||
v-if="!isOtherUser"
|
|
||||||
:to="{ name: 'user-settings' }"
|
|
||||||
>
|
|
||||||
<i
|
|
||||||
class="button-icon icon-wrench usersettings"
|
|
||||||
:title="$t('tool_tip.user_settings')"
|
|
||||||
/>
|
|
||||||
</router-link>
|
|
||||||
<a
|
<a
|
||||||
v-if="isOtherUser && !user.is_local"
|
v-if="isOtherUser && !user.is_local"
|
||||||
:href="user.statusnet_profile_url"
|
:href="user.statusnet_profile_url"
|
||||||
|
|
@ -118,7 +109,7 @@
|
||||||
type="color"
|
type="color"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
for="style-switcher"
|
for="theme_tab"
|
||||||
class="userHighlightSel select"
|
class="userHighlightSel select"
|
||||||
>
|
>
|
||||||
<select
|
<select
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import UserCard from '../user_card/user_card.vue'
|
||||||
import FollowCard from '../follow_card/follow_card.vue'
|
import FollowCard from '../follow_card/follow_card.vue'
|
||||||
import Timeline from '../timeline/timeline.vue'
|
import Timeline from '../timeline/timeline.vue'
|
||||||
import Conversation from '../conversation/conversation.vue'
|
import Conversation from '../conversation/conversation.vue'
|
||||||
|
import TabSwitcher from 'src/components/tab_switcher/tab_switcher.js'
|
||||||
import List from '../list/list.vue'
|
import List from '../list/list.vue'
|
||||||
import withLoadMore from '../../hocs/with_load_more/with_load_more'
|
import withLoadMore from '../../hocs/with_load_more/with_load_more'
|
||||||
|
|
||||||
|
|
@ -146,6 +147,7 @@ const UserProfile = {
|
||||||
FollowerList,
|
FollowerList,
|
||||||
FriendList,
|
FriendList,
|
||||||
FollowCard,
|
FollowCard,
|
||||||
|
TabSwitcher,
|
||||||
Conversation
|
Conversation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,393 +0,0 @@
|
||||||
import unescape from 'lodash/unescape'
|
|
||||||
import get from 'lodash/get'
|
|
||||||
import map from 'lodash/map'
|
|
||||||
import reject from 'lodash/reject'
|
|
||||||
import TabSwitcher from '../tab_switcher/tab_switcher.js'
|
|
||||||
import ImageCropper from '../image_cropper/image_cropper.vue'
|
|
||||||
import StyleSwitcher from '../style_switcher/style_switcher.vue'
|
|
||||||
import ScopeSelector from '../scope_selector/scope_selector.vue'
|
|
||||||
import fileSizeFormatService from '../../services/file_size_format/file_size_format.js'
|
|
||||||
import BlockCard from '../block_card/block_card.vue'
|
|
||||||
import MuteCard from '../mute_card/mute_card.vue'
|
|
||||||
import DomainMuteCard from '../domain_mute_card/domain_mute_card.vue'
|
|
||||||
import SelectableList from '../selectable_list/selectable_list.vue'
|
|
||||||
import ProgressButton from '../progress_button/progress_button.vue'
|
|
||||||
import EmojiInput from '../emoji_input/emoji_input.vue'
|
|
||||||
import suggestor from '../emoji_input/suggestor.js'
|
|
||||||
import Autosuggest from '../autosuggest/autosuggest.vue'
|
|
||||||
import Importer from '../importer/importer.vue'
|
|
||||||
import Exporter from '../exporter/exporter.vue'
|
|
||||||
import withSubscription from '../../hocs/with_subscription/with_subscription'
|
|
||||||
import Checkbox from '../checkbox/checkbox.vue'
|
|
||||||
import Mfa from './mfa.vue'
|
|
||||||
|
|
||||||
const BlockList = withSubscription({
|
|
||||||
fetch: (props, $store) => $store.dispatch('fetchBlocks'),
|
|
||||||
select: (props, $store) => get($store.state.users.currentUser, 'blockIds', []),
|
|
||||||
childPropName: 'items'
|
|
||||||
})(SelectableList)
|
|
||||||
|
|
||||||
const MuteList = withSubscription({
|
|
||||||
fetch: (props, $store) => $store.dispatch('fetchMutes'),
|
|
||||||
select: (props, $store) => get($store.state.users.currentUser, 'muteIds', []),
|
|
||||||
childPropName: 'items'
|
|
||||||
})(SelectableList)
|
|
||||||
|
|
||||||
const DomainMuteList = withSubscription({
|
|
||||||
fetch: (props, $store) => $store.dispatch('fetchDomainMutes'),
|
|
||||||
select: (props, $store) => get($store.state.users.currentUser, 'domainMutes', []),
|
|
||||||
childPropName: 'items'
|
|
||||||
})(SelectableList)
|
|
||||||
|
|
||||||
const UserSettings = {
|
|
||||||
data () {
|
|
||||||
return {
|
|
||||||
newEmail: '',
|
|
||||||
newName: this.$store.state.users.currentUser.name,
|
|
||||||
newBio: unescape(this.$store.state.users.currentUser.description),
|
|
||||||
newLocked: this.$store.state.users.currentUser.locked,
|
|
||||||
newNoRichText: this.$store.state.users.currentUser.no_rich_text,
|
|
||||||
newDefaultScope: this.$store.state.users.currentUser.default_scope,
|
|
||||||
hideFollows: this.$store.state.users.currentUser.hide_follows,
|
|
||||||
hideFollowers: this.$store.state.users.currentUser.hide_followers,
|
|
||||||
hideFollowsCount: this.$store.state.users.currentUser.hide_follows_count,
|
|
||||||
hideFollowersCount: this.$store.state.users.currentUser.hide_followers_count,
|
|
||||||
showRole: this.$store.state.users.currentUser.show_role,
|
|
||||||
role: this.$store.state.users.currentUser.role,
|
|
||||||
discoverable: this.$store.state.users.currentUser.discoverable,
|
|
||||||
allowFollowingMove: this.$store.state.users.currentUser.allow_following_move,
|
|
||||||
pickAvatarBtnVisible: true,
|
|
||||||
bannerUploading: false,
|
|
||||||
backgroundUploading: false,
|
|
||||||
banner: null,
|
|
||||||
bannerPreview: null,
|
|
||||||
background: null,
|
|
||||||
backgroundPreview: null,
|
|
||||||
bannerUploadError: null,
|
|
||||||
backgroundUploadError: null,
|
|
||||||
changeEmailError: false,
|
|
||||||
changeEmailPassword: '',
|
|
||||||
changedEmail: false,
|
|
||||||
deletingAccount: false,
|
|
||||||
deleteAccountConfirmPasswordInput: '',
|
|
||||||
deleteAccountError: false,
|
|
||||||
changePasswordInputs: [ '', '', '' ],
|
|
||||||
changedPassword: false,
|
|
||||||
changePasswordError: false,
|
|
||||||
activeTab: 'profile',
|
|
||||||
notificationSettings: this.$store.state.users.currentUser.notification_settings,
|
|
||||||
newDomainToMute: ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created () {
|
|
||||||
this.$store.dispatch('fetchTokens')
|
|
||||||
},
|
|
||||||
components: {
|
|
||||||
StyleSwitcher,
|
|
||||||
ScopeSelector,
|
|
||||||
TabSwitcher,
|
|
||||||
ImageCropper,
|
|
||||||
BlockList,
|
|
||||||
MuteList,
|
|
||||||
DomainMuteList,
|
|
||||||
EmojiInput,
|
|
||||||
Autosuggest,
|
|
||||||
BlockCard,
|
|
||||||
MuteCard,
|
|
||||||
DomainMuteCard,
|
|
||||||
ProgressButton,
|
|
||||||
Importer,
|
|
||||||
Exporter,
|
|
||||||
Mfa,
|
|
||||||
Checkbox
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
user () {
|
|
||||||
return this.$store.state.users.currentUser
|
|
||||||
},
|
|
||||||
emojiUserSuggestor () {
|
|
||||||
return suggestor({
|
|
||||||
emoji: [
|
|
||||||
...this.$store.state.instance.emoji,
|
|
||||||
...this.$store.state.instance.customEmoji
|
|
||||||
],
|
|
||||||
users: this.$store.state.users.users,
|
|
||||||
updateUsersList: (query) => this.$store.dispatch('searchUsers', { query })
|
|
||||||
})
|
|
||||||
},
|
|
||||||
emojiSuggestor () {
|
|
||||||
return suggestor({ emoji: [
|
|
||||||
...this.$store.state.instance.emoji,
|
|
||||||
...this.$store.state.instance.customEmoji
|
|
||||||
] })
|
|
||||||
},
|
|
||||||
pleromaBackend () {
|
|
||||||
return this.$store.state.instance.pleromaBackend
|
|
||||||
},
|
|
||||||
minimalScopesMode () {
|
|
||||||
return this.$store.state.instance.minimalScopesMode
|
|
||||||
},
|
|
||||||
vis () {
|
|
||||||
return {
|
|
||||||
public: { selected: this.newDefaultScope === 'public' },
|
|
||||||
unlisted: { selected: this.newDefaultScope === 'unlisted' },
|
|
||||||
private: { selected: this.newDefaultScope === 'private' },
|
|
||||||
direct: { selected: this.newDefaultScope === 'direct' }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
currentSaveStateNotice () {
|
|
||||||
return this.$store.state.interface.settings.currentSaveStateNotice
|
|
||||||
},
|
|
||||||
oauthTokens () {
|
|
||||||
return this.$store.state.oauthTokens.tokens.map(oauthToken => {
|
|
||||||
return {
|
|
||||||
id: oauthToken.id,
|
|
||||||
appName: oauthToken.app_name,
|
|
||||||
validUntil: new Date(oauthToken.valid_until).toLocaleDateString()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
updateProfile () {
|
|
||||||
this.$store.state.api.backendInteractor
|
|
||||||
.updateProfile({
|
|
||||||
params: {
|
|
||||||
note: this.newBio,
|
|
||||||
locked: this.newLocked,
|
|
||||||
// Backend notation.
|
|
||||||
/* eslint-disable camelcase */
|
|
||||||
display_name: this.newName,
|
|
||||||
default_scope: this.newDefaultScope,
|
|
||||||
no_rich_text: this.newNoRichText,
|
|
||||||
hide_follows: this.hideFollows,
|
|
||||||
hide_followers: this.hideFollowers,
|
|
||||||
discoverable: this.discoverable,
|
|
||||||
allow_following_move: this.allowFollowingMove,
|
|
||||||
hide_follows_count: this.hideFollowsCount,
|
|
||||||
hide_followers_count: this.hideFollowersCount,
|
|
||||||
show_role: this.showRole
|
|
||||||
/* eslint-enable camelcase */
|
|
||||||
} }).then((user) => {
|
|
||||||
this.$store.commit('addNewUsers', [user])
|
|
||||||
this.$store.commit('setCurrentUser', user)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
updateNotificationSettings () {
|
|
||||||
this.$store.state.api.backendInteractor
|
|
||||||
.updateNotificationSettings({ settings: this.notificationSettings })
|
|
||||||
},
|
|
||||||
changeVis (visibility) {
|
|
||||||
this.newDefaultScope = visibility
|
|
||||||
},
|
|
||||||
uploadFile (slot, e) {
|
|
||||||
const file = e.target.files[0]
|
|
||||||
if (!file) { return }
|
|
||||||
if (file.size > this.$store.state.instance[slot + 'limit']) {
|
|
||||||
const filesize = fileSizeFormatService.fileSizeFormat(file.size)
|
|
||||||
const allowedsize = fileSizeFormatService.fileSizeFormat(this.$store.state.instance[slot + 'limit'])
|
|
||||||
this[slot + 'UploadError'] = this.$t('upload.error.base') + ' ' + this.$t('upload.error.file_too_big', { filesize: filesize.num, filesizeunit: filesize.unit, allowedsize: allowedsize.num, allowedsizeunit: allowedsize.unit })
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
const reader = new FileReader()
|
|
||||||
reader.onload = ({ target }) => {
|
|
||||||
const img = target.result
|
|
||||||
this[slot + 'Preview'] = img
|
|
||||||
this[slot] = file
|
|
||||||
}
|
|
||||||
reader.readAsDataURL(file)
|
|
||||||
},
|
|
||||||
submitAvatar (cropper, file) {
|
|
||||||
const that = this
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
function updateAvatar (avatar) {
|
|
||||||
that.$store.state.api.backendInteractor.updateAvatar({ avatar })
|
|
||||||
.then((user) => {
|
|
||||||
that.$store.commit('addNewUsers', [user])
|
|
||||||
that.$store.commit('setCurrentUser', user)
|
|
||||||
resolve()
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
reject(new Error(that.$t('upload.error.base') + ' ' + err.message))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cropper) {
|
|
||||||
cropper.getCroppedCanvas().toBlob(updateAvatar, file.type)
|
|
||||||
} else {
|
|
||||||
updateAvatar(file)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
clearUploadError (slot) {
|
|
||||||
this[slot + 'UploadError'] = null
|
|
||||||
},
|
|
||||||
submitBanner () {
|
|
||||||
if (!this.bannerPreview) { return }
|
|
||||||
|
|
||||||
this.bannerUploading = true
|
|
||||||
this.$store.state.api.backendInteractor.updateBanner({ banner: this.banner })
|
|
||||||
.then((user) => {
|
|
||||||
this.$store.commit('addNewUsers', [user])
|
|
||||||
this.$store.commit('setCurrentUser', user)
|
|
||||||
this.bannerPreview = null
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
this.bannerUploadError = this.$t('upload.error.base') + ' ' + err.message
|
|
||||||
})
|
|
||||||
.then(() => { this.bannerUploading = false })
|
|
||||||
},
|
|
||||||
submitBg () {
|
|
||||||
if (!this.backgroundPreview) { return }
|
|
||||||
let background = this.background
|
|
||||||
this.backgroundUploading = true
|
|
||||||
this.$store.state.api.backendInteractor.updateBg({ background }).then((data) => {
|
|
||||||
if (!data.error) {
|
|
||||||
this.$store.commit('addNewUsers', [data])
|
|
||||||
this.$store.commit('setCurrentUser', data)
|
|
||||||
this.backgroundPreview = null
|
|
||||||
} else {
|
|
||||||
this.backgroundUploadError = this.$t('upload.error.base') + data.error
|
|
||||||
}
|
|
||||||
this.backgroundUploading = false
|
|
||||||
})
|
|
||||||
},
|
|
||||||
importFollows (file) {
|
|
||||||
return this.$store.state.api.backendInteractor.importFollows({ file })
|
|
||||||
.then((status) => {
|
|
||||||
if (!status) {
|
|
||||||
throw new Error('failed')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
importBlocks (file) {
|
|
||||||
return this.$store.state.api.backendInteractor.importBlocks({ file })
|
|
||||||
.then((status) => {
|
|
||||||
if (!status) {
|
|
||||||
throw new Error('failed')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
generateExportableUsersContent (users) {
|
|
||||||
// Get addresses
|
|
||||||
return users.map((user) => {
|
|
||||||
// check is it's a local user
|
|
||||||
if (user && user.is_local) {
|
|
||||||
// append the instance address
|
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
return user.screen_name + '@' + location.hostname
|
|
||||||
}
|
|
||||||
return user.screen_name
|
|
||||||
}).join('\n')
|
|
||||||
},
|
|
||||||
getFollowsContent () {
|
|
||||||
return this.$store.state.api.backendInteractor.exportFriends({ id: this.$store.state.users.currentUser.id })
|
|
||||||
.then(this.generateExportableUsersContent)
|
|
||||||
},
|
|
||||||
getBlocksContent () {
|
|
||||||
return this.$store.state.api.backendInteractor.fetchBlocks()
|
|
||||||
.then(this.generateExportableUsersContent)
|
|
||||||
},
|
|
||||||
confirmDelete () {
|
|
||||||
this.deletingAccount = true
|
|
||||||
},
|
|
||||||
deleteAccount () {
|
|
||||||
this.$store.state.api.backendInteractor.deleteAccount({ password: this.deleteAccountConfirmPasswordInput })
|
|
||||||
.then((res) => {
|
|
||||||
if (res.status === 'success') {
|
|
||||||
this.$store.dispatch('logout')
|
|
||||||
this.$router.push({ name: 'root' })
|
|
||||||
} else {
|
|
||||||
this.deleteAccountError = res.error
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
changePassword () {
|
|
||||||
const params = {
|
|
||||||
password: this.changePasswordInputs[0],
|
|
||||||
newPassword: this.changePasswordInputs[1],
|
|
||||||
newPasswordConfirmation: this.changePasswordInputs[2]
|
|
||||||
}
|
|
||||||
this.$store.state.api.backendInteractor.changePassword(params)
|
|
||||||
.then((res) => {
|
|
||||||
if (res.status === 'success') {
|
|
||||||
this.changedPassword = true
|
|
||||||
this.changePasswordError = false
|
|
||||||
this.logout()
|
|
||||||
} else {
|
|
||||||
this.changedPassword = false
|
|
||||||
this.changePasswordError = res.error
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
changeEmail () {
|
|
||||||
const params = {
|
|
||||||
email: this.newEmail,
|
|
||||||
password: this.changeEmailPassword
|
|
||||||
}
|
|
||||||
this.$store.state.api.backendInteractor.changeEmail(params)
|
|
||||||
.then((res) => {
|
|
||||||
if (res.status === 'success') {
|
|
||||||
this.changedEmail = true
|
|
||||||
this.changeEmailError = false
|
|
||||||
} else {
|
|
||||||
this.changedEmail = false
|
|
||||||
this.changeEmailError = res.error
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
activateTab (tabName) {
|
|
||||||
this.activeTab = tabName
|
|
||||||
},
|
|
||||||
logout () {
|
|
||||||
this.$store.dispatch('logout')
|
|
||||||
this.$router.replace('/')
|
|
||||||
},
|
|
||||||
revokeToken (id) {
|
|
||||||
if (window.confirm(`${this.$i18n.t('settings.revoke_token')}?`)) {
|
|
||||||
this.$store.dispatch('revokeToken', id)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
filterUnblockedUsers (userIds) {
|
|
||||||
return reject(userIds, (userId) => {
|
|
||||||
const relationship = this.$store.getters.relationship(this.userId)
|
|
||||||
return relationship.blocking || userId === this.$store.state.users.currentUser.id
|
|
||||||
})
|
|
||||||
},
|
|
||||||
filterUnMutedUsers (userIds) {
|
|
||||||
return reject(userIds, (userId) => {
|
|
||||||
const relationship = this.$store.getters.relationship(this.userId)
|
|
||||||
return relationship.muting || userId === this.$store.state.users.currentUser.id
|
|
||||||
})
|
|
||||||
},
|
|
||||||
queryUserIds (query) {
|
|
||||||
return this.$store.dispatch('searchUsers', { query })
|
|
||||||
.then((users) => map(users, 'id'))
|
|
||||||
},
|
|
||||||
blockUsers (ids) {
|
|
||||||
return this.$store.dispatch('blockUsers', ids)
|
|
||||||
},
|
|
||||||
unblockUsers (ids) {
|
|
||||||
return this.$store.dispatch('unblockUsers', ids)
|
|
||||||
},
|
|
||||||
muteUsers (ids) {
|
|
||||||
return this.$store.dispatch('muteUsers', ids)
|
|
||||||
},
|
|
||||||
unmuteUsers (ids) {
|
|
||||||
return this.$store.dispatch('unmuteUsers', ids)
|
|
||||||
},
|
|
||||||
unmuteDomains (domains) {
|
|
||||||
return this.$store.dispatch('unmuteDomains', domains)
|
|
||||||
},
|
|
||||||
muteDomain () {
|
|
||||||
return this.$store.dispatch('muteDomain', this.newDomainToMute)
|
|
||||||
.then(() => { this.newDomainToMute = '' })
|
|
||||||
},
|
|
||||||
identity (value) {
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default UserSettings
|
|
||||||
|
|
@ -1,728 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="settings panel panel-default">
|
|
||||||
<div class="panel-heading">
|
|
||||||
<div class="title">
|
|
||||||
{{ $t('settings.user_settings') }}
|
|
||||||
</div>
|
|
||||||
<transition name="fade">
|
|
||||||
<template v-if="currentSaveStateNotice">
|
|
||||||
<div
|
|
||||||
v-if="currentSaveStateNotice.error"
|
|
||||||
class="alert error"
|
|
||||||
@click.prevent
|
|
||||||
>
|
|
||||||
{{ $t('settings.saving_err') }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
v-if="!currentSaveStateNotice.error"
|
|
||||||
class="alert transparent"
|
|
||||||
@click.prevent
|
|
||||||
>
|
|
||||||
{{ $t('settings.saving_ok') }}
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</transition>
|
|
||||||
</div>
|
|
||||||
<div class="panel-body profile-edit">
|
|
||||||
<tab-switcher>
|
|
||||||
<div :label="$t('settings.profile_tab')">
|
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{ $t('settings.name_bio') }}</h2>
|
|
||||||
<p>{{ $t('settings.name') }}</p>
|
|
||||||
<EmojiInput
|
|
||||||
v-model="newName"
|
|
||||||
enable-emoji-picker
|
|
||||||
:suggest="emojiSuggestor"
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
id="username"
|
|
||||||
v-model="newName"
|
|
||||||
classname="name-changer"
|
|
||||||
>
|
|
||||||
</EmojiInput>
|
|
||||||
<p>{{ $t('settings.bio') }}</p>
|
|
||||||
<EmojiInput
|
|
||||||
v-model="newBio"
|
|
||||||
enable-emoji-picker
|
|
||||||
:suggest="emojiUserSuggestor"
|
|
||||||
>
|
|
||||||
<textarea
|
|
||||||
v-model="newBio"
|
|
||||||
classname="bio"
|
|
||||||
/>
|
|
||||||
</EmojiInput>
|
|
||||||
<p>
|
|
||||||
<Checkbox v-model="newLocked">
|
|
||||||
{{ $t('settings.lock_account_description') }}
|
|
||||||
</Checkbox>
|
|
||||||
</p>
|
|
||||||
<div>
|
|
||||||
<label for="default-vis">{{ $t('settings.default_vis') }}</label>
|
|
||||||
<div
|
|
||||||
id="default-vis"
|
|
||||||
class="visibility-tray"
|
|
||||||
>
|
|
||||||
<scope-selector
|
|
||||||
:show-all="true"
|
|
||||||
:user-default="newDefaultScope"
|
|
||||||
:initial-scope="newDefaultScope"
|
|
||||||
:on-scope-change="changeVis"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<p>
|
|
||||||
<Checkbox v-model="newNoRichText">
|
|
||||||
{{ $t('settings.no_rich_text_description') }}
|
|
||||||
</Checkbox>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<Checkbox v-model="hideFollows">
|
|
||||||
{{ $t('settings.hide_follows_description') }}
|
|
||||||
</Checkbox>
|
|
||||||
</p>
|
|
||||||
<p class="setting-subitem">
|
|
||||||
<Checkbox
|
|
||||||
v-model="hideFollowsCount"
|
|
||||||
:disabled="!hideFollows"
|
|
||||||
>
|
|
||||||
{{ $t('settings.hide_follows_count_description') }}
|
|
||||||
</Checkbox>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<Checkbox v-model="hideFollowers">
|
|
||||||
{{ $t('settings.hide_followers_description') }}
|
|
||||||
</Checkbox>
|
|
||||||
</p>
|
|
||||||
<p class="setting-subitem">
|
|
||||||
<Checkbox
|
|
||||||
v-model="hideFollowersCount"
|
|
||||||
:disabled="!hideFollowers"
|
|
||||||
>
|
|
||||||
{{ $t('settings.hide_followers_count_description') }}
|
|
||||||
</Checkbox>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<Checkbox v-model="allowFollowingMove">
|
|
||||||
{{ $t('settings.allow_following_move') }}
|
|
||||||
</Checkbox>
|
|
||||||
</p>
|
|
||||||
<p v-if="role === 'admin' || role === 'moderator'">
|
|
||||||
<Checkbox v-model="showRole">
|
|
||||||
<template v-if="role === 'admin'">
|
|
||||||
{{ $t('settings.show_admin_badge') }}
|
|
||||||
</template>
|
|
||||||
<template v-if="role === 'moderator'">
|
|
||||||
{{ $t('settings.show_moderator_badge') }}
|
|
||||||
</template>
|
|
||||||
</Checkbox>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<Checkbox v-model="discoverable">
|
|
||||||
{{ $t('settings.discoverable') }}
|
|
||||||
</Checkbox>
|
|
||||||
</p>
|
|
||||||
<button
|
|
||||||
:disabled="newName && newName.length === 0"
|
|
||||||
class="btn btn-default"
|
|
||||||
@click="updateProfile"
|
|
||||||
>
|
|
||||||
{{ $t('general.submit') }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{ $t('settings.avatar') }}</h2>
|
|
||||||
<p class="visibility-notice">
|
|
||||||
{{ $t('settings.avatar_size_instruction') }}
|
|
||||||
</p>
|
|
||||||
<p>{{ $t('settings.current_avatar') }}</p>
|
|
||||||
<img
|
|
||||||
:src="user.profile_image_url_original"
|
|
||||||
class="current-avatar"
|
|
||||||
>
|
|
||||||
<p>{{ $t('settings.set_new_avatar') }}</p>
|
|
||||||
<button
|
|
||||||
v-show="pickAvatarBtnVisible"
|
|
||||||
id="pick-avatar"
|
|
||||||
class="btn"
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
{{ $t('settings.upload_a_photo') }}
|
|
||||||
</button>
|
|
||||||
<image-cropper
|
|
||||||
trigger="#pick-avatar"
|
|
||||||
:submit-handler="submitAvatar"
|
|
||||||
@open="pickAvatarBtnVisible=false"
|
|
||||||
@close="pickAvatarBtnVisible=true"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{ $t('settings.profile_banner') }}</h2>
|
|
||||||
<p>{{ $t('settings.current_profile_banner') }}</p>
|
|
||||||
<img
|
|
||||||
:src="user.cover_photo"
|
|
||||||
class="banner"
|
|
||||||
>
|
|
||||||
<p>{{ $t('settings.set_new_profile_banner') }}</p>
|
|
||||||
<img
|
|
||||||
v-if="bannerPreview"
|
|
||||||
class="banner"
|
|
||||||
:src="bannerPreview"
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<input
|
|
||||||
type="file"
|
|
||||||
@change="uploadFile('banner', $event)"
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
<i
|
|
||||||
v-if="bannerUploading"
|
|
||||||
class=" icon-spin4 animate-spin uploading"
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
v-else-if="bannerPreview"
|
|
||||||
class="btn btn-default"
|
|
||||||
@click="submitBanner"
|
|
||||||
>
|
|
||||||
{{ $t('general.submit') }}
|
|
||||||
</button>
|
|
||||||
<div
|
|
||||||
v-if="bannerUploadError"
|
|
||||||
class="alert error"
|
|
||||||
>
|
|
||||||
Error: {{ bannerUploadError }}
|
|
||||||
<i
|
|
||||||
class="button-icon icon-cancel"
|
|
||||||
@click="clearUploadError('banner')"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{ $t('settings.profile_background') }}</h2>
|
|
||||||
<p>{{ $t('settings.set_new_profile_background') }}</p>
|
|
||||||
<img
|
|
||||||
v-if="backgroundPreview"
|
|
||||||
class="bg"
|
|
||||||
:src="backgroundPreview"
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<input
|
|
||||||
type="file"
|
|
||||||
@change="uploadFile('background', $event)"
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
<i
|
|
||||||
v-if="backgroundUploading"
|
|
||||||
class=" icon-spin4 animate-spin uploading"
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
v-else-if="backgroundPreview"
|
|
||||||
class="btn btn-default"
|
|
||||||
@click="submitBg"
|
|
||||||
>
|
|
||||||
{{ $t('general.submit') }}
|
|
||||||
</button>
|
|
||||||
<div
|
|
||||||
v-if="backgroundUploadError"
|
|
||||||
class="alert error"
|
|
||||||
>
|
|
||||||
Error: {{ backgroundUploadError }}
|
|
||||||
<i
|
|
||||||
class="button-icon icon-cancel"
|
|
||||||
@click="clearUploadError('background')"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div :label="$t('settings.security_tab')">
|
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{ $t('settings.change_email') }}</h2>
|
|
||||||
<div>
|
|
||||||
<p>{{ $t('settings.new_email') }}</p>
|
|
||||||
<input
|
|
||||||
v-model="newEmail"
|
|
||||||
type="email"
|
|
||||||
autocomplete="email"
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<p>{{ $t('settings.current_password') }}</p>
|
|
||||||
<input
|
|
||||||
v-model="changeEmailPassword"
|
|
||||||
type="password"
|
|
||||||
autocomplete="current-password"
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
<button
|
|
||||||
class="btn btn-default"
|
|
||||||
@click="changeEmail"
|
|
||||||
>
|
|
||||||
{{ $t('general.submit') }}
|
|
||||||
</button>
|
|
||||||
<p v-if="changedEmail">
|
|
||||||
{{ $t('settings.changed_email') }}
|
|
||||||
</p>
|
|
||||||
<template v-if="changeEmailError !== false">
|
|
||||||
<p>{{ $t('settings.change_email_error') }}</p>
|
|
||||||
<p>{{ changeEmailError }}</p>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{ $t('settings.change_password') }}</h2>
|
|
||||||
<div>
|
|
||||||
<p>{{ $t('settings.current_password') }}</p>
|
|
||||||
<input
|
|
||||||
v-model="changePasswordInputs[0]"
|
|
||||||
type="password"
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<p>{{ $t('settings.new_password') }}</p>
|
|
||||||
<input
|
|
||||||
v-model="changePasswordInputs[1]"
|
|
||||||
type="password"
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<p>{{ $t('settings.confirm_new_password') }}</p>
|
|
||||||
<input
|
|
||||||
v-model="changePasswordInputs[2]"
|
|
||||||
type="password"
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
<button
|
|
||||||
class="btn btn-default"
|
|
||||||
@click="changePassword"
|
|
||||||
>
|
|
||||||
{{ $t('general.submit') }}
|
|
||||||
</button>
|
|
||||||
<p v-if="changedPassword">
|
|
||||||
{{ $t('settings.changed_password') }}
|
|
||||||
</p>
|
|
||||||
<p v-else-if="changePasswordError !== false">
|
|
||||||
{{ $t('settings.change_password_error') }}
|
|
||||||
</p>
|
|
||||||
<p v-if="changePasswordError">
|
|
||||||
{{ changePasswordError }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{ $t('settings.oauth_tokens') }}</h2>
|
|
||||||
<table class="oauth-tokens">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>{{ $t('settings.app_name') }}</th>
|
|
||||||
<th>{{ $t('settings.valid_until') }}</th>
|
|
||||||
<th />
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr
|
|
||||||
v-for="oauthToken in oauthTokens"
|
|
||||||
:key="oauthToken.id"
|
|
||||||
>
|
|
||||||
<td>{{ oauthToken.appName }}</td>
|
|
||||||
<td>{{ oauthToken.validUntil }}</td>
|
|
||||||
<td class="actions">
|
|
||||||
<button
|
|
||||||
class="btn btn-default"
|
|
||||||
@click="revokeToken(oauthToken.id)"
|
|
||||||
>
|
|
||||||
{{ $t('settings.revoke_token') }}
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<mfa />
|
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{ $t('settings.delete_account') }}</h2>
|
|
||||||
<p v-if="!deletingAccount">
|
|
||||||
{{ $t('settings.delete_account_description') }}
|
|
||||||
</p>
|
|
||||||
<div v-if="deletingAccount">
|
|
||||||
<p>{{ $t('settings.delete_account_instructions') }}</p>
|
|
||||||
<p>{{ $t('login.password') }}</p>
|
|
||||||
<input
|
|
||||||
v-model="deleteAccountConfirmPasswordInput"
|
|
||||||
type="password"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
class="btn btn-default"
|
|
||||||
@click="deleteAccount"
|
|
||||||
>
|
|
||||||
{{ $t('settings.delete_account') }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<p v-if="deleteAccountError !== false">
|
|
||||||
{{ $t('settings.delete_account_error') }}
|
|
||||||
</p>
|
|
||||||
<p v-if="deleteAccountError">
|
|
||||||
{{ deleteAccountError }}
|
|
||||||
</p>
|
|
||||||
<button
|
|
||||||
v-if="!deletingAccount"
|
|
||||||
class="btn btn-default"
|
|
||||||
@click="confirmDelete"
|
|
||||||
>
|
|
||||||
{{ $t('general.submit') }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
v-if="pleromaBackend"
|
|
||||||
:label="$t('settings.notifications')"
|
|
||||||
>
|
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{ $t('settings.notification_setting_filters') }}</h2>
|
|
||||||
<div class="select-multiple">
|
|
||||||
<span class="label">{{ $t('settings.notification_setting') }}</span>
|
|
||||||
<ul class="option-list">
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="notificationSettings.follows">
|
|
||||||
{{ $t('settings.notification_setting_follows') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="notificationSettings.followers">
|
|
||||||
{{ $t('settings.notification_setting_followers') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="notificationSettings.non_follows">
|
|
||||||
{{ $t('settings.notification_setting_non_follows') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="notificationSettings.non_followers">
|
|
||||||
{{ $t('settings.notification_setting_non_followers') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{ $t('settings.notification_setting_privacy') }}</h2>
|
|
||||||
<p>
|
|
||||||
<Checkbox v-model="notificationSettings.privacy_option">
|
|
||||||
{{ $t('settings.notification_setting_privacy_option') }}
|
|
||||||
</Checkbox>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="setting-item">
|
|
||||||
<p>{{ $t('settings.notification_mutes') }}</p>
|
|
||||||
<p>{{ $t('settings.notification_blocks') }}</p>
|
|
||||||
<button
|
|
||||||
class="btn btn-default"
|
|
||||||
@click="updateNotificationSettings"
|
|
||||||
>
|
|
||||||
{{ $t('general.submit') }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
v-if="pleromaBackend"
|
|
||||||
:label="$t('settings.data_import_export_tab')"
|
|
||||||
>
|
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{ $t('settings.follow_import') }}</h2>
|
|
||||||
<p>{{ $t('settings.import_followers_from_a_csv_file') }}</p>
|
|
||||||
<Importer
|
|
||||||
:submit-handler="importFollows"
|
|
||||||
:success-message="$t('settings.follows_imported')"
|
|
||||||
:error-message="$t('settings.follow_import_error')"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{ $t('settings.follow_export') }}</h2>
|
|
||||||
<Exporter
|
|
||||||
:get-content="getFollowsContent"
|
|
||||||
filename="friends.csv"
|
|
||||||
:export-button-label="$t('settings.follow_export_button')"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{ $t('settings.block_import') }}</h2>
|
|
||||||
<p>{{ $t('settings.import_blocks_from_a_csv_file') }}</p>
|
|
||||||
<Importer
|
|
||||||
:submit-handler="importBlocks"
|
|
||||||
:success-message="$t('settings.blocks_imported')"
|
|
||||||
:error-message="$t('settings.block_import_error')"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{ $t('settings.block_export') }}</h2>
|
|
||||||
<Exporter
|
|
||||||
:get-content="getBlocksContent"
|
|
||||||
filename="blocks.csv"
|
|
||||||
:export-button-label="$t('settings.block_export_button')"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div :label="$t('settings.blocks_tab')">
|
|
||||||
<div class="profile-edit-usersearch-wrapper">
|
|
||||||
<Autosuggest
|
|
||||||
:filter="filterUnblockedUsers"
|
|
||||||
:query="queryUserIds"
|
|
||||||
:placeholder="$t('settings.search_user_to_block')"
|
|
||||||
>
|
|
||||||
<BlockCard
|
|
||||||
slot-scope="row"
|
|
||||||
:user-id="row.item"
|
|
||||||
/>
|
|
||||||
</Autosuggest>
|
|
||||||
</div>
|
|
||||||
<BlockList
|
|
||||||
:refresh="true"
|
|
||||||
:get-key="identity"
|
|
||||||
>
|
|
||||||
<template
|
|
||||||
slot="header"
|
|
||||||
slot-scope="{selected}"
|
|
||||||
>
|
|
||||||
<div class="profile-edit-bulk-actions">
|
|
||||||
<ProgressButton
|
|
||||||
v-if="selected.length > 0"
|
|
||||||
class="btn btn-default"
|
|
||||||
:click="() => blockUsers(selected)"
|
|
||||||
>
|
|
||||||
{{ $t('user_card.block') }}
|
|
||||||
<template slot="progress">
|
|
||||||
{{ $t('user_card.block_progress') }}
|
|
||||||
</template>
|
|
||||||
</ProgressButton>
|
|
||||||
<ProgressButton
|
|
||||||
v-if="selected.length > 0"
|
|
||||||
class="btn btn-default"
|
|
||||||
:click="() => unblockUsers(selected)"
|
|
||||||
>
|
|
||||||
{{ $t('user_card.unblock') }}
|
|
||||||
<template slot="progress">
|
|
||||||
{{ $t('user_card.unblock_progress') }}
|
|
||||||
</template>
|
|
||||||
</ProgressButton>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<template
|
|
||||||
slot="item"
|
|
||||||
slot-scope="{item}"
|
|
||||||
>
|
|
||||||
<BlockCard :user-id="item" />
|
|
||||||
</template>
|
|
||||||
<template slot="empty">
|
|
||||||
{{ $t('settings.no_blocks') }}
|
|
||||||
</template>
|
|
||||||
</BlockList>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div :label="$t('settings.mutes_tab')">
|
|
||||||
<tab-switcher>
|
|
||||||
<div label="Users">
|
|
||||||
<div class="profile-edit-usersearch-wrapper">
|
|
||||||
<Autosuggest
|
|
||||||
:filter="filterUnMutedUsers"
|
|
||||||
:query="queryUserIds"
|
|
||||||
:placeholder="$t('settings.search_user_to_mute')"
|
|
||||||
>
|
|
||||||
<MuteCard
|
|
||||||
slot-scope="row"
|
|
||||||
:user-id="row.item"
|
|
||||||
/>
|
|
||||||
</Autosuggest>
|
|
||||||
</div>
|
|
||||||
<MuteList
|
|
||||||
:refresh="true"
|
|
||||||
:get-key="identity"
|
|
||||||
>
|
|
||||||
<template
|
|
||||||
slot="header"
|
|
||||||
slot-scope="{selected}"
|
|
||||||
>
|
|
||||||
<div class="profile-edit-bulk-actions">
|
|
||||||
<ProgressButton
|
|
||||||
v-if="selected.length > 0"
|
|
||||||
class="btn btn-default"
|
|
||||||
:click="() => muteUsers(selected)"
|
|
||||||
>
|
|
||||||
{{ $t('user_card.mute') }}
|
|
||||||
<template slot="progress">
|
|
||||||
{{ $t('user_card.mute_progress') }}
|
|
||||||
</template>
|
|
||||||
</ProgressButton>
|
|
||||||
<ProgressButton
|
|
||||||
v-if="selected.length > 0"
|
|
||||||
class="btn btn-default"
|
|
||||||
:click="() => unmuteUsers(selected)"
|
|
||||||
>
|
|
||||||
{{ $t('user_card.unmute') }}
|
|
||||||
<template slot="progress">
|
|
||||||
{{ $t('user_card.unmute_progress') }}
|
|
||||||
</template>
|
|
||||||
</ProgressButton>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<template
|
|
||||||
slot="item"
|
|
||||||
slot-scope="{item}"
|
|
||||||
>
|
|
||||||
<MuteCard :user-id="item" />
|
|
||||||
</template>
|
|
||||||
<template slot="empty">
|
|
||||||
{{ $t('settings.no_mutes') }}
|
|
||||||
</template>
|
|
||||||
</MuteList>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div :label="$t('settings.domain_mutes')">
|
|
||||||
<div class="profile-edit-domain-mute-form">
|
|
||||||
<input
|
|
||||||
v-model="newDomainToMute"
|
|
||||||
:placeholder="$t('settings.type_domains_to_mute')"
|
|
||||||
type="text"
|
|
||||||
@keyup.enter="muteDomain"
|
|
||||||
>
|
|
||||||
<ProgressButton
|
|
||||||
class="btn btn-default"
|
|
||||||
:click="muteDomain"
|
|
||||||
>
|
|
||||||
{{ $t('domain_mute_card.mute') }}
|
|
||||||
<template slot="progress">
|
|
||||||
{{ $t('domain_mute_card.mute_progress') }}
|
|
||||||
</template>
|
|
||||||
</ProgressButton>
|
|
||||||
</div>
|
|
||||||
<DomainMuteList
|
|
||||||
:refresh="true"
|
|
||||||
:get-key="identity"
|
|
||||||
>
|
|
||||||
<template
|
|
||||||
slot="header"
|
|
||||||
slot-scope="{selected}"
|
|
||||||
>
|
|
||||||
<div class="profile-edit-bulk-actions">
|
|
||||||
<ProgressButton
|
|
||||||
v-if="selected.length > 0"
|
|
||||||
class="btn btn-default"
|
|
||||||
:click="() => unmuteDomains(selected)"
|
|
||||||
>
|
|
||||||
{{ $t('domain_mute_card.unmute') }}
|
|
||||||
<template slot="progress">
|
|
||||||
{{ $t('domain_mute_card.unmute_progress') }}
|
|
||||||
</template>
|
|
||||||
</ProgressButton>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<template
|
|
||||||
slot="item"
|
|
||||||
slot-scope="{item}"
|
|
||||||
>
|
|
||||||
<DomainMuteCard :domain="item" />
|
|
||||||
</template>
|
|
||||||
<template slot="empty">
|
|
||||||
{{ $t('settings.no_mutes') }}
|
|
||||||
</template>
|
|
||||||
</DomainMuteList>
|
|
||||||
</div>
|
|
||||||
</tab-switcher>
|
|
||||||
</div>
|
|
||||||
</tab-switcher>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script src="./user_settings.js">
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
@import '../../_variables.scss';
|
|
||||||
|
|
||||||
.profile-edit {
|
|
||||||
.bio {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.visibility-tray {
|
|
||||||
padding-top: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type=file] {
|
|
||||||
padding: 5px;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.banner {
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.uploading {
|
|
||||||
font-size: 1.5em;
|
|
||||||
margin: 0.25em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.name-changer {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg {
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.current-avatar {
|
|
||||||
display: block;
|
|
||||||
width: 150px;
|
|
||||||
height: 150px;
|
|
||||||
border-radius: $fallback--avatarRadius;
|
|
||||||
border-radius: var(--avatarRadius, $fallback--avatarRadius);
|
|
||||||
}
|
|
||||||
|
|
||||||
.oauth-tokens {
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
th {
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.actions {
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&-usersearch-wrapper {
|
|
||||||
padding: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
&-bulk-actions {
|
|
||||||
text-align: right;
|
|
||||||
padding: 0 1em;
|
|
||||||
min-height: 28px;
|
|
||||||
|
|
||||||
button {
|
|
||||||
width: 10em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&-domain-mute-form {
|
|
||||||
padding: 1em;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
button {
|
|
||||||
align-self: flex-end;
|
|
||||||
margin-top: 1em;
|
|
||||||
width: 10em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.setting-subitem {
|
|
||||||
margin-left: 1.75em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -84,7 +84,10 @@
|
||||||
"account_not_locked_warning_link": "gesperrt",
|
"account_not_locked_warning_link": "gesperrt",
|
||||||
"attachments_sensitive": "Anhänge als heikel markieren",
|
"attachments_sensitive": "Anhänge als heikel markieren",
|
||||||
"content_type": {
|
"content_type": {
|
||||||
"text/plain": "Nur Text"
|
"text/plain": "Nur Text",
|
||||||
|
"text/bbcode": "BBCode",
|
||||||
|
"text/markdown": "Markdown",
|
||||||
|
"text/html": "HTML"
|
||||||
},
|
},
|
||||||
"content_warning": "Betreff (optional)",
|
"content_warning": "Betreff (optional)",
|
||||||
"default": "Sitze gerade im Hofbräuhaus.",
|
"default": "Sitze gerade im Hofbräuhaus.",
|
||||||
|
|
@ -95,6 +98,13 @@
|
||||||
"private": "Nur Follower - Beitrag nur für Follower sichtbar",
|
"private": "Nur Follower - Beitrag nur für Follower sichtbar",
|
||||||
"public": "Öffentlich - Beitrag an öffentliche Zeitleisten",
|
"public": "Öffentlich - Beitrag an öffentliche Zeitleisten",
|
||||||
"unlisted": "Nicht gelistet - Nicht in öffentlichen Zeitleisten anzeigen"
|
"unlisted": "Nicht gelistet - Nicht in öffentlichen Zeitleisten anzeigen"
|
||||||
|
},
|
||||||
|
"direct_warning_to_all": "Dieser Beitrag wird für alle erwähnten Benutzer sichtbar sein.",
|
||||||
|
"direct_warning_to_first_only": "Dieser Beitrag wird für alle Benutzer, die am Anfang der Nachricht erwähnt wurden, sichtbar sein.",
|
||||||
|
"scope_notice": {
|
||||||
|
"public": "Dieser Beitrag wird für alle sichtbar sein",
|
||||||
|
"private": "Dieser Beitrag wird nur für deine Follower sichtbar sein",
|
||||||
|
"unlisted": "Dieser Beitrag wird weder in der öffentlichen Zeitleiste noch im gesamten bekannten Netzwerk sichtbar sein"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"registration": {
|
"registration": {
|
||||||
|
|
@ -112,8 +122,11 @@
|
||||||
"email_required": "darf nicht leer sein",
|
"email_required": "darf nicht leer sein",
|
||||||
"password_required": "darf nicht leer sein",
|
"password_required": "darf nicht leer sein",
|
||||||
"password_confirmation_required": "darf nicht leer sein",
|
"password_confirmation_required": "darf nicht leer sein",
|
||||||
"password_confirmation_match": "sollte mit dem Passwort identisch sein."
|
"password_confirmation_match": "sollte mit dem Passwort identisch sein"
|
||||||
}
|
},
|
||||||
|
"bio_placeholder": "z.B.\nHallo, ich bin Lain.\nIch bin ein Anime Mödchen aus dem vorstädtischen Japan. Du kennst mich vielleicht vom Wired.",
|
||||||
|
"fullname_placeholder": "z.B. Lain Iwakura",
|
||||||
|
"username_placeholder": "z.B. lain"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"attachmentRadius": "Anhänge",
|
"attachmentRadius": "Anhänge",
|
||||||
|
|
@ -125,7 +138,7 @@
|
||||||
"background": "Hintergrund",
|
"background": "Hintergrund",
|
||||||
"bio": "Bio",
|
"bio": "Bio",
|
||||||
"btnRadius": "Buttons",
|
"btnRadius": "Buttons",
|
||||||
"cBlue": "Blau (Antworten, Folgt dir)",
|
"cBlue": "Blau (Antworten, folgt dir)",
|
||||||
"cGreen": "Grün (Retweet)",
|
"cGreen": "Grün (Retweet)",
|
||||||
"cOrange": "Orange (Favorisieren)",
|
"cOrange": "Orange (Favorisieren)",
|
||||||
"cRed": "Rot (Abbrechen)",
|
"cRed": "Rot (Abbrechen)",
|
||||||
|
|
@ -141,21 +154,21 @@
|
||||||
"data_import_export_tab": "Datenimport/-export",
|
"data_import_export_tab": "Datenimport/-export",
|
||||||
"default_vis": "Standard-Sichtbarkeitsumfang",
|
"default_vis": "Standard-Sichtbarkeitsumfang",
|
||||||
"delete_account": "Account löschen",
|
"delete_account": "Account löschen",
|
||||||
"delete_account_description": "Lösche deinen Account und alle deine Nachrichten unwiderruflich.",
|
"delete_account_description": "Lösche deine Daten und deaktiviere deinen Account unwiderruflich.",
|
||||||
"delete_account_error": "Es ist ein Fehler beim Löschen deines Accounts aufgetreten. Tritt dies weiterhin auf, wende dich an den Administrator der Instanz.",
|
"delete_account_error": "Es ist ein Fehler beim Löschen deines Accounts aufgetreten. Tritt dies weiterhin auf, wende dich an den Administrator der Instanz.",
|
||||||
"delete_account_instructions": "Tippe dein Passwort unten in das Feld ein, um die Löschung deines Accounts zu bestätigen.",
|
"delete_account_instructions": "Tippe dein Passwort unten in das Feld ein, um die Löschung deines Accounts zu bestätigen.",
|
||||||
"discoverable": "Erlaubnis für automatisches Suchen nach diesem Account",
|
"discoverable": "Erlaube, dass dieser Account in Suchergebnissen auftaucht",
|
||||||
"avatar_size_instruction": "Die empfohlene minimale Größe für Avatare ist 150x150 Pixel.",
|
"avatar_size_instruction": "Die empfohlene minimale Größe für Avatare ist 150x150 Pixel.",
|
||||||
"pad_emoji": "Emojis mit Leerzeichen umrahmen",
|
"pad_emoji": "Emojis mit Leerzeichen umrahmen",
|
||||||
"export_theme": "Farbschema speichern",
|
"export_theme": "Farbschema speichern",
|
||||||
"filtering": "Filtern",
|
"filtering": "Filtern",
|
||||||
"filtering_explanation": "Alle Beiträge die diese Wörter enthalten werden ausgeblendet. Ein Wort pro Zeile.",
|
"filtering_explanation": "Alle Beiträge, welche diese Wörter enthalten, werden ausgeblendet. Ein Wort pro Zeile.",
|
||||||
"follow_export": "Follower exportieren",
|
"follow_export": "Follower exportieren",
|
||||||
"follow_export_button": "Exportiere deine Follows in eine csv-Datei",
|
"follow_export_button": "Exportiere deine Follows in eine csv-Datei",
|
||||||
"follow_export_processing": "In Bearbeitung. Die Liste steht gleich zum herunterladen bereit.",
|
"follow_export_processing": "In Bearbeitung. Die Liste steht gleich zum herunterladen bereit.",
|
||||||
"follow_import": "Followers importieren",
|
"follow_import": "Follower importieren",
|
||||||
"follow_import_error": "Fehler beim importieren der Follower",
|
"follow_import_error": "Fehler beim Importieren der Follower",
|
||||||
"follows_imported": "Followers importiert! Die Bearbeitung kann eine Zeit lang dauern.",
|
"follows_imported": "Follower importiert! Die Bearbeitung kann einen Moment dauern.",
|
||||||
"foreground": "Vordergrund",
|
"foreground": "Vordergrund",
|
||||||
"general": "Allgemein",
|
"general": "Allgemein",
|
||||||
"hide_attachments_in_convo": "Anhänge in Unterhaltungen ausblenden",
|
"hide_attachments_in_convo": "Anhänge in Unterhaltungen ausblenden",
|
||||||
|
|
@ -168,7 +181,7 @@
|
||||||
"hide_post_stats": "Beitragsstatistiken verbergen (z.B. die Anzahl der Favoriten)",
|
"hide_post_stats": "Beitragsstatistiken verbergen (z.B. die Anzahl der Favoriten)",
|
||||||
"hide_user_stats": "Benutzerstatistiken verbergen (z.B. die Anzahl der Follower)",
|
"hide_user_stats": "Benutzerstatistiken verbergen (z.B. die Anzahl der Follower)",
|
||||||
"hide_filtered_statuses": "Gefilterte Beiträge verbergen",
|
"hide_filtered_statuses": "Gefilterte Beiträge verbergen",
|
||||||
"import_followers_from_a_csv_file": "Importiere Follower, denen du folgen möchtest, aus einer CSV-Datei",
|
"import_followers_from_a_csv_file": "Importiere Follower aus einer CSV-Datei",
|
||||||
"import_theme": "Farbschema laden",
|
"import_theme": "Farbschema laden",
|
||||||
"inputRadius": "Eingabefelder",
|
"inputRadius": "Eingabefelder",
|
||||||
"checkboxRadius": "Auswahlfelder",
|
"checkboxRadius": "Auswahlfelder",
|
||||||
|
|
@ -182,7 +195,7 @@
|
||||||
"lock_account_description": "Sperre deinen Account, um neue Follower zu genehmigen oder abzulehnen",
|
"lock_account_description": "Sperre deinen Account, um neue Follower zu genehmigen oder abzulehnen",
|
||||||
"loop_video": "Videos wiederholen",
|
"loop_video": "Videos wiederholen",
|
||||||
"loop_video_silent_only": "Nur Videos ohne Ton wiederholen (z.B. Mastodons \"gifs\")",
|
"loop_video_silent_only": "Nur Videos ohne Ton wiederholen (z.B. Mastodons \"gifs\")",
|
||||||
"mutes_tab": "Mutes",
|
"mutes_tab": "Stummschaltungen",
|
||||||
"play_videos_in_modal": "Videos in größerem Medienfenster abspielen",
|
"play_videos_in_modal": "Videos in größerem Medienfenster abspielen",
|
||||||
"use_contain_fit": "Vorschaubilder nicht zuschneiden",
|
"use_contain_fit": "Vorschaubilder nicht zuschneiden",
|
||||||
"name": "Name",
|
"name": "Name",
|
||||||
|
|
@ -355,8 +368,44 @@
|
||||||
"checkbox": "Ich habe die Allgemeinen Geschäftsbedingungen überflogen",
|
"checkbox": "Ich habe die Allgemeinen Geschäftsbedingungen überflogen",
|
||||||
"link": "ein netter kleiner Link"
|
"link": "ein netter kleiner Link"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"app_name": "Anwendungsname",
|
||||||
|
"mfa": {
|
||||||
|
"otp": "OTP",
|
||||||
|
"recovery_codes_warning": "Schreibe dir die Codes auf oder speichere sie an einem sicheren Ort - ansonsten wirst du sie nicht wiederfinden. Wenn du den Zugriff zu deiner 2FA App und die Wiederherstellungs-Codes verlierst, wirst du aus deinem Account ausgeschlossen sein.",
|
||||||
|
"recovery_codes": "Wiederherstellungs-Codes.",
|
||||||
|
"warning_of_generate_new_codes": "Wenn du neue Wiederherstellungs-Codes generierst, werden die alten Codes nicht mehr funktionieren.",
|
||||||
|
"generate_new_recovery_codes": "Generiere neue Wiederherstellungs-Codes",
|
||||||
|
"title": "Zwei-Faktor Authentifizierung",
|
||||||
|
"waiting_a_recovery_codes": "Erhalte Wiederherstellungscodes...",
|
||||||
|
"authentication_methods": "Authentifizierungsmethoden",
|
||||||
|
"scan": {
|
||||||
|
"title": "Scan",
|
||||||
|
"secret_code": "Schlüssel",
|
||||||
|
"desc": "Wenn du deine 2FA App verwendest, scanne diesen QR Code oder gebe den Schlüssel ein:"
|
||||||
|
},
|
||||||
|
"verify": {
|
||||||
|
"desc": "Um 2FA zu aktivieren, gib den Code von deiner 2FA-App ein:"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"enter_current_password_to_confirm": "Gib dein aktuelles Passwort ein, um deine Identität zu bestätigen",
|
||||||
|
"security": "Sicherheit",
|
||||||
|
"allow_following_move": "Erlaube automatisches Folgen, sobald ein gefolgter Nutzer umzieht",
|
||||||
|
"blocks_imported": "Blocks importiert! Die Verarbeitung wird einen Moment brauchen.",
|
||||||
|
"block_import_error": "Fehler beim Importieren der Blocks",
|
||||||
|
"block_import": "Block Import",
|
||||||
|
"block_export_button": "Exportiere deine Blocks in eine csv Datei",
|
||||||
|
"block_export": "Block Export",
|
||||||
|
"emoji_reactions_on_timeline": "Zeige Emoji-Reaktionen auf der Zeitleiste",
|
||||||
|
"domain_mutes": "Domains",
|
||||||
|
"changed_email": "Email Adresse erfolgreich geändert!",
|
||||||
|
"change_email_error": "Es trat ein Problem auf beim Versuch, deine Email Adresse zu ändern.",
|
||||||
|
"change_email": "Ändere Email",
|
||||||
|
"notification_setting_non_followers": "Nutzer, die dir nicht folgen",
|
||||||
|
"notification_setting_followers": "Nutzer, die dir folgen",
|
||||||
|
"import_blocks_from_a_csv_file": "Importiere Blocks von einer CSV Datei",
|
||||||
|
"accent": "Akzent"
|
||||||
|
},
|
||||||
"timeline": {
|
"timeline": {
|
||||||
"collapse": "Einklappen",
|
"collapse": "Einklappen",
|
||||||
"conversation": "Unterhaltung",
|
"conversation": "Unterhaltung",
|
||||||
|
|
@ -378,7 +427,7 @@
|
||||||
"follow_again": "Anfrage erneut senden?",
|
"follow_again": "Anfrage erneut senden?",
|
||||||
"follow_unfollow": "Folgen beenden",
|
"follow_unfollow": "Folgen beenden",
|
||||||
"followees": "Folgt",
|
"followees": "Folgt",
|
||||||
"followers": "Followers",
|
"followers": "Folgende",
|
||||||
"following": "Folgst du!",
|
"following": "Folgst du!",
|
||||||
"follows_you": "Folgt dir!",
|
"follows_you": "Folgt dir!",
|
||||||
"its_you": "Das bist du!",
|
"its_you": "Das bist du!",
|
||||||
|
|
@ -386,7 +435,10 @@
|
||||||
"muted": "Stummgeschaltet",
|
"muted": "Stummgeschaltet",
|
||||||
"per_day": "pro Tag",
|
"per_day": "pro Tag",
|
||||||
"remote_follow": "Folgen",
|
"remote_follow": "Folgen",
|
||||||
"statuses": "Beiträge"
|
"statuses": "Beiträge",
|
||||||
|
"admin_menu": {
|
||||||
|
"sandbox": "Erzwinge Beiträge nur für Follower sichtbar zu sein"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"user_profile": {
|
"user_profile": {
|
||||||
"timeline_title": "Beiträge"
|
"timeline_title": "Beiträge"
|
||||||
|
|
@ -511,6 +563,22 @@
|
||||||
"search_emoji": "Nach einem Emoji suchen",
|
"search_emoji": "Nach einem Emoji suchen",
|
||||||
"custom": "Benutzerdefinierter Emoji",
|
"custom": "Benutzerdefinierter Emoji",
|
||||||
"keep_open": "Auswahlfenster offen halten",
|
"keep_open": "Auswahlfenster offen halten",
|
||||||
"add_emoji": "Emoji einfügen"
|
"add_emoji": "Emoji einfügen",
|
||||||
|
"load_all": "Lade alle {emojiAmount} Emoji",
|
||||||
|
"load_all_hint": "Erfolgreich erste {saneAmount} Emoji geladen, alle Emojis zu laden würde Leistungsprobleme hervorrufen.",
|
||||||
|
"unicode": "Unicode Emoji"
|
||||||
|
},
|
||||||
|
"interactions": {
|
||||||
|
"load_older": "Lade ältere Interaktionen",
|
||||||
|
"follows": "Neue Follows",
|
||||||
|
"favs_repeats": "Wiederholungen und Favoriten",
|
||||||
|
"moves": "Benutzer migriert zu"
|
||||||
|
},
|
||||||
|
"selectable_list": {
|
||||||
|
"select_all": "Wähle alle"
|
||||||
|
},
|
||||||
|
"remote_user_resolver": {
|
||||||
|
"searching_for": "Suche nach",
|
||||||
|
"error": "Nicht gefunden."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,9 +34,9 @@
|
||||||
},
|
},
|
||||||
"domain_mute_card": {
|
"domain_mute_card": {
|
||||||
"mute": "Mute",
|
"mute": "Mute",
|
||||||
"mute_progress": "Muting...",
|
"mute_progress": "Muting…",
|
||||||
"unmute": "Unmute",
|
"unmute": "Unmute",
|
||||||
"unmute_progress": "Unmuting..."
|
"unmute_progress": "Unmuting…"
|
||||||
},
|
},
|
||||||
"exporter": {
|
"exporter": {
|
||||||
"export": "Export",
|
"export": "Export",
|
||||||
|
|
@ -59,7 +59,10 @@
|
||||||
"apply": "Apply",
|
"apply": "Apply",
|
||||||
"submit": "Submit",
|
"submit": "Submit",
|
||||||
"more": "More",
|
"more": "More",
|
||||||
|
"loading": "Loading…",
|
||||||
"generic_error": "An error occured",
|
"generic_error": "An error occured",
|
||||||
|
"error_retry": "Please try again",
|
||||||
|
"retry": "Try again",
|
||||||
"optional": "optional",
|
"optional": "optional",
|
||||||
"show_more": "Show more",
|
"show_more": "Show more",
|
||||||
"show_less": "Show less",
|
"show_less": "Show less",
|
||||||
|
|
@ -68,7 +71,9 @@
|
||||||
"disable": "Disable",
|
"disable": "Disable",
|
||||||
"enable": "Enable",
|
"enable": "Enable",
|
||||||
"confirm": "Confirm",
|
"confirm": "Confirm",
|
||||||
"verify": "Verify"
|
"verify": "Verify",
|
||||||
|
"close": "Close",
|
||||||
|
"peek": "Peek"
|
||||||
},
|
},
|
||||||
"image_cropper": {
|
"image_cropper": {
|
||||||
"crop_picture": "Crop picture",
|
"crop_picture": "Crop picture",
|
||||||
|
|
@ -121,7 +126,7 @@
|
||||||
"preferences": "Preferences"
|
"preferences": "Preferences"
|
||||||
},
|
},
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"broken_favorite": "Unknown status, searching for it...",
|
"broken_favorite": "Unknown status, searching for it…",
|
||||||
"favorited_you": "favorited your status",
|
"favorited_you": "favorited your status",
|
||||||
"followed_you": "followed you",
|
"followed_you": "followed you",
|
||||||
"follow_request": "wants to follow you",
|
"follow_request": "wants to follow you",
|
||||||
|
|
@ -234,7 +239,7 @@
|
||||||
"generate_new_recovery_codes": "Generate new recovery codes",
|
"generate_new_recovery_codes": "Generate new recovery codes",
|
||||||
"warning_of_generate_new_codes": "When you generate new recovery codes, your old codes won’t work anymore.",
|
"warning_of_generate_new_codes": "When you generate new recovery codes, your old codes won’t work anymore.",
|
||||||
"recovery_codes": "Recovery codes.",
|
"recovery_codes": "Recovery codes.",
|
||||||
"waiting_a_recovery_codes": "Receiving backup codes...",
|
"waiting_a_recovery_codes": "Receiving backup codes…",
|
||||||
"recovery_codes_warning": "Write the codes down or save them somewhere secure - otherwise you won't see them again. If you lose access to your 2FA app and recovery codes you'll be locked out of your account.",
|
"recovery_codes_warning": "Write the codes down or save them somewhere secure - otherwise you won't see them again. If you lose access to your 2FA app and recovery codes you'll be locked out of your account.",
|
||||||
"authentication_methods": "Authentication methods",
|
"authentication_methods": "Authentication methods",
|
||||||
"scan": {
|
"scan": {
|
||||||
|
|
@ -278,6 +283,7 @@
|
||||||
"current_avatar": "Your current avatar",
|
"current_avatar": "Your current avatar",
|
||||||
"current_password": "Current password",
|
"current_password": "Current password",
|
||||||
"current_profile_banner": "Your current profile banner",
|
"current_profile_banner": "Your current profile banner",
|
||||||
|
"mutes_and_blocks": "Mutes and Blocks",
|
||||||
"data_import_export_tab": "Data Import / Export",
|
"data_import_export_tab": "Data Import / Export",
|
||||||
"default_vis": "Default visibility scope",
|
"default_vis": "Default visibility scope",
|
||||||
"delete_account": "Delete Account",
|
"delete_account": "Delete Account",
|
||||||
|
|
@ -395,7 +401,7 @@
|
||||||
"theme_help_v2_1": "You can also override certain component's colors and opacity by toggling the checkbox, use \"Clear all\" button to clear all overrides.",
|
"theme_help_v2_1": "You can also override certain component's colors and opacity by toggling the checkbox, use \"Clear all\" button to clear all overrides.",
|
||||||
"theme_help_v2_2": "Icons underneath some entries are background/text contrast indicators, hover over for detailed info. Please keep in mind that when using transparency contrast indicators show the worst possible case.",
|
"theme_help_v2_2": "Icons underneath some entries are background/text contrast indicators, hover over for detailed info. Please keep in mind that when using transparency contrast indicators show the worst possible case.",
|
||||||
"tooltipRadius": "Tooltips/alerts",
|
"tooltipRadius": "Tooltips/alerts",
|
||||||
"type_domains_to_mute": "Type in domains to mute",
|
"type_domains_to_mute": "Search domains to mute",
|
||||||
"upload_a_photo": "Upload a photo",
|
"upload_a_photo": "Upload a photo",
|
||||||
"user_settings": "User Settings",
|
"user_settings": "User Settings",
|
||||||
"values": {
|
"values": {
|
||||||
|
|
@ -622,7 +628,9 @@
|
||||||
"mute_conversation": "Mute conversation",
|
"mute_conversation": "Mute conversation",
|
||||||
"unmute_conversation": "Unmute conversation",
|
"unmute_conversation": "Unmute conversation",
|
||||||
"status_unavailable": "Status unavailable",
|
"status_unavailable": "Status unavailable",
|
||||||
"copy_link": "Copy link to status"
|
"copy_link": "Copy link to status",
|
||||||
|
"thread_muted": "Thread muted",
|
||||||
|
"thread_muted_and_words": ", has words:"
|
||||||
},
|
},
|
||||||
"user_card": {
|
"user_card": {
|
||||||
"approve": "Approve",
|
"approve": "Approve",
|
||||||
|
|
@ -652,11 +660,11 @@
|
||||||
"subscribe": "Subscribe",
|
"subscribe": "Subscribe",
|
||||||
"unsubscribe": "Unsubscribe",
|
"unsubscribe": "Unsubscribe",
|
||||||
"unblock": "Unblock",
|
"unblock": "Unblock",
|
||||||
"unblock_progress": "Unblocking...",
|
"unblock_progress": "Unblocking…",
|
||||||
"block_progress": "Blocking...",
|
"block_progress": "Blocking…",
|
||||||
"unmute": "Unmute",
|
"unmute": "Unmute",
|
||||||
"unmute_progress": "Unmuting...",
|
"unmute_progress": "Unmuting…",
|
||||||
"mute_progress": "Muting...",
|
"mute_progress": "Muting…",
|
||||||
"hide_repeats": "Hide repeats",
|
"hide_repeats": "Hide repeats",
|
||||||
"show_repeats": "Show repeats",
|
"show_repeats": "Show repeats",
|
||||||
"admin_menu": {
|
"admin_menu": {
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@
|
||||||
"single_choice": "Elección única",
|
"single_choice": "Elección única",
|
||||||
"multiple_choices": "Elección múltiple",
|
"multiple_choices": "Elección múltiple",
|
||||||
"expiry": "Tiempo de vida de la encuesta",
|
"expiry": "Tiempo de vida de la encuesta",
|
||||||
"expires_in": "La encuensta termina en {0}",
|
"expires_in": "La encuesta termina en {0}",
|
||||||
"expired": "La encuesta terminó hace {0}",
|
"expired": "La encuesta terminó hace {0}",
|
||||||
"not_enough_options": "Muy pocas opciones únicas en la encuesta"
|
"not_enough_options": "Muy pocas opciones únicas en la encuesta"
|
||||||
},
|
},
|
||||||
|
|
@ -137,7 +137,7 @@
|
||||||
},
|
},
|
||||||
"content_warning": "Tema (opcional)",
|
"content_warning": "Tema (opcional)",
|
||||||
"default": "Acabo de aterrizar en L.A.",
|
"default": "Acabo de aterrizar en L.A.",
|
||||||
"direct_warning_to_all": "Esta publicación será visible para todos los usarios mencionados.",
|
"direct_warning_to_all": "Esta publicación será visible para todos los usuarios mencionados.",
|
||||||
"direct_warning_to_first_only": "Esta publicación solo será visible para los usuarios mencionados al comienzo del mensaje.",
|
"direct_warning_to_first_only": "Esta publicación solo será visible para los usuarios mencionados al comienzo del mensaje.",
|
||||||
"posting": "Publicando",
|
"posting": "Publicando",
|
||||||
"scope_notice": {
|
"scope_notice": {
|
||||||
|
|
@ -146,7 +146,7 @@
|
||||||
"unlisted": "Esta publicación no será visible en la Línea Temporal Pública ni en Toda La Red Conocida"
|
"unlisted": "Esta publicación no será visible en la Línea Temporal Pública ni en Toda La Red Conocida"
|
||||||
},
|
},
|
||||||
"scope": {
|
"scope": {
|
||||||
"direct": "Directo - Solo para los usuarios mencionados.",
|
"direct": "Directo - Solo para los usuarios mencionados",
|
||||||
"private": "Solo-seguidores - Solo tus seguidores leerán la publicación",
|
"private": "Solo-seguidores - Solo tus seguidores leerán la publicación",
|
||||||
"public": "Público - Entradas visibles en las Líneas Temporales Públicas",
|
"public": "Público - Entradas visibles en las Líneas Temporales Públicas",
|
||||||
"unlisted": "Sin listar - Entradas no visibles en las Líneas Temporales Públicas"
|
"unlisted": "Sin listar - Entradas no visibles en las Líneas Temporales Públicas"
|
||||||
|
|
@ -210,7 +210,7 @@
|
||||||
"background": "Fondo",
|
"background": "Fondo",
|
||||||
"bio": "Biografía",
|
"bio": "Biografía",
|
||||||
"block_export": "Exportar usuarios bloqueados",
|
"block_export": "Exportar usuarios bloqueados",
|
||||||
"block_export_button": "Exporta la lista de tus usarios bloqueados a un archivo csv",
|
"block_export_button": "Exporta la lista de tus usuarios bloqueados a un archivo csv",
|
||||||
"block_import": "Importar usuarios bloqueados",
|
"block_import": "Importar usuarios bloqueados",
|
||||||
"block_import_error": "Error importando la lista de usuarios bloqueados",
|
"block_import_error": "Error importando la lista de usuarios bloqueados",
|
||||||
"blocks_imported": "¡Lista de usuarios bloqueados importada! El procesado puede tardar un poco.",
|
"blocks_imported": "¡Lista de usuarios bloqueados importada! El procesado puede tardar un poco.",
|
||||||
|
|
@ -222,7 +222,7 @@
|
||||||
"cRed": "Rojo (Cancelar)",
|
"cRed": "Rojo (Cancelar)",
|
||||||
"change_password": "Cambiar contraseña",
|
"change_password": "Cambiar contraseña",
|
||||||
"change_password_error": "Hubo un problema cambiando la contraseña.",
|
"change_password_error": "Hubo un problema cambiando la contraseña.",
|
||||||
"changed_password": "Contraseña cambiada correctamente!",
|
"changed_password": "¡Contraseña cambiada correctamente!",
|
||||||
"collapse_subject": "Colapsar entradas con tema",
|
"collapse_subject": "Colapsar entradas con tema",
|
||||||
"composing": "Redactando",
|
"composing": "Redactando",
|
||||||
"confirm_new_password": "Confirmar la nueva contraseña",
|
"confirm_new_password": "Confirmar la nueva contraseña",
|
||||||
|
|
@ -286,7 +286,7 @@
|
||||||
"notification_visibility_repeats": "Repeticiones (Repeats)",
|
"notification_visibility_repeats": "Repeticiones (Repeats)",
|
||||||
"no_rich_text_description": "Eliminar el formato de texto enriquecido de todas las entradas",
|
"no_rich_text_description": "Eliminar el formato de texto enriquecido de todas las entradas",
|
||||||
"no_blocks": "No hay usuarios bloqueados",
|
"no_blocks": "No hay usuarios bloqueados",
|
||||||
"no_mutes": "No hay usuarios sinlenciados",
|
"no_mutes": "No hay usuarios silenciados",
|
||||||
"hide_follows_description": "No mostrar a quién sigo",
|
"hide_follows_description": "No mostrar a quién sigo",
|
||||||
"hide_followers_description": "No mostrar quién me sigue",
|
"hide_followers_description": "No mostrar quién me sigue",
|
||||||
"hide_follows_count_description": "No mostrar el número de cuentas que sigo",
|
"hide_follows_count_description": "No mostrar el número de cuentas que sigo",
|
||||||
|
|
@ -305,7 +305,7 @@
|
||||||
"profile_background": "Fondo del Perfil",
|
"profile_background": "Fondo del Perfil",
|
||||||
"profile_banner": "Cabecera del Perfil",
|
"profile_banner": "Cabecera del Perfil",
|
||||||
"profile_tab": "Perfil",
|
"profile_tab": "Perfil",
|
||||||
"radii_help": "Estable el redondeo de las esquinas de la interfaz (en píxeles)",
|
"radii_help": "Establezca el redondeo de las esquinas de la interfaz (en píxeles)",
|
||||||
"replies_in_timeline": "Réplicas en la línea temporal",
|
"replies_in_timeline": "Réplicas en la línea temporal",
|
||||||
"reply_link_preview": "Activar la previsualización del enlace de responder al pasar el ratón por encima",
|
"reply_link_preview": "Activar la previsualización del enlace de responder al pasar el ratón por encima",
|
||||||
"reply_visibility_all": "Mostrar todas las réplicas",
|
"reply_visibility_all": "Mostrar todas las réplicas",
|
||||||
|
|
|
||||||
396
src/i18n/et.json
396
src/i18n/et.json
|
|
@ -4,7 +4,19 @@
|
||||||
"find_user": "Otsi kasutajaid"
|
"find_user": "Otsi kasutajaid"
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"submit": "Postita"
|
"submit": "Postita",
|
||||||
|
"verify": "Kinnita",
|
||||||
|
"confirm": "Kinnita",
|
||||||
|
"enable": "Luba",
|
||||||
|
"disable": "Keela",
|
||||||
|
"cancel": "Tühista",
|
||||||
|
"dismiss": "Olgu",
|
||||||
|
"show_less": "Kuva vähem",
|
||||||
|
"show_more": "Kuva rohkem",
|
||||||
|
"optional": "valikuline",
|
||||||
|
"generic_error": "Esines viga",
|
||||||
|
"more": "Rohkem",
|
||||||
|
"apply": "Rakenda"
|
||||||
},
|
},
|
||||||
"login": {
|
"login": {
|
||||||
"login": "Logi sisse",
|
"login": "Logi sisse",
|
||||||
|
|
@ -12,29 +24,95 @@
|
||||||
"password": "Parool",
|
"password": "Parool",
|
||||||
"placeholder": "nt lain",
|
"placeholder": "nt lain",
|
||||||
"register": "Registreeru",
|
"register": "Registreeru",
|
||||||
"username": "Kasutajanimi"
|
"username": "Kasutajanimi",
|
||||||
|
"heading": {
|
||||||
|
"recovery": "Kaheastmelise autentimise taaste",
|
||||||
|
"totp": "Kaheastmeline autentimine"
|
||||||
|
},
|
||||||
|
"recovery_code": "Taastekood",
|
||||||
|
"enter_two_factor_code": "Sisesta kaheastmelise autentimise kood",
|
||||||
|
"enter_recovery_code": "Sisesta taastekood",
|
||||||
|
"authentication_code": "Autentimiskood",
|
||||||
|
"hint": "Logi sisse, et liituda vestlusega",
|
||||||
|
"description": "Logi sisse OAuthiga"
|
||||||
},
|
},
|
||||||
"nav": {
|
"nav": {
|
||||||
"mentions": "Mainimised",
|
"mentions": "Mainimised",
|
||||||
"public_tl": "Avalik Ajajoon",
|
"public_tl": "Avalik Ajajoon",
|
||||||
"timeline": "Ajajoon",
|
"timeline": "Ajajoon",
|
||||||
"twkn": "Kogu Teadaolev Võrgustik"
|
"twkn": "Kogu Teadaolev Võrgustik",
|
||||||
|
"preferences": "Eelistused",
|
||||||
|
"who_to_follow": "Keda jälgida",
|
||||||
|
"search": "Otsing",
|
||||||
|
"user_search": "Kasutajaotsing",
|
||||||
|
"dms": "Privaatsõnumid",
|
||||||
|
"interactions": "Interaktsioonid",
|
||||||
|
"friend_requests": "Jägimistaotlused",
|
||||||
|
"chat": "Kohalik vestlus",
|
||||||
|
"back": "Tagasi",
|
||||||
|
"administration": "Administreerimine",
|
||||||
|
"about": "Meist"
|
||||||
},
|
},
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"followed_you": "alustas sinu jälgimist",
|
"followed_you": "alustas sinu jälgimist",
|
||||||
"notifications": "Teavitused",
|
"notifications": "Teated",
|
||||||
"read": "Loe!"
|
"read": "Loe!",
|
||||||
|
"reacted_with": "reageeris {0}",
|
||||||
|
"migrated_to": "kolis",
|
||||||
|
"no_more_notifications": "Rohkem teateid ei ole",
|
||||||
|
"repeated_you": "taaspostitas su staatuse",
|
||||||
|
"load_older": "Laadi vanemad teated",
|
||||||
|
"follow_request": "soovib Teid jälgida",
|
||||||
|
"favorited_you": "lisas su staatuse lemmikuks",
|
||||||
|
"broken_favorite": "Tundmatu staatus, otsin…"
|
||||||
},
|
},
|
||||||
"post_status": {
|
"post_status": {
|
||||||
"default": "Just sõitsin elektrirongiga Tallinnast Pääskülla.",
|
"default": "Just sõitsin elektrirongiga Tallinnast Pääskülla.",
|
||||||
"posting": "Postitan"
|
"posting": "Postitan",
|
||||||
|
"scope": {
|
||||||
|
"unlisted": "Peidetud - Ära postita avalikele ajajoontele",
|
||||||
|
"public": "Avalil - Postita avalikele ajajoontele",
|
||||||
|
"private": "Jälgijatele - Postita ainult jälgijatele",
|
||||||
|
"direct": "Privaatne - Postita ainult mainitud kasutajatele"
|
||||||
|
},
|
||||||
|
"scope_notice": {
|
||||||
|
"unlisted": "See postitus ei ole nähtav avalikul ega kogu võrgu ajajoonel",
|
||||||
|
"private": "See postitus on nähtav ainult Teie jälgijatele",
|
||||||
|
"public": "See postitus on nähtav kõigile"
|
||||||
|
},
|
||||||
|
"direct_warning_to_first_only": "See postitus on nähtav ainult kirja alguses mainitud kasutajatele.",
|
||||||
|
"direct_warning_to_all": "See postitus on nähtav kõikidele mainitud kasutajatele.",
|
||||||
|
"content_warning": "Pealkiri (valikuline)",
|
||||||
|
"content_type": {
|
||||||
|
"text/bbcode": "BBCode",
|
||||||
|
"text/markdown": "Markdown",
|
||||||
|
"text/html": "HTML",
|
||||||
|
"text/plain": "Lihttekst"
|
||||||
|
},
|
||||||
|
"attachments_sensitive": "Märgi manused sensitiivseks",
|
||||||
|
"account_not_locked_warning_link": "lukus",
|
||||||
|
"account_not_locked_warning": "Teie konto ei ole {0}. Kõik võivad Teid jälgida, et näha Teie ainult-jälgijatele postitusi.",
|
||||||
|
"new_status": "Postita uus staatus"
|
||||||
},
|
},
|
||||||
"registration": {
|
"registration": {
|
||||||
"bio": "Bio",
|
"bio": "Bio",
|
||||||
"email": "E-post",
|
"email": "E-post",
|
||||||
"fullname": "Kuvatav nimi",
|
"fullname": "Kuvatav nimi",
|
||||||
"password_confirm": "Parooli kinnitamine",
|
"password_confirm": "Parooli kinnitamine",
|
||||||
"registration": "Registreerimine"
|
"registration": "Registreerimine",
|
||||||
|
"validations": {
|
||||||
|
"password_confirmation_match": "peaks olema sama kui salasõna",
|
||||||
|
"password_confirmation_required": "ei saa jätta tühjaks",
|
||||||
|
"password_required": "ei saa jätta tühjaks",
|
||||||
|
"email_required": "ei saa jätta tühjaks",
|
||||||
|
"fullname_required": "ei saa jätta tühjaks",
|
||||||
|
"username_required": "ei saa jätta tühjaks"
|
||||||
|
},
|
||||||
|
"fullname_placeholder": "Näiteks Lain Iwakura",
|
||||||
|
"username_placeholder": "Näiteks lain",
|
||||||
|
"new_captcha": "Vajuta pildile, et saada uus captcha",
|
||||||
|
"captcha": "CAPTCHA",
|
||||||
|
"token": "Kutse võti"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"attachments": "Manused",
|
"attachments": "Manused",
|
||||||
|
|
@ -44,7 +122,7 @@
|
||||||
"current_avatar": "Sinu praegune profiilipilt",
|
"current_avatar": "Sinu praegune profiilipilt",
|
||||||
"current_profile_banner": "Praegune profiilibänner",
|
"current_profile_banner": "Praegune profiilibänner",
|
||||||
"filtering": "Sisu filtreerimine",
|
"filtering": "Sisu filtreerimine",
|
||||||
"filtering_explanation": "Kõiki staatuseid, mis sisaldavad neid sõnu, ei kuvata. Üks sõna reale.",
|
"filtering_explanation": "Kõiki staatuseid, mis sisaldavad neid sõnu, ei kuvata. Üks sõna reale",
|
||||||
"hide_attachments_in_convo": "Peida manused vastlustes",
|
"hide_attachments_in_convo": "Peida manused vastlustes",
|
||||||
"hide_attachments_in_tl": "Peida manused ajajoonel",
|
"hide_attachments_in_tl": "Peida manused ajajoonel",
|
||||||
"name": "Nimi",
|
"name": "Nimi",
|
||||||
|
|
@ -58,7 +136,201 @@
|
||||||
"set_new_profile_banner": "Vali uus profiilibänner",
|
"set_new_profile_banner": "Vali uus profiilibänner",
|
||||||
"settings": "Sätted",
|
"settings": "Sätted",
|
||||||
"theme": "Teema",
|
"theme": "Teema",
|
||||||
"user_settings": "Kasutaja sätted"
|
"user_settings": "Kasutaja sätted",
|
||||||
|
"subject_line_noop": "Ära kopeeri",
|
||||||
|
"subject_line_mastodon": "Nagu mastodon: kopeeri nagu on",
|
||||||
|
"subject_line_email": "Nagu e-post: \"vs: pealkiri\"",
|
||||||
|
"subject_line_behavior": "Kopeeri pealkiri vastamisel",
|
||||||
|
"subject_input_always_show": "Alati kuva pealkirja välja",
|
||||||
|
"minimal_scopes_mode": "Peida postituse nähtavussätted",
|
||||||
|
"scope_copy": "Kopeeri nähtavussätted vastamisel (Privaatsed on alati kopeeritud)",
|
||||||
|
"security_tab": "Turvalisus",
|
||||||
|
"search_user_to_mute": "Otsi, keda soovid vaigistada",
|
||||||
|
"search_user_to_block": "Otsi, keda soovid blokeerida",
|
||||||
|
"saving_ok": "Sätted salvestatud",
|
||||||
|
"saving_err": "Sätete salvestamine ebaõnnestus",
|
||||||
|
"autohide_floating_post_button": "Automaatselt peida uue postituse nupp (mobiilil)",
|
||||||
|
"reply_visibility_self": "Näita ainult vastuseid, mis on suunatud mulle",
|
||||||
|
"reply_visibility_following": "Näita ainult vastuseid, mis on suunatud mulle või kasutajatele, keda jälgin",
|
||||||
|
"reply_visibility_all": "Näita kõiki vastuseid",
|
||||||
|
"replies_in_timeline": "Vastused ajajoonel",
|
||||||
|
"radii_help": "Liidese ümardamine (pikslites)",
|
||||||
|
"profile_tab": "Profiil",
|
||||||
|
"presets": "Salvestatud sätted",
|
||||||
|
"pause_on_unfocused": "Peata reaalajas voog kui leht pole fookuses",
|
||||||
|
"panelRadius": "Paneelid",
|
||||||
|
"revoke_token": "Keela",
|
||||||
|
"valid_until": "Kehtiv kuni",
|
||||||
|
"refresh_token": "Värskendustoken",
|
||||||
|
"token": "Token",
|
||||||
|
"oauth_tokens": "OAuth tokenid",
|
||||||
|
"show_moderator_badge": "Näita Moderaator silti mu profiilil",
|
||||||
|
"show_admin_badge": "Näita Admin silti mu profiilil",
|
||||||
|
"hide_followers_count_description": "Ära näita minu jälgijate arvu",
|
||||||
|
"hide_follows_count_description": "Ära näita minu jälgimiste arvu",
|
||||||
|
"hide_followers_description": "Ära näita minu jälgijaid",
|
||||||
|
"hide_follows_description": "Ära näita minu jälgimisi",
|
||||||
|
"no_mutes": "Vaigistusi pole",
|
||||||
|
"no_blocks": "Blokeeringuid pole",
|
||||||
|
"no_rich_text_description": "Muuda kõik postitused lihttekstiks",
|
||||||
|
"notification_visibility_emoji_reactions": "Reaktsioonid",
|
||||||
|
"notification_visibility_moves": "Kasutaja kolimised",
|
||||||
|
"notification_visibility_repeats": "Taaspostitused",
|
||||||
|
"notification_visibility_mentions": "Mainimised",
|
||||||
|
"notification_visibility_likes": "Lemmikud",
|
||||||
|
"notification_visibility_follows": "Jälgimised",
|
||||||
|
"notification_visibility": "Milliseid teateid kuvatakse",
|
||||||
|
"new_password": "Uus salasõna",
|
||||||
|
"new_email": "Uus e-post",
|
||||||
|
"use_contain_fit": "Näita eelvaadetes täis suuruses pilte",
|
||||||
|
"play_videos_in_modal": "Näita videoid eraldi raamis",
|
||||||
|
"mutes_tab": "Vaigistused",
|
||||||
|
"loop_video_silent_only": "Loop videod, millel pole heli (nt. Mastodoni \"gifid\")",
|
||||||
|
"loop_video": "Loop videod",
|
||||||
|
"lock_account_description": "Piira oma konto ainult lubatud jälgijatele",
|
||||||
|
"links": "Lingid",
|
||||||
|
"limited_availability": "Pole Teie veebilehitsejas saadaval",
|
||||||
|
"invalid_theme_imported": "Valitud fail ei ole Pleroma kujundus. Kujundusele muudatusi ei tehtud.",
|
||||||
|
"interfaceLanguage": "Liidese keel",
|
||||||
|
"interface": "Liides",
|
||||||
|
"instance_default_simple": "(vaikimisi)",
|
||||||
|
"instance_default": "(vaikimisi: {value})",
|
||||||
|
"checkboxRadius": "Märkeruudud",
|
||||||
|
"inputRadius": "Sisestuskastid",
|
||||||
|
"import_theme": "Lae sätted",
|
||||||
|
"import_followers_from_a_csv_file": "Impordi jälgimised csv failist",
|
||||||
|
"import_blocks_from_a_csv_file": "Impordi blokeeringud csv failist",
|
||||||
|
"hide_filtered_statuses": "Peida filtreeritud staatused",
|
||||||
|
"hide_user_stats": "Peida kasutaja statistika (nt. jälgijate arv)",
|
||||||
|
"hide_post_stats": "Peida postituse statistika (nt. lemmikute arv)",
|
||||||
|
"use_one_click_nsfw": "Ava NSFW manused ühe klikiga",
|
||||||
|
"preload_images": "Piltide eellaadimine",
|
||||||
|
"hide_isp": "Peida instantsipõhine paneel",
|
||||||
|
"max_thumbnails": "Maksimaalne lubatud eelvaadete arv postituste kohta",
|
||||||
|
"hide_muted_posts": "Peida vaigistatud kasutajate postitused",
|
||||||
|
"general": "Üldine",
|
||||||
|
"foreground": "Esiplaan",
|
||||||
|
"accent": "Rõhk",
|
||||||
|
"follows_imported": "Jälgimised imporditud! Nende töötlemine võtab natuke aega.",
|
||||||
|
"follow_import_error": "Jälgimiste importimisel tekkis viga",
|
||||||
|
"follow_import": "Impordi jälgimised",
|
||||||
|
"follow_export_button": "Ekspordi oma jälgimised csv failiks",
|
||||||
|
"follow_export": "Ekspordi jälgimised",
|
||||||
|
"export_theme": "Salvesta sätted",
|
||||||
|
"emoji_reactions_on_timeline": "Näita reaktsioone ajajoonel",
|
||||||
|
"pad_emoji": "Lisa emotikonidele tühikud ette ja järgi neid menüüst valides",
|
||||||
|
"avatar_size_instruction": "Profiilipildi soovitatud minimaalne suurus on 150x150 pikslit.",
|
||||||
|
"domain_mutes": "Domeenid",
|
||||||
|
"discoverable": "Luba selle konto ilmumine otsingutulemustes ning muudes teenustes",
|
||||||
|
"delete_account_instructions": "Konto kustutamise kinnitamiseks sisestage oma salasõna.",
|
||||||
|
"delete_account_error": "Teie konto kustutamisel tekkis viga. Kui see jätkub, palun võtke kontakti administraatoriga.",
|
||||||
|
"delete_account_description": "Jäädavalt kustuta oma andmed ja konto.",
|
||||||
|
"delete_account": "Kustuta konto",
|
||||||
|
"default_vis": "Vaikimisi nähtavus",
|
||||||
|
"data_import_export_tab": "Andmete import / eksport",
|
||||||
|
"current_password": "Praegune salasõna",
|
||||||
|
"confirm_new_password": "Kinnita uus salasõna",
|
||||||
|
"composing": "Koostamine",
|
||||||
|
"collapse_subject": "Peida postituste pealkirjad",
|
||||||
|
"changed_password": "Salasõna edukalt muudetud!",
|
||||||
|
"change_password_error": "Esines viga salasõna muutmisel.",
|
||||||
|
"change_password": "Muuda salasõna",
|
||||||
|
"changed_email": "E-post edukalt muudetud!",
|
||||||
|
"change_email_error": "Esines viga e-posti muutmisel.",
|
||||||
|
"change_email": "Muuda e-posti",
|
||||||
|
"cRed": "Punane (Tühista)",
|
||||||
|
"cOrange": "Oranž (Lisa lemmikuks)",
|
||||||
|
"cGreen": "Roheline (Taaspostita)",
|
||||||
|
"cBlue": "Sinine (Vasta, jälgi)",
|
||||||
|
"btnRadius": "Nupud",
|
||||||
|
"blocks_tab": "Blokeeringud",
|
||||||
|
"blocks_imported": "Blokeeringud imporditud! Nende töötlemine võtab natuke aega.",
|
||||||
|
"block_import_error": "Blokeeringute importimisel esines viga",
|
||||||
|
"block_import": "Blokeeringute import",
|
||||||
|
"block_export_button": "Ekspordi oma blokeeringud csv failiks",
|
||||||
|
"block_export": "Blokeeringute eksport",
|
||||||
|
"background": "Taust",
|
||||||
|
"avatarRadius": "Profiilipildid",
|
||||||
|
"avatarAltRadius": "Profiilipildid (Teated)",
|
||||||
|
"attachmentRadius": "Manused",
|
||||||
|
"allow_following_move": "Luba automaatjälgimine kui jälgitav konto kolib",
|
||||||
|
"mfa": {
|
||||||
|
"verify": {
|
||||||
|
"desc": "Et lubada kaheastmelist autentimist, sisestage kood oma äpist:"
|
||||||
|
},
|
||||||
|
"scan": {
|
||||||
|
"desc": "Kasutades oma kaheastmelise autentimise äppi, skännige see QR kood või sisestage tekstiline võti:",
|
||||||
|
"secret_code": "Võti",
|
||||||
|
"title": "Skänni"
|
||||||
|
},
|
||||||
|
"authentication_methods": "Autentimismeetodid",
|
||||||
|
"recovery_codes_warning": "Kirjutage need koodid üles ning hoidke need kindlas kohas. Kui Te kaotate ligipääsu oma kaheastmelise autentimise äppile ning nendele koodidele, ei ole Teil võimalik oma kontosse sisse logida.",
|
||||||
|
"waiting_a_recovery_codes": "Laen taastekoode…",
|
||||||
|
"recovery_codes": "Taastekoodid.",
|
||||||
|
"warning_of_generate_new_codes": "Kui Te loote uued taastekoodid, Teie vanad koodid ei tööta enam.",
|
||||||
|
"generate_new_recovery_codes": "Loo uued taastekoodid",
|
||||||
|
"title": "Kaheastmeline autentimine",
|
||||||
|
"confirm_and_enable": "Kinnita & luba OTP",
|
||||||
|
"wait_pre_setup_otp": "sean üles OTP",
|
||||||
|
"setup_otp": "Sea üles OTP",
|
||||||
|
"otp": "OTP"
|
||||||
|
},
|
||||||
|
"enter_current_password_to_confirm": "Sisetage isiku tõestamiseks oma salasõna",
|
||||||
|
"security": "Turvalisus",
|
||||||
|
"app_name": "Rakenduse nimi",
|
||||||
|
"style": {
|
||||||
|
"switcher": {
|
||||||
|
"help": {
|
||||||
|
"snapshot_present": "Kujunduse eelvaade on laetud, nii et kõik väärtused on üle kirjutatud. Te saate laadida ka kujunduse päris sisu.",
|
||||||
|
"older_version_imported": "Teie imporditud fail oli loodud vanemas versioonis.",
|
||||||
|
"future_version_imported": "Teie imporditud fail oli loodud uuemas versioonis.",
|
||||||
|
"v2_imported": "Teie imporditud fail oli vanema versiooni jaoks. Me üritame hoida ühilduvust, kuid ikkagi võib esineda erinevusi.",
|
||||||
|
"upgraded_from_v2": "PleromaFE-d uuendati, teie kujundus võib välja näha natuke erinev, kui mäletate."
|
||||||
|
},
|
||||||
|
"use_source": "Uus versioon",
|
||||||
|
"use_snapshot": "Vana versioon",
|
||||||
|
"keep_as_is": "Jäta nii, nagu on",
|
||||||
|
"load_theme": "Lae kujundus",
|
||||||
|
"clear_opacity": "Tühista läbipaistvus",
|
||||||
|
"clear_all": "Tühista kõik",
|
||||||
|
"reset": "Taasta algne",
|
||||||
|
"keep_fonts": "Jäta fondid",
|
||||||
|
"keep_roundness": "Jäta ümarus",
|
||||||
|
"keep_opacity": "Jäta läbipaistvus",
|
||||||
|
"keep_shadows": "Jäta varjud",
|
||||||
|
"keep_color": "Jäta värvid"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"enable_web_push_notifications": "Luba veebipõhised push-teated",
|
||||||
|
"notification_blocks": "Kasutaja blokeerimisel ei tule neilt enam teateid ning nendele teilt ka mitte.",
|
||||||
|
"notification_setting_privacy_option": "Peida saatja ning sisu push-teadetelt",
|
||||||
|
"notification_setting": "Saa teateid nendelt:",
|
||||||
|
"notifications": "Teated",
|
||||||
|
"notification_mutes": "Kui soovid mõnelt kasutajalt mitte teateid saada, kasuta vaigistust.",
|
||||||
|
"notification_setting_privacy": "Privaatsus",
|
||||||
|
"notification_setting_non_followers": "Kasutajatelt, kes sind ei jälgi",
|
||||||
|
"notification_setting_followers": "Kasutajatelt, kes jälgivad sind",
|
||||||
|
"notification_setting_non_follows": "Kasutajatelt, keda sa ei jälgi",
|
||||||
|
"notification_setting_follows": "Kasutajatelt, keda jälgid",
|
||||||
|
"notification_setting_filters": "Filtrid",
|
||||||
|
"greentext": "Meemi nooled",
|
||||||
|
"fun": "Naljad",
|
||||||
|
"values": {
|
||||||
|
"true": "jah",
|
||||||
|
"false": "ei"
|
||||||
|
},
|
||||||
|
"upload_a_photo": "Lae üles foto",
|
||||||
|
"type_domains_to_mute": "Trüki siia domeene, mida vaigistada",
|
||||||
|
"tooltipRadius": "Vihjed/hoiatused",
|
||||||
|
"theme_help_v2_1": "Te saate ka mõndade komponentide värvust ning läbipaistvust üle kirjutada vajutades ruudule. Kasuta \"Tühista kõik\" nuppu, et need tühistada.",
|
||||||
|
"theme_help": "Kasuta hex värvikoode (#rrggbb) oma kujunduse isikupärastamiseks.",
|
||||||
|
"text": "Tekst",
|
||||||
|
"useStreamingApiWarning": "(Pole soovituslik, eksperimentaalne, on teada, et jätab postitusi vahele)",
|
||||||
|
"useStreamingApi": "Saa postitusi ning teateid reaalajas",
|
||||||
|
"user_mutes": "Kasutajad",
|
||||||
|
"streaming": "Luba uute postituste automaatvoog kui oled lehekülje alguses",
|
||||||
|
"stop_gifs": "Mängi GIFid hiirega ületades",
|
||||||
|
"post_status_content_type": "Postituse sisutüüp"
|
||||||
},
|
},
|
||||||
"timeline": {
|
"timeline": {
|
||||||
"conversation": "Vestlus",
|
"conversation": "Vestlus",
|
||||||
|
|
@ -79,5 +351,111 @@
|
||||||
"muted": "Vaigistatud",
|
"muted": "Vaigistatud",
|
||||||
"per_day": "päevas",
|
"per_day": "päevas",
|
||||||
"statuses": "Staatuseid"
|
"statuses": "Staatuseid"
|
||||||
|
},
|
||||||
|
"about": {
|
||||||
|
"mrf": {
|
||||||
|
"mrf_policies_desc": "MRF poliitikad mõjutavad selle instansi föderatsiooni käitumist. Järgmised poliitikad on lubatud:",
|
||||||
|
"simple": {
|
||||||
|
"media_nsfw_desc": "See instants määrab nendest instantsidest postituste meedia sensitiivseks:",
|
||||||
|
"media_nsfw": "Meedia määratakse sensitiivseks",
|
||||||
|
"media_removal_desc": "See instants eemaldab meedia postitustelt nendest instantsidest:",
|
||||||
|
"media_removal": "Meedia eemaldamine",
|
||||||
|
"ftl_removal_desc": "See instants eemaldab postitused nendelt instantsidest \"Kogu teatud võrgu\" ajajoonelt:",
|
||||||
|
"ftl_removal": "\"Kogu teatud võrgu\" ajajoonelt eemaldamine",
|
||||||
|
"quarantine_desc": "See instants saadab ainult avalikke postitusi järgmistele instantsidele:",
|
||||||
|
"quarantine": "Karantiini",
|
||||||
|
"reject_desc": "See instants ei luba sõnumeid nendest instantsidest:",
|
||||||
|
"reject": "Keela",
|
||||||
|
"accept_desc": "See instants lubab sõnumeid ainult nendest instantsidest:",
|
||||||
|
"accept": "Luba",
|
||||||
|
"simple_policies": "Instansi-omased poliitikad"
|
||||||
|
},
|
||||||
|
"mrf_policies": "Lubatud MRF poliitikad",
|
||||||
|
"keyword": {
|
||||||
|
"is_replaced_by": "→",
|
||||||
|
"replace": "Vaheta",
|
||||||
|
"reject": "Lükka tagasi",
|
||||||
|
"ftl_removal": "\"Kogu teatud võrgu\" ajajoonelt eemaldamine",
|
||||||
|
"keyword_policies": "Võtmesõna poliitikad"
|
||||||
|
},
|
||||||
|
"federation": "Föderatsioon"
|
||||||
|
},
|
||||||
|
"staff": "Personal"
|
||||||
|
},
|
||||||
|
"selectable_list": {
|
||||||
|
"select_all": "Vali kõik"
|
||||||
|
},
|
||||||
|
"remote_user_resolver": {
|
||||||
|
"error": "Ei leitud.",
|
||||||
|
"searching_for": "Otsin",
|
||||||
|
"remote_user_resolver": "Kaugkasutaja leidja"
|
||||||
|
},
|
||||||
|
"interactions": {
|
||||||
|
"load_older": "Laadi vanemad interaktsioonid",
|
||||||
|
"moves": "Kasutaja kolimised",
|
||||||
|
"follows": "Uued jälgimised",
|
||||||
|
"favs_repeats": "Taaspostitused ja lemmikud"
|
||||||
|
},
|
||||||
|
"emoji": {
|
||||||
|
"load_all": "Laen kõik {emojiAmount} emotikoni",
|
||||||
|
"load_all_hint": "Laadisin esimesed {saneAmount} emotikoni, kõike laadides võib esineda probleeme jõudlusega.",
|
||||||
|
"unicode": "Unicode emotikonid",
|
||||||
|
"custom": "Kohandatud emotikonid",
|
||||||
|
"add_emoji": "Lisa emotikon",
|
||||||
|
"search_emoji": "Otsi emotikone",
|
||||||
|
"keep_open": "Hoia valija lahti",
|
||||||
|
"emoji": "Emotikonid",
|
||||||
|
"stickers": "Kleepsud"
|
||||||
|
},
|
||||||
|
"polls": {
|
||||||
|
"not_enough_options": "Liiga vähe unikaalseid valikuid hääletuses",
|
||||||
|
"expired": "Hääletus lõppes {0} tagasi",
|
||||||
|
"expires_in": "Hääletus lõppeb {0}",
|
||||||
|
"expiry": "Hääletuse vanus",
|
||||||
|
"multiple_choices": "Mitu vastust",
|
||||||
|
"single_choice": "Üks vastus",
|
||||||
|
"type": "Hääletuse tüüp",
|
||||||
|
"vote": "Hääleta",
|
||||||
|
"votes": "häält",
|
||||||
|
"option": "Valik",
|
||||||
|
"add_option": "Lisa valik",
|
||||||
|
"add_poll": "Lisa küsitlus"
|
||||||
|
},
|
||||||
|
"media_modal": {
|
||||||
|
"next": "Järgmine",
|
||||||
|
"previous": "Eelmine"
|
||||||
|
},
|
||||||
|
"importer": {
|
||||||
|
"error": "Faili importimisel tekkis viga.",
|
||||||
|
"success": "Import õnnestus.",
|
||||||
|
"submit": "Esita"
|
||||||
|
},
|
||||||
|
"image_cropper": {
|
||||||
|
"cancel": "Tühista",
|
||||||
|
"save_without_cropping": "Salvesta muudatusteta",
|
||||||
|
"save": "Salvesta",
|
||||||
|
"crop_picture": "Modifitseeri pilti"
|
||||||
|
},
|
||||||
|
"features_panel": {
|
||||||
|
"who_to_follow": "Keda jälgida",
|
||||||
|
"title": "Featuurid",
|
||||||
|
"text_limit": "Tekstilimiit",
|
||||||
|
"scope_options": "Ulatuse valikud",
|
||||||
|
"media_proxy": "Meedia proksi",
|
||||||
|
"gopher": "Gopher",
|
||||||
|
"chat": "Vestlus"
|
||||||
|
},
|
||||||
|
"exporter": {
|
||||||
|
"processing": "Töötlemine, Teilt küsitakse varsti faili allalaadimist",
|
||||||
|
"export": "Ekspordi"
|
||||||
|
},
|
||||||
|
"domain_mute_card": {
|
||||||
|
"unmute_progress": "Eemaldan vaigistuse…",
|
||||||
|
"unmute": "Ära vaigista",
|
||||||
|
"mute_progress": "Vaigistan…",
|
||||||
|
"mute": "Vaigista"
|
||||||
|
},
|
||||||
|
"chat": {
|
||||||
|
"title": "Vestlus"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,8 @@
|
||||||
"disable": "Désactiver",
|
"disable": "Désactiver",
|
||||||
"enable": "Activer",
|
"enable": "Activer",
|
||||||
"confirm": "Confirmer",
|
"confirm": "Confirmer",
|
||||||
"verify": "Vérifier"
|
"verify": "Vérifier",
|
||||||
|
"dismiss": "Rejeter"
|
||||||
},
|
},
|
||||||
"image_cropper": {
|
"image_cropper": {
|
||||||
"crop_picture": "Rogner l'image",
|
"crop_picture": "Rogner l'image",
|
||||||
|
|
@ -167,7 +168,7 @@
|
||||||
"generate_new_recovery_codes": "Générer de nouveaux codes de récupération",
|
"generate_new_recovery_codes": "Générer de nouveaux codes de récupération",
|
||||||
"warning_of_generate_new_codes": "Quand vous générez de nouveauc codes de récupération, vos anciens codes ne fonctionnerons plus.",
|
"warning_of_generate_new_codes": "Quand vous générez de nouveauc codes de récupération, vos anciens codes ne fonctionnerons plus.",
|
||||||
"recovery_codes": "Codes de récupération.",
|
"recovery_codes": "Codes de récupération.",
|
||||||
"waiting_a_recovery_codes": "Récéption des codes de récupération…",
|
"waiting_a_recovery_codes": "Réception des codes de récupération…",
|
||||||
"recovery_codes_warning": "Écrivez les codes ou sauvez les quelquepart sécurisé - sinon vous ne les verrez plus jamais. Si vous perdez l'accès à votre application de double authentification et codes de récupération vous serez vérouillé en dehors de votre compte.",
|
"recovery_codes_warning": "Écrivez les codes ou sauvez les quelquepart sécurisé - sinon vous ne les verrez plus jamais. Si vous perdez l'accès à votre application de double authentification et codes de récupération vous serez vérouillé en dehors de votre compte.",
|
||||||
"authentication_methods": "Methodes d'authentification",
|
"authentication_methods": "Methodes d'authentification",
|
||||||
"scan": {
|
"scan": {
|
||||||
|
|
@ -210,7 +211,7 @@
|
||||||
"data_import_export_tab": "Import / Export des Données",
|
"data_import_export_tab": "Import / Export des Données",
|
||||||
"default_vis": "Visibilité par défaut",
|
"default_vis": "Visibilité par défaut",
|
||||||
"delete_account": "Supprimer le compte",
|
"delete_account": "Supprimer le compte",
|
||||||
"delete_account_description": "Supprimer définitivement votre compte et tous vos statuts.",
|
"delete_account_description": "Supprimer définitivement vos données et désactiver votre compte.",
|
||||||
"delete_account_error": "Il y a eu un problème lors de la tentative de suppression de votre compte. Si le problème persiste, contactez l'administrateur⋅ice de cette instance.",
|
"delete_account_error": "Il y a eu un problème lors de la tentative de suppression de votre compte. Si le problème persiste, contactez l'administrateur⋅ice de cette instance.",
|
||||||
"delete_account_instructions": "Indiquez votre mot de passe ci-dessous pour confirmer la suppression de votre compte.",
|
"delete_account_instructions": "Indiquez votre mot de passe ci-dessous pour confirmer la suppression de votre compte.",
|
||||||
"avatar_size_instruction": "La taille minimale recommandée pour l'image de l'avatar est de 150x150 pixels.",
|
"avatar_size_instruction": "La taille minimale recommandée pour l'image de l'avatar est de 150x150 pixels.",
|
||||||
|
|
@ -343,7 +344,13 @@
|
||||||
"upgraded_from_v2": "PleromaFE à été mis à jour, le thème peut être un peu différent que dans vos souvenirs.",
|
"upgraded_from_v2": "PleromaFE à été mis à jour, le thème peut être un peu différent que dans vos souvenirs.",
|
||||||
"v2_imported": "Le fichier que vous avez importé vient d'un version antérieure. Nous essayons de maximizer la compatibilité mais il peu y avoir quelques incohérences.",
|
"v2_imported": "Le fichier que vous avez importé vient d'un version antérieure. Nous essayons de maximizer la compatibilité mais il peu y avoir quelques incohérences.",
|
||||||
"future_version_imported": "Le fichier importé viens d'une version postérieure de PleromaFE.",
|
"future_version_imported": "Le fichier importé viens d'une version postérieure de PleromaFE.",
|
||||||
"older_version_imported": "Le fichier importé viens d'une version antérieure de PleromaFE."
|
"older_version_imported": "Le fichier importé viens d'une version antérieure de PleromaFE.",
|
||||||
|
"snapshot_source_mismatch": "Conflict de version : Probablement due à un retour arrière puis remise à jour de la version de PleromaFE, si vous avez charger le thème en utilisant une version antérieure vous voulez probablement utiliser la version antérieure, autrement utiliser la version postérieure.",
|
||||||
|
"migration_napshot_gone": "Pour une raison inconnue l'instantané est manquant, des parties peuvent rendre différentes que dans vos souvenirs.",
|
||||||
|
"migration_snapshot_ok": "Pour être sûr un instantanée du thème à été chargé. Vos pouvez essayer de charger ses données.",
|
||||||
|
"fe_downgraded": "Retour en arrière de la version de PleromaFE.",
|
||||||
|
"fe_upgraded": "Le moteur de thème PleromaFE à été mis à jour après un changement de version.",
|
||||||
|
"snapshot_missing": "Aucun instantané du thème à été trouvé dans le fichier, il peut y avoir un rendu différent à la vision originelle."
|
||||||
},
|
},
|
||||||
"keep_as_is": "Garder tel-quel",
|
"keep_as_is": "Garder tel-quel",
|
||||||
"use_source": "Nouvelle version"
|
"use_source": "Nouvelle version"
|
||||||
|
|
@ -392,7 +399,10 @@
|
||||||
"selectedPost": "Message sélectionné",
|
"selectedPost": "Message sélectionné",
|
||||||
"selectedMenu": "Objet sélectionné du menu",
|
"selectedMenu": "Objet sélectionné du menu",
|
||||||
"disabled": "Désactivé",
|
"disabled": "Désactivé",
|
||||||
"tabs": "Onglets"
|
"tabs": "Onglets",
|
||||||
|
"toggled": "(Dés)activé",
|
||||||
|
"highlight": "Éléments mis en valeur",
|
||||||
|
"popover": "Infobulles, menus"
|
||||||
},
|
},
|
||||||
"radii": {
|
"radii": {
|
||||||
"_tab_label": "Rondeur"
|
"_tab_label": "Rondeur"
|
||||||
|
|
@ -482,7 +492,9 @@
|
||||||
"useStreamingApi": "Recevoir les messages et notifications en temps réel",
|
"useStreamingApi": "Recevoir les messages et notifications en temps réel",
|
||||||
"notification_setting_filters": "Filtres",
|
"notification_setting_filters": "Filtres",
|
||||||
"notification_setting_privacy_option": "Masquer l'expéditeur et le contenu des notifications push",
|
"notification_setting_privacy_option": "Masquer l'expéditeur et le contenu des notifications push",
|
||||||
"notification_setting_privacy": "Intimité"
|
"notification_setting_privacy": "Intimité",
|
||||||
|
"hide_followers_count_description": "Masquer le nombre d'abonnés",
|
||||||
|
"accent": "Accent"
|
||||||
},
|
},
|
||||||
"timeline": {
|
"timeline": {
|
||||||
"collapse": "Fermer",
|
"collapse": "Fermer",
|
||||||
|
|
@ -666,10 +678,13 @@
|
||||||
"unicode": "émoji unicode",
|
"unicode": "émoji unicode",
|
||||||
"load_all": "Charger tout les {emojiAmount} émojis",
|
"load_all": "Charger tout les {emojiAmount} émojis",
|
||||||
"load_all_hint": "{saneAmount} émojis chargé, charger tout les émojis peuvent causer des problèmes de performances.",
|
"load_all_hint": "{saneAmount} émojis chargé, charger tout les émojis peuvent causer des problèmes de performances.",
|
||||||
"stickers": "Stickers"
|
"stickers": "Stickers",
|
||||||
|
"keep_open": "Garder le sélecteur ouvert"
|
||||||
},
|
},
|
||||||
"remote_user_resolver": {
|
"remote_user_resolver": {
|
||||||
"error": "Non trouvé."
|
"error": "Non trouvé.",
|
||||||
|
"searching_for": "Rechercher",
|
||||||
|
"remote_user_resolver": "Résolution de compte distant"
|
||||||
},
|
},
|
||||||
"time": {
|
"time": {
|
||||||
"minutes_short": "{0}min",
|
"minutes_short": "{0}min",
|
||||||
|
|
|
||||||
279
src/i18n/it.json
279
src/i18n/it.json
|
|
@ -12,7 +12,12 @@
|
||||||
"disable": "Disabilita",
|
"disable": "Disabilita",
|
||||||
"enable": "Abilita",
|
"enable": "Abilita",
|
||||||
"confirm": "Conferma",
|
"confirm": "Conferma",
|
||||||
"verify": "Verifica"
|
"verify": "Verifica",
|
||||||
|
"peek": "Anteprima",
|
||||||
|
"close": "Chiudi",
|
||||||
|
"retry": "Riprova",
|
||||||
|
"error_retry": "Per favore, riprova",
|
||||||
|
"loading": "Carico…"
|
||||||
},
|
},
|
||||||
"nav": {
|
"nav": {
|
||||||
"mentions": "Menzioni",
|
"mentions": "Menzioni",
|
||||||
|
|
@ -20,16 +25,29 @@
|
||||||
"timeline": "Sequenza personale",
|
"timeline": "Sequenza personale",
|
||||||
"twkn": "Sequenza globale",
|
"twkn": "Sequenza globale",
|
||||||
"chat": "Chat della stanza",
|
"chat": "Chat della stanza",
|
||||||
"friend_requests": "Vogliono seguirti"
|
"friend_requests": "Vogliono seguirti",
|
||||||
|
"about": "Informazioni",
|
||||||
|
"administration": "Amministrazione",
|
||||||
|
"back": "Indietro",
|
||||||
|
"interactions": "Interazioni",
|
||||||
|
"dms": "Messaggi diretti",
|
||||||
|
"user_search": "Ricerca utenti",
|
||||||
|
"search": "Ricerca",
|
||||||
|
"who_to_follow": "Chi seguire",
|
||||||
|
"preferences": "Preferenze"
|
||||||
},
|
},
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"followed_you": "ti segue",
|
"followed_you": "ti segue",
|
||||||
"notifications": "Notifiche",
|
"notifications": "Notifiche",
|
||||||
"read": "Letto!",
|
"read": "Letto!",
|
||||||
"broken_favorite": "Stato sconosciuto, lo sto cercando...",
|
"broken_favorite": "Stato sconosciuto, lo sto cercando…",
|
||||||
"favorited_you": "ha gradito il tuo messaggio",
|
"favorited_you": "ha gradito il tuo messaggio",
|
||||||
"load_older": "Carica notifiche precedenti",
|
"load_older": "Carica notifiche precedenti",
|
||||||
"repeated_you": "ha condiviso il tuo messaggio"
|
"repeated_you": "ha condiviso il tuo messaggio",
|
||||||
|
"follow_request": "vuole seguirti",
|
||||||
|
"no_more_notifications": "Fine delle notifiche",
|
||||||
|
"migrated_to": "è migrato verso",
|
||||||
|
"reacted_with": "ha reagito con {0}"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"attachments": "Allegati",
|
"attachments": "Allegati",
|
||||||
|
|
@ -44,7 +62,7 @@
|
||||||
"hide_attachments_in_tl": "Nascondi gli allegati presenti nelle sequenze",
|
"hide_attachments_in_tl": "Nascondi gli allegati presenti nelle sequenze",
|
||||||
"name": "Nome",
|
"name": "Nome",
|
||||||
"name_bio": "Nome ed introduzione",
|
"name_bio": "Nome ed introduzione",
|
||||||
"nsfw_clickthrough": "Fai click per visualizzare gli allegati nascosti",
|
"nsfw_clickthrough": "Fai click per visualizzare gli allegati offuscati",
|
||||||
"profile_background": "Sfondo della tua pagina",
|
"profile_background": "Sfondo della tua pagina",
|
||||||
"profile_banner": "Stendardo del tuo profilo",
|
"profile_banner": "Stendardo del tuo profilo",
|
||||||
"reply_link_preview": "Visualizza le risposte al passaggio del cursore",
|
"reply_link_preview": "Visualizza le risposte al passaggio del cursore",
|
||||||
|
|
@ -72,7 +90,7 @@
|
||||||
"data_import_export_tab": "Importa o esporta dati",
|
"data_import_export_tab": "Importa o esporta dati",
|
||||||
"default_vis": "Visibilità predefinita dei messaggi",
|
"default_vis": "Visibilità predefinita dei messaggi",
|
||||||
"delete_account": "Elimina profilo",
|
"delete_account": "Elimina profilo",
|
||||||
"delete_account_description": "Elimina definitivamente il tuo profilo e tutti i tuoi messaggi.",
|
"delete_account_description": "Elimina definitivamente i tuoi dati e disattiva il tuo profilo.",
|
||||||
"delete_account_error": "C'è stato un problema durante l'eliminazione del tuo profilo. Se il problema persiste contatta l'amministratore della tua stanza.",
|
"delete_account_error": "C'è stato un problema durante l'eliminazione del tuo profilo. Se il problema persiste contatta l'amministratore della tua stanza.",
|
||||||
"delete_account_instructions": "Digita la tua password nel campo sottostante per confermare l'eliminazione del tuo profilo.",
|
"delete_account_instructions": "Digita la tua password nel campo sottostante per confermare l'eliminazione del tuo profilo.",
|
||||||
"export_theme": "Salva impostazioni",
|
"export_theme": "Salva impostazioni",
|
||||||
|
|
@ -125,12 +143,171 @@
|
||||||
"streaming": "Mostra automaticamente i nuovi messaggi quando sei in cima alla pagina",
|
"streaming": "Mostra automaticamente i nuovi messaggi quando sei in cima alla pagina",
|
||||||
"text": "Testo",
|
"text": "Testo",
|
||||||
"theme_help": "Usa codici colore esadecimali (#rrggbb) per personalizzare il tuo schema di colori.",
|
"theme_help": "Usa codici colore esadecimali (#rrggbb) per personalizzare il tuo schema di colori.",
|
||||||
"tooltipRadius": "Descrizioni/avvisi",
|
"tooltipRadius": "Suggerimenti/avvisi",
|
||||||
"values": {
|
"values": {
|
||||||
"false": "no",
|
"false": "no",
|
||||||
"true": "sì"
|
"true": "sì"
|
||||||
|
},
|
||||||
|
"avatar_size_instruction": "La taglia minima per l'icona personale è 150x150 pixel.",
|
||||||
|
"domain_mutes": "Domini",
|
||||||
|
"discoverable": "Permetti la scoperta di questo profilo da servizi di ricerca ed altro",
|
||||||
|
"composing": "Composizione",
|
||||||
|
"changed_email": "Email cambiata con successo!",
|
||||||
|
"change_email_error": "C'è stato un problema nel cambiare la tua email.",
|
||||||
|
"change_email": "Cambia email",
|
||||||
|
"blocks_tab": "Bloccati",
|
||||||
|
"blocks_imported": "Blocchi importati! Saranno elaborati a breve.",
|
||||||
|
"block_import_error": "Errore nell'importazione",
|
||||||
|
"block_import": "Importa blocchi",
|
||||||
|
"block_export_button": "Esporta i tuoi blocchi in un file CSV",
|
||||||
|
"block_export": "Esporta blocchi",
|
||||||
|
"allow_following_move": "Consenti",
|
||||||
|
"mfa": {
|
||||||
|
"verify": {
|
||||||
|
"desc": "Per abilitare l'autenticazione bifattoriale, inserisci il codice fornito dalla tua applicazione:"
|
||||||
|
},
|
||||||
|
"scan": {
|
||||||
|
"secret_code": "Codice",
|
||||||
|
"desc": "Con la tua applicazione bifattoriale, acquisisci questo QR o inserisci il codice manualmente:",
|
||||||
|
"title": "Acquisisci"
|
||||||
|
},
|
||||||
|
"authentication_methods": "Metodi di accesso",
|
||||||
|
"recovery_codes_warning": "Appuntati i codici o salvali in un posto sicuro, altrimenti rischi di non rivederli mai più. Se perderai l'accesso sia alla tua applicazione bifattoriale che ai codici di recupero non potrai più accedere al tuo profilo.",
|
||||||
|
"waiting_a_recovery_codes": "Ricevo codici di recupero…",
|
||||||
|
"recovery_codes": "Codici di recupero.",
|
||||||
|
"warning_of_generate_new_codes": "Alla generazione di nuovi codici di recupero, quelli vecchi saranno disattivati.",
|
||||||
|
"generate_new_recovery_codes": "Genera nuovi codici di recupero",
|
||||||
|
"title": "Accesso bifattoriale",
|
||||||
|
"confirm_and_enable": "Conferma ed abilita OTP",
|
||||||
|
"wait_pre_setup_otp": "preimposto OTP",
|
||||||
|
"setup_otp": "Imposta OTP",
|
||||||
|
"otp": "OTP"
|
||||||
|
},
|
||||||
|
"enter_current_password_to_confirm": "Inserisci la tua password per identificarti",
|
||||||
|
"security": "Sicurezza",
|
||||||
|
"app_name": "Nome applicazione",
|
||||||
|
"style": {
|
||||||
|
"switcher": {
|
||||||
|
"help": {
|
||||||
|
"older_version_imported": "Il tema importato è stato creato per una versione precedente dell'interfaccia.",
|
||||||
|
"future_version_imported": "Il tema importato è stato creato per una versione più recente dell'interfaccia.",
|
||||||
|
"v2_imported": "Il tema importato è stato creato per una vecchia interfaccia. Non tutto potrebbe essere come prima.",
|
||||||
|
"upgraded_from_v2": "L'interfaccia è stata aggiornata, il tema potrebbe essere diverso da come lo intendevi.",
|
||||||
|
"migration_snapshot_ok": "Ho caricato l'anteprima del tema. Puoi provare a caricarne i contenuti.",
|
||||||
|
"fe_downgraded": "L'interfaccia è stata portata ad una versione precedente.",
|
||||||
|
"fe_upgraded": "Lo schema dei temi è stato aggiornato insieme all'interfaccia.",
|
||||||
|
"snapshot_missing": "Il tema non è provvisto di anteprima, quindi potrebbe essere diverso da come appare.",
|
||||||
|
"snapshot_present": "Tutti i valori sono sostituiti dall'anteprima del tema. Puoi invece caricare i suoi contenuti.",
|
||||||
|
"snapshot_source_mismatch": "Conflitto di versione: probabilmente l'interfaccia è stata portata ad una versione precedente e poi aggiornata di nuovo. Se hai modificato il tema con una versione precedente dell'interfaccia, usa la vecchia versione del tema, altrimenti puoi usare la nuova.",
|
||||||
|
"migration_napshot_gone": "Anteprima del tema non trovata, non tutto potrebbe essere come ricordi."
|
||||||
|
},
|
||||||
|
"use_source": "Nuova versione",
|
||||||
|
"use_snapshot": "Versione precedente",
|
||||||
|
"keep_as_is": "Mantieni tal quale",
|
||||||
|
"load_theme": "Carica tema",
|
||||||
|
"clear_opacity": "Rimuovi opacità",
|
||||||
|
"clear_all": "Azzera tutto",
|
||||||
|
"reset": "Reimposta",
|
||||||
|
"save_load_hint": "Le opzioni \"mantieni\" conservano le impostazioni correnti quando selezioni o carichi un tema, e le salvano quando ne esporti uno. Quando nessuna casella è selezionata, tutte le impostazioni correnti saranno salvate nel tema.",
|
||||||
|
"keep_fonts": "Mantieni font",
|
||||||
|
"keep_roundness": "Mantieni vertici",
|
||||||
|
"keep_opacity": "Mantieni opacità",
|
||||||
|
"keep_shadows": "Mantieni ombre",
|
||||||
|
"keep_color": "Mantieni colori"
|
||||||
|
},
|
||||||
|
"common": {
|
||||||
|
"opacity": "Opacità",
|
||||||
|
"color": "Colore",
|
||||||
|
"contrast": {
|
||||||
|
"context": {
|
||||||
|
"text": "per il testo",
|
||||||
|
"18pt": "per il testo grande (oltre 17pt)"
|
||||||
|
},
|
||||||
|
"level": {
|
||||||
|
"bad": "non soddisfa le linee guida di alcun livello",
|
||||||
|
"aaa": "soddisfa le linee guida di livello AAA (ottimo)",
|
||||||
|
"aa": "soddisfa le linee guida di livello AA (sufficiente)"
|
||||||
|
},
|
||||||
|
"hint": "Il rapporto di contrasto è {ratio}, e {level} {context}"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"advanced_colors": {
|
||||||
|
"badge": "Sfondo medaglie",
|
||||||
|
"post": "Messaggi / Biografie",
|
||||||
|
"alert_neutral": "Neutro",
|
||||||
|
"alert_warning": "Attenzione",
|
||||||
|
"alert_error": "Errore",
|
||||||
|
"alert": "Sfondo degli avvertimenti",
|
||||||
|
"_tab_label": "Avanzate"
|
||||||
|
},
|
||||||
|
"common_colors": {
|
||||||
|
"rgbo": "Icone, accenti, medaglie",
|
||||||
|
"foreground_hint": "Seleziona l'etichetta \"Avanzate\" per controlli più fini",
|
||||||
|
"main": "Colori comuni",
|
||||||
|
"_tab_label": "Comuni"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"enable_web_push_notifications": "Abilita notifiche web push",
|
||||||
|
"fun": "Divertimento",
|
||||||
|
"notification_mutes": "Per non ricevere notifiche da uno specifico utente, zittiscilo.",
|
||||||
|
"notification_setting_privacy_option": "Nascondi mittente e contenuti delle notifiche push",
|
||||||
|
"notification_setting_privacy": "Privacy",
|
||||||
|
"notification_setting_followers": "Utenti che ti seguono",
|
||||||
|
"notification_setting_non_followers": "Utenti che non ti seguono",
|
||||||
|
"notification_setting_non_follows": "Utenti che non segui",
|
||||||
|
"notification_setting_follows": "Utenti che segui",
|
||||||
|
"notification_setting": "Ricevi notifiche da:",
|
||||||
|
"notification_setting_filters": "Filtri",
|
||||||
|
"notifications": "Notifiche",
|
||||||
|
"greentext": "Frecce da meme",
|
||||||
|
"upload_a_photo": "Carica un'immagine",
|
||||||
|
"type_domains_to_mute": "Inserisci domini da zittire",
|
||||||
|
"theme_help_v2_2": "Le icone dietro alcuni elementi sono indicatori del contrasto fra testo e sfondo, passaci sopra col puntatore per ulteriori informazioni. Se si usano delle trasparenze, questi indicatori mostrano il peggior caso possibile.",
|
||||||
|
"theme_help_v2_1": "Puoi anche forzare colore ed opacità di alcuni elementi selezionando la casella. Usa il pulsante \"Azzera\" per azzerare tutte le forzature.",
|
||||||
|
"useStreamingApiWarning": "(Sconsigliato, sperimentale, può saltare messaggi)",
|
||||||
|
"useStreamingApi": "Ricevi messaggi e notifiche in tempo reale",
|
||||||
|
"user_mutes": "Utenti",
|
||||||
|
"post_status_content_type": "Tipo di contenuto dei messaggi",
|
||||||
|
"subject_line_noop": "Non copiare",
|
||||||
|
"subject_line_mastodon": "Come in Mastodon: copia tal quale",
|
||||||
|
"subject_line_email": "Come nelle email: \"re: oggetto\"",
|
||||||
|
"subject_line_behavior": "Copia oggetto quando rispondi",
|
||||||
|
"subject_input_always_show": "Mostra sempre il campo Oggetto",
|
||||||
|
"minimal_scopes_mode": "Riduci opzioni di visibilità",
|
||||||
|
"scope_copy": "Risposte ereditano la visibilità (messaggi privati lo fanno sempre)",
|
||||||
|
"search_user_to_mute": "Cerca utente da zittire",
|
||||||
|
"search_user_to_block": "Cerca utente da bloccare",
|
||||||
|
"autohide_floating_post_button": "Nascondi automaticamente il pulsante di composizione (mobile)",
|
||||||
|
"show_moderator_badge": "Mostra l'insegna di moderatore sulla mia pagina",
|
||||||
|
"show_admin_badge": "Mostra l'insegna di amministratore sulla mia pagina",
|
||||||
|
"hide_followers_count_description": "Non mostrare quanti seguaci ho",
|
||||||
|
"hide_follows_count_description": "Non mostrare quanti utenti seguo",
|
||||||
|
"hide_followers_description": "Non mostrare i miei seguaci",
|
||||||
|
"hide_follows_description": "Non mostrare chi seguo",
|
||||||
|
"no_mutes": "Nessun utente zittito",
|
||||||
|
"no_blocks": "Nessun utente bloccato",
|
||||||
|
"notification_visibility_emoji_reactions": "Reazioni",
|
||||||
|
"notification_visibility_moves": "Migrazioni utenti",
|
||||||
|
"new_email": "Nuova email",
|
||||||
|
"use_contain_fit": "Non ritagliare le anteprime degli allegati",
|
||||||
|
"play_videos_in_modal": "Riproduci video in un riquadro a sbalzo",
|
||||||
|
"mutes_tab": "Zittiti",
|
||||||
|
"interface": "Interfaccia",
|
||||||
|
"instance_default_simple": "(predefinito)",
|
||||||
|
"checkboxRadius": "Caselle di selezione",
|
||||||
|
"import_blocks_from_a_csv_file": "Importa blocchi da un file CSV",
|
||||||
|
"hide_filtered_statuses": "Nascondi messaggi filtrati",
|
||||||
|
"use_one_click_nsfw": "Apri media offuscati con un solo click",
|
||||||
|
"preload_images": "Precarica immagini",
|
||||||
|
"hide_isp": "Nascondi pannello della stanza",
|
||||||
|
"max_thumbnails": "Numero massimo di anteprime per messaggio",
|
||||||
|
"hide_muted_posts": "Nascondi messaggi degli utenti zittiti",
|
||||||
|
"accent": "Accento",
|
||||||
|
"emoji_reactions_on_timeline": "Mostra emoji di reazione sulle sequenze",
|
||||||
|
"pad_emoji": "Affianca spazi agli emoji inseriti tramite selettore",
|
||||||
|
"notification_blocks": "Bloccando un utente non riceverai più le sue notifiche né lo seguirai più.",
|
||||||
|
"mutes_and_blocks": "Zittiti e bloccati"
|
||||||
|
},
|
||||||
"timeline": {
|
"timeline": {
|
||||||
"error_fetching": "Errore nell'aggiornamento",
|
"error_fetching": "Errore nell'aggiornamento",
|
||||||
"load_older": "Carica messaggi più vecchi",
|
"load_older": "Carica messaggi più vecchi",
|
||||||
|
|
@ -180,14 +357,26 @@
|
||||||
"placeholder": "es. Lupo Lucio",
|
"placeholder": "es. Lupo Lucio",
|
||||||
"register": "Registrati",
|
"register": "Registrati",
|
||||||
"username": "Nome utente",
|
"username": "Nome utente",
|
||||||
"description": "Accedi con OAuth"
|
"description": "Accedi con OAuth",
|
||||||
|
"hint": "Accedi per partecipare alla discussione",
|
||||||
|
"authentication_code": "Codice di autenticazione",
|
||||||
|
"enter_recovery_code": "Inserisci un codice di recupero",
|
||||||
|
"enter_two_factor_code": "Inserisci un codice two-factor",
|
||||||
|
"recovery_code": "Codice di recupero",
|
||||||
|
"heading": {
|
||||||
|
"totp": "Autenticazione two-factor",
|
||||||
|
"recovery": "Recupero two-factor"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"post_status": {
|
"post_status": {
|
||||||
"account_not_locked_warning": "Il tuo profilo non è {0}. Chiunque può seguirti e vedere i tuoi messaggi riservati ai tuoi seguaci.",
|
"account_not_locked_warning": "Il tuo profilo non è {0}. Chiunque può seguirti e vedere i tuoi messaggi riservati ai tuoi seguaci.",
|
||||||
"account_not_locked_warning_link": "protetto",
|
"account_not_locked_warning_link": "protetto",
|
||||||
"attachments_sensitive": "Nascondi gli allegati",
|
"attachments_sensitive": "Nascondi gli allegati",
|
||||||
"content_type": {
|
"content_type": {
|
||||||
"text/plain": "Testo normale"
|
"text/plain": "Testo normale",
|
||||||
|
"text/bbcode": "BBCode",
|
||||||
|
"text/markdown": "Markdown",
|
||||||
|
"text/html": "HTML"
|
||||||
},
|
},
|
||||||
"content_warning": "Oggetto (facoltativo)",
|
"content_warning": "Oggetto (facoltativo)",
|
||||||
"default": "Sono appena atterrato a Fiumicino.",
|
"default": "Sono appena atterrato a Fiumicino.",
|
||||||
|
|
@ -198,7 +387,15 @@
|
||||||
"private": "Solo per seguaci - Visibile solo dai tuoi seguaci",
|
"private": "Solo per seguaci - Visibile solo dai tuoi seguaci",
|
||||||
"public": "Pubblico - Visibile sulla sequenza pubblica",
|
"public": "Pubblico - Visibile sulla sequenza pubblica",
|
||||||
"unlisted": "Non elencato - Non visibile sulla sequenza pubblica"
|
"unlisted": "Non elencato - Non visibile sulla sequenza pubblica"
|
||||||
}
|
},
|
||||||
|
"scope_notice": {
|
||||||
|
"unlisted": "Questo messaggio non sarà visibile sulla sequenza locale né su quella pubblica",
|
||||||
|
"private": "Questo messaggio sarà visibile solo ai tuoi seguaci",
|
||||||
|
"public": "Questo messaggio sarà visibile a tutti"
|
||||||
|
},
|
||||||
|
"direct_warning_to_first_only": "Questo messaggio sarà visibile solo agli utenti menzionati all'inizio.",
|
||||||
|
"direct_warning_to_all": "Questo messaggio sarà visibile a tutti i menzionati.",
|
||||||
|
"new_status": "Nuovo messaggio"
|
||||||
},
|
},
|
||||||
"registration": {
|
"registration": {
|
||||||
"bio": "Introduzione",
|
"bio": "Introduzione",
|
||||||
|
|
@ -206,7 +403,20 @@
|
||||||
"fullname": "Nome visualizzato",
|
"fullname": "Nome visualizzato",
|
||||||
"password_confirm": "Conferma password",
|
"password_confirm": "Conferma password",
|
||||||
"registration": "Registrazione",
|
"registration": "Registrazione",
|
||||||
"token": "Codice d'invito"
|
"token": "Codice d'invito",
|
||||||
|
"validations": {
|
||||||
|
"password_confirmation_match": "dovrebbe essere uguale alla password",
|
||||||
|
"password_confirmation_required": "non può essere vuoto",
|
||||||
|
"password_required": "non può essere vuoto",
|
||||||
|
"email_required": "non può essere vuoto",
|
||||||
|
"fullname_required": "non può essere vuoto",
|
||||||
|
"username_required": "non può essere vuoto"
|
||||||
|
},
|
||||||
|
"bio_placeholder": "es.\nCiao, sono Lupo Lucio.\nSono un lupo fantastico che vive nel Fantabosco. Forse mi hai visto alla Melevisione.",
|
||||||
|
"fullname_placeholder": "es. Lupo Lucio",
|
||||||
|
"username_placeholder": "es. mister_wolf",
|
||||||
|
"new_captcha": "Clicca l'immagine per avere un altro captcha",
|
||||||
|
"captcha": "CAPTCHA"
|
||||||
},
|
},
|
||||||
"user_profile": {
|
"user_profile": {
|
||||||
"timeline_title": "Sequenza dell'Utente"
|
"timeline_title": "Sequenza dell'Utente"
|
||||||
|
|
@ -247,9 +457,9 @@
|
||||||
},
|
},
|
||||||
"domain_mute_card": {
|
"domain_mute_card": {
|
||||||
"mute": "Zittisci",
|
"mute": "Zittisci",
|
||||||
"mute_progress": "Zittisco...",
|
"mute_progress": "Zittisco…",
|
||||||
"unmute": "Ascolta",
|
"unmute": "Ascolta",
|
||||||
"unmute_progress": "Procedo..."
|
"unmute_progress": "Procedo…"
|
||||||
},
|
},
|
||||||
"exporter": {
|
"exporter": {
|
||||||
"export": "Esporta",
|
"export": "Esporta",
|
||||||
|
|
@ -265,5 +475,48 @@
|
||||||
"submit": "Invia",
|
"submit": "Invia",
|
||||||
"success": "Importato.",
|
"success": "Importato.",
|
||||||
"error": "L'importazione non è andata a buon fine."
|
"error": "L'importazione non è andata a buon fine."
|
||||||
|
},
|
||||||
|
"media_modal": {
|
||||||
|
"previous": "Precedente",
|
||||||
|
"next": "Prossimo"
|
||||||
|
},
|
||||||
|
"polls": {
|
||||||
|
"add_poll": "Sondaggio",
|
||||||
|
"add_option": "Alternativa",
|
||||||
|
"option": "Opzione",
|
||||||
|
"votes": "voti",
|
||||||
|
"vote": "Vota",
|
||||||
|
"type": "Tipo di sondaggio",
|
||||||
|
"single_choice": "Scelta singola",
|
||||||
|
"multiple_choices": "Scelta multipla",
|
||||||
|
"expiry": "Scadenza",
|
||||||
|
"expires_in": "Scade fra {0}",
|
||||||
|
"expired": "Scaduto {0} fa",
|
||||||
|
"not_enough_options": "Aggiungi altre risposte"
|
||||||
|
},
|
||||||
|
"interactions": {
|
||||||
|
"favs_repeats": "Condivisi e preferiti",
|
||||||
|
"load_older": "Carica vecchie interazioni",
|
||||||
|
"moves": "Utenti migrati",
|
||||||
|
"follows": "Nuovi seguìti"
|
||||||
|
},
|
||||||
|
"emoji": {
|
||||||
|
"load_all": "Carico tutti i {emojiAmount} emoji",
|
||||||
|
"load_all_hint": "Primi {saneAmount} emoji caricati, caricarli tutti potrebbe causare rallentamenti.",
|
||||||
|
"unicode": "Emoji Unicode",
|
||||||
|
"custom": "Emoji personale",
|
||||||
|
"add_emoji": "Inserisci Emoji",
|
||||||
|
"search_emoji": "Cerca un emoji",
|
||||||
|
"keep_open": "Tieni aperto il menù",
|
||||||
|
"emoji": "Emoji",
|
||||||
|
"stickers": "Adesivi"
|
||||||
|
},
|
||||||
|
"selectable_list": {
|
||||||
|
"select_all": "Seleziona tutto"
|
||||||
|
},
|
||||||
|
"remote_user_resolver": {
|
||||||
|
"error": "Non trovato.",
|
||||||
|
"searching_for": "Cerco",
|
||||||
|
"remote_user_resolver": "Cerca utenti remoti"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,34 +7,47 @@
|
||||||
// sed -i -e "s/'//gm" -e 's/"/\\"/gm' -re 's/^( +)(.+?): ((.+?))?(,?)(\{?)$/\1"\2": "\4"/gm' -e 's/\"\{\"/{/g' -e 's/,"$/",/g' file.json
|
// sed -i -e "s/'//gm" -e 's/"/\\"/gm' -re 's/^( +)(.+?): ((.+?))?(,?)(\{?)$/\1"\2": "\4"/gm' -e 's/\"\{\"/{/g' -e 's/,"$/",/g' file.json
|
||||||
// There's only problem that apostrophe character ' gets replaced by \\ so you have to fix it manually, sorry.
|
// There's only problem that apostrophe character ' gets replaced by \\ so you have to fix it manually, sorry.
|
||||||
|
|
||||||
|
const loaders = {
|
||||||
|
ar: () => import('./ar.json'),
|
||||||
|
ca: () => import('./ca.json'),
|
||||||
|
cs: () => import('./cs.json'),
|
||||||
|
de: () => import('./de.json'),
|
||||||
|
eo: () => import('./eo.json'),
|
||||||
|
es: () => import('./es.json'),
|
||||||
|
et: () => import('./et.json'),
|
||||||
|
eu: () => import('./eu.json'),
|
||||||
|
fi: () => import('./fi.json'),
|
||||||
|
fr: () => import('./fr.json'),
|
||||||
|
ga: () => import('./ga.json'),
|
||||||
|
he: () => import('./he.json'),
|
||||||
|
hu: () => import('./hu.json'),
|
||||||
|
it: () => import('./it.json'),
|
||||||
|
ja: () => import('./ja_pedantic.json'),
|
||||||
|
ja_easy: () => import('./ja_easy.json'),
|
||||||
|
ko: () => import('./ko.json'),
|
||||||
|
nb: () => import('./nb.json'),
|
||||||
|
nl: () => import('./nl.json'),
|
||||||
|
oc: () => import('./oc.json'),
|
||||||
|
pl: () => import('./pl.json'),
|
||||||
|
pt: () => import('./pt.json'),
|
||||||
|
ro: () => import('./ro.json'),
|
||||||
|
ru: () => import('./ru.json'),
|
||||||
|
te: () => import('./te.json'),
|
||||||
|
zh: () => import('./zh.json')
|
||||||
|
}
|
||||||
|
|
||||||
const messages = {
|
const messages = {
|
||||||
ar: require('./ar.json'),
|
languages: ['en', ...Object.keys(loaders)],
|
||||||
ca: require('./ca.json'),
|
default: {
|
||||||
cs: require('./cs.json'),
|
en: require('./en.json')
|
||||||
de: require('./de.json'),
|
},
|
||||||
en: require('./en.json'),
|
setLanguage: async (i18n, language) => {
|
||||||
eo: require('./eo.json'),
|
if (loaders[language]) {
|
||||||
es: require('./es.json'),
|
let messages = await loaders[language]()
|
||||||
et: require('./et.json'),
|
i18n.setLocaleMessage(language, messages)
|
||||||
eu: require('./eu.json'),
|
}
|
||||||
fi: require('./fi.json'),
|
i18n.locale = language
|
||||||
fr: require('./fr.json'),
|
}
|
||||||
ga: require('./ga.json'),
|
|
||||||
he: require('./he.json'),
|
|
||||||
hu: require('./hu.json'),
|
|
||||||
it: require('./it.json'),
|
|
||||||
ja: require('./ja_pedantic.json'),
|
|
||||||
ja_easy: require('./ja_easy.json'),
|
|
||||||
ko: require('./ko.json'),
|
|
||||||
nb: require('./nb.json'),
|
|
||||||
nl: require('./nl.json'),
|
|
||||||
oc: require('./oc.json'),
|
|
||||||
pl: require('./pl.json'),
|
|
||||||
pt: require('./pt.json'),
|
|
||||||
ro: require('./ro.json'),
|
|
||||||
ru: require('./ru.json'),
|
|
||||||
te: require('./te.json'),
|
|
||||||
zh: require('./zh.json')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default messages
|
export default messages
|
||||||
|
|
|
||||||
465
src/i18n/nl.json
465
src/i18n/nl.json
|
|
@ -16,7 +16,7 @@
|
||||||
"find_user": "Gebruiker zoeken"
|
"find_user": "Gebruiker zoeken"
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"apply": "toepassen",
|
"apply": "Toepassen",
|
||||||
"submit": "Verzend",
|
"submit": "Verzend",
|
||||||
"more": "Meer",
|
"more": "Meer",
|
||||||
"optional": "optioneel",
|
"optional": "optioneel",
|
||||||
|
|
@ -33,10 +33,10 @@
|
||||||
"login": {
|
"login": {
|
||||||
"login": "Log in",
|
"login": "Log in",
|
||||||
"description": "Log in met OAuth",
|
"description": "Log in met OAuth",
|
||||||
"logout": "Log uit",
|
"logout": "Uitloggen",
|
||||||
"password": "Wachtwoord",
|
"password": "Wachtwoord",
|
||||||
"placeholder": "bv. lain",
|
"placeholder": "bijv. lain",
|
||||||
"register": "Registreer",
|
"register": "Registreren",
|
||||||
"username": "Gebruikersnaam",
|
"username": "Gebruikersnaam",
|
||||||
"hint": "Log in om deel te nemen aan de discussie",
|
"hint": "Log in om deel te nemen aan de discussie",
|
||||||
"authentication_code": "Authenticatie code",
|
"authentication_code": "Authenticatie code",
|
||||||
|
|
@ -51,14 +51,14 @@
|
||||||
"nav": {
|
"nav": {
|
||||||
"about": "Over",
|
"about": "Over",
|
||||||
"back": "Terug",
|
"back": "Terug",
|
||||||
"chat": "Locale Chat",
|
"chat": "Lokale Chat",
|
||||||
"friend_requests": "Volgverzoek",
|
"friend_requests": "Volgverzoeken",
|
||||||
"mentions": "Vermeldingen",
|
"mentions": "Vermeldingen",
|
||||||
"dms": "Directe Berichten",
|
"dms": "Directe Berichten",
|
||||||
"public_tl": "Publieke Tijdlijn",
|
"public_tl": "Publieke Tijdlijn",
|
||||||
"timeline": "Tijdlijn",
|
"timeline": "Tijdlijn",
|
||||||
"twkn": "Het Geheel Gekende Netwerk",
|
"twkn": "Het Geheel Bekende Netwerk",
|
||||||
"user_search": "Zoek Gebruiker",
|
"user_search": "Gebruiker Zoeken",
|
||||||
"who_to_follow": "Wie te volgen",
|
"who_to_follow": "Wie te volgen",
|
||||||
"preferences": "Voorkeuren",
|
"preferences": "Voorkeuren",
|
||||||
"administration": "Administratie",
|
"administration": "Administratie",
|
||||||
|
|
@ -66,44 +66,44 @@
|
||||||
"interactions": "Interacties"
|
"interactions": "Interacties"
|
||||||
},
|
},
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"broken_favorite": "Onbekende status, aan het zoeken...",
|
"broken_favorite": "Onbekende status, aan het zoeken…",
|
||||||
"favorited_you": "vond je status leuk",
|
"favorited_you": "vond je status leuk",
|
||||||
"followed_you": "volgt jou",
|
"followed_you": "volgt jou",
|
||||||
"load_older": "Laad oudere meldingen",
|
"load_older": "Laad oudere meldingen",
|
||||||
"notifications": "Meldingen",
|
"notifications": "Meldingen",
|
||||||
"read": "Gelezen!",
|
"read": "Gelezen!",
|
||||||
"repeated_you": "Herhaalde je status",
|
"repeated_you": "Herhaalde je status",
|
||||||
"no_more_notifications": "Geen notificaties meer",
|
"no_more_notifications": "Geen meldingen meer",
|
||||||
"migrated_to": "is gemigreerd naar",
|
"migrated_to": "is gemigreerd naar",
|
||||||
"follow_request": "wil je volgen",
|
"follow_request": "wil je volgen",
|
||||||
"reacted_with": "reageerde met {0}"
|
"reacted_with": "reageerde met {0}"
|
||||||
},
|
},
|
||||||
"post_status": {
|
"post_status": {
|
||||||
"new_status": "Post nieuwe status",
|
"new_status": "Nieuwe status plaatsen",
|
||||||
"account_not_locked_warning": "Je account is niet {0}. Iedereen die je volgt kan enkel-volgers posts lezen.",
|
"account_not_locked_warning": "Je account is niet {0}. Iedereen kan je volgen om je alleen-volgers berichten te lezen.",
|
||||||
"account_not_locked_warning_link": "gesloten",
|
"account_not_locked_warning_link": "gesloten",
|
||||||
"attachments_sensitive": "Markeer bijlage als gevoelig",
|
"attachments_sensitive": "Markeer bijlagen als gevoelig",
|
||||||
"content_type": {
|
"content_type": {
|
||||||
"text/plain": "Gewone tekst",
|
"text/plain": "Platte tekst",
|
||||||
"text/html": "HTML",
|
"text/html": "HTML",
|
||||||
"text/markdown": "Markdown",
|
"text/markdown": "Markdown",
|
||||||
"text/bbcode": "BBCode"
|
"text/bbcode": "BBCode"
|
||||||
},
|
},
|
||||||
"content_warning": "Onderwerp (optioneel)",
|
"content_warning": "Onderwerp (optioneel)",
|
||||||
"default": "Tijd voor een pauze!",
|
"default": "Zojuist geland in L.A.",
|
||||||
"direct_warning": "Deze post zal enkel zichtbaar zijn voor de personen die genoemd zijn.",
|
"direct_warning": "Deze post zal enkel zichtbaar zijn voor de personen die genoemd zijn.",
|
||||||
"posting": "Plaatsen",
|
"posting": "Plaatsen",
|
||||||
"scope": {
|
"scope": {
|
||||||
"direct": "Direct - Post enkel naar genoemde gebruikers",
|
"direct": "Direct - Post enkel naar vermelde gebruikers",
|
||||||
"private": "Enkel volgers - Post enkel naar volgers",
|
"private": "Enkel volgers - Post enkel naar volgers",
|
||||||
"public": "Publiek - Post op publieke tijdlijnen",
|
"public": "Publiek - Post op publieke tijdlijnen",
|
||||||
"unlisted": "Unlisted - Toon niet op publieke tijdlijnen"
|
"unlisted": "Niet Vermelden - Niet tonen op publieke tijdlijnen"
|
||||||
},
|
},
|
||||||
"direct_warning_to_all": "Dit bericht zal zichtbaar zijn voor alle vermelde gebruikers.",
|
"direct_warning_to_all": "Dit bericht zal zichtbaar zijn voor alle vermelde gebruikers.",
|
||||||
"direct_warning_to_first_only": "Dit bericht zal alleen zichtbaar zijn voor de vermelde gebruikers aan het begin van het bericht.",
|
"direct_warning_to_first_only": "Dit bericht zal alleen zichtbaar zijn voor de vermelde gebruikers aan het begin van het bericht.",
|
||||||
"scope_notice": {
|
"scope_notice": {
|
||||||
"public": "Dit bericht zal voor iedereen zichtbaar zijn",
|
"public": "Dit bericht zal voor iedereen zichtbaar zijn",
|
||||||
"unlisted": "Dit bericht zal niet zichtbaar zijn in de Publieke Tijdlijn en Het Geheel Gekende Netwerk",
|
"unlisted": "Dit bericht zal niet zichtbaar zijn in de Publieke Tijdlijn en Het Geheel Bekende Netwerk",
|
||||||
"private": "Dit bericht zal voor alleen je volgers zichtbaar zijn"
|
"private": "Dit bericht zal voor alleen je volgers zichtbaar zijn"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -113,7 +113,7 @@
|
||||||
"fullname": "Weergave naam",
|
"fullname": "Weergave naam",
|
||||||
"password_confirm": "Wachtwoord bevestiging",
|
"password_confirm": "Wachtwoord bevestiging",
|
||||||
"registration": "Registratie",
|
"registration": "Registratie",
|
||||||
"token": "Uitnodigingstoken",
|
"token": "Uitnodigings-token",
|
||||||
"captcha": "CAPTCHA",
|
"captcha": "CAPTCHA",
|
||||||
"new_captcha": "Klik op de afbeelding voor een nieuwe captcha",
|
"new_captcha": "Klik op de afbeelding voor een nieuwe captcha",
|
||||||
"validations": {
|
"validations": {
|
||||||
|
|
@ -131,37 +131,37 @@
|
||||||
"settings": {
|
"settings": {
|
||||||
"attachmentRadius": "Bijlages",
|
"attachmentRadius": "Bijlages",
|
||||||
"attachments": "Bijlages",
|
"attachments": "Bijlages",
|
||||||
"autoload": "Automatisch laden wanneer tot de bodem gescrold inschakelen",
|
"autoload": "Automatisch laden inschakelen wanneer tot de bodem gescrold wordt",
|
||||||
"avatar": "Avatar",
|
"avatar": "Avatar",
|
||||||
"avatarAltRadius": "Avatars (Meldingen)",
|
"avatarAltRadius": "Avatars (Meldingen)",
|
||||||
"avatarRadius": "Avatars",
|
"avatarRadius": "Avatars",
|
||||||
"background": "Achtergrond",
|
"background": "Achtergrond",
|
||||||
"bio": "Bio",
|
"bio": "Bio",
|
||||||
"btnRadius": "Knoppen",
|
"btnRadius": "Knoppen",
|
||||||
"cBlue": "Blauw (Antwoord, volgen)",
|
"cBlue": "Blauw (Beantwoorden, volgen)",
|
||||||
"cGreen": "Groen (Herhaal)",
|
"cGreen": "Groen (Herhalen)",
|
||||||
"cOrange": "Oranje (Vind ik leuk)",
|
"cOrange": "Oranje (Favoriet)",
|
||||||
"cRed": "Rood (Annuleer)",
|
"cRed": "Rood (Annuleren)",
|
||||||
"change_password": "Verander Wachtwoord",
|
"change_password": "Wachtwoord Wijzigen",
|
||||||
"change_password_error": "Er was een probleem bij het aanpassen van je wachtwoord.",
|
"change_password_error": "Er is een fout opgetreden bij het wijzigen van je wachtwoord.",
|
||||||
"changed_password": "Wachtwoord succesvol aangepast!",
|
"changed_password": "Wachtwoord succesvol gewijzigd!",
|
||||||
"collapse_subject": "Klap posts met onderwerp in",
|
"collapse_subject": "Klap berichten met een onderwerp in",
|
||||||
"composing": "Samenstellen",
|
"composing": "Opstellen",
|
||||||
"confirm_new_password": "Bevestig nieuw wachtwoord",
|
"confirm_new_password": "Nieuw wachtwoord bevestigen",
|
||||||
"current_avatar": "Je huidige avatar",
|
"current_avatar": "Je huidige avatar",
|
||||||
"current_password": "Huidig wachtwoord",
|
"current_password": "Huidig wachtwoord",
|
||||||
"current_profile_banner": "Je huidige profiel banner",
|
"current_profile_banner": "Je huidige profiel banner",
|
||||||
"data_import_export_tab": "Data Import / Export",
|
"data_import_export_tab": "Data Import / Export",
|
||||||
"default_vis": "Standaard zichtbaarheidsscope",
|
"default_vis": "Standaard zichtbaarheidsbereik",
|
||||||
"delete_account": "Verwijder Account",
|
"delete_account": "Account Verwijderen",
|
||||||
"delete_account_description": "Verwijder je account en berichten permanent.",
|
"delete_account_description": "Permanent je gegevens verwijderen en account deactiveren.",
|
||||||
"delete_account_error": "Er was een probleem bij het verwijderen van je account. Indien dit probleem blijft, gelieve de administratie van deze instantie te verwittigen.",
|
"delete_account_error": "Er is een fout opgetreden bij het verwijderen van je account. Indien dit probleem zich voor blijft doen, neem dan contact op met de beheerder van deze instantie.",
|
||||||
"delete_account_instructions": "Typ je wachtwoord in de input hieronder om het verwijderen van je account te bevestigen.",
|
"delete_account_instructions": "Voer je wachtwoord in het onderstaande invoerveld in om het verwijderen van je account te bevestigen.",
|
||||||
"export_theme": "Sla preset op",
|
"export_theme": "Preset opslaan",
|
||||||
"filtering": "Filtering",
|
"filtering": "Filtering",
|
||||||
"filtering_explanation": "Alle statussen die deze woorden bevatten worden genegeerd, één filter per lijn.",
|
"filtering_explanation": "Alle statussen die deze woorden bevatten worden genegeerd, één filter per lijn",
|
||||||
"follow_export": "Volgers exporteren",
|
"follow_export": "Volgers exporteren",
|
||||||
"follow_export_button": "Exporteer je volgers naar een csv file",
|
"follow_export_button": "Exporteer je volgers naar een csv bestand",
|
||||||
"follow_export_processing": "Aan het verwerken, binnen enkele ogenblikken wordt je gevraagd je bestand te downloaden",
|
"follow_export_processing": "Aan het verwerken, binnen enkele ogenblikken wordt je gevraagd je bestand te downloaden",
|
||||||
"follow_import": "Volgers importeren",
|
"follow_import": "Volgers importeren",
|
||||||
"follow_import_error": "Fout bij importeren volgers",
|
"follow_import_error": "Fout bij importeren volgers",
|
||||||
|
|
@ -171,98 +171,105 @@
|
||||||
"hide_attachments_in_convo": "Verberg bijlages in conversaties",
|
"hide_attachments_in_convo": "Verberg bijlages in conversaties",
|
||||||
"hide_attachments_in_tl": "Verberg bijlages in de tijdlijn",
|
"hide_attachments_in_tl": "Verberg bijlages in de tijdlijn",
|
||||||
"hide_isp": "Verberg instantie-specifiek paneel",
|
"hide_isp": "Verberg instantie-specifiek paneel",
|
||||||
"preload_images": "Afbeeldingen voorladen",
|
"preload_images": "Afbeeldingen vooraf laden",
|
||||||
"hide_post_stats": "Verberg post statistieken (bv. het aantal vind-ik-leuks)",
|
"hide_post_stats": "Verberg bericht statistieken (bijv. het aantal favorieten)",
|
||||||
"hide_user_stats": "Verberg post statistieken (bv. het aantal volgers)",
|
"hide_user_stats": "Verberg bericht statistieken (bijv. het aantal volgers)",
|
||||||
"import_followers_from_a_csv_file": "Importeer volgers uit een csv file",
|
"import_followers_from_a_csv_file": "Importeer volgers uit een csv bestand",
|
||||||
"import_theme": "Laad preset",
|
"import_theme": "Preset laden",
|
||||||
"inputRadius": "Invoervelden",
|
"inputRadius": "Invoervelden",
|
||||||
"checkboxRadius": "Checkboxen",
|
"checkboxRadius": "Checkboxen",
|
||||||
"instance_default": "(standaard: {value})",
|
"instance_default": "(standaard: {value})",
|
||||||
"instance_default_simple": "(standaard)",
|
"instance_default_simple": "(standaard)",
|
||||||
"interface": "Interface",
|
"interface": "Interface",
|
||||||
"interfaceLanguage": "Interface taal",
|
"interfaceLanguage": "Interface taal",
|
||||||
"invalid_theme_imported": "Het geselecteerde thema is geen door Pleroma ondersteund thema. Er zijn geen aanpassingen gedaan.",
|
"invalid_theme_imported": "Het geselecteerde bestand is geen door Pleroma ondersteund thema. Er zijn geen aanpassingen gedaan.",
|
||||||
"limited_availability": "Onbeschikbaar in je browser",
|
"limited_availability": "Niet beschikbaar in je browser",
|
||||||
"links": "Links",
|
"links": "Links",
|
||||||
"lock_account_description": "Laat volgers enkel toe na expliciete toestemming",
|
"lock_account_description": "Laat volgers enkel toe na expliciete toestemming",
|
||||||
"loop_video": "Speel videos af in een lus",
|
"loop_video": "Herhaal video's",
|
||||||
"loop_video_silent_only": "Speel enkel videos zonder geluid af in een lus (bv. Mastodon's \"gifs\")",
|
"loop_video_silent_only": "Herhaal enkel video's zonder geluid (bijv. Mastodon's \"gifs\")",
|
||||||
"name": "Naam",
|
"name": "Naam",
|
||||||
"name_bio": "Naam & Bio",
|
"name_bio": "Naam & Bio",
|
||||||
"new_password": "Nieuw wachtwoord",
|
"new_password": "Nieuw wachtwoord",
|
||||||
"notification_visibility": "Type meldingen die getoond worden",
|
"notification_visibility": "Type meldingen die getoond worden",
|
||||||
"notification_visibility_follows": "Volgers",
|
"notification_visibility_follows": "Volgingen",
|
||||||
"notification_visibility_likes": "Vind-ik-leuks",
|
"notification_visibility_likes": "Vind-ik-leuks",
|
||||||
"notification_visibility_mentions": "Vermeldingen",
|
"notification_visibility_mentions": "Vermeldingen",
|
||||||
"notification_visibility_repeats": "Herhalingen",
|
"notification_visibility_repeats": "Herhalingen",
|
||||||
"no_rich_text_description": "Strip rich text formattering van alle posts",
|
"no_rich_text_description": "Verwijder rich text formattering van alle berichten",
|
||||||
"hide_network_description": "Toon niet wie mij volgt en wie ik volg.",
|
"hide_network_description": "Toon niet wie mij volgt en wie ik volg.",
|
||||||
"nsfw_clickthrough": "Schakel doorklikbaar verbergen van NSFW bijlages in",
|
"nsfw_clickthrough": "Doorklikbaar verbergen van gevoelige bijlages inschakelen",
|
||||||
"oauth_tokens": "OAuth-tokens",
|
"oauth_tokens": "OAuth-tokens",
|
||||||
"token": "Token",
|
"token": "Token",
|
||||||
"refresh_token": "Token vernieuwen",
|
"refresh_token": "Token Vernieuwen",
|
||||||
"valid_until": "Geldig tot",
|
"valid_until": "Geldig tot",
|
||||||
"revoke_token": "Intrekken",
|
"revoke_token": "Intrekken",
|
||||||
"panelRadius": "Panelen",
|
"panelRadius": "Panelen",
|
||||||
"pause_on_unfocused": "Pauzeer streamen wanneer de tab niet gefocused is",
|
"pause_on_unfocused": "Streamen pauzeren wanneer de tab niet in focus is",
|
||||||
"presets": "Presets",
|
"presets": "Presets",
|
||||||
"profile_background": "Profiel Achtergrond",
|
"profile_background": "Profiel Achtergrond",
|
||||||
"profile_banner": "Profiel Banner",
|
"profile_banner": "Profiel Banner",
|
||||||
"profile_tab": "Profiel",
|
"profile_tab": "Profiel",
|
||||||
"radii_help": "Stel afronding van hoeken in de interface in (in pixels)",
|
"radii_help": "Stel afronding van hoeken in de interface in (in pixels)",
|
||||||
"replies_in_timeline": "Antwoorden in tijdlijn",
|
"replies_in_timeline": "Antwoorden in tijdlijn",
|
||||||
"reply_link_preview": "Schakel antwoordlink preview in bij over zweven met muisaanwijzer",
|
"reply_link_preview": "Antwoord-link weergave inschakelen bij aanwijzen met muisaanwijzer",
|
||||||
"reply_visibility_all": "Toon alle antwoorden",
|
"reply_visibility_all": "Alle antwoorden tonen",
|
||||||
"reply_visibility_following": "Toon enkel antwoorden naar mij of andere gebruikers gericht",
|
"reply_visibility_following": "Enkel antwoorden tonen die aan mij of gevolgde gebruikers gericht zijn",
|
||||||
"reply_visibility_self": "Toon enkel antwoorden naar mij gericht",
|
"reply_visibility_self": "Enkel antwoorden tonen die aan mij gericht zijn",
|
||||||
"saving_err": "Fout tijdens opslaan van instellingen",
|
"saving_err": "Fout tijdens opslaan van instellingen",
|
||||||
"saving_ok": "Instellingen opgeslagen",
|
"saving_ok": "Instellingen opgeslagen",
|
||||||
"security_tab": "Veiligheid",
|
"security_tab": "Beveiliging",
|
||||||
"scope_copy": "Neem scope over bij antwoorden (Directe Berichten blijven altijd Direct)",
|
"scope_copy": "Neem bereik over bij beantwoorden (Directe Berichten blijven altijd Direct)",
|
||||||
"set_new_avatar": "Zet nieuwe avatar",
|
"set_new_avatar": "Nieuwe avatar instellen",
|
||||||
"set_new_profile_background": "Zet nieuwe profiel achtergrond",
|
"set_new_profile_background": "Nieuwe profiel achtergrond instellen",
|
||||||
"set_new_profile_banner": "Zet nieuwe profiel banner",
|
"set_new_profile_banner": "Nieuwe profiel banner instellen",
|
||||||
"settings": "Instellingen",
|
"settings": "Instellingen",
|
||||||
"subject_input_always_show": "Maak onderwerpveld altijd zichtbaar",
|
"subject_input_always_show": "Altijd onderwerpveld tonen",
|
||||||
"subject_line_behavior": "Kopieer onderwerp bij antwoorden",
|
"subject_line_behavior": "Onderwerp kopiëren bij antwoorden",
|
||||||
"subject_line_email": "Zoals email: \"re: onderwerp\"",
|
"subject_line_email": "Zoals email: \"re: onderwerp\"",
|
||||||
"subject_line_mastodon": "Zoals Mastodon: kopieer zoals het is",
|
"subject_line_mastodon": "Zoals mastodon: kopieer zoals het is",
|
||||||
"subject_line_noop": "Kopieer niet",
|
"subject_line_noop": "Niet kopiëren",
|
||||||
"stop_gifs": "Speel GIFs af bij zweven",
|
"stop_gifs": "GIFs afspelen bij zweven",
|
||||||
"streaming": "Schakel automatisch streamen van posts in wanneer tot boven gescrold.",
|
"streaming": "Automatisch streamen van nieuwe berichten inschakelen wanneer tot boven gescrold is",
|
||||||
"text": "Tekst",
|
"text": "Tekst",
|
||||||
"theme": "Thema",
|
"theme": "Thema",
|
||||||
"theme_help": "Gebruik hex color codes (#rrggbb) om je kleurschema te wijzigen.",
|
"theme_help": "Gebruik hex color codes (#rrggbb) om je kleurschema te wijzigen.",
|
||||||
"theme_help_v2_1": "Je kan ook de kleur en transparantie van bepaalde componenten overschrijven door de checkbox aan te vinken, gebruik de \"Wis alles\" knop om alle overschrijvingen te annuleren.",
|
"theme_help_v2_1": "Je kan ook de kleur en transparantie van bepaalde componenten overschrijven door de checkbox aan te vinken, gebruik de \"Alles wissen\" knop om alle overschrijvingen te annuleren.",
|
||||||
"theme_help_v2_2": "Iconen onder sommige items zijn achtergrond/tekst contrast indicators, zweef er over voor gedetailleerde info. Hou er rekening mee dat bij doorzichtigheid de ergst mogelijke situatie wordt weer gegeven.",
|
"theme_help_v2_2": "Iconen onder sommige onderdelen zijn achtergrond/tekst contrast indicatoren, zweef er over voor gedetailleerde info. Hou er rekening mee dat bij doorzichtigheid de ergst mogelijke situatie wordt weer gegeven.",
|
||||||
"tooltipRadius": "Gereedschapstips/alarmen",
|
"tooltipRadius": "Tooltips/alarmen",
|
||||||
"user_settings": "Gebruikers Instellingen",
|
"user_settings": "Gebruikersinstellingen",
|
||||||
"values": {
|
"values": {
|
||||||
"false": "nee",
|
"false": "nee",
|
||||||
"true": "ja"
|
"true": "ja"
|
||||||
},
|
},
|
||||||
"notifications": "Meldingen",
|
"notifications": "Meldingen",
|
||||||
"enable_web_push_notifications": "Schakel web push meldingen in",
|
"enable_web_push_notifications": "Web push meldingen inschakelen",
|
||||||
"style": {
|
"style": {
|
||||||
"switcher": {
|
"switcher": {
|
||||||
"keep_color": "Behoud kleuren",
|
"keep_color": "Kleuren behouden",
|
||||||
"keep_shadows": "Behoud schaduwen",
|
"keep_shadows": "Schaduwen behouden",
|
||||||
"keep_opacity": "Behoud transparantie",
|
"keep_opacity": "Transparantie behouden",
|
||||||
"keep_roundness": "Behoud afrondingen",
|
"keep_roundness": "Rondingen behouden",
|
||||||
"keep_fonts": "Behoud lettertypes",
|
"keep_fonts": "Lettertypes behouden",
|
||||||
"save_load_hint": "\"Behoud\" opties behouden de momenteel ingestelde opties bij het selecteren of laden van thema's, maar slaan ook de genoemde opties op bij het exporteren van een thema. Wanneer alle selectievakjes zijn uitgeschakeld, zal het exporteren van thema's alles opslaan.",
|
"save_load_hint": "\"Behoud\" opties behouden de momenteel ingestelde opties bij het selecteren of laden van thema's, maar slaan ook de genoemde opties op bij het exporteren van een thema. Wanneer alle selectievakjes zijn uitgeschakeld, zal het exporteren van thema's alles opslaan.",
|
||||||
"reset": "Reset",
|
"reset": "Reset",
|
||||||
"clear_all": "Wis alles",
|
"clear_all": "Alles wissen",
|
||||||
"clear_opacity": "Wis transparantie",
|
"clear_opacity": "Transparantie wissen",
|
||||||
"keep_as_is": "Houdt zoals het is",
|
"keep_as_is": "Hou zoals het is",
|
||||||
"use_snapshot": "Oude versie",
|
"use_snapshot": "Oude versie",
|
||||||
"use_source": "Nieuwe versie",
|
"use_source": "Nieuwe versie",
|
||||||
"help": {
|
"help": {
|
||||||
"future_version_imported": "Het geïmporteerde bestand is gemaakt voor een nieuwere versie van FE.",
|
"future_version_imported": "Het geïmporteerde bestand is gemaakt voor een nieuwere versie van FE.",
|
||||||
"older_version_imported": "Het geïmporteerde bestand is gemaakt voor een oudere versie van FE.",
|
"older_version_imported": "Het geïmporteerde bestand is gemaakt voor een oudere versie van FE.",
|
||||||
"upgraded_from_v2": "PleromaFE is bijgewerkt, het thema kan iets anders uitzien dan dat je gewend bent.",
|
"upgraded_from_v2": "PleromaFE is bijgewerkt, het thema kan iets anders uitzien dan dat je gewend bent.",
|
||||||
"v2_imported": "Het geïmporteerde bestand is gemaakt voor een oudere FE. We proberen compatibiliteit te maximaliseren, maar het kan toch voorkomen dat er inconsistenties zijn."
|
"v2_imported": "Het geïmporteerde bestand is gemaakt voor een oudere FE. We proberen compatibiliteit te maximaliseren, maar het kan toch voorkomen dat er inconsistenties zijn.",
|
||||||
|
"snapshot_source_mismatch": "Versie conflict: waarschijnlijk was FE terug gerold en opnieuw bijgewerkt, indien je het thema aangepast hebt met de oudere versie van FE wil je waarschijnlijk de oude versie gebruiken, gebruik anders de nieuwe versie.",
|
||||||
|
"migration_napshot_gone": "Voor een onduidelijke reden mist de momentopname, dus sommige dingen kunnen anders uitzien dan je gewend bent.",
|
||||||
|
"migration_snapshot_ok": "Voor de zekerheid is een momentopname van het thema geladen. Je kunt proberen om de thema gegevens te laden.",
|
||||||
|
"fe_downgraded": "PleromaFE's versie is terug gerold.",
|
||||||
|
"fe_upgraded": "De thema-engine van PleromaFE is bijgewerkt na de versie update.",
|
||||||
|
"snapshot_missing": "Het bestand bevat geen thema momentopname, dus het thema kan anders uitzien dan je oorspronkelijk bedacht had.",
|
||||||
|
"snapshot_present": "Thema momentopname is geladen, alle waarden zijn overschreven. Je kunt in plaats daarvan ook de daadwerkelijke data van het thema laden."
|
||||||
},
|
},
|
||||||
"load_theme": "Thema laden"
|
"load_theme": "Thema laden"
|
||||||
},
|
},
|
||||||
|
|
@ -270,7 +277,7 @@
|
||||||
"color": "Kleur",
|
"color": "Kleur",
|
||||||
"opacity": "Transparantie",
|
"opacity": "Transparantie",
|
||||||
"contrast": {
|
"contrast": {
|
||||||
"hint": "Contrast ratio is {ratio}, {level} {context}",
|
"hint": "Contrast verhouding is {ratio}, {level} {context}",
|
||||||
"level": {
|
"level": {
|
||||||
"aa": "voldoet aan de richtlijn van niveau AA (minimum)",
|
"aa": "voldoet aan de richtlijn van niveau AA (minimum)",
|
||||||
"aaa": "voldoet aan de richtlijn van niveau AAA (aangeraden)",
|
"aaa": "voldoet aan de richtlijn van niveau AAA (aangeraden)",
|
||||||
|
|
@ -283,8 +290,8 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"common_colors": {
|
"common_colors": {
|
||||||
"_tab_label": "Gemeenschappelijk",
|
"_tab_label": "Algemeen",
|
||||||
"main": "Gemeenschappelijke kleuren",
|
"main": "Algemene kleuren",
|
||||||
"foreground_hint": "Zie \"Geavanceerd\" tab voor meer gedetailleerde controle",
|
"foreground_hint": "Zie \"Geavanceerd\" tab voor meer gedetailleerde controle",
|
||||||
"rgbo": "Iconen, accenten, badges"
|
"rgbo": "Iconen, accenten, badges"
|
||||||
},
|
},
|
||||||
|
|
@ -294,58 +301,73 @@
|
||||||
"alert_error": "Fout",
|
"alert_error": "Fout",
|
||||||
"badge": "Badge achtergrond",
|
"badge": "Badge achtergrond",
|
||||||
"badge_notification": "Meldingen",
|
"badge_notification": "Meldingen",
|
||||||
"panel_header": "Paneel hoofding",
|
"panel_header": "Paneel koptekst",
|
||||||
"top_bar": "Top bar",
|
"top_bar": "Top balk",
|
||||||
"borders": "Randen",
|
"borders": "Randen",
|
||||||
"buttons": "Knoppen",
|
"buttons": "Knoppen",
|
||||||
"inputs": "Invoervelden",
|
"inputs": "Invoervelden",
|
||||||
"faint_text": "Vervaagde tekst"
|
"faint_text": "Vervaagde tekst",
|
||||||
|
"tabs": "Tabbladen",
|
||||||
|
"toggled": "Geschakeld",
|
||||||
|
"disabled": "Uitgeschakeld",
|
||||||
|
"selectedMenu": "Geselecteerd menu item",
|
||||||
|
"selectedPost": "Geselecteerd bericht",
|
||||||
|
"pressed": "Ingedrukt",
|
||||||
|
"highlight": "Gemarkeerde elementen",
|
||||||
|
"icons": "Iconen",
|
||||||
|
"poll": "Poll grafiek",
|
||||||
|
"underlay": "Onderlaag",
|
||||||
|
"popover": "Tooltips, menu's, popovers",
|
||||||
|
"post": "Berichten / Gebruiker bios",
|
||||||
|
"alert_neutral": "Neutraal",
|
||||||
|
"alert_warning": "Waarschuwing"
|
||||||
},
|
},
|
||||||
"radii": {
|
"radii": {
|
||||||
"_tab_label": "Rondheid"
|
"_tab_label": "Rondheid"
|
||||||
},
|
},
|
||||||
"shadows": {
|
"shadows": {
|
||||||
"_tab_label": "Schaduw en belichting",
|
"_tab_label": "Schaduw en belichting",
|
||||||
"component": "Component",
|
"component": "Onderdeel",
|
||||||
"override": "Overschrijven",
|
"override": "Overschrijven",
|
||||||
"shadow_id": "Schaduw #{value}",
|
"shadow_id": "Schaduw #{value}",
|
||||||
"blur": "Vervagen",
|
"blur": "Vervagen",
|
||||||
"spread": "Spreid",
|
"spread": "Spreiding",
|
||||||
"inset": "Inzet",
|
"inset": "Inzet",
|
||||||
"hint": "Voor schaduw kan je ook --variable gebruiken als een kleur waarde om CSS3 variabelen te gebruiken. Houd er rekening mee dat het instellen van opaciteit in dit geval niet werkt.",
|
"hint": "Voor schaduw kan je ook --variable gebruiken als een kleur waarde om CSS3 variabelen te gebruiken. Houd er rekening mee dat het instellen van opaciteit in dit geval niet werkt.",
|
||||||
"filter_hint": {
|
"filter_hint": {
|
||||||
"always_drop_shadow": "Waarschuwing, deze schaduw gebruikt altijd {0} als de browser dit ondersteund.",
|
"always_drop_shadow": "Waarschuwing, deze schaduw gebruikt altijd {0} als de browser dit ondersteund.",
|
||||||
"drop_shadow_syntax": "{0} ondersteund niet de {1} parameter en {2} sleutelwoord.",
|
"drop_shadow_syntax": "{0} ondersteund niet de {1} parameter en {2} sleutelwoord.",
|
||||||
"avatar_inset": "Houd er rekening mee dat het combineren van zowel inzet and niet-inzet schaduwen op transparante avatars onverwachte resultaten kan opleveren.",
|
"avatar_inset": "Houdt er rekening mee dat het combineren van zowel inzet and niet-inzet schaduwen op transparante avatars onverwachte resultaten kan opleveren.",
|
||||||
"spread_zero": "Schaduw met spreiding > 0 worden weergegeven alsof ze op nul staan",
|
"spread_zero": "Schaduw met spreiding > 0 worden weergegeven alsof ze op nul staan",
|
||||||
"inset_classic": "Inzet schaduw zal {0} gebruiken"
|
"inset_classic": "Inzet schaduw zal {0} gebruiken"
|
||||||
},
|
},
|
||||||
"components": {
|
"components": {
|
||||||
"panel": "Paneel",
|
"panel": "Paneel",
|
||||||
"panelHeader": "Paneel hoofding",
|
"panelHeader": "Paneel koptekst",
|
||||||
"topBar": "Top bar",
|
"topBar": "Top balk",
|
||||||
"avatar": "Gebruiker avatar (in profiel weergave)",
|
"avatar": "Gebruikers avatar (in profiel weergave)",
|
||||||
"avatarStatus": "Gebruiker avatar (in post weergave)",
|
"avatarStatus": "Gebruikers avatar (in bericht weergave)",
|
||||||
"popup": "Popups en gereedschapstips",
|
"popup": "Popups en tooltips",
|
||||||
"button": "Knop",
|
"button": "Knop",
|
||||||
"buttonHover": "Knop (zweven)",
|
"buttonHover": "Knop (zweven)",
|
||||||
"buttonPressed": "Knop (ingedrukt)",
|
"buttonPressed": "Knop (ingedrukt)",
|
||||||
"buttonPressedHover": "Knop (ingedrukt+zweven)",
|
"buttonPressedHover": "Knop (ingedrukt+zweven)",
|
||||||
"input": "Invoerveld"
|
"input": "Invoerveld"
|
||||||
}
|
},
|
||||||
|
"hintV3": "Voor schaduwen kun je ook de {0} notatie gebruiken om de andere kleur invoer te gebruiken."
|
||||||
},
|
},
|
||||||
"fonts": {
|
"fonts": {
|
||||||
"_tab_label": "Lettertypes",
|
"_tab_label": "Lettertypes",
|
||||||
"help": "Selecteer het lettertype om te gebruiken voor elementen van de UI.Voor \"aangepast\" moet je de exacte naam van het lettertype invoeren zoals die in het systeem wordt weergegeven.",
|
"help": "Selecteer het lettertype om te gebruiken voor elementen van de UI. Voor \"aangepast\" dien je de exacte naam van het lettertype in te voeren zoals die in het systeem wordt weergegeven.",
|
||||||
"components": {
|
"components": {
|
||||||
"interface": "Interface",
|
"interface": "Interface",
|
||||||
"input": "Invoervelden",
|
"input": "Invoervelden",
|
||||||
"post": "Post tekst",
|
"post": "Bericht tekst",
|
||||||
"postCode": "Monospaced tekst in een post (rich text)"
|
"postCode": "Monospaced tekst in een bericht (rich text)"
|
||||||
},
|
},
|
||||||
"family": "Naam lettertype",
|
"family": "Lettertype naam",
|
||||||
"size": "Grootte (in px)",
|
"size": "Grootte (in px)",
|
||||||
"weight": "Gewicht (vetheid)",
|
"weight": "Gewicht (dikgedruktheid)",
|
||||||
"custom": "Aangepast"
|
"custom": "Aangepast"
|
||||||
},
|
},
|
||||||
"preview": {
|
"preview": {
|
||||||
|
|
@ -355,20 +377,20 @@
|
||||||
"button": "Knop",
|
"button": "Knop",
|
||||||
"text": "Nog een boel andere {0} en {1}",
|
"text": "Nog een boel andere {0} en {1}",
|
||||||
"mono": "inhoud",
|
"mono": "inhoud",
|
||||||
"input": "Tijd voor een pauze!",
|
"input": "Zojuist geland in L.A.",
|
||||||
"faint_link": "handige gebruikershandleiding",
|
"faint_link": "handige gebruikershandleiding",
|
||||||
"fine_print": "Lees onze {0} om niets nuttig te leren!",
|
"fine_print": "Lees onze {0} om niets nuttig te leren!",
|
||||||
"header_faint": "Alles komt goed",
|
"header_faint": "Alles komt goed",
|
||||||
"checkbox": "Ik heb de gebruikersvoorwaarden eens van ver bekeken",
|
"checkbox": "Ik heb de gebruikersvoorwaarden gelezen",
|
||||||
"link": "een link"
|
"link": "een leuke kleine link"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"notification_setting_follows": "Gebruikers die je volgt",
|
"notification_setting_follows": "Gebruikers die je volgt",
|
||||||
"notification_setting_non_follows": "Gebruikers die je niet volgt",
|
"notification_setting_non_follows": "Gebruikers die je niet volgt",
|
||||||
"notification_setting_followers": "Gebruikers die je volgen",
|
"notification_setting_followers": "Gebruikers die je volgen",
|
||||||
"notification_setting_privacy": "Privacy",
|
"notification_setting_privacy": "Privacy",
|
||||||
"notification_setting_privacy_option": "Verberg de afzender en inhoud van push notificaties",
|
"notification_setting_privacy_option": "Verberg de afzender en inhoud van push meldingen",
|
||||||
"notification_mutes": "Om niet langer notificaties te ontvangen van een specifieke gebruiker, kun je deze dempen.",
|
"notification_mutes": "Om niet langer meldingen te ontvangen van een specifieke gebruiker, kun je deze negeren.",
|
||||||
"app_name": "App naam",
|
"app_name": "App naam",
|
||||||
"security": "Beveiliging",
|
"security": "Beveiliging",
|
||||||
"enter_current_password_to_confirm": "Voer je huidige wachtwoord in om je identiteit te bevestigen",
|
"enter_current_password_to_confirm": "Voer je huidige wachtwoord in om je identiteit te bevestigen",
|
||||||
|
|
@ -380,7 +402,7 @@
|
||||||
"title": "Twee-factor Authenticatie",
|
"title": "Twee-factor Authenticatie",
|
||||||
"generate_new_recovery_codes": "Genereer nieuwe herstelcodes",
|
"generate_new_recovery_codes": "Genereer nieuwe herstelcodes",
|
||||||
"recovery_codes": "Herstelcodes.",
|
"recovery_codes": "Herstelcodes.",
|
||||||
"waiting_a_recovery_codes": "Backup codes ontvangen...",
|
"waiting_a_recovery_codes": "Backup codes ontvangen…",
|
||||||
"authentication_methods": "Authenticatie methodes",
|
"authentication_methods": "Authenticatie methodes",
|
||||||
"scan": {
|
"scan": {
|
||||||
"title": "Scannen",
|
"title": "Scannen",
|
||||||
|
|
@ -393,74 +415,81 @@
|
||||||
"warning_of_generate_new_codes": "Wanneer je nieuwe herstelcodes genereert, zullen je oude code niet langer werken.",
|
"warning_of_generate_new_codes": "Wanneer je nieuwe herstelcodes genereert, zullen je oude code niet langer werken.",
|
||||||
"recovery_codes_warning": "Schrijf de codes op of sla ze op een veilige locatie op - anders kun je ze niet meer inzien. Als je toegang tot je 2FA app en herstelcodes verliest, zal je buitengesloten zijn uit je account."
|
"recovery_codes_warning": "Schrijf de codes op of sla ze op een veilige locatie op - anders kun je ze niet meer inzien. Als je toegang tot je 2FA app en herstelcodes verliest, zal je buitengesloten zijn uit je account."
|
||||||
},
|
},
|
||||||
"allow_following_move": "Auto-volgen toestaan wanneer een gevolgd account migreert",
|
"allow_following_move": "Automatisch volgen toestaan wanneer een gevolgd account migreert",
|
||||||
"block_export": "Geblokkeerde gebruikers exporteren",
|
"block_export": "Blokkades exporteren",
|
||||||
"block_import": "Geblokkeerde gebruikers importeren",
|
"block_import": "Blokkades importeren",
|
||||||
"blocks_imported": "Geblokkeerde gebruikers geïmporteerd! Het kan even duren voordat deze verwerkt zijn.",
|
"blocks_imported": "Blokkades geïmporteerd! Het kan even duren voordat deze verwerkt zijn.",
|
||||||
"blocks_tab": "Geblokkeerde gebruikers",
|
"blocks_tab": "Blokkades",
|
||||||
"change_email": "Email wijzigen",
|
"change_email": "Email wijzigen",
|
||||||
"change_email_error": "Er is een probleem opgetreden tijdens het wijzigen van je email.",
|
"change_email_error": "Er is een fout opgetreden tijdens het wijzigen van je email.",
|
||||||
"changed_email": "Email succesvol gewijzigd!",
|
"changed_email": "Email succesvol gewijzigd!",
|
||||||
"domain_mutes": "Domeinen",
|
"domain_mutes": "Domeinen",
|
||||||
"avatar_size_instruction": "De aangeraden minimale afmeting voor avatar afbeeldingen is 150x150 pixels.",
|
"avatar_size_instruction": "De aangeraden minimale afmeting voor avatar afbeeldingen is 150x150 pixels.",
|
||||||
"pad_emoji": "Vul emoji op met spaties wanneer deze met de picker ingevoegd worden",
|
"pad_emoji": "Vul emoji aan met spaties wanneer deze met de picker ingevoegd worden",
|
||||||
"emoji_reactions_on_timeline": "Toon emoji reacties op de tijdlijn",
|
"emoji_reactions_on_timeline": "Toon emoji reacties op de tijdlijn",
|
||||||
"accent": "Accent",
|
"accent": "Accent",
|
||||||
"hide_muted_posts": "Verberg berichten van gedempte gebruikers",
|
"hide_muted_posts": "Verberg berichten van genegeerde gebruikers",
|
||||||
"max_thumbnails": "Maximaal aantal miniaturen per bericht",
|
"max_thumbnails": "Maximaal aantal miniaturen per bericht",
|
||||||
"use_one_click_nsfw": "Open gevoelige bijlagen met slechts één klik",
|
"use_one_click_nsfw": "Open gevoelige bijlagen met slechts één klik",
|
||||||
"hide_filtered_statuses": "Verberg gefilterde statussen",
|
"hide_filtered_statuses": "Gefilterde statussen verbergen",
|
||||||
"import_blocks_from_a_csv_file": "Importeer geblokkeerde gebruikers van een csv bestand",
|
"import_blocks_from_a_csv_file": "Importeer blokkades van een csv bestand",
|
||||||
"mutes_tab": "Gedempte gebruikers",
|
"mutes_tab": "Negeringen",
|
||||||
"play_videos_in_modal": "Speel video's af in een popup frame",
|
"play_videos_in_modal": "Speel video's af in een popup frame",
|
||||||
"new_email": "Nieuwe Email",
|
"new_email": "Nieuwe Email",
|
||||||
"notification_visibility_emoji_reactions": "Reacties",
|
"notification_visibility_emoji_reactions": "Reacties",
|
||||||
"no_blocks": "Geen geblokkeerde gebruikers",
|
"no_blocks": "Geen blokkades",
|
||||||
"no_mutes": "Geen gedempte gebruikers",
|
"no_mutes": "Geen negeringen",
|
||||||
"hide_followers_description": "Niet tonen wie mij volgt",
|
"hide_followers_description": "Niet tonen wie mij volgt",
|
||||||
"hide_followers_count_description": "Niet mijn volgers aantal tonen",
|
"hide_followers_count_description": "Niet mijn volgers aantal tonen",
|
||||||
"hide_follows_count_description": "Niet mijn gevolgde aantal tonen",
|
"hide_follows_count_description": "Niet mijn gevolgde aantal tonen",
|
||||||
"show_admin_badge": "Admin badge tonen in mijn profiel",
|
"show_admin_badge": "Beheerders badge tonen in mijn profiel",
|
||||||
"autohide_floating_post_button": "Nieuw Bericht knop automatisch verbergen (mobiel)",
|
"autohide_floating_post_button": "Nieuw Bericht knop automatisch verbergen (mobiel)",
|
||||||
"search_user_to_block": "Zoek wie je wilt blokkeren",
|
"search_user_to_block": "Zoek wie je wilt blokkeren",
|
||||||
"search_user_to_mute": "Zoek wie je wilt dempen",
|
"search_user_to_mute": "Zoek wie je wilt negeren",
|
||||||
"minimal_scopes_mode": "Bericht bereik-opties minimaliseren",
|
"minimal_scopes_mode": "Bericht bereik-opties minimaliseren",
|
||||||
"post_status_content_type": "Bericht status content type",
|
"post_status_content_type": "Bericht status content type",
|
||||||
"user_mutes": "Gebruikers",
|
"user_mutes": "Gebruikers",
|
||||||
"useStreamingApi": "Berichten en notificatie in real-time ontvangen",
|
"useStreamingApi": "Berichten en meldingen in real-time ontvangen",
|
||||||
"useStreamingApiWarning": "(Afgeraden, experimenteel, kan berichten overslaan)",
|
"useStreamingApiWarning": "(Afgeraden, experimenteel, kan berichten overslaan)",
|
||||||
"type_domains_to_mute": "Voer domeinen in om te dempen",
|
"type_domains_to_mute": "Voer domeinen in om te negeren",
|
||||||
"upload_a_photo": "Upload een foto",
|
"upload_a_photo": "Upload een foto",
|
||||||
"fun": "Plezier",
|
"fun": "Plezier",
|
||||||
"greentext": "Meme pijlen",
|
"greentext": "Meme pijlen",
|
||||||
"notification_setting": "Ontvang notificaties van:",
|
"notification_setting": "Ontvang meldingen van:",
|
||||||
"block_export_button": "Exporteer je geblokkeerde gebruikers naar een csv bestand",
|
"block_export_button": "Exporteer je geblokkeerde gebruikers naar een csv bestand",
|
||||||
"block_import_error": "Fout bij importeren geblokkeerde gebruikers",
|
"block_import_error": "Fout bij importeren blokkades",
|
||||||
"discoverable": "Sta toe dat dit account ontdekt kan worden in zoekresultaten en andere diensten",
|
"discoverable": "Sta toe dat dit account ontdekt kan worden in zoekresultaten en andere diensten",
|
||||||
"use_contain_fit": "Bijlage in miniaturen niet bijsnijden",
|
"use_contain_fit": "Snij bijlage in miniaturen niet bij",
|
||||||
"notification_visibility_moves": "Gebruiker Migraties",
|
"notification_visibility_moves": "Gebruiker Migraties",
|
||||||
"hide_follows_description": "Niet tonen wie ik volg",
|
"hide_follows_description": "Niet tonen wie ik volg",
|
||||||
"show_moderator_badge": "Moderator badge tonen in mijn profiel",
|
"show_moderator_badge": "Moderators badge tonen in mijn profiel",
|
||||||
"notification_setting_filters": "Filters",
|
"notification_setting_filters": "Filters",
|
||||||
"notification_setting_non_followers": "Gebruikers die je niet volgen",
|
"notification_setting_non_followers": "Gebruikers die je niet volgen",
|
||||||
"notification_blocks": "Door een gebruiker te blokkeren, ontvang je geen notificaties meer van de gebruiker en wordt je abonnement op de gebruiker opgeheven."
|
"notification_blocks": "Door een gebruiker te blokkeren, ontvang je geen meldingen meer van de gebruiker en wordt je abonnement op de gebruiker opgeheven.",
|
||||||
|
"version": {
|
||||||
|
"frontend_version": "Frontend Versie",
|
||||||
|
"backend_version": "Backend Versie",
|
||||||
|
"title": "Versie"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"timeline": {
|
"timeline": {
|
||||||
"collapse": "Inklappen",
|
"collapse": "Inklappen",
|
||||||
"conversation": "Conversatie",
|
"conversation": "Conversatie",
|
||||||
"error_fetching": "Fout bij ophalen van updates",
|
"error_fetching": "Fout bij ophalen van updates",
|
||||||
"load_older": "Laad oudere Statussen",
|
"load_older": "Oudere statussen laden",
|
||||||
"no_retweet_hint": "Post is gemarkeerd als enkel volgers of direct en kan niet worden herhaald",
|
"no_retweet_hint": "Bericht is gemarkeerd als enkel volgers of direct en kan niet worden herhaald",
|
||||||
"repeated": "herhaalde",
|
"repeated": "herhaalde",
|
||||||
"show_new": "Toon nieuwe",
|
"show_new": "Nieuwe tonen",
|
||||||
"up_to_date": "Up-to-date"
|
"up_to_date": "Up-to-date",
|
||||||
|
"no_statuses": "Geen statussen",
|
||||||
|
"no_more_statuses": "Geen statussen meer"
|
||||||
},
|
},
|
||||||
"user_card": {
|
"user_card": {
|
||||||
"approve": "Goedkeuren",
|
"approve": "Goedkeuren",
|
||||||
"block": "Blokkeren",
|
"block": "Blokkeren",
|
||||||
"blocked": "Geblokkeerd!",
|
"blocked": "Geblokkeerd!",
|
||||||
"deny": "Ontzeggen",
|
"deny": "Weigeren",
|
||||||
"favorites": "Vind-ik-leuks",
|
"favorites": "Favorieten",
|
||||||
"follow": "Volgen",
|
"follow": "Volgen",
|
||||||
"follow_sent": "Aanvraag verzonden!",
|
"follow_sent": "Aanvraag verzonden!",
|
||||||
"follow_progress": "Aanvragen…",
|
"follow_progress": "Aanvragen…",
|
||||||
|
|
@ -471,31 +500,69 @@
|
||||||
"following": "Aan het volgen!",
|
"following": "Aan het volgen!",
|
||||||
"follows_you": "Volgt jou!",
|
"follows_you": "Volgt jou!",
|
||||||
"its_you": "'t is jij!",
|
"its_you": "'t is jij!",
|
||||||
"mute": "Dempen",
|
"mute": "Negeren",
|
||||||
"muted": "Gedempt",
|
"muted": "Genegeerd",
|
||||||
"per_day": "per dag",
|
"per_day": "per dag",
|
||||||
"remote_follow": "Volg vanop afstand",
|
"remote_follow": "Volg vanop afstand",
|
||||||
"statuses": "Statussen"
|
"statuses": "Statussen",
|
||||||
|
"admin_menu": {
|
||||||
|
"delete_user_confirmation": "Weet je het heel zeker? Deze uitvoering kan niet ongedaan worden gemaakt.",
|
||||||
|
"delete_user": "Gebruiker verwijderen",
|
||||||
|
"quarantine": "Federeren van gebruikers berichten verbieden",
|
||||||
|
"disable_any_subscription": "Volgen van gebruiker in zijn geheel verbieden",
|
||||||
|
"disable_remote_subscription": "Volgen van gebruiker vanaf andere instanties verbieden",
|
||||||
|
"sandbox": "Berichten forceren om alleen voor volgers zichtbaar te zijn",
|
||||||
|
"force_unlisted": "Berichten forceren om niet publiekelijk getoond te worden",
|
||||||
|
"strip_media": "Media van berichten verwijderen",
|
||||||
|
"force_nsfw": "Alle berichten als gevoelig markeren",
|
||||||
|
"delete_account": "Account verwijderen",
|
||||||
|
"deactivate_account": "Account deactiveren",
|
||||||
|
"activate_account": "Account activeren",
|
||||||
|
"revoke_moderator": "Moderatorsrechten intrekken",
|
||||||
|
"grant_moderator": "Moderatorsrechten toekennen",
|
||||||
|
"revoke_admin": "Beheerdersrechten intrekken",
|
||||||
|
"grant_admin": "Beheerdersrechten toekennen",
|
||||||
|
"moderation": "Moderatie"
|
||||||
|
},
|
||||||
|
"show_repeats": "Herhalingen tonen",
|
||||||
|
"hide_repeats": "Herhalingen verbergen",
|
||||||
|
"mute_progress": "Negeren…",
|
||||||
|
"unmute_progress": "Negering opheffen…",
|
||||||
|
"unmute": "Negering opheffen",
|
||||||
|
"block_progress": "Blokkeren…",
|
||||||
|
"unblock_progress": "Blokkade opheffen…",
|
||||||
|
"unblock": "Blokkade opheffen",
|
||||||
|
"unsubscribe": "Abonnement opzeggen",
|
||||||
|
"subscribe": "Abonneren",
|
||||||
|
"report": "Aangeven",
|
||||||
|
"mention": "Vermelding",
|
||||||
|
"media": "Media",
|
||||||
|
"hidden": "Verborgen"
|
||||||
},
|
},
|
||||||
"user_profile": {
|
"user_profile": {
|
||||||
"timeline_title": "Gebruikers Tijdlijn"
|
"timeline_title": "Gebruikers Tijdlijn",
|
||||||
|
"profile_loading_error": "Sorry, er is een fout opgetreden bij het laden van dit profiel.",
|
||||||
|
"profile_does_not_exist": "Sorry, dit profiel bestaat niet."
|
||||||
},
|
},
|
||||||
"who_to_follow": {
|
"who_to_follow": {
|
||||||
"more": "Meer",
|
"more": "Meer",
|
||||||
"who_to_follow": "Wie te volgen"
|
"who_to_follow": "Wie te volgen"
|
||||||
},
|
},
|
||||||
"tool_tip": {
|
"tool_tip": {
|
||||||
"media_upload": "Upload Media",
|
"media_upload": "Media Uploaden",
|
||||||
"repeat": "Herhaal",
|
"repeat": "Herhalen",
|
||||||
"reply": "Antwoord",
|
"reply": "Beantwoorden",
|
||||||
"favorite": "Vind-ik-leuk",
|
"favorite": "Favoriet maken",
|
||||||
"user_settings": "Gebruikers Instellingen"
|
"user_settings": "Gebruikers Instellingen",
|
||||||
|
"reject_follow_request": "Volg-verzoek afwijzen",
|
||||||
|
"accept_follow_request": "Volg-aanvraag accepteren",
|
||||||
|
"add_reaction": "Reactie toevoegen"
|
||||||
},
|
},
|
||||||
"upload": {
|
"upload": {
|
||||||
"error": {
|
"error": {
|
||||||
"base": "Upload gefaald.",
|
"base": "Upload mislukt.",
|
||||||
"file_too_big": "Bestand is te groot [{filesize}{filesizeunit} / {allowedsize}{allowedsizeunit}]",
|
"file_too_big": "Bestand is te groot [{filesize}{filesizeunit} / {allowedsize}{allowedsizeunit}]",
|
||||||
"default": "Probeer later opnieuw"
|
"default": "Probeer het later opnieuw"
|
||||||
},
|
},
|
||||||
"file_size_units": {
|
"file_size_units": {
|
||||||
"B": "B",
|
"B": "B",
|
||||||
|
|
@ -512,7 +579,8 @@
|
||||||
"reject": "Afwijzen",
|
"reject": "Afwijzen",
|
||||||
"replace": "Vervangen",
|
"replace": "Vervangen",
|
||||||
"is_replaced_by": "→",
|
"is_replaced_by": "→",
|
||||||
"keyword_policies": "Zoekwoord Beleid"
|
"keyword_policies": "Zoekwoord Beleid",
|
||||||
|
"ftl_removal": "Verwijdering van \"Het Geheel Bekende Netwerk\" Tijdlijn"
|
||||||
},
|
},
|
||||||
"mrf_policies_desc": "MRF regels beïnvloeden het federatie gedrag van de instantie. De volgende regels zijn ingeschakeld:",
|
"mrf_policies_desc": "MRF regels beïnvloeden het federatie gedrag van de instantie. De volgende regels zijn ingeschakeld:",
|
||||||
"mrf_policies": "Ingeschakelde MRF Regels",
|
"mrf_policies": "Ingeschakelde MRF Regels",
|
||||||
|
|
@ -524,20 +592,21 @@
|
||||||
"reject_desc": "Deze instantie zal geen berichten accepteren van de volgende instanties:",
|
"reject_desc": "Deze instantie zal geen berichten accepteren van de volgende instanties:",
|
||||||
"quarantine": "Quarantaine",
|
"quarantine": "Quarantaine",
|
||||||
"quarantine_desc": "Deze instantie zal alleen publieke berichten sturen naar de volgende instanties:",
|
"quarantine_desc": "Deze instantie zal alleen publieke berichten sturen naar de volgende instanties:",
|
||||||
"ftl_removal_desc": "Deze instantie verwijdert de volgende instanties van \"Het Geheel Gekende Netwerk\" tijdlijn:",
|
"ftl_removal_desc": "Deze instantie verwijdert de volgende instanties van \"Het Geheel Bekende Netwerk\" tijdlijn:",
|
||||||
"media_removal_desc": "Deze instantie verwijdert media van berichten van de volgende instanties:",
|
"media_removal_desc": "Deze instantie verwijdert media van berichten van de volgende instanties:",
|
||||||
"media_nsfw_desc": "Deze instantie stelt media in als gevoelig in berichten van de volgende instanties:",
|
"media_nsfw_desc": "Deze instantie stelt media in als gevoelig in berichten van de volgende instanties:",
|
||||||
"ftl_removal": "Verwijderen van \"Het Geheel Bekende Netwerk\" Tijdlijn",
|
"ftl_removal": "Verwijderen van \"Het Geheel Bekende Netwerk\" Tijdlijn",
|
||||||
"media_removal": "Media Verwijdering"
|
"media_removal": "Media Verwijdering",
|
||||||
|
"media_nsfw": "Forceer Media als Gevoelig"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"staff": "Personeel"
|
"staff": "Personeel"
|
||||||
},
|
},
|
||||||
"domain_mute_card": {
|
"domain_mute_card": {
|
||||||
"mute": "Dempen",
|
"mute": "Negeren",
|
||||||
"mute_progress": "Dempen...",
|
"mute_progress": "Negeren…",
|
||||||
"unmute": "Dempen opheffen",
|
"unmute": "Negering opheffen",
|
||||||
"unmute_progress": "Dempen wordt opgeheven..."
|
"unmute_progress": "Negering wordt opgeheven…"
|
||||||
},
|
},
|
||||||
"exporter": {
|
"exporter": {
|
||||||
"export": "Exporteren",
|
"export": "Exporteren",
|
||||||
|
|
@ -564,7 +633,7 @@
|
||||||
"option": "Optie",
|
"option": "Optie",
|
||||||
"votes": "stemmen",
|
"votes": "stemmen",
|
||||||
"vote": "Stem",
|
"vote": "Stem",
|
||||||
"single_choice": "Enkelkeuze",
|
"single_choice": "Enkele keuze",
|
||||||
"multiple_choices": "Meerkeuze",
|
"multiple_choices": "Meerkeuze",
|
||||||
"expiry": "Poll leeftijd",
|
"expiry": "Poll leeftijd",
|
||||||
"expires_in": "Poll eindigt in {0}",
|
"expires_in": "Poll eindigt in {0}",
|
||||||
|
|
@ -574,25 +643,105 @@
|
||||||
},
|
},
|
||||||
"emoji": {
|
"emoji": {
|
||||||
"emoji": "Emoji",
|
"emoji": "Emoji",
|
||||||
"keep_open": "Houdt picker open",
|
"keep_open": "Picker openhouden",
|
||||||
"search_emoji": "Zoek voor een emoji",
|
"search_emoji": "Zoek voor een emoji",
|
||||||
"add_emoji": "Emoji invoegen",
|
"add_emoji": "Emoji invoegen",
|
||||||
"unicode": "Unicode emoji",
|
"unicode": "Unicode emoji",
|
||||||
"load_all": "Alle {emojiAmount} emoji worden geladen",
|
"load_all": "Alle {emojiAmount} emoji worden geladen",
|
||||||
"stickers": "Stickers",
|
"stickers": "Stickers",
|
||||||
"load_all_hint": "Eerste {saneAmount} emoji geladen, alle emoji tegelijk laden kan prestatie problemen veroorzaken."
|
"load_all_hint": "Eerste {saneAmount} emoji geladen, alle emoji tegelijk laden kan problemen veroorzaken met prestaties.",
|
||||||
|
"custom": "Gepersonaliseerde emoji"
|
||||||
},
|
},
|
||||||
"interactions": {
|
"interactions": {
|
||||||
"favs_repeats": "Herhalingen en Favorieten",
|
"favs_repeats": "Herhalingen en Favorieten",
|
||||||
"follows": "Nieuwe volgers",
|
"follows": "Nieuwe volgingen",
|
||||||
"moves": "Gebruiker migreert",
|
"moves": "Gebruiker migreert",
|
||||||
"load_older": "Oudere interacties laden"
|
"load_older": "Oudere interacties laden"
|
||||||
},
|
},
|
||||||
"remote_user_resolver": {
|
"remote_user_resolver": {
|
||||||
"searching_for": "Zoeken naar",
|
"searching_for": "Zoeken naar",
|
||||||
"error": "Niet gevonden."
|
"error": "Niet gevonden.",
|
||||||
|
"remote_user_resolver": "Externe gebruikers zoeker"
|
||||||
},
|
},
|
||||||
"selectable_list": {
|
"selectable_list": {
|
||||||
"select_all": "Alles selecteren"
|
"select_all": "Alles selecteren"
|
||||||
|
},
|
||||||
|
"password_reset": {
|
||||||
|
"password_reset_required_but_mailer_is_disabled": "Je dient je wachtwoord opnieuw in te stellen, maar wachtwoord reset is uitgeschakeld. Neem contact op met de beheerder van deze instantie.",
|
||||||
|
"password_reset_required": "Je dient je wachtwoord opnieuw in te stellen om in te kunnen loggen.",
|
||||||
|
"password_reset_disabled": "Wachtwoord reset is uitgeschakeld. Neem contact op met de beheerder van deze instantie.",
|
||||||
|
"too_many_requests": "Je hebt het maximaal aantal pogingen bereikt, probeer het later opnieuw.",
|
||||||
|
"not_found": "We kunnen die email of gebruikersnaam niet vinden.",
|
||||||
|
"return_home": "Terugkeren naar de home pagina",
|
||||||
|
"check_email": "Controleer je email inbox voor een link om je wachtwoord opnieuw in te stellen.",
|
||||||
|
"placeholder": "Je email of gebruikersnaam",
|
||||||
|
"instruction": "Voer je email adres of gebruikersnaam in. We sturen je een link om je wachtwoord opnieuw in te stellen.",
|
||||||
|
"password_reset": "Wachtwoord opnieuw instellen",
|
||||||
|
"forgot_password": "Wachtwoord vergeten?"
|
||||||
|
},
|
||||||
|
"search": {
|
||||||
|
"no_results": "Geen resultaten",
|
||||||
|
"people_talking": "{count} personen aan het praten",
|
||||||
|
"person_talking": "{count} persoon aan het praten",
|
||||||
|
"hashtags": "Hashtags",
|
||||||
|
"people": "Personen"
|
||||||
|
},
|
||||||
|
"user_reporting": {
|
||||||
|
"generic_error": "Er is een fout opgetreden tijdens het verwerken van je verzoek.",
|
||||||
|
"submit": "Verzenden",
|
||||||
|
"forward_to": "Doorsturen naar {0}",
|
||||||
|
"forward_description": "Dit account hoort bij een andere server. Wil je een kopie van het rapport ook daarheen sturen?",
|
||||||
|
"additional_comments": "Aanvullende opmerkingen",
|
||||||
|
"add_comment_description": "Het rapport zal naar de moderators van de instantie worden verstuurd. Je kunt hieronder uitleg bijvoegen waarom je dit account wilt aangeven:",
|
||||||
|
"title": "{0} aangeven"
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"copy_link": "Link naar status kopiëren",
|
||||||
|
"status_unavailable": "Status niet beschikbaar",
|
||||||
|
"unmute_conversation": "Conversatie niet meer negeren",
|
||||||
|
"mute_conversation": "Conversatie negeren",
|
||||||
|
"replies_list": "Antwoorden:",
|
||||||
|
"reply_to": "Antwoorden aan",
|
||||||
|
"delete_confirm": "Wil je echt deze status verwijderen?",
|
||||||
|
"pin": "Aan profiel vastmaken",
|
||||||
|
"pinned": "Vastgezet",
|
||||||
|
"unpin": "Van profiel losmaken",
|
||||||
|
"delete": "Status verwijderen",
|
||||||
|
"repeats": "Herhalingen",
|
||||||
|
"favorites": "Favorieten"
|
||||||
|
},
|
||||||
|
"time": {
|
||||||
|
"years_short": "{0}j",
|
||||||
|
"year_short": "{0}j",
|
||||||
|
"years": "{0} jaren",
|
||||||
|
"year": "{0} jaar",
|
||||||
|
"weeks_short": "{0}w",
|
||||||
|
"week_short": "{0}w",
|
||||||
|
"weeks": "{0} weken",
|
||||||
|
"week": "{0} week",
|
||||||
|
"seconds_short": "{0}s",
|
||||||
|
"second_short": "{0}s",
|
||||||
|
"seconds": "{0} seconden",
|
||||||
|
"second": "{0} seconde",
|
||||||
|
"now_short": "nu",
|
||||||
|
"now": "zojuist",
|
||||||
|
"months_short": "{0}ma",
|
||||||
|
"month_short": "{0}ma",
|
||||||
|
"months": "{0} maanden",
|
||||||
|
"month": "{0} maand",
|
||||||
|
"minutes_short": "{0}min",
|
||||||
|
"minute_short": "{0}min",
|
||||||
|
"minutes": "{0} minuten",
|
||||||
|
"minute": "{0} minuut",
|
||||||
|
"in_past": "{0} geleden",
|
||||||
|
"in_future": "over {0}",
|
||||||
|
"hours_short": "{0}u",
|
||||||
|
"hour_short": "{0}u",
|
||||||
|
"hours": "{0} uren",
|
||||||
|
"hour": "{0} uur",
|
||||||
|
"days_short": "{0}d",
|
||||||
|
"day_short": "{0}d",
|
||||||
|
"days": "{0} dagen",
|
||||||
|
"day": "{0} dag"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@
|
||||||
"media_nsfw_desc": "Ta instancja wymusza, by multimedia z wymienionych instancji były ustawione jako wrażliwe:"
|
"media_nsfw_desc": "Ta instancja wymusza, by multimedia z wymienionych instancji były ustawione jako wrażliwe:"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"staff": "Obsługa"
|
"staff": "Administracja"
|
||||||
},
|
},
|
||||||
"chat": {
|
"chat": {
|
||||||
"title": "Czat"
|
"title": "Czat"
|
||||||
|
|
@ -40,7 +40,7 @@
|
||||||
},
|
},
|
||||||
"exporter": {
|
"exporter": {
|
||||||
"export": "Eksportuj",
|
"export": "Eksportuj",
|
||||||
"processing": "Przetwarzam, za chwilę zostaniesz zapytany o ściągnięcie pliku"
|
"processing": "Przetwarzam, za chwilę zostaniesz zapytany(-na) o ściągnięcie pliku"
|
||||||
},
|
},
|
||||||
"features_panel": {
|
"features_panel": {
|
||||||
"chat": "Czat",
|
"chat": "Czat",
|
||||||
|
|
@ -131,7 +131,7 @@
|
||||||
"no_more_notifications": "Nie masz więcej powiadomień",
|
"no_more_notifications": "Nie masz więcej powiadomień",
|
||||||
"migrated_to": "wyemigrował do",
|
"migrated_to": "wyemigrował do",
|
||||||
"reacted_with": "zareagował z {0}",
|
"reacted_with": "zareagował z {0}",
|
||||||
"follow_request": "chce cię obserwować"
|
"follow_request": "chce ciebie obserwować"
|
||||||
},
|
},
|
||||||
"polls": {
|
"polls": {
|
||||||
"add_poll": "Dodaj ankietę",
|
"add_poll": "Dodaj ankietę",
|
||||||
|
|
@ -232,10 +232,10 @@
|
||||||
"confirm_and_enable": "Potwierdź i włącz OTP",
|
"confirm_and_enable": "Potwierdź i włącz OTP",
|
||||||
"title": "Weryfikacja dwuetapowa",
|
"title": "Weryfikacja dwuetapowa",
|
||||||
"generate_new_recovery_codes": "Wygeneruj nowe kody zapasowe",
|
"generate_new_recovery_codes": "Wygeneruj nowe kody zapasowe",
|
||||||
"warning_of_generate_new_codes": "Po tym gdy generujesz nowe kody zapasowe, stare przestaną działać.",
|
"warning_of_generate_new_codes": "Po tym gdy wygenerujesz nowe kody zapasowe, stare przestaną działać.",
|
||||||
"recovery_codes": "Kody zapasowe.",
|
"recovery_codes": "Kody zapasowe.",
|
||||||
"waiting_a_recovery_codes": "Otrzymuję kody zapasowe...",
|
"waiting_a_recovery_codes": "Otrzymuję kody zapasowe...",
|
||||||
"recovery_codes_warning": "Spisz kody na kartce papieru, albo zapisz je w bezpiecznym miejscu - inaczej nie zobaczysz ich już nigdy. Jeśli stracisz dostęp do twojej aplikacji 2FA i kodów zapasowych, nie będziesz miał dostępu do swojego konta.",
|
"recovery_codes_warning": "Spisz kody na kartce papieru, albo zapisz je w bezpiecznym miejscu - inaczej nie zobaczysz ich już nigdy. Jeśli stracisz dostęp do twojej aplikacji 2FA i kodów zapasowych, nie będziesz miał(-a) dostępu do swojego konta.",
|
||||||
"authentication_methods": "Metody weryfikacji",
|
"authentication_methods": "Metody weryfikacji",
|
||||||
"scan": {
|
"scan": {
|
||||||
"title": "Skanuj",
|
"title": "Skanuj",
|
||||||
|
|
@ -281,7 +281,7 @@
|
||||||
"data_import_export_tab": "Import/eksport danych",
|
"data_import_export_tab": "Import/eksport danych",
|
||||||
"default_vis": "Domyślny zakres widoczności",
|
"default_vis": "Domyślny zakres widoczności",
|
||||||
"delete_account": "Usuń konto",
|
"delete_account": "Usuń konto",
|
||||||
"delete_account_description": "Trwale usuń konto i wszystkie posty.",
|
"delete_account_description": "Trwale usuń dane i zdezaktywuj konto.",
|
||||||
"delete_account_error": "Wystąpił problem z usuwaniem twojego konta. Jeżeli problem powtarza się, poinformuj administratora swojej instancji.",
|
"delete_account_error": "Wystąpił problem z usuwaniem twojego konta. Jeżeli problem powtarza się, poinformuj administratora swojej instancji.",
|
||||||
"delete_account_instructions": "Wprowadź swoje hasło w poniższe pole aby potwierdzić usunięcie konta.",
|
"delete_account_instructions": "Wprowadź swoje hasło w poniższe pole aby potwierdzić usunięcie konta.",
|
||||||
"discoverable": "Zezwól na odkrywanie tego konta w wynikach wyszukiwania i innych usługach",
|
"discoverable": "Zezwól na odkrywanie tego konta w wynikach wyszukiwania i innych usługach",
|
||||||
|
|
@ -315,14 +315,14 @@
|
||||||
"import_theme": "Załaduj motyw",
|
"import_theme": "Załaduj motyw",
|
||||||
"inputRadius": "Pola tekstowe",
|
"inputRadius": "Pola tekstowe",
|
||||||
"checkboxRadius": "Pola wyboru",
|
"checkboxRadius": "Pola wyboru",
|
||||||
"instance_default": "(domyślny: {value})",
|
"instance_default": "(domyślnie: {value})",
|
||||||
"instance_default_simple": "(domyślny)",
|
"instance_default_simple": "(domyślne)",
|
||||||
"interface": "Interfejs",
|
"interface": "Interfejs",
|
||||||
"interfaceLanguage": "Język interfejsu",
|
"interfaceLanguage": "Język interfejsu",
|
||||||
"invalid_theme_imported": "Wybrany plik nie jest obsługiwanym motywem Pleromy. Nie dokonano zmian w twoim motywie.",
|
"invalid_theme_imported": "Wybrany plik nie jest obsługiwanym motywem Pleromy. Nie dokonano zmian w twoim motywie.",
|
||||||
"limited_availability": "Niedostępne w twojej przeglądarce",
|
"limited_availability": "Niedostępne w twojej przeglądarce",
|
||||||
"links": "Łącza",
|
"links": "Łącza",
|
||||||
"lock_account_description": "Ogranicz swoje konto dla zatwierdzonych obserwowanych",
|
"lock_account_description": "Spraw, by konto mogli wyświetlać tylko zatwierdzeni obserwujący",
|
||||||
"loop_video": "Zapętlaj filmy",
|
"loop_video": "Zapętlaj filmy",
|
||||||
"loop_video_silent_only": "Zapętlaj tylko filmy bez dźwięku (np. mastodonowe „gify”)",
|
"loop_video_silent_only": "Zapętlaj tylko filmy bez dźwięku (np. mastodonowe „gify”)",
|
||||||
"mutes_tab": "Wyciszenia",
|
"mutes_tab": "Wyciszenia",
|
||||||
|
|
@ -420,7 +420,7 @@
|
||||||
"keep_opacity": "Zachowaj widoczność",
|
"keep_opacity": "Zachowaj widoczność",
|
||||||
"keep_roundness": "Zachowaj zaokrąglenie",
|
"keep_roundness": "Zachowaj zaokrąglenie",
|
||||||
"keep_fonts": "Zachowaj czcionki",
|
"keep_fonts": "Zachowaj czcionki",
|
||||||
"save_load_hint": "Opcje „zachowaj” pozwalają na pozostanie przy obecnych opcjach po wybraniu lub załadowaniu motywu, jak i przechowywanie ich podczas eksportowania motywu. Jeżeli wszystkie są odznaczone, eksportowanie motywu spowoduje zapisanie wszystkiego.",
|
"save_load_hint": "Opcje „zachowaj” pozwalają na pozostanie przy obecnych opcjach po wybraniu lub załadowaniu motywu, jak i przechowywanie ich podczas eksportowania motywu. Jeżeli wszystkie opcje są odznaczone, eksportowanie motywu spowoduje zapisanie wszystkiego.",
|
||||||
"reset": "Wyzeruj",
|
"reset": "Wyzeruj",
|
||||||
"clear_all": "Wyczyść wszystko",
|
"clear_all": "Wyczyść wszystko",
|
||||||
"clear_opacity": "Wyczyść widoczność",
|
"clear_opacity": "Wyczyść widoczność",
|
||||||
|
|
@ -429,17 +429,17 @@
|
||||||
"use_snapshot": "Stara wersja",
|
"use_snapshot": "Stara wersja",
|
||||||
"use_source": "Nowa wersja",
|
"use_source": "Nowa wersja",
|
||||||
"help": {
|
"help": {
|
||||||
"upgraded_from_v2": "PleromaFE zostało zaaktualizowane, motyw może wyglądać nieco inaczej niż sobie zapamiętałeś.",
|
"upgraded_from_v2": "PleromaFE zostało zaaktualizowane, motyw może wyglądać nieco inaczej niż zapamiętałeś(-aś).",
|
||||||
"v2_imported": "Plik który zaimportowałeś został stworzony dla starszego FE. Próbujemy zwiększyć kompatybiliność, lecz wciąż mogą występować rozbieżności.",
|
"v2_imported": "Plik który zaimportowałeś(-aś) został stworzony dla starszego FE. Próbujemy zwiększyć kompatybilność, lecz wciąż mogą występować rozbieżności.",
|
||||||
"future_version_imported": "Plik który zaimportowałeś został stworzony w nowszej wersji FE.",
|
"future_version_imported": "Plik który zaimportowałeś(-aś) został stworzony w nowszej wersji FE.",
|
||||||
"older_version_imported": "Plik który zaimportowałeś został stworzony w starszej wersji FE.",
|
"older_version_imported": "Plik który zaimportowałeś(-aś) został stworzony w starszej wersji FE.",
|
||||||
"snapshot_present": "Migawka motywu jest załadowana, więc wszystkie wartości zostały nadpisane. Zamiast tego możesz załadować właściwe dane motywu.",
|
"snapshot_present": "Migawka motywu jest załadowana, więc wszystkie wartości zostały nadpisane. Zamiast tego możesz załadować właściwe dane motywu.",
|
||||||
"snapshot_missing": "Nie znaleziono migawki motywu w pliku, więc motyw może wyglądać inaczej niż pierwotnie zaplanowano.",
|
"snapshot_missing": "Nie znaleziono migawki motywu w pliku, więc motyw może wyglądać inaczej niż pierwotnie zaplanowano.",
|
||||||
"fe_upgraded": "Silnik motywów PleromaFE został zaaktualizowany.",
|
"fe_upgraded": "Silnik motywów PleromaFE został zaaktualizowany.",
|
||||||
"fe_downgraded": "Wersja PleromaFE została cofnięta.",
|
"fe_downgraded": "Wersja PleromaFE została cofnięta.",
|
||||||
"migration_snapshot_ok": "Żeby być bezpiecznym, migawka motywu została załadowana. Możesz spróbować załadować dane motywu.",
|
"migration_snapshot_ok": "Żeby być bezpiecznym, migawka motywu została załadowana. Możesz spróbować załadować dane motywu.",
|
||||||
"migration_napshot_gone": "Z jakiegoś powodu migawka zniknęła, niektóre rzeczy mogą wyglądać inaczej niż sobie zapamiętałeś.",
|
"migration_napshot_gone": "Z jakiegoś powodu migawka zniknęła, niektóre rzeczy mogą wyglądać inaczej niż zapamiętałeś(-aś).",
|
||||||
"snapshot_source_mismatch": "Konflikt wersji: najprawdopodobniej FE zostało cofnięte do poprzedniej wersji i zaaktualizowane ponownie, jeśli zmieniłeś motyw używając starszej wersji FE, najprawdopodobniej chcesz używać starszej wersji, w przeciwnym razie użyj nowej wersji."
|
"snapshot_source_mismatch": "Konflikt wersji: najprawdopodobniej FE zostało cofnięte do poprzedniej wersji i zaktualizowane ponownie, jeśli zmieniłeś(-aś) motyw używając starszej wersji FE, najprawdopodobniej chcesz używać starszej wersji, w przeciwnym razie użyj nowej wersji."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"common": {
|
"common": {
|
||||||
|
|
@ -549,7 +549,7 @@
|
||||||
"faint_link": "pomocny podręcznik",
|
"faint_link": "pomocny podręcznik",
|
||||||
"fine_print": "Przeczytaj nasz {0}, aby nie nauczyć się niczego przydatnego!",
|
"fine_print": "Przeczytaj nasz {0}, aby nie nauczyć się niczego przydatnego!",
|
||||||
"header_faint": "W porządku",
|
"header_faint": "W porządku",
|
||||||
"checkbox": "Przeleciałem przez zasady użytkowania",
|
"checkbox": "Przeleciałem(-am) przez zasady użytkowania",
|
||||||
"link": "i fajny mały odnośnik"
|
"link": "i fajny mały odnośnik"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -646,7 +646,7 @@
|
||||||
"muted": "Wyciszony(-a)",
|
"muted": "Wyciszony(-a)",
|
||||||
"per_day": "dziennie",
|
"per_day": "dziennie",
|
||||||
"remote_follow": "Zdalna obserwacja",
|
"remote_follow": "Zdalna obserwacja",
|
||||||
"report": "Raportuj",
|
"report": "Zgłoś",
|
||||||
"statuses": "Statusy",
|
"statuses": "Statusy",
|
||||||
"subscribe": "Subskrybuj",
|
"subscribe": "Subskrybuj",
|
||||||
"unsubscribe": "Odsubskrybuj",
|
"unsubscribe": "Odsubskrybuj",
|
||||||
|
|
@ -675,7 +675,7 @@
|
||||||
"disable_any_subscription": "Zakaż całkowicie obserwowania użytkownika",
|
"disable_any_subscription": "Zakaż całkowicie obserwowania użytkownika",
|
||||||
"quarantine": "Zakaż federowania postów od tego użytkownika",
|
"quarantine": "Zakaż federowania postów od tego użytkownika",
|
||||||
"delete_user": "Usuń użytkownika",
|
"delete_user": "Usuń użytkownika",
|
||||||
"delete_user_confirmation": "Czy jesteś absolutnie pewny? Ta operacja nie może być cofnięta."
|
"delete_user_confirmation": "Czy jesteś absolutnie pewny(-a)? Ta operacja nie może być cofnięta."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"user_profile": {
|
"user_profile": {
|
||||||
|
|
@ -685,9 +685,9 @@
|
||||||
},
|
},
|
||||||
"user_reporting": {
|
"user_reporting": {
|
||||||
"title": "Raportowanie {0}",
|
"title": "Raportowanie {0}",
|
||||||
"add_comment_description": "Raport zostanie wysłany do moderatorów instancji. Możesz dodać powód dlaczego raportujesz to konto poniżej:",
|
"add_comment_description": "Zgłoszenie zostanie wysłane do moderatorów instancji. Możesz dodać powód dlaczego zgłaszasz owe konto poniżej:",
|
||||||
"additional_comments": "Dodatkowe komentarze",
|
"additional_comments": "Dodatkowe komentarze",
|
||||||
"forward_description": "To konto jest z innego serwera. Wysłać również tam kopię raportu?",
|
"forward_description": "To konto jest z innego serwera. Wysłać również tam kopię zgłoszenia?",
|
||||||
"forward_to": "Przekaż do {0}",
|
"forward_to": "Przekaż do {0}",
|
||||||
"submit": "Wyślij",
|
"submit": "Wyślij",
|
||||||
"generic_error": "Wystąpił błąd podczas przetwarzania twojej prośby."
|
"generic_error": "Wystąpił błąd podczas przetwarzania twojej prośby."
|
||||||
|
|
@ -728,14 +728,14 @@
|
||||||
"no_results": "Brak wyników"
|
"no_results": "Brak wyników"
|
||||||
},
|
},
|
||||||
"password_reset": {
|
"password_reset": {
|
||||||
"forgot_password": "Zapomniałeś hasła?",
|
"forgot_password": "Zapomniałeś(-aś) hasła?",
|
||||||
"password_reset": "Reset hasła",
|
"password_reset": "Reset hasła",
|
||||||
"instruction": "Wprowadź swój adres email lub nazwę użytkownika. Wyślemy ci link z którym możesz zresetować hasło.",
|
"instruction": "Wprowadź swój adres email lub nazwę użytkownika. Wyślemy ci link z którym możesz zresetować hasło.",
|
||||||
"placeholder": "Twój email lub nazwa użytkownika",
|
"placeholder": "Twój email lub nazwa użytkownika",
|
||||||
"check_email": "Sprawdź pocztę, aby uzyskać link do zresetowania hasła.",
|
"check_email": "Sprawdź pocztę, aby uzyskać link do zresetowania hasła.",
|
||||||
"return_home": "Wróć do strony głównej",
|
"return_home": "Wróć do strony głównej",
|
||||||
"not_found": "Nie mogliśmy znaleźć tego emaila lub nazwy użytkownika.",
|
"not_found": "Nie mogliśmy znaleźć tego emaila lub nazwy użytkownika.",
|
||||||
"too_many_requests": "Przekroczyłeś limit prób, spróbuj ponownie później.",
|
"too_many_requests": "Przekroczyłeś(-aś) limit prób, spróbuj ponownie później.",
|
||||||
"password_reset_disabled": "Resetowanie hasła jest wyłączone. Proszę skontaktuj się z administratorem tej instancji.",
|
"password_reset_disabled": "Resetowanie hasła jest wyłączone. Proszę skontaktuj się z administratorem tej instancji.",
|
||||||
"password_reset_required": "Musisz zresetować hasło, by się zalogować.",
|
"password_reset_required": "Musisz zresetować hasło, by się zalogować.",
|
||||||
"password_reset_required_but_mailer_is_disabled": "Musisz zresetować hasło, ale resetowanie hasła jest wyłączone. Proszę skontaktuj się z administratorem tej instancji."
|
"password_reset_required_but_mailer_is_disabled": "Musisz zresetować hasło, ale resetowanie hasła jest wyłączone. Proszę skontaktuj się z administratorem tej instancji."
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,9 @@
|
||||||
"verify": "Проверить",
|
"verify": "Проверить",
|
||||||
"more": "Больше",
|
"more": "Больше",
|
||||||
"generic_error": "Произошла ошибка",
|
"generic_error": "Произошла ошибка",
|
||||||
"optional": "не обязательно"
|
"optional": "не обязательно",
|
||||||
|
"show_less": "Показать меньше",
|
||||||
|
"show_more": "Показать больше"
|
||||||
},
|
},
|
||||||
"login": {
|
"login": {
|
||||||
"login": "Войти",
|
"login": "Войти",
|
||||||
|
|
@ -454,9 +456,9 @@
|
||||||
},
|
},
|
||||||
"domain_mute_card": {
|
"domain_mute_card": {
|
||||||
"mute": "Игнорировать",
|
"mute": "Игнорировать",
|
||||||
"mute_progress": "В процессе...",
|
"mute_progress": "В процессе…",
|
||||||
"unmute": "Прекратить игнорирование",
|
"unmute": "Прекратить игнорирование",
|
||||||
"unmute_progress": "В процессе..."
|
"unmute_progress": "В процессе…"
|
||||||
},
|
},
|
||||||
"exporter": {
|
"exporter": {
|
||||||
"export": "Экспорт",
|
"export": "Экспорт",
|
||||||
|
|
|
||||||
117
src/i18n/zh.json
117
src/i18n/zh.json
|
|
@ -25,13 +25,14 @@
|
||||||
"more": "更多",
|
"more": "更多",
|
||||||
"generic_error": "发生一个错误",
|
"generic_error": "发生一个错误",
|
||||||
"optional": "可选项",
|
"optional": "可选项",
|
||||||
"show_more": "显示更多",
|
"show_more": "展开",
|
||||||
"show_less": "显示更少",
|
"show_less": "收起",
|
||||||
"cancel": "取消",
|
"cancel": "取消",
|
||||||
"disable": "禁用",
|
"disable": "禁用",
|
||||||
"enable": "启用",
|
"enable": "启用",
|
||||||
"confirm": "确认",
|
"confirm": "确认",
|
||||||
"verify": "验证"
|
"verify": "验证",
|
||||||
|
"dismiss": "忽略"
|
||||||
},
|
},
|
||||||
"image_cropper": {
|
"image_cropper": {
|
||||||
"crop_picture": "裁剪图片",
|
"crop_picture": "裁剪图片",
|
||||||
|
|
@ -68,8 +69,8 @@
|
||||||
},
|
},
|
||||||
"nav": {
|
"nav": {
|
||||||
"about": "关于",
|
"about": "关于",
|
||||||
"back": "Back",
|
"back": "后退",
|
||||||
"chat": "本地聊天",
|
"chat": "本站聊天",
|
||||||
"friend_requests": "关注请求",
|
"friend_requests": "关注请求",
|
||||||
"mentions": "提及",
|
"mentions": "提及",
|
||||||
"interactions": "互动",
|
"interactions": "互动",
|
||||||
|
|
@ -80,7 +81,8 @@
|
||||||
"user_search": "用户搜索",
|
"user_search": "用户搜索",
|
||||||
"search": "搜索",
|
"search": "搜索",
|
||||||
"who_to_follow": "推荐关注",
|
"who_to_follow": "推荐关注",
|
||||||
"preferences": "偏好设置"
|
"preferences": "偏好设置",
|
||||||
|
"administration": "管理员"
|
||||||
},
|
},
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"broken_favorite": "未知的状态,正在搜索中...",
|
"broken_favorite": "未知的状态,正在搜索中...",
|
||||||
|
|
@ -90,7 +92,10 @@
|
||||||
"notifications": "通知",
|
"notifications": "通知",
|
||||||
"read": "阅读!",
|
"read": "阅读!",
|
||||||
"repeated_you": "转发了你的状态",
|
"repeated_you": "转发了你的状态",
|
||||||
"no_more_notifications": "没有更多的通知"
|
"no_more_notifications": "没有更多的通知",
|
||||||
|
"reacted_with": "和 {0} 互动过",
|
||||||
|
"migrated_to": "迁移到",
|
||||||
|
"follow_request": "想要关注你"
|
||||||
},
|
},
|
||||||
"polls": {
|
"polls": {
|
||||||
"add_poll": "增加问卷调查",
|
"add_poll": "增加问卷调查",
|
||||||
|
|
@ -112,7 +117,8 @@
|
||||||
"interactions": {
|
"interactions": {
|
||||||
"favs_repeats": "转发和收藏",
|
"favs_repeats": "转发和收藏",
|
||||||
"follows": "新的关注者",
|
"follows": "新的关注者",
|
||||||
"load_older": "加载更早的互动"
|
"load_older": "加载更早的互动",
|
||||||
|
"moves": "用户迁移"
|
||||||
},
|
},
|
||||||
"post_status": {
|
"post_status": {
|
||||||
"new_status": "发布新状态",
|
"new_status": "发布新状态",
|
||||||
|
|
@ -152,8 +158,8 @@
|
||||||
"captcha": "CAPTCHA",
|
"captcha": "CAPTCHA",
|
||||||
"new_captcha": "点击图片获取新的验证码",
|
"new_captcha": "点击图片获取新的验证码",
|
||||||
"username_placeholder": "例如:lain",
|
"username_placeholder": "例如:lain",
|
||||||
"fullname_placeholder": "例如: Lain Iwakura",
|
"fullname_placeholder": "例如:岩仓玲音",
|
||||||
"bio_placeholder": "例如:\n你好, 我是 Lain.\n我是一个住在上海的宅男。你可能在某处见过我。",
|
"bio_placeholder": "例如:\n你好,我是玲音。\n我是一个住在日本郊区的动画少女。你可能在 Wired 见过我。",
|
||||||
"validations": {
|
"validations": {
|
||||||
"username_required": "不能留空",
|
"username_required": "不能留空",
|
||||||
"fullname_required": "不能留空",
|
"fullname_required": "不能留空",
|
||||||
|
|
@ -177,9 +183,9 @@
|
||||||
"confirm_and_enable": "确认并启用 OTP",
|
"confirm_and_enable": "确认并启用 OTP",
|
||||||
"title": "双因素验证",
|
"title": "双因素验证",
|
||||||
"generate_new_recovery_codes": "生成新的恢复码",
|
"generate_new_recovery_codes": "生成新的恢复码",
|
||||||
"warning_of_generate_new_codes" : "当你生成新的恢复码时,你的就恢复码就失效了。",
|
"warning_of_generate_new_codes": "当你生成新的恢复码时,你的旧恢复码就失效了。",
|
||||||
"recovery_codes": "恢复码。",
|
"recovery_codes": "恢复码。",
|
||||||
"waiting_a_recovery_codes": "接受备份码。。。",
|
"waiting_a_recovery_codes": "正在接收备份码……",
|
||||||
"recovery_codes_warning": "抄写这些号码,或者保存在安全的地方。这些号码不会再次显示。如果你无法访问你的 2FA app,也丢失了你的恢复码,你的账号就再也无法登录了。",
|
"recovery_codes_warning": "抄写这些号码,或者保存在安全的地方。这些号码不会再次显示。如果你无法访问你的 2FA app,也丢失了你的恢复码,你的账号就再也无法登录了。",
|
||||||
"authentication_methods": "身份验证方法",
|
"authentication_methods": "身份验证方法",
|
||||||
"scan": {
|
"scan": {
|
||||||
|
|
@ -222,7 +228,7 @@
|
||||||
"data_import_export_tab": "数据导入/导出",
|
"data_import_export_tab": "数据导入/导出",
|
||||||
"default_vis": "默认可见范围",
|
"default_vis": "默认可见范围",
|
||||||
"delete_account": "删除账户",
|
"delete_account": "删除账户",
|
||||||
"delete_account_description": "永久删除你的帐号和所有消息。",
|
"delete_account_description": "永久删除你的帐号和所有数据。",
|
||||||
"delete_account_error": "删除账户时发生错误,如果一直删除不了,请联系实例管理员。",
|
"delete_account_error": "删除账户时发生错误,如果一直删除不了,请联系实例管理员。",
|
||||||
"delete_account_instructions": "在下面输入你的密码来确认删除账户",
|
"delete_account_instructions": "在下面输入你的密码来确认删除账户",
|
||||||
"avatar_size_instruction": "推荐的头像图片最小的尺寸是 150x150 像素。",
|
"avatar_size_instruction": "推荐的头像图片最小的尺寸是 150x150 像素。",
|
||||||
|
|
@ -263,7 +269,7 @@
|
||||||
"loop_video_silent_only": "只循环没有声音的视频(例如:Mastodon 里的“GIF”)",
|
"loop_video_silent_only": "只循环没有声音的视频(例如:Mastodon 里的“GIF”)",
|
||||||
"mutes_tab": "隐藏",
|
"mutes_tab": "隐藏",
|
||||||
"play_videos_in_modal": "在弹出框内播放视频",
|
"play_videos_in_modal": "在弹出框内播放视频",
|
||||||
"use_contain_fit": "生成缩略图时不要裁剪附件。",
|
"use_contain_fit": "生成缩略图时不要裁剪附件",
|
||||||
"name": "名字",
|
"name": "名字",
|
||||||
"name_bio": "名字及简介",
|
"name_bio": "名字及简介",
|
||||||
"new_password": "新密码",
|
"new_password": "新密码",
|
||||||
|
|
@ -348,7 +354,14 @@
|
||||||
"save_load_hint": "\"保留\" 选项在选择或加载主题时保留当前设置的选项,在导出主题时还会存储上述选项。当所有复选框未设置时,导出主题将保存所有内容。",
|
"save_load_hint": "\"保留\" 选项在选择或加载主题时保留当前设置的选项,在导出主题时还会存储上述选项。当所有复选框未设置时,导出主题将保存所有内容。",
|
||||||
"reset": "重置",
|
"reset": "重置",
|
||||||
"clear_all": "清除全部",
|
"clear_all": "清除全部",
|
||||||
"clear_opacity": "清除透明度"
|
"clear_opacity": "清除透明度",
|
||||||
|
"load_theme": "加载主题",
|
||||||
|
"help": {
|
||||||
|
"upgraded_from_v2": "PleromaFE 已升级,主题会和你记忆中的不太一样。"
|
||||||
|
},
|
||||||
|
"use_source": "新版本",
|
||||||
|
"use_snapshot": "老版本",
|
||||||
|
"keep_as_is": "保持原状"
|
||||||
},
|
},
|
||||||
"common": {
|
"common": {
|
||||||
"color": "颜色",
|
"color": "颜色",
|
||||||
|
|
@ -441,7 +454,7 @@
|
||||||
"mono": "内容",
|
"mono": "内容",
|
||||||
"input": "刚刚抵达上海",
|
"input": "刚刚抵达上海",
|
||||||
"faint_link": "帮助菜单",
|
"faint_link": "帮助菜单",
|
||||||
"fine_print": "阅读我们的 {0} 学不到什么东东!",
|
"fine_print": "阅读我们的 {0} ,然而什么也学不到!",
|
||||||
"header_faint": "这很正常",
|
"header_faint": "这很正常",
|
||||||
"checkbox": "我已经浏览了 TOC",
|
"checkbox": "我已经浏览了 TOC",
|
||||||
"link": "一个很棒的摇滚链接"
|
"link": "一个很棒的摇滚链接"
|
||||||
|
|
@ -451,7 +464,20 @@
|
||||||
"title": "版本",
|
"title": "版本",
|
||||||
"backend_version": "后端版本",
|
"backend_version": "后端版本",
|
||||||
"frontend_version": "前端版本"
|
"frontend_version": "前端版本"
|
||||||
}
|
},
|
||||||
|
"notification_setting_filters": "过滤器",
|
||||||
|
"domain_mutes": "域名",
|
||||||
|
"changed_email": "邮箱修改成功!",
|
||||||
|
"change_email_error": "修改你的电子邮箱时发生错误",
|
||||||
|
"change_email": "修改电子邮箱",
|
||||||
|
"allow_following_move": "正在关注的账号迁移时自动重新关注",
|
||||||
|
"notification_setting_privacy_option": "在通知推送中隐藏发送者和内容",
|
||||||
|
"notification_setting_privacy": "隐私",
|
||||||
|
"hide_follows_count_description": "不显示关注数",
|
||||||
|
"notification_visibility_emoji_reactions": "互动",
|
||||||
|
"notification_visibility_moves": "用户迁移",
|
||||||
|
"new_email": "新邮箱",
|
||||||
|
"emoji_reactions_on_timeline": "在时间线上显示表情符号互动"
|
||||||
},
|
},
|
||||||
"time": {
|
"time": {
|
||||||
"day": "{0} 天",
|
"day": "{0} 天",
|
||||||
|
|
@ -561,7 +587,10 @@
|
||||||
"quarantine": "从联合实例中禁止用户帖子",
|
"quarantine": "从联合实例中禁止用户帖子",
|
||||||
"delete_user": "删除用户",
|
"delete_user": "删除用户",
|
||||||
"delete_user_confirmation": "你确认吗?此操作无法撤销。"
|
"delete_user_confirmation": "你确认吗?此操作无法撤销。"
|
||||||
}
|
},
|
||||||
|
"hidden": "已隐藏",
|
||||||
|
"show_repeats": "显示转发",
|
||||||
|
"hide_repeats": "隐藏转发"
|
||||||
},
|
},
|
||||||
"user_profile": {
|
"user_profile": {
|
||||||
"timeline_title": "用户时间线",
|
"timeline_title": "用户时间线",
|
||||||
|
|
@ -586,7 +615,9 @@
|
||||||
"repeat": "转发",
|
"repeat": "转发",
|
||||||
"reply": "回复",
|
"reply": "回复",
|
||||||
"favorite": "收藏",
|
"favorite": "收藏",
|
||||||
"user_settings": "用户设置"
|
"user_settings": "用户设置",
|
||||||
|
"reject_follow_request": "拒绝关注请求",
|
||||||
|
"add_reaction": "添加互动"
|
||||||
},
|
},
|
||||||
"upload": {
|
"upload": {
|
||||||
"error": {
|
"error": {
|
||||||
|
|
@ -605,8 +636,8 @@
|
||||||
"search": {
|
"search": {
|
||||||
"people": "人",
|
"people": "人",
|
||||||
"hashtags": "Hashtags",
|
"hashtags": "Hashtags",
|
||||||
"person_talking": "{count} 人谈论",
|
"person_talking": "{count} 人正在讨论",
|
||||||
"people_talking": "{count} 人谈论",
|
"people_talking": "{count} 人正在讨论",
|
||||||
"no_results": "没有搜索结果"
|
"no_results": "没有搜索结果"
|
||||||
},
|
},
|
||||||
"password_reset": {
|
"password_reset": {
|
||||||
|
|
@ -619,5 +650,49 @@
|
||||||
"not_found": "我们无法找到匹配的邮箱地址或者用户名。",
|
"not_found": "我们无法找到匹配的邮箱地址或者用户名。",
|
||||||
"too_many_requests": "你触发了尝试的限制,请稍后再试。",
|
"too_many_requests": "你触发了尝试的限制,请稍后再试。",
|
||||||
"password_reset_disabled": "密码重置已经被禁用。请联系你的实例管理员。"
|
"password_reset_disabled": "密码重置已经被禁用。请联系你的实例管理员。"
|
||||||
|
},
|
||||||
|
"remote_user_resolver": {
|
||||||
|
"error": "未找到。",
|
||||||
|
"searching_for": "搜索",
|
||||||
|
"remote_user_resolver": "远程用户解析器"
|
||||||
|
},
|
||||||
|
"emoji": {
|
||||||
|
"keep_open": "选择器保持打开",
|
||||||
|
"stickers": "贴图",
|
||||||
|
"unicode": "Unicode 表情符号",
|
||||||
|
"custom": "自定义表情符号",
|
||||||
|
"add_emoji": "插入表情符号",
|
||||||
|
"search_emoji": "搜索表情符号",
|
||||||
|
"emoji": "表情符号"
|
||||||
|
},
|
||||||
|
"about": {
|
||||||
|
"mrf": {
|
||||||
|
"simple": {
|
||||||
|
"quarantine_desc": "本实例只会把公开状态发送非下列实例:",
|
||||||
|
"quarantine": "隔离",
|
||||||
|
"reject_desc": "本实例不会接收来自下列实例的消息:",
|
||||||
|
"reject": "拒绝",
|
||||||
|
"accept_desc": "本实例只接收来自下列实例的消息:",
|
||||||
|
"simple_policies": "站规",
|
||||||
|
"accept": "接受",
|
||||||
|
"media_removal": "移除媒体"
|
||||||
|
},
|
||||||
|
"mrf_policies_desc": "MRF 策略会影响本实例的互通行为。以下策略已启用:",
|
||||||
|
"mrf_policies": "已启动 MRF 策略",
|
||||||
|
"keyword": {
|
||||||
|
"ftl_removal": "从“全部已知网络”时间线上移除",
|
||||||
|
"keyword_policies": "关键词策略",
|
||||||
|
"is_replaced_by": "→",
|
||||||
|
"replace": "替换",
|
||||||
|
"reject": "拒绝"
|
||||||
|
},
|
||||||
|
"federation": "联邦"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"domain_mute_card": {
|
||||||
|
"unmute_progress": "正在取消隐藏……",
|
||||||
|
"unmute": "取消隐藏",
|
||||||
|
"mute_progress": "隐藏中……",
|
||||||
|
"mute": "隐藏"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,11 +46,13 @@ Vue.use(VBodyScrollLock)
|
||||||
|
|
||||||
const i18n = new VueI18n({
|
const i18n = new VueI18n({
|
||||||
// By default, use the browser locale, we will update it if neccessary
|
// By default, use the browser locale, we will update it if neccessary
|
||||||
locale: currentLocale,
|
locale: 'en',
|
||||||
fallbackLocale: 'en',
|
fallbackLocale: 'en',
|
||||||
messages
|
messages: messages.default
|
||||||
})
|
})
|
||||||
|
|
||||||
|
messages.setLanguage(i18n, currentLocale)
|
||||||
|
|
||||||
const persistedStateOptions = {
|
const persistedStateOptions = {
|
||||||
paths: [
|
paths: [
|
||||||
'config',
|
'config',
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,19 @@
|
||||||
import { set, delete as del } from 'vue'
|
import { set, delete as del } from 'vue'
|
||||||
import { setPreset, applyTheme } from '../services/style_setter/style_setter.js'
|
import { setPreset, applyTheme } from '../services/style_setter/style_setter.js'
|
||||||
|
import messages from '../i18n/messages'
|
||||||
|
|
||||||
const browserLocale = (window.navigator.language || 'en').split('-')[0]
|
const browserLocale = (window.navigator.language || 'en').split('-')[0]
|
||||||
|
|
||||||
|
/* TODO this is a bit messy.
|
||||||
|
* We need to declare settings with their types and also deal with
|
||||||
|
* instance-default settings in some way, hopefully try to avoid copy-pasta
|
||||||
|
* in general.
|
||||||
|
*/
|
||||||
|
export const multiChoiceProperties = [
|
||||||
|
'postContentType',
|
||||||
|
'subjectLineBehavior'
|
||||||
|
]
|
||||||
|
|
||||||
export const defaultState = {
|
export const defaultState = {
|
||||||
colors: {},
|
colors: {},
|
||||||
theme: undefined,
|
theme: undefined,
|
||||||
|
|
@ -106,6 +117,10 @@ const config = {
|
||||||
case 'customTheme':
|
case 'customTheme':
|
||||||
case 'customThemeSource':
|
case 'customThemeSource':
|
||||||
applyTheme(value)
|
applyTheme(value)
|
||||||
|
break
|
||||||
|
case 'interfaceLanguage':
|
||||||
|
messages.setLanguage(this.getters.i18n, value)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { set } from 'vue'
|
import { set } from 'vue'
|
||||||
import { getPreset, applyTheme } from '../services/style_setter/style_setter.js'
|
import { getPreset, applyTheme } from '../services/style_setter/style_setter.js'
|
||||||
import { CURRENT_VERSION } from '../services/theme_data/theme_data.service.js'
|
import { CURRENT_VERSION } from '../services/theme_data/theme_data.service.js'
|
||||||
|
import apiService from '../services/api/api.service.js'
|
||||||
import { instanceDefaultProperties } from './config.js'
|
import { instanceDefaultProperties } from './config.js'
|
||||||
|
|
||||||
const defaultState = {
|
const defaultState = {
|
||||||
|
|
@ -49,6 +50,7 @@ const defaultState = {
|
||||||
postFormats: [],
|
postFormats: [],
|
||||||
restrictedNicknames: [],
|
restrictedNicknames: [],
|
||||||
safeDM: true,
|
safeDM: true,
|
||||||
|
knownDomains: [],
|
||||||
|
|
||||||
// Feature-set, apparently, not everything here is reported...
|
// Feature-set, apparently, not everything here is reported...
|
||||||
chatAvailable: false,
|
chatAvailable: false,
|
||||||
|
|
@ -81,6 +83,9 @@ const instance = {
|
||||||
if (typeof value !== 'undefined') {
|
if (typeof value !== 'undefined') {
|
||||||
set(state, name, value)
|
set(state, name, value)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
setKnownDomains (state, domains) {
|
||||||
|
state.knownDomains = domains
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getters: {
|
getters: {
|
||||||
|
|
@ -183,6 +188,18 @@ const instance = {
|
||||||
state.emojiFetched = true
|
state.emojiFetched = true
|
||||||
dispatch('getStaticEmoji')
|
dispatch('getStaticEmoji')
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async getKnownDomains ({ commit, rootState }) {
|
||||||
|
try {
|
||||||
|
const result = await apiService.fetchKnownDomains({
|
||||||
|
credentials: rootState.users.currentUser.credentials
|
||||||
|
})
|
||||||
|
commit('setKnownDomains', result)
|
||||||
|
} catch (e) {
|
||||||
|
console.warn("Can't load known domains")
|
||||||
|
console.warn(e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
import { set, delete as del } from 'vue'
|
import { set, delete as del } from 'vue'
|
||||||
|
|
||||||
const defaultState = {
|
const defaultState = {
|
||||||
|
settingsModalState: 'hidden',
|
||||||
|
settingsModalLoaded: false,
|
||||||
settings: {
|
settings: {
|
||||||
currentSaveStateNotice: null,
|
currentSaveStateNotice: null,
|
||||||
noticeClearTimeout: null,
|
noticeClearTimeout: null,
|
||||||
|
|
@ -35,6 +37,27 @@ const interfaceMod = {
|
||||||
},
|
},
|
||||||
setMobileLayout (state, value) {
|
setMobileLayout (state, value) {
|
||||||
state.mobileLayout = value
|
state.mobileLayout = value
|
||||||
|
},
|
||||||
|
closeSettingsModal (state) {
|
||||||
|
state.settingsModalState = 'hidden'
|
||||||
|
},
|
||||||
|
togglePeekSettingsModal (state) {
|
||||||
|
switch (state.settingsModalState) {
|
||||||
|
case 'minimized':
|
||||||
|
state.settingsModalState = 'visible'
|
||||||
|
return
|
||||||
|
case 'visible':
|
||||||
|
state.settingsModalState = 'minimized'
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
throw new Error('Illegal minimization state of settings modal')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
openSettingsModal (state) {
|
||||||
|
state.settingsModalState = 'visible'
|
||||||
|
if (!state.settingsModalLoaded) {
|
||||||
|
state.settingsModalLoaded = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
|
|
@ -49,6 +72,15 @@ const interfaceMod = {
|
||||||
},
|
},
|
||||||
setMobileLayout ({ commit }, value) {
|
setMobileLayout ({ commit }, value) {
|
||||||
commit('setMobileLayout', value)
|
commit('setMobileLayout', value)
|
||||||
|
},
|
||||||
|
closeSettingsModal ({ commit }) {
|
||||||
|
commit('closeSettingsModal')
|
||||||
|
},
|
||||||
|
openSettingsModal ({ commit }) {
|
||||||
|
commit('openSettingsModal')
|
||||||
|
},
|
||||||
|
togglePeekSettingsModal ({ commit }) {
|
||||||
|
commit('togglePeekSettingsModal')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ import {
|
||||||
import { set } from 'vue'
|
import { set } from 'vue'
|
||||||
import { isStatusNotification } from '../services/notification_utils/notification_utils.js'
|
import { isStatusNotification } from '../services/notification_utils/notification_utils.js'
|
||||||
import apiService from '../services/api/api.service.js'
|
import apiService from '../services/api/api.service.js'
|
||||||
// import parse from '../services/status_parser/status_parser.js'
|
import { muteWordHits } from '../services/status_parser/status_parser.js'
|
||||||
|
|
||||||
const emptyTl = (userId = 0) => ({
|
const emptyTl = (userId = 0) => ({
|
||||||
statuses: [],
|
statuses: [],
|
||||||
|
|
@ -381,7 +381,18 @@ const addNewNotifications = (state, { dispatch, notifications, older, visibleNot
|
||||||
notifObj.image = status.attachments[0].url
|
notifObj.image = status.attachments[0].url
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!notification.seen && !state.notifications.desktopNotificationSilence && visibleNotificationTypes.includes(notification.type)) {
|
const reasonsToMuteNotif = (
|
||||||
|
notification.seen ||
|
||||||
|
state.notifications.desktopNotificationSilence ||
|
||||||
|
!visibleNotificationTypes.includes(notification.type) ||
|
||||||
|
(
|
||||||
|
notification.type === 'mention' && status && (
|
||||||
|
status.muted ||
|
||||||
|
muteWordHits(status, rootGetters.mergedConfig.muteWords).length === 0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if (!reasonsToMuteNotif) {
|
||||||
let desktopNotification = new window.Notification(title, notifObj)
|
let desktopNotification = new window.Notification(title, notifObj)
|
||||||
// Chrome is known for not closing notifications automatically
|
// Chrome is known for not closing notifications automatically
|
||||||
// according to MDN, anyway.
|
// according to MDN, anyway.
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,7 @@ const MASTODON_SEARCH_2 = `/api/v2/search`
|
||||||
const MASTODON_USER_SEARCH_URL = '/api/v1/accounts/search'
|
const MASTODON_USER_SEARCH_URL = '/api/v1/accounts/search'
|
||||||
const MASTODON_DOMAIN_BLOCKS_URL = '/api/v1/domain_blocks'
|
const MASTODON_DOMAIN_BLOCKS_URL = '/api/v1/domain_blocks'
|
||||||
const MASTODON_STREAMING = '/api/v1/streaming'
|
const MASTODON_STREAMING = '/api/v1/streaming'
|
||||||
|
const MASTODON_KNOWN_DOMAIN_LIST_URL = '/api/v1/instance/peers'
|
||||||
const PLEROMA_EMOJI_REACTIONS_URL = id => `/api/v1/pleroma/statuses/${id}/reactions`
|
const PLEROMA_EMOJI_REACTIONS_URL = id => `/api/v1/pleroma/statuses/${id}/reactions`
|
||||||
const PLEROMA_EMOJI_REACT_URL = (id, emoji) => `/api/v1/pleroma/statuses/${id}/reactions/${emoji}`
|
const PLEROMA_EMOJI_REACT_URL = (id, emoji) => `/api/v1/pleroma/statuses/${id}/reactions/${emoji}`
|
||||||
const PLEROMA_EMOJI_UNREACT_URL = (id, emoji) => `/api/v1/pleroma/statuses/${id}/reactions/${emoji}`
|
const PLEROMA_EMOJI_UNREACT_URL = (id, emoji) => `/api/v1/pleroma/statuses/${id}/reactions/${emoji}`
|
||||||
|
|
@ -538,9 +539,11 @@ const fetchTimeline = ({
|
||||||
if (timeline === 'public' || timeline === 'publicAndExternal') {
|
if (timeline === 'public' || timeline === 'publicAndExternal') {
|
||||||
params.push(['only_media', false])
|
params.push(['only_media', false])
|
||||||
}
|
}
|
||||||
|
if (timeline !== 'favorites') {
|
||||||
|
params.push(['with_muted', withMuted])
|
||||||
|
}
|
||||||
|
|
||||||
params.push(['limit', 20])
|
params.push(['limit', 20])
|
||||||
params.push(['with_muted', withMuted])
|
|
||||||
|
|
||||||
const queryString = map(params, (param) => `${param[0]}=${param[1]}`).join('&')
|
const queryString = map(params, (param) => `${param[0]}=${param[1]}`).join('&')
|
||||||
url += `?${queryString}`
|
url += `?${queryString}`
|
||||||
|
|
@ -995,6 +998,10 @@ const search2 = ({ credentials, q, resolve, limit, offset, following }) => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fetchKnownDomains = ({ credentials }) => {
|
||||||
|
return promisedRequest({ url: MASTODON_KNOWN_DOMAIN_LIST_URL, credentials })
|
||||||
|
}
|
||||||
|
|
||||||
const fetchDomainMutes = ({ credentials }) => {
|
const fetchDomainMutes = ({ credentials }) => {
|
||||||
return promisedRequest({ url: MASTODON_DOMAIN_BLOCKS_URL, credentials })
|
return promisedRequest({ url: MASTODON_DOMAIN_BLOCKS_URL, credentials })
|
||||||
}
|
}
|
||||||
|
|
@ -1193,6 +1200,7 @@ const apiService = {
|
||||||
updateNotificationSettings,
|
updateNotificationSettings,
|
||||||
search2,
|
search2,
|
||||||
searchUsers,
|
searchUsers,
|
||||||
|
fetchKnownDomains,
|
||||||
fetchDomainMutes,
|
fetchDomainMutes,
|
||||||
muteDomain,
|
muteDomain,
|
||||||
unmuteDomain
|
unmuteDomain
|
||||||
|
|
|
||||||
|
|
@ -210,7 +210,7 @@ export const addEmojis = (string, emojis) => {
|
||||||
const regexSafeShortCode = emoji.shortcode.replace(matchOperatorsRegex, '\\$&')
|
const regexSafeShortCode = emoji.shortcode.replace(matchOperatorsRegex, '\\$&')
|
||||||
return acc.replace(
|
return acc.replace(
|
||||||
new RegExp(`:${regexSafeShortCode}:`, 'g'),
|
new RegExp(`:${regexSafeShortCode}:`, 'g'),
|
||||||
`<img src='${emoji.url}' alt='${emoji.shortcode}' title='${emoji.shortcode}' class='emoji' />`
|
`<img src='${emoji.url}' alt=':${emoji.shortcode}:' title=':${emoji.shortcode}:' class='emoji' />`
|
||||||
)
|
)
|
||||||
}, string)
|
}, string)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
32
src/services/resettable_async_component.js
Normal file
32
src/services/resettable_async_component.js
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
import Vue from 'vue'
|
||||||
|
|
||||||
|
/* By default async components don't have any way to recover, if component is
|
||||||
|
* failed, it is failed forever. This helper tries to remedy that by recreating
|
||||||
|
* async component when retry is requested (by user). You need to emit the
|
||||||
|
* `resetAsyncComponent` event from child to reset the component. Generally,
|
||||||
|
* this should be done from error component but could be done from loading or
|
||||||
|
* actual target component itself if needs to be.
|
||||||
|
*/
|
||||||
|
function getResettableAsyncComponent (asyncComponent, options) {
|
||||||
|
const asyncComponentFactory = () => () => ({
|
||||||
|
component: asyncComponent(),
|
||||||
|
...options
|
||||||
|
})
|
||||||
|
|
||||||
|
const observe = Vue.observable({ c: asyncComponentFactory() })
|
||||||
|
|
||||||
|
return {
|
||||||
|
functional: true,
|
||||||
|
render (createElement, { data, children }) {
|
||||||
|
// emit event resetAsyncComponent to reloading
|
||||||
|
data.on = {}
|
||||||
|
data.on.resetAsyncComponent = () => {
|
||||||
|
observe.c = asyncComponentFactory()
|
||||||
|
// parent.$forceUpdate()
|
||||||
|
}
|
||||||
|
return createElement(observe.c, data, children)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default getResettableAsyncComponent
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { filter } from 'lodash'
|
||||||
import sanitize from 'sanitize-html'
|
import sanitize from 'sanitize-html'
|
||||||
|
|
||||||
export const removeAttachmentLinks = (html) => {
|
export const removeAttachmentLinks = (html) => {
|
||||||
|
|
@ -12,4 +13,14 @@ export const parse = (html) => {
|
||||||
return removeAttachmentLinks(html)
|
return removeAttachmentLinks(html)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const muteWordHits = (status, muteWords) => {
|
||||||
|
const statusText = status.text.toLowerCase()
|
||||||
|
const statusSummary = status.summary.toLowerCase()
|
||||||
|
const hits = filter(muteWords, (muteWord) => {
|
||||||
|
return statusText.includes(muteWord.toLowerCase()) || statusSummary.includes(muteWord.toLowerCase())
|
||||||
|
})
|
||||||
|
|
||||||
|
return hits
|
||||||
|
}
|
||||||
|
|
||||||
export default parse
|
export default parse
|
||||||
|
|
|
||||||
|
|
@ -363,6 +363,18 @@
|
||||||
"css": "ok",
|
"css": "ok",
|
||||||
"code": 59431,
|
"code": 59431,
|
||||||
"src": "fontawesome"
|
"src": "fontawesome"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uid": "4109c474ff99cad28fd5a2c38af2ec6f",
|
||||||
|
"css": "filter",
|
||||||
|
"code": 61616,
|
||||||
|
"src": "fontawesome"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uid": "9a76bc135eac17d2c8b8ad4a5774fc87",
|
||||||
|
"css": "download",
|
||||||
|
"code": 59429,
|
||||||
|
"src": "fontawesome"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -338,9 +338,9 @@ describe('API Entities normalizer', () => {
|
||||||
|
|
||||||
describe('MastoAPI emoji adder', () => {
|
describe('MastoAPI emoji adder', () => {
|
||||||
const emojis = makeMockEmojiMasto()
|
const emojis = makeMockEmojiMasto()
|
||||||
const imageHtml = '<img src="https://example.com/image.png" alt="image" title="image" class="emoji" />'
|
const imageHtml = '<img src="https://example.com/image.png" alt=":image:" title=":image:" class="emoji" />'
|
||||||
.replace(/"/g, '\'')
|
.replace(/"/g, '\'')
|
||||||
const thinkHtml = '<img src="https://example.com/think.png" alt="thinking" title="thinking" class="emoji" />'
|
const thinkHtml = '<img src="https://example.com/think.png" alt=":thinking:" title=":thinking:" class="emoji" />'
|
||||||
.replace(/"/g, '\'')
|
.replace(/"/g, '\'')
|
||||||
|
|
||||||
it('correctly replaces shortcodes in supplied string', () => {
|
it('correctly replaces shortcodes in supplied string', () => {
|
||||||
|
|
@ -366,8 +366,8 @@ describe('API Entities normalizer', () => {
|
||||||
shortcode: '[a-z] {|}*'
|
shortcode: '[a-z] {|}*'
|
||||||
}])
|
}])
|
||||||
const result = addEmojis('This post has :c++: emoji and :[a-z] {|}*: emoji', emojis)
|
const result = addEmojis('This post has :c++: emoji and :[a-z] {|}*: emoji', emojis)
|
||||||
expect(result).to.include('title=\'c++\'')
|
expect(result).to.include('title=\':c++:\'')
|
||||||
expect(result).to.include('title=\'[a-z] {|}*\'')
|
expect(result).to.include('title=\':[a-z] {|}*:\'')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
||||||
15
yarn.lock
15
yarn.lock
|
|
@ -2327,6 +2327,7 @@ dateformat@^1.0.6:
|
||||||
de-indent@^1.0.2:
|
de-indent@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d"
|
resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d"
|
||||||
|
integrity sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0=
|
||||||
|
|
||||||
debug@2, debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9:
|
debug@2, debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9:
|
||||||
version "2.6.9"
|
version "2.6.9"
|
||||||
|
|
@ -7903,9 +7904,10 @@ vue-style-loader@^4.0.0, vue-style-loader@^4.0.1:
|
||||||
hash-sum "^1.0.2"
|
hash-sum "^1.0.2"
|
||||||
loader-utils "^1.0.2"
|
loader-utils "^1.0.2"
|
||||||
|
|
||||||
vue-template-compiler@^2.3.4:
|
vue-template-compiler@^2.6.11:
|
||||||
version "2.5.21"
|
version "2.6.11"
|
||||||
resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.5.21.tgz#a57ceb903177e8f643560a8d639a0f8db647054a"
|
resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.6.11.tgz#c04704ef8f498b153130018993e56309d4698080"
|
||||||
|
integrity sha512-KIq15bvQDrcCjpGjrAhx4mUlyyHfdmTaoNfeoATHLAiWB+MU3cx4lOzMwrnUh9cCxy0Lt1T11hAFY6TQgroUAA==
|
||||||
dependencies:
|
dependencies:
|
||||||
de-indent "^1.0.2"
|
de-indent "^1.0.2"
|
||||||
he "^1.1.0"
|
he "^1.1.0"
|
||||||
|
|
@ -7914,9 +7916,10 @@ vue-template-es2015-compiler@^1.6.0:
|
||||||
version "1.9.1"
|
version "1.9.1"
|
||||||
resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825"
|
resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825"
|
||||||
|
|
||||||
vue@^2.5.13:
|
vue@^2.6.11:
|
||||||
version "2.5.21"
|
version "2.6.11"
|
||||||
resolved "https://registry.yarnpkg.com/vue/-/vue-2.5.21.tgz#3d33dcd03bb813912ce894a8303ab553699c4a85"
|
resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.11.tgz#76594d877d4b12234406e84e35275c6d514125c5"
|
||||||
|
integrity sha512-VfPwgcGABbGAue9+sfrD4PuwFar7gPb1yl1UK1MwXoQPAw0BKSqWfoYCT/ThFrdEVWoI51dBuyCoiNU9bZDZxQ==
|
||||||
|
|
||||||
vuelidate@^0.7.4:
|
vuelidate@^0.7.4:
|
||||||
version "0.7.4"
|
version "0.7.4"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue