Skip to content

Commit

Permalink
feat: check for node updates. only checking part completed
Browse files Browse the repository at this point in the history
  • Loading branch information
jgresham committed Jun 21, 2024
1 parent 78b12a8 commit 25c572a
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 11 deletions.
1 change: 1 addition & 0 deletions assets/locales/en/genericComponents.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"AboutSecondsRemaining": "About {{seconds}} seconds remaining",
"CheckForUpdates": "Check for updates...",
"Confirm": "Confirm",
"FinishingUp": "Finishing up...",
"Hide": "Hide",
Expand Down
1 change: 1 addition & 0 deletions src/common/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ type Node = {
lastStartedTimestampMs?: number;
lastStoppedTimestampMs?: number;
stoppedBy?: NodeStoppedBy;
updateAvailable?: boolean;
};
type NodeMap = Record<string, Node>;
export type UserNodes = {
Expand Down
4 changes: 4 additions & 0 deletions src/main/ipc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
getMainProcessUsage,
updateNodeLastSyncedBlock,
} from './monitor';
import { checkForCartridgeUpdate } from './nodeLibraryManager.js';
import {
addNode,
deleteNodeStorage,
Expand Down Expand Up @@ -200,6 +201,9 @@ export const initialize = () => {
// Node library
ipcMain.handle('getNodeLibrary', getNodeLibrary);
ipcMain.handle('getNodePackageLibrary', getNodePackageLibrary);
ipcMain.handle('checkForCartridgeUpdate', (_event, nodeId: NodeId) => {
return checkForCartridgeUpdate(nodeId);
});

// Podman
ipcMain.handle('getIsPodmanInstalled', isPodmanInstalled);
Expand Down
57 changes: 57 additions & 0 deletions src/main/nodeLibraryManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ import nitrov1 from '../common/NodeSpecs/nitro/nitro-v1.0.0.json';
import homeAssistantServicev1 from '../common/NodeSpecs/home-assistant-service/home-assistant-service-v1.0.0.json';
import itzgMinecraftv1 from '../common/NodeSpecs/itzg-minecraft/itzg-minecraft-v1.0.0.json';

import type { NodeId } from '../common/node.js';
import type Node from '../common/node.js';
import type {
NodePackageSpecification,
NodeSpecification,
Expand All @@ -47,6 +49,7 @@ import {
updateNodeLibrary,
updateNodePackageLibrary,
} from './state/nodeLibrary';
import { getNode, updateNode } from './state/nodes.js';

export const initialize = async () => {
await updateLocalNodeAndPackageLibrary();
Expand Down Expand Up @@ -88,6 +91,21 @@ const getCartridges = async (): Promise<NodeSpecification[]> => {
return cartridges;
};

const getCartridge = async (
cartridgeId: string,
): Promise<NodeSpecification> => {
const cartridgesApiURL = `http://localhost:3000/api/cartridge/${cartridgeId}`;
const isHttp = true;
// const cartridgesApiURL = `https://api.nicenode.xyz/api/cartridge/${cartridgeId}`;
// const isHttp = false;
const response = await httpGetJson(cartridgesApiURL, isHttp);
if (response.error) {
throw Error(response.error);
}
const cartridge: NodeSpecification = response.data;
return cartridge;
};

// Updates the local electron store with the latest node and package library (aka cartridges)
// Should be called this after user clicks add node, but before showing the previous values
export const updateLocalNodeAndPackageLibrary = async () => {
Expand Down Expand Up @@ -201,3 +219,42 @@ export const updateLocalNodeAndPackageLibrary = async () => {

return updateNodePackageLibrary(nodePackageSpecBySpecId);
};

/**
*
* @param nodeId
* @returns true if there is an update
*/
export const checkForCartridgeUpdate = async (
nodeId: NodeId,
): Promise<boolean> => {
// get node
// using node.url, fetch the latest version
// compare to node.spec.version
// if newer, update node.updateAvailable = true
const node: Node = getNode(nodeId);
if (node) {
const latestCartridge = await getCartridge(node.spec.specId);
logger.info(
`checkForCartridgeUpdate: latestCartridge: ${JSON.stringify(
latestCartridge,
)}`,
);
if (node.spec.version < latestCartridge.version) {
logger.info(
`checkForCartridgeUpdate: Node ${node.spec.displayName} has an update available`,
);
node.updateAvailable = true;
updateNode(node);
return true;
}
logger.info(
`checkForCartridgeUpdate: Node ${node.spec.displayName} does NOT have an update available`,
);
} else {
logger.error(`checkForCartridgeUpdate: Node ${nodeId} not found`);
}
node.updateAvailable = false;
updateNode(node);
return false; // throw
};
3 changes: 3 additions & 0 deletions src/main/preload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type {
NodeSpecification,
} from '../common/nodeSpec';
import { CHANNELS_ARRAY } from './messenger';
import { checkForCartridgeUpdate } from './nodeLibraryManager.js';
import type { AddNodePackageNodeService } from './nodePackageManager';
import type { ThemeSetting } from './state/settings';

Expand Down Expand Up @@ -122,6 +123,8 @@ contextBridge.exposeInMainWorld('electron', {
// Node library
getNodeLibrary: () => ipcRenderer.invoke('getNodeLibrary'),
getNodePackageLibrary: () => ipcRenderer.invoke('getNodePackageLibrary'),
checkForCartridgeUpdate: (nodeId: NodeId) =>
ipcRenderer.invoke('checkForCartridgeUpdate', nodeId),

// Podman
getIsPodmanInstalled: () => ipcRenderer.invoke('getIsPodmanInstalled'),
Expand Down
35 changes: 24 additions & 11 deletions src/renderer/Generics/redesign/Header/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import electron from '../../../electronGlobal.js';
import { useAppDispatch } from '../../../state/hooks';
import { setModalState } from '../../../state/modal';
import Button, { type ButtonProps } from '../Button/Button';
Expand Down Expand Up @@ -31,6 +32,7 @@ type HeaderProps = {
*/
export const Header = ({ nodeOverview, isPodmanRunning }: HeaderProps) => {
const {
nodeId,
name,
displayName,
title,
Expand Down Expand Up @@ -199,17 +201,28 @@ export const Header = ({ nodeOverview, isPodmanRunning }: HeaderProps) => {
<div className={popupContainer}>
<Menu width={156}>
{screenType === 'client' && (
<MenuItem
text={g('NodeSettings')}
onClick={() => {
dispatch(
setModalState({
isModalOpen: true,
screen: { route: 'nodeSettings', type: 'modal' },
}),
);
}}
/>
<>
<MenuItem
text={g('NodeSettings')}
onClick={() => {
dispatch(
setModalState({
isModalOpen: true,
screen: { route: 'nodeSettings', type: 'modal' },
}),
);
}}
/>
<MenuItem
text={g('CheckForUpdates')}
onClick={async () => {
// dispatch checkForUpdates, show loading icon?, then show success or error in-line?
const isUpdateAvailable =
await electron.checkForCartridgeUpdate(nodeId);
console.log('isUpdateAvailable:', isUpdateAvailable);
}}
/>
</>
)}
{screenType === 'nodePackage' && (
<MenuItem
Expand Down
2 changes: 2 additions & 0 deletions src/renderer/Presentational/NodeScreen/NodeScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
selectIsAvailableForPolling,
selectSelectedNode,
} from '../../state/node';
import node from '../../state/node.js';
import {
useGetExecutionIsSyncingQuery,
useGetExecutionLatestBlockQuery,
Expand Down Expand Up @@ -351,6 +352,7 @@ const NodeScreen = () => {
// synchronized: !sIsSyncing && parseFloat(sSyncPercent) > 99.9,
synchronized: sIsSyncing === false && status === NodeStatus.running,
updating: status === NodeStatus.updating,
updateAvailable: selectedNode.updateAvailable,
},
stats: {
peers: sPeers,
Expand Down
1 change: 1 addition & 0 deletions src/renderer/preload.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ declare global {
// Node library
getNodeLibrary(): NodeLibrary;
getNodePackageLibrary(): NodePackageLibrary;
checkForCartridgeUpdate(nodeId: NodeId): boolean;

// Podman
getIsPodmanInstalled(): boolean;
Expand Down

0 comments on commit 25c572a

Please sign in to comment.