poll for package updates and sync tea cli (#473)

This commit is contained in:
ABevier 2023-04-18 21:18:48 -04:00 committed by GitHub
parent d2b5f03ba5
commit 5be042ce67
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 101 additions and 40 deletions

View file

@ -1,12 +1,10 @@
import { spawn, exec } from "child_process";
import { clean } from "semver";
import { getGuiPath } from "./tea-dir";
import fs from "fs";
import path from "path";
import initializeTeaCli from "./initialize";
import * as log from "electron-log";
import { subscribeToPackageTopic } from "./push-notification";
const destinationDirectory = getGuiPath();
@ -97,3 +95,11 @@ export async function asyncExec(cmd: string): Promise<string> {
});
});
}
export async function syncPantry() {
const teaVersion = await initializeTeaCli();
if (!teaVersion) throw new Error("no tea");
log.info("Syncing pantry");
await asyncExec(`cd '${destinationDirectory}' && ./tea -S`);
}

View file

@ -8,7 +8,7 @@ import { post } from "./v1-client";
import { deepReadDir, deletePackageFolder } from "./tea-dir";
import path from "path";
import { installPackage, openTerminal } from "./cli";
import { installPackage, openTerminal, syncPantry } from "./cli";
import initializeTeaCli from "./initialize";
@ -67,6 +67,15 @@ export default function initializeHandlers() {
}
});
ipcMain.handle("sync-pantry", async () => {
try {
return await syncPantry();
} catch (error) {
log.error(error);
return error;
}
});
ipcMain.handle("open-terminal", async (_, data) => {
const { cmd } = data as { cmd: string };
try {

View file

@ -91,6 +91,13 @@ export async function installPackage(pkg: GUIPackage, version?: string) {
await installPackageCommand(pkg.full_name + (specificVersion ? `@${specificVersion}` : ""));
}
export async function syncPantry() {
const res = await ipcRenderer.invoke("sync-pantry");
if (res instanceof Error) {
throw res;
}
}
export async function getTopPackages(): Promise<GUIPackage[]> {
const packages = await mock.getTopPackages();
return packages;

View file

@ -240,6 +240,11 @@ export async function installPackage(pkg: GUIPackage, version?: string) {
await delay(10000);
}
export async function syncPantry() {
console.log("syncing pantry");
await delay(1000);
}
function delay(ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms));
}

View file

@ -11,7 +11,8 @@ import {
getPackageBottles,
setBadgeCount,
loadPackageCache,
writePackageCache
writePackageCache,
syncPantry
} from "@native";
import { getReadme, getContributors, getRepoAsPackage } from "$libs/github";
@ -21,11 +22,16 @@ import { addInstalledVersion } from "$libs/packages/pkg-utils";
import withDebounce from "$libs/utils/debounce";
import { trimGithubSlug } from "$libs/github";
import { notificationStore } from "$libs/stores";
import withRetry from "$libs/utils/retry";
const log = window.require("electron-log");
const packageRefreshInterval = 1000 * 60 * 60; // 1 hour
export default function initPackagesStore() {
let initialized = false;
let isDestroyed = false;
let refreshTimeoutId: ReturnType<typeof setTimeout> | null = null;
const syncProgress = writable<number>(0); // TODO: maybe use this in the UI someday
@ -93,46 +99,69 @@ To read more about this package go to [${guiPkg.homepage}](${guiPkg.homepage}).
log.info(`Loaded ${Object.keys(cachedPkgs.packages).length} packages from cache`);
packageMap.set(cachedPkgs);
log.info("packages store: initializing...");
await refreshPackages();
initialized = true;
const pkgs = await getDistPackages();
const guiPkgs: GUIPackage[] = pkgs.map((p) => ({
...p,
state: PackageStates.AVAILABLE
}));
}
log.info("packages store: initialized!");
};
const refreshPackages = async () => {
if (isDestroyed) return;
log.info("packages store: refreshing...");
const pkgs = await getDistPackages();
const guiPkgs: GUIPackage[] = pkgs.map((p) => ({
...p,
state: PackageStates.AVAILABLE
}));
if (!initialized) {
// set packages data so that i can render something in the UI already
updateAllPackages(guiPkgs);
log.info("initialized packages store with ", guiPkgs.length);
packagesIndex = new Fuse(guiPkgs, {
keys: ["name", "full_name", "desc", "categories"]
});
log.info("initialized packages fuse index");
try {
const installedPkgs: InstalledPackage[] = await getInstalledPackages();
log.info("set NEEDS_UPDATE state to pkgs");
for (const [i, iPkg] of installedPkgs.entries()) {
const pkg = guiPkgs.find((p) => p.full_name === iPkg.full_name);
if (pkg) {
const isUpdated = pkg.version === iPkg.installed_versions[0];
updatePackage(pkg.full_name, {
installed_versions: iPkg.installed_versions,
state: isUpdated ? PackageStates.INSTALLED : PackageStates.NEEDS_UPDATE
});
}
syncProgress.set(+((i + 1) / installedPkgs.length).toFixed(2));
}
// TODO: I think this can just get deleted, updatePackage should be enough
//setBadgeCountFromPkgs(guiPkgs);
} catch (error) {
log.error(error);
}
}
log.info("packages store: initialized!");
packagesIndex = new Fuse(guiPkgs, {
keys: ["name", "full_name", "desc", "categories"]
});
log.info("refreshed packages fuse index");
try {
const installedPkgs: InstalledPackage[] = await getInstalledPackages();
log.info("set NEEDS_UPDATE state to pkgs");
for (const [i, iPkg] of installedPkgs.entries()) {
const pkg = guiPkgs.find((p) => p.full_name === iPkg.full_name);
if (pkg) {
const isUpdated = pkg.version === iPkg.installed_versions[0];
updatePackage(pkg.full_name, {
installed_versions: iPkg.installed_versions,
state: isUpdated ? PackageStates.INSTALLED : PackageStates.NEEDS_UPDATE
});
}
syncProgress.set(+((i + 1) / installedPkgs.length).toFixed(2));
}
} catch (error) {
log.error(error);
}
try {
await withRetry(syncPantry);
} catch (err) {
log.error(err);
}
refreshTimeoutId = setTimeout(() => refreshPackages(), packageRefreshInterval); // refresh every hour
};
// Destructor for the package store
const destroy = () => {
isDestroyed = true;
if (refreshTimeoutId) {
clearTimeout(refreshTimeoutId);
}
log.info("packages store: destroyed");
};
const installPkg = async (pkg: GUIPackage, version?: string) => {
@ -237,7 +266,8 @@ To read more about this package go to [${guiPkg.homepage}](${guiPkg.homepage}).
installPkg,
uninstallPkg,
syncPackageData,
deletePkg
deletePkg,
destroy
};
}

View file

@ -12,7 +12,7 @@
import SearchPopupResults from "$components/search-popup-results/search-popup-results.svelte";
import { getProtocolPath } from "@native";
import { onMount } from "svelte";
import { onDestroy, onMount } from "svelte";
let view: HTMLElement;
@ -51,6 +51,10 @@
});
packagesStore.init();
});
onDestroy(() => {
packagesStore.destroy();
});
</script>
<div id="main-layout" class="font-inter border-gray rounded-xl border transition-all">