Lazy load items

This commit is contained in:
Marcus Noble 2020-10-17 20:52:23 +01:00
parent eb38440ee4
commit 9b56b3a5f6
3 changed files with 67 additions and 20 deletions

View File

@ -36,7 +36,7 @@
<div class="feeds"> <div class="feeds">
<div :class="{ strong: items.length, alert: true, 'alert-success': selectedFeed == ''}" v-on:click="loadFeed('')"> <div :class="{ strong: items.length, alert: true, 'alert-success': selectedFeed == ''}" v-on:click="loadFeed('')">
All ({{items.length}}) All ({{unread}})
</div> </div>
<div v-for="feed in feeds" :class="{strong: unreadCount(feed), 'alert': true, 'alert-success': selectedFeed == feed.FeedURL }" :data-feed="feed.FeedURL" v-on:click="loadFeed(feed.ID)"> <div v-for="feed in feeds" :class="{strong: unreadCount(feed), 'alert': true, 'alert-success': selectedFeed == feed.FeedURL }" :data-feed="feed.FeedURL" v-on:click="loadFeed(feed.ID)">
@ -81,9 +81,8 @@
<span class="date" :title="item.Created">{{item.Created}}</span> <span class="date" :title="item.Created">{{item.Created}}</span>
<h3 class="item-title"><a :href="item.URL">{{item.Title}}</a></h3> <h3 class="item-title"><a :href="item.URL">{{item.Title}}</a></h3>
</div> </div>
<div class="card item-content" :data-id="item.ID" v-show="item.ID == selectedItem"> <div class="card item-content" :data-id="item.ID" v-if="item.ID == selectedItem">
<div class="card-content"> <div class="card-content">
<div class="loading"></div>
<feed-item :item-id="item.ID" :class="{ dark: isDark }"></feed-item> <feed-item :item-id="item.ID" :class="{ dark: isDark }"></feed-item>
</div> </div>
</div> </div>
@ -119,6 +118,9 @@
} else { } else {
return this.items.filter(item => item.FeedID === this.selectedFeed); return this.items.filter(item => item.FeedID === this.selectedFeed);
} }
},
unread() {
return this.items.filter(item => !item.Read).length;
} }
}, },
methods: { methods: {
@ -143,8 +145,8 @@
this.selectedItem = undefined; this.selectedItem = undefined;
} else { } else {
this.selectedItem = item.ID; this.selectedItem = item.ID;
let feedItem = document.querySelector('feed-item[item-id="'+item.ID+'"]');
feedItem.load().then(() => feedItem.parentElement.querySelector('.loading').remove()); // document.querySelector(`feed-item[data-id='${item.ID}']`).content = item.Content || item.Description;
document.getElementById(this.selectedItem).scrollIntoView(); document.getElementById(this.selectedItem).scrollIntoView();
item.Read = true; item.Read = true;
fetch(`/api/read/${item.ID}`, {method: "POST"}) fetch(`/api/read/${item.ID}`, {method: "POST"})

View File

@ -5,10 +5,18 @@ class FeedItem extends HTMLElement {
this.attachShadow({mode: 'open'}); this.attachShadow({mode: 'open'});
} }
load() { connectedCallback() {
const template = document.createElement('template'); const template = document.createElement('template');
template.innerHTML = ` template.innerHTML = `
<style> <style>
@font-face {
font-family: "charter";
src: url("https://glyph.medium.com/font/be78681/0-3j_4g_6bu_6c4_6c8_6c9_6cc_6cd_6ci_6cm/charter-400-normal.woff") format("woff");
font-style: normal;
font-weight: 400;
unicode-range: U+0-7F, U+A0, U+200A, U+2014, U+2018, U+2019, U+201C, U+201D, U+2022, U+2026;
}
:host { :host {
width: 100% !important; width: 100% !important;
overflow: scroll !important; overflow: scroll !important;
@ -25,11 +33,12 @@ class FeedItem extends HTMLElement {
margin: auto auto !important; margin: auto auto !important;
} }
p { p {
font-family: 'Roboto', sans-serif; font-family: charter, Georgia, "Times New Roman", Times, serif;
font-size: 14px; font-size: 21px;
line-height: 20px; font-style: normal;
letter-spacing: 0em; font-weight: 400;
font-weight: 500; letter-spacing: -0.063px;
line-height: 32px
} }
a { a {
color: #333; color: #333;
@ -42,15 +51,13 @@ class FeedItem extends HTMLElement {
</style> </style>
`; `;
if (!this.loaded) { fetch(`/api/item/${this.getAttribute('item-id')}`)
return fetch(`/api/item/${this.getAttribute('item-id')}`)
.then(res => res.json()) .then(res => res.json())
.then(item => { .then(item => {
template.innerHTML += item.Content || item.Description; template.innerHTML += item.Content || item.Description;
this.shadowRoot.appendChild(template.content.cloneNode(true)); this.shadowRoot.appendChild(template.content.cloneNode(true));
}) })
.then(() => this.loaded = true);
}
} }
} }
customElements.define('feed-item', FeedItem); customElements.define('feed-item', FeedItem);

View File

@ -118,3 +118,41 @@
.dark { .dark {
background: #333; background: #333;
} }
.item-content .card-content {
all: unset;
width: 100% !important;
overflow: scroll !important;
overflow-x: auto !important;
}
.item-content .card-content * {
max-width: 100% !important;
height: auto !important;
}
.item-content .card-content table {
width: 100% !important;
}
.item-content .card-content img {
margin: auto auto !important;
}
.item-content .card-content p {
font-family: 'Roboto', sans-serif;
font-size: 14px;
line-height: 20px;
letter-spacing: 0em;
font-weight: 500;
}
.item-content .card-content a {
color: #333;
font-weight: bold;
}
.dark .item-content .card-content a {
color: #ccc;
}