Merge remote-tracking branch 'upstream/develop' into shigusegubu
* upstream/develop: Rename expandCW to collapseMessageWithSubject. fix indent Add support for configurable CW clickthrough. Merge upstream fix lint issues allow default visibility scope to be configured Add validation of the imported theme and the corresponding warning message Unify button styles and use min-width Add German localization for theme import/export Add theme import feature Refactor theme settings state initialization Add theme export feature
This commit is contained in:
commit
e246a3beee
16 changed files with 235 additions and 80 deletions
22
src/App.scss
22
src/App.scss
|
@ -63,6 +63,8 @@ button{
|
||||||
box-shadow: 0px 0px 2px black;
|
box-shadow: 0px 0px 2px black;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
|
min-width: 10em;
|
||||||
|
min-height: 2em;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
box-shadow: 0px 0px 4px rgba(255, 255, 255, 0.3);
|
box-shadow: 0px 0px 4px rgba(255, 255, 255, 0.3);
|
||||||
|
@ -441,3 +443,23 @@ nav {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
padding-right: 20px;
|
padding-right: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.visibility-tray {
|
||||||
|
font-size: 1.2em;
|
||||||
|
padding: 3px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
.selected {
|
||||||
|
color: $fallback--lightFg;
|
||||||
|
color: var(--lightFg, $fallback--lightFg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.visibility-notice {
|
||||||
|
padding: .5em;
|
||||||
|
border: 1px solid $fallback--faint;
|
||||||
|
border: 1px solid var(--faint, $fallback--faint);
|
||||||
|
border-radius: $fallback--inputRadius;
|
||||||
|
border-radius: var(--inputRadius, $fallback--inputRadius);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,11 +34,6 @@
|
||||||
@import '../../_variables.scss';
|
@import '../../_variables.scss';
|
||||||
|
|
||||||
.login-form {
|
.login-form {
|
||||||
.btn {
|
|
||||||
min-height: 28px;
|
|
||||||
width: 10em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.error {
|
.error {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ const PostStatusForm = {
|
||||||
newStatus: {
|
newStatus: {
|
||||||
status: statusText,
|
status: statusText,
|
||||||
files: [],
|
files: [],
|
||||||
visibility: this.messageScope || 'public'
|
visibility: this.messageScope || this.$store.state.users.currentUser.default_scope
|
||||||
},
|
},
|
||||||
caret: 0
|
caret: 0
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,35 +101,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.post-status-form .visibility-tray {
|
|
||||||
font-size: 1.2em;
|
|
||||||
padding: 3px;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
.selected {
|
|
||||||
color: $fallback--lightFg;
|
|
||||||
color: var(--lightFg, $fallback--lightFg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.visibility-notice {
|
|
||||||
padding: .5em;
|
|
||||||
border: 1px solid $fallback--faint;
|
|
||||||
border: 1px solid var(--faint, $fallback--faint);
|
|
||||||
border-radius: $fallback--inputRadius;
|
|
||||||
border-radius: var(--inputRadius, $fallback--inputRadius);
|
|
||||||
}
|
|
||||||
|
|
||||||
.post-status-form, .login {
|
.post-status-form, .login {
|
||||||
.form-bottom {
|
.form-bottom {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
|
|
||||||
button {
|
|
||||||
width: 10em;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
p {
|
||||||
margin: 0.35em;
|
margin: 0.35em;
|
||||||
padding: 0.35em;
|
padding: 0.35em;
|
||||||
|
|
|
@ -15,6 +15,7 @@ const settings = {
|
||||||
streamingLocal: this.$store.state.config.streaming,
|
streamingLocal: this.$store.state.config.streaming,
|
||||||
pauseOnUnfocusedLocal: this.$store.state.config.pauseOnUnfocused,
|
pauseOnUnfocusedLocal: this.$store.state.config.pauseOnUnfocused,
|
||||||
hoverPreviewLocal: this.$store.state.config.hoverPreview,
|
hoverPreviewLocal: this.$store.state.config.hoverPreview,
|
||||||
|
collapseMessageWithSubjectLocal: this.$store.state.config.collapseMessageWithSubject,
|
||||||
stopGifs: this.$store.state.config.stopGifs,
|
stopGifs: this.$store.state.config.stopGifs,
|
||||||
loopSilentAvailable:
|
loopSilentAvailable:
|
||||||
// Firefox
|
// Firefox
|
||||||
|
@ -65,6 +66,9 @@ const settings = {
|
||||||
value = filter(value.split('\n'), (word) => trim(word).length > 0)
|
value = filter(value.split('\n'), (word) => trim(word).length > 0)
|
||||||
this.$store.dispatch('setOption', { name: 'muteWords', value })
|
this.$store.dispatch('setOption', { name: 'muteWords', value })
|
||||||
},
|
},
|
||||||
|
collapseMessageWithSubjectLocal (value) {
|
||||||
|
this.$store.dispatch('setOption', { name: 'collapseMessageWithSubject', value })
|
||||||
|
},
|
||||||
stopGifs (value) {
|
stopGifs (value) {
|
||||||
this.$store.dispatch('setOption', { name: 'stopGifs', value })
|
this.$store.dispatch('setOption', { name: 'stopGifs', value })
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,10 @@
|
||||||
<div class="setting-item">
|
<div class="setting-item">
|
||||||
<h2>{{$t('nav.timeline')}}</h2>
|
<h2>{{$t('nav.timeline')}}</h2>
|
||||||
<ul class="setting-list">
|
<ul class="setting-list">
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="collapseMessageWithSubject" v-model="collapseMessageWithSubjectLocal">
|
||||||
|
<label for="collapseMessageWithSubject">{{$t('settings.collapse_subject')}}</label>
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<input type="checkbox" id="streaming" v-model="streamingLocal">
|
<input type="checkbox" id="streaming" v-model="streamingLocal">
|
||||||
<label for="streaming">{{$t('settings.streaming')}}</label>
|
<label for="streaming">{{$t('settings.streaming')}}</label>
|
||||||
|
@ -113,8 +117,6 @@
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
margin-top: 1em;
|
margin-top: 1em;
|
||||||
min-height: 28px;
|
|
||||||
width: 10em;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.setting-list {
|
.setting-list {
|
||||||
|
|
|
@ -22,15 +22,18 @@ const Status = {
|
||||||
'noHeading',
|
'noHeading',
|
||||||
'inlineExpanded'
|
'inlineExpanded'
|
||||||
],
|
],
|
||||||
data: () => ({
|
data () {
|
||||||
replying: false,
|
return {
|
||||||
expanded: false,
|
replying: false,
|
||||||
unmuted: false,
|
expanded: false,
|
||||||
userExpanded: false,
|
unmuted: false,
|
||||||
preview: null,
|
userExpanded: false,
|
||||||
showPreview: false,
|
preview: null,
|
||||||
showingTall: false
|
showPreview: false,
|
||||||
}),
|
showingTall: false,
|
||||||
|
expandingSubject: !this.$store.state.config.collapseMessageWithSubject
|
||||||
|
}
|
||||||
|
},
|
||||||
computed: {
|
computed: {
|
||||||
muteWords () {
|
muteWords () {
|
||||||
return this.$store.state.config.muteWords
|
return this.$store.state.config.muteWords
|
||||||
|
@ -98,12 +101,27 @@ const Status = {
|
||||||
//
|
//
|
||||||
// Using max-height + overflow: auto for status components resulted in false positives
|
// Using max-height + overflow: auto for status components resulted in false positives
|
||||||
// very often with japanese characters, and it was very annoying.
|
// very often with japanese characters, and it was very annoying.
|
||||||
|
tallStatus () {
|
||||||
|
const lengthScore = this.status.statusnet_html.split(/<p|<br/).length + this.status.text.length / 80
|
||||||
|
return lengthScore > 20
|
||||||
|
},
|
||||||
|
hideSubjectStatus () {
|
||||||
|
if (this.tallStatus && !this.$store.state.config.collapseMessageWithSubject) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return !this.expandingSubject && this.status.summary
|
||||||
|
},
|
||||||
hideTallStatus () {
|
hideTallStatus () {
|
||||||
|
if (this.status.summary && this.$store.state.config.collapseMessageWithSubject) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if (this.showingTall) {
|
if (this.showingTall) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
const lengthScore = this.status.statusnet_html.split(/<p|<br/).length + this.status.text.length / 80
|
return this.tallStatus
|
||||||
return lengthScore > 20
|
},
|
||||||
|
showingMore () {
|
||||||
|
return this.showingTall || (this.status.summary && this.expandingSubject)
|
||||||
},
|
},
|
||||||
attachmentSize () {
|
attachmentSize () {
|
||||||
if ((this.$store.state.config.hideAttachments && !this.inConversation) ||
|
if ((this.$store.state.config.hideAttachments && !this.inConversation) ||
|
||||||
|
@ -163,8 +181,16 @@ const Status = {
|
||||||
toggleUserExpanded () {
|
toggleUserExpanded () {
|
||||||
this.userExpanded = !this.userExpanded
|
this.userExpanded = !this.userExpanded
|
||||||
},
|
},
|
||||||
toggleShowTall () {
|
toggleShowMore () {
|
||||||
this.showingTall = !this.showingTall
|
if (this.showingTall) {
|
||||||
|
this.showingTall = false
|
||||||
|
} else if (this.expandingSubject) {
|
||||||
|
this.expandingSubject = false
|
||||||
|
} else if (this.hideTallStatus) {
|
||||||
|
this.showingTall = true
|
||||||
|
} else if (this.hideSubjectStatus) {
|
||||||
|
this.expandingSubject = true
|
||||||
|
}
|
||||||
},
|
},
|
||||||
replyEnter (id, event) {
|
replyEnter (id, event) {
|
||||||
this.showPreview = true
|
this.showPreview = true
|
||||||
|
|
|
@ -76,9 +76,11 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div :class="{'tall-status': hideTallStatus}" class="status-content-wrapper">
|
<div :class="{'tall-status': hideTallStatus}" class="status-content-wrapper">
|
||||||
<a class="tall-status-hider" :class="{ 'tall-status-hider_focused': isFocused }" v-if="hideTallStatus" href="#" @click.prevent="toggleShowTall">Show more</a>
|
<a class="tall-status-hider" :class="{ 'tall-status-hider_focused': isFocused }" v-if="hideTallStatus" href="#" @click.prevent="toggleShowMore">Show more</a>
|
||||||
<div @click.prevent="linkClicked" class="status-content media-body" v-html="status.statusnet_html"></div>
|
<div @click.prevent="linkClicked" class="status-content media-body" v-html="status.statusnet_html" v-if="!hideSubjectStatus"></div>
|
||||||
<a v-if="showingTall" href="#" class="tall-status-unhider" @click.prevent="toggleShowTall">Show less</a>
|
<div @click.prevent="linkClicked" class="status-content media-body" v-html="status.summary" v-else></div>
|
||||||
|
<a v-if="hideSubjectStatus" href="#" class="cw-status-hider" @click.prevent="toggleShowMore">Show more</a>
|
||||||
|
<a v-if="showingMore" href="#" class="status-unhider" @click.prevent="toggleShowMore">Show less</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if='status.attachments' class='attachments media-body'>
|
<div v-if='status.attachments' class='attachments media-body'>
|
||||||
|
@ -310,7 +312,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tall-status-unhider {
|
.status-unhider, .cw-status-hider {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ export default {
|
||||||
return {
|
return {
|
||||||
availableStyles: [],
|
availableStyles: [],
|
||||||
selected: this.$store.state.config.theme,
|
selected: this.$store.state.config.theme,
|
||||||
|
invalidThemeImported: false,
|
||||||
bgColorLocal: '',
|
bgColorLocal: '',
|
||||||
btnColorLocal: '',
|
btnColorLocal: '',
|
||||||
textColorLocal: '',
|
textColorLocal: '',
|
||||||
|
@ -32,25 +33,61 @@ export default {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
this.bgColorLocal = rgbstr2hex(this.$store.state.config.colors.bg)
|
this.normalizeLocalState(this.$store.state.config.colors, this.$store.state.config.radii)
|
||||||
this.btnColorLocal = rgbstr2hex(this.$store.state.config.colors.btn)
|
|
||||||
this.textColorLocal = rgbstr2hex(this.$store.state.config.colors.fg)
|
|
||||||
this.linkColorLocal = rgbstr2hex(this.$store.state.config.colors.link)
|
|
||||||
|
|
||||||
this.redColorLocal = rgbstr2hex(this.$store.state.config.colors.cRed)
|
|
||||||
this.blueColorLocal = rgbstr2hex(this.$store.state.config.colors.cBlue)
|
|
||||||
this.greenColorLocal = rgbstr2hex(this.$store.state.config.colors.cGreen)
|
|
||||||
this.orangeColorLocal = rgbstr2hex(this.$store.state.config.colors.cOrange)
|
|
||||||
|
|
||||||
this.btnRadiusLocal = this.$store.state.config.radii.btnRadius || 4
|
|
||||||
this.inputRadiusLocal = this.$store.state.config.radii.inputRadius || 4
|
|
||||||
this.panelRadiusLocal = this.$store.state.config.radii.panelRadius || 10
|
|
||||||
this.avatarRadiusLocal = this.$store.state.config.radii.avatarRadius || 5
|
|
||||||
this.avatarAltRadiusLocal = this.$store.state.config.radii.avatarAltRadius || 50
|
|
||||||
this.tooltipRadiusLocal = this.$store.state.config.radii.tooltipRadius || 2
|
|
||||||
this.attachmentRadiusLocal = this.$store.state.config.radii.attachmentRadius || 5
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
exportCurrentTheme () {
|
||||||
|
const stringified = JSON.stringify({
|
||||||
|
// To separate from other random JSON files and possible future theme formats
|
||||||
|
_pleroma_theme_version: 1,
|
||||||
|
colors: this.$store.state.config.colors,
|
||||||
|
radii: this.$store.state.config.radii
|
||||||
|
}, null, 2) // Pretty-print and indent with 2 spaces
|
||||||
|
|
||||||
|
// Create an invisible link with a data url and simulate a click
|
||||||
|
const e = document.createElement('a')
|
||||||
|
e.setAttribute('download', 'pleroma_theme.json')
|
||||||
|
e.setAttribute('href', 'data:application/json;base64,' + window.btoa(stringified))
|
||||||
|
e.style.display = 'none'
|
||||||
|
|
||||||
|
document.body.appendChild(e)
|
||||||
|
e.click()
|
||||||
|
document.body.removeChild(e)
|
||||||
|
},
|
||||||
|
|
||||||
|
importTheme () {
|
||||||
|
this.invalidThemeImported = false
|
||||||
|
const filePicker = document.createElement('input')
|
||||||
|
filePicker.setAttribute('type', 'file')
|
||||||
|
filePicker.setAttribute('accept', '.json')
|
||||||
|
|
||||||
|
filePicker.addEventListener('change', event => {
|
||||||
|
if (event.target.files[0]) {
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
|
const reader = new FileReader()
|
||||||
|
reader.onload = ({target}) => {
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(target.result)
|
||||||
|
if (parsed._pleroma_theme_version === 1) {
|
||||||
|
this.normalizeLocalState(parsed.colors, parsed.radii)
|
||||||
|
} else {
|
||||||
|
// A theme from the future, spooky
|
||||||
|
this.invalidThemeImported = true
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// This will happen both if there is a JSON syntax error or the theme is missing components
|
||||||
|
this.invalidThemeImported = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reader.readAsText(event.target.files[0])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
document.body.appendChild(filePicker)
|
||||||
|
filePicker.click()
|
||||||
|
document.body.removeChild(filePicker)
|
||||||
|
},
|
||||||
|
|
||||||
setCustomTheme () {
|
setCustomTheme () {
|
||||||
if (!this.bgColorLocal && !this.btnColorLocal && !this.linkColorLocal) {
|
if (!this.bgColorLocal && !this.btnColorLocal && !this.linkColorLocal) {
|
||||||
// reset to picked themes
|
// reset to picked themes
|
||||||
|
@ -95,6 +132,26 @@ export default {
|
||||||
attachmentRadius: this.attachmentRadiusLocal
|
attachmentRadius: this.attachmentRadiusLocal
|
||||||
}})
|
}})
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
normalizeLocalState (colors, radii) {
|
||||||
|
this.bgColorLocal = rgbstr2hex(colors.bg)
|
||||||
|
this.btnColorLocal = rgbstr2hex(colors.btn)
|
||||||
|
this.textColorLocal = rgbstr2hex(colors.fg)
|
||||||
|
this.linkColorLocal = rgbstr2hex(colors.link)
|
||||||
|
|
||||||
|
this.redColorLocal = rgbstr2hex(colors.cRed)
|
||||||
|
this.blueColorLocal = rgbstr2hex(colors.cBlue)
|
||||||
|
this.greenColorLocal = rgbstr2hex(colors.cGreen)
|
||||||
|
this.orangeColorLocal = rgbstr2hex(colors.cOrange)
|
||||||
|
|
||||||
|
this.btnRadiusLocal = radii.btnRadius || 4
|
||||||
|
this.inputRadiusLocal = radii.inputRadius || 4
|
||||||
|
this.panelRadiusLocal = radii.panelRadius || 10
|
||||||
|
this.avatarRadiusLocal = radii.avatarRadius || 5
|
||||||
|
this.avatarAltRadiusLocal = radii.avatarAltRadius || 50
|
||||||
|
this.tooltipRadiusLocal = radii.tooltipRadius || 2
|
||||||
|
this.attachmentRadiusLocal = radii.attachmentRadius || 5
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
|
|
@ -11,6 +11,11 @@
|
||||||
<i class="icon-down-open"/>
|
<i class="icon-down-open"/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<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">
|
<div class="color-container">
|
||||||
<p>{{$t('settings.theme_help')}}</p>
|
<p>{{$t('settings.theme_help')}}</p>
|
||||||
<div class="color-item">
|
<div class="color-item">
|
||||||
|
@ -134,6 +139,11 @@
|
||||||
margin-right: 1em;
|
margin-right: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.import-warning {
|
||||||
|
color: $fallback--cRed;
|
||||||
|
color: var(--cRed, $fallback--cRed);
|
||||||
|
}
|
||||||
|
|
||||||
.radius-container,
|
.radius-container,
|
||||||
.color-container {
|
.color-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -6,6 +6,7 @@ const UserSettings = {
|
||||||
newname: this.$store.state.users.currentUser.name,
|
newname: this.$store.state.users.currentUser.name,
|
||||||
newbio: this.$store.state.users.currentUser.description,
|
newbio: this.$store.state.users.currentUser.description,
|
||||||
newlocked: this.$store.state.users.currentUser.locked,
|
newlocked: this.$store.state.users.currentUser.locked,
|
||||||
|
newdefaultScope: this.$store.state.users.currentUser.default_scope,
|
||||||
followList: null,
|
followList: null,
|
||||||
followImportError: false,
|
followImportError: false,
|
||||||
followsImported: false,
|
followsImported: false,
|
||||||
|
@ -17,7 +18,8 @@ const UserSettings = {
|
||||||
deleteAccountError: false,
|
deleteAccountError: false,
|
||||||
changePasswordInputs: [ '', '', '' ],
|
changePasswordInputs: [ '', '', '' ],
|
||||||
changedPassword: false,
|
changedPassword: false,
|
||||||
changePasswordError: false
|
changePasswordError: false,
|
||||||
|
activeTab: 'profile'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
@ -29,6 +31,17 @@ const UserSettings = {
|
||||||
},
|
},
|
||||||
pleromaBackend () {
|
pleromaBackend () {
|
||||||
return this.$store.state.config.pleromaBackend
|
return this.$store.state.config.pleromaBackend
|
||||||
|
},
|
||||||
|
scopeOptionsEnabled () {
|
||||||
|
return this.$store.state.config.scopeOptionsEnabled
|
||||||
|
},
|
||||||
|
vis () {
|
||||||
|
return {
|
||||||
|
public: { selected: this.newdefaultScope === 'public' },
|
||||||
|
unlisted: { selected: this.newdefaultScope === 'unlisted' },
|
||||||
|
private: { selected: this.newdefaultScope === 'private' },
|
||||||
|
direct: { selected: this.newdefaultScope === 'direct' }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -36,12 +49,18 @@ const UserSettings = {
|
||||||
const name = this.newname
|
const name = this.newname
|
||||||
const description = this.newbio
|
const description = this.newbio
|
||||||
const locked = this.newlocked
|
const locked = this.newlocked
|
||||||
this.$store.state.api.backendInteractor.updateProfile({params: {name, description, locked}}).then((user) => {
|
/* eslint-disable camelcase */
|
||||||
|
const default_scope = this.newdefaultScope
|
||||||
|
this.$store.state.api.backendInteractor.updateProfile({params: {name, description, locked, default_scope}}).then((user) => {
|
||||||
if (!user.error) {
|
if (!user.error) {
|
||||||
this.$store.commit('addNewUsers', [user])
|
this.$store.commit('addNewUsers', [user])
|
||||||
this.$store.commit('setCurrentUser', user)
|
this.$store.commit('setCurrentUser', user)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
/* eslint-enable camelcase */
|
||||||
|
},
|
||||||
|
changeVis (visibility) {
|
||||||
|
this.newdefaultScope = visibility
|
||||||
},
|
},
|
||||||
uploadFile (slot, e) {
|
uploadFile (slot, e) {
|
||||||
const file = e.target.files[0]
|
const file = e.target.files[0]
|
||||||
|
@ -217,6 +236,9 @@ const UserSettings = {
|
||||||
this.changePasswordError = res.error
|
this.changePasswordError = res.error
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
activateTab (tabName) {
|
||||||
|
this.activeTab = tabName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,19 +4,33 @@
|
||||||
{{$t('settings.user_settings')}}
|
{{$t('settings.user_settings')}}
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body profile-edit">
|
<div class="panel-body profile-edit">
|
||||||
<div class="setting-item">
|
<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>
|
<h2>{{$t('settings.name_bio')}}</h2>
|
||||||
<p>{{$t('settings.name')}}</p>
|
<p>{{$t('settings.name')}}</p>
|
||||||
<input class='name-changer' id='username' v-model="newname"></input>
|
<input class='name-changer' id='username' v-model="newname"></input>
|
||||||
<p>{{$t('settings.bio')}}</p>
|
<p>{{$t('settings.bio')}}</p>
|
||||||
<textarea class="bio" v-model="newbio"></textarea>
|
<textarea class="bio" v-model="newbio"></textarea>
|
||||||
<div class="setting-item">
|
<p>
|
||||||
<input type="checkbox" v-model="newlocked" id="account-locked">
|
<input type="checkbox" v-model="newlocked" id="account-locked">
|
||||||
<label for="account-locked">{{$t('settings.lock_account_description')}}</label>
|
<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>
|
</div>
|
||||||
<button :disabled='newname.length <= 0' class="btn btn-default" @click="updateProfile">{{$t('general.submit')}}</button>
|
<button :disabled='newname.length <= 0' class="btn btn-default" @click="updateProfile">{{$t('general.submit')}}</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-item">
|
<div class="setting-item" v-if="activeTab == 'profile'">
|
||||||
<h2>{{$t('settings.avatar')}}</h2>
|
<h2>{{$t('settings.avatar')}}</h2>
|
||||||
<p>{{$t('settings.current_avatar')}}</p>
|
<p>{{$t('settings.current_avatar')}}</p>
|
||||||
<img :src="user.profile_image_url_original" class="old-avatar"></img>
|
<img :src="user.profile_image_url_original" class="old-avatar"></img>
|
||||||
|
@ -29,7 +43,7 @@
|
||||||
<i class="icon-spin4 animate-spin" v-if="uploading[0]"></i>
|
<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>
|
<button class="btn btn-default" v-else-if="previews[0]" @click="submitAvatar">{{$t('general.submit')}}</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-item">
|
<div class="setting-item" v-if="activeTab == 'profile'">
|
||||||
<h2>{{$t('settings.profile_banner')}}</h2>
|
<h2>{{$t('settings.profile_banner')}}</h2>
|
||||||
<p>{{$t('settings.current_profile_banner')}}</p>
|
<p>{{$t('settings.current_profile_banner')}}</p>
|
||||||
<img :src="user.cover_photo" class="banner"></img>
|
<img :src="user.cover_photo" class="banner"></img>
|
||||||
|
@ -42,7 +56,7 @@
|
||||||
<i class=" icon-spin4 animate-spin uploading" v-if="uploading[1]"></i>
|
<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>
|
<button class="btn btn-default" v-else-if="previews[1]" @click="submitBanner">{{$t('general.submit')}}</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-item">
|
<div class="setting-item" v-if="activeTab == 'profile'">
|
||||||
<h2>{{$t('settings.profile_background')}}</h2>
|
<h2>{{$t('settings.profile_background')}}</h2>
|
||||||
<p>{{$t('settings.set_new_profile_background')}}</p>
|
<p>{{$t('settings.set_new_profile_background')}}</p>
|
||||||
<img class="bg" v-bind:src="previews[2]" v-if="previews[2]">
|
<img class="bg" v-bind:src="previews[2]" v-if="previews[2]">
|
||||||
|
@ -53,7 +67,7 @@
|
||||||
<i class=" icon-spin4 animate-spin uploading" v-if="uploading[2]"></i>
|
<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>
|
<button class="btn btn-default" v-else-if="previews[2]" @click="submitBg">{{$t('general.submit')}}</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-item">
|
<div class="setting-item" v-if="activeTab == 'security'">
|
||||||
<h2>{{$t('settings.change_password')}}</h2>
|
<h2>{{$t('settings.change_password')}}</h2>
|
||||||
<div>
|
<div>
|
||||||
<p>{{$t('settings.current_password')}}</p>
|
<p>{{$t('settings.current_password')}}</p>
|
||||||
|
@ -72,7 +86,7 @@
|
||||||
<p v-else-if="changePasswordError !== false">{{$t('settings.change_password_error')}}</p>
|
<p v-else-if="changePasswordError !== false">{{$t('settings.change_password_error')}}</p>
|
||||||
<p v-if="changePasswordError">{{changePasswordError}}</p>
|
<p v-if="changePasswordError">{{changePasswordError}}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-item" v-if="pleromaBackend">
|
<div class="setting-item" v-if="pleromaBackend && activeTab == 'data_import_export'">
|
||||||
<h2>{{$t('settings.follow_import')}}</h2>
|
<h2>{{$t('settings.follow_import')}}</h2>
|
||||||
<p>{{$t('settings.import_followers_from_a_csv_file')}}</p>
|
<p>{{$t('settings.import_followers_from_a_csv_file')}}</p>
|
||||||
<form v-model="followImportForm">
|
<form v-model="followImportForm">
|
||||||
|
@ -89,15 +103,15 @@
|
||||||
<p>{{$t('settings.follow_import_error')}}</p>
|
<p>{{$t('settings.follow_import_error')}}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-item" v-if="enableFollowsExport">
|
<div class="setting-item" v-if="enableFollowsExport && activeTab == 'data_import_export'">
|
||||||
<h2>{{$t('settings.follow_export')}}</h2>
|
<h2>{{$t('settings.follow_export')}}</h2>
|
||||||
<button class="btn btn-default" @click="exportFollows">{{$t('settings.follow_export_button')}}</button>
|
<button class="btn btn-default" @click="exportFollows">{{$t('settings.follow_export_button')}}</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-item" v-else>
|
<div class="setting-item" v-else-if="activeTab == 'data_import_export'">
|
||||||
<h2>{{$t('settings.follow_export_processing')}}</h2>
|
<h2>{{$t('settings.follow_export_processing')}}</h2>
|
||||||
</div>
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
<div class="setting-item">
|
<div class="setting-item" v-if="activeTab == 'security'">
|
||||||
<h2>{{$t('settings.delete_account')}}</h2>
|
<h2>{{$t('settings.delete_account')}}</h2>
|
||||||
<p v-if="!deletingAccount">{{$t('settings.delete_account_description')}}</p>
|
<p v-if="!deletingAccount">{{$t('settings.delete_account_description')}}</p>
|
||||||
<div v-if="deletingAccount">
|
<div v-if="deletingAccount">
|
||||||
|
@ -137,4 +151,13 @@
|
||||||
margin: 0.25em;
|
margin: 0.25em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tab-switcher {
|
||||||
|
margin: 7px 7px;
|
||||||
|
display: inline-block;
|
||||||
|
|
||||||
|
button {
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -48,6 +48,9 @@ const de = {
|
||||||
settings: 'Einstellungen',
|
settings: 'Einstellungen',
|
||||||
theme: 'Farbschema',
|
theme: 'Farbschema',
|
||||||
presets: 'Voreinstellungen',
|
presets: 'Voreinstellungen',
|
||||||
|
export_theme: 'Aktuelles Theme exportieren',
|
||||||
|
import_theme: 'Gespeichertes Theme 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',
|
theme_help: 'Benutze HTML Farbcodes (#rrggbb) um dein Farbschema anzupassen',
|
||||||
radii_help: 'Kantenrundung (in Pixel) der Oberfläche anpassen',
|
radii_help: 'Kantenrundung (in Pixel) der Oberfläche anpassen',
|
||||||
background: 'Hintergrund',
|
background: 'Hintergrund',
|
||||||
|
@ -288,7 +291,10 @@ const en = {
|
||||||
settings: 'Settings',
|
settings: 'Settings',
|
||||||
theme: 'Theme',
|
theme: 'Theme',
|
||||||
presets: 'Presets',
|
presets: 'Presets',
|
||||||
|
export_theme: 'Export current theme',
|
||||||
|
import_theme: 'Load saved theme',
|
||||||
theme_help: 'Use hex color codes (#rrggbb) to customize your color theme.',
|
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)',
|
radii_help: 'Set up interface edge rounding (in pixels)',
|
||||||
background: 'Background',
|
background: 'Background',
|
||||||
foreground: 'Foreground',
|
foreground: 'Foreground',
|
||||||
|
@ -311,6 +317,7 @@ const en = {
|
||||||
hide_attachments_in_tl: 'Hide attachments in timeline',
|
hide_attachments_in_tl: 'Hide attachments in timeline',
|
||||||
hide_attachments_in_convo: 'Hide attachments in conversations',
|
hide_attachments_in_convo: 'Hide attachments in conversations',
|
||||||
nsfw_clickthrough: 'Enable clickthrough NSFW attachment hiding',
|
nsfw_clickthrough: 'Enable clickthrough NSFW attachment hiding',
|
||||||
|
collapse_subject: 'Collapse posts with subjects',
|
||||||
stop_gifs: 'Play-on-hover GIFs',
|
stop_gifs: 'Play-on-hover GIFs',
|
||||||
autoload: 'Enable automatic loading when scrolled to the bottom',
|
autoload: 'Enable automatic loading when scrolled to the bottom',
|
||||||
streaming: 'Enable automatic streaming of new posts when scrolled to the top',
|
streaming: 'Enable automatic streaming of new posts when scrolled to the top',
|
||||||
|
@ -336,7 +343,11 @@ const en = {
|
||||||
changed_password: 'Password changed successfully!',
|
changed_password: 'Password changed successfully!',
|
||||||
change_password_error: 'There was an issue changing your password.',
|
change_password_error: 'There was an issue changing your password.',
|
||||||
lock_account_description: 'Restrict your account to approved followers only',
|
lock_account_description: 'Restrict your account to approved followers only',
|
||||||
limited_availability: 'Unavailable in your browser'
|
limited_availability: 'Unavailable in your browser',
|
||||||
|
default_vis: 'Default visibility scope',
|
||||||
|
profile_tab: 'Profile',
|
||||||
|
security_tab: 'Security',
|
||||||
|
data_import_export_tab: 'Data Import / Export'
|
||||||
},
|
},
|
||||||
notifications: {
|
notifications: {
|
||||||
notifications: 'Notifications',
|
notifications: 'Notifications',
|
||||||
|
|
|
@ -45,6 +45,7 @@ Vue.use(VueChatScroll)
|
||||||
|
|
||||||
const persistedStateOptions = {
|
const persistedStateOptions = {
|
||||||
paths: [
|
paths: [
|
||||||
|
'config.collapseMessageWithSubject',
|
||||||
'config.hideAttachments',
|
'config.hideAttachments',
|
||||||
'config.hideAttachmentsInConv',
|
'config.hideAttachmentsInConv',
|
||||||
'config.hideNsfw',
|
'config.hideNsfw',
|
||||||
|
@ -96,7 +97,7 @@ window.fetch('/api/statusnet/config.json')
|
||||||
window.fetch('/static/config.json')
|
window.fetch('/static/config.json')
|
||||||
.then((res) => res.json())
|
.then((res) => res.json())
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
const {theme, background, logo, showWhoToFollowPanel, whoToFollowProvider, whoToFollowLink, showInstanceSpecificPanel, scopeOptionsEnabled} = data
|
const {theme, background, logo, showWhoToFollowPanel, whoToFollowProvider, whoToFollowLink, showInstanceSpecificPanel, scopeOptionsEnabled, collapseMessageWithSubject} = data
|
||||||
store.dispatch('setOption', { name: 'theme', value: theme })
|
store.dispatch('setOption', { name: 'theme', value: theme })
|
||||||
store.dispatch('setOption', { name: 'background', value: background })
|
store.dispatch('setOption', { name: 'background', value: background })
|
||||||
store.dispatch('setOption', { name: 'logo', value: logo })
|
store.dispatch('setOption', { name: 'logo', value: logo })
|
||||||
|
@ -105,6 +106,7 @@ window.fetch('/static/config.json')
|
||||||
store.dispatch('setOption', { name: 'whoToFollowLink', value: whoToFollowLink })
|
store.dispatch('setOption', { name: 'whoToFollowLink', value: whoToFollowLink })
|
||||||
store.dispatch('setOption', { name: 'showInstanceSpecificPanel', value: showInstanceSpecificPanel })
|
store.dispatch('setOption', { name: 'showInstanceSpecificPanel', value: showInstanceSpecificPanel })
|
||||||
store.dispatch('setOption', { name: 'scopeOptionsEnabled', value: scopeOptionsEnabled })
|
store.dispatch('setOption', { name: 'scopeOptionsEnabled', value: scopeOptionsEnabled })
|
||||||
|
store.dispatch('setOption', { name: 'collapseMessageWithSubject', value: collapseMessageWithSubject })
|
||||||
if (data['chatDisabled']) {
|
if (data['chatDisabled']) {
|
||||||
store.dispatch('disableChat')
|
store.dispatch('disableChat')
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import StyleSetter from '../services/style_setter/style_setter.js'
|
||||||
const defaultState = {
|
const defaultState = {
|
||||||
name: 'Pleroma FE',
|
name: 'Pleroma FE',
|
||||||
colors: {},
|
colors: {},
|
||||||
|
collapseMessageWithSubject: false,
|
||||||
hideAttachments: false,
|
hideAttachments: false,
|
||||||
hideAttachmentsInConv: false,
|
hideAttachmentsInConv: false,
|
||||||
hideNsfw: true,
|
hideNsfw: true,
|
||||||
|
|
|
@ -13,5 +13,6 @@
|
||||||
"whoToFollowLinkDummy2": "https://followlink.osa-p.net/recommend.html",
|
"whoToFollowLinkDummy2": "https://followlink.osa-p.net/recommend.html",
|
||||||
"showInstanceSpecificPanel": true,
|
"showInstanceSpecificPanel": true,
|
||||||
"scopeOptionsEnabled": true,
|
"scopeOptionsEnabled": true,
|
||||||
"registrationOpen": true
|
"registrationOpen": true,
|
||||||
|
"collapseMessageWithSubject": false
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue