<commit_before>import React from "react";
import ReactDOM from "react-dom";
import createStyled from "../../modules/core/createStyled";
import { Base } from "../Base";
import { IAppContext, AppContext } from "../../modules/core/AppContext";
import { IHistoryContext } from "history-next";
import { PromiseFactory } from "../../modules/StaticCache";
import { ContentManagerFactory } from "../../modules/content-manager/ContentManagerFactory";
import LoadingView from "../LoadingView/index";
import { IHeadlessRendererState } from "../../modules/core/RendererState";
import { IHeadlessContentManager, IDomContentManager } from "../../modules/content-manager/ContentManager";
import { DomUtils } from "../../modules/utils/index";

interface ContentViewState {
    component: JSX.Element;
}

export class ContentView extends Base<any, ContentViewState> {
    private _contentManager: IDomContentManager | IHeadlessContentManager;
    private _pendingRequest: any = null;
    private _pendingAnimationTimeline: TimelineMax;
    private _suspendAnimations = false;
    private _requestStartedViewUpdateTimer: any = null;
    private _diposeHistoryListener: () => void = null;

    constructor(props: any, context: any) {
        super(props, context);
        this.state = { component: null };
        let services = this.getServices();
        this._contentManager = ContentManagerFactory.create(
            services.localStoreProvider(), services.sessionStoreProvider());
        this.onContentReady = this.onContentReady.bind(this);
        this.onRequestStarted = this.onRequestStarted.bind(this);
        this.onHistoryChange = this.onHistoryChange.bind(this);
    }

    componentWillMount() {
        super.componentWillMount();
        if (__DOM__) {
            let cm = this._contentManager as IDomContentManager;
            cm.addListener(cm.contentReadyEventName, this.onContentReady);
            cm.addListener(cm.requestStartEventName, this.onRequestStarted);
            this._diposeHistoryListener = this.getServices().history.listen(context => {
                this.onHistoryChange();
                return PromiseFactory.EmptyResolved;
            });
            this.onHistoryChange();
        }
    }

    componentWillUnmount() {
        if (__DOM__) {
            let cm = this._contentManager as IDomContentManager;
            cm.removeListener(cm.contentReadyEventName, this.onContentReady);
            cm.removeListener(cm.requestStartEventName, this.onRequestStarted);
            this._diposeHistoryListener();
        }

        this.clearPendingTimeline();
        super.componentWillUnmount();
    }

    componentDidMount() {
        this.setFocusContentView();
    }

    componentWillUpdate(nextProps: any, nextState: ContentViewState) {
        if (this.state.component !== nextState.component) {
            this.clearPendingTimeline();
        }
    }

    componentDidUpdate(prevProps: any, prevState: ContentViewState) {
        if (this.state.component !== prevState.component) {
            if (this._pendingRequest) return;
            if (this._suspendAnimations) {
                // Currently animations are suspending only if the Dom is pre-rendered.
                // So flip it back on. Can move it out later if disabling animations is 
                // to be controlled manually.
                this._suspendAnimations = false;
            }
            else {
                this.animateViewIn(this.getRootElement(), this.getContentElementIfAvailable());
            }
            this.setFocusContentView();
        }
    }

    clearPendingTimeline() {
        if (this._pendingAnimationTimeline != null) {
            this._pendingAnimationTimeline.render(this._pendingAnimationTimeline.endTime(), false, true);
            this._pendingAnimationTimeline.kill();
            this._pendingAnimationTimeline = null;
        }
    }

    getComponentForServerEnvironment() {
        if (!__DOM__) {
            let cm = this._contentManager as IHeadlessContentManager;
            let services = this.getServices();
            let pathname = services.history.current.pathname;
            let rendererState = services.rendererStateProvider() as IHeadlessRendererState;
            let resolution = cm.resolve(pathname);
            rendererState.data = cm.getContentForResolution(resolution);
            rendererState.isPrerenderedDom = true;
            return cm.getComponentForResolution(resolution);
        }
        return null;
    }

    onHistoryChange() {
        this.clearPendingTimeline();
        this.clearRequestStartedViewUpdateTimer();
        let cm = this._contentManager as IDomContentManager;
        if (cm.hasPathChanged(this.context)) {
            let req = this._pendingRequest;
            if (req !== null) {
                req.abort();
                this._pendingRequest = null;
            }
            if (cm.isDomPrerendered()) {
                this._suspendAnimations = true;
                cm.setDomPrerendered(false);
            }
            cm.queueContext(this.context);
        }
    }

    onContentReady(component: JSX.Element) {
        if (this._pendingRequest !== null) {
            this._pendingRequest = null;
        }
        this.clearRequestStartedViewUpdateTimer();
        let cm = this._contentManager as IDomContentManager;
        if (this._suspendAnimations) {
            this.setState({ component });
        } else {
            this.animateViewOut(this.getRootElement())
                .then(() => {
                    this.setState({ component });
                });
        }
    }

