mirror of
https://github.com/uqbar-dao/nectar.git
synced 2025-01-03 06:11:01 +03:00
app_store UI: fix launch buttons
This commit is contained in:
parent
39b5463dda
commit
74e769ba3b
@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useState, useCallback } from "react";
|
||||
import React, { useEffect, useState, useCallback, useMemo } from "react";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import { FaDownload, FaCheck, FaTimes, FaPlay, FaSpinner, FaTrash, FaSync } from "react-icons/fa";
|
||||
import useAppsStore from "../store";
|
||||
@ -8,7 +8,7 @@ import { compareVersions } from "../utils/compareVersions";
|
||||
export default function AppPage() {
|
||||
const { id } = useParams();
|
||||
const navigate = useNavigate();
|
||||
const { fetchListing, fetchInstalledApp, uninstallApp, setAutoUpdate } = useAppsStore();
|
||||
const { fetchListing, fetchInstalledApp, uninstallApp, setAutoUpdate, getLaunchUrl, fetchHomepageApps } = useAppsStore();
|
||||
const [app, setApp] = useState<AppListing | null>(null);
|
||||
const [installedApp, setInstalledApp] = useState<PackageState | null>(null);
|
||||
const [currentVersion, setCurrentVersion] = useState<string | null>(null);
|
||||
@ -57,6 +57,21 @@ export default function AppPage() {
|
||||
}
|
||||
}, [id, fetchListing, fetchInstalledApp]);
|
||||
|
||||
|
||||
const handleLaunch = useCallback(() => {
|
||||
if (app) {
|
||||
const launchUrl = getLaunchUrl(`${app.package_id.package_name}:${app.package_id.publisher_node}`);
|
||||
if (launchUrl) {
|
||||
window.location.href = launchUrl;
|
||||
}
|
||||
}
|
||||
}, [app, getLaunchUrl]);
|
||||
|
||||
const canLaunch = useMemo(() => {
|
||||
if (!app) return false;
|
||||
return !!getLaunchUrl(`${app.package_id.package_name}:${app.package_id.publisher_node}`);
|
||||
}, [app, getLaunchUrl]);
|
||||
|
||||
const handleUninstall = async () => {
|
||||
if (!app) return;
|
||||
setIsUninstalling(true);
|
||||
@ -88,16 +103,13 @@ export default function AppPage() {
|
||||
|
||||
useEffect(() => {
|
||||
loadData();
|
||||
}, [loadData]);
|
||||
fetchHomepageApps();
|
||||
}, [loadData, fetchHomepageApps]);
|
||||
|
||||
const handleDownload = () => {
|
||||
navigate(`/download/${id}`);
|
||||
};
|
||||
|
||||
const handleLaunch = () => {
|
||||
window.location.href = `/${app?.package_id.package_name}:${app?.package_id.package_name}:${app?.package_id.publisher_node}/`;
|
||||
};
|
||||
|
||||
if (isLoading) {
|
||||
return <div className="app-page"><h4>Loading app details...</h4></div>;
|
||||
}
|
||||
@ -150,8 +162,12 @@ export default function AppPage() {
|
||||
<div className="app-actions">
|
||||
{installedApp && (
|
||||
<>
|
||||
<button onClick={handleLaunch} className="primary">
|
||||
<FaPlay /> Launch
|
||||
<button
|
||||
onClick={handleLaunch}
|
||||
className="primary"
|
||||
disabled={!canLaunch}
|
||||
>
|
||||
<FaPlay /> {canLaunch ? 'Launch' : 'No UI found for app'}
|
||||
</button>
|
||||
<button onClick={handleUninstall} className="secondary" disabled={isUninstalling}>
|
||||
{isUninstalling ? <FaSpinner className="fa-spin" /> : <FaTrash />} Uninstall
|
||||
|
@ -17,6 +17,8 @@ export default function DownloadPage() {
|
||||
installApp,
|
||||
removeDownload,
|
||||
clearAllActiveDownloads,
|
||||
fetchHomepageApps,
|
||||
getLaunchUrl
|
||||
} = useAppsStore();
|
||||
|
||||
const [showMetadata, setShowMetadata] = useState(false);
|
||||
@ -35,8 +37,9 @@ export default function DownloadPage() {
|
||||
if (id) {
|
||||
fetchData(id);
|
||||
clearAllActiveDownloads();
|
||||
fetchHomepageApps();
|
||||
}
|
||||
}, [id, fetchData, clearAllActiveDownloads]);
|
||||
}, [id, fetchData, clearAllActiveDownloads, fetchHomepageApps]);
|
||||
|
||||
const handleMirrorSelect = useCallback((mirror: string, status: boolean | null | 'http') => {
|
||||
setSelectedMirror(mirror);
|
||||
@ -145,9 +148,17 @@ export default function DownloadPage() {
|
||||
|
||||
const handleLaunch = useCallback(() => {
|
||||
if (app) {
|
||||
navigate(`/${app.package_id.package_name}:${app.package_id.package_name}:${app.package_id.publisher_node}/`);
|
||||
const launchUrl = getLaunchUrl(`${app.package_id.package_name}:${app.package_id.publisher_node}`);
|
||||
if (launchUrl) {
|
||||
window.location.href = launchUrl;
|
||||
}
|
||||
}, [app, navigate]);
|
||||
}
|
||||
}, [app, getLaunchUrl]);
|
||||
|
||||
const canLaunch = useMemo(() => {
|
||||
if (!app) return false;
|
||||
return !!getLaunchUrl(`${app.package_id.package_name}:${app.package_id.publisher_node}`);
|
||||
}, [app, getLaunchUrl]);
|
||||
|
||||
if (!app) {
|
||||
return <div className="downloads-page"><h4>Loading app details...</h4></div>;
|
||||
@ -158,8 +169,12 @@ export default function DownloadPage() {
|
||||
<div className="app-header">
|
||||
<h2>{app.metadata?.name || app.package_id.package_name}</h2>
|
||||
{installedApp && (
|
||||
<button onClick={handleLaunch} className="launch-button">
|
||||
<FaPlay /> Launch
|
||||
<button
|
||||
onClick={handleLaunch}
|
||||
className="launch-button"
|
||||
disabled={!canLaunch}
|
||||
>
|
||||
<FaPlay /> {canLaunch ? 'Launch' : 'No UI found for app'}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { create } from 'zustand'
|
||||
import { persist } from 'zustand/middleware'
|
||||
import { PackageState, AppListing, MirrorCheckFile, PackageManifest, DownloadItem } from '../types/Apps'
|
||||
import { PackageState, AppListing, MirrorCheckFile, PackageManifest, DownloadItem, HomepageApp } from '../types/Apps'
|
||||
import { HTTP_STATUS } from '../constants/http'
|
||||
import KinodeClientApi from "@kinode/client-api"
|
||||
import { WEBSOCKET_URL } from '../utils/ws'
|
||||
@ -13,6 +13,7 @@ interface AppsStore {
|
||||
downloads: Record<string, DownloadItem[]>
|
||||
ourApps: AppListing[]
|
||||
ws: KinodeClientApi
|
||||
homepageApps: HomepageApp[]
|
||||
activeDownloads: Record<string, { downloaded: number, total: number }>
|
||||
|
||||
fetchData: (id: string) => Promise<void>
|
||||
@ -25,6 +26,9 @@ interface AppsStore {
|
||||
fetchDownloadsForApp: (id: string) => Promise<DownloadItem[]>
|
||||
checkMirror: (node: string) => Promise<MirrorCheckFile | null>
|
||||
|
||||
fetchHomepageApps: () => Promise<void>
|
||||
getLaunchUrl: (id: string) => string | null
|
||||
|
||||
installApp: (id: string, version_hash: string) => Promise<void>
|
||||
uninstallApp: (id: string) => Promise<void>
|
||||
downloadApp: (id: string, version_hash: string, downloadFrom: string) => Promise<void>
|
||||
@ -49,6 +53,8 @@ const useAppsStore = create<AppsStore>()(
|
||||
downloads: {},
|
||||
ourApps: [],
|
||||
activeDownloads: {},
|
||||
homepageApps: [],
|
||||
|
||||
|
||||
fetchData: async (id: string) => {
|
||||
if (!id) return;
|
||||
@ -174,6 +180,26 @@ const useAppsStore = create<AppsStore>()(
|
||||
return [];
|
||||
},
|
||||
|
||||
fetchHomepageApps: async () => {
|
||||
try {
|
||||
const res = await fetch('/apps');
|
||||
if (res.status === HTTP_STATUS.OK) {
|
||||
const data: HomepageApp[] = await res.json();
|
||||
set({ homepageApps: data });
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching homepage apps:", error);
|
||||
}
|
||||
},
|
||||
|
||||
getLaunchUrl: (id: string) => {
|
||||
const app = get().homepageApps.find(app => `${app.package}:${app.publisher}` === id);
|
||||
if (app && app.path) {
|
||||
return app.path;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
checkMirror: async (node: string) => {
|
||||
try {
|
||||
const res = await fetch(`${BASE_URL}/mirrorcheck/${node}`);
|
||||
|
@ -70,3 +70,16 @@ export interface PackageManifest {
|
||||
grant_capabilities: any[]
|
||||
public: boolean
|
||||
}
|
||||
|
||||
export interface HomepageApp {
|
||||
id: string;
|
||||
process: string;
|
||||
package: string;
|
||||
publisher: string;
|
||||
path?: string;
|
||||
label: string;
|
||||
base64_icon?: string;
|
||||
widget?: string;
|
||||
order: number;
|
||||
favorite: boolean;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user