poker-html-client
Version:
HTML client for online poker
1,281 lines (1,174 loc) • 50.6 kB
text/typescript
import * as authManager from "./authmanager";
import * as commandManager from "./commandmanager";
import { debugSettings } from "./debugsettings";
import { _ } from "./languagemanager";
import * as metadataManager from "./metadatamanager";
import {
HomePage,
InfoPageBlock,
LobbyPageBlock,
SeatPage,
TablesPage,
} from "./pages";
import {
AccountStatusPopup,
AddMoneyPopup,
AuthPopup,
ChangePasswordPopup,
ChatPopup,
CustomPopup,
HandHistoryPopup,
JoinTablePopup,
MorePopup,
OkCancelPopup,
RulesPopup,
SettingsPopup,
SlowConnectionPopup,
TableMenuPopup,
} from "./popups";
import { SimplePopup } from "./popups/simplepopup";
import {
connectionService,
deviceEvents,
imagePreloadService,
keyboardActivationService,
orientationService,
pushService,
reloadManager,
slowInternetService,
soundManager,
websiteService,
} from "./services";
import * as broadcastService from "./services/broadcastservice";
import { uiManager, UIManager } from "./services/uimanager";
import { settings } from "./settings";
import { TabBar } from "./tabbar";
import * as runtimeSettings from "./table/runtimesettings";
import { tableManager } from "./table/tablemanager";
import * as timeService from "./timeservice";
type PromiseOrVoid = void | Promise<void>;
export class App {
public static addTabBarItemMapping(tabBarItem: string, pageName: string) {
UIManager.addTabBarItemMapping(tabBarItem, pageName);
}
public currentPopup: string = null;
public homePage: HomePage;
public lobbyPageBlock: LobbyPageBlock;
public tablesPage: TablesPage;
public seatsPage: SeatPage;
public infoPageBlock: InfoPageBlock;
public authPopup: AuthPopup;
public changePasswordPopup: ChangePasswordPopup;
public simplePopup: SimplePopup;
public okcancelPopup: OkCancelPopup;
public customPopup: CustomPopup;
public joinTablePopup: JoinTablePopup;
public tableMenuPopup: TableMenuPopup;
public addMoneyPopup: AddMoneyPopup;
public slowConnectionPopup: SlowConnectionPopup;
public tableChatPopup: ChatPopup;
public handHistoryPopup: HandHistoryPopup;
public accountStatusPopup: AccountStatusPopup;
public settingsPopup: SettingsPopup;
public rulesPopup: RulesPopup;
public morePopup: MorePopup;
public tabBar: TabBar;
public mainSelector: Selector;
public spinner: any;
public progressSpinner: any;
public processing: KnockoutObservable<boolean>;
public popupClosed: Signal;
public loadPromises: JQueryPromise<void>[];
public fullyInitialized: boolean;
public disconnected: boolean;
public suppressResume: boolean;
private stopped = false;
private savedPopup: string = null;
constructor() {
const self = this;
this.loadPromises = [];
// register pages.
this.homePage = new HomePage();
this.infoPageBlock = new InfoPageBlock();
this.lobbyPageBlock = new LobbyPageBlock();
this.tablesPage = new TablesPage();
this.seatsPage = new SeatPage();
this.authPopup = new AuthPopup();
this.changePasswordPopup = new ChangePasswordPopup();
this.simplePopup = new SimplePopup();
this.okcancelPopup = new OkCancelPopup();
this.customPopup = new CustomPopup();
this.joinTablePopup = new JoinTablePopup();
this.settingsPopup = new SettingsPopup();
this.rulesPopup = new RulesPopup();
this.tableMenuPopup = new TableMenuPopup();
this.addMoneyPopup = new AddMoneyPopup();
this.slowConnectionPopup = new SlowConnectionPopup();
this.tableChatPopup = new ChatPopup();
this.handHistoryPopup = new HandHistoryPopup();
this.accountStatusPopup = new AccountStatusPopup();
this.morePopup = new MorePopup();
this.processing = ko.observable(false);
this.bindSubPage("home", self.homePage);
this.bindSubPage("tables", self.tablesPage);
this.bindSubPage("seats", self.seatsPage);
this.bindPopup("auth", self.authPopup);
this.bindPopup("changePassword", self.changePasswordPopup);
this.bindPopup("simple", self.simplePopup);
this.bindPopup("okcancel", self.okcancelPopup);
this.bindPopup("custom", self.customPopup);
this.bindPopup("joinTable", self.joinTablePopup);
this.bindPopup("settings", self.settingsPopup);
this.bindPopup("rules", self.rulesPopup);
this.bindPopup("tableMenu", self.tableMenuPopup);
this.bindPopup("addMoney", self.addMoneyPopup);
this.bindPopup("slowConnection", self.slowConnectionPopup);
this.bindPopup("tableChat", self.tableChatPopup);
this.bindPopup("handHistory", self.handHistoryPopup);
this.bindPopup("accountStatus", self.accountStatusPopup);
this.bindPageBlock("lobby", this.lobbyPageBlock);
this.bindPageBlock("info", this.infoPageBlock);
this.bindUIElement(".more-block", this.morePopup);
this.mainSelector = new Selector();
if (typeof window !== "undefined") {
const mainSelectorElement = $(".page.main .sub-page.selector")[0];
if (mainSelectorElement) {
ko.applyBindings(this.mainSelector, mainSelectorElement);
}
}
this.initializeTabbar();
this.initializeConnection();
// var progressBackgroundElement = $(".progress-background")[0];
// ko.applyBindings(this, progressBackgroundElement);
if (typeof window !== "undefined") {
this.processing.subscribe(function(newValue) {
if (newValue) {
$(".progress-background").show();
} else {
$(".progress-background").hide();
}
});
}
// show startup page
uiManager.showPage("initialization");
if (typeof window !== "undefined") {
const opts = {
lines: 13, // The number of lines to draw
length: 4, // The length of each line
width: 2, // The line thickness
radius: 6, // The radius of the inner circle
corners: 1, // Corner roundness (0..1)
rotate: 0, // The rotation offset
direction: 1, // 1: clockwise, -1: counterclockwise
color: "#fff", // #rgb or #rrggbb or array of colors
speed: 1, // Rounds per second
trail: 60, // Afterglow percentage
shadow: false, // Whether to render a shadow
hwaccel: false, // Whether to use hardware acceleration
className: "spinner", // The CSS class to assign to the spinner
zIndex: 2e9, // The z-index (defaults to 2000000000)
top: "auto", // Top position relative to parent in px
left: "auto", // Left position relative to parent in px
};
this.spinner = new Spinner(opts);
const target = document.getElementById("spinner");
this.spinner.spin(target);
const progressTarget = document.getElementById("progress-spinner");
this.progressSpinner = new Spinner(opts).spin(progressTarget);
}
this.popupClosed = new signals.Signal();
}
// Bind Event Listeners
//
// Bind any events that are required on startup. Common events are:
// "load", "deviceready", "offline", and "online".
public bindEvents() {
document.addEventListener("deviceready", this.onDeviceReady, false);
if (debugSettings.ios.hasMultitasking) {
document.addEventListener("resign", this.onResign, false);
document.addEventListener("active", this.onActive, false);
}
document.addEventListener("pause", this.onPause, false);
document.addEventListener("resume", this.onResume, false);
deviceEvents.initialize();
}
// deviceready Event Handler
//
// The scope of 'this' is the event. In order to call the 'receivedEvent'
// function, we must explicity call 'app.receivedEvent(...);'
public onDeviceReady() {
const device: Device = window.device;
if (device != null && device.available) {
if (device.platform.toLowerCase() === "ios") {
if (device.version.toString().indexOf("7.0") === 0) {
StatusBar.overlaysWebView(false);
/* tslint:disable:no-string-literal */
ko.bindingHandlers["image"].options.enabled = false;
/* tslint:enable:no-string-literal */
runtimeSettings.setShowNewsAfterLogin(false);
}
}
}
if (platformInfo.hasMenu()) {
app.setupMenu();
}
// Recalculate width of the landscape mode.
const currentWidth = $("body").width();
if (currentWidth === 1024) {
platformInfo.isTablet = true;
}
app.tablesPage.calculateLandscapeWidth();
pushService.register();
tableManager.maxTablesReached.add(function(continuation) {
SimplePopup.display(_("maxtables.caption"), _("maxtables.maxtablesreached"));
});
tableManager.hasTurn.subscribe(function(value) {
app.tabBar.notice("tables", value);
});
app.popupClosed.add(function(popupName) {
keyboardActivationService.forceHideKeyboard();
console.log("Popup " + popupName + " closed");
});
app.receivedEvent("deviceready");
}
// Update DOM on a Received Event
public async receivedEvent(id) {
const self = this;
timeService.start();
settings.soundEnabled.subscribe(function(value) {
soundManager.enabled(value);
});
settings.loadSettings();
settings.isGuest.subscribe(function(value) {
if (authManager.authenticated() && !value) {
app.lobbyPageBlock.lobbyPage.cashOptions.currency(1);
app.lobbyPageBlock.lobbyPage.sngOptions.currency(1);
app.lobbyPageBlock.lobbyPage.tournamentOptions.currency(1);
} else {
app.lobbyPageBlock.lobbyPage.cashOptions.currency(2);
app.lobbyPageBlock.lobbyPage.sngOptions.currency(2);
app.lobbyPageBlock.lobbyPage.tournamentOptions.currency(2);
}
});
authManager.authenticated.subscribe(function(value) {
if (value && !settings.isGuest()) {
app.lobbyPageBlock.lobbyPage.cashOptions.currency(1);
app.lobbyPageBlock.lobbyPage.sngOptions.currency(1);
app.lobbyPageBlock.lobbyPage.tournamentOptions.currency(1);
} else {
app.lobbyPageBlock.lobbyPage.cashOptions.currency(2);
app.lobbyPageBlock.lobbyPage.sngOptions.currency(2);
app.lobbyPageBlock.lobbyPage.tournamentOptions.currency(2);
}
});
$.when(this.loadPromises).then(function() {
keyboardActivationService.setup();
self.setupTouchActivation();
});
this.setInitializationState();
let startPage = "main";
if (this.getParameterByName("restore") === "true") {
const currentTime = new Date();
const timeDiff = currentTime.valueOf() - settings.lastTime();
if (timeDiff > 1000 * 60 * 20) {
authToken = null;
startPage = "main";
} else {
authToken = settings.authToken();
startPage = settings.lastPage();
}
}
this.logEvent("Received Event: " + id);
if (window.innerWidth > 640) {
PageBlock.useDoubleView = true;
AnimationSettings.platform = "tablet";
}
this.setDesiredOrientation();
if (platformInfo.isTablet) {
orientationService.suppressRotation();
}
this.setupClosePopupOnClick();
metadataManager.setFailed(() => {
slowInternetService.onConnectionSlow();
slowInternetService.onDisconnected();
self.metadataUpdateFailed();
});
metadataManager.setReady(function() {
// Adjust height
const toolpadHeight = platformInfo.hasTabBar() ? 49 : 15;
const logoHeight = 102;
let noLogoHeight = 57;
const pageHeaderHeight = 58;
if (platformInfo.hasTabBar()) {
$(".page.main").addClass("has-toolbar");
}
noLogoHeight = window.innerHeight - toolpadHeight - noLogoHeight - platformInfo.statusBarHeight();
$(".popup-container.scroll-container").css("max-height", noLogoHeight);
const device: Device = window.device;
let tournamentLobbyAdjustment = 57;
let lobbyAdjustment = 0;
if (device != null && device.available) {
if (device.platform.toLowerCase() === "ios") {
tournamentLobbyAdjustment = 57;
} else {
tournamentLobbyAdjustment = 81;
lobbyAdjustment = -30;
app.setupMenu();
}
}
if (startPage === "main") {
uiManager.showPage("main");
self.showPageBlock("home");
self.showSubPage("home");
} else {
app.showSubPage("tables");
self.loadTablesAndTournaments(true);
}
tableManager.tables.subscribe(function(newValue) {
self.updateTabbar(authManager.authenticated(), newValue);
});
authManager.authenticated.subscribe(function(newValue) {
self.updateTabbar(newValue, tableManager.tables());
// tslint:disable-next-line:no-console
console.log("Authentication changed.");
setTimeout(() => {
self.terminateConnection();
self.loadTablesAndTournaments(newValue);
}, 100);
});
});
slowInternetService.initialize();
const hasInternet = slowInternetService.hasInternet();
// tslint:disable-next-line:no-console
console.log("Detecting internet status..." + hasInternet ? "connected" : "not connected");
if (hasInternet) {
slowInternetService.setRetryHandler(null);
self.updateMetadataOnLaunch();
self.hideSplash();
} else {
slowInternetService.onOffline();
self.hideSplash();
slowInternetService.setRetryHandler(() => self.updateMetadataOnLaunch());
}
}
public setInitializationState() {
const parentElement = document.getElementById("deviceready");
if (parentElement) {
const listeningElement = parentElement.querySelector(".listening");
const receivedElement = parentElement.querySelector(".received");
listeningElement.setAttribute("style", "display:none;");
receivedElement.setAttribute("style", "display:block;");
}
}
public buildStartConnection() {
return connectionService.buildStartConnectionAsync();
}
public showSubPage(pageName: string) {
this.hideMoreBlock();
uiManager.showSubPage(pageName);
}
public showPageBlock(pageBlockName: string) {
uiManager.showPageBlock(pageBlockName);
}
public showSelector(selectorCaption: string, options: SelectorItem[], success: (item: SelectorItem) => void) {
const successCallback = (item: SelectorItem) => {
$(".page .page-block." + uiManager.currentPageBlock).css("display", "block");
$(".page .sub-page." + uiManager.currentPage).css("display", "block");
$(".page .sub-page.selector").css("display", "none");
success(item);
};
const cancelCallback = () => {
$(".page .page-block." + uiManager.currentPageBlock).css("display", "block");
$(".page .sub-page." + uiManager.currentPage).css("display", "block");
$(".page .sub-page.selector").css("display", "none");
};
$(".page .page-block." + uiManager.currentPageBlock).css("display", "none");
$(".page .sub-page." + uiManager.currentPage).css("display", "none");
$(".page .sub-page.selector").css("display", "block");
this.mainSelector.setParams(selectorCaption, options, successCallback, cancelCallback);
}
public bindPageBlock(pageBlockName: string, viewModel: PageBlock) {
const self = this;
commandManager.registerCommand("pageblock." + pageBlockName, function() {
const requireAuthentication = viewModel.requireAuthentication;
if (!requireAuthentication) {
self.showPageBlock(pageBlockName);
} else {
app.requireAuthentication().then(function(value) {
if (value) {
self.showPageBlock(pageBlockName);
}
});
}
});
for (let i = 0; i < viewModel.loadPromises.length; i++) {
const item = viewModel.loadPromises[i];
this.loadPromises.push(item);
}
}
public bindSubPage(pageName: string, viewModel: any) {
const self = this;
commandManager.registerCommand("page." + pageName, function() {
const requireAuthentication = viewModel.requireAuthentication || false;
if (!requireAuthentication) {
self.showSubPage(pageName);
} else {
app.requireAuthentication().then(function(value) {
if (value) {
self.showSubPage(pageName);
}
});
}
});
if (typeof window === "undefined") {
return;
}
const pagejElement = $(".page .sub-page." + pageName);
if (pagejElement.length === 0) {
console.error("Could not bind sub page " + pageName + " since DOM element not found.");
return;
}
if (pagejElement.length > 1) {
console.warn("Page " + pageName + " has more then one element to bind.");
return;
}
const pageElement = pagejElement[0];
if (!pageElement.hasChildNodes()) {
const templateSource: string = pagejElement.data("template") as any;
const pageLoadPromise = $.get(templateSource, "text/html").then(function(data: string) {
pagejElement.html(data);
try {
ko.applyBindings(viewModel, pageElement);
} catch (e) {
console.log("Bind page " + pageName + " failed");
}
});
this.loadPromises.push(pageLoadPromise);
return;
}
ko.applyBindings(viewModel, pageElement);
}
public bindPopup(popup: string, viewModel: any): void {
const self = this;
commandManager.registerCommand("popup." + popup, function() {
self.showPopup(popup);
});
if (typeof window === "undefined") {
return;
}
const popupjElement = $(".popup." + popup);
if (popupjElement.length === 0) {
console.error("Could not bind popup " + popup + " since DOM element not found.");
return;
}
if (popupjElement.length > 1) {
console.warn("Popup " + popup + " has more then one element to bind.");
return;
}
const popupElement = popupjElement[0];
if (!popupElement.hasChildNodes()) {
const templateSource: string = popupjElement.data("template") as any;
$.get(templateSource, "text/html").then(function(data) {
popupjElement.html(data);
try {
ko.applyBindings(viewModel, popupElement);
} catch (e) {
console.log("Bind popup " + popup + " failed");
console.log("Detailed exception: ", e);
}
});
return;
}
ko.applyBindings(viewModel, popupElement);
}
public bindUIElement(className: string, viewModel: any): void {
if (typeof window === "undefined") {
return;
}
const uiElement = $(className);
if (uiElement.length === 0) {
console.error("Could not bind UI element with class " + className + " since DOM element not found.");
return;
}
if (uiElement.length > 1) {
console.warn("UI element with class " + className + " has more then one element.");
return;
}
const domElement = uiElement[0];
if (!domElement.hasChildNodes()) {
const templateSource: string = uiElement.data("template") as any;
$.get(templateSource, "text/html").then(function(data) {
uiElement.html(data);
try {
ko.applyBindings(viewModel, domElement);
} catch (e) {
console.log("Bind UI element " + className + " failed");
}
});
return;
}
ko.applyBindings(viewModel, domElement);
}
public async showPopup(popupName: string, ...args: any[]) {
if (!popupName) {
console.error("The empty popup passed");
throw new Error("The empty popup passed");
}
if (this.currentPopup != null) {
this.hideMoreBlock();
this.closePopup();
}
this.currentPopup = popupName;
console.log("Show popup " + popupName);
const result = new Promise<PopupResult>((resolve) => {
this.popupClosed.addOnce(function(name: string, dialogResults?: any) {
if (popupName !== name) {
console.warn("Responding to popup " + name + " instead of " + popupName);
}
const signalData = {
name,
result: dialogResults,
};
resolve(signalData);
}, this, 1);
const popupObject = this[this.currentPopup + "Popup"];
if (popupObject != null) {
popupObject.shown(args);
}
if (typeof window !== "undefined") {
const popupContainer = $(".popup." + popupName + " .popup-container");
if (popupContainer.length > 0) {
popupContainer[0].scrollTop = 0;
}
$(".popup." + popupName).css("display", "block");
$(".popup-background").css("display", "block");
}
});
return result;
}
public closePopup(result?: any): void {
if (this.currentPopup) {
console.log("Close popup " + this.currentPopup);
if (typeof window !== "undefined") {
$(".popup." + this.currentPopup + " .popup-container")[0].scrollTop = 0;
$(".popup." + this.currentPopup).css("display", "none");
$(".popup-background").css("display", "none");
}
const popupName = this.currentPopup;
const popupObject = this[this.currentPopup + "Popup"];
/* tslint:disable:no-string-literal */
if (popupObject !== undefined && popupObject["visible"] !== undefined) {
popupObject.visible(false);
}
/* tslint:enable:no-string-literal */
this.currentPopup = null;
this.popupClosed.dispatch(popupName, result);
}
}
public executeCommand(commandName: string, parameters: any[]= []) {
if (commandName === "popup.auth.show") {
this.showPopup("auth");
return;
}
if (commandName === "popup.auth.forgetPassword") {
this.showPopup("forgetPassword");
return;
}
if (commandName === "popup.auth.registration") {
this.showPopup("registration");
return;
}
if (commandName === "popup.auth.continueForgetPassword") {
this.showPopup("continueForgetPassword");
return;
}
if (commandName === "popup.close") {
this.closePopup();
return;
}
if (commandName === "legal.eula") {
app.closePopup();
app.executeCommand("pageblock.info");
app.infoPageBlock.showLicenseAgreement();
return;
}
if (commandName === "popup.cancel") {
this.closePopup("cancel");
return;
}
if (commandName === "more.close") {
this.hideMoreBlock();
const currentTabBarItem = UIManager.getTabBarItemForPage(uiManager.currentPageBlock);
app.tabBar.select(currentTabBarItem, true);
return;
}
if (commandName === "logout") {
authManager.logout();
return;
}
if (commandName === "app.exit") {
authManager.logout();
this.reloadApplication();
return;
}
commandManager.executeCommand(commandName, parameters);
}
public reloadApplication() {
/* tslint:disable:no-unused-expression no-string-literal */
window["StatusBar"] && StatusBar.show();
/* tslint:enable:no-unused-expression no-string-literal */
window.location.reload();
}
public shouldRotateToOrientation(interfaceOrientation: any) {
/// Checks that given orientation currently supported
/// For now this is works in iOS.
return ScreenOrientation.shouldRotateToOrientation(interfaceOrientation);
}
public requireAuthentication(): JQueryPromise<boolean> {
const result = $.Deferred<boolean>();
if (!authManager.authenticated()) {
// We don't authenticated, so display authentication popup.
this.popupClosed.addOnce(function() {
// Resolve with current authentication status, so
// caller would know operation was successful or not.
result.resolve(authManager.authenticated(), false);
}, this, null);
this.showPopup("auth");
} else {
// We already authenticated, no need to show authentication popup.
result.resolve(true, true);
}
return result;
}
public requireGuestAuthentication(): JQueryPromise<boolean> {
const result = $.Deferred<boolean>();
if (!authManager.authenticated()) {
// We don't authenticated, so display authentication popup.
authManager.loginAsGuest().then(function(status) {
result.resolve(authManager.authenticated(), false);
});
} else {
// We already authenticated, no need to show authentication popup.
result.resolve(true, true);
}
return result;
}
public prompt(title: string, messages: string[], buttons: string[]= null) {
if (buttons === null) {
buttons = [_("common.ok"), _("common.cancel")];
}
this.showPopup("okcancel");
const popupObject = this.okcancelPopup;
const deferred = popupObject.deferred;
popupObject.title(title);
popupObject.messages(messages);
popupObject.buttons(buttons);
popupObject.customStyle("");
return deferred;
}
public promptEx(title: string, messages: string[], buttons: string[], actions: Array<() => PromiseOrVoid>) {
this.showPopup("custom");
const popupObject = this.customPopup;
const deferred = popupObject.deferred;
popupObject.title(title);
popupObject.messages(messages);
popupObject.buttons(buttons);
popupObject.actions(actions);
return deferred;
}
public promptAsync(title: string, messages: string[], buttons: string[] = null) {
return new Promise<boolean>((resolve, reject) => {
this.prompt(title, messages, buttons).then(() => resolve(true), () => resolve(false));
});
}
private initializeTabbar() {
this.tabBar = new TabBar();
this.tabBar.addItem("home", _("tabbar.home"), "home", function() {
app.executeCommand("page.home");
app.showPageBlock("home");
});
this.tabBar.addItem("lobby", _("tabbar.lobby"), "lobby", function() {
app.lobbyPageBlock.showLobby();
});
this.tabBar.addItem("tables", _("tabbar.tables"), "tables", function() {
const currentTable = app.tablesPage.currentTable();
if (currentTable === null || currentTable.model === null) {
console.warn("No tables opened. Could not open tables page");
SimplePopup.display(_("menu.tables"), _("tablesList.noTablesSelected"));
return;
}
app.executeCommand("app.selectTable", [currentTable.model]);
app.showSubPage("tables");
});
this.tabBar.addItem("cashier", _("tabbar.cashier"), "cashier", function() {
app.executeCommand("pageblock.cashier");
// app.executeCommand("pageblock.other");
});
this.tabBar.addItem("more", _("tabbar.more"), "more", function() {
const currentTabBarItem = UIManager.getTabBarItemForPage(uiManager.currentPageBlock);
const isMoreSelected = app.tabBar.isSelected("more");
const isMoreOpened = $("body").hasClass("more-opened");
if (isMoreOpened) {
app.tabBar.select("more", false);
app.tabBar.select(currentTabBarItem, true);
$(".more-block").hide();
$("body").removeClass("more-opened");
} else {
app.tabBar.select(currentTabBarItem, false);
app.tabBar.select("more", true);
app.morePopup.update();
$(".more-block").show();
$("body").addClass("more-opened");
}
app.morePopup.visible(!app.morePopup.visible());
});
this.tabBar.enable("tables", false);
if (typeof window !== "undefined") {
const tabBarElement = $(".toolbar-container")[0];
if (tabBarElement) {
ko.applyBindings(this.tabBar, tabBarElement);
}
}
uiManager.subPageHiding.add(function(blockHiding: string) {
const name = UIManager.getTabBarItemForPage(blockHiding);
app.tabBar.select(name, false);
});
uiManager.subPageShowing.add(function(blockShowing: string) {
const name = UIManager.getTabBarItemForPage(blockShowing);
app.tabBar.select(name, true);
});
uiManager.pageBlockHiding.add(function(blockHiding: string) {
const name = UIManager.getTabBarItemForPage(blockHiding);
app.tabBar.select(name, false);
});
uiManager.pageBlockShowing.add(function(blockShowing: string) {
const name = UIManager.getTabBarItemForPage(blockShowing);
app.tabBar.select(name, true);
});
uiManager.pageBlockHidden.add(function(pageBlock: string) {
if (app.tabBar.isSelected("more")) {
if (pageBlock !== "more" && !app.morePopup.visible()) {
app.tabBar.select("more", false);
}
app.hideMoreBlock();
}
});
}
private onResign() {
const self = app;
self.logEvent("Application resign active");
// Wrap code in the timeout to prevent application from freezing.
self.terminateConnection();
}
private onActive() {
const self = app;
self.logEvent("Application active");
// Wrap code in the timeout to prevent application from freezing.
self.establishConnection();
}
private onPause() {
const self = app;
const device: Device = window.device;
if (platformInfo.isTablet) {
orientationService.enableRotation();
}
if (platformInfo.reloadOnResume) {
// Don't do anything if reloading on resume.
if (uiManager.currentPage === "tables") {
settings.lastPage("tables");
} else {
settings.lastPage("main");
}
settings.authToken(authToken);
settings.lastTime(new Date().valueOf());
settings.saveSettings();
return;
}
if (self.suppressResume) {
return;
}
if (debugSettings.application.deactivateOnPause) {
uiManager.deactivateSubPage(uiManager.currentPage);
}
self.logEvent("Pause application");
// Wrap code in the timeout to prevent application from freezing.
timeService.setTimeout(function() {
self.logEvent("Pause application#2");
self.showSplash();
settings.saveSettings();
if (self.currentPopup === "registration") {
self.savedPopup = self.currentPopup;
} else {
self.savedPopup = null;
}
self.closePopup();
timeService.printDebug();
}, 0);
timeService.stop();
self.processing(false);
self.spinner.stop();
self.terminateConnection();
}
private onResume() {
const self = app;
const device: Device = window.device;
if (platformInfo.reloadOnResume) {
// Reload to the main page with special configuration parameter
self.showSplash();
location.replace(location.protocol + "//" + location.host + location.pathname + "?restore=true");
return;
}
if (self.suppressResume) {
self.suppressResume = false;
if (self.savedPopup) {
self.showPopup(self.savedPopup, true);
self.savedPopup = null;
}
return;
}
self.logEvent("Resume application");
timeService.start();
self.showSplash();
const target = document.getElementById("spinner");
self.spinner.spin(target);
let pageBeforeClosing = uiManager.effectivePageContainer;
let pageBlockBeforeClosing = uiManager.currentPageBlock;
let subPageBeforeClosing = uiManager.currentPage;
if (pageBeforeClosing === "initialization" || pageBeforeClosing === null) {
pageBeforeClosing = "main";
pageBlockBeforeClosing = "home";
subPageBeforeClosing = "home";
}
uiManager.showPage("initialization");
settings.loadSettings();
self.setInitializationState();
orientationService.setLastOrientation();
if (platformInfo.isTablet) {
orientationService.suppressRotation();
}
if (slowInternetService.fatalError) {
self.hideSplash();
slowInternetService.showDuplicatedConnectionPopup();
return;
}
if (slowInternetService.hasInternet()) {
slowInternetService.closePopup();
self.updateMetadataOnResume(pageBeforeClosing, pageBlockBeforeClosing, subPageBeforeClosing);
slowInternetService.setRetryHandler(null);
self.hideSplash();
} else {
slowInternetService.onOffline();
self.hideSplash();
slowInternetService.setRetryHandler(function() {
self.updateMetadataOnResume(pageBeforeClosing, pageBlockBeforeClosing, subPageBeforeClosing);
});
}
}
private async updateMetadataOnResume(lastPage, pageBlockBeforeClosing, subPageBeforeClosing) {
const self = this;
if (debugSettings.initialization.stopOnResume) {
return;
}
console.log("Launch intialization of metadata on resume");
if (!this.fullyInitialized) {
console.log("Application was never initialized, performing full initialization.");
await this.updateMetadataOnLaunch();
return;
}
const failHandler = function() {
console.log("Failed updating metadata on resume, rescheduling attempt.");
slowInternetService.showReconnectFailedPopup();
slowInternetService.setRetryHandler(() => {
self.updateMetadataOnResume(lastPage, pageBlockBeforeClosing, subPageBeforeClosing);
});
};
if (!await this.versionCheck()) {
return;
}
this.preloadTableImages();
try {
await metadataManager.update();
tableManager.initialize();
try {
await tableManager.getCurrentTablesAndTournaments();
this.spinner.stop();
const wrapper = await self.establishConnection();
if (wrapper.terminated) {
return;
}
this.logEvent("Showing last page");
if (lastPage != null) {
if (!debugSettings.application.goToLobbyAfterPause) {
uiManager.showPage(lastPage);
} else {
uiManager.showPage("main");
if (lastPage === "table") {
uiManager.showPageBlock("lobby");
uiManager.showSubPage("lobby");
}
}
} else {
uiManager.showPage("main");
}
if (debugSettings.application.deactivateOnPause) {
this.logEvent("Activating subpage");
uiManager.activateSubPage(uiManager.currentPage);
}
if (this.savedPopup) {
this.showPopup(this.savedPopup, true);
this.savedPopup = null;
}
orientationService.setLastOrientation();
reloadManager.execute();
} catch (e) {
failHandler();
}
} catch (e) {
failHandler();
}
}
private async updateMetadataOnLaunch() {
const self = this;
if (debugSettings.initialization.stopOnLaunch) {
return;
}
console.log("Launch intialization of metadata first time");
const failHandler = function (e: Error) {
console.error(e);
console.log("Failed updating metadata for first time, rescheduling attempt.");
slowInternetService.setRetryHandler(() => {
self.updateMetadataOnLaunch();
});
};
if (!await this.versionCheck()) {
return;
}
self.preloadTableImages();
try {
await metadataManager.update();
self.spinner.stop();
tableManager.initialize();
try {
await self.establishConnection();
await tableManager.getCurrentTablesAndTournaments();
self.fullyInitialized = true;
metadataManager.setReady(null);
} catch (e) {
failHandler(e);
}
} catch (e) {
failHandler(e);
}
}
private async versionCheck() {
try {
await metadataManager.versionCheck();
return true;
} catch (e) {
// Display dialog which prompts for the update.
app.promptEx(_("updater.title"), [_("updater.line1")], [_("updater.button")], [() => {
websiteService.navigateUpdateApk();
}]);
return false;
}
}
private setupTouchActivation() {
// This is a fix which updates binding for the knockout value binding.
// This is nescessary since touchstart event start handling.
$("body").on("keyup", "input", function(event) {
$(this).trigger("change");
});
$("body").on("touchstart", ".button, .actionable", function(event) {
$(this).addClass("pressed");
}).on("touchend", ".button, .actionable", function(event) {
$(this).removeClass("pressed");
}).on("touchcancel", ".button, .actionable", function(event) {
$(this).removeClass("pressed");
});
}
private setupMenu() {
menu.initialize([
{ id: 1, order: 1, name: _("menu.home") },
{ id: 2, order: 1, name: _("menu.lobby") },
{ id: 3, order: 1, name: _("menu.tables") },
{ id: 4, order: 1, name: _("menu.cashier") },
{ id: 5, order: 1, name: _("menu.account") },
{ id: 6, order: 1, name: _("menu.chat") },
{ id: 7, order: 1, name: _("menu.rating") },
{ id: 8, order: 1, name: _("menu.messages") },
{ id: 9, order: 1, name: _("menu.information") },
]);
menu.optionItemClick = function(itemId) {
if (itemId === 1) {
app.executeCommand("page.home");
app.showPageBlock("home");
}
if (itemId === 2) {
app.lobbyPageBlock.showLobby();
}
if (itemId === 3) {
app.executeCommand("page.tables");
}
if (itemId === 4) {
app.executeCommand("pageblock.cashier");
}
if (itemId === 5) {
app.executeCommand("page.account");
}
if (itemId === 6) {
app.executeCommand("page.chat");
}
if (itemId === 7) {
app.executeCommand("page.rating");
}
if (itemId === 8) {
app.executeCommand("page.messages");
}
if (itemId === 9) {
app.executeCommand("page.information");
}
console.log(itemId);
};
}
private async loadTablesAndTournaments(authenticated: boolean) {
const self = this;
if (authenticated) {
try {
await tableManager.getCurrentTablesAndTournaments();
self.establishConnection();
} catch (e) {
console.log("Could not get current tables!");
slowInternetService.showReconnectFailedPopup();
}
} else {
tableManager.clear();
self.establishConnection();
}
}
private setFailedState() {
const parentElement = document.getElementById("deviceready");
if (parentElement) {
const listeningElement = parentElement.querySelector(".listening");
const receivedElement = parentElement.querySelector(".received");
receivedElement.setAttribute("style", "display:none;");
const failedElement = parentElement.querySelector(".failed");
failedElement.setAttribute("style", "display:block;");
}
}
private metadataUpdateFailed() {
this.setFailedState();
console.log("Metadata retreiving failure");
}
private setDesiredOrientation() {
if (!PageBlock.useDoubleView) {
orientationService.setOrientation("portrait");
} else {
orientationService.setOrientation("landscape");
}
}
private initializeConnection() {
const self = this;
// connectionService.initializeConnection();
connectionService.recoverableError.add(function() {
self.establishConnection();
});
}
private terminateConnection(forceDisconnect = false) {
tableManager.stopConnectingToTables();
connectionService.terminateConnection(forceDisconnect);
}
private async establishConnection(maxAttempts = 3) {
const self = this;
// This part should be moved up to the stack to remove dependency on other services
// in the connection management.
connectionService.initializeConnection();
const wrapper = await connectionService.establishConnectionAsync(maxAttempts);
if (wrapper.terminated) {
return wrapper;
}
self.logEvent("Setting up connection dependent services.");
slowInternetService.manualDisconnect = false;
tableManager.connectTables();
tableManager.connectTournaments();
const connection = wrapper.connection;
try {
self.logEvent("Joining lobby chat.");
connection.Chat.server.join(0);
} catch (error) {
console.log(error);
throw new Error("Could not join chat after establishingConnection");
}
self.logEvent("Listening lobby chat messages.");
const chatHub = connection.createHubProxy("chat");
chatHub.on("Message", function(...msg: any[]) {
const messageId = msg[0];
const tableId = msg[1];
const type = msg[2];
const sender = msg[3];
const message = msg[4];
if (tableId !== 0) {
return;
}
if (type === "B") {
broadcastService.displayMessage(message);
}
});
return wrapper;
}
private hideMoreBlock() {
app.morePopup.visible(false);
$(".more-block").hide();
$("body").removeClass("more-opened");
app.tabBar.select("more", false);
}
private updateTabbar(authenticated, tables) {
const self = this;
if (authenticated) {
const tablesEnabled = tables.length > 0;
self.tabBar.enable("tables", tablesEnabled);
} else {
self.tabBar.enable("tables", false);
}
}
private setupClosePopupOnClick() {
$(".popup-background").on("tap", () => {
if (app.currentPopup !== "slowConnection") {
app.closePopup();
}
});
}
private preloadTableImages() {
imagePreloadService.preloadResource("img/lobby/table2-empty");
imagePreloadService.preloadResource("img/lobby/table2-s1");
imagePreloadService.preloadResource("img/lobby/table2-s2");
imagePreloadService.preloadResource("img/lobby/table6-empty");
imagePreloadService.preloadResource("img/lobby/table6-s1");
imagePreloadService.preloadResource("img/lobby/table6-s2");
imagePreloadService.preloadResource("img/lobby/table6-s3");
imagePreloadService.preloadResource("img/lobby/table6-s4");
imagePreloadService.preloadResource("img/lobby/table6-s5");
imagePreloadService.preloadResource("img/lobby/table6-s6");
imagePreloadService.preloadResource("img/lobby/table10-empty");
imagePreloadService.preloadResource("img/lobby/table10-s1");
imagePreloadService.preloadResource("img/lobby/table10-s2");
imagePreloadService.preloadResource("img/lobby/table10-s3");
imagePreloadService.preloadResource("img/lobby/table10-s4");
imagePreloadService.preloadResource("img/lobby/table10-s5");
imagePreloadService.preloadResource("img/lobby/table10-s6");
imagePreloadService.preloadResource("img/lobby/table10-s7");
imagePreloadService.preloadResource("img/lobby/table10-s8");
imagePreloadService.preloadResource("img/lobby/table10-s9");
imagePreloadService.preloadResource("img/lobby/table10-s10");
imagePreloadService.preloadDeviceSpecificResource("img/images/tableImages/poker_table");
}
private logEvent(message: string) {
if (debugSettings.device.events) {
console.log(message);
}
}
private getParameterByName(name) {
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
const regex = new RegExp("[\\?&]" + name + "=([^&#]*)");
const results = regex.exec(location.search);
return results == null
? ""