parent
8035cb2580
commit
35058ed965
|
@ -6,6 +6,7 @@ export function toggleContentWarningShown (realm) {
|
|||
const newShown = !shown
|
||||
store.setComposeData(realm, {
|
||||
contentWarning: newShown ? contentWarning : '',
|
||||
contentWarningShown: newShown
|
||||
contentWarningShown: newShown,
|
||||
sensitive: contentWarning && newShown // toggling content warning automatically toggles sensitive media
|
||||
})
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
<ComposeToolbar {realm} {postPrivacy} {media} {contentWarningShown} {text} {poll} />
|
||||
<ComposeLengthIndicator {length} {overLimit} />
|
||||
<ComposeMedia {realm} {media} />
|
||||
<ComposeMediaSensitive {realm} {media} {sensitive} {contentWarning} {contentWarningShown} />
|
||||
</div>
|
||||
</ComposeFileDrop>
|
||||
<ComposeStickyButton {showSticky}
|
||||
|
@ -46,7 +47,8 @@
|
|||
"avatar autosuggest autosuggest autosuggest"
|
||||
"avatar poll poll poll"
|
||||
"avatar toolbar toolbar length"
|
||||
"avatar media media media";
|
||||
"avatar media media media"
|
||||
"avatar sensitive sensitive sensitive";
|
||||
grid-template-columns: min-content minmax(0, max-content) 1fr 1fr;
|
||||
position: relative;
|
||||
}
|
||||
|
@ -95,6 +97,7 @@
|
|||
import ComposeFileDrop from './ComposeFileDrop.html'
|
||||
import ComposeAutosuggest from './ComposeAutosuggest.html'
|
||||
import ComposePoll from './ComposePoll.html'
|
||||
import ComposeMediaSensitive from './ComposeMediaSensitive.html'
|
||||
import { measureText } from '../../_utils/measureText'
|
||||
import { POST_PRIVACY_OPTIONS } from '../../_static/statuses'
|
||||
import { store } from '../../_store/store'
|
||||
|
@ -133,7 +136,8 @@
|
|||
ComposeContentWarning,
|
||||
ComposeFileDrop,
|
||||
ComposeAutosuggest,
|
||||
ComposePoll
|
||||
ComposePoll,
|
||||
ComposeMediaSensitive
|
||||
},
|
||||
data: () => ({
|
||||
size: undefined,
|
||||
|
@ -173,7 +177,8 @@
|
|||
),
|
||||
overLimit: ({ length, $maxStatusChars }) => length > $maxStatusChars,
|
||||
contentWarningShown: ({ composeData }) => composeData.contentWarningShown,
|
||||
contentWarning: ({ composeData }) => composeData.contentWarning || ''
|
||||
contentWarning: ({ composeData }) => composeData.contentWarning || '',
|
||||
sensitive: ({ composeData }) => !!composeData.sensitive
|
||||
},
|
||||
transitions: {
|
||||
slide
|
||||
|
@ -196,9 +201,9 @@
|
|||
overLimit,
|
||||
inReplyToUuid, // typical replies, using Pinafore-specific uuid
|
||||
inReplyToId, // delete-and-redraft replies, using standard id
|
||||
poll
|
||||
poll,
|
||||
sensitive
|
||||
} = this.get()
|
||||
const sensitive = media.length && !!contentWarning
|
||||
const mediaIds = media.map(_ => _.data.id)
|
||||
const mediaDescriptions = media.map(_ => _.description)
|
||||
const mediaFocalPoints = media.map(_ => [_.focusX, _.focusY])
|
||||
|
|
|
@ -41,7 +41,10 @@
|
|||
const { realm } = this.get()
|
||||
this.observe('rawText', rawText => {
|
||||
updateContentWarningInStore(() => {
|
||||
this.store.setComposeData(realm, { contentWarning: rawText })
|
||||
this.store.setComposeData(realm, {
|
||||
sensitive: !!rawText, // toggling the content warning automatically toggles sensitive media
|
||||
contentWarning: rawText
|
||||
})
|
||||
this.store.save()
|
||||
})
|
||||
}, { init: false })
|
||||
|
|
|
@ -113,6 +113,12 @@
|
|||
max-height: 7vh;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 320px) {
|
||||
.compose-media-realm-dialog .compose-media-alt-input {
|
||||
display: none; /* too small to show this - use the edit button instead */
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
import { store } from '../../_store/store'
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
{#if media.length}
|
||||
<div class="compose-media-sensitive">
|
||||
<label>
|
||||
<input type="checkbox" bind:checked="rawChecked" {disabled} />
|
||||
<span class="{disabled ? 'compose-sensitive-span-disabled' : ''}">
|
||||
Mark media as sensitive
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
{/if}
|
||||
<style>
|
||||
.compose-media-sensitive {
|
||||
grid-area: sensitive;
|
||||
margin-top: 10px;
|
||||
}
|
||||
label {
|
||||
padding: 5px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
span {
|
||||
margin-left: 5px;
|
||||
}
|
||||
.compose-sensitive-span-disabled {
|
||||
color: var(--deemphasized-text-color);
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.compose-media-sensitive {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 320px) {
|
||||
span {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
<script>
|
||||
import { observe } from 'svelte-extras'
|
||||
import { scheduleIdleTask } from '../../_utils/scheduleIdleTask'
|
||||
|
||||
export default {
|
||||
oncreate () {
|
||||
this.setupSyncToStore()
|
||||
this.setupSyncFromStore()
|
||||
},
|
||||
data: () => ({
|
||||
rawChecked: false
|
||||
}),
|
||||
computed: {
|
||||
disabled: ({ contentWarning, contentWarningShown }) => contentWarning && contentWarningShown
|
||||
},
|
||||
methods: {
|
||||
observe,
|
||||
setupSyncToStore () {
|
||||
this.observe('rawChecked', () => {
|
||||
scheduleIdleTask(() => {
|
||||
const { realm } = this.get()
|
||||
const { rawChecked } = this.get()
|
||||
const sensitive = this.store.getComposeData(realm, 'sensitive')
|
||||
if (sensitive !== rawChecked) {
|
||||
this.store.setComposeData(realm, { sensitive: rawChecked })
|
||||
this.store.save()
|
||||
}
|
||||
})
|
||||
}, { init: false })
|
||||
},
|
||||
setupSyncFromStore () {
|
||||
this.observe('sensitive', sensitive => {
|
||||
this.set({ rawChecked: sensitive })
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -10,7 +10,8 @@ import {
|
|||
homeNavButton,
|
||||
mediaButton,
|
||||
notificationsNavButton,
|
||||
uploadKittenImage
|
||||
uploadKittenImage,
|
||||
composeMediaSensitiveCheckbox, getNthStatusAndSensitiveImage, getNthStatusAndSensitiveButton, getNthStatusContent
|
||||
} from '../utils'
|
||||
import { loginAsFoobar } from '../roles'
|
||||
|
||||
|
@ -97,3 +98,20 @@ test('can post a status with empty content if there is media', async t => {
|
|||
await t.click(composeButton)
|
||||
.expect(getNthStatusAndImage(1, 1).getAttribute('alt')).eql('just an image!')
|
||||
})
|
||||
|
||||
test('can make an image sensitive without adding a CW', async t => {
|
||||
await loginAsFoobar(t)
|
||||
await t
|
||||
.typeText(composeInput, 'this is just a kitteh')
|
||||
await (uploadKittenImage(2)())
|
||||
await t
|
||||
.typeText(getNthMediaAltInput(1), 'sensitive kitteh')
|
||||
.expect(composeMediaSensitiveCheckbox.checked).notOk()
|
||||
.click(composeMediaSensitiveCheckbox)
|
||||
.expect(composeMediaSensitiveCheckbox.checked).ok()
|
||||
.click(composeButton)
|
||||
.expect(getNthStatusContent(1).innerText).contains('this is just a kitteh')
|
||||
.expect(getNthStatusAndSensitiveImage(1, 1).getAttribute('src')).match(/^blob:http:\/\/localhost/)
|
||||
.click(getNthStatusAndSensitiveButton(1, 1))
|
||||
.expect(getNthStatusAndImage(1, 1).getAttribute('alt')).eql('sensitive kitteh')
|
||||
})
|
||||
|
|
|
@ -71,6 +71,8 @@ export const composePollExpiryOption = $('.compose-poll select option')
|
|||
export const composePollExpiryInDialog = $('.modal-dialog .compose-poll select')
|
||||
export const composePollAddButton = $('.compose-poll button:last-of-type')
|
||||
|
||||
export const composeMediaSensitiveCheckbox = $('.compose-media-sensitive input')
|
||||
|
||||
export const postPrivacyDialogButtonUnlisted = $('[aria-label="Post privacy dialog"] li:nth-child(2) button')
|
||||
|
||||
export const accountProfileFilterStatuses = $('.account-profile-filters li:nth-child(1)')
|
||||
|
@ -352,6 +354,14 @@ export function getNthStatusAndImage (nStatus, nImage) {
|
|||
return $(`${getNthStatusSelector(nStatus)} .status-media .show-image-button:nth-child(${nImage}) img`)
|
||||
}
|
||||
|
||||
export function getNthStatusAndSensitiveButton (nStatus, nImage) {
|
||||
return $(`${getNthStatusSelector(nStatus)} .status-sensitive-media-button:nth-child(${nImage})`)
|
||||
}
|
||||
|
||||
export function getNthStatusAndSensitiveImage (nStatus, nImage) {
|
||||
return $(`${getNthStatusSelector(nStatus)} .status-media button:nth-child(${nImage}) img`)
|
||||
}
|
||||
|
||||
export function getFirstVisibleStatus () {
|
||||
return $('.list-item > article[aria-posinset]').nth(0)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue