upgrade to svelte 2.0 (#251)

* upgrade to svelte 2.0

* update svelte-loader to 2.9.0
This commit is contained in:
Nolan Lawson 2018-05-01 17:05:36 -07:00 committed by GitHub
parent d2d82ba2e3
commit 42be854521
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
141 changed files with 1068 additions and 1068 deletions

16
package-lock.json generated
View File

@ -9786,9 +9786,9 @@
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
},
"svelte": {
"version": "1.64.1",
"resolved": "https://registry.npmjs.org/svelte/-/svelte-1.64.1.tgz",
"integrity": "sha512-RsEAcVYF90Bq5y4Lgg56LyKiuxiyDTU+5TG2GM0ppa50z446de0vQgnA3eQTrgecPdRR89ZIqNqN1cgdAdO7wQ=="
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/svelte/-/svelte-2.4.1.tgz",
"integrity": "sha512-49huVkAZV42sLny2/d6fU4Dzg605hkSQfNxISv34Kkb7M5MxmMhe9ywQ3+didcqwiHAqXn0/P0MojdbqU58ZIQ=="
},
"svelte-dev-helper": {
"version": "1.1.7",
@ -9801,13 +9801,12 @@
"integrity": "sha512-yoxNehbDxGEHxJBTWq2RpIPDTHlNNy6eGR7RPSK7qsh8hoyOXbji8uF//l4+I/l2fLP+E8pQTJYrduPXrW3wsw=="
},
"svelte-loader": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/svelte-loader/-/svelte-loader-2.8.1.tgz",
"integrity": "sha512-t3cfLeYCkuz1eJem+urdCYrhI12qUz03wlYzaRJ6oER1qrKBRlOpq8S4ZraInsw2FtKGFbu/VBYekLJS07Ipnw==",
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/svelte-loader/-/svelte-loader-2.9.0.tgz",
"integrity": "sha512-DmzPUCDBN/G/MKvi3iJZ6MDpoPKqN+um9PS8XBJn6yT6Kbu0pkU5AsdDdqauyKx2wEVQZ7DqpT9agWmDCr5TQg==",
"requires": {
"loader-utils": "1.1.0",
"svelte-dev-helper": "1.1.7",
"tmp": "0.0.31"
"svelte-dev-helper": "1.1.7"
}
},
"svelte-transitions": {
@ -10469,6 +10468,7 @@
"version": "0.0.31",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.31.tgz",
"integrity": "sha1-jzirlDjhcxXl29izZX6L+yd65Kc=",
"dev": true,
"requires": {
"os-tmpdir": "1.0.2"
}

View File

@ -77,9 +77,9 @@
"shrink-ray-current": "2.1.0",
"stringz": "1.0.0",
"style-loader": "0.21.0",
"svelte": "1.64.1",
"svelte": "2.4.1",
"svelte-extras": "2.0.2",
"svelte-loader": "2.8.1",
"svelte-loader": "2.9.0",
"svelte-transitions": "1.1.1",
"svgo": "1.0.5",
"timeago.js": "3.0.2",

View File

@ -1,17 +1,17 @@
<div class="accounts-page">
{{#if loading}}
{#if loading}
<LoadingPage />
{{elseif accounts && accounts.length}}
{:elseif accounts && accounts.length}
<ul class="accounts-results">
{{#each accounts as account}}
{#each accounts as account}
<AccountSearchResult
:account
actions={{accountActions}}
{account}
actions={accountActions}
on:click="onClickAction(event)"
/>
{{/each}}
{/each}
</ul>
{{/if}}
{/if}
</div>
<style>
.accounts-page {

View File

@ -1,11 +1,11 @@
<video
class="autoplay-video {{className || ''}}"
aria-label={{ariaLabel || ''}}
style="background-image: url({{poster}});"
:poster
:width
:height
:src
class="autoplay-video {className || ''}"
aria-label={ariaLabel || ''}
style="background-image: url({poster});"
{poster}
{width}
{height}
{src}
autoplay
muted
loop

View File

@ -1,27 +1,27 @@
{{#if error}}
<svg class={{computedClass}} aria-hidden="true">
{#if error}
<svg class={computedClass} aria-hidden="true">
<use xlink:href="#fa-user" />
</svg>
{{elseif $autoplayGifs}}
{:elseif $autoplayGifs}
<img
class={{computedClass}}
class={computedClass}
aria-hidden="true"
alt=""
src={{account.avatar}}
src={account.avatar}
on:imgLoad="set({loaded: true})"
on:imgLoadError="set({error: true})" />
{{else}}
{:else}
<NonAutoplayImg
className={{computedClass}}
className={computedClass}
ariaHidden="true"
alt=""
src={{account.avatar}}
staticSrc={{account.avatar_static}}
:isLink
src={account.avatar}
staticSrc={account.avatar_static}
{isLink}
on:imgLoad="set({loaded: true})"
on:imgLoadError="set({error: true})"
/>
{{/if}}
{/if}
<style>
:global(.avatar) {
border-radius: 4px;
@ -82,7 +82,7 @@
}),
store: () => store,
computed: {
computedClass: (className, loaded, size) => (classname(
computedClass: ({ className, loaded, size }) => (classname(
'avatar',
className,
loaded && 'loaded',

View File

@ -1,10 +1,10 @@
<div class="dynamic-page-banner {{icon ? 'dynamic-page-with-icon' : ''}}">
{{#if icon}}
<div class="dynamic-page-banner {icon ? 'dynamic-page-with-icon' : ''}">
{#if icon}
<svg class="dynamic-page-banner-svg">
<use xlink:href={{icon}} />
<use xlink:href={icon} />
</svg>
{{/if}}
<h1 class="dynamic-page-title">{{title}}</h1>
{/if}
<h1 class="dynamic-page-title">{title}</h1>
<button type="button"
class="dynamic-page-go-back"
on:click="onGoBack(event)">Back</button>

View File

@ -1,13 +1,13 @@
<a rel="nofollow noopener"
target="_blank"
:href
aria-label={{ariaLabel}}
class="{{className || ''}} {{showIcon ? 'external-link-with-icon' : ''}} {{normalIconColor ? 'normal-icon-color' : ''}}">
<slot></slot>{{#if showIcon}}
{href}
aria-label={ariaLabel}
class="{className || ''} {showIcon ? 'external-link-with-icon' : ''} {normalIconColor ? 'normal-icon-color' : ''}">
<slot></slot>{#if showIcon}
<svg class="external-link-svg">
<use xlink:href="#fa-external-link" />
</svg>
{{/if}}</a>
{/if}</a>
<style>
.external-link-with-icon {
display: inline-flex;

View File

@ -1,30 +1,30 @@
{{#if delegateKey}}
{#if delegateKey}
<button type="button"
title={{label}}
aria-label={{label}}
aria-pressed={{pressable ? !!pressed : ''}}
class={{computedClass}}
:disabled
delegate-key={{delegateKey}}
focus-key={{focusKey || ''}} >
<svg class="icon-button-svg {{svgClassName || ''}}" ref:svg>
<use xlink:href={{href}} />
title={label}
aria-label={label}
aria-pressed={pressable ? !!pressed : ''}
class={computedClass}
{disabled}
delegate-key={delegateKey}
focus-key={focusKey || ''} >
<svg class="icon-button-svg {svgClassName || ''}" ref:svg>
<use xlink:href={href} />
</svg>
</button>
{{else}}
{:else}
<button type="button"
title={{label}}
aria-label={{label}}
aria-pressed={{pressable ? !!pressed : ''}}
class={{computedClass}}
focus-key={{focusKey || ''}}
:disabled
title={label}
aria-label={label}
aria-pressed={pressable ? !!pressed : ''}
class={computedClass}
focus-key={focusKey || ''}
{disabled}
on:click >
<svg class="icon-button-svg {{svgClassName || ''}}" ref:svg>
<use xlink:href={{href}} />
<svg class="icon-button-svg {svgClassName || ''}" ref:svg>
<use xlink:href={href} />
</svg>
</button>
{{/if}}
{/if}
<style>
.icon-button {
padding: 6px 10px;
@ -118,7 +118,7 @@
}),
store: () => store,
computed: {
computedClass: (pressable, pressed, big, muted, className) => {
computedClass: ({ pressable, pressed, big, muted, className }) => {
return classname(
'icon-button',
!pressable && 'not-pressable',

View File

@ -1,12 +1,12 @@
<Nav :page />
<Nav {page} />
<div class="container" tabindex="0" ref:container>
<main>
<slot></slot>
</main>
{{#if !$isUserLoggedIn && page === 'home'}}
{#if !$isUserLoggedIn && page === 'home'}
<InformationalFooter />
{{/if}}
{/if}
</div>
<script>
import Nav from './Nav.html'

View File

@ -1,16 +1,16 @@
<div class="lazy-image"
style="width: {{width}}px; height: {{height}}px; background: {{background}};">
{{#if displaySrc}}
style="width: {width}px; height: {height}px; background: {background};">
{#if displaySrc}
<img
class="{{hidden ? 'hidden' : ''}} {{className || ''}}"
aria-hidden={{ariaHidden || ''}}
alt={{alt || ''}}
title={{alt || ''}}
src={{displaySrc}}
:width
:height
class="{hidden ? 'hidden' : ''} {className || ''}"
aria-hidden={ariaHidden || ''}
alt={alt || ''}
title={alt || ''}
src={displaySrc}
{width}
{height}
/>
{{/if}}
{/if}
</div>
<style>
.lazy-image {

View File

@ -1,6 +1,6 @@
{{#if revealed}}
<:Component {pageComponent} :params />
{{/if}}
{#if revealed}
<svelte:component this={pageComponent} {params} />
{/if}
<script>
// On the very first page load, avoid doing a "reveal" because
// it leads to a flash between when the SSR is shown, the two frame we hide it,

View File

@ -1,9 +1,9 @@
<div class="loading-mask-container {{shown ? 'loading-mask-container-shown' : ''}}">
{{#if shown}}
<div class="loading-mask-container {shown ? 'loading-mask-container-shown' : ''}">
{#if shown}
<div class="loading-mask">
<LoadingSpinner maskStyle="true"/>
</div>
{{/if}}
{/if}
</div>
<style>
.loading-mask-container {
@ -37,7 +37,7 @@
export default {
store: () => store,
computed: {
shown: ($logInToInstanceLoading) => $logInToInstanceLoading
shown: ({ $logInToInstanceLoading }) => $logInToInstanceLoading
},
components: {
LoadingSpinner

View File

@ -1,4 +1,4 @@
<div class="loading-page {{shown ? '' : 'hidden'}}">
<div class="loading-page {shown ? '' : 'hidden'}">
<LoadingSpinner />
</div>
<style>

View File

@ -1,5 +1,5 @@
<svg class="loading-spinner-icon spin {{maskStyle ? 'mask-style' : ''}}"
style="width: {{size}}px; height: {{size}}px;"
<svg class="loading-spinner-icon spin {maskStyle ? 'mask-style' : ''}"
style="width: {size}px; height: {size}px;"
aria-label="Loading"
>
<use xlink:href="#fa-spinner" />

Before

Width:  |  Height:  |  Size: 449 B

After

Width:  |  Height:  |  Size: 443 B

View File

@ -1,36 +1,36 @@
<nav class="main-nav">
<ul class="main-nav-ul">
<li class="main-nav-li">
<NavItem :page name="home" href="/" svg="#pinafore-logo" label="Home" />
<NavItem {page} name="home" href="/" svg="#pinafore-logo" label="Home" />
</li>
<li class="main-nav-li">
<NavItem :page name="notifications" href="/notifications" svg="#fa-bell" label="Notifications" />
<NavItem {page} name="notifications" href="/notifications" svg="#fa-bell" label="Notifications" />
</li>
{{#if $pinnedPage === '/local'}}
{#if $pinnedPage === '/local'}
<li class="main-nav-li">
<NavItem :page name="local" href="/local" svg="#fa-users" label="Local" />
<NavItem {page} name="local" href="/local" svg="#fa-users" label="Local" />
</li>
{{elseif $pinnedPage === '/federated'}}
{:elseif $pinnedPage === '/federated'}
<li class="main-nav-li">
<NavItem :page name="federated" href="/federated" svg="#fa-globe" label="Federated" />
<NavItem {page} name="federated" href="/federated" svg="#fa-globe" label="Federated" />
</li>
{{elseif $pinnedPage === '/favorites'}}
{:elseif $pinnedPage === '/favorites'}
<li class="main-nav-li">
<NavItem :page name="favorites" href="/favorites" svg="#fa-star" label="Favorites" />
<NavItem {page} name="favorites" href="/favorites" svg="#fa-star" label="Favorites" />
</li>
{{elseif $pinnedPage.startsWith('/lists/')}}
{:elseif $pinnedPage.startsWith('/lists/')}
<li class="main-nav-li">
<NavItem :page name="lists" href={{$pinnedPage}} svg="#fa-bars" label={{$pinnedListTitle}} />
<NavItem {page} name="lists" href={$pinnedPage} svg="#fa-bars" label={$pinnedListTitle} />
</li>
{{/if}}
{/if}
<li class="main-nav-li">
<NavItem :page name="community" href="/community" svg="#fa-comments" label="Community" />
<NavItem {page} name="community" href="/community" svg="#fa-comments" label="Community" />
</li>
<li class="main-nav-li">
<NavItem :page name="search" href="/search" svg="#fa-search" label="Search" />
<NavItem {page} name="search" href="/search" svg="#fa-search" label="Search" />
</li>
<li class="main-nav-li">
<NavItem :page name="settings" href="/settings" svg="#fa-gear" label="Settings" />
<NavItem {page} name="settings" href="/settings" svg="#fa-gear" label="Settings" />
</li>
</ul>
</nav>

View File

@ -1,25 +1,25 @@
<a class='main-nav-link {{selected ? "selected" : ""}}'
aria-label={{ariaLabel}}
aria-current={{selected}}
<a class='main-nav-link {selected ? "selected" : ""}'
aria-label={ariaLabel}
aria-current={selected}
on:click="onClick(event)"
:href >
{{#if name === 'notifications'}}
{href} >
{#if name === 'notifications'}
<div class="nav-link-svg-wrapper">
<svg class="nav-link-svg">
<use xlink:href={{svg}} />
<use xlink:href={svg} />
</svg>
{{#if $hasNotifications}}
{#if $hasNotifications}
<span class="nav-link-notifications" aria-hidden="true">
{{$numberOfNotifications}}
{$numberOfNotifications}
</span>
{{/if}}
{/if}
</div>
{{else}}
{:else}
<svg class="nav-link-svg">
<use xlink:href={{svg}} />
<use xlink:href={svg} />
</svg>
{{/if}}
<span class="nav-link-label">{{label}}</span>
{/if}
<span class="nav-link-label">{label}</span>
</a>
<style>
.main-nav-link {
@ -122,8 +122,8 @@
export default {
store: () => store,
computed: {
selected: (page, name) => page === name,
ariaLabel: (selected, name, label, $numberOfNotifications) => {
selected: ({ page, name }) => page === name,
ariaLabel: ({ selected, name, label, $numberOfNotifications }) => {
let res = label
if (selected) {
res += ' (current page)'

View File

@ -1,29 +1,29 @@
<div class="non-autoplay-gifv" style="width: {{width}}px; height: {{height}}px;"
<div class="non-autoplay-gifv" style="width: {width}px; height: {height}px;"
on:mouseover="onMouseOver(event)"
ref:node
>
{{#if playing}}
{#if playing}
<AutoplayVideo
className={{class}}
ariaLabel={{label}}
:poster
:src
:width
:height
className={class}
ariaLabel={label}
{poster}
{src}
{width}
{height}
/>
{{else}}
{:else}
<LazyImage
alt={{label || ''}}
title={{label || ''}}
src={{staticSrc}}
fallback={{oneTransparentPixel}}
:width
:height
alt={label || ''}
title={label || ''}
src={staticSrc}
fallback={oneTransparentPixel}
{width}
{height}
background="var(--loading-bg)"
className={{class}}
className={class}
/>
{{/if}}
<PlayVideoIcon className={{playing ? 'hidden' : ''}}/>
{/if}
<PlayVideoIcon className={playing ? 'hidden' : ''}/>
</div>
<style>
.non-autoplay-gifv {

View File

@ -1,22 +1,22 @@
{{#if staticSrc === src}}
<img class={{className || ''}}
aria-hidden={{ariaHidden}}
alt={{alt || ''}}
title={{alt || ''}}
:src
{#if staticSrc === src}
<img class={className || ''}
aria-hidden={ariaHidden}
alt={alt || ''}
title={alt || ''}
{src}
on:imgLoad
on:imgLoadError />
{{else}}
<img class="{{className || ''}} non-autoplay-zoom-in {{isLink ? 'is-link' : ''}}"
aria-hidden={{ariaHidden}}
alt={{alt || ''}}
title={{alt || ''}}
src={{staticSrc}}
{:else}
<img class="{className || ''} non-autoplay-zoom-in {isLink ? 'is-link' : ''}"
aria-hidden={ariaHidden}
alt={alt || ''}
title={alt || ''}
src={staticSrc}
on:imgLoad
on:imgLoadError
on:mouseover="onMouseOver(event)"
ref:node />
{{/if}}
{/if}
<style>
.non-autoplay-zoom-in {
cursor: zoom-in;

View File

@ -1,4 +1,4 @@
<div class="play-video-icon {{className || ''}}">
<div class="play-video-icon {className || ''}">
<svg class="play-video-icon-svg">
<use xlink:href="#fa-play-circle" />
</svg>

View File

@ -3,18 +3,18 @@
without a div wrapper due to sticky-positioned compose button.
TODO: this is a bit hacky due to code duplication
-->
<div class="timeline-home-page" aria-busy={{hideTimeline}}>
{{#if hidePage}}
<div class="timeline-home-page" aria-busy={hideTimeline}>
{#if hidePage}
<LoadingPage />
{{/if}}
{{#if $currentVerifyCredentials }}
<ComposeBox realm="home" hidden={{hidePage}}/>
{{/if}}
{/if}
{#if $currentVerifyCredentials }
<ComposeBox realm="home" hidden={hidePage}/>
{/if}
<div class="timeline-home-anchor-container">
{{#if !hidePage && hideTimeline}}
{#if !hidePage && hideTimeline}
<LoadingPage />
{{/if}}
<div class="timeline-home-reveal-container {{hideTimeline ? 'hidden' : ''}}">
{/if}
<div class="timeline-home-reveal-container {hideTimeline ? 'hidden' : ''}">
<LazyTimeline timeline="home" />
</div>
</div>
@ -41,8 +41,8 @@
})
},
computed: {
hidePage: ($timelineInitialized, $timelinePreinitialized) => !$timelineInitialized && !$timelinePreinitialized,
hideTimeline: ($timelineInitialized) => !$timelineInitialized
hidePage: ({ $timelineInitialized, $timelinePreinitialized }) => !$timelineInitialized && !$timelinePreinitialized,
hideTimeline: ({ $timelineInitialized }) => !$timelineInitialized
},
store: () => store,
components: {

View File

@ -1,16 +1,16 @@
<div class="timeline-page" aria-busy={{hideTimeline}}>
{{#if hidePage}}
<div class="timeline-page" aria-busy={hideTimeline}>
{#if hidePage}
<LoadingPage />
{{/if}}
<div class="timeline-slot-reveal-container {{hidePage ? 'hidden' : ''}}">
{/if}
<div class="timeline-slot-reveal-container {hidePage ? 'hidden' : ''}">
<slot></slot>
</div>
<div class="timeline-anchor-container">
{{#if !hidePage && hideTimeline}}
{#if !hidePage && hideTimeline}
<LoadingPage />
{{/if}}
<div class="timeline-reveal-container {{hideTimeline ? 'hidden' : ''}}">
<LazyTimeline :timeline />
{/if}
<div class="timeline-reveal-container {hideTimeline ? 'hidden' : ''}">
<LazyTimeline {timeline} />
</div>
</div>
</div>
@ -35,8 +35,8 @@
})
},
computed: {
hidePage: ($timelineInitialized, $timelinePreinitialized) => !$timelineInitialized && !$timelinePreinitialized,
hideTimeline: ($timelineInitialized) => !$timelineInitialized
hidePage: ({ $timelineInitialized, $timelinePreinitialized }) => !$timelineInitialized && !$timelinePreinitialized,
hideTimeline: ({ $timelineInitialized }) => !$timelineInitialized
},
store: () => store,
components: {

View File

@ -1,6 +1,6 @@
<div class="toast-modal {{shown ? 'shown' : ''}}" role="alert" aria-hidden={{shown}}>
<div class="toast-modal {shown ? 'shown' : ''}" role="alert" aria-hidden={shown}>
<div class="toast-container">
{{text}}
{text}
</div>
</div>
<style>

View File

@ -1,13 +1,13 @@
<div class="page-list-wrapper">
{{#if label}}
<ul class="page-list" aria-label={{label}}>
{#if label}
<ul class="page-list" aria-label={label}>
<slot></slot>
</ul>
{{else}}
{:else}
<ul class="page-list">
<slot></slot>
</ul>
{{/if}}
{/if}
</div>
<style>
.page-list-wrapper {

View File

@ -1,18 +1,18 @@
<li class="page-list-item">
<a :href>
<a {href}>
<svg class="page-list-item-svg">
<use xlink:href={{icon}} />
<use xlink:href={icon} />
</svg>
<span aria-label="{{label}} {{$pinnedPage === href ? 'Pinned page' : 'Unpinned page'}}">
{{label}}
<span aria-label="{label} {$pinnedPage === href ? 'Pinned page' : 'Unpinned page'}">
{label}
</span>
{{#if pinnable}}
{#if pinnable}
<IconButton pressable="true"
pressed={{$pinnedPage === href}}
label={{$pinnedPage === href ? 'Unpin timeline' : 'Pin timeline'}}
pressed={$pinnedPage === href}
label={$pinnedPage === href ? 'Unpin timeline' : 'Pin timeline'}
href="#fa-thumb-tack"
on:click="onPinClick(event)" />
{{/if}}
{/if}
</a>
</li>
<style>

View File

@ -1,13 +1,13 @@
<a href="/accounts/{{verifyCredentials.id}}"
<a href="/accounts/{verifyCredentials.id}"
class="compose-box-avatar"
aria-label="Profile for {{verifyCredentials.display_name || verifyCredentials.acct}}">
<Avatar account={{verifyCredentials}} size="small"/>
aria-label="Profile for {verifyCredentials.display_name || verifyCredentials.acct}">
<Avatar account={verifyCredentials} size="small"/>
</a>
<a class="compose-box-display-name" href="/accounts/{{verifyCredentials.id}}">
{{verifyCredentials.display_name || verifyCredentials.acct}}
<a class="compose-box-display-name" href="/accounts/{verifyCredentials.id}">
{verifyCredentials.display_name || verifyCredentials.acct}
</a>
<span class="compose-box-handle">
{{'@' + verifyCredentials.acct}}
{'@' + verifyCredentials.acct}
</span>
<style>
.compose-box-avatar {
@ -57,7 +57,7 @@
},
store: () => store,
computed: {
verifyCredentials: ($currentVerifyCredentials) => $currentVerifyCredentials
verifyCredentials: ({ $currentVerifyCredentials }) => $currentVerifyCredentials
}
}
</script>

View File

@ -1,10 +1,10 @@
<div class="compose-autosuggest {{shown ? 'shown' : ''}} {{realm === 'dialog' ? 'is-dialog' : ''}}"
<div class="compose-autosuggest {shown ? 'shown' : ''} {realm === 'dialog' ? 'is-dialog' : ''}"
aria-hidden="true" >
<ComposeAutosuggestionList
items={{searchResults}}
items={searchResults}
on:click="onClick(event)"
:type
:selected
{type}
{selected}
/>
</div>
<style>
@ -139,13 +139,13 @@
}
},
computed: {
composeSelectionStart: ($composeSelectionStart) => $composeSelectionStart,
composeFocused: ($composeFocused) => $composeFocused,
thisComposeFocused: (composeFocusedDeferred, realm) => composeFocusedDeferred === realm,
searchResults: ($composeAutosuggestionSearchResults) => $composeAutosuggestionSearchResults || [],
type: ($composeAutosuggestionType) => $composeAutosuggestionType || 'account',
selected: ($composeAutosuggestionSelected) => $composeAutosuggestionSelected || 0,
searchText: (text, composeSelectionStartDeferred, thisComposeFocused) => {
composeSelectionStart: ({ $composeSelectionStart }) => $composeSelectionStart,
composeFocused: ({ $composeFocused }) => $composeFocused,
thisComposeFocused: ({ composeFocusedDeferred, realm }) => composeFocusedDeferred === realm,
searchResults: ({ $composeAutosuggestionSearchResults }) => $composeAutosuggestionSearchResults || [],
type: ({ $composeAutosuggestionType }) => $composeAutosuggestionType || 'account',
selected: ({ $composeAutosuggestionSelected }) => $composeAutosuggestionSelected || 0,
searchText: ({ text, composeSelectionStartDeferred, thisComposeFocused }) => {
if (!thisComposeFocused) {
return
}
@ -158,7 +158,7 @@
let match = textUpToCursor.match(ACCOUNT_SEARCH_REGEX) || textUpToCursor.match(EMOJI_SEARCH_REGEX)
return match && match[1]
},
shown: (thisComposeFocused, searchText, searchResults) => {
shown: ({ thisComposeFocused, searchText, searchResults }) => {
return !!(thisComposeFocused &&
searchText &&
searchResults.length)

View File

@ -1,35 +1,35 @@
<ul class="compose-autosuggest-list">
{{#each items as item, i}}
{#each items as item, i}
<li class="compose-autosuggest-list-item">
<button class="compose-autosuggest-list-button {{i === selected ? 'selected' : ''}}"
<button class="compose-autosuggest-list-button {i === selected ? 'selected' : ''}"
tabindex="0"
on:click="fire('click', item)">
<div class="compose-autosuggest-list-grid">
{{#if type === 'account'}}
{#if type === 'account'}
<Avatar
className="compose-autosuggest-list-item-avatar"
size="small"
account={{item}}
account={item}
/>
<span class="compose-autosuggest-list-display-name">
{{item.display_name || item.acct}}
{item.display_name || item.acct}
</span>
<span class="compose-autosuggest-list-username">
{{'@' + item.acct}}
{'@' + item.acct}
</span>
{{else}}
<img src={{$autoplayGifs ? item.url : item.static_url}}
{:else}
<img src={$autoplayGifs ? item.url : item.static_url}
class="compose-autosuggest-list-item-icon"
alt="{{':' + item.shortcode + ':'}}"
alt="{':' + item.shortcode + ':'}"
/>
<span class="compose-autosuggest-list-display-name">
{{':' + item.shortcode + ':'}}
{':' + item.shortcode + ':'}
</span>
{{/if}}
{/if}
</div>
</button>
</li>
{{/each}}
{/each}
</ul>
<style>
.compose-autosuggest-list {

View File

@ -1,27 +1,27 @@
{{#if realm === 'home'}}
{#if realm === 'home'}
<h1 class="sr-only">Compose toot</h1>
{{/if}}
<div class="{{computedClassName}} {{hideAndFadeIn}}">
{/if}
<div class="{computedClassName} {hideAndFadeIn}">
<ComposeAuthor />
{{#if contentWarningShown}}
{#if contentWarningShown}
<div class="compose-content-warning-wrapper"
transition:slide="{duration: 333}">
<ComposeContentWarning :realm :contentWarning />
<ComposeContentWarning {realm} {contentWarning} />
</div>
{{/if}}
<ComposeInput :realm :text :autoFocus on:postAction="doPostStatus()" />
<ComposeLengthGauge :length :overLimit />
<ComposeToolbar :realm :postPrivacy :media :contentWarningShown :text />
<ComposeLengthIndicator :length :overLimit />
<ComposeMedia :realm :media :mediaDescriptions />
{/if}
<ComposeInput {realm} {text} {autoFocus} on:postAction="doPostStatus()" />
<ComposeLengthGauge {length} {overLimit} />
<ComposeToolbar {realm} {postPrivacy} {media} {contentWarningShown} {text} />
<ComposeLengthIndicator {length} {overLimit} />
<ComposeMedia {realm} {media} {mediaDescriptions} />
</div>
<div class="compose-box-button-sentinel {{hideAndFadeIn}}" ref:sentinel></div>
<div class="compose-box-button-wrapper {{realm === 'home' ? 'compose-button-sticky' : ''}} {{hideAndFadeIn}}" >
<ComposeButton :length :overLimit :sticky on:click="onClickPostButton()" />
<div class="compose-box-button-sentinel {hideAndFadeIn}" ref:sentinel></div>
<div class="compose-box-button-wrapper {realm === 'home' ? 'compose-button-sticky' : ''} {hideAndFadeIn}" >
<ComposeButton {length} {overLimit} {sticky} on:click="onClickPostButton()" />
</div>
{{#if !hideBottomBorder}}
<div class="compose-box-border-bottom {{hideAndFadeIn}}"></div>
{{/if}}
{#if !hideBottomBorder}
<div class="compose-box-border-bottom {hideAndFadeIn}"></div>
{/if}
<style>
.compose-box {
border-radius: 4px;
@ -162,32 +162,32 @@
}),
store: () => store,
computed: {
computedClassName: (overLimit, realm, size, postPrivacyKey, isReply) => (classname(
computedClassName: ({ overLimit, realm, size, postPrivacyKey, isReply }) => (classname(
'compose-box',
overLimit && 'over-char-limit',
size === 'slim' && 'slim-size',
isReply && postPrivacyKey === 'direct' && 'direct-reply'
)),
hideAndFadeIn: (hidden) => (classname(
hideAndFadeIn: ({ hidden }) => (classname(
'compose-box-fade-in',
hidden && 'hidden'
)),
composeData: ($currentComposeData, realm) => $currentComposeData[realm] || {},
text: (composeData) => composeData.text || '',
media: (composeData) => composeData.media || [],
postPrivacy: (postPrivacyKey) => POST_PRIVACY_OPTIONS.find(_ => _.key === postPrivacyKey),
defaultPostPrivacyKey: ($currentVerifyCredentials) => $currentVerifyCredentials.source.privacy,
postPrivacyKey: (composeData, defaultPostPrivacyKey) => composeData.postPrivacy || defaultPostPrivacyKey,
textLength: (text) => measureText(text),
contentWarningLength: (contentWarning) => measureText(contentWarning),
length: (textLength, contentWarningLength, contentWarningShown) => (
composeData: ({ $currentComposeData, realm }) => $currentComposeData[realm] || {},
text: ({ composeData }) => composeData.text || '',
media: ({ composeData }) => composeData.media || [],
postPrivacy: ({ postPrivacyKey }) => POST_PRIVACY_OPTIONS.find(_ => _.key === postPrivacyKey),
defaultPostPrivacyKey: ({ $currentVerifyCredentials }) => $currentVerifyCredentials.source.privacy,
postPrivacyKey: ({ composeData, defaultPostPrivacyKey }) => composeData.postPrivacy || defaultPostPrivacyKey,
textLength: ({ text }) => measureText(text),
contentWarningLength: ({ contentWarning }) => measureText(contentWarning),
length: ({ textLength, contentWarningLength, contentWarningShown }) => (
textLength + (contentWarningShown ? contentWarningLength : 0)
),
overLimit: (length) => length > CHAR_LIMIT,
contentWarningShown: (composeData) => composeData.contentWarningShown,
contentWarning: (composeData) => composeData.contentWarning || '',
timelineInitialized: ($timelineInitialized) => $timelineInitialized,
mediaDescriptions: (composeData) => composeData.mediaDescriptions || []
overLimit: ({ length }) => length > CHAR_LIMIT,
contentWarningShown: ({ composeData }) => composeData.contentWarningShown,
contentWarning: ({ composeData }) => composeData.contentWarning || '',
timelineInitialized: ({ $timelineInitialized }) => $timelineInitialized,
mediaDescriptions: ({ composeData }) => composeData.mediaDescriptions || []
},
transitions: {
slide

View File

@ -1,19 +1,19 @@
<div class="compose-box-button-halo">
<button class="primary compose-box-button"
:disabled
aria-label={{sticky ? 'Compose' : 'Toot!'}}
{disabled}
aria-label={sticky ? 'Compose' : 'Toot!'}
on:click>
<span class={{$postingStatus || sticky ? 'hidden' : ''}}>
<span class={$postingStatus || sticky ? 'hidden' : ''}>
Toot!
</span>
<div class="compose-box-button-spinner"
aria-hidden="true">
<svg class="compose-box-button-svg {{$postingStatus ? 'spin' : 'hidden'}}">
<svg class="compose-box-button-svg {$postingStatus ? 'spin' : 'hidden'}">
<use xlink:href="#fa-spinner" />
</svg>
</div>
<div class="compose-box-button-compose {{sticky ? '' : 'hidden'}}"
<div class="compose-box-button-compose {sticky ? '' : 'hidden'}"
aria-hidden="true">
<svg class="compose-box-button-svg">
<use xlink:href="#fa-pencil" />
@ -68,7 +68,7 @@
export default {
store: () => store,
computed: {
disabled: ($postingStatus, overLimit) => $postingStatus || overLimit
disabled: ({ $postingStatus, overLimit }) => $postingStatus || overLimit
}
}
</script>

View File

@ -1,5 +1,5 @@
<div class="compose-box-length-gauge {{shouldAnimate ? 'should-animate' : ''}} {{overLimit ? 'over-char-limit' : ''}}"
style="transform: scaleX({{lengthAsFractionDeferred}});"
<div class="compose-box-length-gauge {shouldAnimate ? 'should-animate' : ''} {overLimit ? 'over-char-limit' : ''}"
style="transform: scaleX({lengthAsFractionDeferred});"
aria-hidden="true"
></div>
<style>
@ -45,7 +45,7 @@
}),
store: () => store,
computed: {
lengthAsFraction: (length) => {
lengthAsFraction: ({ length }) => {
// We don't need to update the gauge for every decimal point, so round it to the nearest 0.02
let int = Math.round(Math.min(CHAR_LIMIT, length) / CHAR_LIMIT * 100)
return (int - (int % 2)) / 100

View File

@ -1,6 +1,6 @@
<span class="compose-box-length {{overLimit ? 'over-char-limit' : ''}}"
aria-label={{lengthLabel}}>
{{lengthToDisplayDeferred}}
<span class="compose-box-length {overLimit ? 'over-char-limit' : ''}"
aria-label={lengthLabel}>
{lengthToDisplayDeferred}
</span>
<style>
.compose-box-length {
@ -41,8 +41,8 @@
}),
store: () => store,
computed: {
lengthToDisplay: (length) => CHAR_LIMIT - length,
lengthLabel: (overLimit, lengthToDisplayDeferred) => {
lengthToDisplay: ({ length }) => CHAR_LIMIT - length,
lengthLabel: ({ overLimit, lengthToDisplayDeferred }) => {
if (overLimit) {
return `${lengthToDisplayDeferred} characters over limit`
} else {

View File

@ -1,10 +1,10 @@
{{#if media.length}}
<div class="compose-media-container" style="grid-template-columns: repeat({{media.length}}, 1fr);">
{{#each media as mediaItem, index}}
<ComposeMediaItem :realm :mediaItem :index :mediaDescriptions />
{{/each}}
{#if media.length}
<div class="compose-media-container" style="grid-template-columns: repeat({media.length}, 1fr);">
{#each media as mediaItem, index}
<ComposeMediaItem {realm} {mediaItem} {index} {mediaDescriptions} />
{/each}
</div>
{{/if}}
{/if}
<style>
.compose-media-container {
grid-area: media;

View File

@ -1,8 +1,8 @@
<div class="compose-media">
<img src={{mediaItem.data.preview_url}} alt={{mediaItem.file.name}}/>
<img src={mediaItem.data.preview_url} alt={mediaItem.file.name}/>
<div class="compose-media-delete">
<button class="compose-media-delete-button"
aria-label="Delete {{mediaItem.file.name}}"
aria-label="Delete {mediaItem.file.name}"
on:click="onDeleteMedia()" >
<svg class="compose-media-delete-button-svg">
<use xlink:href="#fa-times" />
@ -12,7 +12,7 @@
<div class="compose-media-alt">
<input type="text"
placeholder="Description"
aria-label="Describe {{mediaItem.file.name}} for the visually impaired"
aria-label="Describe {mediaItem.file.name} for the visually impaired"
bind:value=rawText
>
</div>

View File

@ -6,23 +6,23 @@
on:click="onEmojiClick()"
/>
<IconButton
svgClassName={{$uploadingMedia ? 'spin' : ''}}
svgClassName={$uploadingMedia ? 'spin' : ''}
label="Add media"
href={{$uploadingMedia ? '#fa-spinner' : '#fa-camera'}}
href={$uploadingMedia ? '#fa-spinner' : '#fa-camera'}
on:click="onMediaClick()"
disabled={{$uploadingMedia || (media.length === 4)}}
disabled={$uploadingMedia || (media.length === 4)}
/>
<IconButton
label="Adjust privacy (currently {{postPrivacy.label}})"
href={{postPrivacy.icon}}
label="Adjust privacy (currently {postPrivacy.label})"
href={postPrivacy.icon}
on:click="onPostPrivacyClick()"
/>
<IconButton
label={{contentWarningShown ? 'Remove content warning' : 'Add content warning'}}
label={contentWarningShown ? 'Remove content warning' : 'Add content warning'}
href="#fa-exclamation-triangle"
on:click="onContentWarningClick()"
pressable="true"
pressed={{contentWarningShown}}
pressed={contentWarningShown}
/>
</div>
<input ref:input
@ -30,7 +30,7 @@
style="display: none;"
type="file"
accept=".jpg,.jpeg,.png,.gif,.webm,.mp4,.m4v,image/jpeg,image/png,image/gif,video/webm,video/mp4">
<ComposeAutosuggest :realm :text />
<ComposeAutosuggest {realm} {text} />
</div>
<style>
.compose-box-toolbar {

View File

@ -1,10 +1,10 @@
<ModalDialog
:id
:label
:title
{id}
{label}
{title}
background="var(--main-bg)"
>
<GenericDialogList :items on:click="onClick(event)"/>
<GenericDialogList {items} on:click="onClick(event)"/>
</ModalDialog>
<script>
import ModalDialog from './ModalDialog.html'
@ -27,14 +27,14 @@ export default {
}),
computed: {
// begin account data copypasta
verifyCredentialsId: (verifyCredentials) => verifyCredentials.id,
following: (relationship) => relationship && relationship.following,
followRequested: (relationship) => relationship && relationship.requested,
accountId: (account) => account && account.id,
acct: (account) => account.acct,
muting: (relationship) => relationship.muting,
blocking: (relationship) => relationship.blocking,
followLabel: (following, followRequested, account, acct) => {
verifyCredentialsId: ({ verifyCredentials }) => verifyCredentials.id,
following: ({ relationship }) => relationship && relationship.following,
followRequested: ({ relationship }) => relationship && relationship.requested,
accountId: ({ account }) => account && account.id,
acct: ({ account }) => account.acct,
muting: ({ relationship }) => relationship.muting,
blocking: ({ relationship }) => relationship.blocking,
followLabel: ({ following, followRequested, account, acct }) => {
if (typeof following === 'undefined' || !account) {
return ''
}
@ -42,21 +42,21 @@ export default {
? `Unfollow @${acct}`
: `Follow @${acct}`
},
followIcon: (following, followRequested) => {
followIcon: ({ following, followRequested }) => {
return following ? '#fa-user-times' : followRequested ? '#fa-hourglass' : '#fa-user-plus'
},
blockLabel: (blocking, acct) => {
blockLabel: ({ blocking, acct }) => {
return blocking ? `Unblock @${acct}` : `Block @${acct}`
},
blockIcon: (blocking) => blocking ? '#fa-unlock' : '#fa-ban',
muteLabel: (muting, acct) => {
blockIcon: ({ blocking }) => blocking ? '#fa-unlock' : '#fa-ban',
muteLabel: ({ muting, acct }) => {
return muting ? `Unmute @${acct}` : `Mute @${acct}`
},
muteIcon: (muting) => muting ? '#fa-volume-up' : '#fa-volume-off',
muteIcon: ({ muting }) => muting ? '#fa-volume-up' : '#fa-volume-off',
// end account data copypasta
items: (blockLabel, blocking, blockIcon, muteLabel, muteIcon,
items: ({ blockLabel, blocking, blockIcon, muteLabel, muteIcon,
followLabel, followIcon, following, followRequested,
accountId, verifyCredentialsId, acct) => {
accountId, verifyCredentialsId, acct }) => {
let isUser = accountId === verifyCredentialsId
return [
!isUser && {

View File

@ -1,7 +1,7 @@
<ModalDialog
:id
:label
:title
{id}
{label}
{title}
background="var(--main-bg)"
>
<ComposeBox realm="dialog" size="slim" autoFocus="true" />

View File

@ -1,18 +1,18 @@
<ModalDialog
:id
:label
{id}
{label}
background="var(--main-bg)"
>
<form class="confirmation-dialog-form">
<p>
{{text}}
{text}
</p>
<div class="confirmation-dialog-form-flex">
<button type="button" on:click="onPositive()">
{{positiveText || 'OK'}}
{positiveText || 'OK'}
</button>
<button type="button" on:click="onNegative()">
{{negativeText || 'Cancel'}}
{negativeText || 'Cancel'}
</button>
</div>
</form>

View File

@ -1,26 +1,26 @@
<ModalDialog
:id
:label
:title
{id}
{label}
{title}
background="var(--main-bg)"
>
<div class="custom-emoji-container">
{{#if emojis.length}}
{#if emojis.length}
<ul class="custom-emoji-list">
{{#each emojis as emoji}}
{#each emojis as emoji}
<li class="custom-emoji">
<button type="button" on:click="onClickEmoji(emoji)">
<img src={{$autoplayGifs ? emoji.url : emoji.static_url}}
alt=":{{emoji.shortcode}}:"
title=":{{emoji.shortcode}}:"
<img src={$autoplayGifs ? emoji.url : emoji.static_url}
alt=":{emoji.shortcode}:"
title=":{emoji.shortcode}:"
/>
</button>
</li>
{{/each}}
{/each}
</ul>
{{else}}
{:else}
<div class="custom-emoji-no-emoji">No custom emoji found for this instance.</div>
{{/if}}
{/if}
</div>
</ModalDialog>
<style>
@ -71,7 +71,7 @@
},
store: () => store,
computed: {
emojis: ($currentCustomEmoji) => {
emojis: ({ $currentCustomEmoji }) => {
if (!$currentCustomEmoji) {
return []
}

View File

@ -1,19 +1,19 @@
<ul class="generic-dialog-list">
{{#each items as item @key}}
{#each items as item (item.key)}
<li class="generic-dialog-list-item">
<button class="generic-dialog-list-button" on:click="fire('click', item)">
<svg class="generic-dialog-list-item-svg">
<use xlink:href={{item.icon}} />
<use xlink:href={item.icon} />
</svg>
<span>
{{item.label}}
{item.label}
</span>
<svg class="generic-dialog-list-item-svg {{item.selected ? '' : 'hidden'}}" aria-hidden={{!item.selected}}>
<svg class="generic-dialog-list-item-svg {item.selected ? '' : 'hidden'}" aria-hidden={!item.selected}>
<use xlink:href="#fa-check" />
</svg>
</button>
</li>
{{/each}}
{/each}
</ul>
<style>
.generic-dialog-list {

View File

@ -1,27 +1,27 @@
<ModalDialog
:id
:label
{id}
{label}
background="var(--muted-modal-bg)"
muted="true"
className="image-modal-dialog"
>
{{#if type === 'gifv'}}
{#if type === 'gifv'}
<AutoplayVideo
ariaLabel="Animated GIF: {{description || ''}}"
:poster
:src
:width
:height
ariaLabel="Animated GIF: {description || ''}"
{poster}
{src}
{width}
{height}
/>
{{else}}
{:else}
<img
:src
:width
:height
alt={{description || ''}}
title={{description || ''}}
{src}
{width}
{height}
alt={description || ''}
title={description || ''}
/>
{{/if}}
{/if}
</ModalDialog>
<style>
:global(.image-modal-dialog img, .image-modal-dialog video) {

View File

@ -1,17 +1,17 @@
<div class={{backdropClass}}
<div class={backdropClass}
tabindex="-1"
data-a11y-dialog-hide
></div>
<div class={{contentsClass}}
<div class={contentsClass}
role="dialog"
aria-label={{label || ''}}
aria-label={label || ''}
ref:node
>
<div class="modal-dialog-document" role="document" style="background: {{background || '#000'}};">
<div class="modal-dialog-document" role="document" style="background: {background || '#000'};">
<div class="modal-dialog-header">
{{#if title}}
<h1 class="modal-dialog-title">{{title}}</h1>
{{/if}}
{#if title}
<h1 class="modal-dialog-title">{title}</h1>
{/if}
<div class="close-dialog-button-wrapper">
<button class="close-dialog-button"
data-a11y-dialog-hide aria-label="Close dialog">
@ -148,14 +148,14 @@
title: void 0
}),
computed: {
backdropClass: (fadedIn, shouldAnimate) => {
backdropClass: ({ fadedIn, shouldAnimate }) => {
return classname(
'modal-dialog-backdrop',
!fadedIn && 'hidden',
shouldAnimate && 'should-animate'
)
},
contentsClass: (fadedIn, muted, shouldAnimate, className) => {
contentsClass: ({ fadedIn, muted, shouldAnimate, className }) => {
return classname(
'modal-dialog-contents',
!fadedIn && 'hidden',

View File

@ -1,10 +1,10 @@
<ModalDialog
:id
:label
:title
{id}
{label}
{title}
background="var(--main-bg)"
>
<GenericDialogList :items on:click="onClick(event)" />
<GenericDialogList {items} on:click="onClick(event)" />
</ModalDialog>
<script>
import ModalDialog from './ModalDialog.html'
@ -36,14 +36,14 @@
}
},
computed: {
composeData: ($currentComposeData, realm) => $currentComposeData[realm] || {},
postPrivacy: (postPrivacyKey) => {
composeData: ({ $currentComposeData, realm }) => $currentComposeData[realm] || {},
postPrivacy: ({ postPrivacyKey }) => {
return POST_PRIVACY_OPTIONS.find(_ => _.key === postPrivacyKey)
},
postPrivacyKey: (composeData, $currentVerifyCredentials) => {
postPrivacyKey: ({ composeData, $currentVerifyCredentials }) => {
return composeData.postPrivacy || $currentVerifyCredentials.source.privacy
},
items: (postPrivacy, postPrivacyOptions) => {
items: ({ postPrivacy, postPrivacyOptions }) => {
return postPrivacyOptions.map(option => ({
key: option.key,
label: option.label,

View File

@ -1,10 +1,10 @@
<ModalDialog
:id
:label
:title
{id}
{label}
{title}
background="var(--main-bg)"
>
<GenericDialogList :items on:click="onClick(event)"/>
<GenericDialogList {items} on:click="onClick(event)"/>
</ModalDialog>
<script>
import ModalDialog from './ModalDialog.html'
@ -22,20 +22,20 @@ import { setStatusPinnedOrUnpinned } from '../../../_actions/pin'
export default {
oncreate,
computed: {
relationship: ($currentAccountRelationship) => $currentAccountRelationship,
account: ($currentAccountProfile) => $currentAccountProfile,
verifyCredentials: ($currentVerifyCredentials) => $currentVerifyCredentials,
statusId: (status) => status.id,
pinned: (status) => status.pinned,
relationship: ({ $currentAccountRelationship }) => $currentAccountRelationship,
account: ({ $currentAccountProfile }) => $currentAccountProfile,
verifyCredentials: ({ $currentVerifyCredentials }) => $currentVerifyCredentials,
statusId: ({ status }) => status.id,
pinned: ({ status }) => status.pinned,
// begin account data copypasta
verifyCredentialsId: (verifyCredentials) => verifyCredentials.id,
following: (relationship) => relationship && relationship.following,
followRequested: (relationship) => relationship && relationship.requested,
accountId: (account) => account && account.id,
acct: (account) => account.acct,
muting: (relationship) => relationship.muting,
blocking: (relationship) => relationship.blocking,
followLabel: (following, followRequested, account, acct) => {
verifyCredentialsId: ({ verifyCredentials }) => verifyCredentials.id,
following: ({ relationship }) => relationship && relationship.following,
followRequested: ({ relationship }) => relationship && relationship.requested,
accountId: ({ account }) => account && account.id,
acct: ({ account }) => account.acct,
muting: ({ relationship }) => relationship.muting,
blocking: ({ relationship }) => relationship.blocking,
followLabel: ({ following, followRequested, account, acct }) => {
if (typeof following === 'undefined' || !account) {
return ''
}
@ -43,22 +43,22 @@ export default {
? `Unfollow @${acct}`
: `Follow @${acct}`
},
followIcon: (following, followRequested) => {
followIcon: ({ following, followRequested }) => {
return following ? '#fa-user-times' : followRequested ? '#fa-hourglass' : '#fa-user-plus'
},
blockLabel: (blocking, acct) => {
blockLabel: ({ blocking, acct }) => {
return blocking ? `Unblock @${acct}` : `Block @${acct}`
},
blockIcon: (blocking) => blocking ? '#fa-unlock' : '#fa-ban',
muteLabel: (muting, acct) => {
blockIcon: ({ blocking }) => blocking ? '#fa-unlock' : '#fa-ban',
muteLabel: ({ muting, acct }) => {
return muting ? `Unmute @${acct}` : `Mute @${acct}`
},
muteIcon: (muting) => muting ? '#fa-volume-up' : '#fa-volume-off',
muteIcon: ({ muting }) => muting ? '#fa-volume-up' : '#fa-volume-off',
// end account data copypasta
isUser: (accountId, verifyCredentialsId) => accountId === verifyCredentialsId,
pinLabel: (pinned, isUser) => isUser ? (pinned ? 'Unpin from profile' : 'Pin to profile') : '',
items: (blockLabel, blocking, blockIcon, muteLabel, muteIcon, followLabel, followIcon,
following, followRequested, pinLabel, isUser) => {
isUser: ({ accountId, verifyCredentialsId }) => accountId === verifyCredentialsId,
pinLabel: ({ pinned, isUser }) => isUser ? (pinned ? 'Unpin from profile' : 'Pin to profile') : '',
items: ({ blockLabel, blocking, blockIcon, muteLabel, muteIcon, followLabel, followIcon,
following, followRequested, pinLabel, isUser }) => {
return [
isUser && {
key: 'delete',

View File

@ -1,15 +1,15 @@
<ModalDialog
:id
:label
{id}
{label}
background="var(--muted-modal-bg)"
muted="true"
className="video-modal-dialog"
>
<video :poster
:src
:width
:height
aria-label="Video: {{description || ''}}"
<video {poster}
{src}
{width}
{height}
aria-label="Video: {description || ''}"
controls
/>
</ModalDialog>

View File

@ -1,11 +1,11 @@
<div class="account-profile {{headerImageIsMissing ? 'header-image-is-missing' : ''}}"
style="background-image: url({{headerImage}});">
<div class="account-profile {headerImageIsMissing ? 'header-image-is-missing' : ''}"
style="background-image: url({headerImage});">
<div class="account-profile-grid-wrapper">
<div class="account-profile-grid">
<AccountProfileHeader :account :relationship :verifyCredentials />
<AccountProfileFollow :account :relationship :verifyCredentials />
<AccountProfileNote :account />
<AccountProfileDetails :account :relationship :verifyCredentials />
<AccountProfileHeader {account} {relationship} {verifyCredentials} />
<AccountProfileFollow {account} {relationship} {verifyCredentials} />
<AccountProfileNote {account} />
<AccountProfileDetails {account} {relationship} {verifyCredentials} />
</div>
</div>
</div>
@ -73,8 +73,8 @@
export default {
store: () => store,
computed: {
headerImageIsMissing: (account) => account.header.endsWith('missing.png'),
headerImage: ($autoplayGifs, account) => $autoplayGifs ? account.header : account.header_static
headerImageIsMissing: ({ account }) => account.header.endsWith('missing.png'),
headerImage: ({ $autoplayGifs, account }) => $autoplayGifs ? account.header : account.header_static
},
components: {
AccountProfileHeader,

View File

@ -4,33 +4,33 @@
Toots
</span>
<span class="account-profile-details-item-datum">
{{numStatusesDisplay}}
{numStatusesDisplay}
</span>
</div>
<a class="account-profile-details-item"
href='/accounts/{{account.id}}/follows'
aria-label={{followingLabel}}
href='/accounts/{account.id}/follows'
aria-label={followingLabel}
>
<span class="account-profile-details-item-title">
Follows
</span>
<span class="account-profile-details-item-datum">
{{numFollowingDisplay}}
{numFollowingDisplay}
</span>
</a>
<a class="account-profile-details-item"
href='/accounts/{{account.id}}/followers'
aria-label={{followersLabel}}
href='/accounts/{account.id}/followers'
aria-label={followersLabel}
>
<span class="account-profile-details-item-title">
Followers
</span>
<span class="account-profile-details-item-datum">
{{numFollowersDisplay}}
{numFollowersDisplay}
</span>
</a>
<!-- TODO: re-enable this when we support profile editing -->
{{#if account && verifyCredentials && account.id !== verifyCredentials.id}}
{#if account && verifyCredentials && account.id !== verifyCredentials.id}
<div class="account-profile-more-options">
<IconButton
label="More options"
@ -39,7 +39,7 @@
on:click="onMoreOptionsClick()"
/>
</div>
{{/if}}
{/if}
</div>
<style>
.account-profile-details {
@ -119,14 +119,14 @@
export default {
computed: {
numStatuses: account => account.statuses_count || 0,
numFollowing: account => account.following_count || 0,
numFollowers: account => account.followers_count || 0,
numStatusesDisplay: numStatuses => numberFormat.format(numStatuses),
numFollowingDisplay: numFollowing => numberFormat.format(numFollowing),
numFollowersDisplay: numFollowers => numberFormat.format(numFollowers),
followersLabel: numFollowers => `Followed by ${numFollowers}`,
followingLabel: numFollowing => `Follows ${numFollowing}`
numStatuses: ({ account }) => account.statuses_count || 0,
numFollowing: ({ account }) => account.following_count || 0,
numFollowers: ({ account }) => account.followers_count || 0,
numStatusesDisplay: ({ numStatuses }) => numberFormat.format(numStatuses),
numFollowingDisplay: ({ numFollowing }) => numberFormat.format(numFollowing),
numFollowersDisplay: ({ numFollowers }) => numberFormat.format(numFollowers),
followersLabel: ({ numFollowers }) => `Followed by ${numFollowers}`,
followingLabel: ({ numFollowing }) => `Follows ${numFollowing}`
},
methods: {
async onMoreOptionsClick () {

View File

@ -1,9 +1,9 @@
<div class="account-profile-follow {{shown ? 'shown' : ''}}">
<div class="account-profile-follow {shown ? 'shown' : ''}">
<IconButton
label={{followLabel}}
href={{followIcon}}
label={followLabel}
href={followIcon}
pressable="true"
pressed={{following}}
pressed={following}
big="true"
on:click="onFollowButtonClick(event)"
ref:icon
@ -57,18 +57,18 @@
overrideFollowing: void 0
}),
computed: {
accountId: (account) => account.id,
following: (relationship, overrideFollowing) => {
accountId: ({ account }) => account.id,
following: ({ relationship, overrideFollowing }) => {
if (typeof overrideFollowing === 'boolean') {
return overrideFollowing
}
return relationship && relationship.following
},
blocking: (relationship) => relationship && relationship.blocking,
followRequested: (relationship, account) => {
blocking: ({ relationship }) => relationship && relationship.blocking,
followRequested: ({ relationship, account }) => {
return relationship && relationship.requested && account && account.locked
},
followLabel: (blocking, following, followRequested) => {
followLabel: ({ blocking, following, followRequested }) => {
if (blocking) {
return 'Unblock'
} else if (following) {
@ -79,7 +79,7 @@
return 'Follow'
}
},
followIcon: (blocking, following, followRequested) => {
followIcon: ({ blocking, following, followRequested }) => {
if (blocking) {
return '#fa-unlock'
} else if (following) {
@ -90,7 +90,7 @@
return '#fa-user-plus'
}
},
shown: (verifyCredentials, relationship) => {
shown: ({ verifyCredentials, relationship }) => {
return verifyCredentials && relationship && verifyCredentials.id !== relationship.id
}
},

View File

@ -1,24 +1,24 @@
<div class="account-profile-avatar">
<Avatar :account size="big" />
<Avatar {account} size="big" />
</div>
<div class="account-profile-name">
<ExternalLink href={{account.url}}
<ExternalLink href={account.url}
showIcon="true"
normalIconColor="true"
ariaLabel="{{account.display_name || account.acct}} (opens in new window)"
ariaLabel="{account.display_name || account.acct} (opens in new window)"
>
{{account.display_name || account.acct}}
{account.display_name || account.acct}
</ExternalLink>
</div>
<div class="account-profile-username">
{{'@' + account.acct}}
{'@' + account.acct}
</div>
<div class="account-profile-followed-by">
{{#if relationship && relationship.blocking}}
{#if relationship && relationship.blocking}
<span class="account-profile-followed-by-span">Blocked</span>
{{elseif relationship && relationship.followed_by}}
{:elseif relationship && relationship.followed_by}
<span class="account-profile-followed-by-span">Follows you</span>
{{/if}}
{/if}
</div>
<style>
.account-profile-followed-by {

View File

@ -1,5 +1,5 @@
<div class="account-profile-note">
{{{massagedNote}}}
{@html massagedNote}
</div>
<style>
.account-profile-note {
@ -32,8 +32,8 @@
<script>
export default {
computed: {
note: (account) => account.note,
massagedNote: (note) => {
note: ({ account }) => account.note,
massagedNote: ({ note }) => {
// GNU Social / Pleroma don't add <p> tags
if (!note.startsWith('<p>')) {
note = `<p>${note}</p>`

View File

@ -1,17 +1,17 @@
<div class="pseudo-virtual-list" on:initialized ref:node>
{{#each wrappedItems as wrappedItem, i @item}}
{#each wrappedItems as wrappedItem, i (wrappedItem.item)}
<PseudoVirtualListLazyItem
:component
index={{i}}
length={{wrappedItems.length}}
:makeProps
key={{wrappedItem.item}}
:intersectionObserver
isIntersecting={{isIntersecting(wrappedItem.item, $intersectionStates)}}
isCached={{isCached(wrappedItem.item, $intersectionStates)}}
height={{getHeight(wrappedItem.item, $intersectionStates)}}
{component}
index={i}
length={wrappedItems.length}
{makeProps}
key={wrappedItem.item}
{intersectionObserver}
isIntersecting={isIntersecting(wrappedItem.item, $intersectionStates)}
isCached={isCached(wrappedItem.item, $intersectionStates)}
height={getHeight(wrappedItem.item, $intersectionStates)}
/>
{{/each}}
{/each}
</div>
<style>
.pseudo-virtual-list {
@ -110,8 +110,8 @@
}
},
computed: {
wrappedItems: (items) => items ? items.map(item => ({item})) : [],
allItemsHaveHeight: (items, $intersectionStates) => {
wrappedItems: ({ items }) => items ? items.map(item => ({item})) : [],
allItemsHaveHeight: ({ items, $intersectionStates }) => {
if (!items) {
return false
}

View File

@ -1,15 +1,15 @@
<div class="pseudo-virtual-list-item"
aria-hidden={{hide}}
pseudo-virtual-list-key={{key}}
style="height: {{shouldHide ? `${height}px` : ''}};"
aria-hidden={hide}
pseudo-virtual-list-key={key}
style="height: {shouldHide ? `${height}px` : ''};"
ref:node>
{{#if !shouldHide}}
<:Component {component}
virtualProps={{props}}
virtualIndex={{index}}
virtualLength={{length}}
{#if !shouldHide}
<svelte:component this={component}
virtualProps={props}
virtualIndex={index}
virtualLength={length}
/>
{{/if}}
{/if}
</div>
<script>
import { scheduleIdleTask } from '../../_utils/scheduleIdleTask'
@ -43,7 +43,7 @@
hide: false
}),
computed: {
shouldHide: (isIntersecting, isCached, hide) => {
shouldHide: ({ isIntersecting, isCached, hide }) => {
if (isCached) {
return true // if it's cached, always unrender immediately until proven it's intersecting
}

View File

@ -1,16 +1,16 @@
{{#if props}}
<PseudoVirtualListItem :component
:props
:key
:index
:length
:intersectionObserver
:isIntersecting
:isCached
:height
{#if props}
<PseudoVirtualListItem {component}
{props}
{key}
{index}
{length}
{intersectionObserver}
{isIntersecting}
{isCached}
{height}
on:scrollToPosition
/>
{{/if}}
{/if}
<script>
import PseudoVirtualListItem from './PseudoVirtualListItem.html'
import { mark, stop } from '../../_utils/marks'

View File

@ -1,24 +1,24 @@
<SearchResult href="/accounts/{{account.id}}">
<SearchResult href="/accounts/{account.id}">
<div class="search-result-account">
<Avatar :account size="small" className="search-result-account-avatar"/>
<Avatar {account} size="small" className="search-result-account-avatar"/>
<div class="search-result-account-name">
{{account.display_name || account.acct}}
{account.display_name || account.acct}
</div>
<div class="search-result-account-username">
{{'@' + account.acct}}
{'@' + account.acct}
</div>
{{#if actions && actions.length}}
{#if actions && actions.length}
<div class="search-result-account-buttons">
{{#each actions as action}}
{#each actions as action}
<IconButton
label={{action.label}}
label={action.label}
on:click="onButtonClick(event, action, account.id)"
href={{action.icon}}
href={action.icon}
big="true"
/>
{{/each}}
{/each}
</div>
{{/if}}
{/if}
</div>
</SearchResult>
<style>

View File

@ -1,5 +1,5 @@
<SearchResult href="/tags/{{hashtag}}">
{{'#' + hashtag}}
<SearchResult href="/tags/{hashtag}">
{'#' + hashtag}
</SearchResult>
<style>
</style>

View File

@ -7,21 +7,21 @@
required
bind:value="$queryInSearch">
</div>
<button type="submit" class="primary search-button" aria-label="Search" disabled={{$searchLoading}}>
<button type="submit" class="primary search-button" aria-label="Search" disabled={$searchLoading}>
<svg class="search-button-svg">
<use xlink:href="#fa-search" />
</svg>
</button>
</form>
{{#if $searchLoading}}
{#if $searchLoading}
<div class="search-results-container">
<LoadingPage />
</div>
{{elseif $searchResults && $searchResultsForQuery === $queryInSearch}}
{:elseif $searchResults && $searchResultsForQuery === $queryInSearch}
<div class="search-results-container">
<SearchResults />
</div>
{{/if}}
{/if}
<style>
.search-input-form {
display: grid;

View File

@ -1,5 +1,5 @@
<li class="search-result">
<a :href class="search-result-anchor">
<a {href} class="search-result-anchor">
<slot></slot>
</a>
</li>

View File

@ -1,13 +1,13 @@
<ul class="search-results">
{{#each $searchResults.hashtags as hashtag}}
<HashtagSearchResult :hashtag />
{{/each}}
{{#each $searchResults.accounts as account}}
<AccountSearchResult :account />
{{/each}}
{{#each $searchResults.statuses as status, index}}
<StatusSearchResult :status :index length={{$searchResults.statuses.length}}/>
{{/each}}
{#each $searchResults.hashtags as hashtag}
<HashtagSearchResult {hashtag} />
{/each}
{#each $searchResults.accounts as account}
<AccountSearchResult {account} />
{/each}
{#each $searchResults.statuses as status, index}
<StatusSearchResult {status} {index} length={$searchResults.statuses.length}/>
{/each}
</ul>
<style>
.search-results {

View File

@ -1,7 +1,7 @@
<SearchResult href="/statuses/{{status.id}}">
<Status :index :length
<SearchResult href="/statuses/{status.id}">
<Status {index} {length}
timelineType="search" timelineValue="search"
:status />
{status} />
</SearchResult>
<style>
</style>

View File

@ -1,4 +1,4 @@
<SettingsNav :page :label/>
<SettingsNav {page} {label}/>
<div class="settings">
<FreeTextLayout>

View File

@ -1,13 +1,13 @@
<div class="settings-list-wrapper">
{{#if label}}
<ul class="settings-list" aria-label={{label}}>
{#if label}
<ul class="settings-list" aria-label={label}>
<slot></slot>
</ul>
{{else}}
{:else}
<ul class="settings-list">
<slot></slot>
</ul>
{{/if}}
{/if}
</div>
<style>
.settings-list-wrapper {

View File

@ -1,12 +1,12 @@
<li class="settings-list-item">
<a :href>
{{#if icon}}
<a {href}>
{#if icon}
<svg class="settings-list-item-svg">
<use xlink:href={{icon}} />
<use xlink:href={icon} />
</svg>
{{/if}}
<span aria-label={{ariaLabel || label}} class={{offsetForIcon ? 'offset-for-icon' : ''}}>
{{label}}
{/if}
<span aria-label={ariaLabel || label} class={offsetForIcon ? 'offset-for-icon' : ''}>
{label}
</span>
</a>
</li>

View File

@ -1,12 +1,12 @@
<nav class="settings-nav">
<ul>
{{#each navItems as navItem}}
{#each navItems as navItem}
<li>
<SettingsNavItem :page name={{navItem.name}} href={{navItem.href}} label={{navItem.label}} />
<SettingsNavItem {page} name={navItem.name} href={navItem.href} label={navItem.label} />
</li>
{{/each}}
{/each}
<li>
<SettingsNavItem :page name={{page}} href="/{{page}}" :label />
<SettingsNavItem {page} name={page} href="/{page}" {label} />
</li>
</ul>
</nav>
@ -53,7 +53,7 @@
SettingsNavItem
},
computed: {
navItems: page => {
navItems: ({ page }) => {
let res = []
let breadcrumbs = page.split('/')
let path = ''

View File

@ -1,7 +1,7 @@
<a class="settings-nav-item {{className}}"
aria-label={{ariaLabel}}
:href >
{{label}}
<a class="settings-nav-item {className}"
aria-label={ariaLabel}
{href} >
{label}
</a>
<style>
a.settings-nav-item {
@ -15,8 +15,8 @@
<script>
export default {
computed: {
className: (page, name) => page === name ? 'selected' : '',
ariaLabel: (page, name, label) => page === name ? `${label} (current page)` : label
className: ({ page, name }) => page === name ? 'selected' : '',
ariaLabel: ({ page, name, label }) => page === name ? `${label} (current page)` : label
}
}
</script>

View File

@ -1,64 +1,64 @@
{{#if type === 'video'}}
{#if type === 'video'}
<button type="button"
class="play-video-button"
aria-label="Play video: {{description}}"
delegate-key={{delegateKey}}
style="width: {{inlineWidth}}px; height: {{inlineHeight}}px;">
aria-label="Play video: {description}"
delegate-key={delegateKey}
style="width: {inlineWidth}px; height: {inlineHeight}px;">
<PlayVideoIcon />
<LazyImage
alt={{description}}
title={{description}}
src={{previewUrl}}
fallback={{oneTransparentPixel}}
width={{inlineWidth}}
height={{inlineHeight}}
alt={description}
title={description}
src={previewUrl}
fallback={oneTransparentPixel}
width={inlineWidth}
height={inlineHeight}
background="var(--loading-bg)"
className={{noNativeWidthHeight ? 'no-native-width-height' : ''}}
className={noNativeWidthHeight ? 'no-native-width-height' : ''}
/>
</button>
{{else}}
{:else}
<button type="button"
class="show-image-button"
aria-label="Show image: {{description}}"
title={{description}}
delegate-key={{delegateKey}}
aria-label="Show image: {description}"
title={description}
delegate-key={delegateKey}
on:mouseover="set({mouseover: event})"
style="width: {{inlineWidth}}px; height: {{inlineHeight}}px;"
style="width: {inlineWidth}px; height: {inlineHeight}px;"
>
{{#if type === 'gifv' && $autoplayGifs}}
{#if type === 'gifv' && $autoplayGifs}
<AutoplayVideo
className={{noNativeWidthHeight ? 'no-native-width-height' : ''}}
ariaLabel="Animated GIF: {{description}}"
poster={{previewUrl}}
src={{url}}
width={{inlineWidth}}
height={{inlineHeight}}
className={noNativeWidthHeight ? 'no-native-width-height' : ''}
ariaLabel="Animated GIF: {description}"
poster={previewUrl}
src={url}
width={inlineWidth}
height={inlineHeight}
/>
{{elseif type === 'gifv' && !$autoplayGifs}}
{:elseif type === 'gifv' && !$autoplayGifs}
<NonAutoplayGifv
class={{noNativeWidthHeight ? 'no-native-width-height' : ''}}
label="Animated GIF: {{description}}"
poster={{previewUrl}}
src={{url}}
staticSrc={{previewUrl}}
width={{inlineWidth}}
height={{inlineHeight}}
playing={{mouseover}}
class={noNativeWidthHeight ? 'no-native-width-height' : ''}
label="Animated GIF: {description}"
poster={previewUrl}
src={url}
staticSrc={previewUrl}
width={inlineWidth}
height={inlineHeight}
playing={mouseover}
/>
{{else}}
{:else}
<LazyImage
alt={{description}}
title={{description}}
src={{previewUrl}}
fallback={{oneTransparentPixel}}
width={{inlineWidth}}
height={{inlineHeight}}
alt={description}
title={description}
src={previewUrl}
fallback={oneTransparentPixel}
width={inlineWidth}
height={inlineHeight}
background="var(--loading-bg)"
className={{noNativeWidthHeight ? 'no-native-width-height' : ''}}
className={noNativeWidthHeight ? 'no-native-width-height' : ''}
/>
{{/if}}
{/if}
</button>
{{/if}}
{/if}
<style>
:global(.status-media video, .status-media img) {
object-fit: cover;
@ -121,24 +121,24 @@
},
computed: {
// width/height to show inline
inlineWidth: smallWidth => smallWidth || DEFAULT_MEDIA_WIDTH,
inlineHeight: smallHeight => smallHeight || DEFAULT_MEDIA_HEIGHT,
inlineWidth: ({ smallWidth }) => smallWidth || DEFAULT_MEDIA_WIDTH,
inlineHeight: ({ smallHeight }) => smallHeight || DEFAULT_MEDIA_HEIGHT,
// width/height to show in a modal
modalWidth: (originalWidth, inlineWidth) => originalWidth || inlineWidth,
modalHeight: (originalHeight, inlineHeight) => originalHeight || inlineHeight,
meta: media => media.meta,
small: meta => meta && meta.small,
original: meta => meta && meta.original,
smallWidth: small => small && small.width,
smallHeight: small => small && small.height,
originalWidth: original => original && original.width,
originalHeight: original => original && original.height,
noNativeWidthHeight: (smallWidth, smallHeight) => typeof smallWidth !== 'number' || typeof smallHeight !== 'number',
delegateKey: (media, uuid) => `media-${uuid}-${media.id}`,
description: (media) => media.description || '',
previewUrl: (media) => media.preview_url,
url: (media) => media.url,
type: (media) => media.type
modalWidth: ({ originalWidth, inlineWidth }) => originalWidth || inlineWidth,
modalHeight: ({ originalHeight, inlineHeight }) => originalHeight || inlineHeight,
meta: ({ media }) => media.meta,
small: ({ meta }) => meta && meta.small,
original: ({ meta }) => meta && meta.original,
smallWidth: ({ small }) => small && small.width,
smallHeight: ({ small }) => small && small.height,
originalWidth: ({ original }) => original && original.width,
originalHeight: ({ original }) => original && original.height,
noNativeWidthHeight: ({ smallWidth, smallHeight }) => typeof smallWidth !== 'number' || typeof smallHeight !== 'number',
delegateKey: ({ media, uuid }) => `media-${uuid}-${media.id}`,
description: ({ media }) => media.description || '',
previewUrl: ({ media }) => media.preview_url,
url: ({ media }) => media.url,
type: ({ media }) => media.type
},
methods: {
async onClickPlayVideoButton () {

View File

@ -1,8 +1,8 @@
<div class="status-media {{sensitive ? 'status-media-is-sensitive' : ''}}"
style="grid-template-columns: repeat(auto-fit, minmax({{maxMediaWidth}}px, 1fr));" >
{{#each mediaAttachments as media}}
<Media :media :uuid />
{{/each}}
<div class="status-media {sensitive ? 'status-media-is-sensitive' : ''}"
style="grid-template-columns: repeat(auto-fit, minmax({maxMediaWidth}px, 1fr));" >
{#each mediaAttachments as media}
<Media {media} {uuid} />
{/each}
</div>
<style>
.status-media {
@ -36,7 +36,7 @@
export default {
computed: {
maxMediaWidth: (mediaAttachments) => {
maxMediaWidth: ({ mediaAttachments }) => {
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
}))

View File

@ -1,16 +1,16 @@
{{#if status}}
<Status :index :length :timelineType :timelineValue :focusSelector
:status :notification on:recalculateHeight
{#if status}
<Status {index} {length} {timelineType} {timelineValue} {focusSelector}
{status} {notification} on:recalculateHeight
/>
{{else}}
{:else}
<article class="notification-article"
tabindex="0"
aria-posinset={{index}}
aria-setsize={{length}} >
<StatusHeader :notification :notificationId :status :statusId :timelineType
:account :accountId :uuid isStatusInNotification="true" />
aria-posinset={index}
aria-setsize={length} >
<StatusHeader {notification} {notificationId} {status} {statusId} {timelineType}
{account} {accountId} {uuid} isStatusInNotification="true" />
</article>
{{/if}}
{/if}
<style>
.notification-article {
width: 560px;
@ -38,12 +38,12 @@
},
store: () => store,
computed: {
account: (notification) => notification.account,
accountId: (account) => account.id,
notificationId: (notification) => notification.id,
status: (notification) => notification.status,
statusId: (status) => status && status.id,
uuid: ($currentInstance, timelineType, timelineValue, notificationId, statusId) => {
account: ({ notification }) => notification.account,
accountId: ({ account }) => account.id,
notificationId: ({ notification }) => notification.id,
status: ({ notification }) => notification.status,
statusId: ({ status }) => status && status.id,
uuid: ({ $currentInstance, timelineType, timelineValue, notificationId, statusId }) => {
return `${$currentInstance}/${timelineType}/${timelineValue}/${notificationId}/${statusId || ''}`
}
}

View File

@ -1,36 +1,36 @@
<article class={{className}}
<article class={className}
tabindex="0"
delegate-key={{delegateKey}}
focus-key={{delegateKey}}
aria-posinset={{index}}
aria-setsize={{length}}
aria-label={{ariaLabel}}
delegate-key={delegateKey}
focus-key={delegateKey}
aria-posinset={index}
aria-setsize={length}
aria-label={ariaLabel}
on:recalculateHeight>
{{#if showHeader}}
<StatusHeader {{...params}} />
{{/if}}
<StatusAuthorName {{...params}} />
<StatusAuthorHandle {{...params}} />
{{#if !isStatusInOwnThread}}
<StatusRelativeDate {{...params}} />
{{/if}}
<StatusSidebar {{...params}} />
{{#if spoilerText}}
<StatusSpoiler {{...params}} on:recalculateHeight />
{{/if}}
{{#if showContent || contentPreloaded}}
<StatusContent {{...params}} shown={{showContent}}/>
{{/if}}
{{#if showMedia }}
<StatusMediaAttachments {{...params}} on:recalculateHeight />
{{/if}}
{{#if isStatusInOwnThread}}
<StatusDetails {{...params}} />
{{/if}}
<StatusToolbar {{...params}} on:recalculateHeight />
{{#if replyShown}}
<StatusComposeBox {{...params}} on:recalculateHeight />
{{/if}}
{#if showHeader}
<StatusHeader {...params} />
{/if}
<StatusAuthorName {...params} />
<StatusAuthorHandle {...params} />
{#if !isStatusInOwnThread}
<StatusRelativeDate {...params} />
{/if}
<StatusSidebar {...params} />
{#if spoilerText}
<StatusSpoiler {...params} on:recalculateHeight />
{/if}
{#if showContent || contentPreloaded}
<StatusContent {...params} shown={showContent}/>
{/if}
{#if showMedia }
<StatusMediaAttachments {...params} on:recalculateHeight />
{/if}
{#if isStatusInOwnThread}
<StatusDetails {...params} />
{/if}
<StatusToolbar {...params} on:recalculateHeight />
{#if replyShown}
<StatusComposeBox {...params} on:recalculateHeight />
{/if}
</article>
<style>
@ -170,56 +170,56 @@
}
},
computed: {
originalStatus: (status) => status.reblog ? status.reblog : status,
originalStatusId: (originalStatus) => originalStatus.id,
statusId: (status) => status.id,
notificationId: (notification) => notification && notification.id,
account: (notification, status) => (
originalStatus: ({ status }) => status.reblog ? status.reblog : status,
originalStatusId: ({ originalStatus }) => originalStatus.id,
statusId: ({ status }) => status.id,
notificationId: ({ notification }) => notification && notification.id,
account: ({ notification, status }) => (
(notification && notification.account) || status.account
),
accountId: (account) => account.id,
originalAccount: (originalStatus) => originalStatus.account,
originalAccountId: (originalAccount) => originalAccount.id,
visibility: (originalStatus) => originalStatus.visibility,
spoilerText: (originalStatus) => originalStatus.spoiler_text,
uuid: ($currentInstance, timelineType, timelineValue, notificationId, statusId) => (
accountId: ({ account }) => account.id,
originalAccount: ({ originalStatus }) => originalStatus.account,
originalAccountId: ({ originalAccount }) => originalAccount.id,
visibility: ({ originalStatus }) => originalStatus.visibility,
spoilerText: ({ originalStatus }) => originalStatus.spoiler_text,
uuid: ({ $currentInstance, timelineType, timelineValue, notificationId, statusId }) => (
`${$currentInstance}/${timelineType}/${timelineValue}/${notificationId || ''}/${statusId}`
),
delegateKey: (uuid) => `status-${uuid}`,
isStatusInOwnThread: (timelineType, timelineValue, originalStatusId) => (
delegateKey: ({ uuid }) => `status-${uuid}`,
isStatusInOwnThread: ({ timelineType, timelineValue, originalStatusId }) => (
(timelineType === 'status' || timelineType === 'reply') && timelineValue === originalStatusId
),
isStatusInNotification: (originalStatusId, notification) => (
isStatusInNotification: ({ originalStatusId, notification }) => (
notification && notification.status &&
notification.type !== 'mention' && notification.status.id === originalStatusId
),
spoilerShown: ($spoilersShown, uuid) => !!$spoilersShown[uuid],
replyShown: ($repliesShown, uuid) => !!$repliesShown[uuid],
showMedia: (originalStatus, isStatusInNotification) => (
spoilerShown: ({ $spoilersShown, uuid }) => !!$spoilersShown[uuid],
replyShown: ({ $repliesShown, uuid }) => !!$repliesShown[uuid],
showMedia: ({ originalStatus, isStatusInNotification }) => (
!isStatusInNotification &&
originalStatus.media_attachments &&
originalStatus.media_attachments.length
),
ariaLabel: (originalAccount, originalStatus, visibility) => (
ariaLabel: ({ originalAccount, originalStatus, visibility }) => (
(visibility === 'direct' ? 'Direct message' : 'Status') +
` by ${originalAccount.display_name || originalAccount.username}`
),
showHeader: (notification, status, timelineType) => (
showHeader: ({ notification, status, timelineType }) => (
(notification && (notification.type === 'reblog' || notification.type === 'favourite')) ||
status.reblog ||
timelineType === 'pinned'
),
className: (visibility, timelineType, isStatusInOwnThread) => (classname(
className: ({ visibility, timelineType, isStatusInOwnThread }) => (classname(
'status-article',
visibility === 'direct' && 'status-direct',
timelineType !== 'search' && 'status-in-timeline',
isStatusInOwnThread && 'status-in-own-thread'
)),
showContent: (spoilerText, spoilerShown) => !spoilerText || spoilerShown,
params: (notification, notificationId, status, statusId, timelineType,
showContent: ({ spoilerText, spoilerShown }) => !spoilerText || spoilerShown,
params: ({ notification, notificationId, status, statusId, timelineType,
account, accountId, uuid, isStatusInNotification, isStatusInOwnThread,
originalAccount, originalAccountId, spoilerShown, visibility, replyShown,
replyVisibility, spoilerText, originalStatus, originalStatusId) => ({
replyVisibility, spoilerText, originalStatus, originalStatusId }) => ({
notification,
notificationId,
status,

View File

@ -1,5 +1,5 @@
<span class="status-author-handle {{isStatusInNotification ? 'status-in-notification' : '' }}">
{{'@' + originalAccount.acct}}
<span class="status-author-handle {isStatusInNotification ? 'status-in-notification' : '' }">
{'@' + originalAccount.acct}
</span>
<style>
.status-author-handle {

View File

@ -1,9 +1,9 @@
<a class="status-author-name {{isStatusInNotification ? 'status-in-notification' : '' }} {{isStatusInOwnThread ? 'status-in-own-thread' : ''}}"
href="/accounts/{{originalAccountId}}"
title="{{'@' + originalAccount.acct}}"
focus-key={{focusKey}}
<a class="status-author-name {isStatusInNotification ? 'status-in-notification' : '' } {isStatusInOwnThread ? 'status-in-own-thread' : ''}"
href="/accounts/{originalAccountId}"
title="{'@' + originalAccount.acct}"
focus-key={focusKey}
>
{{originalAccount.display_name || originalAccount.username}}
{originalAccount.display_name || originalAccount.username}
</a>
<style>
.status-author-name {
@ -36,7 +36,7 @@
<script>
export default {
computed: {
focusKey: (uuid) => `status-author-name-${uuid}`
focusKey: ({ uuid }) => `status-author-name-${uuid}`
}
}
</script>

View File

@ -1,12 +1,12 @@
<div class="status-article-compose-box">
<ComposeBox realm={{originalStatusId}}
<ComposeBox realm={originalStatusId}
size="slim"
autoFocus="true"
hideBottomBorder="true"
isReply="true"
replyVisibility={{visibility}}
replySpoiler={{spoilerText}}
inReplyToUuid={{uuid}}
replyVisibility={visibility}
replySpoiler={spoilerText}
inReplyToUuid={uuid}
/>
</div>
<style>
@ -32,7 +32,7 @@
},
store: () => store,
computed: {
composeData: ($currentComposeData, originalStatusId) => $currentComposeData[originalStatusId] || {}
composeData: ({ $currentComposeData, originalStatusId }) => $currentComposeData[originalStatusId] || {}
},
methods: {
observe,

View File

@ -1,5 +1,5 @@
<div class={{computedClass}} ref:node>
{{{massagedContent}}}
<div class={computedClass} ref:node>
{@html massagedContent}
</div>
<style>
.status-content {
@ -71,7 +71,7 @@
},
store: () => store,
computed: {
computedClass: (isStatusInOwnThread, isStatusInNotification, shown) => {
computedClass: ({ isStatusInOwnThread, isStatusInNotification, shown }) => {
return classname(
'status-content',
isStatusInOwnThread && 'status-in-own-thread',
@ -79,9 +79,9 @@
shown && 'shown'
)
},
content: (originalStatus) => originalStatus.content,
emojis: (originalStatus) => originalStatus.emojis,
massagedContent: (content, emojis, $autoplayGifs) => {
content: ({ originalStatus }) => originalStatus.content,
emojis: ({ originalStatus }) => originalStatus.emojis,
massagedContent: ({ content, emojis, $autoplayGifs }) => {
content = emojifyText(content, emojis, $autoplayGifs)
// GNU Social and Pleroma don't add <p> tags

View File

@ -1,26 +1,26 @@
<div class="status-details">
<ExternalLink className="status-absolute-date"
href={{originalStatus.url}}
href={originalStatus.url}
showIcon="true"
ariaLabel="{{formattedDate}} (opens in new window)"
ariaLabel="{formattedDate} (opens in new window)"
>
<time datetime={{createdAtDate}} title={{formattedDate}}>{{formattedDate}}</time>
<time datetime={createdAtDate} title={formattedDate}>{formattedDate}</time>
</ExternalLink>
<a class="status-favs-reblogs"
href="/statuses/{{originalStatusId}}/reblogs"
aria-label={{reblogsLabel}}>
href="/statuses/{originalStatusId}/reblogs"
aria-label={reblogsLabel}>
<svg class="status-favs-reblogs-svg">
<use xlink:href="#fa-retweet"/>
</svg>
<span>{{numReblogs}}</span>
<span>{numReblogs}</span>
</a>
<a class="status-favs-reblogs"
href="/statuses/{{originalStatusId}}/favorites"
aria-label={{favoritesLabel}}>
href="/statuses/{originalStatusId}/favorites"
aria-label={favoritesLabel}>
<svg class="status-favs-reblogs-svg">
<use xlink:href="#fa-star" />
</svg>
<span>{{numFavs}}</span>
<span>{numFavs}</span>
</a>
</div>
<style>
@ -99,17 +99,17 @@
export default {
computed: {
createdAtDate: (originalStatus) => originalStatus.created_at,
numReblogs: (originalStatus) => originalStatus.reblogs_count || 0,
numFavs: (originalStatus) => originalStatus.favourites_count || 0,
formattedDate: (createdAtDate) => formatter.format(new Date(createdAtDate)),
reblogsLabel: (numReblogs) => {
createdAtDate: ({ originalStatus }) => originalStatus.created_at,
numReblogs: ({ originalStatus }) => originalStatus.reblogs_count || 0,
numFavs: ({ originalStatus }) => originalStatus.favourites_count || 0,
formattedDate: ({ createdAtDate }) => formatter.format(new Date(createdAtDate)),
reblogsLabel: ({ numReblogs }) => {
// TODO: intl
return numReblogs === 1
? `Boosted ${numReblogs} time`
: `Boosted ${numReblogs} times`
},
favoritesLabel: (numFavs) => {
favoritesLabel: ({ numFavs }) => {
// TODO: intl
return numFavs === 1
? `Favorited ${numFavs} time`

View File

@ -1,30 +1,30 @@
<div class="status-header {{isStatusInNotification ? 'status-in-notification' : ''}} {{notification && notification.type === 'follow' ? 'header-is-follow' : ''}}">
<div class="status-header-avatar {{timelineType === 'pinned' ? 'hidden' : ''}}">
<Avatar :account size="extra-small"/>
<div class="status-header {isStatusInNotification ? 'status-in-notification' : ''} {notification && notification.type === 'follow' ? 'header-is-follow' : ''}">
<div class="status-header-avatar {timelineType === 'pinned' ? 'hidden' : ''}">
<Avatar {account} size="extra-small"/>
</div>
<svg class="status-header-svg">
<use xlink:href={{icon}}/>
<use xlink:href={icon}/>
</svg>
<span class="status-header-span">
{{#if timelineType === 'pinned'}}
{#if timelineType === 'pinned'}
Pinned toot
{{else}}
<a href="/accounts/{{accountId}}"
{:else}
<a href="/accounts/{accountId}"
class="status-header-a"
title="{{'@' + account.acct}}"
focus-key={{focusKey}} >
{{account.display_name || account.username}}
title="{'@' + account.acct}"
focus-key={focusKey} >
{account.display_name || account.username}
</a>
{{#if notification && notification.type === 'reblog'}}
{#if notification && notification.type === 'reblog'}
boosted your status
{{elseif notification && notification.type === 'favourite'}}
{:elseif notification && notification.type === 'favourite'}
favorited your status
{{elseif notification && notification.type === 'follow'}}
{:elseif notification && notification.type === 'follow'}
followed you
{{elseif status && status.reblog}}
{:elseif status && status.reblog}
boosted
{{/if}}
{{/if}}
{/if}
{/if}
</span>
</div>
<style>
@ -88,8 +88,8 @@
Avatar
},
computed: {
focusKey: (uuid) => `status-header-${uuid}`,
icon: (notification, status, timelineType) => {
focusKey: ({ uuid }) => `status-header-${uuid}`,
icon: ({ notification, status, timelineType }) => {
if (timelineType === 'pinned') {
return '#fa-thumb-tack'
} else if ((notification && notification.type === 'reblog') || (status && status.reblog)) {

View File

@ -1,23 +1,23 @@
{{#if sensitive }}
<div class="status-sensitive-media-container {{sensitiveShown ? 'status-sensitive-media-shown' : 'status-sensitive-media-hidden'}}"
{#if sensitive }
<div class="status-sensitive-media-container {sensitiveShown ? 'status-sensitive-media-shown' : 'status-sensitive-media-hidden'}"
>
{{#if sensitiveShown}}
{#if sensitiveShown}
<button type="button"
class="status-sensitive-media-button"
aria-label="Hide sensitive media"
delegate-key={{delegateKey}} >
delegate-key={delegateKey} >
<div class="svg-wrapper">
<svg class="status-sensitive-media-svg">
<use xlink:href="#fa-eye-slash" />
</svg>
</div>
</button>
<MediaAttachments :mediaAttachments :sensitive :uuid />
{{else}}
<MediaAttachments {mediaAttachments} {sensitive} {uuid} />
{:else}
<button type="button"
class="status-sensitive-media-button"
aria-label="Show sensitive media"
delegate-key={{delegateKey}} >
delegate-key={delegateKey} >
<div class="status-sensitive-media-warning">
<span>Sensitive content. Click to show.</span>
@ -28,11 +28,11 @@
</svg>
</div>
</button>
{{/if}}
{/if}
</div>
{{else}}
<MediaAttachments :mediaAttachments :sensitive :uuid />
{{/if}}
{:else}
<MediaAttachments {mediaAttachments} {sensitive} {uuid} />
{/if}
<style>
.status-sensitive-media-container {
grid-area: media;
@ -138,10 +138,10 @@
},
store: () => store,
computed: {
mediaAttachments: (originalStatus) => originalStatus.media_attachments,
sensitiveShown: ($sensitivesShown, uuid) => !!$sensitivesShown[uuid],
sensitive: (originalStatus, $markMediaAsSensitive) => originalStatus.sensitive || $markMediaAsSensitive,
delegateKey: (uuid) => `sensitive-${uuid}`
mediaAttachments: ({ originalStatus }) => originalStatus.media_attachments,
sensitiveShown: ({ $sensitivesShown, uuid }) => !!$sensitivesShown[uuid],
sensitive: ({ originalStatus, $markMediaAsSensitive }) => originalStatus.sensitive || $markMediaAsSensitive,
delegateKey: ({ uuid }) => `sensitive-${uuid}`
},
methods: {
onClickSensitiveMediaButton () {

View File

@ -1,10 +1,10 @@
<a class="status-relative-date {{isStatusInNotification ? 'status-in-notification' : '' }}"
href="/statuses/{{originalStatusId}}"
focus-key={{focusKey}}
<a class="status-relative-date {isStatusInNotification ? 'status-in-notification' : '' }"
href="/statuses/{originalStatusId}"
focus-key={focusKey}
>
<time datetime={{createdAtDate}} title={{relativeDate}}
aria-label="{{relativeDate}} click to show thread">
{{relativeDate}}
<time datetime={createdAtDate} title={relativeDate}
aria-label="{relativeDate} click to show thread">
{relativeDate}
</time>
</a>
<style>
@ -35,14 +35,14 @@
export default {
computed: {
createdAtDate: (originalStatus) => originalStatus.created_at,
relativeDate: (createdAtDate) => {
createdAtDate: ({ originalStatus }) => originalStatus.created_at,
relativeDate: ({ createdAtDate }) => {
mark('compute relativeDate')
let res = timeagoInstance.format(createdAtDate)
stop('compute relativeDate')
return res
},
focusKey: (uuid) => `status-relative-date-${uuid}`
focusKey: ({ uuid }) => `status-relative-date-${uuid}`
}
}
</script>

View File

@ -1,11 +1,11 @@
<a class="status-sidebar size-{{size}}"
href="/accounts/{{originalAccountId}}"
focus-key={{focusKey}}
<a class="status-sidebar size-{size}"
href="/accounts/{originalAccountId}"
focus-key={focusKey}
aria-hidden="true"
>
<Avatar account={{originalAccount}}
<Avatar account={originalAccount}
isLink="true"
:size />
{size} />
</a>
<style>
.status-sidebar {
@ -36,8 +36,8 @@
Avatar
},
computed: {
focusKey: (uuid) => `status-author-avatar-${uuid}`,
size: (isStatusInOwnThread) => isStatusInOwnThread ? 'medium' : 'small'
focusKey: ({ uuid }) => `status-author-avatar-${uuid}`,
size: ({ isStatusInOwnThread }) => isStatusInOwnThread ? 'medium' : 'small'
}
}
</script>

View File

@ -1,9 +1,9 @@
<div class="status-spoiler {{isStatusInNotification ? 'status-in-notification' : ''}} {{isStatusInOwnThread ? 'status-in-own-thread' : ''}}">
<p>{{{massagedSpoilerText}}}</p>
<div class="status-spoiler {isStatusInNotification ? 'status-in-notification' : ''} {isStatusInOwnThread ? 'status-in-own-thread' : ''}">
<p>{@html massagedSpoilerText}</p>
</div>
<div class="status-spoiler-button {{isStatusInOwnThread ? 'status-in-own-thread' : ''}}">
<button type="button" delegate-key={{delegateKey}}>
{{spoilerShown ? 'Show less' : 'Show more'}}
<div class="status-spoiler-button {isStatusInOwnThread ? 'status-in-own-thread' : ''}">
<button type="button" delegate-key={delegateKey}>
{spoilerShown ? 'Show less' : 'Show more'}
</button>
</div>
<style>
@ -60,13 +60,13 @@
},
store: () => store,
computed: {
spoilerText: (originalStatus) => originalStatus.spoiler_text,
emojis: (originalStatus) => originalStatus.emojis,
massagedSpoilerText: (spoilerText, emojis, $autoplayGifs) => {
spoilerText: ({ originalStatus }) => originalStatus.spoiler_text,
emojis: ({ originalStatus }) => originalStatus.emojis,
massagedSpoilerText: ({ spoilerText, emojis, $autoplayGifs }) => {
spoilerText = escapeHtml(spoilerText)
return emojifyText(spoilerText, emojis, $autoplayGifs)
},
delegateKey: (uuid) => `spoiler-${uuid}`
delegateKey: ({ uuid }) => `spoiler-${uuid}`
},
methods: {
onClickSpoilerButton () {

View File

@ -1,34 +1,34 @@
<div class="status-toolbar {{isStatusInOwnThread ? 'status-in-own-thread' : ''}}" ref:node>
<div class="status-toolbar {isStatusInOwnThread ? 'status-in-own-thread' : ''}" ref:node>
<IconButton
className="status-toolbar-reply-button"
label={{replyLabel}}
label={replyLabel}
pressable="true"
pressed={{replyShown}}
pressed={replyShown}
href="#fa-reply"
delegateKey={{replyKey}}
focusKey={{replyKey}}
delegateKey={replyKey}
focusKey={replyKey}
/>
<IconButton
label={{reblogLabel}}
pressable={{!reblogDisabled}}
pressed={{reblogged}}
disabled={{reblogDisabled}}
href={{reblogIcon}}
delegateKey={{reblogKey}}
label={reblogLabel}
pressable={!reblogDisabled}
pressed={reblogged}
disabled={reblogDisabled}
href={reblogIcon}
delegateKey={reblogKey}
ref:reblogIcon
/>
<IconButton
label="Favorite"
pressable="true"
pressed={{favorited}}
pressed={favorited}
href="#fa-star"
delegateKey={{favoriteKey}}
delegateKey={favoriteKey}
ref:favoriteIcon
/>
<IconButton
label="Show more options"
href="#fa-ellipsis-h"
delegateKey={{optionsKey}}
delegateKey={optionsKey}
/>
</div>
<style>
@ -133,8 +133,8 @@
reblogAnimation: REBLOG_ANIMATION
}),
computed: {
replyLabel: (replyShown) => replyShown ? 'Close reply' : 'Reply',
reblogLabel: (visibility) => {
replyLabel: ({ replyShown }) => replyShown ? 'Close reply' : 'Reply',
reblogLabel: ({ visibility }) => {
switch (visibility) {
case 'private':
return 'Cannot be boosted because this is followers-only'
@ -144,7 +144,7 @@
return 'Boost'
}
},
reblogIcon: (visibility) => {
reblogIcon: ({ visibility }) => {
switch (visibility) {
case 'private':
return '#fa-lock'
@ -154,25 +154,25 @@
return '#fa-retweet'
}
},
reblogDisabled: (visibility) => {
reblogDisabled: ({ visibility }) => {
return visibility === 'private' || visibility === 'direct'
},
reblogged: (originalStatusId, $currentStatusModifications, originalStatus) => {
reblogged: ({ originalStatusId, $currentStatusModifications, originalStatus }) => {
if ($currentStatusModifications && originalStatusId in $currentStatusModifications.reblogs) {
return $currentStatusModifications.reblogs[originalStatusId]
}
return originalStatus.reblogged
},
favorited: (originalStatusId, $currentStatusModifications, originalStatus) => {
favorited: ({ originalStatusId, $currentStatusModifications, originalStatus }) => {
if ($currentStatusModifications && originalStatusId in $currentStatusModifications.favorites) {
return $currentStatusModifications.favorites[originalStatusId]
}
return originalStatus.favourited
},
favoriteKey: (uuid) => `fav-${uuid}`,
reblogKey: (uuid) => `reblog-${uuid}`,
replyKey: (uuid) => `reply-${uuid}`,
optionsKey: (uuid) => `options-${uuid}`
favoriteKey: ({ uuid }) => `fav-${uuid}`,
reblogKey: ({ uuid }) => `reblog-${uuid}`,
replyKey: ({ uuid }) => `reply-${uuid}`,
optionsKey: ({ uuid }) => `options-${uuid}`
}
}
</script>

View File

@ -1,11 +1,11 @@
<div class="lazy-timeline">
{{#await importTimeline}}
{#await importTimeline}
<!-- awaiting promise -->
{{then constructor}}
<:Component {constructor} :timeline />
{{catch error}}
<div>Component failed to load. Try refreshing! {{error}}</div>
{{/await}}
{:then constructor}
<svelte:component this={constructor} {timeline} />
{:catch error}
<div>Component failed to load. Try refreshing! {error}</div>
{/await}
</div>
<style>
.lazy-timeline {

View File

@ -1,5 +1,5 @@
<div class="loading-footer">
<LoadingSpinner size={{48}} />
<LoadingSpinner size={48} />
<span class="loading-footer-info">
Loading more...
</span>

View File

@ -1,6 +1,6 @@
<div class="more-items-header">
<button class="primary" type="button" on:click="onClick(event)">
Show {{count}} more
Show {count} more
</button>
</div>
<style>

View File

@ -1,5 +1,5 @@
<MoreHeader count={{virtualProps.count}}
onClick={{virtualProps.onClick}}
<MoreHeader count={virtualProps.count}
onClick={virtualProps.onClick}
/>
<script>
import MoreHeader from './MoreHeader.html'

View File

@ -1,10 +1,10 @@
<Notification
notification={{virtualProps.notification}}
timelineType={{virtualProps.timelineType}}
timelineValue={{virtualProps.timelineValue}}
focusSelector={{virtualProps.focusSelector}}
index={{virtualIndex}}
length={{virtualLength}}
notification={virtualProps.notification}
timelineType={virtualProps.timelineType}
timelineValue={virtualProps.timelineValue}
focusSelector={virtualProps.focusSelector}
index={virtualIndex}
length={virtualLength}
on:recalculateHeight />
<script>
import Notification from '../status/Notification.html'

View File

@ -1,12 +1,12 @@
<div role="feed" aria-label="Pinned toots" class="pinned-statuses">
{{#each pinnedStatuses as status, index @id}}
<Status :status
{#each pinnedStatuses as status, index (status.id)}
<Status {status}
timelineType="pinned"
timelineValue={{accountId}}
:index
length={{pinnedStatuses.length}}
timelineValue={accountId}
{index}
length={pinnedStatuses.length}
/>
{{/each}}
{/each}
</div>
<script>
import { store } from '../../_store/store'
@ -20,7 +20,7 @@
await this.updatePinnedStatuses()
},
computed: {
pinnedStatuses: ($pinnedStatuses, $currentInstance, accountId) => {
pinnedStatuses: ({ $pinnedStatuses, $currentInstance, accountId }) => {
return ($pinnedStatuses[$currentInstance] && $pinnedStatuses[$currentInstance][accountId]) || []
}
},

View File

@ -1,9 +1,9 @@
<Status status={{virtualProps.status}}
timelineType={{virtualProps.timelineType}}
timelineValue={{virtualProps.timelineValue}}
focusSelector={{virtualProps.focusSelector}}
index={{virtualIndex}}
length={{virtualLength}}
<Status status={virtualProps.status}
timelineType={virtualProps.timelineType}
timelineValue={virtualProps.timelineValue}
focusSelector={virtualProps.focusSelector}
index={virtualIndex}
length={virtualLength}
on:recalculateHeight />
<script>
import Status from '../status/Status.html'

View File

@ -1,33 +1,33 @@
<h1 class="sr-only">{{label}}</h1>
<h1 class="sr-only">{label}</h1>
<div class="timeline"
role="feed"
on:focusWithCapture="saveFocus(event)"
on:blurWithCapture="clearFocus(event)"
>
{{#await componentsPromise}}
{#await componentsPromise}
<!-- awaiting promise -->
{{then result}}
<:Component {result.listComponent}
component={{result.listItemComponent}}
realm="{{$currentInstance + '/' + timeline}}"
{:then result}
<svelte:component this={result.listComponent}
component={result.listItemComponent}
realm="{$currentInstance + '/' + timeline}"
containerQuery=".container"
:makeProps
items={{$timelineItemIds}}
showFooter={{$timelineInitialized && $runningUpdate}}
footerComponent={{LoadingFooter}}
showHeader={{$showHeader}}
headerComponent={{MoreHeaderVirtualWrapper}}
:headerProps
:scrollToItem
{makeProps}
items={$timelineItemIds}
showFooter={$timelineInitialized && $runningUpdate}
footerComponent={LoadingFooter}
showHeader={$showHeader}
headerComponent={MoreHeaderVirtualWrapper}
{headerProps}
{scrollToItem}
on:scrollToBottom="onScrollToBottom()"
on:scrollToTop="onScrollToTop()"
on:scrollTopChanged="onScrollTopChanged(event)"
on:initialized="initialize()"
on:noNeedToScroll="onNoNeedToScroll()"
/>
{{catch error}}
<div>Error: component failed to load! Try reloading. {{error}}</div>
{{/await}}
{:catch error}
<div>Error: component failed to load! Try reloading. {error}</div>
{/await}
</div>
<script>
import { store } from '../../_store/store'
@ -82,7 +82,7 @@
// due to need to scroll to the right item and thus calculate all item heights up-front.
// Here we lazy-load both the virtual list component itself as well as the component
// it renders.
componentsPromise: (timelineType) => {
componentsPromise: ({ timelineType }) => {
return Promise.all([
timelineType === 'status'
? importPseudoVirtualList()
@ -95,7 +95,7 @@
listItemComponent: results[1]
}))
},
makeProps: ($currentInstance, timelineType, timelineValue) => async (itemId) => {
makeProps: ({ $currentInstance, timelineType, timelineValue }) => async (itemId) => {
let res = {
timelineType,
timelineValue
@ -107,7 +107,7 @@
}
return res
},
label: (timeline, $currentInstance, timelineType, timelineValue) => {
label: ({ timeline, $currentInstance, timelineType, timelineValue }) => {
if (timelines[timeline]) {
return `${timelines[timeline].label} timeline for ${$currentInstance}`
}
@ -125,20 +125,20 @@
return `Notifications for ${$currentInstance}`
}
},
timelineType: (timeline) => {
timelineType: ({ timeline }) => {
return timeline.split('/')[0]
},
timelineValue: (timeline) => {
timelineValue: ({ timeline }) => {
return timeline.split('/').slice(-1)[0]
},
// 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.
scrollToItem: (timelineType, timelineValue, $firstTimelineItemId) => (
scrollToItem: ({ timelineType, timelineValue, $firstTimelineItemId }) => (
timelineType === 'status' && $firstTimelineItemId &&
timelineValue !== $firstTimelineItemId && timelineValue
),
itemIdsToAdd: ($itemIdsToAdd) => $itemIdsToAdd,
headerProps: (itemIdsToAdd) => {
itemIdsToAdd: ({ $itemIdsToAdd }) => $itemIdsToAdd,
headerProps: ({ itemIdsToAdd }) => {
return {
count: itemIdsToAdd ? itemIdsToAdd.length : 0,
onClick: showMoreItemsForCurrentTimeline

View File

@ -1,21 +1,21 @@
<VirtualListContainer :realm :containerQuery on:initialized on:noNeedToScroll >
<VirtualListContainer {realm} {containerQuery} on:initialized on:noNeedToScroll >
<div class="virtual-list"
style="height: {{$height}}px;"
style="height: {$height}px;"
ref:node >
<VirtualListHeader component={{headerComponent}} virtualProps={{headerProps}} shown={{$showHeader}}/>
{{#if $visibleItems}}
{{#each $visibleItems as visibleItem @key}}
<VirtualListLazyItem :component
offset={{visibleItem.offset}}
:makeProps
key={{visibleItem.key}}
index={{visibleItem.index}}
<VirtualListHeader component={headerComponent} virtualProps={headerProps} shown={$showHeader}/>
{#if $visibleItems}
{#each $visibleItems as visibleItem (visibleItem.key)}
<VirtualListLazyItem {component}
offset={visibleItem.offset}
{makeProps}
key={visibleItem.key}
index={visibleItem.index}
/>
{{/each}}
{{/if}}
{{#if $showFooter}}
<VirtualListFooter component={{footerComponent}} />
{{/if}}
{/each}
{/if}
{#if $showFooter}
<VirtualListFooter component={footerComponent} />
{/if}
</div>
</VirtualListContainer>
<style>
@ -101,12 +101,12 @@
VirtualListHeader
},
computed: {
distanceFromBottom: ($scrollHeight, $scrollTop, $offsetHeight) => {
distanceFromBottom: ({ $scrollHeight, $scrollTop, $offsetHeight }) => {
return $scrollHeight - $scrollTop - $offsetHeight
},
scrollTop: ($scrollTop) => $scrollTop,
scrollTop: ({ $scrollTop }) => $scrollTop,
// TODO: bug in svelte store, shouldn't need to do this
allVisibleItemsHaveHeight: ($allVisibleItemsHaveHeight) => $allVisibleItemsHaveHeight
allVisibleItemsHaveHeight: ({ $allVisibleItemsHaveHeight }) => $allVisibleItemsHaveHeight
},
methods: {
observe,

View File

@ -115,7 +115,7 @@
},
computed: {
// TODO: bug in svelte/store the observer in oncreate() never get removed without this hack
allVisibleItemsHaveHeight: ($allVisibleItemsHaveHeight) => $allVisibleItemsHaveHeight
allVisibleItemsHaveHeight: ({ $allVisibleItemsHaveHeight }) => $allVisibleItemsHaveHeight
}
}
</script>

View File

@ -1,7 +1,7 @@
<div class="virtual-list-footer"
ref:node
style="transform: translateY({{$heightWithoutFooter}}px);" >
<:Component {component} />
style="transform: translateY({$heightWithoutFooter}px);" >
<svelte:component this={component} />
</div>
<style>
.virtual-list-footer {

View File

@ -1,6 +1,6 @@
<div class="virtual-list-header {{shown ? 'shown' : ''}} {{fadedIn ? 'faded-in' : ''}}"
<div class="virtual-list-header {shown ? 'shown' : ''} {fadedIn ? 'faded-in' : ''}"
ref:node >
<:Component {component} :virtualProps />
<svelte:component this={component} {virtualProps} />
</div>
<style>
.virtual-list-header {

View File

@ -1,12 +1,12 @@
<div class="virtual-list-item {{shown ? 'shown' : ''}}"
aria-hidden={{!shown}}
virtual-list-key={{key}}
<div class="virtual-list-item {shown ? 'shown' : ''}"
aria-hidden={!shown}
virtual-list-key={key}
ref:node
style="transform: translateY({{offset}}px);" >
<:Component {component}
virtualProps={{props}}
virtualIndex={{index}}
virtualLength={{$length}}
style="transform: translateY({offset}px);" >
<svelte:component this={component}
virtualProps={props}
virtualIndex={index}
virtualLength={$length}
on:recalculateHeight="doRecalculateHeight()"/>
</div>
<style>
@ -45,7 +45,7 @@
},
store: () => virtualListStore,
computed: {
'shown': ($itemHeights, key) => $itemHeights[key] > 0
'shown': ({ $itemHeights, key }) => $itemHeights[key] > 0
},
methods: {
doRecalculateHeight () {

View File

@ -1,11 +1,11 @@
{{#if props}}
<VirtualListItem :component
:offset
:props
:key
:index
{#if props}
<VirtualListItem {component}
{offset}
{props}
{key}
{index}
/>
{{/if}}
{/if}
<script>
import VirtualListItem from './VirtualListItem'
import { mark, stop } from '../../_utils/marks'

View File

@ -1,15 +1,15 @@
{{#if $isUserLoggedIn}}
<TimelinePage timeline="account/{{params.accountId}}">
{#if $isUserLoggedIn}
<TimelinePage timeline="account/{params.accountId}">
<DynamicPageBanner title="" />
{{#if $currentAccountProfile && $currentVerifyCredentials}}
<AccountProfile account={{$currentAccountProfile}}
relationship={{$currentAccountRelationship}}
verifyCredentials={{$currentVerifyCredentials}}
{#if $currentAccountProfile && $currentVerifyCredentials}
<AccountProfile account={$currentAccountProfile}
relationship={$currentAccountRelationship}
verifyCredentials={$currentVerifyCredentials}
/>
{{/if}}
<PinnedStatuses accountId={{params.accountId}} />
{/if}
<PinnedStatuses accountId={params.accountId} />
</TimelinePage>
{{else}}
{:else}
<HiddenFromSSR>
<FreeTextLayout>
<h1>Profile</h1>
@ -17,7 +17,7 @@
<p>A user timeline will appear here when logged in.</p>
</FreeTextLayout>
</HiddenFromSSR>
{{/if}}
{/if}
<script>
import TimelinePage from '../../_components/TimelinePage.html'
import FreeTextLayout from '../../_components/FreeTextLayout.html'
@ -37,10 +37,10 @@
},
store: () => store,
computed: {
profileName: ($currentAccountProfile) => {
profileName: ({ $currentAccountProfile }) => {
return ($currentAccountProfile && ('@' + $currentAccountProfile.acct)) || ''
},
shortProfileName: ($currentAccountProfile) => {
shortProfileName: ({ $currentAccountProfile }) => {
return ($currentAccountProfile && ('@' + $currentAccountProfile.username)) || ''
}
},

View File

@ -1,5 +1,5 @@
<DynamicPageBanner title="Followers" />
<AccountsListPage :accountsFetcher />
<AccountsListPage {accountsFetcher} />
<script>
import { getFollowers } from '../../../_api/followsAndFollowers'
import AccountsListPage from '../../../_components/AccountsListPage.html'
@ -8,8 +8,8 @@
export default {
computed: {
accountId: params => params.accountId,
accountsFetcher: ($currentInstance, $accessToken, accountId) => () => getFollowers($currentInstance, $accessToken, accountId)
accountId: ({ params }) => params.accountId,
accountsFetcher: ({ $currentInstance, $accessToken, accountId }) => () => getFollowers($currentInstance, $accessToken, accountId)
},
store: () => store,
components: {

View File

@ -1,5 +1,5 @@
<DynamicPageBanner title="Follows" />
<AccountsListPage :accountsFetcher />
<AccountsListPage {accountsFetcher} />
<script>
import { getFollows } from '../../../_api/followsAndFollowers'
import AccountsListPage from '../../../_components/AccountsListPage.html'
@ -8,8 +8,8 @@
export default {
computed: {
accountId: params => params.accountId,
accountsFetcher: ($currentInstance, $accessToken, accountId) => () => getFollows($currentInstance, $accessToken, accountId)
accountId: ({ params }) => params.accountId,
accountsFetcher: ({ $currentInstance, $accessToken, accountId }) => () => getFollows($currentInstance, $accessToken, accountId)
},
store: () => store,
components: {

View File

@ -1,5 +1,5 @@
<DynamicPageBanner title="Blocked users" icon="#fa-ban" />
<AccountsListPage :accountsFetcher :accountActions />
<AccountsListPage {accountsFetcher} {accountActions} />
<script>
import AccountsListPage from '.././_components/AccountsListPage.html'
import { store } from '.././_store/store'
@ -18,7 +18,7 @@
]
}),
computed: {
accountsFetcher: ($currentInstance, $accessToken) => () => getBlockedAccounts($currentInstance, $accessToken)
accountsFetcher: ({ $currentInstance, $accessToken }) => () => getBlockedAccounts($currentInstance, $accessToken)
},
store: () => store,
components: {

View File

@ -1,4 +1,4 @@
{{#if $isUserLoggedIn}}
{#if $isUserLoggedIn}
<div class="community-page">
<h2 class="community-header">
@ -23,35 +23,35 @@
/>
</PageList>
{{#if $lists.length}}
{#if $lists.length}
<h2 class="community-header">
Lists
</h2>
<PageList label="Lists">
{{#each $lists as list}}
<PageListItem href="/lists/{{list.id}}"
label={{list.title}}
{#each $lists as list}
<PageListItem href="/lists/{list.id}"
label={list.title}
icon="#fa-bars"
pinnable="true"
/>
{{/each}}
{/each}
</PageList>
{{/if}}
{/if}
<h2 class="community-header">
Instance settings
</h2>
<PageList label="Instance settings">
{{#if isLockedAccount}}
{#if isLockedAccount}
<PageListItem href="/requests"
label="Follow requests"
icon="#fa-user-plus"
/>
{{/if}}
{/if}
<PageListItem href="/muted"
label="Muted users"
icon="#fa-volume-off"
@ -67,7 +67,7 @@
</PageList>
</div>
{{else}}
{:else}
<HiddenFromSSR>
<FreeTextLayout>
<h1>Community</h1>
@ -75,7 +75,7 @@
<p>Community options appear here when logged in.</p>
</FreeTextLayout>
</HiddenFromSSR>
{{/if}}
{/if}
<style>
.community-page {
margin: 20px;
@ -109,7 +109,7 @@
PageListItem
},
computed: {
isLockedAccount: ($currentVerifyCredentials) => $currentVerifyCredentials && $currentVerifyCredentials.locked
isLockedAccount: ({ $currentVerifyCredentials }) => $currentVerifyCredentials && $currentVerifyCredentials.locked
}
}
</script>

View File

@ -1,10 +1,10 @@
{{#if $isUserLoggedIn}}
{#if $isUserLoggedIn}
<TimelinePage timeline="favorites">
{{#if $pinnedPage !== '/favorites'}}
{#if $pinnedPage !== '/favorites'}
<DynamicPageBanner title="Favorites" icon="#fa-star"/>
{{/if}}
{/if}
</TimelinePage>
{{else}}
{:else}
<HiddenFromSSR>
<FreeTextLayout>
<h1>Favorites</h1>
@ -12,7 +12,7 @@
<p>Your favorites will appear here when logged in.</p>
</FreeTextLayout>
</HiddenFromSSR>
{{/if}}
{/if}
<script>
import TimelinePage from '.././_components/TimelinePage.html'
import FreeTextLayout from '.././_components/FreeTextLayout.html'

View File

@ -1,10 +1,10 @@
{{#if $isUserLoggedIn}}
{#if $isUserLoggedIn}
<TimelinePage timeline="federated">
{{#if $pinnedPage !== '/federated'}}
{#if $pinnedPage !== '/federated'}
<DynamicPageBanner title="Federated Timeline" icon="#fa-globe"/>
{{/if}}
{/if}
</TimelinePage>
{{else}}
{:else}
<HiddenFromSSR>
<FreeTextLayout>
<h1>Federated</h1>
@ -12,7 +12,7 @@
<p>Your federated timeline will appear here when logged in.</p>
</FreeTextLayout>
</HiddenFromSSR>
{{/if}}
{/if}
<script>
import TimelinePage from '.././_components/TimelinePage.html'
import FreeTextLayout from '.././_components/FreeTextLayout.html'

View File

@ -1,8 +1,8 @@
{{#if $isUserLoggedIn}}
{#if $isUserLoggedIn}
<TimelineHomePage/>
{{else}}
{:else}
<NotLoggedInHome/>
{{/if}}
{/if}
<script>
import NotLoggedInHome from '.././_components/NotLoggedInHome.html'
import { store } from '.././_store/store.js'

Some files were not shown because too many files have changed in this diff Show More