parent
ebbe6ba9f8
commit
7a152fbdac
|
@ -4,12 +4,12 @@ import { toast } from '../_components/toast/toast'
|
|||
import { updateLocalRelationship } from './accounts'
|
||||
import { emit } from '../_utils/eventBus'
|
||||
|
||||
export async function setAccountMuted (accountId, mute, toastOnSuccess) {
|
||||
export async function setAccountMuted (accountId, mute, notifications, toastOnSuccess) {
|
||||
let { currentInstance, accessToken } = store.get()
|
||||
try {
|
||||
let relationship
|
||||
if (mute) {
|
||||
relationship = await muteAccount(currentInstance, accessToken, accountId)
|
||||
relationship = await muteAccount(currentInstance, accessToken, accountId, notifications)
|
||||
} else {
|
||||
relationship = await unmuteAccount(currentInstance, accessToken, accountId)
|
||||
}
|
||||
|
|
10
src/routes/_actions/toggleMute.js
Normal file
10
src/routes/_actions/toggleMute.js
Normal file
|
@ -0,0 +1,10 @@
|
|||
import { importShowMuteDialog } from '../_components/dialog/asyncDialogs'
|
||||
import { setAccountMuted } from './mute'
|
||||
|
||||
export async function toggleMute (account, mute) {
|
||||
if (mute) {
|
||||
(await importShowMuteDialog())(account)
|
||||
} else {
|
||||
await setAccountMuted(account.id, mute, /* notifications */ false, /* toastOnSuccess */ true)
|
||||
}
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
import { auth, basename } from './utils'
|
||||
import { post, WRITE_TIMEOUT } from '../_utils/ajax'
|
||||
|
||||
export async function muteAccount (instanceName, accessToken, accountId) {
|
||||
export async function muteAccount (instanceName, accessToken, accountId, notifications) {
|
||||
let url = `${basename(instanceName)}/api/v1/accounts/${accountId}/mute`
|
||||
return post(url, null, auth(accessToken), { timeout: WRITE_TIMEOUT })
|
||||
return post(url, { notifications }, auth(accessToken), { timeout: WRITE_TIMEOUT })
|
||||
}
|
||||
|
||||
export async function unmuteAccount (instanceName, accessToken, accountId) {
|
||||
|
|
|
@ -8,8 +8,8 @@ export const importShowComposeDialog = () => import(
|
|||
/* webpackChunkName: 'showComposeDialog' */ './creators/showComposeDialog'
|
||||
).then(getDefault)
|
||||
|
||||
export const importShowConfirmationDialog = () => import(
|
||||
/* webpackChunkName: 'showConfirmationDialog' */ './creators/showConfirmationDialog'
|
||||
export const importShowTextConfirmationDialog = () => import(
|
||||
/* webpackChunkName: 'showTextConfirmationDialog' */ './creators/showTextConfirmationDialog'
|
||||
).then(getDefault)
|
||||
|
||||
export const importShowEmojiDialog = () => import(
|
||||
|
@ -35,3 +35,7 @@ export const importShowShortcutHelpDialog = () => import(
|
|||
export const importShowMediaDialog = () => import(
|
||||
/* webpackChunkName: 'showMediaDialog' */ './creators/showMediaDialog'
|
||||
).then(getDefault)
|
||||
|
||||
export const importShowMuteDialog = () => import(
|
||||
/* webpackChunkName: 'showMuteDialog' */ './creators/showMuteDialog'
|
||||
).then(getDefault)
|
||||
|
|
|
@ -15,12 +15,12 @@ import { show } from '../helpers/showDialog'
|
|||
import { close } from '../helpers/closeDialog'
|
||||
import { oncreate } from '../helpers/onCreateDialog'
|
||||
import { setAccountBlocked } from '../../../_actions/block'
|
||||
import { setAccountMuted } from '../../../_actions/mute'
|
||||
import { setAccountFollowed } from '../../../_actions/follow'
|
||||
import { setShowReblogs } from '../../../_actions/setShowReblogs'
|
||||
import { setDomainBlocked } from '../../../_actions/setDomainBlocked'
|
||||
import { copyText } from '../../../_actions/copyText'
|
||||
import { composeNewStatusMentioning } from '../../../_actions/mention'
|
||||
import { toggleMute } from '../../../_actions/toggleMute'
|
||||
|
||||
export default {
|
||||
oncreate,
|
||||
|
@ -155,9 +155,9 @@ export default {
|
|||
await setAccountBlocked(accountId, !blocking, true)
|
||||
},
|
||||
async onMuteClicked () {
|
||||
let { accountId, muting } = this.get()
|
||||
let { account, muting } = this.get()
|
||||
this.close()
|
||||
await setAccountMuted(accountId, !muting, true)
|
||||
await toggleMute(account, !muting)
|
||||
},
|
||||
async onShowReblogsClicked () {
|
||||
let { accountId, showingReblogs } = this.get()
|
||||
|
|
|
@ -1,18 +1,21 @@
|
|||
<ModalDialog
|
||||
{id}
|
||||
{label}
|
||||
{title}
|
||||
background="var(--main-bg)"
|
||||
>
|
||||
<form class="confirmation-dialog-form">
|
||||
<p>
|
||||
{text}
|
||||
</p>
|
||||
{#if component}
|
||||
<svelte:component this={component} {...componentOpts} />
|
||||
{:else}
|
||||
<p>{text}</p>
|
||||
{/if}
|
||||
<div class="confirmation-dialog-form-flex">
|
||||
<button type="button" on:click="onPositive()">
|
||||
{positiveText || 'OK'}
|
||||
{positiveText}
|
||||
</button>
|
||||
<button type="button" on:click="onNegative()">
|
||||
{negativeText || 'Cancel'}
|
||||
{negativeText}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -44,6 +47,15 @@
|
|||
on('destroyDialog', this, this.onDestroyDialog)
|
||||
onCreateDialog.call(this)
|
||||
},
|
||||
data: () => ({
|
||||
component: void 0,
|
||||
text: void 0,
|
||||
onPositive: void 0,
|
||||
onNegative: void 0,
|
||||
title: '',
|
||||
positiveText: 'OK',
|
||||
negativeText: 'Cancel'
|
||||
}),
|
||||
methods: {
|
||||
show,
|
||||
close,
|
||||
|
@ -58,10 +70,12 @@
|
|||
return
|
||||
}
|
||||
if (positiveResult) {
|
||||
this.fire('positive')
|
||||
if (onPositive) {
|
||||
onPositive()
|
||||
}
|
||||
} else {
|
||||
this.fire('negative')
|
||||
if (onNegative) {
|
||||
onNegative()
|
||||
}
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
<ModalDialog
|
||||
{id}
|
||||
{label}
|
||||
{title}
|
||||
background="var(--main-bg)"
|
||||
>
|
||||
<form class="confirmation-dialog-form">
|
||||
<slot></slot>
|
||||
<div class="confirmation-dialog-form-flex">
|
||||
<button type="button" on:click="onPositive()">
|
||||
{positiveText || 'OK'}
|
||||
</button>
|
||||
<button type="button" on:click="onNegative()">
|
||||
{negativeText || 'Cancel'}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</ModalDialog>
|
||||
<style>
|
||||
.confirmation-dialog-form-flex {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
grid-gap: 10px;
|
||||
padding: 10px 20px;
|
||||
}
|
||||
.confirmation-dialog-form-flex button {
|
||||
min-width: 125px;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
import ModalDialog from './ModalDialog.html'
|
||||
import { show } from '../helpers/showDialog'
|
||||
import { close } from '../helpers/closeDialog'
|
||||
import { on } from '../../../_utils/eventBus'
|
||||
import { oncreate as onCreateDialog } from '../helpers/onCreateDialog'
|
||||
|
||||
export default {
|
||||
oncreate () {
|
||||
on('destroyDialog', this, this.onDestroyDialog)
|
||||
onCreateDialog.call(this)
|
||||
},
|
||||
data: () => ({
|
||||
positiveText: void 0,
|
||||
negativeText: void 0
|
||||
}),
|
||||
methods: {
|
||||
show,
|
||||
close,
|
||||
onDestroyDialog (thisId) {
|
||||
let {
|
||||
id,
|
||||
positiveResult
|
||||
} = this.get()
|
||||
if (thisId !== id) {
|
||||
return
|
||||
}
|
||||
if (positiveResult) {
|
||||
this.fire('positive')
|
||||
} else {
|
||||
this.fire('negative')
|
||||
}
|
||||
},
|
||||
onPositive () {
|
||||
this.set({ positiveResult: true })
|
||||
this.close()
|
||||
},
|
||||
onNegative () {
|
||||
this.close()
|
||||
}
|
||||
},
|
||||
components: {
|
||||
ModalDialog
|
||||
}
|
||||
}
|
||||
</script>
|
60
src/routes/_components/dialog/components/MuteDialog.html
Normal file
60
src/routes/_components/dialog/components/MuteDialog.html
Normal file
|
@ -0,0 +1,60 @@
|
|||
<GenericConfirmationDialog
|
||||
{id}
|
||||
{label}
|
||||
{title}
|
||||
{positiveText}
|
||||
on:positive="doMute()"
|
||||
>
|
||||
<div class="mute-dialog">
|
||||
<p>
|
||||
Mute @{account.acct} ?
|
||||
</p>
|
||||
<form class="mute-dialog-form">
|
||||
<input type="checkbox"
|
||||
id="mute-notifications"
|
||||
name="mute-notifications"
|
||||
bind:checked="muteNotifications">
|
||||
<label for="mute-notifications">Mute notifications as well</label>
|
||||
</form>
|
||||
</div>
|
||||
</GenericConfirmationDialog>
|
||||
<style>
|
||||
.mute-dialog {
|
||||
padding: 20px;
|
||||
}
|
||||
.mute-dialog-form {
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
import GenericConfirmationDialog from './GenericConfirmationDialog.html'
|
||||
import { show } from '../helpers/showDialog'
|
||||
import { close } from '../helpers/closeDialog'
|
||||
import { oncreate } from '../helpers/onCreateDialog'
|
||||
import { setAccountMuted } from '../../../_actions/mute'
|
||||
|
||||
export default {
|
||||
oncreate,
|
||||
data: () => ({
|
||||
positiveText: 'Mute',
|
||||
title: '',
|
||||
muteNotifications: true
|
||||
}),
|
||||
methods: {
|
||||
show,
|
||||
close,
|
||||
async doMute () {
|
||||
let { account, muteNotifications } = this.get()
|
||||
this.close()
|
||||
await setAccountMuted(
|
||||
account.id,
|
||||
/* mute */ true,
|
||||
muteNotifications,
|
||||
/* toastOnSuccess */ true)
|
||||
}
|
||||
},
|
||||
components: {
|
||||
GenericConfirmationDialog
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -16,12 +16,12 @@ import { show } from '../helpers/showDialog'
|
|||
import { close } from '../helpers/closeDialog'
|
||||
import { oncreate } from '../helpers/onCreateDialog'
|
||||
import { setAccountBlocked } from '../../../_actions/block'
|
||||
import { setAccountMuted } from '../../../_actions/mute'
|
||||
import { setStatusPinnedOrUnpinned } from '../../../_actions/pin'
|
||||
import { setConversationMuted } from '../../../_actions/muteConversation'
|
||||
import { copyText } from '../../../_actions/copyText'
|
||||
import { deleteAndRedraft } from '../../../_actions/deleteAndRedraft'
|
||||
import { shareStatus } from '../../../_actions/share'
|
||||
import { toggleMute } from '../../../_actions/toggleMute'
|
||||
|
||||
export default {
|
||||
oncreate,
|
||||
|
@ -183,9 +183,9 @@ export default {
|
|||
await setAccountBlocked(accountId, !blocking, true)
|
||||
},
|
||||
async onMuteClicked () {
|
||||
let { accountId, muting } = this.get()
|
||||
let { account, muting } = this.get()
|
||||
this.close()
|
||||
await setAccountMuted(accountId, !muting, true)
|
||||
await toggleMute(account, !muting)
|
||||
},
|
||||
async onMuteConversationClicked () {
|
||||
let { statusId, mutingConversation } = this.get()
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
<GenericConfirmationDialog
|
||||
{id}
|
||||
{label}
|
||||
{title}
|
||||
{positiveText}
|
||||
{negativeText}
|
||||
on:positive
|
||||
on:negative>
|
||||
<p>{text}</p>
|
||||
</GenericConfirmationDialog>
|
||||
<style>
|
||||
p {
|
||||
font-size: 1.3em;
|
||||
padding: 40px 20px;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
import GenericConfirmationDialog from './GenericConfirmationDialog.html'
|
||||
import { show } from '../helpers/showDialog'
|
||||
import { close } from '../helpers/closeDialog'
|
||||
import { oncreate } from '../helpers/onCreateDialog'
|
||||
|
||||
export default {
|
||||
oncreate,
|
||||
data: () => ({
|
||||
title: void 0,
|
||||
positiveText: void 0,
|
||||
negativeText: void 0
|
||||
}),
|
||||
methods: {
|
||||
show,
|
||||
close
|
||||
},
|
||||
components: {
|
||||
GenericConfirmationDialog
|
||||
}
|
||||
}
|
||||
</script>
|
16
src/routes/_components/dialog/creators/showMuteDialog.js
Normal file
16
src/routes/_components/dialog/creators/showMuteDialog.js
Normal file
|
@ -0,0 +1,16 @@
|
|||
import MuteDialog from '../components/MuteDialog.html'
|
||||
import { createDialogElement } from '../helpers/createDialogElement'
|
||||
import { createDialogId } from '../helpers/createDialogId'
|
||||
|
||||
export default function showMuteDialog (account) {
|
||||
let dialog = new MuteDialog({
|
||||
target: createDialogElement(),
|
||||
data: {
|
||||
id: createDialogId(),
|
||||
label: 'Mute dialog',
|
||||
account
|
||||
}
|
||||
})
|
||||
dialog.show()
|
||||
return dialog
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
import ConfirmationDialog from '../components/ConfirmationDialog.html'
|
||||
import TextConfirmationDialog from '../components/TextConfirmationDialog.html'
|
||||
import { createDialogElement } from '../helpers/createDialogElement'
|
||||
import { createDialogId } from '../helpers/createDialogId'
|
||||
|
||||
export default function showConfirmationDialog (options) {
|
||||
let dialog = new ConfirmationDialog({
|
||||
export default function showTextConfirmationDialog (options) {
|
||||
let dialog = new TextConfirmationDialog({
|
||||
target: createDialogElement(),
|
||||
data: Object.assign({
|
||||
id: createDialogId(),
|
||||
|
@ -11,4 +11,5 @@ export default function showConfirmationDialog (options) {
|
|||
}, options)
|
||||
})
|
||||
dialog.show()
|
||||
return dialog
|
||||
}
|
|
@ -21,7 +21,7 @@
|
|||
</style>
|
||||
<script>
|
||||
import { store } from '../../../_store/store'
|
||||
import { importShowConfirmationDialog } from '../../dialog/asyncDialogs'
|
||||
import { importShowTextConfirmationDialog } from '../../dialog/asyncDialogs'
|
||||
import { switchToInstance, logOutOfInstance } from '../../../_actions/instances'
|
||||
|
||||
export default {
|
||||
|
@ -36,12 +36,11 @@
|
|||
e.preventDefault()
|
||||
let { instanceName } = this.get()
|
||||
|
||||
let showConfirmationDialog = await importShowConfirmationDialog()
|
||||
showConfirmationDialog({
|
||||
text: `Log out of ${instanceName}?`,
|
||||
onPositive () {
|
||||
let showTextConfirmationDialog = await importShowTextConfirmationDialog()
|
||||
showTextConfirmationDialog({
|
||||
text: `Log out of ${instanceName}?`
|
||||
}).on('positive', () => {
|
||||
/* no await */ logOutOfInstance(instanceName)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
</style>
|
||||
<script>
|
||||
import { store } from '../../../_store/store'
|
||||
import { importShowConfirmationDialog } from '../../dialog/asyncDialogs'
|
||||
import { importShowTextConfirmationDialog } from '../../dialog/asyncDialogs'
|
||||
import { logOutOfInstance } from '../../../_actions/instances'
|
||||
import { updatePushSubscriptionForInstance, updateAlerts } from '../../../_actions/pushSubscription'
|
||||
import { toast } from '../../toast/toast'
|
||||
|
@ -76,12 +76,11 @@
|
|||
|
||||
// TODO: Better way to detect missing authorization scope
|
||||
if (err.message.startsWith('403:')) {
|
||||
let showConfirmationDialog = await importShowConfirmationDialog()
|
||||
showConfirmationDialog({
|
||||
text: `You need to reauthenticate in order to enable push notification. Log out of ${instanceName}?`,
|
||||
onPositive () {
|
||||
logOutOfInstance(instanceName)
|
||||
}
|
||||
let showTextConfirmationDialog = await importShowTextConfirmationDialog()
|
||||
showTextConfirmationDialog({
|
||||
text: `You need to reauthenticate in order to enable push notification. Log out of ${instanceName}?`
|
||||
}).on('positive', () => {
|
||||
/* no await */ logOutOfInstance(instanceName)
|
||||
})
|
||||
} else {
|
||||
toast.say(`Failed to update push notification settings: ${err.message}`)
|
||||
|
|
|
@ -15,7 +15,10 @@
|
|||
{
|
||||
icon: '#fa-volume-up',
|
||||
label: 'Unmute',
|
||||
onclick: (accountId) => setAccountMuted(accountId, false, true)
|
||||
onclick: (accountId) => setAccountMuted(accountId,
|
||||
/* mute */ false,
|
||||
/* notifications */ false,
|
||||
/* toastOnSuccess */ true)
|
||||
}
|
||||
]
|
||||
}),
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { Selector as $ } from 'testcafe'
|
||||
import {
|
||||
addInstanceButton,
|
||||
authorizeInput,
|
||||
authorizeInput, confirmationDialogOKButton,
|
||||
emailInput,
|
||||
formError,
|
||||
getFirstVisibleStatus, getNthStatus, getOpacity,
|
||||
|
@ -62,7 +62,7 @@ test('Logs in and logs out of localhost:3000', async t => {
|
|||
.expect($('.acct-handle').innerText).eql('@foobar')
|
||||
.expect($('.acct-display-name').innerText).eql('foobar')
|
||||
.click($('button').withText('Log out'))
|
||||
.click($('.modal-dialog button').withText('OK'))
|
||||
.click(confirmationDialogOKButton)
|
||||
.expect($('.main-content').innerText).contains("You're not logged in to any instances")
|
||||
.click(homeNavButton)
|
||||
// check that the "hidden from SSR" content is visible
|
||||
|
@ -89,7 +89,7 @@ test('Logs in, refreshes, then logs out', async t => {
|
|||
.expect($('.acct-handle').innerText).eql('@foobar')
|
||||
.expect($('.acct-display-name').innerText).eql('foobar')
|
||||
.click($('button').withText('Log out'))
|
||||
.click($('.modal-dialog button').withText('OK'))
|
||||
.click(confirmationDialogOKButton)
|
||||
.expect($('.main-content').innerText).contains("You're not logged in to any instances")
|
||||
.click(homeNavButton)
|
||||
.expect(getOpacity('.hidden-from-ssr')()).eql('1')
|
||||
|
|
|
@ -1,7 +1,15 @@
|
|||
import {
|
||||
accountProfileFollowButton,
|
||||
accountProfileMoreOptionsButton, communityNavButton, getNthSearchResult,
|
||||
getNthStatus, getNthStatusOptionsButton, getNthDialogOptionsOption, getUrl, modalDialog, closeDialogButton
|
||||
accountProfileMoreOptionsButton,
|
||||
communityNavButton,
|
||||
getNthSearchResult,
|
||||
getNthStatus,
|
||||
getNthStatusOptionsButton,
|
||||
getNthDialogOptionsOption,
|
||||
getUrl,
|
||||
modalDialog,
|
||||
closeDialogButton,
|
||||
confirmationDialogOKButton, sleep
|
||||
} from '../utils'
|
||||
import { Selector as $ } from 'testcafe'
|
||||
import { loginAsFoobar } from '../roles'
|
||||
|
@ -21,7 +29,12 @@ test('Can mute and unmute an account', async t => {
|
|||
.expect(getNthDialogOptionsOption(2).innerText).contains('Block @admin')
|
||||
.expect(getNthDialogOptionsOption(3).innerText).contains('Mute @admin')
|
||||
.click(getNthDialogOptionsOption(3))
|
||||
await sleep(1000)
|
||||
await t
|
||||
.click(confirmationDialogOKButton)
|
||||
.expect(modalDialog.exists).notOk()
|
||||
await sleep(1000)
|
||||
await t
|
||||
.click(communityNavButton)
|
||||
.click($('a[href="/muted"]'))
|
||||
.expect(getNthSearchResult(1).innerText).contains('@admin')
|
||||
|
@ -33,6 +46,8 @@ test('Can mute and unmute an account', async t => {
|
|||
.expect(getNthDialogOptionsOption(3).innerText).contains('Block @admin')
|
||||
.expect(getNthDialogOptionsOption(4).innerText).contains('Unmute @admin')
|
||||
.click(getNthDialogOptionsOption(4))
|
||||
await sleep(1000)
|
||||
await t
|
||||
.click(accountProfileMoreOptionsButton)
|
||||
.expect(getNthDialogOptionsOption(1).innerText).contains('Mention @admin')
|
||||
.expect(getNthDialogOptionsOption(2).innerText).contains('Unfollow @admin')
|
||||
|
|
|
@ -47,6 +47,7 @@ export const neverMarkMediaSensitiveInput = $('#choice-never-mark-media-sensitiv
|
|||
export const removeEmojiFromDisplayNamesInput = $('#choice-omit-emoji-in-display-names')
|
||||
export const dialogOptionsOption = $(`.modal-dialog button`)
|
||||
export const emojiSearchInput = $('.emoji-mart-search input')
|
||||
export const confirmationDialogOKButton = $('.confirmation-dialog-form-flex button:nth-child(1)')
|
||||
|
||||
export const composeModalInput = $('.modal-dialog .compose-box-input')
|
||||
export const composeModalComposeButton = $('.modal-dialog .compose-box-button')
|
||||
|
|
Loading…
Reference in a new issue