forked from AkkomaGang/akkoma-fe
Merge branch 'develop' of https://git.pleroma.social/pleroma/pleroma-fe into develop
This commit is contained in:
commit
fe4845a7c1
74 changed files with 1082 additions and 1107 deletions
|
@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
### Added
|
### Added
|
||||||
|
- Ability to hide/show repeats from user
|
||||||
|
- User profile button clutter organized into a menu
|
||||||
- Emoji picker
|
- Emoji picker
|
||||||
- Started changelog anew
|
- Started changelog anew
|
||||||
### Changed
|
### Changed
|
||||||
|
|
|
@ -45,7 +45,7 @@ export default {
|
||||||
}),
|
}),
|
||||||
created () {
|
created () {
|
||||||
// Load the locale from the storage
|
// Load the locale from the storage
|
||||||
this.$i18n.locale = this.$store.state.config.interfaceLanguage
|
this.$i18n.locale = this.$store.getters.mergedConfig.interfaceLanguage
|
||||||
window.addEventListener('resize', this.updateMobileState)
|
window.addEventListener('resize', this.updateMobileState)
|
||||||
},
|
},
|
||||||
destroyed () {
|
destroyed () {
|
||||||
|
@ -93,7 +93,7 @@ export default {
|
||||||
suggestionsEnabled () { return this.$store.state.instance.suggestionsEnabled },
|
suggestionsEnabled () { return this.$store.state.instance.suggestionsEnabled },
|
||||||
showInstanceSpecificPanel () {
|
showInstanceSpecificPanel () {
|
||||||
return this.$store.state.instance.showInstanceSpecificPanel &&
|
return this.$store.state.instance.showInstanceSpecificPanel &&
|
||||||
!this.$store.state.config.hideISP &&
|
!this.$store.getters.mergedConfig.hideISP &&
|
||||||
this.$store.state.instance.instanceSpecificPanelContent
|
this.$store.state.instance.instanceSpecificPanelContent
|
||||||
},
|
},
|
||||||
showFeaturesPanel () { return this.$store.state.instance.showFeaturesPanel },
|
showFeaturesPanel () { return this.$store.state.instance.showFeaturesPanel },
|
||||||
|
|
30
src/App.scss
30
src/App.scss
|
@ -39,10 +39,13 @@ h4 {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
font-family: var(--interfaceFont, sans-serif);
|
font-family: var(--interfaceFont, sans-serif);
|
||||||
font-size: 14px;
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
color: $fallback--text;
|
color: $fallback--text;
|
||||||
color: var(--text, $fallback--text);
|
color: var(--text, $fallback--text);
|
||||||
|
@ -705,31 +708,6 @@ nav {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes modal-background-fadein {
|
|
||||||
from {
|
|
||||||
background-color: rgba(0, 0, 0, 0);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
background-color: rgba(0, 0, 0, 0.5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-view {
|
|
||||||
z-index: 1000;
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
overflow: auto;
|
|
||||||
animation-duration: 0.2s;
|
|
||||||
background-color: rgba(0, 0, 0, 0.5);
|
|
||||||
animation-name: modal-background-fadein;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-icon {
|
.button-icon {
|
||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ export default (store) => {
|
||||||
{ 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: '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 },
|
{ 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: 'user-settings', path: '/user-settings', component: UserSettings, beforeEnter: validateAuthenticatedRoute },
|
||||||
|
|
35
src/components/account_actions/account_actions.js
Normal file
35
src/components/account_actions/account_actions.js
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
import ProgressButton from '../progress_button/progress_button.vue'
|
||||||
|
|
||||||
|
const AccountActions = {
|
||||||
|
props: [
|
||||||
|
'user'
|
||||||
|
],
|
||||||
|
data () {
|
||||||
|
return { }
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
ProgressButton
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
showRepeats () {
|
||||||
|
this.$store.dispatch('showReblogs', this.user.id)
|
||||||
|
},
|
||||||
|
hideRepeats () {
|
||||||
|
this.$store.dispatch('hideReblogs', this.user.id)
|
||||||
|
},
|
||||||
|
blockUser () {
|
||||||
|
this.$store.dispatch('blockUser', this.user.id)
|
||||||
|
},
|
||||||
|
unblockUser () {
|
||||||
|
this.$store.dispatch('unblockUser', this.user.id)
|
||||||
|
},
|
||||||
|
reportUser () {
|
||||||
|
this.$store.dispatch('openUserReportingModal', this.user.id)
|
||||||
|
},
|
||||||
|
mentionUser () {
|
||||||
|
this.$store.dispatch('openPostStatusModal', { replyTo: true, repliedUser: this.user })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AccountActions
|
93
src/components/account_actions/account_actions.vue
Normal file
93
src/components/account_actions/account_actions.vue
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
<template>
|
||||||
|
<div class="account-actions">
|
||||||
|
<v-popover
|
||||||
|
trigger="click"
|
||||||
|
class="account-tools-popover"
|
||||||
|
:container="false"
|
||||||
|
placement="bottom-end"
|
||||||
|
:offset="5"
|
||||||
|
>
|
||||||
|
<div slot="popover">
|
||||||
|
<div class="dropdown-menu">
|
||||||
|
<button
|
||||||
|
class="btn btn-default btn-block dropdown-item"
|
||||||
|
@click="mentionUser"
|
||||||
|
>
|
||||||
|
{{ $t('user_card.mention') }}
|
||||||
|
</button>
|
||||||
|
<template v-if="user.following">
|
||||||
|
<div
|
||||||
|
role="separator"
|
||||||
|
class="dropdown-divider"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
v-if="user.showing_reblogs"
|
||||||
|
class="btn btn-default dropdown-item"
|
||||||
|
@click="hideRepeats"
|
||||||
|
>
|
||||||
|
{{ $t('user_card.hide_repeats') }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
v-if="!user.showing_reblogs"
|
||||||
|
class="btn btn-default dropdown-item"
|
||||||
|
@click="showRepeats"
|
||||||
|
>
|
||||||
|
{{ $t('user_card.show_repeats') }}
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
<div
|
||||||
|
role="separator"
|
||||||
|
class="dropdown-divider"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
v-if="user.statusnet_blocking"
|
||||||
|
class="btn btn-default btn-block dropdown-item"
|
||||||
|
@click="unblockUser"
|
||||||
|
>
|
||||||
|
{{ $t('user_card.unblock') }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
v-else
|
||||||
|
class="btn btn-default btn-block dropdown-item"
|
||||||
|
@click="blockUser"
|
||||||
|
>
|
||||||
|
{{ $t('user_card.block') }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="btn btn-default btn-block dropdown-item"
|
||||||
|
@click="reportUser"
|
||||||
|
>
|
||||||
|
{{ $t('user_card.report') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="btn btn-default ellipsis-button">
|
||||||
|
<i class="icon-ellipsis trigger-button" />
|
||||||
|
</div>
|
||||||
|
</v-popover>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./account_actions.js"></script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@import '../../_variables.scss';
|
||||||
|
@import '../popper/popper.scss';
|
||||||
|
.account-actions {
|
||||||
|
margin: 0 .8em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.account-actions button.dropdown-item {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
.account-actions .trigger-button {
|
||||||
|
color: $fallback--lightText;
|
||||||
|
color: var(--lightText, $fallback--lightText);
|
||||||
|
opacity: .8;
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
color: $fallback--text;
|
||||||
|
color: var(--text, $fallback--text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -10,13 +10,14 @@ const Attachment = {
|
||||||
'statusId',
|
'statusId',
|
||||||
'size',
|
'size',
|
||||||
'allowPlay',
|
'allowPlay',
|
||||||
'setMedia'
|
'setMedia',
|
||||||
|
'naturalSizeLoad'
|
||||||
],
|
],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
nsfwImage: this.$store.state.instance.nsfwCensorImage || nsfwImage,
|
nsfwImage: this.$store.state.instance.nsfwCensorImage || nsfwImage,
|
||||||
hideNsfwLocal: this.$store.state.config.hideNsfw,
|
hideNsfwLocal: this.$store.getters.mergedConfig.hideNsfw,
|
||||||
preloadImage: this.$store.state.config.preloadImage,
|
preloadImage: this.$store.getters.mergedConfig.preloadImage,
|
||||||
loading: false,
|
loading: false,
|
||||||
img: fileTypeService.fileType(this.attachment.mimetype) === 'image' && document.createElement('img'),
|
img: fileTypeService.fileType(this.attachment.mimetype) === 'image' && document.createElement('img'),
|
||||||
modalOpen: false,
|
modalOpen: false,
|
||||||
|
@ -57,7 +58,7 @@ const Attachment = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
openModal (event) {
|
openModal (event) {
|
||||||
const modalTypes = this.$store.state.config.playVideosInModal
|
const modalTypes = this.$store.getters.mergedConfig.playVideosInModal
|
||||||
? ['image', 'video']
|
? ['image', 'video']
|
||||||
: ['image']
|
: ['image']
|
||||||
if (fileTypeService.fileMatchesSomeType(modalTypes, this.attachment) ||
|
if (fileTypeService.fileMatchesSomeType(modalTypes, this.attachment) ||
|
||||||
|
@ -70,7 +71,7 @@ const Attachment = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
toggleHidden (event) {
|
toggleHidden (event) {
|
||||||
if (this.$store.state.config.useOneClickNsfw && !this.showHidden) {
|
if (this.$store.getters.mergedConfig.useOneClickNsfw && !this.showHidden) {
|
||||||
this.openModal(event)
|
this.openModal(event)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -88,6 +89,11 @@ const Attachment = {
|
||||||
} else {
|
} else {
|
||||||
this.showHidden = !this.showHidden
|
this.showHidden = !this.showHidden
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
onImageLoad (image) {
|
||||||
|
const width = image.naturalWidth
|
||||||
|
const height = image.naturalHeight
|
||||||
|
this.naturalSizeLoad && this.naturalSizeLoad({ width, height })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,6 +58,7 @@
|
||||||
:referrerpolicy="referrerpolicy"
|
:referrerpolicy="referrerpolicy"
|
||||||
:mimetype="attachment.mimetype"
|
:mimetype="attachment.mimetype"
|
||||||
:src="attachment.large_thumb_url || attachment.url"
|
:src="attachment.large_thumb_url || attachment.url"
|
||||||
|
:image-load-handler="onImageLoad"
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,22 @@
|
||||||
<template>
|
<template>
|
||||||
<label class="checkbox">
|
<label
|
||||||
|
class="checkbox"
|
||||||
|
:class="{ disabled, indeterminate }"
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
|
:disabled="disabled"
|
||||||
:checked="checked"
|
:checked="checked"
|
||||||
:indeterminate.prop="indeterminate"
|
:indeterminate.prop="indeterminate"
|
||||||
@change="$emit('change', $event.target.checked)"
|
@change="$emit('change', $event.target.checked)"
|
||||||
>
|
>
|
||||||
<i class="checkbox-indicator" />
|
<i class="checkbox-indicator" />
|
||||||
<span v-if="!!$slots.default"><slot /></span>
|
<span
|
||||||
|
class="label"
|
||||||
|
v-if="!!$slots.default"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -17,7 +26,11 @@ export default {
|
||||||
prop: 'checked',
|
prop: 'checked',
|
||||||
event: 'change'
|
event: 'change'
|
||||||
},
|
},
|
||||||
props: ['checked', 'indeterminate']
|
props: [
|
||||||
|
'checked',
|
||||||
|
'indeterminate',
|
||||||
|
'disabled'
|
||||||
|
]
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -27,12 +40,16 @@ export default {
|
||||||
.checkbox {
|
.checkbox {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding-left: 1.2em;
|
|
||||||
min-height: 1.2em;
|
min-height: 1.2em;
|
||||||
|
|
||||||
|
&-indicator {
|
||||||
|
position: relative;
|
||||||
|
padding-left: 1.2em;
|
||||||
|
}
|
||||||
|
|
||||||
&-indicator::before {
|
&-indicator::before {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
right: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
display: block;
|
display: block;
|
||||||
content: '✔';
|
content: '✔';
|
||||||
|
@ -54,6 +71,17 @@ export default {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.disabled {
|
||||||
|
.checkbox-indicator::before,
|
||||||
|
.label {
|
||||||
|
opacity: .5;
|
||||||
|
}
|
||||||
|
.label {
|
||||||
|
color: $fallback--faint;
|
||||||
|
color: var(--faint, $fallback--faint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
input[type=checkbox] {
|
input[type=checkbox] {
|
||||||
display: none;
|
display: none;
|
||||||
|
|
||||||
|
@ -68,9 +96,6 @@ export default {
|
||||||
color: var(--text, $fallback--text);
|
color: var(--text, $fallback--text);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:disabled + .checkbox-indicator::before {
|
|
||||||
opacity: .5;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
& > span {
|
& > span {
|
||||||
|
|
|
@ -99,7 +99,7 @@ const EmojiInput = {
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
padEmoji () {
|
padEmoji () {
|
||||||
return this.$store.state.config.padEmoji
|
return this.$store.getters.mergedConfig.padEmoji
|
||||||
},
|
},
|
||||||
suggestions () {
|
suggestions () {
|
||||||
const firstchar = this.textAtCaret.charAt(0)
|
const firstchar = this.textAtCaret.charAt(0)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import Checkbox from '../checkbox/checkbox.vue'
|
||||||
|
|
||||||
const filterByKeyword = (list, keyword = '') => {
|
const filterByKeyword = (list, keyword = '') => {
|
||||||
return list.filter(x => x.displayText.includes(keyword))
|
return list.filter(x => x.displayText.includes(keyword))
|
||||||
|
@ -13,7 +14,6 @@ const EmojiPicker = {
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
labelKey: String(Math.random() * 100000),
|
|
||||||
keyword: '',
|
keyword: '',
|
||||||
activeGroup: 'custom',
|
activeGroup: 'custom',
|
||||||
showingStickers: false,
|
showingStickers: false,
|
||||||
|
@ -22,7 +22,8 @@ const EmojiPicker = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
StickerPicker: () => import('../sticker_picker/sticker_picker.vue')
|
StickerPicker: () => import('../sticker_picker/sticker_picker.vue'),
|
||||||
|
Checkbox
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onEmoji (emoji) {
|
onEmoji (emoji) {
|
||||||
|
|
|
@ -14,10 +14,6 @@
|
||||||
padding: 7px;
|
padding: 7px;
|
||||||
line-height: normal;
|
line-height: normal;
|
||||||
}
|
}
|
||||||
.keep-open-label {
|
|
||||||
padding: 0 7px;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.heading {
|
.heading {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -75,22 +75,10 @@
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div class="keep-open">
|
||||||
class="keep-open"
|
<Checkbox v-model="keepOpen">
|
||||||
>
|
{{ $t('emoji.keep_open') }}
|
||||||
<input
|
</Checkbox>
|
||||||
:id="labelKey + 'keep-open'"
|
|
||||||
v-model="keepOpen"
|
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label
|
|
||||||
class="keep-open-label"
|
|
||||||
:for="labelKey + 'keep-open'"
|
|
||||||
>
|
|
||||||
<div class="keep-open-label-text">
|
|
||||||
{{ $t('emoji.keep_open') }}
|
|
||||||
</div>
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -4,8 +4,6 @@
|
||||||
trigger="click"
|
trigger="click"
|
||||||
placement="top"
|
placement="top"
|
||||||
class="extra-button-popover"
|
class="extra-button-popover"
|
||||||
:offset="5"
|
|
||||||
:container="false"
|
|
||||||
>
|
>
|
||||||
<div slot="popover">
|
<div slot="popover">
|
||||||
<div class="dropdown-menu">
|
<div class="dropdown-menu">
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
|
import { mapGetters } from 'vuex'
|
||||||
|
|
||||||
const FavoriteButton = {
|
const FavoriteButton = {
|
||||||
props: ['status', 'loggedIn'],
|
props: ['status', 'loggedIn'],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
hidePostStatsLocal: typeof this.$store.state.config.hidePostStats === 'undefined'
|
|
||||||
? this.$store.state.instance.hidePostStats
|
|
||||||
: this.$store.state.config.hidePostStats,
|
|
||||||
animated: false
|
animated: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -28,7 +27,8 @@ const FavoriteButton = {
|
||||||
'icon-star': this.status.favorited,
|
'icon-star': this.status.favorited,
|
||||||
'animate-spin': this.animated
|
'animate-spin': this.animated
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
...mapGetters(['mergedConfig'])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
:title="$t('tool_tip.favorite')"
|
:title="$t('tool_tip.favorite')"
|
||||||
@click.prevent="favorite()"
|
@click.prevent="favorite()"
|
||||||
/>
|
/>
|
||||||
<span v-if="!hidePostStatsLocal && status.fave_num > 0">{{ status.fave_num }}</span>
|
<span v-if="!mergedConfig.hidePostStats && status.fave_num > 0">{{ status.fave_num }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<i
|
<i
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
class="button-icon favorite-button"
|
class="button-icon favorite-button"
|
||||||
:title="$t('tool_tip.favorite')"
|
:title="$t('tool_tip.favorite')"
|
||||||
/>
|
/>
|
||||||
<span v-if="!hidePostStatsLocal && status.fave_num > 0">{{ status.fave_num }}</span>
|
<span v-if="!mergedConfig.hidePostStats && status.fave_num > 0">{{ status.fave_num }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
53
src/components/follow_button/follow_button.js
Normal file
53
src/components/follow_button/follow_button.js
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
import { requestFollow, requestUnfollow } from '../../services/follow_manipulate/follow_manipulate'
|
||||||
|
export default {
|
||||||
|
props: ['user', 'labelFollowing', 'buttonClass'],
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
inProgress: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
isPressed () {
|
||||||
|
return this.inProgress || this.user.following
|
||||||
|
},
|
||||||
|
title () {
|
||||||
|
if (this.inProgress || this.user.following) {
|
||||||
|
return this.$t('user_card.follow_unfollow')
|
||||||
|
} else if (this.user.requested) {
|
||||||
|
return this.$t('user_card.follow_again')
|
||||||
|
} else {
|
||||||
|
return this.$t('user_card.follow')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
label () {
|
||||||
|
if (this.inProgress) {
|
||||||
|
return this.$t('user_card.follow_progress')
|
||||||
|
} else if (this.user.following) {
|
||||||
|
return this.labelFollowing || this.$t('user_card.following')
|
||||||
|
} else if (this.user.requested) {
|
||||||
|
return this.$t('user_card.follow_sent')
|
||||||
|
} else {
|
||||||
|
return this.$t('user_card.follow')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onClick () {
|
||||||
|
this.user.following ? this.unfollow() : this.follow()
|
||||||
|
},
|
||||||
|
follow () {
|
||||||
|
this.inProgress = true
|
||||||
|
requestFollow(this.user, this.$store).then(() => {
|
||||||
|
this.inProgress = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
unfollow () {
|
||||||
|
const store = this.$store
|
||||||
|
this.inProgress = true
|
||||||
|
requestUnfollow(this.user, store).then(() => {
|
||||||
|
this.inProgress = false
|
||||||
|
store.commit('removeStatus', { timeline: 'friends', userId: this.user.id })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
src/components/follow_button/follow_button.vue
Normal file
13
src/components/follow_button/follow_button.vue
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<template>
|
||||||
|
<button
|
||||||
|
class="btn btn-default follow-button"
|
||||||
|
:class="{ pressed: isPressed }"
|
||||||
|
:disabled="inProgress"
|
||||||
|
:title="title"
|
||||||
|
@click="onClick"
|
||||||
|
>
|
||||||
|
{{ label }}
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./follow_button.js"></script>
|
|
@ -1,20 +1,16 @@
|
||||||
import BasicUserCard from '../basic_user_card/basic_user_card.vue'
|
import BasicUserCard from '../basic_user_card/basic_user_card.vue'
|
||||||
import RemoteFollow from '../remote_follow/remote_follow.vue'
|
import RemoteFollow from '../remote_follow/remote_follow.vue'
|
||||||
import { requestFollow, requestUnfollow } from '../../services/follow_manipulate/follow_manipulate'
|
import FollowButton from '../follow_button/follow_button.vue'
|
||||||
|
|
||||||
const FollowCard = {
|
const FollowCard = {
|
||||||
props: [
|
props: [
|
||||||
'user',
|
'user',
|
||||||
'noFollowsYou'
|
'noFollowsYou'
|
||||||
],
|
],
|
||||||
data () {
|
|
||||||
return {
|
|
||||||
inProgress: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
components: {
|
components: {
|
||||||
BasicUserCard,
|
BasicUserCard,
|
||||||
RemoteFollow
|
RemoteFollow,
|
||||||
|
FollowButton
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
isMe () {
|
isMe () {
|
||||||
|
@ -23,20 +19,6 @@ const FollowCard = {
|
||||||
loggedIn () {
|
loggedIn () {
|
||||||
return this.$store.state.users.currentUser
|
return this.$store.state.users.currentUser
|
||||||
}
|
}
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
followUser () {
|
|
||||||
this.inProgress = true
|
|
||||||
requestFollow(this.user, this.$store).then(() => {
|
|
||||||
this.inProgress = false
|
|
||||||
})
|
|
||||||
},
|
|
||||||
unfollowUser () {
|
|
||||||
this.inProgress = true
|
|
||||||
requestUnfollow(this.user, this.$store).then(() => {
|
|
||||||
this.inProgress = false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,36 +16,11 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<button
|
<FollowButton
|
||||||
v-if="!user.following"
|
:user="user"
|
||||||
class="btn btn-default follow-card-follow-button"
|
class="follow-card-follow-button"
|
||||||
:disabled="inProgress"
|
:label-following="$t('user_card.follow_unfollow')"
|
||||||
:title="user.requested ? $t('user_card.follow_again') : ''"
|
/>
|
||||||
@click="followUser"
|
|
||||||
>
|
|
||||||
<template v-if="inProgress">
|
|
||||||
{{ $t('user_card.follow_progress') }}
|
|
||||||
</template>
|
|
||||||
<template v-else-if="user.requested">
|
|
||||||
{{ $t('user_card.follow_sent') }}
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
{{ $t('user_card.follow') }}
|
|
||||||
</template>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
v-else
|
|
||||||
class="btn btn-default follow-card-follow-button pressed"
|
|
||||||
:disabled="inProgress"
|
|
||||||
@click="unfollowUser"
|
|
||||||
>
|
|
||||||
<template v-if="inProgress">
|
|
||||||
{{ $t('user_card.follow_progress') }}
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
{{ $t('user_card.follow_unfollow') }}
|
|
||||||
</template>
|
|
||||||
</button>
|
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</basic-user-card>
|
</basic-user-card>
|
||||||
|
|
|
@ -1,23 +1,18 @@
|
||||||
import Attachment from '../attachment/attachment.vue'
|
import Attachment from '../attachment/attachment.vue'
|
||||||
import { chunk, last, dropRight } from 'lodash'
|
import { chunk, last, dropRight, sumBy } from 'lodash'
|
||||||
|
|
||||||
const Gallery = {
|
const Gallery = {
|
||||||
data: () => ({
|
|
||||||
width: 500
|
|
||||||
}),
|
|
||||||
props: [
|
props: [
|
||||||
'attachments',
|
'attachments',
|
||||||
'nsfw',
|
'nsfw',
|
||||||
'setMedia'
|
'setMedia'
|
||||||
],
|
],
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
sizes: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
components: { Attachment },
|
components: { Attachment },
|
||||||
mounted () {
|
|
||||||
this.resize()
|
|
||||||
window.addEventListener('resize', this.resize)
|
|
||||||
},
|
|
||||||
destroyed () {
|
|
||||||
window.removeEventListener('resize', this.resize)
|
|
||||||
},
|
|
||||||
computed: {
|
computed: {
|
||||||
rows () {
|
rows () {
|
||||||
if (!this.attachments) {
|
if (!this.attachments) {
|
||||||
|
@ -33,21 +28,24 @@ const Gallery = {
|
||||||
}
|
}
|
||||||
return rows
|
return rows
|
||||||
},
|
},
|
||||||
rowHeight () {
|
|
||||||
return itemsPerRow => ({ 'height': `${(this.width / (itemsPerRow + 0.6))}px` })
|
|
||||||
},
|
|
||||||
useContainFit () {
|
useContainFit () {
|
||||||
return this.$store.state.config.useContainFit
|
return this.$store.getters.mergedConfig.useContainFit
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
resize () {
|
onNaturalSizeLoad (id, size) {
|
||||||
// Quick optimization to make resizing not always trigger state change,
|
this.$set(this.sizes, id, size)
|
||||||
// only update attachment size in 10px steps
|
},
|
||||||
const width = Math.floor(this.$el.getBoundingClientRect().width / 10) * 10
|
rowStyle (itemsPerRow) {
|
||||||
if (this.width !== width) {
|
return { 'padding-bottom': `${(100 / (itemsPerRow + 0.6))}%` }
|
||||||
this.width = width
|
},
|
||||||
}
|
itemStyle (id, row) {
|
||||||
|
const total = sumBy(row, item => this.getAspectRatio(item.id))
|
||||||
|
return { flex: `${this.getAspectRatio(id) / total} 1 0%` }
|
||||||
|
},
|
||||||
|
getAspectRatio (id) {
|
||||||
|
const size = this.sizes[id]
|
||||||
|
return size ? size.width / size.height : 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,17 +7,21 @@
|
||||||
v-for="(row, index) in rows"
|
v-for="(row, index) in rows"
|
||||||
:key="index"
|
:key="index"
|
||||||
class="gallery-row"
|
class="gallery-row"
|
||||||
:style="rowHeight(row.length)"
|
:style="rowStyle(row.length)"
|
||||||
:class="{ 'contain-fit': useContainFit, 'cover-fit': !useContainFit }"
|
:class="{ 'contain-fit': useContainFit, 'cover-fit': !useContainFit }"
|
||||||
>
|
>
|
||||||
<attachment
|
<div class="gallery-row-inner">
|
||||||
v-for="attachment in row"
|
<attachment
|
||||||
:key="attachment.id"
|
v-for="attachment in row"
|
||||||
:set-media="setMedia"
|
:key="attachment.id"
|
||||||
:nsfw="nsfw"
|
:set-media="setMedia"
|
||||||
:attachment="attachment"
|
:nsfw="nsfw"
|
||||||
:allow-play="false"
|
:attachment="attachment"
|
||||||
/>
|
:allow-play="false"
|
||||||
|
:natural-size-load="onNaturalSizeLoad.bind(null, attachment.id)"
|
||||||
|
:style="itemStyle(attachment.id, row)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -28,15 +32,24 @@
|
||||||
@import '../../_variables.scss';
|
@import '../../_variables.scss';
|
||||||
|
|
||||||
.gallery-row {
|
.gallery-row {
|
||||||
height: 200px;
|
position: relative;
|
||||||
|
height: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
flex-wrap: nowrap;
|
|
||||||
align-content: stretch;
|
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
margin-top: 0.5em;
|
margin-top: 0.5em;
|
||||||
|
|
||||||
|
.gallery-row-inner {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
align-content: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: specificity problem with this and .attachments.attachment
|
// FIXME: specificity problem with this and .attachments.attachment
|
||||||
// we shouldn't have the need for .image here
|
// we shouldn't have the need for .image here
|
||||||
.attachment.image {
|
.attachment.image {
|
||||||
|
|
|
@ -40,7 +40,7 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
language: {
|
language: {
|
||||||
get: function () { return this.$store.state.config.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
|
this.$i18n.locale = val
|
||||||
|
|
|
@ -59,6 +59,8 @@ const LoginForm = {
|
||||||
if (result.error) {
|
if (result.error) {
|
||||||
if (result.error === 'mfa_required') {
|
if (result.error === 'mfa_required') {
|
||||||
this.requireMFA({ app: app, settings: result })
|
this.requireMFA({ app: app, settings: result })
|
||||||
|
} else if (result.identifier === 'password_reset_required') {
|
||||||
|
this.$router.push({ name: 'password-reset', params: { passwordResetRequested: true } })
|
||||||
} else {
|
} else {
|
||||||
this.error = result.error
|
this.error = result.error
|
||||||
this.focusOnPasswordInput()
|
this.focusOnPasswordInput()
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
import StillImage from '../still-image/still-image.vue'
|
import StillImage from '../still-image/still-image.vue'
|
||||||
import VideoAttachment from '../video_attachment/video_attachment.vue'
|
import VideoAttachment from '../video_attachment/video_attachment.vue'
|
||||||
|
import Modal from '../modal/modal.vue'
|
||||||
import fileTypeService from '../../services/file_type/file_type.service.js'
|
import fileTypeService from '../../services/file_type/file_type.service.js'
|
||||||
|
|
||||||
const MediaModal = {
|
const MediaModal = {
|
||||||
components: {
|
components: {
|
||||||
StillImage,
|
StillImage,
|
||||||
VideoAttachment
|
VideoAttachment,
|
||||||
|
Modal
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
showing () {
|
showing () {
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<Modal
|
||||||
v-if="showing"
|
v-if="showing"
|
||||||
v-body-scroll-lock="showing"
|
class="media-modal-view"
|
||||||
class="modal-view media-modal-view"
|
@backdropClicked="hide"
|
||||||
@click.prevent="hide"
|
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
v-if="type === 'image'"
|
v-if="type === 'image'"
|
||||||
|
@ -33,21 +32,15 @@
|
||||||
>
|
>
|
||||||
<i class="icon-right-open arrow-icon" />
|
<i class="icon-right-open arrow-icon" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</Modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./media_modal.js"></script>
|
<script src="./media_modal.js"></script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@import '../../_variables.scss';
|
.modal-view.media-modal-view {
|
||||||
|
|
||||||
.media-modal-view {
|
|
||||||
z-index: 1001;
|
z-index: 1001;
|
||||||
|
|
||||||
body:not(.scroll-locked) & {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
.modal-view-button-arrow {
|
.modal-view-button-arrow {
|
||||||
opacity: 0.75;
|
opacity: 0.75;
|
||||||
|
@ -114,5 +107,4 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -63,7 +63,7 @@ const MobileNav = {
|
||||||
this.$refs.notifications.markAsSeen()
|
this.$refs.notifications.markAsSeen()
|
||||||
},
|
},
|
||||||
onScroll ({ target: { scrollTop, clientHeight, scrollHeight } }) {
|
onScroll ({ target: { scrollTop, clientHeight, scrollHeight } }) {
|
||||||
if (this.$store.state.config.autoLoad && scrollTop + clientHeight >= scrollHeight) {
|
if (this.$store.getters.mergedConfig.autoLoad && scrollTop + clientHeight >= scrollHeight) {
|
||||||
this.$refs.notifications.fetchOlderNotifications()
|
this.$refs.notifications.fetchOlderNotifications()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ const MobilePostStatusButton = {
|
||||||
return this.autohideFloatingPostButton && (this.hidden || this.inputActive)
|
return this.autohideFloatingPostButton && (this.hidden || this.inputActive)
|
||||||
},
|
},
|
||||||
autohideFloatingPostButton () {
|
autohideFloatingPostButton () {
|
||||||
return !!this.$store.state.config.autohideFloatingPostButton
|
return !!this.$store.getters.mergedConfig.autohideFloatingPostButton
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
|
52
src/components/modal/modal.vue
Normal file
52
src/components/modal/modal.vue
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
v-show="isOpen"
|
||||||
|
v-body-scroll-lock="isOpen"
|
||||||
|
class="modal-view"
|
||||||
|
@click.self="$emit('backdropClicked')"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
isOpen: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.modal-view {
|
||||||
|
z-index: 1000;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
overflow: auto;
|
||||||
|
animation-duration: 0.2s;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
animation-name: modal-background-fadein;
|
||||||
|
|
||||||
|
body:not(.scroll-locked) & {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes modal-background-fadein {
|
||||||
|
from {
|
||||||
|
background-color: rgba(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -3,9 +3,7 @@
|
||||||
<v-popover
|
<v-popover
|
||||||
trigger="click"
|
trigger="click"
|
||||||
class="moderation-tools-popover"
|
class="moderation-tools-popover"
|
||||||
:container="false"
|
|
||||||
placement="bottom-end"
|
placement="bottom-end"
|
||||||
:offset="5"
|
|
||||||
@show="showDropDown = true"
|
@show="showDropDown = true"
|
||||||
@hide="showDropDown = false"
|
@hide="showDropDown = false"
|
||||||
>
|
>
|
||||||
|
|
|
@ -39,7 +39,7 @@ const Notification = {
|
||||||
return highlightClass(this.notification.from_profile)
|
return highlightClass(this.notification.from_profile)
|
||||||
},
|
},
|
||||||
userStyle () {
|
userStyle () {
|
||||||
const highlight = this.$store.state.config.highlight
|
const highlight = this.$store.getters.mergedConfig.highlight
|
||||||
const user = this.notification.from_profile
|
const user = this.notification.from_profile
|
||||||
return highlightStyle(highlight[user.screen_name])
|
return highlightStyle(highlight[user.screen_name])
|
||||||
},
|
},
|
||||||
|
|
|
@ -25,6 +25,12 @@ const passwordReset = {
|
||||||
this.$router.push({ name: 'root' })
|
this.$router.push({ name: 'root' })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
props: {
|
||||||
|
passwordResetRequested: {
|
||||||
|
default: false,
|
||||||
|
type: Boolean
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
dismissError () {
|
dismissError () {
|
||||||
this.error = null
|
this.error = null
|
||||||
|
|
|
@ -10,7 +10,10 @@
|
||||||
>
|
>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div v-if="!mailerEnabled">
|
<div v-if="!mailerEnabled">
|
||||||
<p>
|
<p v-if="passwordResetRequested">
|
||||||
|
{{ $t('password_reset.password_reset_required_but_mailer_is_disabled') }}
|
||||||
|
</p>
|
||||||
|
<p v-else>
|
||||||
{{ $t('password_reset.password_reset_disabled') }}
|
{{ $t('password_reset.password_reset_disabled') }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -25,6 +28,12 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
|
<p
|
||||||
|
v-if="passwordResetRequested"
|
||||||
|
class="password-reset-required error"
|
||||||
|
>
|
||||||
|
{{ $t('password_reset.password_reset_required') }}
|
||||||
|
</p>
|
||||||
<p>
|
<p>
|
||||||
{{ $t('password_reset.instruction') }}
|
{{ $t('password_reset.instruction') }}
|
||||||
</p>
|
</p>
|
||||||
|
@ -104,6 +113,11 @@
|
||||||
margin: 0.3em 0.0em 1em;
|
margin: 0.3em 0.0em 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.password-reset-required {
|
||||||
|
background-color: var(--alertError, $fallback--alertError);
|
||||||
|
padding: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
.notice-dismissible {
|
.notice-dismissible {
|
||||||
padding-right: 2rem;
|
padding-right: 2rem;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
border-color: $fallback--bg;
|
border-color: $fallback--bg;
|
||||||
border-color: var(--bg, $fallback--bg);
|
border-color: var(--bg, $fallback--bg);
|
||||||
z-index: 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&[x-placement^="top"] {
|
&[x-placement^="top"] {
|
||||||
|
@ -31,7 +30,7 @@
|
||||||
border-left-color: transparent !important;
|
border-left-color: transparent !important;
|
||||||
border-right-color: transparent !important;
|
border-right-color: transparent !important;
|
||||||
border-bottom-color: transparent !important;
|
border-bottom-color: transparent !important;
|
||||||
bottom: -5px;
|
bottom: -4px;
|
||||||
left: calc(50% - 5px);
|
left: calc(50% - 5px);
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
|
@ -46,7 +45,7 @@
|
||||||
border-left-color: transparent !important;
|
border-left-color: transparent !important;
|
||||||
border-right-color: transparent !important;
|
border-right-color: transparent !important;
|
||||||
border-top-color: transparent !important;
|
border-top-color: transparent !important;
|
||||||
top: -5px;
|
top: -4px;
|
||||||
left: calc(50% - 5px);
|
left: calc(50% - 5px);
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
|
@ -61,7 +60,7 @@
|
||||||
border-left-color: transparent !important;
|
border-left-color: transparent !important;
|
||||||
border-top-color: transparent !important;
|
border-top-color: transparent !important;
|
||||||
border-bottom-color: transparent !important;
|
border-bottom-color: transparent !important;
|
||||||
left: -5px;
|
left: -4px;
|
||||||
top: calc(50% - 5px);
|
top: calc(50% - 5px);
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
|
@ -76,7 +75,7 @@
|
||||||
border-top-color: transparent !important;
|
border-top-color: transparent !important;
|
||||||
border-right-color: transparent !important;
|
border-right-color: transparent !important;
|
||||||
border-bottom-color: transparent !important;
|
border-bottom-color: transparent !important;
|
||||||
right: -5px;
|
right: -4px;
|
||||||
top: calc(50% - 5px);
|
top: calc(50% - 5px);
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
|
|
|
@ -7,6 +7,8 @@ import fileTypeService from '../../services/file_type/file_type.service.js'
|
||||||
import { findOffset } from '../../services/offset_finder/offset_finder.service.js'
|
import { findOffset } from '../../services/offset_finder/offset_finder.service.js'
|
||||||
import { reject, map, uniqBy } from 'lodash'
|
import { reject, map, uniqBy } from 'lodash'
|
||||||
import suggestor from '../emoji_input/suggestor.js'
|
import suggestor from '../emoji_input/suggestor.js'
|
||||||
|
import { mapGetters } from 'vuex'
|
||||||
|
import Checkbox from '../checkbox/checkbox.vue'
|
||||||
|
|
||||||
const buildMentionsString = ({ user, attentions = [] }, currentUser) => {
|
const buildMentionsString = ({ user, attentions = [] }, currentUser) => {
|
||||||
let allAttentions = [...attentions]
|
let allAttentions = [...attentions]
|
||||||
|
@ -35,7 +37,8 @@ const PostStatusForm = {
|
||||||
MediaUpload,
|
MediaUpload,
|
||||||
EmojiInput,
|
EmojiInput,
|
||||||
PollForm,
|
PollForm,
|
||||||
ScopeSelector
|
ScopeSelector,
|
||||||
|
Checkbox
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
this.resize(this.$refs.textarea)
|
this.resize(this.$refs.textarea)
|
||||||
|
@ -50,9 +53,7 @@ const PostStatusForm = {
|
||||||
const preset = this.$route.query.message
|
const preset = this.$route.query.message
|
||||||
let statusText = preset || ''
|
let statusText = preset || ''
|
||||||
|
|
||||||
const scopeCopy = typeof this.$store.state.config.scopeCopy === 'undefined'
|
const { scopeCopy } = this.$store.getters.mergedConfig
|
||||||
? this.$store.state.instance.scopeCopy
|
|
||||||
: this.$store.state.config.scopeCopy
|
|
||||||
|
|
||||||
if (this.replyTo) {
|
if (this.replyTo) {
|
||||||
const currentUser = this.$store.state.users.currentUser
|
const currentUser = this.$store.state.users.currentUser
|
||||||
|
@ -63,9 +64,7 @@ const PostStatusForm = {
|
||||||
? this.copyMessageScope
|
? this.copyMessageScope
|
||||||
: this.$store.state.users.currentUser.default_scope
|
: this.$store.state.users.currentUser.default_scope
|
||||||
|
|
||||||
const contentType = typeof this.$store.state.config.postContentType === 'undefined'
|
const { postContentType: contentType } = this.$store.getters.mergedConfig
|
||||||
? this.$store.state.instance.postContentType
|
|
||||||
: this.$store.state.config.postContentType
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
dropFiles: [],
|
dropFiles: [],
|
||||||
|
@ -94,10 +93,7 @@ const PostStatusForm = {
|
||||||
return this.$store.state.users.currentUser.default_scope
|
return this.$store.state.users.currentUser.default_scope
|
||||||
},
|
},
|
||||||
showAllScopes () {
|
showAllScopes () {
|
||||||
const minimalScopesMode = typeof this.$store.state.config.minimalScopesMode === 'undefined'
|
return !this.mergedConfig.minimalScopesMode
|
||||||
? this.$store.state.instance.minimalScopesMode
|
|
||||||
: this.$store.state.config.minimalScopesMode
|
|
||||||
return !minimalScopesMode
|
|
||||||
},
|
},
|
||||||
emojiUserSuggestor () {
|
emojiUserSuggestor () {
|
||||||
return suggestor({
|
return suggestor({
|
||||||
|
@ -145,13 +141,7 @@ const PostStatusForm = {
|
||||||
return this.$store.state.instance.minimalScopesMode
|
return this.$store.state.instance.minimalScopesMode
|
||||||
},
|
},
|
||||||
alwaysShowSubject () {
|
alwaysShowSubject () {
|
||||||
if (typeof this.$store.state.config.alwaysShowSubjectInput !== 'undefined') {
|
return this.mergedConfig.alwaysShowSubjectInput
|
||||||
return this.$store.state.config.alwaysShowSubjectInput
|
|
||||||
} else if (typeof this.$store.state.instance.alwaysShowSubjectInput !== 'undefined') {
|
|
||||||
return this.$store.state.instance.alwaysShowSubjectInput
|
|
||||||
} else {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
postFormats () {
|
postFormats () {
|
||||||
return this.$store.state.instance.postFormats || []
|
return this.$store.state.instance.postFormats || []
|
||||||
|
@ -164,13 +154,14 @@ const PostStatusForm = {
|
||||||
this.$store.state.instance.pollLimits.max_options >= 2
|
this.$store.state.instance.pollLimits.max_options >= 2
|
||||||
},
|
},
|
||||||
hideScopeNotice () {
|
hideScopeNotice () {
|
||||||
return this.$store.state.config.hideScopeNotice
|
return this.$store.getters.mergedConfig.hideScopeNotice
|
||||||
},
|
},
|
||||||
pollContentError () {
|
pollContentError () {
|
||||||
return this.pollFormVisible &&
|
return this.pollFormVisible &&
|
||||||
this.newStatus.poll &&
|
this.newStatus.poll &&
|
||||||
this.newStatus.poll.error
|
this.newStatus.poll.error
|
||||||
}
|
},
|
||||||
|
...mapGetters(['mergedConfig'])
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
postStatus (newStatus) {
|
postStatus (newStatus) {
|
||||||
|
|
|
@ -261,12 +261,9 @@
|
||||||
v-if="newStatus.files.length > 0"
|
v-if="newStatus.files.length > 0"
|
||||||
class="upload_settings"
|
class="upload_settings"
|
||||||
>
|
>
|
||||||
<input
|
<Checkbox v-model="newStatus.nsfw">
|
||||||
id="filesSensitive"
|
{{ $t('post_status.attachments_sensitive') }}
|
||||||
v-model="newStatus.nsfw"
|
</Checkbox>
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="filesSensitive">{{ $t('post_status.attachments_sensitive') }}</label>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
import PostStatusForm from '../post_status_form/post_status_form.vue'
|
import PostStatusForm from '../post_status_form/post_status_form.vue'
|
||||||
|
import Modal from '../modal/modal.vue'
|
||||||
import get from 'lodash/get'
|
import get from 'lodash/get'
|
||||||
|
|
||||||
const PostStatusModal = {
|
const PostStatusModal = {
|
||||||
components: {
|
components: {
|
||||||
PostStatusForm
|
PostStatusForm,
|
||||||
|
Modal
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<Modal
|
||||||
v-if="isLoggedIn && !resettingForm"
|
v-if="isLoggedIn && !resettingForm"
|
||||||
v-show="modalActivated"
|
:is-open="modalActivated"
|
||||||
class="post-form-modal-view modal-view"
|
class="post-form-modal-view"
|
||||||
@click="closeModal"
|
@backdropClicked="closeModal"
|
||||||
>
|
>
|
||||||
<div
|
<div class="post-form-modal-panel panel">
|
||||||
class="post-form-modal-panel panel"
|
|
||||||
@click.stop=""
|
|
||||||
>
|
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
{{ $t('post_status.new_status') }}
|
{{ $t('post_status.new_status') }}
|
||||||
</div>
|
</div>
|
||||||
|
@ -18,15 +15,13 @@
|
||||||
@posted="closeModal"
|
@posted="closeModal"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./post_status_modal.js"></script>
|
<script src="./post_status_modal.js"></script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@import '../../_variables.scss';
|
.modal-view.post-form-modal-view {
|
||||||
|
|
||||||
.post-form-modal-view {
|
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
|
import { mapGetters } from 'vuex'
|
||||||
|
|
||||||
const RetweetButton = {
|
const RetweetButton = {
|
||||||
props: ['status', 'loggedIn', 'visibility'],
|
props: ['status', 'loggedIn', 'visibility'],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
hidePostStatsLocal: typeof this.$store.state.config.hidePostStats === 'undefined'
|
|
||||||
? this.$store.state.instance.hidePostStats
|
|
||||||
: this.$store.state.config.hidePostStats,
|
|
||||||
animated: false
|
animated: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -28,7 +27,8 @@ const RetweetButton = {
|
||||||
'retweeted-empty': !this.status.repeated,
|
'retweeted-empty': !this.status.repeated,
|
||||||
'animate-spin': this.animated
|
'animate-spin': this.animated
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
...mapGetters(['mergedConfig'])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
:title="$t('tool_tip.repeat')"
|
:title="$t('tool_tip.repeat')"
|
||||||
@click.prevent="retweet()"
|
@click.prevent="retweet()"
|
||||||
/>
|
/>
|
||||||
<span v-if="!hidePostStatsLocal && status.repeat_num > 0">{{ status.repeat_num }}</span>
|
<span v-if="!mergedConfig.hidePostStats && status.repeat_num > 0">{{ status.repeat_num }}</span>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<i
|
<i
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
class="button-icon icon-retweet"
|
class="button-icon icon-retweet"
|
||||||
:title="$t('tool_tip.repeat')"
|
:title="$t('tool_tip.repeat')"
|
||||||
/>
|
/>
|
||||||
<span v-if="!hidePostStatsLocal && status.repeat_num > 0">{{ status.repeat_num }}</span>
|
<span v-if="!mergedConfig.hidePostStats && status.repeat_num > 0">{{ status.repeat_num }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -5,88 +5,22 @@ import TabSwitcher from '../tab_switcher/tab_switcher.js'
|
||||||
import StyleSwitcher from '../style_switcher/style_switcher.vue'
|
import StyleSwitcher from '../style_switcher/style_switcher.vue'
|
||||||
import InterfaceLanguageSwitcher from '../interface_language_switcher/interface_language_switcher.vue'
|
import InterfaceLanguageSwitcher from '../interface_language_switcher/interface_language_switcher.vue'
|
||||||
import { extractCommit } from '../../services/version/version.service'
|
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 pleromaFeCommitUrl = 'https://git.pleroma.social/pleroma/pleroma-fe/commit/'
|
||||||
const pleromaBeCommitUrl = 'https://git.pleroma.social/pleroma/pleroma/commit/'
|
const pleromaBeCommitUrl = 'https://git.pleroma.social/pleroma/pleroma/commit/'
|
||||||
|
|
||||||
|
const multiChoiceProperties = [
|
||||||
|
'postContentType',
|
||||||
|
'subjectLineBehavior'
|
||||||
|
]
|
||||||
|
|
||||||
const settings = {
|
const settings = {
|
||||||
data () {
|
data () {
|
||||||
const user = this.$store.state.config
|
|
||||||
const instance = this.$store.state.instance
|
const instance = this.$store.state.instance
|
||||||
|
|
||||||
return {
|
return {
|
||||||
hideAttachmentsLocal: user.hideAttachments,
|
|
||||||
padEmojiLocal: user.padEmoji,
|
|
||||||
hideAttachmentsInConvLocal: user.hideAttachmentsInConv,
|
|
||||||
maxThumbnails: user.maxThumbnails,
|
|
||||||
hideNsfwLocal: user.hideNsfw,
|
|
||||||
useOneClickNsfw: user.useOneClickNsfw,
|
|
||||||
hideISPLocal: user.hideISP,
|
|
||||||
preloadImage: user.preloadImage,
|
|
||||||
|
|
||||||
hidePostStatsLocal: typeof user.hidePostStats === 'undefined'
|
|
||||||
? instance.hidePostStats
|
|
||||||
: user.hidePostStats,
|
|
||||||
hidePostStatsDefault: this.$t('settings.values.' + instance.hidePostStats),
|
|
||||||
|
|
||||||
hideUserStatsLocal: typeof user.hideUserStats === 'undefined'
|
|
||||||
? instance.hideUserStats
|
|
||||||
: user.hideUserStats,
|
|
||||||
hideUserStatsDefault: this.$t('settings.values.' + instance.hideUserStats),
|
|
||||||
|
|
||||||
hideFilteredStatusesLocal: typeof user.hideFilteredStatuses === 'undefined'
|
|
||||||
? instance.hideFilteredStatuses
|
|
||||||
: user.hideFilteredStatuses,
|
|
||||||
hideFilteredStatusesDefault: this.$t('settings.values.' + instance.hideFilteredStatuses),
|
|
||||||
|
|
||||||
notificationVisibilityLocal: user.notificationVisibility,
|
|
||||||
replyVisibilityLocal: user.replyVisibility,
|
|
||||||
loopVideoLocal: user.loopVideo,
|
|
||||||
muteWordsString: user.muteWords.join('\n'),
|
|
||||||
autoLoadLocal: user.autoLoad,
|
|
||||||
streamingLocal: user.streaming,
|
|
||||||
pauseOnUnfocusedLocal: user.pauseOnUnfocused,
|
|
||||||
hoverPreviewLocal: user.hoverPreview,
|
|
||||||
autohideFloatingPostButtonLocal: user.autohideFloatingPostButton,
|
|
||||||
|
|
||||||
hideMutedPostsLocal: typeof user.hideMutedPosts === 'undefined'
|
|
||||||
? instance.hideMutedPosts
|
|
||||||
: user.hideMutedPosts,
|
|
||||||
hideMutedPostsDefault: this.$t('settings.values.' + instance.hideMutedPosts),
|
|
||||||
|
|
||||||
collapseMessageWithSubjectLocal: typeof user.collapseMessageWithSubject === 'undefined'
|
|
||||||
? instance.collapseMessageWithSubject
|
|
||||||
: user.collapseMessageWithSubject,
|
|
||||||
collapseMessageWithSubjectDefault: this.$t('settings.values.' + instance.collapseMessageWithSubject),
|
|
||||||
|
|
||||||
subjectLineBehaviorLocal: typeof user.subjectLineBehavior === 'undefined'
|
|
||||||
? instance.subjectLineBehavior
|
|
||||||
: user.subjectLineBehavior,
|
|
||||||
subjectLineBehaviorDefault: instance.subjectLineBehavior,
|
|
||||||
|
|
||||||
postContentTypeLocal: typeof user.postContentType === 'undefined'
|
|
||||||
? instance.postContentType
|
|
||||||
: user.postContentType,
|
|
||||||
postContentTypeDefault: instance.postContentType,
|
|
||||||
|
|
||||||
alwaysShowSubjectInputLocal: typeof user.alwaysShowSubjectInput === 'undefined'
|
|
||||||
? instance.alwaysShowSubjectInput
|
|
||||||
: user.alwaysShowSubjectInput,
|
|
||||||
alwaysShowSubjectInputDefault: this.$t('settings.values.' + instance.alwaysShowSubjectInput),
|
|
||||||
|
|
||||||
scopeCopyLocal: typeof user.scopeCopy === 'undefined'
|
|
||||||
? instance.scopeCopy
|
|
||||||
: user.scopeCopy,
|
|
||||||
scopeCopyDefault: this.$t('settings.values.' + instance.scopeCopy),
|
|
||||||
|
|
||||||
minimalScopesModeLocal: typeof user.minimalScopesMode === 'undefined'
|
|
||||||
? instance.minimalScopesMode
|
|
||||||
: user.minimalScopesMode,
|
|
||||||
minimalScopesModeDefault: this.$t('settings.values.' + instance.minimalScopesMode),
|
|
||||||
|
|
||||||
stopGifs: user.stopGifs,
|
|
||||||
webPushNotificationsLocal: user.webPushNotifications,
|
|
||||||
loopVideoSilentOnlyLocal: user.loopVideosSilentOnly,
|
|
||||||
loopSilentAvailable:
|
loopSilentAvailable:
|
||||||
// Firefox
|
// Firefox
|
||||||
Object.getOwnPropertyDescriptor(HTMLVideoElement.prototype, 'mozHasAudio') ||
|
Object.getOwnPropertyDescriptor(HTMLVideoElement.prototype, 'mozHasAudio') ||
|
||||||
|
@ -94,8 +28,6 @@ const settings = {
|
||||||
Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'webkitAudioDecodedByteCount') ||
|
Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'webkitAudioDecodedByteCount') ||
|
||||||
// Future spec, still not supported in Nightly 63 as of 08/2018
|
// Future spec, still not supported in Nightly 63 as of 08/2018
|
||||||
Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'audioTracks'),
|
Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'audioTracks'),
|
||||||
playVideosInModal: user.playVideosInModal,
|
|
||||||
useContainFit: user.useContainFit,
|
|
||||||
|
|
||||||
backendVersion: instance.backendVersion,
|
backendVersion: instance.backendVersion,
|
||||||
frontendVersion: instance.frontendVersion
|
frontendVersion: instance.frontendVersion
|
||||||
|
@ -104,7 +36,8 @@ const settings = {
|
||||||
components: {
|
components: {
|
||||||
TabSwitcher,
|
TabSwitcher,
|
||||||
StyleSwitcher,
|
StyleSwitcher,
|
||||||
InterfaceLanguageSwitcher
|
InterfaceLanguageSwitcher,
|
||||||
|
Checkbox
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
user () {
|
user () {
|
||||||
|
@ -122,116 +55,56 @@ const settings = {
|
||||||
},
|
},
|
||||||
backendVersionLink () {
|
backendVersionLink () {
|
||||||
return pleromaBeCommitUrl + extractCommit(this.backendVersion)
|
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)
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// Updating nested properties
|
||||||
watch: {
|
watch: {
|
||||||
hideAttachmentsLocal (value) {
|
notificationVisibility: {
|
||||||
this.$store.dispatch('setOption', { name: 'hideAttachments', value })
|
handler (value) {
|
||||||
},
|
this.$store.dispatch('setOption', {
|
||||||
padEmojiLocal (value) {
|
name: 'notificationVisibility',
|
||||||
this.$store.dispatch('setOption', { name: 'padEmoji', value })
|
value: this.$store.getters.mergedConfig.notificationVisibility
|
||||||
},
|
})
|
||||||
hideAttachmentsInConvLocal (value) {
|
},
|
||||||
this.$store.dispatch('setOption', { name: 'hideAttachmentsInConv', value })
|
deep: true
|
||||||
},
|
|
||||||
hidePostStatsLocal (value) {
|
|
||||||
this.$store.dispatch('setOption', { name: 'hidePostStats', value })
|
|
||||||
},
|
|
||||||
hideUserStatsLocal (value) {
|
|
||||||
this.$store.dispatch('setOption', { name: 'hideUserStats', value })
|
|
||||||
},
|
|
||||||
hideFilteredStatusesLocal (value) {
|
|
||||||
this.$store.dispatch('setOption', { name: 'hideFilteredStatuses', value })
|
|
||||||
},
|
|
||||||
hideNsfwLocal (value) {
|
|
||||||
this.$store.dispatch('setOption', { name: 'hideNsfw', value })
|
|
||||||
},
|
|
||||||
useOneClickNsfw (value) {
|
|
||||||
this.$store.dispatch('setOption', { name: 'useOneClickNsfw', value })
|
|
||||||
},
|
|
||||||
preloadImage (value) {
|
|
||||||
this.$store.dispatch('setOption', { name: 'preloadImage', value })
|
|
||||||
},
|
|
||||||
hideISPLocal (value) {
|
|
||||||
this.$store.dispatch('setOption', { name: 'hideISP', value })
|
|
||||||
},
|
|
||||||
'notificationVisibilityLocal.likes' (value) {
|
|
||||||
this.$store.dispatch('setOption', { name: 'notificationVisibility', value: this.$store.state.config.notificationVisibility })
|
|
||||||
},
|
|
||||||
'notificationVisibilityLocal.follows' (value) {
|
|
||||||
this.$store.dispatch('setOption', { name: 'notificationVisibility', value: this.$store.state.config.notificationVisibility })
|
|
||||||
},
|
|
||||||
'notificationVisibilityLocal.repeats' (value) {
|
|
||||||
this.$store.dispatch('setOption', { name: 'notificationVisibility', value: this.$store.state.config.notificationVisibility })
|
|
||||||
},
|
|
||||||
'notificationVisibilityLocal.mentions' (value) {
|
|
||||||
this.$store.dispatch('setOption', { name: 'notificationVisibility', value: this.$store.state.config.notificationVisibility })
|
|
||||||
},
|
|
||||||
replyVisibilityLocal (value) {
|
|
||||||
this.$store.dispatch('setOption', { name: 'replyVisibility', value })
|
|
||||||
},
|
|
||||||
loopVideoLocal (value) {
|
|
||||||
this.$store.dispatch('setOption', { name: 'loopVideo', value })
|
|
||||||
},
|
|
||||||
loopVideoSilentOnlyLocal (value) {
|
|
||||||
this.$store.dispatch('setOption', { name: 'loopVideoSilentOnly', value })
|
|
||||||
},
|
|
||||||
autoLoadLocal (value) {
|
|
||||||
this.$store.dispatch('setOption', { name: 'autoLoad', value })
|
|
||||||
},
|
|
||||||
streamingLocal (value) {
|
|
||||||
this.$store.dispatch('setOption', { name: 'streaming', value })
|
|
||||||
},
|
|
||||||
pauseOnUnfocusedLocal (value) {
|
|
||||||
this.$store.dispatch('setOption', { name: 'pauseOnUnfocused', value })
|
|
||||||
},
|
|
||||||
hoverPreviewLocal (value) {
|
|
||||||
this.$store.dispatch('setOption', { name: 'hoverPreview', value })
|
|
||||||
},
|
|
||||||
autohideFloatingPostButtonLocal (value) {
|
|
||||||
this.$store.dispatch('setOption', { name: 'autohideFloatingPostButton', value })
|
|
||||||
},
|
|
||||||
muteWordsString (value) {
|
|
||||||
value = filter(value.split('\n'), (word) => trim(word).length > 0)
|
|
||||||
this.$store.dispatch('setOption', { name: 'muteWords', value })
|
|
||||||
},
|
|
||||||
hideMutedPostsLocal (value) {
|
|
||||||
this.$store.dispatch('setOption', { name: 'hideMutedPosts', value })
|
|
||||||
},
|
|
||||||
collapseMessageWithSubjectLocal (value) {
|
|
||||||
this.$store.dispatch('setOption', { name: 'collapseMessageWithSubject', value })
|
|
||||||
},
|
|
||||||
scopeCopyLocal (value) {
|
|
||||||
this.$store.dispatch('setOption', { name: 'scopeCopy', value })
|
|
||||||
},
|
|
||||||
alwaysShowSubjectInputLocal (value) {
|
|
||||||
this.$store.dispatch('setOption', { name: 'alwaysShowSubjectInput', value })
|
|
||||||
},
|
|
||||||
subjectLineBehaviorLocal (value) {
|
|
||||||
this.$store.dispatch('setOption', { name: 'subjectLineBehavior', value })
|
|
||||||
},
|
|
||||||
postContentTypeLocal (value) {
|
|
||||||
this.$store.dispatch('setOption', { name: 'postContentType', value })
|
|
||||||
},
|
|
||||||
minimalScopesModeLocal (value) {
|
|
||||||
this.$store.dispatch('setOption', { name: 'minimalScopesMode', value })
|
|
||||||
},
|
|
||||||
stopGifs (value) {
|
|
||||||
this.$store.dispatch('setOption', { name: 'stopGifs', value })
|
|
||||||
},
|
|
||||||
webPushNotificationsLocal (value) {
|
|
||||||
this.$store.dispatch('setOption', { name: 'webPushNotifications', value })
|
|
||||||
if (value) this.$store.dispatch('registerPushNotifications')
|
|
||||||
},
|
|
||||||
playVideosInModal (value) {
|
|
||||||
this.$store.dispatch('setOption', { name: 'playVideosInModal', value })
|
|
||||||
},
|
|
||||||
useContainFit (value) {
|
|
||||||
this.$store.dispatch('setOption', { name: 'useContainFit', value })
|
|
||||||
},
|
|
||||||
maxThumbnails (value) {
|
|
||||||
value = this.maxThumbnails = Math.floor(Math.max(value, 0))
|
|
||||||
this.$store.dispatch('setOption', { name: 'maxThumbnails', value })
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,12 +36,9 @@
|
||||||
<interface-language-switcher />
|
<interface-language-switcher />
|
||||||
</li>
|
</li>
|
||||||
<li v-if="instanceSpecificPanelPresent">
|
<li v-if="instanceSpecificPanelPresent">
|
||||||
<input
|
<Checkbox v-model="hideISP">
|
||||||
id="hideISP"
|
{{ $t('settings.hide_isp') }}
|
||||||
v-model="hideISPLocal"
|
</Checkbox>
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="hideISP">{{ $t('settings.hide_isp') }}</label>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -49,58 +46,42 @@
|
||||||
<h2>{{ $t('nav.timeline') }}</h2>
|
<h2>{{ $t('nav.timeline') }}</h2>
|
||||||
<ul class="setting-list">
|
<ul class="setting-list">
|
||||||
<li>
|
<li>
|
||||||
<input
|
<Checkbox v-model="hideMutedPosts">
|
||||||
id="hideMutedPosts"
|
{{ $t('settings.hide_muted_posts') }} {{ $t('settings.instance_default', { value: hideMutedPostsLocalizedValue }) }}
|
||||||
v-model="hideMutedPostsLocal"
|
</Checkbox>
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="hideMutedPosts">{{ $t('settings.hide_muted_posts') }} {{ $t('settings.instance_default', { value: hideMutedPostsDefault }) }}</label>
|
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<input
|
<Checkbox v-model="collapseMessageWithSubject">
|
||||||
id="collapseMessageWithSubject"
|
{{ $t('settings.collapse_subject') }} {{ $t('settings.instance_default', { value: collapseMessageWithSubjectLocalizedValue }) }}
|
||||||
v-model="collapseMessageWithSubjectLocal"
|
</Checkbox>
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="collapseMessageWithSubject">{{ $t('settings.collapse_subject') }} {{ $t('settings.instance_default', { value: collapseMessageWithSubjectDefault }) }}</label>
|
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<input
|
<Checkbox v-model="streaming">
|
||||||
id="streaming"
|
{{ $t('settings.streaming') }}
|
||||||
v-model="streamingLocal"
|
</Checkbox>
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="streaming">{{ $t('settings.streaming') }}</label>
|
|
||||||
<ul
|
<ul
|
||||||
class="setting-list suboptions"
|
class="setting-list suboptions"
|
||||||
:class="[{disabled: !streamingLocal}]"
|
:class="[{disabled: !streaming}]"
|
||||||
>
|
>
|
||||||
<li>
|
<li>
|
||||||
<input
|
<Checkbox
|
||||||
id="pauseOnUnfocused"
|
v-model="pauseOnUnfocused"
|
||||||
v-model="pauseOnUnfocusedLocal"
|
:disabled="!streaming"
|
||||||
:disabled="!streamingLocal"
|
|
||||||
type="checkbox"
|
|
||||||
>
|
>
|
||||||
<label for="pauseOnUnfocused">{{ $t('settings.pause_on_unfocused') }}</label>
|
{{ $t('settings.pause_on_unfocused') }}
|
||||||
|
</Checkbox>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<input
|
<Checkbox v-model="autoLoad">
|
||||||
id="autoload"
|
{{ $t('settings.autoload') }}
|
||||||
v-model="autoLoadLocal"
|
</Checkbox>
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="autoload">{{ $t('settings.autoload') }}</label>
|
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<input
|
<Checkbox v-model="hoverPreview">
|
||||||
id="hoverPreview"
|
{{ $t('settings.reply_link_preview') }}
|
||||||
v-model="hoverPreviewLocal"
|
</Checkbox>
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="hoverPreview">{{ $t('settings.reply_link_preview') }}</label>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -109,24 +90,14 @@
|
||||||
<h2>{{ $t('settings.composing') }}</h2>
|
<h2>{{ $t('settings.composing') }}</h2>
|
||||||
<ul class="setting-list">
|
<ul class="setting-list">
|
||||||
<li>
|
<li>
|
||||||
<input
|
<Checkbox v-model="scopeCopy">
|
||||||
id="scopeCopy"
|
{{ $t('settings.scope_copy') }} {{ $t('settings.instance_default', { value: scopeCopyLocalizedValue }) }}
|
||||||
v-model="scopeCopyLocal"
|
</Checkbox>
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="scopeCopy">
|
|
||||||
{{ $t('settings.scope_copy') }} {{ $t('settings.instance_default', { value: scopeCopyDefault }) }}
|
|
||||||
</label>
|
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<input
|
<Checkbox v-model="alwaysShowSubjectInput">
|
||||||
id="subjectHide"
|
{{ $t('settings.subject_input_always_show') }} {{ $t('settings.instance_default', { value: alwaysShowSubjectInputLocalizedValue }) }}
|
||||||
v-model="alwaysShowSubjectInputLocal"
|
</Checkbox>
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="subjectHide">
|
|
||||||
{{ $t('settings.subject_input_always_show') }} {{ $t('settings.instance_default', { value: alwaysShowSubjectInputDefault }) }}
|
|
||||||
</label>
|
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<div>
|
<div>
|
||||||
|
@ -137,19 +108,19 @@
|
||||||
>
|
>
|
||||||
<select
|
<select
|
||||||
id="subjectLineBehavior"
|
id="subjectLineBehavior"
|
||||||
v-model="subjectLineBehaviorLocal"
|
v-model="subjectLineBehavior"
|
||||||
>
|
>
|
||||||
<option value="email">
|
<option value="email">
|
||||||
{{ $t('settings.subject_line_email') }}
|
{{ $t('settings.subject_line_email') }}
|
||||||
{{ subjectLineBehaviorDefault == 'email' ? $t('settings.instance_default_simple') : '' }}
|
{{ subjectLineBehaviorDefaultValue == 'email' ? $t('settings.instance_default_simple') : '' }}
|
||||||
</option>
|
</option>
|
||||||
<option value="masto">
|
<option value="masto">
|
||||||
{{ $t('settings.subject_line_mastodon') }}
|
{{ $t('settings.subject_line_mastodon') }}
|
||||||
{{ subjectLineBehaviorDefault == 'mastodon' ? $t('settings.instance_default_simple') : '' }}
|
{{ subjectLineBehaviorDefaultValue == 'mastodon' ? $t('settings.instance_default_simple') : '' }}
|
||||||
</option>
|
</option>
|
||||||
<option value="noop">
|
<option value="noop">
|
||||||
{{ $t('settings.subject_line_noop') }}
|
{{ $t('settings.subject_line_noop') }}
|
||||||
{{ subjectLineBehaviorDefault == 'noop' ? $t('settings.instance_default_simple') : '' }}
|
{{ subjectLineBehaviorDefaultValue == 'noop' ? $t('settings.instance_default_simple') : '' }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<i class="icon-down-open" />
|
<i class="icon-down-open" />
|
||||||
|
@ -165,7 +136,7 @@
|
||||||
>
|
>
|
||||||
<select
|
<select
|
||||||
id="postContentType"
|
id="postContentType"
|
||||||
v-model="postContentTypeLocal"
|
v-model="postContentType"
|
||||||
>
|
>
|
||||||
<option
|
<option
|
||||||
v-for="postFormat in postFormats"
|
v-for="postFormat in postFormats"
|
||||||
|
@ -173,7 +144,7 @@
|
||||||
:value="postFormat"
|
:value="postFormat"
|
||||||
>
|
>
|
||||||
{{ $t(`post_status.content_type["${postFormat}"]`) }}
|
{{ $t(`post_status.content_type["${postFormat}"]`) }}
|
||||||
{{ postContentTypeDefault === postFormat ? $t('settings.instance_default_simple') : '' }}
|
{{ postContentTypeDefaultValue === postFormat ? $t('settings.instance_default_simple') : '' }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<i class="icon-down-open" />
|
<i class="icon-down-open" />
|
||||||
|
@ -181,30 +152,19 @@
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<input
|
<Checkbox v-model="minimalScopesMode">
|
||||||
id="minimalScopesMode"
|
{{ $t('settings.minimal_scopes_mode') }} {{ $t('settings.instance_default', { value: minimalScopesModeLocalizedValue }) }}
|
||||||
v-model="minimalScopesModeLocal"
|
</Checkbox>
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="minimalScopesMode">
|
|
||||||
{{ $t('settings.minimal_scopes_mode') }} {{ $t('settings.instance_default', { value: minimalScopesModeDefault }) }}
|
|
||||||
</label>
|
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<input
|
<Checkbox v-model="autohideFloatingPostButton">
|
||||||
id="autohideFloatingPostButton"
|
{{ $t('settings.autohide_floating_post_button') }}
|
||||||
v-model="autohideFloatingPostButtonLocal"
|
</Checkbox>
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="autohideFloatingPostButton">{{ $t('settings.autohide_floating_post_button') }}</label>
|
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<input
|
<Checkbox v-model="padEmoji">
|
||||||
id="padEmoji"
|
{{ $t('settings.pad_emoji') }}
|
||||||
v-model="padEmojiLocal"
|
</Checkbox>
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="padEmoji">{{ $t('settings.pad_emoji') }}</label>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -213,23 +173,19 @@
|
||||||
<h2>{{ $t('settings.attachments') }}</h2>
|
<h2>{{ $t('settings.attachments') }}</h2>
|
||||||
<ul class="setting-list">
|
<ul class="setting-list">
|
||||||
<li>
|
<li>
|
||||||
<input
|
<Checkbox v-model="hideAttachments">
|
||||||
id="hideAttachments"
|
{{ $t('settings.hide_attachments_in_tl') }}
|
||||||
v-model="hideAttachmentsLocal"
|
</Checkbox>
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="hideAttachments">{{ $t('settings.hide_attachments_in_tl') }}</label>
|
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<input
|
<Checkbox v-model="hideAttachmentsInConv">
|
||||||
id="hideAttachmentsInConv"
|
{{ $t('settings.hide_attachments_in_convo') }}
|
||||||
v-model="hideAttachmentsInConvLocal"
|
</Checkbox>
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="hideAttachmentsInConv">{{ $t('settings.hide_attachments_in_convo') }}</label>
|
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<label for="maxThumbnails">{{ $t('settings.max_thumbnails') }}</label>
|
<label for="maxThumbnails">
|
||||||
|
{{ $t('settings.max_thumbnails') }}
|
||||||
|
</label>
|
||||||
<input
|
<input
|
||||||
id="maxThumbnails"
|
id="maxThumbnails"
|
||||||
v-model.number="maxThumbnails"
|
v-model.number="maxThumbnails"
|
||||||
|
@ -240,60 +196,48 @@
|
||||||
>
|
>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<input
|
<Checkbox v-model="hideNsfw">
|
||||||
id="hideNsfw"
|
{{ $t('settings.nsfw_clickthrough') }}
|
||||||
v-model="hideNsfwLocal"
|
</Checkbox>
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="hideNsfw">{{ $t('settings.nsfw_clickthrough') }}</label>
|
|
||||||
</li>
|
</li>
|
||||||
<ul class="setting-list suboptions">
|
<ul class="setting-list suboptions">
|
||||||
<li>
|
<li>
|
||||||
<input
|
<Checkbox
|
||||||
id="preloadImage"
|
|
||||||
v-model="preloadImage"
|
v-model="preloadImage"
|
||||||
:disabled="!hideNsfwLocal"
|
:disabled="!hideNsfw"
|
||||||
type="checkbox"
|
|
||||||
>
|
>
|
||||||
<label for="preloadImage">{{ $t('settings.preload_images') }}</label>
|
{{ $t('settings.preload_images') }}
|
||||||
|
</Checkbox>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<input
|
<Checkbox
|
||||||
id="useOneClickNsfw"
|
|
||||||
v-model="useOneClickNsfw"
|
v-model="useOneClickNsfw"
|
||||||
:disabled="!hideNsfwLocal"
|
:disabled="!hideNsfw"
|
||||||
type="checkbox"
|
|
||||||
>
|
>
|
||||||
<label for="useOneClickNsfw">{{ $t('settings.use_one_click_nsfw') }}</label>
|
{{ $t('settings.use_one_click_nsfw') }}
|
||||||
|
</Checkbox>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<li>
|
<li>
|
||||||
<input
|
<Checkbox v-model="stopGifs">
|
||||||
id="stopGifs"
|
{{ $t('settings.stop_gifs') }}
|
||||||
v-model="stopGifs"
|
</Checkbox>
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="stopGifs">{{ $t('settings.stop_gifs') }}</label>
|
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<input
|
<Checkbox v-model="loopVideo">
|
||||||
id="loopVideo"
|
{{ $t('settings.loop_video') }}
|
||||||
v-model="loopVideoLocal"
|
</Checkbox>
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="loopVideo">{{ $t('settings.loop_video') }}</label>
|
|
||||||
<ul
|
<ul
|
||||||
class="setting-list suboptions"
|
class="setting-list suboptions"
|
||||||
:class="[{disabled: !streamingLocal}]"
|
:class="[{disabled: !streaming}]"
|
||||||
>
|
>
|
||||||
<li>
|
<li>
|
||||||
<input
|
<Checkbox
|
||||||
id="loopVideoSilentOnly"
|
v-model="loopVideoSilentOnly"
|
||||||
v-model="loopVideoSilentOnlyLocal"
|
:disabled="!loopVideo || !loopSilentAvailable"
|
||||||
:disabled="!loopVideoLocal || !loopSilentAvailable"
|
|
||||||
type="checkbox"
|
|
||||||
>
|
>
|
||||||
<label for="loopVideoSilentOnly">{{ $t('settings.loop_video_silent_only') }}</label>
|
{{ $t('settings.loop_video_silent_only') }}
|
||||||
|
</Checkbox>
|
||||||
<div
|
<div
|
||||||
v-if="!loopSilentAvailable"
|
v-if="!loopSilentAvailable"
|
||||||
class="unavailable"
|
class="unavailable"
|
||||||
|
@ -304,20 +248,14 @@
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<input
|
<Checkbox v-model="playVideosInModal">
|
||||||
id="playVideosInModal"
|
{{ $t('settings.play_videos_in_modal') }}
|
||||||
v-model="playVideosInModal"
|
</Checkbox>
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="playVideosInModal">{{ $t('settings.play_videos_in_modal') }}</label>
|
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<input
|
<Checkbox v-model="useContainFit">
|
||||||
id="useContainFit"
|
{{ $t('settings.use_contain_fit') }}
|
||||||
v-model="useContainFit"
|
</Checkbox>
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="useContainFit">{{ $t('settings.use_contain_fit') }}</label>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -326,14 +264,9 @@
|
||||||
<h2>{{ $t('settings.notifications') }}</h2>
|
<h2>{{ $t('settings.notifications') }}</h2>
|
||||||
<ul class="setting-list">
|
<ul class="setting-list">
|
||||||
<li>
|
<li>
|
||||||
<input
|
<Checkbox v-model="webPushNotifications">
|
||||||
id="webPushNotifications"
|
|
||||||
v-model="webPushNotificationsLocal"
|
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="webPushNotifications">
|
|
||||||
{{ $t('settings.enable_web_push_notifications') }}
|
{{ $t('settings.enable_web_push_notifications') }}
|
||||||
</label>
|
</Checkbox>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -351,44 +284,24 @@
|
||||||
<span class="label">{{ $t('settings.notification_visibility') }}</span>
|
<span class="label">{{ $t('settings.notification_visibility') }}</span>
|
||||||
<ul class="option-list">
|
<ul class="option-list">
|
||||||
<li>
|
<li>
|
||||||
<input
|
<Checkbox v-model="notificationVisibility.likes">
|
||||||
id="notification-visibility-likes"
|
|
||||||
v-model="notificationVisibilityLocal.likes"
|
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="notification-visibility-likes">
|
|
||||||
{{ $t('settings.notification_visibility_likes') }}
|
{{ $t('settings.notification_visibility_likes') }}
|
||||||
</label>
|
</Checkbox>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<input
|
<Checkbox v-model="notificationVisibility.repeats">
|
||||||
id="notification-visibility-repeats"
|
|
||||||
v-model="notificationVisibilityLocal.repeats"
|
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="notification-visibility-repeats">
|
|
||||||
{{ $t('settings.notification_visibility_repeats') }}
|
{{ $t('settings.notification_visibility_repeats') }}
|
||||||
</label>
|
</Checkbox>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<input
|
<Checkbox v-model="notificationVisibility.follows">
|
||||||
id="notification-visibility-follows"
|
|
||||||
v-model="notificationVisibilityLocal.follows"
|
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="notification-visibility-follows">
|
|
||||||
{{ $t('settings.notification_visibility_follows') }}
|
{{ $t('settings.notification_visibility_follows') }}
|
||||||
</label>
|
</Checkbox>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<input
|
<Checkbox v-model="notificationVisibility.mentions">
|
||||||
id="notification-visibility-mentions"
|
|
||||||
v-model="notificationVisibilityLocal.mentions"
|
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="notification-visibility-mentions">
|
|
||||||
{{ $t('settings.notification_visibility_mentions') }}
|
{{ $t('settings.notification_visibility_mentions') }}
|
||||||
</label>
|
</Checkbox>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -400,7 +313,7 @@
|
||||||
>
|
>
|
||||||
<select
|
<select
|
||||||
id="replyVisibility"
|
id="replyVisibility"
|
||||||
v-model="replyVisibilityLocal"
|
v-model="replyVisibility"
|
||||||
>
|
>
|
||||||
<option
|
<option
|
||||||
value="all"
|
value="all"
|
||||||
|
@ -413,24 +326,14 @@
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<input
|
<Checkbox v-model="hidePostStats">
|
||||||
id="hidePostStats"
|
{{ $t('settings.hide_post_stats') }} {{ $t('settings.instance_default', { value: hidePostStatsLocalizedValue }) }}
|
||||||
v-model="hidePostStatsLocal"
|
</Checkbox>
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="hidePostStats">
|
|
||||||
{{ $t('settings.hide_post_stats') }} {{ $t('settings.instance_default', { value: hidePostStatsDefault }) }}
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<input
|
<Checkbox v-model="hideUserStats">
|
||||||
id="hideUserStats"
|
{{ $t('settings.hide_user_stats') }} {{ $t('settings.instance_default', { value: hideUserStatsLocalizedValue }) }}
|
||||||
v-model="hideUserStatsLocal"
|
</Checkbox>
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="hideUserStats">
|
|
||||||
{{ $t('settings.hide_user_stats') }} {{ $t('settings.instance_default', { value: hideUserStatsDefault }) }}
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-item">
|
<div class="setting-item">
|
||||||
|
@ -442,14 +345,9 @@
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<input
|
<Checkbox v-model="hideFilteredStatuses">
|
||||||
id="hideFilteredStatuses"
|
{{ $t('settings.hide_filtered_statuses') }} {{ $t('settings.instance_default', { value: hideFilteredStatusesLocalizedValue }) }}
|
||||||
v-model="hideFilteredStatusesLocal"
|
</Checkbox>
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="hideFilteredStatuses">
|
|
||||||
{{ $t('settings.hide_filtered_statuses') }} {{ $t('settings.instance_default', { value: hideFilteredStatusesDefault }) }}
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -10,11 +10,13 @@ import Gallery from '../gallery/gallery.vue'
|
||||||
import LinkPreview from '../link-preview/link-preview.vue'
|
import LinkPreview from '../link-preview/link-preview.vue'
|
||||||
import AvatarList from '../avatar_list/avatar_list.vue'
|
import AvatarList from '../avatar_list/avatar_list.vue'
|
||||||
import Timeago from '../timeago/timeago.vue'
|
import Timeago from '../timeago/timeago.vue'
|
||||||
|
import StatusPopover from '../status_popover/status_popover.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 fileType from 'src/services/file_type/file_type.service'
|
import fileType from 'src/services/file_type/file_type.service'
|
||||||
import { highlightClass, highlightStyle } from '../../services/user_highlighter/user_highlighter.js'
|
import { highlightClass, highlightStyle } from '../../services/user_highlighter/user_highlighter.js'
|
||||||
import { mentionMatchesUrl, extractTagFromUrl } from 'src/services/matcher/matcher.service.js'
|
import { mentionMatchesUrl, extractTagFromUrl } from 'src/services/matcher/matcher.service.js'
|
||||||
import { filter, find, unescape, uniqBy } from 'lodash'
|
import { filter, unescape, uniqBy } from 'lodash'
|
||||||
|
import { mapGetters } from 'vuex'
|
||||||
|
|
||||||
const Status = {
|
const Status = {
|
||||||
name: 'Status',
|
name: 'Status',
|
||||||
|
@ -37,25 +39,19 @@ const Status = {
|
||||||
replying: false,
|
replying: false,
|
||||||
unmuted: false,
|
unmuted: false,
|
||||||
userExpanded: false,
|
userExpanded: false,
|
||||||
preview: null,
|
|
||||||
showPreview: false,
|
|
||||||
showingTall: this.inConversation && this.focused,
|
showingTall: this.inConversation && this.focused,
|
||||||
showingLongSubject: false,
|
showingLongSubject: false,
|
||||||
error: null,
|
error: null,
|
||||||
expandingSubject: typeof this.$store.state.config.collapseMessageWithSubject === 'undefined'
|
expandingSubject: !this.$store.getters.mergedConfig.collapseMessageWithSubject,
|
||||||
? !this.$store.state.instance.collapseMessageWithSubject
|
|
||||||
: !this.$store.state.config.collapseMessageWithSubject,
|
|
||||||
betterShadow: this.$store.state.interface.browserSupport.cssFilter
|
betterShadow: this.$store.state.interface.browserSupport.cssFilter
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
localCollapseSubjectDefault () {
|
localCollapseSubjectDefault () {
|
||||||
return typeof this.$store.state.config.collapseMessageWithSubject === 'undefined'
|
return this.mergedConfig.collapseMessageWithSubject
|
||||||
? this.$store.state.instance.collapseMessageWithSubject
|
|
||||||
: this.$store.state.config.collapseMessageWithSubject
|
|
||||||
},
|
},
|
||||||
muteWords () {
|
muteWords () {
|
||||||
return this.$store.state.config.muteWords
|
return this.mergedConfig.muteWords
|
||||||
},
|
},
|
||||||
repeaterClass () {
|
repeaterClass () {
|
||||||
const user = this.statusoid.user
|
const user = this.statusoid.user
|
||||||
|
@ -70,18 +66,18 @@ const Status = {
|
||||||
},
|
},
|
||||||
repeaterStyle () {
|
repeaterStyle () {
|
||||||
const user = this.statusoid.user
|
const user = this.statusoid.user
|
||||||
const highlight = this.$store.state.config.highlight
|
const highlight = this.mergedConfig.highlight
|
||||||
return highlightStyle(highlight[user.screen_name])
|
return highlightStyle(highlight[user.screen_name])
|
||||||
},
|
},
|
||||||
userStyle () {
|
userStyle () {
|
||||||
if (this.noHeading) return
|
if (this.noHeading) return
|
||||||
const user = this.retweet ? (this.statusoid.retweeted_status.user) : this.statusoid.user
|
const user = this.retweet ? (this.statusoid.retweeted_status.user) : this.statusoid.user
|
||||||
const highlight = this.$store.state.config.highlight
|
const highlight = this.mergedConfig.highlight
|
||||||
return highlightStyle(highlight[user.screen_name])
|
return highlightStyle(highlight[user.screen_name])
|
||||||
},
|
},
|
||||||
hideAttachments () {
|
hideAttachments () {
|
||||||
return (this.$store.state.config.hideAttachments && !this.inConversation) ||
|
return (this.mergedConfig.hideAttachments && !this.inConversation) ||
|
||||||
(this.$store.state.config.hideAttachmentsInConv && this.inConversation)
|
(this.mergedConfig.hideAttachmentsInConv && this.inConversation)
|
||||||
},
|
},
|
||||||
userProfileLink () {
|
userProfileLink () {
|
||||||
return this.generateUserProfileLink(this.status.user.id, this.status.user.screen_name)
|
return this.generateUserProfileLink(this.status.user.id, this.status.user.screen_name)
|
||||||
|
@ -120,9 +116,7 @@ const Status = {
|
||||||
},
|
},
|
||||||
muted () { return !this.unmuted && ((!this.inProfile && this.status.user.muted) || (!this.inConversation && this.status.thread_muted) || this.muteWordHits.length > 0) },
|
muted () { return !this.unmuted && ((!this.inProfile && this.status.user.muted) || (!this.inConversation && this.status.thread_muted) || this.muteWordHits.length > 0) },
|
||||||
hideFilteredStatuses () {
|
hideFilteredStatuses () {
|
||||||
return typeof this.$store.state.config.hideFilteredStatuses === 'undefined'
|
return this.mergedConfig.hideFilteredStatuses
|
||||||
? this.$store.state.instance.hideFilteredStatuses
|
|
||||||
: this.$store.state.config.hideFilteredStatuses
|
|
||||||
},
|
},
|
||||||
hideStatus () {
|
hideStatus () {
|
||||||
return (this.hideReply || this.deleted) || (this.muted && this.hideFilteredStatuses)
|
return (this.hideReply || this.deleted) || (this.muted && this.hideFilteredStatuses)
|
||||||
|
@ -163,7 +157,7 @@ const Status = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
hideReply () {
|
hideReply () {
|
||||||
if (this.$store.state.config.replyVisibility === 'all') {
|
if (this.mergedConfig.replyVisibility === 'all') {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if (this.inConversation || !this.isReply) {
|
if (this.inConversation || !this.isReply) {
|
||||||
|
@ -175,7 +169,7 @@ const Status = {
|
||||||
if (this.status.type === 'retweet') {
|
if (this.status.type === 'retweet') {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
const checkFollowing = this.$store.state.config.replyVisibility === 'following'
|
const checkFollowing = this.mergedConfig.replyVisibility === 'following'
|
||||||
for (var i = 0; i < this.status.attentions.length; ++i) {
|
for (var i = 0; i < this.status.attentions.length; ++i) {
|
||||||
if (this.status.user.id === this.status.attentions[i].id) {
|
if (this.status.user.id === this.status.attentions[i].id) {
|
||||||
continue
|
continue
|
||||||
|
@ -220,9 +214,7 @@ const Status = {
|
||||||
replySubject () {
|
replySubject () {
|
||||||
if (!this.status.summary) return ''
|
if (!this.status.summary) return ''
|
||||||
const decodedSummary = unescape(this.status.summary)
|
const decodedSummary = unescape(this.status.summary)
|
||||||
const behavior = typeof this.$store.state.config.subjectLineBehavior === 'undefined'
|
const behavior = this.mergedConfig.subjectLineBehavior
|
||||||
? this.$store.state.instance.subjectLineBehavior
|
|
||||||
: this.$store.state.config.subjectLineBehavior
|
|
||||||
const startsWithRe = decodedSummary.match(/^re[: ]/i)
|
const startsWithRe = decodedSummary.match(/^re[: ]/i)
|
||||||
if ((behavior !== 'noop' && startsWithRe) || behavior === 'masto') {
|
if ((behavior !== 'noop' && startsWithRe) || behavior === 'masto') {
|
||||||
return decodedSummary
|
return decodedSummary
|
||||||
|
@ -233,8 +225,8 @@ const Status = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
attachmentSize () {
|
attachmentSize () {
|
||||||
if ((this.$store.state.config.hideAttachments && !this.inConversation) ||
|
if ((this.mergedConfig.hideAttachments && !this.inConversation) ||
|
||||||
(this.$store.state.config.hideAttachmentsInConv && this.inConversation) ||
|
(this.mergedConfig.hideAttachmentsInConv && this.inConversation) ||
|
||||||
(this.status.attachments.length > this.maxThumbnails)) {
|
(this.status.attachments.length > this.maxThumbnails)) {
|
||||||
return 'hide'
|
return 'hide'
|
||||||
} else if (this.compact) {
|
} else if (this.compact) {
|
||||||
|
@ -246,7 +238,7 @@ const Status = {
|
||||||
if (this.attachmentSize === 'hide') {
|
if (this.attachmentSize === 'hide') {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
return this.$store.state.config.playVideosInModal
|
return this.mergedConfig.playVideosInModal
|
||||||
? ['image', 'video']
|
? ['image', 'video']
|
||||||
: ['image']
|
: ['image']
|
||||||
},
|
},
|
||||||
|
@ -261,7 +253,7 @@ const Status = {
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
maxThumbnails () {
|
maxThumbnails () {
|
||||||
return this.$store.state.config.maxThumbnails
|
return this.mergedConfig.maxThumbnails
|
||||||
},
|
},
|
||||||
contentHtml () {
|
contentHtml () {
|
||||||
if (!this.status.summary_html) {
|
if (!this.status.summary_html) {
|
||||||
|
@ -284,10 +276,9 @@ const Status = {
|
||||||
return this.status.tags.filter(tagObj => tagObj.hasOwnProperty('name')).map(tagObj => tagObj.name).join(' ')
|
return this.status.tags.filter(tagObj => tagObj.hasOwnProperty('name')).map(tagObj => tagObj.name).join(' ')
|
||||||
},
|
},
|
||||||
hidePostStats () {
|
hidePostStats () {
|
||||||
return typeof this.$store.state.config.hidePostStats === 'undefined'
|
return this.mergedConfig.hidePostStats
|
||||||
? this.$store.state.instance.hidePostStats
|
},
|
||||||
: this.$store.state.config.hidePostStats
|
...mapGetters(['mergedConfig'])
|
||||||
}
|
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
Attachment,
|
Attachment,
|
||||||
|
@ -301,7 +292,8 @@ const Status = {
|
||||||
Gallery,
|
Gallery,
|
||||||
LinkPreview,
|
LinkPreview,
|
||||||
AvatarList,
|
AvatarList,
|
||||||
Timeago
|
Timeago,
|
||||||
|
StatusPopover
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
visibilityIcon (visibility) {
|
visibilityIcon (visibility) {
|
||||||
|
@ -376,27 +368,6 @@ const Status = {
|
||||||
this.expandingSubject = true
|
this.expandingSubject = true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
replyEnter (id, event) {
|
|
||||||
this.showPreview = true
|
|
||||||
const targetId = id
|
|
||||||
const statuses = this.$store.state.statuses.allStatuses
|
|
||||||
|
|
||||||
if (!this.preview) {
|
|
||||||
// if we have the status somewhere already
|
|
||||||
this.preview = find(statuses, { 'id': targetId })
|
|
||||||
// or if we have to fetch it
|
|
||||||
if (!this.preview) {
|
|
||||||
this.$store.state.api.backendInteractor.fetchStatus({ id }).then((status) => {
|
|
||||||
this.preview = status
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} else if (this.preview.id !== targetId) {
|
|
||||||
this.preview = find(statuses, { 'id': targetId })
|
|
||||||
}
|
|
||||||
},
|
|
||||||
replyLeave () {
|
|
||||||
this.showPreview = false
|
|
||||||
},
|
|
||||||
generateUserProfileLink (id, name) {
|
generateUserProfileLink (id, name) {
|
||||||
return generateProfileLink(id, name, this.$store.state.instance.restrictedNicknames)
|
return generateProfileLink(id, name, this.$store.state.instance.restrictedNicknames)
|
||||||
},
|
},
|
||||||
|
|
|
@ -174,20 +174,26 @@
|
||||||
v-if="isReply"
|
v-if="isReply"
|
||||||
class="reply-to-and-accountname"
|
class="reply-to-and-accountname"
|
||||||
>
|
>
|
||||||
<a
|
<StatusPopover
|
||||||
class="reply-to"
|
v-if="!isPreview"
|
||||||
href="#"
|
:status-id="status.in_reply_to_status_id"
|
||||||
:aria-label="$t('tool_tip.reply')"
|
|
||||||
@click.prevent="gotoOriginal(status.in_reply_to_status_id)"
|
|
||||||
@mouseenter.prevent.stop="replyEnter(status.in_reply_to_status_id, $event)"
|
|
||||||
@mouseleave.prevent.stop="replyLeave()"
|
|
||||||
>
|
>
|
||||||
<i
|
<a
|
||||||
v-if="!isPreview"
|
class="reply-to"
|
||||||
class="button-icon icon-reply"
|
href="#"
|
||||||
/>
|
:aria-label="$t('tool_tip.reply')"
|
||||||
<span class="faint-link reply-to-text">{{ $t('status.reply_to') }}</span>
|
@click.prevent="gotoOriginal(status.in_reply_to_status_id)"
|
||||||
</a>
|
>
|
||||||
|
<i class="button-icon icon-reply" />
|
||||||
|
<span class="faint-link reply-to-text">{{ $t('status.reply_to') }}</span>
|
||||||
|
</a>
|
||||||
|
</StatusPopover>
|
||||||
|
<span
|
||||||
|
v-else
|
||||||
|
class="reply-to"
|
||||||
|
>
|
||||||
|
<span class="reply-to-text">{{ $t('status.reply_to') }}</span>
|
||||||
|
</span>
|
||||||
<router-link :to="replyProfileLink">
|
<router-link :to="replyProfileLink">
|
||||||
{{ replyToName }}
|
{{ replyToName }}
|
||||||
</router-link>
|
</router-link>
|
||||||
|
@ -199,50 +205,25 @@
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="inConversation && !isPreview"
|
v-if="inConversation && !isPreview && replies && replies.length"
|
||||||
class="replies"
|
class="replies"
|
||||||
>
|
>
|
||||||
<span
|
<span class="faint">{{ $t('status.replies_list') }}</span>
|
||||||
v-if="replies && replies.length"
|
<StatusPopover
|
||||||
class="faint"
|
v-for="reply in replies"
|
||||||
>{{ $t('status.replies_list') }}</span>
|
:key="reply.id"
|
||||||
<template v-if="replies">
|
:status-id="reply.id"
|
||||||
<span
|
>
|
||||||
v-for="reply in replies"
|
<a
|
||||||
:key="reply.id"
|
href="#"
|
||||||
class="reply-link faint"
|
class="reply-link"
|
||||||
>
|
@click.prevent="gotoOriginal(reply.id)"
|
||||||
<a
|
>{{ reply.name }}</a>
|
||||||
href="#"
|
</StatusPopover>
|
||||||
@click.prevent="gotoOriginal(reply.id)"
|
|
||||||
@mouseenter="replyEnter(reply.id, $event)"
|
|
||||||
@mouseout="replyLeave()"
|
|
||||||
>{{ reply.name }}</a>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
|
||||||
v-if="showPreview"
|
|
||||||
class="status-preview-container"
|
|
||||||
>
|
|
||||||
<status
|
|
||||||
v-if="preview"
|
|
||||||
class="status-preview"
|
|
||||||
:is-preview="true"
|
|
||||||
:statusoid="preview"
|
|
||||||
:compact="true"
|
|
||||||
/>
|
|
||||||
<div
|
|
||||||
v-else
|
|
||||||
class="status-preview status-preview-loading"
|
|
||||||
>
|
|
||||||
<i class="icon-spin4 animate-spin" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-if="longSubject"
|
v-if="longSubject"
|
||||||
class="status-content-wrapper"
|
class="status-content-wrapper"
|
||||||
|
@ -439,18 +420,6 @@ $status-margin: 0.75em;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-preview.status-el {
|
|
||||||
border-style: solid;
|
|
||||||
border-width: 1px;
|
|
||||||
border-color: $fallback--border;
|
|
||||||
border-color: var(--border, $fallback--border);
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-preview-container {
|
|
||||||
position: relative;
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-pin {
|
.status-pin {
|
||||||
padding: $status-margin $status-margin 0;
|
padding: $status-margin $status-margin 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -458,44 +427,6 @@ $status-margin: 0.75em;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-preview {
|
|
||||||
position: absolute;
|
|
||||||
max-width: 95%;
|
|
||||||
display: flex;
|
|
||||||
background-color: $fallback--bg;
|
|
||||||
background-color: var(--bg, $fallback--bg);
|
|
||||||
border-color: $fallback--border;
|
|
||||||
border-color: var(--border, $fallback--border);
|
|
||||||
border-style: solid;
|
|
||||||
border-width: 1px;
|
|
||||||
border-radius: $fallback--tooltipRadius;
|
|
||||||
border-radius: var(--tooltipRadius, $fallback--tooltipRadius);
|
|
||||||
box-shadow: 2px 2px 3px rgba(0, 0, 0, 0.5);
|
|
||||||
box-shadow: var(--popupShadow);
|
|
||||||
margin-top: 0.25em;
|
|
||||||
margin-left: 0.5em;
|
|
||||||
z-index: 50;
|
|
||||||
|
|
||||||
.status {
|
|
||||||
flex: 1;
|
|
||||||
border: 0;
|
|
||||||
min-width: 15em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-preview-loading {
|
|
||||||
display: block;
|
|
||||||
min-width: 15em;
|
|
||||||
padding: 1em;
|
|
||||||
text-align: center;
|
|
||||||
border-width: 1px;
|
|
||||||
border-style: solid;
|
|
||||||
|
|
||||||
i {
|
|
||||||
font-size: 2em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.media-left {
|
.media-left {
|
||||||
margin-right: $status-margin;
|
margin-right: $status-margin;
|
||||||
}
|
}
|
||||||
|
@ -553,11 +484,6 @@ $status-margin: 0.75em;
|
||||||
flex-basis: 100%;
|
flex-basis: 100%;
|
||||||
margin-bottom: 0.5em;
|
margin-bottom: 0.5em;
|
||||||
|
|
||||||
a {
|
|
||||||
display: inline-block;
|
|
||||||
word-break: break-all;
|
|
||||||
}
|
|
||||||
|
|
||||||
small {
|
small {
|
||||||
font-weight: lighter;
|
font-weight: lighter;
|
||||||
}
|
}
|
||||||
|
@ -568,6 +494,11 @@ $status-margin: 0.75em;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
line-height: 18px;
|
line-height: 18px;
|
||||||
|
|
||||||
|
a {
|
||||||
|
display: inline-block;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
.name-and-account-name {
|
.name-and-account-name {
|
||||||
display: flex;
|
display: flex;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
@ -600,6 +531,7 @@ $status-margin: 0.75em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.heading-reply-row {
|
.heading-reply-row {
|
||||||
|
position: relative;
|
||||||
align-content: baseline;
|
align-content: baseline;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
line-height: 18px;
|
line-height: 18px;
|
||||||
|
@ -608,11 +540,13 @@ $status-margin: 0.75em;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
|
|
||||||
a {
|
> .reply-to-and-accountname > a {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
display: inline-block;
|
||||||
|
word-break: break-all;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -639,6 +573,8 @@ $status-margin: 0.75em;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
margin: 0 0.4em 0 0.2em;
|
margin: 0 0.4em 0 0.2em;
|
||||||
|
color: $fallback--faint;
|
||||||
|
color: var(--faint, $fallback--faint);
|
||||||
}
|
}
|
||||||
|
|
||||||
.replies-separator {
|
.replies-separator {
|
||||||
|
@ -840,6 +776,11 @@ $status-margin: 0.75em;
|
||||||
&.button-icon-active {
|
&.button-icon-active {
|
||||||
color: $fallback--cBlue;
|
color: $fallback--cBlue;
|
||||||
color: var(--cBlue, $fallback--cBlue);
|
color: var(--cBlue, $fallback--cBlue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-icon.icon-reply {
|
||||||
|
&:not(.button-icon-disabled) {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
34
src/components/status_popover/status_popover.js
Normal file
34
src/components/status_popover/status_popover.js
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
import { find } from 'lodash'
|
||||||
|
|
||||||
|
const StatusPopover = {
|
||||||
|
name: 'StatusPopover',
|
||||||
|
props: [
|
||||||
|
'statusId'
|
||||||
|
],
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
popperOptions: {
|
||||||
|
modifiers: {
|
||||||
|
preventOverflow: { padding: { top: 50 }, boundariesElement: 'viewport' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
status () {
|
||||||
|
return find(this.$store.state.statuses.allStatuses, { id: this.statusId })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
Status: () => import('../status/status.vue')
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
enter () {
|
||||||
|
if (!this.status) {
|
||||||
|
this.$store.dispatch('fetchStatus', this.statusId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default StatusPopover
|
85
src/components/status_popover/status_popover.vue
Normal file
85
src/components/status_popover/status_popover.vue
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
<template>
|
||||||
|
<v-popover
|
||||||
|
popover-class="status-popover"
|
||||||
|
placement="top-start"
|
||||||
|
:popper-options="popperOptions"
|
||||||
|
@show="enter()"
|
||||||
|
>
|
||||||
|
<template slot="popover">
|
||||||
|
<Status
|
||||||
|
v-if="status"
|
||||||
|
:is-preview="true"
|
||||||
|
:statusoid="status"
|
||||||
|
:compact="true"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
v-else
|
||||||
|
class="status-preview-loading"
|
||||||
|
>
|
||||||
|
<i class="icon-spin4 animate-spin" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<slot />
|
||||||
|
</v-popover>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./status_popover.js" ></script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@import '../../_variables.scss';
|
||||||
|
|
||||||
|
.tooltip.popover.status-popover {
|
||||||
|
font-size: 1rem;
|
||||||
|
min-width: 15em;
|
||||||
|
max-width: 95%;
|
||||||
|
margin-left: 0.5em;
|
||||||
|
|
||||||
|
.popover-inner {
|
||||||
|
border-color: $fallback--border;
|
||||||
|
border-color: var(--border, $fallback--border);
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 1px;
|
||||||
|
border-radius: $fallback--tooltipRadius;
|
||||||
|
border-radius: var(--tooltipRadius, $fallback--tooltipRadius);
|
||||||
|
box-shadow: 2px 2px 3px rgba(0, 0, 0, 0.5);
|
||||||
|
box-shadow: var(--popupShadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.popover-arrow::before {
|
||||||
|
position: absolute;
|
||||||
|
content: '';
|
||||||
|
left: -7px;
|
||||||
|
border: solid 7px transparent;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&[x-placement^="bottom-start"] .popover-arrow::before {
|
||||||
|
top: -2px;
|
||||||
|
border-top-width: 0;
|
||||||
|
border-bottom-color: $fallback--border;
|
||||||
|
border-bottom-color: var(--border, $fallback--border);
|
||||||
|
}
|
||||||
|
|
||||||
|
&[x-placement^="top-start"] .popover-arrow::before {
|
||||||
|
bottom: -2px;
|
||||||
|
border-bottom-width: 0;
|
||||||
|
border-top-color: $fallback--border;
|
||||||
|
border-top-color: var(--border, $fallback--border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-el.status-el {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-preview-loading {
|
||||||
|
padding: 1em;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 2em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
|
@ -3,11 +3,12 @@ const StillImage = {
|
||||||
'src',
|
'src',
|
||||||
'referrerpolicy',
|
'referrerpolicy',
|
||||||
'mimetype',
|
'mimetype',
|
||||||
'imageLoadError'
|
'imageLoadError',
|
||||||
|
'imageLoadHandler'
|
||||||
],
|
],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
stopGifs: this.$store.state.config.stopGifs
|
stopGifs: this.$store.getters.mergedConfig.stopGifs
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -17,6 +18,7 @@ const StillImage = {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onLoad () {
|
onLoad () {
|
||||||
|
this.imageLoadHandler && this.imageLoadHandler(this.$refs.src)
|
||||||
const canvas = this.$refs.canvas
|
const canvas = this.$refs.canvas
|
||||||
if (!canvas) return
|
if (!canvas) return
|
||||||
const width = this.$refs.src.naturalWidth
|
const width = this.$refs.src.naturalWidth
|
||||||
|
|
|
@ -10,6 +10,7 @@ import ContrastRatio from '../contrast_ratio/contrast_ratio.vue'
|
||||||
import TabSwitcher from '../tab_switcher/tab_switcher.js'
|
import TabSwitcher from '../tab_switcher/tab_switcher.js'
|
||||||
import Preview from './preview.vue'
|
import Preview from './preview.vue'
|
||||||
import ExportImport from '../export_import/export_import.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 = [
|
||||||
|
@ -27,7 +28,7 @@ export default {
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
availableStyles: [],
|
availableStyles: [],
|
||||||
selected: this.$store.state.config.theme,
|
selected: this.$store.getters.mergedConfig.theme,
|
||||||
|
|
||||||
previewShadows: {},
|
previewShadows: {},
|
||||||
previewColors: {},
|
previewColors: {},
|
||||||
|
@ -111,7 +112,7 @@ export default {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
this.normalizeLocalState(this.$store.state.config.customTheme)
|
this.normalizeLocalState(this.$store.getters.mergedConfig.customTheme)
|
||||||
if (typeof this.shadowSelected === 'undefined') {
|
if (typeof this.shadowSelected === 'undefined') {
|
||||||
this.shadowSelected = this.shadowsAvailable[0]
|
this.shadowSelected = this.shadowsAvailable[0]
|
||||||
}
|
}
|
||||||
|
@ -338,7 +339,8 @@ export default {
|
||||||
FontControl,
|
FontControl,
|
||||||
TabSwitcher,
|
TabSwitcher,
|
||||||
Preview,
|
Preview,
|
||||||
ExportImport
|
ExportImport,
|
||||||
|
Checkbox
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
setCustomTheme () {
|
setCustomTheme () {
|
||||||
|
@ -365,9 +367,9 @@ export default {
|
||||||
return version >= 1 || version <= 2
|
return version >= 1 || version <= 2
|
||||||
},
|
},
|
||||||
clearAll () {
|
clearAll () {
|
||||||
const state = this.$store.state.config.customTheme
|
const state = this.$store.getters.mergedConfig.customTheme
|
||||||
const version = state.colors ? 2 : 'l1'
|
const version = state.colors ? 2 : 'l1'
|
||||||
this.normalizeLocalState(this.$store.state.config.customTheme, version)
|
this.normalizeLocalState(this.$store.getters.mergedConfig.customTheme, version)
|
||||||
},
|
},
|
||||||
|
|
||||||
// Clears all the extra stuff when loading V1 theme
|
// Clears all the extra stuff when loading V1 theme
|
||||||
|
|
|
@ -42,44 +42,29 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="save-load-options">
|
<div class="save-load-options">
|
||||||
<span class="keep-option">
|
<span class="keep-option">
|
||||||
<input
|
<Checkbox v-model="keepColor">
|
||||||
id="keep-color"
|
{{ $t('settings.style.switcher.keep_color') }}
|
||||||
v-model="keepColor"
|
</Checkbox>
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="keep-color">{{ $t('settings.style.switcher.keep_color') }}</label>
|
|
||||||
</span>
|
</span>
|
||||||
<span class="keep-option">
|
<span class="keep-option">
|
||||||
<input
|
<Checkbox v-model="keepShadows">
|
||||||
id="keep-shadows"
|
{{ $t('settings.style.switcher.keep_shadows') }}
|
||||||
v-model="keepShadows"
|
</Checkbox>
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="keep-shadows">{{ $t('settings.style.switcher.keep_shadows') }}</label>
|
|
||||||
</span>
|
</span>
|
||||||
<span class="keep-option">
|
<span class="keep-option">
|
||||||
<input
|
<Checkbox v-model="keepOpacity">
|
||||||
id="keep-opacity"
|
{{ $t('settings.style.switcher.keep_opacity') }}
|
||||||
v-model="keepOpacity"
|
</Checkbox>
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="keep-opacity">{{ $t('settings.style.switcher.keep_opacity') }}</label>
|
|
||||||
</span>
|
</span>
|
||||||
<span class="keep-option">
|
<span class="keep-option">
|
||||||
<input
|
<Checkbox v-model="keepRoundness">
|
||||||
id="keep-roundness"
|
{{ $t('settings.style.switcher.keep_roundness') }}
|
||||||
v-model="keepRoundness"
|
</Checkbox>
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="keep-roundness">{{ $t('settings.style.switcher.keep_roundness') }}</label>
|
|
||||||
</span>
|
</span>
|
||||||
<span class="keep-option">
|
<span class="keep-option">
|
||||||
<input
|
<Checkbox v-model="keepFonts">
|
||||||
id="keep-fonts"
|
{{ $t('settings.style.switcher.keep_fonts') }}
|
||||||
v-model="keepFonts"
|
</Checkbox>
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="keep-fonts">{{ $t('settings.style.switcher.keep_fonts') }}</label>
|
|
||||||
</span>
|
</span>
|
||||||
<p>{{ $t('settings.style.switcher.save_load_hint') }}</p>
|
<p>{{ $t('settings.style.switcher.save_load_hint') }}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -141,7 +141,7 @@ const Timeline = {
|
||||||
const bodyBRect = document.body.getBoundingClientRect()
|
const bodyBRect = document.body.getBoundingClientRect()
|
||||||
const height = Math.max(bodyBRect.height, -(bodyBRect.y))
|
const height = Math.max(bodyBRect.height, -(bodyBRect.y))
|
||||||
if (this.timeline.loading === false &&
|
if (this.timeline.loading === false &&
|
||||||
this.$store.state.config.autoLoad &&
|
this.$store.getters.mergedConfig.autoLoad &&
|
||||||
this.$el.offsetHeight > 0 &&
|
this.$el.offsetHeight > 0 &&
|
||||||
(window.innerHeight + window.pageYOffset) >= (height - 750)) {
|
(window.innerHeight + window.pageYOffset) >= (height - 750)) {
|
||||||
this.fetchOlderStatuses()
|
this.fetchOlderStatuses()
|
||||||
|
@ -153,7 +153,7 @@ const Timeline = {
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
newStatusCount (count) {
|
newStatusCount (count) {
|
||||||
if (!this.$store.state.config.streaming) {
|
if (!this.$store.getters.mergedConfig.streaming) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
|
@ -162,7 +162,7 @@ const Timeline = {
|
||||||
const top = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0)
|
const top = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0)
|
||||||
if (top < 15 &&
|
if (top < 15 &&
|
||||||
!this.paused &&
|
!this.paused &&
|
||||||
!(this.unfocused && this.$store.state.config.pauseOnUnfocused)
|
!(this.unfocused && this.$store.getters.mergedConfig.pauseOnUnfocused)
|
||||||
) {
|
) {
|
||||||
this.showNewStatuses()
|
this.showNewStatuses()
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,19 +1,20 @@
|
||||||
import UserAvatar from '../user_avatar/user_avatar.vue'
|
import UserAvatar from '../user_avatar/user_avatar.vue'
|
||||||
import RemoteFollow from '../remote_follow/remote_follow.vue'
|
import RemoteFollow from '../remote_follow/remote_follow.vue'
|
||||||
import ProgressButton from '../progress_button/progress_button.vue'
|
import ProgressButton from '../progress_button/progress_button.vue'
|
||||||
|
import FollowButton from '../follow_button/follow_button.vue'
|
||||||
import ModerationTools from '../moderation_tools/moderation_tools.vue'
|
import ModerationTools from '../moderation_tools/moderation_tools.vue'
|
||||||
|
import AccountActions from '../account_actions/account_actions.vue'
|
||||||
import { hex2rgb } from '../../services/color_convert/color_convert.js'
|
import { hex2rgb } from '../../services/color_convert/color_convert.js'
|
||||||
import { requestFollow, requestUnfollow } from '../../services/follow_manipulate/follow_manipulate'
|
|
||||||
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
|
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
|
||||||
|
import { mapGetters } from 'vuex'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: [ 'user', 'switcher', 'selected', 'hideBio', 'rounded', 'bordered', 'allowZoomingAvatar' ],
|
props: [
|
||||||
|
'user', 'switcher', 'selected', 'hideBio', 'rounded', 'bordered', 'allowZoomingAvatar'
|
||||||
|
],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
followRequestInProgress: false,
|
followRequestInProgress: false,
|
||||||
hideUserStatsLocal: typeof this.$store.state.config.hideUserStats === 'undefined'
|
|
||||||
? this.$store.state.instance.hideUserStats
|
|
||||||
: this.$store.state.config.hideUserStats,
|
|
||||||
betterShadow: this.$store.state.interface.browserSupport.cssFilter
|
betterShadow: this.$store.state.interface.browserSupport.cssFilter
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -29,9 +30,9 @@ export default {
|
||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
style () {
|
style () {
|
||||||
const color = this.$store.state.config.customTheme.colors
|
const color = this.$store.getters.mergedConfig.customTheme.colors
|
||||||
? this.$store.state.config.customTheme.colors.bg // v2
|
? this.$store.getters.mergedConfig.customTheme.colors.bg // v2
|
||||||
: this.$store.state.config.colors.bg // v1
|
: this.$store.getters.mergedConfig.colors.bg // v1
|
||||||
|
|
||||||
if (color) {
|
if (color) {
|
||||||
const rgb = (typeof color === 'string') ? hex2rgb(color) : color
|
const rgb = (typeof color === 'string') ? hex2rgb(color) : color
|
||||||
|
@ -63,21 +64,22 @@ export default {
|
||||||
},
|
},
|
||||||
userHighlightType: {
|
userHighlightType: {
|
||||||
get () {
|
get () {
|
||||||
const data = this.$store.state.config.highlight[this.user.screen_name]
|
const data = this.$store.getters.mergedConfig.highlight[this.user.screen_name]
|
||||||
return (data && data.type) || 'disabled'
|
return (data && data.type) || 'disabled'
|
||||||
},
|
},
|
||||||
set (type) {
|
set (type) {
|
||||||
const data = this.$store.state.config.highlight[this.user.screen_name]
|
const data = this.$store.getters.mergedConfig.highlight[this.user.screen_name]
|
||||||
if (type !== 'disabled') {
|
if (type !== 'disabled') {
|
||||||
this.$store.dispatch('setHighlight', { user: this.user.screen_name, color: (data && data.color) || '#FFFFFF', type })
|
this.$store.dispatch('setHighlight', { user: this.user.screen_name, color: (data && data.color) || '#FFFFFF', type })
|
||||||
} else {
|
} else {
|
||||||
this.$store.dispatch('setHighlight', { user: this.user.screen_name, color: undefined })
|
this.$store.dispatch('setHighlight', { user: this.user.screen_name, color: undefined })
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
...mapGetters(['mergedConfig'])
|
||||||
},
|
},
|
||||||
userHighlightColor: {
|
userHighlightColor: {
|
||||||
get () {
|
get () {
|
||||||
const data = this.$store.state.config.highlight[this.user.screen_name]
|
const data = this.$store.getters.mergedConfig.highlight[this.user.screen_name]
|
||||||
return data && data.color
|
return data && data.color
|
||||||
},
|
},
|
||||||
set (color) {
|
set (color) {
|
||||||
|
@ -90,36 +92,18 @@ export default {
|
||||||
const validRole = rights.admin || rights.moderator
|
const validRole = rights.admin || rights.moderator
|
||||||
const roleTitle = rights.admin ? 'admin' : 'moderator'
|
const roleTitle = rights.admin ? 'admin' : 'moderator'
|
||||||
return validRole && roleTitle
|
return validRole && roleTitle
|
||||||
}
|
},
|
||||||
|
...mapGetters(['mergedConfig'])
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
UserAvatar,
|
UserAvatar,
|
||||||
RemoteFollow,
|
RemoteFollow,
|
||||||
ModerationTools,
|
ModerationTools,
|
||||||
ProgressButton
|
AccountActions,
|
||||||
|
ProgressButton,
|
||||||
|
FollowButton
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
followUser () {
|
|
||||||
const store = this.$store
|
|
||||||
this.followRequestInProgress = true
|
|
||||||
requestFollow(this.user, store).then(() => {
|
|
||||||
this.followRequestInProgress = false
|
|
||||||
})
|
|
||||||
},
|
|
||||||
unfollowUser () {
|
|
||||||
const store = this.$store
|
|
||||||
this.followRequestInProgress = true
|
|
||||||
requestUnfollow(this.user, store).then(() => {
|
|
||||||
this.followRequestInProgress = false
|
|
||||||
store.commit('removeStatus', { timeline: 'friends', userId: this.user.id })
|
|
||||||
})
|
|
||||||
},
|
|
||||||
blockUser () {
|
|
||||||
this.$store.dispatch('blockUser', this.user.id)
|
|
||||||
},
|
|
||||||
unblockUser () {
|
|
||||||
this.$store.dispatch('unblockUser', this.user.id)
|
|
||||||
},
|
|
||||||
muteUser () {
|
muteUser () {
|
||||||
this.$store.dispatch('muteUser', this.user.id)
|
this.$store.dispatch('muteUser', this.user.id)
|
||||||
},
|
},
|
||||||
|
@ -147,10 +131,10 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
userProfileLink (user) {
|
userProfileLink (user) {
|
||||||
return generateProfileLink(user.id, user.screen_name, this.$store.state.instance.restrictedNicknames)
|
return generateProfileLink(
|
||||||
},
|
user.id, user.screen_name,
|
||||||
reportUser () {
|
this.$store.state.instance.restrictedNicknames
|
||||||
this.$store.dispatch('openUserReportingModal', this.user.id)
|
)
|
||||||
},
|
},
|
||||||
zoomAvatar () {
|
zoomAvatar () {
|
||||||
const attachment = {
|
const attachment = {
|
||||||
|
@ -159,9 +143,6 @@ export default {
|
||||||
}
|
}
|
||||||
this.$store.dispatch('setMedia', [attachment])
|
this.$store.dispatch('setMedia', [attachment])
|
||||||
this.$store.dispatch('setCurrent', attachment)
|
this.$store.dispatch('setCurrent', attachment)
|
||||||
},
|
|
||||||
mentionUser () {
|
|
||||||
this.$store.dispatch('openPostStatusModal', { replyTo: true, repliedUser: this.user })
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,8 +66,11 @@
|
||||||
>
|
>
|
||||||
<i class="icon-link-ext usersettings" />
|
<i class="icon-link-ext usersettings" />
|
||||||
</a>
|
</a>
|
||||||
|
<AccountActions
|
||||||
|
v-if="isOtherUser && loggedIn"
|
||||||
|
:user="user"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="bottom-line">
|
<div class="bottom-line">
|
||||||
<router-link
|
<router-link
|
||||||
class="user-screen-name"
|
class="user-screen-name"
|
||||||
|
@ -81,7 +84,7 @@
|
||||||
>{{ visibleRole }}</span>
|
>{{ visibleRole }}</span>
|
||||||
<span v-if="user.locked"><i class="icon icon-lock" /></span>
|
<span v-if="user.locked"><i class="icon icon-lock" /></span>
|
||||||
<span
|
<span
|
||||||
v-if="!hideUserStatsLocal && !hideBio"
|
v-if="!mergedConfig.hideUserStats && !hideBio"
|
||||||
class="dailyAvg"
|
class="dailyAvg"
|
||||||
>{{ dailyAvg }} {{ $t('user_card.per_day') }}</span>
|
>{{ dailyAvg }} {{ $t('user_card.per_day') }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -135,72 +138,27 @@
|
||||||
v-if="loggedIn && isOtherUser"
|
v-if="loggedIn && isOtherUser"
|
||||||
class="user-interactions"
|
class="user-interactions"
|
||||||
>
|
>
|
||||||
<div v-if="!user.following">
|
<div class="btn-group">
|
||||||
<button
|
<FollowButton :user="user" />
|
||||||
class="btn btn-default btn-block"
|
<template v-if="user.following">
|
||||||
:disabled="followRequestInProgress"
|
<ProgressButton
|
||||||
:title="user.requested ? $t('user_card.follow_again') : ''"
|
v-if="!user.subscribed"
|
||||||
@click="followUser"
|
class="btn btn-default"
|
||||||
>
|
:click="subscribeUser"
|
||||||
<template v-if="followRequestInProgress">
|
:title="$t('user_card.subscribe')"
|
||||||
{{ $t('user_card.follow_progress') }}
|
>
|
||||||
</template>
|
<i class="icon-bell-alt" />
|
||||||
<template v-else-if="user.requested">
|
</ProgressButton>
|
||||||
{{ $t('user_card.follow_sent') }}
|
<ProgressButton
|
||||||
</template>
|
v-else
|
||||||
<template v-else>
|
class="btn btn-default pressed"
|
||||||
{{ $t('user_card.follow') }}
|
:click="unsubscribeUser"
|
||||||
</template>
|
:title="$t('user_card.unsubscribe')"
|
||||||
</button>
|
>
|
||||||
|
<i class="icon-bell-ringing-o" />
|
||||||
|
</ProgressButton>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="followRequestInProgress">
|
|
||||||
<button
|
|
||||||
class="btn btn-default btn-block pressed"
|
|
||||||
disabled
|
|
||||||
:title="$t('user_card.follow_unfollow')"
|
|
||||||
@click="unfollowUser"
|
|
||||||
>
|
|
||||||
{{ $t('user_card.follow_progress') }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-else
|
|
||||||
class="btn-group"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
class="btn btn-default pressed"
|
|
||||||
:title="$t('user_card.follow_unfollow')"
|
|
||||||
@click="unfollowUser"
|
|
||||||
>
|
|
||||||
{{ $t('user_card.following') }}
|
|
||||||
</button>
|
|
||||||
<ProgressButton
|
|
||||||
v-if="!user.subscribed"
|
|
||||||
class="btn btn-default"
|
|
||||||
:click="subscribeUser"
|
|
||||||
:title="$t('user_card.subscribe')"
|
|
||||||
>
|
|
||||||
<i class="icon-bell-alt" />
|
|
||||||
</ProgressButton>
|
|
||||||
<ProgressButton
|
|
||||||
v-else
|
|
||||||
class="btn btn-default pressed"
|
|
||||||
:click="unsubscribeUser"
|
|
||||||
:title="$t('user_card.unsubscribe')"
|
|
||||||
>
|
|
||||||
<i class="icon-bell-ringing-o" />
|
|
||||||
</ProgressButton>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<button
|
|
||||||
class="btn btn-default btn-block"
|
|
||||||
@click="mentionUser"
|
|
||||||
>
|
|
||||||
{{ $t('user_card.mention') }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<button
|
<button
|
||||||
v-if="user.muted"
|
v-if="user.muted"
|
||||||
|
@ -217,33 +175,6 @@
|
||||||
{{ $t('user_card.mute') }}
|
{{ $t('user_card.mute') }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
|
||||||
<button
|
|
||||||
v-if="user.statusnet_blocking"
|
|
||||||
class="btn btn-default btn-block pressed"
|
|
||||||
@click="unblockUser"
|
|
||||||
>
|
|
||||||
{{ $t('user_card.blocked') }}
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
v-else
|
|
||||||
class="btn btn-default btn-block"
|
|
||||||
@click="blockUser"
|
|
||||||
>
|
|
||||||
{{ $t('user_card.block') }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<button
|
|
||||||
class="btn btn-default btn-block"
|
|
||||||
@click="reportUser"
|
|
||||||
>
|
|
||||||
{{ $t('user_card.report') }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<ModerationTools
|
<ModerationTools
|
||||||
v-if="loggedIn.role === "admin""
|
v-if="loggedIn.role === "admin""
|
||||||
:user="user"
|
:user="user"
|
||||||
|
@ -262,7 +193,7 @@
|
||||||
class="panel-body"
|
class="panel-body"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-if="!hideUserStatsLocal && switcher"
|
v-if="!mergedConfig.hideUserStats && switcher"
|
||||||
class="user-counts"
|
class="user-counts"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
@ -345,6 +276,8 @@
|
||||||
mask-composite: exclude;
|
mask-composite: exclude;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
mask-size: 100% 60%;
|
mask-size: 100% 60%;
|
||||||
|
border-top-left-radius: calc(var(--panelRadius) - 1px);
|
||||||
|
border-top-right-radius: calc(var(--panelRadius) - 1px);
|
||||||
|
|
||||||
&.hide-bio {
|
&.hide-bio {
|
||||||
mask-size: 100% 40px;
|
mask-size: 100% 40px;
|
||||||
|
@ -587,13 +520,12 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: row wrap;
|
flex-flow: row wrap;
|
||||||
justify-content: space-between;
|
|
||||||
margin-right: -.75em;
|
margin-right: -.75em;
|
||||||
|
|
||||||
> * {
|
> * {
|
||||||
flex: 1 0 0;
|
|
||||||
margin: 0 .75em .6em 0;
|
margin: 0 .75em .6em 0;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
min-width: 95px;
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
|
|
|
@ -2,12 +2,14 @@
|
||||||
import Status from '../status/status.vue'
|
import Status from '../status/status.vue'
|
||||||
import List from '../list/list.vue'
|
import List from '../list/list.vue'
|
||||||
import Checkbox from '../checkbox/checkbox.vue'
|
import Checkbox from '../checkbox/checkbox.vue'
|
||||||
|
import Modal from '../modal/modal.vue'
|
||||||
|
|
||||||
const UserReportingModal = {
|
const UserReportingModal = {
|
||||||
components: {
|
components: {
|
||||||
Status,
|
Status,
|
||||||
List,
|
List,
|
||||||
Checkbox
|
Checkbox,
|
||||||
|
Modal
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -1,13 +1,9 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<Modal
|
||||||
v-if="isOpen"
|
v-if="isOpen"
|
||||||
class="modal-view"
|
@backdropClicked="closeModal"
|
||||||
@click="closeModal"
|
|
||||||
>
|
>
|
||||||
<div
|
<div class="user-reporting-panel panel">
|
||||||
class="user-reporting-panel panel"
|
|
||||||
@click.stop=""
|
|
||||||
>
|
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
{{ $t('user_reporting.title', [user.screen_name]) }}
|
{{ $t('user_reporting.title', [user.screen_name]) }}
|
||||||
|
@ -69,7 +65,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./user_reporting_modal.js"></script>
|
<script src="./user_reporting_modal.js"></script>
|
||||||
|
|
|
@ -17,6 +17,7 @@ import Autosuggest from '../autosuggest/autosuggest.vue'
|
||||||
import Importer from '../importer/importer.vue'
|
import Importer from '../importer/importer.vue'
|
||||||
import Exporter from '../exporter/exporter.vue'
|
import Exporter from '../exporter/exporter.vue'
|
||||||
import withSubscription from '../../hocs/with_subscription/with_subscription'
|
import withSubscription from '../../hocs/with_subscription/with_subscription'
|
||||||
|
import Checkbox from '../checkbox/checkbox.vue'
|
||||||
import Mfa from './mfa.vue'
|
import Mfa from './mfa.vue'
|
||||||
|
|
||||||
const BlockList = withSubscription({
|
const BlockList = withSubscription({
|
||||||
|
@ -82,7 +83,8 @@ const UserSettings = {
|
||||||
ProgressButton,
|
ProgressButton,
|
||||||
Importer,
|
Importer,
|
||||||
Exporter,
|
Exporter,
|
||||||
Mfa
|
Mfa,
|
||||||
|
Checkbox
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
user () {
|
user () {
|
||||||
|
|
|
@ -53,12 +53,9 @@
|
||||||
/>
|
/>
|
||||||
</EmojiInput>
|
</EmojiInput>
|
||||||
<p>
|
<p>
|
||||||
<input
|
<Checkbox v-model="newLocked">
|
||||||
id="account-locked"
|
{{ $t('settings.lock_account_description') }}
|
||||||
v-model="newLocked"
|
</Checkbox>
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="account-locked">{{ $t('settings.lock_account_description') }}</label>
|
|
||||||
</p>
|
</p>
|
||||||
<div>
|
<div>
|
||||||
<label for="default-vis">{{ $t('settings.default_vis') }}</label>
|
<label for="default-vis">{{ $t('settings.default_vis') }}</label>
|
||||||
|
@ -75,69 +72,52 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p>
|
<p>
|
||||||
<input
|
<Checkbox v-model="newNoRichText">
|
||||||
id="account-no-rich-text"
|
{{ $t('settings.no_rich_text_description') }}
|
||||||
v-model="newNoRichText"
|
</Checkbox>
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="account-no-rich-text">{{ $t('settings.no_rich_text_description') }}</label>
|
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<input
|
<Checkbox v-model="hideFollows">
|
||||||
id="account-hide-follows"
|
{{ $t('settings.hide_follows_description') }}
|
||||||
v-model="hideFollows"
|
</Checkbox>
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="account-hide-follows">{{ $t('settings.hide_follows_description') }}</label>
|
|
||||||
</p>
|
</p>
|
||||||
<p class="setting-subitem">
|
<p class="setting-subitem">
|
||||||
<input
|
<Checkbox
|
||||||
id="account-hide-follows-count"
|
|
||||||
v-model="hideFollowsCount"
|
v-model="hideFollowsCount"
|
||||||
type="checkbox"
|
|
||||||
:disabled="!hideFollows"
|
:disabled="!hideFollows"
|
||||||
>
|
>
|
||||||
<label for="account-hide-follows-count">{{ $t('settings.hide_follows_count_description') }}</label>
|
{{ $t('settings.hide_follows_count_description') }}
|
||||||
|
</Checkbox>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<input
|
<Checkbox
|
||||||
id="account-hide-followers"
|
|
||||||
v-model="hideFollowers"
|
v-model="hideFollowers"
|
||||||
type="checkbox"
|
|
||||||
>
|
>
|
||||||
<label for="account-hide-followers">{{ $t('settings.hide_followers_description') }}</label>
|
{{ $t('settings.hide_followers_description') }}
|
||||||
|
</Checkbox>
|
||||||
</p>
|
</p>
|
||||||
<p class="setting-subitem">
|
<p class="setting-subitem">
|
||||||
<input
|
<Checkbox
|
||||||
id="account-hide-followers-count"
|
|
||||||
v-model="hideFollowersCount"
|
v-model="hideFollowersCount"
|
||||||
type="checkbox"
|
|
||||||
:disabled="!hideFollowers"
|
:disabled="!hideFollowers"
|
||||||
>
|
>
|
||||||
<label for="account-hide-followers-count">{{ $t('settings.hide_followers_count_description') }}</label>
|
{{ $t('settings.hide_followers_count_description') }}
|
||||||
|
</Checkbox>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<input
|
<Checkbox v-model="showRole">
|
||||||
id="account-show-role"
|
<template v-if="role === 'admin'">
|
||||||
v-model="showRole"
|
{{ $t('settings.show_admin_badge') }}
|
||||||
type="checkbox"
|
</template>
|
||||||
>
|
<template v-if="role === 'moderator'">
|
||||||
<label
|
{{ $t('settings.show_moderator_badge') }}
|
||||||
v-if="role === 'admin'"
|
</template>
|
||||||
for="account-show-role"
|
</Checkbox>
|
||||||
>{{ $t('settings.show_admin_badge') }}</label>
|
|
||||||
<label
|
|
||||||
v-if="role === 'moderator'"
|
|
||||||
for="account-show-role"
|
|
||||||
>{{ $t('settings.show_moderator_badge') }}</label>
|
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<input
|
<Checkbox v-model="discoverable">
|
||||||
id="discoverable"
|
{{ $t('settings.discoverable') }}
|
||||||
v-model="discoverable"
|
</Checkbox>
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="discoverable">{{ $t('settings.discoverable') }}</label>
|
|
||||||
</p>
|
</p>
|
||||||
<button
|
<button
|
||||||
:disabled="newName && newName.length === 0"
|
:disabled="newName && newName.length === 0"
|
||||||
|
@ -367,44 +347,24 @@
|
||||||
<span class="label">{{ $t('settings.notification_setting') }}</span>
|
<span class="label">{{ $t('settings.notification_setting') }}</span>
|
||||||
<ul class="option-list">
|
<ul class="option-list">
|
||||||
<li>
|
<li>
|
||||||
<input
|
<Checkbox v-model="notificationSettings.follows">
|
||||||
id="notification-setting-follows"
|
|
||||||
v-model="notificationSettings.follows"
|
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="notification-setting-follows">
|
|
||||||
{{ $t('settings.notification_setting_follows') }}
|
{{ $t('settings.notification_setting_follows') }}
|
||||||
</label>
|
</Checkbox>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<input
|
<Checkbox v-model="notificationSettings.followers">
|
||||||
id="notification-setting-followers"
|
|
||||||
v-model="notificationSettings.followers"
|
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="notification-setting-followers">
|
|
||||||
{{ $t('settings.notification_setting_followers') }}
|
{{ $t('settings.notification_setting_followers') }}
|
||||||
</label>
|
</Checkbox>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<input
|
<Checkbox v-model="notificationSettings.non_follows">
|
||||||
id="notification-setting-non-follows"
|
|
||||||
v-model="notificationSettings.non_follows"
|
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="notification-setting-non-follows">
|
|
||||||
{{ $t('settings.notification_setting_non_follows') }}
|
{{ $t('settings.notification_setting_non_follows') }}
|
||||||
</label>
|
</Checkbox>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<input
|
<Checkbox v-model="notificationSettings.non_followers">
|
||||||
id="notification-setting-non-followers"
|
|
||||||
v-model="notificationSettings.non_followers"
|
|
||||||
type="checkbox"
|
|
||||||
>
|
|
||||||
<label for="notification-setting-non-followers">
|
|
||||||
{{ $t('settings.notification_setting_non_followers') }}
|
{{ $t('settings.notification_setting_non_followers') }}
|
||||||
</label>
|
</Checkbox>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -3,7 +3,7 @@ const VideoAttachment = {
|
||||||
props: ['attachment', 'controls'],
|
props: ['attachment', 'controls'],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
loopVideo: this.$store.state.config.loopVideo
|
loopVideo: this.$store.getters.mergedConfig.loopVideo
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -12,16 +12,16 @@ const VideoAttachment = {
|
||||||
if (typeof target.webkitAudioDecodedByteCount !== 'undefined') {
|
if (typeof target.webkitAudioDecodedByteCount !== 'undefined') {
|
||||||
// non-zero if video has audio track
|
// non-zero if video has audio track
|
||||||
if (target.webkitAudioDecodedByteCount > 0) {
|
if (target.webkitAudioDecodedByteCount > 0) {
|
||||||
this.loopVideo = this.loopVideo && !this.$store.state.config.loopVideoSilentOnly
|
this.loopVideo = this.loopVideo && !this.$store.getters.mergedConfig.loopVideoSilentOnly
|
||||||
}
|
}
|
||||||
} else if (typeof target.mozHasAudio !== 'undefined') {
|
} else if (typeof target.mozHasAudio !== 'undefined') {
|
||||||
// true if video has audio track
|
// true if video has audio track
|
||||||
if (target.mozHasAudio) {
|
if (target.mozHasAudio) {
|
||||||
this.loopVideo = this.loopVideo && !this.$store.state.config.loopVideoSilentOnly
|
this.loopVideo = this.loopVideo && !this.$store.getters.mergedConfig.loopVideoSilentOnly
|
||||||
}
|
}
|
||||||
} else if (typeof target.audioTracks !== 'undefined') {
|
} else if (typeof target.audioTracks !== 'undefined') {
|
||||||
if (target.audioTracks.length > 0) {
|
if (target.audioTracks.length > 0) {
|
||||||
this.loopVideo = this.loopVideo && !this.$store.state.config.loopVideoSilentOnly
|
this.loopVideo = this.loopVideo && !this.$store.getters.mergedConfig.loopVideoSilentOnly
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,42 +2,49 @@ import * as bodyScrollLock from 'body-scroll-lock'
|
||||||
|
|
||||||
let previousNavPaddingRight
|
let previousNavPaddingRight
|
||||||
let previousAppBgWrapperRight
|
let previousAppBgWrapperRight
|
||||||
|
const lockerEls = new Set([])
|
||||||
|
|
||||||
const disableBodyScroll = (el) => {
|
const disableBodyScroll = (el) => {
|
||||||
const scrollBarGap = window.innerWidth - document.documentElement.clientWidth
|
const scrollBarGap = window.innerWidth - document.documentElement.clientWidth
|
||||||
bodyScrollLock.disableBodyScroll(el, {
|
bodyScrollLock.disableBodyScroll(el, {
|
||||||
reserveScrollBarGap: true
|
reserveScrollBarGap: true
|
||||||
})
|
})
|
||||||
|
lockerEls.add(el)
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
// If previousNavPaddingRight is already set, don't set it again.
|
if (lockerEls.size <= 1) {
|
||||||
if (previousNavPaddingRight === undefined) {
|
// If previousNavPaddingRight is already set, don't set it again.
|
||||||
const navEl = document.getElementById('nav')
|
if (previousNavPaddingRight === undefined) {
|
||||||
previousNavPaddingRight = window.getComputedStyle(navEl).getPropertyValue('padding-right')
|
const navEl = document.getElementById('nav')
|
||||||
navEl.style.paddingRight = previousNavPaddingRight ? `calc(${previousNavPaddingRight} + ${scrollBarGap}px)` : `${scrollBarGap}px`
|
previousNavPaddingRight = window.getComputedStyle(navEl).getPropertyValue('padding-right')
|
||||||
|
navEl.style.paddingRight = previousNavPaddingRight ? `calc(${previousNavPaddingRight} + ${scrollBarGap}px)` : `${scrollBarGap}px`
|
||||||
|
}
|
||||||
|
// If previousAppBgWrapeprRight is already set, don't set it again.
|
||||||
|
if (previousAppBgWrapperRight === undefined) {
|
||||||
|
const appBgWrapperEl = document.getElementById('app_bg_wrapper')
|
||||||
|
previousAppBgWrapperRight = window.getComputedStyle(appBgWrapperEl).getPropertyValue('right')
|
||||||
|
appBgWrapperEl.style.right = previousAppBgWrapperRight ? `calc(${previousAppBgWrapperRight} + ${scrollBarGap}px)` : `${scrollBarGap}px`
|
||||||
|
}
|
||||||
|
document.body.classList.add('scroll-locked')
|
||||||
}
|
}
|
||||||
// If previousAppBgWrapeprRight is already set, don't set it again.
|
|
||||||
if (previousAppBgWrapperRight === undefined) {
|
|
||||||
const appBgWrapperEl = document.getElementById('app_bg_wrapper')
|
|
||||||
previousAppBgWrapperRight = window.getComputedStyle(appBgWrapperEl).getPropertyValue('right')
|
|
||||||
appBgWrapperEl.style.right = previousAppBgWrapperRight ? `calc(${previousAppBgWrapperRight} + ${scrollBarGap}px)` : `${scrollBarGap}px`
|
|
||||||
}
|
|
||||||
document.body.classList.add('scroll-locked')
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const enableBodyScroll = (el) => {
|
const enableBodyScroll = (el) => {
|
||||||
|
lockerEls.delete(el)
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (previousNavPaddingRight !== undefined) {
|
if (lockerEls.size === 0) {
|
||||||
document.getElementById('nav').style.paddingRight = previousNavPaddingRight
|
if (previousNavPaddingRight !== undefined) {
|
||||||
// Restore previousNavPaddingRight to undefined so disableBodyScroll knows it can be set again.
|
document.getElementById('nav').style.paddingRight = previousNavPaddingRight
|
||||||
previousNavPaddingRight = undefined
|
// Restore previousNavPaddingRight to undefined so disableBodyScroll knows it can be set again.
|
||||||
|
previousNavPaddingRight = undefined
|
||||||
|
}
|
||||||
|
if (previousAppBgWrapperRight !== undefined) {
|
||||||
|
document.getElementById('app_bg_wrapper').style.right = previousAppBgWrapperRight
|
||||||
|
// Restore previousAppBgWrapperRight to undefined so disableBodyScroll knows it can be set again.
|
||||||
|
previousAppBgWrapperRight = undefined
|
||||||
|
}
|
||||||
|
document.body.classList.remove('scroll-locked')
|
||||||
}
|
}
|
||||||
if (previousAppBgWrapperRight !== undefined) {
|
|
||||||
document.getElementById('app_bg_wrapper').style.right = previousAppBgWrapperRight
|
|
||||||
// Restore previousAppBgWrapperRight to undefined so disableBodyScroll knows it can be set again.
|
|
||||||
previousAppBgWrapperRight = undefined
|
|
||||||
}
|
|
||||||
document.body.classList.remove('scroll-locked')
|
|
||||||
})
|
})
|
||||||
bodyScrollLock.enableBodyScroll(el)
|
bodyScrollLock.enableBodyScroll(el)
|
||||||
}
|
}
|
||||||
|
|
|
@ -555,6 +555,8 @@
|
||||||
"unmute": "Unmute",
|
"unmute": "Unmute",
|
||||||
"unmute_progress": "Unmuting...",
|
"unmute_progress": "Unmuting...",
|
||||||
"mute_progress": "Muting...",
|
"mute_progress": "Muting...",
|
||||||
|
"hide_repeats": "Hide repeats",
|
||||||
|
"show_repeats": "Show repeats",
|
||||||
"admin_menu": {
|
"admin_menu": {
|
||||||
"moderation": "Moderation",
|
"moderation": "Moderation",
|
||||||
"grant_admin": "Grant Admin",
|
"grant_admin": "Grant Admin",
|
||||||
|
@ -630,6 +632,8 @@
|
||||||
"return_home": "Return to the home page",
|
"return_home": "Return to the home page",
|
||||||
"not_found": "We couldn't find that email or username.",
|
"not_found": "We couldn't find that email or username.",
|
||||||
"too_many_requests": "You have reached the limit of attempts, try again later.",
|
"too_many_requests": "You have reached the limit of attempts, try again later.",
|
||||||
"password_reset_disabled": "Password reset is disabled. Please contact your instance administrator."
|
"password_reset_disabled": "Password reset is disabled. Please contact your instance administrator.",
|
||||||
|
"password_reset_required": "You must reset your password to log in.",
|
||||||
|
"password_reset_required_but_mailer_is_disabled": "You must reset your password, but password reset is disabled. Please contact your instance administrator."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,8 +45,8 @@
|
||||||
"error": "Se ha producido un error al importar el archivo."
|
"error": "Se ha producido un error al importar el archivo."
|
||||||
},
|
},
|
||||||
"login": {
|
"login": {
|
||||||
"login": "Identificación",
|
"login": "Identificarse",
|
||||||
"description": "Identificación con OAuth",
|
"description": "Identificarse con OAuth",
|
||||||
"logout": "Cerrar sesión",
|
"logout": "Cerrar sesión",
|
||||||
"password": "Contraseña",
|
"password": "Contraseña",
|
||||||
"placeholder": "p.ej. lain",
|
"placeholder": "p.ej. lain",
|
||||||
|
|
|
@ -68,6 +68,7 @@
|
||||||
},
|
},
|
||||||
"nav": {
|
"nav": {
|
||||||
"about": "Honi buruz",
|
"about": "Honi buruz",
|
||||||
|
"administration": "Administrazioa",
|
||||||
"back": "Atzera",
|
"back": "Atzera",
|
||||||
"chat": "Txat lokala",
|
"chat": "Txat lokala",
|
||||||
"friend_requests": "Jarraitzeko eskaerak",
|
"friend_requests": "Jarraitzeko eskaerak",
|
||||||
|
@ -106,6 +107,15 @@
|
||||||
"expired": "Inkesta {0} bukatu zen",
|
"expired": "Inkesta {0} bukatu zen",
|
||||||
"not_enough_options": "Aukera gutxiegi inkestan"
|
"not_enough_options": "Aukera gutxiegi inkestan"
|
||||||
},
|
},
|
||||||
|
"emoji": {
|
||||||
|
"stickers": "Pegatinak",
|
||||||
|
"emoji": "Emoji",
|
||||||
|
"keep_open": "Mantendu hautatzailea zabalik",
|
||||||
|
"search_emoji": "Bilatu emoji bat",
|
||||||
|
"add_emoji": "Emoji bat gehitu",
|
||||||
|
"custom": "Ohiko emojiak",
|
||||||
|
"unicode": "Unicode emojiak"
|
||||||
|
},
|
||||||
"stickers": {
|
"stickers": {
|
||||||
"add_sticker": "Pegatina gehitu"
|
"add_sticker": "Pegatina gehitu"
|
||||||
},
|
},
|
||||||
|
@ -199,12 +209,12 @@
|
||||||
"avatarRadius": "Avatarrak",
|
"avatarRadius": "Avatarrak",
|
||||||
"background": "Atzeko planoa",
|
"background": "Atzeko planoa",
|
||||||
"bio": "Biografia",
|
"bio": "Biografia",
|
||||||
"block_export": "Bloke esportatzea",
|
"block_export": "Blokeatu dituzunak esportatu",
|
||||||
"block_export_button": "Esportatu zure blokeak csv fitxategi batera",
|
"block_export_button": "Esportatu blokeatutakoak csv fitxategi batera",
|
||||||
"block_import": "Bloke inportazioa",
|
"block_import": "Blokeatu dituzunak inportatu",
|
||||||
"block_import_error": "Errorea blokeak inportatzen",
|
"block_import_error": "Errorea blokeatutakoak inportatzen",
|
||||||
"blocks_imported": "Blokeak inportaturik! Hauek prozesatzeak denbora hartuko du.",
|
"blocks_imported": "Blokeatutakoak inportaturik! Hauek prozesatzeak denbora hartuko du.",
|
||||||
"blocks_tab": "Blokeak",
|
"blocks_tab": "Blokeatutakoak",
|
||||||
"btnRadius": "Botoiak",
|
"btnRadius": "Botoiak",
|
||||||
"cBlue": "Urdina (erantzun, jarraitu)",
|
"cBlue": "Urdina (erantzun, jarraitu)",
|
||||||
"cGreen": "Berdea (Bertxiotu)",
|
"cGreen": "Berdea (Bertxiotu)",
|
||||||
|
@ -222,7 +232,9 @@
|
||||||
"data_import_export_tab": "Datuak Inportatu / Esportatu",
|
"data_import_export_tab": "Datuak Inportatu / Esportatu",
|
||||||
"default_vis": "Lehenetsitako ikusgaitasunak",
|
"default_vis": "Lehenetsitako ikusgaitasunak",
|
||||||
"delete_account": "Ezabatu kontua",
|
"delete_account": "Ezabatu kontua",
|
||||||
|
"discoverable": "Baimendu zure kontua kanpo bilaketa-emaitzetan eta bestelako zerbitzuetan agertzea",
|
||||||
"delete_account_description": "Betirako ezabatu zure kontua eta zure mezu guztiak",
|
"delete_account_description": "Betirako ezabatu zure kontua eta zure mezu guztiak",
|
||||||
|
"pad_emoji": "Zuriuneak gehitu emoji bat aukeratzen denean",
|
||||||
"delete_account_error": "Arazo bat gertatu da zure kontua ezabatzerakoan. Arazoa jarraitu eskero, administratzailearekin harremanetan jarri.",
|
"delete_account_error": "Arazo bat gertatu da zure kontua ezabatzerakoan. Arazoa jarraitu eskero, administratzailearekin harremanetan jarri.",
|
||||||
"delete_account_instructions": "Idatzi zure pasahitza kontua ezabatzeko.",
|
"delete_account_instructions": "Idatzi zure pasahitza kontua ezabatzeko.",
|
||||||
"avatar_size_instruction": "Avatar irudien gomendatutako gutxieneko tamaina 150x150 pixel dira.",
|
"avatar_size_instruction": "Avatar irudien gomendatutako gutxieneko tamaina 150x150 pixel dira.",
|
||||||
|
@ -254,7 +266,7 @@
|
||||||
"instance_default": "(lehenetsia: {value})",
|
"instance_default": "(lehenetsia: {value})",
|
||||||
"instance_default_simple": "(lehenetsia)",
|
"instance_default_simple": "(lehenetsia)",
|
||||||
"interface": "Interfazea",
|
"interface": "Interfazea",
|
||||||
"interfaceLanguage": "Interfaze hizkuntza",
|
"interfaceLanguage": "Interfazearen hizkuntza",
|
||||||
"invalid_theme_imported": "Hautatutako fitxategia ez da onartutako Pleroma gaia. Ez da zure gaian aldaketarik burutu.",
|
"invalid_theme_imported": "Hautatutako fitxategia ez da onartutako Pleroma gaia. Ez da zure gaian aldaketarik burutu.",
|
||||||
"limited_availability": "Ez dago erabilgarri zure nabigatzailean",
|
"limited_availability": "Ez dago erabilgarri zure nabigatzailean",
|
||||||
"links": "Estekak",
|
"links": "Estekak",
|
||||||
|
@ -277,6 +289,8 @@
|
||||||
"no_mutes": "Ez daude erabiltzaile mututuak",
|
"no_mutes": "Ez daude erabiltzaile mututuak",
|
||||||
"hide_follows_description": "Ez erakutsi nor jarraitzen ari naizen",
|
"hide_follows_description": "Ez erakutsi nor jarraitzen ari naizen",
|
||||||
"hide_followers_description": "Ez erakutsi nor ari den ni jarraitzen",
|
"hide_followers_description": "Ez erakutsi nor ari den ni jarraitzen",
|
||||||
|
"hide_follows_count_description": "Ez erakutsi jarraitzen ari naizen kontuen kopurua",
|
||||||
|
"hide_followers_count_description": "Ez erakutsi nire jarraitzaileen kontuen kopurua",
|
||||||
"show_admin_badge": "Erakutsi Administratzaile etiketa nire profilan",
|
"show_admin_badge": "Erakutsi Administratzaile etiketa nire profilan",
|
||||||
"show_moderator_badge": "Erakutsi Moderatzaile etiketa nire profilan",
|
"show_moderator_badge": "Erakutsi Moderatzaile etiketa nire profilan",
|
||||||
"nsfw_clickthrough": "Gaitu klika hunkigarri eranskinak ezkutatzeko",
|
"nsfw_clickthrough": "Gaitu klika hunkigarri eranskinak ezkutatzeko",
|
||||||
|
@ -449,7 +463,7 @@
|
||||||
},
|
},
|
||||||
"version": {
|
"version": {
|
||||||
"title": "Bertsioa",
|
"title": "Bertsioa",
|
||||||
"backend_version": "Backend Bertsio",
|
"backend_version": "Backend Bertsioa",
|
||||||
"frontend_version": "Frontend Bertsioa"
|
"frontend_version": "Frontend Bertsioa"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -529,6 +543,7 @@
|
||||||
"follows_you": "Jarraitzen dizu!",
|
"follows_you": "Jarraitzen dizu!",
|
||||||
"its_you": "Zu zara!",
|
"its_you": "Zu zara!",
|
||||||
"media": "Multimedia",
|
"media": "Multimedia",
|
||||||
|
"mention": "Aipatu",
|
||||||
"mute": "Isilarazi",
|
"mute": "Isilarazi",
|
||||||
"muted": "Isilduta",
|
"muted": "Isilduta",
|
||||||
"per_day": "eguneko",
|
"per_day": "eguneko",
|
||||||
|
|
|
@ -41,7 +41,13 @@ Vue.use(VueChatScroll)
|
||||||
Vue.use(VueClickOutside)
|
Vue.use(VueClickOutside)
|
||||||
Vue.use(PortalVue)
|
Vue.use(PortalVue)
|
||||||
Vue.use(VBodyScrollLock)
|
Vue.use(VBodyScrollLock)
|
||||||
Vue.use(VTooltip)
|
Vue.use(VTooltip, {
|
||||||
|
popover: {
|
||||||
|
defaultTrigger: 'hover click',
|
||||||
|
defaultContainer: false,
|
||||||
|
defaultOffset: 5
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
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
|
||||||
|
|
|
@ -3,8 +3,9 @@ import { setPreset, applyTheme } from '../services/style_setter/style_setter.js'
|
||||||
|
|
||||||
const browserLocale = (window.navigator.language || 'en').split('-')[0]
|
const browserLocale = (window.navigator.language || 'en').split('-')[0]
|
||||||
|
|
||||||
const defaultState = {
|
export const defaultState = {
|
||||||
colors: {},
|
colors: {},
|
||||||
|
// bad name: actually hides posts of muted USERS
|
||||||
hideMutedPosts: undefined, // instance default
|
hideMutedPosts: undefined, // instance default
|
||||||
collapseMessageWithSubject: undefined, // instance default
|
collapseMessageWithSubject: undefined, // instance default
|
||||||
padEmoji: true,
|
padEmoji: true,
|
||||||
|
@ -37,11 +38,37 @@ const defaultState = {
|
||||||
subjectLineBehavior: undefined, // instance default
|
subjectLineBehavior: undefined, // instance default
|
||||||
alwaysShowSubjectInput: undefined, // instance default
|
alwaysShowSubjectInput: undefined, // instance default
|
||||||
postContentType: undefined, // instance default
|
postContentType: undefined, // instance default
|
||||||
minimalScopesMode: undefined // instance default
|
minimalScopesMode: undefined, // instance default
|
||||||
|
// This hides statuses filtered via a word filter
|
||||||
|
hideFilteredStatuses: undefined, // instance default
|
||||||
|
playVideosInModal: false,
|
||||||
|
useOneClickNsfw: false,
|
||||||
|
useContainFit: false,
|
||||||
|
hidePostStats: undefined, // instance default
|
||||||
|
hideUserStats: undefined // instance default
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// caching the instance default properties
|
||||||
|
export const instanceDefaultProperties = Object.entries(defaultState)
|
||||||
|
.filter(([key, value]) => value === undefined)
|
||||||
|
.map(([key, value]) => key)
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
state: defaultState,
|
state: defaultState,
|
||||||
|
getters: {
|
||||||
|
mergedConfig (state, getters, rootState, rootGetters) {
|
||||||
|
const { instance } = rootState
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
...instanceDefaultProperties
|
||||||
|
.map(key => [key, state[key] === undefined
|
||||||
|
? instance[key]
|
||||||
|
: state[key]
|
||||||
|
])
|
||||||
|
.reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
mutations: {
|
mutations: {
|
||||||
setOption (state, { name, value }) {
|
setOption (state, { name, value }) {
|
||||||
set(state, name, value)
|
set(state, name, value)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { set } from 'vue'
|
import { set } from 'vue'
|
||||||
import { setPreset } from '../services/style_setter/style_setter.js'
|
import { setPreset } from '../services/style_setter/style_setter.js'
|
||||||
|
import { instanceDefaultProperties } from './config.js'
|
||||||
|
|
||||||
const defaultState = {
|
const defaultState = {
|
||||||
// Stuff from static/config.json and apiConfig
|
// Stuff from static/config.json and apiConfig
|
||||||
|
@ -72,6 +73,13 @@ const instance = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
getters: {
|
||||||
|
instanceDefaultConfig (state) {
|
||||||
|
return instanceDefaultProperties
|
||||||
|
.map(key => [key, state[key]])
|
||||||
|
.reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {})
|
||||||
|
}
|
||||||
|
},
|
||||||
actions: {
|
actions: {
|
||||||
setInstanceOption ({ commit, dispatch }, { name, value }) {
|
setInstanceOption ({ commit, dispatch }, { name, value }) {
|
||||||
commit('setInstanceOption', { name, value })
|
commit('setInstanceOption', { name, value })
|
||||||
|
|
|
@ -537,6 +537,10 @@ const statuses = {
|
||||||
setNotificationsSilence ({ rootState, commit }, { value }) {
|
setNotificationsSilence ({ rootState, commit }, { value }) {
|
||||||
commit('setNotificationsSilence', { value })
|
commit('setNotificationsSilence', { value })
|
||||||
},
|
},
|
||||||
|
fetchStatus ({ rootState, dispatch }, id) {
|
||||||
|
rootState.api.backendInteractor.fetchStatus({ id })
|
||||||
|
.then((status) => dispatch('addNewStatuses', { statuses: [status] }))
|
||||||
|
},
|
||||||
deleteStatus ({ rootState, commit }, status) {
|
deleteStatus ({ rootState, commit }, status) {
|
||||||
commit('setDeleted', { status })
|
commit('setDeleted', { status })
|
||||||
apiService.deleteStatus({ id: status.id, credentials: rootState.users.currentUser.credentials })
|
apiService.deleteStatus({ id: status.id, credentials: rootState.users.currentUser.credentials })
|
||||||
|
|
|
@ -60,6 +60,18 @@ const unmuteUser = (store, id) => {
|
||||||
.then((relationship) => store.commit('updateUserRelationship', [relationship]))
|
.then((relationship) => store.commit('updateUserRelationship', [relationship]))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const hideReblogs = (store, userId) => {
|
||||||
|
return store.rootState.api.backendInteractor.followUser({ id: userId, reblogs: false })
|
||||||
|
.then((relationship) => {
|
||||||
|
store.commit('updateUserRelationship', [relationship])
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const showReblogs = (store, userId) => {
|
||||||
|
return store.rootState.api.backendInteractor.followUser({ id: userId, reblogs: true })
|
||||||
|
.then((relationship) => store.commit('updateUserRelationship', [relationship]))
|
||||||
|
}
|
||||||
|
|
||||||
export const mutations = {
|
export const mutations = {
|
||||||
setMuted (state, { user: { id }, muted }) {
|
setMuted (state, { user: { id }, muted }) {
|
||||||
const user = state.usersObject[id]
|
const user = state.usersObject[id]
|
||||||
|
@ -135,6 +147,7 @@ export const mutations = {
|
||||||
user.muted = relationship.muting
|
user.muted = relationship.muting
|
||||||
user.statusnet_blocking = relationship.blocking
|
user.statusnet_blocking = relationship.blocking
|
||||||
user.subscribed = relationship.subscribing
|
user.subscribed = relationship.subscribing
|
||||||
|
user.showing_reblogs = relationship.showing_reblogs
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
@ -272,6 +285,12 @@ const users = {
|
||||||
unmuteUser (store, id) {
|
unmuteUser (store, id) {
|
||||||
return unmuteUser(store, id)
|
return unmuteUser(store, id)
|
||||||
},
|
},
|
||||||
|
hideReblogs (store, id) {
|
||||||
|
return hideReblogs(store, id)
|
||||||
|
},
|
||||||
|
showReblogs (store, id) {
|
||||||
|
return showReblogs(store, id)
|
||||||
|
},
|
||||||
muteUsers (store, ids = []) {
|
muteUsers (store, ids = []) {
|
||||||
return Promise.all(ids.map(id => muteUser(store, id)))
|
return Promise.all(ids.map(id => muteUser(store, id)))
|
||||||
},
|
},
|
||||||
|
|
|
@ -219,10 +219,16 @@ const authHeaders = (accessToken) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const followUser = ({ id, credentials }) => {
|
const followUser = ({ id, credentials, ...options }) => {
|
||||||
let url = MASTODON_FOLLOW_URL(id)
|
let url = MASTODON_FOLLOW_URL(id)
|
||||||
|
const form = {}
|
||||||
|
if (options.reblogs !== undefined) { form['reblogs'] = options.reblogs }
|
||||||
return fetch(url, {
|
return fetch(url, {
|
||||||
headers: authHeaders(credentials),
|
body: JSON.stringify(form),
|
||||||
|
headers: {
|
||||||
|
...authHeaders(credentials),
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
}).then((data) => data.json())
|
}).then((data) => data.json())
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,8 +31,8 @@ const backendInteractorService = credentials => {
|
||||||
return apiService.fetchUserRelationship({ id, credentials })
|
return apiService.fetchUserRelationship({ id, credentials })
|
||||||
}
|
}
|
||||||
|
|
||||||
const followUser = (id) => {
|
const followUser = ({ id, reblogs }) => {
|
||||||
return apiService.followUser({ credentials, id })
|
return apiService.followUser({ credentials, id, reblogs })
|
||||||
}
|
}
|
||||||
|
|
||||||
const unfollowUser = (id) => {
|
const unfollowUser = (id) => {
|
||||||
|
|
|
@ -69,6 +69,7 @@ export const parseUser = (data) => {
|
||||||
output.following = relationship.following
|
output.following = relationship.following
|
||||||
output.statusnet_blocking = relationship.blocking
|
output.statusnet_blocking = relationship.blocking
|
||||||
output.muted = relationship.muting
|
output.muted = relationship.muting
|
||||||
|
output.showing_reblogs = relationship.showing_reblogs
|
||||||
output.subscribed = relationship.subscribing
|
output.subscribed = relationship.subscribing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ const fetchUser = (attempt, user, store) => new Promise((resolve, reject) => {
|
||||||
})
|
})
|
||||||
|
|
||||||
export const requestFollow = (user, store) => new Promise((resolve, reject) => {
|
export const requestFollow = (user, store) => new Promise((resolve, reject) => {
|
||||||
store.state.api.backendInteractor.followUser(user.id)
|
store.state.api.backendInteractor.followUser({ id: user.id })
|
||||||
.then((updated) => {
|
.then((updated) => {
|
||||||
store.commit('updateUserRelationship', [updated])
|
store.commit('updateUserRelationship', [updated])
|
||||||
|
|
||||||
|
|
|
@ -8,11 +8,10 @@ const update = ({ store, notifications, older }) => {
|
||||||
|
|
||||||
const fetchAndUpdate = ({ store, credentials, older = false }) => {
|
const fetchAndUpdate = ({ store, credentials, older = false }) => {
|
||||||
const args = { credentials }
|
const args = { credentials }
|
||||||
|
const { getters } = store
|
||||||
const rootState = store.rootState || store.state
|
const rootState = store.rootState || store.state
|
||||||
const timelineData = rootState.statuses.notifications
|
const timelineData = rootState.statuses.notifications
|
||||||
const hideMutedPosts = typeof rootState.config.hideMutedPosts === 'undefined'
|
const hideMutedPosts = getters.mergedConfig.hideMutedPosts
|
||||||
? rootState.instance.hideMutedPosts
|
|
||||||
: rootState.config.hideMutedPosts
|
|
||||||
|
|
||||||
args['withMuted'] = !hideMutedPosts
|
args['withMuted'] = !hideMutedPosts
|
||||||
|
|
||||||
|
|
|
@ -15,13 +15,21 @@ const update = ({ store, statuses, timeline, showImmediately, userId }) => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const fetchAndUpdate = ({ store, credentials, timeline = 'friends', older = false, showImmediately = false, userId = false, tag = false, until }) => {
|
const fetchAndUpdate = ({
|
||||||
|
store,
|
||||||
|
credentials,
|
||||||
|
timeline = 'friends',
|
||||||
|
older = false,
|
||||||
|
showImmediately = false,
|
||||||
|
userId = false,
|
||||||
|
tag = false,
|
||||||
|
until
|
||||||
|
}) => {
|
||||||
const args = { timeline, credentials }
|
const args = { timeline, credentials }
|
||||||
const rootState = store.rootState || store.state
|
const rootState = store.rootState || store.state
|
||||||
|
const { getters } = store
|
||||||
const timelineData = rootState.statuses.timelines[camelCase(timeline)]
|
const timelineData = rootState.statuses.timelines[camelCase(timeline)]
|
||||||
const hideMutedPosts = typeof rootState.config.hideMutedPosts === 'undefined'
|
const hideMutedPosts = getters.mergedConfig.hideMutedPosts
|
||||||
? rootState.instance.hideMutedPosts
|
|
||||||
: rootState.config.hideMutedPosts
|
|
||||||
|
|
||||||
if (older) {
|
if (older) {
|
||||||
args['until'] = until || timelineData.minId
|
args['until'] = until || timelineData.minId
|
||||||
|
|
|
@ -12,8 +12,8 @@ const generateInput = (value, padEmoji = true) => {
|
||||||
},
|
},
|
||||||
mocks: {
|
mocks: {
|
||||||
$store: {
|
$store: {
|
||||||
state: {
|
getters: {
|
||||||
config: {
|
mergedConfig: {
|
||||||
padEmoji
|
padEmoji
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,14 @@ const actions = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const testGetters = {
|
const testGetters = {
|
||||||
findUser: state => getters.findUser(state.users)
|
findUser: state => getters.findUser(state.users),
|
||||||
|
mergedConfig: state => ({
|
||||||
|
colors: '',
|
||||||
|
highlight: {},
|
||||||
|
customTheme: {
|
||||||
|
colors: []
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const localUser = {
|
const localUser = {
|
||||||
|
@ -45,13 +52,6 @@ const externalProfileStore = new Vuex.Store({
|
||||||
interface: {
|
interface: {
|
||||||
browserSupport: ''
|
browserSupport: ''
|
||||||
},
|
},
|
||||||
config: {
|
|
||||||
colors: '',
|
|
||||||
highlight: {},
|
|
||||||
customTheme: {
|
|
||||||
colors: []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
instance: {
|
instance: {
|
||||||
hideUserStats: true
|
hideUserStats: true
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue