From 8ee50f9f160cab1a0eec3dfddd31de26c3993092 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Mon, 7 Oct 2019 00:05:21 +0300
Subject: replace checkboxes in user-settings with Checkbox component

---
 src/components/user_settings/user_settings.vue | 118 ++++++++-----------------
 1 file changed, 39 insertions(+), 79 deletions(-)

(limited to 'src/components/user_settings/user_settings.vue')

diff --git a/src/components/user_settings/user_settings.vue b/src/components/user_settings/user_settings.vue
index ef75ac52..423589fa 100644
--- a/src/components/user_settings/user_settings.vue
+++ b/src/components/user_settings/user_settings.vue
@@ -53,12 +53,9 @@
               />
             </EmojiInput>
             <p>
-              <input
-                id="account-locked"
-                v-model="newLocked"
-                type="checkbox"
-              >
-              <label for="account-locked">{{ $t('settings.lock_account_description') }}</label>
+              <Checkbox v-model="newLocked">
+                {{ $t('settings.lock_account_description') }}
+              </Checkbox>
             </p>
             <div>
               <label for="default-vis">{{ $t('settings.default_vis') }}</label>
@@ -75,69 +72,52 @@
               </div>
             </div>
             <p>
-              <input
-                id="account-no-rich-text"
-                v-model="newNoRichText"
-                type="checkbox"
-              >
-              <label for="account-no-rich-text">{{ $t('settings.no_rich_text_description') }}</label>
+              <Checkbox v-model="newNoRichText">
+                {{ $t('settings.no_rich_text_description') }}
+              </Checkbox>
             </p>
             <p>
-              <input
-                id="account-hide-follows"
-                v-model="hideFollows"
-                type="checkbox"
-              >
-              <label for="account-hide-follows">{{ $t('settings.hide_follows_description') }}</label>
+              <Checkbox v-model="hideFollows">
+                {{ $t('settings.hide_follows_description') }}
+              </Checkbox>
             </p>
             <p class="setting-subitem">
-              <input
-                id="account-hide-follows-count"
+              <Checkbox
                 v-model="hideFollowsCount"
-                type="checkbox"
                 :disabled="!hideFollows"
-              >
-              <label for="account-hide-follows-count">{{ $t('settings.hide_follows_count_description') }}</label>
+                >
+                {{ $t('settings.hide_follows_count_description') }}
+              </Checkbox>
             </p>
             <p>
-              <input
-                id="account-hide-followers"
+              <Checkbox
                 v-model="hideFollowers"
-                type="checkbox"
-              >
-              <label for="account-hide-followers">{{ $t('settings.hide_followers_description') }}</label>
+                >
+                {{ $t('settings.hide_followers_description') }}
+              </Checkbox>
             </p>
             <p class="setting-subitem">
-              <input
-                id="account-hide-followers-count"
+              <Checkbox
                 v-model="hideFollowersCount"
-                type="checkbox"
                 :disabled="!hideFollowers"
               >
-              <label for="account-hide-followers-count">{{ $t('settings.hide_followers_count_description') }}</label>
+                {{ $t('settings.hide_followers_count_description') }}
+              </Checkbox>
             </p>
             <p>
-              <input
-                id="account-show-role"
-                v-model="showRole"
-                type="checkbox"
-              >
-              <label
-                v-if="role === 'admin'"
-                for="account-show-role"
-              >{{ $t('settings.show_admin_badge') }}</label>
-              <label
-                v-if="role === 'moderator'"
-                for="account-show-role"
-              >{{ $t('settings.show_moderator_badge') }}</label>
+              <Checkbox v-model="showRole">
+                <template v-if="role === 'admin'">
+                  {{ $t('settings.show_admin_badge') }}
+                </template>
+                <template v-if="role === 'moderator'">
+                  {{ $t('settings.show_moderator_badge') }}
+                </template>
+              </Checkbox>
             </p>
             <p>
-              <input
-                id="discoverable"
-                v-model="discoverable"
-                type="checkbox"
-              >
-              <label for="discoverable">{{ $t('settings.discoverable') }}</label>
+              <Checkbox v-model="discoverable">
+                {{ $t('settings.discoverable') }}
+              </Checkbox>
             </p>
             <button
               :disabled="newName && newName.length === 0"
