aboutsummaryrefslogtreecommitdiff
path: root/src/components
diff options
context:
space:
mode:
authorHenry Jameson <me@hjkos.com>2022-06-27 14:49:31 +0300
committerHenry Jameson <me@hjkos.com>2022-06-27 14:49:31 +0300
commit4dc4a912247801733cfc093d6cda38ca48a9d7c4 (patch)
treeafa8a9f93cf4600ce9a549427b1c2c3e877761fe /src/components
parent55e9acc4adcdde0d2a35dfdb73d938634872189b (diff)
parent56501e95c42859a826ad0f0b11de4e6b189b9f92 (diff)
Merge remote-tracking branch 'origin/develop' into disjointed-popovers
* origin/develop: add SK (Slovak) translation ReactButton: Workaround for android composition mode EmojiPicker: Workaround to search immediately on mobile Fix top bar input text colour Show underlay for mobile Fix tests Add English translations for correctly i18nized time units Delegate relativeTime plural rules to vue-i18n restore notifications page, fix z-index issues Make lint happy Add English translations for backup UI Add backup UI Add English translation for list aliases error Log errors when listing aliases Add changelog Add Engilsh translation for migration Add frontend ui for aliases and migration Change translation key Explain better what delete does in moderation menu
Diffstat (limited to 'src/components')
-rw-r--r--src/components/desktop_nav/desktop_nav.scss4
-rw-r--r--src/components/emoji_picker/emoji_picker.js5
-rw-r--r--src/components/emoji_picker/emoji_picker.vue1
-rw-r--r--src/components/notifications/notifications.js4
-rw-r--r--src/components/notifications/notifications.vue2
-rw-r--r--src/components/react_button/react_button.js3
-rw-r--r--src/components/react_button/react_button.vue1
-rw-r--r--src/components/settings_modal/tabs/data_import_export_tab.js29
-rw-r--r--src/components/settings_modal/tabs/data_import_export_tab.vue61
-rw-r--r--src/components/settings_modal/tabs/security_tab/security_tab.js55
-rw-r--r--src/components/settings_modal/tabs/security_tab/security_tab.vue108
-rw-r--r--src/components/timeago/timeago.vue2
-rw-r--r--src/components/timeline/timeline.scss2
13 files changed, 268 insertions, 9 deletions
diff --git a/src/components/desktop_nav/desktop_nav.scss b/src/components/desktop_nav/desktop_nav.scss
index e9a47632..71202244 100644
--- a/src/components/desktop_nav/desktop_nav.scss
+++ b/src/components/desktop_nav/desktop_nav.scss
@@ -4,6 +4,10 @@
width: 100%;
z-index: var(--ZI_navbar);
+ input {
+ color: var(--inputTopbarText, var(--inputText));
+ }
+
a {
color: var(--topBarLink, $fallback--link);
}
diff --git a/src/components/emoji_picker/emoji_picker.js b/src/components/emoji_picker/emoji_picker.js
index 6b589079..bd5c2e39 100644
--- a/src/components/emoji_picker/emoji_picker.js
+++ b/src/components/emoji_picker/emoji_picker.js
@@ -6,6 +6,7 @@ import {
faStickyNote,
faSmileBeam
} from '@fortawesome/free-solid-svg-icons'
+import { trim } from 'lodash'
library.add(
faBoxOpen,
@@ -176,7 +177,7 @@ const EmojiPicker = {
filteredEmoji () {
return filterByKeyword(
this.$store.state.instance.customEmoji || [],
- this.keyword
+ trim(this.keyword)
)
},
customEmojiBuffer () {
@@ -197,7 +198,7 @@ const EmojiPicker = {
id: 'standard',
text: this.$t('emoji.unicode'),
icon: 'box-open',
- emojis: filterByKeyword(standardEmojis, this.keyword)
+ emojis: filterByKeyword(standardEmojis, trim(this.keyword))
}
]
},
diff --git a/src/components/emoji_picker/emoji_picker.vue b/src/components/emoji_picker/emoji_picker.vue
index 3262a3d9..a7269120 100644
--- a/src/components/emoji_picker/emoji_picker.vue
+++ b/src/components/emoji_picker/emoji_picker.vue
@@ -47,6 +47,7 @@
type="text"
class="form-control"
:placeholder="$t('emoji.search_emoji')"
+ @input="$event.target.composing = false"
>
</div>
<div
diff --git a/src/components/notifications/notifications.js b/src/components/notifications/notifications.js
index 63d827d8..0851f407 100644
--- a/src/components/notifications/notifications.js
+++ b/src/components/notifications/notifications.js
@@ -28,7 +28,9 @@ const Notifications = {
// meant for "Interactions" timeline
minimalMode: Boolean,
// Custom filter mode, an array of strings, possible values 'mention', 'repeat', 'like', 'follow', used to override global filter for use in "Interactions" timeline
- filterMode: Array
+ filterMode: Array,
+ // Disable teleporting (i.e. for /users/user/notifications)
+ disableTeleport: Boolean
},
data () {
return {
diff --git a/src/components/notifications/notifications.vue b/src/components/notifications/notifications.vue
index 794ef51d..b46c06aa 100644
--- a/src/components/notifications/notifications.vue
+++ b/src/components/notifications/notifications.vue
@@ -1,5 +1,5 @@
<template>
- <teleport :disabled="minimalMode" :to="teleportTarget">
+ <teleport :disabled="minimalMode || disableTeleport" :to="teleportTarget">
<div
:class="{ minimal: minimalMode }"
class="Notifications"
diff --git a/src/components/react_button/react_button.js b/src/components/react_button/react_button.js
index ce82c90d..e6f9dbff 100644
--- a/src/components/react_button/react_button.js
+++ b/src/components/react_button/react_button.js
@@ -1,6 +1,7 @@
import Popover from '../popover/popover.vue'
import { library } from '@fortawesome/fontawesome-svg-core'
import { faSmileBeam } from '@fortawesome/free-regular-svg-icons'
+import { trim } from 'lodash'
library.add(faSmileBeam)
@@ -43,7 +44,7 @@ const ReactButton = {
},
emojis () {
if (this.filterWord !== '') {
- const filterWordLowercase = this.filterWord.toLowerCase()
+ const filterWordLowercase = trim(this.filterWord.toLowerCase())
let orderedEmojiList = []
for (const emoji of this.$store.state.instance.emoji) {
if (emoji.replacement === this.filterWord) return [emoji]
diff --git a/src/components/react_button/react_button.vue b/src/components/react_button/react_button.vue
index a6541d6f..b76fb244 100644
--- a/src/components/react_button/react_button.vue
+++ b/src/components/react_button/react_button.vue
@@ -13,6 +13,7 @@
<div class="reaction-picker-filter">
<input
v-model="filterWord"
+ @input="$event.target.composing = false"
size="1"
:placeholder="$t('emoji.search_emoji')"
>
diff --git a/src/components/settings_modal/tabs/data_import_export_tab.js b/src/components/settings_modal/tabs/data_import_export_tab.js
index f4b736d2..4895733c 100644
--- a/src/components/settings_modal/tabs/data_import_export_tab.js
+++ b/src/components/settings_modal/tabs/data_import_export_tab.js
@@ -7,11 +7,16 @@ const DataImportExportTab = {
data () {
return {
activeTab: 'profile',
- newDomainToMute: ''
+ newDomainToMute: '',
+ listBackupsError: false,
+ addBackupError: false,
+ addedBackup: false,
+ backups: []
}
},
created () {
this.$store.dispatch('fetchTokens')
+ this.fetchBackups()
},
components: {
Importer,
@@ -72,6 +77,28 @@ const DataImportExportTab = {
}
return user.screen_name
}).join('\n')
+ },
+ addBackup () {
+ this.$store.state.api.backendInteractor.addBackup()
+ .then((res) => {
+ this.addedBackup = true
+ this.addBackupError = false
+ })
+ .catch((error) => {
+ this.addedBackup = false
+ this.addBackupError = error
+ })
+ .then(() => this.fetchBackups())
+ },
+ fetchBackups () {
+ this.$store.state.api.backendInteractor.listBackups()
+ .then((res) => {
+ this.backups = res
+ this.listBackupsError = false
+ })
+ .catch((error) => {
+ this.listBackupsError = error.error
+ })
}
}
}
diff --git a/src/components/settings_modal/tabs/data_import_export_tab.vue b/src/components/settings_modal/tabs/data_import_export_tab.vue
index a406077d..e3b7f407 100644
--- a/src/components/settings_modal/tabs/data_import_export_tab.vue
+++ b/src/components/settings_modal/tabs/data_import_export_tab.vue
@@ -53,6 +53,67 @@
:export-button-label="$t('settings.mute_export_button')"
/>
</div>
+ <div class="setting-item">
+ <h2>{{ $t('settings.account_backup') }}</h2>
+ <p>{{ $t('settings.account_backup_description') }}</p>
+ <table>
+ <thead>
+ <tr>
+ <th>{{ $t('settings.account_backup_table_head') }}</th>
+ <th />
+ </tr>
+ </thead>
+ <tbody>
+ <tr
+ v-for="backup in backups"
+ :key="backup.id"
+ >
+ <td>{{ backup.inserted_at }}</td>
+ <td class="actions">
+ <a
+ v-if="backup.processed"
+ target="_blank"
+ :href="backup.url"
+ >
+ {{ $t('settings.download_backup') }}
+ </a>
+ <span
+ v-else
+ >
+ {{ $t('settings.backup_not_ready') }}
+ </span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ <div
+ v-if="listBackupsError"
+ class="alert error"
+ >
+ {{ $t('settings.list_backups_error', { error }) }}
+ <button
+ :title="$t('settings.hide_list_backups_error_action')"
+ @click="listBackupsError = false"
+ >
+ <FAIcon
+ class="fa-scale-110 fa-old-padding"
+ icon="times"
+ />
+ </button>
+ </div>
+ <button
+ class="btn button-default"
+ @click="addBackup"
+ >
+ {{ $t('settings.add_backup') }}
+ </button>
+ <p v-if="addedBackup">
+ {{ $t('settings.added_backup') }}
+ </p>
+ <template v-if="addBackupError !== false">
+ <p>{{ $t('settings.add_backup_error', { error: addBackupError }) }}</p>
+ </template>
+ </div>
</div>
</template>
diff --git a/src/components/settings_modal/tabs/security_tab/security_tab.js b/src/components/settings_modal/tabs/security_tab/security_tab.js
index 65d20fc0..fc732936 100644
--- a/src/components/settings_modal/tabs/security_tab/security_tab.js
+++ b/src/components/settings_modal/tabs/security_tab/security_tab.js
@@ -15,11 +15,21 @@ const SecurityTab = {
deleteAccountError: false,
changePasswordInputs: [ '', '', '' ],
changedPassword: false,
- changePasswordError: false
+ changePasswordError: false,
+ moveAccountTarget: '',
+ moveAccountPassword: '',
+ movedAccount: false,
+ moveAccountError: false,
+ aliases: [],
+ listAliasesError: false,
+ addAliasTarget: '',
+ addedAlias: false,
+ addAliasError: false
}
},
created () {
this.$store.dispatch('fetchTokens')
+ this.fetchAliases()
},
components: {
ProgressButton,
@@ -92,6 +102,49 @@ const SecurityTab = {
}
})
},
+ moveAccount () {
+ const params = {
+ targetAccount: this.moveAccountTarget,
+ password: this.moveAccountPassword
+ }
+ this.$store.state.api.backendInteractor.moveAccount(params)
+ .then((res) => {
+ if (res.status === 'success') {
+ this.movedAccount = true
+ this.moveAccountError = false
+ } else {
+ this.movedAccount = false
+ this.moveAccountError = res.error
+ }
+ })
+ },
+ removeAlias (alias) {
+ this.$store.state.api.backendInteractor.deleteAlias({ alias })
+ .then(() => this.fetchAliases())
+ },
+ addAlias () {
+ this.$store.state.api.backendInteractor.addAlias({ alias: this.addAliasTarget })
+ .then((res) => {
+ this.addedAlias = true
+ this.addAliasError = false
+ this.addAliasTarget = ''
+ })
+ .catch((error) => {
+ this.addedAlias = false
+ this.addAliasError = error
+ })
+ .then(() => this.fetchAliases())
+ },
+ fetchAliases () {
+ this.$store.state.api.backendInteractor.listAliases()
+ .then((res) => {
+ this.aliases = res.aliases
+ this.listAliasesError = false
+ })
+ .catch((error) => {
+ this.listAliasesError = error.error
+ })
+ },
logout () {
this.$store.dispatch('logout')
this.$router.replace('/')
diff --git a/src/components/settings_modal/tabs/security_tab/security_tab.vue b/src/components/settings_modal/tabs/security_tab/security_tab.vue
index 275d4616..c74a0c67 100644
--- a/src/components/settings_modal/tabs/security_tab/security_tab.vue
+++ b/src/components/settings_modal/tabs/security_tab/security_tab.vue
@@ -103,6 +103,114 @@
</table>
</div>
<mfa />
+
+ <div class="setting-item">
+ <h2>{{ $t('settings.account_alias') }}</h2>
+ <table>
+ <thead>
+ <tr>
+ <th>{{ $t('settings.account_alias_table_head') }}</th>
+ <th />
+ </tr>
+ </thead>
+ <tbody>
+ <tr
+ v-for="alias in aliases"
+ :key="alias"
+ >
+ <td>{{ alias }}</td>
+ <td class="actions">
+ <button
+ class="btn button-default"
+ @click="removeAlias(alias)"
+ >
+ {{ $t('settings.remove_alias') }}
+ </button>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ <div
+ v-if="listAliasesError"
+ class="alert error"
+ >
+ {{ $t('settings.list_aliases_error', { error }) }}
+ <FAIcon
+ class="fa-scale-110 fa-old-padding"
+ icon="times"
+ :title="$t('settings.hide_list_aliases_error_action')"
+ @click="listAliasesError = false"
+ />
+ </div>
+ <div>
+ <i18n
+ path="settings.new_alias_target"
+ tag="p"
+ >
+ <code
+ place="example"
+ >
+ foo@example.org
+ </code>
+ </i18n>
+ <input
+ v-model="addAliasTarget"
+ >
+ </div>
+ <button
+ class="btn button-default"
+ @click="addAlias"
+ >
+ {{ $t('settings.save') }}
+ </button>
+ <p v-if="addedAlias">
+ {{ $t('settings.added_alias') }}
+ </p>
+ <template v-if="addAliasError !== false">
+ <p>{{ $t('settings.add_alias_error', { error: addAliasError }) }}</p>
+ </template>
+ </div>
+
+ <div class="setting-item">
+ <h2>{{ $t('settings.move_account') }}</h2>
+ <p>{{ $t('settings.move_account_notes') }}</p>
+ <div>
+ <i18n
+ path="settings.move_account_target"
+ tag="p"
+ >
+ <code
+ place="example"
+ >
+ foo@example.org
+ </code>
+ </i18n>
+ <input
+ v-model="moveAccountTarget"
+ >
+ </div>
+ <div>
+ <p>{{ $t('settings.current_password') }}</p>
+ <input
+ v-model="moveAccountPassword"
+ type="password"
+ autocomplete="current-password"
+ >
+ </div>
+ <button
+ class="btn button-default"
+ @click="moveAccount"
+ >
+ {{ $t('settings.save') }}
+ </button>
+ <p v-if="movedAccount">
+ {{ $t('settings.moved_account') }}
+ </p>
+ <template v-if="moveAccountError !== false">
+ <p>{{ $t('settings.move_account_error', { error: moveAccountError }) }}</p>
+ </template>
+ </div>
+
<div class="setting-item">
<h2>{{ $t('settings.delete_account') }}</h2>
<p v-if="!deletingAccount">
diff --git a/src/components/timeago/timeago.vue b/src/components/timeago/timeago.vue
index bed29020..2b487dfd 100644
--- a/src/components/timeago/timeago.vue
+++ b/src/components/timeago/timeago.vue
@@ -3,7 +3,7 @@
:datetime="time"
:title="localeDateString"
>
- {{ $t(relativeTime.key, [relativeTime.num]) }}
+ {{ $tc(relativeTime.key, relativeTime.num, [relativeTime.num]) }}
</time>
</template>
diff --git a/src/components/timeline/timeline.scss b/src/components/timeline/timeline.scss
index c7ea0dff..9e009fd3 100644
--- a/src/components/timeline/timeline.scss
+++ b/src/components/timeline/timeline.scss
@@ -11,7 +11,7 @@
.conversation-heading {
top: calc(var(--__panel-heading-height) * var(--currentPanelStack, 2));
- z-index: 1;
+ z-index: 2;
}
&.-nonpanel {