Skip to content

Commit

Permalink
Add TaskManager
Browse files Browse the repository at this point in the history
  • Loading branch information
undyingwraith committed Jun 19, 2024
1 parent c543715 commit 34e2403
Show file tree
Hide file tree
Showing 16 changed files with 125 additions and 37 deletions.
3 changes: 3 additions & 0 deletions packages/core/src/Modules/CoreModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ import { MemoryKeyValueStore } from '../Services/MemoryKeyValueStore';
import { ObjectStore } from '../Services/ObjectStore';
import { IModule } from './IModule';
import { IndexManager } from '../Services/IndexManager';
import { TaskManager } from '../Services/TaskManager';
import { ITaskManagerSymbol } from 'ipmc-interfaces';

export const CoreModule: IModule = (app) => {
app.register(MemoryKeyValueStore, IKeyValueStoreSymbol);
app.register(ObjectStore, IObjectStoreSymbol);
app.register(IndexManager, IIndexManagerSymbol);
app.register(TaskManager, ITaskManagerSymbol);
};
17 changes: 9 additions & 8 deletions packages/core/src/Services/IndexManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ 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';
import { ITaskManager, ITaskManagerSymbol } from 'ipmc-interfaces';

@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,
@inject(ITaskManagerSymbol) private readonly taskManager: ITaskManager
) {
for (const lib of this.profile.libraries) {
this.libraries.set(lib.name, new Signal<ILibrary>(lib));
Expand Down Expand Up @@ -47,14 +49,13 @@ export class IndexManager implements IIndexManager {
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);
}));
this.taskManager.runTask({
task: () => this.updateLibrary(lib),
title: '',
onEnd: () => {
this.updates.delete(lib.name);
},
});
}
}
}
Expand Down
21 changes: 21 additions & 0 deletions packages/core/src/Services/TaskManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Signal } from '@preact/signals-core';
import { injectable } from 'inversify';
import { ITask, ITaskManager, ITaskStatus } from 'ipmc-interfaces';
import { uuid } from '../util';

@injectable()
export class TaskManager implements ITaskManager {
public status: Signal<ITaskStatus[]> = new Signal<ITaskStatus[]>([]);

public runTask(task: ITask): void {
const status: ITaskStatus = {
id: uuid(),
title: task.title,
};
this.status.value = [...this.status.value, status];
task.task()
.finally(() => {
this.status.value = this.status.value.filter(s => s.id !== status.id);
});
}
}
4 changes: 1 addition & 3 deletions packages/core/src/util/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
<<<<<<< HEAD
export { createFilter } from './createFilter';
=======
export { createRemoteIpfs } from './createRemoteIpfs';
>>>>>>> b91302fed0641a56d3300fbe3e23c06e5913baf1
export { uuid } from './uuid';
5 changes: 5 additions & 0 deletions packages/core/src/util/uuid.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export function uuid() {
return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, c =>
(+c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> +c / 4).toString(16)
);
}
7 changes: 0 additions & 7 deletions packages/interfaces/src/ITask.ts

This file was deleted.

21 changes: 21 additions & 0 deletions packages/interfaces/src/Services/ITaskManager/ITask.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* A long running task.
*/
export interface ITask {
title: string;

/**
* The task to run.
*/
task: () => Promise<void>;

/**
* Start event handler.
*/
onStart?: () => void | Promise<void>;

/**
* End event handler.
*/
onEnd?: () => void | Promise<void>;
}
21 changes: 21 additions & 0 deletions packages/interfaces/src/Services/ITaskManager/ITaskManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { ITask } from './ITask';
import { ITaskStatus } from './ITaskStatus';
import { Signal } from '@preact/signals-core';

export const ITaskManagerSymbol = Symbol.for('ITaskManager');

/**
* A Manager for long running {@link ITask}'s.
*/
export interface ITaskManager {
/**
* Instantly runs a long running {@link ITask}.
* @param task Task to execute.
*/
runTask(task: ITask): void;

/**
* Current status of running {@link ITask}'s.
*/
status: Signal<ITaskStatus[]>;
}
19 changes: 19 additions & 0 deletions packages/interfaces/src/Services/ITaskManager/ITaskStatus.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* Represents the status of an {@link ITask}
*/
export interface ITaskStatus {
/**
* Progress of the {@link ITask} (if available).
*/
progress?: number;

/**
* Title of the {@link ITask}.
*/
title: string;

/**
* Id of the {@link ITask}.
*/
id: string;
}
3 changes: 3 additions & 0 deletions packages/interfaces/src/Services/ITaskManager/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { type ITask } from './ITask';
export { type ITaskManager, ITaskManagerSymbol } from './ITaskManager';
export { type ITaskStatus } from './ITaskStatus';
1 change: 1 addition & 0 deletions packages/interfaces/src/Services/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './ITaskManager';
export { type IConfigurationService } from './IConfigurationService';
export { IHotkeyServiceSymbol, type IHotkeyService, type IHotkey } from './IHotkeyService';
export { type IIndexManager, IIndexManagerSymbol } from './IIndexManager';
Expand Down
1 change: 0 additions & 1 deletion packages/interfaces/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
export * from './MetaData';
export * from './Profile';
export * from './Services';
export type { ITask } from './ITask';
11 changes: 4 additions & 7 deletions packages/ui/src/IpmcApp.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React from 'react';
import { LibraryManager } from "./components/pages/LibraryManager";
import { Route, Switch } from 'wouter';
import { BrowserModule, CoreModule, IModule } from 'ipmc-core';
import React from 'react';
import { Switch } from 'wouter';
import { AppBar } from './components/organisms/AppBar';
import { LibraryManager } from "./components/pages/LibraryManager";
import { AppContextProvider } from './context';

