From dbfca224d812c2ba80a48852ba047bb65c4c6dd9 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Thu, 4 Aug 2022 01:56:52 +0300 Subject: server-side storage for flags --- src/modules/users.js | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/modules/users.js') diff --git a/src/modules/users.js b/src/modules/users.js index 13d4e318..b6fb9746 100644 --- a/src/modules/users.js +++ b/src/modules/users.js @@ -525,6 +525,7 @@ const users = { user.muteIds = [] user.domainMutes = [] commit('setCurrentUser', user) + commit('setServerSideStorage', user) commit('addNewUsers', [user]) store.dispatch('fetchEmoji') @@ -534,6 +535,7 @@ const users = { // Set our new backend interactor commit('setBackendInteractor', backendInteractorService(accessToken)) + store.dispatch('pushServerSideStorage') if (user.token) { store.dispatch('setWsToken', user.token) -- cgit v1.2.3-70-g09d2 From 09f9640be168d82f39491831dd9f8be4c682afb2 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Tue, 9 Aug 2022 22:11:55 -0400 Subject: Use lookup endpoint to obtain users by nickname --- src/components/user_profile/user_profile.js | 15 ++++++++++----- src/modules/users.js | 7 +++++++ src/services/api/api.service.js | 21 +++++++++++++++++++++ 3 files changed, 38 insertions(+), 5 deletions(-) (limited to 'src/modules/users.js') diff --git a/src/components/user_profile/user_profile.js b/src/components/user_profile/user_profile.js index f779b823..781fd601 100644 --- a/src/components/user_profile/user_profile.js +++ b/src/components/user_profile/user_profile.js @@ -45,7 +45,7 @@ const UserProfile = { }, created () { const routeParams = this.$route.params - this.load(routeParams.name || routeParams.id) + this.load({ name: routeParams.name, id: routeParams.id }) this.tab = get(this.$route, 'query.tab', defaultTabKey) }, unmounted () { @@ -106,12 +106,17 @@ const UserProfile = { this.userId = null this.error = false + const maybeId = userNameOrId.id + const maybeName = userNameOrId.name + // Check if user data is already loaded in store - const user = this.$store.getters.findUser(userNameOrId) + const user = this.$store.getters.findUser(maybeId || maybeName) if (user) { loadById(user.id) } else { - this.$store.dispatch('fetchUser', userNameOrId) + (maybeId + ? this.$store.dispatch('fetchUser', maybeId) + : this.$store.dispatch('fetchUserByName', maybeName)) .then(({ id }) => loadById(id)) .catch((reason) => { const errorMessage = get(reason, 'error.error') @@ -150,12 +155,12 @@ const UserProfile = { watch: { '$route.params.id': function (newVal) { if (newVal) { - this.switchUser(newVal) + this.switchUser({ id: newVal }) } }, '$route.params.name': function (newVal) { if (newVal) { - this.switchUser(newVal) + this.switchUser({ name: newVal }) } }, '$route.query': function (newVal) { diff --git a/src/modules/users.js b/src/modules/users.js index b6fb9746..47dc8493 100644 --- a/src/modules/users.js +++ b/src/modules/users.js @@ -285,6 +285,13 @@ const users = { return user }) }, + fetchUserByName (store, name) { + return store.rootState.api.backendInteractor.fetchUserByName({ name }) + .then((user) => { + store.commit('addNewUsers', [user]) + return user + }) + }, fetchUserRelationship (store, id) { if (store.state.currentUser) { store.rootState.api.backendInteractor.fetchUserRelationship({ id }) diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js index 7b6f7d67..ce60d65a 100644 --- a/src/services/api/api.service.js +++ b/src/services/api/api.service.js @@ -50,6 +50,7 @@ const MASTODON_USER_HOME_TIMELINE_URL = '/api/v1/timelines/home' const MASTODON_STATUS_URL = id => `/api/v1/statuses/${id}` const MASTODON_STATUS_CONTEXT_URL = id => `/api/v1/statuses/${id}/context` const MASTODON_USER_URL = '/api/v1/accounts' +const MASTODON_USER_LOOKUP_URL = '/api/v1/accounts/lookup' const MASTODON_USER_RELATIONSHIPS_URL = '/api/v1/accounts/relationships' const MASTODON_USER_TIMELINE_URL = id => `/api/v1/accounts/${id}/statuses` const MASTODON_LIST_URL = id => `/api/v1/lists/${id}` @@ -318,6 +319,25 @@ const fetchUser = ({ id, credentials }) => { .then((data) => parseUser(data)) } +const fetchUserByName = ({ name, credentials }) => { + return promisedRequest({ + url: MASTODON_USER_LOOKUP_URL, + credentials, + params: { acct: name } + }) + .then(data => data.id) + .catch(error => { + if (error && error.statusCode === 404) { + // Either the backend does not support lookup endpoint, + // or there is no user with such name. Fallback and treat name as id. + return name + } else { + throw error + } + }) + .then(id => fetchUser({ id, credentials })) +} + const fetchUserRelationship = ({ id, credentials }) => { const url = `${MASTODON_USER_RELATIONSHIPS_URL}/?id=${id}` return fetch(url, { headers: authHeaders(credentials) }) @@ -1481,6 +1501,7 @@ const apiService = { blockUser, unblockUser, fetchUser, + fetchUserByName, fetchUserRelationship, favorite, unfavorite, -- cgit v1.2.3-70-g09d2 From ab4a75bdd92aba7973b6c32eb8ff11280552d6c6 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Wed, 10 Aug 2022 12:17:18 -0400 Subject: Do not allow to find by name in findUser() --- src/components/user_profile/user_profile.js | 2 +- src/modules/users.js | 20 +++++------ test/unit/specs/components/user_profile.spec.js | 5 ++- test/unit/specs/modules/users.spec.js | 44 ++++++++++++++++++++++--- 4 files changed, 54 insertions(+), 17 deletions(-) (limited to 'src/modules/users.js') diff --git a/src/components/user_profile/user_profile.js b/src/components/user_profile/user_profile.js index 781fd601..08adaeab 100644 --- a/src/components/user_profile/user_profile.js +++ b/src/components/user_profile/user_profile.js @@ -110,7 +110,7 @@ const UserProfile = { const maybeName = userNameOrId.name // Check if user data is already loaded in store - const user = this.$store.getters.findUser(maybeId || maybeName) + const user = maybeId ? this.$store.getters.findUser(maybeId) : this.$store.getters.findUserByName(maybeName) if (user) { loadById(user.id) } else { diff --git a/src/modules/users.js b/src/modules/users.js index 47dc8493..be0bc997 100644 --- a/src/modules/users.js +++ b/src/modules/users.js @@ -16,9 +16,6 @@ export const mergeOrAdd = (arr, obj, item) => { // This is a new item, prepare it arr.push(item) obj[item.id] = item - if (item.screen_name && !item.screen_name.includes('@')) { - obj[item.screen_name.toLowerCase()] = item - } return { item, new: true } } } @@ -162,7 +159,11 @@ export const mutations = { if (user.relationship) { state.relationships[user.relationship.id] = user.relationship } - mergeOrAdd(state.users, state.usersObject, user) + const res = mergeOrAdd(state.users, state.usersObject, user) + const item = res.item + if (res.new && item.screen_name && !item.screen_name.includes('@')) { + state.usersByNameObject[item.screen_name.toLowerCase()] = item + } }) }, updateUserRelationship (state, relationships) { @@ -239,12 +240,10 @@ export const mutations = { export const getters = { findUser: state => query => { - const result = state.usersObject[query] - // In case it's a screen_name, we can try searching case-insensitive - if (!result && typeof query === 'string') { - return state.usersObject[query.toLowerCase()] - } - return result + return state.usersObject[query] + }, + findUserByName: state => query => { + return state.usersByNameObject[query.toLowerCase()] }, findUserByUrl: state => query => { return state.users @@ -263,6 +262,7 @@ export const defaultState = { currentUser: false, users: [], usersObject: {}, + usersByNameObject: {}, signUpPending: false, signUpErrors: [], relationships: {} diff --git a/test/unit/specs/components/user_profile.spec.js b/test/unit/specs/components/user_profile.spec.js index 0fbab722..dc0b938a 100644 --- a/test/unit/specs/components/user_profile.spec.js +++ b/test/unit/specs/components/user_profile.spec.js @@ -15,6 +15,7 @@ const actions = { const testGetters = { findUser: state => getters.findUser(state.users), + findUserByName: state => getters.findUserByName(state.users), relationship: state => getters.relationship(state.users), mergedConfig: state => ({ colors: '', @@ -95,6 +96,7 @@ const externalProfileStore = createStore({ credentials: '' }, usersObject: { 100: extUser }, + usersByNameObject: {}, users: [extUser], relationships: {} } @@ -163,7 +165,8 @@ const localProfileStore = createStore({ currentUser: { credentials: '' }, - usersObject: { 100: localUser, testuser: localUser }, + usersObject: { 100: localUser }, + usersByNameObject: { testuser: localUser }, users: [localUser], relationships: {} } diff --git a/test/unit/specs/modules/users.spec.js b/test/unit/specs/modules/users.spec.js index dfa5684d..3073f507 100644 --- a/test/unit/specs/modules/users.spec.js +++ b/test/unit/specs/modules/users.spec.js @@ -57,24 +57,27 @@ describe('The users module', () => { }) describe('findUser', () => { - it('returns user with matching screen_name', () => { + it('does not return user with matching screen_name', () => { const user = { screen_name: 'Guy', id: '1' } const state = { usersObject: { - 1: user, + 1: user + }, + usersByNameObject: { guy: user } } const name = 'Guy' - const expected = { screen_name: 'Guy', id: '1' } - expect(getters.findUser(state)(name)).to.eql(expected) + expect(getters.findUser(state)(name)).to.eql(undefined) }) it('returns user with matching id', () => { const user = { screen_name: 'Guy', id: '1' } const state = { usersObject: { - 1: user, + 1: user + }, + usersByNameObject: { guy: user } } @@ -83,4 +86,35 @@ describe('The users module', () => { expect(getters.findUser(state)(id)).to.eql(expected) }) }) + + describe('findUserByName', () => { + it('returns user with matching screen_name', () => { + const user = { screen_name: 'Guy', id: '1' } + const state = { + usersObject: { + 1: user + }, + usersByNameObject: { + guy: user + } + } + const name = 'Guy' + const expected = { screen_name: 'Guy', id: '1' } + expect(getters.findUserByName(state)(name)).to.eql(expected) + }) + + it('does not return user with matching id', () => { + const user = { screen_name: 'Guy', id: '1' } + const state = { + usersObject: { + 1: user + }, + usersByNameObject: { + guy: user + } + } + const id = '1' + expect(getters.findUserByName(state)(id)).to.eql(undefined) + }) + }) }) -- cgit v1.2.3-70-g09d2 From 8d3d8fffab0106a8aff5822044a8c3c30bd6e057 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Fri, 12 Aug 2022 01:19:19 +0300 Subject: fixes, clear cache on logout --- src/components/nav_panel/nav_panel.js | 4 ++-- src/components/navigation/navigation_entry.js | 1 + src/components/navigation/navigation_pins.js | 2 +- src/modules/serverSideStorage.js | 17 +++++++++++++---- src/modules/users.js | 1 + .../entity_normalizer/entity_normalizer.service.js | 1 + test/unit/specs/modules/serverSideStorage.spec.js | 2 +- 7 files changed, 20 insertions(+), 8 deletions(-) (limited to 'src/modules/users.js') diff --git a/src/components/nav_panel/nav_panel.js b/src/components/nav_panel/nav_panel.js index 0d71a924..26e8440a 100644 --- a/src/components/nav_panel/nav_panel.js +++ b/src/components/nav_panel/nav_panel.js @@ -95,7 +95,7 @@ const NavPanel = { { hasChats: this.pleromaChatMessagesAvailable, isFederating: this.federating, - isPrivate: this.private, + isPrivate: this.privateMode, currentUser: this.currentUser } ) @@ -108,7 +108,7 @@ const NavPanel = { { hasChats: this.pleromaChatMessagesAvailable, isFederating: this.federating, - isPrivate: this.private, + isPrivate: this.privateMode, currentUser: this.currentUser } ) diff --git a/src/components/navigation/navigation_entry.js b/src/components/navigation/navigation_entry.js index 09c216ed..e17e9436 100644 --- a/src/components/navigation/navigation_entry.js +++ b/src/components/navigation/navigation_entry.js @@ -16,6 +16,7 @@ const NavigationEntry = { } else { this.$store.commit('addCollectionPreference', { path: 'collections.pinnedNavItems', value }) } + this.$store.dispatch('pushServerSideStorage') } }, computed: { diff --git a/src/components/navigation/navigation_pins.js b/src/components/navigation/navigation_pins.js index 8a892466..43be4275 100644 --- a/src/components/navigation/navigation_pins.js +++ b/src/components/navigation/navigation_pins.js @@ -64,7 +64,7 @@ const NavPanel = { { hasChats: this.pleromaChatMessagesAvailable, isFederating: this.federating, - isPrivate: this.private, + isPrivate: this.privateMode, currentUser: this.currentUser } ) diff --git a/src/modules/serverSideStorage.js b/src/modules/serverSideStorage.js index d95fbb8a..5581783f 100644 --- a/src/modules/serverSideStorage.js +++ b/src/modules/serverSideStorage.js @@ -51,8 +51,9 @@ export const _moveItemInArray = (array, value, movement) => { return newArray } -const _wrapData = (data) => ({ +const _wrapData = (data, userName) => ({ ...data, + _user: userName, _timestamp: Date.now(), _version: VERSION }) @@ -254,10 +255,17 @@ export const _doMigrations = (cache) => { } export const mutations = { + clearServerSideStorage (state, userData) { + state = { ...cloneDeep(defaultState) } + }, setServerSideStorage (state, userData) { const live = userData.storage state.raw = live let cache = state.cache + if (cache._user !== userData.fqn) { + console.warn('cache belongs to another user! reinitializing local cache!') + cache = null + } cache = _doMigrations(cache) @@ -371,12 +379,12 @@ export const mutations = { ] state.dirty = true }, - updateCache (state) { + updateCache (state, { username }) { state.prefsStorage._journal = _mergeJournal(state.prefsStorage._journal) state.cache = _wrapData({ flagStorage: toRaw(state.flagStorage), prefsStorage: toRaw(state.prefsStorage) - }) + }, username) } } @@ -388,8 +396,9 @@ const serverSideStorage = { actions: { pushServerSideStorage ({ state, rootState, commit }, { force = false } = {}) { const needPush = state.dirty || force + console.log(needPush) if (!needPush) return - commit('updateCache') + commit('updateCache', { username: rootState.users.currentUser.fqn }) const params = { pleroma_settings_store: { 'pleroma-fe': state.cache } } rootState.api.backendInteractor .updateProfile({ params }) diff --git a/src/modules/users.js b/src/modules/users.js index b6fb9746..fe92d697 100644 --- a/src/modules/users.js +++ b/src/modules/users.js @@ -509,6 +509,7 @@ const users = { store.dispatch('setLastTimeline', 'public-timeline') store.dispatch('setLayoutWidth', windowWidth()) store.dispatch('setLayoutHeight', windowHeight()) + store.commit('clearServerSideStorage') }) }, loginUser (store, accessToken) { diff --git a/src/services/entity_normalizer/entity_normalizer.service.js b/src/services/entity_normalizer/entity_normalizer.service.js index e9cbcfe6..b1ad2691 100644 --- a/src/services/entity_normalizer/entity_normalizer.service.js +++ b/src/services/entity_normalizer/entity_normalizer.service.js @@ -48,6 +48,7 @@ export const parseUser = (data) => { if (masto) { output.screen_name = data.acct + output.fqn = data.fqn output.statusnet_profile_url = data.url // There's nothing else to get diff --git a/test/unit/specs/modules/serverSideStorage.spec.js b/test/unit/specs/modules/serverSideStorage.spec.js index edb23e8a..f10e21e6 100644 --- a/test/unit/specs/modules/serverSideStorage.spec.js +++ b/test/unit/specs/modules/serverSideStorage.spec.js @@ -127,7 +127,7 @@ describe('The serverSideStorage module', () => { const state = cloneDeep(defaultState) setPreference(state, { path: 'simple.testing', value: 1 }) setPreference(state, { path: 'simple.testing', value: 2 }) - updateCache(state) + updateCache(state, { username: 'test' }) expect(state.prefsStorage.simple.testing).to.eql(2) expect(state.prefsStorage._journal.length).to.eql(1) expect(state.prefsStorage._journal[0]).to.eql({ -- cgit v1.2.3-70-g09d2 From ebe095bd769481cc114009e8193494d482f9ff4d Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Mon, 15 Aug 2022 20:43:38 +0300 Subject: fix prod build again + fetch lists (and follow request) on login, stop fetching on logout, don't start fetching in components --- src/components/lists/lists.js | 3 --- src/components/lists_menu/lists_menu_content.js | 11 +---------- src/components/nav_panel/nav_panel.js | 3 --- src/modules/users.js | 7 +++++++ 4 files changed, 8 insertions(+), 16 deletions(-) (limited to 'src/modules/users.js') diff --git a/src/components/lists/lists.js b/src/components/lists/lists.js index 791b99b2..9aed37f7 100644 --- a/src/components/lists/lists.js +++ b/src/components/lists/lists.js @@ -11,9 +11,6 @@ const Lists = { ListsCard, ListsNew }, - created () { - this.$store.dispatch('startFetchingLists') - }, computed: { lists () { return this.$store.state.lists.allLists diff --git a/src/components/lists_menu/lists_menu_content.js b/src/components/lists_menu/lists_menu_content.js index 99fea0f0..97b32210 100644 --- a/src/components/lists_menu/lists_menu_content.js +++ b/src/components/lists_menu/lists_menu_content.js @@ -1,20 +1,11 @@ import { mapState } from 'vuex' import NavigationEntry from 'src/components/navigation/navigation_entry.vue' - -export const getListEntries = state => state.lists.allLists.map(list => ({ - name: 'list-' + list.id, - routeObject: { name: 'lists-timeline', params: { id: list.id } }, - labelRaw: list.title, - iconLetter: list.title[0] -})) +import { getListEntries } from 'src/components/navigation/filter.js' export const ListsMenuContent = { props: [ 'showPin' ], - created () { - this.$store.dispatch('startFetchingLists') - }, components: { NavigationEntry }, diff --git a/src/components/nav_panel/nav_panel.js b/src/components/nav_panel/nav_panel.js index aeccd8a7..b11a258b 100644 --- a/src/components/nav_panel/nav_panel.js +++ b/src/components/nav_panel/nav_panel.js @@ -36,9 +36,6 @@ library.add( const NavPanel = { props: ['forceExpand'], created () { - if (this.currentUser && this.currentUser.locked) { - this.$store.dispatch('startFetchingFollowRequests') - } }, components: { ListsMenuContent, diff --git a/src/modules/users.js b/src/modules/users.js index fe92d697..c13beb29 100644 --- a/src/modules/users.js +++ b/src/modules/users.js @@ -502,6 +502,7 @@ const users = { store.dispatch('stopFetchingTimeline', 'friends') store.commit('setBackendInteractor', backendInteractorService(store.getters.getToken())) store.dispatch('stopFetchingNotifications') + store.dispatch('stopFetchingLists') store.dispatch('stopFetchingFollowRequests') store.commit('clearNotifications') store.commit('resetStatuses') @@ -556,6 +557,12 @@ const users = { store.dispatch('startFetchingChats') } + store.dispatch('startFetchingLists') + + if (user.locked) { + store.dispatch('startFetchingFollowRequests') + } + if (store.getters.mergedConfig.useStreamingApi) { store.dispatch('fetchTimeline', 'friends', { since: null }) store.dispatch('fetchNotifications', { since: null }) -- cgit v1.2.3-70-g09d2 From 50f5afbce1f2bc4dbd0ddf6c951c7e519dfc6ce3 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Mon, 15 Aug 2022 23:19:33 +0300 Subject: add and remove users to/from lists from their profile --- src/components/account_actions/account_actions.js | 4 +- src/components/account_actions/account_actions.vue | 1 + src/components/lists_edit/lists_edit.js | 10 +-- src/components/lists_new/lists_new.js | 4 +- src/components/popover/popover.js | 25 +++++- src/i18n/en.json | 3 +- src/modules/lists.js | 97 +++++++++++++++------- src/modules/users.js | 9 ++ src/services/api/api.service.js | 35 +++++--- .../entity_normalizer/entity_normalizer.service.js | 1 + 10 files changed, 134 insertions(+), 55 deletions(-) (limited to 'src/modules/users.js') diff --git a/src/components/account_actions/account_actions.js b/src/components/account_actions/account_actions.js index 99762562..735dd81c 100644 --- a/src/components/account_actions/account_actions.js +++ b/src/components/account_actions/account_actions.js @@ -1,6 +1,7 @@ import { mapState } from 'vuex' import ProgressButton from '../progress_button/progress_button.vue' import Popover from '../popover/popover.vue' +import UserListMenu from 'src/components/user_list_menu/user_list_menu.vue' import { library } from '@fortawesome/fontawesome-svg-core' import { faEllipsisV @@ -19,7 +20,8 @@ const AccountActions = { }, components: { ProgressButton, - Popover + Popover, + UserListMenu }, methods: { showRepeats () { diff --git a/src/components/account_actions/account_actions.vue b/src/components/account_actions/account_actions.vue index 23547f2c..770740e0 100644 --- a/src/components/account_actions/account_actions.vue +++ b/src/components/account_actions/account_actions.vue @@ -28,6 +28,7 @@ class="dropdown-divider" /> +