From b91302fed0641a56d3300fbe3e23c06e5913baf1 Mon Sep 17 00:00:00 2001 From: UndyingWraith Date: Mon, 17 Jun 2024 16:30:20 +0200 Subject: [PATCH] Remove ProfileManager --- packages/core/src/Modules/CoreModule.ts | 4 +- packages/core/src/Services/IndexManager.ts | 92 ++++++++++++++++ .../src/Services/Indexer/IIndexFetcher.ts | 1 + .../src/Services/Indexer/MovieIndexFetcher.ts | 2 + .../Services/Indexer/SeriesIndexFetcher.ts | 2 + packages/core/src/Services/Indexer/index.ts | 1 + .../ProfileManager/BaseProfileManager.ts | 103 ------------------ .../ProfileManager/RemoteProfileManager.ts | 70 ------------ .../ProfileManager/SimpleProfileManager.ts | 17 --- .../core/src/Services/ProfileManager/index.ts | 3 - packages/core/src/Services/index.ts | 1 - packages/core/src/index.ts | 1 + packages/core/src/util/createRemoteIpfs.ts | 59 ++++++++++ packages/core/src/util/index.ts | 1 + .../interfaces/src/MetaData/ILibraryIndex.ts | 5 + .../src/MetaData/Library/LibraryType.ts | 6 + .../interfaces/src/MetaData/Library/index.ts | 1 + packages/interfaces/src/MetaData/index.ts | 13 +-- packages/interfaces/src/Profile/IProfile.ts | 2 + packages/interfaces/src/Profile/index.ts | 2 +- .../interfaces/src/Services/IIndexManager.ts | 11 ++ .../src/Services/IProfileManager.ts | 53 --------- packages/interfaces/src/Services/index.ts | 2 +- packages/ui/src/IpmcLauncher.tsx | 35 +++--- .../ui/src/components/organisms/AppBar.tsx | 4 +- .../ui/src/components/organisms/Library.tsx | 9 +- .../organisms/LibraryHomeScreen.tsx | 13 +-- .../src/components/pages/LibraryManager.tsx | 6 +- 28 files changed, 221 insertions(+), 298 deletions(-) create mode 100644 packages/core/src/Services/IndexManager.ts delete mode 100644 packages/core/src/Services/ProfileManager/BaseProfileManager.ts delete mode 100644 packages/core/src/Services/ProfileManager/RemoteProfileManager.ts delete mode 100644 packages/core/src/Services/ProfileManager/SimpleProfileManager.ts delete mode 100644 packages/core/src/Services/ProfileManager/index.ts create mode 100644 packages/core/src/util/createRemoteIpfs.ts create mode 100644 packages/core/src/util/index.ts create mode 100644 packages/interfaces/src/MetaData/ILibraryIndex.ts create mode 100644 packages/interfaces/src/MetaData/Library/LibraryType.ts create mode 100644 packages/interfaces/src/Services/IIndexManager.ts delete mode 100644 packages/interfaces/src/Services/IProfileManager.ts diff --git a/packages/core/src/Modules/CoreModule.ts b/packages/core/src/Modules/CoreModule.ts index 8bb5fc2..750e121 100644 --- a/packages/core/src/Modules/CoreModule.ts +++ b/packages/core/src/Modules/CoreModule.ts @@ -1,9 +1,11 @@ -import { IKeyValueStoreSymbol, IObjectStoreSymbol } from 'ipmc-interfaces'; +import { IIndexManagerSymbol, IKeyValueStoreSymbol, IObjectStoreSymbol } from 'ipmc-interfaces'; import { MemoryKeyValueStore } from '../Services/MemoryKeyValueStore'; import { ObjectStore } from '../Services/ObjectStore'; import { IModule } from './IModule'; +import { IndexManager } from '../Services/IndexManager'; export const CoreModule: IModule = (app) => { app.register(MemoryKeyValueStore, IKeyValueStoreSymbol); app.register(ObjectStore, IObjectStoreSymbol); + app.register(IndexManager, IIndexManagerSymbol); }; diff --git a/packages/core/src/Services/IndexManager.ts b/packages/core/src/Services/IndexManager.ts new file mode 100644 index 0000000..bfe3f01 --- /dev/null +++ b/packages/core/src/Services/IndexManager.ts @@ -0,0 +1,92 @@ +import { Signal } from '@preact/signals-core'; +import { inject, injectable, postConstruct, preDestroy } from 'inversify'; +import { IIndexManager, IIpfsService, IIpfsServiceSymbol, ILibrary, ILibraryIndex, IObjectStore, IObjectStoreSymbol, IProfile, IProfileSymbol, ITask, isMovieLibrary, isSeriesLibrary } from 'ipmc-interfaces'; +import { MovieIndexFetcher, SeriesIndexFetcher } from './Indexer'; + +@injectable() +export class IndexManager implements IIndexManager { + public constructor( + @inject(IProfileSymbol) private readonly profile: IProfile, + @inject(IIpfsServiceSymbol) private readonly ipfs: IIpfsService, + @inject(IObjectStoreSymbol) private readonly objectStore: IObjectStore, + ) { + for (const lib of this.profile.libraries) { + this.libraries.set(lib.name, new Signal(lib)); + const indexSignal = new Signal | undefined>(this.objectStore.get(this.getIndexStorageKey(lib.name))); + this.indexes.set(lib.name, indexSignal); + indexSignal.subscribe((newState) => { + if (newState !== undefined) { + this.objectStore.set(this.getIndexStorageKey(lib.name), newState); + } + }); + } + } + + @postConstruct() + public start(): void { + this.triggerUpdate(); + this.timer = setInterval(() => { + this.triggerUpdate(); + }, 15 * 60 * 1000); + } + + @preDestroy() + public stop(): void { + clearInterval(this.timer); + } + + public indexes = new Map | undefined>>(); + + public tasks = new Signal([]); + + private getIndexStorageKey(name: string) { + return `${this.profile.id}_index_${name}`; + } + + private triggerUpdate(): void { + for (const library of this.libraries.values()) { + const lib = library.value; + if (!this.updates.has(lib.name)) { + const task = { + title: 'Updating library ' + lib.name, + }; + this.tasks.value = [...this.tasks.value, task]; + this.updates.set(lib.name, this.updateLibrary(lib).finally(() => { + this.updates.delete(lib.name); + this.tasks.value = this.tasks.value.filter(t => t != task); + })); + } + } + } + + private async updateLibrary(library: ILibrary): Promise { + const index = this.indexes.get(library.name); + if (library.upstream != undefined && index != undefined) { + try { + const cid = await this.ipfs.resolve(library.upstream); + const indexer = isMovieLibrary(library) ? new MovieIndexFetcher(this.ipfs, library) : isSeriesLibrary(library) ? new SeriesIndexFetcher(this.ipfs, library) : undefined; + if (index.value?.cid != cid || indexer?.version !== index.value?.indexer) { + if (indexer == undefined) { + throw new Error(`Unknown library type [${library.type}]`); + } + + const newIndex = await indexer.fetchIndex(); + + index.value = { + cid: cid, + indexer: indexer.version, + index: newIndex, + }; + } + } catch (ex) { + console.error(ex); + } + } + } + + private libraries = new Map>(); + + private updates = new Map>(); + + private timer: any; +} diff --git a/packages/core/src/Services/Indexer/IIndexFetcher.ts b/packages/core/src/Services/Indexer/IIndexFetcher.ts index 38f278a..fb1b1ad 100644 --- a/packages/core/src/Services/Indexer/IIndexFetcher.ts +++ b/packages/core/src/Services/Indexer/IIndexFetcher.ts @@ -1,3 +1,4 @@ export interface IIndexFetcher { fetchIndex(): Promise; + version: string; } diff --git a/packages/core/src/Services/Indexer/MovieIndexFetcher.ts b/packages/core/src/Services/Indexer/MovieIndexFetcher.ts index 4f8c35f..2f201e0 100644 --- a/packages/core/src/Services/Indexer/MovieIndexFetcher.ts +++ b/packages/core/src/Services/Indexer/MovieIndexFetcher.ts @@ -6,6 +6,8 @@ export class MovieIndexFetcher implements IIndexFetcher { constructor(private readonly node: IIpfsService, private readonly lib: IGenericLibrary) { } + public version = '0'; + public async fetchIndex(): Promise { const files = (await this.node.ls(this.lib.root.toString())).filter(f => f.type == 'dir'); const index = []; diff --git a/packages/core/src/Services/Indexer/SeriesIndexFetcher.ts b/packages/core/src/Services/Indexer/SeriesIndexFetcher.ts index 765fa20..62f0607 100644 --- a/packages/core/src/Services/Indexer/SeriesIndexFetcher.ts +++ b/packages/core/src/Services/Indexer/SeriesIndexFetcher.ts @@ -6,6 +6,8 @@ export class SeriesIndexFetcher implements IIndexFetcher { constructor(private readonly node: IIpfsService, private readonly lib: IGenericLibrary) { } + public version = '0'; + public async fetchIndex(): Promise { const files = (await this.node.ls(this.lib.root.toString())).filter(f => f.type == 'dir'); const index = []; diff --git a/packages/core/src/Services/Indexer/index.ts b/packages/core/src/Services/Indexer/index.ts index a4da321..e582c30 100644 --- a/packages/core/src/Services/Indexer/index.ts +++ b/packages/core/src/Services/Indexer/index.ts @@ -1,2 +1,3 @@ +export { type IIndexFetcher } from './IIndexFetcher'; export { MovieIndexFetcher } from './MovieIndexFetcher'; export { SeriesIndexFetcher } from './SeriesIndexFetcher'; diff --git a/packages/core/src/Services/ProfileManager/BaseProfileManager.ts b/packages/core/src/Services/ProfileManager/BaseProfileManager.ts deleted file mode 100644 index d3842f8..0000000 --- a/packages/core/src/Services/ProfileManager/BaseProfileManager.ts +++ /dev/null @@ -1,103 +0,0 @@ -import { Signal } from "@preact/signals-react"; -import { IIpfsService, ILibrary, IProfile, isMovieLibrary, isSeriesLibrary, ITask } from 'ipmc-interfaces'; -import { MovieIndexFetcher, SeriesIndexFetcher } from '../Indexer'; -import { IProfileManager, ProfileManagerState } from 'ipmc-interfaces'; - -export abstract class BaseProfileManager implements IProfileManager { - protected constructor(public readonly profile: TProfile) { - for (const lib of this.profile.libraries) { - this.libraries.set(lib.name, new Signal(lib)); - } - } - - public start(): Promise { - return this.startNode() - .then(() => { - this.triggerUpdate(); - this.timer = setInterval(() => { - this.triggerUpdate(); - }, 15 * 60 * 1000); - this.state.value = ProfileManagerState.Running; - }); - } - - public stop(): Promise { - clearInterval(this.timer); - return this.stopNode() - .then(() => { - this.state.value = ProfileManagerState.Stopped; - }); - } - - public libraries = new Map>(); - - public state = new Signal(ProfileManagerState.Stopped); - - public tasks = new Signal([]); - - - protected abstract startNode(): Promise; - - protected abstract stopNode(): Promise; - - public ipfs: IIpfsService | undefined; - - - private triggerUpdate(): void { - for (const library of this.libraries.values()) { - const lib = library.value; - if (!this.updates.has(lib.name)) { - const task = { - title: 'Updating library ' + lib.name, - }; - this.tasks.value = [...this.tasks.value, task]; - this.updates.set(lib.name, this.updateLibrary(lib).finally(() => { - this.updates.delete(lib.name); - this.tasks.value = this.tasks.value.filter(t => t != task); - })); - } - } - } - - private async updateLibrary(library: ILibrary): Promise { - if (library.upstream != undefined) { - try { - const cid = await this.ipfs!.resolve(library.upstream); - if (library.root != cid) { - const lib = this.libraries.get(library.name); - if (lib != undefined) { - lib.value = { - ...lib.value, root: cid - }; - } - } - } catch (ex) { - console.error(ex); - } - } - - if (library.index?.cid !== library.root || library.index?.cid !== undefined) { - const lib = this.libraries.get(library.name); - if (lib != undefined) { - const indexer = isMovieLibrary(lib.value) ? new MovieIndexFetcher(this.ipfs!, lib.value) : isSeriesLibrary(lib.value) ? new SeriesIndexFetcher(this.ipfs!, lib.value) : undefined; - if (indexer == undefined) { - throw new Error(`Unknown library type [${library.type}]`); - } - - const index = await indexer.fetchIndex(); - - //@ts-ignore - lib.value = { - ...lib.value, index: { - values: index, - cid: lib.value.root, - } - }; - } - } - } - - private updates = new Map>(); - - private timer: any; -} diff --git a/packages/core/src/Services/ProfileManager/RemoteProfileManager.ts b/packages/core/src/Services/ProfileManager/RemoteProfileManager.ts deleted file mode 100644 index 4a6ddc3..0000000 --- a/packages/core/src/Services/ProfileManager/RemoteProfileManager.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { IFileInfo, IRemoteProfile } from "ipmc-interfaces"; -import { BaseProfileManager } from "./BaseProfileManager"; -import { create } from 'kubo-rpc-client'; - -export class RemoteProfileManager extends BaseProfileManager { - constructor(profile: IRemoteProfile) { - super(profile); - } - - protected async startNode() { - const node = create({ url: this.profile.url }); - const connString = (await node.config.get('Addresses.Gateway')) as string; - const port = connString.substring(connString.lastIndexOf('/') + 1); - const id = (await node.id()).id.toString(); - - this.ipfs = { - async ls(cid: string) { - const files: IFileInfo[] = []; - for await (const file of node.ls(cid)) { - files.push({ - type: file.type, - name: file.name, - cid: file.cid.toString(), - }); - } - return files; - }, - stop() { - return Promise.resolve(); - }, - toUrl(cid: string) { - return `http://127.0.0.1:${port}/ipfs/${cid}`; - }, - id() { - return id; - }, - async peers() { - return (await node.swarm.peers()).map(p => p.addr.toString() + '/' + p.peer.toString()); - }, - async resolve(name) { - let result = ''; - for await (const res of node.name.resolve(name.at(0) == '/' ? name : '/ipns/' + name)) { - result = res; - } - - return result; - }, - async isPinned(cid) { - for await (const res of node.pin.ls({ - paths: cid, - })) { - if (res.cid.toString() == cid) { - return true; - } - } - return false; - }, - async addPin(cid) { - await node.pin.add(cid); - }, - async rmPin(cid) { - await node.pin.rm(cid); - }, - }; - } - - protected stopNode() { - return Promise.resolve(); - } -} diff --git a/packages/core/src/Services/ProfileManager/SimpleProfileManager.ts b/packages/core/src/Services/ProfileManager/SimpleProfileManager.ts deleted file mode 100644 index 66fa958..0000000 --- a/packages/core/src/Services/ProfileManager/SimpleProfileManager.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { IIpfsService, IProfile } from 'ipmc-interfaces'; -import { BaseProfileManager } from './BaseProfileManager'; - -export class SimpleProfileManager extends BaseProfileManager { - constructor(ipfs: IIpfsService, profile: IProfile) { - super(profile); - this.ipfs = ipfs; - } - - protected startNode(): Promise { - return Promise.resolve(); - } - - protected stopNode(): Promise { - return this.ipfs?.stop() ?? Promise.resolve(); - } -} diff --git a/packages/core/src/Services/ProfileManager/index.ts b/packages/core/src/Services/ProfileManager/index.ts deleted file mode 100644 index 9791a28..0000000 --- a/packages/core/src/Services/ProfileManager/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { BaseProfileManager } from './BaseProfileManager'; -export { RemoteProfileManager } from './RemoteProfileManager'; -export { SimpleProfileManager } from './SimpleProfileManager'; diff --git a/packages/core/src/Services/index.ts b/packages/core/src/Services/index.ts index fd24320..0d6b510 100644 --- a/packages/core/src/Services/index.ts +++ b/packages/core/src/Services/index.ts @@ -1,5 +1,4 @@ export * from './Indexer'; -export * from './ProfileManager'; export { HotkeyService } from './HotkeyService'; export { LocalStorageKeyValueStore } from './LocalStorageKeyValueStore'; export { MemoryKeyValueStore } from './MemoryKeyValueStore'; diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 0cd34eb..c75f191 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -2,6 +2,7 @@ import 'reflect-metadata'; export * from './Modules'; export * from './Services'; +export * from './util'; export { Application } from './Application'; export { type IApplication } from './IApplication'; export { Regexes } from './Regexes'; diff --git a/packages/core/src/util/createRemoteIpfs.ts b/packages/core/src/util/createRemoteIpfs.ts new file mode 100644 index 0000000..0985316 --- /dev/null +++ b/packages/core/src/util/createRemoteIpfs.ts @@ -0,0 +1,59 @@ +import { IFileInfo, IIpfsService } from 'ipmc-interfaces'; +import { create } from 'kubo-rpc-client'; + +export async function createRemoteIpfs(url?: string): Promise { + const node = create({ url }); + const connString = (await node.config.get('Addresses.Gateway')) as string; + const port = connString.substring(connString.lastIndexOf('/') + 1); + const id = (await node.id()).id.toString(); + + return { + async ls(cid: string) { + const files: IFileInfo[] = []; + for await (const file of node.ls(cid)) { + files.push({ + type: file.type, + name: file.name, + cid: file.cid.toString(), + }); + } + return files; + }, + stop() { + return Promise.resolve(); + }, + toUrl(cid: string) { + return `http://127.0.0.1:${port}/ipfs/${cid}`; + }, + id() { + return id; + }, + async peers() { + return (await node.swarm.peers()).map(p => p.addr.toString() + '/' + p.peer.toString()); + }, + async resolve(name) { + let result = ''; + for await (const res of node.name.resolve(name.at(0) == '/' ? name : '/ipns/' + name)) { + result = res; + } + + return result; + }, + async isPinned(cid) { + for await (const res of node.pin.ls({ + paths: cid, + })) { + if (res.cid.toString() == cid) { + return true; + } + } + return false; + }, + async addPin(cid) { + await node.pin.add(cid); + }, + async rmPin(cid) { + await node.pin.rm(cid); + }, + }; +} diff --git a/packages/core/src/util/index.ts b/packages/core/src/util/index.ts new file mode 100644 index 0000000..1f8e910 --- /dev/null +++ b/packages/core/src/util/index.ts @@ -0,0 +1 @@ +export { createRemoteIpfs } from './createRemoteIpfs'; diff --git a/packages/interfaces/src/MetaData/ILibraryIndex.ts b/packages/interfaces/src/MetaData/ILibraryIndex.ts new file mode 100644 index 0000000..12a495f --- /dev/null +++ b/packages/interfaces/src/MetaData/ILibraryIndex.ts @@ -0,0 +1,5 @@ +export interface ILibraryIndex { + indexer: string; + cid: string, + index: TValues[]; +} diff --git a/packages/interfaces/src/MetaData/Library/LibraryType.ts b/packages/interfaces/src/MetaData/Library/LibraryType.ts new file mode 100644 index 0000000..874ccc6 --- /dev/null +++ b/packages/interfaces/src/MetaData/Library/LibraryType.ts @@ -0,0 +1,6 @@ +export enum LibraryType { + Movies, + Series, + Music, + Books, +} diff --git a/packages/interfaces/src/MetaData/Library/index.ts b/packages/interfaces/src/MetaData/Library/index.ts index 922fcba..fd54bc5 100644 --- a/packages/interfaces/src/MetaData/Library/index.ts +++ b/packages/interfaces/src/MetaData/Library/index.ts @@ -3,3 +3,4 @@ export type { ILibrary, IMovieLibrary } from './ILibrary'; export { isMovieLibrary, isMusicLibrary, isSeriesLibrary } from './ILibrary'; export type { IMovieMetaData } from './IMovieMetaData'; export type { IEpisodeMetaData, ISeriesMetaData, ISeasonMetaData } from './ISeriesMetaData'; +export { LibraryType } from './LibraryType'; diff --git a/packages/interfaces/src/MetaData/index.ts b/packages/interfaces/src/MetaData/index.ts index bfabf0a..1ce6e3d 100644 --- a/packages/interfaces/src/MetaData/index.ts +++ b/packages/interfaces/src/MetaData/index.ts @@ -1,10 +1,7 @@ export * from './Features'; export * from './Library'; -export type { IFileInfo } from './IFileInfo'; -export { isIFileInfo } from './IFileInfo'; -export type { IFolderFile } from './IFolderFile'; -export { isIFolderFile } from './IFolderFile'; -export type { IImageFile } from './IImageFile'; -export { isIImageFile } from './IImageFile'; -export type { IVideoFile } from './IVideoFile'; -export { isIVideoFile } from './IVideoFile'; +export { type IFileInfo, isIFileInfo } from './IFileInfo'; +export { type IFolderFile, isIFolderFile } from './IFolderFile'; +export { type IImageFile, isIImageFile } from './IImageFile'; +export { type ILibraryIndex } from './ILibraryIndex'; +export { type IVideoFile, isIVideoFile } from './IVideoFile'; diff --git a/packages/interfaces/src/Profile/IProfile.ts b/packages/interfaces/src/Profile/IProfile.ts index af7f89a..824cf68 100644 --- a/packages/interfaces/src/Profile/IProfile.ts +++ b/packages/interfaces/src/Profile/IProfile.ts @@ -1,6 +1,8 @@ import { IInternalProfile, isInternalProfile } from "./IInternalProfile"; import { IRemoteProfile, isRemoteProfile } from "./IRemoteProfile"; +export const IProfileSymbol = Symbol.for('IProfile'); + export type IProfile = IInternalProfile | IRemoteProfile; export function isIProfile(item: any): item is IProfile { diff --git a/packages/interfaces/src/Profile/index.ts b/packages/interfaces/src/Profile/index.ts index 98ced59..e8ad959 100644 --- a/packages/interfaces/src/Profile/index.ts +++ b/packages/interfaces/src/Profile/index.ts @@ -1,4 +1,4 @@ export { type IBaseProfile } from './IBaseProfile'; export { type IInternalProfile, isInternalProfile } from './IInternalProfile'; -export { type IProfile, isIProfile } from './IProfile'; +export { type IProfile, isIProfile, IProfileSymbol } from './IProfile'; export { type IRemoteProfile, isRemoteProfile } from './IRemoteProfile'; diff --git a/packages/interfaces/src/Services/IIndexManager.ts b/packages/interfaces/src/Services/IIndexManager.ts new file mode 100644 index 0000000..ea046d3 --- /dev/null +++ b/packages/interfaces/src/Services/IIndexManager.ts @@ -0,0 +1,11 @@ +import { ReadonlySignal } from '@preact/signals-core'; +import { ILibraryIndex } from '../MetaData'; + +export const IIndexManagerSymbol = Symbol.for('IIndexManager'); + +export interface IIndexManager { + /** + * Currently available indexes. + */ + indexes: Map | undefined>>; +} diff --git a/packages/interfaces/src/Services/IProfileManager.ts b/packages/interfaces/src/Services/IProfileManager.ts deleted file mode 100644 index 6b3ebc1..0000000 --- a/packages/interfaces/src/Services/IProfileManager.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { ReadonlySignal } from '@preact/signals-react'; -import { ILibrary } from '../MetaData'; -import { ITask } from '../ITask'; -import { IProfile } from '../Profile'; -import { IIpfsService } from './IIpfsService'; - -export const IProfileManagerSymbol = Symbol.for('IProfileManager'); - -/** - * Manages a profile. - */ -export interface IProfileManager { - /** - * Starts the service. - */ - start(): Promise; - - /** - * Stops the service. - */ - stop(): Promise; - - /** - * Currently available libraries. - */ - libraries: Map>; - - /** - * Current status of the service. - */ - state: ReadonlySignal; - - /** - * Current tasks of the service. - */ - tasks: ReadonlySignal; - - /** - * The profile of the service. - */ - profile: IProfile; - - /** - * Ipfs service of the profile if started. - */ - ipfs: undefined | IIpfsService; -} - -export enum ProfileManagerState { - Running, - Stopped, - Error, -} diff --git a/packages/interfaces/src/Services/index.ts b/packages/interfaces/src/Services/index.ts index 24cd4c7..8a3a441 100644 --- a/packages/interfaces/src/Services/index.ts +++ b/packages/interfaces/src/Services/index.ts @@ -1,7 +1,7 @@ export { type IConfigurationService } from './IConfigurationService'; export { IHotkeyServiceSymbol, type IHotkeyService, type IHotkey } from './IHotkeyService'; +export { type IIndexManager, IIndexManagerSymbol } from './IIndexManager'; export { type IIpfsService, IIpfsServiceSymbol } from './IIpfsService'; export { type IKeyValueStore, IKeyValueStoreSymbol } from './IKeyValueStore'; export { type INodeService } from './INodeService'; export { type IObjectStore, IObjectStoreSymbol } from './IObjectStore'; -export { type IProfileManager, ProfileManagerState, IProfileManagerSymbol } from './IProfileManager'; diff --git a/packages/ui/src/IpmcLauncher.tsx b/packages/ui/src/IpmcLauncher.tsx index 5e8af3f..db8cc67 100644 --- a/packages/ui/src/IpmcLauncher.tsx +++ b/packages/ui/src/IpmcLauncher.tsx @@ -1,8 +1,8 @@ import React, { PropsWithChildren } from 'react'; import { useComputed, useSignal } from '@preact/signals-react'; import { useTranslation } from './hooks'; -import { IConfigurationService, IIpfsService, IIpfsServiceSymbol, INodeService, IProfileManager, IProfileManagerSymbol, isInternalProfile, isRemoteProfile } from 'ipmc-interfaces'; -import { RemoteProfileManager, SimpleProfileManager } from 'ipmc-core'; +import { IConfigurationService, IIpfsService, IIpfsServiceSymbol, INodeService, IProfile, IProfileSymbol, isInternalProfile, isRemoteProfile } from 'ipmc-interfaces'; +import { createRemoteIpfs } from 'ipmc-core'; import { IpmcApp } from './IpmcApp'; import { Alert, Box, Button, ButtonGroup, Stack } from '@mui/material'; import { ProfileSelector } from './components/molecules/ProfileSelector'; @@ -28,32 +28,27 @@ export type IReturnToLauncherAction = () => void; export function IpmcLauncher(props: PropsWithChildren) { const _t = useTranslation(); - const profileManager = useSignal(undefined); const state = useSignal(LoadState.Idle); + const node = useSignal(undefined); + const profile = useSignal(undefined); async function start(name: string) { if (name == undefined) return; const currentProfile = props.configService.getProfile(name); if (currentProfile != undefined) { + profile.value = currentProfile; try { state.value = LoadState.Starting; - let manager: IProfileManager | undefined; if (isRemoteProfile(currentProfile)) { - manager = new RemoteProfileManager(currentProfile); + node.value = await createRemoteIpfs(currentProfile.url); } if (isInternalProfile(currentProfile)) { - manager = new SimpleProfileManager(await props.nodeService.create(currentProfile), currentProfile); + node.value = await props.nodeService.create(currentProfile); } - if (manager) { - await manager.start(); - profileManager.value = manager; - state.value = LoadState.Ready; - } else { - state.value = LoadState.Error; - } + state.value = LoadState.Ready; } catch (ex) { console.error(ex); state.value = LoadState.Error; @@ -65,8 +60,9 @@ export function IpmcLauncher(props: PropsWithChildren) { if (node.value != undefined) { state.value = LoadState.Stopping; try { - await profileManager.value!.stop(); - profileManager.value = undefined; + await node.value!.stop(); + node.value = undefined; + profile.value = undefined; } catch (ex) { console.error(ex); state.value = LoadState.Error; @@ -75,11 +71,10 @@ export function IpmcLauncher(props: PropsWithChildren) { state.value = LoadState.Idle; } - const node = useComputed(() => profileManager.value?.ipfs); - const content = useComputed(() => { - const manager = profileManager.value; + const ipfs = node.value; const currentState = state.value; + const currentProfile = profile.value; switch (currentState) { case LoadState.Error: @@ -105,8 +100,8 @@ export function IpmcLauncher(props: PropsWithChildren) { case LoadState.Ready: return ( { - app.registerConstant(manager!.ipfs!, IIpfsServiceSymbol); - app.registerConstant(manager!, IProfileManagerSymbol); + app.registerConstant(ipfs!, IIpfsServiceSymbol); + app.registerConstant(currentProfile!, IProfileSymbol); app.registerConstant(stop, IReturnToLauncherActionSymbol); }} /> ); diff --git a/packages/ui/src/components/organisms/AppBar.tsx b/packages/ui/src/components/organisms/AppBar.tsx index b54c273..6f9e74c 100644 --- a/packages/ui/src/components/organisms/AppBar.tsx +++ b/packages/ui/src/components/organisms/AppBar.tsx @@ -4,7 +4,7 @@ import { ConnectionStatus } from "../molecules/ConnectionStatus"; import { LanguageSelector } from "../molecules/LanguageSelector"; import { ThemeToggle } from '../atoms/ThemeToggle'; import { useTranslation } from '../../hooks/useTranslation'; -import { IIpfsService, IIpfsServiceSymbol, IProfileManager, IProfileManagerSymbol } from 'ipmc-interfaces'; +import { IIpfsService, IIpfsServiceSymbol, IProfile, IProfileSymbol } from 'ipmc-interfaces'; import { useTheme } from '../../context/ThemeContext'; import { useOptionalService, useService } from '../../context'; import { IReturnToLauncherAction, IReturnToLauncherActionSymbol } from '../../IpmcLauncher'; @@ -12,7 +12,7 @@ import { IReturnToLauncherAction, IReturnToLauncherActionSymbol } from '../../Ip export function AppBar() { const shutdownProfile = useOptionalService(IReturnToLauncherActionSymbol); const ipfs = useService(IIpfsServiceSymbol); - const { profile } = useService(IProfileManagerSymbol); + const profile = useService(IProfileSymbol); const _t = useTranslation(); const { darkMode } = useTheme(); diff --git a/packages/ui/src/components/organisms/Library.tsx b/packages/ui/src/components/organisms/Library.tsx index 9fbbe60..d1401cf 100644 --- a/packages/ui/src/components/organisms/Library.tsx +++ b/packages/ui/src/components/organisms/Library.tsx @@ -4,9 +4,8 @@ import { FileView } from './FileView'; import { ReadonlySignal, useComputed, useSignal } from '@preact/signals-react'; import { LoadScreen } from '../molecules/LoadScreen'; import { Grid } from '@mui/material'; -import { IFileInfo, IProfileManager, IProfileManagerSymbol } from 'ipmc-interfaces'; +import { IFileInfo, IIndexManager, IIndexManagerSymbol } from 'ipmc-interfaces'; import { Display } from '../pages/LibraryManager'; -import { useWatcher } from '../../hooks'; import { ErrorBoundary } from '../atoms/ErrorBoundary'; import { useService } from '../../context/AppContext'; @@ -16,10 +15,8 @@ export function Library(props: { library: string; }) { const { display, library } = props; - const profile = useService(IProfileManagerSymbol); - + const index = useService(IIndexManagerSymbol).indexes.get(library)!; const selected = useSignal(undefined); - const index = useWatcher<{ cid: string; values: IFileInfo[]; } | undefined>(profile.libraries.get(library)?.value.index as { cid: string; values: IFileInfo[]; } | undefined); const detail = useComputed(() => selected.value !== undefined ? ( @@ -40,7 +37,7 @@ export function Library(props: { ) : ( <> - {i.values.map(v => ( + {i.index.map(v => ( (IProfileManagerSymbol); const _t = useTranslation(); - const status = useComputed(() => profile.tasks.value.length > 0 ? ( + /*const status = useComputed(() => profile.tasks.value.length > 0 ? ( {profile.tasks.value.map(t => ( @@ -22,10 +17,10 @@ export function LibraryHomeScreen() { ))} - ) : undefined); + ) : undefined);*/ return ( {_t('Home')} - {status} + {/*status*/} ); } diff --git a/packages/ui/src/components/pages/LibraryManager.tsx b/packages/ui/src/components/pages/LibraryManager.tsx index b191b76..7ac9275 100644 --- a/packages/ui/src/components/pages/LibraryManager.tsx +++ b/packages/ui/src/components/pages/LibraryManager.tsx @@ -6,7 +6,7 @@ import QuestionMarkIcon from '@mui/icons-material/QuestionMark'; import { Box, List, ListItem, ListItemButton, ListItemIcon, ListItemText, Paper, Stack } from '@mui/material'; import { Signal, useComputed, useSignal } from "@preact/signals-react"; import React from "react"; -import { ILibrary, IProfileManager, IProfileManagerSymbol } from "ipmc-interfaces"; +import { ILibrary, IProfile, IProfileSymbol } from "ipmc-interfaces"; import { LibraryAppBar } from "../organisms/LibraryAppBar"; import { LibraryHomeScreen } from '../organisms/LibraryHomeScreen'; import { useTranslation } from '../../hooks/useTranslation'; @@ -21,9 +21,9 @@ const icons = { } as { [key: string]: any; }; export function LibraryManager() { - const profile = useService(IProfileManagerSymbol); + const profile = useService(IProfileSymbol); const _t = useTranslation(); - const libraries = profile.profile.libraries; + const libraries = profile.libraries; const library = useSignal(undefined); const display = useSignal(Display.Poster); const query = useSignal('');