make replies inline
This commit is contained in:
parent
3b8f551477
commit
5a0c4897b0
|
@ -1,4 +1,4 @@
|
||||||
<div class="{{className}} {{hideAndFadeIn}}">
|
<div class="{{computedClassName}} {{hideAndFadeIn}}">
|
||||||
<ComposeAuthor />
|
<ComposeAuthor />
|
||||||
{{#if contentWarningShown}}
|
{{#if contentWarningShown}}
|
||||||
<div class="compose-content-warning-wrapper"
|
<div class="compose-content-warning-wrapper"
|
||||||
|
@ -13,10 +13,12 @@
|
||||||
<ComposeMedia :realm :media />
|
<ComposeMedia :realm :media />
|
||||||
</div>
|
</div>
|
||||||
<div class="compose-box-button-sentinel {{hideAndFadeIn}}" ref:sentinel></div>
|
<div class="compose-box-button-sentinel {{hideAndFadeIn}}" ref:sentinel></div>
|
||||||
<div class="compose-box-button-wrapper {{hideAndFadeIn}}" >
|
<div class="compose-box-button-wrapper {{realm === 'home' ? 'compose-button-sticky' : ''}} {{hideAndFadeIn}}" >
|
||||||
<ComposeButton :length :overLimit :sticky on:click="onClickPostButton()" />
|
<ComposeButton :length :overLimit :sticky on:click="onClickPostButton()" />
|
||||||
</div>
|
</div>
|
||||||
<div class="compose-box-border-bottom {{hideAndFadeIn}}"></div>
|
{{#if !hideBottomBorder}}
|
||||||
|
<div class="compose-box-border-bottom {{hideAndFadeIn}}"></div>
|
||||||
|
{{/if}}
|
||||||
<style>
|
<style>
|
||||||
.compose-box {
|
.compose-box {
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
@ -35,7 +37,7 @@
|
||||||
max-width: calc(100vw - 40px);
|
max-width: calc(100vw - 40px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.compose-box.dialog-size {
|
.compose-box.slim-size {
|
||||||
width: 540px;
|
width: 540px;
|
||||||
max-width: calc(100vw - 60px);
|
max-width: calc(100vw - 60px);
|
||||||
}
|
}
|
||||||
|
@ -54,11 +56,14 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.compose-box-button-wrapper.compose-button-sticky {
|
||||||
position: -webkit-sticky;
|
position: -webkit-sticky;
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: 10px;
|
top: 10px;
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
pointer-events: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.compose-content-warning-wrapper {
|
.compose-content-warning-wrapper {
|
||||||
|
@ -71,7 +76,7 @@
|
||||||
max-width: calc(100vw - 20px);
|
max-width: calc(100vw - 20px);
|
||||||
width: 580px;
|
width: 580px;
|
||||||
}
|
}
|
||||||
.compose-box.dialog-size {
|
.compose-box.slim-size {
|
||||||
width: 560px;
|
width: 560px;
|
||||||
max-width: calc(100vw - 40px);
|
max-width: calc(100vw - 40px);
|
||||||
}
|
}
|
||||||
|
@ -115,10 +120,6 @@
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.fire('postedStatus')
|
this.fire('postedStatus')
|
||||||
// if this is a reply, go back immediately after it's posted
|
|
||||||
if (realm !== 'home' && realm !== 'dialog') {
|
|
||||||
window.history.back()
|
|
||||||
}
|
|
||||||
}, {init: false})
|
}, {init: false})
|
||||||
},
|
},
|
||||||
ondestroy() {
|
ondestroy() {
|
||||||
|
@ -138,11 +139,11 @@
|
||||||
},
|
},
|
||||||
store: () => store,
|
store: () => store,
|
||||||
computed: {
|
computed: {
|
||||||
className: (overLimit, realm) => {
|
computedClassName: (overLimit, realm, size) => {
|
||||||
return classname(
|
return classname(
|
||||||
'compose-box',
|
'compose-box',
|
||||||
overLimit && 'over-char-limit',
|
overLimit && 'over-char-limit',
|
||||||
realm === 'dialog' && 'dialog-size'
|
size === 'slim' && 'slim-size'
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
hideAndFadeIn: (hidden) => {
|
hideAndFadeIn: (hidden) => {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<ModalDialog :label :shown :closed :title background="var(--main-bg)">
|
<ModalDialog :label :shown :closed :title background="var(--main-bg)">
|
||||||
<ComposeBox realm="dialog" on:postedStatus="onPostedStatus()" />
|
<ComposeBox realm="dialog" size="slim" on:postedStatus="onPostedStatus()" />
|
||||||
</ModalDialog>
|
</ModalDialog>
|
||||||
<script>
|
<script>
|
||||||
import ModalDialog from './ModalDialog.html'
|
import ModalDialog from './ModalDialog.html'
|
||||||
|
|
|
@ -35,7 +35,11 @@
|
||||||
<StatusDetails :originalStatus :originalStatusId />
|
<StatusDetails :originalStatus :originalStatusId />
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<StatusToolbar :originalStatus :originalStatusId :originalAccountId
|
<StatusToolbar :originalStatus :originalStatusId :originalAccountId
|
||||||
:isStatusInOwnThread :uuid :visibility />
|
:isStatusInOwnThread :uuid :visibility :replyShown
|
||||||
|
on:recalculateHeight />
|
||||||
|
{{#if replyShown}}
|
||||||
|
<StatusComposeBox :originalStatusId :uuid on:recalculateHeight />
|
||||||
|
{{/if}}
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -51,9 +55,10 @@
|
||||||
"sidebar spoiler-btn spoiler-btn spoiler-btn"
|
"sidebar spoiler-btn spoiler-btn spoiler-btn"
|
||||||
"sidebar content content content"
|
"sidebar content content content"
|
||||||
"media media media media"
|
"media media media media"
|
||||||
"....... toolbar toolbar toolbar";
|
"....... toolbar toolbar toolbar"
|
||||||
|
"compose compose compose compose";
|
||||||
grid-template-columns: min-content minmax(0, max-content) 1fr min-content;
|
grid-template-columns: min-content minmax(0, max-content) 1fr min-content;
|
||||||
grid-template-rows: repeat(7, max-content);
|
grid-template-rows: repeat(8, max-content);
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-article.status-in-timeline {
|
.status-article.status-in-timeline {
|
||||||
|
@ -74,9 +79,10 @@
|
||||||
"content content"
|
"content content"
|
||||||
"media media"
|
"media media"
|
||||||
"details details"
|
"details details"
|
||||||
"toolbar toolbar";
|
"toolbar toolbar"
|
||||||
|
"compose compose";
|
||||||
grid-template-columns: min-content 1fr;
|
grid-template-columns: min-content 1fr;
|
||||||
grid-template-rows: repeat(6, max-content);
|
grid-template-rows: repeat(7, max-content);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 767px) {
|
@media (max-width: 767px) {
|
||||||
|
@ -100,11 +106,14 @@
|
||||||
import StatusMediaAttachments from './StatusMediaAttachments.html'
|
import StatusMediaAttachments from './StatusMediaAttachments.html'
|
||||||
import StatusContent from './StatusContent.html'
|
import StatusContent from './StatusContent.html'
|
||||||
import StatusSpoiler from './StatusSpoiler.html'
|
import StatusSpoiler from './StatusSpoiler.html'
|
||||||
|
import StatusComposeBox from './StatusComposeBox.html'
|
||||||
import { store } from '../../_store/store'
|
import { store } from '../../_store/store'
|
||||||
import { goto } from 'sapper/runtime.js'
|
import { goto } from 'sapper/runtime.js'
|
||||||
import { registerClickDelegate, unregisterClickDelegate } from '../../_utils/delegate'
|
import { registerClickDelegate, unregisterClickDelegate } from '../../_utils/delegate'
|
||||||
import { classname } from '../../_utils/classname'
|
import { classname } from '../../_utils/classname'
|
||||||
|
|
||||||
|
const INPUT_TAGS = new Set(['a', 'button', 'input', 'textarea'])
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
oncreate() {
|
oncreate() {
|
||||||
let delegateKey = this.get('delegateKey')
|
let delegateKey = this.get('delegateKey')
|
||||||
|
@ -129,7 +138,8 @@
|
||||||
StatusToolbar,
|
StatusToolbar,
|
||||||
StatusMediaAttachments,
|
StatusMediaAttachments,
|
||||||
StatusContent,
|
StatusContent,
|
||||||
StatusSpoiler
|
StatusSpoiler,
|
||||||
|
StatusComposeBox
|
||||||
},
|
},
|
||||||
store: () => store,
|
store: () => store,
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -138,12 +148,9 @@
|
||||||
let { localName, parentElement } = e.target
|
let { localName, parentElement } = e.target
|
||||||
|
|
||||||
if ((type === 'click' || (type === 'keydown' && keyCode === 13)) &&
|
if ((type === 'click' || (type === 'keydown' && keyCode === 13)) &&
|
||||||
localName !== 'a' &&
|
!INPUT_TAGS.has(localName) &&
|
||||||
localName !== 'button' &&
|
!INPUT_TAGS.has(parentElement.localName) &&
|
||||||
parentElement.localName !== 'a' &&
|
!INPUT_TAGS.has(parentElement.parentElement.localName)) {
|
||||||
parentElement.localName !== 'button' &&
|
|
||||||
parentElement.parentElement.localName !== 'a' &&
|
|
||||||
parentElement.parentElement.localName !== 'button') {
|
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
goto(`/statuses/${this.get('originalStatusId')}`)
|
goto(`/statuses/${this.get('originalStatusId')}`)
|
||||||
|
@ -174,6 +181,7 @@
|
||||||
notification.type !== 'mention' && notification.status.id === originalStatusId
|
notification.type !== 'mention' && notification.status.id === originalStatusId
|
||||||
},
|
},
|
||||||
spoilerShown: ($spoilersShown, uuid) => !!$spoilersShown[uuid],
|
spoilerShown: ($spoilersShown, uuid) => !!$spoilersShown[uuid],
|
||||||
|
replyShown: ($repliesShown, uuid) => !!$repliesShown[uuid],
|
||||||
ariaLabel: (originalAccount, originalStatus, visibility) => {
|
ariaLabel: (originalAccount, originalStatus, visibility) => {
|
||||||
return (visibility === 'direct' ? 'Direct message' : 'Status') +
|
return (visibility === 'direct' ? 'Direct message' : 'Status') +
|
||||||
` by ${originalAccount.display_name || originalAccount.username}`
|
` by ${originalAccount.display_name || originalAccount.username}`
|
||||||
|
|
57
routes/_components/status/StatusComposeBox.html
Normal file
57
routes/_components/status/StatusComposeBox.html
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
<div class="status-article-compose-box">
|
||||||
|
<ComposeBox realm="{{originalStatusId}}"
|
||||||
|
size="slim"
|
||||||
|
autoFocus="true"
|
||||||
|
hideBottomBorder="true"
|
||||||
|
on:postedStatus="onPostedStatus()"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<style>
|
||||||
|
.status-article-compose-box {
|
||||||
|
grid-area: compose;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
import ComposeBox from '../../_components/compose/ComposeBox.html'
|
||||||
|
import { store } from '../../_store/store'
|
||||||
|
import { doubleRAF } from '../../_utils/doubleRAF'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
oncreate() {
|
||||||
|
let lastContentWarningShown = false
|
||||||
|
this.observe('composeData', composeData => {
|
||||||
|
doubleRAF(() => {
|
||||||
|
this.fire('recalculateHeight')
|
||||||
|
let contentWarningShown = !!composeData.contentWarningShown
|
||||||
|
if (contentWarningShown !== lastContentWarningShown) {
|
||||||
|
// TODO: this animation lasts 333ms, hence need to recalculate again
|
||||||
|
setTimeout(() => {
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
this.fire('recalculateHeight')
|
||||||
|
})
|
||||||
|
}, 350)
|
||||||
|
}
|
||||||
|
lastContentWarningShown = contentWarningShown
|
||||||
|
})
|
||||||
|
}, {init: false})
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
ComposeBox
|
||||||
|
},
|
||||||
|
store: () => store,
|
||||||
|
computed: {
|
||||||
|
composeData: ($currentComposeData, originalStatusId) => $currentComposeData[originalStatusId] || {},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onPostedStatus() {
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
let uuid = this.get('uuid')
|
||||||
|
let $repliesShown = this.store.get('repliesShown')
|
||||||
|
$repliesShown[uuid] = false
|
||||||
|
this.store.set({'repliesShown': $repliesShown})
|
||||||
|
this.fire('recalculateHeight')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -1,8 +1,9 @@
|
||||||
<div class="status-toolbar {{isStatusInOwnThread ? 'status-in-own-thread' : ''}}">
|
<div class="status-toolbar {{isStatusInOwnThread ? 'status-in-own-thread' : ''}}">
|
||||||
<IconButton
|
<IconButton
|
||||||
label="Reply"
|
label="{{replyLabel}}"
|
||||||
|
pressable="true"
|
||||||
|
pressed="{{replyShown}}"
|
||||||
href="#fa-reply"
|
href="#fa-reply"
|
||||||
disabled="{{disableReply}}"
|
|
||||||
delegateKey="{{replyKey}}"
|
delegateKey="{{replyKey}}"
|
||||||
focusKey="{{replyKey}}"
|
focusKey="{{replyKey}}"
|
||||||
/>
|
/>
|
||||||
|
@ -45,17 +46,16 @@
|
||||||
import { registerClickDelegate, unregisterClickDelegate } from '../../_utils/delegate'
|
import { registerClickDelegate, unregisterClickDelegate } from '../../_utils/delegate'
|
||||||
import { setFavorited } from '../../_actions/favorite'
|
import { setFavorited } from '../../_actions/favorite'
|
||||||
import { setReblogged } from '../../_actions/reblog'
|
import { setReblogged } from '../../_actions/reblog'
|
||||||
import { goto } from 'sapper/runtime.js'
|
|
||||||
import { importDialogs } from '../../_utils/asyncModules'
|
import { importDialogs } from '../../_utils/asyncModules'
|
||||||
import { updateProfileAndRelationship } from '../../_actions/accounts'
|
import { updateProfileAndRelationship } from '../../_actions/accounts'
|
||||||
import { FAVORITE_ANIMATION, REBLOG_ANIMATION } from '../../_static/animations'
|
import { FAVORITE_ANIMATION, REBLOG_ANIMATION } from '../../_static/animations'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
oncreate() {
|
oncreate() {
|
||||||
registerClickDelegate(this.get('favoriteKey'), () => this.onFavoriteClick())
|
registerClickDelegate(this.get('favoriteKey'), (e) => this.onFavoriteClick(e))
|
||||||
registerClickDelegate(this.get('reblogKey'), () => this.onReblogClick())
|
registerClickDelegate(this.get('reblogKey'), (e) => this.onReblogClick(e))
|
||||||
registerClickDelegate(this.get('replyKey'), () => this.onReplyClick())
|
registerClickDelegate(this.get('replyKey'), (e) => this.onReplyClick(e))
|
||||||
registerClickDelegate(this.get('optionsKey'), () => this.onOptionsClick())
|
registerClickDelegate(this.get('optionsKey'), (e) => this.onOptionsClick(e))
|
||||||
},
|
},
|
||||||
ondestroy() {
|
ondestroy() {
|
||||||
unregisterClickDelegate(this.get('favoriteKey'))
|
unregisterClickDelegate(this.get('favoriteKey'))
|
||||||
|
@ -68,23 +68,36 @@
|
||||||
},
|
},
|
||||||
store: () => store,
|
store: () => store,
|
||||||
methods: {
|
methods: {
|
||||||
onFavoriteClick() {
|
onFavoriteClick(e) {
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
let originalStatusId = this.get('originalStatusId')
|
let originalStatusId = this.get('originalStatusId')
|
||||||
let favorited = this.get('favorited')
|
let favorited = this.get('favorited')
|
||||||
/* no await */ setFavorited(originalStatusId, !favorited)
|
/* no await */ setFavorited(originalStatusId, !favorited)
|
||||||
this.set({animateFavorite: !favorited})
|
this.set({animateFavorite: !favorited})
|
||||||
},
|
},
|
||||||
onReblogClick() {
|
onReblogClick(e) {
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
let originalStatusId = this.get('originalStatusId')
|
let originalStatusId = this.get('originalStatusId')
|
||||||
let reblogged = this.get('reblogged')
|
let reblogged = this.get('reblogged')
|
||||||
/* no await */ setReblogged(originalStatusId, !reblogged)
|
/* no await */ setReblogged(originalStatusId, !reblogged)
|
||||||
this.set({animateReblog: !reblogged})
|
this.set({animateReblog: !reblogged})
|
||||||
},
|
},
|
||||||
onReplyClick() {
|
onReplyClick(e) {
|
||||||
let originalStatusId = this.get('originalStatusId')
|
e.preventDefault()
|
||||||
goto(`/statuses/${originalStatusId}/reply`)
|
e.stopPropagation()
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
let uuid = this.get('uuid')
|
||||||
|
let $repliesShown = this.store.get('repliesShown')
|
||||||
|
$repliesShown[uuid] = !$repliesShown[uuid]
|
||||||
|
this.store.set({'repliesShown': $repliesShown})
|
||||||
|
this.fire('recalculateHeight')
|
||||||
|
})
|
||||||
},
|
},
|
||||||
async onOptionsClick() {
|
async onOptionsClick(e) {
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
let originalStatusId = this.get('originalStatusId')
|
let originalStatusId = this.get('originalStatusId')
|
||||||
let originalAccountId = this.get('originalAccountId')
|
let originalAccountId = this.get('originalAccountId')
|
||||||
let updateRelationshipPromise = updateProfileAndRelationship(originalAccountId)
|
let updateRelationshipPromise = updateProfileAndRelationship(originalAccountId)
|
||||||
|
@ -98,6 +111,7 @@
|
||||||
reblogAnimation: REBLOG_ANIMATION
|
reblogAnimation: REBLOG_ANIMATION
|
||||||
}),
|
}),
|
||||||
computed: {
|
computed: {
|
||||||
|
replyLabel: (replyShown) => replyShown ? 'Close reply' : 'Reply',
|
||||||
reblogLabel: (visibility) => {
|
reblogLabel: (visibility) => {
|
||||||
switch (visibility) {
|
switch (visibility) {
|
||||||
case 'private':
|
case 'private':
|
||||||
|
|
|
@ -1,44 +0,0 @@
|
||||||
<DynamicPageBanner title=""/>
|
|
||||||
<div class="reply-container">
|
|
||||||
{{#if status}}
|
|
||||||
<Status index="0"
|
|
||||||
length="1"
|
|
||||||
timelineType="reply"
|
|
||||||
timelineValue="{{params.statusId}}"
|
|
||||||
:status
|
|
||||||
/>
|
|
||||||
<ComposeBox realm="{{params.statusId}}" autoFocus="true" />
|
|
||||||
{{else}}
|
|
||||||
<LoadingPage />
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
|
||||||
<style>
|
|
||||||
.reply-container {
|
|
||||||
position: relative;
|
|
||||||
margin-top: 20px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<script>
|
|
||||||
import { store } from '../../../_store/store.js'
|
|
||||||
import DynamicPageBanner from '../../../_components/DynamicPageBanner.html'
|
|
||||||
import LoadingPage from '../../../_components/LoadingPage.html'
|
|
||||||
import ComposeBox from '../../../_components/compose/ComposeBox.html'
|
|
||||||
import Status from '../../../_components/status/Status.html'
|
|
||||||
import { database } from '../../../_database/database'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
async oncreate() {
|
|
||||||
let statusId = this.get('params').statusId
|
|
||||||
let instanceName = this.store.get('currentInstance')
|
|
||||||
let status = await database.getStatus(instanceName, statusId)
|
|
||||||
this.set({status})
|
|
||||||
},
|
|
||||||
store: () => store,
|
|
||||||
components: {
|
|
||||||
DynamicPageBanner,
|
|
||||||
LoadingPage,
|
|
||||||
ComposeBox,
|
|
||||||
Status
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
|
@ -33,6 +33,7 @@ export const store = new PinaforeStore({
|
||||||
instanceThemes: {},
|
instanceThemes: {},
|
||||||
spoilersShown: {},
|
spoilersShown: {},
|
||||||
sensitivesShown: {},
|
sensitivesShown: {},
|
||||||
|
repliesShown: {},
|
||||||
autoplayGifs: false,
|
autoplayGifs: false,
|
||||||
markMediaAsSensitive: false,
|
markMediaAsSensitive: false,
|
||||||
reduceMotion: false,
|
reduceMotion: false,
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
<:Head>
|
|
||||||
<title>Pinafore – Reply</title>
|
|
||||||
</:Head>
|
|
||||||
<Layout page='reply' >
|
|
||||||
<LazyPage :pageComponent :params />
|
|
||||||
</Layout>
|
|
||||||
<script>
|
|
||||||
import Layout from '../../_components/Layout.html'
|
|
||||||
import LazyPage from '../../_components/LazyPage.html'
|
|
||||||
import pageComponent from '../../_pages/statuses/[statusId]/reply.html'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
components: {
|
|
||||||
Layout,
|
|
||||||
LazyPage
|
|
||||||
},
|
|
||||||
data: () => ({
|
|
||||||
pageComponent
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</script>
|
|
|
@ -1,6 +1,6 @@
|
||||||
import {
|
import {
|
||||||
getNthStatus, scrollToStatus, closeDialogButton, modalDialogContents, getActiveElementClass, goBack, getUrl,
|
getNthStatus, scrollToStatus, closeDialogButton, modalDialogContents, getActiveElementClass, goBack, getUrl,
|
||||||
goBackButton, getActiveElementInnerText, getNthReplyButton, getActiveElementAriaLabel, getActiveElementInsideNthStatus
|
goBackButton, getActiveElementInnerText, getNthReplyButton, getActiveElementInsideNthStatus
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
import { foobarRole } from '../roles'
|
import { foobarRole } from '../roles'
|
||||||
|
|
||||||
|
@ -81,12 +81,5 @@ test('thread preserves focus', async t => {
|
||||||
test('reply preserves focus and moves focus to the text input', async t => {
|
test('reply preserves focus and moves focus to the text input', async t => {
|
||||||
await t.useRole(foobarRole)
|
await t.useRole(foobarRole)
|
||||||
.click(getNthReplyButton(1))
|
.click(getNthReplyButton(1))
|
||||||
.expect(getUrl()).contains('/reply')
|
|
||||||
.expect(getActiveElementClass()).contains('compose-box-input')
|
.expect(getActiveElementClass()).contains('compose-box-input')
|
||||||
.click(goBackButton)
|
|
||||||
.expect(getUrl()).eql('http://localhost:4002/')
|
|
||||||
.expect(getNthStatus(0).exists).ok()
|
|
||||||
.expect(getActiveElementClass()).contains('icon-button')
|
|
||||||
.expect(getActiveElementAriaLabel()).eql('Reply')
|
|
||||||
.expect(getActiveElementInsideNthStatus()).eql('1')
|
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import {
|
import {
|
||||||
composeInput, getNthReplyButton,
|
composeInput,
|
||||||
getNthStatus, getUrl, goBack
|
getNthComposeReplyInput, getNthReplyButton,
|
||||||
|
getNthStatus, getUrl, goBack, homeNavButton, notificationsNavButton
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
import { foobarRole } from '../roles'
|
import { foobarRole } from '../roles'
|
||||||
|
|
||||||
|
@ -10,34 +11,26 @@ fixture`017-compose-reply.js`
|
||||||
test('account handle populated correctly for replies', async t => {
|
test('account handle populated correctly for replies', async t => {
|
||||||
await t.useRole(foobarRole)
|
await t.useRole(foobarRole)
|
||||||
.click(getNthReplyButton(0))
|
.click(getNthReplyButton(0))
|
||||||
.expect(getUrl()).contains('/statuses')
|
.expect(getNthComposeReplyInput(0).value).eql('@quux ')
|
||||||
.expect(composeInput.value).eql('@quux ')
|
.typeText(getNthComposeReplyInput(0), 'hello quux', {paste: true})
|
||||||
.typeText(composeInput, 'hello quux', {paste: true})
|
.expect(getNthComposeReplyInput(0).value).eql('@quux hello quux')
|
||||||
.expect(composeInput.value).eql('@quux hello quux')
|
.click(notificationsNavButton)
|
||||||
await goBack()
|
.expect(getUrl()).contains('/notifications')
|
||||||
await t.click(getNthReplyButton(0))
|
.click(homeNavButton)
|
||||||
.expect(getUrl()).contains('/statuses')
|
.expect(getUrl()).notContains('/notifications')
|
||||||
.expect(composeInput.value).eql('@quux hello quux')
|
.expect(getNthComposeReplyInput(0).value).eql('@quux hello quux')
|
||||||
await goBack()
|
|
||||||
await t.expect(getUrl()).eql('http://localhost:4002/')
|
|
||||||
.expect(composeInput.value).eql('')
|
.expect(composeInput.value).eql('')
|
||||||
await t.hover(getNthStatus(2))
|
.hover(getNthStatus(2))
|
||||||
.hover(getNthStatus(4))
|
.hover(getNthStatus(4))
|
||||||
.click(getNthReplyButton(4))
|
.click(getNthReplyButton(4))
|
||||||
.expect(getUrl()).contains('/statuses')
|
.expect(getNthComposeReplyInput(4).value).eql('')
|
||||||
.expect(composeInput.value).eql('')
|
|
||||||
await goBack()
|
|
||||||
await t.expect(getUrl()).eql('http://localhost:4002/')
|
|
||||||
.expect(composeInput.value).eql('')
|
|
||||||
})
|
})
|
||||||
|
|
||||||
test('replying to posts with mentions', async t => {
|
test('replying to posts with mentions', async t => {
|
||||||
await t.useRole(foobarRole)
|
await t.useRole(foobarRole)
|
||||||
.click(getNthReplyButton(1))
|
.click(getNthReplyButton(1))
|
||||||
.expect(getUrl()).contains('/statuses')
|
.expect(getNthComposeReplyInput(1).value).eql('@admin ')
|
||||||
.expect(composeInput.value).eql('@admin ')
|
|
||||||
.navigateTo('/accounts/4')
|
.navigateTo('/accounts/4')
|
||||||
.click(getNthReplyButton(0))
|
.click(getNthReplyButton(0))
|
||||||
.expect(getUrl()).contains('/statuses')
|
.expect(getNthComposeReplyInput(0).value).eql('@ExternalLinks @admin @quux ')
|
||||||
.expect(composeInput.value).eql('@ExternalLinks @admin @quux ')
|
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { foobarRole } from '../roles'
|
import { foobarRole } from '../roles'
|
||||||
import {
|
import {
|
||||||
composeInput, getNthReplyButton, getNthStatus, getUrl, homeNavButton, notificationsNavButton,
|
composeInput, getNthComposeReplyButton, getNthComposeReplyInput, getNthReplyButton, getNthStatus, getUrl,
|
||||||
|
homeNavButton, notificationsNavButton,
|
||||||
postStatusButton
|
postStatusButton
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
|
|
||||||
|
@ -27,10 +28,9 @@ test('statuses in threads show up in right order', async t => {
|
||||||
.click(getNthStatus(2))
|
.click(getNthStatus(2))
|
||||||
.expect(getUrl()).contains('/statuses')
|
.expect(getUrl()).contains('/statuses')
|
||||||
.click(getNthReplyButton(3))
|
.click(getNthReplyButton(3))
|
||||||
.expect(getUrl()).contains('/reply')
|
.typeText(getNthComposeReplyInput(3), 'my reply!', {paste: true})
|
||||||
.typeText(composeInput, 'my reply!', {paste: true})
|
.click(getNthComposeReplyButton(3))
|
||||||
.click(postStatusButton)
|
.expect(getNthComposeReplyInput(3).exists).notOk()
|
||||||
.expect(getUrl()).match(/statuses\/[^/]+$/)
|
|
||||||
.expect(getNthStatus(5).innerText).contains('@baz my reply!')
|
.expect(getNthStatus(5).innerText).contains('@baz my reply!')
|
||||||
.navigateTo('/accounts/5')
|
.navigateTo('/accounts/5')
|
||||||
.click(getNthStatus(2))
|
.click(getNthStatus(2))
|
||||||
|
|
|
@ -96,6 +96,14 @@ export const uploadKittenImage = i => (exec(() => {
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
export function getNthComposeReplyInput (n) {
|
||||||
|
return getNthStatus(n).find('.compose-box-input')
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getNthComposeReplyButton (n) {
|
||||||
|
return getNthStatus(n).find('.compose-box-button')
|
||||||
|
}
|
||||||
|
|
||||||
export function getNthAutosuggestionResult (n) {
|
export function getNthAutosuggestionResult (n) {
|
||||||
return $(`.compose-autosuggest-list-item:nth-child(${n}) button`)
|
return $(`.compose-autosuggest-list-item:nth-child(${n}) button`)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue