169 lines
7.0 KiB
Svelte
169 lines
7.0 KiB
Svelte
<script lang="ts">
|
|
import { page } from '$app/state'
|
|
import { modals } from 'svelte-modals'
|
|
import { slide } from 'svelte/transition'
|
|
import { cubicOut } from 'svelte/easing'
|
|
import ConfirmDialog from '$lib/components/ConfirmDialog.svelte'
|
|
import Spinner from '$lib/components/Spinner.svelte'
|
|
import SettingsCard from '$lib/components/SettingsCard.svelte'
|
|
|
|
import { compareVersions } from 'compare-versions'
|
|
import GithubUpdateDialog from '$lib/components/GithubUpdateDialog.svelte'
|
|
import InfoDialog from '$lib/components/InfoDialog.svelte'
|
|
import { api } from '$lib/api'
|
|
import { useFeatureFlags } from '$lib/stores'
|
|
import { Error, Cancel, Check, CloudDown, Github, Prerelease } from '$lib/components/icons'
|
|
|
|
const features = useFeatureFlags()
|
|
|
|
async function getGithubAPI() {
|
|
const headers = {
|
|
accept: 'application/vnd.github+json',
|
|
'X-GitHub-Api-Version': '2022-11-28'
|
|
}
|
|
const result = await api.get(`https://api.github.com/repos/${page.data.github}/releases`, {
|
|
headers
|
|
})
|
|
if (result.isErr()) {
|
|
console.error('Error:', result.inner)
|
|
return
|
|
}
|
|
return result.inner as {
|
|
tag_name: string
|
|
assets: Array<{ name: string; browser_download_url: string }>
|
|
}
|
|
}
|
|
|
|
async function postGithubDownload(url: string) {
|
|
const result = await api.post('/api/firmware/download', { download_url: url })
|
|
if (result.isErr()) {
|
|
console.error('Error:', result.inner)
|
|
return
|
|
}
|
|
}
|
|
|
|
function confirmGithubUpdate(assets: Array<{ name: string; browser_download_url: string }>) {
|
|
let url = ''
|
|
// iterate over assets and find the correct one
|
|
for (let i = 0; i < assets.length; i++) {
|
|
// check if the asset is of type *.bin
|
|
if (
|
|
assets[i].name.includes('.bin') &&
|
|
assets[i].name.includes($features.firmware_built_target)
|
|
) {
|
|
url = assets[i].browser_download_url
|
|
}
|
|
}
|
|
if (url === '') {
|
|
// if no asset was found, use the first one
|
|
modals.open(InfoDialog, {
|
|
title: 'No matching firmware found',
|
|
message:
|
|
'No matching firmware was found for the current device. Upload the firmware manually or build from sources.',
|
|
dismiss: { label: 'OK', icon: Check },
|
|
onDismiss: () => modals.close()
|
|
})
|
|
return
|
|
}
|
|
|
|
modals.open(ConfirmDialog, {
|
|
title: 'Confirm flashing new firmware to the device',
|
|
message: 'Are you sure you want to overwrite the existing firmware with a new one?',
|
|
labels: {
|
|
cancel: { label: 'Abort', icon: Cancel },
|
|
confirm: { label: 'Update', icon: CloudDown }
|
|
},
|
|
onConfirm: () => {
|
|
postGithubDownload(url)
|
|
modals.open(GithubUpdateDialog, {
|
|
onConfirm: () => modals.closeAll()
|
|
})
|
|
}
|
|
})
|
|
}
|
|
</script>
|
|
|
|
<SettingsCard collapsible={false}>
|
|
{#snippet icon()}
|
|
<Github class="lex-shrink-0 mr-2 h-6 w-6 self-end rounded-full" />
|
|
{/snippet}
|
|
{#snippet title()}
|
|
<span>Github Firmware Manager</span>
|
|
{/snippet}
|
|
{#await getGithubAPI()}
|
|
<Spinner />
|
|
{:then githubReleases}
|
|
<div class="relative w-full overflow-visible">
|
|
<div
|
|
class="overflow-x-auto"
|
|
transition:slide|local={{ duration: 300, easing: cubicOut }}
|
|
>
|
|
<table class="table w-full table-auto">
|
|
<thead>
|
|
<tr class="font-bold">
|
|
<th align="left">Release</th>
|
|
<th align="center" class="hidden sm:block">Release Date</th>
|
|
<th align="center">Experimental</th>
|
|
<th align="center">Install</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{#each githubReleases as release}
|
|
<tr
|
|
class={(
|
|
compareVersions(
|
|
$features.firmware_version as string,
|
|
release.tag_name
|
|
) === 0
|
|
) ?
|
|
'bg-primary text-primary-content'
|
|
: 'bg-base-100 h-14'}
|
|
>
|
|
<td align="left" class="text-base font-semibold">
|
|
<a
|
|
href={release.html_url}
|
|
class="link link-hover"
|
|
target="_blank"
|
|
rel="noopener noreferrer">{release.name}</a
|
|
></td
|
|
>
|
|
<td align="center" class="hidden min-h-full align-middle sm:block">
|
|
<div class="my-2">
|
|
{new Intl.DateTimeFormat('en-GB', {
|
|
dateStyle: 'medium'
|
|
}).format(new Date(release.published_at))}
|
|
</div>
|
|
</td>
|
|
<td align="center">
|
|
{#if release.prerelease}
|
|
<Prerelease class="text-accent h-5 w-5" />
|
|
{/if}
|
|
</td>
|
|
<td align="center">
|
|
{#if compareVersions($features.firmware_version as string, release.tag_name) != 0}
|
|
<button
|
|
class="btn btn-ghost btn-circle btn-sm"
|
|
onclick={() => {
|
|
confirmGithubUpdate(release.assets)
|
|
}}
|
|
>
|
|
<CloudDown class="text-secondary h-6 w-6" />
|
|
</button>
|
|
{/if}
|
|
</td>
|
|
</tr>
|
|
{/each}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
{:catch}
|
|
<div class="alert alert-error shadow-lg">
|
|
<Error class="h-6 w-6 shrink-0" />
|
|
<span
|
|
>Please connect to a network with internet access to perform a firmware update.</span
|
|
>
|
|
</div>
|
|
{/await}
|
|
</SettingsCard>
|