diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js index 0c77199b..81c94969 100644 --- a/src/components/post_status_form/post_status_form.js +++ b/src/components/post_status_form/post_status_form.js @@ -10,6 +10,7 @@ import fileTypeService from '../../services/file_type/file_type.service.js' import { findOffset } from '../../services/offset_finder/offset_finder.service.js' import { reject, map, uniqBy, debounce } from 'lodash' import { usePostLanguageOptions } from 'src/lib/post_language' +import scopeUtils from 'src/lib/scope_utils.js' import suggestor from '../emoji_input/suggestor.js' import { mapGetters, mapState } from 'vuex' import Checkbox from '../checkbox/checkbox.vue' @@ -762,15 +763,9 @@ const PostStatusForm = { this.$store.dispatch('openSettingsModalTab', 'profile') }, suggestedVisibility () { - if (this.copyMessageScope) { - if (this.copyMessageScope === 'direct') { - return this.copyMessageScope - } - if (this.copyMessageScope !== 'public' && this.$store.state.users.currentUser.default_scope !== 'private') { - return this.copyMessageScope - } - } - return this.$store.state.users.currentUser.default_scope + const maxScope = this.copyMessageScope + const defaultScope = this.$store.state.users.currentUser.default_scope + return scopeUtils.negotiate(defaultScope, maxScope) } } } diff --git a/src/components/retweet_button/retweet_button.js b/src/components/retweet_button/retweet_button.js index 15542a11..e37b2a25 100644 --- a/src/components/retweet_button/retweet_button.js +++ b/src/components/retweet_button/retweet_button.js @@ -1,4 +1,6 @@ import ConfirmModal from '../confirm_modal/confirm_modal.vue' +import ScopeSelector from '../scope_selector/scope_selector.vue' +import scopeUtils from 'src/lib/scope_utils.js' import { library } from '@fortawesome/fontawesome-svg-core' import { faRetweet } from '@fortawesome/free-solid-svg-icons' @@ -7,12 +9,14 @@ library.add(faRetweet) const RetweetButton = { props: ['status', 'loggedIn', 'visibility'], components: { - ConfirmModal + ConfirmModal, + ScopeSelector }, data () { return { animated: false, - showingConfirmDialog: false + showingConfirmDialog: false, + retweetVisibility: this.$store.state.users.currentUser.default_scope } }, methods: { @@ -25,7 +29,7 @@ const RetweetButton = { }, doRetweet () { if (!this.status.repeated) { - this.$store.dispatch('retweet', { id: this.status.id }) + this.$store.dispatch('retweet', { id: this.status.id, visibility: this.retweetVisibility }) } else { this.$store.dispatch('unretweet', { id: this.status.id }) } @@ -40,6 +44,9 @@ const RetweetButton = { }, hideConfirmDialog () { this.showingConfirmDialog = false + }, + changeVis (visibility) { + this.retweetVisibility = visibility } }, computed: { @@ -54,6 +61,15 @@ const RetweetButton = { }, remoteInteractionLink () { return this.$store.getters.remoteInteractionLink({ statusId: this.status.id }) + }, + userDefaultScope () { + return this.$store.state.users.currentUser.default_scope + }, + statusScope () { + return this.status.visibility + }, + initialScope () { + return scopeUtils.negotiate(this.userDefaultScope, this.status.visibility) } } } diff --git a/src/components/retweet_button/retweet_button.vue b/src/components/retweet_button/retweet_button.vue index 6dac2637..5cf07b6d 100644 --- a/src/components/retweet_button/retweet_button.vue +++ b/src/components/retweet_button/retweet_button.vue @@ -49,6 +49,12 @@ @cancelled="hideConfirmDialog" > {{ $t('status.repeat_confirm') }} + diff --git a/src/components/scope_selector/scope_selector.js b/src/components/scope_selector/scope_selector.js index 8ec7d332..0858a09b 100644 --- a/src/components/scope_selector/scope_selector.js +++ b/src/components/scope_selector/scope_selector.js @@ -6,6 +6,8 @@ import { faGlobe } from '@fortawesome/free-solid-svg-icons' +import scopeUtils from 'src/lib/scope_utils.js' + library.add( faEnvelope, faGlobe, @@ -13,18 +15,11 @@ library.add( faLockOpen ) -const SCOPE_LEVELS = { - 'direct': 0, - 'private': 1, - 'local': 2, - 'unlisted': 2, - 'public': 3 -} - const ScopeSelector = { props: [ 'showAll', 'userDefault', + // scope of parent object 'originalScope', 'initialScope', 'onScopeChange' @@ -39,16 +34,16 @@ const ScopeSelector = { return !this.showPublic && !this.showUnlisted && !this.showPrivate && !this.showDirect }, showPublic () { - return this.originalScope !== 'direct' && this.shouldShow('public') + return this.shouldShow('public') }, showLocal () { - return this.originalScope !== 'direct' && this.shouldShow('local') + return this.shouldShow('local') }, showUnlisted () { - return this.originalScope !== 'direct' && this.shouldShow('unlisted') + return this.shouldShow('unlisted') }, showPrivate () { - return this.originalScope !== 'direct' && this.shouldShow('private') + return this.shouldShow('private') }, showDirect () { return this.shouldShow('direct') @@ -65,15 +60,10 @@ const ScopeSelector = { }, methods: { shouldShow (scope) { - if (!this.originalScope) { + if (!this.originalScope) return true - } - - if (this.originalScope === 'local') { - return scope === 'direct' || scope === 'local' - } - - return SCOPE_LEVELS[scope] <= SCOPE_LEVELS[this.originalScope] + else + return scopeUtils.compare(scope, this.originalScope) <= 0 }, changeVis (scope) { this.currentScope = scope diff --git a/src/lib/scope_utils.js b/src/lib/scope_utils.js new file mode 100644 index 00000000..22142b5a --- /dev/null +++ b/src/lib/scope_utils.js @@ -0,0 +1,37 @@ +const SCOPE_LEVELS = { + 'direct': 0, + 'private': 1, + 'unlisted': 2, + 'local': 3, + 'public': 3 +} + +export default { + negotiate: (defaultScope, maxScope) => { + if (!maxScope) + return defaultScope; + + if (maxScope === 'local') + return defaultScope === 'direct' ? defaultScope : 'local'; + + if (SCOPE_LEVELS[defaultScope] <= SCOPE_LEVELS[maxScope]) + return defaultScope; + else + return maxScope; + }, + compare: (sa, sb) => { + if (sa === 'local') { + if (sb === 'direct') + return 1; + else if (sb === sa) + return 0; + else + return -1; + } + + if (sa === sb) + return 0; + + return SCOPE_LEVELS[sa] < SCOPE_LEVELS[sb] ? -1 : 1; + } +} diff --git a/src/modules/statuses.js b/src/modules/statuses.js index 200718e3..e5dc7056 100644 --- a/src/modules/statuses.js +++ b/src/modules/statuses.js @@ -663,10 +663,10 @@ const statuses = { return rootState.api.backendInteractor.unmuteConversation({ id: statusId }) .then((status) => commit('setMutedStatus', status)) }, - retweet ({ rootState, commit }, status) { + retweet ({ rootState, commit }, {id, visibility}) { // Optimistic retweeting... - commit('setRetweeted', { status, value: true }) - rootState.api.backendInteractor.retweet({ id: status.id }) + commit('setRetweeted', { status: {id: id}, value: true }) + rootState.api.backendInteractor.retweet({ id: id, visibility: visibility }) .then(status => commit('setRetweetedConfirm', { status: status.retweeted_status, user: rootState.users.currentUser })) }, unretweet ({ rootState, commit }, status) { diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js index de21ef3b..03e91ba1 100644 --- a/src/services/api/api.service.js +++ b/src/services/api/api.service.js @@ -822,8 +822,8 @@ const unfavorite = ({ id, credentials }) => { .then((data) => parseStatus(data)) } -const retweet = ({ id, credentials }) => { - return promisedRequest({ url: MASTODON_RETWEET_URL(id), method: 'POST', credentials }) +const retweet = ({ id, visibility, credentials }) => { + return promisedRequest({ url: MASTODON_RETWEET_URL(id), method: 'POST', payload: { visibility }, credentials }) .then((data) => parseStatus(data)) }