diff --git a/src/App.scss b/src/App.scss index ff7fb5dc6..e4c764bf0 100644 --- a/src/App.scss +++ b/src/App.scss @@ -131,6 +131,7 @@ input, textarea, .select { font-family: sans-serif; font-family: var(--inputFont, sans-serif); font-size: 14px; + margin: 0; padding: 8px .5em; box-sizing: border-box; display: inline-block; @@ -199,6 +200,7 @@ input, textarea, .select { } } + label::before { + flex-shrink: 0; display: inline-block; content: ''; transition: box-shadow 200ms; @@ -235,6 +237,7 @@ input, textarea, .select { } } + label::before { + flex-shrink: 0; display: inline-block; content: '✔'; transition: color 200ms; diff --git a/src/components/emoji-input/emoji-input.js b/src/components/emoji-input/emoji-input.js index 0955a37e3..cd0247df2 100644 --- a/src/components/emoji-input/emoji-input.js +++ b/src/components/emoji-input/emoji-input.js @@ -59,7 +59,8 @@ const EmojiInput = { input: undefined, highlighted: 0, caret: 0, - focused: false + focused: false, + blurTimeout: null } }, computed: { @@ -122,12 +123,12 @@ const EmojiInput = { this.$emit('input', newValue) this.caret = 0 }, - replaceText (e) { + replaceText (e, suggestion) { const len = this.suggestions.length || 0 if (this.textAtCaret.length === 1) { return } - if (len > 0) { - const suggestion = this.suggestions[this.highlighted] - const replacement = suggestion.replacement + if (len > 0 || suggestion) { + const chosenSuggestion = suggestion || this.suggestions[this.highlighted] + const replacement = chosenSuggestion.replacement const newValue = Completion.replaceWord(this.value, this.wordAtCaret, replacement) this.$emit('input', newValue) this.highlighted = 0 @@ -173,13 +174,21 @@ const EmojiInput = { onBlur (e) { // Clicking on any suggestion removes focus from autocomplete, // preventing click handler ever executing. - setTimeout(() => { + this.blurTimeout = setTimeout(() => { this.focused = false this.setCaret(e) this.resize() }, 200) }, + onClick (e, suggestion) { + this.replaceText(e, suggestion) + }, onFocus (e) { + if (this.blurTimeout) { + clearTimeout(this.blurTimeout) + this.blurTimeout = null + } + this.focused = true this.setCaret(e) this.resize() diff --git a/src/components/emoji-input/emoji-input.vue b/src/components/emoji-input/emoji-input.vue index 8437a4959..b1f7afa55 100644 --- a/src/components/emoji-input/emoji-input.vue +++ b/src/components/emoji-input/emoji-input.vue @@ -6,7 +6,7 @@
diff --git a/src/components/gallery/gallery.vue b/src/components/gallery/gallery.vue index ea525c95c..f0433f10f 100644 --- a/src/components/gallery/gallery.vue +++ b/src/components/gallery/gallery.vue @@ -28,7 +28,9 @@ flex-grow: 1; margin-top: 0.5em; - .attachments, .attachment { + // FIXME: specificity problem with this and .attachments.attachment + // we shouldn't have the need for .image here + .attachment.image { margin: 0 0.5em 0 0; flex-grow: 1; height: 100%; diff --git a/src/components/login_form/login_form.js b/src/components/login_form/login_form.js index 932146462..4a5b19655 100644 --- a/src/components/login_form/login_form.js +++ b/src/components/login_form/login_form.js @@ -26,9 +26,10 @@ const LoginForm = { this.isTokenAuth ? this.submitToken() : this.submitPassword() }, submitToken () { - const { clientId } = this.oauth + const { clientId, clientSecret } = this.oauth const data = { clientId, + clientSecret, instance: this.instance.server, commit: this.$store.commit } diff --git a/src/components/oauth_callback/oauth_callback.js b/src/components/oauth_callback/oauth_callback.js index 2c6ca235a..a3c7b7f98 100644 --- a/src/components/oauth_callback/oauth_callback.js +++ b/src/components/oauth_callback/oauth_callback.js @@ -4,10 +4,11 @@ const oac = { props: ['code'], mounted () { if (this.code) { - const { clientId } = this.$store.state.oauth + const { clientId, clientSecret } = this.$store.state.oauth oauth.getToken({ clientId, + clientSecret, instance: this.$store.state.instance.server, code: this.code }).then((result) => { diff --git a/src/components/poll/poll.js b/src/components/poll/poll.js index ecacbc350..98db5582e 100644 --- a/src/components/poll/poll.js +++ b/src/components/poll/poll.js @@ -3,26 +3,39 @@ import { forEach, map } from 'lodash' export default { name: 'Poll', - props: ['poll', 'statusId'], + props: ['basePoll'], components: { Timeago }, data () { return { loading: false, - choices: [], - refreshInterval: null + choices: [] } }, created () { - this.refreshInterval = setTimeout(this.refreshPoll, 30 * 1000) - // Initialize choices to booleans and set its length to match options - this.choices = this.poll.options.map(_ => false) + if (!this.$store.state.polls.pollsObject[this.pollId]) { + this.$store.dispatch('mergeOrAddPoll', this.basePoll) + } + this.$store.dispatch('trackPoll', this.pollId) }, destroyed () { - clearTimeout(this.refreshInterval) + this.$store.dispatch('untrackPoll', this.pollId) }, computed: { + pollId () { + return this.basePoll.id + }, + poll () { + const storePoll = this.$store.state.polls.pollsObject[this.pollId] + return storePoll || {} + }, + options () { + return (this.poll && this.poll.options) || [] + }, + expiresAt () { + return (this.poll && this.poll.expires_at) || 0 + }, expired () { - return Date.now() > Date.parse(this.poll.expires_at) + return (this.poll && this.poll.expired) || false }, loggedIn () { return this.$store.state.users.currentUser @@ -33,9 +46,6 @@ export default { totalVotesCount () { return this.poll.votes_count }, - expiresAt () { - return Date.parse(this.poll.expires_at).toLocaleString() - }, containerClass () { return { loading: this.loading @@ -55,11 +65,6 @@ export default { } }, methods: { - refreshPoll () { - if (this.expired) return - this.fetchPoll() - this.refreshInterval = setTimeout(this.refreshPoll, 30 * 1000) - }, percentageForOption (count) { return this.totalVotesCount === 0 ? 0 : Math.round(count / this.totalVotesCount * 100) }, @@ -104,4 +109,4 @@ export default { }) } } -} \ No newline at end of file +} diff --git a/src/components/poll/poll.vue b/src/components/poll/poll.vue index 28e9f4a86..bb67101af 100644 --- a/src/components/poll/poll.vue +++ b/src/components/poll/poll.vue @@ -2,7 +2,7 @@
@@ -31,8 +31,8 @@ :disabled="loading" :value="index" > -
@@ -50,7 +50,7 @@ {{totalVotesCount}} {{ $t("polls.votes") }} · 
- +
@@ -68,8 +68,7 @@ margin: 0 0 0.5em; } .poll-option { - margin: 0.5em 0; - height: 1.5em; + margin: 0.75em 0.5em; } .option-result { height: 100%; @@ -87,6 +86,7 @@ } .result-percentage { width: 3.5em; + flex-shrink: 0; } .result-fill { height: 100%; @@ -99,6 +99,10 @@ left: 0; transition: width 0.5s; } + .option-vote { + display: flex; + align-items: center; + } input { width: 3.5em; } diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js index 5dbb1c9df..ef6b0fce7 100644 --- a/src/components/post_status_form/post_status_form.js +++ b/src/components/post_status_form/post_status_form.js @@ -269,8 +269,11 @@ const PostStatusForm = { resize (e) { const target = e.target || e if (!(target instanceof window.Element)) { return } - const vertPadding = Number(window.getComputedStyle(target)['padding-top'].substr(0, 1)) + - Number(window.getComputedStyle(target)['padding-bottom'].substr(0, 1)) + const topPaddingStr = window.getComputedStyle(target)['padding-top'] + const bottomPaddingStr = window.getComputedStyle(target)['padding-bottom'] + // Remove "px" at the end of the values + const vertPadding = Number(topPaddingStr.substr(0, topPaddingStr.length - 2)) + + Number(bottomPaddingStr.substr(0, bottomPaddingStr.length - 2)) // Auto is needed to make textbox shrink when removing lines target.style.height = 'auto' target.style.height = `${target.scrollHeight - vertPadding}px` diff --git a/src/components/post_status_form/post_status_form.vue b/src/components/post_status_form/post_status_form.vue index fbeaf39b9..67cdc7218 100644 --- a/src/components/post_status_form/post_status_form.vue +++ b/src/components/post_status_form/post_status_form.vue @@ -48,7 +48,7 @@ +

+ {{ charactersLeft }} +

@@ -109,8 +116,6 @@ />
-

{{ charactersLeft }}

-

{{ charactersLeft }}

@@ -304,10 +309,12 @@ } .form-post-body { - line-height:16px; + height: 16px; // Only affects the empty-height + line-height: 16px; resize: none; overflow: hidden; transition: min-height 200ms 100ms; + padding-bottom: 1.75em; min-height: 1px; box-sizing: content-box; } @@ -316,6 +323,23 @@ min-height: 48px; } + .main-input { + position: relative; + } + + .character-counter { + position: absolute; + bottom: 0; + right: 0; + padding: 0; + margin: 0 0.5em; + + &.error { + color: $fallback--cRed; + color: var(--cRed, $fallback--cRed); + } + } + .btn { cursor: pointer; } diff --git a/src/components/status/status.vue b/src/components/status/status.vue index 58402f7e2..440e19575 100644 --- a/src/components/status/status.vue +++ b/src/components/status/status.vue @@ -124,7 +124,7 @@
- +
diff --git a/src/components/user_profile/user_profile.vue b/src/components/user_profile/user_profile.vue index 48b774eaf..84a159dab 100644 --- a/src/components/user_profile/user_profile.vue +++ b/src/components/user_profile/user_profile.vue @@ -3,7 +3,7 @@
-
+