From 5251ccd708678ff373e622b2f4604d47dee39cce Mon Sep 17 00:00:00 2001 From: dave Date: Tue, 19 Feb 2019 09:22:42 -0500 Subject: #364: update ap_id error with username --- src/modules/users.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src/modules') diff --git a/src/modules/users.js b/src/modules/users.js index 4d56ec6f..000cfd72 100644 --- a/src/modules/users.js +++ b/src/modules/users.js @@ -231,8 +231,14 @@ const users = { store.commit('setToken', result.access_token) store.dispatch('loginUser', result.access_token) } else { - let data = await response.json() - let errors = humanizeErrors(JSON.parse(data.error)) + const data = await response.json() + let errors = JSON.parse(data.error) + // replace ap_id with username + if (errors.ap_id) { + errors.username = errors.ap_id + delete errors.ap_id + } + errors = humanizeErrors(errors) store.commit('signUpFailure', errors) throw Error(errors) } -- cgit v1.2.3-70-g09d2 From a817cc7cb464d804ccd8af2bbe22e9b738959a3a Mon Sep 17 00:00:00 2001 From: taehoon Date: Wed, 13 Feb 2019 12:05:23 -0500 Subject: Wire up ui to real blocks api data --- src/components/user_settings/user_settings.js | 4 ++-- src/hocs/with_load_more/with_load_more.js | 2 +- src/modules/users.js | 17 +++++++++++++++++ src/services/api/api.service.js | 17 +++++++++++++++++ .../backend_interactor_service.js | 2 ++ .../entity_normalizer/entity_normalizer.service.js | 1 + 6 files changed, 40 insertions(+), 3 deletions(-) (limited to 'src/modules') diff --git a/src/components/user_settings/user_settings.js b/src/components/user_settings/user_settings.js index 34ab99c7..5d8541f0 100644 --- a/src/components/user_settings/user_settings.js +++ b/src/components/user_settings/user_settings.js @@ -10,8 +10,8 @@ import withLoadMore from '../../hocs/with_load_more/with_load_more' const BlockListWithLoadMore = withLoadMore( UserList, - (props, $store) => $store.dispatch('addFriends', $store.state.users.currentUser.id), - (props, $store) => get($store.getters.userById($store.state.users.currentUser.id), 'friends', []) + (props, $store) => $store.dispatch('fetchBlocks'), + (props, $store) => get($store.state.users.currentUser, 'blocks', []) ) const UserSettings = { diff --git a/src/hocs/with_load_more/with_load_more.js b/src/hocs/with_load_more/with_load_more.js index 0f72ffd6..14d4303d 100644 --- a/src/hocs/with_load_more/with_load_more.js +++ b/src/hocs/with_load_more/with_load_more.js @@ -48,7 +48,7 @@ const withLoadMore = (Component, fetchEntries, getEntries) => { fetchEntries(this.$props, this.$store).then((newEntries) => { this.error = false this.loading = false - this.bottomedOut = newEntries.length === 0 + this.bottomedOut = !newEntries || newEntries.length === 0 }).catch(() => { this.error = true this.loading = false diff --git a/src/modules/users.js b/src/modules/users.js index 000cfd72..6ea4e0c9 100644 --- a/src/modules/users.js +++ b/src/modules/users.js @@ -85,6 +85,15 @@ export const mutations = { addNewUsers (state, users) { each(users, (user) => mergeOrAdd(state.users, state.usersObject, user)) }, + addBlocks (state, { blocks, page }) { + const user = state.currentUser + each(blocks, block => { + if (!find(user.blocks, { id: block.id })) { + user.blocks.push(block) + } + }) + user.blocksPage = page + 1 + }, setUserForStatus (state, status) { status.user = state.usersObject[status.user.id] }, @@ -137,6 +146,14 @@ const users = { store.rootState.api.backendInteractor.fetchUser({ id }) .then((user) => store.commit('addNewUsers', [user])) }, + fetchBlocks (store) { + const page = store.state.currentUser.blocksPage || 1 + return store.rootState.api.backendInteractor.fetchBlocks({ page }) + .then((blocks) => { + store.commit('addBlocks', { blocks, page }) + return blocks + }) + }, addFriends ({ rootState, commit }, fetchBy) { return new Promise((resolve, reject) => { const user = rootState.users.usersObject[fetchBy] diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js index 13d31d91..908edf7c 100644 --- a/src/services/api/api.service.js +++ b/src/services/api/api.service.js @@ -18,6 +18,7 @@ const MENTIONS_URL = '/api/statuses/mentions.json' const DM_TIMELINE_URL = '/api/statuses/dm_timeline.json' const FOLLOWERS_URL = '/api/statuses/followers.json' const FRIENDS_URL = '/api/statuses/friends.json' +const BLOCKS_URL = '/api/statuses/blocks.json' const FOLLOWING_URL = '/api/friendships/create.json' const UNFOLLOWING_URL = '/api/friendships/destroy.json' const QVITTER_USER_PREF_URL = '/api/qvitter/set_profile_pref.json' @@ -519,6 +520,21 @@ const fetchMutes = ({credentials}) => { }).then((data) => data.json()) } +const fetchBlocks = ({page, credentials}) => { + let url = BLOCKS_URL + if (page) { + url = url + `?page=${page}` + } + return fetch(url, { + headers: authHeaders(credentials) + }).then((data) => { + if (data.ok) { + return data.json() + } + throw new Error('Error fetching blocks', data) + }) +} + const suggestions = ({credentials}) => { return fetch(SUGGESTIONS_URL, { headers: authHeaders(credentials) @@ -560,6 +576,7 @@ const apiService = { fetchAllFollowing, setUserMute, fetchMutes, + fetchBlocks, register, getCaptcha, updateAvatar, diff --git a/src/services/backend_interactor_service/backend_interactor_service.js b/src/services/backend_interactor_service/backend_interactor_service.js index 80c5cc5e..43c914d9 100644 --- a/src/services/backend_interactor_service/backend_interactor_service.js +++ b/src/services/backend_interactor_service/backend_interactor_service.js @@ -63,6 +63,7 @@ const backendInteractorService = (credentials) => { } const fetchMutes = () => apiService.fetchMutes({credentials}) + const fetchBlocks = (params) => apiService.fetchBlocks({credentials, ...params}) const fetchFollowRequests = () => apiService.fetchFollowRequests({credentials}) const getCaptcha = () => apiService.getCaptcha() @@ -94,6 +95,7 @@ const backendInteractorService = (credentials) => { startFetching, setUserMute, fetchMutes, + fetchBlocks, register, getCaptcha, updateAvatar, diff --git a/src/services/entity_normalizer/entity_normalizer.service.js b/src/services/entity_normalizer/entity_normalizer.service.js index d20ce77f..1192b6cc 100644 --- a/src/services/entity_normalizer/entity_normalizer.service.js +++ b/src/services/entity_normalizer/entity_normalizer.service.js @@ -120,6 +120,7 @@ export const parseUser = (data) => { if (data.pleroma) { output.follow_request_count = data.pleroma.follow_request_count } + output.blocks = [] return output } -- cgit v1.2.3-70-g09d2 From 52913d8f873dd6994988d6a928cca007a0effeaf Mon Sep 17 00:00:00 2001 From: taehoon Date: Wed, 13 Feb 2019 15:31:20 -0500 Subject: Complete functionality of BlockCard --- src/components/block_card/block_card.js | 22 +++++++++++++++++++--- src/components/block_card/block_card.vue | 10 +++++++++- src/components/user_settings/user_settings.js | 2 +- src/i18n/en.json | 3 ++- src/modules/users.js | 8 ++++++++ 5 files changed, 39 insertions(+), 6 deletions(-) (limited to 'src/modules') diff --git a/src/components/block_card/block_card.js b/src/components/block_card/block_card.js index 8788fb62..11fa27b4 100644 --- a/src/components/block_card/block_card.js +++ b/src/components/block_card/block_card.js @@ -1,11 +1,18 @@ import BasicUserCard from '../basic_user_card/basic_user_card.vue' const BlockCard = { - props: ['user'], + props: ['userId'], data () { return { - progress: false, - updated: false + progress: false + } + }, + computed: { + user () { + return this.$store.getters.userById(this.userId) + }, + blocked () { + return this.user.statusnet_blocking } }, components: { @@ -14,6 +21,15 @@ const BlockCard = { methods: { unblockUser () { this.progress = true + this.$store.dispatch('unblockUser', this.user.id).then(() => { + this.progress = false + }) + }, + blockUser () { + this.progress = true + this.$store.dispatch('blockUser', this.user.id).then(() => { + this.progress = false + }) } } } diff --git a/src/components/block_card/block_card.vue b/src/components/block_card/block_card.vue index 06fc67fc..ed7fe30b 100644 --- a/src/components/block_card/block_card.vue +++ b/src/components/block_card/block_card.vue @@ -1,7 +1,7 @@ diff --git a/src/components/user_settings/user_settings.js b/src/components/user_settings/user_settings.js index 3bcecdf4..621dcd4b 100644 --- a/src/components/user_settings/user_settings.js +++ b/src/components/user_settings/user_settings.js @@ -9,7 +9,7 @@ import BlockCard from '../block_card/block_card.vue' import withLoadMore from '../../hocs/with_load_more/with_load_more' import withList from '../../hocs/with_list/with_list' -const BlockList = withList(BlockCard, entry => ({ user: entry })) +const BlockList = withList(BlockCard, entry => ({ userId: entry.id })) const BlockListWithLoadMore = withLoadMore( BlockList, (props, $store) => $store.dispatch('fetchBlocks'), diff --git a/src/i18n/en.json b/src/i18n/en.json index 9027803d..eeb95f9c 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -368,7 +368,8 @@ "remote_follow": "Remote follow", "statuses": "Statuses", "unblock": "Unblock", - "unblock_progress": "Unblocking..." + "unblock_progress": "Unblocking...", + "block_progress": "Blocking..." }, "user_profile": { "timeline_title": "User Timeline" diff --git a/src/modules/users.js b/src/modules/users.js index 6ea4e0c9..ce8af68c 100644 --- a/src/modules/users.js +++ b/src/modules/users.js @@ -154,6 +154,14 @@ const users = { return blocks }) }, + blockUser (store, id) { + return store.rootState.api.backendInteractor.blockUser(id) + .then((user) => store.commit('addNewUsers', [user])) + }, + unblockUser (store, id) { + return store.rootState.api.backendInteractor.unblockUser(id) + .then((user) => store.commit('addNewUsers', [user])) + }, addFriends ({ rootState, commit }, fetchBy) { return new Promise((resolve, reject) => { const user = rootState.users.usersObject[fetchBy] -- cgit v1.2.3-70-g09d2 From 8c8a6edc7800bac854ef23f29aa87f5b932cb415 Mon Sep 17 00:00:00 2001 From: taehoon Date: Wed, 13 Feb 2019 21:08:14 -0500 Subject: Remove pagination support from block-list --- src/components/user_settings/user_settings.js | 10 ++++++---- src/components/user_settings/user_settings.vue | 2 +- src/modules/users.js | 17 ++++++----------- .../entity_normalizer/entity_normalizer.service.js | 2 +- 4 files changed, 14 insertions(+), 17 deletions(-) (limited to 'src/modules') diff --git a/src/components/user_settings/user_settings.js b/src/components/user_settings/user_settings.js index 621dcd4b..8eade382 100644 --- a/src/components/user_settings/user_settings.js +++ b/src/components/user_settings/user_settings.js @@ -7,13 +7,15 @@ import StyleSwitcher from '../style_switcher/style_switcher.vue' import fileSizeFormatService from '../../services/file_size_format/file_size_format.js' import BlockCard from '../block_card/block_card.vue' import withLoadMore from '../../hocs/with_load_more/with_load_more' +import withSubscription from '../../hocs/with_subscription/with_subscription' import withList from '../../hocs/with_list/with_list' -const BlockList = withList(BlockCard, entry => ({ userId: entry.id })) -const BlockListWithLoadMore = withLoadMore( +const BlockList = withList(BlockCard, userId => ({ userId })) +const BlockListWithSubscription = withSubscription( BlockList, (props, $store) => $store.dispatch('fetchBlocks'), - (props, $store) => get($store.state.users.currentUser, 'blocks', []) + (props, $store) => get($store.state.users.currentUser, 'blockIds', []), + 'entries' ) const UserSettings = { @@ -53,7 +55,7 @@ const UserSettings = { StyleSwitcher, TabSwitcher, ImageCropper, - 'block-list': BlockListWithLoadMore + 'block-list': BlockListWithSubscription }, computed: { user () { diff --git a/src/components/user_settings/user_settings.vue b/src/components/user_settings/user_settings.vue index be9f27e7..5cf21815 100644 --- a/src/components/user_settings/user_settings.vue +++ b/src/components/user_settings/user_settings.vue @@ -164,7 +164,7 @@
- +
diff --git a/src/modules/users.js b/src/modules/users.js index ce8af68c..1f03b47e 100644 --- a/src/modules/users.js +++ b/src/modules/users.js @@ -1,5 +1,5 @@ import backendInteractorService from '../services/backend_interactor_service/backend_interactor_service.js' -import { compact, map, each, merge, find } from 'lodash' +import { compact, map, each, merge, find, union } from 'lodash' import { set } from 'vue' import { registerPushNotifications, unregisterPushNotifications } from '../services/push/push.js' import oauthApi from '../services/new_api/oauth' @@ -85,14 +85,9 @@ export const mutations = { addNewUsers (state, users) { each(users, (user) => mergeOrAdd(state.users, state.usersObject, user)) }, - addBlocks (state, { blocks, page }) { + addBlocks (state, blockIds) { const user = state.currentUser - each(blocks, block => { - if (!find(user.blocks, { id: block.id })) { - user.blocks.push(block) - } - }) - user.blocksPage = page + 1 + user.blockIds = union(user.blockIds, blockIds) }, setUserForStatus (state, status) { status.user = state.usersObject[status.user.id] @@ -147,10 +142,10 @@ const users = { .then((user) => store.commit('addNewUsers', [user])) }, fetchBlocks (store) { - const page = store.state.currentUser.blocksPage || 1 - return store.rootState.api.backendInteractor.fetchBlocks({ page }) + return store.rootState.api.backendInteractor.fetchBlocks() .then((blocks) => { - store.commit('addBlocks', { blocks, page }) + store.commit('addBlocks', map(blocks, 'id')) + store.commit('addNewUsers', blocks) return blocks }) }, diff --git a/src/services/entity_normalizer/entity_normalizer.service.js b/src/services/entity_normalizer/entity_normalizer.service.js index 1192b6cc..0e1be61e 100644 --- a/src/services/entity_normalizer/entity_normalizer.service.js +++ b/src/services/entity_normalizer/entity_normalizer.service.js @@ -120,7 +120,7 @@ export const parseUser = (data) => { if (data.pleroma) { output.follow_request_count = data.pleroma.follow_request_count } - output.blocks = [] + output.blockIds = [] return output } -- cgit v1.2.3-70-g09d2 From e91a94ff9c4b9559f53a4b001f8972ceca843771 Mon Sep 17 00:00:00 2001 From: taehoon Date: Wed, 13 Feb 2019 22:04:28 -0500 Subject: Add mutes tab --- src/components/mute_card/mute_card.js | 37 ++++++++++++++++++++++ src/components/mute_card/mute_card.vue | 24 ++++++++++++++ src/components/user_settings/user_settings.js | 13 ++++++-- src/components/user_settings/user_settings.vue | 4 +++ src/i18n/en.json | 1 + src/modules/users.js | 25 ++++++++++++--- .../entity_normalizer/entity_normalizer.service.js | 1 + 7 files changed, 99 insertions(+), 6 deletions(-) create mode 100644 src/components/mute_card/mute_card.js create mode 100644 src/components/mute_card/mute_card.vue (limited to 'src/modules') diff --git a/src/components/mute_card/mute_card.js b/src/components/mute_card/mute_card.js new file mode 100644 index 00000000..5dd0a9e5 --- /dev/null +++ b/src/components/mute_card/mute_card.js @@ -0,0 +1,37 @@ +import BasicUserCard from '../basic_user_card/basic_user_card.vue' + +const MuteCard = { + props: ['userId'], + data () { + return { + progress: false + } + }, + computed: { + user () { + return this.$store.getters.userById(this.userId) + }, + muted () { + return this.user.muted + } + }, + components: { + BasicUserCard + }, + methods: { + unmuteUser () { + this.progress = true + this.$store.dispatch('unmuteUser', this.user.id).then(() => { + this.progress = false + }) + }, + muteUser () { + this.progress = true + this.$store.dispatch('muteUser', this.user.id).then(() => { + this.progress = false + }) + } + } +} + +export default MuteCard diff --git a/src/components/mute_card/mute_card.vue b/src/components/mute_card/mute_card.vue new file mode 100644 index 00000000..e1bfe20b --- /dev/null +++ b/src/components/mute_card/mute_card.vue @@ -0,0 +1,24 @@ + + + \ No newline at end of file diff --git a/src/components/user_settings/user_settings.js b/src/components/user_settings/user_settings.js index 8eade382..8114d5e2 100644 --- a/src/components/user_settings/user_settings.js +++ b/src/components/user_settings/user_settings.js @@ -6,7 +6,7 @@ import ImageCropper from '../image_cropper/image_cropper.vue' import StyleSwitcher from '../style_switcher/style_switcher.vue' import fileSizeFormatService from '../../services/file_size_format/file_size_format.js' import BlockCard from '../block_card/block_card.vue' -import withLoadMore from '../../hocs/with_load_more/with_load_more' +import MuteCard from '../mute_card/mute_card.vue' import withSubscription from '../../hocs/with_subscription/with_subscription' import withList from '../../hocs/with_list/with_list' @@ -18,6 +18,14 @@ const BlockListWithSubscription = withSubscription( 'entries' ) +const MuteList = withList(MuteCard, userId => ({ userId })) +const MuteListWithSubscription = withSubscription( + MuteList, + (props, $store) => $store.dispatch('fetchMutes'), + (props, $store) => get($store.state.users.currentUser, 'muteIds', []), + 'entries' +) + const UserSettings = { data () { return { @@ -55,7 +63,8 @@ const UserSettings = { StyleSwitcher, TabSwitcher, ImageCropper, - 'block-list': BlockListWithSubscription + 'block-list': BlockListWithSubscription, + 'mute-list': MuteListWithSubscription }, computed: { user () { diff --git a/src/components/user_settings/user_settings.vue b/src/components/user_settings/user_settings.vue index 5bae583c..27f3e7cb 100644 --- a/src/components/user_settings/user_settings.vue +++ b/src/components/user_settings/user_settings.vue @@ -166,6 +166,10 @@
+ +
+ +
diff --git a/src/i18n/en.json b/src/i18n/en.json index eeb95f9c..b41b6db9 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -165,6 +165,7 @@ "lock_account_description": "Restrict your account to approved followers only", "loop_video": "Loop videos", "loop_video_silent_only": "Loop only videos without sound (i.e. Mastodon's \"gifs\")", + "mutes_tab": "Mutes", "play_videos_in_modal": "Play videos directly in the media viewer", "use_contain_fit": "Don't crop the attachment in thumbnails", "name": "Name", diff --git a/src/modules/users.js b/src/modules/users.js index 1f03b47e..71201a77 100644 --- a/src/modules/users.js +++ b/src/modules/users.js @@ -89,6 +89,10 @@ export const mutations = { const user = state.currentUser user.blockIds = union(user.blockIds, blockIds) }, + saveMutes (state, ids) { + const user = state.currentUser + user.muteIds = union(user.muteIds, ids) + }, setUserForStatus (state, status) { status.user = state.usersObject[status.user.id] }, @@ -157,6 +161,22 @@ const users = { return store.rootState.api.backendInteractor.unblockUser(id) .then((user) => store.commit('addNewUsers', [user])) }, + fetchMutes (store) { + return store.rootState.api.backendInteractor.fetchMutes() + .then((mutedUsers) => { + each(mutedUsers, (user) => { user.muted = true }) + store.commit('addNewUsers', mutedUsers) + store.commit('saveMutes', map(mutedUsers, 'id')) + }) + }, + muteUser (store, id) { + return store.state.api.backendInteractor.setUserMute({ id, muted: true }) + .then((user) => store.commit('addNewUsers', [user])) + }, + unmuteUser (store, id) { + return store.state.api.backendInteractor.setUserMute({ id, muted: false }) + .then((user) => store.commit('addNewUsers', [user])) + }, addFriends ({ rootState, commit }, fetchBy) { return new Promise((resolve, reject) => { const user = rootState.users.usersObject[fetchBy] @@ -300,10 +320,7 @@ const users = { store.dispatch('startFetching', { timeline: 'friends' }) // Get user mutes and follower info - store.rootState.api.backendInteractor.fetchMutes().then((mutedUsers) => { - each(mutedUsers, (user) => { user.muted = true }) - store.commit('addNewUsers', mutedUsers) - }) + store.dispatch('fetchMutes') // Fetch our friends store.rootState.api.backendInteractor.fetchFriends({ id: user.id }) diff --git a/src/services/entity_normalizer/entity_normalizer.service.js b/src/services/entity_normalizer/entity_normalizer.service.js index 0e1be61e..49c83811 100644 --- a/src/services/entity_normalizer/entity_normalizer.service.js +++ b/src/services/entity_normalizer/entity_normalizer.service.js @@ -121,6 +121,7 @@ export const parseUser = (data) => { output.follow_request_count = data.pleroma.follow_request_count } output.blockIds = [] + output.muteIds = [] return output } -- cgit v1.2.3-70-g09d2 From 1fd9a1c7c0f9efb3660af44f9a8fa8722e6819cc Mon Sep 17 00:00:00 2001 From: taehoon Date: Wed, 13 Feb 2019 22:14:46 -0500 Subject: Set blockIds and muteIds to the currentUser state only --- src/modules/users.js | 4 +++- src/services/entity_normalizer/entity_normalizer.service.js | 2 -- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/modules') diff --git a/src/modules/users.js b/src/modules/users.js index 71201a77..5921370d 100644 --- a/src/modules/users.js +++ b/src/modules/users.js @@ -303,6 +303,8 @@ const users = { const user = data // user.credentials = userCredentials user.credentials = accessToken + user.blockIds = [] + user.muteIds = [] commit('setCurrentUser', user) commit('addNewUsers', [user]) @@ -319,7 +321,7 @@ const users = { // Start getting fresh posts. store.dispatch('startFetching', { timeline: 'friends' }) - // Get user mutes and follower info + // Get user mutes store.dispatch('fetchMutes') // Fetch our friends diff --git a/src/services/entity_normalizer/entity_normalizer.service.js b/src/services/entity_normalizer/entity_normalizer.service.js index 49c83811..d20ce77f 100644 --- a/src/services/entity_normalizer/entity_normalizer.service.js +++ b/src/services/entity_normalizer/entity_normalizer.service.js @@ -120,8 +120,6 @@ export const parseUser = (data) => { if (data.pleroma) { output.follow_request_count = data.pleroma.follow_request_count } - output.blockIds = [] - output.muteIds = [] return output } -- cgit v1.2.3-70-g09d2 From 8f608e060c813dc6d9aeeb548beca971ce9b74bd Mon Sep 17 00:00:00 2001 From: taehoon Date: Wed, 13 Feb 2019 22:24:09 -0500 Subject: Just save blocks/mutes instead of adding --- src/modules/users.js | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'src/modules') diff --git a/src/modules/users.js b/src/modules/users.js index 5921370d..77df7168 100644 --- a/src/modules/users.js +++ b/src/modules/users.js @@ -1,5 +1,5 @@ import backendInteractorService from '../services/backend_interactor_service/backend_interactor_service.js' -import { compact, map, each, merge, find, union } from 'lodash' +import { compact, map, each, merge, find } from 'lodash' import { set } from 'vue' import { registerPushNotifications, unregisterPushNotifications } from '../services/push/push.js' import oauthApi from '../services/new_api/oauth' @@ -85,13 +85,11 @@ export const mutations = { addNewUsers (state, users) { each(users, (user) => mergeOrAdd(state.users, state.usersObject, user)) }, - addBlocks (state, blockIds) { - const user = state.currentUser - user.blockIds = union(user.blockIds, blockIds) + saveBlocks (state, blockIds) { + state.currentUser.blockIds = blockIds }, - saveMutes (state, ids) { - const user = state.currentUser - user.muteIds = union(user.muteIds, ids) + saveMutes (state, muteIds) { + state.currentUser.muteIds = muteIds }, setUserForStatus (state, status) { status.user = state.usersObject[status.user.id] @@ -148,7 +146,7 @@ const users = { fetchBlocks (store) { return store.rootState.api.backendInteractor.fetchBlocks() .then((blocks) => { - store.commit('addBlocks', map(blocks, 'id')) + store.commit('saveBlocks', map(blocks, 'id')) store.commit('addNewUsers', blocks) return blocks }) -- cgit v1.2.3-70-g09d2 From 4136d9cdd16feb27093971371cd81e357d330bf4 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Thu, 21 Feb 2019 19:52:58 +0200 Subject: bad defaults --- src/modules/instance.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/modules') diff --git a/src/modules/instance.js b/src/modules/instance.js index 59c6b91c..c31d02b9 100644 --- a/src/modules/instance.js +++ b/src/modules/instance.js @@ -21,7 +21,7 @@ const defaultState = { collapseMessageWithSubject: false, hidePostStats: false, hideUserStats: false, - hideFilteredStatuses: true, + hideFilteredStatuses: false, disableChat: false, scopeCopy: true, subjectLineBehavior: 'email', -- cgit v1.2.3-70-g09d2 From 662e6bda147f482d8bf6d119ffb792eb37008209 Mon Sep 17 00:00:00 2001 From: dave Date: Mon, 25 Feb 2019 10:21:17 -0500 Subject: #390: fixed the problem loading other user's media data --- src/modules/statuses.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/modules') diff --git a/src/modules/statuses.js b/src/modules/statuses.js index 46117fd7..fd850d1a 100644 --- a/src/modules/statuses.js +++ b/src/modules/statuses.js @@ -126,7 +126,7 @@ const addNewStatuses = (state, { statuses, showImmediately = false, timeline, us // This makes sure that user timeline won't get data meant for other // user. I.e. opening different user profiles makes request which could // return data late after user already viewing different user profile - if (timeline === 'user' && timelineObject.userId !== userId) { + if ((timeline === 'user' || timeline === 'media') && timelineObject.userId !== userId) { return } -- cgit v1.2.3-70-g09d2 From 4e8b696797d5c4010abbe12584b8d70badb76a4c Mon Sep 17 00:00:00 2001 From: dave Date: Mon, 25 Feb 2019 12:12:49 -0500 Subject: #380: fix false alarm for unread notifications --- src/modules/statuses.js | 3 +++ .../notifications_fetcher/notifications_fetcher.service.js | 12 +++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) (limited to 'src/modules') diff --git a/src/modules/statuses.js b/src/modules/statuses.js index 46117fd7..c6fcfe2e 100644 --- a/src/modules/statuses.js +++ b/src/modules/statuses.js @@ -303,6 +303,9 @@ const addNewNotifications = (state, { dispatch, notifications, older, visibleNot setTimeout(notification.close.bind(notification), 5000) } } + } else if (notification.seen) { + state.notifications.data.find(n => n.id === notification.id).seen = true + state.notifications.idStore[notification.id].seen = true } }) } diff --git a/src/services/notifications_fetcher/notifications_fetcher.service.js b/src/services/notifications_fetcher/notifications_fetcher.service.js index b69ec643..3ecdae6a 100644 --- a/src/services/notifications_fetcher/notifications_fetcher.service.js +++ b/src/services/notifications_fetcher/notifications_fetcher.service.js @@ -16,7 +16,17 @@ const fetchAndUpdate = ({store, credentials, older = false}) => { args['until'] = timelineData.minId } } else { - args['since'] = timelineData.maxId + // load unread notifications repeadedly to provide consistency between browser tabs + const notifications = timelineData.data + const unread = notifications.filter(n => !n.seen).map(n => n.id) + if (!unread.length) { + args['since'] = timelineData.maxId + } else { + args['since'] = Math.min(...unread) - 1 + if (timelineData.maxId !== Math.max(...unread)) { + args['until'] = Math.max(...unread, args['since'] + 20) + } + } } args['timeline'] = 'notifications' -- cgit v1.2.3-70-g09d2 From 7dbbd8e27028e7526154542d210c4f6452d5e433 Mon Sep 17 00:00:00 2001 From: dave Date: Mon, 25 Feb 2019 14:57:56 -0500 Subject: #380: simply and remove redundancy --- src/modules/statuses.js | 1 - 1 file changed, 1 deletion(-) (limited to 'src/modules') diff --git a/src/modules/statuses.js b/src/modules/statuses.js index c6fcfe2e..694067ff 100644 --- a/src/modules/statuses.js +++ b/src/modules/statuses.js @@ -304,7 +304,6 @@ const addNewNotifications = (state, { dispatch, notifications, older, visibleNot } } } else if (notification.seen) { - state.notifications.data.find(n => n.id === notification.id).seen = true state.notifications.idStore[notification.id].seen = true } }) -- cgit v1.2.3-70-g09d2 From e687b58091bcedb6f3a56d94030fa312e51830d5 Mon Sep 17 00:00:00 2001 From: taehoon Date: Thu, 21 Feb 2019 13:32:47 -0500 Subject: Show error message when visit profile page of invalid user --- src/components/user_profile/user_profile.js | 8 ++++++++ src/components/user_profile/user_profile.vue | 3 ++- src/i18n/en.json | 3 ++- src/modules/users.js | 2 +- src/services/api/api.service.js | 6 ++++++ 5 files changed, 19 insertions(+), 3 deletions(-) (limited to 'src/modules') diff --git a/src/components/user_profile/user_profile.js b/src/components/user_profile/user_profile.js index 37179ce1..44192e9a 100644 --- a/src/components/user_profile/user_profile.js +++ b/src/components/user_profile/user_profile.js @@ -4,6 +4,11 @@ import Timeline from '../timeline/timeline.vue' import FollowList from '../follow_list/follow_list.vue' const UserProfile = { + data () { + return { + error: false + } + }, created () { this.$store.commit('clearTimeline', { timeline: 'user' }) this.$store.commit('clearTimeline', { timeline: 'favorites' }) @@ -13,6 +18,9 @@ const UserProfile = { this.startFetchFavorites() if (!this.user.id) { this.$store.dispatch('fetchUser', this.fetchBy) + .catch(() => { + this.error = true + }) } }, destroyed () { diff --git a/src/components/user_profile/user_profile.vue b/src/components/user_profile/user_profile.vue index 09fb93de..ccebe20b 100644 --- a/src/components/user_profile/user_profile.vue +++ b/src/components/user_profile/user_profile.vue @@ -55,7 +55,8 @@
- + {{ $t('user_profile.profile_does_not_exist') }} +
diff --git a/src/i18n/en.json b/src/i18n/en.json index 64753f1d..c482ecb6 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -383,7 +383,8 @@ "mute_progress": "Muting..." }, "user_profile": { - "timeline_title": "User Timeline" + "timeline_title": "User Timeline", + "profile_does_not_exist": "Sorry, this profile does not exist." }, "who_to_follow": { "more": "More", diff --git a/src/modules/users.js b/src/modules/users.js index 77df7168..eabfe5ae 100644 --- a/src/modules/users.js +++ b/src/modules/users.js @@ -140,7 +140,7 @@ const users = { getters, actions: { fetchUser (store, id) { - store.rootState.api.backendInteractor.fetchUser({ id }) + return store.rootState.api.backendInteractor.fetchUser({ id }) .then((user) => store.commit('addNewUsers', [user])) }, fetchBlocks (store) { diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js index 3d2e8823..d8716596 100644 --- a/src/services/api/api.service.js +++ b/src/services/api/api.service.js @@ -244,6 +244,12 @@ const denyUser = ({id, credentials}) => { const fetchUser = ({id, credentials}) => { let url = `${USER_URL}?user_id=${id}` return fetch(url, { headers: authHeaders(credentials) }) + .then((data) => { + if (!data.ok) { + throw Error(data.statusText) + } + return data + }) .then((data) => data.json()) .then((data) => parseUser(data)) } -- cgit v1.2.3-70-g09d2 From 95fb768b5a1200cd3e4317c54293b46aea9c8655 Mon Sep 17 00:00:00 2001 From: Shpuld Shpludson Date: Wed, 27 Feb 2019 14:38:58 +0000 Subject: Fix #399 Make max attachments configurable --- src/components/settings/settings.js | 5 +++++ src/components/settings/settings.vue | 8 ++++++++ src/components/status/status.js | 8 +++++--- src/i18n/en.json | 1 + src/i18n/fi.json | 1 + src/modules/config.js | 1 + 6 files changed, 21 insertions(+), 3 deletions(-) (limited to 'src/modules') diff --git a/src/components/settings/settings.js b/src/components/settings/settings.js index 23c1acdb..6e2dff7b 100644 --- a/src/components/settings/settings.js +++ b/src/components/settings/settings.js @@ -12,6 +12,7 @@ const settings = { return { hideAttachmentsLocal: user.hideAttachments, hideAttachmentsInConvLocal: user.hideAttachmentsInConv, + maxThumbnails: user.maxThumbnails, hideNsfwLocal: user.hideNsfw, useOneClickNsfw: user.useOneClickNsfw, hideISPLocal: user.hideISP, @@ -186,6 +187,10 @@ const settings = { }, useContainFit (value) { this.$store.dispatch('setOption', { name: 'useContainFit', value }) + }, + maxThumbnails (value) { + value = this.maxThumbnails = Math.floor(Math.max(value, 0)) + this.$store.dispatch('setOption', { name: 'maxThumbnails', value }) } } } diff --git a/src/components/settings/settings.vue b/src/components/settings/settings.vue index f5e00995..16814f65 100644 --- a/src/components/settings/settings.vue +++ b/src/components/settings/settings.vue @@ -136,6 +136,10 @@ +
  • + + +
  • @@ -316,6 +320,10 @@ min-width: 10em; padding: 0 2em; } + + .number-input { + max-width: 6em; + } } .select-multiple { display: flex; diff --git a/src/components/status/status.js b/src/components/status/status.js index 0273a5be..fab2fe62 100644 --- a/src/components/status/status.js +++ b/src/components/status/status.js @@ -40,8 +40,7 @@ const Status = { expandingSubject: typeof this.$store.state.config.collapseMessageWithSubject === 'undefined' ? !this.$store.state.instance.collapseMessageWithSubject : !this.$store.state.config.collapseMessageWithSubject, - betterShadow: this.$store.state.interface.browserSupport.cssFilter, - maxAttachments: 9 + betterShadow: this.$store.state.interface.browserSupport.cssFilter } }, computed: { @@ -225,7 +224,7 @@ const Status = { attachmentSize () { if ((this.$store.state.config.hideAttachments && !this.inConversation) || (this.$store.state.config.hideAttachmentsInConv && this.inConversation) || - (this.status.attachments.length > this.maxAttachments)) { + (this.status.attachments.length > this.maxThumbnails)) { return 'hide' } else if (this.compact) { return 'small' @@ -249,6 +248,9 @@ const Status = { return this.status.attachments.filter( file => !fileType.fileMatchesSomeType(this.galleryTypes, file) ) + }, + maxThumbnails () { + return this.$store.state.config.maxThumbnails } }, components: { diff --git a/src/i18n/en.json b/src/i18n/en.json index 64753f1d..8e837d2f 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -149,6 +149,7 @@ "general": "General", "hide_attachments_in_convo": "Hide attachments in conversations", "hide_attachments_in_tl": "Hide attachments in timeline", + "max_thumbnails": "Maximum amount of thumbnails per post", "hide_isp": "Hide instance-specific panel", "preload_images": "Preload images", "use_one_click_nsfw": "Open NSFW attachments with just one click", diff --git a/src/i18n/fi.json b/src/i18n/fi.json index 5a0c1ea8..a8259ca8 100644 --- a/src/i18n/fi.json +++ b/src/i18n/fi.json @@ -133,6 +133,7 @@ "general": "Yleinen", "hide_attachments_in_convo": "Piilota liitteet keskusteluissa", "hide_attachments_in_tl": "Piilota liitteet aikajanalla", + "max_thumbnails": "Suurin sallittu määrä liitteitä esikatselussa", "hide_isp": "Piilota palvelimenkohtainen ruutu", "preload_images": "Esilataa kuvat", "use_one_click_nsfw": "Avaa NSFW-liitteet yhdellä painalluksella", diff --git a/src/modules/config.js b/src/modules/config.js index 71f71376..1c30c203 100644 --- a/src/modules/config.js +++ b/src/modules/config.js @@ -8,6 +8,7 @@ const defaultState = { collapseMessageWithSubject: undefined, // instance default hideAttachments: false, hideAttachmentsInConv: false, + maxThumbnails: 16, hideNsfw: true, preloadImage: true, loopVideo: true, -- cgit v1.2.3-70-g09d2 From 2c7406d9a8d8e961b99286f317c6ed0a48427853 Mon Sep 17 00:00:00 2001 From: Maxim Filippov Date: Tue, 12 Feb 2019 21:53:59 +0300 Subject: Add OAuth Tokens management to settings --- src/components/user_settings/user_settings.js | 24 +++++++++++++++ src/components/user_settings/user_settings.vue | 36 ++++++++++++++++++++++ src/i18n/ar.json | 5 +++ src/i18n/ca.json | 5 +++ src/i18n/de.json | 5 +++ src/i18n/en.json | 5 +++ src/i18n/es.json | 5 +++ src/i18n/fi.json | 5 +++ src/i18n/fr.json | 5 +++ src/i18n/ga.json | 5 +++ src/i18n/he.json | 5 +++ src/i18n/it.json | 5 +++ src/i18n/ja.json | 5 +++ src/i18n/ko.json | 5 +++ src/i18n/nb.json | 5 +++ src/i18n/nl.json | 5 +++ src/i18n/oc.json | 1 + src/i18n/pl.json | 5 +++ src/i18n/ru.json | 5 +++ src/i18n/zh.json | 5 +++ src/main.js | 4 ++- src/modules/oauth_tokens.js | 26 ++++++++++++++++ src/services/api/api.service.js | 19 ++++++++++++ .../backend_interactor_service.js | 4 +++ test/unit/specs/modules/users.spec.js | 10 ++++++ 25 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 src/modules/oauth_tokens.js (limited to 'src/modules') diff --git a/src/components/user_settings/user_settings.js b/src/components/user_settings/user_settings.js index 06e72112..c7dab754 100644 --- a/src/components/user_settings/user_settings.js +++ b/src/components/user_settings/user_settings.js @@ -1,6 +1,10 @@ +<<<<<<< HEAD import { compose } from 'vue-compose' import unescape from 'lodash/unescape' import get from 'lodash/get' +======= +import { unescape, truncate } from 'lodash' +>>>>>>> Add OAuth Tokens management to settings import TabSwitcher from '../tab_switcher/tab_switcher.js' import ImageCropper from '../image_cropper/image_cropper.vue' @@ -62,6 +66,9 @@ const UserSettings = { activeTab: 'profile' } }, + created () { + this.$store.dispatch('fetchTokens') + }, components: { StyleSwitcher, TabSwitcher, @@ -87,8 +94,20 @@ const UserSettings = { direct: { selected: this.newDefaultScope === 'direct' } } }, +<<<<<<< HEAD currentSaveStateNotice () { return this.$store.state.interface.settings.currentSaveStateNotice +======= + oauthTokens () { + return this.$store.state.oauthTokens.tokens.map(oauthToken => { + return { + id: oauthToken.id, + token: truncate(oauthToken.token, { length: 15 }), + refreshToken: truncate(oauthToken.refresh_token, { length: 15 }), + validUntil: new Date(oauthToken.valid_until).toLocaleDateString() + } + }) +>>>>>>> Add OAuth Tokens management to settings } }, methods: { @@ -308,6 +327,11 @@ const UserSettings = { logout () { this.$store.dispatch('logout') this.$router.replace('/') + }, + revokeToken (id) { + if(confirm('Are you sure?')) { + this.$store.dispatch('revokeToken', id) + } } } } diff --git a/src/components/user_settings/user_settings.vue b/src/components/user_settings/user_settings.vue index 983cbda0..ac75ad86 100644 --- a/src/components/user_settings/user_settings.vue +++ b/src/components/user_settings/user_settings.vue @@ -121,6 +121,30 @@

    {{changePasswordError}}

    +
    +

    {{$t('settings.oauth_tokens')}}

    + + + + + + + + + + + + + + + + + +
    TokenRefresh TokenValid Until
    {{oauthToken.token}}{{oauthToken.refreshToken}}{{oauthToken.validUntil}} + +
    +
    +

    {{$t('settings.delete_account')}}

    {{$t('settings.delete_account_description')}}

    @@ -213,5 +237,17 @@ border-radius: $fallback--avatarRadius; border-radius: var(--avatarRadius, $fallback--avatarRadius); } + + .oauth-tokens { + width: 100%; + + th { + text-align: left; + } + + .actions { + text-align: right; + } + } } diff --git a/src/i18n/ar.json b/src/i18n/ar.json index ac7d0f1a..242dab78 100644 --- a/src/i18n/ar.json +++ b/src/i18n/ar.json @@ -134,6 +134,11 @@ "notification_visibility_mentions": "الإشارات", "notification_visibility_repeats": "", "nsfw_clickthrough": "", + "oauth_tokens": "رموز OAuth", + "token": "رمز", + "refresh_token": "رمز التحديث", + "valid_until": "صالح حتى", + "revoke_token": "سحب", "panelRadius": "", "pause_on_unfocused": "", "presets": "النماذج", diff --git a/src/i18n/ca.json b/src/i18n/ca.json index fa517e22..d2f285df 100644 --- a/src/i18n/ca.json +++ b/src/i18n/ca.json @@ -132,6 +132,11 @@ "notification_visibility_repeats": "Republica una entrada meva", "no_rich_text_description": "Neteja el formatat de text de totes les entrades", "nsfw_clickthrough": "Amaga el contingut NSFW darrer d'una imatge clicable", + "oauth_tokens": "Llistats OAuth", + "token": "Token", + "refresh_token": "Actualitza el token", + "valid_until": "Vàlid fins", + "revoke_token": "Revocar", "panelRadius": "Panells", "pause_on_unfocused": "Pausa la reproducció en continu quan la pestanya perdi el focus", "presets": "Temes", diff --git a/src/i18n/de.json b/src/i18n/de.json index d0bfba38..07d44348 100644 --- a/src/i18n/de.json +++ b/src/i18n/de.json @@ -159,6 +159,11 @@ "hide_follows_description": "Zeige nicht, wem ich folge", "hide_followers_description": "Zeige nicht, wer mir folgt", "nsfw_clickthrough": "Aktiviere ausblendbares Overlay für Anhänge, die als NSFW markiert sind", + "oauth_tokens": "OAuth-Token", + "token": "Zeichen", + "refresh_token": "Token aktualisieren", + "valid_until": "Gültig bis", + "revoke_token": "Widerrufen", "panelRadius": "Panel", "pause_on_unfocused": "Streaming pausieren, wenn das Tab nicht fokussiert ist", "presets": "Voreinstellungen", diff --git a/src/i18n/en.json b/src/i18n/en.json index 8e837d2f..0aeb70ab 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -189,6 +189,11 @@ "show_admin_badge": "Show Admin badge in my profile", "show_moderator_badge": "Show Moderator badge in my profile", "nsfw_clickthrough": "Enable clickthrough NSFW attachment hiding", + "oauth_tokens": "OAuth tokens", + "token": "Token", + "refresh_token": "Refresh Token", + "valid_until": "Valid Until", + "revoke_token": "Revoke", "panelRadius": "Panels", "pause_on_unfocused": "Pause streaming when tab is not focused", "presets": "Presets", diff --git a/src/i18n/es.json b/src/i18n/es.json index d14e7a31..167e8c42 100644 --- a/src/i18n/es.json +++ b/src/i18n/es.json @@ -171,6 +171,11 @@ "show_admin_badge": "Mostrar la placa de administrador en mi perfil", "show_moderator_badge": "Mostrar la placa de moderador en mi perfil", "nsfw_clickthrough": "Activar el clic para ocultar los adjuntos NSFW", + "oauth_tokens": "Tokens de OAuth", + "token": "Token", + "refresh_token": "Actualizar el token", + "valid_until": "Válido hasta", + "revoke_token": "Revocar", "panelRadius": "Paneles", "pause_on_unfocused": "Parar la transmisión cuando no estés en foco.", "presets": "Por defecto", diff --git a/src/i18n/fi.json b/src/i18n/fi.json index a8259ca8..c7a25fe1 100644 --- a/src/i18n/fi.json +++ b/src/i18n/fi.json @@ -166,6 +166,11 @@ "no_rich_text_description": "Älä näytä tekstin muotoilua.", "hide_network_description": "Älä näytä seurauksiani tai seuraajiani", "nsfw_clickthrough": "Piilota NSFW liitteet klikkauksen taakse", + "oauth_tokens": "OAuth-merkit", + "token": "Token", + "refresh_token": "Päivitä token", + "valid_until": "Voimassa asti", + "revoke_token": "Peruuttaa", "panelRadius": "Ruudut", "pause_on_unfocused": "Pysäytä automaattinen viestien näyttö välilehden ollessa pois fokuksesta", "presets": "Valmiit teemat", diff --git a/src/i18n/fr.json b/src/i18n/fr.json index 129b7d7c..1209556a 100644 --- a/src/i18n/fr.json +++ b/src/i18n/fr.json @@ -137,6 +137,11 @@ "notification_visibility_mentions": "Mentionnés", "notification_visibility_repeats": "Partages", "nsfw_clickthrough": "Masquer les images marquées comme contenu adulte ou sensible", + "oauth_tokens": "Jetons OAuth", + "token": "Jeton", + "refresh_token": "Refresh Token", + "valid_until": "Valable jusque", + "revoke_token": "Révoquer", "panelRadius": "Fenêtres", "pause_on_unfocused": "Suspendre le streaming lorsque l'onglet n'est pas centré", "presets": "Thèmes prédéfinis", diff --git a/src/i18n/ga.json b/src/i18n/ga.json index 64461202..5be9297a 100644 --- a/src/i18n/ga.json +++ b/src/i18n/ga.json @@ -134,6 +134,11 @@ "notification_visibility_repeats": "Atphostáil", "no_rich_text_description": "Bain formáidiú téacs saibhir ó gach post", "nsfw_clickthrough": "Cumasaigh an ceangaltán NSFW cliceáil ar an gcnaipe", + "oauth_tokens": "Tocanna OAuth", + "token": "Token", + "refresh_token": "Athnuachan Comórtas", + "valid_until": "Bailí Go dtí", + "revoke_token": "Athghairm", "panelRadius": "Painéil", "pause_on_unfocused": "Sruthú ar sos nuair a bhíonn an fócas caillte", "presets": "Réamhshocruithe", diff --git a/src/i18n/he.json b/src/i18n/he.json index 99ae9551..213e6170 100644 --- a/src/i18n/he.json +++ b/src/i18n/he.json @@ -129,6 +129,11 @@ "notification_visibility_mentions": "אזכורים", "notification_visibility_repeats": "חזרות", "nsfw_clickthrough": "החל החבאת צירופים לא בטוחים לצפיה בעת עבודה בעזרת לחיצת עכבר", + "oauth_tokens": "אסימוני OAuth", + "token": "אסימון", + "refresh_token": "רענון האסימון", + "valid_until": "בתוקף עד", + "revoke_token": "בטל", "panelRadius": "פאנלים", "pause_on_unfocused": "השהה זרימת הודעות כשהחלון לא בפוקוס", "presets": "ערכים קבועים מראש", diff --git a/src/i18n/it.json b/src/i18n/it.json index 8f69e7c1..385d21aa 100644 --- a/src/i18n/it.json +++ b/src/i18n/it.json @@ -93,6 +93,11 @@ "notification_visibility_mentions": "Menzioni", "notification_visibility_repeats": "Condivisioni", "no_rich_text_description": "Togli la formattazione del testo da tutti i post", + "oauth_tokens": "Token OAuth", + "token": "Token", + "refresh_token": "Aggiorna token", + "valid_until": "Valido fino a", + "revoke_token": "Revocare", "panelRadius": "Pannelli", "pause_on_unfocused": "Metti in pausa l'aggiornamento continuo quando la scheda non è in primo piano", "presets": "Valori predefiniti", diff --git a/src/i18n/ja.json b/src/i18n/ja.json index 7849aa20..b51fa7fd 100644 --- a/src/i18n/ja.json +++ b/src/i18n/ja.json @@ -171,6 +171,11 @@ "show_admin_badge": "アドミンのしるしをみる", "show_moderator_badge": "モデレーターのしるしをみる", "nsfw_clickthrough": "NSFWなファイルをかくす", + "oauth_tokens": "OAuthトークン", + "token": "トークン", + "refresh_token": "トークンを更新", + "valid_until": "まで有効", + "revoke_token": "取り消す", "panelRadius": "パネル", "pause_on_unfocused": "タブにフォーカスがないときストリーミングをとめる", "presets": "プリセット", diff --git a/src/i18n/ko.json b/src/i18n/ko.json index f9e4dfa3..336e464f 100644 --- a/src/i18n/ko.json +++ b/src/i18n/ko.json @@ -159,6 +159,11 @@ "hide_follows_description": "내가 팔로우하는 사람을 표시하지 않음", "hide_followers_description": "나를 따르는 사람을 보여주지 마라.", "nsfw_clickthrough": "NSFW 이미지 \"클릭해서 보이기\"를 활성화", + "oauth_tokens": "OAuth 토큰", + "token": "토큰", + "refresh_token": "토큰 새로 고침", + "valid_until": "까지 유효하다", + "revoke_token": "취소", "panelRadius": "패널", "pause_on_unfocused": "탭이 활성 상태가 아닐 때 스트리밍 멈추기", "presets": "프리셋", diff --git a/src/i18n/nb.json b/src/i18n/nb.json index 0f4dca58..39e054f7 100644 --- a/src/i18n/nb.json +++ b/src/i18n/nb.json @@ -132,6 +132,11 @@ "notification_visibility_repeats": "Gjentakelser", "no_rich_text_description": "Fjern all formatering fra statuser", "nsfw_clickthrough": "Krev trykk for å vise statuser som kan være upassende", + "oauth_tokens": "OAuth Tokens", + "token": "Pollett", + "refresh_token": "Refresh Token", + "valid_until": "Gyldig til", + "revoke_token": "Tilbakekall", "panelRadius": "Panel", "pause_on_unfocused": "Stopp henting av poster når vinduet ikke er i fokus", "presets": "Forhåndsdefinerte tema", diff --git a/src/i18n/nl.json b/src/i18n/nl.json index bb388a90..799e22b9 100644 --- a/src/i18n/nl.json +++ b/src/i18n/nl.json @@ -159,6 +159,11 @@ "no_rich_text_description": "Strip rich text formattering van alle posts", "hide_network_description": "Toon niet wie mij volgt en wie ik volg.", "nsfw_clickthrough": "Schakel doorklikbaar verbergen van NSFW bijlages in", + "oauth_tokens": "OAuth-tokens", + "token": "Token", + "refresh_token": "Token vernieuwen", + "valid_until": "Geldig tot", + "revoke_token": "Intrekken", "panelRadius": "Panelen", "pause_on_unfocused": "Pauzeer streamen wanneer de tab niet gefocused is", "presets": "Presets", diff --git a/src/i18n/oc.json b/src/i18n/oc.json index 2ce666c6..db66bb98 100644 --- a/src/i18n/oc.json +++ b/src/i18n/oc.json @@ -142,6 +142,7 @@ "notification_visibility_mentions": "Mencions", "notification_visibility_repeats": "Repeticions", "no_rich_text_description": "Netejar lo format tèxte de totas las publicacions", + "oauth_tokens": "Llistats OAuth", "pause_on_unfocused": "Pausar la difusion quand l’onglet es pas seleccionat", "profile_tab": "Perfil", "replies_in_timeline": "Responsas del flux", diff --git a/src/i18n/pl.json b/src/i18n/pl.json index a3952d4f..2e1d7488 100644 --- a/src/i18n/pl.json +++ b/src/i18n/pl.json @@ -86,6 +86,11 @@ "name_bio": "Imię i bio", "new_password": "Nowe hasło", "nsfw_clickthrough": "Włącz domyślne ukrywanie załączników o treści nieprzyzwoitej (NSFW)", + "oauth_tokens": "Tokeny OAuth", + "token": "Token", + "refresh_token": "Odśwież token", + "valid_until": "Ważne do", + "revoke_token": "Odwołać", "panelRadius": "Panele", "presets": "Gotowe motywy", "profile_background": "Tło profilu", diff --git a/src/i18n/ru.json b/src/i18n/ru.json index 4b0bd4b4..6799cc96 100644 --- a/src/i18n/ru.json +++ b/src/i18n/ru.json @@ -132,6 +132,11 @@ "show_admin_badge": "Показывать значок администратора в моем профиле", "show_moderator_badge": "Показывать значок модератора в моем профиле", "nsfw_clickthrough": "Включить скрытие NSFW вложений", + "oauth_tokens": "OAuth токены", + "token": "Токен", + "refresh_token": "Рефреш токен", + "valid_until": "Годен до", + "revoke_token": "Удалить", "panelRadius": "Панели", "pause_on_unfocused": "Приостановить загрузку когда вкладка не в фокусе", "presets": "Пресеты", diff --git a/src/i18n/zh.json b/src/i18n/zh.json index 7ad23c57..089a98e2 100644 --- a/src/i18n/zh.json +++ b/src/i18n/zh.json @@ -134,6 +134,11 @@ "notification_visibility_repeats": "转发", "no_rich_text_description": "不显示富文本格式", "nsfw_clickthrough": "将不和谐附件隐藏,点击才能打开", + "oauth_tokens": "OAuth令牌", + "token": "代币", + "refresh_token": "刷新令牌", + "valid_until": "有效期至", + "revoke_token": "撤消", "panelRadius": "面板", "pause_on_unfocused": "在离开页面时暂停时间线推送", "presets": "预置", diff --git a/src/main.js b/src/main.js index adeb0550..2844194e 100644 --- a/src/main.js +++ b/src/main.js @@ -11,6 +11,7 @@ import configModule from './modules/config.js' import chatModule from './modules/chat.js' import oauthModule from './modules/oauth.js' import mediaViewerModule from './modules/media_viewer.js' +import oauthTokensModule from './modules/oauth_tokens.js' import VueTimeago from 'vue-timeago' import VueI18n from 'vue-i18n' @@ -64,7 +65,8 @@ createPersistedState(persistedStateOptions).then((persistedState) => { config: configModule, chat: chatModule, oauth: oauthModule, - mediaViewer: mediaViewerModule + mediaViewer: mediaViewerModule, + oauthTokens: oauthTokensModule }, plugins: [persistedState, pushNotifications], strict: false // Socket modifies itself, let's ignore this for now. diff --git a/src/modules/oauth_tokens.js b/src/modules/oauth_tokens.js new file mode 100644 index 00000000..00ac1431 --- /dev/null +++ b/src/modules/oauth_tokens.js @@ -0,0 +1,26 @@ +const oauthTokens = { + state: { + tokens: [] + }, + actions: { + fetchTokens ({rootState, commit}) { + rootState.api.backendInteractor.fetchOAuthTokens().then((tokens) => { + commit('swapTokens', tokens) + }) + }, + revokeToken ({rootState, commit, state}, id) { + rootState.api.backendInteractor.revokeOAuthToken(id).then((response) => { + if (response.status === 201) { + commit('swapTokens', state.tokens.filter(token => token.id !== id)) + } + }) + } + }, + mutations: { + swapTokens (state, tokens) { + state.tokens = tokens + } + } +} + +export default oauthTokens diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js index 3d2e8823..7b04343d 100644 --- a/src/services/api/api.service.js +++ b/src/services/api/api.service.js @@ -531,6 +531,23 @@ const fetchBlocks = ({page, credentials}) => { }) } +const fetchOAuthTokens = ({credentials}) => { + const url = '/api/oauth_tokens.json' + + return fetch(url, { + headers: authHeaders(credentials) + }).then((data) => data.json()) +} + +const revokeOAuthToken = ({id, credentials}) => { + const url = `/api/oauth_tokens/${id}` + + return fetch(url, { + headers: authHeaders(credentials), + method: 'DELETE' + }) +} + const suggestions = ({credentials}) => { return fetch(SUGGESTIONS_URL, { headers: authHeaders(credentials) @@ -573,6 +590,8 @@ const apiService = { setUserMute, fetchMutes, fetchBlocks, + fetchOAuthTokens, + revokeOAuthToken, register, getCaptcha, updateAvatar, diff --git a/src/services/backend_interactor_service/backend_interactor_service.js b/src/services/backend_interactor_service/backend_interactor_service.js index 43c914d9..2278cd45 100644 --- a/src/services/backend_interactor_service/backend_interactor_service.js +++ b/src/services/backend_interactor_service/backend_interactor_service.js @@ -65,6 +65,8 @@ const backendInteractorService = (credentials) => { const fetchMutes = () => apiService.fetchMutes({credentials}) const fetchBlocks = (params) => apiService.fetchBlocks({credentials, ...params}) const fetchFollowRequests = () => apiService.fetchFollowRequests({credentials}) + const fetchOAuthTokens = () => apiService.fetchOAuthTokens({credentials}) + const revokeOAuthToken = (id) => apiService.revokeOAuthToken({id, credentials}) const getCaptcha = () => apiService.getCaptcha() const register = (params) => apiService.register(params) @@ -96,6 +98,8 @@ const backendInteractorService = (credentials) => { setUserMute, fetchMutes, fetchBlocks, + fetchOAuthTokens, + revokeOAuthToken, register, getCaptcha, updateAvatar, diff --git a/test/unit/specs/modules/users.spec.js b/test/unit/specs/modules/users.spec.js index 4d49ee24..96ae845b 100644 --- a/test/unit/specs/modules/users.spec.js +++ b/test/unit/specs/modules/users.spec.js @@ -32,6 +32,16 @@ describe('The users module', () => { expect(user.muted).to.eql(false) }) + + it('sets oauth tokens', () => { + const state = cloneDeep(defaultState) + const tokens = [{ id: 1, token: 'bar' }] + + mutations.addOAuthTokens(state, tokens) + + expect(state.oauthTokens).to.have.length(1) + expect(state.oauthTokens).to.eql(tokens) + }) }) describe('getUserByName', () => { -- cgit v1.2.3-70-g09d2 From 9aec49bacb033cdcc118f821706c419d384bf5fe Mon Sep 17 00:00:00 2001 From: jasper Date: Wed, 27 Feb 2019 17:45:08 -0800 Subject: Fetch activites by last id --- src/modules/statuses.js | 19 ++++++++++--------- .../timeline_fetcher/timeline_fetcher.service.js | 2 +- 2 files changed, 11 insertions(+), 10 deletions(-) (limited to 'src/modules') diff --git a/src/modules/statuses.js b/src/modules/statuses.js index 826b544c..4002f282 100644 --- a/src/modules/statuses.js +++ b/src/modules/statuses.js @@ -10,6 +10,7 @@ const emptyTl = (userId = 0) => ({ visibleStatusesObject: {}, newStatusCount: 0, maxId: 0, + minId: 0, minVisibleId: 0, loading: false, followers: [], @@ -117,11 +118,16 @@ const addNewStatuses = (state, { statuses, showImmediately = false, timeline, us const timelineObject = state.timelines[timeline] const maxNew = statuses.length > 0 ? maxBy(statuses, 'id').id : 0 - const older = timeline && maxNew < timelineObject.maxId + const minNew = statuses.length > 0 ? minBy(statuses, 'id').id : 0 + const newer = timeline && maxNew > timelineObject.maxId && statuses.length > 0 + const older = timeline && (minNew < timelineObject.minId || timelineObject.minId === 0) && statuses.length > 0 - if (timeline && !noIdUpdate && statuses.length > 0 && !older) { + if (!noIdUpdate && newer) { timelineObject.maxId = maxNew } + if (!noIdUpdate && older) { + timelineObject.minId = minNew + } // This makes sure that user timeline won't get data meant for other // user. I.e. opening different user profiles makes request which could @@ -255,13 +261,8 @@ const addNewStatuses = (state, { statuses, showImmediately = false, timeline, us processor(status) }) - // Keep the visible statuses sorted - if (timeline) { - sortTimeline(timelineObject) - if ((older || timelineObject.minVisibleId <= 0) && statuses.length > 0) { - timelineObject.minVisibleId = minBy(statuses, 'id').id - } - } + // Keep the visible statuses sorted + if (timeline) sortTimeline(timelineObject) } const addNewNotifications = (state, { dispatch, notifications, older, visibleNotificationTypes }) => { diff --git a/src/services/timeline_fetcher/timeline_fetcher.service.js b/src/services/timeline_fetcher/timeline_fetcher.service.js index 64f8f468..6f99616f 100644 --- a/src/services/timeline_fetcher/timeline_fetcher.service.js +++ b/src/services/timeline_fetcher/timeline_fetcher.service.js @@ -21,7 +21,7 @@ const fetchAndUpdate = ({store, credentials, timeline = 'friends', older = false const timelineData = rootState.statuses.timelines[camelCase(timeline)] if (older) { - args['until'] = until || timelineData.minVisibleId + args['until'] = until || timelineData.minId } else { args['since'] = timelineData.maxId } -- cgit v1.2.3-70-g09d2 From 5c43374588b810bf1ba8b74414867d0324b3c59f Mon Sep 17 00:00:00 2001 From: taehoon Date: Mon, 25 Feb 2019 02:11:39 -0500 Subject: Clean up addFollowers action --- src/modules/users.js | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'src/modules') 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) -- cgit v1.2.3-70-g09d2 From 080786c9458ba8b9db1ea63732824a3e297e10dc Mon Sep 17 00:00:00 2001 From: taehoon Date: Mon, 25 Feb 2019 04:51:23 -0500 Subject: 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 (limited to 'src/modules') 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 -- cgit v1.2.3-70-g09d2 From 81e89fed3d6cc247346611e1b58aae9d87667934 Mon Sep 17 00:00:00 2001 From: jasper Date: Fri, 1 Mar 2019 12:53:24 -0800 Subject: Fetch activites by last id --- src/modules/statuses.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/modules') diff --git a/src/modules/statuses.js b/src/modules/statuses.js index 4002f282..96a3549d 100644 --- a/src/modules/statuses.js +++ b/src/modules/statuses.js @@ -262,7 +262,9 @@ const addNewStatuses = (state, { statuses, showImmediately = false, timeline, us }) // Keep the visible statuses sorted - if (timeline) sortTimeline(timelineObject) + if (timeline) { + sortTimeline(timelineObject) + } } const addNewNotifications = (state, { dispatch, notifications, older, visibleNotificationTypes }) => { -- cgit v1.2.3-70-g09d2