Merge branch 'polish' into 'develop'
Another one of those MR that fixes many many small-to-medium things Closes #92, #75, #122, #52, #72, and #87 See merge request pleroma/pleroma-fe!324
This commit is contained in:
commit
958acbab8d
33 changed files with 866 additions and 450 deletions
4
.babelrc
4
.babelrc
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"presets": ["es2015", "stage-2"],
|
||||
"plugins": ["transform-runtime", "lodash"],
|
||||
"presets": ["es2015", "stage-2", "env"],
|
||||
"plugins": ["transform-runtime", "lodash", "transform-vue-jsx"],
|
||||
"comments": false
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ module.exports = {
|
|||
loader: 'vue'
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
test: /\.jsx?$/,
|
||||
loader: 'babel',
|
||||
include: projectRoot,
|
||||
exclude: /node_modules\/(?!tributejs)/
|
||||
|
|
|
@ -37,8 +37,12 @@
|
|||
"autoprefixer": "^6.4.0",
|
||||
"babel-core": "^6.0.0",
|
||||
"babel-eslint": "^7.0.0",
|
||||
"babel-helper-vue-jsx-merge-props": "^2.0.3",
|
||||
"babel-loader": "^6.0.0",
|
||||
"babel-plugin-syntax-jsx": "^6.18.0",
|
||||
"babel-plugin-transform-runtime": "^6.0.0",
|
||||
"babel-plugin-transform-vue-jsx": "3",
|
||||
"babel-preset-env": "^1.7.0",
|
||||
"babel-preset-es2015": "^6.0.0",
|
||||
"babel-preset-stage-2": "^6.0.0",
|
||||
"babel-register": "^6.0.0",
|
||||
|
|
31
src/App.js
31
src/App.js
|
@ -18,7 +18,14 @@ export default {
|
|||
ChatPanel
|
||||
},
|
||||
data: () => ({
|
||||
mobileActivePanel: 'timeline'
|
||||
mobileActivePanel: 'timeline',
|
||||
supportsMask: window.CSS && window.CSS.supports && (
|
||||
window.CSS.supports('mask-size', 'contain') ||
|
||||
window.CSS.supports('-webkit-mask-size', 'contain') ||
|
||||
window.CSS.supports('-moz-mask-size', 'contain') ||
|
||||
window.CSS.supports('-ms-mask-size', 'contain') ||
|
||||
window.CSS.supports('-o-mask-size', 'contain')
|
||||
)
|
||||
}),
|
||||
created () {
|
||||
// Load the locale from the storage
|
||||
|
@ -29,7 +36,27 @@ export default {
|
|||
background () {
|
||||
return this.currentUser.background_image || this.$store.state.config.background
|
||||
},
|
||||
logoStyle () { return { 'background-image': `url(${this.$store.state.config.logo})` } },
|
||||
enableMask () { return this.supportsMask && this.$store.state.config.logoMask },
|
||||
logoStyle () {
|
||||
return {
|
||||
'visibility': this.enableMask ? 'hidden' : 'visible'
|
||||
}
|
||||
},
|
||||
logoMaskStyle () {
|
||||
return this.enableMask ? {
|
||||
'mask-image': `url(${this.$store.state.config.logo})`
|
||||
} : {
|
||||
'background-color': this.enableMask ? '' : 'transparent'
|
||||
}
|
||||
},
|
||||
logoBgStyle () {
|
||||
return Object.assign({
|
||||
'margin': `${this.$store.state.config.logoMargin} 0`
|
||||
}, this.enableMask ? {} : {
|
||||
'background-color': this.enableMask ? '' : 'transparent'
|
||||
})
|
||||
},
|
||||
logo () { return this.$store.state.config.logo },
|
||||
style () { return { 'background-image': `url(${this.background})` } },
|
||||
sitename () { return this.$store.state.config.name },
|
||||
chat () { return this.$store.state.chat.channel.state === 'joined' },
|
||||
|
|
58
src/App.scss
58
src/App.scss
|
@ -48,7 +48,7 @@ a {
|
|||
color: var(--link, $fallback--link);
|
||||
}
|
||||
|
||||
button{
|
||||
button {
|
||||
user-select: none;
|
||||
color: $fallback--fg;
|
||||
color: var(--fg, $fallback--fg);
|
||||
|
@ -64,10 +64,19 @@ button{
|
|||
font-size: 14px;
|
||||
font-family: sans-serif;
|
||||
|
||||
&::-moz-focus-inner {
|
||||
border: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0px 0px 4px rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
|
||||
&:active {
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.2);
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.5;
|
||||
|
@ -105,6 +114,7 @@ input, textarea, .select {
|
|||
position: relative;
|
||||
height: 29px;
|
||||
line-height: 16px;
|
||||
hyphens: none;
|
||||
|
||||
.icon-down-open {
|
||||
position: absolute;
|
||||
|
@ -226,6 +236,36 @@ nav {
|
|||
position: fixed;
|
||||
height: 50px;
|
||||
|
||||
.logo {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
|
||||
align-items: stretch;
|
||||
justify-content: center;
|
||||
flex: 0 0 auto;
|
||||
z-index: -1;
|
||||
.mask {
|
||||
mask-repeat: no-repeat;
|
||||
mask-position: center;
|
||||
mask-size: contain;
|
||||
background-color: $fallback--fg;
|
||||
background-color: var(--fg, $fallback--fg);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
img {
|
||||
display: block;
|
||||
flex: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.inner-nav {
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
|
@ -234,9 +274,6 @@ nav {
|
|||
flex-basis: 970px;
|
||||
margin: auto;
|
||||
height: 50px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-size: auto 80%;
|
||||
|
||||
a i {
|
||||
color: $fallback--link;
|
||||
|
@ -282,15 +319,25 @@ main-router {
|
|||
}
|
||||
|
||||
.panel-heading {
|
||||
display: flex;
|
||||
border-radius: $fallback--panelRadius $fallback--panelRadius 0 0;
|
||||
border-radius: var(--panelRadius, $fallback--panelRadius) var(--panelRadius, $fallback--panelRadius) 0 0;
|
||||
background-size: cover;
|
||||
padding: 0.6em 1.0em;
|
||||
padding: .6em .6em;
|
||||
text-align: left;
|
||||
font-size: 1.3em;
|
||||
line-height: 24px;
|
||||
background-color: $fallback--btn;
|
||||
background-color: var(--btn, $fallback--btn);
|
||||
align-items: baseline;
|
||||
|
||||
.title {
|
||||
flex: 1 0 auto;
|
||||
}
|
||||
|
||||
button {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.panel-heading.stub {
|
||||
|
@ -464,4 +511,3 @@ nav {
|
|||
border-radius: $fallback--inputRadius;
|
||||
border-radius: var(--inputRadius, $fallback--inputRadius);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
<template>
|
||||
<div id="app" v-bind:style="style">
|
||||
<nav class='container' @click="scrollToTop()" id="nav">
|
||||
<div class='inner-nav' :style="logoStyle">
|
||||
<div class='logo' :style='logoBgStyle'>
|
||||
<div class='mask' :style='logoMaskStyle'></div>
|
||||
<img :src='logo' :style='logoStyle'>
|
||||
</div>
|
||||
<div class='inner-nav'>
|
||||
<div class='item'>
|
||||
<router-link :to="{ name: 'root'}">{{sitename}}</router-link>
|
||||
</div>
|
||||
|
|
|
@ -16,7 +16,7 @@ const Attachment = {
|
|||
loopVideo: this.$store.state.config.loopVideo,
|
||||
showHidden: false,
|
||||
loading: false,
|
||||
img: this.type === 'image' && document.createElement('img')
|
||||
img: fileTypeService.fileType(this.attachment.mimetype) === 'image' && document.createElement('img')
|
||||
}
|
||||
},
|
||||
components: {
|
||||
|
|
|
@ -51,6 +51,10 @@
|
|||
|
||||
.nsfw-placeholder {
|
||||
cursor: pointer;
|
||||
|
||||
&.loading {
|
||||
cursor: progress;
|
||||
}
|
||||
}
|
||||
|
||||
.small-attachment {
|
||||
|
@ -61,6 +65,7 @@
|
|||
}
|
||||
|
||||
.attachment {
|
||||
position: relative;
|
||||
flex: 1 0 30%;
|
||||
margin: 0.5em 0.7em 0.6em 0.0em;
|
||||
align-self: flex-start;
|
||||
|
@ -88,10 +93,6 @@
|
|||
display: flex;
|
||||
}
|
||||
|
||||
&.loading {
|
||||
cursor: progress;
|
||||
}
|
||||
|
||||
.hider {
|
||||
position: absolute;
|
||||
margin: 10px;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<template>
|
||||
<div class="timeline panel panel-default">
|
||||
<div class="panel-heading conversation-heading">
|
||||
{{ $t('timeline.conversation') }}
|
||||
<span v-if="collapsable" style="float:right;">
|
||||
<span class="title"> {{ $t('timeline.conversation') }} </span>
|
||||
<span v-if="collapsable">
|
||||
<small><a href="#" @click.prevent="$emit('toggleExpanded')">{{ $t('timeline.collapse') }}</a></small>
|
||||
</span>
|
||||
</div>
|
||||
|
|
|
@ -6,8 +6,10 @@ const mediaUpload = {
|
|||
const input = this.$el.querySelector('input')
|
||||
|
||||
input.addEventListener('change', ({target}) => {
|
||||
const file = target.files[0]
|
||||
this.uploadFile(file)
|
||||
for (var i = 0; i < target.files.length; i++) {
|
||||
let file = target.files[i]
|
||||
this.uploadFile(file)
|
||||
}
|
||||
})
|
||||
},
|
||||
data () {
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<label class="btn btn-default">
|
||||
<i class="icon-spin4 animate-spin" v-if="uploading"></i>
|
||||
<i class="icon-upload" v-if="!uploading"></i>
|
||||
<input type=file style="position: fixed; top: -100em"></input>
|
||||
<input type="file" style="position: fixed; top: -100em" multiple="true"></input>
|
||||
</label>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -11,6 +11,14 @@ const Notifications = {
|
|||
notificationsFetcher.startFetching({ store, credentials })
|
||||
},
|
||||
computed: {
|
||||
visibleTypes () {
|
||||
return [
|
||||
this.$store.state.config.notificationVisibility.likes && 'like',
|
||||
this.$store.state.config.notificationVisibility.mentions && 'mention',
|
||||
this.$store.state.config.notificationVisibility.repeats && 'repeat',
|
||||
this.$store.state.config.notificationVisibility.follows && 'follow'
|
||||
].filter(_ => _)
|
||||
},
|
||||
notifications () {
|
||||
return this.$store.state.statuses.notifications.data
|
||||
},
|
||||
|
@ -18,13 +26,13 @@ const Notifications = {
|
|||
return this.$store.state.statuses.notifications.error
|
||||
},
|
||||
unseenNotifications () {
|
||||
return filter(this.notifications, ({seen}) => !seen)
|
||||
return filter(this.visibleNotifications, ({seen}) => !seen)
|
||||
},
|
||||
visibleNotifications () {
|
||||
// Don't know why, but sortBy([seen, -action.id]) doesn't work.
|
||||
let sortedNotifications = sortBy(this.notifications, ({action}) => -action.id)
|
||||
sortedNotifications = sortBy(sortedNotifications, 'seen')
|
||||
return sortedNotifications
|
||||
return sortedNotifications.filter((notification) => this.visibleTypes.includes(notification.type))
|
||||
},
|
||||
unseenCount () {
|
||||
return this.unseenNotifications.length
|
||||
|
|
|
@ -4,58 +4,25 @@
|
|||
// a bit of a hack to allow scrolling below notifications
|
||||
padding-bottom: 15em;
|
||||
|
||||
.title {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.panel {
|
||||
background: $fallback--bg;
|
||||
background: var(--bg, $fallback--bg)
|
||||
}
|
||||
|
||||
.panel-body {
|
||||
border-color: $fallback--border;
|
||||
border-color: var(--border, $fallback--border)
|
||||
}
|
||||
|
||||
.panel-heading {
|
||||
// force the text to stay centered, while keeping
|
||||
// the button in the right side of the panel heading
|
||||
position: relative;
|
||||
background: $fallback--btn;
|
||||
background: var(--btn, $fallback--btn);
|
||||
color: $fallback--fg;
|
||||
color: var(--fg, $fallback--fg);
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
.read-button {
|
||||
position: absolute;
|
||||
right: 0.7em;
|
||||
height: 1.8em;
|
||||
line-height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.unseen-count {
|
||||
display: inline-block;
|
||||
background-color: $fallback--cRed;
|
||||
background-color: var(--cRed, $fallback--cRed);
|
||||
text-shadow: 0px 0px 3px rgba(0, 0, 0, 0.5);
|
||||
min-width: 1.3em;
|
||||
border-radius: 1.3em;
|
||||
margin: 0 0.2em 0 -0.4em;
|
||||
border-radius: 99px;
|
||||
min-width: 22px;
|
||||
max-width: 22px;
|
||||
min-height: 22px;
|
||||
max-height: 22px;
|
||||
color: white;
|
||||
font-size: 0.9em;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
text-align: center;
|
||||
line-height: 1.3em;
|
||||
vertical-align: middle
|
||||
}
|
||||
|
||||
.loadmore-error {
|
||||
position: absolute;
|
||||
right: 0.6em;
|
||||
font-size: 14px;
|
||||
min-width: 6em;
|
||||
font-family: sans-serif;
|
||||
text-align: center;
|
||||
padding: 0 0.25em 0 0.25em;
|
||||
margin: 0;
|
||||
|
@ -73,7 +40,8 @@
|
|||
box-sizing: border-box;
|
||||
display: flex;
|
||||
border-bottom: 1px solid;
|
||||
border-bottom-color: inherit;
|
||||
border-color: $fallback--border;
|
||||
border-color: var(--border, $fallback--border);
|
||||
|
||||
.broken-favorite {
|
||||
border-radius: $fallback--tooltipRadius;
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
<div class="notifications">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<span class="unseen-count" v-if="unseenCount">{{unseenCount}}</span>
|
||||
<div class="title"> {{$t('notifications.notifications')}}</div>
|
||||
<div class="title">
|
||||
{{$t('notifications.notifications')}}
|
||||
<span class="unseen-count" v-if="unseenCount">{{unseenCount}}</span>
|
||||
</div>
|
||||
<div @click.prevent class="loadmore-error alert error" v-if="error">
|
||||
{{$t('timeline.error_fetching')}}
|
||||
</div>
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
<template>
|
||||
<div v-if="loggedIn && visibility !== 'private' && visibility !== 'direct'">
|
||||
<i :class='classes' class='icon-retweet rt-active' v-on:click.prevent='retweet()'></i>
|
||||
<span v-if='status.repeat_num > 0'>{{status.repeat_num}}</span>
|
||||
<div v-if="loggedIn">
|
||||
<template v-if="visibility !== 'private' && visibility !== 'direct'">
|
||||
<i :class='classes' class='icon-retweet rt-active' v-on:click.prevent='retweet()'></i>
|
||||
<span v-if='status.repeat_num > 0'>{{status.repeat_num}}</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<i :class='classes' class='icon-lock' :title="$t('timeline.no_retweet_hint')"></i>
|
||||
</template>
|
||||
</div>
|
||||
<div v-else-if="!loggedIn">
|
||||
<i :class='classes' class='icon-retweet'></i>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
/* eslint-env browser */
|
||||
import TabSwitcher from '../tab_switcher/tab_switcher.jsx'
|
||||
import StyleSwitcher from '../style_switcher/style_switcher.vue'
|
||||
import InterfaceLanguageSwitcher from '../interface_language_switcher/interface_language_switcher.vue'
|
||||
import { filter, trim } from 'lodash'
|
||||
|
@ -9,6 +10,7 @@ const settings = {
|
|||
hideAttachmentsLocal: this.$store.state.config.hideAttachments,
|
||||
hideAttachmentsInConvLocal: this.$store.state.config.hideAttachmentsInConv,
|
||||
hideNsfwLocal: this.$store.state.config.hideNsfw,
|
||||
notificationVisibilityLocal: this.$store.state.config.notificationVisibility,
|
||||
replyVisibilityLocal: this.$store.state.config.replyVisibility,
|
||||
loopVideoLocal: this.$store.state.config.loopVideo,
|
||||
loopVideoSilentOnlyLocal: this.$store.state.config.loopVideoSilentOnly,
|
||||
|
@ -29,6 +31,7 @@ const settings = {
|
|||
}
|
||||
},
|
||||
components: {
|
||||
TabSwitcher,
|
||||
StyleSwitcher,
|
||||
InterfaceLanguageSwitcher
|
||||
},
|
||||
|
@ -47,6 +50,18 @@ const settings = {
|
|||
hideNsfwLocal (value) {
|
||||
this.$store.dispatch('setOption', { name: 'hideNsfw', value })
|
||||
},
|
||||
'notificationVisibilityLocal.likes' (value) {
|
||||
this.$store.dispatch('setOption', { name: 'notificationVisibility', value: this.$store.state.config.notificationVisibility })
|
||||
},
|
||||
'notificationVisibilityLocal.follows' (value) {
|
||||
this.$store.dispatch('setOption', { name: 'notificationVisibility', value: this.$store.state.config.notificationVisibility })
|
||||
},
|
||||
'notificationVisibilityLocal.repeats' (value) {
|
||||
this.$store.dispatch('setOption', { name: 'notificationVisibility', value: this.$store.state.config.notificationVisibility })
|
||||
},
|
||||
'notificationVisibilityLocal.mentions' (value) {
|
||||
this.$store.dispatch('setOption', { name: 'notificationVisibility', value: this.$store.state.config.notificationVisibility })
|
||||
},
|
||||
replyVisibilityLocal (value) {
|
||||
this.$store.dispatch('setOption', { name: 'replyVisibility', value })
|
||||
},
|
||||
|
|
|
@ -4,90 +4,132 @@
|
|||
{{$t('settings.settings')}}
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="setting-item">
|
||||
<h2>{{$t('settings.theme')}}</h2>
|
||||
<style-switcher></style-switcher>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<h2>{{$t('settings.filtering')}}</h2>
|
||||
<p>{{$t('settings.filtering_explanation')}}</p>
|
||||
<textarea id="muteWords" v-model="muteWordsString"></textarea>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<h2>{{$t('nav.timeline')}}</h2>
|
||||
<ul class="setting-list">
|
||||
<li>
|
||||
<input type="checkbox" id="collapseMessageWithSubject" v-model="collapseMessageWithSubjectLocal">
|
||||
<label for="collapseMessageWithSubject">{{$t('settings.collapse_subject')}}</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}]">
|
||||
<tab-switcher>
|
||||
<div :label="$t('settings.general')" >
|
||||
<div class="setting-item">
|
||||
<h2>{{ $t('settings.interfaceLanguage') }}</h2>
|
||||
<interface-language-switcher />
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<h2>{{$t('nav.timeline')}}</h2>
|
||||
<ul class="setting-list">
|
||||
<li>
|
||||
<input :disabled="!streamingLocal" type="checkbox" id="pauseOnUnfocused" v-model="pauseOnUnfocusedLocal">
|
||||
<label for="pauseOnUnfocused">{{$t('settings.pause_on_unfocused')}}</label>
|
||||
<input type="checkbox" id="collapseMessageWithSubject" v-model="collapseMessageWithSubjectLocal">
|
||||
<label for="collapseMessageWithSubject">{{$t('settings.collapse_subject')}}</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>
|
||||
<input :disabled="!streamingLocal" type="checkbox" id="pauseOnUnfocused" v-model="pauseOnUnfocusedLocal">
|
||||
<label for="pauseOnUnfocused">{{$t('settings.pause_on_unfocused')}}</label>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<input type="checkbox" id="autoload" v-model="autoLoadLocal">
|
||||
<label for="autoload">{{$t('settings.autoload')}}</label>
|
||||
</li>
|
||||
<li>
|
||||
<input type="checkbox" id="hoverPreview" v-model="hoverPreviewLocal">
|
||||
<label for="hoverPreview">{{$t('settings.reply_link_preview')}}</label>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<input type="checkbox" id="autoload" v-model="autoLoadLocal">
|
||||
<label for="autoload">{{$t('settings.autoload')}}</label>
|
||||
</li>
|
||||
<li>
|
||||
<input type="checkbox" id="hoverPreview" v-model="hoverPreviewLocal">
|
||||
<label for="hoverPreview">{{$t('settings.reply_link_preview')}}</label>
|
||||
</li>
|
||||
<li>
|
||||
<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>
|
||||
</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>
|
||||
<input type="checkbox" id="hideNsfw" v-model="hideNsfwLocal">
|
||||
<label for="hideNsfw">{{$t('settings.nsfw_clickthrough')}}</label>
|
||||
</li>
|
||||
<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}]">
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<h2>{{$t('settings.attachments')}}</h2>
|
||||
<ul class="setting-list">
|
||||
<li>
|
||||
<input :disabled="!loopVideoLocal || !loopSilentAvailable" type="checkbox" id="loopVideoSilentOnly" v-model="loopVideoSilentOnlyLocal">
|
||||
<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>
|
||||
<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>
|
||||
<input type="checkbox" id="hideNsfw" v-model="hideNsfwLocal">
|
||||
<label for="hideNsfw">{{$t('settings.nsfw_clickthrough')}}</label>
|
||||
</li>
|
||||
<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>
|
||||
<input :disabled="!loopVideoLocal || !loopSilentAvailable" type="checkbox" id="loopVideoSilentOnly" v-model="loopVideoSilentOnlyLocal">
|
||||
<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>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<h2>{{ $t('settings.interfaceLanguage') }}</h2>
|
||||
<interface-language-switcher />
|
||||
</div>
|
||||
</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>
|
||||
</label>
|
||||
</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>
|
||||
<div class="setting-item">
|
||||
<p>{{$t('settings.filtering_explanation')}}</p>
|
||||
<textarea id="muteWords" v-model="muteWordsString"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</tab-switcher>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -103,6 +145,23 @@
|
|||
margin: 1em 1em 1.4em;
|
||||
padding-bottom: 1.4em;
|
||||
|
||||
> div {
|
||||
margin-bottom: .5em;
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
padding-bottom: 0;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
select {
|
||||
min-width: 10em;
|
||||
}
|
||||
|
||||
|
||||
textarea {
|
||||
width: 100%;
|
||||
|
@ -130,12 +189,24 @@
|
|||
}
|
||||
|
||||
.btn {
|
||||
margin-top: 1em;
|
||||
min-height: 28px;
|
||||
}
|
||||
|
||||
.submit {
|
||||
margin-top: 1em;
|
||||
min-height: 30px;
|
||||
width: 10em;
|
||||
}
|
||||
}
|
||||
.setting-list {
|
||||
.select-multiple {
|
||||
display: flex;
|
||||
.option-list {
|
||||
margin: 0;
|
||||
padding-left: .5em;
|
||||
}
|
||||
}
|
||||
.setting-list,
|
||||
.option-list{
|
||||
list-style-type: none;
|
||||
padding-left: 2em;
|
||||
li {
|
||||
|
|
|
@ -18,7 +18,11 @@ const StillImage = {
|
|||
onLoad () {
|
||||
const canvas = this.$refs.canvas
|
||||
if (!canvas) return
|
||||
canvas.getContext('2d').drawImage(this.$refs.src, 1, 1, canvas.width, canvas.height)
|
||||
const width = this.$refs.src.naturalWidth
|
||||
const height = this.$refs.src.naturalHeight
|
||||
canvas.width = width
|
||||
canvas.height = height
|
||||
canvas.getContext('2d').drawImage(this.$refs.src, 0, 0, width, height)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
right: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,102 +1,30 @@
|
|||
<template>
|
||||
<div>
|
||||
<div>{{$t('settings.presets')}}
|
||||
<div>
|
||||
<div class="presets-container">
|
||||
<div>
|
||||
{{$t('settings.presets')}}
|
||||
<label for="style-switcher" class='select'>
|
||||
<select id="style-switcher" v-model="selected" class="style-switcher">
|
||||
<option v-for="style in availableStyles" :value="style" :style="{
|
||||
backgroundColor: style[1],
|
||||
color: style[3]
|
||||
}">{{style[0]}}</option>
|
||||
<option v-for="style in availableStyles"
|
||||
:value="style"
|
||||
:style="{
|
||||
backgroundColor: style[1],
|
||||
color: style[3]
|
||||
}">
|
||||
{{style[0]}}
|
||||
</option>
|
||||
</select>
|
||||
<i class="icon-down-open"/>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<div class="import-export">
|
||||
<button class="btn" @click="exportCurrentTheme">{{ $t('settings.export_theme') }}</button>
|
||||
<button class="btn" @click="importTheme">{{ $t('settings.import_theme') }}</button>
|
||||
<p v-if="invalidThemeImported" class="import-warning">{{ $t('settings.invalid_theme_imported') }}</p>
|
||||
</div>
|
||||
<div class="color-container">
|
||||
<p>{{$t('settings.theme_help')}}</p>
|
||||
<div class="color-item">
|
||||
<label for="bgcolor" class="theme-color-lb">{{$t('settings.background')}}</label>
|
||||
<input id="bgcolor" class="theme-color-cl" type="color" v-model="bgColorLocal">
|
||||
<input id="bgcolor-t" class="theme-color-in" type="text" v-model="bgColorLocal">
|
||||
</div>
|
||||
<div class="color-item">
|
||||
<label for="fgcolor" class="theme-color-lb">{{$t('settings.foreground')}}</label>
|
||||
<input id="fgcolor" class="theme-color-cl" type="color" v-model="btnColorLocal">
|
||||
<input id="fgcolor-t" class="theme-color-in" type="text" v-model="btnColorLocal">
|
||||
</div>
|
||||
<div class="color-item">
|
||||
<label for="textcolor" class="theme-color-lb">{{$t('settings.text')}}</label>
|
||||
<input id="textcolor" class="theme-color-cl" type="color" v-model="textColorLocal">
|
||||
<input id="textcolor-t" class="theme-color-in" type="text" v-model="textColorLocal">
|
||||
</div>
|
||||
<div class="color-item">
|
||||
<label for="linkcolor" class="theme-color-lb">{{$t('settings.links')}}</label>
|
||||
<input id="linkcolor" class="theme-color-cl" type="color" v-model="linkColorLocal">
|
||||
<input id="linkcolor-t" class="theme-color-in" type="text" v-model="linkColorLocal">
|
||||
</div>
|
||||
<div class="color-item">
|
||||
<label for="redcolor" class="theme-color-lb">{{$t('settings.cRed')}}</label>
|
||||
<input id="redcolor" class="theme-color-cl" type="color" v-model="redColorLocal">
|
||||
<input id="redcolor-t" class="theme-color-in" type="text" v-model="redColorLocal">
|
||||
</div>
|
||||
<div class="color-item">
|
||||
<label for="bluecolor" class="theme-color-lb">{{$t('settings.cBlue')}}</label>
|
||||
<input id="bluecolor" class="theme-color-cl" type="color" v-model="blueColorLocal">
|
||||
<input id="bluecolor-t" class="theme-color-in" type="text" v-model="blueColorLocal">
|
||||
</div>
|
||||
<div class="color-item">
|
||||
<label for="greencolor" class="theme-color-lb">{{$t('settings.cGreen')}}</label>
|
||||
<input id="greencolor" class="theme-color-cl" type="color" v-model="greenColorLocal">
|
||||
<input id="greencolor-t" class="theme-color-in" type="green" v-model="greenColorLocal">
|
||||
</div>
|
||||
<div class="color-item">
|
||||
<label for="orangecolor" class="theme-color-lb">{{$t('settings.cOrange')}}</label>
|
||||
<input id="orangecolor" class="theme-color-cl" type="color" v-model="orangeColorLocal">
|
||||
<input id="orangecolor-t" class="theme-color-in" type="text" v-model="orangeColorLocal">
|
||||
</div>
|
||||
</div>
|
||||
<div class="radius-container">
|
||||
<p>{{$t('settings.radii_help')}}</p>
|
||||
<div class="radius-item">
|
||||
<label for="btnradius" class="theme-radius-lb">{{$t('settings.btnRadius')}}</label>
|
||||
<input id="btnradius" class="theme-radius-rn" type="range" v-model="btnRadiusLocal" max="16">
|
||||
<input id="btnradius-t" class="theme-radius-in" type="text" v-model="btnRadiusLocal">
|
||||
</div>
|
||||
<div class="radius-item">
|
||||
<label for="inputradius" class="theme-radius-lb">{{$t('settings.inputRadius')}}</label>
|
||||
<input id="inputradius" class="theme-radius-rn" type="range" v-model="inputRadiusLocal" max="16">
|
||||
<input id="inputradius-t" class="theme-radius-in" type="text" v-model="inputRadiusLocal">
|
||||
</div>
|
||||
<div class="radius-item">
|
||||
<label for="panelradius" class="theme-radius-lb">{{$t('settings.panelRadius')}}</label>
|
||||
<input id="panelradius" class="theme-radius-rn" type="range" v-model="panelRadiusLocal" max="50">
|
||||
<input id="panelradius-t" class="theme-radius-in" type="text" v-model="panelRadiusLocal">
|
||||
</div>
|
||||
<div class="radius-item">
|
||||
<label for="avatarradius" class="theme-radius-lb">{{$t('settings.avatarRadius')}}</label>
|
||||
<input id="avatarradius" class="theme-radius-rn" type="range" v-model="avatarRadiusLocal" max="28">
|
||||
<input id="avatarradius-t" class="theme-radius-in" type="green" v-model="avatarRadiusLocal">
|
||||
</div>
|
||||
<div class="radius-item">
|
||||
<label for="avataraltradius" class="theme-radius-lb">{{$t('settings.avatarAltRadius')}}</label>
|
||||
<input id="avataraltradius" class="theme-radius-rn" type="range" v-model="avatarAltRadiusLocal" max="28">
|
||||
<input id="avataraltradius-t" class="theme-radius-in" type="text" v-model="avatarAltRadiusLocal">
|
||||
</div>
|
||||
<div class="radius-item">
|
||||
<label for="attachmentradius" class="theme-radius-lb">{{$t('settings.attachmentRadius')}}</label>
|
||||
<input id="attachmentrradius" class="theme-radius-rn" type="range" v-model="attachmentRadiusLocal" max="50">
|
||||
<input id="attachmentradius-t" class="theme-radius-in" type="text" v-model="attachmentRadiusLocal">
|
||||
</div>
|
||||
<div class="radius-item">
|
||||
<label for="tooltipradius" class="theme-radius-lb">{{$t('settings.tooltipRadius')}}</label>
|
||||
<input id="tooltipradius" class="theme-radius-rn" type="range" v-model="tooltipRadiusLocal" max="20">
|
||||
<input id="tooltipradius-t" class="theme-radius-in" type="text" v-model="tooltipRadiusLocal">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="preview-container">
|
||||
<div :style="{
|
||||
'--btnRadius': btnRadiusLocal + 'px',
|
||||
'--inputRadius': inputRadiusLocal + 'px',
|
||||
|
@ -127,8 +55,95 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn" @click="setCustomTheme">{{$t('general.apply')}}</button>
|
||||
</div>
|
||||
|
||||
<div class="color-container">
|
||||
<p>{{$t('settings.theme_help')}}</p>
|
||||
<div class="color-item">
|
||||
<label for="bgcolor" class="theme-color-lb">{{$t('settings.background')}}</label>
|
||||
<input id="bgcolor" class="theme-color-cl" type="color" v-model="bgColorLocal">
|
||||
<input id="bgcolor-t" class="theme-color-in" type="text" v-model="bgColorLocal">
|
||||
</div>
|
||||
<div class="color-item">
|
||||
<label for="fgcolor" class="theme-color-lb">{{$t('settings.foreground')}}</label>
|
||||
<input id="fgcolor" class="theme-color-cl" type="color" v-model="btnColorLocal">
|
||||
<input id="fgcolor-t" class="theme-color-in" type="text" v-model="btnColorLocal">
|
||||
</div>
|
||||
<div class="color-item">
|
||||
<label for="textcolor" class="theme-color-lb">{{$t('settings.text')}}</label>
|
||||
<input id="textcolor" class="theme-color-cl" type="color" v-model="textColorLocal">
|
||||
<input id="textcolor-t" class="theme-color-in" type="text" v-model="textColorLocal">
|
||||
</div>
|
||||
<div class="color-item">
|
||||
<label for="linkcolor" class="theme-color-lb">{{$t('settings.links')}}</label>
|
||||
<input id="linkcolor" class="theme-color-cl" type="color" v-model="linkColorLocal">
|
||||
<input id="linkcolor-t" class="theme-color-in" type="text" v-model="linkColorLocal">
|
||||
</div>
|
||||
<div class="color-item">
|
||||
<label for="redcolor" class="theme-color-lb">{{$t('settings.cRed')}}</label>
|
||||
<input id="redcolor" class="theme-color-cl" type="color" v-model="redColorLocal">
|
||||
<input id="redcolor-t" class="theme-color-in" type="text" v-model="redColorLocal">
|
||||
</div>
|
||||
<div class="color-item">
|
||||
<label for="bluecolor" class="theme-color-lb">{{$t('settings.cBlue')}}</label>
|
||||
<input id="bluecolor" class="theme-color-cl" type="color" v-model="blueColorLocal">
|
||||
<input id="bluecolor-t" class="theme-color-in" type="text" v-model="blueColorLocal">
|
||||
</div>
|
||||
<div class="color-item">
|
||||
<label for="greencolor" class="theme-color-lb">{{$t('settings.cGreen')}}</label>
|
||||
<input id="greencolor" class="theme-color-cl" type="color" v-model="greenColorLocal">
|
||||
<input id="greencolor-t" class="theme-color-in" type="green" v-model="greenColorLocal">
|
||||
</div>
|
||||
<div class="color-item">
|
||||
<label for="orangecolor" class="theme-color-lb">{{$t('settings.cOrange')}}</label>
|
||||
<input id="orangecolor" class="theme-color-cl" type="color" v-model="orangeColorLocal">
|
||||
<input id="orangecolor-t" class="theme-color-in" type="text" v-model="orangeColorLocal">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="radius-container">
|
||||
<p>{{$t('settings.radii_help')}}</p>
|
||||
<div class="radius-item">
|
||||
<label for="btnradius" class="theme-radius-lb">{{$t('settings.btnRadius')}}</label>
|
||||
<input id="btnradius" class="theme-radius-rn" type="range" v-model="btnRadiusLocal" max="16">
|
||||
<input id="btnradius-t" class="theme-radius-in" type="text" v-model="btnRadiusLocal">
|
||||
</div>
|
||||
<div class="radius-item">
|
||||
<label for="inputradius" class="theme-radius-lb">{{$t('settings.inputRadius')}}</label>
|
||||
<input id="inputradius" class="theme-radius-rn" type="range" v-model="inputRadiusLocal" max="16">
|
||||
<input id="inputradius-t" class="theme-radius-in" type="text" v-model="inputRadiusLocal">
|
||||
</div>
|
||||
<div class="radius-item">
|
||||
<label for="panelradius" class="theme-radius-lb">{{$t('settings.panelRadius')}}</label>
|
||||
<input id="panelradius" class="theme-radius-rn" type="range" v-model="panelRadiusLocal" max="50">
|
||||
<input id="panelradius-t" class="theme-radius-in" type="text" v-model="panelRadiusLocal">
|
||||
</div>
|
||||
<div class="radius-item">
|
||||
<label for="avatarradius" class="theme-radius-lb">{{$t('settings.avatarRadius')}}</label>
|
||||
<input id="avatarradius" class="theme-radius-rn" type="range" v-model="avatarRadiusLocal" max="28">
|
||||
<input id="avatarradius-t" class="theme-radius-in" type="green" v-model="avatarRadiusLocal">
|
||||
</div>
|
||||
<div class="radius-item">
|
||||
<label for="avataraltradius" class="theme-radius-lb">{{$t('settings.avatarAltRadius')}}</label>
|
||||
<input id="avataraltradius" class="theme-radius-rn" type="range" v-model="avatarAltRadiusLocal" max="28">
|
||||
<input id="avataraltradius-t" class="theme-radius-in" type="text" v-model="avatarAltRadiusLocal">
|
||||
</div>
|
||||
<div class="radius-item">
|
||||
<label for="attachmentradius" class="theme-radius-lb">{{$t('settings.attachmentRadius')}}</label>
|
||||
<input id="attachmentrradius" class="theme-radius-rn" type="range" v-model="attachmentRadiusLocal" max="50">
|
||||
<input id="attachmentradius-t" class="theme-radius-in" type="text" v-model="attachmentRadiusLocal">
|
||||
</div>
|
||||
<div class="radius-item">
|
||||
<label for="tooltipradius" class="theme-radius-lb">{{$t('settings.tooltipRadius')}}</label>
|
||||
<input id="tooltipradius" class="theme-radius-rn" type="range" v-model="tooltipRadiusLocal" max="20">
|
||||
<input id="tooltipradius-t" class="theme-radius-in" type="text" v-model="tooltipRadiusLocal">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="apply-container">
|
||||
<button class="btn submit" @click="setCustomTheme">{{$t('general.apply')}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script src="./style_switcher.js"></script>
|
||||
|
@ -144,15 +159,19 @@
|
|||
color: var(--cRed, $fallback--cRed);
|
||||
}
|
||||
|
||||
.apply-container,
|
||||
.radius-container,
|
||||
.color-container {
|
||||
.color-container,
|
||||
.presets-container {
|
||||
display: flex;
|
||||
|
||||
p {
|
||||
flex: 2 0 100%;
|
||||
margin-top: 2em;
|
||||
margin-bottom: .5em;
|
||||
}
|
||||
}
|
||||
|
||||
.radius-container {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
@ -162,6 +181,36 @@
|
|||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.presets-container {
|
||||
justify-content: center;
|
||||
.import-export {
|
||||
display: flex;
|
||||
|
||||
.btn {
|
||||
margin-left: .5em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.preview-container {
|
||||
border-top: 1px dashed;
|
||||
border-bottom: 1px dashed;
|
||||
border-color: $fallback--border;
|
||||
border-color: var(--border, $fallback--border);
|
||||
margin: 1em -1em 0;
|
||||
padding: 1em;
|
||||
|
||||
.btn {
|
||||
margin-top: 1em;
|
||||
min-height: 30px;
|
||||
width: 10em;
|
||||
}
|
||||
}
|
||||
|
||||
.apply-container {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.radius-item,
|
||||
.color-item {
|
||||
min-width: 20em;
|
||||
|
@ -229,6 +278,7 @@
|
|||
flex: 0;
|
||||
min-width: 2em;
|
||||
cursor: pointer;
|
||||
max-height: 29px;
|
||||
}
|
||||
|
||||
.theme-preview-content {
|
||||
|
|
44
src/components/tab_switcher/tab_switcher.jsx
Normal file
44
src/components/tab_switcher/tab_switcher.jsx
Normal file
|
@ -0,0 +1,44 @@
|
|||
import Vue from 'vue'
|
||||
|
||||
import './tab_switcher.scss'
|
||||
|
||||
export default Vue.component('tab-switcher', {
|
||||
name: 'TabSwitcher',
|
||||
data () {
|
||||
return {
|
||||
active: 0
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
activateTab(index) {
|
||||
return () => this.active = index;
|
||||
}
|
||||
},
|
||||
render(h) {
|
||||
const tabs = this.$slots.default
|
||||
.filter(slot => slot.data)
|
||||
.map((slot, index) => {
|
||||
const classes = ['tab']
|
||||
|
||||
if (index === this.active) {
|
||||
classes.push('active')
|
||||
}
|
||||
return (<button onClick={this.activateTab(index)} class={ classes.join(' ') }>{slot.data.attrs.label}</button>)
|
||||
});
|
||||
const contents = (
|
||||
<div>
|
||||
{this.$slots.default.filter(slot => slot.data)[this.active]}
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div class="tab-switcher">
|
||||
<div class="tabs">
|
||||
{tabs}
|
||||
</div>
|
||||
<div class="contents">
|
||||
{contents}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
})
|
43
src/components/tab_switcher/tab_switcher.scss
Normal file
43
src/components/tab_switcher/tab_switcher.scss
Normal file
|
@ -0,0 +1,43 @@
|
|||
@import '../../_variables.scss';
|
||||
|
||||
.tab-switcher {
|
||||
.tabs {
|
||||
display: flex;
|
||||
position: relative;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
padding-top: 5px;
|
||||
|
||||
&::after, &::before {
|
||||
display: block;
|
||||
content: '';
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.tab, &::after, &::before {
|
||||
border-bottom: 1px solid;
|
||||
border-bottom-color: $fallback--btn;
|
||||
border-bottom-color: var(--btn, $fallback--btn);
|
||||
}
|
||||
|
||||
.tab {
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
padding: .3em 1em;
|
||||
|
||||
&:not(.active) {
|
||||
border-bottom: 1px solid;
|
||||
border-bottom-color: $fallback--btn;
|
||||
border-bottom-color: var(--btn, $fallback--btn);
|
||||
z-index: 4;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: transparent;
|
||||
border-bottom: none;
|
||||
z-index: 5;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -57,36 +57,8 @@
|
|||
@import '../../_variables.scss';
|
||||
|
||||
.timeline {
|
||||
.timeline-heading {
|
||||
position: relative;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.title {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 70%;
|
||||
}
|
||||
|
||||
.loadmore-button {
|
||||
position: absolute;
|
||||
right: 0.6em;
|
||||
font-size: 14px;
|
||||
|
||||
min-width: 6em;
|
||||
height: 1.8em;
|
||||
line-height: 100%;
|
||||
}
|
||||
|
||||
.loadmore-text {
|
||||
position: absolute;
|
||||
right: 0.6em;
|
||||
font-size: 14px;
|
||||
min-width: 6em;
|
||||
font-family: sans-serif;
|
||||
text-align: center;
|
||||
padding: 0 0.5em 0 0.5em;
|
||||
opacity: 0.8;
|
||||
background-color: transparent;
|
||||
color: $fallback--faint;
|
||||
|
@ -94,11 +66,8 @@
|
|||
}
|
||||
|
||||
.loadmore-error {
|
||||
position: absolute;
|
||||
right: 0.6em;
|
||||
font-size: 14px;
|
||||
min-width: 6em;
|
||||
font-family: sans-serif;
|
||||
text-align: center;
|
||||
padding: 0 0.25em 0 0.25em;
|
||||
margin: 0;
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
padding-bottom: 10px;
|
||||
.panel-heading {
|
||||
background: transparent;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import TabSwitcher from '../tab_switcher/tab_switcher.jsx'
|
||||
import StyleSwitcher from '../style_switcher/style_switcher.vue'
|
||||
|
||||
const UserSettings = {
|
||||
|
@ -23,7 +24,8 @@ const UserSettings = {
|
|||
}
|
||||
},
|
||||
components: {
|
||||
StyleSwitcher
|
||||
StyleSwitcher,
|
||||
TabSwitcher
|
||||
},
|
||||
computed: {
|
||||
user () {
|
||||
|
|
|
@ -4,126 +4,131 @@
|
|||
{{$t('settings.user_settings')}}
|
||||
</div>
|
||||
<div class="panel-body profile-edit">
|
||||
<div class="tab-switcher">
|
||||
<button class="btn btn-default" @click="activateTab('profile')">{{$t('settings.profile_tab')}}</button>
|
||||
<button class="btn btn-default" @click="activateTab('security')">{{$t('settings.security_tab')}}</button>
|
||||
<button class="btn btn-default" @click="activateTab('data_import_export')" v-if="pleromaBackend">{{$t('settings.data_import_export_tab')}}</button>
|
||||
</div>
|
||||
<div class="setting-item" v-if="activeTab == 'profile'">
|
||||
<h2>{{$t('settings.name_bio')}}</h2>
|
||||
<p>{{$t('settings.name')}}</p>
|
||||
<input class='name-changer' id='username' v-model="newname"></input>
|
||||
<p>{{$t('settings.bio')}}</p>
|
||||
<textarea class="bio" v-model="newbio"></textarea>
|
||||
<p>
|
||||
<input type="checkbox" v-model="newlocked" id="account-locked">
|
||||
<label for="account-locked">{{$t('settings.lock_account_description')}}</label>
|
||||
</p>
|
||||
<div v-if="scopeOptionsEnabled">
|
||||
<label for="default-vis">{{$t('settings.default_vis')}}</label>
|
||||
<div id="default-vis" class="visibility-tray">
|
||||
<i v-on:click="changeVis('direct')" class="icon-mail-alt" :class="vis.direct"></i>
|
||||
<i v-on:click="changeVis('private')" class="icon-lock" :class="vis.private"></i>
|
||||
<i v-on:click="changeVis('unlisted')" class="icon-lock-open-alt" :class="vis.unlisted"></i>
|
||||
<i v-on:click="changeVis('public')" class="icon-globe" :class="vis.public"></i>
|
||||
<tab-switcher>
|
||||
<div :label="$t('settings.profile_tab')">
|
||||
<div class="setting-item" >
|
||||
<h2>{{$t('settings.name_bio')}}</h2>
|
||||
<p>{{$t('settings.name')}}</p>
|
||||
<input class='name-changer' id='username' v-model="newname"></input>
|
||||
<p>{{$t('settings.bio')}}</p>
|
||||
<textarea class="bio" v-model="newbio"></textarea>
|
||||
<p>
|
||||
<input type="checkbox" v-model="newlocked" id="account-locked">
|
||||
<label for="account-locked">{{$t('settings.lock_account_description')}}</label>
|
||||
</p>
|
||||
<div v-if="scopeOptionsEnabled">
|
||||
<label for="default-vis">{{$t('settings.default_vis')}}</label>
|
||||
<div id="default-vis" class="visibility-tray">
|
||||
<i v-on:click="changeVis('direct')" class="icon-mail-alt" :class="vis.direct"></i>
|
||||
<i v-on:click="changeVis('private')" class="icon-lock" :class="vis.private"></i>
|
||||
<i v-on:click="changeVis('unlisted')" class="icon-lock-open-alt" :class="vis.unlisted"></i>
|
||||
<i v-on:click="changeVis('public')" class="icon-globe" :class="vis.public"></i>
|
||||
</div>
|
||||
</div>
|
||||
<button :disabled='newname.length <= 0' class="btn btn-default" @click="updateProfile">{{$t('general.submit')}}</button>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<h2>{{$t('settings.avatar')}}</h2>
|
||||
<p>{{$t('settings.current_avatar')}}</p>
|
||||
<img :src="user.profile_image_url_original" class="old-avatar"></img>
|
||||
<p>{{$t('settings.set_new_avatar')}}</p>
|
||||
<img class="new-avatar" v-bind:src="previews[0]" v-if="previews[0]">
|
||||
</img>
|
||||
<div>
|
||||
<input type="file" @change="uploadFile(0, $event)" ></input>
|
||||
</div>
|
||||
<i class="icon-spin4 animate-spin" v-if="uploading[0]"></i>
|
||||
<button class="btn btn-default" v-else-if="previews[0]" @click="submitAvatar">{{$t('general.submit')}}</button>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<h2>{{$t('settings.profile_banner')}}</h2>
|
||||
<p>{{$t('settings.current_profile_banner')}}</p>
|
||||
<img :src="user.cover_photo" class="banner"></img>
|
||||
<p>{{$t('settings.set_new_profile_banner')}}</p>
|
||||
<img class="banner" v-bind:src="previews[1]" v-if="previews[1]">
|
||||
</img>
|
||||
<div>
|
||||
<input type="file" @change="uploadFile(1, $event)" ></input>
|
||||
</div>
|
||||
<i class=" icon-spin4 animate-spin uploading" v-if="uploading[1]"></i>
|
||||
<button class="btn btn-default" v-else-if="previews[1]" @click="submitBanner">{{$t('general.submit')}}</button>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<h2>{{$t('settings.profile_background')}}</h2>
|
||||
<p>{{$t('settings.set_new_profile_background')}}</p>
|
||||
<img class="bg" v-bind:src="previews[2]" v-if="previews[2]">
|
||||
</img>
|
||||
<div>
|
||||
<input type="file" @change="uploadFile(2, $event)" ></input>
|
||||
</div>
|
||||
<i class=" icon-spin4 animate-spin uploading" v-if="uploading[2]"></i>
|
||||
<button class="btn btn-default" v-else-if="previews[2]" @click="submitBg">{{$t('general.submit')}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<button :disabled='newname.length <= 0' class="btn btn-default" @click="updateProfile">{{$t('general.submit')}}</button>
|
||||
</div>
|
||||
<div class="setting-item" v-if="activeTab == 'profile'">
|
||||
<h2>{{$t('settings.avatar')}}</h2>
|
||||
<p>{{$t('settings.current_avatar')}}</p>
|
||||
<img :src="user.profile_image_url_original" class="old-avatar"></img>
|
||||
<p>{{$t('settings.set_new_avatar')}}</p>
|
||||
<img class="new-avatar" v-bind:src="previews[0]" v-if="previews[0]">
|
||||
</img>
|
||||
<div>
|
||||
<input type="file" @change="uploadFile(0, $event)" ></input>
|
||||
|
||||
<div :label="$t('settings.security_tab')">
|
||||
<div class="setting-item">
|
||||
<h2>{{$t('settings.change_password')}}</h2>
|
||||
<div>
|
||||
<p>{{$t('settings.current_password')}}</p>
|
||||
<input type="password" v-model="changePasswordInputs[0]">
|
||||
</div>
|
||||
<div>
|
||||
<p>{{$t('settings.new_password')}}</p>
|
||||
<input type="password" v-model="changePasswordInputs[1]">
|
||||
</div>
|
||||
<div>
|
||||
<p>{{$t('settings.confirm_new_password')}}</p>
|
||||
<input type="password" v-model="changePasswordInputs[2]">
|
||||
</div>
|
||||
<button class="btn btn-default" @click="changePassword">{{$t('general.submit')}}</button>
|
||||
<p v-if="changedPassword">{{$t('settings.changed_password')}}</p>
|
||||
<p v-else-if="changePasswordError !== false">{{$t('settings.change_password_error')}}</p>
|
||||
<p v-if="changePasswordError">{{changePasswordError}}</p>
|
||||
</div>
|
||||
|
||||
<div class="setting-item">
|
||||
<h2>{{$t('settings.delete_account')}}</h2>
|
||||
<p v-if="!deletingAccount">{{$t('settings.delete_account_description')}}</p>
|
||||
<div v-if="deletingAccount">
|
||||
<p>{{$t('settings.delete_account_instructions')}}</p>
|
||||
<p>{{$t('login.password')}}</p>
|
||||
<input type="password" v-model="deleteAccountConfirmPasswordInput">
|
||||
<button class="btn btn-default" @click="deleteAccount">{{$t('settings.delete_account')}}</button>
|
||||
</div>
|
||||
<p v-if="deleteAccountError !== false">{{$t('settings.delete_account_error')}}</p>
|
||||
<p v-if="deleteAccountError">{{deleteAccountError}}</p>
|
||||
<button class="btn btn-default" v-if="!deletingAccount" @click="confirmDelete">{{$t('general.submit')}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<i class="icon-spin4 animate-spin" v-if="uploading[0]"></i>
|
||||
<button class="btn btn-default" v-else-if="previews[0]" @click="submitAvatar">{{$t('general.submit')}}</button>
|
||||
</div>
|
||||
<div class="setting-item" v-if="activeTab == 'profile'">
|
||||
<h2>{{$t('settings.profile_banner')}}</h2>
|
||||
<p>{{$t('settings.current_profile_banner')}}</p>
|
||||
<img :src="user.cover_photo" class="banner"></img>
|
||||
<p>{{$t('settings.set_new_profile_banner')}}</p>
|
||||
<img class="banner" v-bind:src="previews[1]" v-if="previews[1]">
|
||||
</img>
|
||||
<div>
|
||||
<input type="file" @change="uploadFile(1, $event)" ></input>
|
||||
|
||||
<div :label="$t('settings.data_import_export_tab')" v-if="pleromaBackend">
|
||||
<div class="setting-item">
|
||||
<h2>{{$t('settings.follow_import')}}</h2>
|
||||
<p>{{$t('settings.import_followers_from_a_csv_file')}}</p>
|
||||
<form v-model="followImportForm">
|
||||
<input type="file" ref="followlist" v-on:change="followListChange"></input>
|
||||
</form>
|
||||
<i class=" icon-spin4 animate-spin uploading" v-if="uploading[3]"></i>
|
||||
<button class="btn btn-default" v-else @click="importFollows">{{$t('general.submit')}}</button>
|
||||
<div v-if="followsImported">
|
||||
<i class="icon-cross" @click="dismissImported"></i>
|
||||
<p>{{$t('settings.follows_imported')}}</p>
|
||||
</div>
|
||||
<div v-else-if="followImportError">
|
||||
<i class="icon-cross" @click="dismissImported"></i>
|
||||
<p>{{$t('settings.follow_import_error')}}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-item" v-if="enableFollowsExport">
|
||||
<h2>{{$t('settings.follow_export')}}</h2>
|
||||
<button class="btn btn-default" @click="exportFollows">{{$t('settings.follow_export_button')}}</button>
|
||||
</div>
|
||||
<div class="setting-item" v-else>
|
||||
<h2>{{$t('settings.follow_export_processing')}}</h2>
|
||||
</div>
|
||||
</div>
|
||||
<i class=" icon-spin4 animate-spin uploading" v-if="uploading[1]"></i>
|
||||
<button class="btn btn-default" v-else-if="previews[1]" @click="submitBanner">{{$t('general.submit')}}</button>
|
||||
</div>
|
||||
<div class="setting-item" v-if="activeTab == 'profile'">
|
||||
<h2>{{$t('settings.profile_background')}}</h2>
|
||||
<p>{{$t('settings.set_new_profile_background')}}</p>
|
||||
<img class="bg" v-bind:src="previews[2]" v-if="previews[2]">
|
||||
</img>
|
||||
<div>
|
||||
<input type="file" @change="uploadFile(2, $event)" ></input>
|
||||
</div>
|
||||
<i class=" icon-spin4 animate-spin uploading" v-if="uploading[2]"></i>
|
||||
<button class="btn btn-default" v-else-if="previews[2]" @click="submitBg">{{$t('general.submit')}}</button>
|
||||
</div>
|
||||
<div class="setting-item" v-if="activeTab == 'security'">
|
||||
<h2>{{$t('settings.change_password')}}</h2>
|
||||
<div>
|
||||
<p>{{$t('settings.current_password')}}</p>
|
||||
<input type="password" v-model="changePasswordInputs[0]">
|
||||
</div>
|
||||
<div>
|
||||
<p>{{$t('settings.new_password')}}</p>
|
||||
<input type="password" v-model="changePasswordInputs[1]">
|
||||
</div>
|
||||
<div>
|
||||
<p>{{$t('settings.confirm_new_password')}}</p>
|
||||
<input type="password" v-model="changePasswordInputs[2]">
|
||||
</div>
|
||||
<button class="btn btn-default" @click="changePassword">{{$t('general.submit')}}</button>
|
||||
<p v-if="changedPassword">{{$t('settings.changed_password')}}</p>
|
||||
<p v-else-if="changePasswordError !== false">{{$t('settings.change_password_error')}}</p>
|
||||
<p v-if="changePasswordError">{{changePasswordError}}</p>
|
||||
</div>
|
||||
<div class="setting-item" v-if="pleromaBackend && activeTab == 'data_import_export'">
|
||||
<h2>{{$t('settings.follow_import')}}</h2>
|
||||
<p>{{$t('settings.import_followers_from_a_csv_file')}}</p>
|
||||
<form v-model="followImportForm">
|
||||
<input type="file" ref="followlist" v-on:change="followListChange"></input>
|
||||
</form>
|
||||
<i class=" icon-spin4 animate-spin uploading" v-if="uploading[3]"></i>
|
||||
<button class="btn btn-default" v-else @click="importFollows">{{$t('general.submit')}}</button>
|
||||
<div v-if="followsImported">
|
||||
<i class="icon-cross" @click="dismissImported"></i>
|
||||
<p>{{$t('settings.follows_imported')}}</p>
|
||||
</div>
|
||||
<div v-else-if="followImportError">
|
||||
<i class="icon-cross" @click="dismissImported"></i>
|
||||
<p>{{$t('settings.follow_import_error')}}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-item" v-if="enableFollowsExport && activeTab == 'data_import_export'">
|
||||
<h2>{{$t('settings.follow_export')}}</h2>
|
||||
<button class="btn btn-default" @click="exportFollows">{{$t('settings.follow_export_button')}}</button>
|
||||
</div>
|
||||
<div class="setting-item" v-else-if="activeTab == 'data_import_export'">
|
||||
<h2>{{$t('settings.follow_export_processing')}}</h2>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="setting-item" v-if="activeTab == 'security'">
|
||||
<h2>{{$t('settings.delete_account')}}</h2>
|
||||
<p v-if="!deletingAccount">{{$t('settings.delete_account_description')}}</p>
|
||||
<div v-if="deletingAccount">
|
||||
<p>{{$t('settings.delete_account_instructions')}}</p>
|
||||
<p>{{$t('login.password')}}</p>
|
||||
<input type="password" v-model="deleteAccountConfirmPasswordInput">
|
||||
<button class="btn btn-default" @click="deleteAccount">{{$t('settings.delete_account')}}</button>
|
||||
</div>
|
||||
<p v-if="deleteAccountError !== false">{{$t('settings.delete_account_error')}}</p>
|
||||
<p v-if="deleteAccountError">{{deleteAccountError}}</p>
|
||||
<button class="btn btn-default" v-if="!deletingAccount" @click="confirmDelete">{{$t('general.submit')}}</button>
|
||||
</div>
|
||||
</tab-switcher>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -151,13 +156,4 @@
|
|||
margin: 0.25em;
|
||||
}
|
||||
}
|
||||
|
||||
.tab-switcher {
|
||||
margin: 7px 7px;
|
||||
display: inline-block;
|
||||
|
||||
button {
|
||||
height: 30px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -48,8 +48,8 @@ const de = {
|
|||
settings: 'Einstellungen',
|
||||
theme: 'Farbschema',
|
||||
presets: 'Voreinstellungen',
|
||||
export_theme: 'Aktuelles Theme exportieren',
|
||||
import_theme: 'Gespeichertes Theme laden',
|
||||
export_theme: 'Farbschema speichern',
|
||||
import_theme: 'Farbschema laden',
|
||||
invalid_theme_imported: 'Die ausgewählte Datei ist kein unterstütztes Pleroma-Theme. Keine Änderungen wurden vorgenommen.',
|
||||
theme_help: 'Benutze HTML Farbcodes (#rrggbb) um dein Farbschema anzupassen',
|
||||
radii_help: 'Kantenrundung (in Pixel) der Oberfläche anpassen',
|
||||
|
@ -273,9 +273,11 @@ const en = {
|
|||
load_older: 'Load older statuses',
|
||||
conversation: 'Conversation',
|
||||
collapse: 'Collapse',
|
||||
repeated: 'repeated'
|
||||
repeated: 'repeated',
|
||||
no_retweet_hint: 'Post is marked as followers-only or direct and cannot be repeated'
|
||||
},
|
||||
settings: {
|
||||
general: 'General',
|
||||
user_settings: 'User Settings',
|
||||
name_bio: 'Name & Bio',
|
||||
name: 'Name',
|
||||
|
@ -291,8 +293,8 @@ const en = {
|
|||
settings: 'Settings',
|
||||
theme: 'Theme',
|
||||
presets: 'Presets',
|
||||
export_theme: 'Export current theme',
|
||||
import_theme: 'Load saved theme',
|
||||
export_theme: 'Save preset',
|
||||
import_theme: 'Load preset',
|
||||
theme_help: 'Use hex color codes (#rrggbb) to customize your color theme.',
|
||||
invalid_theme_imported: 'The selected file is not a supported Pleroma theme. No changes to your theme were made.',
|
||||
radii_help: 'Set up interface edge rounding (in pixels)',
|
||||
|
@ -325,9 +327,15 @@ const en = {
|
|||
loop_video: 'Loop videos',
|
||||
loop_video_silent_only: 'Loop only videos without sound (i.e. Mastodon\'s "gifs")',
|
||||
reply_link_preview: 'Enable reply-link preview on mouse hover',
|
||||
replies_in_timeline: 'Replies in timeline',
|
||||
reply_visibility_all: 'Show all replies',
|
||||
reply_visibility_following: 'Only show replies directed at me or users I\'m following',
|
||||
reply_visibility_self: 'Only show replies directed at me',
|
||||
notification_visibility: 'Types of notifications to show',
|
||||
notification_visibility_likes: 'Likes',
|
||||
notification_visibility_mentions: 'Mentions',
|
||||
notification_visibility_repeats: 'Repeats',
|
||||
notification_visibility_follows: 'Follows',
|
||||
follow_import: 'Follow import',
|
||||
import_followers_from_a_csv_file: 'Import follows from a csv file',
|
||||
follows_imported: 'Follows imported! Processing them will take a while.',
|
||||
|
@ -1623,9 +1631,11 @@ const ru = {
|
|||
load_older: 'Загрузить старые статусы',
|
||||
conversation: 'Разговор',
|
||||
collapse: 'Свернуть',
|
||||
repeated: 'повторил(а)'
|
||||
repeated: 'повторил(а)',
|
||||
no_retweet_hint: 'Пост помечен как "только для подписчиков" или "личное" и поэтому не может быть повторён'
|
||||
},
|
||||
settings: {
|
||||
general: 'Общие',
|
||||
user_settings: 'Настройки пользователя',
|
||||
name_bio: 'Имя и описание',
|
||||
name: 'Имя',
|
||||
|
@ -1640,11 +1650,11 @@ const ru = {
|
|||
set_new_profile_background: 'Загрузить новый фон профиля',
|
||||
settings: 'Настройки',
|
||||
theme: 'Тема',
|
||||
export_theme: 'Экспортировать текущую тему',
|
||||
import_theme: 'Загрузить сохранённую тему',
|
||||
export_theme: 'Сохранить Тему',
|
||||
import_theme: 'Загрузить Тему',
|
||||
presets: 'Пресеты',
|
||||
theme_help: 'Используйте шестнадцатеричные коды цветов (#rrggbb) для настройки темы.',
|
||||
radii_help: 'Округление краёв элементов интерфейса (в пикселях)',
|
||||
radii_help: 'Скругление углов элементов интерфейса (в пикселях)',
|
||||
background: 'Фон',
|
||||
foreground: 'Передний план',
|
||||
text: 'Текст',
|
||||
|
@ -1673,6 +1683,15 @@ const ru = {
|
|||
loop_video: 'Зациливать видео',
|
||||
loop_video_silent_only: 'Зацикливать только беззвучные видео (т.е. "гифки" с Mastodon)',
|
||||
reply_link_preview: 'Включить предварительный просмотр ответа при наведении мыши',
|
||||
replies_in_timeline: 'Ответы в ленте',
|
||||
reply_visibility_all: 'Показывать все ответы',
|
||||
reply_visibility_following: 'Показывать только ответы мне и тех на кого я подписан',
|
||||
reply_visibility_self: 'Показывать только ответы мне',
|
||||
notification_visibility: 'Показывать уведомления',
|
||||
notification_visibility_likes: 'Лайки',
|
||||
notification_visibility_mentions: 'Упоминания',
|
||||
notification_visibility_repeats: 'Повторы',
|
||||
notification_visibility_follows: 'Подписки',
|
||||
follow_import: 'Импортировать читаемых',
|
||||
import_followers_from_a_csv_file: 'Импортировать читаемых из файла .csv',
|
||||
follows_imported: 'Список читаемых импортирован. Обработка займёт некоторое время..',
|
||||
|
@ -1725,7 +1744,18 @@ const ru = {
|
|||
},
|
||||
post_status: {
|
||||
posting: 'Отправляется',
|
||||
default: 'Что нового?'
|
||||
content_warning: 'Тема (не обязательно)',
|
||||
default: 'Что нового?',
|
||||
account_not_locked_warning: 'Ваш аккаунт не {0}. Кто угодно может зафоловить вас чтобы прочитать посты только для подписчиков',
|
||||
account_not_locked_warning_link: 'залочен',
|
||||
direct_warning: 'Этот пост будет видет только упомянутым пользователям',
|
||||
attachments_sensitive: 'Вложения содержат чувствительный контент',
|
||||
scope: {
|
||||
public: 'Публичный - этот пост виден всем',
|
||||
unlisted: 'Непубличный - этот пост не виден на публичных лентах',
|
||||
private: 'Для подписчиков - этот пост видят только подписчики',
|
||||
direct: 'Личное - этот пост видят только те кто в нём упомянут'
|
||||
}
|
||||
},
|
||||
finder: {
|
||||
find_user: 'Найти пользователя',
|
||||
|
|
31
src/main.js
31
src/main.js
|
@ -50,6 +50,7 @@ const persistedStateOptions = {
|
|||
'config.hideAttachmentsInConv',
|
||||
'config.hideNsfw',
|
||||
'config.replyVisibility',
|
||||
'config.notificationVisibility',
|
||||
'config.autoLoad',
|
||||
'config.hoverPreview',
|
||||
'config.streaming',
|
||||
|
@ -102,23 +103,29 @@ window.fetch('/api/statusnet/config.json')
|
|||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
var staticConfig = data
|
||||
// This takes static config and overrides properties that are present in apiConfig
|
||||
var config = Object.assign({}, staticConfig, apiConfig)
|
||||
|
||||
var theme = (apiConfig.theme || staticConfig.theme)
|
||||
var background = (apiConfig.background || staticConfig.background)
|
||||
var logo = (apiConfig.logo || staticConfig.logo)
|
||||
var redirectRootNoLogin = (apiConfig.redirectRootNoLogin || staticConfig.redirectRootNoLogin)
|
||||
var redirectRootLogin = (apiConfig.redirectRootLogin || staticConfig.redirectRootLogin)
|
||||
var chatDisabled = (apiConfig.chatDisabled || staticConfig.chatDisabled)
|
||||
var showWhoToFollowPanel = (apiConfig.showWhoToFollowPanel || staticConfig.showWhoToFollowPanel)
|
||||
var whoToFollowProvider = (apiConfig.whoToFollowProvider || staticConfig.whoToFollowProvider)
|
||||
var whoToFollowLink = (apiConfig.whoToFollowLink || staticConfig.whoToFollowLink)
|
||||
var showInstanceSpecificPanel = (apiConfig.showInstanceSpecificPanel || staticConfig.showInstanceSpecificPanel)
|
||||
var scopeOptionsEnabled = (apiConfig.scopeOptionsEnabled || staticConfig.scopeOptionsEnabled)
|
||||
var collapseMessageWithSubject = (apiConfig.collapseMessageWithSubject || staticConfig.collapseMessageWithSubject)
|
||||
var theme = (config.theme)
|
||||
var background = (config.background)
|
||||
var logo = (config.logo)
|
||||
var logoMask = (typeof config.logoMask === 'undefined' ? true : config.logoMask)
|
||||
var logoMargin = (typeof config.logoMargin === 'undefined' ? 0 : config.logoMargin)
|
||||
var redirectRootNoLogin = (config.redirectRootNoLogin)
|
||||
var redirectRootLogin = (config.redirectRootLogin)
|
||||
var chatDisabled = (config.chatDisabled)
|
||||
var showWhoToFollowPanel = (config.showWhoToFollowPanel)
|
||||
var whoToFollowProvider = (config.whoToFollowProvider)
|
||||
var whoToFollowLink = (config.whoToFollowLink)
|
||||
var showInstanceSpecificPanel = (config.showInstanceSpecificPanel)
|
||||
var scopeOptionsEnabled = (config.scopeOptionsEnabled)
|
||||
var collapseMessageWithSubject = (config.collapseMessageWithSubject)
|
||||
|
||||
store.dispatch('setOption', { name: 'theme', value: theme })
|
||||
store.dispatch('setOption', { name: 'background', value: background })
|
||||
store.dispatch('setOption', { name: 'logo', value: logo })
|
||||
store.dispatch('setOption', { name: 'logoMask', value: logoMask })
|
||||
store.dispatch('setOption', { name: 'logoMargin', value: logoMargin })
|
||||
store.dispatch('setOption', { name: 'showWhoToFollowPanel', value: showWhoToFollowPanel })
|
||||
store.dispatch('setOption', { name: 'whoToFollowProvider', value: whoToFollowProvider })
|
||||
store.dispatch('setOption', { name: 'whoToFollowLink', value: whoToFollowLink })
|
||||
|
|
|
@ -18,6 +18,12 @@ const defaultState = {
|
|||
pauseOnUnfocused: true,
|
||||
stopGifs: false,
|
||||
replyVisibility: 'all',
|
||||
notificationVisibility: {
|
||||
follows: true,
|
||||
mentions: true,
|
||||
likes: true,
|
||||
repeats: true
|
||||
},
|
||||
muteWords: [],
|
||||
highlight: {},
|
||||
interfaceLanguage: browserLocale
|
||||
|
|
|
@ -68,6 +68,15 @@ export const prepareStatus = (status) => {
|
|||
return status
|
||||
}
|
||||
|
||||
const visibleNotificationTypes = (rootState) => {
|
||||
return [
|
||||
rootState.config.notificationVisibility.likes && 'like',
|
||||
rootState.config.notificationVisibility.mentions && 'mention',
|
||||
rootState.config.notificationVisibility.repeats && 'repeat',
|
||||
rootState.config.notificationVisibility.follows && 'follow'
|
||||
].filter(_ => _)
|
||||
}
|
||||
|
||||
export const statusType = (status) => {
|
||||
if (status.is_post_verb) {
|
||||
return 'status'
|
||||
|
@ -86,8 +95,7 @@ export const statusType = (status) => {
|
|||
return 'deletion'
|
||||
}
|
||||
|
||||
// TODO change to status.activity_type === 'follow' when gs supports it
|
||||
if (status.text.match(/started following/)) {
|
||||
if (status.text.match(/started following/) || status.activity_type === 'follow') {
|
||||
return 'follow'
|
||||
}
|
||||
|
||||
|
@ -187,11 +195,11 @@ const addNewStatuses = (state, { statuses, showImmediately = false, timeline, us
|
|||
const favoriteStatus = (favorite, counter) => {
|
||||
const status = find(allStatuses, { id: toInteger(favorite.in_reply_to_status_id) })
|
||||
if (status) {
|
||||
status.fave_num += 1
|
||||
|
||||
// This is our favorite, so the relevant bit.
|
||||
if (favorite.user.id === user.id) {
|
||||
status.favorited = true
|
||||
} else {
|
||||
status.fave_num += 1
|
||||
}
|
||||
}
|
||||
return status
|
||||
|
@ -225,6 +233,7 @@ const addNewStatuses = (state, { statuses, showImmediately = false, timeline, us
|
|||
},
|
||||
'favorite': (favorite) => {
|
||||
// Only update if this is a new favorite.
|
||||
// Ignore our own favorites because we get info about likes as response to like request
|
||||
if (!state.favorites.has(favorite.id)) {
|
||||
state.favorites.add(favorite.id)
|
||||
favoriteStatus(favorite)
|
||||
|
@ -268,7 +277,7 @@ const addNewStatuses = (state, { statuses, showImmediately = false, timeline, us
|
|||
}
|
||||
}
|
||||
|
||||
const addNewNotifications = (state, { dispatch, notifications, older }) => {
|
||||
const addNewNotifications = (state, { dispatch, notifications, older, visibleNotificationTypes }) => {
|
||||
const allStatuses = state.allStatuses
|
||||
const allStatusesObject = state.allStatusesObject
|
||||
each(notifications, (notification) => {
|
||||
|
@ -317,7 +326,7 @@ const addNewNotifications = (state, { dispatch, notifications, older }) => {
|
|||
result.image = action.attachments[0].url
|
||||
}
|
||||
|
||||
if (fresh && !state.notifications.desktopNotificationSilence) {
|
||||
if (fresh && !state.notifications.desktopNotificationSilence && visibleNotificationTypes.includes(notification.ntype)) {
|
||||
let notification = new window.Notification(title, result)
|
||||
// Chrome is known for not closing notifications automatically
|
||||
// according to MDN, anyway.
|
||||
|
@ -347,6 +356,11 @@ export const mutations = {
|
|||
const newStatus = state.allStatusesObject[status.id]
|
||||
newStatus.favorited = value
|
||||
},
|
||||
setFavoritedConfirm (state, { status }) {
|
||||
const newStatus = state.allStatusesObject[status.id]
|
||||
newStatus.favorited = status.favorited
|
||||
newStatus.fave_num = status.fave_num
|
||||
},
|
||||
setRetweeted (state, { status, value }) {
|
||||
const newStatus = state.allStatusesObject[status.id]
|
||||
newStatus.repeated = value
|
||||
|
@ -399,7 +413,7 @@ const statuses = {
|
|||
commit('addNewStatuses', { statuses, showImmediately, timeline, noIdUpdate, user: rootState.users.currentUser })
|
||||
},
|
||||
addNewNotifications ({ rootState, commit, dispatch }, { notifications, older }) {
|
||||
commit('addNewNotifications', { dispatch, notifications, older })
|
||||
commit('addNewNotifications', { visibleNotificationTypes: visibleNotificationTypes(rootState), dispatch, notifications, older })
|
||||
},
|
||||
setError ({ rootState, commit }, { value }) {
|
||||
commit('setError', { value })
|
||||
|
@ -424,11 +438,31 @@ const statuses = {
|
|||
// Optimistic favoriting...
|
||||
commit('setFavorited', { status, value: true })
|
||||
apiService.favorite({ id: status.id, credentials: rootState.users.currentUser.credentials })
|
||||
.then(response => {
|
||||
if (response.ok) {
|
||||
return response.json()
|
||||
} else {
|
||||
return {}
|
||||
}
|
||||
})
|
||||
.then(status => {
|
||||
commit('setFavoritedConfirm', { status })
|
||||
})
|
||||
},
|
||||
unfavorite ({ rootState, commit }, status) {
|
||||
// Optimistic favoriting...
|
||||
commit('setFavorited', { status, value: false })
|
||||
apiService.unfavorite({ id: status.id, credentials: rootState.users.currentUser.credentials })
|
||||
.then(response => {
|
||||
if (response.ok) {
|
||||
return response.json()
|
||||
} else {
|
||||
return {}
|
||||
}
|
||||
})
|
||||
.then(status => {
|
||||
commit('setFavoritedConfirm', { status })
|
||||
})
|
||||
},
|
||||
retweet ({ rootState, commit }, status) {
|
||||
// Optimistic retweeting...
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
"theme": "pleroma-dark",
|
||||
"background": "/static/aurora_borealis.jpg",
|
||||
"logo": "/static/logo.png",
|
||||
"logoMask": true,
|
||||
"logoMargin": ".1em",
|
||||
"redirectRootNoLogin": "/main/all",
|
||||
"redirectRootLogin": "/main/friends",
|
||||
"chatDisabled": false,
|
||||
|
|
|
@ -247,7 +247,7 @@ describe('The Statuses module', () => {
|
|||
in_reply_to_status_id: '1', // The API uses strings here...
|
||||
uri: 'tag:shitposter.club,2016-08-21:fave:3895:note:773501:2016-08-21T16:52:15+00:00',
|
||||
text: 'a favorited something by b',
|
||||
user: {}
|
||||
user: { id: 99 }
|
||||
}
|
||||
|
||||
mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' })
|
||||
|
@ -264,7 +264,7 @@ describe('The Statuses module', () => {
|
|||
expect(state.timelines.public.visibleStatuses[0].fave_num).to.eql(1)
|
||||
expect(state.timelines.public.maxId).to.eq(favorite.id)
|
||||
|
||||
// If something is favorited by the current user, it also sets the 'favorited' property
|
||||
// If something is favorited by the current user, it also sets the 'favorited' property but does not increment counter to avoid over-counting. Counter is incremented (updated, really) via response to the favorite request.
|
||||
const user = {
|
||||
id: 1
|
||||
}
|
||||
|
@ -281,7 +281,7 @@ describe('The Statuses module', () => {
|
|||
mutations.addNewStatuses(state, { statuses: [ownFavorite], showImmediately: true, timeline: 'public', user })
|
||||
|
||||
expect(state.timelines.public.visibleStatuses.length).to.eql(1)
|
||||
expect(state.timelines.public.visibleStatuses[0].fave_num).to.eql(2)
|
||||
expect(state.timelines.public.visibleStatuses[0].fave_num).to.eql(1)
|
||||
expect(state.timelines.public.visibleStatuses[0].favorited).to.eql(true)
|
||||
})
|
||||
|
||||
|
|
111
yarn.lock
111
yarn.lock
|
@ -434,6 +434,10 @@ babel-helper-replace-supers@^6.24.1:
|
|||
babel-traverse "^6.24.1"
|
||||
babel-types "^6.24.1"
|
||||
|
||||
babel-helper-vue-jsx-merge-props@^2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.3.tgz#22aebd3b33902328e513293a8e4992b384f9f1b6"
|
||||
|
||||
babel-helpers@^6.24.1:
|
||||
version "6.24.1"
|
||||
resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2"
|
||||
|
@ -500,6 +504,10 @@ babel-plugin-syntax-exponentiation-operator@^6.8.0:
|
|||
version "6.13.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de"
|
||||
|
||||
babel-plugin-syntax-jsx@^6.18.0:
|
||||
version "6.18.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946"
|
||||
|
||||
babel-plugin-syntax-object-rest-spread@^6.8.0:
|
||||
version "6.13.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5"
|
||||
|
@ -516,7 +524,7 @@ babel-plugin-transform-async-generator-functions@^6.24.1:
|
|||
babel-plugin-syntax-async-generators "^6.5.0"
|
||||
babel-runtime "^6.22.0"
|
||||
|
||||
babel-plugin-transform-async-to-generator@^6.24.1:
|
||||
babel-plugin-transform-async-to-generator@^6.22.0, babel-plugin-transform-async-to-generator@^6.24.1:
|
||||
version "6.24.1"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761"
|
||||
dependencies:
|
||||
|
@ -555,7 +563,7 @@ babel-plugin-transform-es2015-block-scoped-functions@^6.22.0:
|
|||
dependencies:
|
||||
babel-runtime "^6.22.0"
|
||||
|
||||
babel-plugin-transform-es2015-block-scoping@^6.24.1:
|
||||
babel-plugin-transform-es2015-block-scoping@^6.23.0, babel-plugin-transform-es2015-block-scoping@^6.24.1:
|
||||
version "6.26.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f"
|
||||
dependencies:
|
||||
|
@ -565,7 +573,7 @@ babel-plugin-transform-es2015-block-scoping@^6.24.1:
|
|||
babel-types "^6.26.0"
|
||||
lodash "^4.17.4"
|
||||
|
||||
babel-plugin-transform-es2015-classes@^6.24.1:
|
||||
babel-plugin-transform-es2015-classes@^6.23.0, babel-plugin-transform-es2015-classes@^6.24.1:
|
||||
version "6.24.1"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db"
|
||||
dependencies:
|
||||
|
@ -579,33 +587,33 @@ babel-plugin-transform-es2015-classes@^6.24.1:
|
|||
babel-traverse "^6.24.1"
|
||||
babel-types "^6.24.1"
|
||||
|
||||
babel-plugin-transform-es2015-computed-properties@^6.24.1:
|
||||
babel-plugin-transform-es2015-computed-properties@^6.22.0, babel-plugin-transform-es2015-computed-properties@^6.24.1:
|
||||
version "6.24.1"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3"
|
||||
dependencies:
|
||||
babel-runtime "^6.22.0"
|
||||
babel-template "^6.24.1"
|
||||
|
||||
babel-plugin-transform-es2015-destructuring@^6.22.0:
|
||||
babel-plugin-transform-es2015-destructuring@^6.22.0, babel-plugin-transform-es2015-destructuring@^6.23.0:
|
||||
version "6.23.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d"
|
||||
dependencies:
|
||||
babel-runtime "^6.22.0"
|
||||
|
||||
babel-plugin-transform-es2015-duplicate-keys@^6.24.1:
|
||||
babel-plugin-transform-es2015-duplicate-keys@^6.22.0, babel-plugin-transform-es2015-duplicate-keys@^6.24.1:
|
||||
version "6.24.1"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e"
|
||||
dependencies:
|
||||
babel-runtime "^6.22.0"
|
||||
babel-types "^6.24.1"
|
||||
|
||||
babel-plugin-transform-es2015-for-of@^6.22.0:
|
||||
babel-plugin-transform-es2015-for-of@^6.22.0, babel-plugin-transform-es2015-for-of@^6.23.0:
|
||||
version "6.23.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691"
|
||||
dependencies:
|
||||
babel-runtime "^6.22.0"
|
||||
|
||||
babel-plugin-transform-es2015-function-name@^6.24.1:
|
||||
babel-plugin-transform-es2015-function-name@^6.22.0, babel-plugin-transform-es2015-function-name@^6.24.1:
|
||||
version "6.24.1"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b"
|
||||
dependencies:
|
||||
|
@ -619,7 +627,7 @@ babel-plugin-transform-es2015-literals@^6.22.0:
|
|||
dependencies:
|
||||
babel-runtime "^6.22.0"
|
||||
|
||||
babel-plugin-transform-es2015-modules-amd@^6.24.1:
|
||||
babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1:
|
||||
version "6.24.1"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154"
|
||||
dependencies:
|
||||
|
@ -627,6 +635,15 @@ babel-plugin-transform-es2015-modules-amd@^6.24.1:
|
|||
babel-runtime "^6.22.0"
|
||||
babel-template "^6.24.1"
|
||||
|
||||
babel-plugin-transform-es2015-modules-commonjs@^6.23.0:
|
||||
version "6.26.2"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3"
|
||||
dependencies:
|
||||
babel-plugin-transform-strict-mode "^6.24.1"
|
||||
babel-runtime "^6.26.0"
|
||||
babel-template "^6.26.0"
|
||||
babel-types "^6.26.0"
|
||||
|
||||
babel-plugin-transform-es2015-modules-commonjs@^6.24.1:
|
||||
version "6.26.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz#0d8394029b7dc6abe1a97ef181e00758dd2e5d8a"
|
||||
|
@ -636,7 +653,7 @@ babel-plugin-transform-es2015-modules-commonjs@^6.24.1:
|
|||
babel-template "^6.26.0"
|
||||
babel-types "^6.26.0"
|
||||
|
||||
babel-plugin-transform-es2015-modules-systemjs@^6.24.1:
|
||||
babel-plugin-transform-es2015-modules-systemjs@^6.23.0, babel-plugin-transform-es2015-modules-systemjs@^6.24.1:
|
||||
version "6.24.1"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23"
|
||||
dependencies:
|
||||
|
@ -644,7 +661,7 @@ babel-plugin-transform-es2015-modules-systemjs@^6.24.1:
|
|||
babel-runtime "^6.22.0"
|
||||
babel-template "^6.24.1"
|
||||
|
||||
babel-plugin-transform-es2015-modules-umd@^6.24.1:
|
||||
babel-plugin-transform-es2015-modules-umd@^6.23.0, babel-plugin-transform-es2015-modules-umd@^6.24.1:
|
||||
version "6.24.1"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468"
|
||||
dependencies:
|
||||
|
@ -652,14 +669,14 @@ babel-plugin-transform-es2015-modules-umd@^6.24.1:
|
|||
babel-runtime "^6.22.0"
|
||||
babel-template "^6.24.1"
|
||||
|
||||
babel-plugin-transform-es2015-object-super@^6.24.1:
|
||||
babel-plugin-transform-es2015-object-super@^6.22.0, babel-plugin-transform-es2015-object-super@^6.24.1:
|
||||
version "6.24.1"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d"
|
||||
dependencies:
|
||||
babel-helper-replace-supers "^6.24.1"
|
||||
babel-runtime "^6.22.0"
|
||||
|
||||
babel-plugin-transform-es2015-parameters@^6.24.1:
|
||||
babel-plugin-transform-es2015-parameters@^6.23.0, babel-plugin-transform-es2015-parameters@^6.24.1:
|
||||
version "6.24.1"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b"
|
||||
dependencies:
|
||||
|
@ -670,7 +687,7 @@ babel-plugin-transform-es2015-parameters@^6.24.1:
|
|||
babel-traverse "^6.24.1"
|
||||
babel-types "^6.24.1"
|
||||
|
||||
babel-plugin-transform-es2015-shorthand-properties@^6.24.1:
|
||||
babel-plugin-transform-es2015-shorthand-properties@^6.22.0, babel-plugin-transform-es2015-shorthand-properties@^6.24.1:
|
||||
version "6.24.1"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0"
|
||||
dependencies:
|
||||
|
@ -683,7 +700,7 @@ babel-plugin-transform-es2015-spread@^6.22.0:
|
|||
dependencies:
|
||||
babel-runtime "^6.22.0"
|
||||
|
||||
babel-plugin-transform-es2015-sticky-regex@^6.24.1:
|
||||
babel-plugin-transform-es2015-sticky-regex@^6.22.0, babel-plugin-transform-es2015-sticky-regex@^6.24.1:
|
||||
version "6.24.1"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc"
|
||||
dependencies:
|
||||
|
@ -697,13 +714,13 @@ babel-plugin-transform-es2015-template-literals@^6.22.0:
|
|||
dependencies:
|
||||
babel-runtime "^6.22.0"
|
||||
|
||||
babel-plugin-transform-es2015-typeof-symbol@^6.22.0:
|
||||
babel-plugin-transform-es2015-typeof-symbol@^6.22.0, babel-plugin-transform-es2015-typeof-symbol@^6.23.0:
|
||||
version "6.23.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372"
|
||||
dependencies:
|
||||
babel-runtime "^6.22.0"
|
||||
|
||||
babel-plugin-transform-es2015-unicode-regex@^6.24.1:
|
||||
babel-plugin-transform-es2015-unicode-regex@^6.22.0, babel-plugin-transform-es2015-unicode-regex@^6.24.1:
|
||||
version "6.24.1"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9"
|
||||
dependencies:
|
||||
|
@ -711,7 +728,7 @@ babel-plugin-transform-es2015-unicode-regex@^6.24.1:
|
|||
babel-runtime "^6.22.0"
|
||||
regexpu-core "^2.0.0"
|
||||
|
||||
babel-plugin-transform-exponentiation-operator@^6.24.1:
|
||||
babel-plugin-transform-exponentiation-operator@^6.22.0, babel-plugin-transform-exponentiation-operator@^6.24.1:
|
||||
version "6.24.1"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e"
|
||||
dependencies:
|
||||
|
@ -726,7 +743,7 @@ babel-plugin-transform-object-rest-spread@^6.22.0:
|
|||
babel-plugin-syntax-object-rest-spread "^6.8.0"
|
||||
babel-runtime "^6.26.0"
|
||||
|
||||
babel-plugin-transform-regenerator@^6.24.1:
|
||||
babel-plugin-transform-regenerator@^6.22.0, babel-plugin-transform-regenerator@^6.24.1:
|
||||
version "6.26.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f"
|
||||
dependencies:
|
||||
|
@ -745,6 +762,47 @@ babel-plugin-transform-strict-mode@^6.24.1:
|
|||
babel-runtime "^6.22.0"
|
||||
babel-types "^6.24.1"
|
||||
|
||||
babel-plugin-transform-vue-jsx@3:
|
||||
version "3.7.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-vue-jsx/-/babel-plugin-transform-vue-jsx-3.7.0.tgz#d40492e6692a36b594f7e9a1928f43e969740960"
|
||||
dependencies:
|
||||
esutils "^2.0.2"
|
||||
|
||||
babel-preset-env@^1.7.0:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.7.0.tgz#dea79fa4ebeb883cd35dab07e260c1c9c04df77a"
|
||||
dependencies:
|
||||
babel-plugin-check-es2015-constants "^6.22.0"
|
||||
babel-plugin-syntax-trailing-function-commas "^6.22.0"
|
||||
babel-plugin-transform-async-to-generator "^6.22.0"
|
||||
babel-plugin-transform-es2015-arrow-functions "^6.22.0"
|
||||
babel-plugin-transform-es2015-block-scoped-functions "^6.22.0"
|
||||
babel-plugin-transform-es2015-block-scoping "^6.23.0"
|
||||
babel-plugin-transform-es2015-classes "^6.23.0"
|
||||
babel-plugin-transform-es2015-computed-properties "^6.22.0"
|
||||
babel-plugin-transform-es2015-destructuring "^6.23.0"
|
||||
babel-plugin-transform-es2015-duplicate-keys "^6.22.0"
|
||||
babel-plugin-transform-es2015-for-of "^6.23.0"
|
||||
babel-plugin-transform-es2015-function-name "^6.22.0"
|
||||
babel-plugin-transform-es2015-literals "^6.22.0"
|
||||
babel-plugin-transform-es2015-modules-amd "^6.22.0"
|
||||
babel-plugin-transform-es2015-modules-commonjs "^6.23.0"
|
||||
babel-plugin-transform-es2015-modules-systemjs "^6.23.0"
|
||||
babel-plugin-transform-es2015-modules-umd "^6.23.0"
|
||||
babel-plugin-transform-es2015-object-super "^6.22.0"
|
||||
babel-plugin-transform-es2015-parameters "^6.23.0"
|
||||
babel-plugin-transform-es2015-shorthand-properties "^6.22.0"
|
||||
babel-plugin-transform-es2015-spread "^6.22.0"
|
||||
babel-plugin-transform-es2015-sticky-regex "^6.22.0"
|
||||
babel-plugin-transform-es2015-template-literals "^6.22.0"
|
||||
babel-plugin-transform-es2015-typeof-symbol "^6.23.0"
|
||||
babel-plugin-transform-es2015-unicode-regex "^6.22.0"
|
||||
babel-plugin-transform-exponentiation-operator "^6.22.0"
|
||||
babel-plugin-transform-regenerator "^6.22.0"
|
||||
browserslist "^3.2.6"
|
||||
invariant "^2.2.2"
|
||||
semver "^5.3.0"
|
||||
|
||||
babel-preset-es2015@^6.0.0:
|
||||
version "6.24.1"
|
||||
resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz#d44050d6bc2c9feea702aaf38d727a0210538939"
|
||||
|
@ -996,6 +1054,13 @@ browserslist@^1.3.6, browserslist@^1.5.2, browserslist@^1.7.6:
|
|||
caniuse-db "^1.0.30000639"
|
||||
electron-to-chromium "^1.2.7"
|
||||
|
||||
browserslist@^3.2.6:
|
||||
version "3.2.8"
|
||||
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-3.2.8.tgz#b0005361d6471f0f5952797a76fc985f1f978fc6"
|
||||
dependencies:
|
||||
caniuse-lite "^1.0.30000844"
|
||||
electron-to-chromium "^1.3.47"
|
||||
|
||||
buffer@^4.9.0:
|
||||
version "4.9.1"
|
||||
resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298"
|
||||
|
@ -1069,6 +1134,10 @@ caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639:
|
|||
version "1.0.30000801"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000801.tgz#a1d49def94c4e5aca5ccf1d58812e4668fac19d4"
|
||||
|
||||
caniuse-lite@^1.0.30000844:
|
||||
version "1.0.30000878"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000878.tgz#c644c39588dd42d3498e952234c372e5a40a4123"
|
||||
|
||||
caseless@~0.12.0:
|
||||
version "0.12.0"
|
||||
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
|
||||
|
@ -1789,6 +1858,10 @@ electron-to-chromium@^1.2.7:
|
|||
version "1.3.32"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.32.tgz#11d0684c0840e003c4be8928f8ac5f35dbc2b4e6"
|
||||
|
||||
electron-to-chromium@^1.3.47:
|
||||
version "1.3.61"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.61.tgz#a8ac295b28d0f03d85e37326fd16b6b6b17a1795"
|
||||
|
||||
emojis-list@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389"
|
||||
|
|
Loading…
Reference in a new issue