forked from cybrespace/pinafore
mvp for notifications
This commit is contained in:
parent
e19b60b9d2
commit
73ba72d58a
|
@ -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>
|
|
@ -3,7 +3,7 @@
|
|||
<PseudoVirtualListLazyItem
|
||||
component="{{component}}"
|
||||
index="{{i}}"
|
||||
length="{{items.length}}"
|
||||
length="{{wrappedItems.length}}"
|
||||
makeProps="{{makeProps}}"
|
||||
key="{{wrappedItem.item}}"
|
||||
intersectionObserver="{{intersectionObserver}}"
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<:Component {component}
|
||||
virtualProps="{{props}}"
|
||||
virtualIndex="{{index}}"
|
||||
virtualLength="{length}}"
|
||||
virtualLength="{{length}}"
|
||||
/>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
:props
|
||||
:key
|
||||
:index
|
||||
:length
|
||||
:scrollToThisItem
|
||||
:intersectionObserver
|
||||
:isIntersecting
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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>
|
|
@ -5,7 +5,7 @@
|
|||
<:Component {component}
|
||||
virtualProps="{{props}}"
|
||||
virtualIndex="{{index}}"
|
||||
virtualLength="{{numItems}}"
|
||||
virtualLength="{{$length}}"
|
||||
on:recalculateHeight="doRecalculateHeight()"/>
|
||||
</div>
|
||||
<style>
|
||||
|
|
|
@ -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'],
|
||||
|
|
Loading…
Reference in New Issue