--fix
This commit is contained in:
parent
0cbfcb99a9
commit
fddb531ed2
18
src/App.vue
18
src/App.vue
|
@ -16,7 +16,11 @@
|
||||||
:class="classes"
|
:class="classes"
|
||||||
>
|
>
|
||||||
<div class="underlay" />
|
<div class="underlay" />
|
||||||
<div id="sidebar" class="column -scrollable" :class="{ '-show-scrollbar': showScrollbars }">
|
<div
|
||||||
|
id="sidebar"
|
||||||
|
class="column -scrollable"
|
||||||
|
:class="{ '-show-scrollbar': showScrollbars }"
|
||||||
|
>
|
||||||
<user-panel />
|
<user-panel />
|
||||||
<template v-if="layoutType !== 'mobile'">
|
<template v-if="layoutType !== 'mobile'">
|
||||||
<nav-panel />
|
<nav-panel />
|
||||||
|
@ -26,7 +30,11 @@
|
||||||
<div id="notifs-sidebar" />
|
<div id="notifs-sidebar" />
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<div id="main-scroller" class="column main" :class="{ '-full-height': isChats }">
|
<div
|
||||||
|
id="main-scroller"
|
||||||
|
class="column main"
|
||||||
|
:class="{ '-full-height': isChats }"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
v-if="!currentUser"
|
v-if="!currentUser"
|
||||||
class="login-hint panel panel-default"
|
class="login-hint panel panel-default"
|
||||||
|
@ -40,7 +48,11 @@
|
||||||
</div>
|
</div>
|
||||||
<router-view />
|
<router-view />
|
||||||
</div>
|
</div>
|
||||||
<div id="notifs-column" class="column -scrollable" :class="{ '-show-scrollbar': showScrollbars }"/>
|
<div
|
||||||
|
id="notifs-column"
|
||||||
|
class="column -scrollable"
|
||||||
|
:class="{ '-show-scrollbar': showScrollbars }"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<MediaModal />
|
<MediaModal />
|
||||||
<shout-panel
|
<shout-panel
|
||||||
|
|
|
@ -156,7 +156,7 @@ const setSettings = async ({ apiConfig, staticConfig, store }) => {
|
||||||
copyInstanceOption('hideSitename')
|
copyInstanceOption('hideSitename')
|
||||||
copyInstanceOption('sidebarRight')
|
copyInstanceOption('sidebarRight')
|
||||||
|
|
||||||
return store.dispatch('setTheme', config['theme'])
|
return store.dispatch('setTheme', config.theme)
|
||||||
}
|
}
|
||||||
|
|
||||||
const getTOS = async ({ store }) => {
|
const getTOS = async ({ store }) => {
|
||||||
|
@ -197,7 +197,7 @@ const getStickers = async ({ store }) => {
|
||||||
const stickers = (await Promise.all(
|
const stickers = (await Promise.all(
|
||||||
Object.entries(values).map(async ([name, path]) => {
|
Object.entries(values).map(async ([name, path]) => {
|
||||||
const resPack = await window.fetch(path + 'pack.json')
|
const resPack = await window.fetch(path + 'pack.json')
|
||||||
var meta = {}
|
let meta = {}
|
||||||
if (resPack.ok) {
|
if (resPack.ok) {
|
||||||
meta = await resPack.json()
|
meta = await resPack.json()
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,8 @@ export default (store) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
let routes = [
|
let routes = [
|
||||||
{ name: 'root',
|
{
|
||||||
|
name: 'root',
|
||||||
path: '/',
|
path: '/',
|
||||||
redirect: _to => {
|
redirect: _to => {
|
||||||
return (store.state.users.currentUser
|
return (store.state.users.currentUser
|
||||||
|
@ -45,12 +46,14 @@ export default (store) => {
|
||||||
{ name: 'tag-timeline', path: '/tag/:tag', component: TagTimeline },
|
{ name: 'tag-timeline', path: '/tag/:tag', component: TagTimeline },
|
||||||
{ name: 'bookmarks', path: '/bookmarks', component: BookmarkTimeline },
|
{ name: 'bookmarks', path: '/bookmarks', component: BookmarkTimeline },
|
||||||
{ name: 'conversation', path: '/notice/:id', component: ConversationPage, meta: { dontScroll: true } },
|
{ name: 'conversation', path: '/notice/:id', component: ConversationPage, meta: { dontScroll: true } },
|
||||||
{ name: 'remote-user-profile-acct',
|
{
|
||||||
|
name: 'remote-user-profile-acct',
|
||||||
path: '/remote-users/:_(@)?:username([^/@]+)@:hostname([^/@]+)',
|
path: '/remote-users/:_(@)?:username([^/@]+)@:hostname([^/@]+)',
|
||||||
component: RemoteUserResolver,
|
component: RemoteUserResolver,
|
||||||
beforeEnter: validateAuthenticatedRoute
|
beforeEnter: validateAuthenticatedRoute
|
||||||
},
|
},
|
||||||
{ name: 'remote-user-profile',
|
{
|
||||||
|
name: 'remote-user-profile',
|
||||||
path: '/remote-users/:hostname/:username',
|
path: '/remote-users/:hostname/:username',
|
||||||
component: RemoteUserResolver,
|
component: RemoteUserResolver,
|
||||||
beforeEnter: validateAuthenticatedRoute
|
beforeEnter: validateAuthenticatedRoute
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
:bound-to="{ x: 'container' }"
|
:bound-to="{ x: 'container' }"
|
||||||
remove-padding
|
remove-padding
|
||||||
>
|
>
|
||||||
<template v-slot:content>
|
<template #content>
|
||||||
<div class="dropdown-menu">
|
<div class="dropdown-menu">
|
||||||
<template v-if="relationship.following">
|
<template v-if="relationship.following">
|
||||||
<button
|
<button
|
||||||
|
@ -57,7 +57,7 @@
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:trigger>
|
<template #trigger>
|
||||||
<button class="button-unstyled ellipsis-button">
|
<button class="button-unstyled ellipsis-button">
|
||||||
<FAIcon
|
<FAIcon
|
||||||
class="icon"
|
class="icon"
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="basic-user-card">
|
<div class="basic-user-card">
|
||||||
<router-link @click.prevent :to="userProfileLink(user)">
|
<router-link
|
||||||
|
:to="userProfileLink(user)"
|
||||||
|
@click.prevent
|
||||||
|
>
|
||||||
<UserPopover
|
<UserPopover
|
||||||
:userId="user.id"
|
:user-id="user.id"
|
||||||
:overlayCenters="true"
|
:overlay-centers="true"
|
||||||
overlayCentersSelector=".avatar"
|
overlay-centers-selector=".avatar"
|
||||||
>
|
>
|
||||||
<UserAvatar
|
<UserAvatar
|
||||||
class="user-avatar avatar"
|
class="user-avatar avatar"
|
||||||
|
|
|
@ -107,7 +107,7 @@ const Chat = {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
'$route': function () {
|
$route: function () {
|
||||||
this.startFetching()
|
this.startFetching()
|
||||||
},
|
},
|
||||||
mastoUserSocketStatus (newValue) {
|
mastoUserSocketStatus (newValue) {
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
class="timeline"
|
class="timeline"
|
||||||
>
|
>
|
||||||
<List :items="sortedChatList">
|
<List :items="sortedChatList">
|
||||||
<template v-slot:item="{item}">
|
<template #item="{item}">
|
||||||
<ChatListItem
|
<ChatListItem
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
:compact="false"
|
:compact="false"
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
>
|
>
|
||||||
<UserPopover
|
<UserPopover
|
||||||
v-if="chatViewItem.isHead"
|
v-if="chatViewItem.isHead"
|
||||||
:userId="author.id"
|
:user-id="author.id"
|
||||||
>
|
>
|
||||||
<UserAvatar
|
<UserAvatar
|
||||||
:compact="true"
|
:compact="true"
|
||||||
|
@ -50,7 +50,7 @@
|
||||||
@show="menuOpened = true"
|
@show="menuOpened = true"
|
||||||
@close="menuOpened = false"
|
@close="menuOpened = false"
|
||||||
>
|
>
|
||||||
<template v-slot:content>
|
<template #content>
|
||||||
<div class="dropdown-menu">
|
<div class="dropdown-menu">
|
||||||
<button
|
<button
|
||||||
class="button-default dropdown-item dropdown-item-icon"
|
class="button-default dropdown-item dropdown-item-icon"
|
||||||
|
@ -60,7 +60,7 @@
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:trigger>
|
<template #trigger>
|
||||||
<button
|
<button
|
||||||
class="button-default menu-icon"
|
class="button-default menu-icon"
|
||||||
:title="$t('chats.more')"
|
:title="$t('chats.more')"
|
||||||
|
@ -75,7 +75,7 @@
|
||||||
:status="messageForStatusContent"
|
:status="messageForStatusContent"
|
||||||
:full-content="true"
|
:full-content="true"
|
||||||
>
|
>
|
||||||
<template v-slot:footer>
|
<template #footer>
|
||||||
<span
|
<span
|
||||||
class="created-at"
|
class="created-at"
|
||||||
>
|
>
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
:title="title"
|
:title="title"
|
||||||
>
|
>
|
||||||
<UserPopover
|
<UserPopover
|
||||||
class="avatar-container"
|
|
||||||
v-if="withAvatar && user"
|
v-if="withAvatar && user"
|
||||||
:userId="user.id"
|
class="avatar-container"
|
||||||
|
:user-id="user.id"
|
||||||
>
|
>
|
||||||
<UserAvatar
|
<UserAvatar
|
||||||
class="titlebar-avatar"
|
class="titlebar-avatar"
|
||||||
|
|
|
@ -22,12 +22,12 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
emits: ['update:modelValue'],
|
|
||||||
props: [
|
props: [
|
||||||
'modelValue',
|
'modelValue',
|
||||||
'indeterminate',
|
'indeterminate',
|
||||||
'disabled'
|
'disabled'
|
||||||
]
|
],
|
||||||
|
emits: ['update:modelValue']
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<style lang="scss" src="./color_input.scss"></style>
|
|
||||||
<script>
|
<script>
|
||||||
import Checkbox from '../checkbox/checkbox.vue'
|
import Checkbox from '../checkbox/checkbox.vue'
|
||||||
import { hex2rgb } from '../../services/color_convert/color_convert.js'
|
import { hex2rgb } from '../../services/color_convert/color_convert.js'
|
||||||
|
@ -108,6 +107,7 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
<style lang="scss" src="./color_input.scss"></style>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.color-control {
|
.color-control {
|
||||||
|
|
|
@ -271,7 +271,7 @@ const conversation = {
|
||||||
result[irid] = result[irid] || []
|
result[irid] = result[irid] || []
|
||||||
result[irid].push({
|
result[irid].push({
|
||||||
name: `#${i}`,
|
name: `#${i}`,
|
||||||
id: id
|
id
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
i++
|
i++
|
||||||
|
|
|
@ -31,8 +31,8 @@
|
||||||
keypath="status.show_all_conversation_with_icon"
|
keypath="status.show_all_conversation_with_icon"
|
||||||
tag="button"
|
tag="button"
|
||||||
class="button-unstyled -link"
|
class="button-unstyled -link"
|
||||||
@click.prevent="diveToTopLevel"
|
|
||||||
scope="global"
|
scope="global"
|
||||||
|
@click.prevent="diveToTopLevel"
|
||||||
>
|
>
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<FAIcon
|
<FAIcon
|
||||||
|
|
|
@ -46,21 +46,25 @@ export default {
|
||||||
enableMask () { return this.supportsMask && this.$store.state.instance.logoMask },
|
enableMask () { return this.supportsMask && this.$store.state.instance.logoMask },
|
||||||
logoStyle () {
|
logoStyle () {
|
||||||
return {
|
return {
|
||||||
'visibility': this.enableMask ? 'hidden' : 'visible'
|
visibility: this.enableMask ? 'hidden' : 'visible'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
logoMaskStyle () {
|
logoMaskStyle () {
|
||||||
return this.enableMask ? {
|
return this.enableMask
|
||||||
|
? {
|
||||||
'mask-image': `url(${this.$store.state.instance.logo})`
|
'mask-image': `url(${this.$store.state.instance.logo})`
|
||||||
} : {
|
}
|
||||||
|
: {
|
||||||
'background-color': this.enableMask ? '' : 'transparent'
|
'background-color': this.enableMask ? '' : 'transparent'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
logoBgStyle () {
|
logoBgStyle () {
|
||||||
return Object.assign({
|
return Object.assign({
|
||||||
'margin': `${this.$store.state.instance.logoMargin} 0`,
|
margin: `${this.$store.state.instance.logoMargin} 0`,
|
||||||
opacity: this.searchBarHidden ? 1 : 0
|
opacity: this.searchBarHidden ? 1 : 0
|
||||||
}, this.enableMask ? {} : {
|
}, this.enableMask
|
||||||
|
? {}
|
||||||
|
: {
|
||||||
'background-color': this.enableMask ? '' : 'transparent'
|
'background-color': this.enableMask ? '' : 'transparent'
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
class="btn button-default"
|
class="btn button-default"
|
||||||
>
|
>
|
||||||
{{ $t('domain_mute_card.unmute') }}
|
{{ $t('domain_mute_card.unmute') }}
|
||||||
<template v-slot:progress>
|
<template #progress>
|
||||||
{{ $t('domain_mute_card.unmute_progress') }}
|
{{ $t('domain_mute_card.unmute_progress') }}
|
||||||
</template>
|
</template>
|
||||||
</ProgressButton>
|
</ProgressButton>
|
||||||
|
@ -19,7 +19,7 @@
|
||||||
class="btn button-default"
|
class="btn button-default"
|
||||||
>
|
>
|
||||||
{{ $t('domain_mute_card.mute') }}
|
{{ $t('domain_mute_card.mute') }}
|
||||||
<template v-slot:progress>
|
<template #progress>
|
||||||
{{ $t('domain_mute_card.mute_progress') }}
|
{{ $t('domain_mute_card.mute_progress') }}
|
||||||
</template>
|
</template>
|
||||||
</ProgressButton>
|
</ProgressButton>
|
||||||
|
|
|
@ -321,7 +321,7 @@ const EmojiInput = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
scrollIntoView () {
|
scrollIntoView () {
|
||||||
const rootRef = this.$refs['picker'].$el
|
const rootRef = this.$refs.picker.$el
|
||||||
/* Scroller is either `window` (replies in TL), sidebar (main post form,
|
/* Scroller is either `window` (replies in TL), sidebar (main post form,
|
||||||
* replies in notifs) or mobile post form. Note that getting and setting
|
* replies in notifs) or mobile post form. Note that getting and setting
|
||||||
* scroll is different for `Window` and `Element`s
|
* scroll is different for `Window` and `Element`s
|
||||||
|
|
|
@ -25,7 +25,7 @@ const filterByKeyword = (list, keyword = '') => {
|
||||||
if (keyword === '') return list
|
if (keyword === '') return list
|
||||||
|
|
||||||
const keywordLowercase = keyword.toLowerCase()
|
const keywordLowercase = keyword.toLowerCase()
|
||||||
let orderedEmojiList = []
|
const orderedEmojiList = []
|
||||||
for (const emoji of list) {
|
for (const emoji of list) {
|
||||||
const indexOfKeyword = emoji.displayText.toLowerCase().indexOf(keywordLowercase)
|
const indexOfKeyword = emoji.displayText.toLowerCase().indexOf(keywordLowercase)
|
||||||
if (indexOfKeyword > -1) {
|
if (indexOfKeyword > -1) {
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
:bound-to="{ x: 'container' }"
|
:bound-to="{ x: 'container' }"
|
||||||
remove-padding
|
remove-padding
|
||||||
>
|
>
|
||||||
<template v-slot:content="{close}">
|
<template #content="{close}">
|
||||||
<div class="dropdown-menu">
|
<div class="dropdown-menu">
|
||||||
<button
|
<button
|
||||||
v-if="canMute && !status.thread_muted"
|
v-if="canMute && !status.thread_muted"
|
||||||
|
@ -120,7 +120,7 @@
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:trigger>
|
<template #trigger>
|
||||||
<span class="button-unstyled popover-trigger">
|
<span class="button-unstyled popover-trigger">
|
||||||
<FAIcon
|
<FAIcon
|
||||||
class="fa-scale-110 fa-old-padding"
|
class="fa-scale-110 fa-old-padding"
|
||||||
|
|
|
@ -95,7 +95,7 @@ const ImageCropper = {
|
||||||
const fileInput = this.$refs.input
|
const fileInput = this.$refs.input
|
||||||
if (fileInput.files != null && fileInput.files[0] != null) {
|
if (fileInput.files != null && fileInput.files[0] != null) {
|
||||||
this.file = fileInput.files[0]
|
this.file = fileInput.files[0]
|
||||||
let reader = new window.FileReader()
|
const reader = new window.FileReader()
|
||||||
reader.onload = (e) => {
|
reader.onload = (e) => {
|
||||||
this.dataUrl = e.target.result
|
this.dataUrl = e.target.result
|
||||||
this.$emit('open')
|
this.$emit('open')
|
||||||
|
|
|
@ -12,7 +12,7 @@ const Interactions = {
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
allowFollowingMove: this.$store.state.users.currentUser.allow_following_move,
|
allowFollowingMove: this.$store.state.users.currentUser.allow_following_move,
|
||||||
filterMode: tabModeDict['mentions']
|
filterMode: tabModeDict.mentions
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
|
@ -25,6 +25,7 @@ import Select from '../select/select.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
|
// eslint-disable-next-line vue/no-reserved-component-names
|
||||||
Select
|
Select
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
|
|
@ -83,7 +83,7 @@ const LoginForm = {
|
||||||
},
|
},
|
||||||
clearError () { this.error = false },
|
clearError () { this.error = false },
|
||||||
focusOnPasswordInput () {
|
focusOnPasswordInput () {
|
||||||
let passwordInput = this.$refs.passwordInput
|
const passwordInput = this.$refs.passwordInput
|
||||||
passwordInput.focus()
|
passwordInput.focus()
|
||||||
passwordInput.setSelectionRange(0, passwordInput.value.length)
|
passwordInput.setSelectionRange(0, passwordInput.value.length)
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,8 @@ const mediaUpload = {
|
||||||
.then((fileData) => {
|
.then((fileData) => {
|
||||||
self.$emit('uploaded', fileData)
|
self.$emit('uploaded', fileData)
|
||||||
self.decreaseUploadCount()
|
self.decreaseUploadCount()
|
||||||
}, (error) => { // eslint-disable-line handle-callback-err
|
}, (error) => {
|
||||||
|
console.error('Error uploading file', error)
|
||||||
self.$emit('upload-failed', 'default')
|
self.$emit('upload-failed', 'default')
|
||||||
self.decreaseUploadCount()
|
self.decreaseUploadCount()
|
||||||
})
|
})
|
||||||
|
@ -73,7 +74,7 @@ const mediaUpload = {
|
||||||
'disabled'
|
'disabled'
|
||||||
],
|
],
|
||||||
watch: {
|
watch: {
|
||||||
'dropFiles': function (fileInfos) {
|
dropFiles: function (fileInfos) {
|
||||||
if (!this.uploading) {
|
if (!this.uploading) {
|
||||||
this.multiUpload(fileInfos)
|
this.multiUpload(fileInfos)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
/><!-- eslint-enable vue/no-v-html -->
|
/><!-- eslint-enable vue/no-v-html -->
|
||||||
<UserPopover
|
<UserPopover
|
||||||
v-else
|
v-else
|
||||||
:userId="user.id"
|
:user-id="user.id"
|
||||||
:disabled="!shouldShowTooltip"
|
:disabled="!shouldShowTooltip"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
|
@ -54,7 +54,10 @@
|
||||||
:class="{ '-you': shouldBoldenYou }"
|
:class="{ '-you': shouldBoldenYou }"
|
||||||
> {{ ' ' + $t('status.you') }}</span>
|
> {{ ' ' + $t('status.you') }}</span>
|
||||||
<!-- eslint-enable vue/no-v-html -->
|
<!-- eslint-enable vue/no-v-html -->
|
||||||
</a><span class="full" ref="full">
|
</a><span
|
||||||
|
ref="full"
|
||||||
|
class="full"
|
||||||
|
>
|
||||||
<!-- eslint-disable vue/no-v-html -->
|
<!-- eslint-disable vue/no-v-html -->
|
||||||
@<span v-html="userName" /><span v-html="'@' + serverName" />
|
@<span v-html="userName" /><span v-html="'@' + serverName" />
|
||||||
<!-- eslint-enable vue/no-v-html -->
|
<!-- eslint-enable vue/no-v-html -->
|
||||||
|
|
|
@ -67,11 +67,10 @@
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="mobile-notifications"
|
|
||||||
id="mobile-notifications"
|
id="mobile-notifications"
|
||||||
|
class="mobile-notifications"
|
||||||
@scroll="onScroll"
|
@scroll="onScroll"
|
||||||
>
|
/>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<SideDrawer
|
<SideDrawer
|
||||||
ref="sideDrawer"
|
ref="sideDrawer"
|
||||||
|
|
|
@ -12,6 +12,9 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
|
provide: {
|
||||||
|
popoversZLayer: 'modals'
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
isOpen: {
|
isOpen: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
|
@ -22,14 +25,11 @@ export default {
|
||||||
default: false
|
default: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
provide: {
|
|
||||||
popoversZLayer: 'modals'
|
|
||||||
},
|
|
||||||
computed: {
|
computed: {
|
||||||
classes () {
|
classes () {
|
||||||
return {
|
return {
|
||||||
'modal-background': !this.noBackground,
|
'modal-background': !this.noBackground,
|
||||||
'open': this.isOpen
|
open: this.isOpen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
@show="setToggled(true)"
|
@show="setToggled(true)"
|
||||||
@close="setToggled(false)"
|
@close="setToggled(false)"
|
||||||
>
|
>
|
||||||
<template v-slot:content>
|
<template #content>
|
||||||
<div class="dropdown-menu">
|
<div class="dropdown-menu">
|
||||||
<span v-if="user.is_local">
|
<span v-if="user.is_local">
|
||||||
<button
|
<button
|
||||||
|
@ -122,7 +122,7 @@
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:trigger>
|
<template #trigger>
|
||||||
<button
|
<button
|
||||||
class="btn button-default btn-block moderation-tools-button"
|
class="btn button-default btn-block moderation-tools-button"
|
||||||
:class="{ toggled }"
|
:class="{ toggled }"
|
||||||
|
@ -137,11 +137,11 @@
|
||||||
v-if="showDeleteUserDialog"
|
v-if="showDeleteUserDialog"
|
||||||
:on-cancel="deleteUserDialog.bind(this, false)"
|
:on-cancel="deleteUserDialog.bind(this, false)"
|
||||||
>
|
>
|
||||||
<template v-slot:header>
|
<template #header>
|
||||||
{{ $t('user_card.admin_menu.delete_user') }}
|
{{ $t('user_card.admin_menu.delete_user') }}
|
||||||
</template>
|
</template>
|
||||||
<p>{{ $t('user_card.admin_menu.delete_user_confirmation') }}</p>
|
<p>{{ $t('user_card.admin_menu.delete_user_confirmation') }}</p>
|
||||||
<template v-slot:footer>
|
<template #footer>
|
||||||
<button
|
<button
|
||||||
class="btn button-default"
|
class="btn button-default"
|
||||||
@click="deleteUserDialog(false)"
|
@click="deleteUserDialog(false)"
|
||||||
|
|
|
@ -9,10 +9,10 @@ import { get } from 'lodash'
|
||||||
*/
|
*/
|
||||||
const toInstanceReasonObject = (instances, info, key) => {
|
const toInstanceReasonObject = (instances, info, key) => {
|
||||||
return instances.map(instance => {
|
return instances.map(instance => {
|
||||||
if (info[key] && info[key][instance] && info[key][instance]['reason']) {
|
if (info[key] && info[key][instance] && info[key][instance].reason) {
|
||||||
return { instance: instance, reason: info[key][instance]['reason'] }
|
return { instance, reason: info[key][instance].reason }
|
||||||
}
|
}
|
||||||
return { instance: instance, reason: '' }
|
return { instance, reason: '' }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,8 +37,8 @@
|
||||||
@click.prevent
|
@click.prevent
|
||||||
>
|
>
|
||||||
<UserPopover
|
<UserPopover
|
||||||
:userId="notification.from_profile.id"
|
:user-id="notification.from_profile.id"
|
||||||
:overlayCenters="true"
|
:overlay-centers="true"
|
||||||
>
|
>
|
||||||
<UserAvatar
|
<UserAvatar
|
||||||
class="post-avatar"
|
class="post-avatar"
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
placement="bottom"
|
placement="bottom"
|
||||||
:bound-to="{ x: 'container' }"
|
:bound-to="{ x: 'container' }"
|
||||||
>
|
>
|
||||||
<template v-slot:content>
|
<template #content>
|
||||||
<div class="dropdown-menu">
|
<div class="dropdown-menu">
|
||||||
<button
|
<button
|
||||||
class="button-default dropdown-item"
|
class="button-default dropdown-item"
|
||||||
|
@ -72,7 +72,7 @@
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:trigger>
|
<template #trigger>
|
||||||
<button class="filter-trigger-button button-unstyled">
|
<button class="filter-trigger-button button-unstyled">
|
||||||
<FAIcon icon="filter" />
|
<FAIcon icon="filter" />
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<teleport :disabled="minimalMode || disableTeleport" :to="teleportTarget">
|
<teleport
|
||||||
|
:disabled="minimalMode || disableTeleport"
|
||||||
|
:to="teleportTarget"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
:class="{ minimal: minimalMode }"
|
:class="{ minimal: minimalMode }"
|
||||||
class="Notifications"
|
class="Notifications"
|
||||||
|
|
|
@ -104,18 +104,22 @@ const Popover = {
|
||||||
|
|
||||||
// What are the screen bounds for the popover? Viewport vs container
|
// What are the screen bounds for the popover? Viewport vs container
|
||||||
// when using viewport, using default margin values to dodge the navbar
|
// when using viewport, using default margin values to dodge the navbar
|
||||||
const xBounds = this.boundTo && this.boundTo.x === 'container' ? {
|
const xBounds = this.boundTo && this.boundTo.x === 'container'
|
||||||
|
? {
|
||||||
min: parentScreenBox.left + (margin.left || 0),
|
min: parentScreenBox.left + (margin.left || 0),
|
||||||
max: parentScreenBox.right - (margin.right || 0)
|
max: parentScreenBox.right - (margin.right || 0)
|
||||||
} : {
|
}
|
||||||
|
: {
|
||||||
min: 0 + (margin.left || 10),
|
min: 0 + (margin.left || 10),
|
||||||
max: window.innerWidth - (margin.right || 10)
|
max: window.innerWidth - (margin.right || 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
const yBounds = this.boundTo && this.boundTo.y === 'container' ? {
|
const yBounds = this.boundTo && this.boundTo.y === 'container'
|
||||||
|
? {
|
||||||
min: parentScreenBox.top + (margin.top || 0),
|
min: parentScreenBox.top + (margin.top || 0),
|
||||||
max: parentScreenBox.bottom - (margin.bottom || 0)
|
max: parentScreenBox.bottom - (margin.bottom || 0)
|
||||||
} : {
|
}
|
||||||
|
: {
|
||||||
min: 0 + (margin.top || 50),
|
min: 0 + (margin.top || 50),
|
||||||
max: window.innerHeight - (margin.bottom || 5)
|
max: window.innerHeight - (margin.bottom || 5)
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ const buildMentionsString = ({ user, attentions = [] }, currentUser) => {
|
||||||
allAttentions = uniqBy(allAttentions, 'id')
|
allAttentions = uniqBy(allAttentions, 'id')
|
||||||
allAttentions = reject(allAttentions, { id: currentUser.id })
|
allAttentions = reject(allAttentions, { id: currentUser.id })
|
||||||
|
|
||||||
let mentions = map(allAttentions, (attention) => {
|
const mentions = map(allAttentions, (attention) => {
|
||||||
return `@${attention.screen_name}`
|
return `@${attention.screen_name}`
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -242,7 +242,7 @@ const PostStatusForm = {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
'newStatus': {
|
newStatus: {
|
||||||
deep: true,
|
deep: true,
|
||||||
handler () {
|
handler () {
|
||||||
this.statusChanged()
|
this.statusChanged()
|
||||||
|
@ -273,7 +273,7 @@ const PostStatusForm = {
|
||||||
this.$refs.textarea.focus()
|
this.$refs.textarea.focus()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
let el = this.$el.querySelector('textarea')
|
const el = this.$el.querySelector('textarea')
|
||||||
el.style.height = 'auto'
|
el.style.height = 'auto'
|
||||||
el.style.height = undefined
|
el.style.height = undefined
|
||||||
this.error = null
|
this.error = null
|
||||||
|
@ -392,7 +392,7 @@ const PostStatusForm = {
|
||||||
this.$emit('resize', { delayed: true })
|
this.$emit('resize', { delayed: true })
|
||||||
},
|
},
|
||||||
removeMediaFile (fileInfo) {
|
removeMediaFile (fileInfo) {
|
||||||
let index = this.newStatus.files.indexOf(fileInfo)
|
const index = this.newStatus.files.indexOf(fileInfo)
|
||||||
this.newStatus.files.splice(index, 1)
|
this.newStatus.files.splice(index, 1)
|
||||||
this.$emit('resize')
|
this.$emit('resize')
|
||||||
},
|
},
|
||||||
|
@ -462,7 +462,7 @@ const PostStatusForm = {
|
||||||
},
|
},
|
||||||
onEmojiInputInput (e) {
|
onEmojiInputInput (e) {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.resize(this.$refs['textarea'])
|
this.resize(this.$refs.textarea)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
resize (e) {
|
resize (e) {
|
||||||
|
@ -477,8 +477,8 @@ const PostStatusForm = {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const formRef = this.$refs['form']
|
const formRef = this.$refs.form
|
||||||
const bottomRef = this.$refs['bottom']
|
const bottomRef = this.$refs.bottom
|
||||||
/* Scroller is either `window` (replies in TL), sidebar (main post form,
|
/* Scroller is either `window` (replies in TL), sidebar (main post form,
|
||||||
* replies in notifs) or mobile post form. Note that getting and setting
|
* replies in notifs) or mobile post form. Note that getting and setting
|
||||||
* scroll is different for `Window` and `Element`s
|
* scroll is different for `Window` and `Element`s
|
||||||
|
@ -564,7 +564,7 @@ const PostStatusForm = {
|
||||||
this.$refs['emoji-input'].resize()
|
this.$refs['emoji-input'].resize()
|
||||||
},
|
},
|
||||||
showEmojiPicker () {
|
showEmojiPicker () {
|
||||||
this.$refs['textarea'].focus()
|
this.$refs.textarea.focus()
|
||||||
this.$refs['emoji-input'].triggerShowPicker()
|
this.$refs['emoji-input'].triggerShowPicker()
|
||||||
},
|
},
|
||||||
clearError () {
|
clearError () {
|
||||||
|
|
|
@ -45,7 +45,7 @@ const ReactButton = {
|
||||||
emojis () {
|
emojis () {
|
||||||
if (this.filterWord !== '') {
|
if (this.filterWord !== '') {
|
||||||
const filterWordLowercase = trim(this.filterWord.toLowerCase())
|
const filterWordLowercase = trim(this.filterWord.toLowerCase())
|
||||||
let orderedEmojiList = []
|
const orderedEmojiList = []
|
||||||
for (const emoji of this.$store.state.instance.emoji) {
|
for (const emoji of this.$store.state.instance.emoji) {
|
||||||
if (emoji.replacement === this.filterWord) return [emoji]
|
if (emoji.replacement === this.filterWord) return [emoji]
|
||||||
|
|
||||||
|
|
|
@ -9,13 +9,13 @@
|
||||||
popover-class="ReactButton popover-default"
|
popover-class="ReactButton popover-default"
|
||||||
@show="focusInput"
|
@show="focusInput"
|
||||||
>
|
>
|
||||||
<template v-slot:content="{close}">
|
<template #content="{close}">
|
||||||
<div class="reaction-picker-filter">
|
<div class="reaction-picker-filter">
|
||||||
<input
|
<input
|
||||||
v-model="filterWord"
|
v-model="filterWord"
|
||||||
@input="$event.target.composing = false"
|
|
||||||
size="1"
|
size="1"
|
||||||
:placeholder="$t('emoji.search_emoji')"
|
:placeholder="$t('emoji.search_emoji')"
|
||||||
|
@input="$event.target.composing = false"
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="reaction-picker">
|
<div class="reaction-picker">
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
<div class="reaction-bottom-fader" />
|
<div class="reaction-bottom-fader" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:trigger>
|
<template #trigger>
|
||||||
<span
|
<span
|
||||||
class="button-unstyled popover-trigger"
|
class="button-unstyled popover-trigger"
|
||||||
:title="$t('tool_tip.add_reaction')"
|
:title="$t('tool_tip.add_reaction')"
|
||||||
|
|
|
@ -16,7 +16,7 @@ const SearchBar = {
|
||||||
error: false
|
error: false
|
||||||
}),
|
}),
|
||||||
watch: {
|
watch: {
|
||||||
'$route': function (route) {
|
$route: function (route) {
|
||||||
if (route.name === 'search') {
|
if (route.name === 'search') {
|
||||||
this.searchTerm = route.query.query
|
this.searchTerm = route.query.query
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
:items="items"
|
:items="items"
|
||||||
:get-key="getKey"
|
:get-key="getKey"
|
||||||
>
|
>
|
||||||
<template v-slot:item="{item}">
|
<template #item="{item}">
|
||||||
<div
|
<div
|
||||||
class="selectable-list-item-inner"
|
class="selectable-list-item-inner"
|
||||||
:class="{ 'selectable-list-item-selected-inner': isSelected(item) }"
|
:class="{ 'selectable-list-item-selected-inner': isSelected(item) }"
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:empty>
|
<template #empty>
|
||||||
<slot name="empty" />
|
<slot name="empty" />
|
||||||
</template>
|
</template>
|
||||||
</List>
|
</List>
|
||||||
|
|
|
@ -6,14 +6,14 @@
|
||||||
<Popover
|
<Popover
|
||||||
trigger="hover"
|
trigger="hover"
|
||||||
>
|
>
|
||||||
<template v-slot:trigger>
|
<template #trigger>
|
||||||
|
|
||||||
<FAIcon
|
<FAIcon
|
||||||
icon="wrench"
|
icon="wrench"
|
||||||
:aria-label="$t('settings.setting_changed')"
|
:aria-label="$t('settings.setting_changed')"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:content>
|
<template #content>
|
||||||
<div class="modified-tooltip">
|
<div class="modified-tooltip">
|
||||||
{{ $t('settings.setting_changed') }}
|
{{ $t('settings.setting_changed') }}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -6,14 +6,14 @@
|
||||||
<Popover
|
<Popover
|
||||||
trigger="hover"
|
trigger="hover"
|
||||||
>
|
>
|
||||||
<template v-slot:trigger>
|
<template #trigger>
|
||||||
|
|
||||||
<FAIcon
|
<FAIcon
|
||||||
icon="server"
|
icon="server"
|
||||||
:aria-label="$t('settings.setting_server_side')"
|
:aria-label="$t('settings.setting_server_side')"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:content>
|
<template #content>
|
||||||
<div class="serverside-tooltip">
|
<div class="serverside-tooltip">
|
||||||
{{ $t('settings.setting_server_side') }}
|
{{ $t('settings.setting_server_side') }}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -53,7 +53,7 @@
|
||||||
:bound-to="{ x: 'container' }"
|
:bound-to="{ x: 'container' }"
|
||||||
remove-padding
|
remove-padding
|
||||||
>
|
>
|
||||||
<template v-slot:trigger>
|
<template #trigger>
|
||||||
<button
|
<button
|
||||||
class="btn button-default"
|
class="btn button-default"
|
||||||
:title="$t('general.close')"
|
:title="$t('general.close')"
|
||||||
|
@ -65,7 +65,7 @@
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:content="{close}">
|
<template #content="{close}">
|
||||||
<div class="dropdown-menu">
|
<div class="dropdown-menu">
|
||||||
<button
|
<button
|
||||||
class="button-default dropdown-item dropdown-item-icon"
|
class="button-default dropdown-item dropdown-item-icon"
|
||||||
|
|
|
@ -75,12 +75,18 @@
|
||||||
</BooleanSetting>
|
</BooleanSetting>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<BooleanSetting path="userPopoverZoom" expert="1">
|
<BooleanSetting
|
||||||
|
path="userPopoverZoom"
|
||||||
|
expert="1"
|
||||||
|
>
|
||||||
{{ $t('settings.user_popover_avatar_zoom') }}
|
{{ $t('settings.user_popover_avatar_zoom') }}
|
||||||
</BooleanSetting>
|
</BooleanSetting>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<BooleanSetting path="userPopoverOverlay" expert="1">
|
<BooleanSetting
|
||||||
|
path="userPopoverOverlay"
|
||||||
|
expert="1"
|
||||||
|
>
|
||||||
{{ $t('settings.user_popover_avatar_overlay') }}
|
{{ $t('settings.user_popover_avatar_overlay') }}
|
||||||
</BooleanSetting>
|
</BooleanSetting>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
:query="queryUserIds"
|
:query="queryUserIds"
|
||||||
:placeholder="$t('settings.search_user_to_block')"
|
:placeholder="$t('settings.search_user_to_block')"
|
||||||
>
|
>
|
||||||
<template v-slot="row">
|
<template #default="row">
|
||||||
<BlockCard
|
<BlockCard
|
||||||
:user-id="row.item"
|
:user-id="row.item"
|
||||||
/>
|
/>
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
:refresh="true"
|
:refresh="true"
|
||||||
:get-key="i => i"
|
:get-key="i => i"
|
||||||
>
|
>
|
||||||
<template v-slot:header="{selected}">
|
<template #header="{selected}">
|
||||||
<div class="bulk-actions">
|
<div class="bulk-actions">
|
||||||
<ProgressButton
|
<ProgressButton
|
||||||
v-if="selected.length > 0"
|
v-if="selected.length > 0"
|
||||||
|
@ -29,7 +29,7 @@
|
||||||
:click="() => blockUsers(selected)"
|
:click="() => blockUsers(selected)"
|
||||||
>
|
>
|
||||||
{{ $t('user_card.block') }}
|
{{ $t('user_card.block') }}
|
||||||
<template v-slot:progress>
|
<template #progress>
|
||||||
{{ $t('user_card.block_progress') }}
|
{{ $t('user_card.block_progress') }}
|
||||||
</template>
|
</template>
|
||||||
</ProgressButton>
|
</ProgressButton>
|
||||||
|
@ -39,16 +39,16 @@
|
||||||
:click="() => unblockUsers(selected)"
|
:click="() => unblockUsers(selected)"
|
||||||
>
|
>
|
||||||
{{ $t('user_card.unblock') }}
|
{{ $t('user_card.unblock') }}
|
||||||
<template v-slot:progress>
|
<template #progress>
|
||||||
{{ $t('user_card.unblock_progress') }}
|
{{ $t('user_card.unblock_progress') }}
|
||||||
</template>
|
</template>
|
||||||
</ProgressButton>
|
</ProgressButton>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:item="{item}">
|
<template #item="{item}">
|
||||||
<BlockCard :user-id="item" />
|
<BlockCard :user-id="item" />
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:empty>
|
<template #empty>
|
||||||
{{ $t('settings.no_blocks') }}
|
{{ $t('settings.no_blocks') }}
|
||||||
</template>
|
</template>
|
||||||
</BlockList>
|
</BlockList>
|
||||||
|
@ -63,7 +63,7 @@
|
||||||
:query="queryUserIds"
|
:query="queryUserIds"
|
||||||
:placeholder="$t('settings.search_user_to_mute')"
|
:placeholder="$t('settings.search_user_to_mute')"
|
||||||
>
|
>
|
||||||
<template v-slot="row">
|
<template #default="row">
|
||||||
<MuteCard
|
<MuteCard
|
||||||
:user-id="row.item"
|
:user-id="row.item"
|
||||||
/>
|
/>
|
||||||
|
@ -74,7 +74,7 @@
|
||||||
:refresh="true"
|
:refresh="true"
|
||||||
:get-key="i => i"
|
:get-key="i => i"
|
||||||
>
|
>
|
||||||
<template v-slot:header="{selected}">
|
<template #header="{selected}">
|
||||||
<div class="bulk-actions">
|
<div class="bulk-actions">
|
||||||
<ProgressButton
|
<ProgressButton
|
||||||
v-if="selected.length > 0"
|
v-if="selected.length > 0"
|
||||||
|
@ -82,7 +82,7 @@
|
||||||
:click="() => muteUsers(selected)"
|
:click="() => muteUsers(selected)"
|
||||||
>
|
>
|
||||||
{{ $t('user_card.mute') }}
|
{{ $t('user_card.mute') }}
|
||||||
<template v-slot:progress>
|
<template #progress>
|
||||||
{{ $t('user_card.mute_progress') }}
|
{{ $t('user_card.mute_progress') }}
|
||||||
</template>
|
</template>
|
||||||
</ProgressButton>
|
</ProgressButton>
|
||||||
|
@ -92,16 +92,16 @@
|
||||||
:click="() => unmuteUsers(selected)"
|
:click="() => unmuteUsers(selected)"
|
||||||
>
|
>
|
||||||
{{ $t('user_card.unmute') }}
|
{{ $t('user_card.unmute') }}
|
||||||
<template v-slot:progress>
|
<template #progress>
|
||||||
{{ $t('user_card.unmute_progress') }}
|
{{ $t('user_card.unmute_progress') }}
|
||||||
</template>
|
</template>
|
||||||
</ProgressButton>
|
</ProgressButton>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:item="{item}">
|
<template #item="{item}">
|
||||||
<MuteCard :user-id="item" />
|
<MuteCard :user-id="item" />
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:empty>
|
<template #empty>
|
||||||
{{ $t('settings.no_mutes') }}
|
{{ $t('settings.no_mutes') }}
|
||||||
</template>
|
</template>
|
||||||
</MuteList>
|
</MuteList>
|
||||||
|
@ -114,7 +114,7 @@
|
||||||
:query="queryKnownDomains"
|
:query="queryKnownDomains"
|
||||||
:placeholder="$t('settings.type_domains_to_mute')"
|
:placeholder="$t('settings.type_domains_to_mute')"
|
||||||
>
|
>
|
||||||
<template v-slot="row">
|
<template #default="row">
|
||||||
<DomainMuteCard
|
<DomainMuteCard
|
||||||
:domain="row.item"
|
:domain="row.item"
|
||||||
/>
|
/>
|
||||||
|
@ -125,7 +125,7 @@
|
||||||
:refresh="true"
|
:refresh="true"
|
||||||
:get-key="i => i"
|
:get-key="i => i"
|
||||||
>
|
>
|
||||||
<template v-slot:header="{selected}">
|
<template #header="{selected}">
|
||||||
<div class="bulk-actions">
|
<div class="bulk-actions">
|
||||||
<ProgressButton
|
<ProgressButton
|
||||||
v-if="selected.length > 0"
|
v-if="selected.length > 0"
|
||||||
|
@ -133,16 +133,16 @@
|
||||||
:click="() => unmuteDomains(selected)"
|
:click="() => unmuteDomains(selected)"
|
||||||
>
|
>
|
||||||
{{ $t('domain_mute_card.unmute') }}
|
{{ $t('domain_mute_card.unmute') }}
|
||||||
<template v-slot:progress>
|
<template #progress>
|
||||||
{{ $t('domain_mute_card.unmute_progress') }}
|
{{ $t('domain_mute_card.unmute_progress') }}
|
||||||
</template>
|
</template>
|
||||||
</ProgressButton>
|
</ProgressButton>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:item="{item}">
|
<template #item="{item}">
|
||||||
<DomainMuteCard :domain="item" />
|
<DomainMuteCard :domain="item" />
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:empty>
|
<template #empty>
|
||||||
{{ $t('settings.no_mutes') }}
|
{{ $t('settings.no_mutes') }}
|
||||||
</template>
|
</template>
|
||||||
</DomainMuteList>
|
</DomainMuteList>
|
||||||
|
|
|
@ -71,10 +71,12 @@ const ProfileTab = {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
emojiSuggestor () {
|
emojiSuggestor () {
|
||||||
return suggestor({ emoji: [
|
return suggestor({
|
||||||
|
emoji: [
|
||||||
...this.$store.state.instance.emoji,
|
...this.$store.state.instance.emoji,
|
||||||
...this.$store.state.instance.customEmoji
|
...this.$store.state.instance.customEmoji
|
||||||
] })
|
]
|
||||||
|
})
|
||||||
},
|
},
|
||||||
userSuggestor () {
|
userSuggestor () {
|
||||||
return suggestor({ store: this.$store })
|
return suggestor({ store: this.$store })
|
||||||
|
|
|
@ -117,8 +117,8 @@
|
||||||
<button
|
<button
|
||||||
v-if="!isDefaultAvatar && pickAvatarBtnVisible"
|
v-if="!isDefaultAvatar && pickAvatarBtnVisible"
|
||||||
:title="$t('settings.reset_avatar')"
|
:title="$t('settings.reset_avatar')"
|
||||||
@click="resetAvatar"
|
|
||||||
class="button-unstyled reset-button"
|
class="button-unstyled reset-button"
|
||||||
|
@click="resetAvatar"
|
||||||
>
|
>
|
||||||
<FAIcon
|
<FAIcon
|
||||||
icon="times"
|
icon="times"
|
||||||
|
|
|
@ -32,8 +32,8 @@ const Mfa = {
|
||||||
components: {
|
components: {
|
||||||
'recovery-codes': RecoveryCodes,
|
'recovery-codes': RecoveryCodes,
|
||||||
'totp-item': TOTP,
|
'totp-item': TOTP,
|
||||||
'qrcode': VueQrcode,
|
qrcode: VueQrcode,
|
||||||
'confirm': Confirm
|
confirm: Confirm
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
canSetupOTP () {
|
canSetupOTP () {
|
||||||
|
@ -139,7 +139,7 @@ const Mfa = {
|
||||||
|
|
||||||
// fetch settings from server
|
// fetch settings from server
|
||||||
async fetchSettings () {
|
async fetchSettings () {
|
||||||
let result = await this.backendInteractor.settingsMFA()
|
const result = await this.backendInteractor.settingsMFA()
|
||||||
if (result.error) return
|
if (result.error) return
|
||||||
this.settings = result.settings
|
this.settings = result.settings
|
||||||
this.settings.available = true
|
this.settings.available = true
|
||||||
|
|
|
@ -10,7 +10,7 @@ export default {
|
||||||
inProgress: false // progress peform request to disable otp method
|
inProgress: false // progress peform request to disable otp method
|
||||||
}),
|
}),
|
||||||
components: {
|
components: {
|
||||||
'confirm': Confirm
|
confirm: Confirm
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
isActivated () {
|
isActivated () {
|
||||||
|
|
|
@ -29,7 +29,10 @@
|
||||||
{{ $t('settings.style.preview.content') }}
|
{{ $t('settings.style.preview.content') }}
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
<i18n-t scope="global" keypath="settings.style.preview.text">
|
<i18n-t
|
||||||
|
scope="global"
|
||||||
|
keypath="settings.style.preview.text"
|
||||||
|
>
|
||||||
<code style="font-family: var(--postCodeFont)">
|
<code style="font-family: var(--postCodeFont)">
|
||||||
{{ $t('settings.style.preview.mono') }}
|
{{ $t('settings.style.preview.mono') }}
|
||||||
</code>
|
</code>
|
||||||
|
|
|
@ -112,9 +112,11 @@ export default {
|
||||||
return hex2rgb(this.selected.color)
|
return hex2rgb(this.selected.color)
|
||||||
},
|
},
|
||||||
style () {
|
style () {
|
||||||
return this.ready ? {
|
return this.ready
|
||||||
|
? {
|
||||||
boxShadow: getCssShadow(this.fallback)
|
boxShadow: getCssShadow(this.fallback)
|
||||||
} : {}
|
}
|
||||||
|
: {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,8 @@ const StaffPanel = {
|
||||||
const groupedStaffAccounts = groupBy(staffAccounts, 'role')
|
const groupedStaffAccounts = groupBy(staffAccounts, 'role')
|
||||||
|
|
||||||
return [
|
return [
|
||||||
{ role: 'admin', users: groupedStaffAccounts['admin'] },
|
{ role: 'admin', users: groupedStaffAccounts.admin },
|
||||||
{ role: 'moderator', users: groupedStaffAccounts['moderator'] }
|
{ role: 'moderator', users: groupedStaffAccounts.moderator }
|
||||||
].filter(group => group.users)
|
].filter(group => group.users)
|
||||||
},
|
},
|
||||||
...mapGetters([
|
...mapGetters([
|
||||||
|
|
|
@ -448,7 +448,7 @@ const Status = {
|
||||||
scrollIfHighlighted (highlightId) {
|
scrollIfHighlighted (highlightId) {
|
||||||
const id = highlightId
|
const id = highlightId
|
||||||
if (this.status.id === id) {
|
if (this.status.id === id) {
|
||||||
let rect = this.$el.getBoundingClientRect()
|
const rect = this.$el.getBoundingClientRect()
|
||||||
if (rect.top < 100) {
|
if (rect.top < 100) {
|
||||||
// Post is above screen, match its top to screen top
|
// Post is above screen, match its top to screen top
|
||||||
window.scrollBy(0, rect.top - 100)
|
window.scrollBy(0, rect.top - 100)
|
||||||
|
@ -463,7 +463,7 @@ const Status = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
'highlight': function (id) {
|
highlight: function (id) {
|
||||||
this.scrollIfHighlighted(id)
|
this.scrollIfHighlighted(id)
|
||||||
},
|
},
|
||||||
'status.repeat_num': function (num) {
|
'status.repeat_num': function (num) {
|
||||||
|
@ -478,7 +478,7 @@ const Status = {
|
||||||
this.$store.dispatch('fetchFavs', this.status.id)
|
this.$store.dispatch('fetchFavs', this.status.id)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'isSuspendable': function (val) {
|
isSuspendable: function (val) {
|
||||||
this.suspendable = val
|
this.suspendable = val
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,10 +122,13 @@
|
||||||
v-if="!noHeading"
|
v-if="!noHeading"
|
||||||
class="left-side"
|
class="left-side"
|
||||||
>
|
>
|
||||||
<a :href="$router.resolve(userProfileLink).href" @click.prevent>
|
<a
|
||||||
|
:href="$router.resolve(userProfileLink).href"
|
||||||
|
@click.prevent
|
||||||
|
>
|
||||||
<UserPopover
|
<UserPopover
|
||||||
:userId="status.user.id"
|
:user-id="status.user.id"
|
||||||
:overlayCenters="true"
|
:overlay-centers="true"
|
||||||
>
|
>
|
||||||
<UserAvatar
|
<UserAvatar
|
||||||
class="post-avatar"
|
class="post-avatar"
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
<template>
|
<template>
|
||||||
<Popover
|
<Popover
|
||||||
|
ref="popover"
|
||||||
trigger="hover"
|
trigger="hover"
|
||||||
:stay-on-click="true"
|
:stay-on-click="true"
|
||||||
popover-class="popover-default status-popover"
|
popover-class="popover-default status-popover"
|
||||||
:bound-to="{ x: 'container' }"
|
:bound-to="{ x: 'container' }"
|
||||||
@show="enter"
|
@show="enter"
|
||||||
ref="popover"
|
|
||||||
>
|
>
|
||||||
<template v-slot:trigger>
|
<template #trigger>
|
||||||
<slot />
|
<slot />
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:content>
|
<template #content>
|
||||||
<Status
|
<Status
|
||||||
v-if="status"
|
v-if="status"
|
||||||
:is-preview="true"
|
:is-preview="true"
|
||||||
|
|
|
@ -31,8 +31,8 @@ const StickerPicker = {
|
||||||
fetch(sticker)
|
fetch(sticker)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
res.blob().then((blob) => {
|
res.blob().then((blob) => {
|
||||||
var file = new File([blob], name, { mimetype: 'image/png' })
|
const file = new File([blob], name, { mimetype: 'image/png' })
|
||||||
var formData = new FormData()
|
const formData = new FormData()
|
||||||
formData.append('file', file)
|
formData.append('file', file)
|
||||||
statusPosterService.uploadMedia({ store, formData })
|
statusPosterService.uploadMedia({ store, formData })
|
||||||
.then((fileData) => {
|
.then((fileData) => {
|
||||||
|
|
|
@ -46,7 +46,10 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div :class="classes.footer">
|
<div :class="classes.footer">
|
||||||
<teleport :to="footerSlipgate" :disabled="!embedded || !footerSlipgate">
|
<teleport
|
||||||
|
:to="footerSlipgate"
|
||||||
|
:disabled="!embedded || !footerSlipgate"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
v-if="count===0"
|
v-if="count===0"
|
||||||
class="new-status-notification text-center faint"
|
class="new-status-notification text-center faint"
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
class="TimelineQuickSettings"
|
class="TimelineQuickSettings"
|
||||||
:bound-to="{ x: 'container' }"
|
:bound-to="{ x: 'container' }"
|
||||||
>
|
>
|
||||||
<template v-slot:content>
|
<template #content>
|
||||||
<div class="dropdown-menu">
|
<div class="dropdown-menu">
|
||||||
<div v-if="loggedIn">
|
<div v-if="loggedIn">
|
||||||
<button
|
<button
|
||||||
|
@ -80,7 +80,7 @@
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:trigger>
|
<template #trigger>
|
||||||
<button class="button-unstyled">
|
<button class="button-unstyled">
|
||||||
<FAIcon icon="filter" />
|
<FAIcon icon="filter" />
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -11,9 +11,9 @@ library.add(faChevronDown)
|
||||||
// because nav panel benefits from the same information.
|
// because nav panel benefits from the same information.
|
||||||
export const timelineNames = () => {
|
export const timelineNames = () => {
|
||||||
return {
|
return {
|
||||||
'friends': 'nav.home_timeline',
|
friends: 'nav.home_timeline',
|
||||||
'bookmarks': 'nav.bookmarks',
|
bookmarks: 'nav.bookmarks',
|
||||||
'dms': 'nav.dms',
|
dms: 'nav.dms',
|
||||||
'public-timeline': 'nav.public_tl',
|
'public-timeline': 'nav.public_tl',
|
||||||
'public-external-timeline': 'nav.twkn'
|
'public-external-timeline': 'nav.twkn'
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,10 +9,10 @@
|
||||||
@show="openMenu"
|
@show="openMenu"
|
||||||
@close="() => isOpen = false"
|
@close="() => isOpen = false"
|
||||||
>
|
>
|
||||||
<template v-slot:content>
|
<template #content>
|
||||||
<TimelineMenuContent />
|
<TimelineMenuContent />
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:trigger>
|
<template #trigger>
|
||||||
<span class="button-unstyled title timeline-menu-title">
|
<span class="button-unstyled title timeline-menu-title">
|
||||||
<span class="timeline-title">{{ timelineName() }}</span>
|
<span class="timeline-title">{{ timelineName() }}</span>
|
||||||
<span>
|
<span>
|
||||||
|
|
|
@ -67,7 +67,7 @@ export default {
|
||||||
style () {
|
style () {
|
||||||
return {
|
return {
|
||||||
backgroundImage: [
|
backgroundImage: [
|
||||||
`linear-gradient(to bottom, var(--profileTint), var(--profileTint))`,
|
'linear-gradient(to bottom, var(--profileTint), var(--profileTint))',
|
||||||
`url(${this.user.cover_photo})`
|
`url(${this.user.cover_photo})`
|
||||||
].join(', ')
|
].join(', ')
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,10 +29,10 @@
|
||||||
</a>
|
</a>
|
||||||
<UserAvatar
|
<UserAvatar
|
||||||
v-else-if="typeof avatarAction === 'function'"
|
v-else-if="typeof avatarAction === 'function'"
|
||||||
@click="avatarAction"
|
|
||||||
class="user-info-avatar"
|
class="user-info-avatar"
|
||||||
:better-shadow="betterShadow"
|
:better-shadow="betterShadow"
|
||||||
:user="user"
|
:user="user"
|
||||||
|
@click="avatarAction"
|
||||||
/>
|
/>
|
||||||
<router-link
|
<router-link
|
||||||
v-else
|
v-else
|
||||||
|
|
|
@ -4,10 +4,10 @@
|
||||||
placement="top"
|
placement="top"
|
||||||
:offset="{ y: 5 }"
|
:offset="{ y: 5 }"
|
||||||
>
|
>
|
||||||
<template v-slot:trigger>
|
<template #trigger>
|
||||||
<slot />
|
<slot />
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:content>
|
<template #content>
|
||||||
<div class="user-list-popover">
|
<div class="user-list-popover">
|
||||||
<template v-if="users.length">
|
<template v-if="users.length">
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -6,10 +6,10 @@
|
||||||
:overlay-centers="overlayCenters && userPopoverOverlay"
|
:overlay-centers="overlayCenters && userPopoverOverlay"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
>
|
>
|
||||||
<template v-slot:trigger>
|
<template #trigger>
|
||||||
<slot />
|
<slot />
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:content={close}>
|
<template #content="{close}">
|
||||||
<UserCard
|
<UserCard
|
||||||
class="user-popover"
|
class="user-popover"
|
||||||
:user-id="userId"
|
:user-id="userId"
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
:user-id="userId"
|
:user-id="userId"
|
||||||
:pinned-status-ids="user.pinnedStatusIds"
|
:pinned-status-ids="user.pinnedStatusIds"
|
||||||
:in-profile="true"
|
:in-profile="true"
|
||||||
:footerSlipgate="footerRef"
|
:footer-slipgate="footerRef"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
v-if="followsTabVisible"
|
v-if="followsTabVisible"
|
||||||
|
@ -65,7 +65,7 @@
|
||||||
:disabled="!user.friends_count"
|
:disabled="!user.friends_count"
|
||||||
>
|
>
|
||||||
<FriendList :user-id="userId">
|
<FriendList :user-id="userId">
|
||||||
<template v-slot:item="{item}">
|
<template #item="{item}">
|
||||||
<FollowCard :user="item" />
|
<FollowCard :user="item" />
|
||||||
</template>
|
</template>
|
||||||
</FriendList>
|
</FriendList>
|
||||||
|
@ -77,7 +77,7 @@
|
||||||
:disabled="!user.followers_count"
|
:disabled="!user.followers_count"
|
||||||
>
|
>
|
||||||
<FollowerList :user-id="userId">
|
<FollowerList :user-id="userId">
|
||||||
<template v-slot:item="{item}">
|
<template #item="{item}">
|
||||||
<FollowCard
|
<FollowCard
|
||||||
:user="item"
|
:user="item"
|
||||||
:no-follows-you="isUs"
|
:no-follows-you="isUs"
|
||||||
|
@ -95,7 +95,7 @@
|
||||||
:timeline="media"
|
:timeline="media"
|
||||||
:user-id="userId"
|
:user-id="userId"
|
||||||
:in-profile="true"
|
:in-profile="true"
|
||||||
:footerSlipgate="footerRef"
|
:footer-slipgate="footerRef"
|
||||||
/>
|
/>
|
||||||
<Timeline
|
<Timeline
|
||||||
v-if="isUs"
|
v-if="isUs"
|
||||||
|
@ -107,10 +107,13 @@
|
||||||
timeline-name="favorites"
|
timeline-name="favorites"
|
||||||
:timeline="favorites"
|
:timeline="favorites"
|
||||||
:in-profile="true"
|
:in-profile="true"
|
||||||
:footerSlipgate="footerRef"
|
:footer-slipgate="footerRef"
|
||||||
/>
|
/>
|
||||||
</tab-switcher>
|
</tab-switcher>
|
||||||
<div class="panel-footer" :ref="setFooterRef"></div>
|
<div
|
||||||
|
:ref="setFooterRef"
|
||||||
|
class="panel-footer"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-else
|
v-else
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="user-reporting-panel-right">
|
<div class="user-reporting-panel-right">
|
||||||
<List :items="statuses">
|
<List :items="statuses">
|
||||||
<template v-slot:item="{item}">
|
<template #item="{item}">
|
||||||
<div class="status-fadein user-reporting-panel-sitem">
|
<div class="status-fadein user-reporting-panel-sitem">
|
||||||
<Status
|
<Status
|
||||||
:in-conversation="false"
|
:in-conversation="false"
|
||||||
|
|
|
@ -28,7 +28,7 @@ const WhoToFollow = {
|
||||||
getWhoToFollow () {
|
getWhoToFollow () {
|
||||||
const credentials = this.$store.state.users.currentUser.credentials
|
const credentials = this.$store.state.users.currentUser.credentials
|
||||||
if (credentials) {
|
if (credentials) {
|
||||||
apiService.suggestions({ credentials: credentials })
|
apiService.suggestions({ credentials })
|
||||||
.then((reply) => {
|
.then((reply) => {
|
||||||
this.showWhoToFollow(reply)
|
this.showWhoToFollow(reply)
|
||||||
})
|
})
|
||||||
|
|
|
@ -6,9 +6,9 @@ function showWhoToFollow (panel, reply) {
|
||||||
const shuffled = shuffle(reply)
|
const shuffled = shuffle(reply)
|
||||||
|
|
||||||
panel.usersToFollow.forEach((toFollow, index) => {
|
panel.usersToFollow.forEach((toFollow, index) => {
|
||||||
let user = shuffled[index]
|
const user = shuffled[index]
|
||||||
let img = user.avatar || this.$store.state.instance.defaultAvatar
|
const img = user.avatar || this.$store.state.instance.defaultAvatar
|
||||||
let name = user.acct
|
const name = user.acct
|
||||||
|
|
||||||
toFollow.img = img
|
toFollow.img = img
|
||||||
toFollow.name = name
|
toFollow.name = name
|
||||||
|
@ -24,12 +24,12 @@ function showWhoToFollow (panel, reply) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getWhoToFollow (panel) {
|
function getWhoToFollow (panel) {
|
||||||
var credentials = panel.$store.state.users.currentUser.credentials
|
const credentials = panel.$store.state.users.currentUser.credentials
|
||||||
if (credentials) {
|
if (credentials) {
|
||||||
panel.usersToFollow.forEach(toFollow => {
|
panel.usersToFollow.forEach(toFollow => {
|
||||||
toFollow.name = 'Loading...'
|
toFollow.name = 'Loading...'
|
||||||
})
|
})
|
||||||
apiService.suggestions({ credentials: credentials })
|
apiService.suggestions({ credentials })
|
||||||
.then((reply) => {
|
.then((reply) => {
|
||||||
showWhoToFollow(panel, reply)
|
showWhoToFollow(panel, reply)
|
||||||
})
|
})
|
||||||
|
|
|
@ -46,7 +46,7 @@ const messages = {
|
||||||
},
|
},
|
||||||
setLanguage: async (i18n, language) => {
|
setLanguage: async (i18n, language) => {
|
||||||
if (loaders[language]) {
|
if (loaders[language]) {
|
||||||
let messages = await loaders[language]()
|
const messages = await loaders[language]()
|
||||||
i18n.setLocaleMessage(language, messages.default)
|
i18n.setLocaleMessage(language, messages.default)
|
||||||
}
|
}
|
||||||
i18n.locale = language
|
i18n.locale = language
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
// meant to be used to load the partial i18n we need for
|
// meant to be used to load the partial i18n we need for
|
||||||
// the service worker.
|
// the service worker.
|
||||||
module.exports = function (source) {
|
module.exports = function (source) {
|
||||||
var object = JSON.parse(source)
|
const object = JSON.parse(source)
|
||||||
var smol = {
|
const smol = {
|
||||||
notifications: object.notifications || {}
|
notifications: object.notifications || {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,9 @@ import { each, get, set, cloneDeep } from 'lodash'
|
||||||
let loaded = false
|
let loaded = false
|
||||||
|
|
||||||
const defaultReducer = (state, paths) => (
|
const defaultReducer = (state, paths) => (
|
||||||
paths.length === 0 ? state : paths.reduce((substate, path) => {
|
paths.length === 0
|
||||||
|
? state
|
||||||
|
: paths.reduce((substate, path) => {
|
||||||
set(substate, path, get(state, path))
|
set(substate, path, get(state, path))
|
||||||
return substate
|
return substate
|
||||||
}, {})
|
}, {})
|
||||||
|
@ -30,7 +32,7 @@ export default function createPersistedState ({
|
||||||
key = 'vuex-lz',
|
key = 'vuex-lz',
|
||||||
paths = [],
|
paths = [],
|
||||||
getState = (key, storage) => {
|
getState = (key, storage) => {
|
||||||
let value = storage.getItem(key)
|
const value = storage.getItem(key)
|
||||||
return value
|
return value
|
||||||
},
|
},
|
||||||
setState = (key, state, storage) => {
|
setState = (key, state, storage) => {
|
||||||
|
|
|
@ -233,7 +233,7 @@ const api = {
|
||||||
|
|
||||||
// Follow requests
|
// Follow requests
|
||||||
startFetchingFollowRequests (store) {
|
startFetchingFollowRequests (store) {
|
||||||
if (store.state.fetchers['followRequests']) return
|
if (store.state.fetchers.followRequests) return
|
||||||
const fetcher = store.state.backendInteractor.startFetchingFollowRequests({ store })
|
const fetcher = store.state.backendInteractor.startFetchingFollowRequests({ store })
|
||||||
|
|
||||||
store.commit('addFetcher', { fetcherName: 'followRequests', fetcher })
|
store.commit('addFetcher', { fetcherName: 'followRequests', fetcher })
|
||||||
|
@ -244,7 +244,7 @@ const api = {
|
||||||
store.commit('removeFetcher', { fetcherName: 'followRequests', fetcher })
|
store.commit('removeFetcher', { fetcherName: 'followRequests', fetcher })
|
||||||
},
|
},
|
||||||
removeFollowRequest (store, request) {
|
removeFollowRequest (store, request) {
|
||||||
let requests = store.state.followRequests.filter((it) => it !== request)
|
const requests = store.state.followRequests.filter((it) => it !== request)
|
||||||
store.commit('setFollowRequests', requests)
|
store.commit('setFollowRequests', requests)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -147,7 +147,7 @@ const config = {
|
||||||
const knownKeys = new Set(Object.keys(defaultState))
|
const knownKeys = new Set(Object.keys(defaultState))
|
||||||
const presentKeys = new Set(Object.keys(data))
|
const presentKeys = new Set(Object.keys(data))
|
||||||
const intersection = new Set()
|
const intersection = new Set()
|
||||||
for (let elem of presentKeys) {
|
for (const elem of presentKeys) {
|
||||||
if (knownKeys.has(elem)) {
|
if (knownKeys.has(elem)) {
|
||||||
intersection.add(elem)
|
intersection.add(elem)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@ import { capitalize } from 'lodash'
|
||||||
|
|
||||||
export function humanizeErrors (errors) {
|
export function humanizeErrors (errors) {
|
||||||
return Object.entries(errors).reduce((errs, [k, val]) => {
|
return Object.entries(errors).reduce((errs, [k, val]) => {
|
||||||
let message = val.reduce((acc, message) => {
|
const message = val.reduce((acc, message) => {
|
||||||
let key = capitalize(k.replace(/_/g, ' '))
|
const key = capitalize(k.replace(/_/g, ' '))
|
||||||
return acc + [key, message].join(' ') + '. '
|
return acc + [key, message].join(' ') + '. '
|
||||||
}, '')
|
}, '')
|
||||||
return [...errs, message]
|
return [...errs, message]
|
||||||
|
|
|
@ -39,53 +39,53 @@ const notificationsApi = ({ rootState, commit }, { path, value, oldValue }) => {
|
||||||
* If no api is specified, defaultApi is used (see above)
|
* If no api is specified, defaultApi is used (see above)
|
||||||
*/
|
*/
|
||||||
export const settingsMap = {
|
export const settingsMap = {
|
||||||
'defaultScope': 'source.privacy',
|
defaultScope: 'source.privacy',
|
||||||
'defaultNSFW': 'source.sensitive', // BROKEN: pleroma/pleroma#2837
|
defaultNSFW: 'source.sensitive', // BROKEN: pleroma/pleroma#2837
|
||||||
'stripRichContent': {
|
stripRichContent: {
|
||||||
get: 'source.pleroma.no_rich_text',
|
get: 'source.pleroma.no_rich_text',
|
||||||
set: 'no_rich_text'
|
set: 'no_rich_text'
|
||||||
},
|
},
|
||||||
// Privacy
|
// Privacy
|
||||||
'locked': 'locked',
|
locked: 'locked',
|
||||||
'acceptChatMessages': {
|
acceptChatMessages: {
|
||||||
get: 'pleroma.accepts_chat_messages',
|
get: 'pleroma.accepts_chat_messages',
|
||||||
set: 'accepts_chat_messages'
|
set: 'accepts_chat_messages'
|
||||||
},
|
},
|
||||||
'allowFollowingMove': {
|
allowFollowingMove: {
|
||||||
get: 'pleroma.allow_following_move',
|
get: 'pleroma.allow_following_move',
|
||||||
set: 'allow_following_move'
|
set: 'allow_following_move'
|
||||||
},
|
},
|
||||||
'discoverable': {
|
discoverable: {
|
||||||
get: 'source.pleroma.discoverable',
|
get: 'source.pleroma.discoverable',
|
||||||
set: 'discoverable'
|
set: 'discoverable'
|
||||||
},
|
},
|
||||||
'hideFavorites': {
|
hideFavorites: {
|
||||||
get: 'pleroma.hide_favorites',
|
get: 'pleroma.hide_favorites',
|
||||||
set: 'hide_favorites'
|
set: 'hide_favorites'
|
||||||
},
|
},
|
||||||
'hideFollowers': {
|
hideFollowers: {
|
||||||
get: 'pleroma.hide_followers',
|
get: 'pleroma.hide_followers',
|
||||||
set: 'hide_followers'
|
set: 'hide_followers'
|
||||||
},
|
},
|
||||||
'hideFollows': {
|
hideFollows: {
|
||||||
get: 'pleroma.hide_follows',
|
get: 'pleroma.hide_follows',
|
||||||
set: 'hide_follows'
|
set: 'hide_follows'
|
||||||
},
|
},
|
||||||
'hideFollowersCount': {
|
hideFollowersCount: {
|
||||||
get: 'pleroma.hide_followers_count',
|
get: 'pleroma.hide_followers_count',
|
||||||
set: 'hide_followers_count'
|
set: 'hide_followers_count'
|
||||||
},
|
},
|
||||||
'hideFollowsCount': {
|
hideFollowsCount: {
|
||||||
get: 'pleroma.hide_follows_count',
|
get: 'pleroma.hide_follows_count',
|
||||||
set: 'hide_follows_count'
|
set: 'hide_follows_count'
|
||||||
},
|
},
|
||||||
// NotificationSettingsAPIs
|
// NotificationSettingsAPIs
|
||||||
'webPushHideContents': {
|
webPushHideContents: {
|
||||||
get: 'pleroma.notification_settings.hide_notification_contents',
|
get: 'pleroma.notification_settings.hide_notification_contents',
|
||||||
set: 'hide_notification_contents',
|
set: 'hide_notification_contents',
|
||||||
api: notificationsApi
|
api: notificationsApi
|
||||||
},
|
},
|
||||||
'blockNotificationsFromStrangers': {
|
blockNotificationsFromStrangers: {
|
||||||
get: 'pleroma.notification_settings.block_from_strangers',
|
get: 'pleroma.notification_settings.block_from_strangers',
|
||||||
set: 'block_from_strangers',
|
set: 'block_from_strangers',
|
||||||
api: notificationsApi
|
api: notificationsApi
|
||||||
|
|
|
@ -245,10 +245,10 @@ const addNewStatuses = (state, { statuses, showImmediately = false, timeline, us
|
||||||
}
|
}
|
||||||
|
|
||||||
const processors = {
|
const processors = {
|
||||||
'status': (status) => {
|
status: (status) => {
|
||||||
addStatus(status, showImmediately)
|
addStatus(status, showImmediately)
|
||||||
},
|
},
|
||||||
'retweet': (status) => {
|
retweet: (status) => {
|
||||||
// RetweetedStatuses are never shown immediately
|
// RetweetedStatuses are never shown immediately
|
||||||
const retweetedStatus = addStatus(status.retweeted_status, false, false)
|
const retweetedStatus = addStatus(status.retweeted_status, false, false)
|
||||||
|
|
||||||
|
@ -270,7 +270,7 @@ const addNewStatuses = (state, { statuses, showImmediately = false, timeline, us
|
||||||
|
|
||||||
retweet.retweeted_status = retweetedStatus
|
retweet.retweeted_status = retweetedStatus
|
||||||
},
|
},
|
||||||
'favorite': (favorite) => {
|
favorite: (favorite) => {
|
||||||
// Only update if this is a new favorite.
|
// Only update if this is a new favorite.
|
||||||
// Ignore our own favorites because we get info about likes as response to like request
|
// Ignore our own favorites because we get info about likes as response to like request
|
||||||
if (!state.favorites.has(favorite.id)) {
|
if (!state.favorites.has(favorite.id)) {
|
||||||
|
@ -278,7 +278,7 @@ const addNewStatuses = (state, { statuses, showImmediately = false, timeline, us
|
||||||
favoriteStatus(favorite)
|
favoriteStatus(favorite)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'deletion': (deletion) => {
|
deletion: (deletion) => {
|
||||||
const uri = deletion.uri
|
const uri = deletion.uri
|
||||||
const status = find(allStatuses, { uri })
|
const status = find(allStatuses, { uri })
|
||||||
if (!status) {
|
if (!status) {
|
||||||
|
@ -292,10 +292,10 @@ const addNewStatuses = (state, { statuses, showImmediately = false, timeline, us
|
||||||
remove(timelineObject.visibleStatuses, { uri })
|
remove(timelineObject.visibleStatuses, { uri })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'follow': (follow) => {
|
follow: (follow) => {
|
||||||
// NOOP, it is known status but we don't do anything about it for now
|
// NOOP, it is known status but we don't do anything about it for now
|
||||||
},
|
},
|
||||||
'default': (unknown) => {
|
default: (unknown) => {
|
||||||
console.log('unknown status type')
|
console.log('unknown status type')
|
||||||
console.log(unknown)
|
console.log(unknown)
|
||||||
}
|
}
|
||||||
|
@ -303,7 +303,7 @@ const addNewStatuses = (state, { statuses, showImmediately = false, timeline, us
|
||||||
|
|
||||||
each(statuses, (status) => {
|
each(statuses, (status) => {
|
||||||
const type = status.type
|
const type = status.type
|
||||||
const processor = processors[type] || processors['default']
|
const processor = processors[type] || processors.default
|
||||||
processor(status)
|
processor(status)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -522,7 +522,7 @@ export const mutations = {
|
||||||
},
|
},
|
||||||
addEmojiReactionsBy (state, { id, emojiReactions, currentUser }) {
|
addEmojiReactionsBy (state, { id, emojiReactions, currentUser }) {
|
||||||
const status = state.allStatusesObject[id]
|
const status = state.allStatusesObject[id]
|
||||||
status['emoji_reactions'] = emojiReactions
|
status.emoji_reactions = emojiReactions
|
||||||
},
|
},
|
||||||
addOwnReaction (state, { id, emoji, currentUser }) {
|
addOwnReaction (state, { id, emoji, currentUser }) {
|
||||||
const status = state.allStatusesObject[id]
|
const status = state.allStatusesObject[id]
|
||||||
|
@ -543,7 +543,7 @@ export const mutations = {
|
||||||
if (reactionIndex >= 0) {
|
if (reactionIndex >= 0) {
|
||||||
status.emoji_reactions[reactionIndex] = newReaction
|
status.emoji_reactions[reactionIndex] = newReaction
|
||||||
} else {
|
} else {
|
||||||
status['emoji_reactions'] = [...status.emoji_reactions, newReaction]
|
status.emoji_reactions = [...status.emoji_reactions, newReaction]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
removeOwnReaction (state, { id, emoji, currentUser }) {
|
removeOwnReaction (state, { id, emoji, currentUser }) {
|
||||||
|
@ -564,7 +564,7 @@ export const mutations = {
|
||||||
if (newReaction.count > 0) {
|
if (newReaction.count > 0) {
|
||||||
status.emoji_reactions[reactionIndex] = newReaction
|
status.emoji_reactions[reactionIndex] = newReaction
|
||||||
} else {
|
} else {
|
||||||
status['emoji_reactions'] = status.emoji_reactions.filter(r => r.name !== emoji)
|
status.emoji_reactions = status.emoji_reactions.filter(r => r.name !== emoji)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
updateStatusWithPoll (state, { id, poll }) {
|
updateStatusWithPoll (state, { id, poll }) {
|
||||||
|
|
|
@ -103,23 +103,23 @@ export const mutations = {
|
||||||
const user = state.usersObject[id]
|
const user = state.usersObject[id]
|
||||||
const tags = user.tags || []
|
const tags = user.tags || []
|
||||||
const newTags = tags.concat([tag])
|
const newTags = tags.concat([tag])
|
||||||
user['tags'] = newTags
|
user.tags = newTags
|
||||||
},
|
},
|
||||||
untagUser (state, { user: { id }, tag }) {
|
untagUser (state, { user: { id }, tag }) {
|
||||||
const user = state.usersObject[id]
|
const user = state.usersObject[id]
|
||||||
const tags = user.tags || []
|
const tags = user.tags || []
|
||||||
const newTags = tags.filter(t => t !== tag)
|
const newTags = tags.filter(t => t !== tag)
|
||||||
user['tags'] = newTags
|
user.tags = newTags
|
||||||
},
|
},
|
||||||
updateRight (state, { user: { id }, right, value }) {
|
updateRight (state, { user: { id }, right, value }) {
|
||||||
const user = state.usersObject[id]
|
const user = state.usersObject[id]
|
||||||
let newRights = user.rights
|
const newRights = user.rights
|
||||||
newRights[right] = value
|
newRights[right] = value
|
||||||
user['rights'] = newRights
|
user.rights = newRights
|
||||||
},
|
},
|
||||||
updateActivationStatus (state, { user: { id }, deactivated }) {
|
updateActivationStatus (state, { user: { id }, deactivated }) {
|
||||||
const user = state.usersObject[id]
|
const user = state.usersObject[id]
|
||||||
user['deactivated'] = deactivated
|
user.deactivated = deactivated
|
||||||
},
|
},
|
||||||
setCurrentUser (state, user) {
|
setCurrentUser (state, user) {
|
||||||
state.lastLoginName = user.screen_name
|
state.lastLoginName = user.screen_name
|
||||||
|
@ -148,13 +148,13 @@ export const mutations = {
|
||||||
clearFriends (state, userId) {
|
clearFriends (state, userId) {
|
||||||
const user = state.usersObject[userId]
|
const user = state.usersObject[userId]
|
||||||
if (user) {
|
if (user) {
|
||||||
user['friendIds'] = []
|
user.friendIds = []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
clearFollowers (state, userId) {
|
clearFollowers (state, userId) {
|
||||||
const user = state.usersObject[userId]
|
const user = state.usersObject[userId]
|
||||||
if (user) {
|
if (user) {
|
||||||
user['followerIds'] = []
|
user.followerIds = []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
addNewUsers (state, users) {
|
addNewUsers (state, users) {
|
||||||
|
@ -222,7 +222,7 @@ export const mutations = {
|
||||||
},
|
},
|
||||||
setColor (state, { user: { id }, highlighted }) {
|
setColor (state, { user: { id }, highlighted }) {
|
||||||
const user = state.usersObject[id]
|
const user = state.usersObject[id]
|
||||||
user['highlight'] = highlighted
|
user.highlight = highlighted
|
||||||
},
|
},
|
||||||
signUpPending (state) {
|
signUpPending (state) {
|
||||||
state.signUpPending = true
|
state.signUpPending = true
|
||||||
|
@ -393,7 +393,7 @@ const users = {
|
||||||
toggleActivationStatus ({ rootState, commit }, { user }) {
|
toggleActivationStatus ({ rootState, commit }, { user }) {
|
||||||
const api = user.deactivated ? rootState.api.backendInteractor.activateUser : rootState.api.backendInteractor.deactivateUser
|
const api = user.deactivated ? rootState.api.backendInteractor.activateUser : rootState.api.backendInteractor.deactivateUser
|
||||||
api({ user })
|
api({ user })
|
||||||
.then((user) => { let deactivated = !user.is_active; commit('updateActivationStatus', { user, deactivated }) })
|
.then((user) => { const deactivated = !user.is_active; commit('updateActivationStatus', { user, deactivated }) })
|
||||||
},
|
},
|
||||||
registerPushNotifications (store) {
|
registerPushNotifications (store) {
|
||||||
const token = store.state.currentUser.credentials
|
const token = store.state.currentUser.credentials
|
||||||
|
@ -457,17 +457,17 @@ const users = {
|
||||||
async signUp (store, userInfo) {
|
async signUp (store, userInfo) {
|
||||||
store.commit('signUpPending')
|
store.commit('signUpPending')
|
||||||
|
|
||||||
let rootState = store.rootState
|
const rootState = store.rootState
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let data = await rootState.api.backendInteractor.register(
|
const data = await rootState.api.backendInteractor.register(
|
||||||
{ params: { ...userInfo } }
|
{ params: { ...userInfo } }
|
||||||
)
|
)
|
||||||
store.commit('signUpSuccess')
|
store.commit('signUpSuccess')
|
||||||
store.commit('setToken', data.access_token)
|
store.commit('setToken', data.access_token)
|
||||||
store.dispatch('loginUser', data.access_token)
|
store.dispatch('loginUser', data.access_token)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
let errors = e.message
|
const errors = e.message
|
||||||
store.commit('signUpFailure', errors)
|
store.commit('signUpFailure', errors)
|
||||||
throw e
|
throw e
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,7 @@ const MASTODON_PIN_OWN_STATUS = id => `/api/v1/statuses/${id}/pin`
|
||||||
const MASTODON_UNPIN_OWN_STATUS = id => `/api/v1/statuses/${id}/unpin`
|
const MASTODON_UNPIN_OWN_STATUS = id => `/api/v1/statuses/${id}/unpin`
|
||||||
const MASTODON_MUTE_CONVERSATION = id => `/api/v1/statuses/${id}/mute`
|
const MASTODON_MUTE_CONVERSATION = id => `/api/v1/statuses/${id}/mute`
|
||||||
const MASTODON_UNMUTE_CONVERSATION = id => `/api/v1/statuses/${id}/unmute`
|
const MASTODON_UNMUTE_CONVERSATION = id => `/api/v1/statuses/${id}/unmute`
|
||||||
const MASTODON_SEARCH_2 = `/api/v2/search`
|
const MASTODON_SEARCH_2 = '/api/v2/search'
|
||||||
const MASTODON_USER_SEARCH_URL = '/api/v1/accounts/search'
|
const MASTODON_USER_SEARCH_URL = '/api/v1/accounts/search'
|
||||||
const MASTODON_DOMAIN_BLOCKS_URL = '/api/v1/domain_blocks'
|
const MASTODON_DOMAIN_BLOCKS_URL = '/api/v1/domain_blocks'
|
||||||
const MASTODON_STREAMING = '/api/v1/streaming'
|
const MASTODON_STREAMING = '/api/v1/streaming'
|
||||||
|
@ -84,7 +84,7 @@ const MASTODON_KNOWN_DOMAIN_LIST_URL = '/api/v1/instance/peers'
|
||||||
const PLEROMA_EMOJI_REACTIONS_URL = id => `/api/v1/pleroma/statuses/${id}/reactions`
|
const PLEROMA_EMOJI_REACTIONS_URL = id => `/api/v1/pleroma/statuses/${id}/reactions`
|
||||||
const PLEROMA_EMOJI_REACT_URL = (id, emoji) => `/api/v1/pleroma/statuses/${id}/reactions/${emoji}`
|
const PLEROMA_EMOJI_REACT_URL = (id, emoji) => `/api/v1/pleroma/statuses/${id}/reactions/${emoji}`
|
||||||
const PLEROMA_EMOJI_UNREACT_URL = (id, emoji) => `/api/v1/pleroma/statuses/${id}/reactions/${emoji}`
|
const PLEROMA_EMOJI_UNREACT_URL = (id, emoji) => `/api/v1/pleroma/statuses/${id}/reactions/${emoji}`
|
||||||
const PLEROMA_CHATS_URL = `/api/v1/pleroma/chats`
|
const PLEROMA_CHATS_URL = '/api/v1/pleroma/chats'
|
||||||
const PLEROMA_CHAT_URL = id => `/api/v1/pleroma/chats/by-account-id/${id}`
|
const PLEROMA_CHAT_URL = id => `/api/v1/pleroma/chats/by-account-id/${id}`
|
||||||
const PLEROMA_CHAT_MESSAGES_URL = id => `/api/v1/pleroma/chats/${id}/messages`
|
const PLEROMA_CHAT_MESSAGES_URL = id => `/api/v1/pleroma/chats/${id}/messages`
|
||||||
const PLEROMA_CHAT_READ_URL = id => `/api/v1/pleroma/chats/${id}/read`
|
const PLEROMA_CHAT_READ_URL = id => `/api/v1/pleroma/chats/${id}/read`
|
||||||
|
@ -93,7 +93,7 @@ const PLEROMA_BACKUP_URL = '/api/v1/pleroma/backups'
|
||||||
|
|
||||||
const oldfetch = window.fetch
|
const oldfetch = window.fetch
|
||||||
|
|
||||||
let fetch = (url, options) => {
|
const fetch = (url, options) => {
|
||||||
options = options || {}
|
options = options || {}
|
||||||
const baseUrl = ''
|
const baseUrl = ''
|
||||||
const fullUrl = baseUrl + url
|
const fullUrl = baseUrl + url
|
||||||
|
@ -105,7 +105,7 @@ const promisedRequest = ({ method, url, params, payload, credentials, headers =
|
||||||
const options = {
|
const options = {
|
||||||
method,
|
method,
|
||||||
headers: {
|
headers: {
|
||||||
'Accept': 'application/json',
|
Accept: 'application/json',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
...headers
|
...headers
|
||||||
}
|
}
|
||||||
|
@ -229,16 +229,16 @@ const getCaptcha = () => fetch('/api/pleroma/captcha').then(resp => resp.json())
|
||||||
|
|
||||||
const authHeaders = (accessToken) => {
|
const authHeaders = (accessToken) => {
|
||||||
if (accessToken) {
|
if (accessToken) {
|
||||||
return { 'Authorization': `Bearer ${accessToken}` }
|
return { Authorization: `Bearer ${accessToken}` }
|
||||||
} else {
|
} else {
|
||||||
return { }
|
return { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const followUser = ({ id, credentials, ...options }) => {
|
const followUser = ({ id, credentials, ...options }) => {
|
||||||
let url = MASTODON_FOLLOW_URL(id)
|
const url = MASTODON_FOLLOW_URL(id)
|
||||||
const form = {}
|
const form = {}
|
||||||
if (options.reblogs !== undefined) { form['reblogs'] = options.reblogs }
|
if (options.reblogs !== undefined) { form.reblogs = options.reblogs }
|
||||||
return fetch(url, {
|
return fetch(url, {
|
||||||
body: JSON.stringify(form),
|
body: JSON.stringify(form),
|
||||||
headers: {
|
headers: {
|
||||||
|
@ -250,7 +250,7 @@ const followUser = ({ id, credentials, ...options }) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const unfollowUser = ({ id, credentials }) => {
|
const unfollowUser = ({ id, credentials }) => {
|
||||||
let url = MASTODON_UNFOLLOW_URL(id)
|
const url = MASTODON_UNFOLLOW_URL(id)
|
||||||
return fetch(url, {
|
return fetch(url, {
|
||||||
headers: authHeaders(credentials),
|
headers: authHeaders(credentials),
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
|
@ -292,7 +292,7 @@ const unblockUser = ({ id, credentials }) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const approveUser = ({ id, credentials }) => {
|
const approveUser = ({ id, credentials }) => {
|
||||||
let url = MASTODON_APPROVE_USER_URL(id)
|
const url = MASTODON_APPROVE_USER_URL(id)
|
||||||
return fetch(url, {
|
return fetch(url, {
|
||||||
headers: authHeaders(credentials),
|
headers: authHeaders(credentials),
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
|
@ -300,7 +300,7 @@ const approveUser = ({ id, credentials }) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const denyUser = ({ id, credentials }) => {
|
const denyUser = ({ id, credentials }) => {
|
||||||
let url = MASTODON_DENY_USER_URL(id)
|
const url = MASTODON_DENY_USER_URL(id)
|
||||||
return fetch(url, {
|
return fetch(url, {
|
||||||
headers: authHeaders(credentials),
|
headers: authHeaders(credentials),
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
|
@ -308,13 +308,13 @@ const denyUser = ({ id, credentials }) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const fetchUser = ({ id, credentials }) => {
|
const fetchUser = ({ id, credentials }) => {
|
||||||
let url = `${MASTODON_USER_URL}/${id}`
|
const url = `${MASTODON_USER_URL}/${id}`
|
||||||
return promisedRequest({ url, credentials })
|
return promisedRequest({ url, credentials })
|
||||||
.then((data) => parseUser(data))
|
.then((data) => parseUser(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
const fetchUserRelationship = ({ id, credentials }) => {
|
const fetchUserRelationship = ({ id, credentials }) => {
|
||||||
let url = `${MASTODON_USER_RELATIONSHIPS_URL}/?id=${id}`
|
const url = `${MASTODON_USER_RELATIONSHIPS_URL}/?id=${id}`
|
||||||
return fetch(url, { headers: authHeaders(credentials) })
|
return fetch(url, { headers: authHeaders(credentials) })
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
return new Promise((resolve, reject) => response.json()
|
return new Promise((resolve, reject) => response.json()
|
||||||
|
@ -333,7 +333,7 @@ const fetchFriends = ({ id, maxId, sinceId, limit = 20, credentials }) => {
|
||||||
maxId && `max_id=${maxId}`,
|
maxId && `max_id=${maxId}`,
|
||||||
sinceId && `since_id=${sinceId}`,
|
sinceId && `since_id=${sinceId}`,
|
||||||
limit && `limit=${limit}`,
|
limit && `limit=${limit}`,
|
||||||
`with_relationships=true`
|
'with_relationships=true'
|
||||||
].filter(_ => _).join('&')
|
].filter(_ => _).join('&')
|
||||||
|
|
||||||
url = url + (args ? '?' + args : '')
|
url = url + (args ? '?' + args : '')
|
||||||
|
@ -368,7 +368,7 @@ const fetchFollowers = ({ id, maxId, sinceId, limit = 20, credentials }) => {
|
||||||
maxId && `max_id=${maxId}`,
|
maxId && `max_id=${maxId}`,
|
||||||
sinceId && `since_id=${sinceId}`,
|
sinceId && `since_id=${sinceId}`,
|
||||||
limit && `limit=${limit}`,
|
limit && `limit=${limit}`,
|
||||||
`with_relationships=true`
|
'with_relationships=true'
|
||||||
].filter(_ => _).join('&')
|
].filter(_ => _).join('&')
|
||||||
|
|
||||||
url += args ? '?' + args : ''
|
url += args ? '?' + args : ''
|
||||||
|
@ -385,7 +385,7 @@ const fetchFollowRequests = ({ credentials }) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const fetchConversation = ({ id, credentials }) => {
|
const fetchConversation = ({ id, credentials }) => {
|
||||||
let urlContext = MASTODON_STATUS_CONTEXT_URL(id)
|
const urlContext = MASTODON_STATUS_CONTEXT_URL(id)
|
||||||
return fetch(urlContext, { headers: authHeaders(credentials) })
|
return fetch(urlContext, { headers: authHeaders(credentials) })
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (data.ok) {
|
if (data.ok) {
|
||||||
|
@ -401,7 +401,7 @@ const fetchConversation = ({ id, credentials }) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const fetchStatus = ({ id, credentials }) => {
|
const fetchStatus = ({ id, credentials }) => {
|
||||||
let url = MASTODON_STATUS_URL(id)
|
const url = MASTODON_STATUS_URL(id)
|
||||||
return fetch(url, { headers: authHeaders(credentials) })
|
return fetch(url, { headers: authHeaders(credentials) })
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (data.ok) {
|
if (data.ok) {
|
||||||
|
@ -425,7 +425,7 @@ const tagUser = ({ tag, credentials, user }) => {
|
||||||
|
|
||||||
return fetch(TAG_USER_URL, {
|
return fetch(TAG_USER_URL, {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
headers: headers,
|
headers,
|
||||||
body: JSON.stringify(form)
|
body: JSON.stringify(form)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -442,7 +442,7 @@ const untagUser = ({ tag, credentials, user }) => {
|
||||||
|
|
||||||
return fetch(TAG_USER_URL, {
|
return fetch(TAG_USER_URL, {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
headers: headers,
|
headers,
|
||||||
body: JSON.stringify(body)
|
body: JSON.stringify(body)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -495,7 +495,7 @@ const deleteUser = ({ credentials, user }) => {
|
||||||
|
|
||||||
return fetch(`${ADMIN_USERS_URL}?nickname=${screenName}`, {
|
return fetch(`${ADMIN_USERS_URL}?nickname=${screenName}`, {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
headers: headers
|
headers
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -514,7 +514,7 @@ const fetchTimeline = ({
|
||||||
friends: MASTODON_USER_HOME_TIMELINE_URL,
|
friends: MASTODON_USER_HOME_TIMELINE_URL,
|
||||||
dms: MASTODON_DIRECT_MESSAGES_TIMELINE_URL,
|
dms: MASTODON_DIRECT_MESSAGES_TIMELINE_URL,
|
||||||
notifications: MASTODON_USER_NOTIFICATIONS_URL,
|
notifications: MASTODON_USER_NOTIFICATIONS_URL,
|
||||||
'publicAndExternal': MASTODON_PUBLIC_TIMELINE,
|
publicAndExternal: MASTODON_PUBLIC_TIMELINE,
|
||||||
user: MASTODON_USER_TIMELINE_URL,
|
user: MASTODON_USER_TIMELINE_URL,
|
||||||
media: MASTODON_USER_TIMELINE_URL,
|
media: MASTODON_USER_TIMELINE_URL,
|
||||||
favorites: MASTODON_USER_FAVORITES_TIMELINE_URL,
|
favorites: MASTODON_USER_FAVORITES_TIMELINE_URL,
|
||||||
|
@ -688,7 +688,7 @@ const postStatus = ({
|
||||||
form.append('preview', 'true')
|
form.append('preview', 'true')
|
||||||
}
|
}
|
||||||
|
|
||||||
let postHeaders = authHeaders(credentials)
|
const postHeaders = authHeaders(credentials)
|
||||||
if (idempotencyKey) {
|
if (idempotencyKey) {
|
||||||
postHeaders['idempotency-key'] = idempotencyKey
|
postHeaders['idempotency-key'] = idempotencyKey
|
||||||
}
|
}
|
||||||
|
@ -993,7 +993,7 @@ const vote = ({ pollId, choices, credentials }) => {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
credentials,
|
credentials,
|
||||||
payload: {
|
payload: {
|
||||||
choices: choices
|
choices
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1053,8 +1053,8 @@ const reportUser = ({ credentials, userId, statusIds, comment, forward }) => {
|
||||||
url: MASTODON_REPORT_USER_URL,
|
url: MASTODON_REPORT_USER_URL,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
payload: {
|
payload: {
|
||||||
'account_id': userId,
|
account_id: userId,
|
||||||
'status_ids': statusIds,
|
status_ids: statusIds,
|
||||||
comment,
|
comment,
|
||||||
forward
|
forward
|
||||||
},
|
},
|
||||||
|
@ -1076,7 +1076,7 @@ const searchUsers = ({ credentials, query }) => {
|
||||||
|
|
||||||
const search2 = ({ credentials, q, resolve, limit, offset, following }) => {
|
const search2 = ({ credentials, q, resolve, limit, offset, following }) => {
|
||||||
let url = MASTODON_SEARCH_2
|
let url = MASTODON_SEARCH_2
|
||||||
let params = []
|
const params = []
|
||||||
|
|
||||||
if (q) {
|
if (q) {
|
||||||
params.push(['q', encodeURIComponent(q)])
|
params.push(['q', encodeURIComponent(q)])
|
||||||
|
@ -1100,7 +1100,7 @@ const search2 = ({ credentials, q, resolve, limit, offset, following }) => {
|
||||||
|
|
||||||
params.push(['with_relationships', true])
|
params.push(['with_relationships', true])
|
||||||
|
|
||||||
let queryString = map(params, (param) => `${param[0]}=${param[1]}`).join('&')
|
const queryString = map(params, (param) => `${param[0]}=${param[1]}`).join('&')
|
||||||
url += `?${queryString}`
|
url += `?${queryString}`
|
||||||
|
|
||||||
return fetch(url, { headers: authHeaders(credentials) })
|
return fetch(url, { headers: authHeaders(credentials) })
|
||||||
|
@ -1254,12 +1254,12 @@ export const handleMastoWS = (wsEvent) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const WSConnectionStatus = Object.freeze({
|
export const WSConnectionStatus = Object.freeze({
|
||||||
'JOINED': 1,
|
JOINED: 1,
|
||||||
'CLOSED': 2,
|
CLOSED: 2,
|
||||||
'ERROR': 3,
|
ERROR: 3,
|
||||||
'DISABLED': 4,
|
DISABLED: 4,
|
||||||
'STARTING': 5,
|
STARTING: 5,
|
||||||
'STARTING_INITIAL': 6
|
STARTING_INITIAL: 6
|
||||||
})
|
})
|
||||||
|
|
||||||
const chats = ({ credentials }) => {
|
const chats = ({ credentials }) => {
|
||||||
|
@ -1297,11 +1297,11 @@ const chatMessages = ({ id, credentials, maxId, sinceId, limit = 20 }) => {
|
||||||
|
|
||||||
const sendChatMessage = ({ id, content, mediaId = null, idempotencyKey, credentials }) => {
|
const sendChatMessage = ({ id, content, mediaId = null, idempotencyKey, credentials }) => {
|
||||||
const payload = {
|
const payload = {
|
||||||
'content': content
|
content
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mediaId) {
|
if (mediaId) {
|
||||||
payload['media_id'] = mediaId
|
payload.media_id = mediaId
|
||||||
}
|
}
|
||||||
|
|
||||||
const headers = {}
|
const headers = {}
|
||||||
|
@ -1313,7 +1313,7 @@ const sendChatMessage = ({ id, content, mediaId = null, idempotencyKey, credenti
|
||||||
return promisedRequest({
|
return promisedRequest({
|
||||||
url: PLEROMA_CHAT_MESSAGES_URL(id),
|
url: PLEROMA_CHAT_MESSAGES_URL(id),
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
payload: payload,
|
payload,
|
||||||
credentials,
|
credentials,
|
||||||
headers
|
headers
|
||||||
})
|
})
|
||||||
|
@ -1324,7 +1324,7 @@ const readChat = ({ id, lastReadId, credentials }) => {
|
||||||
url: PLEROMA_CHAT_READ_URL(id),
|
url: PLEROMA_CHAT_READ_URL(id),
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
payload: {
|
payload: {
|
||||||
'last_read_id': lastReadId
|
last_read_id: lastReadId
|
||||||
},
|
},
|
||||||
credentials
|
credentials
|
||||||
})
|
})
|
||||||
|
|
|
@ -7,7 +7,7 @@ const empty = (chatId) => {
|
||||||
messages: [],
|
messages: [],
|
||||||
newMessageCount: 0,
|
newMessageCount: 0,
|
||||||
lastSeenMessageId: '0',
|
lastSeenMessageId: '0',
|
||||||
chatId: chatId,
|
chatId,
|
||||||
minId: undefined,
|
minId: undefined,
|
||||||
maxId: undefined
|
maxId: undefined
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,7 @@ const add = (storage, { messages: newMessages, updateMaxId = true }) => {
|
||||||
storage.messages = storage.messages.filter(msg => msg.id !== message.id)
|
storage.messages = storage.messages.filter(msg => msg.id !== message.id)
|
||||||
}
|
}
|
||||||
Object.assign(fakeMessage, message, { error: false })
|
Object.assign(fakeMessage, message, { error: false })
|
||||||
delete fakeMessage['fakeId']
|
delete fakeMessage.fakeId
|
||||||
storage.idIndex[fakeMessage.id] = fakeMessage
|
storage.idIndex[fakeMessage.id] = fakeMessage
|
||||||
delete storage.idIndex[message.fakeId]
|
delete storage.idIndex[message.fakeId]
|
||||||
|
|
||||||
|
@ -178,7 +178,7 @@ const getView = (storage) => {
|
||||||
id: date.getTime().toString()
|
id: date.getTime().toString()
|
||||||
})
|
})
|
||||||
|
|
||||||
previousMessage['isTail'] = true
|
previousMessage.isTail = true
|
||||||
currentMessageChainId = undefined
|
currentMessageChainId = undefined
|
||||||
afterDate = true
|
afterDate = true
|
||||||
}
|
}
|
||||||
|
@ -193,15 +193,15 @@ const getView = (storage) => {
|
||||||
|
|
||||||
// end a message chian
|
// end a message chian
|
||||||
if ((nextMessage && nextMessage.account_id) !== message.account_id) {
|
if ((nextMessage && nextMessage.account_id) !== message.account_id) {
|
||||||
object['isTail'] = true
|
object.isTail = true
|
||||||
currentMessageChainId = undefined
|
currentMessageChainId = undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
// start a new message chain
|
// start a new message chain
|
||||||
if ((previousMessage && previousMessage.data && previousMessage.data.account_id) !== message.account_id || afterDate) {
|
if ((previousMessage && previousMessage.data && previousMessage.data.account_id) !== message.account_id || afterDate) {
|
||||||
currentMessageChainId = _.uniqueId()
|
currentMessageChainId = _.uniqueId()
|
||||||
object['isHead'] = true
|
object.isHead = true
|
||||||
object['messageChainId'] = currentMessageChainId
|
object.messageChainId = currentMessageChainId
|
||||||
}
|
}
|
||||||
|
|
||||||
result.push(object)
|
result.push(object)
|
||||||
|
|
|
@ -25,7 +25,7 @@ export const buildFakeMessage = ({ content, chatId, attachments, userId, idempot
|
||||||
chat_id: chatId,
|
chat_id: chatId,
|
||||||
created_at: new Date(),
|
created_at: new Date(),
|
||||||
id: `${new Date().getTime()}`,
|
id: `${new Date().getTime()}`,
|
||||||
attachments: attachments,
|
attachments,
|
||||||
account_id: userId,
|
account_id: userId,
|
||||||
idempotency_key: idempotencyKey,
|
idempotency_key: idempotencyKey,
|
||||||
emojis: [],
|
emojis: [],
|
||||||
|
|
|
@ -144,11 +144,13 @@ export const invert = (rgb) => {
|
||||||
*/
|
*/
|
||||||
export const hex2rgb = (hex) => {
|
export const hex2rgb = (hex) => {
|
||||||
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)
|
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)
|
||||||
return result ? {
|
return result
|
||||||
|
? {
|
||||||
r: parseInt(result[1], 16),
|
r: parseInt(result[1], 16),
|
||||||
g: parseInt(result[2], 16),
|
g: parseInt(result[2], 16),
|
||||||
b: parseInt(result[3], 16)
|
b: parseInt(result[3], 16)
|
||||||
} : null
|
}
|
||||||
|
: null
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -35,7 +35,7 @@ export const addPositionToWords = (words) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const splitByWhitespaceBoundary = (str) => {
|
export const splitByWhitespaceBoundary = (str) => {
|
||||||
let result = []
|
const result = []
|
||||||
let currentWord = ''
|
let currentWord = ''
|
||||||
for (let i = 0; i < str.length; i++) {
|
for (let i = 0; i < str.length; i++) {
|
||||||
const currentChar = str[i]
|
const currentChar = str[i]
|
||||||
|
|
|
@ -10,7 +10,7 @@ export const relativeTime = (date, nowThreshold = 1) => {
|
||||||
if (typeof date === 'string') date = Date.parse(date)
|
if (typeof date === 'string') date = Date.parse(date)
|
||||||
const round = Date.now() > date ? Math.floor : Math.ceil
|
const round = Date.now() > date ? Math.floor : Math.ceil
|
||||||
const d = Math.abs(Date.now() - date)
|
const d = Math.abs(Date.now() - date)
|
||||||
let r = { num: round(d / YEAR), key: 'time.unit.years' }
|
const r = { num: round(d / YEAR), key: 'time.unit.years' }
|
||||||
if (d < nowThreshold * SECOND) {
|
if (d < nowThreshold * SECOND) {
|
||||||
r.num = 0
|
r.num = 0
|
||||||
r.key = 'time.now'
|
r.key = 'time.now'
|
||||||
|
|
|
@ -371,8 +371,8 @@ export const parseStatus = (data) => {
|
||||||
|
|
||||||
export const parseNotification = (data) => {
|
export const parseNotification = (data) => {
|
||||||
const mastoDict = {
|
const mastoDict = {
|
||||||
'favourite': 'like',
|
favourite: 'like',
|
||||||
'reblog': 'repeat'
|
reblog: 'repeat'
|
||||||
}
|
}
|
||||||
const masto = !data.hasOwnProperty('ntype')
|
const masto = !data.hasOwnProperty('ntype')
|
||||||
const output = {}
|
const output = {}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
const fileSizeFormat = (num) => {
|
const fileSizeFormat = (num) => {
|
||||||
var exponent
|
let exponent
|
||||||
var unit
|
let unit
|
||||||
var units = ['B', 'KiB', 'MiB', 'GiB', 'TiB']
|
const units = ['B', 'KiB', 'MiB', 'GiB', 'TiB']
|
||||||
if (num < 1) {
|
if (num < 1) {
|
||||||
return num + ' ' + units[0]
|
return num + ' ' + units[0]
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ const fileSizeFormat = (num) => {
|
||||||
exponent = Math.min(Math.floor(Math.log(num) / Math.log(1024)), units.length - 1)
|
exponent = Math.min(Math.floor(Math.log(num) / Math.log(1024)), units.length - 1)
|
||||||
num = (num / Math.pow(1024, exponent)).toFixed(2) * 1
|
num = (num / Math.pow(1024, exponent)).toFixed(2) * 1
|
||||||
unit = units[exponent]
|
unit = units[exponent]
|
||||||
return { num: num, unit: unit }
|
return { num, unit }
|
||||||
}
|
}
|
||||||
const fileSizeFormatService = {
|
const fileSizeFormatService = {
|
||||||
fileSizeFormat
|
fileSizeFormat
|
||||||
|
|
|
@ -46,7 +46,7 @@ export const convertHtmlToLines = (html = '') => {
|
||||||
// All block-level elements that aren't empty elements, i.e. not <hr>
|
// All block-level elements that aren't empty elements, i.e. not <hr>
|
||||||
const nonEmptyElements = new Set(visualLineElements)
|
const nonEmptyElements = new Set(visualLineElements)
|
||||||
// Difference
|
// Difference
|
||||||
for (let elem of emptyElements) {
|
for (const elem of emptyElements) {
|
||||||
nonEmptyElements.delete(elem)
|
nonEmptyElements.delete(elem)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ export const convertHtmlToLines = (html = '') => {
|
||||||
...emptyElements.values()
|
...emptyElements.values()
|
||||||
])
|
])
|
||||||
|
|
||||||
let buffer = [] // Current output buffer
|
const buffer = [] // Current output buffer
|
||||||
const level = [] // How deep we are in tags and which tags were there
|
const level = [] // How deep we are in tags and which tags were there
|
||||||
let textBuffer = '' // Current line content
|
let textBuffer = '' // Current line content
|
||||||
let tagBuffer = null // Current tag buffer, if null = we are not currently reading a tag
|
let tagBuffer = null // Current tag buffer, if null = we are not currently reading a tag
|
||||||
|
|
|
@ -50,7 +50,7 @@ export const processTextForEmoji = (text, emojis, processor) => {
|
||||||
if (char === ':') {
|
if (char === ':') {
|
||||||
const next = text.slice(i + 1)
|
const next = text.slice(i + 1)
|
||||||
let found = false
|
let found = false
|
||||||
for (let emoji of emojis) {
|
for (const emoji of emojis) {
|
||||||
if (next.slice(0, emoji.shortcode.length + 1) === (emoji.shortcode + ':')) {
|
if (next.slice(0, emoji.shortcode.length + 1) === (emoji.shortcode + ':')) {
|
||||||
found = emoji
|
found = emoji
|
||||||
break
|
break
|
||||||
|
|
|
@ -3,9 +3,9 @@ import ISO6391 from 'iso-639-1'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
|
|
||||||
const specialLanguageCodes = {
|
const specialLanguageCodes = {
|
||||||
'ja_easy': 'ja',
|
ja_easy: 'ja',
|
||||||
'zh_Hant': 'zh-HANT',
|
zh_Hant: 'zh-HANT',
|
||||||
'zh': 'zh-Hans'
|
zh: 'zh-Hans'
|
||||||
}
|
}
|
||||||
|
|
||||||
const internalToBrowserLocale = code => specialLanguageCodes[code] || code
|
const internalToBrowserLocale = code => specialLanguageCodes[code] || code
|
||||||
|
@ -14,16 +14,16 @@ const internalToBackendLocale = code => internalToBrowserLocale(code).replace('_
|
||||||
|
|
||||||
const getLanguageName = (code) => {
|
const getLanguageName = (code) => {
|
||||||
const specialLanguageNames = {
|
const specialLanguageNames = {
|
||||||
'ja_easy': 'やさしいにほんご',
|
ja_easy: 'やさしいにほんご',
|
||||||
'zh': '简体中文',
|
zh: '简体中文',
|
||||||
'zh_Hant': '繁體中文'
|
zh_Hant: '繁體中文'
|
||||||
}
|
}
|
||||||
const languageName = specialLanguageNames[code] || ISO6391.getNativeName(code)
|
const languageName = specialLanguageNames[code] || ISO6391.getNativeName(code)
|
||||||
const browserLocale = internalToBrowserLocale(code)
|
const browserLocale = internalToBrowserLocale(code)
|
||||||
return languageName.charAt(0).toLocaleUpperCase(browserLocale) + languageName.slice(1)
|
return languageName.charAt(0).toLocaleUpperCase(browserLocale) + languageName.slice(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
const languages = _.map(languagesObject.languages, (code) => ({ code: code, name: getLanguageName(code) })).sort((a, b) => a.name.localeCompare(b.name))
|
const languages = _.map(languagesObject.languages, (code) => ({ code, name: getLanguageName(code) })).sort((a, b) => a.name.localeCompare(b.name))
|
||||||
|
|
||||||
const localeService = {
|
const localeService = {
|
||||||
internalToBrowserLocale,
|
internalToBrowserLocale,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { reduce } from 'lodash'
|
import { reduce } from 'lodash'
|
||||||
|
|
||||||
const MASTODON_PASSWORD_RESET_URL = `/auth/password`
|
const MASTODON_PASSWORD_RESET_URL = '/auth/password'
|
||||||
|
|
||||||
const resetPassword = ({ instance, email }) => {
|
const resetPassword = ({ instance, email }) => {
|
||||||
const params = { email }
|
const params = { email }
|
||||||
|
|
|
@ -12,20 +12,20 @@ const fetchAndUpdate = ({ store, credentials, older = false, since }) => {
|
||||||
const timelineData = rootState.statuses.notifications
|
const timelineData = rootState.statuses.notifications
|
||||||
const hideMutedPosts = getters.mergedConfig.hideMutedPosts
|
const hideMutedPosts = getters.mergedConfig.hideMutedPosts
|
||||||
|
|
||||||
args['withMuted'] = !hideMutedPosts
|
args.withMuted = !hideMutedPosts
|
||||||
|
|
||||||
args['timeline'] = 'notifications'
|
args.timeline = 'notifications'
|
||||||
if (older) {
|
if (older) {
|
||||||
if (timelineData.minId !== Number.POSITIVE_INFINITY) {
|
if (timelineData.minId !== Number.POSITIVE_INFINITY) {
|
||||||
args['until'] = timelineData.minId
|
args.until = timelineData.minId
|
||||||
}
|
}
|
||||||
return fetchNotifications({ store, args, older })
|
return fetchNotifications({ store, args, older })
|
||||||
} else {
|
} else {
|
||||||
// fetch new notifications
|
// fetch new notifications
|
||||||
if (since === undefined && timelineData.maxId !== Number.POSITIVE_INFINITY) {
|
if (since === undefined && timelineData.maxId !== Number.POSITIVE_INFINITY) {
|
||||||
args['since'] = timelineData.maxId
|
args.since = timelineData.maxId
|
||||||
} else if (since !== null) {
|
} else if (since !== null) {
|
||||||
args['since'] = since
|
args.since = since
|
||||||
}
|
}
|
||||||
const result = fetchNotifications({ store, args, older })
|
const result = fetchNotifications({ store, args, older })
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ const fetchAndUpdate = ({ store, credentials, older = false, since }) => {
|
||||||
const readNotifsIds = notifications.filter(n => n.seen).map(n => n.id)
|
const readNotifsIds = notifications.filter(n => n.seen).map(n => n.id)
|
||||||
const numUnseenNotifs = notifications.length - readNotifsIds.length
|
const numUnseenNotifs = notifications.length - readNotifsIds.length
|
||||||
if (numUnseenNotifs > 0 && readNotifsIds.length > 0) {
|
if (numUnseenNotifs > 0 && readNotifsIds.length > 0) {
|
||||||
args['since'] = Math.max(...readNotifsIds)
|
args.since = Math.max(...readNotifsIds)
|
||||||
fetchNotifications({ store, args, older })
|
fetchNotifications({ store, args, older })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ function deleteSubscriptionFromBackEnd (token) {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'Authorization': `Bearer ${token}`
|
Authorization: `Bearer ${token}`
|
||||||
}
|
}
|
||||||
}).then((response) => {
|
}).then((response) => {
|
||||||
if (!response.ok) throw new Error('Bad status code from server.')
|
if (!response.ok) throw new Error('Bad status code from server.')
|
||||||
|
@ -56,7 +56,7 @@ function sendSubscriptionToBackEnd (subscription, token, notificationVisibility)
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'Authorization': `Bearer ${token}`
|
Authorization: `Bearer ${token}`
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
subscription,
|
subscription,
|
||||||
|
|
|
@ -39,7 +39,7 @@ import { LAYERS, DEFAULT_OPACITY, SLOT_INHERITANCE } from './pleromafe.js'
|
||||||
export const CURRENT_VERSION = 3
|
export const CURRENT_VERSION = 3
|
||||||
|
|
||||||
export const getLayersArray = (layer, data = LAYERS) => {
|
export const getLayersArray = (layer, data = LAYERS) => {
|
||||||
let array = [layer]
|
const array = [layer]
|
||||||
let parent = data[layer]
|
let parent = data[layer]
|
||||||
while (parent) {
|
while (parent) {
|
||||||
array.unshift(parent)
|
array.unshift(parent)
|
||||||
|
|
|
@ -34,20 +34,20 @@ const fetchAndUpdate = ({
|
||||||
const loggedIn = !!rootState.users.currentUser
|
const loggedIn = !!rootState.users.currentUser
|
||||||
|
|
||||||
if (older) {
|
if (older) {
|
||||||
args['until'] = until || timelineData.minId
|
args.until = until || timelineData.minId
|
||||||
} else {
|
} else {
|
||||||
if (since === undefined) {
|
if (since === undefined) {
|
||||||
args['since'] = timelineData.maxId
|
args.since = timelineData.maxId
|
||||||
} else if (since !== null) {
|
} else if (since !== null) {
|
||||||
args['since'] = since
|
args.since = since
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
args['userId'] = userId
|
args.userId = userId
|
||||||
args['tag'] = tag
|
args.tag = tag
|
||||||
args['withMuted'] = !hideMutedPosts
|
args.withMuted = !hideMutedPosts
|
||||||
if (loggedIn && ['friends', 'public', 'publicAndExternal'].includes(timeline)) {
|
if (loggedIn && ['friends', 'public', 'publicAndExternal'].includes(timeline)) {
|
||||||
args['replyVisibility'] = replyVisibility
|
args.replyVisibility = replyVisibility
|
||||||
}
|
}
|
||||||
|
|
||||||
const numStatusesBeforeFetch = timelineData.statuses.length
|
const numStatusesBeforeFetch = timelineData.statuses.length
|
||||||
|
@ -60,7 +60,7 @@ const fetchAndUpdate = ({
|
||||||
|
|
||||||
const { data: statuses, pagination } = response
|
const { data: statuses, pagination } = response
|
||||||
if (!older && statuses.length >= 20 && !timelineData.loading && numStatusesBeforeFetch > 0) {
|
if (!older && statuses.length >= 20 && !timelineData.loading && numStatusesBeforeFetch > 0) {
|
||||||
store.dispatch('queueFlush', { timeline: timeline, id: timelineData.maxId })
|
store.dispatch('queueFlush', { timeline, id: timelineData.maxId })
|
||||||
}
|
}
|
||||||
update({ store, statuses, timeline, showImmediately, userId, pagination })
|
update({ store, statuses, timeline, showImmediately, userId, pagination })
|
||||||
return { statuses, pagination }
|
return { statuses, pagination }
|
||||||
|
|
|
@ -36,7 +36,7 @@ const highlightStyle = (prefs) => {
|
||||||
'linear-gradient(to right,',
|
'linear-gradient(to right,',
|
||||||
`${solidColor} ,`,
|
`${solidColor} ,`,
|
||||||
`${solidColor} 2px,`,
|
`${solidColor} 2px,`,
|
||||||
`transparent 6px`
|
'transparent 6px'
|
||||||
].join(' '),
|
].join(' '),
|
||||||
backgroundPosition: '0 0',
|
backgroundPosition: '0 0',
|
||||||
...customProps
|
...customProps
|
||||||
|
|
|
@ -57,8 +57,8 @@ self.addEventListener('notificationclick', (event) => {
|
||||||
event.notification.close()
|
event.notification.close()
|
||||||
|
|
||||||
event.waitUntil(getWindowClients().then((list) => {
|
event.waitUntil(getWindowClients().then((list) => {
|
||||||
for (var i = 0; i < list.length; i++) {
|
for (let i = 0; i < list.length; i++) {
|
||||||
var client = list[i]
|
const client = list[i]
|
||||||
if (client.url === '/' && 'focus' in client) { return client.focus() }
|
if (client.url === '/' && 'focus' in client) { return client.focus() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ exports.assertion = function (selector, count) {
|
||||||
return res.value
|
return res.value
|
||||||
}
|
}
|
||||||
this.command = function (cb) {
|
this.command = function (cb) {
|
||||||
var self = this
|
const self = this
|
||||||
return this.api.execute(function (selector) {
|
return this.api.execute(function (selector) {
|
||||||
return document.querySelectorAll(selector).length
|
return document.querySelectorAll(selector).length
|
||||||
}, [selector], function (res) {
|
}, [selector], function (res) {
|
||||||
|
|
|
@ -1,45 +1,45 @@
|
||||||
require('@babel/register')
|
require('@babel/register')
|
||||||
var config = require('../../config')
|
const config = require('../../config')
|
||||||
|
|
||||||
// http://nightwatchjs.org/guide#settings-file
|
// http://nightwatchjs.org/guide#settings-file
|
||||||
module.exports = {
|
module.exports = {
|
||||||
'src_folders': ['test/e2e/specs'],
|
src_folders: ['test/e2e/specs'],
|
||||||
'output_folder': 'test/e2e/reports',
|
output_folder: 'test/e2e/reports',
|
||||||
'custom_assertions_path': ['test/e2e/custom-assertions'],
|
custom_assertions_path: ['test/e2e/custom-assertions'],
|
||||||
|
|
||||||
'selenium': {
|
selenium: {
|
||||||
'start_process': true,
|
start_process: true,
|
||||||
'server_path': 'node_modules/selenium-server/lib/runner/selenium-server-standalone-2.53.1.jar',
|
server_path: 'node_modules/selenium-server/lib/runner/selenium-server-standalone-2.53.1.jar',
|
||||||
'host': '127.0.0.1',
|
host: '127.0.0.1',
|
||||||
'port': 4444,
|
port: 4444,
|
||||||
'cli_args': {
|
cli_args: {
|
||||||
'webdriver.chrome.driver': require('chromedriver').path
|
'webdriver.chrome.driver': require('chromedriver').path
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
'test_settings': {
|
test_settings: {
|
||||||
'default': {
|
default: {
|
||||||
'selenium_port': 4444,
|
selenium_port: 4444,
|
||||||
'selenium_host': 'localhost',
|
selenium_host: 'localhost',
|
||||||
'silent': true,
|
silent: true,
|
||||||
'globals': {
|
globals: {
|
||||||
'devServerURL': 'http://localhost:' + (process.env.PORT || config.dev.port)
|
devServerURL: 'http://localhost:' + (process.env.PORT || config.dev.port)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
'chrome': {
|
chrome: {
|
||||||
'desiredCapabilities': {
|
desiredCapabilities: {
|
||||||
'browserName': 'chrome',
|
browserName: 'chrome',
|
||||||
'javascriptEnabled': true,
|
javascriptEnabled: true,
|
||||||
'acceptSslCerts': true
|
acceptSslCerts: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
'firefox': {
|
firefox: {
|
||||||
'desiredCapabilities': {
|
desiredCapabilities: {
|
||||||
'browserName': 'firefox',
|
browserName: 'firefox',
|
||||||
'javascriptEnabled': true,
|
javascriptEnabled: true,
|
||||||
'acceptSslCerts': true
|
acceptSslCerts: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// 1. start the dev server using production config
|
// 1. start the dev server using production config
|
||||||
process.env.NODE_ENV = 'testing'
|
process.env.NODE_ENV = 'testing'
|
||||||
var server = require('../../build/dev-server.js')
|
const server = require('../../build/dev-server.js')
|
||||||
|
|
||||||
// 2. run the nightwatch test suite against it
|
// 2. run the nightwatch test suite against it
|
||||||
// to run in additional browsers:
|
// to run in additional browsers:
|
||||||
|
@ -9,7 +9,7 @@ var server = require('../../build/dev-server.js')
|
||||||
// or override the environment flag, for example: `npm run e2e -- --env chrome,firefox`
|
// or override the environment flag, for example: `npm run e2e -- --env chrome,firefox`
|
||||||
// For more information on Nightwatch's config file, see
|
// For more information on Nightwatch's config file, see
|
||||||
// http://nightwatchjs.org/guide#settings-file
|
// http://nightwatchjs.org/guide#settings-file
|
||||||
var opts = process.argv.slice(2)
|
let opts = process.argv.slice(2)
|
||||||
if (opts.indexOf('--config') === -1) {
|
if (opts.indexOf('--config') === -1) {
|
||||||
opts = opts.concat(['--config', 'test/e2e/nightwatch.conf.js'])
|
opts = opts.concat(['--config', 'test/e2e/nightwatch.conf.js'])
|
||||||
}
|
}
|
||||||
|
@ -17,8 +17,8 @@ if (opts.indexOf('--env') === -1) {
|
||||||
opts = opts.concat(['--env', 'chrome'])
|
opts = opts.concat(['--env', 'chrome'])
|
||||||
}
|
}
|
||||||
|
|
||||||
var spawn = require('cross-spawn')
|
const spawn = require('cross-spawn')
|
||||||
var runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' })
|
const runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' })
|
||||||
|
|
||||||
runner.on('exit', function (code) {
|
runner.on('exit', function (code) {
|
||||||
server.close()
|
server.close()
|
||||||
|
|
|
@ -4,14 +4,14 @@
|
||||||
// https://github.com/webpack/karma-webpack
|
// https://github.com/webpack/karma-webpack
|
||||||
|
|
||||||
// var path = require('path')
|
// var path = require('path')
|
||||||
var merge = require('webpack-merge')
|
const merge = require('webpack-merge')
|
||||||
var HtmlWebpackPlugin = require('html-webpack-plugin')
|
const HtmlWebpackPlugin = require('html-webpack-plugin')
|
||||||
var baseConfig = require('../../build/webpack.base.conf')
|
const baseConfig = require('../../build/webpack.base.conf')
|
||||||
var utils = require('../../build/utils')
|
const utils = require('../../build/utils')
|
||||||
var webpack = require('webpack')
|
const webpack = require('webpack')
|
||||||
// var projectRoot = path.resolve(__dirname, '../../')
|
// var projectRoot = path.resolve(__dirname, '../../')
|
||||||
|
|
||||||
var webpackConfig = merge(baseConfig, {
|
const webpackConfig = merge(baseConfig, {
|
||||||
// use inline sourcemap for karma-sourcemap-loader
|
// use inline sourcemap for karma-sourcemap-loader
|
||||||
module: {
|
module: {
|
||||||
rules: utils.styleLoaders()
|
rules: utils.styleLoaders()
|
||||||
|
@ -63,7 +63,7 @@ module.exports = function (config) {
|
||||||
frameworks: ['mocha', 'sinon-chai'],
|
frameworks: ['mocha', 'sinon-chai'],
|
||||||
reporters: ['mocha'],
|
reporters: ['mocha'],
|
||||||
customLaunchers: {
|
customLaunchers: {
|
||||||
'FirefoxHeadless': {
|
FirefoxHeadless: {
|
||||||
base: 'Firefox',
|
base: 'Firefox',
|
||||||
flags: [
|
flags: [
|
||||||
'-headless'
|
'-headless'
|
||||||
|
|
|
@ -29,7 +29,7 @@ const generateInput = (value, padEmoji = true) => {
|
||||||
modelValue: value
|
modelValue: value
|
||||||
},
|
},
|
||||||
slots: {
|
slots: {
|
||||||
'default': () => h('input', '')
|
default: () => h('input', '')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
|
@ -4,7 +4,7 @@ import RichContent from 'src/components/rich_content/rich_content.jsx'
|
||||||
const attentions = []
|
const attentions = []
|
||||||
const global = {
|
const global = {
|
||||||
mocks: {
|
mocks: {
|
||||||
'$store': {
|
$store: {
|
||||||
state: {},
|
state: {},
|
||||||
getters: {
|
getters: {
|
||||||
mergedConfig: () => ({
|
mergedConfig: () => ({
|
||||||
|
|
|
@ -163,7 +163,7 @@ const localProfileStore = createStore({
|
||||||
currentUser: {
|
currentUser: {
|
||||||
credentials: ''
|
credentials: ''
|
||||||
},
|
},
|
||||||
usersObject: { 100: localUser, 'testuser': localUser },
|
usersObject: { 100: localUser, testuser: localUser },
|
||||||
users: [localUser],
|
users: [localUser],
|
||||||
relationships: {}
|
relationships: {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -314,8 +314,8 @@ describe('API Entities normalizer', () => {
|
||||||
const linkHeader = '<https://example.com/api/v1/notifications?max_id=861676>; rel="next", <https://example.com/api/v1/notifications?min_id=861741>; rel="prev"'
|
const linkHeader = '<https://example.com/api/v1/notifications?max_id=861676>; rel="next", <https://example.com/api/v1/notifications?min_id=861741>; rel="prev"'
|
||||||
const result = parseLinkHeaderPagination(linkHeader)
|
const result = parseLinkHeaderPagination(linkHeader)
|
||||||
expect(result).to.eql({
|
expect(result).to.eql({
|
||||||
'maxId': 861676,
|
maxId: 861676,
|
||||||
'minId': 861741
|
minId: 861741
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -323,8 +323,8 @@ describe('API Entities normalizer', () => {
|
||||||
const linkHeader = '<http://example.com/api/v1/timelines/home?max_id=9waQx5IIS48qVue2Ai>; rel="next", <http://example.com/api/v1/timelines/home?min_id=9wi61nIPnfn674xgie>; rel="prev"'
|
const linkHeader = '<http://example.com/api/v1/timelines/home?max_id=9waQx5IIS48qVue2Ai>; rel="next", <http://example.com/api/v1/timelines/home?min_id=9wi61nIPnfn674xgie>; rel="prev"'
|
||||||
const result = parseLinkHeaderPagination(linkHeader, { flakeId: true })
|
const result = parseLinkHeaderPagination(linkHeader, { flakeId: true })
|
||||||
expect(result).to.eql({
|
expect(result).to.eql({
|
||||||
'maxId': '9waQx5IIS48qVue2Ai',
|
maxId: '9waQx5IIS48qVue2Ai',
|
||||||
'minId': '9wi61nIPnfn674xgie'
|
minId: '9wi61nIPnfn674xgie'
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue