Skip to content

Commit

Permalink
Configurable feed refresh frequency
Browse files Browse the repository at this point in the history
  • Loading branch information
breadthe committed Feb 9, 2023
1 parent 10e5e73 commit 8cf1bd4
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 62 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# Changelog

## 0.3.0
### Features
* Settings.
* Refresh the feed every 60s by default.
* Configurable feed refresh frequency.
* Support for theming (not yet functional).
### Fixes
* Format the magnitude consistently to 1 decimal.

## 0.2.0
### Features
* Fetch the feed on startup.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Note that I may not implement all of these.

- <label><input type="checkbox" checked />Fetch the feed on startup.</label>
- <label><input type="checkbox" checked />Fetch the feed periodically (60s).</label>
- <label><input type="checkbox" />Configurable fetch frequency.</label>
- <label><input type="checkbox" checked />Configurable feed refresh frequency.</label>
- <label><input type="checkbox" />Desktop notifications for significant events.</label>
- <label><input type="checkbox" />Configurable notification threshold.</label>
- <label><input type="checkbox" />Dark mode.</label>
Expand Down
40 changes: 15 additions & 25 deletions src/Main.svelte
Original file line number Diff line number Diff line change
@@ -1,39 +1,29 @@
<script lang="ts">
import appLogo from './assets/128x128@2x.png'
import { onMount } from 'svelte'
import { feedDownloadError, fetchingFeed, feedData, lastFetchedAt } from './store'
import { tooltip } from './tooltip'
import { fetchFeed } from './feed'
import { round1, diffForHumans, timestampToLocalString } from './utils'
import SettingsButton from './lib/SettingsButton.svelte'
async function refreshData() {
fetchingFeed.set(true)
await fetchFeed()
setTimeout(() => {
fetchingFeed.set(false)
}, 1000)
}
import appLogo from "./assets/128x128@2x.png"
import { onMount } from "svelte"
import { feedDownloadError, fetchingFeed, feedData, refreshInterval, refreshIntervalTimer } from "./store"
import { tooltip } from "./tooltip"
import { refreshFeed, startFeedRefreshInterval } from "./feed"
import { round1, timestampToLocalString } from "./utils"
import SettingsButton from "./lib/SettingsButton.svelte"
onMount(async () => {
await refreshData()
await refreshFeed()
const interval = setInterval(async () => {
await refreshData()
}, 1000 * 60) // 60 seconds
startFeedRefreshInterval($refreshInterval)
return () => {
clearInterval(interval)
clearInterval($refreshIntervalTimer)
}
})
</script>

<main class="w-full overflow-hide">
<header class="sticky top-0 z-10 bg-gray-100">
<div class="flex items-center justify-between gap-4 p-2 ">
<div class="flex items-center justify-between gap-4 px-4 py-2">
<button
on:click={refreshData}
use:tooltip={{ theme: 'dark-border' }}
on:click={refreshFeed}
use:tooltip={{ theme: "dark-border" }}
title="Click to refresh"
class="flex items-center gap-1 text-xl font-extrabold bg-gradient-to-br from-blue-600 to-indigo-800 hover:opacity-90 bg-clip-text text-transparent"
>
Expand All @@ -56,14 +46,14 @@
<SettingsButton />
</div>

{#if $feedData && $feedData.type === 'FeatureCollection'}
{#if $feedData && $feedData.type === "FeatureCollection"}
<div class="w-full bg-white p-2 text-sm border-b">
{$feedData.metadata.title} - <small class="font-bold text-xs">{$feedData.metadata.count}</small> events
</div>
{/if}
</header>

{#if $feedData && $feedData.type === 'FeatureCollection'}
{#if $feedData && $feedData.type === "FeatureCollection"}
<div class="w-full h-full min-h-screen bg-white">
{#each $feedData.features as feature}
<div class="flex items-center justify-between border-b hover:bg-gray-100 p-2">
Expand Down
63 changes: 33 additions & 30 deletions src/Settings.svelte
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
<script lang="ts">
import {
feedDownloadError,
fetchingFeed,
feedData,
lastFetchedAt,
activeSection,
theme,
refreshInterval,
} from "./store"
import { activeSection, theme, DEFAULT_REFRESH_INTERVAL, refreshInterval, refreshIntervalTimer } from "./store"
import { startFeedRefreshInterval } from "./feed"
import { tooltip } from "./tooltip"
import { round1, diffForHumans, timestampToLocalString, setTheme, setIsDark } from "./utils"
import { setTheme } from "./utils"
let selectedTheme = $theme
let refreshIntervalInput: HTMLInputElement
const preferences = {
themes: [
Expand All @@ -22,39 +16,36 @@
}
function saveTheme() {
$theme = selectedTheme
theme.set(selectedTheme)
setTheme($theme)
}
function saveRefreshInterval() {
refreshInterval.set(parseInt(refreshIntervalInput.value) || DEFAULT_REFRESH_INTERVAL)
// clear the feed refresh interval and start a new one
clearInterval($refreshIntervalTimer)
startFeedRefreshInterval($refreshInterval)
}
function closeSettings() {
activeSection.set("Main")
}
</script>

<main class="w-full overflow-hide">
<header class="sticky top-0 z-10 bg-gray-100">
<div class="flex items-center justify-between gap-4 p-2 ">
<div class="flex items-center justify-between gap-4 px-4 py-2">
<button
on:click={closeSettings}
use:tooltip={{ theme: "dark-border" }}
title="Close Settings"
class="flex items-center gap-1 text-xl font-extrabold text-indigo-800"
class="text-2xl text-indigo-800 hover:opacity-90"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"><line x1="19" y1="12" x2="5" y2="12" /><polyline points="12 19 5 12 12 5" /></svg
>
&times;
</button>
<h1 class="font-extrabold text-indigo-800">
Settings
</h1>

<h1 class="font-extrabold text-indigo-800">Settings</h1>
</div>
</header>

Expand All @@ -65,7 +56,7 @@
<h2 class="font-bold text-right">Theme</h2>
</div>
<div class="w-1/2">
<select bind:value={selectedTheme} on:change={saveTheme}>
<select bind:value={selectedTheme} on:change={saveTheme} class="px-2 py-1 rounded">
{#each preferences.themes as theme}
<option value={theme.value}>{theme.label}</option>
{/each}
Expand All @@ -76,10 +67,22 @@
<!-- Feed refresh interval -->
<div class="w-full flex items-center gap-4 border-b p-2">
<div class="w-1/2">
<h2 class="font-bold text-right">Feed refresh interval</h2>
<h2 class="font-bold text-right">Feed refresh interval (s)</h2>
</div>
<div class="w-1/2">
{$refreshInterval}s
<input
type="number"
min="5"
step="1"
bind:this={refreshIntervalInput}
value={$refreshInterval}
class="w-16 border px-2 py-1 rounded"
/>
<button
on:click={saveRefreshInterval}
class="text-sm bg-gradient-to-br from-blue-600 to-indigo-800 hover:opacity-90 text-white px-2 py-1 rounded"
>Save</button
>
</div>
</div>
</section>
Expand Down
23 changes: 21 additions & 2 deletions src/feed.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { feedDownloadError, fetchingFeed, feedData, lastFetchedAt } from './store'
import { feedDownloadError, fetchingFeed, feedData, lastFetchedAt, refreshIntervalTimer } from './store'

export const fetchFeed = async function () {
const url = 'https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/2.5_day.geojson'

feedDownloadError.set('')
lastFetchedAt.set(Date.now())

try {
const response = await fetch(url)
Expand All @@ -15,8 +14,28 @@ export const fetchFeed = async function () {
feedDownloadError.set('Could not download')
return
}

lastFetchedAt.set(Date.now())
} catch (error) {
feedDownloadError.set('Network error')
console.error(error)
}
}

export const refreshFeed = async function () {
fetchingFeed.set(true)

await fetchFeed()

setTimeout(() => {
fetchingFeed.set(false)
}, 1000)
}

export const startFeedRefreshInterval = function (seconds: number) {
const interval = setInterval(async () => {
await refreshFeed()
}, 1000 * seconds)

refreshIntervalTimer.set(interval)
}
12 changes: 8 additions & 4 deletions src/store.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { writable } from 'svelte/store'
import { readable, writable } from 'svelte/store'
import type { FeatureCollection } from './types'

// Page (Main, Settings)
Expand All @@ -11,13 +11,17 @@ theme.subscribe((value: string) => {
localStorage.setItem('theme', value)
})

// Theme: dark, light, automatic
const storedRefreshInterval = localStorage.getItem('refreshInterval') || 60
export const refreshInterval = writable(storedRefreshInterval ? storedRefreshInterval : 60)
// Feed refresh interval, default 60 seconds
export const DEFAULT_REFRESH_INTERVAL = 60
const storedRefreshInterval = parseInt(localStorage.getItem('refreshInterval'), 10) || DEFAULT_REFRESH_INTERVAL
export const refreshInterval = writable<number>(storedRefreshInterval ? storedRefreshInterval : DEFAULT_REFRESH_INTERVAL)
refreshInterval.subscribe((value: number) => {
localStorage.setItem('refreshInterval', value.toString())
})

// Refresh interval timer
export const refreshIntervalTimer = writable<NodeJS.Timeout>(undefined)

export const feedDownloadError = writable('')
export const fetchingFeed = writable(false) // true when fetching feed
export const feedData = writable<FeatureCollection>(undefined)
Expand Down

0 comments on commit 8cf1bd4

Please sign in to comment.