implement post privacy

This commit is contained in:
Nolan Lawson 2018-03-03 13:23:26 -08:00
parent d4e770c28d
commit 35282666cc
12 changed files with 213 additions and 72 deletions

View File

@ -14,6 +14,7 @@ module.exports = [
{id: 'fa-eye', src: 'node_modules/font-awesome-svg-png/white/svg/eye.svg', title: 'Show Sensitive Content'}, {id: 'fa-eye', src: 'node_modules/font-awesome-svg-png/white/svg/eye.svg', title: 'Show Sensitive Content'},
{id: 'fa-eye-slash', src: 'node_modules/font-awesome-svg-png/white/svg/eye-slash.svg', title: 'Hide Sensitive Content'}, {id: 'fa-eye-slash', src: 'node_modules/font-awesome-svg-png/white/svg/eye-slash.svg', title: 'Hide Sensitive Content'},
{id: 'fa-lock', src: 'node_modules/font-awesome-svg-png/white/svg/lock.svg', title: 'Locked'}, {id: 'fa-lock', src: 'node_modules/font-awesome-svg-png/white/svg/lock.svg', title: 'Locked'},
{id: 'fa-unlock', src: 'node_modules/font-awesome-svg-png/white/svg/unlock.svg', title: 'Unlocked'},
{id: 'fa-envelope', src: 'node_modules/font-awesome-svg-png/white/svg/envelope.svg', title: 'Sealed Envelope'}, {id: 'fa-envelope', src: 'node_modules/font-awesome-svg-png/white/svg/envelope.svg', title: 'Sealed Envelope'},
{id: 'fa-user-times', src: 'node_modules/font-awesome-svg-png/white/svg/user-times.svg', title: 'Stop Following'}, {id: 'fa-user-times', src: 'node_modules/font-awesome-svg-png/white/svg/user-times.svg', title: 'Stop Following'},
{id: 'fa-user-plus', src: 'node_modules/font-awesome-svg-png/white/svg/user-plus.svg', title: 'Follow'}, {id: 'fa-user-plus', src: 'node_modules/font-awesome-svg-png/white/svg/user-plus.svg', title: 'Follow'},
@ -25,7 +26,8 @@ module.exports = [
{id: 'fa-bars', src: 'node_modules/font-awesome-svg-png/white/svg/bars.svg', title: 'List'}, {id: 'fa-bars', src: 'node_modules/font-awesome-svg-png/white/svg/bars.svg', title: 'List'},
{id: 'fa-volume-off', src: 'node_modules/font-awesome-svg-png/white/svg/volume-off.svg', title: 'Volume off'}, {id: 'fa-volume-off', src: 'node_modules/font-awesome-svg-png/white/svg/volume-off.svg', title: 'Volume off'},
{id: 'fa-ban', src: 'node_modules/font-awesome-svg-png/white/svg/ban.svg', title: 'Ban'}, {id: 'fa-ban', src: 'node_modules/font-awesome-svg-png/white/svg/ban.svg', title: 'Ban'},
{id: 'fa-camera', src: 'node_modules/font-awesome-svg-png/white/svg/camera.svg', title: 'Camera'}, {id: 'fa-camera', src: 'node_modules/font-awesome-svg-png/white/svg/camera.svg', title: 'Add media'},
{id: 'fa-smile', src: 'node_modules/font-awesome-svg-png/white/svg/smile-o.svg', title: 'Smile'}, {id: 'fa-smile', src: 'node_modules/font-awesome-svg-png/white/svg/smile-o.svg', title: 'Custom emoji'},
{id: 'fa-exclamation-triangle', src: 'node_modules/font-awesome-svg-png/white/svg/exclamation-triangle.svg', title: 'Warning'} {id: 'fa-exclamation-triangle', src: 'node_modules/font-awesome-svg-png/white/svg/exclamation-triangle.svg', title: 'Content warning'},
{id: 'fa-check', src: 'node_modules/font-awesome-svg-png/white/svg/check.svg', title: 'Check'}
] ]

View File

@ -63,7 +63,7 @@ export async function logOutOfInstance (instanceName) {
} }
function setStoreVerifyCredentials (instanceName, thisVerifyCredentials) { function setStoreVerifyCredentials (instanceName, thisVerifyCredentials) {
let verifyCredentials = store.get('verifyCredentials') || {} let verifyCredentials = store.get('verifyCredentials')
verifyCredentials[instanceName] = thisVerifyCredentials verifyCredentials[instanceName] = thisVerifyCredentials
store.set({verifyCredentials: verifyCredentials}) store.set({verifyCredentials: verifyCredentials})
} }

View File

