mirror of
https://github.com/ivabus/gui
synced 2025-04-23 14:07:14 +03:00
poll for package updates and sync tea cli (#473)
This commit is contained in:
parent
d2b5f03ba5
commit
5be042ce67
6 changed files with 101 additions and 40 deletions
|
@ -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`);
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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">
|
||||
|
|
Loading…
Reference in a new issue