Пример #1
0
        },function(t){
            // localization initialized
            App.t = t;

            // Router
            App.Router = require('router')(App); // Passing "App" context to Router also


            // create the main context
            App.MainContext = Engine.createContext();
            App.MainContext.setPerspective(1000);

            // MainView
            App.MainView = new View();
            App.MainView.SizeMod = new StateModifier({
                size: [undefined, undefined]
            });
            App.MainContext.add(App.MainView.SizeMod).add(App.MainView);

            // Add main background image (pattern)
            App.MainBackground = new Surface({
                size: [undefined, undefined],
                classes: ['overall-background']
            });
            App.MainView.add(Utils.usePlane('background')).add(App.MainBackground); 

            // Create main Lightbox
            App.MainController = new Lightbox();
            App.MainController.getSize = function(){
                return [undefined, undefined];
            };
            App.MainController.resetOptions = function(){
                this.setOptions(Lightbox.DEFAULT_OPTIONS);
            };

            App.defaultSize = [window.innerWidth, window.innerHeight]; // use Device Width/height via native plugin? 
            // document.body.setAttribute('style',"width:"+window.innerWidth+"px;height:"+window.innerHeight+"px");
            // Utils.Notification.Toast(window.innerHeight);
            App.mainSize = [window.innerWidth, window.innerHeight];
            // Engine.nextTick(function() {
            //     console.log('After tick=' + App.MainContext.getSize());
            //     App.mainSize = App.MainContext.getSize();
            // });
    
            App.MainContext.on('resize', function(e) {
                // Utils.Notification.Toast('Resized');
                App.MainView.SizeMod.setSize(App.mainSize);
                // document.body.setAttribute('style',"height:"+App.mainSize[1]+"px");
            }.bind(this));


            // Layout for StatusBar / Controller
            if(App.Config.devicePlatform == 'ios'){
                App.StatusBar = true;
            }

            // Main Header/Topbar (for sharing)
            var createMainTopbar = function(){

                App.Views.MainTopBar = new View();

                App.Views.MainTopBar.Bg = new Surface({
                    size: [undefined, undefined],
                    classes: ['main-topbar-background']
                });

                App.Views.MainTopBar.Surface = new Surface({
                    content: template_mainTopBar(),
                    size: [undefined, true],
                    classes: ['main-topbar-content']
                });
                App.Views.MainTopBar.Surface.on('deploy', function(){
                    console.log(App.MainView.Layout.options.ratios);
                    Timer.setTimeout(function(){
                        App.MainView.Layout.setRatios(App.MainView.Layout.options.ratios);
                    },160);
                });

                App.Views.MainTopBar.getSize = function(val){
                    console.info('size');
                    return App.Views.MainTopBar.Surface.getSize(val);
                };

                App.Views.MainTopBar.add(Utils.usePlane('mainTopBar')).add(App.Views.MainTopBar.Surface);

            };
            createMainTopbar();

            // App.StatusBar set in device_ready
            App.DeviceReady.ready.then(function(){

                var ratios = [true, 1]; // including static MainTopBar
                if(App.StatusBar === true){
                    ratios = [true, true, 1]; 
                }
                App.MainView.Layout = new FlexibleLayout({
                    direction: 1,
                    ratios: ratios
                });
                App.MainView.Layout.Views = [];


                // iOS StatusBar (above MainController lightbox, if necessary)
                App.StatusBarView = new View();
                App.StatusBarView.getSize = function(){
                    return [undefined, 20];
                };
                App.StatusBarView.Surface = new Surface({
                    size: [undefined, 20],
                    classes: ['status-bar-default']
                });
                App.StatusBarView.add(Utils.usePlane('statusBar')).add(App.StatusBarView.Surface);
                if(App.StatusBar === true){
                    App.MainView.Layout.Views.push(App.StatusBarView);
                }

                // Push MainTopBar to FlexibleLayout Views
                App.MainView.Layout.Views.push(App.Views.MainTopBar);

                App.MainView.Layout.Views.push(App.MainController);
                App.MainView.Layout.sequenceFrom(App.MainView.Layout.Views);

                // Add Lightbox/RenderController to mainContext
                App.MainView.add(App.MainView.Layout);

            });

            // Main Footer
            var createMainFooter = function(){
                // var that = this;
                App.Views.MainFooter = new View();

                App.Views.MainFooter.Bg = new Surface({
                    size: [undefined, undefined],
                    classes: ['footer-tabbar-background']
                });

                // create the footer
                App.Views.MainFooter.Tabs = new StandardTabBar();  
                var tmpTabs = App.Views.MainFooter.Tabs;

                tmpTabs.defineSection('booths', {
                    content: '<i class="icon ion-ios7-albums"></i><div><span class="ellipsis-all">Swag</span></div>',
                    onClasses: ['footer-tabbar-default', 'on'],
                    offClasses: ['footer-tabbar-default', 'off']
                });
                tmpTabs.defineSection('parties', {
                    content: '<i class="icon ion-nuclear"></i><div><span class="ellipsis-all">Parties</span></div>',
                    onClasses: ['footer-tabbar-default', 'on'],
                    offClasses: ['footer-tabbar-default', 'off']
                });
                tmpTabs.defineSection('speakers', {
                    content: '<i class="icon ion-speakerphone"></i><div><span class="ellipsis-all">Sessions</span></div>',
                    onClasses: ['footer-tabbar-default', 'on'],
                    offClasses: ['footer-tabbar-default', 'off']
                });
                tmpTabs.defineSection('tips', {
                    content: '<i class="icon ion-information-circled"></i><div><span class="ellipsis-all">Vegas</span></div>',
                    onClasses: ['footer-tabbar-default', 'on'],
                    offClasses: ['footer-tabbar-default', 'off']
                });

                tmpTabs.on('select', function(result, eventTriggered){
                    console.log(eventTriggered);
                    console.log(result);
                    switch(result.id){
                        
                        case 'booths':
                            App.history.navigate('booth/list');
                            break;

                        case 'parties':
                            App.history.navigate('party/list');
                            break;

                        case 'speakers':
                            App.history.navigate('speaker/list');
                            break;

                        case 'tips':
                            App.history.navigate('tips/list');
                            break;

                        default:
                            alert('none chosen');
                            break;
                    }
                });


                // Attach header to the layout 
                App.Views.MainFooter.originMod = new StateModifier({
                    origin: [0, 1]
                });
                App.Views.MainFooter.positionMod = new StateModifier({
                    transform: Transform.translate(0,60,0)
                });
                App.Views.MainFooter.sizeMod = new StateModifier({
                    size: [undefined, 60]
                });

                var node = App.Views.MainFooter.add(App.Views.MainFooter.originMod).add(App.Views.MainFooter.positionMod).add(App.Views.MainFooter.sizeMod);
                node.add(App.Views.MainFooter.Bg);
                node.add(App.Views.MainFooter.Tabs);

                App.Views.MainFooter.show = function(transition){
                    transition = transition || {
                        duration: 750,
                        curve: Easing.outExpo
                    };
                    App.Views.MainFooter.positionMod.setTransform(Transform.translate(0,0,0), transition);
                };

                App.Views.MainFooter.hide = function(transition){
                    transition = transition || {
                        duration: 250,
                        curve: Easing.inExpo
                    };
                    App.Views.MainFooter.positionMod.setTransform(Transform.translate(0,1000,0), transition);
                };

                // Add to maincontext
                // App.MainView.add(Utils.usePlane('mainfooter')).add(App.Views.MainFooter);
                App.MainView.add(Utils.usePlane('mainfooter')).add(App.Views.MainFooter);

            };
            createMainFooter();

            // Splash Page (bloom loading)
            // - terminated by the 
            var createSplashLoading = function(){
                // var that = this;
                App.Views.SplashLoading = new RenderController({
                    inTransition: false,
                    // outTransition: false,
                });
                App.Views.SplashLoading.View = new View();
                App.Views.SplashLoading.View.SizeMod = new StateModifier({
                    size: [undefined, undefined]
                });
                App.Views.SplashLoading.View.OriginMod = new StateModifier({
                    origin: [0.5,0.5]
                });
                var viewNode = App.Views.SplashLoading.View.add(App.Views.SplashLoading.View.SizeMod).add(App.Views.SplashLoading.View.OriginMod);
                App.Views.SplashLoading.BgSurface = new Surface({
                    content: '',
                    size: [undefined, undefined],
                    classes: ['splash-background-default']
                });


                // spinning logo

                // 0 - innermost
                App.Views.SplashLoading.Logo = new ImageSurface({
                    // content: 'OddJob',
                    content: 'img/alchemist_logo.png',
                    classes: ['splash-surface-default'],
                    properties: {
                        // 'backface-visibility' : 'visible'
                    },
                    // content: 'https://dl.dropboxusercontent.com/u/6673634/wehicle_square.svg',
                    // size: [window.innerWidth, 70]
                    size: [228, 92]
                });
                App.Views.SplashLoading.Logo.useOpacity = 0;
                var splashOpacity = 0;
                App.Views.SplashLoading.Logo.StateMod = new StateModifier({
                    opacity: App.Views.SplashLoading.Logo.useOpacity
                });
                App.Views.SplashLoading.Logo.Mod = new Modifier({
                    opacity: function(){
                        // splashOpacity += 0.01;
                        // var through = splashOpacity % 1.20;
                        // var topOrBottom = (parseInt(splashOpacity / 1.20,10)) % 2;
                        // if(topOrBottom == 1){
                        //     through = 1 - through;
                        // }
                        // return through;
                        return 1;
                    }
                });

                // App.Views.SplashLoading.hide = function(thisView){
                //     // if(App.Views.SplashLoading.CurrentPopover === thisView){
                //         App.Views.SplashLoading.hide();
                //     // }
                // };

                App.Functions.action = function(){

                    var durationOfOpacity = 2000;

                    if(App.Views.SplashLoading.Logo.useOpacity != 1){
                        App.Views.SplashLoading.Logo.useOpacity = 1;
                    } else {
                        App.Views.SplashLoading.Logo.useOpacity = 0.1;
                    }
                    App.Views.SplashLoading.Logo.StateMod.setOpacity(App.Views.SplashLoading.Logo.useOpacity,{
                        curve: 'linear',
                        duration: durationOfOpacity
                    });

                    Timer.setTimeout(function(){
                        if(App.Views.SplashLoading._showing != -1){
                            App.Functions.action();
                        }
                    },durationOfOpacity);
                    
                    // rotate it
                    // Timer.setTimeout(function(){
                        // App.Views.SplashLoading.Logo.StateMod.setTransform(Transform.rotateY(Math.PI),{
                        //     duration: 1000,
                        //     curve: 'linear',
                        // }, function(){
                        //     // App.Views.SplashLoading.Logo.StateMod.setTransform(0,{
                        //     //     duration: 1000,
                        //     //     curve: 'linear'
                        //     // });
                        // });
                    // },250);

                    // if(1==1){
                    //     Timer.setTimeout(function(){
                    //         App.Functions.action();
                    //     },3000);
                    // }

                }

                App.Views.SplashLoading.View.add(Utils.usePlane('splashLoading',1)).add(App.Views.SplashLoading.BgSurface);
                viewNode.add(Utils.usePlane('splashLoading',2)).add(App.Views.SplashLoading.Logo.StateMod).add(App.Views.SplashLoading.Logo.Mod).add(App.Views.SplashLoading.Logo);

                App.Views.SplashLoading.show(App.Views.SplashLoading.View);
                App.MainView.add(Utils.usePlane('splashLoading')).add(App.Views.SplashLoading);

            };
            createSplashLoading();


            // Main Popover (keeps PageView underneath)
            var createPopover = function(){
                // var that = this;
                App.Views.Popover = new Lightbox({
                    inTransition: false,
                    outTransition: false,
                });
                App.Views.Popover.hideIf = function(thisView){
                    if(App.Views.Popover.CurrentPopover === thisView || App.Views.Popover.CurrentPopover === false){
                        App.Views.Popover.hide();
                    }
                };
                App.MainView.add(Utils.usePlane('popover')).add(App.Views.Popover);

            };
            createPopover();


            // Add ToastController to mainContext
            // - it should be a ViewSequence or something that allows multiple 'toasts' to be displayed at once, with animations)
            // - todo
            var toastNode = new RenderNode();
            App.MainView.add(Utils.usePlane('toast')).add(toastNode);

            // Add FPS Surface to mainContext
            var fps = new View();
            fps.Surface = new Surface({
                content: 'fps',
                size: [12,12],
                classes: ['fps-counter-default']
            });
            fps.Mod = new StateModifier({
                opacity: 0,
                origin: [1,1]
            });
            Timer.setInterval(function(){
                var fpsNum = parseInt(Engine.getFPS(), 10);
                var thresh = App.Credentials.fps_threshold;
                if(fpsNum >= thresh){
                    fps.Mod.setOpacity(0);
                }
                if(fpsNum < thresh && App.Credentials.show_fps){
                    fps.Mod.setOpacity(1);
                }

                fps.Surface.setContent(fpsNum);
            },1000);
            fps.add(fps.Mod).add(fps.Surface);
            App.MainView.add(Utils.usePlane('fps')).add(fps);

            App.StartRouter = new App.Router.DefaultRouter();

            console.info('StartRouter');

            // Start history watching
            // - don't initiate based on the first view, always restart
            var initialUrl = false;
            if(1==1 && window.location.hash.toString() != ''){
                // Skip goto Home 
                initialUrl = true;
                Backbone.history.start();
            } else {
                Backbone.history.start({silent: true}); 
                App.history.navigate(''); // should go to a "loading" page while we figure out who is logged in
            }


            // Test login
            $.ajaxSetup({
                cache: false,
                contentType: 'application/json', // need to do JSON.stringify() every .data in an $.ajax!
                statusCode: {
                    401: function(){
                        // Redirect the to the login page.
                        // alert(401);
                        // window.location.replace('/#login');
                     
                    },
                    403: function() {
                        // alert(403);
                        // 403 -- Access denied
                        // window.location.replace('/#denied');
                        App.Data.User.clear();
                    },
                    404: function() {
                        // alert(404);
                        // 403 -- Access denied
                        // window.location.replace('/#denied');
                    },
                    500: function() {
                        // alert(500);
                        // 403 -- Access denied
                        // window.location.replace('/#denied');
                    }
                }
            });

    
            // Start Splashscreen
            Timer.setTimeout(function(){
                try {
                    App.Functions.action();

                    Timer.setTimeout(function(){
                        App.Views.SplashLoading.hide();
                    },3000);
                    
                    if(App.Data.usePg){
                        navigator.splashscreen.hide();
                    }
                }catch(err){
                    alert('failed hiding splash screen');
                    alert(err);
                }
            },500);



            // // Ajax setup for users
            // var localUser = localStorage.getItem(App.Credentials.local_user_key);
            // App.Data.User = new UserModel.User();
            try {

                // debugger;
                // localUser = JSON.parse(localUser);
                
                // Set User model to our locally-stored values
                // App.Data.User.set(localUser);
                // console.log(App.Data.User);

                // // Set up ajax credentials for later calls using this user
                // App.Data.UserToken = localStorage.getItem(App.Credentials.local_token_key);
                // $.ajaxSetup({
                //     headers: {
                //         'x-token' : App.Data.UserToken
                //     }
                // });
                
                // // Redirect after setting ajax credentials
                // if(localUser && !initialUrl){
                    // Navigate to my Profiles page
                    Timer.setTimeout(function(){
                        // App.Views.MainFooter.Tabs.select('profiles');
                        App.history.navigate(App.Credentials.home_route);
                        // App.history.navigate('user/sentence');
                    }, 100);
                // }

                // Preload models
                PreloadModels(App);

                // // Fetch
                // App.Data.User.fetch({
                //     statusCode: {
                //         403: function(){

                //             // Logout
                //             // - if not already at the login page
                //             // - and if data is already clear
                //             if(!localUser){
                //                 App.history.navigate('landing');
                //                 return;   
                //             }

                //             console.log(window.location.hash);
                //             if(window.location.hash.indexOf('random') != -1){
                //                 App.history.navigate(App.Credentials.home_route);
                //                 return;
                //             }

                //             if(window.location.hash != '#login' && window.location.hash != '#logout'){
                //                 App.history.navigate('logout/force');
                //             }

                //         }
                //     },
                //     error: function(err){
                //         console.error('failed login');
                //         console.error(err);
                //         // Utils.Notification.Toast('Failed login');
                //         // App.history.navigate('logout/force');
                //         // App.history.navigate('');
                //     },
                //     success: function(){
                //         // Resolve deferred (in case anyone is listening)
                //         // Store credentials

                //         // Update localStorage
                //         localStorage.setItem(App.Credentials.local_user_key, JSON.stringify(App.Data.User.toJSON()));

                //     }
                // });

            } catch(err){
                // Failed badly somewhere
                // - log the person out?
                console.error('Failed trying to test login');
                console.error(err);

                // Navigate to Logout
                App.history.navigate('logout/force');
                debugger;
                // return;

                // alert('Unable to log in');
                // debugger;

            }

        });