@ -4,14 +4,22 @@
href="#fa-smile" href="#fa-smile"
on:click="onEmojiClick()" on:click="onEmojiClick()"
/> />
<IconButton className="{{$uploadingMedia ? 'spin' : ''}}" <IconButton
label="Add media" className="{{$uploadingMedia ? 'spin' : ''}}"
href="{{$uploadingMedia ? '#fa-spinner' : '#fa-camera'}}" label="Add media"
on:click="onMediaClick()" href="{{$uploadingMedia ? '#fa-spinner' : '#fa-camera'}}"
disabled="{{$uploadingMedia || (uploadedMedia.length === 4)}}" on:click="onMediaClick()"
disabled="{{$uploadingMedia || (uploadedMedia.length === 4)}}"
/>
<IconButton
label="Adjust privacy (currently {{postPrivacy.label}})"
href="{{postPrivacy.icon}}"
on:click="onPostPrivacyClick()"
/>
<IconButton
label="Add content warning"
href="#fa-exclamation-triangle"
/> />
<IconButton label="Adjust privacy" href="#fa-globe" />
<IconButton label="Add content warning" href="#fa-exclamation-triangle" />
<input ref:input <input ref:input
on:change="onFileChange(event)" on:change="onFileChange(event)"
style="display: none;" style="display: none;"
@ -32,6 +40,7 @@
import { updateCustomEmojiForInstance } from '../../_actions/emoji' import { updateCustomEmojiForInstance } from '../../_actions/emoji'
import { importDialogs } from '../../_utils/asyncModules' import { importDialogs } from '../../_utils/asyncModules'
import { doMediaUpload } from '../../_actions/media' import { doMediaUpload } from '../../_actions/media'
import { POST_PRIVACY_OPTIONS } from '../../_static/statuses'
export default { export default {
oncreate() { oncreate() {
@ -62,10 +71,20 @@
let file = e.target.files[0] let file = e.target.files[0]
let realm = this.get('realm') let realm = this.get('realm')
doMediaUpload(realm, file) doMediaUpload(realm, file)
},
async onPostPrivacyClick() {
let dialogs = await importDialogs()
dialogs.showPostPrivacyDialog(this.get('realm'))
} }
}, },
computed: { computed: {
uploadedMedia: ($currentUploadedMedia, realm) => $currentUploadedMedia[realm] || [] uploadedMedia: ($currentUploadedMedia, realm) => $currentUploadedMedia[realm] || [],
postPrivacy: (postPrivacyKey) => {
return POST_PRIVACY_OPTIONS.find(_ => _.key === postPrivacyKey)
},
postPrivacyKey: ($currentPostPrivacy, $currentVerifyCredentials, realm) => {
return $currentPostPrivacy[realm] || $currentVerifyCredentials.source.privacy
}
} }
} }
</script> </script>

View File

