aboutsummaryrefslogtreecommitdiff
path: root/src/components
diff options
context:
space:
mode:
Diffstat (limited to 'src/components')
-rw-r--r--src/components/attachment/attachment.vue3
-rw-r--r--src/components/conversation/conversation.vue2
-rw-r--r--src/components/nav_panel/nav_panel.vue2
-rw-r--r--src/components/notifications/notifications.scss2
-rw-r--r--src/components/post_status_form/post_status_form.js37
-rw-r--r--src/components/post_status_form/post_status_form.vue55
-rw-r--r--src/components/status/status.js12
-rw-r--r--src/components/status/status.vue7
-rw-r--r--src/components/style_switcher/style_switcher.js3
-rw-r--r--src/components/style_switcher/style_switcher.vue6
-rw-r--r--src/components/user_card_content/user_card_content.js20
-rw-r--r--src/components/user_card_content/user_card_content.vue83
-rw-r--r--src/components/user_profile/user_profile.vue2
-rw-r--r--src/components/user_settings/user_settings.js71
-rw-r--r--src/components/user_settings/user_settings.vue42
-rw-r--r--src/components/who_to_follow_panel/who_to_follow_panel.js123
-rw-r--r--src/components/who_to_follow_panel/who_to_follow_panel.vue37
17 files changed, 437 insertions, 70 deletions
diff --git a/src/components/attachment/attachment.vue b/src/components/attachment/attachment.vue
index b2f63668..c48fb16b 100644
--- a/src/components/attachment/attachment.vue
+++ b/src/components/attachment/attachment.vue
@@ -96,6 +96,9 @@
background: rgba(230,230,230,0.6);
font-weight: bold;
z-index: 4;
+ line-height: 1;
+ border-radius: $fallback--tooltipRadius;
+ border-radius: var(--tooltipRadius, $fallback--tooltipRadius);
}
.small {
diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue
index 308e5e7d..bfcd3fe7 100644
--- a/src/components/conversation/conversation.vue
+++ b/src/components/conversation/conversation.vue
@@ -3,7 +3,7 @@
<div class="panel-heading conversation-heading">
{{ $t('timeline.conversation') }}
<span v-if="collapsable" style="float:right;">
- <small><a href="#" @click.prevent="$emit('toggleExpanded')">Collapse</a></small>
+ <small><a href="#" @click.prevent="$emit('toggleExpanded')">{{ $t('timeline.collapse') }}</a></small>
</span>
</div>
<div class="panel-body">
diff --git a/src/components/nav_panel/nav_panel.vue b/src/components/nav_panel/nav_panel.vue
index 6f949afb..2e1a6c7a 100644
--- a/src/components/nav_panel/nav_panel.vue
+++ b/src/components/nav_panel/nav_panel.vue
@@ -45,8 +45,6 @@
border-bottom: 1px solid;
border-color: $fallback--border;
border-color: var(--border, $fallback--border);
- background-color: $fallback--bg;
- background-color: var(--bg, $fallback--bg);
padding: 0;
&:first-child a {
diff --git a/src/components/notifications/notifications.scss b/src/components/notifications/notifications.scss
index 9cbb1226..008530b4 100644
--- a/src/components/notifications/notifications.scss
+++ b/src/components/notifications/notifications.scss
@@ -98,7 +98,7 @@
.status {
padding: 0.25em 0;
color: $fallback--faint;
- color: var($fallback--faint, --faint);
+ color: var(--faint, $fallback--faint);
}
padding: 0;
.media-body {
diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js
index 6bcf1c66..0597d652 100644
--- a/src/components/post_status_form/post_status_form.js
+++ b/src/components/post_status_form/post_status_form.js
@@ -48,12 +48,21 @@ const PostStatusForm = {
highlighted: 0,
newStatus: {
status: statusText,
- files: []
+ files: [],
+ visibility: 'public'
},
caret: 0
}
},
computed: {
+ vis () {
+ return {
+ public: { selected: this.newStatus.visibility === 'public' },
+ unlisted: { selected: this.newStatus.visibility === 'unlisted' },
+ private: { selected: this.newStatus.visibility === 'private' },
+ direct: { selected: this.newStatus.visibility === 'direct' }
+ }
+ },
candidates () {
const firstchar = this.textAtCaret.charAt(0)
if (firstchar === '@') {
@@ -118,6 +127,9 @@ const PostStatusForm = {
},
isOverLengthLimit () {
return this.hasStatusLengthLimit && (this.statusLength > this.statusLengthLimit)
+ },
+ scopeOptionsEnabled () {
+ return this.$store.state.config.scopeOptionsEnabled
}
},
methods: {
@@ -185,6 +197,8 @@ const PostStatusForm = {
this.posting = true
statusPoster.postStatus({
status: newStatus.status,
+ spoilerText: newStatus.spoilerText || null,
+ visibility: newStatus.visibility,
media: newStatus.files,
store: this.$store,
inReplyToStatusId: this.replyTo
@@ -192,7 +206,8 @@ const PostStatusForm = {
if (!data.error) {
this.newStatus = {
status: '',
- files: []
+ files: [],
+ visibility: newStatus.visibility
}
this.$emit('posted')
let el = this.$el.querySelector('textarea')
@@ -239,18 +254,20 @@ const PostStatusForm = {
e.dataTransfer.dropEffect = 'copy'
},
resize (e) {
- const target = e.target || e
- target.style.height = 'auto'
- const heightPx = target.scrollHeight - 10
- if (heightPx > 54) {
- target.style.height = `${target.scrollHeight - 10}px`
- }
- if (target.value === '') {
- target.style.height = '16px'
+ if (!e.target) { return }
+ const vertPadding = Number(window.getComputedStyle(e.target)['padding-top'].substr(0, 1)) +
+ Number(window.getComputedStyle(e.target)['padding-bottom'].substr(0, 1))
+ e.target.style.height = 'auto'
+ e.target.style.height = `${e.target.scrollHeight - vertPadding}px`
+ if (e.target.value === '') {
+ e.target.style.height = '16px'
}
},
clearError () {
this.error = null
+ },
+ changeVis (visibility) {
+ this.newStatus.visibility = visibility
}
}
}
diff --git a/src/components/post_status_form/post_status_form.vue b/src/components/post_status_form/post_status_form.vue
index 88627e3a..802d51ed 100644
--- a/src/components/post_status_form/post_status_form.vue
+++ b/src/components/post_status_form/post_status_form.vue
@@ -2,6 +2,12 @@
<div class="post-status-form">
<form @submit.prevent="postStatus(newStatus)">
<div class="form-group" >
+ <input
+ v-if="scopeOptionsEnabled"
+ type="text"
+ :placeholder="$t('post_status.content_warning')"
+ v-model="newStatus.spoilerText"
+ class="form-cw">
<textarea
ref="textarea"
@click="setCaret"
@@ -18,16 +24,17 @@
@input="resize"
@paste="paste">
</textarea>
+ <div v-if="scopeOptionsEnabled" 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 style="position:relative;" v-if="candidates">
<div class="autocomplete-panel">
<div v-for="candidate in candidates" @click="replace(candidate.utf || (candidate.screen_name + ' '))">
- <div v-if="candidate.highlighted" class="autocomplete">
- <span v-if="candidate.img"><img :src="candidate.img"></span>
- <span v-else>{{candidate.utf}}</span>
- <span>{{candidate.screen_name}}<small>{{candidate.name}}</small></span>
- </div>
- <div v-else class="autocomplete">
+ <div class="autocomplete" :class="{ highlighted: candidate.highlighted }">
<span v-if="candidate.img"><img :src="candidate.img"></img></span>
<span v-else>{{candidate.utf}}</span>
<span>{{candidate.screen_name}}<small>{{candidate.name}}</small></span>
@@ -84,6 +91,17 @@
}
}
+.post-status-form .visibility-tray {
+ font-size: 1.2em;
+ padding: 3px;
+ cursor: pointer;
+
+ .selected {
+ color: $fallback--lightFg;
+ color: var(--lightFg, $fallback--lightFg);
+ }
+}
+
.post-status-form, .login {
.form-bottom {
display: flex;
@@ -135,10 +153,6 @@
cursor: not-allowed;
}
- .icon-cancel {
- cursor: pointer;
- }
-
form {
display: flex;
flex-direction: column;
@@ -152,7 +166,15 @@
line-height:24px;
}
- form textarea {
+ form textarea.form-cw {
+ line-height:16px;
+ resize: none;
+ overflow: hidden;
+ transition: min-height 200ms 100ms;
+ min-height: 1px;
+ }
+
+ form textarea.form-control {
line-height:16px;
resize: none;
overflow: hidden;
@@ -161,7 +183,7 @@
box-sizing: content-box;
}
- form textarea:focus {
+ form textarea.form-control:focus {
min-height: 48px;
}
@@ -186,8 +208,8 @@
z-index: 1;
box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.5);
min-width: 75%;
- background: $fallback--btn;
- background: var(--btn, $fallback--btn);
+ background: $fallback--bg;
+ background: var(--bg, $fallback--bg);
color: $fallback--lightFg;
color: var(--lightFg, $fallback--lightFg);
}
@@ -216,6 +238,11 @@
color: $fallback--faint;
color: var(--faint, $fallback--faint);
}
+
+ &.highlighted {
+ background-color: $fallback--btn;
+ background-color: var(--btn, $fallback--btn);
+ }
}
}
</style>
diff --git a/src/components/status/status.js b/src/components/status/status.js
index 73f4a7aa..87ef90d8 100644
--- a/src/components/status/status.js
+++ b/src/components/status/status.js
@@ -104,6 +104,18 @@ const Status = {
StillImage
},
methods: {
+ visibilityIcon (visibility) {
+ switch (visibility) {
+ case 'private':
+ return 'icon-lock'
+ case 'unlisted':
+ return 'icon-lock-open-alt'
+ case 'direct':
+ return 'icon-mail-alt'
+ default:
+ return 'icon-globe'
+ }
+ },
linkClicked ({target}) {
if (target.tagName === 'SPAN') {
target = target.parentNode
diff --git a/src/components/status/status.vue b/src/components/status/status.vue
index f1163fd9..ace141cd 100644
--- a/src/components/status/status.vue
+++ b/src/components/status/status.vue
@@ -55,6 +55,7 @@
<router-link class="timeago" :to="{ name: 'conversation', params: { id: status.id } }">
<timeago :since="status.created_at" :auto-update="60"></timeago>
</router-link>
+ <span v-if="status.visibility"><i :class="visibilityIcon(status.visibility)"></i> </span>
<a :href="status.external_url" target="_blank" v-if="!status.is_local" class="source_url"><i class="icon-link-ext"></i></a>
<template v-if="expandable">
<a href="#" @click.prevent="toggleExpanded"><i class="icon-plus-squared"></i></a>
@@ -165,8 +166,6 @@
border-left-width: 0px;
line-height: 18px;
min-width: 0;
- background-color: $fallback--bg;
- background-color: var(--bg, $fallback--bg);
border-color: $fallback--border;
border-color: var(--border, $fallback--border);
@@ -189,6 +188,10 @@
margin: 0 0 0.25em 0.8em;
}
+ .usercard {
+ margin-bottom: .7em
+ }
+
.media-heading {
flex-wrap: nowrap;
}
diff --git a/src/components/style_switcher/style_switcher.js b/src/components/style_switcher/style_switcher.js
index 08bc7113..6f4845c4 100644
--- a/src/components/style_switcher/style_switcher.js
+++ b/src/components/style_switcher/style_switcher.js
@@ -14,6 +14,7 @@ export default {
greenColorLocal: '',
orangeColorLocal: '',
btnRadiusLocal: '',
+ inputRadiusLocal: '',
panelRadiusLocal: '',
avatarRadiusLocal: '',
avatarAltRadiusLocal: '',
@@ -42,6 +43,7 @@ export default {
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
@@ -85,6 +87,7 @@ export default {
cGreen: greenRgb,
cOrange: orangeRgb,
btnRadius: this.btnRadiusLocal,
+ inputRadius: this.inputRadiusLocal,
panelRadius: this.panelRadiusLocal,
avatarRadius: this.avatarRadiusLocal,
avatarAltRadius: this.avatarAltRadiusLocal,
diff --git a/src/components/style_switcher/style_switcher.vue b/src/components/style_switcher/style_switcher.vue
index 9c39b245..7acba1dc 100644
--- a/src/components/style_switcher/style_switcher.vue
+++ b/src/components/style_switcher/style_switcher.vue
@@ -59,6 +59,11 @@
<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">
@@ -86,6 +91,7 @@
</div>
<div :style="{
'--btnRadius': btnRadiusLocal + 'px',
+ '--inputRadius': inputRadiusLocal + 'px',
'--panelRadius': panelRadiusLocal + 'px',
'--avatarRadius': avatarRadiusLocal + 'px',
'--avatarAltRadius': avatarAltRadiusLocal + 'px',
diff --git a/src/components/user_card_content/user_card_content.js b/src/components/user_card_content/user_card_content.js
index 1e8c91de..4d4266cb 100644
--- a/src/components/user_card_content/user_card_content.js
+++ b/src/components/user_card_content/user_card_content.js
@@ -2,16 +2,24 @@ import StillImage from '../still-image/still-image.vue'
import { hex2rgb } from '../../services/color_convert/color_convert.js'
export default {
- props: [ 'user', 'switcher', 'hideBio' ],
+ props: [ 'user', 'switcher', 'selected', 'hideBio' ],
computed: {
headingStyle () {
const color = this.$store.state.config.colors.bg
if (color) {
const rgb = hex2rgb(color)
+ const tintColor = `rgba(${Math.floor(rgb.r)}, ${Math.floor(rgb.g)}, ${Math.floor(rgb.b)}, .5)`
console.log(rgb)
+ console.log([
+ `url(${this.user.cover_photo})`,
+ `linear-gradient(to bottom, ${tintColor}, ${tintColor})`
+ ].join(', '))
return {
- backgroundColor: `rgb(${Math.floor(rgb[0] * 0.53)}, ${Math.floor(rgb[1] * 0.56)}, ${Math.floor(rgb[2] * 0.59)})`,
- backgroundImage: `url(${this.user.cover_photo})`
+ backgroundColor: `rgb(${Math.floor(rgb.r * 0.53)}, ${Math.floor(rgb.g * 0.56)}, ${Math.floor(rgb.b * 0.59)})`,
+ backgroundImage: [
+ `linear-gradient(to bottom, ${tintColor}, ${tintColor})`,
+ `url(${this.user.cover_photo})`
+ ].join(', ')
}
}
},
@@ -61,8 +69,10 @@ export default {
store.state.api.backendInteractor.setUserMute(this.user)
},
setProfileView (v) {
- const store = this.$store
- store.commit('setProfileView', { v })
+ if (this.switcher) {
+ const store = this.$store
+ store.commit('setProfileView', { v })
+ }
}
}
}
diff --git a/src/components/user_card_content/user_card_content.vue b/src/components/user_card_content/user_card_content.vue
index ca8428ca..c120df9a 100644
--- a/src/components/user_card_content/user_card_content.vue
+++ b/src/components/user_card_content/user_card_content.vue
@@ -14,8 +14,9 @@
</router-link>
<div class="name-and-screen-name">
<div :title="user.name" class='user-name'>{{user.name}}</div>
- <router-link :to="{ name: 'user-profile', params: { id: user.id } }">
- <div class='user-screen-name'>@{{user.screen_name}}</div>
+ <router-link class='user-screen-name':to="{ name: 'user-profile', params: { id: user.id } }">
+ <span>@{{user.screen_name}}</span>
+ <span class="dailyAvg">{{dailyAvg}} {{ $t('user_card.per_day') }}</span>
</router-link>
</div>
</div>
@@ -73,20 +74,17 @@
</div>
</div>
<div class="panel-body profile-panel-body">
- <div class="user-counts">
- <div class="user-count">
- <a href="#" v-on:click.prevent="setProfileView('statuses')" v-if="switcher"><h5>{{ $t('user_card.statuses') }}</h5></a>
- <h5 v-else>{{ $t('user_card.statuses') }}</h5>
- <span>{{user.statuses_count}} <br><span class="dailyAvg">{{dailyAvg}} {{ $t('user_card.per_day') }}</span></span>
+ <div class="user-counts" :class="{clickable: switcher}">
+ <div class="user-count" v-on:click.prevent="setProfileView('statuses')" :class="{selected: selected === 'statuses'}">
+ <h5>{{ $t('user_card.statuses') }}</h5>
+ <span>{{user.statuses_count}} <br></span>
</div>
- <div class="user-count">
- <a href="#" v-on:click.prevent="setProfileView('friends')" v-if="switcher"><h5>{{ $t('user_card.followees') }}</h5></a>
- <h5 v-else>{{ $t('user_card.followees') }}</h5>
+ <div class="user-count" v-on:click.prevent="setProfileView('friends')" :class="{selected: selected === 'friends'}">
+ <h5>{{ $t('user_card.followees') }}</h5>
<span>{{user.friends_count}}</span>
</div>
- <div class="user-count">
- <a href="#" v-on:click.prevent="setProfileView('followers')" v-if="switcher"><h5>{{ $t('user_card.followers') }}</h5></a>
- <h5 v-else>{{ $t('user_card.followers') }}</h5>
+ <div class="user-count" v-on:click.prevent="setProfileView('followers')" :class="{selected: selected === 'followers'}">
+ <h5>{{ $t('user_card.followers') }}</h5>
<span>{{user.followers_count}}</span>
</div>
</div>
@@ -112,20 +110,18 @@
}
.profile-panel-body {
- top: -0em;
- padding-top: 4em;
word-wrap: break-word;
background: linear-gradient(to bottom, rgba(0, 0, 0, 0), $fallback--bg 80%);
background: linear-gradient(to bottom, rgba(0, 0, 0, 0), var(--bg, $fallback--bg) 80%)
}
.user-info {
- color: white;
- padding: 0 16px 16px 16px;
- margin-bottom: -4em;
+ color: $fallback--lightFg;
+ color: var(--lightFg, $fallback--lightFg);
+ padding: 0 16px;
.container {
- padding: 16px 10px 4px 10px;
+ padding: 16px 10px 6px 10px;
display: flex;
max-height: 56px;
overflow: hidden;
@@ -154,10 +150,9 @@
}
}
- text-shadow: 0px 1px 1.5px rgba(0, 0, 0, 1.0);
-
.usersettings {
- color: #fff;
+ color: $fallback--lightFg;
+ color: var(--lightFg, $fallback--lightFg);
opacity: .8;
}
@@ -171,14 +166,15 @@
}
.user-name{
- color: white;
text-overflow: ellipsis;
overflow: hidden;
}
.user-screen-name {
- color: white;
- font-weight: lighter;
+ color: $fallback--lightFg;
+ color: var(--lightFg, $fallback--lightFg);
+ display: inline-block;
+ font-weight: light;
font-size: 15px;
padding-right: 0.1em;
}
@@ -191,14 +187,11 @@
div {
flex: 1;
}
- margin-top: 0.7em;
- margin-bottom: -1.0em;
.following {
- color: white;
font-size: 14px;
flex: 0 0 100%;
- margin: -0.7em 0.0em 0.3em 0.0em;
+ margin: 0 0 .4em 0;
padding-left: 16px;
text-align: left;
}
@@ -238,12 +231,37 @@
.user-counts {
display: flex;
line-height:16px;
- padding: 1em 1.5em 0em 1em;
+ padding: .5em 1.5em 0em 1.5em;
text-align: center;
+ justify-content: space-between;
+ color: $fallback--lightFg;
+ color: var(--lightFg, $fallback--lightFg);
+
+ &.clickable {
+ .user-count {
+ cursor: pointer;
+
+ &:hover:not(.selected) {
+ transition: border-bottom 100ms;
+ border-bottom: 3px solid $fallback--link;
+ border-bottom: 3px solid var(--link, $fallback--link);
+ }
+ }
+ }
}
.user-count {
flex: 1;
+ padding: .5em 0 .5em 0;
+ margin: 0 .5em;
+
+ &.selected {
+ transition: none;
+ border-bottom: 5px solid $fallback--link;
+ border-bottom: 5px solid var(--link, $fallback--link);
+ border-radius: $fallback--btnRadius;
+ border-radius: var(--btnRadius, $fallback--btnRadius);
+ }
h5 {
font-size:1em;
@@ -256,7 +274,8 @@
}
.dailyAvg {
- font-size: 0.8em;
- opacity: 0.5;
+ margin-left: 1em;
+ font-size: 0.7em;
+ color: #CCC;
}
</style>
diff --git a/src/components/user_profile/user_profile.vue b/src/components/user_profile/user_profile.vue
index 838a43ab..f8502907 100644
--- a/src/components/user_profile/user_profile.vue
+++ b/src/components/user_profile/user_profile.vue
@@ -1,7 +1,7 @@
<template>
<div>
<div v-if="user" class="user-profile panel panel-default">
- <user-card-content :user="user" :switcher="true"></user-card-content>
+ <user-card-content :user="user" :switcher="true" :selected="timeline.viewing"></user-card-content>
</div>
<Timeline :title="$t('user_profile.timeline_title')" :timeline="timeline" :timeline-name="'user'" :user-id="userId"/>
</div>
diff --git a/src/components/user_settings/user_settings.js b/src/components/user_settings/user_settings.js
index 25ee1f35..b6026e18 100644
--- a/src/components/user_settings/user_settings.js
+++ b/src/components/user_settings/user_settings.js
@@ -8,8 +8,15 @@ const UserSettings = {
followList: null,
followImportError: false,
followsImported: false,
+ enableFollowsExport: true,
uploading: [ false, false, false, false ],
- previews: [ null, null, null ]
+ previews: [ null, null, null ],
+ deletingAccount: false,
+ deleteAccountConfirmPasswordInput: '',
+ deleteAccountError: false,
+ changePasswordInputs: [ '', '', '' ],
+ changedPassword: false,
+ changePasswordError: false
}
},
components: {
@@ -137,6 +144,37 @@ const UserSettings = {
this.uploading[3] = false
})
},
+ /* This function takes an Array of Users
+ * and outputs a file with all the addresses for the user to download
+ */
+ exportPeople (users, filename) {
+ // Get all the friends addresses
+ var UserAddresses = users.map(function (user) {
+ // check is it's a local user
+ if (user && user.is_local) {
+ // append the instance address
+ // eslint-disable-next-line no-undef
+ user.screen_name += '@' + location.hostname
+ }
+ return user.screen_name
+ }).join('\n')
+ // Make the user download the file
+ var fileToDownload = document.createElement('a')
+ fileToDownload.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(UserAddresses))
+ fileToDownload.setAttribute('download', filename)
+ fileToDownload.style.display = 'none'
+ document.body.appendChild(fileToDownload)
+ fileToDownload.click()
+ document.body.removeChild(fileToDownload)
+ },
+ exportFollows () {
+ this.enableFollowsExport = false
+ this.$store.state.api.backendInteractor
+ .fetchFriends({id: this.$store.state.users.currentUser.id})
+ .then((friendList) => {
+ this.exportPeople(friendList, 'friends.csv')
+ })
+ },
followListChange () {
// eslint-disable-next-line no-undef
let formData = new FormData()
@@ -146,6 +184,37 @@ const UserSettings = {
dismissImported () {
this.followsImported = false
this.followImportError = false
+ },
+ confirmDelete () {
+ this.deletingAccount = true
+ },
+ deleteAccount () {
+ this.$store.state.api.backendInteractor.deleteAccount({password: this.deleteAccountConfirmPasswordInput})
+ .then((res) => {
+ if (res.status === 'success') {
+ this.$store.dispatch('logout')
+ this.$router.push('/main/all')
+ } else {
+ this.deleteAccountError = res.error
+ }
+ })
+ },
+ changePassword () {
+ const params = {
+ password: this.changePasswordInputs[0],
+ newPassword: this.changePasswordInputs[1],
+ newPasswordConfirmation: this.changePasswordInputs[2]
+ }
+ this.$store.state.api.backendInteractor.changePassword(params)
+ .then((res) => {
+ if (res.status === 'success') {
+ this.changedPassword = true
+ this.changePasswordError = false
+ } else {
+ this.changedPassword = false
+ this.changePasswordError = res.error
+ }
+ })
}
}
}
diff --git a/src/components/user_settings/user_settings.vue b/src/components/user_settings/user_settings.vue
index ed1864cc..fbf3f651 100644
--- a/src/components/user_settings/user_settings.vue
+++ b/src/components/user_settings/user_settings.vue
@@ -49,6 +49,25 @@
<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">
+ <h3>{{$t('settings.change_password')}}</h3>
+ <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">
<h3>{{$t('settings.follow_import')}}</h3>
<p>{{$t('settings.import_followers_from_a_csv_file')}}</p>
@@ -62,10 +81,31 @@
<p>{{$t('settings.follows_imported')}}</p>
</div>
<div v-else-if="followImportError">
- <i class="icon-cross" @click="dismissImported"</i>
+ <i class="icon-cross" @click="dismissImported"></i>
<p>{{$t('settings.follow_import_error')}}</p>
</div>
</div>
+ <div class="setting-item" v-if="enableFollowsExport">
+ <h3>{{$t('settings.follow_export')}}</h3>
+ <button class="btn btn-default" @click="exportFollows">{{$t('settings.follow_export_button')}}</button>
+ </div>
+ <div class="setting-item" v-else>
+ <h3>{{$t('settings.follow_export_processing')}}</h3>
+ </div>
+ <hr>
+ <div class="setting-item">
+ <h3>{{$t('settings.delete_account')}}</h3>
+ <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>
</div>
</template>
diff --git a/src/components/who_to_follow_panel/who_to_follow_panel.js b/src/components/who_to_follow_panel/who_to_follow_panel.js
new file mode 100644
index 00000000..51b9f469
--- /dev/null
+++ b/src/components/who_to_follow_panel/who_to_follow_panel.js
@@ -0,0 +1,123 @@
+function showWhoToFollow (panel, reply, aHost, aUser) {
+ var users = reply.ids
+ var cn
+ var index = 0
+ var random = Math.floor(Math.random() * 10)
+ for (cn = random; cn < users.length; cn = cn + 10) {
+ var user
+ user = users[cn]
+ var img
+ if (user.icon) {
+ img = user.icon
+ } else {
+ img = '/images/avi.png'
+ }
+ var name = user.to_id
+ if (index === 0) {
+ panel.img1 = img
+ panel.name1 = name
+ panel.$store.state.api.backendInteractor.externalProfile(name)
+ .then((externalUser) => {
+ if (!externalUser.error) {
+ panel.$store.commit('addNewUsers', [externalUser])
+ panel.id1 = externalUser.id
+ }
+ })
+ } else if (index === 1) {
+ panel.img2 = img
+ panel.name2 = name
+ panel.$store.state.api.backendInteractor.externalProfile(name)
+ .then((externalUser) => {
+ if (!externalUser.error) {
+ panel.$store.commit('addNewUsers', [externalUser])
+ panel.id2 = externalUser.id
+ }
+ })
+ } else if (index === 2) {
+ panel.img3 = img
+ panel.name3 = name
+ panel.$store.state.api.backendInteractor.externalProfile(name)
+ .then((externalUser) => {
+ if (!externalUser.error) {
+ panel.$store.commit('addNewUsers', [externalUser])
+ panel.id3 = externalUser.id
+ }
+ })
+ }
+ index = index + 1
+ if (index > 2) {
+ break
+ }
+ }
+}
+
+function getWhoToFollow (panel) {
+ var user = panel.$store.state.users.currentUser.screen_name
+ if (user) {
+ panel.name1 = 'Loading...'
+ panel.name2 = 'Loading...'
+ panel.name3 = 'Loading...'
+ var host = window.location.hostname
+ var whoToFollowProvider = panel.$store.state.config.whoToFollowProvider
+ var url
+ url = whoToFollowProvider.replace(/{{host}}/g, encodeURIComponent(host))
+ url = url.replace(/{{user}}/g, encodeURIComponent(user))
+ window.fetch(url, {mode: 'cors'}).then(function (response) {
+ if (response.ok) {
+ return response.json()
+ } else {
+ panel.name1 = ''
+ panel.name2 = ''
+ panel.name3 = ''
+ }
+ }).then(function (reply) {
+ showWhoToFollow(panel, reply, host, user)
+ })
+ }
+}
+
+const WhoToFollowPanel = {
+ data: () => ({
+ img1: '/images/avi.png',
+ name1: '',
+ id1: 0,
+ img2: '/images/avi.png',
+ name2: '',
+ id2: 0,
+ img3: '/images/avi.png',
+ name3: '',
+ id3: 0
+ }),
+ computed: {
+ user: function () {
+ return this.$store.state.users.currentUser.screen_name
+ },
+ moreUrl: function () {
+ var host = window.location.hostname
+ var user = this.user
+ var whoToFollowLink = this.$store.state.config.whoToFollowLink
+ var url
+ url = whoToFollowLink.replace(/{{host}}/g, encodeURIComponent(host))
+ url = url.replace(/{{user}}/g, encodeURIComponent(user))
+ return url
+ },
+ showWhoToFollowPanel () {
+ return this.$store.state.config.showWhoToFollowPanel
+ }
+ },
+ watch: {
+ user: function (user, oldUser) {
+ if (this.showWhoToFollowPanel) {
+ getWhoToFollow(this)
+ }
+ }
+ },
+ mounted:
+ function () {
+ if (this.showWhoToFollowPanel) {
+ getWhoToFollow(this)
+ }
+ }
+}
+
+export default WhoToFollowPanel
diff --git a/src/components/who_to_follow_panel/who_to_follow_panel.vue b/src/components/who_to_follow_panel/who_to_follow_panel.vue
new file mode 100644
index 00000000..5af6d0d5
--- /dev/null
+++ b/src/components/who_to_follow_panel/who_to_follow_panel.vue
@@ -0,0 +1,37 @@
+<template>
+ <div class="who-to-follow-panel">
+ <div class="panel panel-default base01-background">
+ <div class="panel-heading timeline-heading base02-background base04">
+ <div class="title">
+ Who to follow
+ </div>
+ </div>
+ <div class="panel-body who-to-follow">
+ <p>
+ <img v-bind:src="img1"/> <router-link :to="{ name: 'user-profile', params: { id: id1 } }">{{ name1 }}</router-link><br>
+ <img v-bind:src="img2"/> <router-link :to="{ name: 'user-profile', params: { id: id2 } }">{{ name2 }}</router-link><br>
+ <img v-bind:src="img3"/> <router-link :to="{ name: 'user-profile', params: { id: id3 } }">{{ name3 }}</router-link><br>
+ <img v-bind:src="$store.state.config.logo"> <a v-bind:href="moreUrl" target="_blank">More</a>
+ </p>
+ </div>
+ </div>
+ </div>
+</template>
+
+<script src="./who_to_follow_panel.js" ></script>
+
+<style lang="scss">
+ .who-to-follow * {
+ vertical-align: middle;
+ }
+ .who-to-follow img {
+ width: 32px;
+ height: 32px;
+ }
+ .who-to-follow p {
+ line-height: 40px;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+</style>