feat: implement shortcut for opening/closing all CWs (#1973)
Fixes #1914
This commit is contained in:
parent
a21a889f5f
commit
8c09ede2d4
|
@ -155,6 +155,7 @@ export default {
|
|||
<li><kbd>p</kbd> das Profil des Verfassers öffnen</li>
|
||||
<li><kbd>l</kbd> den Link des aktuellen Tröts in einem neuen Tab öffnen</li>
|
||||
<li><kbd>x</kbd> den Text hinter der Inhaltswarnung anzeigen oder verbergen</li>
|
||||
<li><kbd>z</kbd> den Text hinter der Inhaltswarnung anzeigen oder verbergen (alle)</li>
|
||||
`,
|
||||
mediaHotkeys: `
|
||||
<li><kbd>←</kbd> / <kbd>→</kbd> zum nächsten oder vorherigen Inhalt gehen</li>
|
||||
|
|
|
@ -156,6 +156,7 @@ export default {
|
|||
<li><kbd>p</kbd> to open the author's profile</li>
|
||||
<li><kbd>l</kbd> to open the card's link in a new tab</li>
|
||||
<li><kbd>x</kbd> to show or hide text behind content warning</li>
|
||||
<li><kbd>z</kbd> to show or hide all content warnings in a thread</li>
|
||||
`,
|
||||
mediaHotkeys: `
|
||||
<li><kbd>←</kbd> / <kbd>→</kbd> to go to next or previous</li>
|
||||
|
|
|
@ -156,6 +156,7 @@ export default {
|
|||
<li><kbd>p</kbd> pour voir le profile de l'auteur</li>
|
||||
<li><kbd>l</kbd> pour ouvrir un lien de carte dans un nouvel onglet</li>
|
||||
<li><kbd>x</kbd> pour afficher ou cacher le texte caché derrière une avertissement</li>
|
||||
<li><kbd>z</kbd> pour afficher ou cacher toutes les avertissements</li>
|
||||
`,
|
||||
mediaHotkeys: `
|
||||
<li><kbd>←</kbd> / <kbd>→</kbd> pour voir la prochaine ou dernière image</li>
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
} from '../../_utils/shortcuts'
|
||||
import { smoothScroll } from '../../_utils/smoothScroll'
|
||||
import { getScrollContainer } from '../../_utils/scrollContainer'
|
||||
import { store } from '../../_store/store'
|
||||
import { emit } from '../../_utils/eventBus'
|
||||
|
||||
const VISIBILITY_CHECK_DELAY_MS = 600
|
||||
|
||||
|
@ -32,8 +34,10 @@
|
|||
export default {
|
||||
data: () => ({
|
||||
activeItemChangeTime: 0,
|
||||
elements: document.getElementsByClassName('shortcut-list-item')
|
||||
elements: document.getElementsByClassName('shortcut-list-item'),
|
||||
spoilersShown: false
|
||||
}),
|
||||
store: () => store,
|
||||
oncreate () {
|
||||
addShortcutFallback(scope, this)
|
||||
},
|
||||
|
@ -45,6 +49,15 @@
|
|||
if (shouldIgnoreEvent(event)) {
|
||||
return
|
||||
}
|
||||
if (event.key === 'z' && this.store.get().currentTimeline.startsWith('status/')) {
|
||||
// if we're in a thread, toggle all content warnings on or off
|
||||
event.stopPropagation()
|
||||
event.preventDefault()
|
||||
const { spoilersShown } = this.get()
|
||||
emit('toggleAllSpoilers', !spoilersShown)
|
||||
this.set({ spoilersShown: !spoilersShown })
|
||||
return
|
||||
}
|
||||
if (event.key === 'j' || event.key === 'ArrowDown') {
|
||||
event.stopPropagation()
|
||||
event.preventDefault()
|
||||
|
|
|
@ -52,12 +52,15 @@
|
|||
import { registerClickDelegate } from '../../_utils/delegate'
|
||||
import { mark, stop } from '../../_utils/marks'
|
||||
import { emojifyText } from '../../_utils/emojifyText'
|
||||
import { on } from '../../_utils/eventBus'
|
||||
import escapeHtml from 'escape-html'
|
||||
|
||||
export default {
|
||||
oncreate () {
|
||||
this.toggleSpoilers = this.toggleSpoilers.bind(this)
|
||||
const { elementId } = this.get()
|
||||
registerClickDelegate(this, elementId, () => this.toggleSpoilers())
|
||||
on('toggleAllSpoilers', this, this.toggleSpoilers)
|
||||
},
|
||||
store: () => store,
|
||||
components: {
|
||||
|
@ -71,13 +74,13 @@
|
|||
elementId: ({ uuid }) => `spoiler-${uuid}`
|
||||
},
|
||||
methods: {
|
||||
toggleSpoilers () {
|
||||
requestAnimationFrame(() => {
|
||||
mark('clickSpoilerButton')
|
||||
toggleSpoilers (shown) {
|
||||
const { uuid } = this.get()
|
||||
const { spoilersShown } = this.store.get()
|
||||
spoilersShown[uuid] = !spoilersShown[uuid]
|
||||
spoilersShown[uuid] = typeof shown === 'undefined' ? !spoilersShown[uuid] : !!shown
|
||||
this.store.set({ spoilersShown })
|
||||
requestAnimationFrame(() => {
|
||||
mark('clickSpoilerButton')
|
||||
this.fire('recalculateHeight')
|
||||
stop('clickSpoilerButton')
|
||||
})
|
||||
|
|
|
@ -54,6 +54,11 @@ export async function postReplyAs (username, text, inReplyTo) {
|
|||
inReplyTo, null, false, null, 'public')
|
||||
}
|
||||
|
||||
export async function postReplyWithSpoilerAs (username, text, inReplyTo, spoilerText) {
|
||||
return postStatus(instanceName, users[username].accessToken, text,
|
||||
inReplyTo, null, false, spoilerText, 'public')
|
||||
}
|
||||
|
||||
export async function deleteAs (username, statusId) {
|
||||
return deleteStatus(instanceName, users[username].accessToken, statusId)
|
||||
}
|
||||
|
|
41
tests/spec/137-shortcuts-spoiler.js
Normal file
41
tests/spec/137-shortcuts-spoiler.js
Normal file
|
@ -0,0 +1,41 @@
|
|||
import {
|
||||
getNthStatus, getNthStatusContent, getNthStatusSpoiler, getUrl, sleep
|
||||
} from '../utils'
|
||||
import { loginAsFoobar } from '../roles'
|
||||
import { postReplyWithSpoilerAs, postWithSpoilerAndPrivacyAs } from '../serverActions'
|
||||
|
||||
fixture`137-shortcut-spoiler.js`
|
||||
.page`http://localhost:4002`
|
||||
|
||||
test('Can toggle all spoilers with shortcut', async t => {
|
||||
const { id: statusId1 } = await postWithSpoilerAndPrivacyAs('admin', 'the content', 'yolo', 'public')
|
||||
const { id: statusId2 } = await postReplyWithSpoilerAs('admin', 'the content', statusId1, 'haha')
|
||||
await postReplyWithSpoilerAs('admin', 'the content', statusId2, 'wheeee')
|
||||
await sleep(500)
|
||||
await loginAsFoobar(t)
|
||||
await t
|
||||
.expect(getNthStatusSpoiler(1).innerText).eql('wheeee')
|
||||
.click(getNthStatus(1))
|
||||
.expect(getUrl()).contains('/statuses')
|
||||
.expect(getNthStatusSpoiler(1).innerText).eql('yolo')
|
||||
.expect(getNthStatusSpoiler(2).innerText).eql('haha')
|
||||
.expect(getNthStatusSpoiler(3).innerText).eql('wheeee')
|
||||
.expect(getNthStatusContent(1).visible).notOk()
|
||||
.expect(getNthStatusContent(2).visible).notOk()
|
||||
.expect(getNthStatusContent(3).visible).notOk()
|
||||
await sleep(500)
|
||||
await t
|
||||
.pressKey('z')
|
||||
.expect(getNthStatusContent(1).innerText).contains('the content')
|
||||
.expect(getNthStatusContent(2).innerText).contains('the content')
|
||||
.expect(getNthStatusContent(3).innerText).contains('the content')
|
||||
.expect(getNthStatusContent(1).visible).ok()
|
||||
.expect(getNthStatusContent(2).visible).ok()
|
||||
.expect(getNthStatusContent(3).visible).ok()
|
||||
await sleep(500)
|
||||
await t
|
||||
.pressKey('z')
|
||||
.expect(getNthStatusContent(1).visible).notOk()
|
||||
.expect(getNthStatusContent(2).visible).notOk()
|
||||
.expect(getNthStatusContent(3).visible).notOk()
|
||||
})
|
Loading…
Reference in a new issue