Bug 1747923 - Clean up CalTransactionManager promise usage. r=darktrojan

Differential Revision: https://phabricator.services.mozilla.com/D134887

--HG--
extra : amend_source : 17951c498ee24da63595d47091494430dcf1e79a
This commit is contained in:
Lasana Murray 2022-02-09 19:42:50 +02:00
Родитель 02ca7bd37a
Коммит 06e6133d73
8 изменённых файлов: 343 добавлений и 335 удалений

Просмотреть файл

@ -12,6 +12,7 @@ var { XPCOMUtils } = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm")
XPCOMUtils.defineLazyModuleGetters(this, {
CalEvent: "resource:///modules/CalEvent.jsm",
CalTodo: "resource:///modules/CalTodo.jsm",
CalTransactionManager: "resource:///modules/CalTransactionManager.jsm",
});
/* exported modifyEventWithDialog, undo, redo, setContextPartstat */
@ -635,15 +636,6 @@ function promptOccurrenceModification(aItem, aNeedsFuture, aAction) {
// Undo/Redo code
/**
* Helper to return the transaction manager service.
*
* @return The calITransactionManager service.
*/
function getTransactionMgr() {
return Cc["@mozilla.org/calendar/transactionmanager;1"].getService(Ci.calITransactionManager);
}
/**
* Create and commit a transaction with the given arguments to the transaction
* manager. Also updates the undo/redo menu.
@ -653,29 +645,22 @@ function getTransactionMgr() {
* @param aItem The new item to add/modify/delete
* @param aCalendar The calendar to do the transaction on
* @param aOldItem (optional) some actions require an old item
* @param aListener (optional) the listener to call when complete.
* @param aObserver (optional) the observer to call when complete.
* @param aExtResponse (optional) JS object with additional parameters for sending itip messages
* (see also description of checkAndSend in calItipUtils.jsm)
*/
function doTransaction(aAction, aItem, aCalendar, aOldItem, aListener, aExtResponse = null) {
function doTransaction(aAction, aItem, aCalendar, aOldItem, aObserver, aExtResponse = null) {
// This is usually a user-initiated transaction, so make sure the calendar
// this transaction is happening on is visible.
ensureCalendarVisible(aCalendar);
// Now use the transaction manager to execute the action
let manager = getTransactionMgr();
manager.createAndCommitTxn(
aAction,
aItem,
aCalendar,
aOldItem,
aListener ? aListener : null,
aExtResponse
);
let manager = CalTransactionManager.getInstance();
manager.createAndCommitTxn(aAction, aItem, aCalendar, aOldItem, aObserver, aExtResponse);
// If a batch transaction is active, do not update the menu as
// endBatchTransaction() will take care of that.
if (manager.wrappedJSObject && manager.wrappedJSObject.batchActive) {
if (manager && manager.batchActive) {
return;
}
updateUndoRedoMenu();
@ -686,7 +671,7 @@ function doTransaction(aAction, aItem, aCalendar, aOldItem, aListener, aExtRespo
*/
function undo() {
if (canUndo()) {
getTransactionMgr().undo();
CalTransactionManager.getInstance().undo();
updateUndoRedoMenu();
}
}
@ -696,7 +681,7 @@ function undo() {
*/
function redo() {
if (canRedo()) {
getTransactionMgr().redo();
CalTransactionManager.getInstance().redo();
updateUndoRedoMenu();
}
}
@ -706,7 +691,7 @@ function redo() {
* times, which nests transactions.
*/
function startBatchTransaction() {
getTransactionMgr().beginBatch();
CalTransactionManager.getInstance().beginBatch();
}
/**
@ -715,7 +700,7 @@ function startBatchTransaction() {
* startBatchTransaction and this call.
*/
function endBatchTransaction() {
getTransactionMgr().endBatch();
CalTransactionManager.getInstance().endBatch();
updateUndoRedoMenu();
}
@ -724,14 +709,14 @@ function endBatchTransaction() {
* at all).
*/
function canUndo() {
return getTransactionMgr().canUndo();
return CalTransactionManager.getInstance().canUndo();
}
/**
* Checks if the last undone operation can be redone.
*/
function canRedo() {
return getTransactionMgr().canRedo();
return CalTransactionManager.getInstance().canRedo();
}
/**

Просмотреть файл

@ -3163,8 +3163,9 @@ function onCommandSave(aIsClosing) {
// before the call is complete. In that case, we do need a progress bar and
// the ability to cancel the operation though.
let listener = {
QueryInterface: ChromeUtils.generateQI(["calIOperationListener"]),
onOperationComplete(aCalendar, aStatus, aOpType, aId, aItem) {
onTransactionComplete(aItem) {
let aId = aItem.id;
let aCalendar = aItem.calendar;
// Check if the current window has a calendarItem first, because in case of undo
// window refers to the main window and we would get a 'calendarItem is undefined' warning.
if (!aIsClosing && "calendarItem" in window) {
@ -3172,8 +3173,7 @@ function onCommandSave(aIsClosing) {
// times. We need to make sure we're receiving the update on the right calendar.
if (
(!window.calendarItem.id || aId == window.calendarItem.id) &&
aCalendar.id == window.calendarItem.calendar.id &&
Components.isSuccessCode(aStatus)
aCalendar.id == window.calendarItem.calendar.id
) {
if (window.calendarItem.recurrenceId) {
// TODO This workaround needs to be removed in bug 396182
@ -3224,11 +3224,11 @@ function onCommandDeleteItem() {
} else {
let deleteListener = {
// when deletion of item is complete, close the dialog
onOperationComplete(aCalendar, aStatus, aOperationType, aId, aDetail) {
onTransactionComplete(item) {
// Check if the current window has a calendarItem first, because in case of undo
// window refers to the main window and we would get a 'calendarItem is undefined' warning.
if ("calendarItem" in window) {
if (aId == window.calendarItem.id && Components.isSuccessCode(aStatus)) {
if (item.id == window.calendarItem.id) {
cancelItem();
} else {
eventDialogCalendarObserver.observe(window.calendarItem.calendar);

Просмотреть файл

@ -1,85 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
interface nsITransactionManager;
interface calICalendar;
interface calIItemBase;
interface calIOperationListener;
/**
* calITransactionManager is a service designed to handle nsITransactions
* regarding the calendar. It is here as a service so that we can keep the
* transactions around without holding onto the whole global js scope+window.
*/
[scriptable, uuid(1d529847-d292-4222-b066-b8b17a794d62)]
interface calITransactionManager : nsISupports
{
/**
* @param aAction The Action to execute. This can be one of:
* * add Adds an item
* * modify Modfifies an item
* * delete Deletes an item
* * move Move an item from one calendar to the
* next. With this operation, aCalendar is
* the calendar that the event should be
* moved to.
* @param aCalendar The Calendar to execute the transaction on
* @param aItem The changed item for this transaction. This item
* should be immutable
* @param aOldItem The Item in its original form. Only needed for
* modify.
* @param aListener The listener to call when the transaction has
* completed. This parameter can be null.
* @param aExtResponse JS object to provide additional parameters to prepare an itip message.
Valid attributes are:
* * responseMode A value as defined for calIItipItem.autoResponse
*/
void createAndCommitTxn(in AUTF8String aAction,
in calIItemBase aItem,
in calICalendar aCalendar,
in calIItemBase aOldItem,
in calIOperationListener aListener,
in jsval aExtResponse);
/**
* Signals the transaction manager that a series of transactions are going
* to be performed, but that, for the purposes of undo and redo, they should
* all be regarded as a single transaction. See also
* nsITransactionManager::beginBatch
*/
void beginBatch();
/**
* Ends the batch transaction in process. See also
* nsITransactionManager::endBatch
*/
void endBatch();
/**
* Undo the last transaction in the transaction manager's stack
*/
void undo();
/**
* Returns true if it is possible to undo a transaction at this time
*/
boolean canUndo();
/**
* Redo the last transaction
*/
void redo();
/**
* Returns true if it is possible to redo a transaction at this time
*/
boolean canRedo();
/**
* A reference to the transaction manager for calendar operations
*/
readonly attribute nsITransactionManager transactionManager;
};

Просмотреть файл

@ -41,7 +41,6 @@ XPIDL_SOURCES += [
"calITimezone.idl",
"calITimezoneProvider.idl",
"calITodo.idl",
"calITransactionManager.idl",
"calIWeekInfoService.idl",
]

Просмотреть файл

@ -6,26 +6,89 @@ var EXPORTED_SYMBOLS = ["CalTransactionManager", "CalTransaction"];
var { cal } = ChromeUtils.import("resource:///modules/calendar/calUtils.jsm");
// These commands expect an old and newer copy of the item.
const updateActions = ["modify", "move"];
const OP_ADD = Ci.calIOperationListener.ADD;
const OP_MODIFY = Ci.calIOperationListener.MODIFY;
const OP_DELETE = Ci.calIOperationListener.DELETE;
function CalTransactionManager() {
this.wrappedJSObject = this;
if (!this.transactionManager) {
this.transactionManager = Cc["@mozilla.org/transactionmanager;1"].createInstance(
Ci.nsITransactionManager
);
let transactionManager = null;
/**
* CalTransactionManager is designed to handle nsITransactions regarding the
* calendar.
*/
class CalTransactionManager {
/**
* Indicates whether batch mode as described in nsITransactionManager is active.
* @type {boolean}
*/
batchActive = false;
/**
* Contains the CalTransactions that are part of the batch when batch mode is
* active.
* @type {CalTransaction[]}
*/
batchTransactions = [];
/**
* A reference to the transaction manager for calendar operations.
* @type {nsITransactionManager}
*/
transactionManager = Cc["@mozilla.org/transactionmanager;1"].createInstance(
Ci.nsITransactionManager
);
/**
* Provides a singleton instance of CalTransactionManger.
* @return {CalTransactionManager}
*/
static getInstance() {
if (!transactionManager) {
transactionManager = new CalTransactionManager();
}
return transactionManager;
}
}
CalTransactionManager.prototype = {
QueryInterface: ChromeUtils.generateQI(["calITransactionManager"]),
classID: Components.ID("{1d529847-d292-4222-b066-b8b17a794d62}"),
batchActive: false,
batchTransactions: [],
transactionManager: null,
createAndCommitTxn(aAction, aItem, aCalendar, aOldItem, aListener, aExtResponse) {
let txn = new CalTransaction(aAction, aItem, aCalendar, aOldItem, aListener, aExtResponse);
_checkWritable(transaction) {
// If the transaction is null it is possible the last transaction was a
// batch transaction. Check the transactions we cached because
// nsITransactionManager does not provide a way to query them all.
return !transaction && this.batchTransactions.length
? this.batchTransactions.every(trn => trn.wrappedJSObject.canWrite())
: transaction.wrappedJSObject.canWrite();
}
/**
* @typedef {Object} ExtResponse
* @property {number} responseMode One of the calIItipItem.autoResponse values.
*/
/**
* @param {string} action The action to execute. This can
* be one of:
* * add Adds an item
* * modify Modfifies an item
* * delete Deletes an item
* * move Move an item from one calendar to
* the next. With this operation,
* calendar is the calendar that the
* event should be moved to.
* @param {calICalendar} calendar The Calendar to execute the transaction on.
* @param {calIItemBase} item The changed item for this transaction.
* This item should be immutable.
* @param {calIItemBase} oldItem The item in its original form.
* Only needed for modify.
* @param {CalTransactionObserver} [observer] The observer to call when the
* transaction has completed.
* @param {ExtResponse} [extResponse] Object to provide additional
* parameters to prepare an itip
* message.
*/
createAndCommitTxn(action, item, calendar, oldItem, observer, extResponse) {
let txn = new CalObservableTransaction(
CalTransaction.createTransaction(action, item, calendar, oldItem, extResponse),
observer
);
if (this.batchActive) {
// nsITransactionManager.peek(Undo|Redo)Stack can return null if a batch
// transaction is at the top of the stack. To avoid being mislead by this,
@ -33,239 +96,299 @@ CalTransactionManager.prototype = {
this.batchTransactions.push(txn);
}
this.transactionManager.doTransaction(txn);
},
}
/**
* Signals the transaction manager that a series of transactions are going
* to be performed, but that, for the purposes of undo and redo, they should
* all be regarded as a single transaction. See also
* nsITransactionManager::beginBatch
*/
beginBatch() {
this.transactionManager.beginBatch(null);
this.batchActive = true;
this.batchTransactions = [];
},
}
/**
* Ends the batch transaction in process. See also
* nsITransactionManager::endBatch
*/
endBatch() {
this.transactionManager.endBatch(false);
this.batchActive = false;
},
checkWritable(transaction) {
// If the transaction is null it is possible the last transaction was a
// batch transaction. Check the transactions we cached because
// nsITransactionManager does not provide a way to query them all.
return !transaction && this.batchTransactions.length
? this.batchTransactions.every(transactionCanWrite)
: transactionCanWrite(transaction);
},
}
/**
* Undo the last transaction in the transaction manager's stack
*/
undo() {
this.transactionManager.undoTransaction();
},
}
/**
* Returns true if it is possible to undo a transaction at this time
* @return {boolean}
*/
canUndo() {
return (
this.transactionManager.numberOfUndoItems > 0 &&
this.checkWritable(this.transactionManager.peekUndoStack())
this._checkWritable(this.transactionManager.peekUndoStack())
);
},
}
/**
* Redo the last transaction
*/
redo() {
this.transactionManager.redoTransaction();
},
}
/**
* Returns true if it is possible to redo a transaction at this time
* @return {boolean}
*/
canRedo() {
return (
this.transactionManager.numberOfRedoItems > 0 &&
this.checkWritable(this.transactionManager.peekRedoStack())
this._checkWritable(this.transactionManager.peekRedoStack())
);
},
};
function CalTransaction(aAction, aItem, aCalendar, aOldItem, aListener, aExtResponse) {
this.wrappedJSObject = this;
this.mAction = aAction;
this.mItem = aItem;
this.mCalendar = aCalendar;
this.mOldItem = aOldItem;
this.mListener = aListener;
this.mExtResponse = aExtResponse;
}
}
var calTransactionClassID = Components.ID("{fcb54c82-2fb9-42cb-bf44-1e197a55e520}");
var calTransactionInterfaces = ["nsITransaction", "calIOperationListener"];
CalTransaction.prototype = {
classID: calTransactionClassID,
QueryInterface: ChromeUtils.generateQI(calTransactionInterfaces),
/**
* CalTransaction is the base nsITransaction implementation used to make
* calendar modifications undoable/redoable.
*
* @implements nsITransaction
*/
class CalTransaction {
/**
* @type {CalTransaction}
*/
wrappedJSObject = this;
mAction: null,
mCalendar: null,
mItem: null,
mOldItem: null,
mOldCalendar: null,
mListener: null,
mIsDoTransaction: false,
mExtResponse: null,
/**
* @type {Function}
*/
QueryInterface = ChromeUtils.generateQI(["nsITransaction"]);
_onError(opType, item, error) {
if (this.mListener) {
this.mListener.onOperationComplete(item.calendar, error.result, opType, item.id, error);
}
},
/**
* @type {boolean}
*/
isTransient = false;
_onSuccess(opType, item) {
cal.itip.checkAndSend(
opType,
item,
this.mIsDoTransaction ? this.mOldItem : this.mItem,
this.mExtResponse
);
/**
* @type {calICalendar}
*/
calendar = null;
if (opType == Ci.calIOperationListener.ADD || opType == Ci.calIOperationListener.MODIFY) {
if (this.mIsDoTransaction) {
this.mItem = item;
} else {
this.mOldItem = item;
}
}
/**
* @type {calIItemBase}
*/
item = null;
if (this.mListener) {
this.mListener.onOperationComplete(item.calendar, Cr.NS_OK, opType, item.id, item);
}
},
/**
* @type {calIItemBase}
*/
oldItem = null;
onOperationComplete(aCalendar, aStatus, aOperationType, aId, aDetail) {
if (Components.isSuccessCode(aStatus)) {
cal.itip.checkAndSend(
aOperationType,
aDetail,
this.mIsDoTransaction ? this.mOldItem : this.mItem,
this.mExtResponse
);
/**
* @type {calICalendar}
*/
oldCalendar = null;
if (aOperationType == Ci.calIOperationListener.MODIFY) {
if (this.mIsDoTransaction) {
this.mItem = aDetail;
} else {
this.mOldItem = aDetail;
}
}
}
if (this.mListener) {
this.mListener.onOperationComplete(aCalendar, aStatus, aOperationType, aId, aDetail);
}
},
/**
* @type {ExtResponse}
*/
extResponse = null;
onGetResult(aCalendar, aStatus, aItemType, aDetail, aItems) {
if (this.mListener) {
this.mListener.onGetResult(aCalendar, aStatus, aItemType, aDetail, aItems);
}
},
/**
* @private
* @param {calIItemBase} item
* @param {calICalendar} calendar
* @param {calIItemBase?} oldItem
* @param {object?} extResponse
*/
constructor(item, calendar, oldItem, extResponse) {
this.item = item;
this.calendar = calendar;
this.oldItem = oldItem;
this.extResponse = extResponse;
}
doTransaction() {
this.mIsDoTransaction = true;
switch (this.mAction) {
/**
* Creates a CalTransaction instance based on the action desired.
* @param {string} action - One of "add","modify" or "delete"
* @param {calIItemBase} item - The item the operation is taking place on.
* @param {calICalendar} calendar - The target calendar for the operation.
* @param {calIItemBase} [oldItem] - The old item (for modifications).
* @param {ExtResponse} [extResponse] - Passed to checkAndSend().
*/
static createTransaction(action, item, calendar, oldItem, extResponse) {
switch (action) {
case "add":
this.mCalendar.addItem(this.mItem).then(
item => this._onSuccess(Ci.calIOperationListener.ADD, item),
e => this._onError(Ci.calIOperationListener.ADD, this.mItem, e)
);
break;
return new CalAddTransaction(item, calendar, oldItem, extResponse);
case "modify":
if (this.mItem.calendar.id == this.mOldItem.calendar.id) {
this.mCalendar
.modifyItem(cal.itip.prepareSequence(this.mItem, this.mOldItem), this.mOldItem)
.then(
item => this._onSuccess(Ci.calIOperationListener.MODIFY, item),
e => this._onError(Ci.calIOperationListener.MODIFY, this.mItem, e)
);
} else {
this.mOldCalendar = this.mOldItem.calendar;
this.mCalendar.addItem(this.mItem).then(
item => {
this._onSuccess(Ci.calIOperationListener.ADD, item);
return this.mOldItem.calendar.deleteItem(this.mOldItem).then(
() => this._onSuccess(Ci.calIOperationListener.DELETE, this.mOldItem),
e => this._onError(Ci.calIOperationListener.DELETE, this.mOldItem, e)
);
},
e => this._onError(Ci.calIOperationListener.ADD, this.mOldItem, e)
);
}
break;
return new CalModifyTransaction(item, calendar, oldItem, extResponse);
case "delete":
this.mCalendar.deleteItem(this.mItem).then(
() => this._onSuccess(Ci.calIOperationListener.DELETE, this.mItem),
e => this._onError(Ci.calIOperationListener.DELETE, this.mItem, e)
);
break;
return new CalDeleteTransaction(item, calendar, oldItem, extResponse);
default:
throw new Components.Exception("Invalid action specified", Cr.NS_ERROR_ILLEGAL_VALUE);
}
},
undoTransaction() {
this.mIsDoTransaction = false;
switch (this.mAction) {
case "add":
this.mCalendar.deleteItem(this.mItem).then(
() => this._onSuccess(Ci.calIOperationListener.DELETE, this.mItem),
e => this._onError(Ci.calIOperationListener.DELETE, this.mItem, e)
throw new Components.Exception(
`Invalid action specified "${action}"`,
Cr.NS_ERROR_ILLEGAL_VALUE
);
break;
case "modify":
if (this.mOldItem.calendar.id == this.mItem.calendar.id) {
this.mCalendar
.modifyItem(cal.itip.prepareSequence(this.mOldItem, this.mItem), this.mItem)
.then(
() => this._onSuccess(Ci.calIOperationListener.MODIFY, this.mOldItem),
e => this._onError(Ci.calIOperationListener.MODIFY, this.mOldItem, e)
);
} else {
this.mCalendar.deleteItem(this.mItem).then(
() => this._onSuccess(Ci.calIOperationListener.DELETE, this.mItem),
e => this._onError(Ci.calIOperationListener.DELETE, this.mItem, e)
);
this.mOldCalendar.addItem(this.mOldItem).then(
() => this._onSuccess(Ci.calIOperationListener.ADD, this.mOldItem),
e => this._onError(Ci.calIOperationListener.ADD, this.mOldItem, e)
);
}
break;
case "delete":
this.mCalendar.addItem(this.mItem).then(
() => this._onSuccess(Ci.calIOperationListener.ADD, this.mItem),
e => this._onError(Ci.calIOperationListener.ADD, this.mItem, e)
);
break;
default:
throw new Components.Exception("Invalid action specified", Cr.NS_ERROR_ILLEGAL_VALUE);
}
},
}
_dispatch(opType, item, oldItem) {
cal.itip.checkAndSend(opType, item, oldItem, this.extResponse);
}
/**
* Checks whether the calendar of the transaction's target item can be written to.
* @return {boolean}
*/
canWrite() {
if (itemWritable(this.item)) {
return this instanceof CalModifyTransaction ? itemWritable(this.oldItem) : true;
}
return false;
}
doTransaction() {}
undoTransaction() {}
redoTransaction() {
this.doTransaction();
},
isTransient: false,
}
merge(aTransaction) {
// No support for merging
return false;
},
};
}
}
/**
* Checks whether the calendar of a transaction's item can be written to.
*
* @param {nsITransaction} transaction - Must be a wrapped CalTransaction.
*
* @return {boolean}
* CalAddTransaction handles undo/redo for additions.
*/
function transactionCanWrite(transaction) {
let calTrans = transaction && transaction.wrappedJSObject;
if (calTrans && canWrite(calTrans.mItem)) {
return updateActions.includes(transaction.mAction) ? canWrite(transaction.mOldItem) : true;
class CalAddTransaction extends CalTransaction {
async doTransaction() {
let item = await this.calendar.addItem(this.item);
this._dispatch(OP_ADD, item, this.oldItem);
this.item = item;
}
async undoTransaction() {
await this.calendar.deleteItem(this.item);
this._dispatch(OP_DELETE, this.item, this.item);
this.oldItem = this.item;
}
}
/**
* CalModifyTransaction handles undo/redo for modifications.
*/
class CalModifyTransaction extends CalTransaction {
async doTransaction() {
let item;
if (this.item.calendar.id == this.oldItem.calendar.id) {
item = await this.calendar.modifyItem(
cal.itip.prepareSequence(this.item, this.oldItem),
this.oldItem
);
this._dispatch(OP_MODIFY, item, this.oldItem);
} else {
this.oldCalendar = this.oldItem.calendar;
item = await this.calendar.addItem(this.item);
this._dispatch(OP_ADD, item, this.oldItem);
await this.oldItem.calendar.deleteItem(this.oldItem);
this._dispatch(OP_DELETE, this.oldItem, this.oldItem);
}
this.item = item;
}
async undoTransaction() {
if (this.oldItem.calendar.id == this.item.calendar.id) {
await this.calendar.modifyItem(cal.itip.prepareSequence(this.oldItem, this.item), this.item);
this._dispatch(OP_MODIFY, this.oldItem, this.oldItem);
} else {
await this.calendar.deleteItem(this.item);
this._dispatch(OP_DELETE, this.item, this.item);
await this.oldCalendar.addItem(this.oldItem);
this._dispatch(OP_ADD, this.oldItem, this.item);
}
}
}
/**
* CalDeleteTransaction handles undo/redo for deletions.
*/
class CalDeleteTransaction extends CalTransaction {
async doTransaction() {
await this.calendar.deleteItem(this.item);
this._dispatch(OP_DELETE, this.item, this.oldItem);
}
async undoTransaction() {
await this.calendar.addItem(this.item);
this._dispatch(OP_ADD, this.item, this.item);
}
}
/**
* Observer for CalTransaction execution.
* @type {Object} CalTransactionObserver
* @property {CalTransactionObserverHandler?} onTransctionComplete
*/
/**
* @callback CalTransactionObserverHandler
* @param {calIItemBase} item
* @param {calIItemBase?} oldItem
*/
/**
* CalObservableTransaction allows a transaction's undo/redo execution to be
* observed by other objects. This is needed because the actual execution
* transaction execution takes place in lower level code and is more or less
* opaque to scripts.
*/
class CalObservableTransaction extends CalTransaction {
/**
* @type {CalTransaction}
*/
_transaction;
/**
* @type {CalTransactionObserver}
*/
_observer;
/**
* @param {CalTransaction} transaction
* @param {CalTransactionObserver} observer
*/
constructor(transaction, observer) {
super(null, null, null, null);
this._transaction = transaction;
this._observer = observer;
}
canWrite() {
return this._transaction.canWrite();
}
async doTransaction() {
await this._transaction.doTransaction();
this?._observer?.onTransactionComplete(this._transaction.item, this._transaction.oldItem);
}
async undoTransaction() {
await this._transaction.undoTransaction();
this?._observer?.onTransactionComplete(this._transaction.item, this._transaction.oldItem);
}
return false;
}
/**
@ -273,7 +396,7 @@ function transactionCanWrite(transaction) {
*
* @param {calIItemBase} item
*/
function canWrite(item) {
function itemWritable(item) {
return (
item &&
item.calendar &&

Просмотреть файл

@ -120,18 +120,6 @@ Classes = [
'jsm': 'resource:///modules/CalRelation.jsm',
'constructor': 'CalRelation',
},
{
'cid': '{fcb54c82-2fb9-42cb-bf44-1e197a55e520}',
'contract_ids': ['@mozilla.org/calendar/transaction;1'],
'jsm': 'resource:///modules/CalTransactionManager.jsm',
'constructor': 'CalTransaction',
},
{
'cid': '{1d529847-d292-4222-b066-b8b17a794d62}',
'contract_ids': ['@mozilla.org/calendar/transactionmanager;1'],
'jsm': 'resource:///modules/CalTransactionManager.jsm',
'constructor': 'CalTransactionManager',
},
{
'cid': '{7af51168-6abe-4a31-984d-6f8a3989212d}',
'contract_ids': ['@mozilla.org/calendar/todo;1'],

Просмотреть файл

@ -12,12 +12,11 @@ var { XPCOMUtils } = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm")
XPCOMUtils.defineLazyModuleGetters(this, {
CalEvent: "resource:///modules/CalEvent.jsm",
CalTransactionManager: "resource:///modules/CalTransactionManager.jsm",
});
const calendar = CalendarTestUtils.createCalendar("Undo Redo Test");
const calTransManager = Cc["@mozilla.org/calendar/transactionmanager;1"].getService(
Ci.calITransactionManager
).wrappedJSObject;
const calTransManager = CalTransactionManager.getInstance();
/**
* Checks the value of the "disabled" property for items in either the "Edit"

Просмотреть файл

@ -15,12 +15,11 @@ var { mailTestUtils } = ChromeUtils.import("resource://testing-common/mailnews/M
XPCOMUtils.defineLazyModuleGetters(this, {
CalTodo: "resource:///modules/CalTodo.jsm",
CalTransactionManager: "resource:///modules/CalTransactionManager.jsm",
});
const calendar = CalendarTestUtils.createCalendar("Undo Redo Test", "memory");
const calTransManager = Cc["@mozilla.org/calendar/transactionmanager;1"].getService(
Ci.calITransactionManager
).wrappedJSObject;
const calTransManager = CalTransactionManager.getInstance();
/**
* Checks the value of the "disabled" property for items in either the "Edit"