forked from cybrespace/pinafore
upgrade to svelte 2.0 (#251)
* upgrade to svelte 2.0 * update svelte-loader to 2.9.0
This commit is contained in:
parent
d2d82ba2e3
commit
42be854521
|
@ -9786,9 +9786,9 @@
|
|||
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
|
||||
},
|
||||
"svelte": {
|
||||
"version": "1.64.1",
|
||||
"resolved": "https://registry.npmjs.org/svelte/-/svelte-1.64.1.tgz",
|
||||
"integrity": "sha512-RsEAcVYF90Bq5y4Lgg56LyKiuxiyDTU+5TG2GM0ppa50z446de0vQgnA3eQTrgecPdRR89ZIqNqN1cgdAdO7wQ=="
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/svelte/-/svelte-2.4.1.tgz",
|
||||
"integrity": "sha512-49huVkAZV42sLny2/d6fU4Dzg605hkSQfNxISv34Kkb7M5MxmMhe9ywQ3+didcqwiHAqXn0/P0MojdbqU58ZIQ=="
|
||||
},
|
||||
"svelte-dev-helper": {
|
||||
"version": "1.1.7",
|
||||
|
@ -9801,13 +9801,12 @@
|
|||
"integrity": "sha512-yoxNehbDxGEHxJBTWq2RpIPDTHlNNy6eGR7RPSK7qsh8hoyOXbji8uF//l4+I/l2fLP+E8pQTJYrduPXrW3wsw=="
|
||||
},
|
||||
"svelte-loader": {
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/svelte-loader/-/svelte-loader-2.8.1.tgz",
|
||||
"integrity": "sha512-t3cfLeYCkuz1eJem+urdCYrhI12qUz03wlYzaRJ6oER1qrKBRlOpq8S4ZraInsw2FtKGFbu/VBYekLJS07Ipnw==",
|
||||
"version": "2.9.0",
|
||||
"resolved": "https://registry.npmjs.org/svelte-loader/-/svelte-loader-2.9.0.tgz",
|
||||
"integrity": "sha512-DmzPUCDBN/G/MKvi3iJZ6MDpoPKqN+um9PS8XBJn6yT6Kbu0pkU5AsdDdqauyKx2wEVQZ7DqpT9agWmDCr5TQg==",
|
||||
"requires": {
|
||||
"loader-utils": "1.1.0",
|
||||
"svelte-dev-helper": "1.1.7",
|
||||
"tmp": "0.0.31"
|
||||
"svelte-dev-helper": "1.1.7"
|
||||
}
|
||||
},
|
||||
"svelte-transitions": {
|
||||
|
@ -10469,6 +10468,7 @@
|
|||
"version": "0.0.31",
|
||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.31.tgz",
|
||||
"integrity": "sha1-jzirlDjhcxXl29izZX6L+yd65Kc=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"os-tmpdir": "1.0.2"
|
||||
}
|
||||
|
|
|
@ -77,9 +77,9 @@
|
|||
"shrink-ray-current": "2.1.0",
|
||||
"stringz": "1.0.0",
|
||||
"style-loader": "0.21.0",
|
||||
"svelte": "1.64.1",
|
||||
"svelte": "2.4.1",
|
||||
"svelte-extras": "2.0.2",
|
||||
"svelte-loader": "2.8.1",
|
||||
"svelte-loader": "2.9.0",
|
||||
"svelte-transitions": "1.1.1",
|
||||
"svgo": "1.0.5",
|
||||
"timeago.js": "3.0.2",
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
<div class="accounts-page">
|
||||
{{#if loading}}
|
||||
{#if loading}
|
||||
<LoadingPage />
|
||||
{{elseif accounts && accounts.length}}
|
||||
{:elseif accounts && accounts.length}
|
||||
<ul class="accounts-results">
|
||||
{{#each accounts as account}}
|
||||
{#each accounts as account}
|
||||
<AccountSearchResult
|
||||
:account
|
||||
actions={{accountActions}}
|
||||
{account}
|
||||
actions={accountActions}
|
||||
on:click="onClickAction(event)"
|
||||
/>
|
||||
{{/each}}
|
||||
{/each}
|
||||
</ul>
|
||||
{{/if}}
|
||||
{/if}
|
||||
</div>
|
||||
<style>
|
||||
.accounts-page {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<video
|
||||
class="autoplay-video {{className || ''}}"
|
||||
aria-label={{ariaLabel || ''}}
|
||||
style="background-image: url({{poster}});"
|
||||
:poster
|
||||
:width
|
||||
:height
|
||||
:src
|
||||
class="autoplay-video {className || ''}"
|
||||
aria-label={ariaLabel || ''}
|
||||
style="background-image: url({poster});"
|
||||
{poster}
|
||||
{width}
|
||||
{height}
|
||||
{src}
|
||||
autoplay
|
||||
muted
|
||||
loop
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
{{#if error}}
|
||||
<svg class={{computedClass}} aria-hidden="true">
|
||||
{#if error}
|
||||
<svg class={computedClass} aria-hidden="true">
|
||||
<use xlink:href="#fa-user" />
|
||||
</svg>
|
||||
{{elseif $autoplayGifs}}
|
||||
{:elseif $autoplayGifs}
|
||||
<img
|
||||
class={{computedClass}}
|
||||
class={computedClass}
|
||||
aria-hidden="true"
|
||||
alt=""
|
||||
src={{account.avatar}}
|
||||
src={account.avatar}
|
||||
on:imgLoad="set({loaded: true})"
|
||||
on:imgLoadError="set({error: true})" />
|
||||
{{else}}
|
||||
{:else}
|
||||
<NonAutoplayImg
|
||||
className={{computedClass}}
|
||||
className={computedClass}
|
||||
ariaHidden="true"
|
||||
alt=""
|
||||
src={{account.avatar}}
|
||||
staticSrc={{account.avatar_static}}
|
||||
:isLink
|
||||
src={account.avatar}
|
||||
staticSrc={account.avatar_static}
|
||||
{isLink}
|
||||
on:imgLoad="set({loaded: true})"
|
||||
on:imgLoadError="set({error: true})"
|
||||
/>
|
||||
{{/if}}
|
||||
{/if}
|
||||
<style>
|
||||
:global(.avatar) {
|
||||
border-radius: 4px;
|
||||
|
@ -82,7 +82,7 @@
|
|||
}),
|
||||
store: () => store,
|
||||
computed: {
|
||||
computedClass: (className, loaded, size) => (classname(
|
||||
computedClass: ({ className, loaded, size }) => (classname(
|
||||
'avatar',
|
||||
className,
|
||||
loaded && 'loaded',
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<div class="dynamic-page-banner {{icon ? 'dynamic-page-with-icon' : ''}}">
|
||||
{{#if icon}}
|
||||
<div class="dynamic-page-banner {icon ? 'dynamic-page-with-icon' : ''}">
|
||||
{#if icon}
|
||||
<svg class="dynamic-page-banner-svg">
|
||||
<use xlink:href={{icon}} />
|
||||
<use xlink:href={icon} />
|
||||
</svg>
|
||||
{{/if}}
|
||||
<h1 class="dynamic-page-title">{{title}}</h1>
|
||||
{/if}
|
||||
<h1 class="dynamic-page-title">{title}</h1>
|
||||
<button type="button"
|
||||
class="dynamic-page-go-back"
|
||||
on:click="onGoBack(event)">Back</button>
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<a rel="nofollow noopener"
|
||||
target="_blank"
|
||||
:href
|
||||
aria-label={{ariaLabel}}
|
||||
class="{{className || ''}} {{showIcon ? 'external-link-with-icon' : ''}} {{normalIconColor ? 'normal-icon-color' : ''}}">
|
||||
<slot></slot>{{#if showIcon}}
|
||||
{href}
|
||||
aria-label={ariaLabel}
|
||||
class="{className || ''} {showIcon ? 'external-link-with-icon' : ''} {normalIconColor ? 'normal-icon-color' : ''}">
|
||||
<slot></slot>{#if showIcon}
|
||||
<svg class="external-link-svg">
|
||||
<use xlink:href="#fa-external-link" />
|
||||
</svg>
|
||||
{{/if}}</a>
|
||||
{/if}</a>
|
||||
<style>
|
||||
.external-link-with-icon {
|
||||
display: inline-flex;
|
||||
|
|
|
@ -1,30 +1,30 @@
|
|||
{{#if delegateKey}}
|
||||
{#if delegateKey}
|
||||
<button type="button"
|
||||
title={{label}}
|
||||
aria-label={{label}}
|
||||
aria-pressed={{pressable ? !!pressed : ''}}
|
||||
class={{computedClass}}
|
||||
:disabled
|
||||
delegate-key={{delegateKey}}
|
||||
focus-key={{focusKey || ''}} >
|
||||
<svg class="icon-button-svg {{svgClassName || ''}}" ref:svg>
|
||||
<use xlink:href={{href}} />
|
||||
title={label}
|
||||
aria-label={label}
|
||||
aria-pressed={pressable ? !!pressed : ''}
|
||||
class={computedClass}
|
||||
{disabled}
|
||||
delegate-key={delegateKey}
|
||||
focus-key={focusKey || ''} >
|
||||
<svg class="icon-button-svg {svgClassName || ''}" ref:svg>
|
||||
<use xlink:href={href} />
|
||||
</svg>
|
||||
</button>
|
||||
{{else}}
|
||||
{:else}
|
||||
<button type="button"
|
||||
title={{label}}
|
||||
aria-label={{label}}
|
||||
aria-pressed={{pressable ? !!pressed : ''}}
|
||||
class={{computedClass}}
|
||||
focus-key={{focusKey || ''}}
|
||||
:disabled
|
||||
title={label}
|
||||
aria-label={label}
|
||||
aria-pressed={pressable ? !!pressed : ''}
|
||||
class={computedClass}
|
||||
focus-key={focusKey || ''}
|
||||
{disabled}
|
||||
on:click >
|
||||
<svg class="icon-button-svg {{svgClassName || ''}}" ref:svg>
|
||||
<use xlink:href={{href}} />
|
||||
<svg class="icon-button-svg {svgClassName || ''}" ref:svg>
|
||||
<use xlink:href={href} />
|
||||
</svg>
|
||||
</button>
|
||||
{{/if}}
|
||||
{/if}
|
||||
<style>
|
||||
.icon-button {
|
||||
padding: 6px 10px;
|
||||
|
@ -118,7 +118,7 @@
|
|||
}),
|
||||
store: () => store,
|
||||
computed: {
|
||||
computedClass: (pressable, pressed, big, muted, className) => {
|
||||
computedClass: ({ pressable, pressed, big, muted, className }) => {
|
||||
return classname(
|
||||
'icon-button',
|
||||
!pressable && 'not-pressable',
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<Nav :page />
|
||||
<Nav {page} />
|
||||
|
||||
<div class="container" tabindex="0" ref:container>
|
||||
<main>
|
||||
<slot></slot>
|
||||
</main>
|
||||
{{#if !$isUserLoggedIn && page === 'home'}}
|
||||
{#if !$isUserLoggedIn && page === 'home'}
|
||||
<InformationalFooter />
|
||||
{{/if}}
|
||||
{/if}
|
||||
</div>
|
||||
<script>
|
||||
import Nav from './Nav.html'
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
<div class="lazy-image"
|
||||
style="width: {{width}}px; height: {{height}}px; background: {{background}};">
|
||||
{{#if displaySrc}}
|
||||
style="width: {width}px; height: {height}px; background: {background};">
|
||||
{#if displaySrc}
|
||||
<img
|
||||
class="{{hidden ? 'hidden' : ''}} {{className || ''}}"
|
||||
aria-hidden={{ariaHidden || ''}}
|
||||
alt={{alt || ''}}
|
||||
title={{alt || ''}}
|
||||
src={{displaySrc}}
|
||||
:width
|
||||
:height
|
||||
class="{hidden ? 'hidden' : ''} {className || ''}"
|
||||
aria-hidden={ariaHidden || ''}
|
||||
alt={alt || ''}
|
||||
title={alt || ''}
|
||||
src={displaySrc}
|
||||
{width}
|
||||
{height}
|
||||
/>
|
||||
{{/if}}
|
||||
{/if}
|
||||
</div>
|
||||
<style>
|
||||
.lazy-image {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{{#if revealed}}
|
||||
<:Component {pageComponent} :params />
|
||||
{{/if}}
|
||||
{#if revealed}
|
||||
<svelte:component this={pageComponent} {params} />
|
||||
{/if}
|
||||
<script>
|
||||
// On the very first page load, avoid doing a "reveal" because
|
||||
// it leads to a flash between when the SSR is shown, the two frame we hide it,
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<div class="loading-mask-container {{shown ? 'loading-mask-container-shown' : ''}}">
|
||||
{{#if shown}}
|
||||
<div class="loading-mask-container {shown ? 'loading-mask-container-shown' : ''}">
|
||||
{#if shown}
|
||||
<div class="loading-mask">
|
||||
<LoadingSpinner maskStyle="true"/>
|
||||
</div>
|
||||
{{/if}}
|
||||
{/if}
|
||||
</div>
|
||||
<style>
|
||||
.loading-mask-container {
|
||||
|
@ -37,7 +37,7 @@
|
|||
export default {
|
||||
store: () => store,
|
||||
computed: {
|
||||
shown: ($logInToInstanceLoading) => $logInToInstanceLoading
|
||||
shown: ({ $logInToInstanceLoading }) => $logInToInstanceLoading
|
||||
},
|
||||
components: {
|
||||
LoadingSpinner
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<div class="loading-page {{shown ? '' : 'hidden'}}">
|
||||
<div class="loading-page {shown ? '' : 'hidden'}">
|
||||
<LoadingSpinner />
|
||||
</div>
|
||||
<style>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<svg class="loading-spinner-icon spin {{maskStyle ? 'mask-style' : ''}}"
|
||||
style="width: {{size}}px; height: {{size}}px;"
|
||||
<svg class="loading-spinner-icon spin {maskStyle ? 'mask-style' : ''}"
|
||||
style="width: {size}px; height: {size}px;"
|
||||
aria-label="Loading"
|
||||
>
|
||||
<use xlink:href="#fa-spinner" />
|
||||
|
|
Before Width: | Height: | Size: 449 B After Width: | Height: | Size: 443 B |
|
@ -1,36 +1,36 @@
|
|||
<nav class="main-nav">
|
||||
<ul class="main-nav-ul">
|
||||
<li class="main-nav-li">
|
||||
<NavItem :page name="home" href="/" svg="#pinafore-logo" label="Home" />
|
||||
<NavItem {page} name="home" href="/" svg="#pinafore-logo" label="Home" />
|
||||
</li>
|
||||
<li class="main-nav-li">
|
||||
<NavItem :page name="notifications" href="/notifications" svg="#fa-bell" label="Notifications" />
|
||||
<NavItem {page} name="notifications" href="/notifications" svg="#fa-bell" label="Notifications" />
|
||||
</li>
|
||||
{{#if $pinnedPage === '/local'}}
|
||||
{#if $pinnedPage === '/local'}
|
||||
<li class="main-nav-li">
|
||||
<NavItem :page name="local" href="/local" svg="#fa-users" label="Local" />
|
||||
<NavItem {page} name="local" href="/local" svg="#fa-users" label="Local" />
|
||||
</li>
|
||||
{{elseif $pinnedPage === '/federated'}}
|
||||
{:elseif $pinnedPage === '/federated'}
|
||||
<li class="main-nav-li">
|
||||
<NavItem :page name="federated" href="/federated" svg="#fa-globe" label="Federated" />
|
||||
<NavItem {page} name="federated" href="/federated" svg="#fa-globe" label="Federated" />
|
||||
</li>
|
||||
{{elseif $pinnedPage === '/favorites'}}
|
||||
{:elseif $pinnedPage === '/favorites'}
|
||||
<li class="main-nav-li">
|
||||
<NavItem :page name="favorites" href="/favorites" svg="#fa-star" label="Favorites" />
|
||||
<NavItem {page} name="favorites" href="/favorites" svg="#fa-star" label="Favorites" />
|
||||
</li>
|
||||
{{elseif $pinnedPage.startsWith('/lists/')}}
|
||||
{:elseif $pinnedPage.startsWith('/lists/')}
|
||||
<li class="main-nav-li">
|
||||
<NavItem :page name="lists" href={{$pinnedPage}} svg="#fa-bars" label={{$pinnedListTitle}} />
|
||||
<NavItem {page} name="lists" href={$pinnedPage} svg="#fa-bars" label={$pinnedListTitle} />
|
||||
</li>
|
||||
{{/if}}
|
||||
{/if}
|
||||
<li class="main-nav-li">
|
||||
<NavItem :page name="community" href="/community" svg="#fa-comments" label="Community" />
|
||||
<NavItem {page} name="community" href="/community" svg="#fa-comments" label="Community" />
|
||||
</li>
|
||||
<li class="main-nav-li">
|
||||
<NavItem :page name="search" href="/search" svg="#fa-search" label="Search" />
|
||||
<NavItem {page} name="search" href="/search" svg="#fa-search" label="Search" />
|
||||
</li>
|
||||
<li class="main-nav-li">
|
||||
<NavItem :page name="settings" href="/settings" svg="#fa-gear" label="Settings" />
|
||||
<NavItem {page} name="settings" href="/settings" svg="#fa-gear" label="Settings" />
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
<a class='main-nav-link {{selected ? "selected" : ""}}'
|
||||
aria-label={{ariaLabel}}
|
||||
aria-current={{selected}}
|
||||
<a class='main-nav-link {selected ? "selected" : ""}'
|
||||
aria-label={ariaLabel}
|
||||
aria-current={selected}
|
||||
on:click="onClick(event)"
|
||||
:href >
|
||||
{{#if name === 'notifications'}}
|
||||
{href} >
|
||||
{#if name === 'notifications'}
|
||||
<div class="nav-link-svg-wrapper">
|
||||
<svg class="nav-link-svg">
|
||||
<use xlink:href={{svg}} />
|
||||
<use xlink:href={svg} />
|
||||
</svg>
|
||||
{{#if $hasNotifications}}
|
||||
{#if $hasNotifications}
|
||||
<span class="nav-link-notifications" aria-hidden="true">
|
||||
{{$numberOfNotifications}}
|
||||
{$numberOfNotifications}
|
||||
</span>
|
||||
{{/if}}
|
||||
{/if}
|
||||
</div>
|
||||
{{else}}
|
||||
{:else}
|
||||
<svg class="nav-link-svg">
|
||||
<use xlink:href={{svg}} />
|
||||
<use xlink:href={svg} />
|
||||
</svg>
|
||||
{{/if}}
|
||||
<span class="nav-link-label">{{label}}</span>
|
||||
{/if}
|
||||
<span class="nav-link-label">{label}</span>
|
||||
</a>
|
||||
<style>
|
||||
.main-nav-link {
|
||||
|
@ -122,8 +122,8 @@
|
|||
export default {
|
||||
store: () => store,
|
||||
computed: {
|
||||
selected: (page, name) => page === name,
|
||||
ariaLabel: (selected, name, label, $numberOfNotifications) => {
|
||||
selected: ({ page, name }) => page === name,
|
||||
ariaLabel: ({ selected, name, label, $numberOfNotifications }) => {
|
||||
let res = label
|
||||
if (selected) {
|
||||
res += ' (current page)'
|
||||
|
|
|
@ -1,29 +1,29 @@
|
|||
<div class="non-autoplay-gifv" style="width: {{width}}px; height: {{height}}px;"
|
||||
<div class="non-autoplay-gifv" style="width: {width}px; height: {height}px;"
|
||||
on:mouseover="onMouseOver(event)"
|
||||
ref:node
|
||||
>
|
||||
{{#if playing}}
|
||||
{#if playing}
|
||||
<AutoplayVideo
|
||||
className={{class}}
|
||||
ariaLabel={{label}}
|
||||
:poster
|
||||
:src
|
||||
:width
|
||||
:height
|
||||
className={class}
|
||||
ariaLabel={label}
|
||||
{poster}
|
||||
{src}
|
||||
{width}
|
||||
{height}
|
||||
/>
|
||||
{{else}}
|
||||
{:else}
|
||||
<LazyImage
|
||||
alt={{label || ''}}
|
||||
title={{label || ''}}
|
||||
src={{staticSrc}}
|
||||
fallback={{oneTransparentPixel}}
|
||||
:width
|
||||
:height
|
||||
alt={label || ''}
|
||||
title={label || ''}
|
||||
src={staticSrc}
|
||||
fallback={oneTransparentPixel}
|
||||
{width}
|
||||
{height}
|
||||
background="var(--loading-bg)"
|
||||
className={{class}}
|
||||
className={class}
|
||||
/>
|
||||
{{/if}}
|
||||
<PlayVideoIcon className={{playing ? 'hidden' : ''}}/>
|
||||
{/if}
|
||||
<PlayVideoIcon className={playing ? 'hidden' : ''}/>
|
||||
</div>
|
||||
<style>
|
||||
.non-autoplay-gifv {
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
{{#if staticSrc === src}}
|
||||
<img class={{className || ''}}
|
||||
aria-hidden={{ariaHidden}}
|
||||
alt={{alt || ''}}
|
||||
title={{alt || ''}}
|
||||
:src
|
||||
{#if staticSrc === src}
|
||||
<img class={className || ''}
|
||||
aria-hidden={ariaHidden}
|
||||
alt={alt || ''}
|
||||
title={alt || ''}
|
||||
{src}
|
||||
on:imgLoad
|
||||
on:imgLoadError />
|
||||
{{else}}
|
||||
<img class="{{className || ''}} non-autoplay-zoom-in {{isLink ? 'is-link' : ''}}"
|
||||
aria-hidden={{ariaHidden}}
|
||||
alt={{alt || ''}}
|
||||
title={{alt || ''}}
|
||||
src={{staticSrc}}
|
||||
{:else}
|
||||
<img class="{className || ''} non-autoplay-zoom-in {isLink ? 'is-link' : ''}"
|
||||
aria-hidden={ariaHidden}
|
||||
alt={alt || ''}
|
||||
title={alt || ''}
|
||||
src={staticSrc}
|
||||
on:imgLoad
|
||||
on:imgLoadError
|
||||
on:mouseover="onMouseOver(event)"
|
||||
ref:node />
|
||||
{{/if}}
|
||||
{/if}
|
||||
<style>
|
||||
.non-autoplay-zoom-in {
|
||||
cursor: zoom-in;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<div class="play-video-icon {{className || ''}}">
|
||||
<div class="play-video-icon {className || ''}">
|
||||
<svg class="play-video-icon-svg">
|
||||
<use xlink:href="#fa-play-circle" />
|
||||
</svg>
|
||||
|
|
|
@ -3,18 +3,18 @@
|
|||
without a div wrapper due to sticky-positioned compose button.
|
||||
TODO: this is a bit hacky due to code duplication
|
||||
-->
|
||||
<div class="timeline-home-page" aria-busy={{hideTimeline}}>
|
||||
{{#if hidePage}}
|
||||
<div class="timeline-home-page" aria-busy={hideTimeline}>
|
||||
{#if hidePage}
|
||||
<LoadingPage />
|
||||
{{/if}}
|
||||
{{#if $currentVerifyCredentials }}
|
||||
<ComposeBox realm="home" hidden={{hidePage}}/>
|
||||
{{/if}}
|
||||
{/if}
|
||||
{#if $currentVerifyCredentials }
|
||||
<ComposeBox realm="home" hidden={hidePage}/>
|
||||
{/if}
|
||||
<div class="timeline-home-anchor-container">
|
||||
{{#if !hidePage && hideTimeline}}
|
||||
{#if !hidePage && hideTimeline}
|
||||
<LoadingPage />
|
||||
{{/if}}
|
||||
<div class="timeline-home-reveal-container {{hideTimeline ? 'hidden' : ''}}">
|
||||
{/if}
|
||||
<div class="timeline-home-reveal-container {hideTimeline ? 'hidden' : ''}">
|
||||
<LazyTimeline timeline="home" />
|
||||
</div>
|
||||
</div>
|
||||
|
@ -41,8 +41,8 @@
|
|||
})
|
||||
},
|
||||
computed: {
|
||||
hidePage: ($timelineInitialized, $timelinePreinitialized) => !$timelineInitialized && !$timelinePreinitialized,
|
||||
hideTimeline: ($timelineInitialized) => !$timelineInitialized
|
||||
hidePage: ({ $timelineInitialized, $timelinePreinitialized }) => !$timelineInitialized && !$timelinePreinitialized,
|
||||
hideTimeline: ({ $timelineInitialized }) => !$timelineInitialized
|
||||
},
|
||||
store: () => store,
|
||||
components: {
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
<div class="timeline-page" aria-busy={{hideTimeline}}>
|
||||
{{#if hidePage}}
|
||||
<div class="timeline-page" aria-busy={hideTimeline}>
|
||||
{#if hidePage}
|
||||
<LoadingPage />
|
||||
{{/if}}
|
||||
<div class="timeline-slot-reveal-container {{hidePage ? 'hidden' : ''}}">
|
||||
{/if}
|
||||
<div class="timeline-slot-reveal-container {hidePage ? 'hidden' : ''}">
|
||||
<slot></slot>
|
||||
</div>
|
||||
<div class="timeline-anchor-container">
|
||||
{{#if !hidePage && hideTimeline}}
|
||||
{#if !hidePage && hideTimeline}
|
||||
<LoadingPage />
|
||||
{{/if}}
|
||||
<div class="timeline-reveal-container {{hideTimeline ? 'hidden' : ''}}">
|
||||
<LazyTimeline :timeline />
|
||||
{/if}
|
||||
<div class="timeline-reveal-container {hideTimeline ? 'hidden' : ''}">
|
||||
<LazyTimeline {timeline} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -35,8 +35,8 @@
|
|||
})
|
||||
},
|
||||
computed: {
|
||||
hidePage: ($timelineInitialized, $timelinePreinitialized) => !$timelineInitialized && !$timelinePreinitialized,
|
||||
hideTimeline: ($timelineInitialized) => !$timelineInitialized
|
||||
hidePage: ({ $timelineInitialized, $timelinePreinitialized }) => !$timelineInitialized && !$timelinePreinitialized,
|
||||
hideTimeline: ({ $timelineInitialized }) => !$timelineInitialized
|
||||
},
|
||||
store: () => store,
|
||||
components: {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div class="toast-modal {{shown ? 'shown' : ''}}" role="alert" aria-hidden={{shown}}>
|
||||
<div class="toast-modal {shown ? 'shown' : ''}" role="alert" aria-hidden={shown}>
|
||||
<div class="toast-container">
|
||||
{{text}}
|
||||
{text}
|
||||
</div>
|
||||
</div>
|
||||
<style>
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<div class="page-list-wrapper">
|
||||
{{#if label}}
|
||||
<ul class="page-list" aria-label={{label}}>
|
||||
{#if label}
|
||||
<ul class="page-list" aria-label={label}>
|
||||
<slot></slot>
|
||||
</ul>
|
||||
{{else}}
|
||||
{:else}
|
||||
<ul class="page-list">
|
||||
<slot></slot>
|
||||
</ul>
|
||||
{{/if}}
|
||||
{/if}
|
||||
</div>
|
||||
<style>
|
||||
.page-list-wrapper {
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
<li class="page-list-item">
|
||||
<a :href>
|
||||
<a {href}>
|
||||
<svg class="page-list-item-svg">
|
||||
<use xlink:href={{icon}} />
|
||||
<use xlink:href={icon} />
|
||||
</svg>
|
||||
<span aria-label="{{label}} {{$pinnedPage === href ? 'Pinned page' : 'Unpinned page'}}">
|
||||
{{label}}
|
||||
<span aria-label="{label} {$pinnedPage === href ? 'Pinned page' : 'Unpinned page'}">
|
||||
{label}
|
||||
</span>
|
||||
{{#if pinnable}}
|
||||
{#if pinnable}
|
||||
<IconButton pressable="true"
|
||||
pressed={{$pinnedPage === href}}
|
||||
label={{$pinnedPage === href ? 'Unpin timeline' : 'Pin timeline'}}
|
||||
pressed={$pinnedPage === href}
|
||||
label={$pinnedPage === href ? 'Unpin timeline' : 'Pin timeline'}
|
||||
href="#fa-thumb-tack"
|
||||
on:click="onPinClick(event)" />
|
||||
{{/if}}
|
||||
{/if}
|
||||
</a>
|
||||
</li>
|
||||
<style>
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<a href="/accounts/{{verifyCredentials.id}}"
|
||||
<a href="/accounts/{verifyCredentials.id}"
|
||||
class="compose-box-avatar"
|
||||
aria-label="Profile for {{verifyCredentials.display_name || verifyCredentials.acct}}">
|
||||
<Avatar account={{verifyCredentials}} size="small"/>
|
||||
aria-label="Profile for {verifyCredentials.display_name || verifyCredentials.acct}">
|
||||
<Avatar account={verifyCredentials} size="small"/>
|
||||
</a>
|
||||
<a class="compose-box-display-name" href="/accounts/{{verifyCredentials.id}}">
|
||||
{{verifyCredentials.display_name || verifyCredentials.acct}}
|
||||
<a class="compose-box-display-name" href="/accounts/{verifyCredentials.id}">
|
||||
{verifyCredentials.display_name || verifyCredentials.acct}
|
||||
</a>
|
||||
<span class="compose-box-handle">
|
||||
{{'@' + verifyCredentials.acct}}
|
||||
{'@' + verifyCredentials.acct}
|
||||
</span>
|
||||
<style>
|
||||
.compose-box-avatar {
|
||||
|
@ -57,7 +57,7 @@
|
|||
},
|
||||
store: () => store,
|
||||
computed: {
|
||||
verifyCredentials: ($currentVerifyCredentials) => $currentVerifyCredentials
|
||||
verifyCredentials: ({ $currentVerifyCredentials }) => $currentVerifyCredentials
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -1,10 +1,10 @@
|
|||
<div class="compose-autosuggest {{shown ? 'shown' : ''}} {{realm === 'dialog' ? 'is-dialog' : ''}}"
|
||||
<div class="compose-autosuggest {shown ? 'shown' : ''} {realm === 'dialog' ? 'is-dialog' : ''}"
|
||||
aria-hidden="true" >
|
||||
<ComposeAutosuggestionList
|
||||
items={{searchResults}}
|
||||
items={searchResults}
|
||||
on:click="onClick(event)"
|
||||
:type
|
||||
:selected
|
||||
{type}
|
||||
{selected}
|
||||
/>
|
||||
</div>
|
||||
<style>
|
||||
|
@ -139,13 +139,13 @@
|
|||
}
|
||||
},
|
||||
computed: {
|
||||
composeSelectionStart: ($composeSelectionStart) => $composeSelectionStart,
|
||||
composeFocused: ($composeFocused) => $composeFocused,
|
||||
thisComposeFocused: (composeFocusedDeferred, realm) => composeFocusedDeferred === realm,
|
||||
searchResults: ($composeAutosuggestionSearchResults) => $composeAutosuggestionSearchResults || [],
|
||||
type: ($composeAutosuggestionType) => $composeAutosuggestionType || 'account',
|
||||
selected: ($composeAutosuggestionSelected) => $composeAutosuggestionSelected || 0,
|
||||
searchText: (text, composeSelectionStartDeferred, thisComposeFocused) => {
|
||||
composeSelectionStart: ({ $composeSelectionStart }) => $composeSelectionStart,
|
||||
composeFocused: ({ $composeFocused }) => $composeFocused,
|
||||
thisComposeFocused: ({ composeFocusedDeferred, realm }) => composeFocusedDeferred === realm,
|
||||
searchResults: ({ $composeAutosuggestionSearchResults }) => $composeAutosuggestionSearchResults || [],
|
||||
type: ({ $composeAutosuggestionType }) => $composeAutosuggestionType || 'account',
|
||||
selected: ({ $composeAutosuggestionSelected }) => $composeAutosuggestionSelected || 0,
|
||||
searchText: ({ text, composeSelectionStartDeferred, thisComposeFocused }) => {
|
||||
if (!thisComposeFocused) {
|
||||
return
|
||||
}
|
||||
|
@ -158,7 +158,7 @@
|
|||
let match = textUpToCursor.match(ACCOUNT_SEARCH_REGEX) || textUpToCursor.match(EMOJI_SEARCH_REGEX)
|
||||
return match && match[1]
|
||||
},
|
||||
shown: (thisComposeFocused, searchText, searchResults) => {
|
||||
shown: ({ thisComposeFocused, searchText, searchResults }) => {
|
||||
return !!(thisComposeFocused &&
|
||||
searchText &&
|
||||
searchResults.length)
|
||||
|
|
|
@ -1,35 +1,35 @@
|
|||
<ul class="compose-autosuggest-list">
|
||||
{{#each items as item, i}}
|
||||
{#each items as item, i}
|
||||
<li class="compose-autosuggest-list-item">
|
||||
<button class="compose-autosuggest-list-button {{i === selected ? 'selected' : ''}}"
|
||||
<button class="compose-autosuggest-list-button {i === selected ? 'selected' : ''}"
|
||||
tabindex="0"
|
||||
on:click="fire('click', item)">
|
||||
<div class="compose-autosuggest-list-grid">
|
||||
{{#if type === 'account'}}
|
||||
{#if type === 'account'}
|
||||
<Avatar
|
||||
className="compose-autosuggest-list-item-avatar"
|
||||
size="small"
|
||||
account={{item}}
|
||||
account={item}
|
||||
/>
|
||||
<span class="compose-autosuggest-list-display-name">
|
||||
{{item.display_name || item.acct}}
|
||||
{item.display_name || item.acct}
|
||||
</span>
|
||||
<span class="compose-autosuggest-list-username">
|
||||
{{'@' + item.acct}}
|
||||
{'@' + item.acct}
|
||||
</span>
|
||||
{{else}}
|
||||
<img src={{$autoplayGifs ? item.url : item.static_url}}
|
||||
{:else}
|
||||
<img src={$autoplayGifs ? item.url : item.static_url}
|
||||
class="compose-autosuggest-list-item-icon"
|
||||
alt="{{':' + item.shortcode + ':'}}"
|
||||
alt="{':' + item.shortcode + ':'}"
|
||||
/>
|
||||
<span class="compose-autosuggest-list-display-name">
|
||||
{{':' + item.shortcode + ':'}}
|
||||
{':' + item.shortcode + ':'}
|
||||
</span>
|
||||
{{/if}}
|
||||
{/if}
|
||||
</div>
|
||||
</button>
|
||||
</li>
|
||||
{{/each}}
|
||||
{/each}
|
||||
</ul>
|
||||
<style>
|
||||
.compose-autosuggest-list {
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
{{#if realm === 'home'}}
|
||||
{#if realm === 'home'}
|
||||
<h1 class="sr-only">Compose toot</h1>
|
||||
{{/if}}
|
||||
<div class="{{computedClassName}} {{hideAndFadeIn}}">
|
||||
{/if}
|
||||
<div class="{computedClassName} {hideAndFadeIn}">
|
||||
<ComposeAuthor />
|
||||
{{#if contentWarningShown}}
|
||||
{#if contentWarningShown}
|
||||
<div class="compose-content-warning-wrapper"
|
||||
transition:slide="{duration: 333}">
|
||||
<ComposeContentWarning :realm :contentWarning />
|
||||
<ComposeContentWarning {realm} {contentWarning} />
|
||||
</div>
|
||||
{{/if}}
|
||||
<ComposeInput :realm :text :autoFocus on:postAction="doPostStatus()" />
|
||||
<ComposeLengthGauge :length :overLimit />
|
||||
<ComposeToolbar :realm :postPrivacy :media :contentWarningShown :text />
|
||||
<ComposeLengthIndicator :length :overLimit />
|
||||
<ComposeMedia :realm :media :mediaDescriptions />
|
||||
{/if}
|
||||
<ComposeInput {realm} {text} {autoFocus} on:postAction="doPostStatus()" />
|
||||
<ComposeLengthGauge {length} {overLimit} />
|
||||
<ComposeToolbar {realm} {postPrivacy} {media} {contentWarningShown} {text} />
|
||||
<ComposeLengthIndicator {length} {overLimit} />
|
||||
<ComposeMedia {realm} {media} {mediaDescriptions} />
|
||||
</div>
|
||||
<div class="compose-box-button-sentinel {{hideAndFadeIn}}" ref:sentinel></div>
|
||||
<div class="compose-box-button-wrapper {{realm === 'home' ? 'compose-button-sticky' : ''}} {{hideAndFadeIn}}" >
|
||||
<ComposeButton :length :overLimit :sticky on:click="onClickPostButton()" />
|
||||
<div class="compose-box-button-sentinel {hideAndFadeIn}" ref:sentinel></div>
|
||||
<div class="compose-box-button-wrapper {realm === 'home' ? 'compose-button-sticky' : ''} {hideAndFadeIn}" >
|
||||
<ComposeButton {length} {overLimit} {sticky} on:click="onClickPostButton()" />
|
||||
</div>
|
||||
{{#if !hideBottomBorder}}
|
||||
<div class="compose-box-border-bottom {{hideAndFadeIn}}"></div>
|
||||
{{/if}}
|
||||
{#if !hideBottomBorder}
|
||||
<div class="compose-box-border-bottom {hideAndFadeIn}"></div>
|
||||
{/if}
|
||||
<style>
|
||||
.compose-box {
|
||||
border-radius: 4px;
|
||||
|
@ -162,32 +162,32 @@
|
|||
}),
|
||||
store: () => store,
|
||||
computed: {
|
||||
computedClassName: (overLimit, realm, size, postPrivacyKey, isReply) => (classname(
|
||||
computedClassName: ({ overLimit, realm, size, postPrivacyKey, isReply }) => (classname(
|
||||
'compose-box',
|
||||
overLimit && 'over-char-limit',
|
||||
size === 'slim' && 'slim-size',
|
||||
isReply && postPrivacyKey === 'direct' && 'direct-reply'
|
||||
)),
|
||||
hideAndFadeIn: (hidden) => (classname(
|
||||
hideAndFadeIn: ({ hidden }) => (classname(
|
||||
'compose-box-fade-in',
|
||||
hidden && 'hidden'
|
||||
)),
|
||||
composeData: ($currentComposeData, realm) => $currentComposeData[realm] || {},
|
||||
text: (composeData) => composeData.text || '',
|
||||
media: (composeData) => composeData.media || [],
|
||||
postPrivacy: (postPrivacyKey) => POST_PRIVACY_OPTIONS.find(_ => _.key === postPrivacyKey),
|
||||
defaultPostPrivacyKey: ($currentVerifyCredentials) => $currentVerifyCredentials.source.privacy,
|
||||
postPrivacyKey: (composeData, defaultPostPrivacyKey) => composeData.postPrivacy || defaultPostPrivacyKey,
|
||||
textLength: (text) => measureText(text),
|
||||
contentWarningLength: (contentWarning) => measureText(contentWarning),
|
||||
length: (textLength, contentWarningLength, contentWarningShown) => (
|
||||
composeData: ({ $currentComposeData, realm }) => $currentComposeData[realm] || {},
|
||||
text: ({ composeData }) => composeData.text || '',
|
||||
media: ({ composeData }) => composeData.media || [],
|
||||
postPrivacy: ({ postPrivacyKey }) => POST_PRIVACY_OPTIONS.find(_ => _.key === postPrivacyKey),
|
||||
defaultPostPrivacyKey: ({ $currentVerifyCredentials }) => $currentVerifyCredentials.source.privacy,
|
||||
postPrivacyKey: ({ composeData, defaultPostPrivacyKey }) => composeData.postPrivacy || defaultPostPrivacyKey,
|
||||
textLength: ({ text }) => measureText(text),
|
||||
contentWarningLength: ({ contentWarning }) => measureText(contentWarning),
|
||||
length: ({ textLength, contentWarningLength, contentWarningShown }) => (
|
||||
textLength + (contentWarningShown ? contentWarningLength : 0)
|
||||
),
|
||||
overLimit: (length) => length > CHAR_LIMIT,
|
||||
contentWarningShown: (composeData) => composeData.contentWarningShown,
|
||||
contentWarning: (composeData) => composeData.contentWarning || '',
|
||||
timelineInitialized: ($timelineInitialized) => $timelineInitialized,
|
||||
mediaDescriptions: (composeData) => composeData.mediaDescriptions || []
|
||||
overLimit: ({ length }) => length > CHAR_LIMIT,
|
||||
contentWarningShown: ({ composeData }) => composeData.contentWarningShown,
|
||||
contentWarning: ({ composeData }) => composeData.contentWarning || '',
|
||||
timelineInitialized: ({ $timelineInitialized }) => $timelineInitialized,
|
||||
mediaDescriptions: ({ composeData }) => composeData.mediaDescriptions || []
|
||||
},
|
||||
transitions: {
|
||||
slide
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
<div class="compose-box-button-halo">
|
||||
<button class="primary compose-box-button"
|
||||
:disabled
|
||||
aria-label={{sticky ? 'Compose' : 'Toot!'}}
|
||||
{disabled}
|
||||
aria-label={sticky ? 'Compose' : 'Toot!'}
|
||||
on:click>
|
||||
<span class={{$postingStatus || sticky ? 'hidden' : ''}}>
|
||||
<span class={$postingStatus || sticky ? 'hidden' : ''}>
|
||||
Toot!
|
||||
</span>
|
||||
<div class="compose-box-button-spinner"
|
||||
aria-hidden="true">
|
||||
<svg class="compose-box-button-svg {{$postingStatus ? 'spin' : 'hidden'}}">
|
||||
<svg class="compose-box-button-svg {$postingStatus ? 'spin' : 'hidden'}">
|
||||
<use xlink:href="#fa-spinner" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div class="compose-box-button-compose {{sticky ? '' : 'hidden'}}"
|
||||
<div class="compose-box-button-compose {sticky ? '' : 'hidden'}"
|
||||
aria-hidden="true">
|
||||
<svg class="compose-box-button-svg">
|
||||
<use xlink:href="#fa-pencil" />
|
||||
|
@ -68,7 +68,7 @@
|
|||
export default {
|
||||
store: () => store,
|
||||
computed: {
|
||||
disabled: ($postingStatus, overLimit) => $postingStatus || overLimit
|
||||
disabled: ({ $postingStatus, overLimit }) => $postingStatus || overLimit
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -1,5 +1,5 @@
|
|||
<div class="compose-box-length-gauge {{shouldAnimate ? 'should-animate' : ''}} {{overLimit ? 'over-char-limit' : ''}}"
|
||||
style="transform: scaleX({{lengthAsFractionDeferred}});"
|
||||
<div class="compose-box-length-gauge {shouldAnimate ? 'should-animate' : ''} {overLimit ? 'over-char-limit' : ''}"
|
||||
style="transform: scaleX({lengthAsFractionDeferred});"
|
||||
aria-hidden="true"
|
||||
></div>
|
||||
<style>
|
||||
|
@ -45,7 +45,7 @@
|
|||
}),
|
||||
store: () => store,
|
||||
computed: {
|
||||
lengthAsFraction: (length) => {
|
||||
lengthAsFraction: ({ length }) => {
|
||||
// We don't need to update the gauge for every decimal point, so round it to the nearest 0.02
|
||||
let int = Math.round(Math.min(CHAR_LIMIT, length) / CHAR_LIMIT * 100)
|
||||
return (int - (int % 2)) / 100
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<span class="compose-box-length {{overLimit ? 'over-char-limit' : ''}}"
|
||||
aria-label={{lengthLabel}}>
|
||||
{{lengthToDisplayDeferred}}
|
||||
<span class="compose-box-length {overLimit ? 'over-char-limit' : ''}"
|
||||
aria-label={lengthLabel}>
|
||||
{lengthToDisplayDeferred}
|
||||
</span>
|
||||
<style>
|
||||
.compose-box-length {
|
||||
|
@ -41,8 +41,8 @@
|
|||
}),
|
||||
store: () => store,
|
||||
computed: {
|
||||
lengthToDisplay: (length) => CHAR_LIMIT - length,
|
||||
lengthLabel: (overLimit, lengthToDisplayDeferred) => {
|
||||
lengthToDisplay: ({ length }) => CHAR_LIMIT - length,
|
||||
lengthLabel: ({ overLimit, lengthToDisplayDeferred }) => {
|
||||
if (overLimit) {
|
||||
return `${lengthToDisplayDeferred} characters over limit`
|
||||
} else {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
{{#if media.length}}
|
||||
<div class="compose-media-container" style="grid-template-columns: repeat({{media.length}}, 1fr);">
|
||||
{{#each media as mediaItem, index}}
|
||||
<ComposeMediaItem :realm :mediaItem :index :mediaDescriptions />
|
||||
{{/each}}
|
||||
{#if media.length}
|
||||
<div class="compose-media-container" style="grid-template-columns: repeat({media.length}, 1fr);">
|
||||
{#each media as mediaItem, index}
|
||||
<ComposeMediaItem {realm} {mediaItem} {index} {mediaDescriptions} />
|
||||
{/each}
|
||||
</div>
|
||||
{{/if}}
|
||||
{/if}
|
||||
<style>
|
||||
.compose-media-container {
|
||||
grid-area: media;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<div class="compose-media">
|
||||
<img src={{mediaItem.data.preview_url}} alt={{mediaItem.file.name}}/>
|
||||
<img src={mediaItem.data.preview_url} alt={mediaItem.file.name}/>
|
||||
<div class="compose-media-delete">
|
||||
<button class="compose-media-delete-button"
|
||||
aria-label="Delete {{mediaItem.file.name}}"
|
||||
aria-label="Delete {mediaItem.file.name}"
|
||||
on:click="onDeleteMedia()" >
|
||||
<svg class="compose-media-delete-button-svg">
|
||||
<use xlink:href="#fa-times" />
|
||||
|
@ -12,7 +12,7 @@
|
|||
<div class="compose-media-alt">
|
||||
<input type="text"
|
||||
placeholder="Description"
|
||||
aria-label="Describe {{mediaItem.file.name}} for the visually impaired"
|
||||
aria-label="Describe {mediaItem.file.name} for the visually impaired"
|
||||
bind:value=rawText
|
||||
>
|
||||
</div>
|
||||
|
|
|
@ -6,23 +6,23 @@
|
|||
on:click="onEmojiClick()"
|
||||
/>
|
||||
<IconButton
|
||||
svgClassName={{$uploadingMedia ? 'spin' : ''}}
|
||||
svgClassName={$uploadingMedia ? 'spin' : ''}
|
||||
label="Add media"
|
||||
href={{$uploadingMedia ? '#fa-spinner' : '#fa-camera'}}
|
||||
href={$uploadingMedia ? '#fa-spinner' : '#fa-camera'}
|
||||
on:click="onMediaClick()"
|
||||
disabled={{$uploadingMedia || (media.length === 4)}}
|
||||
disabled={$uploadingMedia || (media.length === 4)}
|
||||
/>
|
||||
<IconButton
|
||||
label="Adjust privacy (currently {{postPrivacy.label}})"
|
||||
href={{postPrivacy.icon}}
|
||||
label="Adjust privacy (currently {postPrivacy.label})"
|
||||
href={postPrivacy.icon}
|
||||
on:click="onPostPrivacyClick()"
|
||||
/>
|
||||
<IconButton
|
||||
label={{contentWarningShown ? 'Remove content warning' : 'Add content warning'}}
|
||||
label={contentWarningShown ? 'Remove content warning' : 'Add content warning'}
|
||||
href="#fa-exclamation-triangle"
|
||||
on:click="onContentWarningClick()"
|
||||
pressable="true"
|
||||
pressed={{contentWarningShown}}
|
||||
pressed={contentWarningShown}
|
||||
/>
|
||||
</div>
|
||||
<input ref:input
|
||||
|
@ -30,7 +30,7 @@
|
|||
style="display: none;"
|
||||
type="file"
|
||||
accept=".jpg,.jpeg,.png,.gif,.webm,.mp4,.m4v,image/jpeg,image/png,image/gif,video/webm,video/mp4">
|
||||
<ComposeAutosuggest :realm :text />
|
||||
<ComposeAutosuggest {realm} {text} />
|
||||
</div>
|
||||
<style>
|
||||
.compose-box-toolbar {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<ModalDialog
|
||||
:id
|
||||
:label
|
||||
:title
|
||||
{id}
|
||||
{label}
|
||||
{title}
|
||||
background="var(--main-bg)"
|
||||
>
|
||||
<GenericDialogList :items on:click="onClick(event)"/>
|
||||
<GenericDialogList {items} on:click="onClick(event)"/>
|
||||
</ModalDialog>
|
||||
<script>
|
||||
import ModalDialog from './ModalDialog.html'
|
||||
|
@ -27,14 +27,14 @@ export default {
|
|||
}),
|
||||
computed: {
|
||||
// begin account data copypasta
|
||||
verifyCredentialsId: (verifyCredentials) => verifyCredentials.id,
|
||||
following: (relationship) => relationship && relationship.following,
|
||||
followRequested: (relationship) => relationship && relationship.requested,
|
||||
accountId: (account) => account && account.id,
|
||||
acct: (account) => account.acct,
|
||||
muting: (relationship) => relationship.muting,
|
||||
blocking: (relationship) => relationship.blocking,
|
||||
followLabel: (following, followRequested, account, acct) => {
|
||||
verifyCredentialsId: ({ verifyCredentials }) => verifyCredentials.id,
|
||||
following: ({ relationship }) => relationship && relationship.following,
|
||||
followRequested: ({ relationship }) => relationship && relationship.requested,
|
||||
accountId: ({ account }) => account && account.id,
|
||||
acct: ({ account }) => account.acct,
|
||||
muting: ({ relationship }) => relationship.muting,
|
||||
blocking: ({ relationship }) => relationship.blocking,
|
||||
followLabel: ({ following, followRequested, account, acct }) => {
|
||||
if (typeof following === 'undefined' || !account) {
|
||||
return ''
|
||||
}
|
||||
|
@ -42,21 +42,21 @@ export default {
|
|||
? `Unfollow @${acct}`
|
||||
: `Follow @${acct}`
|
||||
},
|
||||
followIcon: (following, followRequested) => {
|
||||
followIcon: ({ following, followRequested }) => {
|
||||
return following ? '#fa-user-times' : followRequested ? '#fa-hourglass' : '#fa-user-plus'
|
||||
},
|
||||
blockLabel: (blocking, acct) => {
|
||||
blockLabel: ({ blocking, acct }) => {
|
||||
return blocking ? `Unblock @${acct}` : `Block @${acct}`
|
||||
},
|
||||
blockIcon: (blocking) => blocking ? '#fa-unlock' : '#fa-ban',
|
||||
muteLabel: (muting, acct) => {
|
||||
blockIcon: ({ blocking }) => blocking ? '#fa-unlock' : '#fa-ban',
|
||||
muteLabel: ({ muting, acct }) => {
|
||||
return muting ? `Unmute @${acct}` : `Mute @${acct}`
|
||||
},
|
||||
muteIcon: (muting) => muting ? '#fa-volume-up' : '#fa-volume-off',
|
||||
muteIcon: ({ muting }) => muting ? '#fa-volume-up' : '#fa-volume-off',
|
||||
// end account data copypasta
|
||||
items: (blockLabel, blocking, blockIcon, muteLabel, muteIcon,
|
||||
items: ({ blockLabel, blocking, blockIcon, muteLabel, muteIcon,
|
||||
followLabel, followIcon, following, followRequested,
|
||||
accountId, verifyCredentialsId, acct) => {
|
||||
accountId, verifyCredentialsId, acct }) => {
|
||||
let isUser = accountId === verifyCredentialsId
|
||||
return [
|
||||
!isUser && {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<ModalDialog
|
||||
:id
|
||||
:label
|
||||
:title
|
||||
{id}
|
||||
{label}
|
||||
{title}
|
||||
background="var(--main-bg)"
|
||||
>
|
||||
<ComposeBox realm="dialog" size="slim" autoFocus="true" />
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
<ModalDialog
|
||||
:id
|
||||
:label
|
||||
{id}
|
||||
{label}
|
||||
background="var(--main-bg)"
|
||||
>
|
||||
<form class="confirmation-dialog-form">
|
||||
<p>
|
||||
{{text}}
|
||||
{text}
|
||||
</p>
|
||||
<div class="confirmation-dialog-form-flex">
|
||||
<button type="button" on:click="onPositive()">
|
||||
{{positiveText || 'OK'}}
|
||||
{positiveText || 'OK'}
|
||||
</button>
|
||||
<button type="button" on:click="onNegative()">
|
||||
{{negativeText || 'Cancel'}}
|
||||
{negativeText || 'Cancel'}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
<ModalDialog
|
||||
:id
|
||||
:label
|
||||
:title
|
||||
{id}
|
||||
{label}
|
||||
{title}
|
||||
background="var(--main-bg)"
|
||||
>
|
||||
<div class="custom-emoji-container">
|
||||
{{#if emojis.length}}
|
||||
{#if emojis.length}
|
||||
<ul class="custom-emoji-list">
|
||||
{{#each emojis as emoji}}
|
||||
{#each emojis as emoji}
|
||||
<li class="custom-emoji">
|
||||
<button type="button" on:click="onClickEmoji(emoji)">
|
||||
<img src={{$autoplayGifs ? emoji.url : emoji.static_url}}
|
||||
alt=":{{emoji.shortcode}}:"
|
||||
title=":{{emoji.shortcode}}:"
|
||||
<img src={$autoplayGifs ? emoji.url : emoji.static_url}
|
||||
alt=":{emoji.shortcode}:"
|
||||
title=":{emoji.shortcode}:"
|
||||
/>
|
||||
</button>
|
||||
</li>
|
||||
{{/each}}
|
||||
{/each}
|
||||
</ul>
|
||||
{{else}}
|
||||
{:else}
|
||||
<div class="custom-emoji-no-emoji">No custom emoji found for this instance.</div>
|
||||
{{/if}}
|
||||
{/if}
|
||||
</div>
|
||||
</ModalDialog>
|
||||
<style>
|
||||
|
@ -71,7 +71,7 @@
|
|||
},
|
||||
store: () => store,
|
||||
computed: {
|
||||
emojis: ($currentCustomEmoji) => {
|
||||
emojis: ({ $currentCustomEmoji }) => {
|
||||
if (!$currentCustomEmoji) {
|
||||
return []
|
||||
}
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
<ul class="generic-dialog-list">
|
||||
{{#each items as item @key}}
|
||||
{#each items as item (item.key)}
|
||||
<li class="generic-dialog-list-item">
|
||||
<button class="generic-dialog-list-button" on:click="fire('click', item)">
|
||||
<svg class="generic-dialog-list-item-svg">
|
||||
<use xlink:href={{item.icon}} />
|
||||
<use xlink:href={item.icon} />
|
||||
</svg>
|
||||
<span>
|
||||
{{item.label}}
|
||||
{item.label}
|
||||
</span>
|
||||
<svg class="generic-dialog-list-item-svg {{item.selected ? '' : 'hidden'}}" aria-hidden={{!item.selected}}>
|
||||
<svg class="generic-dialog-list-item-svg {item.selected ? '' : 'hidden'}" aria-hidden={!item.selected}>
|
||||
<use xlink:href="#fa-check" />
|
||||
</svg>
|
||||
</button>
|
||||
</li>
|
||||
{{/each}}
|
||||
{/each}
|
||||
</ul>
|
||||
<style>
|
||||
.generic-dialog-list {
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
<ModalDialog
|
||||
:id
|
||||
:label
|
||||
{id}
|
||||
{label}
|
||||
background="var(--muted-modal-bg)"
|
||||
muted="true"
|
||||
className="image-modal-dialog"
|
||||
>
|
||||
{{#if type === 'gifv'}}
|
||||
{#if type === 'gifv'}
|
||||
<AutoplayVideo
|
||||
ariaLabel="Animated GIF: {{description || ''}}"
|
||||
:poster
|
||||
:src
|
||||
:width
|
||||
:height
|
||||
ariaLabel="Animated GIF: {description || ''}"
|
||||
{poster}
|
||||
{src}
|
||||
{width}
|
||||
{height}
|
||||
/>
|
||||
{{else}}
|
||||
{:else}
|
||||
<img
|
||||
:src
|
||||
:width
|
||||
:height
|
||||
alt={{description || ''}}
|
||||
title={{description || ''}}
|
||||
{src}
|
||||
{width}
|
||||
{height}
|
||||
alt={description || ''}
|
||||
title={description || ''}
|
||||
/>
|
||||
{{/if}}
|
||||
{/if}
|
||||
</ModalDialog>
|
||||
<style>
|
||||
:global(.image-modal-dialog img, .image-modal-dialog video) {
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
<div class={{backdropClass}}
|
||||
<div class={backdropClass}
|
||||
tabindex="-1"
|
||||
data-a11y-dialog-hide
|
||||
></div>
|
||||
<div class={{contentsClass}}
|
||||
<div class={contentsClass}
|
||||
role="dialog"
|
||||
aria-label={{label || ''}}
|
||||
aria-label={label || ''}
|
||||
ref:node
|
||||
>
|
||||
<div class="modal-dialog-document" role="document" style="background: {{background || '#000'}};">
|
||||
<div class="modal-dialog-document" role="document" style="background: {background || '#000'};">
|
||||
<div class="modal-dialog-header">
|
||||
{{#if title}}
|
||||
<h1 class="modal-dialog-title">{{title}}</h1>
|
||||
{{/if}}
|
||||
{#if title}
|
||||
<h1 class="modal-dialog-title">{title}</h1>
|
||||
{/if}
|
||||
<div class="close-dialog-button-wrapper">
|
||||
<button class="close-dialog-button"
|
||||
data-a11y-dialog-hide aria-label="Close dialog">
|
||||
|
@ -148,14 +148,14 @@
|
|||
title: void 0
|
||||
}),
|
||||
computed: {
|
||||
backdropClass: (fadedIn, shouldAnimate) => {
|
||||
backdropClass: ({ fadedIn, shouldAnimate }) => {
|
||||
return classname(
|
||||
'modal-dialog-backdrop',
|
||||
!fadedIn && 'hidden',
|
||||
shouldAnimate && 'should-animate'
|
||||
)
|
||||
},
|
||||
contentsClass: (fadedIn, muted, shouldAnimate, className) => {
|
||||
contentsClass: ({ fadedIn, muted, shouldAnimate, className }) => {
|
||||
return classname(
|
||||
'modal-dialog-contents',
|
||||
!fadedIn && 'hidden',
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<ModalDialog
|
||||
:id
|
||||
:label
|
||||
:title
|
||||
{id}
|
||||
{label}
|
||||
{title}
|
||||
background="var(--main-bg)"
|
||||
>
|
||||
<GenericDialogList :items on:click="onClick(event)" />
|
||||
<GenericDialogList {items} on:click="onClick(event)" />
|
||||
</ModalDialog>
|
||||
<script>
|
||||
import ModalDialog from './ModalDialog.html'
|
||||
|
@ -36,14 +36,14 @@
|
|||
}
|
||||
},
|
||||
computed: {
|
||||
composeData: ($currentComposeData, realm) => $currentComposeData[realm] || {},
|
||||
postPrivacy: (postPrivacyKey) => {
|
||||
composeData: ({ $currentComposeData, realm }) => $currentComposeData[realm] || {},
|
||||
postPrivacy: ({ postPrivacyKey }) => {
|
||||
return POST_PRIVACY_OPTIONS.find(_ => _.key === postPrivacyKey)
|
||||
},
|
||||
postPrivacyKey: (composeData, $currentVerifyCredentials) => {
|
||||
postPrivacyKey: ({ composeData, $currentVerifyCredentials }) => {
|
||||
return composeData.postPrivacy || $currentVerifyCredentials.source.privacy
|
||||
},
|
||||
items: (postPrivacy, postPrivacyOptions) => {
|
||||
items: ({ postPrivacy, postPrivacyOptions }) => {
|
||||
return postPrivacyOptions.map(option => ({
|
||||
key: option.key,
|
||||
label: option.label,
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<ModalDialog
|
||||
:id
|
||||
:label
|
||||
:title
|
||||
{id}
|
||||
{label}
|
||||
{title}
|
||||
background="var(--main-bg)"
|
||||
>
|
||||
<GenericDialogList :items on:click="onClick(event)"/>
|
||||
<GenericDialogList {items} on:click="onClick(event)"/>
|
||||
</ModalDialog>
|
||||
<script>
|
||||
import ModalDialog from './ModalDialog.html'
|
||||
|
@ -22,20 +22,20 @@ import { setStatusPinnedOrUnpinned } from '../../../_actions/pin'
|
|||
export default {
|
||||
oncreate,
|
||||
computed: {
|
||||
relationship: ($currentAccountRelationship) => $currentAccountRelationship,
|
||||
account: ($currentAccountProfile) => $currentAccountProfile,
|
||||
verifyCredentials: ($currentVerifyCredentials) => $currentVerifyCredentials,
|
||||
statusId: (status) => status.id,
|
||||
pinned: (status) => status.pinned,
|
||||
relationship: ({ $currentAccountRelationship }) => $currentAccountRelationship,
|
||||
account: ({ $currentAccountProfile }) => $currentAccountProfile,
|
||||
verifyCredentials: ({ $currentVerifyCredentials }) => $currentVerifyCredentials,
|
||||
statusId: ({ status }) => status.id,
|
||||
pinned: ({ status }) => status.pinned,
|
||||
// begin account data copypasta
|
||||
verifyCredentialsId: (verifyCredentials) => verifyCredentials.id,
|
||||
following: (relationship) => relationship && relationship.following,
|
||||
followRequested: (relationship) => relationship && relationship.requested,
|
||||
accountId: (account) => account && account.id,
|
||||
acct: (account) => account.acct,
|
||||
muting: (relationship) => relationship.muting,
|
||||
blocking: (relationship) => relationship.blocking,
|
||||
followLabel: (following, followRequested, account, acct) => {
|
||||
verifyCredentialsId: ({ verifyCredentials }) => verifyCredentials.id,
|
||||
following: ({ relationship }) => relationship && relationship.following,
|
||||
followRequested: ({ relationship }) => relationship && relationship.requested,
|
||||
accountId: ({ account }) => account && account.id,
|
||||
acct: ({ account }) => account.acct,
|
||||
muting: ({ relationship }) => relationship.muting,
|
||||
blocking: ({ relationship }) => relationship.blocking,
|
||||
followLabel: ({ following, followRequested, account, acct }) => {
|
||||
if (typeof following === 'undefined' || !account) {
|
||||
return ''
|
||||
}
|
||||
|
@ -43,22 +43,22 @@ export default {
|
|||
? `Unfollow @${acct}`
|
||||
: `Follow @${acct}`
|
||||
},
|
||||
followIcon: (following, followRequested) => {
|
||||
followIcon: ({ following, followRequested }) => {
|
||||
return following ? '#fa-user-times' : followRequested ? '#fa-hourglass' : '#fa-user-plus'
|
||||
},
|
||||
blockLabel: (blocking, acct) => {
|
||||
blockLabel: ({ blocking, acct }) => {
|
||||
return blocking ? `Unblock @${acct}` : `Block @${acct}`
|
||||
},
|
||||
blockIcon: (blocking) => blocking ? '#fa-unlock' : '#fa-ban',
|
||||
muteLabel: (muting, acct) => {
|
||||
blockIcon: ({ blocking }) => blocking ? '#fa-unlock' : '#fa-ban',
|
||||
muteLabel: ({ muting, acct }) => {
|
||||
return muting ? `Unmute @${acct}` : `Mute @${acct}`
|
||||
},
|
||||
muteIcon: (muting) => muting ? '#fa-volume-up' : '#fa-volume-off',
|
||||
muteIcon: ({ muting }) => muting ? '#fa-volume-up' : '#fa-volume-off',
|
||||
// end account data copypasta
|
||||
isUser: (accountId, verifyCredentialsId) => accountId === verifyCredentialsId,
|
||||
pinLabel: (pinned, isUser) => isUser ? (pinned ? 'Unpin from profile' : 'Pin to profile') : '',
|
||||
items: (blockLabel, blocking, blockIcon, muteLabel, muteIcon, followLabel, followIcon,
|
||||
following, followRequested, pinLabel, isUser) => {
|
||||
isUser: ({ accountId, verifyCredentialsId }) => accountId === verifyCredentialsId,
|
||||
pinLabel: ({ pinned, isUser }) => isUser ? (pinned ? 'Unpin from profile' : 'Pin to profile') : '',
|
||||
items: ({ blockLabel, blocking, blockIcon, muteLabel, muteIcon, followLabel, followIcon,
|
||||
following, followRequested, pinLabel, isUser }) => {
|
||||
return [
|
||||
isUser && {
|
||||
key: 'delete',
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
<ModalDialog
|
||||
:id
|
||||
:label
|
||||
{id}
|
||||
{label}
|
||||
background="var(--muted-modal-bg)"
|
||||
muted="true"
|
||||
className="video-modal-dialog"
|
||||
>
|
||||
<video :poster
|
||||
:src
|
||||
:width
|
||||
:height
|
||||
aria-label="Video: {{description || ''}}"
|
||||
<video {poster}
|
||||
{src}
|
||||
{width}
|
||||
{height}
|
||||
aria-label="Video: {description || ''}"
|
||||
controls
|
||||
/>
|
||||
</ModalDialog>
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<div class="account-profile {{headerImageIsMissing ? 'header-image-is-missing' : ''}}"
|
||||
style="background-image: url({{headerImage}});">
|
||||
<div class="account-profile {headerImageIsMissing ? 'header-image-is-missing' : ''}"
|
||||
style="background-image: url({headerImage});">
|
||||
<div class="account-profile-grid-wrapper">
|
||||
<div class="account-profile-grid">
|
||||
<AccountProfileHeader :account :relationship :verifyCredentials />
|
||||
<AccountProfileFollow :account :relationship :verifyCredentials />
|
||||
<AccountProfileNote :account />
|
||||
<AccountProfileDetails :account :relationship :verifyCredentials />
|
||||
<AccountProfileHeader {account} {relationship} {verifyCredentials} />
|
||||
<AccountProfileFollow {account} {relationship} {verifyCredentials} />
|
||||
<AccountProfileNote {account} />
|
||||
<AccountProfileDetails {account} {relationship} {verifyCredentials} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -73,8 +73,8 @@
|
|||
export default {
|
||||
store: () => store,
|
||||
computed: {
|
||||
headerImageIsMissing: (account) => account.header.endsWith('missing.png'),
|
||||
headerImage: ($autoplayGifs, account) => $autoplayGifs ? account.header : account.header_static
|
||||
headerImageIsMissing: ({ account }) => account.header.endsWith('missing.png'),
|
||||
headerImage: ({ $autoplayGifs, account }) => $autoplayGifs ? account.header : account.header_static
|
||||
},
|
||||
components: {
|
||||
AccountProfileHeader,
|
||||
|
|
|
@ -4,33 +4,33 @@
|
|||
Toots
|
||||
</span>
|
||||
<span class="account-profile-details-item-datum">
|
||||
{{numStatusesDisplay}}
|
||||
{numStatusesDisplay}
|
||||
</span>
|
||||
</div>
|
||||
<a class="account-profile-details-item"
|
||||
href='/accounts/{{account.id}}/follows'
|
||||
aria-label={{followingLabel}}
|
||||
href='/accounts/{account.id}/follows'
|
||||
aria-label={followingLabel}
|
||||
>
|
||||
<span class="account-profile-details-item-title">
|
||||
Follows
|
||||
</span>
|
||||
<span class="account-profile-details-item-datum">
|
||||
{{numFollowingDisplay}}
|
||||
{numFollowingDisplay}
|
||||
</span>
|
||||
</a>
|
||||
<a class="account-profile-details-item"
|
||||
href='/accounts/{{account.id}}/followers'
|
||||
aria-label={{followersLabel}}
|
||||
href='/accounts/{account.id}/followers'
|
||||
aria-label={followersLabel}
|
||||
>
|
||||
<span class="account-profile-details-item-title">
|
||||
Followers
|
||||
</span>
|
||||
<span class="account-profile-details-item-datum">
|
||||
{{numFollowersDisplay}}
|
||||
{numFollowersDisplay}
|
||||
</span>
|
||||
</a>
|
||||
<!-- TODO: re-enable this when we support profile editing -->
|
||||
{{#if account && verifyCredentials && account.id !== verifyCredentials.id}}
|
||||
{#if account && verifyCredentials && account.id !== verifyCredentials.id}
|
||||
<div class="account-profile-more-options">
|
||||
<IconButton
|
||||
label="More options"
|
||||
|
@ -39,7 +39,7 @@
|
|||
on:click="onMoreOptionsClick()"
|
||||
/>
|
||||
</div>
|
||||
{{/if}}
|
||||
{/if}
|
||||
</div>
|
||||
<style>
|
||||
.account-profile-details {
|
||||
|
@ -119,14 +119,14 @@
|
|||
|
||||
export default {
|
||||
computed: {
|
||||
numStatuses: account => account.statuses_count || 0,
|
||||
numFollowing: account => account.following_count || 0,
|
||||
numFollowers: account => account.followers_count || 0,
|
||||
numStatusesDisplay: numStatuses => numberFormat.format(numStatuses),
|
||||
numFollowingDisplay: numFollowing => numberFormat.format(numFollowing),
|
||||
numFollowersDisplay: numFollowers => numberFormat.format(numFollowers),
|
||||
followersLabel: numFollowers => `Followed by ${numFollowers}`,
|
||||
followingLabel: numFollowing => `Follows ${numFollowing}`
|
||||
numStatuses: ({ account }) => account.statuses_count || 0,
|
||||
numFollowing: ({ account }) => account.following_count || 0,
|
||||
numFollowers: ({ account }) => account.followers_count || 0,
|
||||
numStatusesDisplay: ({ numStatuses }) => numberFormat.format(numStatuses),
|
||||
numFollowingDisplay: ({ numFollowing }) => numberFormat.format(numFollowing),
|
||||
numFollowersDisplay: ({ numFollowers }) => numberFormat.format(numFollowers),
|
||||
followersLabel: ({ numFollowers }) => `Followed by ${numFollowers}`,
|
||||
followingLabel: ({ numFollowing }) => `Follows ${numFollowing}`
|
||||
},
|
||||
methods: {
|
||||
async onMoreOptionsClick () {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<div class="account-profile-follow {{shown ? 'shown' : ''}}">
|
||||
<div class="account-profile-follow {shown ? 'shown' : ''}">
|
||||
<IconButton
|
||||
label={{followLabel}}
|
||||
href={{followIcon}}
|
||||
label={followLabel}
|
||||
href={followIcon}
|
||||
pressable="true"
|
||||
pressed={{following}}
|
||||
pressed={following}
|
||||
big="true"
|
||||
on:click="onFollowButtonClick(event)"
|
||||
ref:icon
|
||||
|
@ -57,18 +57,18 @@
|
|||
overrideFollowing: void 0
|
||||
}),
|
||||
computed: {
|
||||
accountId: (account) => account.id,
|
||||
following: (relationship, overrideFollowing) => {
|
||||
accountId: ({ account }) => account.id,
|
||||
following: ({ relationship, overrideFollowing }) => {
|
||||
if (typeof overrideFollowing === 'boolean') {
|
||||
return overrideFollowing
|
||||
}
|
||||
return relationship && relationship.following
|
||||
},
|
||||
blocking: (relationship) => relationship && relationship.blocking,
|
||||
followRequested: (relationship, account) => {
|
||||
blocking: ({ relationship }) => relationship && relationship.blocking,
|
||||
followRequested: ({ relationship, account }) => {
|
||||
return relationship && relationship.requested && account && account.locked
|
||||
},
|
||||
followLabel: (blocking, following, followRequested) => {
|
||||
followLabel: ({ blocking, following, followRequested }) => {
|
||||
if (blocking) {
|
||||
return 'Unblock'
|
||||
} else if (following) {
|
||||
|
@ -79,7 +79,7 @@
|
|||
return 'Follow'
|
||||
}
|
||||
},
|
||||
followIcon: (blocking, following, followRequested) => {
|
||||
followIcon: ({ blocking, following, followRequested }) => {
|
||||
if (blocking) {
|
||||
return '#fa-unlock'
|
||||
} else if (following) {
|
||||
|
@ -90,7 +90,7 @@
|
|||
return '#fa-user-plus'
|
||||
}
|
||||
},
|
||||
shown: (verifyCredentials, relationship) => {
|
||||
shown: ({ verifyCredentials, relationship }) => {
|
||||
return verifyCredentials && relationship && verifyCredentials.id !== relationship.id
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
<div class="account-profile-avatar">
|
||||
<Avatar :account size="big" />
|
||||
<Avatar {account} size="big" />
|
||||
</div>
|
||||
<div class="account-profile-name">
|
||||
<ExternalLink href={{account.url}}
|
||||
<ExternalLink href={account.url}
|
||||
showIcon="true"
|
||||
normalIconColor="true"
|
||||
ariaLabel="{{account.display_name || account.acct}} (opens in new window)"
|
||||
ariaLabel="{account.display_name || account.acct} (opens in new window)"
|
||||
>
|
||||
{{account.display_name || account.acct}}
|
||||
{account.display_name || account.acct}
|
||||
</ExternalLink>
|
||||
</div>
|
||||
<div class="account-profile-username">
|
||||
{{'@' + account.acct}}
|
||||
{'@' + account.acct}
|
||||
</div>
|
||||
<div class="account-profile-followed-by">
|
||||
{{#if relationship && relationship.blocking}}
|
||||
{#if relationship && relationship.blocking}
|
||||
<span class="account-profile-followed-by-span">Blocked</span>
|
||||
{{elseif relationship && relationship.followed_by}}
|
||||
{:elseif relationship && relationship.followed_by}
|
||||
<span class="account-profile-followed-by-span">Follows you</span>
|
||||
{{/if}}
|
||||
{/if}
|
||||
</div>
|
||||
<style>
|
||||
.account-profile-followed-by {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<div class="account-profile-note">
|
||||
{{{massagedNote}}}
|
||||
{@html massagedNote}
|
||||
</div>
|
||||
<style>
|
||||
.account-profile-note {
|
||||
|
@ -32,8 +32,8 @@
|
|||
<script>
|
||||
export default {
|
||||
computed: {
|
||||
note: (account) => account.note,
|
||||
massagedNote: (note) => {
|
||||
note: ({ account }) => account.note,
|
||||
massagedNote: ({ note }) => {
|
||||
// GNU Social / Pleroma don't add <p> tags
|
||||
if (!note.startsWith('<p>')) {
|
||||
note = `<p>${note}</p>`
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
<div class="pseudo-virtual-list" on:initialized ref:node>
|
||||
{{#each wrappedItems as wrappedItem, i @item}}
|
||||
{#each wrappedItems as wrappedItem, i (wrappedItem.item)}
|
||||
<PseudoVirtualListLazyItem
|
||||
:component
|
||||
index={{i}}
|
||||
length={{wrappedItems.length}}
|
||||
:makeProps
|
||||
key={{wrappedItem.item}}
|
||||
:intersectionObserver
|
||||
isIntersecting={{isIntersecting(wrappedItem.item, $intersectionStates)}}
|
||||
isCached={{isCached(wrappedItem.item, $intersectionStates)}}
|
||||
height={{getHeight(wrappedItem.item, $intersectionStates)}}
|
||||
{component}
|
||||
index={i}
|
||||
length={wrappedItems.length}
|
||||
{makeProps}
|
||||
key={wrappedItem.item}
|
||||
{intersectionObserver}
|
||||
isIntersecting={isIntersecting(wrappedItem.item, $intersectionStates)}
|
||||
isCached={isCached(wrappedItem.item, $intersectionStates)}
|
||||
height={getHeight(wrappedItem.item, $intersectionStates)}
|
||||
/>
|
||||
{{/each}}
|
||||
{/each}
|
||||
</div>
|
||||
<style>
|
||||
.pseudo-virtual-list {
|
||||
|
@ -110,8 +110,8 @@
|
|||
}
|
||||
},
|
||||
computed: {
|
||||
wrappedItems: (items) => items ? items.map(item => ({item})) : [],
|
||||
allItemsHaveHeight: (items, $intersectionStates) => {
|
||||
wrappedItems: ({ items }) => items ? items.map(item => ({item})) : [],
|
||||
allItemsHaveHeight: ({ items, $intersectionStates }) => {
|
||||
if (!items) {
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
<div class="pseudo-virtual-list-item"
|
||||
aria-hidden={{hide}}
|
||||
pseudo-virtual-list-key={{key}}
|
||||
style="height: {{shouldHide ? `${height}px` : ''}};"
|
||||
aria-hidden={hide}
|
||||
pseudo-virtual-list-key={key}
|
||||
style="height: {shouldHide ? `${height}px` : ''};"
|
||||
ref:node>
|
||||
{{#if !shouldHide}}
|
||||
<:Component {component}
|
||||
virtualProps={{props}}
|
||||
virtualIndex={{index}}
|
||||
virtualLength={{length}}
|
||||
{#if !shouldHide}
|
||||
<svelte:component this={component}
|
||||
virtualProps={props}
|
||||
virtualIndex={index}
|
||||
virtualLength={length}
|
||||
/>
|
||||
{{/if}}
|
||||
{/if}
|
||||
</div>
|
||||
<script>
|
||||
import { scheduleIdleTask } from '../../_utils/scheduleIdleTask'
|
||||
|
@ -43,7 +43,7 @@
|
|||
hide: false
|
||||
}),
|
||||
computed: {
|
||||
shouldHide: (isIntersecting, isCached, hide) => {
|
||||
shouldHide: ({ isIntersecting, isCached, hide }) => {
|
||||
if (isCached) {
|
||||
return true // if it's cached, always unrender immediately until proven it's intersecting
|
||||
}
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
{{#if props}}
|
||||
<PseudoVirtualListItem :component
|
||||
:props
|
||||
:key
|
||||
:index
|
||||
:length
|
||||
:intersectionObserver
|
||||
:isIntersecting
|
||||
:isCached
|
||||
:height
|
||||
{#if props}
|
||||
<PseudoVirtualListItem {component}
|
||||
{props}
|
||||
{key}
|
||||
{index}
|
||||
{length}
|
||||
{intersectionObserver}
|
||||
{isIntersecting}
|
||||
{isCached}
|
||||
{height}
|
||||
on:scrollToPosition
|
||||
/>
|
||||
{{/if}}
|
||||
{/if}
|
||||
<script>
|
||||
import PseudoVirtualListItem from './PseudoVirtualListItem.html'
|
||||
import { mark, stop } from '../../_utils/marks'
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
<SearchResult href="/accounts/{{account.id}}">
|
||||
<SearchResult href="/accounts/{account.id}">
|
||||
<div class="search-result-account">
|
||||
<Avatar :account size="small" className="search-result-account-avatar"/>
|
||||
<Avatar {account} size="small" className="search-result-account-avatar"/>
|
||||
<div class="search-result-account-name">
|
||||
{{account.display_name || account.acct}}
|
||||
{account.display_name || account.acct}
|
||||
</div>
|
||||
<div class="search-result-account-username">
|
||||
{{'@' + account.acct}}
|
||||
{'@' + account.acct}
|
||||
</div>
|
||||
{{#if actions && actions.length}}
|
||||
{#if actions && actions.length}
|
||||
<div class="search-result-account-buttons">
|
||||
{{#each actions as action}}
|
||||
{#each actions as action}
|
||||
<IconButton
|
||||
label={{action.label}}
|
||||
label={action.label}
|
||||
on:click="onButtonClick(event, action, account.id)"
|
||||
href={{action.icon}}
|
||||
href={action.icon}
|
||||
big="true"
|
||||
/>
|
||||
{{/each}}
|
||||
{/each}
|
||||
</div>
|
||||
{{/if}}
|
||||
{/if}
|
||||
</div>
|
||||
</SearchResult>
|
||||
<style>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<SearchResult href="/tags/{{hashtag}}">
|
||||
{{'#' + hashtag}}
|
||||
<SearchResult href="/tags/{hashtag}">
|
||||
{'#' + hashtag}
|
||||
</SearchResult>
|
||||
<style>
|
||||
</style>
|
||||
|
|
|
@ -7,21 +7,21 @@
|
|||
required
|
||||
bind:value="$queryInSearch">
|
||||
</div>
|
||||
<button type="submit" class="primary search-button" aria-label="Search" disabled={{$searchLoading}}>
|
||||
<button type="submit" class="primary search-button" aria-label="Search" disabled={$searchLoading}>
|
||||
<svg class="search-button-svg">
|
||||
<use xlink:href="#fa-search" />
|
||||
</svg>
|
||||
</button>
|
||||
</form>
|
||||
{{#if $searchLoading}}
|
||||
{#if $searchLoading}
|
||||
<div class="search-results-container">
|
||||
<LoadingPage />
|
||||
</div>
|
||||
{{elseif $searchResults && $searchResultsForQuery === $queryInSearch}}
|
||||
{:elseif $searchResults && $searchResultsForQuery === $queryInSearch}
|
||||
<div class="search-results-container">
|
||||
<SearchResults />
|
||||
</div>
|
||||
{{/if}}
|
||||
{/if}
|
||||
<style>
|
||||
.search-input-form {
|
||||
display: grid;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<li class="search-result">
|
||||
<a :href class="search-result-anchor">
|
||||
<a {href} class="search-result-anchor">
|
||||
<slot></slot>
|
||||
</a>
|
||||
</li>
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<ul class="search-results">
|
||||
{{#each $searchResults.hashtags as hashtag}}
|
||||
<HashtagSearchResult :hashtag />
|
||||
{{/each}}
|
||||
{{#each $searchResults.accounts as account}}
|
||||
<AccountSearchResult :account />
|
||||
{{/each}}
|
||||
{{#each $searchResults.statuses as status, index}}
|
||||
<StatusSearchResult :status :index length={{$searchResults.statuses.length}}/>
|
||||
{{/each}}
|
||||
{#each $searchResults.hashtags as hashtag}
|
||||
<HashtagSearchResult {hashtag} />
|
||||
{/each}
|
||||
{#each $searchResults.accounts as account}
|
||||
<AccountSearchResult {account} />
|
||||
{/each}
|
||||
{#each $searchResults.statuses as status, index}
|
||||
<StatusSearchResult {status} {index} length={$searchResults.statuses.length}/>
|
||||
{/each}
|
||||
</ul>
|
||||
<style>
|
||||
.search-results {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<SearchResult href="/statuses/{{status.id}}">
|
||||
<Status :index :length
|
||||
<SearchResult href="/statuses/{status.id}">
|
||||
<Status {index} {length}
|
||||
timelineType="search" timelineValue="search"
|
||||
:status />
|
||||
{status} />
|
||||
</SearchResult>
|
||||
<style>
|
||||
</style>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<SettingsNav :page :label/>
|
||||
<SettingsNav {page} {label}/>
|
||||
|
||||
<div class="settings">
|
||||
<FreeTextLayout>
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<div class="settings-list-wrapper">
|
||||
{{#if label}}
|
||||
<ul class="settings-list" aria-label={{label}}>
|
||||
{#if label}
|
||||
<ul class="settings-list" aria-label={label}>
|
||||
<slot></slot>
|
||||
</ul>
|
||||
{{else}}
|
||||
{:else}
|
||||
<ul class="settings-list">
|
||||
<slot></slot>
|
||||
</ul>
|
||||
{{/if}}
|
||||
{/if}
|
||||
</div>
|
||||
<style>
|
||||
.settings-list-wrapper {
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<li class="settings-list-item">
|
||||
<a :href>
|
||||
{{#if icon}}
|
||||
<a {href}>
|
||||
{#if icon}
|
||||
<svg class="settings-list-item-svg">
|
||||
<use xlink:href={{icon}} />
|
||||
<use xlink:href={icon} />
|
||||
</svg>
|
||||
{{/if}}
|
||||
<span aria-label={{ariaLabel || label}} class={{offsetForIcon ? 'offset-for-icon' : ''}}>
|
||||
{{label}}
|
||||
{/if}
|
||||
<span aria-label={ariaLabel || label} class={offsetForIcon ? 'offset-for-icon' : ''}>
|
||||
{label}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<nav class="settings-nav">
|
||||
<ul>
|
||||
{{#each navItems as navItem}}
|
||||
{#each navItems as navItem}
|
||||
<li>
|
||||
<SettingsNavItem :page name={{navItem.name}} href={{navItem.href}} label={{navItem.label}} />
|
||||
<SettingsNavItem {page} name={navItem.name} href={navItem.href} label={navItem.label} />
|
||||
</li>
|
||||
{{/each}}
|
||||
{/each}
|
||||
<li>
|
||||
<SettingsNavItem :page name={{page}} href="/{{page}}" :label />
|
||||
<SettingsNavItem {page} name={page} href="/{page}" {label} />
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
@ -53,7 +53,7 @@
|
|||
SettingsNavItem
|
||||
},
|
||||
computed: {
|
||||
navItems: page => {
|
||||
navItems: ({ page }) => {
|
||||
let res = []
|
||||
let breadcrumbs = page.split('/')
|
||||
let path = ''
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<a class="settings-nav-item {{className}}"
|
||||
aria-label={{ariaLabel}}
|
||||
:href >
|
||||
{{label}}
|
||||
<a class="settings-nav-item {className}"
|
||||
aria-label={ariaLabel}
|
||||
{href} >
|
||||
{label}
|
||||
</a>
|
||||
<style>
|
||||
a.settings-nav-item {
|
||||
|
@ -15,8 +15,8 @@
|
|||
<script>
|
||||
export default {
|
||||
computed: {
|
||||
className: (page, name) => page === name ? 'selected' : '',
|
||||
ariaLabel: (page, name, label) => page === name ? `${label} (current page)` : label
|
||||
className: ({ page, name }) => page === name ? 'selected' : '',
|
||||
ariaLabel: ({ page, name, label }) => page === name ? `${label} (current page)` : label
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -1,64 +1,64 @@
|
|||
{{#if type === 'video'}}
|
||||
{#if type === 'video'}
|
||||
<button type="button"
|
||||
class="play-video-button"
|
||||
aria-label="Play video: {{description}}"
|
||||
delegate-key={{delegateKey}}
|
||||
style="width: {{inlineWidth}}px; height: {{inlineHeight}}px;">
|
||||
aria-label="Play video: {description}"
|
||||
delegate-key={delegateKey}
|
||||
style="width: {inlineWidth}px; height: {inlineHeight}px;">
|
||||
<PlayVideoIcon />
|
||||
<LazyImage
|
||||
alt={{description}}
|
||||
title={{description}}
|
||||
src={{previewUrl}}
|
||||
fallback={{oneTransparentPixel}}
|
||||
width={{inlineWidth}}
|
||||
height={{inlineHeight}}
|
||||
alt={description}
|
||||
title={description}
|
||||
src={previewUrl}
|
||||
fallback={oneTransparentPixel}
|
||||
width={inlineWidth}
|
||||
height={inlineHeight}
|
||||
background="var(--loading-bg)"
|
||||
className={{noNativeWidthHeight ? 'no-native-width-height' : ''}}
|
||||
className={noNativeWidthHeight ? 'no-native-width-height' : ''}
|
||||
/>
|
||||
</button>
|
||||
{{else}}
|
||||
{:else}
|
||||
<button type="button"
|
||||
class="show-image-button"
|
||||
aria-label="Show image: {{description}}"
|
||||
title={{description}}
|
||||
delegate-key={{delegateKey}}
|
||||
aria-label="Show image: {description}"
|
||||
title={description}
|
||||
delegate-key={delegateKey}
|
||||
on:mouseover="set({mouseover: event})"
|
||||
style="width: {{inlineWidth}}px; height: {{inlineHeight}}px;"
|
||||
style="width: {inlineWidth}px; height: {inlineHeight}px;"
|
||||
>
|
||||
{{#if type === 'gifv' && $autoplayGifs}}
|
||||
{#if type === 'gifv' && $autoplayGifs}
|
||||
<AutoplayVideo
|
||||
className={{noNativeWidthHeight ? 'no-native-width-height' : ''}}
|
||||
ariaLabel="Animated GIF: {{description}}"
|
||||
poster={{previewUrl}}
|
||||
src={{url}}
|
||||
width={{inlineWidth}}
|
||||
height={{inlineHeight}}
|
||||
className={noNativeWidthHeight ? 'no-native-width-height' : ''}
|
||||
ariaLabel="Animated GIF: {description}"
|
||||
poster={previewUrl}
|
||||
src={url}
|
||||
width={inlineWidth}
|
||||
height={inlineHeight}
|
||||
/>
|
||||
{{elseif type === 'gifv' && !$autoplayGifs}}
|
||||
{:elseif type === 'gifv' && !$autoplayGifs}
|
||||
<NonAutoplayGifv
|
||||
class={{noNativeWidthHeight ? 'no-native-width-height' : ''}}
|
||||
label="Animated GIF: {{description}}"
|
||||
poster={{previewUrl}}
|
||||
src={{url}}
|
||||
staticSrc={{previewUrl}}
|
||||
width={{inlineWidth}}
|
||||
height={{inlineHeight}}
|
||||
playing={{mouseover}}
|
||||
class={noNativeWidthHeight ? 'no-native-width-height' : ''}
|
||||
label="Animated GIF: {description}"
|
||||
poster={previewUrl}
|
||||
src={url}
|
||||
staticSrc={previewUrl}
|
||||
width={inlineWidth}
|
||||
height={inlineHeight}
|
||||
playing={mouseover}
|
||||
/>
|
||||
{{else}}
|
||||
{:else}
|
||||
<LazyImage
|
||||
alt={{description}}
|
||||
title={{description}}
|
||||
src={{previewUrl}}
|
||||
fallback={{oneTransparentPixel}}
|
||||
width={{inlineWidth}}
|
||||
height={{inlineHeight}}
|
||||
alt={description}
|
||||
title={description}
|
||||
src={previewUrl}
|
||||
fallback={oneTransparentPixel}
|
||||
width={inlineWidth}
|
||||
height={inlineHeight}
|
||||
background="var(--loading-bg)"
|
||||
className={{noNativeWidthHeight ? 'no-native-width-height' : ''}}
|
||||
className={noNativeWidthHeight ? 'no-native-width-height' : ''}
|
||||
/>
|
||||
{{/if}}
|
||||
{/if}
|
||||
</button>
|
||||
{{/if}}
|
||||
{/if}
|
||||
<style>
|
||||
:global(.status-media video, .status-media img) {
|
||||
object-fit: cover;
|
||||
|
@ -121,24 +121,24 @@
|
|||
},
|
||||
computed: {
|
||||
// width/height to show inline
|
||||
inlineWidth: smallWidth => smallWidth || DEFAULT_MEDIA_WIDTH,
|
||||
inlineHeight: smallHeight => smallHeight || DEFAULT_MEDIA_HEIGHT,
|
||||
inlineWidth: ({ smallWidth }) => smallWidth || DEFAULT_MEDIA_WIDTH,
|
||||
inlineHeight: ({ smallHeight }) => smallHeight || DEFAULT_MEDIA_HEIGHT,
|
||||
// width/height to show in a modal
|
||||
modalWidth: (originalWidth, inlineWidth) => originalWidth || inlineWidth,
|
||||
modalHeight: (originalHeight, inlineHeight) => originalHeight || inlineHeight,
|
||||
meta: media => media.meta,
|
||||
small: meta => meta && meta.small,
|
||||
original: meta => meta && meta.original,
|
||||
smallWidth: small => small && small.width,
|
||||
smallHeight: small => small && small.height,
|
||||
originalWidth: original => original && original.width,
|
||||
originalHeight: original => original && original.height,
|
||||
noNativeWidthHeight: (smallWidth, smallHeight) => typeof smallWidth !== 'number' || typeof smallHeight !== 'number',
|
||||
delegateKey: (media, uuid) => `media-${uuid}-${media.id}`,
|
||||
description: (media) => media.description || '',
|
||||
previewUrl: (media) => media.preview_url,
|
||||
url: (media) => media.url,
|
||||
type: (media) => media.type
|
||||
modalWidth: ({ originalWidth, inlineWidth }) => originalWidth || inlineWidth,
|
||||
modalHeight: ({ originalHeight, inlineHeight }) => originalHeight || inlineHeight,
|
||||
meta: ({ media }) => media.meta,
|
||||
small: ({ meta }) => meta && meta.small,
|
||||
original: ({ meta }) => meta && meta.original,
|
||||
smallWidth: ({ small }) => small && small.width,
|
||||
smallHeight: ({ small }) => small && small.height,
|
||||
originalWidth: ({ original }) => original && original.width,
|
||||
originalHeight: ({ original }) => original && original.height,
|
||||
noNativeWidthHeight: ({ smallWidth, smallHeight }) => typeof smallWidth !== 'number' || typeof smallHeight !== 'number',
|
||||
delegateKey: ({ media, uuid }) => `media-${uuid}-${media.id}`,
|
||||
description: ({ media }) => media.description || '',
|
||||
previewUrl: ({ media }) => media.preview_url,
|
||||
url: ({ media }) => media.url,
|
||||
type: ({ media }) => media.type
|
||||
},
|
||||
methods: {
|
||||
async onClickPlayVideoButton () {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<div class="status-media {{sensitive ? 'status-media-is-sensitive' : ''}}"
|
||||
style="grid-template-columns: repeat(auto-fit, minmax({{maxMediaWidth}}px, 1fr));" >
|
||||
{{#each mediaAttachments as media}}
|
||||
<Media :media :uuid />
|
||||
{{/each}}
|
||||
<div class="status-media {sensitive ? 'status-media-is-sensitive' : ''}"
|
||||
style="grid-template-columns: repeat(auto-fit, minmax({maxMediaWidth}px, 1fr));" >
|
||||
{#each mediaAttachments as media}
|
||||
<Media {media} {uuid} />
|
||||
{/each}
|
||||
</div>
|
||||
<style>
|
||||
.status-media {
|
||||
|
@ -36,7 +36,7 @@
|
|||
|
||||
export default {
|
||||
computed: {
|
||||
maxMediaWidth: (mediaAttachments) => {
|
||||
maxMediaWidth: ({ mediaAttachments }) => {
|
||||
return Math.max.apply(Math, mediaAttachments.map(media => {
|
||||
return media.meta && media.meta.small && typeof media.meta.small.width === 'number' ? media.meta.small.width : DEFAULT_MEDIA_WIDTH
|
||||
}))
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
{{#if status}}
|
||||
<Status :index :length :timelineType :timelineValue :focusSelector
|
||||
:status :notification on:recalculateHeight
|
||||
{#if status}
|
||||
<Status {index} {length} {timelineType} {timelineValue} {focusSelector}
|
||||
{status} {notification} on:recalculateHeight
|
||||
/>
|
||||
{{else}}
|
||||
{:else}
|
||||
<article class="notification-article"
|
||||
tabindex="0"
|
||||
aria-posinset={{index}}
|
||||
aria-setsize={{length}} >
|
||||
<StatusHeader :notification :notificationId :status :statusId :timelineType
|
||||
:account :accountId :uuid isStatusInNotification="true" />
|
||||
aria-posinset={index}
|
||||
aria-setsize={length} >
|
||||
<StatusHeader {notification} {notificationId} {status} {statusId} {timelineType}
|
||||
{account} {accountId} {uuid} isStatusInNotification="true" />
|
||||
</article>
|
||||
{{/if}}
|
||||
{/if}
|
||||
<style>
|
||||
.notification-article {
|
||||
width: 560px;
|
||||
|
@ -38,12 +38,12 @@
|
|||
},
|
||||
store: () => store,
|
||||
computed: {
|
||||
account: (notification) => notification.account,
|
||||
accountId: (account) => account.id,
|
||||
notificationId: (notification) => notification.id,
|
||||
status: (notification) => notification.status,
|
||||
statusId: (status) => status && status.id,
|
||||
uuid: ($currentInstance, timelineType, timelineValue, notificationId, statusId) => {
|
||||
account: ({ notification }) => notification.account,
|
||||
accountId: ({ account }) => account.id,
|
||||
notificationId: ({ notification }) => notification.id,
|
||||
status: ({ notification }) => notification.status,
|
||||
statusId: ({ status }) => status && status.id,
|
||||
uuid: ({ $currentInstance, timelineType, timelineValue, notificationId, statusId }) => {
|
||||
return `${$currentInstance}/${timelineType}/${timelineValue}/${notificationId}/${statusId || ''}`
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,36 +1,36 @@
|
|||
<article class={{className}}
|
||||
<article class={className}
|
||||
tabindex="0"
|
||||
delegate-key={{delegateKey}}
|
||||
focus-key={{delegateKey}}
|
||||
aria-posinset={{index}}
|
||||
aria-setsize={{length}}
|
||||
aria-label={{ariaLabel}}
|
||||
delegate-key={delegateKey}
|
||||
focus-key={delegateKey}
|
||||
aria-posinset={index}
|
||||
aria-setsize={length}
|
||||
aria-label={ariaLabel}
|
||||
on:recalculateHeight>
|
||||
{{#if showHeader}}
|
||||
<StatusHeader {{...params}} />
|
||||
{{/if}}
|
||||
<StatusAuthorName {{...params}} />
|
||||
<StatusAuthorHandle {{...params}} />
|
||||
{{#if !isStatusInOwnThread}}
|
||||
<StatusRelativeDate {{...params}} />
|
||||
{{/if}}
|
||||
<StatusSidebar {{...params}} />
|
||||
{{#if spoilerText}}
|
||||
<StatusSpoiler {{...params}} on:recalculateHeight />
|
||||
{{/if}}
|
||||
{{#if showContent || contentPreloaded}}
|
||||
<StatusContent {{...params}} shown={{showContent}}/>
|
||||
{{/if}}
|
||||
{{#if showMedia }}
|
||||
<StatusMediaAttachments {{...params}} on:recalculateHeight />
|
||||
{{/if}}
|
||||
{{#if isStatusInOwnThread}}
|
||||
<StatusDetails {{...params}} />
|
||||
{{/if}}
|
||||
<StatusToolbar {{...params}} on:recalculateHeight />
|
||||
{{#if replyShown}}
|
||||
<StatusComposeBox {{...params}} on:recalculateHeight />
|
||||
{{/if}}
|
||||
{#if showHeader}
|
||||
<StatusHeader {...params} />
|
||||
{/if}
|
||||
<StatusAuthorName {...params} />
|
||||
<StatusAuthorHandle {...params} />
|
||||
{#if !isStatusInOwnThread}
|
||||
<StatusRelativeDate {...params} />
|
||||
{/if}
|
||||
<StatusSidebar {...params} />
|
||||
{#if spoilerText}
|
||||
<StatusSpoiler {...params} on:recalculateHeight />
|
||||
{/if}
|
||||
{#if showContent || contentPreloaded}
|
||||
<StatusContent {...params} shown={showContent}/>
|
||||
{/if}
|
||||
{#if showMedia }
|
||||
<StatusMediaAttachments {...params} on:recalculateHeight />
|
||||
{/if}
|
||||
{#if isStatusInOwnThread}
|
||||
<StatusDetails {...params} />
|
||||
{/if}
|
||||
<StatusToolbar {...params} on:recalculateHeight />
|
||||
{#if replyShown}
|
||||
<StatusComposeBox {...params} on:recalculateHeight />
|
||||
{/if}
|
||||
</article>
|
||||
|
||||
<style>
|
||||
|
@ -170,56 +170,56 @@
|
|||
}
|
||||
},
|
||||
computed: {
|
||||
originalStatus: (status) => status.reblog ? status.reblog : status,
|
||||
originalStatusId: (originalStatus) => originalStatus.id,
|
||||
statusId: (status) => status.id,
|
||||
notificationId: (notification) => notification && notification.id,
|
||||
account: (notification, status) => (
|
||||
originalStatus: ({ status }) => status.reblog ? status.reblog : status,
|
||||
originalStatusId: ({ originalStatus }) => originalStatus.id,
|
||||
statusId: ({ status }) => status.id,
|
||||
notificationId: ({ notification }) => notification && notification.id,
|
||||
account: ({ notification, status }) => (
|
||||
(notification && notification.account) || status.account
|
||||
),
|
||||
accountId: (account) => account.id,
|
||||
originalAccount: (originalStatus) => originalStatus.account,
|
||||
originalAccountId: (originalAccount) => originalAccount.id,
|
||||
visibility: (originalStatus) => originalStatus.visibility,
|
||||
spoilerText: (originalStatus) => originalStatus.spoiler_text,
|
||||
uuid: ($currentInstance, timelineType, timelineValue, notificationId, statusId) => (
|
||||
accountId: ({ account }) => account.id,
|
||||
originalAccount: ({ originalStatus }) => originalStatus.account,
|
||||
originalAccountId: ({ originalAccount }) => originalAccount.id,
|
||||
visibility: ({ originalStatus }) => originalStatus.visibility,
|
||||
spoilerText: ({ originalStatus }) => originalStatus.spoiler_text,
|
||||
uuid: ({ $currentInstance, timelineType, timelineValue, notificationId, statusId }) => (
|
||||
`${$currentInstance}/${timelineType}/${timelineValue}/${notificationId || ''}/${statusId}`
|
||||
),
|
||||
delegateKey: (uuid) => `status-${uuid}`,
|
||||
isStatusInOwnThread: (timelineType, timelineValue, originalStatusId) => (
|
||||
delegateKey: ({ uuid }) => `status-${uuid}`,
|
||||
isStatusInOwnThread: ({ timelineType, timelineValue, originalStatusId }) => (
|
||||
(timelineType === 'status' || timelineType === 'reply') && timelineValue === originalStatusId
|
||||
),
|
||||
isStatusInNotification: (originalStatusId, notification) => (
|
||||
isStatusInNotification: ({ originalStatusId, notification }) => (
|
||||
notification && notification.status &&
|
||||
notification.type !== 'mention' && notification.status.id === originalStatusId
|
||||
),
|
||||
spoilerShown: ($spoilersShown, uuid) => !!$spoilersShown[uuid],
|
||||
replyShown: ($repliesShown, uuid) => !!$repliesShown[uuid],
|
||||
showMedia: (originalStatus, isStatusInNotification) => (
|
||||
spoilerShown: ({ $spoilersShown, uuid }) => !!$spoilersShown[uuid],
|
||||
replyShown: ({ $repliesShown, uuid }) => !!$repliesShown[uuid],
|
||||
showMedia: ({ originalStatus, isStatusInNotification }) => (
|
||||
!isStatusInNotification &&
|
||||
originalStatus.media_attachments &&
|
||||
originalStatus.media_attachments.length
|
||||
),
|
||||
ariaLabel: (originalAccount, originalStatus, visibility) => (
|
||||
ariaLabel: ({ originalAccount, originalStatus, visibility }) => (
|
||||
(visibility === 'direct' ? 'Direct message' : 'Status') +
|
||||
` by ${originalAccount.display_name || originalAccount.username}`
|
||||
),
|
||||
showHeader: (notification, status, timelineType) => (
|
||||
showHeader: ({ notification, status, timelineType }) => (
|
||||
(notification && (notification.type === 'reblog' || notification.type === 'favourite')) ||
|
||||
status.reblog ||
|
||||
timelineType === 'pinned'
|
||||
),
|
||||
className: (visibility, timelineType, isStatusInOwnThread) => (classname(
|
||||
className: ({ visibility, timelineType, isStatusInOwnThread }) => (classname(
|
||||
'status-article',
|
||||
visibility === 'direct' && 'status-direct',
|
||||
timelineType !== 'search' && 'status-in-timeline',
|
||||
isStatusInOwnThread && 'status-in-own-thread'
|
||||
)),
|
||||
showContent: (spoilerText, spoilerShown) => !spoilerText || spoilerShown,
|
||||
params: (notification, notificationId, status, statusId, timelineType,
|
||||
showContent: ({ spoilerText, spoilerShown }) => !spoilerText || spoilerShown,
|
||||
params: ({ notification, notificationId, status, statusId, timelineType,
|
||||
account, accountId, uuid, isStatusInNotification, isStatusInOwnThread,
|
||||
originalAccount, originalAccountId, spoilerShown, visibility, replyShown,
|
||||
replyVisibility, spoilerText, originalStatus, originalStatusId) => ({
|
||||
replyVisibility, spoilerText, originalStatus, originalStatusId }) => ({
|
||||
notification,
|
||||
notificationId,
|
||||
status,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<span class="status-author-handle {{isStatusInNotification ? 'status-in-notification' : '' }}">
|
||||
{{'@' + originalAccount.acct}}
|
||||
<span class="status-author-handle {isStatusInNotification ? 'status-in-notification' : '' }">
|
||||
{'@' + originalAccount.acct}
|
||||
</span>
|
||||
<style>
|
||||
.status-author-handle {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<a class="status-author-name {{isStatusInNotification ? 'status-in-notification' : '' }} {{isStatusInOwnThread ? 'status-in-own-thread' : ''}}"
|
||||
href="/accounts/{{originalAccountId}}"
|
||||
title="{{'@' + originalAccount.acct}}"
|
||||
focus-key={{focusKey}}
|
||||
<a class="status-author-name {isStatusInNotification ? 'status-in-notification' : '' } {isStatusInOwnThread ? 'status-in-own-thread' : ''}"
|
||||
href="/accounts/{originalAccountId}"
|
||||
title="{'@' + originalAccount.acct}"
|
||||
focus-key={focusKey}
|
||||
>
|
||||
{{originalAccount.display_name || originalAccount.username}}
|
||||
{originalAccount.display_name || originalAccount.username}
|
||||
</a>
|
||||
<style>
|
||||
.status-author-name {
|
||||
|
@ -36,7 +36,7 @@
|
|||
<script>
|
||||
export default {
|
||||
computed: {
|
||||
focusKey: (uuid) => `status-author-name-${uuid}`
|
||||
focusKey: ({ uuid }) => `status-author-name-${uuid}`
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -1,12 +1,12 @@
|
|||
<div class="status-article-compose-box">
|
||||
<ComposeBox realm={{originalStatusId}}
|
||||
<ComposeBox realm={originalStatusId}
|
||||
size="slim"
|
||||
autoFocus="true"
|
||||
hideBottomBorder="true"
|
||||
isReply="true"
|
||||
replyVisibility={{visibility}}
|
||||
replySpoiler={{spoilerText}}
|
||||
inReplyToUuid={{uuid}}
|
||||
replyVisibility={visibility}
|
||||
replySpoiler={spoilerText}
|
||||
inReplyToUuid={uuid}
|
||||
/>
|
||||
</div>
|
||||
<style>
|
||||
|
@ -32,7 +32,7 @@
|
|||
},
|
||||
store: () => store,
|
||||
computed: {
|
||||
composeData: ($currentComposeData, originalStatusId) => $currentComposeData[originalStatusId] || {}
|
||||
composeData: ({ $currentComposeData, originalStatusId }) => $currentComposeData[originalStatusId] || {}
|
||||
},
|
||||
methods: {
|
||||
observe,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<div class={{computedClass}} ref:node>
|
||||
{{{massagedContent}}}
|
||||
<div class={computedClass} ref:node>
|
||||
{@html massagedContent}
|
||||
</div>
|
||||
<style>
|
||||
.status-content {
|
||||
|
@ -71,7 +71,7 @@
|
|||
},
|
||||
store: () => store,
|
||||
computed: {
|
||||
computedClass: (isStatusInOwnThread, isStatusInNotification, shown) => {
|
||||
computedClass: ({ isStatusInOwnThread, isStatusInNotification, shown }) => {
|
||||
return classname(
|
||||
'status-content',
|
||||
isStatusInOwnThread && 'status-in-own-thread',
|
||||
|
@ -79,9 +79,9 @@
|
|||
shown && 'shown'
|
||||
)
|
||||
},
|
||||
content: (originalStatus) => originalStatus.content,
|
||||
emojis: (originalStatus) => originalStatus.emojis,
|
||||
massagedContent: (content, emojis, $autoplayGifs) => {
|
||||
content: ({ originalStatus }) => originalStatus.content,
|
||||
emojis: ({ originalStatus }) => originalStatus.emojis,
|
||||
massagedContent: ({ content, emojis, $autoplayGifs }) => {
|
||||
content = emojifyText(content, emojis, $autoplayGifs)
|
||||
|
||||
// GNU Social and Pleroma don't add <p> tags
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
<div class="status-details">
|
||||
<ExternalLink className="status-absolute-date"
|
||||
href={{originalStatus.url}}
|
||||
href={originalStatus.url}
|
||||
showIcon="true"
|
||||
ariaLabel="{{formattedDate}} (opens in new window)"
|
||||
ariaLabel="{formattedDate} (opens in new window)"
|
||||
>
|
||||
<time datetime={{createdAtDate}} title={{formattedDate}}>{{formattedDate}}</time>
|
||||
<time datetime={createdAtDate} title={formattedDate}>{formattedDate}</time>
|
||||
</ExternalLink>
|
||||
<a class="status-favs-reblogs"
|
||||
href="/statuses/{{originalStatusId}}/reblogs"
|
||||
aria-label={{reblogsLabel}}>
|
||||
href="/statuses/{originalStatusId}/reblogs"
|
||||
aria-label={reblogsLabel}>
|
||||
<svg class="status-favs-reblogs-svg">
|
||||
<use xlink:href="#fa-retweet"/>
|
||||
</svg>
|
||||
<span>{{numReblogs}}</span>
|
||||
<span>{numReblogs}</span>
|
||||
</a>
|
||||
<a class="status-favs-reblogs"
|
||||
href="/statuses/{{originalStatusId}}/favorites"
|
||||
aria-label={{favoritesLabel}}>
|
||||
href="/statuses/{originalStatusId}/favorites"
|
||||
aria-label={favoritesLabel}>
|
||||
<svg class="status-favs-reblogs-svg">
|
||||
<use xlink:href="#fa-star" />
|
||||
</svg>
|
||||
<span>{{numFavs}}</span>
|
||||
<span>{numFavs}</span>
|
||||
</a>
|
||||
</div>
|
||||
<style>
|
||||
|
@ -99,17 +99,17 @@
|
|||
|
||||
export default {
|
||||
computed: {
|
||||
createdAtDate: (originalStatus) => originalStatus.created_at,
|
||||
numReblogs: (originalStatus) => originalStatus.reblogs_count || 0,
|
||||
numFavs: (originalStatus) => originalStatus.favourites_count || 0,
|
||||
formattedDate: (createdAtDate) => formatter.format(new Date(createdAtDate)),
|
||||
reblogsLabel: (numReblogs) => {
|
||||
createdAtDate: ({ originalStatus }) => originalStatus.created_at,
|
||||
numReblogs: ({ originalStatus }) => originalStatus.reblogs_count || 0,
|
||||
numFavs: ({ originalStatus }) => originalStatus.favourites_count || 0,
|
||||
formattedDate: ({ createdAtDate }) => formatter.format(new Date(createdAtDate)),
|
||||
reblogsLabel: ({ numReblogs }) => {
|
||||
// TODO: intl
|
||||
return numReblogs === 1
|
||||
? `Boosted ${numReblogs} time`
|
||||
: `Boosted ${numReblogs} times`
|
||||
},
|
||||
favoritesLabel: (numFavs) => {
|
||||
favoritesLabel: ({ numFavs }) => {
|
||||
// TODO: intl
|
||||
return numFavs === 1
|
||||
? `Favorited ${numFavs} time`
|
||||
|
|
|
@ -1,30 +1,30 @@
|
|||
<div class="status-header {{isStatusInNotification ? 'status-in-notification' : ''}} {{notification && notification.type === 'follow' ? 'header-is-follow' : ''}}">
|
||||
<div class="status-header-avatar {{timelineType === 'pinned' ? 'hidden' : ''}}">
|
||||
<Avatar :account size="extra-small"/>
|
||||
<div class="status-header {isStatusInNotification ? 'status-in-notification' : ''} {notification && notification.type === 'follow' ? 'header-is-follow' : ''}">
|
||||
<div class="status-header-avatar {timelineType === 'pinned' ? 'hidden' : ''}">
|
||||
<Avatar {account} size="extra-small"/>
|
||||
</div>
|
||||
<svg class="status-header-svg">
|
||||
<use xlink:href={{icon}}/>
|
||||
<use xlink:href={icon}/>
|
||||
</svg>
|
||||
<span class="status-header-span">
|
||||
{{#if timelineType === 'pinned'}}
|
||||
{#if timelineType === 'pinned'}
|
||||
Pinned toot
|
||||
{{else}}
|
||||
<a href="/accounts/{{accountId}}"
|
||||
{:else}
|
||||
<a href="/accounts/{accountId}"
|
||||
class="status-header-a"
|
||||
title="{{'@' + account.acct}}"
|
||||
focus-key={{focusKey}} >
|
||||
{{account.display_name || account.username}}
|
||||
title="{'@' + account.acct}"
|
||||
focus-key={focusKey} >
|
||||
{account.display_name || account.username}
|
||||
</a>
|
||||
{{#if notification && notification.type === 'reblog'}}
|
||||
{#if notification && notification.type === 'reblog'}
|
||||
boosted your status
|
||||
{{elseif notification && notification.type === 'favourite'}}
|
||||
{:elseif notification && notification.type === 'favourite'}
|
||||
favorited your status
|
||||
{{elseif notification && notification.type === 'follow'}}
|
||||
{:elseif notification && notification.type === 'follow'}
|
||||
followed you
|
||||
{{elseif status && status.reblog}}
|
||||
{:elseif status && status.reblog}
|
||||
boosted
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{/if}
|
||||
{/if}
|
||||
</span>
|
||||
</div>
|
||||
<style>
|
||||
|
@ -88,8 +88,8 @@
|
|||
Avatar
|
||||
},
|
||||
computed: {
|
||||
focusKey: (uuid) => `status-header-${uuid}`,
|
||||
icon: (notification, status, timelineType) => {
|
||||
focusKey: ({ uuid }) => `status-header-${uuid}`,
|
||||
icon: ({ notification, status, timelineType }) => {
|
||||
if (timelineType === 'pinned') {
|
||||
return '#fa-thumb-tack'
|
||||
} else if ((notification && notification.type === 'reblog') || (status && status.reblog)) {
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
{{#if sensitive }}
|
||||
<div class="status-sensitive-media-container {{sensitiveShown ? 'status-sensitive-media-shown' : 'status-sensitive-media-hidden'}}"
|
||||
{#if sensitive }
|
||||
<div class="status-sensitive-media-container {sensitiveShown ? 'status-sensitive-media-shown' : 'status-sensitive-media-hidden'}"
|
||||
>
|
||||
{{#if sensitiveShown}}
|
||||
{#if sensitiveShown}
|
||||
<button type="button"
|
||||
class="status-sensitive-media-button"
|
||||
aria-label="Hide sensitive media"
|
||||
delegate-key={{delegateKey}} >
|
||||
delegate-key={delegateKey} >
|
||||
<div class="svg-wrapper">
|
||||
<svg class="status-sensitive-media-svg">
|
||||
<use xlink:href="#fa-eye-slash" />
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
<MediaAttachments :mediaAttachments :sensitive :uuid />
|
||||
{{else}}
|
||||
<MediaAttachments {mediaAttachments} {sensitive} {uuid} />
|
||||
{:else}
|
||||
<button type="button"
|
||||
class="status-sensitive-media-button"
|
||||
aria-label="Show sensitive media"
|
||||
delegate-key={{delegateKey}} >
|
||||
delegate-key={delegateKey} >
|
||||
|
||||
<div class="status-sensitive-media-warning">
|
||||
<span>Sensitive content. Click to show.</span>
|
||||
|
@ -28,11 +28,11 @@
|
|||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
{{/if}}
|
||||
{/if}
|
||||
</div>
|
||||
{{else}}
|
||||
<MediaAttachments :mediaAttachments :sensitive :uuid />
|
||||
{{/if}}
|
||||
{:else}
|
||||
<MediaAttachments {mediaAttachments} {sensitive} {uuid} />
|
||||
{/if}
|
||||
<style>
|
||||
.status-sensitive-media-container {
|
||||
grid-area: media;
|
||||
|
@ -138,10 +138,10 @@
|
|||
},
|
||||
store: () => store,
|
||||
computed: {
|
||||
mediaAttachments: (originalStatus) => originalStatus.media_attachments,
|
||||
sensitiveShown: ($sensitivesShown, uuid) => !!$sensitivesShown[uuid],
|
||||
sensitive: (originalStatus, $markMediaAsSensitive) => originalStatus.sensitive || $markMediaAsSensitive,
|
||||
delegateKey: (uuid) => `sensitive-${uuid}`
|
||||
mediaAttachments: ({ originalStatus }) => originalStatus.media_attachments,
|
||||
sensitiveShown: ({ $sensitivesShown, uuid }) => !!$sensitivesShown[uuid],
|
||||
sensitive: ({ originalStatus, $markMediaAsSensitive }) => originalStatus.sensitive || $markMediaAsSensitive,
|
||||
delegateKey: ({ uuid }) => `sensitive-${uuid}`
|
||||
},
|
||||
methods: {
|
||||
onClickSensitiveMediaButton () {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<a class="status-relative-date {{isStatusInNotification ? 'status-in-notification' : '' }}"
|
||||
href="/statuses/{{originalStatusId}}"
|
||||
focus-key={{focusKey}}
|
||||
<a class="status-relative-date {isStatusInNotification ? 'status-in-notification' : '' }"
|
||||
href="/statuses/{originalStatusId}"
|
||||
focus-key={focusKey}
|
||||
>
|
||||
<time datetime={{createdAtDate}} title={{relativeDate}}
|
||||
aria-label="{{relativeDate}} – click to show thread">
|
||||
{{relativeDate}}
|
||||
<time datetime={createdAtDate} title={relativeDate}
|
||||
aria-label="{relativeDate} – click to show thread">
|
||||
{relativeDate}
|
||||
</time>
|
||||
</a>
|
||||
<style>
|
||||
|
@ -35,14 +35,14 @@
|
|||
|
||||
export default {
|
||||
computed: {
|
||||
createdAtDate: (originalStatus) => originalStatus.created_at,
|
||||
relativeDate: (createdAtDate) => {
|
||||
createdAtDate: ({ originalStatus }) => originalStatus.created_at,
|
||||
relativeDate: ({ createdAtDate }) => {
|
||||
mark('compute relativeDate')
|
||||
let res = timeagoInstance.format(createdAtDate)
|
||||
stop('compute relativeDate')
|
||||
return res
|
||||
},
|
||||
focusKey: (uuid) => `status-relative-date-${uuid}`
|
||||
focusKey: ({ uuid }) => `status-relative-date-${uuid}`
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -1,11 +1,11 @@
|
|||
<a class="status-sidebar size-{{size}}"
|
||||
href="/accounts/{{originalAccountId}}"
|
||||
focus-key={{focusKey}}
|
||||
<a class="status-sidebar size-{size}"
|
||||
href="/accounts/{originalAccountId}"
|
||||
focus-key={focusKey}
|
||||
aria-hidden="true"
|
||||
>
|
||||
<Avatar account={{originalAccount}}
|
||||
<Avatar account={originalAccount}
|
||||
isLink="true"
|
||||
:size />
|
||||
{size} />
|
||||
</a>
|
||||
<style>
|
||||
.status-sidebar {
|
||||
|
@ -36,8 +36,8 @@
|
|||
Avatar
|
||||
},
|
||||
computed: {
|
||||
focusKey: (uuid) => `status-author-avatar-${uuid}`,
|
||||
size: (isStatusInOwnThread) => isStatusInOwnThread ? 'medium' : 'small'
|
||||
focusKey: ({ uuid }) => `status-author-avatar-${uuid}`,
|
||||
size: ({ isStatusInOwnThread }) => isStatusInOwnThread ? 'medium' : 'small'
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -1,9 +1,9 @@
|
|||
<div class="status-spoiler {{isStatusInNotification ? 'status-in-notification' : ''}} {{isStatusInOwnThread ? 'status-in-own-thread' : ''}}">
|
||||
<p>{{{massagedSpoilerText}}}</p>
|
||||
<div class="status-spoiler {isStatusInNotification ? 'status-in-notification' : ''} {isStatusInOwnThread ? 'status-in-own-thread' : ''}">
|
||||
<p>{@html massagedSpoilerText}</p>
|
||||
</div>
|
||||
<div class="status-spoiler-button {{isStatusInOwnThread ? 'status-in-own-thread' : ''}}">
|
||||
<button type="button" delegate-key={{delegateKey}}>
|
||||
{{spoilerShown ? 'Show less' : 'Show more'}}
|
||||
<div class="status-spoiler-button {isStatusInOwnThread ? 'status-in-own-thread' : ''}">
|
||||
<button type="button" delegate-key={delegateKey}>
|
||||
{spoilerShown ? 'Show less' : 'Show more'}
|
||||
</button>
|
||||
</div>
|
||||
<style>
|
||||
|
@ -60,13 +60,13 @@
|
|||
},
|
||||
store: () => store,
|
||||
computed: {
|
||||
spoilerText: (originalStatus) => originalStatus.spoiler_text,
|
||||
emojis: (originalStatus) => originalStatus.emojis,
|
||||
massagedSpoilerText: (spoilerText, emojis, $autoplayGifs) => {
|
||||
spoilerText: ({ originalStatus }) => originalStatus.spoiler_text,
|
||||
emojis: ({ originalStatus }) => originalStatus.emojis,
|
||||
massagedSpoilerText: ({ spoilerText, emojis, $autoplayGifs }) => {
|
||||
spoilerText = escapeHtml(spoilerText)
|
||||
return emojifyText(spoilerText, emojis, $autoplayGifs)
|
||||
},
|
||||
delegateKey: (uuid) => `spoiler-${uuid}`
|
||||
delegateKey: ({ uuid }) => `spoiler-${uuid}`
|
||||
},
|
||||
methods: {
|
||||
onClickSpoilerButton () {
|
||||
|
|
|
@ -1,34 +1,34 @@
|
|||
<div class="status-toolbar {{isStatusInOwnThread ? 'status-in-own-thread' : ''}}" ref:node>
|
||||
<div class="status-toolbar {isStatusInOwnThread ? 'status-in-own-thread' : ''}" ref:node>
|
||||
<IconButton
|
||||
className="status-toolbar-reply-button"
|
||||
label={{replyLabel}}
|
||||
label={replyLabel}
|
||||
pressable="true"
|
||||
pressed={{replyShown}}
|
||||
pressed={replyShown}
|
||||
href="#fa-reply"
|
||||
delegateKey={{replyKey}}
|
||||
focusKey={{replyKey}}
|
||||
delegateKey={replyKey}
|
||||
focusKey={replyKey}
|
||||
/>
|
||||
<IconButton
|
||||
label={{reblogLabel}}
|
||||
pressable={{!reblogDisabled}}
|
||||
pressed={{reblogged}}
|
||||
disabled={{reblogDisabled}}
|
||||
href={{reblogIcon}}
|
||||
delegateKey={{reblogKey}}
|
||||
label={reblogLabel}
|
||||
pressable={!reblogDisabled}
|
||||
pressed={reblogged}
|
||||
disabled={reblogDisabled}
|
||||
href={reblogIcon}
|
||||
delegateKey={reblogKey}
|
||||
ref:reblogIcon
|
||||
/>
|
||||
<IconButton
|
||||
label="Favorite"
|
||||
pressable="true"
|
||||
pressed={{favorited}}
|
||||
pressed={favorited}
|
||||
href="#fa-star"
|
||||
delegateKey={{favoriteKey}}
|
||||
delegateKey={favoriteKey}
|
||||
ref:favoriteIcon
|
||||
/>
|
||||
<IconButton
|
||||
label="Show more options"
|
||||
href="#fa-ellipsis-h"
|
||||
delegateKey={{optionsKey}}
|
||||
delegateKey={optionsKey}
|
||||
/>
|
||||
</div>
|
||||
<style>
|
||||
|
@ -133,8 +133,8 @@
|
|||
reblogAnimation: REBLOG_ANIMATION
|
||||
}),
|
||||
computed: {
|
||||
replyLabel: (replyShown) => replyShown ? 'Close reply' : 'Reply',
|
||||
reblogLabel: (visibility) => {
|
||||
replyLabel: ({ replyShown }) => replyShown ? 'Close reply' : 'Reply',
|
||||
reblogLabel: ({ visibility }) => {
|
||||
switch (visibility) {
|
||||
case 'private':
|
||||
return 'Cannot be boosted because this is followers-only'
|
||||
|
@ -144,7 +144,7 @@
|
|||
return 'Boost'
|
||||
}
|
||||
},
|
||||
reblogIcon: (visibility) => {
|
||||
reblogIcon: ({ visibility }) => {
|
||||
switch (visibility) {
|
||||
case 'private':
|
||||
return '#fa-lock'
|
||||
|
@ -154,25 +154,25 @@
|
|||
return '#fa-retweet'
|
||||
}
|
||||
},
|
||||
reblogDisabled: (visibility) => {
|
||||
reblogDisabled: ({ visibility }) => {
|
||||
return visibility === 'private' || visibility === 'direct'
|
||||
},
|
||||
reblogged: (originalStatusId, $currentStatusModifications, originalStatus) => {
|
||||
reblogged: ({ originalStatusId, $currentStatusModifications, originalStatus }) => {
|
||||
if ($currentStatusModifications && originalStatusId in $currentStatusModifications.reblogs) {
|
||||
return $currentStatusModifications.reblogs[originalStatusId]
|
||||
}
|
||||
return originalStatus.reblogged
|
||||
},
|
||||
favorited: (originalStatusId, $currentStatusModifications, originalStatus) => {
|
||||
favorited: ({ originalStatusId, $currentStatusModifications, originalStatus }) => {
|
||||
if ($currentStatusModifications && originalStatusId in $currentStatusModifications.favorites) {
|
||||
return $currentStatusModifications.favorites[originalStatusId]
|
||||
}
|
||||
return originalStatus.favourited
|
||||
},
|
||||
favoriteKey: (uuid) => `fav-${uuid}`,
|
||||
reblogKey: (uuid) => `reblog-${uuid}`,
|
||||
replyKey: (uuid) => `reply-${uuid}`,
|
||||
optionsKey: (uuid) => `options-${uuid}`
|
||||
favoriteKey: ({ uuid }) => `fav-${uuid}`,
|
||||
reblogKey: ({ uuid }) => `reblog-${uuid}`,
|
||||
replyKey: ({ uuid }) => `reply-${uuid}`,
|
||||
optionsKey: ({ uuid }) => `options-${uuid}`
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -1,11 +1,11 @@
|
|||
<div class="lazy-timeline">
|
||||
{{#await importTimeline}}
|
||||
{#await importTimeline}
|
||||
<!-- awaiting promise -->
|
||||
{{then constructor}}
|
||||
<:Component {constructor} :timeline />
|
||||
{{catch error}}
|
||||
<div>Component failed to load. Try refreshing! {{error}}</div>
|
||||
{{/await}}
|
||||
{:then constructor}
|
||||
<svelte:component this={constructor} {timeline} />
|
||||
{:catch error}
|
||||
<div>Component failed to load. Try refreshing! {error}</div>
|
||||
{/await}
|
||||
</div>
|
||||
<style>
|
||||
.lazy-timeline {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<div class="loading-footer">
|
||||
<LoadingSpinner size={{48}} />
|
||||
<LoadingSpinner size={48} />
|
||||
<span class="loading-footer-info">
|
||||
Loading more...
|
||||
</span>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div class="more-items-header">
|
||||
<button class="primary" type="button" on:click="onClick(event)">
|
||||
Show {{count}} more
|
||||
Show {count} more
|
||||
</button>
|
||||
</div>
|
||||
<style>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<MoreHeader count={{virtualProps.count}}
|
||||
onClick={{virtualProps.onClick}}
|
||||
<MoreHeader count={virtualProps.count}
|
||||
onClick={virtualProps.onClick}
|
||||
/>
|
||||
<script>
|
||||
import MoreHeader from './MoreHeader.html'
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<Notification
|
||||
notification={{virtualProps.notification}}
|
||||
timelineType={{virtualProps.timelineType}}
|
||||
timelineValue={{virtualProps.timelineValue}}
|
||||
focusSelector={{virtualProps.focusSelector}}
|
||||
index={{virtualIndex}}
|
||||
length={{virtualLength}}
|
||||
notification={virtualProps.notification}
|
||||
timelineType={virtualProps.timelineType}
|
||||
timelineValue={virtualProps.timelineValue}
|
||||
focusSelector={virtualProps.focusSelector}
|
||||
index={virtualIndex}
|
||||
length={virtualLength}
|
||||
on:recalculateHeight />
|
||||
<script>
|
||||
import Notification from '../status/Notification.html'
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<div role="feed" aria-label="Pinned toots" class="pinned-statuses">
|
||||
{{#each pinnedStatuses as status, index @id}}
|
||||
<Status :status
|
||||
{#each pinnedStatuses as status, index (status.id)}
|
||||
<Status {status}
|
||||
timelineType="pinned"
|
||||
timelineValue={{accountId}}
|
||||
:index
|
||||
length={{pinnedStatuses.length}}
|
||||
timelineValue={accountId}
|
||||
{index}
|
||||
length={pinnedStatuses.length}
|
||||
/>
|
||||
{{/each}}
|
||||
{/each}
|
||||
</div>
|
||||
<script>
|
||||
import { store } from '../../_store/store'
|
||||
|
@ -20,7 +20,7 @@
|
|||
await this.updatePinnedStatuses()
|
||||
},
|
||||
computed: {
|
||||
pinnedStatuses: ($pinnedStatuses, $currentInstance, accountId) => {
|
||||
pinnedStatuses: ({ $pinnedStatuses, $currentInstance, accountId }) => {
|
||||
return ($pinnedStatuses[$currentInstance] && $pinnedStatuses[$currentInstance][accountId]) || []
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<Status status={{virtualProps.status}}
|
||||
timelineType={{virtualProps.timelineType}}
|
||||
timelineValue={{virtualProps.timelineValue}}
|
||||
focusSelector={{virtualProps.focusSelector}}
|
||||
index={{virtualIndex}}
|
||||
length={{virtualLength}}
|
||||
<Status status={virtualProps.status}
|
||||
timelineType={virtualProps.timelineType}
|
||||
timelineValue={virtualProps.timelineValue}
|
||||
focusSelector={virtualProps.focusSelector}
|
||||
index={virtualIndex}
|
||||
length={virtualLength}
|
||||
on:recalculateHeight />
|
||||
<script>
|
||||
import Status from '../status/Status.html'
|
||||
|
|
|
@ -1,33 +1,33 @@
|
|||
<h1 class="sr-only">{{label}}</h1>
|
||||
<h1 class="sr-only">{label}</h1>
|
||||
<div class="timeline"
|
||||
role="feed"
|
||||
on:focusWithCapture="saveFocus(event)"
|
||||
on:blurWithCapture="clearFocus(event)"
|
||||
>
|
||||
{{#await componentsPromise}}
|
||||
{#await componentsPromise}
|
||||
<!-- awaiting promise -->
|
||||
{{then result}}
|
||||
<:Component {result.listComponent}
|
||||
component={{result.listItemComponent}}
|
||||
realm="{{$currentInstance + '/' + timeline}}"
|
||||
{:then result}
|
||||
<svelte:component this={result.listComponent}
|
||||
component={result.listItemComponent}
|
||||
realm="{$currentInstance + '/' + timeline}"
|
||||
containerQuery=".container"
|
||||
:makeProps
|
||||
items={{$timelineItemIds}}
|
||||
showFooter={{$timelineInitialized && $runningUpdate}}
|
||||
footerComponent={{LoadingFooter}}
|
||||
showHeader={{$showHeader}}
|
||||
headerComponent={{MoreHeaderVirtualWrapper}}
|
||||
:headerProps
|
||||
:scrollToItem
|
||||
{makeProps}
|
||||
items={$timelineItemIds}
|
||||
showFooter={$timelineInitialized && $runningUpdate}
|
||||
footerComponent={LoadingFooter}
|
||||
showHeader={$showHeader}
|
||||
headerComponent={MoreHeaderVirtualWrapper}
|
||||
{headerProps}
|
||||
{scrollToItem}
|
||||
on:scrollToBottom="onScrollToBottom()"
|
||||
on:scrollToTop="onScrollToTop()"
|
||||
on:scrollTopChanged="onScrollTopChanged(event)"
|
||||
on:initialized="initialize()"
|
||||
on:noNeedToScroll="onNoNeedToScroll()"
|
||||
/>
|
||||
{{catch error}}
|
||||
<div>Error: component failed to load! Try reloading. {{error}}</div>
|
||||
{{/await}}
|
||||
{:catch error}
|
||||
<div>Error: component failed to load! Try reloading. {error}</div>
|
||||
{/await}
|
||||
</div>
|
||||
<script>
|
||||
import { store } from '../../_store/store'
|
||||
|
@ -82,7 +82,7 @@
|
|||
// due to need to scroll to the right item and thus calculate all item heights up-front.
|
||||
// Here we lazy-load both the virtual list component itself as well as the component
|
||||
// it renders.
|
||||
componentsPromise: (timelineType) => {
|
||||
componentsPromise: ({ timelineType }) => {
|
||||
return Promise.all([
|
||||
timelineType === 'status'
|
||||
? importPseudoVirtualList()
|
||||
|
@ -95,7 +95,7 @@
|
|||
listItemComponent: results[1]
|
||||
}))
|
||||
},
|
||||
makeProps: ($currentInstance, timelineType, timelineValue) => async (itemId) => {
|
||||
makeProps: ({ $currentInstance, timelineType, timelineValue }) => async (itemId) => {
|
||||
let res = {
|
||||
timelineType,
|
||||
timelineValue
|
||||
|
@ -107,7 +107,7 @@
|
|||
}
|
||||
return res
|
||||
},
|
||||
label: (timeline, $currentInstance, timelineType, timelineValue) => {
|
||||
label: ({ timeline, $currentInstance, timelineType, timelineValue }) => {
|
||||
if (timelines[timeline]) {
|
||||
return `${timelines[timeline].label} timeline for ${$currentInstance}`
|
||||
}
|
||||
|
@ -125,20 +125,20 @@
|
|||
return `Notifications for ${$currentInstance}`
|
||||
}
|
||||
},
|
||||
timelineType: (timeline) => {
|
||||
timelineType: ({ timeline }) => {
|
||||
return timeline.split('/')[0]
|
||||
},
|
||||
timelineValue: (timeline) => {
|
||||
timelineValue: ({ timeline }) => {
|
||||
return timeline.split('/').slice(-1)[0]
|
||||
},
|
||||
// Scroll to the first item if this is a "status in own thread" timeline.
|
||||
// Don't scroll to the first item because it obscures the "back" button.
|
||||
scrollToItem: (timelineType, timelineValue, $firstTimelineItemId) => (
|
||||
scrollToItem: ({ timelineType, timelineValue, $firstTimelineItemId }) => (
|
||||
timelineType === 'status' && $firstTimelineItemId &&
|
||||
timelineValue !== $firstTimelineItemId && timelineValue
|
||||
),
|
||||
itemIdsToAdd: ($itemIdsToAdd) => $itemIdsToAdd,
|
||||
headerProps: (itemIdsToAdd) => {
|
||||
itemIdsToAdd: ({ $itemIdsToAdd }) => $itemIdsToAdd,
|
||||
headerProps: ({ itemIdsToAdd }) => {
|
||||
return {
|
||||
count: itemIdsToAdd ? itemIdsToAdd.length : 0,
|
||||
onClick: showMoreItemsForCurrentTimeline
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
<VirtualListContainer :realm :containerQuery on:initialized on:noNeedToScroll >
|
||||
<VirtualListContainer {realm} {containerQuery} on:initialized on:noNeedToScroll >
|
||||
<div class="virtual-list"
|
||||
style="height: {{$height}}px;"
|
||||
style="height: {$height}px;"
|
||||
ref:node >
|
||||
<VirtualListHeader component={{headerComponent}} virtualProps={{headerProps}} shown={{$showHeader}}/>
|
||||
{{#if $visibleItems}}
|
||||
{{#each $visibleItems as visibleItem @key}}
|
||||
<VirtualListLazyItem :component
|
||||
offset={{visibleItem.offset}}
|
||||
:makeProps
|
||||
key={{visibleItem.key}}
|
||||
index={{visibleItem.index}}
|
||||
<VirtualListHeader component={headerComponent} virtualProps={headerProps} shown={$showHeader}/>
|
||||
{#if $visibleItems}
|
||||
{#each $visibleItems as visibleItem (visibleItem.key)}
|
||||
<VirtualListLazyItem {component}
|
||||
offset={visibleItem.offset}
|
||||
{makeProps}
|
||||
key={visibleItem.key}
|
||||
index={visibleItem.index}
|
||||
/>
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
{{#if $showFooter}}
|
||||
<VirtualListFooter component={{footerComponent}} />
|
||||
{{/if}}
|
||||
{/each}
|
||||
{/if}
|
||||
{#if $showFooter}
|
||||
<VirtualListFooter component={footerComponent} />
|
||||
{/if}
|
||||
</div>
|
||||
</VirtualListContainer>
|
||||
<style>
|
||||
|
@ -101,12 +101,12 @@
|
|||
VirtualListHeader
|
||||
},
|
||||
computed: {
|
||||
distanceFromBottom: ($scrollHeight, $scrollTop, $offsetHeight) => {
|
||||
distanceFromBottom: ({ $scrollHeight, $scrollTop, $offsetHeight }) => {
|
||||
return $scrollHeight - $scrollTop - $offsetHeight
|
||||
},
|
||||
scrollTop: ($scrollTop) => $scrollTop,
|
||||
scrollTop: ({ $scrollTop }) => $scrollTop,
|
||||
// TODO: bug in svelte store, shouldn't need to do this
|
||||
allVisibleItemsHaveHeight: ($allVisibleItemsHaveHeight) => $allVisibleItemsHaveHeight
|
||||
allVisibleItemsHaveHeight: ({ $allVisibleItemsHaveHeight }) => $allVisibleItemsHaveHeight
|
||||
},
|
||||
methods: {
|
||||
observe,
|
||||
|
|
|
@ -115,7 +115,7 @@
|
|||
},
|
||||
computed: {
|
||||
// TODO: bug in svelte/store – the observer in oncreate() never get removed without this hack
|
||||
allVisibleItemsHaveHeight: ($allVisibleItemsHaveHeight) => $allVisibleItemsHaveHeight
|
||||
allVisibleItemsHaveHeight: ({ $allVisibleItemsHaveHeight }) => $allVisibleItemsHaveHeight
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -1,7 +1,7 @@
|
|||
<div class="virtual-list-footer"
|
||||
ref:node
|
||||
style="transform: translateY({{$heightWithoutFooter}}px);" >
|
||||
<:Component {component} />
|
||||
style="transform: translateY({$heightWithoutFooter}px);" >
|
||||
<svelte:component this={component} />
|
||||
</div>
|
||||
<style>
|
||||
.virtual-list-footer {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div class="virtual-list-header {{shown ? 'shown' : ''}} {{fadedIn ? 'faded-in' : ''}}"
|
||||
<div class="virtual-list-header {shown ? 'shown' : ''} {fadedIn ? 'faded-in' : ''}"
|
||||
ref:node >
|
||||
<:Component {component} :virtualProps />
|
||||
<svelte:component this={component} {virtualProps} />
|
||||
</div>
|
||||
<style>
|
||||
.virtual-list-header {
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<div class="virtual-list-item {{shown ? 'shown' : ''}}"
|
||||
aria-hidden={{!shown}}
|
||||
virtual-list-key={{key}}
|
||||
<div class="virtual-list-item {shown ? 'shown' : ''}"
|
||||
aria-hidden={!shown}
|
||||
virtual-list-key={key}
|
||||
ref:node
|
||||
style="transform: translateY({{offset}}px);" >
|
||||
<:Component {component}
|
||||
virtualProps={{props}}
|
||||
virtualIndex={{index}}
|
||||
virtualLength={{$length}}
|
||||
style="transform: translateY({offset}px);" >
|
||||
<svelte:component this={component}
|
||||
virtualProps={props}
|
||||
virtualIndex={index}
|
||||
virtualLength={$length}
|
||||
on:recalculateHeight="doRecalculateHeight()"/>
|
||||
</div>
|
||||
<style>
|
||||
|
@ -45,7 +45,7 @@
|
|||
},
|
||||
store: () => virtualListStore,
|
||||
computed: {
|
||||
'shown': ($itemHeights, key) => $itemHeights[key] > 0
|
||||
'shown': ({ $itemHeights, key }) => $itemHeights[key] > 0
|
||||
},
|
||||
methods: {
|
||||
doRecalculateHeight () {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
{{#if props}}
|
||||
<VirtualListItem :component
|
||||
:offset
|
||||
:props
|
||||
:key
|
||||
:index
|
||||
{#if props}
|
||||
<VirtualListItem {component}
|
||||
{offset}
|
||||
{props}
|
||||
{key}
|
||||
{index}
|
||||
/>
|
||||
{{/if}}
|
||||
{/if}
|
||||
<script>
|
||||
import VirtualListItem from './VirtualListItem'
|
||||
import { mark, stop } from '../../_utils/marks'
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
{{#if $isUserLoggedIn}}
|
||||
<TimelinePage timeline="account/{{params.accountId}}">
|
||||
{#if $isUserLoggedIn}
|
||||
<TimelinePage timeline="account/{params.accountId}">
|
||||
<DynamicPageBanner title="" />
|
||||
{{#if $currentAccountProfile && $currentVerifyCredentials}}
|
||||
<AccountProfile account={{$currentAccountProfile}}
|
||||
relationship={{$currentAccountRelationship}}
|
||||
verifyCredentials={{$currentVerifyCredentials}}
|
||||
{#if $currentAccountProfile && $currentVerifyCredentials}
|
||||
<AccountProfile account={$currentAccountProfile}
|
||||
relationship={$currentAccountRelationship}
|
||||
verifyCredentials={$currentVerifyCredentials}
|
||||
/>
|
||||
{{/if}}
|
||||
<PinnedStatuses accountId={{params.accountId}} />
|
||||
{/if}
|
||||
<PinnedStatuses accountId={params.accountId} />
|
||||
</TimelinePage>
|
||||
{{else}}
|
||||
{:else}
|
||||
<HiddenFromSSR>
|
||||
<FreeTextLayout>
|
||||
<h1>Profile</h1>
|
||||
|
@ -17,7 +17,7 @@
|
|||
<p>A user timeline will appear here when logged in.</p>
|
||||
</FreeTextLayout>
|
||||
</HiddenFromSSR>
|
||||
{{/if}}
|
||||
{/if}
|
||||
<script>
|
||||
import TimelinePage from '../../_components/TimelinePage.html'
|
||||
import FreeTextLayout from '../../_components/FreeTextLayout.html'
|
||||
|
@ -37,10 +37,10 @@
|
|||
},
|
||||
store: () => store,
|
||||
computed: {
|
||||
profileName: ($currentAccountProfile) => {
|
||||
profileName: ({ $currentAccountProfile }) => {
|
||||
return ($currentAccountProfile && ('@' + $currentAccountProfile.acct)) || ''
|
||||
},
|
||||
shortProfileName: ($currentAccountProfile) => {
|
||||
shortProfileName: ({ $currentAccountProfile }) => {
|
||||
return ($currentAccountProfile && ('@' + $currentAccountProfile.username)) || ''
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<DynamicPageBanner title="Followers" />
|
||||
<AccountsListPage :accountsFetcher />
|
||||
<AccountsListPage {accountsFetcher} />
|
||||
<script>
|
||||
import { getFollowers } from '../../../_api/followsAndFollowers'
|
||||
import AccountsListPage from '../../../_components/AccountsListPage.html'
|
||||
|
@ -8,8 +8,8 @@
|
|||
|
||||
export default {
|
||||
computed: {
|
||||
accountId: params => params.accountId,
|
||||
accountsFetcher: ($currentInstance, $accessToken, accountId) => () => getFollowers($currentInstance, $accessToken, accountId)
|
||||
accountId: ({ params }) => params.accountId,
|
||||
accountsFetcher: ({ $currentInstance, $accessToken, accountId }) => () => getFollowers($currentInstance, $accessToken, accountId)
|
||||
},
|
||||
store: () => store,
|
||||
components: {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<DynamicPageBanner title="Follows" />
|
||||
<AccountsListPage :accountsFetcher />
|
||||
<AccountsListPage {accountsFetcher} />
|
||||
<script>
|
||||
import { getFollows } from '../../../_api/followsAndFollowers'
|
||||
import AccountsListPage from '../../../_components/AccountsListPage.html'
|
||||
|
@ -8,8 +8,8 @@
|
|||
|
||||
export default {
|
||||
computed: {
|
||||
accountId: params => params.accountId,
|
||||
accountsFetcher: ($currentInstance, $accessToken, accountId) => () => getFollows($currentInstance, $accessToken, accountId)
|
||||
accountId: ({ params }) => params.accountId,
|
||||
accountsFetcher: ({ $currentInstance, $accessToken, accountId }) => () => getFollows($currentInstance, $accessToken, accountId)
|
||||
},
|
||||
store: () => store,
|
||||
components: {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<DynamicPageBanner title="Blocked users" icon="#fa-ban" />
|
||||
<AccountsListPage :accountsFetcher :accountActions />
|
||||
<AccountsListPage {accountsFetcher} {accountActions} />
|
||||
<script>
|
||||
import AccountsListPage from '.././_components/AccountsListPage.html'
|
||||
import { store } from '.././_store/store'
|
||||
|
@ -18,7 +18,7 @@
|
|||
]
|
||||
}),
|
||||
computed: {
|
||||
accountsFetcher: ($currentInstance, $accessToken) => () => getBlockedAccounts($currentInstance, $accessToken)
|
||||
accountsFetcher: ({ $currentInstance, $accessToken }) => () => getBlockedAccounts($currentInstance, $accessToken)
|
||||
},
|
||||
store: () => store,
|
||||
components: {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{{#if $isUserLoggedIn}}
|
||||
{#if $isUserLoggedIn}
|
||||
<div class="community-page">
|
||||
|
||||
<h2 class="community-header">
|
||||
|
@ -23,35 +23,35 @@
|
|||
/>
|
||||
</PageList>
|
||||
|
||||
{{#if $lists.length}}
|
||||
{#if $lists.length}
|
||||
|
||||
<h2 class="community-header">
|
||||
Lists
|
||||
</h2>
|
||||
|
||||
<PageList label="Lists">
|
||||
{{#each $lists as list}}
|
||||
<PageListItem href="/lists/{{list.id}}"
|
||||
label={{list.title}}
|
||||
{#each $lists as list}
|
||||
<PageListItem href="/lists/{list.id}"
|
||||
label={list.title}
|
||||
icon="#fa-bars"
|
||||
pinnable="true"
|
||||
/>
|
||||
{{/each}}
|
||||
{/each}
|
||||
</PageList>
|
||||
|
||||
{{/if}}
|
||||
{/if}
|
||||
|
||||
<h2 class="community-header">
|
||||
Instance settings
|
||||
</h2>
|
||||
|
||||
<PageList label="Instance settings">
|
||||
{{#if isLockedAccount}}
|
||||
{#if isLockedAccount}
|
||||
<PageListItem href="/requests"
|
||||
label="Follow requests"
|
||||
icon="#fa-user-plus"
|
||||
/>
|
||||
{{/if}}
|
||||
{/if}
|
||||
<PageListItem href="/muted"
|
||||
label="Muted users"
|
||||
icon="#fa-volume-off"
|
||||
|
@ -67,7 +67,7 @@
|
|||
</PageList>
|
||||
|
||||
</div>
|
||||
{{else}}
|
||||
{:else}
|
||||
<HiddenFromSSR>
|
||||
<FreeTextLayout>
|
||||
<h1>Community</h1>
|
||||
|
@ -75,7 +75,7 @@
|
|||
<p>Community options appear here when logged in.</p>
|
||||
</FreeTextLayout>
|
||||
</HiddenFromSSR>
|
||||
{{/if}}
|
||||
{/if}
|
||||
<style>
|
||||
.community-page {
|
||||
margin: 20px;
|
||||
|
@ -109,7 +109,7 @@
|
|||
PageListItem
|
||||
},
|
||||
computed: {
|
||||
isLockedAccount: ($currentVerifyCredentials) => $currentVerifyCredentials && $currentVerifyCredentials.locked
|
||||
isLockedAccount: ({ $currentVerifyCredentials }) => $currentVerifyCredentials && $currentVerifyCredentials.locked
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -1,10 +1,10 @@
|
|||
{{#if $isUserLoggedIn}}
|
||||
{#if $isUserLoggedIn}
|
||||
<TimelinePage timeline="favorites">
|
||||
{{#if $pinnedPage !== '/favorites'}}
|
||||
{#if $pinnedPage !== '/favorites'}
|
||||
<DynamicPageBanner title="Favorites" icon="#fa-star"/>
|
||||
{{/if}}
|
||||
{/if}
|
||||
</TimelinePage>
|
||||
{{else}}
|
||||
{:else}
|
||||
<HiddenFromSSR>
|
||||
<FreeTextLayout>
|
||||
<h1>Favorites</h1>
|
||||
|
@ -12,7 +12,7 @@
|
|||
<p>Your favorites will appear here when logged in.</p>
|
||||
</FreeTextLayout>
|
||||
</HiddenFromSSR>
|
||||
{{/if}}
|
||||
{/if}
|
||||
<script>
|
||||
import TimelinePage from '.././_components/TimelinePage.html'
|
||||
import FreeTextLayout from '.././_components/FreeTextLayout.html'
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
{{#if $isUserLoggedIn}}
|
||||
{#if $isUserLoggedIn}
|
||||
<TimelinePage timeline="federated">
|
||||
{{#if $pinnedPage !== '/federated'}}
|
||||
{#if $pinnedPage !== '/federated'}
|
||||
<DynamicPageBanner title="Federated Timeline" icon="#fa-globe"/>
|
||||
{{/if}}
|
||||
{/if}
|
||||
</TimelinePage>
|
||||
{{else}}
|
||||
{:else}
|
||||
<HiddenFromSSR>
|
||||
<FreeTextLayout>
|
||||
<h1>Federated</h1>
|
||||
|
@ -12,7 +12,7 @@
|
|||
<p>Your federated timeline will appear here when logged in.</p>
|
||||
</FreeTextLayout>
|
||||
</HiddenFromSSR>
|
||||
{{/if}}
|
||||
{/if}
|
||||
<script>
|
||||
import TimelinePage from '.././_components/TimelinePage.html'
|
||||
import FreeTextLayout from '.././_components/FreeTextLayout.html'
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
{{#if $isUserLoggedIn}}
|
||||
{#if $isUserLoggedIn}
|
||||
<TimelineHomePage/>
|
||||
{{else}}
|
||||
{:else}
|
||||
<NotLoggedInHome/>
|
||||
{{/if}}
|
||||
{/if}
|
||||
<script>
|
||||
import NotLoggedInHome from '.././_components/NotLoggedInHome.html'
|
||||
import { store } from '.././_store/store.js'
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue