From 3a689ef8eead0503b90d3c9dec3b15fa0ace8eb6 Mon Sep 17 00:00:00 2001 From: taehoon Date: Mon, 25 Feb 2019 02:10:59 -0500 Subject: [PATCH 01/27] Allow HOCs to accept additional props --- src/hocs/with_load_more/with_load_more.js | 5 +++-- src/hocs/with_subscription/with_subscription.js | 10 +++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/hocs/with_load_more/with_load_more.js b/src/hocs/with_load_more/with_load_more.js index e862a39b..a521014c 100644 --- a/src/hocs/with_load_more/with_load_more.js +++ b/src/hocs/with_load_more/with_load_more.js @@ -6,10 +6,11 @@ import './with_load_more.scss' const withLoadMore = ({ fetch, // function to fetch entries and return a promise select, // function to select data from store - childPropName = 'entries' // name of the prop to be passed into the wrapped component + childPropName = 'entries', // name of the prop to be passed into the wrapped component + additionalPropNames = [] // additional prop name list of the wrapper component }) => (WrappedComponent) => { const originalProps = WrappedComponent.props || [] - const props = filter(originalProps, v => v !== 'entries') + const props = filter(originalProps, v => v !== childPropName).concat(additionalPropNames) return Vue.component('withLoadMore', { render (createElement) { diff --git a/src/hocs/with_subscription/with_subscription.js b/src/hocs/with_subscription/with_subscription.js index 1ac67cba..b6bc8358 100644 --- a/src/hocs/with_subscription/with_subscription.js +++ b/src/hocs/with_subscription/with_subscription.js @@ -1,16 +1,16 @@ import Vue from 'vue' -import reject from 'lodash/reject' +import filter from 'lodash/filter' import isEmpty from 'lodash/isEmpty' -import omit from 'lodash/omit' import './with_subscription.scss' const withSubscription = ({ fetch, // function to fetch entries and return a promise select, // function to select data from store - childPropName = 'content' // name of the prop to be passed into the wrapped component + childPropName = 'content', // name of the prop to be passed into the wrapped component + additionalPropNames = [] // additional prop name list of the wrapper component }) => (WrappedComponent) => { const originalProps = WrappedComponent.props || [] - const props = reject(originalProps, v => v === 'content') + const props = filter(originalProps, v => v !== childPropName).concat(additionalPropNames) return Vue.component('withSubscription', { props: [ @@ -21,7 +21,7 @@ const withSubscription = ({ if (!this.error && !this.loading) { const props = { props: { - ...omit(this.$props, 'refresh'), + ...this.$props, [childPropName]: this.fetchedData }, on: this.$listeners, From 5c43374588b810bf1ba8b74414867d0324b3c59f Mon Sep 17 00:00:00 2001 From: taehoon Date: Mon, 25 Feb 2019 02:11:39 -0500 Subject: [PATCH 02/27] Clean up addFollowers action --- src/modules/users.js | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/modules/users.js b/src/modules/users.js index eabfe5ae..b2821a92 100644 --- a/src/modules/users.js +++ b/src/modules/users.js @@ -189,17 +189,13 @@ const users = { }) }, addFollowers ({ rootState, commit }, fetchBy) { - return new Promise((resolve, reject) => { - const user = rootState.users.usersObject[fetchBy] - const page = user.followersPage || 1 - rootState.api.backendInteractor.fetchFollowers({ id: user.id, page }) - .then((followers) => { - commit('addFollowers', { id: user.id, followers, page }) - resolve(followers) - }).catch(() => { - reject() - }) - }) + const user = rootState.users.usersObject[fetchBy] + const page = user.followersPage || 1 + return rootState.api.backendInteractor.fetchFollowers({ id: user.id, page }) + .then((followers) => { + commit('addFollowers', { id: user.id, followers, page }) + return followers + }) }, clearFriendsAndFollowers ({ commit }, userKey) { commit('clearFriendsAndFollowers', userKey) From cb383df517dc5cd5b4d90136b533977a33611b71 Mon Sep 17 00:00:00 2001 From: taehoon Date: Mon, 25 Feb 2019 04:18:41 -0500 Subject: [PATCH 03/27] Fix bug to get wrapped component prop name list --- src/hocs/with_load_more/with_load_more.js | 3 ++- src/hocs/with_subscription/with_subscription.js | 3 ++- src/services/component_utils/component_utils.js | 10 ++++++++++ 3 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 src/services/component_utils/component_utils.js diff --git a/src/hocs/with_load_more/with_load_more.js b/src/hocs/with_load_more/with_load_more.js index a521014c..7d53e7ac 100644 --- a/src/hocs/with_load_more/with_load_more.js +++ b/src/hocs/with_load_more/with_load_more.js @@ -1,6 +1,7 @@ import Vue from 'vue' import filter from 'lodash/filter' import isEmpty from 'lodash/isEmpty' +import { getComponentProps } from '../../services/component_utils/component_utils' import './with_load_more.scss' const withLoadMore = ({ @@ -9,7 +10,7 @@ const withLoadMore = ({ childPropName = 'entries', // name of the prop to be passed into the wrapped component additionalPropNames = [] // additional prop name list of the wrapper component }) => (WrappedComponent) => { - const originalProps = WrappedComponent.props || [] + const originalProps = Object.keys(getComponentProps(WrappedComponent)) const props = filter(originalProps, v => v !== childPropName).concat(additionalPropNames) return Vue.component('withLoadMore', { diff --git a/src/hocs/with_subscription/with_subscription.js b/src/hocs/with_subscription/with_subscription.js index b6bc8358..4d3ae811 100644 --- a/src/hocs/with_subscription/with_subscription.js +++ b/src/hocs/with_subscription/with_subscription.js @@ -1,6 +1,7 @@ import Vue from 'vue' import filter from 'lodash/filter' import isEmpty from 'lodash/isEmpty' +import { getComponentProps } from '../../services/component_utils/component_utils' import './with_subscription.scss' const withSubscription = ({ @@ -9,7 +10,7 @@ const withSubscription = ({ childPropName = 'content', // name of the prop to be passed into the wrapped component additionalPropNames = [] // additional prop name list of the wrapper component }) => (WrappedComponent) => { - const originalProps = WrappedComponent.props || [] + const originalProps = Object.keys(getComponentProps(WrappedComponent)) const props = filter(originalProps, v => v !== childPropName).concat(additionalPropNames) return Vue.component('withSubscription', { diff --git a/src/services/component_utils/component_utils.js b/src/services/component_utils/component_utils.js new file mode 100644 index 00000000..77ea14a1 --- /dev/null +++ b/src/services/component_utils/component_utils.js @@ -0,0 +1,10 @@ +import isFunction from 'lodash/isFunction' + +const getComponentOptions = (Component) => (isFunction(Component)) ? Component.options : Component + +const getComponentProps = (Component) => getComponentOptions(Component).props + +export { + getComponentOptions, + getComponentProps +} From 080786c9458ba8b9db1ea63732824a3e297e10dc Mon Sep 17 00:00:00 2001 From: taehoon Date: Mon, 25 Feb 2019 04:51:23 -0500 Subject: [PATCH 04/27] Rewrite FollowList using hocs --- src/components/follow_list/follow_list.js | 68 -------------------- src/components/follow_list/follow_list.vue | 33 ---------- src/components/user_profile/user_profile.js | 29 ++++++++- src/components/user_profile/user_profile.vue | 10 +-- src/hocs/with_load_more/with_load_more.js | 2 + src/modules/users.js | 19 ++++-- 6 files changed, 45 insertions(+), 116 deletions(-) delete mode 100644 src/components/follow_list/follow_list.js delete mode 100644 src/components/follow_list/follow_list.vue diff --git a/src/components/follow_list/follow_list.js b/src/components/follow_list/follow_list.js deleted file mode 100644 index 9777c87e..00000000 --- a/src/components/follow_list/follow_list.js +++ /dev/null @@ -1,68 +0,0 @@ -import UserCard from '../user_card/user_card.vue' - -const FollowList = { - data () { - return { - loading: false, - bottomedOut: false, - error: false - } - }, - props: ['userId', 'showFollowers'], - created () { - window.addEventListener('scroll', this.scrollLoad) - if (this.entries.length === 0) { - this.fetchEntries() - } - }, - destroyed () { - window.removeEventListener('scroll', this.scrollLoad) - this.$store.dispatch('clearFriendsAndFollowers', this.userId) - }, - computed: { - user () { - return this.$store.getters.userById(this.userId) - }, - entries () { - return this.showFollowers ? this.user.followers : this.user.friends - }, - showFollowsYou () { - return !this.showFollowers || (this.showFollowers && this.userId !== this.$store.state.users.currentUser.id) - } - }, - methods: { - fetchEntries () { - if (!this.loading) { - const command = this.showFollowers ? 'addFollowers' : 'addFriends' - this.loading = true - this.$store.dispatch(command, this.userId).then(entries => { - this.error = false - this.loading = false - this.bottomedOut = entries.length === 0 - }).catch(() => { - this.error = true - this.loading = false - }) - } - }, - scrollLoad (e) { - const bodyBRect = document.body.getBoundingClientRect() - const height = Math.max(bodyBRect.height, -(bodyBRect.y)) - if (this.loading === false && - this.bottomedOut === false && - this.$el.offsetHeight > 0 && - (window.innerHeight + window.pageYOffset) >= (height - 750) - ) { - this.fetchEntries() - } - } - }, - watch: { - 'user': 'fetchEntries' - }, - components: { - UserCard - } -} - -export default FollowList diff --git a/src/components/follow_list/follow_list.vue b/src/components/follow_list/follow_list.vue deleted file mode 100644 index 27102edf..00000000 --- a/src/components/follow_list/follow_list.vue +++ /dev/null @@ -1,33 +0,0 @@ - - - - - diff --git a/src/components/user_profile/user_profile.js b/src/components/user_profile/user_profile.js index ebf6c61a..9f9d43e4 100644 --- a/src/components/user_profile/user_profile.js +++ b/src/components/user_profile/user_profile.js @@ -1,8 +1,32 @@ +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 Timeline from '../timeline/timeline.vue' -import FollowList from '../follow_list/follow_list.vue' +import withLoadMore from '../../hocs/with_load_more/with_load_more' +import withList from '../../hocs/with_list/with_list' + +const FollowerList = compose( + withLoadMore({ + fetch: (props, $store) => $store.dispatch('addFollowers', props.userId), + select: (props, $store) => get($store.getters.userById(props.userId), 'followers', []), + destory: (props, $store) => $store.dispatch('clearFollowers', props.userId), + childPropName: 'entries', + additionalPropNames: ['userId'] + }), + withList({ getEntryProps: user => ({ user }) }) +)(UserCard) + +const FriendList = compose( + withLoadMore({ + fetch: (props, $store) => $store.dispatch('addFriends', props.userId), + select: (props, $store) => get($store.getters.userById(props.userId), 'friends', []), + destory: (props, $store) => $store.dispatch('clearFriends', props.userId), + childPropName: 'entries', + additionalPropNames: ['userId'] + }), + withList({ getEntryProps: user => ({ user }) }) +)(UserCard) const UserProfile = { data () { @@ -123,7 +147,8 @@ const UserProfile = { UserCardContent, UserCard, Timeline, - FollowList + FollowerList, + FriendList } } diff --git a/src/components/user_profile/user_profile.vue b/src/components/user_profile/user_profile.vue index ba1a7760..a3d2825f 100644 --- a/src/components/user_profile/user_profile.vue +++ b/src/components/user_profile/user_profile.vue @@ -18,16 +18,10 @@ :user-id="fetchBy" />
- -
- -
+
- -
- -
+
(WrappedComponent) => { @@ -58,6 +59,7 @@ const withLoadMore = ({ }, destroyed () { window.removeEventListener('scroll', this.scrollLoad) + destroy && destroy(this.$props, this.$store) }, methods: { fetchEntries () { diff --git a/src/modules/users.js b/src/modules/users.js index b2821a92..093af497 100644 --- a/src/modules/users.js +++ b/src/modules/users.js @@ -72,14 +72,20 @@ export const mutations = { }, // Because frontend doesn't have a reason to keep these stuff in memory // outside of viewing someones user profile. - clearFriendsAndFollowers (state, userKey) { - const user = state.usersObject[userKey] + clearFriends (state, userId) { + const user = state.usersObject[userId] if (!user) { return } user.friends = [] - user.followers = [] user.friendsPage = 0 + }, + clearFollowers (state, userId) { + const user = state.usersObject[userId] + if (!user) { + return + } + user.followers = [] user.followersPage = 0 }, addNewUsers (state, users) { @@ -197,8 +203,11 @@ const users = { return followers }) }, - clearFriendsAndFollowers ({ commit }, userKey) { - commit('clearFriendsAndFollowers', userKey) + clearFriends ({ commit }, userId) { + commit('clearFriends', userId) + }, + clearFollowers ({ commit }, userId) { + commit('clearFollowers', userId) }, registerPushNotifications (store) { const token = store.state.currentUser.credentials From bb1fac4bc202c58064ee94d124967db463b3178e Mon Sep 17 00:00:00 2001 From: taehoon Date: Mon, 25 Feb 2019 07:36:38 -0500 Subject: [PATCH 05/27] Remove needless component local registration --- src/components/user_profile/user_profile.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/user_profile/user_profile.js b/src/components/user_profile/user_profile.js index 9f9d43e4..643727de 100644 --- a/src/components/user_profile/user_profile.js +++ b/src/components/user_profile/user_profile.js @@ -145,7 +145,6 @@ const UserProfile = { }, components: { UserCardContent, - UserCard, Timeline, FollowerList, FriendList From 3f9fd07f93b470f59a90abc3ee914d03a11efb87 Mon Sep 17 00:00:00 2001 From: taehoon Date: Mon, 25 Feb 2019 16:30:27 -0500 Subject: [PATCH 06/27] Remove non-existing prop binding --- src/components/follow_requests/follow_requests.vue | 2 +- src/components/user_search/user_search.vue | 2 +- src/components/who_to_follow/who_to_follow.vue | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/follow_requests/follow_requests.vue b/src/components/follow_requests/follow_requests.vue index 87dc4194..afa3fcaf 100644 --- a/src/components/follow_requests/follow_requests.vue +++ b/src/components/follow_requests/follow_requests.vue @@ -4,7 +4,7 @@ {{$t('nav.friend_requests')}}
- +
diff --git a/src/components/user_search/user_search.vue b/src/components/user_search/user_search.vue index b39e10f4..8e07f62b 100644 --- a/src/components/user_search/user_search.vue +++ b/src/components/user_search/user_search.vue @@ -13,7 +13,7 @@
- +
diff --git a/src/components/who_to_follow/who_to_follow.vue b/src/components/who_to_follow/who_to_follow.vue index df2e03c8..e148a089 100644 --- a/src/components/who_to_follow/who_to_follow.vue +++ b/src/components/who_to_follow/who_to_follow.vue @@ -4,7 +4,7 @@ {{$t('who_to_follow.who_to_follow')}}
- +
From 3ab42efbc3534c732446f8ee1b8cb9fef4bf7f69 Mon Sep 17 00:00:00 2001 From: taehoon Date: Mon, 25 Feb 2019 16:30:45 -0500 Subject: [PATCH 07/27] Remove unused component local registration --- src/components/timeline/timeline.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/components/timeline/timeline.js b/src/components/timeline/timeline.js index 62536bc5..d986663e 100644 --- a/src/components/timeline/timeline.js +++ b/src/components/timeline/timeline.js @@ -1,7 +1,6 @@ import Status from '../status/status.vue' import timelineFetcher from '../../services/timeline_fetcher/timeline_fetcher.service.js' import StatusOrConversation from '../status_or_conversation/status_or_conversation.vue' -import UserCard from '../user_card/user_card.vue' import { throttle } from 'lodash' const Timeline = { @@ -44,8 +43,7 @@ const Timeline = { }, components: { Status, - StatusOrConversation, - UserCard + StatusOrConversation }, created () { const store = this.$store From 784523b8ec7cb40def78dd6bb3682813f8052ee5 Mon Sep 17 00:00:00 2001 From: taehoon Date: Mon, 25 Feb 2019 22:49:50 -0500 Subject: [PATCH 08/27] Use big avatar in BasicUserCard --- src/components/basic_user_card/basic_user_card.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/basic_user_card/basic_user_card.vue b/src/components/basic_user_card/basic_user_card.vue index 4ede15e9..bd7a325e 100644 --- a/src/components/basic_user_card/basic_user_card.vue +++ b/src/components/basic_user_card/basic_user_card.vue @@ -1,7 +1,7 @@ From 0d283c3f17f24533f092468ded5547900478c63d Mon Sep 17 00:00:00 2001 From: taehoon Date: Mon, 25 Feb 2019 23:35:06 -0500 Subject: [PATCH 15/27] Remove UserCard --- src/components/user_card/user_card.js | 64 ---------- src/components/user_card/user_card.vue | 159 ------------------------- 2 files changed, 223 deletions(-) delete mode 100644 src/components/user_card/user_card.js delete mode 100644 src/components/user_card/user_card.vue diff --git a/src/components/user_card/user_card.js b/src/components/user_card/user_card.js deleted file mode 100644 index 28e22f09..00000000 --- a/src/components/user_card/user_card.js +++ /dev/null @@ -1,64 +0,0 @@ -import UserCardContent from '../user_card_content/user_card_content.vue' -import UserAvatar from '../user_avatar/user_avatar.vue' -import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator' -import { requestFollow, requestUnfollow } from '../../services/follow_manipulate/follow_manipulate' - -const UserCard = { - props: [ - 'user', - 'noFollowsYou', - 'showApproval' - ], - data () { - return { - userExpanded: false, - followRequestInProgress: false, - followRequestSent: false, - updated: false - } - }, - components: { - UserCardContent, - UserAvatar - }, - computed: { - currentUser () { return this.$store.state.users.currentUser }, - following () { return this.updated ? this.updated.following : this.user.following }, - showFollow () { - return !this.showApproval && (!this.following || this.updated && !this.updated.following) - } - }, - methods: { - toggleUserExpanded () { - this.userExpanded = !this.userExpanded - }, - approveUser () { - this.$store.state.api.backendInteractor.approveUser(this.user.id) - this.$store.dispatch('removeFollowRequest', this.user) - }, - denyUser () { - this.$store.state.api.backendInteractor.denyUser(this.user.id) - this.$store.dispatch('removeFollowRequest', this.user) - }, - userProfileLink (user) { - return generateProfileLink(user.id, user.screen_name, this.$store.state.instance.restrictedNicknames) - }, - followUser () { - this.followRequestInProgress = true - requestFollow(this.user, this.$store).then(({ sent, updated }) => { - this.followRequestInProgress = false - this.followRequestSent = sent - this.updated = updated - }) - }, - unfollowUser () { - this.followRequestInProgress = true - requestUnfollow(this.user, this.$store).then(({ updated }) => { - this.followRequestInProgress = false - this.updated = updated - }) - } - } -} - -export default UserCard diff --git a/src/components/user_card/user_card.vue b/src/components/user_card/user_card.vue deleted file mode 100644 index ce4edb3c..00000000 --- a/src/components/user_card/user_card.vue +++ /dev/null @@ -1,159 +0,0 @@ - - - - - From 30f5bf1463cf7f850df5a50253eb69c1c48db371 Mon Sep 17 00:00:00 2001 From: taehoon Date: Tue, 26 Feb 2019 06:57:29 -0500 Subject: [PATCH 16/27] Remove legacy class names in BasicUserCard --- .../basic_user_card/basic_user_card.vue | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/components/basic_user_card/basic_user_card.vue b/src/components/basic_user_card/basic_user_card.vue index 020f82c1..cb73d54d 100644 --- a/src/components/basic_user_card/basic_user_card.vue +++ b/src/components/basic_user_card/basic_user_card.vue @@ -9,15 +9,13 @@
-
+
{{ user.name }}
-
- - @{{user.screen_name}} - -
+ + @{{user.screen_name}} +
@@ -61,13 +59,14 @@ &-primary-area { flex: 1; - .user-name { - img { - object-fit: contain; - height: 16px; - width: 16px; - vertical-align: middle; - } + } + + &-user-name { + img { + object-fit: contain; + height: 16px; + width: 16px; + vertical-align: middle; } } From 8dd42cfc65cb572c5e218d01a0a19ab14d1e5591 Mon Sep 17 00:00:00 2001 From: taehoon Date: Tue, 26 Feb 2019 07:13:09 -0500 Subject: [PATCH 17/27] Add back some css --- .../user_card_content/user_card_content.vue | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/components/user_card_content/user_card_content.vue b/src/components/user_card_content/user_card_content.vue index a3d24eb1..689b9ec6 100644 --- a/src/components/user_card_content/user_card_content.vue +++ b/src/components/user_card_content/user_card_content.vue @@ -222,6 +222,13 @@ overflow: hidden; flex: 1 1 auto; margin-right: 1em; + + img { + object-fit: contain; + height: 16px; + width: 16px; + vertical-align: middle; + } } .user-screen-name { @@ -386,4 +393,24 @@ } } +.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; + } +} From 1fecac9ba6350216bb02ef156aa1573b546cee7f Mon Sep 17 00:00:00 2001 From: taehoon Date: Tue, 26 Feb 2019 10:14:12 -0500 Subject: [PATCH 18/27] Update naming --- src/components/basic_user_card/basic_user_card.vue | 4 ++-- src/components/follow_card/follow_card.js | 10 +++++----- src/components/follow_card/follow_card.vue | 10 +++++----- .../follow_request_card/follow_request_card.vue | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/components/basic_user_card/basic_user_card.vue b/src/components/basic_user_card/basic_user_card.vue index cb73d54d..af4ffc08 100644 --- a/src/components/basic_user_card/basic_user_card.vue +++ b/src/components/basic_user_card/basic_user_card.vue @@ -21,8 +21,8 @@
-
- +
+
diff --git a/src/components/follow_card/follow_card.js b/src/components/follow_card/follow_card.js index 85e6a6d2..425c9c3e 100644 --- a/src/components/follow_card/follow_card.js +++ b/src/components/follow_card/follow_card.js @@ -8,7 +8,7 @@ const FollowCard = { ], data () { return { - progress: false, + inProgress: false, requestSent: false, updated: false } @@ -25,17 +25,17 @@ const FollowCard = { }, methods: { followUser () { - this.progress = true + this.inProgress = true requestFollow(this.user, this.$store).then(({ sent, updated }) => { - this.progress = false + this.inProgress = false this.requestSent = sent this.updated = updated }) }, unfollowUser () { - this.progress = true + this.inProgress = true requestUnfollow(this.user, this.$store).then(({ updated }) => { - this.progress = false + this.inProgress = false this.updated = updated }) } diff --git a/src/components/follow_card/follow_card.vue b/src/components/follow_card/follow_card.vue index 936307c4..e6933e3c 100644 --- a/src/components/follow_card/follow_card.vue +++ b/src/components/follow_card/follow_card.vue @@ -5,10 +5,10 @@ v-if="showFollow" class="btn btn-default" @click="followUser" - :disabled="progress" + :disabled="inProgress" :title="requestSent ? $t('user_card.follow_again') : ''" > -