Files
DocumentServer-v-9.2.0/sdkjs/word/Editor/CollaborativeEditing.js
Yajbir Singh f1b860b25c
Some checks failed
check / markdownlint (push) Has been cancelled
check / spellchecker (push) Has been cancelled
updated
2025-12-11 19:03:17 +05:30

555 lines
20 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* (c) Copyright Ascensio System SIA 2010-2024
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish
* street, Riga, Latvia, EU, LV-1050.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
"use strict";
/**
*
* @constructor
* @extends {AscCommon.CCollaborativeEditingBase}
*/
function CWordCollaborativeEditing()
{
AscCommon.CCollaborativeEditingBase.call(this);
this.m_aSkipContentControlsOnCheckEditingLock = {};
}
CWordCollaborativeEditing.prototype = Object.create(AscCommon.CCollaborativeEditingBase.prototype);
CWordCollaborativeEditing.prototype.constructor = CWordCollaborativeEditing;
CWordCollaborativeEditing.prototype.GetEditorApi = function()
{
if(this.m_oLogicDocument)
{
return this.m_oLogicDocument.GetApi();
}
return null;
};
CWordCollaborativeEditing.prototype.GetDrawingDocument = function()
{
if(this.m_oLogicDocument)
{
return this.m_oLogicDocument.GetDrawingDocument();
}
return null;
};
CWordCollaborativeEditing.prototype.Clear = function()
{
AscCommon.CCollaborativeEditingBase.prototype.Clear.apply(this, arguments);
this.Remove_AllForeignCursors();
};
CWordCollaborativeEditing.prototype.Apply_OtherChanges = function()
{
AscCommon.executeNoRevisions(AscCommon.CCollaborativeEditingBase.prototype.Apply_OtherChanges, this.GetLogicDocument(), this, arguments);
};
CWordCollaborativeEditing.prototype.Send_Changes = function(IsUserSave, AdditionalInfo, IsUpdateInterface, isAfterAskSave)
{
if (!this.canSendChanges())
return;
// Пересчитываем позиции
this.Refresh_DCChanges();
// Генерируем свои изменения
var StartPoint = ( null === AscCommon.History.SavedIndex ? 0 : AscCommon.History.SavedIndex + 1 );
var LastPoint = -1;
if (this.m_nUseType <= 0)
{
// (ненужные точки предварительно удаляем)
AscCommon.History.Clear_Redo();
LastPoint = AscCommon.History.Points.length - 1;
}
else
{
LastPoint = AscCommon.History.Index;
}
// Просчитаем сколько изменений на сервер пересылать не надо
var SumIndex = 0;
var StartPoint2 = Math.min(StartPoint, LastPoint + 1);
for (var PointIndex = 0; PointIndex < StartPoint2; PointIndex++)
{
var Point = AscCommon.History.Points[PointIndex];
SumIndex += Point.Items.length;
}
var deleteIndex = ( null === AscCommon.History.SavedIndex ? null : SumIndex );
var aChanges = [], aChanges2 = [];
for (var PointIndex = StartPoint; PointIndex <= LastPoint; PointIndex++)
{
var Point = AscCommon.History.Points[PointIndex];
AscCommon.History.Update_PointInfoItem(PointIndex, StartPoint, LastPoint, SumIndex, deleteIndex);
for (var Index = 0; Index < Point.Items.length; Index++)
{
var Item = Point.Items[Index];
var oChanges = new AscCommon.CCollaborativeChanges();
oChanges.Set_FromUndoRedo(Item.Class, Item.Data, Item.Binary);
aChanges2.push(Item.Data);
aChanges.push(oChanges.m_pData);
}
}
var UnlockCount = 0;
// Пока пользователь сидит один, мы не чистим его локи до тех пор пока не зайдет второй
var bCollaborative = this.getCollaborativeEditing();
if (bCollaborative)
{
UnlockCount = this.m_aNeedUnlock.length;
this.Release_Locks();
var UnlockCount2 = this.m_aNeedUnlock2.length;
for (var Index = 0; Index < UnlockCount2; Index++)
{
var Class = this.m_aNeedUnlock2[Index];
Class.Lock.Set_Type(AscCommon.c_oAscLockTypes.kLockTypeNone, false);
editor.CoAuthoringApi.releaseLocks(Class.Get_Id());
}
this.m_aNeedUnlock.length = 0;
this.m_aNeedUnlock2.length = 0;
}
var deleteIndex = ( null === AscCommon.History.SavedIndex ? null : SumIndex );
if (0 < aChanges.length || null !== deleteIndex)
{
this.CoHistory.AddOwnChanges(aChanges2, deleteIndex);
editor.CoAuthoringApi.saveChanges(aChanges, deleteIndex, AdditionalInfo, editor.canUnlockDocument2, bCollaborative);
AscCommon.History.CanNotAddChanges = true;
}
else
{
editor.CoAuthoringApi.unLockDocument(!!isAfterAskSave, editor.canUnlockDocument2, null, bCollaborative);
}
editor.canUnlockDocument2 = false;
if (-1 === this.m_nUseType)
{
// Чистим Undo/Redo только во время совместного редактирования
AscCommon.History.Clear();
AscCommon.History.SavedIndex = null;
}
else if (0 === this.m_nUseType)
{
// Чистим Undo/Redo только во время совместного редактирования
AscCommon.History.Clear();
AscCommon.History.SavedIndex = null;
this.m_nUseType = 1;
}
else
{
// Обновляем точку последнего сохранения в истории
AscCommon.History.Reset_SavedIndex(IsUserSave);
}
if (false !== IsUpdateInterface)
editor.WordControl.m_oLogicDocument.UpdateInterface(undefined, true);
// TODO: Пока у нас обнуляется история на сохранении нужно обновлять Undo/Redo
editor.WordControl.m_oLogicDocument.Document_UpdateUndoRedoState();
// Свои локи не проверяем. Когда все пользователи выходят, происходит перерисовка и свои локи уже не рисуются.
if (0 !== UnlockCount || 1 !== this.m_nUseType)
{
// Перерисовываем документ (для обновления локов)
editor.WordControl.m_oLogicDocument.DrawingDocument.ClearCachePages();
editor.WordControl.m_oLogicDocument.DrawingDocument.FirePaint();
}
editor.WordControl.m_oLogicDocument.getCompositeInput().checkState();
};
CWordCollaborativeEditing.prototype.Release_Locks = function()
{
var UnlockCount = this.m_aNeedUnlock.length;
for (var Index = 0; Index < UnlockCount; Index++)
{
var CurLockType = this.m_aNeedUnlock[Index].Lock.Get_Type();
if (AscCommon.c_oAscLockTypes.kLockTypeOther3 != CurLockType && AscCommon.c_oAscLockTypes.kLockTypeOther != CurLockType)
{
this.m_aNeedUnlock[Index].Lock.Set_Type(AscCommon.c_oAscLockTypes.kLockTypeNone, false);
if (this.m_aNeedUnlock[Index] instanceof AscCommonWord.CHeaderFooterController)
editor.sync_UnLockHeaderFooters();
else if (this.m_aNeedUnlock[Index] instanceof AscCommonWord.CDocument)
editor.sync_UnLockDocumentProps();
else if (this.m_aNeedUnlock[Index] instanceof AscCommon.CComment)
editor.sync_UnLockComment(this.m_aNeedUnlock[Index].Get_Id());
else if (this.m_aNeedUnlock[Index] instanceof AscCommonWord.CGraphicObjects)
editor.sync_UnLockDocumentSchema();
else if (this.m_aNeedUnlock[Index] instanceof AscCommon.CCore)
editor.sendEvent("asc_onLockCore", false);
else if (this.m_aNeedUnlock[Index] instanceof AscCommonWord.CDocProtect)
editor.sendEvent("asc_onLockDocumentProtection", false);
}
else if (AscCommon.c_oAscLockTypes.kLockTypeOther3 === CurLockType)
{
this.m_aNeedUnlock[Index].Lock.Set_Type(AscCommon.c_oAscLockTypes.kLockTypeOther, false);
}
}
};
CWordCollaborativeEditing.prototype.OnEnd_Load_Objects = function()
{
// Данная функция вызывается, когда загрузились внешние объекты (картинки и шрифты)
// Снимаем лок
AscCommon.CollaborativeEditing.Set_GlobalLock(false);
AscCommon.CollaborativeEditing.Set_GlobalLockSelection(false);
if (this.m_fEndLoadCallBack)
{
this.m_fEndLoadCallBack();
this.m_fEndLoadCallBack = null;
}
var nPageIndex = undefined;
if (this.Is_Fast())
{
var oParagraph = this.m_oLogicDocument.GetCurrentParagraph();
nPageIndex = oParagraph ? Math.max(oParagraph.GetAbsoluteCurrentPage(), editor.GetCurrentVisiblePage()) : undefined;
}
this.m_oLogicDocument.ResumeRecalculate();
this.m_oLogicDocument.RecalculateByChanges(this.CoHistory.GetAllChanges(), this.m_nRecalcIndexStart, this.m_nRecalcIndexEnd, false, nPageIndex);
this.m_oLogicDocument.UpdateTracks();
let oform = this.m_oLogicDocument.GetOFormDocument();
if (oform)
oform.onEndLoadChanges();
editor.sync_EndAction(Asc.c_oAscAsyncActionType.BlockInteraction, Asc.c_oAscAsyncAction.ApplyChanges);
};
CWordCollaborativeEditing.prototype.Check_MergeData = function()
{
var LogicDocument = editor.WordControl.m_oLogicDocument;
LogicDocument.Comments.Check_MergeData();
};
CWordCollaborativeEditing.prototype.OnEnd_CheckLock = function(isDontLockInFastMode, fCallback)
{
// Если задан fCallback, тогда действие нужно выполнять именно на нём, поэотому возвращаемое значение true
var aIds = [];
for (var nIndex = 0, nCount = this.m_aCheckLocks.length; nIndex < nCount; ++nIndex)
{
var oItem = this.m_aCheckLocks[nIndex];
if (true === oItem) // сравниваем по значению и типу обязательно
{
if (fCallback)
fCallback(true);
return true;
}
else if (false !== oItem)
{
aIds.push(oItem);
}
}
if ((true === isDontLockInFastMode && true === this.Is_Fast()) || !this.canSendChanges())
{
if (fCallback)
{
fCallback(false);
return true;
}
else
{
return false;
}
}
if (fCallback)
{
if (aIds.length > 0)
{
var oThis = this;
editor.CoAuthoringApi.askLock(aIds, function(result)
{
oThis.Set_GlobalLock(false);
if (result["lock"])
{
oThis.private_LockByMe();
fCallback(false);
}
else if (result["error"])
{
fCallback(true);
}
});
this.Set_GlobalLock(true);
}
else
{
fCallback(false);
}
return true;
}
else
{
if (aIds.length > 0)
{
// Отправляем запрос на сервер со списком Id
editor.CoAuthoringApi.askLock(aIds, this.OnCallback_AskLock);
// Ставим глобальный лок, только во время совместного редактирования
if (-1 === this.m_nUseType)
{
this.Set_GlobalLock(true);
}
else
{
this.private_LockByMe();
this.m_aCheckLocks.length = 0;
}
}
return false;
}
};
CWordCollaborativeEditing.prototype.private_LockByMe = function()
{
for (var nIndex = 0, nCount = this.m_aCheckLocks.length; nIndex < nCount; ++nIndex)
{
var oItem = this.m_aCheckLocks[nIndex];
if (true !== oItem && false !== oItem) // сравниваем по значению и типу обязательно
{
var oClass = AscCommon.g_oTableId.Get_ById(oItem);
if (oClass)
{
oClass.Lock.Set_Type(AscCommon.c_oAscLockTypes.kLockTypeMine);
this.Add_Unlock2(oClass);
}
}
}
};
CWordCollaborativeEditing.prototype.OnCallback_AskLock = function(result)
{
var oThis = AscCommon.CollaborativeEditing;
var oEditor = editor;
if (true === oThis.Get_GlobalLock())
{
// Здесь проверяем есть ли длинная операция, если она есть, то до ее окончания нельзя делать
// Undo, иначе точка истории уберется, а изменения допишутся в предыдущую.
if (false == oEditor.checkLongActionCallback(oThis.OnCallback_AskLock, result))
return;
// Снимаем глобальный лок
oThis.Set_GlobalLock(false);
if (result["lock"])
{
oThis.private_LockByMe();
}
else if (result["error"])
{
// Если у нас началось редактирование диаграммы, а вернулось, что ее редактировать нельзя,
// посылаем сообщение о закрытии редактора диаграмм.
if (oEditor.frameManager.isLoadingChartEditor)
oEditor.sync_closeChartEditor();
if (oEditor.frameManager.isLoadingOleEditor)
oEditor.sync_closeOleEditor();
// Делаем откат на 1 шаг назад и удаляем из Undo/Redo эту последнюю точку
oEditor.WordControl.m_oLogicDocument.Document_Undo();
AscCommon.History.Clear_Redo();
}
oEditor.frameManager.endLoadChartEditor();
oEditor.frameManager.endLoadOleEditor();
}
};
CWordCollaborativeEditing.prototype.AddContentControlForSkippingOnCheckEditingLock = function(oContentControl)
{
this.m_aSkipContentControlsOnCheckEditingLock[oContentControl.GetId()] = oContentControl;
};
CWordCollaborativeEditing.prototype.RemoveContentControlForSkippingOnCheckEditingLock = function(oContentControl)
{
delete this.m_aSkipContentControlsOnCheckEditingLock[oContentControl.GetId()];
};
CWordCollaborativeEditing.prototype.IsNeedToSkipContentControlOnCheckEditingLock = function(oContentControl)
{
if (this.m_aSkipContentControlsOnCheckEditingLock[oContentControl.GetId()] === oContentControl)
return true;
return false;
};
CWordCollaborativeEditing.prototype.Start_CollaborationEditing = function()
{
this.m_nUseType = -1;
};
CWordCollaborativeEditing.prototype.End_CollaborationEditing = function()
{
if (this.m_nUseType <= 0)
{
if (this.m_oLogicDocument && !this.m_oLogicDocument.GetHistory().Have_Changes() && !this.Have_OtherChanges())
this.m_nUseType = 1;
else
this.m_nUseType = 0;
}
};
CWordCollaborativeEditing.prototype._PreUndo = function()
{
let logicDocument = this.m_oLogicDocument;
logicDocument.DrawingDocument.EndTrackTable(null, true);
logicDocument.TurnOffCheckChartSelection();
return this.private_SaveDocumentState()
};
CWordCollaborativeEditing.prototype._PostUndo = function(state, changes)
{
this.private_RestoreDocumentState(state);
this.private_RecalculateDocument(changes);
let logicDocument = this.m_oLogicDocument;
logicDocument.TurnOnCheckChartSelection();
logicDocument.UpdateSelection();
logicDocument.UpdateInterface();
logicDocument.UpdateRulers();
};
//----------------------------------------------------------------------------------------------------------------------
// Функции для работы с сохраненными позициями документа.
//----------------------------------------------------------------------------------------------------------------------
CWordCollaborativeEditing.prototype.Remove_ForeignCursor = function(UserId)
{
AscCommon.CCollaborativeEditingBase.prototype.Remove_ForeignCursor.call(this, UserId);
var DrawingDocument = this.m_oLogicDocument.DrawingDocument;
DrawingDocument.Collaborative_RemoveTarget(UserId);
this.Remove_ForeignCursorXY(UserId);
this.Remove_ForeignCursorToShow(UserId);
};
CWordCollaborativeEditing.prototype.Update_ForeignCursorsPositions = function()
{
for (var UserId in this.m_aForeignCursors)
{
var DocPos = this.m_aForeignCursors[UserId];
if (!DocPos || DocPos.length <= 0)
continue;
this.m_aForeignCursorsPos.Update_DocumentPosition(DocPos);
var Run = DocPos[DocPos.length - 1].Class;
var InRunPos = DocPos[DocPos.length - 1].Position;
this.Update_ForeignCursorPosition(UserId, Run, InRunPos, false);
}
};
CWordCollaborativeEditing.prototype.Update_ForeignCursorPosition = function(UserId, Run, InRunPos, isRemoveLabel)
{
var DrawingDocument = this.m_oLogicDocument.DrawingDocument;
if (!(Run instanceof AscCommonWord.ParaRun))
return;
var Paragraph = Run.GetParagraph();
if (!Paragraph)
{
DrawingDocument.Collaborative_RemoveTarget(UserId);
return;
}
var ParaContentPos = Paragraph.Get_PosByElement(Run);
if (!ParaContentPos)
{
DrawingDocument.Collaborative_RemoveTarget(UserId);
return;
}
ParaContentPos.Update(InRunPos, ParaContentPos.GetDepth() + 1);
var XY = Paragraph.Get_XYByContentPos(ParaContentPos);
if (XY && XY.Height > 0.001)
{
var ShortId = this.m_aForeignCursorsId[UserId] ? this.m_aForeignCursorsId[UserId] : UserId;
DrawingDocument.Collaborative_UpdateTarget(UserId, ShortId, XY.X, XY.Y, XY.Height, XY.PageNum, Paragraph.Get_ParentTextTransform());
this.Add_ForeignCursorXY(UserId, XY.X, XY.Y, XY.PageNum, XY.Height, Paragraph, isRemoveLabel);
if (true === this.m_aForeignCursorsToShow[UserId])
{
this.Show_ForeignCursorLabel(UserId);
this.Remove_ForeignCursorToShow(UserId);
}
}
else
{
DrawingDocument.Collaborative_RemoveTarget(UserId);
this.Remove_ForeignCursorXY(UserId);
this.Remove_ForeignCursorToShow(UserId);
}
};
CWordCollaborativeEditing.prototype.OnEnd_ReadForeignChanges = function()
{
AscCommon.CCollaborativeEditingBase.prototype.OnEnd_ReadForeignChanges.apply(this, arguments);
if (this.m_oLogicDocument && this.m_oLogicDocument.GetApi())
{
var oApi = this.m_oLogicDocument.GetApi();
if (this.m_oLogicDocument.GetBookmarksManager().IsNeedUpdate())
{
oApi.asc_OnBookmarksUpdate();
}
if (this.m_oLogicDocument && this.m_oLogicDocument.ClearListsCache)
this.m_oLogicDocument.ClearListsCache();
if (this.m_oLogicDocument && this.m_oLogicDocument.Settings && this.m_oLogicDocument.Settings.DocumentProtection)
{
let updateFromUser = this.m_oLogicDocument.Settings.DocumentProtection.GetNeedUpdate();
if (updateFromUser) {
oApi.asc_OnProtectionUpdate(updateFromUser);
this.m_oLogicDocument.Settings.DocumentProtection.SetNeedUpdate(null);
}
}
}
};
CWordCollaborativeEditing.prototype.private_RecalculateDocument = function(arrChanges)
{
this.m_oLogicDocument.RecalculateByChanges(arrChanges);
};
CWordCollaborativeEditing.prototype.private_UpdateForeignCursor = function(CursorInfo, UserId, Show, UserShortId)
{
this.m_oLogicDocument.Update_ForeignCursor(CursorInfo, UserId, Show, UserShortId);
};
//--------------------------------------------------------export----------------------------------------------------
window['AscCommon'] = window['AscCommon'] || {};
window['AscCommon'].CWordCollaborativeEditing = CWordCollaborativeEditing;