Commit cf3f4aa3 authored by Laurent Wouters's avatar Laurent Wouters
Browse files

[fix] Support caching of view implementations in the browser

parent cf1ba690563b
......@@ -49,6 +49,7 @@ require("./view-defaults-impl");
*/
class LDBrowserData {
constructor(observation: ResourceObservedData) {
this.renderer = implementation.newRenderer(getResourceContent);
let init = new ResourceData();
init.observations = observation;
init.command = new ResourceUserCommand();
......@@ -57,6 +58,10 @@ class LDBrowserData {
this.byResource[observation.url] = init;
this.storeCache = {};
}
/**
* The view renderer for the browser
*/
renderer: implementation.CachingViewRenderer;
/**
* The history of resources
*/
......@@ -310,8 +315,8 @@ function onReachedResource(resource: ResourceData): void {
getViewRegistry()
.then((registry: definition.ViewRegistry) => {
currentApp.onLoad("Fetching views");
implementation
.newRenderer(registry, getResourceContent)
currentBrowser.renderer
.refresh(registry)
.then((renderer: application.ViewRenderer) => {
currentApp.onLoad("Rendering");
let rendering = renderer.render(context, context.root);
......@@ -341,7 +346,9 @@ function onReachedResource(resource: ResourceData): void {
* When a resource has been suggested by the rendered view for expansion
* @param uri The URI of the resource
*/
function onSuggestedResource(uri: string): void {}
function onSuggestedResource(uri: string): void {
}
/**
* Creates a new rendering context
......
......@@ -28,7 +28,8 @@ import {
import {
ViewDescriptor,
ViewRegistry,
ViewResourceContentResolver
ViewResourceContentResolver,
ViewDescriptors
} from "./view-def";
/**
......@@ -139,48 +140,6 @@ function fetchImplementation(
);
}
/**
* Loads all implementations for the registered views
* @param registry The registry to load
* @param resolver The content resolver to use
*/
function loadImplementations(
registry: ViewRegistry,
resolver: ViewResourceContentResolver
): Promise<ViewImplementations> {
return new Promise<ViewImplementations>(
(
resolve: (impls: ViewImplementations) => void,
reject: (reason: any) => void
) => {
var finished = 0;
var target = Object.keys(registry.descriptors).length;
var implementations: ViewImplementations = {};
function onPartFinished() {
finished += 1;
if (finished >= target) resolve(implementations);
}
Object.keys(registry.descriptors).map((id: string) => {
let descriptor = registry.descriptors[id];
fetchImplementation(descriptor, resolver)
.then((implementation: ViewImplementation) => {
implementations[id] = implementation;
onPartFinished();
})
.catch((reason: string) => {
console.log(
"Failed to fetch implementation for view " +
descriptor.name +
": " +
reason
);
onPartFinished();
});
});
}
);
}
/**
* A prioritized view implementation
*/
......@@ -223,28 +182,43 @@ function resolveViewFor(
return sorted[0].implementation;
}
/**
* A view renderer that caches the view implementations
*/
export interface CachingViewRenderer extends ViewRenderer {
/**
* Refreshes this view renderer
* @param registry The current view registry
*/
refresh(registry: ViewRegistry): Promise<CachingViewRenderer>;
}
/**
* A renderer for an application
*/
class ViewRendererImpl implements ViewRenderer {
class ViewRendererImpl implements CachingViewRenderer {
/**
* Initializes a renderer
* @param registry The registry to use
* @param implementations The view implementations
* @param resolver The content resolver to use
*/
constructor(registry: ViewRegistry, implementations: ViewImplementations) {
this.registry = registry;
this.implementations = implementations;
constructor(resolver: ViewResourceContentResolver) {
this.descriptors = {};
this.implementations = {};
this.resolver = resolver;
}
/**
* The registry to use
* The registry of descriptors
*/
registry: ViewRegistry;
descriptors: ViewDescriptors;
/**
* The view implementations
*/
implementations: ViewImplementations;
/**
* The content resolver to use
*/
resolver: ViewResourceContentResolver;
/**
* Selects the language to use for a target resource
......@@ -295,28 +269,71 @@ class ViewRendererImpl implements ViewRenderer {
result.viewId = view.descriptor.identifier; // ensure view id is correct
return result;
}
/**
* Refreshes this view renderer
* @param registry The current view registry
*/
refresh(registry: ViewRegistry): Promise<CachingViewRenderer> {
let self = this;
return new Promise<CachingViewRenderer>(
(
resolve: (renderer: CachingViewRenderer) => void,
reject: (reason: any) => void
) => {
let toAdd: ViewDescriptor[] = [];
Object.keys(registry.descriptors).forEach((id: string) => {
let candidate = self.descriptors[id];
if (candidate == null || candidate == undefined) {
toAdd.push(registry.descriptors[id]);
}
});
Object.keys(self.descriptors).forEach((id: string) => {
let candidate = registry.descriptors[id];
if (candidate == null || candidate == undefined) {
// has been deleted
delete self.descriptors[id];
delete self.implementations[id];
}
});
if (toAdd.length == 0) {
resolve(self);
return;
}
var finished = 0;
function onPartFinished() {
finished += 1;
if (finished >= toAdd.length) resolve(self);
}
toAdd.forEach((descriptor: ViewDescriptor) => {
fetchImplementation(descriptor, self.resolver)
.then((implementation: ViewImplementation) => {
self.descriptors[descriptor.identifier] = descriptor;
self.implementations[descriptor.identifier] = implementation;
onPartFinished();
})
.catch((reason: string) => {
console.log(
"Failed to fetch implementation for view " +
descriptor.name +
": " +
reason
);
onPartFinished();
});
});
}
);
}
}
/**
* Creates a new view renderer
* @param registry The view registry to use
* @param resolver The content resolver to use
*/
export function newRenderer(
registry: ViewRegistry,
resolver: ViewResourceContentResolver
): Promise<ViewRenderer> {
return new Promise<ViewRenderer>(
(
resolve: (renderer: ViewRenderer) => void,
reject: (reason: any) => void
) => {
loadImplementations(registry, resolver).then(
(impls: ViewImplementations) => {
let renderer = new ViewRendererImpl(registry, impls);
resolve(renderer);
}
);
}
);
): CachingViewRenderer {
return new ViewRendererImpl(resolver);
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment