Skip to content

Commit

Permalink
Handle source data breaking channel references, optimize update loop …
Browse files Browse the repository at this point in the history
…while idle (should hopefully not overload tab after long idle tab elsewhere)
  • Loading branch information
Skovvart committed Jun 8, 2021
1 parent 9a2a649 commit 84a2f7b
Showing 1 changed file with 30 additions and 5 deletions.
35 changes: 30 additions & 5 deletions src/state.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Writable } from "svelte/store";
import type { Channel, ChannelProgram, Show } from "./api";
import { writable, readable, derived } from "svelte/store";
import { get, writable, readable, derived } from "svelte/store";
import dayjs from "dayjs";
import { getUserChannels, saveUserChannels, getCachedChannels, getCachedPrograms, cacheChannels, cachePrograms } from "./persistence";

Expand All @@ -11,10 +11,23 @@ programs.subscribe(cachePrograms)

export const filterCategories = writable([]);


// Update loop based on "JavaScript counters the hard way - HTTP 203" https://youtu.be/MCi6AZMkxcU?t=1219
// Accurate over time (not important here, but sure), update visually steadily (not important here, but sure), avoids running in background (yes, important), otherwise good CPU usage (sure, nice, was not too worried with previous implementation though)
const now = readable(new Date(), set => {
const interval = setInterval(() => {
set(new Date());
}, 5 * 1000);
const start = document.timeline.currentTime;
let interval;
const frame = time => {
const elapsed = time - start;
const seconds = Math.round(elapsed / 1000);
set(new Date()); // call set function instead of update UI, update every 5 seconds instead of every one
const targetNext = (seconds + 5) * 1000 + start;
interval = setTimeout(
() => requestAnimationFrame(frame),
targetNext - performance.now()
);
};
frame(start);
return () => {
clearInterval(interval);
};
Expand All @@ -30,4 +43,16 @@ userChannels.subscribe(saveUserChannels)

// We want to cache promises by channelId + showId, that can be shared for identical descriptions, but only show descriptions by explicit reference (so the shared descriptions don't open up at the same time when one is clicked)
export const descriptionPromises = writable({});
export const shownDescription: Writable<{ channel: Channel, show: Show } | null> = writable(null);
export const shownDescription: Writable<{ channel: Channel, show: Show } | null> = writable(null);

// Try to filter out broken userChannel references, for when source data removes them (for whatever reason...)
const userChannelsSnapShot = get(userChannels);
channels.subscribe(updatedChannelsValue => {
if (updatedChannelsValue.length) {
const channelsIds = updatedChannelsValue.map(c => c.id);
const invalidChannels = userChannelsSnapShot.filter(uc => channelsIds.indexOf(uc) == -1);
if (invalidChannels.length) {
userChannels.update(currentUserChannels => currentUserChannels.filter(cuc => invalidChannels.indexOf(cuc) == -1));
}
}
});

0 comments on commit 84a2f7b

Please sign in to comment.