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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,6 @@
{{#if revealed}} {#if revealed}
<:Component {pageComponent} :params /> <svelte:component this={pageComponent} {params} />
{{/if}} {/if}
<script> <script>
// On the very first page load, avoid doing a "reveal" because // 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, // 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' : ''}}"> <div class="loading-mask-container {shown ? 'loading-mask-container-shown' : ''}">
{{#if shown}} {#if shown}
<div class="loading-mask"> <div class="loading-mask">
<LoadingSpinner maskStyle="true"/> <LoadingSpinner maskStyle="true"/>
</div> </div>
{{/if}} {/if}
</div> </div>
<style> <style>
.loading-mask-container { .loading-mask-container {
@ -37,7 +37,7 @@
export default { export default {
store: () => store, store: () => store,
computed: { computed: {
shown: ($logInToInstanceLoading) => $logInToInstanceLoading shown: ({ $logInToInstanceLoading }) => $logInToInstanceLoading
}, },
components: { components: {
LoadingSpinner LoadingSpinner

View File

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

View File

@ -1,5 +1,5 @@
<svg class="loading-spinner-icon spin {{maskStyle ? 'mask-style' : ''}}" <svg class="loading-spinner-icon spin {maskStyle ? 'mask-style' : ''}"
style="width: {{size}}px; height: {{size}}px;" style="width: {size}px; height: {size}px;"
aria-label="Loading" aria-label="Loading"
> >
<use xlink:href="#fa-spinner" /> <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"> <nav class="main-nav">
<ul class="main-nav-ul"> <ul class="main-nav-ul">
<li class="main-nav-li"> <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>
<li class="main-nav-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> </li>
{{#if $pinnedPage === '/local'}} {#if $pinnedPage === '/local'}
<li class="main-nav-li"> <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> </li>
{{elseif $pinnedPage === '/federated'}} {:elseif $pinnedPage === '/federated'}
<li class="main-nav-li"> <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> </li>
{{elseif $pinnedPage === '/favorites'}} {:elseif $pinnedPage === '/favorites'}
<li class="main-nav-li"> <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> </li>
{{elseif $pinnedPage.startsWith('/lists/')}} {:elseif $pinnedPage.startsWith('/lists/')}
<li class="main-nav-li"> <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> </li>
{{/if}} {/if}
<li class="main-nav-li"> <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>
<li class="main-nav-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>
<li class="main-nav-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> </li>
</ul> </ul>
</nav> </nav>

View File

@ -1,25 +1,25 @@
<a class='main-nav-link {{selected ? "selected" : ""}}' <a class='main-nav-link {selected ? "selected" : ""}'
aria-label={{ariaLabel}} aria-label={ariaLabel}
aria-current={{selected}} aria-current={selected}
on:click="onClick(event)" on:click="onClick(event)"
:href > {href} >
{{#if name === 'notifications'}} {#if name === 'notifications'}
<div class="nav-link-svg-wrapper"> <div class="nav-link-svg-wrapper">
<svg class="nav-link-svg"> <svg class="nav-link-svg">
<use xlink:href={{svg}} /> <use xlink:href={svg} />
</svg> </svg>
{{#if $hasNotifications}} {#if $hasNotifications}
<span class="nav-link-notifications" aria-hidden="true"> <span class="nav-link-notifications" aria-hidden="true">
{{$numberOfNotifications}} {$numberOfNotifications}
</span> </span>
{{/if}} {/if}
</div> </div>
{{else}} {:else}
<svg class="nav-link-svg"> <svg class="nav-link-svg">
<use xlink:href={{svg}} /> <use xlink:href={svg} />
</svg> </svg>
{{/if}} {/if}
<span class="nav-link-label">{{label}}</span> <span class="nav-link-label">{label}</span>
</a> </a>
<style> <style>
.main-nav-link { .main-nav-link {
@ -122,8 +122,8 @@
export default { export default {
store: () => store, store: () => store,
computed: { computed: {
selected: (page, name) => page === name, selected: ({ page, name }) => page === name,
ariaLabel: (selected, name, label, $numberOfNotifications) => { ariaLabel: ({ selected, name, label, $numberOfNotifications }) => {
let res = label let res = label
if (selected) { if (selected) {
res += ' (current page)' 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)" on:mouseover="onMouseOver(event)"
ref:node ref:node
> >
{{#if playing}} {#if playing}
<AutoplayVideo <AutoplayVideo
className={{class}} className={class}
ariaLabel={{label}} ariaLabel={label}
:poster {poster}
:src {src}
:width {width}
:height {height}
/> />
{{else}} {:else}
<LazyImage <LazyImage
alt={{label || ''}} alt={label || ''}
title={{label || ''}} title={label || ''}
src={{staticSrc}} src={staticSrc}
fallback={{oneTransparentPixel}} fallback={oneTransparentPixel}
:width {width}
:height {height}
background="var(--loading-bg)" background="var(--loading-bg)"
className={{class}} className={class}
/> />
{{/if}} {/if}
<PlayVideoIcon className={{playing ? 'hidden' : ''}}/> <PlayVideoIcon className={playing ? 'hidden' : ''}/>
</div> </div>
<style> <style>
.non-autoplay-gifv { .non-autoplay-gifv {

View File

@ -1,22 +1,22 @@
{{#if staticSrc === src}} {#if staticSrc === src}
<img class={{className || ''}} <img class={className || ''}
aria-hidden={{ariaHidden}} aria-hidden={ariaHidden}
alt={{alt || ''}} alt={alt || ''}
title={{alt || ''}} title={alt || ''}
:src {src}
on:imgLoad on:imgLoad
on:imgLoadError /> on:imgLoadError />
{{else}} {:else}
<img class="{{className || ''}} non-autoplay-zoom-in {{isLink ? 'is-link' : ''}}" <img class="{className || ''} non-autoplay-zoom-in {isLink ? 'is-link' : ''}"
aria-hidden={{ariaHidden}} aria-hidden={ariaHidden}
alt={{alt || ''}} alt={alt || ''}
title={{alt || ''}} title={alt || ''}
src={{staticSrc}} src={staticSrc}
on:imgLoad on:imgLoad
on:imgLoadError on:imgLoadError
on:mouseover="onMouseOver(event)" on:mouseover="onMouseOver(event)"
ref:node /> ref:node />
{{/if}} {/if}
<style> <style>
.non-autoplay-zoom-in { .non-autoplay-zoom-in {
cursor: 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"> <svg class="play-video-icon-svg">
<use xlink:href="#fa-play-circle" /> <use xlink:href="#fa-play-circle" />
</svg> </svg>

View File

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

View File

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

View File

@ -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"> <div class="toast-container">
{{text}} {text}
</div> </div>
</div> </div>
<style> <style>

View File

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

View File

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

View File

@ -1,13 +1,13 @@
<a href="/accounts/{{verifyCredentials.id}}" <a href="/accounts/{verifyCredentials.id}"
class="compose-box-avatar" class="compose-box-avatar"
aria-label="Profile for {{verifyCredentials.display_name || verifyCredentials.acct}}"> aria-label="Profile for {verifyCredentials.display_name || verifyCredentials.acct}">
<Avatar account={{verifyCredentials}} size="small"/> <Avatar account={verifyCredentials} size="small"/>
</a> </a>
<a class="compose-box-display-name" href="/accounts/{{verifyCredentials.id}}"> <a class="compose-box-display-name" href="/accounts/{verifyCredentials.id}">
{{verifyCredentials.display_name || verifyCredentials.acct}} {verifyCredentials.display_name || verifyCredentials.acct}
</a> </a>
<span class="compose-box-handle"> <span class="compose-box-handle">
{{'@' + verifyCredentials.acct}} {'@' + verifyCredentials.acct}
</span> </span>
<style> <style>
.compose-box-avatar { .compose-box-avatar {
@ -57,7 +57,7 @@
}, },
store: () => store, store: () => store,
computed: { computed: {
verifyCredentials: ($currentVerifyCredentials) => $currentVerifyCredentials verifyCredentials: ({ $currentVerifyCredentials }) => $currentVerifyCredentials
} }
} }
</script> </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" > aria-hidden="true" >
<ComposeAutosuggestionList <ComposeAutosuggestionList
items={{searchResults}} items={searchResults}
on:click="onClick(event)" on:click="onClick(event)"
:type {type}
:selected {selected}
/> />
</div> </div>
<style> <style>
@ -139,13 +139,13 @@
} }
}, },
computed: { computed: {
composeSelectionStart: ($composeSelectionStart) => $composeSelectionStart, composeSelectionStart: ({ $composeSelectionStart }) => $composeSelectionStart,
composeFocused: ($composeFocused) => $composeFocused, composeFocused: ({ $composeFocused }) => $composeFocused,
thisComposeFocused: (composeFocusedDeferred, realm) => composeFocusedDeferred === realm, thisComposeFocused: ({ composeFocusedDeferred, realm }) => composeFocusedDeferred === realm,
searchResults: ($composeAutosuggestionSearchResults) => $composeAutosuggestionSearchResults || [], searchResults: ({ $composeAutosuggestionSearchResults }) => $composeAutosuggestionSearchResults || [],
type: ($composeAutosuggestionType) => $composeAutosuggestionType || 'account', type: ({ $composeAutosuggestionType }) => $composeAutosuggestionType || 'account',
selected: ($composeAutosuggestionSelected) => $composeAutosuggestionSelected || 0, selected: ({ $composeAutosuggestionSelected }) => $composeAutosuggestionSelected || 0,
searchText: (text, composeSelectionStartDeferred, thisComposeFocused) => { searchText: ({ text, composeSelectionStartDeferred, thisComposeFocused }) => {
if (!thisComposeFocused) { if (!thisComposeFocused) {
return return
} }
@ -158,7 +158,7 @@
let match = textUpToCursor.match(ACCOUNT_SEARCH_REGEX) || textUpToCursor.match(EMOJI_SEARCH_REGEX) let match = textUpToCursor.match(ACCOUNT_SEARCH_REGEX) || textUpToCursor.match(EMOJI_SEARCH_REGEX)
return match && match[1] return match && match[1]
}, },
shown: (thisComposeFocused, searchText, searchResults) => { shown: ({ thisComposeFocused, searchText, searchResults }) => {
return !!(thisComposeFocused && return !!(thisComposeFocused &&
searchText && searchText &&
searchResults.length) searchResults.length)

View File

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

View File

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

View File

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

View File

@ -1,5 +1,5 @@
<div class="compose-box-length-gauge {{shouldAnimate ? 'should-animate' : ''}} {{overLimit ? 'over-char-limit' : ''}}" <div class="compose-box-length-gauge {shouldAnimate ? 'should-animate' : ''} {overLimit ? 'over-char-limit' : ''}"
style="transform: scaleX({{lengthAsFractionDeferred}});" style="transform: scaleX({lengthAsFractionDeferred});"
aria-hidden="true" aria-hidden="true"
></div> ></div>
<style> <style>
@ -45,7 +45,7 @@
}), }),
store: () => store, store: () => store,
computed: { 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 // 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) let int = Math.round(Math.min(CHAR_LIMIT, length) / CHAR_LIMIT * 100)
return (int - (int % 2)) / 100 return (int - (int % 2)) / 100

View File

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

View File

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

View File

@ -1,8 +1,8 @@
<div class="compose-media"> <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"> <div class="compose-media-delete">
<button class="compose-media-delete-button" <button class="compose-media-delete-button"
aria-label="Delete {{mediaItem.file.name}}" aria-label="Delete {mediaItem.file.name}"
on:click="onDeleteMedia()" > on:click="onDeleteMedia()" >
<svg class="compose-media-delete-button-svg"> <svg class="compose-media-delete-button-svg">
<use xlink:href="#fa-times" /> <use xlink:href="#fa-times" />
@ -12,7 +12,7 @@
<div class="compose-media-alt"> <div class="compose-media-alt">
<input type="text" <input type="text"
placeholder="Description" 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 bind:value=rawText
> >
</div> </div>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,24 +1,24 @@
<div class="account-profile-avatar"> <div class="account-profile-avatar">
<Avatar :account size="big" /> <Avatar {account} size="big" />
</div> </div>
<div class="account-profile-name"> <div class="account-profile-name">
<ExternalLink href={{account.url}} <ExternalLink href={account.url}
showIcon="true" showIcon="true"
normalIconColor="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> </ExternalLink>
</div> </div>
<div class="account-profile-username"> <div class="account-profile-username">
{{'@' + account.acct}} {'@' + account.acct}
</div> </div>
<div class="account-profile-followed-by"> <div class="account-profile-followed-by">
{{#if relationship && relationship.blocking}} {#if relationship && relationship.blocking}
<span class="account-profile-followed-by-span">Blocked</span> <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> <span class="account-profile-followed-by-span">Follows you</span>
{{/if}} {/if}
</div> </div>
<style> <style>
.account-profile-followed-by { .account-profile-followed-by {

View File

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

View File

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

View File

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

View File

@ -1,16 +1,16 @@
{{#if props}} {#if props}
<PseudoVirtualListItem :component <PseudoVirtualListItem {component}
:props {props}
:key {key}
:index {index}
:length {length}
:intersectionObserver {intersectionObserver}
:isIntersecting {isIntersecting}
:isCached {isCached}
:height {height}
on:scrollToPosition on:scrollToPosition
/> />
{{/if}} {/if}
<script> <script>
import PseudoVirtualListItem from './PseudoVirtualListItem.html' import PseudoVirtualListItem from './PseudoVirtualListItem.html'
import { mark, stop } from '../../_utils/marks' 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"> <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"> <div class="search-result-account-name">
{{account.display_name || account.acct}} {account.display_name || account.acct}
</div> </div>
<div class="search-result-account-username"> <div class="search-result-account-username">
{{'@' + account.acct}} {'@' + account.acct}
</div> </div>
{{#if actions && actions.length}} {#if actions && actions.length}
<div class="search-result-account-buttons"> <div class="search-result-account-buttons">
{{#each actions as action}} {#each actions as action}
<IconButton <IconButton
label={{action.label}} label={action.label}
on:click="onButtonClick(event, action, account.id)" on:click="onButtonClick(event, action, account.id)"
href={{action.icon}} href={action.icon}
big="true" big="true"
/> />
{{/each}} {/each}
</div> </div>
{{/if}} {/if}
</div> </div>
</SearchResult> </SearchResult>
<style> <style>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,8 +1,8 @@
<div class="status-media {{sensitive ? 'status-media-is-sensitive' : ''}}" <div class="status-media {sensitive ? 'status-media-is-sensitive' : ''}"
style="grid-template-columns: repeat(auto-fit, minmax({{maxMediaWidth}}px, 1fr));" > style="grid-template-columns: repeat(auto-fit, minmax({maxMediaWidth}px, 1fr));" >
{{#each mediaAttachments as media}} {#each mediaAttachments as media}
<Media :media :uuid /> <Media {media} {uuid} />
{{/each}} {/each}
</div> </div>
<style> <style>
.status-media { .status-media {
@ -36,7 +36,7 @@
export default { export default {
computed: { computed: {
maxMediaWidth: (mediaAttachments) => { maxMediaWidth: ({ mediaAttachments }) => {
return Math.max.apply(Math, mediaAttachments.map(media => { return Math.max.apply(Math, mediaAttachments.map(media => {
return media.meta && media.meta.small && typeof media.meta.small.width === 'number' ? media.meta.small.width : DEFAULT_MEDIA_WIDTH return media.meta && media.meta.small && typeof media.meta.small.width === 'number' ? media.meta.small.width : DEFAULT_MEDIA_WIDTH
})) }))

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,26 +1,26 @@
<div class="status-details"> <div class="status-details">
<ExternalLink className="status-absolute-date" <ExternalLink className="status-absolute-date"
href={{originalStatus.url}} href={originalStatus.url}
showIcon="true" 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> </ExternalLink>
<a class="status-favs-reblogs" <a class="status-favs-reblogs"
href="/statuses/{{originalStatusId}}/reblogs" href="/statuses/{originalStatusId}/reblogs"
aria-label={{reblogsLabel}}> aria-label={reblogsLabel}>
<svg class="status-favs-reblogs-svg"> <svg class="status-favs-reblogs-svg">
<use xlink:href="#fa-retweet"/> <use xlink:href="#fa-retweet"/>
</svg> </svg>
<span>{{numReblogs}}</span> <span>{numReblogs}</span>
</a> </a>
<a class="status-favs-reblogs" <a class="status-favs-reblogs"
href="/statuses/{{originalStatusId}}/favorites" href="/statuses/{originalStatusId}/favorites"
aria-label={{favoritesLabel}}> aria-label={favoritesLabel}>
<svg class="status-favs-reblogs-svg"> <svg class="status-favs-reblogs-svg">
<use xlink:href="#fa-star" /> <use xlink:href="#fa-star" />
</svg> </svg>
<span>{{numFavs}}</span> <span>{numFavs}</span>
</a> </a>
</div> </div>
<style> <style>
@ -99,17 +99,17 @@
export default { export default {
computed: { computed: {
createdAtDate: (originalStatus) => originalStatus.created_at, createdAtDate: ({ originalStatus }) => originalStatus.created_at,
numReblogs: (originalStatus) => originalStatus.reblogs_count || 0, numReblogs: ({ originalStatus }) => originalStatus.reblogs_count || 0,
numFavs: (originalStatus) => originalStatus.favourites_count || 0, numFavs: ({ originalStatus }) => originalStatus.favourites_count || 0,
formattedDate: (createdAtDate) => formatter.format(new Date(createdAtDate)), formattedDate: ({ createdAtDate }) => formatter.format(new Date(createdAtDate)),
reblogsLabel: (numReblogs) => { reblogsLabel: ({ numReblogs }) => {
// TODO: intl // TODO: intl
return numReblogs === 1 return numReblogs === 1
? `Boosted ${numReblogs} time` ? `Boosted ${numReblogs} time`
: `Boosted ${numReblogs} times` : `Boosted ${numReblogs} times`
}, },
favoritesLabel: (numFavs) => { favoritesLabel: ({ numFavs }) => {
// TODO: intl // TODO: intl
return numFavs === 1 return numFavs === 1
? `Favorited ${numFavs} time` ? `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 {isStatusInNotification ? 'status-in-notification' : ''} {notification && notification.type === 'follow' ? 'header-is-follow' : ''}">
<div class="status-header-avatar {{timelineType === 'pinned' ? 'hidden' : ''}}"> <div class="status-header-avatar {timelineType === 'pinned' ? 'hidden' : ''}">
<Avatar :account size="extra-small"/> <Avatar {account} size="extra-small"/>
</div> </div>
<svg class="status-header-svg"> <svg class="status-header-svg">
<use xlink:href={{icon}}/> <use xlink:href={icon}/>
</svg> </svg>
<span class="status-header-span"> <span class="status-header-span">
{{#if timelineType === 'pinned'}} {#if timelineType === 'pinned'}
Pinned toot Pinned toot
{{else}} {:else}
<a href="/accounts/{{accountId}}" <a href="/accounts/{accountId}"
class="status-header-a" class="status-header-a"
title="{{'@' + account.acct}}" title="{'@' + account.acct}"
focus-key={{focusKey}} > focus-key={focusKey} >
{{account.display_name || account.username}} {account.display_name || account.username}
</a> </a>
{{#if notification && notification.type === 'reblog'}} {#if notification && notification.type === 'reblog'}
boosted your status boosted your status
{{elseif notification && notification.type === 'favourite'}} {:elseif notification && notification.type === 'favourite'}
favorited your status favorited your status
{{elseif notification && notification.type === 'follow'}} {:elseif notification && notification.type === 'follow'}
followed you followed you
{{elseif status && status.reblog}} {:elseif status && status.reblog}
boosted boosted
{{/if}} {/if}
{{/if}} {/if}
</span> </span>
</div> </div>
<style> <style>
@ -88,8 +88,8 @@
Avatar Avatar
}, },
computed: { computed: {
focusKey: (uuid) => `status-header-${uuid}`, focusKey: ({ uuid }) => `status-header-${uuid}`,
icon: (notification, status, timelineType) => { icon: ({ notification, status, timelineType }) => {
if (timelineType === 'pinned') { if (timelineType === 'pinned') {
return '#fa-thumb-tack' return '#fa-thumb-tack'
} else if ((notification && notification.type === 'reblog') || (status && status.reblog)) { } else if ((notification && notification.type === 'reblog') || (status && status.reblog)) {

View File

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

View File

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

View File

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

View File

@ -1,9 +1,9 @@
<div class="status-spoiler {{isStatusInNotification ? 'status-in-notification' : ''}} {{isStatusInOwnThread ? 'status-in-own-thread' : ''}}"> <div class="status-spoiler {isStatusInNotification ? 'status-in-notification' : ''} {isStatusInOwnThread ? 'status-in-own-thread' : ''}">
<p>{{{massagedSpoilerText}}}</p> <p>{@html massagedSpoilerText}</p>
</div> </div>
<div class="status-spoiler-button {{isStatusInOwnThread ? 'status-in-own-thread' : ''}}"> <div class="status-spoiler-button {isStatusInOwnThread ? 'status-in-own-thread' : ''}">
<button type="button" delegate-key={{delegateKey}}> <button type="button" delegate-key={delegateKey}>
{{spoilerShown ? 'Show less' : 'Show more'}} {spoilerShown ? 'Show less' : 'Show more'}
</button> </button>
</div> </div>
<style> <style>
@ -60,13 +60,13 @@
}, },
store: () => store, store: () => store,
computed: { computed: {
spoilerText: (originalStatus) => originalStatus.spoiler_text, spoilerText: ({ originalStatus }) => originalStatus.spoiler_text,
emojis: (originalStatus) => originalStatus.emojis, emojis: ({ originalStatus }) => originalStatus.emojis,
massagedSpoilerText: (spoilerText, emojis, $autoplayGifs) => { massagedSpoilerText: ({ spoilerText, emojis, $autoplayGifs }) => {
spoilerText = escapeHtml(spoilerText) spoilerText = escapeHtml(spoilerText)
return emojifyText(spoilerText, emojis, $autoplayGifs) return emojifyText(spoilerText, emojis, $autoplayGifs)
}, },
delegateKey: (uuid) => `spoiler-${uuid}` delegateKey: ({ uuid }) => `spoiler-${uuid}`
}, },
methods: { methods: {
onClickSpoilerButton () { 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 <IconButton
className="status-toolbar-reply-button" className="status-toolbar-reply-button"
label={{replyLabel}} label={replyLabel}
pressable="true" pressable="true"
pressed={{replyShown}} pressed={replyShown}
href="#fa-reply" href="#fa-reply"
delegateKey={{replyKey}} delegateKey={replyKey}
focusKey={{replyKey}} focusKey={replyKey}
/> />
<IconButton <IconButton
label={{reblogLabel}} label={reblogLabel}
pressable={{!reblogDisabled}} pressable={!reblogDisabled}
pressed={{reblogged}} pressed={reblogged}
disabled={{reblogDisabled}} disabled={reblogDisabled}
href={{reblogIcon}} href={reblogIcon}
delegateKey={{reblogKey}} delegateKey={reblogKey}
ref:reblogIcon ref:reblogIcon
/> />
<IconButton <IconButton
label="Favorite" label="Favorite"
pressable="true" pressable="true"
pressed={{favorited}} pressed={favorited}
href="#fa-star" href="#fa-star"
delegateKey={{favoriteKey}} delegateKey={favoriteKey}
ref:favoriteIcon ref:favoriteIcon
/> />
<IconButton <IconButton
label="Show more options" label="Show more options"
href="#fa-ellipsis-h" href="#fa-ellipsis-h"
delegateKey={{optionsKey}} delegateKey={optionsKey}
/> />
</div> </div>
<style> <style>
@ -133,8 +133,8 @@
reblogAnimation: REBLOG_ANIMATION reblogAnimation: REBLOG_ANIMATION
}), }),
computed: { computed: {
replyLabel: (replyShown) => replyShown ? 'Close reply' : 'Reply', replyLabel: ({ replyShown }) => replyShown ? 'Close reply' : 'Reply',
reblogLabel: (visibility) => { reblogLabel: ({ visibility }) => {
switch (visibility) { switch (visibility) {
case 'private': case 'private':
return 'Cannot be boosted because this is followers-only' return 'Cannot be boosted because this is followers-only'
@ -144,7 +144,7 @@
return 'Boost' return 'Boost'
} }
}, },
reblogIcon: (visibility) => { reblogIcon: ({ visibility }) => {
switch (visibility) { switch (visibility) {
case 'private': case 'private':
return '#fa-lock' return '#fa-lock'
@ -154,25 +154,25 @@
return '#fa-retweet' return '#fa-retweet'
} }
}, },
reblogDisabled: (visibility) => { reblogDisabled: ({ visibility }) => {
return visibility === 'private' || visibility === 'direct' return visibility === 'private' || visibility === 'direct'
}, },
reblogged: (originalStatusId, $currentStatusModifications, originalStatus) => { reblogged: ({ originalStatusId, $currentStatusModifications, originalStatus }) => {
if ($currentStatusModifications && originalStatusId in $currentStatusModifications.reblogs) { if ($currentStatusModifications && originalStatusId in $currentStatusModifications.reblogs) {
return $currentStatusModifications.reblogs[originalStatusId] return $currentStatusModifications.reblogs[originalStatusId]
} }
return originalStatus.reblogged return originalStatus.reblogged
}, },
favorited: (originalStatusId, $currentStatusModifications, originalStatus) => { favorited: ({ originalStatusId, $currentStatusModifications, originalStatus }) => {
if ($currentStatusModifications && originalStatusId in $currentStatusModifications.favorites) { if ($currentStatusModifications && originalStatusId in $currentStatusModifications.favorites) {
return $currentStatusModifications.favorites[originalStatusId] return $currentStatusModifications.favorites[originalStatusId]
} }
return originalStatus.favourited return originalStatus.favourited
}, },
favoriteKey: (uuid) => `fav-${uuid}`, favoriteKey: ({ uuid }) => `fav-${uuid}`,
reblogKey: (uuid) => `reblog-${uuid}`, reblogKey: ({ uuid }) => `reblog-${uuid}`,
replyKey: (uuid) => `reply-${uuid}`, replyKey: ({ uuid }) => `reply-${uuid}`,
optionsKey: (uuid) => `options-${uuid}` optionsKey: ({ uuid }) => `options-${uuid}`
} }
} }
</script> </script>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,9 +1,9 @@
<Status status={{virtualProps.status}} <Status status={virtualProps.status}
timelineType={{virtualProps.timelineType}} timelineType={virtualProps.timelineType}
timelineValue={{virtualProps.timelineValue}} timelineValue={virtualProps.timelineValue}
focusSelector={{virtualProps.focusSelector}} focusSelector={virtualProps.focusSelector}
index={{virtualIndex}} index={virtualIndex}
length={{virtualLength}} length={virtualLength}
on:recalculateHeight /> on:recalculateHeight />
<script> <script>
import Status from '../status/Status.html' 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" <div class="timeline"
role="feed" role="feed"
on:focusWithCapture="saveFocus(event)" on:focusWithCapture="saveFocus(event)"
on:blurWithCapture="clearFocus(event)" on:blurWithCapture="clearFocus(event)"
> >
{{#await componentsPromise}} {#await componentsPromise}
<!-- awaiting promise --> <!-- awaiting promise -->
{{then result}} {:then result}
<:Component {result.listComponent} <svelte:component this={result.listComponent}
component={{result.listItemComponent}} component={result.listItemComponent}
realm="{{$currentInstance + '/' + timeline}}" realm="{$currentInstance + '/' + timeline}"
containerQuery=".container" containerQuery=".container"
:makeProps {makeProps}
items={{$timelineItemIds}} items={$timelineItemIds}
showFooter={{$timelineInitialized && $runningUpdate}} showFooter={$timelineInitialized && $runningUpdate}
footerComponent={{LoadingFooter}} footerComponent={LoadingFooter}
showHeader={{$showHeader}} showHeader={$showHeader}
headerComponent={{MoreHeaderVirtualWrapper}} headerComponent={MoreHeaderVirtualWrapper}
:headerProps {headerProps}
:scrollToItem {scrollToItem}
on:scrollToBottom="onScrollToBottom()" on:scrollToBottom="onScrollToBottom()"
on:scrollToTop="onScrollToTop()" on:scrollToTop="onScrollToTop()"
on:scrollTopChanged="onScrollTopChanged(event)" on:scrollTopChanged="onScrollTopChanged(event)"
on:initialized="initialize()" on:initialized="initialize()"
on:noNeedToScroll="onNoNeedToScroll()" on:noNeedToScroll="onNoNeedToScroll()"
/> />
{{catch error}} {:catch error}
<div>Error: component failed to load! Try reloading. {{error}}</div> <div>Error: component failed to load! Try reloading. {error}</div>
{{/await}} {/await}
</div> </div>
<script> <script>
import { store } from '../../_store/store' 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. // 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 // Here we lazy-load both the virtual list component itself as well as the component
// it renders. // it renders.
componentsPromise: (timelineType) => { componentsPromise: ({ timelineType }) => {
return Promise.all([ return Promise.all([
timelineType === 'status' timelineType === 'status'
? importPseudoVirtualList() ? importPseudoVirtualList()
@ -95,7 +95,7 @@
listItemComponent: results[1] listItemComponent: results[1]
})) }))
}, },
makeProps: ($currentInstance, timelineType, timelineValue) => async (itemId) => { makeProps: ({ $currentInstance, timelineType, timelineValue }) => async (itemId) => {
let res = { let res = {
timelineType, timelineType,
timelineValue timelineValue
@ -107,7 +107,7 @@
} }
return res return res
}, },
label: (timeline, $currentInstance, timelineType, timelineValue) => { label: ({ timeline, $currentInstance, timelineType, timelineValue }) => {
if (timelines[timeline]) { if (timelines[timeline]) {
return `${timelines[timeline].label} timeline for ${$currentInstance}` return `${timelines[timeline].label} timeline for ${$currentInstance}`
} }
@ -125,20 +125,20 @@
return `Notifications for ${$currentInstance}` return `Notifications for ${$currentInstance}`
} }
}, },
timelineType: (timeline) => { timelineType: ({ timeline }) => {
return timeline.split('/')[0] return timeline.split('/')[0]
}, },
timelineValue: (timeline) => { timelineValue: ({ timeline }) => {
return timeline.split('/').slice(-1)[0] return timeline.split('/').slice(-1)[0]
}, },
// Scroll to the first item if this is a "status in own thread" timeline. // Scroll to the first item if this is a "status in own thread" timeline.
// Don't scroll to the first item because it obscures the "back" button. // Don't scroll to the first item because it obscures the "back" button.
scrollToItem: (timelineType, timelineValue, $firstTimelineItemId) => ( scrollToItem: ({ timelineType, timelineValue, $firstTimelineItemId }) => (
timelineType === 'status' && $firstTimelineItemId && timelineType === 'status' && $firstTimelineItemId &&
timelineValue !== $firstTimelineItemId && timelineValue timelineValue !== $firstTimelineItemId && timelineValue
), ),
itemIdsToAdd: ($itemIdsToAdd) => $itemIdsToAdd, itemIdsToAdd: ({ $itemIdsToAdd }) => $itemIdsToAdd,
headerProps: (itemIdsToAdd) => { headerProps: ({ itemIdsToAdd }) => {
return { return {
count: itemIdsToAdd ? itemIdsToAdd.length : 0, count: itemIdsToAdd ? itemIdsToAdd.length : 0,
onClick: showMoreItemsForCurrentTimeline 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" <div class="virtual-list"
style="height: {{$height}}px;" style="height: {$height}px;"
ref:node > ref:node >
<VirtualListHeader component={{headerComponent}} virtualProps={{headerProps}} shown={{$showHeader}}/> <VirtualListHeader component={headerComponent} virtualProps={headerProps} shown={$showHeader}/>
{{#if $visibleItems}} {#if $visibleItems}
{{#each $visibleItems as visibleItem @key}} {#each $visibleItems as visibleItem (visibleItem.key)}
<VirtualListLazyItem :component <VirtualListLazyItem {component}
offset={{visibleItem.offset}} offset={visibleItem.offset}
:makeProps {makeProps}
key={{visibleItem.key}} key={visibleItem.key}
index={{visibleItem.index}} index={visibleItem.index}
/> />
{{/each}} {/each}
{{/if}} {/if}
{{#if $showFooter}} {#if $showFooter}
<VirtualListFooter component={{footerComponent}} /> <VirtualListFooter component={footerComponent} />
{{/if}} {/if}
</div> </div>
</VirtualListContainer> </VirtualListContainer>
<style> <style>
@ -101,12 +101,12 @@
VirtualListHeader VirtualListHeader
}, },
computed: { computed: {
distanceFromBottom: ($scrollHeight, $scrollTop, $offsetHeight) => { distanceFromBottom: ({ $scrollHeight, $scrollTop, $offsetHeight }) => {
return $scrollHeight - $scrollTop - $offsetHeight return $scrollHeight - $scrollTop - $offsetHeight
}, },
scrollTop: ($scrollTop) => $scrollTop, scrollTop: ({ $scrollTop }) => $scrollTop,
// TODO: bug in svelte store, shouldn't need to do this // TODO: bug in svelte store, shouldn't need to do this
allVisibleItemsHaveHeight: ($allVisibleItemsHaveHeight) => $allVisibleItemsHaveHeight allVisibleItemsHaveHeight: ({ $allVisibleItemsHaveHeight }) => $allVisibleItemsHaveHeight
}, },
methods: { methods: {
observe, observe,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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