Пример #2
0
        },function(t){
            // localization initialized
            App.t = t;

            // Router
            App.Router = require('router')(App); // Passing "App" context to Router also


            // Sizing
            App.defaultSize = [Utils.WindowWidth(), Utils.WindowHeight()]; // use Device Width/height via native plugin? 
            // document.body.setAttribute('style',"width:"+window.innerWidth+"px;height:"+window.innerHeight+"px");
            // Utils.Notification.Toast(window.innerHeight);
            App.mainSize = [Utils.WindowWidth(), Utils.WindowHeight()];
            // Engine.nextTick(function() {
            //     console.log('After tick=' + App.MainContext.getSize());
            //     App.mainSize = App.MainContext.getSize();
            // });
            console.log('App Size:', App.mainSize);

            // create the main context
            App.MainContext = Engine.createContext();
            window.context = App.MainContext;
            App.MainContext.setPerspective(1000);

            // MainView
            App.MainView = new View();
            App.MainView.OuterSizeMod = new StateModifier({
                size: [undefined, undefined]
            });
            App.MainView.OriginMod = new StateModifier({
                origin: [0.5, 0],
                align: [0.5, 0]
            });
            App.MainView.InnerSizeMod = new StateModifier({
                size: App.mainSize
            });
            //.add(App.MainView.OuterSizeMod).add(App.MainView.OriginMod).add(App.MainView.InnerSizeMod)
            App.MainContext.add(App.MainView.OuterSizeMod).add(App.MainView.OriginMod).add(App.MainView.InnerSizeMod).add(App.MainView);

            // Add main background image (pattern)
            App.MainBackground = new Surface({
                size: [undefined, undefined],
                classes: ['overall-background']
            });
            App.MainView.add(Utils.usePlane('background')).add(App.MainBackground); 

            // Create main Lightbox
            App.MainController = new Lightbox();
            // App.MainController.getSize = function(){
            //     return [undefined, undefined];
            // };
            App.MainController.resetOptions = function(){
                this.setOptions(Lightbox.DEFAULT_OPTIONS);
            };
            
            // Resize
            App.Events.on('resize', function(e) {
                // Utils.Notification.Toast('Resized');
                App.MainView.InnerSizeMod.setSize(App.mainSize);
                // document.body.setAttribute('style',"height:"+App.mainSize[1]+"px");
            }.bind(this));


            // Layout for StatusBar / Controller
            if(App.Config.devicePlatform == 'ios'){
                App.StatusBar = true;
            }

            // App.StatusBar set in device_ready
            App.DeviceReady.ready.then(function(){

                var ratios = [1];
                if(App.StatusBar === true){
                    ratios = [true, 1];
                }
                App.MainView.Layout = new FlexibleLayout({
                    direction: 1,
                    ratios: ratios
                });
                App.MainView.Layout.Views = [];


                // iOS StatusBar (above MainController lightbox, if necessary)
                App.StatusBarView = new View();
                App.StatusBarView.getSize = function(){
                    return [undefined, 20];
                };
                App.StatusBarView.Controller = new RenderController();
                App.StatusBarView.add(Utils.usePlane('statusBar')).add(App.StatusBarView.Controller);

                // Animate new colors accordingly (wish it were easier)
                App.StatusBarView.newSurface = function(surf){
                    // animates in a new Surface
                    if(surf instanceof Surface){
                        debugger;
                        // App.StatusBarView.Controller.show(surf);
                        // return;
                    }

                    // create new surface for color, if passed that in an object
                    if(surf.bgClasses){

                        var tmpSurf = new Surface({
                            size: [undefined, 20],
                            classes: surf.bgClasses
                        })

                        console.info(surf.bgClasses);

                        App.StatusBarView.Controller.show(tmpSurf);
                        return;
                    }

                    // what else?
                    console.error('no other handler for newSurface');
                    
                };

                // Add first surface
                App.StatusBarView.newSurface({
                    bgClasses: ['header-bg-default']
                });


                // Add to Layout
                if(App.StatusBar === true){
                    App.MainView.Layout.Views.push(App.StatusBarView);
                }

                App.MainView.Layout.Views.push(App.MainController);
                App.MainView.Layout.sequenceFrom(App.MainView.Layout.Views);

                // Add Lightbox/RenderController to mainContext
                App.MainView.add(App.MainView.Layout);

            });

            // Main Footer
            var createMainFooter = function(){
                // var that = this;
                App.Views.MainFooter = new View();

                App.Views.MainFooter.Bg = new Surface({
                    size: [undefined, undefined],
                    classes: ['footer-tabbar-background']
                });

                // create the footer
                App.Views.MainFooter.Tabs = new StandardTabBar();  
                var tmpTabs = App.Views.MainFooter.Tabs;

                tmpTabs.defineSection('home', {
                    content: '<i class="icon ion-home"></i><div><span class="ellipsis-all">'+App.t('footer.waiting')+'</span></div>',
                    onClasses: ['footer-tabbar-default', 'on'],
                    offClasses: ['footer-tabbar-default', 'off']
                });
                tmpTabs.defineSection('messages', {
                    content: '<i class="icon ion-paper-airplane"></i><div><span class="ellipsis-all">'+App.t('footer.messages')+'</span></div>',
                    onClasses: ['footer-tabbar-default', 'on'],
                    offClasses: ['footer-tabbar-default', 'off']
                });
                tmpTabs.defineSection('profiles', {
                    content: '<i class="icon ion-person"></i><div><span class="ellipsis-all">'+App.t('footer.profiles')+'</span></div>',
                    onClasses: ['footer-tabbar-default', 'on'],
                    offClasses: ['footer-tabbar-default', 'off']
                });
                tmpTabs.defineSection('friends', {
                    content: '<i class="icon ion-person-stalker"></i><div><span class="ellipsis-all">'+App.t('footer.friends')+'</span></div>',
                    onClasses: ['footer-tabbar-default', 'on'],
                    offClasses: ['footer-tabbar-default', 'off']
                });



                tmpTabs.on('select', function(result, eventTriggered){
                    console.error(eventTriggered);
                    console.error(result);
                    switch(result.id){
                        
                        case 'home':
                            App.history.navigate('user/waiting');
                            break;

                        case 'profiles':
                            // display the "last" profile we looked at
                            if(App.history.findLastTag('user')){
                                // found a tag to go back to
                                App.history.backTo('user');
                            } else {
                                // show the default user
                                if(App.Data.User.hasFetched){
                                    App.history.navigate('user/' + App.Data.User.get('_id'));
                                    return;
                                }
                                App.history.navigate('user',{history: false});
                            }
                            break;

                        case 'messages':
                            App.history.navigate('inbox');
                            break;

                        case 'friends':
                            App.history.navigate('friend/list');
                            break;

                        default:
                            alert('none chosen');
                            break;
                    }
                });

                // Attach header to the layout 
                App.Views.MainFooter.originMod = new StateModifier({
                    origin: [0.5, 1],
                    align: [0.5,1]
                });
                App.Views.MainFooter.positionMod = new StateModifier({
                    transform: Transform.translate(0,60,0)
                });
                App.Views.MainFooter.sizeMod = new StateModifier({
                    size: [undefined, 60]
                });

                var node = App.Views.MainFooter.add(App.Views.MainFooter.originMod).add(App.Views.MainFooter.positionMod).add(App.Views.MainFooter.sizeMod);
                node.add(App.Views.MainFooter.Bg);
                node.add(App.Views.MainFooter.Tabs);

                App.Views.MainFooter.show = function(transition){
                    transition = transition || {
                        duration: 750,
                        curve: Easing.outExpo
                    };
                    App.Views.MainFooter.positionMod.setTransform(Transform.translate(0,0,0), transition);
                };

                App.Views.MainFooter.hide = function(transition){
                    transition = transition || {
                        duration: 250,
                        curve: Easing.inExpo
                    };
                    App.Views.MainFooter.positionMod.setTransform(Transform.translate(0,1000,0), transition);
                };

                // Add to maincontext
                App.MainView.add(Utils.usePlane('mainfooter')).add(App.Views.MainFooter);

            };
            createMainFooter();

            // Splash Page
            var createSplashLoading = function(){
                // 
                App.Views.SplashLoading = new RenderController({
                    inTransition: false // want to immediately show our splash image
                });
                // Splash image same as image used in cordova
                App.Views.SplashLoading.Image = new ImageSurface({
                    content: 'res/splash/splash.png',
                    size: [undefined, undefined]
                });

                App.Views.SplashLoading.show(App.Views.SplashLoading.Image);

                App.Functions.SplashAction = function(){
                    // No animation, but could have one!
                }

                // Only show the SplashLoading if on a device
                if(App.usePg){
                    App.MainView.add(Utils.usePlane('splashLoading')).add(App.Views.SplashLoading);
                }

            };
            createSplashLoading();


            // Main Popover (keeps PageView underneath)
            var createPopover = function(){
                // var that = this;
                App.Views.Popover = new Lightbox({
                    inTransition: false,
                    outTransition: false,
                });
                App.Views.Popover.hideIf = function(thisView){
                    if(App.Views.Popover.CurrentPopover === thisView || App.Views.Popover.CurrentPopover === false){
                        App.Views.Popover.hide();
                    }
                };
                App.MainView.add(Utils.usePlane('popover')).add(App.Views.Popover);

            };
            createPopover();


            // Add ToastController to mainContext
            // - it should be a ViewSequence or something that allows multiple 'toasts' to be displayed at once, with animations)
            // - todo
            var toastNode = new RenderNode();
            App.MainView.add(Utils.usePlane('toast')).add(toastNode);

            // Add FPS Surface to mainContext
            var fps = new View();
            fps.Surface = new Surface({
                content: 'fps',
                size: [12,12],
                classes: ['fps-counter-default']
            });
            fps.Mod = new StateModifier({
                opacity: 0,
                origin: [1,1]
            });
            Timer.setInterval(function(){
                var fpsNum = parseInt(Engine.getFPS(), 10);
                var thresh = App.Credentials.fps_threshold;
                if(fpsNum >= thresh){
                    fps.Mod.setOpacity(0);
                }
                if(fpsNum < thresh && App.Credentials.show_fps){
                    fps.Mod.setOpacity(1);
                }

                fps.Surface.setContent(fpsNum);
            },1000);
            fps.add(fps.Mod).add(fps.Surface);
            App.MainView.add(Utils.usePlane('fps')).add(fps);

            // Test login
            $.ajaxSetup({
                cache: false,
                contentType: 'application/json', // need to do JSON.stringify() every .data in an $.ajax!
                statusCode: {
                    401: function(){
                        // Redirect the to the login page.
                        // alert(401);
                        // window.location.replace('/#login');
                     
                    },
                    403: function() {
                        // alert(403);
                        // 403 -- Access denied
                        // window.location.replace('/#denied');
                        App.Data.User.clear();
                    },
                    404: function() {
                        // alert(404);
                        // 403 -- Access denied
                        // window.location.replace('/#denied');
                    },
                    500: function() {
                        // alert(500);
                        // 403 -- Access denied
                        // window.location.replace('/#denied');
                    }
                }
            });

    
            // Hide device splash screen, start our splash screen animation
            App.Functions.SplashAction();
            App.BackboneEvents.once('page-show', function(){
                Timer.setTimeout(function(){
                    if(App.usePg){
                        navigator.splashscreen.hide();
                    }
                    Timer.setTimeout(function(){
                        App.Views.SplashLoading.hide();
                    },500);
                },100);
            });


            // Ajax setup for users
            var localUser = localStorage.getItem(App.Credentials.local_user_key);
            App.Data.User = new UserModel.User();

            localUser = JSON.parse(localUser);
            
            // Set User model to our locally-stored values
            App.Data.User.set(localUser);
            console.log(App.Data.User);

            // Set up ajax credentials for later calls using this user
            App.Data.UserToken = localStorage.getItem(App.Credentials.local_token_key);
            $.ajaxSetup({
                headers: {
                    'x-token' : App.Data.UserToken
                }
            });

            // Set up websocket token
            App.Data.UserWebsocketToken = localStorage.getItem(App.Credentials.local_token_key + '_websocket');

            // Initiate websockets
            Utils.Websocket.init();
            
            // Redirect after setting ajax credentials
            if(localUser && !initialUrl){
                // Navigate to my Profiles page
                Timer.setTimeout(function(){
                    App.Views.MainFooter.Tabs.select('home');
                    // App.history.navigate('user/sentence');
                }, 100);
            }

            // Preload models
            PreloadModels(App);

            // Fetch
            App.Data.User.fetch({
                statusCode: {
                    403: function(){

                        // Logout
                        // - if not already at the login page
                        // - and if data is already clear
                        if(!localUser){
                            App.history.navigate('landing');
                            return;   
                        }

                        console.log(window.location.hash);
                        if(window.location.hash.indexOf('random') != -1){
                            App.history.navigate(App.Credentials.home_route);
                            return;
                        }

                        if(window.location.hash != '#login' && window.location.hash != '#logout'){
                            App.history.navigate('logout/force');
                        }

                    }
                },
                error: function(err){
                    console.error('failed login');
                    console.error(err);

                    Utils.Notification.Toast('Failed initial login');
                    App.history.navigate('logout/force');

                    // Utils.Notification.Toast('Failed login');
                    // App.history.navigate('logout/force');
                    // App.history.navigate('');
                },
                success: function(){
                    // Resolve deferred (in case anyone is listening)
                    // Store credentials

                    // Update localStorage
                    localStorage.setItem(App.Credentials.local_user_key, JSON.stringify(App.Data.User.toJSON()));

                }
            });
    
            // Start the navigation/router
            console.info('StartRouter');
            App.StartRouter = new App.Router.DefaultRouter();

            // Start history watching
            // - don't initiate based on the first view, always restart
            var initialUrl = false;
            if(window.location.hash.toString() != ''){
                // Skip goto Home 
                initialUrl = window.location.hash.toString();
            }
            Backbone.history.start({silent: true});
            Backbone.history.navigate('',{trigger: false, replace: true});
            initialUrl = initialUrl ? initialUrl : App.Credentials.home_route;

            // Logged in?
            // - determiens initial path
            // - home_route/initialUrl
            if(localUser){
                App.history.navigate(initialUrl);
            } else {
                App.history.navigate('landing');
            }
            


        });