Integrate supported ops into the UI

This commit is contained in:
Ingvar Stepanyan
2021-07-26 13:09:10 +00:00
parent 95ed711729
commit e3ea463db5
6 changed files with 49 additions and 44 deletions

View File

@@ -185,12 +185,6 @@ class Context {
}); });
} }
void triggerCapture() {
gpp_rethrow([=]() {
gpp_try(gp_camera_trigger_capture(camera.get(), context.get()));
});
}
private: private:
gpp_unique_ptr<Camera, gp_camera_unref> camera; gpp_unique_ptr<Camera, gp_camera_unref> camera;
gpp_unique_ptr<GPContext, gp_context_unref> context; gpp_unique_ptr<GPContext, gp_context_unref> context;

10
libapi.mjs.d.ts vendored
View File

@@ -13,6 +13,15 @@ export type Config = {
| { type: 'datetime'; value: number } | { type: 'datetime'; value: number }
); );
declare interface SupportedOps {
captureImage: boolean;
captureVideo: boolean;
captureAudio: boolean;
capturePreview: boolean;
config: boolean;
triggerCapture: boolean;
}
declare class Context { declare class Context {
configToJS(): Promise<Config & { type: 'window' }>; configToJS(): Promise<Config & { type: 'window' }>;
setConfigValue( setConfigValue(
@@ -22,6 +31,7 @@ declare class Context {
capturePreviewAsBlob(): Promise<Blob>; capturePreviewAsBlob(): Promise<Blob>;
captureImageAsFile(): Promise<File>; captureImageAsFile(): Promise<File>;
hasPendingEvent(): Promise<boolean>; hasPendingEvent(): Promise<boolean>;
supportedOps(): SupportedOps;
delete(): void; delete(): void;
isDeleted(): boolean; isDeleted(): boolean;

View File

@@ -143,7 +143,9 @@ class App extends Component {
'div', 'div',
{ class: 'pure-u-2-3' }, { class: 'pure-u-2-3' },
h(Preview, { h(Preview, {
getPreview: this.capturePreview getPreview: this.connection.supportedOps.capturePreview
? this.capturePreview
: undefined
}) })
), ),
h( h(
@@ -152,7 +154,9 @@ class App extends Component {
h( h(
'form', 'form',
{ class: 'pure-form pure-form-aligned' }, { class: 'pure-form pure-form-aligned' },
h(CaptureButton, { getFile: this.captureImage }), this.connection.supportedOps.triggerCapture
? h(CaptureButton, { getFile: this.captureImage })
: undefined,
h(Widget, { config: state.config, setValue: this.setValue }) h(Widget, { config: state.config, setValue: this.setValue })
) )
) )

View File

@@ -2,12 +2,13 @@ import initModule from '../libapi.mjs';
/** @typedef {import('../libapi.mjs').Context} Context */ /** @typedef {import('../libapi.mjs').Context} Context */
const ContextPromise = initModule().then(Module => Module.Context); const ModulePromise = initModule();
export async function connect() { export async function connect() {
let Context = await ContextPromise; const Module = await ModulePromise;
let context = await new Context(); let context = await new Module.Context();
let supportedOps = await context.supportedOps();
let queue = Promise.resolve(); let queue = Promise.resolve();
@@ -30,6 +31,7 @@ export async function connect() {
} }
return { return {
supportedOps,
schedule, schedule,
disconnect() { disconnect() {
context.delete(); context.delete();

View File

@@ -8,7 +8,7 @@ const Stats = isDebug
) )
: null; : null;
/** @extends Component<{ getPreview: () => Promise<Blob> }, { error?: string }> */ /** @extends Component<{ getPreview?: () => Promise<Blob> }, { error?: string }> */
export class Preview extends Component { export class Preview extends Component {
canvasHolderRef = createRef(); canvasHolderRef = createRef();
canvasRef = createRef(); canvasRef = createRef();
@@ -20,17 +20,15 @@ export class Preview extends Component {
return h( return h(
'div', 'div',
{ class: 'center-parent', ref: this.canvasHolderRef }, { class: 'center-parent', ref: this.canvasHolderRef },
this.state.error !this.props.getPreview
? h( ? h('div', { class: 'center' }, `Preview is unsupported`)
'div',
{ class: 'center' },
`Could not retrieve preview: ${this.state.error}`
)
: h('canvas', { class: 'center', ref: this.canvasRef }) : h('canvas', { class: 'center', ref: this.canvasRef })
); );
} }
async componentDidMount() { async componentDidMount() {
if (!this.props.getPreview) return;
let canvas = /** @type {HTMLCanvasElement} */ (this.canvasRef.current); let canvas = /** @type {HTMLCanvasElement} */ (this.canvasRef.current);
let canvasHolder = this.canvasHolderRef.current; let canvasHolder = this.canvasHolderRef.current;
@@ -70,13 +68,8 @@ export class Preview extends Component {
await new Promise(resolve => setTimeout(resolve, 1000)); await new Promise(resolve => setTimeout(resolve, 1000));
while (this.canvasRef.current) { while (this.canvasRef.current) {
let blob;
try { try {
blob = await this.props.getPreview(); let blob = await this.props.getPreview();
} catch (error) {
this.setState({ error: error.message });
return;
}
// If ratio is known; decode resized image right away - it's a bit faster. // If ratio is known; decode resized image right away - it's a bit faster.
// If it isn't known, retrieve entire image to calculate ratio from its dimensions. // If it isn't known, retrieve entire image to calculate ratio from its dimensions.
@@ -94,15 +87,15 @@ export class Preview extends Component {
updateCanvasSize(); updateCanvasSize();
} }
canvasCtx.transferFromImageBitmap(img); canvasCtx.transferFromImageBitmap(img);
} catch (error) {
console.error(error);
}
await new Promise(resolve => requestAnimationFrame(resolve)); await new Promise(resolve => requestAnimationFrame(resolve));
this.stats?.update(); this.stats?.update();
} }
} }
componentWillUnmount() { componentWillUnmount() {
this.resizeObserver.disconnect(); this.resizeObserver?.disconnect();
if (isDebug) {
this.canvasHolderRef.current.removeChild(this.stats.dom);
}
} }
} }

View File

@@ -68,11 +68,13 @@ export class Widget extends Component {
let { label, name } = config; let { label, name } = config;
let id = `config-${name}`; let id = `config-${name}`;
if (config.type === 'window' || config.type === 'section') { if (config.type === 'window' || config.type === 'section') {
let children = Object.values(config.children);
if (!children.length) return;
return h( return h(
'fieldset', 'fieldset',
{ id }, { id },
h('legend', {}, label), h('legend', {}, label),
Object.values(config.children).map(config => children.map(config =>
h(Widget, { key: config.name, config, setValue }) h(Widget, { key: config.name, config, setValue })
) )
); );