use standard to lint HTML too (#186)

This commit is contained in:
Nolan Lawson 2018-04-19 21:38:01 -07:00 committed by GitHub
parent ef80919269
commit bfc3c46462
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
70 changed files with 214 additions and 210 deletions

View File

@ -32,6 +32,7 @@ Lint:
Automatically fix most linting issues: Automatically fix most linting issues:
npx standard --fix npx standard --fix
npx standard --fix --plugin html 'routes/**/*.html'
## Testing ## Testing

9
package-lock.json generated
View File

@ -3084,6 +3084,15 @@
} }
} }
}, },
"eslint-plugin-html": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/eslint-plugin-html/-/eslint-plugin-html-4.0.3.tgz",
"integrity": "sha512-ArFnlfQxwYSz/CP0zvk8Cy3MUhcDpT3o6jgO8eKD/b8ezcLVBrgkYzmMv+7S/ya+Yl9pN+Cz2tsgYp/zElkQzA==",
"dev": true,
"requires": {
"htmlparser2": "3.9.2"
}
},
"eslint-plugin-import": { "eslint-plugin-import": {
"version": "2.9.0", "version": "2.9.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.9.0.tgz", "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.9.0.tgz",

View File

@ -3,7 +3,7 @@
"description": "Alternative web client for Mastodon", "description": "Alternative web client for Mastodon",
"version": "0.2.2", "version": "0.2.2",
"scripts": { "scripts": {
"lint": "standard", "lint": "standard && standard --plugin html 'routes/**/*.html'",
"dev": "run-s build-svg build-inline-script serve-dev", "dev": "run-s build-svg build-inline-script serve-dev",
"serve-dev": "run-p --race build-sass-watch serve", "serve-dev": "run-p --race build-sass-watch serve",
"serve": "node server.js", "serve": "node server.js",
@ -83,6 +83,7 @@
"yargs": "11.0.0" "yargs": "11.0.0"
}, },
"devDependencies": { "devDependencies": {
"eslint-plugin-html": "4.0.3",
"now": "11.1.7", "now": "11.1.7",
"standard": "11.0.1", "standard": "11.0.1",
"testcafe": "0.19.1" "testcafe": "0.19.1"
@ -117,7 +118,8 @@
"atob", "atob",
"btoa", "btoa",
"Blob", "Blob",
"Element" "Element",
"Image"
], ],
"ignore": [ "ignore": [
"dist", "dist",

View File

@ -33,7 +33,7 @@
import { toast } from '../_utils/toast' import { toast } from '../_utils/toast'
export default { export default {
async oncreate() { async oncreate () {
let { accountsFetcher } = this.get() let { accountsFetcher } = this.get()
try { try {
// TODO: paginate // TODO: paginate

View File

@ -61,7 +61,7 @@
<script> <script>
export default { export default {
methods: { methods: {
onGoBack(e) { onGoBack (e) {
e.preventDefault() e.preventDefault()
window.history.back() window.history.back()
} }

View File

@ -105,7 +105,7 @@
import { store } from '../_store/store' import { store } from '../_store/store'
export default { export default {
oncreate() { oncreate () {
this.observe('animation', animation => { this.observe('animation', animation => {
let reduceMotion = this.store.get() let reduceMotion = this.store.get()
if (!animation || reduceMotion) { if (!animation || reduceMotion) {

View File

@ -9,19 +9,19 @@
{{/if}} {{/if}}
</div> </div>
<script> <script>
import Nav from './Nav.html'; import Nav from './Nav.html'
import { store } from '../_store/store' import { store } from '../_store/store'
import InformationalFooter from './InformationalFooter.html' import InformationalFooter from './InformationalFooter.html'
// Only focus the `.container` div on first load so it does not intefere // Only focus the `.container` div on first load so it does not intefere
// with other desired behaviours (e.g. you click a toot, you navigate from // with other desired behaviours (e.g. you click a toot, you navigate from
// a timeline view to a thread view, you press the back button, and now // a timeline view to a thread view, you press the back button, and now
// you're still focused on the toot). // you're still focused on the toot).
let firstTime = true let firstTime = true
export default { export default {
components: { components: {
Nav, Nav,
InformationalFooter InformationalFooter
}, },
oncreate () { oncreate () {
@ -31,5 +31,5 @@
} }
}, },
store: () => store store: () => store
} }
</script> </script>

View File

@ -21,11 +21,10 @@
} }
</style> </style>
<script> <script>
import { mark, stop } from '../_utils/marks' import { mark, stop } from '../_utils/marks'
export default { export default {
oncreate() { oncreate () {
mark('LazyImage oncreate()') mark('LazyImage oncreate()')
let img = new Image() let img = new Image()
let { src } = this.get() let { src } = this.get()

View File

@ -11,7 +11,7 @@
let firstTime = true let firstTime = true
export default { export default {
oncreate() { oncreate () {
firstTime = false firstTime = false
requestAnimationFrame(() => { requestAnimationFrame(() => {
requestAnimationFrame(() => { requestAnimationFrame(() => {

View File

@ -21,7 +21,7 @@
const SPINNER_DELAY = 700 const SPINNER_DELAY = 700
export default { export default {
oncreate() { oncreate () {
setTimeout(() => { setTimeout(() => {
this.set({shown: true}) this.set({shown: true})
}, SPINNER_DELAY) }, SPINNER_DELAY)

View File

@ -135,7 +135,7 @@
} }
}, },
methods: { methods: {
onClick(e) { onClick (e) {
let { selected } = this.get() let { selected } = this.get()
if (!selected) { if (!selected) {
return return
@ -146,5 +146,4 @@
} }
} }
} }
</script> </script>

View File

@ -43,7 +43,7 @@
export default { export default {
methods: { methods: {
onMouseOver(mouseOver) { onMouseOver (mouseOver) {
this.set({playing: mouseOver}) this.set({playing: mouseOver})
} }
}, },

View File

@ -27,7 +27,7 @@
import { imgLoadError, mouseover } from '../_utils/events' import { imgLoadError, mouseover } from '../_utils/events'
export default { export default {
methods: { methods: {
onMouseOver(mouseOver) { onMouseOver (mouseOver) {
let { src, staticSrc } = this.get() let { src, staticSrc } = this.get()
this.refs.node.src = mouseOver ? src : staticSrc this.refs.node.src = mouseOver ? src : staticSrc
} }

View File

@ -42,7 +42,7 @@
}, },
computed: { computed: {
hidePage: ($timelineInitialized, $timelinePreinitialized) => !$timelineInitialized && !$timelinePreinitialized, hidePage: ($timelineInitialized, $timelinePreinitialized) => !$timelineInitialized && !$timelinePreinitialized,
hideTimeline: ($timelineInitialized) => !$timelineInitialized, hideTimeline: ($timelineInitialized) => !$timelineInitialized
}, },
store: () => store, store: () => store,
components: { components: {

View File

@ -36,7 +36,7 @@
}, },
computed: { computed: {
hidePage: ($timelineInitialized, $timelinePreinitialized) => !$timelineInitialized && !$timelinePreinitialized, hidePage: ($timelineInitialized, $timelinePreinitialized) => !$timelineInitialized && !$timelinePreinitialized,
hideTimeline: ($timelineInitialized) => !$timelineInitialized, hideTimeline: ($timelineInitialized) => !$timelineInitialized
}, },
store: () => store, store: () => store,
components: { components: {

View File

@ -67,10 +67,10 @@
methods: { methods: {
push, push,
splice, splice,
say(text) { say (text) {
this.push('messages', text) this.push('messages', text)
}, },
onNewToast(text) { onNewToast (text) {
this._queue = this._queue.then(() => { this._queue = this._queue.then(() => {
this.set({ this.set({
'text': text, 'text': text,

View File

@ -73,7 +73,7 @@
IconButton IconButton
}, },
methods: { methods: {
onPinClick(e) { onPinClick (e) {
e.preventDefault() e.preventDefault()
let { currentInstance, pinnedPages } = this.store.get() let { currentInstance, pinnedPages } = this.store.get()
let { href } = this.get() let { href } = this.get()

View File

@ -55,7 +55,7 @@
const EMOJI_SEARCH_REGEX = new RegExp(`(?:\\s|^)(:[^:]{${MIN_PREFIX_LENGTH},})$`) const EMOJI_SEARCH_REGEX = new RegExp(`(?:\\s|^)(:[^:]{${MIN_PREFIX_LENGTH},})$`)
export default { export default {
oncreate() { oncreate () {
// perf improves for input responsiveness // perf improves for input responsiveness
this.observe('composeSelectionStart', () => { this.observe('composeSelectionStart', () => {
scheduleIdleTask(() => { scheduleIdleTask(() => {
@ -94,7 +94,7 @@
composeAutosuggestionSelected: 0, composeAutosuggestionSelected: 0,
composeAutosuggestionSearchText: searchText, composeAutosuggestionSearchText: searchText,
composeAutosuggestionSearchResults: results, composeAutosuggestionSearchResults: results,
composeAutosuggestionType: type, composeAutosuggestionType: type
}) })
}) })
this.observe('shown', shown => { this.observe('shown', shown => {
@ -103,7 +103,7 @@
}, },
methods: { methods: {
once: once, once: once,
onClick(item) { onClick (item) {
this.fire('autosuggestItemSelected') this.fire('autosuggestItemSelected')
let { realm } = this.get() let { realm } = this.get()
let { composeSelectionStart, composeAutosuggestionSearchText } = this.store.get() let { composeSelectionStart, composeAutosuggestionSearchText } = this.store.get()
@ -114,16 +114,15 @@
} else { } else {
/* no await */ insertEmojiAtPosition(realm, item, startIndex, endIndex) /* no await */ insertEmojiAtPosition(realm, item, startIndex, endIndex)
} }
}, },
async searchAccounts(searchText) { async searchAccounts (searchText) {
searchText = searchText.substring(1) searchText = searchText.substring(1)
let { currentInstance } = this.store.get() let { currentInstance } = this.store.get()
let results = await searchAccountsByUsernameInDatabase( let results = await searchAccountsByUsernameInDatabase(
currentInstance, searchText, DATABASE_SEARCH_RESULTS_LIMIT) currentInstance, searchText, DATABASE_SEARCH_RESULTS_LIMIT)
return results.slice(0, SEARCH_RESULTS_LIMIT) return results.slice(0, SEARCH_RESULTS_LIMIT)
}, },
searchEmoji(searchText) { searchEmoji (searchText) {
searchText = searchText.toLowerCase().substring(1) searchText = searchText.toLowerCase().substring(1)
let { currentCustomEmoji } = this.store.get() let { currentCustomEmoji } = this.store.get()
let results = currentCustomEmoji.filter(emoji => emoji.shortcode.toLowerCase().startsWith(searchText)) let results = currentCustomEmoji.filter(emoji => emoji.shortcode.toLowerCase().startsWith(searchText))

View File

@ -117,7 +117,7 @@
import { classname } from '../../_utils/classname' import { classname } from '../../_utils/classname'
export default { export default {
oncreate() { oncreate () {
let { realm } = this.get() let { realm } = this.get()
if (realm === 'home') { if (realm === 'home') {
this.setupStickyObserver() this.setupStickyObserver()
@ -138,7 +138,7 @@
setReplyVisibility(realm, replyVisibility) setReplyVisibility(realm, replyVisibility)
} }
}, },
ondestroy() { ondestroy () {
this.teardownStickyObserver() this.teardownStickyObserver()
}, },
components: { components: {
@ -188,7 +188,7 @@
slide slide
}, },
methods: { methods: {
async onClickPostButton() { async onClickPostButton () {
let { sticky } = this.get() let { sticky } = this.get()
if (sticky) { if (sticky) {
// when the button is sticky, we're scrolled down the home timeline, // when the button is sticky, we're scrolled down the home timeline,
@ -197,10 +197,10 @@
dialogs.showComposeDialog() dialogs.showComposeDialog()
} else { } else {
// else we're actually posting a new toot // else we're actually posting a new toot
this.doPostStatus(); this.doPostStatus()
} }
}, },
doPostStatus() { doPostStatus () {
let { let {
text, text,
media, media,
@ -224,7 +224,7 @@
sensitive, contentWarning, postPrivacyKey, sensitive, contentWarning, postPrivacyKey,
mediaDescriptions, inReplyToUuid) mediaDescriptions, inReplyToUuid)
}, },
setupStickyObserver() { setupStickyObserver () {
this.__stickyObserver = new IntersectionObserver(entries => { this.__stickyObserver = new IntersectionObserver(entries => {
this.set({sticky: !entries[0].isIntersecting}) this.set({sticky: !entries[0].isIntersecting})
}) })
@ -243,7 +243,7 @@
} }
}, {init: false}) }, {init: false})
}, },
teardownStickyObserver() { teardownStickyObserver () {
if (this.__stickyObserver) { if (this.__stickyObserver) {
this.__stickyObserver.disconnect() this.__stickyObserver.disconnect()
} }

View File

@ -19,7 +19,7 @@
import { scheduleIdleTask } from '../../_utils/scheduleIdleTask' import { scheduleIdleTask } from '../../_utils/scheduleIdleTask'
export default { export default {
oncreate() { oncreate () {
this.setupSyncFromStore() this.setupSyncFromStore()
this.setupSyncToStore() this.setupSyncToStore()
}, },
@ -28,12 +28,12 @@
rawText: '' rawText: ''
}), }),
methods: { methods: {
setupSyncFromStore() { setupSyncFromStore () {
this.observe('contentWarning', contentWarning => { this.observe('contentWarning', contentWarning => {
this.set({rawText: contentWarning}) this.set({rawText: contentWarning})
}) })
}, },
setupSyncToStore() { setupSyncToStore () {
const saveText = debounce(() => scheduleIdleTask(() => this.store.save()), 1000) const saveText = debounce(() => scheduleIdleTask(() => this.store.save()), 1000)
this.observe('rawText', rawText => { this.observe('rawText', rawText => {

View File

@ -37,16 +37,16 @@
import { clickSelectedAutosuggestionEmoji } from '../../_actions/emoji' import { clickSelectedAutosuggestionEmoji } from '../../_actions/emoji'
export default { export default {
oncreate() { oncreate () {
this.setupSyncFromStore() this.setupSyncFromStore()
this.setupSyncToStore() this.setupSyncToStore()
this.setupAutosize() this.setupAutosize()
}, },
ondestroy() { ondestroy () {
this.teardownAutosize() this.teardownAutosize()
}, },
methods: { methods: {
setupSyncFromStore() { setupSyncFromStore () {
let textarea = this.refs.textarea let textarea = this.refs.textarea
let firstTime = true let firstTime = true
this.observe('text', text => { this.observe('text', text => {
@ -68,7 +68,7 @@
} }
}) })
}, },
setupSyncToStore() { setupSyncToStore () {
const saveStore = debounce(() => scheduleIdleTask(() => this.store.save()), 1000) const saveStore = debounce(() => scheduleIdleTask(() => this.store.save()), 1000)
this.observe('rawText', rawText => { this.observe('rawText', rawText => {
@ -79,7 +79,7 @@
stop('observe rawText') stop('observe rawText')
}, {init: false}) }, {init: false})
}, },
setupAutosize() { setupAutosize () {
let textarea = this.refs.textarea let textarea = this.refs.textarea
requestAnimationFrame(() => { requestAnimationFrame(() => {
mark('autosize()') mark('autosize()')
@ -87,21 +87,21 @@
stop('autosize()') stop('autosize()')
}) })
}, },
teardownAutosize() { teardownAutosize () {
mark('autosize.destroy()') mark('autosize.destroy()')
autosize.destroy(this.refs.textarea) autosize.destroy(this.refs.textarea)
stop('autosize.destroy()') stop('autosize.destroy()')
}, },
onBlur() { onBlur () {
this.store.set({composeFocused: false}) this.store.set({composeFocused: false})
}, },
onFocus() { onFocus () {
this.store.set({composeFocused: true}) this.store.set({composeFocused: true})
}, },
onSelectionChange(selectionStart) { onSelectionChange (selectionStart) {
this.store.set({composeSelectionStart: selectionStart}) this.store.set({composeSelectionStart: selectionStart})
}, },
onKeydown(e) { onKeydown (e) {
let { keyCode } = e let { keyCode } = e
// ctrl or cmd (on macs) was pressed; ctrl-enter means post a toot // ctrl or cmd (on macs) was pressed; ctrl-enter means post a toot
const ctrlPressed = e.getModifierState('Control') || e.getModifierState('Meta') const ctrlPressed = e.getModifierState('Control') || e.getModifierState('Meta')
@ -109,7 +109,7 @@
case 9: // tab case 9: // tab
this.clickSelectedAutosuggestion(e) this.clickSelectedAutosuggestion(e)
break break
case 13: //enter case 13: // enter
const autosuggestionClicked = this.clickSelectedAutosuggestion(e) const autosuggestionClicked = this.clickSelectedAutosuggestion(e)
if (!autosuggestionClicked && ctrlPressed) { if (!autosuggestionClicked && ctrlPressed) {
this.fire('postAction') this.fire('postAction')
@ -127,7 +127,7 @@
default: default:
} }
}, },
clickSelectedAutosuggestion(event) { clickSelectedAutosuggestion (event) {
let { let {
composeAutosuggestionShown, composeAutosuggestionShown,
composeAutosuggestionType composeAutosuggestionType
@ -145,7 +145,7 @@
event.stopPropagation() event.stopPropagation()
return true return true
}, },
incrementAutosuggestSelected(increment, event) { incrementAutosuggestSelected (increment, event) {
let { let {
composeAutosuggestionShown, composeAutosuggestionShown,
composeAutosuggestionSelected, composeAutosuggestionSelected,
@ -166,7 +166,7 @@
event.preventDefault() event.preventDefault()
event.stopPropagation() event.stopPropagation()
}, },
clearAutosuggestions(event) { clearAutosuggestions (event) {
let { composeAutosuggestionShown } = this.store.get() let { composeAutosuggestionShown } = this.store.get()
if (!composeAutosuggestionShown) { if (!composeAutosuggestionShown) {
return return

View File

@ -24,7 +24,7 @@
import { scheduleIdleTask } from '../../_utils/scheduleIdleTask' import { scheduleIdleTask } from '../../_utils/scheduleIdleTask'
export default { export default {
oncreate() { oncreate () {
let { lengthAsFraction } = this.get() let { lengthAsFraction } = this.get()
this.set({lengthAsFractionDeferred: lengthAsFraction}) this.set({lengthAsFractionDeferred: lengthAsFraction})
// perf improvement for keyboard input latency // perf improvement for keyboard input latency

View File

@ -22,7 +22,7 @@
import { scheduleIdleTask } from '../../_utils/scheduleIdleTask' import { scheduleIdleTask } from '../../_utils/scheduleIdleTask'
export default { export default {
oncreate() { oncreate () {
let { lengthToDisplay } = this.get() let { lengthToDisplay } = this.get()
this.set({lengthToDisplayDeferred: lengthToDisplay}) this.set({lengthToDisplayDeferred: lengthToDisplay})
// perf improvement for keyboard input latency // perf improvement for keyboard input latency

View File

@ -81,7 +81,7 @@
import { scheduleIdleTask } from '../../_utils/scheduleIdleTask' import { scheduleIdleTask } from '../../_utils/scheduleIdleTask'
export default { export default {
oncreate() { oncreate () {
this.setupSyncFromStore() this.setupSyncFromStore()
this.setupSyncToStore() this.setupSyncToStore()
}, },
@ -90,7 +90,7 @@
}), }),
store: () => store, store: () => store,
methods: { methods: {
setupSyncFromStore() { setupSyncFromStore () {
this.observe('mediaDescriptions', mediaDescriptions => { this.observe('mediaDescriptions', mediaDescriptions => {
mediaDescriptions = mediaDescriptions || [] mediaDescriptions = mediaDescriptions || []
let { index, rawText } = this.get() let { index, rawText } = this.get()
@ -100,7 +100,7 @@
} }
}) })
}, },
setupSyncToStore() { setupSyncToStore () {
const saveStore = debounce(() => scheduleIdleTask(() => this.store.save()), 1000) const saveStore = debounce(() => scheduleIdleTask(() => this.store.save()), 1000)
this.observe('rawText', rawText => { this.observe('rawText', rawText => {
@ -118,7 +118,7 @@
saveStore() saveStore()
}, {init: false}) }, {init: false})
}, },
onDeleteMedia() { onDeleteMedia () {
let { let {
realm, realm,
index index

View File

@ -52,7 +52,7 @@
import ComposeAutosuggest from './ComposeAutosuggest.html' import ComposeAutosuggest from './ComposeAutosuggest.html'
export default { export default {
oncreate() { oncreate () {
if (process.env.NODE_ENV !== 'production') { if (process.env.NODE_ENV !== 'production') {
window.__fakeFileInput = (file) => { window.__fakeFileInput = (file) => {
this.onFileChange({ this.onFileChange({
@ -69,25 +69,25 @@
}, },
store: () => store, store: () => store,
methods: { methods: {
async onEmojiClick() { async onEmojiClick () {
let dialogs = await importDialogs() let dialogs = await importDialogs()
let { realm } = this.get() let { realm } = this.get()
dialogs.showEmojiDialog(realm) dialogs.showEmojiDialog(realm)
}, },
onMediaClick() { onMediaClick () {
this.refs.input.click() this.refs.input.click()
}, },
onFileChange(e) { onFileChange (e) {
let file = e.target.files[0] let file = e.target.files[0]
let { realm } = this.get() let { realm } = this.get()
doMediaUpload(realm, file) doMediaUpload(realm, file)
}, },
async onPostPrivacyClick() { async onPostPrivacyClick () {
let dialogs = await importDialogs() let dialogs = await importDialogs()
let { realm } = this.get() let { realm } = this.get()
dialogs.showPostPrivacyDialog(realm) dialogs.showPostPrivacyDialog(realm)
}, },
onContentWarningClick() { onContentWarningClick () {
let { realm } = this.get() let { realm } = this.get()
toggleContentWarningShown(realm) toggleContentWarningShown(realm)
} }

View File

@ -55,8 +55,8 @@ export default {
muteIcon: (muting) => muting ? '#fa-volume-up' : '#fa-volume-off', muteIcon: (muting) => muting ? '#fa-volume-up' : '#fa-volume-off',
// end account data copypasta // end account data copypasta
items: (blockLabel, blocking, blockIcon, muteLabel, muteIcon, items: (blockLabel, blocking, blockIcon, muteLabel, muteIcon,
followLabel, followIcon, following, followRequested, followLabel, followIcon, following, followRequested,
accountId, verifyCredentialsId, acct) => { accountId, verifyCredentialsId, acct) => {
let isUser = accountId === verifyCredentialsId let isUser = accountId === verifyCredentialsId
return [ return [
!isUser && { !isUser && {
@ -86,7 +86,7 @@ export default {
methods: { methods: {
show, show,
close, close,
onClick(item) { onClick (item) {
switch (item.key) { switch (item.key) {
case 'mention': case 'mention':
return this.onMentionClicked() return this.onMentionClicked()
@ -98,7 +98,7 @@ export default {
return this.onMuteClicked() return this.onMuteClicked()
} }
}, },
async onMentionClicked() { async onMentionClicked () {
let { acct } = this.get() let { acct } = this.get()
this.store.setComposeData('dialog', { this.store.setComposeData('dialog', {
text: `@${acct} ` text: `@${acct} `
@ -107,17 +107,17 @@ export default {
dialogs.showComposeDialog() dialogs.showComposeDialog()
this.close() this.close()
}, },
async onFollowClicked() { async onFollowClicked () {
let { accountId, following } = this.get() let { accountId, following } = this.get()
this.close() this.close()
await setAccountFollowed(accountId, !following, true) await setAccountFollowed(accountId, !following, true)
}, },
async onBlockClicked() { async onBlockClicked () {
let { accountId, blocking } = this.get() let { accountId, blocking } = this.get()
this.close() this.close()
await setAccountBlocked(accountId, !blocking, true) await setAccountBlocked(accountId, !blocking, true)
}, },
async onMuteClicked() { async onMuteClicked () {
let { accountId, muting } = this.get() let { accountId, muting } = this.get()
this.close() this.close()
await setAccountMuted(accountId, !muting, true) await setAccountMuted(accountId, !muting, true)
@ -126,6 +126,6 @@ export default {
components: { components: {
ModalDialog, ModalDialog,
GenericDialogList GenericDialogList
}, }
} }
</script> </script>

View File

@ -15,14 +15,14 @@
import { close } from '../helpers/closeDialog' import { close } from '../helpers/closeDialog'
export default { export default {
oncreate() { oncreate () {
on('postedStatus', this, this.onPostedStatus) on('postedStatus', this, this.onPostedStatus)
onCreateDialog.call(this) onCreateDialog.call(this)
}, },
methods: { methods: {
show, show,
close, close,
onPostedStatus(realm) { onPostedStatus (realm) {
if (realm !== 'dialog') { if (realm !== 'dialog') {
return return
} }

View File

@ -40,14 +40,14 @@
import { oncreate as onCreateDialog } from '../helpers/onCreateDialog' import { oncreate as onCreateDialog } from '../helpers/onCreateDialog'
export default { export default {
oncreate() { oncreate () {
on('destroyDialog', this, this.onDestroyDialog) on('destroyDialog', this, this.onDestroyDialog)
onCreateDialog.call(this) onCreateDialog.call(this)
}, },
methods: { methods: {
show, show,
close, close,
onDestroyDialog(thisId) { onDestroyDialog (thisId) {
let { let {
id, id,
positiveResult, positiveResult,
@ -67,11 +67,11 @@
} }
} }
}, },
onPositive() { onPositive () {
this.set({positiveResult: true}) this.set({positiveResult: true})
this.close() this.close()
}, },
onNegative() { onNegative () {
this.close() this.close()
} }
}, },

View File

@ -81,7 +81,7 @@
methods: { methods: {
show, show,
close, close,
onClickEmoji(emoji) { onClickEmoji (emoji) {
let { realm } = this.get() let { realm } = this.get()
insertEmoji(realm, emoji) insertEmoji(realm, emoji)
this.close() this.close()

View File

@ -127,7 +127,7 @@
import { on, emit } from '../../../_utils/eventBus' import { on, emit } from '../../../_utils/eventBus'
export default { export default {
oncreate() { oncreate () {
let dialogElement = this.refs.node.parentElement let dialogElement = this.refs.node.parentElement
this._a11yDialog = new A11yDialog(dialogElement) this._a11yDialog = new A11yDialog(dialogElement)
this._a11yDialog.on('hide', () => { this._a11yDialog.on('hide', () => {
@ -162,7 +162,7 @@
} }
}, },
methods: { methods: {
showDialog(thisId) { showDialog (thisId) {
let { id } = this.get() let { id } = this.get()
if (id !== thisId) { if (id !== thisId) {
return return
@ -172,7 +172,7 @@
this.set({ fadedIn: true }) this.set({ fadedIn: true })
}) })
}, },
closeDialog(thisId) { closeDialog (thisId) {
let { id } = this.get() let { id } = this.get()
if (id !== thisId) { if (id !== thisId) {
return return

View File

@ -29,7 +29,7 @@
methods: { methods: {
show, show,
close, close,
onClick(item) { onClick (item) {
let { realm } = this.get() let { realm } = this.get()
setPostPrivacy(realm, item.key) setPostPrivacy(realm, item.key)
this.close() this.close()

View File

@ -53,8 +53,8 @@ export default {
muteIcon: (muting) => muting ? '#fa-volume-up' : '#fa-volume-off', muteIcon: (muting) => muting ? '#fa-volume-up' : '#fa-volume-off',
// end account data copypasta // end account data copypasta
items: (blockLabel, blocking, blockIcon, muteLabel, muteIcon, items: (blockLabel, blocking, blockIcon, muteLabel, muteIcon,
followLabel, followIcon, following, followRequested, followLabel, followIcon, following, followRequested,
accountId, verifyCredentialsId) => { accountId, verifyCredentialsId) => {
let isUser = accountId === verifyCredentialsId let isUser = accountId === verifyCredentialsId
return [ return [
isUser && { isUser && {
@ -89,7 +89,7 @@ export default {
methods: { methods: {
show, show,
close, close,
onClick(item) { onClick (item) {
switch (item.key) { switch (item.key) {
case 'delete': case 'delete':
return this.onDeleteClicked() return this.onDeleteClicked()
@ -101,22 +101,22 @@ export default {
return this.onMuteClicked() return this.onMuteClicked()
} }
}, },
async onDeleteClicked() { async onDeleteClicked () {
let { statusId } = this.get() let { statusId } = this.get()
this.close() this.close()
await doDeleteStatus(statusId) await doDeleteStatus(statusId)
}, },
async onFollowClicked() { async onFollowClicked () {
let { accountId, following } = this.get() let { accountId, following } = this.get()
this.close() this.close()
await setAccountFollowed(accountId, !following, true) await setAccountFollowed(accountId, !following, true)
}, },
async onBlockClicked() { async onBlockClicked () {
let { accountId, blocking } = this.get() let { accountId, blocking } = this.get()
this.close() this.close()
await setAccountBlocked(accountId, !blocking, true) await setAccountBlocked(accountId, !blocking, true)
}, },
async onMuteClicked() { async onMuteClicked () {
let { accountId, muting } = this.get() let { accountId, muting } = this.get()
this.close() this.close()
await setAccountMuted(accountId, !muting, true) await setAccountMuted(accountId, !muting, true)

View File

@ -120,7 +120,7 @@
numFollowersDisplay: numFollowers => numberFormat.format(numFollowers) numFollowersDisplay: numFollowers => numberFormat.format(numFollowers)
}, },
methods: { methods: {
async onMoreOptionsClick() { async onMoreOptionsClick () {
let { account, relationship, verifyCredentials } = this.get() let { account, relationship, verifyCredentials } = this.get()
let dialogs = await importDialogs() let dialogs = await importDialogs()
dialogs.showAccountProfileOptionsDialog(account, relationship, verifyCredentials) dialogs.showAccountProfileOptionsDialog(account, relationship, verifyCredentials)

View File

@ -28,7 +28,7 @@
export default { export default {
methods: { methods: {
async onFollowButtonClick(e) { async onFollowButtonClick (e) {
e.preventDefault() e.preventDefault()
e.stopPropagation() e.stopPropagation()
let { let {

View File

@ -39,7 +39,7 @@
note = `<p>${note}</p>` note = `<p>${note}</p>`
} }
return note return note
}, }
} }
} }
</script> </script>

View File

@ -19,14 +19,13 @@
} }
</style> </style>
<script> <script>
import PseudoVirtualListLazyItem from './PseudoVirtualListLazyItem.html' import PseudoVirtualListLazyItem from './PseudoVirtualListLazyItem.html'
import { getRectFromEntry } from '../../_utils/getRectFromEntry' import { getRectFromEntry } from '../../_utils/getRectFromEntry'
import { mark, stop } from '../../_utils/marks' import { mark, stop } from '../../_utils/marks'
import { pseudoVirtualListStore } from './pseudoVirtualListStore' import { pseudoVirtualListStore } from './pseudoVirtualListStore'
export default { export default {
oncreate() { oncreate () {
mark('PseudoVirtualList oncreate()') mark('PseudoVirtualList oncreate()')
let { realm } = this.get() let { realm } = this.get()
this.store.setCurrentRealm(realm) this.store.setCurrentRealm(realm)
@ -57,7 +56,7 @@
}) })
stop('PseudoVirtualList oncreate()') stop('PseudoVirtualList oncreate()')
}, },
ondestroy() { ondestroy () {
let { intersectionObserver } = this.get() let { intersectionObserver } = this.get()
if (intersectionObserver) { if (intersectionObserver) {
intersectionObserver.disconnect() intersectionObserver.disconnect()
@ -65,18 +64,18 @@
this.store.setCurrentRealm(null) this.store.setCurrentRealm(null)
}, },
helpers: { helpers: {
isIntersecting(key, $intersectionStates) { isIntersecting (key, $intersectionStates) {
return !!($intersectionStates[key] && $intersectionStates[key].isIntersecting) return !!($intersectionStates[key] && $intersectionStates[key].isIntersecting)
}, },
isCached(key, $intersectionStates) { isCached (key, $intersectionStates) {
return !!($intersectionStates[key] && $intersectionStates[key].isCached) return !!($intersectionStates[key] && $intersectionStates[key].isCached)
}, },
getHeight(key, $intersectionStates) { getHeight (key, $intersectionStates) {
return $intersectionStates[key] && $intersectionStates[key].height return $intersectionStates[key] && $intersectionStates[key].height
} }
}, },
methods: { methods: {
scrollToPosition(element) { scrollToPosition (element) {
let { scrolledToPosition } = this.get() let { scrolledToPosition } = this.get()
if (scrolledToPosition) { if (scrolledToPosition) {
return return
@ -87,7 +86,7 @@
element.scrollIntoView(true) element.scrollIntoView(true)
}) })
}, },
onIntersection(entries) { onIntersection (entries) {
mark('onIntersection') mark('onIntersection')
let newIntersectionStates = {} let newIntersectionStates = {}
let { scrollToItem } = this.get() let { scrollToItem } = this.get()

View File

@ -16,7 +16,7 @@
import { mark, stop } from '../../_utils/marks' import { mark, stop } from '../../_utils/marks'
export default { export default {
oncreate() { oncreate () {
this.observe('isIntersecting', isIntersecting => { this.observe('isIntersecting', isIntersecting => {
if (isIntersecting) { if (isIntersecting) {
mark('render') mark('render')

View File

@ -16,7 +16,7 @@
import { mark, stop } from '../../_utils/marks' import { mark, stop } from '../../_utils/marks'
export default { export default {
async oncreate() { async oncreate () {
// TODO: there appears to be a bug in {{#await}} that means we have to do this manually. // TODO: there appears to be a bug in {{#await}} that means we have to do this manually.
// Some items may appear on top of other items because their offset is 0 and never updated. // Some items may appear on top of other items because their offset is 0 and never updated.
let { makeProps, key } = this.get() let { makeProps, key } = this.get()

View File

@ -22,7 +22,7 @@
} }
</style> </style>
<script> <script>
import SettingsNav from './SettingsNav.html'; import SettingsNav from './SettingsNav.html'
import FreeTextLayout from '../../_components/FreeTextLayout' import FreeTextLayout from '../../_components/FreeTextLayout'
export default { export default {
@ -30,5 +30,5 @@
FreeTextLayout, FreeTextLayout,
SettingsNav SettingsNav
} }
}; }
</script> </script>

View File

@ -13,10 +13,10 @@
<script> <script>
export default { export default {
helpers: { helpers: {
getCurrentClass(page, name) { getCurrentClass (page, name) {
return page === name ? "selected" : "" return page === name ? 'selected' : ''
}, },
getAriaLabel(page, name, label) { getAriaLabel (page, name, label) {
return page === name ? `${label} (current page)` : label return page === name ? `${label} (current page)` : label
} }
} }

View File

@ -98,19 +98,18 @@
} }
</style> </style>
<script> <script>
import { DEFAULT_MEDIA_WIDTH, DEFAULT_MEDIA_HEIGHT } from '../../_static/media' import { DEFAULT_MEDIA_WIDTH, DEFAULT_MEDIA_HEIGHT, ONE_TRANSPARENT_PIXEL } from '../../_static/media'
import { importDialogs } from '../../_utils/asyncModules' import { importDialogs } from '../../_utils/asyncModules'
import { mouseover } from '../../_utils/events' import { mouseover } from '../../_utils/events'
import NonAutoplayGifv from '../NonAutoplayGifv.html' import NonAutoplayGifv from '../NonAutoplayGifv.html'
import PlayVideoIcon from '../PlayVideoIcon.html' import PlayVideoIcon from '../PlayVideoIcon.html'
import { ONE_TRANSPARENT_PIXEL } from '../../_static/media'
import { store } from '../../_store/store' import { store } from '../../_store/store'
import LazyImage from '../LazyImage.html' import LazyImage from '../LazyImage.html'
import AutoplayVideo from '../AutoplayVideo.html' import AutoplayVideo from '../AutoplayVideo.html'
import { registerClickDelegate } from '../../_utils/delegate' import { registerClickDelegate } from '../../_utils/delegate'
export default { export default {
oncreate() { oncreate () {
let { delegateKey } = this.get() let { delegateKey } = this.get()
registerClickDelegate(this, delegateKey, () => { registerClickDelegate(this, delegateKey, () => {
let { media } = this.get() let { media } = this.get()
@ -139,13 +138,13 @@
delegateKey: (media, uuid) => `media-${uuid}-${media.id}` delegateKey: (media, uuid) => `media-${uuid}-${media.id}`
}, },
methods: { methods: {
async onClickPlayVideoButton() { async onClickPlayVideoButton () {
let { media, modalWidth, modalHeight } = this.get() let { media, modalWidth, modalHeight } = this.get()
let dialogs = await importDialogs() let dialogs = await importDialogs()
dialogs.showVideoDialog(media.preview_url, media.url, dialogs.showVideoDialog(media.preview_url, media.url,
modalWidth, modalHeight, media.description) modalWidth, modalHeight, media.description)
}, },
async onClickShowImageButton() { async onClickShowImageButton () {
let { media, modalWidth, modalHeight } = this.get() let { media, modalWidth, modalHeight } = this.get()
let dialogs = await importDialogs() let dialogs = await importDialogs()
dialogs.showImageDialog(media.preview_url, media.url, media.type, dialogs.showImageDialog(media.preview_url, media.url, media.type,

View File

@ -38,7 +38,7 @@
computed: { computed: {
maxMediaWidth: (mediaAttachments) => { maxMediaWidth: (mediaAttachments) => {
return Math.max.apply(Math, mediaAttachments.map(media => { return Math.max.apply(Math, mediaAttachments.map(media => {
return media.meta && media.meta.small && typeof media.meta.small.width === 'number' ? media.meta.small.width : DEFAULT_MEDIA_WIDTH return media.meta && media.meta.small && typeof media.meta.small.width === 'number' ? media.meta.small.width : DEFAULT_MEDIA_WIDTH
})) }))
} }
}, },

View File

@ -46,7 +46,7 @@
statusId: (status) => status && status.id, statusId: (status) => status && status.id,
uuid: ($currentInstance, timelineType, timelineValue, notificationId, statusId) => { uuid: ($currentInstance, timelineType, timelineValue, notificationId, statusId) => {
return `${$currentInstance}/${timelineType}/${timelineValue}/${notificationId}/${statusId || ''}` return `${$currentInstance}/${timelineType}/${timelineValue}/${notificationId}/${statusId || ''}`
}, }
} }
} }
</script> </script>

View File

@ -122,7 +122,7 @@
const isStatusArticle = node => node.classList.contains('status-article') const isStatusArticle = node => node.classList.contains('status-article')
export default { export default {
oncreate() { oncreate () {
let { delegateKey, isStatusInOwnThread, showContent } = this.get() let { delegateKey, isStatusInOwnThread, showContent } = this.get()
if (!isStatusInOwnThread) { if (!isStatusInOwnThread) {
// the whole <article> is clickable in this case // the whole <article> is clickable in this case
@ -151,7 +151,7 @@
}, },
store: () => store, store: () => store,
methods: { methods: {
onClickOrKeydown(e) { onClickOrKeydown (e) {
let { type, keyCode, target } = e let { type, keyCode, target } = e
let isClick = type === 'click' let isClick = type === 'click'
@ -202,18 +202,18 @@
spoilerShown: ($spoilersShown, uuid) => !!$spoilersShown[uuid], spoilerShown: ($spoilersShown, uuid) => !!$spoilersShown[uuid],
replyShown: ($repliesShown, uuid) => !!$repliesShown[uuid], replyShown: ($repliesShown, uuid) => !!$repliesShown[uuid],
showMedia: (originalStatus, isStatusInNotification) => { showMedia: (originalStatus, isStatusInNotification) => {
return !isStatusInNotification return !isStatusInNotification &&
&& originalStatus.media_attachments originalStatus.media_attachments &&
&& originalStatus.media_attachments.length originalStatus.media_attachments.length
}, },
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}`
}, },
showHeader: (notification, status, timelineType) => { showHeader: (notification, status, timelineType) => {
return (notification && (notification.type === 'reblog' || notification.type === 'favourite')) return (notification && (notification.type === 'reblog' || notification.type === 'favourite')) ||
|| status.reblog status.reblog ||
|| timelineType === 'pinned' timelineType === 'pinned'
}, },
className: (visibility, timelineType, isStatusInOwnThread) => { className: (visibility, timelineType, isStatusInOwnThread) => {
return classname( return classname(

View File

@ -25,7 +25,7 @@
const THROTTLE_DELAY = 150 const THROTTLE_DELAY = 150
export default { export default {
oncreate() { oncreate () {
on('postedStatus', this, this.onPostedStatus) on('postedStatus', this, this.onPostedStatus)
this.setupRecalculateHeightListener() this.setupRecalculateHeightListener()
}, },
@ -34,7 +34,7 @@
composeData: ($currentComposeData, originalStatusId) => $currentComposeData[originalStatusId] || {} composeData: ($currentComposeData, originalStatusId) => $currentComposeData[originalStatusId] || {}
}, },
methods: { methods: {
onPostedStatus(realm) { onPostedStatus (realm) {
let { originalStatusId } = this.get() let { originalStatusId } = this.get()
if (realm !== originalStatusId) { if (realm !== originalStatusId) {
return return
@ -47,7 +47,7 @@
this.fire('recalculateHeight') this.fire('recalculateHeight')
}) })
}, },
setupRecalculateHeightListener() { setupRecalculateHeightListener () {
const recalc = () => requestAnimationFrame(() => this.fire('recalculateHeight')) const recalc = () => requestAnimationFrame(() => this.fire('recalculateHeight'))
// debounce AND throttle due to 333ms content warning animation // debounce AND throttle due to 333ms content warning animation
const debounced = debounce(recalc, DEBOUNCE_DELAY) const debounced = debounce(recalc, DEBOUNCE_DELAY)

View File

@ -64,7 +64,7 @@
import { emojifyText } from '../../_utils/emojifyText' import { emojifyText } from '../../_utils/emojifyText'
export default { export default {
oncreate() { oncreate () {
this.hydrateContent() this.hydrateContent()
}, },
store: () => store, store: () => store,
@ -90,7 +90,7 @@
} }
}, },
methods: { methods: {
hydrateContent() { hydrateContent () {
if (!this.refs.node) { if (!this.refs.node) {
return return
} }

View File

@ -81,7 +81,6 @@
} }
</style> </style>
<script> <script>
import Avatar from '../Avatar.html' import Avatar from '../Avatar.html'
export default { export default {

View File

@ -129,7 +129,7 @@
import { registerClickDelegate } from '../../_utils/delegate' import { registerClickDelegate } from '../../_utils/delegate'
export default { export default {
oncreate() { oncreate () {
let { delegateKey } = this.get() let { delegateKey } = this.get()
registerClickDelegate(this, delegateKey, () => this.onClickSensitiveMediaButton()) registerClickDelegate(this, delegateKey, () => this.onClickSensitiveMediaButton())
}, },
@ -141,10 +141,10 @@
mediaAttachments: (originalStatus) => originalStatus.media_attachments, mediaAttachments: (originalStatus) => originalStatus.media_attachments,
sensitiveShown: ($sensitivesShown, uuid) => !!$sensitivesShown[uuid], sensitiveShown: ($sensitivesShown, uuid) => !!$sensitivesShown[uuid],
sensitive: (originalStatus, $markMediaAsSensitive) => originalStatus.sensitive || $markMediaAsSensitive, sensitive: (originalStatus, $markMediaAsSensitive) => originalStatus.sensitive || $markMediaAsSensitive,
delegateKey: (uuid) => `sensitive-${uuid}`, delegateKey: (uuid) => `sensitive-${uuid}`
}, },
methods: { methods: {
onClickSensitiveMediaButton() { onClickSensitiveMediaButton () {
let { uuid } = this.get() let { uuid } = this.get()
let { sensitivesShown } = this.store.get() let { sensitivesShown } = this.store.get()
sensitivesShown[uuid] = !sensitivesShown[uuid] sensitivesShown[uuid] = !sensitivesShown[uuid]

View File

@ -52,7 +52,7 @@
import escapeHtml from 'escape-html' import escapeHtml from 'escape-html'
export default { export default {
oncreate() { oncreate () {
let { delegateKey } = this.get() let { delegateKey } = this.get()
registerClickDelegate(this, delegateKey, () => this.onClickSpoilerButton()) registerClickDelegate(this, delegateKey, () => this.onClickSpoilerButton())
}, },
@ -67,7 +67,7 @@
delegateKey: (uuid) => `spoiler-${uuid}` delegateKey: (uuid) => `spoiler-${uuid}`
}, },
methods: { methods: {
onClickSpoilerButton() { onClickSpoilerButton () {
requestAnimationFrame(() => { requestAnimationFrame(() => {
mark('clickSpoilerButton') mark('clickSpoilerButton')
let { uuid } = this.get() let { uuid } = this.get()

View File

@ -53,7 +53,7 @@
import { on } from '../../_utils/eventBus' import { on } from '../../_utils/eventBus'
export default { export default {
oncreate() { oncreate () {
let { let {
favoriteKey, favoriteKey,
reblogKey, reblogKey,
@ -73,21 +73,21 @@
}, },
store: () => store, store: () => store,
methods: { methods: {
onFavoriteClick(e) { onFavoriteClick (e) {
e.preventDefault() e.preventDefault()
e.stopPropagation() e.stopPropagation()
let { originalStatusId, favorited } = this.get() let { originalStatusId, favorited } = this.get()
/* no await */ setFavorited(originalStatusId, !favorited) /* no await */ setFavorited(originalStatusId, !favorited)
this.set({animateFavorite: !favorited}) this.set({animateFavorite: !favorited})
}, },
onReblogClick(e) { onReblogClick (e) {
e.preventDefault() e.preventDefault()
e.stopPropagation() e.stopPropagation()
let { originalStatusId, reblogged } = this.get() let { originalStatusId, reblogged } = this.get()
/* no await */ setReblogged(originalStatusId, !reblogged) /* no await */ setReblogged(originalStatusId, !reblogged)
this.set({animateReblog: !reblogged}) this.set({animateReblog: !reblogged})
}, },
onReplyClick(e) { onReplyClick (e) {
e.preventDefault() e.preventDefault()
e.stopPropagation() e.stopPropagation()
requestAnimationFrame(() => { requestAnimationFrame(() => {
@ -98,7 +98,7 @@
this.fire('recalculateHeight') this.fire('recalculateHeight')
}) })
}, },
async onOptionsClick(e) { async onOptionsClick (e) {
e.preventDefault() e.preventDefault()
e.stopPropagation() e.stopPropagation()
let { originalStatusId, originalAccountId } = this.get() let { originalStatusId, originalAccountId } = this.get()
@ -107,7 +107,7 @@
await updateRelationshipPromise await updateRelationshipPromise
dialogs.showStatusOptionsDialog(originalStatusId) dialogs.showStatusOptionsDialog(originalStatusId)
}, },
onPostedStatus(realm, inReplyToUuid) { onPostedStatus (realm, inReplyToUuid) {
let { let {
originalStatusId, originalStatusId,
uuid uuid
@ -166,7 +166,7 @@
favoriteKey: (uuid) => `fav-${uuid}`, favoriteKey: (uuid) => `fav-${uuid}`,
reblogKey: (uuid) => `reblog-${uuid}`, reblogKey: (uuid) => `reblog-${uuid}`,
replyKey: (uuid) => `reply-${uuid}`, replyKey: (uuid) => `reply-${uuid}`,
optionsKey: (uuid) => `options-${uuid}`, optionsKey: (uuid) => `options-${uuid}`
} }
} }
</script> </script>

View File

@ -16,7 +16,7 @@
import { store } from '../../_store/store' import { store } from '../../_store/store'
export default { export default {
oncreate() { oncreate () {
let { currentInstance } = this.store.get() let { currentInstance } = this.store.get()
let { timeline } = this.get() let { timeline } = this.get()
this.store.set({currentTimeline: timeline}) this.store.set({currentTimeline: timeline})

View File

@ -14,7 +14,7 @@
<script> <script>
export default { export default {
methods: { methods: {
onClick(event) { onClick (event) {
let { onClick } = this.get() let { onClick } = this.get()
if (onClick) { if (onClick) {
onClick(event) onClick(event)

View File

@ -16,7 +16,7 @@
import { updatePinnedStatusesForAccount } from '../../_actions/pinnedStatuses' import { updatePinnedStatusesForAccount } from '../../_actions/pinnedStatuses'
export default { export default {
async oncreate() { async oncreate () {
let { accountId } = this.get() let { accountId } = this.get()
await updatePinnedStatusesForAccount(accountId) await updatePinnedStatusesForAccount(accountId)
}, },

View File

@ -63,14 +63,14 @@
import { doubleRAF } from '../../_utils/doubleRAF' import { doubleRAF } from '../../_utils/doubleRAF'
export default { export default {
oncreate() { oncreate () {
console.log('timeline oncreate()') console.log('timeline oncreate()')
this.setupFocus() this.setupFocus()
setupTimeline() setupTimeline()
this.restoreFocus() this.restoreFocus()
this.setupStreaming() this.setupStreaming()
}, },
ondestroy() { ondestroy () {
console.log('ondestroy') console.log('ondestroy')
this.teardownFocus() this.teardownFocus()
}, },
@ -122,15 +122,13 @@
}, },
// for threads, it's simpler to just render all items as a pseudo-virtual list // for threads, it's simpler to just render all items as a pseudo-virtual list
// due to need to scroll to the right item and thus calculate all item heights up-front // due to need to scroll to the right item and thus calculate all item heights up-front
virtual: (timelineType) => timelineType !=='status', virtual: (timelineType) => timelineType !== 'status',
scrollToItem: (timelineType, timelineValue, $firstTimelineItemId) => { // Scroll to the first item if this is a "status in own thread" timeline.
// Scroll to the first item if this is a "status in own thread" timeline. // Don't scroll to the first item because it obscures the "back" button.
// Don't scroll to the first item because it obscures the "back" button. scrollToItem: (timelineType, timelineValue, $firstTimelineItemId) => (
return timelineType === 'status' timelineType === 'status' && $firstTimelineItemId &&
&& $firstTimelineItemId timelineValue !== $firstTimelineItemId && timelineValue
&& timelineValue !== $firstTimelineItemId ),
&& timelineValue
},
itemIdsToAdd: ($itemIdsToAdd) => $itemIdsToAdd, itemIdsToAdd: ($itemIdsToAdd) => $itemIdsToAdd,
headerProps: (itemIdsToAdd) => { headerProps: (itemIdsToAdd) => {
return { return {
@ -149,7 +147,7 @@
blurWithCapture blurWithCapture
}, },
methods: { methods: {
initialize() { initialize () {
let { initializeStarted } = this.get() let { initializeStarted } = this.get()
if (initializeStarted) { if (initializeStarted) {
return return
@ -162,10 +160,10 @@
stop('initializeTimeline') stop('initializeTimeline')
}) })
}, },
onScrollTopChanged(scrollTop) { onScrollTopChanged (scrollTop) {
this.set({scrollTop: scrollTop}) this.set({scrollTop: scrollTop})
}, },
onScrollToBottom() { onScrollToBottom () {
let { let {
timelineInitialized, timelineInitialized,
runningUpdate runningUpdate
@ -185,7 +183,7 @@
timeline timeline
) )
}, },
onScrollToTop() { onScrollToTop () {
let { shouldShowHeader } = this.store.get() let { shouldShowHeader } = this.store.get()
if (shouldShowHeader) { if (shouldShowHeader) {
this.store.setForCurrentTimeline({ this.store.setForCurrentTimeline({
@ -194,7 +192,7 @@
}) })
} }
}, },
setupStreaming() { setupStreaming () {
let { currentInstance } = this.store.get() let { currentInstance } = this.store.get()
let { timeline } = this.get() let { timeline } = this.get()
let handleItemIdsToAdd = () => { let handleItemIdsToAdd = () => {
@ -230,20 +228,20 @@
scheduleIdleTask(handleItemIdsToAdd) scheduleIdleTask(handleItemIdsToAdd)
}) })
}, },
setupFocus() { setupFocus () {
this.onPushState = this.onPushState.bind(this) this.onPushState = this.onPushState.bind(this)
this.store.setForCurrentTimeline({ this.store.setForCurrentTimeline({
ignoreBlurEvents: false ignoreBlurEvents: false
}) })
window.addEventListener('pushState', this.onPushState) window.addEventListener('pushState', this.onPushState)
}, },
teardownFocus() { teardownFocus () {
window.removeEventListener('pushState', this.onPushState) window.removeEventListener('pushState', this.onPushState)
}, },
onPushState() { onPushState () {
this.store.setForCurrentTimeline({ ignoreBlurEvents: true }) this.store.setForCurrentTimeline({ ignoreBlurEvents: true })
}, },
saveFocus(e) { saveFocus (e) {
try { try {
let { currentInstance } = this.store.get() let { currentInstance } = this.store.get()
let { timeline } = this.get() let { timeline } = this.get()
@ -263,7 +261,7 @@
console.error('unable to save focus', err) console.error('unable to save focus', err)
} }
}, },
clearFocus() { clearFocus () {
try { try {
let { ignoreBlurEvents } = this.store.get() let { ignoreBlurEvents } = this.store.get()
if (ignoreBlurEvents) { if (ignoreBlurEvents) {
@ -279,7 +277,7 @@
console.error('unable to clear focus', err) console.error('unable to clear focus', err)
} }
}, },
restoreFocus() { restoreFocus () {
let { lastFocusedElementSelector } = this.store.get() let { lastFocusedElementSelector } = this.store.get()
if (!lastFocusedElementSelector) { if (!lastFocusedElementSelector) {
return return
@ -294,7 +292,7 @@
}) })
}) })
}, },
onNoNeedToScroll() { onNoNeedToScroll () {
// If the timeline doesn't need to scroll, then we can safely "preinitialize," // If the timeline doesn't need to scroll, then we can safely "preinitialize,"
// i.e. render anything above the fold of the timeline. This avoids the affect // i.e. render anything above the fold of the timeline. This avoids the affect
// where the scrollable content appears to jump around if we need to scroll it. // where the scrollable content appears to jump around if we need to scroll it.

View File

@ -105,10 +105,10 @@
}, },
scrollTop: ($scrollTop) => $scrollTop, scrollTop: ($scrollTop) => $scrollTop,
// TODO: bug in svelte store, shouldn't need to do this // TODO: bug in svelte store, shouldn't need to do this
allVisibleItemsHaveHeight: ($allVisibleItemsHaveHeight) => $allVisibleItemsHaveHeight, allVisibleItemsHaveHeight: ($allVisibleItemsHaveHeight) => $allVisibleItemsHaveHeight
}, },
methods: { methods: {
calculateListOffset() { calculateListOffset () {
// TODO: better way to get the offset top? // TODO: better way to get the offset top?
let node = this.refs.node let node = this.refs.node
if (!node) { if (!node) {

View File

@ -11,7 +11,7 @@
const SCROLL_EVENT_DELAY = 300 const SCROLL_EVENT_DELAY = 300
export default { export default {
oncreate() { oncreate () {
mark('onCreate VirtualListContainer') mark('onCreate VirtualListContainer')
let { let {
realm, realm,
@ -53,14 +53,14 @@
} }
stop('onCreate VirtualListContainer') stop('onCreate VirtualListContainer')
}, },
ondestroy() { ondestroy () {
this.teardownScroll() this.teardownScroll()
this.teardownFullscreen() this.teardownFullscreen()
this.store.setCurrentRealm(null) this.store.setCurrentRealm(null)
}, },
store: () => virtualListStore, store: () => virtualListStore,
methods: { methods: {
setupScroll(node) { setupScroll (node) {
if (!node) { if (!node) {
return return
} }
@ -76,21 +76,21 @@
}) })
node.addEventListener('scroll', this.scrollListener) node.addEventListener('scroll', this.scrollListener)
}, },
teardownScroll() { teardownScroll () {
let { containerQuery } = this.get() let { containerQuery } = this.get()
let node = document.querySelector(containerQuery) let node = document.querySelector(containerQuery)
if (node) { if (node) {
node.removeEventListener('scroll', this.scrollListener) node.removeEventListener('scroll', this.scrollListener)
} }
}, },
setupFullscreen() { setupFullscreen () {
this.onFullscreenChange = this.onFullscreenChange.bind(this) this.onFullscreenChange = this.onFullscreenChange.bind(this)
attachFullscreenListener(this.onFullscreenChange) attachFullscreenListener(this.onFullscreenChange)
}, },
teardownFullscreen() { teardownFullscreen () {
detachFullscreenListener(this.onFullscreenChange) detachFullscreenListener(this.onFullscreenChange)
}, },
onScroll(event) { onScroll (event) {
let { scrollTop, scrollHeight } = event.target let { scrollTop, scrollHeight } = event.target
// On mobile devices, this can make scrolling more responsive. On // On mobile devices, this can make scrolling more responsive. On
@ -104,7 +104,7 @@
stop('onScroll -> setForRealm()') stop('onScroll -> setForRealm()')
}) })
}, },
onFullscreenChange() { onFullscreenChange () {
mark('onFullscreenChange') mark('onFullscreenChange')
console.log('is fullscreen? ', isFullscreen()) console.log('is fullscreen? ', isFullscreen())
this.set({ fullscreen: isFullscreen() }) this.set({ fullscreen: isFullscreen() })
@ -115,5 +115,5 @@
// TODO: bug in svelte/store the observer in oncreate() never get removed without this hack // TODO: bug in svelte/store the observer in oncreate() never get removed without this hack
allVisibleItemsHaveHeight: ($allVisibleItemsHaveHeight) => $allVisibleItemsHaveHeight allVisibleItemsHaveHeight: ($allVisibleItemsHaveHeight) => $allVisibleItemsHaveHeight
} }
}; }
</script> </script>

View File

@ -15,13 +15,13 @@
import { AsyncLayout } from '../../_utils/AsyncLayout' import { AsyncLayout } from '../../_utils/AsyncLayout'
export default { export default {
oncreate() { oncreate () {
const asyncLayout = new AsyncLayout(() => '__footer__') const asyncLayout = new AsyncLayout(() => '__footer__')
asyncLayout.observe('__footer__', this.refs.node, (rect) => { asyncLayout.observe('__footer__', this.refs.node, (rect) => {
asyncLayout.disconnect() asyncLayout.disconnect()
this.store.setForRealm({footerHeight: rect.height}) this.store.setForRealm({footerHeight: rect.height})
}) })
}, },
store: () => virtualListStore, store: () => virtualListStore
} }
</script> </script>

View File

@ -26,7 +26,7 @@
import { doubleRAF } from '../../_utils/doubleRAF' import { doubleRAF } from '../../_utils/doubleRAF'
export default { export default {
oncreate() { oncreate () {
this.observe('shown', shown => { this.observe('shown', shown => {
if (shown) { if (shown) {
this.doCalculateHeight() this.doCalculateHeight()
@ -38,7 +38,7 @@
}, },
store: () => virtualListStore, store: () => virtualListStore,
methods: { methods: {
doCalculateHeight() { doCalculateHeight () {
let { heightCalculated } = this.get() let { heightCalculated } = this.get()
if (heightCalculated) { // only need to calculate once, it never changes if (heightCalculated) { // only need to calculate once, it never changes
return return

View File

@ -28,7 +28,7 @@
import { registerResizeListener, unregisterResizeListener } from '../../_utils/resize' import { registerResizeListener, unregisterResizeListener } from '../../_utils/resize'
export default { export default {
oncreate() { oncreate () {
let asyncLayout = new AsyncLayout(node => node.getAttribute('virtual-list-key')) let asyncLayout = new AsyncLayout(node => node.getAttribute('virtual-list-key'))
let { key } = this.get() let { key } = this.get()
asyncLayout.observe(key, this.refs.node, (rect) => { asyncLayout.observe(key, this.refs.node, (rect) => {
@ -39,7 +39,7 @@
this.doRecalculateHeight = this.doRecalculateHeight.bind(this) this.doRecalculateHeight = this.doRecalculateHeight.bind(this)
registerResizeListener(this.doRecalculateHeight) registerResizeListener(this.doRecalculateHeight)
}, },
ondestroy() { ondestroy () {
unregisterResizeListener(this.doRecalculateHeight) unregisterResizeListener(this.doRecalculateHeight)
}, },
store: () => virtualListStore, store: () => virtualListStore,
@ -47,7 +47,7 @@
'shown': ($itemHeights, key) => $itemHeights[key] > 0 'shown': ($itemHeights, key) => $itemHeights[key] > 0
}, },
methods: { methods: {
doRecalculateHeight() { doRecalculateHeight () {
// Recalculate immediately because this is done on-demand, e.g. // Recalculate immediately because this is done on-demand, e.g.
// when clicking the "More" button on a spoiler. // when clicking the "More" button on a spoiler.
let rect = this.refs.node.getBoundingClientRect() let rect = this.refs.node.getBoundingClientRect()

View File

@ -11,7 +11,7 @@
import { mark, stop } from '../../_utils/marks' import { mark, stop } from '../../_utils/marks'
export default { export default {
async oncreate() { async oncreate () {
// TODO: there appears to be a bug in {{#await}} that means we have to do this manually. // TODO: there appears to be a bug in {{#await}} that means we have to do this manually.
// Some items may appear on top of other items because their offset is 0 and never updated. // Some items may appear on top of other items because their offset is 0 and never updated.
let { makeProps, key } = this.get() let { makeProps, key } = this.get()

View File

@ -29,7 +29,7 @@
import PinnedStatuses from '../../_components/timeline/PinnedStatuses.html' import PinnedStatuses from '../../_components/timeline/PinnedStatuses.html'
export default { export default {
oncreate() { oncreate () {
let { params } = this.get() let { params } = this.get()
let { accountId } = params let { accountId } = params
clearProfileAndRelationship() clearProfileAndRelationship()

View File

@ -95,7 +95,7 @@
import { updateLists } from '../../_actions/lists' import { updateLists } from '../../_actions/lists'
export default { export default {
async oncreate() { async oncreate () {
let { currentInstance } = this.store.get() let { currentInstance } = this.store.get()
if (currentInstance) { if (currentInstance) {
await updateLists() await updateLists()
@ -111,5 +111,5 @@
computed: { computed: {
isLockedAccount: ($currentVerifyCredentials) => $currentVerifyCredentials && $currentVerifyCredentials.locked isLockedAccount: ($currentVerifyCredentials) => $currentVerifyCredentials && $currentVerifyCredentials.locked
} }
}; }
</script> </script>

View File

@ -8,11 +8,11 @@
import { store } from '.././_store/store.js' import { store } from '.././_store/store.js'
import TimelineHomePage from '../_components/TimelineHomePage.html' import TimelineHomePage from '../_components/TimelineHomePage.html'
export default { export default {
store: () => store, store: () => store,
components: { components: {
NotLoggedInHome, NotLoggedInHome,
TimelineHomePage TimelineHomePage
} }
} }
</script> </script>

View File

@ -22,5 +22,5 @@
HiddenFromSSR, HiddenFromSSR,
TimelinePage TimelinePage
} }
}; }
</script> </script>

View File

@ -37,7 +37,7 @@
import { updateVerifyCredentialsForInstance } from '.././_actions/instances' import { updateVerifyCredentialsForInstance } from '.././_actions/instances'
export default { export default {
async oncreate() { async oncreate () {
try { try {
let { currentInstance } = this.store.get() let { currentInstance } = this.store.get()
await updateVerifyCredentialsForInstance(currentInstance) await updateVerifyCredentialsForInstance(currentInstance)

View File

@ -27,5 +27,5 @@
data: () => ({ data: () => ({
version version
}) })
}; }
</script> </script>

View File

@ -42,5 +42,5 @@
SettingsLayout SettingsLayout
}, },
store: () => store store: () => store
}; }
</script> </script>

View File

@ -19,5 +19,5 @@
SettingsList, SettingsList,
SettingsListItem SettingsListItem
} }
}; }
</script> </script>

View File

@ -112,9 +112,9 @@
}, },
store: () => store, store: () => store,
data: () => ({ data: () => ({
themes: themes, themes: themes
}), }),
async oncreate() { async oncreate () {
let { instanceName } = this.get() let { instanceName } = this.get()
await updateVerifyCredentialsForInstance(instanceName) await updateVerifyCredentialsForInstance(instanceName)
}, },
@ -124,23 +124,23 @@
verifyCredentials: ($verifyCredentials, instanceName) => $verifyCredentials && $verifyCredentials[instanceName] verifyCredentials: ($verifyCredentials, instanceName) => $verifyCredentials && $verifyCredentials[instanceName]
}, },
methods: { methods: {
onThemeChange() { onThemeChange () {
let { newTheme, instanceName } = this.get() let { newTheme, instanceName } = this.get()
changeTheme(instanceName, newTheme) changeTheme(instanceName, newTheme)
}, },
onSwitchToThisInstance(e) { onSwitchToThisInstance (e) {
e.preventDefault() e.preventDefault()
let { instanceName } = this.get() let { instanceName } = this.get()
switchToInstance(instanceName) switchToInstance(instanceName)
}, },
async onLogOut(e) { async onLogOut (e) {
e.preventDefault() e.preventDefault()
let { instanceName } = this.get() let { instanceName } = this.get()
let dialogs = await importDialogs() let dialogs = await importDialogs()
dialogs.showConfirmationDialog({ dialogs.showConfirmationDialog({
text: `Log out of ${instanceName}?`, text: `Log out of ${instanceName}?`,
onPositive() { onPositive () {
logOutOfInstance(instanceName) logOutOfInstance(instanceName)
} }
}) })

View File

@ -75,7 +75,7 @@
}, },
store: () => store, store: () => store,
methods: { methods: {
onSubmit(event) { onSubmit (event) {
event.preventDefault() event.preventDefault()
logInToInstance() logInToInstance()
} }