@@ -367,44 +347,24 @@
               <span class="label">{{ $t('settings.notification_setting') }}</span>
               <ul class="option-list">
                 <li>
-                  <input
-                    id="notification-setting-follows"
-                    v-model="notificationSettings.follows"
-                    type="checkbox"
-                  >
-                  <label for="notification-setting-follows">
+                  <Checkbox v-model="notificationSettings.follows">
                     {{ $t('settings.notification_setting_follows') }}
-                  </label>
+                  </Checkbox>
                 </li>
                 <li>
-                  <input
-                    id="notification-setting-followers"
-                    v-model="notificationSettings.followers"
-                    type="checkbox"
-                  >
-                  <label for="notification-setting-followers">
+                  <Checkbox v-model="notificationSettings.followers">
                     {{ $t('settings.notification_setting_followers') }}
-                  </label>
+                  </Checkbox>
                 </li>
                 <li>
-                  <input
-                    id="notification-setting-non-follows"
-                    v-model="notificationSettings.non_follows"
-                    type="checkbox"
-                  >
-                  <label for="notification-setting-non-follows">
+                  <Checkbox v-model="notificationSettings.non_follows">
                     {{ $t('settings.notification_setting_non_follows') }}
-                  </label>
+                  </Checkbox>
                 </li>
                 <li>
-                  <input
-                    id="notification-setting-non-followers"
-                    v-model="notificationSettings.non_followers"
-                    type="checkbox"
-                  >
-                  <label for="notification-setting-non-followers">
+                  <Checkbox v-model="notificationSettings.non_followers">
                     {{ $t('settings.notification_setting_non_followers') }}
-                  </label>
+                  </Checkbox>
                 </li>
               </ul>
             </div>
-- 
cgit v1.2.3-70-g09d2


From c79b2501d275d8d022c6a9a2810211f606f14cde Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Tue, 29 Oct 2019 09:35:42 +0200
Subject: fix indentation

---
 src/components/checkbox/checkbox.vue           | 4 ++--
 src/components/user_settings/user_settings.vue | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

(limited to 'src/components/user_settings/user_settings.vue')

diff --git a/src/components/checkbox/checkbox.vue b/src/components/checkbox/checkbox.vue
index 6e164c1b..5917598a 100644
--- a/src/components/checkbox/checkbox.vue
+++ b/src/components/checkbox/checkbox.vue
@@ -2,7 +2,7 @@
   <label
     class="checkbox"
     :class="{ disabled, indeterminate }"
-    >
+  >
     <input
       type="checkbox"
       :disabled="disabled"
@@ -14,7 +14,7 @@
     <span
       class="label"
       v-if="!!$slots.default"
-      >
+    >
       <slot />
     </span>
   </label>
diff --git a/src/components/user_settings/user_settings.vue b/src/components/user_settings/user_settings.vue
index 423589fa..adf11907 100644
--- a/src/components/user_settings/user_settings.vue
+++ b/src/components/user_settings/user_settings.vue
@@ -92,7 +92,7 @@
             <p>
               <Checkbox
                 v-model="hideFollowers"
-                >
+              >
                 {{ $t('settings.hide_followers_description') }}
               </Checkbox>
             </p>
-- 
cgit v1.2.3-70-g09d2


From e3381cdef1b410aafce15f2d2f1caeccbfae7c87 Mon Sep 17 00:00:00 2001
From: Sergey Suprunenko <suprunenko.s@gmail.com>
Date: Fri, 8 Nov 2019 02:21:19 +0000
Subject: Add ability to change user's email

---
 CHANGELOG.md                                       |  5 ++--
 src/components/user_settings/user_settings.js      | 20 +++++++++++++
 src/components/user_settings/user_settings.vue     | 35 +++++++++++++++++++++-
 src/i18n/en.json                                   |  4 +++
 src/i18n/ru.json                                   |  4 +++
 src/services/api/api.service.js                    | 16 ++++++++++
 .../backend_interactor_service.js                  |  2 ++
 7 files changed, 83 insertions(+), 3 deletions(-)

(limited to 'src/components/user_settings/user_settings.vue')

