public HUpdate(int cycle, HElement page, object state, TimeSpan elapsed) { this.Cycle = cycle; this.Page = page; this.State = state; this.Elapsed = elapsed; }
public static void PushUpdate(string frame, int cycle, HElement page, object state, TimeSpan elapsed) { for (;;) { HFrame hframe; if (Frames.TryGetValue(frame, out hframe)) { var nextFrame = hframe.With(updates: hframe.Updates.Add(cycle, new HUpdate(cycle, page, state, elapsed))); if (Frames.TryUpdate(frame, nextFrame, hframe)) { return; } } else { if (Frames.TryAdd(frame, new HFrame(cycle, ImmutableDictionary <int, HUpdate> .Empty.Add(cycle, new HUpdate(cycle, page, state, elapsed))))) { return; } } } }
static HElement FirstHtmlTransformer(HElement element) { return(new HElement("html", element.Element("head"), new HElement("body", ""))); }
public static TResponse Process <TRequest, TResponse, TState>(TRequest request, IRequestAdapter <TRequest, TResponse> requestAdapter, Func <TState, JsonData[], TRequest, HtmlResult <HElement> > page) where TState : class, new() { if (requestAdapter.IsGetMethod(request)) { var result = page(new TState(), Array <JsonData> .Empty, request); var rawResponse = requestAdapter.RawResponse(result); if (rawResponse != null) { return(rawResponse); } var html = result.Html; var head = html.Element("head") ?? new HElement("head"); var startHead = new HElement(head.Name, head.Attributes, Scripts(frame: Guid.NewGuid().ToString(), refreshPeriod: result.RefreshPeriod ?? TimeSpan.FromSeconds(10)), head.Nodes ); var firstHtmlTransformer = result.As <HtmlResult>()?.FirstHtmlTransformer ?? FirstHtmlTransformer; html = firstHtmlTransformer(new HElement("html", startHead, html.Nodes.Where(node => node.As <HElement>()?.Name.LocalName != "head"))); var toHtmlText = result.As <HtmlResult>()?.ToHtmlText ?? ToHtmlText; return(requestAdapter.ToResponse(toHtmlText(html), "text/html", result)); } else { var json = Parse(requestAdapter.Content(request)); var route = requestAdapter.Frame(request) ?? "<null>"; var frame = route + ":" + json.JPath("frame")?.ToString(); var cycle = ConvertHlp.ToInt(json.JPath("cycle")).OrDefault(0); var prev = PopUpdate(frame, cycle); var json_commands = (json.JPath("commands").As <JArray>()?.Select(j => new JsonData(j)).ToArray()).OrEmpty(); HtmlResult <HElement> result = null; var watch = System.Diagnostics.Stopwatch.StartNew(); try { result = page(prev?.Item2?.State.As <TState>() ?? new TState(), json_commands, request); } catch (Exception exc) //HACK ловятся все ошибки для того, чтобы не зациклилась страница. Добавить обработку ошибок на сторону js. { result = new HtmlResult <HElement> { State = prev.Item2.State, Html = prev.Item2.Page }; } watch.Stop(); var rawResponse = requestAdapter.RawResponse(result); if (rawResponse != null) { return(rawResponse); } var isPartial = result.Html.Name.LocalName != "html"; var toBody = isPartial ? html => html : (Func <HElement, HElement>)(html => html?.Element("body")); var js_updates = HtmlJavaScriptDiffer.JsSync(new HElementProvider(), toBody(prev?.Item2?.Page), toBody(result.Html)).ToArray(); var jupdate = new Dictionary <string, object>() { { "cycle", prev.Item1 }, { "prev_cycle", cycle }, { "processed_commands", json_commands.Length }, { "updates", js_updates } }; PushUpdate(frame, prev.Item1, result.Html, result.State, watch.Elapsed); return(requestAdapter.ToResponse(JsonConvert.SerializeObject(jupdate), "application/javascript", result)); } }
static string ToHtmlText(HElement element) { return(element?.ToHtmlText()); }