// Setup translations
Expand All @@ -23,10 +23,7 @@ export function IpmcApp(props: IIpmcAppProps) {
}}>
<AppBar />
<Switch>
<Route path={'/'}>
<LibraryManager />
</Route>
<Route>404: No such page!</Route>
<LibraryManager />
</Switch>
</AppContextProvider>
);
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/components/organisms/Library.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export function Library(props: {
query: ReadonlySignal<string | undefined>;
library: string;
}) {
const { display, library } = props;
const { display, library, query } = props;
const indexManager = useService<IIndexManager>(IIndexManagerSymbol);
const index = useWatcher(indexManager.indexes.get(library)!.value);
const selected = useSignal<IFileInfo | undefined>(undefined);
Expand Down
15 changes: 10 additions & 5 deletions packages/ui/src/components/organisms/LibraryHomeScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import { Box, Typography } from '@mui/material';
import { Box, Card, CardContent, CardHeader, Stack, Typography } from '@mui/material';
import { useComputed } from '@preact/signals-react';
import { ITaskManager, ITaskManagerSymbol } from 'ipmc-interfaces';
import React from 'react';
import { useService } from '../../context';
import { useTranslation } from '../../hooks/useTranslation';
import { Loader } from '../atoms';

export function LibraryHomeScreen() {
const _t = useTranslation();
const taskManager = useService<ITaskManager>(ITaskManagerSymbol);

/*const status = useComputed(() => profile.tasks.value.length > 0 ? (
const status = useComputed(() => taskManager.status.value.length > 0 ? (
<Card>
<CardHeader title={_t('ActiveTasks')} />
{profile.tasks.value.map(t => (
{taskManager.status.value.map(t => (
<CardContent>
<Stack direction={"row"} gap={1}>
<Loader />
Expand All @@ -17,10 +22,10 @@ export function LibraryHomeScreen() {
</CardContent>
))}
</Card>
) : undefined);*/
) : undefined);

return (<Box>
<Typography>{_t('Home')}</Typography>
{/*status*/}
{status}
</Box>);
}
11 changes: 6 additions & 5 deletions packages/ui/src/components/pages/LibraryManager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import MusicNoteIcon from '@mui/icons-material/MusicNote';
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 { ILibrary, IProfile, IProfileSymbol } from "ipmc-interfaces";
import { IProfile, IProfileSymbol } from "ipmc-interfaces";
import React from "react";
import { Route, useLocation } from 'wouter';
import { useService } from '../../context/AppContext';
Expand All @@ -14,6 +14,7 @@ import { ErrorBoundary } from '../atoms/ErrorBoundary';
import { Library } from '../organisms/Library';
import { LibraryAppBar } from "../organisms/LibraryAppBar";
import { LibraryHomeScreen } from '../organisms/LibraryHomeScreen';
import { useWatcher } from '../../hooks';

const icons = {
movie: <MovieIcon />,
Expand All @@ -25,16 +26,16 @@ export function LibraryManager() {
const profile = useService<IProfile>(IProfileSymbol);
const _t = useTranslation();
const libraries = profile.libraries;
const library = useSignal<ILibrary | undefined>(undefined);
const display = useSignal<Display>(Display.Poster);
const query = useSignal<string>('');
const [_, setLocation] = useLocation();
const [loc, setLocation] = useLocation();
const location = useWatcher(loc);

const sidebar = useComputed(() => (
<List>
<ListItem disablePadding>
<ListItemButton
selected={library.value == undefined}
selected={location.value === '/'}
onClick={() => {
setLocation('/');
}}>
Expand All @@ -47,7 +48,7 @@ export function LibraryManager() {
{libraries.map((lib) => (
<ListItem key={lib.name} disablePadding>
<ListItemButton
selected={library.value?.name == lib.name}
selected={location.value === '/' + lib.name}
onClick={() => {
setLocation('/' + lib.name);
}}>
Expand Down

0 comments on commit 34e2403

Please sign in to comment.