forked from AkkomaGang/akkoma-fe
Merge branch 'eslint-fix' into 'develop'
Fix shitton warning eslint gives See merge request pleroma/pleroma-fe!871
This commit is contained in:
commit
54b0f90133
145 changed files with 5313 additions and 2617 deletions
22
.eslintrc.js
22
.eslintrc.js
|
@ -21,26 +21,6 @@ module.exports = {
|
||||||
'generator-star-spacing': 0,
|
'generator-star-spacing': 0,
|
||||||
// allow debugger during development
|
// allow debugger during development
|
||||||
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
|
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
|
||||||
// Webpack 4 update commit, most of these probably should be fixed and removed in a separate MR
|
'vue/require-prop-types': 0
|
||||||
// A lot of errors come from .vue files that are now properly linted
|
|
||||||
'vue/valid-v-if': 1,
|
|
||||||
'vue/use-v-on-exact': 1,
|
|
||||||
'vue/no-parsing-error': 1,
|
|
||||||
'vue/require-v-for-key': 1,
|
|
||||||
'vue/valid-v-for': 1,
|
|
||||||
'vue/require-prop-types': 1,
|
|
||||||
'vue/no-use-v-if-with-v-for': 1,
|
|
||||||
'indent': 1,
|
|
||||||
'import/first': 1,
|
|
||||||
'object-curly-spacing': 1,
|
|
||||||
'prefer-promise-reject-errors': 1,
|
|
||||||
'eol-last': 1,
|
|
||||||
'no-return-await': 1,
|
|
||||||
'no-multi-spaces': 1,
|
|
||||||
'no-trailing-spaces': 1,
|
|
||||||
'no-unused-expressions': 1,
|
|
||||||
'no-mixed-operators': 1,
|
|
||||||
'camelcase': 1,
|
|
||||||
'no-multiple-empty-lines': 1
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
108
src/App.vue
108
src/App.vue
|
@ -1,53 +1,111 @@
|
||||||
<template>
|
<template>
|
||||||
<div id="app" v-bind:style="bgAppStyle">
|
<div
|
||||||
<div class="app-bg-wrapper" v-bind:style="bgStyle"></div>
|
id="app"
|
||||||
|
:style="bgAppStyle"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="app-bg-wrapper"
|
||||||
|
:style="bgStyle"
|
||||||
|
/>
|
||||||
<MobileNav v-if="isMobileLayout" />
|
<MobileNav v-if="isMobileLayout" />
|
||||||
<nav v-else class='nav-bar container' @click="scrollToTop()" id="nav">
|
<nav
|
||||||
<div class='logo' :style='logoBgStyle'>
|
v-else
|
||||||
<div class='mask' :style='logoMaskStyle'></div>
|
id="nav"
|
||||||
<img :src='logo' :style='logoStyle'>
|
class="nav-bar container"
|
||||||
|
@click="scrollToTop()"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="logo"
|
||||||
|
:style="logoBgStyle"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mask"
|
||||||
|
:style="logoMaskStyle"
|
||||||
|
/>
|
||||||
|
<img
|
||||||
|
:src="logo"
|
||||||
|
:style="logoStyle"
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class='inner-nav'>
|
<div class="inner-nav">
|
||||||
<div class='item'>
|
<div class="item">
|
||||||
<router-link class="site-name" :to="{ name: 'root' }" active-class="home">{{sitename}}</router-link>
|
<router-link
|
||||||
|
class="site-name"
|
||||||
|
:to="{ name: 'root' }"
|
||||||
|
active-class="home"
|
||||||
|
>
|
||||||
|
{{ sitename }}
|
||||||
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
<div class='item right'>
|
<div class="item right">
|
||||||
<user-finder class="button-icon nav-icon mobile-hidden" @toggled="onFinderToggled"></user-finder>
|
<user-finder
|
||||||
<router-link class="mobile-hidden" :to="{ name: 'settings'}"><i class="button-icon icon-cog nav-icon" :title="$t('nav.preferences')"></i></router-link>
|
class="button-icon nav-icon mobile-hidden"
|
||||||
<a href="#" class="mobile-hidden" v-if="currentUser" @click.prevent="logout"><i class="button-icon icon-logout nav-icon" :title="$t('login.logout')"></i></a>
|
@toggled="onFinderToggled"
|
||||||
|
/>
|
||||||
|
<router-link
|
||||||
|
class="mobile-hidden"
|
||||||
|
:to="{ name: 'settings'}"
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
class="button-icon icon-cog nav-icon"
|
||||||
|
:title="$t('nav.preferences')"
|
||||||
|
/>
|
||||||
|
</router-link>
|
||||||
|
<a
|
||||||
|
v-if="currentUser"
|
||||||
|
href="#"
|
||||||
|
class="mobile-hidden"
|
||||||
|
@click.prevent="logout"
|
||||||
|
><i
|
||||||
|
class="button-icon icon-logout nav-icon"
|
||||||
|
:title="$t('login.logout')"
|
||||||
|
/></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<div class="container" id="content">
|
<div
|
||||||
|
id="content"
|
||||||
|
class="container"
|
||||||
|
>
|
||||||
<div class="sidebar-flexer mobile-hidden">
|
<div class="sidebar-flexer mobile-hidden">
|
||||||
<div class="sidebar-bounds">
|
<div class="sidebar-bounds">
|
||||||
<div class="sidebar-scroller">
|
<div class="sidebar-scroller">
|
||||||
<div class="sidebar">
|
<div class="sidebar">
|
||||||
<user-panel></user-panel>
|
<user-panel />
|
||||||
<div v-if="!isMobileLayout">
|
<div v-if="!isMobileLayout">
|
||||||
<nav-panel></nav-panel>
|
<nav-panel />
|
||||||
<instance-specific-panel v-if="showInstanceSpecificPanel"></instance-specific-panel>
|
<instance-specific-panel v-if="showInstanceSpecificPanel" />
|
||||||
<features-panel v-if="!currentUser && showFeaturesPanel"></features-panel>
|
<features-panel v-if="!currentUser && showFeaturesPanel" />
|
||||||
<who-to-follow-panel v-if="currentUser && suggestionsEnabled"></who-to-follow-panel>
|
<who-to-follow-panel v-if="currentUser && suggestionsEnabled" />
|
||||||
<notifications v-if="currentUser"></notifications>
|
<notifications v-if="currentUser" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="main">
|
<div class="main">
|
||||||
<div v-if="!currentUser" class="login-hint panel panel-default">
|
<div
|
||||||
<router-link :to="{ name: 'login' }" class="panel-body">
|
v-if="!currentUser"
|
||||||
|
class="login-hint panel panel-default"
|
||||||
|
>
|
||||||
|
<router-link
|
||||||
|
:to="{ name: 'login' }"
|
||||||
|
class="panel-body"
|
||||||
|
>
|
||||||
{{ $t("login.hint") }}
|
{{ $t("login.hint") }}
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
<transition name="fade">
|
<transition name="fade">
|
||||||
<router-view></router-view>
|
<router-view />
|
||||||
</transition>
|
</transition>
|
||||||
</div>
|
</div>
|
||||||
<media-modal></media-modal>
|
<media-modal />
|
||||||
</div>
|
</div>
|
||||||
<chat-panel :floating="true" v-if="currentUser && chat" class="floating-chat mobile-hidden"></chat-panel>
|
<chat-panel
|
||||||
|
v-if="currentUser && chat"
|
||||||
|
:floating="true"
|
||||||
|
class="floating-chat mobile-hidden"
|
||||||
|
/>
|
||||||
<UserReportingModal />
|
<UserReportingModal />
|
||||||
<portal-target name="modal" />
|
<portal-target name="modal" />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -24,8 +24,8 @@ export default (store) => {
|
||||||
path: '/',
|
path: '/',
|
||||||
redirect: _to => {
|
redirect: _to => {
|
||||||
return (store.state.users.currentUser
|
return (store.state.users.currentUser
|
||||||
? store.state.instance.redirectRootLogin
|
? store.state.instance.redirectRootLogin
|
||||||
: store.state.instance.redirectRootNoLogin) || '/main/all'
|
: store.state.instance.redirectRootNoLogin) || '/main/all'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ name: 'public-external-timeline', path: '/main/all', component: PublicAndExternalTimeline },
|
{ name: 'public-external-timeline', path: '/main/all', component: PublicAndExternalTimeline },
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="sidebar">
|
<div class="sidebar">
|
||||||
<instance-specific-panel></instance-specific-panel>
|
<instance-specific-panel />
|
||||||
<features-panel v-if="showFeaturesPanel"></features-panel>
|
<features-panel v-if="showFeaturesPanel" />
|
||||||
<terms-of-service-panel></terms-of-service-panel>
|
<terms-of-service-panel />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ const Attachment = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
linkClicked ({target}) {
|
linkClicked ({ target }) {
|
||||||
if (target.tagName === 'A') {
|
if (target.tagName === 'A') {
|
||||||
window.open(target.href, '_blank')
|
window.open(target.href, '_blank')
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,54 +1,106 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-if="usePlaceHolder" @click="openModal">
|
<div
|
||||||
<a class="placeholder"
|
v-if="usePlaceHolder"
|
||||||
|
@click="openModal"
|
||||||
|
>
|
||||||
|
<a
|
||||||
v-if="type !== 'html'"
|
v-if="type !== 'html'"
|
||||||
target="_blank" :href="attachment.url"
|
class="placeholder"
|
||||||
|
target="_blank"
|
||||||
|
:href="attachment.url"
|
||||||
>
|
>
|
||||||
[{{nsfw ? "NSFW/" : ""}}{{type.toUpperCase()}}]
|
[{{ nsfw ? "NSFW/" : "" }}{{ type.toUpperCase() }}]
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-else class="attachment"
|
v-else
|
||||||
:class="{[type]: true, loading, 'fullwidth': fullwidth, 'nsfw-placeholder': hidden}"
|
|
||||||
v-show="!isEmpty"
|
v-show="!isEmpty"
|
||||||
|
class="attachment"
|
||||||
|
:class="{[type]: true, loading, 'fullwidth': fullwidth, 'nsfw-placeholder': hidden}"
|
||||||
>
|
>
|
||||||
<a class="image-attachment" v-if="hidden" :href="attachment.url" @click.prevent="toggleHidden">
|
<a
|
||||||
<img class="nsfw" :key="nsfwImage" :src="nsfwImage" :class="{'small': isSmall}"/>
|
v-if="hidden"
|
||||||
<i v-if="type === 'video'" class="play-icon icon-play-circled"></i>
|
class="image-attachment"
|
||||||
|
:href="attachment.url"
|
||||||
|
@click.prevent="toggleHidden"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
:key="nsfwImage"
|
||||||
|
class="nsfw"
|
||||||
|
:src="nsfwImage"
|
||||||
|
:class="{'small': isSmall}"
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
v-if="type === 'video'"
|
||||||
|
class="play-icon icon-play-circled"
|
||||||
|
/>
|
||||||
</a>
|
</a>
|
||||||
<div class="hider" v-if="nsfw && hideNsfwLocal && !hidden">
|
<div
|
||||||
<a href="#" @click.prevent="toggleHidden">Hide</a>
|
v-if="nsfw && hideNsfwLocal && !hidden"
|
||||||
|
class="hider"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
@click.prevent="toggleHidden"
|
||||||
|
>Hide</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a v-if="type === 'image' && (!hidden || preloadImage)"
|
<a
|
||||||
@click="openModal"
|
v-if="type === 'image' && (!hidden || preloadImage)"
|
||||||
class="image-attachment"
|
class="image-attachment"
|
||||||
:class="{'hidden': hidden && preloadImage }"
|
:class="{'hidden': hidden && preloadImage }"
|
||||||
:href="attachment.url" target="_blank"
|
:href="attachment.url"
|
||||||
|
target="_blank"
|
||||||
:title="attachment.description"
|
:title="attachment.description"
|
||||||
|
@click="openModal"
|
||||||
>
|
>
|
||||||
<StillImage :referrerpolicy="referrerpolicy" :mimetype="attachment.mimetype" :src="attachment.large_thumb_url || attachment.url"/>
|
<StillImage
|
||||||
|
:referrerpolicy="referrerpolicy"
|
||||||
|
:mimetype="attachment.mimetype"
|
||||||
|
:src="attachment.large_thumb_url || attachment.url"
|
||||||
|
/>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a class="video-container"
|
<a
|
||||||
@click="openModal"
|
|
||||||
v-if="type === 'video' && !hidden"
|
v-if="type === 'video' && !hidden"
|
||||||
|
class="video-container"
|
||||||
:class="{'small': isSmall}"
|
:class="{'small': isSmall}"
|
||||||
:href="allowPlay ? undefined : attachment.url"
|
:href="allowPlay ? undefined : attachment.url"
|
||||||
|
@click="openModal"
|
||||||
>
|
>
|
||||||
<VideoAttachment class="video" :attachment="attachment" :controls="allowPlay" />
|
<VideoAttachment
|
||||||
<i v-if="!allowPlay" class="play-icon icon-play-circled"></i>
|
class="video"
|
||||||
|
:attachment="attachment"
|
||||||
|
:controls="allowPlay"
|
||||||
|
/>
|
||||||
|
<i
|
||||||
|
v-if="!allowPlay"
|
||||||
|
class="play-icon icon-play-circled"
|
||||||
|
/>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<audio v-if="type === 'audio'" :src="attachment.url" controls></audio>
|
<audio
|
||||||
|
v-if="type === 'audio'"
|
||||||
|
:src="attachment.url"
|
||||||
|
controls
|
||||||
|
/>
|
||||||
|
|
||||||
<div @click.prevent="linkClicked" v-if="type === 'html' && attachment.oembed" class="oembed">
|
<div
|
||||||
<div v-if="attachment.thumb_url" class="image">
|
v-if="type === 'html' && attachment.oembed"
|
||||||
<img :src="attachment.thumb_url"/>
|
class="oembed"
|
||||||
|
@click.prevent="linkClicked"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-if="attachment.thumb_url"
|
||||||
|
class="image"
|
||||||
|
>
|
||||||
|
<img :src="attachment.thumb_url">
|
||||||
</div>
|
</div>
|
||||||
<div class="text">
|
<div class="text">
|
||||||
<h1><a :href="attachment.url">{{attachment.oembed.title}}</a></h1>
|
<!-- eslint-disable vue/no-v-html -->
|
||||||
<div v-html="attachment.oembed.oembedHTML"></div>
|
<h1><a :href="attachment.url">{{ attachment.oembed.title }}</a></h1>
|
||||||
|
<div v-html="attachment.oembed.oembedHTML" />
|
||||||
|
<!-- eslint-enabled vue/no-v-html -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,11 +2,11 @@ const debounceMilliseconds = 500
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
query: { // function to query results and return a promise
|
query: { // function to query results and return a promise
|
||||||
type: Function,
|
type: Function,
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
filter: { // function to filter results in real time
|
filter: { // function to filter results in real time
|
||||||
type: Function
|
type: Function
|
||||||
},
|
},
|
||||||
placeholder: {
|
placeholder: {
|
||||||
|
|
|
@ -1,8 +1,22 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="autosuggest" v-click-outside="onClickOutside">
|
<div
|
||||||
<input v-model="term" :placeholder="placeholder" @click="onInputClick" class="autosuggest-input" />
|
v-click-outside="onClickOutside"
|
||||||
<div class="autosuggest-results" v-if="resultsVisible && filtered.length > 0">
|
class="autosuggest"
|
||||||
<slot v-for="item in filtered" :item="item" />
|
>
|
||||||
|
<input
|
||||||
|
v-model="term"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
class="autosuggest-input"
|
||||||
|
@click="onInputClick"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-if="resultsVisible && filtered.length > 0"
|
||||||
|
class="autosuggest-results"
|
||||||
|
>
|
||||||
|
<slot
|
||||||
|
v-for="item in filtered"
|
||||||
|
:item="item"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="avatars">
|
<div class="avatars">
|
||||||
<router-link
|
<router-link
|
||||||
:to="userProfileLink(user)"
|
|
||||||
class="avatars-item"
|
|
||||||
v-for="user in slicedUsers"
|
v-for="user in slicedUsers"
|
||||||
:key="user.id"
|
:key="user.id"
|
||||||
|
:to="userProfileLink(user)"
|
||||||
|
class="avatars-item"
|
||||||
>
|
>
|
||||||
<UserAvatar :user="user" class="avatar-small" />
|
<UserAvatar
|
||||||
|
:user="user"
|
||||||
|
class="avatar-small"
|
||||||
|
/>
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -7,20 +7,45 @@
|
||||||
@click.prevent.native="toggleUserExpanded"
|
@click.prevent.native="toggleUserExpanded"
|
||||||
/>
|
/>
|
||||||
</router-link>
|
</router-link>
|
||||||
<div class="basic-user-card-expanded-content" v-if="userExpanded">
|
<div
|
||||||
<UserCard :user="user" :rounded="true" :bordered="true"/>
|
v-if="userExpanded"
|
||||||
|
class="basic-user-card-expanded-content"
|
||||||
|
>
|
||||||
|
<UserCard
|
||||||
|
:user="user"
|
||||||
|
:rounded="true"
|
||||||
|
:bordered="true"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="basic-user-card-collapsed-content" v-else>
|
<div
|
||||||
<div :title="user.name" class="basic-user-card-user-name">
|
v-else
|
||||||
<span v-if="user.name_html" class="basic-user-card-user-name-value" v-html="user.name_html"></span>
|
class="basic-user-card-collapsed-content"
|
||||||
<span v-else class="basic-user-card-user-name-value">{{ user.name }}</span>
|
>
|
||||||
|
<div
|
||||||
|
:title="user.name"
|
||||||
|
class="basic-user-card-user-name"
|
||||||
|
>
|
||||||
|
<!-- eslint-disable vue/no-v-html -->
|
||||||
|
<span
|
||||||
|
v-if="user.name_html"
|
||||||
|
class="basic-user-card-user-name-value"
|
||||||
|
v-html="user.name_html"
|
||||||
|
/>
|
||||||
|
<!-- eslint-enable vue/no-v-html -->
|
||||||
|
<span
|
||||||
|
v-else
|
||||||
|
class="basic-user-card-user-name-value"
|
||||||
|
>{{ user.name }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<router-link class="basic-user-card-screen-name" :to="userProfileLink(user)">
|
<router-link
|
||||||
@{{user.screen_name}}
|
class="basic-user-card-screen-name"
|
||||||
|
:to="userProfileLink(user)"
|
||||||
|
>
|
||||||
|
@{{ user.screen_name }}
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
<slot></slot>
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
<template>
|
<template>
|
||||||
<basic-user-card :user="user">
|
<basic-user-card :user="user">
|
||||||
<div class="block-card-content-container">
|
<div class="block-card-content-container">
|
||||||
<button class="btn btn-default" @click="unblockUser" :disabled="progress" v-if="blocked">
|
<button
|
||||||
|
v-if="blocked"
|
||||||
|
class="btn btn-default"
|
||||||
|
:disabled="progress"
|
||||||
|
@click="unblockUser"
|
||||||
|
>
|
||||||
<template v-if="progress">
|
<template v-if="progress">
|
||||||
{{ $t('user_card.unblock_progress') }}
|
{{ $t('user_card.unblock_progress') }}
|
||||||
</template>
|
</template>
|
||||||
|
@ -9,7 +14,12 @@
|
||||||
{{ $t('user_card.unblock') }}
|
{{ $t('user_card.unblock') }}
|
||||||
</template>
|
</template>
|
||||||
</button>
|
</button>
|
||||||
<button class="btn btn-default" @click="blockUser" :disabled="progress" v-else>
|
<button
|
||||||
|
v-else
|
||||||
|
class="btn btn-default"
|
||||||
|
:disabled="progress"
|
||||||
|
@click="blockUser"
|
||||||
|
>
|
||||||
<template v-if="progress">
|
<template v-if="progress">
|
||||||
{{ $t('user_card.block_progress') }}
|
{{ $t('user_card.block_progress') }}
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -16,7 +16,7 @@ const chatPanel = {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
submit (message) {
|
submit (message) {
|
||||||
this.$store.state.chat.channel.push('new_msg', {text: message}, 10000)
|
this.$store.state.chat.channel.push('new_msg', { text: message }, 10000)
|
||||||
this.currentMessage = ''
|
this.currentMessage = ''
|
||||||
},
|
},
|
||||||
togglePanel () {
|
togglePanel () {
|
||||||
|
|
|
@ -1,41 +1,70 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="chat-panel" v-if="!this.collapsed || !this.floating">
|
<div
|
||||||
|
v-if="!collapsed || !floating"
|
||||||
|
class="chat-panel"
|
||||||
|
>
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading timeline-heading" :class="{ 'chat-heading': floating }" @click.stop.prevent="togglePanel">
|
<div
|
||||||
|
class="panel-heading timeline-heading"
|
||||||
|
:class="{ 'chat-heading': floating }"
|
||||||
|
@click.stop.prevent="togglePanel"
|
||||||
|
>
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<span>{{$t('chat.title')}}</span>
|
<span>{{ $t('chat.title') }}</span>
|
||||||
<i class="icon-cancel" v-if="floating"></i>
|
<i
|
||||||
|
v-if="floating"
|
||||||
|
class="icon-cancel"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="chat-window" v-chat-scroll>
|
<div
|
||||||
<div class="chat-message" v-for="message in messages" :key="message.id">
|
v-chat-scroll
|
||||||
|
class="chat-window"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-for="message in messages"
|
||||||
|
:key="message.id"
|
||||||
|
class="chat-message"
|
||||||
|
>
|
||||||
<span class="chat-avatar">
|
<span class="chat-avatar">
|
||||||
<img :src="message.author.avatar" />
|
<img :src="message.author.avatar">
|
||||||
</span>
|
</span>
|
||||||
<div class="chat-content">
|
<div class="chat-content">
|
||||||
<router-link
|
<router-link
|
||||||
class="chat-name"
|
class="chat-name"
|
||||||
:to="userProfileLink(message.author)">
|
:to="userProfileLink(message.author)"
|
||||||
{{message.author.username}}
|
>
|
||||||
|
{{ message.author.username }}
|
||||||
</router-link>
|
</router-link>
|
||||||
<br>
|
<br>
|
||||||
<span class="chat-text">
|
<span class="chat-text">
|
||||||
{{message.text}}
|
{{ message.text }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="chat-input">
|
<div class="chat-input">
|
||||||
<textarea @keyup.enter="submit(currentMessage)" v-model="currentMessage" class="chat-input-textarea" rows="1"></textarea>
|
<textarea
|
||||||
|
v-model="currentMessage"
|
||||||
|
class="chat-input-textarea"
|
||||||
|
rows="1"
|
||||||
|
@keyup.enter="submit(currentMessage)"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="chat-panel">
|
<div
|
||||||
|
v-else
|
||||||
|
class="chat-panel"
|
||||||
|
>
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading stub timeline-heading chat-heading" @click.stop.prevent="togglePanel">
|
<div
|
||||||
|
class="panel-heading stub timeline-heading chat-heading"
|
||||||
|
@click.stop.prevent="togglePanel"
|
||||||
|
>
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<i class="icon-comment-empty"></i>
|
<i class="icon-comment-empty" />
|
||||||
{{$t('chat.title')}}
|
{{ $t('chat.title') }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,8 +1,13 @@
|
||||||
<template>
|
<template>
|
||||||
<label class="checkbox">
|
<label class="checkbox">
|
||||||
<input type="checkbox" :checked="checked" @change="$emit('change', $event.target.checked)" :indeterminate.prop="indeterminate">
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
:checked="checked"
|
||||||
|
:indeterminate.prop="indeterminate"
|
||||||
|
@change="$emit('change', $event.target.checked)"
|
||||||
|
>
|
||||||
<i class="checkbox-indicator" />
|
<i class="checkbox-indicator" />
|
||||||
<span v-if="!!$slots.default"><slot></slot></span>
|
<span v-if="!!$slots.default"><slot /></span>
|
||||||
</label>
|
</label>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -1,33 +1,44 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="color-control style-control" :class="{ disabled: !present || disabled }">
|
<div
|
||||||
<label :for="name" class="label">
|
class="color-control style-control"
|
||||||
{{label}}
|
:class="{ disabled: !present || disabled }"
|
||||||
</label>
|
>
|
||||||
<input
|
<label
|
||||||
v-if="typeof fallback !== 'undefined'"
|
:for="name"
|
||||||
class="opt exlcude-disabled"
|
class="label"
|
||||||
:id="name + '-o'"
|
|
||||||
type="checkbox"
|
|
||||||
:checked="present"
|
|
||||||
@input="$emit('input', typeof value === 'undefined' ? fallback : undefined)">
|
|
||||||
<label v-if="typeof fallback !== 'undefined'" class="opt-l" :for="name + '-o'"></label>
|
|
||||||
<input
|
|
||||||
:id="name"
|
|
||||||
class="color-input"
|
|
||||||
type="color"
|
|
||||||
:value="value || fallback"
|
|
||||||
:disabled="!present || disabled"
|
|
||||||
@input="$emit('input', $event.target.value)"
|
|
||||||
>
|
>
|
||||||
<input
|
{{ label }}
|
||||||
:id="name + '-t'"
|
</label>
|
||||||
class="text-input"
|
<input
|
||||||
type="text"
|
v-if="typeof fallback !== 'undefined'"
|
||||||
:value="value || fallback"
|
:id="name + '-o'"
|
||||||
:disabled="!present || disabled"
|
class="opt exlcude-disabled"
|
||||||
@input="$emit('input', $event.target.value)"
|
type="checkbox"
|
||||||
|
:checked="present"
|
||||||
|
@input="$emit('input', typeof value === 'undefined' ? fallback : undefined)"
|
||||||
>
|
>
|
||||||
</div>
|
<label
|
||||||
|
v-if="typeof fallback !== 'undefined'"
|
||||||
|
class="opt-l"
|
||||||
|
:for="name + '-o'"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
:id="name"
|
||||||
|
class="color-input"
|
||||||
|
type="color"
|
||||||
|
:value="value || fallback"
|
||||||
|
:disabled="!present || disabled"
|
||||||
|
@input="$emit('input', $event.target.value)"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
:id="name + '-t'"
|
||||||
|
class="text-input"
|
||||||
|
type="text"
|
||||||
|
:value="value || fallback"
|
||||||
|
:disabled="!present || disabled"
|
||||||
|
@input="$emit('input', $event.target.value)"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
|
@ -1,28 +1,38 @@
|
||||||
<template>
|
<template>
|
||||||
<span v-if="contrast" class="contrast-ratio">
|
<span
|
||||||
<span :title="hint" class="rating">
|
v-if="contrast"
|
||||||
<span v-if="contrast.aaa">
|
class="contrast-ratio"
|
||||||
<i class="icon-thumbs-up-alt"/>
|
>
|
||||||
|
<span
|
||||||
|
:title="hint"
|
||||||
|
class="rating"
|
||||||
|
>
|
||||||
|
<span v-if="contrast.aaa">
|
||||||
|
<i class="icon-thumbs-up-alt" />
|
||||||
|
</span>
|
||||||
|
<span v-if="!contrast.aaa && contrast.aa">
|
||||||
|
<i class="icon-adjust" />
|
||||||
|
</span>
|
||||||
|
<span v-if="!contrast.aaa && !contrast.aa">
|
||||||
|
<i class="icon-attention" />
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<span v-if="!contrast.aaa && contrast.aa">
|
<span
|
||||||
<i class="icon-adjust"/>
|
v-if="contrast && large"
|
||||||
</span>
|
class="rating"
|
||||||
<span v-if="!contrast.aaa && !contrast.aa">
|
:title="hint_18pt"
|
||||||
<i class="icon-attention"/>
|
>
|
||||||
|
<span v-if="contrast.laaa">
|
||||||
|
<i class="icon-thumbs-up-alt" />
|
||||||
|
</span>
|
||||||
|
<span v-if="!contrast.laaa && contrast.laa">
|
||||||
|
<i class="icon-adjust" />
|
||||||
|
</span>
|
||||||
|
<span v-if="!contrast.laaa && !contrast.laa">
|
||||||
|
<i class="icon-attention" />
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<span class="rating" v-if="contrast && large" :title="hint_18pt">
|
|
||||||
<span v-if="contrast.laaa">
|
|
||||||
<i class="icon-thumbs-up-alt"/>
|
|
||||||
</span>
|
|
||||||
<span v-if="!contrast.laaa && contrast.laa">
|
|
||||||
<i class="icon-adjust"/>
|
|
||||||
</span>
|
|
||||||
<span v-if="!contrast.laaa && !contrast.laa">
|
|
||||||
<i class="icon-attention"/>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
<template>
|
<template>
|
||||||
<conversation
|
<conversation
|
||||||
:collapsable="false"
|
:collapsable="false"
|
||||||
isPage="true"
|
is-page="true"
|
||||||
:statusoid="statusoid"
|
:statusoid="statusoid"
|
||||||
></conversation>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./conversation-page.js"></script>
|
<script src="./conversation-page.js"></script>
|
||||||
|
|
|
@ -86,7 +86,8 @@ const conversation = {
|
||||||
},
|
},
|
||||||
replies () {
|
replies () {
|
||||||
let i = 1
|
let i = 1
|
||||||
return reduce(this.conversation, (result, {id, in_reply_to_status_id}) => {
|
// eslint-disable-next-line camelcase
|
||||||
|
return reduce(this.conversation, (result, { id, in_reply_to_status_id }) => {
|
||||||
/* eslint-disable camelcase */
|
/* eslint-disable camelcase */
|
||||||
const irid = in_reply_to_status_id
|
const irid = in_reply_to_status_id
|
||||||
/* eslint-enable camelcase */
|
/* eslint-enable camelcase */
|
||||||
|
@ -119,15 +120,15 @@ const conversation = {
|
||||||
methods: {
|
methods: {
|
||||||
fetchConversation () {
|
fetchConversation () {
|
||||||
if (this.status) {
|
if (this.status) {
|
||||||
this.$store.state.api.backendInteractor.fetchConversation({id: this.status.id})
|
this.$store.state.api.backendInteractor.fetchConversation({ id: this.status.id })
|
||||||
.then(({ancestors, descendants}) => {
|
.then(({ ancestors, descendants }) => {
|
||||||
this.$store.dispatch('addNewStatuses', { statuses: ancestors })
|
this.$store.dispatch('addNewStatuses', { statuses: ancestors })
|
||||||
this.$store.dispatch('addNewStatuses', { statuses: descendants })
|
this.$store.dispatch('addNewStatuses', { statuses: descendants })
|
||||||
})
|
})
|
||||||
.then(() => this.setHighlight(this.statusId))
|
.then(() => this.setHighlight(this.statusId))
|
||||||
} else {
|
} else {
|
||||||
const id = this.$route.params.id
|
const id = this.$route.params.id
|
||||||
this.$store.state.api.backendInteractor.fetchStatus({id})
|
this.$store.state.api.backendInteractor.fetchStatus({ id })
|
||||||
.then((status) => this.$store.dispatch('addNewStatuses', { statuses: [status] }))
|
.then((status) => this.$store.dispatch('addNewStatuses', { statuses: [status] }))
|
||||||
.then(() => this.fetchConversation())
|
.then(() => this.fetchConversation())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,25 +1,34 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="timeline panel-default" :class="[isExpanded ? 'panel' : 'panel-disabled']">
|
<div
|
||||||
<div v-if="isExpanded" class="panel-heading conversation-heading">
|
class="timeline panel-default"
|
||||||
|
:class="[isExpanded ? 'panel' : 'panel-disabled']"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-if="isExpanded"
|
||||||
|
class="panel-heading conversation-heading"
|
||||||
|
>
|
||||||
<span class="title"> {{ $t('timeline.conversation') }} </span>
|
<span class="title"> {{ $t('timeline.conversation') }} </span>
|
||||||
<span v-if="collapsable">
|
<span v-if="collapsable">
|
||||||
<a href="#" @click.prevent="toggleExpanded">{{ $t('timeline.collapse') }}</a>
|
<a
|
||||||
|
href="#"
|
||||||
|
@click.prevent="toggleExpanded"
|
||||||
|
>{{ $t('timeline.collapse') }}</a>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<status
|
<status
|
||||||
v-for="status in conversation"
|
v-for="status in conversation"
|
||||||
@goto="setHighlight"
|
|
||||||
@toggleExpanded="toggleExpanded"
|
|
||||||
:key="status.id"
|
:key="status.id"
|
||||||
:inlineExpanded="collapsable && isExpanded"
|
:inline-expanded="collapsable && isExpanded"
|
||||||
:statusoid="status"
|
:statusoid="status"
|
||||||
:expandable='!isExpanded'
|
:expandable="!isExpanded"
|
||||||
:showPinned="showPinned"
|
:show-pinned="showPinned"
|
||||||
:focused="focused(status.id)"
|
:focused="focused(status.id)"
|
||||||
:inConversation="isExpanded"
|
:in-conversation="isExpanded"
|
||||||
:highlight="getHighlight()"
|
:highlight="getHighlight()"
|
||||||
:replies="getReplies(status.id)"
|
:replies="getReplies(status.id)"
|
||||||
class="status-fadein panel-body"
|
class="status-fadein panel-body"
|
||||||
|
@goto="setHighlight"
|
||||||
|
@toggleExpanded="toggleExpanded"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,16 +1,22 @@
|
||||||
<template>
|
<template>
|
||||||
<span v-bind:class="{ 'dark-overlay': darkOverlay }" @click.self.stop='onCancel()'>
|
<span
|
||||||
<div class="dialog-modal panel panel-default" @click.stop=''>
|
:class="{ 'dark-overlay': darkOverlay }"
|
||||||
|
@click.self.stop="onCancel()"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="dialog-modal panel panel-default"
|
||||||
|
@click.stop=""
|
||||||
|
>
|
||||||
<div class="panel-heading dialog-modal-heading">
|
<div class="panel-heading dialog-modal-heading">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<slot name="header"></slot>
|
<slot name="header" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="dialog-modal-content">
|
<div class="dialog-modal-content">
|
||||||
<slot name="default"></slot>
|
<slot name="default" />
|
||||||
</div>
|
</div>
|
||||||
<div class="dialog-modal-footer user-interactions panel-footer">
|
<div class="dialog-modal-footer user-interactions panel-footer">
|
||||||
<slot name="footer"></slot>
|
<slot name="footer" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
<template>
|
<template>
|
||||||
<Timeline :title="$t('nav.dms')" v-bind:timeline="timeline" v-bind:timeline-name="'dms'"/>
|
<Timeline
|
||||||
|
:title="$t('nav.dms')"
|
||||||
|
:timeline="timeline"
|
||||||
|
:timeline-name="'dms'"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./dm_timeline.js"></script>
|
<script src="./dm_timeline.js"></script>
|
||||||
|
|
|
@ -53,7 +53,7 @@ const EmojiInput = {
|
||||||
required: true,
|
required: true,
|
||||||
type: String
|
type: String
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
input: undefined,
|
input: undefined,
|
||||||
|
|
|
@ -1,27 +1,34 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="emoji-input">
|
<div class="emoji-input">
|
||||||
<slot></slot>
|
<slot />
|
||||||
<div ref="panel" class="autocomplete-panel" :class="{ hide: !showPopup }">
|
<div
|
||||||
<div class="autocomplete-panel-body">
|
ref="panel"
|
||||||
<div
|
class="autocomplete-panel"
|
||||||
v-for="(suggestion, index) in suggestions"
|
:class="{ hide: !showPopup }"
|
||||||
:key="index"
|
>
|
||||||
@click.stop.prevent="onClick($event, suggestion)"
|
<div class="autocomplete-panel-body">
|
||||||
class="autocomplete-item"
|
<div
|
||||||
:class="{ highlighted: suggestion.highlighted }"
|
v-for="(suggestion, index) in suggestions"
|
||||||
|
:key="index"
|
||||||
|
class="autocomplete-item"
|
||||||
|
:class="{ highlighted: suggestion.highlighted }"
|
||||||
|
@click.stop.prevent="onClick($event, suggestion)"
|
||||||
>
|
>
|
||||||
<span class="image">
|
<span class="image">
|
||||||
<img v-if="suggestion.img":src="suggestion.img" />
|
<img
|
||||||
<span v-else>{{suggestion.replacement}}</span>
|
v-if="suggestion.img"
|
||||||
</span>
|
:src="suggestion.img"
|
||||||
<div class="label">
|
>
|
||||||
<span class="displayText">{{suggestion.displayText}}</span>
|
<span v-else>{{ suggestion.replacement }}</span>
|
||||||
<span class="detailText">{{suggestion.detailText}}</span>
|
</span>
|
||||||
|
<div class="label">
|
||||||
|
<span class="displayText">{{ suggestion.displayText }}</span>
|
||||||
|
<span class="detailText">{{ suggestion.detailText }}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./emoji-input.js"></script>
|
<script src="./emoji-input.js"></script>
|
||||||
|
@ -103,7 +110,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
input, textarea {
|
input, textarea {
|
||||||
flex: 1 0 auto;
|
flex: 1 0 auto;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,27 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="import-export-container">
|
<div class="import-export-container">
|
||||||
<slot name="before"/>
|
<slot name="before" />
|
||||||
<button class="btn" @click="exportData">{{ exportLabel }}</button>
|
<button
|
||||||
<button class="btn" @click="importData">{{ importLabel }}</button>
|
class="btn"
|
||||||
<slot name="afterButtons"/>
|
@click="exportData"
|
||||||
<p v-if="importFailed" class="alert error">{{ importFailedText }}</p>
|
>
|
||||||
<slot name="afterError"/>
|
{{ exportLabel }}
|
||||||
</div>
|
</button>
|
||||||
|
<button
|
||||||
|
class="btn"
|
||||||
|
@click="importData"
|
||||||
|
>
|
||||||
|
{{ importLabel }}
|
||||||
|
</button>
|
||||||
|
<slot name="afterButtons" />
|
||||||
|
<p
|
||||||
|
v-if="importFailed"
|
||||||
|
class="alert error"
|
||||||
|
>
|
||||||
|
{{ importFailedText }}
|
||||||
|
</p>
|
||||||
|
<slot name="afterError" />
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
@ -49,7 +64,7 @@ export default {
|
||||||
if (event.target.files[0]) {
|
if (event.target.files[0]) {
|
||||||
// eslint-disable-next-line no-undef
|
// eslint-disable-next-line no-undef
|
||||||
const reader = new FileReader()
|
const reader = new FileReader()
|
||||||
reader.onload = ({target}) => {
|
reader.onload = ({ target }) => {
|
||||||
try {
|
try {
|
||||||
const parsed = JSON.parse(target.result)
|
const parsed = JSON.parse(target.result)
|
||||||
const valid = this.validator(parsed)
|
const valid = this.validator(parsed)
|
||||||
|
|
|
@ -1,10 +1,16 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="exporter">
|
<div class="exporter">
|
||||||
<div v-if="processing">
|
<div v-if="processing">
|
||||||
<i class="icon-spin4 animate-spin exporter-processing"></i>
|
<i class="icon-spin4 animate-spin exporter-processing" />
|
||||||
<span>{{processingMessage}}</span>
|
<span>{{ processingMessage }}</span>
|
||||||
</div>
|
</div>
|
||||||
<button class="btn btn-default" @click="process" v-else>{{exportButtonLabel}}</button>
|
<button
|
||||||
|
v-else
|
||||||
|
class="btn btn-default"
|
||||||
|
@click="process"
|
||||||
|
>
|
||||||
|
{{ exportButtonLabel }}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<Popper
|
<Popper
|
||||||
trigger="click"
|
|
||||||
@hide='showDropDown = false'
|
|
||||||
append-to-body
|
|
||||||
v-if="enabled && showPopper"
|
v-if="enabled && showPopper"
|
||||||
|
trigger="click"
|
||||||
|
append-to-body
|
||||||
:options="{
|
:options="{
|
||||||
placement: 'top',
|
placement: 'top',
|
||||||
modifiers: {
|
modifiers: {
|
||||||
|
@ -11,22 +10,42 @@
|
||||||
offset: { offset: '0, 5px' },
|
offset: { offset: '0, 5px' },
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
|
@hide="showDropDown = false"
|
||||||
>
|
>
|
||||||
<div class="popper-wrapper">
|
<div class="popper-wrapper">
|
||||||
<div class="dropdown-menu">
|
<div class="dropdown-menu">
|
||||||
<button class="dropdown-item dropdown-item-icon" @click.prevent="pinStatus" v-if="!status.pinned && canPin">
|
<button
|
||||||
<i class="icon-pin"></i><span>{{$t("status.pin")}}</span>
|
v-if="!status.pinned && canPin"
|
||||||
|
class="dropdown-item dropdown-item-icon"
|
||||||
|
@click.prevent="pinStatus"
|
||||||
|
>
|
||||||
|
<i class="icon-pin" /><span>{{ $t("status.pin") }}</span>
|
||||||
</button>
|
</button>
|
||||||
<button class="dropdown-item dropdown-item-icon" @click.prevent="unpinStatus" v-if="status.pinned && canPin">
|
<button
|
||||||
<i class="icon-pin"></i><span>{{$t("status.unpin")}}</span>
|
v-if="status.pinned && canPin"
|
||||||
|
class="dropdown-item dropdown-item-icon"
|
||||||
|
@click.prevent="unpinStatus"
|
||||||
|
>
|
||||||
|
<i class="icon-pin" /><span>{{ $t("status.unpin") }}</span>
|
||||||
</button>
|
</button>
|
||||||
<button class="dropdown-item dropdown-item-icon" @click.prevent="deleteStatus" v-if="canDelete">
|
<button
|
||||||
<i class="icon-cancel"></i><span>{{$t("status.delete")}}</span>
|
v-if="canDelete"
|
||||||
|
class="dropdown-item dropdown-item-icon"
|
||||||
|
@click.prevent="deleteStatus"
|
||||||
|
>
|
||||||
|
<i class="icon-cancel" /><span>{{ $t("status.delete") }}</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="button-icon" slot="reference" @click="toggleMenu">
|
<div
|
||||||
<i class='icon-ellipsis' :class="{'icon-clicked': showDropDown}"></i>
|
slot="reference"
|
||||||
|
class="button-icon"
|
||||||
|
@click="toggleMenu"
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
class="icon-ellipsis"
|
||||||
|
:class="{'icon-clicked': showDropDown}"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Popper>
|
</Popper>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -11,9 +11,9 @@ const FavoriteButton = {
|
||||||
methods: {
|
methods: {
|
||||||
favorite () {
|
favorite () {
|
||||||
if (!this.status.favorited) {
|
if (!this.status.favorited) {
|
||||||
this.$store.dispatch('favorite', {id: this.status.id})
|
this.$store.dispatch('favorite', { id: this.status.id })
|
||||||
} else {
|
} else {
|
||||||
this.$store.dispatch('unfavorite', {id: this.status.id})
|
this.$store.dispatch('unfavorite', { id: this.status.id })
|
||||||
}
|
}
|
||||||
this.animated = true
|
this.animated = true
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|
|
@ -1,11 +1,20 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-if="loggedIn">
|
<div v-if="loggedIn">
|
||||||
<i :class='classes' class='button-icon favorite-button fav-active' @click.prevent='favorite()' :title="$t('tool_tip.favorite')"/>
|
<i
|
||||||
<span v-if='!hidePostStatsLocal && status.fave_num > 0'>{{status.fave_num}}</span>
|
:class="classes"
|
||||||
|
class="button-icon favorite-button fav-active"
|
||||||
|
:title="$t('tool_tip.favorite')"
|
||||||
|
@click.prevent="favorite()"
|
||||||
|
/>
|
||||||
|
<span v-if="!hidePostStatsLocal && status.fave_num > 0">{{ status.fave_num }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<i :class='classes' class='button-icon favorite-button' :title="$t('tool_tip.favorite')"/>
|
<i
|
||||||
<span v-if='!hidePostStatsLocal && status.fave_num > 0'>{{status.fave_num}}</span>
|
:class="classes"
|
||||||
|
class="button-icon favorite-button"
|
||||||
|
:title="$t('tool_tip.favorite')"
|
||||||
|
/>
|
||||||
|
<span v-if="!hidePostStatsLocal && status.fave_num > 0">{{ status.fave_num }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -3,17 +3,25 @@
|
||||||
<div class="panel panel-default base01-background">
|
<div class="panel panel-default base01-background">
|
||||||
<div class="panel-heading timeline-heading base02-background base04">
|
<div class="panel-heading timeline-heading base02-background base04">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
{{$t('features_panel.title')}}
|
{{ $t('features_panel.title') }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body features-panel">
|
<div class="panel-body features-panel">
|
||||||
<ul>
|
<ul>
|
||||||
<li v-if="chat">{{$t('features_panel.chat')}}</li>
|
<li v-if="chat">
|
||||||
<li v-if="gopher">{{$t('features_panel.gopher')}}</li>
|
{{ $t('features_panel.chat') }}
|
||||||
<li v-if="whoToFollow">{{$t('features_panel.who_to_follow')}}</li>
|
</li>
|
||||||
<li v-if="mediaProxy">{{$t('features_panel.media_proxy')}}</li>
|
<li v-if="gopher">
|
||||||
<li>{{$t('features_panel.scope_options')}}</li>
|
{{ $t('features_panel.gopher') }}
|
||||||
<li>{{$t('features_panel.text_limit')}} = {{textlimit}}</li>
|
</li>
|
||||||
|
<li v-if="whoToFollow">
|
||||||
|
{{ $t('features_panel.who_to_follow') }}
|
||||||
|
</li>
|
||||||
|
<li v-if="mediaProxy">
|
||||||
|
{{ $t('features_panel.media_proxy') }}
|
||||||
|
</li>
|
||||||
|
<li>{{ $t('features_panel.scope_options') }}</li>
|
||||||
|
<li>{{ $t('features_panel.text_limit') }} = {{ textlimit }}</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,11 +1,17 @@
|
||||||
<template>
|
<template>
|
||||||
<basic-user-card :user="user">
|
<basic-user-card :user="user">
|
||||||
<div class="follow-card-content-container">
|
<div class="follow-card-content-container">
|
||||||
<span class="faint" v-if="!noFollowsYou && user.follows_you">
|
<span
|
||||||
|
v-if="!noFollowsYou && user.follows_you"
|
||||||
|
class="faint"
|
||||||
|
>
|
||||||
{{ isMe ? $t('user_card.its_you') : $t('user_card.follows_you') }}
|
{{ isMe ? $t('user_card.its_you') : $t('user_card.follows_you') }}
|
||||||
</span>
|
</span>
|
||||||
<template v-if="!loggedIn">
|
<template v-if="!loggedIn">
|
||||||
<div class="follow-card-follow-button" v-if="!user.following">
|
<div
|
||||||
|
v-if="!user.following"
|
||||||
|
class="follow-card-follow-button"
|
||||||
|
>
|
||||||
<RemoteFollow :user="user" />
|
<RemoteFollow :user="user" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -13,9 +19,9 @@
|
||||||
<button
|
<button
|
||||||
v-if="!user.following"
|
v-if="!user.following"
|
||||||
class="btn btn-default follow-card-follow-button"
|
class="btn btn-default follow-card-follow-button"
|
||||||
@click="followUser"
|
|
||||||
:disabled="inProgress"
|
:disabled="inProgress"
|
||||||
:title="requestSent ? $t('user_card.follow_again') : ''"
|
:title="requestSent ? $t('user_card.follow_again') : ''"
|
||||||
|
@click="followUser"
|
||||||
>
|
>
|
||||||
<template v-if="inProgress">
|
<template v-if="inProgress">
|
||||||
{{ $t('user_card.follow_progress') }}
|
{{ $t('user_card.follow_progress') }}
|
||||||
|
@ -27,7 +33,12 @@
|
||||||
{{ $t('user_card.follow') }}
|
{{ $t('user_card.follow') }}
|
||||||
</template>
|
</template>
|
||||||
</button>
|
</button>
|
||||||
<button v-else class="btn btn-default follow-card-follow-button pressed" @click="unfollowUser" :disabled="inProgress">
|
<button
|
||||||
|
v-else
|
||||||
|
class="btn btn-default follow-card-follow-button pressed"
|
||||||
|
:disabled="inProgress"
|
||||||
|
@click="unfollowUser"
|
||||||
|
>
|
||||||
<template v-if="inProgress">
|
<template v-if="inProgress">
|
||||||
{{ $t('user_card.follow_progress') }}
|
{{ $t('user_card.follow_progress') }}
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,8 +1,18 @@
|
||||||
<template>
|
<template>
|
||||||
<basic-user-card :user="user">
|
<basic-user-card :user="user">
|
||||||
<div class="follow-request-card-content-container">
|
<div class="follow-request-card-content-container">
|
||||||
<button class="btn btn-default" @click="approveUser">{{ $t('user_card.approve') }}</button>
|
<button
|
||||||
<button class="btn btn-default" @click="denyUser">{{ $t('user_card.deny') }}</button>
|
class="btn btn-default"
|
||||||
|
@click="approveUser"
|
||||||
|
>
|
||||||
|
{{ $t('user_card.approve') }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="btn btn-default"
|
||||||
|
@click="denyUser"
|
||||||
|
>
|
||||||
|
{{ $t('user_card.deny') }}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</basic-user-card>
|
</basic-user-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="settings panel panel-default">
|
<div class="settings panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
{{$t('nav.friend_requests')}}
|
{{ $t('nav.friend_requests') }}
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<FollowRequestCard v-for="request in requests" :key="request.id" :user="request" class="list-item"/>
|
<FollowRequestCard
|
||||||
|
v-for="request in requests"
|
||||||
|
:key="request.id"
|
||||||
|
:user="request"
|
||||||
|
class="list-item"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,35 +1,56 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="font-control style-control" :class="{ custom: isCustom }">
|
<div
|
||||||
<label :for="preset === 'custom' ? name : name + '-font-switcher'" class="label">
|
class="font-control style-control"
|
||||||
{{label}}
|
:class="{ custom: isCustom }"
|
||||||
</label>
|
>
|
||||||
<input
|
<label
|
||||||
v-if="typeof fallback !== 'undefined'"
|
:for="preset === 'custom' ? name : name + '-font-switcher'"
|
||||||
class="opt exlcude-disabled"
|
class="label"
|
||||||
type="checkbox"
|
>
|
||||||
:id="name + '-o'"
|
{{ label }}
|
||||||
:checked="present"
|
</label>
|
||||||
@input="$emit('input', typeof value === 'undefined' ? fallback : undefined)">
|
<input
|
||||||
<label v-if="typeof fallback !== 'undefined'" class="opt-l" :for="name + '-o'"></label>
|
v-if="typeof fallback !== 'undefined'"
|
||||||
<label :for="name + '-font-switcher'" class="select" :disabled="!present">
|
:id="name + '-o'"
|
||||||
<select
|
class="opt exlcude-disabled"
|
||||||
|
type="checkbox"
|
||||||
|
:checked="present"
|
||||||
|
@input="$emit('input', typeof value === 'undefined' ? fallback : undefined)"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
v-if="typeof fallback !== 'undefined'"
|
||||||
|
class="opt-l"
|
||||||
|
:for="name + '-o'"
|
||||||
|
/>
|
||||||
|
<label
|
||||||
|
:for="name + '-font-switcher'"
|
||||||
|
class="select"
|
||||||
:disabled="!present"
|
:disabled="!present"
|
||||||
v-model="preset"
|
>
|
||||||
class="font-switcher"
|
<select
|
||||||
:id="name + '-font-switcher'">
|
:id="name + '-font-switcher'"
|
||||||
<option v-for="option in availableOptions" :value="option">
|
v-model="preset"
|
||||||
{{ option === 'custom' ? $t('settings.style.fonts.custom') : option }}
|
:disabled="!present"
|
||||||
</option>
|
class="font-switcher"
|
||||||
</select>
|
>
|
||||||
<i class="icon-down-open"/>
|
<option
|
||||||
</label>
|
v-for="option in availableOptions"
|
||||||
<input
|
:key="option"
|
||||||
v-if="isCustom"
|
:value="option"
|
||||||
class="custom-font"
|
>
|
||||||
type="text"
|
{{ option === 'custom' ? $t('settings.style.fonts.custom') : option }}
|
||||||
:id="name"
|
</option>
|
||||||
v-model="family">
|
</select>
|
||||||
</div>
|
<i class="icon-down-open" />
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
v-if="isCustom"
|
||||||
|
:id="name"
|
||||||
|
v-model="family"
|
||||||
|
class="custom-font"
|
||||||
|
type="text"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./font_control.js" ></script>
|
<script src="./font_control.js" ></script>
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
<template>
|
<template>
|
||||||
<Timeline :title="$t('nav.timeline')" v-bind:timeline="timeline" v-bind:timeline-name="'friends'"/>
|
<Timeline
|
||||||
|
:title="$t('nav.timeline')"
|
||||||
|
:timeline="timeline"
|
||||||
|
:timeline-name="'friends'"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./friends_timeline.js"></script>
|
<script src="./friends_timeline.js"></script>
|
||||||
|
|
|
@ -1,13 +1,22 @@
|
||||||
<template>
|
<template>
|
||||||
<div ref="galleryContainer" style="width: 100%;">
|
<div
|
||||||
<div class="gallery-row" v-for="row in rows" :style="rowHeight(row.length)" :class="{ 'contain-fit': useContainFit, 'cover-fit': !useContainFit }">
|
ref="galleryContainer"
|
||||||
|
style="width: 100%;"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-for="(row, index) in rows"
|
||||||
|
:key="index"
|
||||||
|
class="gallery-row"
|
||||||
|
:style="rowHeight(row.length)"
|
||||||
|
:class="{ 'contain-fit': useContainFit, 'cover-fit': !useContainFit }"
|
||||||
|
>
|
||||||
<attachment
|
<attachment
|
||||||
v-for="attachment in row"
|
v-for="attachment in row"
|
||||||
:setMedia="setMedia"
|
:key="attachment.id"
|
||||||
|
:set-media="setMedia"
|
||||||
:nsfw="nsfw"
|
:nsfw="nsfw"
|
||||||
:attachment="attachment"
|
:attachment="attachment"
|
||||||
:allowPlay="false"
|
:allow-play="false"
|
||||||
:key="attachment.id"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,20 +2,57 @@
|
||||||
<div class="image-cropper">
|
<div class="image-cropper">
|
||||||
<div v-if="dataUrl">
|
<div v-if="dataUrl">
|
||||||
<div class="image-cropper-image-container">
|
<div class="image-cropper-image-container">
|
||||||
<img ref="img" :src="dataUrl" alt="" @load.stop="createCropper" />
|
<img
|
||||||
|
ref="img"
|
||||||
|
:src="dataUrl"
|
||||||
|
alt=""
|
||||||
|
@load.stop="createCropper"
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="image-cropper-buttons-wrapper">
|
<div class="image-cropper-buttons-wrapper">
|
||||||
<button class="btn" type="button" :disabled="submitting" @click="submit()" v-text="saveText"></button>
|
<button
|
||||||
<button class="btn" type="button" :disabled="submitting" @click="destroy" v-text="cancelText"></button>
|
class="btn"
|
||||||
<button class="btn" type="button" :disabled="submitting" @click="submit(false)" v-text="saveWithoutCroppingText"></button>
|
type="button"
|
||||||
<i class="icon-spin4 animate-spin" v-if="submitting"></i>
|
:disabled="submitting"
|
||||||
|
@click="submit()"
|
||||||
|
v-text="saveText"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
class="btn"
|
||||||
|
type="button"
|
||||||
|
:disabled="submitting"
|
||||||
|
@click="destroy"
|
||||||
|
v-text="cancelText"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
class="btn"
|
||||||
|
type="button"
|
||||||
|
:disabled="submitting"
|
||||||
|
@click="submit(false)"
|
||||||
|
v-text="saveWithoutCroppingText"
|
||||||
|
/>
|
||||||
|
<i
|
||||||
|
v-if="submitting"
|
||||||
|
class="icon-spin4 animate-spin"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="alert error" v-if="submitError">
|
<div
|
||||||
{{submitErrorMsg}}
|
v-if="submitError"
|
||||||
<i class="button-icon icon-cancel" @click="clearError"></i>
|
class="alert error"
|
||||||
|
>
|
||||||
|
{{ submitErrorMsg }}
|
||||||
|
<i
|
||||||
|
class="button-icon icon-cancel"
|
||||||
|
@click="clearError"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<input ref="input" type="file" class="image-cropper-img-input" :accept="mimes">
|
<input
|
||||||
|
ref="input"
|
||||||
|
type="file"
|
||||||
|
class="image-cropper-img-input"
|
||||||
|
:accept="mimes"
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,36 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="importer">
|
<div class="importer">
|
||||||
<form>
|
<form>
|
||||||
<input type="file" ref="input" v-on:change="change" />
|
<input
|
||||||
|
ref="input"
|
||||||
|
type="file"
|
||||||
|
@change="change"
|
||||||
|
>
|
||||||
</form>
|
</form>
|
||||||
<i class="icon-spin4 animate-spin importer-uploading" v-if="submitting"></i>
|
<i
|
||||||
<button class="btn btn-default" v-else @click="submit">{{submitButtonLabel}}</button>
|
v-if="submitting"
|
||||||
|
class="icon-spin4 animate-spin importer-uploading"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
v-else
|
||||||
|
class="btn btn-default"
|
||||||
|
@click="submit"
|
||||||
|
>
|
||||||
|
{{ submitButtonLabel }}
|
||||||
|
</button>
|
||||||
<div v-if="success">
|
<div v-if="success">
|
||||||
<i class="icon-cross" @click="dismiss"></i>
|
<i
|
||||||
<p>{{successMessage}}</p>
|
class="icon-cross"
|
||||||
|
@click="dismiss"
|
||||||
|
/>
|
||||||
|
<p>{{ successMessage }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="error">
|
<div v-else-if="error">
|
||||||
<i class="icon-cross" @click="dismiss"></i>
|
<i
|
||||||
<p>{{errorMessage}}</p>
|
class="icon-cross"
|
||||||
|
@click="dismiss"
|
||||||
|
/>
|
||||||
|
<p>{{ errorMessage }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-if="show" class="instance-specific-panel">
|
<div
|
||||||
|
v-if="show"
|
||||||
|
class="instance-specific-panel"
|
||||||
|
>
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<div v-html="instanceSpecificPanelContent">
|
<!-- eslint-disable vue/no-v-html -->
|
||||||
</div>
|
<div v-html="instanceSpecificPanelContent" />
|
||||||
|
<!-- eslint-enable vue/no-v-html -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -7,18 +7,30 @@
|
||||||
</div>
|
</div>
|
||||||
<tab-switcher
|
<tab-switcher
|
||||||
ref="tabSwitcher"
|
ref="tabSwitcher"
|
||||||
:onSwitch="onModeSwitch"
|
:on-switch="onModeSwitch"
|
||||||
>
|
>
|
||||||
<span data-tab-dummy data-filter="mentions" :label="$t('nav.mentions')"/>
|
<span
|
||||||
<span data-tab-dummy data-filter="likes+repeats" :label="$t('interactions.favs_repeats')"/>
|
data-tab-dummy
|
||||||
<span data-tab-dummy data-filter="follows" :label="$t('interactions.follows')"/>
|
data-filter="mentions"
|
||||||
|
:label="$t('nav.mentions')"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
data-tab-dummy
|
||||||
|
data-filter="likes+repeats"
|
||||||
|
:label="$t('interactions.favs_repeats')"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
data-tab-dummy
|
||||||
|
data-filter="follows"
|
||||||
|
:label="$t('interactions.follows')"
|
||||||
|
/>
|
||||||
</tab-switcher>
|
</tab-switcher>
|
||||||
<Notifications
|
<Notifications
|
||||||
ref="notifications"
|
ref="notifications"
|
||||||
:noHeading="true"
|
:no-heading="true"
|
||||||
:minimalMode="true"
|
:minimal-mode="true"
|
||||||
:filterMode="filterMode"
|
:filter-mode="filterMode"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -3,50 +3,60 @@
|
||||||
<label for="interface-language-switcher">
|
<label for="interface-language-switcher">
|
||||||
{{ $t('settings.interfaceLanguage') }}
|
{{ $t('settings.interfaceLanguage') }}
|
||||||
</label>
|
</label>
|
||||||
<label for="interface-language-switcher" class='select'>
|
<label
|
||||||
<select id="interface-language-switcher" v-model="language">
|
for="interface-language-switcher"
|
||||||
<option v-for="(langCode, i) in languageCodes" :value="langCode">
|
class="select"
|
||||||
|
>
|
||||||
|
<select
|
||||||
|
id="interface-language-switcher"
|
||||||
|
v-model="language"
|
||||||
|
>
|
||||||
|
<option
|
||||||
|
v-for="(langCode, i) in languageCodes"
|
||||||
|
:key="langCode"
|
||||||
|
:value="langCode"
|
||||||
|
>
|
||||||
{{ languageNames[i] }}
|
{{ languageNames[i] }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<i class="icon-down-open"/>
|
<i class="icon-down-open" />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import languagesObject from '../../i18n/messages'
|
import languagesObject from '../../i18n/messages'
|
||||||
import ISO6391 from 'iso-639-1'
|
import ISO6391 from 'iso-639-1'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
computed: {
|
computed: {
|
||||||
languageCodes () {
|
languageCodes () {
|
||||||
return Object.keys(languagesObject)
|
return Object.keys(languagesObject)
|
||||||
},
|
|
||||||
|
|
||||||
languageNames () {
|
|
||||||
return _.map(this.languageCodes, this.getLanguageName)
|
|
||||||
},
|
|
||||||
|
|
||||||
language: {
|
|
||||||
get: function () { return this.$store.state.config.interfaceLanguage },
|
|
||||||
set: function (val) {
|
|
||||||
this.$store.dispatch('setOption', { name: 'interfaceLanguage', value: val })
|
|
||||||
this.$i18n.locale = val
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
languageNames () {
|
||||||
getLanguageName (code) {
|
return _.map(this.languageCodes, this.getLanguageName)
|
||||||
const specialLanguageNames = {
|
},
|
||||||
'ja': 'Japanese (やさしいにほんご)',
|
|
||||||
'ja_pedantic': 'Japanese (日本語)',
|
language: {
|
||||||
'zh': 'Chinese (简体中文)'
|
get: function () { return this.$store.state.config.interfaceLanguage },
|
||||||
}
|
set: function (val) {
|
||||||
return specialLanguageNames[code] || ISO6391.getName(code)
|
this.$store.dispatch('setOption', { name: 'interfaceLanguage', value: val })
|
||||||
|
this.$i18n.locale = val
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
getLanguageName (code) {
|
||||||
|
const specialLanguageNames = {
|
||||||
|
'ja': 'Japanese (やさしいにほんご)',
|
||||||
|
'ja_pedantic': 'Japanese (日本語)',
|
||||||
|
'zh': 'Chinese (简体中文)'
|
||||||
|
}
|
||||||
|
return specialLanguageNames[code] || ISO6391.getName(code)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,13 +1,25 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<a class="link-preview-card" :href="card.url" target="_blank" rel="noopener">
|
<a
|
||||||
<div class="card-image" :class="{ 'small-image': size === 'small' }" v-if="useImage">
|
class="link-preview-card"
|
||||||
<img :src="card.image"></img>
|
:href="card.url"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-if="useImage"
|
||||||
|
class="card-image"
|
||||||
|
:class="{ 'small-image': size === 'small' }"
|
||||||
|
>
|
||||||
|
<img :src="card.image">
|
||||||
</div>
|
</div>
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<span class="card-host faint">{{ card.provider_name }}</span>
|
<span class="card-host faint">{{ card.provider_name }}</span>
|
||||||
<h4 class="card-title">{{ card.title }}</h4>
|
<h4 class="card-title">{{ card.title }}</h4>
|
||||||
<p class="card-description" v-if="useDescription">{{ card.description }}</p>
|
<p
|
||||||
|
v-if="useDescription"
|
||||||
|
class="card-description"
|
||||||
|
>{{ card.description }}</p>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,9 +1,19 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="list">
|
<div class="list">
|
||||||
<div v-for="item in items" class="list-item" :key="getKey(item)">
|
<div
|
||||||
<slot name="item" :item="item" />
|
v-for="item in items"
|
||||||
|
:key="getKey(item)"
|
||||||
|
class="list-item"
|
||||||
|
>
|
||||||
|
<slot
|
||||||
|
name="item"
|
||||||
|
:item="item"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="list-empty-content faint" v-if="items.length === 0 && !!$slots.empty">
|
<div
|
||||||
|
v-if="items.length === 0 && !!$slots.empty"
|
||||||
|
class="list-empty-content faint"
|
||||||
|
>
|
||||||
<slot name="empty" />
|
<slot name="empty" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -58,7 +58,7 @@ const LoginForm = {
|
||||||
).then((result) => {
|
).then((result) => {
|
||||||
if (result.error) {
|
if (result.error) {
|
||||||
if (result.error === 'mfa_required') {
|
if (result.error === 'mfa_required') {
|
||||||
this.requireMFA({app: app, settings: result})
|
this.requireMFA({ app: app, settings: result })
|
||||||
} else {
|
} else {
|
||||||
this.error = result.error
|
this.error = result.error
|
||||||
this.focusOnPasswordInput()
|
this.focusOnPasswordInput()
|
||||||
|
@ -66,7 +66,7 @@ const LoginForm = {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.login(result).then(() => {
|
this.login(result).then(() => {
|
||||||
this.$router.push({name: 'friends'})
|
this.$router.push({ name: 'friends' })
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,53 +1,83 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="login panel panel-default">
|
<div class="login panel panel-default">
|
||||||
<!-- Default panel contents -->
|
<!-- Default panel contents -->
|
||||||
|
|
||||||
<div class="panel-heading">{{$t('login.login')}}</div>
|
<div class="panel-heading">
|
||||||
|
{{ $t('login.login') }}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<form class='login-form' @submit.prevent='submit'>
|
<form
|
||||||
<template v-if="isPasswordAuth">
|
class="login-form"
|
||||||
<div class='form-group'>
|
@submit.prevent="submit"
|
||||||
<label for='username'>{{$t('login.username')}}</label>
|
>
|
||||||
<input :disabled="loggingIn" v-model='user.username'
|
<template v-if="isPasswordAuth">
|
||||||
class='form-control' id='username'
|
<div class="form-group">
|
||||||
:placeholder="$t('login.placeholder')">
|
<label for="username">{{ $t('login.username') }}</label>
|
||||||
</div>
|
<input
|
||||||
<div class='form-group'>
|
id="username"
|
||||||
<label for='password'>{{$t('login.password')}}</label>
|
v-model="user.username"
|
||||||
<input :disabled="loggingIn" v-model='user.password'
|
:disabled="loggingIn"
|
||||||
ref='passwordInput' class='form-control' id='password' type='password'>
|
class="form-control"
|
||||||
</div>
|
:placeholder="$t('login.placeholder')"
|
||||||
</template>
|
>
|
||||||
|
|
||||||
<div class="form-group" v-if="isTokenAuth">
|
|
||||||
<p>{{$t('login.description')}}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class='form-group'>
|
|
||||||
<div class='login-bottom'>
|
|
||||||
<div>
|
|
||||||
<router-link :to="{name: 'registration'}"
|
|
||||||
v-if='registrationOpen'
|
|
||||||
class='register'>
|
|
||||||
{{$t('login.register')}}
|
|
||||||
</router-link>
|
|
||||||
</div>
|
</div>
|
||||||
<button :disabled="loggingIn" type='submit' class='btn btn-default'>
|
<div class="form-group">
|
||||||
{{$t('login.login')}}
|
<label for="password">{{ $t('login.password') }}</label>
|
||||||
</button>
|
<input
|
||||||
</div>
|
id="password"
|
||||||
</div>
|
ref="passwordInput"
|
||||||
</form>
|
v-model="user.password"
|
||||||
</div>
|
:disabled="loggingIn"
|
||||||
|
class="form-control"
|
||||||
|
type="password"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
<div v-if="error" class='form-group'>
|
<div
|
||||||
<div class='alert error'>
|
v-if="isTokenAuth"
|
||||||
{{error}}
|
class="form-group"
|
||||||
<i class="button-icon icon-cancel" @click="clearError"></i>
|
>
|
||||||
|
<p>{{ $t('login.description') }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="login-bottom">
|
||||||
|
<div>
|
||||||
|
<router-link
|
||||||
|
v-if="registrationOpen"
|
||||||
|
:to="{name: 'registration'}"
|
||||||
|
class="register"
|
||||||
|
>
|
||||||
|
{{ $t('login.register') }}
|
||||||
|
</router-link>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
:disabled="loggingIn"
|
||||||
|
type="submit"
|
||||||
|
class="btn btn-default"
|
||||||
|
>
|
||||||
|
{{ $t('login.login') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="error"
|
||||||
|
class="form-group"
|
||||||
|
>
|
||||||
|
<div class="alert error">
|
||||||
|
{{ error }}
|
||||||
|
<i
|
||||||
|
class="button-icon icon-cancel"
|
||||||
|
@click="clearError"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./login_form.js" ></script>
|
<script src="./login_form.js" ></script>
|
||||||
|
|
|
@ -1,25 +1,33 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="modal-view media-modal-view" v-if="showing" @click.prevent="hide">
|
<div
|
||||||
<img class="modal-image" v-if="type === 'image'" :src="currentMedia.url"></img>
|
v-if="showing"
|
||||||
<VideoAttachment
|
class="modal-view media-modal-view"
|
||||||
|
@click.prevent="hide"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
v-if="type === 'image'"
|
||||||
class="modal-image"
|
class="modal-image"
|
||||||
|
:src="currentMedia.url"
|
||||||
|
>
|
||||||
|
<VideoAttachment
|
||||||
v-if="type === 'video'"
|
v-if="type === 'video'"
|
||||||
|
class="modal-image"
|
||||||
:attachment="currentMedia"
|
:attachment="currentMedia"
|
||||||
:controls="true"
|
:controls="true"
|
||||||
@click.stop.native="">
|
@click.stop.native=""
|
||||||
</VideoAttachment>
|
/>
|
||||||
<button
|
<button
|
||||||
|
v-if="canNavigate"
|
||||||
:title="$t('media_modal.previous')"
|
:title="$t('media_modal.previous')"
|
||||||
class="modal-view-button-arrow modal-view-button-arrow--prev"
|
class="modal-view-button-arrow modal-view-button-arrow--prev"
|
||||||
v-if="canNavigate"
|
|
||||||
@click.stop.prevent="goPrev"
|
@click.stop.prevent="goPrev"
|
||||||
>
|
>
|
||||||
<i class="icon-left-open arrow-icon" />
|
<i class="icon-left-open arrow-icon" />
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
|
v-if="canNavigate"
|
||||||
:title="$t('media_modal.next')"
|
:title="$t('media_modal.next')"
|
||||||
class="modal-view-button-arrow modal-view-button-arrow--next"
|
class="modal-view-button-arrow modal-view-button-arrow--next"
|
||||||
v-if="canNavigate"
|
|
||||||
@click.stop.prevent="goNext"
|
@click.stop.prevent="goNext"
|
||||||
>
|
>
|
||||||
<i class="icon-right-open arrow-icon" />
|
<i class="icon-right-open arrow-icon" />
|
||||||
|
|
|
@ -16,7 +16,7 @@ const mediaUpload = {
|
||||||
if (file.size > store.state.instance.uploadlimit) {
|
if (file.size > store.state.instance.uploadlimit) {
|
||||||
const filesize = fileSizeFormatService.fileSizeFormat(file.size)
|
const filesize = fileSizeFormatService.fileSizeFormat(file.size)
|
||||||
const allowedsize = fileSizeFormatService.fileSizeFormat(store.state.instance.uploadlimit)
|
const allowedsize = fileSizeFormatService.fileSizeFormat(store.state.instance.uploadlimit)
|
||||||
self.$emit('upload-failed', 'file_too_big', {filesize: filesize.num, filesizeunit: filesize.unit, allowedsize: allowedsize.num, allowedsizeunit: allowedsize.unit})
|
self.$emit('upload-failed', 'file_too_big', { filesize: filesize.num, filesizeunit: filesize.unit, allowedsize: allowedsize.num, allowedsizeunit: allowedsize.unit })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const formData = new FormData()
|
const formData = new FormData()
|
||||||
|
@ -36,7 +36,7 @@ const mediaUpload = {
|
||||||
},
|
},
|
||||||
fileDrop (e) {
|
fileDrop (e) {
|
||||||
if (e.dataTransfer.files.length > 0) {
|
if (e.dataTransfer.files.length > 0) {
|
||||||
e.preventDefault() // allow dropping text like before
|
e.preventDefault() // allow dropping text like before
|
||||||
this.uploadFile(e.dataTransfer.files[0])
|
this.uploadFile(e.dataTransfer.files[0])
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -54,7 +54,7 @@ const mediaUpload = {
|
||||||
this.uploadReady = true
|
this.uploadReady = true
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
change ({target}) {
|
change ({ target }) {
|
||||||
for (var i = 0; i < target.files.length; i++) {
|
for (var i = 0; i < target.files.length; i++) {
|
||||||
let file = target.files[i]
|
let file = target.files[i]
|
||||||
this.uploadFile(file)
|
this.uploadFile(file)
|
||||||
|
|
|
@ -1,9 +1,29 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="media-upload" @drop.prevent @dragover.prevent="fileDrag" @drop="fileDrop">
|
<div
|
||||||
<label class="btn btn-default" :title="$t('tool_tip.media_upload')">
|
class="media-upload"
|
||||||
<i class="icon-spin4 animate-spin" v-if="uploading"></i>
|
@drop.prevent
|
||||||
<i class="icon-upload" v-if="!uploading"></i>
|
@dragover.prevent="fileDrag"
|
||||||
<input type="file" v-if="uploadReady" @change="change" style="position: fixed; top: -100em" multiple="true"></input>
|
@drop="fileDrop"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="btn btn-default"
|
||||||
|
:title="$t('tool_tip.media_upload')"
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
v-if="uploading"
|
||||||
|
class="icon-spin4 animate-spin"
|
||||||
|
/>
|
||||||
|
<i
|
||||||
|
v-if="!uploading"
|
||||||
|
class="icon-upload"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
v-if="uploadReady"
|
||||||
|
type="file"
|
||||||
|
style="position: fixed; top: -100em"
|
||||||
|
multiple="true"
|
||||||
|
@change="change"
|
||||||
|
>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
<template>
|
<template>
|
||||||
<Timeline :title="$t('nav.interactions')" v-bind:timeline="timeline" v-bind:timeline-name="'mentions'"/>
|
<Timeline
|
||||||
|
:title="$t('nav.interactions')"
|
||||||
|
:timeline="timeline"
|
||||||
|
:timeline-name="'mentions'"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./mentions.js"></script>
|
<script src="./mentions.js"></script>
|
||||||
|
|
|
@ -33,7 +33,7 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.login(result).then(() => {
|
this.login(result).then(() => {
|
||||||
this.$router.push({name: 'friends'})
|
this.$router.push({ name: 'friends' })
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,42 +1,65 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="login panel panel-default">
|
<div class="login panel panel-default">
|
||||||
<!-- Default panel contents -->
|
<!-- Default panel contents -->
|
||||||
|
|
||||||
<div class="panel-heading">{{$t('login.heading.recovery')}}</div>
|
<div class="panel-heading">
|
||||||
|
{{ $t('login.heading.recovery') }}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<form class='login-form' @submit.prevent='submit'>
|
<form
|
||||||
<div class='form-group'>
|
class="login-form"
|
||||||
<label for='code'>{{$t('login.recovery_code')}}</label>
|
@submit.prevent="submit"
|
||||||
<input v-model='code' class='form-control' id='code'>
|
>
|
||||||
</div>
|
<div class="form-group">
|
||||||
|
<label for="code">{{ $t('login.recovery_code') }}</label>
|
||||||
<div class='form-group'>
|
<input
|
||||||
<div class='login-bottom'>
|
id="code"
|
||||||
<div>
|
v-model="code"
|
||||||
<a href="#" @click.prevent="requireTOTP">
|
class="form-control"
|
||||||
{{$t('login.enter_two_factor_code')}}
|
>
|
||||||
</a>
|
|
||||||
<br />
|
|
||||||
<a href="#" @click.prevent="abortMFA">
|
|
||||||
{{$t('general.cancel')}}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<button type='submit' class='btn btn-default'>
|
|
||||||
{{$t('general.verify')}}
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="login-bottom">
|
||||||
|
<div>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
@click.prevent="requireTOTP"
|
||||||
|
>
|
||||||
|
{{ $t('login.enter_two_factor_code') }}
|
||||||
|
</a>
|
||||||
|
<br>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
@click.prevent="abortMFA"
|
||||||
|
>
|
||||||
|
{{ $t('general.cancel') }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
class="btn btn-default"
|
||||||
|
>
|
||||||
|
{{ $t('general.verify') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="error"
|
||||||
|
class="form-group"
|
||||||
|
>
|
||||||
|
<div class="alert error">
|
||||||
|
{{ error }}
|
||||||
|
<i
|
||||||
|
class="button-icon icon-cancel"
|
||||||
|
@click="clearError"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-if="error" class='form-group'>
|
|
||||||
<div class='alert error'>
|
|
||||||
{{error}}
|
|
||||||
<i class="button-icon icon-cancel" @click="clearError"></i>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
<script src="./recovery_form.js" ></script>
|
<script src="./recovery_form.js" ></script>
|
||||||
|
|
|
@ -32,7 +32,7 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.login(result).then(() => {
|
this.login(result).then(() => {
|
||||||
this.$router.push({name: 'friends'})
|
this.$router.push({ name: 'friends' })
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,45 +1,67 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="login panel panel-default">
|
<div class="login panel panel-default">
|
||||||
<!-- Default panel contents -->
|
<!-- Default panel contents -->
|
||||||
|
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
{{$t('login.heading.totp')}}
|
{{ $t('login.heading.totp') }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<form class='login-form' @submit.prevent='submit'>
|
<form
|
||||||
<div class='form-group'>
|
class="login-form"
|
||||||
<label for='code'>
|
@submit.prevent="submit"
|
||||||
{{$t('login.authentication_code')}}
|
>
|
||||||
</label>
|
<div class="form-group">
|
||||||
<input v-model='code' class='form-control' id='code'>
|
<label for="code">
|
||||||
</div>
|
{{ $t('login.authentication_code') }}
|
||||||
|
</label>
|
||||||
<div class='form-group'>
|
<input
|
||||||
<div class='login-bottom'>
|
id="code"
|
||||||
<div>
|
v-model="code"
|
||||||
<a href="#" @click.prevent="requireRecovery">
|
class="form-control"
|
||||||
{{$t('login.enter_recovery_code')}}
|
>
|
||||||
</a>
|
|
||||||
<br />
|
|
||||||
<a href="#" @click.prevent="abortMFA">
|
|
||||||
{{$t('general.cancel')}}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<button type='submit' class='btn btn-default'>
|
|
||||||
{{$t('general.verify')}}
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-if="error" class='form-group'>
|
<div class="form-group">
|
||||||
<div class='alert error'>
|
<div class="login-bottom">
|
||||||
{{error}}
|
<div>
|
||||||
<i class="button-icon icon-cancel" @click="clearError"></i>
|
<a
|
||||||
|
href="#"
|
||||||
|
@click.prevent="requireRecovery"
|
||||||
|
>
|
||||||
|
{{ $t('login.enter_recovery_code') }}
|
||||||
|
</a>
|
||||||
|
<br>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
@click.prevent="abortMFA"
|
||||||
|
>
|
||||||
|
{{ $t('general.cancel') }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
class="btn btn-default"
|
||||||
|
>
|
||||||
|
{{ $t('general.verify') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="error"
|
||||||
|
class="form-group"
|
||||||
|
>
|
||||||
|
<div class="alert error">
|
||||||
|
{{ error }}
|
||||||
|
<i
|
||||||
|
class="button-icon icon-cancel"
|
||||||
|
@click="clearError"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
<script src="./totp_form.js"></script>
|
<script src="./totp_form.js"></script>
|
||||||
|
|
|
@ -1,38 +1,75 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<nav class='nav-bar container' id="nav">
|
<nav
|
||||||
<div class='mobile-inner-nav' @click="scrollToTop()">
|
id="nav"
|
||||||
<div class='item'>
|
class="nav-bar container"
|
||||||
<a href="#" class="mobile-nav-button" @click.stop.prevent="toggleMobileSidebar()">
|
>
|
||||||
<i class="button-icon icon-menu"></i>
|
<div
|
||||||
|
class="mobile-inner-nav"
|
||||||
|
@click="scrollToTop()"
|
||||||
|
>
|
||||||
|
<div class="item">
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
class="mobile-nav-button"
|
||||||
|
@click.stop.prevent="toggleMobileSidebar()"
|
||||||
|
>
|
||||||
|
<i class="button-icon icon-menu" />
|
||||||
</a>
|
</a>
|
||||||
<router-link class="site-name" :to="{ name: 'root' }" active-class="home">{{sitename}}</router-link>
|
<router-link
|
||||||
|
class="site-name"
|
||||||
|
:to="{ name: 'root' }"
|
||||||
|
active-class="home"
|
||||||
|
>
|
||||||
|
{{ sitename }}
|
||||||
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
<div class='item right'>
|
<div class="item right">
|
||||||
<a class="mobile-nav-button" v-if="currentUser" href="#" @click.stop.prevent="openMobileNotifications()">
|
<a
|
||||||
<i class="button-icon icon-bell-alt"></i>
|
v-if="currentUser"
|
||||||
<div class="alert-dot" v-if="unseenNotificationsCount"></div>
|
class="mobile-nav-button"
|
||||||
|
href="#"
|
||||||
|
@click.stop.prevent="openMobileNotifications()"
|
||||||
|
>
|
||||||
|
<i class="button-icon icon-bell-alt" />
|
||||||
|
<div
|
||||||
|
v-if="unseenNotificationsCount"
|
||||||
|
class="alert-dot"
|
||||||
|
/>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<div v-if="currentUser"
|
<div
|
||||||
|
v-if="currentUser"
|
||||||
class="mobile-notifications-drawer"
|
class="mobile-notifications-drawer"
|
||||||
:class="{ 'closed': !notificationsOpen }"
|
:class="{ 'closed': !notificationsOpen }"
|
||||||
@touchstart.stop="notificationsTouchStart"
|
@touchstart.stop="notificationsTouchStart"
|
||||||
@touchmove.stop="notificationsTouchMove"
|
@touchmove.stop="notificationsTouchMove"
|
||||||
>
|
>
|
||||||
<div class="mobile-notifications-header">
|
<div class="mobile-notifications-header">
|
||||||
<span class="title">{{$t('notifications.notifications')}}</span>
|
<span class="title">{{ $t('notifications.notifications') }}</span>
|
||||||
<a class="mobile-nav-button" @click.stop.prevent="closeMobileNotifications()">
|
<a
|
||||||
<i class="button-icon icon-cancel"/>
|
class="mobile-nav-button"
|
||||||
|
@click.stop.prevent="closeMobileNotifications()"
|
||||||
|
>
|
||||||
|
<i class="button-icon icon-cancel" />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="mobile-notifications" @scroll="onScroll">
|
<div
|
||||||
<Notifications ref="notifications" :noHeading="true"/>
|
class="mobile-notifications"
|
||||||
|
@scroll="onScroll"
|
||||||
|
>
|
||||||
|
<Notifications
|
||||||
|
ref="notifications"
|
||||||
|
:no-heading="true"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<SideDrawer ref="sideDrawer" :logout="logout"/>
|
<SideDrawer
|
||||||
|
ref="sideDrawer"
|
||||||
|
:logout="logout"
|
||||||
|
/>
|
||||||
<MobilePostStatusModal />
|
<MobilePostStatusModal />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -96,12 +96,12 @@ const MobilePostStatusModal = {
|
||||||
this.hidden = false
|
this.hidden = false
|
||||||
}
|
}
|
||||||
this.oldScrollPos = window.scrollY
|
this.oldScrollPos = window.scrollY
|
||||||
}, 100, {leading: true, trailing: false}),
|
}, 100, { leading: true, trailing: false }),
|
||||||
|
|
||||||
handleScrollEnd: debounce(function () {
|
handleScrollEnd: debounce(function () {
|
||||||
this.hidden = false
|
this.hidden = false
|
||||||
this.oldScrollPos = window.scrollY
|
this.oldScrollPos = window.scrollY
|
||||||
}, 100, {leading: false, trailing: true})
|
}, 100, { leading: false, trailing: true })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,23 +1,31 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-if="currentUser">
|
<div v-if="currentUser">
|
||||||
<div
|
<div
|
||||||
class="post-form-modal-view modal-view"
|
v-show="postFormOpen"
|
||||||
v-show="postFormOpen"
|
class="post-form-modal-view modal-view"
|
||||||
@click="closePostForm"
|
@click="closePostForm"
|
||||||
>
|
>
|
||||||
<div class="post-form-modal-panel panel" @click.stop="">
|
<div
|
||||||
<div class="panel-heading">{{$t('post_status.new_status')}}</div>
|
class="post-form-modal-panel panel"
|
||||||
<PostStatusForm class="panel-body" @posted="closePostForm" />
|
@click.stop=""
|
||||||
|
>
|
||||||
|
<div class="panel-heading">
|
||||||
|
{{ $t('post_status.new_status') }}
|
||||||
|
</div>
|
||||||
|
<PostStatusForm
|
||||||
|
class="panel-body"
|
||||||
|
@posted="closePostForm"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<button
|
||||||
|
class="new-status-button"
|
||||||
|
:class="{ 'hidden': isHidden }"
|
||||||
|
@click="openPostForm"
|
||||||
|
>
|
||||||
|
<i class="icon-edit" />
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<button
|
|
||||||
class="new-status-button"
|
|
||||||
:class="{ 'hidden': isHidden }"
|
|
||||||
@click="openPostForm"
|
|
||||||
>
|
|
||||||
<i class="icon-edit" />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./mobile_post_status_modal.js"></script>
|
<script src="./mobile_post_status_modal.js"></script>
|
||||||
|
|
|
@ -52,12 +52,12 @@ const ModerationTools = {
|
||||||
if (this.tagsSet.has(tag)) {
|
if (this.tagsSet.has(tag)) {
|
||||||
store.state.api.backendInteractor.untagUser(this.user, tag).then(response => {
|
store.state.api.backendInteractor.untagUser(this.user, tag).then(response => {
|
||||||
if (!response.ok) { return }
|
if (!response.ok) { return }
|
||||||
store.commit('untagUser', {user: this.user, tag})
|
store.commit('untagUser', { user: this.user, tag })
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
store.state.api.backendInteractor.tagUser(this.user, tag).then(response => {
|
store.state.api.backendInteractor.tagUser(this.user, tag).then(response => {
|
||||||
if (!response.ok) { return }
|
if (!response.ok) { return }
|
||||||
store.commit('tagUser', {user: this.user, tag})
|
store.commit('tagUser', { user: this.user, tag })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -66,12 +66,12 @@ const ModerationTools = {
|
||||||
if (this.user.rights[right]) {
|
if (this.user.rights[right]) {
|
||||||
store.state.api.backendInteractor.deleteRight(this.user, right).then(response => {
|
store.state.api.backendInteractor.deleteRight(this.user, right).then(response => {
|
||||||
if (!response.ok) { return }
|
if (!response.ok) { return }
|
||||||
store.commit('updateRight', {user: this.user, right: right, value: false})
|
store.commit('updateRight', { user: this.user, right: right, value: false })
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
store.state.api.backendInteractor.addRight(this.user, right).then(response => {
|
store.state.api.backendInteractor.addRight(this.user, right).then(response => {
|
||||||
if (!response.ok) { return }
|
if (!response.ok) { return }
|
||||||
store.commit('updateRight', {user: this.user, right: right, value: true})
|
store.commit('updateRight', { user: this.user, right: right, value: true })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -80,7 +80,7 @@ const ModerationTools = {
|
||||||
const status = !!this.user.deactivated
|
const status = !!this.user.deactivated
|
||||||
store.state.api.backendInteractor.setActivationStatus(this.user, status).then(response => {
|
store.state.api.backendInteractor.setActivationStatus(this.user, status).then(response => {
|
||||||
if (!response.ok) { return }
|
if (!response.ok) { return }
|
||||||
store.commit('updateActivationStatus', {user: this.user, status: status})
|
store.commit('updateActivationStatus', { user: this.user, status: status })
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
deleteUserDialog (show) {
|
deleteUserDialog (show) {
|
||||||
|
@ -89,7 +89,7 @@ const ModerationTools = {
|
||||||
deleteUser () {
|
deleteUser () {
|
||||||
const store = this.$store
|
const store = this.$store
|
||||||
const user = this.user
|
const user = this.user
|
||||||
const {id, name} = user
|
const { id, name } = user
|
||||||
store.state.api.backendInteractor.deleteUser(user)
|
store.state.api.backendInteractor.deleteUser(user)
|
||||||
.then(e => {
|
.then(e => {
|
||||||
this.$store.dispatch('markStatusesAsDeleted', status => user.id === status.user.id)
|
this.$store.dispatch('markStatusesAsDeleted', status => user.id === status.user.id)
|
||||||
|
|
|
@ -1,85 +1,168 @@
|
||||||
<template>
|
<template>
|
||||||
<div class='block' style='position: relative'>
|
<div
|
||||||
<Popper
|
class="block"
|
||||||
trigger="click"
|
style="position: relative"
|
||||||
@hide='showDropDown = false'
|
>
|
||||||
append-to-body
|
<Popper
|
||||||
:options="{
|
trigger="click"
|
||||||
placement: 'bottom-end',
|
append-to-body
|
||||||
modifiers: {
|
:options="{
|
||||||
arrow: { enabled: true },
|
placement: 'bottom-end',
|
||||||
offset: { offset: '0, 5px' },
|
modifiers: {
|
||||||
}
|
arrow: { enabled: true },
|
||||||
}">
|
offset: { offset: '0, 5px' },
|
||||||
<div class="popper-wrapper">
|
}
|
||||||
<div class="dropdown-menu">
|
}"
|
||||||
<span v-if='user.is_local'>
|
@hide="showDropDown = false"
|
||||||
<button class="dropdown-item" @click='toggleRight("admin")'>
|
>
|
||||||
{{ $t(!!user.rights.admin ? 'user_card.admin_menu.revoke_admin' : 'user_card.admin_menu.grant_admin') }}
|
<div class="popper-wrapper">
|
||||||
|
<div class="dropdown-menu">
|
||||||
|
<span v-if="user.is_local">
|
||||||
|
<button
|
||||||
|
class="dropdown-item"
|
||||||
|
@click="toggleRight("admin")"
|
||||||
|
>
|
||||||
|
{{ $t(!!user.rights.admin ? 'user_card.admin_menu.revoke_admin' : 'user_card.admin_menu.grant_admin') }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="dropdown-item"
|
||||||
|
@click="toggleRight("moderator")"
|
||||||
|
>
|
||||||
|
{{ $t(!!user.rights.moderator ? 'user_card.admin_menu.revoke_moderator' : 'user_card.admin_menu.grant_moderator') }}
|
||||||
|
</button>
|
||||||
|
<div
|
||||||
|
role="separator"
|
||||||
|
class="dropdown-divider"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<button
|
||||||
|
class="dropdown-item"
|
||||||
|
@click="toggleActivationStatus()"
|
||||||
|
>
|
||||||
|
{{ $t(!!user.deactivated ? 'user_card.admin_menu.activate_account' : 'user_card.admin_menu.deactivate_account') }}
|
||||||
</button>
|
</button>
|
||||||
<button class="dropdown-item" @click='toggleRight("moderator")'>
|
<button
|
||||||
{{ $t(!!user.rights.moderator ? 'user_card.admin_menu.revoke_moderator' : 'user_card.admin_menu.grant_moderator') }}
|
class="dropdown-item"
|
||||||
|
@click="deleteUserDialog(true)"
|
||||||
|
>
|
||||||
|
{{ $t('user_card.admin_menu.delete_account') }}
|
||||||
</button>
|
</button>
|
||||||
<div role="separator" class="dropdown-divider"></div>
|
<div
|
||||||
</span>
|
v-if="hasTagPolicy"
|
||||||
<button class="dropdown-item" @click='toggleActivationStatus()'>
|
role="separator"
|
||||||
{{ $t(!!user.deactivated ? 'user_card.admin_menu.activate_account' : 'user_card.admin_menu.deactivate_account') }}
|
class="dropdown-divider"
|
||||||
</button>
|
/>
|
||||||
<button class="dropdown-item" @click='deleteUserDialog(true)'>
|
<span v-if="hasTagPolicy">
|
||||||
{{ $t('user_card.admin_menu.delete_account') }}
|
<button
|
||||||
</button>
|
class="dropdown-item"
|
||||||
<div role="separator" class="dropdown-divider" v-if='hasTagPolicy'></div>
|
@click="toggleTag(tags.FORCE_NSFW)"
|
||||||
<span v-if='hasTagPolicy'>
|
>
|
||||||
<button class="dropdown-item" @click='toggleTag(tags.FORCE_NSFW)'>
|
{{ $t('user_card.admin_menu.force_nsfw') }}
|
||||||
{{ $t('user_card.admin_menu.force_nsfw') }}
|
<span
|
||||||
<span class="menu-checkbox" v-bind:class="{ 'menu-checkbox-checked': hasTag(tags.FORCE_NSFW) }"></span>
|
class="menu-checkbox"
|
||||||
</button>
|
:class="{ 'menu-checkbox-checked': hasTag(tags.FORCE_NSFW) }"
|
||||||
<button class="dropdown-item" @click='toggleTag(tags.STRIP_MEDIA)'>
|
/>
|
||||||
{{ $t('user_card.admin_menu.strip_media') }}
|
</button>
|
||||||
<span class="menu-checkbox" v-bind:class="{ 'menu-checkbox-checked': hasTag(tags.STRIP_MEDIA) }"></span>
|
<button
|
||||||
</button>
|
class="dropdown-item"
|
||||||
<button class="dropdown-item" @click='toggleTag(tags.FORCE_UNLISTED)'>
|
@click="toggleTag(tags.STRIP_MEDIA)"
|
||||||
{{ $t('user_card.admin_menu.force_unlisted') }}
|
>
|
||||||
<span class="menu-checkbox" v-bind:class="{ 'menu-checkbox-checked': hasTag(tags.FORCE_UNLISTED) }"></span>
|
{{ $t('user_card.admin_menu.strip_media') }}
|
||||||
</button>
|
<span
|
||||||
<button class="dropdown-item" @click='toggleTag(tags.SANDBOX)'>
|
class="menu-checkbox"
|
||||||
{{ $t('user_card.admin_menu.sandbox') }}
|
:class="{ 'menu-checkbox-checked': hasTag(tags.STRIP_MEDIA) }"
|
||||||
<span class="menu-checkbox" v-bind:class="{ 'menu-checkbox-checked': hasTag(tags.SANDBOX) }"></span>
|
/>
|
||||||
</button>
|
</button>
|
||||||
<button class="dropdown-item" v-if='user.is_local' @click='toggleTag(tags.DISABLE_REMOTE_SUBSCRIPTION)'>
|
<button
|
||||||
{{ $t('user_card.admin_menu.disable_remote_subscription') }}
|
class="dropdown-item"
|
||||||
<span class="menu-checkbox" v-bind:class="{ 'menu-checkbox-checked': hasTag(tags.DISABLE_REMOTE_SUBSCRIPTION) }"></span>
|
@click="toggleTag(tags.FORCE_UNLISTED)"
|
||||||
</button>
|
>
|
||||||
<button class="dropdown-item" v-if='user.is_local' @click='toggleTag(tags.DISABLE_ANY_SUBSCRIPTION)'>
|
{{ $t('user_card.admin_menu.force_unlisted') }}
|
||||||
{{ $t('user_card.admin_menu.disable_any_subscription') }}
|
<span
|
||||||
<span class="menu-checkbox" v-bind:class="{ 'menu-checkbox-checked': hasTag(tags.DISABLE_ANY_SUBSCRIPTION) }"></span>
|
class="menu-checkbox"
|
||||||
</button>
|
:class="{ 'menu-checkbox-checked': hasTag(tags.FORCE_UNLISTED) }"
|
||||||
<button class="dropdown-item" v-if='user.is_local' @click='toggleTag(tags.QUARANTINE)'>
|
/>
|
||||||
{{ $t('user_card.admin_menu.quarantine') }}
|
</button>
|
||||||
<span class="menu-checkbox" v-bind:class="{ 'menu-checkbox-checked': hasTag(tags.QUARANTINE) }"></span>
|
<button
|
||||||
</button>
|
class="dropdown-item"
|
||||||
</span>
|
@click="toggleTag(tags.SANDBOX)"
|
||||||
|
>
|
||||||
|
{{ $t('user_card.admin_menu.sandbox') }}
|
||||||
|
<span
|
||||||
|
class="menu-checkbox"
|
||||||
|
:class="{ 'menu-checkbox-checked': hasTag(tags.SANDBOX) }"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
v-if="user.is_local"
|
||||||
|
class="dropdown-item"
|
||||||
|
@click="toggleTag(tags.DISABLE_REMOTE_SUBSCRIPTION)"
|
||||||
|
>
|
||||||
|
{{ $t('user_card.admin_menu.disable_remote_subscription') }}
|
||||||
|
<span
|
||||||
|
class="menu-checkbox"
|
||||||
|
:class="{ 'menu-checkbox-checked': hasTag(tags.DISABLE_REMOTE_SUBSCRIPTION) }"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
v-if="user.is_local"
|
||||||
|
class="dropdown-item"
|
||||||
|
@click="toggleTag(tags.DISABLE_ANY_SUBSCRIPTION)"
|
||||||
|
>
|
||||||
|
{{ $t('user_card.admin_menu.disable_any_subscription') }}
|
||||||
|
<span
|
||||||
|
class="menu-checkbox"
|
||||||
|
:class="{ 'menu-checkbox-checked': hasTag(tags.DISABLE_ANY_SUBSCRIPTION) }"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
v-if="user.is_local"
|
||||||
|
class="dropdown-item"
|
||||||
|
@click="toggleTag(tags.QUARANTINE)"
|
||||||
|
>
|
||||||
|
{{ $t('user_card.admin_menu.quarantine') }}
|
||||||
|
<span
|
||||||
|
class="menu-checkbox"
|
||||||
|
:class="{ 'menu-checkbox-checked': hasTag(tags.QUARANTINE) }"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<button
|
||||||
<button slot="reference" v-bind:class="{ pressed: showDropDown }" @click='toggleMenu'>
|
slot="reference"
|
||||||
{{ $t('user_card.admin_menu.moderation') }}
|
:class="{ pressed: showDropDown }"
|
||||||
</button>
|
@click="toggleMenu"
|
||||||
</Popper>
|
>
|
||||||
<portal to="modal">
|
{{ $t('user_card.admin_menu.moderation') }}
|
||||||
<DialogModal v-if="showDeleteUserDialog" :onCancel='deleteUserDialog.bind(this, false)'>
|
</button>
|
||||||
<template slot="header">{{ $t('user_card.admin_menu.delete_user') }}</template>
|
</Popper>
|
||||||
<p>{{ $t('user_card.admin_menu.delete_user_confirmation') }}</p>
|
<portal to="modal">
|
||||||
<template slot="footer">
|
<DialogModal
|
||||||
<button class="btn btn-default" @click='deleteUserDialog(false)'>
|
v-if="showDeleteUserDialog"
|
||||||
{{ $t('general.cancel') }}
|
:on-cancel="deleteUserDialog.bind(this, false)"
|
||||||
</button>
|
>
|
||||||
<button class="btn btn-default danger" @click='deleteUser()'>
|
<template slot="header">
|
||||||
{{ $t('user_card.admin_menu.delete_user') }}
|
{{ $t('user_card.admin_menu.delete_user') }}
|
||||||
</button>
|
</template>
|
||||||
</template>
|
<p>{{ $t('user_card.admin_menu.delete_user_confirmation') }}</p>
|
||||||
</DialogModal>
|
<template slot="footer">
|
||||||
</portal>
|
<button
|
||||||
</div>
|
class="btn btn-default"
|
||||||
|
@click="deleteUserDialog(false)"
|
||||||
|
>
|
||||||
|
{{ $t('general.cancel') }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="btn btn-default danger"
|
||||||
|
@click="deleteUser()"
|
||||||
|
>
|
||||||
|
{{ $t('user_card.admin_menu.delete_user') }}
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
</DialogModal>
|
||||||
|
</portal>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./moderation_tools.js"></script>
|
<script src="./moderation_tools.js"></script>
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
<template>
|
<template>
|
||||||
<basic-user-card :user="user">
|
<basic-user-card :user="user">
|
||||||
<div class="mute-card-content-container">
|
<div class="mute-card-content-container">
|
||||||
<button class="btn btn-default" @click="unmuteUser" :disabled="progress" v-if="muted">
|
<button
|
||||||
|
v-if="muted"
|
||||||
|
class="btn btn-default"
|
||||||
|
:disabled="progress"
|
||||||
|
@click="unmuteUser"
|
||||||
|
>
|
||||||
<template v-if="progress">
|
<template v-if="progress">
|
||||||
{{ $t('user_card.unmute_progress') }}
|
{{ $t('user_card.unmute_progress') }}
|
||||||
</template>
|
</template>
|
||||||
|
@ -9,7 +14,12 @@
|
||||||
{{ $t('user_card.unmute') }}
|
{{ $t('user_card.unmute') }}
|
||||||
</template>
|
</template>
|
||||||
</button>
|
</button>
|
||||||
<button class="btn btn-default" @click="muteUser" :disabled="progress" v-else>
|
<button
|
||||||
|
v-else
|
||||||
|
class="btn btn-default"
|
||||||
|
:disabled="progress"
|
||||||
|
@click="muteUser"
|
||||||
|
>
|
||||||
<template v-if="progress">
|
<template v-if="progress">
|
||||||
{{ $t('user_card.mute_progress') }}
|
{{ $t('user_card.mute_progress') }}
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -2,26 +2,29 @@
|
||||||
<div class="nav-panel">
|
<div class="nav-panel">
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<ul>
|
<ul>
|
||||||
<li v-if='currentUser'>
|
<li v-if="currentUser">
|
||||||
<router-link :to="{ name: 'friends' }">
|
<router-link :to="{ name: 'friends' }">
|
||||||
{{ $t("nav.timeline") }}
|
{{ $t("nav.timeline") }}
|
||||||
</router-link>
|
</router-link>
|
||||||
</li>
|
</li>
|
||||||
<li v-if='currentUser'>
|
<li v-if="currentUser">
|
||||||
<router-link :to="{ name: 'interactions', params: { username: currentUser.screen_name } }">
|
<router-link :to="{ name: 'interactions', params: { username: currentUser.screen_name } }">
|
||||||
{{ $t("nav.interactions") }}
|
{{ $t("nav.interactions") }}
|
||||||
</router-link>
|
</router-link>
|
||||||
</li>
|
</li>
|
||||||
<li v-if='currentUser'>
|
<li v-if="currentUser">
|
||||||
<router-link :to="{ name: 'dms', params: { username: currentUser.screen_name } }">
|
<router-link :to="{ name: 'dms', params: { username: currentUser.screen_name } }">
|
||||||
{{ $t("nav.dms") }}
|
{{ $t("nav.dms") }}
|
||||||
</router-link>
|
</router-link>
|
||||||
</li>
|
</li>
|
||||||
<li v-if='currentUser && currentUser.locked'>
|
<li v-if="currentUser && currentUser.locked">
|
||||||
<router-link :to="{ name: 'friend-requests' }">
|
<router-link :to="{ name: 'friend-requests' }">
|
||||||
{{ $t("nav.friend_requests")}}
|
{{ $t("nav.friend_requests") }}
|
||||||
<span v-if='followRequestCount > 0' class="badge follow-request-count">
|
<span
|
||||||
{{followRequestCount}}
|
v-if="followRequestCount > 0"
|
||||||
|
class="badge follow-request-count"
|
||||||
|
>
|
||||||
|
{{ followRequestCount }}
|
||||||
</span>
|
</span>
|
||||||
</router-link>
|
</router-link>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -3,49 +3,104 @@
|
||||||
v-if="notification.type === 'mention'"
|
v-if="notification.type === 'mention'"
|
||||||
:compact="true"
|
:compact="true"
|
||||||
:statusoid="notification.status"
|
:statusoid="notification.status"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
v-else
|
||||||
|
class="non-mention"
|
||||||
|
:class="[userClass, { highlighted: userStyle }]"
|
||||||
|
:style="[ userStyle ]"
|
||||||
>
|
>
|
||||||
</status>
|
<a
|
||||||
<div class="non-mention" :class="[userClass, { highlighted: userStyle }]" :style="[ userStyle ]" v-else>
|
class="avatar-container"
|
||||||
<a class='avatar-container' :href="notification.from_profile.statusnet_profile_url" @click.stop.prevent.capture="toggleUserExpanded">
|
:href="notification.from_profile.statusnet_profile_url"
|
||||||
<UserAvatar :compact="true" :betterShadow="betterShadow" :user="notification.from_profile"/>
|
@click.stop.prevent.capture="toggleUserExpanded"
|
||||||
|
>
|
||||||
|
<UserAvatar
|
||||||
|
:compact="true"
|
||||||
|
:better-shadow="betterShadow"
|
||||||
|
:user="notification.from_profile"
|
||||||
|
/>
|
||||||
</a>
|
</a>
|
||||||
<div class='notification-right'>
|
<div class="notification-right">
|
||||||
<UserCard :user="getUser(notification)" :rounded="true" :bordered="true" v-if="userExpanded" />
|
<UserCard
|
||||||
|
v-if="userExpanded"
|
||||||
|
:user="getUser(notification)"
|
||||||
|
:rounded="true"
|
||||||
|
:bordered="true"
|
||||||
|
/>
|
||||||
<span class="notification-details">
|
<span class="notification-details">
|
||||||
<div class="name-and-action">
|
<div class="name-and-action">
|
||||||
<span class="username" v-if="!!notification.from_profile.name_html" :title="'@'+notification.from_profile.screen_name" v-html="notification.from_profile.name_html"></span>
|
<!-- eslint-disable vue/no-v-html -->
|
||||||
<span class="username" v-else :title="'@'+notification.from_profile.screen_name">{{ notification.from_profile.name }}</span>
|
<span
|
||||||
|
v-if="!!notification.from_profile.name_html"
|
||||||
|
class="username"
|
||||||
|
:title="'@'+notification.from_profile.screen_name"
|
||||||
|
v-html="notification.from_profile.name_html"
|
||||||
|
/>
|
||||||
|
<!-- eslint-enable vue/no-v-html -->
|
||||||
|
<span
|
||||||
|
v-else
|
||||||
|
class="username"
|
||||||
|
:title="'@'+notification.from_profile.screen_name"
|
||||||
|
>{{ notification.from_profile.name }}</span>
|
||||||
<span v-if="notification.type === 'like'">
|
<span v-if="notification.type === 'like'">
|
||||||
<i class="fa icon-star lit"></i>
|
<i class="fa icon-star lit" />
|
||||||
<small>{{$t('notifications.favorited_you')}}</small>
|
<small>{{ $t('notifications.favorited_you') }}</small>
|
||||||
</span>
|
</span>
|
||||||
<span v-if="notification.type === 'repeat'">
|
<span v-if="notification.type === 'repeat'">
|
||||||
<i class="fa icon-retweet lit" :title="$t('tool_tip.repeat')"></i>
|
<i
|
||||||
<small>{{$t('notifications.repeated_you')}}</small>
|
class="fa icon-retweet lit"
|
||||||
|
:title="$t('tool_tip.repeat')"
|
||||||
|
/>
|
||||||
|
<small>{{ $t('notifications.repeated_you') }}</small>
|
||||||
</span>
|
</span>
|
||||||
<span v-if="notification.type === 'follow'">
|
<span v-if="notification.type === 'follow'">
|
||||||
<i class="fa icon-user-plus lit"></i>
|
<i class="fa icon-user-plus lit" />
|
||||||
<small>{{$t('notifications.followed_you')}}</small>
|
<small>{{ $t('notifications.followed_you') }}</small>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="timeago" v-if="notification.type === 'follow'">
|
<div
|
||||||
|
v-if="notification.type === 'follow'"
|
||||||
|
class="timeago"
|
||||||
|
>
|
||||||
<span class="faint">
|
<span class="faint">
|
||||||
<Timeago :time="notification.created_at" :auto-update="240"></Timeago>
|
<Timeago
|
||||||
|
:time="notification.created_at"
|
||||||
|
:auto-update="240"
|
||||||
|
/>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="timeago" v-else>
|
<div
|
||||||
<router-link v-if="notification.status" :to="{ name: 'conversation', params: { id: notification.status.id } }" class="faint-link">
|
v-else
|
||||||
<Timeago :time="notification.created_at" :auto-update="240"></Timeago>
|
class="timeago"
|
||||||
|
>
|
||||||
|
<router-link
|
||||||
|
v-if="notification.status"
|
||||||
|
:to="{ name: 'conversation', params: { id: notification.status.id } }"
|
||||||
|
class="faint-link"
|
||||||
|
>
|
||||||
|
<Timeago
|
||||||
|
:time="notification.created_at"
|
||||||
|
:auto-update="240"
|
||||||
|
/>
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
</span>
|
</span>
|
||||||
<div class="follow-text" v-if="notification.type === 'follow'">
|
<div
|
||||||
|
v-if="notification.type === 'follow'"
|
||||||
|
class="follow-text"
|
||||||
|
>
|
||||||
<router-link :to="userProfileLink(notification.from_profile)">
|
<router-link :to="userProfileLink(notification.from_profile)">
|
||||||
@{{notification.from_profile.screen_name}}
|
@{{ notification.from_profile.screen_name }}
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<status class="faint" :compact="true" :statusoid="notification.action" :noHeading="true"></status>
|
<status
|
||||||
|
class="faint"
|
||||||
|
:compact="true"
|
||||||
|
:statusoid="notification.action"
|
||||||
|
:no-heading="true"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,33 +1,67 @@
|
||||||
<template>
|
<template>
|
||||||
<div :class="{ minimal: minimalMode }" class="notifications">
|
<div
|
||||||
|
:class="{ minimal: minimalMode }"
|
||||||
|
class="notifications"
|
||||||
|
>
|
||||||
<div :class="mainClass">
|
<div :class="mainClass">
|
||||||
<div v-if="!noHeading" class="panel-heading">
|
<div
|
||||||
|
v-if="!noHeading"
|
||||||
|
class="panel-heading"
|
||||||
|
>
|
||||||
<div class="title">
|
<div class="title">
|
||||||
{{$t('notifications.notifications')}}
|
{{ $t('notifications.notifications') }}
|
||||||
<span class="badge badge-notification unseen-count" v-if="unseenCount">{{unseenCount}}</span>
|
<span
|
||||||
|
v-if="unseenCount"
|
||||||
|
class="badge badge-notification unseen-count"
|
||||||
|
>{{ unseenCount }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div @click.prevent class="loadmore-error alert error" v-if="error">
|
<div
|
||||||
{{$t('timeline.error_fetching')}}
|
v-if="error"
|
||||||
|
class="loadmore-error alert error"
|
||||||
|
@click.prevent
|
||||||
|
>
|
||||||
|
{{ $t('timeline.error_fetching') }}
|
||||||
</div>
|
</div>
|
||||||
<button v-if="unseenCount" @click.prevent="markAsSeen" class="read-button">{{$t('notifications.read')}}</button>
|
<button
|
||||||
|
v-if="unseenCount"
|
||||||
|
class="read-button"
|
||||||
|
@click.prevent="markAsSeen"
|
||||||
|
>
|
||||||
|
{{ $t('notifications.read') }}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<div v-for="notification in visibleNotifications" :key="notification.id" class="notification" :class='{"unseen": !minimalMode && !notification.seen}'>
|
<div
|
||||||
<div class="notification-overlay"></div>
|
v-for="notification in visibleNotifications"
|
||||||
<notification :notification="notification"></notification>
|
:key="notification.id"
|
||||||
|
class="notification"
|
||||||
|
:class="{"unseen": !minimalMode && !notification.seen}"
|
||||||
|
>
|
||||||
|
<div class="notification-overlay" />
|
||||||
|
<notification :notification="notification" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-footer">
|
<div class="panel-footer">
|
||||||
<div v-if="bottomedOut" class="new-status-notification text-center panel-footer faint">
|
<div
|
||||||
{{$t('notifications.no_more_notifications')}}
|
v-if="bottomedOut"
|
||||||
|
class="new-status-notification text-center panel-footer faint"
|
||||||
|
>
|
||||||
|
{{ $t('notifications.no_more_notifications') }}
|
||||||
</div>
|
</div>
|
||||||
<a v-else-if="!loading" href="#" v-on:click.prevent="fetchOlderNotifications()">
|
<a
|
||||||
|
v-else-if="!loading"
|
||||||
|
href="#"
|
||||||
|
@click.prevent="fetchOlderNotifications()"
|
||||||
|
>
|
||||||
<div class="new-status-notification text-center panel-footer">
|
<div class="new-status-notification text-center panel-footer">
|
||||||
{{ minimalMode ? $t('interactions.load_older') : $t('notifications.load_older')}}
|
{{ minimalMode ? $t('interactions.load_older') : $t('notifications.load_older') }}
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
<div v-else class="new-status-notification text-center panel-footer">
|
<div
|
||||||
<i class="icon-spin3 animate-spin"/>
|
v-else
|
||||||
|
class="new-status-notification text-center panel-footer"
|
||||||
|
>
|
||||||
|
<i class="icon-spin3 animate-spin" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,27 +1,39 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="opacity-control style-control" :class="{ disabled: !present || disabled }">
|
<div
|
||||||
<label :for="name" class="label">
|
class="opacity-control style-control"
|
||||||
{{$t('settings.style.common.opacity')}}
|
:class="{ disabled: !present || disabled }"
|
||||||
</label>
|
>
|
||||||
<input
|
<label
|
||||||
v-if="typeof fallback !== 'undefined'"
|
:for="name"
|
||||||
class="opt exclude-disabled"
|
class="label"
|
||||||
:id="name + '-o'"
|
>
|
||||||
type="checkbox"
|
{{ $t('settings.style.common.opacity') }}
|
||||||
:checked="present"
|
</label>
|
||||||
@input="$emit('input', !present ? fallback : undefined)">
|
<input
|
||||||
<label v-if="typeof fallback !== 'undefined'" class="opt-l" :for="name + '-o'"></label>
|
v-if="typeof fallback !== 'undefined'"
|
||||||
<input
|
:id="name + '-o'"
|
||||||
:id="name"
|
class="opt exclude-disabled"
|
||||||
class="input-number"
|
type="checkbox"
|
||||||
type="number"
|
:checked="present"
|
||||||
:value="value || fallback"
|
@input="$emit('input', !present ? fallback : undefined)"
|
||||||
:disabled="!present || disabled"
|
>
|
||||||
@input="$emit('input', $event.target.value)"
|
<label
|
||||||
max="1"
|
v-if="typeof fallback !== 'undefined'"
|
||||||
min="0"
|
class="opt-l"
|
||||||
step=".05">
|
:for="name + '-o'"
|
||||||
</div>
|
/>
|
||||||
|
<input
|
||||||
|
:id="name"
|
||||||
|
class="input-number"
|
||||||
|
type="number"
|
||||||
|
:value="value || fallback"
|
||||||
|
:disabled="!present || disabled"
|
||||||
|
max="1"
|
||||||
|
min="0"
|
||||||
|
step=".05"
|
||||||
|
@input="$emit('input', $event.target.value)"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
|
@ -1,24 +1,33 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="poll" v-bind:class="containerClass">
|
<div
|
||||||
|
class="poll"
|
||||||
|
:class="containerClass"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
class="poll-option"
|
|
||||||
v-for="(option, index) in options"
|
v-for="(option, index) in options"
|
||||||
:key="index"
|
:key="index"
|
||||||
|
class="poll-option"
|
||||||
>
|
>
|
||||||
<div v-if="showResults" :title="resultTitle(option)" class="option-result">
|
<div
|
||||||
|
v-if="showResults"
|
||||||
|
:title="resultTitle(option)"
|
||||||
|
class="option-result"
|
||||||
|
>
|
||||||
<div class="option-result-label">
|
<div class="option-result-label">
|
||||||
<span class="result-percentage">
|
<span class="result-percentage">
|
||||||
{{percentageForOption(option.votes_count)}}%
|
{{ percentageForOption(option.votes_count) }}%
|
||||||
</span>
|
</span>
|
||||||
<span>{{option.title}}</span>
|
<span>{{ option.title }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="result-fill"
|
class="result-fill"
|
||||||
:style="{ 'width': `${percentageForOption(option.votes_count)}%` }"
|
:style="{ 'width': `${percentageForOption(option.votes_count)}%` }"
|
||||||
>
|
/>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div v-else @click="activateOption(index)">
|
<div
|
||||||
|
v-else
|
||||||
|
@click="activateOption(index)"
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
v-if="poll.multiple"
|
v-if="poll.multiple"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
|
@ -32,7 +41,7 @@
|
||||||
:value="index"
|
:value="index"
|
||||||
>
|
>
|
||||||
<label class="option-vote">
|
<label class="option-vote">
|
||||||
<div>{{option.title}}</div>
|
<div>{{ option.title }}</div>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -41,16 +50,20 @@
|
||||||
v-if="!showResults"
|
v-if="!showResults"
|
||||||
class="btn btn-default poll-vote-button"
|
class="btn btn-default poll-vote-button"
|
||||||
type="button"
|
type="button"
|
||||||
@click="vote"
|
|
||||||
:disabled="isDisabled"
|
:disabled="isDisabled"
|
||||||
|
@click="vote"
|
||||||
>
|
>
|
||||||
{{$t('polls.vote')}}
|
{{ $t('polls.vote') }}
|
||||||
</button>
|
</button>
|
||||||
<div class="total">
|
<div class="total">
|
||||||
{{totalVotesCount}} {{ $t("polls.votes") }} ·
|
{{ totalVotesCount }} {{ $t("polls.votes") }} ·
|
||||||
</div>
|
</div>
|
||||||
<i18n :path="expired ? 'polls.expired' : 'polls.expires_in'">
|
<i18n :path="expired ? 'polls.expired' : 'polls.expires_in'">
|
||||||
<Timeago :time="this.expiresAt" :auto-update="60" :now-threshold="0" />
|
<Timeago
|
||||||
|
:time="expiresAt"
|
||||||
|
:auto-update="60"
|
||||||
|
:now-threshold="0"
|
||||||
|
/>
|
||||||
</i18n>
|
</i18n>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,20 +1,33 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="poll-form" v-if="visible">
|
<div
|
||||||
<div class="poll-option" v-for="(option, index) in options" :key="index">
|
v-if="visible"
|
||||||
|
class="poll-form"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-for="(option, index) in options"
|
||||||
|
:key="index"
|
||||||
|
class="poll-option"
|
||||||
|
>
|
||||||
<div class="input-container">
|
<div class="input-container">
|
||||||
<input
|
<input
|
||||||
|
:id="`poll-${index}`"
|
||||||
|
v-model="options[index]"
|
||||||
class="poll-option-input"
|
class="poll-option-input"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('polls.option')"
|
:placeholder="$t('polls.option')"
|
||||||
:maxlength="maxLength"
|
:maxlength="maxLength"
|
||||||
:id="`poll-${index}`"
|
|
||||||
v-model="options[index]"
|
|
||||||
@change="updatePollToParent"
|
@change="updatePollToParent"
|
||||||
@keydown.enter.stop.prevent="nextOption(index)"
|
@keydown.enter.stop.prevent="nextOption(index)"
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="icon-container" v-if="options.length > 2">
|
<div
|
||||||
<i class="icon-cancel" @click="deleteOption(index)"></i>
|
v-if="options.length > 2"
|
||||||
|
class="icon-container"
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
class="icon-cancel"
|
||||||
|
@click="deleteOption(index)"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<a
|
<a
|
||||||
|
@ -26,22 +39,35 @@
|
||||||
{{ $t("polls.add_option") }}
|
{{ $t("polls.add_option") }}
|
||||||
</a>
|
</a>
|
||||||
<div class="poll-type-expiry">
|
<div class="poll-type-expiry">
|
||||||
<div class="poll-type" :title="$t('polls.type')">
|
<div
|
||||||
<label for="poll-type-selector" class="select">
|
class="poll-type"
|
||||||
<select class="select" v-model="pollType" @change="updatePollToParent">
|
:title="$t('polls.type')"
|
||||||
<option value="single">{{$t('polls.single_choice')}}</option>
|
>
|
||||||
<option value="multiple">{{$t('polls.multiple_choices')}}</option>
|
<label
|
||||||
|
for="poll-type-selector"
|
||||||
|
class="select"
|
||||||
|
>
|
||||||
|
<select
|
||||||
|
v-model="pollType"
|
||||||
|
class="select"
|
||||||
|
@change="updatePollToParent"
|
||||||
|
>
|
||||||
|
<option value="single">{{ $t('polls.single_choice') }}</option>
|
||||||
|
<option value="multiple">{{ $t('polls.multiple_choices') }}</option>
|
||||||
</select>
|
</select>
|
||||||
<i class="icon-down-open"/>
|
<i class="icon-down-open" />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="poll-expiry" :title="$t('polls.expiry')">
|
<div
|
||||||
|
class="poll-expiry"
|
||||||
|
:title="$t('polls.expiry')"
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
|
v-model="expiryAmount"
|
||||||
type="number"
|
type="number"
|
||||||
class="expiry-amount hide-number-spinner"
|
class="expiry-amount hide-number-spinner"
|
||||||
:min="minExpirationInCurrentUnit"
|
:min="minExpirationInCurrentUnit"
|
||||||
:max="maxExpirationInCurrentUnit"
|
:max="maxExpirationInCurrentUnit"
|
||||||
v-model="expiryAmount"
|
|
||||||
@change="expiryAmountChange"
|
@change="expiryAmountChange"
|
||||||
>
|
>
|
||||||
<label class="expiry-unit select">
|
<label class="expiry-unit select">
|
||||||
|
@ -49,11 +75,15 @@
|
||||||
v-model="expiryUnit"
|
v-model="expiryUnit"
|
||||||
@change="expiryAmountChange"
|
@change="expiryAmountChange"
|
||||||
>
|
>
|
||||||
<option v-for="unit in expiryUnits" :value="unit">
|
<option
|
||||||
|
v-for="unit in expiryUnits"
|
||||||
|
:key="unit"
|
||||||
|
:value="unit"
|
||||||
|
>
|
||||||
{{ $t(`time.${unit}_short`, ['']) }}
|
{{ $t(`time.${unit}_short`, ['']) }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<i class="icon-down-open"/>
|
<i class="icon-down-open" />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,147 +1,254 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="post-status-form">
|
<div class="post-status-form">
|
||||||
<form @submit.prevent="postStatus(newStatus)" autocomplete="off">
|
<form
|
||||||
<div class="form-group" >
|
autocomplete="off"
|
||||||
<i18n
|
@submit.prevent="postStatus(newStatus)"
|
||||||
v-if="!$store.state.users.currentUser.locked && newStatus.visibility == 'private'"
|
>
|
||||||
path="post_status.account_not_locked_warning"
|
<div class="form-group">
|
||||||
tag="p"
|
<i18n
|
||||||
class="visibility-notice">
|
v-if="!$store.state.users.currentUser.locked && newStatus.visibility == 'private'"
|
||||||
<router-link :to="{ name: 'user-settings' }">{{ $t('post_status.account_not_locked_warning_link') }}</router-link>
|
path="post_status.account_not_locked_warning"
|
||||||
</i18n>
|
tag="p"
|
||||||
<p v-if="!hideScopeNotice && newStatus.visibility === 'public'" class="visibility-notice notice-dismissible">
|
class="visibility-notice"
|
||||||
<span>{{ $t('post_status.scope_notice.public') }}</span>
|
|
||||||
<a v-on:click.prevent="dismissScopeNotice()" class="button-icon dismiss">
|
|
||||||
<i class='icon-cancel'></i>
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
<p v-else-if="!hideScopeNotice && newStatus.visibility === 'unlisted'" class="visibility-notice notice-dismissible">
|
|
||||||
<span>{{ $t('post_status.scope_notice.unlisted') }}</span>
|
|
||||||
<a v-on:click.prevent="dismissScopeNotice()" class="button-icon dismiss">
|
|
||||||
<i class='icon-cancel'></i>
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
<p v-else-if="!hideScopeNotice && newStatus.visibility === 'private' && $store.state.users.currentUser.locked" class="visibility-notice notice-dismissible">
|
|
||||||
<span>{{ $t('post_status.scope_notice.private') }}</span>
|
|
||||||
<a v-on:click.prevent="dismissScopeNotice()" class="button-icon dismiss">
|
|
||||||
<i class='icon-cancel'></i>
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
<p v-else-if="newStatus.visibility === 'direct'" class="visibility-notice">
|
|
||||||
<span v-if="safeDMEnabled">{{ $t('post_status.direct_warning_to_first_only') }}</span>
|
|
||||||
<span v-else>{{ $t('post_status.direct_warning_to_all') }}</span>
|
|
||||||
</p>
|
|
||||||
<EmojiInput
|
|
||||||
v-if="newStatus.spoilerText || alwaysShowSubject"
|
|
||||||
:suggest="emojiSuggestor"
|
|
||||||
v-model="newStatus.spoilerText"
|
|
||||||
class="form-control"
|
|
||||||
>
|
>
|
||||||
<input
|
<router-link :to="{ name: 'user-settings' }">
|
||||||
|
{{ $t('post_status.account_not_locked_warning_link') }}
|
||||||
type="text"
|
</router-link>
|
||||||
:placeholder="$t('post_status.content_warning')"
|
</i18n>
|
||||||
v-model="newStatus.spoilerText"
|
|
||||||
class="form-post-subject"
|
|
||||||
/>
|
|
||||||
</EmojiInput>
|
|
||||||
<EmojiInput
|
|
||||||
:suggest="emojiUserSuggestor"
|
|
||||||
v-model="newStatus.status"
|
|
||||||
class="form-control main-input"
|
|
||||||
>
|
|
||||||
<textarea
|
|
||||||
ref="textarea"
|
|
||||||
v-model="newStatus.status"
|
|
||||||
:placeholder="$t('post_status.default')"
|
|
||||||
rows="1"
|
|
||||||
@keydown.meta.enter="postStatus(newStatus)"
|
|
||||||
@keyup.ctrl.enter="postStatus(newStatus)"
|
|
||||||
@drop="fileDrop"
|
|
||||||
@dragover.prevent="fileDrag"
|
|
||||||
@input="resize"
|
|
||||||
@paste="paste"
|
|
||||||
:disabled="posting"
|
|
||||||
class="form-post-body"
|
|
||||||
>
|
|
||||||
</textarea>
|
|
||||||
<p
|
<p
|
||||||
v-if="hasStatusLengthLimit"
|
v-if="!hideScopeNotice && newStatus.visibility === 'public'"
|
||||||
class="character-counter faint"
|
class="visibility-notice notice-dismissible"
|
||||||
:class="{ error: isOverLengthLimit }"
|
|
||||||
>
|
>
|
||||||
{{ charactersLeft }}
|
<span>{{ $t('post_status.scope_notice.public') }}</span>
|
||||||
|
<a
|
||||||
|
class="button-icon dismiss"
|
||||||
|
@click.prevent="dismissScopeNotice()"
|
||||||
|
>
|
||||||
|
<i class="icon-cancel" />
|
||||||
|
</a>
|
||||||
</p>
|
</p>
|
||||||
</EmojiInput>
|
<p
|
||||||
<div class="visibility-tray">
|
v-else-if="!hideScopeNotice && newStatus.visibility === 'unlisted'"
|
||||||
<scope-selector
|
class="visibility-notice notice-dismissible"
|
||||||
:showAll="showAllScopes"
|
>
|
||||||
:userDefault="userDefaultScope"
|
<span>{{ $t('post_status.scope_notice.unlisted') }}</span>
|
||||||
:originalScope="copyMessageScope"
|
<a
|
||||||
:initialScope="newStatus.visibility"
|
class="button-icon dismiss"
|
||||||
:onScopeChange="changeVis"/>
|
@click.prevent="dismissScopeNotice()"
|
||||||
|
>
|
||||||
|
<i class="icon-cancel" />
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<p
|
||||||
|
v-else-if="!hideScopeNotice && newStatus.visibility === 'private' && $store.state.users.currentUser.locked"
|
||||||
|
class="visibility-notice notice-dismissible"
|
||||||
|
>
|
||||||
|
<span>{{ $t('post_status.scope_notice.private') }}</span>
|
||||||
|
<a
|
||||||
|
class="button-icon dismiss"
|
||||||
|
@click.prevent="dismissScopeNotice()"
|
||||||
|
>
|
||||||
|
<i class="icon-cancel" />
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<p
|
||||||
|
v-else-if="newStatus.visibility === 'direct'"
|
||||||
|
class="visibility-notice"
|
||||||
|
>
|
||||||
|
<span v-if="safeDMEnabled">{{ $t('post_status.direct_warning_to_first_only') }}</span>
|
||||||
|
<span v-else>{{ $t('post_status.direct_warning_to_all') }}</span>
|
||||||
|
</p>
|
||||||
|
<EmojiInput
|
||||||
|
v-if="newStatus.spoilerText || alwaysShowSubject"
|
||||||
|
v-model="newStatus.spoilerText"
|
||||||
|
:suggest="emojiSuggestor"
|
||||||
|
class="form-control"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
|
||||||
<div class="text-format" v-if="postFormats.length > 1">
|
v-model="newStatus.spoilerText"
|
||||||
<label for="post-content-type" class="select">
|
type="text"
|
||||||
<select id="post-content-type" v-model="newStatus.contentType" class="form-control">
|
:placeholder="$t('post_status.content_warning')"
|
||||||
<option v-for="postFormat in postFormats" :key="postFormat" :value="postFormat">
|
class="form-post-subject"
|
||||||
{{$t(`post_status.content_type["${postFormat}"]`)}}
|
>
|
||||||
</option>
|
</EmojiInput>
|
||||||
</select>
|
<EmojiInput
|
||||||
<i class="icon-down-open"></i>
|
v-model="newStatus.status"
|
||||||
</label>
|
:suggest="emojiUserSuggestor"
|
||||||
</div>
|
class="form-control main-input"
|
||||||
<div class="text-format" v-if="postFormats.length === 1 && postFormats[0] !== 'text/plain'">
|
>
|
||||||
<span class="only-format">
|
<textarea
|
||||||
{{$t(`post_status.content_type["${postFormats[0]}"]`)}}
|
ref="textarea"
|
||||||
</span>
|
v-model="newStatus.status"
|
||||||
</div>
|
:placeholder="$t('post_status.default')"
|
||||||
</div>
|
rows="1"
|
||||||
</div>
|
:disabled="posting"
|
||||||
<poll-form
|
class="form-post-body"
|
||||||
ref="pollForm"
|
@keydown.meta.enter="postStatus(newStatus)"
|
||||||
v-if="pollsAvailable"
|
@keyup.ctrl.enter="postStatus(newStatus)"
|
||||||
:visible="pollFormVisible"
|
@drop="fileDrop"
|
||||||
@update-poll="setPoll"
|
@dragover.prevent="fileDrag"
|
||||||
/>
|
@input="resize"
|
||||||
<div class='form-bottom'>
|
@paste="paste"
|
||||||
<div class='form-bottom-left'>
|
/>
|
||||||
<media-upload ref="mediaUpload" @uploading="disableSubmit" @uploaded="addMediaFile" @upload-failed="uploadFailed" :drop-files="dropFiles"></media-upload>
|
<p
|
||||||
<div v-if="pollsAvailable" class="poll-icon">
|
v-if="hasStatusLengthLimit"
|
||||||
<i
|
class="character-counter faint"
|
||||||
:title="$t('polls.add_poll')"
|
:class="{ error: isOverLengthLimit }"
|
||||||
@click="togglePollForm"
|
>
|
||||||
class="icon-chart-bar btn btn-default"
|
{{ charactersLeft }}
|
||||||
:class="pollFormVisible && 'selected'"
|
</p>
|
||||||
|
</EmojiInput>
|
||||||
|
<div class="visibility-tray">
|
||||||
|
<scope-selector
|
||||||
|
:show-all="showAllScopes"
|
||||||
|
:user-default="userDefaultScope"
|
||||||
|
:original-scope="copyMessageScope"
|
||||||
|
:initial-scope="newStatus.visibility"
|
||||||
|
:on-scope-change="changeVis"
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button v-if="posting" disabled class="btn btn-default">{{$t('post_status.posting')}}</button>
|
<div
|
||||||
<button v-else-if="isOverLengthLimit" disabled class="btn btn-default">{{$t('general.submit')}}</button>
|
v-if="postFormats.length > 1"
|
||||||
<button v-else :disabled="submitDisabled" type="submit" class="btn btn-default">{{$t('general.submit')}}</button>
|
class="text-format"
|
||||||
</div>
|
>
|
||||||
<div class='alert error' v-if="error">
|
<label
|
||||||
Error: {{ error }}
|
for="post-content-type"
|
||||||
<i class="button-icon icon-cancel" @click="clearError"></i>
|
class="select"
|
||||||
</div>
|
>
|
||||||
<div class="attachments">
|
<select
|
||||||
<div class="media-upload-wrapper" v-for="file in newStatus.files">
|
id="post-content-type"
|
||||||
<i class="fa button-icon icon-cancel" @click="removeMediaFile(file)"></i>
|
v-model="newStatus.contentType"
|
||||||
<div class="media-upload-container attachment">
|
class="form-control"
|
||||||
<img class="thumbnail media-upload" :src="file.url" v-if="type(file) === 'image'"></img>
|
>
|
||||||
<video v-if="type(file) === 'video'" :src="file.url" controls></video>
|
<option
|
||||||
<audio v-if="type(file) === 'audio'" :src="file.url" controls></audio>
|
v-for="postFormat in postFormats"
|
||||||
<a v-if="type(file) === 'unknown'" :href="file.url">{{file.url}}</a>
|
:key="postFormat"
|
||||||
|
:value="postFormat"
|
||||||
|
>
|
||||||
|
{{ $t(`post_status.content_type["${postFormat}"]`) }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<i class="icon-down-open" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="postFormats.length === 1 && postFormats[0] !== 'text/plain'"
|
||||||
|
class="text-format"
|
||||||
|
>
|
||||||
|
<span class="only-format">
|
||||||
|
{{ $t(`post_status.content_type["${postFormats[0]}"]`) }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<poll-form
|
||||||
<div class="upload_settings" v-if="newStatus.files.length > 0">
|
v-if="pollsAvailable"
|
||||||
<input type="checkbox" id="filesSensitive" v-model="newStatus.nsfw">
|
ref="pollForm"
|
||||||
<label for="filesSensitive">{{$t('post_status.attachments_sensitive')}}</label>
|
:visible="pollFormVisible"
|
||||||
</div>
|
@update-poll="setPoll"
|
||||||
</form>
|
/>
|
||||||
</div>
|
<div class="form-bottom">
|
||||||
|
<div class="form-bottom-left">
|
||||||
|
<media-upload
|
||||||
|
ref="mediaUpload"
|
||||||
|
:drop-files="dropFiles"
|
||||||
|
@uploading="disableSubmit"
|
||||||
|
@uploaded="addMediaFile"
|
||||||
|
@upload-failed="uploadFailed"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
v-if="pollsAvailable"
|
||||||
|
class="poll-icon"
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
:title="$t('polls.add_poll')"
|
||||||
|
class="icon-chart-bar btn btn-default"
|
||||||
|
:class="pollFormVisible && 'selected'"
|
||||||
|
@click="togglePollForm"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
v-if="posting"
|
||||||
|
disabled
|
||||||
|
class="btn btn-default"
|
||||||
|
>
|
||||||
|
{{ $t('post_status.posting') }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
v-else-if="isOverLengthLimit"
|
||||||
|
disabled
|
||||||
|
class="btn btn-default"
|
||||||
|
>
|
||||||
|
{{ $t('general.submit') }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
v-else
|
||||||
|
:disabled="submitDisabled"
|
||||||
|
type="submit"
|
||||||
|
class="btn btn-default"
|
||||||
|
>
|
||||||
|
{{ $t('general.submit') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="error"
|
||||||
|
class="alert error"
|
||||||
|
>
|
||||||
|
Error: {{ error }}
|
||||||
|
<i
|
||||||
|
class="button-icon icon-cancel"
|
||||||
|
@click="clearError"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="attachments">
|
||||||
|
<div
|
||||||
|
v-for="file in newStatus.files"
|
||||||
|
:key="file.url"
|
||||||
|
class="media-upload-wrapper"
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
class="fa button-icon icon-cancel"
|
||||||
|
@click="removeMediaFile(file)"
|
||||||
|
/>
|
||||||
|
<div class="media-upload-container attachment">
|
||||||
|
<img
|
||||||
|
v-if="type(file) === 'image'"
|
||||||
|
class="thumbnail media-upload"
|
||||||
|
:src="file.url"
|
||||||
|
>
|
||||||
|
<video
|
||||||
|
v-if="type(file) === 'video'"
|
||||||
|
:src="file.url"
|
||||||
|
controls
|
||||||
|
/>
|
||||||
|
<audio
|
||||||
|
v-if="type(file) === 'audio'"
|
||||||
|
:src="file.url"
|
||||||
|
controls
|
||||||
|
/>
|
||||||
|
<a
|
||||||
|
v-if="type(file) === 'unknown'"
|
||||||
|
:href="file.url"
|
||||||
|
>{{ file.url }}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="newStatus.files.length > 0"
|
||||||
|
class="upload_settings"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
id="filesSensitive"
|
||||||
|
v-model="newStatus.nsfw"
|
||||||
|
type="checkbox"
|
||||||
|
>
|
||||||
|
<label for="filesSensitive">{{ $t('post_status.attachments_sensitive') }}</label>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./post_status_form.js"></script>
|
<script src="./post_status_form.js"></script>
|
||||||
|
@ -217,7 +324,6 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.error {
|
.error {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<button :disabled="progress || disabled" @click="onClick">
|
<button
|
||||||
|
:disabled="progress || disabled"
|
||||||
|
@click="onClick"
|
||||||
|
>
|
||||||
<template v-if="progress">
|
<template v-if="progress">
|
||||||
<slot name="progress" />
|
<slot name="progress" />
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
<template>
|
<template>
|
||||||
<Timeline :title="$t('nav.twkn')" v-bind:timeline="timeline" v-bind:timeline-name="'publicAndExternal'"/>
|
<Timeline
|
||||||
|
:title="$t('nav.twkn')"
|
||||||
|
:timeline="timeline"
|
||||||
|
:timeline-name="'publicAndExternal'"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./public_and_external_timeline.js"></script>
|
<script src="./public_and_external_timeline.js"></script>
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
<template>
|
<template>
|
||||||
<Timeline :title="$t('nav.public_tl')" v-bind:timeline="timeline" v-bind:timeline-name="'public'"/>
|
<Timeline
|
||||||
|
:title="$t('nav.public_tl')"
|
||||||
|
:timeline="timeline"
|
||||||
|
:timeline-name="'public'"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./public_timeline.js"></script>
|
<script src="./public_timeline.js"></script>
|
||||||
|
|
|
@ -1,37 +1,50 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="range-control style-control" :class="{ disabled: !present || disabled }">
|
<div
|
||||||
<label :for="name" class="label">
|
class="range-control style-control"
|
||||||
{{label}}
|
:class="{ disabled: !present || disabled }"
|
||||||
</label>
|
>
|
||||||
<input
|
<label
|
||||||
v-if="typeof fallback !== 'undefined'"
|
:for="name"
|
||||||
class="opt exclude-disabled"
|
class="label"
|
||||||
:id="name + '-o'"
|
>
|
||||||
type="checkbox"
|
{{ label }}
|
||||||
:checked="present"
|
</label>
|
||||||
@input="$emit('input', !present ? fallback : undefined)">
|
<input
|
||||||
<label v-if="typeof fallback !== 'undefined'" class="opt-l" :for="name + '-o'"></label>
|
v-if="typeof fallback !== 'undefined'"
|
||||||
<input
|
:id="name + '-o'"
|
||||||
:id="name"
|
class="opt exclude-disabled"
|
||||||
class="input-number"
|
type="checkbox"
|
||||||
type="range"
|
:checked="present"
|
||||||
:value="value || fallback"
|
@input="$emit('input', !present ? fallback : undefined)"
|
||||||
:disabled="!present || disabled"
|
>
|
||||||
@input="$emit('input', $event.target.value)"
|
<label
|
||||||
:max="max || hardMax || 100"
|
v-if="typeof fallback !== 'undefined'"
|
||||||
:min="min || hardMin || 0"
|
class="opt-l"
|
||||||
:step="step || 1">
|
:for="name + '-o'"
|
||||||
<input
|
/>
|
||||||
:id="name"
|
<input
|
||||||
class="input-number"
|
:id="name"
|
||||||
type="number"
|
class="input-number"
|
||||||
:value="value || fallback"
|
type="range"
|
||||||
:disabled="!present || disabled"
|
:value="value || fallback"
|
||||||
@input="$emit('input', $event.target.value)"
|
:disabled="!present || disabled"
|
||||||
:max="hardMax"
|
:max="max || hardMax || 100"
|
||||||
:min="hardMin"
|
:min="min || hardMin || 0"
|
||||||
:step="step || 1">
|
:step="step || 1"
|
||||||
</div>
|
@input="$emit('input', $event.target.value)"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
:id="name"
|
||||||
|
class="input-number"
|
||||||
|
type="number"
|
||||||
|
:value="value || fallback"
|
||||||
|
:disabled="!present || disabled"
|
||||||
|
:max="hardMax"
|
||||||
|
:min="hardMin"
|
||||||
|
:step="step || 1"
|
||||||
|
@input="$emit('input', $event.target.value)"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
|
@ -28,7 +28,7 @@ const registration = {
|
||||||
},
|
},
|
||||||
created () {
|
created () {
|
||||||
if ((!this.registrationOpen && !this.token) || this.signedIn) {
|
if ((!this.registrationOpen && !this.token) || this.signedIn) {
|
||||||
this.$router.push({name: 'root'})
|
this.$router.push({ name: 'root' })
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setCaptcha()
|
this.setCaptcha()
|
||||||
|
@ -61,7 +61,7 @@ const registration = {
|
||||||
if (!this.$v.$invalid) {
|
if (!this.$v.$invalid) {
|
||||||
try {
|
try {
|
||||||
await this.signUp(this.user)
|
await this.signUp(this.user)
|
||||||
this.$router.push({name: 'friends'})
|
this.$router.push({ name: 'friends' })
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn('Registration failed: ' + error)
|
console.warn('Registration failed: ' + error)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,109 +1,236 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="settings panel panel-default">
|
<div class="settings panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
{{$t('registration.registration')}}
|
{{ $t('registration.registration') }}
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<form v-on:submit.prevent='submit(user)' class='registration-form'>
|
<form
|
||||||
<div class='container'>
|
class="registration-form"
|
||||||
<div class='text-fields'>
|
@submit.prevent="submit(user)"
|
||||||
<div class='form-group' :class="{ 'form-group--error': $v.user.username.$error }">
|
>
|
||||||
<label class='form--label' for='sign-up-username'>{{$t('login.username')}}</label>
|
<div class="container">
|
||||||
<input :disabled="isPending" v-model.trim='$v.user.username.$model' class='form-control' id='sign-up-username' :placeholder="$t('registration.username_placeholder')">
|
<div class="text-fields">
|
||||||
|
<div
|
||||||
|
class="form-group"
|
||||||
|
:class="{ 'form-group--error': $v.user.username.$error }"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="form--label"
|
||||||
|
for="sign-up-username"
|
||||||
|
>{{ $t('login.username') }}</label>
|
||||||
|
<input
|
||||||
|
id="sign-up-username"
|
||||||
|
v-model.trim="$v.user.username.$model"
|
||||||
|
:disabled="isPending"
|
||||||
|
class="form-control"
|
||||||
|
:placeholder="$t('registration.username_placeholder')"
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-error" v-if="$v.user.username.$dirty">
|
<div
|
||||||
|
v-if="$v.user.username.$dirty"
|
||||||
|
class="form-error"
|
||||||
|
>
|
||||||
<ul>
|
<ul>
|
||||||
<li v-if="!$v.user.username.required">
|
<li v-if="!$v.user.username.required">
|
||||||
<span>{{$t('registration.validations.username_required')}}</span>
|
<span>{{ $t('registration.validations.username_required') }}</span>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class='form-group' :class="{ 'form-group--error': $v.user.fullname.$error }">
|
<div
|
||||||
<label class='form--label' for='sign-up-fullname'>{{$t('registration.fullname')}}</label>
|
class="form-group"
|
||||||
<input :disabled="isPending" v-model.trim='$v.user.fullname.$model' class='form-control' id='sign-up-fullname' :placeholder="$t('registration.fullname_placeholder')">
|
:class="{ 'form-group--error': $v.user.fullname.$error }"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="form--label"
|
||||||
|
for="sign-up-fullname"
|
||||||
|
>{{ $t('registration.fullname') }}</label>
|
||||||
|
<input
|
||||||
|
id="sign-up-fullname"
|
||||||
|
v-model.trim="$v.user.fullname.$model"
|
||||||
|
:disabled="isPending"
|
||||||
|
class="form-control"
|
||||||
|
:placeholder="$t('registration.fullname_placeholder')"
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-error" v-if="$v.user.fullname.$dirty">
|
<div
|
||||||
|
v-if="$v.user.fullname.$dirty"
|
||||||
|
class="form-error"
|
||||||
|
>
|
||||||
<ul>
|
<ul>
|
||||||
<li v-if="!$v.user.fullname.required">
|
<li v-if="!$v.user.fullname.required">
|
||||||
<span>{{$t('registration.validations.fullname_required')}}</span>
|
<span>{{ $t('registration.validations.fullname_required') }}</span>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class='form-group' :class="{ 'form-group--error': $v.user.email.$error }">
|
<div
|
||||||
<label class='form--label' for='email'>{{$t('registration.email')}}</label>
|
class="form-group"
|
||||||
<input :disabled="isPending" v-model='$v.user.email.$model' class='form-control' id='email' type="email">
|
:class="{ 'form-group--error': $v.user.email.$error }"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="form--label"
|
||||||
|
for="email"
|
||||||
|
>{{ $t('registration.email') }}</label>
|
||||||
|
<input
|
||||||
|
id="email"
|
||||||
|
v-model="$v.user.email.$model"
|
||||||
|
:disabled="isPending"
|
||||||
|
class="form-control"
|
||||||
|
type="email"
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-error" v-if="$v.user.email.$dirty">
|
<div
|
||||||
|
v-if="$v.user.email.$dirty"
|
||||||
|
class="form-error"
|
||||||
|
>
|
||||||
<ul>
|
<ul>
|
||||||
<li v-if="!$v.user.email.required">
|
<li v-if="!$v.user.email.required">
|
||||||
<span>{{$t('registration.validations.email_required')}}</span>
|
<span>{{ $t('registration.validations.email_required') }}</span>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class='form-group'>
|
<div class="form-group">
|
||||||
<label class='form--label' for='bio'>{{$t('registration.bio')}} ({{$t('general.optional')}})</label>
|
<label
|
||||||
<textarea :disabled="isPending" v-model='user.bio' class='form-control' id='bio' :placeholder="bioPlaceholder"></textarea>
|
class="form--label"
|
||||||
|
for="bio"
|
||||||
|
>{{ $t('registration.bio') }} ({{ $t('general.optional') }})</label>
|
||||||
|
<textarea
|
||||||
|
id="bio"
|
||||||
|
v-model="user.bio"
|
||||||
|
:disabled="isPending"
|
||||||
|
class="form-control"
|
||||||
|
:placeholder="bioPlaceholder"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class='form-group' :class="{ 'form-group--error': $v.user.password.$error }">
|
<div
|
||||||
<label class='form--label' for='sign-up-password'>{{$t('login.password')}}</label>
|
class="form-group"
|
||||||
<input :disabled="isPending" v-model='user.password' class='form-control' id='sign-up-password' type='password'>
|
:class="{ 'form-group--error': $v.user.password.$error }"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="form--label"
|
||||||
|
for="sign-up-password"
|
||||||
|
>{{ $t('login.password') }}</label>
|
||||||
|
<input
|
||||||
|
id="sign-up-password"
|
||||||
|
v-model="user.password"
|
||||||
|
:disabled="isPending"
|
||||||
|
class="form-control"
|
||||||
|
type="password"
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-error" v-if="$v.user.password.$dirty">
|
<div
|
||||||
|
v-if="$v.user.password.$dirty"
|
||||||
|
class="form-error"
|
||||||
|
>
|
||||||
<ul>
|
<ul>
|
||||||
<li v-if="!$v.user.password.required">
|
<li v-if="!$v.user.password.required">
|
||||||
<span>{{$t('registration.validations.password_required')}}</span>
|
<span>{{ $t('registration.validations.password_required') }}</span>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class='form-group' :class="{ 'form-group--error': $v.user.confirm.$error }">
|
<div
|
||||||
<label class='form--label' for='sign-up-password-confirmation'>{{$t('registration.password_confirm')}}</label>
|
class="form-group"
|
||||||
<input :disabled="isPending" v-model='user.confirm' class='form-control' id='sign-up-password-confirmation' type='password'>
|
:class="{ 'form-group--error': $v.user.confirm.$error }"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="form--label"
|
||||||
|
for="sign-up-password-confirmation"
|
||||||
|
>{{ $t('registration.password_confirm') }}</label>
|
||||||
|
<input
|
||||||
|
id="sign-up-password-confirmation"
|
||||||
|
v-model="user.confirm"
|
||||||
|
:disabled="isPending"
|
||||||
|
class="form-control"
|
||||||
|
type="password"
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-error" v-if="$v.user.confirm.$dirty">
|
<div
|
||||||
|
v-if="$v.user.confirm.$dirty"
|
||||||
|
class="form-error"
|
||||||
|
>
|
||||||
<ul>
|
<ul>
|
||||||
<li v-if="!$v.user.confirm.required">
|
<li v-if="!$v.user.confirm.required">
|
||||||
<span>{{$t('registration.validations.password_confirmation_required')}}</span>
|
<span>{{ $t('registration.validations.password_confirmation_required') }}</span>
|
||||||
</li>
|
</li>
|
||||||
<li v-if="!$v.user.confirm.sameAsPassword">
|
<li v-if="!$v.user.confirm.sameAsPassword">
|
||||||
<span>{{$t('registration.validations.password_confirmation_match')}}</span>
|
<span>{{ $t('registration.validations.password_confirmation_match') }}</span>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group" id="captcha-group" v-if="captcha.type != 'none'">
|
<div
|
||||||
<label class='form--label' for='captcha-label'>{{$t('captcha')}}</label>
|
v-if="captcha.type != 'none'"
|
||||||
|
id="captcha-group"
|
||||||
|
class="form-group"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="form--label"
|
||||||
|
for="captcha-label"
|
||||||
|
>{{ $t('captcha') }}</label>
|
||||||
|
|
||||||
<template v-if="captcha.type == 'kocaptcha'">
|
<template v-if="captcha.type == 'kocaptcha'">
|
||||||
<img v-bind:src="captcha.url" v-on:click="setCaptcha">
|
<img
|
||||||
|
:src="captcha.url"
|
||||||
|
@click="setCaptcha"
|
||||||
|
>
|
||||||
|
|
||||||
<sub>{{$t('registration.new_captcha')}}</sub>
|
<sub>{{ $t('registration.new_captcha') }}</sub>
|
||||||
|
|
||||||
<input :disabled="isPending"
|
<input
|
||||||
v-model='captcha.solution'
|
id="captcha-answer"
|
||||||
class='form-control' id='captcha-answer' type='text' autocomplete="off">
|
v-model="captcha.solution"
|
||||||
|
:disabled="isPending"
|
||||||
|
class="form-control"
|
||||||
|
type="text"
|
||||||
|
autocomplete="off"
|
||||||
|
>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class='form-group' v-if='token' >
|
<div
|
||||||
<label for='token'>{{$t('registration.token')}}</label>
|
v-if="token"
|
||||||
<input disabled='true' v-model='token' class='form-control' id='token' type='text'>
|
class="form-group"
|
||||||
|
>
|
||||||
|
<label for="token">{{ $t('registration.token') }}</label>
|
||||||
|
<input
|
||||||
|
id="token"
|
||||||
|
v-model="token"
|
||||||
|
disabled="true"
|
||||||
|
class="form-control"
|
||||||
|
type="text"
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class='form-group'>
|
<div class="form-group">
|
||||||
<button :disabled="isPending" type='submit' class='btn btn-default'>{{$t('general.submit')}}</button>
|
<button
|
||||||
|
:disabled="isPending"
|
||||||
|
type="submit"
|
||||||
|
class="btn btn-default"
|
||||||
|
>
|
||||||
|
{{ $t('general.submit') }}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class='terms-of-service' v-html="termsOfService">
|
<!-- eslint-disable vue/no-v-html -->
|
||||||
</div>
|
<div
|
||||||
|
class="terms-of-service"
|
||||||
|
v-html="termsOfService"
|
||||||
|
/>
|
||||||
|
<!-- eslint-enable vue/no-v-html -->
|
||||||
</div>
|
</div>
|
||||||
<div v-if="serverValidationErrors.length" class='form-group'>
|
<div
|
||||||
<div class='alert error'>
|
v-if="serverValidationErrors.length"
|
||||||
<span v-for="error in serverValidationErrors">{{error}}</span>
|
class="form-group"
|
||||||
|
>
|
||||||
|
<div class="alert error">
|
||||||
|
<span
|
||||||
|
v-for="error in serverValidationErrors"
|
||||||
|
:key="error"
|
||||||
|
>{{ error }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -1,9 +1,23 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="remote-follow">
|
<div class="remote-follow">
|
||||||
<form method="POST" :action='subscribeUrl'>
|
<form
|
||||||
<input type="hidden" name="nickname" :value="user.screen_name">
|
method="POST"
|
||||||
<input type="hidden" name="profile" value="">
|
:action="subscribeUrl"
|
||||||
<button click="submit" class="remote-button">
|
>
|
||||||
|
<input
|
||||||
|
type="hidden"
|
||||||
|
name="nickname"
|
||||||
|
:value="user.screen_name"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
type="hidden"
|
||||||
|
name="profile"
|
||||||
|
value=""
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
click="submit"
|
||||||
|
class="remote-button"
|
||||||
|
>
|
||||||
{{ $t('user_card.remote_follow') }}
|
{{ $t('user_card.remote_follow') }}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -11,9 +11,9 @@ const RetweetButton = {
|
||||||
methods: {
|
methods: {
|
||||||
retweet () {
|
retweet () {
|
||||||
if (!this.status.repeated) {
|
if (!this.status.repeated) {
|
||||||
this.$store.dispatch('retweet', {id: this.status.id})
|
this.$store.dispatch('retweet', { id: this.status.id })
|
||||||
} else {
|
} else {
|
||||||
this.$store.dispatch('unretweet', {id: this.status.id})
|
this.$store.dispatch('unretweet', { id: this.status.id })
|
||||||
}
|
}
|
||||||
this.animated = true
|
this.animated = true
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|
|
@ -1,16 +1,29 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-if="loggedIn">
|
<div v-if="loggedIn">
|
||||||
<template v-if="visibility !== 'private' && visibility !== 'direct'">
|
<template v-if="visibility !== 'private' && visibility !== 'direct'">
|
||||||
<i :class='classes' class='button-icon retweet-button icon-retweet rt-active' v-on:click.prevent='retweet()' :title="$t('tool_tip.repeat')"></i>
|
<i
|
||||||
<span v-if='!hidePostStatsLocal && status.repeat_num > 0'>{{status.repeat_num}}</span>
|
:class="classes"
|
||||||
|
class="button-icon retweet-button icon-retweet rt-active"
|
||||||
|
:title="$t('tool_tip.repeat')"
|
||||||
|
@click.prevent="retweet()"
|
||||||
|
/>
|
||||||
|
<span v-if="!hidePostStatsLocal && status.repeat_num > 0">{{ status.repeat_num }}</span>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<i :class='classes' class='button-icon icon-lock' :title="$t('timeline.no_retweet_hint')"></i>
|
<i
|
||||||
|
:class="classes"
|
||||||
|
class="button-icon icon-lock"
|
||||||
|
:title="$t('timeline.no_retweet_hint')"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="!loggedIn">
|
<div v-else-if="!loggedIn">
|
||||||
<i :class='classes' class='button-icon icon-retweet' :title="$t('tool_tip.repeat')"></i>
|
<i
|
||||||
<span v-if='!hidePostStatsLocal && status.repeat_num > 0'>{{status.repeat_num}}</span>
|
:class="classes"
|
||||||
|
class="button-icon icon-retweet"
|
||||||
|
:title="$t('tool_tip.repeat')"
|
||||||
|
/>
|
||||||
|
<span v-if="!hidePostStatsLocal && status.repeat_num > 0">{{ status.repeat_num }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -29,10 +29,10 @@ const ScopeSelector = {
|
||||||
},
|
},
|
||||||
css () {
|
css () {
|
||||||
return {
|
return {
|
||||||
public: {selected: this.currentScope === 'public'},
|
public: { selected: this.currentScope === 'public' },
|
||||||
unlisted: {selected: this.currentScope === 'unlisted'},
|
unlisted: { selected: this.currentScope === 'unlisted' },
|
||||||
private: {selected: this.currentScope === 'private'},
|
private: { selected: this.currentScope === 'private' },
|
||||||
direct: {selected: this.currentScope === 'direct'}
|
direct: { selected: this.currentScope === 'direct' }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,30 +1,37 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-if="!showNothing" class="scope-selector">
|
<div
|
||||||
<i class="icon-mail-alt"
|
v-if="!showNothing"
|
||||||
:class="css.direct"
|
class="scope-selector"
|
||||||
:title="$t('post_status.scope.direct')"
|
>
|
||||||
v-if="showDirect"
|
<i
|
||||||
@click="changeVis('direct')">
|
v-if="showDirect"
|
||||||
</i>
|
class="icon-mail-alt"
|
||||||
<i class="icon-lock"
|
:class="css.direct"
|
||||||
:class="css.private"
|
:title="$t('post_status.scope.direct')"
|
||||||
:title="$t('post_status.scope.private')"
|
@click="changeVis('direct')"
|
||||||
v-if="showPrivate"
|
/>
|
||||||
v-on:click="changeVis('private')">
|
<i
|
||||||
</i>
|
v-if="showPrivate"
|
||||||
<i class="icon-lock-open-alt"
|
class="icon-lock"
|
||||||
:class="css.unlisted"
|
:class="css.private"
|
||||||
:title="$t('post_status.scope.unlisted')"
|
:title="$t('post_status.scope.private')"
|
||||||
v-if="showUnlisted"
|
@click="changeVis('private')"
|
||||||
@click="changeVis('unlisted')">
|
/>
|
||||||
</i>
|
<i
|
||||||
<i class="icon-globe"
|
v-if="showUnlisted"
|
||||||
:class="css.public"
|
class="icon-lock-open-alt"
|
||||||
:title="$t('post_status.scope.public')"
|
:class="css.unlisted"
|
||||||
v-if="showPublic"
|
:title="$t('post_status.scope.unlisted')"
|
||||||
@click="changeVis('public')">
|
@click="changeVis('unlisted')"
|
||||||
</i>
|
/>
|
||||||
</div>
|
<i
|
||||||
|
v-if="showPublic"
|
||||||
|
class="icon-globe"
|
||||||
|
:class="css.public"
|
||||||
|
:title="$t('post_status.scope.public')"
|
||||||
|
@click="changeVis('public')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./scope_selector.js"></script>
|
<script src="./scope_selector.js"></script>
|
||||||
|
|
|
@ -1,23 +1,52 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="selectable-list">
|
<div class="selectable-list">
|
||||||
<div class="selectable-list-header" v-if="items.length > 0">
|
<div
|
||||||
|
v-if="items.length > 0"
|
||||||
|
class="selectable-list-header"
|
||||||
|
>
|
||||||
<div class="selectable-list-checkbox-wrapper">
|
<div class="selectable-list-checkbox-wrapper">
|
||||||
<Checkbox :checked="allSelected" @change="toggleAll" :indeterminate="someSelected">{{ $t('selectable_list.select_all') }}</Checkbox>
|
<Checkbox
|
||||||
|
:checked="allSelected"
|
||||||
|
:indeterminate="someSelected"
|
||||||
|
@change="toggleAll"
|
||||||
|
>
|
||||||
|
{{ $t('selectable_list.select_all') }}
|
||||||
|
</Checkbox>
|
||||||
</div>
|
</div>
|
||||||
<div class="selectable-list-header-actions">
|
<div class="selectable-list-header-actions">
|
||||||
<slot name="header" :selected="filteredSelected" />
|
<slot
|
||||||
|
name="header"
|
||||||
|
:selected="filteredSelected"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<List :items="items" :getKey="getKey">
|
<List
|
||||||
<template slot="item" slot-scope="{item}">
|
:items="items"
|
||||||
<div class="selectable-list-item-inner" :class="{ 'selectable-list-item-selected-inner': isSelected(item) }">
|
:get-key="getKey"
|
||||||
|
>
|
||||||
|
<template
|
||||||
|
slot="item"
|
||||||
|
slot-scope="{item}"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="selectable-list-item-inner"
|
||||||
|
:class="{ 'selectable-list-item-selected-inner': isSelected(item) }"
|
||||||
|
>
|
||||||
<div class="selectable-list-checkbox-wrapper">
|
<div class="selectable-list-checkbox-wrapper">
|
||||||
<Checkbox :checked="isSelected(item)" @change="checked => toggle(checked, item)" />
|
<Checkbox
|
||||||
|
:checked="isSelected(item)"
|
||||||
|
@change="checked => toggle(checked, item)"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<slot name="item" :item="item" />
|
<slot
|
||||||
|
name="item"
|
||||||
|
:item="item"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template slot="empty"><slot name="empty" /></template>
|
<template slot="empty">
|
||||||
|
<slot name="empty" />
|
||||||
|
</template>
|
||||||
</List>
|
</List>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,304 +1,482 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="settings panel panel-default">
|
<div class="settings panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
{{$t('settings.settings')}}
|
{{ $t('settings.settings') }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<transition name="fade">
|
||||||
|
<template v-if="currentSaveStateNotice">
|
||||||
|
<div
|
||||||
|
v-if="currentSaveStateNotice.error"
|
||||||
|
class="alert error"
|
||||||
|
@click.prevent
|
||||||
|
>
|
||||||
|
{{ $t('settings.saving_err') }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="!currentSaveStateNotice.error"
|
||||||
|
class="alert transparent"
|
||||||
|
@click.prevent
|
||||||
|
>
|
||||||
|
{{ $t('settings.saving_ok') }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</transition>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
<transition name="fade">
|
<keep-alive>
|
||||||
<template v-if="currentSaveStateNotice">
|
<tab-switcher>
|
||||||
<div @click.prevent class="alert error" v-if="currentSaveStateNotice.error">
|
<div :label="$t('settings.general')">
|
||||||
{{ $t('settings.saving_err') }}
|
<div class="setting-item">
|
||||||
</div>
|
<h2>{{ $t('settings.interface') }}</h2>
|
||||||
|
<ul class="setting-list">
|
||||||
<div @click.prevent class="alert transparent" v-if="!currentSaveStateNotice.error">
|
|
||||||
{{ $t('settings.saving_ok') }}
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</transition>
|
|
||||||
</div>
|
|
||||||
<div class="panel-body">
|
|
||||||
<keep-alive>
|
|
||||||
<tab-switcher>
|
|
||||||
<div :label="$t('settings.general')" >
|
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{ $t('settings.interface') }}</h2>
|
|
||||||
<ul class="setting-list">
|
|
||||||
<li>
|
|
||||||
<interface-language-switcher />
|
|
||||||
</li>
|
|
||||||
<li v-if="instanceSpecificPanelPresent">
|
|
||||||
<input type="checkbox" id="hideISP" v-model="hideISPLocal">
|
|
||||||
<label for="hideISP">{{$t('settings.hide_isp')}}</label>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{$t('nav.timeline')}}</h2>
|
|
||||||
<ul class="setting-list">
|
|
||||||
<li>
|
|
||||||
<input type="checkbox" id="hideMutedPosts" v-model="hideMutedPostsLocal">
|
|
||||||
<label for="hideMutedPosts">{{$t('settings.hide_muted_posts')}} {{$t('settings.instance_default', { value: hideMutedPostsDefault })}}</label>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<input type="checkbox" id="collapseMessageWithSubject" v-model="collapseMessageWithSubjectLocal">
|
|
||||||
<label for="collapseMessageWithSubject">{{$t('settings.collapse_subject')}} {{$t('settings.instance_default', { value: collapseMessageWithSubjectDefault })}}</label>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<input type="checkbox" id="streaming" v-model="streamingLocal">
|
|
||||||
<label for="streaming">{{$t('settings.streaming')}}</label>
|
|
||||||
<ul class="setting-list suboptions" :class="[{disabled: !streamingLocal}]">
|
|
||||||
<li>
|
<li>
|
||||||
<input :disabled="!streamingLocal" type="checkbox" id="pauseOnUnfocused" v-model="pauseOnUnfocusedLocal">
|
<interface-language-switcher />
|
||||||
<label for="pauseOnUnfocused">{{$t('settings.pause_on_unfocused')}}</label>
|
</li>
|
||||||
|
<li v-if="instanceSpecificPanelPresent">
|
||||||
|
<input
|
||||||
|
id="hideISP"
|
||||||
|
v-model="hideISPLocal"
|
||||||
|
type="checkbox"
|
||||||
|
>
|
||||||
|
<label for="hideISP">{{ $t('settings.hide_isp') }}</label>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</div>
|
||||||
<li>
|
<div class="setting-item">
|
||||||
<input type="checkbox" id="autoload" v-model="autoLoadLocal">
|
<h2>{{ $t('nav.timeline') }}</h2>
|
||||||
<label for="autoload">{{$t('settings.autoload')}}</label>
|
<ul class="setting-list">
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<input type="checkbox" id="hoverPreview" v-model="hoverPreviewLocal">
|
|
||||||
<label for="hoverPreview">{{$t('settings.reply_link_preview')}}</label>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{$t('settings.composing')}}</h2>
|
|
||||||
<ul class="setting-list">
|
|
||||||
<li>
|
|
||||||
<input type="checkbox" id="scopeCopy" v-model="scopeCopyLocal">
|
|
||||||
<label for="scopeCopy">
|
|
||||||
{{$t('settings.scope_copy')}} {{$t('settings.instance_default', { value: scopeCopyDefault })}}
|
|
||||||
</label>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<input type="checkbox" id="subjectHide" v-model="alwaysShowSubjectInputLocal">
|
|
||||||
<label for="subjectHide">
|
|
||||||
{{$t('settings.subject_input_always_show')}} {{$t('settings.instance_default', { value: alwaysShowSubjectInputDefault })}}
|
|
||||||
</label>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<div>
|
|
||||||
{{$t('settings.subject_line_behavior')}}
|
|
||||||
<label for="subjectLineBehavior" class="select">
|
|
||||||
<select id="subjectLineBehavior" v-model="subjectLineBehaviorLocal">
|
|
||||||
<option value="email">
|
|
||||||
{{$t('settings.subject_line_email')}}
|
|
||||||
{{subjectLineBehaviorDefault == 'email' ? $t('settings.instance_default_simple') : ''}}
|
|
||||||
</option>
|
|
||||||
<option value="masto">
|
|
||||||
{{$t('settings.subject_line_mastodon')}}
|
|
||||||
{{subjectLineBehaviorDefault == 'mastodon' ? $t('settings.instance_default_simple') : ''}}
|
|
||||||
</option>
|
|
||||||
<option value="noop">
|
|
||||||
{{$t('settings.subject_line_noop')}}
|
|
||||||
{{subjectLineBehaviorDefault == 'noop' ? $t('settings.instance_default_simple') : ''}}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
<i class="icon-down-open"/>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<li v-if="postFormats.length > 0">
|
|
||||||
<div>
|
|
||||||
{{$t('settings.post_status_content_type')}}
|
|
||||||
<label for="postContentType" class="select">
|
|
||||||
<select id="postContentType" v-model="postContentTypeLocal">
|
|
||||||
<option v-for="postFormat in postFormats" :key="postFormat" :value="postFormat">
|
|
||||||
{{$t(`post_status.content_type["${postFormat}"]`)}}
|
|
||||||
{{postContentTypeDefault === postFormat ? $t('settings.instance_default_simple') : ''}}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
<i class="icon-down-open"/>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<input type="checkbox" id="minimalScopesMode" v-model="minimalScopesModeLocal">
|
|
||||||
<label for="minimalScopesMode">
|
|
||||||
{{$t('settings.minimal_scopes_mode')}} {{$t('settings.instance_default', { value: minimalScopesModeDefault })}}
|
|
||||||
</label>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<input type="checkbox" id="autohideFloatingPostButton" v-model="autohideFloatingPostButtonLocal">
|
|
||||||
<label for="autohideFloatingPostButton">{{$t('settings.autohide_floating_post_button')}}</label>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{$t('settings.attachments')}}</h2>
|
|
||||||
<ul class="setting-list">
|
|
||||||
<li>
|
|
||||||
<input type="checkbox" id="hideAttachments" v-model="hideAttachmentsLocal">
|
|
||||||
<label for="hideAttachments">{{$t('settings.hide_attachments_in_tl')}}</label>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<input type="checkbox" id="hideAttachmentsInConv" v-model="hideAttachmentsInConvLocal">
|
|
||||||
<label for="hideAttachmentsInConv">{{$t('settings.hide_attachments_in_convo')}}</label>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<label for="maxThumbnails">{{$t('settings.max_thumbnails')}}</label>
|
|
||||||
<input class="number-input" type="number" id="maxThumbnails" v-model.number="maxThumbnails" min="0" step="1">
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<input type="checkbox" id="hideNsfw" v-model="hideNsfwLocal">
|
|
||||||
<label for="hideNsfw">{{$t('settings.nsfw_clickthrough')}}</label>
|
|
||||||
</li>
|
|
||||||
<ul class="setting-list suboptions" >
|
|
||||||
<li>
|
|
||||||
<input :disabled="!hideNsfwLocal" type="checkbox" id="preloadImage" v-model="preloadImage">
|
|
||||||
<label for="preloadImage">{{$t('settings.preload_images')}}</label>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<input :disabled="!hideNsfwLocal" type="checkbox" id="useOneClickNsfw" v-model="useOneClickNsfw">
|
|
||||||
<label for="useOneClickNsfw">{{$t('settings.use_one_click_nsfw')}}</label>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<li>
|
|
||||||
<input type="checkbox" id="stopGifs" v-model="stopGifs">
|
|
||||||
<label for="stopGifs">{{$t('settings.stop_gifs')}}</label>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<input type="checkbox" id="loopVideo" v-model="loopVideoLocal">
|
|
||||||
<label for="loopVideo">{{$t('settings.loop_video')}}</label>
|
|
||||||
<ul class="setting-list suboptions" :class="[{disabled: !streamingLocal}]">
|
|
||||||
<li>
|
<li>
|
||||||
<input :disabled="!loopVideoLocal || !loopSilentAvailable" type="checkbox" id="loopVideoSilentOnly" v-model="loopVideoSilentOnlyLocal">
|
<input
|
||||||
<label for="loopVideoSilentOnly">{{$t('settings.loop_video_silent_only')}}</label>
|
id="hideMutedPosts"
|
||||||
<div v-if="!loopSilentAvailable" class="unavailable">
|
v-model="hideMutedPostsLocal"
|
||||||
<i class="icon-globe"/>! {{$t('settings.limited_availability')}}
|
type="checkbox"
|
||||||
|
>
|
||||||
|
<label for="hideMutedPosts">{{ $t('settings.hide_muted_posts') }} {{ $t('settings.instance_default', { value: hideMutedPostsDefault }) }}</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input
|
||||||
|
id="collapseMessageWithSubject"
|
||||||
|
v-model="collapseMessageWithSubjectLocal"
|
||||||
|
type="checkbox"
|
||||||
|
>
|
||||||
|
<label for="collapseMessageWithSubject">{{ $t('settings.collapse_subject') }} {{ $t('settings.instance_default', { value: collapseMessageWithSubjectDefault }) }}</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input
|
||||||
|
id="streaming"
|
||||||
|
v-model="streamingLocal"
|
||||||
|
type="checkbox"
|
||||||
|
>
|
||||||
|
<label for="streaming">{{ $t('settings.streaming') }}</label>
|
||||||
|
<ul
|
||||||
|
class="setting-list suboptions"
|
||||||
|
:class="[{disabled: !streamingLocal}]"
|
||||||
|
>
|
||||||
|
<li>
|
||||||
|
<input
|
||||||
|
id="pauseOnUnfocused"
|
||||||
|
v-model="pauseOnUnfocusedLocal"
|
||||||
|
:disabled="!streamingLocal"
|
||||||
|
type="checkbox"
|
||||||
|
>
|
||||||
|
<label for="pauseOnUnfocused">{{ $t('settings.pause_on_unfocused') }}</label>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input
|
||||||
|
id="autoload"
|
||||||
|
v-model="autoLoadLocal"
|
||||||
|
type="checkbox"
|
||||||
|
>
|
||||||
|
<label for="autoload">{{ $t('settings.autoload') }}</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input
|
||||||
|
id="hoverPreview"
|
||||||
|
v-model="hoverPreviewLocal"
|
||||||
|
type="checkbox"
|
||||||
|
>
|
||||||
|
<label for="hoverPreview">{{ $t('settings.reply_link_preview') }}</label>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="setting-item">
|
||||||
|
<h2>{{ $t('settings.composing') }}</h2>
|
||||||
|
<ul class="setting-list">
|
||||||
|
<li>
|
||||||
|
<input
|
||||||
|
id="scopeCopy"
|
||||||
|
v-model="scopeCopyLocal"
|
||||||
|
type="checkbox"
|
||||||
|
>
|
||||||
|
<label for="scopeCopy">
|
||||||
|
{{ $t('settings.scope_copy') }} {{ $t('settings.instance_default', { value: scopeCopyDefault }) }}
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input
|
||||||
|
id="subjectHide"
|
||||||
|
v-model="alwaysShowSubjectInputLocal"
|
||||||
|
type="checkbox"
|
||||||
|
>
|
||||||
|
<label for="subjectHide">
|
||||||
|
{{ $t('settings.subject_input_always_show') }} {{ $t('settings.instance_default', { value: alwaysShowSubjectInputDefault }) }}
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div>
|
||||||
|
{{ $t('settings.subject_line_behavior') }}
|
||||||
|
<label
|
||||||
|
for="subjectLineBehavior"
|
||||||
|
class="select"
|
||||||
|
>
|
||||||
|
<select
|
||||||
|
id="subjectLineBehavior"
|
||||||
|
v-model="subjectLineBehaviorLocal"
|
||||||
|
>
|
||||||
|
<option value="email">
|
||||||
|
{{ $t('settings.subject_line_email') }}
|
||||||
|
{{ subjectLineBehaviorDefault == 'email' ? $t('settings.instance_default_simple') : '' }}
|
||||||
|
</option>
|
||||||
|
<option value="masto">
|
||||||
|
{{ $t('settings.subject_line_mastodon') }}
|
||||||
|
{{ subjectLineBehaviorDefault == 'mastodon' ? $t('settings.instance_default_simple') : '' }}
|
||||||
|
</option>
|
||||||
|
<option value="noop">
|
||||||
|
{{ $t('settings.subject_line_noop') }}
|
||||||
|
{{ subjectLineBehaviorDefault == 'noop' ? $t('settings.instance_default_simple') : '' }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<i class="icon-down-open" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li v-if="postFormats.length > 0">
|
||||||
|
<div>
|
||||||
|
{{ $t('settings.post_status_content_type') }}
|
||||||
|
<label
|
||||||
|
for="postContentType"
|
||||||
|
class="select"
|
||||||
|
>
|
||||||
|
<select
|
||||||
|
id="postContentType"
|
||||||
|
v-model="postContentTypeLocal"
|
||||||
|
>
|
||||||
|
<option
|
||||||
|
v-for="postFormat in postFormats"
|
||||||
|
:key="postFormat"
|
||||||
|
:value="postFormat"
|
||||||
|
>
|
||||||
|
{{ $t(`post_status.content_type["${postFormat}"]`) }}
|
||||||
|
{{ postContentTypeDefault === postFormat ? $t('settings.instance_default_simple') : '' }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<i class="icon-down-open" />
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<input type="checkbox" id="playVideosInModal" v-model="playVideosInModal">
|
|
||||||
<label for="playVideosInModal">{{$t('settings.play_videos_in_modal')}}</label>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<input type="checkbox" id="useContainFit" v-model="useContainFit">
|
|
||||||
<label for="useContainFit">{{$t('settings.use_contain_fit')}}</label>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{$t('settings.notifications')}}</h2>
|
|
||||||
<ul class="setting-list">
|
|
||||||
<li>
|
|
||||||
<input type="checkbox" id="webPushNotifications" v-model="webPushNotificationsLocal">
|
|
||||||
<label for="webPushNotifications">
|
|
||||||
{{$t('settings.enable_web_push_notifications')}}
|
|
||||||
</label>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div :label="$t('settings.theme')" >
|
|
||||||
<div class="setting-item">
|
|
||||||
<style-switcher></style-switcher>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div :label="$t('settings.filtering')" >
|
|
||||||
<div class="setting-item">
|
|
||||||
<div class="select-multiple">
|
|
||||||
<span class="label">{{$t('settings.notification_visibility')}}</span>
|
|
||||||
<ul class="option-list">
|
|
||||||
<li>
|
|
||||||
<input type="checkbox" id="notification-visibility-likes" v-model="notificationVisibilityLocal.likes">
|
|
||||||
<label for="notification-visibility-likes">
|
|
||||||
{{$t('settings.notification_visibility_likes')}}
|
|
||||||
</label>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<input type="checkbox" id="notification-visibility-repeats" v-model="notificationVisibilityLocal.repeats">
|
|
||||||
<label for="notification-visibility-repeats">
|
|
||||||
{{$t('settings.notification_visibility_repeats')}}
|
|
||||||
</label>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<input type="checkbox" id="notification-visibility-follows" v-model="notificationVisibilityLocal.follows">
|
|
||||||
<label for="notification-visibility-follows">
|
|
||||||
{{$t('settings.notification_visibility_follows')}}
|
|
||||||
</label>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<input type="checkbox" id="notification-visibility-mentions" v-model="notificationVisibilityLocal.mentions">
|
|
||||||
<label for="notification-visibility-mentions">
|
|
||||||
{{$t('settings.notification_visibility_mentions')}}
|
|
||||||
</label>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
{{$t('settings.replies_in_timeline')}}
|
|
||||||
<label for="replyVisibility" class="select">
|
|
||||||
<select id="replyVisibility" v-model="replyVisibilityLocal">
|
|
||||||
<option value="all" selected>{{$t('settings.reply_visibility_all')}}</option>
|
|
||||||
<option value="following">{{$t('settings.reply_visibility_following')}}</option>
|
|
||||||
<option value="self">{{$t('settings.reply_visibility_self')}}</option>
|
|
||||||
</select>
|
|
||||||
<i class="icon-down-open"/>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<input type="checkbox" id="hidePostStats" v-model="hidePostStatsLocal">
|
|
||||||
<label for="hidePostStats">
|
|
||||||
{{$t('settings.hide_post_stats')}} {{$t('settings.instance_default', { value: hidePostStatsDefault })}}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<input type="checkbox" id="hideUserStats" v-model="hideUserStatsLocal">
|
|
||||||
<label for="hideUserStats">
|
|
||||||
{{$t('settings.hide_user_stats')}} {{$t('settings.instance_default', { value: hideUserStatsDefault })}}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="setting-item">
|
|
||||||
<div>
|
|
||||||
<p>{{$t('settings.filtering_explanation')}}</p>
|
|
||||||
<textarea id="muteWords" v-model="muteWordsString"></textarea>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<input type="checkbox" id="hideFilteredStatuses" v-model="hideFilteredStatusesLocal">
|
|
||||||
<label for="hideFilteredStatuses">
|
|
||||||
{{$t('settings.hide_filtered_statuses')}} {{$t('settings.instance_default', { value: hideFilteredStatusesDefault })}}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div :label="$t('settings.version.title')" >
|
|
||||||
<div class="setting-item">
|
|
||||||
<ul class="setting-list">
|
|
||||||
<li>
|
|
||||||
<p>{{$t('settings.version.backend_version')}}</p>
|
|
||||||
<ul class="option-list">
|
|
||||||
<li>
|
<li>
|
||||||
<a :href="backendVersionLink" target="_blank">{{backendVersion}}</a>
|
<input
|
||||||
|
id="minimalScopesMode"
|
||||||
|
v-model="minimalScopesModeLocal"
|
||||||
|
type="checkbox"
|
||||||
|
>
|
||||||
|
<label for="minimalScopesMode">
|
||||||
|
{{ $t('settings.minimal_scopes_mode') }} {{ $t('settings.instance_default', { value: minimalScopesModeDefault }) }}
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input
|
||||||
|
id="autohideFloatingPostButton"
|
||||||
|
v-model="autohideFloatingPostButtonLocal"
|
||||||
|
type="checkbox"
|
||||||
|
>
|
||||||
|
<label for="autohideFloatingPostButton">{{ $t('settings.autohide_floating_post_button') }}</label>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</div>
|
||||||
<li>
|
|
||||||
<p>{{$t('settings.version.frontend_version')}}</p>
|
<div class="setting-item">
|
||||||
<ul class="option-list">
|
<h2>{{ $t('settings.attachments') }}</h2>
|
||||||
|
<ul class="setting-list">
|
||||||
<li>
|
<li>
|
||||||
<a :href="frontendVersionLink" target="_blank">{{frontendVersion}}</a>
|
<input
|
||||||
|
id="hideAttachments"
|
||||||
|
v-model="hideAttachmentsLocal"
|
||||||
|
type="checkbox"
|
||||||
|
>
|
||||||
|
<label for="hideAttachments">{{ $t('settings.hide_attachments_in_tl') }}</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input
|
||||||
|
id="hideAttachmentsInConv"
|
||||||
|
v-model="hideAttachmentsInConvLocal"
|
||||||
|
type="checkbox"
|
||||||
|
>
|
||||||
|
<label for="hideAttachmentsInConv">{{ $t('settings.hide_attachments_in_convo') }}</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<label for="maxThumbnails">{{ $t('settings.max_thumbnails') }}</label>
|
||||||
|
<input
|
||||||
|
id="maxThumbnails"
|
||||||
|
v-model.number="maxThumbnails"
|
||||||
|
class="number-input"
|
||||||
|
type="number"
|
||||||
|
min="0"
|
||||||
|
step="1"
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input
|
||||||
|
id="hideNsfw"
|
||||||
|
v-model="hideNsfwLocal"
|
||||||
|
type="checkbox"
|
||||||
|
>
|
||||||
|
<label for="hideNsfw">{{ $t('settings.nsfw_clickthrough') }}</label>
|
||||||
|
</li>
|
||||||
|
<ul class="setting-list suboptions">
|
||||||
|
<li>
|
||||||
|
<input
|
||||||
|
id="preloadImage"
|
||||||
|
v-model="preloadImage"
|
||||||
|
:disabled="!hideNsfwLocal"
|
||||||
|
type="checkbox"
|
||||||
|
>
|
||||||
|
<label for="preloadImage">{{ $t('settings.preload_images') }}</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input
|
||||||
|
id="useOneClickNsfw"
|
||||||
|
v-model="useOneClickNsfw"
|
||||||
|
:disabled="!hideNsfwLocal"
|
||||||
|
type="checkbox"
|
||||||
|
>
|
||||||
|
<label for="useOneClickNsfw">{{ $t('settings.use_one_click_nsfw') }}</label>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<li>
|
||||||
|
<input
|
||||||
|
id="stopGifs"
|
||||||
|
v-model="stopGifs"
|
||||||
|
type="checkbox"
|
||||||
|
>
|
||||||
|
<label for="stopGifs">{{ $t('settings.stop_gifs') }}</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input
|
||||||
|
id="loopVideo"
|
||||||
|
v-model="loopVideoLocal"
|
||||||
|
type="checkbox"
|
||||||
|
>
|
||||||
|
<label for="loopVideo">{{ $t('settings.loop_video') }}</label>
|
||||||
|
<ul
|
||||||
|
class="setting-list suboptions"
|
||||||
|
:class="[{disabled: !streamingLocal}]"
|
||||||
|
>
|
||||||
|
<li>
|
||||||
|
<input
|
||||||
|
id="loopVideoSilentOnly"
|
||||||
|
v-model="loopVideoSilentOnlyLocal"
|
||||||
|
:disabled="!loopVideoLocal || !loopSilentAvailable"
|
||||||
|
type="checkbox"
|
||||||
|
>
|
||||||
|
<label for="loopVideoSilentOnly">{{ $t('settings.loop_video_silent_only') }}</label>
|
||||||
|
<div
|
||||||
|
v-if="!loopSilentAvailable"
|
||||||
|
class="unavailable"
|
||||||
|
>
|
||||||
|
<i class="icon-globe" />! {{ $t('settings.limited_availability') }}
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input
|
||||||
|
id="playVideosInModal"
|
||||||
|
v-model="playVideosInModal"
|
||||||
|
type="checkbox"
|
||||||
|
>
|
||||||
|
<label for="playVideosInModal">{{ $t('settings.play_videos_in_modal') }}</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input
|
||||||
|
id="useContainFit"
|
||||||
|
v-model="useContainFit"
|
||||||
|
type="checkbox"
|
||||||
|
>
|
||||||
|
<label for="useContainFit">{{ $t('settings.use_contain_fit') }}</label>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</div>
|
||||||
</ul>
|
|
||||||
</div>
|
<div class="setting-item">
|
||||||
</div>
|
<h2>{{ $t('settings.notifications') }}</h2>
|
||||||
</tab-switcher>
|
<ul class="setting-list">
|
||||||
</keep-alive>
|
<li>
|
||||||
|
<input
|
||||||
|
id="webPushNotifications"
|
||||||
|
v-model="webPushNotificationsLocal"
|
||||||
|
type="checkbox"
|
||||||
|
>
|
||||||
|
<label for="webPushNotifications">
|
||||||
|
{{ $t('settings.enable_web_push_notifications') }}
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div :label="$t('settings.theme')">
|
||||||
|
<div class="setting-item">
|
||||||
|
<style-switcher />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div :label="$t('settings.filtering')">
|
||||||
|
<div class="setting-item">
|
||||||
|
<div class="select-multiple">
|
||||||
|
<span class="label">{{ $t('settings.notification_visibility') }}</span>
|
||||||
|
<ul class="option-list">
|
||||||
|
<li>
|
||||||
|
<input
|
||||||
|
id="notification-visibility-likes"
|
||||||
|
v-model="notificationVisibilityLocal.likes"
|
||||||
|
type="checkbox"
|
||||||
|
>
|
||||||
|
<label for="notification-visibility-likes">
|
||||||
|
{{ $t('settings.notification_visibility_likes') }}
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input
|
||||||
|
id="notification-visibility-repeats"
|
||||||
|
v-model="notificationVisibilityLocal.repeats"
|
||||||
|
type="checkbox"
|
||||||
|
>
|
||||||
|
<label for="notification-visibility-repeats">
|
||||||
|
{{ $t('settings.notification_visibility_repeats') }}
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input
|
||||||
|
id="notification-visibility-follows"
|
||||||
|
v-model="notificationVisibilityLocal.follows"
|
||||||
|
type="checkbox"
|
||||||
|
>
|
||||||
|
<label for="notification-visibility-follows">
|
||||||
|
{{ $t('settings.notification_visibility_follows') }}
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input
|
||||||
|
id="notification-visibility-mentions"
|
||||||
|
v-model="notificationVisibilityLocal.mentions"
|
||||||
|
type="checkbox"
|
||||||
|
>
|
||||||
|
<label for="notification-visibility-mentions">
|
||||||
|
{{ $t('settings.notification_visibility_mentions') }}
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{{ $t('settings.replies_in_timeline') }}
|
||||||
|
<label
|
||||||
|
for="replyVisibility"
|
||||||
|
class="select"
|
||||||
|
>
|
||||||
|
<select
|
||||||
|
id="replyVisibility"
|
||||||
|
v-model="replyVisibilityLocal"
|
||||||
|
>
|
||||||
|
<option
|
||||||
|
value="all"
|
||||||
|
selected
|
||||||
|
>{{ $t('settings.reply_visibility_all') }}</option>
|
||||||
|
<option value="following">{{ $t('settings.reply_visibility_following') }}</option>
|
||||||
|
<option value="self">{{ $t('settings.reply_visibility_self') }}</option>
|
||||||
|
</select>
|
||||||
|
<i class="icon-down-open" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input
|
||||||
|
id="hidePostStats"
|
||||||
|
v-model="hidePostStatsLocal"
|
||||||
|
type="checkbox"
|
||||||
|
>
|
||||||
|
<label for="hidePostStats">
|
||||||
|
{{ $t('settings.hide_post_stats') }} {{ $t('settings.instance_default', { value: hidePostStatsDefault }) }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input
|
||||||
|
id="hideUserStats"
|
||||||
|
v-model="hideUserStatsLocal"
|
||||||
|
type="checkbox"
|
||||||
|
>
|
||||||
|
<label for="hideUserStats">
|
||||||
|
{{ $t('settings.hide_user_stats') }} {{ $t('settings.instance_default', { value: hideUserStatsDefault }) }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="setting-item">
|
||||||
|
<div>
|
||||||
|
<p>{{ $t('settings.filtering_explanation') }}</p>
|
||||||
|
<textarea
|
||||||
|
id="muteWords"
|
||||||
|
v-model="muteWordsString"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input
|
||||||
|
id="hideFilteredStatuses"
|
||||||
|
v-model="hideFilteredStatusesLocal"
|
||||||
|
type="checkbox"
|
||||||
|
>
|
||||||
|
<label for="hideFilteredStatuses">
|
||||||
|
{{ $t('settings.hide_filtered_statuses') }} {{ $t('settings.instance_default', { value: hideFilteredStatusesDefault }) }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div :label="$t('settings.version.title')">
|
||||||
|
<div class="setting-item">
|
||||||
|
<ul class="setting-list">
|
||||||
|
<li>
|
||||||
|
<p>{{ $t('settings.version.backend_version') }}</p>
|
||||||
|
<ul class="option-list">
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
:href="backendVersionLink"
|
||||||
|
target="_blank"
|
||||||
|
>{{ backendVersion }}</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>{{ $t('settings.version.frontend_version') }}</p>
|
||||||
|
<ul class="option-list">
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
:href="frontendVersionLink"
|
||||||
|
target="_blank"
|
||||||
|
>{{ frontendVersion }}</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</tab-switcher>
|
||||||
|
</keep-alive>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./settings.js">
|
<script src="./settings.js">
|
||||||
|
|
|
@ -1,134 +1,207 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="shadow-control" :class="{ disabled: !present }">
|
<div
|
||||||
<div class="shadow-preview-container">
|
class="shadow-control"
|
||||||
<div :disabled="!present" class="y-shift-control">
|
:class="{ disabled: !present }"
|
||||||
<input
|
>
|
||||||
v-model="selected.y"
|
<div class="shadow-preview-container">
|
||||||
|
<div
|
||||||
:disabled="!present"
|
:disabled="!present"
|
||||||
class="input-number"
|
class="y-shift-control"
|
||||||
type="number">
|
>
|
||||||
<div class="wrap">
|
|
||||||
<input
|
<input
|
||||||
v-model="selected.y"
|
v-model="selected.y"
|
||||||
:disabled="!present"
|
:disabled="!present"
|
||||||
class="input-range"
|
class="input-number"
|
||||||
type="range"
|
type="number"
|
||||||
max="20"
|
>
|
||||||
min="-20">
|
<div class="wrap">
|
||||||
|
<input
|
||||||
|
v-model="selected.y"
|
||||||
|
:disabled="!present"
|
||||||
|
class="input-range"
|
||||||
|
type="range"
|
||||||
|
max="20"
|
||||||
|
min="-20"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="preview-window">
|
||||||
<div class="preview-window">
|
<div
|
||||||
<div class="preview-block" :style="style"></div>
|
class="preview-block"
|
||||||
</div>
|
:style="style"
|
||||||
<div :disabled="!present" class="x-shift-control">
|
/>
|
||||||
<input
|
</div>
|
||||||
v-model="selected.x"
|
<div
|
||||||
:disabled="!present"
|
:disabled="!present"
|
||||||
class="input-number"
|
class="x-shift-control"
|
||||||
type="number">
|
>
|
||||||
<div class="wrap">
|
|
||||||
<input
|
<input
|
||||||
v-model="selected.x"
|
v-model="selected.x"
|
||||||
:disabled="!present"
|
:disabled="!present"
|
||||||
|
class="input-number"
|
||||||
|
type="number"
|
||||||
|
>
|
||||||
|
<div class="wrap">
|
||||||
|
<input
|
||||||
|
v-model="selected.x"
|
||||||
|
:disabled="!present"
|
||||||
|
class="input-range"
|
||||||
|
type="range"
|
||||||
|
max="20"
|
||||||
|
min="-20"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="shadow-tweak">
|
||||||
|
<div
|
||||||
|
:disabled="usingFallback"
|
||||||
|
class="id-control style-control"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
for="shadow-switcher"
|
||||||
|
class="select"
|
||||||
|
:disabled="!ready || usingFallback"
|
||||||
|
>
|
||||||
|
<select
|
||||||
|
id="shadow-switcher"
|
||||||
|
v-model="selectedId"
|
||||||
|
class="shadow-switcher"
|
||||||
|
:disabled="!ready || usingFallback"
|
||||||
|
>
|
||||||
|
<option
|
||||||
|
v-for="(shadow, index) in cValue"
|
||||||
|
:key="index"
|
||||||
|
:value="index"
|
||||||
|
>
|
||||||
|
{{ $t('settings.style.shadows.shadow_id', { value: index }) }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<i class="icon-down-open" />
|
||||||
|
</label>
|
||||||
|
<button
|
||||||
|
class="btn btn-default"
|
||||||
|
:disabled="!ready || !present"
|
||||||
|
@click="del"
|
||||||
|
>
|
||||||
|
<i class="icon-cancel" />
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="btn btn-default"
|
||||||
|
:disabled="!moveUpValid"
|
||||||
|
@click="moveUp"
|
||||||
|
>
|
||||||
|
<i class="icon-up-open" />
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="btn btn-default"
|
||||||
|
:disabled="!moveDnValid"
|
||||||
|
@click="moveDn"
|
||||||
|
>
|
||||||
|
<i class="icon-down-open" />
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="btn btn-default"
|
||||||
|
:disabled="usingFallback"
|
||||||
|
@click="add"
|
||||||
|
>
|
||||||
|
<i class="icon-plus" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
:disabled="!present"
|
||||||
|
class="inset-control style-control"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
for="inset"
|
||||||
|
class="label"
|
||||||
|
>
|
||||||
|
{{ $t('settings.style.shadows.inset') }}
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="inset"
|
||||||
|
v-model="selected.inset"
|
||||||
|
:disabled="!present"
|
||||||
|
name="inset"
|
||||||
|
class="input-inset"
|
||||||
|
type="checkbox"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="checkbox-label"
|
||||||
|
for="inset"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
:disabled="!present"
|
||||||
|
class="blur-control style-control"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
for="spread"
|
||||||
|
class="label"
|
||||||
|
>
|
||||||
|
{{ $t('settings.style.shadows.blur') }}
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="blur"
|
||||||
|
v-model="selected.blur"
|
||||||
|
:disabled="!present"
|
||||||
|
name="blur"
|
||||||
class="input-range"
|
class="input-range"
|
||||||
type="range"
|
type="range"
|
||||||
max="20"
|
max="20"
|
||||||
min="-20">
|
min="0"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
v-model="selected.blur"
|
||||||
|
:disabled="!present"
|
||||||
|
class="input-number"
|
||||||
|
type="number"
|
||||||
|
min="0"
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
:disabled="!present"
|
||||||
|
class="spread-control style-control"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
for="spread"
|
||||||
|
class="label"
|
||||||
|
>
|
||||||
|
{{ $t('settings.style.shadows.spread') }}
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="spread"
|
||||||
|
v-model="selected.spread"
|
||||||
|
:disabled="!present"
|
||||||
|
name="spread"
|
||||||
|
class="input-range"
|
||||||
|
type="range"
|
||||||
|
max="20"
|
||||||
|
min="-20"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
v-model="selected.spread"
|
||||||
|
:disabled="!present"
|
||||||
|
class="input-number"
|
||||||
|
type="number"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<ColorInput
|
||||||
|
v-model="selected.color"
|
||||||
|
:disabled="!present"
|
||||||
|
:label="$t('settings.style.common.color')"
|
||||||
|
name="shadow"
|
||||||
|
/>
|
||||||
|
<OpacityInput
|
||||||
|
v-model="selected.alpha"
|
||||||
|
:disabled="!present"
|
||||||
|
/>
|
||||||
|
<p>
|
||||||
|
{{ $t('settings.style.shadows.hint') }}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="shadow-tweak">
|
|
||||||
<div :disabled="usingFallback" class="id-control style-control">
|
|
||||||
<label for="shadow-switcher" class="select" :disabled="!ready || usingFallback">
|
|
||||||
<select
|
|
||||||
v-model="selectedId" class="shadow-switcher"
|
|
||||||
:disabled="!ready || usingFallback"
|
|
||||||
id="shadow-switcher">
|
|
||||||
<option v-for="(shadow, index) in cValue" :value="index">
|
|
||||||
{{$t('settings.style.shadows.shadow_id', { value: index })}}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
<i class="icon-down-open"/>
|
|
||||||
</label>
|
|
||||||
<button class="btn btn-default" :disabled="!ready || !present" @click="del">
|
|
||||||
<i class="icon-cancel"/>
|
|
||||||
</button>
|
|
||||||
<button class="btn btn-default" :disabled="!moveUpValid" @click="moveUp">
|
|
||||||
<i class="icon-up-open"/>
|
|
||||||
</button>
|
|
||||||
<button class="btn btn-default" :disabled="!moveDnValid" @click="moveDn">
|
|
||||||
<i class="icon-down-open"/>
|
|
||||||
</button>
|
|
||||||
<button class="btn btn-default" :disabled="usingFallback" @click="add">
|
|
||||||
<i class="icon-plus"/>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div :disabled="!present" class="inset-control style-control">
|
|
||||||
<label for="inset" class="label">
|
|
||||||
{{$t('settings.style.shadows.inset')}}
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
v-model="selected.inset"
|
|
||||||
:disabled="!present"
|
|
||||||
name="inset"
|
|
||||||
id="inset"
|
|
||||||
class="input-inset"
|
|
||||||
type="checkbox">
|
|
||||||
<label class="checkbox-label" for="inset"></label>
|
|
||||||
</div>
|
|
||||||
<div :disabled="!present" class="blur-control style-control">
|
|
||||||
<label for="spread" class="label">
|
|
||||||
{{$t('settings.style.shadows.blur')}}
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
v-model="selected.blur"
|
|
||||||
:disabled="!present"
|
|
||||||
name="blur"
|
|
||||||
id="blur"
|
|
||||||
class="input-range"
|
|
||||||
type="range"
|
|
||||||
max="20"
|
|
||||||
min="0">
|
|
||||||
<input
|
|
||||||
v-model="selected.blur"
|
|
||||||
:disabled="!present"
|
|
||||||
class="input-number"
|
|
||||||
type="number"
|
|
||||||
min="0">
|
|
||||||
</div>
|
|
||||||
<div :disabled="!present" class="spread-control style-control">
|
|
||||||
<label for="spread" class="label">
|
|
||||||
{{$t('settings.style.shadows.spread')}}
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
v-model="selected.spread"
|
|
||||||
:disabled="!present"
|
|
||||||
name="spread"
|
|
||||||
id="spread"
|
|
||||||
class="input-range"
|
|
||||||
type="range"
|
|
||||||
max="20"
|
|
||||||
min="-20">
|
|
||||||
<input
|
|
||||||
v-model="selected.spread"
|
|
||||||
:disabled="!present"
|
|
||||||
class="input-number"
|
|
||||||
type="number">
|
|
||||||
</div>
|
|
||||||
<ColorInput
|
|
||||||
v-model="selected.color"
|
|
||||||
:disabled="!present"
|
|
||||||
:label="$t('settings.style.common.color')"
|
|
||||||
name="shadow"/>
|
|
||||||
<OpacityInput
|
|
||||||
v-model="selected.alpha"
|
|
||||||
:disabled="!present"/>
|
|
||||||
<p>
|
|
||||||
{{$t('settings.style.shadows.hint')}}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./shadow_control.js" ></script>
|
<script src="./shadow_control.js" ></script>
|
||||||
|
|
|
@ -1,63 +1,98 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="side-drawer-container"
|
<div
|
||||||
|
class="side-drawer-container"
|
||||||
:class="{ 'side-drawer-container-closed': closed, 'side-drawer-container-open': !closed }"
|
:class="{ 'side-drawer-container-closed': closed, 'side-drawer-container-open': !closed }"
|
||||||
>
|
>
|
||||||
<div class="side-drawer-darken" :class="{ 'side-drawer-darken-closed': closed}" />
|
<div
|
||||||
<div class="side-drawer"
|
class="side-drawer-darken"
|
||||||
|
:class="{ 'side-drawer-darken-closed': closed}"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="side-drawer"
|
||||||
:class="{'side-drawer-closed': closed}"
|
:class="{'side-drawer-closed': closed}"
|
||||||
@touchstart="touchStart"
|
@touchstart="touchStart"
|
||||||
@touchmove="touchMove"
|
@touchmove="touchMove"
|
||||||
>
|
>
|
||||||
<div class="side-drawer-heading" @click="toggleDrawer">
|
<div
|
||||||
<UserCard :user="currentUser" :hideBio="true" v-if="currentUser"/>
|
class="side-drawer-heading"
|
||||||
<div class="side-drawer-logo-wrapper" v-else>
|
@click="toggleDrawer"
|
||||||
<img :src="logo"/>
|
>
|
||||||
<span>{{sitename}}</span>
|
<UserCard
|
||||||
|
v-if="currentUser"
|
||||||
|
:user="currentUser"
|
||||||
|
:hide-bio="true"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
v-else
|
||||||
|
class="side-drawer-logo-wrapper"
|
||||||
|
>
|
||||||
|
<img :src="logo">
|
||||||
|
<span>{{ sitename }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ul>
|
<ul>
|
||||||
<li v-if="!currentUser" @click="toggleDrawer">
|
<li
|
||||||
|
v-if="!currentUser"
|
||||||
|
@click="toggleDrawer"
|
||||||
|
>
|
||||||
<router-link :to="{ name: 'login' }">
|
<router-link :to="{ name: 'login' }">
|
||||||
{{ $t("login.login") }}
|
{{ $t("login.login") }}
|
||||||
</router-link>
|
</router-link>
|
||||||
</li>
|
</li>
|
||||||
<li v-if="currentUser" @click="toggleDrawer">
|
<li
|
||||||
|
v-if="currentUser"
|
||||||
|
@click="toggleDrawer"
|
||||||
|
>
|
||||||
<router-link :to="{ name: 'dms', params: { username: currentUser.screen_name } }">
|
<router-link :to="{ name: 'dms', params: { username: currentUser.screen_name } }">
|
||||||
{{ $t("nav.dms") }}
|
{{ $t("nav.dms") }}
|
||||||
</router-link>
|
</router-link>
|
||||||
</li>
|
</li>
|
||||||
<li v-if="currentUser" @click="toggleDrawer">
|
<li
|
||||||
|
v-if="currentUser"
|
||||||
|
@click="toggleDrawer"
|
||||||
|
>
|
||||||
<router-link :to="{ name: 'interactions', params: { username: currentUser.screen_name } }">
|
<router-link :to="{ name: 'interactions', params: { username: currentUser.screen_name } }">
|
||||||
{{ $t("nav.interactions") }}
|
{{ $t("nav.interactions") }}
|
||||||
</router-link>
|
</router-link>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul>
|
<ul>
|
||||||
<li v-if="currentUser" @click="toggleDrawer">
|
<li
|
||||||
|
v-if="currentUser"
|
||||||
|
@click="toggleDrawer"
|
||||||
|
>
|
||||||
<router-link :to="{ name: 'friends' }">
|
<router-link :to="{ name: 'friends' }">
|
||||||
{{ $t("nav.timeline") }}
|
{{ $t("nav.timeline") }}
|
||||||
</router-link>
|
</router-link>
|
||||||
</li>
|
</li>
|
||||||
<li v-if="currentUser && currentUser.locked" @click="toggleDrawer">
|
<li
|
||||||
<router-link to='/friend-requests'>
|
v-if="currentUser && currentUser.locked"
|
||||||
|
@click="toggleDrawer"
|
||||||
|
>
|
||||||
|
<router-link to="/friend-requests">
|
||||||
{{ $t("nav.friend_requests") }}
|
{{ $t("nav.friend_requests") }}
|
||||||
<span v-if='followRequestCount > 0' class="badge follow-request-count">
|
<span
|
||||||
{{followRequestCount}}
|
v-if="followRequestCount > 0"
|
||||||
|
class="badge follow-request-count"
|
||||||
|
>
|
||||||
|
{{ followRequestCount }}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
</router-link>
|
</router-link>
|
||||||
</li>
|
</li>
|
||||||
<li @click="toggleDrawer">
|
<li @click="toggleDrawer">
|
||||||
<router-link to='/main/public'>
|
<router-link to="/main/public">
|
||||||
{{ $t("nav.public_tl") }}
|
{{ $t("nav.public_tl") }}
|
||||||
</router-link>
|
</router-link>
|
||||||
</li>
|
</li>
|
||||||
<li @click="toggleDrawer">
|
<li @click="toggleDrawer">
|
||||||
<router-link to='/main/all'>
|
<router-link to="/main/all">
|
||||||
{{ $t("nav.twkn") }}
|
{{ $t("nav.twkn") }}
|
||||||
</router-link>
|
</router-link>
|
||||||
</li>
|
</li>
|
||||||
<li v-if="currentUser && chat" @click="toggleDrawer">
|
<li
|
||||||
|
v-if="currentUser && chat"
|
||||||
|
@click="toggleDrawer"
|
||||||
|
>
|
||||||
<router-link :to="{ name: 'chat' }">
|
<router-link :to="{ name: 'chat' }">
|
||||||
{{ $t("nav.chat") }}
|
{{ $t("nav.chat") }}
|
||||||
</router-link>
|
</router-link>
|
||||||
|
@ -69,7 +104,10 @@
|
||||||
{{ $t("nav.user_search") }}
|
{{ $t("nav.user_search") }}
|
||||||
</router-link>
|
</router-link>
|
||||||
</li>
|
</li>
|
||||||
<li v-if="currentUser && suggestionsEnabled" @click="toggleDrawer">
|
<li
|
||||||
|
v-if="currentUser && suggestionsEnabled"
|
||||||
|
@click="toggleDrawer"
|
||||||
|
>
|
||||||
<router-link :to="{ name: 'who-to-follow' }">
|
<router-link :to="{ name: 'who-to-follow' }">
|
||||||
{{ $t("nav.who_to_follow") }}
|
{{ $t("nav.who_to_follow") }}
|
||||||
</router-link>
|
</router-link>
|
||||||
|
@ -84,17 +122,24 @@
|
||||||
{{ $t("nav.about") }}
|
{{ $t("nav.about") }}
|
||||||
</router-link>
|
</router-link>
|
||||||
</li>
|
</li>
|
||||||
<li v-if="currentUser" @click="toggleDrawer">
|
<li
|
||||||
<a @click="doLogout" href="#">
|
v-if="currentUser"
|
||||||
|
@click="toggleDrawer"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
@click="doLogout"
|
||||||
|
>
|
||||||
{{ $t("login.logout") }}
|
{{ $t("login.logout") }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="side-drawer-click-outside"
|
<div
|
||||||
@click.stop.prevent="toggleDrawer"
|
class="side-drawer-click-outside"
|
||||||
:class="{'side-drawer-click-outside-closed': closed}"
|
:class="{'side-drawer-click-outside-closed': closed}"
|
||||||
></div>
|
@click.stop.prevent="toggleDrawer"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -221,7 +221,7 @@ const Status = {
|
||||||
? this.$store.state.instance.subjectLineBehavior
|
? this.$store.state.instance.subjectLineBehavior
|
||||||
: this.$store.state.config.subjectLineBehavior
|
: this.$store.state.config.subjectLineBehavior
|
||||||
const startsWithRe = decodedSummary.match(/^re[: ]/i)
|
const startsWithRe = decodedSummary.match(/^re[: ]/i)
|
||||||
if (behavior !== 'noop' && startsWithRe || behavior === 'masto') {
|
if ((behavior !== 'noop' && startsWithRe) || behavior === 'masto') {
|
||||||
return decodedSummary
|
return decodedSummary
|
||||||
} else if (behavior === 'email') {
|
} else if (behavior === 'email') {
|
||||||
return 're: '.concat(decodedSummary)
|
return 're: '.concat(decodedSummary)
|
||||||
|
|
|
@ -1,190 +1,431 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="status-el" v-if="!hideStatus" :class="[{ 'status-el_focused': isFocused }, { 'status-conversation': inlineExpanded }]">
|
<!-- eslint-disable vue/no-v-html -->
|
||||||
<div v-if="error" class="alert error">
|
<div
|
||||||
{{error}}
|
v-if="!hideStatus"
|
||||||
<i class="button-icon icon-cancel" @click="clearError"></i>
|
class="status-el"
|
||||||
|
:class="[{ 'status-el_focused': isFocused }, { 'status-conversation': inlineExpanded }]"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-if="error"
|
||||||
|
class="alert error"
|
||||||
|
>
|
||||||
|
{{ error }}
|
||||||
|
<i
|
||||||
|
class="button-icon icon-cancel"
|
||||||
|
@click="clearError"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<template v-if="muted && !isPreview">
|
<template v-if="muted && !isPreview">
|
||||||
<div class="media status container muted">
|
<div class="media status container muted">
|
||||||
<small>
|
<small>
|
||||||
<router-link :to="userProfileLink">
|
<router-link :to="userProfileLink">
|
||||||
{{status.user.screen_name}}
|
{{ status.user.screen_name }}
|
||||||
</router-link>
|
</router-link>
|
||||||
</small>
|
</small>
|
||||||
<small class="muteWords">{{muteWordHits.join(', ')}}</small>
|
<small class="muteWords">{{ muteWordHits.join(', ') }}</small>
|
||||||
<a href="#" class="unmute" @click.prevent="toggleMute"><i class="button-icon icon-eye-off"></i></a>
|
<a
|
||||||
|
href="#"
|
||||||
|
class="unmute"
|
||||||
|
@click.prevent="toggleMute"
|
||||||
|
><i class="button-icon icon-eye-off" /></a>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<div v-if="showPinned && statusoid.pinned" class="status-pin">
|
<div
|
||||||
<i class="fa icon-pin faint"></i>
|
v-if="showPinned && statusoid.pinned"
|
||||||
<span class="faint">{{$t('status.pinned')}}</span>
|
class="status-pin"
|
||||||
|
>
|
||||||
|
<i class="fa icon-pin faint" />
|
||||||
|
<span class="faint">{{ $t('status.pinned') }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="retweet && !noHeading && !inConversation" :class="[repeaterClass, { highlighted: repeaterStyle }]" :style="[repeaterStyle]" class="media container retweet-info">
|
<div
|
||||||
<UserAvatar class="media-left" v-if="retweet" :betterShadow="betterShadow" :user="statusoid.user"/>
|
v-if="retweet && !noHeading && !inConversation"
|
||||||
|
:class="[repeaterClass, { highlighted: repeaterStyle }]"
|
||||||
|
:style="[repeaterStyle]"
|
||||||
|
class="media container retweet-info"
|
||||||
|
>
|
||||||
|
<UserAvatar
|
||||||
|
v-if="retweet"
|
||||||
|
class="media-left"
|
||||||
|
:better-shadow="betterShadow"
|
||||||
|
:user="statusoid.user"
|
||||||
|
/>
|
||||||
<div class="media-body faint">
|
<div class="media-body faint">
|
||||||
<span class="user-name">
|
<span class="user-name">
|
||||||
<router-link v-if="retweeterHtml" :to="retweeterProfileLink" v-html="retweeterHtml"/>
|
<router-link
|
||||||
<router-link v-else :to="retweeterProfileLink">{{retweeter}}</router-link>
|
v-if="retweeterHtml"
|
||||||
|
:to="retweeterProfileLink"
|
||||||
|
v-html="retweeterHtml"
|
||||||
|
/>
|
||||||
|
<router-link
|
||||||
|
v-else
|
||||||
|
:to="retweeterProfileLink"
|
||||||
|
>{{ retweeter }}</router-link>
|
||||||
</span>
|
</span>
|
||||||
<i class='fa icon-retweet retweeted' :title="$t('tool_tip.repeat')"></i>
|
<i
|
||||||
{{$t('timeline.repeated')}}
|
class="fa icon-retweet retweeted"
|
||||||
|
:title="$t('tool_tip.repeat')"
|
||||||
|
/>
|
||||||
|
{{ $t('timeline.repeated') }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div :class="[userClass, { highlighted: userStyle, 'is-retweet': retweet && !inConversation }]" :style="[ userStyle ]" class="media status" :data-tags="tags">
|
<div
|
||||||
<div v-if="!noHeading" class="media-left">
|
:class="[userClass, { highlighted: userStyle, 'is-retweet': retweet && !inConversation }]"
|
||||||
<router-link :to="userProfileLink" @click.stop.prevent.capture.native="toggleUserExpanded">
|
:style="[ userStyle ]"
|
||||||
<UserAvatar :compact="compact" :betterShadow="betterShadow" :user="status.user"/>
|
class="media status"
|
||||||
|
:data-tags="tags"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-if="!noHeading"
|
||||||
|
class="media-left"
|
||||||
|
>
|
||||||
|
<router-link
|
||||||
|
:to="userProfileLink"
|
||||||
|
@click.stop.prevent.capture.native="toggleUserExpanded"
|
||||||
|
>
|
||||||
|
<UserAvatar
|
||||||
|
:compact="compact"
|
||||||
|
:better-shadow="betterShadow"
|
||||||
|
:user="status.user"
|
||||||
|
/>
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
<div class="status-body">
|
<div class="status-body">
|
||||||
<UserCard :user="status.user" :rounded="true" :bordered="true" class="status-usercard" v-if="userExpanded"/>
|
<UserCard
|
||||||
<div v-if="!noHeading" class="media-heading">
|
v-if="userExpanded"
|
||||||
|
:user="status.user"
|
||||||
|
:rounded="true"
|
||||||
|
:bordered="true"
|
||||||
|
class="status-usercard"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
v-if="!noHeading"
|
||||||
|
class="media-heading"
|
||||||
|
>
|
||||||
<div class="heading-name-row">
|
<div class="heading-name-row">
|
||||||
<div class="name-and-account-name">
|
<div class="name-and-account-name">
|
||||||
<h4 class="user-name" v-if="status.user.name_html" v-html="status.user.name_html"></h4>
|
<h4
|
||||||
<h4 class="user-name" v-else>{{status.user.name}}</h4>
|
v-if="status.user.name_html"
|
||||||
<router-link class="account-name" :to="userProfileLink">
|
class="user-name"
|
||||||
{{status.user.screen_name}}
|
v-html="status.user.name_html"
|
||||||
|
/>
|
||||||
|
<h4
|
||||||
|
v-else
|
||||||
|
class="user-name"
|
||||||
|
>
|
||||||
|
{{ status.user.name }}
|
||||||
|
</h4>
|
||||||
|
<router-link
|
||||||
|
class="account-name"
|
||||||
|
:to="userProfileLink"
|
||||||
|
>
|
||||||
|
{{ status.user.screen_name }}
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="heading-right">
|
<span class="heading-right">
|
||||||
<router-link class="timeago faint-link" :to="{ name: 'conversation', params: { id: status.id } }">
|
<router-link
|
||||||
<Timeago :time="status.created_at" :auto-update="60"></Timeago>
|
class="timeago faint-link"
|
||||||
|
:to="{ name: 'conversation', params: { id: status.id } }"
|
||||||
|
>
|
||||||
|
<Timeago
|
||||||
|
:time="status.created_at"
|
||||||
|
:auto-update="60"
|
||||||
|
/>
|
||||||
</router-link>
|
</router-link>
|
||||||
<div class="button-icon visibility-icon" v-if="status.visibility">
|
<div
|
||||||
<i :class="visibilityIcon(status.visibility)" :title="status.visibility | capitalize"></i>
|
v-if="status.visibility"
|
||||||
|
class="button-icon visibility-icon"
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
:class="visibilityIcon(status.visibility)"
|
||||||
|
:title="status.visibility | capitalize"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<a :href="status.external_url" target="_blank" v-if="!status.is_local && !isPreview" class="source_url" title="Source">
|
<a
|
||||||
<i class="button-icon icon-link-ext-alt"></i>
|
v-if="!status.is_local && !isPreview"
|
||||||
|
:href="status.external_url"
|
||||||
|
target="_blank"
|
||||||
|
class="source_url"
|
||||||
|
title="Source"
|
||||||
|
>
|
||||||
|
<i class="button-icon icon-link-ext-alt" />
|
||||||
</a>
|
</a>
|
||||||
<template v-if="expandable && !isPreview">
|
<template v-if="expandable && !isPreview">
|
||||||
<a href="#" @click.prevent="toggleExpanded" title="Expand">
|
<a
|
||||||
<i class="button-icon icon-plus-squared"></i>
|
href="#"
|
||||||
|
title="Expand"
|
||||||
|
@click.prevent="toggleExpanded"
|
||||||
|
>
|
||||||
|
<i class="button-icon icon-plus-squared" />
|
||||||
</a>
|
</a>
|
||||||
</template>
|
</template>
|
||||||
<a href="#" @click.prevent="toggleMute" v-if="unmuted"><i class="button-icon icon-eye-off"></i></a>
|
<a
|
||||||
|
v-if="unmuted"
|
||||||
|
href="#"
|
||||||
|
@click.prevent="toggleMute"
|
||||||
|
><i class="button-icon icon-eye-off" /></a>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="heading-reply-row">
|
<div class="heading-reply-row">
|
||||||
<div v-if="isReply" class="reply-to-and-accountname">
|
<div
|
||||||
<a class="reply-to"
|
v-if="isReply"
|
||||||
href="#" @click.prevent="gotoOriginal(status.in_reply_to_status_id)"
|
class="reply-to-and-accountname"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
class="reply-to"
|
||||||
|
href="#"
|
||||||
:aria-label="$t('tool_tip.reply')"
|
:aria-label="$t('tool_tip.reply')"
|
||||||
|
@click.prevent="gotoOriginal(status.in_reply_to_status_id)"
|
||||||
@mouseenter.prevent.stop="replyEnter(status.in_reply_to_status_id, $event)"
|
@mouseenter.prevent.stop="replyEnter(status.in_reply_to_status_id, $event)"
|
||||||
@mouseleave.prevent.stop="replyLeave()"
|
@mouseleave.prevent.stop="replyLeave()"
|
||||||
>
|
>
|
||||||
<i class="button-icon icon-reply" v-if="!isPreview"></i>
|
<i
|
||||||
<span class="faint-link reply-to-text">{{$t('status.reply_to')}}</span>
|
v-if="!isPreview"
|
||||||
|
class="button-icon icon-reply"
|
||||||
|
/>
|
||||||
|
<span class="faint-link reply-to-text">{{ $t('status.reply_to') }}</span>
|
||||||
</a>
|
</a>
|
||||||
<router-link :to="replyProfileLink">
|
<router-link :to="replyProfileLink">
|
||||||
{{replyToName}}
|
{{ replyToName }}
|
||||||
</router-link>
|
</router-link>
|
||||||
<span class="faint replies-separator" v-if="replies && replies.length">
|
<span
|
||||||
|
v-if="replies && replies.length"
|
||||||
|
class="faint replies-separator"
|
||||||
|
>
|
||||||
-
|
-
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="replies" v-if="inConversation && !isPreview">
|
<div
|
||||||
<span class="faint" v-if="replies && replies.length">{{$t('status.replies_list')}}</span>
|
v-if="inConversation && !isPreview"
|
||||||
<span class="reply-link faint" v-if="replies" v-for="reply in replies">
|
class="replies"
|
||||||
<a href="#" @click.prevent="gotoOriginal(reply.id)" @mouseenter="replyEnter(reply.id, $event)" @mouseout="replyLeave()">{{reply.name}}</a>
|
>
|
||||||
</span>
|
<span
|
||||||
|
v-if="replies && replies.length"
|
||||||
|
class="faint"
|
||||||
|
>{{ $t('status.replies_list') }}</span>
|
||||||
|
<template v-if="replies">
|
||||||
|
<span
|
||||||
|
v-for="reply in replies"
|
||||||
|
:key="reply.id"
|
||||||
|
class="reply-link faint"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
@click.prevent="gotoOriginal(reply.id)"
|
||||||
|
@mouseenter="replyEnter(reply.id, $event)"
|
||||||
|
@mouseout="replyLeave()"
|
||||||
|
>{{ reply.name }}</a>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="showPreview" class="status-preview-container">
|
<div
|
||||||
<status class="status-preview"
|
v-if="showPreview"
|
||||||
|
class="status-preview-container"
|
||||||
|
>
|
||||||
|
<status
|
||||||
v-if="preview"
|
v-if="preview"
|
||||||
:isPreview="true"
|
class="status-preview"
|
||||||
|
:is-preview="true"
|
||||||
:statusoid="preview"
|
:statusoid="preview"
|
||||||
:compact="true"
|
:compact="true"
|
||||||
/>
|
/>
|
||||||
<div v-else class="status-preview status-preview-loading">
|
<div
|
||||||
<i class="icon-spin4 animate-spin"></i>
|
v-else
|
||||||
|
class="status-preview status-preview-loading"
|
||||||
|
>
|
||||||
|
<i class="icon-spin4 animate-spin" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="status-content-wrapper" :class="{ 'tall-status': !showingLongSubject }" v-if="longSubject">
|
<div
|
||||||
<a class="tall-status-hider" :class="{ 'tall-status-hider_focused': isFocused }" v-if="!showingLongSubject" href="#" @click.prevent="showingLongSubject=true">{{$t("general.show_more")}}</a>
|
v-if="longSubject"
|
||||||
<div @click.prevent="linkClicked" class="status-content media-body" v-html="contentHtml"></div>
|
class="status-content-wrapper"
|
||||||
<a v-if="showingLongSubject" href="#" class="status-unhider" @click.prevent="showingLongSubject=false">{{$t("general.show_less")}}</a>
|
:class="{ 'tall-status': !showingLongSubject }"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
v-if="!showingLongSubject"
|
||||||
|
class="tall-status-hider"
|
||||||
|
:class="{ 'tall-status-hider_focused': isFocused }"
|
||||||
|
href="#"
|
||||||
|
@click.prevent="showingLongSubject=true"
|
||||||
|
>{{ $t("general.show_more") }}</a>
|
||||||
|
<div
|
||||||
|
class="status-content media-body"
|
||||||
|
@click.prevent="linkClicked"
|
||||||
|
v-html="contentHtml"
|
||||||
|
/>
|
||||||
|
<a
|
||||||
|
v-if="showingLongSubject"
|
||||||
|
href="#"
|
||||||
|
class="status-unhider"
|
||||||
|
@click.prevent="showingLongSubject=false"
|
||||||
|
>{{ $t("general.show_less") }}</a>
|
||||||
</div>
|
</div>
|
||||||
<div :class="{'tall-status': hideTallStatus}" class="status-content-wrapper" v-else>
|
<div
|
||||||
<a class="tall-status-hider" :class="{ 'tall-status-hider_focused': isFocused }" v-if="hideTallStatus" href="#" @click.prevent="toggleShowMore">{{$t("general.show_more")}}</a>
|
v-else
|
||||||
<div @click.prevent="linkClicked" class="status-content media-body" v-html="contentHtml" v-if="!hideSubjectStatus"></div>
|
:class="{'tall-status': hideTallStatus}"
|
||||||
<div @click.prevent="linkClicked" class="status-content media-body" v-html="status.summary_html" v-else></div>
|
class="status-content-wrapper"
|
||||||
<a v-if="hideSubjectStatus" href="#" class="cw-status-hider" @click.prevent="toggleShowMore">{{$t("general.show_more")}}</a>
|
>
|
||||||
<a v-if="showingMore" href="#" class="status-unhider" @click.prevent="toggleShowMore">{{$t("general.show_less")}}</a>
|
<a
|
||||||
|
v-if="hideTallStatus"
|
||||||
|
class="tall-status-hider"
|
||||||
|
:class="{ 'tall-status-hider_focused': isFocused }"
|
||||||
|
href="#"
|
||||||
|
@click.prevent="toggleShowMore"
|
||||||
|
>{{ $t("general.show_more") }}</a>
|
||||||
|
<div
|
||||||
|
v-if="!hideSubjectStatus"
|
||||||
|
class="status-content media-body"
|
||||||
|
@click.prevent="linkClicked"
|
||||||
|
v-html="contentHtml"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
v-else
|
||||||
|
class="status-content media-body"
|
||||||
|
@click.prevent="linkClicked"
|
||||||
|
v-html="status.summary_html"
|
||||||
|
/>
|
||||||
|
<a
|
||||||
|
v-if="hideSubjectStatus"
|
||||||
|
href="#"
|
||||||
|
class="cw-status-hider"
|
||||||
|
@click.prevent="toggleShowMore"
|
||||||
|
>{{ $t("general.show_more") }}</a>
|
||||||
|
<a
|
||||||
|
v-if="showingMore"
|
||||||
|
href="#"
|
||||||
|
class="status-unhider"
|
||||||
|
@click.prevent="toggleShowMore"
|
||||||
|
>{{ $t("general.show_less") }}</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="status.poll && status.poll.options">
|
<div v-if="status.poll && status.poll.options">
|
||||||
<poll :base-poll="status.poll" />
|
<poll :base-poll="status.poll" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="status.attachments && (!hideSubjectStatus || showingLongSubject)" class="attachments media-body">
|
<div
|
||||||
|
v-if="status.attachments && (!hideSubjectStatus || showingLongSubject)"
|
||||||
|
class="attachments media-body"
|
||||||
|
>
|
||||||
<attachment
|
<attachment
|
||||||
class="non-gallery"
|
|
||||||
v-for="attachment in nonGalleryAttachments"
|
v-for="attachment in nonGalleryAttachments"
|
||||||
|
:key="attachment.id"
|
||||||
|
class="non-gallery"
|
||||||
:size="attachmentSize"
|
:size="attachmentSize"
|
||||||
:nsfw="nsfwClickthrough"
|
:nsfw="nsfwClickthrough"
|
||||||
:attachment="attachment"
|
:attachment="attachment"
|
||||||
:allowPlay="true"
|
:allow-play="true"
|
||||||
:setMedia="setMedia()"
|
:set-media="setMedia()"
|
||||||
:key="attachment.id"
|
|
||||||
/>
|
/>
|
||||||
<gallery
|
<gallery
|
||||||
v-if="galleryAttachments.length > 0"
|
v-if="galleryAttachments.length > 0"
|
||||||
:nsfw="nsfwClickthrough"
|
:nsfw="nsfwClickthrough"
|
||||||
:attachments="galleryAttachments"
|
:attachments="galleryAttachments"
|
||||||
:setMedia="setMedia()"
|
:set-media="setMedia()"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="status.card && !hideSubjectStatus && !noHeading" class="link-preview media-body">
|
<div
|
||||||
<link-preview :card="status.card" :size="attachmentSize" :nsfw="nsfwClickthrough" />
|
v-if="status.card && !hideSubjectStatus && !noHeading"
|
||||||
|
class="link-preview media-body"
|
||||||
|
>
|
||||||
|
<link-preview
|
||||||
|
:card="status.card"
|
||||||
|
:size="attachmentSize"
|
||||||
|
:nsfw="nsfwClickthrough"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<transition name="fade">
|
<transition name="fade">
|
||||||
<div class="favs-repeated-users" v-if="isFocused && combinedFavsAndRepeatsUsers.length > 0">
|
<div
|
||||||
|
v-if="isFocused && combinedFavsAndRepeatsUsers.length > 0"
|
||||||
|
class="favs-repeated-users"
|
||||||
|
>
|
||||||
<div class="stats">
|
<div class="stats">
|
||||||
<div class="stat-count" v-if="statusFromGlobalRepository.rebloggedBy && statusFromGlobalRepository.rebloggedBy.length > 0">
|
<div
|
||||||
|
v-if="statusFromGlobalRepository.rebloggedBy && statusFromGlobalRepository.rebloggedBy.length > 0"
|
||||||
|
class="stat-count"
|
||||||
|
>
|
||||||
<a class="stat-title">{{ $t('status.repeats') }}</a>
|
<a class="stat-title">{{ $t('status.repeats') }}</a>
|
||||||
<div class="stat-number">{{ statusFromGlobalRepository.rebloggedBy.length }}</div>
|
<div class="stat-number">
|
||||||
|
{{ statusFromGlobalRepository.rebloggedBy.length }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="stat-count" v-if="statusFromGlobalRepository.favoritedBy && statusFromGlobalRepository.favoritedBy.length > 0">
|
<div
|
||||||
|
v-if="statusFromGlobalRepository.favoritedBy && statusFromGlobalRepository.favoritedBy.length > 0"
|
||||||
|
class="stat-count"
|
||||||
|
>
|
||||||
<a class="stat-title">{{ $t('status.favorites') }}</a>
|
<a class="stat-title">{{ $t('status.favorites') }}</a>
|
||||||
<div class="stat-number">{{ statusFromGlobalRepository.favoritedBy.length }}</div>
|
<div class="stat-number">
|
||||||
|
{{ statusFromGlobalRepository.favoritedBy.length }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="avatar-row">
|
<div class="avatar-row">
|
||||||
<AvatarList :users="combinedFavsAndRepeatsUsers"></AvatarList>
|
<AvatarList :users="combinedFavsAndRepeatsUsers" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
|
|
||||||
<div v-if="!noHeading && !isPreview" class='status-actions media-body'>
|
<div
|
||||||
|
v-if="!noHeading && !isPreview"
|
||||||
|
class="status-actions media-body"
|
||||||
|
>
|
||||||
<div>
|
<div>
|
||||||
<i class="button-icon icon-reply" v-on:click.prevent="toggleReplying" :title="$t('tool_tip.reply')" :class="{'button-icon-active': replying}" v-if="loggedIn"/>
|
<i
|
||||||
<i class="button-icon button-icon-disabled icon-reply" :title="$t('tool_tip.reply')" v-else />
|
v-if="loggedIn"
|
||||||
<span v-if="status.replies_count > 0">{{status.replies_count}}</span>
|
class="button-icon icon-reply"
|
||||||
|
:title="$t('tool_tip.reply')"
|
||||||
|
:class="{'button-icon-active': replying}"
|
||||||
|
@click.prevent="toggleReplying"
|
||||||
|
/>
|
||||||
|
<i
|
||||||
|
v-else
|
||||||
|
class="button-icon button-icon-disabled icon-reply"
|
||||||
|
:title="$t('tool_tip.reply')"
|
||||||
|
/>
|
||||||
|
<span v-if="status.replies_count > 0">{{ status.replies_count }}</span>
|
||||||
</div>
|
</div>
|
||||||
<retweet-button :visibility='status.visibility' :loggedIn='loggedIn' :status='status'></retweet-button>
|
<retweet-button
|
||||||
<favorite-button :loggedIn='loggedIn' :status='status'></favorite-button>
|
:visibility="status.visibility"
|
||||||
<extra-buttons :status="status" @onError="showError" @onSuccess="clearError"></extra-buttons>
|
:logged-in="loggedIn"
|
||||||
|
:status="status"
|
||||||
|
/>
|
||||||
|
<favorite-button
|
||||||
|
:logged-in="loggedIn"
|
||||||
|
:status="status"
|
||||||
|
/>
|
||||||
|
<extra-buttons
|
||||||
|
:status="status"
|
||||||
|
@onError="showError"
|
||||||
|
@onSuccess="clearError"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="container" v-if="replying">
|
<div
|
||||||
<post-status-form class="reply-body" :reply-to="status.id" :attentions="status.attentions" :repliedUser="status.user" :copy-message-scope="status.visibility" :subject="replySubject" v-on:posted="toggleReplying"/>
|
v-if="replying"
|
||||||
|
class="container"
|
||||||
|
>
|
||||||
|
<post-status-form
|
||||||
|
class="reply-body"
|
||||||
|
:reply-to="status.id"
|
||||||
|
:attentions="status.attentions"
|
||||||
|
:replied-user="status.user"
|
||||||
|
:copy-message-scope="status.visibility"
|
||||||
|
:subject="replySubject"
|
||||||
|
@posted="toggleReplying"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- eslint-enable vue/no-v-html -->
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./status.js" ></script>
|
<script src="./status.js" ></script>
|
||||||
|
|
|
@ -1,7 +1,19 @@
|
||||||
<template>
|
<template>
|
||||||
<div class='still-image' :class='{ animated: animated }' >
|
<div
|
||||||
<canvas ref="canvas" v-if="animated"></canvas>
|
class="still-image"
|
||||||
<img ref="src" :src="src" :referrerpolicy="referrerpolicy" v-on:load="onLoad" @error="onError"/>
|
:class="{ animated: animated }"
|
||||||
|
>
|
||||||
|
<canvas
|
||||||
|
v-if="animated"
|
||||||
|
ref="canvas"
|
||||||
|
/>
|
||||||
|
<img
|
||||||
|
ref="src"
|
||||||
|
:src="src"
|
||||||
|
:referrerpolicy="referrerpolicy"
|
||||||
|
@load="onLoad"
|
||||||
|
@error="onError"
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -1,78 +1,101 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="panel dummy">
|
<div class="panel dummy">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
{{$t('settings.style.preview.header')}}
|
{{ $t('settings.style.preview.header') }}
|
||||||
<span class="badge badge-notification">
|
<span class="badge badge-notification">
|
||||||
99
|
99
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<span class="faint">
|
||||||
|
{{ $t('settings.style.preview.header_faint') }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
<span class="alert error">
|
||||||
<span class="faint">
|
{{ $t('settings.style.preview.error') }}
|
||||||
{{$t('settings.style.preview.header_faint')}}
|
|
||||||
</span>
|
|
||||||
<span class="alert error">
|
|
||||||
{{$t('settings.style.preview.error')}}
|
|
||||||
</span>
|
|
||||||
<button class="btn">
|
|
||||||
{{$t('settings.style.preview.button')}}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="panel-body theme-preview-content">
|
|
||||||
<div class="post">
|
|
||||||
<div class="avatar">
|
|
||||||
( ͡° ͜ʖ ͡°)
|
|
||||||
</div>
|
|
||||||
<div class="content">
|
|
||||||
<h4>
|
|
||||||
{{$t('settings.style.preview.content')}}
|
|
||||||
</h4>
|
|
||||||
|
|
||||||
<i18n path="settings.style.preview.text">
|
|
||||||
<code style="font-family: var(--postCodeFont)">
|
|
||||||
{{$t('settings.style.preview.mono')}}
|
|
||||||
</code>
|
|
||||||
<a style="color: var(--link)">
|
|
||||||
{{$t('settings.style.preview.link')}}
|
|
||||||
</a>
|
|
||||||
</i18n>
|
|
||||||
|
|
||||||
<div class="icons">
|
|
||||||
<i style="color: var(--cBlue)" class="button-icon icon-reply"/>
|
|
||||||
<i style="color: var(--cGreen)" class="button-icon icon-retweet"/>
|
|
||||||
<i style="color: var(--cOrange)" class="button-icon icon-star"/>
|
|
||||||
<i style="color: var(--cRed)" class="button-icon icon-cancel"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="after-post">
|
|
||||||
<div class="avatar-alt">
|
|
||||||
:^)
|
|
||||||
</div>
|
|
||||||
<div class="content">
|
|
||||||
<i18n path="settings.style.preview.fine_print" tag="span" class="faint">
|
|
||||||
<a style="color: var(--faintLink)">
|
|
||||||
{{$t('settings.style.preview.faint_link')}}
|
|
||||||
</a>
|
|
||||||
</i18n>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="separator"></div>
|
|
||||||
|
|
||||||
<span class="alert error">
|
|
||||||
{{$t('settings.style.preview.error')}}
|
|
||||||
</span>
|
|
||||||
<input :value="$t('settings.style.preview.input')" type="text">
|
|
||||||
|
|
||||||
<div class="actions">
|
|
||||||
<span class="checkbox">
|
|
||||||
<input checked="very yes" type="checkbox" id="preview_checkbox">
|
|
||||||
<label for="preview_checkbox">{{$t('settings.style.preview.checkbox')}}</label>
|
|
||||||
</span>
|
</span>
|
||||||
<button class="btn">
|
<button class="btn">
|
||||||
{{$t('settings.style.preview.button')}}
|
{{ $t('settings.style.preview.button') }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="panel-body theme-preview-content">
|
||||||
|
<div class="post">
|
||||||
|
<div class="avatar">
|
||||||
|
( ͡° ͜ʖ ͡°)
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
<h4>
|
||||||
|
{{ $t('settings.style.preview.content') }}
|
||||||
|
</h4>
|
||||||
|
|
||||||
|
<i18n path="settings.style.preview.text">
|
||||||
|
<code style="font-family: var(--postCodeFont)">
|
||||||
|
{{ $t('settings.style.preview.mono') }}
|
||||||
|
</code>
|
||||||
|
<a style="color: var(--link)">
|
||||||
|
{{ $t('settings.style.preview.link') }}
|
||||||
|
</a>
|
||||||
|
</i18n>
|
||||||
|
|
||||||
|
<div class="icons">
|
||||||
|
<i
|
||||||
|
style="color: var(--cBlue)"
|
||||||
|
class="button-icon icon-reply"
|
||||||
|
/>
|
||||||
|
<i
|
||||||
|
style="color: var(--cGreen)"
|
||||||
|
class="button-icon icon-retweet"
|
||||||
|
/>
|
||||||
|
<i
|
||||||
|
style="color: var(--cOrange)"
|
||||||
|
class="button-icon icon-star"
|
||||||
|
/>
|
||||||
|
<i
|
||||||
|
style="color: var(--cRed)"
|
||||||
|
class="button-icon icon-cancel"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="after-post">
|
||||||
|
<div class="avatar-alt">
|
||||||
|
:^)
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
<i18n
|
||||||
|
path="settings.style.preview.fine_print"
|
||||||
|
tag="span"
|
||||||
|
class="faint"
|
||||||
|
>
|
||||||
|
<a style="color: var(--faintLink)">
|
||||||
|
{{ $t('settings.style.preview.faint_link') }}
|
||||||
|
</a>
|
||||||
|
</i18n>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="separator" />
|
||||||
|
|
||||||
|
<span class="alert error">
|
||||||
|
{{ $t('settings.style.preview.error') }}
|
||||||
|
</span>
|
||||||
|
<input
|
||||||
|
:value="$t('settings.style.preview.input')"
|
||||||
|
type="text"
|
||||||
|
>
|
||||||
|
|
||||||
|
<div class="actions">
|
||||||
|
<span class="checkbox">
|
||||||
|
<input
|
||||||
|
id="preview_checkbox"
|
||||||
|
checked="very yes"
|
||||||
|
type="checkbox"
|
||||||
|
>
|
||||||
|
<label for="preview_checkbox">{{ $t('settings.style.preview.checkbox') }}</label>
|
||||||
|
</span>
|
||||||
|
<button class="btn">
|
||||||
|
{{ $t('settings.style.preview.button') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,274 +1,593 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="style-switcher">
|
<div class="style-switcher">
|
||||||
<div class="presets-container">
|
<div class="presets-container">
|
||||||
<div class="save-load">
|
<div class="save-load">
|
||||||
<export-import
|
<export-import
|
||||||
:exportObject='exportedTheme'
|
:export-object="exportedTheme"
|
||||||
:exportLabel='$t("settings.export_theme")'
|
:export-label="$t("settings.export_theme")"
|
||||||
:importLabel='$t("settings.import_theme")'
|
:import-label="$t("settings.import_theme")"
|
||||||
:importFailedText='$t("settings.invalid_theme_imported")'
|
:import-failed-text="$t("settings.invalid_theme_imported")"
|
||||||
:onImport='onImport'
|
:on-import="onImport"
|
||||||
:validator='importValidator'>
|
:validator="importValidator"
|
||||||
<template slot="before">
|
>
|
||||||
<div class="presets">
|
<template slot="before">
|
||||||
{{$t('settings.presets')}}
|
<div class="presets">
|
||||||
<label for="preset-switcher" class='select'>
|
{{ $t('settings.presets') }}
|
||||||
<select id="preset-switcher" v-model="selected" class="preset-switcher">
|
<label
|
||||||
<option v-for="style in availableStyles"
|
for="preset-switcher"
|
||||||
:value="style"
|
class="select"
|
||||||
:style="{
|
>
|
||||||
backgroundColor: style[1] || style.theme.colors.bg,
|
<select
|
||||||
color: style[3] || style.theme.colors.text
|
id="preset-switcher"
|
||||||
}">
|
v-model="selected"
|
||||||
{{style[0] || style.name}}
|
class="preset-switcher"
|
||||||
</option>
|
>
|
||||||
</select>
|
<option
|
||||||
<i class="icon-down-open"/>
|
v-for="style in availableStyles"
|
||||||
</label>
|
:key="style.name"
|
||||||
</div>
|
:value="style"
|
||||||
</template>
|
:style="{
|
||||||
</export-import>
|
backgroundColor: style[1] || style.theme.colors.bg,
|
||||||
|
color: style[3] || style.theme.colors.text
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
{{ style[0] || style.name }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<i class="icon-down-open" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</export-import>
|
||||||
|
</div>
|
||||||
|
<div class="save-load-options">
|
||||||
|
<span class="keep-option">
|
||||||
|
<input
|
||||||
|
id="keep-color"
|
||||||
|
v-model="keepColor"
|
||||||
|
type="checkbox"
|
||||||
|
>
|
||||||
|
<label for="keep-color">{{ $t('settings.style.switcher.keep_color') }}</label>
|
||||||
|
</span>
|
||||||
|
<span class="keep-option">
|
||||||
|
<input
|
||||||
|
id="keep-shadows"
|
||||||
|
v-model="keepShadows"
|
||||||
|
type="checkbox"
|
||||||
|
>
|
||||||
|
<label for="keep-shadows">{{ $t('settings.style.switcher.keep_shadows') }}</label>
|
||||||
|
</span>
|
||||||
|
<span class="keep-option">
|
||||||
|
<input
|
||||||
|
id="keep-opacity"
|
||||||
|
v-model="keepOpacity"
|
||||||
|
type="checkbox"
|
||||||
|
>
|
||||||
|
<label for="keep-opacity">{{ $t('settings.style.switcher.keep_opacity') }}</label>
|
||||||
|
</span>
|
||||||
|
<span class="keep-option">
|
||||||
|
<input
|
||||||
|
id="keep-roundness"
|
||||||
|
v-model="keepRoundness"
|
||||||
|
type="checkbox"
|
||||||
|
>
|
||||||
|
<label for="keep-roundness">{{ $t('settings.style.switcher.keep_roundness') }}</label>
|
||||||
|
</span>
|
||||||
|
<span class="keep-option">
|
||||||
|
<input
|
||||||
|
id="keep-fonts"
|
||||||
|
v-model="keepFonts"
|
||||||
|
type="checkbox"
|
||||||
|
>
|
||||||
|
<label for="keep-fonts">{{ $t('settings.style.switcher.keep_fonts') }}</label>
|
||||||
|
</span>
|
||||||
|
<p>{{ $t('settings.style.switcher.save_load_hint') }}</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="save-load-options">
|
|
||||||
<span class="keep-option">
|
<div class="preview-container">
|
||||||
<input
|
<preview :style="previewRules" />
|
||||||
id="keep-color"
|
</div>
|
||||||
type="checkbox"
|
|
||||||
v-model="keepColor">
|
<keep-alive>
|
||||||
<label for="keep-color">{{$t('settings.style.switcher.keep_color')}}</label>
|
<tab-switcher key="style-tweak">
|
||||||
</span>
|
<div
|
||||||
<span class="keep-option">
|
:label="$t('settings.style.common_colors._tab_label')"
|
||||||
<input
|
class="color-container"
|
||||||
id="keep-shadows"
|
>
|
||||||
type="checkbox"
|
<div class="tab-header">
|
||||||
v-model="keepShadows">
|
<p>{{ $t('settings.theme_help') }}</p>
|
||||||
<label for="keep-shadows">{{$t('settings.style.switcher.keep_shadows')}}</label>
|
<button
|
||||||
</span>
|
class="btn"
|
||||||
<span class="keep-option">
|
@click="clearOpacity"
|
||||||
<input
|
>
|
||||||
id="keep-opacity"
|
{{ $t('settings.style.switcher.clear_opacity') }}
|
||||||
type="checkbox"
|
</button>
|
||||||
v-model="keepOpacity">
|
<button
|
||||||
<label for="keep-opacity">{{$t('settings.style.switcher.keep_opacity')}}</label>
|
class="btn"
|
||||||
</span>
|
@click="clearV1"
|
||||||
<span class="keep-option">
|
>
|
||||||
<input
|
{{ $t('settings.style.switcher.clear_all') }}
|
||||||
id="keep-roundness"
|
</button>
|
||||||
type="checkbox"
|
</div>
|
||||||
v-model="keepRoundness">
|
<p>{{ $t('settings.theme_help_v2_1') }}</p>
|
||||||
<label for="keep-roundness">{{$t('settings.style.switcher.keep_roundness')}}</label>
|
<h4>{{ $t('settings.style.common_colors.main') }}</h4>
|
||||||
</span>
|
<div class="color-item">
|
||||||
<span class="keep-option">
|
<ColorInput
|
||||||
<input
|
v-model="bgColorLocal"
|
||||||
id="keep-fonts"
|
name="bgColor"
|
||||||
type="checkbox"
|
:label="$t('settings.background')"
|
||||||
v-model="keepFonts">
|
/>
|
||||||
<label for="keep-fonts">{{$t('settings.style.switcher.keep_fonts')}}</label>
|
<OpacityInput
|
||||||
</span>
|
v-model="bgOpacityLocal"
|
||||||
<p>{{$t('settings.style.switcher.save_load_hint')}}</p>
|
name="bgOpacity"
|
||||||
|
:fallback="previewTheme.opacity.bg || 1"
|
||||||
|
/>
|
||||||
|
<ColorInput
|
||||||
|
v-model="textColorLocal"
|
||||||
|
name="textColor"
|
||||||
|
:label="$t('settings.text')"
|
||||||
|
/>
|
||||||
|
<ContrastRatio :contrast="previewContrast.bgText" />
|
||||||
|
<ColorInput
|
||||||
|
v-model="linkColorLocal"
|
||||||
|
name="linkColor"
|
||||||
|
:label="$t('settings.links')"
|
||||||
|
/>
|
||||||
|
<ContrastRatio :contrast="previewContrast.bgLink" />
|
||||||
|
</div>
|
||||||
|
<div class="color-item">
|
||||||
|
<ColorInput
|
||||||
|
v-model="fgColorLocal"
|
||||||
|
name="fgColor"
|
||||||
|
:label="$t('settings.foreground')"
|
||||||
|
/>
|
||||||
|
<ColorInput
|
||||||
|
v-model="fgTextColorLocal"
|
||||||
|
name="fgTextColor"
|
||||||
|
:label="$t('settings.text')"
|
||||||
|
:fallback="previewTheme.colors.fgText"
|
||||||
|
/>
|
||||||
|
<ColorInput
|
||||||
|
v-model="fgLinkColorLocal"
|
||||||
|
name="fgLinkColor"
|
||||||
|
:label="$t('settings.links')"
|
||||||
|
:fallback="previewTheme.colors.fgLink"
|
||||||
|
/>
|
||||||
|
<p>{{ $t('settings.style.common_colors.foreground_hint') }}</p>
|
||||||
|
</div>
|
||||||
|
<h4>{{ $t('settings.style.common_colors.rgbo') }}</h4>
|
||||||
|
<div class="color-item">
|
||||||
|
<ColorInput
|
||||||
|
v-model="cRedColorLocal"
|
||||||
|
name="cRedColor"
|
||||||
|
:label="$t('settings.cRed')"
|
||||||
|
/>
|
||||||
|
<ContrastRatio :contrast="previewContrast.bgRed" />
|
||||||
|
<ColorInput
|
||||||
|
v-model="cBlueColorLocal"
|
||||||
|
name="cBlueColor"
|
||||||
|
:label="$t('settings.cBlue')"
|
||||||
|
/>
|
||||||
|
<ContrastRatio :contrast="previewContrast.bgBlue" />
|
||||||
|
</div>
|
||||||
|
<div class="color-item">
|
||||||
|
<ColorInput
|
||||||
|
v-model="cGreenColorLocal"
|
||||||
|
name="cGreenColor"
|
||||||
|
:label="$t('settings.cGreen')"
|
||||||
|
/>
|
||||||
|
<ContrastRatio :contrast="previewContrast.bgGreen" />
|
||||||
|
<ColorInput
|
||||||
|
v-model="cOrangeColorLocal"
|
||||||
|
name="cOrangeColor"
|
||||||
|
:label="$t('settings.cOrange')"
|
||||||
|
/>
|
||||||
|
<ContrastRatio :contrast="previewContrast.bgOrange" />
|
||||||
|
</div>
|
||||||
|
<p>{{ $t('settings.theme_help_v2_2') }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
:label="$t('settings.style.advanced_colors._tab_label')"
|
||||||
|
class="color-container"
|
||||||
|
>
|
||||||
|
<div class="tab-header">
|
||||||
|
<p>{{ $t('settings.theme_help') }}</p>
|
||||||
|
<button
|
||||||
|
class="btn"
|
||||||
|
@click="clearOpacity"
|
||||||
|
>
|
||||||
|
{{ $t('settings.style.switcher.clear_opacity') }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="btn"
|
||||||
|
@click="clearV1"
|
||||||
|
>
|
||||||
|
{{ $t('settings.style.switcher.clear_all') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="color-item">
|
||||||
|
<h4>{{ $t('settings.style.advanced_colors.alert') }}</h4>
|
||||||
|
<ColorInput
|
||||||
|
v-model="alertErrorColorLocal"
|
||||||
|
name="alertError"
|
||||||
|
:label="$t('settings.style.advanced_colors.alert_error')"
|
||||||
|
:fallback="previewTheme.colors.alertError"
|
||||||
|
/>
|
||||||
|
<ContrastRatio :contrast="previewContrast.alertError" />
|
||||||
|
</div>
|
||||||
|
<div class="color-item">
|
||||||
|
<h4>{{ $t('settings.style.advanced_colors.badge') }}</h4>
|
||||||
|
<ColorInput
|
||||||
|
v-model="badgeNotificationColorLocal"
|
||||||
|
name="badgeNotification"
|
||||||
|
:label="$t('settings.style.advanced_colors.badge_notification')"
|
||||||
|
:fallback="previewTheme.colors.badgeNotification"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="color-item">
|
||||||
|
<h4>{{ $t('settings.style.advanced_colors.panel_header') }}</h4>
|
||||||
|
<ColorInput
|
||||||
|
v-model="panelColorLocal"
|
||||||
|
name="panelColor"
|
||||||
|
:fallback="fgColorLocal"
|
||||||
|
:label="$t('settings.background')"
|
||||||
|
/>
|
||||||
|
<OpacityInput
|
||||||
|
v-model="panelOpacityLocal"
|
||||||
|
name="panelOpacity"
|
||||||
|
:fallback="previewTheme.opacity.panel || 1"
|
||||||
|
/>
|
||||||
|
<ColorInput
|
||||||
|
v-model="panelTextColorLocal"
|
||||||
|
name="panelTextColor"
|
||||||
|
:fallback="previewTheme.colors.panelText"
|
||||||
|
:label="$t('settings.text')"
|
||||||
|
/>
|
||||||
|
<ContrastRatio
|
||||||
|
:contrast="previewContrast.panelText"
|
||||||
|
large="1"
|
||||||
|
/>
|
||||||
|
<ColorInput
|
||||||
|
v-model="panelLinkColorLocal"
|
||||||
|
name="panelLinkColor"
|
||||||
|
:fallback="previewTheme.colors.panelLink"
|
||||||
|
:label="$t('settings.links')"
|
||||||
|
/>
|
||||||
|
<ContrastRatio
|
||||||
|
:contrast="previewContrast.panelLink"
|
||||||
|
large="1"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="color-item">
|
||||||
|
<h4>{{ $t('settings.style.advanced_colors.top_bar') }}</h4>
|
||||||
|
<ColorInput
|
||||||
|
v-model="topBarColorLocal"
|
||||||
|
name="topBarColor"
|
||||||
|
:fallback="fgColorLocal"
|
||||||
|
:label="$t('settings.background')"
|
||||||
|
/>
|
||||||
|
<ColorInput
|
||||||
|
v-model="topBarTextColorLocal"
|
||||||
|
name="topBarTextColor"
|
||||||
|
:fallback="previewTheme.colors.topBarText"
|
||||||
|
:label="$t('settings.text')"
|
||||||
|
/>
|
||||||
|
<ContrastRatio :contrast="previewContrast.topBarText" />
|
||||||
|
<ColorInput
|
||||||
|
v-model="topBarLinkColorLocal"
|
||||||
|
name="topBarLinkColor"
|
||||||
|
:fallback="previewTheme.colors.topBarLink"
|
||||||
|
:label="$t('settings.links')"
|
||||||
|
/>
|
||||||
|
<ContrastRatio :contrast="previewContrast.topBarLink" />
|
||||||
|
</div>
|
||||||
|
<div class="color-item">
|
||||||
|
<h4>{{ $t('settings.style.advanced_colors.inputs') }}</h4>
|
||||||
|
<ColorInput
|
||||||
|
v-model="inputColorLocal"
|
||||||
|
name="inputColor"
|
||||||
|
:fallback="fgColorLocal"
|
||||||
|
:label="$t('settings.background')"
|
||||||
|
/>
|
||||||
|
<OpacityInput
|
||||||
|
v-model="inputOpacityLocal"
|
||||||
|
name="inputOpacity"
|
||||||
|
:fallback="previewTheme.opacity.input || 1"
|
||||||
|
/>
|
||||||
|
<ColorInput
|
||||||
|
v-model="inputTextColorLocal"
|
||||||
|
name="inputTextColor"
|
||||||
|
:fallback="previewTheme.colors.inputText"
|
||||||
|
:label="$t('settings.text')"
|
||||||
|
/>
|
||||||
|
<ContrastRatio :contrast="previewContrast.inputText" />
|
||||||
|
</div>
|
||||||
|
<div class="color-item">
|
||||||
|
<h4>{{ $t('settings.style.advanced_colors.buttons') }}</h4>
|
||||||
|
<ColorInput
|
||||||
|
v-model="btnColorLocal"
|
||||||
|
name="btnColor"
|
||||||
|
:fallback="fgColorLocal"
|
||||||
|
:label="$t('settings.background')"
|
||||||
|
/>
|
||||||
|
<OpacityInput
|
||||||
|
v-model="btnOpacityLocal"
|
||||||
|
name="btnOpacity"
|
||||||
|
:fallback="previewTheme.opacity.btn || 1"
|
||||||
|
/>
|
||||||
|
<ColorInput
|
||||||
|
v-model="btnTextColorLocal"
|
||||||
|
name="btnTextColor"
|
||||||
|
:fallback="previewTheme.colors.btnText"
|
||||||
|
:label="$t('settings.text')"
|
||||||
|
/>
|
||||||
|
<ContrastRatio :contrast="previewContrast.btnText" />
|
||||||
|
</div>
|
||||||
|
<div class="color-item">
|
||||||
|
<h4>{{ $t('settings.style.advanced_colors.borders') }}</h4>
|
||||||
|
<ColorInput
|
||||||
|
v-model="borderColorLocal"
|
||||||
|
name="borderColor"
|
||||||
|
:fallback="previewTheme.colors.border"
|
||||||
|
:label="$t('settings.style.common.color')"
|
||||||
|
/>
|
||||||
|
<OpacityInput
|
||||||
|
v-model="borderOpacityLocal"
|
||||||
|
name="borderOpacity"
|
||||||
|
:fallback="previewTheme.opacity.border || 1"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="color-item">
|
||||||
|
<h4>{{ $t('settings.style.advanced_colors.faint_text') }}</h4>
|
||||||
|
<ColorInput
|
||||||
|
v-model="faintColorLocal"
|
||||||
|
name="faintColor"
|
||||||
|
:fallback="previewTheme.colors.faint || 1"
|
||||||
|
:label="$t('settings.text')"
|
||||||
|
/>
|
||||||
|
<ColorInput
|
||||||
|
v-model="faintLinkColorLocal"
|
||||||
|
name="faintLinkColor"
|
||||||
|
:fallback="previewTheme.colors.faintLink"
|
||||||
|
:label="$t('settings.links')"
|
||||||
|
/>
|
||||||
|
<ColorInput
|
||||||
|
v-model="panelFaintColorLocal"
|
||||||
|
name="panelFaintColor"
|
||||||
|
:fallback="previewTheme.colors.panelFaint"
|
||||||
|
:label="$t('settings.style.advanced_colors.panel_header')"
|
||||||
|
/>
|
||||||
|
<OpacityInput
|
||||||
|
v-model="faintOpacityLocal"
|
||||||
|
name="faintOpacity"
|
||||||
|
:fallback="previewTheme.opacity.faint || 0.5"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
:label="$t('settings.style.radii._tab_label')"
|
||||||
|
class="radius-container"
|
||||||
|
>
|
||||||
|
<div class="tab-header">
|
||||||
|
<p>{{ $t('settings.radii_help') }}</p>
|
||||||
|
<button
|
||||||
|
class="btn"
|
||||||
|
@click="clearRoundness"
|
||||||
|
>
|
||||||
|
{{ $t('settings.style.switcher.clear_all') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<RangeInput
|
||||||
|
v-model="btnRadiusLocal"
|
||||||
|
name="btnRadius"
|
||||||
|
:label="$t('settings.btnRadius')"
|
||||||
|
:fallback="previewTheme.radii.btn"
|
||||||
|
max="16"
|
||||||
|
hard-min="0"
|
||||||
|
/>
|
||||||
|
<RangeInput
|
||||||
|
v-model="inputRadiusLocal"
|
||||||
|
name="inputRadius"
|
||||||
|
:label="$t('settings.inputRadius')"
|
||||||
|
:fallback="previewTheme.radii.input"
|
||||||
|
max="9"
|
||||||
|
hard-min="0"
|
||||||
|
/>
|
||||||
|
<RangeInput
|
||||||
|
v-model="checkboxRadiusLocal"
|
||||||
|
name="checkboxRadius"
|
||||||
|
:label="$t('settings.checkboxRadius')"
|
||||||
|
:fallback="previewTheme.radii.checkbox"
|
||||||
|
max="16"
|
||||||
|
hard-min="0"
|
||||||
|
/>
|
||||||
|
<RangeInput
|
||||||
|
v-model="panelRadiusLocal"
|
||||||
|
name="panelRadius"
|
||||||
|
:label="$t('settings.panelRadius')"
|
||||||
|
:fallback="previewTheme.radii.panel"
|
||||||
|
max="50"
|
||||||
|
hard-min="0"
|
||||||
|
/>
|
||||||
|
<RangeInput
|
||||||
|
v-model="avatarRadiusLocal"
|
||||||
|
name="avatarRadius"
|
||||||
|
:label="$t('settings.avatarRadius')"
|
||||||
|
:fallback="previewTheme.radii.avatar"
|
||||||
|
max="28"
|
||||||
|
hard-min="0"
|
||||||
|
/>
|
||||||
|
<RangeInput
|
||||||
|
v-model="avatarAltRadiusLocal"
|
||||||
|
name="avatarAltRadius"
|
||||||
|
:label="$t('settings.avatarAltRadius')"
|
||||||
|
:fallback="previewTheme.radii.avatarAlt"
|
||||||
|
max="28"
|
||||||
|
hard-min="0"
|
||||||
|
/>
|
||||||
|
<RangeInput
|
||||||
|
v-model="attachmentRadiusLocal"
|
||||||
|
name="attachmentRadius"
|
||||||
|
:label="$t('settings.attachmentRadius')"
|
||||||
|
:fallback="previewTheme.radii.attachment"
|
||||||
|
max="50"
|
||||||
|
hard-min="0"
|
||||||
|
/>
|
||||||
|
<RangeInput
|
||||||
|
v-model="tooltipRadiusLocal"
|
||||||
|
name="tooltipRadius"
|
||||||
|
:label="$t('settings.tooltipRadius')"
|
||||||
|
:fallback="previewTheme.radii.tooltip"
|
||||||
|
max="50"
|
||||||
|
hard-min="0"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
:label="$t('settings.style.shadows._tab_label')"
|
||||||
|
class="shadow-container"
|
||||||
|
>
|
||||||
|
<div class="tab-header shadow-selector">
|
||||||
|
<div class="select-container">
|
||||||
|
{{ $t('settings.style.shadows.component') }}
|
||||||
|
<label
|
||||||
|
for="shadow-switcher"
|
||||||
|
class="select"
|
||||||
|
>
|
||||||
|
<select
|
||||||
|
id="shadow-switcher"
|
||||||
|
v-model="shadowSelected"
|
||||||
|
class="shadow-switcher"
|
||||||
|
>
|
||||||
|
<option
|
||||||
|
v-for="shadow in shadowsAvailable"
|
||||||
|
:key="shadow"
|
||||||
|
:value="shadow"
|
||||||
|
>
|
||||||
|
{{ $t('settings.style.shadows.components.' + shadow) }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<i class="icon-down-open" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="override">
|
||||||
|
<label
|
||||||
|
for="override"
|
||||||
|
class="label"
|
||||||
|
>
|
||||||
|
{{ $t('settings.style.shadows.override') }}
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="override"
|
||||||
|
v-model="currentShadowOverriden"
|
||||||
|
name="override"
|
||||||
|
class="input-override"
|
||||||
|
type="checkbox"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="checkbox-label"
|
||||||
|
for="override"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
class="btn"
|
||||||
|
@click="clearShadows"
|
||||||
|
>
|
||||||
|
{{ $t('settings.style.switcher.clear_all') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<shadow-control
|
||||||
|
v-model="currentShadow"
|
||||||
|
:ready="!!currentShadowFallback"
|
||||||
|
:fallback="currentShadowFallback"
|
||||||
|
/>
|
||||||
|
<div v-if="shadowSelected === 'avatar' || shadowSelected === 'avatarStatus'">
|
||||||
|
<i18n
|
||||||
|
path="settings.style.shadows.filter_hint.always_drop_shadow"
|
||||||
|
tag="p"
|
||||||
|
>
|
||||||
|
<code>filter: drop-shadow()</code>
|
||||||
|
</i18n>
|
||||||
|
<p>{{ $t('settings.style.shadows.filter_hint.avatar_inset') }}</p>
|
||||||
|
<i18n
|
||||||
|
path="settings.style.shadows.filter_hint.drop_shadow_syntax"
|
||||||
|
tag="p"
|
||||||
|
>
|
||||||
|
<code>drop-shadow</code>
|
||||||
|
<code>spread-radius</code>
|
||||||
|
<code>inset</code>
|
||||||
|
</i18n>
|
||||||
|
<i18n
|
||||||
|
path="settings.style.shadows.filter_hint.inset_classic"
|
||||||
|
tag="p"
|
||||||
|
>
|
||||||
|
<code>box-shadow</code>
|
||||||
|
</i18n>
|
||||||
|
<p>{{ $t('settings.style.shadows.filter_hint.spread_zero') }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
:label="$t('settings.style.fonts._tab_label')"
|
||||||
|
class="fonts-container"
|
||||||
|
>
|
||||||
|
<div class="tab-header">
|
||||||
|
<p>{{ $t('settings.style.fonts.help') }}</p>
|
||||||
|
<button
|
||||||
|
class="btn"
|
||||||
|
@click="clearFonts"
|
||||||
|
>
|
||||||
|
{{ $t('settings.style.switcher.clear_all') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<FontControl
|
||||||
|
v-model="fontsLocal.interface"
|
||||||
|
name="ui"
|
||||||
|
:label="$t('settings.style.fonts.components.interface')"
|
||||||
|
:fallback="previewTheme.fonts.interface"
|
||||||
|
no-inherit="1"
|
||||||
|
/>
|
||||||
|
<FontControl
|
||||||
|
v-model="fontsLocal.input"
|
||||||
|
name="input"
|
||||||
|
:label="$t('settings.style.fonts.components.input')"
|
||||||
|
:fallback="previewTheme.fonts.input"
|
||||||
|
/>
|
||||||
|
<FontControl
|
||||||
|
v-model="fontsLocal.post"
|
||||||
|
name="post"
|
||||||
|
:label="$t('settings.style.fonts.components.post')"
|
||||||
|
:fallback="previewTheme.fonts.post"
|
||||||
|
/>
|
||||||
|
<FontControl
|
||||||
|
v-model="fontsLocal.postCode"
|
||||||
|
name="postCode"
|
||||||
|
:label="$t('settings.style.fonts.components.postCode')"
|
||||||
|
:fallback="previewTheme.fonts.postCode"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</tab-switcher>
|
||||||
|
</keep-alive>
|
||||||
|
|
||||||
|
<div class="apply-container">
|
||||||
|
<button
|
||||||
|
class="btn submit"
|
||||||
|
:disabled="!themeValid"
|
||||||
|
@click="setCustomTheme"
|
||||||
|
>
|
||||||
|
{{ $t('general.apply') }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="btn"
|
||||||
|
@click="clearAll"
|
||||||
|
>
|
||||||
|
{{ $t('settings.style.switcher.reset') }}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="preview-container">
|
|
||||||
<preview :style="previewRules"/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<keep-alive>
|
|
||||||
<tab-switcher key="style-tweak">
|
|
||||||
<div :label="$t('settings.style.common_colors._tab_label')" class="color-container">
|
|
||||||
<div class="tab-header">
|
|
||||||
<p>{{$t('settings.theme_help')}}</p>
|
|
||||||
<button class="btn" @click="clearOpacity">{{$t('settings.style.switcher.clear_opacity')}}</button>
|
|
||||||
<button class="btn" @click="clearV1">{{$t('settings.style.switcher.clear_all')}}</button>
|
|
||||||
</div>
|
|
||||||
<p>{{$t('settings.theme_help_v2_1')}}</p>
|
|
||||||
<h4>{{ $t('settings.style.common_colors.main') }}</h4>
|
|
||||||
<div class="color-item">
|
|
||||||
<ColorInput name="bgColor" v-model="bgColorLocal" :label="$t('settings.background')"/>
|
|
||||||
<OpacityInput name="bgOpacity" v-model="bgOpacityLocal" :fallback="previewTheme.opacity.bg || 1"/>
|
|
||||||
<ColorInput name="textColor" v-model="textColorLocal" :label="$t('settings.text')"/>
|
|
||||||
<ContrastRatio :contrast="previewContrast.bgText"/>
|
|
||||||
<ColorInput name="linkColor" v-model="linkColorLocal" :label="$t('settings.links')"/>
|
|
||||||
<ContrastRatio :contrast="previewContrast.bgLink"/>
|
|
||||||
</div>
|
|
||||||
<div class="color-item">
|
|
||||||
<ColorInput name="fgColor" v-model="fgColorLocal" :label="$t('settings.foreground')"/>
|
|
||||||
<ColorInput name="fgTextColor" v-model="fgTextColorLocal" :label="$t('settings.text')" :fallback="previewTheme.colors.fgText"/>
|
|
||||||
<ColorInput name="fgLinkColor" v-model="fgLinkColorLocal" :label="$t('settings.links')" :fallback="previewTheme.colors.fgLink"/>
|
|
||||||
<p>{{ $t('settings.style.common_colors.foreground_hint') }}</p>
|
|
||||||
</div>
|
|
||||||
<h4>{{ $t('settings.style.common_colors.rgbo') }}</h4>
|
|
||||||
<div class="color-item">
|
|
||||||
<ColorInput name="cRedColor" v-model="cRedColorLocal" :label="$t('settings.cRed')"/>
|
|
||||||
<ContrastRatio :contrast="previewContrast.bgRed"/>
|
|
||||||
<ColorInput name="cBlueColor" v-model="cBlueColorLocal" :label="$t('settings.cBlue')"/>
|
|
||||||
<ContrastRatio :contrast="previewContrast.bgBlue"/>
|
|
||||||
</div>
|
|
||||||
<div class="color-item">
|
|
||||||
<ColorInput name="cGreenColor" v-model="cGreenColorLocal" :label="$t('settings.cGreen')"/>
|
|
||||||
<ContrastRatio :contrast="previewContrast.bgGreen"/>
|
|
||||||
<ColorInput name="cOrangeColor" v-model="cOrangeColorLocal" :label="$t('settings.cOrange')"/>
|
|
||||||
<ContrastRatio :contrast="previewContrast.bgOrange"/>
|
|
||||||
</div>
|
|
||||||
<p>{{$t('settings.theme_help_v2_2')}}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div :label="$t('settings.style.advanced_colors._tab_label')" class="color-container">
|
|
||||||
<div class="tab-header">
|
|
||||||
<p>{{$t('settings.theme_help')}}</p>
|
|
||||||
<button class="btn" @click="clearOpacity">{{$t('settings.style.switcher.clear_opacity')}}</button>
|
|
||||||
<button class="btn" @click="clearV1">{{$t('settings.style.switcher.clear_all')}}</button>
|
|
||||||
</div>
|
|
||||||
<div class="color-item">
|
|
||||||
<h4>{{ $t('settings.style.advanced_colors.alert') }}</h4>
|
|
||||||
<ColorInput name="alertError" v-model="alertErrorColorLocal" :label="$t('settings.style.advanced_colors.alert_error')" :fallback="previewTheme.colors.alertError"/>
|
|
||||||
<ContrastRatio :contrast="previewContrast.alertError"/>
|
|
||||||
</div>
|
|
||||||
<div class="color-item">
|
|
||||||
<h4>{{ $t('settings.style.advanced_colors.badge') }}</h4>
|
|
||||||
<ColorInput name="badgeNotification" v-model="badgeNotificationColorLocal" :label="$t('settings.style.advanced_colors.badge_notification')" :fallback="previewTheme.colors.badgeNotification"/>
|
|
||||||
</div>
|
|
||||||
<div class="color-item">
|
|
||||||
<h4>{{ $t('settings.style.advanced_colors.panel_header') }}</h4>
|
|
||||||
<ColorInput name="panelColor" v-model="panelColorLocal" :fallback="fgColorLocal" :label="$t('settings.background')"/>
|
|
||||||
<OpacityInput name="panelOpacity" v-model="panelOpacityLocal" :fallback="previewTheme.opacity.panel || 1"/>
|
|
||||||
<ColorInput name="panelTextColor" v-model="panelTextColorLocal" :fallback="previewTheme.colors.panelText" :label="$t('settings.text')"/>
|
|
||||||
<ContrastRatio :contrast="previewContrast.panelText" large="1"/>
|
|
||||||
<ColorInput name="panelLinkColor" v-model="panelLinkColorLocal" :fallback="previewTheme.colors.panelLink" :label="$t('settings.links')"/>
|
|
||||||
<ContrastRatio :contrast="previewContrast.panelLink" large="1"/>
|
|
||||||
</div>
|
|
||||||
<div class="color-item">
|
|
||||||
<h4>{{ $t('settings.style.advanced_colors.top_bar') }}</h4>
|
|
||||||
<ColorInput name="topBarColor" v-model="topBarColorLocal" :fallback="fgColorLocal" :label="$t('settings.background')"/>
|
|
||||||
<ColorInput name="topBarTextColor" v-model="topBarTextColorLocal" :fallback="previewTheme.colors.topBarText" :label="$t('settings.text')"/>
|
|
||||||
<ContrastRatio :contrast="previewContrast.topBarText"/>
|
|
||||||
<ColorInput name="topBarLinkColor" v-model="topBarLinkColorLocal" :fallback="previewTheme.colors.topBarLink" :label="$t('settings.links')"/>
|
|
||||||
<ContrastRatio :contrast="previewContrast.topBarLink"/>
|
|
||||||
</div>
|
|
||||||
<div class="color-item">
|
|
||||||
<h4>{{ $t('settings.style.advanced_colors.inputs') }}</h4>
|
|
||||||
<ColorInput name="inputColor" v-model="inputColorLocal" :fallback="fgColorLocal" :label="$t('settings.background')"/>
|
|
||||||
<OpacityInput name="inputOpacity" v-model="inputOpacityLocal" :fallback="previewTheme.opacity.input || 1"/>
|
|
||||||
<ColorInput name="inputTextColor" v-model="inputTextColorLocal" :fallback="previewTheme.colors.inputText" :label="$t('settings.text')"/>
|
|
||||||
<ContrastRatio :contrast="previewContrast.inputText"/>
|
|
||||||
</div>
|
|
||||||
<div class="color-item">
|
|
||||||
<h4>{{ $t('settings.style.advanced_colors.buttons') }}</h4>
|
|
||||||
<ColorInput name="btnColor" v-model="btnColorLocal" :fallback="fgColorLocal" :label="$t('settings.background')"/>
|
|
||||||
<OpacityInput name="btnOpacity" v-model="btnOpacityLocal" :fallback="previewTheme.opacity.btn || 1"/>
|
|
||||||
<ColorInput name="btnTextColor" v-model="btnTextColorLocal" :fallback="previewTheme.colors.btnText" :label="$t('settings.text')"/>
|
|
||||||
<ContrastRatio :contrast="previewContrast.btnText"/>
|
|
||||||
</div>
|
|
||||||
<div class="color-item">
|
|
||||||
<h4>{{ $t('settings.style.advanced_colors.borders') }}</h4>
|
|
||||||
<ColorInput name="borderColor" v-model="borderColorLocal" :fallback="previewTheme.colors.border" :label="$t('settings.style.common.color')"/>
|
|
||||||
<OpacityInput name="borderOpacity" v-model="borderOpacityLocal" :fallback="previewTheme.opacity.border || 1"/>
|
|
||||||
</div>
|
|
||||||
<div class="color-item">
|
|
||||||
<h4>{{ $t('settings.style.advanced_colors.faint_text') }}</h4>
|
|
||||||
<ColorInput name="faintColor" v-model="faintColorLocal" :fallback="previewTheme.colors.faint || 1" :label="$t('settings.text')"/>
|
|
||||||
<ColorInput name="faintLinkColor" v-model="faintLinkColorLocal" :fallback="previewTheme.colors.faintLink" :label="$t('settings.links')"/>
|
|
||||||
<ColorInput name="panelFaintColor" v-model="panelFaintColorLocal" :fallback="previewTheme.colors.panelFaint" :label="$t('settings.style.advanced_colors.panel_header')"/>
|
|
||||||
<OpacityInput name="faintOpacity" v-model="faintOpacityLocal" :fallback="previewTheme.opacity.faint || 0.5"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div :label="$t('settings.style.radii._tab_label')" class="radius-container">
|
|
||||||
<div class="tab-header">
|
|
||||||
<p>{{$t('settings.radii_help')}}</p>
|
|
||||||
<button class="btn" @click="clearRoundness">{{$t('settings.style.switcher.clear_all')}}</button>
|
|
||||||
</div>
|
|
||||||
<RangeInput name="btnRadius" :label="$t('settings.btnRadius')" v-model="btnRadiusLocal" :fallback="previewTheme.radii.btn" max="16" hardMin="0"/>
|
|
||||||
<RangeInput name="inputRadius" :label="$t('settings.inputRadius')" v-model="inputRadiusLocal" :fallback="previewTheme.radii.input" max="9" hardMin="0"/>
|
|
||||||
<RangeInput name="checkboxRadius" :label="$t('settings.checkboxRadius')" v-model="checkboxRadiusLocal" :fallback="previewTheme.radii.checkbox" max="16" hardMin="0"/>
|
|
||||||
<RangeInput name="panelRadius" :label="$t('settings.panelRadius')" v-model="panelRadiusLocal" :fallback="previewTheme.radii.panel" max="50" hardMin="0"/>
|
|
||||||
<RangeInput name="avatarRadius" :label="$t('settings.avatarRadius')" v-model="avatarRadiusLocal" :fallback="previewTheme.radii.avatar" max="28" hardMin="0"/>
|
|
||||||
<RangeInput name="avatarAltRadius" :label="$t('settings.avatarAltRadius')" v-model="avatarAltRadiusLocal" :fallback="previewTheme.radii.avatarAlt" max="28" hardMin="0"/>
|
|
||||||
<RangeInput name="attachmentRadius" :label="$t('settings.attachmentRadius')" v-model="attachmentRadiusLocal" :fallback="previewTheme.radii.attachment" max="50" hardMin="0"/>
|
|
||||||
<RangeInput name="tooltipRadius" :label="$t('settings.tooltipRadius')" v-model="tooltipRadiusLocal" :fallback="previewTheme.radii.tooltip" max="50" hardMin="0"/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div :label="$t('settings.style.shadows._tab_label')" class="shadow-container">
|
|
||||||
<div class="tab-header shadow-selector">
|
|
||||||
<div class="select-container">
|
|
||||||
{{$t('settings.style.shadows.component')}}
|
|
||||||
<label for="shadow-switcher" class="select">
|
|
||||||
<select id="shadow-switcher" v-model="shadowSelected" class="shadow-switcher">
|
|
||||||
<option v-for="shadow in shadowsAvailable"
|
|
||||||
:value="shadow">
|
|
||||||
{{$t('settings.style.shadows.components.' + shadow)}}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
<i class="icon-down-open"/>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="override">
|
|
||||||
<label for="override" class="label">
|
|
||||||
{{$t('settings.style.shadows.override')}}
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
v-model="currentShadowOverriden"
|
|
||||||
name="override"
|
|
||||||
id="override"
|
|
||||||
class="input-override"
|
|
||||||
type="checkbox">
|
|
||||||
<label class="checkbox-label" for="override"></label>
|
|
||||||
</div>
|
|
||||||
<button class="btn" @click="clearShadows">{{$t('settings.style.switcher.clear_all')}}</button>
|
|
||||||
</div>
|
|
||||||
<shadow-control :ready="!!currentShadowFallback" :fallback="currentShadowFallback" v-model="currentShadow"/>
|
|
||||||
<div v-if="shadowSelected === 'avatar' || shadowSelected === 'avatarStatus'">
|
|
||||||
<i18n path="settings.style.shadows.filter_hint.always_drop_shadow" tag="p">
|
|
||||||
<code>filter: drop-shadow()</code>
|
|
||||||
</i18n>
|
|
||||||
<p>{{$t('settings.style.shadows.filter_hint.avatar_inset')}}</p>
|
|
||||||
<i18n path="settings.style.shadows.filter_hint.drop_shadow_syntax" tag="p">
|
|
||||||
<code>drop-shadow</code>
|
|
||||||
<code>spread-radius</code>
|
|
||||||
<code>inset</code>
|
|
||||||
</i18n>
|
|
||||||
<i18n path="settings.style.shadows.filter_hint.inset_classic" tag="p">
|
|
||||||
<code>box-shadow</code>
|
|
||||||
</i18n>
|
|
||||||
<p>{{$t('settings.style.shadows.filter_hint.spread_zero')}}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div :label="$t('settings.style.fonts._tab_label')" class="fonts-container">
|
|
||||||
<div class="tab-header">
|
|
||||||
<p>{{$t('settings.style.fonts.help')}}</p>
|
|
||||||
<button class="btn" @click="clearFonts">{{$t('settings.style.switcher.clear_all')}}</button>
|
|
||||||
</div>
|
|
||||||
<FontControl
|
|
||||||
name="ui"
|
|
||||||
v-model="fontsLocal.interface"
|
|
||||||
:label="$t('settings.style.fonts.components.interface')"
|
|
||||||
:fallback="previewTheme.fonts.interface"
|
|
||||||
no-inherit="1"/>
|
|
||||||
<FontControl
|
|
||||||
name="input"
|
|
||||||
v-model="fontsLocal.input"
|
|
||||||
:label="$t('settings.style.fonts.components.input')"
|
|
||||||
:fallback="previewTheme.fonts.input"/>
|
|
||||||
<FontControl
|
|
||||||
name="post"
|
|
||||||
v-model="fontsLocal.post"
|
|
||||||
:label="$t('settings.style.fonts.components.post')"
|
|
||||||
:fallback="previewTheme.fonts.post"/>
|
|
||||||
<FontControl
|
|
||||||
name="postCode"
|
|
||||||
v-model="fontsLocal.postCode"
|
|
||||||
:label="$t('settings.style.fonts.components.postCode')"
|
|
||||||
:fallback="previewTheme.fonts.postCode"/>
|
|
||||||
</div>
|
|
||||||
</tab-switcher>
|
|
||||||
</keep-alive>
|
|
||||||
|
|
||||||
<div class="apply-container">
|
|
||||||
<button class="btn submit" :disabled="!themeValid" @click="setCustomTheme">{{$t('general.apply')}}</button>
|
|
||||||
<button class="btn" @click="clearAll">{{$t('settings.style.switcher.reset')}}</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./style_switcher.js"></script>
|
<script src="./style_switcher.js"></script>
|
||||||
|
|
|
@ -10,6 +10,12 @@ export default Vue.component('tab-switcher', {
|
||||||
active: this.$slots.default.findIndex(_ => _.tag)
|
active: this.$slots.default.findIndex(_ => _.tag)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
beforeUpdate () {
|
||||||
|
const currentSlot = this.$slots.default[this.active]
|
||||||
|
if (!currentSlot.tag) {
|
||||||
|
this.active = this.$slots.default.findIndex(_ => _.tag)
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
activateTab (index, dataset) {
|
activateTab (index, dataset) {
|
||||||
return () => {
|
return () => {
|
||||||
|
@ -20,34 +26,28 @@ export default Vue.component('tab-switcher', {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
beforeUpdate () {
|
|
||||||
const currentSlot = this.$slots.default[this.active]
|
|
||||||
if (!currentSlot.tag) {
|
|
||||||
this.active = this.$slots.default.findIndex(_ => _.tag)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
render (h) {
|
render (h) {
|
||||||
const tabs = this.$slots.default
|
const tabs = this.$slots.default
|
||||||
.map((slot, index) => {
|
.map((slot, index) => {
|
||||||
if (!slot.tag) return
|
if (!slot.tag) return
|
||||||
const classesTab = ['tab']
|
const classesTab = ['tab']
|
||||||
const classesWrapper = ['tab-wrapper']
|
const classesWrapper = ['tab-wrapper']
|
||||||
|
|
||||||
if (index === this.active) {
|
if (index === this.active) {
|
||||||
classesTab.push('active')
|
classesTab.push('active')
|
||||||
classesWrapper.push('active')
|
classesWrapper.push('active')
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class={ classesWrapper.join(' ')}>
|
<div class={ classesWrapper.join(' ')}>
|
||||||
<button
|
<button
|
||||||
disabled={slot.data.attrs.disabled}
|
disabled={slot.data.attrs.disabled}
|
||||||
onClick={this.activateTab(index)}
|
onClick={this.activateTab(index)}
|
||||||
class={classesTab.join(' ')}>
|
class={classesTab.join(' ')}>
|
||||||
{slot.data.attrs.label}</button>
|
{slot.data.attrs.label}</button>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
const contents = this.$slots.default.map((slot, index) => {
|
const contents = this.$slots.default.map((slot, index) => {
|
||||||
if (!slot.tag) return
|
if (!slot.tag) return
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
<template>
|
<template>
|
||||||
<Timeline :title="tag" :timeline="timeline" :timeline-name="'tag'" :tag="tag" />
|
<Timeline
|
||||||
|
:title="tag"
|
||||||
|
:timeline="timeline"
|
||||||
|
:timeline-name="'tag'"
|
||||||
|
:tag="tag"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src='./tag_timeline.js'></script>
|
<script src='./tag_timeline.js'></script>
|
|
@ -2,8 +2,12 @@
|
||||||
<div>
|
<div>
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<div v-html="content" class="tos-content">
|
<!-- eslint-disable vue/no-v-html -->
|
||||||
</div>
|
<div
|
||||||
|
class="tos-content"
|
||||||
|
v-html="content"
|
||||||
|
/>
|
||||||
|
<!-- eslint-enable vue/no-v-html -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<time :datetime="time" :title="localeDateString">
|
<time
|
||||||
|
:datetime="time"
|
||||||
|
:title="localeDateString"
|
||||||
|
>
|
||||||
{{ $t(relativeTime.key, [relativeTime.num]) }}
|
{{ $t(relativeTime.key, [relativeTime.num]) }}
|
||||||
</time>
|
</time>
|
||||||
</template>
|
</template>
|
||||||
|
@ -16,12 +19,6 @@ export default {
|
||||||
interval: null
|
interval: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created () {
|
|
||||||
this.refreshRelativeTimeObject()
|
|
||||||
},
|
|
||||||
destroyed () {
|
|
||||||
clearTimeout(this.interval)
|
|
||||||
},
|
|
||||||
computed: {
|
computed: {
|
||||||
localeDateString () {
|
localeDateString () {
|
||||||
return typeof this.time === 'string'
|
return typeof this.time === 'string'
|
||||||
|
@ -29,6 +26,12 @@ export default {
|
||||||
: this.time.toLocaleString()
|
: this.time.toLocaleString()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
created () {
|
||||||
|
this.refreshRelativeTimeObject()
|
||||||
|
},
|
||||||
|
destroyed () {
|
||||||
|
clearTimeout(this.interval)
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
refreshRelativeTimeObject () {
|
refreshRelativeTimeObject () {
|
||||||
const nowThreshold = typeof this.nowThreshold === 'number' ? this.nowThreshold : 1
|
const nowThreshold = typeof this.nowThreshold === 'number' ? this.nowThreshold : 1
|
||||||
|
|
|
@ -139,7 +139,7 @@ const Timeline = {
|
||||||
if (top < 15 &&
|
if (top < 15 &&
|
||||||
!this.paused &&
|
!this.paused &&
|
||||||
!(this.unfocused && this.$store.state.config.pauseOnUnfocused)
|
!(this.unfocused && this.$store.state.config.pauseOnUnfocused)
|
||||||
) {
|
) {
|
||||||
this.showNewStatuses()
|
this.showNewStatuses()
|
||||||
} else {
|
} else {
|
||||||
this.paused = true
|
this.paused = true
|
||||||
|
|
|
@ -2,41 +2,66 @@
|
||||||
<div :class="classes.root">
|
<div :class="classes.root">
|
||||||
<div :class="classes.header">
|
<div :class="classes.header">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
{{title}}
|
{{ title }}
|
||||||
</div>
|
</div>
|
||||||
<div @click.prevent class="loadmore-error alert error" v-if="timelineError">
|
<div
|
||||||
{{$t('timeline.error_fetching')}}
|
v-if="timelineError"
|
||||||
|
class="loadmore-error alert error"
|
||||||
|
@click.prevent
|
||||||
|
>
|
||||||
|
{{ $t('timeline.error_fetching') }}
|
||||||
</div>
|
</div>
|
||||||
<button @click.prevent="showNewStatuses" class="loadmore-button" v-if="timeline.newStatusCount > 0 && !timelineError">
|
<button
|
||||||
{{$t('timeline.show_new')}}{{newStatusCountStr}}
|
v-if="timeline.newStatusCount > 0 && !timelineError"
|
||||||
|
class="loadmore-button"
|
||||||
|
@click.prevent="showNewStatuses"
|
||||||
|
>
|
||||||
|
{{ $t('timeline.show_new') }}{{ newStatusCountStr }}
|
||||||
</button>
|
</button>
|
||||||
<div @click.prevent class="loadmore-text faint" v-if="!timeline.newStatusCount > 0 && !timelineError">
|
<div
|
||||||
{{$t('timeline.up_to_date')}}
|
v-if="!timeline.newStatusCount > 0 && !timelineError"
|
||||||
|
class="loadmore-text faint"
|
||||||
|
@click.prevent
|
||||||
|
>
|
||||||
|
{{ $t('timeline.up_to_date') }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div :class="classes.body">
|
<div :class="classes.body">
|
||||||
<div class="timeline">
|
<div class="timeline">
|
||||||
<conversation
|
<conversation
|
||||||
v-for="status in timeline.visibleStatuses"
|
v-for="status in timeline.visibleStatuses"
|
||||||
class="status-fadein"
|
|
||||||
:key="status.id"
|
:key="status.id"
|
||||||
|
class="status-fadein"
|
||||||
:statusoid="status"
|
:statusoid="status"
|
||||||
:collapsable="true"
|
:collapsable="true"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div :class="classes.footer">
|
<div :class="classes.footer">
|
||||||
<div v-if="count===0" class="new-status-notification text-center panel-footer faint">
|
<div
|
||||||
{{$t('timeline.no_statuses')}}
|
v-if="count===0"
|
||||||
|
class="new-status-notification text-center panel-footer faint"
|
||||||
|
>
|
||||||
|
{{ $t('timeline.no_statuses') }}
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="bottomedOut" class="new-status-notification text-center panel-footer faint">
|
<div
|
||||||
{{$t('timeline.no_more_statuses')}}
|
v-else-if="bottomedOut"
|
||||||
|
class="new-status-notification text-center panel-footer faint"
|
||||||
|
>
|
||||||
|
{{ $t('timeline.no_more_statuses') }}
|
||||||
</div>
|
</div>
|
||||||
<a v-else-if="!timeline.loading" href="#" v-on:click.prevent='fetchOlderStatuses()'>
|
<a
|
||||||
<div class="new-status-notification text-center panel-footer">{{$t('timeline.load_older')}}</div>
|
v-else-if="!timeline.loading"
|
||||||
|
href="#"
|
||||||
|
@click.prevent="fetchOlderStatuses()"
|
||||||
|
>
|
||||||
|
<div class="new-status-notification text-center panel-footer">{{ $t('timeline.load_older') }}</div>
|
||||||
</a>
|
</a>
|
||||||
<div v-else class="new-status-notification text-center panel-footer">
|
<div
|
||||||
<i class="icon-spin3 animate-spin"/>
|
v-else
|
||||||
|
class="new-status-notification text-center panel-footer"
|
||||||
|
>
|
||||||
|
<i class="icon-spin3 animate-spin" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
:title="user.screen_name"
|
:title="user.screen_name"
|
||||||
:src="user.profile_image_url_original"
|
:src="user.profile_image_url_original"
|
||||||
:class="{ 'avatar-compact': compact, 'better-shadow': betterShadow }"
|
:class="{ 'avatar-compact': compact, 'better-shadow': betterShadow }"
|
||||||
:imageLoadError="imageLoadError"
|
:image-load-error="imageLoadError"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -23,15 +23,15 @@ export default {
|
||||||
computed: {
|
computed: {
|
||||||
classes () {
|
classes () {
|
||||||
return [{
|
return [{
|
||||||
'user-card-rounded-t': this.rounded === 'top', // set border-top-left-radius and border-top-right-radius
|
'user-card-rounded-t': this.rounded === 'top', // set border-top-left-radius and border-top-right-radius
|
||||||
'user-card-rounded': this.rounded === true, // set border-radius for all sides
|
'user-card-rounded': this.rounded === true, // set border-radius for all sides
|
||||||
'user-card-bordered': this.bordered === true // set border for all sides
|
'user-card-bordered': this.bordered === true // set border for all sides
|
||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
style () {
|
style () {
|
||||||
const color = this.$store.state.config.customTheme.colors
|
const color = this.$store.state.config.customTheme.colors
|
||||||
? this.$store.state.config.customTheme.colors.bg // v2
|
? this.$store.state.config.customTheme.colors.bg // v2
|
||||||
: this.$store.state.config.colors.bg // v1
|
: this.$store.state.config.colors.bg // v1
|
||||||
|
|
||||||
if (color) {
|
if (color) {
|
||||||
const rgb = (typeof color === 'string') ? hex2rgb(color) : color
|
const rgb = (typeof color === 'string') ? hex2rgb(color) : color
|
||||||
|
@ -73,12 +73,12 @@ export default {
|
||||||
userHighlightType: {
|
userHighlightType: {
|
||||||
get () {
|
get () {
|
||||||
const data = this.$store.state.config.highlight[this.user.screen_name]
|
const data = this.$store.state.config.highlight[this.user.screen_name]
|
||||||
return data && data.type || 'disabled'
|
return (data && data.type) || 'disabled'
|
||||||
},
|
},
|
||||||
set (type) {
|
set (type) {
|
||||||
const data = this.$store.state.config.highlight[this.user.screen_name]
|
const data = this.$store.state.config.highlight[this.user.screen_name]
|
||||||
if (type !== 'disabled') {
|
if (type !== 'disabled') {
|
||||||
this.$store.dispatch('setHighlight', { user: this.user.screen_name, color: data && data.color || '#FFFFFF', type })
|
this.$store.dispatch('setHighlight', { user: this.user.screen_name, color: (data && data.color) || '#FFFFFF', type })
|
||||||
} else {
|
} else {
|
||||||
this.$store.dispatch('setHighlight', { user: this.user.screen_name, color: undefined })
|
this.$store.dispatch('setHighlight', { user: this.user.screen_name, color: undefined })
|
||||||
}
|
}
|
||||||
|
@ -110,7 +110,7 @@ export default {
|
||||||
followUser () {
|
followUser () {
|
||||||
const store = this.$store
|
const store = this.$store
|
||||||
this.followRequestInProgress = true
|
this.followRequestInProgress = true
|
||||||
requestFollow(this.user, store).then(({sent}) => {
|
requestFollow(this.user, store).then(({ sent }) => {
|
||||||
this.followRequestInProgress = false
|
this.followRequestInProgress = false
|
||||||
this.followRequestSent = sent
|
this.followRequestSent = sent
|
||||||
})
|
})
|
||||||
|
@ -141,7 +141,7 @@ export default {
|
||||||
store.commit('setProfileView', { v })
|
store.commit('setProfileView', { v })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
linkClicked ({target}) {
|
linkClicked ({ target }) {
|
||||||
if (target.tagName === 'SPAN') {
|
if (target.tagName === 'SPAN') {
|
||||||
target = target.parentNode
|
target = target.parentNode
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,134 +1,260 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="user-card" :class="classes" :style="style">
|
<div
|
||||||
<div class="panel-heading">
|
class="user-card"
|
||||||
<div class='user-info'>
|
:class="classes"
|
||||||
<div class='container'>
|
:style="style"
|
||||||
<router-link :to="userProfileLink(user)">
|
>
|
||||||
<UserAvatar :betterShadow="betterShadow" :user="user"/>
|
<div class="panel-heading">
|
||||||
</router-link>
|
<div class="user-info">
|
||||||
<div class="user-summary">
|
<div class="container">
|
||||||
<div class="top-line">
|
<router-link :to="userProfileLink(user)">
|
||||||
<div :title="user.name" class='user-name' v-if="user.name_html" v-html="user.name_html"></div>
|
<UserAvatar
|
||||||
<div :title="user.name" class='user-name' v-else>{{user.name}}</div>
|
:better-shadow="betterShadow"
|
||||||
<router-link :to="{ name: 'user-settings' }" v-if="!isOtherUser">
|
:user="user"
|
||||||
<i class="button-icon icon-wrench usersettings" :title="$t('tool_tip.user_settings')"></i>
|
/>
|
||||||
</router-link>
|
</router-link>
|
||||||
<a :href="user.statusnet_profile_url" target="_blank" v-if="isOtherUser && !user.is_local">
|
<div class="user-summary">
|
||||||
<i class="icon-link-ext usersettings"></i>
|
<div class="top-line">
|
||||||
</a>
|
<!-- eslint-disable vue/no-v-html -->
|
||||||
</div>
|
<div
|
||||||
|
v-if="user.name_html"
|
||||||
|
:title="user.name"
|
||||||
|
class="user-name"
|
||||||
|
v-html="user.name_html"
|
||||||
|
/>
|
||||||
|
<!-- eslint-enable vue/no-v-html -->
|
||||||
|
<div
|
||||||
|
v-else
|
||||||
|
:title="user.name"
|
||||||
|
class="user-name"
|
||||||
|
>
|
||||||
|
{{ user.name }}
|
||||||
|
</div>
|
||||||
|
<router-link
|
||||||
|
v-if="!isOtherUser"
|
||||||
|
:to="{ name: 'user-settings' }"
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
class="button-icon icon-wrench usersettings"
|
||||||
|
:title="$t('tool_tip.user_settings')"
|
||||||
|
/>
|
||||||
|
</router-link>
|
||||||
|
<a
|
||||||
|
v-if="isOtherUser && !user.is_local"
|
||||||
|
:href="user.statusnet_profile_url"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
<i class="icon-link-ext usersettings" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="bottom-line">
|
<div class="bottom-line">
|
||||||
<router-link class="user-screen-name" :to="userProfileLink(user)">@{{user.screen_name}}</router-link>
|
<router-link
|
||||||
<span class="alert staff" v-if="!hideBio && !!visibleRole">{{visibleRole}}</span>
|
class="user-screen-name"
|
||||||
<span v-if="user.locked"><i class="icon icon-lock"></i></span>
|
:to="userProfileLink(user)"
|
||||||
<span v-if="!hideUserStatsLocal && !hideBio" class="dailyAvg">{{dailyAvg}} {{ $t('user_card.per_day') }}</span>
|
>
|
||||||
|
@{{ user.screen_name }}
|
||||||
|
</router-link>
|
||||||
|
<span
|
||||||
|
v-if="!hideBio && !!visibleRole"
|
||||||
|
class="alert staff"
|
||||||
|
>{{ visibleRole }}</span>
|
||||||
|
<span v-if="user.locked"><i class="icon icon-lock" /></span>
|
||||||
|
<span
|
||||||
|
v-if="!hideUserStatsLocal && !hideBio"
|
||||||
|
class="dailyAvg"
|
||||||
|
>{{ dailyAvg }} {{ $t('user_card.per_day') }}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="user-meta">
|
||||||
<div class="user-meta">
|
<div
|
||||||
<div v-if="user.follows_you && loggedIn && isOtherUser" class="following">
|
v-if="user.follows_you && loggedIn && isOtherUser"
|
||||||
{{ $t('user_card.follows_you') }}
|
class="following"
|
||||||
|
>
|
||||||
|
{{ $t('user_card.follows_you') }}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="isOtherUser && (loggedIn || !switcher)"
|
||||||
|
class="highlighter"
|
||||||
|
>
|
||||||
|
<!-- id's need to be unique, otherwise vue confuses which user-card checkbox belongs to -->
|
||||||
|
<input
|
||||||
|
v-if="userHighlightType !== 'disabled'"
|
||||||
|
:id="'userHighlightColorTx'+user.id"
|
||||||
|
v-model="userHighlightColor"
|
||||||
|
class="userHighlightText"
|
||||||
|
type="text"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
v-if="userHighlightType !== 'disabled'"
|
||||||
|
:id="'userHighlightColor'+user.id"
|
||||||
|
v-model="userHighlightColor"
|
||||||
|
class="userHighlightCl"
|
||||||
|
type="color"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
for="style-switcher"
|
||||||
|
class="userHighlightSel select"
|
||||||
|
>
|
||||||
|
<select
|
||||||
|
:id="'userHighlightSel'+user.id"
|
||||||
|
v-model="userHighlightType"
|
||||||
|
class="userHighlightSel"
|
||||||
|
>
|
||||||
|
<option value="disabled">No highlight</option>
|
||||||
|
<option value="solid">Solid bg</option>
|
||||||
|
<option value="striped">Striped bg</option>
|
||||||
|
<option value="side">Side stripe</option>
|
||||||
|
</select>
|
||||||
|
<i class="icon-down-open" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="highlighter" v-if="isOtherUser && (loggedIn || !switcher)">
|
<div
|
||||||
<!-- id's need to be unique, otherwise vue confuses which user-card checkbox belongs to -->
|
v-if="isOtherUser"
|
||||||
<input class="userHighlightText" type="text" :id="'userHighlightColorTx'+user.id" v-if="userHighlightType !== 'disabled'" v-model="userHighlightColor"/>
|
class="user-interactions"
|
||||||
<input class="userHighlightCl" type="color" :id="'userHighlightColor'+user.id" v-if="userHighlightType !== 'disabled'" v-model="userHighlightColor"/>
|
>
|
||||||
<label for="style-switcher" class='userHighlightSel select'>
|
<div
|
||||||
<select class="userHighlightSel" :id="'userHighlightSel'+user.id" v-model="userHighlightType">
|
v-if="loggedIn"
|
||||||
<option value="disabled">No highlight</option>
|
class="follow"
|
||||||
<option value="solid">Solid bg</option>
|
>
|
||||||
<option value="striped">Striped bg</option>
|
<span v-if="user.following">
|
||||||
<option value="side">Side stripe</option>
|
<!--Following them!-->
|
||||||
</select>
|
<button
|
||||||
<i class="icon-down-open"/>
|
class="pressed"
|
||||||
</label>
|
:disabled="followRequestInProgress"
|
||||||
|
:title="$t('user_card.follow_unfollow')"
|
||||||
|
@click="unfollowUser"
|
||||||
|
>
|
||||||
|
<template v-if="followRequestInProgress">
|
||||||
|
{{ $t('user_card.follow_progress') }}
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
{{ $t('user_card.following') }}
|
||||||
|
</template>
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
<span v-if="!user.following">
|
||||||
|
<button
|
||||||
|
:disabled="followRequestInProgress"
|
||||||
|
:title="followRequestSent ? $t('user_card.follow_again') : ''"
|
||||||
|
@click="followUser"
|
||||||
|
>
|
||||||
|
<template v-if="followRequestInProgress">
|
||||||
|
{{ $t('user_card.follow_progress') }}
|
||||||
|
</template>
|
||||||
|
<template v-else-if="followRequestSent">
|
||||||
|
{{ $t('user_card.follow_sent') }}
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
{{ $t('user_card.follow') }}
|
||||||
|
</template>
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="isOtherUser && loggedIn"
|
||||||
|
class="mute"
|
||||||
|
>
|
||||||
|
<span v-if="user.muted">
|
||||||
|
<button
|
||||||
|
class="pressed"
|
||||||
|
@click="unmuteUser"
|
||||||
|
>
|
||||||
|
{{ $t('user_card.muted') }}
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
<span v-if="!user.muted">
|
||||||
|
<button @click="muteUser">
|
||||||
|
{{ $t('user_card.mute') }}
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div v-if="!loggedIn && user.is_local">
|
||||||
|
<RemoteFollow :user="user" />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="isOtherUser && loggedIn"
|
||||||
|
class="block"
|
||||||
|
>
|
||||||
|
<span v-if="user.statusnet_blocking">
|
||||||
|
<button
|
||||||
|
class="pressed"
|
||||||
|
@click="unblockUser"
|
||||||
|
>
|
||||||
|
{{ $t('user_card.blocked') }}
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
<span v-if="!user.statusnet_blocking">
|
||||||
|
<button @click="blockUser">
|
||||||
|
{{ $t('user_card.block') }}
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="isOtherUser && loggedIn"
|
||||||
|
class="block"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
<button @click="reportUser">
|
||||||
|
{{ $t('user_card.report') }}
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<ModerationTools
|
||||||
|
v-if="loggedIn.role === "admin""
|
||||||
|
:user="user"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="isOtherUser" class="user-interactions">
|
|
||||||
<div class="follow" v-if="loggedIn">
|
|
||||||
<span v-if="user.following">
|
|
||||||
<!--Following them!-->
|
|
||||||
<button @click="unfollowUser" class="pressed" :disabled="followRequestInProgress" :title="$t('user_card.follow_unfollow')">
|
|
||||||
<template v-if="followRequestInProgress">
|
|
||||||
{{ $t('user_card.follow_progress') }}
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
{{ $t('user_card.following') }}
|
|
||||||
</template>
|
|
||||||
</button>
|
|
||||||
</span>
|
|
||||||
<span v-if="!user.following">
|
|
||||||
<button @click="followUser" :disabled="followRequestInProgress" :title="followRequestSent ? $t('user_card.follow_again') : ''">
|
|
||||||
<template v-if="followRequestInProgress">
|
|
||||||
{{ $t('user_card.follow_progress') }}
|
|
||||||
</template>
|
|
||||||
<template v-else-if="followRequestSent">
|
|
||||||
{{ $t('user_card.follow_sent') }}
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
{{ $t('user_card.follow') }}
|
|
||||||
</template>
|
|
||||||
</button>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class='mute' v-if='isOtherUser && loggedIn'>
|
|
||||||
<span v-if='user.muted'>
|
|
||||||
<button @click="unmuteUser" class="pressed">
|
|
||||||
{{ $t('user_card.muted') }}
|
|
||||||
</button>
|
|
||||||
</span>
|
|
||||||
<span v-if='!user.muted'>
|
|
||||||
<button @click="muteUser">
|
|
||||||
{{ $t('user_card.mute') }}
|
|
||||||
</button>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div v-if='!loggedIn && user.is_local'>
|
|
||||||
<RemoteFollow :user="user" />
|
|
||||||
</div>
|
|
||||||
<div class='block' v-if='isOtherUser && loggedIn'>
|
|
||||||
<span v-if='user.statusnet_blocking'>
|
|
||||||
<button @click="unblockUser" class="pressed">
|
|
||||||
{{ $t('user_card.blocked') }}
|
|
||||||
</button>
|
|
||||||
</span>
|
|
||||||
<span v-if='!user.statusnet_blocking'>
|
|
||||||
<button @click="blockUser">
|
|
||||||
{{ $t('user_card.block') }}
|
|
||||||
</button>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class='block' v-if='isOtherUser && loggedIn'>
|
|
||||||
<span>
|
|
||||||
<button @click="reportUser">
|
|
||||||
{{ $t('user_card.report') }}
|
|
||||||
</button>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<ModerationTools :user='user' v-if='loggedIn.role === "admin"'/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div
|
||||||
<div class="panel-body" v-if="!hideBio">
|
v-if="!hideBio"
|
||||||
<div v-if="!hideUserStatsLocal && switcher" class="user-counts">
|
class="panel-body"
|
||||||
<div class="user-count" v-on:click.prevent="setProfileView('statuses')">
|
>
|
||||||
<h5>{{ $t('user_card.statuses') }}</h5>
|
<div
|
||||||
<span>{{user.statuses_count}} <br></span>
|
v-if="!hideUserStatsLocal && switcher"
|
||||||
</div>
|
class="user-counts"
|
||||||
<div class="user-count" v-on:click.prevent="setProfileView('friends')">
|
>
|
||||||
<h5>{{ $t('user_card.followees') }}</h5>
|
<div
|
||||||
<span>{{user.friends_count}}</span>
|
class="user-count"
|
||||||
</div>
|
@click.prevent="setProfileView('statuses')"
|
||||||
<div class="user-count" v-on:click.prevent="setProfileView('followers')">
|
>
|
||||||
<h5>{{ $t('user_card.followers') }}</h5>
|
<h5>{{ $t('user_card.statuses') }}</h5>
|
||||||
<span>{{user.followers_count}}</span>
|
<span>{{ user.statuses_count }} <br></span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="user-count"
|
||||||
|
@click.prevent="setProfileView('friends')"
|
||||||
|
>
|
||||||
|
<h5>{{ $t('user_card.followees') }}</h5>
|
||||||
|
<span>{{ user.friends_count }}</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="user-count"
|
||||||
|
@click.prevent="setProfileView('followers')"
|
||||||
|
>
|
||||||
|
<h5>{{ $t('user_card.followers') }}</h5>
|
||||||
|
<span>{{ user.followers_count }}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- eslint-disable vue/no-v-html -->
|
||||||
|
<p
|
||||||
|
v-if="!hideBio && user.description_html"
|
||||||
|
class="user-card-bio"
|
||||||
|
@click.prevent="linkClicked"
|
||||||
|
v-html="user.description_html"
|
||||||
|
/>
|
||||||
|
<!-- eslint-enable vue/no-v-html -->
|
||||||
|
<p
|
||||||
|
v-else-if="!hideBio"
|
||||||
|
class="user-card-bio"
|
||||||
|
>
|
||||||
|
{{ user.description }}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<p @click.prevent="linkClicked" v-if="!hideBio && user.description_html" class="user-card-bio" v-html="user.description_html"></p>
|
|
||||||
<p v-else-if="!hideBio" class="user-card-bio">{{ user.description }}</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./user_card.js"></script>
|
<script src="./user_card.js"></script>
|
||||||
|
|
|
@ -1,14 +1,38 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div class="user-finder-container">
|
<div class="user-finder-container">
|
||||||
<i class="icon-spin4 user-finder-icon animate-spin-slow" v-if="loading" />
|
<i
|
||||||
<a href="#" v-if="hidden" :title="$t('finder.find_user')"><i class="icon-user-plus user-finder-icon" @click.prevent.stop="toggleHidden" /></a>
|
v-if="loading"
|
||||||
|
class="icon-spin4 user-finder-icon animate-spin-slow"
|
||||||
|
/>
|
||||||
|
<a
|
||||||
|
v-if="hidden"
|
||||||
|
href="#"
|
||||||
|
:title="$t('finder.find_user')"
|
||||||
|
><i
|
||||||
|
class="icon-user-plus user-finder-icon"
|
||||||
|
@click.prevent.stop="toggleHidden"
|
||||||
|
/></a>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<input class="user-finder-input" ref="userSearchInput" @keyup.enter="findUser(username)" v-model="username" :placeholder="$t('finder.find_user')" id="user-finder-input" type="text"/>
|
<input
|
||||||
<button class="btn search-button" @click="findUser(username)">
|
id="user-finder-input"
|
||||||
<i class="icon-search"/>
|
ref="userSearchInput"
|
||||||
|
v-model="username"
|
||||||
|
class="user-finder-input"
|
||||||
|
:placeholder="$t('finder.find_user')"
|
||||||
|
type="text"
|
||||||
|
@keyup.enter="findUser(username)"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
class="btn search-button"
|
||||||
|
@click="findUser(username)"
|
||||||
|
>
|
||||||
|
<i class="icon-search" />
|
||||||
</button>
|
</button>
|
||||||
<i class="button-icon icon-cancel user-finder-icon" @click.prevent.stop="toggleHidden"/>
|
<i
|
||||||
|
class="button-icon icon-cancel user-finder-icon"
|
||||||
|
@click.prevent.stop="toggleHidden"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -25,7 +49,6 @@
|
||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
vertical-align: baseline;
|
vertical-align: baseline;
|
||||||
|
|
||||||
|
|
||||||
.user-finder-input,
|
.user-finder-input,
|
||||||
.search-button {
|
.search-button {
|
||||||
height: 29px;
|
height: 29px;
|
||||||
|
|
|
@ -1,13 +1,23 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="user-panel">
|
<div class="user-panel">
|
||||||
|
<div
|
||||||
<div v-if="signedIn" key="user-panel" class="panel panel-default signed-in">
|
v-if="signedIn"
|
||||||
<UserCard :user="user" :hideBio="true" rounded="top"/>
|
key="user-panel"
|
||||||
|
class="panel panel-default signed-in"
|
||||||
|
>
|
||||||
|
<UserCard
|
||||||
|
:user="user"
|
||||||
|
:hide-bio="true"
|
||||||
|
rounded="top"
|
||||||
|
/>
|
||||||
<div class="panel-footer">
|
<div class="panel-footer">
|
||||||
<post-status-form v-if='user'></post-status-form>
|
<post-status-form v-if="user" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<auth-form v-else key="user-panel"/>
|
<auth-form
|
||||||
|
v-else
|
||||||
|
key="user-panel"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -1,75 +1,110 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div v-if="user" class="user-profile panel panel-default">
|
<div
|
||||||
<UserCard :user="user" :switcher="true" :selected="timeline.viewing" rounded="top"/>
|
v-if="user"
|
||||||
<tab-switcher :renderOnlyFocused="true" ref="tabSwitcher">
|
class="user-profile panel panel-default"
|
||||||
<div :label="$t('user_card.statuses')">
|
>
|
||||||
<div class="timeline">
|
<UserCard
|
||||||
<template v-for="statusId in user.pinnedStatuseIds">
|
:user="user"
|
||||||
<Conversation
|
:switcher="true"
|
||||||
v-if="timeline.statusesObject[statusId]"
|
:selected="timeline.viewing"
|
||||||
class="status-fadein"
|
rounded="top"
|
||||||
:key="statusId"
|
/>
|
||||||
:statusoid="timeline.statusesObject[statusId]"
|
<tab-switcher
|
||||||
:collapsable="true"
|
ref="tabSwitcher"
|
||||||
:showPinned="true"
|
:render-only-focused="true"
|
||||||
/>
|
>
|
||||||
</template>
|
<div :label="$t('user_card.statuses')">
|
||||||
|
<div class="timeline">
|
||||||
|
<template v-for="statusId in user.pinnedStatuseIds">
|
||||||
|
<Conversation
|
||||||
|
v-if="timeline.statusesObject[statusId]"
|
||||||
|
:key="statusId"
|
||||||
|
class="status-fadein"
|
||||||
|
:statusoid="timeline.statusesObject[statusId]"
|
||||||
|
:collapsable="true"
|
||||||
|
:show-pinned="true"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
<Timeline
|
||||||
|
:count="user.statuses_count"
|
||||||
|
:embedded="true"
|
||||||
|
:title="$t('user_profile.timeline_title')"
|
||||||
|
:timeline="timeline"
|
||||||
|
:timeline-name="'user'"
|
||||||
|
:user-id="userId"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="followsTabVisible"
|
||||||
|
:label="$t('user_card.followees')"
|
||||||
|
:disabled="!user.friends_count"
|
||||||
|
>
|
||||||
|
<FriendList :user-id="userId">
|
||||||
|
<template
|
||||||
|
slot="item"
|
||||||
|
slot-scope="{item}"
|
||||||
|
>
|
||||||
|
<FollowCard :user="item" />
|
||||||
|
</template>
|
||||||
|
</FriendList>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="followersTabVisible"
|
||||||
|
:label="$t('user_card.followers')"
|
||||||
|
:disabled="!user.followers_count"
|
||||||
|
>
|
||||||
|
<FollowerList :user-id="userId">
|
||||||
|
<template
|
||||||
|
slot="item"
|
||||||
|
slot-scope="{item}"
|
||||||
|
>
|
||||||
|
<FollowCard
|
||||||
|
:user="item"
|
||||||
|
:no-follows-you="isUs"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</FollowerList>
|
||||||
</div>
|
</div>
|
||||||
<Timeline
|
<Timeline
|
||||||
:count="user.statuses_count"
|
:label="$t('user_card.media')"
|
||||||
|
:disabled="!media.visibleStatuses.length"
|
||||||
:embedded="true"
|
:embedded="true"
|
||||||
:title="$t('user_profile.timeline_title')"
|
:title="$t('user_card.media')"
|
||||||
:timeline="timeline"
|
timeline-name="media"
|
||||||
:timeline-name="'user'"
|
:timeline="media"
|
||||||
:user-id="userId"
|
:user-id="userId"
|
||||||
/>
|
/>
|
||||||
|
<Timeline
|
||||||
|
v-if="isUs"
|
||||||
|
:label="$t('user_card.favorites')"
|
||||||
|
:disabled="!favorites.visibleStatuses.length"
|
||||||
|
:embedded="true"
|
||||||
|
:title="$t('user_card.favorites')"
|
||||||
|
timeline-name="favorites"
|
||||||
|
:timeline="favorites"
|
||||||
|
/>
|
||||||
|
</tab-switcher>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-else
|
||||||
|
class="panel user-profile-placeholder"
|
||||||
|
>
|
||||||
|
<div class="panel-heading">
|
||||||
|
<div class="title">
|
||||||
|
{{ $t('settings.profile_tab') }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div :label="$t('user_card.followees')" v-if="followsTabVisible" :disabled="!user.friends_count">
|
<div class="panel-body">
|
||||||
<FriendList :userId="userId">
|
<span v-if="error">{{ error }}</span>
|
||||||
<template slot="item" slot-scope="{item}">
|
<i
|
||||||
<FollowCard :user="item" />
|
v-else
|
||||||
</template>
|
class="icon-spin3 animate-spin"
|
||||||
</FriendList>
|
/>
|
||||||
</div>
|
|
||||||
<div :label="$t('user_card.followers')" v-if="followersTabVisible" :disabled="!user.followers_count">
|
|
||||||
<FollowerList :userId="userId">
|
|
||||||
<template slot="item" slot-scope="{item}">
|
|
||||||
<FollowCard :user="item" :noFollowsYou="isUs" />
|
|
||||||
</template>
|
|
||||||
</FollowerList>
|
|
||||||
</div>
|
|
||||||
<Timeline
|
|
||||||
:label="$t('user_card.media')"
|
|
||||||
:disabled="!media.visibleStatuses.length"
|
|
||||||
:embedded="true" :title="$t('user_card.media')"
|
|
||||||
timeline-name="media"
|
|
||||||
:timeline="media"
|
|
||||||
:user-id="userId"
|
|
||||||
/>
|
|
||||||
<Timeline
|
|
||||||
v-if="isUs"
|
|
||||||
:label="$t('user_card.favorites')"
|
|
||||||
:disabled="!favorites.visibleStatuses.length"
|
|
||||||
:embedded="true"
|
|
||||||
:title="$t('user_card.favorites')"
|
|
||||||
timeline-name="favorites"
|
|
||||||
:timeline="favorites"
|
|
||||||
/>
|
|
||||||
</tab-switcher>
|
|
||||||
</div>
|
|
||||||
<div v-else class="panel user-profile-placeholder">
|
|
||||||
<div class="panel-heading">
|
|
||||||
<div class="title">
|
|
||||||
{{ $t('settings.profile_tab') }}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
|
||||||
<span v-if="error">{{ error }}</span>
|
|
||||||
<i class="icon-spin3 animate-spin" v-else></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./user_profile.js"></script>
|
<script src="./user_profile.js"></script>
|
||||||
|
|
|
@ -1,45 +1,75 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="modal-view" @click="closeModal" v-if="isOpen">
|
<div
|
||||||
<div class="user-reporting-panel panel" @click.stop="">
|
v-if="isOpen"
|
||||||
<div class="panel-heading">
|
class="modal-view"
|
||||||
<div class="title">{{$t('user_reporting.title', [user.screen_name])}}</div>
|
@click="closeModal"
|
||||||
</div>
|
>
|
||||||
<div class="panel-body">
|
<div
|
||||||
<div class="user-reporting-panel-left">
|
class="user-reporting-panel panel"
|
||||||
<div>
|
@click.stop=""
|
||||||
<p>{{$t('user_reporting.add_comment_description')}}</p>
|
>
|
||||||
<textarea
|
<div class="panel-heading">
|
||||||
v-model="comment"
|
<div class="title">
|
||||||
class="form-control"
|
{{ $t('user_reporting.title', [user.screen_name]) }}
|
||||||
:placeholder="$t('user_reporting.additional_comments')"
|
|
||||||
rows="1"
|
|
||||||
@input="resize"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div v-if="!user.is_local">
|
|
||||||
<p>{{$t('user_reporting.forward_description')}}</p>
|
|
||||||
<Checkbox v-model="forward">{{$t('user_reporting.forward_to', [remoteInstance])}}</Checkbox>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<button class="btn btn-default" @click="reportUser" :disabled="processing">{{$t('user_reporting.submit')}}</button>
|
|
||||||
<div class="alert error" v-if="error">
|
|
||||||
{{$t('user_reporting.generic_error')}}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="user-reporting-panel-right">
|
<div class="panel-body">
|
||||||
<List :items="statuses">
|
<div class="user-reporting-panel-left">
|
||||||
<template slot="item" slot-scope="{item}">
|
<div>
|
||||||
<div class="status-fadein user-reporting-panel-sitem">
|
<p>{{ $t('user_reporting.add_comment_description') }}</p>
|
||||||
<Status :inConversation="false" :focused="false" :statusoid="item" />
|
<textarea
|
||||||
<Checkbox :checked="isChecked(item.id)" @change="checked => toggleStatus(checked, item.id)" />
|
v-model="comment"
|
||||||
|
class="form-control"
|
||||||
|
:placeholder="$t('user_reporting.additional_comments')"
|
||||||
|
rows="1"
|
||||||
|
@input="resize"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div v-if="!user.is_local">
|
||||||
|
<p>{{ $t('user_reporting.forward_description') }}</p>
|
||||||
|
<Checkbox v-model="forward">
|
||||||
|
{{ $t('user_reporting.forward_to', [remoteInstance]) }}
|
||||||
|
</Checkbox>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
class="btn btn-default"
|
||||||
|
:disabled="processing"
|
||||||
|
@click="reportUser"
|
||||||
|
>
|
||||||
|
{{ $t('user_reporting.submit') }}
|
||||||
|
</button>
|
||||||
|
<div
|
||||||
|
v-if="error"
|
||||||
|
class="alert error"
|
||||||
|
>
|
||||||
|
{{ $t('user_reporting.generic_error') }}
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</div>
|
||||||
</List>
|
</div>
|
||||||
|
<div class="user-reporting-panel-right">
|
||||||
|
<List :items="statuses">
|
||||||
|
<template
|
||||||
|
slot="item"
|
||||||
|
slot-scope="{item}"
|
||||||
|
>
|
||||||
|
<div class="status-fadein user-reporting-panel-sitem">
|
||||||
|
<Status
|
||||||
|
:in-conversation="false"
|
||||||
|
:focused="false"
|
||||||
|
:statusoid="item"
|
||||||
|
/>
|
||||||
|
<Checkbox
|
||||||
|
:checked="isChecked(item.id)"
|
||||||
|
@change="checked => toggleStatus(checked, item.id)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</List>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./user_reporting_modal.js"></script>
|
<script src="./user_reporting_modal.js"></script>
|
||||||
|
|
|
@ -1,19 +1,39 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="user-search panel panel-default">
|
<div class="user-search panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
{{$t('nav.user_search')}}
|
{{ $t('nav.user_search') }}
|
||||||
</div>
|
</div>
|
||||||
<div class="user-search-input-container">
|
<div class="user-search-input-container">
|
||||||
<input class="user-finder-input" ref="userSearchInput" @keyup.enter="newQuery(username)" v-model="username" :placeholder="$t('finder.find_user')"/>
|
<input
|
||||||
<button class="btn search-button" @click="newQuery(username)">
|
ref="userSearchInput"
|
||||||
<i class="icon-search"/>
|
v-model="username"
|
||||||
|
class="user-finder-input"
|
||||||
|
:placeholder="$t('finder.find_user')"
|
||||||
|
@keyup.enter="newQuery(username)"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
class="btn search-button"
|
||||||
|
@click="newQuery(username)"
|
||||||
|
>
|
||||||
|
<i class="icon-search" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="loading" class="text-center loading-icon">
|
<div
|
||||||
<i class="icon-spin3 animate-spin"/>
|
v-if="loading"
|
||||||
|
class="text-center loading-icon"
|
||||||
|
>
|
||||||
|
<i class="icon-spin3 animate-spin" />
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="panel-body">
|
<div
|
||||||
<FollowCard v-for="user in users" :key="user.id" :user="user" class="list-item"/>
|
v-else
|
||||||
|
class="panel-body"
|
||||||
|
>
|
||||||
|
<FollowCard
|
||||||
|
v-for="user in users"
|
||||||
|
:key="user.id"
|
||||||
|
:user="user"
|
||||||
|
class="list-item"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,13 +1,21 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<slot></slot>
|
<slot />
|
||||||
<button class="btn btn-default" @click="confirm" :disabled="disabled">
|
<button
|
||||||
{{$t('general.confirm')}}
|
class="btn btn-default"
|
||||||
</button>
|
:disabled="disabled"
|
||||||
<button class="btn btn-default" @click="cancel" :disabled="disabled">
|
@click="confirm"
|
||||||
{{$t('general.cancel')}}
|
>
|
||||||
</button>
|
{{ $t('general.confirm') }}
|
||||||
</div>
|
</button>
|
||||||
|
<button
|
||||||
|
class="btn btn-default"
|
||||||
|
:disabled="disabled"
|
||||||
|
@click="cancel"
|
||||||
|
>
|
||||||
|
{{ $t('general.cancel') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./confirm.js">
|
<script src="./confirm.js">
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue