Your IP : 3.144.225.144


Current Path : /var/www/axolotl/data/www/arhangelsk.axolotls.ru/bitrix/js/im/controller/src/
Upload File :
Current File : /var/www/axolotl/data/www/arhangelsk.axolotls.ru/bitrix/js/im/controller/src/core.js

/**
 * Bitrix im dialog mobile
 * Dialog runtime class
 *
 * @package bitrix
 * @subpackage mobile
 * @copyright 2001-2019 Bitrix
 */

// main
import "promise";

// ui
import {Vue} from "ui.vue";
import {VuexBuilder} from "ui.vue.vuex";

// messenger files
import {ApplicationModel, MessagesModel, DialoguesModel, UsersModel, FilesModel, RecentModel} from 'im.model';
import {DeviceType} from 'im.const';
import {Utils} from "im.lib.utils";
import {ImPullCommandHandler} from "im.provider.pull";
import {CoreRestHandler} from "im.provider.rest";

import {ApplicationController} from "./application";
import {RecentController} from "./recent";
import {Logger} from "im.lib.logger";

// TODO change BX.Promise, BX.Main.Date to IMPORT

export class Controller
{
	/* region 01. Initialize and store data */

	constructor(params = {})
	{
		this.inited = false;
		this.initPromise = new BX.Promise;

		this.offline = false;

		this.restAnswerHandler = [];
		this.vuexAdditionalModel = [];

		this.store = null;
		this.storeBuilder = null;

		this.prepareConstructorParams(params);

		this.initController()
			.then(() => this.initLocalStorage())
			.then(() => this.initStorage())
			.then(() => this.initRestClient())
			.then(() => this.initPullClient())
			.then(() => this.initEnvironment())
			.then(() => this.initComponent())
			.then(() => this.initComplete())
		;
	}

	prepareConstructorParams(params)
	{
		if (typeof params.localize !== 'undefined')
		{
			this.localize = params.localize;
		}
		else
		{
			this.localize = {...BX.message};
		}

		if (typeof params.host !== 'undefined')
		{
			this.host = params.host;
		}
		else
		{
			this.host = location.origin;
		}

		if (typeof params.userId !== 'undefined')
		{
			this.userId = params.userId? parseInt(params.userId): 0;
		}
		else
		{
			let userId = this.getLocalize('USER_ID');
			this.userId = userId? parseInt(userId): 0;
		}

		if (typeof params.siteId !== 'undefined')
		{
			this.siteId = params.siteId? params.userId: 's1';
		}
		else
		{
			this.siteId = this.getLocalize('SITE_ID') || 's1';
		}

		if (typeof params.siteDir !== 'undefined')
		{
			this.siteDir = params.siteDir? params.siteDir: 's1';
		}
		else
		{
			this.siteDir = this.getLocalize('SITE_DIR') || 's1';
		}

		if (typeof params.languageId !== 'undefined')
		{
			this.languageId = params.languageId? params.languageId: 'en';
		}
		else
		{
			this.languageId = this.getLocalize('LANGUAGE_ID') || 'en';
		}

		this.pull = BX.PullClient;
		this.pullClient = BX.PULL;

		if (typeof params.pull !== 'undefined')
		{
			if (typeof params.pull.instance !== 'undefined')
			{
				this.pull = params.pull.instance;
			}
			if (typeof params.pull.client !== 'undefined')
			{
				this.pullClient = params.pull.client;
			}
		}


		this.rest = BX.RestClient;
		this.restClient = BX.rest;

		if (typeof params.rest !== 'undefined')
		{
			if (typeof params.rest.instance !== 'undefined')
			{
				this.rest = params.rest.instance;
			}
			if (typeof params.rest.client !== 'undefined')
			{
				this.restClient = params.rest.client;
			}
		}


		this.vuexBuilder = {
			database: false,
			databaseName: 'desktop/im',
			databaseType: VuexBuilder.DatabaseType.indexedDb
		};

		if (typeof params.vuexBuilder !== 'undefined')
		{
			if (typeof params.vuexBuilder.database !== 'undefined')
			{
				this.vuexBuilder.database = params.vuexBuilder.database;
			}
			if (typeof params.vuexBuilder.databaseName !== 'undefined')
			{
				this.vuexBuilder.databaseName = params.vuexBuilder.databaseName;
			}
			if (typeof params.vuexBuilder.databaseType !== 'undefined')
			{
				this.vuexBuilder.databaseType = params.vuexBuilder.databaseType;
			}
			if (typeof params.vuexBuilder.models !== 'undefined')
			{
				params.vuexBuilder.models.forEach(model => {
					this.addVuexModel(model);
				});
			}
		}

		return true;
	}

	initConstructorParams()
	{
		return this.paramsPromise.then(params => {
			this.prepareConstructorParams(
				this.paramsCallback(params)
			);
			return new Promise((resolve, reject) => resolve());
		});
	}

	initController()
	{
		this.application = new ApplicationController();
		this.application.setCoreController(this);

		this.recent = new RecentController();
		this.recent.setCoreController(this);

		return new Promise((resolve, reject) => resolve());
	}

	initLocalStorage()
	{
		return new Promise((resolve, reject) => resolve());
	}

	initStorage()
	{
		let applicationVariables = {
			common: {
				host: this.getHost(),
				userId: this.getUserId(),
				siteId: this.getSiteId(),
				languageId: this.getLanguageId(),
			},
			dialog: {
				messageLimit: this.application.getDefaultMessageLimit(),
				enableReadMessages: false, // TODO: remove
			},
			device: {
				type: Utils.device.isMobile()? DeviceType.mobile: DeviceType.desktop,
				orientation: Utils.device.getOrientation(),
			},
		};

		let builder = new VuexBuilder()
			.addModel(ApplicationModel.create().useDatabase(false).setVariables(applicationVariables))
			.addModel(MessagesModel.create().useDatabase(this.vuexBuilder.database).setVariables({host: this.getHost()}))
			.addModel(DialoguesModel.create().useDatabase(this.vuexBuilder.database).setVariables({host: this.getHost()}))
			.addModel(FilesModel.create().useDatabase(this.vuexBuilder.database).setVariables({host: this.getHost(), default: {name: 'File is deleted'}}))
			.addModel(UsersModel.create().useDatabase(this.vuexBuilder.database).setVariables({host: this.getHost(), default: {name: 'Anonymous'}}))
			.addModel(RecentModel.create().useDatabase(false).setVariables({host: this.getHost()}))
		;

		this.vuexAdditionalModel.forEach(model => {
			builder.addModel(model);
		});

		builder.setDatabaseConfig({
			name: this.vuexBuilder.databaseName,
			type: this.vuexBuilder.databaseType,
			siteId: this.getSiteId(),
			userId: this.getUserId(),
		});

		return builder.build().then(result => {
			this.store = result.store;
			this.storeBuilder = result.builder;
			return new Promise((resolve, reject) => resolve());
		})
	}

	initRestClient(result)
	{
		this.addRestAnswerHandler(
			CoreRestHandler.create({
				store: this.store,
				controller: this,
			})
		);

		return new Promise((resolve, reject) => resolve());
	}

	initPullClient()
	{
		if (!this.pullClient)
		{
			return false;
		}

		this.pullClient.subscribe(
			this.pullCommandHandler = new ImPullCommandHandler({
				store: this.store,
				controller: this,
			})
		);

		this.pullClient.subscribe({
			type: this.pull.SubscriptionType.Status,
			callback: this.eventStatusInteraction.bind(this)
		});

		this.pullClient.subscribe({
			type: this.pull.SubscriptionType.Online,
			callback: this.eventOnlineInteraction.bind(this)
		});

		return new Promise((resolve, reject) => resolve());
	}

	initEnvironment(result)
	{
		window.addEventListener('orientationchange', () =>
		{
			if (!this.store)
			{
				return;
			}

			this.store.commit('application/set', {device: {
				orientation: Utils.device.getOrientation()
			}});

			if (
				this.store.state.application.device.type === DeviceType.mobile
				&& this.store.state.application.device.orientation === DeviceOrientation.horizontal
			)
			{
				document.activeElement.blur();
			}
		});

		return new Promise((resolve, reject) => resolve());
	}

	initComponent()
	{
		return new Promise((resolve, reject) => resolve());
	}

	initComplete()
	{
		this.inited = true;
		this.initPromise.resolve(this);
	}

/* endregion 01. Initialize and store data */

/* region 02. Push & Pull */

	eventStatusInteraction(data)
	{
		if (data.status === this.pull.PullStatus.Online)
		{
			this.offline = false;

			//this.pullCommandHandler.option.skip = true;
			// this.getDialogUnread().then(() => {
			// 	this.pullCommandHandler.option.skip = false;
			// 	this.processSendMessages();
			// 	this.emit(EventType.dialog.sendReadMessages);
			// }).catch(() => {
			// 	this.pullCommandHandler.option.skip = false;
			// 	this.processSendMessages();
			// });
		}
		else if (data.status === this.pull.PullStatus.Offline)
		{
			this.offline = true;
		}
	}

