add floating compose button

This commit is contained in:
Nolan Lawson 2018-03-27 00:02:55 -07:00
parent 62c82a05c0
commit 58b700788c
11 changed files with 195 additions and 49 deletions

View File

@ -31,5 +31,6 @@ module.exports = [
{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'},
{id: 'fa-trash', src: 'node_modules/font-awesome-svg-png/white/svg/trash-o.svg', title: 'Delete'},
{id: 'fa-hourglass', src: 'node_modules/font-awesome-svg-png/white/svg/hourglass.svg', title: 'Follow requested'}
{id: 'fa-hourglass', src: 'node_modules/font-awesome-svg-png/white/svg/hourglass.svg', title: 'Follow requested'},
{id: 'fa-pencil', src: 'node_modules/font-awesome-svg-png/white/svg/pencil.svg', title: 'Compose'}
]

View File

@ -1,4 +1,4 @@
<div class="compose-box {{overLimit ? 'over-char-limit' : ''}}">
<div class="compose-box {{overLimit ? 'over-char-limit' : ''}} {{realm === 'dialog' ? 'dialog-size' : '' }}">
<ComposeAuthor />
{{#if contentWarningShown}}
<div class="compose-content-warning-wrapper"
@ -11,12 +11,16 @@
<ComposeToolbar :realm :postPrivacy :media :contentWarningShown :text />
<ComposeLengthIndicator :length :overLimit />
<ComposeMedia :realm :media />
<ComposeButton :length :overLimit on:click="onClickPostButton()" />
</div>
<div class="compose-box-button-sentinel" ref:sentinel></div>
<div class="compose-box-button-wrapper" >
<ComposeButton :length :overLimit :sticky on:click="onClickPostButton()" />
</div>
<div class="compose-box-border-bottom"></div>
<style>
.compose-box {
border-radius: 4px;
padding: 20px;
padding: 20px 20px 0 20px;
display: grid;
align-items: flex-start;
grid-template-areas:
@ -25,24 +29,50 @@
"avatar input input input"
"avatar gauge gauge gauge"
"avatar toolbar toolbar length"
"avatar media media media"
"avatar button button button";
"avatar media media media";
grid-template-columns: min-content minmax(0, max-content) 1fr 1fr;
border-bottom: 1px solid var(--main-border);
width: 560px;
max-width: calc(100vw - 40px);
}
.compose-box.dialog-size {
width: 540px;
max-width: calc(100vw - 80px);
}
.compose-box-border-bottom {
height: 1px;
background: var(--main-border);
width: 100%;
}
.compose-box-button-wrapper {
width: 100%;
display: flex;
justify-content: flex-end;
position: -webkit-sticky;
position: sticky;
top: 10px;
z-index: 10;
}
.compose-content-warning-wrapper {
grid-area: cw;
}
@media (max-width: 767px) {
.compose-box {
padding: 10px 10px;
padding: 10px 10px 0 10px;
max-width: calc(100vw - 20px);
width: 580px;
}
.compose-box.dialog-size {
width: 560px;
max-width: calc(100vw - 40px);
}
.compose-box-button-wrapper {
top: 5px;
}
}
</style>
<script>
@ -59,20 +89,35 @@
import { store } from '../../_store/store'
import { slide } from 'svelte-transitions'
import { postStatus, insertHandleForReply } from '../../_actions/compose'
import { importDialogs } from '../../_utils/asyncModules'
export default {
oncreate() {
let realm = this.get('realm')
if (realm !== 'home') {
if (realm === 'home') {
this.__stickyObserver = new IntersectionObserver(entries => {
this.set({sticky: !entries[0].isIntersecting})
})
this.__stickyObserver.observe(this.refs.sentinel)
} else if (realm !== 'dialog') {
// if this is a reply, populate the handle immediately
insertHandleForReply(realm)
}
this.observe('postedStatusForRealm', postedStatusForRealm => {
if (postedStatusForRealm !== realm) {
return
}
this.fire('postedStatus')
// if this is a reply, go back immediately after it's posted
this.observe('postedStatusForRealm', postedStatusForRealm => {
if (postedStatusForRealm === realm) {
window.history.back()
}
}, {init: false})
if (realm !== 'home' && realm !== 'dialog') {
window.history.back()
}
}, {init: false})
},
ondestroy() {
if (this.__stickyObserver) {
this.__stickyObserver.disconnect()
}
},
components: {
@ -107,23 +152,32 @@
slide
},
methods: {
onClickPostButton() {
let text = this.get('text')
let media = this.get('media')
let postPrivacyKey = this.get('postPrivacyKey')
let contentWarning = this.get('contentWarning')
let sensitive = media.length && !!contentWarning
let realm = this.get('realm')
let mediaIds = media.map(_ => _.data.id)
let inReplyTo = realm === 'home' ? null : realm
let overLimit = this.get('overLimit')
async onClickPostButton() {
if (this.get('sticky')) {
// when the button is sticky, we're scrolled down the home timeline,
// so we should launch a new compose dialog
let dialogs = await importDialogs()
dialogs.showComposeDialog()
} else {
// else we're actually posting a new toot
let text = this.get('text')
let media = this.get('media')
let postPrivacyKey = this.get('postPrivacyKey')
let contentWarning = this.get('contentWarning')
let sensitive = media.length && !!contentWarning
let realm = this.get('realm')
let mediaIds = media.map(_ => _.data.id)
let inReplyTo = (realm === 'home' || realm === 'dialog') ? null : realm
let overLimit = this.get('overLimit')
if (!text || overLimit) {
return // do nothing if invalid
if (!text || overLimit) {
return // do nothing if invalid
}
/* no await */
postStatus(realm, text, inReplyTo, mediaIds,
sensitive, contentWarning, postPrivacyKey)
}
/* no await */ postStatus(realm, text, inReplyTo, mediaIds,
sensitive, contentWarning, postPrivacyKey)
}
}
}

View File

@ -1,26 +1,40 @@
<button class="primary compose-box-button"
:disabled
on:click>
<span class="{{$postingStatus ? 'hidden' : ''}}">
Toot!
</span>
<div class="compose-box-button-spinner {{$postingStatus ? 'spin' : 'hidden'}}"
aria-hidden="true">
<svg class="compose-box-button-spinner-svg">
<use xlink:href="#fa-spinner" />
</svg>
</div>
</button>
<div class="compose-box-button-halo frosted-glass">
<button class="primary compose-box-button"
:disabled
aria-label="{{sticky ? 'Compose' : 'Toot!'}}"
on:click>
<span class="{{$postingStatus || sticky ? 'hidden' : ''}}">
Toot!
</span>
<div class="compose-box-button-spinner {{$postingStatus ? 'spin' : 'hidden'}}"
aria-hidden="true">
<svg class="compose-box-button-svg">
<use xlink:href="#fa-spinner" />
</svg>
</div>
<div class="compose-box-button-compose {{sticky ? '' : 'hidden'}}"
aria-hidden="true">
<svg class="compose-box-button-svg">
<use xlink:href="#fa-pencil" />
</svg>
</div>
</button>
</div>
<style>
.compose-box-button-halo {
border-radius: 2px;
margin: 5px 15px 15px 5px;
background: var(--compose-button-halo);
}
.compose-box-button {
grid-area: button;
justify-self: right;
text-transform: uppercase;
margin-top: 10px;
position: relative;
margin: 5px;
}
.compose-box-button-spinner {
pointer-events: none;
.compose-box-button-spinner, .compose-box-button-compose {
position: absolute;
display: flex;
justify-content: center;
@ -31,11 +45,20 @@
left: 0;
right: 0;
}
.compose-box-button-spinner-svg {
.compose-box-button-svg {
width: 24px;
height: 24px;
fill: var(--button-primary-text);
}
@media (max-width: 767px) {
.compose-box-button-halo {
margin: 5px;
}
.compose-box-button {
margin: 5px;
}
}
</style>
<script>
import { store } from '../../_store/store'

View File

@ -0,0 +1,22 @@
<ModalDialog :label :shown :closed :title background="var(--main-bg)">
<ComposeBox realm="dialog" on:postedStatus="onPostedStatus()" />
</ModalDialog>
<script>
import ModalDialog from './ModalDialog.html'
import ComposeBox from '../compose/ComposeBox.html'
export default {
components: {
ModalDialog,
ComposeBox
},
methods: {
async show() {
this.set({shown: true})
},
onPostedStatus() {
this.set({closed: true})
}
}
}
</script>

View File

@ -4,7 +4,7 @@
></div>
<div class="modal-dialog-contents {{fadedIn ? '' : 'hidden'}} {{muted ? 'muted-style' : ''}}"
role="dialog"
aria-label="{{label}}"
aria-label="{{label || ''}}"
ref:node
>
<div class="modal-dialog-document" role="document" style="background: {{background || '#000'}};">
@ -41,7 +41,10 @@
position: fixed;
top: 50%;
left: 50%;
-webkit-filter: blur(0);
will-change: transform;
transform: translate(-50%, -50%);
-webkit-font-smoothing: antialiased; /* fix for transform:translate causing blurry text in Chrome/Safari */
padding: 0;
border: 1px solid var(--main-border);
border-radius: 2px;

View File

@ -4,3 +4,4 @@ export * from './showVideoDialog'
export * from './showEmojiDialog'
export * from './showPostPrivacyDialog'
export * from './showStatusOptionsDialog'
export * from './showComposeDialog'

View File

@ -0,0 +1,11 @@
import ComposeDialog from './ComposeDialog.html'
export function showComposeDialog () {
let dialog = new ComposeDialog({
target: document.getElementById('modal-dialog'),
data: {
label: 'Compose dialog'
}
})
dialog.show()
}

View File

@ -78,4 +78,6 @@
--compose-autosuggest-item-hover: $compose-background;
--compose-autosuggest-item-active: darken($compose-background, 5%);
--compose-autosuggest-outline: lighten($focus-outline, 5%);
--compose-button-halo: rgba(255, 255, 255, 0.2);
}

View File

@ -16,9 +16,9 @@
<style>
/* auto-generated w/ build-sass.js */
body{--button-primary-bg:#6081e6;--button-primary-text:#fff;--button-primary-border:#132c76;--button-primary-bg-active:#456ce2;--button-primary-bg-hover:#6988e7;--button-bg:#e6e6e6;--button-text:#333;--button-border:#a7a7a7;--button-bg-active:#bfbfbf;--button-bg-hover:#f2f2f2;--input-border:#dadada;--anchor-text:#4169e1;--main-bg:#fff;--body-bg:#e8edfb;--body-text-color:#333;--main-border:#dadada;--svg-fill:#4169e1;--form-bg:#f7f7f7;--form-border:#c1c1c1;--nav-bg:#4169e1;--nav-border:#214cce;--nav-a-border:#4169e1;--nav-a-selected-border:#fff;--nav-a-selected-bg:#6d8ce8;--nav-svg-fill:#fff;--nav-text-color:#fff;--nav-a-selected-border-hover:#fff;--nav-a-selected-bg-hover:#839deb;--nav-a-bg-hover:#577ae4;--nav-a-border-hover:#4169e1;--nav-svg-fill-hover:#fff;--nav-text-color-hover:#fff;--action-button-fill-color:#90a8ee;--action-button-fill-color-hover:#a2b6f0;--action-button-fill-color-active:#577ae4;--action-button-fill-color-pressed:#2351dc;--action-button-fill-color-pressed-hover:#3862e0;--action-button-fill-color-pressed-active:#1d44b8;--settings-list-item-bg:#fff;--settings-list-item-text:#4169e1;--settings-list-item-text-hover:#4169e1;--settings-list-item-border:#dadada;--settings-list-item-bg-active:#e6e6e6;--settings-list-item-bg-hover:#fafafa;--toast-bg:#333;--toast-border:#fafafa;--toast-text:#fff;--mask-bg:#333;--mask-svg-fill:#fff;--mask-opaque-bg:rgba(51,51,51,0.8);--loading-bg:#ededed;--deemphasized-text-color:#666;--focus-outline:#c5d1f6;--very-deemphasized-link-color:rgba(65,105,225,0.6);--very-deemphasized-text-color:rgba(102,102,102,0.6);--status-direct-background:#d2dcf8;--main-theme-color:#4169e1;--warning-color:#e01f19;--alt-input-bg:rgba(255,255,255,0.7);--muted-modal-bg:transparent;--muted-modal-focus:#999;--muted-modal-hover:rgba(255,255,255,0.2);--compose-autosuggest-item-hover:#ced8f7;--compose-autosuggest-item-active:#b8c7f4;--compose-autosuggest-outline:#dbe3f9}
body{--button-primary-bg:#6081e6;--button-primary-text:#fff;--button-primary-border:#132c76;--button-primary-bg-active:#456ce2;--button-primary-bg-hover:#6988e7;--button-bg:#e6e6e6;--button-text:#333;--button-border:#a7a7a7;--button-bg-active:#bfbfbf;--button-bg-hover:#f2f2f2;--input-border:#dadada;--anchor-text:#4169e1;--main-bg:#fff;--body-bg:#e8edfb;--body-text-color:#333;--main-border:#dadada;--svg-fill:#4169e1;--form-bg:#f7f7f7;--form-border:#c1c1c1;--nav-bg:#4169e1;--nav-border:#214cce;--nav-a-border:#4169e1;--nav-a-selected-border:#fff;--nav-a-selected-bg:#6d8ce8;--nav-svg-fill:#fff;--nav-text-color:#fff;--nav-a-selected-border-hover:#fff;--nav-a-selected-bg-hover:#839deb;--nav-a-bg-hover:#577ae4;--nav-a-border-hover:#4169e1;--nav-svg-fill-hover:#fff;--nav-text-color-hover:#fff;--action-button-fill-color:#90a8ee;--action-button-fill-color-hover:#a2b6f0;--action-button-fill-color-active:#577ae4;--action-button-fill-color-pressed:#2351dc;--action-button-fill-color-pressed-hover:#3862e0;--action-button-fill-color-pressed-active:#1d44b8;--settings-list-item-bg:#fff;--settings-list-item-text:#4169e1;--settings-list-item-text-hover:#4169e1;--settings-list-item-border:#dadada;--settings-list-item-bg-active:#e6e6e6;--settings-list-item-bg-hover:#fafafa;--toast-bg:#333;--toast-border:#fafafa;--toast-text:#fff;--mask-bg:#333;--mask-svg-fill:#fff;--mask-opaque-bg:rgba(51,51,51,0.8);--loading-bg:#ededed;--deemphasized-text-color:#666;--focus-outline:#c5d1f6;--very-deemphasized-link-color:rgba(65,105,225,0.6);--very-deemphasized-text-color:rgba(102,102,102,0.6);--status-direct-background:#d2dcf8;--main-theme-color:#4169e1;--warning-color:#e01f19;--alt-input-bg:rgba(255,255,255,0.7);--muted-modal-bg:transparent;--muted-modal-focus:#999;--muted-modal-hover:rgba(255,255,255,0.2);--compose-autosuggest-item-hover:#ced8f7;--compose-autosuggest-item-active:#b8c7f4;--compose-autosuggest-outline:#dbe3f9;--compose-button-halo:rgba(255,255,255,0.2)}
body{margin:0;font-family:system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue;font-size:14px;line-height:1.4;color:var(--body-text-color);background:var(--body-bg);position:fixed;left:0;right:0;bottom:0;top:0}.container{overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;will-change:transform;position:absolute;top:72px;left:0;right:0;bottom:0}@media (max-width: 767px){.container{top:62px}}main{position:relative;width:602px;max-width:100vw;padding:0;box-sizing:border-box;margin:30px auto 15px;background:var(--main-bg);border:1px solid var(--main-border);border-radius:1px;min-height:70vh}@media (max-width: 767px){main{margin:5px auto 15px}}footer{width:602px;max-width:100vw;box-sizing:border-box;margin:20px auto;border-radius:1px;background:var(--main-bg);font-size:0.9em;padding:20px;border:1px solid var(--main-border)}h1,h2,h3,h4,h5,h6{margin:0 0 0.5em 0;font-weight:400;line-height:1.2}h1{font-size:2em}a{color:var(--anchor-text);text-decoration:none}a:visited{color:var(--anchor-text)}a:hover{text-decoration:underline}input{border:1px solid var(--input-border);padding:5px;box-sizing:border-box}button,.button{font-size:1.2em;background:var(--button-bg);border-radius:2px;padding:10px 15px;border:1px solid var(--button-border);cursor:pointer;color:var(--button-text)}button:hover,.button:hover{background:var(--button-bg-hover);text-decoration:none}button:active,.button:active{background:var(--button-bg-active)}button[disabled],.button[disabled]{opacity:0.35;pointer-events:none;cursor:not-allowed}button.primary,.button.primary{border:1px solid var(--button-primary-border);background:var(--button-primary-bg);color:var(--button-primary-text)}button.primary:hover,.button.primary:hover{background:var(--button-primary-bg-hover)}button.primary:active,.button.primary:active{background:var(--button-primary-bg-active)}p,label,input{font-size:1.3em}ul,li,p{padding:0;margin:0}.hidden{opacity:0}*:focus{outline:2px solid var(--focus-outline)}button::-moz-focus-inner{border:0}input:required,input:invalid{box-shadow:none}textarea{font-family:inherit;font-size:inherit;box-sizing:border-box}@keyframes spin{0%{transform:rotate(0deg)}50%{transform:rotate(180deg)}100%{transform:rotate(360deg)}}.spin{animation:spin 2s infinite linear}.ellipsis::after{content:"\2026"}
body.offline,body.theme-hotpants.offline,body.theme-majesty.offline,body.theme-oaken.offline,body.theme-scarlet.offline,body.theme-seafoam.offline,body.theme-gecko.offline{--button-primary-bg:#ababab;--button-primary-text:#fff;--button-primary-border:#4d4d4d;--button-primary-bg-active:#9c9c9c;--button-primary-bg-hover:#b0b0b0;--button-bg:#e6e6e6;--button-text:#333;--button-border:#a7a7a7;--button-bg-active:#bfbfbf;--button-bg-hover:#f2f2f2;--input-border:#dadada;--anchor-text:#999;--main-bg:#fff;--body-bg:#fafafa;--body-text-color:#333;--main-border:#dadada;--svg-fill:#999;--form-bg:#f7f7f7;--form-border:#c1c1c1;--nav-bg:#999;--nav-border:gray;--nav-a-border:#999;--nav-a-selected-border:#fff;--nav-a-selected-bg:#b3b3b3;--nav-svg-fill:#fff;--nav-text-color:#fff;--nav-a-selected-border-hover:#fff;--nav-a-selected-bg-hover:#bfbfbf;--nav-a-bg-hover:#a6a6a6;--nav-a-border-hover:#999;--nav-svg-fill-hover:#fff;--nav-text-color-hover:#fff;--action-button-fill-color:#c7c7c7;--action-button-fill-color-hover:#d1d1d1;--action-button-fill-color-active:#a6a6a6;--action-button-fill-color-pressed:#878787;--action-button-fill-color-pressed-hover:#949494;--action-button-fill-color-pressed-active:#737373;--settings-list-item-bg:#fff;--settings-list-item-text:#999;--settings-list-item-text-hover:#999;--settings-list-item-border:#dadada;--settings-list-item-bg-active:#e6e6e6;--settings-list-item-bg-hover:#fafafa;--toast-bg:#333;--toast-border:#fafafa;--toast-text:#fff;--mask-bg:#333;--mask-svg-fill:#fff;--mask-opaque-bg:rgba(51,51,51,0.8);--loading-bg:#ededed;--deemphasized-text-color:#666;--focus-outline:#bfbfbf;--very-deemphasized-link-color:rgba(153,153,153,0.6);--very-deemphasized-text-color:rgba(102,102,102,0.6);--status-direct-background:#ededed;--main-theme-color:#999;--warning-color:#e01f19;--alt-input-bg:rgba(255,255,255,0.7);--muted-modal-bg:transparent;--muted-modal-focus:#999;--muted-modal-hover:rgba(255,255,255,0.2);--compose-autosuggest-item-hover:#c4c4c4;--compose-autosuggest-item-active:#b8b8b8;--compose-autosuggest-outline:#ccc}
body.offline,body.theme-hotpants.offline,body.theme-majesty.offline,body.theme-oaken.offline,body.theme-scarlet.offline,body.theme-seafoam.offline,body.theme-gecko.offline{--button-primary-bg:#ababab;--button-primary-text:#fff;--button-primary-border:#4d4d4d;--button-primary-bg-active:#9c9c9c;--button-primary-bg-hover:#b0b0b0;--button-bg:#e6e6e6;--button-text:#333;--button-border:#a7a7a7;--button-bg-active:#bfbfbf;--button-bg-hover:#f2f2f2;--input-border:#dadada;--anchor-text:#999;--main-bg:#fff;--body-bg:#fafafa;--body-text-color:#333;--main-border:#dadada;--svg-fill:#999;--form-bg:#f7f7f7;--form-border:#c1c1c1;--nav-bg:#999;--nav-border:gray;--nav-a-border:#999;--nav-a-selected-border:#fff;--nav-a-selected-bg:#b3b3b3;--nav-svg-fill:#fff;--nav-text-color:#fff;--nav-a-selected-border-hover:#fff;--nav-a-selected-bg-hover:#bfbfbf;--nav-a-bg-hover:#a6a6a6;--nav-a-border-hover:#999;--nav-svg-fill-hover:#fff;--nav-text-color-hover:#fff;--action-button-fill-color:#c7c7c7;--action-button-fill-color-hover:#d1d1d1;--action-button-fill-color-active:#a6a6a6;--action-button-fill-color-pressed:#878787;--action-button-fill-color-pressed-hover:#949494;--action-button-fill-color-pressed-active:#737373;--settings-list-item-bg:#fff;--settings-list-item-text:#999;--settings-list-item-text-hover:#999;--settings-list-item-border:#dadada;--settings-list-item-bg-active:#e6e6e6;--settings-list-item-bg-hover:#fafafa;--toast-bg:#333;--toast-border:#fafafa;--toast-text:#fff;--mask-bg:#333;--mask-svg-fill:#fff;--mask-opaque-bg:rgba(51,51,51,0.8);--loading-bg:#ededed;--deemphasized-text-color:#666;--focus-outline:#bfbfbf;--very-deemphasized-link-color:rgba(153,153,153,0.6);--very-deemphasized-text-color:rgba(102,102,102,0.6);--status-direct-background:#ededed;--main-theme-color:#999;--warning-color:#e01f19;--alt-input-bg:rgba(255,255,255,0.7);--muted-modal-bg:transparent;--muted-modal-focus:#999;--muted-modal-hover:rgba(255,255,255,0.2);--compose-autosuggest-item-hover:#c4c4c4;--compose-autosuggest-item-active:#b8b8b8;--compose-autosuggest-outline:#ccc;--compose-button-halo:rgba(255,255,255,0.2)}
</style>
@ -109,6 +109,7 @@ body.offline,body.theme-hotpants.offline,body.theme-majesty.offline,body.theme-o
<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>
<symbol id="fa-trash" viewBox="0 0 1792 1792"><title>Delete</title><path d="M704 736v576q0 14-9 23t-23 9h-64q-14 0-23-9t-9-23V736q0-14 9-23t23-9h64q14 0 23 9t9 23zm256 0v576q0 14-9 23t-23 9h-64q-14 0-23-9t-9-23V736q0-14 9-23t23-9h64q14 0 23 9t9 23zm256 0v576q0 14-9 23t-23 9h-64q-14 0-23-9t-9-23V736q0-14 9-23t23-9h64q14 0 23 9t9 23zm128 724V512H448v948q0 22 7 40.5t14.5 27 10.5 8.5h832q3 0 10.5-8.5t14.5-27 7-40.5zM672 384h448l-48-117q-7-9-17-11H738q-10 2-17 11zm928 32v64q0 14-9 23t-23 9h-96v948q0 83-47 143.5t-113 60.5H480q-66 0-113-58.5T320 1464V512h-96q-14 0-23-9t-9-23v-64q0-14 9-23t23-9h309l70-167q15-37 54-63t79-26h320q40 0 79 26t54 63l70 167h309q14 0 23 9t9 23z"></path></symbol>
<symbol id="fa-hourglass" viewBox="0 0 1792 1792"><title>Follow requested</title><path d="M1632 1600q14 0 23 9t9 23v128q0 14-9 23t-23 9H160q-14 0-23-9t-9-23v-128q0-14 9-23t23-9h1472zm-1374-64q3-55 16-107t30-95 46-87 53.5-76 64.5-69.5 66-60 70.5-55T671 939t65-43q-43-28-65-43t-66.5-47.5-70.5-55-66-60-64.5-69.5-53.5-76-46-87-30-95-16-107h1276q-3 55-16 107t-30 95-46 87-53.5 76-64.5 69.5-66 60-70.5 55T1121 853t-65 43q43 28 65 43t66.5 47.5 70.5 55 66 60 64.5 69.5 53.5 76 46 87 30 95 16 107H258zM1632 0q14 0 23 9t9 23v128q0 14-9 23t-23 9H160q-14 0-23-9t-9-23V32q0-14 9-23t23-9h1472z"></path></symbol>
<symbol id="fa-pencil" viewBox="0 0 1792 1792"><title>Compose</title><path d="M491 1536l91-91-235-235-91 91v107h128v128h107zm523-928q0-22-22-22-10 0-17 7l-542 542q-7 7-7 17 0 22 22 22 10 0 17-7l542-542q7-7 7-17zm-54-192l416 416-832 832H128v-416zm683 96q0 53-37 90l-166 166-416-416 166-165q36-38 90-38 53 0 91 38l235 234q37 39 37 91z"></path></symbol>
</svg><!-- end insert svg here -->
</svg>
<!-- The application will be rendered inside this element,

View File

@ -0,0 +1,27 @@
import {
composeButton, getNthStatus, scrollToStatus, scrollToTopOfTimeline, modalDialog, sleep, showMoreButton,
scrollContainerToTop
} from '../utils'
import { foobarRole } from '../roles'
fixture`108-compose-dialog.js`
.page`http://localhost:4002`
test('can compose using a dialog', async t => {
await t.useRole(foobarRole)
await scrollToStatus(t, 15)
await t.expect(modalDialog.getAttribute('aria-hidden')).eql('true')
.click(composeButton)
.expect(modalDialog.hasAttribute('aria-hidden')).notOk()
.typeText(modalDialog.find('.compose-box-input'), 'hello from the modal')
.click(modalDialog.find('.compose-box-button-compose'))
.expect(modalDialog.getAttribute('aria-hidden')).eql('true')
await sleep(5000)
await scrollToTopOfTimeline(t)
await t.hover(getNthStatus(0))
await scrollContainerToTop()
await t
.expect(showMoreButton.innerText).contains('Show 1 more')
.click(showMoreButton)
await t.expect(getNthStatus(0).innerText).contains('hello from the modal', {timeout: 20000})
})

View File

@ -6,6 +6,7 @@ const SCROLL_INTERVAL = 1
export const settingsButton = $('nav a[aria-label=Settings]')
export const instanceInput = $('#instanceInput')
export const modalDialog = $('#modal-dialog')
export const modalDialogContents = $('.modal-dialog-contents')
export const closeDialogButton = $('.close-dialog-button')
export const notificationsNavButton = $('nav a[href="/notifications"]')