    animateViewOut(rootElement: HTMLElement) {
        return new Promise((res, reject) => {
            this.clearPendingTimeline();
            if (!rootElement) {
                res(); return;
            }
            let t = new TimelineMax();
            // Do the scrolling manually, by breaking the overflow visibility
            // and translating the element across, with forced hardware acceleration.
            // This is significantly faster on lower mobile devices.<commit_msg>fix: enforce update on history change without path change<commit_after>import React from "react";
import ReactDOM from "react-dom";
import createStyled from "../../modules/core/createStyled";
import { Base } from "../Base";
import { IAppContext, AppContext } from "../../modules/core/AppContext";
import { IHistoryContext } from "history-next";
import { PromiseFactory } from "../../modules/StaticCache";
import { ContentManagerFactory } from "../../modules/content-manager/ContentManagerFactory";
import LoadingView from "../LoadingView/index";
import { IHeadlessRendererState } from "../../modules/core/RendererState";
import { IHeadlessContentManager, IDomContentManager } from "../../modules/content-manager/ContentManager";
import { DomUtils } from "../../modules/utils/index";

interface ContentViewState {
    component: JSX.Element;
}

export class ContentView extends Base<any, ContentViewState> {
    private _contentManager: IDomContentManager | IHeadlessContentManager;
    private _pendingRequest: any = null;
    private _pendingAnimationTimeline: TimelineMax;
    private _suspendAnimations = false;
    private _requestStartedViewUpdateTimer: any = null;
    private _diposeHistoryListener: () => void = null;

    constructor(props: any, context: any) {
        super(props, context);
        this.state = { component: null };
        let services = this.getServices();
        this._contentManager = ContentManagerFactory.create(
            services.localStoreProvider(), services.sessionStoreProvider());
        this.onContentReady = this.onContentReady.bind(this);
        this.onRequestStarted = this.onRequestStarted.bind(this);
        this.onHistoryChange = this.onHistoryChange.bind(this);
    }

    componentWillMount() {
        super.componentWillMount();
        if (__DOM__) {
            let cm = this._contentManager as IDomContentManager;
            cm.addListener(cm.contentReadyEventName, this.onContentReady);
            cm.addListener(cm.requestStartEventName, this.onRequestStarted);
            this._diposeHistoryListener = this.getServices().history.listen(context => {
                this.onHistoryChange();
                return PromiseFactory.EmptyResolved;
            });
            this.onHistoryChange();
        }
    }

    componentWillUnmount() {
        if (__DOM__) {
            let cm = this._contentManager as IDomContentManager;
            cm.removeListener(cm.contentReadyEventName, this.onContentReady);
            cm.removeListener(cm.requestStartEventName, this.onRequestStarted);
            this._diposeHistoryListener();
        }

        this.clearPendingTimeline();
        super.componentWillUnmount();
    }

    componentDidMount() {
        this.setFocusContentView();
    }

    componentWillUpdate(nextProps: any, nextState: ContentViewState) {
        if (this.state.component !== nextState.component) {
            this.clearPendingTimeline();
        }
    }

    componentDidUpdate(prevProps: any, prevState: ContentViewState) {
        if (this.state.component !== prevState.component) {
            if (this._pendingRequest) return;
            if (this._suspendAnimations) {
                // Currently animations are suspending only if the Dom is pre-rendered.
                // So flip it back on. Can move it out later if disabling animations is 
                // to be controlled manually.
                this._suspendAnimations = false;
            }
            else {
                this.animateViewIn(this.getRootElement(), this.getContentElementIfAvailable());
            }
            this.setFocusContentView();
        }
    }

    clearPendingTimeline() {
        if (this._pendingAnimationTimeline != null) {
            this._pendingAnimationTimeline.render(this._pendingAnimationTimeline.endTime(), false, true);
            this._pendingAnimationTimeline.kill();
            this._pendingAnimationTimeline = null;
        }
    }

    getComponentForServerEnvironment() {
        if (!__DOM__) {
            let cm = this._contentManager as IHeadlessContentManager;
            let services = this.getServices();
            let pathname = services.history.current.pathname;
            let rendererState = services.rendererStateProvider() as IHeadlessRendererState;
            let resolution = cm.resolve(pathname);
            rendererState.data = cm.getContentForResolution(resolution);
            rendererState.isPrerenderedDom = true;
            return cm.getComponentForResolution(resolution);
        }
        return null;
    }

    onHistoryChange() {
        this.clearPendingTimeline();
        this.clearRequestStartedViewUpdateTimer();
        let cm = this._contentManager as IDomContentManager;
        if (cm.hasPathChanged(this.context)) {
            let req = this._pendingRequest;
            if (req !== null) {
                req.abort();
                this._pendingRequest = null;
            }
            if (cm.isDomPrerendered()) {
                this._suspendAnimations = true;
                cm.setDomPrerendered(false);
            }
            cm.queueContext(this.context);
        } else {
            this.forceUpdate();
        }
    }

    onContentReady(component: JSX.Element) {
        if (this._pendingRequest !== null) {
            this._pendingRequest = null;
        }
        this.clearRequestStartedViewUpdateTimer();
        let cm = this._contentManager as IDomContentManager;
        if (this._suspendAnimations) {
            this.setState({ component });
        } else {
            this.animateViewOut(this.getRootElement())
                .then(() => {
                    this.setState({ component });
                });
        }
    }

    animateViewOut(rootElement: HTMLElement) {
        return new Promise((res, reject) => {
            this.clearPendingTimeline();
            if (!rootElement) {
                res(); return;
            }
            let t = new TimelineMax();
            // Do the scrolling manually, by breaking the overflow visibility
            // and translating the element across, with forced hardware acceleration.
            // This is significantly faster on lower mobile devices.
{'fraction_non_alphanumeric': 0.10047924620258306, 'fraction_numerical': 0.0, 'mean_word_length': 2.320388349514563, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '232324', 'n_tokens_mistral': 3093, 'n_tokens_neox': 3032, 'n_words': 653}