	eventOnlineInteraction(data)
	{
		if (data.command === 'list' || data.command === 'userStatus')
		{
			for (let userId in data.params.users)
			{
				if (!data.params.users.hasOwnProperty(userId))
				{
					continue;
				}

				this.store.dispatch('users/update', {
					id: data.params.users[userId].id,
					fields: data.params.users[userId]
				});
			}
		}
	}

/* endregion 02. Push & Pull */

/* region 03. Rest */

	executeRestAnswer(command, result, extra)
	{
		Logger.warn('Core.controller.executeRestAnswer', command, result, extra);

		this.restAnswerHandler.forEach(handler => {
			handler.execute(command, result, extra);
		});
	}

/* endregion 03. Rest */

/* region 04. Template engine */

	createVue(application, config = {})
	{
		const controller = this;
		const restClient = this.restClient;
		const pullClient = this.pullClient || null;

		let beforeCreateFunction = () => {};
		if (config.beforeCreate)
		{
			beforeCreateFunction = config.beforeCreate;
		}

		let destroyedFunction = () => {};
		if (config.destroyed)
		{
			destroyedFunction = config.destroyed;
		}

		let initConfig = {
			store: this.store,
			beforeCreate()
			{
				this.$bitrixApplication = application;
				this.$bitrixController = controller;
				this.$bitrixRestClient = restClient;
				this.$bitrixPullClient = pullClient;
				this.$bitrixMessages = controller.localize;

				beforeCreateFunction.bind(this)();
			},
			destroyed()
			{
				this.$bitrixApplication = null;
				this.$bitrixController = null;
				this.$bitrixRestClient = null;
				this.$bitrixPullClient = null;
				this.$bitrixMessages = null;

				destroyedFunction.bind(this)();
			}
		};

		if (config.el)
		{
			initConfig.el = config.el;
		}

		if (config.template)
		{
			initConfig.template = config.template;
		}

		if (config.computed)
		{
			initConfig.computed = config.computed;
		}

		if (config.created)
		{
			initConfig.created = config.created;
		}

		if (config.data)
		{
			initConfig.data = config.data;
		}

		return new Promise((resolve, reject) => {
			initConfig.created = function() { resolve(this); };
			Vue.create(initConfig);
		});
	}

/* endregion 04. Template engine */

/* region 05. Core methods */
	getHost()
	{
		return this.host;
	}

	getUserId()
	{
		return this.userId;
	}

	getSiteId()
	{
		return this.siteId;
	}

	getLanguageId()
	{
		return this.languageId;
	}

	getStore()
	{
		return this.store;
	}

	getStoreBuilder()
	{
		return this.storeBuilder;
	}

	addRestAnswerHandler(handler)
	{
		this.restAnswerHandler.push(handler);
	}

	addVuexModel(model)
	{
		this.vuexAdditionalModel.push(model);
	}

	isOnline()
	{
		return !this.offline;
	}

	ready()
	{
		if (this.inited)
		{
			let promise = new BX.Promise;
			promise.resolve(this);

			return promise;
		}

		return this.initPromise;
	}

/* endregion 05. Methods */

/* region 06. Interaction and utils */

	setError(code = '', description = '')
	{
		Logger.error(`Messenger.Application.error: ${code} (${description})`);

		let localizeDescription = '';
		if (code.endsWith('LOCALIZED'))
		{
			localizeDescription = description;
		}

		this.store.commit('application/set', {error: {
			active: true,
			code,
			description: localizeDescription
		}});
	}

	clearError()
	{
		this.store.commit('application/set', {error: {
			active: false,
			code: '',
			description: ''}
		});
	}

	addLocalize(phrases)
	{
		if (typeof phrases !== "object" || !phrases)
		{
			return false;
		}

		for (let name in phrases)
		{
			if (phrases.hasOwnProperty(name))
			{
				this.localize[name] = phrases[name];
			}
		}

		return true;
	}

	getLocalize(name)
	{
		let phrase = '';
		if (typeof name === 'undefined')
		{
			return this.localize;
		}
		else if (typeof this.localize[name.toString()] === 'undefined')
		{
			Logger.warn(`Controller.Core.getLocalize: message with code '${name.toString()}' is undefined.`)
			Logger.trace();
		}
		else
		{
			phrase = this.localize[name];
		}

		return phrase;
	}

/* endregion 06. Interaction and utils */
}