+
-
+
@@ -44,14 +48,15 @@
width: 16px;
vertical-align: middle;
}
+ }
- &-value {
- display: inline-block;
- max-width: 100%;
- overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
- }
+ &-user-name-value,
+ &-screen-name {
+ display: inline-block;
+ max-width: 100%;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
}
&-expanded-content {
diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js
index 30600f73..ffeb7244 100644
--- a/src/components/conversation/conversation.js
+++ b/src/components/conversation/conversation.js
@@ -139,6 +139,7 @@ const conversation = {
},
setHighlight (id) {
this.highlight = id
+ this.$store.dispatch('fetchFavsAndRepeats', id)
},
getHighlight () {
return this.isExpanded ? this.highlight : null
diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue
index c3bbb597..d04ff722 100644
--- a/src/components/conversation/conversation.vue
+++ b/src/components/conversation/conversation.vue
@@ -11,7 +11,7 @@
@goto="setHighlight"
@toggleExpanded="toggleExpanded"
:key="status.id"
- :inlineExpanded="collapsable"
+ :inlineExpanded="collapsable && isExpanded"
:statusoid="status"
:expandable='!isExpanded'
:focused="focused(status.id)"
diff --git a/src/components/exporter/exporter.js b/src/components/exporter/exporter.js
new file mode 100644
index 00000000..8f507416
--- /dev/null
+++ b/src/components/exporter/exporter.js
@@ -0,0 +1,48 @@
+const Exporter = {
+ props: {
+ getContent: {
+ type: Function,
+ required: true
+ },
+ filename: {
+ type: String,
+ default: 'export.csv'
+ },
+ exportButtonLabel: {
+ type: String,
+ default () {
+ return this.$t('exporter.export')
+ }
+ },
+ processingMessage: {
+ type: String,
+ default () {
+ return this.$t('exporter.processing')
+ }
+ }
+ },
+ data () {
+ return {
+ processing: false
+ }
+ },
+ methods: {
+ process () {
+ this.processing = true
+ this.getContent()
+ .then((content) => {
+ const fileToDownload = document.createElement('a')
+ fileToDownload.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(content))
+ fileToDownload.setAttribute('download', this.filename)
+ fileToDownload.style.display = 'none'
+ document.body.appendChild(fileToDownload)
+ fileToDownload.click()
+ document.body.removeChild(fileToDownload)
+ // Add delay before hiding processing state since browser takes some time to handle file download
+ setTimeout(() => { this.processing = false }, 2000)
+ })
+ }
+ }
+}
+
+export default Exporter
diff --git a/src/components/exporter/exporter.vue b/src/components/exporter/exporter.vue
new file mode 100644
index 00000000..f22e579e
--- /dev/null
+++ b/src/components/exporter/exporter.vue
@@ -0,0 +1,20 @@
+
+
+
-
-
-
-
-
+
@@ -46,6 +48,7 @@
+
diff --git a/src/components/avatar_list/avatar_list.js b/src/components/avatar_list/avatar_list.js
new file mode 100644
index 00000000..9b6301b2
--- /dev/null
+++ b/src/components/avatar_list/avatar_list.js
@@ -0,0 +1,21 @@
+import UserAvatar from '../user_avatar/user_avatar.vue'
+import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
+
+const AvatarList = {
+ props: ['users'],
+ computed: {
+ slicedUsers () {
+ return this.users ? this.users.slice(0, 15) : []
+ }
+ },
+ components: {
+ UserAvatar
+ },
+ methods: {
+ userProfileLink (user) {
+ return generateProfileLink(user.id, user.screen_name, this.$store.state.instance.restrictedNicknames)
+ }
+ }
+}
+
+export default AvatarList
diff --git a/src/components/avatar_list/avatar_list.vue b/src/components/avatar_list/avatar_list.vue
new file mode 100644
index 00000000..c0238570
--- /dev/null
+++ b/src/components/avatar_list/avatar_list.vue
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/basic_user_card/basic_user_card.vue b/src/components/basic_user_card/basic_user_card.vue
index 48de6678..634d62b3 100644
--- a/src/components/basic_user_card/basic_user_card.vue
+++ b/src/components/basic_user_card/basic_user_card.vue
@@ -1,7 +1,11 @@
+
+
+
+
+
+
diff --git a/src/components/image_cropper/image_cropper.js b/src/components/image_cropper/image_cropper.js
index 5ba8f04e..01361e25 100644
--- a/src/components/image_cropper/image_cropper.js
+++ b/src/components/image_cropper/image_cropper.js
@@ -70,22 +70,10 @@ const ImageCropper = {
this.dataUrl = undefined
this.$emit('close')
},
- submit () {
+ submit (cropping = true) {
this.submitting = true
this.avatarUploadError = null
- this.submitHandler(this.cropper, this.file)
- .then(() => this.destroy())
- .catch((err) => {
- this.submitError = err
- })
- .finally(() => {
- this.submitting = false
- })
- },
- submitWithoutCropping () {
- this.submitting = true
- this.avatarUploadError = null
- this.submitHandler(false, this.dataUrl)
+ this.submitHandler(cropping && this.cropper, this.file)
.then(() => this.destroy())
.catch((err) => {
this.submitError = err
diff --git a/src/components/image_cropper/image_cropper.vue b/src/components/image_cropper/image_cropper.vue
index 129e6f46..d2b86e9e 100644
--- a/src/components/image_cropper/image_cropper.vue
+++ b/src/components/image_cropper/image_cropper.vue
@@ -5,9 +5,9 @@
+
+ {{processingMessage}}
+
+
+
-
+
-
+
diff --git a/src/components/importer/importer.js b/src/components/importer/importer.js
new file mode 100644
index 00000000..c5f9e4d2
--- /dev/null
+++ b/src/components/importer/importer.js
@@ -0,0 +1,53 @@
+const Importer = {
+ props: {
+ submitHandler: {
+ type: Function,
+ required: true
+ },
+ submitButtonLabel: {
+ type: String,
+ default () {
+ return this.$t('importer.submit')
+ }
+ },
+ successMessage: {
+ type: String,
+ default () {
+ return this.$t('importer.success')
+ }
+ },
+ errorMessage: {
+ type: String,
+ default () {
+ return this.$t('importer.error')
+ }
+ }
+ },
+ data () {
+ return {
+ file: null,
+ error: false,
+ success: false,
+ submitting: false
+ }
+ },
+ methods: {
+ change () {
+ this.file = this.$refs.input.files[0]
+ },
+ submit () {
+ this.dismiss()
+ this.submitting = true
+ this.submitHandler(this.file)
+ .then(() => { this.success = true })
+ .catch(() => { this.error = true })
+ .finally(() => { this.submitting = false })
+ },
+ dismiss () {
+ this.success = false
+ this.error = false
+ }
+ }
+}
+
+export default Importer
diff --git a/src/components/importer/importer.vue b/src/components/importer/importer.vue
new file mode 100644
index 00000000..0c5aa93d
--- /dev/null
+++ b/src/components/importer/importer.vue
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/media_modal/media_modal.vue b/src/components/media_modal/media_modal.vue
index 7f666603..a4c12d74 100644
--- a/src/components/media_modal/media_modal.vue
+++ b/src/components/media_modal/media_modal.vue
@@ -33,6 +33,8 @@
@import '../../_variables.scss';
.media-modal-view {
+ z-index: 1001;
+
&:hover {
.modal-view-button-arrow {
opacity: 0.75;
diff --git a/src/components/mobile_nav/mobile_nav.js b/src/components/mobile_nav/mobile_nav.js
index bc63d2ba..9b341a3b 100644
--- a/src/components/mobile_nav/mobile_nav.js
+++ b/src/components/mobile_nav/mobile_nav.js
@@ -63,6 +63,11 @@ const MobileNav = {
},
markNotificationsAsSeen () {
this.$refs.notifications.markAsSeen()
+ },
+ onScroll ({ target: { scrollTop, clientHeight, scrollHeight } }) {
+ if (this.$store.state.config.autoLoad && scrollTop + clientHeight >= scrollHeight) {
+ this.$refs.notifications.fetchOlderNotifications()
+ }
}
},
watch: {
diff --git a/src/components/mobile_nav/mobile_nav.vue b/src/components/mobile_nav/mobile_nav.vue
index 5fa41638..90707ce7 100644
--- a/src/components/mobile_nav/mobile_nav.vue
+++ b/src/components/mobile_nav/mobile_nav.vue
@@ -1,25 +1,26 @@
-
+
+
+ {{successMessage}}
+
+
+
+ {{errorMessage}}
+