diff --git a/CHANGELOG.md b/CHANGELOG.md
index d08da09e..2719edcf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,14 +1,15 @@
 # Changelog
 All notable changes to this project will be documented in this file.
 
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 
 ## [Unreleased]
 ### Added
 - Ability to hide/show repeats from user
-- User profile button clutter organized into a menu 
+- User profile button clutter organized into a menu
 - Emoji picker
 - Started changelog anew
+- Ability to change user's email
 ### Changed
 - changed the way fading effects for user profile/long statuses works, now uses css-mask instead of gradient background hacks which weren't exactly compatible with semi-transparent themes
 ### Fixed
diff --git a/src/components/user_settings/user_settings.js b/src/components/user_settings/user_settings.js
index 32eb802e..3fdc5340 100644
--- a/src/components/user_settings/user_settings.js
+++ b/src/components/user_settings/user_settings.js
@@ -35,6 +35,7 @@ const MuteList = withSubscription({
 const UserSettings = {
   data () {
     return {
+      newEmail: '',
       newName: this.$store.state.users.currentUser.name,
       newBio: unescape(this.$store.state.users.currentUser.description),
       newLocked: this.$store.state.users.currentUser.locked,
@@ -56,6 +57,9 @@ const UserSettings = {
       backgroundPreview: null,
       bannerUploadError: null,
       backgroundUploadError: null,
+      changeEmailError: false,
+      changeEmailPassword: '',
+      changedEmail: false,
       deletingAccount: false,
       deleteAccountConfirmPasswordInput: '',
       deleteAccountError: false,
@@ -305,6 +309,22 @@ const UserSettings = {
           }
         })
     },
+    changeEmail () {
+      const params = {
+        email: this.newEmail,
+        password: this.changeEmailPassword
+      }
+      this.$store.state.api.backendInteractor.changeEmail(params)
+        .then((res) => {
+          if (res.status === 'success') {
+            this.changedEmail = true
+            this.changeEmailError = false
+          } else {
+            this.changedEmail = false
+            this.changeEmailError = res.error
+          }
+        })
+    },
     activateTab (tabName) {
       this.activeTab = tabName
     },
diff --git a/src/components/user_settings/user_settings.vue b/src/components/user_settings/user_settings.vue
index adf11907..8c18cf49 100644
--- a/src/components/user_settings/user_settings.vue
+++ b/src/components/user_settings/user_settings.vue
@@ -85,7 +85,7 @@
               <Checkbox
                 v-model="hideFollowsCount"
                 :disabled="!hideFollows"
-                >
+              >
                 {{ $t('settings.hide_follows_count_description') }}
               </Checkbox>
             </p>
@@ -233,6 +233,39 @@
         </div>
 
         <div :label="$t('settings.security_tab')">
+          <div class="setting-item">
+            <h2>{{ $t('settings.change_email') }}</h2>
+            <div>
+              <p>{{ $t('settings.new_email') }}</p>
+              <input
+                v-model="newEmail"
+                type="email"
+                autocomplete="email"
+              >
+            </div>
+            <div>
+              <p>{{ $t('settings.current_password') }}</p>
+              <input
+                v-model="changeEmailPassword"
+                type="password"
+                autocomplete="current-password"
+              >
+            </div>
+            <button
+              class="btn btn-default"
+              @click="changeEmail"
+            >
+              {{ $t('general.submit') }}
+            </button>
+            <p v-if="changedEmail">
+              {{ $t('settings.changed_email') }}
+            </p>
+            <template v-if="changeEmailError !== false">
+              <p>{{ $t('settings.change_email_error') }}</p>
+              <p>{{ changeEmailError }}</p>
+            </template>
+          </div>
+
           <div class="setting-item">
             <h2>{{ $t('settings.change_password') }}</h2>
             <div>
diff --git a/src/i18n/en.json b/src/i18n/en.json
index d11b2d14..7afe7857 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -217,6 +217,9 @@
     "cGreen": "Green (Retweet)",
     "cOrange": "Orange (Favorite)",
     "cRed": "Red (Cancel)",
+    "change_email": "Change Email",
+    "change_email_error": "There was an issue changing your email.",
+    "changed_email": "Email changed successfully!",
     "change_password": "Change Password",
     "change_password_error": "There was an issue changing your password.",
     "changed_password": "Password changed successfully!",
@@ -275,6 +278,7 @@
     "use_contain_fit": "Don't crop the attachment in thumbnails",
     "name": "Name",
     "name_bio": "Name & Bio",
+    "new_email": "New Email",
     "new_password": "New password",
     "notification_visibility": "Types of notifications to show",
     "notification_visibility_follows": "Follows",
diff --git a/src/i18n/ru.json b/src/i18n/ru.json
index 16268425..f8bcd996 100644
--- a/src/i18n/ru.json
+++ b/src/i18n/ru.json
@@ -127,6 +127,9 @@
     "cGreen": "Повторить",
     "cOrange": "Нравится",
     "cRed": "Отменить",
+    "change_email": "Сменить email",
+    "change_email_error": "Произошла ошибка при попытке изменить email.",
+    "changed_email": "Email изменён успешно.",
     "change_password": "Сменить пароль",
     "change_password_error": "Произошла ошибка при попытке изменить пароль.",
     "changed_password": "Пароль изменён успешно.",
@@ -169,6 +172,7 @@
     "loop_video_silent_only": "Зацикливать только беззвучные видео (т.е. \"гифки\" с Mastodon)",
     "name": "Имя",
     "name_bio": "Имя и описание",
+    "new_email": "Новый email",
     "new_password": "Новый пароль",
     "notification_visibility": "Показывать уведомления",
     "notification_visibility_follows": "Подписки",
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index 61cd4f16..68c4939a 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -8,6 +8,7 @@ const QVITTER_USER_NOTIFICATIONS_READ_URL = '/api/qvitter/statuses/notifications
 const BLOCKS_IMPORT_URL = '/api/pleroma/blocks_import'
 const FOLLOW_IMPORT_URL = '/api/pleroma/follow_import'
 const DELETE_ACCOUNT_URL = '/api/pleroma/delete_account'
+const CHANGE_EMAIL_URL = '/api/pleroma/change_email'
 const CHANGE_PASSWORD_URL = '/api/pleroma/change_password'
 const TAG_USER_URL = '/api/pleroma/admin/users/tag'
 const PERMISSION_GROUP_URL = (screenName, right) => `/api/pleroma/admin/users/${screenName}/permission_group/${right}`
@@ -691,6 +692,20 @@ const deleteAccount = ({ credentials, password }) => {
     .then((response) => response.json())
 }
 
+const changeEmail = ({ credentials, email, password }) => {
+  const form = new FormData()
+
+  form.append('email', email)
+  form.append('password', password)
+
+  return fetch(CHANGE_EMAIL_URL, {
+    body: form,
+    method: 'POST',
+    headers: authHeaders(credentials)
+  })
+    .then((response) => response.json())
+}
+
 const changePassword = ({ credentials, password, newPassword, newPasswordConfirmation }) => {
   const form = new FormData()
 
@@ -966,6 +981,7 @@ const apiService = {
   importBlocks,
   importFollows,
   deleteAccount,
+  changeEmail,
   changePassword,
   settingsMFA,
   mfaDisableOTP,
diff --git a/src/services/backend_interactor_service/backend_interactor_service.js b/src/services/backend_interactor_service/backend_interactor_service.js
index cbf48ee4..d6617276 100644
--- a/src/services/backend_interactor_service/backend_interactor_service.js
+++ b/src/services/backend_interactor_service/backend_interactor_service.js
@@ -131,6 +131,7 @@ const backendInteractorService = credentials => {
   const importFollows = (file) => apiService.importFollows({ file, credentials })
 
   const deleteAccount = ({ password }) => apiService.deleteAccount({ credentials, password })
+  const changeEmail = ({ email, password }) => apiService.changeEmail({ credentials, email, password })
   const changePassword = ({ password, newPassword, newPasswordConfirmation }) =>
     apiService.changePassword({ credentials, password, newPassword, newPasswordConfirmation })
 
@@ -195,6 +196,7 @@ const backendInteractorService = credentials => {
     importBlocks,
     importFollows,
     deleteAccount,
+    changeEmail,
     changePassword,
     fetchSettingsMFA,
     generateMfaBackupCodes,
-- 
cgit v1.2.3-70-g09d2

