mvp for notifications

This commit is contained in:
Nolan Lawson 2018-02-04 10:05:01 -08:00
parent e19b60b9d2
commit 73ba72d58a
8 changed files with 116 additions and 45 deletions

View File

@ -1,7 +1,43 @@
<article class="notification-article"
tabindex="0"
aria-posinset="{{index}}" aria-setsize="{{length}}"
on:recalculateHeight
>
Notification
</article>
{{#if notification.type === 'mention' || notification.type === 'reblog' || notification.type === 'favourite'}}
<Status :index :length :timelineType :timelineValue
status="{{notification.status}}"
:notification
on:recalculateHeight
/>
{{else}}
<article class="notification-article"
tabindex="0"
aria-posinset="{{index}}" aria-setsize="{{length}}"
>
<div class="follow-notification-offset">
<StatusHeader :status :notification />
</div>
</article>
{{/if}}
<style>
.notification-article {
width: 560px;
max-width: calc(100vw - 40px);
padding: 10px 20px;
border-bottom: 1px solid var(--main-border);
}
.follow-notification-offset {
margin-left: 58px; /* offset for avatar, 48px + 10px */
}
@media (max-width: 767px) {
.notification-article {
padding: 10px 10px;
max-width: calc(100vw - 20px);
}
}
</style>
<script>
import Status from '../status/Status.html'
import StatusHeader from '../status/StatusHeader.html'
export default {
components: {
Status,
StatusHeader
}
}
</script>

View File

@ -3,7 +3,7 @@
<PseudoVirtualListLazyItem
component="{{component}}"
index="{{i}}"
length="{{items.length}}"
length="{{wrappedItems.length}}"
makeProps="{{makeProps}}"
key="{{wrappedItem.item}}"
intersectionObserver="{{intersectionObserver}}"

View File

@ -7,7 +7,7 @@
<:Component {component}
virtualProps="{{props}}"
virtualIndex="{{index}}"
virtualLength="{length}}"
virtualLength="{{length}}"
/>
{{/if}}
</div>

View File

@ -3,6 +3,7 @@
:props
:key
:index
:length
:scrollToThisItem
:intersectionObserver
:isIntersecting

View File

@ -2,16 +2,8 @@
tabindex="0"
aria-posinset="{{index}}" aria-setsize="{{length}}"
on:recalculateHeight>
{{#if status.reblog}}
<div class="status-boosted">
<svg>
<use xlink:href="#fa-retweet" />
</svg>
<span>
<a href="/accounts/{{status.account.id}}">{{status.account.username}}</a>
boosted
</span>
</div>
{{#if (notification && (notification.type === 'reblog' || notification.type === 'favourite')) || status.reblog}}
<StatusHeader :notification :status />
{{/if}}
<div class="status-author">
<a class="status-author-name" href="/accounts/{{originalAccount.id}}">
@ -80,9 +72,10 @@
width: 560px;
max-width: calc(100vw - 40px);
padding: 10px 20px;
border-bottom: 1px solid var(--main-border);
display: grid;
grid-template-areas:
".............. status-boosted"
".............. status-header"
"status-sidebar status-author"
"status-sidebar status-spoiler"
"status-sidebar status-spoiler-button"
@ -90,7 +83,6 @@
"status-media status-media"
".............. status-toolbar";
grid-template-columns: 58px 1fr;
border-bottom: 1px solid var(--main-border);
}
.status-article.status-direct {
@ -200,27 +192,6 @@
margin: 0;
}
.status-boosted span {
margin-left: 5px;
}
:global(.status-boosted span, .status-boosted a, .status-boosted a:visited, .status-boosted a:hover) {
color: var(--deemphasized-text-color);
}
.status-boosted {
grid-area: status-boosted;
margin: 5px 10px 5px 5px;
display: flex;
align-items: center;
}
.status-boosted svg {
width: 18px;
height: 18px;
fill: var(--deemphasized-text-color);
}
.status-sensitive-media-container {
grid-area: status-media;
margin: 10px 0;
@ -315,6 +286,7 @@
import Avatar from './Avatar.html'
import Media from './Media.html'
import Toolbar from './Toolbar.html'
import StatusHeader from './StatusHeader.html'
import { mark, stop } from '../../_utils/marks'
import IntlRelativeFormat from 'intl-relativeformat'
import { replaceAll } from '../../_utils/strings'
@ -331,7 +303,8 @@
Avatar,
Media,
Toolbar,
ExternalLink
ExternalLink,
StatusHeader
},
store: () => store,
computed: {

View File

@ -0,0 +1,61 @@
<div class="status-header">
<svg>
<use xlink:href="{{getIcon(notification, status)}}"/>
</svg>
<span>
<a href="/accounts/{{getAccount(notification, status).id}}">
{{getAccount(notification, status).display_name || ('@' + getAccount(notification, status).username)}}
</a>
{{#if notification && notification.type === 'reblog'}}
boosted your status
{{elseif notification && notification.type === 'favourite'}}
favorited your status
{{elseif notification && notification.type === 'follow'}}
followed you
{{elseif status && status.reblog}}
boosted
{{/if}}
</span>
</div>
<style>
.status-header span {
margin-left: 5px;
}
:global(.status-header span, .status-header a, .status-header a:visited, .status-header a:hover) {
color: var(--deemphasized-text-color);
}
.status-header {
grid-area: status-header;
margin: 5px 10px 5px 5px;
display: flex;
align-items: center;
}
.status-header svg {
width: 18px;
height: 18px;
fill: var(--deemphasized-text-color);
}
</style>
<script>
export default {
helpers: {
getIcon(notification, status) {
if ((notification && notification.type === 'reblog') || (status && status.reblog)) {
return '#fa-retweet'
} else if (notification && notification.type === 'follow') {
return '#fa-user-plus'
}
return '#fa-star'
},
getAccount(notification, status) {
if (notification && notification.account) {
return notification.account
}
return status.account
}
}
}
</script>

View File

@ -5,7 +5,7 @@
<:Component {component}
virtualProps="{{props}}"
virtualIndex="{{index}}"
virtualLength="{{numItems}}"
virtualLength="{{$length}}"
on:recalculateHeight="doRecalculateHeight()"/>
</div>
<style>

View File

@ -72,7 +72,7 @@ virtualListStore.compute('height',
return showFooter ? (heightWithoutFooter + footerHeight) : heightWithoutFooter
})
virtualListStore.compute('numItems', ['items'], (items) => items.length)
virtualListStore.compute('length', ['items'], (items) => items ? items.length : 0)
virtualListStore.compute('allVisibleItemsHaveHeight',
['visibleItems', 'itemHeights'],