From 50f0d216861bfce22c98caec7dd00bf8d9dc4a70 Mon Sep 17 00:00:00 2001 From: Edijs <iamedijs@hotmail.com> Date: Thu, 14 Feb 2019 09:52:23 -0700 Subject: [PATCH 01/31] Use static height if gallery has single image --- src/components/gallery/gallery.js | 4 +++- src/components/gallery/gallery.vue | 7 ++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/components/gallery/gallery.js b/src/components/gallery/gallery.js index 7f33a81b86..c713ce07bb 100644 --- a/src/components/gallery/gallery.js +++ b/src/components/gallery/gallery.js @@ -34,7 +34,9 @@ const Gallery = { return rows }, rowHeight () { - return itemsPerRow => ({ 'height': `${(this.width / (itemsPerRow + 0.6))}px` }) + return itemsPerRow => ({ + 'height': this.attachments.length === 1 ? '260px' : `${(this.width / (itemsPerRow + 0.6))}px` + }) }, useContainFit () { return this.$store.state.config.useContainFit diff --git a/src/components/gallery/gallery.vue b/src/components/gallery/gallery.vue index 3f90caa99f..90888c21bf 100644 --- a/src/components/gallery/gallery.vue +++ b/src/components/gallery/gallery.vue @@ -1,6 +1,11 @@ <template> <div ref="galleryContainer" style="width: 100%;"> - <div class="gallery-row" v-for="row in rows" :style="rowHeight(row.length)" :class="{ 'contain-fit': useContainFit, 'cover-fit': !useContainFit }"> + <div + v-for="(row, row_num) in rows" + :key="row_num" + :style="rowHeight(row.length)" + :class="{ 'gallery-row': true, 'contain-fit': useContainFit, 'cover-fit': !useContainFit }" + > <attachment v-for="attachment in row" :setMedia="setMedia" -- GitLab From 28660d698650d3a4fd8bda08b694444e88d7afda Mon Sep 17 00:00:00 2001 From: Edijs <iamedijs@hotmail.com> Date: Thu, 14 Feb 2019 10:21:10 -0700 Subject: [PATCH 02/31] Issue #335 - place hide button on right hand --- src/components/attachment/attachment.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/attachment/attachment.vue b/src/components/attachment/attachment.vue index 7e972026e7..a93c901457 100644 --- a/src/components/attachment/attachment.vue +++ b/src/components/attachment/attachment.vue @@ -160,6 +160,7 @@ .hider { position: absolute; + right: 0; white-space: nowrap; margin: 10px; padding: 5px; -- GitLab From 6c8ccf2733c780543a9afc5ffbe7942064ad2596 Mon Sep 17 00:00:00 2001 From: jasper <jasper92341@hotmail.com> Date: Fri, 15 Feb 2019 07:52:34 -0800 Subject: [PATCH 03/31] Remove posts immediately by blocking --- .../user_card_content/user_card_content.js | 36 ++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/src/components/user_card_content/user_card_content.js b/src/components/user_card_content/user_card_content.js index 7a7b89d490..41e4e8176b 100644 --- a/src/components/user_card_content/user_card_content.js +++ b/src/components/user_card_content/user_card_content.js @@ -93,27 +93,55 @@ export default { }, methods: { followUser () { + const store = this.$store this.followRequestInProgress = true - requestFollow(this.user, this.$store).then(({sent}) => { + requestFollow(this.user, store).then(({sent}) => { this.followRequestInProgress = false this.followRequestSent = sent + + store.dispatch('stopFetching', 'friends') + store.commit('clearTimeline', { timeline: 'friends' }) + store.dispatch('startFetching', { timeline: 'friends' }) }) }, unfollowUser () { + const store = this.$store this.followRequestInProgress = true - requestUnfollow(this.user, this.$store).then(() => { + requestUnfollow(this.user, store).then(() => { this.followRequestInProgress = false + + store.dispatch('stopFetching', 'friends') + store.commit('clearTimeline', { timeline: 'friends' }) + store.dispatch('startFetching', { timeline: 'friends' }) }) }, blockUser () { const store = this.$store store.state.api.backendInteractor.blockUser(this.user.id) - .then((blockedUser) => store.commit('addNewUsers', [blockedUser])) + .then((blockedUser) => { + store.commit('addNewUsers', [blockedUser]) + + store.dispatch('stopFetching', 'friends') + store.commit('clearTimeline', { timeline: 'friends' }) + store.dispatch('startFetching', { timeline: 'friends' }) + + store.commit('clearTimeline', { timeline: 'public' }) + store.commit('clearTimeline', { timeline: 'publicAndExternal' }) + }) }, unblockUser () { const store = this.$store store.state.api.backendInteractor.unblockUser(this.user.id) - .then((unblockedUser) => store.commit('addNewUsers', [unblockedUser])) + .then((unblockedUser) => { + store.commit('addNewUsers', [unblockedUser]) + + store.dispatch('stopFetching', 'friends') + store.commit('clearTimeline', { timeline: 'friends' }) + store.dispatch('startFetching', { timeline: 'friends' }) + + store.commit('clearTimeline', { timeline: 'public' }) + store.commit('clearTimeline', { timeline: 'publicAndExternal' }) + }) }, toggleMute () { const store = this.$store -- GitLab From 24d7f9917b1a4a147b92bd31ec65511c1d528c6f Mon Sep 17 00:00:00 2001 From: jasper <jasper92341@hotmail.com> Date: Mon, 18 Feb 2019 11:39:35 -0800 Subject: [PATCH 04/31] Remove posts by blocking or following --- .../user_card_content/user_card_content.js | 71 ++++++++++++++----- src/modules/statuses.js | 23 ++++++ src/services/api/api.service.js | 7 +- 3 files changed, 80 insertions(+), 21 deletions(-) diff --git a/src/components/user_card_content/user_card_content.js b/src/components/user_card_content/user_card_content.js index 41e4e8176b..8bc01941e0 100644 --- a/src/components/user_card_content/user_card_content.js +++ b/src/components/user_card_content/user_card_content.js @@ -1,4 +1,5 @@ import UserAvatar from '../user_avatar/user_avatar.vue' +import apiService from '../../services/api/api.service.js' import { hex2rgb } from '../../services/color_convert/color_convert.js' import { requestFollow, requestUnfollow } from '../../services/follow_manipulate/follow_manipulate' import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator' @@ -99,9 +100,24 @@ export default { this.followRequestInProgress = false this.followRequestSent = sent - store.dispatch('stopFetching', 'friends') - store.commit('clearTimeline', { timeline: 'friends' }) - store.dispatch('startFetching', { timeline: 'friends' }) + const rootState = store.rootState || store.state + const credentials = store.state.users.currentUser.credentials + const timelineData = rootState.statuses.timelines['friends'] + apiService.fetchTimeline({ + store, + credentials, + userId: this.user.id, + timeline: 'user', + between: true, + until: timelineData.maxId, + since: timelineData.minVisibleId + }).then((statuses) => { + store.dispatch('addNewStatuses', { + timeline: 'friends', + statuses, + showImmediately: true + }) + }, () => store.dispatch('setError', { value: true })) }) }, unfollowUser () { @@ -110,9 +126,7 @@ export default { requestUnfollow(this.user, store).then(() => { this.followRequestInProgress = false - store.dispatch('stopFetching', 'friends') - store.commit('clearTimeline', { timeline: 'friends' }) - store.dispatch('startFetching', { timeline: 'friends' }) + store.commit('removeStatus', { timeline: 'friends', userId: this.user.id }) }) }, blockUser () { @@ -121,12 +135,9 @@ export default { .then((blockedUser) => { store.commit('addNewUsers', [blockedUser]) - store.dispatch('stopFetching', 'friends') - store.commit('clearTimeline', { timeline: 'friends' }) - store.dispatch('startFetching', { timeline: 'friends' }) - - store.commit('clearTimeline', { timeline: 'public' }) - store.commit('clearTimeline', { timeline: 'publicAndExternal' }) + store.commit('removeStatus', { timeline: 'friends', userId: this.user.id }) + store.commit('removeStatus', { timeline: 'public', userId: this.user.id }) + store.commit('removeStatus', { timeline: 'publicAndExternal', userId: this.user.id }) }) }, unblockUser () { @@ -135,12 +146,36 @@ export default { .then((unblockedUser) => { store.commit('addNewUsers', [unblockedUser]) - store.dispatch('stopFetching', 'friends') - store.commit('clearTimeline', { timeline: 'friends' }) - store.dispatch('startFetching', { timeline: 'friends' }) - - store.commit('clearTimeline', { timeline: 'public' }) - store.commit('clearTimeline', { timeline: 'publicAndExternal' }) + const rootState = store.rootState || store.state + const credentials = store.state.users.currentUser.credentials + const timelineData = rootState.statuses.timelines['friends'] + apiService.fetchTimeline({ + store, + credentials, + userId: this.user.id, + timeline: 'user', + between: true, + until: timelineData.maxId, + since: timelineData.minVisibleId + }).then((statuses) => { + store.dispatch('addNewStatuses', { + timeline: 'public', + statuses, + showImmediately: true + }) + store.dispatch('addNewStatuses', { + timeline: 'publicAndExternal', + statuses, + showImmediately: true + }) + if (this.user.follows_you) { + store.dispatch('addNewStatuses', { + timeline: 'friends', + statuses, + showImmediately: true + }) + } + }, () => store.dispatch('setError', { value: true })) }) }, toggleMute () { diff --git a/src/modules/statuses.js b/src/modules/statuses.js index 46117fd770..57095f378b 100644 --- a/src/modules/statuses.js +++ b/src/modules/statuses.js @@ -307,9 +307,32 @@ const addNewNotifications = (state, { dispatch, notifications, older, visibleNot }) } +const removeStatus = (state, { timeline, userId }) => { + const timelineObject = state.timelines[timeline] + if (userId) { + remove(timelineObject.statuses, { user: { id: userId } }) + remove(timelineObject.visibleStatuses, { user: { id: userId } }) + const statusesObject = timelineObject.statusesObject + const visibleStatusesObject = timelineObject.visibleStatusesObject + each(statusesObject, (status, key) => { + if (status.user.id === userId) { + delete statusesObject[key] + } + }) + each(visibleStatusesObject, (status, key) => { + if (status.user.id === userId) { + delete visibleStatusesObject[key] + } + }) + timelineObject.minVisibleId = (last(timeline.visibleStatuses) || {}).id + timelineObject.maxId = statuses.length > 0 ? maxBy(statuses, 'id').id : 0 + } +} + export const mutations = { addNewStatuses, addNewNotifications, + removeStatus, showNewStatuses (state, { timeline }) { const oldTimeline = (state.timelines[timeline]) diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js index 92daa04e57..d35c72b113 100644 --- a/src/services/api/api.service.js +++ b/src/services/api/api.service.js @@ -329,7 +329,7 @@ const setUserMute = ({id, credentials, muted = true}) => { }) } -const fetchTimeline = ({timeline, credentials, since = false, until = false, userId = false, tag = false}) => { +const fetchTimeline = ({timeline, credentials, since = false, until = false, between = false, count = 20, userId = false, tag = false}) => { const timelineUrls = { public: PUBLIC_TIMELINE_URL, friends: FRIENDS_TIMELINE_URL, @@ -362,8 +362,9 @@ const fetchTimeline = ({timeline, credentials, since = false, until = false, use if (timeline === 'media') { params.push(['only_media', 1]) } - - params.push(['count', 20]) + if (!between) { + params.push(['count', count]) + } const queryString = map(params, (param) => `${param[0]}=${param[1]}`).join('&') url += `?${queryString}` -- GitLab From 66a105a519ee3a83a2a4354ed36f59355a45f970 Mon Sep 17 00:00:00 2001 From: Edijs <iamedijs@hotmail.com> Date: Fri, 22 Feb 2019 13:53:43 -0700 Subject: [PATCH 05/31] Revert --- src/components/gallery/gallery.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/components/gallery/gallery.js b/src/components/gallery/gallery.js index c713ce07bb..7f33a81b86 100644 --- a/src/components/gallery/gallery.js +++ b/src/components/gallery/gallery.js @@ -34,9 +34,7 @@ const Gallery = { return rows }, rowHeight () { - return itemsPerRow => ({ - 'height': this.attachments.length === 1 ? '260px' : `${(this.width / (itemsPerRow + 0.6))}px` - }) + return itemsPerRow => ({ 'height': `${(this.width / (itemsPerRow + 0.6))}px` }) }, useContainFit () { return this.$store.state.config.useContainFit -- GitLab From 4e79300232288fd9b7c4456e8b461f7c1cbac6fa Mon Sep 17 00:00:00 2001 From: jasper <jasper92341@hotmail.com> Date: Mon, 25 Feb 2019 14:35:47 -0800 Subject: [PATCH 06/31] Remove posts by blocking or unfollowing --- .../user_card_content/user_card_content.js | 51 ------------------- src/modules/statuses.js | 18 ++----- src/services/api/api.service.js | 6 +-- 3 files changed, 5 insertions(+), 70 deletions(-) diff --git a/src/components/user_card_content/user_card_content.js b/src/components/user_card_content/user_card_content.js index 8bc01941e0..d2a97a8481 100644 --- a/src/components/user_card_content/user_card_content.js +++ b/src/components/user_card_content/user_card_content.js @@ -1,5 +1,4 @@ import UserAvatar from '../user_avatar/user_avatar.vue' -import apiService from '../../services/api/api.service.js' import { hex2rgb } from '../../services/color_convert/color_convert.js' import { requestFollow, requestUnfollow } from '../../services/follow_manipulate/follow_manipulate' import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator' @@ -99,25 +98,6 @@ export default { requestFollow(this.user, store).then(({sent}) => { this.followRequestInProgress = false this.followRequestSent = sent - - const rootState = store.rootState || store.state - const credentials = store.state.users.currentUser.credentials - const timelineData = rootState.statuses.timelines['friends'] - apiService.fetchTimeline({ - store, - credentials, - userId: this.user.id, - timeline: 'user', - between: true, - until: timelineData.maxId, - since: timelineData.minVisibleId - }).then((statuses) => { - store.dispatch('addNewStatuses', { - timeline: 'friends', - statuses, - showImmediately: true - }) - }, () => store.dispatch('setError', { value: true })) }) }, unfollowUser () { @@ -145,37 +125,6 @@ export default { store.state.api.backendInteractor.unblockUser(this.user.id) .then((unblockedUser) => { store.commit('addNewUsers', [unblockedUser]) - - const rootState = store.rootState || store.state - const credentials = store.state.users.currentUser.credentials - const timelineData = rootState.statuses.timelines['friends'] - apiService.fetchTimeline({ - store, - credentials, - userId: this.user.id, - timeline: 'user', - between: true, - until: timelineData.maxId, - since: timelineData.minVisibleId - }).then((statuses) => { - store.dispatch('addNewStatuses', { - timeline: 'public', - statuses, - showImmediately: true - }) - store.dispatch('addNewStatuses', { - timeline: 'publicAndExternal', - statuses, - showImmediately: true - }) - if (this.user.follows_you) { - store.dispatch('addNewStatuses', { - timeline: 'friends', - statuses, - showImmediately: true - }) - } - }, () => store.dispatch('setError', { value: true })) }) }, toggleMute () { diff --git a/src/modules/statuses.js b/src/modules/statuses.js index 57095f378b..d144702ec0 100644 --- a/src/modules/statuses.js +++ b/src/modules/statuses.js @@ -1,4 +1,4 @@ -import { remove, slice, each, find, maxBy, minBy, merge, last, isArray } from 'lodash' +import { remove, slice, each, find, maxBy, minBy, merge, first, last, isArray } from 'lodash' import apiService from '../services/api/api.service.js' // import parse from '../services/status_parser/status_parser.js' @@ -312,20 +312,8 @@ const removeStatus = (state, { timeline, userId }) => { if (userId) { remove(timelineObject.statuses, { user: { id: userId } }) remove(timelineObject.visibleStatuses, { user: { id: userId } }) - const statusesObject = timelineObject.statusesObject - const visibleStatusesObject = timelineObject.visibleStatusesObject - each(statusesObject, (status, key) => { - if (status.user.id === userId) { - delete statusesObject[key] - } - }) - each(visibleStatusesObject, (status, key) => { - if (status.user.id === userId) { - delete visibleStatusesObject[key] - } - }) - timelineObject.minVisibleId = (last(timeline.visibleStatuses) || {}).id - timelineObject.maxId = statuses.length > 0 ? maxBy(statuses, 'id').id : 0 + timelineObject.minVisibleId = timelineObject.visibleStatuses.length > 0 ? last(timelineObject.visibleStatuses).id : 0 + timelineObject.maxId = timelineObject.statuses.length > 0 ? first(timelineObject.statuses).id : 0 } } diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js index d35c72b113..c5fdcb7250 100644 --- a/src/services/api/api.service.js +++ b/src/services/api/api.service.js @@ -329,7 +329,7 @@ const setUserMute = ({id, credentials, muted = true}) => { }) } -const fetchTimeline = ({timeline, credentials, since = false, until = false, between = false, count = 20, userId = false, tag = false}) => { +const fetchTimeline = ({timeline, credentials, since = false, until = false, userId = false, tag = false}) => { const timelineUrls = { public: PUBLIC_TIMELINE_URL, friends: FRIENDS_TIMELINE_URL, @@ -362,9 +362,7 @@ const fetchTimeline = ({timeline, credentials, since = false, until = false, bet if (timeline === 'media') { params.push(['only_media', 1]) } - if (!between) { - params.push(['count', count]) - } + params.push(['count', 20]) const queryString = map(params, (param) => `${param[0]}=${param[1]}`).join('&') url += `?${queryString}` -- GitLab From 7698a6fb0dad962a15855adc2a9c4134abe13de7 Mon Sep 17 00:00:00 2001 From: jasper <jasper92341@hotmail.com> Date: Tue, 26 Feb 2019 23:21:04 -0800 Subject: [PATCH 07/31] Remove posts by blocking or unfollowing --- src/components/user_card_content/user_card_content.js | 6 +----- src/services/api/api.service.js | 1 + 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/components/user_card_content/user_card_content.js b/src/components/user_card_content/user_card_content.js index d2a97a8481..351395044a 100644 --- a/src/components/user_card_content/user_card_content.js +++ b/src/components/user_card_content/user_card_content.js @@ -105,7 +105,6 @@ export default { this.followRequestInProgress = true requestUnfollow(this.user, store).then(() => { this.followRequestInProgress = false - store.commit('removeStatus', { timeline: 'friends', userId: this.user.id }) }) }, @@ -114,7 +113,6 @@ export default { store.state.api.backendInteractor.blockUser(this.user.id) .then((blockedUser) => { store.commit('addNewUsers', [blockedUser]) - store.commit('removeStatus', { timeline: 'friends', userId: this.user.id }) store.commit('removeStatus', { timeline: 'public', userId: this.user.id }) store.commit('removeStatus', { timeline: 'publicAndExternal', userId: this.user.id }) @@ -123,9 +121,7 @@ export default { unblockUser () { const store = this.$store store.state.api.backendInteractor.unblockUser(this.user.id) - .then((unblockedUser) => { - store.commit('addNewUsers', [unblockedUser]) - }) + .then((unblockedUser) => store.commit('addNewUsers', [unblockedUser])) }, toggleMute () { const store = this.$store diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js index c5fdcb7250..92daa04e57 100644 --- a/src/services/api/api.service.js +++ b/src/services/api/api.service.js @@ -362,6 +362,7 @@ const fetchTimeline = ({timeline, credentials, since = false, until = false, use if (timeline === 'media') { params.push(['only_media', 1]) } + params.push(['count', 20]) const queryString = map(params, (param) => `${param[0]}=${param[1]}`).join('&') -- GitLab From 882e0243313e8f08e5e8995a6374b79f886c91a6 Mon Sep 17 00:00:00 2001 From: Edijs <iamedijs@hotmail.com> Date: Thu, 28 Feb 2019 11:16:16 +0800 Subject: [PATCH 08/31] Revert code --- src/components/gallery/gallery.vue | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/components/gallery/gallery.vue b/src/components/gallery/gallery.vue index 90888c21bf..3f90caa99f 100644 --- a/src/components/gallery/gallery.vue +++ b/src/components/gallery/gallery.vue @@ -1,11 +1,6 @@ <template> <div ref="galleryContainer" style="width: 100%;"> - <div - v-for="(row, row_num) in rows" - :key="row_num" - :style="rowHeight(row.length)" - :class="{ 'gallery-row': true, 'contain-fit': useContainFit, 'cover-fit': !useContainFit }" - > + <div class="gallery-row" v-for="row in rows" :style="rowHeight(row.length)" :class="{ 'contain-fit': useContainFit, 'cover-fit': !useContainFit }"> <attachment v-for="attachment in row" :setMedia="setMedia" -- GitLab From ba2e05bc63e0b36d5a126b422c9f87a7ace43305 Mon Sep 17 00:00:00 2001 From: dave <starpumadev@gmail.com> Date: Thu, 28 Feb 2019 14:03:44 -0500 Subject: [PATCH 09/31] #392: stale data served to new user account --- src/components/notifications/notifications.js | 3 ++- src/modules/statuses.js | 15 ++++++++++++--- src/modules/users.js | 4 ++++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/components/notifications/notifications.js b/src/components/notifications/notifications.js index 5e95631a99..9fc5e38a28 100644 --- a/src/components/notifications/notifications.js +++ b/src/components/notifications/notifications.js @@ -11,7 +11,8 @@ const Notifications = { const store = this.$store const credentials = store.state.users.currentUser.credentials - notificationsFetcher.startFetching({ store, credentials }) + const fetcherId = notificationsFetcher.startFetching({ store, credentials }) + this.$store.commit('setNotificationFetcher', { fetcherId }) }, data () { return { diff --git a/src/modules/statuses.js b/src/modules/statuses.js index 826b544c43..2d1313a584 100644 --- a/src/modules/statuses.js +++ b/src/modules/statuses.js @@ -1,4 +1,4 @@ -import { remove, slice, each, find, maxBy, minBy, merge, last, isArray } from 'lodash' +import { remove, slice, each, find, maxBy, minBy, merge, last, isArray, cloneDeep } from 'lodash' import apiService from '../services/api/api.service.js' // import parse from '../services/status_parser/status_parser.js' @@ -29,7 +29,8 @@ export const defaultState = { data: [], idStore: {}, loading: false, - error: false + error: false, + fetcherId: null }, favorites: new Set(), error: false, @@ -321,6 +322,14 @@ export const mutations = { oldTimeline.visibleStatusesObject = {} each(oldTimeline.visibleStatuses, (status) => { oldTimeline.visibleStatusesObject[status.id] = status }) }, + setNotificationFetcher (state, { fetcherId }) { + state.notifications.fetcherId = fetcherId + }, + resetStatuses (state) { + Object.keys(state).forEach(key => { + state[key] = cloneDeep(defaultState[key]) + }) + }, clearTimeline (state, { timeline }) { state.timelines[timeline] = emptyTl(state.timelines[timeline].userId) }, @@ -371,7 +380,7 @@ export const mutations = { } const statuses = { - state: defaultState, + state: cloneDeep(defaultState), actions: { addNewStatuses ({ rootState, commit }, { statuses, showImmediately = false, timeline = false, noIdUpdate = false, userId }) { commit('addNewStatuses', { statuses, showImmediately, timeline, noIdUpdate, user: rootState.users.currentUser, userId }) diff --git a/src/modules/users.js b/src/modules/users.js index 77df7168e2..84fe039bf5 100644 --- a/src/modules/users.js +++ b/src/modules/users.js @@ -290,6 +290,10 @@ const users = { store.commit('setToken', false) store.dispatch('stopFetching', 'friends') store.commit('setBackendInteractor', backendInteractorService()) + if (store.rootState.statuses.notifications.fetcherId) { + window.clearInterval(store.rootState.statuses.notifications.fetcherId) + } + store.commit('resetStatuses') }, loginUser (store, accessToken) { return new Promise((resolve, reject) => { -- GitLab From f5adb62e2e6efdf6bd9a9c7a8c2677c618de53f9 Mon Sep 17 00:00:00 2001 From: dave <starpumadev@gmail.com> Date: Thu, 28 Feb 2019 14:27:47 -0500 Subject: [PATCH 10/31] #392: update defaultState into a function --- src/modules/statuses.js | 11 +++++----- test/unit/specs/modules/statuses.spec.js | 27 ++++++++++++------------ 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/modules/statuses.js b/src/modules/statuses.js index 2d1313a584..2af23a9d2c 100644 --- a/src/modules/statuses.js +++ b/src/modules/statuses.js @@ -1,4 +1,4 @@ -import { remove, slice, each, find, maxBy, minBy, merge, last, isArray, cloneDeep } from 'lodash' +import { remove, slice, each, find, maxBy, minBy, merge, last, isArray } from 'lodash' import apiService from '../services/api/api.service.js' // import parse from '../services/status_parser/status_parser.js' @@ -18,7 +18,7 @@ const emptyTl = (userId = 0) => ({ flushMarker: 0 }) -export const defaultState = { +export const defaultState = () => ({ allStatuses: [], allStatusesObject: {}, maxId: 0, @@ -45,7 +45,7 @@ export const defaultState = { tag: emptyTl(), dms: emptyTl() } -} +}) export const prepareStatus = (status) => { // Set deleted flag @@ -326,8 +326,9 @@ export const mutations = { state.notifications.fetcherId = fetcherId }, resetStatuses (state) { + const emptyState = defaultState() Object.keys(state).forEach(key => { - state[key] = cloneDeep(defaultState[key]) + state[key] = emptyState[key] }) }, clearTimeline (state, { timeline }) { @@ -380,7 +381,7 @@ export const mutations = { } const statuses = { - state: cloneDeep(defaultState), + state: defaultState(), actions: { addNewStatuses ({ rootState, commit }, { statuses, showImmediately = false, timeline = false, noIdUpdate = false, userId }) { commit('addNewStatuses', { statuses, showImmediately, timeline, noIdUpdate, user: rootState.users.currentUser, userId }) diff --git a/test/unit/specs/modules/statuses.spec.js b/test/unit/specs/modules/statuses.spec.js index 01d2ce061f..864b798dd1 100644 --- a/test/unit/specs/modules/statuses.spec.js +++ b/test/unit/specs/modules/statuses.spec.js @@ -1,4 +1,3 @@ -import { cloneDeep } from 'lodash' import { defaultState, mutations, prepareStatus } from '../../../../src/modules/statuses.js' // eslint-disable-next-line camelcase @@ -24,7 +23,7 @@ describe('Statuses.prepareStatus', () => { describe('The Statuses module', () => { it('adds the status to allStatuses and to the given timeline', () => { - const state = cloneDeep(defaultState) + const state = defaultState() const status = makeMockStatus({id: '1'}) mutations.addNewStatuses(state, { statuses: [status], timeline: 'public' }) @@ -36,7 +35,7 @@ describe('The Statuses module', () => { }) it('counts the status as new if it has not been seen on this timeline', () => { - const state = cloneDeep(defaultState) + const state = defaultState() const status = makeMockStatus({id: '1'}) mutations.addNewStatuses(state, { statuses: [status], timeline: 'public' }) @@ -54,7 +53,7 @@ describe('The Statuses module', () => { }) it('add the statuses to allStatuses if no timeline is given', () => { - const state = cloneDeep(defaultState) + const state = defaultState() const status = makeMockStatus({id: '1'}) mutations.addNewStatuses(state, { statuses: [status] }) @@ -66,7 +65,7 @@ describe('The Statuses module', () => { }) it('adds the status to allStatuses and to the given timeline, directly visible', () => { - const state = cloneDeep(defaultState) + const state = defaultState() const status = makeMockStatus({id: '1'}) mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' }) @@ -78,7 +77,7 @@ describe('The Statuses module', () => { }) it('removes statuses by tag on deletion', () => { - const state = cloneDeep(defaultState) + const state = defaultState() const status = makeMockStatus({id: '1'}) const otherStatus = makeMockStatus({id: '3'}) status.uri = 'xxx' @@ -96,7 +95,7 @@ describe('The Statuses module', () => { }) it('does not update the maxId when the noIdUpdate flag is set', () => { - const state = cloneDeep(defaultState) + const state = defaultState() const status = makeMockStatus({id: '1'}) const secondStatus = makeMockStatus({id: '2'}) @@ -110,7 +109,7 @@ describe('The Statuses module', () => { }) it('keeps a descending by id order in timeline.visibleStatuses and timeline.statuses', () => { - const state = cloneDeep(defaultState) + const state = defaultState() const nonVisibleStatus = makeMockStatus({id: '1'}) const status = makeMockStatus({id: '3'}) const statusTwo = makeMockStatus({id: '2'}) @@ -130,7 +129,7 @@ describe('The Statuses module', () => { }) it('splits retweets from their status and links them', () => { - const state = cloneDeep(defaultState) + const state = defaultState() const status = makeMockStatus({id: '1'}) const retweet = makeMockStatus({id: '2', type: 'retweet'}) const modStatus = makeMockStatus({id: '1', text: 'something else'}) @@ -155,7 +154,7 @@ describe('The Statuses module', () => { }) it('replaces existing statuses with the same id', () => { - const state = cloneDeep(defaultState) + const state = defaultState() const status = makeMockStatus({id: '1'}) const modStatus = makeMockStatus({id: '1', text: 'something else'}) @@ -172,7 +171,7 @@ describe('The Statuses module', () => { }) it('replaces existing statuses with the same id, coming from a retweet', () => { - const state = cloneDeep(defaultState) + const state = defaultState() const status = makeMockStatus({id: '1'}) const modStatus = makeMockStatus({id: '1', text: 'something else'}) const retweet = makeMockStatus({id: '2', type: 'retweet'}) @@ -193,7 +192,7 @@ describe('The Statuses module', () => { }) it('handles favorite actions', () => { - const state = cloneDeep(defaultState) + const state = defaultState() const status = makeMockStatus({id: '1'}) const favorite = { @@ -241,7 +240,7 @@ describe('The Statuses module', () => { }) it('keeps userId when clearing user timeline', () => { - const state = cloneDeep(defaultState) + const state = defaultState() state.timelines.user.userId = 123 mutations.clearTimeline(state, { timeline: 'user' }) @@ -252,7 +251,7 @@ describe('The Statuses module', () => { describe('notifications', () => { it('removes a notification when the notice gets removed', () => { const user = { id: '1' } - const state = cloneDeep(defaultState) + const state = defaultState() const status = makeMockStatus({id: '1'}) const otherStatus = makeMockStatus({id: '3'}) const mentionedStatus = makeMockStatus({id: '2'}) -- GitLab From bbe1821be7c098f3a23bd0dd54b4ec89a159e9c1 Mon Sep 17 00:00:00 2001 From: dave <starpumadev@gmail.com> Date: Thu, 28 Feb 2019 14:44:43 -0500 Subject: [PATCH 11/31] #392: update object.entries --- src/modules/statuses.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/statuses.js b/src/modules/statuses.js index 2af23a9d2c..028053cf69 100644 --- a/src/modules/statuses.js +++ b/src/modules/statuses.js @@ -327,8 +327,8 @@ export const mutations = { }, resetStatuses (state) { const emptyState = defaultState() - Object.keys(state).forEach(key => { - state[key] = emptyState[key] + Object.entries(emptyState).forEach(([key, value]) => { + state[key] = value }) }, clearTimeline (state, { timeline }) { -- GitLab From f3f9fbe3027bf5284adc05387e89d904884490b2 Mon Sep 17 00:00:00 2001 From: dave <starpumadev@gmail.com> Date: Fri, 1 Mar 2019 11:59:50 -0500 Subject: [PATCH 12/31] #392: clean up notification stopping section --- src/modules/statuses.js | 6 ++++++ src/modules/users.js | 4 +--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/modules/statuses.js b/src/modules/statuses.js index 028053cf69..77a8ec726e 100644 --- a/src/modules/statuses.js +++ b/src/modules/statuses.js @@ -401,6 +401,12 @@ const statuses = { setNotificationsSilence ({ rootState, commit }, { value }) { commit('setNotificationsSilence', { value }) }, + stopFetchingNotifications ({ rootState, commit }) { + if (rootState.statuses.notifications.fetcherId) { + window.clearInterval(rootState.statuses.notifications.fetcherId) + } + commit('setNotificationFetcher', { fetcherId: null }) + }, deleteStatus ({ rootState, commit }, status) { commit('setDeleted', { status }) apiService.deleteStatus({ id: status.id, credentials: rootState.users.currentUser.credentials }) diff --git a/src/modules/users.js b/src/modules/users.js index 84fe039bf5..0e1dd16692 100644 --- a/src/modules/users.js +++ b/src/modules/users.js @@ -290,9 +290,7 @@ const users = { store.commit('setToken', false) store.dispatch('stopFetching', 'friends') store.commit('setBackendInteractor', backendInteractorService()) - if (store.rootState.statuses.notifications.fetcherId) { - window.clearInterval(store.rootState.statuses.notifications.fetcherId) - } + store.dispatch('stopFetchingNotifications') store.commit('resetStatuses') }, loginUser (store, accessToken) { -- GitLab From f91e4a5801b99084894c4921746f9c47566f30dd Mon Sep 17 00:00:00 2001 From: Edijs <iamedijs@hotmail.com> Date: Mon, 4 Mar 2019 21:29:56 -0800 Subject: [PATCH 13/31] Load post status content type from instance config --- src/boot/after_store.js | 2 ++ src/components/settings/settings.js | 3 +++ src/components/settings/settings.vue | 14 +++----------- src/i18n/en.json | 5 +++++ src/modules/instance.js | 1 + 5 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/boot/after_store.js b/src/boot/after_store.js index 53ecc08319..a8e2bf35f5 100644 --- a/src/boot/after_store.js +++ b/src/boot/after_store.js @@ -169,6 +169,8 @@ const afterStoreSetup = ({ store, i18n }) => { store.dispatch('setInstanceOption', { name: 'chatAvailable', value: features.includes('chat') }) store.dispatch('setInstanceOption', { name: 'gopherAvailable', value: features.includes('gopher') }) + store.dispatch('setInstanceOption', { name: 'postFormats', value: metadata.postFormats }) + store.dispatch('setInstanceOption', { name: 'restrictedNicknames', value: metadata.restrictedNicknames }) const suggestions = metadata.suggestions diff --git a/src/components/settings/settings.js b/src/components/settings/settings.js index 6e2dff7bec..979457a56f 100644 --- a/src/components/settings/settings.js +++ b/src/components/settings/settings.js @@ -93,6 +93,9 @@ const settings = { currentSaveStateNotice () { return this.$store.state.interface.settings.currentSaveStateNotice }, + postFormats () { + return this.$store.state.instance.postFormats || [] + }, instanceSpecificPanelPresent () { return this.$store.state.instance.showInstanceSpecificPanel } }, watch: { diff --git a/src/components/settings/settings.vue b/src/components/settings/settings.vue index 5041b3a392..c0cfe1abd1 100644 --- a/src/components/settings/settings.vue +++ b/src/components/settings/settings.vue @@ -105,17 +105,9 @@ {{$t('settings.post_status_content_type')}} <label for="postContentType" class="select"> <select id="postContentType" v-model="postContentTypeLocal"> - <option value="text/plain"> - {{$t('settings.status_content_type_plain')}} - {{postContentTypeDefault == 'text/plain' ? $t('settings.instance_default_simple') : ''}} - </option> - <option value="text/html"> - HTML - {{postContentTypeDefault == 'text/html' ? $t('settings.instance_default_simple') : ''}} - </option> - <option value="text/markdown"> - Markdown - {{postContentTypeDefault == 'text/markdown' ? $t('settings.instance_default_simple') : ''}} + <option v-for="postFormat in postFormats" :key="postFormat" :value="postFormat"> + {{$t(`settings.post_formats["${postFormat}"]`)}} + {{postContentTypeDefault === postFormat ? $t('settings.instance_default_simple') : ''}} </option> </select> <i class="icon-down-open"/> diff --git a/src/i18n/en.json b/src/i18n/en.json index c5a4a90d34..e614fb6ca2 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -220,6 +220,11 @@ "subject_line_email": "Like email: \"re: subject\"", "subject_line_mastodon": "Like mastodon: copy as is", "subject_line_noop": "Do not copy", + "post_formats": { + "text/plain": "Plain text", + "text/html": "HTML", + "text/markdown": "Markdown" + }, "post_status_content_type": "Post status content type", "status_content_type_plain": "Plain text", "stop_gifs": "Play-on-hover GIFs", diff --git a/src/modules/instance.js b/src/modules/instance.js index c31d02b97f..24c52f9c11 100644 --- a/src/modules/instance.js +++ b/src/modules/instance.js @@ -37,6 +37,7 @@ const defaultState = { emoji: [], customEmoji: [], restrictedNicknames: [], + postFormats: [], // Feature-set, apparently, not everything here is reported... mediaProxyAvailable: false, -- GitLab From e0a66b989d8f30f6475bc04064c8c36f9f876539 Mon Sep 17 00:00:00 2001 From: taehoon <th.dev91@gmail.com> Date: Tue, 5 Mar 2019 02:32:23 -0500 Subject: [PATCH 14/31] Re-do UserCardContent css --- .../basic_user_card/basic_user_card.vue | 21 +---- src/components/notification/notification.vue | 4 +- .../notifications/notifications.scss | 4 - src/components/side_drawer/side_drawer.vue | 11 +-- src/components/status/status.vue | 7 +- .../user_card_content/user_card_content.js | 11 ++- .../user_card_content/user_card_content.vue | 79 ++++++++++--------- src/components/user_panel/user_panel.vue | 12 +-- src/components/user_profile/user_profile.vue | 11 +-- 9 files changed, 58 insertions(+), 102 deletions(-) diff --git a/src/components/basic_user_card/basic_user_card.vue b/src/components/basic_user_card/basic_user_card.vue index 77fb0aa0f7..a358c971b4 100644 --- a/src/components/basic_user_card/basic_user_card.vue +++ b/src/components/basic_user_card/basic_user_card.vue @@ -4,7 +4,7 @@ <UserAvatar class="avatar" @click.prevent.native="toggleUserExpanded" :src="user.profile_image_url"/> </router-link> <div class="user-card-expanded-content" v-if="userExpanded"> - <user-card-content :user="user" :switcher="false"></user-card-content> + <UserCardContent :user="user" :rounded="true" :bordered="true"/> </div> <div class="user-card-collapsed-content" v-else> <div :title="user.name" class="user-card-user-name"> @@ -29,12 +29,12 @@ .user-card { display: flex; flex: 1 0; + margin: 0; padding-top: 0.6em; padding-right: 1em; padding-bottom: 0.6em; padding-left: 1em; border-bottom: 1px solid; - margin: 0; border-bottom-color: $fallback--border; border-bottom-color: var(--border, $fallback--border); @@ -57,23 +57,6 @@ &-expanded-content { flex: 1; margin-left: 0.7em; - border-radius: $fallback--panelRadius; - border-radius: var(--panelRadius, $fallback--panelRadius); - border-style: solid; - border-color: $fallback--border; - border-color: var(--border, $fallback--border); - border-width: 1px; - overflow: hidden; - - .panel-heading { - background: transparent; - flex-direction: column; - align-items: stretch; - } - - p { - margin-bottom: 0; - } } } </style> diff --git a/src/components/notification/notification.vue b/src/components/notification/notification.vue index 87925cfc08..6583570e2f 100644 --- a/src/components/notification/notification.vue +++ b/src/components/notification/notification.vue @@ -5,9 +5,7 @@ <UserAvatar :compact="true" :betterShadow="betterShadow" :src="notification.action.user.profile_image_url_original"/> </a> <div class='notification-right'> - <div class="usercard notification-usercard" v-if="userExpanded"> - <user-card-content :user="notification.action.user" :switcher="false"></user-card-content> - </div> + <UserCardContent :user="notification.action.user" :rounded="true" :bordered="true" v-if="userExpanded"/> <span class="notification-details"> <div class="name-and-action"> <span class="username" v-if="!!notification.action.user.name_html" :title="'@'+notification.action.user.screen_name" v-html="notification.action.user.name_html"></span> diff --git a/src/components/notifications/notifications.scss b/src/components/notifications/notifications.scss index 2240c10a8f..c0b458ccf4 100644 --- a/src/components/notifications/notifications.scss +++ b/src/components/notifications/notifications.scss @@ -45,10 +45,6 @@ } } - .notification-usercard { - margin: 0; - } - .non-mention { display: flex; flex: 1; diff --git a/src/components/side_drawer/side_drawer.vue b/src/components/side_drawer/side_drawer.vue index 6996380dde..f346b44088 100644 --- a/src/components/side_drawer/side_drawer.vue +++ b/src/components/side_drawer/side_drawer.vue @@ -8,7 +8,7 @@ @touchmove="touchMove" > <div class="side-drawer-heading" @click="toggleDrawer"> - <user-card-content :user="currentUser" :switcher="false" :hideBio="true" v-if="currentUser"/> + <UserCardContent :user="currentUser" :hideBio="true" v-if="currentUser"/> <div class="side-drawer-logo-wrapper" v-else> <img :src="logo"/> <span>{{sitename}}</span> @@ -181,15 +181,6 @@ display: flex; padding: 0; margin: 0; - - .profile-panel-background { - border-radius: 0; - .panel-heading { - background: transparent; - flex-direction: column; - align-items: stretch; - } - } } .side-drawer ul { diff --git a/src/components/status/status.vue b/src/components/status/status.vue index ee6ef7daf6..0c110c90e3 100644 --- a/src/components/status/status.vue +++ b/src/components/status/status.vue @@ -31,9 +31,7 @@ </router-link> </div> <div class="status-body"> - <div class="usercard" v-if="userExpanded"> - <user-card-content :user="status.user" :switcher="false"></user-card-content> - </div> + <UserCardContent :user="status.user" :rounded="true" :bordered="true" class="status-usercard-content" v-if="userExpanded"/> <div v-if="!noHeading" class="media-heading"> <div class="heading-name-row"> <div class="name-and-account-name"> @@ -248,8 +246,7 @@ $status-margin: 0.75em; padding: 0; } - .usercard { - margin: 0; + .status-usercard-content { margin-bottom: $status-margin; } diff --git a/src/components/user_card_content/user_card_content.js b/src/components/user_card_content/user_card_content.js index 7a7b89d490..78c7eb6b62 100644 --- a/src/components/user_card_content/user_card_content.js +++ b/src/components/user_card_content/user_card_content.js @@ -4,7 +4,7 @@ import { requestFollow, requestUnfollow } from '../../services/follow_manipulate import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator' export default { - props: [ 'user', 'switcher', 'selected', 'hideBio' ], + props: [ 'user', 'switcher', 'selected', 'hideBio', 'rounded', 'bordered' ], data () { return { followRequestInProgress: false, @@ -16,7 +16,14 @@ export default { } }, computed: { - headingStyle () { + classes () { + return [{ + 'user-card-content-rounded': this.rounded === true, + 'user-card-content-rounded-t': this.rounded === 'top', // top only + 'user-card-content-bordered': this.bordered + }] + }, + style () { const color = this.$store.state.config.customTheme.colors ? this.$store.state.config.customTheme.colors.bg // v2 : this.$store.state.config.colors.bg // v1 diff --git a/src/components/user_card_content/user_card_content.vue b/src/components/user_card_content/user_card_content.vue index 702c338512..f06a0a45d6 100644 --- a/src/components/user_card_content/user_card_content.vue +++ b/src/components/user_card_content/user_card_content.vue @@ -1,6 +1,6 @@ <template> -<div id="heading" class="profile-panel-background" :style="headingStyle"> - <div class="panel-heading text-center"> +<div class="user-card-content" :class="classes" :style="style"> + <div class="panel-heading"> <div class='user-info'> <div class='container'> <router-link :to="userProfileLink(user)"> @@ -108,7 +108,7 @@ </div> </div> </div> - <div class="panel-body profile-panel-body" v-if="!hideBio"> + <div class="panel-body" v-if="!hideBio"> <div v-if="!hideUserStatsLocal && switcher" class="user-counts"> <div class="user-count" v-on:click.prevent="setProfileView('statuses')"> <h5>{{ $t('user_card.statuses') }}</h5> @@ -123,8 +123,8 @@ <span>{{user.followers_count}}</span> </div> </div> - <p @click.prevent="linkClicked" v-if="!hideBio && user.description_html" class="profile-bio" v-html="user.description_html"></p> - <p v-else-if="!hideBio" class="profile-bio">{{ user.description }}</p> + <p @click.prevent="linkClicked" v-if="!hideBio && user.description_html" class="user-card-content-bio" v-html="user.description_html"></p> + <p v-else-if="!hideBio" class="user-card-content-bio">{{ user.description }}</p> </div> </div> </template> @@ -134,30 +134,54 @@ <style lang="scss"> @import '../../_variables.scss'; -.profile-panel-background { +.user-card-content { background-size: cover; - border-radius: $fallback--panelRadius; - border-radius: var(--panelRadius, $fallback--panelRadius); overflow: hidden; - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; - .panel-heading { padding: .5em 0; text-align: center; box-shadow: none; + background: transparent; + flex-direction: column; + align-items: stretch; } -} -.profile-panel-body { - 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%); + .panel-body { + 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%); + } - .profile-bio { + p { + margin-bottom: 0; + } + + &-bio { text-align: center; } + + // + // Modifiers + + &-rounded { + border-radius: $fallback--panelRadius; + border-radius: var(--panelRadius, $fallback--panelRadius); + } + + &-rounded-t { + border-radius: $fallback--panelRadius; + border-radius: var(--panelRadius, $fallback--panelRadius); + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + } + + &-bordered { + border-width: 1px; + border-style: solid; + border-color: $fallback--border; + border-color: var(--border, $fallback--border); + } } .user-info { @@ -393,25 +417,4 @@ text-decoration: none; } } - -.usercard { - width: fill-available; - border-radius: $fallback--panelRadius; - border-radius: var(--panelRadius, $fallback--panelRadius); - border-style: solid; - border-color: $fallback--border; - border-color: var(--border, $fallback--border); - border-width: 1px; - overflow: hidden; - - .panel-heading { - background: transparent; - flex-direction: column; - align-items: stretch; - } - - p { - margin-bottom: 0; - } -} </style> diff --git a/src/components/user_panel/user_panel.vue b/src/components/user_panel/user_panel.vue index 2d5cb500d6..4b3d8971e1 100644 --- a/src/components/user_panel/user_panel.vue +++ b/src/components/user_panel/user_panel.vue @@ -1,7 +1,7 @@ <template> <div class="user-panel"> <div v-if='user' class="panel panel-default" style="overflow: visible;"> - <user-card-content :user="user" :switcher="false" :hideBio="true"></user-card-content> + <UserCardContent :user="user" :hideBio="true" rounded="top"/> <div class="panel-footer"> <post-status-form v-if='user'></post-status-form> </div> @@ -11,13 +11,3 @@ </template> <script src="./user_panel.js"></script> - -<style lang="scss"> -.user-panel { - .profile-panel-background .panel-heading { - background: transparent; - flex-direction: column; - align-items: stretch; - } -} -</style> diff --git a/src/components/user_profile/user_profile.vue b/src/components/user_profile/user_profile.vue index 8090efa56e..c57d3409ea 100644 --- a/src/components/user_profile/user_profile.vue +++ b/src/components/user_profile/user_profile.vue @@ -1,11 +1,7 @@ <template> <div> <div v-if="user.id" class="user-profile panel panel-default"> - <user-card-content - :user="user" - :switcher="true" - :selected="timeline.viewing" - /> + <UserCardContent :user="user" :switcher="true" :selected="timeline.viewing" rounded="top"/> <tab-switcher :renderOnlyFocused="true" ref="tabSwitcher"> <Timeline :label="$t('user_card.statuses')" @@ -64,11 +60,6 @@ flex: 2; flex-basis: 500px; - .profile-panel-background .panel-heading { - background: transparent; - flex-direction: column; - align-items: stretch; - } .userlist-placeholder { display: flex; justify-content: center; -- GitLab From 43c52cb95054d3de43a3a7a5ab46836c84013d1b Mon Sep 17 00:00:00 2001 From: taehoon <th.dev91@gmail.com> Date: Tue, 5 Mar 2019 13:25:31 -0500 Subject: [PATCH 15/31] Update modifier class notation --- .../user_card_content/user_card_content.js | 6 +++--- .../user_card_content/user_card_content.vue | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/components/user_card_content/user_card_content.js b/src/components/user_card_content/user_card_content.js index 78c7eb6b62..96c6036ce0 100644 --- a/src/components/user_card_content/user_card_content.js +++ b/src/components/user_card_content/user_card_content.js @@ -18,9 +18,9 @@ export default { computed: { classes () { return [{ - 'user-card-content-rounded': this.rounded === true, - 'user-card-content-rounded-t': this.rounded === 'top', // top only - 'user-card-content-bordered': this.bordered + 'user-card-content-rt': this.rounded === 'top', // set border-top-left-radius and border-top-right-radius + 'user-card-content-r': this.rounded === true, // set border-radius for all sides + 'user-card-content-b': this.bordered === true // set border for all sides }] }, style () { diff --git a/src/components/user_card_content/user_card_content.vue b/src/components/user_card_content/user_card_content.vue index f06a0a45d6..e003e85029 100644 --- a/src/components/user_card_content/user_card_content.vue +++ b/src/components/user_card_content/user_card_content.vue @@ -164,19 +164,19 @@ // // Modifiers - &-rounded { - border-radius: $fallback--panelRadius; - border-radius: var(--panelRadius, $fallback--panelRadius); + &-rt { + border-top-left-radius: $fallback--panelRadius; + border-top-left-radius: var(--panelRadius, $fallback--panelRadius); + border-top-right-radius: $fallback--panelRadius; + border-top-right-radius: var(--panelRadius, $fallback--panelRadius); } - &-rounded-t { + &-r { border-radius: $fallback--panelRadius; border-radius: var(--panelRadius, $fallback--panelRadius); - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; } - &-bordered { + &-b { border-width: 1px; border-style: solid; border-color: $fallback--border; -- GitLab From baf603a506529cfacdd4bf0b98f248cd3ed35b34 Mon Sep 17 00:00:00 2001 From: taehoon <th.dev91@gmail.com> Date: Tue, 5 Mar 2019 13:54:49 -0500 Subject: [PATCH 16/31] Update block class name of BasicUserCard component --- src/components/basic_user_card/basic_user_card.vue | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/components/basic_user_card/basic_user_card.vue b/src/components/basic_user_card/basic_user_card.vue index a358c971b4..f72620a351 100644 --- a/src/components/basic_user_card/basic_user_card.vue +++ b/src/components/basic_user_card/basic_user_card.vue @@ -1,18 +1,18 @@ <template> - <div class="user-card"> + <div class="basic-user-card"> <router-link :to="userProfileLink(user)"> <UserAvatar class="avatar" @click.prevent.native="toggleUserExpanded" :src="user.profile_image_url"/> </router-link> - <div class="user-card-expanded-content" v-if="userExpanded"> + <div class="basic-user-card-expanded-content" v-if="userExpanded"> <UserCardContent :user="user" :rounded="true" :bordered="true"/> </div> - <div class="user-card-collapsed-content" v-else> - <div :title="user.name" class="user-card-user-name"> + <div class="basic-user-card-collapsed-content" v-else> + <div :title="user.name" class="basic-user-card-user-name"> <span v-if="user.name_html" v-html="user.name_html"></span> <span v-else>{{ user.name }}</span> </div> <div> - <router-link class="user-card-screen-name" :to="userProfileLink(user)"> + <router-link class="basic-user-card-screen-name" :to="userProfileLink(user)"> @{{user.screen_name}} </router-link> </div> @@ -26,7 +26,7 @@ <style lang="scss"> @import '../../_variables.scss'; -.user-card { +.basic-user-card { display: flex; flex: 1 0; margin: 0; -- GitLab From 7bceabb5bda1f7d0737f8f51e0aa07879b7ce72e Mon Sep 17 00:00:00 2001 From: taehoon <th.dev91@gmail.com> Date: Tue, 5 Mar 2019 14:01:49 -0500 Subject: [PATCH 17/31] Rename UserCardContent to UserCard --- src/components/basic_user_card/basic_user_card.js | 4 ++-- src/components/basic_user_card/basic_user_card.vue | 2 +- src/components/notification/notification.js | 4 ++-- src/components/notification/notification.vue | 2 +- src/components/side_drawer/side_drawer.js | 4 ++-- src/components/side_drawer/side_drawer.vue | 2 +- src/components/status/status.js | 4 ++-- src/components/status/status.vue | 2 +- .../user_card_content.js => user_card/user_card.js} | 6 +++--- .../user_card_content.vue => user_card/user_card.vue} | 10 +++++----- src/components/user_panel/user_panel.js | 4 ++-- src/components/user_panel/user_panel.vue | 2 +- src/components/user_profile/user_profile.js | 4 ++-- src/components/user_profile/user_profile.vue | 2 +- 14 files changed, 26 insertions(+), 26 deletions(-) rename src/components/{user_card_content/user_card_content.js => user_card/user_card.js} (94%) rename src/components/{user_card_content/user_card_content.vue => user_card/user_card.vue} (97%) diff --git a/src/components/basic_user_card/basic_user_card.js b/src/components/basic_user_card/basic_user_card.js index a844144691..87085a2824 100644 --- a/src/components/basic_user_card/basic_user_card.js +++ b/src/components/basic_user_card/basic_user_card.js @@ -1,4 +1,4 @@ -import UserCardContent from '../user_card_content/user_card_content.vue' +import UserCard from '../user_card/user_card.vue' import UserAvatar from '../user_avatar/user_avatar.vue' import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator' @@ -12,7 +12,7 @@ const BasicUserCard = { } }, components: { - UserCardContent, + UserCard, UserAvatar }, methods: { diff --git a/src/components/basic_user_card/basic_user_card.vue b/src/components/basic_user_card/basic_user_card.vue index f72620a351..9b80c72b81 100644 --- a/src/components/basic_user_card/basic_user_card.vue +++ b/src/components/basic_user_card/basic_user_card.vue @@ -4,7 +4,7 @@ <UserAvatar class="avatar" @click.prevent.native="toggleUserExpanded" :src="user.profile_image_url"/> </router-link> <div class="basic-user-card-expanded-content" v-if="userExpanded"> - <UserCardContent :user="user" :rounded="true" :bordered="true"/> + <UserCard :user="user" :rounded="true" :bordered="true"/> </div> <div class="basic-user-card-collapsed-content" v-else> <div :title="user.name" class="basic-user-card-user-name"> diff --git a/src/components/notification/notification.js b/src/components/notification/notification.js index 7d9807deb3..fe5b701840 100644 --- a/src/components/notification/notification.js +++ b/src/components/notification/notification.js @@ -1,6 +1,6 @@ import Status from '../status/status.vue' import UserAvatar from '../user_avatar/user_avatar.vue' -import UserCardContent from '../user_card_content/user_card_content.vue' +import UserCard from '../user_card/user_card.vue' import { highlightClass, highlightStyle } from '../../services/user_highlighter/user_highlighter.js' import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator' @@ -13,7 +13,7 @@ const Notification = { }, props: [ 'notification' ], components: { - Status, UserAvatar, UserCardContent + Status, UserAvatar, UserCard }, methods: { toggleUserExpanded () { diff --git a/src/components/notification/notification.vue b/src/components/notification/notification.vue index 6583570e2f..5e9cef97d5 100644 --- a/src/components/notification/notification.vue +++ b/src/components/notification/notification.vue @@ -5,7 +5,7 @@ <UserAvatar :compact="true" :betterShadow="betterShadow" :src="notification.action.user.profile_image_url_original"/> </a> <div class='notification-right'> - <UserCardContent :user="notification.action.user" :rounded="true" :bordered="true" v-if="userExpanded"/> + <UserCard :user="notification.action.user" :rounded="true" :bordered="true" v-if="userExpanded"/> <span class="notification-details"> <div class="name-and-action"> <span class="username" v-if="!!notification.action.user.name_html" :title="'@'+notification.action.user.screen_name" v-html="notification.action.user.name_html"></span> diff --git a/src/components/side_drawer/side_drawer.js b/src/components/side_drawer/side_drawer.js index b5c4905934..ad3738d167 100644 --- a/src/components/side_drawer/side_drawer.js +++ b/src/components/side_drawer/side_drawer.js @@ -1,4 +1,4 @@ -import UserCardContent from '../user_card_content/user_card_content.vue' +import UserCard from '../user_card/user_card.vue' import { unseenNotificationsFromStore } from '../../services/notification_utils/notification_utils' // TODO: separate touch gesture stuff into their own utils if more components want them @@ -12,7 +12,7 @@ const SideDrawer = { closed: true, touchCoord: [0, 0] }), - components: { UserCardContent }, + components: { UserCard }, computed: { currentUser () { return this.$store.state.users.currentUser diff --git a/src/components/side_drawer/side_drawer.vue b/src/components/side_drawer/side_drawer.vue index f346b44088..b608b008dc 100644 --- a/src/components/side_drawer/side_drawer.vue +++ b/src/components/side_drawer/side_drawer.vue @@ -8,7 +8,7 @@ @touchmove="touchMove" > <div class="side-drawer-heading" @click="toggleDrawer"> - <UserCardContent :user="currentUser" :hideBio="true" v-if="currentUser"/> + <UserCard :user="currentUser" :hideBio="true" v-if="currentUser"/> <div class="side-drawer-logo-wrapper" v-else> <img :src="logo"/> <span>{{sitename}}</span> diff --git a/src/components/status/status.js b/src/components/status/status.js index fbbca6c49d..9e18fe151c 100644 --- a/src/components/status/status.js +++ b/src/components/status/status.js @@ -3,7 +3,7 @@ import FavoriteButton from '../favorite_button/favorite_button.vue' import RetweetButton from '../retweet_button/retweet_button.vue' import DeleteButton from '../delete_button/delete_button.vue' import PostStatusForm from '../post_status_form/post_status_form.vue' -import UserCardContent from '../user_card_content/user_card_content.vue' +import UserCard from '../user_card/user_card.vue' import UserAvatar from '../user_avatar/user_avatar.vue' import Gallery from '../gallery/gallery.vue' import LinkPreview from '../link-preview/link-preview.vue' @@ -259,7 +259,7 @@ const Status = { RetweetButton, DeleteButton, PostStatusForm, - UserCardContent, + UserCard, UserAvatar, Gallery, LinkPreview diff --git a/src/components/status/status.vue b/src/components/status/status.vue index 0c110c90e3..8fda68f5b0 100644 --- a/src/components/status/status.vue +++ b/src/components/status/status.vue @@ -31,7 +31,7 @@ </router-link> </div> <div class="status-body"> - <UserCardContent :user="status.user" :rounded="true" :bordered="true" class="status-usercard-content" v-if="userExpanded"/> + <UserCard :user="status.user" :rounded="true" :bordered="true" class="status-usercard-content" v-if="userExpanded"/> <div v-if="!noHeading" class="media-heading"> <div class="heading-name-row"> <div class="name-and-account-name"> diff --git a/src/components/user_card_content/user_card_content.js b/src/components/user_card/user_card.js similarity index 94% rename from src/components/user_card_content/user_card_content.js rename to src/components/user_card/user_card.js index 96c6036ce0..0cb616f46b 100644 --- a/src/components/user_card_content/user_card_content.js +++ b/src/components/user_card/user_card.js @@ -18,9 +18,9 @@ export default { computed: { classes () { return [{ - 'user-card-content-rt': this.rounded === 'top', // set border-top-left-radius and border-top-right-radius - 'user-card-content-r': this.rounded === true, // set border-radius for all sides - 'user-card-content-b': this.bordered === true // set border for all sides + 'user-card-rt': this.rounded === 'top', // set border-top-left-radius and border-top-right-radius + 'user-card-r': this.rounded === true, // set border-radius for all sides + 'user-card-b': this.bordered === true // set border for all sides }] }, style () { diff --git a/src/components/user_card_content/user_card_content.vue b/src/components/user_card/user_card.vue similarity index 97% rename from src/components/user_card_content/user_card_content.vue rename to src/components/user_card/user_card.vue index e003e85029..b90f57a139 100644 --- a/src/components/user_card_content/user_card_content.vue +++ b/src/components/user_card/user_card.vue @@ -1,5 +1,5 @@ <template> -<div class="user-card-content" :class="classes" :style="style"> +<div class="user-card" :class="classes" :style="style"> <div class="panel-heading"> <div class='user-info'> <div class='container'> @@ -123,18 +123,18 @@ <span>{{user.followers_count}}</span> </div> </div> - <p @click.prevent="linkClicked" v-if="!hideBio && user.description_html" class="user-card-content-bio" v-html="user.description_html"></p> - <p v-else-if="!hideBio" class="user-card-content-bio">{{ user.description }}</p> + <p @click.prevent="linkClicked" v-if="!hideBio && user.description_html" class="user-card-bio" v-html="user.description_html"></p> + <p v-else-if="!hideBio" class="user-card-bio">{{ user.description }}</p> </div> </div> </template> -<script src="./user_card_content.js"></script> +<script src="./user_card.js"></script> <style lang="scss"> @import '../../_variables.scss'; -.user-card-content { +.user-card { background-size: cover; overflow: hidden; diff --git a/src/components/user_panel/user_panel.js b/src/components/user_panel/user_panel.js index 15804b8847..d447829070 100644 --- a/src/components/user_panel/user_panel.js +++ b/src/components/user_panel/user_panel.js @@ -1,6 +1,6 @@ import LoginForm from '../login_form/login_form.vue' import PostStatusForm from '../post_status_form/post_status_form.vue' -import UserCardContent from '../user_card_content/user_card_content.vue' +import UserCard from '../user_card/user_card.vue' const UserPanel = { computed: { @@ -9,7 +9,7 @@ const UserPanel = { components: { LoginForm, PostStatusForm, - UserCardContent + UserCard } } diff --git a/src/components/user_panel/user_panel.vue b/src/components/user_panel/user_panel.vue index 4b3d8971e1..8310f30e4a 100644 --- a/src/components/user_panel/user_panel.vue +++ b/src/components/user_panel/user_panel.vue @@ -1,7 +1,7 @@ <template> <div class="user-panel"> <div v-if='user' class="panel panel-default" style="overflow: visible;"> - <UserCardContent :user="user" :hideBio="true" rounded="top"/> + <UserCard :user="user" :hideBio="true" rounded="top"/> <div class="panel-footer"> <post-status-form v-if='user'></post-status-form> </div> diff --git a/src/components/user_profile/user_profile.js b/src/components/user_profile/user_profile.js index cdf1cee925..54126514ed 100644 --- a/src/components/user_profile/user_profile.js +++ b/src/components/user_profile/user_profile.js @@ -1,6 +1,6 @@ import { compose } from 'vue-compose' import get from 'lodash/get' -import UserCardContent from '../user_card_content/user_card_content.vue' +import UserCard from '../user_card/user_card.vue' import FollowCard from '../follow_card/follow_card.vue' import Timeline from '../timeline/timeline.vue' import withLoadMore from '../../hocs/with_load_more/with_load_more' @@ -147,7 +147,7 @@ const UserProfile = { } }, components: { - UserCardContent, + UserCard, Timeline, FollowerList, FriendList diff --git a/src/components/user_profile/user_profile.vue b/src/components/user_profile/user_profile.vue index c57d3409ea..7d4a8b1f6f 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.id" class="user-profile panel panel-default"> - <UserCardContent :user="user" :switcher="true" :selected="timeline.viewing" rounded="top"/> + <UserCard :user="user" :switcher="true" :selected="timeline.viewing" rounded="top"/> <tab-switcher :renderOnlyFocused="true" ref="tabSwitcher"> <Timeline :label="$t('user_card.statuses')" -- GitLab From 7cb13df8adcd9ad24b017a3399137a53acb3eb4c Mon Sep 17 00:00:00 2001 From: taehoon <th.dev91@gmail.com> Date: Tue, 5 Mar 2019 14:13:22 -0500 Subject: [PATCH 18/31] Update tests --- test/unit/specs/boot/routes.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unit/specs/boot/routes.spec.js b/test/unit/specs/boot/routes.spec.js index 383ba90f2a..a415aeafc5 100644 --- a/test/unit/specs/boot/routes.spec.js +++ b/test/unit/specs/boot/routes.spec.js @@ -24,7 +24,7 @@ describe('routes', () => { const matchedComponents = router.getMatchedComponents() - expect(matchedComponents[0].components.hasOwnProperty('UserCardContent')).to.eql(true) + expect(matchedComponents[0].components.hasOwnProperty('UserCard')).to.eql(true) }) it('user\'s profile at /users', () => { @@ -32,6 +32,6 @@ describe('routes', () => { const matchedComponents = router.getMatchedComponents() - expect(matchedComponents[0].components.hasOwnProperty('UserCardContent')).to.eql(true) + expect(matchedComponents[0].components.hasOwnProperty('UserCard')).to.eql(true) }) }) -- GitLab From 37acb51df416a2475f467c0402a5e18821c5934d Mon Sep 17 00:00:00 2001 From: taehoon <th.dev91@gmail.com> Date: Tue, 5 Mar 2019 21:48:07 -0500 Subject: [PATCH 19/31] Update classname --- src/components/status/status.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/status/status.vue b/src/components/status/status.vue index 8fda68f5b0..c234bc03dc 100644 --- a/src/components/status/status.vue +++ b/src/components/status/status.vue @@ -31,7 +31,7 @@ </router-link> </div> <div class="status-body"> - <UserCard :user="status.user" :rounded="true" :bordered="true" class="status-usercard-content" v-if="userExpanded"/> + <UserCard :user="status.user" :rounded="true" :bordered="true" class="status-usercard" v-if="userExpanded"/> <div v-if="!noHeading" class="media-heading"> <div class="heading-name-row"> <div class="name-and-account-name"> @@ -246,7 +246,7 @@ $status-margin: 0.75em; padding: 0; } - .status-usercard-content { + .status-usercard { margin-bottom: $status-margin; } -- GitLab From 5f51fe897dcd7d32c46a67a8d31c8b4ffc8858b2 Mon Sep 17 00:00:00 2001 From: taehoon <th.dev91@gmail.com> Date: Tue, 5 Mar 2019 21:52:04 -0500 Subject: [PATCH 20/31] Revert modifier class notation --- src/components/user_card/user_card.js | 6 +++--- src/components/user_card/user_card.vue | 7 +++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/components/user_card/user_card.js b/src/components/user_card/user_card.js index 0cb616f46b..81c938c05c 100644 --- a/src/components/user_card/user_card.js +++ b/src/components/user_card/user_card.js @@ -18,9 +18,9 @@ export default { computed: { classes () { return [{ - 'user-card-rt': this.rounded === 'top', // set border-top-left-radius and border-top-right-radius - 'user-card-r': this.rounded === true, // set border-radius for all sides - 'user-card-b': this.bordered === true // set border for all sides + 'user-card-rounded-t': this.rounded === 'top', // set border-top-left-radius and border-top-right-radius + 'user-card-rounded': this.rounded === true, // set border-radius for all sides + 'user-card-bordered': this.bordered === true // set border for all sides }] }, style () { diff --git a/src/components/user_card/user_card.vue b/src/components/user_card/user_card.vue index b90f57a139..cc2ce6b8fe 100644 --- a/src/components/user_card/user_card.vue +++ b/src/components/user_card/user_card.vue @@ -161,22 +161,21 @@ text-align: center; } - // // Modifiers - &-rt { + &-rounded-t { border-top-left-radius: $fallback--panelRadius; border-top-left-radius: var(--panelRadius, $fallback--panelRadius); border-top-right-radius: $fallback--panelRadius; border-top-right-radius: var(--panelRadius, $fallback--panelRadius); } - &-r { + &-rounded { border-radius: $fallback--panelRadius; border-radius: var(--panelRadius, $fallback--panelRadius); } - &-b { + &-bordered { border-width: 1px; border-style: solid; border-color: $fallback--border; -- GitLab From aca3b37134ef797f9c112f9584bf42dee1d9c87e Mon Sep 17 00:00:00 2001 From: taehoon <th.dev91@gmail.com> Date: Wed, 6 Mar 2019 12:03:42 -0500 Subject: [PATCH 21/31] Use a cross browser safe solution to get scroll top --- src/components/timeline/timeline.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/timeline/timeline.js b/src/components/timeline/timeline.js index 655bfb3faf..c45f89470d 100644 --- a/src/components/timeline/timeline.js +++ b/src/components/timeline/timeline.js @@ -132,7 +132,9 @@ const Timeline = { } if (count > 0) { // only 'stream' them when you're scrolled to the top - if (window.pageYOffset < 15 && + const doc = document.documentElement + const top = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0) + if (top < 15 && !this.paused && !(this.unfocused && this.$store.state.config.pauseOnUnfocused) ) { -- GitLab From 292cdfb24b2d42d38728e8ff9ab16e2ad9e66410 Mon Sep 17 00:00:00 2001 From: Edijs <iamedijs@hotmail.com> Date: Wed, 6 Mar 2019 20:13:04 -0800 Subject: [PATCH 22/31] Merge content types translations --- src/components/post_status_form/post_status_form.js | 3 +++ src/components/post_status_form/post_status_form.vue | 6 +++--- src/components/settings/settings.vue | 2 +- src/i18n/en.json | 10 +++------- src/i18n/eo.json | 1 - src/i18n/es.json | 1 - src/i18n/ja.json | 1 - src/i18n/oc.json | 1 - src/i18n/pt.json | 1 - 9 files changed, 10 insertions(+), 16 deletions(-) diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js index c28c51bf45..23a2c7e270 100644 --- a/src/components/post_status_form/post_status_form.js +++ b/src/components/post_status_form/post_status_form.js @@ -171,6 +171,9 @@ const PostStatusForm = { }, formattingOptionsEnabled () { return this.$store.state.instance.formattingOptionsEnabled + }, + postFormats () { + return this.$store.state.instance.postFormats || [] } }, methods: { diff --git a/src/components/post_status_form/post_status_form.vue b/src/components/post_status_form/post_status_form.vue index 5085570be3..93f78f65fc 100644 --- a/src/components/post_status_form/post_status_form.vue +++ b/src/components/post_status_form/post_status_form.vue @@ -36,9 +36,9 @@ <span class="text-format" v-if="formattingOptionsEnabled"> <label for="post-content-type" class="select"> <select id="post-content-type" v-model="newStatus.contentType" class="form-control"> - <option value="text/plain">{{$t('post_status.content_type.plain_text')}}</option> - <option value="text/html">HTML</option> - <option value="text/markdown">Markdown</option> + <option v-for="postFormat in postFormats" :key="postFormat" :value="postFormat"> + {{$t(`post_status.content_type["${postFormat}"]`)}} + </option> </select> <i class="icon-down-open"></i> </label> diff --git a/src/components/settings/settings.vue b/src/components/settings/settings.vue index c0cfe1abd1..d234674728 100644 --- a/src/components/settings/settings.vue +++ b/src/components/settings/settings.vue @@ -106,7 +106,7 @@ <label for="postContentType" class="select"> <select id="postContentType" v-model="postContentTypeLocal"> <option v-for="postFormat in postFormats" :key="postFormat" :value="postFormat"> - {{$t(`settings.post_formats["${postFormat}"]`)}} + {{$t(`post_status.content_type["${postFormat}"]`)}} {{postContentTypeDefault === postFormat ? $t('settings.instance_default_simple') : ''}} </option> </select> diff --git a/src/i18n/en.json b/src/i18n/en.json index e614fb6ca2..01fe2fba21 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -71,7 +71,9 @@ "account_not_locked_warning_link": "locked", "attachments_sensitive": "Mark attachments as sensitive", "content_type": { - "plain_text": "Plain text" + "text/plain": "Plain text", + "text/html": "HTML", + "text/markdown": "Markdown" }, "content_warning": "Subject (optional)", "default": "Just landed in L.A.", @@ -220,13 +222,7 @@ "subject_line_email": "Like email: \"re: subject\"", "subject_line_mastodon": "Like mastodon: copy as is", "subject_line_noop": "Do not copy", - "post_formats": { - "text/plain": "Plain text", - "text/html": "HTML", - "text/markdown": "Markdown" - }, "post_status_content_type": "Post status content type", - "status_content_type_plain": "Plain text", "stop_gifs": "Play-on-hover GIFs", "streaming": "Enable automatic streaming of new posts when scrolled to the top", "text": "Text", diff --git a/src/i18n/eo.json b/src/i18n/eo.json index 2438b4d5f6..34851a4406 100644 --- a/src/i18n/eo.json +++ b/src/i18n/eo.json @@ -221,7 +221,6 @@ "subject_line_mastodon": "Kiel Mastodon: kopii senÅanÄe", "subject_line_noop": "Ne kopii", "post_status_content_type": "AfiÅi specon de la enhavo de la stato", - "status_content_type_plain": "Plata teksto", "stop_gifs": "Movi GIF-bildojn dum musa Åvebo", "streaming": "Åœalti memfaran fluigon de novaj afiÅoj ĉe la supro de la paÄo", "text": "Teksto", diff --git a/src/i18n/es.json b/src/i18n/es.json index 167e8c4288..fe96dd083a 100644 --- a/src/i18n/es.json +++ b/src/i18n/es.json @@ -202,7 +202,6 @@ "subject_line_mastodon": "Tipo mastodon: copiar como es", "subject_line_noop": "No copiar", "post_status_content_type": "Formato de publicación", - "status_content_type_plain": "Texto plano", "stop_gifs": "Iniciar GIFs al pasar el ratón", "streaming": "Habilite la transmisión automática de nuevas publicaciones cuando se desplaza hacia la parte superior", "text": "Texto", diff --git a/src/i18n/ja.json b/src/i18n/ja.json index b51fa7fdc7..f39a5a7c93 100644 --- a/src/i18n/ja.json +++ b/src/i18n/ja.json @@ -202,7 +202,6 @@ "subject_line_mastodon": "マストドンãµã†: ãã®ã¾ã¾ã‚³ãƒ”ー", "subject_line_noop": "コピーã—ãªã„", "post_status_content_type": "ã¨ã†ã“ã†ã®ã‚³ãƒ³ãƒ†ãƒ³ãƒˆã‚¿ã‚¤ãƒ—", - "status_content_type_plain": "プレーンテã‚スト", "stop_gifs": "カーソルをã‹ã•ããŸã¨ãã€GIFã‚’ã†ã”ã‹ã™", "streaming": "ã†ãˆã¾ã§ã‚¹ã‚¯ãƒãƒ¼ãƒ«ã—ãŸã¨ãã€ã˜ã©ã†ã¦ãã«ã‚¹ãƒˆãƒªãƒ¼ãƒŸãƒ³ã‚°ã™ã‚‹", "text": "ã‚‚ã˜", diff --git a/src/i18n/oc.json b/src/i18n/oc.json index ef32f83bd5..fd5ccc97ef 100644 --- a/src/i18n/oc.json +++ b/src/i18n/oc.json @@ -221,7 +221,6 @@ "subject_line_mastodon": "Coma mastodon : copiar tal coma es", "subject_line_noop": "Copiar pas", "post_status_content_type": "Publicar lo tipe de contengut dels estatuts", - "status_content_type_plain": "Tèxte brut", "stop_gifs": "Lançar los GIFs al subrevòl", "streaming": "Activar lo cargament automatic dels novèls estatus en anar amont", "text": "Tèxt", diff --git a/src/i18n/pt.json b/src/i18n/pt.json index 39ff6c63a7..cbc2c9a353 100644 --- a/src/i18n/pt.json +++ b/src/i18n/pt.json @@ -221,7 +221,6 @@ "subject_line_mastodon": "Como o Mastodon: copiar como está", "subject_line_noop": "Não copiar", "post_status_content_type": "Postar tipo de conteúdo do status", - "status_content_type_plain": "Texto puro", "stop_gifs": "Reproduzir GIFs ao passar o cursor em cima", "streaming": "Habilitar o fluxo automático de postagens quando ao topo da página", "text": "Texto", -- GitLab From 3468c0fd042544c28c5b24fd3fe4048114046957 Mon Sep 17 00:00:00 2001 From: dave <starpumadev@gmail.com> Date: Fri, 8 Mar 2019 13:53:46 -0500 Subject: [PATCH 23/31] #432 - prevent post status form textarea keydown event propagation --- src/components/post_status_form/post_status_form.js | 3 +++ src/components/post_status_form/post_status_form.vue | 1 + 2 files changed, 4 insertions(+) diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js index 23a2c7e270..1f0df35a0f 100644 --- a/src/components/post_status_form/post_status_form.js +++ b/src/components/post_status_form/post_status_form.js @@ -222,6 +222,9 @@ const PostStatusForm = { this.highlighted = 0 } }, + onKeydown (e) { + e.stopPropagation() + }, setCaret ({target: {selectionStart}}) { this.caret = selectionStart }, diff --git a/src/components/post_status_form/post_status_form.vue b/src/components/post_status_form/post_status_form.vue index 0ddde4ea63..3d1df91b85 100644 --- a/src/components/post_status_form/post_status_form.vue +++ b/src/components/post_status_form/post_status_form.vue @@ -20,6 +20,7 @@ ref="textarea" @click="setCaret" @keyup="setCaret" v-model="newStatus.status" :placeholder="$t('post_status.default')" rows="1" class="form-control" + @keydown="onKeydown" @keydown.down="cycleForward" @keydown.up="cycleBackward" @keydown.shift.tab="cycleBackward" -- GitLab From 07a46f7736eb881a62669f27af355713f28bee78 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" <contact@hacktivis.me> Date: Sun, 10 Mar 2019 01:56:21 +0100 Subject: [PATCH 24/31] =?UTF-8?q?user=5Fcard.vue:=20Set=20img.emoji=20to?= =?UTF-8?q?=2032=C3=9732px?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Related to https://git.pleroma.social/pleroma/pleroma/merge_requests/792 --- src/components/user_card/user_card.vue | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/components/user_card/user_card.vue b/src/components/user_card/user_card.vue index cc2ce6b8fe..7ea96e80a9 100644 --- a/src/components/user_card/user_card.vue +++ b/src/components/user_card/user_card.vue @@ -159,6 +159,11 @@ &-bio { text-align: center; + + img.emoji { + width: 32px; + height: 32px; + } } // Modifiers -- GitLab From a67881b096dc4e49db804b7267c3bf49ff78bca6 Mon Sep 17 00:00:00 2001 From: slice <ryaneft@gmail.com> Date: Sun, 10 Mar 2019 01:54:26 -0800 Subject: [PATCH 25/31] Check for websocket token before connecting to chat Closes #403. Previously, a socket to the chat channel would be opened if chat is enabled, regardless if the user is logged in or not. This patch only allows a connection to be opened if a wsToken (websocket token) is present, which prevents websocket errors from unauthenticated users. --- src/modules/api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/api.js b/src/modules/api.js index 31cb55c6d5..dc5278f8bd 100644 --- a/src/modules/api.js +++ b/src/modules/api.js @@ -50,7 +50,7 @@ const api = { }, initializeSocket (store) { // Set up websocket connection - if (!store.state.chatDisabled) { + if (!store.state.chatDisabled && store.state.wsToken) { const token = store.state.wsToken const socket = new Socket('/socket', {params: {token}}) socket.connect() -- GitLab From e618c6ffb0b974156b89f3e54737e738e94b12b3 Mon Sep 17 00:00:00 2001 From: slice <ryaneft@gmail.com> Date: Sun, 10 Mar 2019 11:23:27 -0700 Subject: [PATCH 26/31] Only connect to chat when authenticating in the first place To avoid duplication of the connection, the chat socket is destroyed upon logging out. --- src/boot/after_store.js | 4 +--- src/modules/api.js | 2 +- src/modules/chat.js | 10 +++++++++- src/modules/users.js | 4 ++++ 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/boot/after_store.js b/src/boot/after_store.js index a8e2bf35f5..cd88c188b3 100644 --- a/src/boot/after_store.js +++ b/src/boot/after_store.js @@ -89,10 +89,8 @@ const afterStoreSetup = ({ store, i18n }) => { copyInstanceOption('noAttachmentLinks') copyInstanceOption('showFeaturesPanel') - if ((config.chatDisabled)) { + if (config.chatDisabled) { store.dispatch('disableChat') - } else { - store.dispatch('initializeSocket') } return store.dispatch('setTheme', config['theme']) diff --git a/src/modules/api.js b/src/modules/api.js index dc5278f8bd..31cb55c6d5 100644 --- a/src/modules/api.js +++ b/src/modules/api.js @@ -50,7 +50,7 @@ const api = { }, initializeSocket (store) { // Set up websocket connection - if (!store.state.chatDisabled && store.state.wsToken) { + if (!store.state.chatDisabled) { const token = store.state.wsToken const socket = new Socket('/socket', {params: {token}}) socket.connect() diff --git a/src/modules/chat.js b/src/modules/chat.js index 383ac75c23..2804e5776d 100644 --- a/src/modules/chat.js +++ b/src/modules/chat.js @@ -1,12 +1,16 @@ const chat = { state: { messages: [], - channel: {state: ''} + channel: {state: ''}, + socket: null }, mutations: { setChannel (state, channel) { state.channel = channel }, + setSocket (state, socket) { + state.socket = socket + }, addMessage (state, message) { state.messages.push(message) state.messages = state.messages.slice(-19, 20) @@ -16,8 +20,12 @@ const chat = { } }, actions: { + disconnectFromChat (store) { + store.state.socket.disconnect() + }, initializeChat (store, socket) { const channel = socket.channel('chat:public') + store.commit('setSocket', socket) channel.on('new_msg', (msg) => { store.commit('addMessage', msg) }) diff --git a/src/modules/users.js b/src/modules/users.js index 4159964c79..26884750d5 100644 --- a/src/modules/users.js +++ b/src/modules/users.js @@ -292,6 +292,7 @@ const users = { logout (store) { store.commit('clearCurrentUser') + store.dispatch('disconnectFromChat') store.commit('setToken', false) store.dispatch('stopFetching', 'friends') store.commit('setBackendInteractor', backendInteractorService()) @@ -321,6 +322,9 @@ const users = { if (user.token) { store.dispatch('setWsToken', user.token) + + // Initialize the chat socket. + store.dispatch('initializeSocket') } // Start getting fresh posts. -- GitLab From 70d7ed36076081f22368bceaa42dd0548fd1c89a Mon Sep 17 00:00:00 2001 From: shpuld <shp@cock.li> Date: Sun, 10 Mar 2019 22:40:48 +0200 Subject: [PATCH 27/31] Make minId reset with minVisibleId to prevent gaps when showing new --- src/modules/statuses.js | 1 + test/unit/specs/modules/statuses.spec.js | 418 ++++++++++++----------- 2 files changed, 220 insertions(+), 199 deletions(-) diff --git a/src/modules/statuses.js b/src/modules/statuses.js index 7571b62abd..6b512fa372 100644 --- a/src/modules/statuses.js +++ b/src/modules/statuses.js @@ -333,6 +333,7 @@ export const mutations = { oldTimeline.newStatusCount = 0 oldTimeline.visibleStatuses = slice(oldTimeline.statuses, 0, 50) oldTimeline.minVisibleId = last(oldTimeline.visibleStatuses).id + oldTimeline.minId = oldTimeline.minVisibleId oldTimeline.visibleStatusesObject = {} each(oldTimeline.visibleStatuses, (status) => { oldTimeline.visibleStatusesObject[status.id] = status }) }, diff --git a/test/unit/specs/modules/statuses.spec.js b/test/unit/specs/modules/statuses.spec.js index 864b798dd1..0bbcb25a3e 100644 --- a/test/unit/specs/modules/statuses.spec.js +++ b/test/unit/specs/modules/statuses.spec.js @@ -14,238 +14,258 @@ const makeMockStatus = ({id, text, type = 'status'}) => { } } -describe('Statuses.prepareStatus', () => { - it('sets deleted flag to false', () => { - const aStatus = makeMockStatus({id: '1', text: 'Hello oniichan'}) - expect(prepareStatus(aStatus).deleted).to.eq(false) +describe('Statuses module', () => { + describe('prepareStatus', () => { + it('sets deleted flag to false', () => { + const aStatus = makeMockStatus({id: '1', text: 'Hello oniichan'}) + expect(prepareStatus(aStatus).deleted).to.eq(false) + }) }) -}) -describe('The Statuses module', () => { - it('adds the status to allStatuses and to the given timeline', () => { - const state = defaultState() - const status = makeMockStatus({id: '1'}) + describe('addNewStatuses', () => { + it('adds the status to allStatuses and to the given timeline', () => { + const state = defaultState() + const status = makeMockStatus({id: '1'}) - mutations.addNewStatuses(state, { statuses: [status], timeline: 'public' }) + mutations.addNewStatuses(state, { statuses: [status], timeline: 'public' }) - expect(state.allStatuses).to.eql([status]) - expect(state.timelines.public.statuses).to.eql([status]) - expect(state.timelines.public.visibleStatuses).to.eql([]) - expect(state.timelines.public.newStatusCount).to.equal(1) - }) + expect(state.allStatuses).to.eql([status]) + expect(state.timelines.public.statuses).to.eql([status]) + expect(state.timelines.public.visibleStatuses).to.eql([]) + expect(state.timelines.public.newStatusCount).to.equal(1) + }) - it('counts the status as new if it has not been seen on this timeline', () => { - const state = defaultState() - const status = makeMockStatus({id: '1'}) + it('counts the status as new if it has not been seen on this timeline', () => { + const state = defaultState() + const status = makeMockStatus({id: '1'}) - mutations.addNewStatuses(state, { statuses: [status], timeline: 'public' }) - mutations.addNewStatuses(state, { statuses: [status], timeline: 'friends' }) + mutations.addNewStatuses(state, { statuses: [status], timeline: 'public' }) + mutations.addNewStatuses(state, { statuses: [status], timeline: 'friends' }) - expect(state.allStatuses).to.eql([status]) - expect(state.timelines.public.statuses).to.eql([status]) - expect(state.timelines.public.visibleStatuses).to.eql([]) - expect(state.timelines.public.newStatusCount).to.equal(1) + expect(state.allStatuses).to.eql([status]) + expect(state.timelines.public.statuses).to.eql([status]) + expect(state.timelines.public.visibleStatuses).to.eql([]) + expect(state.timelines.public.newStatusCount).to.equal(1) - expect(state.allStatuses).to.eql([status]) - expect(state.timelines.friends.statuses).to.eql([status]) - expect(state.timelines.friends.visibleStatuses).to.eql([]) - expect(state.timelines.friends.newStatusCount).to.equal(1) - }) + expect(state.allStatuses).to.eql([status]) + expect(state.timelines.friends.statuses).to.eql([status]) + expect(state.timelines.friends.visibleStatuses).to.eql([]) + expect(state.timelines.friends.newStatusCount).to.equal(1) + }) - it('add the statuses to allStatuses if no timeline is given', () => { - const state = defaultState() - const status = makeMockStatus({id: '1'}) + it('add the statuses to allStatuses if no timeline is given', () => { + const state = defaultState() + const status = makeMockStatus({id: '1'}) - mutations.addNewStatuses(state, { statuses: [status] }) + mutations.addNewStatuses(state, { statuses: [status] }) - expect(state.allStatuses).to.eql([status]) - expect(state.timelines.public.statuses).to.eql([]) - expect(state.timelines.public.visibleStatuses).to.eql([]) - expect(state.timelines.public.newStatusCount).to.equal(0) - }) + expect(state.allStatuses).to.eql([status]) + expect(state.timelines.public.statuses).to.eql([]) + expect(state.timelines.public.visibleStatuses).to.eql([]) + expect(state.timelines.public.newStatusCount).to.equal(0) + }) - it('adds the status to allStatuses and to the given timeline, directly visible', () => { - const state = defaultState() - const status = makeMockStatus({id: '1'}) + it('adds the status to allStatuses and to the given timeline, directly visible', () => { + const state = defaultState() + const status = makeMockStatus({id: '1'}) - mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' }) + mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' }) - expect(state.allStatuses).to.eql([status]) - expect(state.timelines.public.statuses).to.eql([status]) - expect(state.timelines.public.visibleStatuses).to.eql([status]) - expect(state.timelines.public.newStatusCount).to.equal(0) - }) + expect(state.allStatuses).to.eql([status]) + expect(state.timelines.public.statuses).to.eql([status]) + expect(state.timelines.public.visibleStatuses).to.eql([status]) + expect(state.timelines.public.newStatusCount).to.equal(0) + }) - it('removes statuses by tag on deletion', () => { - const state = defaultState() - const status = makeMockStatus({id: '1'}) - const otherStatus = makeMockStatus({id: '3'}) - status.uri = 'xxx' - const deletion = makeMockStatus({id: '2', type: 'deletion'}) - deletion.text = 'Dolus deleted notice {{tag:gs.smuglo.li,2016-11-18:noticeId=1038007:objectType=note}}.' - deletion.uri = 'xxx' - - mutations.addNewStatuses(state, { statuses: [status, otherStatus], showImmediately: true, timeline: 'public' }) - mutations.addNewStatuses(state, { statuses: [deletion], showImmediately: true, timeline: 'public' }) - - expect(state.allStatuses).to.eql([otherStatus]) - expect(state.timelines.public.statuses).to.eql([otherStatus]) - expect(state.timelines.public.visibleStatuses).to.eql([otherStatus]) - expect(state.timelines.public.maxId).to.eql('3') - }) + it('removes statuses by tag on deletion', () => { + const state = defaultState() + const status = makeMockStatus({id: '1'}) + const otherStatus = makeMockStatus({id: '3'}) + status.uri = 'xxx' + const deletion = makeMockStatus({id: '2', type: 'deletion'}) + deletion.text = 'Dolus deleted notice {{tag:gs.smuglo.li,2016-11-18:noticeId=1038007:objectType=note}}.' + deletion.uri = 'xxx' - it('does not update the maxId when the noIdUpdate flag is set', () => { - const state = defaultState() - const status = makeMockStatus({id: '1'}) - const secondStatus = makeMockStatus({id: '2'}) + mutations.addNewStatuses(state, { statuses: [status, otherStatus], showImmediately: true, timeline: 'public' }) + mutations.addNewStatuses(state, { statuses: [deletion], showImmediately: true, timeline: 'public' }) - mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' }) - expect(state.timelines.public.maxId).to.eql('1') + expect(state.allStatuses).to.eql([otherStatus]) + expect(state.timelines.public.statuses).to.eql([otherStatus]) + expect(state.timelines.public.visibleStatuses).to.eql([otherStatus]) + expect(state.timelines.public.maxId).to.eql('3') + }) - mutations.addNewStatuses(state, { statuses: [secondStatus], showImmediately: true, timeline: 'public', noIdUpdate: true }) - expect(state.timelines.public.statuses).to.eql([secondStatus, status]) - expect(state.timelines.public.visibleStatuses).to.eql([secondStatus, status]) - expect(state.timelines.public.maxId).to.eql('1') - }) + it('does not update the maxId when the noIdUpdate flag is set', () => { + const state = defaultState() + const status = makeMockStatus({id: '1'}) + const secondStatus = makeMockStatus({id: '2'}) - it('keeps a descending by id order in timeline.visibleStatuses and timeline.statuses', () => { - const state = defaultState() - const nonVisibleStatus = makeMockStatus({id: '1'}) - const status = makeMockStatus({id: '3'}) - const statusTwo = makeMockStatus({id: '2'}) - const statusThree = makeMockStatus({id: '4'}) + mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' }) + expect(state.timelines.public.maxId).to.eql('1') - mutations.addNewStatuses(state, { statuses: [nonVisibleStatus], showImmediately: false, timeline: 'public' }) + mutations.addNewStatuses(state, { statuses: [secondStatus], showImmediately: true, timeline: 'public', noIdUpdate: true }) + expect(state.timelines.public.statuses).to.eql([secondStatus, status]) + expect(state.timelines.public.visibleStatuses).to.eql([secondStatus, status]) + expect(state.timelines.public.maxId).to.eql('1') + }) - mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' }) - mutations.addNewStatuses(state, { statuses: [statusTwo], showImmediately: true, timeline: 'public' }) + it('keeps a descending by id order in timeline.visibleStatuses and timeline.statuses', () => { + const state = defaultState() + const nonVisibleStatus = makeMockStatus({id: '1'}) + const status = makeMockStatus({id: '3'}) + const statusTwo = makeMockStatus({id: '2'}) + const statusThree = makeMockStatus({id: '4'}) - expect(state.timelines.public.minVisibleId).to.equal('2') + mutations.addNewStatuses(state, { statuses: [nonVisibleStatus], showImmediately: false, timeline: 'public' }) - mutations.addNewStatuses(state, { statuses: [statusThree], showImmediately: true, timeline: 'public' }) + mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' }) + mutations.addNewStatuses(state, { statuses: [statusTwo], showImmediately: true, timeline: 'public' }) - expect(state.timelines.public.statuses).to.eql([statusThree, status, statusTwo, nonVisibleStatus]) - expect(state.timelines.public.visibleStatuses).to.eql([statusThree, status, statusTwo]) - }) + expect(state.timelines.public.minVisibleId).to.equal('2') - it('splits retweets from their status and links them', () => { - const state = defaultState() - const status = makeMockStatus({id: '1'}) - const retweet = makeMockStatus({id: '2', type: 'retweet'}) - const modStatus = makeMockStatus({id: '1', text: 'something else'}) - - retweet.retweeted_status = status - - // It adds both statuses, but only the retweet to visible. - mutations.addNewStatuses(state, { statuses: [retweet], timeline: 'public', showImmediately: true }) - expect(state.timelines.public.visibleStatuses).to.have.length(1) - expect(state.timelines.public.statuses).to.have.length(1) - expect(state.allStatuses).to.have.length(2) - expect(state.allStatuses[0].id).to.equal('1') - expect(state.allStatuses[1].id).to.equal('2') - - // It refers to the modified status. - mutations.addNewStatuses(state, { statuses: [modStatus], timeline: 'public' }) - expect(state.allStatuses).to.have.length(2) - expect(state.allStatuses[0].id).to.equal('1') - expect(state.allStatuses[0].text).to.equal(modStatus.text) - expect(state.allStatuses[1].id).to.equal('2') - expect(retweet.retweeted_status.text).to.eql(modStatus.text) - }) + mutations.addNewStatuses(state, { statuses: [statusThree], showImmediately: true, timeline: 'public' }) - it('replaces existing statuses with the same id', () => { - const state = defaultState() - const status = makeMockStatus({id: '1'}) - const modStatus = makeMockStatus({id: '1', text: 'something else'}) - - // Add original status - mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' }) - expect(state.timelines.public.visibleStatuses).to.have.length(1) - expect(state.allStatuses).to.have.length(1) - - // Add new version of status - mutations.addNewStatuses(state, { statuses: [modStatus], showImmediately: true, timeline: 'public' }) - expect(state.timelines.public.visibleStatuses).to.have.length(1) - expect(state.allStatuses).to.have.length(1) - expect(state.allStatuses[0].text).to.eql(modStatus.text) - }) + expect(state.timelines.public.statuses).to.eql([statusThree, status, statusTwo, nonVisibleStatus]) + expect(state.timelines.public.visibleStatuses).to.eql([statusThree, status, statusTwo]) + }) - it('replaces existing statuses with the same id, coming from a retweet', () => { - const state = defaultState() - const status = makeMockStatus({id: '1'}) - const modStatus = makeMockStatus({id: '1', text: 'something else'}) - const retweet = makeMockStatus({id: '2', type: 'retweet'}) - retweet.retweeted_status = modStatus - - // Add original status - mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' }) - expect(state.timelines.public.visibleStatuses).to.have.length(1) - expect(state.allStatuses).to.have.length(1) - - // Add new version of status - mutations.addNewStatuses(state, { statuses: [retweet], showImmediately: false, timeline: 'public' }) - expect(state.timelines.public.visibleStatuses).to.have.length(1) - // Don't add the retweet itself if the tweet is visible - expect(state.timelines.public.statuses).to.have.length(1) - expect(state.allStatuses).to.have.length(2) - expect(state.allStatuses[0].text).to.eql(modStatus.text) + it('splits retweets from their status and links them', () => { + const state = defaultState() + const status = makeMockStatus({id: '1'}) + const retweet = makeMockStatus({id: '2', type: 'retweet'}) + const modStatus = makeMockStatus({id: '1', text: 'something else'}) + + retweet.retweeted_status = status + + // It adds both statuses, but only the retweet to visible. + mutations.addNewStatuses(state, { statuses: [retweet], timeline: 'public', showImmediately: true }) + expect(state.timelines.public.visibleStatuses).to.have.length(1) + expect(state.timelines.public.statuses).to.have.length(1) + expect(state.allStatuses).to.have.length(2) + expect(state.allStatuses[0].id).to.equal('1') + expect(state.allStatuses[1].id).to.equal('2') + + // It refers to the modified status. + mutations.addNewStatuses(state, { statuses: [modStatus], timeline: 'public' }) + expect(state.allStatuses).to.have.length(2) + expect(state.allStatuses[0].id).to.equal('1') + expect(state.allStatuses[0].text).to.equal(modStatus.text) + expect(state.allStatuses[1].id).to.equal('2') + expect(retweet.retweeted_status.text).to.eql(modStatus.text) + }) + + it('replaces existing statuses with the same id', () => { + const state = defaultState() + const status = makeMockStatus({id: '1'}) + const modStatus = makeMockStatus({id: '1', text: 'something else'}) + + // Add original status + mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' }) + expect(state.timelines.public.visibleStatuses).to.have.length(1) + expect(state.allStatuses).to.have.length(1) + + // Add new version of status + mutations.addNewStatuses(state, { statuses: [modStatus], showImmediately: true, timeline: 'public' }) + expect(state.timelines.public.visibleStatuses).to.have.length(1) + expect(state.allStatuses).to.have.length(1) + expect(state.allStatuses[0].text).to.eql(modStatus.text) + }) + + it('replaces existing statuses with the same id, coming from a retweet', () => { + const state = defaultState() + const status = makeMockStatus({id: '1'}) + const modStatus = makeMockStatus({id: '1', text: 'something else'}) + const retweet = makeMockStatus({id: '2', type: 'retweet'}) + retweet.retweeted_status = modStatus + + // Add original status + mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' }) + expect(state.timelines.public.visibleStatuses).to.have.length(1) + expect(state.allStatuses).to.have.length(1) + + // Add new version of status + mutations.addNewStatuses(state, { statuses: [retweet], showImmediately: false, timeline: 'public' }) + expect(state.timelines.public.visibleStatuses).to.have.length(1) + // Don't add the retweet itself if the tweet is visible + expect(state.timelines.public.statuses).to.have.length(1) + expect(state.allStatuses).to.have.length(2) + expect(state.allStatuses[0].text).to.eql(modStatus.text) + }) + + it('handles favorite actions', () => { + const state = defaultState() + const status = makeMockStatus({id: '1'}) + + const favorite = { + id: '2', + type: 'favorite', + in_reply_to_status_id: '1', // The API uses strings here... + uri: 'tag:shitposter.club,2016-08-21:fave:3895:note:773501:2016-08-21T16:52:15+00:00', + text: 'a favorited something by b', + user: { id: '99' } + } + + mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' }) + mutations.addNewStatuses(state, { statuses: [favorite], showImmediately: true, timeline: 'public' }) + + expect(state.timelines.public.visibleStatuses.length).to.eql(1) + expect(state.timelines.public.visibleStatuses[0].fave_num).to.eql(1) + expect(state.timelines.public.maxId).to.eq(favorite.id) + + // Adding it again does nothing + mutations.addNewStatuses(state, { statuses: [favorite], showImmediately: true, timeline: 'public' }) + + expect(state.timelines.public.visibleStatuses.length).to.eql(1) + expect(state.timelines.public.visibleStatuses[0].fave_num).to.eql(1) + expect(state.timelines.public.maxId).to.eq(favorite.id) + + // If something is favorited by the current user, it also sets the 'favorited' property but does not increment counter to avoid over-counting. Counter is incremented (updated, really) via response to the favorite request. + const user = { + id: '1' + } + + const ownFavorite = { + id: '3', + type: 'favorite', + in_reply_to_status_id: '1', // The API uses strings here... + uri: 'tag:shitposter.club,2016-08-21:fave:3895:note:773501:2016-08-21T16:52:15+00:00', + text: 'a favorited something by b', + user + } + + mutations.addNewStatuses(state, { statuses: [ownFavorite], showImmediately: true, timeline: 'public', user }) + + expect(state.timelines.public.visibleStatuses.length).to.eql(1) + expect(state.timelines.public.visibleStatuses[0].fave_num).to.eql(1) + expect(state.timelines.public.visibleStatuses[0].favorited).to.eql(true) + }) }) - it('handles favorite actions', () => { - const state = defaultState() - const status = makeMockStatus({id: '1'}) - - const favorite = { - id: '2', - type: 'favorite', - in_reply_to_status_id: '1', // The API uses strings here... - uri: 'tag:shitposter.club,2016-08-21:fave:3895:note:773501:2016-08-21T16:52:15+00:00', - text: 'a favorited something by b', - user: { id: '99' } - } - - mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' }) - mutations.addNewStatuses(state, { statuses: [favorite], showImmediately: true, timeline: 'public' }) - - expect(state.timelines.public.visibleStatuses.length).to.eql(1) - expect(state.timelines.public.visibleStatuses[0].fave_num).to.eql(1) - expect(state.timelines.public.maxId).to.eq(favorite.id) - - // Adding it again does nothing - mutations.addNewStatuses(state, { statuses: [favorite], showImmediately: true, timeline: 'public' }) - - expect(state.timelines.public.visibleStatuses.length).to.eql(1) - expect(state.timelines.public.visibleStatuses[0].fave_num).to.eql(1) - expect(state.timelines.public.maxId).to.eq(favorite.id) - - // If something is favorited by the current user, it also sets the 'favorited' property but does not increment counter to avoid over-counting. Counter is incremented (updated, really) via response to the favorite request. - const user = { - id: '1' - } - - const ownFavorite = { - id: '3', - type: 'favorite', - in_reply_to_status_id: '1', // The API uses strings here... - uri: 'tag:shitposter.club,2016-08-21:fave:3895:note:773501:2016-08-21T16:52:15+00:00', - text: 'a favorited something by b', - user - } - - mutations.addNewStatuses(state, { statuses: [ownFavorite], showImmediately: true, timeline: 'public', user }) - - expect(state.timelines.public.visibleStatuses.length).to.eql(1) - expect(state.timelines.public.visibleStatuses[0].fave_num).to.eql(1) - expect(state.timelines.public.visibleStatuses[0].favorited).to.eql(true) + describe('showNewStatuses', () => { + it('resets the minId to the min of the visible statuses when adding new to visible statuses', () => { + const state = defaultState() + const status = makeMockStatus({ id: '10' }) + mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' }) + const newStatus = makeMockStatus({ id: '20' }) + mutations.addNewStatuses(state, { statuses: [newStatus], showImmediately: false, timeline: 'public' }) + state.timelines.public.minId = '5' + mutations.showNewStatuses(state, { timeline: 'public' }) + + expect(state.timelines.public.visibleStatuses.length).to.eql(2) + expect(state.timelines.public.minVisibleId).to.eql('10') + expect(state.timelines.public.minId).to.eql('10') + }) }) - it('keeps userId when clearing user timeline', () => { - const state = defaultState() - state.timelines.user.userId = 123 + describe('clearTimeline', () => { + it('keeps userId when clearing user timeline', () => { + const state = defaultState() + state.timelines.user.userId = 123 - mutations.clearTimeline(state, { timeline: 'user' }) + mutations.clearTimeline(state, { timeline: 'user' }) - expect(state.timelines.user.userId).to.eql(123) + expect(state.timelines.user.userId).to.eql(123) + }) }) describe('notifications', () => { -- GitLab From d0e78df22062105435f81b1d147434af8cce1530 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" <contact@hacktivis.me> Date: Mon, 11 Mar 2019 05:14:49 +0100 Subject: [PATCH 28/31] user_card.vue: Copy over .status-content img styling --- src/components/user_card/user_card.vue | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/components/user_card/user_card.vue b/src/components/user_card/user_card.vue index 7ea96e80a9..002cb48fb7 100644 --- a/src/components/user_card/user_card.vue +++ b/src/components/user_card/user_card.vue @@ -160,9 +160,16 @@ &-bio { text-align: center; - img.emoji { - width: 32px; - height: 32px; + img { + object-fit: contain; + vertical-align: middle; + max-width: 100%; + max-height: 400px; + + .emoji { + width: 32px; + height: 32px; + } } } -- GitLab From 3414fce53b416658b20446f66fcc77167b68b6c8 Mon Sep 17 00:00:00 2001 From: Lorem Ipsum <aditoo@seznam.cz> Date: Mon, 11 Mar 2019 14:28:44 +0000 Subject: [PATCH 29/31] I18n: Update Czech translation --- src/i18n/cs.json | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/i18n/cs.json b/src/i18n/cs.json index 6326032c16..51e9d34299 100644 --- a/src/i18n/cs.json +++ b/src/i18n/cs.json @@ -71,7 +71,9 @@ "account_not_locked_warning_link": "uzamÄen", "attachments_sensitive": "OznaÄovat pÅ™Ãlohy jako citlivé", "content_type": { - "plain_text": "Prostý text" + "plain_text": "Prostý text", + "text/html": "HTML", + "text/markdown": "Markdown" }, "content_warning": "PÅ™edmÄ›t (volitelný)", "default": "PrávÄ› jsem pÅ™istál v L.A.", @@ -95,7 +97,7 @@ "new_captcha": "KliknutÃm na obrázek zÃskáte novou CAPTCHA", "username_placeholder": "napÅ™. lain", "fullname_placeholder": "napÅ™. Lain Iwakura", - "bio_placeholder": "napÅ™.\nNazdar, jsem Lain\nJsem anime dÃvka a žiji v pÅ™ÃmÄ›stském Japonsku. Možná mÄ› znáte z Wired.", + "bio_placeholder": "napÅ™.\nNazdar, jsem Lain\nJsem anime dÃvka žijÃcà v pÅ™ÃmÄ›stském Japonsku. Možná mÄ› znáte z Wired.", "validations": { "username_required": "nemůže být prázdné", "fullname_required": "nemůže být prázdné", @@ -204,7 +206,7 @@ "radii_help": "Nastavit zakulacenà rohů rozhranà (v pixelech)", "replies_in_timeline": "OdpovÄ›di v Äasové ose", "reply_link_preview": "Povolit náhledy odkazu pro odpovÄ›Ä pÅ™i pÅ™ejetà myÅ¡i", - "reply_visibility_all": "Zobrazit vÅ¡echny odpovÄ›diShow all replies", + "reply_visibility_all": "Zobrazit vÅ¡echny odpovÄ›di", "reply_visibility_following": "Zobrazit pouze odpovÄ›di směřované na mÄ› nebo uživatele, které sleduji", "reply_visibility_self": "Zobrazit pouze odpovÄ›di směřované na mÄ›", "saving_err": "Chyba pÅ™i ukládánà nastavenÃ", @@ -221,7 +223,6 @@ "subject_line_mastodon": "Jako u Mastodonu: zkopÃrovat tak, jak je", "subject_line_noop": "NekopÃrovat", "post_status_content_type": "Publikovat typ obsahu pÅ™ÃspÄ›vku", - "status_content_type_plain": "Prostý text", "stop_gifs": "PÅ™ehrávat GIFy pÅ™i pÅ™ejetà myÅ¡i", "streaming": "Povolit automatické streamovánà nových pÅ™ÃspÄ›vků pÅ™i rolovánà nahoru", "text": "Text", @@ -339,7 +340,7 @@ "button": "TlaÄÃtko", "text": "Spousta dalÅ¡Ãho {0} a {1}", "mono": "obsahu", - "input": "Just landed in L.A.", + "input": "PrávÄ› jsem pÅ™istál v L.A.", "faint_link": "pomocný manuál", "fine_print": "PÅ™eÄtÄ›te si náš {0} a nenauÄte se nic užiteÄného!", "header_faint": "Tohle je v pohodÄ›", @@ -361,7 +362,7 @@ "no_statuses": "Žádné pÅ™ÃspÄ›vky" }, "status": { - "reply_to": "OdpovÄ›dÄ›t uživateli", + "reply_to": "OdpovÄ›Ä uživateli", "replies_list": "OdpovÄ›di:" }, @@ -413,7 +414,7 @@ "upload":{ "error": { "base": "Nahrávánà selhalo.", - "file_too_big": "Soubor je úřÃliÅ¡ velký [{filesize}{filesizeunit} / {allowedsize}{allowedsizeunit}]", + "file_too_big": "Soubor je pÅ™ÃliÅ¡ velký [{filesize}{filesizeunit} / {allowedsize}{allowedsizeunit}]", "default": "Zkuste to znovu pozdÄ›ji" }, "file_size_units": { -- GitLab From d8e938bb5eb4cd538a55203ff5548ce2d2ffc66d Mon Sep 17 00:00:00 2001 From: taehoon <th.dev91@gmail.com> Date: Wed, 20 Feb 2019 13:40:34 -0500 Subject: [PATCH 30/31] Update user settings icon to pencil --- src/components/user_card/user_card.vue | 2 +- static/font/LICENSE.txt | 0 static/font/README.txt | 0 static/font/config.json | 6 ++++++ static/font/css/animation.css | 0 static/font/css/fontello-codes.css | 1 + static/font/css/fontello-embedded.css | 13 +++++++------ static/font/css/fontello-ie7-codes.css | 1 + static/font/css/fontello-ie7.css | 1 + static/font/css/fontello.css | 15 ++++++++------- static/font/demo.html | 17 +++++++++-------- static/font/font/fontello.eot | Bin 17472 -> 17760 bytes static/font/font/fontello.svg | 2 ++ static/font/font/fontello.ttf | Bin 17304 -> 17592 bytes static/font/font/fontello.woff | Bin 10572 -> 10752 bytes static/font/font/fontello.woff2 | Bin 8932 -> 9148 bytes 16 files changed, 36 insertions(+), 22 deletions(-) mode change 100644 => 100755 static/font/LICENSE.txt mode change 100644 => 100755 static/font/README.txt mode change 100644 => 100755 static/font/config.json mode change 100644 => 100755 static/font/css/animation.css mode change 100644 => 100755 static/font/css/fontello-codes.css mode change 100644 => 100755 static/font/css/fontello-embedded.css mode change 100644 => 100755 static/font/css/fontello-ie7-codes.css mode change 100644 => 100755 static/font/css/fontello-ie7.css mode change 100644 => 100755 static/font/css/fontello.css mode change 100644 => 100755 static/font/demo.html mode change 100644 => 100755 static/font/font/fontello.eot mode change 100644 => 100755 static/font/font/fontello.svg mode change 100644 => 100755 static/font/font/fontello.ttf mode change 100644 => 100755 static/font/font/fontello.woff mode change 100644 => 100755 static/font/font/fontello.woff2 diff --git a/src/components/user_card/user_card.vue b/src/components/user_card/user_card.vue index 002cb48fb7..690e1bde92 100644 --- a/src/components/user_card/user_card.vue +++ b/src/components/user_card/user_card.vue @@ -11,7 +11,7 @@ <div :title="user.name" class='user-name' v-if="user.name_html" v-html="user.name_html"></div> <div :title="user.name" class='user-name' v-else>{{user.name}}</div> <router-link :to="{ name: 'user-settings' }" v-if="!isOtherUser"> - <i class="button-icon icon-cog usersettings" :title="$t('tool_tip.user_settings')"></i> + <i class="button-icon icon-pencil usersettings" :title="$t('tool_tip.user_settings')"></i> </router-link> <a :href="user.statusnet_profile_url" target="_blank" v-if="isOtherUser && !user.is_local"> <i class="icon-link-ext usersettings"></i> diff --git a/static/font/LICENSE.txt b/static/font/LICENSE.txt old mode 100644 new mode 100755 diff --git a/static/font/README.txt b/static/font/README.txt old mode 100644 new mode 100755 diff --git a/static/font/config.json b/static/font/config.json old mode 100644 new mode 100755 index f16b802904..d72b622c04 --- a/static/font/config.json +++ b/static/font/config.json @@ -233,6 +233,12 @@ "css": "play-circled", "code": 61764, "src": "fontawesome" + }, + { + "uid": "d35a1d35efeb784d1dc9ac18b9b6c2b6", + "css": "pencil", + "code": 59416, + "src": "fontawesome" } ] } \ No newline at end of file diff --git a/static/font/css/animation.css b/static/font/css/animation.css old mode 100644 new mode 100755 diff --git a/static/font/css/fontello-codes.css b/static/font/css/fontello-codes.css old mode 100644 new mode 100755 index cdc21ef377..49175c8fe2 --- a/static/font/css/fontello-codes.css +++ b/static/font/css/fontello-codes.css @@ -23,6 +23,7 @@ .icon-plus:before { content: '\e815'; } /* 'î •' */ .icon-adjust:before { content: '\e816'; } /* 'î –' */ .icon-edit:before { content: '\e817'; } /* 'î —' */ +.icon-pencil:before { content: '\e818'; } /* 'î ˜' */ .icon-spin3:before { content: '\e832'; } /* 'î ²' */ .icon-spin4:before { content: '\e834'; } /* 'î ´' */ .icon-link-ext:before { content: '\f08e'; } /* 'ï‚Ž' */ diff --git a/static/font/css/fontello-embedded.css b/static/font/css/fontello-embedded.css old mode 100644 new mode 100755 index b24597b271..c43ad321da --- a/static/font/css/fontello-embedded.css +++ b/static/font/css/fontello-embedded.css @@ -1,15 +1,15 @@ @font-face { font-family: 'fontello'; - src: url('../font/fontello.eot?50735214'); - src: url('../font/fontello.eot?50735214#iefix') format('embedded-opentype'), - url('../font/fontello.svg?50735214#fontello') format('svg'); + src: url('../font/fontello.eot?21048049'); + src: url('../font/fontello.eot?21048049#iefix') format('embedded-opentype'), + url('../font/fontello.svg?21048049#fontello') format('svg'); font-weight: normal; font-style: normal; } @font-face { font-family: 'fontello'; - src: url('data:application/octet-stream;base64,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') format('woff'), - url('data:application/octet-stream;base64,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') format('truetype'); + src: url('data:application/octet-stream;base64,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') format('woff'), + url('data:application/octet-stream;base64,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') format('truetype'); } /* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */ /* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */ @@ -17,7 +17,7 @@ @media screen and (-webkit-min-device-pixel-ratio:0) { @font-face { font-family: 'fontello'; - src: url('../font/fontello.svg?50735214#fontello') format('svg'); + src: url('../font/fontello.svg?21048049#fontello') format('svg'); } } */ @@ -76,6 +76,7 @@ .icon-plus:before { content: '\e815'; } /* 'î •' */ .icon-adjust:before { content: '\e816'; } /* 'î –' */ .icon-edit:before { content: '\e817'; } /* 'î —' */ +.icon-pencil:before { content: '\e818'; } /* 'î ˜' */ .icon-spin3:before { content: '\e832'; } /* 'î ²' */ .icon-spin4:before { content: '\e834'; } /* 'î ´' */ .icon-link-ext:before { content: '\f08e'; } /* 'ï‚Ž' */ diff --git a/static/font/css/fontello-ie7-codes.css b/static/font/css/fontello-ie7-codes.css old mode 100644 new mode 100755 index 638813cd53..56e1144704 --- a/static/font/css/fontello-ie7-codes.css +++ b/static/font/css/fontello-ie7-codes.css @@ -23,6 +23,7 @@ .icon-plus { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } .icon-adjust { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } .icon-edit { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.icon-pencil { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } .icon-spin3 { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } .icon-spin4 { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } .icon-link-ext { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } diff --git a/static/font/css/fontello-ie7.css b/static/font/css/fontello-ie7.css old mode 100644 new mode 100755 index decbcc437a..edced9cb60 --- a/static/font/css/fontello-ie7.css +++ b/static/font/css/fontello-ie7.css @@ -34,6 +34,7 @@ .icon-plus { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } .icon-adjust { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } .icon-edit { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.icon-pencil { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } .icon-spin3 { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } .icon-spin4 { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } .icon-link-ext { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } diff --git a/static/font/css/fontello.css b/static/font/css/fontello.css old mode 100644 new mode 100755 index 63630d13e9..64a7a938e6 --- a/static/font/css/fontello.css +++ b/static/font/css/fontello.css @@ -1,11 +1,11 @@ @font-face { font-family: 'fontello'; - src: url('../font/fontello.eot?94672585'); - src: url('../font/fontello.eot?94672585#iefix') format('embedded-opentype'), - url('../font/fontello.woff2?94672585') format('woff2'), - url('../font/fontello.woff?94672585') format('woff'), - url('../font/fontello.ttf?94672585') format('truetype'), - url('../font/fontello.svg?94672585#fontello') format('svg'); + src: url('../font/fontello.eot?40679575'); + src: url('../font/fontello.eot?40679575#iefix') format('embedded-opentype'), + url('../font/fontello.woff2?40679575') format('woff2'), + url('../font/fontello.woff?40679575') format('woff'), + url('../font/fontello.ttf?40679575') format('truetype'), + url('../font/fontello.svg?40679575#fontello') format('svg'); font-weight: normal; font-style: normal; } @@ -15,7 +15,7 @@ @media screen and (-webkit-min-device-pixel-ratio:0) { @font-face { font-family: 'fontello'; - src: url('../font/fontello.svg?94672585#fontello') format('svg'); + src: url('../font/fontello.svg?40679575#fontello') format('svg'); } } */ @@ -79,6 +79,7 @@ .icon-plus:before { content: '\e815'; } /* 'î •' */ .icon-adjust:before { content: '\e816'; } /* 'î –' */ .icon-edit:before { content: '\e817'; } /* 'î —' */ +.icon-pencil:before { content: '\e818'; } /* 'î ˜' */ .icon-spin3:before { content: '\e832'; } /* 'î ²' */ .icon-spin4:before { content: '\e834'; } /* 'î ´' */ .icon-link-ext:before { content: '\f08e'; } /* 'ï‚Ž' */ diff --git a/static/font/demo.html b/static/font/demo.html old mode 100644 new mode 100755 index 9015b35922..2c89a505d3 --- a/static/font/demo.html +++ b/static/font/demo.html @@ -229,11 +229,11 @@ body { } @font-face { font-family: 'fontello'; - src: url('./font/fontello.eot?28736547'); - src: url('./font/fontello.eot?28736547#iefix') format('embedded-opentype'), - url('./font/fontello.woff?28736547') format('woff'), - url('./font/fontello.ttf?28736547') format('truetype'), - url('./font/fontello.svg?28736547#fontello') format('svg'); + src: url('./font/fontello.eot?50378338'); + src: url('./font/fontello.eot?50378338#iefix') format('embedded-opentype'), + url('./font/fontello.woff?50378338') format('woff'), + url('./font/fontello.ttf?50378338') format('truetype'), + url('./font/fontello.svg?50378338#fontello') format('svg'); font-weight: normal; font-style: normal; } @@ -334,24 +334,25 @@ body { <div class="the-icons span3" title="Code: 0xe817"><i class="demo-icon icon-edit"></i> <span class="i-name">icon-edit</span><span class="i-code">0xe817</span></div> </div> <div class="row"> + <div class="the-icons span3" title="Code: 0xe818"><i class="demo-icon icon-pencil"></i> <span class="i-name">icon-pencil</span><span class="i-code">0xe818</span></div> <div class="the-icons span3" title="Code: 0xe832"><i class="demo-icon icon-spin3 animate-spin"></i> <span class="i-name">icon-spin3</span><span class="i-code">0xe832</span></div> <div class="the-icons span3" title="Code: 0xe834"><i class="demo-icon icon-spin4 animate-spin"></i> <span class="i-name">icon-spin4</span><span class="i-code">0xe834</span></div> <div class="the-icons span3" title="Code: 0xf08e"><i class="demo-icon icon-link-ext"></i> <span class="i-name">icon-link-ext</span><span class="i-code">0xf08e</span></div> - <div class="the-icons span3" title="Code: 0xf08f"><i class="demo-icon icon-link-ext-alt"></i> <span class="i-name">icon-link-ext-alt</span><span class="i-code">0xf08f</span></div> </div> <div class="row"> + <div class="the-icons span3" title="Code: 0xf08f"><i class="demo-icon icon-link-ext-alt"></i> <span class="i-name">icon-link-ext-alt</span><span class="i-code">0xf08f</span></div> <div class="the-icons span3" title="Code: 0xf0c9"><i class="demo-icon icon-menu"></i> <span class="i-name">icon-menu</span><span class="i-code">0xf0c9</span></div> <div class="the-icons span3" title="Code: 0xf0e0"><i class="demo-icon icon-mail-alt"></i> <span class="i-name">icon-mail-alt</span><span class="i-code">0xf0e0</span></div> <div class="the-icons span3" title="Code: 0xf0e5"><i class="demo-icon icon-comment-empty"></i> <span class="i-name">icon-comment-empty</span><span class="i-code">0xf0e5</span></div> - <div class="the-icons span3" title="Code: 0xf0fe"><i class="demo-icon icon-plus-squared"></i> <span class="i-name">icon-plus-squared</span><span class="i-code">0xf0fe</span></div> </div> <div class="row"> + <div class="the-icons span3" title="Code: 0xf0fe"><i class="demo-icon icon-plus-squared"></i> <span class="i-name">icon-plus-squared</span><span class="i-code">0xf0fe</span></div> <div class="the-icons span3" title="Code: 0xf112"><i class="demo-icon icon-reply"></i> <span class="i-name">icon-reply</span><span class="i-code">0xf112</span></div> <div class="the-icons span3" title="Code: 0xf13e"><i class="demo-icon icon-lock-open-alt"></i> <span class="i-name">icon-lock-open-alt</span><span class="i-code">0xf13e</span></div> <div class="the-icons span3" title="Code: 0xf144"><i class="demo-icon icon-play-circled"></i> <span class="i-name">icon-play-circled</span><span class="i-code">0xf144</span></div> - <div class="the-icons span3" title="Code: 0xf164"><i class="demo-icon icon-thumbs-up-alt"></i> <span class="i-name">icon-thumbs-up-alt</span><span class="i-code">0xf164</span></div> </div> <div class="row"> + <div class="the-icons span3" title="Code: 0xf164"><i class="demo-icon icon-thumbs-up-alt"></i> <span class="i-name">icon-thumbs-up-alt</span><span class="i-code">0xf164</span></div> <div class="the-icons span3" title="Code: 0xf1e5"><i class="demo-icon icon-binoculars"></i> <span class="i-name">icon-binoculars</span><span class="i-code">0xf1e5</span></div> <div class="the-icons span3" title="Code: 0xf234"><i class="demo-icon icon-user-plus"></i> <span class="i-name">icon-user-plus</span><span class="i-code">0xf234</span></div> </div> diff --git a/static/font/font/fontello.eot b/static/font/font/fontello.eot old mode 100644 new mode 100755 index 30867c9265516fa35bf7f841b7a2b4b4c58e7e45..a72671b0d0dfe2fc4d11a57efae27916b5d236e6 GIT binary patch delta 916 zcmZXSOK1~O6o&sZ_hu6NPMk?wwQbr|Q?1&P)TE$Dgi3{AEiS4>i-wq{O45v4L<Q-h zSfomAog(4`3W6wzsM!=$$ij`N3tfn~G5CN8iuJiFsVB}#oXa=={O8_t@41J`o}t_X zsr$DAb6wMFQ2vNKa!!ZOj-CXl7eHSu6*Zbex4yE!35d_JV<R4QvG5b<oaK4Xppi&T zOi%T*&jO`JB6`%|coq9gtd2zT#NhSpgU5hv23S`z6ptRz?!WyG_-A=OIK%<_6Diog zX5T!N8aX}{>05lqfdvlCCeyL#`!BBsfxuPvJ5$l)2AwLu!G4~-XE>UQKfBh@2z2nF z%5x)qbfmw0*FD}l$3@Q>N8-lEEv*lMu6A>l_Rtk`ffB17AkGFU5P!ecvX*eZ0}`)z zqMolHP?4`O&nW}7Jt&Ue|A(oF9puaOigH@=p|~MGzRaNX(r68kXHd)Px4<&i4ht*? z<|i$%g7v%w>R6vxa21%(S)hUSqXj&y1q<-azqu^X#JbtS4=;aoS)iHqfCW~v@<v6l z3i!?i72&$u)p*^g1QzGScA-Lr#??1tJX~E*imlFFVV6Rw6^ei$BFOH@U03h!un#uH zmWCpfH1|xTxvhklN+c!iWFff=l4N9gc-8+ak^Xn#XmMqKm~YhRsj052T;kw5RLySF zTLU4VT@UEg;cc>$s%rs%h=RUq@@^oll6;|{zk%FO{bPY`w6Dx23om53O;Vev&llSB zV!JkwAJ8_s$F#s$U{klEmdV0P$!}UO59bSQpXhR(KJdx5SJ%hfnHlfxiWSaBkstdi zH~m7X$a916+U(&DTWap*(_73Lf1LWw-~RN<j;fNX%g#>cMdyMm=_)Kev^1-&(UQ7L sf8##QNyY!IB{Lo<6`Xb<*rU*DGZ(yLSB>~^>|oNI3|+`Hb~cp#0rXPT00000 delta 638 zcmZXRPe@cz6vn?hZ+b=JpZQmlr8(xLMQ+r|sW6$ajS%K)EJETj^PCB0@{vPKF`>)B zq-MIC78x!|q#zdqty;7zAvY4?DkK;ftc8k!RA}Gx(yDj)-S2+qa1Q6*w>l->7la<Y z3_R^G={?S6b6~g>eK?T^#1Md3JY!gut-wY4c|iLbzncx}yE|JzWRm&dsFlo2m5SHt zX91U$G{!B)-Sj!?fn@sL=w|1KIIyn(bm%G5NcdwHCV|c(^F1jB_Afde^dIR%sZ2IE zy&2p6#=s8-o~6g)#?suE5ul3=FqAQJmdMx6(XY@4ZyOo&(@b*<{WjoOvc|@<(ZGZ6 zz*#mF3)UUes$4qr4(NBwS#d+m$Uh=^T8Ch@y=i-=4(dVH>u};T6UTW44RzIkoOX;f zT!Fm?|6kIfU1bAZ8rrtBG*^AiURQfE`)ezwoULM_3#bw_P{Rrw1=b%aaE$s`fkx`0 z0!`Fa1qZ@<MS*7Ojsiho!>a%vVWUrh6IA|In^S1zA)!Es%0@Og32bs88?*uCUfpae zzYM*uYaAXhmv7eh{)9`bGKrPM?_2*=rn@7eUB2ixWo<a!Qg9z}zxDV%_dRRgytnG> m^UeF#{KZ4p4y&haFFy~vG#0#y49Z`TH*(?JlXCQYu;wo=Wv0pi diff --git a/static/font/font/fontello.svg b/static/font/font/fontello.svg old mode 100644 new mode 100755 index b5a6725a9d..91aba5ef6c --- a/static/font/font/fontello.svg +++ b/static/font/font/fontello.svg @@ -54,6 +54,8 @@ <glyph glyph-name="edit" unicode="" d="M496 196l64 65-85 85-64-65v-31h53v-54h32z m245 402q-9 9-18 0l-196-196q-9-9 0-18t18 0l196 196q9 9 0 18z m45-331v-106q0-67-47-114t-114-47h-464q-67 0-114 47t-47 114v464q0 66 47 113t114 48h464q35 0 65-14 9-4 10-13 2-10-5-16l-27-28q-8-8-18-4-13 3-25 3h-464q-37 0-63-26t-27-63v-464q0-37 27-63t63-27h464q37 0 63 27t26 63v70q0 7 5 12l36 36q8 8 20 4t11-16z m-54 411l161-160-375-375h-161v160z m248-73l-51-52-161 161 51 52q16 15 38 15t38-15l85-85q16-16 16-38t-16-38z" horiz-adv-x="1000" /> +<glyph glyph-name="pencil" unicode="" d="M203 0l50 51-131 131-51-51v-60h72v-71h60z m291 518q0 12-12 12-5 0-9-4l-303-302q-4-4-4-10 0-12 13-12 5 0 9 4l303 302q3 4 3 10z m-30 107l232-232-464-465h-232v233z m381-54q0-29-20-50l-93-93-232 233 93 92q20 21 50 21 29 0 51-21l131-131q20-22 20-51z" horiz-adv-x="857.1" /> + <glyph glyph-name="spin3" unicode="" d="M494 857c-266 0-483-210-494-472-1-19 13-20 13-20l84 0c16 0 19 10 19 18 10 199 176 358 378 358 107 0 205-45 273-118l-58-57c-11-12-11-27 5-31l247-50c21-5 46 11 37 44l-58 227c-2 9-16 22-29 13l-65-60c-89 91-214 148-352 148z m409-508c-16 0-19-10-19-18-10-199-176-358-377-358-108 0-205 45-274 118l59 57c10 12 10 27-5 31l-248 50c-21 5-46-11-37-44l58-227c2-9 16-22 30-13l64 60c89-91 214-148 353-148 265 0 482 210 493 473 1 18-13 19-13 19l-84 0z" horiz-adv-x="1000" /> <glyph glyph-name="spin4" unicode="" d="M498 857c-114 0-228-39-320-116l0 0c173 140 428 130 588-31 134-134 164-332 89-495-10-29-5-50 12-68 21-20 61-23 84 0 3 3 12 15 15 24 71 180 33 393-112 539-99 98-228 147-356 147z m-409-274c-14 0-29-5-39-16-3-3-13-15-15-24-71-180-34-393 112-539 185-185 479-195 676-31l0 0c-173-140-428-130-589 31-134 134-163 333-89 495 11 29 6 50-12 68-11 11-27 17-44 16z" horiz-adv-x="1001" /> diff --git a/static/font/font/fontello.ttf b/static/font/font/fontello.ttf old mode 100644 new mode 100755 index 87c3d0d9b8a2dab90fa7e350d42fb5f953975df6..9d36bc11823cf06fd839b4e954b8710de81bd438 GIT binary patch delta 910 zcmZXST}V@57{{OIyyu+FZ#U1Gnjf2PI?YPm<|ZUz5Eu-XNNB4>#+<X*+$kkA2rs11 zi_%VnSb-2kK~%Obgg)@18>uepLZpk5(wJdnR?vmao^`Im^YT0Y_y4}{^PJ~>I1}e_ z<|2++M@|D^8vt|!qXEU{x%Zv?T>!QkJT+($H<P~r8mDOA(yN4{m&V8Z<YxgglyG1` zq4iwy6QufZWVrYC?9-P3!Zm=M>3yL<kM#KCI)Gz}_T7E7pqt|v`33T}zUbi4n73o| z6D@4e!c-&{41E4J-wWWpNxnTA7*g;|)*bR|<SqSyXz2AVa~Xh(KFYmOVgrNztj=l5 zy+}pRC?`Y8^4^+f0Q>63{~W;^>Ol-w>j5bkkOTH_wu3aC!u7zzJZ+TH4H#r63e+X+ zD)d2Wv~3;gVeWunr#zxM%_Y@3PEa2*F>NW8n;v`o1+(Hv0YHL)LQ;nYY$J7PKoP*& zWeq4My`ljnq;ncn5Ued~fSGhz11zLT4WJ(UFls<K=^hOSSZT6P18k%{8c;z>iBdo% zz&aI_g6h5?gi1zufXx}!%0v)BqUvpMt~tLHIibXqt>YP2$T$WJ5rJ><J~Fl)YPN&G z2{GUp7o+yE7<C3AC?fJawv!;=2|V)NqUOr2Cn5I#!I9KSe>2^v%u<k_o0F!eIz&k) z$Td!nT_-zbbXm)FD9V!4;X$`OAFT~2<)Gc;c9_xh$}#HPkKLI9pM1+_2|U)a(nPW@ z!CIxRM3=PNG%7hqolPyAn8_#K@$|-B{E0-eb_FL(<gOLrs4S0~;;ZHNvx^PSy+6Bi zntnqDOHhMgLG@9GHC3O~d$3Aftq-AJ^*Le{uH5w8NkgOIx?#f@F(&hl=gmsnrHE{l s-<!@-Q0mvKihpoqFbezH;N!4bZFE1-iAtzHcr2oRabJxOd(4@C0iXHP>i_@% delta 620 zcmZXQPe>F|9LK+JM#pH)_Frw5=IELhd2y{)qNJ!x5GE0u6%xblxEt)`kV|Z_p|>oe z)~17pgdh+hC}JQwbm$PIke7(?6cH^f)<G8wq0+wNqf_(vyzl$|e*Av#H}B;wF>zBA zqay`C^Z`gDEyFG?M-J0Z1L~*b)ts)atu6!cQRekQJ8j(_FP@`+1o-T<F>EvLr_WP2 zq_fusE1hqXK=l~Vp=C@X6;2!+1v-n&AILCJGh3z5&(ODKtX%$1C9(E}f$t1F%nl`u zxv7r>K#UF0XBl~06gExK&(rId4a<Bt+0;zG0w{C#&~WZZ<i<B(KO2f?_7&4E9o_p1 zIOZQ;xgaK;Ga|i5gJ7|@sq3c>>PD7psKN&(cJdEY)RiO7S20k365i_le>vxsQ*59; zey)fh%WBt~dUJVSoBLXgijf#lCa9<GlVCfrcvpfQ)O!*%P-i7*q<)rg9xRq5Xriu4 zpaV<1*aLimr5*`dsK+I{5#=EzK`WJwJg^I>a3Bw~0q%opv(fz%eNxwO_JsNV;^sp? z;8V*?Vm|fj(m!?H#Nwje`5iMIvn$&?=HKRj5eNsa2Nr^bU^&zinhq_5i(C4)%9m|- Ze|Gs)7AWyv=XCt3Q`3Flo#@tU{{nuJp*H{k diff --git a/static/font/font/fontello.woff b/static/font/font/fontello.woff old mode 100644 new mode 100755 index 3a87b4b62144c53b65864a7c9c905ab5beed720e..35eea15d73495423f65271dfa0d9dbc0459951cb GIT binary patch delta 8534 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 KAa#a0;Qs(+^Gv4z delta 8318 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 I0F#6%d~$&)EdT%j diff --git a/static/font/font/fontello.woff2 b/static/font/font/fontello.woff2 old mode 100644 new mode 100755 index 009e5e85129e96b79a4ec9a3475434776047a811..c88c4b24f60e58032feb8176557ed610cd47b99d GIT binary patch literal 9148 zcmV;tBSYMGPew8T0RR9103*Br4*&oF07SR|03%`m0RR9100000000000000000000 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 G0002L)|8(B literal 8932 zcmV<AA{*UzPew8T0RR9103zf74*&oF07IAn03wV40RR9100000000000000000000 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 -- GitLab From 4a27c6d8d3f736e0bd46e9d0ca3dbaaa2108b9bc Mon Sep 17 00:00:00 2001 From: Shpuld Shpludson <shp@cock.li> Date: Mon, 11 Mar 2019 16:51:37 +0000 Subject: [PATCH 31/31] Add floating post-status button on mobile --- src/App.js | 4 +- src/App.scss | 25 +++++ src/App.vue | 1 + src/boot/routes.js | 2 - src/components/media_modal/media_modal.vue | 15 +-- .../mobile_post_status_modal.js | 91 +++++++++++++++++++ .../mobile_post_status_modal.vue | 76 ++++++++++++++++ src/components/side_drawer/side_drawer.vue | 15 +-- 8 files changed, 203 insertions(+), 26 deletions(-) create mode 100644 src/components/mobile_post_status_modal/mobile_post_status_modal.js create mode 100644 src/components/mobile_post_status_modal/mobile_post_status_modal.vue diff --git a/src/App.js b/src/App.js index 214e0f481b..5c27a3df1d 100644 --- a/src/App.js +++ b/src/App.js @@ -8,6 +8,7 @@ import WhoToFollowPanel from './components/who_to_follow_panel/who_to_follow_pan import ChatPanel from './components/chat_panel/chat_panel.vue' import MediaModal from './components/media_modal/media_modal.vue' import SideDrawer from './components/side_drawer/side_drawer.vue' +import MobilePostStatusModal from './components/mobile_post_status_modal/mobile_post_status_modal.vue' import { unseenNotificationsFromStore } from './services/notification_utils/notification_utils' export default { @@ -22,7 +23,8 @@ export default { WhoToFollowPanel, ChatPanel, MediaModal, - SideDrawer + SideDrawer, + MobilePostStatusModal }, data: () => ({ mobileActivePanel: 'timeline', diff --git a/src/App.scss b/src/App.scss index a0d1a804aa..598735d9ff 100644 --- a/src/App.scss +++ b/src/App.scss @@ -671,6 +671,31 @@ nav { border-radius: var(--inputRadius, $fallback--inputRadius); } +@keyframes modal-background-fadein { + from { + background-color: rgba(0, 0, 0, 0); + } + to { + background-color: rgba(0, 0, 0, 0.5); + } +} + +.modal-view { + z-index: 1000; + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + display: flex; + justify-content: center; + align-items: center; + overflow: auto; + animation-duration: 0.2s; + background-color: rgba(0, 0, 0, 0.5); + animation-name: modal-background-fadein; +} + .button-icon { font-size: 1.2em; } diff --git a/src/App.vue b/src/App.vue index acbbeb7570..4fff3d1de5 100644 --- a/src/App.vue +++ b/src/App.vue @@ -50,6 +50,7 @@ <media-modal></media-modal> </div> <chat-panel :floating="true" v-if="currentUser && chat" class="floating-chat mobile-hidden"></chat-panel> + <MobilePostStatusModal /> </div> </template> diff --git a/src/boot/routes.js b/src/boot/routes.js index cfbcb1feac..7e54a98bcb 100644 --- a/src/boot/routes.js +++ b/src/boot/routes.js @@ -13,7 +13,6 @@ import FollowRequests from 'components/follow_requests/follow_requests.vue' import OAuthCallback from 'components/oauth_callback/oauth_callback.vue' import UserSearch from 'components/user_search/user_search.vue' import Notifications from 'components/notifications/notifications.vue' -import UserPanel from 'components/user_panel/user_panel.vue' import LoginForm from 'components/login_form/login_form.vue' import ChatPanel from 'components/chat_panel/chat_panel.vue' import WhoToFollow from 'components/who_to_follow/who_to_follow.vue' @@ -43,7 +42,6 @@ export default (store) => { { name: 'friend-requests', path: '/friend-requests', component: FollowRequests }, { name: 'user-settings', path: '/user-settings', component: UserSettings }, { name: 'notifications', path: '/:username/notifications', component: Notifications }, - { name: 'new-status', path: '/:username/new-status', component: UserPanel }, { name: 'login', path: '/login', component: LoginForm }, { name: 'chat', path: '/chat', component: ChatPanel, props: () => ({ floating: false }) }, { name: 'oauth-callback', path: '/oauth-callback', component: OAuthCallback, props: (route) => ({ code: route.query.code }) }, diff --git a/src/components/media_modal/media_modal.vue b/src/components/media_modal/media_modal.vue index 427bf12b06..7f666603c0 100644 --- a/src/components/media_modal/media_modal.vue +++ b/src/components/media_modal/media_modal.vue @@ -1,5 +1,5 @@ <template> - <div class="modal-view" v-if="showing" @click.prevent="hide"> + <div class="modal-view media-modal-view" v-if="showing" @click.prevent="hide"> <img class="modal-image" v-if="type === 'image'" :src="currentMedia.url"></img> <VideoAttachment class="modal-image" @@ -32,18 +32,7 @@ <style lang="scss"> @import '../../_variables.scss'; -.modal-view { - z-index: 1000; - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; - display: flex; - justify-content: center; - align-items: center; - background-color: rgba(0, 0, 0, 0.5); - +.media-modal-view { &:hover { .modal-view-button-arrow { opacity: 0.75; diff --git a/src/components/mobile_post_status_modal/mobile_post_status_modal.js b/src/components/mobile_post_status_modal/mobile_post_status_modal.js new file mode 100644 index 0000000000..2f24dd08da --- /dev/null +++ b/src/components/mobile_post_status_modal/mobile_post_status_modal.js @@ -0,0 +1,91 @@ +import PostStatusForm from '../post_status_form/post_status_form.vue' +import { throttle } from 'lodash' + +const MobilePostStatusModal = { + components: { + PostStatusForm + }, + data () { + return { + hidden: false, + postFormOpen: false, + scrollingDown: false, + inputActive: false, + oldScrollPos: 0, + amountScrolled: 0 + } + }, + created () { + window.addEventListener('scroll', this.handleScroll) + window.addEventListener('resize', this.handleOSK) + }, + destroyed () { + window.removeEventListener('scroll', this.handleScroll) + window.removeEventListener('resize', this.handleOSK) + }, + computed: { + currentUser () { + return this.$store.state.users.currentUser + }, + isHidden () { + return this.hidden || this.inputActive + } + }, + methods: { + openPostForm () { + this.postFormOpen = true + this.hidden = true + + const el = this.$el.querySelector('textarea') + this.$nextTick(function () { + el.focus() + }) + }, + closePostForm () { + this.postFormOpen = false + this.hidden = false + }, + handleOSK () { + // This is a big hack: we're guessing from changed window sizes if the + // on-screen keyboard is active or not. This is only really important + // for phones in portrait mode and it's more important to show the button + // in normal scenarios on all phones, than it is to hide it when the + // keyboard is active. + // Guesswork based on https://www.mydevice.io/#compare-devices + + // for example, iphone 4 and android phones from the same time period + const smallPhone = window.innerWidth < 350 + const smallPhoneKbOpen = smallPhone && window.innerHeight < 345 + + const biggerPhone = !smallPhone && window.innerWidth < 450 + const biggerPhoneKbOpen = biggerPhone && window.innerHeight < 560 + if (smallPhoneKbOpen || biggerPhoneKbOpen) { + this.inputActive = true + } else { + this.inputActive = false + } + }, + handleScroll: throttle(function () { + const scrollAmount = window.scrollY - this.oldScrollPos + const scrollingDown = scrollAmount > 0 + + if (scrollingDown !== this.scrollingDown) { + this.amountScrolled = 0 + this.scrollingDown = scrollingDown + if (!scrollingDown) { + this.hidden = false + } + } else if (scrollingDown) { + this.amountScrolled += scrollAmount + if (this.amountScrolled > 100 && !this.hidden) { + this.hidden = true + } + } + + this.oldScrollPos = window.scrollY + this.scrollingDown = scrollingDown + }, 100) + } +} + +export default MobilePostStatusModal diff --git a/src/components/mobile_post_status_modal/mobile_post_status_modal.vue b/src/components/mobile_post_status_modal/mobile_post_status_modal.vue new file mode 100644 index 0000000000..0a451c2864 --- /dev/null +++ b/src/components/mobile_post_status_modal/mobile_post_status_modal.vue @@ -0,0 +1,76 @@ +<template> +<div v-if="currentUser"> + <div + class="post-form-modal-view modal-view" + v-show="postFormOpen" + @click="closePostForm" + > + <div class="post-form-modal-panel panel" @click.stop=""> + <div class="panel-heading">{{$t('post_status.new_status')}}</div> + <PostStatusForm class="panel-body" @posted="closePostForm"/> + </div> + </div> + <button + class="new-status-button" + :class="{ 'hidden': isHidden }" + @click="openPostForm" + > + <i class="icon-edit" /> + </button> +</div> +</template> + +<script src="./mobile_post_status_modal.js"></script> + +<style lang="scss"> +@import '../../_variables.scss'; + +.post-form-modal-view { + max-height: 100%; + display: block; +} + +.post-form-modal-panel { + flex-shrink: 0; + margin: 25% 0 4em 0; + width: 100%; +} + +.new-status-button { + width: 5em; + height: 5em; + border-radius: 100%; + position: fixed; + bottom: 1.5em; + right: 1.5em; + // TODO: this needs its own color, it has to stand out enough and link color + // is not very optimal for this particular use. + background-color: $fallback--fg; + background-color: var(--btn, $fallback--fg); + display: flex; + justify-content: center; + align-items: center; + box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3), 0px 4px 6px rgba(0, 0, 0, 0.3); + z-index: 10; + + transition: 0.35s transform; + transition-timing-function: cubic-bezier(0, 1, 0.5, 1); + + &.hidden { + transform: translateY(150%); + } + + i { + font-size: 1.5em; + color: $fallback--text; + color: var(--text, $fallback--text); + } +} + +@media all and (min-width: 801px) { + .new-status-button { + display: none; + } +} + +</style> diff --git a/src/components/side_drawer/side_drawer.vue b/src/components/side_drawer/side_drawer.vue index b608b008dc..95ee21b449 100644 --- a/src/components/side_drawer/side_drawer.vue +++ b/src/components/side_drawer/side_drawer.vue @@ -15,12 +15,7 @@ </div> </div> <ul> - <li v-if="currentUser" @click="toggleDrawer"> - <router-link :to="{ name: 'new-status', params: { username: currentUser.screen_name } }"> - {{ $t("post_status.new_status") }} - </router-link> - </li> - <li v-else @click="toggleDrawer"> + <li v-if="!currentUser" @click="toggleDrawer"> <router-link :to="{ name: 'login' }"> {{ $t("login.login") }} </router-link> @@ -119,14 +114,14 @@ } .side-drawer-container-open { - transition-delay: 0.0s; - transition-property: left; + transition: 0.35s; + transition-property: background-color; + background-color: rgba(0, 0, 0, 0.5); } .side-drawer-container-closed { left: -100%; - transition-delay: 0.5s; - transition-property: left; + background-color: rgba(0, 0, 0, 0); } .side-drawer-click-outside { -- GitLab