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" {{#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" tabindex="0"
aria-posinset="{{index}}" aria-setsize="{{length}}" aria-posinset="{{index}}" aria-setsize="{{length}}"
on:recalculateHeight >
> <div class="follow-notification-offset">
Notification <StatusHeader :status :notification />
</article> </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 <PseudoVirtualListLazyItem
component="{{component}}" component="{{component}}"
index="{{i}}" index="{{i}}"
length="{{items.length}}" length="{{wrappedItems.length}}"
makeProps="{{makeProps}}" makeProps="{{makeProps}}"
key="{{wrappedItem.item}}" key="{{wrappedItem.item}}"
intersectionObserver="{{intersectionObserver}}" intersectionObserver="{{intersectionObserver}}"

View file

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

View file

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

View file

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

View file

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