@ -0,0 +1,98 @@
<ModalDialog :label :shown :closed :title background="var(--main-bg)">
<ul class="post-privacy">
{{#each postPrivacyOptions as option}}
<li class="post-privacy-item">
<button class="post-privacy-button" on:click="onClick(option)">
<svg>
<use xlink:href="{{option.icon}}" />
</svg>
<span>
{{option.label}}
</span>
<svg class="{{isSelected(option, postPrivacy) ? '' : 'hidden'}}"
aria-hidden="{{!isSelected(option, postPrivacy)}}">
<use xlink:href="#fa-check" />
</svg>
</button>
</li>
{{/each}}
</ul>
</ModalDialog>
<style>
.post-privacy {
list-style: none;
width: 100%;
border: 1px solid var(--settings-list-item-border);
box-sizing: border-box;
min-width: 300px;
max-width: calc(100vw - 20px);
}
.post-privacy-item {
border: 1px solid var(--settings-list-item-border);
font-size: 1.3em;
display: flex;
}
.post-privacy-item svg {
width: 24px;
height: 24px;
fill: var(--svg-fill);
}
.post-privacy-button {
flex: 1;
padding: 20px;
background: var(--settings-list-item-bg);
border: none;
margin: 0;
display: flex;
flex-direction: row;
}
.post-privacy-button span {
flex: 1;
}
.post-privacy-button:hover {
background: var(--settings-list-item-bg-hover);
}
.post-privacy-button:active {
background: var(--settings-list-item-bg-active);
}
</style>
<script>
import ModalDialog from './ModalDialog.html'
import { store } from '../../_store/store'
import { POST_PRIVACY_OPTIONS } from '../../_static/statuses'
export default {
components: {
ModalDialog
},
store: () => store,
data: () => ({
postPrivacyOptions: POST_PRIVACY_OPTIONS
}),
helpers: {
isSelected: (option, postPrivacy) => postPrivacy.key === option.key
},
methods: {
async show() {
this.set({shown: true})
},
onClick(option) {
let postPrivacy = store.get('postPrivacy')
let instanceName = store.get('currentInstance')
let realm = this.get('realm')
postPrivacy[instanceName] = postPrivacy[instanceName] || {}
postPrivacy[instanceName][realm] = option.key
store.set({postPrivacy})
this.set({closed: true})
}
},
computed: {
postPrivacy: (postPrivacyKey) => {
return POST_PRIVACY_OPTIONS.find(_ => _.key === postPrivacyKey)
},
postPrivacyKey: ($currentPostPrivacy, $currentVerifyCredentials, realm) => {
return $currentPostPrivacy[realm] || $currentVerifyCredentials.source.privacy
}
}
}
</script>

View File

@ -2,3 +2,4 @@ export * from './showConfirmationDialog'
export * from './showImageDialog' export * from './showImageDialog'
export * from './showVideoDialog' export * from './showVideoDialog'
export * from './showEmojiDialog' export * from './showEmojiDialog'
export * from './showPostPrivacyDialog'

View File

@ -0,0 +1,13 @@
import PostPrivacyDialog from './PostPrivacyDialog.html'
export function showPostPrivacyDialog (realm) {
let dialog = new PostPrivacyDialog({
target: document.getElementById('modal-dialog'),
data: {
label: 'Post privacy dialog',
title: 'Post privacy',
realm: realm
}
})
dialog.show()
}

View File

@ -1 +1,24 @@
export const CHAR_LIMIT = 500 export const CHAR_LIMIT = 500
export const POST_PRIVACY_OPTIONS = [
{
label: 'Public',
key: 'public',
icon: '#fa-globe'
},
{
label: 'Unlisted',
key: 'unlisted',
icon: '#fa-unlock'
},
{
label: 'Followers-only',
key: 'private',
icon: '#fa-lock'
},
{
label: 'Direct',
key: 'direct',
icon: '#fa-envelope'
}
]

View File

@ -1,4 +1,21 @@
function computeForInstance (store, computedKey, key, defaultValue) {
store.compute(computedKey,
[key, 'currentInstance'],
(instanceData, currentInstance) => (currentInstance && instanceData[currentInstance]) || defaultValue)
}
export function instanceComputations (store) { export function instanceComputations (store) {
computeForInstance(store, 'currentTheme', 'instanceThemes', 'default')
computeForInstance(store, 'currentVerifyCredentials', 'verifyCredentials', null)
computeForInstance(store, 'currentInstanceInfo', 'instanceInfos', null)
computeForInstance(store, 'pinnedPage', 'pinnedPages', '/local')
computeForInstance(store, 'lists', 'instanceLists', [])
computeForInstance(store, 'currentStatusModifications', 'statusModifications', null)
computeForInstance(store, 'currentComposeText', 'composeText', {})
computeForInstance(store, 'currentUploadedMedia', 'uploadedMedia', {})
computeForInstance(store, 'currentCustomEmoji', 'customEmoji', [])
computeForInstance(store, 'currentPostPrivacy', 'postPrivacy', {})
store.compute( store.compute(
'isUserLoggedIn', 'isUserLoggedIn',
['currentInstance', 'loggedInInstances'], ['currentInstance', 'loggedInInstances'],
@ -33,37 +50,6 @@ export function instanceComputations (store) {
(currentInstanceData) => currentInstanceData && currentInstanceData.access_token (currentInstanceData) => currentInstanceData && currentInstanceData.access_token
) )
store.compute(
'currentTheme',
['currentInstance', 'instanceThemes'],
(currentInstance, instanceThemes) => {
return instanceThemes[currentInstance] || 'default'
}
)
store.compute(
'currentVerifyCredentials',
['currentInstance', 'verifyCredentials'],
(currentInstance, verifyCredentials) => verifyCredentials && verifyCredentials[currentInstance]
)
store.compute(
'currentInstanceInfo',
['currentInstance', 'instanceInfos'],
(currentInstance, instanceInfos) => instanceInfos && instanceInfos[currentInstance]
)
store.compute(
'pinnedPage',
['pinnedPages', 'currentInstance'],
(pinnedPages, currentInstance) => (currentInstance && pinnedPages[currentInstance]) || '/local')
store.compute(
'lists',
['instanceLists', 'currentInstance'],
(instanceLists, currentInstance) => (currentInstance && instanceLists[currentInstance]) || []
)
store.compute( store.compute(
'pinnedListTitle', 'pinnedListTitle',
['lists', 'pinnedPage'], ['lists', 'pinnedPage'],
@ -91,29 +77,6 @@ export function instanceComputations (store) {
store.compute('hasNotifications', store.compute('hasNotifications',
['numberOfNotifications'], ['numberOfNotifications'],
(numberOfNotifications) => { (numberOfNotifications) => !!numberOfNotifications
return !!numberOfNotifications
}
)
store.compute('currentStatusModifications',
['statusModifications', 'currentInstance'],
(statusModifications, currentInstance) => {
return statusModifications[currentInstance]
})
store.compute('currentComposeText',
['composeText', 'currentInstance'],
(composeText, currentInstance) => (composeText[currentInstance] || {})
)
store.compute('currentUploadedMedia',
['uploadedMedia', 'currentInstance'],
(uploadedMedia, currentInstance) => (uploadedMedia[currentInstance] || {})
)
store.compute('currentCustomEmoji',
['customEmoji', 'currentInstance'],
(customEmoji, currentInstance) => (customEmoji[currentInstance] || [])
) )
} }

View File

@ -15,7 +15,8 @@ const KEYS_TO_STORE_IN_LOCAL_STORAGE = new Set([
'markMediaAsSensitive', 'markMediaAsSensitive',
'pinnedPages', 'pinnedPages',
'composeText', 'composeText',
'uploadedMedia' 'uploadedMedia',
'postPrivacy'
]) ])
class PinaforeStore extends LocalStorageStore { class PinaforeStore extends LocalStorageStore {
@ -43,7 +44,9 @@ export const store = new PinaforeStore({
composeText: {}, composeText: {},
rawComposeText: '', rawComposeText: '',
customEmoji: {}, customEmoji: {},
uploadedMedia: {} uploadedMedia: {},
postPrivacy: {},
verifyCredentials: {}
}) })
mixins(PinaforeStore) mixins(PinaforeStore)

View File

@ -79,6 +79,7 @@ body.offline,body.theme-hotpants.offline,body.theme-majesty.offline,body.theme-o
<symbol id="fa-eye" viewBox="0 0 1792 1792"><title>Show Sensitive Content</title><path d="M1664 960q-152-236-381-353 61 104 61 225 0 185-131.5 316.5T896 1280t-316.5-131.5T448 832q0-121 61-225-229 117-381 353 133 205 333.5 326.5T896 1408t434.5-121.5T1664 960zM944 576q0-20-14-34t-34-14q-125 0-214.5 89.5T592 832q0 20 14 34t34 14 34-14 14-34q0-86 61-147t147-61q20 0 34-14t14-34zm848 384q0 34-20 69-140 230-376.5 368.5T896 1536t-499.5-139T20 1029Q0 994 0 960t20-69q140-229 376.5-368T896 384t499.5 139T1772 891q20 35 20 69z"></path></symbol> <symbol id="fa-eye" viewBox="0 0 1792 1792"><title>Show Sensitive Content</title><path d="M1664 960q-152-236-381-353 61 104 61 225 0 185-131.5 316.5T896 1280t-316.5-131.5T448 832q0-121 61-225-229 117-381 353 133 205 333.5 326.5T896 1408t434.5-121.5T1664 960zM944 576q0-20-14-34t-34-14q-125 0-214.5 89.5T592 832q0 20 14 34t34 14 34-14 14-34q0-86 61-147t147-61q20 0 34-14t14-34zm848 384q0 34-20 69-140 230-376.5 368.5T896 1536t-499.5-139T20 1029Q0 994 0 960t20-69q140-229 376.5-368T896 384t499.5 139T1772 891q20 35 20 69z"></path></symbol>
<symbol id="fa-eye-slash" viewBox="0 0 1792 1792"><title>Hide Sensitive Content</title><path d="M555 1335l78-141q-87-63-136-159t-49-203q0-121 61-225-229 117-381 353 167 258 427 375zm389-759q0-20-14-34t-34-14q-125 0-214.5 89.5T592 832q0 20 14 34t34 14 34-14 14-34q0-86 61-147t147-61q20 0 34-14t14-34zm363-191q0 7-1 9-106 189-316 567t-315 566l-49 89q-10 16-28 16-12 0-134-70-16-10-16-28 0-12 44-87-143-65-263.5-173T20 1029Q0 998 0 960t20-69q153-235 380-371t496-136q89 0 180 17l54-97q10-16 28-16 5 0 18 6t31 15.5 33 18.5 31.5 18.5T1291 358q16 10 16 27zm37 447q0 139-79 253.5T1056 1250l280-502q8 45 8 84zm448 128q0 35-20 69-39 64-109 145-150 172-347.5 267T896 1536l74-132q212-18 392.5-137T1664 960q-115-179-282-294l63-112q95 64 182.5 153T1772 891q20 34 20 69z"></path></symbol> <symbol id="fa-eye-slash" viewBox="0 0 1792 1792"><title>Hide Sensitive Content</title><path d="M555 1335l78-141q-87-63-136-159t-49-203q0-121 61-225-229 117-381 353 167 258 427 375zm389-759q0-20-14-34t-34-14q-125 0-214.5 89.5T592 832q0 20 14 34t34 14 34-14 14-34q0-86 61-147t147-61q20 0 34-14t14-34zm363-191q0 7-1 9-106 189-316 567t-315 566l-49 89q-10 16-28 16-12 0-134-70-16-10-16-28 0-12 44-87-143-65-263.5-173T20 1029Q0 998 0 960t20-69q153-235 380-371t496-136q89 0 180 17l54-97q10-16 28-16 5 0 18 6t31 15.5 33 18.5 31.5 18.5T1291 358q16 10 16 27zm37 447q0 139-79 253.5T1056 1250l280-502q8 45 8 84zm448 128q0 35-20 69-39 64-109 145-150 172-347.5 267T896 1536l74-132q212-18 392.5-137T1664 960q-115-179-282-294l63-112q95 64 182.5 153T1772 891q20 34 20 69z"></path></symbol>
<symbol id="fa-lock" viewBox="0 0 1792 1792"><title>Locked</title><path d="M640 768h512V576q0-106-75-181t-181-75-181 75-75 181v192zm832 96v576q0 40-28 68t-68 28H416q-40 0-68-28t-28-68V864q0-40 28-68t68-28h32V576q0-184 132-316t316-132 316 132 132 316v192h32q40 0 68 28t28 68z"></path></symbol> <symbol id="fa-lock" viewBox="0 0 1792 1792"><title>Locked</title><path d="M640 768h512V576q0-106-75-181t-181-75-181 75-75 181v192zm832 96v576q0 40-28 68t-68 28H416q-40 0-68-28t-28-68V864q0-40 28-68t68-28h32V576q0-184 132-316t316-132 316 132 132 316v192h32q40 0 68 28t28 68z"></path></symbol>
<symbol id="fa-unlock" viewBox="0 0 1792 1792"><title>Unlocked</title><path d="M1728 576v256q0 26-19 45t-45 19h-64q-26 0-45-19t-19-45V576q0-106-75-181t-181-75-181 75-75 181v192h96q40 0 68 28t28 68v576q0 40-28 68t-68 28H160q-40 0-68-28t-28-68V864q0-40 28-68t68-28h672V576q0-185 131.5-316.5T1280 128t316.5 131.5T1728 576z"></path></symbol>
<symbol id="fa-envelope" viewBox="0 0 1792 1792"><title>Sealed Envelope</title><path d="M1792 710v794q0 66-47 113t-113 47H160q-66 0-113-47T0 1504V710q44 49 101 87 362 246 497 345 57 42 92.5 65.5t94.5 48 110 24.5h2q51 0 110-24.5t94.5-48 92.5-65.5q170-123 498-345 57-39 100-87zm0-294q0 79-49 151t-122 123q-376 261-468 325-10 7-42.5 30.5t-54 38-52 32.5-57.5 27-50 9h-2q-23 0-50-9t-57.5-27-52-32.5-54-38T639 1015q-91-64-262-182.5T172 690q-62-42-117-115.5T0 438q0-78 41.5-130T160 256h1472q65 0 112.5 47t47.5 113z"></path></symbol> <symbol id="fa-envelope" viewBox="0 0 1792 1792"><title>Sealed Envelope</title><path d="M1792 710v794q0 66-47 113t-113 47H160q-66 0-113-47T0 1504V710q44 49 101 87 362 246 497 345 57 42 92.5 65.5t94.5 48 110 24.5h2q51 0 110-24.5t94.5-48 92.5-65.5q170-123 498-345 57-39 100-87zm0-294q0 79-49 151t-122 123q-376 261-468 325-10 7-42.5 30.5t-54 38-52 32.5-57.5 27-50 9h-2q-23 0-50-9t-57.5-27-52-32.5-54-38T639 1015q-91-64-262-182.5T172 690q-62-42-117-115.5T0 438q0-78 41.5-130T160 256h1472q65 0 112.5 47t47.5 113z"></path></symbol>
<symbol id="fa-user-times" viewBox="0 0 2048 1792"><title>Stop Following</title><path d="M704 896q-159 0-271.5-112.5T320 512t112.5-271.5T704 128t271.5 112.5T1088 512 975.5 783.5 704 896zm1077 320l249 249q9 9 9 23 0 13-9 22l-136 136q-9 9-22 9-14 0-23-9l-249-249-249 249q-9 9-23 9-13 0-22-9l-136-136q-9-9-9-22 0-14 9-23l249-249-249-249q-9-9-9-23 0-13 9-22l136-136q9-9 22-9 14 0 23 9l249 249 249-249q9-9 23-9 13 0 22 9l136 136q9 9 9 22 0 14-9 23zm-498 0l-181 181q-37 37-37 91 0 53 37 90l83 83q-21 3-44 3H267q-121 0-194-69T0 1405q0-53 3.5-103.5t14-109T44 1084t43-97.5 62-81 85.5-53.5T346 832q19 0 39 17 154 122 319 122t319-122q20-17 39-17 28 0 57 6-28 27-41 50t-13 56q0 54 37 91z"></path></symbol> <symbol id="fa-user-times" viewBox="0 0 2048 1792"><title>Stop Following</title><path d="M704 896q-159 0-271.5-112.5T320 512t112.5-271.5T704 128t271.5 112.5T1088 512 975.5 783.5 704 896zm1077 320l249 249q9 9 9 23 0 13-9 22l-136 136q-9 9-22 9-14 0-23-9l-249-249-249 249q-9 9-23 9-13 0-22-9l-136-136q-9-9-9-22 0-14 9-23l249-249-249-249q-9-9-9-23 0-13 9-22l136-136q9-9 22-9 14 0 23 9l249 249 249-249q9-9 23-9 13 0 22 9l136 136q9 9 9 22 0 14-9 23zm-498 0l-181 181q-37 37-37 91 0 53 37 90l83 83q-21 3-44 3H267q-121 0-194-69T0 1405q0-53 3.5-103.5t14-109T44 1084t43-97.5 62-81 85.5-53.5T346 832q19 0 39 17 154 122 319 122t319-122q20-17 39-17 28 0 57 6-28 27-41 50t-13 56q0 54 37 91z"></path></symbol>
<symbol id="fa-user-plus" viewBox="0 0 2048 1792"><title>Follow</title><path d="M704 896q-159 0-271.5-112.5T320 512t112.5-271.5T704 128t271.5 112.5T1088 512 975.5 783.5 704 896zm960 128h352q13 0 22.5 9.5t9.5 22.5v192q0 13-9.5 22.5t-22.5 9.5h-352v352q0 13-9.5 22.5t-22.5 9.5h-192q-13 0-22.5-9.5t-9.5-22.5v-352h-352q-13 0-22.5-9.5t-9.5-22.5v-192q0-13 9.5-22.5t22.5-9.5h352V672q0-13 9.5-22.5t22.5-9.5h192q13 0 22.5 9.5t9.5 22.5v352zm-736 224q0 52 38 90t90 38h256v238q-68 50-171 50H267q-121 0-194-69T0 1405q0-53 3.5-103.5t14-109T44 1084t43-97.5 62-81 85.5-53.5T346 832q19 0 39 17 79 61 154.5 91.5T704 971t164.5-30.5T1023 849q20-17 39-17 132 0 217 96h-223q-52 0-90 38t-38 90v192z"></path></symbol> <symbol id="fa-user-plus" viewBox="0 0 2048 1792"><title>Follow</title><path d="M704 896q-159 0-271.5-112.5T320 512t112.5-271.5T704 128t271.5 112.5T1088 512 975.5 783.5 704 896zm960 128h352q13 0 22.5 9.5t9.5 22.5v192q0 13-9.5 22.5t-22.5 9.5h-352v352q0 13-9.5 22.5t-22.5 9.5h-192q-13 0-22.5-9.5t-9.5-22.5v-352h-352q-13 0-22.5-9.5t-9.5-22.5v-192q0-13 9.5-22.5t22.5-9.5h352V672q0-13 9.5-22.5t22.5-9.5h192q13 0 22.5 9.5t9.5 22.5v352zm-736 224q0 52 38 90t90 38h256v238q-68 50-171 50H267q-121 0-194-69T0 1405q0-53 3.5-103.5t14-109T44 1084t43-97.5 62-81 85.5-53.5T346 832q19 0 39 17 79 61 154.5 91.5T704 971t164.5-30.5T1023 849q20-17 39-17 132 0 217 96h-223q-52 0-90 38t-38 90v192z"></path></symbol>
@ -90,9 +91,10 @@ body.offline,body.theme-hotpants.offline,body.theme-majesty.offline,body.theme-o
<symbol id="fa-bars" viewBox="0 0 1792 1792"><title>List</title><path d="M1664 1344v128q0 26-19 45t-45 19H192q-26 0-45-19t-19-45v-128q0-26 19-45t45-19h1408q26 0 45 19t19 45zm0-512v128q0 26-19 45t-45 19H192q-26 0-45-19t-19-45V832q0-26 19-45t45-19h1408q26 0 45 19t19 45zm0-512v128q0 26-19 45t-45 19H192q-26 0-45-19t-19-45V320q0-26 19-45t45-19h1408q26 0 45 19t19 45z"></path></symbol> <symbol id="fa-bars" viewBox="0 0 1792 1792"><title>List</title><path d="M1664 1344v128q0 26-19 45t-45 19H192q-26 0-45-19t-19-45v-128q0-26 19-45t45-19h1408q26 0 45 19t19 45zm0-512v128q0 26-19 45t-45 19H192q-26 0-45-19t-19-45V832q0-26 19-45t45-19h1408q26 0 45 19t19 45zm0-512v128q0 26-19 45t-45 19H192q-26 0-45-19t-19-45V320q0-26 19-45t45-19h1408q26 0 45 19t19 45z"></path></symbol>
<symbol id="fa-volume-off" viewBox="0 0 1792 1792"><title>Volume off</title><path d="M1280 352v1088q0 26-19 45t-45 19-45-19l-333-333H576q-26 0-45-19t-19-45V704q0-26 19-45t45-19h262l333-333q19-19 45-19t45 19 19 45z"></path></symbol> <symbol id="fa-volume-off" viewBox="0 0 1792 1792"><title>Volume off</title><path d="M1280 352v1088q0 26-19 45t-45 19-45-19l-333-333H576q-26 0-45-19t-19-45V704q0-26 19-45t45-19h262l333-333q19-19 45-19t45 19 19 45z"></path></symbol>
<symbol id="fa-ban" viewBox="0 0 1792 1792"><title>Ban</title><path d="M1440 893q0-161-87-295l-754 753q137 89 297 89 111 0 211.5-43.5T1281 1280t116-174.5 43-212.5zm-999 299l755-754q-135-91-300-91-148 0-273 73T425 619t-73 274q0 162 89 299zm1223-299q0 157-61 300t-163.5 246-245 164-298.5 61-298.5-61-245-164T189 1193t-61-300 61-299.5T352.5 348t245-164T896 123t298.5 61 245 164T1603 593.5t61 299.5z"></path></symbol> <symbol id="fa-ban" viewBox="0 0 1792 1792"><title>Ban</title><path d="M1440 893q0-161-87-295l-754 753q137 89 297 89 111 0 211.5-43.5T1281 1280t116-174.5 43-212.5zm-999 299l755-754q-135-91-300-91-148 0-273 73T425 619t-73 274q0 162 89 299zm1223-299q0 157-61 300t-163.5 246-245 164-298.5 61-298.5-61-245-164T189 1193t-61-300 61-299.5T352.5 348t245-164T896 123t298.5 61 245 164T1603 593.5t61 299.5z"></path></symbol>
<symbol id="fa-camera" viewBox="0 0 2048 1792"><title>Camera</title><path d="M1024 672q119 0 203.5 84.5T1312 960t-84.5 203.5T1024 1248t-203.5-84.5T736 960t84.5-203.5T1024 672zm704-416q106 0 181 75t75 181v896q0 106-75 181t-181 75H320q-106 0-181-75t-75-181V512q0-106 75-181t181-75h224l51-136q19-49 69.5-84.5T768 0h512q53 0 103.5 35.5T1453 120l51 136h224zm-704 1152q185 0 316.5-131.5T1472 960t-131.5-316.5T1024 512 707.5 643.5 576 960t131.5 316.5T1024 1408z"></path></symbol> <symbol id="fa-camera" viewBox="0 0 2048 1792"><title>Add media</title><path d="M1024 672q119 0 203.5 84.5T1312 960t-84.5 203.5T1024 1248t-203.5-84.5T736 960t84.5-203.5T1024 672zm704-416q106 0 181 75t75 181v896q0 106-75 181t-181 75H320q-106 0-181-75t-75-181V512q0-106 75-181t181-75h224l51-136q19-49 69.5-84.5T768 0h512q53 0 103.5 35.5T1453 120l51 136h224zm-704 1152q185 0 316.5-131.5T1472 960t-131.5-316.5T1024 512 707.5 643.5 576 960t131.5 316.5T1024 1408z"></path></symbol>
<symbol id="fa-smile" viewBox="0 0 1792 1792"><title>Smile</title><path d="M1262 1075q-37 121-138 195t-228 74-228-74-138-195q-8-25 4-48.5t38-31.5q25-8 48.5 4t31.5 38q25 80 92.5 129.5T896 1216t151.5-49.5T1140 1037q8-26 32-38t49-4 37 31.5 4 48.5zM768 640q0 53-37.5 90.5T640 768t-90.5-37.5T512 640t37.5-90.5T640 512t90.5 37.5T768 640zm512 0q0 53-37.5 90.5T1152 768t-90.5-37.5T1024 640t37.5-90.5T1152 512t90.5 37.5T1280 640zm256 256q0-130-51-248.5t-136.5-204-204-136.5T896 256t-248.5 51-204 136.5-136.5 204T256 896t51 248.5 136.5 204 204 136.5 248.5 51 248.5-51 204-136.5 136.5-204 51-248.5zm128 0q0 209-103 385.5T1281.5 1561 896 1664t-385.5-103T231 1281.5 128 896t103-385.5T510.5 231 896 128t385.5 103T1561 510.5 1664 896z"></path></symbol> <symbol id="fa-smile" viewBox="0 0 1792 1792"><title>Custom emoji</title><path d="M1262 1075q-37 121-138 195t-228 74-228-74-138-195q-8-25 4-48.5t38-31.5q25-8 48.5 4t31.5 38q25 80 92.5 129.5T896 1216t151.5-49.5T1140 1037q8-26 32-38t49-4 37 31.5 4 48.5zM768 640q0 53-37.5 90.5T640 768t-90.5-37.5T512 640t37.5-90.5T640 512t90.5 37.5T768 640zm512 0q0 53-37.5 90.5T1152 768t-90.5-37.5T1024 640t37.5-90.5T1152 512t90.5 37.5T1280 640zm256 256q0-130-51-248.5t-136.5-204-204-136.5T896 256t-248.5 51-204 136.5-136.5 204T256 896t51 248.5 136.5 204 204 136.5 248.5 51 248.5-51 204-136.5 136.5-204 51-248.5zm128 0q0 209-103 385.5T1281.5 1561 896 1664t-385.5-103T231 1281.5 128 896t103-385.5T510.5 231 896 128t385.5 103T1561 510.5 1664 896z"></path></symbol>
<symbol id="fa-exclamation-triangle" viewBox="0 0 1792 1792"><title>Warning</title><path d="M1024 1375v-190q0-14-9.5-23.5T992 1152H800q-13 0-22.5 9.5T768 1185v190q0 14 9.5 23.5t22.5 9.5h192q13 0 22.5-9.5t9.5-23.5zm-2-374l18-459q0-12-10-19-13-11-24-11H786q-11 0-24 11-10 7-10 21l17 457q0 10 10 16.5t24 6.5h185q14 0 23.5-6.5t10.5-16.5zm-14-934l768 1408q35 63-2 126-17 29-46.5 46t-63.5 17H128q-34 0-63.5-17T18 1601q-37-63-2-126L784 67q17-31 47-49t65-18 65 18 47 49z"></path></symbol> <symbol id="fa-exclamation-triangle" viewBox="0 0 1792 1792"><title>Content warning</title><path d="M1024 1375v-190q0-14-9.5-23.5T992 1152H800q-13 0-22.5 9.5T768 1185v190q0 14 9.5 23.5t22.5 9.5h192q13 0 22.5-9.5t9.5-23.5zm-2-374l18-459q0-12-10-19-13-11-24-11H786q-11 0-24 11-10 7-10 21l17 457q0 10 10 16.5t24 6.5h185q14 0 23.5-6.5t10.5-16.5zm-14-934l768 1408q35 63-2 126-17 29-46.5 46t-63.5 17H128q-34 0-63.5-17T18 1601q-37-63-2-126L784 67q17-31 47-49t65-18 65 18 47 49z"></path></symbol>
<symbol id="fa-check" viewBox="0 0 1792 1792"><title>Check</title><path d="M1671 566q0 40-28 68l-724 724-136 136q-28 28-68 28t-68-28l-136-136-362-362q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 295 656-657q28-28 68-28t68 28l136 136q28 28 28 68z"></path></symbol>
</svg><!-- end insert svg here --> </svg><!-- end insert svg here -->
</svg> </svg>
<!-- The application will be rendered inside this element, <!-- The application will be rendered inside this element,

View File

@ -0,0 +1,16 @@
import { postPrivacyButton } from '../utils'
import { foobarRole } from '../roles'
fixture`14-compose-post-privacy.js`
.page`http://localhost:4002`
test('Changes post privacy', async t => {
await t.useRole(foobarRole)
.expect(postPrivacyButton.getAttribute('aria-label')).eql('Adjust privacy (currently Public)')
.click(postPrivacyButton)
.click('.post-privacy li:nth-child(2) button')
.expect(postPrivacyButton.getAttribute('aria-label')).eql('Adjust privacy (currently Unlisted)')
.click(postPrivacyButton)
.click('.post-privacy li:nth-child(1) button')
.expect(postPrivacyButton.getAttribute('aria-label')).eql('Adjust privacy (currently Public)')
})

View File

@ -16,6 +16,7 @@ export const composeButton = $('.compose-box-button')
export const composeLengthIndicator = $('.compose-box-length') export const composeLengthIndicator = $('.compose-box-length')
export const emojiButton = $('.compose-box-toolbar button:first-child') export const emojiButton = $('.compose-box-toolbar button:first-child')
export const mediaButton = $('.compose-box-toolbar button:nth-child(2)') export const mediaButton = $('.compose-box-toolbar button:nth-child(2)')
export const postPrivacyButton = $('.compose-box-toolbar button:nth-child(3)')
export const emailInput = $('input#user_email') export const emailInput = $('input#user_email')
export const passwordInput = $('input#user_password') export const passwordInput = $('input#user_password')
export const authorizeInput = $('button[type=submit]:not(.negative)') export const authorizeInput = $('button[type=submit]:not(.negative)')